1 /* df - summarize free disk space
2 Copyright (C) 1991, 1995-2010 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>
30 #include "mountlist.h"
32 #include "find-mount-point.h"
34 /* The official name of this program (e.g., no `g' prefix). */
35 #define PROGRAM_NAME "df"
38 proper_name_utf8 ("Torbjorn Granlund", "Torbj\303\266rn Granlund"), \
39 proper_name ("David MacKenzie"), \
40 proper_name ("Paul Eggert")
42 /* If true, show inode information. */
43 static bool inode_format
;
45 /* If true, show even file systems with zero size or
46 uninteresting types. */
47 static bool show_all_fs
;
49 /* If true, show only local file systems. */
50 static bool show_local_fs
;
52 /* If true, output data for each file system corresponding to a
53 command line argument -- even if it's a dummy (automounter) entry. */
54 static bool show_listed_fs
;
56 /* Human-readable options for output. */
57 static int human_output_opts
;
59 /* The units to use when printing sizes. */
60 static uintmax_t output_block_size
;
62 /* If true, use the POSIX output format. */
63 static bool posix_format
;
65 /* True if a file system has been processed for output. */
66 static bool file_systems_processed
;
68 /* If true, invoke the `sync' system call before getting any usage data.
69 Using this option can make df very slow, especially with many or very
70 busy disks. Note that this may make a difference on some systems --
71 SunOS 4.1.3, for one. It is *not* necessary on GNU/Linux. */
72 static bool require_sync
;
74 /* Desired exit status. */
75 static int exit_status
;
77 /* A file system type to display. */
82 struct fs_type_list
*fs_next
;
85 /* Linked list of file system types to display.
86 If `fs_select_list' is NULL, list all types.
87 This table is generated dynamically from command-line options,
88 rather than hardcoding into the program what it thinks are the
89 valid file system types; let the user specify any file system type
90 they want to, and if there are any file systems of that type, they
93 Some file system types:
94 4.2 4.3 ufs nfs swap ignore io vm efs dbg */
96 static struct fs_type_list
*fs_select_list
;
98 /* Linked list of file system types to omit.
99 If the list is empty, don't exclude any types. */
101 static struct fs_type_list
*fs_exclude_list
;
103 /* Linked list of mounted file systems. */
104 static struct mount_entry
*mount_list
;
106 /* If true, print file system type as well. */
107 static bool print_type
;
109 /* If true, print a grand total at the end. */
110 static bool print_grand_total
;
112 /* Grand total data. */
113 static struct fs_usage grand_fsu
;
115 /* For long options that have no equivalent short option, use a
116 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
119 NO_SYNC_OPTION
= CHAR_MAX
+ 1,
123 static struct option
const long_options
[] =
125 {"all", no_argument
, NULL
, 'a'},
126 {"block-size", required_argument
, NULL
, 'B'},
127 {"inodes", no_argument
, NULL
, 'i'},
128 {"human-readable", no_argument
, NULL
, 'h'},
129 {"si", no_argument
, NULL
, 'H'},
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 {"total", no_argument
, NULL
, 'c'},
137 {"type", required_argument
, NULL
, 't'},
138 {"exclude-type", required_argument
, NULL
, 'x'},
139 {GETOPT_HELP_OPTION_DECL
},
140 {GETOPT_VERSION_OPTION_DECL
},
147 char buf
[MAX (LONGEST_HUMAN_READABLE
+ 1, INT_BUFSIZE_BOUND (uintmax_t))];
151 For best results (df header/column alignment), ensure that
152 your translation has the same length as the original. */
153 fputs (_("Filesystem Type"), stdout
);
155 fputs (_("Filesystem "), stdout
);
159 For best results (df header/column alignment), ensure that
160 your translation has the same length as the original.
161 Also, each column name translation should end at the same
162 column as the corresponding original. */
163 fputs (_(" Inodes IUsed IFree IUse%"), stdout
);
164 else if (human_output_opts
& human_autoscale
)
166 if (human_output_opts
& human_base_1024
)
167 fputs (_(" Size Used Avail Use%"), stdout
);
169 fputs (_(" Size Used Avail Use%"), stdout
);
171 else if (posix_format
)
172 printf (_(" %s-blocks Used Available Capacity"),
173 umaxtostr (output_block_size
, buf
));
176 int opts
= (human_suppress_point_zero
177 | human_autoscale
| human_SI
179 & (human_group_digits
| human_base_1024
| human_B
)));
181 /* Prefer the base that makes the human-readable value more exact,
182 if there is a difference. */
184 uintmax_t q1000
= output_block_size
;
185 uintmax_t q1024
= output_block_size
;
186 bool divisible_by_1000
;
187 bool divisible_by_1024
;
191 divisible_by_1000
= q1000
% 1000 == 0; q1000
/= 1000;
192 divisible_by_1024
= q1024
% 1024 == 0; q1024
/= 1024;
194 while (divisible_by_1000
& divisible_by_1024
);
196 if (divisible_by_1000
< divisible_by_1024
)
197 opts
|= human_base_1024
;
198 if (divisible_by_1024
< divisible_by_1000
)
199 opts
&= ~human_base_1024
;
200 if (! (opts
& human_base_1024
))
203 printf (_(" %4s-blocks Used Available Use%%"),
204 human_readable (output_block_size
, buf
, opts
, 1, 1));
207 fputs (_(" Mounted on\n"), stdout
);
210 /* Is FSTYPE a type of file system that should be listed? */
213 selected_fstype (const char *fstype
)
215 const struct fs_type_list
*fsp
;
217 if (fs_select_list
== NULL
|| fstype
== NULL
)
219 for (fsp
= fs_select_list
; fsp
; fsp
= fsp
->fs_next
)
220 if (STREQ (fstype
, fsp
->fs_name
))
225 /* Is FSTYPE a type of file system that should be omitted? */
228 excluded_fstype (const char *fstype
)
230 const struct fs_type_list
*fsp
;
232 if (fs_exclude_list
== NULL
|| fstype
== NULL
)
234 for (fsp
= fs_exclude_list
; fsp
; fsp
= fsp
->fs_next
)
235 if (STREQ (fstype
, fsp
->fs_name
))
240 /* Return true if N is a known integer value. On many file systems,
241 UINTMAX_MAX represents an unknown value; on AIX, UINTMAX_MAX - 1
242 represents unknown. Use a rule that works on AIX file systems, and
243 that almost-always works on other types. */
245 known_value (uintmax_t n
)
247 return n
< UINTMAX_MAX
- 1;
250 /* Like human_readable (N, BUF, human_output_opts, INPUT_UNITS, OUTPUT_UNITS),
253 - If NEGATIVE, then N represents a negative number,
254 expressed in two's complement.
255 - Otherwise, return "-" if N is unknown. */
258 df_readable (bool negative
, uintmax_t n
, char *buf
,
259 uintmax_t input_units
, uintmax_t output_units
)
261 if (! known_value (n
) && !negative
)
265 char *p
= human_readable (negative
? -n
: n
, buf
+ negative
,
266 human_output_opts
, input_units
, output_units
);
273 /* Logical equivalence */
274 #define LOG_EQ(a, b) (!(a) == !(b))
276 /* Add integral value while using uintmax_t for value part and separate
277 negation flag. It adds value of SRC and SRC_NEG to DEST and DEST_NEG.
278 The result will be in DEST and DEST_NEG. See df_readable to understand
279 how the negation flag is used. */
281 add_uint_with_neg_flag (uintmax_t *dest
, bool *dest_neg
,
282 uintmax_t src
, bool src_neg
)
284 if (LOG_EQ (*dest_neg
, src_neg
))
308 /* Display a space listing for the disk device with absolute file name DISK.
309 If MOUNT_POINT is non-NULL, it is the name of the root of the
311 If STAT_FILE is non-null, it is the name of a file within the file
312 system that the user originally asked for; this provides better
313 diagnostics, and sometimes it provides better results on networked
314 file systems that give different free-space results depending on
315 where in the file system you probe.
316 If FSTYPE is non-NULL, it is the type of the file system on DISK.
317 If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may
318 not be able to produce statistics in this case.
319 ME_DUMMY and ME_REMOTE are the mount entry flags. */
322 show_dev (char const *disk
, char const *mount_point
,
323 char const *stat_file
, char const *fstype
,
324 bool me_dummy
, bool me_remote
,
325 const struct fs_usage
*force_fsu
)
328 char buf
[3][LONGEST_HUMAN_READABLE
+ 2];
330 int col1_adjustment
= 0;
332 uintmax_t input_units
;
333 uintmax_t output_units
;
336 bool negate_available
;
337 uintmax_t available_to_root
;
342 if (me_remote
&& show_local_fs
)
345 if (me_dummy
&& !show_all_fs
&& !show_listed_fs
)
348 if (!selected_fstype (fstype
) || excluded_fstype (fstype
))
351 /* If MOUNT_POINT is NULL, then the file system is not mounted, and this
352 program reports on the file system that the special file is on.
353 It would be better to report on the unmounted file system,
354 but statfs doesn't do that on most systems. */
356 stat_file
= mount_point
? mount_point
: disk
;
360 else if (get_fs_usage (stat_file
, disk
, &fsu
))
362 error (0, errno
, "%s", quote (stat_file
));
363 exit_status
= EXIT_FAILURE
;
367 if (fsu
.fsu_blocks
== 0 && !show_all_fs
&& !show_listed_fs
)
370 if (! file_systems_processed
)
372 file_systems_processed
= true;
377 disk
= "-"; /* unknown */
379 fstype
= "-"; /* unknown */
381 /* df.c reserved 5 positions for fstype,
382 but that does not suffice for type iso9660 */
385 size_t disk_name_len
= strlen (disk
);
386 size_t fstype_len
= strlen (fstype
);
387 if (disk_name_len
+ fstype_len
< 18)
388 printf ("%s%*s ", disk
, 18 - (int) disk_name_len
, fstype
);
389 else if (!posix_format
)
390 printf ("%s\n%18s ", disk
, fstype
);
392 printf ("%s %s", disk
, fstype
);
396 if (strlen (disk
) > 20 && !posix_format
)
397 printf ("%s\n%20s", disk
, "");
399 printf ("%-20s", disk
);
406 input_units
= output_units
= 1;
407 total
= fsu
.fsu_files
;
408 available
= fsu
.fsu_ffree
;
409 negate_available
= false;
410 available_to_root
= available
;
412 if (known_value (total
))
413 grand_fsu
.fsu_files
+= total
;
414 if (known_value (available
))
415 grand_fsu
.fsu_ffree
+= available
;
419 if (human_output_opts
& human_autoscale
)
420 width
= 5 + ! (human_output_opts
& human_base_1024
);
427 col1_adjustment
= -3;
428 for (b
= output_block_size
; 9 < b
; b
/= 10)
432 use_width
= ((posix_format
433 && ! (human_output_opts
& human_autoscale
))
435 input_units
= fsu
.fsu_blocksize
;
436 output_units
= output_block_size
;
437 total
= fsu
.fsu_blocks
;
438 available
= fsu
.fsu_bavail
;
439 negate_available
= (fsu
.fsu_bavail_top_bit_set
440 && known_value (available
));
441 available_to_root
= fsu
.fsu_bfree
;
443 if (known_value (total
))
444 grand_fsu
.fsu_blocks
+= input_units
* total
;
445 if (known_value (available_to_root
))
446 grand_fsu
.fsu_bfree
+= input_units
* available_to_root
;
447 if (known_value (available
))
448 add_uint_with_neg_flag (&grand_fsu
.fsu_bavail
,
449 &grand_fsu
.fsu_bavail_top_bit_set
,
450 input_units
* available
, negate_available
);
455 if (known_value (total
) && known_value (available_to_root
))
457 used
= total
- available_to_root
;
458 negate_used
= (total
< available_to_root
);
461 printf (" %*s %*s %*s ",
462 width
+ col1_adjustment
,
463 df_readable (false, total
,
464 buf
[0], input_units
, output_units
),
465 width
, df_readable (negate_used
, used
,
466 buf
[1], input_units
, output_units
),
467 width
, df_readable (negate_available
, available
,
468 buf
[2], input_units
, output_units
));
470 if (! known_value (used
) || ! known_value (available
))
472 else if (!negate_used
473 && used
<= TYPE_MAXIMUM (uintmax_t) / 100
474 && used
+ available
!= 0
475 && (used
+ available
< used
) == negate_available
)
477 uintmax_t u100
= used
* 100;
478 uintmax_t nonroot_total
= used
+ available
;
479 pct
= u100
/ nonroot_total
+ (u100
% nonroot_total
!= 0);
483 /* The calculation cannot be done easily with integer
484 arithmetic. Fall back on floating point. This can suffer
485 from minor rounding errors, but doing it exactly requires
486 multiple precision arithmetic, and it's not worth the
488 double u
= negate_used
? - (double) - used
: used
;
489 double a
= negate_available
? - (double) - available
: available
;
490 double nonroot_total
= u
+ a
;
493 long int lipct
= pct
= u
* 100 / nonroot_total
;
496 /* Like `pct = ceil (dpct);', but avoid ceil so that
497 the math library needn't be linked. */
498 if (ipct
- 1 < pct
&& pct
<= ipct
+ 1)
499 pct
= ipct
+ (ipct
< pct
);
504 printf ("%*.0f%%", use_width
- 1, pct
);
506 printf ("%*s", use_width
, "- ");
510 #ifdef HIDE_AUTOMOUNT_PREFIX
511 /* Don't print the first directory name in MOUNT_POINT if it's an
512 artifact of an automounter. This is a bit too aggressive to be
514 if (strncmp ("/auto/", mount_point
, 6) == 0)
516 else if (strncmp ("/tmp_mnt/", mount_point
, 9) == 0)
519 printf (" %s", mount_point
);
524 /* If DISK corresponds to a mount point, show its usage
525 and return true. Otherwise, return false. */
527 show_disk (char const *disk
)
529 struct mount_entry
const *me
;
530 struct mount_entry
const *best_match
= NULL
;
532 for (me
= mount_list
; me
; me
= me
->me_next
)
533 if (STREQ (disk
, me
->me_devname
))
538 show_dev (best_match
->me_devname
, best_match
->me_mountdir
, NULL
,
539 best_match
->me_type
, best_match
->me_dummy
,
540 best_match
->me_remote
, NULL
);
547 /* Figure out which device file or directory POINT is mounted on
548 and show its disk usage.
549 STATP must be the result of `stat (POINT, STATP)'. */
551 show_point (const char *point
, const struct stat
*statp
)
553 struct stat disk_stats
;
554 struct mount_entry
*me
;
555 struct mount_entry
const *best_match
= NULL
;
557 /* Calculate the real absolute file name for POINT, and use that to find
558 the mount point. This avoids statting unavailable mount points,
559 which can hang df. */
560 char *resolved
= canonicalize_file_name (point
);
561 if (resolved
&& resolved
[0] == '/')
563 size_t resolved_len
= strlen (resolved
);
564 size_t best_match_len
= 0;
566 for (me
= mount_list
; me
; me
= me
->me_next
)
567 if (!STREQ (me
->me_type
, "lofs")
568 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
570 size_t len
= strlen (me
->me_mountdir
);
571 if (best_match_len
<= len
&& len
<= resolved_len
572 && (len
== 1 /* root file system */
573 || ((len
== resolved_len
|| resolved
[len
] == '/')
574 && strncmp (me
->me_mountdir
, resolved
, len
) == 0)))
577 best_match_len
= len
;
583 && (stat (best_match
->me_mountdir
, &disk_stats
) != 0
584 || disk_stats
.st_dev
!= statp
->st_dev
))
588 for (me
= mount_list
; me
; me
= me
->me_next
)
590 if (me
->me_dev
== (dev_t
) -1)
592 if (stat (me
->me_mountdir
, &disk_stats
) == 0)
593 me
->me_dev
= disk_stats
.st_dev
;
596 /* Report only I/O errors. Other errors might be
597 caused by shadowed mount points, which means POINT
598 can't possibly be on this file system. */
601 error (0, errno
, "%s", quote (me
->me_mountdir
));
602 exit_status
= EXIT_FAILURE
;
605 /* So we won't try and fail repeatedly. */
606 me
->me_dev
= (dev_t
) -2;
610 if (statp
->st_dev
== me
->me_dev
611 && !STREQ (me
->me_type
, "lofs")
612 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
614 /* Skip bogus mtab entries. */
615 if (stat (me
->me_mountdir
, &disk_stats
) != 0
616 || disk_stats
.st_dev
!= me
->me_dev
)
617 me
->me_dev
= (dev_t
) -2;
624 show_dev (best_match
->me_devname
, best_match
->me_mountdir
, point
,
625 best_match
->me_type
, best_match
->me_dummy
, best_match
->me_remote
,
629 /* We couldn't find the mount entry corresponding to POINT. Go ahead and
630 print as much info as we can; methods that require the device to be
631 present will fail at a later point. */
633 /* Find the actual mount point. */
634 char *mp
= find_mount_point (point
, statp
);
637 show_dev (NULL
, mp
, NULL
, NULL
, false, false, NULL
);
643 /* Determine what kind of node NAME is and show the disk usage
644 for it. STATP is the results of `stat' on NAME. */
647 show_entry (char const *name
, struct stat
const *statp
)
649 if ((S_ISBLK (statp
->st_mode
) || S_ISCHR (statp
->st_mode
))
653 show_point (name
, statp
);
656 /* Show all mounted file systems, except perhaps those that are of
657 an unselected type or are empty. */
660 show_all_entries (void)
662 struct mount_entry
*me
;
664 for (me
= mount_list
; me
; me
= me
->me_next
)
665 show_dev (me
->me_devname
, me
->me_mountdir
, NULL
, me
->me_type
,
666 me
->me_dummy
, me
->me_remote
, NULL
);
669 /* Add FSTYPE to the list of file system types to display. */
672 add_fs_type (const char *fstype
)
674 struct fs_type_list
*fsp
;
676 fsp
= xmalloc (sizeof *fsp
);
677 fsp
->fs_name
= (char *) fstype
;
678 fsp
->fs_next
= fs_select_list
;
679 fs_select_list
= fsp
;
682 /* Add FSTYPE to the list of file system types to be omitted. */
685 add_excluded_fs_type (const char *fstype
)
687 struct fs_type_list
*fsp
;
689 fsp
= xmalloc (sizeof *fsp
);
690 fsp
->fs_name
= (char *) fstype
;
691 fsp
->fs_next
= fs_exclude_list
;
692 fs_exclude_list
= fsp
;
698 if (status
!= EXIT_SUCCESS
)
699 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
703 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name
);
705 Show information about the file system on which each FILE resides,\n\
706 or all file systems by default.\n\
710 Mandatory arguments to long options are mandatory for short options too.\n\
713 -a, --all include dummy file systems\n\
714 -B, --block-size=SIZE scale sizes by SIZE before printing them. E.g.,\n\
715 `-BM' prints sizes in units of 1,048,576 bytes.\n\
716 See SIZE format below.\n\
717 --total produce a grand total\n\
718 -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\n\
719 -H, --si likewise, but use powers of 1000 not 1024\n\
722 -i, --inodes list inode information instead of block usage\n\
723 -k like --block-size=1K\n\
724 -l, --local limit listing to local file systems\n\
725 --no-sync do not invoke sync before getting usage info (default)\n\
728 -P, --portability use the POSIX output format\n\
729 --sync invoke sync before getting usage info\n\
730 -t, --type=TYPE limit listing to file systems of type TYPE\n\
731 -T, --print-type print file system type\n\
732 -x, --exclude-type=TYPE limit listing to file systems not of type TYPE\n\
735 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
736 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
737 emit_blocksize_note ("DF");
739 emit_ancillary_info ();
745 main (int argc
, char **argv
)
747 struct stat
*stats
IF_LINT ( = 0);
749 initialize_main (&argc
, &argv
);
750 set_program_name (argv
[0]);
751 setlocale (LC_ALL
, "");
752 bindtextdomain (PACKAGE
, LOCALEDIR
);
753 textdomain (PACKAGE
);
755 atexit (close_stdout
);
757 fs_select_list
= NULL
;
758 fs_exclude_list
= NULL
;
759 inode_format
= false;
761 show_listed_fs
= false;
762 human_output_opts
= -1;
764 file_systems_processed
= false;
765 posix_format
= false;
766 exit_status
= EXIT_SUCCESS
;
767 print_grand_total
= false;
768 grand_fsu
.fsu_blocksize
= 1;
773 int c
= getopt_long (argc
, argv
, "aB:iF:hHklmPTt:vx:", long_options
,
785 enum strtol_error e
= human_options (optarg
, &human_output_opts
,
788 xstrtol_fatal (e
, oi
, c
, long_options
, optarg
);
795 human_output_opts
= human_autoscale
| human_SI
| human_base_1024
;
796 output_block_size
= 1;
799 human_output_opts
= human_autoscale
| human_SI
;
800 output_block_size
= 1;
803 human_output_opts
= 0;
804 output_block_size
= 1024;
807 show_local_fs
= true;
809 case 'm': /* obsolescent */
810 human_output_opts
= 0;
811 output_block_size
= 1024 * 1024;
823 require_sync
= false;
827 /* Accept -F as a synonym for -t for compatibility with Solaris. */
829 add_fs_type (optarg
);
832 case 'v': /* For SysV compatibility. */
836 add_excluded_fs_type (optarg
);
840 print_grand_total
= true;
843 case_GETOPT_HELP_CHAR
;
844 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
847 usage (EXIT_FAILURE
);
851 if (human_output_opts
== -1)
855 human_output_opts
= 0;
856 output_block_size
= (getenv ("POSIXLY_CORRECT") ? 512 : 1024);
859 human_options (getenv ("DF_BLOCK_SIZE"),
860 &human_output_opts
, &output_block_size
);
863 /* Fail if the same file system type was both selected and excluded. */
866 struct fs_type_list
*fs_incl
;
867 for (fs_incl
= fs_select_list
; fs_incl
; fs_incl
= fs_incl
->fs_next
)
869 struct fs_type_list
*fs_excl
;
870 for (fs_excl
= fs_exclude_list
; fs_excl
; fs_excl
= fs_excl
->fs_next
)
872 if (STREQ (fs_incl
->fs_name
, fs_excl
->fs_name
))
875 _("file system type %s both selected and excluded"),
876 quote (fs_incl
->fs_name
));
890 /* Open each of the given entries to make sure any corresponding
891 partition is automounted. This must be done before reading the
892 file system table. */
893 stats
= xnmalloc (argc
- optind
, sizeof *stats
);
894 for (i
= optind
; i
< argc
; ++i
)
896 /* Prefer to open with O_NOCTTY and use fstat, but fall back
897 on using "stat", in case the file is unreadable. */
898 int fd
= open (argv
[i
], O_RDONLY
| O_NOCTTY
);
899 if ((fd
< 0 || fstat (fd
, &stats
[i
- optind
]))
900 && stat (argv
[i
], &stats
[i
- optind
]))
902 error (0, errno
, "%s", quote (argv
[i
]));
903 exit_status
= EXIT_FAILURE
;
912 read_file_system_list ((fs_select_list
!= NULL
913 || fs_exclude_list
!= NULL
917 if (mount_list
== NULL
)
919 /* Couldn't read the table of mounted file systems.
920 Fail if df was invoked with no file name arguments;
921 Otherwise, merely give a warning and proceed. */
922 int status
= (optind
< argc
? 0 : EXIT_FAILURE
);
923 const char *warning
= (optind
< argc
? _("Warning: ") : "");
924 error (status
, errno
, "%s%s", warning
,
925 _("cannot read table of mounted file systems"));
935 /* Display explicitly requested empty file systems. */
936 show_listed_fs
= true;
938 for (i
= optind
; i
< argc
; ++i
)
940 show_entry (argv
[i
], &stats
[i
- optind
]);
945 if (print_grand_total
)
948 grand_fsu
.fsu_blocks
= 1;
949 show_dev ("total", NULL
, NULL
, NULL
, false, false, &grand_fsu
);
952 if (! file_systems_processed
)
953 error (EXIT_FAILURE
, 0, _("no file systems processed"));