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
= N_("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
; me
= me
->me_next
)
619 struct devlist
*devlist
;
621 if (-1 == stat (me
->me_mountdir
, &buf
))
623 ; /* Stat failed - add ME to be able to complain about it later. */
627 /* If the device name is a real path name ... */
628 if (strchr (me
->me_devname
, '/'))
630 /* ... try to find its device number in the devlist. */
631 for (devlist
= devlist_head
; devlist
; devlist
= devlist
->next
)
632 if (devlist
->dev_num
== buf
.st_dev
)
637 /* Let the shorter mountdir win. */
638 if ( !strchr (devlist
->me
->me_devname
, '/')
639 || ( strlen (devlist
->me
->me_mountdir
)
640 > strlen (me
->me_mountdir
)))
642 /* FIXME: free ME - the others are also not free()d. */
645 continue; /* ... with the loop over the mount_list. */
650 /* Add the device number to the global list devlist. */
651 devlist
= xmalloc (sizeof *devlist
);
653 devlist
->dev_num
= buf
.st_dev
;
654 devlist
->next
= devlist_head
;
655 devlist_head
= devlist
;
658 /* Finally rebuild the mount_list from the devlist. */
662 /* Add the mount entry. */
663 me
= devlist_head
->me
;
664 me
->me_next
= mount_list
;
666 /* Free devlist entry and advance. */
667 struct devlist
*devlist
= devlist_head
->next
;
669 devlist_head
= devlist
;
673 /* Return true if N is a known integer value. On many file systems,
674 UINTMAX_MAX represents an unknown value; on AIX, UINTMAX_MAX - 1
675 represents unknown. Use a rule that works on AIX file systems, and
676 that almost-always works on other types. */
678 known_value (uintmax_t n
)
680 return n
< UINTMAX_MAX
- 1;
683 /* Like human_readable (N, BUF, human_output_opts, INPUT_UNITS, OUTPUT_UNITS),
686 - If NEGATIVE, then N represents a negative number,
687 expressed in two's complement.
688 - Otherwise, return "-" if N is unknown. */
691 df_readable (bool negative
, uintmax_t n
, char *buf
,
692 uintmax_t input_units
, uintmax_t output_units
)
694 if (! known_value (n
) && !negative
)
698 char *p
= human_readable (negative
? -n
: n
, buf
+ negative
,
699 human_output_opts
, input_units
, output_units
);
706 /* Logical equivalence */
707 #define LOG_EQ(a, b) (!(a) == !(b))
709 /* Add integral value while using uintmax_t for value part and separate
710 negation flag. It adds value of SRC and SRC_NEG to DEST and DEST_NEG.
711 The result will be in DEST and DEST_NEG. See df_readable to understand
712 how the negation flag is used. */
714 add_uint_with_neg_flag (uintmax_t *dest
, bool *dest_neg
,
715 uintmax_t src
, bool src_neg
)
717 if (LOG_EQ (*dest_neg
, src_neg
))
741 /* Return true if S ends in a string that may be a 36-byte UUID,
742 i.e., of the form HHHHHHHH-HHHH-HHHH-HHHH-HHHHHHHHHHHH, where
743 each H is an upper or lower case hexadecimal digit. */
744 static bool _GL_ATTRIBUTE_PURE
745 has_uuid_suffix (char const *s
)
747 size_t len
= strlen (s
);
749 && strspn (s
+ len
- 36, "-0123456789abcdefABCDEF") == 36);
752 /* Obtain the block values BV and inode values IV
753 from the file system usage FSU. */
755 get_field_values (struct field_values_t
*bv
,
756 struct field_values_t
*iv
,
757 const struct fs_usage
*fsu
)
760 iv
->input_units
= iv
->output_units
= 1;
761 iv
->total
= fsu
->fsu_files
;
762 iv
->available
= iv
->available_to_root
= fsu
->fsu_ffree
;
763 iv
->negate_available
= false;
765 iv
->used
= UINTMAX_MAX
;
766 iv
->negate_used
= false;
767 if (known_value (iv
->total
) && known_value (iv
->available_to_root
))
769 iv
->used
= iv
->total
- iv
->available_to_root
;
770 iv
->negate_used
= (iv
->total
< iv
->available_to_root
);
774 bv
->input_units
= fsu
->fsu_blocksize
;
775 bv
->output_units
= output_block_size
;
776 bv
->total
= fsu
->fsu_blocks
;
777 bv
->available
= fsu
->fsu_bavail
;
778 bv
->available_to_root
= fsu
->fsu_bfree
;
779 bv
->negate_available
= (fsu
->fsu_bavail_top_bit_set
780 && known_value (fsu
->fsu_bavail
));
782 bv
->used
= UINTMAX_MAX
;
783 bv
->negate_used
= false;
784 if (known_value (bv
->total
) && known_value (bv
->available_to_root
))
786 bv
->used
= bv
->total
- bv
->available_to_root
;
787 bv
->negate_used
= (bv
->total
< bv
->available_to_root
);
791 /* Add block and inode values to grand total. */
793 add_to_grand_total (struct field_values_t
*bv
, struct field_values_t
*iv
)
795 if (known_value (iv
->total
))
796 grand_fsu
.fsu_files
+= iv
->total
;
797 if (known_value (iv
->available
))
798 grand_fsu
.fsu_ffree
+= iv
->available
;
800 if (known_value (bv
->total
))
801 grand_fsu
.fsu_blocks
+= bv
->input_units
* bv
->total
;
802 if (known_value (bv
->available_to_root
))
803 grand_fsu
.fsu_bfree
+= bv
->input_units
* bv
->available_to_root
;
804 if (known_value (bv
->available
))
805 add_uint_with_neg_flag (&grand_fsu
.fsu_bavail
,
806 &grand_fsu
.fsu_bavail_top_bit_set
,
807 bv
->input_units
* bv
->available
,
808 bv
->negate_available
);
811 /* Obtain a space listing for the disk device with absolute file name DISK.
812 If MOUNT_POINT is non-NULL, it is the name of the root of the
814 If STAT_FILE is non-null, it is the name of a file within the file
815 system that the user originally asked for; this provides better
816 diagnostics, and sometimes it provides better results on networked
817 file systems that give different free-space results depending on
818 where in the file system you probe.
819 If FSTYPE is non-NULL, it is the type of the file system on DISK.
820 If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may
821 not be able to produce statistics in this case.
822 ME_DUMMY and ME_REMOTE are the mount entry flags.
823 Caller must set PROCESS_ALL to true when iterating over all entries, as
824 when df is invoked with no non-option argument. See below for details. */
827 get_dev (char const *disk
, char const *mount_point
,
828 char const *stat_file
, char const *fstype
,
829 bool me_dummy
, bool me_remote
,
830 const struct fs_usage
*force_fsu
,
833 if (me_remote
&& show_local_fs
)
836 if (me_dummy
&& !show_all_fs
&& !show_listed_fs
)
839 if (!selected_fstype (fstype
) || excluded_fstype (fstype
))
842 /* If MOUNT_POINT is NULL, then the file system is not mounted, and this
843 program reports on the file system that the special file is on.
844 It would be better to report on the unmounted file system,
845 but statfs doesn't do that on most systems. */
847 stat_file
= mount_point
? mount_point
: disk
;
852 else if (get_fs_usage (stat_file
, disk
, &fsu
))
854 error (0, errno
, "%s", quote (stat_file
));
855 exit_status
= EXIT_FAILURE
;
859 if (fsu
.fsu_blocks
== 0 && !show_all_fs
&& !show_listed_fs
)
863 file_systems_processed
= true;
868 disk
= "-"; /* unknown */
870 char *dev_name
= xstrdup (disk
);
873 /* On some systems, dev_name is a long-named symlink like
874 /dev/disk/by-uuid/828fc648-9f30-43d8-a0b1-f7196a2edb66 pointing to a
875 much shorter and more useful name like /dev/sda1. It may also look
876 like /dev/mapper/luks-828fc648-9f30-43d8-a0b1-f7196a2edb66 and point to
877 /dev/dm-0. When process_all is true and dev_name is a symlink whose
878 name ends with a UUID use the resolved name instead. */
880 && has_uuid_suffix (dev_name
)
881 && (resolved_dev
= canonicalize_filename_mode (dev_name
, CAN_EXISTING
)))
884 dev_name
= resolved_dev
;
888 fstype
= "-"; /* unknown */
890 struct field_values_t block_values
;
891 struct field_values_t inode_values
;
892 get_field_values (&block_values
, &inode_values
, &fsu
);
894 /* Add to grand total unless processing grand total line. */
895 if (print_grand_total
&& ! force_fsu
)
896 add_to_grand_total (&block_values
, &inode_values
);
899 for (col
= 0; col
< ncolumns
; col
++)
901 char buf
[LONGEST_HUMAN_READABLE
+ 2];
904 struct field_values_t
*v
;
905 switch (columns
[col
]->field_type
)
917 assert (!"bad field_type");
920 switch (columns
[col
]->field
)
923 cell
= xstrdup (dev_name
);
927 cell
= xstrdup (fstype
);
932 cell
= xstrdup (df_readable (false, v
->total
, buf
,
933 v
->input_units
, v
->output_units
));
938 cell
= xstrdup (df_readable (v
->negate_used
, v
->used
, buf
,
939 v
->input_units
, v
->output_units
));
944 cell
= xstrdup (df_readable (v
->negate_available
, v
->available
, buf
,
945 v
->input_units
, v
->output_units
));
952 if (! known_value (v
->used
) || ! known_value (v
->available
))
954 else if (!v
->negate_used
955 && v
->used
<= TYPE_MAXIMUM (uintmax_t) / 100
956 && v
->used
+ v
->available
!= 0
957 && (v
->used
+ v
->available
< v
->used
)
958 == v
->negate_available
)
960 uintmax_t u100
= v
->used
* 100;
961 uintmax_t nonroot_total
= v
->used
+ v
->available
;
962 pct
= u100
/ nonroot_total
+ (u100
% nonroot_total
!= 0);
966 /* The calculation cannot be done easily with integer
967 arithmetic. Fall back on floating point. This can suffer
968 from minor rounding errors, but doing it exactly requires
969 multiple precision arithmetic, and it's not worth the
971 double u
= v
->negate_used
? - (double) - v
->used
: v
->used
;
972 double a
= v
->negate_available
973 ? - (double) - v
->available
: v
->available
;
974 double nonroot_total
= u
+ a
;
977 long int lipct
= pct
= u
* 100 / nonroot_total
;
980 /* Like 'pct = ceil (dpct);', but avoid ceil so that
981 the math library needn't be linked. */
982 if (ipct
- 1 < pct
&& pct
<= ipct
+ 1)
983 pct
= ipct
+ (ipct
< pct
);
989 if (asprintf (&cell
, "%.0f%%", pct
) == -1)
1002 #ifdef HIDE_AUTOMOUNT_PREFIX
1003 /* Don't print the first directory name in MOUNT_POINT if it's an
1004 artifact of an automounter. This is a bit too aggressive to be
1006 if (STRNCMP_LIT (mount_point
, "/auto/") == 0)
1008 else if (STRNCMP_LIT (mount_point
, "/tmp_mnt/") == 0)
1011 cell
= xstrdup (mount_point
);
1015 assert (!"unhandled field");
1019 assert (!"empty cell");
1021 hide_problematic_chars (cell
);
1022 columns
[col
]->width
= MAX (columns
[col
]->width
, mbswidth (cell
, 0));
1023 table
[nrows
- 1][col
] = cell
;
1028 /* If DISK corresponds to a mount point, show its usage
1029 and return true. Otherwise, return false. */
1031 get_disk (char const *disk
)
1033 struct mount_entry
const *me
;
1034 struct mount_entry
const *best_match
= NULL
;
1036 for (me
= mount_list
; me
; me
= me
->me_next
)
1037 if (STREQ (disk
, me
->me_devname
))
1042 get_dev (best_match
->me_devname
, best_match
->me_mountdir
, NULL
,
1043 best_match
->me_type
, best_match
->me_dummy
,
1044 best_match
->me_remote
, NULL
, false);
1051 /* Figure out which device file or directory POINT is mounted on
1052 and show its disk usage.
1053 STATP must be the result of 'stat (POINT, STATP)'. */
1055 get_point (const char *point
, const struct stat
*statp
)
1057 struct stat disk_stats
;
1058 struct mount_entry
*me
;
1059 struct mount_entry
const *best_match
= NULL
;
1061 /* Calculate the real absolute file name for POINT, and use that to find
1062 the mount point. This avoids statting unavailable mount points,
1063 which can hang df. */
1064 char *resolved
= canonicalize_file_name (point
);
1065 if (resolved
&& resolved
[0] == '/')
1067 size_t resolved_len
= strlen (resolved
);
1068 size_t best_match_len
= 0;
1070 for (me
= mount_list
; me
; me
= me
->me_next
)
1071 if (!STREQ (me
->me_type
, "lofs")
1072 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
1074 size_t len
= strlen (me
->me_mountdir
);
1075 if (best_match_len
<= len
&& len
<= resolved_len
1076 && (len
== 1 /* root file system */
1077 || ((len
== resolved_len
|| resolved
[len
] == '/')
1078 && STREQ_LEN (me
->me_mountdir
, resolved
, len
))))
1081 best_match_len
= len
;
1087 && (stat (best_match
->me_mountdir
, &disk_stats
) != 0
1088 || disk_stats
.st_dev
!= statp
->st_dev
))
1092 for (me
= mount_list
; me
; me
= me
->me_next
)
1094 if (me
->me_dev
== (dev_t
) -1)
1096 if (stat (me
->me_mountdir
, &disk_stats
) == 0)
1097 me
->me_dev
= disk_stats
.st_dev
;
1100 /* Report only I/O errors. Other errors might be
1101 caused by shadowed mount points, which means POINT
1102 can't possibly be on this file system. */
1105 error (0, errno
, "%s", quote (me
->me_mountdir
));
1106 exit_status
= EXIT_FAILURE
;
1109 /* So we won't try and fail repeatedly. */
1110 me
->me_dev
= (dev_t
) -2;
1114 if (statp
->st_dev
== me
->me_dev
1115 && !STREQ (me
->me_type
, "lofs")
1116 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
1118 /* Skip bogus mtab entries. */
1119 if (stat (me
->me_mountdir
, &disk_stats
) != 0
1120 || disk_stats
.st_dev
!= me
->me_dev
)
1121 me
->me_dev
= (dev_t
) -2;
1128 get_dev (best_match
->me_devname
, best_match
->me_mountdir
, point
,
1129 best_match
->me_type
, best_match
->me_dummy
, best_match
->me_remote
,
1133 /* We couldn't find the mount entry corresponding to POINT. Go ahead and
1134 print as much info as we can; methods that require the device to be
1135 present will fail at a later point. */
1137 /* Find the actual mount point. */
1138 char *mp
= find_mount_point (point
, statp
);
1141 get_dev (NULL
, mp
, NULL
, NULL
, false, false, NULL
, false);
1147 /* Determine what kind of node NAME is and show the disk usage
1148 for it. STATP is the results of 'stat' on NAME. */
1151 get_entry (char const *name
, struct stat
const *statp
)
1153 if ((S_ISBLK (statp
->st_mode
) || S_ISCHR (statp
->st_mode
))
1157 get_point (name
, statp
);
1160 /* Show all mounted file systems, except perhaps those that are of
1161 an unselected type or are empty. */
1164 get_all_entries (void)
1166 struct mount_entry
*me
;
1169 filter_mount_list ();
1171 for (me
= mount_list
; me
; me
= me
->me_next
)
1172 get_dev (me
->me_devname
, me
->me_mountdir
, NULL
, me
->me_type
,
1173 me
->me_dummy
, me
->me_remote
, NULL
, true);
1176 /* Add FSTYPE to the list of file system types to display. */
1179 add_fs_type (const char *fstype
)
1181 struct fs_type_list
*fsp
;
1183 fsp
= xmalloc (sizeof *fsp
);
1184 fsp
->fs_name
= (char *) fstype
;
1185 fsp
->fs_next
= fs_select_list
;
1186 fs_select_list
= fsp
;
1189 /* Add FSTYPE to the list of file system types to be omitted. */
1192 add_excluded_fs_type (const char *fstype
)
1194 struct fs_type_list
*fsp
;
1196 fsp
= xmalloc (sizeof *fsp
);
1197 fsp
->fs_name
= (char *) fstype
;
1198 fsp
->fs_next
= fs_exclude_list
;
1199 fs_exclude_list
= fsp
;
1205 if (status
!= EXIT_SUCCESS
)
1209 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name
);
1211 Show information about the file system on which each FILE resides,\n\
1212 or all file systems by default.\n\
1215 emit_mandatory_arg_note ();
1218 -a, --all include dummy file systems\n\
1219 -B, --block-size=SIZE scale sizes by SIZE before printing them. E.g.,\n\
1220 '-BM' prints sizes in units of 1,048,576 bytes.\n\
1221 See SIZE format below.\n\
1222 --total produce a grand total\n\
1223 -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\
1225 -H, --si likewise, but use powers of 1000 not 1024\n\
1228 -i, --inodes list inode information instead of block usage\n\
1229 -k like --block-size=1K\n\
1230 -l, --local limit listing to local file systems\n\
1231 --no-sync do not invoke sync before getting usage info (default)\
1235 --output[=FIELD_LIST] use the output format defined by FIELD_LIST,\n\
1236 or print all fields if FIELD_LIST is omitted.\n\
1237 -P, --portability use the POSIX output format\n\
1238 --sync invoke sync before getting usage info\n\
1239 -t, --type=TYPE limit listing to file systems of type TYPE\n\
1240 -T, --print-type print file system type\n\
1241 -x, --exclude-type=TYPE limit listing to file systems not of type TYPE\n\
1244 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
1245 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
1246 emit_blocksize_note ("DF");
1249 FIELD_LIST is a comma-separated list of columns to be included. Valid\n\
1250 field names are: 'source', 'fstype', 'itotal', 'iused', 'iavail', 'ipcent',\n\
1251 'size', 'used', 'avail', 'pcent' and 'target' (see info page).\n\
1253 emit_ancillary_info ();
1259 main (int argc
, char **argv
)
1261 struct stat
*stats
IF_LINT ( = 0);
1263 initialize_main (&argc
, &argv
);
1264 set_program_name (argv
[0]);
1265 setlocale (LC_ALL
, "");
1266 bindtextdomain (PACKAGE
, LOCALEDIR
);
1267 textdomain (PACKAGE
);
1269 atexit (close_stdout
);
1271 fs_select_list
= NULL
;
1272 fs_exclude_list
= NULL
;
1273 show_all_fs
= false;
1274 show_listed_fs
= false;
1275 human_output_opts
= -1;
1277 file_systems_processed
= false;
1278 exit_status
= EXIT_SUCCESS
;
1279 print_grand_total
= false;
1280 grand_fsu
.fsu_blocksize
= 1;
1282 /* If true, use the POSIX output format. */
1283 bool posix_format
= false;
1285 const char *msg_mut_excl
= _("options %s and %s are mutually exclusive");
1290 int c
= getopt_long (argc
, argv
, "aB:iF:hHklmPTt:vx:", long_options
,
1302 enum strtol_error e
= human_options (optarg
, &human_output_opts
,
1303 &output_block_size
);
1304 if (e
!= LONGINT_OK
)
1305 xstrtol_fatal (e
, oi
, c
, long_options
, optarg
);
1309 if (header_mode
== OUTPUT_MODE
)
1311 error (0, 0, msg_mut_excl
, "-i", "--output");
1312 usage (EXIT_FAILURE
);
1314 header_mode
= INODES_MODE
;
1317 human_output_opts
= human_autoscale
| human_SI
| human_base_1024
;
1318 output_block_size
= 1;
1321 human_output_opts
= human_autoscale
| human_SI
;
1322 output_block_size
= 1;
1325 human_output_opts
= 0;
1326 output_block_size
= 1024;
1329 show_local_fs
= true;
1331 case MEGABYTES_OPTION
:
1332 /* Distinguish between the long and the short option.
1333 As we want to remove the long option soon,
1334 give a warning when the long form is used. */
1335 error (0, 0, "%s%s", _("warning: "),
1336 _("long option '--megabytes' is deprecated"
1337 " and will soon be removed"));
1338 case 'm': /* obsolescent, exists for BSD compatibility */
1339 human_output_opts
= 0;
1340 output_block_size
= 1024 * 1024;
1343 if (header_mode
== OUTPUT_MODE
)
1345 error (0, 0, msg_mut_excl
, "-T", "--output");
1346 usage (EXIT_FAILURE
);
1351 if (header_mode
== OUTPUT_MODE
)
1353 error (0, 0, msg_mut_excl
, "-P", "--output");
1354 usage (EXIT_FAILURE
);
1356 posix_format
= true;
1359 require_sync
= true;
1361 case NO_SYNC_OPTION
:
1362 require_sync
= false;
1366 /* Accept -F as a synonym for -t for compatibility with Solaris. */
1368 add_fs_type (optarg
);
1371 case 'v': /* For SysV compatibility. */
1375 add_excluded_fs_type (optarg
);
1379 if (header_mode
== INODES_MODE
)
1381 error (0, 0, msg_mut_excl
, "-i", "--output");
1382 usage (EXIT_FAILURE
);
1384 if (posix_format
&& header_mode
== DEFAULT_MODE
)
1386 error (0, 0, msg_mut_excl
, "-P", "--output");
1387 usage (EXIT_FAILURE
);
1391 error (0, 0, msg_mut_excl
, "-T", "--output");
1392 usage (EXIT_FAILURE
);
1394 header_mode
= OUTPUT_MODE
;
1396 decode_output_arg (optarg
);
1400 print_grand_total
= true;
1403 case_GETOPT_HELP_CHAR
;
1404 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
1407 usage (EXIT_FAILURE
);
1411 if (human_output_opts
== -1)
1415 human_output_opts
= 0;
1416 output_block_size
= (getenv ("POSIXLY_CORRECT") ? 512 : 1024);
1419 human_options (getenv ("DF_BLOCK_SIZE"),
1420 &human_output_opts
, &output_block_size
);
1423 if (header_mode
== INODES_MODE
|| header_mode
== OUTPUT_MODE
)
1425 else if (human_output_opts
& human_autoscale
)
1426 header_mode
= HUMAN_MODE
;
1427 else if (posix_format
)
1428 header_mode
= POSIX_MODE
;
1430 /* Fail if the same file system type was both selected and excluded. */
1433 struct fs_type_list
*fs_incl
;
1434 for (fs_incl
= fs_select_list
; fs_incl
; fs_incl
= fs_incl
->fs_next
)
1436 struct fs_type_list
*fs_excl
;
1437 for (fs_excl
= fs_exclude_list
; fs_excl
; fs_excl
= fs_excl
->fs_next
)
1439 if (STREQ (fs_incl
->fs_name
, fs_excl
->fs_name
))
1442 _("file system type %s both selected and excluded"),
1443 quote (fs_incl
->fs_name
));
1450 exit (EXIT_FAILURE
);
1457 /* Open each of the given entries to make sure any corresponding
1458 partition is automounted. This must be done before reading the
1459 file system table. */
1460 stats
= xnmalloc (argc
- optind
, sizeof *stats
);
1461 for (i
= optind
; i
< argc
; ++i
)
1463 /* Prefer to open with O_NOCTTY and use fstat, but fall back
1464 on using "stat", in case the file is unreadable. */
1465 int fd
= open (argv
[i
], O_RDONLY
| O_NOCTTY
);
1466 if ((fd
< 0 || fstat (fd
, &stats
[i
- optind
]))
1467 && stat (argv
[i
], &stats
[i
- optind
]))
1469 error (0, errno
, "%s", quote (argv
[i
]));
1470 exit_status
= EXIT_FAILURE
;
1479 read_file_system_list ((fs_select_list
!= NULL
1480 || fs_exclude_list
!= NULL
1482 || field_data
[FSTYPE_FIELD
].used
1485 if (mount_list
== NULL
)
1487 /* Couldn't read the table of mounted file systems.
1488 Fail if df was invoked with no file name arguments,
1489 or when either of -a, -l, -t or -x is used with file name
1490 arguments. Otherwise, merely give a warning and proceed. */
1492 if ( ! (optind
< argc
)
1495 || fs_select_list
!= NULL
1496 || fs_exclude_list
!= NULL
))
1498 status
= EXIT_FAILURE
;
1500 const char *warning
= (status
== 0 ? _("Warning: ") : "");
1501 error (status
, errno
, "%s%s", warning
,
1502 _("cannot read table of mounted file systems"));
1515 /* Display explicitly requested empty file systems. */
1516 show_listed_fs
= true;
1518 for (i
= optind
; i
< argc
; ++i
)
1520 get_entry (argv
[i
], &stats
[i
- optind
]);
1525 if (file_systems_processed
)
1527 if (print_grand_total
)
1529 (field_data
[SOURCE_FIELD
].used
? "-" : "total"),
1530 NULL
, NULL
, false, false, &grand_fsu
, false);
1536 /* Print the "no FS processed" diagnostic only if there was no preceding
1537 diagnostic, e.g., if all have been excluded. */
1538 if (exit_status
== EXIT_SUCCESS
)
1539 error (EXIT_FAILURE
, 0, _("no file systems processed"));
1542 IF_LINT (free (columns
));