df: add --output=file to directly output specified arguments
[coreutils.git] / src / df.c
blob07a468bc82fa3dfdee3bb2500232f94fbd4fa442
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,
246 MEGABYTES_OPTION /* FIXME: remove long opt in Aug 2013 */
249 static struct option const long_options[] =
251 {"all", no_argument, NULL, 'a'},
252 {"block-size", required_argument, NULL, 'B'},
253 {"inodes", no_argument, NULL, 'i'},
254 {"human-readable", no_argument, NULL, 'h'},
255 {"si", no_argument, NULL, 'H'},
256 {"local", no_argument, NULL, 'l'},
257 {"megabytes", no_argument, NULL, MEGABYTES_OPTION}, /* obsolescent, */
258 {"output", optional_argument, NULL, OUTPUT_OPTION},
259 {"portability", no_argument, NULL, 'P'},
260 {"print-type", no_argument, NULL, 'T'},
261 {"sync", no_argument, NULL, SYNC_OPTION},
262 {"no-sync", no_argument, NULL, NO_SYNC_OPTION},
263 {"total", no_argument, NULL, TOTAL_OPTION},
264 {"type", required_argument, NULL, 't'},
265 {"exclude-type", required_argument, NULL, 'x'},
266 {GETOPT_HELP_OPTION_DECL},
267 {GETOPT_VERSION_OPTION_DECL},
268 {NULL, 0, NULL, 0}
271 /* Replace problematic chars with '?'.
272 Since only control characters are currently considered,
273 this should work in all encodings. */
275 static char*
276 hide_problematic_chars (char *cell)
278 char *p = cell;
279 while (*p)
281 if (iscntrl (to_uchar (*p)))
282 *p = '?';
283 p++;
285 return cell;
288 /* Dynamically allocate a row of pointers in TABLE, which
289 can then be accessed with standard 2D array notation. */
291 static void
292 alloc_table_row (void)
294 nrows++;
295 table = xnrealloc (table, nrows, sizeof (char *));
296 table[nrows - 1] = xnmalloc (ncolumns, sizeof (char *));
299 /* Output each cell in the table, accounting for the
300 alignment and max width of each column. */
302 static void
303 print_table (void)
305 size_t row;
307 for (row = 0; row < nrows; row++)
309 size_t col;
310 for (col = 0; col < ncolumns; col++)
312 char *cell = table[row][col];
314 /* Note the SOURCE_FIELD used to be displayed on it's own line
315 if (!posix_format && mbswidth (cell) > 20), but that
316 functionality was probably more problematic than helpful,
317 hence changed in commit v8.10-40-g99679ff. */
318 if (col != 0)
319 putchar (' ');
321 int flags = 0;
322 if (col == ncolumns - 1) /* The last one. */
323 flags = MBA_NO_RIGHT_PAD;
325 size_t width = columns[col]->width;
326 cell = ambsalign (cell, &width, columns[col]->align, flags);
327 /* When ambsalign fails, output unaligned data. */
328 fputs (cell ? cell : table[row][col], stdout);
329 free (cell);
331 IF_LINT (free (table[row][col]));
333 putchar ('\n');
334 IF_LINT (free (table[row]));
337 IF_LINT (free (table));
340 /* Dynamically allocate a struct field_t in COLUMNS, which
341 can then be accessed with standard array notation. */
343 static void
344 alloc_field (int f, const char *c)
346 ncolumns++;
347 columns = xnrealloc (columns, ncolumns, sizeof (struct field_data_t *));
348 columns[ncolumns - 1] = &field_data[f];
349 if (c != NULL)
350 columns[ncolumns - 1]->caption = c;
352 if (field_data[f].used)
353 assert (!"field used");
355 /* Mark field as used. */
356 field_data[f].used = true;
360 /* Given a string, ARG, containing a comma-separated list of arguments
361 to the --output option, add the appropriate fields to columns. */
362 static void
363 decode_output_arg (char const *arg)
365 char *arg_writable = xstrdup (arg);
366 char *s = arg_writable;
369 /* find next comma */
370 char *comma = strchr (s, ',');
372 /* If we found a comma, put a NUL in its place and advance. */
373 if (comma)
374 *comma++ = 0;
376 /* process S. */
377 display_field_t field = -1;
378 for (unsigned int i = 0; i < ARRAY_CARDINALITY (field_data); i++)
380 if (STREQ (field_data[i].arg, s))
382 field = i;
383 break;
386 if (field == -1)
388 error (0, 0, _("option --output: field '%s' unknown"), s);
389 usage (EXIT_FAILURE);
392 if (field_data[field].used)
394 /* Prevent the fields from being used more than once. */
395 error (0, 0, _("option --output: field '%s' used more than once"),
396 field_data[field].arg);
397 usage (EXIT_FAILURE);
400 switch (field)
402 case SOURCE_FIELD:
403 case FSTYPE_FIELD:
404 case USED_FIELD:
405 case PCENT_FIELD:
406 case ITOTAL_FIELD:
407 case IUSED_FIELD:
408 case IAVAIL_FIELD:
409 case IPCENT_FIELD:
410 case TARGET_FIELD:
411 case FILE_FIELD:
412 alloc_field (field, NULL);
413 break;
415 case SIZE_FIELD:
416 alloc_field (field, N_("Size"));
417 break;
419 case AVAIL_FIELD:
420 alloc_field (field, N_("Avail"));
421 break;
423 default:
424 assert (!"invalid field");
426 s = comma;
428 while (s);
430 free (arg_writable);
433 /* Get the appropriate columns for the mode. */
434 static void
435 get_field_list (void)
437 switch (header_mode)
439 case DEFAULT_MODE:
440 alloc_field (SOURCE_FIELD, NULL);
441 if (print_type)
442 alloc_field (FSTYPE_FIELD, NULL);
443 alloc_field (SIZE_FIELD, NULL);
444 alloc_field (USED_FIELD, NULL);
445 alloc_field (AVAIL_FIELD, NULL);
446 alloc_field (PCENT_FIELD, NULL);
447 alloc_field (TARGET_FIELD, NULL);
448 break;
450 case HUMAN_MODE:
451 alloc_field (SOURCE_FIELD, NULL);
452 if (print_type)
453 alloc_field (FSTYPE_FIELD, NULL);
455 alloc_field (SIZE_FIELD, N_("Size"));
456 alloc_field (USED_FIELD, NULL);
457 alloc_field (AVAIL_FIELD, N_("Avail"));
458 alloc_field (PCENT_FIELD, NULL);
459 alloc_field (TARGET_FIELD, NULL);
460 break;
462 case INODES_MODE:
463 alloc_field (SOURCE_FIELD, NULL);
464 if (print_type)
465 alloc_field (FSTYPE_FIELD, NULL);
466 alloc_field (ITOTAL_FIELD, NULL);
467 alloc_field (IUSED_FIELD, NULL);
468 alloc_field (IAVAIL_FIELD, NULL);
469 alloc_field (IPCENT_FIELD, NULL);
470 alloc_field (TARGET_FIELD, NULL);
471 break;
473 case POSIX_MODE:
474 alloc_field (SOURCE_FIELD, NULL);
475 if (print_type)
476 alloc_field (FSTYPE_FIELD, NULL);
477 alloc_field (SIZE_FIELD, NULL);
478 alloc_field (USED_FIELD, NULL);
479 alloc_field (AVAIL_FIELD, NULL);
480 alloc_field (PCENT_FIELD, N_("Capacity"));
481 alloc_field (TARGET_FIELD, NULL);
482 break;
484 case OUTPUT_MODE:
485 if (!ncolumns)
487 /* Add all fields if --output was given without a field list. */
488 decode_output_arg (all_args_string);
490 break;
492 default:
493 assert (!"invalid header_mode");
497 /* Obtain the appropriate header entries. */
499 static void
500 get_header (void)
502 size_t col;
504 alloc_table_row ();
506 for (col = 0; col < ncolumns; col++)
508 char *cell = NULL;
509 char const *header = _(columns[col]->caption);
511 if (columns[col]->field == SIZE_FIELD
512 && (header_mode == DEFAULT_MODE
513 || (header_mode == OUTPUT_MODE
514 && !(human_output_opts & human_autoscale))))
516 char buf[LONGEST_HUMAN_READABLE + 1];
518 int opts = (human_suppress_point_zero
519 | human_autoscale | human_SI
520 | (human_output_opts
521 & (human_group_digits | human_base_1024 | human_B)));
523 /* Prefer the base that makes the human-readable value more exact,
524 if there is a difference. */
526 uintmax_t q1000 = output_block_size;
527 uintmax_t q1024 = output_block_size;
528 bool divisible_by_1000;
529 bool divisible_by_1024;
533 divisible_by_1000 = q1000 % 1000 == 0; q1000 /= 1000;
534 divisible_by_1024 = q1024 % 1024 == 0; q1024 /= 1024;
536 while (divisible_by_1000 & divisible_by_1024);
538 if (divisible_by_1000 < divisible_by_1024)
539 opts |= human_base_1024;
540 if (divisible_by_1024 < divisible_by_1000)
541 opts &= ~human_base_1024;
542 if (! (opts & human_base_1024))
543 opts |= human_B;
545 char *num = human_readable (output_block_size, buf, opts, 1, 1);
547 /* Reset the header back to the default in OUTPUT_MODE. */
548 header = _("blocks");
550 /* TRANSLATORS: this is the "1K-blocks" header in "df" output. */
551 if (asprintf (&cell, _("%s-%s"), num, header) == -1)
552 cell = NULL;
554 else if (header_mode == POSIX_MODE && columns[col]->field == SIZE_FIELD)
556 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
557 char *num = umaxtostr (output_block_size, buf);
559 /* TRANSLATORS: this is the "1024-blocks" header in "df -P". */
560 if (asprintf (&cell, _("%s-%s"), num, header) == -1)
561 cell = NULL;
563 else
564 cell = strdup (header);
566 if (!cell)
567 xalloc_die ();
569 hide_problematic_chars (cell);
571 table[nrows - 1][col] = cell;
573 columns[col]->width = MAX (columns[col]->width, mbswidth (cell, 0));
577 /* Is FSTYPE a type of file system that should be listed? */
579 static bool _GL_ATTRIBUTE_PURE
580 selected_fstype (const char *fstype)
582 const struct fs_type_list *fsp;
584 if (fs_select_list == NULL || fstype == NULL)
585 return true;
586 for (fsp = fs_select_list; fsp; fsp = fsp->fs_next)
587 if (STREQ (fstype, fsp->fs_name))
588 return true;
589 return false;
592 /* Is FSTYPE a type of file system that should be omitted? */
594 static bool _GL_ATTRIBUTE_PURE
595 excluded_fstype (const char *fstype)
597 const struct fs_type_list *fsp;
599 if (fs_exclude_list == NULL || fstype == NULL)
600 return false;
601 for (fsp = fs_exclude_list; fsp; fsp = fsp->fs_next)
602 if (STREQ (fstype, fsp->fs_name))
603 return true;
604 return false;
607 /* Filter mount list by skipping duplicate entries.
608 In the case of duplicities - based on to the device number - the mount entry
609 with a '/' in its me_devname (i.e. not pseudo name like tmpfs) wins.
610 If both have a real devname (e.g. bind mounts), then that with the shorter
611 me_mountdir wins. */
613 static void
614 filter_mount_list (void)
616 struct mount_entry *me;
618 /* Store of already-processed device numbers. */
619 struct devlist *devlist_head = NULL;
621 /* Sort all 'wanted' entries into the list devlist_head. */
622 for (me = mount_list; me;)
624 struct stat buf;
625 struct devlist *devlist;
626 struct mount_entry *discard_me = NULL;
628 if (-1 == stat (me->me_mountdir, &buf))
630 /* Stat failed - add ME to be able to complain about it later. */
631 buf.st_dev = me->me_dev;
633 else
635 /* If the device name is a real path name ... */
636 if (strchr (me->me_devname, '/'))
638 /* ... try to find its device number in the devlist. */
639 for (devlist = devlist_head; devlist; devlist = devlist->next)
640 if (devlist->dev_num == buf.st_dev)
641 break;
643 if (devlist)
645 discard_me = me;
647 /* Let the shorter mountdir win. */
648 if (! strchr (devlist->me->me_devname, '/')
649 || (strlen (devlist->me->me_mountdir)
650 > strlen (me->me_mountdir)))
652 discard_me = devlist->me;
653 devlist->me = me;
659 if (discard_me)
661 me = me->me_next;
662 free_mount_entry (discard_me);
664 else
666 /* Add the device number to the global list devlist. */
667 devlist = xmalloc (sizeof *devlist);
668 devlist->me = me;
669 devlist->dev_num = buf.st_dev;
670 devlist->next = devlist_head;
671 devlist_head = devlist;
673 me = me->me_next;
677 /* Finally rebuild the mount_list from the devlist. */
678 mount_list = NULL;
679 while (devlist_head)
681 /* Add the mount entry. */
682 me = devlist_head->me;
683 me->me_next = mount_list;
684 mount_list = me;
685 /* Free devlist entry and advance. */
686 struct devlist *devlist = devlist_head->next;
687 free (devlist_head);
688 devlist_head = devlist;
692 /* Return true if N is a known integer value. On many file systems,
693 UINTMAX_MAX represents an unknown value; on AIX, UINTMAX_MAX - 1
694 represents unknown. Use a rule that works on AIX file systems, and
695 that almost-always works on other types. */
696 static bool
697 known_value (uintmax_t n)
699 return n < UINTMAX_MAX - 1;
702 /* Like human_readable (N, BUF, human_output_opts, INPUT_UNITS, OUTPUT_UNITS),
703 except:
705 - If NEGATIVE, then N represents a negative number,
706 expressed in two's complement.
707 - Otherwise, return "-" if N is unknown. */
709 static char const *
710 df_readable (bool negative, uintmax_t n, char *buf,
711 uintmax_t input_units, uintmax_t output_units)
713 if (! known_value (n) && !negative)
714 return "-";
715 else
717 char *p = human_readable (negative ? -n : n, buf + negative,
718 human_output_opts, input_units, output_units);
719 if (negative)
720 *--p = '-';
721 return p;
725 /* Logical equivalence */
726 #define LOG_EQ(a, b) (!(a) == !(b))
728 /* Add integral value while using uintmax_t for value part and separate
729 negation flag. It adds value of SRC and SRC_NEG to DEST and DEST_NEG.
730 The result will be in DEST and DEST_NEG. See df_readable to understand
731 how the negation flag is used. */
732 static void
733 add_uint_with_neg_flag (uintmax_t *dest, bool *dest_neg,
734 uintmax_t src, bool src_neg)
736 if (LOG_EQ (*dest_neg, src_neg))
738 *dest += src;
739 return;
742 if (*dest_neg)
743 *dest = -*dest;
745 if (src_neg)
746 src = -src;
748 if (src < *dest)
749 *dest -= src;
750 else
752 *dest = src - *dest;
753 *dest_neg = src_neg;
756 if (*dest_neg)
757 *dest = -*dest;
760 /* Return true if S ends in a string that may be a 36-byte UUID,
761 i.e., of the form HHHHHHHH-HHHH-HHHH-HHHH-HHHHHHHHHHHH, where
762 each H is an upper or lower case hexadecimal digit. */
763 static bool _GL_ATTRIBUTE_PURE
764 has_uuid_suffix (char const *s)
766 size_t len = strlen (s);
767 return (36 < len
768 && strspn (s + len - 36, "-0123456789abcdefABCDEF") == 36);
771 /* Obtain the block values BV and inode values IV
772 from the file system usage FSU. */
773 static void
774 get_field_values (struct field_values_t *bv,
775 struct field_values_t *iv,
776 const struct fs_usage *fsu)
778 /* Inode values. */
779 iv->input_units = iv->output_units = 1;
780 iv->total = fsu->fsu_files;
781 iv->available = iv->available_to_root = fsu->fsu_ffree;
782 iv->negate_available = false;
784 iv->used = UINTMAX_MAX;
785 iv->negate_used = false;
786 if (known_value (iv->total) && known_value (iv->available_to_root))
788 iv->used = iv->total - iv->available_to_root;
789 iv->negate_used = (iv->total < iv->available_to_root);
792 /* Block values. */
793 bv->input_units = fsu->fsu_blocksize;
794 bv->output_units = output_block_size;
795 bv->total = fsu->fsu_blocks;
796 bv->available = fsu->fsu_bavail;
797 bv->available_to_root = fsu->fsu_bfree;
798 bv->negate_available = (fsu->fsu_bavail_top_bit_set
799 && known_value (fsu->fsu_bavail));
801 bv->used = UINTMAX_MAX;
802 bv->negate_used = false;
803 if (known_value (bv->total) && known_value (bv->available_to_root))
805 bv->used = bv->total - bv->available_to_root;
806 bv->negate_used = (bv->total < bv->available_to_root);
810 /* Add block and inode values to grand total. */
811 static void
812 add_to_grand_total (struct field_values_t *bv, struct field_values_t *iv)
814 if (known_value (iv->total))
815 grand_fsu.fsu_files += iv->total;
816 if (known_value (iv->available))
817 grand_fsu.fsu_ffree += iv->available;
819 if (known_value (bv->total))
820 grand_fsu.fsu_blocks += bv->input_units * bv->total;
821 if (known_value (bv->available_to_root))
822 grand_fsu.fsu_bfree += bv->input_units * bv->available_to_root;
823 if (known_value (bv->available))
824 add_uint_with_neg_flag (&grand_fsu.fsu_bavail,
825 &grand_fsu.fsu_bavail_top_bit_set,
826 bv->input_units * bv->available,
827 bv->negate_available);
830 /* Obtain a space listing for the disk device with absolute file name DISK.
831 If MOUNT_POINT is non-NULL, it is the name of the root of the
832 file system on DISK.
833 If STAT_FILE is non-null, it is the name of a file within the file
834 system that the user originally asked for; this provides better
835 diagnostics, and sometimes it provides better results on networked
836 file systems that give different free-space results depending on
837 where in the file system you probe.
838 If FSTYPE is non-NULL, it is the type of the file system on DISK.
839 If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may
840 not be able to produce statistics in this case.
841 ME_DUMMY and ME_REMOTE are the mount entry flags.
842 Caller must set PROCESS_ALL to true when iterating over all entries, as
843 when df is invoked with no non-option argument. See below for details. */
845 static void
846 get_dev (char const *disk, char const *mount_point, char const* file,
847 char const *stat_file, char const *fstype,
848 bool me_dummy, bool me_remote,
849 const struct fs_usage *force_fsu,
850 bool process_all)
852 if (me_remote && show_local_fs)
853 return;
855 if (me_dummy && !show_all_fs && !show_listed_fs)
856 return;
858 if (!selected_fstype (fstype) || excluded_fstype (fstype))
859 return;
861 /* If MOUNT_POINT is NULL, then the file system is not mounted, and this
862 program reports on the file system that the special file is on.
863 It would be better to report on the unmounted file system,
864 but statfs doesn't do that on most systems. */
865 if (!stat_file)
866 stat_file = mount_point ? mount_point : disk;
868 struct fs_usage fsu;
869 if (force_fsu)
870 fsu = *force_fsu;
871 else if (get_fs_usage (stat_file, disk, &fsu))
873 error (0, errno, "%s", quote (stat_file));
874 exit_status = EXIT_FAILURE;
875 return;
878 if (fsu.fsu_blocks == 0 && !show_all_fs && !show_listed_fs)
879 return;
881 if (! force_fsu)
882 file_systems_processed = true;
884 alloc_table_row ();
886 if (! disk)
887 disk = "-"; /* unknown */
889 if (! file)
890 file = "-"; /* unspecified */
892 char *dev_name = xstrdup (disk);
893 char *resolved_dev;
895 /* On some systems, dev_name is a long-named symlink like
896 /dev/disk/by-uuid/828fc648-9f30-43d8-a0b1-f7196a2edb66 pointing to a
897 much shorter and more useful name like /dev/sda1. It may also look
898 like /dev/mapper/luks-828fc648-9f30-43d8-a0b1-f7196a2edb66 and point to
899 /dev/dm-0. When process_all is true and dev_name is a symlink whose
900 name ends with a UUID use the resolved name instead. */
901 if (process_all
902 && has_uuid_suffix (dev_name)
903 && (resolved_dev = canonicalize_filename_mode (dev_name, CAN_EXISTING)))
905 free (dev_name);
906 dev_name = resolved_dev;
909 if (! fstype)
910 fstype = "-"; /* unknown */
912 struct field_values_t block_values;
913 struct field_values_t inode_values;
914 get_field_values (&block_values, &inode_values, &fsu);
916 /* Add to grand total unless processing grand total line. */
917 if (print_grand_total && ! force_fsu)
918 add_to_grand_total (&block_values, &inode_values);
920 size_t col;
921 for (col = 0; col < ncolumns; col++)
923 char buf[LONGEST_HUMAN_READABLE + 2];
924 char *cell;
926 struct field_values_t *v;
927 switch (columns[col]->field_type)
929 case BLOCK_FLD:
930 v = &block_values;
931 break;
932 case INODE_FLD:
933 v = &inode_values;
934 break;
935 case OTHER_FLD:
936 v = NULL;
937 break;
938 default:
939 assert (!"bad field_type");
942 switch (columns[col]->field)
944 case SOURCE_FIELD:
945 cell = xstrdup (dev_name);
946 break;
948 case FSTYPE_FIELD:
949 cell = xstrdup (fstype);
950 break;
952 case SIZE_FIELD:
953 case ITOTAL_FIELD:
954 cell = xstrdup (df_readable (false, v->total, buf,
955 v->input_units, v->output_units));
956 break;
958 case USED_FIELD:
959 case IUSED_FIELD:
960 cell = xstrdup (df_readable (v->negate_used, v->used, buf,
961 v->input_units, v->output_units));
962 break;
964 case AVAIL_FIELD:
965 case IAVAIL_FIELD:
966 cell = xstrdup (df_readable (v->negate_available, v->available, buf,
967 v->input_units, v->output_units));
968 break;
970 case PCENT_FIELD:
971 case IPCENT_FIELD:
973 double pct = -1;
974 if (! known_value (v->used) || ! known_value (v->available))
976 else if (!v->negate_used
977 && v->used <= TYPE_MAXIMUM (uintmax_t) / 100
978 && v->used + v->available != 0
979 && (v->used + v->available < v->used)
980 == v->negate_available)
982 uintmax_t u100 = v->used * 100;
983 uintmax_t nonroot_total = v->used + v->available;
984 pct = u100 / nonroot_total + (u100 % nonroot_total != 0);
986 else
988 /* The calculation cannot be done easily with integer
989 arithmetic. Fall back on floating point. This can suffer
990 from minor rounding errors, but doing it exactly requires
991 multiple precision arithmetic, and it's not worth the
992 aggravation. */
993 double u = v->negate_used ? - (double) - v->used : v->used;
994 double a = v->negate_available
995 ? - (double) - v->available : v->available;
996 double nonroot_total = u + a;
997 if (nonroot_total)
999 long int lipct = pct = u * 100 / nonroot_total;
1000 double ipct = lipct;
1002 /* Like 'pct = ceil (dpct);', but avoid ceil so that
1003 the math library needn't be linked. */
1004 if (ipct - 1 < pct && pct <= ipct + 1)
1005 pct = ipct + (ipct < pct);
1009 if (0 <= pct)
1011 if (asprintf (&cell, "%.0f%%", pct) == -1)
1012 cell = NULL;
1014 else
1015 cell = strdup ("-");
1017 if (!cell)
1018 xalloc_die ();
1020 break;
1023 case FILE_FIELD:
1024 cell = xstrdup (file);
1025 break;
1027 case TARGET_FIELD:
1028 #ifdef HIDE_AUTOMOUNT_PREFIX
1029 /* Don't print the first directory name in MOUNT_POINT if it's an
1030 artifact of an automounter. This is a bit too aggressive to be
1031 the default. */
1032 if (STRNCMP_LIT (mount_point, "/auto/") == 0)
1033 mount_point += 5;
1034 else if (STRNCMP_LIT (mount_point, "/tmp_mnt/") == 0)
1035 mount_point += 8;
1036 #endif
1037 cell = xstrdup (mount_point);
1038 break;
1040 default:
1041 assert (!"unhandled field");
1044 if (!cell)
1045 assert (!"empty cell");
1047 hide_problematic_chars (cell);
1048 columns[col]->width = MAX (columns[col]->width, mbswidth (cell, 0));
1049 table[nrows - 1][col] = cell;
1051 free (dev_name);
1054 /* If DISK corresponds to a mount point, show its usage
1055 and return true. Otherwise, return false. */
1056 static bool
1057 get_disk (char const *disk)
1059 struct mount_entry const *me;
1060 struct mount_entry const *best_match = NULL;
1062 for (me = mount_list; me; me = me->me_next)
1064 if (STREQ (disk, me->me_devname))
1065 best_match = me;
1068 if (best_match)
1070 get_dev (best_match->me_devname, best_match->me_mountdir, disk, NULL,
1071 best_match->me_type, best_match->me_dummy,
1072 best_match->me_remote, NULL, false);
1073 return true;
1076 return false;
1079 /* Figure out which device file or directory POINT is mounted on
1080 and show its disk usage.
1081 STATP must be the result of 'stat (POINT, STATP)'. */
1082 static void
1083 get_point (const char *point, const struct stat *statp)
1085 struct stat disk_stats;
1086 struct mount_entry *me;
1087 struct mount_entry const *best_match = NULL;
1089 /* Calculate the real absolute file name for POINT, and use that to find
1090 the mount point. This avoids statting unavailable mount points,
1091 which can hang df. */
1092 char *resolved = canonicalize_file_name (point);
1093 if (resolved && resolved[0] == '/')
1095 size_t resolved_len = strlen (resolved);
1096 size_t best_match_len = 0;
1098 for (me = mount_list; me; me = me->me_next)
1100 if (!STREQ (me->me_type, "lofs")
1101 && (!best_match || best_match->me_dummy || !me->me_dummy))
1103 size_t len = strlen (me->me_mountdir);
1104 if (best_match_len <= len && len <= resolved_len
1105 && (len == 1 /* root file system */
1106 || ((len == resolved_len || resolved[len] == '/')
1107 && STREQ_LEN (me->me_mountdir, resolved, len))))
1109 best_match = me;
1110 best_match_len = len;
1115 free (resolved);
1116 if (best_match
1117 && (stat (best_match->me_mountdir, &disk_stats) != 0
1118 || disk_stats.st_dev != statp->st_dev))
1119 best_match = NULL;
1121 if (! best_match)
1122 for (me = mount_list; me; me = me->me_next)
1124 if (me->me_dev == (dev_t) -1)
1126 if (stat (me->me_mountdir, &disk_stats) == 0)
1127 me->me_dev = disk_stats.st_dev;
1128 else
1130 /* Report only I/O errors. Other errors might be
1131 caused by shadowed mount points, which means POINT
1132 can't possibly be on this file system. */
1133 if (errno == EIO)
1135 error (0, errno, "%s", quote (me->me_mountdir));
1136 exit_status = EXIT_FAILURE;
1139 /* So we won't try and fail repeatedly. */
1140 me->me_dev = (dev_t) -2;
1144 if (statp->st_dev == me->me_dev
1145 && !STREQ (me->me_type, "lofs")
1146 && (!best_match || best_match->me_dummy || !me->me_dummy))
1148 /* Skip bogus mtab entries. */
1149 if (stat (me->me_mountdir, &disk_stats) != 0
1150 || disk_stats.st_dev != me->me_dev)
1151 me->me_dev = (dev_t) -2;
1152 else
1153 best_match = me;
1157 if (best_match)
1158 get_dev (best_match->me_devname, best_match->me_mountdir, point, point,
1159 best_match->me_type, best_match->me_dummy, best_match->me_remote,
1160 NULL, false);
1161 else
1163 /* We couldn't find the mount entry corresponding to POINT. Go ahead and
1164 print as much info as we can; methods that require the device to be
1165 present will fail at a later point. */
1167 /* Find the actual mount point. */
1168 char *mp = find_mount_point (point, statp);
1169 if (mp)
1171 get_dev (NULL, mp, point, NULL, NULL, false, false, NULL, false);
1172 free (mp);
1177 /* Determine what kind of node NAME is and show the disk usage
1178 for it. STATP is the results of 'stat' on NAME. */
1180 static void
1181 get_entry (char const *name, struct stat const *statp)
1183 if ((S_ISBLK (statp->st_mode) || S_ISCHR (statp->st_mode))
1184 && get_disk (name))
1185 return;
1187 get_point (name, statp);
1190 /* Show all mounted file systems, except perhaps those that are of
1191 an unselected type or are empty. */
1193 static void
1194 get_all_entries (void)
1196 struct mount_entry *me;
1198 if (!show_all_fs)
1199 filter_mount_list ();
1201 for (me = mount_list; me; me = me->me_next)
1202 get_dev (me->me_devname, me->me_mountdir, NULL, NULL, me->me_type,
1203 me->me_dummy, me->me_remote, NULL, true);
1206 /* Add FSTYPE to the list of file system types to display. */
1208 static void
1209 add_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_select_list;
1216 fs_select_list = fsp;
1219 /* Add FSTYPE to the list of file system types to be omitted. */
1221 static void
1222 add_excluded_fs_type (const char *fstype)
1224 struct fs_type_list *fsp;
1226 fsp = xmalloc (sizeof *fsp);
1227 fsp->fs_name = (char *) fstype;
1228 fsp->fs_next = fs_exclude_list;
1229 fs_exclude_list = fsp;
1232 void
1233 usage (int status)
1235 if (status != EXIT_SUCCESS)
1236 emit_try_help ();
1237 else
1239 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name);
1240 fputs (_("\
1241 Show information about the file system on which each FILE resides,\n\
1242 or all file systems by default.\n\
1243 "), stdout);
1245 emit_mandatory_arg_note ();
1247 fputs (_("\
1248 -a, --all include dummy file systems\n\
1249 -B, --block-size=SIZE scale sizes by SIZE before printing them; e.g.,\n\
1250 '-BM' prints sizes in units of 1,048,576 bytes;\n\
1251 see SIZE format below\n\
1252 --total produce a grand total\n\
1253 -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\
1255 -H, --si likewise, but use powers of 1000 not 1024\n\
1256 "), stdout);
1257 fputs (_("\
1258 -i, --inodes list inode information instead of block usage\n\
1259 -k like --block-size=1K\n\
1260 -l, --local limit listing to local file systems\n\
1261 --no-sync do not invoke sync before getting usage info (default)\
1263 "), stdout);
1264 fputs (_("\
1265 --output[=FIELD_LIST] use the output format defined by FIELD_LIST,\n\
1266 or print all fields if FIELD_LIST is omitted.\n\
1267 -P, --portability use the POSIX output format\n\
1268 --sync invoke sync before getting usage info\n\
1269 -t, --type=TYPE limit listing to file systems of type TYPE\n\
1270 -T, --print-type print file system type\n\
1271 -x, --exclude-type=TYPE limit listing to file systems not of type TYPE\n\
1272 -v (ignored)\n\
1273 "), stdout);
1274 fputs (HELP_OPTION_DESCRIPTION, stdout);
1275 fputs (VERSION_OPTION_DESCRIPTION, stdout);
1276 emit_blocksize_note ("DF");
1277 emit_size_note ();
1278 fputs (_("\n\
1279 FIELD_LIST is a comma-separated list of columns to be included. Valid\n\
1280 field names are: 'source', 'fstype', 'itotal', 'iused', 'iavail', 'ipcent',\n\
1281 'size', 'used', 'avail', 'pcent', 'file' and 'target' (see info page).\n\
1282 "), stdout);
1283 emit_ancillary_info ();
1285 exit (status);
1289 main (int argc, char **argv)
1291 struct stat *stats IF_LINT ( = 0);
1293 initialize_main (&argc, &argv);
1294 set_program_name (argv[0]);
1295 setlocale (LC_ALL, "");
1296 bindtextdomain (PACKAGE, LOCALEDIR);
1297 textdomain (PACKAGE);
1299 atexit (close_stdout);
1301 fs_select_list = NULL;
1302 fs_exclude_list = NULL;
1303 show_all_fs = false;
1304 show_listed_fs = false;
1305 human_output_opts = -1;
1306 print_type = false;
1307 file_systems_processed = false;
1308 exit_status = EXIT_SUCCESS;
1309 print_grand_total = false;
1310 grand_fsu.fsu_blocksize = 1;
1312 /* If true, use the POSIX output format. */
1313 bool posix_format = false;
1315 const char *msg_mut_excl = _("options %s and %s are mutually exclusive");
1317 while (true)
1319 int oi = -1;
1320 int c = getopt_long (argc, argv, "aB:iF:hHklmPTt:vx:", long_options,
1321 &oi);
1322 if (c == -1)
1323 break;
1325 switch (c)
1327 case 'a':
1328 show_all_fs = true;
1329 break;
1330 case 'B':
1332 enum strtol_error e = human_options (optarg, &human_output_opts,
1333 &output_block_size);
1334 if (e != LONGINT_OK)
1335 xstrtol_fatal (e, oi, c, long_options, optarg);
1337 break;
1338 case 'i':
1339 if (header_mode == OUTPUT_MODE)
1341 error (0, 0, msg_mut_excl, "-i", "--output");
1342 usage (EXIT_FAILURE);
1344 header_mode = INODES_MODE;
1345 break;
1346 case 'h':
1347 human_output_opts = human_autoscale | human_SI | human_base_1024;
1348 output_block_size = 1;
1349 break;
1350 case 'H':
1351 human_output_opts = human_autoscale | human_SI;
1352 output_block_size = 1;
1353 break;
1354 case 'k':
1355 human_output_opts = 0;
1356 output_block_size = 1024;
1357 break;
1358 case 'l':
1359 show_local_fs = true;
1360 break;
1361 case MEGABYTES_OPTION:
1362 /* Distinguish between the long and the short option.
1363 As we want to remove the long option soon,
1364 give a warning when the long form is used. */
1365 error (0, 0, "%s%s", _("warning: "),
1366 _("long option '--megabytes' is deprecated"
1367 " and will soon be removed"));
1368 case 'm': /* obsolescent, exists for BSD compatibility */
1369 human_output_opts = 0;
1370 output_block_size = 1024 * 1024;
1371 break;
1372 case 'T':
1373 if (header_mode == OUTPUT_MODE)
1375 error (0, 0, msg_mut_excl, "-T", "--output");
1376 usage (EXIT_FAILURE);
1378 print_type = true;
1379 break;
1380 case 'P':
1381 if (header_mode == OUTPUT_MODE)
1383 error (0, 0, msg_mut_excl, "-P", "--output");
1384 usage (EXIT_FAILURE);
1386 posix_format = true;
1387 break;
1388 case SYNC_OPTION:
1389 require_sync = true;
1390 break;
1391 case NO_SYNC_OPTION:
1392 require_sync = false;
1393 break;
1395 case 'F':
1396 /* Accept -F as a synonym for -t for compatibility with Solaris. */
1397 case 't':
1398 add_fs_type (optarg);
1399 break;
1401 case 'v': /* For SysV compatibility. */
1402 /* ignore */
1403 break;
1404 case 'x':
1405 add_excluded_fs_type (optarg);
1406 break;
1408 case OUTPUT_OPTION:
1409 if (header_mode == INODES_MODE)
1411 error (0, 0, msg_mut_excl, "-i", "--output");
1412 usage (EXIT_FAILURE);
1414 if (posix_format && header_mode == DEFAULT_MODE)
1416 error (0, 0, msg_mut_excl, "-P", "--output");
1417 usage (EXIT_FAILURE);
1419 if (print_type)
1421 error (0, 0, msg_mut_excl, "-T", "--output");
1422 usage (EXIT_FAILURE);
1424 header_mode = OUTPUT_MODE;
1425 if (optarg)
1426 decode_output_arg (optarg);
1427 break;
1429 case TOTAL_OPTION:
1430 print_grand_total = true;
1431 break;
1433 case_GETOPT_HELP_CHAR;
1434 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1436 default:
1437 usage (EXIT_FAILURE);
1441 if (human_output_opts == -1)
1443 if (posix_format)
1445 human_output_opts = 0;
1446 output_block_size = (getenv ("POSIXLY_CORRECT") ? 512 : 1024);
1448 else
1449 human_options (getenv ("DF_BLOCK_SIZE"),
1450 &human_output_opts, &output_block_size);
1453 if (header_mode == INODES_MODE || header_mode == OUTPUT_MODE)
1455 else if (human_output_opts & human_autoscale)
1456 header_mode = HUMAN_MODE;
1457 else if (posix_format)
1458 header_mode = POSIX_MODE;
1460 /* Fail if the same file system type was both selected and excluded. */
1462 bool match = false;
1463 struct fs_type_list *fs_incl;
1464 for (fs_incl = fs_select_list; fs_incl; fs_incl = fs_incl->fs_next)
1466 struct fs_type_list *fs_excl;
1467 for (fs_excl = fs_exclude_list; fs_excl; fs_excl = fs_excl->fs_next)
1469 if (STREQ (fs_incl->fs_name, fs_excl->fs_name))
1471 error (0, 0,
1472 _("file system type %s both selected and excluded"),
1473 quote (fs_incl->fs_name));
1474 match = true;
1475 break;
1479 if (match)
1480 exit (EXIT_FAILURE);
1483 if (optind < argc)
1485 int i;
1487 /* Open each of the given entries to make sure any corresponding
1488 partition is automounted. This must be done before reading the
1489 file system table. */
1490 stats = xnmalloc (argc - optind, sizeof *stats);
1491 for (i = optind; i < argc; ++i)
1493 /* Prefer to open with O_NOCTTY and use fstat, but fall back
1494 on using "stat", in case the file is unreadable. */
1495 int fd = open (argv[i], O_RDONLY | O_NOCTTY);
1496 if ((fd < 0 || fstat (fd, &stats[i - optind]))
1497 && stat (argv[i], &stats[i - optind]))
1499 error (0, errno, "%s", quote (argv[i]));
1500 exit_status = EXIT_FAILURE;
1501 argv[i] = NULL;
1503 if (0 <= fd)
1504 close (fd);
1508 mount_list =
1509 read_file_system_list ((fs_select_list != NULL
1510 || fs_exclude_list != NULL
1511 || print_type
1512 || field_data[FSTYPE_FIELD].used
1513 || show_local_fs));
1515 if (mount_list == NULL)
1517 /* Couldn't read the table of mounted file systems.
1518 Fail if df was invoked with no file name arguments,
1519 or when either of -a, -l, -t or -x is used with file name
1520 arguments. Otherwise, merely give a warning and proceed. */
1521 int status = 0;
1522 if ( ! (optind < argc)
1523 || (show_all_fs
1524 || show_local_fs
1525 || fs_select_list != NULL
1526 || fs_exclude_list != NULL))
1528 status = EXIT_FAILURE;
1530 const char *warning = (status == 0 ? _("Warning: ") : "");
1531 error (status, errno, "%s%s", warning,
1532 _("cannot read table of mounted file systems"));
1535 if (require_sync)
1536 sync ();
1538 get_field_list ();
1539 get_header ();
1541 if (optind < argc)
1543 int i;
1545 /* Display explicitly requested empty file systems. */
1546 show_listed_fs = true;
1548 for (i = optind; i < argc; ++i)
1549 if (argv[i])
1550 get_entry (argv[i], &stats[i - optind]);
1552 else
1553 get_all_entries ();
1555 if (file_systems_processed)
1557 if (print_grand_total)
1558 get_dev ("total",
1559 (field_data[SOURCE_FIELD].used ? "-" : "total"),
1560 NULL, NULL, NULL, false, false, &grand_fsu, false);
1562 print_table ();
1564 else
1566 /* Print the "no FS processed" diagnostic only if there was no preceding
1567 diagnostic, e.g., if all have been excluded. */
1568 if (exit_status == EXIT_SUCCESS)
1569 error (EXIT_FAILURE, 0, _("no file systems processed"));
1572 IF_LINT (free (columns));
1574 exit (exit_status);