diff --git a/sys/src/cmd/walk.c b/sys/src/cmd/walk.c index e70709dcc..5296c310d 100644 --- a/sys/src/cmd/walk.c +++ b/sys/src/cmd/walk.c @@ -4,15 +4,21 @@ #include #include +typedef struct Seen Seen; +struct Seen { + Seen *up; + Dir *d; +}; + int Cflag = 0; int uflag = 0; String *stfmt; /* should turn these flags into a mask */ -int dflag = 1; -int fflag = 1; -int tflag = 0; -int xflag = 0; +int printdirs = 1; +int printfiles = 1; +int temponly = 0; +int execonly = 0; long maxdepth = ~(1<<31); long mindepth = 0; @@ -21,9 +27,6 @@ Dir *dotdir = nil; Biobuf *bout; -void unsee(Dir*); -int seen(Dir*); - void warn(char *fmt, ...) { @@ -41,6 +44,17 @@ warn(char *fmt, ...) fprint(2, "%s\n", buf); } +int +seen(Seen *s, Dir *d) +{ + for(; s != nil; s = s->up) + if(d->qid.path == s->d->qid.path + && d->qid.type == s->d->qid.type + && d->dev == s->d->dev) + return 1; + return 0; +} + void dofile(char *path, Dir *f, int pathonly) { @@ -48,8 +62,8 @@ dofile(char *path, Dir *f, int pathonly) if( (f == dotdir) - || (tflag && ! (f->qid.type & QTTMP)) - || (xflag && ! (f->mode & DMEXEC)) + || (temponly && ! (f->qid.type & QTTMP)) + || (execonly && ! (f->mode & DMEXEC)) ) return; @@ -92,19 +106,21 @@ dofile(char *path, Dir *f, int pathonly) } void -walk(char *path, Dir *cf, long depth) +walk(char *path, Dir *cf, Seen *up, long depth) { String *file; Dir *dirs, *f, *fe; + Seen s; + long n, fseen; int fd; - long n; if(cf == nil){ warn("path: %s: %r", path); return; } - if(depth >= maxdepth) + fseen = seen(up, cf); + if(depth >= maxdepth || fseen) goto nodescend; if((fd = open(path, OREAD)) < 0){ @@ -112,11 +128,13 @@ walk(char *path, Dir *cf, long depth) return; } + s.d = cf; + s.up = up; while((n = dirread(fd, &dirs)) > 0){ fe = dirs+n; for(f = dirs; f < fe; f++){ if(!(f->qid.type & QTDIR)){ - if(fflag && depth >= mindepth) + if(printfiles && depth >= mindepth) dofile(path, f, 0); }else if(strcmp(f->name, ".") == 0 || strcmp(f->name, "..") == 0){ warn(". or .. named file: %s/%s", path, f->name); @@ -134,11 +152,7 @@ walk(char *path, Dir *cf, long depth) s_putc(file, '/'); } s_append(file, f->name); - if(seen(f)) - dofile(s_to_c(file), f, 0); - else - walk(s_to_c(file), f, depth+1); - unsee(f); + walk(s_to_c(file), f, &s, depth+1); s_free(file); } } @@ -150,7 +164,7 @@ walk(char *path, Dir *cf, long depth) nodescend: depth--; - if(dflag && depth >= mindepth) + if(printdirs && (depth >= mindepth || fseen)) dofile(path, cf, 0); } @@ -234,10 +248,10 @@ main(int argc, char **argv) case 'C': Cflag++; break; /* undocumented; do not cleanname() the args */ case 'u': uflag++; break; /* unbuffered output */ - case 'd': dflag++; fflag = 0; break; /* only dirs */ - case 'f': fflag++; dflag = 0; break; /* only non-dirs */ - case 't': tflag++; break; /* only tmp files */ - case 'x': xflag++; break; /* only executable permission */ + case 'd': printfiles = 0; break; /* only dirs */ + case 'f': printdirs = 0; break; /* only non-dirs */ + case 't': temponly = 1; break; /* only tmp files */ + case 'x': execonly = 1; break; /* only executable permission */ case 'n': elimdepth(EARGF(usage())); break; case 'e': @@ -267,7 +281,7 @@ main(int argc, char **argv) maxdepth++; if(argc == 0){ dotdir = dirstat("."); - walk(dotpath, dotdir, 1); + walk(dotpath, dotdir, nil, 1); }else for(i=0; iqid.type & QTDIR){ - seen(d); - walk(argv[i], d, 1); + walk(argv[i], d, nil, 1); }else{ - if(!dflag && !seen(d) && mindepth < 1) + if(printfiles && mindepth < 1) dofile(argv[i], d, 1); } free(d); @@ -291,60 +304,3 @@ main(int argc, char **argv) exits(nil); } - -/* below pilfered from /sys/src/cmd/du.c - * NOTE: I did not check for bugs */ - -#define NCACHE 256 /* must be power of two */ - -typedef struct -{ - Dir* cache; - int n; - int max; -} Cache; -Cache cache[NCACHE]; - -void -unsee(Dir *dir) -{ - Dir *dp; - int i; - Cache *c; - - c = &cache[dir->qid.path&(NCACHE-1)]; - dp = c->cache; - for(i=0; in; i++, dp++){ - if(dir->qid.path == dp->qid.path && - dir->type == dp->type && - dir->dev == dp->dev) - c->cache[i] = c->cache[--c->n]; - } -} - -int -seen(Dir *dir) -{ - Dir *dp; - int i; - Cache *c; - - c = &cache[dir->qid.path&(NCACHE-1)]; - dp = c->cache; - for(i=0; in; i++, dp++) - if(dir->qid.path == dp->qid.path && - dir->type == dp->type && - dir->dev == dp->dev) - return 1; - if(c->n == c->max){ - if (c->max == 0) - c->max = 8; - else - c->max += c->max/2; - c->cache = realloc(c->cache, c->max*sizeof(Dir)); - if(c->cache == nil) - sysfatal("realloc: %r"); - } - c->cache[c->n++] = *dir; - return 0; -}