📄 du.c
字号:
/* du -- summarize disk usage Copyright (C) 88, 89, 90, 91, 1995-2002 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* Differences from the Unix du: * Doesn't simply ignore the names of regular files given as arguments when -a is given. * Additional options: -l Count the size of all files, even if they have appeared already in another hard link. -x Do not cross file-system boundaries during the recursion. -c Write a grand total of all of the arguments after all arguments have been processed. This can be used to find out the disk usage of a directory, with some files excluded. -h Print sizes in human readable format (1k 234M 2G, etc). -H Similar, but use powers of 1000 not 1024. -k Print sizes in kilobytes. -m Print sizes in megabytes. -b Print sizes in bytes. -S Count the size of each directory separately, not including the sizes of subdirectories. -D Dereference only symbolic links given on the command line. -L Dereference all symbolic links. --exclude=PATTERN Exclude files that match PATTERN. -X FILE Exclude files that match patterns taken from FILE. By tege@sics.se, Torbjorn Granlund, and djm@ai.mit.edu, David MacKenzie. Variable blocks added by lm@sgi.com and eggert@twinsun.com.*/#include <config.h>#if HAVE_INTTYPES_H# include <inttypes.h>#endif#include <stdio.h>#include <getopt.h>#include <sys/types.h>#include <assert.h>#include "system.h"#include "error.h"#include "exclude.h"#include "hash.h"#include "human.h"#include "quote.h"#include "same.h"#include "save-cwd.h"#include "savedir.h"#include "xstrtol.h"/* The official name of this program (e.g., no `g' prefix). */#define PROGRAM_NAME "du"#define AUTHORS \ "Torbjorn Granlund, David MacKenzie, Larry McVoy, and Paul Eggert"/* Initial size of the hash table. */#define INITIAL_TABLE_SIZE 103/* Initial size to allocate for `path'. */#define INITIAL_PATH_SIZE 100/* Hash structure for inode and device numbers. The separate entry structure makes it easier to rehash "in place". */struct entry{ ino_t st_ino; dev_t st_dev;};/* A set of dev/ino pairs. */static Hash_table *htab;/* Structure for dynamically resizable strings. */struct String{ unsigned alloc; /* Size of allocation for the text. */ unsigned length; /* Length of the text currently. */ char *text; /* Pointer to the text. */};typedef struct String String;int stat ();int lstat ();/* Name under which this program was invoked. */char *program_name;/* If nonzero, display counts for all files, not just directories. */static int opt_all = 0;/* If nonzero, count each hard link of files with multiple links. */static int opt_count_all = 0;/* If nonzero, do not cross file-system boundaries. */static int opt_one_file_system = 0;/* If nonzero, print a grand total at the end. */static int print_totals = 0;/* If nonzero, do not add sizes of subdirectories. */static int opt_separate_dirs = 0;/* If nonzero, dereference symlinks that are command line arguments. */static int opt_dereference_arguments = 0;/* Show the total for each directory (and file if --all) that is at most MAX_DEPTH levels down from the root of the hierarchy. The root is at level 0, so `du --max-depth=0' is equivalent to `du -s'. */static int max_depth = INT_MAX;/* If positive, the units to use when printing sizes; if negative, the human-readable base. */static int output_block_size;/* Accumulated path for file or directory being processed. */static String *path;/* A pointer to either lstat or stat, depending on whether dereferencing of all symbolic links is to be done. */static int (*xstat) ();/* The exit status to use if we don't get any fatal errors. */static int exit_status;/* File name patterns to exclude. */static struct exclude *exclude;/* Grand total size of all args, in units of ST_NBLOCKSIZE-byte blocks. */static uintmax_t tot_size = 0;/* For long options that have no equivalent short option, use a non-character as a pseudo short option, starting with CHAR_MAX + 1. */enum{ EXCLUDE_OPTION = CHAR_MAX + 1, MAX_DEPTH_OPTION};static struct option const long_options[] ={ {"all", no_argument, NULL, 'a'}, {"block-size", required_argument, 0, 'B'}, {"bytes", no_argument, NULL, 'b'}, {"count-links", no_argument, NULL, 'l'}, {"dereference", no_argument, NULL, 'L'}, {"dereference-args", no_argument, NULL, 'D'}, {"exclude", required_argument, 0, EXCLUDE_OPTION}, {"exclude-from", required_argument, 0, 'X'}, {"human-readable", no_argument, NULL, 'h'}, {"si", no_argument, 0, 'H'}, {"kilobytes", no_argument, NULL, 'k'}, /* long form is obsolescent */ {"max-depth", required_argument, NULL, MAX_DEPTH_OPTION}, {"megabytes", no_argument, NULL, 'm'}, /* obsolescent */ {"one-file-system", no_argument, NULL, 'x'}, {"separate-dirs", no_argument, NULL, 'S'}, {"summarize", no_argument, NULL, 's'}, {"total", no_argument, NULL, 'c'}, {GETOPT_HELP_OPTION_DECL}, {GETOPT_VERSION_OPTION_DECL}, {NULL, 0, NULL, 0}};voidusage (int status){ if (status != 0) fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name); else { printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name); fputs (_("\Summarize disk usage of each FILE, recursively for directories.\n\\n\"), stdout); fputs (_("\Mandatory arguments to long options are mandatory for short options too.\n\"), stdout); fputs (_("\ -a, --all write counts for all files, not just directories\n\ -B, --block-size=SIZE use SIZE-byte blocks\n\ -b, --bytes print size in bytes\n\ -c, --total produce a grand total\n\ -D, --dereference-args dereference PATHs when symbolic link\n\"), stdout); fputs (_("\ -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\n\ -H, --si likewise, but use powers of 1000 not 1024\n\ -k like --block-size=1K\n\ -l, --count-links count sizes many times if hard linked\n\"), stdout); fputs (_("\ -L, --dereference dereference all symbolic links\n\ -S, --separate-dirs do not include size of subdirectories\n\ -s, --summarize display only a total for each argument\n\"), stdout); fputs (_("\ -x, --one-file-system skip directories on different filesystems\n\ -X FILE, --exclude-from=FILE Exclude files that match any pattern in FILE.\n\ --exclude=PATTERN Exclude files that match PATTERN.\n\ --max-depth=N print the total for a directory (or file, with --all)\n\ only if it is N or fewer levels below the command\n\ line argument; --max-depth=0 is the same as\n\ --summarize\n\"), stdout); fputs (HELP_OPTION_DESCRIPTION, stdout); fputs (VERSION_OPTION_DESCRIPTION, stdout); fputs (_("\n\SIZE may be (or may be an integer optionally followed by) one of following:\n\kB 1000, K 1024, MB 1,000,000, M 1,048,576, and so on for G, T, P, E, Z, Y.\n\"), stdout); printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT); } exit (status);}static unsigned intentry_hash (void const *x, unsigned int table_size){ struct entry const *p = x; /* Ignoring the device number here should be fine. */ /* The cast to uintmax_t prevents negative remainders if st_ino is negative. */ return (uintmax_t) p->st_ino % table_size;}/* Compare two dev/ino pairs. Return true if they are the same. */static boolentry_compare (void const *x, void const *y){ struct entry const *a = x; struct entry const *b = y; return SAME_INODE (*a, *b) ? true : false;}/* Try to insert the INO/DEV pair into the global table, HTAB. If the pair is successfully inserted, return zero. Upon failed memory allocation exit nonzero. If the pair is already in the table, return nonzero. */static inthash_ins (ino_t ino, dev_t dev){ struct entry *ent; struct entry *ent_from_table; ent = (struct entry *) xmalloc (sizeof *ent); ent->st_ino = ino; ent->st_dev = dev; ent_from_table = hash_insert (htab, ent); if (ent_from_table == NULL) { /* Insertion failed due to lack of memory. */ xalloc_die (); } if (ent_from_table == ent) { /* Insertion succeeded. */ return 0; } /* That pair is already in the table, so ENT was not inserted. Free it. */ free (ent); return 1;}/* Initialize the hash table. */static voidhash_init (void){ htab = hash_initialize (INITIAL_TABLE_SIZE, NULL, entry_hash, entry_compare, free); if (htab == NULL) xalloc_die ();}/* Initialize string S1 to hold SIZE characters. */static voidstr_init (String **s1, unsigned int size){ String *s; s = (String *) xmalloc (sizeof (struct String)); s->text = xmalloc (size + 1); s->alloc = size; *s1 = s;}static voidensure_space (String *s, unsigned int size){ if (s->alloc < size) { s->text = xrealloc (s->text, size + 1); s->alloc = size; }}/* Assign the null-terminated C-string CSTR to S1. */static voidstr_copyc (String *s1, const char *cstr){ unsigned l = strlen (cstr); ensure_space (s1, l); strcpy (s1->text, cstr); s1->length = l;}static voidstr_concatc (String *s1, const char *cstr){ unsigned l1 = s1->length; unsigned l2 = strlen (cstr); unsigned l = l1 + l2; ensure_space (s1, l); strcpy (s1->text + l1, cstr); s1->length = l;}/* Truncate the string S1 to have length LENGTH. */static voidstr_trunc (String *s1, unsigned int length){ if (s1->length > length) { s1->text[length] = 0; s1->length = length; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -