static Walkqid* devlogfswalk(Chan *c, Chan *nc, char **name, int nname) { int instance, qid, qt, clone; Walkqid *wq; #ifdef CALLTRACE print("devlogfswalk(c = 0x%.8lux, nc = 0x%.8lux, name = 0x%.8lux, nname = %d) - start\n", (ulong)c, (ulong)nc, (ulong)name, nname); #endif clone = 0; if(nc == nil){ nc = devclone(c); nc->type = 0; SPLITPATH(c->qid.path, c->qid.type, instance, qid, qt); if(DATAQID(qid, qt)) nc->aux = devlogfsget(instance); clone = 1; } wq = devwalk(c, nc, name, nname, 0, 0, devlogfsgen); if (wq == nil || wq->nqid < nname) { if(clone) cclose(nc); } else if (clone) { wq->clone = nc; nc->type = c->type; } #ifdef CALLTRACE print("devlogfswalk(c = 0x%.8lux, nc = 0x%.8lux, name = 0x%.8lux, nname = %d) - return\n", (ulong)c, (ulong)nc, (ulong)name, nname); #endif return wq; }
static Chan * powerclone(Chan *c, Chan *nc) { Puser *p; nc = devclone(c, nc); if((p = nc->aux) != nil) incref(p); return nc; }
static Walkqid* fswalk(Chan *c, Chan *nc, char **name, int nname) { int i; Path *path; Walkqid *wq; UnixFd *ufd; if(nc != nil) panic("fswalk: nc != nil"); wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid)); nc = devclone(c); fsclone(c, nc); ufd = c->aux; path = ufd->path; incref(&path->ref); wq->clone = nc; for(i=0; i<nname; i++){ ufd = nc->aux; replacepath(nc, path); if(fswalk1(nc, name[i]) < 0){ if(i == 0){ pathclose(path); cclose(nc); free(wq); error(Enonexist); } break; } path = addelem(path, name[i], nil); wq->qid[i] = nc->qid; } replacepath(nc, path); pathclose(path); if(i != nname){ cclose(nc); wq->clone = nil; } wq->nqid = i; return wq; }
static Walkqid* fswalk(Chan *c, Chan *nc, char **name, int nname) { int i; Walkqid *wq; if(nc != nil) panic("fswalk: nc != nil"); wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid)); nc = devclone(c); fsclone(c, nc); wq->clone = nc; for(i=0; i<nname; i++){ if(fswalk1(nc, name[i]) == 0) break; wq->qid[i] = nc->qid; } if(i != nname){ cclose(nc); wq->clone = nil; } wq->nqid = i; return wq; }
Walkqid* devwalk(Chan *c, Chan *nc, char **name, int nname, Dirtab *tab, int ntab, Devgen *gen) { int i, j, alloc; Walkqid *wq; char *n; Dir dir; if(nname > 0) isdir(c); alloc = 0; wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid)); if(waserror()){ if(alloc && wq->clone!=nil) cclose(wq->clone); free(wq); return nil; } if(nc == nil){ nc = devclone(c); nc->type = 0; /* device doesn't know about this channel yet */ alloc = 1; } wq->clone = nc; for(j=0; j<nname; j++){ if(!(nc->qid.type&QTDIR)){ if(j==0) error(Enotdir); goto Done; } n = name[j]; if(strcmp(n, ".") == 0){ Accept: wq->qid[wq->nqid++] = nc->qid; continue; } if(strcmp(n, "..") == 0){ if((*gen)(nc, nil, tab, ntab, DEVDOTDOT, &dir) != 1){ print("devgen walk .. in dev%s %llux broken\n", devtab[nc->type]->name, nc->qid.path); error("broken devgen"); } nc->qid = dir.qid; goto Accept; } /* * Ugly problem: If we're using devgen, make sure we're * walking the directory itself, represented by the first * entry in the table, and not trying to step into a sub- * directory of the table, e.g. /net/net. Devgen itself * should take care of the problem, but it doesn't have * the necessary information (that we're doing a walk). */ if(gen==devgen && nc->qid.path!=tab[0].qid.path) goto Notfound; for(i=0;; i++) { switch((*gen)(nc, n, tab, ntab, i, &dir)){ case -1: Notfound: if(j == 0) error(Enonexist); kstrcpy(up->errstr, Enonexist, ERRMAX); goto Done; case 0: continue; case 1: if(strcmp(n, dir.name) == 0){ nc->qid = dir.qid; goto Accept; } continue; } } } /* * We processed at least one name, so will return some data. * If we didn't process all nname entries succesfully, we drop * the cloned channel and return just the Qids of the walks. */ Done: poperror(); if(wq->nqid < nname){ if(alloc) cclose(wq->clone); wq->clone = nil; }else if(wq->clone){ /* attach cloned channel to same device */ wq->clone->type = c->type; } return wq; }
struct walkqid *devwalk(struct chan *c, struct chan *nc, char **name, int nname, struct dirtab *tab, int ntab, Devgen * gen) { ERRSTACK(1); int i, j; volatile int alloc; /* to keep waserror from optimizing this out */ struct walkqid *wq; char *n; struct dir dir; if (nname > 0) isdir(c); alloc = 0; wq = kzmalloc(sizeof(struct walkqid) + nname * sizeof(struct qid), KMALLOC_WAIT); if (waserror()) { if (alloc && wq->clone != NULL) cclose(wq->clone); kfree(wq); poperror(); return NULL; } if (nc == NULL) { nc = devclone(c); /* inferno was setting this to 0, assuming it was devroot. lining up * with chanrelease and newchan */ nc->type = -1; /* device doesn't know about this channel yet */ alloc = 1; } wq->clone = nc; dir.qid.path = 0; for (j = 0; j < nname; j++) { if (!(nc->qid.type & QTDIR)) { if (j == 0) error(Enotdir); goto Done; } n = name[j]; if (strcmp(n, ".") == 0) { Accept: wq->qid[wq->nqid++] = nc->qid; continue; } if (strcmp(n, "..") == 0) { (*gen) (nc, NULL, tab, ntab, DEVDOTDOT, &dir); nc->qid = dir.qid; goto Accept; } /* * Ugly problem: If we're using devgen, make sure we're * walking the directory itself, represented by the first * entry in the table, and not trying to step into a sub- * directory of the table, e.g. /net/net. Devgen itself * should take care of the problem, but it doesn't have * the necessary information (that we're doing a walk). */ if (gen == devgen && nc->qid.path != tab[0].qid.path) goto Notfound; dir.qid.path = 0; for (i = 0;; i++) { switch ((*gen) (nc, n, tab, ntab, i, &dir)) { case -1: printd("DEVWALK -1, i was %d, want path %p\n", i, c->qid.path); Notfound: set_errno(ENOENT); if (j == 0) error(Enonexist); set_errstr(Enonexist); goto Done; case 0: printd("DEVWALK continue, i was %d\n", i); continue; case 1: printd ("DEVWALK gen returns path %p name %s, want path %p\n", dir.qid.path, dir.name, c->qid.path); if (strcmp(n, dir.name) == 0) { nc->qid = dir.qid; goto Accept; } continue; } } } /* * We processed at least one name, so will return some data. * If we didn't process all nname entries succesfully, we drop * the cloned channel and return just the Qids of the walks. */ Done: poperror(); if (wq->nqid < nname) { if (alloc) cclose(wq->clone); wq->clone = NULL; } else if (wq->clone) { /* attach cloned channel to same device */ wq->clone->type = c->type; } return wq; }
Walkqid* devwalk(Chan *c, Chan *nc, char **name, int nname, Dirtab *tab, int ntab, Devgen *gen) { Proc *up = externup(); if (0) print_func_entry(); int i, j, alloc; Walkqid *wq; char *n; Dir dir; if(nname > 0) isdir(c); if (0) { int i; iprint("%d names:", nname); for(i = 0; i < nname; i++) iprint("%s ", name[i]); iprint("\n");} alloc = 0; wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid)); if(waserror()){ if(alloc && wq->clone!=nil) cclose(wq->clone); free(wq); if (0) print_func_exit(); return nil; } if(nc == nil){ nc = devclone(c); /* * nc->dev remains nil for now. //XDYNX */ alloc = 1; } wq->clone = nc; for(j=0; j<nname; j++){ if(!(nc->qid.type & QTDIR)){ if(j==0) error(Enotdir); goto Done; } n = name[j]; if(strcmp(n, ".") == 0){ Accept: wq->qid[wq->nqid++] = nc->qid; continue; } if(strcmp(n, "..") == 0){ /* * Use c->dev->name in the error because * nc->dev should be nil here. */ if((*gen)(nc, nil, tab, ntab, DEVDOTDOT, &dir) != 1){ print("devgen walk .. in dev%s %#llx broken\n", c->dev->name, nc->qid.path); error("broken devgen"); } nc->qid = dir.qid; goto Accept; } /* * Ugly problem: If we're using devgen, make sure we're * walking the directory itself, represented by the first * entry in the table, and not trying to step into a sub- * directory of the table, e.g. /net/net. Devgen itself * should take care of the problem, but it doesn't have * the necessary information (that we're doing a walk). */ if(gen==devgen && nc->qid.path!=tab[0].qid.path) goto Notfound; for(i=0;; i++) { switch((*gen)(nc, n, tab, ntab, i, &dir)){ case -1: Notfound: if(j == 0) error(Enonexist); kstrcpy(up->errstr, Enonexist, ERRMAX); goto Done; case 0: continue; case 1: if(strcmp(n, dir.name) == 0){ nc->qid = dir.qid; goto Accept; } continue; } } } /* * We processed at least one name, so will return some data. * If we didn't process all nname entries succesfully, we drop * the cloned channel and return just the Qids of the walks. */ Done: poperror(); if(wq->nqid < nname){ if(alloc) cclose(wq->clone); wq->clone = nil; }else if(wq->clone){ /* attach cloned channel to same device */ //what goes here: //XDYNX // ->dev must be nil because can't walk an open chan, right? // what about ref count on dev? wq->clone->dev = c->dev; //if(wq->clone->dev) //XDYNX // devtabincr(wq->clone->dev); } if (0) print_func_exit(); return wq; }
Walkqid* fswalk(Chan *c, Chan *nc, char **name, int nname) { int j, alloc; Walkqid *wq; Dir *dir; char *n; Cname *current, *next; Qid rootqid; if(nname > 0) isdir(c); /* do we need this? */ alloc = 0; current = nil; wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid)); if(waserror()){ if(alloc && wq->clone!=nil) cclose(wq->clone); cnameclose(current); free(wq); return nil; } if(nc == nil){ nc = devclone(c); nc->type = 0; alloc = 1; } wq->clone = nc; rootqid = FS(c)->rootqid; current = FS(c)->name; if(current != nil) incref(¤t->r); for(j=0; j<nname; j++){ if(!(nc->qid.type&QTDIR)){ if(j==0) error(Enotdir); break; } n = name[j]; if(strcmp(n, ".") != 0 && !(isdotdot(n) && nc->qid.path == rootqid.path)){ /* TO DO: underlying qids aliased */ //print("** ufs walk '%s' -> %s\n", current->s, n); next = current; incref(&next->r); next = addelem(current, n); dir = dirstat(next->s); if(dir == nil){ cnameclose(next); if(j == 0) error(Enonexist); strcpy(up->env->errstr, Enonexist); break; } nc->qid = dir->qid; free(dir); cnameclose(current); current = next; } wq->qid[wq->nqid++] = nc->qid; } // print("** ufs walk '%s'\n", current->s); poperror(); if(wq->nqid < nname){ cnameclose(current); if(alloc) cclose(wq->clone); wq->clone = nil; }else if(wq->clone){ /* now attach to our device */ nc->aux = smalloc(sizeof(Fsinfo)); nc->type = c->type; FS(nc)->rootqid = FS(c)->rootqid; FS(nc)->name = current; FS(nc)->fd = -1; FS(nc)->root = FS(c)->root; }else panic("fswalk: can't happen"); return wq; }