]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/ext2srv/xfile.c
mothra: fix alt display resizing, filter control characters in panel entries, use...
[plan9front.git] / sys / src / cmd / ext2srv / xfile.c
1 #include <u.h>
2 #include <libc.h>
3 #include <fcall.h>
4 #include <thread.h>
5 #include <9p.h>
6 #include "dat.h"
7 #include "fns.h"
8
9
10 static Xfs      *xhead;
11 static Xfile *freelist;
12 static Lock     xlock, freelock;
13
14 int     client;
15
16 Xfs *
17 getxfs(char *name)
18 {
19         int fd;
20         Dir *dir;
21         Xfs *xf, *fxf;
22
23         if(name==0 || name[0]==0)
24                 name = deffile;
25         if(name == 0){
26                 errno = Enofilsys;
27                 return 0;
28         }
29         fd = open(name, rdonly ? OREAD : ORDWR);
30         if(fd < 0){
31                 errno = Enonexist;
32                 return 0;
33         }
34         if((dir = dirfstat(fd)) == 0){
35                 errno = Eio;
36                 close(fd);
37                 return 0;
38         }
39         lock(&xlock);
40         for(fxf=0, xf=xhead; xf; xf=xf->next){
41                 if(xf->ref == 0){
42                         if(fxf == 0)
43                                 fxf = xf;
44                         continue;
45                 }
46                 if(xf->qid.path != dir->qid.path || xf->qid.vers != dir->qid.vers)
47                         continue;
48                 if(strcmp(xf->name, name) != 0 || xf->dev < 0)
49                         continue;
50                 chat("incref \"%s\", dev=%d...", xf->name, xf->dev);
51                 ++xf->ref;
52                 unlock(&xlock);
53                 close(fd);
54                 free(dir);
55                 return xf;
56         }
57         if(fxf==0){
58                 fxf = malloc(sizeof(Xfs));
59                 if(fxf==0){
60                         unlock(&xlock);
61                         close(fd);
62                         free(dir);
63                         errno = Enomem;
64                         return 0;
65                 }
66                 fxf->next = xhead;
67                 xhead = fxf;
68         }
69         chat("alloc \"%s\", dev=%d...", name, fd);
70         fxf->name = strdup(name);
71         fxf->ref = 1;
72         fxf->qid = dir->qid;
73         fxf->dev = fd;
74         fxf->fmt = 0;
75         fxf->ptr = 0;
76         free(dir);
77         if( ext2fs(fxf)<0 ){ 
78                 xhead = fxf->next;
79                 free(fxf);
80                 unlock(&xlock);
81                 return 0;
82         }
83         unlock(&xlock);
84         return fxf;
85 }
86
87 void
88 refxfs(Xfs *xf, int delta)
89 {
90         lock(&xlock);
91         xf->ref += delta;
92         if(xf->ref == 0){
93                 /*mchat("free \"%s\", dev=%d...", xf->name, xf->dev);
94                 dumpbuf();*/
95                 CleanSuper(xf);
96                 syncbuf();
97                 free(xf->name);
98                 purgebuf(xf);
99                 if(xf->dev >= 0){
100                         close(xf->dev);
101                         xf->dev = -1;
102                 }
103         }
104         unlock(&xlock);
105 }
106
107 Xfile *
108 xfile(Fid *fid, int flag)
109 {
110         Xfile *f;
111
112         f = (Xfile*)fid->aux;
113         switch(flag){
114         default:
115                 panic("xfile");
116         case Asis:
117                 return (f && f->xf && f->xf->dev < 0) ? 0 : f;
118         case Clean:
119                 if (f) chat("Clean and fid->aux already exists\n");
120                 break;
121         case Clunk:
122                 if(f){
123                         clean(f);
124                         lock(&freelock);
125                         f->next = freelist;
126                         freelist = f;
127                         unlock(&freelock);
128                         fid->aux = 0;
129                 }
130                 return 0;
131         }
132         if(f)
133                 return clean(f);
134         lock(&freelock);
135         if(f = freelist){       /* assign = */
136                 freelist = f->next;
137                 unlock(&freelock);
138         } else {
139                 unlock(&freelock);
140                 f = malloc(sizeof(Xfile));
141         }
142         fid->aux = f;
143         f->fid = fid->fid;
144         f->client = client;
145         f->xf = 0;
146         f->ptr = 0;
147         f->root = 0;
148         return f;
149 }
150 Xfile *
151 clean(Xfile *f)
152 {
153         if(f->xf && f->root){
154                 refxfs(f->xf, -1);
155                 f->xf = 0;
156         }
157         f->xf = 0;
158         f->root = 0;
159         f->dirindex = 0;
160         return f;
161 }