1 /* df - summarize free disk space
2 Copyright (C) 91, 1995-2009 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 GNU/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 /* If true, print a grand total at the end. */
112 static bool print_grand_total
;
114 /* Grand total data. */
115 static struct fs_usage grand_fsu
;
117 /* For long options that have no equivalent short option, use a
118 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
121 NO_SYNC_OPTION
= CHAR_MAX
+ 1,
125 static struct option
const long_options
[] =
127 {"all", no_argument
, NULL
, 'a'},
128 {"block-size", required_argument
, NULL
, 'B'},
129 {"inodes", no_argument
, NULL
, 'i'},
130 {"human-readable", no_argument
, NULL
, 'h'},
131 {"si", no_argument
, NULL
, 'H'},
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 {"total", no_argument
, NULL
, 'c'},
139 {"type", required_argument
, NULL
, 't'},
140 {"exclude-type", required_argument
, NULL
, 'x'},
141 {GETOPT_HELP_OPTION_DECL
},
142 {GETOPT_VERSION_OPTION_DECL
},
149 char buf
[MAX (LONGEST_HUMAN_READABLE
+ 1, INT_BUFSIZE_BOUND (uintmax_t))];
152 fputs (_("Filesystem Type"), stdout
);
154 fputs (_("Filesystem "), stdout
);
157 printf (_(" Inodes IUsed IFree IUse%%"));
158 else if (human_output_opts
& human_autoscale
)
160 if (human_output_opts
& human_base_1024
)
161 printf (_(" Size Used Avail Use%%"));
163 printf (_(" Size Used Avail Use%%"));
165 else if (posix_format
)
166 printf (_(" %s-blocks Used Available Capacity"),
167 umaxtostr (output_block_size
, buf
));
170 int opts
= (human_suppress_point_zero
171 | human_autoscale
| human_SI
173 & (human_group_digits
| human_base_1024
| human_B
)));
175 /* Prefer the base that makes the human-readable value more exact,
176 if there is a difference. */
178 uintmax_t q1000
= output_block_size
;
179 uintmax_t q1024
= output_block_size
;
180 bool divisible_by_1000
;
181 bool divisible_by_1024
;
185 divisible_by_1000
= q1000
% 1000 == 0; q1000
/= 1000;
186 divisible_by_1024
= q1024
% 1024 == 0; q1024
/= 1024;
188 while (divisible_by_1000
& divisible_by_1024
);
190 if (divisible_by_1000
< divisible_by_1024
)
191 opts
|= human_base_1024
;
192 if (divisible_by_1024
< divisible_by_1000
)
193 opts
&= ~human_base_1024
;
194 if (! (opts
& human_base_1024
))
197 printf (_(" %4s-blocks Used Available Use%%"),
198 human_readable (output_block_size
, buf
, opts
, 1, 1));
201 printf (_(" Mounted on\n"));
204 /* Is FSTYPE a type of file system that should be listed? */
207 selected_fstype (const char *fstype
)
209 const struct fs_type_list
*fsp
;
211 if (fs_select_list
== NULL
|| fstype
== NULL
)
213 for (fsp
= fs_select_list
; fsp
; fsp
= fsp
->fs_next
)
214 if (STREQ (fstype
, fsp
->fs_name
))
219 /* Is FSTYPE a type of file system that should be omitted? */
222 excluded_fstype (const char *fstype
)
224 const struct fs_type_list
*fsp
;
226 if (fs_exclude_list
== NULL
|| fstype
== NULL
)
228 for (fsp
= fs_exclude_list
; fsp
; fsp
= fsp
->fs_next
)
229 if (STREQ (fstype
, fsp
->fs_name
))
234 /* Return true if N is a known integer value. On many file systems,
235 UINTMAX_MAX represents an unknown value; on AIX, UINTMAX_MAX - 1
236 represents unknown. Use a rule that works on AIX file systems, and
237 that almost-always works on other types. */
239 known_value (uintmax_t n
)
241 return n
< UINTMAX_MAX
- 1;
244 /* Like human_readable (N, BUF, human_output_opts, INPUT_UNITS, OUTPUT_UNITS),
247 - If NEGATIVE, then N represents a negative number,
248 expressed in two's complement.
249 - Otherwise, return "-" if N is unknown. */
252 df_readable (bool negative
, uintmax_t n
, char *buf
,
253 uintmax_t input_units
, uintmax_t output_units
)
255 if (! known_value (n
) && !negative
)
259 char *p
= human_readable (negative
? -n
: n
, buf
+ negative
,
260 human_output_opts
, input_units
, output_units
);
267 /* Logical equivalence */
268 #define LOG_EQ(a, b) (!(a) == !(b))
270 /* Add integral value while using uintmax_t for value part and separate
271 negation flag. It adds value of SRC and SRC_NEG to DEST and DEST_NEG.
272 The result will be in DEST and DEST_NEG. See df_readable to understand
273 how the negation flag is used. */
275 add_uint_with_neg_flag (uintmax_t *dest
, bool *dest_neg
,
276 uintmax_t src
, bool src_neg
)
278 if (LOG_EQ (*dest_neg
, src_neg
))
302 /* Display a space listing for the disk device with absolute file name DISK.
303 If MOUNT_POINT is non-NULL, it is the name of the root of the
305 If STAT_FILE is non-null, it is the name of a file within the file
306 system that the user originally asked for; this provides better
307 diagnostics, and sometimes it provides better results on networked
308 file systems that give different free-space results depending on
309 where in the file system you probe.
310 If FSTYPE is non-NULL, it is the type of the file system on DISK.
311 If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may
312 not be able to produce statistics in this case.
313 ME_DUMMY and ME_REMOTE are the mount entry flags. */
316 show_dev (char const *disk
, char const *mount_point
,
317 char const *stat_file
, char const *fstype
,
318 bool me_dummy
, bool me_remote
,
319 const struct fs_usage
*force_fsu
)
322 char buf
[3][LONGEST_HUMAN_READABLE
+ 2];
324 int col1_adjustment
= 0;
326 uintmax_t input_units
;
327 uintmax_t output_units
;
330 bool negate_available
;
331 uintmax_t available_to_root
;
336 if (me_remote
& show_local_fs
)
339 if (me_dummy
& !show_all_fs
& !show_listed_fs
)
342 if (!selected_fstype (fstype
) || excluded_fstype (fstype
))
345 /* If MOUNT_POINT is NULL, then the file system is not mounted, and this
346 program reports on the file system that the special file is on.
347 It would be better to report on the unmounted file system,
348 but statfs doesn't do that on most systems. */
350 stat_file
= mount_point
? mount_point
: disk
;
354 else if (get_fs_usage (stat_file
, disk
, &fsu
))
356 error (0, errno
, "%s", quote (stat_file
));
357 exit_status
= EXIT_FAILURE
;
361 if (fsu
.fsu_blocks
== 0 && !show_all_fs
&& !show_listed_fs
)
364 if (! file_systems_processed
)
366 file_systems_processed
= true;
371 disk
= "-"; /* unknown */
373 fstype
= "-"; /* unknown */
375 /* df.c reserved 5 positions for fstype,
376 but that does not suffice for type iso9660 */
379 size_t disk_name_len
= strlen (disk
);
380 size_t fstype_len
= strlen (fstype
);
381 if (disk_name_len
+ fstype_len
< 18)
382 printf ("%s%*s ", disk
, 18 - (int) disk_name_len
, fstype
);
383 else if (!posix_format
)
384 printf ("%s\n%18s ", disk
, fstype
);
386 printf ("%s %s", disk
, fstype
);
390 if (strlen (disk
) > 20 && !posix_format
)
391 printf ("%s\n%20s", disk
, "");
393 printf ("%-20s", disk
);
400 input_units
= output_units
= 1;
401 total
= fsu
.fsu_files
;
402 available
= fsu
.fsu_ffree
;
403 negate_available
= false;
404 available_to_root
= available
;
406 if (known_value (total
))
407 grand_fsu
.fsu_files
+= total
;
408 if (known_value (available
))
409 grand_fsu
.fsu_ffree
+= available
;
413 if (human_output_opts
& human_autoscale
)
414 width
= 5 + ! (human_output_opts
& human_base_1024
);
421 col1_adjustment
= -3;
422 for (b
= output_block_size
; 9 < b
; b
/= 10)
426 use_width
= ((posix_format
427 && ! (human_output_opts
& human_autoscale
))
429 input_units
= fsu
.fsu_blocksize
;
430 output_units
= output_block_size
;
431 total
= fsu
.fsu_blocks
;
432 available
= fsu
.fsu_bavail
;
433 negate_available
= (fsu
.fsu_bavail_top_bit_set
434 & known_value (available
));
435 available_to_root
= fsu
.fsu_bfree
;
437 if (known_value (total
))
438 grand_fsu
.fsu_blocks
+= input_units
* total
;
439 if (known_value (available_to_root
))
440 grand_fsu
.fsu_bfree
+= input_units
* available_to_root
;
441 if (known_value (available
))
442 add_uint_with_neg_flag (&grand_fsu
.fsu_bavail
,
443 &grand_fsu
.fsu_bavail_top_bit_set
,
444 input_units
* available
, negate_available
);
449 if (known_value (total
) && known_value (available_to_root
))
451 used
= total
- available_to_root
;
452 negate_used
= (total
< available_to_root
);
455 printf (" %*s %*s %*s ",
456 width
+ col1_adjustment
,
457 df_readable (false, total
,
458 buf
[0], input_units
, output_units
),
459 width
, df_readable (negate_used
, used
,
460 buf
[1], input_units
, output_units
),
461 width
, df_readable (negate_available
, available
,
462 buf
[2], input_units
, output_units
));
464 if (! known_value (used
) || ! known_value (available
))
466 else if (!negate_used
467 && used
<= TYPE_MAXIMUM (uintmax_t) / 100
468 && used
+ available
!= 0
469 && (used
+ available
< used
) == negate_available
)
471 uintmax_t u100
= used
* 100;
472 uintmax_t nonroot_total
= used
+ available
;
473 pct
= u100
/ nonroot_total
+ (u100
% nonroot_total
!= 0);
477 /* The calculation cannot be done easily with integer
478 arithmetic. Fall back on floating point. This can suffer
479 from minor rounding errors, but doing it exactly requires
480 multiple precision arithmetic, and it's not worth the
482 double u
= negate_used
? - (double) - used
: used
;
483 double a
= negate_available
? - (double) - available
: available
;
484 double nonroot_total
= u
+ a
;
487 long int lipct
= pct
= u
* 100 / nonroot_total
;
490 /* Like `pct = ceil (dpct);', but avoid ceil so that
491 the math library needn't be linked. */
492 if (ipct
- 1 < pct
&& pct
<= ipct
+ 1)
493 pct
= ipct
+ (ipct
< pct
);
498 printf ("%*.0f%%", use_width
- 1, pct
);
500 printf ("%*s", use_width
, "- ");
504 #ifdef HIDE_AUTOMOUNT_PREFIX
505 /* Don't print the first directory name in MOUNT_POINT if it's an
506 artifact of an automounter. This is a bit too aggressive to be
508 if (strncmp ("/auto/", mount_point
, 6) == 0)
510 else if (strncmp ("/tmp_mnt/", mount_point
, 9) == 0)
513 printf (" %s", mount_point
);
518 /* Return the root mountpoint of the file system on which FILE exists, in
519 malloced storage. FILE_STAT should be the result of stating FILE.
520 Give a diagnostic and return NULL if unable to determine the mount point.
521 Exit if unable to restore current working directory. */
523 find_mount_point (const char *file
, const struct stat
*file_stat
)
525 struct saved_cwd cwd
;
526 struct stat last_stat
;
527 char *mp
= NULL
; /* The malloced mount point. */
529 if (save_cwd (&cwd
) != 0)
531 error (0, errno
, _("cannot get current directory"));
535 if (S_ISDIR (file_stat
->st_mode
))
536 /* FILE is a directory, so just chdir there directly. */
538 last_stat
= *file_stat
;
539 if (chdir (file
) < 0)
541 error (0, errno
, _("cannot change to directory %s"), quote (file
));
546 /* FILE is some other kind of file; use its directory. */
548 char *xdir
= dir_name (file
);
550 ASSIGN_STRDUPA (dir
, xdir
);
555 error (0, errno
, _("cannot change to directory %s"), quote (dir
));
559 if (stat (".", &last_stat
) < 0)
561 error (0, errno
, _("cannot stat current directory (now %s)"),
567 /* Now walk up FILE's parents until we find another file system or /,
568 chdiring as we go. LAST_STAT holds stat information for the last place
573 if (stat ("..", &st
) < 0)
575 error (0, errno
, _("cannot stat %s"), quote (".."));
578 if (st
.st_dev
!= last_stat
.st_dev
|| st
.st_ino
== last_stat
.st_ino
)
579 /* cwd is the mount point. */
581 if (chdir ("..") < 0)
583 error (0, errno
, _("cannot change to directory %s"), quote (".."));
589 /* Finally reached a mount point, see what it's called. */
593 /* Restore the original cwd. */
595 int save_errno
= errno
;
596 if (restore_cwd (&cwd
) != 0)
597 error (EXIT_FAILURE
, errno
,
598 _("failed to return to initial working directory"));
606 /* If DISK corresponds to a mount point, show its usage
607 and return true. Otherwise, return false. */
609 show_disk (char const *disk
)
611 struct mount_entry
const *me
;
612 struct mount_entry
const *best_match
= NULL
;
614 for (me
= mount_list
; me
; me
= me
->me_next
)
615 if (STREQ (disk
, me
->me_devname
))
620 show_dev (best_match
->me_devname
, best_match
->me_mountdir
, NULL
,
621 best_match
->me_type
, best_match
->me_dummy
,
622 best_match
->me_remote
, NULL
);
629 /* Figure out which device file or directory POINT is mounted on
630 and show its disk usage.
631 STATP must be the result of `stat (POINT, STATP)'. */
633 show_point (const char *point
, const struct stat
*statp
)
635 struct stat disk_stats
;
636 struct mount_entry
*me
;
637 struct mount_entry
const *best_match
= NULL
;
639 /* If POINT is an absolute file name, see if we can find the
640 mount point without performing any extra stat calls at all. */
643 /* Find the best match: prefer non-dummies, and then prefer the
644 last match if there are ties. */
646 for (me
= mount_list
; me
; me
= me
->me_next
)
647 if (STREQ (me
->me_mountdir
, point
) && !STREQ (me
->me_type
, "lofs")
648 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
652 /* Calculate the real absolute file name for POINT, and use that to find
653 the mount point. This avoids statting unavailable mount points,
654 which can hang df. */
657 char *resolved
= canonicalize_file_name (point
);
659 if (resolved
&& resolved
[0] == '/')
661 size_t resolved_len
= strlen (resolved
);
662 size_t best_match_len
= 0;
664 for (me
= mount_list
; me
; me
= me
->me_next
)
665 if (!STREQ (me
->me_type
, "lofs")
666 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
668 size_t len
= strlen (me
->me_mountdir
);
669 if (best_match_len
<= len
&& len
<= resolved_len
670 && (len
== 1 /* root file system */
671 || ((len
== resolved_len
|| resolved
[len
] == '/')
672 && strncmp (me
->me_mountdir
, resolved
, len
) == 0)))
675 best_match_len
= len
;
683 && (stat (best_match
->me_mountdir
, &disk_stats
) != 0
684 || disk_stats
.st_dev
!= statp
->st_dev
))
689 for (me
= mount_list
; me
; me
= me
->me_next
)
691 if (me
->me_dev
== (dev_t
) -1)
693 if (stat (me
->me_mountdir
, &disk_stats
) == 0)
694 me
->me_dev
= disk_stats
.st_dev
;
697 /* Report only I/O errors. Other errors might be
698 caused by shadowed mount points, which means POINT
699 can't possibly be on this file system. */
702 error (0, errno
, "%s", quote (me
->me_mountdir
));
703 exit_status
= EXIT_FAILURE
;
706 /* So we won't try and fail repeatedly. */
707 me
->me_dev
= (dev_t
) -2;
711 if (statp
->st_dev
== me
->me_dev
712 && !STREQ (me
->me_type
, "lofs")
713 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
715 /* Skip bogus mtab entries. */
716 if (stat (me
->me_mountdir
, &disk_stats
) != 0
717 || disk_stats
.st_dev
!= me
->me_dev
)
718 me
->me_dev
= (dev_t
) -2;
725 show_dev (best_match
->me_devname
, best_match
->me_mountdir
, point
,
726 best_match
->me_type
, best_match
->me_dummy
, best_match
->me_remote
,
730 /* We couldn't find the mount entry corresponding to POINT. Go ahead and
731 print as much info as we can; methods that require the device to be
732 present will fail at a later point. */
734 /* Find the actual mount point. */
735 char *mp
= find_mount_point (point
, statp
);
738 show_dev (NULL
, mp
, NULL
, NULL
, false, false, NULL
);
744 /* Determine what kind of node NAME is and show the disk usage
745 for it. STATP is the results of `stat' on NAME. */
748 show_entry (char const *name
, struct stat
const *statp
)
750 if ((S_ISBLK (statp
->st_mode
) || S_ISCHR (statp
->st_mode
))
754 show_point (name
, statp
);
757 /* Show all mounted file systems, except perhaps those that are of
758 an unselected type or are empty. */
761 show_all_entries (void)
763 struct mount_entry
*me
;
765 for (me
= mount_list
; me
; me
= me
->me_next
)
766 show_dev (me
->me_devname
, me
->me_mountdir
, NULL
, me
->me_type
,
767 me
->me_dummy
, me
->me_remote
, NULL
);
770 /* Add FSTYPE to the list of file system types to display. */
773 add_fs_type (const char *fstype
)
775 struct fs_type_list
*fsp
;
777 fsp
= xmalloc (sizeof *fsp
);
778 fsp
->fs_name
= (char *) fstype
;
779 fsp
->fs_next
= fs_select_list
;
780 fs_select_list
= fsp
;
783 /* Add FSTYPE to the list of file system types to be omitted. */
786 add_excluded_fs_type (const char *fstype
)
788 struct fs_type_list
*fsp
;
790 fsp
= xmalloc (sizeof *fsp
);
791 fsp
->fs_name
= (char *) fstype
;
792 fsp
->fs_next
= fs_exclude_list
;
793 fs_exclude_list
= fsp
;
799 if (status
!= EXIT_SUCCESS
)
800 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
804 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name
);
806 Show information about the file system on which each FILE resides,\n\
807 or all file systems by default.\n\
811 Mandatory arguments to long options are mandatory for short options too.\n\
814 -a, --all include dummy file systems\n\
815 -B, --block-size=SIZE use SIZE-byte blocks\n\
816 --total produce a grand total\n\
817 -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\n\
818 -H, --si likewise, but use powers of 1000 not 1024\n\
821 -i, --inodes list inode information instead of block usage\n\
822 -k like --block-size=1K\n\
823 -l, --local limit listing to local file systems\n\
824 --no-sync do not invoke sync before getting usage info (default)\n\
827 -P, --portability use the POSIX output format\n\
828 --sync invoke sync before getting usage info\n\
829 -t, --type=TYPE limit listing to file systems of type TYPE\n\
830 -T, --print-type print file system type\n\
831 -x, --exclude-type=TYPE limit listing to file systems not of type TYPE\n\
834 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
835 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
837 SIZE may be (or may be an integer optionally followed by) one of following:\n\
838 kB 1000, K 1024, MB 1000*1000, M 1024*1024, and so on for G, T, P, E, Z, Y.\n\
840 emit_bug_reporting_address ();
846 main (int argc
, char **argv
)
848 struct stat
*stats
IF_LINT (= 0);
850 initialize_main (&argc
, &argv
);
851 set_program_name (argv
[0]);
852 setlocale (LC_ALL
, "");
853 bindtextdomain (PACKAGE
, LOCALEDIR
);
854 textdomain (PACKAGE
);
856 atexit (close_stdout
);
858 fs_select_list
= NULL
;
859 fs_exclude_list
= NULL
;
860 inode_format
= false;
862 show_listed_fs
= false;
863 human_output_opts
= -1;
865 file_systems_processed
= false;
866 posix_format
= false;
867 exit_status
= EXIT_SUCCESS
;
868 print_grand_total
= false;
869 grand_fsu
.fsu_blocksize
= 1;
874 int c
= getopt_long (argc
, argv
, "aB:iF:hHklmPTt:vx:", long_options
,
886 enum strtol_error e
= human_options (optarg
, &human_output_opts
,
889 xstrtol_fatal (e
, oi
, c
, long_options
, optarg
);
896 human_output_opts
= human_autoscale
| human_SI
| human_base_1024
;
897 output_block_size
= 1;
900 human_output_opts
= human_autoscale
| human_SI
;
901 output_block_size
= 1;
904 human_output_opts
= 0;
905 output_block_size
= 1024;
908 show_local_fs
= true;
910 case 'm': /* obsolescent */
911 human_output_opts
= 0;
912 output_block_size
= 1024 * 1024;
924 require_sync
= false;
928 /* Accept -F as a synonym for -t for compatibility with Solaris. */
930 add_fs_type (optarg
);
933 case 'v': /* For SysV compatibility. */
937 add_excluded_fs_type (optarg
);
941 print_grand_total
= true;
944 case_GETOPT_HELP_CHAR
;
945 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
948 usage (EXIT_FAILURE
);
952 if (human_output_opts
== -1)
956 human_output_opts
= 0;
957 output_block_size
= (getenv ("POSIXLY_CORRECT") ? 512 : 1024);
960 human_options (getenv ("DF_BLOCK_SIZE"),
961 &human_output_opts
, &output_block_size
);
964 /* Fail if the same file system type was both selected and excluded. */
967 struct fs_type_list
*fs_incl
;
968 for (fs_incl
= fs_select_list
; fs_incl
; fs_incl
= fs_incl
->fs_next
)
970 struct fs_type_list
*fs_excl
;
971 for (fs_excl
= fs_exclude_list
; fs_excl
; fs_excl
= fs_excl
->fs_next
)
973 if (STREQ (fs_incl
->fs_name
, fs_excl
->fs_name
))
976 _("file system type %s both selected and excluded"),
977 quote (fs_incl
->fs_name
));
991 /* Open each of the given entries to make sure any corresponding
992 partition is automounted. This must be done before reading the
993 file system table. */
994 stats
= xnmalloc (argc
- optind
, sizeof *stats
);
995 for (i
= optind
; i
< argc
; ++i
)
997 int fd
= open (argv
[i
], O_RDONLY
| O_NOCTTY
);
998 if (fd
< 0 || fstat (fd
, &stats
[i
- optind
]))
1000 error (0, errno
, "%s", quote (argv
[i
]));
1001 exit_status
= EXIT_FAILURE
;
1010 read_file_system_list ((fs_select_list
!= NULL
1011 || fs_exclude_list
!= NULL
1015 if (mount_list
== NULL
)
1017 /* Couldn't read the table of mounted file systems.
1018 Fail if df was invoked with no file name arguments;
1019 Otherwise, merely give a warning and proceed. */
1020 int status
= (optind
< argc
? 0 : EXIT_FAILURE
);
1021 const char *warning
= (optind
< argc
? _("Warning: ") : "");
1022 error (status
, errno
, "%s%s", warning
,
1023 _("cannot read table of mounted file systems"));
1033 /* Display explicitly requested empty file systems. */
1034 show_listed_fs
= true;
1036 for (i
= optind
; i
< argc
; ++i
)
1038 show_entry (argv
[i
], &stats
[i
- optind
]);
1041 show_all_entries ();
1043 if (print_grand_total
)
1046 grand_fsu
.fsu_blocks
= 1;
1047 show_dev ("total", NULL
, NULL
, NULL
, false, false, &grand_fsu
);
1050 if (! file_systems_processed
)
1051 error (EXIT_FAILURE
, 0, _("no file systems processed"));