ref: 038b1d6b1e2f30d0cc5168ee342b8b422b7d4818
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)
}