17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <auth.h>
47dd7cddfSDavid du Colombier #include <fcall.h>
57dd7cddfSDavid du Colombier #include <thread.h>
67dd7cddfSDavid du Colombier #include <bio.h>
77dd7cddfSDavid du Colombier
873e742d7SDavid du Colombier typedef struct Args Args;
973e742d7SDavid du Colombier
1073e742d7SDavid du Colombier struct Args {
1173e742d7SDavid du Colombier int argc;
1273e742d7SDavid du Colombier char **argv;
1373e742d7SDavid du Colombier };
1473e742d7SDavid du Colombier
157dd7cddfSDavid du Colombier typedef struct Dfile Dfile;
167dd7cddfSDavid du Colombier typedef struct Fid Fid;
177dd7cddfSDavid du Colombier typedef struct File File;
187dd7cddfSDavid du Colombier typedef struct Fs Fs;
197dd7cddfSDavid du Colombier typedef struct Request Request;
207dd7cddfSDavid du Colombier typedef struct Symbol Symbol;
217dd7cddfSDavid du Colombier typedef struct Tardir Tardir;
227dd7cddfSDavid du Colombier
237dd7cddfSDavid du Colombier extern int threadrforkflag = RFNAMEG;
247dd7cddfSDavid du Colombier
259a747e4fSDavid du Colombier enum{
269a747e4fSDavid du Colombier Nstat = 1024, /* plenty for this application */
279a747e4fSDavid du Colombier MAXSIZE = 8192+IOHDRSZ,
289a747e4fSDavid du Colombier };
299a747e4fSDavid du Colombier
309a747e4fSDavid du Colombier int messagesize = MAXSIZE;
319a747e4fSDavid du Colombier
327dd7cddfSDavid du Colombier void
fatal(char * fmt,...)337dd7cddfSDavid du Colombier fatal(char *fmt, ...)
347dd7cddfSDavid du Colombier {
357dd7cddfSDavid du Colombier va_list arg;
367dd7cddfSDavid du Colombier char buf[1024];
377dd7cddfSDavid du Colombier
387dd7cddfSDavid du Colombier write(2, "depend: ", 8);
397dd7cddfSDavid du Colombier va_start(arg, fmt);
409a747e4fSDavid du Colombier vseprint(buf, buf+1024, fmt, arg);
417dd7cddfSDavid du Colombier va_end(arg);
427dd7cddfSDavid du Colombier write(2, buf, strlen(buf));
437dd7cddfSDavid du Colombier write(2, "\n", 1);
447dd7cddfSDavid du Colombier threadexitsall(fmt);
457dd7cddfSDavid du Colombier }
467dd7cddfSDavid du Colombier
477dd7cddfSDavid du Colombier enum
487dd7cddfSDavid du Colombier {
497dd7cddfSDavid du Colombier Nfidhash= 64,
507dd7cddfSDavid du Colombier Ndfhash= 128,
517dd7cddfSDavid du Colombier };
527dd7cddfSDavid du Colombier
537dd7cddfSDavid du Colombier struct Symbol
547dd7cddfSDavid du Colombier {
557dd7cddfSDavid du Colombier Symbol *next; /* hash list chaining */
569a747e4fSDavid du Colombier char *sym;
577dd7cddfSDavid du Colombier int fno; /* file symbol is defined in */
587dd7cddfSDavid du Colombier };
597dd7cddfSDavid du Colombier
607dd7cddfSDavid du Colombier /* source file */
617dd7cddfSDavid du Colombier struct File
627dd7cddfSDavid du Colombier {
637dd7cddfSDavid du Colombier QLock;
647dd7cddfSDavid du Colombier
657dd7cddfSDavid du Colombier char *name;
667dd7cddfSDavid du Colombier Symbol *ref;
677dd7cddfSDavid du Colombier uchar *refvec; /* files resolving the references */
687dd7cddfSDavid du Colombier uint len; /* length of file */
697dd7cddfSDavid du Colombier uint tarlen; /* length of tar file */
707dd7cddfSDavid du Colombier uint mode;
717dd7cddfSDavid du Colombier uint mtime;
727dd7cddfSDavid du Colombier
737dd7cddfSDavid du Colombier int use;
747dd7cddfSDavid du Colombier int fd;
757dd7cddfSDavid du Colombier };
767dd7cddfSDavid du Colombier
777dd7cddfSDavid du Colombier /* .depend file */
787dd7cddfSDavid du Colombier struct Dfile
797dd7cddfSDavid du Colombier {
807dd7cddfSDavid du Colombier Lock;
817dd7cddfSDavid du Colombier int use; /* use count */
827dd7cddfSDavid du Colombier int old; /* true if this is an superceded dfile */
837dd7cddfSDavid du Colombier
847dd7cddfSDavid du Colombier File *file; /* files */
857dd7cddfSDavid du Colombier int nfile; /* number of files */
867dd7cddfSDavid du Colombier int flen; /* length of file table */
877dd7cddfSDavid du Colombier
887dd7cddfSDavid du Colombier Symbol **dhash; /* hash table of symbols */
897dd7cddfSDavid du Colombier int hlen; /* length of hash table */
907dd7cddfSDavid du Colombier
917dd7cddfSDavid du Colombier Dfile *next; /* hash chain */
927dd7cddfSDavid du Colombier char *path; /* path name of dependency file */
937dd7cddfSDavid du Colombier Qid qid; /* qid of the dependency file */
947dd7cddfSDavid du Colombier };
957dd7cddfSDavid du Colombier
967dd7cddfSDavid du Colombier struct Fid
977dd7cddfSDavid du Colombier {
987dd7cddfSDavid du Colombier Fid *next;
997dd7cddfSDavid du Colombier int fid;
1007dd7cddfSDavid du Colombier int ref;
1017dd7cddfSDavid du Colombier
1027dd7cddfSDavid du Colombier int attached;
1037dd7cddfSDavid du Colombier int open;
1047dd7cddfSDavid du Colombier Qid qid;
1057dd7cddfSDavid du Colombier char *path;
1067dd7cddfSDavid du Colombier Dfile *df;
1077dd7cddfSDavid du Colombier Symbol *dp;
1087dd7cddfSDavid du Colombier int fd;
1099a747e4fSDavid du Colombier Dir *dir;
1109a747e4fSDavid du Colombier int ndir;
1119a747e4fSDavid du Colombier int dirindex;
1127dd7cddfSDavid du Colombier };
1137dd7cddfSDavid du Colombier
1147dd7cddfSDavid du Colombier struct Request
1157dd7cddfSDavid du Colombier {
1167dd7cddfSDavid du Colombier Request *next;
1177dd7cddfSDavid du Colombier Fid *fid;
1187dd7cddfSDavid du Colombier Fcall f;
1199a747e4fSDavid du Colombier uchar buf[1];
1207dd7cddfSDavid du Colombier };
1217dd7cddfSDavid du Colombier
1227dd7cddfSDavid du Colombier enum
1237dd7cddfSDavid du Colombier {
1247dd7cddfSDavid du Colombier Tblocksize= 512, /* tar block size */
1257dd7cddfSDavid du Colombier Tnamesize= 100, /* tar name size */
1267dd7cddfSDavid du Colombier };
1277dd7cddfSDavid du Colombier
1287dd7cddfSDavid du Colombier struct Tardir
1297dd7cddfSDavid du Colombier {
1307dd7cddfSDavid du Colombier char name[Tnamesize];
1317dd7cddfSDavid du Colombier char mode[8];
1327dd7cddfSDavid du Colombier char uid[8];
1337dd7cddfSDavid du Colombier char gid[8];
1347dd7cddfSDavid du Colombier char size[12];
1357dd7cddfSDavid du Colombier char mtime[12];
1367dd7cddfSDavid du Colombier char chksum[8];
1377dd7cddfSDavid du Colombier char linkflag;
1387dd7cddfSDavid du Colombier char linkname[Tnamesize];
1397dd7cddfSDavid du Colombier };
1407dd7cddfSDavid du Colombier
1417dd7cddfSDavid du Colombier struct Fs
1427dd7cddfSDavid du Colombier {
1437dd7cddfSDavid du Colombier Lock;
1447dd7cddfSDavid du Colombier
1457dd7cddfSDavid du Colombier int fd; /* to kernel mount point */
1467dd7cddfSDavid du Colombier Fid *hash[Nfidhash];
1477dd7cddfSDavid du Colombier char *root;
1487dd7cddfSDavid du Colombier Qid rootqid;
1497dd7cddfSDavid du Colombier
1507dd7cddfSDavid du Colombier };
1517dd7cddfSDavid du Colombier
1527dd7cddfSDavid du Colombier struct Fsarg
1537dd7cddfSDavid du Colombier {
1547dd7cddfSDavid du Colombier Fs *fs;
1557dd7cddfSDavid du Colombier int fd;
1567dd7cddfSDavid du Colombier char *root;
1577dd7cddfSDavid du Colombier };
1587dd7cddfSDavid du Colombier
1597dd7cddfSDavid du Colombier
1607dd7cddfSDavid du Colombier extern void fsrun(void*);
1617dd7cddfSDavid du Colombier extern Fid* fsgetfid(Fs*, int);
1627dd7cddfSDavid du Colombier extern void fsputfid(Fs*, Fid*);
1637dd7cddfSDavid du Colombier extern void fsreply(Fs*, Request*, char*);
1649a747e4fSDavid du Colombier extern void fsversion(Fs*, Request*, Fid*);
1659a747e4fSDavid du Colombier extern void fsauth(Fs*, Request*, Fid*);
1667dd7cddfSDavid du Colombier extern void fsflush(Fs*, Request*, Fid*);
1677dd7cddfSDavid du Colombier extern void fsattach(Fs*, Request*, Fid*);
1687dd7cddfSDavid du Colombier extern void fswalk(Fs*, Request*, Fid*);
1697dd7cddfSDavid du Colombier extern void fsopen(Fs*, Request*, Fid*);
1707dd7cddfSDavid du Colombier extern void fscreate(Fs*, Request*, Fid*);
1717dd7cddfSDavid du Colombier extern void fsread(Fs*, Request*, Fid*);
1727dd7cddfSDavid du Colombier extern void fswrite(Fs*, Request*, Fid*);
1737dd7cddfSDavid du Colombier extern void fsclunk(Fs*, Request*, Fid*);
1747dd7cddfSDavid du Colombier extern void fsremove(Fs*, Request*, Fid*);
1757dd7cddfSDavid du Colombier extern void fsstat(Fs*, Request*, Fid*);
1767dd7cddfSDavid du Colombier extern void fswstat(Fs*, Request*, Fid*);
1777dd7cddfSDavid du Colombier
1787dd7cddfSDavid du Colombier void (*fcall[])(Fs*, Request*, Fid*) =
1797dd7cddfSDavid du Colombier {
1807dd7cddfSDavid du Colombier [Tflush] fsflush,
1819a747e4fSDavid du Colombier [Tversion] fsversion,
1829a747e4fSDavid du Colombier [Tauth] fsauth,
1837dd7cddfSDavid du Colombier [Tattach] fsattach,
1847dd7cddfSDavid du Colombier [Twalk] fswalk,
1857dd7cddfSDavid du Colombier [Topen] fsopen,
1867dd7cddfSDavid du Colombier [Tcreate] fscreate,
1877dd7cddfSDavid du Colombier [Tread] fsread,
1887dd7cddfSDavid du Colombier [Twrite] fswrite,
1897dd7cddfSDavid du Colombier [Tclunk] fsclunk,
1907dd7cddfSDavid du Colombier [Tremove] fsremove,
1917dd7cddfSDavid du Colombier [Tstat] fsstat,
1927dd7cddfSDavid du Colombier [Twstat] fswstat
1937dd7cddfSDavid du Colombier };
1947dd7cddfSDavid du Colombier
1957dd7cddfSDavid du Colombier char Eperm[] = "permission denied";
1967dd7cddfSDavid du Colombier char Eexist[] = "file does not exist";
1977dd7cddfSDavid du Colombier char Enotdir[] = "not a directory";
1987dd7cddfSDavid du Colombier char Eisopen[] = "file already open";
1997dd7cddfSDavid du Colombier char Enofid[] = "no such fid";
2007dd7cddfSDavid du Colombier char mallocerr[] = "malloc: %r";
2019a747e4fSDavid du Colombier char Etoolong[] = "name too long";
2027dd7cddfSDavid du Colombier
2037dd7cddfSDavid du Colombier char *dependlog = "depend";
2047dd7cddfSDavid du Colombier
2057dd7cddfSDavid du Colombier int debug;
2067dd7cddfSDavid du Colombier Dfile *dfhash[Ndfhash]; /* dependency file hash */
2077dd7cddfSDavid du Colombier QLock dfhlock[Ndfhash];
2089a747e4fSDavid du Colombier QLock iolock;
2097dd7cddfSDavid du Colombier
2107dd7cddfSDavid du Colombier Request* allocreq(int);
2117dd7cddfSDavid du Colombier Dfile* getdf(char*);
2127dd7cddfSDavid du Colombier void releasedf(Dfile*);
2137dd7cddfSDavid du Colombier Symbol* dfsearch(Dfile*, char*);
2147dd7cddfSDavid du Colombier void dfresolve(Dfile*, int);
2157dd7cddfSDavid du Colombier char* mkpath(char*, char*);
2169a747e4fSDavid du Colombier int mktar(Dfile*, Symbol*, uchar*, uint, int);
2177dd7cddfSDavid du Colombier void closetar(Dfile*, Symbol*);
2187dd7cddfSDavid du Colombier
2197dd7cddfSDavid du Colombier void*
emalloc(uint n)2207dd7cddfSDavid du Colombier emalloc(uint n)
2217dd7cddfSDavid du Colombier {
2227dd7cddfSDavid du Colombier void *p;
2237dd7cddfSDavid du Colombier
2247dd7cddfSDavid du Colombier p = malloc(n);
2257dd7cddfSDavid du Colombier if(p == nil)
2267dd7cddfSDavid du Colombier fatal(mallocerr);
2277dd7cddfSDavid du Colombier memset(p, 0, n);
2287dd7cddfSDavid du Colombier return p;
2297dd7cddfSDavid du Colombier }
2307dd7cddfSDavid du Colombier
2319a747e4fSDavid du Colombier void *
erealloc(void * ReallocP,int ReallocN)2329a747e4fSDavid du Colombier erealloc(void *ReallocP, int ReallocN)
2339a747e4fSDavid du Colombier {
2349a747e4fSDavid du Colombier if(ReallocN == 0)
2359a747e4fSDavid du Colombier ReallocN = 1;
2369a747e4fSDavid du Colombier if(!ReallocP)
2379a747e4fSDavid du Colombier ReallocP = emalloc(ReallocN);
2389a747e4fSDavid du Colombier else if(!(ReallocP = realloc(ReallocP, ReallocN)))
2399a747e4fSDavid du Colombier fatal("unable to allocate %d bytes",ReallocN);
2409a747e4fSDavid du Colombier return(ReallocP);
2419a747e4fSDavid du Colombier }
2429a747e4fSDavid du Colombier
2439a747e4fSDavid du Colombier char*
estrdup(char * s)2449a747e4fSDavid du Colombier estrdup(char *s)
2459a747e4fSDavid du Colombier {
2469a747e4fSDavid du Colombier char *d, *d0;
2479a747e4fSDavid du Colombier
2489a747e4fSDavid du Colombier if(!s)
2499a747e4fSDavid du Colombier return 0;
2509a747e4fSDavid du Colombier d = d0 = emalloc(strlen(s)+1);
2519a747e4fSDavid du Colombier while(*d++ = *s++)
2529a747e4fSDavid du Colombier ;
2539a747e4fSDavid du Colombier return d0;
2549a747e4fSDavid du Colombier }
2559a747e4fSDavid du Colombier
2567dd7cddfSDavid du Colombier /*
2577dd7cddfSDavid du Colombier * mount the user interface and start one request processor
2587dd7cddfSDavid du Colombier * per CPU
2597dd7cddfSDavid du Colombier */
2607dd7cddfSDavid du Colombier void
realmain(void * a)2617dd7cddfSDavid du Colombier realmain(void *a)
2627dd7cddfSDavid du Colombier {
2637dd7cddfSDavid du Colombier Fs *fs;
2647dd7cddfSDavid du Colombier int pfd[2];
2657dd7cddfSDavid du Colombier int srv;
2669a747e4fSDavid du Colombier char service[128];
2677dd7cddfSDavid du Colombier struct Fsarg fsarg;
26873e742d7SDavid du Colombier Args *args;
2697dd7cddfSDavid du Colombier int argc;
2707dd7cddfSDavid du Colombier char **argv;
2717dd7cddfSDavid du Colombier
27273e742d7SDavid du Colombier args = a;
27373e742d7SDavid du Colombier argc = args->argc;
27473e742d7SDavid du Colombier argv = args->argv;
2757dd7cddfSDavid du Colombier
2769a747e4fSDavid du Colombier fmtinstall('F', fcallfmt);
2777dd7cddfSDavid du Colombier
2787dd7cddfSDavid du Colombier ARGBEGIN{
2797dd7cddfSDavid du Colombier case 'd':
2807dd7cddfSDavid du Colombier debug++;
2817dd7cddfSDavid du Colombier break;
2827dd7cddfSDavid du Colombier }ARGEND
2837dd7cddfSDavid du Colombier if(argc != 2){
28473e742d7SDavid du Colombier fprint(2, "usage: %s [-d] svc-name directory\n", argv0);
2857dd7cddfSDavid du Colombier exits("usage");
2867dd7cddfSDavid du Colombier }
2879a747e4fSDavid du Colombier snprint(service, sizeof service, "#s/%s", argv[0]);
2887dd7cddfSDavid du Colombier if(argv[1][0] != '/')
2897dd7cddfSDavid du Colombier fatal("directory must be rooted");
2907dd7cddfSDavid du Colombier
2917dd7cddfSDavid du Colombier if(pipe(pfd) < 0)
2927dd7cddfSDavid du Colombier fatal("opening pipe: %r");
2937dd7cddfSDavid du Colombier
2947dd7cddfSDavid du Colombier /* Typically mounted before /srv exists */
2957dd7cddfSDavid du Colombier srv = create(service, OWRITE, 0666);
2967dd7cddfSDavid du Colombier if(srv < 0)
2977dd7cddfSDavid du Colombier fatal("post: %r");
2989a747e4fSDavid du Colombier fprint(srv, "%d", pfd[1]);
2997dd7cddfSDavid du Colombier close(srv);
3007dd7cddfSDavid du Colombier close(pfd[1]);
3017dd7cddfSDavid du Colombier
3027dd7cddfSDavid du Colombier time(nil); /* open fd for time before losing / */
3037dd7cddfSDavid du Colombier if(bind(argv[1], "/", MREPL) == 0)
3047dd7cddfSDavid du Colombier fatal("can't bind %s to /", argv[1]);
3057dd7cddfSDavid du Colombier
3067dd7cddfSDavid du Colombier fs = emalloc(sizeof(Fs));
3077dd7cddfSDavid du Colombier fsarg.fs = fs;
3087dd7cddfSDavid du Colombier fsarg.fd = pfd[0];
3097dd7cddfSDavid du Colombier fsarg.root = argv[1];
3107dd7cddfSDavid du Colombier proccreate(fsrun, &fsarg, 16*1024);
3117dd7cddfSDavid du Colombier proccreate(fsrun, &fsarg, 16*1024);
3127dd7cddfSDavid du Colombier fsrun(&fsarg);
3137dd7cddfSDavid du Colombier exits(nil);
3147dd7cddfSDavid du Colombier }
3157dd7cddfSDavid du Colombier
3167dd7cddfSDavid du Colombier void
threadmain(int argc,char * argv[])3177dd7cddfSDavid du Colombier threadmain(int argc, char *argv[])
3187dd7cddfSDavid du Colombier {
31973e742d7SDavid du Colombier static Args args;
3207dd7cddfSDavid du Colombier
32173e742d7SDavid du Colombier args.argc = argc;
32273e742d7SDavid du Colombier args.argv = argv;
3239a747e4fSDavid du Colombier rfork(RFNAMEG);
32473e742d7SDavid du Colombier proccreate(realmain, &args, 16*1024);
3257dd7cddfSDavid du Colombier }
3267dd7cddfSDavid du Colombier
3277dd7cddfSDavid du Colombier char*
mkpath(char * dir,char * file)3287dd7cddfSDavid du Colombier mkpath(char *dir, char *file)
3297dd7cddfSDavid du Colombier {
3307dd7cddfSDavid du Colombier int len;
3317dd7cddfSDavid du Colombier char *path;
3327dd7cddfSDavid du Colombier
3337dd7cddfSDavid du Colombier len = strlen(dir) + 1;
3347dd7cddfSDavid du Colombier if(file != nil)
3357dd7cddfSDavid du Colombier len += strlen(file) + 1;
3367dd7cddfSDavid du Colombier path = emalloc(len);
3377dd7cddfSDavid du Colombier if(file != nil)
3387dd7cddfSDavid du Colombier sprint(path, "%s/%s", dir, file);
3397dd7cddfSDavid du Colombier else
3407dd7cddfSDavid du Colombier sprint(path, "%s", dir);
3417dd7cddfSDavid du Colombier return path;
3427dd7cddfSDavid du Colombier }
3437dd7cddfSDavid du Colombier
3447dd7cddfSDavid du Colombier void
fsrun(void * a)3457dd7cddfSDavid du Colombier fsrun(void *a)
3467dd7cddfSDavid du Colombier {
3477dd7cddfSDavid du Colombier struct Fsarg *fsarg;
3487dd7cddfSDavid du Colombier Fs* fs;
3497dd7cddfSDavid du Colombier char *root;
3507dd7cddfSDavid du Colombier int n, t;
3517dd7cddfSDavid du Colombier Request *r;
3527dd7cddfSDavid du Colombier Fid *f;
3539a747e4fSDavid du Colombier Dir *d;
3547dd7cddfSDavid du Colombier
3557dd7cddfSDavid du Colombier fsarg = a;
3567dd7cddfSDavid du Colombier fs = fsarg->fs;
3577dd7cddfSDavid du Colombier fs->fd = fsarg->fd;
3587dd7cddfSDavid du Colombier root = fsarg->root;
3599a747e4fSDavid du Colombier d = dirstat("/");
3609a747e4fSDavid du Colombier if(d == nil)
3617dd7cddfSDavid du Colombier fatal("root %s inaccessible: %r", root);
3629a747e4fSDavid du Colombier fs->rootqid = d->qid;
3639a747e4fSDavid du Colombier free(d);
3647dd7cddfSDavid du Colombier
3657dd7cddfSDavid du Colombier for(;;){
3669a747e4fSDavid du Colombier r = allocreq(messagesize);
3679a747e4fSDavid du Colombier qlock(&iolock);
3689a747e4fSDavid du Colombier n = read9pmsg(fs->fd, r->buf, messagesize);
3699a747e4fSDavid du Colombier qunlock(&iolock);
3707dd7cddfSDavid du Colombier if(n <= 0)
3719a747e4fSDavid du Colombier fatal("read9pmsg error: %r");
3727dd7cddfSDavid du Colombier
3739a747e4fSDavid du Colombier if(convM2S(r->buf, n, &r->f) == 0){
3749a747e4fSDavid du Colombier fprint(2, "can't convert %ux %ux %ux\n", r->buf[0],
3757dd7cddfSDavid du Colombier r->buf[1], r->buf[2]);
3767dd7cddfSDavid du Colombier free(r);
3777dd7cddfSDavid du Colombier continue;
3787dd7cddfSDavid du Colombier }
3797dd7cddfSDavid du Colombier
3807dd7cddfSDavid du Colombier f = fsgetfid(fs, r->f.fid);
3817dd7cddfSDavid du Colombier r->fid = f;
3827dd7cddfSDavid du Colombier if(debug)
3839a747e4fSDavid du Colombier fprint(2, "%F path %llux\n", &r->f, f->qid.path);
3847dd7cddfSDavid du Colombier
3857dd7cddfSDavid du Colombier t = r->f.type;
3867dd7cddfSDavid du Colombier r->f.type++;
3877dd7cddfSDavid du Colombier (*fcall[t])(fs, r, f);
3887dd7cddfSDavid du Colombier fsputfid(fs, f);
3897dd7cddfSDavid du Colombier }
3907dd7cddfSDavid du Colombier
3917dd7cddfSDavid du Colombier }
3927dd7cddfSDavid du Colombier
3937dd7cddfSDavid du Colombier /*
3947dd7cddfSDavid du Colombier * any request that can get queued for a delayed reply
3957dd7cddfSDavid du Colombier */
3967dd7cddfSDavid du Colombier Request*
allocreq(int bufsize)3977dd7cddfSDavid du Colombier allocreq(int bufsize)
3987dd7cddfSDavid du Colombier {
3997dd7cddfSDavid du Colombier Request *r;
4007dd7cddfSDavid du Colombier
4017dd7cddfSDavid du Colombier r = emalloc(sizeof(Request)+bufsize);
4027dd7cddfSDavid du Colombier r->next = nil;
4037dd7cddfSDavid du Colombier return r;
4047dd7cddfSDavid du Colombier }
4057dd7cddfSDavid du Colombier
4067dd7cddfSDavid du Colombier Fid*
fsgetfid(Fs * fs,int fid)4077dd7cddfSDavid du Colombier fsgetfid(Fs *fs, int fid)
4087dd7cddfSDavid du Colombier {
4097dd7cddfSDavid du Colombier Fid *f, *nf;
4107dd7cddfSDavid du Colombier
4117dd7cddfSDavid du Colombier lock(fs);
4127dd7cddfSDavid du Colombier for(f = fs->hash[fid%Nfidhash]; f; f = f->next){
4137dd7cddfSDavid du Colombier if(f->fid == fid){
4147dd7cddfSDavid du Colombier f->ref++;
4157dd7cddfSDavid du Colombier unlock(fs);
4167dd7cddfSDavid du Colombier return f;
4177dd7cddfSDavid du Colombier }
4187dd7cddfSDavid du Colombier }
4197dd7cddfSDavid du Colombier
4207dd7cddfSDavid du Colombier nf = emalloc(sizeof(Fid));
4217dd7cddfSDavid du Colombier nf->next = fs->hash[fid%Nfidhash];
4227dd7cddfSDavid du Colombier fs->hash[fid%Nfidhash] = nf;
4237dd7cddfSDavid du Colombier nf->fid = fid;
4247dd7cddfSDavid du Colombier nf->ref = 1;
4257dd7cddfSDavid du Colombier nf->fd = -1;
4267dd7cddfSDavid du Colombier unlock(fs);
4277dd7cddfSDavid du Colombier return nf;
4287dd7cddfSDavid du Colombier }
4297dd7cddfSDavid du Colombier
4307dd7cddfSDavid du Colombier void
fsputfid(Fs * fs,Fid * f)4317dd7cddfSDavid du Colombier fsputfid(Fs *fs, Fid *f)
4327dd7cddfSDavid du Colombier {
4337dd7cddfSDavid du Colombier Fid **l, *nf;
4347dd7cddfSDavid du Colombier
4357dd7cddfSDavid du Colombier lock(fs);
4367dd7cddfSDavid du Colombier if(--f->ref > 0){
4377dd7cddfSDavid du Colombier unlock(fs);
4387dd7cddfSDavid du Colombier return;
4397dd7cddfSDavid du Colombier }
4407dd7cddfSDavid du Colombier for(l = &fs->hash[f->fid%Nfidhash]; nf = *l; l = &nf->next)
4417dd7cddfSDavid du Colombier if(nf == f){
4427dd7cddfSDavid du Colombier *l = f->next;
4437dd7cddfSDavid du Colombier break;
4447dd7cddfSDavid du Colombier }
4457dd7cddfSDavid du Colombier unlock(fs);
4467dd7cddfSDavid du Colombier free(f);
4477dd7cddfSDavid du Colombier }
4487dd7cddfSDavid du Colombier
4497dd7cddfSDavid du Colombier void
fsreply(Fs * fs,Request * r,char * err)4507dd7cddfSDavid du Colombier fsreply(Fs *fs, Request *r, char *err)
4517dd7cddfSDavid du Colombier {
4527dd7cddfSDavid du Colombier int n;
4539a747e4fSDavid du Colombier uchar buf[MAXSIZE];
4547dd7cddfSDavid du Colombier
4557dd7cddfSDavid du Colombier if(err){
4567dd7cddfSDavid du Colombier r->f.type = Rerror;
4579a747e4fSDavid du Colombier r->f.ename = err;
4587dd7cddfSDavid du Colombier }
4597dd7cddfSDavid du Colombier if(debug)
4609a747e4fSDavid du Colombier fprint(2, "%F path %llux\n", &r->f, r->fid->qid.path);
4619a747e4fSDavid du Colombier n = convS2M(&r->f, buf, messagesize);
4629a747e4fSDavid du Colombier if(n == 0)
4639a747e4fSDavid du Colombier fatal("bad convS2M");
4647dd7cddfSDavid du Colombier if(write(fs->fd, buf, n) != n)
4657dd7cddfSDavid du Colombier fatal("unmounted");
4667dd7cddfSDavid du Colombier free(r);
4677dd7cddfSDavid du Colombier }
4687dd7cddfSDavid du Colombier
4697dd7cddfSDavid du Colombier void
fsversion(Fs * fs,Request * r,Fid *)4709a747e4fSDavid du Colombier fsversion(Fs *fs, Request *r, Fid*)
4717dd7cddfSDavid du Colombier {
4729a747e4fSDavid du Colombier if(r->f.msize < 256){
4739a747e4fSDavid du Colombier fsreply(fs, r, "version: bad message size");
4749a747e4fSDavid du Colombier return;
4759a747e4fSDavid du Colombier }
4769a747e4fSDavid du Colombier if(messagesize > r->f.msize)
4779a747e4fSDavid du Colombier messagesize = r->f.msize;
4789a747e4fSDavid du Colombier r->f.msize = messagesize;
4799a747e4fSDavid du Colombier r->f.version = "9P2000";
4807dd7cddfSDavid du Colombier fsreply(fs, r, nil);
4817dd7cddfSDavid du Colombier }
4827dd7cddfSDavid du Colombier
4837dd7cddfSDavid du Colombier void
fsauth(Fs * fs,Request * r,Fid *)4849a747e4fSDavid du Colombier fsauth(Fs *fs, Request *r, Fid*)
4857dd7cddfSDavid du Colombier {
4869a747e4fSDavid du Colombier fsreply(fs, r, "depend: authentication not required");
4877dd7cddfSDavid du Colombier }
4887dd7cddfSDavid du Colombier
4897dd7cddfSDavid du Colombier void
fsflush(Fs *,Request *,Fid *)4907dd7cddfSDavid du Colombier fsflush(Fs*, Request*, Fid*)
4917dd7cddfSDavid du Colombier {
4927dd7cddfSDavid du Colombier }
4937dd7cddfSDavid du Colombier
4947dd7cddfSDavid du Colombier void
fsattach(Fs * fs,Request * r,Fid * f)4957dd7cddfSDavid du Colombier fsattach(Fs *fs, Request *r, Fid *f)
4967dd7cddfSDavid du Colombier {
4977dd7cddfSDavid du Colombier f->qid = fs->rootqid;
4987dd7cddfSDavid du Colombier f->path = strdup("/");
4997dd7cddfSDavid du Colombier f->df = getdf(mkpath(f->path, ".depend"));
5007dd7cddfSDavid du Colombier
5017dd7cddfSDavid du Colombier /* hold down the fid till the clunk */
5027dd7cddfSDavid du Colombier f->attached = 1;
5037dd7cddfSDavid du Colombier lock(fs);
5047dd7cddfSDavid du Colombier f->ref++;
5057dd7cddfSDavid du Colombier unlock(fs);
5067dd7cddfSDavid du Colombier
5077dd7cddfSDavid du Colombier r->f.qid = f->qid;
5087dd7cddfSDavid du Colombier fsreply(fs, r, nil);
5097dd7cddfSDavid du Colombier }
5107dd7cddfSDavid du Colombier
5117dd7cddfSDavid du Colombier void
fswalk(Fs * fs,Request * r,Fid * f)5129a747e4fSDavid du Colombier fswalk(Fs *fs, Request *r, Fid *f)
5139a747e4fSDavid du Colombier {
5149a747e4fSDavid du Colombier Fid *nf;
5159a747e4fSDavid du Colombier char *name, *tmp;
5169a747e4fSDavid du Colombier int i, nqid, nwname;
5179a747e4fSDavid du Colombier char errbuf[ERRMAX], *err;
5189a747e4fSDavid du Colombier Qid qid[MAXWELEM];
5199a747e4fSDavid du Colombier Dfile *lastdf;
5209a747e4fSDavid du Colombier char *path, *npath;
5219a747e4fSDavid du Colombier Dir *d;
5229a747e4fSDavid du Colombier Symbol *dp;
5239a747e4fSDavid du Colombier
5249a747e4fSDavid du Colombier if(f->attached == 0){
5259a747e4fSDavid du Colombier fsreply(fs, r, Eexist);
5269a747e4fSDavid du Colombier return;
5279a747e4fSDavid du Colombier }
5289a747e4fSDavid du Colombier
5299a747e4fSDavid du Colombier if(f->fd >= 0 || f->open)
5309a747e4fSDavid du Colombier fatal("walk of an open file");
5319a747e4fSDavid du Colombier
5329a747e4fSDavid du Colombier nf = nil;
5339a747e4fSDavid du Colombier if(r->f.newfid != r->f.fid){
5349a747e4fSDavid du Colombier nf = fsgetfid(fs, r->f.newfid);
5359a747e4fSDavid du Colombier nf->attached = 1;
5369a747e4fSDavid du Colombier nf->open = f->open;
5379a747e4fSDavid du Colombier nf->path = strdup(f->path);
5389a747e4fSDavid du Colombier nf->qid = f->qid;
5399a747e4fSDavid du Colombier nf->dp = f->dp;
5409a747e4fSDavid du Colombier nf->fd = f->fd;
5419a747e4fSDavid du Colombier nf->df = f->df;
5429a747e4fSDavid du Colombier if(nf->df){
5439a747e4fSDavid du Colombier lock(nf->df);
5449a747e4fSDavid du Colombier nf->df->use++;
5459a747e4fSDavid du Colombier unlock(nf->df);
5469a747e4fSDavid du Colombier }
5479a747e4fSDavid du Colombier if(r->f.nwname == 0){
5489a747e4fSDavid du Colombier r->f.nwqid = 0;
5499a747e4fSDavid du Colombier fsreply(fs, r, nil);
5509a747e4fSDavid du Colombier return;
5519a747e4fSDavid du Colombier }
5529a747e4fSDavid du Colombier f = nf;
5539a747e4fSDavid du Colombier }
5549a747e4fSDavid du Colombier
5559a747e4fSDavid du Colombier err = nil;
5569a747e4fSDavid du Colombier path = strdup(f->path);
5579a747e4fSDavid du Colombier if(path == nil)
5589a747e4fSDavid du Colombier fatal(mallocerr);
5599a747e4fSDavid du Colombier nqid = 0;
5609a747e4fSDavid du Colombier nwname = r->f.nwname;
5619a747e4fSDavid du Colombier lastdf = f->df;
5629a747e4fSDavid du Colombier
5639a747e4fSDavid du Colombier if(nwname > 0){
5649a747e4fSDavid du Colombier for(; nqid<nwname; nqid++){
5659a747e4fSDavid du Colombier name = r->f.wname[nqid];
5669a747e4fSDavid du Colombier
5679a747e4fSDavid du Colombier if(strcmp(name, ".") == 0){
5689a747e4fSDavid du Colombier Noop:
5699a747e4fSDavid du Colombier if(nqid == 0)
5709a747e4fSDavid du Colombier qid[nqid] = f->qid;
5719a747e4fSDavid du Colombier else
5729a747e4fSDavid du Colombier qid[nqid] = qid[nqid-1];
5739a747e4fSDavid du Colombier continue;
5749a747e4fSDavid du Colombier }
5759a747e4fSDavid du Colombier
5769a747e4fSDavid du Colombier if(strcmp(name, "..") == 0){
5779a747e4fSDavid du Colombier name = strrchr(path, '/');
5789a747e4fSDavid du Colombier if(name){
5799a747e4fSDavid du Colombier if(name == path) /* at root */
5809a747e4fSDavid du Colombier goto Noop;
5819a747e4fSDavid du Colombier *name = '\0';
5829a747e4fSDavid du Colombier }
5839a747e4fSDavid du Colombier d = dirstat(path);
5849a747e4fSDavid du Colombier if(d == nil){
5859a747e4fSDavid du Colombier *name = '/';
5869a747e4fSDavid du Colombier errstr(errbuf, sizeof errbuf);
5879a747e4fSDavid du Colombier err = errbuf;
5889a747e4fSDavid du Colombier break;
5899a747e4fSDavid du Colombier }
5909a747e4fSDavid du Colombier Directory:
5919a747e4fSDavid du Colombier qid[nqid] = d->qid;
5929a747e4fSDavid du Colombier free(d);
5939a747e4fSDavid du Colombier releasedf(lastdf);
5949a747e4fSDavid du Colombier lastdf = getdf(mkpath(path, ".depend"));
5959a747e4fSDavid du Colombier continue;
5969a747e4fSDavid du Colombier }
5979a747e4fSDavid du Colombier
5989a747e4fSDavid du Colombier npath = mkpath(path, name);
5999a747e4fSDavid du Colombier free(path);
6009a747e4fSDavid du Colombier path = npath;
6019a747e4fSDavid du Colombier d = dirstat(path);
6029a747e4fSDavid du Colombier
6039a747e4fSDavid du Colombier if(d !=nil && (d->qid.type & QTDIR))
6049a747e4fSDavid du Colombier goto Directory;
6059a747e4fSDavid du Colombier free(d);
6069a747e4fSDavid du Colombier
6079a747e4fSDavid du Colombier qid[nqid].type = QTFILE;
6089a747e4fSDavid du Colombier qid[nqid].path = 0;
6099a747e4fSDavid du Colombier qid[nqid].vers = 0;
6109a747e4fSDavid du Colombier
6119a747e4fSDavid du Colombier dp = dfsearch(lastdf, name);
6129a747e4fSDavid du Colombier if(dp == nil){
6139a747e4fSDavid du Colombier tmp = strdup(name);
6149a747e4fSDavid du Colombier if(tmp == nil)
6159a747e4fSDavid du Colombier fatal("mallocerr");
6169a747e4fSDavid du Colombier i = strlen(tmp);
6179a747e4fSDavid du Colombier if(i > 4 && strcmp(&tmp[i-4], ".tar") == 0){
6189a747e4fSDavid du Colombier tmp[i-4] = 0;
6199a747e4fSDavid du Colombier dp = dfsearch(lastdf, tmp);
6209a747e4fSDavid du Colombier }
6219a747e4fSDavid du Colombier free(tmp);
6229a747e4fSDavid du Colombier }
6239a747e4fSDavid du Colombier
6249a747e4fSDavid du Colombier if(dp == nil){
6259a747e4fSDavid du Colombier err = Eexist;
6269a747e4fSDavid du Colombier break;
6279a747e4fSDavid du Colombier }
6285e91980fSDavid du Colombier qid[nqid].path = (uvlong)dp;
6299a747e4fSDavid du Colombier qid[nqid].vers = 0;
6309a747e4fSDavid du Colombier }
6319a747e4fSDavid du Colombier if(nqid == 0 && err == nil)
6329a747e4fSDavid du Colombier err = "file does not exist";
6339a747e4fSDavid du Colombier }
6349a747e4fSDavid du Colombier
6359a747e4fSDavid du Colombier /* for error or partial success, put the cloned fid back*/
6369a747e4fSDavid du Colombier if(nf!=nil && (err != nil || nqid < nwname)){
6379a747e4fSDavid du Colombier releasedf(nf->df);
6389a747e4fSDavid du Colombier nf->df = nil;
6399a747e4fSDavid du Colombier fsputfid(fs, nf);
6409a747e4fSDavid du Colombier }
6419a747e4fSDavid du Colombier
6429a747e4fSDavid du Colombier if(err == nil){
6439a747e4fSDavid du Colombier /* return (possibly short) list of qids */
6449a747e4fSDavid du Colombier for(i=0; i<nqid; i++)
6459a747e4fSDavid du Colombier r->f.wqid[i] = qid[i];
6469a747e4fSDavid du Colombier r->f.nwqid = nqid;
6479a747e4fSDavid du Colombier
6489a747e4fSDavid du Colombier /* for full success, advance f */
6499a747e4fSDavid du Colombier if(nqid > 0 && nqid == nwname){
6509a747e4fSDavid du Colombier free(f->path);
6519a747e4fSDavid du Colombier f->path = path;
6529a747e4fSDavid du Colombier path = nil;
6539a747e4fSDavid du Colombier
6549a747e4fSDavid du Colombier f->qid = qid[nqid-1];
6559a747e4fSDavid du Colombier f->dp = (Symbol*)f->qid.path;
6569a747e4fSDavid du Colombier
6579a747e4fSDavid du Colombier if(f->df != lastdf){
6589a747e4fSDavid du Colombier releasedf(f->df);
6599a747e4fSDavid du Colombier f->df = lastdf;
6609a747e4fSDavid du Colombier lastdf = nil;
6619a747e4fSDavid du Colombier }
6629a747e4fSDavid du Colombier
6639a747e4fSDavid du Colombier }
6649a747e4fSDavid du Colombier }
6659a747e4fSDavid du Colombier
6669a747e4fSDavid du Colombier releasedf(lastdf);
6679a747e4fSDavid du Colombier free(path);
6689a747e4fSDavid du Colombier
6699a747e4fSDavid du Colombier fsreply(fs, r, err);
6709a747e4fSDavid du Colombier }
6719a747e4fSDavid du Colombier
6729a747e4fSDavid du Colombier #ifdef adf
6739a747e4fSDavid du Colombier void
fsclone(Fs * fs,Request * r,Fid * f)6747dd7cddfSDavid du Colombier fsclone(Fs *fs, Request *r, Fid *f)
6757dd7cddfSDavid du Colombier {
6767dd7cddfSDavid du Colombier Fid *nf;
6777dd7cddfSDavid du Colombier
6787dd7cddfSDavid du Colombier if(f->attached == 0){
6797dd7cddfSDavid du Colombier fsreply(fs, r, Eexist);
6807dd7cddfSDavid du Colombier return;
6817dd7cddfSDavid du Colombier }
6827dd7cddfSDavid du Colombier nf = fsgetfid(fs, r->f.newfid);
6837dd7cddfSDavid du Colombier
6847dd7cddfSDavid du Colombier nf->attached = 1;
6857dd7cddfSDavid du Colombier nf->open = f->open;
6867dd7cddfSDavid du Colombier nf->path = strdup(f->path);
6877dd7cddfSDavid du Colombier nf->qid = f->qid;
6887dd7cddfSDavid du Colombier nf->dp = f->dp;
6897dd7cddfSDavid du Colombier nf->fd = f->fd;
6907dd7cddfSDavid du Colombier nf->df = f->df;
6917dd7cddfSDavid du Colombier if(nf->df){
6927dd7cddfSDavid du Colombier lock(nf->df);
6937dd7cddfSDavid du Colombier nf->df->use++;
6947dd7cddfSDavid du Colombier unlock(nf->df);
6957dd7cddfSDavid du Colombier }
6967dd7cddfSDavid du Colombier fsreply(fs, r, nil);
6977dd7cddfSDavid du Colombier }
6987dd7cddfSDavid du Colombier
6997dd7cddfSDavid du Colombier void
fswalk(Fs * fs,Request * r,Fid * f)7007dd7cddfSDavid du Colombier fswalk(Fs *fs, Request *r, Fid *f)
7017dd7cddfSDavid du Colombier {
7027dd7cddfSDavid du Colombier char *name;
7037dd7cddfSDavid du Colombier int i;
7047dd7cddfSDavid du Colombier Dir d;
7057dd7cddfSDavid du Colombier char errbuf[ERRLEN];
7067dd7cddfSDavid du Colombier char *path;
7077dd7cddfSDavid du Colombier Symbol *dp;
7087dd7cddfSDavid du Colombier
7097dd7cddfSDavid du Colombier if(f->attached == 0){
7107dd7cddfSDavid du Colombier fsreply(fs, r, Enofid);
7117dd7cddfSDavid du Colombier return;
7127dd7cddfSDavid du Colombier }
7137dd7cddfSDavid du Colombier
7147dd7cddfSDavid du Colombier if(f->fd >= 0 || f->open)
7157dd7cddfSDavid du Colombier fatal("walk of an open file");
7167dd7cddfSDavid du Colombier
7177dd7cddfSDavid du Colombier name = r->f.name;
7187dd7cddfSDavid du Colombier if(strcmp(name, ".") == 0){
7197dd7cddfSDavid du Colombier fsreply(fs, r, nil);
7207dd7cddfSDavid du Colombier return;
7217dd7cddfSDavid du Colombier }
7227dd7cddfSDavid du Colombier if(strcmp(name, "..") == 0){
7237dd7cddfSDavid du Colombier name = strrchr(f->path, '/');
7247dd7cddfSDavid du Colombier if(name){
7257dd7cddfSDavid du Colombier if(name == f->path){
7267dd7cddfSDavid du Colombier fsreply(fs, r, nil);
7277dd7cddfSDavid du Colombier return;
7287dd7cddfSDavid du Colombier }
7297dd7cddfSDavid du Colombier *name = 0;
7307dd7cddfSDavid du Colombier }
7317dd7cddfSDavid du Colombier if(dirstat(f->path, &d) < 0){
7327dd7cddfSDavid du Colombier *name = '/';
7337dd7cddfSDavid du Colombier errstr(errbuf);
7347dd7cddfSDavid du Colombier fsreply(fs, r, errbuf);
7357dd7cddfSDavid du Colombier return;
7367dd7cddfSDavid du Colombier }
7377dd7cddfSDavid du Colombier r->f.qid = f->qid = d.qid;
7387dd7cddfSDavid du Colombier
7397dd7cddfSDavid du Colombier releasedf(f->df);
7407dd7cddfSDavid du Colombier f->df = getdf(mkpath(f->path, ".depend"));
7417dd7cddfSDavid du Colombier
7427dd7cddfSDavid du Colombier fsreply(fs, r, nil);
7437dd7cddfSDavid du Colombier return;
7447dd7cddfSDavid du Colombier }
7457dd7cddfSDavid du Colombier
7467dd7cddfSDavid du Colombier path = mkpath(f->path, name);
7477dd7cddfSDavid du Colombier if(dirstat(path, &d) < 0 || (d.qid.path & CHDIR) == 0){
7487dd7cddfSDavid du Colombier dp = dfsearch(f->df, name);
7497dd7cddfSDavid du Colombier if(dp == nil){
7507dd7cddfSDavid du Colombier i = strlen(name);
7517dd7cddfSDavid du Colombier if(i > 4 && strcmp(&name[i-4], ".tar") == 0){
7527dd7cddfSDavid du Colombier name[i-4] = 0;
7537dd7cddfSDavid du Colombier dp = dfsearch(f->df, name);
7547dd7cddfSDavid du Colombier }
7557dd7cddfSDavid du Colombier }
7567dd7cddfSDavid du Colombier if(dp == nil){
7577dd7cddfSDavid du Colombier fsreply(fs, r, Eexist);
7587dd7cddfSDavid du Colombier free(path);
7597dd7cddfSDavid du Colombier return;
7607dd7cddfSDavid du Colombier }
7617dd7cddfSDavid du Colombier f->dp = dp;
7627dd7cddfSDavid du Colombier d.qid.path = (uint)dp;
7637dd7cddfSDavid du Colombier d.qid.vers = 0;
7647dd7cddfSDavid du Colombier }
7657dd7cddfSDavid du Colombier
7667dd7cddfSDavid du Colombier free(f->path);
7677dd7cddfSDavid du Colombier f->path = path;
7687dd7cddfSDavid du Colombier
7697dd7cddfSDavid du Colombier if(d.qid.path & CHDIR){
7707dd7cddfSDavid du Colombier releasedf(f->df);
7717dd7cddfSDavid du Colombier f->df = getdf(mkpath(f->path, ".depend"));
7727dd7cddfSDavid du Colombier }
7737dd7cddfSDavid du Colombier
7747dd7cddfSDavid du Colombier r->f.qid = f->qid = d.qid;
7757dd7cddfSDavid du Colombier fsreply(fs, r, nil);
7767dd7cddfSDavid du Colombier }
7779a747e4fSDavid du Colombier #endif
7787dd7cddfSDavid du Colombier void
fsopen(Fs * fs,Request * r,Fid * f)7797dd7cddfSDavid du Colombier fsopen(Fs *fs, Request *r, Fid *f)
7807dd7cddfSDavid du Colombier {
7817dd7cddfSDavid du Colombier int mode;
7829a747e4fSDavid du Colombier char errbuf[ERRMAX];
7837dd7cddfSDavid du Colombier
7847dd7cddfSDavid du Colombier if(f->attached == 0){
7857dd7cddfSDavid du Colombier fsreply(fs, r, Enofid);
7867dd7cddfSDavid du Colombier return;
7877dd7cddfSDavid du Colombier }
7887dd7cddfSDavid du Colombier if(f->open){
7897dd7cddfSDavid du Colombier fsreply(fs, r, Eisopen);
7907dd7cddfSDavid du Colombier return;
7917dd7cddfSDavid du Colombier }
7927dd7cddfSDavid du Colombier
7937dd7cddfSDavid du Colombier mode = r->f.mode & 3;
7947dd7cddfSDavid du Colombier if(mode != OREAD){
7957dd7cddfSDavid du Colombier fsreply(fs, r, Eperm);
7967dd7cddfSDavid du Colombier return;
7977dd7cddfSDavid du Colombier }
7987dd7cddfSDavid du Colombier
7999a747e4fSDavid du Colombier if(f->qid.type & QTDIR){
8007dd7cddfSDavid du Colombier f->fd = open(f->path, OREAD);
8017dd7cddfSDavid du Colombier if(f->fd < 0){
8029a747e4fSDavid du Colombier errstr(errbuf, sizeof errbuf);
8037dd7cddfSDavid du Colombier fsreply(fs, r, errbuf);
8047dd7cddfSDavid du Colombier return;
8057dd7cddfSDavid du Colombier }
8067dd7cddfSDavid du Colombier }
8077dd7cddfSDavid du Colombier
8087dd7cddfSDavid du Colombier f->open = 1;
8097dd7cddfSDavid du Colombier r->f.qid = f->qid;
8107dd7cddfSDavid du Colombier fsreply(fs, r, nil);
8117dd7cddfSDavid du Colombier }
8127dd7cddfSDavid du Colombier
8137dd7cddfSDavid du Colombier void
fscreate(Fs * fs,Request * r,Fid *)8147dd7cddfSDavid du Colombier fscreate(Fs *fs, Request *r, Fid*)
8157dd7cddfSDavid du Colombier {
8167dd7cddfSDavid du Colombier fsreply(fs, r, Eperm);
8177dd7cddfSDavid du Colombier }
8187dd7cddfSDavid du Colombier
8197dd7cddfSDavid du Colombier void
fsread(Fs * fs,Request * r,Fid * f)8207dd7cddfSDavid du Colombier fsread(Fs *fs, Request *r, Fid *f)
8217dd7cddfSDavid du Colombier {
8229a747e4fSDavid du Colombier int i, n, len,skip;
8237dd7cddfSDavid du Colombier Dir d;
8247dd7cddfSDavid du Colombier Symbol *dp;
8259a747e4fSDavid du Colombier char buf[512];
8267dd7cddfSDavid du Colombier
8277dd7cddfSDavid du Colombier if(f->attached == 0){
8287dd7cddfSDavid du Colombier fsreply(fs, r, Enofid);
8297dd7cddfSDavid du Colombier return;
8307dd7cddfSDavid du Colombier }
831*22a127bbSDavid du Colombier if((int)r->f.count < 0){
8327dd7cddfSDavid du Colombier fsreply(fs, r, "bad read count");
8337dd7cddfSDavid du Colombier return;
8347dd7cddfSDavid du Colombier }
8357dd7cddfSDavid du Colombier
8369a747e4fSDavid du Colombier if(f->qid.type & QTDIR){
8379a747e4fSDavid du Colombier n = 0;
8389a747e4fSDavid du Colombier if(f->dir == nil){
8399a747e4fSDavid du Colombier f->ndir = dirreadall(f->fd, &f->dir);
8409a747e4fSDavid du Colombier f->dirindex = 0;
8417dd7cddfSDavid du Colombier }
8429a747e4fSDavid du Colombier if(f->dir == nil)
8439a747e4fSDavid du Colombier goto Return;
8449a747e4fSDavid du Colombier if(r->f.offset == 0) /* seeking to zero is permitted */
8459a747e4fSDavid du Colombier f->dirindex = 0;
8469a747e4fSDavid du Colombier for(; f->dirindex < f->ndir; f->dirindex++){
8479a747e4fSDavid du Colombier if((f->dir[f->dirindex].qid.type & QTDIR) == 0)
8489a747e4fSDavid du Colombier continue;
8499a747e4fSDavid du Colombier len = convD2M(&f->dir[f->dirindex], r->buf+n, r->f.count-n);
8509a747e4fSDavid du Colombier if(len <= BIT16SZ)
8519a747e4fSDavid du Colombier goto Return;
8529a747e4fSDavid du Colombier n += len;
8539a747e4fSDavid du Colombier }
8549a747e4fSDavid du Colombier
8559a747e4fSDavid du Colombier skip = f->dirindex - f->ndir; /* # depend records already read */
8569a747e4fSDavid du Colombier
8577dd7cddfSDavid du Colombier if(f->df){
8587dd7cddfSDavid du Colombier for(i = 0; i < f->df->hlen; i++)
8597dd7cddfSDavid du Colombier for(dp = f->df->dhash[i]; dp; dp = dp->next){
8607dd7cddfSDavid du Colombier if(skip-- > 0)
8617dd7cddfSDavid du Colombier continue;
8629a747e4fSDavid du Colombier snprint(buf, sizeof buf, "%s.tar", dp->sym);
8639a747e4fSDavid du Colombier d.name = buf;
8649a747e4fSDavid du Colombier d.uid = "none";
8659a747e4fSDavid du Colombier d.gid = "none";
8669a747e4fSDavid du Colombier d.muid = "none";
8679a747e4fSDavid du Colombier d.qid.type = QTFILE;
8685e91980fSDavid du Colombier d.qid.path = (uvlong)dp;
8697dd7cddfSDavid du Colombier d.qid.vers = 0;
8707dd7cddfSDavid du Colombier d.length = f->df->file[dp->fno].tarlen;
8717dd7cddfSDavid du Colombier d.mode = 0444;
8727dd7cddfSDavid du Colombier d.mtime = time(nil);
8737dd7cddfSDavid du Colombier d.atime = time(nil);
8749a747e4fSDavid du Colombier len = convD2M(&d, r->buf + n, r->f.count - n);
8759a747e4fSDavid du Colombier if(len <= BIT16SZ)
8769a747e4fSDavid du Colombier goto Return;
8779a747e4fSDavid du Colombier n += len;
8789a747e4fSDavid du Colombier f->dirindex++;
8797dd7cddfSDavid du Colombier }
8807dd7cddfSDavid du Colombier }
8817dd7cddfSDavid du Colombier } else
8827dd7cddfSDavid du Colombier n = mktar(f->df, f->dp, r->buf, r->f.offset, r->f.count);
8837dd7cddfSDavid du Colombier
8849a747e4fSDavid du Colombier Return:
8859a747e4fSDavid du Colombier r->f.data = (char*)r->buf;
8867dd7cddfSDavid du Colombier r->f.count = n;
8877dd7cddfSDavid du Colombier fsreply(fs, r, nil);
8887dd7cddfSDavid du Colombier }
8897dd7cddfSDavid du Colombier
8907dd7cddfSDavid du Colombier void
fswrite(Fs * fs,Request * r,Fid *)8917dd7cddfSDavid du Colombier fswrite(Fs *fs, Request *r, Fid*)
8927dd7cddfSDavid du Colombier {
8937dd7cddfSDavid du Colombier fsreply(fs, r, Eperm);
8947dd7cddfSDavid du Colombier }
8957dd7cddfSDavid du Colombier
8967dd7cddfSDavid du Colombier void
fsclunk(Fs * fs,Request * r,Fid * f)8977dd7cddfSDavid du Colombier fsclunk(Fs *fs, Request *r, Fid *f)
8987dd7cddfSDavid du Colombier {
8997dd7cddfSDavid du Colombier if(f->attached == 0){
9007dd7cddfSDavid du Colombier fsreply(fs, r, Enofid);
9017dd7cddfSDavid du Colombier return;
9027dd7cddfSDavid du Colombier }
9037dd7cddfSDavid du Colombier if(f->fd >= 0){
9047dd7cddfSDavid du Colombier close(f->fd);
9057dd7cddfSDavid du Colombier f->fd = -1;
9067dd7cddfSDavid du Colombier }
9077dd7cddfSDavid du Colombier
9089a747e4fSDavid du Colombier if((f->qid.type & QTDIR) == 0)
9097dd7cddfSDavid du Colombier closetar(f->df, f->dp);
9107dd7cddfSDavid du Colombier
9117dd7cddfSDavid du Colombier releasedf(f->df);
9127dd7cddfSDavid du Colombier f->df = nil;
9139a747e4fSDavid du Colombier free(f->dir);
9149a747e4fSDavid du Colombier f->dir = nil;
9157dd7cddfSDavid du Colombier
9167dd7cddfSDavid du Colombier fsreply(fs, r, nil);
9177dd7cddfSDavid du Colombier fsputfid(fs, f);
9187dd7cddfSDavid du Colombier }
9197dd7cddfSDavid du Colombier
9207dd7cddfSDavid du Colombier void
fsremove(Fs * fs,Request * r,Fid *)9217dd7cddfSDavid du Colombier fsremove(Fs *fs, Request *r, Fid*)
9227dd7cddfSDavid du Colombier {
9237dd7cddfSDavid du Colombier fsreply(fs, r, Eperm);
9247dd7cddfSDavid du Colombier }
9257dd7cddfSDavid du Colombier
9267dd7cddfSDavid du Colombier void
fsstat(Fs * fs,Request * r,Fid * f)9277dd7cddfSDavid du Colombier fsstat(Fs *fs, Request *r, Fid *f)
9287dd7cddfSDavid du Colombier {
9299a747e4fSDavid du Colombier char err[ERRMAX];
9307dd7cddfSDavid du Colombier Dir d;
9317dd7cddfSDavid du Colombier Symbol *dp;
9329a747e4fSDavid du Colombier int n;
9339a747e4fSDavid du Colombier uchar statbuf[Nstat];
9347dd7cddfSDavid du Colombier
9359a747e4fSDavid du Colombier if(f->qid.type & QTDIR)
9369a747e4fSDavid du Colombier n = stat(f->path, statbuf, sizeof statbuf);
9379a747e4fSDavid du Colombier else {
9387dd7cddfSDavid du Colombier dp = f->dp;
9399a747e4fSDavid du Colombier d.name = dp->sym;
9409a747e4fSDavid du Colombier d.uid = "none";
9419a747e4fSDavid du Colombier d.gid = "none";
9429a747e4fSDavid du Colombier d.muid = "none";
9439a747e4fSDavid du Colombier d.qid.type = QTFILE;
9445e91980fSDavid du Colombier d.qid.path = (uvlong)dp;
9457dd7cddfSDavid du Colombier d.qid.vers = 0;
9467dd7cddfSDavid du Colombier d.length = f->df->file[dp->fno].tarlen;
9477dd7cddfSDavid du Colombier d.mode = 0444;
9487dd7cddfSDavid du Colombier d.mtime = time(nil);
9497dd7cddfSDavid du Colombier d.atime = time(nil);
9509a747e4fSDavid du Colombier n = convD2M(&d, statbuf, sizeof statbuf);
9519a747e4fSDavid du Colombier }
9529a747e4fSDavid du Colombier if(n <= BIT16SZ){
9539a747e4fSDavid du Colombier errstr(err, sizeof err);
9549a747e4fSDavid du Colombier fsreply(fs, r, err);
9559a747e4fSDavid du Colombier } else {
9569a747e4fSDavid du Colombier r->f.stat = statbuf;
9579a747e4fSDavid du Colombier r->f.nstat = n;
9587dd7cddfSDavid du Colombier fsreply(fs, r, nil);
9597dd7cddfSDavid du Colombier }
9607dd7cddfSDavid du Colombier }
9617dd7cddfSDavid du Colombier
9627dd7cddfSDavid du Colombier void
fswstat(Fs * fs,Request * r,Fid *)9637dd7cddfSDavid du Colombier fswstat(Fs *fs, Request *r, Fid*)
9647dd7cddfSDavid du Colombier {
9657dd7cddfSDavid du Colombier fsreply(fs, r, Eperm);
9667dd7cddfSDavid du Colombier }
9677dd7cddfSDavid du Colombier
9687dd7cddfSDavid du Colombier /*
9697dd7cddfSDavid du Colombier * string hash
9707dd7cddfSDavid du Colombier */
9717dd7cddfSDavid du Colombier uint
shash(char * str,int len)9727dd7cddfSDavid du Colombier shash(char *str, int len)
9737dd7cddfSDavid du Colombier {
9747dd7cddfSDavid du Colombier uint hash;
9757dd7cddfSDavid du Colombier char *val;
9767dd7cddfSDavid du Colombier
9777dd7cddfSDavid du Colombier hash = 0;
9787dd7cddfSDavid du Colombier for(val = str; *val; val++)
9797dd7cddfSDavid du Colombier hash = (hash*13) + *val-'a';
9807dd7cddfSDavid du Colombier return hash % len;
9817dd7cddfSDavid du Colombier }
9827dd7cddfSDavid du Colombier
9837dd7cddfSDavid du Colombier /*
9847dd7cddfSDavid du Colombier * free info about a dependency file
9857dd7cddfSDavid du Colombier */
9867dd7cddfSDavid du Colombier void
freedf(Dfile * df)9877dd7cddfSDavid du Colombier freedf(Dfile *df)
9887dd7cddfSDavid du Colombier {
9897dd7cddfSDavid du Colombier int i;
9907dd7cddfSDavid du Colombier Symbol *dp, *next;
9917dd7cddfSDavid du Colombier
9927dd7cddfSDavid du Colombier lock(df);
9937dd7cddfSDavid du Colombier df->old = 1;
9947dd7cddfSDavid du Colombier if(df->use){
9957dd7cddfSDavid du Colombier unlock(df);
9967dd7cddfSDavid du Colombier return;
9977dd7cddfSDavid du Colombier }
9987dd7cddfSDavid du Colombier
9997dd7cddfSDavid du Colombier unlock(df); /* we're no longer referenced */
10007dd7cddfSDavid du Colombier for(i = 0; i < df->nfile; i++)
10017dd7cddfSDavid du Colombier free(df->file[i].name);
10027dd7cddfSDavid du Colombier free(df->file[i].refvec);
10037dd7cddfSDavid du Colombier free(df->file);
10047dd7cddfSDavid du Colombier df->file = nil;
10057dd7cddfSDavid du Colombier
10067dd7cddfSDavid du Colombier for(i = 0; i < df->hlen; i++)
10077dd7cddfSDavid du Colombier for(dp = df->dhash[i]; dp != nil; dp = next){
10087dd7cddfSDavid du Colombier next = dp->next;
10097dd7cddfSDavid du Colombier free(dp);
10107dd7cddfSDavid du Colombier }
10117dd7cddfSDavid du Colombier
10127dd7cddfSDavid du Colombier free(df->path);
10137dd7cddfSDavid du Colombier free(df);
10147dd7cddfSDavid du Colombier free(df->dhash);
10157dd7cddfSDavid du Colombier df->dhash = nil;
10167dd7cddfSDavid du Colombier }
10177dd7cddfSDavid du Colombier
10187dd7cddfSDavid du Colombier /*
10197dd7cddfSDavid du Colombier * crack a dependency file
10207dd7cddfSDavid du Colombier */
10217dd7cddfSDavid du Colombier void
newsym(char * name,int fno,Symbol ** l)10227dd7cddfSDavid du Colombier newsym(char *name, int fno, Symbol **l)
10237dd7cddfSDavid du Colombier {
10247dd7cddfSDavid du Colombier Symbol *dp;
10257dd7cddfSDavid du Colombier
10267dd7cddfSDavid du Colombier dp = emalloc(sizeof(Symbol));
10279a747e4fSDavid du Colombier dp->sym = strdup(name);
10289a747e4fSDavid du Colombier if(dp->sym == nil)
10299a747e4fSDavid du Colombier fatal("mallocerr");
10307dd7cddfSDavid du Colombier dp->next = *l;
10317dd7cddfSDavid du Colombier dp->fno = fno;
10327dd7cddfSDavid du Colombier *l = dp;
10337dd7cddfSDavid du Colombier }
10347dd7cddfSDavid du Colombier int
awk(Biobuf * b,char ** field,int n)10357dd7cddfSDavid du Colombier awk(Biobuf *b, char **field, int n)
10367dd7cddfSDavid du Colombier {
10377dd7cddfSDavid du Colombier char *line;
10387dd7cddfSDavid du Colombier int i;
10397dd7cddfSDavid du Colombier
10407dd7cddfSDavid du Colombier while(line = Brdline(b, '\n')){
10417dd7cddfSDavid du Colombier line[Blinelen(b)-1] = 0;
10427dd7cddfSDavid du Colombier while(*line == ' ' || *line == '\t')
10437dd7cddfSDavid du Colombier *line++ = 0;
10447dd7cddfSDavid du Colombier for(i = 0; i < n; i++){
10457dd7cddfSDavid du Colombier if(*line == 0 || *line == '#')
10467dd7cddfSDavid du Colombier break;
10477dd7cddfSDavid du Colombier field[i] = line;
10487dd7cddfSDavid du Colombier while(*line && *line != ' ' && *line != '\t')
10497dd7cddfSDavid du Colombier line++;
10507dd7cddfSDavid du Colombier while(*line == ' ' || *line == '\t')
10517dd7cddfSDavid du Colombier *line++ = 0;
10527dd7cddfSDavid du Colombier }
10537dd7cddfSDavid du Colombier if(i)
10547dd7cddfSDavid du Colombier return i;
10557dd7cddfSDavid du Colombier }
10567dd7cddfSDavid du Colombier
10577dd7cddfSDavid du Colombier return 0;
10587dd7cddfSDavid du Colombier }
10597dd7cddfSDavid du Colombier
10607dd7cddfSDavid du Colombier void
crackdf(Dfile * df,Biobuf * b,uint len,char * dpath)10617dd7cddfSDavid du Colombier crackdf(Dfile *df, Biobuf *b, uint len, char *dpath)
10627dd7cddfSDavid du Colombier {
10637dd7cddfSDavid du Colombier char *name;
10647dd7cddfSDavid du Colombier char *field[3];
10659a747e4fSDavid du Colombier char path[512];
10669a747e4fSDavid du Colombier int n, inc, ok, npath;
10677dd7cddfSDavid du Colombier Symbol **l, *dp, *next;
10687dd7cddfSDavid du Colombier File *f, *ef;
10699a747e4fSDavid du Colombier Dir *d;
10707dd7cddfSDavid du Colombier
10717dd7cddfSDavid du Colombier inc = 32;
10727dd7cddfSDavid du Colombier df->flen = inc;
10737dd7cddfSDavid du Colombier df->file = emalloc(df->flen*sizeof(File));
10747dd7cddfSDavid du Colombier df->nfile = 0;
10757dd7cddfSDavid du Colombier
10767dd7cddfSDavid du Colombier df->hlen = 1 + len/8;
10777dd7cddfSDavid du Colombier df->dhash = emalloc(df->hlen*sizeof(Symbol*));
10787dd7cddfSDavid du Colombier
10797dd7cddfSDavid du Colombier l = nil;
10807dd7cddfSDavid du Colombier while((n = awk(b, field, 3)) > 0){
10817dd7cddfSDavid du Colombier if(n != 2)
10827dd7cddfSDavid du Colombier continue;
10837dd7cddfSDavid du Colombier
10847dd7cddfSDavid du Colombier name = field[1];
10857dd7cddfSDavid du Colombier switch(*field[0]){
10867dd7cddfSDavid du Colombier case 'F':
10877dd7cddfSDavid du Colombier if(df->flen == df->nfile){
10887dd7cddfSDavid du Colombier df->flen += inc;
10897dd7cddfSDavid du Colombier df->file = realloc(df->file, df->flen*sizeof(File));
10907dd7cddfSDavid du Colombier if(df->file == nil)
10917dd7cddfSDavid du Colombier fatal(mallocerr);
10927dd7cddfSDavid du Colombier memset(&df->file[df->nfile], 0, inc*sizeof(File));
10937dd7cddfSDavid du Colombier }
10947dd7cddfSDavid du Colombier f = &df->file[df->nfile++];
10957dd7cddfSDavid du Colombier f->name = strdup(name);
10967dd7cddfSDavid du Colombier l = &f->ref;
10977dd7cddfSDavid du Colombier /* fall through and define as a symbol */
10987dd7cddfSDavid du Colombier case 'D':
10997dd7cddfSDavid du Colombier if(l == nil)
11007dd7cddfSDavid du Colombier continue;
11017dd7cddfSDavid du Colombier newsym(name, df->nfile-1, &(df->dhash[shash(name, df->hlen)]));
11027dd7cddfSDavid du Colombier break;
11037dd7cddfSDavid du Colombier case 'R':
11047dd7cddfSDavid du Colombier if(l == nil)
11057dd7cddfSDavid du Colombier continue;
11067dd7cddfSDavid du Colombier newsym(name, 0, l);
11077dd7cddfSDavid du Colombier break;
11087dd7cddfSDavid du Colombier }
11097dd7cddfSDavid du Colombier }
11107dd7cddfSDavid du Colombier
11117dd7cddfSDavid du Colombier ef = &df->file[df->nfile];
11127dd7cddfSDavid du Colombier
11137dd7cddfSDavid du Colombier /* stat the files to get sizes */
11149a747e4fSDavid du Colombier npath = strlen(dpath);
11159a747e4fSDavid du Colombier if(npath+1+1 >= sizeof path)
11169a747e4fSDavid du Colombier fatal(Etoolong);
11179a747e4fSDavid du Colombier memmove(path, dpath, npath+1); /* include NUL */
11187dd7cddfSDavid du Colombier name = strrchr(path, '/') + 1;
11197dd7cddfSDavid du Colombier for(f = df->file; f < ef; f++){
11209a747e4fSDavid du Colombier n = strlen(f->name);
11219a747e4fSDavid du Colombier if(npath+1+n+3+1 > sizeof path)
11229a747e4fSDavid du Colombier fatal(Etoolong);
11239a747e4fSDavid du Colombier memmove(name, f->name, n+1); /* include NUL */
11249a747e4fSDavid du Colombier ok = access(path, AEXIST);
11257dd7cddfSDavid du Colombier if(ok < 0){
11267dd7cddfSDavid du Colombier strcpy(name+n, ".Z");
11279a747e4fSDavid du Colombier ok = access(path, AEXIST);
11287dd7cddfSDavid du Colombier if(ok < 0){
11297dd7cddfSDavid du Colombier strcpy(name+n, ".gz");
11309a747e4fSDavid du Colombier ok = access(path, AEXIST);
11317dd7cddfSDavid du Colombier }
11327dd7cddfSDavid du Colombier }
11337dd7cddfSDavid du Colombier if(ok >= 0){
11347dd7cddfSDavid du Colombier free(f->name);
11357dd7cddfSDavid du Colombier f->name = strdup(name);
11367dd7cddfSDavid du Colombier if(f->name == nil)
11377dd7cddfSDavid du Colombier fatal(mallocerr);
11387dd7cddfSDavid du Colombier }
11399a747e4fSDavid du Colombier d = dirstat(path);
11409a747e4fSDavid du Colombier if(d){
11419a747e4fSDavid du Colombier f->len = d->length;
11429a747e4fSDavid du Colombier f->mode = d->mode;
11439a747e4fSDavid du Colombier f->mtime = d->mtime;
11449a747e4fSDavid du Colombier free(d);
11459a747e4fSDavid du Colombier }else{
11469a747e4fSDavid du Colombier f->len = 0;
11479a747e4fSDavid du Colombier f->mode = 0;
11489a747e4fSDavid du Colombier f->mtime = 0;
11499a747e4fSDavid du Colombier }
11507dd7cddfSDavid du Colombier f->fd = -1;
11517dd7cddfSDavid du Colombier }
11527dd7cddfSDavid du Colombier
11537dd7cddfSDavid du Colombier /* resolve all file references */
11547dd7cddfSDavid du Colombier for(f = df->file; f < ef; f++)
11557dd7cddfSDavid du Colombier dfresolve(df, f-df->file);
11567dd7cddfSDavid du Colombier
11577dd7cddfSDavid du Colombier /* free the referenced symbols, don't need them anymore */
11587dd7cddfSDavid du Colombier for(f = df->file; f < ef; f++){
11597dd7cddfSDavid du Colombier f->tarlen += 2*Tblocksize; /* tars trailing 0 blocks */
11607dd7cddfSDavid du Colombier for(dp = f->ref; dp != nil; dp = next){
11617dd7cddfSDavid du Colombier next = dp->next;
11627dd7cddfSDavid du Colombier free(dp);
11637dd7cddfSDavid du Colombier }
11647dd7cddfSDavid du Colombier f->ref = nil;
11657dd7cddfSDavid du Colombier }
11667dd7cddfSDavid du Colombier }
11677dd7cddfSDavid du Colombier
11687dd7cddfSDavid du Colombier /*
11697dd7cddfSDavid du Colombier * get a cracked dependency file
11707dd7cddfSDavid du Colombier */
11717dd7cddfSDavid du Colombier Dfile*
getdf(char * path)11727dd7cddfSDavid du Colombier getdf(char *path)
11737dd7cddfSDavid du Colombier {
11747dd7cddfSDavid du Colombier Dfile *df, **l;
11757dd7cddfSDavid du Colombier QLock *lk;
11769a747e4fSDavid du Colombier Dir *d;
11779a747e4fSDavid du Colombier int i, fd;
11787dd7cddfSDavid du Colombier Biobuf *b;
11797dd7cddfSDavid du Colombier
11807dd7cddfSDavid du Colombier i = shash(path, Ndfhash);
11817dd7cddfSDavid du Colombier l = &dfhash[i];
11827dd7cddfSDavid du Colombier lk = &dfhlock[i];
11837dd7cddfSDavid du Colombier qlock(lk);
11847dd7cddfSDavid du Colombier for(df = *l; df; df = *l){
11857dd7cddfSDavid du Colombier if(strcmp(path, df->path) == 0)
11867dd7cddfSDavid du Colombier break;
11877dd7cddfSDavid du Colombier l = &df->next;
11887dd7cddfSDavid du Colombier }
11899a747e4fSDavid du Colombier d = dirstat(path);
11907dd7cddfSDavid du Colombier
11917dd7cddfSDavid du Colombier if(df){
11929a747e4fSDavid du Colombier if(d!=nil && d->qid.type == df->qid.type && d->qid.vers == df->qid.vers && d->qid.vers == df->qid.vers){
11937dd7cddfSDavid du Colombier free(path);
11947dd7cddfSDavid du Colombier lock(df);
11957dd7cddfSDavid du Colombier df->use++;
11967dd7cddfSDavid du Colombier unlock(df);
11979a747e4fSDavid du Colombier goto Return;
11987dd7cddfSDavid du Colombier }
11997dd7cddfSDavid du Colombier *l = df->next;
12007dd7cddfSDavid du Colombier freedf(df);
12017dd7cddfSDavid du Colombier }
12027dd7cddfSDavid du Colombier
12037dd7cddfSDavid du Colombier fd = open(path, OREAD);
12049a747e4fSDavid du Colombier if(d == nil || fd < 0){
12057dd7cddfSDavid du Colombier close(fd);
12069a747e4fSDavid du Colombier goto Return;
12077dd7cddfSDavid du Colombier }
12087dd7cddfSDavid du Colombier
12097dd7cddfSDavid du Colombier df = emalloc(sizeof(*df));
12107dd7cddfSDavid du Colombier b = emalloc(sizeof(Biobuf));
12117dd7cddfSDavid du Colombier
12127dd7cddfSDavid du Colombier Binit(b, fd, OREAD);
12139a747e4fSDavid du Colombier df->qid = d->qid;
12147dd7cddfSDavid du Colombier df->path = path;
12159a747e4fSDavid du Colombier crackdf(df, b, d->length, path);
12167dd7cddfSDavid du Colombier Bterm(b);
12177dd7cddfSDavid du Colombier
12187dd7cddfSDavid du Colombier free(b);
12197dd7cddfSDavid du Colombier
12207dd7cddfSDavid du Colombier df->next = *l;
12217dd7cddfSDavid du Colombier *l = df;
12227dd7cddfSDavid du Colombier df->use = 1;
12239a747e4fSDavid du Colombier Return:
12247dd7cddfSDavid du Colombier qunlock(lk);
12259a747e4fSDavid du Colombier free(d);
12267dd7cddfSDavid du Colombier return df;
12277dd7cddfSDavid du Colombier }
12287dd7cddfSDavid du Colombier
12297dd7cddfSDavid du Colombier /*
12307dd7cddfSDavid du Colombier * stop using a dependency file. Free it if it is no longer linked in.
12317dd7cddfSDavid du Colombier */
12327dd7cddfSDavid du Colombier void
releasedf(Dfile * df)12337dd7cddfSDavid du Colombier releasedf(Dfile *df)
12347dd7cddfSDavid du Colombier {
12357dd7cddfSDavid du Colombier Dfile **l, *d;
12367dd7cddfSDavid du Colombier QLock *lk;
12377dd7cddfSDavid du Colombier int i;
12387dd7cddfSDavid du Colombier
12399a747e4fSDavid du Colombier if(df == nil)
12409a747e4fSDavid du Colombier return;
12419a747e4fSDavid du Colombier
12427dd7cddfSDavid du Colombier /* remove from hash chain */
12437dd7cddfSDavid du Colombier i = shash(df->path, Ndfhash);
12447dd7cddfSDavid du Colombier l = &dfhash[i];
12457dd7cddfSDavid du Colombier lk = &dfhlock[i];
12467dd7cddfSDavid du Colombier qlock(lk);
12477dd7cddfSDavid du Colombier lock(df);
12487dd7cddfSDavid du Colombier df->use--;
12497dd7cddfSDavid du Colombier if(df->old == 0 || df->use > 0){
12507dd7cddfSDavid du Colombier unlock(df);
12517dd7cddfSDavid du Colombier qunlock(lk);
12527dd7cddfSDavid du Colombier return;
12537dd7cddfSDavid du Colombier }
12547dd7cddfSDavid du Colombier for(d = *l; d; d = *l){
12557dd7cddfSDavid du Colombier if(d == df){
12567dd7cddfSDavid du Colombier *l = d->next;
12577dd7cddfSDavid du Colombier break;
12587dd7cddfSDavid du Colombier }
12597dd7cddfSDavid du Colombier l = &d->next;
12607dd7cddfSDavid du Colombier }
12617dd7cddfSDavid du Colombier unlock(df);
12627dd7cddfSDavid du Colombier qunlock(lk);
12637dd7cddfSDavid du Colombier
12647dd7cddfSDavid du Colombier /* now we know it is unreferenced, remove it */
12657dd7cddfSDavid du Colombier freedf(df);
12667dd7cddfSDavid du Colombier }
12677dd7cddfSDavid du Colombier
12687dd7cddfSDavid du Colombier /*
12697dd7cddfSDavid du Colombier * search a dependency file for a symbol
12707dd7cddfSDavid du Colombier */
12717dd7cddfSDavid du Colombier Symbol*
dfsearch(Dfile * df,char * name)12727dd7cddfSDavid du Colombier dfsearch(Dfile *df, char *name)
12737dd7cddfSDavid du Colombier {
12747dd7cddfSDavid du Colombier Symbol *dp;
12757dd7cddfSDavid du Colombier
12767dd7cddfSDavid du Colombier if(df == nil)
12777dd7cddfSDavid du Colombier return nil;
12787dd7cddfSDavid du Colombier for(dp = df->dhash[shash(name, df->hlen)]; dp; dp = dp->next)
12797dd7cddfSDavid du Colombier if(strcmp(dp->sym, name) == 0)
12807dd7cddfSDavid du Colombier return dp;
12817dd7cddfSDavid du Colombier return nil;
12827dd7cddfSDavid du Colombier }
12837dd7cddfSDavid du Colombier
12847dd7cddfSDavid du Colombier /*
12857dd7cddfSDavid du Colombier * resolve a single file into a vector of referenced files and the sum of their
12867dd7cddfSDavid du Colombier * lengths
12877dd7cddfSDavid du Colombier */
12887dd7cddfSDavid du Colombier /* set a bit in the referenced file vector */
12897dd7cddfSDavid du Colombier int
set(uchar * vec,int fno)12907dd7cddfSDavid du Colombier set(uchar *vec, int fno)
12917dd7cddfSDavid du Colombier {
12927dd7cddfSDavid du Colombier if(vec[fno/8] & (1<<(fno&7)))
12937dd7cddfSDavid du Colombier return 1;
12947dd7cddfSDavid du Colombier vec[fno/8] |= 1<<(fno&7);
12957dd7cddfSDavid du Colombier return 0;
12967dd7cddfSDavid du Colombier }
12977dd7cddfSDavid du Colombier /* merge two referenced file vectors */
12987dd7cddfSDavid du Colombier void
merge(uchar * vec,uchar * ovec,int nfile)12997dd7cddfSDavid du Colombier merge(uchar *vec, uchar *ovec, int nfile)
13007dd7cddfSDavid du Colombier {
13017dd7cddfSDavid du Colombier nfile = (nfile+7)/8;
13027dd7cddfSDavid du Colombier while(nfile-- > 0)
13037dd7cddfSDavid du Colombier *vec++ |= *ovec++;
13047dd7cddfSDavid du Colombier }
13057dd7cddfSDavid du Colombier uint
res(Dfile * df,uchar * vec,int fno)13067dd7cddfSDavid du Colombier res(Dfile *df, uchar *vec, int fno)
13077dd7cddfSDavid du Colombier {
13087dd7cddfSDavid du Colombier File *f;
13097dd7cddfSDavid du Colombier Symbol *rp, *dp;
13107dd7cddfSDavid du Colombier int len;
13117dd7cddfSDavid du Colombier
13127dd7cddfSDavid du Colombier f = &df->file[fno];
13137dd7cddfSDavid du Colombier if(set(vec, fno))
13147dd7cddfSDavid du Colombier return 0; /* already set */
13157dd7cddfSDavid du Colombier if(f->refvec != nil){
13167dd7cddfSDavid du Colombier merge(vec, f->refvec, df->nfile); /* we've descended here before */
13177dd7cddfSDavid du Colombier return f->tarlen;
13187dd7cddfSDavid du Colombier }
13197dd7cddfSDavid du Colombier
13207dd7cddfSDavid du Colombier len = 0;
13217dd7cddfSDavid du Colombier for(rp = f->ref; rp; rp = rp->next){
13227dd7cddfSDavid du Colombier dp = dfsearch(df, rp->sym);
13237dd7cddfSDavid du Colombier if(dp == nil)
13247dd7cddfSDavid du Colombier continue;
13257dd7cddfSDavid du Colombier len += res(df, vec, dp->fno);
13267dd7cddfSDavid du Colombier }
13277dd7cddfSDavid du Colombier return len + Tblocksize + ((f->len + Tblocksize - 1)/Tblocksize)*Tblocksize;
13287dd7cddfSDavid du Colombier }
13297dd7cddfSDavid du Colombier void
dfresolve(Dfile * df,int fno)13307dd7cddfSDavid du Colombier dfresolve(Dfile *df, int fno)
13317dd7cddfSDavid du Colombier {
13327dd7cddfSDavid du Colombier uchar *vec;
13337dd7cddfSDavid du Colombier File *f;
13347dd7cddfSDavid du Colombier
13357dd7cddfSDavid du Colombier f = &df->file[fno];
13367dd7cddfSDavid du Colombier vec = emalloc((df->nfile+7)/8);
13377dd7cddfSDavid du Colombier f->tarlen = res(df, vec, fno);
13387dd7cddfSDavid du Colombier f->refvec = vec;
13397dd7cddfSDavid du Colombier }
13407dd7cddfSDavid du Colombier
13417dd7cddfSDavid du Colombier /*
13427dd7cddfSDavid du Colombier * make the tar directory block for a file
13437dd7cddfSDavid du Colombier */
13449a747e4fSDavid du Colombier uchar*
mktardir(File * f)13457dd7cddfSDavid du Colombier mktardir(File *f)
13467dd7cddfSDavid du Colombier {
13479a747e4fSDavid du Colombier uchar *ep;
13487dd7cddfSDavid du Colombier Tardir *tp;
13497dd7cddfSDavid du Colombier uint sum;
13509a747e4fSDavid du Colombier uchar *p, *cp;
13517dd7cddfSDavid du Colombier
13527dd7cddfSDavid du Colombier p = emalloc(Tblocksize);
13537dd7cddfSDavid du Colombier tp = (Tardir*)p;
13547dd7cddfSDavid du Colombier
13557dd7cddfSDavid du Colombier strcpy(tp->name, f->name);
13567dd7cddfSDavid du Colombier sprint(tp->mode, "%6o ", f->mode & 0777);
13577dd7cddfSDavid du Colombier sprint(tp->uid, "%6o ", 0);
13587dd7cddfSDavid du Colombier sprint(tp->gid, "%6o ", 0);
13597dd7cddfSDavid du Colombier sprint(tp->size, "%11o ", f->len);
13607dd7cddfSDavid du Colombier sprint(tp->mtime, "%11o ", f->mtime);
13617dd7cddfSDavid du Colombier
13627dd7cddfSDavid du Colombier /* calculate checksum */
13637dd7cddfSDavid du Colombier memset(tp->chksum, ' ', sizeof(tp->chksum));
13647dd7cddfSDavid du Colombier sum = 0;
13657dd7cddfSDavid du Colombier ep = p + Tblocksize;
13667dd7cddfSDavid du Colombier for (cp = p; cp < ep; cp++)
13677dd7cddfSDavid du Colombier sum += *cp;
13687dd7cddfSDavid du Colombier sprint(tp->chksum, "%6o", sum);
13697dd7cddfSDavid du Colombier
13707dd7cddfSDavid du Colombier return p;
13717dd7cddfSDavid du Colombier }
13727dd7cddfSDavid du Colombier
13737dd7cddfSDavid du Colombier /*
13747dd7cddfSDavid du Colombier * manage open files
13757dd7cddfSDavid du Colombier */
13767dd7cddfSDavid du Colombier int
getfile(Dfile * df,File * f)13777dd7cddfSDavid du Colombier getfile(Dfile *df, File *f)
13787dd7cddfSDavid du Colombier {
13799a747e4fSDavid du Colombier int n;
13809a747e4fSDavid du Colombier char path[512], *name;
13817dd7cddfSDavid du Colombier
13827dd7cddfSDavid du Colombier qlock(f);
13837dd7cddfSDavid du Colombier f->use++;
13847dd7cddfSDavid du Colombier if(f->fd < 0){
13859a747e4fSDavid du Colombier name = strrchr(df->path, '/') + 1;
13869a747e4fSDavid du Colombier n = snprint(path, sizeof path, "%.*s/%s", (int)(name-df->path), df->path, f->name);
13879a747e4fSDavid du Colombier if(n >= sizeof path - UTFmax){
13889a747e4fSDavid du Colombier syslog(0, dependlog, "path name too long: %.20s.../%.20s...", df->path, f->name);
13899a747e4fSDavid du Colombier return -1;
13909a747e4fSDavid du Colombier }
13917dd7cddfSDavid du Colombier f->fd = open(path, OREAD);
13927dd7cddfSDavid du Colombier if(f->fd < 0)
13937dd7cddfSDavid du Colombier syslog(0, dependlog, "can't open %s: %r", path);
13947dd7cddfSDavid du Colombier }
13957dd7cddfSDavid du Colombier
13967dd7cddfSDavid du Colombier return f->fd;
13977dd7cddfSDavid du Colombier }
13987dd7cddfSDavid du Colombier void
releasefile(File * f)13997dd7cddfSDavid du Colombier releasefile(File *f)
14007dd7cddfSDavid du Colombier {
14017dd7cddfSDavid du Colombier --f->use;
14027dd7cddfSDavid du Colombier qunlock(f);
14037dd7cddfSDavid du Colombier }
14047dd7cddfSDavid du Colombier void
closefile(File * f)14057dd7cddfSDavid du Colombier closefile(File *f)
14067dd7cddfSDavid du Colombier {
14077dd7cddfSDavid du Colombier qlock(f);
14087dd7cddfSDavid du Colombier if(f->use == 0){
14097dd7cddfSDavid du Colombier close(f->fd);
14107dd7cddfSDavid du Colombier f->fd = -1;
14117dd7cddfSDavid du Colombier }
14127dd7cddfSDavid du Colombier qunlock(f);
14137dd7cddfSDavid du Colombier }
14147dd7cddfSDavid du Colombier
14157dd7cddfSDavid du Colombier /*
14167dd7cddfSDavid du Colombier * return a block of a tar file
14177dd7cddfSDavid du Colombier */
14187dd7cddfSDavid du Colombier int
mktar(Dfile * df,Symbol * dp,uchar * area,uint offset,int len)14199a747e4fSDavid du Colombier mktar(Dfile *df, Symbol *dp, uchar *area, uint offset, int len)
14207dd7cddfSDavid du Colombier {
14217dd7cddfSDavid du Colombier int fd, i, j, n, off;
14229a747e4fSDavid du Colombier uchar *p, *buf;
14237dd7cddfSDavid du Colombier uchar *vec;
14247dd7cddfSDavid du Colombier File *f;
14257dd7cddfSDavid du Colombier
14267dd7cddfSDavid du Colombier f = &df->file[dp->fno];
14277dd7cddfSDavid du Colombier vec = f->refvec;
14287dd7cddfSDavid du Colombier p = area;
14297dd7cddfSDavid du Colombier
14307dd7cddfSDavid du Colombier /* find file */
14317dd7cddfSDavid du Colombier for(i = 0; i < df->nfile && len > 0; i++){
14327dd7cddfSDavid du Colombier if((vec[i/8] & (1<<(i&7))) == 0)
14337dd7cddfSDavid du Colombier continue;
14347dd7cddfSDavid du Colombier
14357dd7cddfSDavid du Colombier f = &df->file[i];
14367dd7cddfSDavid du Colombier n = Tblocksize + ((f->len + Tblocksize - 1)/Tblocksize)*Tblocksize;
14377dd7cddfSDavid du Colombier if(offset >= n){
14387dd7cddfSDavid du Colombier offset -= n;
14397dd7cddfSDavid du Colombier continue;
14407dd7cddfSDavid du Colombier }
14417dd7cddfSDavid du Colombier
14427dd7cddfSDavid du Colombier if(offset < Tblocksize){
14437dd7cddfSDavid du Colombier buf = mktardir(f);
14447dd7cddfSDavid du Colombier if(offset + len > Tblocksize)
14457dd7cddfSDavid du Colombier j = Tblocksize - offset;
14467dd7cddfSDavid du Colombier else
14477dd7cddfSDavid du Colombier j = len;
14489a747e4fSDavid du Colombier //if(debug)fprint(2, "reading %d bytes dir of %s\n", j, f->name);
14497dd7cddfSDavid du Colombier memmove(p, buf+offset, j);
14507dd7cddfSDavid du Colombier p += j;
14517dd7cddfSDavid du Colombier len -= j;
14527dd7cddfSDavid du Colombier offset += j;
14537dd7cddfSDavid du Colombier free(buf);
14547dd7cddfSDavid du Colombier }
14557dd7cddfSDavid du Colombier if(len <= 0)
14567dd7cddfSDavid du Colombier break;
14577dd7cddfSDavid du Colombier off = offset - Tblocksize;
14587dd7cddfSDavid du Colombier if(off >= 0 && off < f->len){
14597dd7cddfSDavid du Colombier if(off + len > f->len)
14607dd7cddfSDavid du Colombier j = f->len - off;
14617dd7cddfSDavid du Colombier else
14627dd7cddfSDavid du Colombier j = len;
14637dd7cddfSDavid du Colombier fd = getfile(df, f);
14647dd7cddfSDavid du Colombier if(fd >= 0){
14659a747e4fSDavid du Colombier //if(debug)fprint(2, "reading %d bytes from offset %d of %s\n", j, off, f->name);
14669a747e4fSDavid du Colombier if(pread(fd, p, j, off) != j)
14677dd7cddfSDavid du Colombier syslog(0, dependlog, "%r reading %d bytes from offset %d of %s", j, off, f->name);
14687dd7cddfSDavid du Colombier }
14697dd7cddfSDavid du Colombier releasefile(f);
14707dd7cddfSDavid du Colombier p += j;
14717dd7cddfSDavid du Colombier len -= j;
14727dd7cddfSDavid du Colombier offset += j;
14737dd7cddfSDavid du Colombier }
14747dd7cddfSDavid du Colombier if(len <= 0)
14757dd7cddfSDavid du Colombier break;
14767dd7cddfSDavid du Colombier if(offset < n){
14777dd7cddfSDavid du Colombier if(offset + len > n)
14787dd7cddfSDavid du Colombier j = n - offset;
14797dd7cddfSDavid du Colombier else
14807dd7cddfSDavid du Colombier j = len;
14819a747e4fSDavid du Colombier //if(debug)fprint(2, "filling %d bytes after %s\n", j, f->name);
14827dd7cddfSDavid du Colombier memset(p, 0, j);
14837dd7cddfSDavid du Colombier p += j;
14847dd7cddfSDavid du Colombier len -= j;
14857dd7cddfSDavid du Colombier }
14867dd7cddfSDavid du Colombier offset = 0;
14877dd7cddfSDavid du Colombier }
14887dd7cddfSDavid du Colombier
14897dd7cddfSDavid du Colombier /* null blocks at end of tar file */
14907dd7cddfSDavid du Colombier if(offset < 2*Tblocksize && len > 0){
14917dd7cddfSDavid du Colombier if(offset + len > 2*Tblocksize)
14927dd7cddfSDavid du Colombier j = 2*Tblocksize - offset;
14937dd7cddfSDavid du Colombier else
14947dd7cddfSDavid du Colombier j = len;
14959a747e4fSDavid du Colombier //if(debug)fprint(2, "filling %d bytes at end\n", j);
14967dd7cddfSDavid du Colombier memset(p, 0, j);
14977dd7cddfSDavid du Colombier p += j;
14987dd7cddfSDavid du Colombier }
14997dd7cddfSDavid du Colombier
15007dd7cddfSDavid du Colombier return p - area;
15017dd7cddfSDavid du Colombier }
15027dd7cddfSDavid du Colombier
15037dd7cddfSDavid du Colombier /*
15047dd7cddfSDavid du Colombier * close the files making up a tar file
15057dd7cddfSDavid du Colombier */
15067dd7cddfSDavid du Colombier void
closetar(Dfile * df,Symbol * dp)15077dd7cddfSDavid du Colombier closetar(Dfile *df, Symbol *dp)
15087dd7cddfSDavid du Colombier {
15097dd7cddfSDavid du Colombier int i;
15107dd7cddfSDavid du Colombier uchar *vec;
15117dd7cddfSDavid du Colombier File *f;
15127dd7cddfSDavid du Colombier
15137dd7cddfSDavid du Colombier f = &df->file[dp->fno];
15147dd7cddfSDavid du Colombier vec = f->refvec;
15157dd7cddfSDavid du Colombier
15167dd7cddfSDavid du Colombier /* find file */
15177dd7cddfSDavid du Colombier for(i = 0; i < df->nfile; i++){
15187dd7cddfSDavid du Colombier if((vec[i/8] & (1<<(i&7))) == 0)
15197dd7cddfSDavid du Colombier continue;
15207dd7cddfSDavid du Colombier closefile(&df->file[i]);
15217dd7cddfSDavid du Colombier }
15227dd7cddfSDavid du Colombier }
15237dd7cddfSDavid du Colombier
1524