mirror of
git://git.9front.org/plan9front/plan9front
synced 2025-01-12 11:10:06 +00:00
walk: fix skipped files, simplify seen()
This commit is contained in:
parent
e59b7e28cd
commit
b8797a1cc6
1 changed files with 40 additions and 84 deletions
|
@ -4,15 +4,21 @@
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
#include <fcall.h>
|
#include <fcall.h>
|
||||||
|
|
||||||
|
typedef struct Seen Seen;
|
||||||
|
struct Seen {
|
||||||
|
Seen *up;
|
||||||
|
Dir *d;
|
||||||
|
};
|
||||||
|
|
||||||
int Cflag = 0;
|
int Cflag = 0;
|
||||||
int uflag = 0;
|
int uflag = 0;
|
||||||
String *stfmt;
|
String *stfmt;
|
||||||
|
|
||||||
/* should turn these flags into a mask */
|
/* should turn these flags into a mask */
|
||||||
int dflag = 1;
|
int printdirs = 1;
|
||||||
int fflag = 1;
|
int printfiles = 1;
|
||||||
int tflag = 0;
|
int temponly = 0;
|
||||||
int xflag = 0;
|
int execonly = 0;
|
||||||
long maxdepth = ~(1<<31);
|
long maxdepth = ~(1<<31);
|
||||||
long mindepth = 0;
|
long mindepth = 0;
|
||||||
|
|
||||||
|
@ -21,9 +27,6 @@ Dir *dotdir = nil;
|
||||||
|
|
||||||
Biobuf *bout;
|
Biobuf *bout;
|
||||||
|
|
||||||
void unsee(Dir*);
|
|
||||||
int seen(Dir*);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
warn(char *fmt, ...)
|
warn(char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
@ -41,6 +44,17 @@ warn(char *fmt, ...)
|
||||||
fprint(2, "%s\n", buf);
|
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
|
void
|
||||||
dofile(char *path, Dir *f, int pathonly)
|
dofile(char *path, Dir *f, int pathonly)
|
||||||
{
|
{
|
||||||
|
@ -48,8 +62,8 @@ dofile(char *path, Dir *f, int pathonly)
|
||||||
|
|
||||||
if(
|
if(
|
||||||
(f == dotdir)
|
(f == dotdir)
|
||||||
|| (tflag && ! (f->qid.type & QTTMP))
|
|| (temponly && ! (f->qid.type & QTTMP))
|
||||||
|| (xflag && ! (f->mode & DMEXEC))
|
|| (execonly && ! (f->mode & DMEXEC))
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -92,19 +106,21 @@ dofile(char *path, Dir *f, int pathonly)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
walk(char *path, Dir *cf, long depth)
|
walk(char *path, Dir *cf, Seen *up, long depth)
|
||||||
{
|
{
|
||||||
String *file;
|
String *file;
|
||||||
Dir *dirs, *f, *fe;
|
Dir *dirs, *f, *fe;
|
||||||
|
Seen s;
|
||||||
|
long n, fseen;
|
||||||
int fd;
|
int fd;
|
||||||
long n;
|
|
||||||
|
|
||||||
if(cf == nil){
|
if(cf == nil){
|
||||||
warn("path: %s: %r", path);
|
warn("path: %s: %r", path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(depth >= maxdepth)
|
fseen = seen(up, cf);
|
||||||
|
if(depth >= maxdepth || fseen)
|
||||||
goto nodescend;
|
goto nodescend;
|
||||||
|
|
||||||
if((fd = open(path, OREAD)) < 0){
|
if((fd = open(path, OREAD)) < 0){
|
||||||
|
@ -112,11 +128,13 @@ walk(char *path, Dir *cf, long depth)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.d = cf;
|
||||||
|
s.up = up;
|
||||||
while((n = dirread(fd, &dirs)) > 0){
|
while((n = dirread(fd, &dirs)) > 0){
|
||||||
fe = dirs+n;
|
fe = dirs+n;
|
||||||
for(f = dirs; f < fe; f++){
|
for(f = dirs; f < fe; f++){
|
||||||
if(!(f->qid.type & QTDIR)){
|
if(!(f->qid.type & QTDIR)){
|
||||||
if(fflag && depth >= mindepth)
|
if(printfiles && depth >= mindepth)
|
||||||
dofile(path, f, 0);
|
dofile(path, f, 0);
|
||||||
}else if(strcmp(f->name, ".") == 0 || strcmp(f->name, "..") == 0){
|
}else if(strcmp(f->name, ".") == 0 || strcmp(f->name, "..") == 0){
|
||||||
warn(". or .. named file: %s/%s", path, f->name);
|
warn(". or .. named file: %s/%s", path, f->name);
|
||||||
|
@ -134,11 +152,7 @@ walk(char *path, Dir *cf, long depth)
|
||||||
s_putc(file, '/');
|
s_putc(file, '/');
|
||||||
}
|
}
|
||||||
s_append(file, f->name);
|
s_append(file, f->name);
|
||||||
if(seen(f))
|
walk(s_to_c(file), f, &s, depth+1);
|
||||||
dofile(s_to_c(file), f, 0);
|
|
||||||
else
|
|
||||||
walk(s_to_c(file), f, depth+1);
|
|
||||||
unsee(f);
|
|
||||||
s_free(file);
|
s_free(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,7 +164,7 @@ walk(char *path, Dir *cf, long depth)
|
||||||
|
|
||||||
nodescend:
|
nodescend:
|
||||||
depth--;
|
depth--;
|
||||||
if(dflag && depth >= mindepth)
|
if(printdirs && (depth >= mindepth || fseen))
|
||||||
dofile(path, cf, 0);
|
dofile(path, cf, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,10 +248,10 @@ main(int argc, char **argv)
|
||||||
case 'C': Cflag++; break; /* undocumented; do not cleanname() the args */
|
case 'C': Cflag++; break; /* undocumented; do not cleanname() the args */
|
||||||
case 'u': uflag++; break; /* unbuffered output */
|
case 'u': uflag++; break; /* unbuffered output */
|
||||||
|
|
||||||
case 'd': dflag++; fflag = 0; break; /* only dirs */
|
case 'd': printfiles = 0; break; /* only dirs */
|
||||||
case 'f': fflag++; dflag = 0; break; /* only non-dirs */
|
case 'f': printdirs = 0; break; /* only non-dirs */
|
||||||
case 't': tflag++; break; /* only tmp files */
|
case 't': temponly = 1; break; /* only tmp files */
|
||||||
case 'x': xflag++; break; /* only executable permission */
|
case 'x': execonly = 1; break; /* only executable permission */
|
||||||
|
|
||||||
case 'n': elimdepth(EARGF(usage())); break;
|
case 'n': elimdepth(EARGF(usage())); break;
|
||||||
case 'e':
|
case 'e':
|
||||||
|
@ -267,7 +281,7 @@ main(int argc, char **argv)
|
||||||
maxdepth++;
|
maxdepth++;
|
||||||
if(argc == 0){
|
if(argc == 0){
|
||||||
dotdir = dirstat(".");
|
dotdir = dirstat(".");
|
||||||
walk(dotpath, dotdir, 1);
|
walk(dotpath, dotdir, nil, 1);
|
||||||
}else for(i=0; i<argc; i++){
|
}else for(i=0; i<argc; i++){
|
||||||
if(strncmp(argv[i], "#/", 2) == 0)
|
if(strncmp(argv[i], "#/", 2) == 0)
|
||||||
slashslash(argv[i]+2);
|
slashslash(argv[i]+2);
|
||||||
|
@ -279,10 +293,9 @@ main(int argc, char **argv)
|
||||||
if((d = dirstat(argv[i])) == nil)
|
if((d = dirstat(argv[i])) == nil)
|
||||||
continue;
|
continue;
|
||||||
if(d->qid.type & QTDIR){
|
if(d->qid.type & QTDIR){
|
||||||
seen(d);
|
walk(argv[i], d, nil, 1);
|
||||||
walk(argv[i], d, 1);
|
|
||||||
}else{
|
}else{
|
||||||
if(!dflag && !seen(d) && mindepth < 1)
|
if(printfiles && mindepth < 1)
|
||||||
dofile(argv[i], d, 1);
|
dofile(argv[i], d, 1);
|
||||||
}
|
}
|
||||||
free(d);
|
free(d);
|
||||||
|
@ -291,60 +304,3 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
exits(nil);
|
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; i<c->n; 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; i<c->n; 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;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue