# HG changeset patch # User Francisco J Ballesteros # Date 1329923289 -3600 # Node ID 0a28e31635376cca8751312157727dcc79f6a453 # Parent 104e7add5754e0f6c392e4307c1735dacd23dc82 ix: is gone. it was not creepy enough. use creepy for that. and we always have the dump. R=nixiedev CC=nix-dev http://codereview.appspot.com/5685053 diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/GET.out --- a/sys/src/cmd/ix/GET.out Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -dial tcp!localhost!9999 -session[24fd8]: new tcp!localhost!9999 -rproc[24fd8]: started -wproc[24fd8]: started -cmuxproc[4b738]: starting -cmuxproc[4b738]: new ch0 0x4e720 -chwproc[4e720]: started --ch0-> Tversion msize 8192 version 'ix' -|ch0-> Tattach afid -1 uname nemo aname main -chwproc[4e720]: exiting -<-ch0- Rversion msize 8190 version 'ix' -msize 8190 -cmuxproc[4b738]:2: del ch0 -<-ch0| Rattach fid 0 qid (0000000000000054 692693930 d) -cmuxproc[4b738]: new ch0 0x51710 -chwproc[51710]: started --ch0-> Tfid fid 0 cflags 0 --ch0-> Tclone cflags 3 --ch0-> Twalk wname acme.dump --ch0-> Tstat --ch0-> Topen mode 0 -|ch0-> Tread nmsg -1 offset 0 count 8190 -<-ch0- Rfid -chwproc[51710]: exiting -<-ch0- Rclone newfid 1 -<-ch0- Rwalk wqid (0000000000efd4d2 100 ) -<-ch0- Rstat stat 'acme.dump' 'nemo' 'nemo' 'nemo' q (0000000000efd4d2 100 ) m 0600 at 1313355326 mt 1310326405 l 33686 t 77 d 13 -<-ch0- Ropen qid (0000000000efd4d2 100 ) iounit 0 -<-ch0- Rread count 8185 '/usr/nemo /lib/font/bit/inferno/charon/plain.normal.font /lib/fo' -<-ch0- Rread count 8185 ' rm -f *.[5687qv] *.a[5687qv] y.tab.? lex.yy.c y.debug y.output ' -<-ch0- Rread count 8185 '57.6 tcp.6 ioapic.6 devsrv.6 ipaux.6 devenv.6 devdup.6 devpipe.6' -<-ch0- Rread count 8185 ' $names 6c -FTVw -I. -D'_DBGC_=''p''' ../port/page.c r - printst' -<-ch0- Rread count 946 ' ethermii.6 etherigbe.6 devproc.6 devkprof.6 netlog.6 nullmedium' -<-ch0| Rread count 0 '' -cmuxproc[4b738]:2: del ch0 -closemux 4b738 -abortconn[24fd8]: hanging up -wproc[24fd8]: exiting -cmuxproc[4b738]: done -rproc[24fd8]: exiting diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/PUT.out --- a/sys/src/cmd/ix/PUT.out Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -dial tcp!localhost!9999 -session[24fd8]: new tcp!localhost!9999 -rproc[24fd8]: started -wproc[24fd8]: started -cmuxproc[4b738]: starting -cmuxproc[4b738]: new ch0 0x4e720 -chwproc[4e720]: started --ch0-> Tversion msize 8192 version 'ix' -|ch0-> Tattach afid -1 uname nemo aname main -chwproc[4e720]: exiting -<-ch0- Rversion msize 8190 version 'ix' -msize 8190 -cmuxproc[4b738]:2: del ch0 -<-ch0| Rattach fid 0 qid (0000000000000054 692693930 d) -cmuxproc[4b738]: new ch0 0x517d0 -chwproc[517d0]: started --ch0-> Tfid fid 0 cflags 0 --ch0-> Tclone cflags 3 --ch0-> Tcreate name adump perm %M% mode 384 -<-ch0- Rfid -<-ch0- Rclone newfid 1 -<-ch0- Rcreate qid (00000000026b920f 0 ) iounit 0 --ch0-> Twrite offset 0 count 8177 '00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000' --ch0-> Twrite offset 8177 count 8177 '00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000' --ch0-> Twrite offset 16354 count 8177 '00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000' --ch0-> Twrite offset 24531 count 8177 '00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000' --ch0-> Twrite offset 32708 count 978 '00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0b000080' -closech ch0 -chwproc[517d0]: ch0: nil msg -<-ch0- Rwrite count 8177 -<-ch0- Rwrite count 8177 -<-ch0- Rwrite count 8177 -<-ch0- Rwrite count 8177 -<-ch0- Rwrite count 978 -cmuxproc[4b738]:1: del ch0 -closemux 4b738 -chwproc[517d0]: exiting -abortconn[24fd8]: hanging up -wproc[24fd8]: exiting -cmuxproc[4b738]: done -rproc[24fd8]: exiting diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/SRV.out --- a/sys/src/cmd/ix/SRV.out Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -announce tcp!*!9999 -session[2aa50]: new tcp!*!9999 -fssrvproc: 2cbe8 tcp!*!9999 -fsrpc[2aa50!0]: new chan tcp!*!9999 -<-ch0- Tversion msize 8192 version 'ix' --ch0-> Rversion msize 8190 version 'ix' -<-ch0| Tattach afid -1 uname nemo aname main -|ch0-> Rattach fid 0 qid (0000000000000054 692693930 d) -fsrpc[2aa50!0]: done -cmuxproc[537e8]:1: del ch0 -fsrpc[2aa50!0]: new chan tcp!*!9999 -<-ch0- Tfid fid 0 cflags 0 --ch0-> Rfid -<-ch0- Tclone cflags 3 --ch0-> Rclone newfid 1 -<-ch0- Twalk wname acme.dump --ch0-> Rwalk wqid (0000000000efd4d2 100 ) -<-ch0- Tstat --ch0-> Rstat stat 'acme.dump' 'nemo' 'nemo' 'nemo' q (0000000000efd4d2 100 ) m 0600 at 1313355326 mt 1310326405 l 33686 t 77 d 13 -<-ch0- Topen mode 0 --ch0-> Ropen qid (0000000000efd4d2 100 ) iounit 0 -<-ch0| Tread nmsg -1 offset 0 count 8190 --ch0-> Rread count 8185 '/usr/nemo /lib/font/bit/inferno/charon/plain.normal.font /lib/fo' --ch0-> Rread count 8185 ' rm -f *.[5687qv] *.a[5687qv] y.tab.? lex.yy.c y.debug y.output ' --ch0-> Rread count 8185 '57.6 tcp.6 ioapic.6 devsrv.6 ipaux.6 devenv.6 devdup.6 devpipe.6' --ch0-> Rread count 8185 ' $names 6c -FTVw -I. -D'_DBGC_=''p''' ../port/page.c r - printst' --ch0-> Rread count 946 ' ethermii.6 etherigbe.6 devproc.6 devkprof.6 netlog.6 nullmedium' -|ch0-> Rread count 0 '' -cmuxproc[537e8]:1: del ch0 -fsrpc[2aa50!0]: done -cmuxproc[537e8]: eof -closemux 537e8 -abortconn[2aa50]: hanging up -fssrvproc[2cbe8]: done -cmuxproc[537e8]: done -session[2aaf0]: new tcp!*!9999 -fssrvproc: 2cb48 tcp!*!9999 -fsrpc[2aaf0!0]: new chan tcp!*!9999 -<-ch0- Tversion msize 8192 version 'ix' --ch0-> Rversion msize 8190 version 'ix' -<-ch0| Tattach afid -1 uname nemo aname main -|ch0-> Rattach fid 0 qid (0000000000000054 692693930 d) -fsrpc[2aaf0!0]: done -cmuxproc[5b130]:1: del ch0 -fsrpc[2aaf0!0]: new chan tcp!*!9999 -<-ch0- Tfid fid 0 cflags 0 --ch0-> Rfid -<-ch0- Tclone cflags 3 --ch0-> Rclone newfid 1 -<-ch0- Tcreate name adump perm --rw------- mode 1 --ch0-> Rcreate qid (00000000026b920f 0 ) iounit 0 -<-ch0- Twrite offset 0 count 8177 '/usr/nemo /lib/font/bit/inferno/charon/plain.normal.font /lib/fo' --ch0-> Rwrite count 8177 -<-ch0- Twrite offset 8177 count 8177 'EANFILES rm -f *.[5687qv] *.a[5687qv] y.tab.? lex.yy.c y.debug y' --ch0-> Rwrite count 8177 -<-ch0- Twrite offset 16354 count 8177 'edium.6 ether82557.6 tcp.6 ioapic.6 devsrv.6 ipaux.6 devenv.6 de' --ch0-> Rwrite count 8177 -<-ch0- Twrite offset 24531 count 8177 'oot/libboot.a6 $names rm $names 6c -FTVw -I. -D'_DBGC_=''p''' ..' --ch0-> Rwrite count 8177 -<-ch0- Twrite offset 32708 count 978 '6 ether82563.6 devip.6 devuart.6 ethermii.6 etherigbe.6 devproc.' --ch0-> Rwrite count 978 -ch0: eof -fsrpc[2aaf0!0]: done -cmuxproc[5b130]:1: del ch0 -cmuxproc[5b130]: eof -closemux 5b130 -abortconn[2aaf0]: hanging up -cmuxproc[5b130]: done -fssrvproc[2cb48]: done diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/catixd.c --- a/sys/src/cmd/ix/catixd.c Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,148 +0,0 @@ -#include -#include -#include -#include -#include - - -static char* -qidtype(char *s, uchar t) -{ - char *p; - - p = s; - if(t & QTDIR) - *p++ = 'd'; - if(t & QTAPPEND) - *p++ = 'a'; - if(t & QTEXCL) - *p++ = 'l'; - if(t & QTAUTH) - *p++ = 'A'; - *p = '\0'; - return s; -} - - -static void -fdirconv(char *buf, char *e, Dir *d) -{ - char tmp[16]; - - seprint(buf, e, "%s '%s' " - "(%llux %lud %s) %#luo l %lld", d->name, - d->uid, - d->qid.path, d->qid.vers, qidtype(tmp, d->qid.type), d->mode, - d->length); -} - -static int -shortdirfmt(Fmt *fmt) -{ - char buf[160]; - - fdirconv(buf, buf+sizeof buf, va_arg(fmt->args, Dir*)); - return fmtstrcpy(fmt, buf); -} - -static Dir* -readdir(Biobuf *bin, char *p) -{ - static uchar buf[DIRMAX]; - ulong sz; - Dir *d; - - if(Bread(bin, buf, BIT16SZ) != BIT16SZ) - sysfatal("%s: eof", p); - sz = GBIT16(buf); - if(BIT16SZ + sz > sizeof buf) - sysfatal("%s: dir too long", p); - if(Bread(bin, buf + BIT16SZ, sz) != sz) - sysfatal("%s: read failed", p); - d = malloc(sizeof *d + sz); - if(convM2D(buf, sizeof buf, d, (char*)(d+1)) <= 0) - sysfatal("%s: convM2D failed", p); - return d; -} - -static int -loaddir(Biobuf *bin, char *parent) -{ - Dir *d, *sd; - int nchild; - char *p, *path; - char tmp[16]; - - p = "/"; - if(parent != nil) - p = parent; - d = readdir(bin, p); - if(d == nil) - return -1; - sd = readdir(bin, p); - if(sd == nil){ - free(d); - return -1; - } - if(parent == nil) - path = "."; - else - path = smprint("%s/%s", parent, d->name); - if(sd->qid.path == ~0ULL && sd->qid.vers == ~0 && sd->qid.type == 0xFF) - print("'%s' sq nulldir %D\n", path, d); - else - print("'%s' sq (%llux %lud %s) %D\n", - path, sd->qid.path, sd->qid.vers, - qidtype(tmp, sd->qid.type), d); - if(d->qid.type&QTDIR){ - nchild = d->length; - d->length = 0; - while(nchild-- > 0) - if(loaddir(bin, path) < 0) - break; - } - free(d); - free(sd); - return 0; -} - -static void -catixd(char *fname) -{ - Biobuf *bin; - - bin = Bopen(fname, OREAD); - if(bin == nil) - sysfatal("%s: %r", fname); - loaddir(bin, nil); - Bterm(bin); -} - -static void -usage(void) -{ - fprint(2, "usage: %s [file...]\n", argv0); - exits("usage"); -} - -void -main(int argc, char *argv[]) -{ - int i; - - ARGBEGIN{ - default: - usage(); - }ARGEND; - fmtinstall('M', dirmodefmt); - fmtinstall('D', shortdirfmt); - if(argc == 0) - catixd("/fd/0"); - else - for(i = 0; i < argc; i++){ - print("%s:\n", argv[i]); - catixd(argv[i]); - } - exits(0); -} - diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/cfile.c --- a/sys/src/cmd/ix/cfile.c Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,656 +0,0 @@ -#include -#include -#include -#include -#include - -#include "conf.h" -#include "msg.h" -#include "ch.h" -#include "mpool.h" -#include "tses.h" -#include "fs.h" -#include "file.h" -#include "cfile.h" -#include "ixreqs.h" -#include "dbg.h" - -/* - * Conflict policy: - * upon conflicts, we report the conflict and save the local - * change in the local cache. The saved file is ignored for pulls/pushes. - * The user may resolve by removing the saved copy or using it to - * update the server's file. - * - * Removed files: - * - removed files must stay with the removed flag until - * any conflict is resolved: - * - removed in the server: - * the cache file is renamed and we are back in sync. - * - removed in the client: - * there's no local version to keep; just report - * and we are back in sync. - */ - -static void updatefile(File *f); -static int condpull(File *f); -static int condremove(File *f); - -static Cmux *cmux; -static File *root; -static int disc; -static int rootfid; -static int twritehdrsz; - -extern ulong msz; - -File* -crootfile(void) -{ - incref(root); - return root; -} - -void -cputfile(File *f) -{ - putfile(f); -} - -static void -disconnected(void) -{ - if(disc++) - return; - fprint(2, "%s: disconnected: %r\n", argv0); -} - -/* - * There's a conflict in f due to concurrent changes in server and client. - * Copy our local version to a conflicting name and pull the server version. - */ -static void -conflict(File *f) -{ - Dir d; - - nulldir(&d); - d.name = esmprint("%s.!!", f->d->name); - if(dirwstat(f->path, &d) < 0) - fprint(2, "conflict in %s. not copied.\n", f->path); - else - fprint(2, "conflict in %s. copied to %s.!!\n", f->path, f->path); - free(d.name); - - free(f->sd); - f->sd = nil; - condpull(f); -} - -static long -gotdents(File *f, uchar *a, long n) -{ - Dir d; - char buf[512]; - int ns, fd; - File *nf; - - while(n > 0){ - ns = convM2D(a, n, &d, buf); - if(ns <= 0){ - dcprint("%s: gotdents: %s: convM2D\n", argv0, f->path); - return -1; - } - a += ns; - n -= ns; - nf = getchild(f, d.name); - if(nf == nil){ - nf = f; - incref(f); - fd = createfile(&nf, d.name, OREAD, d.mode); - if(fd < 0){ - putfile(f); - dcprint("%s: gotdents: %s/%s: %r\n", - argv0, f->path, d.name); - }else - close(fd); - /* f->sd is nil, and it will be retrieved by updatefile */ - }else{ - if(nf->sremoved){ /* it came back to life */ - free(nf->sd); - nf->sd = nil; - } - if(nf->sd == nil) - nf->sd = dupdir(&d); - } - nf->visited = 1; - /* don't putfile(nf); gotdir releases all child refs */ - } - return 0; -} - -static void -gotdir(File *f) -{ - File *cf; - int chg; - - rlock(f); - for(cf = f->child; cf != nil; cf = cf->next){ - if(cf->sd == nil) - updatefile(cf); - else if(cf->visited == 0) - cf->sremoved = 1; - cf->visited = 0; - putfile(cf); - } -Again: - for(cf = f->child; cf != nil; cf = cf->next) - if(cf->sremoved){ - chg = filechanged(cf); - if(chg && (chg&Gone) == 0) - conflict(cf); - else{ - runlock(f); - removefile(cf); - rlock(f); - goto Again; - } - } - runlock(f); -} - -static int -walkpath(Ch *ch, File *f) -{ - int n; - - if(f->parent == nil) - return 0; - n = walkpath(ch, f->parent); - xtwalk(ch, f->d->name, 0); - return n + 1; -} - -/* - * Get a chan and send fid, clone, and walk requests to get to the file. - * it's ok if f is nil, and that means also / - */ -static int -walktofile(File *f, Ch **chp, int *nwalksp, char *why) -{ - Ch *ch; - - if(disc) - return -1; - ch = newch(cmux); - if(ch == nil){ - disconnected(); - dcprint("%s %s: newch %r\n", why, f ? f->path : "/"); - return -1; - } - xtfid(ch, root->fid, 0); - xtclone(ch, OCEND|OCERR, 0); - if(f == nil) - *nwalksp = 0; - else - *nwalksp = walkpath(ch, f); - *chp = ch; - return 0; -} - -/* - * Get the file, cond that it has changed. - * Save it at a temporary place and replace the cached - * one with the new one. - * Return 0 if ok or disconnected. 1 if file changed. -1 upon errors. - */ -static int -condpull(File *f) -{ - Ch *ch; - int fd, i, nwalks; - Dir d, wd; - char *fn, buf[512]; - uvlong offset; - long nr; - Msg *m; - - if(walktofile(f, &ch, &nwalks, "pull") < 0) - return 0; - /* - * If we got it from server, cond that it changed or we are done. - */ - if(f->sd != nil) - xtcond(ch, CNE, f->sd, 0); - xtstat(ch, 0); - /* - * If we got it from server, cond that data changed or we are done. - */ - if(f->sd != nil){ - nulldir(&wd); - wd.qid = f->sd->qid; - wd.mtime = f->sd->mtime; - xtcond(ch, CNE, &wd, 0); - } - xtopen(ch, OREAD, 0); - xtread(ch, -1, 0ULL, msz, 1); - - fn = nil; - fd = -1; - if(xrfid(ch) < 0 || xrclone(ch) < 0) - goto Fail; - for(i = 0; i < nwalks; i++) - if(xrwalk(ch, nil) < 0){ - rerrstr(buf, sizeof buf); - if(strstr(buf, "not exist") != 0){ - f->sremoved = 1; - goto Done; - } - goto Fail; - } - - if(f->sd != nil) - if(xrcond(ch) < 0) - return 0; /* file is up to date; we are done */ - if(xrstat(ch, &d, buf) < 0) - goto Fail; - - if(f->sd != nil) - if(xrcond(ch) < 0) /* data didn't change; we are done */ - goto Done; - - if(xropen(ch) < 0) - goto Fail; - - /* - * create the directory in case it does not exist, or a temporary - * file to retrieve the new version from the server. - */ - if((d.qid.type&QTDIR) != 0){ - fd = create(f->path, OREAD, d.mode); /* ignore errors */ - close(fd); - fd = -1; - }else{ - fn = tmpfile(f->path); - fd = create(fn, OWRITE, d.mode); - if(fd < 0){ - abortch(ch); - goto Fail; - } - } - - /* - * Gather data or directory entries or file data. - */ - offset = 0ULL; - do{ - m = xrread(ch); - if(m == nil){ - dcprint("%s: read: %r\n", f->path); - goto Fail; - } - nr = IOLEN(m->io); - if(nr > 0){ - if(d.qid.type&QTDIR) - nr = gotdents(f, m->io->rp, nr); - else - nr = pwrite(fd, m->io->rp, nr, offset); - if(nr < 0){ - abortch(ch); - freemsg(m); - goto Fail; - } - } - offset += nr; - freemsg(m); - }while(nr > 0); - - /* - * Got everything, merge dir entries or move data into place. - */ - if(d.qid.type&QTDIR){ - gotdir(f); - } - if(wstatfile(f, &d) < 0) - goto Fail; -Done: - free(f->sd); - f->sd = dupdir(&d); - if(fn != nil){ - remove(fn); /* mail fail, if we could rename it */ - free(fn); - } - if(fd >= 0) - close(fd); - return 1; - -Fail: - if(fn != nil){ - remove(fn); - free(fn); - } - if(fd >= 0) - close(fd); - return -1; -} - -/* - * Push the file, cond that it has not changed. - * Return 0 if ok or disconnected, 1 if changed, -1 upon errors. - * - * XXX: Shouldn't we push metadata changes and then data cond that - * data has also changed? - */ -static int -condpush(File *f) -{ - Ch *ch; - int fd, i, nwalks; - long nw, nr; - Msg *m; - uvlong offset; - char buf[ERRMAX]; - - if(f->sd != nil){ - if(walktofile(f, &ch, &nwalks, "push") < 0) - return 0; - xtcond(ch, CEQ, f->sd, 0); - xtwalk(ch, "..", 0); - }else - if(walktofile(f->parent, &ch, &nwalks, "push") < 0) - return 0; - xtcreate(ch, f->d->name, OWRITE, f->d->mode, ISDIR(f)); - if(xrfid(ch) < 0 || xrclone(ch) < 0){ - if(!ISDIR(f)) - closech(ch); - return -1; - } - for(i = 0; i < nwalks; i++) - if(xrwalk(ch, nil) < 0){ - if(!ISDIR(f)) - closech(ch); - rerrstr(buf, sizeof buf); - return -1; - } - if(f->sd != nil){ - if(xrcond(ch) < 0){ /* changed in server */ - if(!ISDIR(f)) - closech(ch); - return 1; /* shouldn't we ignore and push? */ - } - if(xrwalk(ch, nil) < 0){ - if(!ISDIR(f)) - closech(ch); - return -1; - } - } - if(xrcreate(ch) < 0){ - if(!ISDIR(f)) - closech(ch); - return -1; - } - if(ISDIR(f)) - return 0; - fd = open(f->path, OREAD); - if(fd < 0){ - fprint(2, "%s: %r\n", f->path); - xtclunk(ch, 1); - xrclunk(ch); - return -1; - } - nw = 0; - offset = 0ULL; - for(;;){ - m = newmsg(pool); - nr = IOCAP(m->io) - Chhdrsz - twritehdrsz; - m->io->wp += twritehdrsz; - nr = read(fd, m->io->wp, nr); - if(nr <= 0){ - if(nr < 0) - fprint(2, "%s: read: %r", f->path); - xtclunk(ch, 1); - break; - } - m->io->wp += nr; - if(xtwrite(ch, m, nr, offset, 0) < 0){ - fprint(2, "%s: write: %r\n", f->path); - closech(ch); - drainch(ch); - close(fd); - return -1; - } - nw++; - offset += nr; - - /* read replies so that no more than - * 10 outstanding writes are going. - */ - if(nw > Maxwritewin){ - nw--; - if(xrwrite(ch) < 0){ - fprint(2, "%s: write: %r\n", f->path); - closech(ch); - close(fd); - return -1; - } - } - } - close(fd); - while(nw-- > 0) - if(xrwrite(ch) < 0){ - fprint(2, "%s: write: %r\n", f->path); - return -1; - } - - xrclunk(ch); - return 0; -} - -/* - * Remove the file, cond that it has not changed. - * Return 0 if ok or disconnected, 1 if changed, -1 upon errors. - */ -static int -condremove(File *f) -{ - Ch *ch; - int i, nwalks; - char buf[ERRMAX]; - - if(walktofile(f, &ch, &nwalks, "remove") < 0) - return 0; - - /* - * If got it from server, cond that it has not changed or conflict. - */ - if(f->sd != nil) - xtcond(ch, CEQ, f->sd, 0); - xtremove(ch, 1); - if(xrfid(ch) < 0 || xrclone(ch) < 0) - return -1; - if(xrfid(ch) < 0 || xrclone(ch) < 0) - return -1; - for(i = 0; i < nwalks; i++) - if(xrwalk(ch, nil) < 0){ - rerrstr(buf, sizeof buf); - if(strstr(buf, "not exist") != 0){ - f->sremoved = 1; - return 0; - } - return -1; - } - if(f->sd != nil) - if(xrcond(ch) < 0) - return 1; /* file changed in server! */ - if(xrremove(ch) < 0) - return -1; - return 0; -} - -/* - * Try to sync file: - * This can be done with a cond push: - * 1- if local changes & out of date -> conflict - * 2- if local changes and up to date -> push - * - * These can be done with a cond pull: - * 3- if no local changes & out of date -> pull - * 4- if no local changes & up to date -> done. - * - * For directories, recur to check out inner files. - */ -static void -updatefile(File *f) -{ - int chg; - - chg = filechanged(f); - if(chg){ - if(chg&Gone){ - f->cremoved = 1; - if(condremove(f) == 1) - conflict(f); - }else - if(condpush(f) == 1) - conflict(f); - }else - condpull(f); - if(ISDIR(f)) - childmap(f, updatefile); - -} - -static void -settwritehdrsz(void) -{ - Fscall t; - - t.type = Twrite; - twritehdrsz = packedsize(&t); -} - -void -cfileinit(Cmux *cm) -{ - Ch *ch; - int fid; - - settwritehdrsz(); - cmux = cm; - fid = -1; - if(cm == nil){ - werrstr("no cmux"); - disconnected(); - }else{ - ch = newch(cmux); - xtversion(ch, 0); - xtattach(ch, getuser(), "main", 1); - if(xrversion(ch, &msz) < 0) - disconnected(); - else if(xrattach(ch, &fid) < 0) - disconnected(); - } - root = rootfile(); - root->fid = fid; - updatefile(root); -} - -int -cwstatfile(File *f, Dir *d) -{ - return -1; -/* send wstat - if failed - return -1; - return wstatfile(f, d); - */ -} - -Dir* -cstatfile(File *f, int refresh) -{ -return nil; - return statfile(f, 0); -} - -int -cwalkfile(File **fp, char *elem) -{ -return -1; - return walkfile(fp, elem); -} - -int -copenfile(File *f, int mode) -{ -return -1; -/* be sure mode is 3|OTRUNC at most. - - - send the open, cond to our version, - if it's for reading, we want to get the file - and send local changes after the cond - if it's for writing - - truncating, nothing else - - otherwise, we want to get the file - and leave the chan open if its a write, to send - delayed writes. - - - return openfile(f, mode); - */ -} - -void -cclosefile(File *f, int fd) -{ -/* - closefile(f, fd); - if it was an update, send stat and update f->sd - release the chan -*/ -} - - -int -ccreatefile(File **fp, char *elem, int mode, int perm) -{ -return -1; -/* - change locally - send to server - - return createfile(fp, elem, mode, perm); -*/ -} - -long -cpreadfile(File *f, int fd, void *a, ulong count, uvlong offset) -{ -return -1; -/* - return cpreadfile(f, fd, a, count, offset); -*/ -} - -long -cpwritefile(File *f, int fd, void *a, ulong count, uvlong offset) -{ -return -1; -/* - send to server - return pwritefile(f, fd, a, count, offset); -*/ -} - - -int -cremovefile(File *f) -{ -return -1; -/* send to server - - return removefile(f); -*/ -} diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/cfile.h --- a/sys/src/cmd/ix/cfile.h Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ - -/* |c/f2p cfile.c */ -extern void cclosefile(File *f, int fd); -extern int ccreatefile(File **fp, char *elem, int mode, int perm); -extern void cfileinit(Cmux *cm); -extern int copenfile(File *f, int mode); -extern long cpreadfile(File *f, int fd, void *a, ulong count, uvlong offset); -extern void cputfile(File *f); -extern long cpwritefile(File *f, int fd, void *a, ulong count, uvlong offset); -extern int cremovefile(File *f); -extern File* crootfile(void); -extern Dir* cstatfile(File *f, int refresh); -extern int cwalkfile(File **fp, char *elem); -extern int cwstatfile(File *f, Dir *d); diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/ch.c --- a/sys/src/cmd/ix/ch.c Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,601 +0,0 @@ -/* - * A single session is multiplexed among channels - * - * Clients create channels, send messages through channels, - * and receive new channels and gone channels. - * Messages must be received from returned channels by clients. - * (NB: where channel has type Ch*) - * - * Termination: - * chwproc is a client for a tses (writer) - * cmuxproc is a client for a tses (reader) - * - * - If the session gets and eof or error during read - * 1. nil is sent to cmux - * 2. it informs the client (for both cmux and all chans) - * 3. the client closes the chans and the mux - * 4. cmux sends nil to tses wc. - * - If the client terminates the session - * 1. nil is sent to chwproc - * 3. it informs cmux, which will also get nil from tses - * and playes the tses close protocol. - * - * Sending a message with last releases the chan for writing. - * receving a message with last releases the chan for reading. - * The message may have no data, in which case it's used just to - * notify that the channel is being released. - * A channel is gone only when it's released both for reading and - * writing. - * Normal termination is: - * send last and recv last - * recv last and send last - * flushing: - * abortch - * early close: - * closech - * drainch - * eof: - * send last (null msg ok) - * - * The client is not required to read from the channel at all times, - * the mux queues messages and sends them only when the client is - * ready to receive them. - */ -#include -#include -#include -#include /* *BIG* macros */ -#include "conf.h" -#include "msg.h" -#include "ch.h" -#include "dbg.h" - -enum -{ - /* cmuxproc() alts */ - Amkc = 0, - Aendc, - Asrc, - Afixedents, /* first Ch rc in alts */ -}; - - -static void -cmdump(Cmux *cm) -{ - int i; - - if(dbg['s'] == 0) - return; - print("cm %p: %d chs:", cm, cm->nchs); - for(i = 0; i < cm->nchs; i++) - if(cm->chs[i] != nil){ - if(cm->chs[i]->dead == 0) - print(" %d", i); - else - print(" %dd", i); - assert(cm->chs[i]->id == i); - } - print("\n"); -} - -extern void dumpmsg(Msg*); - -/* - * mux messages sent to ch->wc into cm->swc - * terminates when a nil is received. - */ -static void -chwproc(void *a) -{ - Ch *ch; - int nmsgs; - uint flags; - uchar *buf; - Chmsg chm; - Cmux *cm; - Msg *m; - - ch = a; - threadsetname("chwproc %p", a); - dpprint("chwproc[%p]: started\n", a); -Resurrection: - assert(ch->id <= CFidmask); - cm = ch->cm; - for(nmsgs = 0; recv(ch->wc, &chm) == 1; nmsgs++){ - m = chm.m; - if(m == nil){ - dsprint("chwproc[%p]: ch%d: nil msg\n", a, ch->id); - break; - } - flags = 0; - if(chm.last) - flags |= CFend; - if(nmsgs == 0 && ch->notnew == 0) - flags |= CFnew; - buf = msgpushhdr(m, BIT16SZ); - PBIT16(buf, flags|ch->id); - if(dbg['s']>1) - print("chwproc[%p]: hdr %#x\n", a, flags|ch->id); - if(sendp(cm->swc, m) != 1){ - dprint("chwproc[%p]: send failed", a); - freemsg(m); - break; - } - if(chm.last != 0){ - while(nbrecv(ch->wc, &chm) == 1){ - dprint("chwproc[%p]: extra msg\n", a); - freemsg(chm.m); - } - break; - } - } - sendp(cm->endc, ch); - dpprint("chwproc[%p]: limbo\n", a); - if(recvul(ch->dc) != 0){ - dpprint("chwproc[%p]: resurrection\n", a); - goto Resurrection; - } - dpprint("chwproc[%p]: exiting\n", a); - chanfree(ch->dc); -} - -/* - * A channel might have been terminated for writing, yet the - * peer may be still busy processing outgoing requests. - * If the channel is aborted, we send hup request to the server - * to let it know that we will drop any further reply to this channel. - */ -static void -wendch(Ch *ch) -{ - Msg *m; - uchar *buf; - - m = mallocz(sizeof *m, 1); - buf = msgpushhdr(m, BIT16SZ); - PBIT16(buf, CFend|ch->id); - sendp(ch->cm->swc, m); -} - -static Ch* -mkch(Cmux *cm, int i, int notnew) -{ - Ch *ch; - - ch = cm->chs[i]; - if(ch != nil){ - assert(ch->dead != 0); - ch->notnew = notnew; - ch->rclosed = ch->wclosed = ch->flushing = 0; - sendul(ch->dc, 1); /* resurrect chwproc */ - ch->dead = 0; - assert(cm->alts[Afixedents+i].c == ch->rc && cm->alts[Afixedents+i].op == CHANNOP); - return ch; - } - ch = mallocz(sizeof *ch, 1); - cm->chs[i] = ch; - ch->id = i; - ch->rc = echancreate(sizeof(Chmsg), 0); - ch->wc = echancreate(sizeof(Chmsg), 0); - ch->dc = echancreate(sizeof(ulong), 0); - ch->cm = cm; - ch->notnew = notnew; - cm->alts[Afixedents+i].c = ch->rc; - cm->alts[Afixedents+i].op = CHANNOP; - threadcreate(chwproc, ch, Stack); - return ch; -} - -static void -grow(Cmux *cm, int n) -{ - int i, elsz; - - if(n > CFidmask) - sysfatal("growto: no more channel ids"); - if(cm->nachs < n){ - cm->alts = realloc(cm->alts, (Afixedents+n+1) * sizeof(Alt)); - for(i = cm->nachs; i < n+1; i++) - cm->alts[Afixedents+i].op = CHANNOP; - cm->alts[Afixedents+n].op = CHANEND; - - elsz = sizeof cm->chs[0]; - cm->chs = realloc(cm->chs, n * elsz); - memset(&cm->chs[cm->nachs], 0, (n - cm->nachs) * elsz); - cm->nachs = n; - } -} - -static Ch* -addch(Cmux *cm, int i, int notnew) -{ - if(i < 0) - for(i =0 ; i < cm->nchs; i++) - if(cm->chs[i] == nil || cm->chs[i]->dead) - break; - if(i >= cm->nchs){ - grow(cm, i+1); - cm->nchs = i+1; - } - if(cm->chs[i] != nil && cm->chs[i]->dead == 0){ - werrstr("channel %d in use", i); - return nil; - } - cm->nuse++; - dsprint("cmuxproc[%p]: addch: ch%d (%d chs)\n", cm, i, cm->nuse); - return mkch(cm, i, notnew); -} - -enum{Free = 0, Keep = 1}; - -static void -delch(Cmux *cm, Ch *ch, int keep) -{ - - dsprint("cmux[%p]: delch: ch%d keep=%d (%d chs)\n", cm, ch->id, keep, cm->nuse); - if(ch->dead == 0 || keep != 0) - cm->nuse--; - if(keep){ - cm->alts[Afixedents+ch->id].op = CHANNOP; - ch->dead = 1; - }else{ - chanfree(ch->rc); - chanfree(ch->wc); - sendul(ch->dc, 0); - ch->rc = ch->wc = nil; - assert(cm->chs[ch->id] == ch); - cm->chs[ch->id] = nil; - cm->alts[Afixedents+ch->id] = (Alt){nil, nil, CHANNOP, 0, 0, 0}; - free(ch->chms); - free(ch); - } -} - -/* - * Demux message already received in cm->rc and return - * the Ch id for it, perhaps it's a new Ch. - */ -static int -cdemux(Cmux *cm, Msg *m, int *lastp) -{ - uint id, flags; - uchar *hdr; - - Ch *ch; - - if(msglen(m) < BIT16SZ){ - werrstr("short message header"); - return -1; - } - hdr = msgpophdr(m, BIT16SZ); - assert(hdr != nil); - flags = GBIT16(hdr); - if(dbg['s']>1) - print("cdemux: hdr %#x\n", flags); - id = flags & CFidmask; - if(flags&CFnew){ - ch = addch(cm, id, 1); - if(ch == nil) - return -1; - sendp(cm->newc, ch); - }else - if(id >= cm->nchs || cm->chs[id] == nil || cm->chs[id]->dead){ - werrstr("no channel %d", id); - return -1; - } - *lastp = flags&CFend; - return id; -} - -static void -allclosed(Cmux *cm) -{ - int i; - - for(i = 0; i < cm->nchs; i++) - if(cm->chs[i] != nil) - if(cm->chs[i]->dead) - delch(cm, cm->chs[i], Free); - else{ - fprint(2,"abort: cmuxproc: terminated but ch%d open", i); - abort(); - } -} - -static void -queuechm(Cmux *cm, int id, Chmsg chm) -{ - Ch *ch; - - ch = cm->chs[id]; - if(ch->nchms == ch->nachms){ - ch->nachms += Incr; - ch->chms = realloc(ch->chms, ch->nachms*sizeof(Chmsg)); - cm->alts[Afixedents+id].v = &ch->chms[0]; - } - ch->chms[ch->nchms++] = chm; - cm->alts[Afixedents+id].op = CHANSND; -} - -static void -dequeuechm(Cmux *cm, int id) -{ - Ch *ch; - - ch = cm->chs[id]; - assert(ch->nchms > 0); - ch->nchms--; - if(ch->nchms > 0) - memmove(&ch->chms[0], &ch->chms[1], ch->nchms*sizeof(Chmsg)); - else - cm->alts[Afixedents+id].op = CHANNOP; -} - -static void -allabort(Cmux *cm) -{ - int i; - Chmsg chm; - - for(i = 0; i < cm->nchs; i++) - if(cm->chs[i] != nil) - if(cm->chs[i]->dead == 0){ - if(!cm->chs[i]->rclosed){ - chm.m = nil; - chm.last = 1; - queuechm(cm, i, chm); - }else if(cm->chs[i]->wclosed) - delch(cm, cm->chs[i], Free); - }else - delch(cm, cm->chs[i], Free); -} - -static void -cmuxproc(void *a) -{ - enum{Mkc, Endc, Rc}; - Cmux *cm; - ulong dummy; - char *err; - Chmsg chm; - Msg *m; - Ch *ch; - int id; - - cm = a; - threadsetname("cmuxproc %p", a); - dpprint("cmuxproc[%p]: starting\n", a); - cm->alts[Amkc] = (Alt){cm->mkc, &dummy, CHANRCV, 0, 0, 0}; - cm->alts[Aendc] = (Alt){cm->endc, &ch, CHANRCV, 0, 0, 0}; - cm->alts[Asrc] = (Alt){cm->src, &m, CHANRCV, 0, 0, 0}; - cm->alts[Afixedents] = (Alt){nil, nil, CHANEND, 0, 0, 0}; - for(;;){ - switch(id = alt(cm->alts)){ - case Mkc: - ch = addch(cm, -1, 0); - sendp(cm->mkrc, ch); - break; - case Endc: - if(ch == nil){ - allclosed(cm); - sendp(cm->swc, nil); - while((m = recvp(cm->src)) != nil) - freemsg(m); - free(recvp(cm->sec)); - goto Done; - } - if(ch->wclosed){ - dsprint("cmuxproc[%p]: ch%d flushing\n", a, ch->id); - ch->flushing = 1; - wendch(ch); - }else - ch->wclosed = 1; - if(ch->rclosed) - delch(cm, ch, Keep); - break; - case Rc: - if(m == nil){ - err = recvp(cm->sec); - if(err == nil) - dsprint("cmuxproc[%p]: eof (%d chs)\n", a, cm->nuse); - else - dsprint("cmuxproc[%p]: %s\n", a, err); - free(err); - sendp(cm->newc, nil); - if(cm->nuse > 0){ - allabort(cm); - break; - } - sendp(cm->swc, nil); - recvp(cm->endc); - goto Done; - } - chm.m = m; - id = cdemux(cm, m, &chm.last); - if(id < 0){ - dsprint("cdemux: drop msg: %r\n"); - cmdump(cm); - freemsg(m); - break; - } - ch = cm->chs[id]; - if(!ch->rclosed && !ch->flushing) - queuechm(cm, id, chm); - else - freemsg(m); - break; - case -1: - sysfatal("cmuxproc[%p]: alt", a); - default: - id -= Afixedents; - if(id < 0 || id >= cm->nachs) - sysfatal("cmuxproc[%p]: alt id %d", a, id); - ch = cm->chs[id]; - assert(ch != nil && ch->nchms > 0); - if(ch->chms[0].last){ - if(ch->rclosed){ - dsprint("cmuxproc[%p]: ch%d flush\n", a, ch->id); - ch->flushing = 1; - } - ch->rclosed = 1; - if(ch->wclosed) - delch(cm, ch, Keep); - } - dequeuechm(cm, id); - } - } -Done: - allclosed(cm); - dsprint("cmuxproc[%p]: done\n", a); - chanfree(cm->newc); - chanfree(cm->mkc); - chanfree(cm->mkrc); - chanfree(cm->endc); - free(cm->chs); - free(cm->alts); - free(cm); - threadexits(nil); -} - -Cmux* -muxses(Channel *src, Channel *swc, Channel *sec) -{ - Cmux *cm; - - cm = mallocz(sizeof *cm, 1); - cm->src = src; - cm->swc = swc; - cm->sec = sec; - cm->newc = echancreate(sizeof(Ch*), 0); - cm->mkc = echancreate(sizeof(ulong), 0); - cm->mkrc = echancreate(sizeof(Ch*), 0); - cm->endc = echancreate(sizeof(ulong), 0); - cm->alts = mallocz(sizeof(Alt)*(Afixedents+1), 1); - - /* - * Could be a thread, but then the caller - * would have to be aware and don't block the process. - */ - proccreate(cmuxproc, cm, Stack); - return cm; -} - -void -closemux(Cmux *cm) -{ - dsprint("closemux %p\n", cm); - sendp(cm->endc, nil); -} - -Ch* -newch(Cmux *cm) -{ - sendul(cm->mkc, 0); - return recvp(cm->mkrc); -} - -int -chsend(Ch *ch, Msg *m, int last) -{ - Chmsg chm; - - assert(m != nil); - chm.m = m; - chm.last = last; - if(ch->flushing){ - freemsg(m); - chm.m = nil; - chm.last = 1; - werrstr("chsend: ch%d flushing", ch->id); - send(ch->wc, &chm); - - /* - * client is sending which means that the last - * message was not sent. - * We are flushing and asking the wproc to exit, - * so we must notify the peer that we are done. - */ - wendch(ch); - - return -1; - } - send(ch->wc, &chm); - return 0; -} - -Msg* -chrecv(Ch *ch, int *last) -{ - Chmsg chm; - - recv(ch->rc, &chm); - *last = chm.last; - return chm.m; -} - -/* - * Close a Ch without sending a msg with the last request. - * The caller is expected to read until learning that the peer is - * done, unless it knows the peer is already done. - */ -void -closech(Ch *ch) -{ - Chmsg chm; - - dsprint("closech: ch%d\n", ch->id); - chm.m = nil; - chm.last = 1; - send(ch->wc, &chm); - wendch(ch); -} - -/* - * Close a Ch after having sent the last msg through it. - * Note that cmuxproc might be trying to send a reply to our caller. - */ -void -abortch(Ch *ch) -{ - Chmsg chm; - - Alt alts[] = { - {ch->cm->endc, &ch, CHANSND}, - {ch->rc, &chm, CHANRCV}, - {nil, nil, CHANEND} - }; - - dsprint("abortch: ch%d\n", ch->id); - for(;;){ - switch(alt(alts)){ - case 0: - /* could notify our termination request */ - return; - case 1: - freemsg(chm.m); - if(chm.last){ - /* got the last msg; ch is gone */ - return; - } - break; - default: - sysfatal("alt"); - } - } -} - -void -drainch(Ch *ch) -{ - Msg *m; - int last; - - dsprint("drainch: ch%d\n", ch->id); - while((m = chrecv(ch, &last)) != nil){ - freemsg(m); - if(last) - break; - } -} - diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/ch.h --- a/sys/src/cmd/ix/ch.h Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -typedef struct Ch Ch; -typedef struct Cmux Cmux; -typedef struct Chmsg Chmsg; - - -enum -{ - /* Ch flags */ - CFnew = 0x8000, - CFend = 0x4000, - CFidmask = 0x3FFF, - - Chhdrsz = BIT16SZ, - -}; - -struct Chmsg -{ - Msg *m; - int last; -}; - -struct Ch -{ - ushort id; - Channel*rc; /* read channel (of Chmsg) */ - Channel*wc; /* write channel (of Chmsg) */ - - /* implementation */ - Cmux *cm; - int notnew; /* already created because of peer */ - int rclosed; - int wclosed; - int flushing; - - Chmsg *chms; - int nchms; - int nachms; - - int dead; /* gone channel, waiting to be reused */ - Channel *dc; -}; - -struct Cmux -{ - Channel*newc; /* of Ch*; to report new Ch's created */ - - /* implementation*/ - Channel*src; /* multiplexed session read channel */ - Channel*swc; /* multiplexed session write channel */ - Channel*sec; /* multiplexed session error channel */ - Channel*mkc; /* of ulong; request a new ch */ - Channel*mkrc; /* of Ch*; reply ......with new ch */ - Channel*endc; /* of Ch*; to release ch */ - Ch** chs; /* array of channels in this session */ - int nuse; /* # of channels in use */ - int nchs; /* number of channels used */ - int nachs; /* number of channels allocated */ - Alt *alts; /* cmux chans + one read channel per Ch */ -}; - -/* |c/f2p ch.c */ -extern void abortch(Ch *ch); -extern Msg* chrecv(Ch *ch, int *last); -extern int chsend(Ch *ch, Msg *m, int last); -extern void closech(Ch *ch); -extern void closemux(Cmux *cm); -extern void drainch(Ch *ch); -extern Cmux* muxses(Channel *src, Channel *swc, Channel *sec); -extern Ch* newch(Cmux *cm); diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/conf.h --- a/sys/src/cmd/ix/conf.h Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -enum -{ - KiB = 1024, - Stack = 32*KiB, /* stack size for threads */ - - Hbufsz = 8, /* room for message headers */ - Msgsz = 8*KiB, /* message size */ - Smsgsz = 64, /* small message size */ - Nmsgs = 16, /* # of messages per session */ - - Maxid = 255, /* # of channels per session */ - Nses = 512, /* max # of sessions */ - - Nchs = 64, /* max # of chans in ix */ - - Nels = 64, /* max # of elems in path */ - - Maxwritewin = 10, /* max # of outstanding writes */ - Incr = 16, -}; diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/dbg.c --- a/sys/src/cmd/ix/dbg.c Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - -char dbg[256]; - diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/dbg.h --- a/sys/src/cmd/ix/dbg.h Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -/* - * 'P': mpools - * 'd': general debug - * 'f': fs - * 'm': messages - * 'p': processes - * 's': session debug - * 't': test client - * 'n': nsfile - * 'c': cache - * 'D': disk - */ -#define dDprint if(!dbg['D']){}else print -#define dPprint if(!dbg['P']){}else print -#define dcprint if(!dbg['c']){}else print -#define dfprint if(!dbg['f']){}else print -#define dmprint if(!dbg['m']){}else print -#define dnprint if(!dbg['n']){}else print -#define dpprint if(!dbg['p']){}else print -#define dprint if(!dbg['d']){}else print -#define dsprint if(!dbg['s']){}else print -#define dtprint if(!dbg['t']){}else print -extern char dbg[]; diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/file.h --- a/sys/src/cmd/ix/file.h Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -typedef struct File File; - -enum -{ - None = 0, - Meta = 1, - Data = 2, - Gone = 4, -}; - -struct File -{ - Ref; - int nopens; - RWLock; - char *path; - Dir *d; - Dir *sd; /* dir in server */ - File *parent; - File *child; - int nchild; - File *next; /* in child list */ - int visited; - int cremoved; /* file removed on client */ - int sremoved; /* file removed on server */ - /* used by ixc */ - int fid; -}; - -#pragma varargck type "T" File* -#define ISDIR(f) ((f)->d->qid.type&QTDIR) - - -/* |c/f2p nsfile.c */ -extern void childmap(File *f, void(*fn)(File*)); -extern void closefile(File *f, int fd); -extern int createfile(File **fp, char *elem, int mode, int perm); -extern void dumptree(void); -extern Dir* dupdir(Dir *d); -extern int filechanged(File *f); -extern int filefmt(Fmt *fmt); -extern void fileinit(char *path, int udb); -extern Qid fileqid(File *f); -extern int filesync(void); -extern File* getchild(File *parent, char *name); -extern File* newfile(File *parent, char *path, Dir *d); -extern int openfile(File *f, int mode); -extern int perm(File *f, char *user, int p); -extern long preadfile(File *, int fd, void *a, ulong count, uvlong offset); -extern void putfile(File *f); -extern long pwritefile(File *, int fd, void *a, ulong count, uvlong offset); -extern int removefile(File *f); -extern File* rootfile(void); -extern int shortdirfmt(Fmt *fmt); -extern Dir* statfile(File *f, int refresh); -extern char* tmpfile(char *name); -extern int walkfile(File **fp, char *elem); -extern int wstatfile(File *f, Dir *d); diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/fmt.c --- a/sys/src/cmd/ix/fmt.c Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,243 +0,0 @@ -#include -#include -#include - -#include "ix.h" - - - -static char* cname[CMAX] = -{ - [CEQ] "==", - [CGE] ">=", - [CGT] "> ", - [CLT] "< ", - [CLE] "<=", - [CNE] "!=", -}; - -int -ixcallfmt(Fmt *fmt) -{ - IXcall *f; - int type, i; - char buf[512]; - char *p, *e, *s; - - e = buf+sizeof(buf); - f = va_arg(fmt->args, IXcall*); - type = f->type; - switch(type){ - case IXTversion: - seprint(buf, e, "Tversion msize %ud version '%s'", f->msize, f->version); - break; - case IXRversion: - seprint(buf, e, "Rversion msize %ud version '%s'", f->msize, f->version); - break; - - case IXTsession: - seprint(buf, e, "Tsession ssid %ud uname '%s' keep %d", f->ssid, f->uname, f->keep); - break; - case IXRsession: - seprint(buf, e, "Rsession ssid %ud afid %ud uname '%s'", - f->ssid, f->afid, f->uname); - break; - - case IXTsid: - seprint(buf, e, "Tsid ssid %ud", f->ssid); - break; - case IXRsid: - seprint(buf, e, "Rsid"); - break; - - case IXTendsession: - seprint(buf, e, "Tendsession"); - break; - case IXRendsession: - seprint(buf, e, "Rendsession"); - break; - - case IXTfid: - seprint(buf, e, "Tfid fid %ud", f->fid); - break; - case IXRfid: - seprint(buf, e, "Rfid"); - break; - - case IXTattach: - seprint(buf, e, "Tattach aname '%s'", f->aname); - break; - case IXRattach: - seprint(buf, e, "Rattach fid %d", f->fid); - break; - - case IXRerror: - seprint(buf, e, "Rerror ename '%s'", f->ename); - break; - - case IXTclone: - seprint(buf, e, "Tclone cflags %#x", f->cflags); - break; - case IXRclone: - seprint(buf, e, "Rclone fid %d", f->fid); - break; - - - case IXTwalk: - s = seprint(buf, e, "Twalk"); - for(i = 0; i < f->nwname; i++) - s = seprint(s, e, " '%s'", f->wname[i]); - break; - case IXRwalk: - seprint(buf, e, "Rwalk"); - break; - - case IXTopen: - seprint(buf, e, "Topen mode %d", f->mode); - break; - case IXRopen: - seprint(buf, e, "Ropen"); - break; - - case IXTcreate: - seprint(buf, e, "Tcreate name %s perm %M mode %d", f->name, (ulong)f->perm, f->mode); - break; - case IXRcreate: - seprint(buf, e, "Rcreate"); - break; - - case IXTread: - seprint(buf, e, "Tread nmsg %d offset %lld count %ud", - f->nmsg, f->offset, f->count); - break; - case IXRread: - s = seprint(buf, e, "Rread count %ud ", f->count); - dumpsome(s, e, f->data, f->count); - break; - - case IXTwrite: - p = seprint(buf, e, "Twrite offset %lld endoffset %lld count %ud ", - f->offset, f->endoffset, f->count); - dumpsome(p, e, f->data, f->count); - break; - case IXRwrite: - seprint(buf, e, "Rwrite offset %lld count %ud", f->offset, f->count); - break; - - case IXTclunk: - seprint(buf, e, "Tclunk"); - break; - case IXRclunk: - seprint(buf, e, "Rclunk"); - break; - case IXTclose: - seprint(buf, e, "Tclose"); - break; - case IXRclose: - seprint(buf, e, "Rclose"); - break; - case IXTremove: - seprint(buf, e, "Tremove"); - break; - case IXRremove: - seprint(buf, e, "Rremove"); - break; - - case IXTattr: - seprint(buf, e, "Tattr attr '%s'", f->attr); - break; - case IXRattr: - p = seprint(buf, e, "Rattr value "); - dumpsome(p, e, f->value, f->nvalue); - break; - - case IXTwattr: - p = seprint(buf, e, "Twattr attr '%s' value ", f->attr); - dumpsome(p, e, f->value, f->nvalue); - break; - case IXRwattr: - seprint(buf, e, "Rwattr"); - break; - - case IXTcond: - if(f->op >= CMAX) - s = "??"; - else - s = cname[f->op]; - p = seprint(buf, e, "Tcond op %s", s); - p = seprint(p, e, "attr '%s' value ", f->attr); - dumpsome(p, e, f->value, f->nvalue); - break; - case IXRcond: - seprint(buf, e, "Rcond"); - break; - - case IXTmove: - seprint(buf, e, "Tmove dirfid %d newname '%s'", f->dirfid, f->newname); - break; - case IXRmove: - seprint(buf, e, "Rmove"); - break; - - case IXTflush: - seprint(buf, e, "Tflush"); - break; - case IXRflush: - seprint(buf, e, "Rflush"); - break; - - default: - seprint(buf, e, "unknown type %d", type); - } - return fmtstrcpy(fmt, buf); -} - -/* - * dump out count (or DUMPL, if count is bigger) bytes from - * buf to ans, as a string if they are all printable, - * else as a series of hex bytes - */ -#define DUMPL 64 - -uint -dumpsome(char *ans, char *e, void *b, long count) -{ - int i, printable; - char *p; - char *buf; - - buf = b; - if(buf == nil){ - seprint(ans, e, ""); - return strlen(ans); - } - printable = 1; - if(count > DUMPL) - count = DUMPL; - for(i=0; i127) - printable = 0; - p = ans; - *p++ = '\''; - if(printable){ - if(count > e-p-2) - count = e-p-2; - for(; count > 0; count--, p++, buf++) - if(*buf == '\n' || *buf == '\t') - *p = ' '; - else - *p = *buf; - }else{ - if(2*count > e-p-2) - count = (e-p-2)/2; - for(i=0; i0 && i%4==0) - *p++ = ' '; - sprint(p, "%2.2ux", (uchar)buf[i]); - p += 2; - } - } - *p++ = '\''; - *p = 0; - return p - ans; -} diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/fs.c --- a/sys/src/cmd/ix/fs.c Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1030 +0,0 @@ -#include -#include -#include -#include -#include - -#include "conf.h" -#include "msg.h" -#include "mpool.h" -#include "tses.h" -#include "ch.h" -#include "dbg.h" -#include "ix.h" -#include "ixfile.h" - -enum -{ - SSID = 42 -}; - -/* - * Mbuf convention: - * Msg.io[0] always refers to the message buffer. - */ - -typedef struct Fs Fs; -typedef struct Rpc Rpc; -typedef struct Fid Fid; -typedef struct Ses Ses; - -struct Ses -{ - QLock; - Ref; - char *uname; - int ssid; - Ses *next; /* in avail sessions list */ - Fid **fids; - int nfids; - Fid *free; - void *tag; /* to remove those not kept */ -}; - -struct Fs -{ - QLock; - Con *s; /* transport session (i.e., tcp connection) */ - Cmux *cm; /* channel multiplexor */ - Channel *argc; /* to pass args to workers */ - ulong msize; /* maximum data size */ -}; - -struct Fid -{ - Ref; - Fid *next; /* in free list */ - File *file; - int id; - int fd; /* meaningful to File only */ - int cflags; /* OCEND|OCERR */ - int omode; - int aborting; -}; - -struct Rpc -{ - Fs *fs; - Ch *ch; - Msg *m; - Ses *ix; - Fid *fid; - IXcall t, r; - int last; -}; - -enum -{ - Large = 0, - Small, -}; - -static QLock ixslk; -static Ssrv *ssrv; -static Ses *ixs; /* sessions in server */ - -static int ssid = SSID; /* server session id; any number would do */ -static Channel *poolc[2]; -static int npools[2]; -static ulong poolmsz[2] = -{ - [Large] Msgsz, - [Small] Smsgsz, -}; - -static QLock hugelock; /* BUG: single lock for the fs */ -static int nfids; - -static Fid* -newfid(Ses *ix) -{ - Fid *fid; - - qlock(ix); - nfids++; - if(ix->free != nil){ - fid = ix->free; - ix->free = fid->next; - qunlock(ix); - return fid; - } - if((ix->nfids%Incr) == 0) - ix->fids = realloc(ix->fids, (ix->nfids+Incr)*sizeof(Fid*)); - fid = mallocz(sizeof *fid, 1); - ix->fids[ix->nfids] = fid; - fid->id = ix->nfids++; - fid->ref = 1; - fid->omode = -1; - fid->fd = -1; - fid->aborting = 0; - qunlock(ix); - return fid; -} - -static void -clunkfid(Fid *fid) -{ - if(fid->file != nil){ - if(fid->fd != -1) - closefile(fid->file, fid->fd, fid->aborting); - putfile(fid->file); - } - fid->file = nil; - fid->fd = -1; - fid->omode = -1; -} - - -static void -putfid(Ses *ix, Fid *fid) -{ - assert(ix != nil); - if(decref(fid) == 0){ - qlock(ix); - nfids--; - dfprint("free fid. %d fids in use\n", nfids); - fid->next = ix->free; - ix->free = fid; - clunkfid(fid); - qunlock(ix); - } -} - -static Fid* -getfid(Ses *ix, int id) -{ - Fid *fid; - - assert(ix != nil); - qlock(ix); - if(id < 0 || id >= ix->nfids || ix->fids[id]->file == nil){ - qunlock(ix); - return nil; - } - fid = ix->fids[id]; - incref(fid); - qunlock(ix); - return fid; -} - -static void -putpool(Mpool *mp) -{ - poolstats(mp); - sendp(poolc[Large], mp); -} - -static void -putspool(Mpool *mp) -{ - poolstats(mp); - sendp(poolc[Small], mp); -} - -static Mpool* -getpool(int sz) -{ - Mpool *mp; - - mp = nbrecvp(poolc[sz]); - if(mp != nil) - return mp; - - if(ainc(&npools[sz]) < Nses){ - mp = newpool(poolmsz[sz], Nmsgs); - if(mp == nil){ - adec(&npools[sz]); - return nil; - } - mp->freepool = putpool; - if(sz == Small) - mp->freepool = putspool; - return mp; - } - return recvp(poolc[sz]); -} - -static void -freeses(Ses *ix) -{ - int i; - - for(i = 0; i < ix->nfids; i++) - free(ix->fids[i]); - free(ix->fids); - free(ix->uname); - free(ix); -} - -static Ses* -getses(int ssid) -{ - Ses *ix; - - qlock(&ixslk); - for(ix = ixs; ix != nil; ix = ix->next) - if(ix->ssid == ssid){ - incref(ix); - break; - } - qunlock(&ixslk); - return ix; -} - -static void -_putses(Ses *ix) -{ - Ses **s; - - if(ix == nil || decref(ix) > 0) - return; - dfprint("putses: free session id %d\n", ix->ssid); - for(s = &ixs; *s != nil; s = &(*s)->next) - if(*s == ix){ - *s = ix->next; - freeses(ix); - return; - } - sysfatal("session not found in putses"); -} - -static void -putses(Ses *ix) -{ - Ses **s; - - if(ix == nil || decref(ix) > 0) - return; - dfprint("putses: free session id %d\n", ix->ssid); - qlock(&ixslk); - for(s = &ixs; *s != nil; s = &(*s)->next) - if(*s == ix){ - *s = ix->next; - freeses(ix); - qunlock(&ixslk); - return; - } - sysfatal("session not found in putses"); -} - -static Ses* -newses(void *tag) -{ - Ses *ix; - static int ssidgen; - - assert(tag != nil); - qlock(&ixslk); - ix = mallocz(sizeof *ix, 1); - ix->ref = 1; - ix->next = ixs; - ix->ssid = ++ssidgen; - ix->tag = tag; - ixs = ix; - qunlock(&ixslk); - return ix; -} - -static void -killses(void *tag) -{ - Ses *ns, *s; - - qlock(&ixslk); - for(s = ixs; s != nil; s = ns){ - ns = s->next; - if(s->tag == tag) - _putses(s); - } - qunlock(&ixslk); -} - -static int -fsreply(Rpc *rpc) -{ - Msg *m; - Io *io; - ulong n; - int rc; - - m = rpc->m; - m->hdr = nil; - io = &m->io[0]; - /* - * Rread puts data directly after the packed reply Fscall - * and sets io's rp and wp by itself. - * The same goes for Rattr. - */ - dfprint("%cch%d-> %G\n", rpc->last?'|':'-', rpc->ch->id, &rpc->r); - if(rpc->r.type == IXRread || rpc->r.type == IXRattr) - n = ixpack(&rpc->r, io->bp, ixpackedsize(&rpc->r)); - else{ - ioreset(io); - n = ixpack(&rpc->r, io->wp, IOCAP(io)); - io->wp += n; - } - if(n <= 0) - sysfatal("fsreply: pack (Smsgsz too small?)"); - rc = chsend(rpc->ch, rpc->m, rpc->last); - if(rc < 0){ - dfprint("fsreply: %r\n"); - rpc->last = 1; - } - if(rpc->last != 0 && rpc->fid != nil && (rpc->fid->cflags&OCEND) != 0){ - if(rpc->r.type == IXRerror) - rpc->fid->aborting++; - putfid(rpc->ix, rpc->fid); /* held by client */ - putfid(rpc->ix, rpc->fid); /* held by rpc */ - rpc->fid = nil; - } - return rc; -} - -static int -fserror(Rpc *rpc, char *e) -{ - rpc->r.type = IXRerror; - rpc->r.ename = e; - rpc->last = 1; - fsreply(rpc); - return -1; -} - -static int -fssyserror(Rpc *rpc) -{ - char *e; - - e = smprint("%r"); - rpc->r.type = IXRerror; - rpc->r.ename = e; - rpc->last = 1; - if(rpc->fid != nil && (rpc->fid->cflags&OCERR) != 0) - rpc->fid->cflags |= OCEND; - fsreply(rpc); - free(e); - return -1; -} - -static int -fsversion(Rpc *rpc) -{ - if(rpc->t.msize < rpc->fs->msize){ - rpc->fs->msize = rpc->t.msize; - dfprint("fsversion: msize %uld\n", rpc->fs->msize); - } - rpc->r.msize = rpc->fs->msize; - if(strcmp(rpc->t.version, "3.1415926P") != 0) - return fserror(rpc, "wrong version"); - rpc->r.version = "3.1415926P"; - return fsreply(rpc); -} - -static int -fssession(Rpc *rpc) -{ - Ses *s; - - /* only the owner can set a session by now */ - if(strcmp(rpc->t.uname, getuser()) != 0) - return fserror(rpc, "bad user in session"); - - if(rpc->t.ssid != Nossid) - s = getses(rpc->t.ssid); - else{ - s = newses(rpc->fs); /* use fs as the tag */ - incref(s); /* it's allocated now until endsession */ - } - if(rpc->t.keep) - s->tag = nil; /* forget thet tag: keep it when done */ - putses(rpc->ix); - rpc->ix = s; - if(s == nil) - return fserror(rpc, "unknown session id"); - rpc->ix->uname = strdup(rpc->t.uname); - rpc->r.afid = ~0; - rpc->r.ssid = s->ssid; - rpc->r.uname = getuser(); - dfprint("fssession: session id %d ref %d\n", s->ssid, s->ref); - return fsreply(rpc); -} - -static int -fssid(Rpc *rpc) -{ - Ses *ix; - - ix = getses(rpc->t.ssid); - putses(rpc->ix); - rpc->ix = ix; - if(ix == nil) - return fserror(rpc, "unknown session id"); - return fsreply(rpc); -} - -static int -fsendsession(Rpc *rpc) -{ - Ses *ix; - - if(rpc->ix == nil) - return fserror(rpc, "session not set"); - putses(rpc->ix); - ix = rpc->ix; - rpc->ix = nil; - - putses(ix); /* should destroy it when unused */ - return fsreply(rpc); -} - -static int -fsfid(Rpc *rpc) -{ - if(rpc->ix == nil) - return fserror(rpc, "session not set"); - if(rpc->fid != nil) - putfid(rpc->ix, rpc->fid); - rpc->fid = getfid(rpc->ix, rpc->t.fid); - if(rpc->fid == nil) - return fserror(rpc, "no such fid"); - rpc->fid->cflags = rpc->t.cflags; - return fsreply(rpc); -} - -static int -fsattach(Rpc *rpc) -{ - if(rpc->ix == nil) - return fserror(rpc, "session not set"); - - /* - * rpc->t.aname ignored - */ - rpc->fid = newfid(rpc->ix); - incref(rpc->fid); /* client's reference */ - rpc->r.fid = rpc->fid->id; - rpc->fid->file = rootfile(); - return fsreply(rpc); -} - -static int -fsclone(Rpc *rpc) -{ - Fid *nfid; - Fid *fid; - - if(rpc->ix == nil) - return fserror(rpc, "session not set"); - fid = rpc->fid; - if(fid == nil) - return fserror(rpc, "fid not set"); - nfid = newfid(rpc->ix); /* ref held by client */ - rpc->r.fid = nfid->id; - nfid->omode = fid->omode; - nfid->file = fid->file; - increffile(nfid->file); - putfid(rpc->ix, fid); /* held by rpc */ - rpc->fid = nfid; - nfid->cflags = rpc->t.cflags; - incref(nfid); /* held by rpc */ - return fsreply(rpc); -} - -static int -fswalk(Rpc *rpc) -{ - Fid *fid; - int i; - - if(rpc->ix == nil) - return fserror(rpc, "session not set"); - fid = rpc->fid; - if(fid == nil) - return fserror(rpc, "fid not set"); - if(fid->omode != -1) - return fserror(rpc, "can't walk an open fid"); - /* - * NB: This differs from 9p. A walk succeeds only if all - * names can be walked. - */ - for(i = 0; i < rpc->t.nwname; i++) - if(walkfile(&fid->file, rpc->t.wname[i]) < 0) - return fssyserror(rpc); - return fsreply(rpc); -} - -static int -fsopen(Rpc *rpc) -{ - Fid *fid; - - if(rpc->ix == nil) - return fserror(rpc, "session not set"); - fid = rpc->fid; - if(fid == nil) - return fserror(rpc, "fid not set"); - if(fid->omode != -1) - return fserror(rpc, "fid already open"); - fid->fd = openfile(fid->file, rpc->t.mode); - if(fid->fd < 0) - return fssyserror(rpc); - fid->omode = rpc->t.mode; - return fsreply(rpc); -} - -static int -fscreate(Rpc *rpc) -{ - int fd; - Fid *fid; - - if(rpc->ix == nil) - return fserror(rpc, "session not set"); - fid = rpc->fid; - if(fid == nil) - return fserror(rpc, "fid not set"); - if(fid->omode != -1) - return fserror(rpc, "fid already open"); - fd = createfile(&fid->file, rpc->t.name, rpc->t.mode, rpc->t.perm); - if(fd < 0) - return fssyserror(rpc); - fid->fd = fd; - fid->omode = rpc->t.mode; - return fsreply(rpc); -} - -static int -fsread(Rpc *rpc) -{ - long nr; - Io *io; - Fid *fid; - int i, saved, last; - - if(rpc->ix == nil) - return fserror(rpc, "session not set"); - fid = rpc->fid; - if(fid == nil) - return fserror(rpc, "fid not set"); - if(fid->omode < 0 || (fid->omode&3) == OWRITE) - return fserror(rpc, "fid not open for reading"); - if(rpc->t.nmsg == 0) - rpc->t.nmsg = 1; - /* - * Get a large buffer; we are probably using a small one. - */ - freemsg(rpc->m); - rpc->m = newmsg(rpc->fs->s->pool); - for(i = 0; i != rpc->t.nmsg; i++){ - io = &rpc->m->io[0]; - nr = rpc->t.count; - rpc->m->hdr = nil; - ioreset(io); - io->wp += ixpackedsize(&rpc->r); - if(nr < 0 || nr > IOCAP(io)) - nr = IOCAP(io); - if(IOLEN(io)+nr > rpc->fs->msize) - nr = rpc->fs->msize - IOLEN(io); - rpc->r.data = io->wp; - nr = preadfile(fid->file, fid->fd, io->wp, nr, rpc->t.offset); - if(nr < 0) - return fssyserror(rpc); - io->wp += nr; - rpc->t.offset += nr; - - rpc->r.count = nr; - saved = rpc->last; - rpc->last = last = (saved && (i == rpc->t.nmsg || nr == 0)); - if(fsreply(rpc) < 0){ - rpc->last = saved; - return -1; - } - rpc->last = saved; - if(last || nr == 0) - break; - rpc->m = newmsg(rpc->fs->s->pool); - } - return 0; -} - -static int -fswrite(Rpc *rpc) -{ - long nw; - Fid *fid; - IXcall *t; - - if(rpc->ix == nil) - return fserror(rpc, "session not set"); - fid = rpc->fid; - if(fid == nil) - return fserror(rpc, "fid not set"); - if(fid->omode < 0 || (fid->omode&3) == OREAD) - return fserror(rpc, "fid not open for writing"); - t = &rpc->t; - nw = pwritefile(fid->file, fid->fd, t->data, t->count, &t->offset, t->offset+t->count); - if(nw < 0) - return fssyserror(rpc); - rpc->r.count = nw; - rpc->r.offset = t->offset; - return fsreply(rpc); -} - -static int -fsclunk(Rpc *rpc) -{ - Fid * fid; - - if(rpc->ix == nil) - return fserror(rpc, "session not set"); - fid = rpc->fid; - if(fid == nil) - return fserror(rpc, "fid not set"); - fid->aborting++; - putfid(rpc->ix, fid); /* in session */ - putfid(rpc->ix, fid); /* in rpc */ - rpc->fid = nil; - return fsreply(rpc); -} - -static int -fsclose(Rpc *rpc) -{ - Fid * fid; - int isopen; - - if(rpc->ix == nil) - return fserror(rpc, "session not set"); - fid = rpc->fid; - if(fid == nil) - return fserror(rpc, "fid not set"); - isopen = fid->omode >= 0; - assert(fid->aborting == 0); - putfid(rpc->ix, fid); /* in session */ - putfid(rpc->ix, fid); /* in rpc */ - rpc->fid = nil; - if(!isopen) - return fserror(rpc, "fid not open"); - return fsreply(rpc); -} - -static int -fsremove(Rpc *rpc) -{ - Fid * fid; - int r; - - if(rpc->ix == nil) - return fserror(rpc, "session not set"); - fid = rpc->fid; - if(fid == nil) - return fserror(rpc, "fid not set"); - if(fid->omode >= 0){ - closefile(fid->file, fid->fd, fid->aborting); - fid->fd = -1; - fid->omode = -1; - } - putfid(rpc->ix, fid); /* held by client */ - - /* file goes when rpc->fid reference is released later */ - r = removefile(fid->file); - - putfid(rpc->ix, fid); /* held by rpc */ - rpc->fid = nil; - if(r < 0) - return fssyserror(rpc); - else - return fsreply(rpc); -} - -static int -fsattr(Rpc *rpc) -{ - Fid *fid; - Io *io; - long nr; - - if(rpc->ix == nil) - return fserror(rpc, "session not set"); - fid = rpc->fid; - if(fid == nil) - return fserror(rpc, "fid not set"); - /* - * Get a large buffer; we are probably using a small one. - */ - freemsg(rpc->m); - rpc->m = newmsg(rpc->fs->s->pool); - io = &rpc->m->io[0]; - rpc->m->hdr = nil; - ioreset(io); - io->wp += ixpackedsize(&rpc->r); - rpc->r.value = io->wp; - nr = fileattr(fid->file, rpc->t.attr, rpc->r.value, IOCAP(io)); - if(nr < 0) - return fssyserror(rpc); - rpc->r.nvalue = nr; - io->wp += nr; - return fsreply(rpc); -} - -static int -fswattr(Rpc *rpc) -{ - Fid *fid; - - if(rpc->ix == nil) - return fserror(rpc, "session not set"); - fid = rpc->fid; - if(fid == nil) - return fserror(rpc, "fid not set"); - if(filewattr(fid->file, rpc->t.attr, rpc->t.value, IOLEN(rpc->m->io)) < 0) - return fssyserror(rpc); - return fsreply(rpc); -} - -static int -cmpstr(char *s1, char *s2, int cond) -{ - switch(cond){ - case CEQ: - return strcmp(s1, s2) == 0; - case CNE: - return strcmp(s1, s2) != 0; - case CLE: - return strcmp(s1, s2) >= 0; - case CLT: - return strcmp(s1, s2) > 0; - case CGT: - return strcmp(s1, s2) < 0; - case CGE: - return strcmp(s1, s2) <= 0; - default: - return 0; - } -} - -static int -fscond(Rpc *rpc) -{ - Fid *fid; - char buf[128]; /* bug: fixes stat size */ - char buf2[128]; - Msg *m; - long n; - - if(rpc->ix == nil) - return fserror(rpc, "session not set"); - fid = rpc->fid; - if(fid == nil) - return fserror(rpc, "fid not set"); - m = rpc->m; - if(IOLEN(m->io) >= sizeof buf - 1) - return fserror(rpc, "fscond: bug: attr value too large"); - memmove(buf, m->io->rp, IOLEN(m->io)); - buf[IOLEN(m->io)] = 0; - n = fileattr(fid->file, rpc->t.attr, (uchar*)buf2, sizeof buf2 - 1); - if(n < 0) - return fssyserror(rpc); - buf[n] = 0; - if(cmpstr(buf, buf2, rpc->t.op) == 0) - return fserror(rpc, "false"); - return fsreply(rpc); -} - -static int -fsmove(Rpc *rpc) -{ - if(rpc->ix == nil) - return fserror(rpc, "session not set"); - return fserror(rpc, "move not supported"); -} - -static int -fscopy(Rpc *rpc) -{ - if(rpc->ix == nil) - return fserror(rpc, "session not set"); - return fserror(rpc, "copy not supported"); -} - -static int -fsflush(Rpc *rpc) -{ - if(rpc->ix == nil) - return fserror(rpc, "session not set"); - return fserror(rpc, "abort the channel for flushing"); -} - -typedef int (*Rpcfn)(Rpc*); - -static Rpcfn reqfn[Tmax] = { -[IXTversion] fsversion, -[IXTsession] fssession, -[IXTsid] fssid, -[IXTendsession] fsendsession, -[IXTfid] fsfid, -[IXTattach] fsattach, -[IXTclone] fsclone, -[IXTwalk] fswalk, -[IXTopen] fsopen, -[IXTcreate] fscreate, -[IXTread] fsread, -[IXTwrite] fswrite, -[IXTclunk] fsclunk, -[IXTclose] fsclose, -[IXTremove] fsremove, -[IXTattr] fsattr, -[IXTwattr] fswattr, -[IXTcond] fscond, -[IXTmove] fsmove, -[IXTflush] fsflush, -}; - -static int -fsrpc(Rpc *rpc) -{ - Msg *m; - int r, n; - - m = rpc->m; - if(IOLEN(&m->io[0]) == 0){ - dfprint("ch%d: eof\n", rpc->ch->id); - goto Fail; - } - n = ixunpack(m->io[0].rp, IOLEN(&m->io[0]), &rpc->t); - if(n <= 0){ - dfprint("ch%d: unknown message: %r\n", rpc->ch->id); - goto Fail; - } - m->io->rp += n; - switch(rpc->t.type){ - case IXTwrite: - rpc->t.count = IOLEN(m->io); - break; - case IXTwattr: - case IXTcond: - rpc->t.nvalue = IOLEN(m->io); - break; - } - dfprint("<-ch%d%c %G\n", rpc->ch->id, rpc->last?'|':'-', &rpc->t); - if(rpc->t.type >= nelem(reqfn) || reqfn[rpc->t.type] == nil){ - dfprint("bad msg type %d\n", rpc->t.type); - goto Fail; - } - rpc->r.type = rpc->t.type+1; - r = reqfn[rpc->t.type](rpc); - return r; -Fail: - m->hdr = nil; - ioreset(m->io); - rpc->last = 1; - chsend(rpc->ch, m, 1); - return -1; -} - -static void -fsrpcproc(void *a) -{ - Channel *c; - int id, waslast; - Rpc rpc; - - c = a; - threadsetname("fsrpcproc fs %p ch %p", rpc.fs, rpc.ch); - memset(&rpc, 0, sizeof rpc); - rpc.fid = nil; - rpc.fs = recvp(c); - rpc.ch = recvp(c); - id = rpc.ch->id; - dfprint("fsrpc[%p!%d]: new chan %s\n", rpc.fs->s, id, rpc.fs->s->addr); - while((rpc.m = chrecv(rpc.ch, &rpc.last)) != nil){ - qlock(&hugelock); - waslast = rpc.last; - if(fsrpc(&rpc) < 0 && !waslast){ - drainch(rpc.ch); - break; - } - if(rpc.last) - break; - qunlock(&hugelock); - } - if(rpc.fid != nil) - putfid(rpc.ix, rpc.fid); - if(rpc.ix != nil) - putses(rpc.ix); - qunlock(&hugelock); - dfprint("fsrpc[%p!%d]: done.\n", rpc.fs->s, id); - dfprint("%d fids in use; %d files in use\n", nfids, ixnfiles); - threadexits(nil); -} - -static void -fssrvproc(void *a) -{ - Fs fs; - Ch *ch; - - threadsetname("fssrvproc %p", a); - dfprint("fssrvproc[%p]: started\n", &fs); - memset(&fs, 0, sizeof fs); - fs.s = a; - fs.msize = Msgsz - Chhdrsz; - startses(fs.s, getpool(Large), getpool(Small)); - fs.argc = echancreate(sizeof(void*), 0); - fs.cm = muxses(fs.s->rc, fs.s->wc, fs.s->ec); - dfprint("fssrvproc: %p %s\n", &fs, fs.s->addr); - while((ch = recvp(fs.cm->newc)) != nil){ - threadcreate(fsrpcproc, fs.argc, Stack); - sendp(fs.argc, &fs); - sendp(fs.argc, ch); - } - /* mux released by itself */ - closemux(fs.cm); - chanfree(fs.argc); - killses(&fs); - dfprint("fssrvproc[%p]: done\n", &fs); - threadexits(nil); -} - - -static int consfd = -1; -static int constid = -1; -static Biobuf bcmd; - -static void -consproc(void *a) -{ - int fd; - char *cmd; - - threadsetname("consproc"); - dfprint("consproc started\n"); - fd = (int)a; - Binit(&bcmd, fd, OREAD); - constid = threadid(); - for(;;){ - fprint(fd, "> "); - cmd = Brdstr(&bcmd, '\n', 1); - if(cmd == nil) - break; - if(cmd[0] == 0){ - free(cmd); - continue; - } - dfprint("cmd: %s\n", cmd); - if(strcmp(cmd, "halt") == 0){ - free(cmd); - break; - }else - fprint(fd, "%s?\n", cmd); - free(cmd); - } - fprint(fd, "halted\n"); - fprint(2, "halted\n"); - dfprint("consproc done\n"); - threadexitsall(nil); -} - -static int -cons(char *srv) -{ - char *fn; - int p[2], fd; - - fn = smprint("/srv/%s", srv); - fd = create(fn, OWRITE|ORCLOSE|OCEXEC, 0660); - if(fd < 0){ - free(fn); - return -1; - } - if(pipe(p) < 0) - sysfatal("pipe: %r"); - fprint(fd, "%d", p[0]); - consfd = p[0]; - proccreate(consproc, (void*)p[1], Stack); - free(fn); - return 0; -} - -void -ixinit(char *addr, char *srv) -{ - ssrv = newsrv(addr); - if(ssrv == nil) - sysfatal("fsinit: newsrv: %r"); - if(cons(srv) < 0) - sysfatal("cons: %r"); - poolc[0] = echancreate(sizeof(Mpool*), Nses); - poolc[1] = echancreate(sizeof(Mpool*), Nses); -} - -void -ixsrv(void) -{ - Con *s; - - while((s = recvp(ssrv->newc)) != nil) - threadcreate(fssrvproc, s, Stack); - fprint(consfd, "halt\n"); - threadexitsall(nil); -} diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/fs.h --- a/sys/src/cmd/ix/fs.h Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ -enum{ - Tfid = Tversion-6, - Rfid, - Tclone, /* unused numbers in fcall.h */ - Rclone, /* following T&R conventions */ - Tcond, - Rcond, - - OCEND = 1, /* clunk on end of rpc */ - OCERR = 2, /* clunk on error */ - - CEQ = 0, /* Tcond.cond */ - CGE, - CGT, - CLE, - CLT, - CNE, - CMAX, -}; - -/* - Protocol: - Tversion msize[4] version[s] - Rversion msize[4] version[s] - Tauth afid[4] uname[s] aname[s] - Rauth aqid[13] - Rerror ename[s] - Tattach afid[4] uname[s] aname[s] - Rattach fid[4] qid[13] - Tfid fid[4] cflags[1] - Rfid - Tclone cflags[1] - Rclone newfid[4] - Twalk wname[s] - Rwalk wqid[13] - Topen mode[1] - Ropen qid[13] iounit[4] - Tcreate name[s] perm[4] mode[1] - Rcreate qid[13] iounit[4] - Tread nmsg[4] offset[8] count[4] - Rread count[4] data[count] may be repeated - Twrite offset[8] count[4] data[count] - Rwrite count[4] - Tclunk - Rclunk - Tremove - Rremove - Tstat - Rstat stat[n] - Twstat stat[n] - Rwstat - Tcond cond[1] stat[n] - Rcond - - The largest packed messages, not counting strings and data, are - Rattach, Ropen, and Rcreate, with 18 bytes. - Plus ch header (2 bytes), plus message size (2 bytes). - Could create pools for small messages with, say, 64 bytes, - and use them for messages that we know that fit there. - Probably only Rstat, Tcond, Twstat, Rread, and Twrite won't fit. - Perhaps also some Twalk for a long name element. - */ - -typedef -struct Fscall -{ - uchar type; - u32int fid; /* Tattach, Tfid */ - union { - struct { - u32int msize; /* Tversion, Rversion */ - char *version; /* Tversion, Rversion */ - }; - struct { - char *ename; /* Rerror */ - }; - struct { - Qid qid; /* Rattach, Ropen, Rcreate */ - u32int iounit; /* Ropen, Rcreate */ - }; - struct { - Qid aqid; /* Rauth */ - }; - struct { - u32int afid; /* Tauth, Tattach */ - char *uname; /* Tauth, Tattach */ - char *aname; /* Tauth, Tattach */ - }; - struct { - u32int perm; /* Tcreate */ - char *name; /* Tcreate */ - uchar mode; /* Tcreate, Topen */ - }; - struct { - char *wname; /* Twalk */ - }; - struct { - Qid wqid; /* Rwalk */ - }; - struct { - u32int newfid; /* Rclone */ - }; - struct { - u32int nmsg; /* Tread */ - vlong offset; /* Tread, Twrite */ - u32int count; /* Tread, Twrite, Rread */ - char *data; /* Twrite, Rread */ - }; - struct { - uchar cond; /* Tcond */ - ushort nstat; /* Tcond, Twstat, Rstat */ - uchar *stat; /* Tcond, Twstat, Rstat */ - }; - struct { - uchar cflags; /* Tfid, Tclone */ - }; - }; -} Fscall; - -#pragma varargck type "G" Fscall* - -/* - * |c/f2p fs.c - */ -extern void fsinit(char *addr, char *srv); -extern void fssrv(void); - -/* - * |c/f2p pack.c - */ -extern uint pack(Fscall *f, uchar *ap, uint nap); -extern uint packedsize(Fscall *f); -extern uint unpack(uchar *ap, uint nap, Fscall *f); - -/* - * |c/f2p fmt.c - */ -extern int fscallfmt(Fmt *fmt); - diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/ix.c --- a/sys/src/cmd/ix/ix.c Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -#include -#include -#include -#include - -#include "conf.h" -#include "msg.h" -#include "mpool.h" -#include "tses.h" -#include "ch.h" -#include "dbg.h" -#include "ix.h" -#include "ixfile.h" - -#define SRVADDR "tcp!*!9999" -#define TESTDIR "/sys/src/cmd/ix/Testfs" - -int mainstacksize = Stack; - -static void -usage(void) -{ - fprint(2, "usage: %s [-d] [-D flags] [-s srv] [addr]\n", argv0); - exits("usage"); -} - -void -threadmain(int argc, char *argv[]) -{ - char *addr, *flags, *srv; - - addr = SRVADDR; - srv = "ix"; - - ARGBEGIN{ - case 'd': - dbg['d']++; - break; - case 'D': - flags = EARGF(usage()); - for(;*flags != 0; flags++) - dbg[*flags]++; - dbg['d']++; - break; - case 's': - srv = EARGF(usage()); - break; - default: - usage(); - }ARGEND; - if(argc == 1) - addr = argv[1]; - else if(argc > 1) - usage(); - - outofmemoryexits(1); - fmtinstall('G', ixcallfmt); - fmtinstall('M', dirmodefmt); - fmtinstall('T', filefmt); - fileinit(TESTDIR); - ixinit(addr, srv); - ixsrv(); - dtprint("testsrv: exiting\n"); - threadexits(nil); -} diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/ixc.c --- a/sys/src/cmd/ix/ixc.c Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,719 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "conf.h" -#include "msg.h" -#include "ch.h" -#include "mpool.h" -#include "tses.h" -#include "fs.h" -#include "file.h" -#include "cfile.h" -#include "dbg.h" - -/* - 8.ix -Dfn -! slay 8.ix|rc - 8.ixc -Dfn cache tcp!localhost!9999 - - */ - -typedef struct Cfid Cfid; -typedef struct Rpc Rpc; - -struct Cfid -{ - Cfid *next; - short busy; - int omode; - int fid; - int fd; - char *user; - File* file; -}; - -struct Rpc -{ - Fcall t; - Fcall r; - Msg *m; - Cfid *fid; - int fd; -}; - -static Cfid *fids; -static QLock fidslk; - -ulong msz = Msgsz; - -static void io(int fd); - -static int rflush(Rpc*), rversion(Rpc*), rauth(Rpc*), - rattach(Rpc*), rwalk(Rpc*), - ropen(Rpc*), rcreate(Rpc*), - rread(Rpc*), rwrite(Rpc*), rclunk(Rpc*), - rremove(Rpc*), rstat(Rpc*), rwstat(Rpc*); - -static int (*fcalls[])(Rpc*) = { - [Tversion] rversion, - [Tflush] rflush, - [Tauth] rauth, - [Tattach] rattach, - [Twalk] rwalk, - [Topen] ropen, - [Tcreate] rcreate, - [Tread] rread, - [Twrite] rwrite, - [Tclunk] rclunk, - [Tremove] rremove, - [Tstat] rstat, - [Twstat] rwstat, -}; - -static char Enofid[] = "fid not found"; -static char Eperm[] = "permission denied"; -static char Enotdir[] = "not a directory"; -static char Enoauth[] = "ramfs: authentication not required"; -static char Enotexist[] = "file does not exist"; -static char Einuse[] = "file in use"; -static char Eexist[] = "file exists"; -static char Eisdir[] = "file is a directory"; -static char Enotowner[] = "not owner"; -static char Eisopen[] = "file already open for I/O"; -static char Enotopen[] = "file not open for I/O"; -static char Excl[] = "exclusive use file already open"; -static char Ename[] = "illegal name"; -static char Eversion[] = "unknown 9P version"; -static char Enotempty[] = "directory not empty"; - -static Ses *ses; -static Cmux *cmux; -Mpool *pool, *spool; - -static char *cdir; - -void -notifyf(void *a, char *s) -{ - USED(a); - if(strncmp(s, "interrupt", 9) == 0) - noted(NCONT); - noted(NDFLT); -} - -static Cfid* -newfid(int fid, int mk) -{ - Cfid *f, *ff; - - qlock(&fidslk); - ff = 0; - for(f = fids; f; f = f->next) - if(f->fid == fid) - return f; - else if(!ff && !f->busy) - ff = f; - if(mk == 0) - return nil; - if(ff){ - ff->busy = 1; - ff->fid = fid; - ff->file = nil; - ff->omode = -1; - free(ff->user); - ff->user = nil; - qunlock(&fidslk); - return ff; - } - f = emalloc(sizeof *f); - f->fid = fid; - f->next = fids; - fids = f; - f->busy = 1; - f->omode = -1; - qunlock(&fidslk); - return f; -} - -static int -p9reply(Rpc *rpc) -{ - int n; - Io *io; - - io = rpc->m->io; - ioreset(io); - rpc->m->hdr = nil; - n = convS2M(&rpc->r, io->wp, IOCAP(io)); - if(n <= 0) - sysfatal("p9reply: convS2M"); - io->wp += n; - if(write(rpc->fd, io->rp, IOLEN(io)) != IOLEN(io)) - return -1; - freemsg(rpc->m); - rpc->m = nil; - return 0; -} - -static int -p9error(Rpc *rpc, char *e) -{ - rpc->r.type = Rerror; - rpc->r.ename = e; - return p9reply(rpc); -} - -static int -p9syserror(Rpc *rpc) -{ - char buf[128]; - - rerrstr(buf, sizeof buf); - buf[sizeof buf - 1] = 0; - return p9error(rpc, buf); -} - -static int -rversion(Rpc *rpc) -{ - if(rpc->t.msize > msz) - rpc->t.msize = msz; - else - msz = rpc->t.msize; - rpc->r.msize = msz; - if(strncmp(rpc->t.version, "9P2000", 6) != 0) - return p9error(rpc, Eversion); - rpc->r.version = "9P2000"; - return p9reply(rpc); -} - -static int -rauth(Rpc *rpc) -{ - return p9error(rpc, "no authentication required"); -} - -static int -rflush(Rpc *rpc) -{ - return p9reply(rpc); -} - -static int -rattach(Rpc *rpc) -{ - Cfid *fid; - - fid = newfid(rpc->t.fid, 1); - /* no authentication! */ - fid->file = crootfile(); - if(rpc->t.uname[0]) - fid->user = estrdup(rpc->t.uname); - else - fid->user = estrdup("none"); - rpc->r.qid = fileqid(fid->file); - return p9reply(rpc); -} - -static Cfid* -clone(Cfid *f, int nfid) -{ - Cfid *nf; - - nf = newfid(nfid, 1); - nf->busy = 1; - nf->omode = -1; - nf->file = f->file; - incref(f->file); - nf->user = estrdup(f->user); - return nf; -} - -static int -rwalk(Rpc *rpc) -{ - File *file; - char *name; - Cfid *fid, *nfid; - Qid q; - char *err; - int i; - - nfid = nil; - rpc->r.nwqid = 0; - fid = newfid(rpc->t.fid, 0); - if(fid == nil) - return p9error(rpc, Enofid); - if(fid->omode >= 0) - return p9error(rpc, Eisopen); - if(rpc->t.newfid != NOFID){ - nfid = clone(fid, rpc->t.newfid); - if(nfid == nil) - return p9syserror(rpc); - fid = nfid; /* walk the new fid */ - } - file = fid->file; - err = nil; - incref(file); /* temp. ref used during walk */ - if(rpc->t.nwname > 0){ - for(i=0; it.nwname && it.wname[i]; - if(!perm(file, fid->user, AEXEC)){ - err = Eperm; - break; - } - if(cwalkfile(&file, name) < 0){ - err = Enotexist; - break; - } - rpc->r.nwqid++; - rpc->r.wqid[i] = q; - } - if(i==0 && err == nil) - err = Enotexist; - } - if(nfid != nil && (err!=nil || rpc->r.nwqid < rpc->t.nwname)){ - /* clunk the new fid, which is the one we walked */ - nfid->busy = 0; - cputfile(nfid->file); - nfid->file = nil; - } - if(rpc->r.nwqid > 0) - err = nil; /* didn't get everything in 9P2000 right! */ - if(rpc->r.nwqid == rpc->t.nwname){ - /* update the fid after a successful walk */ - cputfile(fid->file); - fid->file = file; - }else - cputfile(file); /* temp ref used during walk */ - if(err != nil) - return p9error(rpc, err); - return p9reply(rpc); -} - -static int -ropen(Rpc *rpc) -{ - Cfid *fid; - int mode, omode; - File *file; - Dir *d; - - fid = newfid(rpc->t.fid, 0); - if(fid == nil) - return p9error(rpc, Enofid); - if(fid->omode >= 0) - return p9error(rpc, Eisopen); - file = fid->file; - d = cstatfile(file, 0); - mode = rpc->t.mode; - if(d->qid.type & QTDIR){ - if(mode != OREAD) - return p9error(rpc, Eperm); - rpc->r.qid = d->qid; - free(d); - return 0; - } - if((d->mode&DMEXCL) && file->nopens){ - free(d); - return p9error(rpc, Excl); - } - free(d); - if(mode & ORCLOSE){ - /* can't remove root; must be able to write parent */ - if(file->parent == nil || !perm(file, fid->user, AWRITE)) - return p9error(rpc, Eperm); - } - omode = mode&3; - if(omode != OREAD || (mode&OTRUNC)) - if(!perm(file, fid->user, AWRITE)) - return p9error(rpc, Eperm); - if(omode != OWRITE) - if(!perm(file, fid->user, AREAD)) - return p9error(rpc, Eperm); - fid->fd = copenfile(file, mode); - if(fid->fd < 0) - return p9syserror(rpc); - fid->omode = mode; - rpc->r.qid = fileqid(file); - rpc->r.iounit = msz - Chhdrsz - IOHDRSZ; - return p9reply(rpc); -} - - -static int -rcreate(Rpc *rpc) -{ - Cfid *fid; - File *file; - Dir *d; - - fid = newfid(rpc->t.fid, 0); - if(fid == nil) - return p9error(rpc, Enofid); - if(fid->omode >= 0) - return p9error(rpc, Eisopen); - file = fid->file; - d = cstatfile(file, 0); - if((d->qid.type&QTDIR) == 0){ - free(d); - return p9error(rpc, Enotdir); - } - /* must be able to write parent */ - if(!perm(file, fid->user, AWRITE)){ - free(d); - return p9error(rpc, Eperm); - } - rpc->t.perm &= d->mode; - free(d); - fid->fd = ccreatefile(&file, rpc->t.name, rpc->t.mode, rpc->t.perm); - if(fid->fd < 0) - return p9syserror(rpc); - fid->omode = rpc->t.mode; - fid->file = file; - - rpc->r.qid = fileqid(file); - rpc->r.iounit = msz-Chhdrsz-IOHDRSZ; - return p9reply(rpc); -} - -static int -rread(Rpc *rpc) -{ - Cfid *fid; - File *file; - Io *io; - long fcsz, nr; - - fid = newfid(rpc->t.fid, 0); - if(fid == nil) - return p9error(rpc, Enofid); - if(fid->omode < 0) - return p9error(rpc, Enotopen); - if((fid->omode&3) == OWRITE) - return p9error(rpc, "file not open for reading"); - file = fid->file; - - io = rpc->m->io; - ioreset(io); - /* - * read the data directly in the place where convS2M will - * copy it (it should not do the memmove in that case). - */ - rpc->r.count = 0; - fcsz = sizeS2M(&rpc->r); - rpc->r.data = (char*)io->wp+fcsz; - if(rpc->t.count > IOCAP(io)) - rpc->t.count = IOCAP(io); - if(rpc->t.count > msz) - rpc->t.count = msz; - nr = cpreadfile(file, fid->fd, rpc->r.data, rpc->t.count, rpc->t.offset); - if(nr < 0) - return p9syserror(rpc); - rpc->r.count = nr; - return p9reply(rpc); -} - -static int -rwrite(Rpc *rpc) -{ - Cfid *fid; - File *file; - long nw; - - fid = newfid(rpc->t.fid, 0); - if(fid == nil) - return p9error(rpc, Enofid); - if(fid->omode < 0) - return p9error(rpc, Enotopen); - if((fid->omode&3) == OREAD) - return p9error(rpc, "file not open for writing"); - file = fid->file; - - nw = cpwritefile(file, fid->fd, rpc->t.data, rpc->t.count, rpc->t.offset); - if(nw < 0) - return p9syserror(rpc); - rpc->r.count = nw; - return p9reply(rpc); -} - -static int -rclunk(Rpc *rpc) -{ - Cfid *fid; - File *file; - - fid = newfid(rpc->t.fid, 0); - if(fid == nil) - return p9error(rpc, Enofid); - file = fid->file; - if(fid->omode >= 0){ - cclosefile(file, fid->fd); - fid->fd = -1; - if(fid->omode&ORCLOSE) - cremovefile(file); - fid->omode = 0; - } - cputfile(file); - fid->file = nil; - return p9reply(rpc); -} - -static int -rremove(Rpc *rpc) -{ - Cfid *fid; - File *file; - int rc; - - fid = newfid(rpc->t.fid, 0); - if(fid == nil) - return p9error(rpc, Enofid); - file = fid->file; - if(fid->omode >= 0){ - cclosefile(file, fid->fd); - fid->fd = -1; - fid->omode = 0; - } - if(file->parent != nil && perm(file->parent, fid->user, AWRITE)) - rc = cremovefile(file); - else{ - werrstr(Eperm); - rc = -1; - } - cputfile(file); - fid->file = nil; - if(rc < 0) - return p9syserror(rpc); - else - return p9reply(rpc); -} - -static int -rstat(Rpc *rpc) -{ - Cfid *fid; - File *file; - Dir *d; - uchar buf[512]; - - fid = newfid(rpc->t.fid, 0); - if(fid == nil) - return p9error(rpc, Enofid); - file = fid->file; - d = cstatfile(file, 1); - rpc->r.nstat = convD2M(d, buf, sizeof buf); - rpc->r.stat = buf; - free(d); - return p9reply(rpc); -} - -static int -rwstat(Rpc *rpc) -{ - Cfid *fid; - File *file; - Dir wd, *d; - char buf[512]; - - fid = newfid(rpc->t.fid, 0); - if(fid == nil) - return p9error(rpc, Enofid); - file = fid->file; - d = cstatfile(file, 0); - convM2D(rpc->t.stat, rpc->t.nstat, &wd, buf); - - - /* - * To change length, must have write permission on file. - */ - if(wd.length!=~0 && d->length!=wd.length) - if(!perm(file, fid->user, AWRITE)){ - free(d); - return p9error(rpc, Eperm); - } - - /* - * To change name, must have write permission in parent - * and name must be unique. - */ - if(wd.name[0]!='\0' && strcmp(wd.name, d->name)!=0) - if(!file->parent || !perm(file->parent, fid->user, AWRITE)){ - free(d); - return p9error(rpc, Eperm); - } - - /* - * To change mode, must be owner or group leader. - * Because of lack of users file, leader=>group itself. - */ - if(wd.mode!=~0 && wd.mode!=d->mode && - strcmp(fid->user, d->uid) != 0 && strcmp(fid->user, d->gid) != 0){ - free(d); - return p9error(rpc, Enotowner); - } - - /* - * To change group, must be owner and member of new group, - * or leader of current group and leader of new group. - */ - if(wd.gid[0]!='\0' && strcmp(wd.gid, d->gid)!=0 && - strcmp(fid->user, d->uid) != 0){ - free(d); - return p9error(rpc, Enotowner); - } - free(d); - /* all ok; do it */ - if(cwstatfile(file, &wd) < 0) - return p9syserror(rpc); - return p9reply(rpc); -} - -static void -p9io(int fd) -{ - char buf[40]; - int n; - Rpc rpc; - - for(;;){ - /* - * reading from a pipe or a network device - * will give an error after a few eof reads. - * however, we cannot tell the difference - * between a zero-length read and an interrupt - * on the processes writing to us, - * so we wait for the error. - */ - memset(&rpc, 0, sizeof rpc); - rpc.m = newmsg(pool); - rpc.fd = fd; - n = read9pmsg(fd, rpc.m->io->wp, IOCAP(rpc.m->io)); - if(n < 0){ - rerrstr(buf, sizeof buf); - if(buf[0]=='\0' || strstr(buf, "hungup")) - exits(""); - sysfatal("mount read: %r"); - } - if(n == 0){ - freemsg(rpc.m); - continue; - } - rpc.m->io->wp += n; - if(convM2S(rpc.m->io->rp, IOLEN(rpc.m->io), &rpc.t) == 0){ - freemsg(rpc.m); - continue; - } - dfprint("-9-> %F\n", &rpc.t); - - if(rpc.t.type>=nelem(fcalls) || fcalls[rpc.t.type] == nil){ - if(p9error(&rpc, "bad fcall type") < 0) - sysfatal("p9error: %r"); - continue; - } - rpc.r.tag = rpc.t.tag; - rpc.r.type = rpc.t.type+1; - if(fcalls[rpc.t.type](&rpc) < 0) - sysfatal("fscalls[%d]: %r", rpc.t.type); - dfprint("<-9- %F\n", &rpc.r); - } -} - -static void -fsproc(void *a) -{ - int *p; - - p = a; - close(p[1]); - fileinit(".", 1); - pool = newpool(Msgsz, Nmsgs); - spool = newpool(Smsgsz, Nmsgs); - startses(ses, pool, spool); - cmux = muxses(ses->rc, ses->wc, ses->ec); - cfileinit(cmux); - p9io(p[0]); -} - -static void -usage(void) -{ - fprint(2, "usage: %s [-D flags] [-s] [-m mnt] [-S srv] dir addr\n", argv0); - exits("usage"); -} - -void -threadmain(int argc, char *argv[]) -{ - char *defmnt, *service, *addr, *flags; - int p[2]; - int fd; - - service = "ix"; - defmnt = "/n/ix"; - - ARGBEGIN{ - case 'm': - defmnt = EARGF(usage()); - break; - case 's': - defmnt = 0; - break; - case 'D': - flags = EARGF(usage()); - for(;*flags != 0; flags++) - dbg[*flags]++; - dbg['d']++; - break; - case 'S': - defmnt = 0; - service = EARGF(usage()); - break; - default: - usage(); - }ARGEND - if(argc != 2) - usage(); - cdir = cleanname(argv[0]); - addr = argv[1]; - if(chdir(cdir) < 0) - sysfatal("%s: %r", cdir); - if(pipe(p) < 0) - sysfatal("pipe failed: %r"); - if(defmnt == 0){ - char buf[64]; - snprint(buf, sizeof buf, "#s/%s", service); - fd = create(buf, OWRITE|ORCLOSE, 0666); - if(fd < 0) - sysfatal("create failed: %r"); - sprint(buf, "%d", p[0]); - if(write(fd, buf, strlen(buf)) < 0) - sysfatal("writing service file: %r"); - } - - notify(notifyf); - - fmtinstall('G', fscallfmt); - fmtinstall('F', fcallfmt); - fmtinstall('D', shortdirfmt); - fmtinstall('M', dirmodefmt); - fmtinstall('T', filefmt); - - ses = dialsrv(addr); - if(ses == nil) - sysfatal("dialsrv: %r"); - procrfork(fsproc, p, Stack, RFFDG|RFNAMEG|RFNOTEG); - close(p[0]); /* don't deadlock if child fails */ - if(defmnt && mount(p[1], -1, defmnt, MREPL|MCREATE, "") < 0) - sysfatal("mount failed: %r"); - threadexits(0); -} - diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/ixget.c --- a/sys/src/cmd/ix/ixget.c Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,662 +0,0 @@ -/* - * Test program for ix. - * - ! mk all - ! slay 8.ix 8.ixget 8.ixp |rc - X/\[/D - ! rm -r /usr/nemo/src/9/ixp/Testfs/* - ! 8.ixp -DDfn - ! slay 8.ixget|rc - ! cd /tmp ; /usr/nemo/src/9/ixp/8.ixget -Dstf acme.dump >[2=1] - ! cmp /tmp/acme.dump /sys/src/cmd/ix/test/acme.dump - ! cd /tmp ; /usr/nemo/src/9/ixp/8.ixget -pDstf adump>[2=1] - ! cmp /tmp/adump /sys/src/cmd/ix/test/adump - ! tstack 8.ix - ! tstack 8.ixget - ! 8.ix -Dfn - - */ - -#include -#include -#include -#include - -#include "conf.h" -#include "msg.h" -#include "mpool.h" -#include "tses.h" -#include "ch.h" -#include "dbg.h" -#include "ix.h" -#include "ixreqs.h" - -#define CLIADDR "tcp!localhost!9999" - -int mainstacksize = Stack; - -static Cmux *cm; -static Con *ses; -Mpool *pool, *spool; -static Channel *wc; -static int rootfid = -1; -static ulong msz; -static int doflush; -static int twritehdrsz; -static int tcondhdrsz; -static int ssid; - -static long -wdata(int fd, void *a, long cnt, uvlong off) -{ - - return pwrite(fd, a, cnt, off); -} - -static void -printfile(char *s, char *e) -{ - char *str, *val; - - print("dir:\n"); - while(s < e){ - s = (char*)gstring((uchar*)s, (uchar*)e, &str); - if(s == nil) - return; - s = (char*)gstring((uchar*)s, (uchar*)e, &val); - if(s == nil) - return; - if(strcmp(str, "name") == 0 || strcmp(str, "uid") == 0 || - strcmp(str, "gid") == 0 || strcmp(str, "muid") == 0) - print("\t[%s] = '%s'\n", str, val); - else if(strcmp(str, "mode") == 0) - print("\t[%s] = %M\n", str, GBIT32(val)); - else - print("\t[%s] = %#ullx\n", str, GBIT64(val)); - } -} - -static void -printdir(char *buf, int count) -{ - int tot, n; - - for(tot = 0; tot < count; tot += n){ - if(count-tot < BIT32SZ) - break; - n = GBIT32(buf+tot); - tot += BIT32SZ; - if(tot+n > count){ - print("wrong count in dir entry\n"); - break; - } - printfile(buf+tot, buf+tot+n); - } -} - -static void -getstat(Ch *ch, int last) -{ - ixtattr(ch, "name", last); - ixtattr(ch, "path", last); - ixtattr(ch, "vers", last); - ixtattr(ch, "atime", last); - ixtattr(ch, "prev", last); - ixtattr(ch, "length", last); - ixtattr(ch, "mode", last); - ixtattr(ch, "uid", last); - ixtattr(ch, "gid", last); - ixtattr(ch, "muid", last); -} - -static int -gotu64(Ch *ch, uvlong *ip) -{ - Msg *m; - - m = ixrattr(ch); - if(m == nil) - return -1; - if(IOLEN(m->io) < BIT64SZ){ - freemsg(m); - return -1; - } - *ip = GBIT64(m->io->rp); - freemsg(m); - return 0; -} - -static int -gotu32(Ch *ch, ulong *ip) -{ - Msg *m; - - m = ixrattr(ch); - if(m == nil) - return -1; - if(IOLEN(m->io) < BIT32SZ){ - freemsg(m); - return -1; - } - *ip = GBIT32(m->io->rp); - freemsg(m); - return 0; -} - -static int -gotstr(Ch *ch, char **cp) -{ - Msg *m; - - m = ixrattr(ch); - if(m == nil) - return -1; - if(IOLEN(m->io) == 0){ - freemsg(m); - return -1; - } - *m->io->wp = 0; /* BUG, but ok for this */ - *cp = strdup((char*)m->io->rp); - freemsg(m); - return 0; -} - -static int -gotstat(Ch *ch, Dir *d) -{ - uvlong x; - - nulldir(d); - if(gotstr(ch, &d->name) < 0) - return -1; - if(gotu64(ch, &d->qid.path) < 0) - return -1; - if(gotu64(ch, &x) < 0) - return -1; - d->qid.vers = x; - if(gotu64(ch, &x) < 0) - return -1; - d->atime = x; - if(gotu64(ch, &x) < 0) - return -1; - /* prev */ - if(gotu64(ch, (uvlong*)&d->length) < 0) - return -1; - if(gotu32(ch, &d->mode) < 0) - return -1; - if(gotstr(ch, &d->uid) < 0) - return -1; - if(gotstr(ch, &d->gid) < 0) - return -1; - if(gotstr(ch, &d->muid) < 0) - return -1; - - d->qid.type = ((d->mode >>24) & 0xFF); - return 0; -} - -/* - * If doflush, this will test a flush (abortch) before - * retrieving all data. - * Because ch does not convey more data to the receiver when it - * enters the flushing state, we can only flush when we are sure - * regarding the state of the server (i.e., if we sent a clone, - * should either clone OCERR|OCEND or wait until receiving the Rclone, - * to learn of the allocated fid, before flushing). - */ -static void -getproc(void *a) -{ - char *path, *els[64], *fn, *dirbuf; - int nels, fd; - Ch *ch; - Dir d; - long nr; - uvlong offset; - Msg *m; - - path = a; - threadsetname("getproc %s", path); - if(*path == '/') - path++; - path = strdup(path); - nels = getfields(path, els, nelem(els), 1, "/"); - if(nels < 1) - sysfatal("short path"); - fn = els[nels-1]; - ch = newch(cm); - ixtsid(ch, ssid, 0); - ixtfid(ch, rootfid, 0); - ixtclone(ch, OCEND|OCERR, 0); - ixtwalk(ch, nels, els, 0); - getstat(ch, 0); - ixtopen(ch, OREAD, 0); - ixtread(ch, -1, msz, 0ULL, 1); - /* fid automatically clunked on errors and eof */ - dirbuf = nil; - - fd = -1; - if(ixrsid(ch) < 0){ - fprint(2, "%s: sid: %r\n", a); - goto Done; - } - if(ixrfid(ch) < 0){ - fprint(2, "%s: fid: %r\n", a); - goto Done; - } - if(ixrclone(ch, nil) < 0){ - fprint(2, "%s: clone: %r\n", a); - goto Done; - } - if(ixrwalk(ch) < 0){ - fprint(2, "%s: walk: %r\n", a); - goto Done; - } - if(gotstat(ch, &d) < 0){ - fprint(2, "%s: stat: %r\n", a); - goto Done; - } - dtprint("get: %D\n", &d); - remove(fn); /* ignore errors */ - fd = create(fn, OWRITE, d.mode&~DMDIR); - if(fd < 0){ - fprint(2, "create %s: %r\n", fn); - goto Done; - } - if(ixropen(ch) < 0){ - fprint(2, "%s: open: %r\n", a); - goto Done; - } - offset = 0ULL; - do{ - if(doflush){ /* flush testing */ - doflush = 0; - abortch(ch); - goto Done; - } - m = ixrread(ch); - if(m == nil){ - fprint(2, "%s: read: %r\n", a); - goto Done; - } - nr = IOLEN(m->io); - if(nr > 0) - if(d.qid.type&QTDIR){ - dirbuf = realloc(dirbuf, offset+nr); - memmove(dirbuf+offset, m->io->rp, nr); - }else - nr = wdata(fd, m->io->rp, nr, offset); - offset += nr; - freemsg(m); - }while(nr > 0); - close(fd); - fd = -1; - if(dirbuf != nil){ - printdir(dirbuf, offset); - free(dirbuf); - dirbuf = nil; - } -Done: - if(fd >= 0){ - close(fd); - remove(fn); - } - free(dirbuf); - sendul(wc, 0); - free(path); - threadexits(nil); - close(fd); -} - -static void -condproc(void *a) -{ - char *path, *els[64], *fn, *dirbuf; - int nels, fd; - Ch *ch; - Dir d; - long nr; - uvlong offset; - Dir *ld; - Msg *m; - - path = a; - threadsetname("condproc %s", path); - if(*path == '/') - path++; - path = strdup(path); - nels = getfields(path, els, nelem(els), 1, "/"); - if(nels < 1) - sysfatal("short path"); - fn = els[nels-1]; - ld = dirstat(fn); - if(ld == nil) - sysfatal("%s: dirstat: %r", fn); - ch = newch(cm); - ixtsid(ch, ssid, 0); - ixtfid(ch, rootfid, 0); - ixtclone(ch, OCEND|OCERR, 0); - ixtwalk(ch, nels, els, 0); - nulldir(&d); - d.qid = ld->qid; - m = newmsg(pool); - m->io->wp += tcondhdrsz; - PBIT64(m->io->wp, d.qid.path); m->io->wp += BIT64SZ; - ixtcond(ch, m, CEQ, "path", BIT64SZ+BIT32SZ+BIT8SZ, 0); - free(ld); - getstat(ch, 0); - ixtopen(ch, OREAD, 0); - ixtread(ch, -1, msz, 0ULL, 1); - /* fid automatically clunked on errors and eof */ - dirbuf = nil; - - fd = -1; - if(ixrsid(ch) < 0){ - fprint(2, "%s: sid: %r\n", a); - goto Done; - } - if(ixrfid(ch) < 0){ - fprint(2, "%s: fid: %r\n", a); - goto Done; - } - if(ixrclone(ch, nil) < 0){ - fprint(2, "%s: clone: %r\n", a); - goto Done; - } - if(ixrwalk(ch) < 0){ - fprint(2, "%s: walk: %r\n", a); - goto Done; - } - if(ixrcond(ch) < 0){ - fprint(2, "%s: cond: %r\n", a); - goto Done; - } - if(gotstat(ch, &d) < 0){ - fprint(2, "%s: stat: %r\n", a); - goto Done; - } - dtprint("get: %D\n", &d); - remove(fn); /* ignore errors */ - fd = create(fn, OWRITE, d.mode&~DMDIR); - if(fd < 0){ - fprint(2, "create %s: %r\n", fn); - goto Done; - } - if(ixropen(ch) < 0){ - fprint(2, "%s: open: %r\n", a); - goto Done; - } - offset = 0ULL; - do{ - m = ixrread(ch); - if(m == nil){ - fprint(2, "%s: read: %r\n", a); - goto Done; - } - nr = IOLEN(m->io); - if(nr > 0) - if(d.qid.type&QTDIR){ - dirbuf = realloc(dirbuf, offset+nr); - memmove(dirbuf+offset, m->io->rp, nr); - }else - nr = wdata(fd, m->io->rp, nr, offset); - offset += nr; - freemsg(m); - }while(nr > 0); - close(fd); - fd = -1; - if(dirbuf != nil){ - printdir(dirbuf, offset); - free(dirbuf); - dirbuf = nil; - } - -Done: - if(fd >= 0){ - close(fd); - remove(fn); - } - free(dirbuf); - sendul(wc, 0); - free(path); - threadexits(nil); - close(fd); -} - -static void -settwritehdrsz(void) -{ - IXcall t; - - t.type = IXTwrite; - twritehdrsz = ixpackedsize(&t); - t.type = IXTcond; - t.attr = "qid"; - tcondhdrsz = ixpackedsize(&t); -} - -static void -putproc(void *a) -{ - char *path, *els[64], *fn; - int nels, fd, nw; - Ch *ch; - Dir *d; - long nr; - Msg *m; - uvlong offset; - uchar buf[BIT32SZ]; - - path = a; - threadsetname("putproc %s", path); - settwritehdrsz(); - if(*path == '/') - path++; - path = strdup(path); - nels = getfields(path, els, nelem(els), 1, "/"); - if(nels < 1) - sysfatal("short path"); - fn = els[nels-1]; - fd = open(fn, OREAD); - if(fd < 0) - sysfatal("%s: %r", fn); - d = dirfstat(fd); - if(d == nil) - sysfatal("%s: %r", fn); - ch = newch(cm); - ixtsid(ch, ssid, 0); - ixtfid(ch, rootfid, 0); - ixtclone(ch, OCEND|OCERR, 0); - if(nels > 1) - ixtwalk(ch, nels-1, els, 0); - if(d->qid.type&QTDIR) - ixtcreate(ch, els[nels-1], OREAD, d->mode, 1); - else - ixtcreate(ch, els[nels-1], OWRITE, d->mode, 0); - /* fid automatically clunked on errors and eof */ - PBIT32(buf, 0777); - ixtwattr(ch, "mode", buf, BIT32SZ, 0); - ixtwattr(ch, "gid", "planb", 5, 0); - if(ixrsid(ch) < 0){ - fprint(2, "%s: sid: %r\n", a); - goto Done; - } - if(ixrfid(ch) < 0){ - fprint(2, "%s: fid: %r\n", a); - closech(ch); - goto Done; - } - if(ixrclone(ch, nil) < 0){ - fprint(2, "%s: clone: %r\n", a); - closech(ch); - goto Done; - } - if(nels > 1 && ixrwalk(ch) < 0){ - fprint(2, "%s: walk: %r\n", a); - goto Done; - } - if(ixrcreate(ch) < 0){ - fprint(2, "%s: create: %r\n", a); - closech(ch); - goto Done; - } - if(ixrwattr(ch) < 0){ - fprint(2, "%s: wattr: %r\n", a); - closech(ch); - goto Done; - } - if(ixrwattr(ch) < 0){ - fprint(2, "%s: wattr: %r\n", a); - closech(ch); - goto Done; - } - if((d->qid.type&QTDIR) == 0){ - nw = 0; - offset = 0ULL; - for(;;){ - m = newmsg(pool); - nr = IOCAP(m->io) - Chhdrsz - twritehdrsz; - m->io->wp += twritehdrsz; - nr = read(fd, m->io->wp, nr); - if(nr <= 0){ - if(nr < 0) - fprint(2, "%s: read: %r", fn); - ixtclose(ch, 1); - break; - } - m->io->wp += nr; - if(ixtwrite(ch, m, nr, offset, offset+nr, 0) < 0){ - closech(ch); - drainch(ch); - goto Done; - } - nw++; - offset += nr; - - /* read replies so that no more than - * 10 outstanding writes are going. - */ - if(nw > 10){ - nw--; - if(ixrwrite(ch, nil) < 0){ - fprint(2, "%s: write: %r\n", a); - closech(ch); - goto Done; - } - } - } - while(nw-- > 0) - if(ixrwrite(ch, nil) < 0){ - fprint(2, "%s: write: %r\n", a); - closech(ch); - goto Done; - } - ixrclose(ch); - } -Done: - if(fd >= 0) - close(fd); - sendul(wc, 0); - free(path); - threadexits(nil); - close(fd); -} - -static void -ixattach(char *) -{ - Ch *ch; - char *u; - int afid; - - ch = newch(cm); - ixtversion(ch, 0); - ixtsession(ch, Nossid, getuser(), 0, 0); - ixtattach(ch, "main", 1); - if(ixrversion(ch, &msz) < 0) - sysfatal("wrong ix version: %r"); - if(ixrsession(ch, &ssid, &afid, &u) < 0) - sysfatal("can't set session: %r"); - print("session is %d %s %s \n", ssid, getuser(), u); - if(ixrattach(ch, &rootfid) < 0) - sysfatal("can't attach: %r"); -} - -static void -usage(void) -{ - fprint(2, "usage: %s [-fhpc] [-D flags] [-m msz] [-a addr] file...\n", argv0); - exits("usage"); -} - -void -threadmain(int argc, char *argv[]) -{ - char *addr, *flags; - int i, dosleep, doput, docond; - - addr = CLIADDR; - dosleep = doput = docond = 0; - ARGBEGIN{ - case 'D': - flags = EARGF(usage()); - for(;*flags != 0; flags++) - dbg[*flags]++; - dbg['d']++; - break; - case 'a': - addr = EARGF(usage()); - break; - case 'm': - msz = atoi(EARGF(usage())); - if(msz < 1) - sysfatal("message size too short"); - break; - case 's': - dosleep = 1; - break; - case 'f': - doflush = 1; - break; - case 'p': - doput = 1; - break; - case 'c': - docond = 1; - break; - default: - usage(); - }ARGEND; - if(argc == 0 || doput + docond + doflush> 1) - usage(); - outofmemoryexits(1); - fmtinstall('G', ixcallfmt); - fmtinstall('M', dirmodefmt); - fmtinstall('D', dirfmt); - ses = dialsrv(addr); - if(ses == nil) - sysfatal("dialsrv: %r"); - pool = newpool(Msgsz, Nmsgs); - spool = newpool(Smsgsz, Nmsgs); - startses(ses, pool, spool); - cm = muxses(ses->rc, ses->wc, ses->ec); - ixattach(getuser()); - wc = chancreate(sizeof(ulong), argc); - for(i = 0; i < argc; i++) - if(doput) - proccreate(putproc, argv[i], Stack); - else if(docond) - proccreate(condproc, argv[i], Stack); - else - proccreate(getproc, argv[i], Stack); - for(i = 0; i < argc; i++) - recvul(wc); - chanfree(wc); - closemux(cm); - if(dosleep){ - print("%s: sleeping forever\n", argv0); - for(;;) - sleep(3600); - } - threadexits(nil); -} diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/ixreqs.c --- a/sys/src/cmd/ix/ixreqs.c Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,540 +0,0 @@ -#include -#include -#include -#include -#include "conf.h" -#include "msg.h" -#include "mpool.h" -#include "tses.h" -#include "ch.h" -#include "dbg.h" -#include "ix.h" -#include "ixreqs.h" - -static int -sendreq(Ch *ch, IXcall *t, Msg *m, int last) -{ - int n; - - /* - * Twrite and Twattr read data directly after the packed T call, - * and set io's rp and wp by themselves. - * Requests using strings like Tattach, Twalk, may not - * fit in a small Msg if strings are large, in which case - * we try using a large buffer before failing. - */ - dfprint("%cch%d-> %G\n", last?'|':'-', ch->id, t); - if(t->type != IXTwrite && t->type != IXTwattr && t->type != IXTcond){ - n = ixpack(t, m->io->wp, IOCAP(m->io)); - if(n < 0 && IOCAP(m->io) < Msgsz){ - /* try with a large buffer */ - freemsg(m); - m = newmsg(pool); - n = ixpack(t, m->io->wp, IOCAP(m->io)); - } - }else - n = ixpack(t, m->io->bp, ixpackedsize(t)); - if(n <= 0) - sysfatal("sendreq: pack"); - if(t->type != IXTwrite && t->type != IXTwattr && t->type != IXTcond) - m->io->wp += n; - return chsend(ch, m, last); -} - - -int -ixtversion(Ch *ch, int last) -{ - IXcall t; - Msg *m; - - m = newmsg(spool); - t.type = IXTversion; - t.msize = Msgsz; - t.version = "3.1415926P"; - return sendreq(ch, &t, m, last); -} - -int -ixtsession(Ch *ch, int ssid, char *u, int keep, int last) -{ - IXcall t; - Msg *m; - - m = newmsg(spool); - t.type = IXTsession; - t.ssid = ssid; - t.uname = u; - t.keep = keep; - return sendreq(ch, &t, m, last); -} - -int -ixtsid(Ch *ch, int ssid, int last) -{ - IXcall t; - Msg *m; - - m = newmsg(spool); - t.type = IXTsid; - t.ssid = ssid; - return sendreq(ch, &t, m, last); -} - -static int -ixtmsg(Ch *ch, int type, int last) -{ - IXcall t; - Msg *m; - - m = newmsg(spool); - t.type = type; - return sendreq(ch, &t, m, last); -} - -int -ixtendsession(Ch *ch, int last) -{ - return ixtmsg(ch, IXTendsession, last); -} - -int -ixtfid(Ch *ch, int fid, int last) -{ - IXcall t; - Msg *m; - - m = newmsg(spool); - t.type = IXTfid; - t.fid = fid; - return sendreq(ch, &t, m, last); -} - -int -ixtattach(Ch *ch, char *aname, int last) -{ - IXcall t; - Msg *m; - - m = newmsg(spool); - t.type = IXTattach; - t.aname = aname; - return sendreq(ch, &t, m, last); -} - -int -ixtclone(Ch *ch, int cflags, int last) -{ - IXcall t; - Msg *m; - - m = newmsg(spool); - t.type = IXTclone; - t.cflags = cflags; - return sendreq(ch, &t, m, last); -} - -int -ixtwalk(Ch *ch, int nel, char **elem, int last) -{ - IXcall t; - Msg *m; - int i; - - m = newmsg(spool); - t.type = IXTwalk; - t.nwname = nel; - if(nel > Nwalks) - sysfatal("ixtwalk: bug: too many elems"); - - for(i = 0; i < nel; i++) - t.wname[i] = elem[i]; - return sendreq(ch, &t, m, last); -} - -int -ixtopen(Ch *ch, int mode, int last) -{ - IXcall t; - Msg *m; - - m = newmsg(spool); - t.type = IXTopen; - t.mode = mode; - return sendreq(ch, &t, m, last); -} - -int -ixtcreate(Ch *ch, char *name, int mode, int perm, int last) -{ - IXcall t; - Msg *m; - - m = newmsg(spool); - t.type = IXTcreate; - t.name = name; - t.perm = perm; - t.mode = mode; - return sendreq(ch, &t, m, last); -} - -int -ixtread(Ch *ch, int nmsg, long count, uvlong offset, int last) -{ - IXcall t; - Msg *m; - - m = newmsg(spool); - t.type = IXTread; - t.nmsg = nmsg; - t.count = count; - t.offset = offset; - return sendreq(ch, &t, m, last); -} - -int -ixtwrite(Ch *ch, Msg *m, long count, uvlong offset, uvlong endoffset, int last) -{ - IXcall t; - - t.type = IXTwrite; - t.offset = offset; - t.endoffset = endoffset; - t.count = count; - t.data = m->io->bp + ixpackedsize(&t); /* so fmt works */ - return sendreq(ch, &t, m, last); -} - -int -ixtclunk(Ch *ch, int last) -{ - return ixtmsg(ch, IXTclunk, last); -} - -int -ixtclose(Ch *ch, int last) -{ - return ixtmsg(ch, IXTclose, last); -} - -int -ixtremove(Ch *ch, int last) -{ - return ixtmsg(ch, IXTremove, last); -} - -int -ixtattr(Ch *ch, char *attr, int last) -{ - IXcall t; - Msg *m; - - m = newmsg(spool); - t.type = IXTattr; - t.attr = attr; - return sendreq(ch, &t, m, last); -} - -int -ixtwattr(Ch *ch, char *attr, void *data, long nvalue, int last) -{ - IXcall t; - Msg *m; - uchar *value; - - value = data; - m = newmsg(pool); - t.type = IXTwattr; - t.attr = attr; - t.nvalue = nvalue; - m->io->wp += ixpackedsize(&t); - t.value = m->io->wp; /* for fmt */ - memmove(m->io->wp, value, nvalue); - m->io->wp += nvalue; - return sendreq(ch, &t, m, last); -} - -int -ixtcond(Ch *ch, Msg *m, int op, char *attr, long nvalue, int last) -{ - IXcall t; - - t.type = IXTcond; - t.op = op; - t.attr = attr; - t.nvalue = nvalue; - return sendreq(ch, &t, m, last); -} - -int -ixtmove(Ch *ch, int dirfid, char *newname, int last) -{ - IXcall t; - Msg *m; - - m = newmsg(spool); - t.type = IXTmove; - t.dirfid = dirfid; - t.newname = newname; - return sendreq(ch, &t, m, last); -} - -static Msg* -getreply(Ch *ch, int type, IXcall *r) -{ - Msg *m; - int last, id, n; - -Again: - id = ch->id; /* ch is released if last */ - m = chrecv(ch, &last); - if(m == nil){ - werrstr("eof"); - dfprint("getreply: %r\n"); - return nil; - } - n = ixunpack(m->io->rp, IOLEN(m->io), r); - if(n <= 0){ - werrstr("getreply: rp %#p wp %#p ep %#p %r", m->io->rp, m->io->wp, m->io->ep); - dfprint("getreply: %r\n"); - freemsg(m); - return nil; - } - m->io->rp += n; - - switch(r->type){ /* needed just for printing the reply */ - case IXRread: - case IXTwrite: - r->count = IOLEN(m->io); - break; - case IXRattr: - case IXTwattr: - case IXTcond: - r->nvalue = IOLEN(m->io); - break; - } - - dfprint("<-ch%d%c %G\n", id, last?'|':'-', r); - if(r->type == type) - return m; - if(r->type == IXRerror) - werrstr("%s", r->ename); - else{ - werrstr("wrong reply type %d", r->type); - /* - * we could fail always here because we got an unexpected reply, - * but, this permits issuing requests, and then check the - * status on a later request without having to call the - * receive function for each request unless we are really - * interested in the reply. - */ - if(!last){ - freemsg(m); - goto Again; - } - } - freemsg(m); - return nil; -} - -int -ixrversion(Ch *ch, ulong *mszp) -{ - Msg *m; - IXcall r; - - m = getreply(ch, IXRversion, &r); - if(m == nil) - return -1; - if(strcmp(r.version, "3.1415926P") != 0){ - werrstr("wrong version %s", r.version); - freemsg(m); - return -1; - } - if(mszp != nil && (*mszp == 0 || r.msize < *mszp)){ - *mszp = r.msize; - dfprint("msize %uld\n", *mszp); - } - freemsg(m); - return 0; -} - -int -ixrsession(Ch *ch, int *ssid, int *afid, char **u) -{ - Msg *m; - IXcall r; - - m = getreply(ch, IXRsession, &r); - if(m == nil) - return -1; - if(ssid != nil) - *ssid = r.ssid; - if(afid != nil) - *afid = r.afid; - if(u != nil) - *u = strdup(r.uname); - freemsg(m); - return 0; -} - -static int -ixrmsg(Ch *ch, int type) -{ - Msg *m; - IXcall r; - - m = getreply(ch, type, &r); - if(m == nil) - return -1; - freemsg(m); - return 0; -} - -int -ixrsid(Ch *ch) -{ - return ixrmsg(ch, IXRsid); -} - -int -ixrendsession(Ch *ch) -{ - return ixrmsg(ch, IXRendsession); -} - -int -ixrfid(Ch *ch) -{ - return ixrmsg(ch, IXRfid); -} - -int -ixrattach(Ch *ch, int *fidp) -{ - Msg *m; - IXcall r; - - m = getreply(ch, IXRattach, &r); - if(m == nil) - return -1; - if(fidp != nil) - *fidp = r.fid; - freemsg(m); - return 0; -} - -int -ixrclone(Ch *ch, int *fidp) -{ - Msg *m; - IXcall r; - - m = getreply(ch, IXRclone, &r); - if(m == nil) - return -1; - freemsg(m); - if(fidp != nil) - *fidp = r.fid; - return 0; -} - -int -ixrwalk(Ch *ch) -{ - return ixrmsg(ch, IXRwalk); -} - -int -ixropen(Ch *ch) -{ - return ixrmsg(ch, IXRopen); -} - -int -ixrcreate(Ch *ch) -{ - return ixrmsg(ch, IXRcreate); -} - -Msg* -ixrread(Ch *ch) -{ - Msg *m; - IXcall r; - - m = getreply(ch, IXRread, &r); - if(m == nil) - return nil; - r.count = IOLEN(m->io); /* unused */ - return m; -} - -long -ixrwrite(Ch *ch, uvlong *offsetp) -{ - Msg *m; - IXcall r; - - m = getreply(ch, IXRwrite, &r); - if(m == nil) - return -1; - if(offsetp) - *offsetp = r.offset; - freemsg(m); - return r.count; -} - -int -ixrclunk(Ch *ch) -{ - return ixrmsg(ch, IXRclunk); -} - -int -ixrclose(Ch *ch) -{ - return ixrmsg(ch, IXRclose); -} - -int -ixrremove(Ch *ch) -{ - return ixrmsg(ch, IXRremove); -} - -Msg* -ixrattr(Ch *ch) -{ - Msg *m; - IXcall r; - - m = getreply(ch, IXRattr, &r); - if(m == nil) - return nil; - r.nvalue = IOLEN(m->io); /* unused */ - return m; -} - -int -ixrwattr(Ch *ch) -{ - return ixrmsg(ch, IXRwattr); -} - -int -ixrcond(Ch *ch) -{ - return ixrmsg(ch, IXRcond); -} - -int -ixrmove(Ch *ch) -{ - return ixrmsg(ch, IXRmove); -} - -/* - * NB: Tflush, Rflush are done by aborting the channel - * in this implementation. - */ diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/ixreqs.h --- a/sys/src/cmd/ix/ixreqs.h Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ - - -/* |c/f2p ixreqs.c */ -extern int ixrattach(Ch *ch, int *fidp); -extern Msg* ixrattr(Ch *ch); -extern int ixrclone(Ch *ch, int *fidp); -extern int ixrclose(Ch *ch); -extern int ixrclunk(Ch *ch); -extern int ixrcond(Ch *ch); -extern long ixrcopy(Ch *ch); -extern int ixrcreate(Ch *ch); -extern int ixrendsession(Ch *ch); -extern int ixrfid(Ch *ch); -extern int ixrmove(Ch *ch); -extern int ixropen(Ch *ch); -extern Msg* ixrread(Ch *ch); -extern int ixrremove(Ch *ch); -extern int ixrsession(Ch *ch, int *ssid, int *afid, char **u); -extern int ixrsid(Ch *ch); -extern int ixrversion(Ch *ch, ulong *mszp); -extern int ixrwalk(Ch *ch); -extern int ixrwattr(Ch *ch); -extern long ixrwrite(Ch *ch, uvlong *offsetp); -extern int ixtattach(Ch *ch, char *aname, int last); -extern int ixtattr(Ch *ch, char *attr, int last); -extern int ixtclone(Ch *ch, int cflags, int last); -extern int ixtclose(Ch *ch, int last); -extern int ixtclunk(Ch *ch, int last); -extern int ixtcond(Ch *ch, Msg *m, int op, char *attr, long nvalue, int last); -extern int ixtcopy(Ch *ch, int nmsg, long count, uvlong offset, long msz,int dstfid, uvlong dstoffset, int last); -extern int ixtcreate(Ch *ch, char *name, int mode, int perm, int last); -extern int ixtendsession(Ch *ch, int last); -extern int ixtfid(Ch *ch, int fid, int last); -extern int ixtmove(Ch *ch, int dirfid, char *newname, int last); -extern int ixtopen(Ch *ch, int mode, int last); -extern int ixtread(Ch *ch, int nmsg, long count, uvlong offset, int last); -extern int ixtremove(Ch *ch, int last); -extern int ixtsession(Ch *ch, int ssid, char *u, int keep, int last); -extern int ixtsid(Ch *ch, int ssid, int last); -extern int ixtversion(Ch *ch, int last); -extern int ixtwalk(Ch *ch, int nel, char **elem, int last); -extern int ixtwattr(Ch *ch, char *attr, void *value, long nvalue, int last); -extern int ixtwrite(Ch *ch, Msg *m, long count, uvlong offset, uvlong endoffset, int last); - -extern Mpool *pool, *spool; diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/mkfile.notyet --- a/sys/src/cmd/ix/mkfile.notyet Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ - -#include -#include /* chancreate */ -#include -#include "conf.h" -#include "msg.h" -#include "mpool.h" -#include "dbg.h" - -static Mbuf *bufs; -static Lock bufslck; -static int nbufs; -static int nmaxbufs; - -void -freepoolmsg(Msg *m) -{ - int i; - Mbuf *mb; - Mpool *mp; - - mb = m->aux; - assert(&mb->m == m); - - dPprint("freepoolmsg %#p pc %#ulx\n", mb, getcallerpc(&m)); - mp = mb->mp; - mb->m.hdr = nil; - mb->m.io[0].bp = mb->buf; - mb->m.io[0].rp = mb->buf; - mb->m.io[0].wp = mb->buf; - mb->m.io[0].ep = mb->m.io[0].bp + mp->msize; - for(i = 1; i < nelem(mb->m.io); i++){ - mb->m.io[i].bp = nil; - mb->m.io[i].rp = nil; - mb->m.io[i].wp = nil; - mb->m.io[i].ep = nil; - } - sendp(mp->bc, mb); - lock(mp); - mp->nfree++; - mp->nfrees++; - unlock(mp); -} - -Mpool* -newpool(ulong msize, int nmsg) -{ - Mpool *mp; - Mbuf *mb; - int i; - - if(nmsg == 0) - sysfatal("newpool: called for 0 messages"); - mp = mallocz(sizeof *mp, 1); - mp->msize = msize; - mp->bc = echancreate(sizeof(Mbuf*), nmsg); - for(i = 0; i < nmsg; i++){ - mb = nil; - if(bufs != nil){ - lock(&bufslck); - if(bufs != nil){ - mb = bufs; - bufs = bufs->next; - nbufs--; - } - unlock(&bufslck); - } - if(mb == nil) - mb = malloc(sizeof(Mbuf) + msize); - if(mb == nil) - break; - memset(mb, 0, sizeof *mb); - mb->mp = mp; - mb->m.io[0].bp = mb->buf; - mb->m.io[0].rp = mb->buf; - mb->m.io[0].wp = mb->buf; - mb->m.io[0].ep = mb->buf + msize; - mb->m.aux = mb; - mb->m.free = freepoolmsg; - mp->nmsg++; - mp->nfree++; - sendp(mp->bc, mb); - } - if(i == 0){ - chanfree(mp->bc); - free(mp); - return nil; - } - return mp; -} - -void -poolstats(Mpool *mp) -{ - dprint("pool %p: nmsg %d nfree %d nminfree %d nallocs %uld nfrees %uld\n", - mp, mp->nmsg, mp->nfree, mp->nminfree, mp->nallocs, mp->nfrees); - dprint("nbufs %d nmaxbufs %d\n", nbufs, nmaxbufs); -} - -/* - * To free a pool we must collect all messages allocated - * from it. - * Note that the caller might have given a message to other process - * which might free it after freepool is called. - * e.g., a client may terminate a session and release its pool, but - * the session read process may be still terminating and holding - * its last message buffer. - */ -void -freepool(Mpool *mp) -{ - Mbuf *mb; - int i; - - if(mp == nil) - return; - if(mp->freepool != nil){ - mp->freepool(mp); - return; - } - for(i = 0; i < mp->nmsg; i++){ - mb = recvp(mp->bc); - lock(&bufslck); - mb->next = bufs; - mb->mp = nil; - mb->m.free = nil; - bufs = mb; - nbufs++; - if(nmaxbufs < nbufs) - nmaxbufs = nbufs; - unlock(&bufslck); - } - poolstats(mp); - chanfree(mp->bc); - memset(mp, 9, sizeof *mp); - free(mp); -} - -Msg* -newmsg(Mpool *mp) -{ - Mbuf *mb; - - if(mp == nil) - sysfatal("newmsg: nil pool"); - - mb = recvp(mp->bc); - setmalloctag(mb, getcallerpc(&mp)); - dPprint("newmsg %#p pc %#ulx\n", mb, getcallerpc(&mp)); - lock(mp); - mp->nfree--; - mp->nallocs++; - if(mp->nfree < mp->nminfree) - mp->nminfree = mp->nfree; - unlock(mp); - return &mb->m; -} - diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/mpool.h --- a/sys/src/cmd/ix/mpool.h Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ - -typedef struct Mpool Mpool; -typedef struct Mbuf Mbuf; - -struct Mbuf -{ - Msg m; - Mpool *mp; - Mbuf* next; - uchar buf[]; -}; - -struct Mpool -{ - Lock; /* stats */ - int nmsg; - ulong msize; - int nfree; - ulong nallocs; - ulong nfrees; - int nminfree; - - void (*freepool)(Mpool*); - Channel *bc; -}; - -/* |c/f2p mpool.c */ -extern void poolstats(Mpool *mp); -extern void freepool(Mpool *mp); -extern void freepoolmsg(Msg *m); -extern Msg* newmsg(Mpool *mp); -extern Mpool* newpool(ulong msize, int nmsg); diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/msg.c --- a/sys/src/cmd/ix/msg.c Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,224 +0,0 @@ -/* - * Gather/scatter messages with protocol headers - */ -#include -#include -#include /* chancreate */ -#include -#include "conf.h" -#include "msg.h" -#include "mpool.h" -#include "dbg.h" - -void -ioreset(Io *io) -{ - io->rp = io->bp; - io->wp = io->bp; -} - -static int -hdrlen(Msg *m) -{ - if(m->hdr == nil) - return 0; - return (m->hbuf + sizeof m->hbuf) - m->hdr; -} - -Channel* -echancreate(int elsz, int n) -{ - Channel *c; - - c = chancreate(elsz, n); - if(c == nil) - sysfatal("chancreate"); - setmalloctag(c, getcallerpc(&elsz)); - return c; -} - -long -msglen(Msg *m) -{ - Io *io; - long tot; - int i; - - tot = hdrlen(m); - for(i = 0; i < nelem(m->io); i++){ - io = &m->io[i]; - if(io->bp == nil) - break; - tot += IOLEN(io); - } - return tot; -} - -void* -msgpushhdr(Msg *m, long sz) -{ - if(m->hdr == nil) - m->hdr = m->hbuf + sizeof m->hbuf; - if(m->hdr - m->hbuf < sz){ - werrstr("no room for headers"); - return nil; - } - m->hdr -= sz; - return m->hdr; -} - -void* -msgpophdr(Msg *m, long sz) -{ - void *p; - - if(m->hdr != nil){ - if(hdrlen(m) < sz){ - werrstr("short header"); - return nil; - } - p = m->hbuf; - m->hdr += sz; - return p; - } - /* - * no headers in hbuf, probably they were read along with - * the body, take them from there. - */ - if(m->io[0].rp != nil && IOLEN(&m->io[0]) >= sz){ - p = m->io[0].rp; - m->io[0].rp += sz; - return p; - } - werrstr("short header"); - return nil; -} - -int -msgput(Msg *m, void *p, long sz) -{ - int i; - Io *io; - - for(i = 0; i < nelem(m->io); i++){ - io = &m->io[i]; - if(io->bp == nil) - break; - } - if(i == nelem(m->io)) - sysfatal("msgputtd: msg full"); - m->io[i].bp = p; - m->io[i].rp = p; - m->io[i].wp = m->io[i].rp + sz; - m->io[i].ep = m->io[i].wp; - return i; -} - -int -readmsg(int fd, Msg *m) -{ - uchar hdr[BIT16SZ]; - long nhdr, nr; - ulong sz; - - werrstr("eof"); - nhdr = readn(fd, hdr, sizeof hdr); - if(nhdr < 0){ - dmprint("readmsg: %r\n"); - return -1; - } - if(nhdr == 0){ - dmprint("readmsg: eof\n"); - return 0; - } - if(nhdr < sizeof hdr){ - werrstr("short header %r"); - return -1; - } - sz = GBIT16(hdr); - if(sz > IOCAP(&m->io[0])){ - /* - * Message too long. - * We could read it and skip it, but let's fail - * so the user knows. - */ - fprint(2, "readmsg: message too long (%uld > %d)\n", - sz, Msgsz); - werrstr("message too long"); - return -1; - } - nr = readn(fd, m->io->wp, sz); - dmprint("readmsg: %ld+%ld bytes sz %ld\n", nhdr, nr, sz); - if(nr != sz){ - werrstr("short msg data"); - return -1; - } - m->io->wp += nr; - return nr; -} - -long -writemsg(int fd, Msg *m) -{ - Io *io; - long len, hlen, iol; - uchar *hdr; - int i; - - len = msglen(m); - if(len > 0xFFFF){ - werrstr("message too long"); - return -1; - } - hdr = msgpushhdr(m, BIT16SZ); - if(hdr == nil) - return -1; - PBIT16(hdr, len); - hlen = hdrlen(m); - if(write(fd, hdr, hlen) != hlen) - goto Fail; - for(i = 0; i < nelem(m->io); i++){ - io = &m->io[i]; - if(io->bp == nil) - break; - iol = IOLEN(io); - if(write(fd, io->rp, iol) != iol) - goto Fail; - dmprint("writemsg: %ld bytes\n", iol); - } - msgpophdr(m, BIT16SZ); - return len; -Fail: - msgpophdr(m, BIT16SZ); - return -1; -} - -void -freemsg(Msg *m) -{ - Io *io; - int i; - - if(m == nil) - return; - if(m->free != nil){ - dPprint("freemsg pc %#p\n", getcallerpc(&m)); - m->free(m); - return; - } - for(i = 0; i < nelem(m->io); i++){ - io = &m->io[i]; - if(io->bp == nil) - break; - free(io->bp); - } - free(m); -} - -void -dumpmsg(Msg *m) -{ - print("msg %#p hdr %#p ehdr %#p bp %#p rp %#p wp %#p ep %#p\n", - m, m->hdr, m->hbuf + sizeof m->hbuf, - m->io->bp, m->io->rp, m->io->wp, m->io->ep); -} diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/msg.h --- a/sys/src/cmd/ix/msg.h Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -typedef struct Msg Msg; -typedef struct Io Io; - -enum -{ - Nio = 1, -}; - -struct Io -{ - uchar *bp; /* buffer pointer */ - uchar *rp; /* read pointer */ - uchar *wp; /* write pointer */ - uchar *ep; /* end pointer */ -}; - -struct Msg -{ - uchar hbuf[Hbufsz]; - uchar* hdr; /* headers go from hdr to &hbuf[Hdrsz] */ - Io io[Nio]; - void* aux; - void (*free)(Msg*); -}; - -#define IOLEN(io) ((io)->wp - (io)->rp) -#define IOCAP(io) ((io)->ep - (io)->wp) - -/* |c/f2p msg.c */ -extern void dumpmsg(Msg *m); -extern Channel* echancreate(int elsz, int n); -extern void freemsg(Msg *m); -extern void ioreset(Io *io); -extern long msglen(Msg *m); -extern void* msgpophdr(Msg *m, long sz); -extern void* msgpushhdr(Msg *m, long sz); -extern int msgput(Msg *m, void *p, long sz); -extern int readmsg(int fd, Msg *m); -extern long writemsg(int fd, Msg *m); diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/nsfile.c --- a/sys/src/cmd/ix/nsfile.c Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,849 +0,0 @@ -/* - * File tree kept in an external file system. - * Metadata is kept in an index file. - * External changes are detected. - * Suitable for use as a cache of a remote file tree. - */ - -#include -#include -#include -#include -#include -#include -#include "conf.h" -#include "file.h" -#include "dbg.h" - -static File *root; -static char *dir; -static int usedb; - -static char* -qidtype(char *s, uchar t) -{ - char *p; - - p = s; - if(t & QTDIR) - *p++ = 'd'; - if(t & QTAPPEND) - *p++ = 'a'; - if(t & QTEXCL) - *p++ = 'l'; - if(t & QTAUTH) - *p++ = 'A'; - *p = '\0'; - return s; -} - - -static void -fdirconv(char *buf, char *e, Dir *d) -{ - char tmp[16]; - - seprint(buf, e, "%s '%s' " - "(%llux %lud %s) %#luo l %lld mt %uld", d->name, - d->uid, - d->qid.path, d->qid.vers, qidtype(tmp, d->qid.type), d->mode, - d->length, d->mtime); -} - -int -shortdirfmt(Fmt *fmt) -{ - char buf[160]; - - fdirconv(buf, buf+sizeof buf, va_arg(fmt->args, Dir*)); - return fmtstrcpy(fmt, buf); -} - -Dir* -dupdir(Dir *d) -{ - int sz; - Dir *nd; - char *s; - - sz = strlen(d->name) + strlen(d->uid) + - strlen(d->gid) + strlen(d->muid) + 4; - nd = emalloc(sizeof *nd + sz); - *nd = *d; - nd->name = (char*)(nd+1); - s = strecpy(nd->name, nd->name+sz, d->name); - nd->uid = s+1; - s = strecpy(nd->uid, nd->name+sz, d->uid); - nd->gid = s+1; - s = strecpy(nd->gid, nd->name+sz, d->gid); - nd->muid = s+1; - strecpy(nd->muid, nd->name+sz, d->muid); - return nd; -} - -int -filefmt(Fmt *fmt) -{ - File *f; - Dir *sd; - char tmp[16]; - - f = va_arg(fmt->args, File*); - if(f == nil) - return fmtprint(fmt, ""); - if((sd = f->sd) != nil) - return fmtprint(fmt, "'%s' r=%ld sq (%llux %lud %s) %D", - f->path, f->ref, - sd->qid.path, sd->qid.vers, qidtype(tmp, sd->qid.type), - f->d); - else - return fmtprint(fmt, "'%s' r=%ld %D", - f->path, f->ref, f->d); -} - -static void -dumpfile(File *f) -{ - print("%T\n", f); - for(f = f->child; f != nil; f = f->next) - dumpfile(f); -} - -/* - * BEWARE: no locks. - */ -void -dumptree(void) -{ - dumpfile(root); -} - -static void -delchild(File *parent, File *f) -{ - File **fp; - - for(fp = &parent->child; *fp != nil; fp = &(*fp)->next) - if(*fp == f) - break; - if(*fp == nil) - sysfatal("delchild"); - *fp = f->next; - f->next = nil; - parent->nchild--; - f->parent = nil; -} - -static void -addchild(File *parent, File *f) -{ - assert(f->next == nil); - f->next = parent->child; - parent->child = f; - parent->nchild++; - f->parent = parent; -} - -File* -getchild(File *parent, char *name) -{ - File *f; - - for(f = parent->child; f != nil; f = f->next) - if(strcmp(f->d->name, name) == 0){ - incref(f); - return f; - } - return nil; -} - -void -putfile(File *f) -{ - File *parent; - - if(decref(f) > 0) - return; - parent = f->parent; - if(parent != nil){ - wlock(parent); - delchild(parent, f); - wunlock(parent); - } - while(f->child != nil) - putfile(f->child); - free(f->path); - free(f->d); - free(f); -} - -/* - * parent must be wlocked by caller. - */ -static void -unlinkfile(File *f) -{ - if(f->parent != nil) - delchild(f->parent, f); - putfile(f); -} - -/* - * keeps ptr to path within new file. - */ -File* -newfile(File *parent, char *path, Dir *d) -{ - File *f; - - if(d == nil){ - dnprint("dirstat %s (newfile)\n", path); - d = dirstat(path); - } - if(d == nil) - return nil; - - f = emalloc(sizeof *f); - f->ref = 1; - f->path = path; - if(parent != nil) - addchild(parent, f); - f->d = d; - return f; -} - -static Dir* -readdir(Biobuf *bin, char *p) -{ - static uchar buf[DIRMAX]; - ulong sz; - Dir *d; - - if(Bread(bin, buf, BIT16SZ) != BIT16SZ){ - fprint(2, "%s: %s: eof\n", argv0, p); - return nil; - } - sz = GBIT16(buf); - if(BIT16SZ + sz > sizeof buf){ - fprint(2, "%s: %s: dir too long\n", argv0, p); - return nil; - } - if(Bread(bin, buf + BIT16SZ, sz) != sz){ - fprint(2, "%s: %s: read failed\n", argv0, p); - return nil; - } - d = emalloc(sizeof *d + sz); - if(convM2D(buf, sizeof buf, d, (char*)(d+1)) <= 0){ - fprint(2, "%s: %s: convM2D failed\n", argv0, p); - free(d); - return nil; - } - return d; -} - -static File* -loaddir(Biobuf *bin, File *parent) -{ - File *f; - Dir *d, *sd; - int nchild; - char *p; - - p = "/"; - if(parent != nil) - p = parent->path; - d = readdir(bin, p); - if(d == nil) - return nil; - sd = readdir(bin, p); - if(sd == nil){ - free(d); - return nil; - } - f = emalloc(sizeof *f); - f->ref = 1; - f->d = d; - f->sd = sd; - if(parent == nil) - f->path = estrdup("."); - else{ - f->path = smprint("%s/%s", parent->path, f->d->name); - addchild(parent, f); - } - if(ISDIR(f)){ - nchild = f->d->length; - f->d->length = 0; - while(nchild-- > 0) - if(loaddir(bin, f) == nil) - break; - } - if(dbg['n'] > 1) - dnprint("loaded %T\n", f); - return f; -} - -static int -changed(Dir *d1, Dir *d2) -{ - if((d1->qid.type&QTDIR) != 0 && (d2->qid.type&QTDIR) != 0) - return 0; - return d1->length != d2->length || d1->mtime != d2->mtime || - d1->qid.path != d2->qid.path || d1->qid.vers != d2->qid.vers || - d1->qid.type != d2->qid.type; -} - -static int -mchanged(Dir *d1, Dir *d2) -{ - return d1->mode != d2->mode || strcmp(d1->uid, d2->uid) != 0 || - strcmp(d1->gid, d2->gid) != 0; -} - -char* -tmpfile(char *name) -{ - return esmprint("%s.!.", name); -} - -static int -ignorename(char *name) -{ - int len; - - if(strcmp(name, ".ixd") == 0 || strcmp(name, ".ixd.new") == 0) - return 1; - len = strlen(name); - if(len > 3 && strcmp(&name[len-3], ".!.") == 0) - return 1; - if(len > 3 && strcmp(&name[len-3], ".!!") == 0) - return 1; - return 0; -} - - -static int -scandir(File *f, Dir *ud, int recur) -{ - Dir *d, *cd; - File *cf; - int i, nd, fd, mustrecur; - char *s; - - wlock(f); - if(dbg['n']>1) - dnprint("scan %s\n", f->path); - d = ud; - if(d == nil){ - dnprint("dirstat %s (scandir)\n", f->path); - d = dirstat(f->path); - } - if(d == nil){ - wunlock(f); - return 0; - } - if((f->d->qid.type&QTDIR) != (d->qid.type&QTDIR)){ - /* a file became a dir or a dir became a file - * get rid of the old data and scan it according to - * its new nature. - */ - dnprint("gone and came: %T\n", f); - if(ISDIR(f)){ - while(f->child != nil){ - unlinkfile(f->child); - } - f->d->qid.type &= ~QTDIR; - }else - f->d->qid.type |= QTDIR; - } - if(mchanged(f->d, d) || changed(f->d, d)){ - free(f->d); - if(d == ud) - d = dupdir(ud); - f->d = d; - dnprint("changed: %T\n", f); - } - wunlock(f); - rlock(f); - if(ISDIR(f)){ - fd = open(f->path, OREAD); - if(fd < 0){ - runlock(f); - free(d); - return -1; - } - dnprint("dirreadall %s\n", f->path); - nd = dirreadall(fd, &cd); - close(fd); - for(i = 0; i < nd; i++){ - if(ignorename(cd[i].name)) - continue; - cf = getchild(f, cd[i].name); - if(cf == nil){ - mustrecur = 1; - s = smprint("%s/%s", f->path, cd[i].name); - cf = newfile(f, s, dupdir(&cd[i])); - if(cf == nil){ - fprint(2, "%s: %s: %r\n", argv0, s); - free(s); - continue; - } - dnprint("came: %T\n", cf); - }else{ - mustrecur = recur; - putfile(cf); /* ref won't be zero */ - } - cf->visited = 1; - if(mustrecur ||!ISDIR(cf)){ - runlock(f); - scandir(cf, &cd[i], mustrecur); - rlock(f); - } - } - runlock(f); - wlock(f); - Again: - for(cf = f->child; cf != nil; cf = cf->next) - if(cf->visited == 0){ - /* - * If it's dirty, and has been removed, - * there's nothing we can do. - * let the client notice. - */ - dnprint("gone: %T\n", cf); - incref(cf); - unlinkfile(cf); - putfile(cf); - goto Again; /* list has changed */ - } - for(cf = f->child; cf != nil; cf = cf->next) - cf->visited = 0; - wunlock(f); - free(cd); - }else - runlock(f); - return 1; -} - -static int -writedir(Biobuf *bout, File *f) -{ - File *cf; - static uchar buf[DIRMAX]; - int n; - Dir d; - - wlock(f); - if(ISDIR(f)) - f->d->length = f->nchild; - n = convD2M(f->d, buf, sizeof buf); - if(ISDIR(f)) - f->d->length = 0; - if(Bwrite(bout, buf, n) != n){ - wunlock(f); - fprint(2, "%s: writedir: %r\n", f->path); - return -1; - } - if(f->sd == nil){ - nulldir(&d); - n = convD2M(&d, buf, sizeof buf); - }else - n = convD2M(f->sd, buf, sizeof buf); - if(Bwrite(bout, buf, n) != n){ - wunlock(f); - fprint(2, "%s: writedir2: %r\n", f->path); - return -1; - } - if(dbg['n'] > 1) - dnprint("written: %T\n", f); - wunlock(f); - rlock(f); - for(cf = f->child; cf != nil; cf = cf->next) - if(writedir(bout, cf) < 0){ - runlock(f); - return -1; - } - runlock(f); - return 0; -} - -void -childmap(File *f, void(*fn)(File*)) -{ - File *cf; - - rlock(f); - for(cf = f->child; cf != nil; cf = cf->next) - fn(cf); - wunlock(f); -} - -static int -writetree(File *f) -{ - Biobuf *bout; - Dir d; - int rc; - - bout = Bopen(".ixd.new", OWRITE); - if(bout == nil){ - fprint(2, "%s: writetree: %r\n", argv0); - return -1; - } - rc = writedir(bout, f); - if(Bterm(bout) < 0) - rc = -1; - if(rc < 0){ - remove(".ixd.new"); - return -1; - } - nulldir(&d); - d.name = ".ixd"; - if(dirwstat(".ixd.new", &d) < 0){ - fprint(2, "%s: rename .ixd: %r\n", argv0); - remove(".ixd.new"); - return -1; - } - return 0; -} - -static File* -loadtree(void) -{ - Biobuf *bin; - File *f; - - dnprint("loadtree:\n"); - bin = Bopen(".ixd", OREAD); - if(bin != nil){ - f = loaddir(bin, nil); - Bterm(bin); - }else - f = newfile(nil, ".", nil); - if(scandir(f, nil, 1) <= 0) - sysfatal("loadtree: can't scan root"); - if(bin == nil) - writetree(f); - return f; -} - -File* -rootfile(void) -{ - incref(root); - return root; -} - -void -fileinit(char *path, int udb) -{ - if(chdir(path) < 0) - sysfatal("chdir %s: %r", path); - usedb = udb; - if(usedb) - root = loadtree(); - else{ - root = newfile(nil, ".", nil); - if(scandir(root, nil, 1) <= 0) - sysfatal("can't scan %s", path); - } - if(root == nil) - sysfatal("fileinit: %r"); -} - -int -filesync(void) -{ - dnprint("filesync\n"); - if(usedb) - return writetree(root); - return 0; -} - -int -filechanged(File *f) -{ - Dir *nd; - int r; - - wlock(f); - r = None; - dnprint("dirstat %s\n", f->path); - nd = dirstat(f->path); - if(nd == nil){ - wunlock(f); - return Meta|Data|Gone; - } - if(changed(f->d, nd)) - r |= Data; - if(mchanged(f->d, nd)) - r |= Meta; - - free(f->d); - f->d = nd; - wunlock(f); - return r; -} - -int -wstatfile(File *f, Dir *d) -{ - Dir *nd; - Dir wd; - - dnprint("wstat: %T\n", f); - if(d->name[0] != 0 && strcmp(d->name, f->d->name) != 0 && - f->parent == nil){ - werrstr("can't rename /"); - return -1; - } - wlock(f); - if(dirwstat(f->path, d) < 0){ - nulldir(&wd); - wd.mode = d->mode; - if(dirwstat(f->path, &wd) < 0){ - wunlock(f); - return -1; - } - fprint(2, "%s: can't change uid/mtime/...: %r\n", f->path); - } - - if(d->name[0] != 0 && strcmp(d->name, f->d->name) != 0){ - free(f->path); - f->path = smprint("%s/%s", f->parent->path, d->name); - } - dnprint("dirstat %s\n", f->path); - nd = dirstat(f->path); - if(nd == nil) - sysfatal("wstatfile: dirstat bug"); - free(f->d); - f->d = nd; - wunlock(f); - return 0; -} - -Qid -fileqid(File *f) -{ - Qid q; - - rlock(f); - q = f->d->qid; - runlock(f); - return q; -} - -Dir* -statfile(File *f, int refresh) -{ - Dir *d; - - if(refresh){ - wlock(f); - dnprint("stat: %T\n", f); - d = dirstat(f->path); - if(d == nil){ - wunlock(f); - return nil; - } - free(f->d); - f->d = d; - d = dupdir(f->d); - wunlock(f); - }else{ - rlock(f); - d = dupdir(f->d); - runlock(f); - } - return d; -} - -int -walkfile(File **fp, char *elem) -{ - File *f, *nf; - - f = *fp; - dnprint("walk %s %s\n", f->path, elem); - if(utfrune(elem, '/') != nil){ - werrstr("'/' not allowed in file name"); - return -1; - } - if(strcmp(elem, ".") == 0) - return 0; - if(strcmp(elem, "..") == 0){ - if(f != root){ - incref(f->parent); - *fp = f->parent; - putfile(f); - } - return 0; - } - rlock(f); - nf = getchild(f, elem); - runlock(f); - if(nf == nil){ - werrstr("file does not exist"); - return -1; - } - putfile(f); - *fp = nf; - return 0; -} - -int -openfile(File *f, int mode) -{ - int fd; - - dnprint("open: mode %#x %T\n", mode, f); - if((mode&~(OTRUNC|3)) != 0){ - werrstr("bad mode for openfile"); - return -1; - } - wlock(f); - fd = open(f->path, mode); - if(fd >= 0) - f->nopens++; - wunlock(f); - return fd; -} - -void -closefile(File *f, int fd) -{ - wlock(f); - dnprint("close: %T\n", f); - close(fd); - if(--f->nopens == 0){ - dnprint("dirstat %s\n", f->path); - free(f->d); - f->d = dirstat(f->path); - if(f->d == nil) - sysfatal("closefile: dirstat bug"); - } - wunlock(f); -} - -int -createfile(File **fp, char *elem, int mode, int perm) -{ - char *s; - File *f, *nf; - int fd; - - f = *fp; - dnprint("create: %s in %T\n", elem, f); - if(utfrune(elem, '/') != nil){ - werrstr("'/' not allowed in file name"); - return -1; - } - if(strcmp(elem, ".") == 0 || strcmp(elem, "..") == 0){ - werrstr("'%s' can't be created", elem); - return -1; - } - if(mode&~(DMDIR|3)){ - werrstr("createfile: bad mode"); - return -1; - } - scandir(f, nil, 0); - wlock(f); - nf = getchild(f, elem); - if(nf != nil){ - /* - * truncate, actually. - */ - wlock(nf); - fd = create(nf->path, mode, perm); - if(fd >= 0) - nf->nopens++; - wunlock(nf); - wunlock(f); - putfile(*fp); - *fp = nf; - return fd; - } - s = smprint("%s/%s", f->path, elem); - fd = create(s, mode, perm); - if(fd < 0){ - free(s); - wunlock(f); - return -1; - } - nf = newfile(f, s, nil); - nf->nopens++; - wunlock(f); - incref(nf); - putfile(*fp); - *fp = nf; - return fd; -} - -long -preadfile(File *, int fd, void *a, ulong count, uvlong offset) -{ - return pread(fd, a, count, offset); -} - -long -pwritefile(File *, int fd, void *a, ulong count, uvlong offset) -{ - return pwrite(fd, a, count, offset); -} - -int -removefile(File *f) -{ - File *parent; - - dnprint("remove: %T\n", f); - parent = f->parent; - if(parent == nil){ - werrstr("can't remove /"); - return -1; - } -Again: - wlock(f); - incref(f); /* keep it here while we use it */ - parent = f->parent; - - if(!canwlock(parent)){ /* lock order: parent, then child */ - wunlock(f); - yield(); - goto Again; - } - if(remove(f->path) < 0){ - wunlock(f); - wunlock(parent); - putfile(f); - return -1; - } - unlinkfile(f); - - wunlock(f); - wunlock(parent); - /* - * We don't put the ref given by the caller. - * When he calls putfile() the file should go. - */ - return 0; -} - -enum -{ - Pother = 1, - Pgroup = 8, - Powner = 64, -}; - -int -perm(File *f, char *user, int p) -{ - if((p*Pother) & f->d->mode) - return 1; - if(strcmp(user, f->d->gid)==0 && ((p*Pgroup) & f->d->mode)) - return 1; - if(strcmp(user, f->d->uid)==0 && ((p*Powner) & f->d->mode)) - return 1; - return 0; -} - diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/nstest.c --- a/sys/src/cmd/ix/nstest.c Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -/* - * Test program for nsfile. - * - X/\[/D - ! mk 8.nstest - ! rm /tmp/tmeasure/new - ! rm /tmp/tmeasure/.ixd - ! 8.nstest -Dn /tmp/tmeasure >[2=1] - ! slay 8.nstest | rc - */ - -#include -#include -#include -#include -#include - -#include "conf.h" -#include "dbg.h" -#include "file.h" - - -static void -usage(void) -{ - fprint(2, "usage: %s [-s] [-D flags] dir\n", argv0); - exits("usage"); -} - -void -threadmain(int argc, char *argv[]) -{ - char *flags; - int dosleep; - File *f; - Dir *d; - Dir wd; - int fd, n; - char buf[128]; - - dosleep = 0; - ARGBEGIN{ - case 'D': - flags = EARGF(usage()); - for(;*flags != 0; flags++) - dbg[*flags]++; - dbg['d']++; - break; - case 's': - dosleep = 1; - break; - }ARGEND; - if(argc != 1) - usage(); - - fmtinstall('M', dirmodefmt); - fmtinstall('D', shortdirfmt); - fileinit(argv[0], 1); - f = rootfile(); - walkfile(&f, "plotnumb"); - walkfile(&f, "resultclose"); - d = statfile(f, 0); - print("got %D\n", d); - free(d); - fd = openfile(f, OWRITE); - if(fd < 0) - print("got %r\n"); - else{ - pwritefile(f, fd, "hola", 4, 0ULL); - print("file %T\n", f); - closefile(f, fd); - } - print("file %T\n", f); - putfile(f); - f = rootfile(); - if(walkfile(&f, "foo") < 0) - print("walk failed; ok\n"); - print("file %T\n", f); - walkfile(&f, "plotnumb"); - walkfile(&f, "resultclose"); - fd = openfile(f, OREAD); - if(fd < 0) - sysfatal("openfile: %r"); - n = preadfile(f, fd, buf, 4, 0ULL); - if(n != 4) - sysfatal("preadfile: %r"); - buf[4] = 0; - print("read: '%s'\n", buf); - closefile(f, fd); - print("file %T\n", f); - putfile(f); - f = rootfile(); - if((fd = createfile(&f, "new", OREAD, 0775|DMDIR)) < 0) - print("create: %r\n"); - else - closefile(f, fd); - print("created: %T\n", f); - putfile(f); - f = rootfile(); - walkfile(&f, "new"); - removefile(f); - print("file is %T\n", f); - putfile(f); - f = rootfile(); - if(removefile(f) < 0) - print("remove root: %r\n"); - putfile(f); - nulldir(&wd); - wd.mode = 0700; - f = rootfile(); - if(walkfile(&f, "hola") < 0) - print("can't walk to hola\n"); - else if(wstatfile(f, &wd) < 0) - print("wstat: %r\n"); - print("file is %T\n", f); - putfile(f); - filesync(); - dumptree(); - if(dosleep){ - print("%s: sleeping forever\n", argv0); - for(;;) - sleep(3600); - } - - threadexits(nil); -} diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/pack.c --- a/sys/src/cmd/ix/pack.c Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,658 +0,0 @@ -#include -#include -#include - -#include "ix.h" - -uchar* -pdata(uchar *p, uchar *s, int ns) -{ - if(s == nil){ - PBIT16(p, 0); - p += BIT16SZ; - return p; - } - - /* - * We are moving the string before the length, - * so you can S2M a struct into an existing message - */ - memmove(p + BIT16SZ, s, ns); - PBIT16(p, ns); - p += ns + BIT16SZ; - return p; -} - -uchar* -pstring(uchar *p, char *s) -{ - uint n; - - if(s == nil){ - PBIT16(p, 0); - p += BIT16SZ; - return p; - } - - n = strlen(s); - /* - * We are moving the string before the length, - * so you can S2M a struct into an existing message - */ - memmove(p + BIT16SZ, s, n); - PBIT16(p, n); - p += n + BIT16SZ; - return p; -} - -uint -stringsz(char *s) -{ - if(s == nil) - return BIT16SZ; - - return BIT16SZ+strlen(s); -} - -/* - * Does NOT include the data bytes added past the packed - * message for IXRread, IXTwrite, IXTwattr, IXRattr - * This is so to save copying. - */ -uint -ixpackedsize(IXcall *f) -{ - uint n; - int i; - - n = BIT8SZ; /* type */ - - switch(f->type){ - case IXTversion: - case IXRversion: - n += BIT32SZ; - n += stringsz(f->version); - break; - - case IXTsession: - n += BIT16SZ; - n += stringsz(f->uname); - n += BIT8SZ; - break; - case IXRsession: - n += BIT16SZ; - n += BIT32SZ; - n += stringsz(f->uname); - break; - - case IXTsid: - n += BIT16SZ; - break; - case IXRsid: - break; - - case IXTendsession: - case IXRendsession: - break; - - case IXTfid: - n += BIT32SZ; - break; - case IXRfid: - break; - - case IXTattach: - n += stringsz(f->aname); - break; - case IXRattach: - n += BIT32SZ; - break; - - case IXRerror: - n += stringsz(f->ename); - break; - - case IXTclone: - n += BIT8SZ; - break; - case IXRclone: - n += BIT32SZ; - break; - - case IXTwalk: - n += BIT16SZ; - for(i=0; inwname; i++) - n += stringsz(f->wname[i]); - break; - case IXRwalk: - break; - - case IXTopen: - n += BIT8SZ; - break; - case IXRopen: - break; - - case IXTcreate: - n += stringsz(f->name); - n += BIT32SZ; - n += BIT8SZ; - break; - case IXRcreate: - break; - - case IXTread: - n += BIT16SZ; - n += BIT64SZ; - n += BIT32SZ; - break; - case IXRread: - /* data follows */ - break; - - case IXTwrite: - n += BIT64SZ; - n += BIT64SZ; - /* data follows */ - break; - case IXRwrite: - n += BIT64SZ; - n += BIT32SZ; - break; - - case IXTclunk: - case IXRclunk: - case IXTclose: - case IXRclose: - case IXTremove: - case IXRremove: - break; - - case IXTattr: - n += stringsz(f->attr); - break; - case IXRattr: - /* data follows */ - break; - - case IXTwattr: - n += stringsz(f->attr); - /* value data follows */ - break; - case IXRwattr: - break; - - case IXTcond: - n += BIT8SZ; - n += stringsz(f->attr); - /* value data follows */ - break; - case IXRcond: - break; - - case IXTmove: - n += BIT32SZ; - n += stringsz(f->newname); - break; - case IXRmove: - break; - - case IXTflush: - case IXRflush: - break; - default: - sysfatal("packedsize: unknown type %d", f->type); - - } - return n; -} - -uint -ixpack(IXcall *f, uchar *ap, uint nap) -{ - uchar *p; - uint size; - int i; - - size = ixpackedsize(f); - if(size == 0) - return 0; - if(size > nap) - return 0; - - p = (uchar*)ap; - - PBIT8(p, f->type); - p += BIT8SZ; - - switch(f->type){ - case IXTversion: - case IXRversion: - PBIT32(p, f->msize); - p += BIT32SZ; - p = pstring(p, f->version); - break; - - case IXTsession: - PBIT16(p, f->ssid); - p += BIT16SZ; - p = pstring(p, f->uname); - PBIT8(p, f->keep); - p += BIT8SZ; - break; - case IXRsession: - PBIT16(p, f->ssid); - p += BIT16SZ; - PBIT32(p, f->afid); - p += BIT32SZ; - p = pstring(p, f->uname); - break; - - case IXTsid: - PBIT16(p, f->ssid); - p += BIT16SZ; - break; - case IXRsid: - break; - - case IXTendsession: - case IXRendsession: - break; - - case IXTfid: - PBIT32(p, f->fid); - p += BIT32SZ; - break; - case IXRfid: - break; - - case IXTattach: - p = pstring(p, f->aname); - break; - case IXRattach: - PBIT32(p, f->fid); - p += BIT32SZ; - break; - - case IXRerror: - p = pstring(p, f->ename); - break; - - case IXTclone: - PBIT8(p, f->cflags); - p += BIT8SZ; - break; - case IXRclone: - PBIT32(p, f->fid); - p += BIT32SZ; - break; - - case IXTwalk: - PBIT16(p, f->nwname); - p += BIT16SZ; - for(i=0; inwname; i++) - p = pstring(p, f->wname[i]); - break; - case IXRwalk: - break; - - case IXTopen: - PBIT8(p, f->mode); - p += BIT8SZ; - break; - case IXRopen: - break; - - case IXTcreate: - p = pstring(p, f->name); - PBIT32(p, f->perm); - p += BIT32SZ; - PBIT8(p, f->mode); - p += BIT8SZ; - break; - case IXRcreate: - break; - - case IXTread: - PBIT16(p, f->nmsg); - p += BIT16SZ; - PBIT64(p, f->offset); - p += BIT64SZ; - PBIT32(p, f->count); - p += BIT32SZ; - break; - case IXRread: - /* data follows */ - break; - - case IXTwrite: - PBIT64(p, f->offset); - p += BIT64SZ; - PBIT64(p, f->endoffset); - p += BIT64SZ; - /* data follows */ - break; - case IXRwrite: - PBIT64(p, f->offset); - p += BIT64SZ; - PBIT32(p, f->count); - p += BIT32SZ; - break; - - case IXTclunk: - case IXRclunk: - case IXTclose: - case IXRclose: - case IXTremove: - case IXRremove: - break; - - case IXTattr: - p = pstring(p, f->attr); - break; - case IXRattr: - /* value data follows */ - break; - - case IXTwattr: - p = pstring(p, f->attr); - /* value data follows */ - break; - case IXRwattr: - break; - - case IXTcond: - PBIT8(p, f->op); - p += BIT8SZ; - p = pstring(p, f->attr); - /* value data follows */ - break; - case IXRcond: - break; - - case IXTmove: - PBIT32(p, f->dirfid); - p += BIT32SZ; - p = pstring(p, f->newname); - break; - case IXRmove: - break; - - case IXTflush: - case IXRflush: - break; - - default: - sysfatal("pack: type %d", f->type); - - } - if(size != p-ap) - return 0; - return size; -} - -uchar* -gstring(uchar *p, uchar *ep, char **s) -{ - uint n; - - if(p+BIT16SZ > ep) - return nil; - n = GBIT16(p); - p += BIT16SZ - 1; - if(p+n+1 > ep) - return nil; - /* move it down, on top of count, to make room for '\0' */ - memmove(p, p + 1, n); - p[n] = '\0'; - *s = (char*)p; - p += n+1; - return p; -} - -uchar* -gdata(uchar *p, uchar *ep, uchar **s, int *ns) -{ - uint n; - - if(p+BIT16SZ > ep) - return nil; - n = GBIT16(p); - *ns = n; - p += BIT16SZ; - if(p+n > ep) - return nil; - *s = p; - p += n; - return p; -} - -uint -ixunpack(uchar *ap, uint nap, IXcall *f) -{ - uchar *p, *ep; - int i; - - p = ap; - ep = p + nap; - - if(p+BIT8SZ > ep){ - werrstr("msg too short"); - return 0; - } - - f->type = GBIT8(p); - p += BIT8SZ; - - switch(f->type){ - case IXTversion: - case IXRversion: - if(p+BIT32SZ > ep) - return 0; - f->msize = GBIT32(p); - p += BIT32SZ; - p = gstring(p, ep, &f->version); - break; - - case IXTsession: - if(p+BIT16SZ > ep) - return 0; - f->ssid = GBIT16(p); - p += BIT16SZ; - p = gstring(p, ep, &f->uname); - if(p == nil) - return 0; - if(p+BIT8SZ > ep) - return 0; - f->keep = GBIT8(p); - p += BIT8SZ; - break; - case IXRsession: - if(p+BIT16SZ+BIT32SZ > ep) - return 0; - f->ssid = GBIT16(p); - p += BIT16SZ; - f->afid = GBIT32(p); - p += BIT32SZ; - p = gstring(p, ep, &f->uname); - break; - - case IXTsid: - if(p+BIT16SZ > ep) - return 0; - f->ssid = GBIT16(p); - p += BIT16SZ; - break; - case IXRsid: - break; - - case IXTendsession: - case IXRendsession: - break; - - case IXTfid: - if(p+BIT32SZ > ep) - return 0; - f->fid = GBIT32(p); - p += BIT32SZ; - break; - case IXRfid: - break; - - case IXTattach: - p = gstring(p, ep, &f->aname); - break; - case IXRattach: - if(p+BIT32SZ > ep) - return 0; - f->fid = GBIT32(p); - p += BIT32SZ; - break; - - case IXRerror: - p = gstring(p, ep, &f->ename); - break; - - case IXTclone: - if(p+BIT8SZ > ep) - return 0; - f->cflags = GBIT8(p); - p += BIT8SZ; - break; - case IXRclone: - if(p+BIT32SZ > ep) - return 0; - f->fid = GBIT32(p); - p += BIT32SZ; - break; - - case IXTwalk: - if(p+BIT16SZ > ep) - return 0; - f->nwname = GBIT16(p); - p += BIT16SZ; - if(f->nwname > Nwalks) - sysfatal("unpack: bug: too many walk elems"); - for(i=0; inwname && p != nil; i++) - p = gstring(p, ep, &f->wname[i]); - break; - case IXRwalk: - break; - - case IXTopen: - if(p+BIT8SZ > ep) - return 0; - f->mode = GBIT8(p); - p += BIT8SZ; - break; - case IXRopen: - break; - - case IXTcreate: - p = gstring(p, ep, &f->name); - if(p == nil) - break; - if(p+BIT32SZ+BIT8SZ > ep) - return 0; - f->perm = GBIT32(p); - p += BIT32SZ; - f->mode = GBIT8(p); - p += BIT8SZ; - break; - case IXRcreate: - break; - - case IXTread: - if(p+BIT16SZ+BIT64SZ+BIT32SZ > ep) - return 0; - f->nmsg = GBIT16(p); - p += BIT16SZ; - f->offset = GBIT64(p); - p += BIT64SZ; - f->count = GBIT32(p); - p += BIT32SZ; - break; - case IXRread: - f->data = p; - break; - - case IXTwrite: - if(p+BIT64SZ > ep) - return 0; - f->offset = GBIT64(p); - p += BIT64SZ; - f->endoffset = GBIT64(p); - p += BIT64SZ; - f->data = p; - break; - case IXRwrite: - if(p+BIT32SZ+BIT64SZ > ep) - return 0; - f->offset = GBIT64(p); - p += BIT64SZ; - f->count = GBIT32(p); - p += BIT32SZ; - break; - - case IXTclunk: - case IXRclunk: - case IXTclose: - case IXRclose: - case IXTremove: - case IXRremove: - break; - - case IXTattr: - p = gstring(p, ep, &f->attr); - break; - case IXRattr: - f->value = p; - break; - - case IXTwattr: - p = gstring(p, ep, &f->attr); - if(p == nil) - return 0; - f->value = p; - break; - case IXRwattr: - break; - - case IXTcond: - if(p+BIT8SZ > ep) - return 0; - f->op = GBIT8(p); - p += BIT8SZ; - p = gstring(p, ep, &f->attr); - if(p == nil) - return 0; - f->value = p; - break; - case IXRcond: - break; - - case IXTmove: - if(p+BIT32SZ > ep) - return 0; - f->dirfid = GBIT32(p); - p += BIT32SZ; - p = gstring(p, ep, &f->newname); - break; - case IXRmove: - break; - - case IXTflush: - case IXRflush: - break; - - default: - werrstr("unpack: unknown type %d", f->type); - return 0; - } - - if(p==nil || p>ep || p == ap){ - werrstr("unpack: p %#p ep %#p", p, ep); - return 0; - } - return p - ap; -} diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/tses.c --- a/sys/src/cmd/ix/tses.c Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,312 +0,0 @@ -/* - * Tcp-like transports, wrapped in a Con structure - * to send and receive messages. - * - * Termination: - * - rproc gets and error or eof: - * 1. rproc sends nil to client (e.g., cmux) and exits - * 2. client is noted and writes nil to wproc - * it may look at s->err for the error condition. - * 3. wproc intrs. rproc (harmless). - * - * - client terminates: - * 1. client writes nil to wproc - * 2. wproc intrs. rproc and terminates - * 3. rproc is noted and sends nil to client - * - * Concurrent termination works ok, because rproc - * only sends nil once to the client. - */ -#include -#include -#include - -#include "conf.h" -#include "msg.h" -#include "mpool.h" -#include "tses.h" -#include "dbg.h" - -static void -abortconn(Con *s) -{ - if(s->cfd < 0) - return; - dsprint("abortconn[%p]: hanging up\n", s); -// write(s->cfd, "hangup", 6); - close(s->cfd); - close(s->dfd); - s->cfd = s->dfd = -1; -} - -static void -freeses(Con *s) -{ - dsprint("free session %p\n", s); - free(s->addr); - free(s->err); - if(s->rc != nil) - chanfree(s->rc); - if(s->wc != nil) - chanfree(s->wc); - if(s->ec != nil) - chanfree(s->ec); - freepool(s->pool); - freepool(s->spool); - memset(s, 6, sizeof *s); /* poison */ - free(s); -} - -static void -putses(Con *s) -{ - if(decref(s) == 0) - freeses(s); -} - -static void -syserr(Con *s) -{ - /* - * BUG: could leak if concurrent errors. - */ - if(s->err == nil) - s->err = smprint("%r"); -} - -static void -rproc(void *a) -{ - Con *s; - Msg *m, *sm; - long nr; - - s = a; - threadsetname("rproc[%p]", a); - dpprint("rproc[%p]: started\n", a); - s->rtid = threadid(); - m = newmsg(s->pool); - sm = newmsg(s->spool); - for(;;){ - if(m == nil) - sysfatal("rproc: newmsg"); - nr = readmsg(s->dfd, m); - if(nr < 0){ - syserr(s); - dmprint("rproc[%p]: readmsg: %r\n", a); - break; - } - if(nr == 0){ - dmprint("rproc[%p]: eof\n", a); - break; - } - if(IOLEN(m->io) <= IOCAP(sm->io)){ - memmove(sm->io->wp, m->io->rp, IOLEN(m->io)); - sm->io->wp += IOLEN(m->io); - m->hdr = nil; - ioreset(m->io); - sendp(s->rc, sm); - sm = newmsg(s->spool); - }else{ - sendp(s->rc, m); - m = newmsg(s->pool); - } - } - sendp(s->rc, nil); - sendp(s->ec, s->err); - s->err = nil; - freemsg(m); - freemsg(sm); - putses(s); - dpprint("rproc[%p]: exiting\n", a); -} - -static void -wproc(void *a) -{ - Con *s; - Msg *m; - - s = a; - threadsetname("wproc[%p]", a); - dpprint("wproc[%p]: started\n", a); - for(;;){ - m = recvp(s->wc); - if(m == nil){ - dmprint("wproc[%p]: got nil msg\n", a); - abortconn(s); - break; - } - if(writemsg(s->dfd, m) < 0){ - syserr(s); - dmprint("wproc[%p]: snd len %uld: %r\n", a, msglen(m)); - freemsg(m); - abortconn(s); - break; - } - dmprint("wproc[%p]: sent %uld bytes\n", a, msglen(m)); - freemsg(m); - } - threadint(s->rtid); - while((m = nbrecvp(s->wc)) != nil) - freemsg(m); - putses(s); - dpprint("wproc[%p]: exiting\n", a); -} - -void -startses(Con *s, Mpool *mp, Mpool *smp) -{ - s->pool = mp; - s->spool = smp; - s->ec = echancreate(sizeof(char*), 0); - s->rc = echancreate(sizeof(Msg*), 0); - incref(s); - proccreate(rproc, s, Stack); - s->wc = echancreate(sizeof(Msg*), 0); - incref(s); - proccreate(wproc, s, Stack); -} - -static void -ssrvproc(void *a) -{ - enum{New, End}; - - Ssrv *ss; - Con *sl, **nl, *s; - Alt alts[] = { - [New] {nil, &s, CHANRCV}, - [End] {nil, &s, CHANRCV}, - {nil, nil, CHANEND}, - }; - - ss = a; - alts[New].c = ss->listenc; - alts[End].c = ss->endc; - sl = nil; - threadsetname("ssrvproc %p", a); - dpprint("ssrvproc[%p]: started\n", a); - for(;;){ - switch(alt(alts)){ - case New: - dsprint("session[%p]: new %s\n", s, s->addr); - s->next = sl; - sl = s; - incref(s); - sendp(ss->newc, s); - break; - - case End: - dsprint("session[%p]: done %s\n", s, s->addr); - for(nl = &sl; *nl != nil; nl = &(*nl)->next) - if(s == *nl) - break; - if(*nl == nil) - sysfatal("ssrvproc[%p]: no session", a); - *nl = s->next; - putses(s); - break; - - default: - sysfatal("alt"); - } - } -} - -static void -listenproc(void *a) -{ - Ssrv *ss; - Con *s; - char ldir[40]; - - ss = a; - threadsetname("listenproc %p", a); - dpprint("listenproc[%p]: started\n", a); - for(;;){ - s = mallocz(sizeof *s, 1); - s->addr = strdup(ss->addr); /* not needed in srv */ - s->cfd = s->dfd = -1; - s->ref = 1; - s->cfd = listen(ss->adir, ldir); - if(s->cfd < 0){ - dprint("listen: %r"); - goto Fail; - } - s->dfd = accept(s->cfd, ldir); - if(s->dfd < 0){ - dprint("accept: %r"); - goto Fail; - } - sendp(ss->listenc, s); - continue; - Fail: - if(s->cfd >= 0) - close(s->cfd); - if(s->dfd >= 0) - close(s->dfd); - s->cfd = s->dfd = -1; - freeses(s); - fprint(2, "%s: listenproc: failed: %r\n", argv0); - sleep(1000); /* avoid retrying too fast */ - } -} - -Ssrv* -newsrv(char *addr) -{ - Ssrv *ss; - - ss = mallocz(sizeof *ss, 1); - dprint("announce %s\n", addr); - ss->afd = announce(addr, ss->adir); - if(ss->afd < 0){ - free(ss); - return nil; - } - ss->addr = strdup(addr); - ss->listenc = echancreate(sizeof(Con*), 0); - ss->newc = echancreate(sizeof(Con*), 0); - ss->endc = echancreate(sizeof(Con*), 0); - proccreate(listenproc, ss, Stack); - threadcreate(ssrvproc, ss, Stack); - return ss; -} - -Con* -dialsrv(char *addr) -{ - Con *s; - - s = mallocz(sizeof *s, 1); - dprint("dial %s\n", addr); - s->dfd = dial(addr, nil, nil, &s->cfd); - if(s->dfd < 0){ - free(s); - return nil; - } - s->ref = 1; - s->addr = strdup(addr); - dsprint("session[%p]: new %s\n", s, s->addr); - return s; -} - -int -closeses(Con *s) -{ - Msg *m; - char *e; - - sendp(s->wc, nil); - while((m = recvp(s->rc)) != nil) - freemsg(m); - e = recvp(s->ec); - if(e != nil){ - werrstr(e); - free(e); - return -1; - } - return 0; -} - diff -r 104e7add5754 -r 0a28e3163537 sys/src/cmd/ix/tses.h --- a/sys/src/cmd/ix/tses.h Wed Feb 22 16:04:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -typedef struct Con Con; -typedef struct Ssrv Ssrv; - -struct Con -{ - Channel*rc; /* read channel (of Msg*) */ - Channel*wc; /* write channel (of Msg*) */ - Channel*ec; /* error channel (of char*) */ - - - /* implementation */ - Mpool*pool; /* message pool */ - Mpool*spool; /* small message pool */ - char* err; - Ref; /* used by reader, writer, client */ - Con *next; /* in list of sessions */ - char* addr; /* debug */ - int cfd; /* control fd */ - int dfd; /* data fd */ - int rtid; /* reader thread id */ -}; - -struct Ssrv -{ - Channel*newc; /* of Con* */ - - /* implementation*/ - char* addr; - char adir[40]; - int afd; - int lfd; - Channel*endc; /* of Con* */ - Channel*listenc; /* of ses* */ -}; - -/* |c/f2p tses.c */ -extern int closeses(Con *s); -extern Con* dialsrv(char *addr); -extern Ssrv* newsrv(char *addr); -extern void startses(Con *s, Mpool *p, Mpool *sp);