Blame


1 2277c5d7 2004-03-21 devnull #include <u.h>
2 2277c5d7 2004-03-21 devnull #include <libc.h>
3 2277c5d7 2004-03-21 devnull #include <fcall.h>
4 2277c5d7 2004-03-21 devnull #include <thread.h>
5 2277c5d7 2004-03-21 devnull #include <9p.h>
6 2277c5d7 2004-03-21 devnull
7 2277c5d7 2004-03-21 devnull /*
8 2277c5d7 2004-03-21 devnull * To avoid deadlock, the following rules must be followed.
9 2277c5d7 2004-03-21 devnull * Always lock child then parent, never parent then child.
10 2277c5d7 2004-03-21 devnull * If holding the free file lock, do not lock any Files.
11 2277c5d7 2004-03-21 devnull */
12 2277c5d7 2004-03-21 devnull struct Filelist {
13 2277c5d7 2004-03-21 devnull File *f;
14 2277c5d7 2004-03-21 devnull Filelist *link;
15 2277c5d7 2004-03-21 devnull };
16 2277c5d7 2004-03-21 devnull
17 2277c5d7 2004-03-21 devnull static QLock filelk;
18 2277c5d7 2004-03-21 devnull static File *freefilelist;
19 2277c5d7 2004-03-21 devnull
20 2277c5d7 2004-03-21 devnull static File*
21 2277c5d7 2004-03-21 devnull allocfile(void)
22 2277c5d7 2004-03-21 devnull {
23 2277c5d7 2004-03-21 devnull int i, a;
24 2277c5d7 2004-03-21 devnull File *f;
25 2277c5d7 2004-03-21 devnull enum { N = 16 };
26 2277c5d7 2004-03-21 devnull
27 2277c5d7 2004-03-21 devnull qlock(&filelk);
28 2277c5d7 2004-03-21 devnull if(freefilelist == nil){
29 2277c5d7 2004-03-21 devnull f = emalloc9p(N*sizeof(*f));
30 2277c5d7 2004-03-21 devnull for(i=0; i<N-1; i++)
31 2277c5d7 2004-03-21 devnull f[i].aux = &f[i+1];
32 2277c5d7 2004-03-21 devnull f[N-1].aux = nil;
33 2277c5d7 2004-03-21 devnull f[0].allocd = 1;
34 2277c5d7 2004-03-21 devnull freefilelist = f;
35 2277c5d7 2004-03-21 devnull }
36 2277c5d7 2004-03-21 devnull
37 2277c5d7 2004-03-21 devnull f = freefilelist;
38 2277c5d7 2004-03-21 devnull freefilelist = f->aux;
39 2277c5d7 2004-03-21 devnull qunlock(&filelk);
40 2277c5d7 2004-03-21 devnull
41 2277c5d7 2004-03-21 devnull a = f->allocd;
42 2277c5d7 2004-03-21 devnull memset(f, 0, sizeof *f);
43 2277c5d7 2004-03-21 devnull f->allocd = a;
44 2277c5d7 2004-03-21 devnull return f;
45 2277c5d7 2004-03-21 devnull }
46 2277c5d7 2004-03-21 devnull
47 2277c5d7 2004-03-21 devnull static void
48 2277c5d7 2004-03-21 devnull freefile(File *f)
49 2277c5d7 2004-03-21 devnull {
50 2277c5d7 2004-03-21 devnull Filelist *fl, *flnext;
51 2277c5d7 2004-03-21 devnull
52 2277c5d7 2004-03-21 devnull for(fl=f->filelist; fl; fl=flnext){
53 2277c5d7 2004-03-21 devnull flnext = fl->link;
54 2277c5d7 2004-03-21 devnull assert(fl->f == nil);
55 2277c5d7 2004-03-21 devnull free(fl);
56 2277c5d7 2004-03-21 devnull }
57 2277c5d7 2004-03-21 devnull
58 2277c5d7 2004-03-21 devnull free(f->dir.name);
59 2277c5d7 2004-03-21 devnull free(f->dir.uid);
60 2277c5d7 2004-03-21 devnull free(f->dir.gid);
61 2277c5d7 2004-03-21 devnull free(f->dir.muid);
62 2277c5d7 2004-03-21 devnull qlock(&filelk);
63 2277c5d7 2004-03-21 devnull assert(f->ref.ref == 0);
64 2277c5d7 2004-03-21 devnull f->aux = freefilelist;
65 2277c5d7 2004-03-21 devnull freefilelist = f;
66 2277c5d7 2004-03-21 devnull qunlock(&filelk);
67 2277c5d7 2004-03-21 devnull }
68 2277c5d7 2004-03-21 devnull
69 2277c5d7 2004-03-21 devnull void
70 2277c5d7 2004-03-21 devnull closefile(File *f)
71 2277c5d7 2004-03-21 devnull {
72 2277c5d7 2004-03-21 devnull if(decref(&f->ref) == 0){
73 2277c5d7 2004-03-21 devnull f->tree->destroy(f);
74 2277c5d7 2004-03-21 devnull freefile(f);
75 2277c5d7 2004-03-21 devnull }
76 2277c5d7 2004-03-21 devnull }
77 2277c5d7 2004-03-21 devnull
78 2277c5d7 2004-03-21 devnull static void
79 2277c5d7 2004-03-21 devnull nop(File *f)
80 2277c5d7 2004-03-21 devnull {
81 2277c5d7 2004-03-21 devnull USED(f);
82 2277c5d7 2004-03-21 devnull }
83 2277c5d7 2004-03-21 devnull
84 2277c5d7 2004-03-21 devnull int
85 2277c5d7 2004-03-21 devnull removefile(File *f)
86 2277c5d7 2004-03-21 devnull {
87 2277c5d7 2004-03-21 devnull File *fp;
88 2277c5d7 2004-03-21 devnull Filelist *fl;
89 fa325e9b 2020-01-10 cross
90 2277c5d7 2004-03-21 devnull fp = f->parent;
91 2277c5d7 2004-03-21 devnull if(fp == nil){
92 2277c5d7 2004-03-21 devnull werrstr("no parent");
93 2277c5d7 2004-03-21 devnull closefile(f);
94 2277c5d7 2004-03-21 devnull return -1;
95 2277c5d7 2004-03-21 devnull }
96 2277c5d7 2004-03-21 devnull
97 2277c5d7 2004-03-21 devnull if(fp == f){
98 2277c5d7 2004-03-21 devnull werrstr("cannot remove root");
99 2277c5d7 2004-03-21 devnull closefile(f);
100 2277c5d7 2004-03-21 devnull return -1;
101 2277c5d7 2004-03-21 devnull }
102 2277c5d7 2004-03-21 devnull
103 2277c5d7 2004-03-21 devnull wlock(&fp->rwlock);
104 2277c5d7 2004-03-21 devnull wlock(&f->rwlock);
105 2277c5d7 2004-03-21 devnull if(f->nchild != 0){
106 2277c5d7 2004-03-21 devnull werrstr("has children");
107 2277c5d7 2004-03-21 devnull wunlock(&f->rwlock);
108 2277c5d7 2004-03-21 devnull wunlock(&fp->rwlock);
109 2277c5d7 2004-03-21 devnull closefile(f);
110 2277c5d7 2004-03-21 devnull return -1;
111 2277c5d7 2004-03-21 devnull }
112 2277c5d7 2004-03-21 devnull
113 2277c5d7 2004-03-21 devnull if(f->parent != fp){
114 2277c5d7 2004-03-21 devnull werrstr("parent changed underfoot");
115 2277c5d7 2004-03-21 devnull wunlock(&f->rwlock);
116 2277c5d7 2004-03-21 devnull wunlock(&fp->rwlock);
117 2277c5d7 2004-03-21 devnull closefile(f);
118 2277c5d7 2004-03-21 devnull return -1;
119 2277c5d7 2004-03-21 devnull }
120 2277c5d7 2004-03-21 devnull
121 2277c5d7 2004-03-21 devnull for(fl=fp->filelist; fl; fl=fl->link)
122 2277c5d7 2004-03-21 devnull if(fl->f == f)
123 2277c5d7 2004-03-21 devnull break;
124 2277c5d7 2004-03-21 devnull assert(fl != nil && fl->f == f);
125 2277c5d7 2004-03-21 devnull
126 2277c5d7 2004-03-21 devnull fl->f = nil;
127 2277c5d7 2004-03-21 devnull fp->nchild--;
128 2277c5d7 2004-03-21 devnull f->parent = nil;
129 2277c5d7 2004-03-21 devnull wunlock(&fp->rwlock);
130 2277c5d7 2004-03-21 devnull wunlock(&f->rwlock);
131 2277c5d7 2004-03-21 devnull
132 2277c5d7 2004-03-21 devnull closefile(fp); /* reference from child */
133 2277c5d7 2004-03-21 devnull closefile(f); /* reference from tree */
134 2277c5d7 2004-03-21 devnull closefile(f);
135 2277c5d7 2004-03-21 devnull return 0;
136 2277c5d7 2004-03-21 devnull }
137 2277c5d7 2004-03-21 devnull
138 2277c5d7 2004-03-21 devnull File*
139 2277c5d7 2004-03-21 devnull createfile(File *fp, char *name, char *uid, ulong perm, void *aux)
140 2277c5d7 2004-03-21 devnull {
141 2277c5d7 2004-03-21 devnull File *f;
142 2277c5d7 2004-03-21 devnull Filelist *fl, *freel;
143 2277c5d7 2004-03-21 devnull Tree *t;
144 2277c5d7 2004-03-21 devnull
145 2277c5d7 2004-03-21 devnull if((fp->dir.qid.type&QTDIR) == 0){
146 2277c5d7 2004-03-21 devnull werrstr("create in non-directory");
147 2277c5d7 2004-03-21 devnull return nil;
148 2277c5d7 2004-03-21 devnull }
149 2277c5d7 2004-03-21 devnull
150 2277c5d7 2004-03-21 devnull freel = nil;
151 2277c5d7 2004-03-21 devnull wlock(&fp->rwlock);
152 2277c5d7 2004-03-21 devnull for(fl=fp->filelist; fl; fl=fl->link){
153 2277c5d7 2004-03-21 devnull if(fl->f == nil)
154 2277c5d7 2004-03-21 devnull freel = fl;
155 2277c5d7 2004-03-21 devnull else if(strcmp(fl->f->dir.name, name) == 0){
156 2277c5d7 2004-03-21 devnull wunlock(&fp->rwlock);
157 2277c5d7 2004-03-21 devnull werrstr("file already exists");
158 2277c5d7 2004-03-21 devnull return nil;
159 2277c5d7 2004-03-21 devnull }
160 2277c5d7 2004-03-21 devnull }
161 2277c5d7 2004-03-21 devnull
162 2277c5d7 2004-03-21 devnull if(freel == nil){
163 2277c5d7 2004-03-21 devnull freel = emalloc9p(sizeof *freel);
164 2277c5d7 2004-03-21 devnull freel->link = fp->filelist;
165 2277c5d7 2004-03-21 devnull fp->filelist = freel;
166 2277c5d7 2004-03-21 devnull }
167 2277c5d7 2004-03-21 devnull
168 2277c5d7 2004-03-21 devnull f = allocfile();
169 2277c5d7 2004-03-21 devnull f->dir.name = estrdup9p(name);
170 2277c5d7 2004-03-21 devnull f->dir.uid = estrdup9p(uid ? uid : fp->dir.uid);
171 2277c5d7 2004-03-21 devnull f->dir.gid = estrdup9p(fp->dir.gid);
172 2277c5d7 2004-03-21 devnull f->dir.muid = estrdup9p(uid ? uid : "unknown");
173 2277c5d7 2004-03-21 devnull f->aux = aux;
174 2277c5d7 2004-03-21 devnull f->dir.mode = perm;
175 2277c5d7 2004-03-21 devnull
176 2277c5d7 2004-03-21 devnull t = fp->tree;
177 2277c5d7 2004-03-21 devnull lock(&t->genlock);
178 2277c5d7 2004-03-21 devnull f->dir.qid.path = t->qidgen++;
179 2277c5d7 2004-03-21 devnull unlock(&t->genlock);
180 2277c5d7 2004-03-21 devnull if(perm & DMDIR)
181 2277c5d7 2004-03-21 devnull f->dir.qid.type |= QTDIR;
182 2277c5d7 2004-03-21 devnull if(perm & DMAPPEND)
183 2277c5d7 2004-03-21 devnull f->dir.qid.type |= QTAPPEND;
184 2277c5d7 2004-03-21 devnull if(perm & DMEXCL)
185 2277c5d7 2004-03-21 devnull f->dir.qid.type |= QTEXCL;
186 2277c5d7 2004-03-21 devnull
187 2277c5d7 2004-03-21 devnull f->dir.mode = perm;
188 2277c5d7 2004-03-21 devnull f->dir.atime = f->dir.mtime = time(0);
189 2277c5d7 2004-03-21 devnull f->dir.length = 0;
190 2277c5d7 2004-03-21 devnull f->parent = fp;
191 2277c5d7 2004-03-21 devnull incref(&fp->ref);
192 2277c5d7 2004-03-21 devnull f->tree = fp->tree;
193 2277c5d7 2004-03-21 devnull
194 2277c5d7 2004-03-21 devnull incref(&f->ref); /* being returned */
195 2277c5d7 2004-03-21 devnull incref(&f->ref); /* for the tree */
196 2277c5d7 2004-03-21 devnull freel->f = f;
197 2277c5d7 2004-03-21 devnull fp->nchild++;
198 2277c5d7 2004-03-21 devnull wunlock(&fp->rwlock);
199 2277c5d7 2004-03-21 devnull
200 2277c5d7 2004-03-21 devnull return f;
201 2277c5d7 2004-03-21 devnull }
202 2277c5d7 2004-03-21 devnull
203 2277c5d7 2004-03-21 devnull static File*
204 2277c5d7 2004-03-21 devnull walkfile1(File *dir, char *elem)
205 2277c5d7 2004-03-21 devnull {
206 2277c5d7 2004-03-21 devnull File *fp;
207 2277c5d7 2004-03-21 devnull Filelist *fl;
208 2277c5d7 2004-03-21 devnull
209 2277c5d7 2004-03-21 devnull rlock(&dir->rwlock);
210 2277c5d7 2004-03-21 devnull if(strcmp(elem, "..") == 0){
211 2277c5d7 2004-03-21 devnull fp = dir->parent;
212 2277c5d7 2004-03-21 devnull incref(&fp->ref);
213 2277c5d7 2004-03-21 devnull runlock(&dir->rwlock);
214 2277c5d7 2004-03-21 devnull closefile(dir);
215 2277c5d7 2004-03-21 devnull return fp;
216 2277c5d7 2004-03-21 devnull }
217 2277c5d7 2004-03-21 devnull
218 2277c5d7 2004-03-21 devnull fp = nil;
219 2277c5d7 2004-03-21 devnull for(fl=dir->filelist; fl; fl=fl->link)
220 2277c5d7 2004-03-21 devnull if(fl->f && strcmp(fl->f->dir.name, elem)==0){
221 2277c5d7 2004-03-21 devnull fp = fl->f;
222 2277c5d7 2004-03-21 devnull incref(&fp->ref);
223 2277c5d7 2004-03-21 devnull break;
224 2277c5d7 2004-03-21 devnull }
225 2277c5d7 2004-03-21 devnull
226 2277c5d7 2004-03-21 devnull runlock(&dir->rwlock);
227 2277c5d7 2004-03-21 devnull closefile(dir);
228 2277c5d7 2004-03-21 devnull return fp;
229 2277c5d7 2004-03-21 devnull }
230 2277c5d7 2004-03-21 devnull
231 2277c5d7 2004-03-21 devnull File*
232 2277c5d7 2004-03-21 devnull walkfile(File *f, char *path)
233 2277c5d7 2004-03-21 devnull {
234 2277c5d7 2004-03-21 devnull char *os, *s, *nexts;
235 2277c5d7 2004-03-21 devnull
236 2277c5d7 2004-03-21 devnull if(strchr(path, '/') == nil)
237 2277c5d7 2004-03-21 devnull return walkfile1(f, path); /* avoid malloc */
238 2277c5d7 2004-03-21 devnull
239 2277c5d7 2004-03-21 devnull os = s = estrdup9p(path);
240 2277c5d7 2004-03-21 devnull for(; *s; s=nexts){
241 2277c5d7 2004-03-21 devnull if(nexts = strchr(s, '/'))
242 2277c5d7 2004-03-21 devnull *nexts++ = '\0';
243 2277c5d7 2004-03-21 devnull else
244 2277c5d7 2004-03-21 devnull nexts = s+strlen(s);
245 729e53b9 2006-10-12 devnull f = walkfile1(f, s);
246 2277c5d7 2004-03-21 devnull if(f == nil)
247 2277c5d7 2004-03-21 devnull break;
248 2277c5d7 2004-03-21 devnull }
249 2277c5d7 2004-03-21 devnull free(os);
250 2277c5d7 2004-03-21 devnull return f;
251 a0f1e21f 2004-04-20 devnull }
252 a0f1e21f 2004-04-20 devnull
253 a0f1e21f 2004-04-20 devnull static Qid
254 a0f1e21f 2004-04-20 devnull mkqid(vlong path, long vers, int type)
255 a0f1e21f 2004-04-20 devnull {
256 a0f1e21f 2004-04-20 devnull Qid q;
257 a0f1e21f 2004-04-20 devnull
258 a0f1e21f 2004-04-20 devnull q.path = path;
259 a0f1e21f 2004-04-20 devnull q.vers = vers;
260 a0f1e21f 2004-04-20 devnull q.type = type;
261 a0f1e21f 2004-04-20 devnull return q;
262 2277c5d7 2004-03-21 devnull }
263 a0f1e21f 2004-04-20 devnull
264 fa325e9b 2020-01-10 cross
265 2277c5d7 2004-03-21 devnull Tree*
266 2277c5d7 2004-03-21 devnull alloctree(char *uid, char *gid, ulong mode, void (*destroy)(File*))
267 2277c5d7 2004-03-21 devnull {
268 2277c5d7 2004-03-21 devnull char *muid;
269 2277c5d7 2004-03-21 devnull Tree *t;
270 2277c5d7 2004-03-21 devnull File *f;
271 2277c5d7 2004-03-21 devnull
272 2277c5d7 2004-03-21 devnull t = emalloc9p(sizeof *t);
273 2277c5d7 2004-03-21 devnull f = allocfile();
274 2277c5d7 2004-03-21 devnull f->dir.name = estrdup9p("/");
275 2277c5d7 2004-03-21 devnull if(uid == nil){
276 2277c5d7 2004-03-21 devnull if(uid = getuser())
277 2277c5d7 2004-03-21 devnull uid = estrdup9p(uid);
278 2277c5d7 2004-03-21 devnull }
279 2277c5d7 2004-03-21 devnull if(uid == nil)
280 2277c5d7 2004-03-21 devnull uid = estrdup9p("none");
281 2277c5d7 2004-03-21 devnull else
282 2277c5d7 2004-03-21 devnull uid = estrdup9p(uid);
283 2277c5d7 2004-03-21 devnull
284 2277c5d7 2004-03-21 devnull if(gid == nil)
285 2277c5d7 2004-03-21 devnull gid = estrdup9p(uid);
286 2277c5d7 2004-03-21 devnull else
287 2277c5d7 2004-03-21 devnull gid = estrdup9p(gid);
288 2277c5d7 2004-03-21 devnull
289 2277c5d7 2004-03-21 devnull muid = estrdup9p(uid);
290 2277c5d7 2004-03-21 devnull
291 a0f1e21f 2004-04-20 devnull f->dir.qid = mkqid(0, 0, QTDIR);
292 2277c5d7 2004-03-21 devnull f->dir.length = 0;
293 2277c5d7 2004-03-21 devnull f->dir.atime = f->dir.mtime = time(0);
294 2277c5d7 2004-03-21 devnull f->dir.mode = DMDIR | mode;
295 2277c5d7 2004-03-21 devnull f->tree = t;
296 2277c5d7 2004-03-21 devnull f->parent = f;
297 2277c5d7 2004-03-21 devnull f->dir.uid = uid;
298 2277c5d7 2004-03-21 devnull f->dir.gid = gid;
299 2277c5d7 2004-03-21 devnull f->dir.muid = muid;
300 2277c5d7 2004-03-21 devnull
301 2277c5d7 2004-03-21 devnull incref(&f->ref);
302 2277c5d7 2004-03-21 devnull t->root = f;
303 2277c5d7 2004-03-21 devnull t->qidgen = 0;
304 2277c5d7 2004-03-21 devnull t->dirqidgen = 1;
305 2277c5d7 2004-03-21 devnull if(destroy == nil)
306 2277c5d7 2004-03-21 devnull destroy = nop;
307 2277c5d7 2004-03-21 devnull t->destroy = destroy;
308 2277c5d7 2004-03-21 devnull
309 2277c5d7 2004-03-21 devnull return t;
310 2277c5d7 2004-03-21 devnull }
311 2277c5d7 2004-03-21 devnull
312 2277c5d7 2004-03-21 devnull static void
313 2277c5d7 2004-03-21 devnull _freefiles(File *f)
314 2277c5d7 2004-03-21 devnull {
315 2277c5d7 2004-03-21 devnull Filelist *fl, *flnext;
316 2277c5d7 2004-03-21 devnull
317 2277c5d7 2004-03-21 devnull for(fl=f->filelist; fl; fl=flnext){
318 2277c5d7 2004-03-21 devnull flnext = fl->link;
319 2277c5d7 2004-03-21 devnull _freefiles(fl->f);
320 2277c5d7 2004-03-21 devnull free(fl);
321 2277c5d7 2004-03-21 devnull }
322 2277c5d7 2004-03-21 devnull
323 2277c5d7 2004-03-21 devnull f->tree->destroy(f);
324 2277c5d7 2004-03-21 devnull freefile(f);
325 2277c5d7 2004-03-21 devnull }
326 2277c5d7 2004-03-21 devnull
327 2277c5d7 2004-03-21 devnull void
328 2277c5d7 2004-03-21 devnull freetree(Tree *t)
329 2277c5d7 2004-03-21 devnull {
330 2277c5d7 2004-03-21 devnull _freefiles(t->root);
331 2277c5d7 2004-03-21 devnull free(t);
332 2277c5d7 2004-03-21 devnull }
333 2277c5d7 2004-03-21 devnull
334 2277c5d7 2004-03-21 devnull struct Readdir {
335 2277c5d7 2004-03-21 devnull Filelist *fl;
336 2277c5d7 2004-03-21 devnull };
337 2277c5d7 2004-03-21 devnull
338 2277c5d7 2004-03-21 devnull Readdir*
339 2277c5d7 2004-03-21 devnull opendirfile(File *dir)
340 2277c5d7 2004-03-21 devnull {
341 2277c5d7 2004-03-21 devnull Readdir *r;
342 2277c5d7 2004-03-21 devnull
343 2277c5d7 2004-03-21 devnull rlock(&dir->rwlock);
344 2277c5d7 2004-03-21 devnull if((dir->dir.mode & DMDIR)==0){
345 2277c5d7 2004-03-21 devnull runlock(&dir->rwlock);
346 2277c5d7 2004-03-21 devnull return nil;
347 2277c5d7 2004-03-21 devnull }
348 2277c5d7 2004-03-21 devnull r = emalloc9p(sizeof(*r));
349 2277c5d7 2004-03-21 devnull
350 2277c5d7 2004-03-21 devnull /*
351 2277c5d7 2004-03-21 devnull * This reference won't go away while we're using it
352 2277c5d7 2004-03-21 devnull * since we are dir->rdir.
353 2277c5d7 2004-03-21 devnull */
354 2277c5d7 2004-03-21 devnull r->fl = dir->filelist;
355 2277c5d7 2004-03-21 devnull runlock(&dir->rwlock);
356 2277c5d7 2004-03-21 devnull return r;
357 2277c5d7 2004-03-21 devnull }
358 2277c5d7 2004-03-21 devnull
359 2277c5d7 2004-03-21 devnull long
360 2277c5d7 2004-03-21 devnull readdirfile(Readdir *r, uchar *buf, long n)
361 2277c5d7 2004-03-21 devnull {
362 2277c5d7 2004-03-21 devnull long x, m;
363 2277c5d7 2004-03-21 devnull Filelist *fl;
364 2277c5d7 2004-03-21 devnull
365 2277c5d7 2004-03-21 devnull for(fl=r->fl, m=0; fl && m+2<=n; fl=fl->link, m+=x){
366 2277c5d7 2004-03-21 devnull if(fl->f == nil)
367 2277c5d7 2004-03-21 devnull x = 0;
368 2277c5d7 2004-03-21 devnull else if((x=convD2M(&fl->f->dir, buf+m, n-m)) <= BIT16SZ)
369 2277c5d7 2004-03-21 devnull break;
370 2277c5d7 2004-03-21 devnull }
371 2277c5d7 2004-03-21 devnull r->fl = fl;
372 2277c5d7 2004-03-21 devnull return m;
373 2277c5d7 2004-03-21 devnull }
374 2277c5d7 2004-03-21 devnull
375 2277c5d7 2004-03-21 devnull void
376 2277c5d7 2004-03-21 devnull closedirfile(Readdir *r)
377 2277c5d7 2004-03-21 devnull {
378 2277c5d7 2004-03-21 devnull free(r);
379 2277c5d7 2004-03-21 devnull }