📄 df.c
字号:
/* Restore the original cwd. */ { int save_errno = errno; if (restore_cwd (&cwd, 0, mp)) exit (1); /* We're scrod. */ free_cwd (&cwd); errno = save_errno; } return mp;}/* Figure out which device file or directory POINT is mounted on and show its disk usage. STATP is the results of `stat' on POINT. */static voidshow_point (const char *point, const struct stat *statp){ struct stat disk_stats; struct mount_entry *me; struct mount_entry *matching_dummy = NULL; char *needs_freeing = NULL; /* If POINT is an absolute path name, see if we can find the mount point without performing any extra stat calls at all. */ if (*point == '/') { for (me = mount_list; me; me = me->me_next) { if (STREQ (me->me_mountdir, point) && !STREQ (me->me_type, "lofs")) { /* Prefer non-dummy entries. */ if (! me->me_dummy) goto show_me; matching_dummy = me; } } if (matching_dummy) goto show_matching_dummy; } /* Ideally, the following mess of #if'd code would be in a separate file, and there'd be a single function call here. FIXME, someday. */#if HAVE_REALPATH || HAVE_RESOLVEPATH || HAVE_CANONICALIZE_FILE_NAME /* Calculate the real absolute path for POINT, and use that to find the mount point. This avoids statting unavailable mount points, which can hang df. */ { char const *abspoint = point; char *resolved; ssize_t resolved_len; struct mount_entry *best_match = NULL;# if HAVE_CANONICALIZE_FILE_NAME resolved = canonicalize_file_name (abspoint); resolved_len = resolved ? strlen (resolved) : -1;# else# if HAVE_RESOLVEPATH /* All known hosts with resolvepath (e.g. Solaris 7) don't turn relative names into absolute ones, so prepend the working directory if the path is not absolute. */ if (*point != '/') { static char const *wd; if (! wd) { struct stat pwd_stats; struct stat dot_stats; /* Use PWD if it is correct; this is usually cheaper than xgetcwd. */ wd = getenv ("PWD"); if (! (wd && stat (wd, &pwd_stats) == 0 && stat (".", &dot_stats) == 0 && SAME_INODE (pwd_stats, dot_stats))) wd = xgetcwd (); } if (wd) { needs_freeing = path_concat (wd, point, NULL); if (needs_freeing) abspoint = needs_freeing; } }# endif# if HAVE_RESOLVEPATH { size_t resolved_size = strlen (abspoint); while (1) { resolved_size = 2 * resolved_size + 1; resolved = xmalloc (resolved_size); resolved_len = resolvepath (abspoint, resolved, resolved_size); if (resolved_len < resolved_size) break; free (resolved); } }# else /* Use realpath only as a last resort. It provides a very poor interface. */ resolved = xmalloc (PATH_MAX + 1); resolved = (char *) realpath (abspoint, resolved); resolved_len = resolved ? strlen (resolved) : -1;# endif# endif if (1 <= resolved_len && resolved[0] == '/') { size_t best_match_len = 0; for (me = mount_list; me; me = me->me_next) if (! me->me_dummy) { size_t len = strlen (me->me_mountdir); if (best_match_len < len && len <= resolved_len && (len == 1 /* root file system */ || ((len == resolved_len || resolved[len] == '/') && strncmp (me->me_mountdir, resolved, len) == 0))) { best_match = me; best_match_len = len; } } } if (resolved) free (resolved); if (best_match && !STREQ (best_match->me_type, "lofs") && stat (best_match->me_mountdir, &disk_stats) == 0 && disk_stats.st_dev == statp->st_dev) { me = best_match; goto show_me; } }#endif for (me = mount_list; me; me = me->me_next) { if (me->me_dev == (dev_t) -1) { if (stat (me->me_mountdir, &disk_stats) == 0) me->me_dev = disk_stats.st_dev; else { error (0, errno, "%s", quote (me->me_mountdir)); exit_status = 1; /* So we won't try and fail repeatedly. */ me->me_dev = (dev_t) -2; } } if (statp->st_dev == me->me_dev) { /* Skip bogus mtab entries. */ if (stat (me->me_mountdir, &disk_stats) != 0 || disk_stats.st_dev != me->me_dev) { me->me_dev = (dev_t) -2; continue; } /* Prefer non-dummy entries. */ if (! me->me_dummy) goto show_me; matching_dummy = me; } } if (matching_dummy) goto show_matching_dummy; /* We couldn't find the mount entry corresponding to POINT. Go ahead and print as much info as we can; methods that require the device to be present will fail at a later point. */ { /* Find the actual mount point. */ char *mp = find_mount_point (point, statp); if (mp) { show_dev (0, mp, 0, 0, 0); free (mp); } else error (0, errno, "%s", quote (point)); } goto free_then_return; show_matching_dummy: me = matching_dummy; show_me: show_dev (me->me_devname, me->me_mountdir, me->me_type, me->me_dummy, me->me_remote); free_then_return: if (needs_freeing) free (needs_freeing);}/* Determine what kind of node PATH is and show the disk usage for it. STATP is the results of `stat' on PATH. */static voidshow_entry (const char *path, const struct stat *statp){ if (S_ISBLK (statp->st_mode) || S_ISCHR (statp->st_mode)) show_disk (path); else show_point (path, statp);}/* Show all mounted filesystems, except perhaps those that are of an unselected type or are empty. */static voidshow_all_entries (void){ struct mount_entry *me; for (me = mount_list; me; me = me->me_next) show_dev (me->me_devname, me->me_mountdir, me->me_type, me->me_dummy, me->me_remote);}/* Add FSTYPE to the list of filesystem types to display. */static voidadd_fs_type (const char *fstype){ struct fs_type_list *fsp; fsp = (struct fs_type_list *) xmalloc (sizeof (struct fs_type_list)); fsp->fs_name = (char *) fstype; fsp->fs_next = fs_select_list; fs_select_list = fsp;}/* Add FSTYPE to the list of filesystem types to be omitted. */static voidadd_excluded_fs_type (const char *fstype){ struct fs_type_list *fsp; fsp = (struct fs_type_list *) xmalloc (sizeof (struct fs_type_list)); fsp->fs_name = (char *) fstype; fsp->fs_next = fs_exclude_list; fs_exclude_list = fsp;}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 (_("\Show information about the filesystem on which each FILE resides,\n\or all filesystems by default.\n\\n\"), stdout); fputs (_("\Mandatory arguments to long options are mandatory for short options too.\n\"), stdout); fputs (_("\ -a, --all include filesystems having 0 blocks\n\ -B, --block-size=SIZE use SIZE-byte blocks\n\ -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\"), stdout); fputs (_("\ -i, --inodes list inode information instead of block usage\n\ -k like --block-size=1K\n\ -l, --local limit listing to local filesystems\n\ --no-sync do not invoke sync before getting usage info (default)\n\"), stdout); fputs (_("\ -P, --portability use the POSIX output format\n\ --sync invoke sync before getting usage info\n\ -t, --type=TYPE limit listing to filesystems of type TYPE\n\ -T, --print-type print filesystem type\n\ -x, --exclude-type=TYPE limit listing to filesystems not of type TYPE\n\ -v (ignored)\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);}intmain (int argc, char **argv){ int c; struct stat *stats IF_LINT (= 0); int n_valid_args = 0; program_name = argv[0]; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); atexit (close_stdout); fs_select_list = NULL; fs_exclude_list = NULL; inode_format = 0; show_all_fs = 0; show_listed_fs = 0; human_block_size (getenv ("DF_BLOCK_SIZE"), 0, &output_block_size); print_type = 0; posix_format = 0; exit_status = 0; while ((c = getopt_long (argc, argv, "aB:iF:hHklmPTt:vx:", long_options, NULL)) != -1) { switch (c) { case 0: /* Long option. */ break; case 'a': show_all_fs = 1; break; case 'B': human_block_size (optarg, 1, &output_block_size); break; case 'i': inode_format = 1; break; case 'h': output_block_size = -1024; break; case 'H': output_block_size = -1000; break; case 'k': output_block_size = 1024; break; case 'l': show_local_fs = 1; break; case 'm': /* obsolescent */ output_block_size = 1024 * 1024; break; case 'T': print_type = 1; break; case 'P': posix_format = 1; break; case SYNC_OPTION: require_sync = 1; break; case NO_SYNC_OPTION: require_sync = 0; break; case 'F': /* Accept -F as a synonym for -t for compatibility with Solaris. */ case 't': add_fs_type (optarg); break; case 'v': /* For SysV compatibility. */ /* ignore */ break; case 'x': add_excluded_fs_type (optarg); break; case_GETOPT_HELP_CHAR; case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); default: usage (1); } } /* Fail if the same file system type was both selected and excluded. */ { int match = 0; struct fs_type_list *fs_incl; for (fs_incl = fs_select_list; fs_incl; fs_incl = fs_incl->fs_next) { struct fs_type_list *fs_excl; for (fs_excl = fs_exclude_list; fs_excl; fs_excl = fs_excl->fs_next) { if (STREQ (fs_incl->fs_name, fs_excl->fs_name)) { error (0, 0, _("file system type %s both selected and excluded"), quote (fs_incl->fs_name)); match = 1; break; } } } if (match) exit (1); } { int i; /* stat all the given entries to make sure they get automounted, if necessary, before reading the filesystem table. */ stats = (struct stat *) xmalloc ((argc - optind) * sizeof (struct stat)); for (i = optind; i < argc; ++i) { if (stat (argv[i], &stats[i - optind])) { error (0, errno, "%s", quote (argv[i])); exit_status = 1; argv[i] = NULL; } else { ++n_valid_args; } } } mount_list = read_filesystem_list ((fs_select_list != NULL || fs_exclude_list != NULL || print_type || show_local_fs)); if (mount_list == NULL) { /* Couldn't read the table of mounted filesystems. Fail if df was invoked with no file name arguments; Otherwise, merely give a warning and proceed. */ const char *warning = (optind == argc ? "" : _("Warning: ")); int status = (optind == argc ? 1 : 0); error (status, errno, _("%scannot read table of mounted filesystems"), warning); } if (require_sync) sync (); if (optind == argc) { print_header (); show_all_entries (); } else { int i; /* Display explicitly requested empty filesystems. */ show_listed_fs = 1; if (n_valid_args > 0) print_header (); for (i = optind; i < argc; ++i) if (argv[i]) show_entry (argv[i], &stats[i - optind]); } exit (exit_status);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -