1 /* df - summarize free disk space
2 Copyright (C) 1991-2012 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. */
23 #include <sys/types.h>
28 #include "canonicalize.h"
34 #include "mountlist.h"
36 #include "find-mount-point.h"
38 /* The official name of this program (e.g., no 'g' prefix). */
39 #define PROGRAM_NAME "df"
42 proper_name_utf8 ("Torbjorn Granlund", "Torbj\303\266rn Granlund"), \
43 proper_name ("David MacKenzie"), \
44 proper_name ("Paul Eggert")
46 /* If true, show even file systems with zero size or
47 uninteresting types. */
48 static bool show_all_fs;
50 /* If true, show only local file systems. */
51 static bool show_local_fs;
53 /* If true, output data for each file system corresponding to a
54 command line argument -- even if it's a dummy (automounter) entry. */
55 static bool show_listed_fs;
57 /* Human-readable options for output. */
58 static int human_output_opts;
60 /* The units to use when printing sizes. */
61 static uintmax_t output_block_size;
63 /* True if a file system has been processed for output. */
64 static bool file_systems_processed;
66 /* If true, invoke the 'sync' system call before getting any usage data.
67 Using this option can make df very slow, especially with many or very
68 busy disks. Note that this may make a difference on some systems --
69 SunOS 4.1.3, for one. It is *not* necessary on GNU/Linux. */
70 static bool require_sync;
72 /* Desired exit status. */
73 static int exit_status;
75 /* A file system type to display. */
80 struct fs_type_list *fs_next;
83 /* Linked list of file system types to display.
84 If 'fs_select_list' is NULL, list all types.
85 This table is generated dynamically from command-line options,
86 rather than hardcoding into the program what it thinks are the
87 valid file system types; let the user specify any file system type
88 they want to, and if there are any file systems of that type, they
91 Some file system types:
92 4.2 4.3 ufs nfs swap ignore io vm efs dbg */
94 static struct fs_type_list *fs_select_list;
96 /* Linked list of file system types to omit.
97 If the list is empty, don't exclude any types. */
99 static struct fs_type_list *fs_exclude_list;
101 /* Linked list of mounted file systems. */
102 static struct mount_entry *mount_list;
104 /* If true, print file system type as well. */
105 static bool print_type;
107 /* If true, print a grand total at the end. */
108 static bool print_grand_total;
110 /* Grand total data. */
111 static struct fs_usage grand_fsu;
122 static int header_mode = DEFAULT_MODE;
124 /* Displayable fields. */
127 SOURCE_FIELD, /* file system */
128 FSTYPE_FIELD, /* FS type */
129 SIZE_FIELD, /* FS size */
130 USED_FIELD, /* FS size used */
131 AVAIL_FIELD, /* FS size available */
132 PCENT_FIELD, /* percent used */
133 ITOTAL_FIELD, /* inode total */
134 IUSED_FIELD, /* inodes used */
135 IAVAIL_FIELD, /* inodes available */
136 IPCENT_FIELD, /* inodes used in percent */
137 TARGET_FIELD /* mount point */
140 /* Flag if a field contains a block, an inode or another value. */
143 BLOCK_FLD, /* Block values field */
144 INODE_FLD, /* Inode values field */
145 OTHER_FLD /* Neutral field, e.g. target */
148 /* Attributes of a display field. */
151 display_field_t field;
153 field_type_t field_type;
154 const char *caption;/* NULL means to use the default header of this field. */
155 size_t width; /* Auto adjusted (up) widths used to align columns. */
156 mbs_align_t align; /* Alignment for this field. */
160 /* Header strings, minimum width and alignment for the above fields. */
161 static struct field_data_t field_data[] = {
162 [SOURCE_FIELD] = { SOURCE_FIELD,
163 "source", OTHER_FLD, N_("Filesystem"), 14, MBS_ALIGN_LEFT, false },
165 [FSTYPE_FIELD] = { FSTYPE_FIELD,
166 "fstype", OTHER_FLD, N_("Type"), 4, MBS_ALIGN_LEFT, false },
168 [SIZE_FIELD] = { SIZE_FIELD,
169 "size", BLOCK_FLD, N_("blocks"), 5, MBS_ALIGN_RIGHT, false },
171 [USED_FIELD] = { USED_FIELD,
172 "used", BLOCK_FLD, N_("Used"), 5, MBS_ALIGN_RIGHT, false },
174 [AVAIL_FIELD] = { AVAIL_FIELD,
175 "avail", BLOCK_FLD, N_("Available"), 5, MBS_ALIGN_RIGHT, false },
177 [PCENT_FIELD] = { PCENT_FIELD,
178 "pcent", BLOCK_FLD, N_("Use%"), 4, MBS_ALIGN_RIGHT, false },
180 [ITOTAL_FIELD] = { ITOTAL_FIELD,
181 "itotal", INODE_FLD, N_("Inodes"), 5, MBS_ALIGN_RIGHT, false },
183 [IUSED_FIELD] = { IUSED_FIELD,
184 "iused", INODE_FLD, N_("IUsed"), 5, MBS_ALIGN_RIGHT, false },
186 [IAVAIL_FIELD] = { IAVAIL_FIELD,
187 "iavail", INODE_FLD, N_("IFree"), 5, MBS_ALIGN_RIGHT, false },
189 [IPCENT_FIELD] = { IPCENT_FIELD,
190 "ipcent", INODE_FLD, N_("IUse%"), 4, MBS_ALIGN_RIGHT, false },
192 [TARGET_FIELD] = { TARGET_FIELD,
193 "target", OTHER_FLD, N_("Mounted on"), 0, MBS_ALIGN_LEFT, false }
196 static char const *all_args_string =
197 "source,fstype,itotal,iused,iavail,ipcent,size,used,avail,pcent,target";
199 /* Storage for the definition of output columns. */
200 static struct field_data_t **columns;
202 /* The current number of output columns. */
203 static size_t ncolumns;
206 struct field_values_t
208 uintmax_t input_units;
209 uintmax_t output_units;
212 bool negate_available;
213 uintmax_t available_to_root;
218 /* Storage for pointers for each string (cell of table). */
219 static char ***table;
221 /* The current number of processed rows (including header). */
224 /* For long options that have no equivalent short option, use a
225 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
228 NO_SYNC_OPTION = CHAR_MAX + 1,
232 MEGABYTES_OPTION /* FIXME: remove long opt in Aug 2013 */
235 static struct option const long_options[] =
237 {"all", no_argument, NULL, 'a'},
238 {"block-size", required_argument, NULL, 'B'},
239 {"inodes", no_argument, NULL, 'i'},
240 {"human-readable", no_argument, NULL, 'h'},
241 {"si", no_argument, NULL, 'H'},
242 {"local", no_argument, NULL, 'l'},
243 {"megabytes", no_argument, NULL, MEGABYTES_OPTION}, /* obsolescent, */
244 {"output", optional_argument, NULL, OUTPUT_OPTION},
245 {"portability", no_argument, NULL, 'P'},
246 {"print-type", no_argument, NULL, 'T'},
247 {"sync", no_argument, NULL, SYNC_OPTION},
248 {"no-sync", no_argument, NULL, NO_SYNC_OPTION},
249 {"total", no_argument, NULL, TOTAL_OPTION},
250 {"type", required_argument, NULL, 't'},
251 {"exclude-type", required_argument, NULL, 'x'},
252 {GETOPT_HELP_OPTION_DECL},
253 {GETOPT_VERSION_OPTION_DECL},
257 /* Replace problematic chars with '?'.
258 Since only control characters are currently considered,
259 this should work in all encodings. */
262 hide_problematic_chars (char *cell)
267 if (iscntrl (to_uchar (*p)))
274 /* Dynamically allocate a row of pointers in TABLE, which
275 can then be accessed with standard 2D array notation. */
278 alloc_table_row (void)
281 table = xnrealloc (table, nrows, sizeof (char *));
282 table[nrows - 1] = xnmalloc (ncolumns, sizeof (char *));
285 /* Output each cell in the table, accounting for the
286 alignment and max width of each column. */
293 for (row = 0; row < nrows; row++)
296 for (col = 0; col < ncolumns; col++)
298 char *cell = table[row][col];
300 /* Note the SOURCE_FIELD used to be displayed on it's own line
301 if (!posix_format && mbswidth (cell) > 20), but that
302 functionality was probably more problematic than helpful,
303 hence changed in commit v8.10-40-g99679ff. */
308 if (col == ncolumns - 1) /* The last one. */
309 flags = MBA_NO_RIGHT_PAD;
311 size_t width = columns[col]->width;
312 cell = ambsalign (cell, &width, columns[col]->align, flags);
313 /* When ambsalign fails, output unaligned data. */
314 fputs (cell ? cell : table[row][col], stdout);
317 IF_LINT (free (table[row][col]));
320 IF_LINT (free (table[row]));
323 IF_LINT (free (table));
326 /* Dynamically allocate a struct field_t in COLUMNS, which
327 can then be accessed with standard array notation. */
330 alloc_field (int f, const char *c)
333 columns = xnrealloc (columns, ncolumns, sizeof (struct field_data_t *));
334 columns[ncolumns - 1] = &field_data[f];
336 columns[ncolumns - 1]->caption = c;
338 if (field_data[f].used)
339 assert (!"field used");
341 /* Mark field as used. */
342 field_data[f].used = true;
346 /* Given a string, ARG, containing a comma-separated list of arguments
347 to the --output option, add the appropriate fields to columns. */
349 decode_output_arg (char const *arg)
351 char *arg_writable = xstrdup (arg);
352 char *s = arg_writable;
355 /* find next comma */
356 char *comma = strchr (s, ',');
358 /* If we found a comma, put a NUL in its place and advance. */
363 display_field_t field = -1;
364 for (unsigned int i = 0; i < ARRAY_CARDINALITY (field_data); i++)
366 if (STREQ (field_data[i].arg, s))
374 error (0, 0, _("option --output: field '%s' unknown"), s);
375 usage (EXIT_FAILURE);
378 if (field_data[field].used)
380 /* Prevent the fields from being used more than once. */
381 error (0, 0, _("option --output: field '%s' used more than once"),
382 field_data[field].arg);
383 usage (EXIT_FAILURE);
397 alloc_field (field, NULL);
401 alloc_field (field, N_("Size"));
405 alloc_field (field, N_("Avail"));
409 assert (!"invalid field");
418 /* Get the appropriate columns for the mode. */
420 get_field_list (void)
425 alloc_field (SOURCE_FIELD, NULL);
427 alloc_field (FSTYPE_FIELD, NULL);
428 alloc_field (SIZE_FIELD, NULL);
429 alloc_field (USED_FIELD, NULL);
430 alloc_field (AVAIL_FIELD, NULL);
431 alloc_field (PCENT_FIELD, NULL);
432 alloc_field (TARGET_FIELD, NULL);
436 alloc_field (SOURCE_FIELD, NULL);
438 alloc_field (FSTYPE_FIELD, NULL);
440 alloc_field (SIZE_FIELD, N_("Size"));
441 alloc_field (USED_FIELD, NULL);
442 alloc_field (AVAIL_FIELD, N_("Avail"));
443 alloc_field (PCENT_FIELD, NULL);
444 alloc_field (TARGET_FIELD, NULL);
448 alloc_field (SOURCE_FIELD, NULL);
450 alloc_field (FSTYPE_FIELD, NULL);
451 alloc_field (ITOTAL_FIELD, NULL);
452 alloc_field (IUSED_FIELD, NULL);
453 alloc_field (IAVAIL_FIELD, NULL);
454 alloc_field (IPCENT_FIELD, NULL);
455 alloc_field (TARGET_FIELD, NULL);
459 alloc_field (SOURCE_FIELD, NULL);
461 alloc_field (FSTYPE_FIELD, NULL);
462 alloc_field (SIZE_FIELD, NULL);
463 alloc_field (USED_FIELD, NULL);
464 alloc_field (AVAIL_FIELD, NULL);
465 alloc_field (PCENT_FIELD, N_("Capacity"));
466 alloc_field (TARGET_FIELD, NULL);
472 /* Add all fields if --output was given without a field list. */
473 decode_output_arg (all_args_string);
478 assert (!"invalid header_mode");
482 /* Obtain the appropriate header entries. */
491 for (col = 0; col < ncolumns; col++)
494 char const *header = _(columns[col]->caption);
496 if (columns[col]->field == SIZE_FIELD
497 && (header_mode == DEFAULT_MODE
498 || (header_mode == OUTPUT_MODE
499 && !(human_output_opts & human_autoscale))))
501 char buf[LONGEST_HUMAN_READABLE + 1];
503 int opts = (human_suppress_point_zero
504 | human_autoscale | human_SI
506 & (human_group_digits | human_base_1024 | human_B)));
508 /* Prefer the base that makes the human-readable value more exact,
509 if there is a difference. */
511 uintmax_t q1000 = output_block_size;
512 uintmax_t q1024 = output_block_size;
513 bool divisible_by_1000;
514 bool divisible_by_1024;
518 divisible_by_1000 = q1000 % 1000 == 0; q1000 /= 1000;
519 divisible_by_1024 = q1024 % 1024 == 0; q1024 /= 1024;
521 while (divisible_by_1000 & divisible_by_1024);
523 if (divisible_by_1000 < divisible_by_1024)
524 opts |= human_base_1024;
525 if (divisible_by_1024 < divisible_by_1000)
526 opts &= ~human_base_1024;
527 if (! (opts & human_base_1024))
530 char *num = human_readable (output_block_size, buf, opts, 1, 1);
532 /* Reset the header back to the default in OUTPUT_MODE. */
533 header = N_("blocks");
535 /* TRANSLATORS: this is the "1K-blocks" header in "df" output. */
536 if (asprintf (&cell, _("%s-%s"), num, header) == -1)
539 else if (header_mode == POSIX_MODE && columns[col]->field == SIZE_FIELD)
541 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
542 char *num = umaxtostr (output_block_size, buf);
544 /* TRANSLATORS: this is the "1024-blocks" header in "df -P". */
545 if (asprintf (&cell, _("%s-%s"), num, header) == -1)
549 cell = strdup (header);
554 hide_problematic_chars (cell);
556 table[nrows - 1][col] = cell;
558 columns[col]->width = MAX (columns[col]->width, mbswidth (cell, 0));
562 /* Is FSTYPE a type of file system that should be listed? */
564 static bool _GL_ATTRIBUTE_PURE
565 selected_fstype (const char *fstype)
567 const struct fs_type_list *fsp;
569 if (fs_select_list == NULL || fstype == NULL)
571 for (fsp = fs_select_list; fsp; fsp = fsp->fs_next)
572 if (STREQ (fstype, fsp->fs_name))
577 /* Is FSTYPE a type of file system that should be omitted? */
579 static bool _GL_ATTRIBUTE_PURE
580 excluded_fstype (const char *fstype)
582 const struct fs_type_list *fsp;
584 if (fs_exclude_list == NULL || fstype == NULL)
586 for (fsp = fs_exclude_list; fsp; fsp = fsp->fs_next)
587 if (STREQ (fstype, fsp->fs_name))
592 /* Return true if N is a known integer value. On many file systems,
593 UINTMAX_MAX represents an unknown value; on AIX, UINTMAX_MAX - 1
594 represents unknown. Use a rule that works on AIX file systems, and
595 that almost-always works on other types. */
597 known_value (uintmax_t n)
599 return n < UINTMAX_MAX - 1;
602 /* Like human_readable (N, BUF, human_output_opts, INPUT_UNITS, OUTPUT_UNITS),
605 - If NEGATIVE, then N represents a negative number,
606 expressed in two's complement.
607 - Otherwise, return "-" if N is unknown. */
610 df_readable (bool negative, uintmax_t n, char *buf,
611 uintmax_t input_units, uintmax_t output_units)
613 if (! known_value (n) && !negative)
617 char *p = human_readable (negative ? -n : n, buf + negative,
618 human_output_opts, input_units, output_units);
625 /* Logical equivalence */
626 #define LOG_EQ(a, b) (!(a) == !(b))
628 /* Add integral value while using uintmax_t for value part and separate
629 negation flag. It adds value of SRC and SRC_NEG to DEST and DEST_NEG.
630 The result will be in DEST and DEST_NEG. See df_readable to understand
631 how the negation flag is used. */
633 add_uint_with_neg_flag (uintmax_t *dest, bool *dest_neg,
634 uintmax_t src, bool src_neg)
636 if (LOG_EQ (*dest_neg, src_neg))
660 /* Return true if S ends in a string that may be a 36-byte UUID,
661 i.e., of the form HHHHHHHH-HHHH-HHHH-HHHH-HHHHHHHHHHHH, where
662 each H is an upper or lower case hexadecimal digit. */
663 static bool _GL_ATTRIBUTE_PURE
664 has_uuid_suffix (char const *s)
666 size_t len = strlen (s);
668 && strspn (s + len - 36, "-0123456789abcdefABCDEF") == 36);
671 /* Obtain the block values BV and inode values IV
672 from the file system usage FSU. */
674 get_field_values (struct field_values_t *bv,
675 struct field_values_t *iv,
676 const struct fs_usage *fsu)
679 iv->input_units = iv->output_units = 1;
680 iv->total = fsu->fsu_files;
681 iv->available = iv->available_to_root = fsu->fsu_ffree;
682 iv->negate_available = false;
684 iv->used = UINTMAX_MAX;
685 iv->negate_used = false;
686 if (known_value (iv->total) && known_value (iv->available_to_root))
688 iv->used = iv->total - iv->available_to_root;
689 iv->negate_used = (iv->total < iv->available_to_root);
693 bv->input_units = fsu->fsu_blocksize;
694 bv->output_units = output_block_size;
695 bv->total = fsu->fsu_blocks;
696 bv->available = fsu->fsu_bavail;
697 bv->available_to_root = fsu->fsu_bfree;
698 bv->negate_available = (fsu->fsu_bavail_top_bit_set
699 && known_value (fsu->fsu_bavail));
701 bv->used = UINTMAX_MAX;
702 bv->negate_used = false;
703 if (known_value (bv->total) && known_value (bv->available_to_root))
705 bv->used = bv->total - bv->available_to_root;
706 bv->negate_used = (bv->total < bv->available_to_root);
710 /* Add block and inode values to grand total. */
712 add_to_grand_total (struct field_values_t *bv, struct field_values_t *iv)
714 if (known_value (iv->total))
715 grand_fsu.fsu_files += iv->total;
716 if (known_value (iv->available))
717 grand_fsu.fsu_ffree += iv->available;
719 if (known_value (bv->total))
720 grand_fsu.fsu_blocks += bv->input_units * bv->total;
721 if (known_value (bv->available_to_root))
722 grand_fsu.fsu_bfree += bv->input_units * bv->available_to_root;
723 if (known_value (bv->available))
724 add_uint_with_neg_flag (&grand_fsu.fsu_bavail,
725 &grand_fsu.fsu_bavail_top_bit_set,
726 bv->input_units * bv->available,
727 bv->negate_available);
730 /* Obtain a space listing for the disk device with absolute file name DISK.
731 If MOUNT_POINT is non-NULL, it is the name of the root of the
733 If STAT_FILE is non-null, it is the name of a file within the file
734 system that the user originally asked for; this provides better
735 diagnostics, and sometimes it provides better results on networked
736 file systems that give different free-space results depending on
737 where in the file system you probe.
738 If FSTYPE is non-NULL, it is the type of the file system on DISK.
739 If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may
740 not be able to produce statistics in this case.
741 ME_DUMMY and ME_REMOTE are the mount entry flags.
742 Caller must set PROCESS_ALL to true when iterating over all entries, as
743 when df is invoked with no non-option argument. See below for details. */
746 get_dev (char const *disk, char const *mount_point,
747 char const *stat_file, char const *fstype,
748 bool me_dummy, bool me_remote,
749 const struct fs_usage *force_fsu,
752 if (me_remote && show_local_fs)
755 if (me_dummy && !show_all_fs && !show_listed_fs)
758 if (!selected_fstype (fstype) || excluded_fstype (fstype))
761 /* If MOUNT_POINT is NULL, then the file system is not mounted, and this
762 program reports on the file system that the special file is on.
763 It would be better to report on the unmounted file system,
764 but statfs doesn't do that on most systems. */
766 stat_file = mount_point ? mount_point : disk;
771 else if (get_fs_usage (stat_file, disk, &fsu))
773 error (0, errno, "%s", quote (stat_file));
774 exit_status = EXIT_FAILURE;
778 if (fsu.fsu_blocks == 0 && !show_all_fs && !show_listed_fs)
782 file_systems_processed = true;
787 disk = "-"; /* unknown */
789 char *dev_name = xstrdup (disk);
792 /* On some systems, dev_name is a long-named symlink like
793 /dev/disk/by-uuid/828fc648-9f30-43d8-a0b1-f7196a2edb66 pointing to a
794 much shorter and more useful name like /dev/sda1. It may also look
795 like /dev/mapper/luks-828fc648-9f30-43d8-a0b1-f7196a2edb66 and point to
796 /dev/dm-0. When process_all is true and dev_name is a symlink whose
797 name ends with a UUID use the resolved name instead. */
799 && has_uuid_suffix (dev_name)
800 && (resolved_dev = canonicalize_filename_mode (dev_name, CAN_EXISTING)))
803 dev_name = resolved_dev;
807 fstype = "-"; /* unknown */
809 struct field_values_t block_values;
810 struct field_values_t inode_values;
811 get_field_values (&block_values, &inode_values, &fsu);
813 /* Add to grand total unless processing grand total line. */
814 if (print_grand_total && ! force_fsu)
815 add_to_grand_total (&block_values, &inode_values);
818 for (col = 0; col < ncolumns; col++)
820 char buf[LONGEST_HUMAN_READABLE + 2];
823 struct field_values_t *v;
824 switch (columns[col]->field_type)
836 assert (!"bad field_type");
839 switch (columns[col]->field)
842 cell = xstrdup (dev_name);
846 cell = xstrdup (fstype);
851 cell = xstrdup (df_readable (false, v->total, buf,
852 v->input_units, v->output_units));
857 cell = xstrdup (df_readable (v->negate_used, v->used, buf,
858 v->input_units, v->output_units));
863 cell = xstrdup (df_readable (v->negate_available, v->available, buf,
864 v->input_units, v->output_units));
871 if (! known_value (v->used) || ! known_value (v->available))
873 else if (!v->negate_used
874 && v->used <= TYPE_MAXIMUM (uintmax_t) / 100
875 && v->used + v->available != 0
876 && (v->used + v->available < v->used)
877 == v->negate_available)
879 uintmax_t u100 = v->used * 100;
880 uintmax_t nonroot_total = v->used + v->available;
881 pct = u100 / nonroot_total + (u100 % nonroot_total != 0);
885 /* The calculation cannot be done easily with integer
886 arithmetic. Fall back on floating point. This can suffer
887 from minor rounding errors, but doing it exactly requires
888 multiple precision arithmetic, and it's not worth the
890 double u = v->negate_used ? - (double) - v->used : v->used;
891 double a = v->negate_available
892 ? - (double) - v->available : v->available;
893 double nonroot_total = u + a;
896 long int lipct = pct = u * 100 / nonroot_total;
899 /* Like 'pct = ceil (dpct);', but avoid ceil so that
900 the math library needn't be linked. */
901 if (ipct - 1 < pct && pct <= ipct + 1)
902 pct = ipct + (ipct < pct);
908 if (asprintf (&cell, "%.0f%%", pct) == -1)
921 #ifdef HIDE_AUTOMOUNT_PREFIX
922 /* Don't print the first directory name in MOUNT_POINT if it's an
923 artifact of an automounter. This is a bit too aggressive to be
925 if (STRNCMP_LIT (mount_point, "/auto/") == 0)
927 else if (STRNCMP_LIT (mount_point, "/tmp_mnt/") == 0)
930 cell = xstrdup (mount_point);
934 assert (!"unhandled field");
938 assert (!"empty cell");
940 hide_problematic_chars (cell);
941 columns[col]->width = MAX (columns[col]->width, mbswidth (cell, 0));
942 table[nrows - 1][col] = cell;
947 /* If DISK corresponds to a mount point, show its usage
948 and return true. Otherwise, return false. */
950 get_disk (char const *disk)
952 struct mount_entry const *me;
953 struct mount_entry const *best_match = NULL;
955 for (me = mount_list; me; me = me->me_next)
956 if (STREQ (disk, me->me_devname))
961 get_dev (best_match->me_devname, best_match->me_mountdir, NULL,
962 best_match->me_type, best_match->me_dummy,
963 best_match->me_remote, NULL, false);
970 /* Figure out which device file or directory POINT is mounted on
971 and show its disk usage.
972 STATP must be the result of 'stat (POINT, STATP)'. */
974 get_point (const char *point, const struct stat *statp)
976 struct stat disk_stats;
977 struct mount_entry *me;
978 struct mount_entry const *best_match = NULL;
980 /* Calculate the real absolute file name for POINT, and use that to find
981 the mount point. This avoids statting unavailable mount points,
982 which can hang df. */
983 char *resolved = canonicalize_file_name (point);
984 if (resolved && resolved[0] == '/')
986 size_t resolved_len = strlen (resolved);
987 size_t best_match_len = 0;
989 for (me = mount_list; me; me = me->me_next)
990 if (!STREQ (me->me_type, "lofs")
991 && (!best_match || best_match->me_dummy || !me->me_dummy))
993 size_t len = strlen (me->me_mountdir);
994 if (best_match_len <= len && len <= resolved_len
995 && (len == 1 /* root file system */
996 || ((len == resolved_len || resolved[len] == '/')
997 && STREQ_LEN (me->me_mountdir, resolved, len))))
1000 best_match_len = len;
1006 && (stat (best_match->me_mountdir, &disk_stats) != 0
1007 || disk_stats.st_dev != statp->st_dev))
1011 for (me = mount_list; me; me = me->me_next)
1013 if (me->me_dev == (dev_t) -1)
1015 if (stat (me->me_mountdir, &disk_stats) == 0)
1016 me->me_dev = disk_stats.st_dev;
1019 /* Report only I/O errors. Other errors might be
1020 caused by shadowed mount points, which means POINT
1021 can't possibly be on this file system. */
1024 error (0, errno, "%s", quote (me->me_mountdir));
1025 exit_status = EXIT_FAILURE;
1028 /* So we won't try and fail repeatedly. */
1029 me->me_dev = (dev_t) -2;
1033 if (statp->st_dev == me->me_dev
1034 && !STREQ (me->me_type, "lofs")
1035 && (!best_match || best_match->me_dummy || !me->me_dummy))
1037 /* Skip bogus mtab entries. */
1038 if (stat (me->me_mountdir, &disk_stats) != 0
1039 || disk_stats.st_dev != me->me_dev)
1040 me->me_dev = (dev_t) -2;
1047 get_dev (best_match->me_devname, best_match->me_mountdir, point,
1048 best_match->me_type, best_match->me_dummy, best_match->me_remote,
1052 /* We couldn't find the mount entry corresponding to POINT. Go ahead and
1053 print as much info as we can; methods that require the device to be
1054 present will fail at a later point. */
1056 /* Find the actual mount point. */
1057 char *mp = find_mount_point (point, statp);
1060 get_dev (NULL, mp, NULL, NULL, false, false, NULL, false);
1066 /* Determine what kind of node NAME is and show the disk usage
1067 for it. STATP is the results of 'stat' on NAME. */
1070 get_entry (char const *name, struct stat const *statp)
1072 if ((S_ISBLK (statp->st_mode) || S_ISCHR (statp->st_mode))
1076 get_point (name, statp);
1079 /* Show all mounted file systems, except perhaps those that are of
1080 an unselected type or are empty. */
1083 get_all_entries (void)
1085 struct mount_entry *me;
1087 for (me = mount_list; me; me = me->me_next)
1088 get_dev (me->me_devname, me->me_mountdir, NULL, me->me_type,
1089 me->me_dummy, me->me_remote, NULL, true);
1092 /* Add FSTYPE to the list of file system types to display. */
1095 add_fs_type (const char *fstype)
1097 struct fs_type_list *fsp;
1099 fsp = xmalloc (sizeof *fsp);
1100 fsp->fs_name = (char *) fstype;
1101 fsp->fs_next = fs_select_list;
1102 fs_select_list = fsp;
1105 /* Add FSTYPE to the list of file system types to be omitted. */
1108 add_excluded_fs_type (const char *fstype)
1110 struct fs_type_list *fsp;
1112 fsp = xmalloc (sizeof *fsp);
1113 fsp->fs_name = (char *) fstype;
1114 fsp->fs_next = fs_exclude_list;
1115 fs_exclude_list = fsp;
1121 if (status != EXIT_SUCCESS)
1125 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name);
1127 Show information about the file system on which each FILE resides,\n\
1128 or all file systems by default.\n\
1132 Mandatory arguments to long options are mandatory for short options too.\n\
1135 -a, --all include dummy file systems\n\
1136 -B, --block-size=SIZE scale sizes by SIZE before printing them. E.g.,\n\
1137 '-BM' prints sizes in units of 1,048,576 bytes.\n\
1138 See SIZE format below.\n\
1139 --total produce a grand total\n\
1140 -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\
1142 -H, --si likewise, but use powers of 1000 not 1024\n\
1145 -i, --inodes list inode information instead of block usage\n\
1146 -k like --block-size=1K\n\
1147 -l, --local limit listing to local file systems\n\
1148 --no-sync do not invoke sync before getting usage info (default)\
1152 --output[=FIELD_LIST] use the output format defined by FIELD_LIST,\n\
1153 or print all fields if FIELD_LIST is omitted.\n\
1154 -P, --portability use the POSIX output format\n\
1155 --sync invoke sync before getting usage info\n\
1156 -t, --type=TYPE limit listing to file systems of type TYPE\n\
1157 -T, --print-type print file system type\n\
1158 -x, --exclude-type=TYPE limit listing to file systems not of type TYPE\n\
1161 fputs (HELP_OPTION_DESCRIPTION, stdout);
1162 fputs (VERSION_OPTION_DESCRIPTION, stdout);
1163 emit_blocksize_note ("DF");
1166 FIELD_LIST is a comma-separated list of columns to be included. Valid\n\
1167 field names are: 'source', 'fstype', 'itotal', 'iused', 'iavail', 'ipcent',\n\
1168 'size', 'used', 'avail', 'pcent' and 'target' (see info page).\n\
1170 emit_ancillary_info ();
1176 main (int argc, char **argv)
1178 struct stat *stats IF_LINT ( = 0);
1180 initialize_main (&argc, &argv);
1181 set_program_name (argv[0]);
1182 setlocale (LC_ALL, "");
1183 bindtextdomain (PACKAGE, LOCALEDIR);
1184 textdomain (PACKAGE);
1186 atexit (close_stdout);
1188 fs_select_list = NULL;
1189 fs_exclude_list = NULL;
1190 show_all_fs = false;
1191 show_listed_fs = false;
1192 human_output_opts = -1;
1194 file_systems_processed = false;
1195 exit_status = EXIT_SUCCESS;
1196 print_grand_total = false;
1197 grand_fsu.fsu_blocksize = 1;
1199 /* If true, use the POSIX output format. */
1200 bool posix_format = false;
1202 const char *msg_mut_excl = _("options %s and %s are mutually exclusive");
1207 int c = getopt_long (argc, argv, "aB:iF:hHklmPTt:vx:", long_options,
1219 enum strtol_error e = human_options (optarg, &human_output_opts,
1220 &output_block_size);
1221 if (e != LONGINT_OK)
1222 xstrtol_fatal (e, oi, c, long_options, optarg);
1226 if (header_mode == OUTPUT_MODE)
1228 error (0, 0, msg_mut_excl, "-i", "--output");
1229 usage (EXIT_FAILURE);
1231 header_mode = INODES_MODE;
1234 human_output_opts = human_autoscale | human_SI | human_base_1024;
1235 output_block_size = 1;
1238 human_output_opts = human_autoscale | human_SI;
1239 output_block_size = 1;
1242 human_output_opts = 0;
1243 output_block_size = 1024;
1246 show_local_fs = true;
1248 case MEGABYTES_OPTION:
1249 /* Distinguish between the long and the short option.
1250 As we want to remove the long option soon,
1251 give a warning when the long form is used. */
1252 error (0, 0, "%s%s", _("warning: "),
1253 _("long option '--megabytes' is deprecated"
1254 " and will soon be removed"));
1255 case 'm': /* obsolescent, exists for BSD compatibility */
1256 human_output_opts = 0;
1257 output_block_size = 1024 * 1024;
1260 if (header_mode == OUTPUT_MODE)
1262 error (0, 0, msg_mut_excl, "-T", "--output");
1263 usage (EXIT_FAILURE);
1268 if (header_mode == OUTPUT_MODE)
1270 error (0, 0, msg_mut_excl, "-P", "--output");
1271 usage (EXIT_FAILURE);
1273 posix_format = true;
1276 require_sync = true;
1278 case NO_SYNC_OPTION:
1279 require_sync = false;
1283 /* Accept -F as a synonym for -t for compatibility with Solaris. */
1285 add_fs_type (optarg);
1288 case 'v': /* For SysV compatibility. */
1292 add_excluded_fs_type (optarg);
1296 if (header_mode == INODES_MODE)
1298 error (0, 0, msg_mut_excl, "-i", "--output");
1299 usage (EXIT_FAILURE);
1301 if (posix_format && header_mode == DEFAULT_MODE)
1303 error (0, 0, msg_mut_excl, "-P", "--output");
1304 usage (EXIT_FAILURE);
1308 error (0, 0, msg_mut_excl, "-T", "--output");
1309 usage (EXIT_FAILURE);
1311 header_mode = OUTPUT_MODE;
1313 decode_output_arg (optarg);
1317 print_grand_total = true;
1320 case_GETOPT_HELP_CHAR;
1321 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1324 usage (EXIT_FAILURE);
1328 if (human_output_opts == -1)
1332 human_output_opts = 0;
1333 output_block_size = (getenv ("POSIXLY_CORRECT") ? 512 : 1024);
1336 human_options (getenv ("DF_BLOCK_SIZE"),
1337 &human_output_opts, &output_block_size);
1340 if (header_mode == INODES_MODE || header_mode == OUTPUT_MODE)
1342 else if (human_output_opts & human_autoscale)
1343 header_mode = HUMAN_MODE;
1344 else if (posix_format)
1345 header_mode = POSIX_MODE;
1347 /* Fail if the same file system type was both selected and excluded. */
1350 struct fs_type_list *fs_incl;
1351 for (fs_incl = fs_select_list; fs_incl; fs_incl = fs_incl->fs_next)
1353 struct fs_type_list *fs_excl;
1354 for (fs_excl = fs_exclude_list; fs_excl; fs_excl = fs_excl->fs_next)
1356 if (STREQ (fs_incl->fs_name, fs_excl->fs_name))
1359 _("file system type %s both selected and excluded"),
1360 quote (fs_incl->fs_name));
1367 exit (EXIT_FAILURE);
1374 /* Open each of the given entries to make sure any corresponding
1375 partition is automounted. This must be done before reading the
1376 file system table. */
1377 stats = xnmalloc (argc - optind, sizeof *stats);
1378 for (i = optind; i < argc; ++i)
1380 /* Prefer to open with O_NOCTTY and use fstat, but fall back
1381 on using "stat", in case the file is unreadable. */
1382 int fd = open (argv[i], O_RDONLY | O_NOCTTY);
1383 if ((fd < 0 || fstat (fd, &stats[i - optind]))
1384 && stat (argv[i], &stats[i - optind]))
1386 error (0, errno, "%s", quote (argv[i]));
1387 exit_status = EXIT_FAILURE;
1396 read_file_system_list ((fs_select_list != NULL
1397 || fs_exclude_list != NULL
1399 || field_data[FSTYPE_FIELD].used
1402 if (mount_list == NULL)
1404 /* Couldn't read the table of mounted file systems.
1405 Fail if df was invoked with no file name arguments,
1406 or when either of -a, -l, -t or -x is used with file name
1407 arguments. Otherwise, merely give a warning and proceed. */
1409 if ( ! (optind < argc)
1412 || fs_select_list != NULL
1413 || fs_exclude_list != NULL))
1415 status = EXIT_FAILURE;
1417 const char *warning = (status == 0 ? _("Warning: ") : "");
1418 error (status, errno, "%s%s", warning,
1419 _("cannot read table of mounted file systems"));
1432 /* Display explicitly requested empty file systems. */
1433 show_listed_fs = true;
1435 for (i = optind; i < argc; ++i)
1437 get_entry (argv[i], &stats[i - optind]);
1442 if (file_systems_processed)
1444 if (print_grand_total)
1446 (field_data[SOURCE_FIELD].used ? "-" : "total"),
1447 NULL, NULL, false, false, &grand_fsu, false);
1453 /* Print the "no FS processed" diagnostic only if there was no preceding
1454 diagnostic, e.g., if all have been excluded. */
1455 if (exit_status == EXIT_SUCCESS)
1456 error (EXIT_FAILURE, 0, _("no file systems processed"));
1459 IF_LINT (free (columns));