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"
35 /* The official name of this program (e.g., no `g' prefix). */
36 #define PROGRAM_NAME "df"
39 proper_name_utf8 ("Torbjorn Granlund", "Torbj\303\266rn Granlund"), \
40 proper_name ("David MacKenzie"), \
41 proper_name ("Paul Eggert")
43 /* If true, show inode information. */
44 static bool inode_format
;
46 /* If true, show even file systems with zero size or
47 uninteresting types. */
48 static bool show_all_fs
;
50 /* If true, show only local file systems. */
51 static bool show_local_fs
;
53 /* If true, output data for each file system corresponding to a
54 command line argument -- even if it's a dummy (automounter) entry. */
55 static bool show_listed_fs
;
57 /* Human-readable options for output. */
58 static int human_output_opts
;
60 /* The units to use when printing sizes. */
61 static uintmax_t output_block_size
;
63 /* If true, use the POSIX output format. */
64 static bool posix_format
;
66 /* True if a file system has been processed for output. */
67 static bool file_systems_processed
;
69 /* If true, invoke the `sync' system call before getting any usage data.
70 Using this option can make df very slow, especially with many or very
71 busy disks. Note that this may make a difference on some systems --
72 SunOS 4.1.3, for one. It is *not* necessary on GNU/Linux. */
73 static bool require_sync
;
75 /* Desired exit status. */
76 static int exit_status
;
78 /* A file system type to display. */
83 struct fs_type_list
*fs_next
;
86 /* Linked list of file system types to display.
87 If `fs_select_list' is NULL, list all types.
88 This table is generated dynamically from command-line options,
89 rather than hardcoding into the program what it thinks are the
90 valid file system types; let the user specify any file system type
91 they want to, and if there are any file systems of that type, they
94 Some file system types:
95 4.2 4.3 ufs nfs swap ignore io vm efs dbg */
97 static struct fs_type_list
*fs_select_list
;
99 /* Linked list of file system types to omit.
100 If the list is empty, don't exclude any types. */
102 static struct fs_type_list
*fs_exclude_list
;
104 /* Linked list of mounted file systems. */
105 static struct mount_entry
*mount_list
;
107 /* If true, print file system type as well. */
108 static bool print_type
;
110 /* If true, print a grand total at the end. */
111 static bool print_grand_total
;
113 /* Grand total data. */
114 static struct fs_usage grand_fsu
;
116 /* For long options that have no equivalent short option, use a
117 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
120 NO_SYNC_OPTION
= CHAR_MAX
+ 1,
124 static struct option
const long_options
[] =
126 {"all", no_argument
, NULL
, 'a'},
127 {"block-size", required_argument
, NULL
, 'B'},
128 {"inodes", no_argument
, NULL
, 'i'},
129 {"human-readable", no_argument
, NULL
, 'h'},
130 {"si", no_argument
, NULL
, 'H'},
131 {"local", no_argument
, NULL
, 'l'},
132 {"megabytes", no_argument
, NULL
, 'm'}, /* obsolescent */
133 {"portability", no_argument
, NULL
, 'P'},
134 {"print-type", no_argument
, NULL
, 'T'},
135 {"sync", no_argument
, NULL
, SYNC_OPTION
},
136 {"no-sync", no_argument
, NULL
, NO_SYNC_OPTION
},
137 {"total", no_argument
, NULL
, 'c'},
138 {"type", required_argument
, NULL
, 't'},
139 {"exclude-type", required_argument
, NULL
, 'x'},
140 {GETOPT_HELP_OPTION_DECL
},
141 {GETOPT_VERSION_OPTION_DECL
},
148 char buf
[MAX (LONGEST_HUMAN_READABLE
+ 1, INT_BUFSIZE_BOUND (uintmax_t))];
152 For best results (df header/column alignment), ensure that
153 your translation has the same length as the original. */
154 fputs (_("Filesystem Type"), stdout
);
156 fputs (_("Filesystem "), stdout
);
160 For best results (df header/column alignment), ensure that
161 your translation has the same length as the original.
162 Also, each column name translation should end at the same
163 column as the corresponding original. */
164 fputs (_(" Inodes IUsed IFree IUse%"), stdout
);
165 else if (human_output_opts
& human_autoscale
)
167 if (human_output_opts
& human_base_1024
)
168 fputs (_(" Size Used Avail Use%"), stdout
);
170 fputs (_(" Size Used Avail Use%"), stdout
);
172 else if (posix_format
)
173 printf (_(" %s-blocks Used Available Capacity"),
174 umaxtostr (output_block_size
, buf
));
177 int opts
= (human_suppress_point_zero
178 | human_autoscale
| human_SI
180 & (human_group_digits
| human_base_1024
| human_B
)));
182 /* Prefer the base that makes the human-readable value more exact,
183 if there is a difference. */
185 uintmax_t q1000
= output_block_size
;
186 uintmax_t q1024
= output_block_size
;
187 bool divisible_by_1000
;
188 bool divisible_by_1024
;
192 divisible_by_1000
= q1000
% 1000 == 0; q1000
/= 1000;
193 divisible_by_1024
= q1024
% 1024 == 0; q1024
/= 1024;
195 while (divisible_by_1000
& divisible_by_1024
);
197 if (divisible_by_1000
< divisible_by_1024
)
198 opts
|= human_base_1024
;
199 if (divisible_by_1024
< divisible_by_1000
)
200 opts
&= ~human_base_1024
;
201 if (! (opts
& human_base_1024
))
204 printf (_(" %4s-blocks Used Available Use%%"),
205 human_readable (output_block_size
, buf
, opts
, 1, 1));
208 fputs (_(" Mounted on\n"), stdout
);
211 /* Is FSTYPE a type of file system that should be listed? */
214 selected_fstype (const char *fstype
)
216 const struct fs_type_list
*fsp
;
218 if (fs_select_list
== NULL
|| fstype
== NULL
)
220 for (fsp
= fs_select_list
; fsp
; fsp
= fsp
->fs_next
)
221 if (STREQ (fstype
, fsp
->fs_name
))
226 /* Is FSTYPE a type of file system that should be omitted? */
229 excluded_fstype (const char *fstype
)
231 const struct fs_type_list
*fsp
;
233 if (fs_exclude_list
== NULL
|| fstype
== NULL
)
235 for (fsp
= fs_exclude_list
; fsp
; fsp
= fsp
->fs_next
)
236 if (STREQ (fstype
, fsp
->fs_name
))
241 /* Return true if N is a known integer value. On many file systems,
242 UINTMAX_MAX represents an unknown value; on AIX, UINTMAX_MAX - 1
243 represents unknown. Use a rule that works on AIX file systems, and
244 that almost-always works on other types. */
246 known_value (uintmax_t n
)
248 return n
< UINTMAX_MAX
- 1;
251 /* Like human_readable (N, BUF, human_output_opts, INPUT_UNITS, OUTPUT_UNITS),
254 - If NEGATIVE, then N represents a negative number,
255 expressed in two's complement.
256 - Otherwise, return "-" if N is unknown. */
259 df_readable (bool negative
, uintmax_t n
, char *buf
,
260 uintmax_t input_units
, uintmax_t output_units
)
262 if (! known_value (n
) && !negative
)
266 char *p
= human_readable (negative
? -n
: n
, buf
+ negative
,
267 human_output_opts
, input_units
, output_units
);
274 /* Logical equivalence */
275 #define LOG_EQ(a, b) (!(a) == !(b))
277 /* Add integral value while using uintmax_t for value part and separate
278 negation flag. It adds value of SRC and SRC_NEG to DEST and DEST_NEG.
279 The result will be in DEST and DEST_NEG. See df_readable to understand
280 how the negation flag is used. */
282 add_uint_with_neg_flag (uintmax_t *dest
, bool *dest_neg
,
283 uintmax_t src
, bool src_neg
)
285 if (LOG_EQ (*dest_neg
, src_neg
))
309 /* Display a space listing for the disk device with absolute file name DISK.
310 If MOUNT_POINT is non-NULL, it is the name of the root of the
312 If STAT_FILE is non-null, it is the name of a file within the file
313 system that the user originally asked for; this provides better
314 diagnostics, and sometimes it provides better results on networked
315 file systems that give different free-space results depending on
316 where in the file system you probe.
317 If FSTYPE is non-NULL, it is the type of the file system on DISK.
318 If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may
319 not be able to produce statistics in this case.
320 ME_DUMMY and ME_REMOTE are the mount entry flags. */
323 show_dev (char const *disk
, char const *mount_point
,
324 char const *stat_file
, char const *fstype
,
325 bool me_dummy
, bool me_remote
,
326 const struct fs_usage
*force_fsu
)
329 char buf
[3][LONGEST_HUMAN_READABLE
+ 2];
331 int col1_adjustment
= 0;
333 uintmax_t input_units
;
334 uintmax_t output_units
;
337 bool negate_available
;
338 uintmax_t available_to_root
;
343 if (me_remote
&& show_local_fs
)
346 if (me_dummy
&& !show_all_fs
&& !show_listed_fs
)
349 if (!selected_fstype (fstype
) || excluded_fstype (fstype
))
352 /* If MOUNT_POINT is NULL, then the file system is not mounted, and this
353 program reports on the file system that the special file is on.
354 It would be better to report on the unmounted file system,
355 but statfs doesn't do that on most systems. */
357 stat_file
= mount_point
? mount_point
: disk
;
361 else if (get_fs_usage (stat_file
, disk
, &fsu
))
363 error (0, errno
, "%s", quote (stat_file
));
364 exit_status
= EXIT_FAILURE
;
368 if (fsu
.fsu_blocks
== 0 && !show_all_fs
&& !show_listed_fs
)
371 if (! file_systems_processed
)
373 file_systems_processed
= true;
378 disk
= "-"; /* unknown */
380 fstype
= "-"; /* unknown */
382 /* df.c reserved 5 positions for fstype,
383 but that does not suffice for type iso9660 */
386 size_t disk_name_len
= strlen (disk
);
387 size_t fstype_len
= strlen (fstype
);
388 if (disk_name_len
+ fstype_len
< 18)
389 printf ("%s%*s ", disk
, 18 - (int) disk_name_len
, fstype
);
390 else if (!posix_format
)
391 printf ("%s\n%18s ", disk
, fstype
);
393 printf ("%s %s", disk
, fstype
);
397 if (strlen (disk
) > 20 && !posix_format
)
398 printf ("%s\n%20s", disk
, "");
400 printf ("%-20s", disk
);
407 input_units
= output_units
= 1;
408 total
= fsu
.fsu_files
;
409 available
= fsu
.fsu_ffree
;
410 negate_available
= false;
411 available_to_root
= available
;
413 if (known_value (total
))
414 grand_fsu
.fsu_files
+= total
;
415 if (known_value (available
))
416 grand_fsu
.fsu_ffree
+= available
;
420 if (human_output_opts
& human_autoscale
)
421 width
= 5 + ! (human_output_opts
& human_base_1024
);
428 col1_adjustment
= -3;
429 for (b
= output_block_size
; 9 < b
; b
/= 10)
433 use_width
= ((posix_format
434 && ! (human_output_opts
& human_autoscale
))
436 input_units
= fsu
.fsu_blocksize
;
437 output_units
= output_block_size
;
438 total
= fsu
.fsu_blocks
;
439 available
= fsu
.fsu_bavail
;
440 negate_available
= (fsu
.fsu_bavail_top_bit_set
441 && known_value (available
));
442 available_to_root
= fsu
.fsu_bfree
;
444 if (known_value (total
))
445 grand_fsu
.fsu_blocks
+= input_units
* total
;
446 if (known_value (available_to_root
))
447 grand_fsu
.fsu_bfree
+= input_units
* available_to_root
;
448 if (known_value (available
))
449 add_uint_with_neg_flag (&grand_fsu
.fsu_bavail
,
450 &grand_fsu
.fsu_bavail_top_bit_set
,
451 input_units
* available
, negate_available
);
456 if (known_value (total
) && known_value (available_to_root
))
458 used
= total
- available_to_root
;
459 negate_used
= (total
< available_to_root
);
462 printf (" %*s %*s %*s ",
463 width
+ col1_adjustment
,
464 df_readable (false, total
,
465 buf
[0], input_units
, output_units
),
466 width
, df_readable (negate_used
, used
,
467 buf
[1], input_units
, output_units
),
468 width
, df_readable (negate_available
, available
,
469 buf
[2], input_units
, output_units
));
471 if (! known_value (used
) || ! known_value (available
))
473 else if (!negate_used
474 && used
<= TYPE_MAXIMUM (uintmax_t) / 100
475 && used
+ available
!= 0
476 && (used
+ available
< used
) == negate_available
)
478 uintmax_t u100
= used
* 100;
479 uintmax_t nonroot_total
= used
+ available
;
480 pct
= u100
/ nonroot_total
+ (u100
% nonroot_total
!= 0);
484 /* The calculation cannot be done easily with integer
485 arithmetic. Fall back on floating point. This can suffer
486 from minor rounding errors, but doing it exactly requires
487 multiple precision arithmetic, and it's not worth the
489 double u
= negate_used
? - (double) - used
: used
;
490 double a
= negate_available
? - (double) - available
: available
;
491 double nonroot_total
= u
+ a
;
494 long int lipct
= pct
= u
* 100 / nonroot_total
;
497 /* Like `pct = ceil (dpct);', but avoid ceil so that
498 the math library needn't be linked. */
499 if (ipct
- 1 < pct
&& pct
<= ipct
+ 1)
500 pct
= ipct
+ (ipct
< pct
);
505 printf ("%*.0f%%", use_width
- 1, pct
);
507 printf ("%*s", use_width
, "- ");
511 #ifdef HIDE_AUTOMOUNT_PREFIX
512 /* Don't print the first directory name in MOUNT_POINT if it's an
513 artifact of an automounter. This is a bit too aggressive to be
515 if (strncmp ("/auto/", mount_point
, 6) == 0)
517 else if (strncmp ("/tmp_mnt/", mount_point
, 9) == 0)
520 printf (" %s", mount_point
);
525 /* Return the root mountpoint of the file system on which FILE exists, in
526 malloced storage. FILE_STAT should be the result of stating FILE.
527 Give a diagnostic and return NULL if unable to determine the mount point.
528 Exit if unable to restore current working directory. */
530 find_mount_point (const char *file
, const struct stat
*file_stat
)
532 struct saved_cwd cwd
;
533 struct stat last_stat
;
534 char *mp
= NULL
; /* The malloced mount point. */
536 if (save_cwd (&cwd
) != 0)
538 error (0, errno
, _("cannot get current directory"));
542 if (S_ISDIR (file_stat
->st_mode
))
543 /* FILE is a directory, so just chdir there directly. */
545 last_stat
= *file_stat
;
546 if (chdir (file
) < 0)
548 error (0, errno
, _("cannot change to directory %s"), quote (file
));
553 /* FILE is some other kind of file; use its directory. */
555 char *xdir
= dir_name (file
);
557 ASSIGN_STRDUPA (dir
, xdir
);
562 error (0, errno
, _("cannot change to directory %s"), quote (dir
));
566 if (stat (".", &last_stat
) < 0)
568 error (0, errno
, _("cannot stat current directory (now %s)"),
574 /* Now walk up FILE's parents until we find another file system or /,
575 chdiring as we go. LAST_STAT holds stat information for the last place
580 if (stat ("..", &st
) < 0)
582 error (0, errno
, _("cannot stat %s"), quote (".."));
585 if (st
.st_dev
!= last_stat
.st_dev
|| st
.st_ino
== last_stat
.st_ino
)
586 /* cwd is the mount point. */
588 if (chdir ("..") < 0)
590 error (0, errno
, _("cannot change to directory %s"), quote (".."));
596 /* Finally reached a mount point, see what it's called. */
600 /* Restore the original cwd. */
602 int save_errno
= errno
;
603 if (restore_cwd (&cwd
) != 0)
604 error (EXIT_FAILURE
, errno
,
605 _("failed to return to initial working directory"));
613 /* If DISK corresponds to a mount point, show its usage
614 and return true. Otherwise, return false. */
616 show_disk (char const *disk
)
618 struct mount_entry
const *me
;
619 struct mount_entry
const *best_match
= NULL
;
621 for (me
= mount_list
; me
; me
= me
->me_next
)
622 if (STREQ (disk
, me
->me_devname
))
627 show_dev (best_match
->me_devname
, best_match
->me_mountdir
, NULL
,
628 best_match
->me_type
, best_match
->me_dummy
,
629 best_match
->me_remote
, NULL
);
636 /* Figure out which device file or directory POINT is mounted on
637 and show its disk usage.
638 STATP must be the result of `stat (POINT, STATP)'. */
640 show_point (const char *point
, const struct stat
*statp
)
642 struct stat disk_stats
;
643 struct mount_entry
*me
;
644 struct mount_entry
const *best_match
= NULL
;
646 /* If POINT is an absolute file name, see if we can find the
647 mount point without performing any extra stat calls at all. */
650 /* Find the best match: prefer non-dummies, and then prefer the
651 last match if there are ties. */
653 for (me
= mount_list
; me
; me
= me
->me_next
)
654 if (STREQ (me
->me_mountdir
, point
) && !STREQ (me
->me_type
, "lofs")
655 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
659 /* Calculate the real absolute file name for POINT, and use that to find
660 the mount point. This avoids statting unavailable mount points,
661 which can hang df. */
664 char *resolved
= canonicalize_file_name (point
);
666 if (resolved
&& resolved
[0] == '/')
668 size_t resolved_len
= strlen (resolved
);
669 size_t best_match_len
= 0;
671 for (me
= mount_list
; me
; me
= me
->me_next
)
672 if (!STREQ (me
->me_type
, "lofs")
673 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
675 size_t len
= strlen (me
->me_mountdir
);
676 if (best_match_len
<= len
&& len
<= resolved_len
677 && (len
== 1 /* root file system */
678 || ((len
== resolved_len
|| resolved
[len
] == '/')
679 && strncmp (me
->me_mountdir
, resolved
, len
) == 0)))
682 best_match_len
= len
;
690 && (stat (best_match
->me_mountdir
, &disk_stats
) != 0
691 || disk_stats
.st_dev
!= statp
->st_dev
))
696 for (me
= mount_list
; me
; me
= me
->me_next
)
698 if (me
->me_dev
== (dev_t
) -1)
700 if (stat (me
->me_mountdir
, &disk_stats
) == 0)
701 me
->me_dev
= disk_stats
.st_dev
;
704 /* Report only I/O errors. Other errors might be
705 caused by shadowed mount points, which means POINT
706 can't possibly be on this file system. */
709 error (0, errno
, "%s", quote (me
->me_mountdir
));
710 exit_status
= EXIT_FAILURE
;
713 /* So we won't try and fail repeatedly. */
714 me
->me_dev
= (dev_t
) -2;
718 if (statp
->st_dev
== me
->me_dev
719 && !STREQ (me
->me_type
, "lofs")
720 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
722 /* Skip bogus mtab entries. */
723 if (stat (me
->me_mountdir
, &disk_stats
) != 0
724 || disk_stats
.st_dev
!= me
->me_dev
)
725 me
->me_dev
= (dev_t
) -2;
732 show_dev (best_match
->me_devname
, best_match
->me_mountdir
, point
,
733 best_match
->me_type
, best_match
->me_dummy
, best_match
->me_remote
,
737 /* We couldn't find the mount entry corresponding to POINT. Go ahead and
738 print as much info as we can; methods that require the device to be
739 present will fail at a later point. */
741 /* Find the actual mount point. */
742 char *mp
= find_mount_point (point
, statp
);
745 show_dev (NULL
, mp
, NULL
, NULL
, false, false, NULL
);
751 /* Determine what kind of node NAME is and show the disk usage
752 for it. STATP is the results of `stat' on NAME. */
755 show_entry (char const *name
, struct stat
const *statp
)
757 if ((S_ISBLK (statp
->st_mode
) || S_ISCHR (statp
->st_mode
))
761 show_point (name
, statp
);
764 /* Show all mounted file systems, except perhaps those that are of
765 an unselected type or are empty. */
768 show_all_entries (void)
770 struct mount_entry
*me
;
772 for (me
= mount_list
; me
; me
= me
->me_next
)
773 show_dev (me
->me_devname
, me
->me_mountdir
, NULL
, me
->me_type
,
774 me
->me_dummy
, me
->me_remote
, NULL
);
777 /* Add FSTYPE to the list of file system types to display. */
780 add_fs_type (const char *fstype
)
782 struct fs_type_list
*fsp
;
784 fsp
= xmalloc (sizeof *fsp
);
785 fsp
->fs_name
= (char *) fstype
;
786 fsp
->fs_next
= fs_select_list
;
787 fs_select_list
= fsp
;
790 /* Add FSTYPE to the list of file system types to be omitted. */
793 add_excluded_fs_type (const char *fstype
)
795 struct fs_type_list
*fsp
;
797 fsp
= xmalloc (sizeof *fsp
);
798 fsp
->fs_name
= (char *) fstype
;
799 fsp
->fs_next
= fs_exclude_list
;
800 fs_exclude_list
= fsp
;
806 if (status
!= EXIT_SUCCESS
)
807 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
811 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name
);
813 Show information about the file system on which each FILE resides,\n\
814 or all file systems by default.\n\
818 Mandatory arguments to long options are mandatory for short options too.\n\
821 -a, --all include dummy file systems\n\
822 -B, --block-size=SIZE scale sizes by SIZE before printing them. E.g.,\n\
823 `-BM' prints sizes in units of 1,048,576 bytes.\n\
824 See SIZE format below.\n\
825 --total produce a grand total\n\
826 -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\n\
827 -H, --si likewise, but use powers of 1000 not 1024\n\
830 -i, --inodes list inode information instead of block usage\n\
831 -k like --block-size=1K\n\
832 -l, --local limit listing to local file systems\n\
833 --no-sync do not invoke sync before getting usage info (default)\n\
836 -P, --portability use the POSIX output format\n\
837 --sync invoke sync before getting usage info\n\
838 -t, --type=TYPE limit listing to file systems of type TYPE\n\
839 -T, --print-type print file system type\n\
840 -x, --exclude-type=TYPE limit listing to file systems not of type TYPE\n\
843 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
844 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
845 emit_blocksize_note ("DF");
847 emit_ancillary_info ();
853 main (int argc
, char **argv
)
855 struct stat
*stats
IF_LINT ( = 0);
857 initialize_main (&argc
, &argv
);
858 set_program_name (argv
[0]);
859 setlocale (LC_ALL
, "");
860 bindtextdomain (PACKAGE
, LOCALEDIR
);
861 textdomain (PACKAGE
);
863 atexit (close_stdout
);
865 fs_select_list
= NULL
;
866 fs_exclude_list
= NULL
;
867 inode_format
= false;
869 show_listed_fs
= false;
870 human_output_opts
= -1;
872 file_systems_processed
= false;
873 posix_format
= false;
874 exit_status
= EXIT_SUCCESS
;
875 print_grand_total
= false;
876 grand_fsu
.fsu_blocksize
= 1;
881 int c
= getopt_long (argc
, argv
, "aB:iF:hHklmPTt:vx:", long_options
,
893 enum strtol_error e
= human_options (optarg
, &human_output_opts
,
896 xstrtol_fatal (e
, oi
, c
, long_options
, optarg
);
903 human_output_opts
= human_autoscale
| human_SI
| human_base_1024
;
904 output_block_size
= 1;
907 human_output_opts
= human_autoscale
| human_SI
;
908 output_block_size
= 1;
911 human_output_opts
= 0;
912 output_block_size
= 1024;
915 show_local_fs
= true;
917 case 'm': /* obsolescent */
918 human_output_opts
= 0;
919 output_block_size
= 1024 * 1024;
931 require_sync
= false;
935 /* Accept -F as a synonym for -t for compatibility with Solaris. */
937 add_fs_type (optarg
);
940 case 'v': /* For SysV compatibility. */
944 add_excluded_fs_type (optarg
);
948 print_grand_total
= true;
951 case_GETOPT_HELP_CHAR
;
952 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
955 usage (EXIT_FAILURE
);
959 if (human_output_opts
== -1)
963 human_output_opts
= 0;
964 output_block_size
= (getenv ("POSIXLY_CORRECT") ? 512 : 1024);
967 human_options (getenv ("DF_BLOCK_SIZE"),
968 &human_output_opts
, &output_block_size
);
971 /* Fail if the same file system type was both selected and excluded. */
974 struct fs_type_list
*fs_incl
;
975 for (fs_incl
= fs_select_list
; fs_incl
; fs_incl
= fs_incl
->fs_next
)
977 struct fs_type_list
*fs_excl
;
978 for (fs_excl
= fs_exclude_list
; fs_excl
; fs_excl
= fs_excl
->fs_next
)
980 if (STREQ (fs_incl
->fs_name
, fs_excl
->fs_name
))
983 _("file system type %s both selected and excluded"),
984 quote (fs_incl
->fs_name
));
998 /* Open each of the given entries to make sure any corresponding
999 partition is automounted. This must be done before reading the
1000 file system table. */
1001 stats
= xnmalloc (argc
- optind
, sizeof *stats
);
1002 for (i
= optind
; i
< argc
; ++i
)
1004 /* Prefer to open with O_NOCTTY and use fstat, but fall back
1005 on using "stat", in case the file is unreadable. */
1006 int fd
= open (argv
[i
], O_RDONLY
| O_NOCTTY
);
1007 if ((fd
< 0 || fstat (fd
, &stats
[i
- optind
]))
1008 && stat (argv
[i
], &stats
[i
- optind
]))
1010 error (0, errno
, "%s", quote (argv
[i
]));
1011 exit_status
= EXIT_FAILURE
;
1020 read_file_system_list ((fs_select_list
!= NULL
1021 || fs_exclude_list
!= NULL
1025 if (mount_list
== NULL
)
1027 /* Couldn't read the table of mounted file systems.
1028 Fail if df was invoked with no file name arguments;
1029 Otherwise, merely give a warning and proceed. */
1030 int status
= (optind
< argc
? 0 : EXIT_FAILURE
);
1031 const char *warning
= (optind
< argc
? _("Warning: ") : "");
1032 error (status
, errno
, "%s%s", warning
,
1033 _("cannot read table of mounted file systems"));
1043 /* Display explicitly requested empty file systems. */
1044 show_listed_fs
= true;
1046 for (i
= optind
; i
< argc
; ++i
)
1048 show_entry (argv
[i
], &stats
[i
- optind
]);
1051 show_all_entries ();
1053 if (print_grand_total
)
1056 grand_fsu
.fsu_blocks
= 1;
1057 show_dev ("total", NULL
, NULL
, NULL
, false, false, &grand_fsu
);
1060 if (! file_systems_processed
)
1061 error (EXIT_FAILURE
, 0, _("no file systems processed"));