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 8*73e742d7SDavid du Colombier typedef struct Args Args; 9*73e742d7SDavid du Colombier 10*73e742d7SDavid du Colombier struct Args { 11*73e742d7SDavid du Colombier int argc; 12*73e742d7SDavid du Colombier char **argv; 13*73e742d7SDavid du Colombier }; 14*73e742d7SDavid 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 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* 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 * 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* 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 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; 268*73e742d7SDavid du Colombier Args *args; 2697dd7cddfSDavid du Colombier int argc; 2707dd7cddfSDavid du Colombier char **argv; 2717dd7cddfSDavid du Colombier 272*73e742d7SDavid du Colombier args = a; 273*73e742d7SDavid du Colombier argc = args->argc; 274*73e742d7SDavid 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){ 284*73e742d7SDavid 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 3177dd7cddfSDavid du Colombier threadmain(int argc, char *argv[]) 3187dd7cddfSDavid du Colombier { 319*73e742d7SDavid du Colombier static Args args; 3207dd7cddfSDavid du Colombier 321*73e742d7SDavid du Colombier args.argc = argc; 322*73e742d7SDavid du Colombier args.argv = argv; 3239a747e4fSDavid du Colombier rfork(RFNAMEG); 324*73e742d7SDavid du Colombier proccreate(realmain, &args, 16*1024); 3257dd7cddfSDavid du Colombier } 3267dd7cddfSDavid du Colombier 3277dd7cddfSDavid du Colombier char* 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 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* 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* 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 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 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 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 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 4907dd7cddfSDavid du Colombier fsflush(Fs*, Request*, Fid*) 4917dd7cddfSDavid du Colombier { 4927dd7cddfSDavid du Colombier } 4937dd7cddfSDavid du Colombier 4947dd7cddfSDavid du Colombier void 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 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 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 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 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 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 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 } 8317dd7cddfSDavid du Colombier if(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 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 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 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 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 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 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 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 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 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 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* 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 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* 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 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 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 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 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* 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 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 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 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 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 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