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