⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 du.c

📁 HLPDK V10.0+ System Extension Library
💻 C
📖 第 1 页 / 共 2 页
字号:
/* du -- summarize disk usage
   Copyright (C) 1988, 1989, 1990 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, 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.
   -k		Print sizes in kilobytes instead of 512 byte blocks
		(the default required by POSIX).
   -b		Print sizes in bytes (added by POSIX).

   By tege@sics.se, Torbjorn Granlund,
   and djm@ai.mit.edu, David MacKenzie.  */

#include <stdio.h>
#include <errno.h>
#include <getopt.h>
#include <sys/types.h>
#include "system.h"

#ifdef STDC_HEADERS
#include <stdlib.h>
#else
char *malloc ();
char *realloc ();

extern int errno;
#endif

/* Initial number of entries in each hash table entry's table of inodes.  */
#define INITIAL_HASH_MODULE 100

/* Initial number of entries in the inode hash table.  */
#define INITIAL_ENTRY_TAB_SIZE 70

/* 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 ino;
  dev_t dev;
  struct entry *coll_link;
};

/* Structure for a hash table for inode numbers. */

struct htab
{
  unsigned modulus;		/* Size of the `hash' pointer vector.  */
  struct entry *entry_tab;	/* Pointer to dynamically growing vector.  */
  unsigned entry_tab_size;	/* Size of current `entry_tab' allocation.  */
  unsigned first_free_entry;	/* Index in `entry_tab'.  */
  struct entry *hash[1];	/* Vector of pointers in `entry_tab'.  */
};


/* Structure for dynamically resizable strings. */

typedef struct
{
  unsigned alloc;		/* Size of allocation for the text.  */
  unsigned length;		/* Length of the text currently.  */
  char *text;			/* Pointer to the text.  */
} *string, stringstruct;

char *savedir ();
char *xmalloc ();
char *xrealloc ();
int hash_insert ();
int hash_insert2 ();
long count_entry ();
void error ();
void hash_init ();
void hash_reset ();
void str_concatc ();
void str_copyc ();
void str_init ();
void str_trunc ();

/* Name under which this program was invoked.  */
char *program_name;

/* If nonzero, display only a total for each argument. */
int opt_summarize_only = 0;

/* If nonzero, display counts for all files, not just directories. */
int opt_all = 0;

/* If nonzero, count each hard link of files with multiple links. */
int opt_count_all = 0;

/* If nonzero, do not cross file-system boundaries. */
int opt_one_file_system = 0;

/* If nonzero, print a grand total at the end. */
int opt_combined_arguments = 0;

enum output_size
{
  size_blocks,			/* Default. */
  size_kilobytes,		/* -k. */
  size_bytes			/* -b. */
};

/* The units to count in. */
enum output_size output_size = size_blocks;

/* Accumulated path for file or directory being processed.  */
string path;

/* Pointer to hash structure, used by the hash routines.  */
struct htab *htab;

/* Globally used stat buffer.  */
struct stat stat_buf;

struct option long_options[] =
{
  {"all", 0, &opt_all, 1},
  {"bytes", 0, NULL, 'b'},
  {"count-links", 0, &opt_count_all, 1},
  {"kilobytes", 0, NULL, 'k'},
  {"one-file-system", 0, &opt_one_file_system, 1},
  {"summarize", 0, &opt_summarize_only, 1},
  {"total", 0, &opt_combined_arguments, 1},
  {NULL, 0, NULL, 0}
};

void
usage (reason)
     char *reason;
{
  if (reason != NULL)
    fprintf (stderr, "%s: %s\n", program_name, reason);

  fprintf (stderr, "\
Usage: %s [-abcklsx] [+all] [+total] [+count-links] [+summarize]\n\
       [+bytes] [+kilobytes] [+one-file-system] [path...]\n",
	   program_name);

  exit (2);
}

void
main (argc, argv)
     int argc;
     char *argv[];
{
  int c;
  int ind;

  program_name = argv[0];

  while ((c = getopt_long (argc, argv, "abcklsx", long_options, &ind)) != EOF)
    {
      switch (c)
	{
	case 0:			/* Long option. */
	  break;

	case 'a':
	  opt_all = 1;
	  break;

	case 'b':
	  output_size = size_bytes;
	  break;

	case 'c':
	  opt_combined_arguments = 1;
	  break;

	case 'x':
	  opt_one_file_system = 1;
	  break;

	case 'k':
	  output_size = size_kilobytes;
	  break;

	case 'l':
	  opt_count_all = 1;
	  break;

	case 's':
	  opt_summarize_only = 1;
	  break;

	default:
	  usage ((char *) 0);
	}
    }

  if (opt_all && opt_summarize_only)
    usage ("cannot both summarize and show all entries");

  /* Initialize the hash structure for inode numbers.  */

  hash_init (INITIAL_HASH_MODULE, INITIAL_ENTRY_TAB_SIZE);

  str_init (&path, INITIAL_PATH_SIZE);

  if (optind == argc)
    {
      str_copyc (path, ".");

      /* Initialize the hash structure for inode numbers.  */

      hash_reset ();

      /* Get the size of the current directory only.  */

      count_entry (".", 1, 0);
    }
  else
    {
      char wd[PATH_MAX + 2];
      char *arg;
      ino_t initial_ino;	/* Initial directory's inode. */
      dev_t initial_dev;	/* Initial directory's device. */
      long tot_size = 0;	/* Grand total size of all args. */

      if (getwd (wd) == NULL)
	error (1, errno, "cannot get current directory");

      /* Remember the inode and device number of the current directory.  */

      if (stat (".", &stat_buf))
	error (1, errno, "current directory");
      initial_ino = stat_buf.st_ino;
      initial_dev = stat_buf.st_dev;

      do
	{
	  int s;
	  arg = argv[optind];

	  /* Delete final slash in the argument, unless the slash is alone.  */

	  s = strlen (arg) - 1;
	  if (s != 0)
	    {
	      if (arg[s] == '/')
		arg[s] = 0;

	      str_copyc (path, arg);
	    }
	  else if (arg[0] == '/')
	    str_trunc (path, 0);/* Null path for root directory.  */
	  else
	    str_copyc (path, arg);

	  if (!opt_combined_arguments)
	    hash_reset ();

	  tot_size += count_entry (arg, 1, 0);

	  /* chdir if `count_entry' has changed the working directory.  */

	  if (stat (".", &stat_buf))
	    error (1, errno, ".");
	  if ((stat_buf.st_ino != initial_ino
	       || stat_buf.st_dev != initial_dev)
	      && chdir (wd) < 0)
	    error (1, errno, "cannot change to directory %s", wd);

	  optind++;
	}
      while (optind < argc);

      if (opt_combined_arguments)
	{
	  printf ("%ld\ttotal\n", output_size == size_bytes ? tot_size
		  : convert_blocks (tot_size, output_size == size_kilobytes));
	  fflush (stdout);
	}
    }
  exit (0);
}

/* Print (if appropriate) and return the size
   (in units determined by `output_size') of file or directory ENT.
   TOP is one for external calls, zero for recursive calls.
   LAST_DEV is the device that the parent directory of ENT is on.  */

long
count_entry (ent, top, last_dev)
     char *ent;
     int top;
     dev_t last_dev;
{
  long size;

  if (lstat (ent, &stat_buf) < 0)
    {
      error (0, errno, "%s", path->text);
      return 0;
    }

  if (!opt_count_all
      && stat_buf.st_nlink > 1
      && hash_insert (stat_buf.st_ino, stat_buf.st_dev))
    return 0;			/* Have counted this already.  */

  if (output_size == size_bytes)
    size = stat_buf.st_size;
  else
    {
      size = ST_NBLOCKS (stat_buf);
#ifdef HPUX_NFS_BUG
      if (size >= 2 * (stat_buf.st_size + DEV_BSIZE - 1) / DEV_BSIZE)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -