1 /* df - summarize free disk space
2 Copyright (C) 1991-2013 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 /* Filled with device numbers of examined file systems to avoid
47 duplicities in output. */
51 struct mount_entry
*me
;
55 /* If true, show even file systems with zero size or
56 uninteresting types. */
57 static bool show_all_fs
;
59 /* If true, show only local file systems. */
60 static bool show_local_fs
;
62 /* If true, output data for each file system corresponding to a
63 command line argument -- even if it's a dummy (automounter) entry. */
64 static bool show_listed_fs
;
66 /* Human-readable options for output. */
67 static int human_output_opts
;
69 /* The units to use when printing sizes. */
70 static uintmax_t output_block_size
;
72 /* True if a file system has been processed for output. */
73 static bool file_systems_processed
;
75 /* If true, invoke the 'sync' system call before getting any usage data.
76 Using this option can make df very slow, especially with many or very
77 busy disks. Note that this may make a difference on some systems --
78 SunOS 4.1.3, for one. It is *not* necessary on GNU/Linux. */
79 static bool require_sync
;
81 /* Desired exit status. */
82 static int exit_status
;
84 /* A file system type to display. */
89 struct fs_type_list
*fs_next
;
92 /* Linked list of file system types to display.
93 If 'fs_select_list' is NULL, list all types.
94 This table is generated dynamically from command-line options,
95 rather than hardcoding into the program what it thinks are the
96 valid file system types; let the user specify any file system type
97 they want to, and if there are any file systems of that type, they
100 Some file system types:
101 4.2 4.3 ufs nfs swap ignore io vm efs dbg */
103 static struct fs_type_list
*fs_select_list
;
105 /* Linked list of file system types to omit.
106 If the list is empty, don't exclude any types. */
108 static struct fs_type_list
*fs_exclude_list
;
110 /* Linked list of mounted file systems. */
111 static struct mount_entry
*mount_list
;
113 /* If true, print file system type as well. */
114 static bool print_type
;
116 /* If true, print a grand total at the end. */
117 static bool print_grand_total
;
119 /* Grand total data. */
120 static struct fs_usage grand_fsu
;
131 static int header_mode
= DEFAULT_MODE
;
133 /* Displayable fields. */
136 SOURCE_FIELD
, /* file system */
137 FSTYPE_FIELD
, /* FS type */
138 SIZE_FIELD
, /* FS size */
139 USED_FIELD
, /* FS size used */
140 AVAIL_FIELD
, /* FS size available */
141 PCENT_FIELD
, /* percent used */
142 ITOTAL_FIELD
, /* inode total */
143 IUSED_FIELD
, /* inodes used */
144 IAVAIL_FIELD
, /* inodes available */
145 IPCENT_FIELD
, /* inodes used in percent */
146 TARGET_FIELD
/* mount point */
149 /* Flag if a field contains a block, an inode or another value. */
152 BLOCK_FLD
, /* Block values field */
153 INODE_FLD
, /* Inode values field */
154 OTHER_FLD
/* Neutral field, e.g. target */
157 /* Attributes of a display field. */
160 display_field_t field
;
162 field_type_t field_type
;
163 const char *caption
;/* NULL means to use the default header of this field. */
164 size_t width
; /* Auto adjusted (up) widths used to align columns. */
165 mbs_align_t align
; /* Alignment for this field. */
169 /* Header strings, minimum width and alignment for the above fields. */
170 static struct field_data_t field_data
[] = {
171 [SOURCE_FIELD
] = { SOURCE_FIELD
,
172 "source", OTHER_FLD
, N_("Filesystem"), 14, MBS_ALIGN_LEFT
, false },
174 [FSTYPE_FIELD
] = { FSTYPE_FIELD
,
175 "fstype", OTHER_FLD
, N_("Type"), 4, MBS_ALIGN_LEFT
, false },
177 [SIZE_FIELD
] = { SIZE_FIELD
,
178 "size", BLOCK_FLD
, N_("blocks"), 5, MBS_ALIGN_RIGHT
, false },
180 [USED_FIELD
] = { USED_FIELD
,
181 "used", BLOCK_FLD
, N_("Used"), 5, MBS_ALIGN_RIGHT
, false },
183 [AVAIL_FIELD
] = { AVAIL_FIELD
,
184 "avail", BLOCK_FLD
, N_("Available"), 5, MBS_ALIGN_RIGHT
, false },
186 [PCENT_FIELD
] = { PCENT_FIELD
,
187 "pcent", BLOCK_FLD
, N_("Use%"), 4, MBS_ALIGN_RIGHT
, false },
189 [ITOTAL_FIELD
] = { ITOTAL_FIELD
,
190 "itotal", INODE_FLD
, N_("Inodes"), 5, MBS_ALIGN_RIGHT
, false },
192 [IUSED_FIELD
] = { IUSED_FIELD
,
193 "iused", INODE_FLD
, N_("IUsed"), 5, MBS_ALIGN_RIGHT
, false },
195 [IAVAIL_FIELD
] = { IAVAIL_FIELD
,
196 "iavail", INODE_FLD
, N_("IFree"), 5, MBS_ALIGN_RIGHT
, false },
198 [IPCENT_FIELD
] = { IPCENT_FIELD
,
199 "ipcent", INODE_FLD
, N_("IUse%"), 4, MBS_ALIGN_RIGHT
, false },
201 [TARGET_FIELD
] = { TARGET_FIELD
,
202 "target", OTHER_FLD
, N_("Mounted on"), 0, MBS_ALIGN_LEFT
, false }
205 static char const *all_args_string
=
206 "source,fstype,itotal,iused,iavail,ipcent,size,used,avail,pcent,target";
208 /* Storage for the definition of output columns. */
209 static struct field_data_t
**columns
;
211 /* The current number of output columns. */
212 static size_t ncolumns
;
215 struct field_values_t
217 uintmax_t input_units
;
218 uintmax_t output_units
;
221 bool negate_available
;
222 uintmax_t available_to_root
;
227 /* Storage for pointers for each string (cell of table). */
228 static char ***table
;
230 /* The current number of processed rows (including header). */
233 /* For long options that have no equivalent short option, use a
234 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
237 NO_SYNC_OPTION
= CHAR_MAX
+ 1,
241 MEGABYTES_OPTION
/* FIXME: remove long opt in Aug 2013 */
244 static struct option
const long_options
[] =
246 {"all", no_argument
, NULL
, 'a'},
247 {"block-size", required_argument
, NULL
, 'B'},
248 {"inodes", no_argument
, NULL
, 'i'},
249 {"human-readable", no_argument
, NULL
, 'h'},
250 {"si", no_argument
, NULL
, 'H'},
251 {"local", no_argument
, NULL
, 'l'},
252 {"megabytes", no_argument
, NULL
, MEGABYTES_OPTION
}, /* obsolescent, */
253 {"output", optional_argument
, NULL
, OUTPUT_OPTION
},
254 {"portability", no_argument
, NULL
, 'P'},
255 {"print-type", no_argument
, NULL
, 'T'},
256 {"sync", no_argument
, NULL
, SYNC_OPTION
},
257 {"no-sync", no_argument
, NULL
, NO_SYNC_OPTION
},
258 {"total", no_argument
, NULL
, TOTAL_OPTION
},
259 {"type", required_argument
, NULL
, 't'},
260 {"exclude-type", required_argument
, NULL
, 'x'},
261 {GETOPT_HELP_OPTION_DECL
},
262 {GETOPT_VERSION_OPTION_DECL
},
266 /* Replace problematic chars with '?'.
267 Since only control characters are currently considered,
268 this should work in all encodings. */
271 hide_problematic_chars (char *cell
)
276 if (iscntrl (to_uchar (*p
)))
283 /* Dynamically allocate a row of pointers in TABLE, which
284 can then be accessed with standard 2D array notation. */
287 alloc_table_row (void)
290 table
= xnrealloc (table
, nrows
, sizeof (char *));
291 table
[nrows
- 1] = xnmalloc (ncolumns
, sizeof (char *));
294 /* Output each cell in the table, accounting for the
295 alignment and max width of each column. */
302 for (row
= 0; row
< nrows
; row
++)
305 for (col
= 0; col
< ncolumns
; col
++)
307 char *cell
= table
[row
][col
];
309 /* Note the SOURCE_FIELD used to be displayed on it's own line
310 if (!posix_format && mbswidth (cell) > 20), but that
311 functionality was probably more problematic than helpful,
312 hence changed in commit v8.10-40-g99679ff. */
317 if (col
== ncolumns
- 1) /* The last one. */
318 flags
= MBA_NO_RIGHT_PAD
;
320 size_t width
= columns
[col
]->width
;
321 cell
= ambsalign (cell
, &width
, columns
[col
]->align
, flags
);
322 /* When ambsalign fails, output unaligned data. */
323 fputs (cell
? cell
: table
[row
][col
], stdout
);
326 IF_LINT (free (table
[row
][col
]));
329 IF_LINT (free (table
[row
]));
332 IF_LINT (free (table
));
335 /* Dynamically allocate a struct field_t in COLUMNS, which
336 can then be accessed with standard array notation. */
339 alloc_field (int f
, const char *c
)
342 columns
= xnrealloc (columns
, ncolumns
, sizeof (struct field_data_t
*));
343 columns
[ncolumns
- 1] = &field_data
[f
];
345 columns
[ncolumns
- 1]->caption
= c
;
347 if (field_data
[f
].used
)
348 assert (!"field used");
350 /* Mark field as used. */
351 field_data
[f
].used
= true;
355 /* Given a string, ARG, containing a comma-separated list of arguments
356 to the --output option, add the appropriate fields to columns. */
358 decode_output_arg (char const *arg
)
360 char *arg_writable
= xstrdup (arg
);
361 char *s
= arg_writable
;
364 /* find next comma */
365 char *comma
= strchr (s
, ',');
367 /* If we found a comma, put a NUL in its place and advance. */
372 display_field_t field
= -1;
373 for (unsigned int i
= 0; i
< ARRAY_CARDINALITY (field_data
); i
++)
375 if (STREQ (field_data
[i
].arg
, s
))
383 error (0, 0, _("option --output: field '%s' unknown"), s
);
384 usage (EXIT_FAILURE
);
387 if (field_data
[field
].used
)
389 /* Prevent the fields from being used more than once. */
390 error (0, 0, _("option --output: field '%s' used more than once"),
391 field_data
[field
].arg
);
392 usage (EXIT_FAILURE
);
406 alloc_field (field
, NULL
);
410 alloc_field (field
, N_("Size"));
414 alloc_field (field
, N_("Avail"));
418 assert (!"invalid field");
427 /* Get the appropriate columns for the mode. */
429 get_field_list (void)
434 alloc_field (SOURCE_FIELD
, NULL
);
436 alloc_field (FSTYPE_FIELD
, NULL
);
437 alloc_field (SIZE_FIELD
, NULL
);
438 alloc_field (USED_FIELD
, NULL
);
439 alloc_field (AVAIL_FIELD
, NULL
);
440 alloc_field (PCENT_FIELD
, NULL
);
441 alloc_field (TARGET_FIELD
, NULL
);
445 alloc_field (SOURCE_FIELD
, NULL
);
447 alloc_field (FSTYPE_FIELD
, NULL
);
449 alloc_field (SIZE_FIELD
, N_("Size"));
450 alloc_field (USED_FIELD
, NULL
);
451 alloc_field (AVAIL_FIELD
, N_("Avail"));
452 alloc_field (PCENT_FIELD
, NULL
);
453 alloc_field (TARGET_FIELD
, NULL
);
457 alloc_field (SOURCE_FIELD
, NULL
);
459 alloc_field (FSTYPE_FIELD
, NULL
);
460 alloc_field (ITOTAL_FIELD
, NULL
);
461 alloc_field (IUSED_FIELD
, NULL
);
462 alloc_field (IAVAIL_FIELD
, NULL
);
463 alloc_field (IPCENT_FIELD
, NULL
);
464 alloc_field (TARGET_FIELD
, NULL
);
468 alloc_field (SOURCE_FIELD
, NULL
);
470 alloc_field (FSTYPE_FIELD
, NULL
);
471 alloc_field (SIZE_FIELD
, NULL
);
472 alloc_field (USED_FIELD
, NULL
);
473 alloc_field (AVAIL_FIELD
, NULL
);
474 alloc_field (PCENT_FIELD
, N_("Capacity"));
475 alloc_field (TARGET_FIELD
, NULL
);
481 /* Add all fields if --output was given without a field list. */
482 decode_output_arg (all_args_string
);
487 assert (!"invalid header_mode");
491 /* Obtain the appropriate header entries. */
500 for (col
= 0; col
< ncolumns
; col
++)
503 char const *header
= _(columns
[col
]->caption
);
505 if (columns
[col
]->field
== SIZE_FIELD
506 && (header_mode
== DEFAULT_MODE
507 || (header_mode
== OUTPUT_MODE
508 && !(human_output_opts
& human_autoscale
))))
510 char buf
[LONGEST_HUMAN_READABLE
+ 1];
512 int opts
= (human_suppress_point_zero
513 | human_autoscale
| human_SI
515 & (human_group_digits
| human_base_1024
| human_B
)));
517 /* Prefer the base that makes the human-readable value more exact,
518 if there is a difference. */
520 uintmax_t q1000
= output_block_size
;
521 uintmax_t q1024
= output_block_size
;
522 bool divisible_by_1000
;
523 bool divisible_by_1024
;
527 divisible_by_1000
= q1000
% 1000 == 0; q1000
/= 1000;
528 divisible_by_1024
= q1024
% 1024 == 0; q1024
/= 1024;
530 while (divisible_by_1000
& divisible_by_1024
);
532 if (divisible_by_1000
< divisible_by_1024
)
533 opts
|= human_base_1024
;
534 if (divisible_by_1024
< divisible_by_1000
)
535 opts
&= ~human_base_1024
;
536 if (! (opts
& human_base_1024
))
539 char *num
= human_readable (output_block_size
, buf
, opts
, 1, 1);
541 /* Reset the header back to the default in OUTPUT_MODE. */
542 header
= _("blocks");
544 /* TRANSLATORS: this is the "1K-blocks" header in "df" output. */
545 if (asprintf (&cell
, _("%s-%s"), num
, header
) == -1)
548 else if (header_mode
== POSIX_MODE
&& columns
[col
]->field
== SIZE_FIELD
)
550 char buf
[INT_BUFSIZE_BOUND (uintmax_t)];
551 char *num
= umaxtostr (output_block_size
, buf
);
553 /* TRANSLATORS: this is the "1024-blocks" header in "df -P". */
554 if (asprintf (&cell
, _("%s-%s"), num
, header
) == -1)
558 cell
= strdup (header
);
563 hide_problematic_chars (cell
);
565 table
[nrows
- 1][col
] = cell
;
567 columns
[col
]->width
= MAX (columns
[col
]->width
, mbswidth (cell
, 0));
571 /* Is FSTYPE a type of file system that should be listed? */
573 static bool _GL_ATTRIBUTE_PURE
574 selected_fstype (const char *fstype
)
576 const struct fs_type_list
*fsp
;
578 if (fs_select_list
== NULL
|| fstype
== NULL
)
580 for (fsp
= fs_select_list
; fsp
; fsp
= fsp
->fs_next
)
581 if (STREQ (fstype
, fsp
->fs_name
))
586 /* Is FSTYPE a type of file system that should be omitted? */
588 static bool _GL_ATTRIBUTE_PURE
589 excluded_fstype (const char *fstype
)
591 const struct fs_type_list
*fsp
;
593 if (fs_exclude_list
== NULL
|| fstype
== NULL
)
595 for (fsp
= fs_exclude_list
; fsp
; fsp
= fsp
->fs_next
)
596 if (STREQ (fstype
, fsp
->fs_name
))
601 /* Filter mount list by skipping duplicate entries.
602 In the case of duplicities - based on to the device number - the mount entry
603 with a '/' in its me_devname (i.e. not pseudo name like tmpfs) wins.
604 If both have a real devname (e.g. bind mounts), then that with the shorter
608 filter_mount_list (void)
610 struct mount_entry
*me
;
612 /* Store of already-processed device numbers. */
613 struct devlist
*devlist_head
= NULL
;
615 /* Sort all 'wanted' entries into the list devlist_head. */
616 for (me
= mount_list
; me
;)
619 struct devlist
*devlist
;
620 struct mount_entry
*discard_me
= NULL
;
622 if (-1 == stat (me
->me_mountdir
, &buf
))
624 /* Stat failed - add ME to be able to complain about it later. */
625 buf
.st_dev
= me
->me_dev
;
629 /* If the device name is a real path name ... */
630 if (strchr (me
->me_devname
, '/'))
632 /* ... try to find its device number in the devlist. */
633 for (devlist
= devlist_head
; devlist
; devlist
= devlist
->next
)
634 if (devlist
->dev_num
== buf
.st_dev
)
641 /* Let the shorter mountdir win. */
642 if (! strchr (devlist
->me
->me_devname
, '/')
643 || (strlen (devlist
->me
->me_mountdir
)
644 > strlen (me
->me_mountdir
)))
646 discard_me
= devlist
->me
;
656 free_mount_entry (discard_me
);
660 /* Add the device number to the global list devlist. */
661 devlist
= xmalloc (sizeof *devlist
);
663 devlist
->dev_num
= buf
.st_dev
;
664 devlist
->next
= devlist_head
;
665 devlist_head
= devlist
;
671 /* Finally rebuild the mount_list from the devlist. */
675 /* Add the mount entry. */
676 me
= devlist_head
->me
;
677 me
->me_next
= mount_list
;
679 /* Free devlist entry and advance. */
680 struct devlist
*devlist
= devlist_head
->next
;
682 devlist_head
= devlist
;
686 /* Return true if N is a known integer value. On many file systems,
687 UINTMAX_MAX represents an unknown value; on AIX, UINTMAX_MAX - 1
688 represents unknown. Use a rule that works on AIX file systems, and
689 that almost-always works on other types. */
691 known_value (uintmax_t n
)
693 return n
< UINTMAX_MAX
- 1;
696 /* Like human_readable (N, BUF, human_output_opts, INPUT_UNITS, OUTPUT_UNITS),
699 - If NEGATIVE, then N represents a negative number,
700 expressed in two's complement.
701 - Otherwise, return "-" if N is unknown. */
704 df_readable (bool negative
, uintmax_t n
, char *buf
,
705 uintmax_t input_units
, uintmax_t output_units
)
707 if (! known_value (n
) && !negative
)
711 char *p
= human_readable (negative
? -n
: n
, buf
+ negative
,
712 human_output_opts
, input_units
, output_units
);
719 /* Logical equivalence */
720 #define LOG_EQ(a, b) (!(a) == !(b))
722 /* Add integral value while using uintmax_t for value part and separate
723 negation flag. It adds value of SRC and SRC_NEG to DEST and DEST_NEG.
724 The result will be in DEST and DEST_NEG. See df_readable to understand
725 how the negation flag is used. */
727 add_uint_with_neg_flag (uintmax_t *dest
, bool *dest_neg
,
728 uintmax_t src
, bool src_neg
)
730 if (LOG_EQ (*dest_neg
, src_neg
))
754 /* Return true if S ends in a string that may be a 36-byte UUID,
755 i.e., of the form HHHHHHHH-HHHH-HHHH-HHHH-HHHHHHHHHHHH, where
756 each H is an upper or lower case hexadecimal digit. */
757 static bool _GL_ATTRIBUTE_PURE
758 has_uuid_suffix (char const *s
)
760 size_t len
= strlen (s
);
762 && strspn (s
+ len
- 36, "-0123456789abcdefABCDEF") == 36);
765 /* Obtain the block values BV and inode values IV
766 from the file system usage FSU. */
768 get_field_values (struct field_values_t
*bv
,
769 struct field_values_t
*iv
,
770 const struct fs_usage
*fsu
)
773 iv
->input_units
= iv
->output_units
= 1;
774 iv
->total
= fsu
->fsu_files
;
775 iv
->available
= iv
->available_to_root
= fsu
->fsu_ffree
;
776 iv
->negate_available
= false;
778 iv
->used
= UINTMAX_MAX
;
779 iv
->negate_used
= false;
780 if (known_value (iv
->total
) && known_value (iv
->available_to_root
))
782 iv
->used
= iv
->total
- iv
->available_to_root
;
783 iv
->negate_used
= (iv
->total
< iv
->available_to_root
);
787 bv
->input_units
= fsu
->fsu_blocksize
;
788 bv
->output_units
= output_block_size
;
789 bv
->total
= fsu
->fsu_blocks
;
790 bv
->available
= fsu
->fsu_bavail
;
791 bv
->available_to_root
= fsu
->fsu_bfree
;
792 bv
->negate_available
= (fsu
->fsu_bavail_top_bit_set
793 && known_value (fsu
->fsu_bavail
));
795 bv
->used
= UINTMAX_MAX
;
796 bv
->negate_used
= false;
797 if (known_value (bv
->total
) && known_value (bv
->available_to_root
))
799 bv
->used
= bv
->total
- bv
->available_to_root
;
800 bv
->negate_used
= (bv
->total
< bv
->available_to_root
);
804 /* Add block and inode values to grand total. */
806 add_to_grand_total (struct field_values_t
*bv
, struct field_values_t
*iv
)
808 if (known_value (iv
->total
))
809 grand_fsu
.fsu_files
+= iv
->total
;
810 if (known_value (iv
->available
))
811 grand_fsu
.fsu_ffree
+= iv
->available
;
813 if (known_value (bv
->total
))
814 grand_fsu
.fsu_blocks
+= bv
->input_units
* bv
->total
;
815 if (known_value (bv
->available_to_root
))
816 grand_fsu
.fsu_bfree
+= bv
->input_units
* bv
->available_to_root
;
817 if (known_value (bv
->available
))
818 add_uint_with_neg_flag (&grand_fsu
.fsu_bavail
,
819 &grand_fsu
.fsu_bavail_top_bit_set
,
820 bv
->input_units
* bv
->available
,
821 bv
->negate_available
);
824 /* Obtain a space listing for the disk device with absolute file name DISK.
825 If MOUNT_POINT is non-NULL, it is the name of the root of the
827 If STAT_FILE is non-null, it is the name of a file within the file
828 system that the user originally asked for; this provides better
829 diagnostics, and sometimes it provides better results on networked
830 file systems that give different free-space results depending on
831 where in the file system you probe.
832 If FSTYPE is non-NULL, it is the type of the file system on DISK.
833 If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may
834 not be able to produce statistics in this case.
835 ME_DUMMY and ME_REMOTE are the mount entry flags.
836 Caller must set PROCESS_ALL to true when iterating over all entries, as
837 when df is invoked with no non-option argument. See below for details. */
840 get_dev (char const *disk
, char const *mount_point
,
841 char const *stat_file
, char const *fstype
,
842 bool me_dummy
, bool me_remote
,
843 const struct fs_usage
*force_fsu
,
846 if (me_remote
&& show_local_fs
)
849 if (me_dummy
&& !show_all_fs
&& !show_listed_fs
)
852 if (!selected_fstype (fstype
) || excluded_fstype (fstype
))
855 /* If MOUNT_POINT is NULL, then the file system is not mounted, and this
856 program reports on the file system that the special file is on.
857 It would be better to report on the unmounted file system,
858 but statfs doesn't do that on most systems. */
860 stat_file
= mount_point
? mount_point
: disk
;
865 else if (get_fs_usage (stat_file
, disk
, &fsu
))
867 error (0, errno
, "%s", quote (stat_file
));
868 exit_status
= EXIT_FAILURE
;
872 if (fsu
.fsu_blocks
== 0 && !show_all_fs
&& !show_listed_fs
)
876 file_systems_processed
= true;
881 disk
= "-"; /* unknown */
883 char *dev_name
= xstrdup (disk
);
886 /* On some systems, dev_name is a long-named symlink like
887 /dev/disk/by-uuid/828fc648-9f30-43d8-a0b1-f7196a2edb66 pointing to a
888 much shorter and more useful name like /dev/sda1. It may also look
889 like /dev/mapper/luks-828fc648-9f30-43d8-a0b1-f7196a2edb66 and point to
890 /dev/dm-0. When process_all is true and dev_name is a symlink whose
891 name ends with a UUID use the resolved name instead. */
893 && has_uuid_suffix (dev_name
)
894 && (resolved_dev
= canonicalize_filename_mode (dev_name
, CAN_EXISTING
)))
897 dev_name
= resolved_dev
;
901 fstype
= "-"; /* unknown */
903 struct field_values_t block_values
;
904 struct field_values_t inode_values
;
905 get_field_values (&block_values
, &inode_values
, &fsu
);
907 /* Add to grand total unless processing grand total line. */
908 if (print_grand_total
&& ! force_fsu
)
909 add_to_grand_total (&block_values
, &inode_values
);
912 for (col
= 0; col
< ncolumns
; col
++)
914 char buf
[LONGEST_HUMAN_READABLE
+ 2];
917 struct field_values_t
*v
;
918 switch (columns
[col
]->field_type
)
930 assert (!"bad field_type");
933 switch (columns
[col
]->field
)
936 cell
= xstrdup (dev_name
);
940 cell
= xstrdup (fstype
);
945 cell
= xstrdup (df_readable (false, v
->total
, buf
,
946 v
->input_units
, v
->output_units
));
951 cell
= xstrdup (df_readable (v
->negate_used
, v
->used
, buf
,
952 v
->input_units
, v
->output_units
));
957 cell
= xstrdup (df_readable (v
->negate_available
, v
->available
, buf
,
958 v
->input_units
, v
->output_units
));
965 if (! known_value (v
->used
) || ! known_value (v
->available
))
967 else if (!v
->negate_used
968 && v
->used
<= TYPE_MAXIMUM (uintmax_t) / 100
969 && v
->used
+ v
->available
!= 0
970 && (v
->used
+ v
->available
< v
->used
)
971 == v
->negate_available
)
973 uintmax_t u100
= v
->used
* 100;
974 uintmax_t nonroot_total
= v
->used
+ v
->available
;
975 pct
= u100
/ nonroot_total
+ (u100
% nonroot_total
!= 0);
979 /* The calculation cannot be done easily with integer
980 arithmetic. Fall back on floating point. This can suffer
981 from minor rounding errors, but doing it exactly requires
982 multiple precision arithmetic, and it's not worth the
984 double u
= v
->negate_used
? - (double) - v
->used
: v
->used
;
985 double a
= v
->negate_available
986 ? - (double) - v
->available
: v
->available
;
987 double nonroot_total
= u
+ a
;
990 long int lipct
= pct
= u
* 100 / nonroot_total
;
993 /* Like 'pct = ceil (dpct);', but avoid ceil so that
994 the math library needn't be linked. */
995 if (ipct
- 1 < pct
&& pct
<= ipct
+ 1)
996 pct
= ipct
+ (ipct
< pct
);
1002 if (asprintf (&cell
, "%.0f%%", pct
) == -1)
1006 cell
= strdup ("-");
1015 #ifdef HIDE_AUTOMOUNT_PREFIX
1016 /* Don't print the first directory name in MOUNT_POINT if it's an
1017 artifact of an automounter. This is a bit too aggressive to be
1019 if (STRNCMP_LIT (mount_point
, "/auto/") == 0)
1021 else if (STRNCMP_LIT (mount_point
, "/tmp_mnt/") == 0)
1024 cell
= xstrdup (mount_point
);
1028 assert (!"unhandled field");
1032 assert (!"empty cell");
1034 hide_problematic_chars (cell
);
1035 columns
[col
]->width
= MAX (columns
[col
]->width
, mbswidth (cell
, 0));
1036 table
[nrows
- 1][col
] = cell
;
1041 /* If DISK corresponds to a mount point, show its usage
1042 and return true. Otherwise, return false. */
1044 get_disk (char const *disk
)
1046 struct mount_entry
const *me
;
1047 struct mount_entry
const *best_match
= NULL
;
1049 for (me
= mount_list
; me
; me
= me
->me_next
)
1051 if (STREQ (disk
, me
->me_devname
))
1057 get_dev (best_match
->me_devname
, best_match
->me_mountdir
, NULL
,
1058 best_match
->me_type
, best_match
->me_dummy
,
1059 best_match
->me_remote
, NULL
, false);
1066 /* Figure out which device file or directory POINT is mounted on
1067 and show its disk usage.
1068 STATP must be the result of 'stat (POINT, STATP)'. */
1070 get_point (const char *point
, const struct stat
*statp
)
1072 struct stat disk_stats
;
1073 struct mount_entry
*me
;
1074 struct mount_entry
const *best_match
= NULL
;
1076 /* Calculate the real absolute file name for POINT, and use that to find
1077 the mount point. This avoids statting unavailable mount points,
1078 which can hang df. */
1079 char *resolved
= canonicalize_file_name (point
);
1080 if (resolved
&& resolved
[0] == '/')
1082 size_t resolved_len
= strlen (resolved
);
1083 size_t best_match_len
= 0;
1085 for (me
= mount_list
; me
; me
= me
->me_next
)
1087 if (!STREQ (me
->me_type
, "lofs")
1088 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
1090 size_t len
= strlen (me
->me_mountdir
);
1091 if (best_match_len
<= len
&& len
<= resolved_len
1092 && (len
== 1 /* root file system */
1093 || ((len
== resolved_len
|| resolved
[len
] == '/')
1094 && STREQ_LEN (me
->me_mountdir
, resolved
, len
))))
1097 best_match_len
= len
;
1104 && (stat (best_match
->me_mountdir
, &disk_stats
) != 0
1105 || disk_stats
.st_dev
!= statp
->st_dev
))
1109 for (me
= mount_list
; me
; me
= me
->me_next
)
1111 if (me
->me_dev
== (dev_t
) -1)
1113 if (stat (me
->me_mountdir
, &disk_stats
) == 0)
1114 me
->me_dev
= disk_stats
.st_dev
;
1117 /* Report only I/O errors. Other errors might be
1118 caused by shadowed mount points, which means POINT
1119 can't possibly be on this file system. */
1122 error (0, errno
, "%s", quote (me
->me_mountdir
));
1123 exit_status
= EXIT_FAILURE
;
1126 /* So we won't try and fail repeatedly. */
1127 me
->me_dev
= (dev_t
) -2;
1131 if (statp
->st_dev
== me
->me_dev
1132 && !STREQ (me
->me_type
, "lofs")
1133 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
1135 /* Skip bogus mtab entries. */
1136 if (stat (me
->me_mountdir
, &disk_stats
) != 0
1137 || disk_stats
.st_dev
!= me
->me_dev
)
1138 me
->me_dev
= (dev_t
) -2;
1145 get_dev (best_match
->me_devname
, best_match
->me_mountdir
, point
,
1146 best_match
->me_type
, best_match
->me_dummy
, best_match
->me_remote
,
1150 /* We couldn't find the mount entry corresponding to POINT. Go ahead and
1151 print as much info as we can; methods that require the device to be
1152 present will fail at a later point. */
1154 /* Find the actual mount point. */
1155 char *mp
= find_mount_point (point
, statp
);
1158 get_dev (NULL
, mp
, NULL
, NULL
, false, false, NULL
, false);
1164 /* Determine what kind of node NAME is and show the disk usage
1165 for it. STATP is the results of 'stat' on NAME. */
1168 get_entry (char const *name
, struct stat
const *statp
)
1170 if ((S_ISBLK (statp
->st_mode
) || S_ISCHR (statp
->st_mode
))
1174 get_point (name
, statp
);
1177 /* Show all mounted file systems, except perhaps those that are of
1178 an unselected type or are empty. */
1181 get_all_entries (void)
1183 struct mount_entry
*me
;
1186 filter_mount_list ();
1188 for (me
= mount_list
; me
; me
= me
->me_next
)
1189 get_dev (me
->me_devname
, me
->me_mountdir
, NULL
, me
->me_type
,
1190 me
->me_dummy
, me
->me_remote
, NULL
, true);
1193 /* Add FSTYPE to the list of file system types to display. */
1196 add_fs_type (const char *fstype
)
1198 struct fs_type_list
*fsp
;
1200 fsp
= xmalloc (sizeof *fsp
);
1201 fsp
->fs_name
= (char *) fstype
;
1202 fsp
->fs_next
= fs_select_list
;
1203 fs_select_list
= fsp
;
1206 /* Add FSTYPE to the list of file system types to be omitted. */
1209 add_excluded_fs_type (const char *fstype
)
1211 struct fs_type_list
*fsp
;
1213 fsp
= xmalloc (sizeof *fsp
);
1214 fsp
->fs_name
= (char *) fstype
;
1215 fsp
->fs_next
= fs_exclude_list
;
1216 fs_exclude_list
= fsp
;
1222 if (status
!= EXIT_SUCCESS
)
1226 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name
);
1228 Show information about the file system on which each FILE resides,\n\
1229 or all file systems by default.\n\
1232 emit_mandatory_arg_note ();
1235 -a, --all include dummy file systems\n\
1236 -B, --block-size=SIZE scale sizes by SIZE before printing them; e.g.,\n\
1237 '-BM' prints sizes in units of 1,048,576 bytes;\n\
1238 see SIZE format below\n\
1239 --total produce a grand total\n\
1240 -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\
1242 -H, --si likewise, but use powers of 1000 not 1024\n\
1245 -i, --inodes list inode information instead of block usage\n\
1246 -k like --block-size=1K\n\
1247 -l, --local limit listing to local file systems\n\
1248 --no-sync do not invoke sync before getting usage info (default)\
1252 --output[=FIELD_LIST] use the output format defined by FIELD_LIST,\n\
1253 or print all fields if FIELD_LIST is omitted.\n\
1254 -P, --portability use the POSIX output format\n\
1255 --sync invoke sync before getting usage info\n\
1256 -t, --type=TYPE limit listing to file systems of type TYPE\n\
1257 -T, --print-type print file system type\n\
1258 -x, --exclude-type=TYPE limit listing to file systems not of type TYPE\n\
1261 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
1262 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
1263 emit_blocksize_note ("DF");
1266 FIELD_LIST is a comma-separated list of columns to be included. Valid\n\
1267 field names are: 'source', 'fstype', 'itotal', 'iused', 'iavail', 'ipcent',\n\
1268 'size', 'used', 'avail', 'pcent' and 'target' (see info page).\n\
1270 emit_ancillary_info ();
1276 main (int argc
, char **argv
)
1278 struct stat
*stats
IF_LINT ( = 0);
1280 initialize_main (&argc
, &argv
);
1281 set_program_name (argv
[0]);
1282 setlocale (LC_ALL
, "");
1283 bindtextdomain (PACKAGE
, LOCALEDIR
);
1284 textdomain (PACKAGE
);
1286 atexit (close_stdout
);
1288 fs_select_list
= NULL
;
1289 fs_exclude_list
= NULL
;
1290 show_all_fs
= false;
1291 show_listed_fs
= false;
1292 human_output_opts
= -1;
1294 file_systems_processed
= false;
1295 exit_status
= EXIT_SUCCESS
;
1296 print_grand_total
= false;
1297 grand_fsu
.fsu_blocksize
= 1;
1299 /* If true, use the POSIX output format. */
1300 bool posix_format
= false;
1302 const char *msg_mut_excl
= _("options %s and %s are mutually exclusive");
1307 int c
= getopt_long (argc
, argv
, "aB:iF:hHklmPTt:vx:", long_options
,
1319 enum strtol_error e
= human_options (optarg
, &human_output_opts
,
1320 &output_block_size
);
1321 if (e
!= LONGINT_OK
)
1322 xstrtol_fatal (e
, oi
, c
, long_options
, optarg
);
1326 if (header_mode
== OUTPUT_MODE
)
1328 error (0, 0, msg_mut_excl
, "-i", "--output");
1329 usage (EXIT_FAILURE
);
1331 header_mode
= INODES_MODE
;
1334 human_output_opts
= human_autoscale
| human_SI
| human_base_1024
;
1335 output_block_size
= 1;
1338 human_output_opts
= human_autoscale
| human_SI
;
1339 output_block_size
= 1;
1342 human_output_opts
= 0;
1343 output_block_size
= 1024;
1346 show_local_fs
= true;
1348 case MEGABYTES_OPTION
:
1349 /* Distinguish between the long and the short option.
1350 As we want to remove the long option soon,
1351 give a warning when the long form is used. */
1352 error (0, 0, "%s%s", _("warning: "),
1353 _("long option '--megabytes' is deprecated"
1354 " and will soon be removed"));
1355 case 'm': /* obsolescent, exists for BSD compatibility */
1356 human_output_opts
= 0;
1357 output_block_size
= 1024 * 1024;
1360 if (header_mode
== OUTPUT_MODE
)
1362 error (0, 0, msg_mut_excl
, "-T", "--output");
1363 usage (EXIT_FAILURE
);
1368 if (header_mode
== OUTPUT_MODE
)
1370 error (0, 0, msg_mut_excl
, "-P", "--output");
1371 usage (EXIT_FAILURE
);
1373 posix_format
= true;
1376 require_sync
= true;
1378 case NO_SYNC_OPTION
:
1379 require_sync
= false;
1383 /* Accept -F as a synonym for -t for compatibility with Solaris. */
1385 add_fs_type (optarg
);
1388 case 'v': /* For SysV compatibility. */
1392 add_excluded_fs_type (optarg
);
1396 if (header_mode
== INODES_MODE
)
1398 error (0, 0, msg_mut_excl
, "-i", "--output");
1399 usage (EXIT_FAILURE
);
1401 if (posix_format
&& header_mode
== DEFAULT_MODE
)
1403 error (0, 0, msg_mut_excl
, "-P", "--output");
1404 usage (EXIT_FAILURE
);
1408 error (0, 0, msg_mut_excl
, "-T", "--output");
1409 usage (EXIT_FAILURE
);
1411 header_mode
= OUTPUT_MODE
;
1413 decode_output_arg (optarg
);
1417 print_grand_total
= true;
1420 case_GETOPT_HELP_CHAR
;
1421 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
1424 usage (EXIT_FAILURE
);
1428 if (human_output_opts
== -1)
1432 human_output_opts
= 0;
1433 output_block_size
= (getenv ("POSIXLY_CORRECT") ? 512 : 1024);
1436 human_options (getenv ("DF_BLOCK_SIZE"),
1437 &human_output_opts
, &output_block_size
);
1440 if (header_mode
== INODES_MODE
|| header_mode
== OUTPUT_MODE
)
1442 else if (human_output_opts
& human_autoscale
)
1443 header_mode
= HUMAN_MODE
;
1444 else if (posix_format
)
1445 header_mode
= POSIX_MODE
;
1447 /* Fail if the same file system type was both selected and excluded. */
1450 struct fs_type_list
*fs_incl
;
1451 for (fs_incl
= fs_select_list
; fs_incl
; fs_incl
= fs_incl
->fs_next
)
1453 struct fs_type_list
*fs_excl
;
1454 for (fs_excl
= fs_exclude_list
; fs_excl
; fs_excl
= fs_excl
->fs_next
)
1456 if (STREQ (fs_incl
->fs_name
, fs_excl
->fs_name
))
1459 _("file system type %s both selected and excluded"),
1460 quote (fs_incl
->fs_name
));
1467 exit (EXIT_FAILURE
);
1474 /* Open each of the given entries to make sure any corresponding
1475 partition is automounted. This must be done before reading the
1476 file system table. */
1477 stats
= xnmalloc (argc
- optind
, sizeof *stats
);
1478 for (i
= optind
; i
< argc
; ++i
)
1480 /* Prefer to open with O_NOCTTY and use fstat, but fall back
1481 on using "stat", in case the file is unreadable. */
1482 int fd
= open (argv
[i
], O_RDONLY
| O_NOCTTY
);
1483 if ((fd
< 0 || fstat (fd
, &stats
[i
- optind
]))
1484 && stat (argv
[i
], &stats
[i
- optind
]))
1486 error (0, errno
, "%s", quote (argv
[i
]));
1487 exit_status
= EXIT_FAILURE
;
1496 read_file_system_list ((fs_select_list
!= NULL
1497 || fs_exclude_list
!= NULL
1499 || field_data
[FSTYPE_FIELD
].used
1502 if (mount_list
== NULL
)
1504 /* Couldn't read the table of mounted file systems.
1505 Fail if df was invoked with no file name arguments,
1506 or when either of -a, -l, -t or -x is used with file name
1507 arguments. Otherwise, merely give a warning and proceed. */
1509 if ( ! (optind
< argc
)
1512 || fs_select_list
!= NULL
1513 || fs_exclude_list
!= NULL
))
1515 status
= EXIT_FAILURE
;
1517 const char *warning
= (status
== 0 ? _("Warning: ") : "");
1518 error (status
, errno
, "%s%s", warning
,
1519 _("cannot read table of mounted file systems"));
1532 /* Display explicitly requested empty file systems. */
1533 show_listed_fs
= true;
1535 for (i
= optind
; i
< argc
; ++i
)
1537 get_entry (argv
[i
], &stats
[i
- optind
]);
1542 if (file_systems_processed
)
1544 if (print_grand_total
)
1546 (field_data
[SOURCE_FIELD
].used
? "-" : "total"),
1547 NULL
, NULL
, false, false, &grand_fsu
, false);
1553 /* Print the "no FS processed" diagnostic only if there was no preceding
1554 diagnostic, e.g., if all have been excluded. */
1555 if (exit_status
== EXIT_SUCCESS
)
1556 error (EXIT_FAILURE
, 0, _("no file systems processed"));
1559 IF_LINT (free (columns
));