1 /* df - summarize free disk space
2 Copyright (C) 1991, 1995-2011 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)\
720 -H, --si likewise, but use powers of 1000 not 1024\n\
723 -i, --inodes list inode information instead of block usage\n\
724 -k like --block-size=1K\n\
725 -l, --local limit listing to local file systems\n\
726 --no-sync do not invoke sync before getting usage info (default)\
730 -P, --portability use the POSIX output format\n\
731 --sync invoke sync before getting usage info\n\
732 -t, --type=TYPE limit listing to file systems of type TYPE\n\
733 -T, --print-type print file system type\n\
734 -x, --exclude-type=TYPE limit listing to file systems not of type TYPE\n\
737 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
738 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
739 emit_blocksize_note ("DF");
741 emit_ancillary_info ();
747 main (int argc
, char **argv
)
749 struct stat
*stats
IF_LINT ( = 0);
751 initialize_main (&argc
, &argv
);
752 set_program_name (argv
[0]);
753 setlocale (LC_ALL
, "");
754 bindtextdomain (PACKAGE
, LOCALEDIR
);
755 textdomain (PACKAGE
);
757 atexit (close_stdout
);
759 fs_select_list
= NULL
;
760 fs_exclude_list
= NULL
;
761 inode_format
= false;
763 show_listed_fs
= false;
764 human_output_opts
= -1;
766 file_systems_processed
= false;
767 posix_format
= false;
768 exit_status
= EXIT_SUCCESS
;
769 print_grand_total
= false;
770 grand_fsu
.fsu_blocksize
= 1;
775 int c
= getopt_long (argc
, argv
, "aB:iF:hHklmPTt:vx:", long_options
,
787 enum strtol_error e
= human_options (optarg
, &human_output_opts
,
790 xstrtol_fatal (e
, oi
, c
, long_options
, optarg
);
797 human_output_opts
= human_autoscale
| human_SI
| human_base_1024
;
798 output_block_size
= 1;
801 human_output_opts
= human_autoscale
| human_SI
;
802 output_block_size
= 1;
805 human_output_opts
= 0;
806 output_block_size
= 1024;
809 show_local_fs
= true;
811 case 'm': /* obsolescent */
812 human_output_opts
= 0;
813 output_block_size
= 1024 * 1024;
825 require_sync
= false;
829 /* Accept -F as a synonym for -t for compatibility with Solaris. */
831 add_fs_type (optarg
);
834 case 'v': /* For SysV compatibility. */
838 add_excluded_fs_type (optarg
);
842 print_grand_total
= true;
845 case_GETOPT_HELP_CHAR
;
846 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
849 usage (EXIT_FAILURE
);
853 if (human_output_opts
== -1)
857 human_output_opts
= 0;
858 output_block_size
= (getenv ("POSIXLY_CORRECT") ? 512 : 1024);
861 human_options (getenv ("DF_BLOCK_SIZE"),
862 &human_output_opts
, &output_block_size
);
865 /* Fail if the same file system type was both selected and excluded. */
868 struct fs_type_list
*fs_incl
;
869 for (fs_incl
= fs_select_list
; fs_incl
; fs_incl
= fs_incl
->fs_next
)
871 struct fs_type_list
*fs_excl
;
872 for (fs_excl
= fs_exclude_list
; fs_excl
; fs_excl
= fs_excl
->fs_next
)
874 if (STREQ (fs_incl
->fs_name
, fs_excl
->fs_name
))
877 _("file system type %s both selected and excluded"),
878 quote (fs_incl
->fs_name
));
892 /* Open each of the given entries to make sure any corresponding
893 partition is automounted. This must be done before reading the
894 file system table. */
895 stats
= xnmalloc (argc
- optind
, sizeof *stats
);
896 for (i
= optind
; i
< argc
; ++i
)
898 /* Prefer to open with O_NOCTTY and use fstat, but fall back
899 on using "stat", in case the file is unreadable. */
900 int fd
= open (argv
[i
], O_RDONLY
| O_NOCTTY
);
901 if ((fd
< 0 || fstat (fd
, &stats
[i
- optind
]))
902 && stat (argv
[i
], &stats
[i
- optind
]))
904 error (0, errno
, "%s", quote (argv
[i
]));
905 exit_status
= EXIT_FAILURE
;
914 read_file_system_list ((fs_select_list
!= NULL
915 || fs_exclude_list
!= NULL
919 if (mount_list
== NULL
)
921 /* Couldn't read the table of mounted file systems.
922 Fail if df was invoked with no file name arguments;
923 Otherwise, merely give a warning and proceed. */
924 int status
= (optind
< argc
? 0 : EXIT_FAILURE
);
925 const char *warning
= (optind
< argc
? _("Warning: ") : "");
926 error (status
, errno
, "%s%s", warning
,
927 _("cannot read table of mounted file systems"));
937 /* Display explicitly requested empty file systems. */
938 show_listed_fs
= true;
940 for (i
= optind
; i
< argc
; ++i
)
942 show_entry (argv
[i
], &stats
[i
- optind
]);
947 if (print_grand_total
)
950 grand_fsu
.fsu_blocks
= 1;
951 show_dev ("total", NULL
, NULL
, NULL
, false, false, &grand_fsu
);
954 if (! file_systems_processed
)
955 error (EXIT_FAILURE
, 0, _("no file systems processed"));