md5sum, sha*sum: improve help for --check related options
[coreutils.git] / src / df.c
blob949fe2fe3be4d39f6e139addf0f5d0ab8631ddad
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. */
21 #include <config.h>
22 #include <stdio.h>
23 #include <sys/types.h>
24 #include <getopt.h>
25 #include <assert.h>
27 #include "system.h"
28 #include "canonicalize.h"
29 #include "error.h"
30 #include "fsusage.h"
31 #include "human.h"
32 #include "mbsalign.h"
33 #include "mbswidth.h"
34 #include "mountlist.h"
35 #include "quote.h"
36 #include "find-mount-point.h"
38 /* The official name of this program (e.g., no 'g' prefix). */
39 #define PROGRAM_NAME "df"
41 #define AUTHORS \
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. */
48 struct devlist
50 dev_t dev_num;
51 struct mount_entry *me;
52 struct devlist *next;
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. */
86 struct fs_type_list
88 char *fs_name;
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
98 will be shown.
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;
122 /* Display modes. */
123 enum
125 DEFAULT_MODE,
126 INODES_MODE,
127 HUMAN_MODE,
128 POSIX_MODE,
129 OUTPUT_MODE
131 static int header_mode = DEFAULT_MODE;
133 /* Displayable fields. */
134 typedef enum
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 } display_field_t;
149 /* Flag if a field contains a block, an inode or another value. */
150 typedef enum
152 BLOCK_FLD, /* Block values field */
153 INODE_FLD, /* Inode values field */
154 OTHER_FLD /* Neutral field, e.g. target */
155 } field_type_t;
157 /* Attributes of a display field. */
158 struct field_data_t
160 display_field_t field;
161 char const *arg;
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. */
166 bool used;
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;
214 /* Field values. */
215 struct field_values_t
217 uintmax_t input_units;
218 uintmax_t output_units;
219 uintmax_t total;
220 uintmax_t available;
221 bool negate_available;
222 uintmax_t available_to_root;
223 uintmax_t used;
224 bool negate_used;
227 /* Storage for pointers for each string (cell of table). */
228 static char ***table;
230 /* The current number of processed rows (including header). */
231 static size_t nrows;
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. */
235 enum
237 NO_SYNC_OPTION = CHAR_MAX + 1,
238 SYNC_OPTION,
239 TOTAL_OPTION,
240 OUTPUT_OPTION,
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},
263 {NULL, 0, NULL, 0}
266 /* Replace problematic chars with '?'.
267 Since only control characters are currently considered,
268 this should work in all encodings. */
270 static char*
271 hide_problematic_chars (char *cell)
273 char *p = cell;
274 while (*p)
276 if (iscntrl (to_uchar (*p)))
277 *p = '?';
278 p++;
280 return cell;
283 /* Dynamically allocate a row of pointers in TABLE, which
284 can then be accessed with standard 2D array notation. */
286 static void
287 alloc_table_row (void)
289 nrows++;
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. */
297 static void
298 print_table (void)
300 size_t row;
302 for (row = 0; row < nrows; row++)
304 size_t col;
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. */
313 if (col != 0)
314 putchar (' ');
316 int flags = 0;
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);
324 free (cell);
326 IF_LINT (free (table[row][col]));
328 putchar ('\n');
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. */
338 static void
339 alloc_field (int f, const char *c)
341 ncolumns++;
342 columns = xnrealloc (columns, ncolumns, sizeof (struct field_data_t *));
343 columns[ncolumns - 1] = &field_data[f];
344 if (c != NULL)
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. */
357 static void
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. */
368 if (comma)
369 *comma++ = 0;
371 /* process S. */
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))
377 field = i;
378 break;
381 if (field == -1)
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);
395 switch (field)
397 case SOURCE_FIELD:
398 case FSTYPE_FIELD:
399 case USED_FIELD:
400 case PCENT_FIELD:
401 case ITOTAL_FIELD:
402 case IUSED_FIELD:
403 case IAVAIL_FIELD:
404 case IPCENT_FIELD:
405 case TARGET_FIELD:
406 alloc_field (field, NULL);
407 break;
409 case SIZE_FIELD:
410 alloc_field (field, N_("Size"));
411 break;
413 case AVAIL_FIELD:
414 alloc_field (field, N_("Avail"));
415 break;
417 default:
418 assert (!"invalid field");
420 s = comma;
422 while (s);
424 free (arg_writable);
427 /* Get the appropriate columns for the mode. */
428 static void
429 get_field_list (void)
431 switch (header_mode)
433 case DEFAULT_MODE:
434 alloc_field (SOURCE_FIELD, NULL);
435 if (print_type)
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);
442 break;
444 case HUMAN_MODE:
445 alloc_field (SOURCE_FIELD, NULL);
446 if (print_type)
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);
454 break;
456 case INODES_MODE:
457 alloc_field (SOURCE_FIELD, NULL);
458 if (print_type)
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);
465 break;
467 case POSIX_MODE:
468 alloc_field (SOURCE_FIELD, NULL);
469 if (print_type)
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);
476 break;
478 case OUTPUT_MODE:
479 if (!ncolumns)
481 /* Add all fields if --output was given without a field list. */
482 decode_output_arg (all_args_string);
484 break;
486 default:
487 assert (!"invalid header_mode");
491 /* Obtain the appropriate header entries. */
493 static void
494 get_header (void)
496 size_t col;
498 alloc_table_row ();
500 for (col = 0; col < ncolumns; col++)
502 char *cell = NULL;
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
514 | (human_output_opts
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))
537 opts |= human_B;
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)
546 cell = NULL;
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)
555 cell = NULL;
557 else
558 cell = strdup (header);
560 if (!cell)
561 xalloc_die ();
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)
579 return true;
580 for (fsp = fs_select_list; fsp; fsp = fsp->fs_next)
581 if (STREQ (fstype, fsp->fs_name))
582 return true;
583 return false;
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)
594 return false;
595 for (fsp = fs_exclude_list; fsp; fsp = fsp->fs_next)
596 if (STREQ (fstype, fsp->fs_name))
597 return true;
598 return false;
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
605 me_mountdir wins. */
607 static void
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;)
618 struct stat buf;
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;
627 else
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)
635 break;
637 if (devlist)
639 discard_me = me;
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;
647 devlist->me = me;
653 if (discard_me)
655 me = me->me_next;
656 free_mount_entry (discard_me);
658 else
660 /* Add the device number to the global list devlist. */
661 devlist = xmalloc (sizeof *devlist);
662 devlist->me = me;
663 devlist->dev_num = buf.st_dev;
664 devlist->next = devlist_head;
665 devlist_head = devlist;
667 me = me->me_next;
671 /* Finally rebuild the mount_list from the devlist. */
672 mount_list = NULL;
673 while (devlist_head)
675 /* Add the mount entry. */
676 me = devlist_head->me;
677 me->me_next = mount_list;
678 mount_list = me;
679 /* Free devlist entry and advance. */
680 struct devlist *devlist = devlist_head->next;
681 free (devlist_head);
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. */
690 static bool
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),
697 except:
699 - If NEGATIVE, then N represents a negative number,
700 expressed in two's complement.
701 - Otherwise, return "-" if N is unknown. */
703 static char const *
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)
708 return "-";
709 else
711 char *p = human_readable (negative ? -n : n, buf + negative,
712 human_output_opts, input_units, output_units);
713 if (negative)
714 *--p = '-';
715 return p;
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. */
726 static void
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))
732 *dest += src;
733 return;
736 if (*dest_neg)
737 *dest = -*dest;
739 if (src_neg)
740 src = -src;
742 if (src < *dest)
743 *dest -= src;
744 else
746 *dest = src - *dest;
747 *dest_neg = src_neg;
750 if (*dest_neg)
751 *dest = -*dest;
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);
761 return (36 < len
762 && strspn (s + len - 36, "-0123456789abcdefABCDEF") == 36);
765 /* Obtain the block values BV and inode values IV
766 from the file system usage FSU. */
767 static void
768 get_field_values (struct field_values_t *bv,
769 struct field_values_t *iv,
770 const struct fs_usage *fsu)
772 /* Inode values. */
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);
786 /* Block values. */
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. */
805 static void
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
826 file system on DISK.
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. */
839 static void
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,
844 bool process_all)
846 if (me_remote && show_local_fs)
847 return;
849 if (me_dummy && !show_all_fs && !show_listed_fs)
850 return;
852 if (!selected_fstype (fstype) || excluded_fstype (fstype))
853 return;
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. */
859 if (!stat_file)
860 stat_file = mount_point ? mount_point : disk;
862 struct fs_usage fsu;
863 if (force_fsu)
864 fsu = *force_fsu;
865 else if (get_fs_usage (stat_file, disk, &fsu))
867 error (0, errno, "%s", quote (stat_file));
868 exit_status = EXIT_FAILURE;
869 return;
872 if (fsu.fsu_blocks == 0 && !show_all_fs && !show_listed_fs)
873 return;
875 if (! force_fsu)
876 file_systems_processed = true;
878 alloc_table_row ();
880 if (! disk)
881 disk = "-"; /* unknown */
883 char *dev_name = xstrdup (disk);
884 char *resolved_dev;
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. */
892 if (process_all
893 && has_uuid_suffix (dev_name)
894 && (resolved_dev = canonicalize_filename_mode (dev_name, CAN_EXISTING)))
896 free (dev_name);
897 dev_name = resolved_dev;
900 if (! fstype)
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);
911 size_t col;
912 for (col = 0; col < ncolumns; col++)
914 char buf[LONGEST_HUMAN_READABLE + 2];
915 char *cell;
917 struct field_values_t *v;
918 switch (columns[col]->field_type)
920 case BLOCK_FLD:
921 v = &block_values;
922 break;
923 case INODE_FLD:
924 v = &inode_values;
925 break;
926 case OTHER_FLD:
927 v = NULL;
928 break;
929 default:
930 assert (!"bad field_type");
933 switch (columns[col]->field)
935 case SOURCE_FIELD:
936 cell = xstrdup (dev_name);
937 break;
939 case FSTYPE_FIELD:
940 cell = xstrdup (fstype);
941 break;
943 case SIZE_FIELD:
944 case ITOTAL_FIELD:
945 cell = xstrdup (df_readable (false, v->total, buf,
946 v->input_units, v->output_units));
947 break;
949 case USED_FIELD:
950 case IUSED_FIELD:
951 cell = xstrdup (df_readable (v->negate_used, v->used, buf,
952 v->input_units, v->output_units));
953 break;
955 case AVAIL_FIELD:
956 case IAVAIL_FIELD:
957 cell = xstrdup (df_readable (v->negate_available, v->available, buf,
958 v->input_units, v->output_units));
959 break;
961 case PCENT_FIELD:
962 case IPCENT_FIELD:
964 double pct = -1;
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);
977 else
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
983 aggravation. */
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;
988 if (nonroot_total)
990 long int lipct = pct = u * 100 / nonroot_total;
991 double ipct = lipct;
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);
1000 if (0 <= pct)
1002 if (asprintf (&cell, "%.0f%%", pct) == -1)
1003 cell = NULL;
1005 else
1006 cell = strdup ("-");
1008 if (!cell)
1009 xalloc_die ();
1011 break;
1014 case TARGET_FIELD:
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
1018 the default. */
1019 if (STRNCMP_LIT (mount_point, "/auto/") == 0)
1020 mount_point += 5;
1021 else if (STRNCMP_LIT (mount_point, "/tmp_mnt/") == 0)
1022 mount_point += 8;
1023 #endif
1024 cell = xstrdup (mount_point);
1025 break;
1027 default:
1028 assert (!"unhandled field");
1031 if (!cell)
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;
1038 free (dev_name);
1041 /* If DISK corresponds to a mount point, show its usage
1042 and return true. Otherwise, return false. */
1043 static bool
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))
1052 best_match = me;
1055 if (best_match)
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);
1060 return true;
1063 return 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)'. */
1069 static void
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))))
1096 best_match = me;
1097 best_match_len = len;
1102 free (resolved);
1103 if (best_match
1104 && (stat (best_match->me_mountdir, &disk_stats) != 0
1105 || disk_stats.st_dev != statp->st_dev))
1106 best_match = NULL;
1108 if (! best_match)
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;
1115 else
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. */
1120 if (errno == EIO)
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;
1139 else
1140 best_match = me;
1144 if (best_match)
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,
1147 NULL, false);
1148 else
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);
1156 if (mp)
1158 get_dev (NULL, mp, NULL, NULL, false, false, NULL, false);
1159 free (mp);
1164 /* Determine what kind of node NAME is and show the disk usage
1165 for it. STATP is the results of 'stat' on NAME. */
1167 static void
1168 get_entry (char const *name, struct stat const *statp)
1170 if ((S_ISBLK (statp->st_mode) || S_ISCHR (statp->st_mode))
1171 && get_disk (name))
1172 return;
1174 get_point (name, statp);
1177 /* Show all mounted file systems, except perhaps those that are of
1178 an unselected type or are empty. */
1180 static void
1181 get_all_entries (void)
1183 struct mount_entry *me;
1185 if (!show_all_fs)
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. */
1195 static void
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. */
1208 static void
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;
1219 void
1220 usage (int status)
1222 if (status != EXIT_SUCCESS)
1223 emit_try_help ();
1224 else
1226 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name);
1227 fputs (_("\
1228 Show information about the file system on which each FILE resides,\n\
1229 or all file systems by default.\n\
1230 "), stdout);
1232 emit_mandatory_arg_note ();
1234 fputs (_("\
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\
1243 "), stdout);
1244 fputs (_("\
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)\
1250 "), stdout);
1251 fputs (_("\
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\
1259 -v (ignored)\n\
1260 "), stdout);
1261 fputs (HELP_OPTION_DESCRIPTION, stdout);
1262 fputs (VERSION_OPTION_DESCRIPTION, stdout);
1263 emit_blocksize_note ("DF");
1264 emit_size_note ();
1265 fputs (_("\n\
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\
1269 "), stdout);
1270 emit_ancillary_info ();
1272 exit (status);
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;
1293 print_type = false;
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");
1304 while (true)
1306 int oi = -1;
1307 int c = getopt_long (argc, argv, "aB:iF:hHklmPTt:vx:", long_options,
1308 &oi);
1309 if (c == -1)
1310 break;
1312 switch (c)
1314 case 'a':
1315 show_all_fs = true;
1316 break;
1317 case 'B':
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);
1324 break;
1325 case 'i':
1326 if (header_mode == OUTPUT_MODE)
1328 error (0, 0, msg_mut_excl, "-i", "--output");
1329 usage (EXIT_FAILURE);
1331 header_mode = INODES_MODE;
1332 break;
1333 case 'h':
1334 human_output_opts = human_autoscale | human_SI | human_base_1024;
1335 output_block_size = 1;
1336 break;
1337 case 'H':
1338 human_output_opts = human_autoscale | human_SI;
1339 output_block_size = 1;
1340 break;
1341 case 'k':
1342 human_output_opts = 0;
1343 output_block_size = 1024;
1344 break;
1345 case 'l':
1346 show_local_fs = true;
1347 break;
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;
1358 break;
1359 case 'T':
1360 if (header_mode == OUTPUT_MODE)
1362 error (0, 0, msg_mut_excl, "-T", "--output");
1363 usage (EXIT_FAILURE);
1365 print_type = true;
1366 break;
1367 case 'P':
1368 if (header_mode == OUTPUT_MODE)
1370 error (0, 0, msg_mut_excl, "-P", "--output");
1371 usage (EXIT_FAILURE);
1373 posix_format = true;
1374 break;
1375 case SYNC_OPTION:
1376 require_sync = true;
1377 break;
1378 case NO_SYNC_OPTION:
1379 require_sync = false;
1380 break;
1382 case 'F':
1383 /* Accept -F as a synonym for -t for compatibility with Solaris. */
1384 case 't':
1385 add_fs_type (optarg);
1386 break;
1388 case 'v': /* For SysV compatibility. */
1389 /* ignore */
1390 break;
1391 case 'x':
1392 add_excluded_fs_type (optarg);
1393 break;
1395 case OUTPUT_OPTION:
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);
1406 if (print_type)
1408 error (0, 0, msg_mut_excl, "-T", "--output");
1409 usage (EXIT_FAILURE);
1411 header_mode = OUTPUT_MODE;
1412 if (optarg)
1413 decode_output_arg (optarg);
1414 break;
1416 case TOTAL_OPTION:
1417 print_grand_total = true;
1418 break;
1420 case_GETOPT_HELP_CHAR;
1421 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1423 default:
1424 usage (EXIT_FAILURE);
1428 if (human_output_opts == -1)
1430 if (posix_format)
1432 human_output_opts = 0;
1433 output_block_size = (getenv ("POSIXLY_CORRECT") ? 512 : 1024);
1435 else
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. */
1449 bool match = false;
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))
1458 error (0, 0,
1459 _("file system type %s both selected and excluded"),
1460 quote (fs_incl->fs_name));
1461 match = true;
1462 break;
1466 if (match)
1467 exit (EXIT_FAILURE);
1470 if (optind < argc)
1472 int i;
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;
1488 argv[i] = NULL;
1490 if (0 <= fd)
1491 close (fd);
1495 mount_list =
1496 read_file_system_list ((fs_select_list != NULL
1497 || fs_exclude_list != NULL
1498 || print_type
1499 || field_data[FSTYPE_FIELD].used
1500 || show_local_fs));
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. */
1508 int status = 0;
1509 if ( ! (optind < argc)
1510 || (show_all_fs
1511 || show_local_fs
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"));
1522 if (require_sync)
1523 sync ();
1525 get_field_list ();
1526 get_header ();
1528 if (optind < argc)
1530 int i;
1532 /* Display explicitly requested empty file systems. */
1533 show_listed_fs = true;
1535 for (i = optind; i < argc; ++i)
1536 if (argv[i])
1537 get_entry (argv[i], &stats[i - optind]);
1539 else
1540 get_all_entries ();
1542 if (file_systems_processed)
1544 if (print_grand_total)
1545 get_dev ("total",
1546 (field_data[SOURCE_FIELD].used ? "-" : "total"),
1547 NULL, NULL, false, false, &grand_fsu, false);
1549 print_table ();
1551 else
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));
1561 exit (exit_status);