1 /* df - summarize free disk space
2 Copyright (C) 1991, 1995-2012 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>
28 #include "canonicalize.h"
34 #include "mountlist.h"
36 #include "find-mount-point.h"
38 /* The official name of this program (e.g., no `g' prefix). */
39 #define PROGRAM_NAME "df"
42 proper_name_utf8 ("Torbjorn Granlund", "Torbj\303\266rn Granlund"), \
43 proper_name ("David MacKenzie"), \
44 proper_name ("Paul Eggert")
46 /* If true, show inode information. */
47 static bool inode_format
;
49 /* If true, show even file systems with zero size or
50 uninteresting types. */
51 static bool show_all_fs
;
53 /* If true, show only local file systems. */
54 static bool show_local_fs
;
56 /* If true, output data for each file system corresponding to a
57 command line argument -- even if it's a dummy (automounter) entry. */
58 static bool show_listed_fs
;
60 /* Human-readable options for output. */
61 static int human_output_opts
;
63 /* The units to use when printing sizes. */
64 static uintmax_t output_block_size
;
66 /* If true, use the POSIX output format. */
67 static bool posix_format
;
69 /* True if a file system has been processed for output. */
70 static bool file_systems_processed
;
72 /* If true, invoke the `sync' system call before getting any usage data.
73 Using this option can make df very slow, especially with many or very
74 busy disks. Note that this may make a difference on some systems --
75 SunOS 4.1.3, for one. It is *not* necessary on GNU/Linux. */
76 static bool require_sync
;
78 /* Desired exit status. */
79 static int exit_status
;
81 /* A file system type to display. */
86 struct fs_type_list
*fs_next
;
89 /* Linked list of file system types to display.
90 If `fs_select_list' is NULL, list all types.
91 This table is generated dynamically from command-line options,
92 rather than hardcoding into the program what it thinks are the
93 valid file system types; let the user specify any file system type
94 they want to, and if there are any file systems of that type, they
97 Some file system types:
98 4.2 4.3 ufs nfs swap ignore io vm efs dbg */
100 static struct fs_type_list
*fs_select_list
;
102 /* Linked list of file system types to omit.
103 If the list is empty, don't exclude any types. */
105 static struct fs_type_list
*fs_exclude_list
;
107 /* Linked list of mounted file systems. */
108 static struct mount_entry
*mount_list
;
110 /* If true, print file system type as well. */
111 static bool print_type
;
113 /* If true, print a grand total at the end. */
114 static bool print_grand_total
;
116 /* Grand total data. */
117 static struct fs_usage grand_fsu
;
120 enum { DEFAULT_MODE
, INODES_MODE
, HUMAN_MODE
, POSIX_MODE
, NMODES
};
121 static int header_mode
= DEFAULT_MODE
;
123 /* Displayable fields. */
126 DEV_FIELD
, /* file system */
127 TYPE_FIELD
, /* FS type */
128 TOTAL_FIELD
, /* blocks or inodes */
129 USED_FIELD
, /* ditto */
130 FREE_FIELD
, /* ditto */
131 PCENT_FIELD
, /* percent used */
132 MNT_FIELD
, /* mount point */
136 /* Header strings for the above fields in each mode.
137 NULL means to use the header for the default mode. */
138 static const char *headers
[NFIELDS
][NMODES
] = {
139 /* DEFAULT_MODE INODES_MODE HUMAN_MODE POSIX_MODE */
140 { N_("Filesystem"), NULL
, NULL
, NULL
},
141 { N_("Type"), NULL
, NULL
, NULL
},
142 { N_("blocks"), N_("Inodes"), N_("Size"), NULL
},
143 { N_("Used"), N_("IUsed"), NULL
, NULL
},
144 { N_("Available"), N_("IFree"), N_("Avail"), NULL
},
145 { N_("Use%"), N_("IUse%"), NULL
, N_("Capacity") },
146 { N_("Mounted on"), NULL
, NULL
, NULL
}
149 /* Alignments for the 3 textual and 4 numeric fields. */
150 static mbs_align_t alignments
[NFIELDS
] = {
151 MBS_ALIGN_LEFT
, MBS_ALIGN_LEFT
,
152 MBS_ALIGN_RIGHT
, MBS_ALIGN_RIGHT
, MBS_ALIGN_RIGHT
, MBS_ALIGN_RIGHT
,
156 /* Auto adjusted (up) widths used to align columns. */
157 static size_t widths
[NFIELDS
] = { 14, 4, 5, 5, 5, 4, 0 };
159 /* Storage for pointers for each string (cell of table). */
160 static char ***table
;
162 /* The current number of processed rows (including header). */
165 /* For long options that have no equivalent short option, use a
166 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
169 NO_SYNC_OPTION
= CHAR_MAX
+ 1,
173 static struct option
const long_options
[] =
175 {"all", no_argument
, NULL
, 'a'},
176 {"block-size", required_argument
, NULL
, 'B'},
177 {"inodes", no_argument
, NULL
, 'i'},
178 {"human-readable", no_argument
, NULL
, 'h'},
179 {"si", no_argument
, NULL
, 'H'},
180 {"local", no_argument
, NULL
, 'l'},
181 {"megabytes", no_argument
, NULL
, 'm'}, /* obsolescent */
182 {"portability", no_argument
, NULL
, 'P'},
183 {"print-type", no_argument
, NULL
, 'T'},
184 {"sync", no_argument
, NULL
, SYNC_OPTION
},
185 {"no-sync", no_argument
, NULL
, NO_SYNC_OPTION
},
186 {"total", no_argument
, NULL
, 'c'},
187 {"type", required_argument
, NULL
, 't'},
188 {"exclude-type", required_argument
, NULL
, 'x'},
189 {GETOPT_HELP_OPTION_DECL
},
190 {GETOPT_VERSION_OPTION_DECL
},
194 /* Dynamically allocate a row of pointers in TABLE, which
195 can then be accessed with standard 2D array notation. */
198 alloc_table_row (void)
201 table
= xnrealloc (table
, nrows
, sizeof (char *));
202 table
[nrows
-1] = xnmalloc (NFIELDS
, sizeof (char *));
205 /* Output each cell in the table, accounting for the
206 alignment and max width of each column. */
213 for (row
= 0; row
< nrows
; row
++)
215 for (field
= 0; field
< NFIELDS
; field
++)
217 size_t width
= widths
[field
];
218 char *cell
= table
[row
][field
];
219 if (!cell
) /* Missing type column, or mount point etc. */
222 /* Note the DEV_FIELD used to be displayed on it's own line
223 if (!posix_format && mbswidth (cell) > 20), but that
224 functionality is probably more problematic than helpful. */
227 if (field
== MNT_FIELD
) /* The last one. */
228 fputs (cell
, stdout
);
231 cell
= ambsalign (cell
, &width
, alignments
[field
], 0);
232 /* When ambsalign fails, output unaligned data. */
233 fputs (cell
? cell
: table
[row
][field
], stdout
);
236 IF_LINT (free (table
[row
][field
]));
239 IF_LINT (free (table
[row
]));
242 IF_LINT (free (table
));
245 /* Obtain the appropriate header entries. */
254 for (field
= 0; field
< NFIELDS
; field
++)
256 if (field
== TYPE_FIELD
&& !print_type
)
258 table
[nrows
-1][field
] = NULL
;
263 char const *header
= _(headers
[field
][header_mode
]);
265 header
= _(headers
[field
][DEFAULT_MODE
]);
267 if (header_mode
== DEFAULT_MODE
&& field
== TOTAL_FIELD
)
269 char buf
[LONGEST_HUMAN_READABLE
+ 1];
271 int opts
= (human_suppress_point_zero
272 | human_autoscale
| human_SI
274 & (human_group_digits
| human_base_1024
| human_B
)));
276 /* Prefer the base that makes the human-readable value more exact,
277 if there is a difference. */
279 uintmax_t q1000
= output_block_size
;
280 uintmax_t q1024
= output_block_size
;
281 bool divisible_by_1000
;
282 bool divisible_by_1024
;
286 divisible_by_1000
= q1000
% 1000 == 0; q1000
/= 1000;
287 divisible_by_1024
= q1024
% 1024 == 0; q1024
/= 1024;
289 while (divisible_by_1000
& divisible_by_1024
);
291 if (divisible_by_1000
< divisible_by_1024
)
292 opts
|= human_base_1024
;
293 if (divisible_by_1024
< divisible_by_1000
)
294 opts
&= ~human_base_1024
;
295 if (! (opts
& human_base_1024
))
298 char *num
= human_readable (output_block_size
, buf
, opts
, 1, 1);
300 if (asprintf (&cell
, "%s-%s", num
, header
) == -1)
303 else if (header_mode
== POSIX_MODE
&& field
== TOTAL_FIELD
)
305 char buf
[INT_BUFSIZE_BOUND (uintmax_t)];
306 char *num
= umaxtostr (output_block_size
, buf
);
308 if (asprintf (&cell
, "%s-%s", num
, header
) == -1)
312 cell
= strdup (header
);
317 table
[nrows
-1][field
] = cell
;
319 widths
[field
] = MAX (widths
[field
], mbswidth (cell
, 0));
323 /* Is FSTYPE a type of file system that should be listed? */
325 static bool _GL_ATTRIBUTE_PURE
326 selected_fstype (const char *fstype
)
328 const struct fs_type_list
*fsp
;
330 if (fs_select_list
== NULL
|| fstype
== NULL
)
332 for (fsp
= fs_select_list
; fsp
; fsp
= fsp
->fs_next
)
333 if (STREQ (fstype
, fsp
->fs_name
))
338 /* Is FSTYPE a type of file system that should be omitted? */
340 static bool _GL_ATTRIBUTE_PURE
341 excluded_fstype (const char *fstype
)
343 const struct fs_type_list
*fsp
;
345 if (fs_exclude_list
== NULL
|| fstype
== NULL
)
347 for (fsp
= fs_exclude_list
; fsp
; fsp
= fsp
->fs_next
)
348 if (STREQ (fstype
, fsp
->fs_name
))
353 /* Return true if N is a known integer value. On many file systems,
354 UINTMAX_MAX represents an unknown value; on AIX, UINTMAX_MAX - 1
355 represents unknown. Use a rule that works on AIX file systems, and
356 that almost-always works on other types. */
358 known_value (uintmax_t n
)
360 return n
< UINTMAX_MAX
- 1;
363 /* Like human_readable (N, BUF, human_output_opts, INPUT_UNITS, OUTPUT_UNITS),
366 - If NEGATIVE, then N represents a negative number,
367 expressed in two's complement.
368 - Otherwise, return "-" if N is unknown. */
371 df_readable (bool negative
, uintmax_t n
, char *buf
,
372 uintmax_t input_units
, uintmax_t output_units
)
374 if (! known_value (n
) && !negative
)
378 char *p
= human_readable (negative
? -n
: n
, buf
+ negative
,
379 human_output_opts
, input_units
, output_units
);
386 /* Logical equivalence */
387 #define LOG_EQ(a, b) (!(a) == !(b))
389 /* Add integral value while using uintmax_t for value part and separate
390 negation flag. It adds value of SRC and SRC_NEG to DEST and DEST_NEG.
391 The result will be in DEST and DEST_NEG. See df_readable to understand
392 how the negation flag is used. */
394 add_uint_with_neg_flag (uintmax_t *dest
, bool *dest_neg
,
395 uintmax_t src
, bool src_neg
)
397 if (LOG_EQ (*dest_neg
, src_neg
))
421 /* Return true if S ends in a string that may be a 36-byte UUID,
422 i.e., of the form HHHHHHHH-HHHH-HHHH-HHHH-HHHHHHHHHHHH, where
423 each H is an upper or lower case hexadecimal digit. */
424 static bool _GL_ATTRIBUTE_PURE
425 has_uuid_suffix (char const *s
)
427 size_t len
= strlen (s
);
429 && strspn (s
+ len
- 36, "-0123456789abcdefABCDEF") == 36);
432 /* Obtain a space listing for the disk device with absolute file name DISK.
433 If MOUNT_POINT is non-NULL, it is the name of the root of the
435 If STAT_FILE is non-null, it is the name of a file within the file
436 system that the user originally asked for; this provides better
437 diagnostics, and sometimes it provides better results on networked
438 file systems that give different free-space results depending on
439 where in the file system you probe.
440 If FSTYPE is non-NULL, it is the type of the file system on DISK.
441 If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may
442 not be able to produce statistics in this case.
443 ME_DUMMY and ME_REMOTE are the mount entry flags.
444 Caller must set PROCESS_ALL to true when iterating over all entries, as
445 when df is invoked with no non-option argument. See below for details. */
448 get_dev (char const *disk
, char const *mount_point
,
449 char const *stat_file
, char const *fstype
,
450 bool me_dummy
, bool me_remote
,
451 const struct fs_usage
*force_fsu
,
455 char buf
[LONGEST_HUMAN_READABLE
+ 2];
456 uintmax_t input_units
;
457 uintmax_t output_units
;
460 bool negate_available
;
461 uintmax_t available_to_root
;
468 if (me_remote
&& show_local_fs
)
471 if (me_dummy
&& !show_all_fs
&& !show_listed_fs
)
474 if (!selected_fstype (fstype
) || excluded_fstype (fstype
))
477 /* If MOUNT_POINT is NULL, then the file system is not mounted, and this
478 program reports on the file system that the special file is on.
479 It would be better to report on the unmounted file system,
480 but statfs doesn't do that on most systems. */
482 stat_file
= mount_point
? mount_point
: disk
;
486 else if (get_fs_usage (stat_file
, disk
, &fsu
))
488 error (0, errno
, "%s", quote (stat_file
));
489 exit_status
= EXIT_FAILURE
;
493 if (fsu
.fsu_blocks
== 0 && !show_all_fs
&& !show_listed_fs
)
496 if (! file_systems_processed
)
498 file_systems_processed
= true;
505 disk
= "-"; /* unknown */
507 char *dev_name
= xstrdup (disk
);
510 /* On some systems, dev_name is a long-named symlink like
511 /dev/disk/by-uuid/828fc648-9f30-43d8-a0b1-f7196a2edb66 pointing to a
512 much shorter and more useful name like /dev/sda1. It may also look
513 like /dev/mapper/luks-828fc648-9f30-43d8-a0b1-f7196a2edb66 and point to
514 /dev/dm-0. When process_all is true and dev_name is a symlink whose
515 name ends with a UUID use the resolved name instead. */
517 && has_uuid_suffix (dev_name
)
518 && (resolved_dev
= canonicalize_filename_mode (dev_name
, CAN_EXISTING
)))
521 dev_name
= resolved_dev
;
525 fstype
= "-"; /* unknown */
529 input_units
= output_units
= 1;
530 total
= fsu
.fsu_files
;
531 available
= fsu
.fsu_ffree
;
532 negate_available
= false;
533 available_to_root
= available
;
535 if (known_value (total
))
536 grand_fsu
.fsu_files
+= total
;
537 if (known_value (available
))
538 grand_fsu
.fsu_ffree
+= available
;
542 input_units
= fsu
.fsu_blocksize
;
543 output_units
= output_block_size
;
544 total
= fsu
.fsu_blocks
;
545 available
= fsu
.fsu_bavail
;
546 negate_available
= (fsu
.fsu_bavail_top_bit_set
547 && known_value (available
));
548 available_to_root
= fsu
.fsu_bfree
;
550 if (known_value (total
))
551 grand_fsu
.fsu_blocks
+= input_units
* total
;
552 if (known_value (available_to_root
))
553 grand_fsu
.fsu_bfree
+= input_units
* available_to_root
;
554 if (known_value (available
))
555 add_uint_with_neg_flag (&grand_fsu
.fsu_bavail
,
556 &grand_fsu
.fsu_bavail_top_bit_set
,
557 input_units
* available
, negate_available
);
562 if (known_value (total
) && known_value (available_to_root
))
564 used
= total
- available_to_root
;
565 negate_used
= (total
< available_to_root
);
568 for (field
= 0; field
< NFIELDS
; field
++)
577 cell
= print_type
? xstrdup (fstype
) : NULL
;
581 cell
= xstrdup (df_readable (false, total
, buf
,
582 input_units
, output_units
));
585 cell
= xstrdup (df_readable (negate_used
, used
, buf
,
586 input_units
, output_units
));
589 cell
= xstrdup (df_readable (negate_available
, available
, buf
,
590 input_units
, output_units
));
594 if (! known_value (used
) || ! known_value (available
))
596 else if (!negate_used
597 && used
<= TYPE_MAXIMUM (uintmax_t) / 100
598 && used
+ available
!= 0
599 && (used
+ available
< used
) == negate_available
)
601 uintmax_t u100
= used
* 100;
602 uintmax_t nonroot_total
= used
+ available
;
603 pct
= u100
/ nonroot_total
+ (u100
% nonroot_total
!= 0);
607 /* The calculation cannot be done easily with integer
608 arithmetic. Fall back on floating point. This can suffer
609 from minor rounding errors, but doing it exactly requires
610 multiple precision arithmetic, and it's not worth the
612 double u
= negate_used
? - (double) - used
: used
;
613 double a
= negate_available
? - (double) - available
: available
;
614 double nonroot_total
= u
+ a
;
617 long int lipct
= pct
= u
* 100 / nonroot_total
;
620 /* Like `pct = ceil (dpct);', but avoid ceil so that
621 the math library needn't be linked. */
622 if (ipct
- 1 < pct
&& pct
<= ipct
+ 1)
623 pct
= ipct
+ (ipct
< pct
);
629 if (asprintf (&cell
, "%.0f%%", pct
) == -1)
643 #ifdef HIDE_AUTOMOUNT_PREFIX
644 /* Don't print the first directory name in MOUNT_POINT if it's an
645 artifact of an automounter. This is a bit too aggressive to be
647 if (STRNCMP_LIT (mount_point
, "/auto/") == 0)
649 else if (STRNCMP_LIT (mount_point
, "/tmp_mnt/") == 0)
652 cell
= xstrdup (mount_point
);
659 assert (!"unhandled field");
663 widths
[field
] = MAX (widths
[field
], mbswidth (cell
, 0));
664 table
[nrows
-1][field
] = cell
;
668 /* If DISK corresponds to a mount point, show its usage
669 and return true. Otherwise, return false. */
671 get_disk (char const *disk
)
673 struct mount_entry
const *me
;
674 struct mount_entry
const *best_match
= NULL
;
676 for (me
= mount_list
; me
; me
= me
->me_next
)
677 if (STREQ (disk
, me
->me_devname
))
682 get_dev (best_match
->me_devname
, best_match
->me_mountdir
, NULL
,
683 best_match
->me_type
, best_match
->me_dummy
,
684 best_match
->me_remote
, NULL
, false);
691 /* Figure out which device file or directory POINT is mounted on
692 and show its disk usage.
693 STATP must be the result of `stat (POINT, STATP)'. */
695 get_point (const char *point
, const struct stat
*statp
)
697 struct stat disk_stats
;
698 struct mount_entry
*me
;
699 struct mount_entry
const *best_match
= NULL
;
701 /* Calculate the real absolute file name for POINT, and use that to find
702 the mount point. This avoids statting unavailable mount points,
703 which can hang df. */
704 char *resolved
= canonicalize_file_name (point
);
705 if (resolved
&& resolved
[0] == '/')
707 size_t resolved_len
= strlen (resolved
);
708 size_t best_match_len
= 0;
710 for (me
= mount_list
; me
; me
= me
->me_next
)
711 if (!STREQ (me
->me_type
, "lofs")
712 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
714 size_t len
= strlen (me
->me_mountdir
);
715 if (best_match_len
<= len
&& len
<= resolved_len
716 && (len
== 1 /* root file system */
717 || ((len
== resolved_len
|| resolved
[len
] == '/')
718 && STREQ_LEN (me
->me_mountdir
, resolved
, len
))))
721 best_match_len
= len
;
727 && (stat (best_match
->me_mountdir
, &disk_stats
) != 0
728 || disk_stats
.st_dev
!= statp
->st_dev
))
732 for (me
= mount_list
; me
; me
= me
->me_next
)
734 if (me
->me_dev
== (dev_t
) -1)
736 if (stat (me
->me_mountdir
, &disk_stats
) == 0)
737 me
->me_dev
= disk_stats
.st_dev
;
740 /* Report only I/O errors. Other errors might be
741 caused by shadowed mount points, which means POINT
742 can't possibly be on this file system. */
745 error (0, errno
, "%s", quote (me
->me_mountdir
));
746 exit_status
= EXIT_FAILURE
;
749 /* So we won't try and fail repeatedly. */
750 me
->me_dev
= (dev_t
) -2;
754 if (statp
->st_dev
== me
->me_dev
755 && !STREQ (me
->me_type
, "lofs")
756 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
758 /* Skip bogus mtab entries. */
759 if (stat (me
->me_mountdir
, &disk_stats
) != 0
760 || disk_stats
.st_dev
!= me
->me_dev
)
761 me
->me_dev
= (dev_t
) -2;
768 get_dev (best_match
->me_devname
, best_match
->me_mountdir
, point
,
769 best_match
->me_type
, best_match
->me_dummy
, best_match
->me_remote
,
773 /* We couldn't find the mount entry corresponding to POINT. Go ahead and
774 print as much info as we can; methods that require the device to be
775 present will fail at a later point. */
777 /* Find the actual mount point. */
778 char *mp
= find_mount_point (point
, statp
);
781 get_dev (NULL
, mp
, NULL
, NULL
, false, false, NULL
, false);
787 /* Determine what kind of node NAME is and show the disk usage
788 for it. STATP is the results of `stat' on NAME. */
791 get_entry (char const *name
, struct stat
const *statp
)
793 if ((S_ISBLK (statp
->st_mode
) || S_ISCHR (statp
->st_mode
))
797 get_point (name
, statp
);
800 /* Show all mounted file systems, except perhaps those that are of
801 an unselected type or are empty. */
804 get_all_entries (void)
806 struct mount_entry
*me
;
808 for (me
= mount_list
; me
; me
= me
->me_next
)
809 get_dev (me
->me_devname
, me
->me_mountdir
, NULL
, me
->me_type
,
810 me
->me_dummy
, me
->me_remote
, NULL
, true);
813 /* Add FSTYPE to the list of file system types to display. */
816 add_fs_type (const char *fstype
)
818 struct fs_type_list
*fsp
;
820 fsp
= xmalloc (sizeof *fsp
);
821 fsp
->fs_name
= (char *) fstype
;
822 fsp
->fs_next
= fs_select_list
;
823 fs_select_list
= fsp
;
826 /* Add FSTYPE to the list of file system types to be omitted. */
829 add_excluded_fs_type (const char *fstype
)
831 struct fs_type_list
*fsp
;
833 fsp
= xmalloc (sizeof *fsp
);
834 fsp
->fs_name
= (char *) fstype
;
835 fsp
->fs_next
= fs_exclude_list
;
836 fs_exclude_list
= fsp
;
842 if (status
!= EXIT_SUCCESS
)
846 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name
);
848 Show information about the file system on which each FILE resides,\n\
849 or all file systems by default.\n\
853 Mandatory arguments to long options are mandatory for short options too.\n\
856 -a, --all include dummy file systems\n\
857 -B, --block-size=SIZE scale sizes by SIZE before printing them. E.g.,\n\
858 `-BM' prints sizes in units of 1,048,576 bytes.\n\
859 See SIZE format below.\n\
860 --total produce a grand total\n\
861 -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\
863 -H, --si likewise, but use powers of 1000 not 1024\n\
866 -i, --inodes list inode information instead of block usage\n\
867 -k like --block-size=1K\n\
868 -l, --local limit listing to local file systems\n\
869 --no-sync do not invoke sync before getting usage info (default)\
873 -P, --portability use the POSIX output format\n\
874 --sync invoke sync before getting usage info\n\
875 -t, --type=TYPE limit listing to file systems of type TYPE\n\
876 -T, --print-type print file system type\n\
877 -x, --exclude-type=TYPE limit listing to file systems not of type TYPE\n\
880 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
881 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
882 emit_blocksize_note ("DF");
884 emit_ancillary_info ();
890 main (int argc
, char **argv
)
892 struct stat
*stats
IF_LINT ( = 0);
894 initialize_main (&argc
, &argv
);
895 set_program_name (argv
[0]);
896 setlocale (LC_ALL
, "");
897 bindtextdomain (PACKAGE
, LOCALEDIR
);
898 textdomain (PACKAGE
);
900 atexit (close_stdout
);
902 fs_select_list
= NULL
;
903 fs_exclude_list
= NULL
;
904 inode_format
= false;
906 show_listed_fs
= false;
907 human_output_opts
= -1;
909 file_systems_processed
= false;
910 posix_format
= false;
911 exit_status
= EXIT_SUCCESS
;
912 print_grand_total
= false;
913 grand_fsu
.fsu_blocksize
= 1;
918 int c
= getopt_long (argc
, argv
, "aB:iF:hHklmPTt:vx:", long_options
,
930 enum strtol_error e
= human_options (optarg
, &human_output_opts
,
933 xstrtol_fatal (e
, oi
, c
, long_options
, optarg
);
940 human_output_opts
= human_autoscale
| human_SI
| human_base_1024
;
941 output_block_size
= 1;
944 human_output_opts
= human_autoscale
| human_SI
;
945 output_block_size
= 1;
948 human_output_opts
= 0;
949 output_block_size
= 1024;
952 show_local_fs
= true;
954 case 'm': /* obsolescent */
955 human_output_opts
= 0;
956 output_block_size
= 1024 * 1024;
968 require_sync
= false;
972 /* Accept -F as a synonym for -t for compatibility with Solaris. */
974 add_fs_type (optarg
);
977 case 'v': /* For SysV compatibility. */
981 add_excluded_fs_type (optarg
);
985 print_grand_total
= true;
988 case_GETOPT_HELP_CHAR
;
989 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
992 usage (EXIT_FAILURE
);
996 if (human_output_opts
== -1)
1000 human_output_opts
= 0;
1001 output_block_size
= (getenv ("POSIXLY_CORRECT") ? 512 : 1024);
1004 human_options (getenv ("DF_BLOCK_SIZE"),
1005 &human_output_opts
, &output_block_size
);
1009 header_mode
= INODES_MODE
;
1010 else if (human_output_opts
& human_autoscale
)
1011 header_mode
= HUMAN_MODE
;
1012 else if (posix_format
)
1013 header_mode
= POSIX_MODE
;
1015 /* Fail if the same file system type was both selected and excluded. */
1018 struct fs_type_list
*fs_incl
;
1019 for (fs_incl
= fs_select_list
; fs_incl
; fs_incl
= fs_incl
->fs_next
)
1021 struct fs_type_list
*fs_excl
;
1022 for (fs_excl
= fs_exclude_list
; fs_excl
; fs_excl
= fs_excl
->fs_next
)
1024 if (STREQ (fs_incl
->fs_name
, fs_excl
->fs_name
))
1027 _("file system type %s both selected and excluded"),
1028 quote (fs_incl
->fs_name
));
1035 exit (EXIT_FAILURE
);
1042 /* Open each of the given entries to make sure any corresponding
1043 partition is automounted. This must be done before reading the
1044 file system table. */
1045 stats
= xnmalloc (argc
- optind
, sizeof *stats
);
1046 for (i
= optind
; i
< argc
; ++i
)
1048 /* Prefer to open with O_NOCTTY and use fstat, but fall back
1049 on using "stat", in case the file is unreadable. */
1050 int fd
= open (argv
[i
], O_RDONLY
| O_NOCTTY
);
1051 if ((fd
< 0 || fstat (fd
, &stats
[i
- optind
]))
1052 && stat (argv
[i
], &stats
[i
- optind
]))
1054 error (0, errno
, "%s", quote (argv
[i
]));
1055 exit_status
= EXIT_FAILURE
;
1064 read_file_system_list ((fs_select_list
!= NULL
1065 || fs_exclude_list
!= NULL
1069 if (mount_list
== NULL
)
1071 /* Couldn't read the table of mounted file systems.
1072 Fail if df was invoked with no file name arguments;
1073 Otherwise, merely give a warning and proceed. */
1074 int status
= (optind
< argc
? 0 : EXIT_FAILURE
);
1075 const char *warning
= (optind
< argc
? _("Warning: ") : "");
1076 error (status
, errno
, "%s%s", warning
,
1077 _("cannot read table of mounted file systems"));
1087 /* Display explicitly requested empty file systems. */
1088 show_listed_fs
= true;
1090 for (i
= optind
; i
< argc
; ++i
)
1092 get_entry (argv
[i
], &stats
[i
- optind
]);
1097 if (print_grand_total
)
1100 grand_fsu
.fsu_blocks
= 1;
1101 get_dev ("total", NULL
, NULL
, NULL
, false, false, &grand_fsu
, false);
1106 if (! file_systems_processed
)
1107 error (EXIT_FAILURE
, 0, _("no file systems processed"));