shithub: riscv

Download patch

ref: b8797a1cc66808d8147a846d20e569baf8279993
parent: e59b7e28cdc546f6a4e00ca03bf88514136e15d4
author: Ori Bernstein <ori@eigenstate.org>
date: Thu Dec 12 15:17:51 EST 2024

walk: fix skipped files, simplify seen()

--- a/sys/src/cmd/walk.c
+++ b/sys/src/cmd/walk.c
@@ -4,15 +4,21 @@
 #include <String.h>
 #include <fcall.h>
 
+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 @@
 
 Biobuf *bout;
 
-void unsee(Dir*);
-int seen(Dir*);
-
 void
 warn(char *fmt, ...)
 {
@@ -41,6 +44,17 @@
 	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 @@
 
 	if(
 		(f == dotdir)
-		|| (tflag && ! (f->qid.type & QTTMP))
-		|| (xflag && ! (f->mode & DMEXEC))
+		|| (temponly && ! (f->qid.type & QTTMP))
+		|| (execonly && ! (f->mode & DMEXEC))
 	)
 		return;
 
@@ -92,12 +106,13 @@
 }
 
 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);
@@ -104,7 +119,8 @@
 		return;
 	}
 
-	if(depth >= maxdepth)
+	fseen = seen(up, cf);
+	if(depth >= maxdepth || fseen)
 		goto nodescend;
 
 	if((fd = open(path, OREAD)) < 0){
@@ -112,11 +128,13 @@
 		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 @@
 						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 @@
 
 nodescend:
 	depth--;
-	if(dflag && depth >= mindepth)
+	if(printdirs && (depth >= mindepth || fseen))
 		dofile(path, cf, 0);
 }
 
@@ -234,10 +248,10 @@
 	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 @@
 		maxdepth++;
 	if(argc == 0){
 		dotdir = dirstat(".");
-		walk(dotpath, dotdir, 1);
+		walk(dotpath, dotdir, nil, 1);
 	}else for(i=0; i<argc; i++){
 		if(strncmp(argv[i], "#/", 2) == 0)
 			slashslash(argv[i]+2);
@@ -279,10 +293,9 @@
 		if((d = dirstat(argv[i])) == nil)
 			continue;
 		if(d->qid.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);
@@ -290,61 +303,4 @@
 	Bterm(bout);
 
 	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;
 }
--