Blob
1 #include <u.h>2 #include <libc.h>3 #include <auth.h>4 #include <fcall.h>5 #include "dat.h"6 #include "fns.h"8 static Xfile* clean(Xfile*);10 #define FIDMOD 127 /* prime */12 static Xdata* xhead;13 static Xfile* xfiles[FIDMOD];14 static Xfile* freelist;16 Xdata*17 getxdata(char *name)18 {19 int fd;20 Dir *dir;21 Xdata *xf, *fxf;22 int flag;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 }76 static void77 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 }92 void93 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 }105 Xfile*106 xfile(int fid, int flag)107 {108 int k = fid%FIDMOD;109 Xfile **hp=&xfiles[k], *f, *pf;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 else142 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 }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 }