<div dir="ltr">Hi Rob,<div><br></div><div>My patch was</div><div><br></div><div><div> </div><div>+// is recursive tree</div><div>+static int is_recursive_loop(struct dirtree *node)</div><div>+{</div><div>+ struct dirtree *tmp = node;</div><div>+</div><div>+ while ((tmp = tmp->parent)) {</div><div>+ if ((tmp->st.st_ino == node->st.st_ino) &&</div><div>+ (tmp->st.st_dev == node->st.st_dev))</div><div>+ return 1;</div><div>+ }</div><div>+ return 0;</div><div>+}</div><div>+</div><div> // dirtree callback, comput/display size of node</div><div> static int do_du(struct dirtree *node)</div><div> {</div><div>@@ -114,6 +127,8 @@</div><div> if (!(toys.optflags & FLAG_l) && !node->again)</div><div> if (seen_inode(&TT.inodes, &node->st)) return 0;</div><div> </div><div>+ if (is_recursive_loop(node)) goto ADD;</div><div>+</div><div> // Collect child info before printing directory size</div><div> if (S_ISDIR(node->st.st_mode)) {</div><div> if (!node->again) {</div><div>@@ -121,7 +136,7 @@</div><div> return DIRTREE_COMEAGAIN | (DIRTREE_SYMFOLLOW*!!(toys.optflags & FLAG_L));</div><div> } else TT.depth--;</div><div> }</div><div>-</div><div>+ADD:</div><div> node->extra += node->st.st_blocks;</div><div> if (node->parent) node->parent->extra += node->extra;</div></div><div><br></div><div>and not the one you mentioned.</div><div><br></div><div>This patch is handling the case, of self point symlinks.</div><div><br></div><div>$ mkdir sub</div><div>$ cd sub</div><div>$ ln -s ../sub lnk</div><div>$ cd ../</div><div>$ du -L sub</div><div><br></div><div>without my patch it will keep looping. This patch stops from this looping.</div><div><br></div><div>Thanks,</div><div>Ashwini</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Nov 30, 2014 at 6:03 AM, Rob Landley <span dir="ltr"><<a href="mailto:rob@landley.net" target="_blank">rob@landley.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Going through Ashwini's patch stack from last month. (Sorry for the delay,<br>
but I think I applied all the trivial ones in earlier passes.)<br>
<br>
What does the du.c patch do?<br>
<br>
$ mkdir sub<br>
$ ln -s . sub/here<br>
$ ln -s loop sub/loop<br>
$ ./toybox du sub<br>
4 sub<br>
<br>
There's also a hardlink filter (disabled via -l)...<br>
<br>
I'm tempted to add the following to lib/dirtree.c<br>
<br>
+// Have we already seen this node?<br>
+int dirtree_seen(struct dirtree *try, struct stat *st)<br>
+{<br>
+ while (try) {<br>
+ if (try->st.st_ino==st->st_ino && try->st.st_dev==st->st_dev) return 1;<br>
+ try = try->parent;<br>
+ }<br>
+<br>
+ return 0;<br>
+}<br>
+<br>
<br>
But the existing user I can think of that's already doing this is in cp.c:<br>
<br>
// Detect recursive copies via repeated top node (cp -R .. .) or<br>
// identical source/target (fun with hardlinks).<br>
if ((TT.top.st_dev == try->st.st_dev && TT.top.st_ino == try->st.st_ino<br>
&& (catch = TT.destname))<br>
|| (!fstatat(cfd, catch, &cst, 0) && cst.st_dev == try->st.st_dev<br>
&& cst.st_ino == try->st.st_ino))<br>
{<br>
error_msg("'%s' is '%s'", catch, err = dirtree_path(try, 0));<br>
free(err);<br>
<br>
return 0;<br>
}<br>
<br>
Which seems to work?<br>
<br>
Anyway, could you give me a testcase where the du.c patch you submitted makes a<br>
difference?<br>
<span class="HOEnZb"><font color="#888888"><br>
Rob<br>
</font></span></blockquote></div><br></div>