xref: /plan9/sys/src/cmd/9660srv/xfile.c (revision 4f28177105e14bc5c70ae9ec986773133c757004)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
3219b2ee8SDavid du Colombier #include <auth.h>
43e12c5d1SDavid du Colombier #include <fcall.h>
53e12c5d1SDavid du Colombier #include "dat.h"
63e12c5d1SDavid du Colombier #include "fns.h"
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier static Xfile*	clean(Xfile*);
93e12c5d1SDavid du Colombier 
103e12c5d1SDavid du Colombier #define	FIDMOD	127	/* prime */
113e12c5d1SDavid du Colombier 
123e12c5d1SDavid du Colombier static Xdata*	xhead;
13bd389b36SDavid du Colombier static Xfile*	xfiles[FIDMOD];
14bd389b36SDavid du Colombier static Xfile*	freelist;
153e12c5d1SDavid du Colombier 
163e12c5d1SDavid du Colombier Xdata*
getxdata(char * name)173e12c5d1SDavid du Colombier getxdata(char *name)
183e12c5d1SDavid du Colombier {
193e12c5d1SDavid du Colombier 	int fd;
209a747e4fSDavid du Colombier 	Dir *dir;
213e12c5d1SDavid du Colombier 	Xdata *xf, *fxf;
223e12c5d1SDavid du Colombier 	int flag;
233e12c5d1SDavid du Colombier 
243e12c5d1SDavid du Colombier 	if(name[0] == 0)
253e12c5d1SDavid du Colombier 		name = deffile;
263e12c5d1SDavid du Colombier 	if(name == 0)
273e12c5d1SDavid du Colombier 		error(Enofile);
283e12c5d1SDavid du Colombier 	flag = (access(name, 6) == 0) ? ORDWR : OREAD;
293e12c5d1SDavid du Colombier 	fd = open(name, flag);
303e12c5d1SDavid du Colombier 	if(fd < 0)
313e12c5d1SDavid du Colombier 		error(Enonexist);
329a747e4fSDavid du Colombier 	dir = nil;
333e12c5d1SDavid du Colombier 	if(waserror()){
343e12c5d1SDavid du Colombier 		close(fd);
359a747e4fSDavid du Colombier 		free(dir);
363e12c5d1SDavid du Colombier 		nexterror();
373e12c5d1SDavid du Colombier 	}
389a747e4fSDavid du Colombier 	if((dir = dirfstat(fd)) == nil)
393e12c5d1SDavid du Colombier 		error("I/O error");
40*4f281771SDavid du Colombier 	if((dir->qid.type & ~QTTMP) != QTFILE)
419a747e4fSDavid du Colombier 		error("attach name not a plain file");
423e12c5d1SDavid du Colombier 	for(fxf=0,xf=xhead; xf; xf=xf->next){
433e12c5d1SDavid du Colombier 		if(xf->name == 0){
443e12c5d1SDavid du Colombier 			if(fxf == 0)
453e12c5d1SDavid du Colombier 				fxf = xf;
463e12c5d1SDavid du Colombier 			continue;
473e12c5d1SDavid du Colombier 		}
489a747e4fSDavid du Colombier 		if(xf->qid.path != dir->qid.path || xf->qid.vers != dir->qid.vers)
493e12c5d1SDavid du Colombier 			continue;
509a747e4fSDavid du Colombier 		if(xf->type != dir->type || xf->fdev != dir->dev)
513e12c5d1SDavid du Colombier 			continue;
52bd389b36SDavid du Colombier 		xf->ref++;
533e12c5d1SDavid du Colombier 		chat("incref=%d, \"%s\", dev=%d...", xf->ref, xf->name, xf->dev);
543e12c5d1SDavid du Colombier 		close(fd);
553e12c5d1SDavid du Colombier 		poperror();
569a747e4fSDavid du Colombier 		free(dir);
573e12c5d1SDavid du Colombier 		return xf;
583e12c5d1SDavid du Colombier 	}
593e12c5d1SDavid du Colombier 	if(fxf==0){
603e12c5d1SDavid du Colombier 		fxf = ealloc(sizeof(Xfs));
613e12c5d1SDavid du Colombier 		fxf->next = xhead;
623e12c5d1SDavid du Colombier 		xhead = fxf;
633e12c5d1SDavid du Colombier 	}
643e12c5d1SDavid du Colombier 	chat("alloc \"%s\", dev=%d...", name, fd);
653e12c5d1SDavid du Colombier 	fxf->ref = 1;
663e12c5d1SDavid du Colombier 	fxf->name = strcpy(ealloc(strlen(name)+1), name);
679a747e4fSDavid du Colombier 	fxf->qid = dir->qid;
689a747e4fSDavid du Colombier 	fxf->type = dir->type;
699a747e4fSDavid du Colombier 	fxf->fdev = dir->dev;
703e12c5d1SDavid du Colombier 	fxf->dev = fd;
719a747e4fSDavid du Colombier 	free(dir);
723e12c5d1SDavid du Colombier 	poperror();
733e12c5d1SDavid du Colombier 	return fxf;
743e12c5d1SDavid du Colombier }
753e12c5d1SDavid du Colombier 
763e12c5d1SDavid du Colombier static void
putxdata(Xdata * d)773e12c5d1SDavid du Colombier putxdata(Xdata *d)
783e12c5d1SDavid du Colombier {
793e12c5d1SDavid du Colombier 	if(d->ref <= 0)
803e12c5d1SDavid du Colombier 		panic(0, "putxdata");
81bd389b36SDavid du Colombier 	d->ref--;
823e12c5d1SDavid du Colombier 	chat("decref=%d, \"%s\", dev=%d...", d->ref, d->name, d->dev);
833e12c5d1SDavid du Colombier 	if(d->ref == 0){
843e12c5d1SDavid du Colombier 		chat("purgebuf...");
853e12c5d1SDavid du Colombier 		purgebuf(d);
863e12c5d1SDavid du Colombier 		close(d->dev);
873e12c5d1SDavid du Colombier 		free(d->name);
883e12c5d1SDavid du Colombier 		d->name = 0;
893e12c5d1SDavid du Colombier 	}
903e12c5d1SDavid du Colombier }
913e12c5d1SDavid du Colombier 
923e12c5d1SDavid du Colombier void
refxfs(Xfs * xf,int delta)933e12c5d1SDavid du Colombier refxfs(Xfs *xf, int delta)
943e12c5d1SDavid du Colombier {
953e12c5d1SDavid du Colombier 	xf->ref += delta;
963e12c5d1SDavid du Colombier 	if(xf->ref == 0){
973e12c5d1SDavid du Colombier 		if(xf->d)
983e12c5d1SDavid du Colombier 			putxdata(xf->d);
993e12c5d1SDavid du Colombier 		if(xf->ptr)
1003e12c5d1SDavid du Colombier 			free(xf->ptr);
1013e12c5d1SDavid du Colombier 		free(xf);
1023e12c5d1SDavid du Colombier 	}
1033e12c5d1SDavid du Colombier }
1043e12c5d1SDavid du Colombier 
1053e12c5d1SDavid du Colombier Xfile*
xfile(int fid,int flag)1063e12c5d1SDavid du Colombier xfile(int fid, int flag)
1073e12c5d1SDavid du Colombier {
1083e12c5d1SDavid du Colombier 	int k = fid%FIDMOD;
1093e12c5d1SDavid du Colombier 	Xfile **hp=&xfiles[k], *f, *pf;
1103e12c5d1SDavid du Colombier 
1113e12c5d1SDavid du Colombier 	for(f=*hp,pf=0; f; pf=f,f=f->next)
1123e12c5d1SDavid du Colombier 		if(f->fid == fid)
1133e12c5d1SDavid du Colombier 			break;
1143e12c5d1SDavid du Colombier 	if(f && pf){
1153e12c5d1SDavid du Colombier 		pf->next = f->next;
1163e12c5d1SDavid du Colombier 		f->next = *hp;
1173e12c5d1SDavid du Colombier 		*hp = f;
1183e12c5d1SDavid du Colombier 	}
1193e12c5d1SDavid du Colombier 	switch(flag){
1203e12c5d1SDavid du Colombier 	default:
1213e12c5d1SDavid du Colombier 		panic(0, "xfile");
1223e12c5d1SDavid du Colombier 	case Asis:
1233e12c5d1SDavid du Colombier 		if(f == 0)
1243e12c5d1SDavid du Colombier 			error("unassigned fid");
1253e12c5d1SDavid du Colombier 		return f;
1263e12c5d1SDavid du Colombier 	case Clean:
1273e12c5d1SDavid du Colombier 		break;
1283e12c5d1SDavid du Colombier 	case Clunk:
1293e12c5d1SDavid du Colombier 		if(f){
1303e12c5d1SDavid du Colombier 			*hp = f->next;
1313e12c5d1SDavid du Colombier 			clean(f);
1323e12c5d1SDavid du Colombier 			f->next = freelist;
1333e12c5d1SDavid du Colombier 			freelist = f;
1343e12c5d1SDavid du Colombier 		}
1353e12c5d1SDavid du Colombier 		return 0;
1363e12c5d1SDavid du Colombier 	}
1373e12c5d1SDavid du Colombier 	if(f)
1383e12c5d1SDavid du Colombier 		return clean(f);
1393e12c5d1SDavid du Colombier 	if(f = freelist)	/* assign = */
1403e12c5d1SDavid du Colombier 		freelist = f->next;
1413e12c5d1SDavid du Colombier 	else
1423e12c5d1SDavid du Colombier 		f = ealloc(sizeof(Xfile));
1433e12c5d1SDavid du Colombier 	f->next = *hp;
1443e12c5d1SDavid du Colombier 	*hp = f;
1453e12c5d1SDavid du Colombier 	f->xf = 0;
1463e12c5d1SDavid du Colombier 	f->fid = fid;
1473e12c5d1SDavid du Colombier 	f->flags = 0;
1489a747e4fSDavid du Colombier 	f->qid = (Qid){0,0,0};
1493e12c5d1SDavid du Colombier 	f->len = 0;
1503e12c5d1SDavid du Colombier 	f->ptr = 0;
1513e12c5d1SDavid du Colombier 	return f;
1523e12c5d1SDavid du Colombier }
1533e12c5d1SDavid du Colombier 
1543e12c5d1SDavid du Colombier static Xfile *
clean(Xfile * f)1553e12c5d1SDavid du Colombier clean(Xfile *f)
1563e12c5d1SDavid du Colombier {
1573e12c5d1SDavid du Colombier 	if(f->xf){
1583e12c5d1SDavid du Colombier 		refxfs(f->xf, -1);
1593e12c5d1SDavid du Colombier 		f->xf = 0;
1603e12c5d1SDavid du Colombier 	}
1613e12c5d1SDavid du Colombier 	if(f->len){
1623e12c5d1SDavid du Colombier 		free(f->ptr);
1633e12c5d1SDavid du Colombier 		f->len = 0;
1643e12c5d1SDavid du Colombier 	}
1653e12c5d1SDavid du Colombier 	f->ptr = 0;
1663e12c5d1SDavid du Colombier 	f->flags = 0;
1679a747e4fSDavid du Colombier 	f->qid = (Qid){0,0,0};
1683e12c5d1SDavid du Colombier 	return f;
1693e12c5d1SDavid du Colombier }
1703e12c5d1SDavid du Colombier 
171