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 61a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 7880d4a96523c94d84bee1f066de5cf03756877a3Rob LandleyUSE_DU(NEWTOY(du, "d#<0hmlcaHkKLsx[-HL][-kKmh]", TOYFLAG_USR|TOYFLAG_BIN)) 81a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 91a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumarconfig DU 107aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley bool "du" 117aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley default y 127aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley help 137aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley usage: du [-d N] [-askxHLlmc] [file...] 147aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 15880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley Show disk usage, space consumed by files and directories. 16880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 17880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley Size in: 18880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -k 1024 byte blocks (default) 19880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -K 512 byte blocks (posix) 20880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -m megabytes 21880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -h human readable format (e.g., 1K 243M 2G ) 22880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 23880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley What to show: 24880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -a all files, not just directories 25880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -H follow symlinks on cmdline 26880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -L follow all symlinks 27880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -s only total size of each argument 28880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -x don't leave this filesystem 29880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -c cumulative total 30880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -d N only depth < N 31880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley -l disable hardlink filter 321a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar*/ 331a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 34c0e56edaf256adb6c60c5a052525a1ffbb927901Rob Landley#define FOR_du 351a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar#include "toys.h" 361a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 37c0e56edaf256adb6c60c5a052525a1ffbb927901Rob LandleyGLOBALS( 387aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley long maxdepth; 39880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 40880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley long depth, total; 417aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley dev_t st_dev; 42880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley void *inodes; 431a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar) 441a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 451a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumartypedef struct node_size { 467aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley struct dirtree *node; 477aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley long size; 48880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley} node_size; 491a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 50880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley// Print the size and name, given size in bytes 51880d4a96523c94d84bee1f066de5cf03756877a3Rob Landleystatic void print(long long size, struct dirtree *node) 521a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar{ 53880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley char *name = "total"; 541a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 55880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (TT.maxdepth && TT.depth > TT.maxdepth) return; 561a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 576c64f5f186d26d4c95d408979d33831935e026f1Rob Landley if (toys.optflags & FLAG_h) { 5848c172ba589cfd848624b51f6f748b56bc217775Rob Landley human_readable(toybuf, size); 5948c172ba589cfd848624b51f6f748b56bc217775Rob Landley printf("%s", toybuf); 606c64f5f186d26d4c95d408979d33831935e026f1Rob Landley } else { 61880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley int bits = 10; 62880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 63880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (toys.optflags & FLAG_K) bits = 9; 64880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley else if (toys.optflags & FLAG_m) bits = 20; 651a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 66880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley printf("%llu", (size>>bits)+!!(size&((1<<bits)-1))); 67880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley } 68880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (node) name = dirtree_path(node, NULL); 69880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley xprintf("\t%s\n", name); 70880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (node) free(name); 711a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar} 721a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 73880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley// Return whether or not we've seen this inode+dev, adding it to the list if 74880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley// we haven't. 75880d4a96523c94d84bee1f066de5cf03756877a3Rob Landleystatic int seen_inode(void **list, struct stat *st) 761a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar{ 77880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (!st) llist_traverse(st, free); 78880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 79880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley // Skipping dir nodes isn't _quite_ right. They're not hardlinked, but could 80880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley // be bind mounted. Still, it's more efficient and the archivers can't use 81880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley // hardlinked directory info anyway. (Note that we don't catch bind mounted 82880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley // _files_ because it doesn't change st_nlink.) 83880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley else if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) { 84880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley struct inode_list { 85880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley struct inode_list *next; 86880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley ino_t ino; 87880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley dev_t dev; 88880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley } *new; 89880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 90880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley for (new = *list; new; new = new->next) 91880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if(new->ino == st->st_ino && new->dev == st->st_dev) 92880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley return 1; 93880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 94880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley new = xzalloc(sizeof(*new)); 95880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley new->ino = st->st_ino; 96880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley new->dev = st->st_dev; 97880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley new->next = *list; 98880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley *list = new; 997aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 100880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 1017aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley return 0; 1021a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar} 1031a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 104880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley// dirtree callback, comput/display size of node 105880d4a96523c94d84bee1f066de5cf03756877a3Rob Landleystatic int do_du(struct dirtree *node) 1061a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar{ 107aab9164df395a4b0878b0ad930a5ec8a806a58e9Rob Landley if (!node->parent) TT.st_dev = node->st.st_dev; 108aab9164df395a4b0878b0ad930a5ec8a806a58e9Rob Landley else if (!dirtree_notdotdot(node)) return 0; 1097aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 110880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley // detect swiching filesystems 111880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if ((toys.optflags & FLAG_x) && (TT.st_dev != node->st.st_dev)) 112880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley return 0; 113880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 11410e0d86c088a3eccc27095b51d753e05f3f3cbc8Rob Landley // Don't loop endlessly on recursive directory symlink 11510e0d86c088a3eccc27095b51d753e05f3f3cbc8Rob Landley if (toys.optflags & FLAG_L) { 11610e0d86c088a3eccc27095b51d753e05f3f3cbc8Rob Landley struct dirtree *try = node; 11710e0d86c088a3eccc27095b51d753e05f3f3cbc8Rob Landley 11810e0d86c088a3eccc27095b51d753e05f3f3cbc8Rob Landley while ((try = try->parent)) 11910e0d86c088a3eccc27095b51d753e05f3f3cbc8Rob Landley if (node->st.st_dev==try->st.st_dev && node->st.st_ino==try->st.st_ino) 12010e0d86c088a3eccc27095b51d753e05f3f3cbc8Rob Landley return 0; 12110e0d86c088a3eccc27095b51d753e05f3f3cbc8Rob Landley } 12210e0d86c088a3eccc27095b51d753e05f3f3cbc8Rob Landley 123880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley // Don't count hard links twice 124fec3fd1f8ac1db9ed87b79bd3eb5e38aa835e881Rob Landley if (!(toys.optflags & FLAG_l) && !node->again) 125880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (seen_inode(&TT.inodes, &node->st)) return 0; 126880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 127880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley // Collect child info before printing directory size 128880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (S_ISDIR(node->st.st_mode)) { 129fec3fd1f8ac1db9ed87b79bd3eb5e38aa835e881Rob Landley if (!node->again) { 1307aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley TT.depth++; 1311f5f436826505df6dfabe1de9724424fc40fae23Rob Landley return DIRTREE_COMEAGAIN|(DIRTREE_SYMFOLLOW*!!(toys.optflags&FLAG_L)); 132880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley } else TT.depth--; 1337aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 134880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 135880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley node->extra += node->st.st_blocks; 136880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (node->parent) node->parent->extra += node->extra; 137880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley else TT.total += node->extra; 138880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 139880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if ((toys.optflags & FLAG_a) || !node->parent 140880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley || (S_ISDIR(node->st.st_mode) && !(toys.optflags & FLAG_s))) 141880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley { 142880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley print(node->extra*512, node); 1437aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 144880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 145880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley return 0; 1461a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar} 1471a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar 1481a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumarvoid du_main(void) 1491a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar{ 150aab9164df395a4b0878b0ad930a5ec8a806a58e9Rob Landley char *noargs[] = {".", 0}, **args; 151880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 152880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley // Loop over command line arguments, recursing through children 153aab9164df395a4b0878b0ad930a5ec8a806a58e9Rob Landley for (args = toys.optc ? toys.optargs : noargs; *args; args++) 1541f5f436826505df6dfabe1de9724424fc40fae23Rob Landley dirtree_handle_callback(dirtree_start(*args, toys.optflags&(FLAG_H|FLAG_L)), 1551f5f436826505df6dfabe1de9724424fc40fae23Rob Landley do_du); 156880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (toys.optflags & FLAG_c) print(TT.total*512, 0); 157880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley 158880d4a96523c94d84bee1f066de5cf03756877a3Rob Landley if (CFG_TOYBOX_FREE) seen_inode(TT.inodes, 0); 1591a0eedf795546171a7e84b47f0f02c7d286d2ec4Ashwini Kumar} 160