plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

xfile.c (2735B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <auth.h>
      4 #include <fcall.h>
      5 #include "dat.h"
      6 #include "fns.h"
      7 
      8 static Xfile*	clean(Xfile*);
      9 
     10 #define	FIDMOD	127	/* prime */
     11 
     12 static Xdata*	xhead;
     13 static Xfile*	xfiles[FIDMOD];
     14 static Xfile*	freelist;
     15 
     16 Xdata*
     17 getxdata(char *name)
     18 {
     19 	int fd;
     20 	Dir *dir;
     21 	Xdata *xf, *fxf;
     22 	int flag;
     23 
     24 	if(name[0] == 0)
     25 		name = deffile;
     26 	if(name == 0)
     27 		error(Enofile);
     28 	flag = (access(name, 6) == 0) ? ORDWR : OREAD;
     29 	fd = open(name, flag);
     30 	if(fd < 0)
     31 		error(Enonexist);
     32 	dir = nil;
     33 	if(waserror()){
     34 		close(fd);
     35 		free(dir);
     36 		nexterror();
     37 	}
     38 	if((dir = dirfstat(fd)) == nil)
     39 		error("I/O error");
     40 	if((dir->qid.type & ~QTTMP) != QTFILE)
     41 		error("attach name not a plain file");
     42 	for(fxf=0,xf=xhead; xf; xf=xf->next){
     43 		if(xf->name == 0){
     44 			if(fxf == 0)
     45 				fxf = xf;
     46 			continue;
     47 		}
     48 		if(xf->qid.path != dir->qid.path || xf->qid.vers != dir->qid.vers)
     49 			continue;
     50 		if(xf->type != dir->type || xf->fdev != dir->dev)
     51 			continue;
     52 		xf->ref++;
     53 		chat("incref=%d, \"%s\", dev=%d...", xf->ref, xf->name, xf->dev);
     54 		close(fd);
     55 		poperror();
     56 		free(dir);
     57 		return xf;
     58 	}
     59 	if(fxf==0){
     60 		fxf = ealloc(sizeof(Xfs));
     61 		fxf->next = xhead;
     62 		xhead = fxf;
     63 	}
     64 	chat("alloc \"%s\", dev=%d...", name, fd);
     65 	fxf->ref = 1;
     66 	fxf->name = strcpy(ealloc(strlen(name)+1), name);
     67 	fxf->qid = dir->qid;
     68 	fxf->type = dir->type;
     69 	fxf->fdev = dir->dev;
     70 	fxf->dev = fd;
     71 	free(dir);
     72 	poperror();
     73 	return fxf;
     74 }
     75 
     76 static void
     77 putxdata(Xdata *d)
     78 {
     79 	if(d->ref <= 0)
     80 		panic(0, "putxdata");
     81 	d->ref--;
     82 	chat("decref=%d, \"%s\", dev=%d...", d->ref, d->name, d->dev);
     83 	if(d->ref == 0){
     84 		chat("purgebuf...");
     85 		purgebuf(d);
     86 		close(d->dev);
     87 		free(d->name);
     88 		d->name = 0;
     89 	}
     90 }
     91 
     92 void
     93 refxfs(Xfs *xf, int delta)
     94 {
     95 	xf->ref += delta;
     96 	if(xf->ref == 0){
     97 		if(xf->d)
     98 			putxdata(xf->d);
     99 		if(xf->ptr)
    100 			free(xf->ptr);
    101 		free(xf);
    102 	}
    103 }
    104 
    105 Xfile*
    106 xfile(int fid, int flag)
    107 {
    108 	int k = fid%FIDMOD;
    109 	Xfile **hp=&xfiles[k], *f, *pf;
    110 
    111 	for(f=*hp,pf=0; f; pf=f,f=f->next)
    112 		if(f->fid == fid)
    113 			break;
    114 	if(f && pf){
    115 		pf->next = f->next;
    116 		f->next = *hp;
    117 		*hp = f;
    118 	}
    119 	switch(flag){
    120 	default:
    121 		panic(0, "xfile");
    122 	case Asis:
    123 		if(f == 0)
    124 			error("unassigned fid");
    125 		return f;
    126 	case Clean:
    127 		break;
    128 	case Clunk:
    129 		if(f){
    130 			*hp = f->next;
    131 			clean(f);
    132 			f->next = freelist;
    133 			freelist = f;
    134 		}
    135 		return 0;
    136 	}
    137 	if(f)
    138 		return clean(f);
    139 	if(f = freelist)	/* assign = */
    140 		freelist = f->next;
    141 	else
    142 		f = ealloc(sizeof(Xfile));
    143 	f->next = *hp;
    144 	*hp = f;
    145 	f->xf = 0;
    146 	f->fid = fid;
    147 	f->flags = 0;
    148 	f->qid = (Qid){0,0,0};
    149 	f->len = 0;
    150 	f->ptr = 0;
    151 	return f;
    152 }
    153 
    154 static Xfile *
    155 clean(Xfile *f)
    156 {
    157 	if(f->xf){
    158 		refxfs(f->xf, -1);
    159 		f->xf = 0;
    160 	}
    161 	if(f->len){
    162 		free(f->ptr);
    163 		f->len = 0;
    164 	}
    165 	f->ptr = 0;
    166 	f->flags = 0;
    167 	f->qid = (Qid){0,0,0};
    168 	return f;
    169 }