1 /* df - summarize free disk space
2 Copyright (C) 91, 1995-2008 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 3 of the License, or
7 (at your option) any later version.
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, see <http://www.gnu.org/licenses/>. */
17 /* Written by David MacKenzie <djm@gnu.ai.mit.edu>.
18 --human-readable and --megabyte options added by lm@sgi.com.
19 --si and large file support added by eggert@twinsun.com. */
23 #include <sys/types.h>
27 #include "canonicalize.h"
31 #include "mountlist.h"
36 /* The official name of this program (e.g., no `g' prefix). */
37 #define PROGRAM_NAME "df"
40 proper_name_utf8 ("Torbjorn Granlund", "Torbj\303\266rn Granlund"), \
41 proper_name ("David MacKenzie"), \
42 proper_name ("Paul Eggert")
44 /* If true, show inode information. */
45 static bool inode_format;
47 /* If true, show even file systems with zero size or
48 uninteresting types. */
49 static bool show_all_fs;
51 /* If true, show only local file systems. */
52 static bool show_local_fs;
54 /* If true, output data for each file system corresponding to a
55 command line argument -- even if it's a dummy (automounter) entry. */
56 static bool show_listed_fs;
58 /* Human-readable options for output. */
59 static int human_output_opts;
61 /* The units to use when printing sizes. */
62 static uintmax_t output_block_size;
64 /* If true, use the POSIX output format. */
65 static bool posix_format;
67 /* True if a file system has been processed for output. */
68 static bool file_systems_processed;
70 /* If true, invoke the `sync' system call before getting any usage data.
71 Using this option can make df very slow, especially with many or very
72 busy disks. Note that this may make a difference on some systems --
73 SunOS 4.1.3, for one. It is *not* necessary on Linux. */
74 static bool require_sync;
76 /* Desired exit status. */
77 static int exit_status;
79 /* A file system type to display. */
84 struct fs_type_list *fs_next;
87 /* Linked list of file system types to display.
88 If `fs_select_list' is NULL, list all types.
89 This table is generated dynamically from command-line options,
90 rather than hardcoding into the program what it thinks are the
91 valid file system types; let the user specify any file system type
92 they want to, and if there are any file systems of that type, they
95 Some file system types:
96 4.2 4.3 ufs nfs swap ignore io vm efs dbg */
98 static struct fs_type_list *fs_select_list;
100 /* Linked list of file system types to omit.
101 If the list is empty, don't exclude any types. */
103 static struct fs_type_list *fs_exclude_list;
105 /* Linked list of mounted file systems. */
106 static struct mount_entry *mount_list;
108 /* If true, print file system type as well. */
109 static bool print_type;
111 /* For long options that have no equivalent short option, use a
112 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
115 NO_SYNC_OPTION = CHAR_MAX + 1,
119 static struct option const long_options[] =
121 {"all", no_argument, NULL, 'a'},
122 {"block-size", required_argument, NULL, 'B'},
123 {"inodes", no_argument, NULL, 'i'},
124 {"human-readable", no_argument, NULL, 'h'},
125 {"si", no_argument, NULL, 'H'},
126 {"local", no_argument, NULL, 'l'},
127 {"megabytes", no_argument, NULL, 'm'}, /* obsolescent */
128 {"portability", no_argument, NULL, 'P'},
129 {"print-type", no_argument, NULL, 'T'},
130 {"sync", no_argument, NULL, SYNC_OPTION},
131 {"no-sync", no_argument, NULL, NO_SYNC_OPTION},
132 {"type", required_argument, NULL, 't'},
133 {"exclude-type", required_argument, NULL, 'x'},
134 {GETOPT_HELP_OPTION_DECL},
135 {GETOPT_VERSION_OPTION_DECL},
142 char buf[MAX (LONGEST_HUMAN_READABLE + 1, INT_BUFSIZE_BOUND (uintmax_t))];
145 fputs (_("Filesystem Type"), stdout);
147 fputs (_("Filesystem "), stdout);
150 printf (_(" Inodes IUsed IFree IUse%%"));
151 else if (human_output_opts & human_autoscale)
153 if (human_output_opts & human_base_1024)
154 printf (_(" Size Used Avail Use%%"));
156 printf (_(" Size Used Avail Use%%"));
158 else if (posix_format)
159 printf (_(" %s-blocks Used Available Capacity"),
160 umaxtostr (output_block_size, buf));
163 int opts = (human_suppress_point_zero
164 | human_autoscale | human_SI
166 & (human_group_digits | human_base_1024 | human_B)));
168 /* Prefer the base that makes the human-readable value more exact,
169 if there is a difference. */
171 uintmax_t q1000 = output_block_size;
172 uintmax_t q1024 = output_block_size;
173 bool divisible_by_1000;
174 bool divisible_by_1024;
178 divisible_by_1000 = q1000 % 1000 == 0; q1000 /= 1000;
179 divisible_by_1024 = q1024 % 1024 == 0; q1024 /= 1024;
181 while (divisible_by_1000 & divisible_by_1024);
183 if (divisible_by_1000 < divisible_by_1024)
184 opts |= human_base_1024;
185 if (divisible_by_1024 < divisible_by_1000)
186 opts &= ~human_base_1024;
187 if (! (opts & human_base_1024))
190 printf (_(" %4s-blocks Used Available Use%%"),
191 human_readable (output_block_size, buf, opts, 1, 1));
194 printf (_(" Mounted on\n"));
197 /* Is FSTYPE a type of file system that should be listed? */
200 selected_fstype (const char *fstype)
202 const struct fs_type_list *fsp;
204 if (fs_select_list == NULL || fstype == NULL)
206 for (fsp = fs_select_list; fsp; fsp = fsp->fs_next)
207 if (STREQ (fstype, fsp->fs_name))
212 /* Is FSTYPE a type of file system that should be omitted? */
215 excluded_fstype (const char *fstype)
217 const struct fs_type_list *fsp;
219 if (fs_exclude_list == NULL || fstype == NULL)
221 for (fsp = fs_exclude_list; fsp; fsp = fsp->fs_next)
222 if (STREQ (fstype, fsp->fs_name))
227 /* Like human_readable (N, BUF, human_output_opts, INPUT_UNITS, OUTPUT_UNITS),
230 - If NEGATIVE, then N represents a negative number,
231 expressed in two's complement.
232 - Otherwise, return "-" if N is UINTMAX_MAX. */
235 df_readable (bool negative, uintmax_t n, char *buf,
236 uintmax_t input_units, uintmax_t output_units)
238 if (n == UINTMAX_MAX && !negative)
242 char *p = human_readable (negative ? -n : n, buf + negative,
243 human_output_opts, input_units, output_units);
250 /* Display a space listing for the disk device with absolute file name DISK.
251 If MOUNT_POINT is non-NULL, it is the name of the root of the
253 If STAT_FILE is non-null, it is the name of a file within the file
254 system that the user originally asked for; this provides better
255 diagnostics, and sometimes it provides better results on networked
256 file systems that give different free-space results depending on
257 where in the file system you probe.
258 If FSTYPE is non-NULL, it is the type of the file system on DISK.
259 If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may
260 not be able to produce statistics in this case.
261 ME_DUMMY and ME_REMOTE are the mount entry flags. */
264 show_dev (char const *disk, char const *mount_point,
265 char const *stat_file, char const *fstype,
266 bool me_dummy, bool me_remote)
269 char buf[3][LONGEST_HUMAN_READABLE + 2];
271 int col1_adjustment = 0;
273 uintmax_t input_units;
274 uintmax_t output_units;
277 bool negate_available;
278 uintmax_t available_to_root;
283 if (me_remote & show_local_fs)
286 if (me_dummy & !show_all_fs & !show_listed_fs)
289 if (!selected_fstype (fstype) || excluded_fstype (fstype))
292 /* If MOUNT_POINT is NULL, then the file system is not mounted, and this
293 program reports on the file system that the special file is on.
294 It would be better to report on the unmounted file system,
295 but statfs doesn't do that on most systems. */
297 stat_file = mount_point ? mount_point : disk;
299 if (get_fs_usage (stat_file, disk, &fsu))
301 error (0, errno, "%s", quote (stat_file));
302 exit_status = EXIT_FAILURE;
306 if (fsu.fsu_blocks == 0 && !show_all_fs && !show_listed_fs)
309 if (! file_systems_processed)
311 file_systems_processed = true;
316 disk = "-"; /* unknown */
318 fstype = "-"; /* unknown */
320 /* df.c reserved 5 positions for fstype,
321 but that does not suffice for type iso9660 */
324 size_t disk_name_len = strlen (disk);
325 size_t fstype_len = strlen (fstype);
326 if (disk_name_len + fstype_len < 18)
327 printf ("%s%*s ", disk, 18 - (int) disk_name_len, fstype);
328 else if (!posix_format)
329 printf ("%s\n%18s ", disk, fstype);
331 printf ("%s %s", disk, fstype);
335 if (strlen (disk) > 20 && !posix_format)
336 printf ("%s\n%20s", disk, "");
338 printf ("%-20s", disk);
345 input_units = output_units = 1;
346 total = fsu.fsu_files;
347 available = fsu.fsu_ffree;
348 negate_available = false;
349 available_to_root = available;
353 if (human_output_opts & human_autoscale)
354 width = 5 + ! (human_output_opts & human_base_1024);
361 col1_adjustment = -3;
362 for (b = output_block_size; 9 < b; b /= 10)
366 use_width = ((posix_format
367 && ! (human_output_opts & human_autoscale))
369 input_units = fsu.fsu_blocksize;
370 output_units = output_block_size;
371 total = fsu.fsu_blocks;
372 available = fsu.fsu_bavail;
373 negate_available = (fsu.fsu_bavail_top_bit_set
374 & (available != UINTMAX_MAX));
375 available_to_root = fsu.fsu_bfree;
380 if (total != UINTMAX_MAX && available_to_root != UINTMAX_MAX)
382 used = total - available_to_root;
383 negate_used = (total < available_to_root);
386 printf (" %*s %*s %*s ",
387 width + col1_adjustment,
388 df_readable (false, total,
389 buf[0], input_units, output_units),
390 width, df_readable (negate_used, used,
391 buf[1], input_units, output_units),
392 width, df_readable (negate_available, available,
393 buf[2], input_units, output_units));
395 if (used == UINTMAX_MAX || available == UINTMAX_MAX)
397 else if (!negate_used
398 && used <= TYPE_MAXIMUM (uintmax_t) / 100
399 && used + available != 0
400 && (used + available < used) == negate_available)
402 uintmax_t u100 = used * 100;
403 uintmax_t nonroot_total = used + available;
404 pct = u100 / nonroot_total + (u100 % nonroot_total != 0);
408 /* The calculation cannot be done easily with integer
409 arithmetic. Fall back on floating point. This can suffer
410 from minor rounding errors, but doing it exactly requires
411 multiple precision arithmetic, and it's not worth the
413 double u = negate_used ? - (double) - used : used;
414 double a = negate_available ? - (double) - available : available;
415 double nonroot_total = u + a;
418 long int lipct = pct = u * 100 / nonroot_total;
421 /* Like `pct = ceil (dpct);', but avoid ceil so that
422 the math library needn't be linked. */
423 if (ipct - 1 < pct && pct <= ipct + 1)
424 pct = ipct + (ipct < pct);
429 printf ("%*.0f%%", use_width - 1, pct);
431 printf ("%*s", use_width, "- ");
435 #ifdef HIDE_AUTOMOUNT_PREFIX
436 /* Don't print the first directory name in MOUNT_POINT if it's an
437 artifact of an automounter. This is a bit too aggressive to be
439 if (strncmp ("/auto/", mount_point, 6) == 0)
441 else if (strncmp ("/tmp_mnt/", mount_point, 9) == 0)
444 printf (" %s", mount_point);
449 /* Return the root mountpoint of the file system on which FILE exists, in
450 malloced storage. FILE_STAT should be the result of stating FILE.
451 Give a diagnostic and return NULL if unable to determine the mount point.
452 Exit if unable to restore current working directory. */
454 find_mount_point (const char *file, const struct stat *file_stat)
456 struct saved_cwd cwd;
457 struct stat last_stat;
458 char *mp = NULL; /* The malloced mount point. */
460 if (save_cwd (&cwd) != 0)
462 error (0, errno, _("cannot get current directory"));
466 if (S_ISDIR (file_stat->st_mode))
467 /* FILE is a directory, so just chdir there directly. */
469 last_stat = *file_stat;
470 if (chdir (file) < 0)
472 error (0, errno, _("cannot change to directory %s"), quote (file));
477 /* FILE is some other kind of file; use its directory. */
479 char *xdir = dir_name (file);
481 ASSIGN_STRDUPA (dir, xdir);
486 error (0, errno, _("cannot change to directory %s"), quote (dir));
490 if (stat (".", &last_stat) < 0)
492 error (0, errno, _("cannot stat current directory (now %s)"),
498 /* Now walk up FILE's parents until we find another file system or /,
499 chdiring as we go. LAST_STAT holds stat information for the last place
504 if (stat ("..", &st) < 0)
506 error (0, errno, _("cannot stat %s"), quote (".."));
509 if (st.st_dev != last_stat.st_dev || st.st_ino == last_stat.st_ino)
510 /* cwd is the mount point. */
512 if (chdir ("..") < 0)
514 error (0, errno, _("cannot change to directory %s"), quote (".."));
520 /* Finally reached a mount point, see what it's called. */
524 /* Restore the original cwd. */
526 int save_errno = errno;
527 if (restore_cwd (&cwd) != 0)
528 error (EXIT_FAILURE, errno,
529 _("failed to return to initial working directory"));
537 /* If DISK corresponds to a mount point, show its usage
538 and return true. Otherwise, return false. */
540 show_disk (char const *disk)
542 struct mount_entry const *me;
543 struct mount_entry const *best_match = NULL;
545 for (me = mount_list; me; me = me->me_next)
546 if (STREQ (disk, me->me_devname))
551 show_dev (best_match->me_devname, best_match->me_mountdir, NULL,
552 best_match->me_type, best_match->me_dummy,
553 best_match->me_remote);
560 /* Figure out which device file or directory POINT is mounted on
561 and show its disk usage.
562 STATP must be the result of `stat (POINT, STATP)'. */
564 show_point (const char *point, const struct stat *statp)
566 struct stat disk_stats;
567 struct mount_entry *me;
568 struct mount_entry const *best_match = NULL;
570 /* If POINT is an absolute file name, see if we can find the
571 mount point without performing any extra stat calls at all. */
574 /* Find the best match: prefer non-dummies, and then prefer the
575 last match if there are ties. */
577 for (me = mount_list; me; me = me->me_next)
578 if (STREQ (me->me_mountdir, point) && !STREQ (me->me_type, "lofs")
579 && (!best_match || best_match->me_dummy || !me->me_dummy))
583 /* Calculate the real absolute file name for POINT, and use that to find
584 the mount point. This avoids statting unavailable mount points,
585 which can hang df. */
588 char *resolved = canonicalize_file_name (point);
590 if (resolved && resolved[0] == '/')
592 size_t resolved_len = strlen (resolved);
593 size_t best_match_len = 0;
595 for (me = mount_list; me; me = me->me_next)
596 if (!STREQ (me->me_type, "lofs")
597 && (!best_match || best_match->me_dummy || !me->me_dummy))
599 size_t len = strlen (me->me_mountdir);
600 if (best_match_len <= len && len <= resolved_len
601 && (len == 1 /* root file system */
602 || ((len == resolved_len || resolved[len] == '/')
603 && strncmp (me->me_mountdir, resolved, len) == 0)))
606 best_match_len = len;
614 && (stat (best_match->me_mountdir, &disk_stats) != 0
615 || disk_stats.st_dev != statp->st_dev))
620 for (me = mount_list; me; me = me->me_next)
622 if (me->me_dev == (dev_t) -1)
624 if (stat (me->me_mountdir, &disk_stats) == 0)
625 me->me_dev = disk_stats.st_dev;
628 /* Report only I/O errors. Other errors might be
629 caused by shadowed mount points, which means POINT
630 can't possibly be on this file system. */
633 error (0, errno, "%s", quote (me->me_mountdir));
634 exit_status = EXIT_FAILURE;
637 /* So we won't try and fail repeatedly. */
638 me->me_dev = (dev_t) -2;
642 if (statp->st_dev == me->me_dev
643 && !STREQ (me->me_type, "lofs")
644 && (!best_match || best_match->me_dummy || !me->me_dummy))
646 /* Skip bogus mtab entries. */
647 if (stat (me->me_mountdir, &disk_stats) != 0
648 || disk_stats.st_dev != me->me_dev)
649 me->me_dev = (dev_t) -2;
656 show_dev (best_match->me_devname, best_match->me_mountdir, point,
657 best_match->me_type, best_match->me_dummy, best_match->me_remote);
660 /* We couldn't find the mount entry corresponding to POINT. Go ahead and
661 print as much info as we can; methods that require the device to be
662 present will fail at a later point. */
664 /* Find the actual mount point. */
665 char *mp = find_mount_point (point, statp);
668 show_dev (NULL, mp, NULL, NULL, false, false);
674 /* Determine what kind of node NAME is and show the disk usage
675 for it. STATP is the results of `stat' on NAME. */
678 show_entry (char const *name, struct stat const *statp)
680 if ((S_ISBLK (statp->st_mode) || S_ISCHR (statp->st_mode))
684 show_point (name, statp);
687 /* Show all mounted file systems, except perhaps those that are of
688 an unselected type or are empty. */
691 show_all_entries (void)
693 struct mount_entry *me;
695 for (me = mount_list; me; me = me->me_next)
696 show_dev (me->me_devname, me->me_mountdir, NULL, me->me_type,
697 me->me_dummy, me->me_remote);
700 /* Add FSTYPE to the list of file system types to display. */
703 add_fs_type (const char *fstype)
705 struct fs_type_list *fsp;
707 fsp = xmalloc (sizeof *fsp);
708 fsp->fs_name = (char *) fstype;
709 fsp->fs_next = fs_select_list;
710 fs_select_list = fsp;
713 /* Add FSTYPE to the list of file system types to be omitted. */
716 add_excluded_fs_type (const char *fstype)
718 struct fs_type_list *fsp;
720 fsp = xmalloc (sizeof *fsp);
721 fsp->fs_name = (char *) fstype;
722 fsp->fs_next = fs_exclude_list;
723 fs_exclude_list = fsp;
729 if (status != EXIT_SUCCESS)
730 fprintf (stderr, _("Try `%s --help' for more information.\n"),
734 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name);
736 Show information about the file system on which each FILE resides,\n\
737 or all file systems by default.\n\
741 Mandatory arguments to long options are mandatory for short options too.\n\
744 -a, --all include dummy file systems\n\
745 -B, --block-size=SIZE use SIZE-byte blocks\n\
746 -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\n\
747 -H, --si likewise, but use powers of 1000 not 1024\n\
750 -i, --inodes list inode information instead of block usage\n\
751 -k like --block-size=1K\n\
752 -l, --local limit listing to local file systems\n\
753 --no-sync do not invoke sync before getting usage info (default)\n\
756 -P, --portability use the POSIX output format\n\
757 --sync invoke sync before getting usage info\n\
758 -t, --type=TYPE limit listing to file systems of type TYPE\n\
759 -T, --print-type print file system type\n\
760 -x, --exclude-type=TYPE limit listing to file systems not of type TYPE\n\
763 fputs (HELP_OPTION_DESCRIPTION, stdout);
764 fputs (VERSION_OPTION_DESCRIPTION, stdout);
766 SIZE may be (or may be an integer optionally followed by) one of following:\n\
767 kB 1000, K 1024, MB 1000*1000, M 1024*1024, and so on for G, T, P, E, Z, Y.\n\
769 emit_bug_reporting_address ();
775 main (int argc, char **argv)
777 struct stat *stats IF_LINT (= 0);
779 initialize_main (&argc, &argv);
780 set_program_name (argv[0]);
781 setlocale (LC_ALL, "");
782 bindtextdomain (PACKAGE, LOCALEDIR);
783 textdomain (PACKAGE);
785 atexit (close_stdout);
787 fs_select_list = NULL;
788 fs_exclude_list = NULL;
789 inode_format = false;
791 show_listed_fs = false;
792 human_output_opts = -1;
794 file_systems_processed = false;
795 posix_format = false;
796 exit_status = EXIT_SUCCESS;
801 int c = getopt_long (argc, argv, "aB:iF:hHklmPTt:vx:", long_options,
813 enum strtol_error e = human_options (optarg, &human_output_opts,
816 xstrtol_fatal (e, oi, c, long_options, optarg);
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;
831 human_output_opts = 0;
832 output_block_size = 1024;
835 show_local_fs = true;
837 case 'm': /* obsolescent */
838 human_output_opts = 0;
839 output_block_size = 1024 * 1024;
851 require_sync = false;
855 /* Accept -F as a synonym for -t for compatibility with Solaris. */
857 add_fs_type (optarg);
860 case 'v': /* For SysV compatibility. */
864 add_excluded_fs_type (optarg);
867 case_GETOPT_HELP_CHAR;
868 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
871 usage (EXIT_FAILURE);
875 if (human_output_opts == -1)
879 human_output_opts = 0;
880 output_block_size = (getenv ("POSIXLY_CORRECT") ? 512 : 1024);
883 human_options (getenv ("DF_BLOCK_SIZE"),
884 &human_output_opts, &output_block_size);
887 /* Fail if the same file system type was both selected and excluded. */
890 struct fs_type_list *fs_incl;
891 for (fs_incl = fs_select_list; fs_incl; fs_incl = fs_incl->fs_next)
893 struct fs_type_list *fs_excl;
894 for (fs_excl = fs_exclude_list; fs_excl; fs_excl = fs_excl->fs_next)
896 if (STREQ (fs_incl->fs_name, fs_excl->fs_name))
899 _("file system type %s both selected and excluded"),
900 quote (fs_incl->fs_name));
914 /* stat all the given entries to make sure they get automounted,
915 if necessary, before reading the file system table. */
916 stats = xnmalloc (argc - optind, sizeof *stats);
917 for (i = optind; i < argc; ++i)
919 if (stat (argv[i], &stats[i - optind]))
921 error (0, errno, "%s", quote (argv[i]));
922 exit_status = EXIT_FAILURE;
929 read_file_system_list ((fs_select_list != NULL
930 || fs_exclude_list != NULL
934 if (mount_list == NULL)
936 /* Couldn't read the table of mounted file systems.
937 Fail if df was invoked with no file name arguments;
938 Otherwise, merely give a warning and proceed. */
939 int status = (optind < argc ? 0 : EXIT_FAILURE);
940 const char *warning = (optind < argc ? _("Warning: ") : "");
941 error (status, errno, "%s%s", warning,
942 _("cannot read table of mounted file systems"));
952 /* Display explicitly requested empty file systems. */
953 show_listed_fs = true;
955 for (i = optind; i < argc; ++i)
957 show_entry (argv[i], &stats[i - optind]);
962 if (! file_systems_processed)
963 error (EXIT_FAILURE, 0, _("no file systems processed"));