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 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 }
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);
105 Xfile*
106 xfile(int fid, int flag)
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;
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;
135 return 0;
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;
154 static Xfile *
155 clean(Xfile *f)
157 if(f->xf){
158 refxfs(f->xf, -1);
159 f->xf = 0;
161 if(f->len){
162 free(f->ptr);
163 f->len = 0;
165 f->ptr = 0;
166 f->flags = 0;
167 f->qid = (Qid){0,0,0};
168 return f;