17aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley/* du.c - disk usage program. 21a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar * 31a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar * Copyright 2012 Ashwini Kumar <ak.ashwini@gmail.com> 41a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar * 51a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar * See http://opengroup.org/onlinepubs/9699919799/utilities/du.html 6f033f8607f156464747abe57487c1f6226f94001Rob Landley * 7f033f8607f156464747abe57487c1f6226f94001Rob Landley * TODO: cleanup 81a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 9880d4a96523c94d84bee1f066de5cf03756877a3Rob LandleyUSE_DU(NEWTOY(du, "d#<0hmlcaHkKLsx[-HL][-kKmh]", TOYFLAG_USR|TOYFLAG_BIN)) 101a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 111a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumarconfig DU 127aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley bool "du" 137aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley default y 147aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley help 157aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley usage: du [-d N] [-askxHLlmc] [file...] 167aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 17880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley Show disk usage, space consumed by files and directories. 18880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 19880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley Size in: 20880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -k 1024 byte blocks (default) 21880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -K 512 byte blocks (posix) 22880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -m megabytes 23880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -h human readable format (e.g., 1K 243M 2G ) 24880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 25880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley What to show: 26880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -a all files, not just directories 27880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -H follow symlinks on cmdline 28880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -L follow all symlinks 29880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -s only total size of each argument 30880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -x don't leave this filesystem 31880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -c cumulative total 32880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -d N only depth < N 33880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -l disable hardlink filter 341a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar*/ 351a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 36c0e56edaf256adb6c60c5a052525a1ffbb927901Rob Landley#define FOR_du 371a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar#include "toys.h" 381a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 39c0e56edaf256adb6c60c5a052525a1ffbb927901Rob LandleyGLOBALS( 407aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley long maxdepth; 41880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 42880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley long depth, total; 437aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley dev_t st_dev; 44880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley void *inodes; 451a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar) 461a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 471a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumartypedef struct node_size { 487aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley struct dirtree *node; 497aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley long size; 50880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley} node_size; 511a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 52880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley// Print the size and name, given size in bytes 53880d4a96523c94d84bee1f066de5cf03756877a3Rob Landleystatic void print(long long size, struct dirtree *node) 541a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar{ 55880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley char *name = "total"; 561a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 57880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (TT.maxdepth && TT.depth > TT.maxdepth) return; 581a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 596c64f5f186d26d4c95d408979d33831935e026f1Rob Landley if (toys.optflags & FLAG_h) { 600fb465194789965b6fb2efd31995a2441144d650Elliott Hughes human_readable(toybuf, size, 0); 6148c172ba589cfd848624b51f6f748b56bc217775Rob Landley printf("%s", toybuf); 626c64f5f186d26d4c95d408979d33831935e026f1Rob Landley } else { 63880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley int bits = 10; 64880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 65880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (toys.optflags & FLAG_K) bits = 9; 66880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley else if (toys.optflags & FLAG_m) bits = 20; 671a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 68880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley printf("%llu", (size>>bits)+!!(size&((1<<bits)-1))); 69880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley } 70880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (node) name = dirtree_path(node, NULL); 71880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley xprintf("\t%s\n", name); 72880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (node) free(name); 731a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar} 741a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 75880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley// Return whether or not we've seen this inode+dev, adding it to the list if 76880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley// we haven't. 77880d4a96523c94d84bee1f066de5cf03756877a3Rob Landleystatic int seen_inode(void **list, struct stat *st) 781a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar{ 79880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (!st) llist_traverse(st, free); 80880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 81880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley // Skipping dir nodes isn't _quite_ right. They're not hardlinked, but could 82880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley // be bind mounted. Still, it's more efficient and the archivers can't use 83880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley // hardlinked directory info anyway. (Note that we don't catch bind mounted 84880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley // _files_ because it doesn't change st_nlink.) 85880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley else if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) { 86880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley struct inode_list { 87880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley struct inode_list *next; 88880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley ino_t ino; 89880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley dev_t dev; 90880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley } *new; 91880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 92880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley for (new = *list; new; new = new->next) 93880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if(new->ino == st->st_ino && new->dev == st->st_dev) 94880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley return 1; 95880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 96880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley new = xzalloc(sizeof(*new)); 97880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley new->ino = st->st_ino; 98880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley new->dev = st->st_dev; 99880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley new->next = *list; 100880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley *list = new; 1017aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 102880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 1037aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley return 0; 1041a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar} 1051a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 106880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley// dirtree callback, comput/display size of node 107880d4a96523c94d84bee1f066de5cf03756877a3Rob Landleystatic int do_du(struct dirtree *node) 1081a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar{ 109aab9164df395a4b0878b0ad930a5ec8a806a58e9Rob Landley if (!node->parent) TT.st_dev = node->st.st_dev; 110aab9164df395a4b0878b0ad930a5ec8a806a58e9Rob Landley else if (!dirtree_notdotdot(node)) return 0; 1117aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 112880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley // detect swiching filesystems 113880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if ((toys.optflags & FLAG_x) && (TT.st_dev != node->st.st_dev)) 114880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley return 0; 115880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 11610e0d86c088a3eccc27095b51d753e05f3f3cbc8Rob Landley // Don't loop endlessly on recursive directory symlink 11710e0d86c088a3eccc27095b51d753e05f3f3cbc8Rob Landley if (toys.optflags & FLAG_L) { 11810e0d86c088a3eccc27095b51d753e05f3f3cbc8Rob Landley struct dirtree *try = node; 11910e0d86c088a3eccc27095b51d753e05f3f3cbc8Rob Landley 12010e0d86c088a3eccc27095b51d753e05f3f3cbc8Rob Landley while ((try = try->parent)) 12110e0d86c088a3eccc27095b51d753e05f3f3cbc8Rob Landley if (node->st.st_dev==try->st.st_dev && node->st.st_ino==try->st.st_ino) 12210e0d86c088a3eccc27095b51d753e05f3f3cbc8Rob Landley return 0; 12310e0d86c088a3eccc27095b51d753e05f3f3cbc8Rob Landley } 12410e0d86c088a3eccc27095b51d753e05f3f3cbc8Rob Landley 125880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley // Don't count hard links twice 126fec3fd1f8ac1db9ed87b79bd3eb5e38aa835e881Rob Landley if (!(toys.optflags & FLAG_l) && !node->again) 127880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (seen_inode(&TT.inodes, &node->st)) return 0; 128880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 129880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley // Collect child info before printing directory size 130880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (S_ISDIR(node->st.st_mode)) { 131fec3fd1f8ac1db9ed87b79bd3eb5e38aa835e881Rob Landley if (!node->again) { 1327aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley TT.depth++; 1331f5f436826505df6dfabe1de9724424fc40fae23Rob Landley return DIRTREE_COMEAGAIN|(DIRTREE_SYMFOLLOW*!!(toys.optflags&FLAG_L)); 134880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley } else TT.depth--; 1357aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 136880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 137880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley node->extra += node->st.st_blocks; 138880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (node->parent) node->parent->extra += node->extra; 139880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley else TT.total += node->extra; 140880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 141880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if ((toys.optflags & FLAG_a) || !node->parent 142880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley || (S_ISDIR(node->st.st_mode) && !(toys.optflags & FLAG_s))) 143880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley { 144880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley print(node->extra*512, node); 1457aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 146880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 147880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley return 0; 1481a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar} 1491a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 1501a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumarvoid du_main(void) 1511a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar{ 152aab9164df395a4b0878b0ad930a5ec8a806a58e9Rob Landley char *noargs[] = {".", 0}, **args; 153880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 154880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley // Loop over command line arguments, recursing through children 155aab9164df395a4b0878b0ad930a5ec8a806a58e9Rob Landley for (args = toys.optc ? toys.optargs : noargs; *args; args++) 1561f5f436826505df6dfabe1de9724424fc40fae23Rob Landley dirtree_handle_callback(dirtree_start(*args, toys.optflags&(FLAG_H|FLAG_L)), 1571f5f436826505df6dfabe1de9724424fc40fae23Rob Landley do_du); 158880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (toys.optflags & FLAG_c) print(TT.total*512, 0); 159880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 160880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (CFG_TOYBOX_FREE) seen_inode(TT.inodes, 0); 1611a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar} 162