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 if(waserror()){ 33 close(fd); 34 nexterror(); 35 } 36 if(dirfstat(fd, &dir) < 0) 37 error("I/O error"); 38 for(fxf=0,xf=xhead; xf; xf=xf->next){ 39 if(xf->name == 0){ 40 if(fxf == 0) 41 fxf = xf; 42 continue; 43 } 44 if(xf->qid.path != dir.qid.path || xf->qid.vers != dir.qid.vers) 45 continue; 46 if(xf->type != dir.type || xf->fdev != dir.dev) 47 continue; 48 xf->ref++; 49 chat("incref=%d, \"%s\", dev=%d...", xf->ref, xf->name, xf->dev); 50 close(fd); 51 poperror(); 52 return xf; 53 } 54 if(fxf==0){ 55 fxf = ealloc(sizeof(Xfs)); 56 fxf->next = xhead; 57 xhead = fxf; 58 } 59 chat("alloc \"%s\", dev=%d...", name, fd); 60 fxf->ref = 1; 61 fxf->name = strcpy(ealloc(strlen(name)+1), name); 62 fxf->qid = dir.qid; 63 fxf->type = dir.type; 64 fxf->fdev = dir.dev; 65 fxf->dev = fd; 66 poperror(); 67 return fxf; 68 } 69 70 static void 71 putxdata(Xdata *d) 72 { 73 if(d->ref <= 0) 74 panic(0, "putxdata"); 75 d->ref--; 76 chat("decref=%d, \"%s\", dev=%d...", d->ref, d->name, d->dev); 77 if(d->ref == 0){ 78 chat("purgebuf..."); 79 purgebuf(d); 80 close(d->dev); 81 free(d->name); 82 d->name = 0; 83 } 84 } 85 86 void 87 refxfs(Xfs *xf, int delta) 88 { 89 xf->ref += delta; 90 if(xf->ref == 0){ 91 if(xf->d) 92 putxdata(xf->d); 93 if(xf->ptr) 94 free(xf->ptr); 95 free(xf); 96 } 97 } 98 99 Xfile* 100 xfile(int fid, int flag) 101 { 102 int k = fid%FIDMOD; 103 Xfile **hp=&xfiles[k], *f, *pf; 104 105 for(f=*hp,pf=0; f; pf=f,f=f->next) 106 if(f->fid == fid) 107 break; 108 if(f && pf){ 109 pf->next = f->next; 110 f->next = *hp; 111 *hp = f; 112 } 113 switch(flag){ 114 default: 115 panic(0, "xfile"); 116 case Asis: 117 if(f == 0) 118 error("unassigned fid"); 119 return f; 120 case Clean: 121 break; 122 case Clunk: 123 if(f){ 124 *hp = f->next; 125 clean(f); 126 f->next = freelist; 127 freelist = f; 128 } 129 return 0; 130 } 131 if(f) 132 return clean(f); 133 if(f = freelist) /* assign = */ 134 freelist = f->next; 135 else 136 f = ealloc(sizeof(Xfile)); 137 f->next = *hp; 138 *hp = f; 139 f->xf = 0; 140 f->fid = fid; 141 f->flags = 0; 142 f->qid = (Qid){0,0}; 143 f->len = 0; 144 f->ptr = 0; 145 return f; 146 } 147 148 static Xfile * 149 clean(Xfile *f) 150 { 151 if(f->xf){ 152 refxfs(f->xf, -1); 153 f->xf = 0; 154 } 155 if(f->len){ 156 free(f->ptr); 157 f->len = 0; 158 } 159 f->ptr = 0; 160 f->flags = 0; 161 f->qid = (Qid){0,0}; 162 return f; 163 } 164 165 void 166 xread(Iobuf *p) 167 { 168 Xdata *dev; 169 long addr; 170 171 dev = p->dev; 172 addr = p->addr; 173 chat("xread %d,%d...", dev->dev, addr); 174 175 seek(dev->dev, addr*Sectorsize, 0); 176 if(read(dev->dev, p->iobuf, Sectorsize) != Sectorsize) 177 error("I/O read error"); 178 } 179