lib9pclient is the new libfs
This commit is contained in:
parent
5ba841dffa
commit
46f79934b7
16 changed files with 1033 additions and 0 deletions
27
src/lib9pclient/COPYRIGHT
Normal file
27
src/lib9pclient/COPYRIGHT
Normal file
|
|
@ -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.
|
||||||
|
|
||||||
38
src/lib9pclient/auth.c
Normal file
38
src/lib9pclient/auth.c
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */
|
||||||
|
/* See COPYRIGHT */
|
||||||
|
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <fcall.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
29
src/lib9pclient/close.c
Normal file
29
src/lib9pclient/close.c
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */
|
||||||
|
/* See COPYRIGHT */
|
||||||
|
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <fcall.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
25
src/lib9pclient/create.c
Normal file
25
src/lib9pclient/create.c
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <fcall.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
99
src/lib9pclient/dirread.c
Normal file
99
src/lib9pclient/dirread.c
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
/* Mostly copied from Plan 9's libc. */
|
||||||
|
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <fcall.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
333
src/lib9pclient/fs.c
Normal file
333
src/lib9pclient/fs.c
Normal file
|
|
@ -0,0 +1,333 @@
|
||||||
|
/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */
|
||||||
|
/* See COPYRIGHT */
|
||||||
|
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <fcall.h>
|
||||||
|
#include <9pclient.h>
|
||||||
|
#include <thread.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
|
||||||
|
{
|
||||||
|
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; i<CFidchunk; i++){
|
||||||
|
f[i].fid = fs->nextfid++;
|
||||||
|
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;
|
||||||
|
}
|
||||||
47
src/lib9pclient/fsimpl.h
Normal file
47
src/lib9pclient/fsimpl.h
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */
|
||||||
|
/* See COPYRIGHT */
|
||||||
|
|
||||||
|
#include <thread.h>
|
||||||
|
|
||||||
|
typedef struct Queue Queue;
|
||||||
|
Queue *_fsqalloc(void);
|
||||||
|
int _fsqsend(Queue*, void*);
|
||||||
|
void *_fsqrecv(Queue*);
|
||||||
|
void _fsqhangup(Queue*);
|
||||||
|
void *_fsnbqrecv(Queue*);
|
||||||
|
|
||||||
|
#include <mux.h>
|
||||||
|
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*);
|
||||||
23
src/lib9pclient/mkfile
Normal file
23
src/lib9pclient/mkfile
Normal file
|
|
@ -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
|
||||||
40
src/lib9pclient/ns.c
Normal file
40
src/lib9pclient/ns.c
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <fcall.h>
|
||||||
|
#include <9pclient.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
24
src/lib9pclient/open.c
Normal file
24
src/lib9pclient/open.c
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <fcall.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
26
src/lib9pclient/openfd.c
Normal file
26
src/lib9pclient/openfd.c
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <fcall.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
72
src/lib9pclient/read.c
Normal file
72
src/lib9pclient/read.c
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */
|
||||||
|
/* See COPYRIGHT */
|
||||||
|
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <fcall.h>
|
||||||
|
#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<n; tot+=nn){
|
||||||
|
nn = fsread(fid, (char*)buf+tot, n-tot);
|
||||||
|
if(nn <= 0){
|
||||||
|
if(tot == 0)
|
||||||
|
return nn;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tot;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
54
src/lib9pclient/stat.c
Normal file
54
src/lib9pclient/stat.c
Normal file
|
|
@ -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 <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;
|
||||||
|
}
|
||||||
|
|
||||||
73
src/lib9pclient/walk.c
Normal file
73
src/lib9pclient/walk.c
Normal file
|
|
@ -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 <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;
|
||||||
|
}
|
||||||
74
src/lib9pclient/write.c
Normal file
74
src/lib9pclient/write.c
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */
|
||||||
|
/* See COPYRIGHT */
|
||||||
|
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <fcall.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
49
src/lib9pclient/wstat.c
Normal file
49
src/lib9pclient/wstat.c
Normal file
|
|
@ -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 <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;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue