shithub: riscv

Download patch

ref: e58df8173f2c3188de76a22eae8262f8d3c58190
parent: ace81cb1aee0f0827d698768607421f16a9c657e
author: Ori Bernstein <ori@eigenstate.org>
date: Tue Dec 10 18:14:33 EST 2024

walk: show siblings with the same qid

the code for skipping directory loops in
walk was taken from du, but the desired
behavior for the two programs is differnt;

while du wants to count the total size used,
and double-counting directories would be a
mistake, walk wants to enumerate all finite
paths in a namespace.

--- a/sys/src/cmd/walk.c
+++ b/sys/src/cmd/walk.c
@@ -21,6 +21,7 @@
 
 Biobuf *bout;
 
+void unsee(Dir*);
 int seen(Dir*);
 
 void
@@ -114,21 +115,19 @@
 	while((n = dirread(fd, &dirs)) > 0){
 		fe = dirs+n;
 		for(f = dirs; f < fe; f++){
-			if(seen(f))
-				continue;
-			if(! (f->qid.type & QTDIR)){
+			if(!(f->qid.type & QTDIR)){
 				if(fflag && depth >= mindepth)
 					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);
-			} else{
+			}else{
 				if(depth+1 > maxdepth){
 					dofile(path, f, 0);
 					continue;
-				} else if(path == dotpath){
+				}else if(path == dotpath){
 					if((file = s_new()) == nil)
 						sysfatal("s_new: %r");
-				} else{
+				}else{
 					if((file = s_copy(path)) == nil)
 						sysfatal("s_copy: %r");
 					if(s_len(file) != 1 || *s_to_c(file) != '/')
@@ -135,8 +134,11 @@
 						s_putc(file, '/');
 				}
 				s_append(file, f->name);
-
-				walk(s_to_c(file), f, depth+1);	
+				if(seen(f))
+					dofile(s_to_c(file), f, 0);
+				else
+					walk(s_to_c(file), f, depth+1);
+				unsee(f);
 				s_free(file);
 			}
 		}
@@ -221,7 +223,6 @@
 	functions, but since they are a no-op and libString needs
 	a rework, I left them in - BurnZeZ
 */
-
 void
 main(int argc, char **argv)
 {
@@ -267,7 +268,7 @@
 	if(argc == 0){
 		dotdir = dirstat(".");
 		walk(dotpath, dotdir, 1);
-	} else for(i=0; i<argc; i++){
+	}else for(i=0; i<argc; i++){
 		if(strncmp(argv[i], "#/", 2) == 0)
 			slashslash(argv[i]+2);
 		else{
@@ -275,11 +276,15 @@
 				cleanname(argv[i]);
 			slashslash(argv[i]);
 		}
-		if((d = dirstat(argv[i])) != nil && ! (d->qid.type & QTDIR)){
-			if(fflag && !seen(d) && mindepth < 1)
-				dofile(argv[i], d, 1);
-		} else
+		if((d = dirstat(argv[i])) == nil)
+			continue;
+		if(d->qid.type & QTDIR){
+			seen(d);
 			walk(argv[i], d, 1);
+		}else{
+			if(!dflag && !seen(d) && mindepth < 1)
+				dofile(argv[i], d, 1);
+		}
 		free(d);
 	}
 	Bterm(bout);
@@ -299,6 +304,23 @@
 	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)
--