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"
45 #include "safe-stat.h"
51 static int selected_fstype ();
52 static int excluded_fstype ();
53 static void add_excluded_fs_type ();
54 static void add_fs_type ();
55 static void print_header ();
56 static void show_entry ();
57 static void show_all_entries ();
58 static void show_dev ();
59 static void show_disk ();
60 static void show_point ();
63 /* Name this program was run with. */
66 /* If nonzero, show inode information. */
67 static int inode_format;
69 /* If nonzero, show even filesystems with zero size or
70 uninteresting types. */
71 static int show_all_fs;
73 /* If nonzero, output data for each filesystem corresponding to a
74 command line argument -- even if it's a dummy (automounter) entry. */
75 static int show_listed_fs;
77 /* If nonzero, use 1K blocks instead of 512-byte blocks. */
78 static int kilobyte_blocks;
80 /* If nonzero, use the POSIX output format. */
81 static int posix_format;
83 /* If nonzero, invoke the `sync' system call before getting any usage data.
84 Using this option can make df very slow, especially with many or very
85 busy disks. Default to non-zero because the sync call does make a
86 difference on some systems -- SunOs4.1.3, for one. I have been assured
87 that it is *not* necessary on Linux, so there should be a way to
88 configure this. FIXME. */
89 static int require_sync = 1;
91 /* Nonzero if errors have occurred. */
92 static int exit_status;
94 /* A filesystem type to display. */
99 struct fs_type_list *fs_next;
102 /* Linked list of filesystem types to display.
103 If `fs_select_list' is NULL, list all types.
104 This table is generated dynamically from command-line options,
105 rather than hardcoding into the program what it thinks are the
106 valid filesystem types; let the user specify any filesystem type
107 they want to, and if there are any filesystems of that type, they
110 Some filesystem types:
111 4.2 4.3 ufs nfs swap ignore io vm efs dbg */
113 static struct fs_type_list *fs_select_list;
115 /* Linked list of filesystem types to omit.
116 If the list is empty, don't exclude any types. */
118 static struct fs_type_list *fs_exclude_list;
120 /* Linked list of mounted filesystems. */
121 static struct mount_entry *mount_list;
123 /* If non-zero, display usage information and exit. */
124 static int show_help;
126 /* If non-zero, print the version on standard output and exit. */
127 static int show_version;
129 /* If non-zero, print filesystem type as well. */
130 static int print_type;
132 static struct option const long_options[] =
134 {"all", no_argument, &show_all_fs, 1},
135 {"inodes", no_argument, &inode_format, 1},
136 {"kilobytes", no_argument, &kilobyte_blocks, 1},
137 {"portability", no_argument, &posix_format, 1},
138 {"print-type", no_argument, &print_type, 1},
139 {"sync", no_argument, 0, 129},
140 {"no-sync", no_argument, 0, 130},
141 {"type", required_argument, 0, 't'},
142 {"exclude-type", required_argument, 0, 'x'},
143 {"help", no_argument, &show_help, 1},
144 {"version", no_argument, &show_version, 1},
156 program_name = argv[0];
157 fs_select_list = NULL;
158 fs_exclude_list = NULL;
162 kilobyte_blocks = getenv ("POSIXLY_CORRECT") == 0;
167 while ((i = getopt_long (argc, argv, "aikPTt:vx:", long_options, (int *) 0))
172 case 0: /* Long option. */
196 add_fs_type (optarg);
198 case 'v': /* For SysV compatibility. */
201 add_excluded_fs_type (optarg);
210 printf ("%s\n", version_string);
220 /* Suppress `used before initialized' warning. */
226 /* stat all the given entries to make sure they get automounted,
227 if necessary, before reading the filesystem table. */
228 stats = (struct stat *)
229 xmalloc ((argc - optind) * sizeof (struct stat));
230 for (i = optind; i < argc; ++i)
231 if (safe_stat (argv[i], &stats[i - optind]))
233 error (0, errno, "%s", argv[i]);
240 read_filesystem_list ((fs_select_list != NULL || fs_exclude_list != NULL),
243 if (mount_list == NULL)
244 error (1, errno, "cannot read table of mounted filesystems");
254 /* Display explicitly requested empty filesystems. */
257 for (i = optind; i < argc; ++i)
259 show_entry (argv[i], &stats[i - optind]);
268 printf ("Filesystem ");
276 printf (" Inodes IUsed IFree %%IUsed");
278 printf (" %s Used Available Capacity",
279 kilobyte_blocks ? "1024-blocks" : " 512-blocks");
280 printf (" Mounted on\n");
283 /* Show all mounted filesystems, except perhaps those that are of
284 an unselected type or are empty. */
289 struct mount_entry *me;
291 for (me = mount_list; me; me = me->me_next)
292 show_dev (me->me_devname, me->me_mountdir, me->me_type);
295 /* Determine what kind of node PATH is and show the disk usage
296 for it. STATP is the results of `stat' on PATH. */
299 show_entry (path, statp)
303 if (S_ISBLK (statp->st_mode) || S_ISCHR (statp->st_mode))
306 show_point (path, statp);
309 /* Identify the directory, if any, that device
310 DISK is mounted on, and show its disk usage. */
316 struct mount_entry *me;
318 for (me = mount_list; me; me = me->me_next)
319 if (!strcmp (disk, me->me_devname))
321 show_dev (me->me_devname, me->me_mountdir, me->me_type);
324 /* No filesystem is mounted on DISK. */
325 show_dev (disk, (char *) NULL, (char *) NULL);
328 /* Figure out which device file or directory POINT is mounted on
329 and show its disk usage.
330 STATP is the results of `stat' on POINT. */
333 show_point (point, statp)
337 struct stat disk_stats;
338 struct mount_entry *me;
340 for (me = mount_list; me; me = me->me_next)
342 if (me->me_dev == (dev_t) -1)
344 if (safe_stat (me->me_mountdir, &disk_stats) == 0)
345 me->me_dev = disk_stats.st_dev;
348 error (0, errno, "%s", me->me_mountdir);
350 me->me_dev = -2; /* So we won't try and fail repeatedly. */
354 if (statp->st_dev == me->me_dev)
356 show_dev (me->me_devname, me->me_mountdir, me->me_type);
360 error (0, 0, "cannot find mount point for %s", point);
364 /* Display a space listing for the disk device with absolute path DISK.
365 If MOUNT_POINT is non-NULL, it is the path of the root of the
367 If FSTYPE is non-NULL, it is the type of the filesystem on DISK. */
370 show_dev (disk, mount_point, fstype)
377 long blocks_percent_used;
379 long inodes_percent_used;
382 if (!selected_fstype (fstype) || excluded_fstype (fstype))
385 /* If MOUNT_POINT is NULL, then the filesystem is not mounted, and this
386 program reports on the filesystem that the special file is on.
387 It would be better to report on the unmounted filesystem,
388 but statfs doesn't do that on most systems. */
389 stat_file = mount_point ? mount_point : disk;
391 if (get_fs_usage (stat_file, disk, &fsu))
393 error (0, errno, "%s", stat_file);
405 if (fsu.fsu_blocks == 0)
407 if (!show_all_fs && !show_listed_fs)
409 blocks_used = fsu.fsu_bavail = blocks_percent_used = 0;
413 blocks_used = fsu.fsu_blocks - fsu.fsu_bfree;
414 blocks_percent_used = (long)
415 (blocks_used * 100.0 / (blocks_used + fsu.fsu_bavail) + 0.5);
418 if (fsu.fsu_files == 0)
420 inodes_used = fsu.fsu_ffree = inodes_percent_used = 0;
424 inodes_used = fsu.fsu_files - fsu.fsu_ffree;
425 inodes_percent_used = (long)
426 (inodes_used * 100.0 / fsu.fsu_files + 0.5);
429 printf ((print_type ? "%-13s" : "%-20s"), disk);
430 if (strlen (disk) > (print_type ? 13 : 20) && !posix_format)
431 printf ((print_type ? "\n%13s" : "\n%20s"), "");
434 printf (" %-5s ", fstype);
437 printf (" %7ld %7ld %7ld %5ld%%",
438 fsu.fsu_files, inodes_used, fsu.fsu_ffree, inodes_percent_used);
440 printf (" %7ld %7ld %7ld %5ld%% ",
441 fsu.fsu_blocks, blocks_used, fsu.fsu_bavail, blocks_percent_used);
444 printf (" %s", mount_point);
448 /* Add FSTYPE to the list of filesystem types to display. */
454 struct fs_type_list *fsp;
456 fsp = (struct fs_type_list *) xmalloc (sizeof (struct fs_type_list));
457 fsp->fs_name = fstype;
458 fsp->fs_next = fs_select_list;
459 fs_select_list = fsp;
462 /* Add FSTYPE to the list of filesystem types to be omitted. */
465 add_excluded_fs_type (fstype)
468 struct fs_type_list *fsp;
470 fsp = (struct fs_type_list *) xmalloc (sizeof (struct fs_type_list));
471 fsp->fs_name = fstype;
472 fsp->fs_next = fs_exclude_list;
473 fs_exclude_list = fsp;
476 /* If FSTYPE is a type of filesystem that should be listed,
477 return nonzero, else zero. */
480 selected_fstype (fstype)
483 struct fs_type_list *fsp;
485 if (fs_select_list == NULL || fstype == NULL)
487 for (fsp = fs_select_list; fsp; fsp = fsp->fs_next)
488 if (!strcmp (fstype, fsp->fs_name))
494 /* If FSTYPE is a type of filesystem that should be omitted,
495 return nonzero, else zero. */
498 excluded_fstype (fstype)
501 struct fs_type_list *fsp;
503 if (fs_exclude_list == NULL || fstype == NULL)
505 for (fsp = fs_exclude_list; fsp; fsp = fsp->fs_next)
506 if (!strcmp (fstype, fsp->fs_name))
516 fprintf (stderr, "Try `%s --help' for more information.\n",
520 printf ("Usage: %s [OPTION]... [FILE]...\n", program_name);
523 -a, --all include filesystems having 0 blocks\n\
524 -i, --inodes list inode information instead of block usage\n\
525 -k, --kilobytes use 1024 blocks, not 512 despite POSIXLY_CORRECT\n\
526 --sync invoke sync before getting usage info (default)\n\
527 --no-sync do not invoke sync before getting usage info\n\
528 -t, --type=TYPE limit the listing to TYPE filesystems type\n\
529 -x, --exclude-type=TYPE limit the listing to not TYPE filesystems type\n\
531 -P, --portability use the POSIX output format\n\
532 -T, --print-type print filesystem type\n\
533 --help display this help and exit\n\
534 --version output version information and exit\n\
536 If no FILEs are given, list all currently mounted filesystems.\n");