diff options
author | rsc <devnull@localhost> | 2003-12-06 18:08:52 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2003-12-06 18:08:52 +0000 |
commit | d3df308747ee4d1fcc063a348dcf1146b390bda7 (patch) | |
tree | a204b027256ec29b110caaa86100cbd701808b5b /src/libfs | |
parent | e97ceade5e1bba5787e39429384336fa37797906 (diff) | |
download | plan9port-d3df308747ee4d1fcc063a348dcf1146b390bda7.tar.gz plan9port-d3df308747ee4d1fcc063a348dcf1146b390bda7.tar.bz2 plan9port-d3df308747ee4d1fcc063a348dcf1146b390bda7.zip |
File system stuff.
Diffstat (limited to 'src/libfs')
-rw-r--r-- | src/libfs/COPYRIGHT | 27 | ||||
-rw-r--r-- | src/libfs/close.c | 26 | ||||
-rw-r--r-- | src/libfs/create.c | 25 | ||||
-rw-r--r-- | src/libfs/dirread.c | 100 | ||||
-rw-r--r-- | src/libfs/fs.c | 276 | ||||
-rw-r--r-- | src/libfs/fsimpl.h | 41 | ||||
-rw-r--r-- | src/libfs/mkfile | 22 | ||||
-rw-r--r-- | src/libfs/open.c | 24 | ||||
-rw-r--r-- | src/libfs/read.c | 48 | ||||
-rw-r--r-- | src/libfs/stat.c | 54 | ||||
-rw-r--r-- | src/libfs/walk.c | 73 | ||||
-rw-r--r-- | src/libfs/write.c | 46 | ||||
-rw-r--r-- | src/libfs/wstat.c | 49 |
13 files changed, 811 insertions, 0 deletions
diff --git a/src/libfs/COPYRIGHT b/src/libfs/COPYRIGHT new file mode 100644 index 00000000..de348d12 --- /dev/null +++ b/src/libfs/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. + diff --git a/src/libfs/close.c b/src/libfs/close.c new file mode 100644 index 00000000..23388ae3 --- /dev/null +++ b/src/libfs/close.c @@ -0,0 +1,26 @@ +/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ +/* See COPYRIGHT */ + +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <fs.h> +#include "fsimpl.h" + +static void +fidclunk(Fid *fid) +{ + Fcall tx, rx; + + tx.type = Tclunk; + tx.fid = fid->fid; + fsrpc(fid->fs, &tx, &rx, 0); + _fsputfid(fid); +} + +void +fsclose(Fid *fid) +{ + /* maybe someday there will be a ref count */ + fidclunk(fid); +} diff --git a/src/libfs/create.c b/src/libfs/create.c new file mode 100644 index 00000000..ef52a2a8 --- /dev/null +++ b/src/libfs/create.c @@ -0,0 +1,25 @@ +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <fs.h> +#include "fsimpl.h" + +Fid* +fscreate(Fsys *fs, char *name, int mode, ulong perm) +{ + Fid *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; +} diff --git a/src/libfs/dirread.c b/src/libfs/dirread.c new file mode 100644 index 00000000..0ca40645 --- /dev/null +++ b/src/libfs/dirread.c @@ -0,0 +1,100 @@ +/* Mostly copied from Plan 9's libc. */ + +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <fs.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(Fid *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(Fid *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; +} diff --git a/src/libfs/fs.c b/src/libfs/fs.c new file mode 100644 index 00000000..985071c1 --- /dev/null +++ b/src/libfs/fs.c @@ -0,0 +1,276 @@ +/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ +/* See COPYRIGHT */ + +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <fs.h> +#include "fsimpl.h" + +static int _fssend(Mux*, void*); +static void *_fsrecv(Mux*); +static int _fsgettag(Mux*, void*); +static int _fssettag(Mux*, void*, uint); + +enum +{ + Fidchunk = 32 +}; + +Fsys* +fsinit(int fd) +{ + Fsys *fs; + + fs = mallocz(sizeof(Fsys), 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; + muxinit(&fs->mux); + return fs; +} + +Fid* +fsroot(Fsys *fs) +{ + /* N.B. no incref */ + return fs->root; +} + +Fsys* +fsmount(int fd) +{ + int n; + char *user; + Fsys *fs; + + fs = fsinit(fd); + if(fs == nil) + return nil; + strcpy(fs->version, "9P2000"); + if((n = fsversion(fs, 8192, fs->version, sizeof fs->version)) < 0){ + Error: + fsunmount(fs); + return nil; + } + fs->msize = n; + + user = getuser(); + if((fs->root = fsattach(fs, nil, getuser(), "")) == nil) + goto Error; + return fs; +} + +void +fsunmount(Fsys *fs) +{ + _fsdecref(fs); +} + +void +_fsdecref(Fsys *fs) +{ + Fid *f, *next; + + qlock(&fs->lk); + if(--fs->ref == 0){ + close(fs->fd); + for(f=fs->freefid; f; f=next){ + next = f->next; + if(f->fid%Fidchunk == 0) + free(f); + } + free(fs); + } + qunlock(&fs->lk); +} + +int +fsversion(Fsys *fs, int msize, char *version, int nversion) +{ + void *freep; + Fcall tx, rx; + + tx.type = Tversion; + tx.version = version; + tx.msize = msize; + + if(fsrpc(fs, &tx, &rx, &freep) < 0) + return -1; + strecpy(version, version+nversion, rx.version); + free(freep); + return rx.msize; +} + +Fid* +fsattach(Fsys *fs, Fid *afid, char *user, char *aname) +{ + Fcall tx, rx; + Fid *fid; + + if((fid = _fsgetfid(fs)) == nil) + return nil; + + 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; +} + +int +fsrpc(Fsys *fs, Fcall *tx, Fcall *rx, void **freep) +{ + int n, nn; + void *tpkt, *rpkt; + + n = sizeS2M(tx); + tpkt = malloc(n); + if(tpkt == nil) + return -1; + 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"); + fprint(2, "%r\n"); + return -1; + } + 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; +} + +Fid* +_fsgetfid(Fsys *fs) +{ + int i; + Fid *f; + + qlock(&fs->lk); + if(fs->freefid == nil){ + f = malloc(sizeof(Fid)*Fidchunk); + if(f == nil){ + qunlock(&fs->lk); + return nil; + } + for(i=0; i<Fidchunk; i++){ + f[i].fid = fs->nextfid++; + f[i].next = &f[i+1]; + f[i].fs = fs; + fs->ref++; + } + f[i-1].next = nil; + fs->freefid = f; + } + f = fs->freefid; + fs->freefid = f->next; + qunlock(&fs->lk); + return f; +} + +void +_fsputfid(Fid *f) +{ + Fsys *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) +{ + Fsys *fs; + + fs = mux->aux; + return write(fs->fd, pkt, GBIT32((uchar*)pkt)); +} + +static void* +_fsrecv(Mux *mux) +{ + uchar *pkt; + uchar buf[4]; + int n; + Fsys *fs; + + fs = mux->aux; + n = readn(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(buf, n); + if(readn(fs->fd, pkt+4, n-4) != n-4){ + free(pkt); + return nil; + } +#if 0 + if(pkt[4] == Ropenfd){ + /* do unix socket crap */ + sysfatal("no socket crap implemented"); + } +#endif + return pkt; +} diff --git a/src/libfs/fsimpl.h b/src/libfs/fsimpl.h new file mode 100644 index 00000000..fbcc3777 --- /dev/null +++ b/src/libfs/fsimpl.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ +/* See COPYRIGHT */ + +typedef struct Queue Queue; +Queue *_fsqalloc(void); +int _fsqsend(Queue*, void*); +void *_fsqrecv(Queue*); +void _fsqhangup(Queue*); +void *_fsnbqrecv(Queue*); + +#include <mux.h> +struct Fsys +{ + char version[20]; + int msize; + QLock lk; + int fd; + int ref; + Mux mux; + Fid *root; + Queue *txq; + Queue *rxq; + Fid *freefid; + int nextfid; +}; + +struct Fid +{ + int fid; + int mode; + Fid *next; + QLock lk; + Fsys *fs; + Qid qid; + vlong offset; +}; + +void _fsdecref(Fsys*); +void _fsputfid(Fid*); +Fid *_fsgetfid(Fsys*); + diff --git a/src/libfs/mkfile b/src/libfs/mkfile new file mode 100644 index 00000000..acfb0ae5 --- /dev/null +++ b/src/libfs/mkfile @@ -0,0 +1,22 @@ +PLAN9=../.. +<$PLAN9/src/mkhdr + +LIB=libfs.a + +OFILES=\ + close.$O\ + create.$O\ + dirread.$O\ + fs.$O\ + open.$O\ + read.$O\ + stat.$O\ + walk.$O\ + write.$O\ + wstat.$O\ + +HFILES=\ + $PLAN9/include/fs.h\ + $PLAN9/include/mux.h\ + +<$PLAN9/src/mksyslib diff --git a/src/libfs/open.c b/src/libfs/open.c new file mode 100644 index 00000000..458c5dac --- /dev/null +++ b/src/libfs/open.c @@ -0,0 +1,24 @@ +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <fs.h> +#include "fsimpl.h" + +Fid* +fsopen(Fsys *fs, char *name, int mode) +{ + Fid *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; +} diff --git a/src/libfs/read.c b/src/libfs/read.c new file mode 100644 index 00000000..ca6c628c --- /dev/null +++ b/src/libfs/read.c @@ -0,0 +1,48 @@ +/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ +/* See COPYRIGHT */ + +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <fs.h> +#include "fsimpl.h" + +long +fspread(Fid *fid, void *buf, long n, vlong offset) +{ + Fcall tx, rx; + void *freep; + + tx.type = Tread; + if(offset == -1){ + qlock(&fid->lk); + tx.offset = fid->offset; + qunlock(&fid->lk); + }else + tx.offset = offset; + tx.count = n; + + fsrpc(fid->fs, &tx, &rx, &freep); + 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); + tx.offset += n; + qunlock(&fid->lk); + } + } + free(freep); + + return rx.count; +} + +long +fsread(Fid *fid, void *buf, long n) +{ + return fspread(fid, buf, n, -1); +} diff --git a/src/libfs/stat.c b/src/libfs/stat.c new file mode 100644 index 00000000..e55e0b12 --- /dev/null +++ b/src/libfs/stat.c @@ -0,0 +1,54 @@ +/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ +/* See COPYRIGHT */ + +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <fs.h> +#include "fsimpl.h" + +Dir* +fsdirstat(Fsys *fs, char *name) +{ + Dir *d; + Fid *fid; + + if((fid = fswalk(fs->root, name)) == nil) + return nil; + + d = fsdirfstat(fid); + fsclose(fid); + return d; +} + +Dir* +fsdirfstat(Fid *fid) +{ + Dir *d; + Fsys *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; +} + diff --git a/src/libfs/walk.c b/src/libfs/walk.c new file mode 100644 index 00000000..ad4eddc7 --- /dev/null +++ b/src/libfs/walk.c @@ -0,0 +1,73 @@ +/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ +/* See COPYRIGHT */ + +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <fs.h> +#include "fsimpl.h" + +Fid* +fswalk(Fid *fid, char *oname) +{ + char *freep, *name; + int i, nwalk; + char *p; + Fid *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) + 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; +} diff --git a/src/libfs/write.c b/src/libfs/write.c new file mode 100644 index 00000000..96ecfa86 --- /dev/null +++ b/src/libfs/write.c @@ -0,0 +1,46 @@ +/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ +/* See COPYRIGHT */ + +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <fs.h> +#include "fsimpl.h" + +long +fspwrite(Fid *fd, void *buf, long n, vlong offset) +{ + Fcall tx, rx; + void *freep; + + tx.type = Tread; + if(offset == -1){ + qlock(&fd->lk); + tx.offset = fd->offset; + fd->offset += n; + qunlock(&fd->lk); + }else + tx.offset = offset; + tx.count = n; + tx.data = buf; + + fsrpc(fd->fs, &tx, &rx, &freep); + if(rx.type == Rerror){ + if(offset == -1){ + qlock(&fd->lk); + fd->offset -= n; + qunlock(&fd->lk); + } + werrstr("%s", rx.ename); + free(freep); + return -1; + } + free(freep); + return rx.count; +} + +long +fswrite(Fid *fd, void *buf, long n) +{ + return fspwrite(fd, buf, n, -1); +} diff --git a/src/libfs/wstat.c b/src/libfs/wstat.c new file mode 100644 index 00000000..90ae0e0f --- /dev/null +++ b/src/libfs/wstat.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ +/* See COPYRIGHT */ + +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <fs.h> +#include "fsimpl.h" + +int +fsdirwstat(Fsys *fs, char *name, Dir *d) +{ + int n; + Fid *fid; + + if((fid = fswalk(fs->root, name)) == nil) + return -1; + + n = fsdirfwstat(fid, d); + fsclose(fid); + return n; +} + +int +fsdirfwstat(Fid *fid, Dir *d) +{ + char *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; +} |