1 /* df - summarize free disk space
2 Copyright (C) 91, 1995-2007 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"
33 #include "mountlist.h"
38 /* The official name of this program (e.g., no `g' prefix). */
39 #define PROGRAM_NAME "df"
42 "Torbjorn Granlund", "David MacKenzie", "Paul Eggert"
44 /* Name this program was run with. */
47 /* If true, show inode information. */
48 static bool inode_format;
50 /* If true, show even file systems with zero size or
51 uninteresting types. */
52 static bool show_all_fs;
54 /* If true, show only local file systems. */
55 static bool show_local_fs;
57 /* If true, output data for each file system corresponding to a
58 command line argument -- even if it's a dummy (automounter) entry. */
59 static bool show_listed_fs;
61 /* Human-readable options for output. */
62 static int human_output_opts;
64 /* The units to use when printing sizes. */
65 static uintmax_t output_block_size;
67 /* If true, use the POSIX output format. */
68 static bool posix_format;
70 /* True if a file system has been processed for output. */
71 static bool file_systems_processed;
73 /* If true, invoke the `sync' system call before getting any usage data.
74 Using this option can make df very slow, especially with many or very
75 busy disks. Note that this may make a difference on some systems --
76 SunOS 4.1.3, for one. It is *not* necessary on Linux. */
77 static bool require_sync;
79 /* Desired exit status. */
80 static int exit_status;
82 /* A file system type to display. */
87 struct fs_type_list *fs_next;
90 /* Linked list of file system types to display.
91 If `fs_select_list' is NULL, list all types.
92 This table is generated dynamically from command-line options,
93 rather than hardcoding into the program what it thinks are the
94 valid file system types; let the user specify any file system type
95 they want to, and if there are any file systems of that type, they
98 Some file system types:
99 4.2 4.3 ufs nfs swap ignore io vm efs dbg */
101 static struct fs_type_list *fs_select_list;
103 /* Linked list of file system types to omit.
104 If the list is empty, don't exclude any types. */
106 static struct fs_type_list *fs_exclude_list;
108 /* Linked list of mounted file systems. */
109 static struct mount_entry *mount_list;
111 /* If true, print file system type as well. */
112 static bool print_type;
114 /* For long options that have no equivalent short option, use a
115 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
118 NO_SYNC_OPTION = CHAR_MAX + 1,
119 /* FIXME: --kilobytes is deprecated (but not -k); remove in late 2006 */
120 KILOBYTES_LONG_OPTION,
124 static struct option const long_options[] =
126 {"all", no_argument, NULL, 'a'},
127 {"block-size", required_argument, NULL, 'B'},
128 {"inodes", no_argument, NULL, 'i'},
129 {"human-readable", no_argument, NULL, 'h'},
130 {"si", no_argument, NULL, 'H'},
131 {"kilobytes", no_argument, NULL, KILOBYTES_LONG_OPTION},
132 {"local", no_argument, NULL, 'l'},
133 {"megabytes", no_argument, NULL, 'm'}, /* obsolescent */
134 {"portability", no_argument, NULL, 'P'},
135 {"print-type", no_argument, NULL, 'T'},
136 {"sync", no_argument, NULL, SYNC_OPTION},
137 {"no-sync", no_argument, NULL, NO_SYNC_OPTION},
138 {"type", required_argument, NULL, 't'},
139 {"exclude-type", required_argument, NULL, 'x'},
140 {GETOPT_HELP_OPTION_DECL},
141 {GETOPT_VERSION_OPTION_DECL},
148 char buf[MAX (LONGEST_HUMAN_READABLE + 1, INT_BUFSIZE_BOUND (uintmax_t))];
151 fputs (_("Filesystem Type"), stdout);
153 fputs (_("Filesystem "), stdout);
156 printf (_(" Inodes IUsed IFree IUse%%"));
157 else if (human_output_opts & human_autoscale)
159 if (human_output_opts & human_base_1024)
160 printf (_(" Size Used Avail Use%%"));
162 printf (_(" Size Used Avail Use%%"));
164 else if (posix_format)
165 printf (_(" %s-blocks Used Available Capacity"),
166 umaxtostr (output_block_size, buf));
169 int opts = (human_suppress_point_zero
170 | human_autoscale | human_SI
172 & (human_group_digits | human_base_1024 | human_B)));
174 /* Prefer the base that makes the human-readable value more exact,
175 if there is a difference. */
177 uintmax_t q1000 = output_block_size;
178 uintmax_t q1024 = output_block_size;
179 bool divisible_by_1000;
180 bool divisible_by_1024;
184 divisible_by_1000 = q1000 % 1000 == 0; q1000 /= 1000;
185 divisible_by_1024 = q1024 % 1024 == 0; q1024 /= 1024;
187 while (divisible_by_1000 & divisible_by_1024);
189 if (divisible_by_1000 < divisible_by_1024)
190 opts |= human_base_1024;
191 if (divisible_by_1024 < divisible_by_1000)
192 opts &= ~human_base_1024;
193 if (! (opts & human_base_1024))
196 printf (_(" %4s-blocks Used Available Use%%"),
197 human_readable (output_block_size, buf, opts, 1, 1));
200 printf (_(" Mounted on\n"));
203 /* Is FSTYPE a type of file system that should be listed? */
206 selected_fstype (const char *fstype)
208 const struct fs_type_list *fsp;
210 if (fs_select_list == NULL || fstype == NULL)
212 for (fsp = fs_select_list; fsp; fsp = fsp->fs_next)
213 if (STREQ (fstype, fsp->fs_name))
218 /* Is FSTYPE a type of file system that should be omitted? */
221 excluded_fstype (const char *fstype)
223 const struct fs_type_list *fsp;
225 if (fs_exclude_list == NULL || fstype == NULL)
227 for (fsp = fs_exclude_list; fsp; fsp = fsp->fs_next)
228 if (STREQ (fstype, fsp->fs_name))
233 /* Like human_readable (N, BUF, human_output_opts, INPUT_UNITS, OUTPUT_UNITS),
236 - If NEGATIVE, then N represents a negative number,
237 expressed in two's complement.
238 - Otherwise, return "-" if N is UINTMAX_MAX. */
241 df_readable (bool negative, uintmax_t n, char *buf,
242 uintmax_t input_units, uintmax_t output_units)
244 if (n == UINTMAX_MAX && !negative)
248 char *p = human_readable (negative ? -n : n, buf + negative,
249 human_output_opts, input_units, output_units);
256 /* Display a space listing for the disk device with absolute file name DISK.
257 If MOUNT_POINT is non-NULL, it is the name of the root of the
259 If STAT_FILE is non-null, it is the name of a file within the file
260 system that the user originally asked for; this provides better
261 diagnostics, and sometimes it provides better results on networked
262 file systems that give different free-space results depending on
263 where in the file system you probe.
264 If FSTYPE is non-NULL, it is the type of the file system on DISK.
265 If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may
266 not be able to produce statistics in this case.
267 ME_DUMMY and ME_REMOTE are the mount entry flags. */
270 show_dev (char const *disk, char const *mount_point,
271 char const *stat_file, char const *fstype,
272 bool me_dummy, bool me_remote)
275 char buf[3][LONGEST_HUMAN_READABLE + 2];
277 int col1_adjustment = 0;
279 uintmax_t input_units;
280 uintmax_t output_units;
283 bool negate_available;
284 uintmax_t available_to_root;
289 if (me_remote & show_local_fs)
292 if (me_dummy & !show_all_fs & !show_listed_fs)
295 if (!selected_fstype (fstype) || excluded_fstype (fstype))
298 /* If MOUNT_POINT is NULL, then the file system is not mounted, and this
299 program reports on the file system that the special file is on.
300 It would be better to report on the unmounted file system,
301 but statfs doesn't do that on most systems. */
303 stat_file = mount_point ? mount_point : disk;
305 if (get_fs_usage (stat_file, disk, &fsu))
307 error (0, errno, "%s", quote (stat_file));
308 exit_status = EXIT_FAILURE;
312 if (fsu.fsu_blocks == 0 && !show_all_fs && !show_listed_fs)
315 if (! file_systems_processed)
317 file_systems_processed = true;
322 disk = "-"; /* unknown */
324 fstype = "-"; /* unknown */
326 /* df.c reserved 5 positions for fstype,
327 but that does not suffice for type iso9660 */
330 size_t disk_name_len = strlen (disk);
331 size_t fstype_len = strlen (fstype);
332 if (disk_name_len + fstype_len < 18)
333 printf ("%s%*s ", disk, 18 - (int) disk_name_len, fstype);
334 else if (!posix_format)
335 printf ("%s\n%18s ", disk, fstype);
337 printf ("%s %s", disk, fstype);
341 if (strlen (disk) > 20 && !posix_format)
342 printf ("%s\n%20s", disk, "");
344 printf ("%-20s", disk);
351 input_units = output_units = 1;
352 total = fsu.fsu_files;
353 available = fsu.fsu_ffree;
354 negate_available = false;
355 available_to_root = available;
359 if (human_output_opts & human_autoscale)
360 width = 5 + ! (human_output_opts & human_base_1024);
367 col1_adjustment = -3;
368 for (b = output_block_size; 9 < b; b /= 10)
372 use_width = ((posix_format
373 && ! (human_output_opts & human_autoscale))
375 input_units = fsu.fsu_blocksize;
376 output_units = output_block_size;
377 total = fsu.fsu_blocks;
378 available = fsu.fsu_bavail;
379 negate_available = (fsu.fsu_bavail_top_bit_set
380 & (available != UINTMAX_MAX));
381 available_to_root = fsu.fsu_bfree;
386 if (total != UINTMAX_MAX && available_to_root != UINTMAX_MAX)
388 used = total - available_to_root;
389 negate_used = (total < available_to_root);
392 printf (" %*s %*s %*s ",
393 width + col1_adjustment,
394 df_readable (false, total,
395 buf[0], input_units, output_units),
396 width, df_readable (negate_used, used,
397 buf[1], input_units, output_units),
398 width, df_readable (negate_available, available,
399 buf[2], input_units, output_units));
401 if (used == UINTMAX_MAX || available == UINTMAX_MAX)
403 else if (!negate_used
404 && used <= TYPE_MAXIMUM (uintmax_t) / 100
405 && used + available != 0
406 && (used + available < used) == negate_available)
408 uintmax_t u100 = used * 100;
409 uintmax_t nonroot_total = used + available;
410 pct = u100 / nonroot_total + (u100 % nonroot_total != 0);
414 /* The calculation cannot be done easily with integer
415 arithmetic. Fall back on floating point. This can suffer
416 from minor rounding errors, but doing it exactly requires
417 multiple precision arithmetic, and it's not worth the
419 double u = negate_used ? - (double) - used : used;
420 double a = negate_available ? - (double) - available : available;
421 double nonroot_total = u + a;
424 long int lipct = pct = u * 100 / nonroot_total;
427 /* Like `pct = ceil (dpct);', but avoid ceil so that
428 the math library needn't be linked. */
429 if (ipct - 1 < pct && pct <= ipct + 1)
430 pct = ipct + (ipct < pct);
435 printf ("%*.0f%%", use_width - 1, pct);
437 printf ("%*s", use_width, "- ");
441 #ifdef HIDE_AUTOMOUNT_PREFIX
442 /* Don't print the first directory name in MOUNT_POINT if it's an
443 artifact of an automounter. This is a bit too aggressive to be
445 if (strncmp ("/auto/", mount_point, 6) == 0)
447 else if (strncmp ("/tmp_mnt/", mount_point, 9) == 0)
450 printf (" %s", mount_point);
455 /* Return the root mountpoint of the file system on which FILE exists, in
456 malloced storage. FILE_STAT should be the result of stating FILE.
457 Give a diagnostic and return NULL if unable to determine the mount point.
458 Exit if unable to restore current working directory. */
460 find_mount_point (const char *file, const struct stat *file_stat)
462 struct saved_cwd cwd;
463 struct stat last_stat;
464 char *mp = NULL; /* The malloced mount point. */
466 if (save_cwd (&cwd) != 0)
468 error (0, errno, _("cannot get current directory"));
472 if (S_ISDIR (file_stat->st_mode))
473 /* FILE is a directory, so just chdir there directly. */
475 last_stat = *file_stat;
476 if (chdir (file) < 0)
478 error (0, errno, _("cannot change to directory %s"), quote (file));
483 /* FILE is some other kind of file; use its directory. */
485 char *xdir = dir_name (file);
487 ASSIGN_STRDUPA (dir, xdir);
492 error (0, errno, _("cannot change to directory %s"), quote (dir));
496 if (stat (".", &last_stat) < 0)
498 error (0, errno, _("cannot stat current directory (now %s)"),
504 /* Now walk up FILE's parents until we find another file system or /,
505 chdiring as we go. LAST_STAT holds stat information for the last place
510 if (stat ("..", &st) < 0)
512 error (0, errno, _("cannot stat %s"), quote (".."));
515 if (st.st_dev != last_stat.st_dev || st.st_ino == last_stat.st_ino)
516 /* cwd is the mount point. */
518 if (chdir ("..") < 0)
520 error (0, errno, _("cannot change to directory %s"), quote (".."));
526 /* Finally reached a mount point, see what it's called. */
530 /* Restore the original cwd. */
532 int save_errno = errno;
533 if (restore_cwd (&cwd) != 0)
534 error (EXIT_FAILURE, errno,
535 _("failed to return to initial working directory"));
543 /* If DISK corresponds to a mount point, show its usage
544 and return true. Otherwise, return false. */
546 show_disk (char const *disk)
548 struct mount_entry const *me;
549 struct mount_entry const *best_match = NULL;
551 for (me = mount_list; me; me = me->me_next)
552 if (STREQ (disk, me->me_devname))
557 show_dev (best_match->me_devname, best_match->me_mountdir, NULL,
558 best_match->me_type, best_match->me_dummy,
559 best_match->me_remote);
566 /* Figure out which device file or directory POINT is mounted on
567 and show its disk usage.
568 STATP must be the result of `stat (POINT, STATP)'. */
570 show_point (const char *point, const struct stat *statp)
572 struct stat disk_stats;
573 struct mount_entry *me;
574 struct mount_entry const *best_match = NULL;
576 /* If POINT is an absolute file name, see if we can find the
577 mount point without performing any extra stat calls at all. */
580 /* Find the best match: prefer non-dummies, and then prefer the
581 last match if there are ties. */
583 for (me = mount_list; me; me = me->me_next)
584 if (STREQ (me->me_mountdir, point) && !STREQ (me->me_type, "lofs")
585 && (!best_match || best_match->me_dummy || !me->me_dummy))
589 /* Calculate the real absolute file name for POINT, and use that to find
590 the mount point. This avoids statting unavailable mount points,
591 which can hang df. */
594 char *resolved = canonicalize_file_name (point);
596 if (resolved && resolved[0] == '/')
598 size_t resolved_len = strlen (resolved);
599 size_t best_match_len = 0;
601 for (me = mount_list; me; me = me->me_next)
602 if (!STREQ (me->me_type, "lofs")
603 && (!best_match || best_match->me_dummy || !me->me_dummy))
605 size_t len = strlen (me->me_mountdir);
606 if (best_match_len <= len && len <= resolved_len
607 && (len == 1 /* root file system */
608 || ((len == resolved_len || resolved[len] == '/')
609 && strncmp (me->me_mountdir, resolved, len) == 0)))
612 best_match_len = len;
620 && (stat (best_match->me_mountdir, &disk_stats) != 0
621 || disk_stats.st_dev != statp->st_dev))
626 for (me = mount_list; me; me = me->me_next)
628 if (me->me_dev == (dev_t) -1)
630 if (stat (me->me_mountdir, &disk_stats) == 0)
631 me->me_dev = disk_stats.st_dev;
634 /* Report only I/O errors. Other errors might be
635 caused by shadowed mount points, which means POINT
636 can't possibly be on this file system. */
639 error (0, errno, "%s", quote (me->me_mountdir));
640 exit_status = EXIT_FAILURE;
643 /* So we won't try and fail repeatedly. */
644 me->me_dev = (dev_t) -2;
648 if (statp->st_dev == me->me_dev
649 && !STREQ (me->me_type, "lofs")
650 && (!best_match || best_match->me_dummy || !me->me_dummy))
652 /* Skip bogus mtab entries. */
653 if (stat (me->me_mountdir, &disk_stats) != 0
654 || disk_stats.st_dev != me->me_dev)
655 me->me_dev = (dev_t) -2;
662 show_dev (best_match->me_devname, best_match->me_mountdir, point,
663 best_match->me_type, best_match->me_dummy, best_match->me_remote);
666 /* We couldn't find the mount entry corresponding to POINT. Go ahead and
667 print as much info as we can; methods that require the device to be
668 present will fail at a later point. */
670 /* Find the actual mount point. */
671 char *mp = find_mount_point (point, statp);
674 show_dev (NULL, mp, NULL, NULL, false, false);
680 /* Determine what kind of node NAME is and show the disk usage
681 for it. STATP is the results of `stat' on NAME. */
684 show_entry (char const *name, struct stat const *statp)
686 if ((S_ISBLK (statp->st_mode) || S_ISCHR (statp->st_mode))
690 show_point (name, statp);
693 /* Show all mounted file systems, except perhaps those that are of
694 an unselected type or are empty. */
697 show_all_entries (void)
699 struct mount_entry *me;
701 for (me = mount_list; me; me = me->me_next)
702 show_dev (me->me_devname, me->me_mountdir, NULL, me->me_type,
703 me->me_dummy, me->me_remote);
706 /* Add FSTYPE to the list of file system types to display. */
709 add_fs_type (const char *fstype)
711 struct fs_type_list *fsp;
713 fsp = xmalloc (sizeof *fsp);
714 fsp->fs_name = (char *) fstype;
715 fsp->fs_next = fs_select_list;
716 fs_select_list = fsp;
719 /* Add FSTYPE to the list of file system types to be omitted. */
722 add_excluded_fs_type (const char *fstype)
724 struct fs_type_list *fsp;
726 fsp = xmalloc (sizeof *fsp);
727 fsp->fs_name = (char *) fstype;
728 fsp->fs_next = fs_exclude_list;
729 fs_exclude_list = fsp;
735 if (status != EXIT_SUCCESS)
736 fprintf (stderr, _("Try `%s --help' for more information.\n"),
740 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name);
742 Show information about the file system on which each FILE resides,\n\
743 or all file systems by default.\n\
747 Mandatory arguments to long options are mandatory for short options too.\n\
750 -a, --all include dummy file systems\n\
751 -B, --block-size=SIZE use SIZE-byte blocks\n\
752 -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\n\
753 -H, --si likewise, but use powers of 1000 not 1024\n\
756 -i, --inodes list inode information instead of block usage\n\
757 -k like --block-size=1K\n\
758 -l, --local limit listing to local file systems\n\
759 --no-sync do not invoke sync before getting usage info (default)\n\
762 -P, --portability use the POSIX output format\n\
763 --sync invoke sync before getting usage info\n\
764 -t, --type=TYPE limit listing to file systems of type TYPE\n\
765 -T, --print-type print file system type\n\
766 -x, --exclude-type=TYPE limit listing to file systems not of type TYPE\n\
769 fputs (HELP_OPTION_DESCRIPTION, stdout);
770 fputs (VERSION_OPTION_DESCRIPTION, stdout);
772 SIZE may be (or may be an integer optionally followed by) one of following:\n\
773 kB 1000, K 1024, MB 1000*1000, M 1024*1024, and so on for G, T, P, E, Z, Y.\n\
775 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
781 main (int argc, char **argv)
784 struct stat *stats IF_LINT (= 0);
786 initialize_main (&argc, &argv);
787 program_name = argv[0];
788 setlocale (LC_ALL, "");
789 bindtextdomain (PACKAGE, LOCALEDIR);
790 textdomain (PACKAGE);
792 atexit (close_stdout);
794 fs_select_list = NULL;
795 fs_exclude_list = NULL;
796 inode_format = false;
798 show_listed_fs = false;
800 human_output_opts = human_options (getenv ("DF_BLOCK_SIZE"), false,
804 file_systems_processed = false;
805 posix_format = false;
806 exit_status = EXIT_SUCCESS;
808 while ((c = getopt_long (argc, argv, "aB:iF:hHklmPTt:vx:", long_options, NULL))
817 human_output_opts = human_options (optarg, true, &output_block_size);
823 human_output_opts = human_autoscale | human_SI | human_base_1024;
824 output_block_size = 1;
827 human_output_opts = human_autoscale | human_SI;
828 output_block_size = 1;
830 case KILOBYTES_LONG_OPTION:
832 _("the --kilobytes option is deprecated; use -k instead"));
835 human_output_opts = 0;
836 output_block_size = 1024;
839 show_local_fs = true;
841 case 'm': /* obsolescent */
842 human_output_opts = 0;
843 output_block_size = 1024 * 1024;
855 require_sync = false;
859 /* Accept -F as a synonym for -t for compatibility with Solaris. */
861 add_fs_type (optarg);
864 case 'v': /* For SysV compatibility. */
868 add_excluded_fs_type (optarg);
871 case_GETOPT_HELP_CHAR;
872 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
875 usage (EXIT_FAILURE);
879 /* Fail if the same file system type was both selected and excluded. */
882 struct fs_type_list *fs_incl;
883 for (fs_incl = fs_select_list; fs_incl; fs_incl = fs_incl->fs_next)
885 struct fs_type_list *fs_excl;
886 for (fs_excl = fs_exclude_list; fs_excl; fs_excl = fs_excl->fs_next)
888 if (STREQ (fs_incl->fs_name, fs_excl->fs_name))
891 _("file system type %s both selected and excluded"),
892 quote (fs_incl->fs_name));
906 /* stat all the given entries to make sure they get automounted,
907 if necessary, before reading the file system table. */
908 stats = xnmalloc (argc - optind, sizeof *stats);
909 for (i = optind; i < argc; ++i)
911 if (stat (argv[i], &stats[i - optind]))
913 error (0, errno, "%s", quote (argv[i]));
914 exit_status = EXIT_FAILURE;
921 read_file_system_list ((fs_select_list != NULL
922 || fs_exclude_list != NULL
926 if (mount_list == NULL)
928 /* Couldn't read the table of mounted file systems.
929 Fail if df was invoked with no file name arguments;
930 Otherwise, merely give a warning and proceed. */
931 const char *warning = (optind < argc ? _("Warning: ") : "");
932 int status = (optind < argc ? 0 : EXIT_FAILURE);
933 error (status, errno,
934 _("%scannot read table of mounted file systems"), warning);
944 /* Display explicitly requested empty file systems. */
945 show_listed_fs = true;
947 for (i = optind; i < argc; ++i)
949 show_entry (argv[i], &stats[i - optind]);
954 if (! file_systems_processed)
955 error (EXIT_FAILURE, 0, _("no file systems processed"));