1 /* df - summarize free disk space
2 Copyright (C) 91, 1995-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18 /* Written by David MacKenzie <djm@gnu.ai.mit.edu>.
19 --human-readable and --megabyte options added by lm@sgi.com.
20 --si and large file support added by eggert@twinsun.com. */
24 #include <sys/types.h>
28 #include "canonicalize.h"
34 #include "mountlist.h"
39 /* The official name of this program (e.g., no `g' prefix). */
40 #define PROGRAM_NAME "df"
43 "Torbjorn Granlund", "David MacKenzie", "Paul Eggert"
45 /* Name this program was run with. */
48 /* If true, show inode information. */
49 static bool inode_format;
51 /* If true, show even file systems with zero size or
52 uninteresting types. */
53 static bool show_all_fs;
55 /* If true, show only local file systems. */
56 static bool show_local_fs;
58 /* If true, output data for each file system corresponding to a
59 command line argument -- even if it's a dummy (automounter) entry. */
60 static bool show_listed_fs;
62 /* Human-readable options for output. */
63 static int human_output_opts;
65 /* The units to use when printing sizes. */
66 static uintmax_t output_block_size;
68 /* If true, use the POSIX output format. */
69 static bool posix_format;
71 /* If true, invoke the `sync' system call before getting any usage data.
72 Using this option can make df very slow, especially with many or very
73 busy disks. Note that this may make a difference on some systems --
74 SunOS 4.1.3, for one. It is *not* necessary on Linux. */
75 static bool require_sync;
77 /* Desired exit status. */
78 static int exit_status;
80 /* A file system type to display. */
85 struct fs_type_list *fs_next;
88 /* Linked list of file system types to display.
89 If `fs_select_list' is NULL, list all types.
90 This table is generated dynamically from command-line options,
91 rather than hardcoding into the program what it thinks are the
92 valid file system types; let the user specify any file system type
93 they want to, and if there are any file systems of that type, they
96 Some file system types:
97 4.2 4.3 ufs nfs swap ignore io vm efs dbg */
99 static struct fs_type_list *fs_select_list;
101 /* Linked list of file system types to omit.
102 If the list is empty, don't exclude any types. */
104 static struct fs_type_list *fs_exclude_list;
106 /* Linked list of mounted file systems. */
107 static struct mount_entry *mount_list;
109 /* If true, print file system type as well. */
110 static bool print_type;
112 /* For long options that have no equivalent short option, use a
113 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
116 NO_SYNC_OPTION = CHAR_MAX + 1,
117 /* FIXME: --kilobytes is deprecated (but not -k); remove in late 2006 */
118 KILOBYTES_LONG_OPTION,
122 static struct option const long_options[] =
124 {"all", no_argument, NULL, 'a'},
125 {"block-size", required_argument, NULL, 'B'},
126 {"inodes", no_argument, NULL, 'i'},
127 {"human-readable", no_argument, NULL, 'h'},
128 {"si", no_argument, NULL, 'H'},
129 {"kilobytes", no_argument, NULL, KILOBYTES_LONG_OPTION},
130 {"local", no_argument, NULL, 'l'},
131 {"megabytes", no_argument, NULL, 'm'}, /* obsolescent */
132 {"portability", no_argument, NULL, 'P'},
133 {"print-type", no_argument, NULL, 'T'},
134 {"sync", no_argument, NULL, SYNC_OPTION},
135 {"no-sync", no_argument, NULL, NO_SYNC_OPTION},
136 {"type", required_argument, NULL, 't'},
137 {"exclude-type", required_argument, NULL, 'x'},
138 {GETOPT_HELP_OPTION_DECL},
139 {GETOPT_VERSION_OPTION_DECL},
146 char buf[MAX (LONGEST_HUMAN_READABLE + 1, INT_BUFSIZE_BOUND (uintmax_t))];
149 fputs (_("Filesystem Type"), stdout);
151 fputs (_("Filesystem "), stdout);
154 printf (_(" Inodes IUsed IFree IUse%%"));
155 else if (human_output_opts & human_autoscale)
157 if (human_output_opts & human_base_1024)
158 printf (_(" Size Used Avail Use%%"));
160 printf (_(" Size Used Avail Use%%"));
162 else if (posix_format)
163 printf (_(" %4s-blocks Used Available Capacity"),
164 umaxtostr (output_block_size, buf));
167 int opts = (human_suppress_point_zero
168 | human_autoscale | human_SI
170 & (human_group_digits | human_base_1024 | human_B)));
172 /* Prefer the base that makes the human-readable value more exact,
173 if there is a difference. */
175 uintmax_t q1000 = output_block_size;
176 uintmax_t q1024 = output_block_size;
177 bool divisible_by_1000;
178 bool divisible_by_1024;
182 divisible_by_1000 = q1000 % 1000 == 0; q1000 /= 1000;
183 divisible_by_1024 = q1024 % 1024 == 0; q1024 /= 1024;
185 while (divisible_by_1000 & divisible_by_1024);
187 if (divisible_by_1000 < divisible_by_1024)
188 opts |= human_base_1024;
189 if (divisible_by_1024 < divisible_by_1000)
190 opts &= ~human_base_1024;
191 if (! (opts & human_base_1024))
194 printf (_(" %4s-blocks Used Available Use%%"),
195 human_readable (output_block_size, buf, opts, 1, 1));
198 printf (_(" Mounted on\n"));
201 /* Is FSTYPE a type of file system that should be listed? */
204 selected_fstype (const char *fstype)
206 const struct fs_type_list *fsp;
208 if (fs_select_list == NULL || fstype == NULL)
210 for (fsp = fs_select_list; fsp; fsp = fsp->fs_next)
211 if (STREQ (fstype, fsp->fs_name))
216 /* Is FSTYPE a type of file system that should be omitted? */
219 excluded_fstype (const char *fstype)
221 const struct fs_type_list *fsp;
223 if (fs_exclude_list == NULL || fstype == NULL)
225 for (fsp = fs_exclude_list; fsp; fsp = fsp->fs_next)
226 if (STREQ (fstype, fsp->fs_name))
231 /* Like human_readable (N, BUF, human_output_opts, INPUT_UNITS, OUTPUT_UNITS),
234 - If NEGATIVE, then N represents a negative number,
235 expressed in two's complement.
236 - Otherwise, return "-" if N is UINTMAX_MAX. */
239 df_readable (bool negative, uintmax_t n, char *buf,
240 uintmax_t input_units, uintmax_t output_units)
242 if (n == UINTMAX_MAX && !negative)
246 char *p = human_readable (negative ? -n : n, buf + negative,
247 human_output_opts, input_units, output_units);
254 /* Display a space listing for the disk device with absolute file name DISK.
255 If MOUNT_POINT is non-NULL, it is the name of the root of the
257 If STAT_FILE is non-null, it is the name of a file within the file
258 system that the user originally asked for; this provides better
259 diagnostics, and sometimes it provides better results on networked
260 file systems that give different free-space results depending on
261 where in the file system you probe.
262 If FSTYPE is non-NULL, it is the type of the file system on DISK.
263 If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may
264 not be able to produce statistics in this case.
265 ME_DUMMY and ME_REMOTE are the mount entry flags. */
268 show_dev (char const *disk, char const *mount_point,
269 char const *stat_file, char const *fstype,
270 bool me_dummy, bool me_remote)
273 char buf[3][LONGEST_HUMAN_READABLE + 2];
276 uintmax_t input_units;
277 uintmax_t output_units;
280 bool negate_available;
281 uintmax_t available_to_root;
286 if (me_remote & show_local_fs)
289 if (me_dummy & !show_all_fs & !show_listed_fs)
292 if (!selected_fstype (fstype) || excluded_fstype (fstype))
295 /* If MOUNT_POINT is NULL, then the file system is not mounted, and this
296 program reports on the file system that the special file is on.
297 It would be better to report on the unmounted file system,
298 but statfs doesn't do that on most systems. */
300 stat_file = mount_point ? mount_point : disk;
302 if (get_fs_usage (stat_file, disk, &fsu))
304 error (0, errno, "%s", quote (stat_file));
305 exit_status = EXIT_FAILURE;
309 if (fsu.fsu_blocks == 0 && !show_all_fs && !show_listed_fs)
313 disk = "-"; /* unknown */
315 fstype = "-"; /* unknown */
317 /* df.c reserved 5 positions for fstype,
318 but that does not suffice for type iso9660 */
321 size_t disk_name_len = strlen (disk);
322 size_t fstype_len = strlen (fstype);
323 if (disk_name_len + fstype_len < 18)
324 printf ("%s%*s ", disk, 18 - (int) disk_name_len, fstype);
325 else if (!posix_format)
326 printf ("%s\n%18s ", disk, fstype);
328 printf ("%s %s", disk, fstype);
332 if (strlen (disk) > 20 && !posix_format)
333 printf ("%s\n%20s", disk, "");
335 printf ("%-20s", disk);
342 input_units = output_units = 1;
343 total = fsu.fsu_files;
344 available = fsu.fsu_ffree;
345 negate_available = false;
346 available_to_root = available;
350 width = (human_output_opts & human_autoscale
351 ? 5 + ! (human_output_opts & human_base_1024)
353 use_width = ((posix_format
354 && ! (human_output_opts & human_autoscale))
356 input_units = fsu.fsu_blocksize;
357 output_units = output_block_size;
358 total = fsu.fsu_blocks;
359 available = fsu.fsu_bavail;
360 negate_available = (fsu.fsu_bavail_top_bit_set
361 & (available != UINTMAX_MAX));
362 available_to_root = fsu.fsu_bfree;
367 if (total != UINTMAX_MAX && available_to_root != UINTMAX_MAX)
369 used = total - available_to_root;
370 negate_used = (total < available_to_root);
373 printf (" %*s %*s %*s ",
374 width, df_readable (false, total,
375 buf[0], input_units, output_units),
376 width, df_readable (negate_used, used,
377 buf[1], input_units, output_units),
378 width, df_readable (negate_available, available,
379 buf[2], input_units, output_units));
381 if (used == UINTMAX_MAX || available == UINTMAX_MAX)
383 else if (!negate_used
384 && used <= TYPE_MAXIMUM (uintmax_t) / 100
385 && used + available != 0
386 && (used + available < used) == negate_available)
388 uintmax_t u100 = used * 100;
389 uintmax_t nonroot_total = used + available;
390 pct = u100 / nonroot_total + (u100 % nonroot_total != 0);
394 /* The calculation cannot be done easily with integer
395 arithmetic. Fall back on floating point. This can suffer
396 from minor rounding errors, but doing it exactly requires
397 multiple precision arithmetic, and it's not worth the
399 double u = negate_used ? - (double) - used : used;
400 double a = negate_available ? - (double) - available : available;
401 double nonroot_total = u + a;
404 long int lipct = pct = u * 100 / nonroot_total;
407 /* Like `pct = ceil (dpct);', but avoid ceil so that
408 the math library needn't be linked. */
409 if (ipct - 1 < pct && pct <= ipct + 1)
410 pct = ipct + (ipct < pct);
415 printf ("%*.0f%%", use_width - 1, pct);
417 printf ("%*s", use_width, "- ");
421 #ifdef HIDE_AUTOMOUNT_PREFIX
422 /* Don't print the first directory name in MOUNT_POINT if it's an
423 artifact of an automounter. This is a bit too aggressive to be
425 if (strncmp ("/auto/", mount_point, 6) == 0)
427 else if (strncmp ("/tmp_mnt/", mount_point, 9) == 0)
430 printf (" %s", mount_point);
435 /* Return the root mountpoint of the file system on which FILE exists, in
436 malloced storage. FILE_STAT should be the result of stating FILE.
437 Give a diagnostic and return NULL if unable to determine the mount point.
438 Exit if unable to restore current working directory. */
440 find_mount_point (const char *file, const struct stat *file_stat)
442 struct saved_cwd cwd;
443 struct stat last_stat;
444 char *mp = NULL; /* The malloced mount point. */
446 if (save_cwd (&cwd) != 0)
448 error (0, errno, _("cannot get current directory"));
452 if (S_ISDIR (file_stat->st_mode))
453 /* FILE is a directory, so just chdir there directly. */
455 last_stat = *file_stat;
456 if (chdir (file) < 0)
458 error (0, errno, _("cannot change to directory %s"), quote (file));
463 /* FILE is some other kind of file; use its directory. */
465 char *xdir = dir_name (file);
467 ASSIGN_STRDUPA (dir, xdir);
472 error (0, errno, _("cannot change to directory %s"), quote (dir));
476 if (stat (".", &last_stat) < 0)
478 error (0, errno, _("cannot stat current directory (now %s)"),
484 /* Now walk up FILE's parents until we find another file system or /,
485 chdiring as we go. LAST_STAT holds stat information for the last place
490 if (stat ("..", &st) < 0)
492 error (0, errno, _("cannot stat %s"), quote (".."));
495 if (st.st_dev != last_stat.st_dev || st.st_ino == last_stat.st_ino)
496 /* cwd is the mount point. */
498 if (chdir ("..") < 0)
500 error (0, errno, _("cannot change to directory %s"), quote (".."));
506 /* Finally reached a mount point, see what it's called. */
510 /* Restore the original cwd. */
512 int save_errno = errno;
513 if (restore_cwd (&cwd) != 0)
514 error (EXIT_FAILURE, errno,
515 _("failed to return to initial working directory"));
523 /* If DISK corresponds to a mount point, show its usage
524 and return true. Otherwise, return false. */
526 show_disk (char const *disk)
528 struct mount_entry const *me;
529 struct mount_entry const *best_match = NULL;
531 for (me = mount_list; me; me = me->me_next)
532 if (STREQ (disk, me->me_devname))
537 show_dev (best_match->me_devname, best_match->me_mountdir, NULL,
538 best_match->me_type, best_match->me_dummy,
539 best_match->me_remote);
546 /* Figure out which device file or directory POINT is mounted on
547 and show its disk usage.
548 STATP must be the result of `stat (POINT, STATP)'. */
550 show_point (const char *point, const struct stat *statp)
552 struct stat disk_stats;
553 struct mount_entry *me;
554 struct mount_entry const *best_match = NULL;
556 /* If POINT is an absolute file name, see if we can find the
557 mount point without performing any extra stat calls at all. */
560 /* Find the best match: prefer non-dummies, and then prefer the
561 last match if there are ties. */
563 for (me = mount_list; me; me = me->me_next)
564 if (STREQ (me->me_mountdir, point) && !STREQ (me->me_type, "lofs")
565 && (!best_match || best_match->me_dummy || !me->me_dummy))
569 /* Calculate the real absolute file name for POINT, and use that to find
570 the mount point. This avoids statting unavailable mount points,
571 which can hang df. */
574 char *resolved = canonicalize_file_name (point);
576 if (resolved && resolved[0] == '/')
578 size_t resolved_len = strlen (resolved);
579 size_t best_match_len = 0;
581 for (me = mount_list; me; me = me->me_next)
582 if (!STREQ (me->me_type, "lofs")
583 && (!best_match || best_match->me_dummy || !me->me_dummy))
585 size_t len = strlen (me->me_mountdir);
586 if (best_match_len <= len && len <= resolved_len
587 && (len == 1 /* root file system */
588 || ((len == resolved_len || resolved[len] == '/')
589 && strncmp (me->me_mountdir, resolved, len) == 0)))
592 best_match_len = len;
600 && (stat (best_match->me_mountdir, &disk_stats) != 0
601 || disk_stats.st_dev != statp->st_dev))
606 for (me = mount_list; me; me = me->me_next)
608 if (me->me_dev == (dev_t) -1)
610 if (stat (me->me_mountdir, &disk_stats) == 0)
611 me->me_dev = disk_stats.st_dev;
614 /* Report only I/O errors. Other errors might be
615 caused by shadowed mount points, which means POINT
616 can't possibly be on this file system. */
619 error (0, errno, "%s", quote (me->me_mountdir));
620 exit_status = EXIT_FAILURE;
623 /* So we won't try and fail repeatedly. */
624 me->me_dev = (dev_t) -2;
628 if (statp->st_dev == me->me_dev
629 && !STREQ (me->me_type, "lofs")
630 && (!best_match || best_match->me_dummy || !me->me_dummy))
632 /* Skip bogus mtab entries. */
633 if (stat (me->me_mountdir, &disk_stats) != 0
634 || disk_stats.st_dev != me->me_dev)
635 me->me_dev = (dev_t) -2;
642 show_dev (best_match->me_devname, best_match->me_mountdir, point,
643 best_match->me_type, best_match->me_dummy, best_match->me_remote);
646 /* We couldn't find the mount entry corresponding to POINT. Go ahead and
647 print as much info as we can; methods that require the device to be
648 present will fail at a later point. */
650 /* Find the actual mount point. */
651 char *mp = find_mount_point (point, statp);
654 show_dev (NULL, mp, NULL, NULL, false, false);
660 /* Determine what kind of node NAME is and show the disk usage
661 for it. STATP is the results of `stat' on NAME. */
664 show_entry (char const *name, struct stat const *statp)
666 if ((S_ISBLK (statp->st_mode) || S_ISCHR (statp->st_mode))
670 show_point (name, statp);
673 /* Show all mounted file systems, except perhaps those that are of
674 an unselected type or are empty. */
677 show_all_entries (void)
679 struct mount_entry *me;
681 for (me = mount_list; me; me = me->me_next)
682 show_dev (me->me_devname, me->me_mountdir, NULL, me->me_type,
683 me->me_dummy, me->me_remote);
686 /* Add FSTYPE to the list of file system types to display. */
689 add_fs_type (const char *fstype)
691 struct fs_type_list *fsp;
693 fsp = xmalloc (sizeof *fsp);
694 fsp->fs_name = (char *) fstype;
695 fsp->fs_next = fs_select_list;
696 fs_select_list = fsp;
699 /* Add FSTYPE to the list of file system types to be omitted. */
702 add_excluded_fs_type (const char *fstype)
704 struct fs_type_list *fsp;
706 fsp = xmalloc (sizeof *fsp);
707 fsp->fs_name = (char *) fstype;
708 fsp->fs_next = fs_exclude_list;
709 fs_exclude_list = fsp;
715 if (status != EXIT_SUCCESS)
716 fprintf (stderr, _("Try `%s --help' for more information.\n"),
720 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name);
722 Show information about the file system on which each FILE resides,\n\
723 or all file systems by default.\n\
727 Mandatory arguments to long options are mandatory for short options too.\n\
730 -a, --all include dummy file systems\n\
731 -B, --block-size=SIZE use SIZE-byte blocks\n\
732 -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\n\
733 -H, --si likewise, but use powers of 1000 not 1024\n\
736 -i, --inodes list inode information instead of block usage\n\
737 -k like --block-size=1K\n\
738 -l, --local limit listing to local file systems\n\
739 --no-sync do not invoke sync before getting usage info (default)\n\
742 -P, --portability use the POSIX output format\n\
743 --sync invoke sync before getting usage info\n\
744 -t, --type=TYPE limit listing to file systems of type TYPE\n\
745 -T, --print-type print file system type\n\
746 -x, --exclude-type=TYPE limit listing to file systems not of type TYPE\n\
749 fputs (HELP_OPTION_DESCRIPTION, stdout);
750 fputs (VERSION_OPTION_DESCRIPTION, stdout);
752 SIZE may be (or may be an integer optionally followed by) one of following:\n\
753 kB 1000, K 1024, MB 1000*1000, M 1024*1024, and so on for G, T, P, E, Z, Y.\n\
755 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
761 main (int argc, char **argv)
764 struct stat *stats IF_LINT (= 0);
765 int n_valid_args = 0;
767 initialize_main (&argc, &argv);
768 program_name = argv[0];
769 setlocale (LC_ALL, "");
770 bindtextdomain (PACKAGE, LOCALEDIR);
771 textdomain (PACKAGE);
773 atexit (close_stdout);
775 fs_select_list = NULL;
776 fs_exclude_list = NULL;
777 inode_format = false;
779 show_listed_fs = false;
781 human_output_opts = human_options (getenv ("DF_BLOCK_SIZE"), false,
785 posix_format = false;
786 exit_status = EXIT_SUCCESS;
788 while ((c = getopt_long (argc, argv, "aB:iF:hHklmPTt:vx:", long_options, NULL))
797 human_output_opts = human_options (optarg, true, &output_block_size);
803 human_output_opts = human_autoscale | human_SI | human_base_1024;
804 output_block_size = 1;
807 human_output_opts = human_autoscale | human_SI;
808 output_block_size = 1;
810 case KILOBYTES_LONG_OPTION:
812 _("the --kilobytes option is deprecated; use -k instead"));
815 human_output_opts = 0;
816 output_block_size = 1024;
819 show_local_fs = true;
821 case 'm': /* obsolescent */
822 human_output_opts = 0;
823 output_block_size = 1024 * 1024;
835 require_sync = false;
839 /* Accept -F as a synonym for -t for compatibility with Solaris. */
841 add_fs_type (optarg);
844 case 'v': /* For SysV compatibility. */
848 add_excluded_fs_type (optarg);
851 case_GETOPT_HELP_CHAR;
852 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
855 usage (EXIT_FAILURE);
859 /* Fail if the same file system type was both selected and excluded. */
862 struct fs_type_list *fs_incl;
863 for (fs_incl = fs_select_list; fs_incl; fs_incl = fs_incl->fs_next)
865 struct fs_type_list *fs_excl;
866 for (fs_excl = fs_exclude_list; fs_excl; fs_excl = fs_excl->fs_next)
868 if (STREQ (fs_incl->fs_name, fs_excl->fs_name))
871 _("file system type %s both selected and excluded"),
872 quote (fs_incl->fs_name));
886 /* stat all the given entries to make sure they get automounted,
887 if necessary, before reading the file system table. */
888 stats = xnmalloc (argc - optind, sizeof *stats);
889 for (i = optind; i < argc; ++i)
891 if (stat (argv[i], &stats[i - optind]))
893 error (0, errno, "%s", quote (argv[i]));
894 exit_status = EXIT_FAILURE;
905 read_file_system_list ((fs_select_list != NULL
906 || fs_exclude_list != NULL
910 if (mount_list == NULL)
912 /* Couldn't read the table of mounted file systems.
913 Fail if df was invoked with no file name arguments;
914 Otherwise, merely give a warning and proceed. */
915 const char *warning = (optind < argc ? _("Warning: ") : "");
916 int status = (optind < argc ? 0 : EXIT_FAILURE);
917 error (status, errno,
918 _("%scannot read table of mounted file systems"), warning);
928 /* Display explicitly requested empty file systems. */
929 show_listed_fs = true;
931 if (n_valid_args > 0)
934 for (i = optind; i < argc; ++i)
936 show_entry (argv[i], &stats[i - optind]);