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>
33 #include "mountlist.h"
35 #include "find-mount-point.h"
37 /* The official name of this program (e.g., no `g' prefix). */
38 #define PROGRAM_NAME "df"
41 proper_name_utf8 ("Torbjorn Granlund", "Torbj\303\266rn Granlund"), \
42 proper_name ("David MacKenzie"), \
43 proper_name ("Paul Eggert")
45 /* If true, show inode information. */
46 static bool inode_format
;
48 /* If true, show even file systems with zero size or
49 uninteresting types. */
50 static bool show_all_fs
;
52 /* If true, show only local file systems. */
53 static bool show_local_fs
;
55 /* If true, output data for each file system corresponding to a
56 command line argument -- even if it's a dummy (automounter) entry. */
57 static bool show_listed_fs
;
59 /* Human-readable options for output. */
60 static int human_output_opts
;
62 /* The units to use when printing sizes. */
63 static uintmax_t output_block_size
;
65 /* If true, use the POSIX output format. */
66 static bool posix_format
;
68 /* True if a file system has been processed for output. */
69 static bool file_systems_processed
;
71 /* If true, invoke the `sync' system call before getting any usage data.
72 Using this option can make df very slow, especially with many or very
73 busy disks. Note that this may make a difference on some systems --
74 SunOS 4.1.3, for one. It is *not* necessary on GNU/Linux. */
75 static bool require_sync
;
77 /* Desired exit status. */
78 static int exit_status
;
80 /* A file system type to display. */
85 struct fs_type_list
*fs_next
;
88 /* Linked list of file system types to display.
89 If `fs_select_list' is NULL, list all types.
90 This table is generated dynamically from command-line options,
91 rather than hardcoding into the program what it thinks are the
92 valid file system types; let the user specify any file system type
93 they want to, and if there are any file systems of that type, they
96 Some file system types:
97 4.2 4.3 ufs nfs swap ignore io vm efs dbg */
99 static struct fs_type_list
*fs_select_list
;
101 /* Linked list of file system types to omit.
102 If the list is empty, don't exclude any types. */
104 static struct fs_type_list
*fs_exclude_list
;
106 /* Linked list of mounted file systems. */
107 static struct mount_entry
*mount_list
;
109 /* If true, print file system type as well. */
110 static bool print_type
;
112 /* If true, print a grand total at the end. */
113 static bool print_grand_total
;
115 /* Grand total data. */
116 static struct fs_usage grand_fsu
;
119 enum { DEFAULT_MODE
, INODES_MODE
, HUMAN_MODE
, POSIX_MODE
, NMODES
};
120 static int header_mode
= DEFAULT_MODE
;
122 /* Displayable fields. */
125 DEV_FIELD
, /* file system */
126 TYPE_FIELD
, /* FS type */
127 TOTAL_FIELD
, /* blocks or inodes */
128 USED_FIELD
, /* ditto */
129 FREE_FIELD
, /* ditto */
130 PCENT_FIELD
, /* percent used */
131 MNT_FIELD
, /* mount point */
135 /* Header strings for the above fields in each mode.
136 NULL means to use the header for the default mode. */
137 static const char *headers
[NFIELDS
][NMODES
] = {
138 /* DEFAULT_MODE INODES_MODE HUMAN_MODE POSIX_MODE */
139 { N_("Filesystem"), NULL
, NULL
, NULL
},
140 { N_("Type"), NULL
, NULL
, NULL
},
141 { N_("blocks"), N_("Inodes"), N_("Size"), NULL
},
142 { N_("Used"), N_("IUsed"), NULL
, NULL
},
143 { N_("Available"), N_("IFree"), N_("Avail"), NULL
},
144 { N_("Use%"), N_("IUse%"), NULL
, N_("Capacity") },
145 { N_("Mounted on"), NULL
, NULL
, NULL
}
148 /* Alignments for the 3 textual and 4 numeric fields. */
149 static mbs_align_t alignments
[NFIELDS
] = {
150 MBS_ALIGN_LEFT
, MBS_ALIGN_LEFT
,
151 MBS_ALIGN_RIGHT
, MBS_ALIGN_RIGHT
, MBS_ALIGN_RIGHT
, MBS_ALIGN_RIGHT
,
155 /* Auto adjusted (up) widths used to align columns. */
156 static size_t widths
[NFIELDS
] = { 14, 4, 5, 5, 5, 4, 0 };
158 /* Storage for pointers for each string (cell of table). */
159 static char ***table
;
161 /* The current number of processed rows (including header). */
164 /* For long options that have no equivalent short option, use a
165 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
168 NO_SYNC_OPTION
= CHAR_MAX
+ 1,
172 static struct option
const long_options
[] =
174 {"all", no_argument
, NULL
, 'a'},
175 {"block-size", required_argument
, NULL
, 'B'},
176 {"inodes", no_argument
, NULL
, 'i'},
177 {"human-readable", no_argument
, NULL
, 'h'},
178 {"si", no_argument
, NULL
, 'H'},
179 {"local", no_argument
, NULL
, 'l'},
180 {"megabytes", no_argument
, NULL
, 'm'}, /* obsolescent */
181 {"portability", no_argument
, NULL
, 'P'},
182 {"print-type", no_argument
, NULL
, 'T'},
183 {"sync", no_argument
, NULL
, SYNC_OPTION
},
184 {"no-sync", no_argument
, NULL
, NO_SYNC_OPTION
},
185 {"total", no_argument
, NULL
, 'c'},
186 {"type", required_argument
, NULL
, 't'},
187 {"exclude-type", required_argument
, NULL
, 'x'},
188 {GETOPT_HELP_OPTION_DECL
},
189 {GETOPT_VERSION_OPTION_DECL
},
193 /* Dynamically allocate a row of pointers in TABLE, which
194 can then be accessed with standard 2D array notation. */
197 alloc_table_row (void)
200 table
= xnrealloc (table
, nrows
, sizeof (char *));
201 table
[nrows
-1] = xnmalloc (NFIELDS
, sizeof (char *));
204 /* Output each cell in the table, accounting for the
205 alignment and max width of each column. */
212 for (row
= 0; row
< nrows
; row
++)
214 for (field
= 0; field
< NFIELDS
; field
++)
216 size_t width
= widths
[field
];
217 char *cell
= table
[row
][field
];
218 if (!cell
) /* Missing type column, or mount point etc. */
221 /* Note the DEV_FIELD used to be displayed on it's own line
222 if (!posix_format && mbswidth (cell) > 20), but that
223 functionality is probably more problematic than helpful. */
226 if (field
== MNT_FIELD
) /* The last one. */
227 fputs (cell
, stdout
);
230 cell
= ambsalign (cell
, &width
, alignments
[field
], 0);
231 /* When ambsalign fails, output unaligned data. */
232 fputs (cell
? cell
: table
[row
][field
], stdout
);
235 IF_LINT (free (table
[row
][field
]));
238 IF_LINT (free (table
[row
]));
241 IF_LINT (free (table
));
244 /* Obtain the appropriate header entries. */
253 for (field
= 0; field
< NFIELDS
; field
++)
255 if (field
== TYPE_FIELD
&& !print_type
)
257 table
[nrows
-1][field
] = NULL
;
262 char const *header
= _(headers
[field
][header_mode
]);
264 header
= _(headers
[field
][DEFAULT_MODE
]);
266 if (header_mode
== DEFAULT_MODE
&& field
== TOTAL_FIELD
)
268 char buf
[LONGEST_HUMAN_READABLE
+ 1];
270 int opts
= (human_suppress_point_zero
271 | human_autoscale
| human_SI
273 & (human_group_digits
| human_base_1024
| human_B
)));
275 /* Prefer the base that makes the human-readable value more exact,
276 if there is a difference. */
278 uintmax_t q1000
= output_block_size
;
279 uintmax_t q1024
= output_block_size
;
280 bool divisible_by_1000
;
281 bool divisible_by_1024
;
285 divisible_by_1000
= q1000
% 1000 == 0; q1000
/= 1000;
286 divisible_by_1024
= q1024
% 1024 == 0; q1024
/= 1024;
288 while (divisible_by_1000
& divisible_by_1024
);
290 if (divisible_by_1000
< divisible_by_1024
)
291 opts
|= human_base_1024
;
292 if (divisible_by_1024
< divisible_by_1000
)
293 opts
&= ~human_base_1024
;
294 if (! (opts
& human_base_1024
))
297 char *num
= human_readable (output_block_size
, buf
, opts
, 1, 1);
299 if (asprintf (&cell
, "%s-%s", num
, header
) == -1)
302 else if (header_mode
== POSIX_MODE
&& field
== TOTAL_FIELD
)
304 char buf
[INT_BUFSIZE_BOUND (uintmax_t)];
305 char *num
= umaxtostr (output_block_size
, buf
);
307 if (asprintf (&cell
, "%s-%s", num
, header
) == -1)
311 cell
= strdup (header
);
316 table
[nrows
-1][field
] = cell
;
318 widths
[field
] = MAX (widths
[field
], mbswidth (cell
, 0));
322 /* Is FSTYPE a type of file system that should be listed? */
324 static bool _GL_ATTRIBUTE_PURE
325 selected_fstype (const char *fstype
)
327 const struct fs_type_list
*fsp
;
329 if (fs_select_list
== NULL
|| fstype
== NULL
)
331 for (fsp
= fs_select_list
; fsp
; fsp
= fsp
->fs_next
)
332 if (STREQ (fstype
, fsp
->fs_name
))
337 /* Is FSTYPE a type of file system that should be omitted? */
339 static bool _GL_ATTRIBUTE_PURE
340 excluded_fstype (const char *fstype
)
342 const struct fs_type_list
*fsp
;
344 if (fs_exclude_list
== NULL
|| fstype
== NULL
)
346 for (fsp
= fs_exclude_list
; fsp
; fsp
= fsp
->fs_next
)
347 if (STREQ (fstype
, fsp
->fs_name
))
352 /* Return true if N is a known integer value. On many file systems,
353 UINTMAX_MAX represents an unknown value; on AIX, UINTMAX_MAX - 1
354 represents unknown. Use a rule that works on AIX file systems, and
355 that almost-always works on other types. */
357 known_value (uintmax_t n
)
359 return n
< UINTMAX_MAX
- 1;
362 /* Like human_readable (N, BUF, human_output_opts, INPUT_UNITS, OUTPUT_UNITS),
365 - If NEGATIVE, then N represents a negative number,
366 expressed in two's complement.
367 - Otherwise, return "-" if N is unknown. */
370 df_readable (bool negative
, uintmax_t n
, char *buf
,
371 uintmax_t input_units
, uintmax_t output_units
)
373 if (! known_value (n
) && !negative
)
377 char *p
= human_readable (negative
? -n
: n
, buf
+ negative
,
378 human_output_opts
, input_units
, output_units
);
385 /* Logical equivalence */
386 #define LOG_EQ(a, b) (!(a) == !(b))
388 /* Add integral value while using uintmax_t for value part and separate
389 negation flag. It adds value of SRC and SRC_NEG to DEST and DEST_NEG.
390 The result will be in DEST and DEST_NEG. See df_readable to understand
391 how the negation flag is used. */
393 add_uint_with_neg_flag (uintmax_t *dest
, bool *dest_neg
,
394 uintmax_t src
, bool src_neg
)
396 if (LOG_EQ (*dest_neg
, src_neg
))
420 /* Obtain a space listing for the disk device with absolute file name DISK.
421 If MOUNT_POINT is non-NULL, it is the name of the root of the
423 If STAT_FILE is non-null, it is the name of a file within the file
424 system that the user originally asked for; this provides better
425 diagnostics, and sometimes it provides better results on networked
426 file systems that give different free-space results depending on
427 where in the file system you probe.
428 If FSTYPE is non-NULL, it is the type of the file system on DISK.
429 If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may
430 not be able to produce statistics in this case.
431 ME_DUMMY and ME_REMOTE are the mount entry flags. */
434 get_dev (char const *disk
, char const *mount_point
,
435 char const *stat_file
, char const *fstype
,
436 bool me_dummy
, bool me_remote
,
437 const struct fs_usage
*force_fsu
)
440 char buf
[LONGEST_HUMAN_READABLE
+ 2];
441 uintmax_t input_units
;
442 uintmax_t output_units
;
445 bool negate_available
;
446 uintmax_t available_to_root
;
453 if (me_remote
&& show_local_fs
)
456 if (me_dummy
&& !show_all_fs
&& !show_listed_fs
)
459 if (!selected_fstype (fstype
) || excluded_fstype (fstype
))
462 /* If MOUNT_POINT is NULL, then the file system is not mounted, and this
463 program reports on the file system that the special file is on.
464 It would be better to report on the unmounted file system,
465 but statfs doesn't do that on most systems. */
467 stat_file
= mount_point
? mount_point
: disk
;
471 else if (get_fs_usage (stat_file
, disk
, &fsu
))
473 error (0, errno
, "%s", quote (stat_file
));
474 exit_status
= EXIT_FAILURE
;
478 if (fsu
.fsu_blocks
== 0 && !show_all_fs
&& !show_listed_fs
)
481 if (! file_systems_processed
)
483 file_systems_processed
= true;
490 disk
= "-"; /* unknown */
492 fstype
= "-"; /* unknown */
496 input_units
= output_units
= 1;
497 total
= fsu
.fsu_files
;
498 available
= fsu
.fsu_ffree
;
499 negate_available
= false;
500 available_to_root
= available
;
502 if (known_value (total
))
503 grand_fsu
.fsu_files
+= total
;
504 if (known_value (available
))
505 grand_fsu
.fsu_ffree
+= available
;
509 input_units
= fsu
.fsu_blocksize
;
510 output_units
= output_block_size
;
511 total
= fsu
.fsu_blocks
;
512 available
= fsu
.fsu_bavail
;
513 negate_available
= (fsu
.fsu_bavail_top_bit_set
514 && known_value (available
));
515 available_to_root
= fsu
.fsu_bfree
;
517 if (known_value (total
))
518 grand_fsu
.fsu_blocks
+= input_units
* total
;
519 if (known_value (available_to_root
))
520 grand_fsu
.fsu_bfree
+= input_units
* available_to_root
;
521 if (known_value (available
))
522 add_uint_with_neg_flag (&grand_fsu
.fsu_bavail
,
523 &grand_fsu
.fsu_bavail_top_bit_set
,
524 input_units
* available
, negate_available
);
529 if (known_value (total
) && known_value (available_to_root
))
531 used
= total
- available_to_root
;
532 negate_used
= (total
< available_to_root
);
535 for (field
= 0; field
< NFIELDS
; field
++)
540 cell
= xstrdup (disk
);
544 cell
= print_type
? xstrdup (fstype
) : NULL
;
548 cell
= xstrdup (df_readable (false, total
, buf
,
549 input_units
, output_units
));
552 cell
= xstrdup (df_readable (negate_used
, used
, buf
,
553 input_units
, output_units
));
556 cell
= xstrdup (df_readable (negate_available
, available
, buf
,
557 input_units
, output_units
));
561 if (! known_value (used
) || ! known_value (available
))
563 else if (!negate_used
564 && used
<= TYPE_MAXIMUM (uintmax_t) / 100
565 && used
+ available
!= 0
566 && (used
+ available
< used
) == negate_available
)
568 uintmax_t u100
= used
* 100;
569 uintmax_t nonroot_total
= used
+ available
;
570 pct
= u100
/ nonroot_total
+ (u100
% nonroot_total
!= 0);
574 /* The calculation cannot be done easily with integer
575 arithmetic. Fall back on floating point. This can suffer
576 from minor rounding errors, but doing it exactly requires
577 multiple precision arithmetic, and it's not worth the
579 double u
= negate_used
? - (double) - used
: used
;
580 double a
= negate_available
? - (double) - available
: available
;
581 double nonroot_total
= u
+ a
;
584 long int lipct
= pct
= u
* 100 / nonroot_total
;
587 /* Like `pct = ceil (dpct);', but avoid ceil so that
588 the math library needn't be linked. */
589 if (ipct
- 1 < pct
&& pct
<= ipct
+ 1)
590 pct
= ipct
+ (ipct
< pct
);
596 if (asprintf (&cell
, "%.0f%%", pct
) == -1)
610 #ifdef HIDE_AUTOMOUNT_PREFIX
611 /* Don't print the first directory name in MOUNT_POINT if it's an
612 artifact of an automounter. This is a bit too aggressive to be
614 if (STRNCMP_LIT (mount_point
, "/auto/") == 0)
616 else if (STRNCMP_LIT (mount_point
, "/tmp_mnt/") == 0)
619 cell
= xstrdup (mount_point
);
626 assert (!"unhandled field");
630 widths
[field
] = MAX (widths
[field
], mbswidth (cell
, 0));
631 table
[nrows
-1][field
] = cell
;
635 /* If DISK corresponds to a mount point, show its usage
636 and return true. Otherwise, return false. */
638 get_disk (char const *disk
)
640 struct mount_entry
const *me
;
641 struct mount_entry
const *best_match
= NULL
;
643 for (me
= mount_list
; me
; me
= me
->me_next
)
644 if (STREQ (disk
, me
->me_devname
))
649 get_dev (best_match
->me_devname
, best_match
->me_mountdir
, NULL
,
650 best_match
->me_type
, best_match
->me_dummy
,
651 best_match
->me_remote
, NULL
);
658 /* Figure out which device file or directory POINT is mounted on
659 and show its disk usage.
660 STATP must be the result of `stat (POINT, STATP)'. */
662 get_point (const char *point
, const struct stat
*statp
)
664 struct stat disk_stats
;
665 struct mount_entry
*me
;
666 struct mount_entry
const *best_match
= NULL
;
668 /* Calculate the real absolute file name for POINT, and use that to find
669 the mount point. This avoids statting unavailable mount points,
670 which can hang df. */
671 char *resolved
= canonicalize_file_name (point
);
672 if (resolved
&& resolved
[0] == '/')
674 size_t resolved_len
= strlen (resolved
);
675 size_t best_match_len
= 0;
677 for (me
= mount_list
; me
; me
= me
->me_next
)
678 if (!STREQ (me
->me_type
, "lofs")
679 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
681 size_t len
= strlen (me
->me_mountdir
);
682 if (best_match_len
<= len
&& len
<= resolved_len
683 && (len
== 1 /* root file system */
684 || ((len
== resolved_len
|| resolved
[len
] == '/')
685 && STREQ_LEN (me
->me_mountdir
, resolved
, len
))))
688 best_match_len
= len
;
694 && (stat (best_match
->me_mountdir
, &disk_stats
) != 0
695 || disk_stats
.st_dev
!= statp
->st_dev
))
699 for (me
= mount_list
; me
; me
= me
->me_next
)
701 if (me
->me_dev
== (dev_t
) -1)
703 if (stat (me
->me_mountdir
, &disk_stats
) == 0)
704 me
->me_dev
= disk_stats
.st_dev
;
707 /* Report only I/O errors. Other errors might be
708 caused by shadowed mount points, which means POINT
709 can't possibly be on this file system. */
712 error (0, errno
, "%s", quote (me
->me_mountdir
));
713 exit_status
= EXIT_FAILURE
;
716 /* So we won't try and fail repeatedly. */
717 me
->me_dev
= (dev_t
) -2;
721 if (statp
->st_dev
== me
->me_dev
722 && !STREQ (me
->me_type
, "lofs")
723 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
725 /* Skip bogus mtab entries. */
726 if (stat (me
->me_mountdir
, &disk_stats
) != 0
727 || disk_stats
.st_dev
!= me
->me_dev
)
728 me
->me_dev
= (dev_t
) -2;
735 get_dev (best_match
->me_devname
, best_match
->me_mountdir
, point
,
736 best_match
->me_type
, best_match
->me_dummy
, best_match
->me_remote
,
740 /* We couldn't find the mount entry corresponding to POINT. Go ahead and
741 print as much info as we can; methods that require the device to be
742 present will fail at a later point. */
744 /* Find the actual mount point. */
745 char *mp
= find_mount_point (point
, statp
);
748 get_dev (NULL
, mp
, NULL
, NULL
, false, false, NULL
);
754 /* Determine what kind of node NAME is and show the disk usage
755 for it. STATP is the results of `stat' on NAME. */
758 get_entry (char const *name
, struct stat
const *statp
)
760 if ((S_ISBLK (statp
->st_mode
) || S_ISCHR (statp
->st_mode
))
764 get_point (name
, statp
);
767 /* Show all mounted file systems, except perhaps those that are of
768 an unselected type or are empty. */
771 get_all_entries (void)
773 struct mount_entry
*me
;
775 for (me
= mount_list
; me
; me
= me
->me_next
)
776 get_dev (me
->me_devname
, me
->me_mountdir
, NULL
, me
->me_type
,
777 me
->me_dummy
, me
->me_remote
, NULL
);
780 /* Add FSTYPE to the list of file system types to display. */
783 add_fs_type (const char *fstype
)
785 struct fs_type_list
*fsp
;
787 fsp
= xmalloc (sizeof *fsp
);
788 fsp
->fs_name
= (char *) fstype
;
789 fsp
->fs_next
= fs_select_list
;
790 fs_select_list
= fsp
;
793 /* Add FSTYPE to the list of file system types to be omitted. */
796 add_excluded_fs_type (const char *fstype
)
798 struct fs_type_list
*fsp
;
800 fsp
= xmalloc (sizeof *fsp
);
801 fsp
->fs_name
= (char *) fstype
;
802 fsp
->fs_next
= fs_exclude_list
;
803 fs_exclude_list
= fsp
;
809 if (status
!= EXIT_SUCCESS
)
810 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
814 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name
);
816 Show information about the file system on which each FILE resides,\n\
817 or all file systems by default.\n\
821 Mandatory arguments to long options are mandatory for short options too.\n\
824 -a, --all include dummy file systems\n\
825 -B, --block-size=SIZE scale sizes by SIZE before printing them. E.g.,\n\
826 `-BM' prints sizes in units of 1,048,576 bytes.\n\
827 See SIZE format below.\n\
828 --total produce a grand total\n\
829 -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\
831 -H, --si likewise, but use powers of 1000 not 1024\n\
834 -i, --inodes list inode information instead of block usage\n\
835 -k like --block-size=1K\n\
836 -l, --local limit listing to local file systems\n\
837 --no-sync do not invoke sync before getting usage info (default)\
841 -P, --portability use the POSIX output format\n\
842 --sync invoke sync before getting usage info\n\
843 -t, --type=TYPE limit listing to file systems of type TYPE\n\
844 -T, --print-type print file system type\n\
845 -x, --exclude-type=TYPE limit listing to file systems not of type TYPE\n\
848 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
849 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
850 emit_blocksize_note ("DF");
852 emit_ancillary_info ();
858 main (int argc
, char **argv
)
860 struct stat
*stats
IF_LINT ( = 0);
862 initialize_main (&argc
, &argv
);
863 set_program_name (argv
[0]);
864 setlocale (LC_ALL
, "");
865 bindtextdomain (PACKAGE
, LOCALEDIR
);
866 textdomain (PACKAGE
);
868 atexit (close_stdout
);
870 fs_select_list
= NULL
;
871 fs_exclude_list
= NULL
;
872 inode_format
= false;
874 show_listed_fs
= false;
875 human_output_opts
= -1;
877 file_systems_processed
= false;
878 posix_format
= false;
879 exit_status
= EXIT_SUCCESS
;
880 print_grand_total
= false;
881 grand_fsu
.fsu_blocksize
= 1;
886 int c
= getopt_long (argc
, argv
, "aB:iF:hHklmPTt:vx:", long_options
,
898 enum strtol_error e
= human_options (optarg
, &human_output_opts
,
901 xstrtol_fatal (e
, oi
, c
, long_options
, optarg
);
908 human_output_opts
= human_autoscale
| human_SI
| human_base_1024
;
909 output_block_size
= 1;
912 human_output_opts
= human_autoscale
| human_SI
;
913 output_block_size
= 1;
916 human_output_opts
= 0;
917 output_block_size
= 1024;
920 show_local_fs
= true;
922 case 'm': /* obsolescent */
923 human_output_opts
= 0;
924 output_block_size
= 1024 * 1024;
936 require_sync
= false;
940 /* Accept -F as a synonym for -t for compatibility with Solaris. */
942 add_fs_type (optarg
);
945 case 'v': /* For SysV compatibility. */
949 add_excluded_fs_type (optarg
);
953 print_grand_total
= true;
956 case_GETOPT_HELP_CHAR
;
957 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
960 usage (EXIT_FAILURE
);
964 if (human_output_opts
== -1)
968 human_output_opts
= 0;
969 output_block_size
= (getenv ("POSIXLY_CORRECT") ? 512 : 1024);
972 human_options (getenv ("DF_BLOCK_SIZE"),
973 &human_output_opts
, &output_block_size
);
977 header_mode
= INODES_MODE
;
978 else if (human_output_opts
& human_autoscale
)
979 header_mode
= HUMAN_MODE
;
980 else if (posix_format
)
981 header_mode
= POSIX_MODE
;
983 /* Fail if the same file system type was both selected and excluded. */
986 struct fs_type_list
*fs_incl
;
987 for (fs_incl
= fs_select_list
; fs_incl
; fs_incl
= fs_incl
->fs_next
)
989 struct fs_type_list
*fs_excl
;
990 for (fs_excl
= fs_exclude_list
; fs_excl
; fs_excl
= fs_excl
->fs_next
)
992 if (STREQ (fs_incl
->fs_name
, fs_excl
->fs_name
))
995 _("file system type %s both selected and excluded"),
996 quote (fs_incl
->fs_name
));
1003 exit (EXIT_FAILURE
);
1010 /* Open each of the given entries to make sure any corresponding
1011 partition is automounted. This must be done before reading the
1012 file system table. */
1013 stats
= xnmalloc (argc
- optind
, sizeof *stats
);
1014 for (i
= optind
; i
< argc
; ++i
)
1016 /* Prefer to open with O_NOCTTY and use fstat, but fall back
1017 on using "stat", in case the file is unreadable. */
1018 int fd
= open (argv
[i
], O_RDONLY
| O_NOCTTY
);
1019 if ((fd
< 0 || fstat (fd
, &stats
[i
- optind
]))
1020 && stat (argv
[i
], &stats
[i
- optind
]))
1022 error (0, errno
, "%s", quote (argv
[i
]));
1023 exit_status
= EXIT_FAILURE
;
1032 read_file_system_list ((fs_select_list
!= NULL
1033 || fs_exclude_list
!= NULL
1037 if (mount_list
== NULL
)
1039 /* Couldn't read the table of mounted file systems.
1040 Fail if df was invoked with no file name arguments;
1041 Otherwise, merely give a warning and proceed. */
1042 int status
= (optind
< argc
? 0 : EXIT_FAILURE
);
1043 const char *warning
= (optind
< argc
? _("Warning: ") : "");
1044 error (status
, errno
, "%s%s", warning
,
1045 _("cannot read table of mounted file systems"));
1055 /* Display explicitly requested empty file systems. */
1056 show_listed_fs
= true;
1058 for (i
= optind
; i
< argc
; ++i
)
1060 get_entry (argv
[i
], &stats
[i
- optind
]);
1065 if (print_grand_total
)
1068 grand_fsu
.fsu_blocks
= 1;
1069 get_dev ("total", NULL
, NULL
, NULL
, false, false, &grand_fsu
);
1074 if (! file_systems_processed
)
1075 error (EXIT_FAILURE
, 0, _("no file systems processed"));