df: handle bind mounts when processing device nodes
[coreutils.git] / src / df.c
blob969670e821760d09f74aaf22741f549a22f190b7
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 FILE_FIELD /* specified file name */
148 } display_field_t;
150 /* Flag if a field contains a block, an inode or another value. */
151 typedef enum
153 BLOCK_FLD, /* Block values field */
154 INODE_FLD, /* Inode values field */
155 OTHER_FLD /* Neutral field, e.g. target */
156 } field_type_t;
158 /* Attributes of a display field. */
159 struct field_data_t
161 display_field_t field;
162 char const *arg;
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. */
167 bool used;
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;
219 /* Field values. */
220 struct field_values_t
222 uintmax_t input_units;
223 uintmax_t output_units;
224 uintmax_t total;
225 uintmax_t available;
226 bool negate_available;
227 uintmax_t available_to_root;
228 uintmax_t used;
229 bool negate_used;
232 /* Storage for pointers for each string (cell of table). */
233 static char ***table;
235 /* The current number of processed rows (including header). */
236 static size_t nrows;
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. */
240 enum
242 NO_SYNC_OPTION = CHAR_MAX + 1,
243 SYNC_OPTION,
244 TOTAL_OPTION,
245 OUTPUT_OPTION
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},
266 {NULL, 0, NULL, 0}
269 /* Replace problematic chars with '?'.
270 Since only control characters are currently considered,
271 this should work in all encodings. */
273 static char*
274 hide_problematic_chars (char *cell)
276 char *p = cell;
277 while (*p)
279 if (iscntrl (to_uchar (*p)))
280 *p = '?';
281 p++;
283 return cell;
286 /* Dynamically allocate a row of pointers in TABLE, which
287 can then be accessed with standard 2D array notation. */
289 static void
290 alloc_table_row (void)
292 nrows++;
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. */
300 static void
301 print_table (void)
303 size_t row;
305 for (row = 0; row < nrows; row++)
307 size_t col;
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. */
316 if (col != 0)
317 putchar (' ');
319 int flags = 0;
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);
327 free (cell);
329 IF_LINT (free (table[row][col]));
331 putchar ('\n');
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. */
341 static void
342 alloc_field (int f, const char *c)
344 ncolumns++;
345 columns = xnrealloc (columns, ncolumns, sizeof (struct field_data_t *));
346 columns[ncolumns - 1] = &field_data[f];
347 if (c != NULL)
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. */
360 static void
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. */
371 if (comma)
372 *comma++ = 0;
374 /* process S. */
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))
380 field = i;
381 break;
384 if (field == -1)
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);
398 switch (field)
400 case SOURCE_FIELD:
401 case FSTYPE_FIELD:
402 case USED_FIELD:
403 case PCENT_FIELD:
404 case ITOTAL_FIELD:
405 case IUSED_FIELD:
406 case IAVAIL_FIELD:
407 case IPCENT_FIELD:
408 case TARGET_FIELD:
409 case FILE_FIELD:
410 alloc_field (field, NULL);
411 break;
413 case SIZE_FIELD:
414 alloc_field (field, N_("Size"));
415 break;
417 case AVAIL_FIELD:
418 alloc_field (field, N_("Avail"));
419 break;
421 default:
422 assert (!"invalid field");
424 s = comma;
426 while (s);
428 free (arg_writable);
431 /* Get the appropriate columns for the mode. */
432 static void
433 get_field_list (void)
435 switch (header_mode)
437 case DEFAULT_MODE:
438 alloc_field (SOURCE_FIELD, NULL);
439 if (print_type)
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);
446 break;
448 case HUMAN_MODE:
449 alloc_field (SOURCE_FIELD, NULL);
450 if (print_type)
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);
458 break;
460 case INODES_MODE:
461 alloc_field (SOURCE_FIELD, NULL);
462 if (print_type)
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);
469 break;
471 case POSIX_MODE:
472 alloc_field (SOURCE_FIELD, NULL);
473 if (print_type)
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);
480 break;
482 case OUTPUT_MODE:
483 if (!ncolumns)
485 /* Add all fields if --output was given without a field list. */
486 decode_output_arg (all_args_string);
488 break;
490 default:
491 assert (!"invalid header_mode");
495 /* Obtain the appropriate header entries. */
497 static void
498 get_header (void)
500 size_t col;
502 alloc_table_row ();
504 for (col = 0; col < ncolumns; col++)
506 char *cell = NULL;
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
518 | (human_output_opts
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))
541 opts |= human_B;
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)
550 cell = NULL;
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)
559 cell = NULL;
561 else
562 cell = strdup (header);
564 if (!cell)
565 xalloc_die ();
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)
583 return true;
584 for (fsp = fs_select_list; fsp; fsp = fsp->fs_next)
585 if (STREQ (fstype, fsp->fs_name))
586 return true;
587 return false;
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)
598 return false;
599 for (fsp = fs_exclude_list; fsp; fsp = fsp->fs_next)
600 if (STREQ (fstype, fsp->fs_name))
601 return true;
602 return false;
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
609 me_mountdir wins. */
611 static void
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;)
622 struct stat buf;
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;
631 else
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)
639 break;
641 if (devlist)
643 discard_me = me;
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;
651 devlist->me = me;
657 if (discard_me)
659 me = me->me_next;
660 free_mount_entry (discard_me);
662 else
664 /* Add the device number to the global list devlist. */
665 devlist = xmalloc (sizeof *devlist);
666 devlist->me = me;
667 devlist->dev_num = buf.st_dev;
668 devlist->next = devlist_head;
669 devlist_head = devlist;
671 me = me->me_next;
675 /* Finally rebuild the mount_list from the devlist. */
676 mount_list = NULL;
677 while (devlist_head)
679 /* Add the mount entry. */
680 me = devlist_head->me;
681 me->me_next = mount_list;
682 mount_list = me;
683 /* Free devlist entry and advance. */
684 struct devlist *devlist = devlist_head->next;
685 free (devlist_head);
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. */
694 static bool
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),
701 except:
703 - If NEGATIVE, then N represents a negative number,
704 expressed in two's complement.
705 - Otherwise, return "-" if N is unknown. */
707 static char const *
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)
712 return "-";
713 else
715 char *p = human_readable (negative ? -n : n, buf + negative,
716 human_output_opts, input_units, output_units);
717 if (negative)
718 *--p = '-';
719 return p;
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. */
730 static void
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))
736 *dest += src;
737 return;
740 if (*dest_neg)
741 *dest = -*dest;
743 if (src_neg)
744 src = -src;
746 if (src < *dest)
747 *dest -= src;
748 else
750 *dest = src - *dest;
751 *dest_neg = src_neg;
754 if (*dest_neg)
755 *dest = -*dest;
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);
765 return (36 < len
766 && strspn (s + len - 36, "-0123456789abcdefABCDEF") == 36);
769 /* Obtain the block values BV and inode values IV
770 from the file system usage FSU. */
771 static void
772 get_field_values (struct field_values_t *bv,
773 struct field_values_t *iv,
774 const struct fs_usage *fsu)
776 /* Inode values. */
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);
790 /* Block values. */
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. */
809 static void
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
830 file system on DISK.
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. */
843 static void
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,
848 bool process_all)
850 if (me_remote && show_local_fs)
851 return;
853 if (me_dummy && !show_all_fs && !show_listed_fs)
854 return;
856 if (!selected_fstype (fstype) || excluded_fstype (fstype))
857 return;
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. */
863 if (!stat_file)
864 stat_file = mount_point ? mount_point : disk;
866 struct fs_usage fsu;
867 if (force_fsu)
868 fsu = *force_fsu;
869 else if (get_fs_usage (stat_file, disk, &fsu))
871 error (0, errno, "%s", quote (stat_file));
872 exit_status = EXIT_FAILURE;
873 return;
876 if (fsu.fsu_blocks == 0 && !show_all_fs && !show_listed_fs)
877 return;
879 if (! force_fsu)
880 file_systems_processed = true;
882 alloc_table_row ();
884 if (! disk)
885 disk = "-"; /* unknown */
887 if (! file)
888 file = "-"; /* unspecified */
890 char *dev_name = xstrdup (disk);
891 char *resolved_dev;
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. */
899 if (process_all
900 && has_uuid_suffix (dev_name)
901 && (resolved_dev = canonicalize_filename_mode (dev_name, CAN_EXISTING)))
903 free (dev_name);
904 dev_name = resolved_dev;
907 if (! fstype)
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);
918 size_t col;
919 for (col = 0; col < ncolumns; col++)
921 char buf[LONGEST_HUMAN_READABLE + 2];
922 char *cell;
924 struct field_values_t *v;
925 switch (columns[col]->field_type)
927 case BLOCK_FLD:
928 v = &block_values;
929 break;
930 case INODE_FLD:
931 v = &inode_values;
932 break;
933 case OTHER_FLD:
934 v = NULL;
935 break;
936 default:
937 assert (!"bad field_type");
940 switch (columns[col]->field)
942 case SOURCE_FIELD:
943 cell = xstrdup (dev_name);
944 break;
946 case FSTYPE_FIELD:
947 cell = xstrdup (fstype);
948 break;
950 case SIZE_FIELD:
951 case ITOTAL_FIELD:
952 cell = xstrdup (df_readable (false, v->total, buf,
953 v->input_units, v->output_units));
954 break;
956 case USED_FIELD:
957 case IUSED_FIELD:
958 cell = xstrdup (df_readable (v->negate_used, v->used, buf,
959 v->input_units, v->output_units));
960 break;
962 case AVAIL_FIELD:
963 case IAVAIL_FIELD:
964 cell = xstrdup (df_readable (v->negate_available, v->available, buf,
965 v->input_units, v->output_units));
966 break;
968 case PCENT_FIELD:
969 case IPCENT_FIELD:
971 double pct = -1;
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);
984 else
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
990 aggravation. */
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;
995 if (nonroot_total)
997 long int lipct = pct = u * 100 / nonroot_total;
998 double ipct = lipct;
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);
1007 if (0 <= pct)
1009 if (asprintf (&cell, "%.0f%%", pct) == -1)
1010 cell = NULL;
1012 else
1013 cell = strdup ("-");
1015 if (!cell)
1016 xalloc_die ();
1018 break;
1021 case FILE_FIELD:
1022 cell = xstrdup (file);
1023 break;
1025 case TARGET_FIELD:
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
1029 the default. */
1030 if (STRNCMP_LIT (mount_point, "/auto/") == 0)
1031 mount_point += 5;
1032 else if (STRNCMP_LIT (mount_point, "/tmp_mnt/") == 0)
1033 mount_point += 8;
1034 #endif
1035 cell = xstrdup (mount_point);
1036 break;
1038 default:
1039 assert (!"unhandled field");
1042 if (!cell)
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;
1049 free (dev_name);
1052 /* If DISK corresponds to a mount point, show its usage
1053 and return true. Otherwise, return false. */
1054 static bool
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] == '/')
1063 disk = resolved;
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)
1073 best_match = me;
1074 if (len == 1) /* Traditional root. */
1075 break;
1076 else
1077 best_match_len = len;
1082 free (resolved);
1084 if (best_match)
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);
1089 return true;
1092 return 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)'. */
1098 static void
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))))
1125 best_match = me;
1126 best_match_len = len;
1131 free (resolved);
1132 if (best_match
1133 && (stat (best_match->me_mountdir, &disk_stats) != 0
1134 || disk_stats.st_dev != statp->st_dev))
1135 best_match = NULL;
1137 if (! best_match)
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;
1144 else
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. */
1149 if (errno == EIO)
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;
1168 else
1169 best_match = me;
1173 if (best_match)
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,
1176 NULL, false);
1177 else
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);
1185 if (mp)
1187 get_dev (NULL, mp, point, NULL, NULL, false, false, NULL, false);
1188 free (mp);
1193 /* Determine what kind of node NAME is and show the disk usage
1194 for it. STATP is the results of 'stat' on NAME. */
1196 static void
1197 get_entry (char const *name, struct stat const *statp)
1199 if ((S_ISBLK (statp->st_mode) || S_ISCHR (statp->st_mode))
1200 && get_disk (name))
1201 return;
1203 get_point (name, statp);
1206 /* Show all mounted file systems, except perhaps those that are of
1207 an unselected type or are empty. */
1209 static void
1210 get_all_entries (void)
1212 struct mount_entry *me;
1214 if (!show_all_fs)
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. */
1224 static void
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. */
1237 static void
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;
1248 void
1249 usage (int status)
1251 if (status != EXIT_SUCCESS)
1252 emit_try_help ();
1253 else
1255 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name);
1256 fputs (_("\
1257 Show information about the file system on which each FILE resides,\n\
1258 or all file systems by default.\n\
1259 "), stdout);
1261 emit_mandatory_arg_note ();
1263 fputs (_("\
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\
1272 "), stdout);
1273 fputs (_("\
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)\
1279 "), stdout);
1280 fputs (_("\
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\
1288 -v (ignored)\n\
1289 "), stdout);
1290 fputs (HELP_OPTION_DESCRIPTION, stdout);
1291 fputs (VERSION_OPTION_DESCRIPTION, stdout);
1292 emit_blocksize_note ("DF");
1293 emit_size_note ();
1294 fputs (_("\n\
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\
1298 "), stdout);
1299 emit_ancillary_info ();
1301 exit (status);
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;
1322 print_type = false;
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");
1333 while (true)
1335 int oi = -1;
1336 int c = getopt_long (argc, argv, "aB:iF:hHklmPTt:vx:", long_options,
1337 &oi);
1338 if (c == -1)
1339 break;
1341 switch (c)
1343 case 'a':
1344 show_all_fs = true;
1345 break;
1346 case 'B':
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);
1353 break;
1354 case 'i':
1355 if (header_mode == OUTPUT_MODE)
1357 error (0, 0, msg_mut_excl, "-i", "--output");
1358 usage (EXIT_FAILURE);
1360 header_mode = INODES_MODE;
1361 break;
1362 case 'h':
1363 human_output_opts = human_autoscale | human_SI | human_base_1024;
1364 output_block_size = 1;
1365 break;
1366 case 'H':
1367 human_output_opts = human_autoscale | human_SI;
1368 output_block_size = 1;
1369 break;
1370 case 'k':
1371 human_output_opts = 0;
1372 output_block_size = 1024;
1373 break;
1374 case 'l':
1375 show_local_fs = true;
1376 break;
1377 case 'm': /* obsolescent, exists for BSD compatibility */
1378 human_output_opts = 0;
1379 output_block_size = 1024 * 1024;
1380 break;
1381 case 'T':
1382 if (header_mode == OUTPUT_MODE)
1384 error (0, 0, msg_mut_excl, "-T", "--output");
1385 usage (EXIT_FAILURE);
1387 print_type = true;
1388 break;
1389 case 'P':
1390 if (header_mode == OUTPUT_MODE)
1392 error (0, 0, msg_mut_excl, "-P", "--output");
1393 usage (EXIT_FAILURE);
1395 posix_format = true;
1396 break;
1397 case SYNC_OPTION:
1398 require_sync = true;
1399 break;
1400 case NO_SYNC_OPTION:
1401 require_sync = false;
1402 break;
1404 case 'F':
1405 /* Accept -F as a synonym for -t for compatibility with Solaris. */
1406 case 't':
1407 add_fs_type (optarg);
1408 break;
1410 case 'v': /* For SysV compatibility. */
1411 /* ignore */
1412 break;
1413 case 'x':
1414 add_excluded_fs_type (optarg);
1415 break;
1417 case OUTPUT_OPTION:
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);
1428 if (print_type)
1430 error (0, 0, msg_mut_excl, "-T", "--output");
1431 usage (EXIT_FAILURE);
1433 header_mode = OUTPUT_MODE;
1434 if (optarg)
1435 decode_output_arg (optarg);
1436 break;
1438 case TOTAL_OPTION:
1439 print_grand_total = true;
1440 break;
1442 case_GETOPT_HELP_CHAR;
1443 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1445 default:
1446 usage (EXIT_FAILURE);
1450 if (human_output_opts == -1)
1452 if (posix_format)
1454 human_output_opts = 0;
1455 output_block_size = (getenv ("POSIXLY_CORRECT") ? 512 : 1024);
1457 else
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. */
1471 bool match = false;
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))
1480 error (0, 0,
1481 _("file system type %s both selected and excluded"),
1482 quote (fs_incl->fs_name));
1483 match = true;
1484 break;
1488 if (match)
1489 exit (EXIT_FAILURE);
1492 if (optind < argc)
1494 int i;
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;
1510 argv[i] = NULL;
1512 if (0 <= fd)
1513 close (fd);
1517 mount_list =
1518 read_file_system_list ((fs_select_list != NULL
1519 || fs_exclude_list != NULL
1520 || print_type
1521 || field_data[FSTYPE_FIELD].used
1522 || show_local_fs));
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. */
1530 int status = 0;
1531 if ( ! (optind < argc)
1532 || (show_all_fs
1533 || show_local_fs
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"));
1544 if (require_sync)
1545 sync ();
1547 get_field_list ();
1548 get_header ();
1550 if (optind < argc)
1552 int i;
1554 /* Display explicitly requested empty file systems. */
1555 show_listed_fs = true;
1557 for (i = optind; i < argc; ++i)
1558 if (argv[i])
1559 get_entry (argv[i], &stats[i - optind]);
1561 else
1562 get_all_entries ();
1564 if (file_systems_processed)
1566 if (print_grand_total)
1567 get_dev ("total",
1568 (field_data[SOURCE_FIELD].used ? "-" : "total"),
1569 NULL, NULL, NULL, false, false, &grand_fsu, false);
1571 print_table ();
1573 else
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));
1583 exit (exit_status);