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