291 lines
5.5 KiB
C
291 lines
5.5 KiB
C
|
#pragma src "/sys/src/lib9p"
|
||
|
#pragma lib "lib9p.a"
|
||
|
|
||
|
/*
|
||
|
* Maps from uint32_ts to void*s.
|
||
|
*/
|
||
|
typedef struct Intmap Intmap;
|
||
|
|
||
|
#pragma incomplete Intmap
|
||
|
|
||
|
Intmap* allocmap(void (*inc)(void*));
|
||
|
void freemap(Intmap*, void (*destroy)(void*));
|
||
|
void* lookupkey(Intmap*, uint32_t);
|
||
|
void* insertkey(Intmap*, uint32_t, void*);
|
||
|
int caninsertkey(Intmap*, uint32_t, void*);
|
||
|
void* deletekey(Intmap*, uint32_t);
|
||
|
|
||
|
/*
|
||
|
* Fid and Request structures.
|
||
|
*/
|
||
|
typedef struct Fid Fid;
|
||
|
typedef struct Req Req;
|
||
|
typedef struct Fidpool Fidpool;
|
||
|
typedef struct Reqpool Reqpool;
|
||
|
typedef struct File File;
|
||
|
typedef struct Filelist Filelist;
|
||
|
typedef struct Tree Tree;
|
||
|
typedef struct Readdir Readdir;
|
||
|
typedef struct Srv Srv;
|
||
|
typedef struct Reqqueue Reqqueue;
|
||
|
typedef struct Queueelem Queueelem;
|
||
|
|
||
|
#pragma incomplete Filelist
|
||
|
#pragma incomplete Readdir
|
||
|
|
||
|
struct Queueelem
|
||
|
{
|
||
|
Queueelem *prev, *next;
|
||
|
void (*f)(Req *);
|
||
|
};
|
||
|
|
||
|
struct Reqqueue
|
||
|
{
|
||
|
QLock ql;
|
||
|
Rendez r;
|
||
|
Queueelem;
|
||
|
int pid, flush;
|
||
|
Req *cur;
|
||
|
};
|
||
|
|
||
|
struct Fid
|
||
|
{
|
||
|
uint32_t fid;
|
||
|
char omode; /* -1 = not open */
|
||
|
File* file;
|
||
|
char* uid;
|
||
|
Qid qid;
|
||
|
void* aux;
|
||
|
|
||
|
/* below is implementation-specific; don't use */
|
||
|
Readdir* rdir;
|
||
|
Ref ref;
|
||
|
Fidpool* pool;
|
||
|
int64_t diroffset;
|
||
|
int32_t dirindex;
|
||
|
};
|
||
|
|
||
|
struct Req
|
||
|
{
|
||
|
uint32_t tag;
|
||
|
void* aux;
|
||
|
Fcall ifcall;
|
||
|
Fcall ofcall;
|
||
|
Dir d;
|
||
|
Req* oldreq;
|
||
|
Fid* fid;
|
||
|
Fid* afid;
|
||
|
Fid* newfid;
|
||
|
Srv* srv;
|
||
|
|
||
|
Queueelem qu;
|
||
|
|
||
|
/* below is implementation-specific; don't use */
|
||
|
QLock lk;
|
||
|
Ref ref;
|
||
|
Reqpool* pool;
|
||
|
uint8_t* buf;
|
||
|
uint8_t type;
|
||
|
uint8_t responded;
|
||
|
char* error;
|
||
|
void* rbuf;
|
||
|
Req** flush;
|
||
|
int nflush;
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* Pools to maintain Fid <-> fid and Req <-> tag maps.
|
||
|
*/
|
||
|
|
||
|
struct Fidpool {
|
||
|
Intmap *map;
|
||
|
void (*destroy)(Fid*);
|
||
|
Srv *srv;
|
||
|
};
|
||
|
|
||
|
struct Reqpool {
|
||
|
Intmap *map;
|
||
|
void (*destroy)(Req*);
|
||
|
Srv *srv;
|
||
|
};
|
||
|
|
||
|
Fidpool* allocfidpool(void (*destroy)(Fid*));
|
||
|
void freefidpool(Fidpool*);
|
||
|
Fid* allocfid(Fidpool*, uint32_t);
|
||
|
Fid* lookupfid(Fidpool*, uint32_t);
|
||
|
void closefid(Fid*);
|
||
|
Fid* removefid(Fidpool*, uint32_t);
|
||
|
|
||
|
Reqpool* allocreqpool(void (*destroy)(Req*));
|
||
|
void freereqpool(Reqpool*);
|
||
|
Req* allocreq(Reqpool*, uint32_t);
|
||
|
Req* lookupreq(Reqpool*, uint32_t);
|
||
|
void closereq(Req*);
|
||
|
Req* removereq(Reqpool*, uint32_t);
|
||
|
|
||
|
typedef int Dirgen(int, Dir*, void*);
|
||
|
void dirread9p(Req*, Dirgen*, void*);
|
||
|
|
||
|
/*
|
||
|
* File trees.
|
||
|
*/
|
||
|
struct File {
|
||
|
Ref ref;
|
||
|
Dir;
|
||
|
File *parent;
|
||
|
void *aux;
|
||
|
|
||
|
/* below is implementation-specific; don't use */
|
||
|
RWLock rwl;
|
||
|
Filelist *filelist;
|
||
|
Tree *tree;
|
||
|
int nchild;
|
||
|
int allocd;
|
||
|
int nxchild;
|
||
|
Ref readers;
|
||
|
};
|
||
|
|
||
|
struct Tree {
|
||
|
File *root;
|
||
|
void (*destroy)(File *file);
|
||
|
|
||
|
/* below is implementation-specific; don't use */
|
||
|
Lock genlock;
|
||
|
uint32_t qidgen;
|
||
|
uint32_t dirqidgen;
|
||
|
};
|
||
|
|
||
|
Tree* alloctree(char*, char*, uint32_t, void(*destroy)(File*));
|
||
|
void freetree(Tree*);
|
||
|
File* createfile(File*, char*, char*, uint32_t, void*);
|
||
|
int removefile(File*);
|
||
|
void closefile(File*);
|
||
|
File* walkfile(File*, char*);
|
||
|
Readdir* opendirfile(File*);
|
||
|
int32_t readdirfile(Readdir*, uint8_t*, int32_t);
|
||
|
void closedirfile(Readdir*);
|
||
|
|
||
|
/*
|
||
|
* Kernel-style command parser
|
||
|
*/
|
||
|
typedef struct Cmdbuf Cmdbuf;
|
||
|
typedef struct Cmdtab Cmdtab;
|
||
|
Cmdbuf* parsecmd(char *a, int n);
|
||
|
void respondcmderror(Req*, Cmdbuf*, char*, ...);
|
||
|
Cmdtab* lookupcmd(Cmdbuf*, Cmdtab*, int);
|
||
|
#pragma varargck argpos respondcmderr 3
|
||
|
struct Cmdbuf
|
||
|
{
|
||
|
char *buf;
|
||
|
char **f;
|
||
|
int nf;
|
||
|
};
|
||
|
|
||
|
struct Cmdtab
|
||
|
{
|
||
|
int index; /* used by client to switch on result */
|
||
|
char *cmd; /* command name */
|
||
|
int narg; /* expected #args; 0 ==> variadic */
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* File service loop.
|
||
|
*/
|
||
|
struct Srv {
|
||
|
Tree* tree;
|
||
|
void (*destroyfid)(Fid*);
|
||
|
void (*destroyreq)(Req*);
|
||
|
void (*start)(Srv*);
|
||
|
void (*end)(Srv*);
|
||
|
void* aux;
|
||
|
|
||
|
void (*attach)(Req*);
|
||
|
void (*auth)(Req*);
|
||
|
void (*open)(Req*);
|
||
|
void (*create)(Req*);
|
||
|
void (*read)(Req*);
|
||
|
void (*write)(Req*);
|
||
|
void (*remove)(Req*);
|
||
|
void (*flush)(Req*);
|
||
|
void (*stat)(Req*);
|
||
|
void (*wstat)(Req*);
|
||
|
void (*walk)(Req*);
|
||
|
char* (*clone)(Fid*, Fid*);
|
||
|
char* (*walk1)(Fid*, char*, Qid*);
|
||
|
|
||
|
int infd;
|
||
|
int outfd;
|
||
|
int nopipe;
|
||
|
int srvfd;
|
||
|
int leavefdsopen; /* magic for acme win */
|
||
|
char* keyspec;
|
||
|
|
||
|
/* below is implementation-specific; don't use */
|
||
|
Fidpool* fpool;
|
||
|
Reqpool* rpool;
|
||
|
uint32_t msize;
|
||
|
|
||
|
uint8_t* rbuf;
|
||
|
QLock rlock;
|
||
|
uint8_t* wbuf;
|
||
|
QLock wlock;
|
||
|
|
||
|
char* addr;
|
||
|
|
||
|
QLock slock;
|
||
|
Ref sref; /* srvwork procs */
|
||
|
Ref rref; /* requests in flight */
|
||
|
|
||
|
void (*free)(Srv*);
|
||
|
};
|
||
|
|
||
|
void srv(Srv*);
|
||
|
void postmountsrv(Srv*, char*, char*, int);
|
||
|
void _postmountsrv(Srv*, char*, char*, int);
|
||
|
void postsharesrv(Srv*, char*, char*, char*);
|
||
|
void _postsharesrv(Srv*, char*, char*, char*);
|
||
|
void listensrv(Srv*, char*);
|
||
|
void _listensrv(Srv*, char*);
|
||
|
int postfd(char*, int);
|
||
|
int sharefd(char*, char*, int);
|
||
|
int chatty9p;
|
||
|
void respond(Req*, char*);
|
||
|
void responderror(Req*);
|
||
|
void threadpostmountsrv(Srv*, char*, char*, int);
|
||
|
void threadpostsharesrv(Srv*, char*, char*, char*);
|
||
|
void threadlistensrv(Srv *s, char *addr);
|
||
|
|
||
|
/*
|
||
|
* Helper. Assumes user is same as group.
|
||
|
*/
|
||
|
int hasperm(File*, char*, int);
|
||
|
|
||
|
void* emalloc9p(uint32_t);
|
||
|
void* erealloc9p(void*, uint32_t);
|
||
|
char* estrdup9p(char*);
|
||
|
|
||
|
enum {
|
||
|
OMASK = 3
|
||
|
};
|
||
|
|
||
|
void readstr(Req*, char*);
|
||
|
void readbuf(Req*, void*, int32_t);
|
||
|
void walkandclone(Req*, char*(*walk1)(Fid*,char*,void*),
|
||
|
char*(*clone)(Fid*,Fid*,void*), void*);
|
||
|
|
||
|
void auth9p(Req*);
|
||
|
void authread(Req*);
|
||
|
void authwrite(Req*);
|
||
|
void authdestroy(Fid*);
|
||
|
int authattach(Req*);
|
||
|
|
||
|
extern void (*_forker)(void (*)(void*), void*, int);
|
||
|
|
||
|
void srvacquire(Srv *);
|
||
|
void srvrelease(Srv *);
|
||
|
|
||
|
Reqqueue* reqqueuecreate(void);
|
||
|
void reqqueuepush(Reqqueue*, Req*, void (*)(Req *));
|
||
|
void reqqueueflush(Reqqueue*, Req*);
|
||
|
void reqqueuefree(Reqqueue*);
|