/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>#include <thread.h>#include <bio.h> typedef struct Args Args; struct Args { int argc; char **argv;}; typedef struct Dfile Dfile;typedef struct Fid Fid;typedef struct File File;typedef struct Fs Fs;typedef struct Request Request;typedef struct Symbol Symbol;typedef struct Tardir Tardir; extern int threadrforkflag = RFNAMEG; enum{ Nstat = 1024, /* plenty for this application */ MAXSIZE = 8192+IOHDRSZ,}; int messagesize = MAXSIZE; voidfatal(char *fmt, ...){ va_list arg; char buf[1024]; write(2, "depend: ", 8); va_start(arg, fmt); vseprint(buf, buf+1024, fmt, arg); va_end(arg); write(2, buf, strlen(buf)); write(2, "\n", 1); threadexitsall(fmt);} enum{ Nfidhash= 64, Ndfhash= 128,}; struct Symbol{ Symbol *next; /* hash list chaining */ char *sym; int fno; /* file symbol is defined in */}; /* source file */struct File{ QLock; char *name; Symbol *ref; uchar *refvec; /* files resolving the references */ uint len; /* length of file */ uint tarlen; /* length of tar file */ uint mode; uint mtime; int use; int fd;}; /* .depend file */struct Dfile{ Lock; int use; /* use count */ int old; /* true if this is an superceded dfile */ File *file; /* files */ int nfile; /* number of files */ int flen; /* length of file table */ Symbol **dhash; /* hash table of symbols */ int hlen; /* length of hash table */ Dfile *next; /* hash chain */ char *path; /* path name of dependency file */ Qid qid; /* qid of the dependency file */}; struct Fid{ Fid *next; int fid; int ref; int attached; int open; Qid qid; char *path; Dfile *df; Symbol *dp; int fd; Dir *dir; int ndir; int dirindex;}; struct Request{ Request *next; Fid *fid; Fcall f; uchar buf[1];}; enum{ Tblocksize= 512, /* tar block size */ Tnamesize= 100, /* tar name size */}; struct Tardir{ char name[Tnamesize]; char mode[8]; char uid[8]; char gid[8]; char size[12]; char mtime[12]; char chksum[8]; char linkflag; char linkname[Tnamesize];}; struct Fs{ Lock; int fd; /* to kernel mount point */ Fid *hash[Nfidhash]; char *root; Qid rootqid; }; struct Fsarg{ Fs *fs; int fd; char *root;}; extern void fsrun(void*);extern Fid* fsgetfid(Fs*, int);extern void fsputfid(Fs*, Fid*);extern void fsreply(Fs*, Request*, char*);extern void fsversion(Fs*, Request*, Fid*);extern void fsauth(Fs*, Request*, Fid*);extern void fsflush(Fs*, Request*, Fid*);extern void fsattach(Fs*, Request*, Fid*);extern void fswalk(Fs*, Request*, Fid*);extern void fsopen(Fs*, Request*, Fid*);extern void fscreate(Fs*, Request*, Fid*);extern void fsread(Fs*, Request*, Fid*);extern void fswrite(Fs*, Request*, Fid*);extern void fsclunk(Fs*, Request*, Fid*);extern void fsremove(Fs*, Request*, Fid*);extern void fsstat(Fs*, Request*, Fid*);extern void fswstat(Fs*, Request*, Fid*); void (*fcall[])(Fs*, Request*, Fid*) ={ [Tflush] fsflush, [Tversion] fsversion, [Tauth] fsauth, [Tattach] fsattach, [Twalk] fswalk, [Topen] fsopen, [Tcreate] fscreate, [Tread] fsread, [Twrite] fswrite, [Tclunk] fsclunk, [Tremove] fsremove, [Tstat] fsstat, [Twstat] fswstat}; char Eperm[] = "permission denied";char Eexist[] = "file does not exist";char Enotdir[] = "not a directory";char Eisopen[] = "file already open";char Enofid[] = "no such fid";char mallocerr[] = "malloc: %r";char Etoolong[] = "name too long"; char *dependlog = "depend"; int debug;Dfile *dfhash[Ndfhash]; /* dependency file hash */QLock dfhlock[Ndfhash];QLock iolock; Request* allocreq(int);Dfile* getdf(char*);void releasedf(Dfile*);Symbol* dfsearch(Dfile*, char*);void dfresolve(Dfile*, int);char* mkpath(char*, char*);int mktar(Dfile*, Symbol*, uchar*, uint, int);void closetar(Dfile*, Symbol*); void*emalloc(uint n){ void *p; p = malloc(n); if(p == nil) fatal(mallocerr); memset(p, 0, n); return p;} void *erealloc(void *ReallocP, int ReallocN){ if(ReallocN == 0) ReallocN = 1; if(!ReallocP) ReallocP = emalloc(ReallocN); else if(!(ReallocP = realloc(ReallocP, ReallocN))) fatal("unable to allocate %d bytes",ReallocN); return(ReallocP);} char*estrdup(char *s){ char *d, *d0; if(!s) return 0; d = d0 = emalloc(strlen(s)+1); while(*d++ = *s++) ; return d0;} /* * mount the user interface and start one request processor * per CPU */voidrealmain(void *a){ Fs *fs; int pfd[2]; int srv; char service[128]; struct Fsarg fsarg; Args *args; int argc; char **argv; args = a; argc = args->argc; argv = args->argv; fmtinstall('F', fcallfmt); ARGBEGIN{ case 'd': debug++; break; }ARGEND if(argc != 2){ fprint(2, "usage: %s [-d] svc-name directory\n", argv0); exits("usage"); } snprint(service, sizeof service, "#s/%s", argv[0]); if(argv[1][0] != '/') fatal("directory must be rooted"); if(pipe(pfd) < 0) fatal("opening pipe: %r"); /* Typically mounted before /srv exists */ srv = create(service, OWRITE, 0666); if(srv < 0) fatal("post: %r"); fprint(srv, "%d", pfd[1]); close(srv); close(pfd[1]); time(nil); /* open fd for time before losing / */ if(bind(argv[1], "/", MREPL) == 0) fatal("can't bind %s to /", argv[1]); fs = emalloc(sizeof(Fs)); fsarg.fs = fs; fsarg.fd = pfd[0]; fsarg.root = argv[1]; proccreate(fsrun, &fsarg, 16*1024); proccreate(fsrun, &fsarg, 16*1024); fsrun(&fsarg); exits(nil);} voidthreadmain(int argc, char *argv[]){ static Args args; args.argc = argc; args.argv = argv; rfork(RFNAMEG); proccreate(realmain, &args, 16*1024);} char*mkpath(char *dir, char *file){ int len; char *path; len = strlen(dir) + 1; if(file != nil) len += strlen(file) + 1; path = emalloc(len); if(file != nil) sprint(path, "%s/%s", dir, file); else sprint(path, "%s", dir); return path;} voidfsrun(void *a){ struct Fsarg *fsarg; Fs* fs; char *root; int n, t; Request *r; Fid *f; Dir *d; fsarg = a; fs = fsarg->fs; fs->fd = fsarg->fd; root = fsarg->root; d = dirstat("/"); if(d == nil) fatal("root %s inaccessible: %r", root); fs->rootqid = d->qid; free(d); for(;;){ r = allocreq(messagesize); qlock(&iolock); n = read9pmsg(fs->fd, r->buf, messagesize); qunlock(&iolock); if(n <= 0) fatal("read9pmsg error: %r"); if(convM2S(r->buf, n, &r->f) == 0){ fprint(2, "can't convert %ux %ux %ux\n", r->buf[0], r->buf[1], r->buf[2]); free(r); continue; } f = fsgetfid(fs, r->f.fid); r->fid = f; if(debug) fprint(2, "%F path %llux\n", &r->f, f->qid.path); t = r->f.type; r->f.type++; (*fcall[t])(fs, r, f); fsputfid(fs, f); } } /* * any request that can get queued for a delayed reply */Request*allocreq(int bufsize){ Request *r; r = emalloc(sizeof(Request)+bufsize); r->next = nil; return r;} Fid*fsgetfid(Fs *fs, int fid){ Fid *f, *nf; lock(fs); for(f = fs->hash[fid%Nfidhash]; f; f = f->next){ if(f->fid == fid){ f->ref++; unlock(fs); return f; } } nf = emalloc(sizeof(Fid)); nf->next = fs->hash[fid%Nfidhash]; fs->hash[fid%Nfidhash] = nf; nf->fid = fid; nf->ref = 1; nf->fd = -1; unlock(fs); return nf;} voidfsputfid(Fs *fs, Fid *f){ Fid **l, *nf; lock(fs); if(--f->ref > 0){ unlock(fs); return; } for(l = &fs->hash[f->fid%Nfidhash]; nf = *l; l = &nf->next) if(nf == f){ *l = f->next; break; } unlock(fs); free(f);} voidfsreply(Fs *fs, Request *r, char *err){ int n; uchar buf[MAXSIZE]; if(err){ r->f.type = Rerror; r->f.ename = err; } if(debug) fprint(2, "%F path %llux\n", &r->f, r->fid->qid.path); n = convS2M(&r->f, buf, messagesize); if(n == 0) fatal("bad convS2M"); if(write(fs->fd, buf, n) != n) fatal("unmounted"); free(r);} voidfsversion(Fs *fs, Request *r, Fid*){ if(r->f.msize < 256){ fsreply(fs, r, "version: bad message size"); return; } if(messagesize > r->f.msize) messagesize = r->f.msize; r->f.msize = messagesize; r->f.version = "9P2000"; fsreply(fs, r, nil);} voidfsauth(Fs *fs, Request *r, Fid*){ fsreply(fs, r, "depend: authentication not required");} voidfsflush(Fs*, Request*, Fid*){Lines 1–500 of 1532. Load more
/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h> #include <libc.h> #include <auth.h> #include <fcall.h> #include <thread.h> #include <bio.h> typedef struct Args Args; struct Args { int argc; char **argv; }; typedef struct Dfile Dfile; typedef struct Fid Fid; typedef struct File File; typedef struct Fs Fs; typedef struct Request Request; typedef struct Symbol Symbol; typedef struct Tardir Tardir; extern int threadrforkflag = RFNAMEG; enum{ Nstat = 1024, /* plenty for this application */ MAXSIZE = 8192+IOHDRSZ, }; int messagesize = MAXSIZE; void fatal(char *fmt, ...) { va_list arg; char buf[1024]; write(2, "depend: ", 8); va_start(arg, fmt); vseprint(buf, buf+1024, fmt, arg); va_end(arg); write(2, buf, strlen(buf)); write(2, "\n", 1); threadexitsall(fmt); } enum { Nfidhash= 64, Ndfhash= 128, }; struct Symbol { Symbol *next; /* hash list chaining */ char *sym; int fno; /* file symbol is defined in */ }; /* source file */ struct File { QLock; char *name; Symbol *ref; uchar *refvec; /* files resolving the references */ uint len; /* length of file */ uint tarlen; /* length of tar file */ uint mode; uint mtime; int use; int fd; }; /* .depend file */ struct Dfile { Lock; int use; /* use count */ int old; /* true if this is an superceded dfile */ File *file; /* files */ int nfile; /* number of files */ int flen; /* length of file table */ Symbol **dhash; /* hash table of symbols */ int hlen; /* length of hash table */ Dfile *next; /* hash chain */ char *path; /* path name of dependency file */ Qid qid; /* qid of the dependency file */ }; struct Fid { Fid *next; int fid; int ref; int attached; int open; Qid qid; char *path; Dfile *df; Symbol *dp; int fd; Dir *dir; int ndir; int dirindex; }; struct Request { Request *next; Fid *fid; Fcall f; uchar buf[1]; }; enum { Tblocksize= 512, /* tar block size */ Tnamesize= 100, /* tar name size */ }; struct Tardir { char name[Tnamesize]; char mode[8]; char uid[8]; char gid[8]; char size[12]; char mtime[12]; char chksum[8]; char linkflag; char linkname[Tnamesize]; }; struct Fs { Lock; int fd; /* to kernel mount point */ Fid *hash[Nfidhash]; char *root; Qid rootqid; }; struct Fsarg { Fs *fs; int fd; char *root; }; extern void fsrun(void*); extern Fid* fsgetfid(Fs*, int); extern void fsputfid(Fs*, Fid*); extern void fsreply(Fs*, Request*, char*); extern void fsversion(Fs*, Request*, Fid*); extern void fsauth(Fs*, Request*, Fid*); extern void fsflush(Fs*, Request*, Fid*); extern void fsattach(Fs*, Request*, Fid*); extern void fswalk(Fs*, Request*, Fid*); extern void fsopen(Fs*, Request*, Fid*); extern void fscreate(Fs*, Request*, Fid*); extern void fsread(Fs*, Request*, Fid*); extern void fswrite(Fs*, Request*, Fid*); extern void fsclunk(Fs*, Request*, Fid*); extern void fsremove(Fs*, Request*, Fid*); extern void fsstat(Fs*, Request*, Fid*); extern void fswstat(Fs*, Request*, Fid*); void (*fcall[])(Fs*, Request*, Fid*) = { [Tflush] fsflush, [Tversion] fsversion, [Tauth] fsauth, [Tattach] fsattach, [Twalk] fswalk, [Topen] fsopen, [Tcreate] fscreate, [Tread] fsread, [Twrite] fswrite, [Tclunk] fsclunk, [Tremove] fsremove, [Tstat] fsstat, [Twstat] fswstat }; char Eperm[] = "permission denied"; char Eexist[] = "file does not exist"; char Enotdir[] = "not a directory"; char Eisopen[] = "file already open"; char Enofid[] = "no such fid"; char mallocerr[] = "malloc: %r"; char Etoolong[] = "name too long"; char *dependlog = "depend"; int debug; Dfile *dfhash[Ndfhash]; /* dependency file hash */ QLock dfhlock[Ndfhash]; QLock iolock; Request* allocreq(int); Dfile* getdf(char*); void releasedf(Dfile*); Symbol* dfsearch(Dfile*, char*); void dfresolve(Dfile*, int); char* mkpath(char*, char*); int mktar(Dfile*, Symbol*, uchar*, uint, int); void closetar(Dfile*, Symbol*); void* emalloc(uint n) { void *p; p = malloc(n); if(p == nil) fatal(mallocerr); memset(p, 0, n); return p; } void * erealloc(void *ReallocP, int ReallocN) { if(ReallocN == 0) ReallocN = 1; if(!ReallocP) ReallocP = emalloc(ReallocN); else if(!(ReallocP = realloc(ReallocP, ReallocN))) fatal("unable to allocate %d bytes",ReallocN); return(ReallocP); } char* estrdup(char *s) { char *d, *d0; if(!s) return 0; d = d0 = emalloc(strlen(s)+1); while(*d++ = *s++) ; return d0; } /* * mount the user interface and start one request processor * per CPU */ void realmain(void *a) { Fs *fs; int pfd[2]; int srv; char service[128]; struct Fsarg fsarg; Args *args; int argc; char **argv; args = a; argc = args->argc; argv = args->argv; fmtinstall('F', fcallfmt); ARGBEGIN{ case 'd': debug++; break; }ARGEND if(argc != 2){ fprint(2, "usage: %s [-d] svc-name directory\n", argv0); exits("usage"); } snprint(service, sizeof service, "#s/%s", argv[0]); if(argv[1][0] != '/') fatal("directory must be rooted"); if(pipe(pfd) < 0) fatal("opening pipe: %r"); /* Typically mounted before /srv exists */ srv = create(service, OWRITE, 0666); if(srv < 0) fatal("post: %r"); fprint(srv, "%d", pfd[1]); close(srv); close(pfd[1]); time(nil); /* open fd for time before losing / */ if(bind(argv[1], "/", MREPL) == 0) fatal("can't bind %s to /", argv[1]); fs = emalloc(sizeof(Fs)); fsarg.fs = fs; fsarg.fd = pfd[0]; fsarg.root = argv[1]; proccreate(fsrun, &fsarg, 16*1024); proccreate(fsrun, &fsarg, 16*1024); fsrun(&fsarg); exits(nil); } void threadmain(int argc, char *argv[]) { static Args args; args.argc = argc; args.argv = argv; rfork(RFNAMEG); proccreate(realmain, &args, 16*1024); } char* mkpath(char *dir, char *file) { int len; char *path; len = strlen(dir) + 1; if(file != nil) len += strlen(file) + 1; path = emalloc(len); if(file != nil) sprint(path, "%s/%s", dir, file); else sprint(path, "%s", dir); return path; } void fsrun(void *a) { struct Fsarg *fsarg; Fs* fs; char *root; int n, t; Request *r; Fid *f; Dir *d; fsarg = a; fs = fsarg->fs; fs->fd = fsarg->fd; root = fsarg->root; d = dirstat("/"); if(d == nil) fatal("root %s inaccessible: %r", root); fs->rootqid = d->qid; free(d); for(;;){ r = allocreq(messagesize); qlock(&iolock); n = read9pmsg(fs->fd, r->buf, messagesize); qunlock(&iolock); if(n <= 0) fatal("read9pmsg error: %r"); if(convM2S(r->buf, n, &r->f) == 0){ fprint(2, "can't convert %ux %ux %ux\n", r->buf[0], r->buf[1], r->buf[2]); free(r); continue; } f = fsgetfid(fs, r->f.fid); r->fid = f; if(debug) fprint(2, "%F path %llux\n", &r->f, f->qid.path); t = r->f.type; r->f.type++; (*fcall[t])(fs, r, f); fsputfid(fs, f); } } /* * any request that can get queued for a delayed reply */ Request* allocreq(int bufsize) { Request *r; r = emalloc(sizeof(Request)+bufsize); r->next = nil; return r; } Fid* fsgetfid(Fs *fs, int fid) { Fid *f, *nf; lock(fs); for(f = fs->hash[fid%Nfidhash]; f; f = f->next){ if(f->fid == fid){ f->ref++; unlock(fs); return f; } } nf = emalloc(sizeof(Fid)); nf->next = fs->hash[fid%Nfidhash]; fs->hash[fid%Nfidhash] = nf; nf->fid = fid; nf->ref = 1; nf->fd = -1; unlock(fs); return nf; } void fsputfid(Fs *fs, Fid *f) { Fid **l, *nf; lock(fs); if(--f->ref > 0){ unlock(fs); return; } for(l = &fs->hash[f->fid%Nfidhash]; nf = *l; l = &nf->next) if(nf == f){ *l = f->next; break; } unlock(fs); free(f); } void fsreply(Fs *fs, Request *r, char *err) { int n; uchar buf[MAXSIZE]; if(err){ r->f.type = Rerror; r->f.ename = err; } if(debug) fprint(2, "%F path %llux\n", &r->f, r->fid->qid.path); n = convS2M(&r->f, buf, messagesize); if(n == 0) fatal("bad convS2M"); if(write(fs->fd, buf, n) != n) fatal("unmounted"); free(r); } void fsversion(Fs *fs, Request *r, Fid*) { if(r->f.msize < 256){ fsreply(fs, r, "version: bad message size"); return; } if(messagesize > r->f.msize) messagesize = r->f.msize; r->f.msize = messagesize; r->f.version = "9P2000"; fsreply(fs, r, nil); } void fsauth(Fs *fs, Request *r, Fid*) { fsreply(fs, r, "depend: authentication not required"); } void fsflush(Fs*, Request*, Fid*) {