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

📄 du.c

📁 Linux下文件工具。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Print N_BLOCKS followed by STRING on a line.  NBLOCKS is the number of   ST_NBLOCKSIZE-byte blocks; convert it to OUTPUT_BLOCK_SIZE units before   printing.  If OUTPUT_BLOCK_SIZE is negative, use a human readable   notation instead.  */static voidprint_size (uintmax_t n_blocks, const char *string){  char buf[LONGEST_HUMAN_READABLE + 1];  printf ("%s\t%s\n",	  human_readable_inexact (n_blocks, buf, ST_NBLOCKSIZE,				  output_block_size, human_ceiling),	  string);  fflush (stdout);}/* Restore the previous working directory or exit.   If CWD is null, simply call `chdir ("..")'.  Otherwise,   use CWD and free it.  CURR_DIR_NAME is the name of the current directory   and is used solely in failure diagnostics.  */static voidpop_dir (struct saved_cwd *cwd, const char *curr_dir_name){  if (cwd)    {      if (restore_cwd (cwd, "..", curr_dir_name))	exit (1);      free_cwd (cwd);    }  else if (chdir ("..") < 0)    {      error (1, errno, _("cannot change to `..' from directory %s"),	     quote (curr_dir_name));    }}/* Print (if appropriate) the size (in units determined by `output_block_size')   of file or directory ENT. Return the size of ENT in units of 512-byte   blocks.  TOP is one for external calls, zero for recursive calls.   LAST_DEV is the device that the parent directory of ENT is on.   DEPTH is the number of levels (in hierarchy) down from a command   line argument.  Don't print if DEPTH > max_depth.   An important invariant is that when this function returns, the current   working directory is the same as when it was called.  */static uintmax_tcount_entry (const char *ent, int top, dev_t last_dev, int depth){  uintmax_t size;  struct stat stat_buf;  if (((top && opt_dereference_arguments)       ? stat (ent, &stat_buf)       : (*xstat) (ent, &stat_buf)) < 0)    {      error (0, errno, "%s", quote (path->text));      exit_status = 1;      return 0;    }  if (!opt_count_all      && stat_buf.st_nlink > 1      && hash_ins (stat_buf.st_ino, stat_buf.st_dev))    return 0;			/* Have counted this already.  */  size = ST_NBLOCKS (stat_buf);  tot_size += size;  if (S_ISDIR (stat_buf.st_mode))    {      unsigned pathlen;      dev_t dir_dev;      char *name_space;      char *namep;      struct saved_cwd *cwd;      struct saved_cwd cwd_buf;      struct stat e_buf;      dir_dev = stat_buf.st_dev;      /* Return `0' here, not SIZE, since the SIZE bytes	 would reside in the new filesystem.  */      if (opt_one_file_system && !top && last_dev != dir_dev)	return 0;		/* Don't enter a new file system.  */#ifndef S_ISLNK# define S_ISLNK(s) 0#endif      /* If we're traversing more than one level, or if we're	 dereferencing symlinks and we're about to chdir through a	 symlink, remember the current directory so we can return to	 it later.  In other cases, chdir ("..") works fine.	 Treat `.' and `..' like multi-level paths, since `chdir ("..")'	 wont't restore the current working directory after a `chdir'	 to one of those.  */      if (strchr (ent, '/')	  || DOT_OR_DOTDOT (ent)	  || (xstat == stat	      && lstat (ent, &e_buf) == 0	      && S_ISLNK (e_buf.st_mode)))	{	  if (save_cwd (&cwd_buf))	    exit (1);	  cwd = &cwd_buf;	}      else	cwd = NULL;      if (chdir (ent) < 0)	{	  error (0, errno, _("cannot change to directory %s"),		 quote (path->text));	  if (cwd)	    free_cwd (cwd);	  exit_status = 1;	  /* Do return SIZE, here, since even though we can't chdir into ENT,	     we *can* count the blocks used by its directory entry.  */	  return opt_separate_dirs ? 0 : size;	}      name_space = savedir (".");      if (name_space == NULL)	{	  error (0, errno, "%s", quote (path->text));	  pop_dir (cwd, path->text);	  exit_status = 1;	  /* Do count the SIZE bytes.  */	  return opt_separate_dirs ? 0 : size;	}      /* Remember the current path.  */      str_concatc (path, "/");      pathlen = path->length;      for (namep = name_space; *namep; namep += strlen (namep) + 1)	{	  if (!excluded_filename (exclude, namep))	    {	      str_concatc (path, namep);	      size += count_entry (namep, 0, dir_dev, depth + 1);	      str_trunc (path, pathlen);	    }	}      free (name_space);      pop_dir (cwd, path->text);      str_trunc (path, pathlen - 1); /* Remove the "/" we added.  */      if (depth <= max_depth || top)	print_size (size, path->length > 0 ? path->text : "/");      return opt_separate_dirs ? 0 : size;    }  else if ((opt_all && depth <= max_depth) || top)    {      /* FIXME: make this an option.  */      int print_only_dir_size = 0;      if (!print_only_dir_size)	print_size (size, path->length > 0 ? path->text : "/");    }  return size;}/* Recursively print the sizes of the directories (and, if selected, files)   named in FILES, the last entry of which is NULL.  */static voiddu_files (char **files){  int i;			/* Index in FILES. */  for (i = 0; files[i]; i++)    {      char *arg;      int s;      arg = files[i];      /* 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 (!print_totals)	hash_clear (htab);      count_entry (arg, 1, 0, 0);    }  if (print_totals)    print_size (tot_size, _("total"));}intmain (int argc, char **argv){  int c;  char *cwd_only[2];  int max_depth_specified = 0;  /* If nonzero, display only a total for each argument. */  int opt_summarize_only = 0;  cwd_only[0] = ".";  cwd_only[1] = NULL;  program_name = argv[0];  setlocale (LC_ALL, "");  bindtextdomain (PACKAGE, LOCALEDIR);  textdomain (PACKAGE);  atexit (close_stdout);  exclude = new_exclude ();  xstat = lstat;  human_block_size (getenv ("DU_BLOCK_SIZE"), 0, &output_block_size);  while ((c = getopt_long (argc, argv, "abchHklmsxB:DLSX:", long_options, NULL))	 != -1)    {      long int tmp_long;      switch (c)	{	case 0:			/* Long option. */	  break;	case 'a':	  opt_all = 1;	  break;	case 'b':	  output_block_size = 1;	  break;	case 'c':	  print_totals = 1;	  break;	case 'h':	  output_block_size = -1024;	  break;	case 'H':	  output_block_size = -1000;	  break;	case 'k':	  output_block_size = 1024;	  break;	case MAX_DEPTH_OPTION:		/* --max-depth=N */	  if (xstrtol (optarg, NULL, 0, &tmp_long, NULL) != LONGINT_OK	      || tmp_long < 0 || tmp_long > INT_MAX)	    error (1, 0, _("invalid maximum depth %s"), quote (optarg));	  max_depth_specified = 1;	  max_depth = (int) tmp_long; 	  break;	case 'm': /* obsolescent */	  output_block_size = 1024 * 1024;	  break;	case 'l':	  opt_count_all = 1;	  break;	case 's':	  opt_summarize_only = 1;	  break;	case 'x':	  opt_one_file_system = 1;	  break;	case 'B':	  human_block_size (optarg, 1, &output_block_size);	  break;	case 'D':	  opt_dereference_arguments = 1;	  break;	case 'L':	  xstat = stat;	  break;	case 'S':	  opt_separate_dirs = 1;	  break;	case 'X':	  if (add_exclude_file (add_exclude, exclude, optarg,				EXCLUDE_WILDCARDS, '\n'))	    error (1, errno, "%s", quote (optarg));	  break;	case EXCLUDE_OPTION:	  add_exclude (exclude, optarg, EXCLUDE_WILDCARDS);	  break;	case_GETOPT_HELP_CHAR;	case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);	default:	  usage (1);	}    }  if (opt_all && opt_summarize_only)    {      error (0, 0, _("cannot both summarize and show all entries"));      usage (1);    }  if (opt_summarize_only && max_depth_specified && max_depth == 0)    {      error (0, 0,	     _("warning: summarizing is the same as using --max-depth=0"));    }  if (opt_summarize_only && max_depth_specified && max_depth != 0)    {      error (0, 0,	     _("warning: summarizing conflicts with --max-depth=%d"),	       max_depth);      usage (1);    }  if (opt_summarize_only)    max_depth = 0;  /* Initialize the hash structure for inode numbers.  */  hash_init ();  str_init (&path, INITIAL_PATH_SIZE);  du_files (optind == argc ? cwd_only : argv + optind);  exit (exit_status);}

⌨️ 快捷键说明

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