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 */
147 FILE_FIELD
/* specified file name */
150 /* Flag if a field contains a block, an inode or another value. */
153 BLOCK_FLD
, /* Block values field */
154 INODE_FLD
, /* Inode values field */
155 OTHER_FLD
/* Neutral field, e.g. target */
158 /* Attributes of a display field. */
161 display_field_t field
;
163 field_type_t field_type
;
164 const char *caption
;/* NULL means to use the default header of this field. */
165 size_t width
; /* Auto adjusted (up) widths used to align columns. */
166 mbs_align_t align
; /* Alignment for this field. */
170 /* Header strings, minimum width and alignment for the above fields. */
171 static struct field_data_t field_data
[] = {
172 [SOURCE_FIELD
] = { SOURCE_FIELD
,
173 "source", OTHER_FLD
, N_("Filesystem"), 14, MBS_ALIGN_LEFT
, false },
175 [FSTYPE_FIELD
] = { FSTYPE_FIELD
,
176 "fstype", OTHER_FLD
, N_("Type"), 4, MBS_ALIGN_LEFT
, false },
178 [SIZE_FIELD
] = { SIZE_FIELD
,
179 "size", BLOCK_FLD
, N_("blocks"), 5, MBS_ALIGN_RIGHT
, false },
181 [USED_FIELD
] = { USED_FIELD
,
182 "used", BLOCK_FLD
, N_("Used"), 5, MBS_ALIGN_RIGHT
, false },
184 [AVAIL_FIELD
] = { AVAIL_FIELD
,
185 "avail", BLOCK_FLD
, N_("Available"), 5, MBS_ALIGN_RIGHT
, false },
187 [PCENT_FIELD
] = { PCENT_FIELD
,
188 "pcent", BLOCK_FLD
, N_("Use%"), 4, MBS_ALIGN_RIGHT
, false },
190 [ITOTAL_FIELD
] = { ITOTAL_FIELD
,
191 "itotal", INODE_FLD
, N_("Inodes"), 5, MBS_ALIGN_RIGHT
, false },
193 [IUSED_FIELD
] = { IUSED_FIELD
,
194 "iused", INODE_FLD
, N_("IUsed"), 5, MBS_ALIGN_RIGHT
, false },
196 [IAVAIL_FIELD
] = { IAVAIL_FIELD
,
197 "iavail", INODE_FLD
, N_("IFree"), 5, MBS_ALIGN_RIGHT
, false },
199 [IPCENT_FIELD
] = { IPCENT_FIELD
,
200 "ipcent", INODE_FLD
, N_("IUse%"), 4, MBS_ALIGN_RIGHT
, false },
202 [TARGET_FIELD
] = { TARGET_FIELD
,
203 "target", OTHER_FLD
, N_("Mounted on"), 0, MBS_ALIGN_LEFT
, false },
205 [FILE_FIELD
] = { FILE_FIELD
,
206 "file", OTHER_FLD
, N_("File"), 0, MBS_ALIGN_LEFT
, false }
209 static char const *all_args_string
=
210 "source,fstype,itotal,iused,iavail,ipcent,size,"
211 "used,avail,pcent,file,target";
213 /* Storage for the definition of output columns. */
214 static struct field_data_t
**columns
;
216 /* The current number of output columns. */
217 static size_t ncolumns
;
220 struct field_values_t
222 uintmax_t input_units
;
223 uintmax_t output_units
;
226 bool negate_available
;
227 uintmax_t available_to_root
;
232 /* Storage for pointers for each string (cell of table). */
233 static char ***table
;
235 /* The current number of processed rows (including header). */
238 /* For long options that have no equivalent short option, use a
239 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
242 NO_SYNC_OPTION
= CHAR_MAX
+ 1,
248 static struct option
const long_options
[] =
250 {"all", no_argument
, NULL
, 'a'},
251 {"block-size", required_argument
, NULL
, 'B'},
252 {"inodes", no_argument
, NULL
, 'i'},
253 {"human-readable", no_argument
, NULL
, 'h'},
254 {"si", no_argument
, NULL
, 'H'},
255 {"local", no_argument
, NULL
, 'l'},
256 {"output", optional_argument
, NULL
, OUTPUT_OPTION
},
257 {"portability", no_argument
, NULL
, 'P'},
258 {"print-type", no_argument
, NULL
, 'T'},
259 {"sync", no_argument
, NULL
, SYNC_OPTION
},
260 {"no-sync", no_argument
, NULL
, NO_SYNC_OPTION
},
261 {"total", no_argument
, NULL
, TOTAL_OPTION
},
262 {"type", required_argument
, NULL
, 't'},
263 {"exclude-type", required_argument
, NULL
, 'x'},
264 {GETOPT_HELP_OPTION_DECL
},
265 {GETOPT_VERSION_OPTION_DECL
},
269 /* Replace problematic chars with '?'.
270 Since only control characters are currently considered,
271 this should work in all encodings. */
274 hide_problematic_chars (char *cell
)
279 if (iscntrl (to_uchar (*p
)))
286 /* Dynamically allocate a row of pointers in TABLE, which
287 can then be accessed with standard 2D array notation. */
290 alloc_table_row (void)
293 table
= xnrealloc (table
, nrows
, sizeof (char *));
294 table
[nrows
- 1] = xnmalloc (ncolumns
, sizeof (char *));
297 /* Output each cell in the table, accounting for the
298 alignment and max width of each column. */
305 for (row
= 0; row
< nrows
; row
++)
308 for (col
= 0; col
< ncolumns
; col
++)
310 char *cell
= table
[row
][col
];
312 /* Note the SOURCE_FIELD used to be displayed on it's own line
313 if (!posix_format && mbswidth (cell) > 20), but that
314 functionality was probably more problematic than helpful,
315 hence changed in commit v8.10-40-g99679ff. */
320 if (col
== ncolumns
- 1) /* The last one. */
321 flags
= MBA_NO_RIGHT_PAD
;
323 size_t width
= columns
[col
]->width
;
324 cell
= ambsalign (cell
, &width
, columns
[col
]->align
, flags
);
325 /* When ambsalign fails, output unaligned data. */
326 fputs (cell
? cell
: table
[row
][col
], stdout
);
329 IF_LINT (free (table
[row
][col
]));
332 IF_LINT (free (table
[row
]));
335 IF_LINT (free (table
));
338 /* Dynamically allocate a struct field_t in COLUMNS, which
339 can then be accessed with standard array notation. */
342 alloc_field (int f
, const char *c
)
345 columns
= xnrealloc (columns
, ncolumns
, sizeof (struct field_data_t
*));
346 columns
[ncolumns
- 1] = &field_data
[f
];
348 columns
[ncolumns
- 1]->caption
= c
;
350 if (field_data
[f
].used
)
351 assert (!"field used");
353 /* Mark field as used. */
354 field_data
[f
].used
= true;
358 /* Given a string, ARG, containing a comma-separated list of arguments
359 to the --output option, add the appropriate fields to columns. */
361 decode_output_arg (char const *arg
)
363 char *arg_writable
= xstrdup (arg
);
364 char *s
= arg_writable
;
367 /* find next comma */
368 char *comma
= strchr (s
, ',');
370 /* If we found a comma, put a NUL in its place and advance. */
375 display_field_t field
= -1;
376 for (unsigned int i
= 0; i
< ARRAY_CARDINALITY (field_data
); i
++)
378 if (STREQ (field_data
[i
].arg
, s
))
386 error (0, 0, _("option --output: field %s unknown"), quote (s
));
387 usage (EXIT_FAILURE
);
390 if (field_data
[field
].used
)
392 /* Prevent the fields from being used more than once. */
393 error (0, 0, _("option --output: field %s used more than once"),
394 quote (field_data
[field
].arg
));
395 usage (EXIT_FAILURE
);
410 alloc_field (field
, NULL
);
414 alloc_field (field
, N_("Size"));
418 alloc_field (field
, N_("Avail"));
422 assert (!"invalid field");
431 /* Get the appropriate columns for the mode. */
433 get_field_list (void)
438 alloc_field (SOURCE_FIELD
, NULL
);
440 alloc_field (FSTYPE_FIELD
, NULL
);
441 alloc_field (SIZE_FIELD
, NULL
);
442 alloc_field (USED_FIELD
, NULL
);
443 alloc_field (AVAIL_FIELD
, NULL
);
444 alloc_field (PCENT_FIELD
, NULL
);
445 alloc_field (TARGET_FIELD
, NULL
);
449 alloc_field (SOURCE_FIELD
, NULL
);
451 alloc_field (FSTYPE_FIELD
, NULL
);
453 alloc_field (SIZE_FIELD
, N_("Size"));
454 alloc_field (USED_FIELD
, NULL
);
455 alloc_field (AVAIL_FIELD
, N_("Avail"));
456 alloc_field (PCENT_FIELD
, NULL
);
457 alloc_field (TARGET_FIELD
, NULL
);
461 alloc_field (SOURCE_FIELD
, NULL
);
463 alloc_field (FSTYPE_FIELD
, NULL
);
464 alloc_field (ITOTAL_FIELD
, NULL
);
465 alloc_field (IUSED_FIELD
, NULL
);
466 alloc_field (IAVAIL_FIELD
, NULL
);
467 alloc_field (IPCENT_FIELD
, NULL
);
468 alloc_field (TARGET_FIELD
, NULL
);
472 alloc_field (SOURCE_FIELD
, NULL
);
474 alloc_field (FSTYPE_FIELD
, NULL
);
475 alloc_field (SIZE_FIELD
, NULL
);
476 alloc_field (USED_FIELD
, NULL
);
477 alloc_field (AVAIL_FIELD
, NULL
);
478 alloc_field (PCENT_FIELD
, N_("Capacity"));
479 alloc_field (TARGET_FIELD
, NULL
);
485 /* Add all fields if --output was given without a field list. */
486 decode_output_arg (all_args_string
);
491 assert (!"invalid header_mode");
495 /* Obtain the appropriate header entries. */
504 for (col
= 0; col
< ncolumns
; col
++)
507 char const *header
= _(columns
[col
]->caption
);
509 if (columns
[col
]->field
== SIZE_FIELD
510 && (header_mode
== DEFAULT_MODE
511 || (header_mode
== OUTPUT_MODE
512 && !(human_output_opts
& human_autoscale
))))
514 char buf
[LONGEST_HUMAN_READABLE
+ 1];
516 int opts
= (human_suppress_point_zero
517 | human_autoscale
| human_SI
519 & (human_group_digits
| human_base_1024
| human_B
)));
521 /* Prefer the base that makes the human-readable value more exact,
522 if there is a difference. */
524 uintmax_t q1000
= output_block_size
;
525 uintmax_t q1024
= output_block_size
;
526 bool divisible_by_1000
;
527 bool divisible_by_1024
;
531 divisible_by_1000
= q1000
% 1000 == 0; q1000
/= 1000;
532 divisible_by_1024
= q1024
% 1024 == 0; q1024
/= 1024;
534 while (divisible_by_1000
& divisible_by_1024
);
536 if (divisible_by_1000
< divisible_by_1024
)
537 opts
|= human_base_1024
;
538 if (divisible_by_1024
< divisible_by_1000
)
539 opts
&= ~human_base_1024
;
540 if (! (opts
& human_base_1024
))
543 char *num
= human_readable (output_block_size
, buf
, opts
, 1, 1);
545 /* Reset the header back to the default in OUTPUT_MODE. */
546 header
= _("blocks");
548 /* TRANSLATORS: this is the "1K-blocks" header in "df" output. */
549 if (asprintf (&cell
, _("%s-%s"), num
, header
) == -1)
552 else if (header_mode
== POSIX_MODE
&& columns
[col
]->field
== SIZE_FIELD
)
554 char buf
[INT_BUFSIZE_BOUND (uintmax_t)];
555 char *num
= umaxtostr (output_block_size
, buf
);
557 /* TRANSLATORS: this is the "1024-blocks" header in "df -P". */
558 if (asprintf (&cell
, _("%s-%s"), num
, header
) == -1)
562 cell
= strdup (header
);
567 hide_problematic_chars (cell
);
569 table
[nrows
- 1][col
] = cell
;
571 columns
[col
]->width
= MAX (columns
[col
]->width
, mbswidth (cell
, 0));
575 /* Is FSTYPE a type of file system that should be listed? */
577 static bool _GL_ATTRIBUTE_PURE
578 selected_fstype (const char *fstype
)
580 const struct fs_type_list
*fsp
;
582 if (fs_select_list
== NULL
|| fstype
== NULL
)
584 for (fsp
= fs_select_list
; fsp
; fsp
= fsp
->fs_next
)
585 if (STREQ (fstype
, fsp
->fs_name
))
590 /* Is FSTYPE a type of file system that should be omitted? */
592 static bool _GL_ATTRIBUTE_PURE
593 excluded_fstype (const char *fstype
)
595 const struct fs_type_list
*fsp
;
597 if (fs_exclude_list
== NULL
|| fstype
== NULL
)
599 for (fsp
= fs_exclude_list
; fsp
; fsp
= fsp
->fs_next
)
600 if (STREQ (fstype
, fsp
->fs_name
))
605 /* Filter mount list by skipping duplicate entries.
606 In the case of duplicities - based on to the device number - the mount entry
607 with a '/' in its me_devname (i.e. not pseudo name like tmpfs) wins.
608 If both have a real devname (e.g. bind mounts), then that with the shorter
612 filter_mount_list (void)
614 struct mount_entry
*me
;
616 /* Store of already-processed device numbers. */
617 struct devlist
*devlist_head
= NULL
;
619 /* Sort all 'wanted' entries into the list devlist_head. */
620 for (me
= mount_list
; me
;)
623 struct devlist
*devlist
;
624 struct mount_entry
*discard_me
= NULL
;
626 if (-1 == stat (me
->me_mountdir
, &buf
))
628 /* Stat failed - add ME to be able to complain about it later. */
629 buf
.st_dev
= me
->me_dev
;
633 /* If the device name is a real path name ... */
634 if (strchr (me
->me_devname
, '/'))
636 /* ... try to find its device number in the devlist. */
637 for (devlist
= devlist_head
; devlist
; devlist
= devlist
->next
)
638 if (devlist
->dev_num
== buf
.st_dev
)
645 /* Let the shorter mountdir win. */
646 if (! strchr (devlist
->me
->me_devname
, '/')
647 || (strlen (devlist
->me
->me_mountdir
)
648 > strlen (me
->me_mountdir
)))
650 discard_me
= devlist
->me
;
660 free_mount_entry (discard_me
);
664 /* Add the device number to the global list devlist. */
665 devlist
= xmalloc (sizeof *devlist
);
667 devlist
->dev_num
= buf
.st_dev
;
668 devlist
->next
= devlist_head
;
669 devlist_head
= devlist
;
675 /* Finally rebuild the mount_list from the devlist. */
679 /* Add the mount entry. */
680 me
= devlist_head
->me
;
681 me
->me_next
= mount_list
;
683 /* Free devlist entry and advance. */
684 struct devlist
*devlist
= devlist_head
->next
;
686 devlist_head
= devlist
;
690 /* Return true if N is a known integer value. On many file systems,
691 UINTMAX_MAX represents an unknown value; on AIX, UINTMAX_MAX - 1
692 represents unknown. Use a rule that works on AIX file systems, and
693 that almost-always works on other types. */
695 known_value (uintmax_t n
)
697 return n
< UINTMAX_MAX
- 1;
700 /* Like human_readable (N, BUF, human_output_opts, INPUT_UNITS, OUTPUT_UNITS),
703 - If NEGATIVE, then N represents a negative number,
704 expressed in two's complement.
705 - Otherwise, return "-" if N is unknown. */
708 df_readable (bool negative
, uintmax_t n
, char *buf
,
709 uintmax_t input_units
, uintmax_t output_units
)
711 if (! known_value (n
) && !negative
)
715 char *p
= human_readable (negative
? -n
: n
, buf
+ negative
,
716 human_output_opts
, input_units
, output_units
);
723 /* Logical equivalence */
724 #define LOG_EQ(a, b) (!(a) == !(b))
726 /* Add integral value while using uintmax_t for value part and separate
727 negation flag. It adds value of SRC and SRC_NEG to DEST and DEST_NEG.
728 The result will be in DEST and DEST_NEG. See df_readable to understand
729 how the negation flag is used. */
731 add_uint_with_neg_flag (uintmax_t *dest
, bool *dest_neg
,
732 uintmax_t src
, bool src_neg
)
734 if (LOG_EQ (*dest_neg
, src_neg
))
758 /* Return true if S ends in a string that may be a 36-byte UUID,
759 i.e., of the form HHHHHHHH-HHHH-HHHH-HHHH-HHHHHHHHHHHH, where
760 each H is an upper or lower case hexadecimal digit. */
761 static bool _GL_ATTRIBUTE_PURE
762 has_uuid_suffix (char const *s
)
764 size_t len
= strlen (s
);
766 && strspn (s
+ len
- 36, "-0123456789abcdefABCDEF") == 36);
769 /* Obtain the block values BV and inode values IV
770 from the file system usage FSU. */
772 get_field_values (struct field_values_t
*bv
,
773 struct field_values_t
*iv
,
774 const struct fs_usage
*fsu
)
777 iv
->input_units
= iv
->output_units
= 1;
778 iv
->total
= fsu
->fsu_files
;
779 iv
->available
= iv
->available_to_root
= fsu
->fsu_ffree
;
780 iv
->negate_available
= false;
782 iv
->used
= UINTMAX_MAX
;
783 iv
->negate_used
= false;
784 if (known_value (iv
->total
) && known_value (iv
->available_to_root
))
786 iv
->used
= iv
->total
- iv
->available_to_root
;
787 iv
->negate_used
= (iv
->total
< iv
->available_to_root
);
791 bv
->input_units
= fsu
->fsu_blocksize
;
792 bv
->output_units
= output_block_size
;
793 bv
->total
= fsu
->fsu_blocks
;
794 bv
->available
= fsu
->fsu_bavail
;
795 bv
->available_to_root
= fsu
->fsu_bfree
;
796 bv
->negate_available
= (fsu
->fsu_bavail_top_bit_set
797 && known_value (fsu
->fsu_bavail
));
799 bv
->used
= UINTMAX_MAX
;
800 bv
->negate_used
= false;
801 if (known_value (bv
->total
) && known_value (bv
->available_to_root
))
803 bv
->used
= bv
->total
- bv
->available_to_root
;
804 bv
->negate_used
= (bv
->total
< bv
->available_to_root
);
808 /* Add block and inode values to grand total. */
810 add_to_grand_total (struct field_values_t
*bv
, struct field_values_t
*iv
)
812 if (known_value (iv
->total
))
813 grand_fsu
.fsu_files
+= iv
->total
;
814 if (known_value (iv
->available
))
815 grand_fsu
.fsu_ffree
+= iv
->available
;
817 if (known_value (bv
->total
))
818 grand_fsu
.fsu_blocks
+= bv
->input_units
* bv
->total
;
819 if (known_value (bv
->available_to_root
))
820 grand_fsu
.fsu_bfree
+= bv
->input_units
* bv
->available_to_root
;
821 if (known_value (bv
->available
))
822 add_uint_with_neg_flag (&grand_fsu
.fsu_bavail
,
823 &grand_fsu
.fsu_bavail_top_bit_set
,
824 bv
->input_units
* bv
->available
,
825 bv
->negate_available
);
828 /* Obtain a space listing for the disk device with absolute file name DISK.
829 If MOUNT_POINT is non-NULL, it is the name of the root of the
831 If STAT_FILE is non-null, it is the name of a file within the file
832 system that the user originally asked for; this provides better
833 diagnostics, and sometimes it provides better results on networked
834 file systems that give different free-space results depending on
835 where in the file system you probe.
836 If FSTYPE is non-NULL, it is the type of the file system on DISK.
837 If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may
838 not be able to produce statistics in this case.
839 ME_DUMMY and ME_REMOTE are the mount entry flags.
840 Caller must set PROCESS_ALL to true when iterating over all entries, as
841 when df is invoked with no non-option argument. See below for details. */
844 get_dev (char const *disk
, char const *mount_point
, char const* file
,
845 char const *stat_file
, char const *fstype
,
846 bool me_dummy
, bool me_remote
,
847 const struct fs_usage
*force_fsu
,
850 if (me_remote
&& show_local_fs
)
853 if (me_dummy
&& !show_all_fs
&& !show_listed_fs
)
856 if (!selected_fstype (fstype
) || excluded_fstype (fstype
))
859 /* If MOUNT_POINT is NULL, then the file system is not mounted, and this
860 program reports on the file system that the special file is on.
861 It would be better to report on the unmounted file system,
862 but statfs doesn't do that on most systems. */
864 stat_file
= mount_point
? mount_point
: disk
;
869 else if (get_fs_usage (stat_file
, disk
, &fsu
))
871 error (0, errno
, "%s", quote (stat_file
));
872 exit_status
= EXIT_FAILURE
;
876 if (fsu
.fsu_blocks
== 0 && !show_all_fs
&& !show_listed_fs
)
880 file_systems_processed
= true;
885 disk
= "-"; /* unknown */
888 file
= "-"; /* unspecified */
890 char *dev_name
= xstrdup (disk
);
893 /* On some systems, dev_name is a long-named symlink like
894 /dev/disk/by-uuid/828fc648-9f30-43d8-a0b1-f7196a2edb66 pointing to a
895 much shorter and more useful name like /dev/sda1. It may also look
896 like /dev/mapper/luks-828fc648-9f30-43d8-a0b1-f7196a2edb66 and point to
897 /dev/dm-0. When process_all is true and dev_name is a symlink whose
898 name ends with a UUID use the resolved name instead. */
900 && has_uuid_suffix (dev_name
)
901 && (resolved_dev
= canonicalize_filename_mode (dev_name
, CAN_EXISTING
)))
904 dev_name
= resolved_dev
;
908 fstype
= "-"; /* unknown */
910 struct field_values_t block_values
;
911 struct field_values_t inode_values
;
912 get_field_values (&block_values
, &inode_values
, &fsu
);
914 /* Add to grand total unless processing grand total line. */
915 if (print_grand_total
&& ! force_fsu
)
916 add_to_grand_total (&block_values
, &inode_values
);
919 for (col
= 0; col
< ncolumns
; col
++)
921 char buf
[LONGEST_HUMAN_READABLE
+ 2];
924 struct field_values_t
*v
;
925 switch (columns
[col
]->field_type
)
937 assert (!"bad field_type");
940 switch (columns
[col
]->field
)
943 cell
= xstrdup (dev_name
);
947 cell
= xstrdup (fstype
);
952 cell
= xstrdup (df_readable (false, v
->total
, buf
,
953 v
->input_units
, v
->output_units
));
958 cell
= xstrdup (df_readable (v
->negate_used
, v
->used
, buf
,
959 v
->input_units
, v
->output_units
));
964 cell
= xstrdup (df_readable (v
->negate_available
, v
->available
, buf
,
965 v
->input_units
, v
->output_units
));
972 if (! known_value (v
->used
) || ! known_value (v
->available
))
974 else if (!v
->negate_used
975 && v
->used
<= TYPE_MAXIMUM (uintmax_t) / 100
976 && v
->used
+ v
->available
!= 0
977 && (v
->used
+ v
->available
< v
->used
)
978 == v
->negate_available
)
980 uintmax_t u100
= v
->used
* 100;
981 uintmax_t nonroot_total
= v
->used
+ v
->available
;
982 pct
= u100
/ nonroot_total
+ (u100
% nonroot_total
!= 0);
986 /* The calculation cannot be done easily with integer
987 arithmetic. Fall back on floating point. This can suffer
988 from minor rounding errors, but doing it exactly requires
989 multiple precision arithmetic, and it's not worth the
991 double u
= v
->negate_used
? - (double) - v
->used
: v
->used
;
992 double a
= v
->negate_available
993 ? - (double) - v
->available
: v
->available
;
994 double nonroot_total
= u
+ a
;
997 long int lipct
= pct
= u
* 100 / nonroot_total
;
1000 /* Like 'pct = ceil (dpct);', but avoid ceil so that
1001 the math library needn't be linked. */
1002 if (ipct
- 1 < pct
&& pct
<= ipct
+ 1)
1003 pct
= ipct
+ (ipct
< pct
);
1009 if (asprintf (&cell
, "%.0f%%", pct
) == -1)
1013 cell
= strdup ("-");
1022 cell
= xstrdup (file
);
1026 #ifdef HIDE_AUTOMOUNT_PREFIX
1027 /* Don't print the first directory name in MOUNT_POINT if it's an
1028 artifact of an automounter. This is a bit too aggressive to be
1030 if (STRNCMP_LIT (mount_point
, "/auto/") == 0)
1032 else if (STRNCMP_LIT (mount_point
, "/tmp_mnt/") == 0)
1035 cell
= xstrdup (mount_point
);
1039 assert (!"unhandled field");
1043 assert (!"empty cell");
1045 hide_problematic_chars (cell
);
1046 columns
[col
]->width
= MAX (columns
[col
]->width
, mbswidth (cell
, 0));
1047 table
[nrows
- 1][col
] = cell
;
1052 /* If DISK corresponds to a mount point, show its usage
1053 and return true. Otherwise, return false. */
1055 get_disk (char const *disk
)
1057 struct mount_entry
const *me
;
1058 struct mount_entry
const *best_match
= NULL
;
1059 char const *file
= disk
;
1061 char *resolved
= canonicalize_file_name (disk
);
1062 if (resolved
&& resolved
[0] == '/')
1065 size_t best_match_len
= SIZE_MAX
;
1066 for (me
= mount_list
; me
; me
= me
->me_next
)
1068 if (STREQ (disk
, me
->me_devname
))
1070 size_t len
= strlen (me
->me_mountdir
);
1071 if (len
< best_match_len
)
1074 if (len
== 1) /* Traditional root. */
1077 best_match_len
= len
;
1086 get_dev (best_match
->me_devname
, best_match
->me_mountdir
, file
, NULL
,
1087 best_match
->me_type
, best_match
->me_dummy
,
1088 best_match
->me_remote
, NULL
, false);
1095 /* Figure out which device file or directory POINT is mounted on
1096 and show its disk usage.
1097 STATP must be the result of 'stat (POINT, STATP)'. */
1099 get_point (const char *point
, const struct stat
*statp
)
1101 struct stat disk_stats
;
1102 struct mount_entry
*me
;
1103 struct mount_entry
const *best_match
= NULL
;
1105 /* Calculate the real absolute file name for POINT, and use that to find
1106 the mount point. This avoids statting unavailable mount points,
1107 which can hang df. */
1108 char *resolved
= canonicalize_file_name (point
);
1109 if (resolved
&& resolved
[0] == '/')
1111 size_t resolved_len
= strlen (resolved
);
1112 size_t best_match_len
= 0;
1114 for (me
= mount_list
; me
; me
= me
->me_next
)
1116 if (!STREQ (me
->me_type
, "lofs")
1117 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
1119 size_t len
= strlen (me
->me_mountdir
);
1120 if (best_match_len
<= len
&& len
<= resolved_len
1121 && (len
== 1 /* root file system */
1122 || ((len
== resolved_len
|| resolved
[len
] == '/')
1123 && STREQ_LEN (me
->me_mountdir
, resolved
, len
))))
1126 best_match_len
= len
;
1133 && (stat (best_match
->me_mountdir
, &disk_stats
) != 0
1134 || disk_stats
.st_dev
!= statp
->st_dev
))
1138 for (me
= mount_list
; me
; me
= me
->me_next
)
1140 if (me
->me_dev
== (dev_t
) -1)
1142 if (stat (me
->me_mountdir
, &disk_stats
) == 0)
1143 me
->me_dev
= disk_stats
.st_dev
;
1146 /* Report only I/O errors. Other errors might be
1147 caused by shadowed mount points, which means POINT
1148 can't possibly be on this file system. */
1151 error (0, errno
, "%s", quote (me
->me_mountdir
));
1152 exit_status
= EXIT_FAILURE
;
1155 /* So we won't try and fail repeatedly. */
1156 me
->me_dev
= (dev_t
) -2;
1160 if (statp
->st_dev
== me
->me_dev
1161 && !STREQ (me
->me_type
, "lofs")
1162 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
1164 /* Skip bogus mtab entries. */
1165 if (stat (me
->me_mountdir
, &disk_stats
) != 0
1166 || disk_stats
.st_dev
!= me
->me_dev
)
1167 me
->me_dev
= (dev_t
) -2;
1174 get_dev (best_match
->me_devname
, best_match
->me_mountdir
, point
, point
,
1175 best_match
->me_type
, best_match
->me_dummy
, best_match
->me_remote
,
1179 /* We couldn't find the mount entry corresponding to POINT. Go ahead and
1180 print as much info as we can; methods that require the device to be
1181 present will fail at a later point. */
1183 /* Find the actual mount point. */
1184 char *mp
= find_mount_point (point
, statp
);
1187 get_dev (NULL
, mp
, point
, NULL
, NULL
, false, false, NULL
, false);
1193 /* Determine what kind of node NAME is and show the disk usage
1194 for it. STATP is the results of 'stat' on NAME. */
1197 get_entry (char const *name
, struct stat
const *statp
)
1199 if ((S_ISBLK (statp
->st_mode
) || S_ISCHR (statp
->st_mode
))
1203 get_point (name
, statp
);
1206 /* Show all mounted file systems, except perhaps those that are of
1207 an unselected type or are empty. */
1210 get_all_entries (void)
1212 struct mount_entry
*me
;
1215 filter_mount_list ();
1217 for (me
= mount_list
; me
; me
= me
->me_next
)
1218 get_dev (me
->me_devname
, me
->me_mountdir
, NULL
, NULL
, me
->me_type
,
1219 me
->me_dummy
, me
->me_remote
, NULL
, true);
1222 /* Add FSTYPE to the list of file system types to display. */
1225 add_fs_type (const char *fstype
)
1227 struct fs_type_list
*fsp
;
1229 fsp
= xmalloc (sizeof *fsp
);
1230 fsp
->fs_name
= (char *) fstype
;
1231 fsp
->fs_next
= fs_select_list
;
1232 fs_select_list
= fsp
;
1235 /* Add FSTYPE to the list of file system types to be omitted. */
1238 add_excluded_fs_type (const char *fstype
)
1240 struct fs_type_list
*fsp
;
1242 fsp
= xmalloc (sizeof *fsp
);
1243 fsp
->fs_name
= (char *) fstype
;
1244 fsp
->fs_next
= fs_exclude_list
;
1245 fs_exclude_list
= fsp
;
1251 if (status
!= EXIT_SUCCESS
)
1255 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name
);
1257 Show information about the file system on which each FILE resides,\n\
1258 or all file systems by default.\n\
1261 emit_mandatory_arg_note ();
1264 -a, --all include dummy file systems\n\
1265 -B, --block-size=SIZE scale sizes by SIZE before printing them; e.g.,\n\
1266 '-BM' prints sizes in units of 1,048,576 bytes;\n\
1267 see SIZE format below\n\
1268 --total produce a grand total\n\
1269 -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\
1271 -H, --si likewise, but use powers of 1000 not 1024\n\
1274 -i, --inodes list inode information instead of block usage\n\
1275 -k like --block-size=1K\n\
1276 -l, --local limit listing to local file systems\n\
1277 --no-sync do not invoke sync before getting usage info (default)\
1281 --output[=FIELD_LIST] use the output format defined by FIELD_LIST,\n\
1282 or print all fields if FIELD_LIST is omitted.\n\
1283 -P, --portability use the POSIX output format\n\
1284 --sync invoke sync before getting usage info\n\
1285 -t, --type=TYPE limit listing to file systems of type TYPE\n\
1286 -T, --print-type print file system type\n\
1287 -x, --exclude-type=TYPE limit listing to file systems not of type TYPE\n\
1290 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
1291 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
1292 emit_blocksize_note ("DF");
1295 FIELD_LIST is a comma-separated list of columns to be included. Valid\n\
1296 field names are: 'source', 'fstype', 'itotal', 'iused', 'iavail', 'ipcent',\n\
1297 'size', 'used', 'avail', 'pcent', 'file' and 'target' (see info page).\n\
1299 emit_ancillary_info ();
1305 main (int argc
, char **argv
)
1307 struct stat
*stats
IF_LINT ( = 0);
1309 initialize_main (&argc
, &argv
);
1310 set_program_name (argv
[0]);
1311 setlocale (LC_ALL
, "");
1312 bindtextdomain (PACKAGE
, LOCALEDIR
);
1313 textdomain (PACKAGE
);
1315 atexit (close_stdout
);
1317 fs_select_list
= NULL
;
1318 fs_exclude_list
= NULL
;
1319 show_all_fs
= false;
1320 show_listed_fs
= false;
1321 human_output_opts
= -1;
1323 file_systems_processed
= false;
1324 exit_status
= EXIT_SUCCESS
;
1325 print_grand_total
= false;
1326 grand_fsu
.fsu_blocksize
= 1;
1328 /* If true, use the POSIX output format. */
1329 bool posix_format
= false;
1331 const char *msg_mut_excl
= _("options %s and %s are mutually exclusive");
1336 int c
= getopt_long (argc
, argv
, "aB:iF:hHklmPTt:vx:", long_options
,
1348 enum strtol_error e
= human_options (optarg
, &human_output_opts
,
1349 &output_block_size
);
1350 if (e
!= LONGINT_OK
)
1351 xstrtol_fatal (e
, oi
, c
, long_options
, optarg
);
1355 if (header_mode
== OUTPUT_MODE
)
1357 error (0, 0, msg_mut_excl
, "-i", "--output");
1358 usage (EXIT_FAILURE
);
1360 header_mode
= INODES_MODE
;
1363 human_output_opts
= human_autoscale
| human_SI
| human_base_1024
;
1364 output_block_size
= 1;
1367 human_output_opts
= human_autoscale
| human_SI
;
1368 output_block_size
= 1;
1371 human_output_opts
= 0;
1372 output_block_size
= 1024;
1375 show_local_fs
= true;
1377 case 'm': /* obsolescent, exists for BSD compatibility */
1378 human_output_opts
= 0;
1379 output_block_size
= 1024 * 1024;
1382 if (header_mode
== OUTPUT_MODE
)
1384 error (0, 0, msg_mut_excl
, "-T", "--output");
1385 usage (EXIT_FAILURE
);
1390 if (header_mode
== OUTPUT_MODE
)
1392 error (0, 0, msg_mut_excl
, "-P", "--output");
1393 usage (EXIT_FAILURE
);
1395 posix_format
= true;
1398 require_sync
= true;
1400 case NO_SYNC_OPTION
:
1401 require_sync
= false;
1405 /* Accept -F as a synonym for -t for compatibility with Solaris. */
1407 add_fs_type (optarg
);
1410 case 'v': /* For SysV compatibility. */
1414 add_excluded_fs_type (optarg
);
1418 if (header_mode
== INODES_MODE
)
1420 error (0, 0, msg_mut_excl
, "-i", "--output");
1421 usage (EXIT_FAILURE
);
1423 if (posix_format
&& header_mode
== DEFAULT_MODE
)
1425 error (0, 0, msg_mut_excl
, "-P", "--output");
1426 usage (EXIT_FAILURE
);
1430 error (0, 0, msg_mut_excl
, "-T", "--output");
1431 usage (EXIT_FAILURE
);
1433 header_mode
= OUTPUT_MODE
;
1435 decode_output_arg (optarg
);
1439 print_grand_total
= true;
1442 case_GETOPT_HELP_CHAR
;
1443 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
1446 usage (EXIT_FAILURE
);
1450 if (human_output_opts
== -1)
1454 human_output_opts
= 0;
1455 output_block_size
= (getenv ("POSIXLY_CORRECT") ? 512 : 1024);
1458 human_options (getenv ("DF_BLOCK_SIZE"),
1459 &human_output_opts
, &output_block_size
);
1462 if (header_mode
== INODES_MODE
|| header_mode
== OUTPUT_MODE
)
1464 else if (human_output_opts
& human_autoscale
)
1465 header_mode
= HUMAN_MODE
;
1466 else if (posix_format
)
1467 header_mode
= POSIX_MODE
;
1469 /* Fail if the same file system type was both selected and excluded. */
1472 struct fs_type_list
*fs_incl
;
1473 for (fs_incl
= fs_select_list
; fs_incl
; fs_incl
= fs_incl
->fs_next
)
1475 struct fs_type_list
*fs_excl
;
1476 for (fs_excl
= fs_exclude_list
; fs_excl
; fs_excl
= fs_excl
->fs_next
)
1478 if (STREQ (fs_incl
->fs_name
, fs_excl
->fs_name
))
1481 _("file system type %s both selected and excluded"),
1482 quote (fs_incl
->fs_name
));
1489 exit (EXIT_FAILURE
);
1496 /* Open each of the given entries to make sure any corresponding
1497 partition is automounted. This must be done before reading the
1498 file system table. */
1499 stats
= xnmalloc (argc
- optind
, sizeof *stats
);
1500 for (i
= optind
; i
< argc
; ++i
)
1502 /* Prefer to open with O_NOCTTY and use fstat, but fall back
1503 on using "stat", in case the file is unreadable. */
1504 int fd
= open (argv
[i
], O_RDONLY
| O_NOCTTY
);
1505 if ((fd
< 0 || fstat (fd
, &stats
[i
- optind
]))
1506 && stat (argv
[i
], &stats
[i
- optind
]))
1508 error (0, errno
, "%s", quote (argv
[i
]));
1509 exit_status
= EXIT_FAILURE
;
1518 read_file_system_list ((fs_select_list
!= NULL
1519 || fs_exclude_list
!= NULL
1521 || field_data
[FSTYPE_FIELD
].used
1524 if (mount_list
== NULL
)
1526 /* Couldn't read the table of mounted file systems.
1527 Fail if df was invoked with no file name arguments,
1528 or when either of -a, -l, -t or -x is used with file name
1529 arguments. Otherwise, merely give a warning and proceed. */
1531 if ( ! (optind
< argc
)
1534 || fs_select_list
!= NULL
1535 || fs_exclude_list
!= NULL
))
1537 status
= EXIT_FAILURE
;
1539 const char *warning
= (status
== 0 ? _("Warning: ") : "");
1540 error (status
, errno
, "%s%s", warning
,
1541 _("cannot read table of mounted file systems"));
1554 /* Display explicitly requested empty file systems. */
1555 show_listed_fs
= true;
1557 for (i
= optind
; i
< argc
; ++i
)
1559 get_entry (argv
[i
], &stats
[i
- optind
]);
1564 if (file_systems_processed
)
1566 if (print_grand_total
)
1568 (field_data
[SOURCE_FIELD
].used
? "-" : "total"),
1569 NULL
, NULL
, NULL
, false, false, &grand_fsu
, false);
1575 /* Print the "no FS processed" diagnostic only if there was no preceding
1576 diagnostic, e.g., if all have been excluded. */
1577 if (exit_status
== EXIT_SUCCESS
)
1578 error (EXIT_FAILURE
, 0, _("no file systems processed"));
1581 IF_LINT (free (columns
));