URI:
       txfile.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       txfile.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 }