ref: 62ea6ad22c399c646e396efe264c8314f14027a3
dir: /lib/std/syswrap+plan9.myr/
use sys
use "option.use"
use "types.use"
use "errno.use"
use "result.use"
use "cstrconv.use"
use "strfind.use"
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 castto(byte#)
const Ordonly : fdopt = sys.Ordonly castto(fdopt)
const Owronly : fdopt = sys.Owronly castto(fdopt)
const Ordwr : fdopt = sys.Ordwr castto(fdopt)
const Otrunc : fdopt = sys.Otrunc castto(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 creat : (path : byte[:], mode : int64 -> result(fd, errno))
const read : (fd : fd, buf : byte[:] -> result(size, errno))
const write : (fd : fd, buf : byte[:] -> 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)
/* 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)
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[:])
pkglocal const waitpid : (pid:pid, loc:int32#, opt : int64 -> pid)
/* statbuf offsets */
pkglocal const Sizeoff : int64 = 0
pkglocal const Typeoff : int64 = 2
pkglocal const Devoff : int64 = 4
pkglocal const Qidtypeoff : int64 =8
pkglocal const Qidversoff : int64 = 9
pkglocal const Qidpathoff : int64 = 13
pkglocal const Modeoff : int64 = 21
pkglocal const Atimeoff : int64 = 25
pkglocal const Mtimeoff : int64 = 29
pkglocal const Lengthoff : int64 = 31
pkglocal const Stringsoff : int64 = 39
;;
/* UGLY: circular dependency breaking... */
extern const getenvv : (name : byte[:], default : byte[:] -> byte[:])
/* fd stuff */
const open = {path, opts; -> check(sys.open(path, opts castto(sys.fdopt)))}
const openmode = {path, opts, mode;
var fd
if opts & Ocreat != 0
fd = sys.create(path, (opts & ~Ocreat) castto(sys.fdopt), mode castto(int))
else
fd = sys.open(path, opts castto(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
-> `Fail Emisc
;;
-> `Ok (getle32(buf[Mtimeoff:Mtimeoff + 8]) castto(time))
}
const fsize = {path
var buf : byte[Stringsoff + 512] /* enough space for some strings */
if sys.stat(path, buf[:]) < Stringsoff
-> `Fail Emisc
;;
-> `Ok (getle64(buf[Lengthoff:Lengthoff + 8]) castto(off))
}
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 castto(sys.fd)) castto(errno)}
const read = {fd, buf; -> check(sys.pread(fd castto(sys.fd), buf, -1))}
const write = {fd, buf; -> check(sys.pwrite(fd castto(sys.fd), buf, -1))}
const seek = {fd, off, whence; -> check(sys.seek(fd castto(sys.fd), off castto(sys.off), whence castto(int64)))}
const pipe = {fds; -> sys.pipe(fds castto(sys.fd[2]#)) castto(errno)}
const dup2 = {ofd, nfd; -> check(sys.dup(ofd castto(sys.fd), nfd castto(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.Ordonly, sys.Dmdir | (mode castto(int)))
if fd < 0
-> lasterr()
;;
sys.close(fd)
-> 0
}
/* process stuff */
const getpid = {; -> sys.tosptr.pid castto(pid)}
const suicide = {; (0 castto(byte#))#} /* let's happy segfault!! t */
const fork = {; -> sys.rfork(sys.Rffdg | sys.Rfrend | sys.Rfproc) castto(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 castto(intptr)) + (sz castto(intptr))
endp = (endp + 4095) & ~4095
if sys.brk_(endp castto(byte#)) < 0
-> Failmem
;;
sys.curbrk = endp castto(byte#)
-> oldp
}
const freemem = {p, sz
/* FIXME: we leak address space */
sys.segfree(p, sz castto(sys.size))
}
const curtime = {
-> sys.nsec()/1000 castto(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] castto(int64)) | ((buf[1] << 8) castto(int64))
}
*/
const getle32 = {buf
-> (buf[0] castto(int32)) \
| ((buf[1] castto(int32)) << 8) \
| ((buf[2] castto(int32)) << 16) \
| ((buf[3] castto(int32)) << 24)
}
const getle64 = {buf
-> (buf[0] castto(int64)) \
| ((buf[1] castto(int64)) << 8) \
| ((buf[2] castto(int64)) << 16) \
| ((buf[3] castto(int64)) << 24) \
| ((buf[4] castto(int64)) << 64) \
| ((buf[5] castto(int64)) << 40) \
| ((buf[6] castto(int64)) << 48) \
| ((buf[7] castto(int64)) << 56)
}
generic check = {e : @a::(integral, numeric) -> result(@b, errno)
if e < 0
-> `Fail lasterr()
else
-> `Ok e castto(@b)
;;
}
const lasterr = {
var errbuf : byte[sys.Maxerr]
var err
sys.errstr(errbuf[:])
err = cstrconv(errbuf[:])
if strhas(err, "no error")
-> Enone
elif strhas(err, "already exists")
-> Eexist
elif strhas(err, "read or write too large")
-> Erange
elif strhas(err, "read or write too small")
-> Erange
elif strhas(err, "i/o error")
-> Eio
elif strhas(err, "fd out of range or not open")
-> Ebadf
else
-> Emisc
;;
}