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");
195 * We might encounter blank spots along the
196 * way due to deleted files that have not yet
197 * been flushed from the file list. Don't reuse
198 * those - some apps (e.g., omero) depend on
199 * the file order reflecting creation order.
200 * Always create at the end of the list.
202 for(l=&fp->filelist; fl=*l; l=&fl->link){
203 if(fl->f && strcmp(fl->f->name, name) == 0){
205 werrstr("file already exists");
210 fl = emalloc9p(sizeof *fl);
214 f->name = estrdup9p(name);
215 f->uid = estrdup9p(uid ? uid : fp->uid);
216 f->gid = estrdup9p(fp->gid);
217 f->muid = estrdup9p(uid ? uid : "unknown");
223 f->qid.path = t->qidgen++;
226 f->qid.type |= QTDIR;
228 f->qid.type |= QTAPPEND;
230 f->qid.type |= QTEXCL;
233 f->atime = f->mtime = time(0);
239 incref(f); /* being returned */
240 incref(f); /* for the tree */
249 walkfile1(File *dir, char *elem)
255 if(strcmp(elem, "..") == 0){
265 for(fl=dir->filelist; fl; fl=fl->link)
266 if(fl->f && strcmp(fl->f->name, elem)==0){
278 walkfile(File *f, char *path)
280 char *os, *s, *nexts;
282 if(strchr(path, '/') == nil)
283 return walkfile1(f, path); /* avoid malloc */
285 os = s = estrdup9p(path);
287 if(nexts = strchr(s, '/'))
300 alloctree(char *uid, char *gid, ulong mode, void (*destroy)(File*))
306 t = emalloc9p(sizeof *t);
308 f->name = estrdup9p("/");
314 uid = estrdup9p(uid);
317 gid = estrdup9p(uid);
319 gid = estrdup9p(gid);
321 muid = estrdup9p(uid);
323 f->qid = (Qid){0, 0, QTDIR};
325 f->atime = f->mtime = time(0);
326 f->mode = DMDIR | mode;
339 t->destroy = destroy;
347 Filelist *fl, *flnext;
349 for(fl=f->filelist; fl; fl=flnext){
367 opendirfile(File *dir)
372 if((dir->mode & DMDIR)==0){
376 r = emalloc9p(sizeof(*r));
379 * This reference won't go away while we're
380 * using it because file list entries are not freed
381 * until the directory is removed and all refs to
382 * it (our fid is one!) have gone away.
384 r->fl = dir->filelist;
386 incref(&dir->readers);
392 readdirfile(Readdir *r, uchar *buf, long n)
397 for(fl=r->fl, m=0; fl && m+2<=n; fl=fl->link, m+=x){
400 else if((x=convD2M(fl->f, buf+m, n-m)) <= BIT16SZ)
408 closedirfile(Readdir *r)
410 if(decref(&r->dir->readers) == 0){
412 cleanfilelist(r->dir);