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