9 * To avoid deadlock, the following rules must be followed.
10 * Always lock child then parent, never parent then child.
11 * If holding the free file lock, do not lock any Files.
26 static File *freefilelist;
36 if(freefilelist == nil){
37 f = emalloc9p(N*sizeof(*f));
46 freefilelist = f->aux;
50 memset(f, 0, sizeof *f);
58 Filelist *fl, *flnext;
60 for(fl=f->filelist; fl; fl=flnext){
72 f->aux = freefilelist;
78 cleanfilelist(File *f)
84 * can't delete filelist structures while there
85 * are open readers of this directory, because
86 * they might have references to the structures.
87 * instead, just leave the empty refs in the list
88 * until there is no activity and then clean up.
90 if(f->readers.ref != 0)
96 * no dir readers, file is locked, and
97 * there are empty entries in the file list.
100 for(l=&f->filelist; fl=*l; ){
132 werrstr("no parent");
138 werrstr("cannot remove root");
146 werrstr("has children");
154 werrstr("parent changed underfoot");
161 for(fl=fp->filelist; fl; fl=fl->link)
164 assert(fl != nil && fl->f == f);
175 closefile(fp); /* reference from child */
176 closefile(f); /* reference from tree */
182 createfile(File *fp, char *name, char *uid, ulong perm, void *aux)
188 if((fp->qid.type&QTDIR) == 0){
189 werrstr("create in non-directory");
194 if(fp->parent == nil){
196 werrstr("create in deleted directory");
201 * We might encounter blank spots along the
202 * way due to deleted files that have not yet
203 * been flushed from the file list. Don't reuse
204 * those - some apps (e.g., omero) depend on
205 * the file order reflecting creation order.
206 * Always create at the end of the list.
208 for(l=&fp->filelist; fl=*l; l=&fl->link){
209 if(fl->f && strcmp(fl->f->name, name) == 0){
211 werrstr("file already exists");
216 fl = emalloc9p(sizeof *fl);
220 f->name = estrdup9p(name);
221 f->uid = estrdup9p(uid ? uid : fp->uid);
222 f->gid = estrdup9p(fp->gid);
223 f->muid = estrdup9p(uid ? uid : "unknown");
229 f->qid.path = t->qidgen++;
232 f->qid.type |= QTDIR;
234 f->qid.type |= QTAPPEND;
236 f->qid.type |= QTEXCL;
239 f->atime = f->mtime = time(0);
245 incref(f); /* being returned */
246 incref(f); /* for the tree */
255 walkfile1(File *dir, char *elem)
261 if(strcmp(elem, "..") == 0){
271 for(fl=dir->filelist; fl; fl=fl->link)
272 if(fl->f && strcmp(fl->f->name, elem)==0){
284 walkfile(File *f, char *path)
286 char *os, *s, *nexts;
288 if(strchr(path, '/') == nil)
289 return walkfile1(f, path); /* avoid malloc */
291 os = s = estrdup9p(path);
293 if(nexts = strchr(s, '/'))
306 alloctree(char *uid, char *gid, ulong mode, void (*destroy)(File*))
312 t = emalloc9p(sizeof *t);
314 f->name = estrdup9p("/");
320 uid = estrdup9p(uid);
323 gid = estrdup9p(uid);
325 gid = estrdup9p(gid);
327 muid = estrdup9p(uid);
329 f->qid = (Qid){0, 0, QTDIR};
331 f->atime = f->mtime = time(0);
332 f->mode = DMDIR | mode;
345 t->destroy = destroy;
353 Filelist *fl, *flnext;
355 for(fl=f->filelist; fl; fl=flnext){
373 opendirfile(File *dir)
378 if((dir->mode & DMDIR)==0){
382 r = emalloc9p(sizeof(*r));
385 * This reference won't go away while we're
386 * using it because file list entries are not freed
387 * until the directory is removed and all refs to
388 * it (our fid is one!) have gone away.
390 r->fl = dir->filelist;
392 incref(&dir->readers);
398 readdirfile(Readdir *r, uchar *buf, long n)
403 for(fl=r->fl, m=0; fl && m+2<=n; fl=fl->link, m+=x){
406 else if((x=convD2M(fl->f, buf+m, n-m)) <= BIT16SZ)
414 closedirfile(Readdir *r)
416 if(decref(&r->dir->readers) == 0){
418 cleanfilelist(r->dir);