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
__P ((char *fstype
));
51 static int excluded_fstype
__P ((char *fstype
));
52 static void add_excluded_fs_type
__P ((char *fstype
));
53 static void add_fs_type
__P ((char *fstype
));
54 static void print_header
__P ((void));
55 static void show_entry
__P ((char *path
, struct stat
*statp
));
56 static void show_all_entries
__P ((void));
57 static void show_dev
__P ((char *disk
, char *mount_point
, char *fstype
));
58 static void show_disk
__P ((char *disk
));
59 static void show_point
__P ((char *point
, struct stat
*statp
));
60 static void usage
__P ((int status
));
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 nonzero 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 nonzero, display usage information and exit. */
123 static int show_help
;
125 /* If nonzero, print the version on standard output and exit. */
126 static int show_version
;
128 /* If nonzero, 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},
148 main (int argc
, char **argv
)
153 program_name
= argv
[0];
154 fs_select_list
= NULL
;
155 fs_exclude_list
= NULL
;
159 kilobyte_blocks
= getenv ("POSIXLY_CORRECT") == 0;
164 while ((i
= getopt_long (argc
, argv
, "aikPTt:vx:", long_options
, (int *) 0))
169 case 0: /* Long option. */
193 add_fs_type (optarg
);
195 case 'v': /* For SysV compatibility. */
198 add_excluded_fs_type (optarg
);
207 printf ("df - %s\n", version_string
);
214 /* Fail if the same file system type was both selected and excluded. */
217 struct fs_type_list
*i
;
218 for (i
= fs_select_list
; i
; i
= i
->fs_next
)
220 struct fs_type_list
*j
;
221 for (j
= fs_exclude_list
; j
; j
= j
->fs_next
)
223 if (strcmp (i
->fs_name
, j
->fs_name
) == 0)
226 _("file system type `%s' both selected and excluded"),
240 /* Suppress `used before initialized' warning. */
246 /* stat all the given entries to make sure they get automounted,
247 if necessary, before reading the filesystem table. */
248 stats
= (struct stat
*)
249 xmalloc ((argc
- optind
) * sizeof (struct stat
));
250 for (i
= optind
; i
< argc
; ++i
)
251 if (stat (argv
[i
], &stats
[i
- optind
]))
253 error (0, errno
, "%s", argv
[i
]);
260 read_filesystem_list ((fs_select_list
!= NULL
|| fs_exclude_list
!= NULL
),
263 if (mount_list
== NULL
)
264 error (1, errno
, _("cannot read table of mounted filesystems"));
274 /* Display explicitly requested empty filesystems. */
277 for (i
= optind
; i
< argc
; ++i
)
279 show_entry (argv
[i
], &stats
[i
- optind
]);
288 printf ("Filesystem ");
296 printf (" Inodes IUsed IFree %%IUsed");
298 printf (" %s Used Available Capacity",
299 kilobyte_blocks
? "1024-blocks" : " 512-blocks");
300 printf (" Mounted on\n");
303 /* Show all mounted filesystems, except perhaps those that are of
304 an unselected type or are empty. */
307 show_all_entries (void)
309 struct mount_entry
*me
;
311 for (me
= mount_list
; me
; me
= me
->me_next
)
312 show_dev (me
->me_devname
, me
->me_mountdir
, me
->me_type
);
315 /* Determine what kind of node PATH is and show the disk usage
316 for it. STATP is the results of `stat' on PATH. */
319 show_entry (char *path
, struct stat
*statp
)
321 if (S_ISBLK (statp
->st_mode
) || S_ISCHR (statp
->st_mode
))
324 show_point (path
, statp
);
327 /* Identify the directory, if any, that device
328 DISK is mounted on, and show its disk usage. */
331 show_disk (char *disk
)
333 struct mount_entry
*me
;
335 for (me
= mount_list
; me
; me
= me
->me_next
)
336 if (!strcmp (disk
, me
->me_devname
))
338 show_dev (me
->me_devname
, me
->me_mountdir
, me
->me_type
);
341 /* No filesystem is mounted on DISK. */
342 show_dev (disk
, (char *) NULL
, (char *) NULL
);
345 /* Figure out which device file or directory POINT is mounted on
346 and show its disk usage.
347 STATP is the results of `stat' on POINT. */
350 show_point (char *point
, struct stat
*statp
)
352 struct stat disk_stats
;
353 struct mount_entry
*me
;
355 for (me
= mount_list
; me
; me
= me
->me_next
)
357 if (me
->me_dev
== (dev_t
) -1)
359 if (stat (me
->me_mountdir
, &disk_stats
) == 0)
360 me
->me_dev
= disk_stats
.st_dev
;
363 error (0, errno
, "%s", me
->me_mountdir
);
365 /* So we won't try and fail repeatedly. */
366 me
->me_dev
= (dev_t
) -2;
370 if (statp
->st_dev
== me
->me_dev
)
372 /* Skip bogus mtab entries. */
373 if (stat (me
->me_mountdir
, &disk_stats
) != 0 ||
374 disk_stats
.st_dev
!= me
->me_dev
)
376 show_dev (me
->me_devname
, me
->me_mountdir
, me
->me_type
);
380 error (0, 0, _("cannot find mount point for %s"), point
);
384 /* Display a space listing for the disk device with absolute path DISK.
385 If MOUNT_POINT is non-NULL, it is the path of the root of the
387 If FSTYPE is non-NULL, it is the type of the filesystem on DISK. */
390 show_dev (char *disk
, char *mount_point
, char *fstype
)
394 long blocks_percent_used
;
396 long inodes_percent_used
;
399 if (!selected_fstype (fstype
) || excluded_fstype (fstype
))
402 /* If MOUNT_POINT is NULL, then the filesystem is not mounted, and this
403 program reports on the filesystem that the special file is on.
404 It would be better to report on the unmounted filesystem,
405 but statfs doesn't do that on most systems. */
406 stat_file
= mount_point
? mount_point
: disk
;
408 if (get_fs_usage (stat_file
, disk
, &fsu
))
410 error (0, errno
, "%s", stat_file
);
422 if (fsu
.fsu_blocks
== 0)
424 if (!show_all_fs
&& !show_listed_fs
)
426 blocks_used
= fsu
.fsu_bavail
= blocks_percent_used
= 0;
430 blocks_used
= fsu
.fsu_blocks
- fsu
.fsu_bfree
;
431 blocks_percent_used
= (long)
432 (blocks_used
* 100.0 / (blocks_used
+ fsu
.fsu_bavail
) + 0.5);
435 if (fsu
.fsu_files
== 0)
437 inodes_used
= fsu
.fsu_ffree
= inodes_percent_used
= 0;
441 inodes_used
= fsu
.fsu_files
- fsu
.fsu_ffree
;
442 inodes_percent_used
= (long)
443 (inodes_used
* 100.0 / fsu
.fsu_files
+ 0.5);
446 printf ((print_type
? "%-13s" : "%-20s"), disk
);
447 if (strlen (disk
) > (print_type
? 13 : 20) && !posix_format
)
448 printf ((print_type
? "\n%13s" : "\n%20s"), "");
451 printf (" %-5s ", fstype
);
454 printf (" %7ld %7ld %7ld %5ld%%",
455 fsu
.fsu_files
, inodes_used
, fsu
.fsu_ffree
, inodes_percent_used
);
457 printf (" %7ld %7ld %7ld %5ld%% ",
458 fsu
.fsu_blocks
, blocks_used
, fsu
.fsu_bavail
, blocks_percent_used
);
461 printf (" %s", mount_point
);
465 /* Add FSTYPE to the list of filesystem types to display. */
468 add_fs_type (char *fstype
)
470 struct fs_type_list
*fsp
;
472 fsp
= (struct fs_type_list
*) xmalloc (sizeof (struct fs_type_list
));
473 fsp
->fs_name
= fstype
;
474 fsp
->fs_next
= fs_select_list
;
475 fs_select_list
= fsp
;
478 /* Add FSTYPE to the list of filesystem types to be omitted. */
481 add_excluded_fs_type (char *fstype
)
483 struct fs_type_list
*fsp
;
485 fsp
= (struct fs_type_list
*) xmalloc (sizeof (struct fs_type_list
));
486 fsp
->fs_name
= fstype
;
487 fsp
->fs_next
= fs_exclude_list
;
488 fs_exclude_list
= fsp
;
491 /* If FSTYPE is a type of filesystem that should be listed,
492 return nonzero, else zero. */
495 selected_fstype (char *fstype
)
497 struct fs_type_list
*fsp
;
499 if (fs_select_list
== NULL
|| fstype
== NULL
)
501 for (fsp
= fs_select_list
; fsp
; fsp
= fsp
->fs_next
)
502 if (!strcmp (fstype
, fsp
->fs_name
))
508 /* If FSTYPE is a type of filesystem that should be omitted,
509 return nonzero, else zero. */
512 excluded_fstype (char *fstype
)
514 struct fs_type_list
*fsp
;
516 if (fs_exclude_list
== NULL
|| fstype
== NULL
)
518 for (fsp
= fs_exclude_list
; fsp
; fsp
= fsp
->fs_next
)
519 if (!strcmp (fstype
, fsp
->fs_name
))
528 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
532 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name
);
534 Show information about the filesystem on which each FILE resides,\n\
535 or all filesystems by default.\n\
537 -a, --all include filesystems having 0 blocks\n\
538 -i, --inodes list inode information instead of block usage\n\
539 -k, --kilobytes use 1024 blocks, not 512 despite POSIXLY_CORRECT\n\
540 --sync invoke sync before getting usage info (default)\n\
541 --no-sync do not invoke sync before getting usage info\n\
542 -t, --type=TYPE limit listing to filesystems of type TYPE\n\
543 -x, --exclude-type=TYPE limit listing to filesystems not of type TYPE\n\
545 -P, --portability use the POSIX output format\n\
546 -T, --print-type print filesystem type\n\
547 --help display this help and exit\n\
548 --version output version information and exit\n"));