xref: /plan9/sys/src/cmd/aux/depend.c (revision 22a127bbfe4dd304949cc596400de973c0138e31)
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