├── .gitignore ├── compat ├── lib9.h ├── rand.c ├── lib9 │ ├── md │ │ ├── getcallerpc-sun4u.s │ │ ├── getcallerpc-386.c │ │ ├── getcallerpc-arm.c │ │ ├── getcallerpc-x86_64.c │ │ └── getcallerpc-power.c │ ├── exitcode.c │ ├── atoi.c │ ├── pin.c │ ├── nulldir.c │ ├── dup.c │ ├── argv0.c │ ├── get9root.c │ ├── strdup.c │ ├── mallocz.c │ ├── strecpy.c │ ├── jmp.c │ ├── getenv.c │ ├── getuser.c │ ├── readn.c │ ├── write.c │ ├── waitpid.c │ ├── sysfatal.c │ ├── cistrstr.c │ ├── cistrncmp.c │ ├── malloc.c │ ├── read9pmsg.c │ ├── atexit.c │ ├── atnotify.c │ ├── sleep.c │ ├── dirmodefmt.c │ ├── netmkaddr.c │ ├── errstr.c │ ├── convM2D.c │ ├── convD2M.c │ ├── sendfd.c │ ├── tokenize.c │ ├── LICENSE │ ├── qlock.c │ ├── await.c │ ├── dial.c │ ├── _p9dialparse.c │ ├── _p9dir.c │ ├── notify.c │ ├── convM2S.c │ ├── convS2M.c │ ├── fcallfmt.c │ └── open.c ├── fmt │ ├── nan.h │ ├── fmtlock.c │ ├── print.c │ ├── smprint.c │ ├── fprint.c │ ├── fmtstr.c │ ├── seprint.c │ ├── snprint.c │ ├── vfprint.c │ ├── fmtfdflush.c │ ├── vseprint.c │ ├── vsnprint.c │ ├── fmtprint.c │ ├── fmtfd.c │ ├── sprint.c │ ├── plan9.h │ ├── NOTICE │ ├── README │ ├── LICENSE │ ├── fmtlocale.c │ ├── nan64.c │ ├── vsmprint.c │ ├── fmtdef.h │ ├── fmt.c │ └── fmtquote.c ├── libthread │ ├── ioproc.h │ ├── ref.c │ ├── ioproc.c │ ├── threadimpl.h │ ├── iorw.c │ ├── daemonize.c │ └── pthread.c ├── utf │ ├── plan9.h │ ├── LICENSE │ ├── NOTICE │ ├── README │ ├── utflen.c │ ├── utfnlen.c │ ├── utfecpy.c │ ├── utfrune.c │ └── rune.c ├── lib9pclient │ ├── open.c │ ├── close.c │ ├── seek.c │ ├── fsimpl.h │ ├── wstat.c │ ├── create.c │ ├── stat.c │ ├── COPYRIGHT │ ├── read.c │ ├── write.c │ ├── walk.c │ └── dirread.c ├── libmux │ ├── COPYRIGHT │ ├── queue.c │ ├── io.c │ └── mux.c ├── lrand.c ├── mux.h ├── utf.h ├── 9pclient.h ├── fcall.h ├── fmt.h ├── thread.h ├── u.h └── 9p.h ├── main_p9main.c ├── CHANGELOG.md ├── README.md ├── COPYRIGHT ├── 9pfuse.4 ├── a.h ├── errstr.c └── meson.build /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.sw[op] 3 | -------------------------------------------------------------------------------- /compat/lib9.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | -------------------------------------------------------------------------------- /compat/rand.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | p9rand(void) 5 | { 6 | return lrand() & 0x7fff; 7 | } 8 | -------------------------------------------------------------------------------- /compat/lib9/md/getcallerpc-sun4u.s: -------------------------------------------------------------------------------- 1 | .text 2 | .globl getcallerpc 3 | getcallerpc: 4 | retl 5 | or %o7, %r0, %o0 6 | -------------------------------------------------------------------------------- /compat/lib9/exitcode.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int 5 | exitcode(char *s) 6 | { 7 | return 1; 8 | } 9 | -------------------------------------------------------------------------------- /compat/lib9/atoi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int 5 | atoi(char *s) 6 | { 7 | return strtol(s, 0, 0); 8 | } 9 | -------------------------------------------------------------------------------- /compat/lib9/md/getcallerpc-386.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | ulong 4 | getcallerpc(void *x) 5 | { 6 | return (((ulong*)(x))[-1]); 7 | } 8 | -------------------------------------------------------------------------------- /compat/lib9/md/getcallerpc-arm.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | ulong 4 | getcallerpc(void *x) 5 | { 6 | return ((ulong*)x)[-2]; 7 | } 8 | 9 | -------------------------------------------------------------------------------- /compat/lib9/md/getcallerpc-x86_64.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | ulong 4 | getcallerpc(void *x) 5 | { 6 | return (((ulong*)(x))[-1]); 7 | } 8 | -------------------------------------------------------------------------------- /compat/fmt/nan.h: -------------------------------------------------------------------------------- 1 | extern double __NaN(void); 2 | extern double __Inf(int); 3 | extern int __isNaN(double); 4 | extern int __isInf(double, int); 5 | -------------------------------------------------------------------------------- /main_p9main.c: -------------------------------------------------------------------------------- 1 | 2 | extern int p9main(int argc, char **argv); 3 | 4 | int 5 | main(int argc, char **argv) 6 | { 7 | return p9main(argc, argv); 8 | } 9 | 10 | -------------------------------------------------------------------------------- /compat/lib9/md/getcallerpc-power.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | ulong 4 | getcallerpc(void *x) 5 | { 6 | ulong *lp; 7 | 8 | lp = x; 9 | 10 | return lp[-1]; 11 | } 12 | -------------------------------------------------------------------------------- /compat/lib9/pin.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static void 5 | nop(void) 6 | { 7 | } 8 | 9 | void (*_pin)(void) = nop; 10 | void (*_unpin)(void) = nop; 11 | -------------------------------------------------------------------------------- /compat/lib9/nulldir.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void 5 | nulldir(Dir *d) 6 | { 7 | memset(d, ~0, sizeof(Dir)); 8 | d->name = d->uid = d->gid = d->muid = d->ext = ""; 9 | } 10 | -------------------------------------------------------------------------------- /compat/lib9/dup.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #undef dup 5 | 6 | int 7 | p9dup(int old, int new) 8 | { 9 | if(new == -1) 10 | return dup(old); 11 | return dup2(old, new); 12 | } 13 | -------------------------------------------------------------------------------- /compat/lib9/argv0.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char *argv0; 4 | 5 | /* 6 | * Mac OS can't deal with files that only declare data. 7 | * ARGBEGIN mentions this function so that this file gets pulled in. 8 | */ 9 | void __fixargv0(void) { } 10 | -------------------------------------------------------------------------------- /compat/lib9/get9root.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | char* 5 | get9root(void) 6 | { 7 | static char *s; 8 | 9 | if(s) 10 | return s; 11 | 12 | if((s = getenv("PLAN9")) != 0) 13 | return s; 14 | s = PLAN9_TARGET; 15 | return s; 16 | } 17 | -------------------------------------------------------------------------------- /compat/lib9/strdup.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | char* 5 | strdup(char *s) 6 | { 7 | char *t; 8 | int l; 9 | 10 | l = strlen(s); 11 | t = malloc(l+1); 12 | if(t == nil) 13 | return nil; 14 | memmove(t, s, l+1); 15 | return t; 16 | } 17 | -------------------------------------------------------------------------------- /compat/lib9/mallocz.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void* 7 | mallocz(unsigned long n, int clr) 8 | { 9 | void *v; 10 | 11 | v = malloc(n); 12 | if(clr && v) 13 | memset(v, 0, n); 14 | return v; 15 | } 16 | -------------------------------------------------------------------------------- /compat/fmt/fmtlock.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 | #include 3 | #include "plan9.h" 4 | #include "fmt.h" 5 | #include "fmtdef.h" 6 | 7 | void 8 | __fmtlock(void) 9 | { 10 | } 11 | 12 | void 13 | __fmtunlock(void) 14 | { 15 | } 16 | -------------------------------------------------------------------------------- /compat/libthread/ioproc.h: -------------------------------------------------------------------------------- 1 | #define ioproc_arg(io, type) (va_arg((io)->arg, type)) 2 | 3 | struct Ioproc 4 | { 5 | int tid; 6 | Channel *c, *creply; 7 | int inuse; 8 | long (*op)(va_list*); 9 | va_list arg; 10 | long ret; 11 | char err[ERRMAX]; 12 | Ioproc *next; 13 | }; 14 | -------------------------------------------------------------------------------- /compat/lib9/strecpy.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char* 4 | strecpy(char *to, char *e, char *from) 5 | { 6 | if(to >= e) 7 | return to; 8 | to = memccpy(to, from, '\0', e - to); 9 | if(to == nil){ 10 | to = e - 1; 11 | *to = '\0'; 12 | }else{ 13 | to--; 14 | } 15 | return to; 16 | } 17 | -------------------------------------------------------------------------------- /compat/lib9/jmp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define NOPLAN9DEFINES 3 | #include 4 | 5 | void 6 | p9longjmp(p9jmp_buf buf, int val) 7 | { 8 | siglongjmp((void*)buf, val); 9 | } 10 | 11 | void 12 | p9notejmp(void *x, p9jmp_buf buf, int val) 13 | { 14 | USED(x); 15 | siglongjmp((void*)buf, val); 16 | } 17 | -------------------------------------------------------------------------------- /compat/lib9/getenv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define NOPLAN9DEFINES 3 | #include 4 | 5 | char* 6 | p9getenv(char *s) 7 | { 8 | char *t; 9 | 10 | t = getenv(s); 11 | if(t == 0) 12 | return 0; 13 | return strdup(t); 14 | } 15 | 16 | int 17 | p9putenv(char *s, char *v) 18 | { 19 | return setenv(s, v, 1); 20 | } 21 | -------------------------------------------------------------------------------- /compat/lib9/getuser.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | char* 6 | getuser(void) 7 | { 8 | static char user[64]; 9 | struct passwd *pw; 10 | 11 | pw = getpwuid(getuid()); 12 | if(pw == nil) 13 | return "none"; 14 | strecpy(user, user+sizeof user, pw->pw_name); 15 | return user; 16 | } 17 | -------------------------------------------------------------------------------- /compat/lib9/readn.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | long 4 | readn(int f, void *av, long n) 5 | { 6 | char *a; 7 | long m, t; 8 | 9 | a = av; 10 | t = 0; 11 | while(t < n){ 12 | m = read(f, a+t, n-t); 13 | if(m <= 0){ 14 | if(t == 0) 15 | return m; 16 | break; 17 | } 18 | t += m; 19 | } 20 | return t; 21 | } 22 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## v2 4 | 5 | ### Added 6 | 7 | - The Meson build system now also installs the `9pfuse.4` manual page. 8 | 9 | ### Changed 10 | 11 | - Updated plan9port sources, and change build system accordingly. 12 | 13 | 14 | ## v1 15 | 16 | ### Added 17 | 18 | - Meson build system. 19 | - First tagged release. 20 | -------------------------------------------------------------------------------- /compat/fmt/print.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 | #include 3 | #include "plan9.h" 4 | #include "fmt.h" 5 | #include "fmtdef.h" 6 | 7 | int 8 | print(char *fmt, ...) 9 | { 10 | int n; 11 | va_list args; 12 | 13 | va_start(args, fmt); 14 | n = vfprint(1, fmt, args); 15 | va_end(args); 16 | return n; 17 | } 18 | -------------------------------------------------------------------------------- /compat/fmt/smprint.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 | #include 3 | #include "plan9.h" 4 | #include "fmt.h" 5 | #include "fmtdef.h" 6 | 7 | char* 8 | smprint(char *fmt, ...) 9 | { 10 | va_list args; 11 | char *p; 12 | 13 | va_start(args, fmt); 14 | p = vsmprint(fmt, args); 15 | va_end(args); 16 | return p; 17 | } 18 | -------------------------------------------------------------------------------- /compat/fmt/fprint.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 | #include 3 | #include "plan9.h" 4 | #include "fmt.h" 5 | #include "fmtdef.h" 6 | 7 | int 8 | fprint(int fd, char *fmt, ...) 9 | { 10 | int n; 11 | va_list args; 12 | 13 | va_start(args, fmt); 14 | n = vfprint(fd, fmt, args); 15 | va_end(args); 16 | return n; 17 | } 18 | -------------------------------------------------------------------------------- /compat/fmt/fmtstr.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 | #include 3 | #include 4 | #include "plan9.h" 5 | #include "fmt.h" 6 | #include "fmtdef.h" 7 | 8 | char* 9 | fmtstrflush(Fmt *f) 10 | { 11 | if(f->start == nil) 12 | return nil; 13 | *(char*)f->to = '\0'; 14 | f->to = f->start; 15 | return (char*)f->start; 16 | } 17 | -------------------------------------------------------------------------------- /compat/lib9/write.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define NOPLAN9DEFINES 3 | #include 4 | 5 | long 6 | p9write(int f, void *av, long n) 7 | { 8 | char *a; 9 | long m, t; 10 | 11 | a = av; 12 | t = 0; 13 | while(t < n){ 14 | m = write(f, a+t, n-t); 15 | if(m <= 0){ 16 | if(t == 0) 17 | return m; 18 | break; 19 | } 20 | t += m; 21 | } 22 | return t; 23 | } 24 | -------------------------------------------------------------------------------- /compat/fmt/seprint.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 | #include 3 | #include "plan9.h" 4 | #include "fmt.h" 5 | #include "fmtdef.h" 6 | 7 | char* 8 | seprint(char *buf, char *e, char *fmt, ...) 9 | { 10 | char *p; 11 | va_list args; 12 | 13 | va_start(args, fmt); 14 | p = vseprint(buf, e, fmt, args); 15 | va_end(args); 16 | return p; 17 | } 18 | -------------------------------------------------------------------------------- /compat/fmt/snprint.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 | #include 3 | #include "plan9.h" 4 | #include "fmt.h" 5 | #include "fmtdef.h" 6 | 7 | int 8 | snprint(char *buf, int len, char *fmt, ...) 9 | { 10 | int n; 11 | va_list args; 12 | 13 | va_start(args, fmt); 14 | n = vsnprint(buf, len, fmt, args); 15 | va_end(args); 16 | return n; 17 | } 18 | -------------------------------------------------------------------------------- /compat/lib9/waitpid.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int 5 | waitpid(void) 6 | { 7 | int n; 8 | char buf[512], *fld[5]; 9 | 10 | n = await(buf, sizeof buf-1); 11 | if(n <= 0) 12 | return -1; 13 | buf[n] = '\0'; 14 | if(tokenize(buf, fld, nelem(fld)) != nelem(fld)){ 15 | werrstr("couldn't parse wait message"); 16 | return -1; 17 | } 18 | return atoi(fld[0]); 19 | } 20 | -------------------------------------------------------------------------------- /compat/libthread/ref.c: -------------------------------------------------------------------------------- 1 | #include "u.h" 2 | #include "libc.h" 3 | #include "thread.h" 4 | 5 | static long 6 | refadd(Ref *r, long a) 7 | { 8 | long ref; 9 | 10 | lock(&r->lock); 11 | r->ref += a; 12 | ref = r->ref; 13 | unlock(&r->lock); 14 | return ref; 15 | } 16 | 17 | long 18 | incref(Ref *r) 19 | { 20 | return refadd(r, 1); 21 | } 22 | 23 | long 24 | decref(Ref *r) 25 | { 26 | return refadd(r, -1); 27 | } 28 | -------------------------------------------------------------------------------- /compat/lib9/sysfatal.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void (*_sysfatal)(char*, ...); 4 | 5 | void 6 | sysfatal(char *fmt, ...) 7 | { 8 | char buf[256]; 9 | va_list arg; 10 | 11 | va_start(arg, fmt); 12 | if(_sysfatal) 13 | (*_sysfatal)(fmt, arg); 14 | vseprint(buf, buf+sizeof buf, fmt, arg); 15 | va_end(arg); 16 | 17 | __fixargv0(); 18 | fprint(2, "%s: %s\n", argv0 ? argv0 : "", buf); 19 | exits("fatal"); 20 | } 21 | -------------------------------------------------------------------------------- /compat/lib9/cistrstr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | char* 5 | cistrstr(char *s, char *sub) 6 | { 7 | int c, csub, n; 8 | 9 | csub = *sub; 10 | if(csub == '\0') 11 | return s; 12 | if(csub >= 'A' && csub <= 'Z') 13 | csub -= 'A' - 'a'; 14 | sub++; 15 | n = strlen(sub); 16 | for(; c = *s; s++){ 17 | if(c >= 'A' && c <= 'Z') 18 | c -= 'A' - 'a'; 19 | if(c == csub && cistrncmp(s+1, sub, n) == 0) 20 | return s; 21 | } 22 | return nil; 23 | } 24 | -------------------------------------------------------------------------------- /compat/fmt/vfprint.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 | #include 3 | #include "plan9.h" 4 | #include "fmt.h" 5 | #include "fmtdef.h" 6 | 7 | int 8 | vfprint(int fd, char *fmt, va_list args) 9 | { 10 | Fmt f; 11 | char buf[256]; 12 | int n; 13 | 14 | fmtfdinit(&f, fd, buf, sizeof(buf)); 15 | VA_COPY(f.args,args); 16 | n = dofmt(&f, fmt); 17 | VA_END(f.args); 18 | if(n > 0 && __fmtFdFlush(&f) == 0) 19 | return -1; 20 | return n; 21 | } 22 | -------------------------------------------------------------------------------- /compat/lib9/cistrncmp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int 5 | cistrncmp(char *s1, char *s2, int n) 6 | { 7 | int c1, c2; 8 | 9 | while(*s1 && n-- > 0){ 10 | c1 = *(uchar*)s1++; 11 | c2 = *(uchar*)s2++; 12 | 13 | if(c1 == c2) 14 | continue; 15 | 16 | if(c1 >= 'A' && c1 <= 'Z') 17 | c1 -= 'A' - 'a'; 18 | 19 | if(c2 >= 'A' && c2 <= 'Z') 20 | c2 -= 'A' - 'a'; 21 | 22 | if(c1 != c2) 23 | return c1 - c2; 24 | } 25 | if(n <= 0) 26 | return 0; 27 | return -*s2; 28 | } 29 | -------------------------------------------------------------------------------- /compat/fmt/fmtfdflush.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 | #include 3 | #include 4 | #include "plan9.h" 5 | #include "fmt.h" 6 | #include "fmtdef.h" 7 | 8 | /* 9 | * generic routine for flushing a formatting buffer 10 | * to a file descriptor 11 | */ 12 | int 13 | __fmtFdFlush(Fmt *f) 14 | { 15 | int n; 16 | 17 | n = (char*)f->to - (char*)f->start; 18 | if(n && write((uintptr)f->farg, f->start, n) != n) 19 | return 0; 20 | f->to = f->start; 21 | return 1; 22 | } 23 | -------------------------------------------------------------------------------- /compat/lib9/malloc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * These are here mainly so that I can link against 3 | * debugmalloc.c instead and not recompile the world. 4 | */ 5 | 6 | #include 7 | #define NOPLAN9DEFINES 8 | #include 9 | 10 | 11 | void* 12 | p9malloc(ulong n) 13 | { 14 | if(n == 0) 15 | n++; 16 | return malloc(n); 17 | } 18 | 19 | void 20 | p9free(void *v) 21 | { 22 | free(v); 23 | } 24 | 25 | void* 26 | p9calloc(ulong a, ulong b) 27 | { 28 | if(a*b == 0) 29 | a = b = 1; 30 | return calloc(a, b); 31 | } 32 | 33 | void* 34 | p9realloc(void *v, ulong n) 35 | { 36 | return realloc(v, n); 37 | } 38 | -------------------------------------------------------------------------------- /compat/fmt/vseprint.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 | #include 3 | #include "plan9.h" 4 | #include "fmt.h" 5 | #include "fmtdef.h" 6 | 7 | char* 8 | vseprint(char *buf, char *e, char *fmt, va_list args) 9 | { 10 | Fmt f; 11 | 12 | if(e <= buf) 13 | return nil; 14 | f.runes = 0; 15 | f.start = buf; 16 | f.to = buf; 17 | f.stop = e - 1; 18 | f.flush = 0; 19 | f.farg = nil; 20 | f.nfmt = 0; 21 | VA_COPY(f.args,args); 22 | fmtlocaleinit(&f, nil, nil, nil); 23 | dofmt(&f, fmt); 24 | VA_END(f.args); 25 | *(char*)f.to = '\0'; 26 | return (char*)f.to; 27 | } 28 | -------------------------------------------------------------------------------- /compat/lib9/read9pmsg.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int 6 | read9pmsg(int fd, void *abuf, uint n) 7 | { 8 | int m, len; 9 | uchar *buf; 10 | 11 | buf = abuf; 12 | 13 | /* read count */ 14 | m = readn(fd, buf, BIT32SZ); 15 | if(m != BIT32SZ){ 16 | if(m < 0) 17 | return -1; 18 | return 0; 19 | } 20 | 21 | len = GBIT32(buf); 22 | if(len <= BIT32SZ || len > n){ 23 | werrstr("bad length in 9P2000 message header"); 24 | return -1; 25 | } 26 | len -= BIT32SZ; 27 | m = readn(fd, buf+BIT32SZ, len); 28 | if(m < len) 29 | return 0; 30 | return BIT32SZ+m; 31 | } 32 | -------------------------------------------------------------------------------- /compat/fmt/vsnprint.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 | #include 3 | #include 4 | #include "plan9.h" 5 | #include "fmt.h" 6 | #include "fmtdef.h" 7 | 8 | int 9 | vsnprint(char *buf, int len, char *fmt, va_list args) 10 | { 11 | Fmt f; 12 | 13 | if(len <= 0) 14 | return -1; 15 | f.runes = 0; 16 | f.start = buf; 17 | f.to = buf; 18 | f.stop = buf + len - 1; 19 | f.flush = 0; 20 | f.farg = nil; 21 | f.nfmt = 0; 22 | VA_COPY(f.args,args); 23 | fmtlocaleinit(&f, nil, nil, nil); 24 | dofmt(&f, fmt); 25 | VA_END(f.args); 26 | *(char*)f.to = '\0'; 27 | return (char*)f.to - buf; 28 | } 29 | -------------------------------------------------------------------------------- /compat/utf/plan9.h: -------------------------------------------------------------------------------- 1 | /* 2 | * compiler directive on Plan 9 3 | */ 4 | #ifndef USED 5 | #define USED(x) if(x);else 6 | #endif 7 | 8 | /* 9 | * easiest way to make sure these are defined 10 | */ 11 | #define uchar _utfuchar 12 | #define ushort _utfushort 13 | #define uint _utfuint 14 | #define ulong _utfulong 15 | typedef unsigned char uchar; 16 | typedef unsigned short ushort; 17 | typedef unsigned int uint; 18 | typedef unsigned long ulong; 19 | 20 | /* 21 | * nil cannot be ((void*)0) on ANSI C, 22 | * because it is used for function pointers 23 | */ 24 | #undef nil 25 | #define nil 0 26 | 27 | #undef nelem 28 | #define nelem(x) (sizeof (x)/sizeof (x)[0]) 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 9pfuse 2 | ====== 3 | 4 | This is a standalone version of `9pfuse`, a FUSE client for the 9P protocol 5 | as included in [Plan9 Port](http://swtch.com/plan9port). The source code has 6 | been imported from the `src/cmd/9pfuse` directory of the repository, adding 7 | the minimum set of needed sources from `src/lib9`, `src/libthread` and 8 | `src/lib9pclient` directories to make it build correctly. 9 | 10 | 11 | Building 9pfuse 12 | --------------- 13 | 14 | As a bonus, [Meson](https://mesonbuild.com)-based build system tested to work 15 | under recent GNU/Linux sustems has been included: just run the usual `meson 16 | setup build && meson compile -Cbuild` incantation from the source directory. 17 | 18 | -------------------------------------------------------------------------------- /compat/lib9pclient/open.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include <9pclient.h> 5 | #include "fsimpl.h" 6 | 7 | int 8 | fsfopen(CFid *fid, int mode) 9 | { 10 | Fcall tx, rx; 11 | 12 | tx.type = Topen; 13 | tx.fid = fid->fid; 14 | tx.mode = mode; 15 | if(_fsrpc(fid->fs, &tx, &rx, 0) < 0) 16 | return -1; 17 | fid->mode = mode; 18 | return 0; 19 | } 20 | 21 | CFid* 22 | fsopen(CFsys *fs, char *name, int mode) 23 | { 24 | char e[ERRMAX]; 25 | CFid *fid; 26 | 27 | if((fid = fswalk(fs->root, name)) == nil) 28 | return nil; 29 | if(fsfopen(fid, mode) < 0){ 30 | rerrstr(e, sizeof e); 31 | fsclose(fid); 32 | errstr(e, sizeof e); 33 | return nil; 34 | } 35 | fid->mode = mode; 36 | return fid; 37 | } 38 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | The files in this directory are subject to the following license. 2 | 3 | The author of this software is Russ Cox. 4 | 5 | Copyright (c) 2006 Russ Cox 6 | 7 | Permission to use, copy, modify, and distribute this software for any 8 | purpose without fee is hereby granted, provided that this entire notice 9 | is included in all copies of any software which is or includes a copy 10 | or modification of this software and in all copies of the supporting 11 | documentation for such software. 12 | 13 | THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 14 | WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION OR WARRANTY 15 | OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS 16 | FITNESS FOR ANY PARTICULAR PURPOSE. 17 | 18 | -------------------------------------------------------------------------------- /compat/fmt/fmtprint.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 | #include 3 | #include 4 | #include "plan9.h" 5 | #include "fmt.h" 6 | #include "fmtdef.h" 7 | 8 | /* 9 | * format a string into the output buffer 10 | * designed for formats which themselves call fmt, 11 | * but ignore any width flags 12 | */ 13 | int 14 | fmtprint(Fmt *f, char *fmt, ...) 15 | { 16 | va_list va; 17 | int n; 18 | 19 | f->flags = 0; 20 | f->width = 0; 21 | f->prec = 0; 22 | VA_COPY(va, f->args); 23 | VA_END(f->args); 24 | va_start(f->args, fmt); 25 | n = dofmt(f, fmt); 26 | va_end(f->args); 27 | f->flags = 0; 28 | f->width = 0; 29 | f->prec = 0; 30 | VA_COPY(f->args,va); 31 | VA_END(va); 32 | if(n >= 0) 33 | return 0; 34 | return n; 35 | } 36 | -------------------------------------------------------------------------------- /compat/lib9pclient/close.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ 2 | /* See COPYRIGHT */ 3 | 4 | #include 5 | #include 6 | #include 7 | #include <9pclient.h> 8 | #include "fsimpl.h" 9 | 10 | static void 11 | fidclunk(CFid *fid) 12 | { 13 | Fcall tx, rx; 14 | 15 | tx.type = Tclunk; 16 | tx.fid = fid->fid; 17 | _fsrpc(fid->fs, &tx, &rx, 0); 18 | _fsputfid(fid); 19 | } 20 | 21 | void 22 | fsclose(CFid *fid) 23 | { 24 | if(fid == nil) 25 | return; 26 | 27 | /* maybe someday there will be a ref count */ 28 | fidclunk(fid); 29 | } 30 | 31 | int 32 | fsfremove(CFid *fid) 33 | { 34 | int n; 35 | Fcall tx, rx; 36 | 37 | tx.type = Tremove; 38 | tx.fid = fid->fid; 39 | n = _fsrpc(fid->fs, &tx, &rx, 0); 40 | _fsputfid(fid); 41 | return n; 42 | } 43 | -------------------------------------------------------------------------------- /compat/utf/LICENSE: -------------------------------------------------------------------------------- 1 | /* 2 | * The authors of this software are Rob Pike and Ken Thompson. 3 | * Copyright (c) 1998-2002 by Lucent Technologies. 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose without fee is hereby granted, provided that this entire notice 6 | * is included in all copies of any software which is or includes a copy 7 | * or modification of this software and in all copies of the supporting 8 | * documentation for such software. 9 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 10 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY 11 | * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY 12 | * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 13 | */ 14 | -------------------------------------------------------------------------------- /compat/utf/NOTICE: -------------------------------------------------------------------------------- 1 | /* 2 | * The authors of this software are Rob Pike and Ken Thompson. 3 | * Copyright (c) 1998-2002 by Lucent Technologies. 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose without fee is hereby granted, provided that this entire notice 6 | * is included in all copies of any software which is or includes a copy 7 | * or modification of this software and in all copies of the supporting 8 | * documentation for such software. 9 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 10 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY 11 | * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY 12 | * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 13 | */ 14 | -------------------------------------------------------------------------------- /compat/utf/README: -------------------------------------------------------------------------------- 1 | /* 2 | * The authors of this software are Rob Pike and Ken Thompson. 3 | * Copyright (c) 1998-2002 by Lucent Technologies. 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose without fee is hereby granted, provided that this entire notice 6 | * is included in all copies of any software which is or includes a copy 7 | * or modification of this software and in all copies of the supporting 8 | * documentation for such software. 9 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 10 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY 11 | * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY 12 | * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 13 | */ 14 | -------------------------------------------------------------------------------- /compat/fmt/fmtfd.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 | #include 3 | #include 4 | #include "plan9.h" 5 | #include "fmt.h" 6 | #include "fmtdef.h" 7 | 8 | /* 9 | * public routine for final flush of a formatting buffer 10 | * to a file descriptor; returns total char count. 11 | */ 12 | int 13 | fmtfdflush(Fmt *f) 14 | { 15 | if(__fmtFdFlush(f) <= 0) 16 | return -1; 17 | return f->nfmt; 18 | } 19 | 20 | /* 21 | * initialize an output buffer for buffered printing 22 | */ 23 | int 24 | fmtfdinit(Fmt *f, int fd, char *buf, int size) 25 | { 26 | f->runes = 0; 27 | f->start = buf; 28 | f->to = buf; 29 | f->stop = buf + size; 30 | f->flush = __fmtFdFlush; 31 | f->farg = (void*)(uintptr_t)fd; 32 | f->flags = 0; 33 | f->nfmt = 0; 34 | fmtlocaleinit(f, nil, nil, nil); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /compat/fmt/sprint.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 | #include 3 | #include 4 | #include "plan9.h" 5 | #include "fmt.h" 6 | #include "fmtdef.h" 7 | 8 | int 9 | sprint(char *buf, char *fmt, ...) 10 | { 11 | int n; 12 | uint len; 13 | va_list args; 14 | 15 | len = 1<<30; /* big number, but sprint is deprecated anyway */ 16 | /* 17 | * on PowerPC, the stack is near the top of memory, so 18 | * we must be sure not to overflow a 32-bit pointer. 19 | * 20 | * careful! gcc-4.2 assumes buf+len < buf can never be true and 21 | * optimizes the test away. casting to uintptr works around this bug. 22 | */ 23 | if((uintptr)buf+len < (uintptr)buf) 24 | len = -(uintptr)buf-1; 25 | 26 | va_start(args, fmt); 27 | n = vsnprint(buf, len, fmt, args); 28 | va_end(args); 29 | return n; 30 | } 31 | -------------------------------------------------------------------------------- /compat/fmt/plan9.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * compiler directive on Plan 9 5 | */ 6 | #ifndef USED 7 | #define USED(x) if(x);else 8 | #endif 9 | 10 | /* 11 | * easiest way to make sure these are defined 12 | */ 13 | #define uchar _fmtuchar 14 | #define ushort _fmtushort 15 | #define uint _fmtuint 16 | #define ulong _fmtulong 17 | #define vlong _fmtvlong 18 | #define uvlong _fmtuvlong 19 | #define uintptr _fmtuintptr 20 | 21 | typedef unsigned char uchar; 22 | typedef unsigned short ushort; 23 | typedef unsigned int uint; 24 | typedef unsigned long ulong; 25 | typedef unsigned long long uvlong; 26 | typedef long long vlong; 27 | typedef uintptr_t uintptr; 28 | 29 | /* 30 | * nil cannot be ((void*)0) on ANSI C, 31 | * because it is used for function pointers 32 | */ 33 | #undef nil 34 | #define nil 0 35 | 36 | #undef nelem 37 | #define nelem(x) (sizeof (x)/sizeof (x)[0]) 38 | -------------------------------------------------------------------------------- /compat/lib9pclient/seek.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include <9pclient.h> 5 | #include "fsimpl.h" 6 | 7 | vlong 8 | fsseek(CFid *fid, vlong n, int whence) 9 | { 10 | Dir *d; 11 | 12 | switch(whence){ 13 | case 0: 14 | qlock(&fid->lk); 15 | fid->offset = n; 16 | qunlock(&fid->lk); 17 | break; 18 | case 1: 19 | qlock(&fid->lk); 20 | n += fid->offset; 21 | if(n < 0){ 22 | qunlock(&fid->lk); 23 | werrstr("negative offset"); 24 | return -1; 25 | } 26 | fid->offset = n; 27 | qunlock(&fid->lk); 28 | break; 29 | case 2: 30 | if((d = fsdirfstat(fid)) == nil) 31 | return -1; 32 | n += d->length; 33 | if(n < 0){ 34 | werrstr("negative offset"); 35 | return -1; 36 | } 37 | qlock(&fid->lk); 38 | fid->offset = n; 39 | qunlock(&fid->lk); 40 | break; 41 | default: 42 | werrstr("bad whence in fsseek"); 43 | return -1; 44 | } 45 | return n; 46 | } 47 | -------------------------------------------------------------------------------- /compat/fmt/NOTICE: -------------------------------------------------------------------------------- 1 | /* 2 | * The authors of this software are Rob Pike and Ken Thompson. 3 | * Copyright (c) 2002 by Lucent Technologies. 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose without fee is hereby granted, provided that this entire notice 6 | * is included in all copies of any software which is or includes a copy 7 | * or modification of this software and in all copies of the supporting 8 | * documentation for such software. 9 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 10 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY 11 | * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY 12 | * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 13 | */ 14 | 15 | This is a Unix port of the Plan 9 formatted I/O package. 16 | 17 | Please send comments about the packaging 18 | to Russ Cox . 19 | 20 | -------------------------------------------------------------------------------- /compat/fmt/README: -------------------------------------------------------------------------------- 1 | /* 2 | * The authors of this software are Rob Pike and Ken Thompson. 3 | * Copyright (c) 2002 by Lucent Technologies. 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose without fee is hereby granted, provided that this entire notice 6 | * is included in all copies of any software which is or includes a copy 7 | * or modification of this software and in all copies of the supporting 8 | * documentation for such software. 9 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 10 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY 11 | * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY 12 | * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 13 | */ 14 | 15 | This is a Unix port of the Plan 9 formatted I/O package. 16 | 17 | Please send comments about the packaging 18 | to Russ Cox . 19 | 20 | -------------------------------------------------------------------------------- /compat/lib9pclient/fsimpl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ 2 | /* See COPYRIGHT */ 3 | 4 | #include 5 | 6 | typedef struct Queue Queue; 7 | Queue *_fsqalloc(void); 8 | int _fsqsend(Queue*, void*); 9 | void *_fsqrecv(Queue*); 10 | void _fsqhangup(Queue*); 11 | void *_fsnbqrecv(Queue*); 12 | 13 | #include 14 | struct CFsys 15 | { 16 | char version[20]; 17 | int msize; 18 | QLock lk; 19 | int fd; 20 | int ref; 21 | Mux mux; 22 | CFid *root; 23 | Queue *txq; 24 | Queue *rxq; 25 | CFid *freefid; 26 | int nextfid; 27 | Ioproc *iorecv; 28 | Ioproc *iosend; 29 | }; 30 | 31 | struct CFid 32 | { 33 | int fid; 34 | int mode; 35 | CFid *next; 36 | QLock lk; 37 | CFsys *fs; 38 | Qid qid; 39 | vlong offset; 40 | }; 41 | 42 | void _fsdecref(CFsys*); 43 | void _fsputfid(CFid*); 44 | CFid *_fsgetfid(CFsys*); 45 | 46 | int _fsrpc(CFsys*, Fcall*, Fcall*, void**); 47 | CFid *_fswalk(CFid*, char*); 48 | -------------------------------------------------------------------------------- /compat/lib9pclient/wstat.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ 2 | /* See COPYRIGHT */ 3 | 4 | #include 5 | #include 6 | #include 7 | #include <9pclient.h> 8 | #include "fsimpl.h" 9 | 10 | int 11 | fsdirwstat(CFsys *fs, char *name, Dir *d) 12 | { 13 | int n; 14 | CFid *fid; 15 | 16 | if((fid = fswalk(fs->root, name)) == nil) 17 | return -1; 18 | 19 | n = fsdirfwstat(fid, d); 20 | fsclose(fid); 21 | return n; 22 | } 23 | 24 | int 25 | fsdirfwstat(CFid *fid, Dir *d) 26 | { 27 | uchar *a; 28 | int n, nn; 29 | Fcall tx, rx; 30 | 31 | n = sizeD2M(d); 32 | a = malloc(n); 33 | if(a == nil) 34 | return -1; 35 | nn = convD2M(d, a, n); 36 | if(n != nn){ 37 | werrstr("convD2M and sizeD2M disagree"); 38 | free(a); 39 | return -1; 40 | } 41 | 42 | tx.type = Twstat; 43 | tx.fid = fid->fid; 44 | tx.stat = a; 45 | tx.nstat = n; 46 | n = _fsrpc(fid->fs, &tx, &rx, 0); 47 | free(a); 48 | return n; 49 | } 50 | -------------------------------------------------------------------------------- /compat/lib9/atexit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define NEXIT 33 5 | 6 | static Lock onexlock; 7 | static struct 8 | { 9 | void (*f)(void); 10 | int pid; 11 | }onex[NEXIT]; 12 | 13 | int 14 | atexit(void (*f)(void)) 15 | { 16 | int i; 17 | 18 | lock(&onexlock); 19 | for(i=0; i= 0; i--) 49 | if((f = onex[i].f) && pid == onex[i].pid) { 50 | onex[i].f = 0; 51 | (*f)(); 52 | } 53 | if(s == 0 || *s == 0) 54 | exit(0); 55 | exit(exitcode(s)); 56 | } 57 | -------------------------------------------------------------------------------- /compat/lib9pclient/create.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include <9pclient.h> 5 | #include "fsimpl.h" 6 | 7 | int 8 | fsfcreate(CFid *fid, char *name, int mode, ulong perm) 9 | { 10 | Fcall tx, rx; 11 | 12 | tx.type = Tcreate; 13 | tx.name = name; 14 | tx.fid = fid->fid; 15 | tx.mode = mode; 16 | tx.perm = perm; 17 | tx.extension = nil; 18 | if(_fsrpc(fid->fs, &tx, &rx, 0) < 0) 19 | return -1; 20 | fid->mode = mode; 21 | return 0; 22 | } 23 | 24 | CFid* 25 | fscreate(CFsys *fs, char *name, int mode, ulong perm) 26 | { 27 | CFid *fid; 28 | char *p, *dir, *elem; 29 | 30 | p = strrchr(name, '/'); 31 | if(p == nil){ 32 | dir = ""; 33 | elem = name; 34 | }else{ 35 | dir = name; 36 | *p = 0; 37 | elem = p+1; 38 | } 39 | 40 | if((fid = fswalk(fs->root, dir)) == nil){ 41 | if(p) 42 | *p = '/'; 43 | return nil; 44 | } 45 | if(p) 46 | *p = '/'; 47 | if(fsfcreate(fid, elem, mode, perm) < 0){ 48 | fsclose(fid); 49 | return nil; 50 | } 51 | return fid; 52 | } 53 | -------------------------------------------------------------------------------- /compat/lib9/atnotify.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define NFN 33 5 | static int (*onnot[NFN])(void*, char*); 6 | static Lock onnotlock; 7 | 8 | static 9 | void 10 | notifier(void *v, char *s) 11 | { 12 | int i; 13 | 14 | for(i=0; i 5 | #include 6 | #include 7 | #include <9pclient.h> 8 | #include "fsimpl.h" 9 | 10 | Dir* 11 | fsdirstat(CFsys *fs, char *name) 12 | { 13 | Dir *d; 14 | CFid *fid; 15 | 16 | if((fid = fswalk(fs->root, name)) == nil) 17 | return nil; 18 | 19 | d = fsdirfstat(fid); 20 | fsclose(fid); 21 | return d; 22 | } 23 | 24 | Dir* 25 | fsdirfstat(CFid *fid) 26 | { 27 | Dir *d; 28 | CFsys *fs; 29 | Fcall tx, rx; 30 | void *freep; 31 | int n; 32 | 33 | fs = fid->fs; 34 | tx.type = Tstat; 35 | tx.fid = fid->fid; 36 | 37 | if(_fsrpc(fs, &tx, &rx, &freep) < 0) 38 | return nil; 39 | 40 | d = malloc(sizeof(Dir)+rx.nstat); 41 | if(d == nil){ 42 | free(freep); 43 | return nil; 44 | } 45 | n = convM2D(rx.stat, rx.nstat, d, (char*)&d[1]); 46 | free(freep); 47 | if(n != rx.nstat){ 48 | free(d); 49 | werrstr("rx.nstat and convM2D disagree about dir length"); 50 | return nil; 51 | } 52 | return d; 53 | } 54 | -------------------------------------------------------------------------------- /compat/fmt/LICENSE: -------------------------------------------------------------------------------- 1 | /* 2 | * The authors of this software are Rob Pike and Ken Thompson, 3 | * with contributions from Mike Burrows and Sean Dorward. 4 | * 5 | * Copyright (c) 2002-2006 by Lucent Technologies. 6 | * Portions Copyright (c) 2004 Google Inc. 7 | * 8 | * Permission to use, copy, modify, and distribute this software for any 9 | * purpose without fee is hereby granted, provided that this entire notice 10 | * is included in all copies of any software which is or includes a copy 11 | * or modification of this software and in all copies of the supporting 12 | * documentation for such software. 13 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 14 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 15 | * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 16 | * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 17 | */ 18 | 19 | This is a Unix port of the Plan 9 formatted I/O package. 20 | 21 | Please send comments about the packaging to Russ Cox . 22 | 23 | -------------------------------------------------------------------------------- /compat/lib9/sleep.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define NOPLAN9DEFINES 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #if defined(__NetBSD__) || (defined(__OpenBSD__) && OpenBSD <= 200611) 9 | #if !defined(sched_yield) 10 | # define sched_yield() \ 11 | do{ struct timespec ts; \ 12 | ts.tv_sec = 0; \ 13 | ts.tv_nsec = 0; \ 14 | nanosleep(&ts, 0); \ 15 | }while(0) 16 | #endif 17 | #endif 18 | 19 | int 20 | p9sleep(long milli) 21 | { 22 | struct timeval tv; 23 | 24 | if(milli == 0){ 25 | sched_yield(); 26 | return 0; 27 | } 28 | 29 | tv.tv_sec = milli/1000; 30 | tv.tv_usec = (milli%1000)*1000; 31 | return select(0, 0, 0, 0, &tv); 32 | } 33 | 34 | long 35 | p9alarm(ulong milli) 36 | { 37 | struct itimerval itv; 38 | struct itimerval oitv; 39 | 40 | itv.it_interval.tv_sec = 0; 41 | itv.it_interval.tv_usec = 0; 42 | itv.it_value.tv_sec = milli/1000; 43 | itv.it_value.tv_usec = (milli%1000)*1000; 44 | if(setitimer(ITIMER_REAL, &itv, &oitv) < 0) 45 | return -1; 46 | return oitv.it_value.tv_sec*1000+oitv.it_value.tv_usec/1000; 47 | } 48 | -------------------------------------------------------------------------------- /compat/utf/utflen.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The authors of this software are Rob Pike and Ken Thompson. 3 | * Copyright (c) 2002 by Lucent Technologies. 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose without fee is hereby granted, provided that this entire notice 6 | * is included in all copies of any software which is or includes a copy 7 | * or modification of this software and in all copies of the supporting 8 | * documentation for such software. 9 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 10 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE 11 | * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY 12 | * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 13 | */ 14 | #include 15 | #include 16 | #include "plan9.h" 17 | #include "utf.h" 18 | 19 | int 20 | utflen(char *s) 21 | { 22 | int c; 23 | long n; 24 | Rune rune; 25 | 26 | n = 0; 27 | for(;;) { 28 | c = *(uchar*)s; 29 | if(c < Runeself) { 30 | if(c == 0) 31 | return n; 32 | s++; 33 | } else 34 | s += chartorune(&rune, s); 35 | n++; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /compat/lib9/dirmodefmt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static char *modes[] = 5 | { 6 | "---", 7 | "--x", 8 | "-w-", 9 | "-wx", 10 | "r--", 11 | "r-x", 12 | "rw-", 13 | "rwx", 14 | }; 15 | 16 | static void 17 | rwx(long m, char *s) 18 | { 19 | strncpy(s, modes[m], 3); 20 | } 21 | 22 | int 23 | dirmodefmt(Fmt *f) 24 | { 25 | static char buf[16]; 26 | ulong m; 27 | 28 | m = va_arg(f->args, ulong); 29 | 30 | if(m & DMDIR) 31 | buf[0]='d'; 32 | else if(m & DMAPPEND) 33 | buf[0]='a'; 34 | else if(m & DMAUTH) 35 | buf[0]='A'; 36 | else if(m & DMDEVICE) 37 | buf[0] = 'D'; 38 | else if(m & DMSOCKET) 39 | buf[0] = 'S'; 40 | else if(m & DMNAMEDPIPE) 41 | buf[0] = 'P'; 42 | else 43 | buf[0]='-'; 44 | 45 | /* 46 | * It's a little weird to have DMSYMLINK conflict with DMEXCL 47 | * here, but since you can have symlinks to any of the above 48 | * things, this is a better display. Especially since we don't do 49 | * DMEXCL on any of the supported systems. 50 | */ 51 | if(m & DMEXCL) 52 | buf[1]='l'; 53 | else if(m & DMSYMLINK) 54 | buf[1] = 'L'; 55 | else 56 | buf[1]='-'; 57 | rwx((m>>6)&7, buf+2); 58 | rwx((m>>3)&7, buf+5); 59 | rwx((m>>0)&7, buf+8); 60 | buf[11] = 0; 61 | return fmtstrcpy(f, buf); 62 | } 63 | -------------------------------------------------------------------------------- /compat/utf/utfnlen.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The authors of this software are Rob Pike and Ken Thompson. 3 | * Copyright (c) 2002 by Lucent Technologies. 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose without fee is hereby granted, provided that this entire notice 6 | * is included in all copies of any software which is or includes a copy 7 | * or modification of this software and in all copies of the supporting 8 | * documentation for such software. 9 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 10 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE 11 | * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY 12 | * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 13 | */ 14 | #include 15 | #include 16 | #include "plan9.h" 17 | #include "utf.h" 18 | 19 | int 20 | utfnlen(char *s, long m) 21 | { 22 | int c; 23 | long n; 24 | Rune rune; 25 | char *es; 26 | 27 | es = s + m; 28 | for(n = 0; s < es; n++) { 29 | c = *(uchar*)s; 30 | if(c < Runeself){ 31 | if(c == '\0') 32 | break; 33 | s++; 34 | continue; 35 | } 36 | if(!fullrune(s, es-s)) 37 | break; 38 | s += chartorune(&rune, s); 39 | } 40 | return n; 41 | } 42 | -------------------------------------------------------------------------------- /9pfuse.4: -------------------------------------------------------------------------------- 1 | .TH 9PFUSE 4 2 | .SH NAME 3 | 9pfuse \- mount 9P service via FUSE 4 | .SH SYNOPSIS 5 | .B 9pfuse 6 | [ 7 | .B -D 8 | ] 9 | [ 10 | .B -A 11 | .I t 12 | ] 13 | [ 14 | .B -a 15 | .I aname 16 | ] 17 | .I addr 18 | .I mtpt 19 | .SH DESCRIPTION 20 | .I 9pfuse 21 | mounts the 9P service running at 22 | .I addr 23 | onto 24 | .I mtpt 25 | using the FUSE user-level file system driver. 26 | .PP 27 | .I 9pfuse 28 | sets up the initial mount and then forks itself 29 | into the background, where it serves the FUSE 30 | protocol, translating the requests into 9P. 31 | .PP 32 | The options are: 33 | .TP 34 | .B -D 35 | Print each FUSE and 9P message to standard error. 36 | .TP 37 | .B -a\fI aname 38 | Use 39 | .I aname 40 | as the attach name. 41 | .TP 42 | .B -A\fI t 43 | Set the kernel cache timeout for attribute information 44 | to 45 | .I t 46 | (default 1.0) seconds. 47 | .PD 48 | .PP 49 | The 50 | .I fusermount 51 | binary must exist in the current search path. 52 | .PP 53 | FUSE is available for Linux 2.4.21 and later, 54 | Linux 2.6, and FreeBSD 6.x and later. 55 | .SH SEE ALSO 56 | FUSE Homepage, 57 | .HR http://fuse.sourceforge.net 58 | .PP 59 | FUSE for FreeBSD, 60 | .HR http://fuse4bsd.creo.hu 61 | .PP 62 | MacFUSE, 63 | .HR http://code.google.com/p/macfuse 64 | .SH SOURCE 65 | .B \*9/src/cmd/9pfuse 66 | -------------------------------------------------------------------------------- /compat/utf/utfecpy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The authors of this software are Rob Pike and Ken Thompson. 3 | * Copyright (c) 2002 by Lucent Technologies. 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose without fee is hereby granted, provided that this entire notice 6 | * is included in all copies of any software which is or includes a copy 7 | * or modification of this software and in all copies of the supporting 8 | * documentation for such software. 9 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 10 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE 11 | * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY 12 | * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 13 | */ 14 | #define _BSD_SOURCE 1 /* memccpy */ 15 | #define _DEFAULT_SOURCE 1 16 | #include 17 | #include 18 | #include "plan9.h" 19 | #include "utf.h" 20 | 21 | char* 22 | utfecpy(char *to, char *e, char *from) 23 | { 24 | char *end; 25 | 26 | if(to >= e) 27 | return to; 28 | end = memccpy(to, from, '\0', e - to); 29 | if(end == nil){ 30 | end = e-1; 31 | while(end>to && (*--end&0xC0)==0x80) 32 | ; 33 | *end = '\0'; 34 | }else{ 35 | end--; 36 | } 37 | return end; 38 | } 39 | -------------------------------------------------------------------------------- /compat/libmux/COPYRIGHT: -------------------------------------------------------------------------------- 1 | 2 | This software was developed as part of a project at MIT: 3 | /sys/src/libmux/* 4 | /sys/include/mux.h 5 | 6 | Copyright (c) 2003 Russ Cox, 7 | Massachusetts Institute of Technology 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining 10 | a copy of this software and associated documentation files (the 11 | "Software"), to deal in the Software without restriction, including 12 | without limitation the rights to use, copy, modify, merge, publish, 13 | distribute, sublicense, and/or sell copies of the Software, and to 14 | permit persons to whom the Software is furnished to do so, subject to 15 | the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be 18 | included in all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | -------------------------------------------------------------------------------- /compat/lib9pclient/COPYRIGHT: -------------------------------------------------------------------------------- 1 | 2 | This software was developed as part of a project at MIT: 3 | /sys/src/lib9pclient/* except dirread.c 4 | /sys/include/fs.h 5 | 6 | Copyright (c) 2003 Russ Cox, 7 | Massachusetts Institute of Technology 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining 10 | a copy of this software and associated documentation files (the 11 | "Software"), to deal in the Software without restriction, including 12 | without limitation the rights to use, copy, modify, merge, publish, 13 | distribute, sublicense, and/or sell copies of the Software, and to 14 | permit persons to whom the Software is furnished to do so, subject to 15 | the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be 18 | included in all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | -------------------------------------------------------------------------------- /compat/utf/utfrune.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The authors of this software are Rob Pike and Ken Thompson. 3 | * Copyright (c) 2002 by Lucent Technologies. 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose without fee is hereby granted, provided that this entire notice 6 | * is included in all copies of any software which is or includes a copy 7 | * or modification of this software and in all copies of the supporting 8 | * documentation for such software. 9 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 10 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE 11 | * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY 12 | * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 13 | */ 14 | #include 15 | #include 16 | #include "plan9.h" 17 | #include "utf.h" 18 | 19 | char* 20 | utfrune(char *s, long c) 21 | { 22 | long c1; 23 | Rune r; 24 | int n; 25 | 26 | if(c < Runesync) /* not part of utf sequence */ 27 | return strchr(s, c); 28 | 29 | for(;;) { 30 | c1 = *(uchar*)s; 31 | if(c1 < Runeself) { /* one byte rune */ 32 | if(c1 == 0) 33 | return 0; 34 | if(c1 == c) 35 | return s; 36 | s++; 37 | continue; 38 | } 39 | n = chartorune(&r, s); 40 | if(r == c) 41 | return s; 42 | s += n; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /a.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include <9pclient.h> 11 | 12 | #if defined(__APPLE__) 13 | #define __FreeBSD__ 10 14 | #endif 15 | 16 | #include "fuse_kernel.h" 17 | 18 | /* Somehow the FUSE guys forgot to define this one! */ 19 | struct fuse_create_out { 20 | struct fuse_entry_out e; 21 | struct fuse_open_out o; 22 | }; 23 | 24 | typedef struct FuseMsg FuseMsg; 25 | struct FuseMsg 26 | { 27 | FuseMsg *next; 28 | uchar *buf; 29 | int nbuf; 30 | struct fuse_in_header *hdr; /* = buf */ 31 | void *tx; /* = hdr+1 */ 32 | }; 33 | 34 | extern int debug; 35 | 36 | extern int fusefd; 37 | extern int fuseeof; 38 | extern int fusebufsize; 39 | extern int fusemaxwrite; 40 | extern FuseMsg *fusemsglist; 41 | extern char *fusemtpt; 42 | 43 | void freefusemsg(FuseMsg *m); 44 | int fusefmt(Fmt*); 45 | void initfuse(char *mtpt); 46 | void waitfuse(void); 47 | FuseMsg* readfusemsg(void); 48 | void replyfuse(FuseMsg *m, void *arg, int narg); 49 | void replyfuseerrno(FuseMsg *m, int e); 50 | void replyfuseerrstr(FuseMsg*); 51 | void request9p(Fcall *tx); 52 | 53 | void* emalloc(uint n); 54 | void* erealloc(void *p, uint n); 55 | char* estrdup(char *p); 56 | 57 | int errstr2errno(void); 58 | void unmountatexit(void); 59 | -------------------------------------------------------------------------------- /compat/lib9/netmkaddr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 6 | * make an address, add the defaults 7 | */ 8 | char * 9 | netmkaddr(char *linear, char *defnet, char *defsrv) 10 | { 11 | static char addr[256]; 12 | char *cp; 13 | 14 | /* 15 | * dump network name 16 | */ 17 | cp = strchr(linear, '!'); 18 | if(cp == 0){ 19 | if(defnet == 0) 20 | defnet = "net"; 21 | /* allow unix sockets to omit unix! prefix */ 22 | if(access(linear, 0) >= 0){ 23 | snprint(addr, sizeof(addr), "unix!%s", linear); 24 | return addr; 25 | } 26 | /* allow host:service in deference to Unix convention */ 27 | if((cp = strchr(linear, ':')) != nil){ 28 | snprint(addr, sizeof(addr), "%s!%.*s!%s", 29 | defnet, utfnlen(linear, cp-linear), 30 | linear, cp+1); 31 | return addr; 32 | } 33 | if(defsrv) 34 | snprint(addr, sizeof(addr), "%s!%s!%s", 35 | defnet, linear, defsrv); 36 | else 37 | snprint(addr, sizeof(addr), "%s!%s", defnet, linear); 38 | return addr; 39 | } 40 | 41 | /* 42 | * if there is already a service, use it 43 | */ 44 | cp = strchr(cp+1, '!'); 45 | if(cp) 46 | return linear; 47 | 48 | /* 49 | * if the network is unix, no service 50 | */ 51 | if(strncmp(linear, "unix!", 5) == 0) 52 | return linear; 53 | 54 | /* 55 | * add default service 56 | */ 57 | if(defsrv == 0) 58 | return linear; 59 | 60 | snprint(addr, sizeof(addr), "%s!%s", linear, defsrv); 61 | return addr; 62 | } 63 | -------------------------------------------------------------------------------- /compat/lrand.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | * algorithm by 6 | * D. P. Mitchell & J. A. Reeds 7 | */ 8 | 9 | #define LEN 607 10 | #define TAP 273 11 | #define MASK 0x7fffffffL 12 | #define A 48271 13 | #define M 2147483647 14 | #define Q 44488 15 | #define R 3399 16 | #define NORM (1.0/(1.0+MASK)) 17 | 18 | static ulong rng_vec[LEN]; 19 | static ulong* rng_tap = rng_vec; 20 | static ulong* rng_feed = 0; 21 | static Lock lk; 22 | 23 | static void 24 | isrand(long seed) 25 | { 26 | long lo, hi, x; 27 | int i; 28 | 29 | rng_tap = rng_vec; 30 | rng_feed = rng_vec+LEN-TAP; 31 | seed = seed%M; 32 | if(seed < 0) 33 | seed += M; 34 | if(seed == 0) 35 | seed = 89482311; 36 | x = seed; 37 | /* 38 | * Initialize by x[n+1] = 48271 * x[n] mod (2**31 - 1) 39 | */ 40 | for(i = -20; i < LEN; i++) { 41 | hi = x / Q; 42 | lo = x % Q; 43 | x = A*lo - R*hi; 44 | if(x < 0) 45 | x += M; 46 | if(i >= 0) 47 | rng_vec[i] = x; 48 | } 49 | } 50 | 51 | void 52 | p9srand(long seed) 53 | { 54 | lock(&lk); 55 | isrand(seed); 56 | unlock(&lk); 57 | } 58 | 59 | long 60 | p9lrand(void) 61 | { 62 | ulong x; 63 | 64 | lock(&lk); 65 | 66 | rng_tap--; 67 | if(rng_tap < rng_vec) { 68 | if(rng_feed == 0) { 69 | isrand(1); 70 | rng_tap--; 71 | } 72 | rng_tap += LEN; 73 | } 74 | rng_feed--; 75 | if(rng_feed < rng_vec) 76 | rng_feed += LEN; 77 | x = (*rng_feed + *rng_tap) & MASK; 78 | *rng_feed = x; 79 | 80 | unlock(&lk); 81 | 82 | return x; 83 | } 84 | -------------------------------------------------------------------------------- /compat/lib9pclient/read.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ 2 | /* See COPYRIGHT */ 3 | 4 | #include 5 | #include 6 | #include 7 | #include <9pclient.h> 8 | #include "fsimpl.h" 9 | 10 | long 11 | fspread(CFid *fid, void *buf, long n, vlong offset) 12 | { 13 | Fcall tx, rx; 14 | void *freep; 15 | uint msize; 16 | long nr; 17 | 18 | msize = fid->fs->msize - IOHDRSZ; 19 | if(n > msize) 20 | n = msize; 21 | tx.type = Tread; 22 | tx.fid = fid->fid; 23 | if(offset == -1){ 24 | qlock(&fid->lk); 25 | tx.offset = fid->offset; 26 | qunlock(&fid->lk); 27 | }else 28 | tx.offset = offset; 29 | tx.count = n; 30 | 31 | if(_fsrpc(fid->fs, &tx, &rx, &freep) < 0) 32 | return -1; 33 | if(rx.type == Rerror){ 34 | werrstr("%s", rx.ename); 35 | free(freep); 36 | return -1; 37 | } 38 | nr = rx.count; 39 | if(nr > n) 40 | nr = n; 41 | 42 | if(nr){ 43 | memmove(buf, rx.data, nr); 44 | if(offset == -1){ 45 | qlock(&fid->lk); 46 | fid->offset += nr; 47 | qunlock(&fid->lk); 48 | } 49 | } 50 | free(freep); 51 | 52 | return nr; 53 | } 54 | 55 | long 56 | fsread(CFid *fid, void *buf, long n) 57 | { 58 | return fspread(fid, buf, n, -1); 59 | } 60 | 61 | long 62 | fsreadn(CFid *fid, void *buf, long n) 63 | { 64 | long tot, nn; 65 | 66 | for(tot=0; tot 4 | #include 5 | #include "plan9.h" 6 | #include "fmt.h" 7 | #include "fmtdef.h" 8 | 9 | /* 10 | * Fill in the internationalization stuff in the State structure. 11 | * For nil arguments, provide the sensible defaults: 12 | * decimal is a period 13 | * thousands separator is a comma 14 | * thousands are marked every three digits 15 | */ 16 | void 17 | fmtlocaleinit(Fmt *f, char *decimal, char *thousands, char *grouping) 18 | { 19 | if(decimal == nil || decimal[0] == '\0') 20 | decimal = "."; 21 | if(thousands == nil) 22 | thousands = ","; 23 | if(grouping == nil) 24 | grouping = "\3"; 25 | f->decimal = decimal; 26 | f->thousands = thousands; 27 | f->grouping = grouping; 28 | } 29 | 30 | /* 31 | * We are about to emit a digit in e.g. %'d. If that digit would 32 | * overflow a thousands (e.g.) grouping, tell the caller to emit 33 | * the thousands separator. Always advance the digit counter 34 | * and pointer into the grouping descriptor. 35 | */ 36 | int 37 | __needsep(int *ndig, char **grouping) 38 | { 39 | int group; 40 | 41 | (*ndig)++; 42 | group = *(unsigned char*)*grouping; 43 | /* CHAR_MAX means no further grouping. \0 means we got the empty string */ 44 | if(group == 0xFF || group == 0x7f || group == 0x00) 45 | return 0; 46 | if(*ndig > group){ 47 | /* if we're at end of string, continue with this grouping; else advance */ 48 | if((*grouping)[1] != '\0') 49 | (*grouping)++; 50 | *ndig = 1; 51 | return 1; 52 | } 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /compat/mux.h: -------------------------------------------------------------------------------- 1 | #ifndef _MUX_H_ 2 | #define _MUX_H_ 1 3 | #if defined(__cplusplus) 4 | extern "C" { 5 | #endif 6 | 7 | AUTOLIB(mux) 8 | 9 | typedef struct Mux Mux; 10 | typedef struct Muxrpc Muxrpc; 11 | typedef struct Muxqueue Muxqueue; 12 | 13 | struct Muxrpc 14 | { 15 | Mux *mux; 16 | Muxrpc *next; 17 | Muxrpc *prev; 18 | Rendez r; 19 | uint tag; 20 | void *p; 21 | int waiting; 22 | int async; 23 | }; 24 | 25 | struct Mux 26 | { 27 | uint mintag; /* to be filled by client */ 28 | uint maxtag; 29 | int (*send)(Mux*, void*); 30 | void *(*recv)(Mux*); 31 | int (*nbrecv)(Mux*, void**); 32 | int (*gettag)(Mux*, void*); 33 | int (*settag)(Mux*, void*, uint); 34 | void *aux; /* for private use by client */ 35 | 36 | /* private */ 37 | QLock lk; /* must be first for muxinit */ 38 | QLock inlk; 39 | QLock outlk; 40 | Rendez tagrend; 41 | Rendez rpcfork; 42 | Muxqueue *readq; 43 | Muxqueue *writeq; 44 | uint nwait; 45 | uint mwait; 46 | uint freetag; 47 | Muxrpc **wait; 48 | Muxrpc *muxer; 49 | Muxrpc sleep; 50 | }; 51 | 52 | void muxinit(Mux*); 53 | void* muxrpc(Mux*, void*); 54 | void muxprocs(Mux*); 55 | Muxrpc* muxrpcstart(Mux*, void*); 56 | int muxrpccanfinish(Muxrpc*, void**); 57 | 58 | /* private */ 59 | int _muxsend(Mux*, void*); 60 | int _muxrecv(Mux*, int, void**); 61 | void _muxsendproc(void*); 62 | void _muxrecvproc(void*); 63 | Muxqueue *_muxqalloc(void); 64 | int _muxqsend(Muxqueue*, void*); 65 | void *_muxqrecv(Muxqueue*); 66 | void _muxqhangup(Muxqueue*); 67 | int _muxnbqrecv(Muxqueue*, void**); 68 | 69 | #if defined(__cplusplus) 70 | } 71 | #endif 72 | #endif 73 | -------------------------------------------------------------------------------- /compat/lib9pclient/write.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ 2 | /* See COPYRIGHT */ 3 | 4 | #include 5 | #include 6 | #include 7 | #include <9pclient.h> 8 | #include "fsimpl.h" 9 | 10 | static long 11 | _fspwrite(CFid *fid, void *buf, long n, vlong offset) 12 | { 13 | Fcall tx, rx; 14 | void *freep; 15 | 16 | tx.type = Twrite; 17 | tx.fid = fid->fid; 18 | if(offset == -1){ 19 | qlock(&fid->lk); 20 | tx.offset = fid->offset; 21 | qunlock(&fid->lk); 22 | }else 23 | tx.offset = offset; 24 | tx.count = n; 25 | tx.data = buf; 26 | 27 | if(_fsrpc(fid->fs, &tx, &rx, &freep) < 0) 28 | return -1; 29 | if(rx.type == Rerror){ 30 | werrstr("%s", rx.ename); 31 | free(freep); 32 | return -1; 33 | } 34 | if(offset == -1 && rx.count){ 35 | qlock(&fid->lk); 36 | fid->offset += rx.count; 37 | qunlock(&fid->lk); 38 | } 39 | free(freep); 40 | return rx.count; 41 | } 42 | 43 | long 44 | fspwrite(CFid *fid, void *buf, long n, vlong offset) 45 | { 46 | long tot, want, got, first; 47 | uint msize; 48 | 49 | msize = fid->fs->msize - IOHDRSZ; 50 | tot = 0; 51 | first = 1; 52 | while(tot < n || first){ 53 | want = n - tot; 54 | if(want > msize) 55 | want = msize; 56 | got = _fspwrite(fid, (char*)buf+tot, want, offset); 57 | first = 0; 58 | if(got < 0){ 59 | if(tot == 0) 60 | return got; 61 | break; 62 | } 63 | tot += got; 64 | if(offset != -1) 65 | offset += got; 66 | } 67 | return tot; 68 | } 69 | 70 | long 71 | fswrite(CFid *fid, void *buf, long n) 72 | { 73 | return fspwrite(fid, buf, n, -1); 74 | } 75 | -------------------------------------------------------------------------------- /compat/fmt/nan64.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 | 3 | /* 4 | * 64-bit IEEE not-a-number routines. 5 | * This is big/little-endian portable assuming that 6 | * the 64-bit doubles and 64-bit integers have the 7 | * same byte ordering. 8 | */ 9 | 10 | #include "plan9.h" 11 | #include 12 | #include "fmt.h" 13 | #include "fmtdef.h" 14 | 15 | static uvlong uvnan = ((uvlong)0x7FF00000<<32)|0x00000001; 16 | static uvlong uvinf = ((uvlong)0x7FF00000<<32)|0x00000000; 17 | static uvlong uvneginf = ((uvlong)0xFFF00000<<32)|0x00000000; 18 | 19 | /* gcc sees through the obvious casts. */ 20 | static uvlong 21 | d2u(double d) 22 | { 23 | union { 24 | uvlong v; 25 | double d; 26 | } u; 27 | assert(sizeof(u.d) == sizeof(u.v)); 28 | u.d = d; 29 | return u.v; 30 | } 31 | 32 | static double 33 | u2d(uvlong v) 34 | { 35 | union { 36 | uvlong v; 37 | double d; 38 | } u; 39 | assert(sizeof(u.d) == sizeof(u.v)); 40 | u.v = v; 41 | return u.d; 42 | } 43 | 44 | double 45 | __NaN(void) 46 | { 47 | return u2d(uvnan); 48 | } 49 | 50 | int 51 | __isNaN(double d) 52 | { 53 | uvlong x; 54 | 55 | x = d2u(d); 56 | /* IEEE 754: exponent bits 0x7FF and non-zero mantissa */ 57 | return (x&uvinf) == uvinf && (x&~uvneginf) != 0; 58 | } 59 | 60 | double 61 | __Inf(int sign) 62 | { 63 | return u2d(sign < 0 ? uvneginf : uvinf); 64 | } 65 | 66 | int 67 | __isInf(double d, int sign) 68 | { 69 | uvlong x; 70 | 71 | x = d2u(d); 72 | if(sign == 0) 73 | return x==uvinf || x==uvneginf; 74 | else if(sign > 0) 75 | return x==uvinf; 76 | else 77 | return x==uvneginf; 78 | } 79 | -------------------------------------------------------------------------------- /compat/lib9pclient/walk.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ 2 | /* See COPYRIGHT */ 3 | 4 | #include 5 | #include 6 | #include 7 | #include <9pclient.h> 8 | #include "fsimpl.h" 9 | 10 | CFid* 11 | fswalk(CFid *fid, char *oname) 12 | { 13 | char *freep, *name; 14 | int i, nwalk; 15 | char *p; 16 | CFid *wfid; 17 | Fcall tx, rx; 18 | 19 | freep = nil; 20 | name = oname; 21 | if(name){ 22 | freep = malloc(strlen(name)+1); 23 | if(freep == nil) 24 | return nil; 25 | strcpy(freep, name); 26 | name = freep; 27 | } 28 | 29 | if((wfid = _fsgetfid(fid->fs)) == nil){ 30 | free(freep); 31 | return nil; 32 | } 33 | 34 | nwalk = 0; 35 | do{ 36 | /* collect names */ 37 | for(i=0; name && *name && i < MAXWELEM; ){ 38 | p = name; 39 | name = strchr(name, '/'); 40 | if(name) 41 | *name++ = 0; 42 | if(*p == 0 || (*p == '.' && *(p+1) == 0)) 43 | continue; 44 | tx.wname[i++] = p; 45 | } 46 | 47 | /* do a walk */ 48 | tx.type = Twalk; 49 | tx.fid = nwalk ? wfid->fid : fid->fid; 50 | tx.newfid = wfid->fid; 51 | tx.nwname = i; 52 | if(_fsrpc(fid->fs, &tx, &rx, 0) < 0){ 53 | Error: 54 | free(freep); 55 | if(nwalk) 56 | fsclose(wfid); 57 | else 58 | _fsputfid(wfid); 59 | return nil; 60 | } 61 | if(rx.nwqid != tx.nwname){ 62 | /* XXX lame error */ 63 | werrstr("file '%s' not found", oname); 64 | goto Error; 65 | } 66 | if(rx.nwqid == 0) 67 | wfid->qid = fid->qid; 68 | else 69 | wfid->qid = rx.wqid[rx.nwqid-1]; 70 | nwalk++; 71 | }while(name && *name); 72 | return wfid; 73 | } 74 | -------------------------------------------------------------------------------- /compat/lib9/errstr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * We assume there's only one error buffer for the whole system. 3 | * If you use ffork, you need to provide a _syserrstr. Since most 4 | * people will use libthread (which provides a _syserrstr), this is 5 | * okay. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | enum 14 | { 15 | EPLAN9 = 0x19283745 16 | }; 17 | 18 | char *(*_syserrstr)(void); 19 | static char xsyserr[ERRMAX]; 20 | static char* 21 | getsyserr(void) 22 | { 23 | char *s; 24 | 25 | s = nil; 26 | if(_syserrstr) 27 | s = (*_syserrstr)(); 28 | if(s == nil) 29 | s = xsyserr; 30 | return s; 31 | } 32 | 33 | int 34 | errstr(char *err, uint n) 35 | { 36 | char tmp[ERRMAX]; 37 | char *syserr; 38 | 39 | strecpy(tmp, tmp+ERRMAX, err); 40 | rerrstr(err, n); 41 | syserr = getsyserr(); 42 | strecpy(syserr, syserr+ERRMAX, tmp); 43 | errno = EPLAN9; 44 | return 0; 45 | } 46 | 47 | void 48 | rerrstr(char *err, uint n) 49 | { 50 | char *syserr; 51 | 52 | syserr = getsyserr(); 53 | if(errno == EINTR) 54 | strcpy(syserr, "interrupted"); 55 | else if(errno != EPLAN9) 56 | strcpy(syserr, strerror(errno)); 57 | strecpy(err, err+n, syserr); 58 | } 59 | 60 | /* replaces __errfmt in libfmt */ 61 | 62 | int 63 | __errfmt(Fmt *f) 64 | { 65 | if(errno == EPLAN9) 66 | return fmtstrcpy(f, getsyserr()); 67 | return fmtstrcpy(f, strerror(errno)); 68 | } 69 | 70 | void 71 | werrstr(char *fmt, ...) 72 | { 73 | va_list arg; 74 | char buf[ERRMAX]; 75 | 76 | va_start(arg, fmt); 77 | vseprint(buf, buf+ERRMAX, fmt, arg); 78 | va_end(arg); 79 | errstr(buf, ERRMAX); 80 | } 81 | -------------------------------------------------------------------------------- /compat/fmt/vsmprint.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 | /* 3 | * Plan 9 port version must include libc.h in order to 4 | * get Plan 9 debugging malloc, which sometimes returns 5 | * different pointers than the standard malloc. 6 | */ 7 | #ifdef PLAN9PORT 8 | #include 9 | #include 10 | #include "fmtdef.h" 11 | #else 12 | #include 13 | #include 14 | #include "plan9.h" 15 | #include "fmt.h" 16 | #include "fmtdef.h" 17 | #endif 18 | 19 | static int 20 | fmtStrFlush(Fmt *f) 21 | { 22 | char *s; 23 | int n; 24 | 25 | if(f->start == nil) 26 | return 0; 27 | n = (uintptr)f->farg; 28 | n *= 2; 29 | s = (char*)f->start; 30 | f->start = realloc(s, n); 31 | if(f->start == nil){ 32 | f->farg = nil; 33 | f->to = nil; 34 | f->stop = nil; 35 | free(s); 36 | return 0; 37 | } 38 | f->farg = (void*)(uintptr)n; 39 | f->to = (char*)f->start + ((char*)f->to - s); 40 | f->stop = (char*)f->start + n - 1; 41 | return 1; 42 | } 43 | 44 | int 45 | fmtstrinit(Fmt *f) 46 | { 47 | int n; 48 | 49 | memset(f, 0, sizeof *f); 50 | f->runes = 0; 51 | n = 32; 52 | f->start = malloc(n); 53 | if(f->start == nil) 54 | return -1; 55 | f->to = f->start; 56 | f->stop = (char*)f->start + n - 1; 57 | f->flush = fmtStrFlush; 58 | f->farg = (void*)(uintptr)n; 59 | f->nfmt = 0; 60 | fmtlocaleinit(f, nil, nil, nil); 61 | return 0; 62 | } 63 | 64 | /* 65 | * print into an allocated string buffer 66 | */ 67 | char* 68 | vsmprint(char *fmt, va_list args) 69 | { 70 | Fmt f; 71 | int n; 72 | 73 | if(fmtstrinit(&f) < 0) 74 | return nil; 75 | VA_COPY(f.args,args); 76 | n = dofmt(&f, fmt); 77 | VA_END(f.args); 78 | if(n < 0){ 79 | free(f.start); 80 | return nil; 81 | } 82 | return fmtstrflush(&f); 83 | } 84 | -------------------------------------------------------------------------------- /errstr.c: -------------------------------------------------------------------------------- 1 | #include "a.h" 2 | 3 | enum 4 | { 5 | EPLAN9 = 0x19283745 /* see /usr/local/plan9/src/lib9/errstr.c */ 6 | }; 7 | 8 | typedef struct Error Error; 9 | struct Error 10 | { 11 | char *text; 12 | int err; 13 | int len; 14 | }; 15 | 16 | static Error errortab[] = { 17 | { "permitted", EPERM }, 18 | { "permission", EACCES }, 19 | { "access", EACCES }, 20 | { "exists", EEXIST }, 21 | { "exist", ENOENT }, 22 | { "no such", ENOENT }, 23 | { "not found", ENOENT }, 24 | { "not implemented", ENOSYS}, 25 | { "input/output", EIO }, 26 | { "timeout", ETIMEDOUT }, 27 | { "timed out", ETIMEDOUT }, 28 | { "i/o", EIO }, 29 | { "too long", E2BIG }, 30 | { "interrupt", EINTR }, 31 | { "no such", ENODEV }, 32 | { "bad file", EBADF }, 33 | { " fid ", EBADF }, 34 | { "temporar", EAGAIN }, 35 | { "memory", ENOMEM }, 36 | { "is a directory", EISDIR }, 37 | { "directory", ENOTDIR }, 38 | { "argument", EINVAL }, 39 | { "pipe", EPIPE }, 40 | { "in use", EBUSY }, 41 | { "busy", EBUSY }, 42 | { "illegal", EINVAL }, 43 | { "invalid", EINVAL }, 44 | { "read-only", EROFS }, 45 | { "read only", EROFS }, 46 | { "stale ", ESTALE}, 47 | #ifdef EPROTO 48 | { "proto", EPROTO }, 49 | #else 50 | { "proto", EINVAL }, 51 | #endif 52 | { "entry", ENOENT }, 53 | }; 54 | 55 | int 56 | errstr2errno(void) 57 | { 58 | char e[ERRMAX]; 59 | int i, len; 60 | 61 | if(errno != EPLAN9) 62 | return errno; 63 | 64 | if(errortab[0].len == 0) 65 | for(i=0; i 2 | #include 3 | #include 4 | 5 | int 6 | statcheck(uchar *buf, uint nbuf) 7 | { 8 | uchar *ebuf; 9 | int i, nstr; 10 | 11 | ebuf = buf + nbuf; 12 | 13 | if(nbuf < STATFIXLEN || nbuf != BIT16SZ + GBIT16(buf)) 14 | return -1; 15 | 16 | buf += STATFIXLEN - 4 * BIT16SZ; 17 | 18 | nstr = 4; 19 | for(i = 0; i < nstr; i++){ 20 | if(buf + BIT16SZ > ebuf) 21 | return -1; 22 | buf += BIT16SZ + GBIT16(buf); 23 | } 24 | 25 | if(buf != ebuf) 26 | return -1; 27 | 28 | return 0; 29 | } 30 | 31 | static char nullstring[] = ""; 32 | 33 | uint 34 | convM2D(uchar *buf, uint nbuf, Dir *d, char *strs) 35 | { 36 | uchar *p, *ebuf; 37 | char *sv[5]; 38 | int i, ns, nstr; 39 | 40 | if(nbuf < STATFIXLEN) 41 | return 0; 42 | 43 | p = buf; 44 | ebuf = buf + nbuf; 45 | 46 | p += BIT16SZ; /* ignore size */ 47 | d->type = GBIT16(p); 48 | p += BIT16SZ; 49 | d->dev = GBIT32(p); 50 | p += BIT32SZ; 51 | d->qid.type = GBIT8(p); 52 | p += BIT8SZ; 53 | d->qid.vers = GBIT32(p); 54 | p += BIT32SZ; 55 | d->qid.path = GBIT64(p); 56 | p += BIT64SZ; 57 | d->mode = GBIT32(p); 58 | p += BIT32SZ; 59 | d->atime = GBIT32(p); 60 | p += BIT32SZ; 61 | d->mtime = GBIT32(p); 62 | p += BIT32SZ; 63 | d->length = GBIT64(p); 64 | p += BIT64SZ; 65 | 66 | nstr = 4; 67 | for(i = 0; i < nstr; i++){ 68 | if(p + BIT16SZ > ebuf) 69 | return 0; 70 | ns = GBIT16(p); 71 | p += BIT16SZ; 72 | if(p + ns > ebuf) 73 | return 0; 74 | if(strs){ 75 | sv[i] = strs; 76 | memmove(strs, p, ns); 77 | strs += ns; 78 | *strs++ = '\0'; 79 | } 80 | p += ns; 81 | } 82 | 83 | if(strs){ 84 | d->name = sv[0]; 85 | d->uid = sv[1]; 86 | d->gid = sv[2]; 87 | d->muid = sv[3]; 88 | d->ext = nullstring; 89 | }else{ 90 | d->name = nullstring; 91 | d->uid = nullstring; 92 | d->gid = nullstring; 93 | d->muid = nullstring; 94 | d->ext = nullstring; 95 | } 96 | 97 | return p - buf; 98 | } 99 | -------------------------------------------------------------------------------- /compat/libmux/queue.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ 2 | /* See COPYRIGHT */ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | typedef struct Qel Qel; 9 | struct Qel 10 | { 11 | Qel *next; 12 | void *p; 13 | }; 14 | 15 | struct Muxqueue 16 | { 17 | int hungup; 18 | QLock lk; 19 | Rendez r; 20 | Qel *head; 21 | Qel *tail; 22 | }; 23 | 24 | Muxqueue* 25 | _muxqalloc(void) 26 | { 27 | Muxqueue *q; 28 | 29 | q = mallocz(sizeof(Muxqueue), 1); 30 | if(q == nil) 31 | return nil; 32 | q->r.l = &q->lk; 33 | return q; 34 | } 35 | 36 | int 37 | _muxqsend(Muxqueue *q, void *p) 38 | { 39 | Qel *e; 40 | 41 | e = malloc(sizeof(Qel)); 42 | if(e == nil) 43 | return -1; 44 | qlock(&q->lk); 45 | if(q->hungup){ 46 | werrstr("hungup queue"); 47 | qunlock(&q->lk); 48 | free(e); 49 | return -1; 50 | } 51 | e->p = p; 52 | e->next = nil; 53 | if(q->head == nil) 54 | q->head = e; 55 | else 56 | q->tail->next = e; 57 | q->tail = e; 58 | rwakeup(&q->r); 59 | qunlock(&q->lk); 60 | return 0; 61 | } 62 | 63 | void* 64 | _muxqrecv(Muxqueue *q) 65 | { 66 | void *p; 67 | Qel *e; 68 | 69 | qlock(&q->lk); 70 | while(q->head == nil && !q->hungup) 71 | rsleep(&q->r); 72 | if(q->hungup){ 73 | qunlock(&q->lk); 74 | return nil; 75 | } 76 | e = q->head; 77 | q->head = e->next; 78 | qunlock(&q->lk); 79 | p = e->p; 80 | free(e); 81 | return p; 82 | } 83 | 84 | int 85 | _muxnbqrecv(Muxqueue *q, void **vp) 86 | { 87 | void *p; 88 | Qel *e; 89 | 90 | qlock(&q->lk); 91 | if(q->head == nil){ 92 | qunlock(&q->lk); 93 | *vp = nil; 94 | return q->hungup; 95 | } 96 | e = q->head; 97 | q->head = e->next; 98 | qunlock(&q->lk); 99 | p = e->p; 100 | free(e); 101 | *vp = p; 102 | return 1; 103 | } 104 | 105 | void 106 | _muxqhangup(Muxqueue *q) 107 | { 108 | qlock(&q->lk); 109 | q->hungup = 1; 110 | rwakeupall(&q->r); 111 | qunlock(&q->lk); 112 | } 113 | -------------------------------------------------------------------------------- /compat/lib9/convD2M.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | uint 6 | sizeD2M(Dir *d) 7 | { 8 | char *sv[5]; 9 | int i, ns, nstr, fixlen; 10 | 11 | sv[0] = d->name; 12 | sv[1] = d->uid; 13 | sv[2] = d->gid; 14 | sv[3] = d->muid; 15 | 16 | fixlen = STATFIXLEN; 17 | nstr = 4; 18 | 19 | ns = 0; 20 | for(i = 0; i < nstr; i++) 21 | if(sv[i]) 22 | ns += strlen(sv[i]); 23 | 24 | return fixlen + ns; 25 | } 26 | 27 | uint 28 | convD2M(Dir *d, uchar *buf, uint nbuf) 29 | { 30 | uchar *p, *ebuf; 31 | char *sv[5]; 32 | int i, ns, nsv[5], ss, nstr, fixlen; 33 | 34 | if(nbuf < BIT16SZ) 35 | return 0; 36 | 37 | p = buf; 38 | ebuf = buf + nbuf; 39 | 40 | sv[0] = d->name; 41 | sv[1] = d->uid; 42 | sv[2] = d->gid; 43 | sv[3] = d->muid; 44 | 45 | fixlen = STATFIXLEN; 46 | nstr = 4; 47 | 48 | ns = 0; 49 | for(i = 0; i < nstr; i++){ 50 | if(sv[i]) 51 | nsv[i] = strlen(sv[i]); 52 | else 53 | nsv[i] = 0; 54 | ns += nsv[i]; 55 | } 56 | 57 | ss = fixlen + ns; 58 | 59 | /* set size befor erroring, so user can know how much is needed */ 60 | /* note that length excludes count field itself */ 61 | PBIT16(p, ss-BIT16SZ); 62 | p += BIT16SZ; 63 | 64 | if(ss > nbuf) 65 | return BIT16SZ; 66 | 67 | PBIT16(p, d->type); 68 | p += BIT16SZ; 69 | PBIT32(p, d->dev); 70 | p += BIT32SZ; 71 | PBIT8(p, d->qid.type); 72 | p += BIT8SZ; 73 | PBIT32(p, d->qid.vers); 74 | p += BIT32SZ; 75 | PBIT64(p, d->qid.path); 76 | p += BIT64SZ; 77 | PBIT32(p, d->mode); 78 | p += BIT32SZ; 79 | PBIT32(p, d->atime); 80 | p += BIT32SZ; 81 | PBIT32(p, d->mtime); 82 | p += BIT32SZ; 83 | PBIT64(p, d->length); 84 | p += BIT64SZ; 85 | 86 | for(i = 0; i < nstr; i++){ 87 | ns = nsv[i]; 88 | if(p + ns + BIT16SZ > ebuf) 89 | return 0; 90 | PBIT16(p, ns); 91 | p += BIT16SZ; 92 | if(ns) 93 | memmove(p, sv[i], ns); 94 | p += ns; 95 | } 96 | 97 | if(ss != p - buf) 98 | return 0; 99 | 100 | return p - buf; 101 | } 102 | -------------------------------------------------------------------------------- /compat/lib9/sendfd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define NOPLAN9DEFINES 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifndef CMSG_ALIGN 10 | # ifdef __sun__ 11 | # define CMSG_ALIGN _CMSG_DATA_ALIGN 12 | # else 13 | # define CMSG_ALIGN(len) (((len)+sizeof(long)-1) & ~(sizeof(long)-1)) 14 | # endif 15 | #endif 16 | 17 | #ifndef CMSG_SPACE 18 | # define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr))+CMSG_ALIGN(len)) 19 | #endif 20 | 21 | #ifndef CMSG_LEN 22 | # define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr))+(len)) 23 | #endif 24 | 25 | int 26 | sendfd(int s, int fd) 27 | { 28 | char buf[1]; 29 | struct iovec iov; 30 | struct msghdr msg; 31 | struct cmsghdr *cmsg; 32 | int n; 33 | char cms[CMSG_SPACE(sizeof(int))]; 34 | 35 | buf[0] = 0; 36 | iov.iov_base = buf; 37 | iov.iov_len = 1; 38 | 39 | memset(&msg, 0, sizeof msg); 40 | msg.msg_iov = &iov; 41 | msg.msg_iovlen = 1; 42 | msg.msg_control = (caddr_t)cms; 43 | msg.msg_controllen = CMSG_LEN(sizeof(int)); 44 | 45 | cmsg = CMSG_FIRSTHDR(&msg); 46 | cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 47 | cmsg->cmsg_level = SOL_SOCKET; 48 | cmsg->cmsg_type = SCM_RIGHTS; 49 | memmove(CMSG_DATA(cmsg), &fd, sizeof(int)); 50 | 51 | if((n=sendmsg(s, &msg, 0)) != iov.iov_len) 52 | return -1; 53 | return 0; 54 | } 55 | 56 | int 57 | recvfd(int s) 58 | { 59 | int n; 60 | int fd; 61 | char buf[1]; 62 | struct iovec iov; 63 | struct msghdr msg; 64 | struct cmsghdr *cmsg; 65 | char cms[CMSG_SPACE(sizeof(int))]; 66 | 67 | iov.iov_base = buf; 68 | iov.iov_len = 1; 69 | 70 | memset(&msg, 0, sizeof msg); 71 | msg.msg_name = 0; 72 | msg.msg_namelen = 0; 73 | msg.msg_iov = &iov; 74 | msg.msg_iovlen = 1; 75 | 76 | msg.msg_control = (caddr_t)cms; 77 | msg.msg_controllen = sizeof cms; 78 | 79 | if((n=recvmsg(s, &msg, 0)) < 0) 80 | return -1; 81 | if(n == 0){ 82 | werrstr("unexpected EOF"); 83 | return -1; 84 | } 85 | cmsg = CMSG_FIRSTHDR(&msg); 86 | memmove(&fd, CMSG_DATA(cmsg), sizeof(int)); 87 | return fd; 88 | } 89 | -------------------------------------------------------------------------------- /compat/lib9pclient/dirread.c: -------------------------------------------------------------------------------- 1 | /* Mostly copied from Plan 9's libc. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include <9pclient.h> 7 | #include "fsimpl.h" 8 | 9 | static long 10 | dirpackage(uchar *buf, long ts, Dir **d) 11 | { 12 | char *s; 13 | long ss, i, n, nn, m; 14 | 15 | *d = nil; 16 | if(ts <= 0) 17 | return 0; 18 | 19 | /* 20 | * first find number of all stats, check they look like stats, & size all associated strings 21 | */ 22 | ss = 0; 23 | n = 0; 24 | for(i = 0; i < ts; i += m){ 25 | m = BIT16SZ + GBIT16(&buf[i]); 26 | if(statcheck(&buf[i], m) < 0) 27 | break; 28 | ss += m; 29 | n++; 30 | } 31 | 32 | if(i != ts) 33 | return -1; 34 | 35 | *d = malloc(n * sizeof(Dir) + ss); 36 | if(*d == nil) 37 | return -1; 38 | 39 | /* 40 | * then convert all buffers 41 | */ 42 | s = (char*)*d + n * sizeof(Dir); 43 | nn = 0; 44 | for(i = 0; i < ts; i += m){ 45 | m = BIT16SZ + GBIT16((uchar*)&buf[i]); 46 | if(nn >= n || convM2D(&buf[i], m, *d + nn, s) != m){ 47 | free(*d); 48 | *d = nil; 49 | return -1; 50 | } 51 | nn++; 52 | s += m; 53 | } 54 | 55 | return nn; 56 | } 57 | 58 | long 59 | fsdirread(CFid *fid, Dir **d) 60 | { 61 | uchar *buf; 62 | long ts; 63 | 64 | buf = malloc(DIRMAX); 65 | if(buf == nil) 66 | return -1; 67 | ts = fsread(fid, buf, DIRMAX); 68 | if(ts >= 0) 69 | ts = dirpackage(buf, ts, d); 70 | free(buf); 71 | return ts; 72 | } 73 | 74 | long 75 | fsdirreadall(CFid *fid, Dir **d) 76 | { 77 | uchar *buf, *nbuf; 78 | long n, ts; 79 | 80 | buf = nil; 81 | ts = 0; 82 | for(;;){ 83 | nbuf = realloc(buf, ts+DIRMAX); 84 | if(nbuf == nil){ 85 | free(buf); 86 | return -1; 87 | } 88 | buf = nbuf; 89 | n = fsread(fid, buf+ts, DIRMAX); 90 | if(n <= 0) 91 | break; 92 | ts += n; 93 | } 94 | if(ts >= 0){ 95 | ts = dirpackage(buf, ts, d); 96 | if(ts < 0) 97 | werrstr("malformed directory contents"); 98 | } 99 | free(buf); 100 | if(ts == 0 && n < 0) 101 | return -1; 102 | return ts; 103 | } 104 | -------------------------------------------------------------------------------- /compat/lib9/tokenize.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static char qsep[] = " \t\r\n"; 4 | 5 | static char* 6 | qtoken(char *s, char *sep) 7 | { 8 | int quoting; 9 | char *t; 10 | 11 | quoting = 0; 12 | t = s; /* s is output string, t is input string */ 13 | while(*t!='\0' && (quoting || utfrune(sep, *t)==nil)){ 14 | if(*t != '\''){ 15 | *s++ = *t++; 16 | continue; 17 | } 18 | /* *t is a quote */ 19 | if(!quoting){ 20 | quoting = 1; 21 | t++; 22 | continue; 23 | } 24 | /* quoting and we're on a quote */ 25 | if(t[1] != '\''){ 26 | /* end of quoted section; absorb closing quote */ 27 | t++; 28 | quoting = 0; 29 | continue; 30 | } 31 | /* doubled quote; fold one quote into two */ 32 | t++; 33 | *s++ = *t++; 34 | } 35 | if(*s != '\0'){ 36 | *s = '\0'; 37 | if(t == s) 38 | t++; 39 | } 40 | return t; 41 | } 42 | 43 | static char* 44 | etoken(char *t, char *sep) 45 | { 46 | int quoting; 47 | 48 | /* move to end of next token */ 49 | quoting = 0; 50 | while(*t!='\0' && (quoting || utfrune(sep, *t)==nil)){ 51 | if(*t != '\''){ 52 | t++; 53 | continue; 54 | } 55 | /* *t is a quote */ 56 | if(!quoting){ 57 | quoting = 1; 58 | t++; 59 | continue; 60 | } 61 | /* quoting and we're on a quote */ 62 | if(t[1] != '\''){ 63 | /* end of quoted section; absorb closing quote */ 64 | t++; 65 | quoting = 0; 66 | continue; 67 | } 68 | /* doubled quote; fold one quote into two */ 69 | t += 2; 70 | } 71 | return t; 72 | } 73 | 74 | int 75 | gettokens(char *s, char **args, int maxargs, char *sep) 76 | { 77 | int nargs; 78 | 79 | for(nargs=0; nargs 2 | #include 3 | #include 4 | #include "ioproc.h" 5 | 6 | enum 7 | { 8 | STACK = 32768 9 | }; 10 | 11 | void 12 | iointerrupt(Ioproc *io) 13 | { 14 | if(!io->inuse) 15 | return; 16 | fprint(2, "bug: cannot iointerrupt %p yet\n", io); 17 | } 18 | 19 | static void 20 | xioproc(void *a) 21 | { 22 | Ioproc *io, *x; 23 | 24 | threadsetname("ioproc"); 25 | io = a; 26 | /* 27 | * first recvp acquires the ioproc. 28 | * second tells us that the data is ready. 29 | */ 30 | for(;;){ 31 | while(recv(io->c, &x) == -1) 32 | ; 33 | if(x == 0) /* our cue to leave */ 34 | break; 35 | assert(x == io); 36 | 37 | /* caller is now committed -- even if interrupted he'll return */ 38 | while(recv(io->creply, &x) == -1) 39 | ; 40 | if(x == 0) /* caller backed out */ 41 | continue; 42 | assert(x == io); 43 | 44 | io->ret = io->op(&io->arg); 45 | if(io->ret < 0) 46 | rerrstr(io->err, sizeof io->err); 47 | while(send(io->creply, &io) == -1) 48 | ; 49 | while(recv(io->creply, &x) == -1) 50 | ; 51 | } 52 | } 53 | 54 | Ioproc* 55 | ioproc(void) 56 | { 57 | Ioproc *io; 58 | 59 | io = mallocz(sizeof(*io), 1); 60 | if(io == nil) 61 | sysfatal("ioproc malloc: %r"); 62 | io->c = chancreate(sizeof(void*), 0); 63 | chansetname(io->c, "ioc%p", io->c); 64 | io->creply = chancreate(sizeof(void*), 0); 65 | chansetname(io->creply, "ior%p", io->c); 66 | io->tid = proccreate(xioproc, io, STACK); 67 | return io; 68 | } 69 | 70 | void 71 | closeioproc(Ioproc *io) 72 | { 73 | if(io == nil) 74 | return; 75 | iointerrupt(io); 76 | while(send(io->c, 0) == -1) 77 | ; 78 | chanfree(io->c); 79 | chanfree(io->creply); 80 | free(io); 81 | } 82 | 83 | long 84 | iocall(Ioproc *io, long (*op)(va_list*), ...) 85 | { 86 | char e[ERRMAX]; 87 | int ret, inted; 88 | Ioproc *msg; 89 | 90 | if(send(io->c, &io) == -1){ 91 | werrstr("interrupted"); 92 | return -1; 93 | } 94 | assert(!io->inuse); 95 | io->inuse = 1; 96 | io->op = op; 97 | va_start(io->arg, op); 98 | msg = io; 99 | inted = 0; 100 | while(send(io->creply, &msg) == -1){ 101 | msg = nil; 102 | inted = 1; 103 | } 104 | if(inted){ 105 | werrstr("interrupted"); 106 | return -1; 107 | } 108 | 109 | /* 110 | * If we get interrupted, we have stick around so that 111 | * the IO proc has someone to talk to. Send it an interrupt 112 | * and try again. 113 | */ 114 | inted = 0; 115 | while(recv(io->creply, nil) == -1){ 116 | inted = 1; 117 | iointerrupt(io); 118 | } 119 | USED(inted); 120 | va_end(io->arg); 121 | ret = io->ret; 122 | if(ret < 0) 123 | strecpy(e, e+sizeof e, io->err); 124 | io->inuse = 0; 125 | 126 | /* release resources */ 127 | while(send(io->creply, &io) == -1) 128 | ; 129 | if(ret < 0) 130 | errstr(e, sizeof e); 131 | return ret; 132 | } 133 | -------------------------------------------------------------------------------- /compat/libmux/io.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ 2 | /* See COPYRIGHT */ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | /* 9 | * If you fork off two procs running muxrecvproc and muxsendproc, 10 | * then muxrecv/muxsend (and thus muxrpc) will never block except on 11 | * rendevouses, which is nice when it's running in one thread of many. 12 | */ 13 | void 14 | _muxrecvproc(void *v) 15 | { 16 | void *p; 17 | Mux *mux; 18 | Muxqueue *q; 19 | 20 | mux = v; 21 | q = _muxqalloc(); 22 | 23 | qlock(&mux->lk); 24 | mux->readq = q; 25 | qlock(&mux->inlk); 26 | rwakeup(&mux->rpcfork); 27 | qunlock(&mux->lk); 28 | 29 | while((p = mux->recv(mux)) != nil) 30 | if(_muxqsend(q, p) < 0){ 31 | free(p); 32 | break; 33 | } 34 | qunlock(&mux->inlk); 35 | qlock(&mux->lk); 36 | _muxqhangup(q); 37 | p = nil; 38 | while(_muxnbqrecv(q, &p) && p != nil){ 39 | free(p); 40 | p = nil; 41 | } 42 | free(q); 43 | mux->readq = nil; 44 | rwakeup(&mux->rpcfork); 45 | qunlock(&mux->lk); 46 | } 47 | 48 | void 49 | _muxsendproc(void *v) 50 | { 51 | Muxqueue *q; 52 | void *p; 53 | Mux *mux; 54 | 55 | mux = v; 56 | q = _muxqalloc(); 57 | 58 | qlock(&mux->lk); 59 | mux->writeq = q; 60 | qlock(&mux->outlk); 61 | rwakeup(&mux->rpcfork); 62 | qunlock(&mux->lk); 63 | 64 | while((p = _muxqrecv(q)) != nil) 65 | if(mux->send(mux, p) < 0) 66 | break; 67 | qunlock(&mux->outlk); 68 | qlock(&mux->lk); 69 | _muxqhangup(q); 70 | while(_muxnbqrecv(q, &p)) 71 | free(p); 72 | free(q); 73 | mux->writeq = nil; 74 | rwakeup(&mux->rpcfork); 75 | qunlock(&mux->lk); 76 | return; 77 | } 78 | 79 | int 80 | _muxrecv(Mux *mux, int canblock, void **vp) 81 | { 82 | void *p; 83 | int ret; 84 | 85 | qlock(&mux->lk); 86 | if(mux->readq){ 87 | qunlock(&mux->lk); 88 | if(canblock){ 89 | *vp = _muxqrecv(mux->readq); 90 | return 1; 91 | } 92 | return _muxnbqrecv(mux->readq, vp); 93 | } 94 | 95 | qlock(&mux->inlk); 96 | qunlock(&mux->lk); 97 | if(canblock){ 98 | p = mux->recv(mux); 99 | ret = 1; 100 | }else{ 101 | if(mux->nbrecv) 102 | ret = mux->nbrecv(mux, &p); 103 | else{ 104 | /* send eof, not "no packet ready" */ 105 | p = nil; 106 | ret = 1; 107 | } 108 | } 109 | qunlock(&mux->inlk); 110 | *vp = p; 111 | return ret; 112 | } 113 | 114 | int 115 | _muxsend(Mux *mux, void *p) 116 | { 117 | qlock(&mux->lk); 118 | /* 119 | if(mux->state != VtStateConnected){ 120 | packetfree(p); 121 | werrstr("not connected"); 122 | qunlock(&mux->lk); 123 | return -1; 124 | } 125 | */ 126 | if(mux->writeq){ 127 | qunlock(&mux->lk); 128 | if(_muxqsend(mux->writeq, p) < 0){ 129 | free(p); 130 | return -1; 131 | } 132 | return 0; 133 | } 134 | 135 | qlock(&mux->outlk); 136 | qunlock(&mux->lk); 137 | if(mux->send(mux, p) < 0){ 138 | qunlock(&mux->outlk); 139 | /* vthangup(mux); */ 140 | return -1; 141 | } 142 | qunlock(&mux->outlk); 143 | return 0; 144 | } 145 | -------------------------------------------------------------------------------- /compat/lib9/qlock.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | * The function pointers are supplied by the thread 6 | * library during its initialization. If there is no thread 7 | * library, there is no multithreading. 8 | */ 9 | 10 | int (*_lock)(Lock*, int, ulong); 11 | void (*_unlock)(Lock*, ulong); 12 | int (*_qlock)(QLock*, int, ulong); /* do not use */ 13 | void (*_qunlock)(QLock*, ulong); 14 | void (*_rsleep)(Rendez*, ulong); /* do not use */ 15 | int (*_rwakeup)(Rendez*, int, ulong); 16 | int (*_rlock)(RWLock*, int, ulong); /* do not use */ 17 | int (*_wlock)(RWLock*, int, ulong); 18 | void (*_runlock)(RWLock*, ulong); 19 | void (*_wunlock)(RWLock*, ulong); 20 | 21 | void 22 | lock(Lock *l) 23 | { 24 | if(_lock) 25 | (*_lock)(l, 1, getcallerpc(&l)); 26 | else 27 | l->held = 1; 28 | } 29 | 30 | int 31 | canlock(Lock *l) 32 | { 33 | if(_lock) 34 | return (*_lock)(l, 0, getcallerpc(&l)); 35 | else{ 36 | if(l->held) 37 | return 0; 38 | l->held = 1; 39 | return 1; 40 | } 41 | } 42 | 43 | void 44 | unlock(Lock *l) 45 | { 46 | if(_unlock) 47 | (*_unlock)(l, getcallerpc(&l)); 48 | else 49 | l->held = 0; 50 | } 51 | 52 | void 53 | qlock(QLock *l) 54 | { 55 | if(_qlock) 56 | (*_qlock)(l, 1, getcallerpc(&l)); 57 | else 58 | l->l.held = 1; 59 | } 60 | 61 | int 62 | canqlock(QLock *l) 63 | { 64 | if(_qlock) 65 | return (*_qlock)(l, 0, getcallerpc(&l)); 66 | else{ 67 | if(l->l.held) 68 | return 0; 69 | l->l.held = 1; 70 | return 1; 71 | } 72 | } 73 | 74 | void 75 | qunlock(QLock *l) 76 | { 77 | if(_qunlock) 78 | (*_qunlock)(l, getcallerpc(&l)); 79 | else 80 | l->l.held = 0; 81 | } 82 | 83 | void 84 | rlock(RWLock *l) 85 | { 86 | if(_rlock) 87 | (*_rlock)(l, 1, getcallerpc(&l)); 88 | else 89 | l->readers++; 90 | } 91 | 92 | int 93 | canrlock(RWLock *l) 94 | { 95 | if(_rlock) 96 | return (*_rlock)(l, 0, getcallerpc(&l)); 97 | else{ 98 | if(l->writer) 99 | return 0; 100 | l->readers++; 101 | return 1; 102 | } 103 | } 104 | 105 | void 106 | runlock(RWLock *l) 107 | { 108 | if(_runlock) 109 | (*_runlock)(l, getcallerpc(&l)); 110 | else 111 | l->readers--; 112 | } 113 | 114 | void 115 | wlock(RWLock *l) 116 | { 117 | if(_wlock) 118 | (*_wlock)(l, 1, getcallerpc(&l)); 119 | else 120 | l->writer = (void*)1; 121 | } 122 | 123 | int 124 | canwlock(RWLock *l) 125 | { 126 | if(_wlock) 127 | return (*_wlock)(l, 0, getcallerpc(&l)); 128 | else{ 129 | if(l->writer || l->readers) 130 | return 0; 131 | l->writer = (void*)1; 132 | return 1; 133 | } 134 | } 135 | 136 | void 137 | wunlock(RWLock *l) 138 | { 139 | if(_wunlock) 140 | (*_wunlock)(l, getcallerpc(&l)); 141 | else 142 | l->writer = nil; 143 | } 144 | 145 | void 146 | rsleep(Rendez *r) 147 | { 148 | if(_rsleep) 149 | (*_rsleep)(r, getcallerpc(&r)); 150 | } 151 | 152 | int 153 | rwakeup(Rendez *r) 154 | { 155 | if(_rwakeup) 156 | return (*_rwakeup)(r, 0, getcallerpc(&r)); 157 | return 0; 158 | } 159 | 160 | int 161 | rwakeupall(Rendez *r) 162 | { 163 | if(_rwakeup) 164 | return (*_rwakeup)(r, 1, getcallerpc(&r)); 165 | return 0; 166 | } 167 | -------------------------------------------------------------------------------- /compat/libthread/threadimpl.h: -------------------------------------------------------------------------------- 1 | #include "u.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #if !defined(__OpenBSD__) 9 | # if defined(__APPLE__) 10 | # define _XOPEN_SOURCE /* for Snow Leopard */ 11 | # endif 12 | #endif 13 | #include 14 | #include "libc.h" 15 | #include "thread.h" 16 | 17 | typedef struct Execjob Execjob; 18 | typedef struct Proc Proc; 19 | typedef struct _Procrendez _Procrendez; 20 | 21 | typedef struct Jmp Jmp; 22 | struct Jmp 23 | { 24 | p9jmp_buf b; 25 | }; 26 | 27 | enum 28 | { 29 | STACK = 8192 30 | }; 31 | 32 | struct Execjob 33 | { 34 | int *fd; 35 | char *cmd; 36 | char **argv; 37 | char *dir; 38 | Channel *c; 39 | }; 40 | 41 | struct _Procrendez 42 | { 43 | Lock *l; 44 | int asleep; 45 | pthread_cond_t cond; 46 | }; 47 | 48 | struct _Thread 49 | { 50 | _Thread *next; 51 | _Thread *prev; 52 | _Thread *allnext; 53 | _Thread *allprev; 54 | void (*startfn)(void*); 55 | void *startarg; 56 | uint id; 57 | pthread_t osprocid; 58 | uchar *stk; 59 | uint stksize; 60 | int exiting; 61 | int mainthread; 62 | Proc *proc; 63 | char name[256]; 64 | char state[256]; 65 | void *udata; 66 | Alt *alt; 67 | _Procrendez schedrend; 68 | }; 69 | 70 | extern void _procsleep(_Procrendez*); 71 | extern void _procwakeup(_Procrendez*); 72 | extern void _procwakeupandunlock(_Procrendez*); 73 | 74 | struct Proc 75 | { 76 | Proc *next; 77 | Proc *prev; 78 | char msg[128]; 79 | pthread_t osprocid; 80 | Lock lock; 81 | int nswitch; 82 | _Thread *thread0; 83 | _Thread *thread; 84 | _Thread *pinthread; 85 | _Threadlist runqueue; 86 | _Threadlist idlequeue; 87 | _Threadlist allthreads; 88 | uint nthread; 89 | uint sysproc; 90 | _Procrendez runrend; 91 | _Thread *schedthread; 92 | void *udata; 93 | Jmp sigjmp; 94 | int mainproc; 95 | }; 96 | 97 | #define proc() _threadproc() 98 | 99 | extern Proc *_threadprocs; 100 | extern Lock _threadprocslock; 101 | extern Proc *_threadexecproc; 102 | extern Channel *_threadexecchan; 103 | extern QLock _threadexeclock; 104 | extern Channel *_dowaitchan; 105 | 106 | extern void _procstart(Proc*, void (*fn)(Proc*)); 107 | extern _Thread *_threadcreate(Proc*, void(*fn)(void*), void*, uint); 108 | extern void _procexit(void); 109 | extern Proc *_threadproc(void); 110 | extern void _threadsetproc(Proc*); 111 | extern int _threadlock(Lock*, int, ulong); 112 | extern void _threadunlock(Lock*, ulong); 113 | extern void _pthreadinit(void); 114 | extern int _threadspawn(int*, char*, char**, char*); 115 | extern int _runthreadspawn(int*, char*, char**, char*); 116 | extern void _threadsetupdaemonize(void); 117 | extern void _threaddodaemonize(char*); 118 | extern void _threadpexit(void); 119 | extern void _threaddaemonize(void); 120 | extern void *_threadstkalloc(int); 121 | extern void _threadstkfree(void*, int); 122 | extern void _threadpthreadmain(Proc*, _Thread*); 123 | extern void _threadpthreadstart(Proc*, _Thread*); 124 | 125 | #define USPALIGN(ucp, align) \ 126 | (void*)((((uintptr)(ucp)->uc_stack.ss_sp+(ucp)->uc_stack.ss_size)-(align))&~((align)-1)) 127 | -------------------------------------------------------------------------------- /compat/fmt/fmtdef.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 | 3 | /* 4 | * dofmt -- format to a buffer 5 | * the number of characters formatted is returned, 6 | * or -1 if there was an error. 7 | * if the buffer is ever filled, flush is called. 8 | * it should reset the buffer and return whether formatting should continue. 9 | */ 10 | 11 | typedef int (*Fmts)(Fmt*); 12 | 13 | typedef struct Quoteinfo Quoteinfo; 14 | struct Quoteinfo 15 | { 16 | int quoted; /* if set, string must be quoted */ 17 | int nrunesin; /* number of input runes that can be accepted */ 18 | int nbytesin; /* number of input bytes that can be accepted */ 19 | int nrunesout; /* number of runes that will be generated */ 20 | int nbytesout; /* number of bytes that will be generated */ 21 | }; 22 | 23 | /* Edit .+1,/^$/ |cfn |grep -v static | grep __ */ 24 | double __Inf(int sign); 25 | double __NaN(void); 26 | int __badfmt(Fmt *f); 27 | int __charfmt(Fmt *f); 28 | int __countfmt(Fmt *f); 29 | int __efgfmt(Fmt *fmt); 30 | int __errfmt(Fmt *f); 31 | int __flagfmt(Fmt *f); 32 | int __fmtFdFlush(Fmt *f); 33 | int __fmtcpy(Fmt *f, const void *vm, int n, int sz); 34 | void* __fmtdispatch(Fmt *f, void *fmt, int isrunes); 35 | void * __fmtflush(Fmt *f, void *t, int len); 36 | int __fmtpad(Fmt *f, int n); 37 | double __fmtpow10(int n); 38 | int __fmtrcpy(Fmt *f, const void *vm, int n); 39 | void __fmtlock(void); 40 | void __fmtunlock(void); 41 | int __ifmt(Fmt *f); 42 | int __isInf(double d, int sign); 43 | int __isNaN(double d); 44 | int __needsep(int*, char**); 45 | int __needsquotes(char *s, int *quotelenp); 46 | int __percentfmt(Fmt *f); 47 | void __quotesetup(char *s, Rune *r, int nin, int nout, Quoteinfo *q, int sharp, int runesout); 48 | int __quotestrfmt(int runesin, Fmt *f); 49 | int __rfmtpad(Fmt *f, int n); 50 | int __runefmt(Fmt *f); 51 | int __runeneedsquotes(Rune *r, int *quotelenp); 52 | int __runesfmt(Fmt *f); 53 | int __strfmt(Fmt *f); 54 | 55 | #define FMTCHAR(f, t, s, c)\ 56 | do{\ 57 | if(t + 1 > (char*)s){\ 58 | t = (char*)__fmtflush(f, t, 1);\ 59 | if(t != nil)\ 60 | s = (char*)f->stop;\ 61 | else\ 62 | return -1;\ 63 | }\ 64 | *t++ = c;\ 65 | }while(0) 66 | 67 | #define FMTRCHAR(f, t, s, c)\ 68 | do{\ 69 | if(t + 1 > (Rune*)s){\ 70 | t = (Rune*)__fmtflush(f, t, sizeof(Rune));\ 71 | if(t != nil)\ 72 | s = (Rune*)f->stop;\ 73 | else\ 74 | return -1;\ 75 | }\ 76 | *t++ = c;\ 77 | }while(0) 78 | 79 | #define FMTRUNE(f, t, s, r)\ 80 | do{\ 81 | Rune _rune;\ 82 | int _runelen;\ 83 | if(t + UTFmax > (char*)s && t + (_runelen = runelen(r)) > (char*)s){\ 84 | t = (char*)__fmtflush(f, t, _runelen);\ 85 | if(t != nil)\ 86 | s = (char*)f->stop;\ 87 | else\ 88 | return -1;\ 89 | }\ 90 | if(r < Runeself)\ 91 | *t++ = r;\ 92 | else{\ 93 | _rune = r;\ 94 | t += runetochar(t, &_rune);\ 95 | }\ 96 | }while(0) 97 | 98 | #ifdef va_copy 99 | # define VA_COPY(a,b) va_copy(a,b) 100 | # define VA_END(a) va_end(a) 101 | #else 102 | # define VA_COPY(a,b) (a) = (b) 103 | # define VA_END(a) 104 | #endif 105 | -------------------------------------------------------------------------------- /compat/libthread/iorw.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "ioproc.h" 8 | 9 | static long 10 | _ioclose(va_list *arg) 11 | { 12 | int fd; 13 | 14 | fd = va_arg(*arg, int); 15 | return close(fd); 16 | } 17 | int 18 | ioclose(Ioproc *io, int fd) 19 | { 20 | return iocall(io, _ioclose, fd); 21 | } 22 | 23 | static long 24 | _iodial(va_list *arg) 25 | { 26 | char *addr, *local, *dir; 27 | int *cdfp, fd; 28 | 29 | addr = va_arg(*arg, char*); 30 | local = va_arg(*arg, char*); 31 | dir = va_arg(*arg, char*); 32 | cdfp = va_arg(*arg, int*); 33 | 34 | fd = dial(addr, local, dir, cdfp); 35 | return fd; 36 | } 37 | int 38 | iodial(Ioproc *io, char *addr, char *local, char *dir, int *cdfp) 39 | { 40 | return iocall(io, _iodial, addr, local, dir, cdfp); 41 | } 42 | 43 | static long 44 | _ioopen(va_list *arg) 45 | { 46 | char *path; 47 | int mode; 48 | 49 | path = va_arg(*arg, char*); 50 | mode = va_arg(*arg, int); 51 | return open(path, mode); 52 | } 53 | int 54 | ioopen(Ioproc *io, char *path, int mode) 55 | { 56 | return iocall(io, _ioopen, path, mode); 57 | } 58 | 59 | static long 60 | _ioread(va_list *arg) 61 | { 62 | int fd; 63 | void *a; 64 | long n; 65 | 66 | fd = va_arg(*arg, int); 67 | a = va_arg(*arg, void*); 68 | n = va_arg(*arg, long); 69 | return read(fd, a, n); 70 | } 71 | long 72 | ioread(Ioproc *io, int fd, void *a, long n) 73 | { 74 | return iocall(io, _ioread, fd, a, n); 75 | } 76 | 77 | static long 78 | _ioreadn(va_list *arg) 79 | { 80 | int fd; 81 | void *a; 82 | long n; 83 | 84 | fd = va_arg(*arg, int); 85 | a = va_arg(*arg, void*); 86 | n = va_arg(*arg, long); 87 | n = readn(fd, a, n); 88 | return n; 89 | } 90 | long 91 | ioreadn(Ioproc *io, int fd, void *a, long n) 92 | { 93 | return iocall(io, _ioreadn, fd, a, n); 94 | } 95 | 96 | static long 97 | _iosleep(va_list *arg) 98 | { 99 | long n; 100 | 101 | n = va_arg(*arg, long); 102 | return sleep(n); 103 | } 104 | int 105 | iosleep(Ioproc *io, long n) 106 | { 107 | return iocall(io, _iosleep, n); 108 | } 109 | 110 | static long 111 | _iowrite(va_list *arg) 112 | { 113 | int fd; 114 | void *a; 115 | long n, nn; 116 | 117 | fd = va_arg(*arg, int); 118 | a = va_arg(*arg, void*); 119 | n = va_arg(*arg, long); 120 | nn = write(fd, a, n); 121 | return nn; 122 | } 123 | long 124 | iowrite(Ioproc *io, int fd, void *a, long n) 125 | { 126 | n = iocall(io, _iowrite, fd, a, n); 127 | return n; 128 | } 129 | 130 | static long 131 | _iosendfd(va_list *arg) 132 | { 133 | int n, fd, fd2; 134 | 135 | fd = va_arg(*arg, int); 136 | fd2 = va_arg(*arg, int); 137 | n = sendfd(fd, fd2); 138 | return n; 139 | } 140 | int 141 | iosendfd(Ioproc *io, int fd, int fd2) 142 | { 143 | return iocall(io, _iosendfd, fd, fd2); 144 | } 145 | 146 | static long 147 | _iorecvfd(va_list *arg) 148 | { 149 | int n, fd; 150 | 151 | fd = va_arg(*arg, int); 152 | n = recvfd(fd); 153 | return n; 154 | } 155 | int 156 | iorecvfd(Ioproc *io, int fd) 157 | { 158 | return iocall(io, _iorecvfd, fd); 159 | } 160 | 161 | static long 162 | _ioread9pmsg(va_list *arg) 163 | { 164 | int fd; 165 | void *a; 166 | int n; 167 | 168 | fd = va_arg(*arg, int); 169 | a = va_arg(*arg, void*); 170 | n = va_arg(*arg, int); 171 | read9pmsg(fd, a, n); 172 | return n; 173 | } 174 | int 175 | ioread9pmsg(Ioproc *io, int fd, void *a, int n) 176 | { 177 | return iocall(io, _ioread9pmsg, fd, a, n); 178 | } 179 | -------------------------------------------------------------------------------- /compat/lib9/await.c: -------------------------------------------------------------------------------- 1 | #define NOPLAN9DEFINES 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #ifndef WCOREDUMP /* not on Mac OS X Tiger */ 12 | #define WCOREDUMP(status) 0 13 | #endif 14 | 15 | static struct { 16 | int sig; 17 | char *str; 18 | } tab[] = { 19 | SIGHUP, "hangup", 20 | SIGINT, "interrupt", 21 | SIGQUIT, "quit", 22 | SIGILL, "sys: illegal instruction", 23 | SIGTRAP, "sys: breakpoint", 24 | SIGABRT, "sys: abort", 25 | #ifdef SIGEMT 26 | SIGEMT, "sys: emulate instruction executed", 27 | #endif 28 | SIGFPE, "sys: fp: trap", 29 | SIGKILL, "sys: kill", 30 | SIGBUS, "sys: bus error", 31 | SIGSEGV, "sys: segmentation violation", 32 | SIGALRM, "alarm", 33 | SIGTERM, "kill", 34 | SIGURG, "sys: urgent condition on socket", 35 | SIGSTOP, "sys: stop", 36 | SIGTSTP, "sys: tstp", 37 | SIGCONT, "sys: cont", 38 | SIGCHLD, "sys: child", 39 | SIGTTIN, "sys: ttin", 40 | SIGTTOU, "sys: ttou", 41 | #ifdef SIGIO /* not on Mac OS X Tiger */ 42 | SIGIO, "sys: i/o possible on fd", 43 | #endif 44 | SIGXCPU, "sys: cpu time limit exceeded", 45 | SIGXFSZ, "sys: file size limit exceeded", 46 | SIGVTALRM, "sys: virtual time alarm", 47 | SIGPROF, "sys: profiling timer alarm", 48 | #ifdef SIGWINCH /* not on Mac OS X Tiger */ 49 | SIGWINCH, "sys: window size change", 50 | #endif 51 | #ifdef SIGINFO 52 | SIGINFO, "sys: status request", 53 | #endif 54 | SIGUSR1, "sys: usr1", 55 | SIGUSR2, "sys: usr2", 56 | SIGPIPE, "sys: write on closed pipe", 57 | }; 58 | 59 | char* 60 | _p9sigstr(int sig, char *tmp) 61 | { 62 | int i; 63 | 64 | for(i=0; i 2 | #include 3 | 4 | #undef accept 5 | #undef announce 6 | #undef dial 7 | #undef setnetmtpt 8 | #undef hangup 9 | #undef listen 10 | #undef netmkaddr 11 | #undef reject 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #undef unix 20 | #define unix xunix 21 | 22 | static int 23 | isany(struct sockaddr_storage *ss) 24 | { 25 | switch(ss->ss_family){ 26 | case AF_INET: 27 | return (((struct sockaddr_in*)ss)->sin_addr.s_addr == INADDR_ANY); 28 | case AF_INET6: 29 | return (memcmp(((struct sockaddr_in6*)ss)->sin6_addr.s6_addr, 30 | in6addr_any.s6_addr, sizeof (struct in6_addr)) == 0); 31 | } 32 | return 0; 33 | } 34 | 35 | static int 36 | addrlen(struct sockaddr_storage *ss) 37 | { 38 | switch(ss->ss_family){ 39 | case AF_INET: 40 | return sizeof(struct sockaddr_in); 41 | case AF_INET6: 42 | return sizeof(struct sockaddr_in6); 43 | case AF_UNIX: 44 | return sizeof(struct sockaddr_un); 45 | } 46 | return 0; 47 | } 48 | 49 | int 50 | p9dial(char *addr, char *local, char *dummy2, int *dummy3) 51 | { 52 | char *buf; 53 | char *net, *unix; 54 | int port; 55 | int proto; 56 | socklen_t sn; 57 | int n; 58 | struct sockaddr_storage ss, ssl; 59 | int s; 60 | 61 | if(dummy2 || dummy3){ 62 | werrstr("cannot handle extra arguments in dial"); 63 | return -1; 64 | } 65 | 66 | buf = strdup(addr); 67 | if(buf == nil) 68 | return -1; 69 | 70 | if(p9dialparse(buf, &net, &unix, &ss, &port) < 0){ 71 | free(buf); 72 | return -1; 73 | } 74 | if(strcmp(net, "unix") != 0 && isany(&ss)){ 75 | werrstr("invalid dial address 0.0.0.0 (aka *)"); 76 | free(buf); 77 | return -1; 78 | } 79 | 80 | if(strcmp(net, "tcp") == 0) 81 | proto = SOCK_STREAM; 82 | else if(strcmp(net, "udp") == 0) 83 | proto = SOCK_DGRAM; 84 | else if(strcmp(net, "unix") == 0) 85 | goto Unix; 86 | else{ 87 | werrstr("can only handle tcp, udp, and unix: not %s", net); 88 | free(buf); 89 | return -1; 90 | } 91 | free(buf); 92 | 93 | if((s = socket(ss.ss_family, proto, 0)) < 0) 94 | return -1; 95 | 96 | if(local){ 97 | buf = strdup(local); 98 | if(buf == nil){ 99 | close(s); 100 | return -1; 101 | } 102 | if(p9dialparse(buf, &net, &unix, &ss, &port) < 0){ 103 | badlocal: 104 | free(buf); 105 | close(s); 106 | return -1; 107 | } 108 | if(unix){ 109 | werrstr("bad local address %s for dial %s", local, addr); 110 | goto badlocal; 111 | } 112 | sn = sizeof n; 113 | if(port && getsockopt(s, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) >= 0 114 | && n == SOCK_STREAM){ 115 | n = 1; 116 | setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof n); 117 | } 118 | if(bind(s, (struct sockaddr*)&ssl, addrlen(&ssl)) < 0) 119 | goto badlocal; 120 | free(buf); 121 | } 122 | 123 | n = 1; 124 | setsockopt(s, SOL_SOCKET, SO_BROADCAST, &n, sizeof n); 125 | if(!isany(&ss)){ 126 | if(connect(s, (struct sockaddr*)&ss, addrlen(&ss)) < 0){ 127 | close(s); 128 | return -1; 129 | } 130 | } 131 | if(proto == SOCK_STREAM){ 132 | int one = 1; 133 | setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof one); 134 | } 135 | return s; 136 | 137 | Unix: 138 | if(local){ 139 | werrstr("local address not supported on unix network"); 140 | free(buf); 141 | return -1; 142 | } 143 | /* Allow regular files in addition to Unix sockets. */ 144 | if((s = open(unix, ORDWR)) >= 0){ 145 | free(buf); 146 | return s; 147 | } 148 | free(buf); 149 | if((s = socket(ss.ss_family, SOCK_STREAM, 0)) < 0){ 150 | werrstr("socket: %r"); 151 | return -1; 152 | } 153 | if(connect(s, (struct sockaddr*)&ss, addrlen(&ss)) < 0){ 154 | werrstr("connect %s: %r", ((struct sockaddr_un*)&ss)->sun_path); 155 | close(s); 156 | return -1; 157 | } 158 | return s; 159 | } 160 | -------------------------------------------------------------------------------- /compat/fcall.h: -------------------------------------------------------------------------------- 1 | #ifndef _FCALL_H_ 2 | #define _FCALL_H_ 1 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | /* 7 | #pragma src "/sys/src/libc/9sys" 8 | #pragma lib "libc.a" 9 | */ 10 | 11 | #define VERSION9P "9P2000" 12 | #define MAXWELEM 16 13 | 14 | typedef 15 | struct Fcall 16 | { 17 | uchar type; 18 | u32int fid; 19 | ushort tag; 20 | u32int msize; /* Tversion, Rversion */ 21 | char *version; /* Tversion, Rversion */ 22 | ushort oldtag; /* Tflush */ 23 | char *ename; /* Rerror */ 24 | Qid qid; /* Rattach, Ropen, Rcreate */ 25 | u32int iounit; /* Ropen, Rcreate */ 26 | Qid aqid; /* Rauth */ 27 | u32int afid; /* Tauth, Tattach */ 28 | char *uname; /* Tauth, Tattach */ 29 | char *aname; /* Tauth, Tattach */ 30 | u32int perm; /* Tcreate */ 31 | char *name; /* Tcreate */ 32 | uchar mode; /* Tcreate, Topen */ 33 | u32int newfid; /* Twalk */ 34 | ushort nwname; /* Twalk */ 35 | char *wname[MAXWELEM]; /* Twalk */ 36 | ushort nwqid; /* Rwalk */ 37 | Qid wqid[MAXWELEM]; /* Rwalk */ 38 | vlong offset; /* Tread, Twrite */ 39 | u32int count; /* Tread, Twrite, Rread */ 40 | char *data; /* Twrite, Rread */ 41 | ushort nstat; /* Twstat, Rstat */ 42 | uchar *stat; /* Twstat, Rstat */ 43 | int unixfd; /* Ropenfd */ 44 | 45 | /* 9P2000.u extensions */ 46 | int errornum; /* Rerror */ 47 | int uidnum; /* Tattach, Tauth */ 48 | char *extension; /* Tcreate */ 49 | } Fcall; 50 | 51 | 52 | #define GBIT8(p) ((p)[0]) 53 | #define GBIT16(p) ((p)[0]|((p)[1]<<8)) 54 | #define GBIT32(p) ((u32int)((p)[0]|((p)[1]<<8)|((p)[2]<<16)|((p)[3]<<24))) 55 | #define GBIT64(p) ((u32int)((p)[0]|((p)[1]<<8)|((p)[2]<<16)|((p)[3]<<24)) |\ 56 | ((vlong)((p)[4]|((p)[5]<<8)|((p)[6]<<16)|((p)[7]<<24)) << 32)) 57 | 58 | #define PBIT8(p,v) (p)[0]=(v) 59 | #define PBIT16(p,v) (p)[0]=(v);(p)[1]=(v)>>8 60 | #define PBIT32(p,v) (p)[0]=(v);(p)[1]=(v)>>8;(p)[2]=(v)>>16;(p)[3]=(v)>>24 61 | #define PBIT64(p,v) (p)[0]=(v);(p)[1]=(v)>>8;(p)[2]=(v)>>16;(p)[3]=(v)>>24;\ 62 | (p)[4]=(v)>>32;(p)[5]=(v)>>40;(p)[6]=(v)>>48;(p)[7]=(v)>>56 63 | 64 | #define BIT8SZ 1 65 | #define BIT16SZ 2 66 | #define BIT32SZ 4 67 | #define BIT64SZ 8 68 | #define QIDSZ (BIT8SZ+BIT32SZ+BIT64SZ) 69 | 70 | /* STATFIXLEN includes leading 16-bit count */ 71 | /* The count, however, excludes itself; total size is BIT16SZ+count */ 72 | #define STATFIXLEN (BIT16SZ+QIDSZ+5*BIT16SZ+4*BIT32SZ+1*BIT64SZ) /* amount of fixed length data in a stat buffer */ 73 | #define STATFIXLENU (STATFIXLEN+BIT16SZ+3*BIT32SZ) /* for 9P2000.u */ 74 | 75 | #define NOTAG (ushort)~0U /* Dummy tag */ 76 | #define NOFID (u32int)~0U /* Dummy fid */ 77 | #define NOUID (-1) /* Dummy uid */ 78 | #define IOHDRSZ 24 /* ample room for Twrite/Rread header (iounit) */ 79 | 80 | enum 81 | { 82 | Tversion = 100, 83 | Rversion, 84 | Tauth = 102, 85 | Rauth, 86 | Tattach = 104, 87 | Rattach, 88 | Terror = 106, /* illegal */ 89 | Rerror, 90 | Tflush = 108, 91 | Rflush, 92 | Twalk = 110, 93 | Rwalk, 94 | Topen = 112, 95 | Ropen, 96 | Tcreate = 114, 97 | Rcreate, 98 | Tread = 116, 99 | Rread, 100 | Twrite = 118, 101 | Rwrite, 102 | Tclunk = 120, 103 | Rclunk, 104 | Tremove = 122, 105 | Rremove, 106 | Tstat = 124, 107 | Rstat, 108 | Twstat = 126, 109 | Rwstat, 110 | Tmax, 111 | 112 | Topenfd = 98, 113 | Ropenfd 114 | }; 115 | 116 | uint convM2S(uchar*, uint, Fcall*); 117 | uint convS2M(Fcall*, uchar*, uint); 118 | uint sizeS2M(Fcall*); 119 | 120 | int statcheck(uchar *abuf, uint nbuf); 121 | uint convM2D(uchar*, uint, Dir*, char*); 122 | uint convD2M(Dir*, uchar*, uint); 123 | uint sizeD2M(Dir*); 124 | 125 | int fcallfmt(Fmt*); 126 | int dirfmt(Fmt*); 127 | int dirmodefmt(Fmt*); 128 | 129 | int read9pmsg(int, void*, uint); 130 | 131 | /* 132 | #pragma varargck type "F" Fcall* 133 | #pragma varargck type "M" ulong 134 | #pragma varargck type "D" Dir* 135 | */ 136 | 137 | #ifdef __cplusplus 138 | } 139 | #endif 140 | #endif 141 | -------------------------------------------------------------------------------- /compat/libthread/daemonize.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "threadimpl.h" 5 | 6 | #undef waitpid 7 | #undef pipe 8 | #undef wait 9 | 10 | static int sigpid; 11 | static int threadpassfd = -1; 12 | static int gotsigchld; 13 | 14 | static void 15 | child(void) 16 | { 17 | int status, pid; 18 | struct rlimit rl; 19 | 20 | notedisable("sys: child"); 21 | pid = waitpid(sigpid, &status, 0); 22 | if(pid < 0){ 23 | fprint(2, "%s: wait: %r\n", argv0); 24 | _exit(97); 25 | } 26 | if(WIFEXITED(status)) 27 | _exit(WEXITSTATUS(status)); 28 | if(WIFSIGNALED(status)){ 29 | /* 30 | * Make sure we don't scribble over the nice 31 | * core file that our child just wrote out. 32 | */ 33 | rl.rlim_cur = 0; 34 | rl.rlim_max = 0; 35 | setrlimit(RLIMIT_CORE, &rl); 36 | 37 | signal(WTERMSIG(status), SIG_DFL); 38 | raise(WTERMSIG(status)); 39 | _exit(98); /* not reached */ 40 | } 41 | if(WIFSTOPPED(status)){ 42 | fprint(2, "%s: wait pid %d stopped\n", argv0, pid); 43 | return; 44 | } 45 | #ifdef WIFCONTINUED 46 | if(WIFCONTINUED(status)){ 47 | fprint(2, "%s: wait pid %d continued\n", argv0, pid); 48 | return; 49 | } 50 | #endif 51 | fprint(2, "%s: wait pid %d status 0x%ux\n", argv0, pid, status); 52 | _exit(99); 53 | } 54 | 55 | static void 56 | sigpass(int sig) 57 | { 58 | if(sigpid == 1){ 59 | gotsigchld = 1; 60 | return; 61 | } 62 | 63 | if(sig == SIGCHLD) 64 | child(); 65 | else 66 | kill(sigpid, sig); 67 | } 68 | 69 | static int sigs[] = 70 | { 71 | SIGHUP, SIGINT, SIGQUIT, SIGILL, 72 | SIGTRAP, SIGABRT, SIGBUS, SIGFPE, 73 | SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, 74 | SIGALRM, SIGTERM, SIGCHLD, SIGSTOP, 75 | /*SIGTSTP, SIGTTIN, SIGTTOU,*/ SIGURG, 76 | SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, 77 | #ifdef SIGWINCH 78 | SIGWINCH, 79 | #endif 80 | #ifdef SIGIO 81 | SIGIO, 82 | #endif 83 | #ifdef SIGEMT 84 | SIGEMT, 85 | #endif 86 | #ifdef SIGPWR 87 | SIGPWR, 88 | #endif 89 | #ifdef SIGINFO 90 | SIGINFO, 91 | #endif 92 | SIGSYS 93 | }; 94 | 95 | void 96 | _threadsetupdaemonize(void) 97 | { 98 | int i, n, pid; 99 | int p[2]; 100 | char buf[20]; 101 | 102 | sigpid = 1; 103 | 104 | /* 105 | * We've been told this program is likely to background itself. 106 | * Put it in its own process group so that we don't get a SIGHUP 107 | * when the parent exits. 108 | */ 109 | setpgid(0, 0); 110 | 111 | if(pipe(p) < 0) 112 | sysfatal("passer pipe: %r"); 113 | 114 | /* hide these somewhere they won't cause harm */ 115 | /* can't go too high: NetBSD max is 64, for example */ 116 | if(dup(p[0], 28) < 0 || dup(p[1], 29) < 0) 117 | sysfatal("passer pipe dup: %r"); 118 | close(p[0]); 119 | close(p[1]); 120 | p[0] = 28; 121 | p[1] = 29; 122 | 123 | /* close on exec */ 124 | if(fcntl(p[0], F_SETFD, 1) < 0 || fcntl(p[1], F_SETFD, 1) < 0) 125 | sysfatal("passer pipe pipe fcntl: %r"); 126 | 127 | noteenable("sys: child"); 128 | signal(SIGCHLD, sigpass); 129 | switch(pid = fork()){ 130 | case -1: 131 | sysfatal("passer fork: %r"); 132 | default: 133 | close(p[1]); 134 | break; 135 | case 0: 136 | notedisable("sys: child"); 137 | signal(SIGCHLD, SIG_DFL); 138 | /* rfork(RFNOTEG); */ 139 | close(p[0]); 140 | threadpassfd = p[1]; 141 | return; 142 | } 143 | 144 | sigpid = pid; 145 | if(gotsigchld) 146 | sigpass(SIGCHLD); 147 | 148 | for(i=0; i 0) 163 | break; 164 | print("passer read: %r\n"); 165 | } 166 | buf[n] = 0; 167 | _exit(atoi(buf)); 168 | } 169 | 170 | void 171 | _threaddaemonize(void) 172 | { 173 | if(threadpassfd < 0) 174 | sysfatal("threads in main proc exited w/o threadmaybackground"); 175 | write(threadpassfd, "0", 1); 176 | close(threadpassfd); 177 | threadpassfd = -1; 178 | } 179 | -------------------------------------------------------------------------------- /compat/libthread/pthread.c: -------------------------------------------------------------------------------- 1 | #include "threadimpl.h" 2 | 3 | #undef exits 4 | #undef _exits 5 | 6 | static pthread_mutex_t initmutex = PTHREAD_MUTEX_INITIALIZER; 7 | 8 | static void 9 | lockinit(Lock *lk) 10 | { 11 | pthread_mutexattr_t attr; 12 | 13 | pthread_mutex_lock(&initmutex); 14 | if(lk->init == 0){ 15 | pthread_mutexattr_init(&attr); 16 | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); 17 | pthread_mutex_init(&lk->mutex, &attr); 18 | pthread_mutexattr_destroy(&attr); 19 | lk->init = 1; 20 | } 21 | pthread_mutex_unlock(&initmutex); 22 | } 23 | 24 | int 25 | _threadlock(Lock *lk, int block, ulong pc) 26 | { 27 | int r; 28 | 29 | if(!lk->init) 30 | lockinit(lk); 31 | if(block){ 32 | if(pthread_mutex_lock(&lk->mutex) != 0) 33 | abort(); 34 | return 1; 35 | }else{ 36 | r = pthread_mutex_trylock(&lk->mutex); 37 | if(r == 0) 38 | return 1; 39 | if(r == EBUSY) 40 | return 0; 41 | abort(); 42 | return 0; 43 | } 44 | } 45 | 46 | void 47 | _threadunlock(Lock *lk, ulong pc) 48 | { 49 | if(pthread_mutex_unlock(&lk->mutex) != 0) 50 | abort(); 51 | } 52 | 53 | /* note: _procsleep can have spurious wakeups, like pthread_cond_wait */ 54 | void 55 | _procsleep(_Procrendez *r) 56 | { 57 | /* r is protected by r->l, which we hold */ 58 | pthread_cond_init(&r->cond, 0); 59 | r->asleep = 1; 60 | if(pthread_cond_wait(&r->cond, &r->l->mutex) != 0) 61 | sysfatal("pthread_cond_wait: %r"); 62 | pthread_cond_destroy(&r->cond); 63 | r->asleep = 0; 64 | } 65 | 66 | void 67 | _procwakeup(_Procrendez *r) 68 | { 69 | if(r->asleep){ 70 | r->asleep = 0; 71 | pthread_cond_signal(&r->cond); 72 | } 73 | } 74 | 75 | void 76 | _procwakeupandunlock(_Procrendez *r) 77 | { 78 | if(r->asleep){ 79 | r->asleep = 0; 80 | pthread_cond_signal(&r->cond); 81 | } 82 | unlock(r->l); 83 | } 84 | 85 | static void 86 | startprocfn(void *v) 87 | { 88 | void **a; 89 | void (*fn)(void*); 90 | Proc *p; 91 | 92 | a = (void**)v; 93 | fn = (void(*)(void*))a[0]; 94 | p = a[1]; 95 | free(a); 96 | p->osprocid = pthread_self(); 97 | pthread_detach(p->osprocid); 98 | 99 | (*fn)(p); 100 | 101 | pthread_exit(0); 102 | } 103 | 104 | static void 105 | startpthreadfn(void *v) 106 | { 107 | void **a; 108 | Proc *p; 109 | _Thread *t; 110 | 111 | a = (void**)v; 112 | p = a[0]; 113 | t = a[1]; 114 | free(a); 115 | t->osprocid = pthread_self(); 116 | pthread_detach(t->osprocid); 117 | _threadpthreadmain(p, t); 118 | pthread_exit(0); 119 | } 120 | 121 | void 122 | _procstart(Proc *p, void (*fn)(Proc*)) 123 | { 124 | void **a; 125 | 126 | a = malloc(2*sizeof a[0]); 127 | if(a == nil) 128 | sysfatal("_procstart malloc: %r"); 129 | a[0] = (void*)fn; 130 | a[1] = p; 131 | 132 | if(pthread_create(&p->osprocid, nil, (void*(*)(void*))startprocfn, (void*)a) < 0){ 133 | fprint(2, "pthread_create: %r\n"); 134 | abort(); 135 | } 136 | } 137 | 138 | void 139 | _threadpthreadstart(Proc *p, _Thread *t) 140 | { 141 | void **a; 142 | 143 | a = malloc(3*sizeof a[0]); 144 | if(a == nil) 145 | sysfatal("_pthreadstart malloc: %r"); 146 | a[0] = p; 147 | a[1] = t; 148 | if(pthread_create(&t->osprocid, nil, (void*(*)(void*))startpthreadfn, (void*)a) < 0){ 149 | fprint(2, "pthread_create: %r\n"); 150 | abort(); 151 | } 152 | } 153 | 154 | static pthread_key_t prockey; 155 | 156 | Proc* 157 | _threadproc(void) 158 | { 159 | Proc *p; 160 | 161 | p = pthread_getspecific(prockey); 162 | return p; 163 | } 164 | 165 | void 166 | _threadsetproc(Proc *p) 167 | { 168 | pthread_setspecific(prockey, p); 169 | } 170 | 171 | void 172 | _pthreadinit(void) 173 | { 174 | static struct utsname un; 175 | pthread_t id; 176 | 177 | if(uname(&un) < 0) 178 | fprint(2, "warning: uname failed: %r\n"); 179 | if(strcmp(un.sysname, "Linux") == 0){ 180 | /* 181 | * Want to distinguish between the old LinuxThreads pthreads 182 | * and the new NPTL implementation. NPTL uses much bigger 183 | * thread IDs. 184 | */ 185 | id = pthread_self(); 186 | if(*(ulong*)(void*)&id < 1024*1024) 187 | sysfatal("cannot use LinuxThreads as pthread library; see %s/src/libthread/README.Linux", get9root()); 188 | } 189 | pthread_key_create(&prockey, 0); 190 | } 191 | 192 | void 193 | threadexitsall(char *msg) 194 | { 195 | exits(msg); 196 | } 197 | 198 | void 199 | _threadpexit(void) 200 | { 201 | pthread_exit(0); 202 | } 203 | -------------------------------------------------------------------------------- /compat/fmt.h: -------------------------------------------------------------------------------- 1 | #ifndef _FMT_H_ 2 | #define _FMT_H_ 1 3 | #if defined(__cplusplus) 4 | extern "C" { 5 | #endif 6 | /* 7 | * The authors of this software are Rob Pike and Ken Thompson. 8 | * Copyright (c) 2002 by Lucent Technologies. 9 | * Permission to use, copy, modify, and distribute this software for any 10 | * purpose without fee is hereby granted, provided that this entire notice 11 | * is included in all copies of any software which is or includes a copy 12 | * or modification of this software and in all copies of the supporting 13 | * documentation for such software. 14 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 15 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY 16 | * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY 17 | * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | typedef struct Fmt Fmt; 24 | struct Fmt{ 25 | unsigned char runes; /* output buffer is runes or chars? */ 26 | void *start; /* of buffer */ 27 | void *to; /* current place in the buffer */ 28 | void *stop; /* end of the buffer; overwritten if flush fails */ 29 | int (*flush)(Fmt *); /* called when to == stop */ 30 | void *farg; /* to make flush a closure */ 31 | int nfmt; /* num chars formatted so far */ 32 | va_list args; /* args passed to dofmt */ 33 | Rune r; /* % format Rune */ 34 | int width; 35 | int prec; 36 | unsigned long flags; 37 | char *decimal; /* decimal point; cannot be "" */ 38 | 39 | /* For %'d */ 40 | char *thousands; /* separator for thousands */ 41 | 42 | /* 43 | * Each char is an integer indicating #digits before next separator. Values: 44 | * \xFF: no more grouping (or \x7F; defined to be CHAR_MAX in POSIX) 45 | * \x00: repeat previous indefinitely 46 | * \x**: count that many 47 | */ 48 | char *grouping; /* descriptor of separator placement */ 49 | }; 50 | 51 | enum{ 52 | FmtWidth = 1, 53 | FmtLeft = FmtWidth << 1, 54 | FmtPrec = FmtLeft << 1, 55 | FmtSharp = FmtPrec << 1, 56 | FmtSpace = FmtSharp << 1, 57 | FmtSign = FmtSpace << 1, 58 | FmtApost = FmtSign << 1, 59 | FmtZero = FmtApost << 1, 60 | FmtUnsigned = FmtZero << 1, 61 | FmtShort = FmtUnsigned << 1, 62 | FmtLong = FmtShort << 1, 63 | FmtVLong = FmtLong << 1, 64 | FmtComma = FmtVLong << 1, 65 | FmtByte = FmtComma << 1, 66 | FmtLDouble = FmtByte << 1, 67 | 68 | FmtFlag = FmtLDouble << 1 69 | }; 70 | 71 | extern int (*fmtdoquote)(int); 72 | 73 | /* Edit .+1,/^$/ | cfn $PLAN9/src/lib9/fmt/?*.c | grep -v static |grep -v __ */ 74 | int dofmt(Fmt *f, char *fmt); 75 | int dorfmt(Fmt *f, const Rune *fmt); 76 | double fmtcharstod(int(*f)(void*), void *vp); 77 | int fmtfdflush(Fmt *f); 78 | int fmtfdinit(Fmt *f, int fd, char *buf, int size); 79 | int fmtinstall(int c, int (*f)(Fmt*)); 80 | int fmtnullinit(Fmt*); 81 | void fmtlocaleinit(Fmt*, char*, char*, char*); 82 | int fmtprint(Fmt *f, char *fmt, ...); 83 | int fmtrune(Fmt *f, int r); 84 | int fmtrunestrcpy(Fmt *f, Rune *s); 85 | int fmtstrcpy(Fmt *f, char *s); 86 | char* fmtstrflush(Fmt *f); 87 | int fmtstrinit(Fmt *f); 88 | double fmtstrtod(const char *as, char **aas); 89 | int fmtvprint(Fmt *f, char *fmt, va_list args); 90 | int fprint(int fd, char *fmt, ...); 91 | int print(char *fmt, ...); 92 | void quotefmtinstall(void); 93 | int quoterunestrfmt(Fmt *f); 94 | int quotestrfmt(Fmt *f); 95 | Rune* runefmtstrflush(Fmt *f); 96 | int runefmtstrinit(Fmt *f); 97 | Rune* runeseprint(Rune *buf, Rune *e, char *fmt, ...); 98 | Rune* runesmprint(char *fmt, ...); 99 | int runesnprint(Rune *buf, int len, char *fmt, ...); 100 | int runesprint(Rune *buf, char *fmt, ...); 101 | Rune* runevseprint(Rune *buf, Rune *e, char *fmt, va_list args); 102 | Rune* runevsmprint(char *fmt, va_list args); 103 | int runevsnprint(Rune *buf, int len, char *fmt, va_list args); 104 | char* seprint(char *buf, char *e, char *fmt, ...); 105 | char* smprint(char *fmt, ...); 106 | int snprint(char *buf, int len, char *fmt, ...); 107 | int sprint(char *buf, char *fmt, ...); 108 | int vfprint(int fd, char *fmt, va_list args); 109 | char* vseprint(char *buf, char *e, char *fmt, va_list args); 110 | char* vsmprint(char *fmt, va_list args); 111 | int vsnprint(char *buf, int len, char *fmt, va_list args); 112 | 113 | #if defined(__cplusplus) 114 | } 115 | #endif 116 | #endif 117 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('9pfuse', 'c', 2 | meson_version: '>=0.53', 3 | default_options: [ 4 | 'buildtype=debugoptimized', 5 | 'b_ndebug=if-release', 6 | 'c_std=c11', 7 | ], 8 | version: '2', 9 | ) 10 | 11 | add_project_arguments('-DPLAN9_TARGET="@0@"'.format(get_option('prefix')), language: 'c') 12 | 13 | cc = meson.get_compiler('c') 14 | add_project_arguments(cc.get_supported_arguments( 15 | '-fcommon', 16 | '-Wno-dangling-else', 17 | '-Wno-missing-braces', 18 | '-Wno-parentheses', 19 | ), 20 | language: 'c', 21 | ) 22 | 23 | extra_sources = [] 24 | getcallerpc_clang_gcc_check = ''' 25 | #if defined(__GNUC__) || defined(__clang__) || defined(__IBMC__) 26 | int main(int argc, char **argv) { return (int) __builtin_return_address(0); } 27 | #else 28 | # error No built-in implementation 29 | #endif 30 | ''' 31 | 32 | if not cc.compiles(getcallerpc_clang_gcc_check) 33 | if target_machine.cpu_family() == 'x86_64' 34 | getcallerpc_impl = 'x86_64' 35 | elif target_machine.cpu_family() == 'x86' 36 | getcallerpc_impl = '386' 37 | elif target_machine.cpu_family() == 'arm' 38 | # Might work on aarch64, but it was not yet tested. 39 | getcallerpc_impl = 'arm' 40 | elif target_machine.cpu_family() == 'ppc' 41 | # Might work on ppc64, but it was not yet tested. 42 | getcallerpc_impl = 'power' 43 | else 44 | error('Target architecture unsupported: @0@'.format(target_machine.cpu_family())) 45 | endif 46 | extra_sources += ['compat/lib9/md/getcallerpc-@0@.c'.format(getcallerpc_impl)] 47 | endif 48 | 49 | executable('9pfuse', 50 | 'errstr.c', 51 | 'fuse.c', 52 | 'main.c', 53 | 'main_p9main.c', 54 | 'compat/fmt/dofmt.c', 55 | 'compat/fmt/fltfmt.c', 56 | 'compat/fmt/fmt.c', 57 | 'compat/fmt/fmtfd.c', 58 | 'compat/fmt/fmtfdflush.c', 59 | 'compat/fmt/fmtlocale.c', 60 | 'compat/fmt/fmtlock.c', 61 | 'compat/fmt/fmtprint.c', 62 | 'compat/fmt/fmtquote.c', 63 | 'compat/fmt/fmtstr.c', 64 | 'compat/fmt/fprint.c', 65 | 'compat/fmt/nan64.c', 66 | 'compat/fmt/print.c', 67 | 'compat/fmt/seprint.c', 68 | 'compat/fmt/smprint.c', 69 | 'compat/fmt/snprint.c', 70 | 'compat/fmt/sprint.c', 71 | 'compat/fmt/strtod.c', 72 | 'compat/fmt/vfprint.c', 73 | 'compat/fmt/vseprint.c', 74 | 'compat/fmt/vsmprint.c', 75 | 'compat/fmt/vsnprint.c', 76 | 'compat/lib9/argv0.c', 77 | 'compat/lib9/atexit.c', 78 | 'compat/lib9/atnotify.c', 79 | 'compat/lib9/atoi.c', 80 | 'compat/lib9/await.c', 81 | 'compat/lib9/cistrncmp.c', 82 | 'compat/lib9/cistrstr.c', 83 | 'compat/lib9/convD2M.c', 84 | 'compat/lib9/convM2D.c', 85 | 'compat/lib9/convM2S.c', 86 | 'compat/lib9/convS2M.c', 87 | 'compat/lib9/dial.c', 88 | 'compat/lib9/dirmodefmt.c', 89 | 'compat/lib9/dup.c', 90 | 'compat/lib9/errstr.c', 91 | 'compat/lib9/exitcode.c', 92 | 'compat/lib9/fcallfmt.c', 93 | 'compat/lib9/get9root.c', 94 | 'compat/lib9/getenv.c', 95 | 'compat/lib9/getuser.c', 96 | 'compat/lib9/jmp.c', 97 | 'compat/lib9/malloc.c', 98 | 'compat/lib9/mallocz.c', 99 | 'compat/lib9/netmkaddr.c', 100 | 'compat/lib9/notify.c', 101 | 'compat/lib9/nulldir.c', 102 | 'compat/lib9/open.c', 103 | 'compat/lib9/_p9dialparse.c', 104 | 'compat/lib9/_p9dir.c', 105 | 'compat/lib9pclient/close.c', 106 | 'compat/lib9pclient/create.c', 107 | 'compat/lib9pclient/dirread.c', 108 | 'compat/lib9pclient/fs.c', 109 | 'compat/lib9pclient/open.c', 110 | 'compat/lib9pclient/read.c', 111 | 'compat/lib9pclient/seek.c', 112 | 'compat/lib9pclient/stat.c', 113 | 'compat/lib9pclient/walk.c', 114 | 'compat/lib9pclient/write.c', 115 | 'compat/lib9pclient/wstat.c', 116 | 'compat/lib9/pin.c', 117 | 'compat/lib9/qlock.c', 118 | 'compat/lib9/read9pmsg.c', 119 | 'compat/lib9/readn.c', 120 | 'compat/lib9/sendfd.c', 121 | 'compat/lib9/sleep.c', 122 | 'compat/lib9/strdup.c', 123 | 'compat/lib9/strecpy.c', 124 | 'compat/lib9/sysfatal.c', 125 | 'compat/lib9/tokenize.c', 126 | 'compat/lib9/waitpid.c', 127 | 'compat/lib9/write.c', 128 | 'compat/libmux/io.c', 129 | 'compat/libmux/mux.c', 130 | 'compat/libmux/queue.c', 131 | 'compat/libthread/channel.c', 132 | 'compat/libthread/daemonize.c', 133 | 'compat/libthread/ioproc.c', 134 | 'compat/libthread/iorw.c', 135 | 'compat/libthread/pthread.c', 136 | 'compat/libthread/ref.c', 137 | 'compat/libthread/thread.c', 138 | 'compat/utf/rune.c', 139 | 'compat/utf/utfecpy.c', 140 | 'compat/utf/utflen.c', 141 | 'compat/utf/utfnlen.c', 142 | 'compat/utf/utfrune.c', 143 | 'compat/lrand.c', 144 | 'compat/rand.c', 145 | extra_sources, 146 | dependencies: [ 147 | dependency('fuse'), 148 | dependency('threads'), 149 | ], 150 | include_directories: include_directories('compat'), 151 | install: true, 152 | ) 153 | 154 | install_man('9pfuse.4') 155 | -------------------------------------------------------------------------------- /compat/thread.h: -------------------------------------------------------------------------------- 1 | #ifndef _THREAD_H_ 2 | #define _THREAD_H_ 1 3 | #if defined(__cplusplus) 4 | extern "C" { 5 | #endif 6 | 7 | AUTOLIB(thread) 8 | 9 | /* 10 | * basic procs and threads 11 | */ 12 | int proccreate(void (*f)(void *arg), void *arg, unsigned int stacksize); 13 | int threadcreate(void (*f)(void *arg), void *arg, unsigned int stacksize); 14 | void threadexits(char *); 15 | void threadexitsall(char *); 16 | void threadsetname(char*, ...); 17 | void threadsetstate(char*, ...); 18 | void threadneedbackground(void); 19 | char *threadgetname(void); 20 | int threadyield(void); 21 | int threadidle(void); 22 | void _threadready(_Thread*); 23 | void _threadswitch(void); 24 | void _threadsetsysproc(void); 25 | void _threadsleep(Rendez*); 26 | _Thread *_threadwakeup(Rendez*); 27 | #define yield threadyield 28 | int threadid(void); 29 | void _threadpin(void); 30 | void _threadunpin(void); 31 | 32 | /* 33 | * I am tired of making this mistake. 34 | */ 35 | #define exits do_not_call_exits_in_threaded_programs 36 | #define _exits do_not_call__exits_in_threaded_programs 37 | 38 | 39 | 40 | /* 41 | * signals 42 | */ 43 | void threadnotify(int(*f)(void*,char*), int); 44 | 45 | /* 46 | * daemonize 47 | * 48 | void threaddaemonize(void); 49 | */ 50 | 51 | /* 52 | * per proc and thread data 53 | */ 54 | void **procdata(void); 55 | void **threaddata(void); 56 | 57 | /* 58 | * supplied by user instead of main. 59 | * mainstacksize is size of stack allocated to run threadmain 60 | */ 61 | void threadmain(int argc, char *argv[]); 62 | extern int mainstacksize; 63 | 64 | int threadmaybackground(void); 65 | 66 | /* 67 | * channel communication 68 | */ 69 | typedef struct Alt Alt; 70 | typedef struct _Altarray _Altarray; 71 | typedef struct Channel Channel; 72 | 73 | enum 74 | { 75 | CHANEND, 76 | CHANSND, 77 | CHANRCV, 78 | CHANNOP, 79 | CHANNOBLK 80 | }; 81 | 82 | struct Alt 83 | { 84 | Channel *c; 85 | void *v; 86 | uint op; 87 | _Thread *thread; 88 | }; 89 | 90 | struct _Altarray 91 | { 92 | Alt **a; 93 | uint n; 94 | uint m; 95 | }; 96 | 97 | struct Channel 98 | { 99 | uint bufsize; 100 | uint elemsize; 101 | uchar *buf; 102 | uint nbuf; 103 | uint off; 104 | _Altarray asend; 105 | _Altarray arecv; 106 | char *name; 107 | }; 108 | 109 | /* [Edit .+1,./^$/ |cfn -h $PLAN9/src/libthread/channel.c] */ 110 | int chanalt(Alt *alts); 111 | Channel* chancreate(int elemsize, int elemcnt); 112 | void chanfree(Channel *c); 113 | int channbrecv(Channel *c, void *v); 114 | void* channbrecvp(Channel *c); 115 | ulong channbrecvul(Channel *c); 116 | int channbsend(Channel *c, void *v); 117 | int channbsendp(Channel *c, void *v); 118 | int channbsendul(Channel *c, ulong v); 119 | int chanrecv(Channel *c, void *v); 120 | void* chanrecvp(Channel *c); 121 | ulong chanrecvul(Channel *c); 122 | int chansend(Channel *c, void *v); 123 | int chansendp(Channel *c, void *v); 124 | int chansendul(Channel *c, ulong v); 125 | void chansetname(Channel *c, char *fmt, ...); 126 | 127 | #define alt chanalt 128 | #define nbrecv channbrecv 129 | #define nbrecvp channbrecvp 130 | #define nbrecvul channbrecvul 131 | #define nbsend channbsend 132 | #define nbsendp channbsendp 133 | #define nbsendul channbsendul 134 | #define recv chanrecv 135 | #define recvp chanrecvp 136 | #define recvul chanrecvul 137 | #define send chansend 138 | #define sendp chansendp 139 | #define sendul chansendul 140 | 141 | /* 142 | * reference counts 143 | */ 144 | typedef struct Ref Ref; 145 | 146 | struct Ref { 147 | Lock lock; 148 | long ref; 149 | }; 150 | 151 | long decref(Ref *r); 152 | long incref(Ref *r); 153 | 154 | /* 155 | * slave i/o processes 156 | */ 157 | typedef struct Ioproc Ioproc; 158 | 159 | /* [Edit .+1,/^$/ |cfn -h $PLAN9/src/libthread/io*.c] */ 160 | void closeioproc(Ioproc *io); 161 | long iocall(Ioproc *io, long (*op)(va_list*), ...); 162 | int ioclose(Ioproc *io, int fd); 163 | int iodial(Ioproc *io, char *addr, char *local, char *dir, int *cdfp); 164 | void iointerrupt(Ioproc *io); 165 | int ioopen(Ioproc *io, char *path, int mode); 166 | Ioproc* ioproc(void); 167 | long ioread(Ioproc *io, int fd, void *a, long n); 168 | int ioread9pmsg(Ioproc*, int, void*, int); 169 | long ioreadn(Ioproc *io, int fd, void *a, long n); 170 | int iorecvfd(Ioproc *, int); 171 | int iosendfd(Ioproc*, int, int); 172 | int iosleep(Ioproc *io, long n); 173 | long iowrite(Ioproc *io, int fd, void *a, long n); 174 | 175 | /* 176 | * exec external programs 177 | */ 178 | void threadexec(Channel*, int[3], char*, char *[]); 179 | void threadexecl(Channel*, int[3], char*, ...); 180 | int threadspawn(int[3], char*, char*[]); 181 | int threadspawnd(int[3], char*, char*[], char*); 182 | int threadspawnl(int[3], char*, ...); 183 | Channel* threadwaitchan(void); 184 | 185 | /* 186 | * alternate interface to threadwaitchan - don't use both! 187 | */ 188 | Waitmsg* procwait(int pid); 189 | 190 | #if defined(__cplusplus) 191 | } 192 | #endif 193 | #endif /* _THREADH_ */ 194 | -------------------------------------------------------------------------------- /compat/lib9/_p9dialparse.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define NOPLAN9DEFINES 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | static char *nets[] = { "tcp", "udp", nil }; 12 | #define CLASS(p) ((*(uchar*)(p))>>6) 13 | 14 | static struct { 15 | char *net; 16 | char *service; 17 | int port; 18 | } porttbl[] = { 19 | "tcp", "9fs", 564, 20 | "tcp", "whoami", 565, 21 | "tcp", "guard", 566, 22 | "tcp", "ticket", 567, 23 | "tcp", "exportfs", 17007, 24 | "tcp", "rexexec", 17009, 25 | "tcp", "ncpu", 17010, 26 | "tcp", "cpu", 17013, 27 | "tcp", "venti", 17034, 28 | "tcp", "wiki", 17035, 29 | "tcp", "secstore", 5356, 30 | "udp", "dns", 53, 31 | "tcp", "dns", 53, 32 | }; 33 | 34 | static int 35 | setport(struct sockaddr_storage *ss, int port) 36 | { 37 | switch(ss->ss_family){ 38 | case AF_INET: 39 | ((struct sockaddr_in*)ss)->sin_port = htons(port); 40 | break; 41 | case AF_INET6: 42 | ((struct sockaddr_in6*)ss)->sin6_port = htons(port); 43 | break; 44 | default: 45 | errstr("unknown protocol family %d", ss->ss_family); 46 | return -1; 47 | } 48 | return 0; 49 | } 50 | 51 | int 52 | p9dialparse(char *addr, char **pnet, char **punix, void *phost, int *pport) 53 | { 54 | char *net, *host, *port, *e; 55 | int i; 56 | struct servent *se; 57 | struct hostent *he; 58 | struct sockaddr_storage *ss; 59 | struct addrinfo *result; 60 | 61 | ss = phost; 62 | 63 | memset(ss, 0, sizeof *ss); 64 | 65 | *punix = nil; 66 | net = addr; 67 | if((host = strchr(net, '!')) == nil){ 68 | werrstr("malformed address"); 69 | return -1; 70 | } 71 | *host++ = 0; 72 | if((port = strchr(host, '!')) == nil){ 73 | if(strcmp(net, "unix")==0 || strcmp(net, "net")==0){ 74 | Unix: 75 | if(strlen(host)+1 > sizeof ((struct sockaddr_un*)ss)->sun_path){ 76 | werrstr("unix socket name too long"); 77 | return -1; 78 | } 79 | *punix = host; 80 | *pnet = "unix"; 81 | ss->ss_family = AF_UNIX; 82 | strcpy(((struct sockaddr_un*)ss)->sun_path, host); 83 | *pport = 0; 84 | return 0; 85 | } 86 | werrstr("malformed address"); 87 | return -1; 88 | } 89 | *port++ = 0; 90 | 91 | if(*host == 0){ 92 | werrstr("malformed address (empty host)"); 93 | return -1; 94 | } 95 | if(*port == 0){ 96 | werrstr("malformed address (empty port)"); 97 | return -1; 98 | } 99 | 100 | if(strcmp(net, "unix") == 0) 101 | goto Unix; 102 | 103 | if(strcmp(net, "tcp")!=0 && strcmp(net, "udp")!=0 && strcmp(net, "net") != 0){ 104 | werrstr("bad network %s!%s!%s", net, host, port); 105 | return -1; 106 | } 107 | 108 | /* translate host */ 109 | if(strcmp(host, "*") == 0){ 110 | ss->ss_family = AF_INET6; 111 | ((struct sockaddr_in6*)ss)->sin6_addr = in6addr_any; 112 | }else if((he = gethostbyname(host)) != nil && he->h_addr_list[0] != nil){ 113 | ss->ss_family = he->h_addrtype; 114 | switch(ss->ss_family){ 115 | case AF_INET: 116 | ((struct sockaddr_in*)ss)->sin_addr = *(struct in_addr*) *(he->h_addr_list); 117 | break; 118 | case AF_INET6: 119 | ((struct sockaddr_in6*)ss)->sin6_addr = *(struct in6_addr*) *(he->h_addr_list); 120 | break; 121 | default: 122 | errstr("unknown protocol family %d", ss->ss_family); 123 | return -1; 124 | } 125 | }else if(getaddrinfo(host, NULL, NULL, &result) == 0) { 126 | switch (result->ai_family) { 127 | case AF_INET: 128 | memmove((struct sockaddr_in*)ss, result->ai_addr, result->ai_addrlen); 129 | break; 130 | case AF_INET6: 131 | memmove((struct sockaddr_in6*)ss, result->ai_addr, result->ai_addrlen); 132 | break; 133 | default: 134 | errstr("unknown protocol family %d", ss->ss_family); 135 | return -1; 136 | } 137 | }else{ 138 | werrstr("unknown host %s", host); 139 | return -1; 140 | } 141 | 142 | /* translate network and port; should return list rather than first */ 143 | if(strcmp(net, "net") == 0){ 144 | for(i=0; nets[i]; i++){ 145 | if((se = getservbyname(port, nets[i])) != nil){ 146 | *pnet = nets[i]; 147 | *pport = ntohs(se->s_port); 148 | return setport(ss, *pport); 149 | } 150 | } 151 | } 152 | 153 | for(i=0; is_port); 181 | return setport(ss, *pport); 182 | } 183 | werrstr("unknown service %s!*!%s", net, port); 184 | return -1; 185 | } 186 | -------------------------------------------------------------------------------- /compat/utf/rune.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The authors of this software are Rob Pike and Ken Thompson. 3 | * Copyright (c) 2002 by Lucent Technologies. 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose without fee is hereby granted, provided that this entire notice 6 | * is included in all copies of any software which is or includes a copy 7 | * or modification of this software and in all copies of the supporting 8 | * documentation for such software. 9 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 10 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE 11 | * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY 12 | * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 13 | */ 14 | #include 15 | #include 16 | #include "plan9.h" 17 | #include "utf.h" 18 | 19 | enum 20 | { 21 | Bit1 = 7, 22 | Bitx = 6, 23 | Bit2 = 5, 24 | Bit3 = 4, 25 | Bit4 = 3, 26 | Bit5 = 2, 27 | 28 | T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */ 29 | Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */ 30 | T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */ 31 | T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */ 32 | T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */ 33 | T5 = ((1<<(Bit5+1))-1) ^ 0xFF, /* 1111 1000 */ 34 | 35 | Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0000 0000 0111 1111 */ 36 | Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0000 0000 0111 1111 1111 */ 37 | Rune3 = (1<<(Bit3+2*Bitx))-1, /* 0000 0000 1111 1111 1111 1111 */ 38 | Rune4 = (1<<(Bit4+3*Bitx))-1, /* 0011 1111 1111 1111 1111 1111 */ 39 | 40 | Maskx = (1< T1 55 | */ 56 | c = *(uchar*)str; 57 | if(c < Tx) { 58 | *rune = c; 59 | return 1; 60 | } 61 | 62 | /* 63 | * two character sequence 64 | * 0080-07FF => T2 Tx 65 | */ 66 | c1 = *(uchar*)(str+1) ^ Tx; 67 | if(c1 & Testx) 68 | goto bad; 69 | if(c < T3) { 70 | if(c < T2) 71 | goto bad; 72 | l = ((c << Bitx) | c1) & Rune2; 73 | if(l <= Rune1) 74 | goto bad; 75 | *rune = l; 76 | return 2; 77 | } 78 | 79 | /* 80 | * three character sequence 81 | * 0800-FFFF => T3 Tx Tx 82 | */ 83 | c2 = *(uchar*)(str+2) ^ Tx; 84 | if(c2 & Testx) 85 | goto bad; 86 | if(c < T4) { 87 | l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3; 88 | if(l <= Rune2) 89 | goto bad; 90 | *rune = l; 91 | return 3; 92 | } 93 | 94 | /* 95 | * four character sequence 96 | * 10000-10FFFF => T4 Tx Tx Tx 97 | */ 98 | if(UTFmax >= 4) { 99 | c3 = *(uchar*)(str+3) ^ Tx; 100 | if(c3 & Testx) 101 | goto bad; 102 | if(c < T5) { 103 | l = ((((((c << Bitx) | c1) << Bitx) | c2) << Bitx) | c3) & Rune4; 104 | if(l <= Rune3) 105 | goto bad; 106 | if(l > Runemax) 107 | goto bad; 108 | *rune = l; 109 | return 4; 110 | } 111 | } 112 | 113 | /* 114 | * bad decoding 115 | */ 116 | bad: 117 | *rune = Bad; 118 | return 1; 119 | } 120 | 121 | int 122 | runetochar(char *str, Rune *rune) 123 | { 124 | long c; 125 | 126 | /* 127 | * one character sequence 128 | * 00000-0007F => 00-7F 129 | */ 130 | c = *rune; 131 | if(c <= Rune1) { 132 | str[0] = c; 133 | return 1; 134 | } 135 | 136 | /* 137 | * two character sequence 138 | * 00080-007FF => T2 Tx 139 | */ 140 | if(c <= Rune2) { 141 | str[0] = T2 | (c >> 1*Bitx); 142 | str[1] = Tx | (c & Maskx); 143 | return 2; 144 | } 145 | 146 | /* 147 | * three character sequence 148 | * 00800-0FFFF => T3 Tx Tx 149 | */ 150 | if(c > Runemax) 151 | c = Runeerror; 152 | if(c <= Rune3) { 153 | str[0] = T3 | (c >> 2*Bitx); 154 | str[1] = Tx | ((c >> 1*Bitx) & Maskx); 155 | str[2] = Tx | (c & Maskx); 156 | return 3; 157 | } 158 | 159 | /* 160 | * four character sequence 161 | * 010000-1FFFFF => T4 Tx Tx Tx 162 | */ 163 | str[0] = T4 | (c >> 3*Bitx); 164 | str[1] = Tx | ((c >> 2*Bitx) & Maskx); 165 | str[2] = Tx | ((c >> 1*Bitx) & Maskx); 166 | str[3] = Tx | (c & Maskx); 167 | return 4; 168 | } 169 | 170 | int 171 | runelen(long c) 172 | { 173 | Rune rune; 174 | char str[10]; 175 | 176 | rune = c; 177 | return runetochar(str, &rune); 178 | } 179 | 180 | int 181 | runenlen(Rune *r, int nrune) 182 | { 183 | int nb, c; 184 | 185 | nb = 0; 186 | while(nrune--) { 187 | c = *r++; 188 | if(c <= Rune1) 189 | nb++; 190 | else 191 | if(c <= Rune2) 192 | nb += 2; 193 | else 194 | if(c <= Rune3 || c > Runemax) 195 | nb += 3; 196 | else 197 | nb += 4; 198 | } 199 | return nb; 200 | } 201 | 202 | int 203 | fullrune(char *str, int n) 204 | { 205 | int c; 206 | 207 | if(n <= 0) 208 | return 0; 209 | c = *(uchar*)str; 210 | if(c < Tx) 211 | return 1; 212 | if(c < T3) 213 | return n >= 2; 214 | if(UTFmax == 3 || c < T4) 215 | return n >= 3; 216 | return n >= 4; 217 | } 218 | -------------------------------------------------------------------------------- /compat/u.h: -------------------------------------------------------------------------------- 1 | // See ../src/lib9/LICENSE 2 | 3 | #ifndef _U_H_ 4 | #define _U_H_ 1 5 | #if defined(__cplusplus) 6 | extern "C" { 7 | #endif 8 | 9 | #define HAS_SYS_TERMIOS 1 10 | 11 | #define __BSD_VISIBLE 1 /* FreeBSD 5.x */ 12 | #if defined(__sun__) 13 | # define __EXTENSIONS__ 1 /* SunOS */ 14 | # if defined(__SunOS5_6__) || defined(__SunOS5_7__) || defined(__SunOS5_8__) || defined(__SunOS5_9__) || defined(__SunOS5_10__) 15 | /* NOT USING #define __MAKECONTEXT_V2_SOURCE 1 / * SunOS */ 16 | # else 17 | /* What's left? */ 18 | # define __MAKECONTEXT_V2_SOURCE 1 19 | # endif 20 | #endif 21 | #define _BSD_SOURCE 1 22 | #define _NETBSD_SOURCE 1 /* NetBSD */ 23 | #define _SVID_SOURCE 1 24 | #define _DEFAULT_SOURCE 1 25 | #if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__AIX__) 26 | # define _XOPEN_SOURCE 1000 27 | # define _XOPEN_SOURCE_EXTENDED 1 28 | #endif 29 | #if defined(__FreeBSD__) 30 | # include 31 | /* for strtoll */ 32 | # undef __ISO_C_VISIBLE 33 | # define __ISO_C_VISIBLE 1999 34 | # undef __LONG_LONG_SUPPORTED 35 | # define __LONG_LONG_SUPPORTED 36 | #endif 37 | #if defined(__AIX__) 38 | # define _ALL_SOURCE 39 | # undef HAS_SYS_TERMIOS 40 | #endif 41 | #define _LARGEFILE64_SOURCE 1 42 | #define _FILE_OFFSET_BITS 64 43 | 44 | #include 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include /* for tolower */ 56 | 57 | /* 58 | * OS-specific crap 59 | */ 60 | #define _NEEDUCHAR 1 61 | #define _NEEDUSHORT 1 62 | #define _NEEDUINT 1 63 | #define _NEEDULONG 1 64 | 65 | typedef long p9jmp_buf[sizeof(sigjmp_buf)/(sizeof(long))]; 66 | 67 | #if defined(__linux__) 68 | # include 69 | # include 70 | # if defined(__USE_MISC) 71 | # undef _NEEDUSHORT 72 | # undef _NEEDUINT 73 | # undef _NEEDULONG 74 | # endif 75 | #elif defined(__sun__) 76 | # include 77 | # include 78 | # undef _NEEDUSHORT 79 | # undef _NEEDUINT 80 | # undef _NEEDULONG 81 | # define nil 0 /* no cast to void* */ 82 | #elif defined(__FreeBSD__) 83 | # include 84 | # include 85 | # include 86 | # if !defined(_POSIX_SOURCE) 87 | # undef _NEEDUSHORT 88 | # undef _NEEDUINT 89 | # endif 90 | #elif defined(__APPLE__) 91 | # include 92 | # include 93 | # if __GNUC__ < 4 94 | # undef _NEEDUSHORT 95 | # undef _NEEDUINT 96 | # endif 97 | # undef _ANSI_SOURCE 98 | # undef _POSIX_C_SOURCE 99 | # undef _XOPEN_SOURCE 100 | # if !defined(NSIG) 101 | # define NSIG 32 102 | # endif 103 | # define _NEEDLL 1 104 | #elif defined(__NetBSD__) 105 | # include 106 | # include 107 | # include 108 | # undef _NEEDUSHORT 109 | # undef _NEEDUINT 110 | # undef _NEEDULONG 111 | #elif defined(__OpenBSD__) 112 | # include 113 | # include 114 | # undef _NEEDUSHORT 115 | # undef _NEEDUINT 116 | # undef _NEEDULONG 117 | #else 118 | /* No idea what system this is -- try some defaults */ 119 | # include 120 | #endif 121 | 122 | #ifndef O_DIRECT 123 | #define O_DIRECT 0 124 | #endif 125 | 126 | typedef signed char schar; 127 | 128 | #ifdef _NEEDUCHAR 129 | typedef unsigned char uchar; 130 | #endif 131 | #ifdef _NEEDUSHORT 132 | typedef unsigned short ushort; 133 | #endif 134 | #ifdef _NEEDUINT 135 | typedef unsigned int uint; 136 | #endif 137 | #ifdef _NEEDULONG 138 | typedef unsigned long ulong; 139 | #endif 140 | typedef unsigned long long uvlong; 141 | typedef long long vlong; 142 | 143 | typedef uvlong u64int; 144 | typedef vlong s64int; 145 | typedef uint8_t u8int; 146 | typedef int8_t s8int; 147 | typedef uint16_t u16int; 148 | typedef int16_t s16int; 149 | typedef uintptr_t uintptr; 150 | typedef intptr_t intptr; 151 | typedef uint u32int; 152 | typedef int s32int; 153 | 154 | typedef u32int uint32; 155 | typedef s32int int32; 156 | typedef u16int uint16; 157 | typedef s16int int16; 158 | typedef u64int uint64; 159 | typedef s64int int64; 160 | typedef u8int uint8; 161 | typedef s8int int8; 162 | 163 | #undef _NEEDUCHAR 164 | #undef _NEEDUSHORT 165 | #undef _NEEDUINT 166 | #undef _NEEDULONG 167 | 168 | /* 169 | * Funny-named symbols to tip off 9l to autolink. 170 | */ 171 | #define AUTOLIB(x) static int __p9l_autolib_ ## x = 1; 172 | #define AUTOFRAMEWORK(x) static int __p9l_autoframework_ ## x = 1; 173 | 174 | /* 175 | * Gcc is too smart for its own good. 176 | */ 177 | #if defined(__GNUC__) 178 | # undef strcmp /* causes way too many warnings */ 179 | # if __GNUC__ >= 4 || (__GNUC__==3 && !defined(__APPLE_CC__)) 180 | # undef AUTOLIB 181 | # define AUTOLIB(x) int __p9l_autolib_ ## x __attribute__ ((weak)); 182 | # undef AUTOFRAMEWORK 183 | # define AUTOFRAMEWORK(x) int __p9l_autoframework_ ## x __attribute__ ((weak)); 184 | # else 185 | # undef AUTOLIB 186 | # define AUTOLIB(x) static int __p9l_autolib_ ## x __attribute__ ((unused)); 187 | # undef AUTOFRAMEWORK 188 | # define AUTOFRAMEWORK(x) static int __p9l_autoframework_ ## x __attribute__ ((unused)); 189 | # endif 190 | #endif 191 | 192 | #if defined(__cplusplus) 193 | } 194 | #endif 195 | #endif 196 | -------------------------------------------------------------------------------- /compat/fmt/fmt.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 | #include 3 | #include 4 | 5 | /* 6 | * As of 2020, older systems like RHEL 6 and AIX still do not have C11 atomics. 7 | * On those systems, make the code use volatile int accesses and hope for the best. 8 | * (Most uses of fmtinstall are not actually racing with calls to print that lookup 9 | * formats. The code used volatile here for years without too many problems, 10 | * even though that's technically racy. A mutex is not OK, because we want to 11 | * be able to call print from signal handlers.) 12 | * 13 | * RHEL is using an old GCC (atomics were added in GCC 4.9). 14 | * AIX is using its own IBM compiler (XL C). 15 | */ 16 | #if __IBMC__ || !__clang__ && __GNUC__ && (__GNUC__ < 4 || (__GNUC__==4 && __GNUC_MINOR__<9)) 17 | #warning not using C11 stdatomic on legacy system 18 | #define _Atomic volatile 19 | #define atomic_load(x) (*(x)) 20 | #define atomic_store(x, y) (*(x)=(y)) 21 | #define ATOMIC_VAR_INIT(x) (x) 22 | #else 23 | #include 24 | #endif 25 | 26 | #include "plan9.h" 27 | #include "fmt.h" 28 | #include "fmtdef.h" 29 | 30 | enum 31 | { 32 | Maxfmt = 128 33 | }; 34 | 35 | typedef struct Convfmt Convfmt; 36 | struct Convfmt 37 | { 38 | int c; 39 | Fmts fmt; 40 | }; 41 | 42 | static struct 43 | { 44 | /* 45 | * lock updates to fmt by calling __fmtlock, __fmtunlock. 46 | * reads can start at nfmt and work backward without 47 | * further locking. later fmtinstalls take priority over earlier 48 | * ones because of the backwards loop. 49 | * once installed, a format is never overwritten. 50 | */ 51 | _Atomic int nfmt; 52 | Convfmt fmt[Maxfmt]; 53 | } fmtalloc = { 54 | #ifdef PLAN9PORT 55 | ATOMIC_VAR_INIT(27), 56 | #else 57 | ATOMIC_VAR_INIT(30), 58 | #endif 59 | { 60 | {' ', __flagfmt}, 61 | {'#', __flagfmt}, 62 | {'%', __percentfmt}, 63 | {'\'', __flagfmt}, 64 | {'+', __flagfmt}, 65 | {',', __flagfmt}, 66 | {'-', __flagfmt}, 67 | {'C', __runefmt}, /* Plan 9 addition */ 68 | {'E', __efgfmt}, 69 | #ifndef PLAN9PORT 70 | {'F', __efgfmt}, /* ANSI only */ 71 | #endif 72 | {'G', __efgfmt}, 73 | #ifndef PLAN9PORT 74 | {'L', __flagfmt}, /* ANSI only */ 75 | #endif 76 | {'S', __runesfmt}, /* Plan 9 addition */ 77 | {'X', __ifmt}, 78 | {'b', __ifmt}, /* Plan 9 addition */ 79 | {'c', __charfmt}, 80 | {'d', __ifmt}, 81 | {'e', __efgfmt}, 82 | {'f', __efgfmt}, 83 | {'g', __efgfmt}, 84 | {'h', __flagfmt}, 85 | #ifndef PLAN9PORT 86 | {'i', __ifmt}, /* ANSI only */ 87 | #endif 88 | {'l', __flagfmt}, 89 | {'n', __countfmt}, 90 | {'o', __ifmt}, 91 | {'p', __ifmt}, 92 | {'r', __errfmt}, 93 | {'s', __strfmt}, 94 | #ifdef PLAN9PORT 95 | {'u', __flagfmt}, 96 | #else 97 | {'u', __ifmt}, 98 | #endif 99 | {'x', __ifmt}, 100 | } 101 | }; 102 | 103 | int (*fmtdoquote)(int); 104 | 105 | /* 106 | * __fmtlock() must be set 107 | */ 108 | static int 109 | __fmtinstall(int c, Fmts f) 110 | { 111 | Convfmt *p; 112 | int i; 113 | 114 | if(c<=0 || c>=65536) 115 | return -1; 116 | if(!f) 117 | f = __badfmt; 118 | 119 | i = atomic_load(&fmtalloc.nfmt); 120 | if(i == Maxfmt) 121 | return -1; 122 | p = &fmtalloc.fmt[i]; 123 | p->c = c; 124 | p->fmt = f; 125 | atomic_store(&fmtalloc.nfmt, i+1); 126 | 127 | return 0; 128 | } 129 | 130 | int 131 | fmtinstall(int c, int (*f)(Fmt*)) 132 | { 133 | int ret; 134 | 135 | __fmtlock(); 136 | ret = __fmtinstall(c, f); 137 | __fmtunlock(); 138 | return ret; 139 | } 140 | 141 | static Fmts 142 | fmtfmt(int c) 143 | { 144 | Convfmt *p, *ep; 145 | 146 | ep = &fmtalloc.fmt[atomic_load(&fmtalloc.nfmt)]; 147 | for(p=ep; p-- > fmtalloc.fmt; ) 148 | if(p->c == c) 149 | return p->fmt; 150 | 151 | return __badfmt; 152 | } 153 | 154 | void* 155 | __fmtdispatch(Fmt *f, void *fmt, int isrunes) 156 | { 157 | Rune rune, r; 158 | int i, n; 159 | 160 | f->flags = 0; 161 | f->width = f->prec = 0; 162 | 163 | for(;;){ 164 | if(isrunes){ 165 | r = *(Rune*)fmt; 166 | fmt = (Rune*)fmt + 1; 167 | }else{ 168 | fmt = (char*)fmt + chartorune(&rune, (char*)fmt); 169 | r = rune; 170 | } 171 | f->r = r; 172 | switch(r){ 173 | case '\0': 174 | return nil; 175 | case '.': 176 | f->flags |= FmtWidth|FmtPrec; 177 | continue; 178 | case '0': 179 | if(!(f->flags & FmtWidth)){ 180 | f->flags |= FmtZero; 181 | continue; 182 | } 183 | /* fall through */ 184 | case '1': case '2': case '3': case '4': 185 | case '5': case '6': case '7': case '8': case '9': 186 | i = 0; 187 | while(r >= '0' && r <= '9'){ 188 | i = i * 10 + r - '0'; 189 | if(isrunes){ 190 | r = *(Rune*)fmt; 191 | fmt = (Rune*)fmt + 1; 192 | }else{ 193 | r = *(char*)fmt; 194 | fmt = (char*)fmt + 1; 195 | } 196 | } 197 | if(isrunes) 198 | fmt = (Rune*)fmt - 1; 199 | else 200 | fmt = (char*)fmt - 1; 201 | numflag: 202 | if(f->flags & FmtWidth){ 203 | f->flags |= FmtPrec; 204 | f->prec = i; 205 | }else{ 206 | f->flags |= FmtWidth; 207 | f->width = i; 208 | } 209 | continue; 210 | case '*': 211 | i = va_arg(f->args, int); 212 | if(i < 0){ 213 | /* 214 | * negative precision => 215 | * ignore the precision. 216 | */ 217 | if(f->flags & FmtPrec){ 218 | f->flags &= ~FmtPrec; 219 | f->prec = 0; 220 | continue; 221 | } 222 | i = -i; 223 | f->flags |= FmtLeft; 224 | } 225 | goto numflag; 226 | } 227 | n = (*fmtfmt(r))(f); 228 | if(n < 0) 229 | return nil; 230 | if(n == 0) 231 | return fmt; 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /compat/9p.h: -------------------------------------------------------------------------------- 1 | #ifndef __9P_H__ 2 | #define __9P_H__ 1 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | /* 9 | #pragma src "/sys/src/lib9p" 10 | #pragma lib "lib9p.a" 11 | */ 12 | AUTOLIB(9p) 13 | 14 | /* 15 | * Maps from ulongs to void*s. 16 | */ 17 | typedef struct Intmap Intmap; 18 | 19 | Intmap* allocmap(void (*inc)(void*)); 20 | void freemap(Intmap*, void (*destroy)(void*)); 21 | void* lookupkey(Intmap*, ulong); 22 | void* insertkey(Intmap*, ulong, void*); 23 | int caninsertkey(Intmap*, ulong, void*); 24 | void* deletekey(Intmap*, ulong); 25 | 26 | /* 27 | * Fid and Request structures. 28 | */ 29 | typedef struct Fid Fid; 30 | typedef struct Req Req; 31 | typedef struct Fidpool Fidpool; 32 | typedef struct Reqpool Reqpool; 33 | typedef struct File File; 34 | typedef struct Filelist Filelist; 35 | typedef struct Tree Tree; 36 | typedef struct Readdir Readdir; 37 | typedef struct Srv Srv; 38 | 39 | struct Fid 40 | { 41 | ulong fid; 42 | int omode; /* -1 = not open */ 43 | File* file; 44 | char* uid; 45 | Qid qid; 46 | void* aux; 47 | 48 | /* below is implementation-specific; don't use */ 49 | Readdir* rdir; 50 | Ref ref; 51 | Fidpool* pool; 52 | vlong diroffset; 53 | long dirindex; 54 | }; 55 | 56 | struct Req 57 | { 58 | ulong tag; 59 | void* aux; 60 | Fcall ifcall; 61 | Fcall ofcall; 62 | Dir d; 63 | Req* oldreq; 64 | Fid* fid; 65 | Fid* afid; 66 | Fid* newfid; 67 | Srv* srv; 68 | 69 | /* below is implementation-specific; don't use */ 70 | QLock lk; 71 | Ref ref; 72 | Reqpool* pool; 73 | uchar* buf; 74 | uchar type; 75 | uchar responded; 76 | char* error; 77 | void* rbuf; 78 | Req** flush; 79 | int nflush; 80 | }; 81 | 82 | /* 83 | * Pools to maintain Fid <-> fid and Req <-> tag maps. 84 | */ 85 | 86 | struct Fidpool { 87 | Intmap *map; 88 | void (*destroy)(Fid*); 89 | Srv *srv; 90 | }; 91 | 92 | struct Reqpool { 93 | Intmap *map; 94 | void (*destroy)(Req*); 95 | Srv *srv; 96 | }; 97 | 98 | Fidpool* allocfidpool(void (*destroy)(Fid*)); 99 | void freefidpool(Fidpool*); 100 | Fid* allocfid(Fidpool*, ulong); 101 | Fid* lookupfid(Fidpool*, ulong); 102 | void closefid(Fid*); 103 | Fid* removefid(Fidpool*, ulong); 104 | 105 | Reqpool* allocreqpool(void (*destroy)(Req*)); 106 | void freereqpool(Reqpool*); 107 | Req* allocreq(Reqpool*, ulong); 108 | Req* lookupreq(Reqpool*, ulong); 109 | void closereq(Req*); 110 | Req* removereq(Reqpool*, ulong); 111 | 112 | typedef int Dirgen(int, Dir*, void*); 113 | void dirread9p(Req*, Dirgen*, void*); 114 | 115 | /* 116 | * File trees. 117 | */ 118 | struct File { 119 | Ref ref; 120 | Dir dir; 121 | File *parent; 122 | void *aux; 123 | 124 | /* below is implementation-specific; don't use */ 125 | RWLock rwlock; 126 | Filelist *filelist; 127 | Tree *tree; 128 | int nchild; 129 | int allocd; 130 | }; 131 | 132 | struct Tree { 133 | File *root; 134 | void (*destroy)(File *file); 135 | 136 | /* below is implementation-specific; don't use */ 137 | Lock genlock; 138 | ulong qidgen; 139 | ulong dirqidgen; 140 | }; 141 | 142 | Tree* alloctree(char*, char*, ulong, void(*destroy)(File*)); 143 | void freetree(Tree*); 144 | File* createfile(File*, char*, char*, ulong, void*); 145 | int removefile(File*); 146 | void closefile(File*); 147 | File* walkfile(File*, char*); 148 | Readdir* opendirfile(File*); 149 | long readdirfile(Readdir*, uchar*, long); 150 | void closedirfile(Readdir*); 151 | 152 | /* 153 | * Kernel-style command parser 154 | */ 155 | typedef struct Cmdbuf Cmdbuf; 156 | typedef struct Cmdtab Cmdtab; 157 | Cmdbuf* parsecmd(char *a, int n); 158 | void respondcmderror(Req*, Cmdbuf*, char*, ...); 159 | Cmdtab* lookupcmd(Cmdbuf*, Cmdtab*, int); 160 | /* 161 | #pragma varargck argpos respondcmderr 3 162 | */ 163 | struct Cmdbuf 164 | { 165 | char *buf; 166 | char **f; 167 | int nf; 168 | }; 169 | 170 | struct Cmdtab 171 | { 172 | int index; /* used by client to switch on result */ 173 | char *cmd; /* command name */ 174 | int narg; /* expected #args; 0 ==> variadic */ 175 | }; 176 | 177 | /* 178 | * File service loop. 179 | */ 180 | struct Srv { 181 | Tree* tree; 182 | void (*destroyfid)(Fid*); 183 | void (*destroyreq)(Req*); 184 | void (*start)(Srv*); 185 | void (*end)(Srv*); 186 | void* aux; 187 | 188 | void (*attach)(Req*); 189 | void (*auth)(Req*); 190 | void (*open)(Req*); 191 | void (*create)(Req*); 192 | void (*read)(Req*); 193 | void (*write)(Req*); 194 | void (*remove)(Req*); 195 | void (*flush)(Req*); 196 | void (*stat)(Req*); 197 | void (*wstat)(Req*); 198 | void (*walk)(Req*); 199 | char* (*clone)(Fid*, Fid*); 200 | char* (*walk1)(Fid*, char*, Qid*); 201 | 202 | int infd; 203 | int outfd; 204 | int nopipe; 205 | int srvfd; 206 | int leavefdsopen; /* magic for acme win */ 207 | int foreground; /* run in foreground */ 208 | int fake; 209 | 210 | /* below is implementation-specific; don't use */ 211 | Fidpool* fpool; 212 | Reqpool* rpool; 213 | uint msize; 214 | 215 | uchar* rbuf; 216 | QLock rlock; 217 | uchar* wbuf; 218 | QLock wlock; 219 | }; 220 | 221 | void srv(Srv*); 222 | int postfd(char*, int); 223 | extern int chatty9p; 224 | void respond(Req*, char*); 225 | void threadpostmountsrv(Srv*, char*, char*, int); 226 | 227 | /* 228 | * Helper. Assumes user is same as group. 229 | */ 230 | int hasperm(File*, char*, int); 231 | 232 | void* emalloc9p(ulong); 233 | void* erealloc9p(void*, ulong); 234 | char* estrdup9p(char*); 235 | 236 | enum { 237 | OMASK = 3 238 | }; 239 | 240 | void readstr(Req*, char*); 241 | void readbuf(Req*, void*, long); 242 | void walkandclone(Req*, char*(*walk1)(Fid*,char*,void*), char*(*clone)(Fid*,Fid*,void*), void*); 243 | 244 | #ifdef __cplusplus 245 | } 246 | #endif 247 | #endif 248 | -------------------------------------------------------------------------------- /compat/lib9/_p9dir.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define NOPLAN9DEFINES 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #if defined(__APPLE__) 11 | #define _HAVESTGEN 12 | #include 13 | static vlong 14 | disksize(int fd, struct stat *st) 15 | { 16 | u64int bc; 17 | u32int bs; 18 | 19 | bs = 0; 20 | bc = 0; 21 | ioctl(fd, DKIOCGETBLOCKSIZE, &bs); 22 | ioctl(fd, DKIOCGETBLOCKCOUNT, &bc); 23 | if(bs >0 && bc > 0) 24 | return bc*bs; 25 | return 0; 26 | } 27 | 28 | #elif defined(__FreeBSD__) 29 | #define _HAVESTGEN 30 | #include 31 | #include 32 | #include 33 | static vlong 34 | disksize(int fd, struct stat *st) 35 | { 36 | off_t mediasize; 37 | 38 | if(ioctl(fd, DIOCGMEDIASIZE, &mediasize) >= 0) 39 | return mediasize; 40 | return 0; 41 | } 42 | 43 | #elif defined(__OpenBSD__) 44 | #define _HAVESTGEN 45 | #include 46 | #include 47 | #include 48 | static vlong 49 | disksize(int fd, struct stat *st) 50 | { 51 | struct disklabel lab; 52 | int n; 53 | 54 | if(!S_ISCHR(st->st_mode)) 55 | return 0; 56 | if(ioctl(fd, DIOCGDINFO, &lab) < 0) 57 | return 0; 58 | n = minor(st->st_rdev)&7; 59 | if(n >= lab.d_npartitions) 60 | return 0; 61 | return (vlong)lab.d_partitions[n].p_size * lab.d_secsize; 62 | } 63 | 64 | #elif defined(__linux__) 65 | #include 66 | #include 67 | #include 68 | #undef major 69 | #define major(dev) ((int)(((dev) >> 8) & 0xff)) 70 | static vlong 71 | disksize(int fd, struct stat *st) 72 | { 73 | u64int u64; 74 | long l; 75 | struct hd_geometry geo; 76 | 77 | memset(&geo, 0, sizeof geo); 78 | l = 0; 79 | u64 = 0; 80 | #ifdef BLKGETSIZE64 81 | if(ioctl(fd, BLKGETSIZE64, &u64) >= 0) 82 | return u64; 83 | #endif 84 | if(ioctl(fd, BLKGETSIZE, &l) >= 0) 85 | return l*512; 86 | if(ioctl(fd, HDIO_GETGEO, &geo) >= 0) 87 | return (vlong)geo.heads*geo.sectors*geo.cylinders*512; 88 | return 0; 89 | } 90 | 91 | #else 92 | static vlong 93 | disksize(int fd, struct stat *st) 94 | { 95 | return 0; 96 | } 97 | #endif 98 | 99 | int _p9usepwlibrary = 1; 100 | /* 101 | * Caching the last group and passwd looked up is 102 | * a significant win (stupidly enough) on most systems. 103 | * It's not safe for threaded programs, but neither is using 104 | * getpwnam in the first place, so I'm not too worried. 105 | */ 106 | int 107 | _p9dir(struct stat *lst, struct stat *st, char *name, Dir *d, char **str, char *estr) 108 | { 109 | char *s; 110 | char tmp[20]; 111 | static struct group *g; 112 | static struct passwd *p; 113 | static int gid, uid; 114 | int sz, fd; 115 | 116 | fd = -1; 117 | USED(fd); 118 | sz = 0; 119 | if(d) 120 | memset(d, 0, sizeof *d); 121 | 122 | /* name */ 123 | s = strrchr(name, '/'); 124 | if(s) 125 | s++; 126 | if(!s || !*s) 127 | s = name; 128 | if(*s == '/') 129 | s++; 130 | if(*s == 0) 131 | s = "/"; 132 | if(d){ 133 | if(*str + strlen(s)+1 > estr) 134 | d->name = "oops"; 135 | else{ 136 | strcpy(*str, s); 137 | d->name = *str; 138 | *str += strlen(*str)+1; 139 | } 140 | } 141 | sz += strlen(s)+1; 142 | 143 | /* user */ 144 | if(p && st->st_uid == uid && p->pw_uid == uid) 145 | ; 146 | else if(_p9usepwlibrary){ 147 | p = getpwuid(st->st_uid); 148 | uid = st->st_uid; 149 | } 150 | if(p == nil || st->st_uid != uid || p->pw_uid != uid){ 151 | snprint(tmp, sizeof tmp, "%d", (int)st->st_uid); 152 | s = tmp; 153 | }else 154 | s = p->pw_name; 155 | sz += strlen(s)+1; 156 | if(d){ 157 | if(*str+strlen(s)+1 > estr) 158 | d->uid = "oops"; 159 | else{ 160 | strcpy(*str, s); 161 | d->uid = *str; 162 | *str += strlen(*str)+1; 163 | } 164 | } 165 | 166 | /* group */ 167 | if(g && st->st_gid == gid && g->gr_gid == gid) 168 | ; 169 | else if(_p9usepwlibrary){ 170 | g = getgrgid(st->st_gid); 171 | gid = st->st_gid; 172 | } 173 | if(g == nil || st->st_gid != gid || g->gr_gid != gid){ 174 | snprint(tmp, sizeof tmp, "%d", (int)st->st_gid); 175 | s = tmp; 176 | }else 177 | s = g->gr_name; 178 | sz += strlen(s)+1; 179 | if(d){ 180 | if(*str + strlen(s)+1 > estr) 181 | d->gid = "oops"; 182 | else{ 183 | strcpy(*str, s); 184 | d->gid = *str; 185 | *str += strlen(*str)+1; 186 | } 187 | } 188 | 189 | if(d){ 190 | d->type = 'M'; 191 | 192 | d->muid = ""; 193 | d->qid.path = st->st_ino; 194 | /* 195 | * do not include st->st_dev in path, because 196 | * automounters give the same file system different 197 | * st_dev values for successive mounts, causing 198 | * spurious write warnings in acme and sam. 199 | d->qid.path |= (uvlong)st->st_dev<<32; 200 | */ 201 | #ifdef _HAVESTGEN 202 | d->qid.vers = st->st_gen; 203 | #endif 204 | if(d->qid.vers == 0) 205 | d->qid.vers = st->st_mtime + st->st_ctime; 206 | d->mode = st->st_mode&0777; 207 | d->atime = st->st_atime; 208 | d->mtime = st->st_mtime; 209 | d->length = st->st_size; 210 | 211 | if(S_ISLNK(lst->st_mode)){ /* yes, lst not st */ 212 | d->mode |= DMSYMLINK; 213 | d->length = lst->st_size; 214 | } 215 | else if(S_ISDIR(st->st_mode)){ 216 | d->length = 0; 217 | d->mode |= DMDIR; 218 | d->qid.type = QTDIR; 219 | } 220 | else if(S_ISFIFO(st->st_mode)) 221 | d->mode |= DMNAMEDPIPE; 222 | else if(S_ISSOCK(st->st_mode)) 223 | d->mode |= DMSOCKET; 224 | else if(S_ISBLK(st->st_mode)){ 225 | d->mode |= DMDEVICE; 226 | d->qid.path = ('b'<<16)|st->st_rdev; 227 | } 228 | else if(S_ISCHR(st->st_mode)){ 229 | d->mode |= DMDEVICE; 230 | d->qid.path = ('c'<<16)|st->st_rdev; 231 | } 232 | /* fetch real size for disks */ 233 | if(S_ISBLK(lst->st_mode)){ 234 | if((fd = open(name, O_RDONLY)) >= 0){ 235 | d->length = disksize(fd, st); 236 | close(fd); 237 | } 238 | } 239 | } 240 | 241 | return sz; 242 | } 243 | -------------------------------------------------------------------------------- /compat/lib9/notify.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Signal handling for Plan 9 programs. 3 | * We stubbornly use the strings from Plan 9 instead 4 | * of the enumerated Unix constants. 5 | * There are some weird translations. In particular, 6 | * a "kill" note is the same as SIGTERM in Unix. 7 | * There is no equivalent note to Unix's SIGKILL, since 8 | * it's not a deliverable signal anyway. 9 | * 10 | * We do not handle SIGABRT or SIGSEGV, mainly because 11 | * the thread library queues its notes for later, and we want 12 | * to dump core with the state at time of delivery. 13 | * 14 | * We have to add some extra entry points to provide the 15 | * ability to tweak which signals are deliverable and which 16 | * are acted upon. Notifydisable and notifyenable play with 17 | * the process signal mask. Notifyignore enables the signal 18 | * but will not call notifyf when it comes in. This is occasionally 19 | * useful. 20 | */ 21 | 22 | #include 23 | #include 24 | #define NOPLAN9DEFINES 25 | #include 26 | 27 | extern char *_p9sigstr(int, char*); 28 | extern int _p9strsig(char*); 29 | 30 | typedef struct Sig Sig; 31 | struct Sig 32 | { 33 | int sig; /* signal number */ 34 | int flags; 35 | }; 36 | 37 | enum 38 | { 39 | Restart = 1<<0, 40 | Ignore = 1<<1, 41 | NoNotify = 1<<2, 42 | }; 43 | 44 | static Sig sigs[] = { 45 | SIGHUP, 0, 46 | SIGINT, 0, 47 | SIGQUIT, 0, 48 | SIGILL, 0, 49 | SIGTRAP, 0, 50 | /* SIGABRT, 0, */ 51 | #ifdef SIGEMT 52 | SIGEMT, 0, 53 | #endif 54 | SIGFPE, 0, 55 | SIGBUS, 0, 56 | /* SIGSEGV, 0, */ 57 | SIGCHLD, Restart|Ignore, 58 | SIGSYS, 0, 59 | SIGPIPE, Ignore, 60 | SIGALRM, 0, 61 | SIGTERM, 0, 62 | SIGTSTP, Restart|Ignore|NoNotify, 63 | /* SIGTTIN, Restart|Ignore, */ 64 | /* SIGTTOU, Restart|Ignore, */ 65 | SIGXCPU, 0, 66 | SIGXFSZ, 0, 67 | SIGVTALRM, 0, 68 | SIGUSR1, 0, 69 | SIGUSR2, 0, 70 | #ifdef SIGWINCH 71 | SIGWINCH, Restart|Ignore|NoNotify, 72 | #endif 73 | #ifdef SIGINFO 74 | SIGINFO, Restart|Ignore|NoNotify, 75 | #endif 76 | }; 77 | 78 | static Sig* 79 | findsig(int s) 80 | { 81 | int i; 82 | 83 | for(i=0; ib)){ 127 | case 0: 128 | if(notifyf) 129 | (*notifyf)(nil, _p9sigstr(sig, tmp)); 130 | /* fall through */ 131 | case 1: /* noted(NDFLT) */ 132 | if(0)print("DEFAULT %d\n", sig); 133 | s = findsig(sig); 134 | if(s && (s->flags&Ignore)) 135 | return; 136 | signal(sig, SIG_DFL); 137 | raise(sig); 138 | _exit(1); 139 | case 2: /* noted(NCONT) */ 140 | if(0)print("HANDLED %d\n", sig); 141 | return; 142 | } 143 | } 144 | 145 | static void 146 | signonotify(int sig) 147 | { 148 | USED(sig); 149 | } 150 | 151 | int 152 | noted(int v) 153 | { 154 | p9longjmp((*_notejmpbuf)()->b, v==NCONT ? 2 : 1); 155 | abort(); 156 | return 0; 157 | } 158 | 159 | int 160 | notify(void (*f)(void*, char*)) 161 | { 162 | static int init; 163 | 164 | notifyf = f; 165 | if(!init){ 166 | init = 1; 167 | noteinit(); 168 | } 169 | return 0; 170 | } 171 | 172 | /* 173 | * Nonsense about enabling and disabling signals. 174 | */ 175 | typedef void Sighandler(int); 176 | static Sighandler* 177 | handler(int s) 178 | { 179 | struct sigaction sa; 180 | 181 | sigaction(s, nil, &sa); 182 | return sa.sa_handler; 183 | } 184 | 185 | static int 186 | notesetenable(int sig, int enabled) 187 | { 188 | sigset_t mask, omask; 189 | 190 | if(sig == 0) 191 | return -1; 192 | 193 | sigemptyset(&mask); 194 | sigaddset(&mask, sig); 195 | sigprocmask(enabled ? SIG_UNBLOCK : SIG_BLOCK, &mask, &omask); 196 | return !sigismember(&omask, sig); 197 | } 198 | 199 | int 200 | noteenable(char *msg) 201 | { 202 | return notesetenable(_p9strsig(msg), 1); 203 | } 204 | 205 | int 206 | notedisable(char *msg) 207 | { 208 | return notesetenable(_p9strsig(msg), 0); 209 | } 210 | 211 | static int 212 | notifyseton(int s, int on) 213 | { 214 | Sig *sig; 215 | struct sigaction sa, osa; 216 | 217 | sig = findsig(s); 218 | if(sig == nil) 219 | return -1; 220 | memset(&sa, 0, sizeof sa); 221 | sa.sa_handler = on ? signotify : signonotify; 222 | if(sig->flags&Restart) 223 | sa.sa_flags |= SA_RESTART; 224 | 225 | /* 226 | * We can't allow signals within signals because there's 227 | * only one jump buffer. 228 | */ 229 | sigfillset(&sa.sa_mask); 230 | 231 | /* 232 | * Install handler. 233 | */ 234 | sigaction(sig->sig, &sa, &osa); 235 | return osa.sa_handler == signotify; 236 | } 237 | 238 | int 239 | notifyon(char *msg) 240 | { 241 | return notifyseton(_p9strsig(msg), 1); 242 | } 243 | 244 | int 245 | notifyoff(char *msg) 246 | { 247 | return notifyseton(_p9strsig(msg), 0); 248 | } 249 | 250 | /* 251 | * Initialization follows sigs table. 252 | */ 253 | static void 254 | noteinit(void) 255 | { 256 | int i; 257 | Sig *sig; 258 | 259 | for(i=0; isig) != SIG_DFL) 269 | continue; 270 | notifyseton(sig->sig, !(sig->flags&NoNotify)); 271 | } 272 | } 273 | -------------------------------------------------------------------------------- /compat/fmt/fmtquote.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 | #include 3 | #include 4 | #include "plan9.h" 5 | #include "fmt.h" 6 | #include "fmtdef.h" 7 | 8 | /* 9 | * How many bytes of output UTF will be produced by quoting (if necessary) this string? 10 | * How many runes? How much of the input will be consumed? 11 | * The parameter q is filled in by __quotesetup. 12 | * The string may be UTF or Runes (s or r). 13 | * Return count does not include NUL. 14 | * Terminate the scan at the first of: 15 | * NUL in input 16 | * count exceeded in input 17 | * count exceeded on output 18 | * *ninp is set to number of input bytes accepted. 19 | * nin may be <0 initially, to avoid checking input by count. 20 | */ 21 | void 22 | __quotesetup(char *s, Rune *r, int nin, int nout, Quoteinfo *q, int sharp, int runesout) 23 | { 24 | int w; 25 | Rune c; 26 | 27 | q->quoted = 0; 28 | q->nbytesout = 0; 29 | q->nrunesout = 0; 30 | q->nbytesin = 0; 31 | q->nrunesin = 0; 32 | if(sharp || nin==0 || (s && *s=='\0') || (r && *r=='\0')){ 33 | if(nout < 2) 34 | return; 35 | q->quoted = 1; 36 | q->nbytesout = 2; 37 | q->nrunesout = 2; 38 | } 39 | for(; nin!=0; nin--){ 40 | if(s) 41 | w = chartorune(&c, s); 42 | else{ 43 | c = *r; 44 | w = runelen(c); 45 | } 46 | 47 | if(c == '\0') 48 | break; 49 | if(runesout){ 50 | if(q->nrunesout+1 > nout) 51 | break; 52 | }else{ 53 | if(q->nbytesout+w > nout) 54 | break; 55 | } 56 | 57 | if((c <= L' ') || (c == L'\'') || (fmtdoquote!=nil && fmtdoquote(c))){ 58 | if(!q->quoted){ 59 | if(runesout){ 60 | if(1+q->nrunesout+1+1 > nout) /* no room for quotes */ 61 | break; 62 | }else{ 63 | if(1+q->nbytesout+w+1 > nout) /* no room for quotes */ 64 | break; 65 | } 66 | q->nrunesout += 2; /* include quotes */ 67 | q->nbytesout += 2; /* include quotes */ 68 | q->quoted = 1; 69 | } 70 | if(c == '\'') { 71 | if(runesout){ 72 | if(1+q->nrunesout+1 > nout) /* no room for quotes */ 73 | break; 74 | }else{ 75 | if(1+q->nbytesout+w > nout) /* no room for quotes */ 76 | break; 77 | } 78 | q->nbytesout++; 79 | q->nrunesout++; /* quotes reproduce as two characters */ 80 | } 81 | } 82 | 83 | /* advance input */ 84 | if(s) 85 | s += w; 86 | else 87 | r++; 88 | q->nbytesin += w; 89 | q->nrunesin++; 90 | 91 | /* advance output */ 92 | q->nbytesout += w; 93 | q->nrunesout++; 94 | 95 | #ifndef PLAN9PORT 96 | /* ANSI requires precision in bytes, not Runes. */ 97 | nin-= w-1; /* and then n-- in the loop */ 98 | #endif 99 | } 100 | } 101 | 102 | static int 103 | qstrfmt(char *sin, Rune *rin, Quoteinfo *q, Fmt *f) 104 | { 105 | Rune r, *rm, *rme; 106 | char *t, *s, *m, *me; 107 | Rune *rt, *rs; 108 | ulong fl; 109 | int nc, w; 110 | 111 | m = sin; 112 | me = m + q->nbytesin; 113 | rm = rin; 114 | rme = rm + q->nrunesin; 115 | 116 | fl = f->flags; 117 | w = 0; 118 | if(fl & FmtWidth) 119 | w = f->width; 120 | if(f->runes){ 121 | if(!(fl & FmtLeft) && __rfmtpad(f, w - q->nrunesout) < 0) 122 | return -1; 123 | }else{ 124 | if(!(fl & FmtLeft) && __fmtpad(f, w - q->nbytesout) < 0) 125 | return -1; 126 | } 127 | t = (char*)f->to; 128 | s = (char*)f->stop; 129 | rt = (Rune*)f->to; 130 | rs = (Rune*)f->stop; 131 | if(f->runes) 132 | FMTRCHAR(f, rt, rs, '\''); 133 | else 134 | FMTRUNE(f, t, s, '\''); 135 | for(nc = q->nrunesin; nc > 0; nc--){ 136 | if(sin){ 137 | r = *(uchar*)m; 138 | if(r < Runeself) 139 | m++; 140 | else if((me - m) >= UTFmax || fullrune(m, me-m)) 141 | m += chartorune(&r, m); 142 | else 143 | break; 144 | }else{ 145 | if(rm >= rme) 146 | break; 147 | r = *(uchar*)rm++; 148 | } 149 | if(f->runes){ 150 | FMTRCHAR(f, rt, rs, r); 151 | if(r == '\'') 152 | FMTRCHAR(f, rt, rs, r); 153 | }else{ 154 | FMTRUNE(f, t, s, r); 155 | if(r == '\'') 156 | FMTRUNE(f, t, s, r); 157 | } 158 | } 159 | 160 | if(f->runes){ 161 | FMTRCHAR(f, rt, rs, '\''); 162 | USED(rs); 163 | f->nfmt += rt - (Rune *)f->to; 164 | f->to = rt; 165 | if(fl & FmtLeft && __rfmtpad(f, w - q->nrunesout) < 0) 166 | return -1; 167 | }else{ 168 | FMTRUNE(f, t, s, '\''); 169 | USED(s); 170 | f->nfmt += t - (char *)f->to; 171 | f->to = t; 172 | if(fl & FmtLeft && __fmtpad(f, w - q->nbytesout) < 0) 173 | return -1; 174 | } 175 | return 0; 176 | } 177 | 178 | int 179 | __quotestrfmt(int runesin, Fmt *f) 180 | { 181 | int nin, outlen; 182 | Rune *r; 183 | char *s; 184 | Quoteinfo q; 185 | 186 | nin = -1; 187 | if(f->flags&FmtPrec) 188 | nin = f->prec; 189 | if(runesin){ 190 | r = va_arg(f->args, Rune *); 191 | s = nil; 192 | }else{ 193 | s = va_arg(f->args, char *); 194 | r = nil; 195 | } 196 | if(!s && !r) 197 | return __fmtcpy(f, (void*)"", 5, 5); 198 | 199 | if(f->flush) 200 | outlen = 0x7FFFFFFF; /* if we can flush, no output limit */ 201 | else if(f->runes) 202 | outlen = (Rune*)f->stop - (Rune*)f->to; 203 | else 204 | outlen = (char*)f->stop - (char*)f->to; 205 | 206 | __quotesetup(s, r, nin, outlen, &q, f->flags&FmtSharp, f->runes); 207 | /*print("bytes in %d bytes out %d runes in %d runesout %d\n", q.nbytesin, q.nbytesout, q.nrunesin, q.nrunesout); */ 208 | 209 | if(runesin){ 210 | if(!q.quoted) 211 | return __fmtrcpy(f, r, q.nrunesin); 212 | return qstrfmt(nil, r, &q, f); 213 | } 214 | 215 | if(!q.quoted) 216 | return __fmtcpy(f, s, q.nrunesin, q.nbytesin); 217 | return qstrfmt(s, nil, &q, f); 218 | } 219 | 220 | int 221 | quotestrfmt(Fmt *f) 222 | { 223 | return __quotestrfmt(0, f); 224 | } 225 | 226 | int 227 | quoterunestrfmt(Fmt *f) 228 | { 229 | return __quotestrfmt(1, f); 230 | } 231 | 232 | void 233 | quotefmtinstall(void) 234 | { 235 | fmtinstall('q', quotestrfmt); 236 | fmtinstall('Q', quoterunestrfmt); 237 | } 238 | 239 | int 240 | __needsquotes(char *s, int *quotelenp) 241 | { 242 | Quoteinfo q; 243 | 244 | __quotesetup(s, nil, -1, 0x7FFFFFFF, &q, 0, 0); 245 | *quotelenp = q.nbytesout; 246 | 247 | return q.quoted; 248 | } 249 | 250 | int 251 | __runeneedsquotes(Rune *r, int *quotelenp) 252 | { 253 | Quoteinfo q; 254 | 255 | __quotesetup(nil, r, -1, 0x7FFFFFFF, &q, 0, 0); 256 | *quotelenp = q.nrunesout; 257 | 258 | return q.quoted; 259 | } 260 | -------------------------------------------------------------------------------- /compat/libmux/mux.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2003-2006 Russ Cox, Massachusetts Institute of Technology */ 2 | /* See COPYRIGHT */ 3 | 4 | /* 5 | * Generic RPC packet multiplexor. Inspired by but not derived from 6 | * Plan 9 kernel. Originally developed as part of Tra, later used in 7 | * libnventi, and then finally split out into a generic library. 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | static int gettag(Mux*, Muxrpc*); 15 | static void puttag(Mux*, Muxrpc*); 16 | static void enqueue(Mux*, Muxrpc*); 17 | static void dequeue(Mux*, Muxrpc*); 18 | 19 | void 20 | muxinit(Mux *mux) 21 | { 22 | memset(&mux->lk, 0, sizeof(Mux)-offsetof(Mux, lk)); 23 | mux->tagrend.l = &mux->lk; 24 | mux->rpcfork.l = &mux->lk; 25 | mux->sleep.next = &mux->sleep; 26 | mux->sleep.prev = &mux->sleep; 27 | } 28 | 29 | static Muxrpc* 30 | allocmuxrpc(Mux *mux) 31 | { 32 | Muxrpc *r; 33 | 34 | /* must malloc because stack could be private */ 35 | r = mallocz(sizeof(Muxrpc), 1); 36 | if(r == nil){ 37 | werrstr("mallocz: %r"); 38 | return nil; 39 | } 40 | r->mux = mux; 41 | r->r.l = &mux->lk; 42 | r->waiting = 1; 43 | 44 | return r; 45 | } 46 | 47 | static int 48 | tagmuxrpc(Muxrpc *r, void *tx) 49 | { 50 | int tag; 51 | Mux *mux; 52 | 53 | mux = r->mux; 54 | /* assign the tag, add selves to response queue */ 55 | qlock(&mux->lk); 56 | tag = gettag(mux, r); 57 | /*print("gettag %p %d\n", r, tag); */ 58 | enqueue(mux, r); 59 | qunlock(&mux->lk); 60 | 61 | /* actually send the packet */ 62 | if(tag < 0 || mux->settag(mux, tx, tag) < 0 || _muxsend(mux, tx) < 0){ 63 | werrstr("settag/send tag %d: %r", tag); 64 | fprint(2, "%r\n"); 65 | qlock(&mux->lk); 66 | dequeue(mux, r); 67 | puttag(mux, r); 68 | qunlock(&mux->lk); 69 | return -1; 70 | } 71 | return 0; 72 | } 73 | 74 | void 75 | muxmsgandqlock(Mux *mux, void *p) 76 | { 77 | int tag; 78 | Muxrpc *r2; 79 | 80 | tag = mux->gettag(mux, p) - mux->mintag; 81 | /*print("mux tag %d\n", tag); */ 82 | qlock(&mux->lk); 83 | /* hand packet to correct sleeper */ 84 | if(tag < 0 || tag >= mux->mwait){ 85 | fprint(2, "%s: bad rpc tag %ux\n", argv0, tag); 86 | /* must leak packet! don't know how to free it! */ 87 | return; 88 | } 89 | r2 = mux->wait[tag]; 90 | if(r2 == nil || r2->prev == nil){ 91 | fprint(2, "%s: bad rpc tag %ux (no one waiting on that tag)\n", argv0, tag); 92 | /* must leak packet! don't know how to free it! */ 93 | return; 94 | } 95 | r2->p = p; 96 | dequeue(mux, r2); 97 | rwakeup(&r2->r); 98 | } 99 | 100 | void 101 | electmuxer(Mux *mux) 102 | { 103 | Muxrpc *rpc; 104 | 105 | /* if there is anyone else sleeping, wake them to mux */ 106 | for(rpc=mux->sleep.next; rpc != &mux->sleep; rpc = rpc->next){ 107 | if(!rpc->async){ 108 | mux->muxer = rpc; 109 | rwakeup(&rpc->r); 110 | return; 111 | } 112 | } 113 | mux->muxer = nil; 114 | } 115 | 116 | void* 117 | muxrpc(Mux *mux, void *tx) 118 | { 119 | int tag; 120 | Muxrpc *r; 121 | void *p; 122 | 123 | if((r = allocmuxrpc(mux)) == nil) 124 | return nil; 125 | 126 | if((tag = tagmuxrpc(r, tx)) < 0) 127 | return nil; 128 | 129 | qlock(&mux->lk); 130 | /* wait for our packet */ 131 | while(mux->muxer && mux->muxer != r && !r->p) 132 | rsleep(&r->r); 133 | 134 | /* if not done, there's no muxer: start muxing */ 135 | if(!r->p){ 136 | if(mux->muxer != nil && mux->muxer != r) 137 | abort(); 138 | mux->muxer = r; 139 | while(!r->p){ 140 | qunlock(&mux->lk); 141 | _muxrecv(mux, 1, &p); 142 | if(p == nil){ 143 | /* eof -- just give up and pass the buck */ 144 | qlock(&mux->lk); 145 | dequeue(mux, r); 146 | break; 147 | } 148 | muxmsgandqlock(mux, p); 149 | } 150 | electmuxer(mux); 151 | } 152 | p = r->p; 153 | puttag(mux, r); 154 | qunlock(&mux->lk); 155 | if(p == nil) 156 | werrstr("unexpected eof"); 157 | return p; 158 | } 159 | 160 | Muxrpc* 161 | muxrpcstart(Mux *mux, void *tx) 162 | { 163 | int tag; 164 | Muxrpc *r; 165 | 166 | if((r = allocmuxrpc(mux)) == nil) 167 | return nil; 168 | r->async = 1; 169 | if((tag = tagmuxrpc(r, tx)) < 0) 170 | return nil; 171 | return r; 172 | } 173 | 174 | int 175 | muxrpccanfinish(Muxrpc *r, void **vp) 176 | { 177 | void *p; 178 | Mux *mux; 179 | int ret; 180 | 181 | mux = r->mux; 182 | qlock(&mux->lk); 183 | ret = 1; 184 | if(!r->p && !mux->muxer){ 185 | mux->muxer = r; 186 | while(!r->p){ 187 | qunlock(&mux->lk); 188 | p = nil; 189 | if(!_muxrecv(mux, 0, &p)) 190 | ret = 0; 191 | if(p == nil){ 192 | qlock(&mux->lk); 193 | break; 194 | } 195 | muxmsgandqlock(mux, p); 196 | } 197 | electmuxer(mux); 198 | } 199 | p = r->p; 200 | if(p) 201 | puttag(mux, r); 202 | qunlock(&mux->lk); 203 | *vp = p; 204 | return ret; 205 | } 206 | 207 | static void 208 | enqueue(Mux *mux, Muxrpc *r) 209 | { 210 | r->next = mux->sleep.next; 211 | r->prev = &mux->sleep; 212 | r->next->prev = r; 213 | r->prev->next = r; 214 | } 215 | 216 | static void 217 | dequeue(Mux *mux, Muxrpc *r) 218 | { 219 | r->next->prev = r->prev; 220 | r->prev->next = r->next; 221 | r->prev = nil; 222 | r->next = nil; 223 | } 224 | 225 | static int 226 | gettag(Mux *mux, Muxrpc *r) 227 | { 228 | int i, mw; 229 | Muxrpc **w; 230 | 231 | for(;;){ 232 | /* wait for a free tag */ 233 | while(mux->nwait == mux->mwait){ 234 | if(mux->mwait < mux->maxtag-mux->mintag){ 235 | mw = mux->mwait; 236 | if(mw == 0) 237 | mw = 1; 238 | else 239 | mw <<= 1; 240 | w = realloc(mux->wait, mw*sizeof(w[0])); 241 | if(w == nil) 242 | return -1; 243 | memset(w+mux->mwait, 0, (mw-mux->mwait)*sizeof(w[0])); 244 | mux->wait = w; 245 | mux->freetag = mux->mwait; 246 | mux->mwait = mw; 247 | break; 248 | } 249 | rsleep(&mux->tagrend); 250 | } 251 | 252 | i=mux->freetag; 253 | if(mux->wait[i] == 0) 254 | goto Found; 255 | for(; imwait; i++) 256 | if(mux->wait[i] == 0) 257 | goto Found; 258 | for(i=0; ifreetag; i++) 259 | if(mux->wait[i] == 0) 260 | goto Found; 261 | /* should not fall out of while without free tag */ 262 | fprint(2, "libfs: nwait botch\n"); 263 | abort(); 264 | } 265 | 266 | Found: 267 | mux->nwait++; 268 | mux->wait[i] = r; 269 | r->tag = i+mux->mintag; 270 | return r->tag; 271 | } 272 | 273 | static void 274 | puttag(Mux *mux, Muxrpc *r) 275 | { 276 | int i; 277 | 278 | i = r->tag - mux->mintag; 279 | assert(mux->wait[i] == r); 280 | mux->wait[i] = nil; 281 | mux->nwait--; 282 | mux->freetag = i; 283 | rwakeup(&mux->tagrend); 284 | free(r); 285 | } 286 | -------------------------------------------------------------------------------- /compat/lib9/convM2S.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static 6 | uchar* 7 | gstring(uchar *p, uchar *ep, char **s) 8 | { 9 | uint n; 10 | 11 | if(p+BIT16SZ > ep) 12 | return nil; 13 | n = GBIT16(p); 14 | p += BIT16SZ - 1; 15 | if(p+n+1 > ep) 16 | return nil; 17 | /* move it down, on top of count, to make room for '\0' */ 18 | memmove(p, p + 1, n); 19 | p[n] = '\0'; 20 | *s = (char*)p; 21 | p += n+1; 22 | return p; 23 | } 24 | 25 | static 26 | uchar* 27 | gqid(uchar *p, uchar *ep, Qid *q) 28 | { 29 | if(p+QIDSZ > ep) 30 | return nil; 31 | q->type = GBIT8(p); 32 | p += BIT8SZ; 33 | q->vers = GBIT32(p); 34 | p += BIT32SZ; 35 | q->path = GBIT64(p); 36 | p += BIT64SZ; 37 | return p; 38 | } 39 | 40 | /* 41 | * no syntactic checks. 42 | * three causes for error: 43 | * 1. message size field is incorrect 44 | * 2. input buffer too short for its own data (counts too long, etc.) 45 | * 3. too many names or qids 46 | * gqid() and gstring() return nil if they would reach beyond buffer. 47 | * main switch statement checks range and also can fall through 48 | * to test at end of routine. 49 | */ 50 | uint 51 | convM2S(uchar *ap, uint nap, Fcall *f) 52 | { 53 | uchar *p, *ep; 54 | uint i, size; 55 | 56 | p = ap; 57 | ep = p + nap; 58 | 59 | if(p+BIT32SZ+BIT8SZ+BIT16SZ > ep) 60 | return 0; 61 | size = GBIT32(p); 62 | p += BIT32SZ; 63 | 64 | if(size < BIT32SZ+BIT8SZ+BIT16SZ) 65 | return 0; 66 | 67 | f->type = GBIT8(p); 68 | p += BIT8SZ; 69 | f->tag = GBIT16(p); 70 | p += BIT16SZ; 71 | 72 | switch(f->type) 73 | { 74 | default: 75 | return 0; 76 | 77 | case Tversion: 78 | if(p+BIT32SZ > ep) 79 | return 0; 80 | f->msize = GBIT32(p); 81 | p += BIT32SZ; 82 | p = gstring(p, ep, &f->version); 83 | break; 84 | 85 | case Tflush: 86 | if(p+BIT16SZ > ep) 87 | return 0; 88 | f->oldtag = GBIT16(p); 89 | p += BIT16SZ; 90 | break; 91 | 92 | case Tauth: 93 | if(p+BIT32SZ > ep) 94 | return 0; 95 | f->afid = GBIT32(p); 96 | p += BIT32SZ; 97 | p = gstring(p, ep, &f->uname); 98 | if(p == nil) 99 | break; 100 | p = gstring(p, ep, &f->aname); 101 | if(p == nil) 102 | break; 103 | f->uidnum = NOUID; 104 | break; 105 | 106 | case Tattach: 107 | if(p+BIT32SZ > ep) 108 | return 0; 109 | f->fid = GBIT32(p); 110 | p += BIT32SZ; 111 | if(p+BIT32SZ > ep) 112 | return 0; 113 | f->afid = GBIT32(p); 114 | p += BIT32SZ; 115 | p = gstring(p, ep, &f->uname); 116 | if(p == nil) 117 | break; 118 | p = gstring(p, ep, &f->aname); 119 | if(p == nil) 120 | break; 121 | f->uidnum = NOUID; 122 | break; 123 | 124 | case Twalk: 125 | if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep) 126 | return 0; 127 | f->fid = GBIT32(p); 128 | p += BIT32SZ; 129 | f->newfid = GBIT32(p); 130 | p += BIT32SZ; 131 | f->nwname = GBIT16(p); 132 | p += BIT16SZ; 133 | if(f->nwname > MAXWELEM) 134 | return 0; 135 | for(i=0; inwname; i++){ 136 | p = gstring(p, ep, &f->wname[i]); 137 | if(p == nil) 138 | break; 139 | } 140 | break; 141 | 142 | case Topen: 143 | case Topenfd: 144 | if(p+BIT32SZ+BIT8SZ > ep) 145 | return 0; 146 | f->fid = GBIT32(p); 147 | p += BIT32SZ; 148 | f->mode = GBIT8(p); 149 | p += BIT8SZ; 150 | break; 151 | 152 | case Tcreate: 153 | if(p+BIT32SZ > ep) 154 | return 0; 155 | f->fid = GBIT32(p); 156 | p += BIT32SZ; 157 | p = gstring(p, ep, &f->name); 158 | if(p == nil) 159 | break; 160 | if(p+BIT32SZ+BIT8SZ > ep) 161 | return 0; 162 | f->perm = GBIT32(p); 163 | p += BIT32SZ; 164 | f->mode = GBIT8(p); 165 | p += BIT8SZ; 166 | break; 167 | 168 | case Tread: 169 | if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep) 170 | return 0; 171 | f->fid = GBIT32(p); 172 | p += BIT32SZ; 173 | f->offset = GBIT64(p); 174 | p += BIT64SZ; 175 | f->count = GBIT32(p); 176 | p += BIT32SZ; 177 | break; 178 | 179 | case Twrite: 180 | if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep) 181 | return 0; 182 | f->fid = GBIT32(p); 183 | p += BIT32SZ; 184 | f->offset = GBIT64(p); 185 | p += BIT64SZ; 186 | f->count = GBIT32(p); 187 | p += BIT32SZ; 188 | if(p+f->count > ep) 189 | return 0; 190 | f->data = (char*)p; 191 | p += f->count; 192 | break; 193 | 194 | case Tclunk: 195 | case Tremove: 196 | if(p+BIT32SZ > ep) 197 | return 0; 198 | f->fid = GBIT32(p); 199 | p += BIT32SZ; 200 | break; 201 | 202 | case Tstat: 203 | if(p+BIT32SZ > ep) 204 | return 0; 205 | f->fid = GBIT32(p); 206 | p += BIT32SZ; 207 | break; 208 | 209 | case Twstat: 210 | if(p+BIT32SZ+BIT16SZ > ep) 211 | return 0; 212 | f->fid = GBIT32(p); 213 | p += BIT32SZ; 214 | f->nstat = GBIT16(p); 215 | p += BIT16SZ; 216 | if(p+f->nstat > ep) 217 | return 0; 218 | f->stat = p; 219 | p += f->nstat; 220 | break; 221 | 222 | /* 223 | */ 224 | case Rversion: 225 | if(p+BIT32SZ > ep) 226 | return 0; 227 | f->msize = GBIT32(p); 228 | p += BIT32SZ; 229 | p = gstring(p, ep, &f->version); 230 | break; 231 | 232 | case Rerror: 233 | p = gstring(p, ep, &f->ename); 234 | f->errornum = 0; 235 | break; 236 | 237 | case Rflush: 238 | break; 239 | 240 | case Rauth: 241 | p = gqid(p, ep, &f->aqid); 242 | if(p == nil) 243 | break; 244 | break; 245 | 246 | case Rattach: 247 | p = gqid(p, ep, &f->qid); 248 | if(p == nil) 249 | break; 250 | break; 251 | 252 | case Rwalk: 253 | if(p+BIT16SZ > ep) 254 | return 0; 255 | f->nwqid = GBIT16(p); 256 | p += BIT16SZ; 257 | if(f->nwqid > MAXWELEM) 258 | return 0; 259 | for(i=0; inwqid; i++){ 260 | p = gqid(p, ep, &f->wqid[i]); 261 | if(p == nil) 262 | break; 263 | } 264 | break; 265 | 266 | case Ropen: 267 | case Ropenfd: 268 | case Rcreate: 269 | p = gqid(p, ep, &f->qid); 270 | if(p == nil) 271 | break; 272 | if(p+BIT32SZ > ep) 273 | return 0; 274 | f->iounit = GBIT32(p); 275 | p += BIT32SZ; 276 | if(f->type == Ropenfd){ 277 | if(p+BIT32SZ > ep) 278 | return 0; 279 | f->unixfd = GBIT32(p); 280 | p += BIT32SZ; 281 | } 282 | break; 283 | 284 | case Rread: 285 | if(p+BIT32SZ > ep) 286 | return 0; 287 | f->count = GBIT32(p); 288 | p += BIT32SZ; 289 | if(p+f->count > ep) 290 | return 0; 291 | f->data = (char*)p; 292 | p += f->count; 293 | break; 294 | 295 | case Rwrite: 296 | if(p+BIT32SZ > ep) 297 | return 0; 298 | f->count = GBIT32(p); 299 | p += BIT32SZ; 300 | break; 301 | 302 | case Rclunk: 303 | case Rremove: 304 | break; 305 | 306 | case Rstat: 307 | if(p+BIT16SZ > ep) 308 | return 0; 309 | f->nstat = GBIT16(p); 310 | p += BIT16SZ; 311 | if(p+f->nstat > ep) 312 | return 0; 313 | f->stat = p; 314 | p += f->nstat; 315 | break; 316 | 317 | case Rwstat: 318 | break; 319 | } 320 | 321 | if(p==nil || p>ep) 322 | return 0; 323 | if(ap+size == p) 324 | return size; 325 | return 0; 326 | } 327 | -------------------------------------------------------------------------------- /compat/lib9/convS2M.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static 6 | uchar* 7 | pstring(uchar *p, char *s) 8 | { 9 | uint n; 10 | 11 | if(s == nil){ 12 | PBIT16(p, 0); 13 | p += BIT16SZ; 14 | return p; 15 | } 16 | 17 | n = strlen(s); 18 | PBIT16(p, n); 19 | p += BIT16SZ; 20 | memmove(p, s, n); 21 | p += n; 22 | return p; 23 | } 24 | 25 | static 26 | uchar* 27 | pqid(uchar *p, Qid *q) 28 | { 29 | PBIT8(p, q->type); 30 | p += BIT8SZ; 31 | PBIT32(p, q->vers); 32 | p += BIT32SZ; 33 | PBIT64(p, q->path); 34 | p += BIT64SZ; 35 | return p; 36 | } 37 | 38 | static 39 | uint 40 | stringsz(char *s) 41 | { 42 | if(s == nil) 43 | return BIT16SZ; 44 | 45 | return BIT16SZ+strlen(s); 46 | } 47 | 48 | uint 49 | sizeS2M(Fcall *f) 50 | { 51 | uint n; 52 | int i; 53 | 54 | n = 0; 55 | n += BIT32SZ; /* size */ 56 | n += BIT8SZ; /* type */ 57 | n += BIT16SZ; /* tag */ 58 | 59 | switch(f->type) 60 | { 61 | default: 62 | return 0; 63 | 64 | case Tversion: 65 | n += BIT32SZ; 66 | n += stringsz(f->version); 67 | break; 68 | 69 | case Tflush: 70 | n += BIT16SZ; 71 | break; 72 | 73 | case Tauth: 74 | n += BIT32SZ; 75 | n += stringsz(f->uname); 76 | n += stringsz(f->aname); 77 | break; 78 | 79 | case Tattach: 80 | n += BIT32SZ; 81 | n += BIT32SZ; 82 | n += stringsz(f->uname); 83 | n += stringsz(f->aname); 84 | break; 85 | 86 | case Twalk: 87 | n += BIT32SZ; 88 | n += BIT32SZ; 89 | n += BIT16SZ; 90 | for(i=0; inwname; i++) 91 | n += stringsz(f->wname[i]); 92 | break; 93 | 94 | case Topen: 95 | case Topenfd: 96 | n += BIT32SZ; 97 | n += BIT8SZ; 98 | break; 99 | 100 | case Tcreate: 101 | n += BIT32SZ; 102 | n += stringsz(f->name); 103 | n += BIT32SZ; 104 | n += BIT8SZ; 105 | break; 106 | 107 | case Tread: 108 | n += BIT32SZ; 109 | n += BIT64SZ; 110 | n += BIT32SZ; 111 | break; 112 | 113 | case Twrite: 114 | n += BIT32SZ; 115 | n += BIT64SZ; 116 | n += BIT32SZ; 117 | n += f->count; 118 | break; 119 | 120 | case Tclunk: 121 | case Tremove: 122 | n += BIT32SZ; 123 | break; 124 | 125 | case Tstat: 126 | n += BIT32SZ; 127 | break; 128 | 129 | case Twstat: 130 | n += BIT32SZ; 131 | n += BIT16SZ; 132 | n += f->nstat; 133 | break; 134 | /* 135 | */ 136 | 137 | case Rversion: 138 | n += BIT32SZ; 139 | n += stringsz(f->version); 140 | break; 141 | 142 | case Rerror: 143 | n += stringsz(f->ename); 144 | break; 145 | 146 | case Rflush: 147 | break; 148 | 149 | case Rauth: 150 | n += QIDSZ; 151 | break; 152 | 153 | case Rattach: 154 | n += QIDSZ; 155 | break; 156 | 157 | case Rwalk: 158 | n += BIT16SZ; 159 | n += f->nwqid*QIDSZ; 160 | break; 161 | 162 | case Ropen: 163 | case Rcreate: 164 | n += QIDSZ; 165 | n += BIT32SZ; 166 | break; 167 | 168 | case Ropenfd: 169 | n += QIDSZ; 170 | n += BIT32SZ; 171 | n += BIT32SZ; 172 | break; 173 | 174 | case Rread: 175 | n += BIT32SZ; 176 | n += f->count; 177 | break; 178 | 179 | case Rwrite: 180 | n += BIT32SZ; 181 | break; 182 | 183 | case Rclunk: 184 | break; 185 | 186 | case Rremove: 187 | break; 188 | 189 | case Rstat: 190 | n += BIT16SZ; 191 | n += f->nstat; 192 | break; 193 | 194 | case Rwstat: 195 | break; 196 | } 197 | return n; 198 | } 199 | 200 | uint 201 | convS2M(Fcall *f, uchar *ap, uint nap) 202 | { 203 | uchar *p; 204 | uint i, size; 205 | 206 | size = sizeS2M(f); 207 | if(size == 0) 208 | return 0; 209 | if(size > nap) 210 | return 0; 211 | 212 | p = (uchar*)ap; 213 | 214 | PBIT32(p, size); 215 | p += BIT32SZ; 216 | PBIT8(p, f->type); 217 | p += BIT8SZ; 218 | PBIT16(p, f->tag); 219 | p += BIT16SZ; 220 | 221 | switch(f->type) 222 | { 223 | default: 224 | return 0; 225 | 226 | case Tversion: 227 | PBIT32(p, f->msize); 228 | p += BIT32SZ; 229 | p = pstring(p, f->version); 230 | break; 231 | 232 | case Tflush: 233 | PBIT16(p, f->oldtag); 234 | p += BIT16SZ; 235 | break; 236 | 237 | case Tauth: 238 | PBIT32(p, f->afid); 239 | p += BIT32SZ; 240 | p = pstring(p, f->uname); 241 | p = pstring(p, f->aname); 242 | break; 243 | 244 | case Tattach: 245 | PBIT32(p, f->fid); 246 | p += BIT32SZ; 247 | PBIT32(p, f->afid); 248 | p += BIT32SZ; 249 | p = pstring(p, f->uname); 250 | p = pstring(p, f->aname); 251 | break; 252 | 253 | case Twalk: 254 | PBIT32(p, f->fid); 255 | p += BIT32SZ; 256 | PBIT32(p, f->newfid); 257 | p += BIT32SZ; 258 | PBIT16(p, f->nwname); 259 | p += BIT16SZ; 260 | if(f->nwname > MAXWELEM) 261 | return 0; 262 | for(i=0; inwname; i++) 263 | p = pstring(p, f->wname[i]); 264 | break; 265 | 266 | case Topen: 267 | case Topenfd: 268 | PBIT32(p, f->fid); 269 | p += BIT32SZ; 270 | PBIT8(p, f->mode); 271 | p += BIT8SZ; 272 | break; 273 | 274 | case Tcreate: 275 | PBIT32(p, f->fid); 276 | p += BIT32SZ; 277 | p = pstring(p, f->name); 278 | PBIT32(p, f->perm); 279 | p += BIT32SZ; 280 | PBIT8(p, f->mode); 281 | p += BIT8SZ; 282 | break; 283 | 284 | case Tread: 285 | PBIT32(p, f->fid); 286 | p += BIT32SZ; 287 | PBIT64(p, f->offset); 288 | p += BIT64SZ; 289 | PBIT32(p, f->count); 290 | p += BIT32SZ; 291 | break; 292 | 293 | case Twrite: 294 | PBIT32(p, f->fid); 295 | p += BIT32SZ; 296 | PBIT64(p, f->offset); 297 | p += BIT64SZ; 298 | PBIT32(p, f->count); 299 | p += BIT32SZ; 300 | memmove(p, f->data, f->count); 301 | p += f->count; 302 | break; 303 | 304 | case Tclunk: 305 | case Tremove: 306 | PBIT32(p, f->fid); 307 | p += BIT32SZ; 308 | break; 309 | 310 | case Tstat: 311 | PBIT32(p, f->fid); 312 | p += BIT32SZ; 313 | break; 314 | 315 | case Twstat: 316 | PBIT32(p, f->fid); 317 | p += BIT32SZ; 318 | PBIT16(p, f->nstat); 319 | p += BIT16SZ; 320 | memmove(p, f->stat, f->nstat); 321 | p += f->nstat; 322 | break; 323 | /* 324 | */ 325 | 326 | case Rversion: 327 | PBIT32(p, f->msize); 328 | p += BIT32SZ; 329 | p = pstring(p, f->version); 330 | break; 331 | 332 | case Rerror: 333 | p = pstring(p, f->ename); 334 | break; 335 | 336 | case Rflush: 337 | break; 338 | 339 | case Rauth: 340 | p = pqid(p, &f->aqid); 341 | break; 342 | 343 | case Rattach: 344 | p = pqid(p, &f->qid); 345 | break; 346 | 347 | case Rwalk: 348 | PBIT16(p, f->nwqid); 349 | p += BIT16SZ; 350 | if(f->nwqid > MAXWELEM) 351 | return 0; 352 | for(i=0; inwqid; i++) 353 | p = pqid(p, &f->wqid[i]); 354 | break; 355 | 356 | case Ropen: 357 | case Rcreate: 358 | case Ropenfd: 359 | p = pqid(p, &f->qid); 360 | PBIT32(p, f->iounit); 361 | p += BIT32SZ; 362 | if(f->type == Ropenfd){ 363 | PBIT32(p, f->unixfd); 364 | p += BIT32SZ; 365 | } 366 | break; 367 | 368 | case Rread: 369 | PBIT32(p, f->count); 370 | p += BIT32SZ; 371 | memmove(p, f->data, f->count); 372 | p += f->count; 373 | break; 374 | 375 | case Rwrite: 376 | PBIT32(p, f->count); 377 | p += BIT32SZ; 378 | break; 379 | 380 | case Rclunk: 381 | break; 382 | 383 | case Rremove: 384 | break; 385 | 386 | case Rstat: 387 | PBIT16(p, f->nstat); 388 | p += BIT16SZ; 389 | memmove(p, f->stat, f->nstat); 390 | p += f->nstat; 391 | break; 392 | 393 | case Rwstat: 394 | break; 395 | } 396 | if(size != p-ap) 397 | return 0; 398 | return size; 399 | } 400 | -------------------------------------------------------------------------------- /compat/lib9/fcallfmt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static uint dumpsome(char*, char*, char*, long); 6 | static void fdirconv(char*, char*, Dir*); 7 | static char *qidtype(char*, uchar); 8 | 9 | #define QIDFMT "(%.16llux %lud %s)" 10 | 11 | int 12 | fcallfmt(Fmt *fmt) 13 | { 14 | Fcall *f; 15 | int fid, type, tag, i; 16 | char buf[512], tmp[200]; 17 | char *p, *e; 18 | Dir *d; 19 | Qid *q; 20 | 21 | e = buf+sizeof(buf); 22 | f = va_arg(fmt->args, Fcall*); 23 | type = f->type; 24 | fid = f->fid; 25 | tag = f->tag; 26 | switch(type){ 27 | case Tversion: /* 100 */ 28 | seprint(buf, e, "Tversion tag %ud msize %ud version '%s'", tag, f->msize, f->version); 29 | break; 30 | case Rversion: 31 | seprint(buf, e, "Rversion tag %ud msize %ud version '%s'", tag, f->msize, f->version); 32 | break; 33 | case Tauth: /* 102 */ 34 | seprint(buf, e, "Tauth tag %ud afid %d uname %s aname %s", tag, 35 | f->afid, f->uname, f->aname); 36 | break; 37 | case Rauth: 38 | seprint(buf, e, "Rauth tag %ud qid " QIDFMT, tag, 39 | f->aqid.path, f->aqid.vers, qidtype(tmp, f->aqid.type)); 40 | break; 41 | case Tattach: /* 104 */ 42 | seprint(buf, e, "Tattach tag %ud fid %d afid %d uname %s aname %s", tag, 43 | fid, f->afid, f->uname, f->aname); 44 | break; 45 | case Rattach: 46 | seprint(buf, e, "Rattach tag %ud qid " QIDFMT, tag, 47 | f->qid.path, f->qid.vers, qidtype(tmp, f->qid.type)); 48 | break; 49 | case Rerror: /* 107; 106 (Terror) illegal */ 50 | seprint(buf, e, "Rerror tag %ud ename %s", tag, f->ename); 51 | break; 52 | case Tflush: /* 108 */ 53 | seprint(buf, e, "Tflush tag %ud oldtag %ud", tag, f->oldtag); 54 | break; 55 | case Rflush: 56 | seprint(buf, e, "Rflush tag %ud", tag); 57 | break; 58 | case Twalk: /* 110 */ 59 | p = seprint(buf, e, "Twalk tag %ud fid %d newfid %d nwname %d ", tag, fid, f->newfid, f->nwname); 60 | if(f->nwname <= MAXWELEM) 61 | for(i=0; inwname; i++) 62 | p = seprint(p, e, "%d:%s ", i, f->wname[i]); 63 | break; 64 | case Rwalk: 65 | p = seprint(buf, e, "Rwalk tag %ud nwqid %ud ", tag, f->nwqid); 66 | if(f->nwqid <= MAXWELEM) 67 | for(i=0; inwqid; i++){ 68 | q = &f->wqid[i]; 69 | p = seprint(p, e, "%d:" QIDFMT " ", i, 70 | q->path, q->vers, qidtype(tmp, q->type)); 71 | } 72 | break; 73 | case Topen: /* 112 */ 74 | seprint(buf, e, "Topen tag %ud fid %ud mode %d", tag, fid, f->mode); 75 | break; 76 | case Ropen: 77 | seprint(buf, e, "Ropen tag %ud qid " QIDFMT " iounit %ud", tag, 78 | f->qid.path, f->qid.vers, qidtype(tmp, f->qid.type), f->iounit); 79 | break; 80 | case Topenfd: /* 98 */ 81 | seprint(buf, e, "Topenfd tag %ud fid %ud mode %d", tag, fid, f->mode); 82 | break; 83 | case Ropenfd: 84 | seprint(buf, e, "Ropenfd tag %ud qid " QIDFMT " iounit %ud unixfd %d", tag, 85 | f->qid.path, f->qid.vers, qidtype(tmp, f->qid.type), f->iounit, f->unixfd); 86 | break; 87 | case Tcreate: /* 114 */ 88 | seprint(buf, e, "Tcreate tag %ud fid %ud name %s perm %M mode %d", tag, fid, f->name, (ulong)f->perm, f->mode); 89 | break; 90 | case Rcreate: 91 | seprint(buf, e, "Rcreate tag %ud qid " QIDFMT " iounit %ud ", tag, 92 | f->qid.path, f->qid.vers, qidtype(tmp, f->qid.type), f->iounit); 93 | break; 94 | case Tread: /* 116 */ 95 | seprint(buf, e, "Tread tag %ud fid %d offset %lld count %ud", 96 | tag, fid, f->offset, f->count); 97 | break; 98 | case Rread: 99 | p = seprint(buf, e, "Rread tag %ud count %ud ", tag, f->count); 100 | dumpsome(p, e, f->data, f->count); 101 | break; 102 | case Twrite: /* 118 */ 103 | p = seprint(buf, e, "Twrite tag %ud fid %d offset %lld count %ud ", 104 | tag, fid, f->offset, f->count); 105 | dumpsome(p, e, f->data, f->count); 106 | break; 107 | case Rwrite: 108 | seprint(buf, e, "Rwrite tag %ud count %ud", tag, f->count); 109 | break; 110 | case Tclunk: /* 120 */ 111 | seprint(buf, e, "Tclunk tag %ud fid %ud", tag, fid); 112 | break; 113 | case Rclunk: 114 | seprint(buf, e, "Rclunk tag %ud", tag); 115 | break; 116 | case Tremove: /* 122 */ 117 | seprint(buf, e, "Tremove tag %ud fid %ud", tag, fid); 118 | break; 119 | case Rremove: 120 | seprint(buf, e, "Rremove tag %ud", tag); 121 | break; 122 | case Tstat: /* 124 */ 123 | seprint(buf, e, "Tstat tag %ud fid %ud", tag, fid); 124 | break; 125 | case Rstat: 126 | p = seprint(buf, e, "Rstat tag %ud ", tag); 127 | if(f->stat == nil || f->nstat > sizeof tmp) 128 | seprint(p, e, " stat(%d bytes)", f->nstat); 129 | else{ 130 | d = (Dir*)tmp; 131 | convM2D(f->stat, f->nstat, d, (char*)(d+1)); 132 | seprint(p, e, " stat "); 133 | fdirconv(p+6, e, d); 134 | } 135 | break; 136 | case Twstat: /* 126 */ 137 | p = seprint(buf, e, "Twstat tag %ud fid %ud", tag, fid); 138 | if(f->stat == nil || f->nstat > sizeof tmp) 139 | seprint(p, e, " stat(%d bytes)", f->nstat); 140 | else{ 141 | d = (Dir*)tmp; 142 | convM2D(f->stat, f->nstat, d, (char*)(d+1)); 143 | seprint(p, e, " stat "); 144 | fdirconv(p+6, e, d); 145 | } 146 | break; 147 | case Rwstat: 148 | seprint(buf, e, "Rwstat tag %ud", tag); 149 | break; 150 | default: 151 | seprint(buf, e, "unknown type %d", type); 152 | } 153 | return fmtstrcpy(fmt, buf); 154 | } 155 | 156 | static char* 157 | qidtype(char *s, uchar t) 158 | { 159 | char *p; 160 | 161 | p = s; 162 | if(t & QTDIR) 163 | *p++ = 'd'; 164 | if(t & QTAPPEND) 165 | *p++ = 'a'; 166 | if(t & QTEXCL) 167 | *p++ = 'l'; 168 | if(t & QTAUTH) 169 | *p++ = 'A'; 170 | *p = '\0'; 171 | return s; 172 | } 173 | 174 | int 175 | dirfmt(Fmt *fmt) 176 | { 177 | char buf[160]; 178 | 179 | fdirconv(buf, buf+sizeof buf, va_arg(fmt->args, Dir*)); 180 | return fmtstrcpy(fmt, buf); 181 | } 182 | 183 | static void 184 | fdirconv(char *buf, char *e, Dir *d) 185 | { 186 | char tmp[16]; 187 | 188 | seprint(buf, e, "'%s' '%s' '%s' '%s' " 189 | "q " QIDFMT " m %#luo " 190 | "at %ld mt %ld l %lld " 191 | "t %d d %d", 192 | d->name, d->uid, d->gid, d->muid, 193 | d->qid.path, d->qid.vers, qidtype(tmp, d->qid.type), d->mode, 194 | d->atime, d->mtime, d->length, 195 | d->type, d->dev); 196 | } 197 | 198 | /* 199 | * dump out count (or DUMPL, if count is bigger) bytes from 200 | * buf to ans, as a string if they are all printable, 201 | * else as a series of hex bytes 202 | */ 203 | #define DUMPL 64 204 | 205 | static uint 206 | dumpsome(char *ans, char *e, char *buf, long count) 207 | { 208 | int i, printable; 209 | char *p; 210 | 211 | if(buf == nil){ 212 | seprint(ans, e, ""); 213 | return strlen(ans); 214 | } 215 | printable = 1; 216 | if(count > DUMPL) 217 | count = DUMPL; 218 | for(i=0; i127) 220 | printable = 0; 221 | p = ans; 222 | *p++ = '\''; 223 | if(printable){ 224 | if(2*count > e-p-2) 225 | count = (e-p-2)/2; 226 | for(i=0; i e-p-2) 241 | count = (e-p-2)/2; 242 | for(i=0; i0 && i%4==0) 244 | *p++ = ' '; 245 | sprint(p, "%2.2ux", (uchar)buf[i]); 246 | p += 2; 247 | } 248 | } 249 | *p++ = '\''; 250 | *p = 0; 251 | assert(p < e); 252 | return p - ans; 253 | } 254 | -------------------------------------------------------------------------------- /compat/lib9/open.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE /* for Linux O_DIRECT */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define NOPLAN9DEFINES 8 | #include 9 | 10 | static struct { 11 | Lock lk; 12 | DIR **d; 13 | int nd; 14 | } dirs; 15 | 16 | static int 17 | dirput(int fd, DIR *d) 18 | { 19 | int i, nd; 20 | DIR **dp; 21 | 22 | if(fd < 0) { 23 | werrstr("invalid fd"); 24 | return -1; 25 | } 26 | lock(&dirs.lk); 27 | if(fd >= dirs.nd) { 28 | nd = dirs.nd*2; 29 | if(nd <= fd) 30 | nd = fd+1; 31 | dp = realloc(dirs.d, nd*sizeof dirs.d[0]); 32 | if(dp == nil) { 33 | werrstr("out of memory"); 34 | unlock(&dirs.lk); 35 | return -1; 36 | } 37 | for(i=dirs.nd; i= 0){ 120 | if(lock){ 121 | fl.l_type = (rdwr==OREAD) ? F_RDLCK : F_WRLCK; 122 | fl.l_whence = SEEK_SET; 123 | fl.l_start = 0; 124 | fl.l_len = 0; 125 | if(fcntl(fd, F_SETLK, &fl) < 0){ 126 | close(fd); 127 | werrstr("lock: %r"); 128 | return -1; 129 | } 130 | } 131 | if(cexec) 132 | fcntl(fd, F_SETFL, FD_CLOEXEC); 133 | if(rclose) 134 | remove(path); 135 | } 136 | return fd; 137 | } 138 | 139 | int 140 | p9open(char *name, int mode) 141 | { 142 | int cexec, rclose; 143 | int fd, umode, lock, rdwr; 144 | struct flock fl; 145 | struct stat st; 146 | DIR *d; 147 | 148 | rdwr = mode&3; 149 | umode = rdwr; 150 | cexec = mode&OCEXEC; 151 | rclose = mode&ORCLOSE; 152 | lock = mode&OLOCK; 153 | mode &= ~(3|OCEXEC|ORCLOSE|OLOCK); 154 | if(mode&OTRUNC){ 155 | umode |= O_TRUNC; 156 | mode ^= OTRUNC; 157 | } 158 | if(mode&ODIRECT){ 159 | umode |= O_DIRECT; 160 | mode ^= ODIRECT; 161 | } 162 | if(mode&ONONBLOCK){ 163 | umode |= O_NONBLOCK; 164 | mode ^= ONONBLOCK; 165 | } 166 | if(mode&OAPPEND){ 167 | umode |= O_APPEND; 168 | mode ^= OAPPEND; 169 | } 170 | if(mode){ 171 | werrstr("mode 0x%x not supported", mode); 172 | return -1; 173 | } 174 | fd = open(name, umode); 175 | if(fd >= 0){ 176 | if(lock){ 177 | fl.l_type = (rdwr==OREAD) ? F_RDLCK : F_WRLCK; 178 | fl.l_whence = SEEK_SET; 179 | fl.l_start = 0; 180 | fl.l_len = 0; 181 | if(fcntl(fd, F_SETLK, &fl) < 0){ 182 | close(fd); 183 | werrstr("lock: %r"); 184 | return -1; 185 | } 186 | } 187 | if(cexec) 188 | fcntl(fd, F_SETFL, FD_CLOEXEC); 189 | if(fstat(fd, &st) >= 0 && S_ISDIR(st.st_mode)) { 190 | d = fdopendir(fd); 191 | if(d == nil) { 192 | close(fd); 193 | return -1; 194 | } 195 | if(dirput(fd, d) < 0) { 196 | closedir(d); 197 | return -1; 198 | } 199 | } 200 | if(rclose) 201 | remove(name); 202 | } 203 | return fd; 204 | } 205 | 206 | vlong 207 | p9seek(int fd, vlong offset, int whence) 208 | { 209 | DIR *d; 210 | 211 | if((d = dirget(fd)) != nil) { 212 | if(whence == 1 && offset == 0) 213 | return telldir(d); 214 | if(whence == 0) { 215 | seekdir(d, offset); 216 | return 0; 217 | } 218 | werrstr("bad seek in directory"); 219 | return -1; 220 | } 221 | 222 | return lseek(fd, offset, whence); 223 | } 224 | 225 | int 226 | p9close(int fd) 227 | { 228 | DIR *d; 229 | 230 | if((d = dirdel(fd)) != nil) 231 | return closedir(d); 232 | return close(fd); 233 | } 234 | 235 | typedef struct DirBuild DirBuild; 236 | struct DirBuild { 237 | Dir *d; 238 | int nd; 239 | int md; 240 | char *str; 241 | char *estr; 242 | }; 243 | 244 | extern int _p9dir(struct stat*, struct stat*, char*, Dir*, char**, char*); 245 | 246 | static int 247 | dirbuild1(DirBuild *b, struct stat *lst, struct stat *st, char *name) 248 | { 249 | int i, nstr; 250 | Dir *d; 251 | int md, mstr; 252 | char *lo, *hi, *newlo; 253 | 254 | nstr = _p9dir(lst, st, name, nil, nil, nil); 255 | if(b->md-b->nd < 1 || b->estr-b->str < nstr) { 256 | // expand either d space or str space or both. 257 | md = b->md; 258 | if(b->md-b->nd < 1) { 259 | md *= 2; 260 | if(md < 16) 261 | md = 16; 262 | } 263 | mstr = b->estr-(char*)&b->d[b->md]; 264 | if(b->estr-b->str < nstr) { 265 | mstr += nstr; 266 | mstr += mstr/2; 267 | } 268 | if(mstr < 512) 269 | mstr = 512; 270 | d = realloc(b->d, md*sizeof d[0] + mstr); 271 | if(d == nil) 272 | return -1; 273 | // move strings and update pointers in Dirs 274 | lo = (char*)&b->d[b->md]; 275 | newlo = (char*)&d[md]; 276 | hi = b->str; 277 | memmove(newlo, lo+((char*)d-(char*)b->d), hi-lo); 278 | for(i=0; ind; i++) { 279 | if(lo <= d[i].name && d[i].name < hi) 280 | d[i].name += newlo - lo; 281 | if(lo <= d[i].uid && d[i].uid < hi) 282 | d[i].uid += newlo - lo; 283 | if(lo <= d[i].gid && d[i].gid < hi) 284 | d[i].gid += newlo - lo; 285 | if(lo <= d[i].muid && d[i].muid < hi) 286 | d[i].muid += newlo - lo; 287 | } 288 | b->d = d; 289 | b->md = md; 290 | b->str += newlo - lo; 291 | b->estr = newlo + mstr; 292 | } 293 | _p9dir(lst, st, name, &b->d[b->nd], &b->str, b->estr); 294 | b->nd++; 295 | return 0; 296 | } 297 | 298 | static long 299 | dirreadmax(int fd, Dir **dp, int max) 300 | { 301 | int i; 302 | DIR *dir; 303 | DirBuild b; 304 | struct dirent *de; 305 | struct stat st, lst; 306 | 307 | if((dir = dirget(fd)) == nil) { 308 | werrstr("not a directory"); 309 | return -1; 310 | } 311 | 312 | memset(&b, 0, sizeof b); 313 | for(i=0; max == -1 || id_name[0]=='.' && de->d_name[1]==0) 323 | continue; 324 | if(de->d_name[0]=='.' && de->d_name[1]=='.' && de->d_name[2]==0) 325 | continue; 326 | if(fstatat(fd, de->d_name, &lst, AT_SYMLINK_NOFOLLOW) < 0) 327 | continue; 328 | st = lst; 329 | if(S_ISLNK(lst.st_mode)) 330 | fstatat(fd, de->d_name, &st, 0); 331 | dirbuild1(&b, &lst, &st, de->d_name); 332 | } 333 | *dp = b.d; 334 | return b.nd; 335 | } 336 | 337 | long 338 | dirread(int fd, Dir **dp) 339 | { 340 | return dirreadmax(fd, dp, 10); 341 | } 342 | 343 | long 344 | dirreadall(int fd, Dir **dp) 345 | { 346 | return dirreadmax(fd, dp, -1); 347 | } 348 | --------------------------------------------------------------------------------