1 /* du -- summarize disk usage
2 Copyright (C) 88, 89, 90, 91, 1995-2002 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Differences from the Unix du:
19 * Doesn't simply ignore the names of regular files given as arguments
22 -l Count the size of all files, even if they have appeared
23 already in another hard link.
24 -x Do not cross file-system boundaries during the recursion.
25 -c Write a grand total of all of the arguments after all
26 arguments have been processed. This can be used to find
27 out the disk usage of a directory, with some files excluded.
28 -h Print sizes in human readable format (1k 234M 2G, etc).
29 -H Similar, but use powers of 1000 not 1024.
30 -k Print sizes in kilobytes.
31 -m Print sizes in megabytes.
32 -b Print sizes in bytes.
33 -S Count the size of each directory separately, not including
34 the sizes of subdirectories.
35 -D Dereference only symbolic links given on the command line.
36 -L Dereference all symbolic links.
37 --exclude=PATTERN Exclude files that match PATTERN.
38 -X FILE Exclude files that match patterns taken from FILE.
40 By tege@sics.se, Torbjorn Granlund,
41 and djm@ai.mit.edu, David MacKenzie.
42 Variable blocks added by lm@sgi.com and eggert@twinsun.com.
47 # include <inttypes.h>
51 #include <sys/types.h>
65 /* The official name of this program (e.g., no `g' prefix). */
66 #define PROGRAM_NAME "du"
69 "Torbjorn Granlund, David MacKenzie, Larry McVoy, and Paul Eggert"
71 /* Initial size of the hash table. */
72 #define INITIAL_TABLE_SIZE 103
74 /* Initial size to allocate for `path'. */
75 #define INITIAL_PATH_SIZE 100
77 /* Hash structure for inode and device numbers. The separate entry
78 structure makes it easier to rehash "in place". */
86 /* A set of dev/ino pairs. */
87 static Hash_table
*htab
;
89 /* Structure for dynamically resizable strings. */
93 unsigned alloc
; /* Size of allocation for the text. */
94 unsigned length
; /* Length of the text currently. */
95 char *text
; /* Pointer to the text. */
97 typedef struct String String
;
102 /* Name under which this program was invoked. */
105 /* If nonzero, display counts for all files, not just directories. */
106 static int opt_all
= 0;
108 /* If nonzero, count each hard link of files with multiple links. */
109 static int opt_count_all
= 0;
111 /* If nonzero, do not cross file-system boundaries. */
112 static int opt_one_file_system
= 0;
114 /* If nonzero, print a grand total at the end. */
115 static int print_totals
= 0;
117 /* If nonzero, do not add sizes of subdirectories. */
118 static int opt_separate_dirs
= 0;
120 /* If nonzero, dereference symlinks that are command line arguments. */
121 static int opt_dereference_arguments
= 0;
123 /* Show the total for each directory (and file if --all) that is at
124 most MAX_DEPTH levels down from the root of the hierarchy. The root
125 is at level 0, so `du --max-depth=0' is equivalent to `du -s'. */
126 static int max_depth
= INT_MAX
;
128 /* If positive, the units to use when printing sizes;
129 if negative, the human-readable base. */
130 static int output_block_size
;
132 /* Accumulated path for file or directory being processed. */
135 /* A pointer to either lstat or stat, depending on whether
136 dereferencing of all symbolic links is to be done. */
137 static int (*xstat
) ();
139 /* The exit status to use if we don't get any fatal errors. */
140 static int exit_status
;
142 /* File name patterns to exclude. */
143 static struct exclude
*exclude
;
145 /* Grand total size of all args, in units of ST_NBLOCKSIZE-byte blocks. */
146 static uintmax_t tot_size
= 0;
148 /* For long options that have no equivalent short option, use a
149 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
152 EXCLUDE_OPTION
= CHAR_MAX
+ 1,
156 static struct option
const long_options
[] =
158 {"all", no_argument
, NULL
, 'a'},
159 {"block-size", required_argument
, 0, 'B'},
160 {"bytes", no_argument
, NULL
, 'b'},
161 {"count-links", no_argument
, NULL
, 'l'},
162 {"dereference", no_argument
, NULL
, 'L'},
163 {"dereference-args", no_argument
, NULL
, 'D'},
164 {"exclude", required_argument
, 0, EXCLUDE_OPTION
},
165 {"exclude-from", required_argument
, 0, 'X'},
166 {"human-readable", no_argument
, NULL
, 'h'},
167 {"si", no_argument
, 0, 'H'},
168 {"kilobytes", no_argument
, NULL
, 'k'}, /* long form is obsolescent */
169 {"max-depth", required_argument
, NULL
, MAX_DEPTH_OPTION
},
170 {"megabytes", no_argument
, NULL
, 'm'}, /* obsolescent */
171 {"one-file-system", no_argument
, NULL
, 'x'},
172 {"separate-dirs", no_argument
, NULL
, 'S'},
173 {"summarize", no_argument
, NULL
, 's'},
174 {"total", no_argument
, NULL
, 'c'},
175 {GETOPT_HELP_OPTION_DECL
},
176 {GETOPT_VERSION_OPTION_DECL
},
184 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
188 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name
);
190 Summarize disk usage of each FILE, recursively for directories.\n\
194 Mandatory arguments to long options are mandatory for short options too.\n\
197 -a, --all write counts for all files, not just directories\n\
198 -B, --block-size=SIZE use SIZE-byte blocks\n\
199 -b, --bytes print size in bytes\n\
200 -c, --total produce a grand total\n\
201 -D, --dereference-args dereference PATHs when symbolic link\n\
204 -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\n\
205 -H, --si likewise, but use powers of 1000 not 1024\n\
206 -k like --block-size=1K\n\
207 -l, --count-links count sizes many times if hard linked\n\
210 -L, --dereference dereference all symbolic links\n\
211 -S, --separate-dirs do not include size of subdirectories\n\
212 -s, --summarize display only a total for each argument\n\
215 -x, --one-file-system skip directories on different filesystems\n\
216 -X FILE, --exclude-from=FILE Exclude files that match any pattern in FILE.\n\
217 --exclude=PATTERN Exclude files that match PATTERN.\n\
218 --max-depth=N print the total for a directory (or file, with --all)\n\
219 only if it is N or fewer levels below the command\n\
220 line argument; --max-depth=0 is the same as\n\
223 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
224 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
226 SIZE may be (or may be an integer optionally followed by) one of following:\n\
227 kB 1000, K 1024, MB 1,000,000, M 1,048,576, and so on for G, T, P, E, Z, Y.\n\
229 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT
);
235 entry_hash (void const *x
, unsigned int table_size
)
237 struct entry
const *p
= x
;
239 /* Ignoring the device number here should be fine. */
240 /* The cast to uintmax_t prevents negative remainders
241 if st_ino is negative. */
242 return (uintmax_t) p
->st_ino
% table_size
;
245 /* Compare two dev/ino pairs. Return true if they are the same. */
247 entry_compare (void const *x
, void const *y
)
249 struct entry
const *a
= x
;
250 struct entry
const *b
= y
;
251 return SAME_INODE (*a
, *b
) ? true : false;
254 /* Try to insert the INO/DEV pair into the global table, HTAB.
255 If the pair is successfully inserted, return zero.
256 Upon failed memory allocation exit nonzero.
257 If the pair is already in the table, return nonzero. */
259 hash_ins (ino_t ino
, dev_t dev
)
262 struct entry
*ent_from_table
;
264 ent
= (struct entry
*) xmalloc (sizeof *ent
);
268 ent_from_table
= hash_insert (htab
, ent
);
269 if (ent_from_table
== NULL
)
271 /* Insertion failed due to lack of memory. */
275 if (ent_from_table
== ent
)
277 /* Insertion succeeded. */
281 /* That pair is already in the table, so ENT was not inserted. Free it. */
287 /* Initialize the hash table. */
291 htab
= hash_initialize (INITIAL_TABLE_SIZE
, NULL
,
292 entry_hash
, entry_compare
, free
);
297 /* Initialize string S1 to hold SIZE characters. */
300 str_init (String
**s1
, unsigned int size
)
304 s
= (String
*) xmalloc (sizeof (struct String
));
305 s
->text
= xmalloc (size
+ 1);
312 ensure_space (String
*s
, unsigned int size
)
316 s
->text
= xrealloc (s
->text
, size
+ 1);
321 /* Assign the null-terminated C-string CSTR to S1. */
324 str_copyc (String
*s1
, const char *cstr
)
326 unsigned l
= strlen (cstr
);
327 ensure_space (s1
, l
);
328 strcpy (s1
->text
, cstr
);
333 str_concatc (String
*s1
, const char *cstr
)
335 unsigned l1
= s1
->length
;
336 unsigned l2
= strlen (cstr
);
337 unsigned l
= l1
+ l2
;
339 ensure_space (s1
, l
);
340 strcpy (s1
->text
+ l1
, cstr
);
344 /* Truncate the string S1 to have length LENGTH. */
347 str_trunc (String
*s1
, unsigned int length
)
349 if (s1
->length
> length
)
351 s1
->text
[length
] = 0;
356 /* Print N_BLOCKS followed by STRING on a line. NBLOCKS is the number of
357 ST_NBLOCKSIZE-byte blocks; convert it to OUTPUT_BLOCK_SIZE units before
358 printing. If OUTPUT_BLOCK_SIZE is negative, use a human readable
362 print_size (uintmax_t n_blocks
, const char *string
)
364 char buf
[LONGEST_HUMAN_READABLE
+ 1];
366 human_readable_inexact (n_blocks
, buf
, ST_NBLOCKSIZE
,
367 output_block_size
, human_ceiling
),
372 /* Restore the previous working directory or exit.
373 If CWD is null, simply call `chdir ("..")'. Otherwise,
374 use CWD and free it. CURR_DIR_NAME is the name of the current directory
375 and is used solely in failure diagnostics. */
378 pop_dir (struct saved_cwd
*cwd
, const char *curr_dir_name
)
382 if (restore_cwd (cwd
, "..", curr_dir_name
))
386 else if (chdir ("..") < 0)
388 error (1, errno
, _("cannot change to `..' from directory %s"),
389 quote (curr_dir_name
));
393 /* Print (if appropriate) the size (in units determined by `output_block_size')
394 of file or directory ENT. Return the size of ENT in units of 512-byte
395 blocks. TOP is one for external calls, zero for recursive calls.
396 LAST_DEV is the device that the parent directory of ENT is on.
397 DEPTH is the number of levels (in hierarchy) down from a command
398 line argument. Don't print if DEPTH > max_depth.
399 An important invariant is that when this function returns, the current
400 working directory is the same as when it was called. */
403 count_entry (const char *ent
, int top
, dev_t last_dev
, int depth
)
406 struct stat stat_buf
;
408 if (((top
&& opt_dereference_arguments
)
409 ? stat (ent
, &stat_buf
)
410 : (*xstat
) (ent
, &stat_buf
)) < 0)
412 error (0, errno
, "%s", quote (path
->text
));
418 && stat_buf
.st_nlink
> 1
419 && hash_ins (stat_buf
.st_ino
, stat_buf
.st_dev
))
420 return 0; /* Have counted this already. */
422 size
= ST_NBLOCKS (stat_buf
);
425 if (S_ISDIR (stat_buf
.st_mode
))
431 struct saved_cwd
*cwd
;
432 struct saved_cwd cwd_buf
;
435 dir_dev
= stat_buf
.st_dev
;
437 /* Return `0' here, not SIZE, since the SIZE bytes
438 would reside in the new filesystem. */
439 if (opt_one_file_system
&& !top
&& last_dev
!= dir_dev
)
440 return 0; /* Don't enter a new file system. */
443 # define S_ISLNK(s) 0
445 /* If we're traversing more than one level, or if we're
446 dereferencing symlinks and we're about to chdir through a
447 symlink, remember the current directory so we can return to
448 it later. In other cases, chdir ("..") works fine.
449 Treat `.' and `..' like multi-level paths, since `chdir ("..")'
450 wont't restore the current working directory after a `chdir'
452 if (strchr (ent
, '/')
453 || DOT_OR_DOTDOT (ent
)
455 && lstat (ent
, &e_buf
) == 0
456 && S_ISLNK (e_buf
.st_mode
)))
458 if (save_cwd (&cwd_buf
))
467 error (0, errno
, _("cannot change to directory %s"),
472 /* Do return SIZE, here, since even though we can't chdir into ENT,
473 we *can* count the blocks used by its directory entry. */
474 return opt_separate_dirs
? 0 : size
;
477 name_space
= savedir (".");
478 if (name_space
== NULL
)
480 error (0, errno
, "%s", quote (path
->text
));
481 pop_dir (cwd
, path
->text
);
483 /* Do count the SIZE bytes. */
484 return opt_separate_dirs
? 0 : size
;
487 /* Remember the current path. */
489 str_concatc (path
, "/");
490 pathlen
= path
->length
;
492 for (namep
= name_space
; *namep
; namep
+= strlen (namep
) + 1)
494 if (!excluded_filename (exclude
, namep
))
496 str_concatc (path
, namep
);
497 size
+= count_entry (namep
, 0, dir_dev
, depth
+ 1);
498 str_trunc (path
, pathlen
);
503 pop_dir (cwd
, path
->text
);
505 str_trunc (path
, pathlen
- 1); /* Remove the "/" we added. */
506 if (depth
<= max_depth
|| top
)
507 print_size (size
, path
->length
> 0 ? path
->text
: "/");
508 return opt_separate_dirs
? 0 : size
;
510 else if ((opt_all
&& depth
<= max_depth
) || top
)
512 /* FIXME: make this an option. */
513 int print_only_dir_size
= 0;
514 if (!print_only_dir_size
)
515 print_size (size
, path
->length
> 0 ? path
->text
: "/");
521 /* Recursively print the sizes of the directories (and, if selected, files)
522 named in FILES, the last entry of which is NULL. */
525 du_files (char **files
)
527 int i
; /* Index in FILES. */
529 for (i
= 0; files
[i
]; i
++)
536 /* Delete final slash in the argument, unless the slash is alone. */
537 s
= strlen (arg
) - 1;
543 str_copyc (path
, arg
);
545 else if (arg
[0] == '/')
546 str_trunc (path
, 0); /* Null path for root directory. */
548 str_copyc (path
, arg
);
553 count_entry (arg
, 1, 0, 0);
557 print_size (tot_size
, _("total"));
561 main (int argc
, char **argv
)
565 int max_depth_specified
= 0;
567 /* If nonzero, display only a total for each argument. */
568 int opt_summarize_only
= 0;
573 program_name
= argv
[0];
574 setlocale (LC_ALL
, "");
575 bindtextdomain (PACKAGE
, LOCALEDIR
);
576 textdomain (PACKAGE
);
578 atexit (close_stdout
);
580 exclude
= new_exclude ();
583 human_block_size (getenv ("DU_BLOCK_SIZE"), 0, &output_block_size
);
585 while ((c
= getopt_long (argc
, argv
, "abchHklmsxB:DLSX:", long_options
, NULL
))
591 case 0: /* Long option. */
599 output_block_size
= 1;
607 output_block_size
= -1024;
611 output_block_size
= -1000;
615 output_block_size
= 1024;
618 case MAX_DEPTH_OPTION
: /* --max-depth=N */
619 if (xstrtol (optarg
, NULL
, 0, &tmp_long
, NULL
) != LONGINT_OK
620 || tmp_long
< 0 || tmp_long
> INT_MAX
)
621 error (1, 0, _("invalid maximum depth %s"), quote (optarg
));
623 max_depth_specified
= 1;
624 max_depth
= (int) tmp_long
;
627 case 'm': /* obsolescent */
628 output_block_size
= 1024 * 1024;
636 opt_summarize_only
= 1;
640 opt_one_file_system
= 1;
644 human_block_size (optarg
, 1, &output_block_size
);
648 opt_dereference_arguments
= 1;
656 opt_separate_dirs
= 1;
660 if (add_exclude_file (add_exclude
, exclude
, optarg
,
661 EXCLUDE_WILDCARDS
, '\n'))
662 error (1, errno
, "%s", quote (optarg
));
666 add_exclude (exclude
, optarg
, EXCLUDE_WILDCARDS
);
669 case_GETOPT_HELP_CHAR
;
671 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
678 if (opt_all
&& opt_summarize_only
)
680 error (0, 0, _("cannot both summarize and show all entries"));
684 if (opt_summarize_only
&& max_depth_specified
&& max_depth
== 0)
687 _("warning: summarizing is the same as using --max-depth=0"));
690 if (opt_summarize_only
&& max_depth_specified
&& max_depth
!= 0)
693 _("warning: summarizing conflicts with --max-depth=%d"),
698 if (opt_summarize_only
)
701 /* Initialize the hash structure for inode numbers. */
704 str_init (&path
, INITIAL_PATH_SIZE
);
706 du_files (optind
== argc
? cwd_only
: argv
+ optind
);