commit 46f79934b79ef526ed42bbe5a565e6b5d884d24a from: rsc date: Tue Jan 04 21:22:40 2005 UTC lib9pclient is the new libfs commit - 5ba841dffa1f6cda712ebcff27c55c9d0a672c67 commit + 46f79934b79ef526ed42bbe5a565e6b5d884d24a blob - /dev/null blob + de348d126b2bed47cefa2f493e03f8f1e23c5b19 (mode 644) --- /dev/null +++ src/lib9pclient/COPYRIGHT @@ -0,0 +1,27 @@ + +This software was developed as part of a project at MIT: + /sys/src/libfs/* except dirread.c + /sys/include/fs.h + +Copyright (c) 2003 Russ Cox, + Massachusetts Institute of Technology + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + blob - /dev/null blob + 2c740e12972c2a98e64adddf74739ae94ea06b7f (mode 644) --- /dev/null +++ src/lib9pclient/auth.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ +/* See COPYRIGHT */ + +#include +#include +#include +#include <9pclient.h> +#include "fsimpl.h" + +CFid* +fsauth(CFsys *fsys, char *uname, char *aname) +{ + Fcall tx, rx; + void *freep; + CFid *afid; + + if((fid = _fsgetfid(fsys)) == nil) + return nil; + + tx.type = Tauth; + tx.afid = afid->fid; + tx.uname = uname; + tx.aname = aname; + + if(_fsrpc(fsys, &tx, &rx, &freep) < 0){ + _fsputfid(afid); + return nil; + } + if(rx.type == Rerror){ + werrstr("%s", rx.ename); + free(freep); + _fsputfid(afid); + return nil; + } + afid->qid = rx.aqid; + free(freep); + return afid; +} blob - /dev/null blob + 98c6cfb2a4244dc9658606ed5e9616f1ecd94de1 (mode 644) --- /dev/null +++ src/lib9pclient/close.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ +/* See COPYRIGHT */ + +#include +#include +#include +#include <9pclient.h> +#include "fsimpl.h" + +static void +fidclunk(CFid *fid) +{ + Fcall tx, rx; + + tx.type = Tclunk; + tx.fid = fid->fid; + _fsrpc(fid->fs, &tx, &rx, 0); + _fsputfid(fid); +} + +void +fsclose(CFid *fid) +{ + if(fid == nil) + return; + + /* maybe someday there will be a ref count */ + fidclunk(fid); +} blob - /dev/null blob + cbb4a3acc340864b134984c361d31090ad6d7667 (mode 644) --- /dev/null +++ src/lib9pclient/create.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include <9pclient.h> +#include "fsimpl.h" + +CFid* +fscreate(CFsys *fs, char *name, int mode, ulong perm) +{ + CFid *fid; + Fcall tx, rx; + + if((fid = _fswalk(fs->root, name)) == nil) + return nil; + tx.type = Tcreate; + tx.fid = fid->fid; + tx.mode = mode; + tx.perm = perm; + if(_fsrpc(fs, &tx, &rx, 0) < 0){ + fsclose(fid); + return nil; + } + fid->mode = mode; + return fid; +} blob - /dev/null blob + 540cfc6b5ef6659d4286cb4734f0f7eea4688795 (mode 644) --- /dev/null +++ src/lib9pclient/dirread.c @@ -0,0 +1,99 @@ +/* Mostly copied from Plan 9's libc. */ + +#include +#include +#include +#include <9pclient.h> + +static long +dirpackage(uchar *buf, long ts, Dir **d) +{ + char *s; + long ss, i, n, nn, m; + + *d = nil; + if(ts <= 0) + return 0; + + /* + * first find number of all stats, check they look like stats, & size all associated strings + */ + ss = 0; + n = 0; + for(i = 0; i < ts; i += m){ + m = BIT16SZ + GBIT16(&buf[i]); + if(statcheck(&buf[i], m) < 0) + break; + ss += m; + n++; + } + + if(i != ts) + return -1; + + *d = malloc(n * sizeof(Dir) + ss); + if(*d == nil) + return -1; + + /* + * then convert all buffers + */ + s = (char*)*d + n * sizeof(Dir); + nn = 0; + for(i = 0; i < ts; i += m){ + m = BIT16SZ + GBIT16((uchar*)&buf[i]); + if(nn >= n || convM2D(&buf[i], m, *d + nn, s) != m){ + free(*d); + *d = nil; + return -1; + } + nn++; + s += m; + } + + return nn; +} + +long +fsdirread(CFid *fid, Dir **d) +{ + uchar *buf; + long ts; + + buf = malloc(DIRMAX); + if(buf == nil) + return -1; + ts = fsread(fid, buf, DIRMAX); + if(ts >= 0) + ts = dirpackage(buf, ts, d); + free(buf); + return ts; +} + +long +fsdirreadall(CFid *fid, Dir **d) +{ + uchar *buf, *nbuf; + long n, ts; + + buf = nil; + ts = 0; + for(;;){ + nbuf = realloc(buf, ts+DIRMAX); + if(nbuf == nil){ + free(buf); + return -1; + } + buf = nbuf; + n = fsread(fid, buf+ts, DIRMAX); + if(n <= 0) + break; + ts += n; + } + if(ts >= 0) + ts = dirpackage(buf, ts, d); + free(buf); + if(ts == 0 && n < 0) + return -1; + return ts; +} blob - /dev/null blob + d72aa4c772e6081d9fa51945ccb7e26ad0cb43ae (mode 644) --- /dev/null +++ src/lib9pclient/fs.c @@ -0,0 +1,333 @@ +/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ +/* See COPYRIGHT */ + +#include +#include +#include +#include <9pclient.h> +#include +#include "fsimpl.h" + +static int _fssend(Mux*, void*); +static void *_fsrecv(Mux*); +static int _fsgettag(Mux*, void*); +static int _fssettag(Mux*, void*, uint); + +enum +{ + CFidchunk = 32 +}; + +CFsys* +fsinit(int fd) +{ + CFsys *fs; + + fmtinstall('F', fcallfmt); + fmtinstall('D', dirfmt); + fmtinstall('M', dirmodefmt); + + fs = mallocz(sizeof(CFsys), 1); + if(fs == nil) + return nil; + fs->fd = fd; + fs->ref = 1; + fs->mux.aux = fs; + fs->mux.mintag = 0; + fs->mux.maxtag = 256; + fs->mux.send = _fssend; + fs->mux.recv = _fsrecv; + fs->mux.gettag = _fsgettag; + fs->mux.settag = _fssettag; + fs->iorecv = ioproc(); + fs->iosend = ioproc(); + muxinit(&fs->mux); + return fs; +} + +CFid* +fsroot(CFsys *fs) +{ + /* N.B. no incref */ + return fs->root; +} + +CFsys* +fsmount(int fd, char *aname) +{ + int n; + char *user; + CFsys *fs; + CFid *fid; + + fs = fsinit(fd); + if(fs == nil) + return nil; + strcpy(fs->version, "9P2000"); + if((n = fsversion(fs, 8192, fs->version, sizeof fs->version)) < 0){ + Error: + fs->fd = -1; + fsunmount(fs); + return nil; + } + fs->msize = n; + + user = getuser(); + if((fid = fsattach(fs, nil, getuser(), aname)) == nil) + goto Error; + fssetroot(fs, fid); + return fs; +} + +void +fsunmount(CFsys *fs) +{ + fsclose(fs->root); + fs->root = nil; + _fsdecref(fs); +} + +void +_fsdecref(CFsys *fs) +{ + CFid *f, **l, *next; + + qlock(&fs->lk); + --fs->ref; + //fprint(2, "fsdecref %p to %d\n", fs, fs->ref); + if(fs->ref == 0){ + close(fs->fd); + /* trim the list down to just the first in each chunk */ + for(l=&fs->freefid; *l; ){ + if((*l)->fid%CFidchunk == 0) + l = &(*l)->next; + else + *l = (*l)->next; + } + /* now free the list */ + for(f=fs->freefid; f; f=next){ + next = f->next; + free(f); + } + closeioproc(fs->iorecv); + closeioproc(fs->iosend); + free(fs); + return; + } + qunlock(&fs->lk); +} + +int +fsversion(CFsys *fs, int msize, char *version, int nversion) +{ + void *freep; + int r, oldmintag, oldmaxtag; + Fcall tx, rx; + + tx.tag = 0; + tx.type = Tversion; + tx.version = version; + tx.msize = msize; + + /* + * bit of a clumsy hack -- force libmux to use NOTAG as tag. + * version can only be sent when there are no other messages + * outstanding on the wire, so this is more reasonable than it looks. + */ + oldmintag = fs->mux.mintag; + oldmaxtag = fs->mux.maxtag; + fs->mux.mintag = NOTAG; + fs->mux.maxtag = NOTAG+1; + r = _fsrpc(fs, &tx, &rx, &freep); + fs->mux.mintag = oldmintag; + fs->mux.maxtag = oldmaxtag; + if(r < 0) + return -1; + + strecpy(version, version+nversion, rx.version); + free(freep); + return rx.msize; +} + +CFid* +fsattach(CFsys *fs, CFid *afid, char *user, char *aname) +{ + Fcall tx, rx; + CFid *fid; + + if(aname == nil) + aname = ""; + + if((fid = _fsgetfid(fs)) == nil) + return nil; + + tx.tag = 0; + tx.type = Tattach; + tx.afid = afid ? afid->fid : NOFID; + tx.fid = fid->fid; + tx.uname = user; + tx.aname = aname; + + if(_fsrpc(fs, &tx, &rx, 0) < 0){ + _fsputfid(fid); + return nil; + } + fid->qid = rx.qid; + return fid; +} + +void +fssetroot(CFsys *fs, CFid *fid) +{ + if(fs->root) + _fsputfid(fs->root); + fs->root = fid; +} + +int +_fsrpc(CFsys *fs, Fcall *tx, Fcall *rx, void **freep) +{ + int n, nn; + void *tpkt, *rpkt; + + n = sizeS2M(tx); + tpkt = malloc(n); + if(freep) + *freep = nil; + if(tpkt == nil) + return -1; + //fprint(2, "<- %F\n", tx); + nn = convS2M(tx, tpkt, n); + if(nn != n){ + free(tpkt); + werrstr("libfs: sizeS2M convS2M mismatch"); + fprint(2, "%r\n"); + return -1; + } + rpkt = muxrpc(&fs->mux, tpkt); + free(tpkt); + if(rpkt == nil) + return -1; + n = GBIT32((uchar*)rpkt); + nn = convM2S(rpkt, n, rx); + if(nn != n){ + free(rpkt); + werrstr("libfs: convM2S packet size mismatch %d %d", n, nn); + fprint(2, "%r\n"); + return -1; + } + //fprint(2, "-> %F\n", rx); + if(rx->type == Rerror){ + werrstr("%s", rx->ename); + free(rpkt); + return -1; + } + if(rx->type != tx->type+1){ + werrstr("packet type mismatch -- tx %d rx %d", + tx->type, rx->type); + free(rpkt); + return -1; + } + if(freep) + *freep = rpkt; + else + free(rpkt); + return 0; +} + +CFid* +_fsgetfid(CFsys *fs) +{ + int i; + CFid *f; + + qlock(&fs->lk); + if(fs->freefid == nil){ + f = mallocz(sizeof(CFid)*CFidchunk, 1); + if(f == nil){ + qunlock(&fs->lk); + return nil; + } + for(i=0; inextfid++; + f[i].next = &f[i+1]; + f[i].fs = fs; + } + f[i-1].next = nil; + fs->freefid = f; + } + f = fs->freefid; + fs->freefid = f->next; + fs->ref++; + qunlock(&fs->lk); + return f; +} + +void +_fsputfid(CFid *f) +{ + CFsys *fs; + + fs = f->fs; + qlock(&fs->lk); + f->next = fs->freefid; + fs->freefid = f; + qunlock(&fs->lk); + _fsdecref(fs); +} + +static int +_fsgettag(Mux *mux, void *pkt) +{ + return GBIT16((uchar*)pkt+5); +} + +static int +_fssettag(Mux *mux, void *pkt, uint tag) +{ + PBIT16((uchar*)pkt+5, tag); + return 0; +} + +static int +_fssend(Mux *mux, void *pkt) +{ + CFsys *fs; + + fs = mux->aux; + return iowrite(fs->iosend, fs->fd, pkt, GBIT32((uchar*)pkt)); +} + +static void* +_fsrecv(Mux *mux) +{ + uchar *pkt; + uchar buf[4]; + int n, nfd; + CFsys *fs; + + fs = mux->aux; + n = ioreadn(fs->iorecv, fs->fd, buf, 4); + if(n != 4) + return nil; + n = GBIT32(buf); + pkt = malloc(n+4); + if(pkt == nil){ + fprint(2, "libfs out of memory reading 9p packet; here comes trouble\n"); + return nil; + } + PBIT32(pkt, n); + if(ioreadn(fs->iorecv, fs->fd, pkt+4, n-4) != n-4){ + free(pkt); + return nil; + } + if(pkt[4] == Ropenfd){ + if((nfd=iorecvfd(fs->iorecv, fs->fd)) < 0){ + fprint(2, "recv fd error: %r\n"); + free(pkt); + return nil; + } + PBIT32(pkt+n-4, nfd); + } + return pkt; +} blob - /dev/null blob + 9c5c555355fd58ca2e3b7d397de11475ee8981fd (mode 644) --- /dev/null +++ src/lib9pclient/fsimpl.h @@ -0,0 +1,47 @@ +/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ +/* See COPYRIGHT */ + +#include + +typedef struct Queue Queue; +Queue *_fsqalloc(void); +int _fsqsend(Queue*, void*); +void *_fsqrecv(Queue*); +void _fsqhangup(Queue*); +void *_fsnbqrecv(Queue*); + +#include +struct CFsys +{ + char version[20]; + int msize; + QLock lk; + int fd; + int ref; + Mux mux; + CFid *root; + Queue *txq; + Queue *rxq; + CFid *freefid; + int nextfid; + Ioproc *iorecv; + Ioproc *iosend; +}; + +struct CFid +{ + int fid; + int mode; + CFid *next; + QLock lk; + CFsys *fs; + Qid qid; + vlong offset; +}; + +void _fsdecref(CFsys*); +void _fsputfid(CFid*); +CFid *_fsgetfid(CFsys*); + +int _fsrpc(CFsys*, Fcall*, Fcall*, void**); +CFid *_fswalk(CFid*, char*); blob - /dev/null blob + c6bbc7dc8cd96755159ac5f4c91686fa135ff2bb (mode 644) --- /dev/null +++ src/lib9pclient/mkfile @@ -0,0 +1,23 @@ +<$PLAN9/src/mkhdr + +LIB=lib9pclient.a + +OFILES=\ + close.$O\ + create.$O\ + dirread.$O\ + fs.$O\ + ns.$O\ + open.$O\ + openfd.$O\ + read.$O\ + stat.$O\ + walk.$O\ + write.$O\ + wstat.$O\ + +HFILES=\ + $PLAN9/include/9pclient.h\ + $PLAN9/include/mux.h\ + +<$PLAN9/src/mksyslib blob - /dev/null blob + 9c86547e5c7f5c052dd1118e5bc6966a640103ca (mode 644) --- /dev/null +++ src/lib9pclient/ns.c @@ -0,0 +1,40 @@ +#include +#include +#include +#include <9pclient.h> +#include + +CFsys* +nsmount(char *name, char *aname) +{ + char *addr, *ns; + int fd; + CFsys *fs; + + ns = getns(); + if(ns == nil) + return nil; + + addr = smprint("unix!%s/%s", ns, name); + free(ns); + if(addr == nil) + return nil; + + fd = dial(addr, 0, 0, 0); + if(fd < 0){ + werrstr("dial %s: %r", addr); + free(addr); + return nil; + } + free(addr); + + fcntl(fd, F_SETFL, FD_CLOEXEC); + + fs = fsmount(fd, aname); + if(fs == nil){ + close(fd); + return nil; + } + + return fs; +} blob - /dev/null blob + e9fb981bafaed18a26c022f57d08c8760d3e0241 (mode 644) --- /dev/null +++ src/lib9pclient/open.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <9pclient.h> +#include "fsimpl.h" + +CFid* +fsopen(CFsys *fs, char *name, int mode) +{ + CFid *fid; + Fcall tx, rx; + + if((fid = _fswalk(fs->root, name)) == nil) + return nil; + tx.type = Topen; + tx.fid = fid->fid; + tx.mode = mode; + if(_fsrpc(fs, &tx, &rx, 0) < 0){ + fsclose(fid); + return nil; + } + fid->mode = mode; + return fid; +} blob - /dev/null blob + ef26e5c457960bedda083a475c16ba390d885cf4 (mode 644) --- /dev/null +++ src/lib9pclient/openfd.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include <9pclient.h> +#include "fsimpl.h" + +int +fsopenfd(CFsys *fs, char *name, int mode) +{ + CFid *fid; + Fcall tx, rx; + + if((fid = _fswalk(fs->root, name)) == nil) + return -1; + tx.type = Topenfd; + tx.fid = fid->fid; + tx.mode = mode&~OCEXEC; + if(_fsrpc(fs, &tx, &rx, 0) < 0){ + fsclose(fid); + return -1; + } + _fsputfid(fid); + if(mode&OCEXEC && rx.unixfd>=0) + fcntl(rx.unixfd, F_SETFL, FD_CLOEXEC); + return rx.unixfd; +} blob - /dev/null blob + 605372884cd371b0f3f41476c76e5a98f1e49aa8 (mode 644) --- /dev/null +++ src/lib9pclient/read.c @@ -0,0 +1,72 @@ +/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ +/* See COPYRIGHT */ + +#include +#include +#include +#include <9pclient.h> +#include "fsimpl.h" + +long +fspread(CFid *fid, void *buf, long n, vlong offset) +{ + Fcall tx, rx; + void *freep; + uint msize; + + msize = fid->fs->msize - IOHDRSZ; + if(n > msize) + n = msize; + tx.type = Tread; + tx.fid = fid->fid; + if(offset == -1){ + qlock(&fid->lk); + tx.offset = fid->offset; + qunlock(&fid->lk); + }else + tx.offset = offset; + tx.count = n; + + if(_fsrpc(fid->fs, &tx, &rx, &freep) < 0) + return -1; + if(rx.type == Rerror){ + werrstr("%s", rx.ename); + free(freep); + return -1; + } + if(rx.count){ + memmove(buf, rx.data, rx.count); + if(offset == -1){ + qlock(&fid->lk); + fid->offset += rx.count; + qunlock(&fid->lk); + } + } + free(freep); + + return rx.count; +} + +long +fsread(CFid *fid, void *buf, long n) +{ + return fspread(fid, buf, n, -1); +} + +long +fsreadn(CFid *fid, void *buf, long n) +{ + long tot, nn; + + for(tot=0; tot +#include +#include +#include <9pclient.h> +#include "fsimpl.h" + +Dir* +fsdirstat(CFsys *fs, char *name) +{ + Dir *d; + CFid *fid; + + if((fid = _fswalk(fs->root, name)) == nil) + return nil; + + d = fsdirfstat(fid); + fsclose(fid); + return d; +} + +Dir* +fsdirfstat(CFid *fid) +{ + Dir *d; + CFsys *fs; + Fcall tx, rx; + void *freep; + int n; + + fs = fid->fs; + tx.type = Tstat; + tx.fid = fid->fid; + + if(_fsrpc(fs, &tx, &rx, &freep) < 0) + return nil; + + d = malloc(sizeof(Dir)+rx.nstat); + if(d == nil){ + free(freep); + return nil; + } + n = convM2D(rx.stat, rx.nstat, d, (char*)&d[1]); + free(freep); + if(n != rx.nstat){ + free(d); + werrstr("rx.nstat and convM2D disagree about dir length"); + return nil; + } + return d; +} + blob - /dev/null blob + 32a2fd7b52cb45650c643818d286eff483b55c29 (mode 644) --- /dev/null +++ src/lib9pclient/walk.c @@ -0,0 +1,73 @@ +/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ +/* See COPYRIGHT */ + +#include +#include +#include +#include <9pclient.h> +#include "fsimpl.h" + +CFid* +_fswalk(CFid *fid, char *oname) +{ + char *freep, *name; + int i, nwalk; + char *p; + CFid *wfid; + Fcall tx, rx; + + freep = nil; + name = oname; + if(name){ + freep = malloc(strlen(name)+1); + if(freep == nil) + return nil; + strcpy(freep, name); + name = freep; + } + + if((wfid = _fsgetfid(fid->fs)) == nil){ + free(freep); + return nil; + } + + nwalk = 0; + do{ + /* collect names */ + for(i=0; name && *name && i < MAXWELEM; ){ + p = name; + name = strchr(name, '/'); + if(name) + *name++ = 0; + if(*p == 0 || (*p == '.' && *(p+1) == 0)) + continue; + tx.wname[i++] = p; + } + + /* do a walk */ + tx.type = Twalk; + tx.fid = nwalk ? wfid->fid : fid->fid; + tx.newfid = wfid->fid; + tx.nwname = i; + if(_fsrpc(fid->fs, &tx, &rx, 0) < 0){ + Error: + free(freep); + if(nwalk) + fsclose(wfid); + else + _fsputfid(wfid); + return nil; + } + if(rx.nwqid != tx.nwname){ + /* XXX lame error */ + werrstr("file '%s' not found", oname); + goto Error; + } + if(rx.nwqid == 0) + wfid->qid = fid->qid; + else + wfid->qid = rx.wqid[rx.nwqid-1]; + nwalk++; + }while(name && *name); + return wfid; +} blob - /dev/null blob + f4eab964de3216d358f717961837d4aa20999ab0 (mode 644) --- /dev/null +++ src/lib9pclient/write.c @@ -0,0 +1,74 @@ +/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ +/* See COPYRIGHT */ + +#include +#include +#include +#include <9pclient.h> +#include "fsimpl.h" + +static long +_fspwrite(CFid *fid, void *buf, long n, vlong offset) +{ + Fcall tx, rx; + void *freep; + + tx.type = Twrite; + tx.fid = fid->fid; + if(offset == -1){ + qlock(&fid->lk); + tx.offset = fid->offset; + qunlock(&fid->lk); + }else + tx.offset = offset; + tx.count = n; + tx.data = buf; + + if(_fsrpc(fid->fs, &tx, &rx, &freep) < 0) + return -1; + if(rx.type == Rerror){ + werrstr("%s", rx.ename); + free(freep); + return -1; + } + if(offset == -1 && rx.count){ + qlock(&fid->lk); + fid->offset += rx.count; + qunlock(&fid->lk); + } + free(freep); + return rx.count; +} + +long +fspwrite(CFid *fid, void *buf, long n, vlong offset) +{ + long tot, want, got, first; + uint msize; + + msize = fid->fs->msize - IOHDRSZ; + tot = 0; + first = 1; + while(tot < n || first){ + want = n - tot; + if(want > msize) + want = msize; + got = _fspwrite(fid, buf, want, offset); + first = 0; + if(got < 0){ + if(tot == 0) + return got; + break; + } + tot += got; + if(offset != -1) + offset += got; + } + return tot; +} + +long +fswrite(CFid *fid, void *buf, long n) +{ + return fspwrite(fid, buf, n, -1); +} blob - /dev/null blob + 27a28740210e45ed6fb5d63a070d96f0f2e47c4c (mode 644) --- /dev/null +++ src/lib9pclient/wstat.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ +/* See COPYRIGHT */ + +#include +#include +#include +#include <9pclient.h> +#include "fsimpl.h" + +int +fsdirwstat(CFsys *fs, char *name, Dir *d) +{ + int n; + CFid *fid; + + if((fid = _fswalk(fs->root, name)) == nil) + return -1; + + n = fsdirfwstat(fid, d); + fsclose(fid); + return n; +} + +int +fsdirfwstat(CFid *fid, Dir *d) +{ + uchar *a; + int n, nn; + Fcall tx, rx; + + n = sizeD2M(d); + a = malloc(n); + if(a == nil) + return -1; + nn = convD2M(d, a, n); + if(n != nn){ + werrstr("convD2M and sizeD2M disagree"); + free(a); + return -1; + } + + tx.type = Twstat; + tx.fid = fid->fid; + tx.stat = a; + tx.nstat = n; + n = _fsrpc(fid->fs, &tx, &rx, 0); + free(a); + return n; +}