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