ref: e3843e8fa26afff64728ffe93ef77f0b10a1f109
dir: /lib/std/syswrap+plan9.myr/
use sys use "option" use "types" use "errno" use "result" use "cstrconv" use "strfind" use "syswrap-ss" pkg std = type fd = sys.fd type pid = sys.pid type fdopt = sys.fdopt type whence = int64 type sysinfo = struct system : byte[:] version : byte[:] release : byte[:] arch : byte[:] ;; const Seekset : whence = 0 const Seekcur : whence = 1 const Seekend : whence = 2 const Failmem : byte# = (-1 : byte#) const Oread : fdopt = (sys.Oread : fdopt) const Owrite : fdopt = (sys.Owrite : fdopt) const Ordwr : fdopt = (sys.Ordwr : fdopt) const Otrunc : fdopt = (sys.Otrunc : fdopt) const Ocexec : fdopt = (sys.Ocexec : fdopt) const Ocreat : fdopt = 0x1000000 /* emulated by redirecting to creat(). */ const Oappend : fdopt = 0x2000000 /* emulated by seeking to EOF */ const Odir : fdopt = 0x0 /* no-op on plan9 */ /* fd stuff */ const open : (path : byte[:], opts : fdopt -> result(fd, errno)) const openmode : (path : byte[:], opts : fdopt, mode : int64 -> result(fd, errno)) const close : (fd : fd -> errno) const read : (fd : fd, buf : byte[:] -> result(size, errno)) const pread : (fd : fd, buf : byte[:], off : off -> result(size, errno)) const write : (fd : fd, buf : byte[:] -> result(size, errno)) const pwrite : (fd : fd, buf : byte[:], off : off -> result(size, errno)) const seek : (fd : fd, delta : off, whence : whence -> result(off, errno)) const pipe : (fds : fd[2]# -> errno) const dup2 : (ofd : fd, nfd : fd -> result(fd, errno)) /* useful/portable bits of stat */ const fmtime : (f : byte[:] -> result(time, errno)) const fsize : (f : byte[:] -> result(off, errno)) const fexists : (f : byte[:] -> bool) const fisdir : (f : byte[:] -> bool) const fisreg : (f : byte[:] -> bool) /* the important bits that uname provides */ const getsysinfo : (si : sysinfo# -> void) /* path manipulation */ const mkdir : (path : byte[:], mode : int64 -> errno) const chdir : (path : byte[:] -> bool) const remove : (path : byte[:] -> bool) /* process stuff */ const getpid : ( -> pid) $noret const suicide : ( -> void) const fork : (-> pid) const execv : (cmd : byte[:], args : byte[:][:] -> errno) const execve : (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> errno) pkglocal const Canunmap : bool = true pkglocal const getmem : (sz : size -> byte#) pkglocal const freemem : (p : byte#, sz : size -> void) pkglocal const curtime : (-> time) pkglocal const p9errstr : (buf : byte[:] -> byte[:]) /* statbuf offsets */ pkglocal const Sizeoff : int64 = 0 pkglocal const Sizesz : int64 = 2 pkglocal const Typeoff : int64 = Sizeoff + Sizesz pkglocal const Typesz : int64 = 2 pkglocal const Devoff : int64 = Typeoff + Typesz pkglocal const Devsz : int64 = 4 pkglocal const Qidtypeoff : int64 = Devoff + Devsz pkglocal const Qidtypesz : int64 = 1 pkglocal const Qidversoff : int64 = Qidtypeoff + Qidtypesz pkglocal const Qidverssz : int64 = 4 pkglocal const Qidpathoff : int64 = Qidversoff + Qidverssz pkglocal const Qidpathsz : int64 = 8 pkglocal const Modeoff : int64 = Qidpathoff + Qidpathsz pkglocal const Modesz : int64 = 4 pkglocal const Atimeoff : int64 = Modeoff + Modesz pkglocal const Atimesz : int64 = 4 pkglocal const Mtimeoff : int64 = Atimeoff + Atimesz pkglocal const Mtimesz : int64 = 4 pkglocal const Lengthoff : int64 = Mtimeoff + Mtimesz pkglocal const Lengthsz : int64 = 8 pkglocal const Stringsoff : int64 = Lengthoff + Lengthsz ;; /* UGLY: circular dependency breaking... */ extern const getenvv : (name : byte[:], default : byte[:] -> byte[:]) /* fd stuff */ const open = {path, opts; -> check(sys.open(path, (opts : sys.fdopt)))} const openmode = {path, opts, mode; var fd if opts & Ocreat != 0 opts &= ~Ocreat fd = sys.create(path, (opts : sys.fdopt), (mode : int)) else fd = sys.open(path, (opts : sys.fdopt)) ;; if opts & Oappend != 0 sys.seek(fd, 0, 2) ;; -> check(fd) } /* useful/portable bits of stat */ const fexists = {path var buf : byte[4] /* big enough for size, nothing else. */ -> sys.stat(path, buf[:]) >= 0 } const fmtime = {path var buf : byte[Stringsoff + 512] /* enough space for some strings */ if sys.stat(path, buf[:]) < Stringsoff -> `Err Emisc ;; -> `Ok ((_getle32(buf[Mtimeoff:Mtimeoff + 8]) : time)*1_000_000) } const fsize = {path var buf : byte[Stringsoff + 512] /* enough space for some strings */ if sys.stat(path, buf[:]) < Stringsoff -> `Err Emisc ;; -> `Ok (_getle64(buf[Lengthoff:Lengthoff + 8]) : off) } extern const put : (fmt : byte[:], args : ... -> int64) const fisdir = {path var buf : byte[Stringsoff + 39] /* enough space for qid type */ if sys.stat(path, buf[:]) < Stringsoff -> false ;; -> (_getle32(buf[Modeoff:Modeoff + 4]) & sys.Dmdir) != 0 } const fisreg = {path var buf : byte[Stringsoff + 512] /* enough space for some strings */ var ty if sys.stat(path, buf[:]) < Stringsoff -> false ;; ty = _getle16(buf[Typeoff:Typeoff + 2]) if (_getle32(buf[Modeoff:Modeoff + 4]) & sys.Dmdir) != 0 -> false /* ugh. maybe this call should just be '!fisdir()' */ elif ty == '|' || ty == 's' || ty == 'm' -> false else -> true ;; } const getsysinfo = {si si.system = getenvv("osname", "Plan9") si.release = "4" si.version = "0" si.arch = getenvv("objtype", "amd64") } const close = {fd; -> (sys.close((fd : sys.fd)) : errno)} const read = {fd, buf; -> check(sys.pread((fd : sys.fd), buf, -1))} const pread = {fd, buf,off; -> check(sys.pread((fd : sys.fd), buf, (off : sys.off)))} const write = {fd, buf; -> check(sys.pwrite((fd : sys.fd), buf, -1))} const pwrite = {fd, buf,off; -> check(sys.pwrite((fd : sys.fd), buf, (off : sys.off)))} const seek = {fd, off, whence; -> check(sys.seek((fd : sys.fd), (off : sys.off), (whence : int64)))} const pipe = {fds; -> (sys.pipe((fds : sys.fd[2]#)) : errno)} const dup2 = {ofd, nfd; -> check(sys.dup((ofd : sys.fd), (nfd : sys.fd)))} /* path manipulation */ const remove = {path; -> sys.remove(path) == 0} const chdir = {path; -> sys.chdir(path) == 0} const mkdir = {path, mode; var fd fd = sys.create(path, sys.Oread, sys.Dmdir | (mode : int)) if fd < 0 -> lasterr() ;; sys.close(fd) -> 0 } /* process stuff */ const getpid = {; -> (sys.tosptr.pid : pid)} const suicide = {; (0 : byte#)#} /* let's happy segfault!! t */ const fork = {; -> (sys.rfork(sys.Rffdg | sys.Rfrend | sys.Rfproc) : pid)} const execv = {cmd, args; sys.exec(cmd, args) -> lasterr() } const execve = {cmd, args, env; sys.exec(cmd, args) -> lasterr() } /* memory stuff */ const getmem = {sz var endp, oldp oldp = sys.curbrk endp = (sys.curbrk : intptr) + (sz : intptr) endp = (endp + 4095) & ~4095 if sys.brk_((endp : byte#)) < 0 -> Failmem ;; sys.curbrk = (endp : byte#) -> oldp } const freemem = {p, sz /* FIXME: we leak address space */ sys.segfree(p, (sz : sys.size)) } const curtime = { -> (sys.nsec()/1000 : time) } const p9errstr = {errbuf var i sys.errstr(errbuf) for i = 0; errbuf[i] != 0 && i < errbuf.len; i++ continue ;; -> errbuf[:i] } /* FIXME: will be needed when we resize stat bufs when statting. const statsz = {buf -> (buf[0] : int64)) | ((buf[1] << 8 : int64)) } */ generic check = {e : @a -> result(@b, errno) :: integral, numeric @a if e < 0 -> `Err lasterr() else -> `Ok (e : @b) ;; } /* duplicated code to break dependency cycle */ generic _getle16 = {buf -> @a :: numeric,integral @a -> ((buf[0] : @a) << 0) | \ ((buf[1] : @a) << 8) } generic _getle32 = {buf -> @a :: numeric,integral @a -> ((buf[0] : @a) << 0) | \ ((buf[1] : @a) << 8) | \ ((buf[2] : @a) << 16) | \ ((buf[3] : @a) << 24) } generic _getle64 = {buf -> @a :: numeric,integral @a -> ((buf[0] : @a) << 0) | \ ((buf[1] : @a) << 8) | \ ((buf[2] : @a) << 16) | \ ((buf[3] : @a) << 24) | \ ((buf[4] : @a) << 32) | \ ((buf[5] : @a) << 40) | \ ((buf[6] : @a) << 48) | \ ((buf[7] : @a) << 56) }