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)
--
⑨