tests: fix false failure with spaces in $PWD
[coreutils.git] / src / df.c
blob8f760db7df0a93daa7109ce3986df9bed732c080
1 /* df - summarize free disk space
2 Copyright (C) 1991-2016 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 option 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 "die.h"
30 #include "error.h"
31 #include "fsusage.h"
32 #include "human.h"
33 #include "mbsalign.h"
34 #include "mbswidth.h"
35 #include "mountlist.h"
36 #include "quote.h"
37 #include "find-mount-point.h"
38 #include "hash.h"
40 /* The official name of this program (e.g., no 'g' prefix). */
41 #define PROGRAM_NAME "df"
43 #define AUTHORS \
44 proper_name ("Torbjorn Granlund"), \
45 proper_name ("David MacKenzie"), \
46 proper_name ("Paul Eggert")
48 struct devlist
50 dev_t dev_num;
51 struct mount_entry *me;
52 struct devlist *next;
55 /* Filled with device numbers of examined file systems to avoid
56 duplicates in output. */
57 static Hash_table *devlist_table;
59 /* If true, show even file systems with zero size or
60 uninteresting types. */
61 static bool show_all_fs;
63 /* If true, show only local file systems. */
64 static bool show_local_fs;
66 /* If true, output data for each file system corresponding to a
67 command line argument -- even if it's a dummy (automounter) entry. */
68 static bool show_listed_fs;
70 /* Human-readable options for output. */
71 static int human_output_opts;
73 /* The units to use when printing sizes. */
74 static uintmax_t output_block_size;
76 /* True if a file system has been processed for output. */
77 static bool file_systems_processed;
79 /* If true, invoke the 'sync' system call before getting any usage data.
80 Using this option can make df very slow, especially with many or very
81 busy disks. Note that this may make a difference on some systems --
82 SunOS 4.1.3, for one. It is *not* necessary on GNU/Linux. */
83 static bool require_sync;
85 /* Desired exit status. */
86 static int exit_status;
88 /* A file system type to display. */
90 struct fs_type_list
92 char *fs_name;
93 struct fs_type_list *fs_next;
96 /* Linked list of file system types to display.
97 If 'fs_select_list' is NULL, list all types.
98 This table is generated dynamically from command-line options,
99 rather than hardcoding into the program what it thinks are the
100 valid file system types; let the user specify any file system type
101 they want to, and if there are any file systems of that type, they
102 will be shown.
104 Some file system types:
105 4.2 4.3 ufs nfs swap ignore io vm efs dbg */
107 static struct fs_type_list *fs_select_list;
109 /* Linked list of file system types to omit.
110 If the list is empty, don't exclude any types. */
112 static struct fs_type_list *fs_exclude_list;
114 /* Linked list of mounted file systems. */
115 static struct mount_entry *mount_list;
117 /* If true, print file system type as well. */
118 static bool print_type;
120 /* If true, print a grand total at the end. */
121 static bool print_grand_total;
123 /* Grand total data. */
124 static struct fs_usage grand_fsu;
126 /* Display modes. */
127 enum
129 DEFAULT_MODE,
130 INODES_MODE,
131 HUMAN_MODE,
132 POSIX_MODE,
133 OUTPUT_MODE
135 static int header_mode = DEFAULT_MODE;
137 /* Displayable fields. */
138 typedef enum
140 SOURCE_FIELD, /* file system */
141 FSTYPE_FIELD, /* FS type */
142 SIZE_FIELD, /* FS size */
143 USED_FIELD, /* FS size used */
144 AVAIL_FIELD, /* FS size available */
145 PCENT_FIELD, /* percent used */
146 ITOTAL_FIELD, /* inode total */
147 IUSED_FIELD, /* inodes used */
148 IAVAIL_FIELD, /* inodes available */
149 IPCENT_FIELD, /* inodes used in percent */
150 TARGET_FIELD, /* mount point */
151 FILE_FIELD, /* specified file name */
152 INVALID_FIELD /* validation marker */
153 } display_field_t;
155 /* Flag if a field contains a block, an inode or another value. */
156 typedef enum
158 BLOCK_FLD, /* Block values field */
159 INODE_FLD, /* Inode values field */
160 OTHER_FLD /* Neutral field, e.g. target */
161 } field_type_t;
163 /* Attributes of a display field. */
164 struct field_data_t
166 display_field_t field;
167 char const *arg;
168 field_type_t field_type;
169 const char *caption;/* NULL means to use the default header of this field. */
170 size_t width; /* Auto adjusted (up) widths used to align columns. */
171 mbs_align_t align; /* Alignment for this field. */
172 bool used;
175 /* Header strings, minimum width and alignment for the above fields. */
176 static struct field_data_t field_data[] = {
177 [SOURCE_FIELD] = { SOURCE_FIELD,
178 "source", OTHER_FLD, N_("Filesystem"), 14, MBS_ALIGN_LEFT, false },
180 [FSTYPE_FIELD] = { FSTYPE_FIELD,
181 "fstype", OTHER_FLD, N_("Type"), 4, MBS_ALIGN_LEFT, false },
183 [SIZE_FIELD] = { SIZE_FIELD,
184 "size", BLOCK_FLD, N_("blocks"), 5, MBS_ALIGN_RIGHT, false },
186 [USED_FIELD] = { USED_FIELD,
187 "used", BLOCK_FLD, N_("Used"), 5, MBS_ALIGN_RIGHT, false },
189 [AVAIL_FIELD] = { AVAIL_FIELD,
190 "avail", BLOCK_FLD, N_("Available"), 5, MBS_ALIGN_RIGHT, false },
192 [PCENT_FIELD] = { PCENT_FIELD,
193 "pcent", BLOCK_FLD, N_("Use%"), 4, MBS_ALIGN_RIGHT, false },
195 [ITOTAL_FIELD] = { ITOTAL_FIELD,
196 "itotal", INODE_FLD, N_("Inodes"), 5, MBS_ALIGN_RIGHT, false },
198 [IUSED_FIELD] = { IUSED_FIELD,
199 "iused", INODE_FLD, N_("IUsed"), 5, MBS_ALIGN_RIGHT, false },
201 [IAVAIL_FIELD] = { IAVAIL_FIELD,
202 "iavail", INODE_FLD, N_("IFree"), 5, MBS_ALIGN_RIGHT, false },
204 [IPCENT_FIELD] = { IPCENT_FIELD,
205 "ipcent", INODE_FLD, N_("IUse%"), 4, MBS_ALIGN_RIGHT, false },
207 [TARGET_FIELD] = { TARGET_FIELD,
208 "target", OTHER_FLD, N_("Mounted on"), 0, MBS_ALIGN_LEFT, false },
210 [FILE_FIELD] = { FILE_FIELD,
211 "file", OTHER_FLD, N_("File"), 0, MBS_ALIGN_LEFT, false }
214 static char const *all_args_string =
215 "source,fstype,itotal,iused,iavail,ipcent,size,"
216 "used,avail,pcent,file,target";
218 /* Storage for the definition of output columns. */
219 static struct field_data_t **columns;
221 /* The current number of output columns. */
222 static size_t ncolumns;
224 /* Field values. */
225 struct field_values_t
227 uintmax_t input_units;
228 uintmax_t output_units;
229 uintmax_t total;
230 uintmax_t available;
231 bool negate_available;
232 uintmax_t available_to_root;
233 uintmax_t used;
234 bool negate_used;
237 /* Storage for pointers for each string (cell of table). */
238 static char ***table;
240 /* The current number of processed rows (including header). */
241 static size_t nrows;
243 /* For long options that have no equivalent short option, use a
244 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
245 enum
247 NO_SYNC_OPTION = CHAR_MAX + 1,
248 SYNC_OPTION,
249 TOTAL_OPTION,
250 OUTPUT_OPTION
253 static struct option const long_options[] =
255 {"all", no_argument, NULL, 'a'},
256 {"block-size", required_argument, NULL, 'B'},
257 {"inodes", no_argument, NULL, 'i'},
258 {"human-readable", no_argument, NULL, 'h'},
259 {"si", no_argument, NULL, 'H'},
260 {"local", no_argument, NULL, 'l'},
261 {"output", optional_argument, NULL, OUTPUT_OPTION},
262 {"portability", no_argument, NULL, 'P'},
263 {"print-type", no_argument, NULL, 'T'},
264 {"sync", no_argument, NULL, SYNC_OPTION},
265 {"no-sync", no_argument, NULL, NO_SYNC_OPTION},
266 {"total", no_argument, NULL, TOTAL_OPTION},
267 {"type", required_argument, NULL, 't'},
268 {"exclude-type", required_argument, NULL, 'x'},
269 {GETOPT_HELP_OPTION_DECL},
270 {GETOPT_VERSION_OPTION_DECL},
271 {NULL, 0, NULL, 0}
274 /* Replace problematic chars with '?'.
275 Since only control characters are currently considered,
276 this should work in all encodings. */
278 static char*
279 hide_problematic_chars (char *cell)
281 char *p = cell;
282 while (*p)
284 if (iscntrl (to_uchar (*p)))
285 *p = '?';
286 p++;
288 return cell;
291 /* Dynamically allocate a row of pointers in TABLE, which
292 can then be accessed with standard 2D array notation. */
294 static void
295 alloc_table_row (void)
297 nrows++;
298 table = xnrealloc (table, nrows, sizeof (char **));
299 table[nrows - 1] = xnmalloc (ncolumns, sizeof (char *));
302 /* Output each cell in the table, accounting for the
303 alignment and max width of each column. */
305 static void
306 print_table (void)
308 size_t row;
310 for (row = 0; row < nrows; row++)
312 size_t col;
313 for (col = 0; col < ncolumns; col++)
315 char *cell = table[row][col];
317 /* Note the SOURCE_FIELD used to be displayed on it's own line
318 if (!posix_format && mbswidth (cell) > 20), but that
319 functionality was probably more problematic than helpful,
320 hence changed in commit v8.10-40-g99679ff. */
321 if (col != 0)
322 putchar (' ');
324 int flags = 0;
325 if (col == ncolumns - 1) /* The last one. */
326 flags = MBA_NO_RIGHT_PAD;
328 size_t width = columns[col]->width;
329 cell = ambsalign (cell, &width, columns[col]->align, flags);
330 /* When ambsalign fails, output unaligned data. */
331 fputs (cell ? cell : table[row][col], stdout);
332 free (cell);
334 IF_LINT (free (table[row][col]));
336 putchar ('\n');
337 IF_LINT (free (table[row]));
340 IF_LINT (free (table));
343 /* Dynamically allocate a struct field_t in COLUMNS, which
344 can then be accessed with standard array notation. */
346 static void
347 alloc_field (int f, const char *c)
349 ncolumns++;
350 columns = xnrealloc (columns, ncolumns, sizeof (struct field_data_t *));
351 columns[ncolumns - 1] = &field_data[f];
352 if (c != NULL)
353 columns[ncolumns - 1]->caption = c;
355 if (field_data[f].used)
356 assert (!"field used");
358 /* Mark field as used. */
359 field_data[f].used = true;
363 /* Given a string, ARG, containing a comma-separated list of arguments
364 to the --output option, add the appropriate fields to columns. */
365 static void
366 decode_output_arg (char const *arg)
368 char *arg_writable = xstrdup (arg);
369 char *s = arg_writable;
372 /* find next comma */
373 char *comma = strchr (s, ',');
375 /* If we found a comma, put a NUL in its place and advance. */
376 if (comma)
377 *comma++ = 0;
379 /* process S. */
380 display_field_t field = INVALID_FIELD;
381 for (unsigned int i = 0; i < ARRAY_CARDINALITY (field_data); i++)
383 if (STREQ (field_data[i].arg, s))
385 field = i;
386 break;
389 if (field == INVALID_FIELD)
391 error (0, 0, _("option --output: field %s unknown"), quote (s));
392 usage (EXIT_FAILURE);
395 if (field_data[field].used)
397 /* Prevent the fields from being used more than once. */
398 error (0, 0, _("option --output: field %s used more than once"),
399 quote (field_data[field].arg));
400 usage (EXIT_FAILURE);
403 switch (field)
405 case SOURCE_FIELD:
406 case FSTYPE_FIELD:
407 case USED_FIELD:
408 case PCENT_FIELD:
409 case ITOTAL_FIELD:
410 case IUSED_FIELD:
411 case IAVAIL_FIELD:
412 case IPCENT_FIELD:
413 case TARGET_FIELD:
414 case FILE_FIELD:
415 alloc_field (field, NULL);
416 break;
418 case SIZE_FIELD:
419 alloc_field (field, N_("Size"));
420 break;
422 case AVAIL_FIELD:
423 alloc_field (field, N_("Avail"));
424 break;
426 default:
427 assert (!"invalid field");
429 s = comma;
431 while (s);
433 free (arg_writable);
436 /* Get the appropriate columns for the mode. */
437 static void
438 get_field_list (void)
440 switch (header_mode)
442 case DEFAULT_MODE:
443 alloc_field (SOURCE_FIELD, NULL);
444 if (print_type)
445 alloc_field (FSTYPE_FIELD, NULL);
446 alloc_field (SIZE_FIELD, NULL);
447 alloc_field (USED_FIELD, NULL);
448 alloc_field (AVAIL_FIELD, NULL);
449 alloc_field (PCENT_FIELD, NULL);
450 alloc_field (TARGET_FIELD, NULL);
451 break;
453 case HUMAN_MODE:
454 alloc_field (SOURCE_FIELD, NULL);
455 if (print_type)
456 alloc_field (FSTYPE_FIELD, NULL);
458 alloc_field (SIZE_FIELD, N_("Size"));
459 alloc_field (USED_FIELD, NULL);
460 alloc_field (AVAIL_FIELD, N_("Avail"));
461 alloc_field (PCENT_FIELD, NULL);
462 alloc_field (TARGET_FIELD, NULL);
463 break;
465 case INODES_MODE:
466 alloc_field (SOURCE_FIELD, NULL);
467 if (print_type)
468 alloc_field (FSTYPE_FIELD, NULL);
469 alloc_field (ITOTAL_FIELD, NULL);
470 alloc_field (IUSED_FIELD, NULL);
471 alloc_field (IAVAIL_FIELD, NULL);
472 alloc_field (IPCENT_FIELD, NULL);
473 alloc_field (TARGET_FIELD, NULL);
474 break;
476 case POSIX_MODE:
477 alloc_field (SOURCE_FIELD, NULL);
478 if (print_type)
479 alloc_field (FSTYPE_FIELD, NULL);
480 alloc_field (SIZE_FIELD, NULL);
481 alloc_field (USED_FIELD, NULL);
482 alloc_field (AVAIL_FIELD, NULL);
483 alloc_field (PCENT_FIELD, N_("Capacity"));
484 alloc_field (TARGET_FIELD, NULL);
485 break;
487 case OUTPUT_MODE:
488 if (!ncolumns)
490 /* Add all fields if --output was given without a field list. */
491 decode_output_arg (all_args_string);
493 break;
495 default:
496 assert (!"invalid header_mode");
500 /* Obtain the appropriate header entries. */
502 static void
503 get_header (void)
505 size_t col;
507 alloc_table_row ();
509 for (col = 0; col < ncolumns; col++)
511 char *cell = NULL;
512 char const *header = _(columns[col]->caption);
514 if (columns[col]->field == SIZE_FIELD
515 && (header_mode == DEFAULT_MODE
516 || (header_mode == OUTPUT_MODE
517 && !(human_output_opts & human_autoscale))))
519 char buf[LONGEST_HUMAN_READABLE + 1];
521 int opts = (human_suppress_point_zero
522 | human_autoscale | human_SI
523 | (human_output_opts
524 & (human_group_digits | human_base_1024 | human_B)));
526 /* Prefer the base that makes the human-readable value more exact,
527 if there is a difference. */
529 uintmax_t q1000 = output_block_size;
530 uintmax_t q1024 = output_block_size;
531 bool divisible_by_1000;
532 bool divisible_by_1024;
536 divisible_by_1000 = q1000 % 1000 == 0; q1000 /= 1000;
537 divisible_by_1024 = q1024 % 1024 == 0; q1024 /= 1024;
539 while (divisible_by_1000 & divisible_by_1024);
541 if (divisible_by_1000 < divisible_by_1024)
542 opts |= human_base_1024;
543 if (divisible_by_1024 < divisible_by_1000)
544 opts &= ~human_base_1024;
545 if (! (opts & human_base_1024))
546 opts |= human_B;
548 char *num = human_readable (output_block_size, buf, opts, 1, 1);
550 /* Reset the header back to the default in OUTPUT_MODE. */
551 header = _("blocks");
553 /* TRANSLATORS: this is the "1K-blocks" header in "df" output. */
554 if (asprintf (&cell, _("%s-%s"), num, header) == -1)
555 cell = NULL;
557 else if (header_mode == POSIX_MODE && columns[col]->field == SIZE_FIELD)
559 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
560 char *num = umaxtostr (output_block_size, buf);
562 /* TRANSLATORS: this is the "1024-blocks" header in "df -P". */
563 if (asprintf (&cell, _("%s-%s"), num, header) == -1)
564 cell = NULL;
566 else
567 cell = strdup (header);
569 if (!cell)
570 xalloc_die ();
572 hide_problematic_chars (cell);
574 table[nrows - 1][col] = cell;
576 columns[col]->width = MAX (columns[col]->width, mbswidth (cell, 0));
580 /* Is FSTYPE a type of file system that should be listed? */
582 static bool _GL_ATTRIBUTE_PURE
583 selected_fstype (const char *fstype)
585 const struct fs_type_list *fsp;
587 if (fs_select_list == NULL || fstype == NULL)
588 return true;
589 for (fsp = fs_select_list; fsp; fsp = fsp->fs_next)
590 if (STREQ (fstype, fsp->fs_name))
591 return true;
592 return false;
595 /* Is FSTYPE a type of file system that should be omitted? */
597 static bool _GL_ATTRIBUTE_PURE
598 excluded_fstype (const char *fstype)
600 const struct fs_type_list *fsp;
602 if (fs_exclude_list == NULL || fstype == NULL)
603 return false;
604 for (fsp = fs_exclude_list; fsp; fsp = fsp->fs_next)
605 if (STREQ (fstype, fsp->fs_name))
606 return true;
607 return false;
610 static size_t
611 devlist_hash (void const *x, size_t table_size)
613 struct devlist const *p = x;
614 return (uintmax_t) p->dev_num % table_size;
617 static bool
618 devlist_compare (void const *x, void const *y)
620 struct devlist const *a = x;
621 struct devlist const *b = y;
622 return a->dev_num == b->dev_num;
625 static struct devlist *
626 devlist_for_dev (dev_t dev)
628 if (devlist_table == NULL)
629 return NULL;
630 struct devlist dev_entry;
631 dev_entry.dev_num = dev;
632 return hash_lookup (devlist_table, &dev_entry);
635 static void
636 devlist_free (void *p)
638 free (p);
641 /* Filter mount list by skipping duplicate entries.
642 In the case of duplicates - based on the device number - the mount entry
643 with a '/' in its me_devname (i.e., not pseudo name like tmpfs) wins.
644 If both have a real devname (e.g. bind mounts), then that with the shorter
645 me_mountdir wins. With DEVICES_ONLY == true (set with df -a), only update
646 the global devlist_table, rather than filtering the global mount_list. */
648 static void
649 filter_mount_list (bool devices_only)
651 struct mount_entry *me;
653 /* Temporary list to keep entries ordered. */
654 struct devlist *device_list = NULL;
655 int mount_list_size = 0;
657 for (me = mount_list; me; me = me->me_next)
658 mount_list_size++;
660 devlist_table = hash_initialize (mount_list_size, NULL,
661 devlist_hash,
662 devlist_compare,
663 devlist_free);
664 if (devlist_table == NULL)
665 xalloc_die ();
667 /* Sort all 'wanted' entries into the list device_list. */
668 for (me = mount_list; me;)
670 struct stat buf;
671 struct mount_entry *discard_me = NULL;
673 /* Avoid stating remote file systems as that may hang.
674 On Linux we probably have me_dev populated from /proc/self/mountinfo,
675 however we still stat() in case another device was mounted later. */
676 if ((me->me_remote && show_local_fs)
677 || -1 == stat (me->me_mountdir, &buf))
679 /* If remote, and showing just local, add ME for filtering later.
680 If stat failed; add ME to be able to complain about it later. */
681 buf.st_dev = me->me_dev;
683 else
685 /* If we've already seen this device... */
686 struct devlist *seen_dev = devlist_for_dev (buf.st_dev);
688 if (seen_dev)
690 bool target_nearer_root = strlen (seen_dev->me->me_mountdir)
691 > strlen (me->me_mountdir);
692 /* With bind mounts, prefer items nearer the root of the source */
693 bool source_below_root = seen_dev->me->me_mntroot != NULL
694 && me->me_mntroot != NULL
695 && (strlen (seen_dev->me->me_mntroot)
696 < strlen (me->me_mntroot));
697 if (! print_grand_total
698 && me->me_remote && seen_dev->me->me_remote
699 && ! STREQ (seen_dev->me->me_devname, me->me_devname))
701 /* Don't discard remote entries with different locations,
702 as these are more likely to be explicitly mounted.
703 However avoid this when producing a total to give
704 a more accurate value in that case. */
706 else if ((strchr (me->me_devname, '/')
707 /* let "real" devices with '/' in the name win. */
708 && ! strchr (seen_dev->me->me_devname, '/'))
709 /* let points towards the root of the device win. */
710 || (target_nearer_root && ! source_below_root)
711 /* let an entry overmounted on a new device win... */
712 || (! STREQ (seen_dev->me->me_devname, me->me_devname)
713 /* ... but only when matching an existing mnt point,
714 to avoid problematic replacement when given
715 inaccurate mount lists, seen with some chroot
716 environments for example. */
717 && STREQ (me->me_mountdir,
718 seen_dev->me->me_mountdir)))
720 /* Discard mount entry for existing device. */
721 discard_me = seen_dev->me;
722 seen_dev->me = me;
724 else
726 /* Discard mount entry currently being processed. */
727 discard_me = me;
733 if (discard_me)
735 me = me->me_next;
736 if (! devices_only)
737 free_mount_entry (discard_me);
739 else
741 /* Add the device number to the device_table. */
742 struct devlist *devlist = xmalloc (sizeof *devlist);
743 devlist->me = me;
744 devlist->dev_num = buf.st_dev;
745 devlist->next = device_list;
746 device_list = devlist;
747 if (hash_insert (devlist_table, devlist) == NULL)
748 xalloc_die ();
750 me = me->me_next;
754 /* Finally rebuild the mount_list from the devlist. */
755 if (! devices_only) {
756 mount_list = NULL;
757 while (device_list)
759 /* Add the mount entry. */
760 me = device_list->me;
761 me->me_next = mount_list;
762 mount_list = me;
763 device_list = device_list->next;
766 hash_free (devlist_table);
767 devlist_table = NULL;
772 /* Search a mount entry list for device id DEV.
773 Return the corresponding mount entry if found or NULL if not. */
775 static struct mount_entry const * _GL_ATTRIBUTE_PURE
776 me_for_dev (dev_t dev)
778 struct devlist *dl = devlist_for_dev (dev);
779 if (dl)
780 return dl->me;
782 return NULL;
785 /* Return true if N is a known integer value. On many file systems,
786 UINTMAX_MAX represents an unknown value; on AIX, UINTMAX_MAX - 1
787 represents unknown. Use a rule that works on AIX file systems, and
788 that almost-always works on other types. */
789 static bool
790 known_value (uintmax_t n)
792 return n < UINTMAX_MAX - 1;
795 /* Like human_readable (N, BUF, human_output_opts, INPUT_UNITS, OUTPUT_UNITS),
796 except:
798 - If NEGATIVE, then N represents a negative number,
799 expressed in two's complement.
800 - Otherwise, return "-" if N is unknown. */
802 static char const *
803 df_readable (bool negative, uintmax_t n, char *buf,
804 uintmax_t input_units, uintmax_t output_units)
806 if (! known_value (n) && !negative)
807 return "-";
808 else
810 char *p = human_readable (negative ? -n : n, buf + negative,
811 human_output_opts, input_units, output_units);
812 if (negative)
813 *--p = '-';
814 return p;
818 /* Logical equivalence */
819 #define LOG_EQ(a, b) (!(a) == !(b))
821 /* Add integral value while using uintmax_t for value part and separate
822 negation flag. It adds value of SRC and SRC_NEG to DEST and DEST_NEG.
823 The result will be in DEST and DEST_NEG. See df_readable to understand
824 how the negation flag is used. */
825 static void
826 add_uint_with_neg_flag (uintmax_t *dest, bool *dest_neg,
827 uintmax_t src, bool src_neg)
829 if (LOG_EQ (*dest_neg, src_neg))
831 *dest += src;
832 return;
835 if (*dest_neg)
836 *dest = -*dest;
838 if (src_neg)
839 src = -src;
841 if (src < *dest)
842 *dest -= src;
843 else
845 *dest = src - *dest;
846 *dest_neg = src_neg;
849 if (*dest_neg)
850 *dest = -*dest;
853 /* Return true if S ends in a string that may be a 36-byte UUID,
854 i.e., of the form HHHHHHHH-HHHH-HHHH-HHHH-HHHHHHHHHHHH, where
855 each H is an upper or lower case hexadecimal digit. */
856 static bool _GL_ATTRIBUTE_PURE
857 has_uuid_suffix (char const *s)
859 size_t len = strlen (s);
860 return (36 < len
861 && strspn (s + len - 36, "-0123456789abcdefABCDEF") == 36);
864 /* Obtain the block values BV and inode values IV
865 from the file system usage FSU. */
866 static void
867 get_field_values (struct field_values_t *bv,
868 struct field_values_t *iv,
869 const struct fs_usage *fsu)
871 /* Inode values. */
872 iv->input_units = iv->output_units = 1;
873 iv->total = fsu->fsu_files;
874 iv->available = iv->available_to_root = fsu->fsu_ffree;
875 iv->negate_available = false;
877 iv->used = UINTMAX_MAX;
878 iv->negate_used = false;
879 if (known_value (iv->total) && known_value (iv->available_to_root))
881 iv->used = iv->total - iv->available_to_root;
882 iv->negate_used = (iv->total < iv->available_to_root);
885 /* Block values. */
886 bv->input_units = fsu->fsu_blocksize;
887 bv->output_units = output_block_size;
888 bv->total = fsu->fsu_blocks;
889 bv->available = fsu->fsu_bavail;
890 bv->available_to_root = fsu->fsu_bfree;
891 bv->negate_available = (fsu->fsu_bavail_top_bit_set
892 && known_value (fsu->fsu_bavail));
894 bv->used = UINTMAX_MAX;
895 bv->negate_used = false;
896 if (known_value (bv->total) && known_value (bv->available_to_root))
898 bv->used = bv->total - bv->available_to_root;
899 bv->negate_used = (bv->total < bv->available_to_root);
903 /* Add block and inode values to grand total. */
904 static void
905 add_to_grand_total (struct field_values_t *bv, struct field_values_t *iv)
907 if (known_value (iv->total))
908 grand_fsu.fsu_files += iv->total;
909 if (known_value (iv->available))
910 grand_fsu.fsu_ffree += iv->available;
912 if (known_value (bv->total))
913 grand_fsu.fsu_blocks += bv->input_units * bv->total;
914 if (known_value (bv->available_to_root))
915 grand_fsu.fsu_bfree += bv->input_units * bv->available_to_root;
916 if (known_value (bv->available))
917 add_uint_with_neg_flag (&grand_fsu.fsu_bavail,
918 &grand_fsu.fsu_bavail_top_bit_set,
919 bv->input_units * bv->available,
920 bv->negate_available);
923 /* Obtain a space listing for the disk device with absolute file name DISK.
924 If MOUNT_POINT is non-NULL, it is the name of the root of the
925 file system on DISK.
926 If STAT_FILE is non-null, it is the name of a file within the file
927 system that the user originally asked for; this provides better
928 diagnostics, and sometimes it provides better results on networked
929 file systems that give different free-space results depending on
930 where in the file system you probe.
931 If FSTYPE is non-NULL, it is the type of the file system on DISK.
932 If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may
933 not be able to produce statistics in this case.
934 ME_DUMMY and ME_REMOTE are the mount entry flags.
935 Caller must set PROCESS_ALL to true when iterating over all entries, as
936 when df is invoked with no non-option argument. See below for details. */
938 static void
939 get_dev (char const *disk, char const *mount_point, char const* file,
940 char const *stat_file, char const *fstype,
941 bool me_dummy, bool me_remote,
942 const struct fs_usage *force_fsu,
943 bool process_all)
945 if (me_remote && show_local_fs)
946 return;
948 if (me_dummy && !show_all_fs && !show_listed_fs)
949 return;
951 if (!selected_fstype (fstype) || excluded_fstype (fstype))
952 return;
954 /* Ignore relative MOUNT_POINTs, which are present for example
955 in /proc/mounts on Linux with network namespaces. */
956 if (!force_fsu && mount_point && ! IS_ABSOLUTE_FILE_NAME (mount_point))
957 return;
959 /* If MOUNT_POINT is NULL, then the file system is not mounted, and this
960 program reports on the file system that the special file is on.
961 It would be better to report on the unmounted file system,
962 but statfs doesn't do that on most systems. */
963 if (!stat_file)
964 stat_file = mount_point ? mount_point : disk;
966 struct fs_usage fsu;
967 if (force_fsu)
968 fsu = *force_fsu;
969 else if (get_fs_usage (stat_file, disk, &fsu))
971 /* If we can't access a system provided entry due
972 to it not being present (now), or due to permissions,
973 just output placeholder values rather than failing. */
974 if (process_all && (errno == EACCES || errno == ENOENT))
976 if (! show_all_fs)
977 return;
979 fstype = "-";
980 fsu.fsu_bavail_top_bit_set = false;
981 fsu.fsu_blocksize = fsu.fsu_blocks = fsu.fsu_bfree =
982 fsu.fsu_bavail = fsu.fsu_files = fsu.fsu_ffree = UINTMAX_MAX;
984 else
986 error (0, errno, "%s", quotef (stat_file));
987 exit_status = EXIT_FAILURE;
988 return;
991 else if (process_all && show_all_fs)
993 /* Ensure we don't output incorrect stats for over-mounted directories.
994 Discard stats when the device name doesn't match. Though don't
995 discard when used and current mount entries are both remote due
996 to the possibility of aliased host names or exports. */
997 struct stat sb;
998 if (stat (stat_file, &sb) == 0)
1000 struct mount_entry const * dev_me = me_for_dev (sb.st_dev);
1001 if (dev_me && ! STREQ (dev_me->me_devname, disk)
1002 && (! dev_me->me_remote || ! me_remote))
1004 fstype = "-";
1005 fsu.fsu_bavail_top_bit_set = false;
1006 fsu.fsu_blocksize = fsu.fsu_blocks = fsu.fsu_bfree =
1007 fsu.fsu_bavail = fsu.fsu_files = fsu.fsu_ffree = UINTMAX_MAX;
1012 if (fsu.fsu_blocks == 0 && !show_all_fs && !show_listed_fs)
1013 return;
1015 if (! force_fsu)
1016 file_systems_processed = true;
1018 alloc_table_row ();
1020 if (! disk)
1021 disk = "-"; /* unknown */
1023 if (! file)
1024 file = "-"; /* unspecified */
1026 char *dev_name = xstrdup (disk);
1027 char *resolved_dev;
1029 /* On some systems, dev_name is a long-named symlink like
1030 /dev/disk/by-uuid/828fc648-9f30-43d8-a0b1-f7196a2edb66 pointing to a
1031 much shorter and more useful name like /dev/sda1. It may also look
1032 like /dev/mapper/luks-828fc648-9f30-43d8-a0b1-f7196a2edb66 and point to
1033 /dev/dm-0. When process_all is true and dev_name is a symlink whose
1034 name ends with a UUID use the resolved name instead. */
1035 if (process_all
1036 && has_uuid_suffix (dev_name)
1037 && (resolved_dev = canonicalize_filename_mode (dev_name, CAN_EXISTING)))
1039 free (dev_name);
1040 dev_name = resolved_dev;
1043 if (! fstype)
1044 fstype = "-"; /* unknown */
1046 struct field_values_t block_values;
1047 struct field_values_t inode_values;
1048 get_field_values (&block_values, &inode_values, &fsu);
1050 /* Add to grand total unless processing grand total line. */
1051 if (print_grand_total && ! force_fsu)
1052 add_to_grand_total (&block_values, &inode_values);
1054 size_t col;
1055 for (col = 0; col < ncolumns; col++)
1057 char buf[LONGEST_HUMAN_READABLE + 2];
1058 char *cell;
1060 struct field_values_t *v;
1061 switch (columns[col]->field_type)
1063 case BLOCK_FLD:
1064 v = &block_values;
1065 break;
1066 case INODE_FLD:
1067 v = &inode_values;
1068 break;
1069 case OTHER_FLD:
1070 v = NULL;
1071 break;
1072 default:
1073 v = NULL; /* Avoid warnings where assert() is not __noreturn__. */
1074 assert (!"bad field_type");
1077 switch (columns[col]->field)
1079 case SOURCE_FIELD:
1080 cell = xstrdup (dev_name);
1081 break;
1083 case FSTYPE_FIELD:
1084 cell = xstrdup (fstype);
1085 break;
1087 case SIZE_FIELD:
1088 case ITOTAL_FIELD:
1089 cell = xstrdup (df_readable (false, v->total, buf,
1090 v->input_units, v->output_units));
1091 break;
1093 case USED_FIELD:
1094 case IUSED_FIELD:
1095 cell = xstrdup (df_readable (v->negate_used, v->used, buf,
1096 v->input_units, v->output_units));
1097 break;
1099 case AVAIL_FIELD:
1100 case IAVAIL_FIELD:
1101 cell = xstrdup (df_readable (v->negate_available, v->available, buf,
1102 v->input_units, v->output_units));
1103 break;
1105 case PCENT_FIELD:
1106 case IPCENT_FIELD:
1108 double pct = -1;
1109 if (! known_value (v->used) || ! known_value (v->available))
1111 else if (!v->negate_used
1112 && v->used <= TYPE_MAXIMUM (uintmax_t) / 100
1113 && v->used + v->available != 0
1114 && (v->used + v->available < v->used)
1115 == v->negate_available)
1117 uintmax_t u100 = v->used * 100;
1118 uintmax_t nonroot_total = v->used + v->available;
1119 pct = u100 / nonroot_total + (u100 % nonroot_total != 0);
1121 else
1123 /* The calculation cannot be done easily with integer
1124 arithmetic. Fall back on floating point. This can suffer
1125 from minor rounding errors, but doing it exactly requires
1126 multiple precision arithmetic, and it's not worth the
1127 aggravation. */
1128 double u = v->negate_used ? - (double) - v->used : v->used;
1129 double a = v->negate_available
1130 ? - (double) - v->available : v->available;
1131 double nonroot_total = u + a;
1132 if (nonroot_total)
1134 long int lipct = pct = u * 100 / nonroot_total;
1135 double ipct = lipct;
1137 /* Like 'pct = ceil (dpct);', but avoid ceil so that
1138 the math library needn't be linked. */
1139 if (ipct - 1 < pct && pct <= ipct + 1)
1140 pct = ipct + (ipct < pct);
1144 if (0 <= pct)
1146 if (asprintf (&cell, "%.0f%%", pct) == -1)
1147 cell = NULL;
1149 else
1150 cell = strdup ("-");
1152 if (!cell)
1153 xalloc_die ();
1155 break;
1158 case FILE_FIELD:
1159 cell = xstrdup (file);
1160 break;
1162 case TARGET_FIELD:
1163 #ifdef HIDE_AUTOMOUNT_PREFIX
1164 /* Don't print the first directory name in MOUNT_POINT if it's an
1165 artifact of an automounter. This is a bit too aggressive to be
1166 the default. */
1167 if (STRNCMP_LIT (mount_point, "/auto/") == 0)
1168 mount_point += 5;
1169 else if (STRNCMP_LIT (mount_point, "/tmp_mnt/") == 0)
1170 mount_point += 8;
1171 #endif
1172 cell = xstrdup (mount_point);
1173 break;
1175 default:
1176 assert (!"unhandled field");
1179 if (!cell)
1180 assert (!"empty cell");
1182 hide_problematic_chars (cell);
1183 columns[col]->width = MAX (columns[col]->width, mbswidth (cell, 0));
1184 table[nrows - 1][col] = cell;
1186 free (dev_name);
1189 /* Scan the mount list returning the _last_ device found for MOUNT.
1190 NULL is returned if MOUNT not found. The result is malloced. */
1191 static char *
1192 last_device_for_mount (char const* mount)
1194 struct mount_entry const *me;
1195 struct mount_entry const *le = NULL;
1197 for (me = mount_list; me; me = me->me_next)
1199 if (STREQ (me->me_mountdir, mount))
1200 le = me;
1203 if (le)
1205 char *devname = le->me_devname;
1206 char *canon_dev = canonicalize_file_name (devname);
1207 if (canon_dev && IS_ABSOLUTE_FILE_NAME (canon_dev))
1208 return canon_dev;
1209 free (canon_dev);
1210 return xstrdup (le->me_devname);
1212 else
1213 return NULL;
1216 /* If DISK corresponds to a mount point, show its usage
1217 and return true. Otherwise, return false. */
1218 static bool
1219 get_disk (char const *disk)
1221 struct mount_entry const *me;
1222 struct mount_entry const *best_match = NULL;
1223 bool best_match_accessible = false;
1224 bool eclipsed_device = false;
1225 char const *file = disk;
1227 char *resolved = canonicalize_file_name (disk);
1228 if (resolved && IS_ABSOLUTE_FILE_NAME (resolved))
1229 disk = resolved;
1231 size_t best_match_len = SIZE_MAX;
1232 for (me = mount_list; me; me = me->me_next)
1234 /* TODO: Should cache canon_dev in the mount_entry struct. */
1235 char *devname = me->me_devname;
1236 char *canon_dev = canonicalize_file_name (me->me_devname);
1237 if (canon_dev && IS_ABSOLUTE_FILE_NAME (canon_dev))
1238 devname = canon_dev;
1240 if (STREQ (disk, devname))
1242 char *last_device = last_device_for_mount (me->me_mountdir);
1243 eclipsed_device = last_device && ! STREQ (last_device, devname);
1244 size_t len = strlen (me->me_mountdir);
1246 if (! eclipsed_device
1247 && (! best_match_accessible || len < best_match_len))
1249 struct stat disk_stats;
1250 bool this_match_accessible = false;
1252 if (stat (me->me_mountdir, &disk_stats) == 0)
1253 best_match_accessible = this_match_accessible = true;
1255 if (this_match_accessible
1256 || (! best_match_accessible && len < best_match_len))
1258 best_match = me;
1259 if (len == 1) /* Traditional root. */
1261 free (last_device);
1262 free (canon_dev);
1263 break;
1265 else
1266 best_match_len = len;
1270 free (last_device);
1273 free (canon_dev);
1276 free (resolved);
1278 if (best_match)
1280 get_dev (best_match->me_devname, best_match->me_mountdir, file, NULL,
1281 best_match->me_type, best_match->me_dummy,
1282 best_match->me_remote, NULL, false);
1283 return true;
1285 else if (eclipsed_device)
1287 error (0, 0, _("cannot access %s: over-mounted by another device"),
1288 quoteaf (file));
1289 exit_status = EXIT_FAILURE;
1290 return true;
1293 return false;
1296 /* Figure out which device file or directory POINT is mounted on
1297 and show its disk usage.
1298 STATP must be the result of 'stat (POINT, STATP)'. */
1299 static void
1300 get_point (const char *point, const struct stat *statp)
1302 struct stat disk_stats;
1303 struct mount_entry *me;
1304 struct mount_entry const *best_match = NULL;
1306 /* Calculate the real absolute file name for POINT, and use that to find
1307 the mount point. This avoids statting unavailable mount points,
1308 which can hang df. */
1309 char *resolved = canonicalize_file_name (point);
1310 if (resolved && resolved[0] == '/')
1312 size_t resolved_len = strlen (resolved);
1313 size_t best_match_len = 0;
1315 for (me = mount_list; me; me = me->me_next)
1317 if (!STREQ (me->me_type, "lofs")
1318 && (!best_match || best_match->me_dummy || !me->me_dummy))
1320 size_t len = strlen (me->me_mountdir);
1321 if (best_match_len <= len && len <= resolved_len
1322 && (len == 1 /* root file system */
1323 || ((len == resolved_len || resolved[len] == '/')
1324 && STREQ_LEN (me->me_mountdir, resolved, len))))
1326 best_match = me;
1327 best_match_len = len;
1332 free (resolved);
1333 if (best_match
1334 && (stat (best_match->me_mountdir, &disk_stats) != 0
1335 || disk_stats.st_dev != statp->st_dev))
1336 best_match = NULL;
1338 if (! best_match)
1339 for (me = mount_list; me; me = me->me_next)
1341 if (me->me_dev == (dev_t) -1)
1343 if (stat (me->me_mountdir, &disk_stats) == 0)
1344 me->me_dev = disk_stats.st_dev;
1345 else
1347 /* Report only I/O errors. Other errors might be
1348 caused by shadowed mount points, which means POINT
1349 can't possibly be on this file system. */
1350 if (errno == EIO)
1352 error (0, errno, "%s", quotef (me->me_mountdir));
1353 exit_status = EXIT_FAILURE;
1356 /* So we won't try and fail repeatedly. */
1357 me->me_dev = (dev_t) -2;
1361 if (statp->st_dev == me->me_dev
1362 && !STREQ (me->me_type, "lofs")
1363 && (!best_match || best_match->me_dummy || !me->me_dummy))
1365 /* Skip bogus mtab entries. */
1366 if (stat (me->me_mountdir, &disk_stats) != 0
1367 || disk_stats.st_dev != me->me_dev)
1368 me->me_dev = (dev_t) -2;
1369 else
1370 best_match = me;
1374 if (best_match)
1375 get_dev (best_match->me_devname, best_match->me_mountdir, point, point,
1376 best_match->me_type, best_match->me_dummy, best_match->me_remote,
1377 NULL, false);
1378 else
1380 /* We couldn't find the mount entry corresponding to POINT. Go ahead and
1381 print as much info as we can; methods that require the device to be
1382 present will fail at a later point. */
1384 /* Find the actual mount point. */
1385 char *mp = find_mount_point (point, statp);
1386 if (mp)
1388 get_dev (NULL, mp, point, NULL, NULL, false, false, NULL, false);
1389 free (mp);
1394 /* Determine what kind of node NAME is and show the disk usage
1395 for it. STATP is the results of 'stat' on NAME. */
1397 static void
1398 get_entry (char const *name, struct stat const *statp)
1400 if ((S_ISBLK (statp->st_mode) || S_ISCHR (statp->st_mode))
1401 && get_disk (name))
1402 return;
1404 get_point (name, statp);
1407 /* Show all mounted file systems, except perhaps those that are of
1408 an unselected type or are empty. */
1410 static void
1411 get_all_entries (void)
1413 struct mount_entry *me;
1415 filter_mount_list (show_all_fs);
1417 for (me = mount_list; me; me = me->me_next)
1418 get_dev (me->me_devname, me->me_mountdir, NULL, NULL, me->me_type,
1419 me->me_dummy, me->me_remote, NULL, true);
1422 /* Add FSTYPE to the list of file system types to display. */
1424 static void
1425 add_fs_type (const char *fstype)
1427 struct fs_type_list *fsp;
1429 fsp = xmalloc (sizeof *fsp);
1430 fsp->fs_name = (char *) fstype;
1431 fsp->fs_next = fs_select_list;
1432 fs_select_list = fsp;
1435 /* Add FSTYPE to the list of file system types to be omitted. */
1437 static void
1438 add_excluded_fs_type (const char *fstype)
1440 struct fs_type_list *fsp;
1442 fsp = xmalloc (sizeof *fsp);
1443 fsp->fs_name = (char *) fstype;
1444 fsp->fs_next = fs_exclude_list;
1445 fs_exclude_list = fsp;
1448 void
1449 usage (int status)
1451 if (status != EXIT_SUCCESS)
1452 emit_try_help ();
1453 else
1455 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name);
1456 fputs (_("\
1457 Show information about the file system on which each FILE resides,\n\
1458 or all file systems by default.\n\
1459 "), stdout);
1461 emit_mandatory_arg_note ();
1463 /* TRANSLATORS: The thousands and decimal separators are best
1464 adjusted to an appropriate default for your locale. */
1465 fputs (_("\
1466 -a, --all include pseudo, duplicate, inaccessible file systems\n\
1467 -B, --block-size=SIZE scale sizes by SIZE before printing them; e.g.,\n\
1468 '-BM' prints sizes in units of 1,048,576 bytes;\n\
1469 see SIZE format below\n\
1470 -h, --human-readable print sizes in powers of 1024 (e.g., 1023M)\n\
1471 -H, --si print sizes in powers of 1000 (e.g., 1.1G)\n\
1472 "), stdout);
1473 fputs (_("\
1474 -i, --inodes list inode information instead of block usage\n\
1475 -k like --block-size=1K\n\
1476 -l, --local limit listing to local file systems\n\
1477 --no-sync do not invoke sync before getting usage info (default)\
1479 "), stdout);
1480 fputs (_("\
1481 --output[=FIELD_LIST] use the output format defined by FIELD_LIST,\n\
1482 or print all fields if FIELD_LIST is omitted.\n\
1483 -P, --portability use the POSIX output format\n\
1484 --sync invoke sync before getting usage info\n\
1485 "), stdout);
1486 fputs (_("\
1487 --total elide all entries insignificant to available space,\n\
1488 and produce a grand total\n\
1489 "), stdout);
1490 fputs (_("\
1491 -t, --type=TYPE limit listing to file systems of type TYPE\n\
1492 -T, --print-type print file system type\n\
1493 -x, --exclude-type=TYPE limit listing to file systems not of type TYPE\n\
1494 -v (ignored)\n\
1495 "), stdout);
1496 fputs (HELP_OPTION_DESCRIPTION, stdout);
1497 fputs (VERSION_OPTION_DESCRIPTION, stdout);
1498 emit_blocksize_note ("DF");
1499 emit_size_note ();
1500 fputs (_("\n\
1501 FIELD_LIST is a comma-separated list of columns to be included. Valid\n\
1502 field names are: 'source', 'fstype', 'itotal', 'iused', 'iavail', 'ipcent',\n\
1503 'size', 'used', 'avail', 'pcent', 'file' and 'target' (see info page).\n\
1504 "), stdout);
1505 emit_ancillary_info (PROGRAM_NAME);
1507 exit (status);
1511 main (int argc, char **argv)
1513 struct stat *stats IF_LINT ( = 0);
1515 initialize_main (&argc, &argv);
1516 set_program_name (argv[0]);
1517 setlocale (LC_ALL, "");
1518 bindtextdomain (PACKAGE, LOCALEDIR);
1519 textdomain (PACKAGE);
1521 atexit (close_stdout);
1523 fs_select_list = NULL;
1524 fs_exclude_list = NULL;
1525 show_all_fs = false;
1526 show_listed_fs = false;
1527 human_output_opts = -1;
1528 print_type = false;
1529 file_systems_processed = false;
1530 exit_status = EXIT_SUCCESS;
1531 print_grand_total = false;
1532 grand_fsu.fsu_blocksize = 1;
1534 /* If true, use the POSIX output format. */
1535 bool posix_format = false;
1537 const char *msg_mut_excl = _("options %s and %s are mutually exclusive");
1539 while (true)
1541 int oi = -1;
1542 int c = getopt_long (argc, argv, "aB:iF:hHklmPTt:vx:", long_options,
1543 &oi);
1544 if (c == -1)
1545 break;
1547 switch (c)
1549 case 'a':
1550 show_all_fs = true;
1551 break;
1552 case 'B':
1554 enum strtol_error e = human_options (optarg, &human_output_opts,
1555 &output_block_size);
1556 if (e != LONGINT_OK)
1557 xstrtol_fatal (e, oi, c, long_options, optarg);
1559 break;
1560 case 'i':
1561 if (header_mode == OUTPUT_MODE)
1563 error (0, 0, msg_mut_excl, "-i", "--output");
1564 usage (EXIT_FAILURE);
1566 header_mode = INODES_MODE;
1567 break;
1568 case 'h':
1569 human_output_opts = human_autoscale | human_SI | human_base_1024;
1570 output_block_size = 1;
1571 break;
1572 case 'H':
1573 human_output_opts = human_autoscale | human_SI;
1574 output_block_size = 1;
1575 break;
1576 case 'k':
1577 human_output_opts = 0;
1578 output_block_size = 1024;
1579 break;
1580 case 'l':
1581 show_local_fs = true;
1582 break;
1583 case 'm': /* obsolescent, exists for BSD compatibility */
1584 human_output_opts = 0;
1585 output_block_size = 1024 * 1024;
1586 break;
1587 case 'T':
1588 if (header_mode == OUTPUT_MODE)
1590 error (0, 0, msg_mut_excl, "-T", "--output");
1591 usage (EXIT_FAILURE);
1593 print_type = true;
1594 break;
1595 case 'P':
1596 if (header_mode == OUTPUT_MODE)
1598 error (0, 0, msg_mut_excl, "-P", "--output");
1599 usage (EXIT_FAILURE);
1601 posix_format = true;
1602 break;
1603 case SYNC_OPTION:
1604 require_sync = true;
1605 break;
1606 case NO_SYNC_OPTION:
1607 require_sync = false;
1608 break;
1610 case 'F':
1611 /* Accept -F as a synonym for -t for compatibility with Solaris. */
1612 case 't':
1613 add_fs_type (optarg);
1614 break;
1616 case 'v': /* For SysV compatibility. */
1617 /* ignore */
1618 break;
1619 case 'x':
1620 add_excluded_fs_type (optarg);
1621 break;
1623 case OUTPUT_OPTION:
1624 if (header_mode == INODES_MODE)
1626 error (0, 0, msg_mut_excl, "-i", "--output");
1627 usage (EXIT_FAILURE);
1629 if (posix_format && header_mode == DEFAULT_MODE)
1631 error (0, 0, msg_mut_excl, "-P", "--output");
1632 usage (EXIT_FAILURE);
1634 if (print_type)
1636 error (0, 0, msg_mut_excl, "-T", "--output");
1637 usage (EXIT_FAILURE);
1639 header_mode = OUTPUT_MODE;
1640 if (optarg)
1641 decode_output_arg (optarg);
1642 break;
1644 case TOTAL_OPTION:
1645 print_grand_total = true;
1646 break;
1648 case_GETOPT_HELP_CHAR;
1649 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1651 default:
1652 usage (EXIT_FAILURE);
1656 if (human_output_opts == -1)
1658 if (posix_format)
1660 human_output_opts = 0;
1661 output_block_size = (getenv ("POSIXLY_CORRECT") ? 512 : 1024);
1663 else
1664 human_options (getenv ("DF_BLOCK_SIZE"),
1665 &human_output_opts, &output_block_size);
1668 if (header_mode == INODES_MODE || header_mode == OUTPUT_MODE)
1670 else if (human_output_opts & human_autoscale)
1671 header_mode = HUMAN_MODE;
1672 else if (posix_format)
1673 header_mode = POSIX_MODE;
1675 /* Fail if the same file system type was both selected and excluded. */
1677 bool match = false;
1678 struct fs_type_list *fs_incl;
1679 for (fs_incl = fs_select_list; fs_incl; fs_incl = fs_incl->fs_next)
1681 struct fs_type_list *fs_excl;
1682 for (fs_excl = fs_exclude_list; fs_excl; fs_excl = fs_excl->fs_next)
1684 if (STREQ (fs_incl->fs_name, fs_excl->fs_name))
1686 error (0, 0,
1687 _("file system type %s both selected and excluded"),
1688 quote (fs_incl->fs_name));
1689 match = true;
1690 break;
1694 if (match)
1695 return EXIT_FAILURE;
1698 assume (0 < optind);
1700 if (optind < argc)
1702 int i;
1704 /* Open each of the given entries to make sure any corresponding
1705 partition is automounted. This must be done before reading the
1706 file system table. */
1707 stats = xnmalloc (argc - optind, sizeof *stats);
1708 for (i = optind; i < argc; ++i)
1710 /* Prefer to open with O_NOCTTY and use fstat, but fall back
1711 on using "stat", in case the file is unreadable. */
1712 int fd = open (argv[i], O_RDONLY | O_NOCTTY);
1713 if ((fd < 0 || fstat (fd, &stats[i - optind]))
1714 && stat (argv[i], &stats[i - optind]))
1716 error (0, errno, "%s", quotef (argv[i]));
1717 exit_status = EXIT_FAILURE;
1718 argv[i] = NULL;
1720 if (0 <= fd)
1721 close (fd);
1725 mount_list =
1726 read_file_system_list ((fs_select_list != NULL
1727 || fs_exclude_list != NULL
1728 || print_type
1729 || field_data[FSTYPE_FIELD].used
1730 || show_local_fs));
1732 if (mount_list == NULL)
1734 /* Couldn't read the table of mounted file systems.
1735 Fail if df was invoked with no file name arguments,
1736 or when either of -a, -l, -t or -x is used with file name
1737 arguments. Otherwise, merely give a warning and proceed. */
1738 int status = 0;
1739 if ( ! (optind < argc)
1740 || (show_all_fs
1741 || show_local_fs
1742 || fs_select_list != NULL
1743 || fs_exclude_list != NULL))
1745 status = EXIT_FAILURE;
1747 const char *warning = (status == 0 ? _("Warning: ") : "");
1748 error (status, errno, "%s%s", warning,
1749 _("cannot read table of mounted file systems"));
1752 if (require_sync)
1753 sync ();
1755 get_field_list ();
1756 get_header ();
1758 if (optind < argc)
1760 int i;
1762 /* Display explicitly requested empty file systems. */
1763 show_listed_fs = true;
1765 for (i = optind; i < argc; ++i)
1766 if (argv[i])
1767 get_entry (argv[i], &stats[i - optind]);
1769 IF_LINT (free (stats));
1771 else
1772 get_all_entries ();
1774 if (file_systems_processed)
1776 if (print_grand_total)
1777 get_dev ("total",
1778 (field_data[SOURCE_FIELD].used ? "-" : "total"),
1779 NULL, NULL, NULL, false, false, &grand_fsu, false);
1781 print_table ();
1783 else
1785 /* Print the "no FS processed" diagnostic only if there was no preceding
1786 diagnostic, e.g., if all have been excluded. */
1787 if (exit_status == EXIT_SUCCESS)
1788 die (EXIT_FAILURE, 0, _("no file systems processed"));
1791 IF_LINT (free (columns));
1793 return exit_status;