1 /* df - summarize free disk space
2 Copyright (C) 1991, 1995 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 2, or (at your option)
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, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 /* Usage: df [-aikPT] [-t fstype] [-x fstype] [--all] [--inodes] [--print-type]
19 [--type fstype] [--exclude-type fstype] [--kilobytes] [--portability]
23 -a, --all List all filesystems, even zero-size ones.
24 -i, --inodes List inode usage information instead of block usage.
25 -k, --kilobytes Print sizes in 1K blocks instead of 512-byte blocks.
26 -P, --portability Use the POSIX output format (one line per filesystem).
27 -T, --print-type Print filesystem type.
28 -t, --type fstype Limit the listing to filesystems of type `fstype'.
29 -x, --exclude-type=fstype
30 Limit the listing to filesystems not of type `fstype'.
31 Multiple -t and/or -x options can be given.
32 By default, all filesystem types are listed.
34 Written by David MacKenzie <djm@gnu.ai.mit.edu> */
38 #include <sys/types.h>
41 #include "mountlist.h"
50 static int selected_fstype ();
51 static int excluded_fstype ();
52 static void add_excluded_fs_type ();
53 static void add_fs_type ();
54 static void print_header ();
55 static void show_entry ();
56 static void show_all_entries ();
57 static void show_dev ();
58 static void show_disk ();
59 static void show_point ();
62 /* Name this program was run with. */
65 /* If nonzero, show inode information. */
66 static int inode_format;
68 /* If nonzero, show even filesystems with zero size or
69 uninteresting types. */
70 static int show_all_fs;
72 /* If nonzero, output data for each filesystem corresponding to a
73 command line argument -- even if it's a dummy (automounter) entry. */
74 static int show_listed_fs;
76 /* If nonzero, use 1K blocks instead of 512-byte blocks. */
77 static int kilobyte_blocks;
79 /* If nonzero, use the POSIX output format. */
80 static int posix_format;
82 /* If nonzero, invoke the `sync' system call before getting any usage data.
83 Using this option can make df very slow, especially with many or very
84 busy disks. Default to non-zero because the sync call does make a
85 difference on some systems -- SunOs4.1.3, for one. I have been assured
86 that it is *not* necessary on Linux, so there should be a way to
87 configure this. FIXME. */
88 static int require_sync = 1;
90 /* Nonzero if errors have occurred. */
91 static int exit_status;
93 /* A filesystem type to display. */
98 struct fs_type_list *fs_next;
101 /* Linked list of filesystem types to display.
102 If `fs_select_list' is NULL, list all types.
103 This table is generated dynamically from command-line options,
104 rather than hardcoding into the program what it thinks are the
105 valid filesystem types; let the user specify any filesystem type
106 they want to, and if there are any filesystems of that type, they
109 Some filesystem types:
110 4.2 4.3 ufs nfs swap ignore io vm efs dbg */
112 static struct fs_type_list *fs_select_list;
114 /* Linked list of filesystem types to omit.
115 If the list is empty, don't exclude any types. */
117 static struct fs_type_list *fs_exclude_list;
119 /* Linked list of mounted filesystems. */
120 static struct mount_entry *mount_list;
122 /* If non-zero, display usage information and exit. */
123 static int show_help;
125 /* If non-zero, print the version on standard output and exit. */
126 static int show_version;
128 /* If non-zero, print filesystem type as well. */
129 static int print_type;
131 static struct option const long_options[] =
133 {"all", no_argument, &show_all_fs, 1},
134 {"inodes", no_argument, &inode_format, 1},
135 {"kilobytes", no_argument, &kilobyte_blocks, 1},
136 {"portability", no_argument, &posix_format, 1},
137 {"print-type", no_argument, &print_type, 1},
138 {"sync", no_argument, 0, 129},
139 {"no-sync", no_argument, 0, 130},
140 {"type", required_argument, 0, 't'},
141 {"exclude-type", required_argument, 0, 'x'},
142 {"help", no_argument, &show_help, 1},
143 {"version", no_argument, &show_version, 1},
155 program_name = argv[0];
156 fs_select_list = NULL;
157 fs_exclude_list = NULL;
161 kilobyte_blocks = getenv ("POSIXLY_CORRECT") == 0;
166 while ((i = getopt_long (argc, argv, "aikPTt:vx:", long_options, (int *) 0))
171 case 0: /* Long option. */
195 add_fs_type (optarg);
197 case 'v': /* For SysV compatibility. */
200 add_excluded_fs_type (optarg);
209 printf ("%s\n", version_string);
219 /* Suppress `used before initialized' warning. */
225 /* stat all the given entries to make sure they get automounted,
226 if necessary, before reading the filesystem table. */
227 stats = (struct stat *)
228 xmalloc ((argc - optind) * sizeof (struct stat));
229 for (i = optind; i < argc; ++i)
230 if (stat (argv[i], &stats[i - optind]))
232 error (0, errno, "%s", argv[i]);
239 read_filesystem_list ((fs_select_list != NULL || fs_exclude_list != NULL),
242 if (mount_list == NULL)
243 error (1, errno, "cannot read table of mounted filesystems");
253 /* Display explicitly requested empty filesystems. */
256 for (i = optind; i < argc; ++i)
258 show_entry (argv[i], &stats[i - optind]);
267 printf ("Filesystem ");
275 printf (" Inodes IUsed IFree %%IUsed");
277 printf (" %s Used Available Capacity",
278 kilobyte_blocks ? "1024-blocks" : " 512-blocks");
279 printf (" Mounted on\n");
282 /* Show all mounted filesystems, except perhaps those that are of
283 an unselected type or are empty. */
288 struct mount_entry *me;
290 for (me = mount_list; me; me = me->me_next)
291 show_dev (me->me_devname, me->me_mountdir, me->me_type);
294 /* Determine what kind of node PATH is and show the disk usage
295 for it. STATP is the results of `stat' on PATH. */
298 show_entry (path, statp)
302 if (S_ISBLK (statp->st_mode) || S_ISCHR (statp->st_mode))
305 show_point (path, statp);
308 /* Identify the directory, if any, that device
309 DISK is mounted on, and show its disk usage. */
315 struct mount_entry *me;
317 for (me = mount_list; me; me = me->me_next)
318 if (!strcmp (disk, me->me_devname))
320 show_dev (me->me_devname, me->me_mountdir, me->me_type);
323 /* No filesystem is mounted on DISK. */
324 show_dev (disk, (char *) NULL, (char *) NULL);
327 /* Figure out which device file or directory POINT is mounted on
328 and show its disk usage.
329 STATP is the results of `stat' on POINT. */
332 show_point (point, statp)
336 struct stat disk_stats;
337 struct mount_entry *me;
339 for (me = mount_list; me; me = me->me_next)
341 if (me->me_dev == (dev_t) -1)
343 if (stat (me->me_mountdir, &disk_stats) == 0)
344 me->me_dev = disk_stats.st_dev;
347 error (0, errno, "%s", me->me_mountdir);
349 me->me_dev = -2; /* So we won't try and fail repeatedly. */
353 if (statp->st_dev == me->me_dev)
355 show_dev (me->me_devname, me->me_mountdir, me->me_type);
359 error (0, 0, "cannot find mount point for %s", point);
363 /* Display a space listing for the disk device with absolute path DISK.
364 If MOUNT_POINT is non-NULL, it is the path of the root of the
366 If FSTYPE is non-NULL, it is the type of the filesystem on DISK. */
369 show_dev (disk, mount_point, fstype)
376 long blocks_percent_used;
378 long inodes_percent_used;
381 if (!selected_fstype (fstype) || excluded_fstype (fstype))
384 /* If MOUNT_POINT is NULL, then the filesystem is not mounted, and this
385 program reports on the filesystem that the special file is on.
386 It would be better to report on the unmounted filesystem,
387 but statfs doesn't do that on most systems. */
388 stat_file = mount_point ? mount_point : disk;
390 if (get_fs_usage (stat_file, disk, &fsu))
392 error (0, errno, "%s", stat_file);
404 if (fsu.fsu_blocks == 0)
406 if (!show_all_fs && !show_listed_fs)
408 blocks_used = fsu.fsu_bavail = blocks_percent_used = 0;
412 blocks_used = fsu.fsu_blocks - fsu.fsu_bfree;
413 blocks_percent_used = (long)
414 (blocks_used * 100.0 / (blocks_used + fsu.fsu_bavail) + 0.5);
417 if (fsu.fsu_files == 0)
419 inodes_used = fsu.fsu_ffree = inodes_percent_used = 0;
423 inodes_used = fsu.fsu_files - fsu.fsu_ffree;
424 inodes_percent_used = (long)
425 (inodes_used * 100.0 / fsu.fsu_files + 0.5);
428 printf ((print_type ? "%-13s" : "%-20s"), disk);
429 if (strlen (disk) > (print_type ? 13 : 20) && !posix_format)
430 printf ((print_type ? "\n%13s" : "\n%20s"), "");
433 printf (" %-5s ", fstype);
436 printf (" %7ld %7ld %7ld %5ld%%",
437 fsu.fsu_files, inodes_used, fsu.fsu_ffree, inodes_percent_used);
439 printf (" %7ld %7ld %7ld %5ld%% ",
440 fsu.fsu_blocks, blocks_used, fsu.fsu_bavail, blocks_percent_used);
443 printf (" %s", mount_point);
447 /* Add FSTYPE to the list of filesystem types to display. */
453 struct fs_type_list *fsp;
455 fsp = (struct fs_type_list *) xmalloc (sizeof (struct fs_type_list));
456 fsp->fs_name = fstype;
457 fsp->fs_next = fs_select_list;
458 fs_select_list = fsp;
461 /* Add FSTYPE to the list of filesystem types to be omitted. */
464 add_excluded_fs_type (fstype)
467 struct fs_type_list *fsp;
469 fsp = (struct fs_type_list *) xmalloc (sizeof (struct fs_type_list));
470 fsp->fs_name = fstype;
471 fsp->fs_next = fs_exclude_list;
472 fs_exclude_list = fsp;
475 /* If FSTYPE is a type of filesystem that should be listed,
476 return nonzero, else zero. */
479 selected_fstype (fstype)
482 struct fs_type_list *fsp;
484 if (fs_select_list == NULL || fstype == NULL)
486 for (fsp = fs_select_list; fsp; fsp = fsp->fs_next)
487 if (!strcmp (fstype, fsp->fs_name))
493 /* If FSTYPE is a type of filesystem that should be omitted,
494 return nonzero, else zero. */
497 excluded_fstype (fstype)
500 struct fs_type_list *fsp;
502 if (fs_exclude_list == NULL || fstype == NULL)
504 for (fsp = fs_exclude_list; fsp; fsp = fsp->fs_next)
505 if (!strcmp (fstype, fsp->fs_name))
515 fprintf (stderr, "Try `%s --help' for more information.\n",
519 printf ("Usage: %s [OPTION]... [FILE]...\n", program_name);
522 -a, --all include filesystems having 0 blocks\n\
523 -i, --inodes list inode information instead of block usage\n\
524 -k, --kilobytes use 1024 blocks, not 512 despite POSIXLY_CORRECT\n\
525 --sync invoke sync before getting usage info (default)\n\
526 --no-sync do not invoke sync before getting usage info\n\
527 -t, --type=TYPE limit the listing to TYPE filesystems type\n\
528 -x, --exclude-type=TYPE limit the listing to not TYPE filesystems type\n\
530 -P, --portability use the POSIX output format\n\
531 -T, --print-type print filesystem type\n\
532 --help display this help and exit\n\
533 --version output version information and exit\n\
535 If no FILEs are given, list all currently mounted filesystems.\n");