gemini-browser

A text-based gemini browser
git clone git://git.laack.co/gemini-browser.git
Log | Files | Refs | README

syscall_plan9.go (7216B)


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