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