Home | History | Annotate | Download | only in syscall
      1 // Copyright 2011 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // Plan 9 system calls.
      6 // This file is compiled as ordinary Go code,
      7 // but it is also input to mksyscall,
      8 // which parses the //sys lines and generates system call stubs.
      9 // Note that sometimes we use a lowercase //sys name and
     10 // wrap it in our own nicer implementation.
     11 
     12 package syscall
     13 
     14 import "unsafe"
     15 
     16 const ImplementsGetwd = true
     17 
     18 // ErrorString implements Error's String method by returning itself.
     19 type ErrorString string
     20 
     21 func (e ErrorString) Error() string { return string(e) }
     22 
     23 // NewError converts s to an ErrorString, which satisfies the Error interface.
     24 func NewError(s string) error { return ErrorString(s) }
     25 
     26 func (e ErrorString) Temporary() bool {
     27 	return e == EINTR || e == EMFILE || e.Timeout()
     28 }
     29 
     30 func (e ErrorString) Timeout() bool {
     31 	return e == EBUSY || e == ETIMEDOUT
     32 }
     33 
     34 // A Note is a string describing a process note.
     35 // It implements the os.Signal interface.
     36 type Note string
     37 
     38 func (n Note) Signal() {}
     39 
     40 func (n Note) String() string {
     41 	return string(n)
     42 }
     43 
     44 var (
     45 	Stdin  = 0
     46 	Stdout = 1
     47 	Stderr = 2
     48 )
     49 
     50 // For testing: clients can set this flag to force
     51 // creation of IPv6 sockets to return EAFNOSUPPORT.
     52 var SocketDisableIPv6 bool
     53 
     54 func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err ErrorString)
     55 func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err ErrorString)
     56 func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
     57 func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
     58 
     59 func atoi(b []byte) (n uint) {
     60 	n = 0
     61 	for i := 0; i < len(b); i++ {
     62 		n = n*10 + uint(b[i]-'0')
     63 	}
     64 	return
     65 }
     66 
     67 func cstring(s []byte) string {
     68 	for i := range s {
     69 		if s[i] == 0 {
     70 			return string(s[0:i])
     71 		}
     72 	}
     73 	return string(s)
     74 }
     75 
     76 func errstr() string {
     77 	var buf [ERRMAX]byte
     78 
     79 	RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0)
     80 
     81 	buf[len(buf)-1] = 0
     82 	return cstring(buf[:])
     83 }
     84 
     85 // Implemented in assembly to import from runtime.
     86 func exit(code int)
     87 
     88 func Exit(code int) { exit(code) }
     89 
     90 func readnum(path string) (uint, error) {
     91 	var b [12]byte
     92 
     93 	fd, e := Open(path, O_RDONLY)
     94 	if e != nil {
     95 		return 0, e
     96 	}
     97 	defer Close(fd)
     98 
     99 	n, e := Pread(fd, b[:], 0)
    100 
    101 	if e != nil {
    102 		return 0, e
    103 	}
    104 
    105 	m := 0
    106 	for ; m < n && b[m] == ' '; m++ {
    107 	}
    108 
    109 	return atoi(b[m : n-1]), nil
    110 }
    111 
    112 func Getpid() (pid int) {
    113 	n, _ := readnum("#c/pid")
    114 	return int(n)
    115 }
    116 
    117 func Getppid() (ppid int) {
    118 	n, _ := readnum("#c/ppid")
    119 	return int(n)
    120 }
    121 
    122 func Read(fd int, p []byte) (n int, err error) {
    123 	return Pread(fd, p, -1)
    124 }
    125 
    126 func Write(fd int, p []byte) (n int, err error) {
    127 	return Pwrite(fd, p, -1)
    128 }
    129 
    130 var ioSync int64
    131 
    132 //sys	fd2path(fd int, buf []byte) (err error)
    133 func Fd2path(fd int) (path string, err error) {
    134 	var buf [512]byte
    135 
    136 	e := fd2path(fd, buf[:])
    137 	if e != nil {
    138 		return "", e
    139 	}
    140 	return cstring(buf[:]), nil
    141 }
    142 
    143 //sys	pipe(p *[2]int32) (err error)
    144 func Pipe(p []int) (err error) {
    145 	if len(p) != 2 {
    146 		return NewError("bad arg in system call")
    147 	}
    148 	var pp [2]int32
    149 	err = pipe(&pp)
    150 	p[0] = int(pp[0])
    151 	p[1] = int(pp[1])
    152 	return
    153 }
    154 
    155 // Underlying system call writes to newoffset via pointer.
    156 // Implemented in assembly to avoid allocation.
    157 func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
    158 
    159 func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
    160 	newoffset, e := seek(0, fd, offset, whence)
    161 
    162 	if newoffset == -1 {
    163 		err = NewError(e)
    164 	}
    165 	return
    166 }
    167 
    168 func Mkdir(path string, mode uint32) (err error) {
    169 	fd, err := Create(path, O_RDONLY, DMDIR|mode)
    170 
    171 	if fd != -1 {
    172 		Close(fd)
    173 	}
    174 
    175 	return
    176 }
    177 
    178 type Waitmsg struct {
    179 	Pid  int
    180 	Time [3]uint32
    181 	Msg  string
    182 }
    183 
    184 func (w Waitmsg) Exited() bool   { return true }
    185 func (w Waitmsg) Signaled() bool { return false }
    186 
    187 func (w Waitmsg) ExitStatus() int {
    188 	if len(w.Msg) == 0 {
    189 		// a normal exit returns no message
    190 		return 0
    191 	}
    192 	return 1
    193 }
    194 
    195 //sys	await(s []byte) (n int, err error)
    196 func Await(w *Waitmsg) (err error) {
    197 	var buf [512]byte
    198 	var f [5][]byte
    199 
    200 	n, err := await(buf[:])
    201 
    202 	if err != nil || w == nil {
    203 		return
    204 	}
    205 
    206 	nf := 0
    207 	p := 0
    208 	for i := 0; i < n && nf < len(f)-1; i++ {
    209 		if buf[i] == ' ' {
    210 			f[nf] = buf[p:i]
    211 			p = i + 1
    212 			nf++
    213 		}
    214 	}
    215 	f[nf] = buf[p:]
    216 	nf++
    217 
    218 	if nf != len(f) {
    219 		return NewError("invalid wait message")
    220 	}
    221 	w.Pid = int(atoi(f[0]))
    222 	w.Time[0] = uint32(atoi(f[1]))
    223 	w.Time[1] = uint32(atoi(f[2]))
    224 	w.Time[2] = uint32(atoi(f[3]))
    225 	w.Msg = cstring(f[4])
    226 	if w.Msg == "''" {
    227 		// await() returns '' for no error
    228 		w.Msg = ""
    229 	}
    230 	return
    231 }
    232 
    233 func Unmount(name, old string) (err error) {
    234 	Fixwd()
    235 	oldp, err := BytePtrFromString(old)
    236 	if err != nil {
    237 		return err
    238 	}
    239 	oldptr := uintptr(unsafe.Pointer(oldp))
    240 
    241 	var r0 uintptr
    242 	var e ErrorString
    243 
    244 	// bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted.
    245 	if name == "" {
    246 		r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldptr, 0)
    247 	} else {
    248 		namep, err := BytePtrFromString(name)
    249 		if err != nil {
    250 			return err
    251 		}
    252 		r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(namep)), oldptr, 0)
    253 		use(unsafe.Pointer(namep))
    254 	}
    255 	use(unsafe.Pointer(oldp))
    256 
    257 	if int32(r0) == -1 {
    258 		err = e
    259 	}
    260 	return
    261 }
    262 
    263 func Fchdir(fd int) (err error) {
    264 	path, err := Fd2path(fd)
    265 
    266 	if err != nil {
    267 		return
    268 	}
    269 
    270 	return Chdir(path)
    271 }
    272 
    273 type Timespec struct {
    274 	Sec  int32
    275 	Nsec int32
    276 }
    277 
    278 type Timeval struct {
    279 	Sec  int32
    280 	Usec int32
    281 }
    282 
    283 func NsecToTimeval(nsec int64) (tv Timeval) {
    284 	nsec += 999 // round up to microsecond
    285 	tv.Usec = int32(nsec % 1e9 / 1e3)
    286 	tv.Sec = int32(nsec / 1e9)
    287 	return
    288 }
    289 
    290 func nsec() int64 {
    291 	var scratch int64
    292 
    293 	r0, _, _ := Syscall(SYS_NSEC, uintptr(unsafe.Pointer(&scratch)), 0, 0)
    294 	// TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
    295 	if r0 == 0 {
    296 		return scratch
    297 	}
    298 	return int64(r0)
    299 }
    300 
    301 func Gettimeofday(tv *Timeval) error {
    302 	nsec := nsec()
    303 	*tv = NsecToTimeval(nsec)
    304 	return nil
    305 }
    306 
    307 func Getpagesize() int { return 0x1000 }
    308 
    309 func Getegid() (egid int) { return -1 }
    310 func Geteuid() (euid int) { return -1 }
    311 func Getgid() (gid int)   { return -1 }
    312 func Getuid() (uid int)   { return -1 }
    313 
    314 func Getgroups() (gids []int, err error) {
    315 	return make([]int, 0), nil
    316 }
    317 
    318 //sys	open(path string, mode int) (fd int, err error)
    319 func Open(path string, mode int) (fd int, err error) {
    320 	Fixwd()
    321 	return open(path, mode)
    322 }
    323 
    324 //sys	create(path string, mode int, perm uint32) (fd int, err error)
    325 func Create(path string, mode int, perm uint32) (fd int, err error) {
    326 	Fixwd()
    327 	return create(path, mode, perm)
    328 }
    329 
    330 //sys	remove(path string) (err error)
    331 func Remove(path string) error {
    332 	Fixwd()
    333 	return remove(path)
    334 }
    335 
    336 //sys	stat(path string, edir []byte) (n int, err error)
    337 func Stat(path string, edir []byte) (n int, err error) {
    338 	Fixwd()
    339 	return stat(path, edir)
    340 }
    341 
    342 //sys	bind(name string, old string, flag int) (err error)
    343 func Bind(name string, old string, flag int) (err error) {
    344 	Fixwd()
    345 	return bind(name, old, flag)
    346 }
    347 
    348 //sys	mount(fd int, afd int, old string, flag int, aname string) (err error)
    349 func Mount(fd int, afd int, old string, flag int, aname string) (err error) {
    350 	Fixwd()
    351 	return mount(fd, afd, old, flag, aname)
    352 }
    353 
    354 //sys	wstat(path string, edir []byte) (err error)
    355 func Wstat(path string, edir []byte) (err error) {
    356 	Fixwd()
    357 	return wstat(path, edir)
    358 }
    359 
    360 //sys	chdir(path string) (err error)
    361 //sys	Dup(oldfd int, newfd int) (fd int, err error)
    362 //sys	Pread(fd int, p []byte, offset int64) (n int, err error)
    363 //sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
    364 //sys	Close(fd int) (err error)
    365 //sys	Fstat(fd int, edir []byte) (n int, err error)
    366 //sys	Fwstat(fd int, edir []byte) (err error)
    367