dave@onfcanim.UUCP (Dave Martindale) (01/20/88)
Dale Worley's "dugraph" is a useful little program. However, it has one serious glitch: it fails badly on a directory where the space reported by "du" for the directory itself is less than the sum of all of its subdirectories. At least on a recent 4BSD system, du reports disk usage in Kb, regardless of the size of the blocks and fragments in the underlying filesystem. If the filesystem uses 512-byte fragments, the total disk space used by a file or a directory may not be an integral multiple of 1Kb, and is then rounded to the nearest 1K for printing. However, the true size (not the rounded size) propagates up the tree. When dugraph sums the sizes of all subdirectories, the rounding errors accumulate and the total may not match the size reported for the directory itself. The patches below fix this problem. They also make two other changes: 1) A leading slash on a pathname is taken as belonging to the first component, rather than creating an extra null node. Thus a du of /usr will display the top-level directory as "/usr", not as nullstring with a subdirectory of "usr". This also changes the handling of multiple adjacent slashes in a pathname - it's not clear what is "correct" anyway, but this gets rid of the useless null directories. 2) The "last" field in the tree node is useless, since essentially the same information can be found by looking at the right brother pointer. The field, plus the routine for setting it, have been deleted. Dave Martindale watmath!onfcanim!dave ------ feed to "patch" ------------------------------------------------------- *** dugraph.old Tue Jan 19 10:19:52 1988 --- dugraph.c Tue Jan 19 18:55:09 1988 *************** *** 18,24 **** int print_limit; /* location we can't print on or * after */ - int last; /* are we last son of our father? */ char name[1]; /* name */ }; --- 18,23 ---- *************** *** 42,48 **** void sort(); void calc_loc(); void blank(); - void mark_last(); void calc_pc(); void output(); void position(); --- 41,46 ---- *************** *** 69,78 **** /* print out the tree */ for (t = root->lson; t != NULL; t = t->rbrother) { - /* mark the last son of each directory */ /* figure out the print columns */ t->print_col = 0; ! dfs1(calc_pc, mark_last, t); dfs1(output, NULL, t); } /* put blank space at end */ --- 67,75 ---- /* print out the tree */ for (t = root->lson; t != NULL; t = t->rbrother) { /* figure out the print columns */ t->print_col = 0; ! dfs1(calc_pc, NULL, t); dfs1(output, NULL, t); } /* put blank space at end */ *************** *** 111,118 **** * down the tree, constructing nodes as needed */ for (t = root, np = name; np != NULL; np = np1) { /* extract the next directory-part */ ! if ((np1 = strchr(np, '/')) != NULL) { /* we found a slash, replace it with a null, and position * np1 to point to the remainder of the name */ --- 108,118 ---- * down the tree, constructing nodes as needed */ for (t = root, np = name; np != NULL; np = np1) { + /* group any leading slashes with the name itself */ + for (np1 = np; *np1 == '/'; np1++) + ; /* extract the next directory-part */ ! if ((np1 = strchr(np1, '/')) != NULL) { /* we found a slash, replace it with a null, and position * np1 to point to the remainder of the name */ *************** *** 248,254 **** cs += t1->size; } /* cs is the size accounted for by subdirectories */ ! cs = t->size - cs; } /* cs is the size of the files in the directory itself */ /* convert cs to lines */ --- 248,257 ---- cs += t1->size; } /* cs is the size accounted for by subdirectories */ ! if (cs >= t->size) ! cs = 0; ! else ! cs = t->size - cs; } /* cs is the size of the files in the directory itself */ /* convert cs to lines */ *************** *** 298,315 **** } } - /* mark the last son of each directory */ - void mark_last(t) - struct node *t; - { - struct node *t1, *t2; /* scratch pointers */ - t->last = 0; - for (t1 = t->lson, t2 = NULL; t1 != NULL; t2 = t1, t1 = t1->rbrother) - ; - if (t2 != NULL) - t2->last = 1; - } - /* calculate the print columns */ void calc_pc(t) struct node *t; --- 301,306 ---- *************** *** 329,335 **** position(t->loc); printf("--%s%s", t->name, (t->lson != NULL ? "--+" : "")); /* remove the bar for our father if we are the last son */ ! if (t->last) bar_count--; /* add the location of the bar to the bar list if we have a son */ if (t->lson != NULL) --- 320,326 ---- position(t->loc); printf("--%s%s", t->name, (t->lson != NULL ? "--+" : "")); /* remove the bar for our father if we are the last son */ ! if (t->rbrother == NULL && bar_count > 0) bar_count--; /* add the location of the bar to the bar list if we have a son */ if (t->lson != NULL)