1 /* df - summarize free disk space
2 Copyright (C) 91, 1995-2005 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 Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18 /* Written by David MacKenzie <djm@gnu.ai.mit.edu>.
19 --human-readable and --megabyte options added by lm@sgi.com.
20 --si and large file support added by eggert@twinsun.com. */
24 #include <sys/types.h>
29 #include "canonicalize.h"
35 #include "mountlist.h"
40 /* The official name of this program (e.g., no `g' prefix). */
41 #define PROGRAM_NAME "df"
44 "Torbjorn Granlund", "David MacKenzie", "Paul Eggert"
46 /* Name this program was run with. */
49 /* If true, show inode information. */
50 static bool inode_format
;
52 /* If true, show even file systems with zero size or
53 uninteresting types. */
54 static bool show_all_fs
;
56 /* If true, show only local file systems. */
57 static bool show_local_fs
;
59 /* If true, output data for each file system corresponding to a
60 command line argument -- even if it's a dummy (automounter) entry. */
61 static bool show_listed_fs
;
63 /* Human-readable options for output. */
64 static int human_output_opts
;
66 /* The units to use when printing sizes. */
67 static uintmax_t output_block_size
;
69 /* If true, use the POSIX output format. */
70 static bool posix_format
;
72 /* If true, invoke the `sync' system call before getting any usage data.
73 Using this option can make df very slow, especially with many or very
74 busy disks. Note that this may make a difference on some systems --
75 SunOS 4.1.3, for one. It is *not* necessary on Linux. */
76 static bool require_sync
;
78 /* Desired exit status. */
79 static int exit_status
;
81 /* A file system type to display. */
86 struct fs_type_list
*fs_next
;
89 /* Linked list of file system types to display.
90 If `fs_select_list' is NULL, list all types.
91 This table is generated dynamically from command-line options,
92 rather than hardcoding into the program what it thinks are the
93 valid file system types; let the user specify any file system type
94 they want to, and if there are any file systems of that type, they
97 Some file system types:
98 4.2 4.3 ufs nfs swap ignore io vm efs dbg */
100 static struct fs_type_list
*fs_select_list
;
102 /* Linked list of file system types to omit.
103 If the list is empty, don't exclude any types. */
105 static struct fs_type_list
*fs_exclude_list
;
107 /* Linked list of mounted file systems. */
108 static struct mount_entry
*mount_list
;
110 /* If true, print file system type as well. */
111 static bool print_type
;
113 /* For long options that have no equivalent short option, use a
114 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
117 SYNC_OPTION
= CHAR_MAX
+ 1,
121 static struct option
const long_options
[] =
123 {"all", no_argument
, NULL
, 'a'},
124 {"block-size", required_argument
, NULL
, 'B'},
125 {"inodes", no_argument
, NULL
, 'i'},
126 {"human-readable", no_argument
, NULL
, 'h'},
127 {"si", no_argument
, NULL
, 'H'},
128 {"kilobytes", no_argument
, NULL
, 'k'}, /* long form is obsolescent */
129 {"local", no_argument
, NULL
, 'l'},
130 {"megabytes", no_argument
, NULL
, 'm'}, /* obsolescent */
131 {"portability", no_argument
, NULL
, 'P'},
132 {"print-type", no_argument
, NULL
, 'T'},
133 {"sync", no_argument
, NULL
, SYNC_OPTION
},
134 {"no-sync", no_argument
, NULL
, NO_SYNC_OPTION
},
135 {"type", required_argument
, NULL
, 't'},
136 {"exclude-type", required_argument
, NULL
, 'x'},
137 {GETOPT_HELP_OPTION_DECL
},
138 {GETOPT_VERSION_OPTION_DECL
},
145 char buf
[MAX (LONGEST_HUMAN_READABLE
+ 1, INT_BUFSIZE_BOUND (uintmax_t))];
148 fputs (_("Filesystem Type"), stdout
);
150 fputs (_("Filesystem "), stdout
);
153 printf (_(" Inodes IUsed IFree IUse%%"));
154 else if (human_output_opts
& human_autoscale
)
156 if (human_output_opts
& human_base_1024
)
157 printf (_(" Size Used Avail Use%%"));
159 printf (_(" Size Used Avail Use%%"));
161 else if (posix_format
)
162 printf (_(" %4s-blocks Used Available Capacity"),
163 umaxtostr (output_block_size
, buf
));
166 int opts
= (human_suppress_point_zero
167 | human_autoscale
| human_SI
169 & (human_group_digits
| human_base_1024
| human_B
)));
171 /* Prefer the base that makes the human-readable value more exact,
172 if there is a difference. */
174 uintmax_t q1000
= output_block_size
;
175 uintmax_t q1024
= output_block_size
;
176 bool divisible_by_1000
;
177 bool divisible_by_1024
;
181 divisible_by_1000
= q1000
% 1000 == 0; q1000
/= 1000;
182 divisible_by_1024
= q1024
% 1024 == 0; q1024
/= 1024;
184 while (divisible_by_1000
& divisible_by_1024
);
186 if (divisible_by_1000
< divisible_by_1024
)
187 opts
|= human_base_1024
;
188 if (divisible_by_1024
< divisible_by_1000
)
189 opts
&= ~human_base_1024
;
190 if (! (opts
& human_base_1024
))
193 printf (_(" %4s-blocks Used Available Use%%"),
194 human_readable (output_block_size
, buf
, opts
, 1, 1));
197 printf (_(" Mounted on\n"));
200 /* Is FSTYPE a type of file system that should be listed? */
203 selected_fstype (const char *fstype
)
205 const struct fs_type_list
*fsp
;
207 if (fs_select_list
== NULL
|| fstype
== NULL
)
209 for (fsp
= fs_select_list
; fsp
; fsp
= fsp
->fs_next
)
210 if (STREQ (fstype
, fsp
->fs_name
))
215 /* Is FSTYPE a type of file system that should be omitted? */
218 excluded_fstype (const char *fstype
)
220 const struct fs_type_list
*fsp
;
222 if (fs_exclude_list
== NULL
|| fstype
== NULL
)
224 for (fsp
= fs_exclude_list
; fsp
; fsp
= fsp
->fs_next
)
225 if (STREQ (fstype
, fsp
->fs_name
))
230 /* Like human_readable (N, BUF, human_output_opts, INPUT_UNITS, OUTPUT_UNITS),
233 - Return "-" if N is -1,
234 - If NEGATIVE is 1 then N represents a negative number,
235 expressed in two's complement. */
238 df_readable (bool negative
, uintmax_t n
, char *buf
,
239 uintmax_t input_units
, uintmax_t output_units
)
241 if (n
== UINTMAX_MAX
)
245 char *p
= human_readable (negative
? -n
: n
, buf
+ negative
,
246 human_output_opts
, input_units
, output_units
);
253 /* Display a space listing for the disk device with absolute file name DISK.
254 If MOUNT_POINT is non-NULL, it is the name of the root of the
256 If STAT_FILE is non-null, it is the name of a file within the file
257 system that the user originally asked for; this provides better
258 diagnostics, and sometimes it provides better results on networked
259 file systems that give different free-space results depending on
260 where in the file system you probe.
261 If FSTYPE is non-NULL, it is the type of the file system on DISK.
262 If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may
263 not be able to produce statistics in this case.
264 ME_DUMMY and ME_REMOTE are the mount entry flags. */
267 show_dev (char const *disk
, char const *mount_point
,
268 char const *stat_file
, char const *fstype
,
269 bool me_dummy
, bool me_remote
)
272 char buf
[3][LONGEST_HUMAN_READABLE
+ 2];
275 uintmax_t input_units
;
276 uintmax_t output_units
;
279 bool negate_available
;
280 uintmax_t available_to_root
;
285 if (me_remote
& show_local_fs
)
288 if (me_dummy
& !show_all_fs
& !show_listed_fs
)
291 if (!selected_fstype (fstype
) || excluded_fstype (fstype
))
294 /* If MOUNT_POINT is NULL, then the file system is not mounted, and this
295 program reports on the file system that the special file is on.
296 It would be better to report on the unmounted file system,
297 but statfs doesn't do that on most systems. */
299 stat_file
= mount_point
? mount_point
: disk
;
301 if (get_fs_usage (stat_file
, disk
, &fsu
))
303 error (0, errno
, "%s", quote (stat_file
));
304 exit_status
= EXIT_FAILURE
;
308 if (fsu
.fsu_blocks
== 0 && !show_all_fs
&& !show_listed_fs
)
312 disk
= "-"; /* unknown */
314 fstype
= "-"; /* unknown */
316 /* df.c reserved 5 positions for fstype,
317 but that does not suffice for type iso9660 */
320 size_t disk_name_len
= strlen (disk
);
321 size_t fstype_len
= strlen (fstype
);
322 if (disk_name_len
+ fstype_len
< 18)
323 printf ("%s%*s ", disk
, 18 - (int) disk_name_len
, fstype
);
324 else if (!posix_format
)
325 printf ("%s\n%18s ", disk
, fstype
);
327 printf ("%s %s", disk
, fstype
);
331 if (strlen (disk
) > 20 && !posix_format
)
332 printf ("%s\n%20s", disk
, "");
334 printf ("%-20s", disk
);
341 input_units
= output_units
= 1;
342 total
= fsu
.fsu_files
;
343 available
= fsu
.fsu_ffree
;
344 negate_available
= false;
345 available_to_root
= available
;
349 width
= (human_output_opts
& human_autoscale
350 ? 5 + ! (human_output_opts
& human_base_1024
)
352 use_width
= ((posix_format
353 && ! (human_output_opts
& human_autoscale
))
355 input_units
= fsu
.fsu_blocksize
;
356 output_units
= output_block_size
;
357 total
= fsu
.fsu_blocks
;
358 available
= fsu
.fsu_bavail
;
359 negate_available
= fsu
.fsu_bavail_top_bit_set
;
360 available_to_root
= fsu
.fsu_bfree
;
365 if (total
!= UINTMAX_MAX
&& available_to_root
!= UINTMAX_MAX
)
367 used
= total
- available_to_root
;
368 if (total
< available_to_root
)
375 printf (" %*s %*s %*s ",
376 width
, df_readable (false, total
,
377 buf
[0], input_units
, output_units
),
378 width
, df_readable (negate_used
, used
,
379 buf
[1], input_units
, output_units
),
380 width
, df_readable (negate_available
, available
,
381 buf
[2], input_units
, output_units
));
383 if (used
== UINTMAX_MAX
|| available
== UINTMAX_MAX
)
385 else if (!negate_used
386 && used
<= TYPE_MAXIMUM (uintmax_t) / 100
387 && used
+ available
!= 0
388 && (used
+ available
< used
) == negate_available
)
390 uintmax_t u100
= used
* 100;
391 uintmax_t nonroot_total
= used
+ available
;
392 pct
= u100
/ nonroot_total
+ (u100
% nonroot_total
!= 0);
396 /* The calculation cannot be done easily with integer
397 arithmetic. Fall back on floating point. This can suffer
398 from minor rounding errors, but doing it exactly requires
399 multiple precision arithmetic, and it's not worth the
401 double u
= negate_used
? - (double) - used
: used
;
402 double a
= negate_available
? - (double) - available
: available
;
403 double nonroot_total
= u
+ a
;
406 long int lipct
= pct
= u
* 100 / nonroot_total
;
409 /* Like `pct = ceil (dpct);', but avoid ceil so that
410 the math library needn't be linked. */
411 if (ipct
- 1 < pct
&& pct
<= ipct
+ 1)
412 pct
= ipct
+ (ipct
< pct
);
417 printf ("%*.0f%%", use_width
- 1, pct
);
419 printf ("%*s", use_width
, "- ");
423 #ifdef HIDE_AUTOMOUNT_PREFIX
424 /* Don't print the first directory name in MOUNT_POINT if it's an
425 artifact of an automounter. This is a bit too aggressive to be
427 if (strncmp ("/auto/", mount_point
, 6) == 0)
429 else if (strncmp ("/tmp_mnt/", mount_point
, 9) == 0)
432 printf (" %s", mount_point
);
437 /* Return the root mountpoint of the file system on which FILE exists, in
438 malloced storage. FILE_STAT should be the result of stating FILE.
439 Give a diagnostic and return NULL if unable to determine the mount point.
440 Exit if unable to restore current working directory. */
442 find_mount_point (const char *file
, const struct stat
*file_stat
)
444 struct saved_cwd cwd
;
445 struct stat last_stat
;
446 char *mp
= NULL
; /* The malloced mount point. */
448 if (save_cwd (&cwd
) != 0)
450 error (0, errno
, _("cannot get current directory"));
454 if (S_ISDIR (file_stat
->st_mode
))
455 /* FILE is a directory, so just chdir there directly. */
457 last_stat
= *file_stat
;
458 if (chdir (file
) < 0)
460 error (0, errno
, _("cannot change to directory %s"), quote (file
));
465 /* FILE is some other kind of file; use its directory. */
467 char *xdir
= dir_name (file
);
469 ASSIGN_STRDUPA (dir
, xdir
);
474 error (0, errno
, _("cannot change to directory %s"), quote (dir
));
478 if (stat (".", &last_stat
) < 0)
480 error (0, errno
, _("cannot stat current directory (now %s)"),
486 /* Now walk up FILE's parents until we find another file system or /,
487 chdiring as we go. LAST_STAT holds stat information for the last place
492 if (stat ("..", &st
) < 0)
494 error (0, errno
, _("cannot stat %s"), quote (".."));
497 if (st
.st_dev
!= last_stat
.st_dev
|| st
.st_ino
== last_stat
.st_ino
)
498 /* cwd is the mount point. */
500 if (chdir ("..") < 0)
502 error (0, errno
, _("cannot change to directory %s"), quote (".."));
508 /* Finally reached a mount point, see what it's called. */
512 /* Restore the original cwd. */
514 int save_errno
= errno
;
515 if (restore_cwd (&cwd
) != 0)
516 error (EXIT_FAILURE
, errno
,
517 _("failed to return to initial working directory"));
525 /* If DISK corresponds to a mount point, show its usage
526 and return true. Otherwise, return false. */
528 show_disk (char const *disk
)
530 struct mount_entry
const *me
;
531 struct mount_entry
const *best_match
= NULL
;
533 for (me
= mount_list
; me
; me
= me
->me_next
)
534 if (STREQ (disk
, me
->me_devname
))
539 show_dev (best_match
->me_devname
, best_match
->me_mountdir
, NULL
,
540 best_match
->me_type
, best_match
->me_dummy
,
541 best_match
->me_remote
);
548 /* Figure out which device file or directory POINT is mounted on
549 and show its disk usage.
550 STATP must be the result of `stat (POINT, STATP)'. */
552 show_point (const char *point
, const struct stat
*statp
)
554 struct stat disk_stats
;
555 struct mount_entry
*me
;
556 struct mount_entry
const *best_match
= NULL
;
558 /* If POINT is an absolute file name, see if we can find the
559 mount point without performing any extra stat calls at all. */
562 /* Find the best match: prefer non-dummies, and then prefer the
563 last match if there are ties. */
565 for (me
= mount_list
; me
; me
= me
->me_next
)
566 if (STREQ (me
->me_mountdir
, point
) && !STREQ (me
->me_type
, "lofs")
567 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
571 /* Calculate the real absolute file name for POINT, and use that to find
572 the mount point. This avoids statting unavailable mount points,
573 which can hang df. */
576 char *resolved
= canonicalize_file_name (point
);
578 if (resolved
&& resolved
[0] == '/')
580 size_t resolved_len
= strlen (resolved
);
581 size_t best_match_len
= 0;
583 for (me
= mount_list
; me
; me
= me
->me_next
)
584 if (!STREQ (me
->me_type
, "lofs")
585 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
587 size_t len
= strlen (me
->me_mountdir
);
588 if (best_match_len
<= len
&& len
<= resolved_len
589 && (len
== 1 /* root file system */
590 || ((len
== resolved_len
|| resolved
[len
] == '/')
591 && strncmp (me
->me_mountdir
, resolved
, len
) == 0)))
594 best_match_len
= len
;
602 && (stat (best_match
->me_mountdir
, &disk_stats
) != 0
603 || disk_stats
.st_dev
!= statp
->st_dev
))
608 for (me
= mount_list
; me
; me
= me
->me_next
)
610 if (me
->me_dev
== (dev_t
) -1)
612 if (stat (me
->me_mountdir
, &disk_stats
) == 0)
613 me
->me_dev
= disk_stats
.st_dev
;
616 error (0, errno
, "%s", quote (me
->me_mountdir
));
617 exit_status
= EXIT_FAILURE
;
618 /* So we won't try and fail repeatedly. */
619 me
->me_dev
= (dev_t
) -2;
623 if (statp
->st_dev
== me
->me_dev
624 && !STREQ (me
->me_type
, "lofs")
625 && (!best_match
|| best_match
->me_dummy
|| !me
->me_dummy
))
627 /* Skip bogus mtab entries. */
628 if (stat (me
->me_mountdir
, &disk_stats
) != 0
629 || disk_stats
.st_dev
!= me
->me_dev
)
630 me
->me_dev
= (dev_t
) -2;
637 show_dev (best_match
->me_devname
, best_match
->me_mountdir
, point
,
638 best_match
->me_type
, best_match
->me_dummy
, best_match
->me_remote
);
641 /* We couldn't find the mount entry corresponding to POINT. Go ahead and
642 print as much info as we can; methods that require the device to be
643 present will fail at a later point. */
645 /* Find the actual mount point. */
646 char *mp
= find_mount_point (point
, statp
);
649 show_dev (NULL
, mp
, NULL
, NULL
, false, false);
655 /* Determine what kind of node NAME is and show the disk usage
656 for it. STATP is the results of `stat' on NAME. */
659 show_entry (char const *name
, struct stat
const *statp
)
661 if ((S_ISBLK (statp
->st_mode
) || S_ISCHR (statp
->st_mode
))
665 show_point (name
, statp
);
668 /* Show all mounted file systems, except perhaps those that are of
669 an unselected type or are empty. */
672 show_all_entries (void)
674 struct mount_entry
*me
;
676 for (me
= mount_list
; me
; me
= me
->me_next
)
677 show_dev (me
->me_devname
, me
->me_mountdir
, NULL
, me
->me_type
,
678 me
->me_dummy
, me
->me_remote
);
681 /* Add FSTYPE to the list of file system types to display. */
684 add_fs_type (const char *fstype
)
686 struct fs_type_list
*fsp
;
688 fsp
= xmalloc (sizeof *fsp
);
689 fsp
->fs_name
= (char *) fstype
;
690 fsp
->fs_next
= fs_select_list
;
691 fs_select_list
= fsp
;
694 /* Add FSTYPE to the list of file system types to be omitted. */
697 add_excluded_fs_type (const char *fstype
)
699 struct fs_type_list
*fsp
;
701 fsp
= xmalloc (sizeof *fsp
);
702 fsp
->fs_name
= (char *) fstype
;
703 fsp
->fs_next
= fs_exclude_list
;
704 fs_exclude_list
= fsp
;
710 if (status
!= EXIT_SUCCESS
)
711 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
715 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name
);
717 Show information about the file system on which each FILE resides,\n\
718 or all file systems by default.\n\
722 Mandatory arguments to long options are mandatory for short options too.\n\
725 -a, --all include file systems having 0 blocks\n\
726 -B, --block-size=SIZE use SIZE-byte blocks\n\
727 -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\n\
728 -H, --si likewise, but use powers of 1000 not 1024\n\
731 -i, --inodes list inode information instead of block usage\n\
732 -k like --block-size=1K\n\
733 -l, --local limit listing to local file systems\n\
734 --no-sync do not invoke sync before getting usage info (default)\n\
737 -P, --portability use the POSIX output format\n\
738 --sync invoke sync before getting usage info\n\
739 -t, --type=TYPE limit listing to file systems of type TYPE\n\
740 -T, --print-type print file system type\n\
741 -x, --exclude-type=TYPE limit listing to file systems not of type TYPE\n\
744 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
745 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
747 SIZE may be (or may be an integer optionally followed by) one of following:\n\
748 kB 1000, K 1024, MB 1000*1000, M 1024*1024, and so on for G, T, P, E, Z, Y.\n\
750 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT
);
756 main (int argc
, char **argv
)
759 struct stat
*stats
IF_LINT (= 0);
760 int n_valid_args
= 0;
762 initialize_main (&argc
, &argv
);
763 program_name
= argv
[0];
764 setlocale (LC_ALL
, "");
765 bindtextdomain (PACKAGE
, LOCALEDIR
);
766 textdomain (PACKAGE
);
768 atexit (close_stdout
);
770 fs_select_list
= NULL
;
771 fs_exclude_list
= NULL
;
772 inode_format
= false;
774 show_listed_fs
= false;
776 human_output_opts
= human_options (getenv ("DF_BLOCK_SIZE"), false,
780 posix_format
= false;
781 exit_status
= EXIT_SUCCESS
;
783 while ((c
= getopt_long (argc
, argv
, "aB:iF:hHklmPTt:vx:", long_options
, NULL
))
792 human_output_opts
= human_options (optarg
, true, &output_block_size
);
798 human_output_opts
= human_autoscale
| human_SI
| human_base_1024
;
799 output_block_size
= 1;
802 human_output_opts
= human_autoscale
| human_SI
;
803 output_block_size
= 1;
806 human_output_opts
= 0;
807 output_block_size
= 1024;
810 show_local_fs
= true;
812 case 'm': /* obsolescent */
813 human_output_opts
= 0;
814 output_block_size
= 1024 * 1024;
826 require_sync
= false;
830 /* Accept -F as a synonym for -t for compatibility with Solaris. */
832 add_fs_type (optarg
);
835 case 'v': /* For SysV compatibility. */
839 add_excluded_fs_type (optarg
);
842 case_GETOPT_HELP_CHAR
;
843 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
846 usage (EXIT_FAILURE
);
850 /* Fail if the same file system type was both selected and excluded. */
853 struct fs_type_list
*fs_incl
;
854 for (fs_incl
= fs_select_list
; fs_incl
; fs_incl
= fs_incl
->fs_next
)
856 struct fs_type_list
*fs_excl
;
857 for (fs_excl
= fs_exclude_list
; fs_excl
; fs_excl
= fs_excl
->fs_next
)
859 if (STREQ (fs_incl
->fs_name
, fs_excl
->fs_name
))
862 _("file system type %s both selected and excluded"),
863 quote (fs_incl
->fs_name
));
877 /* stat all the given entries to make sure they get automounted,
878 if necessary, before reading the file system table. */
879 stats
= xnmalloc (argc
- optind
, sizeof *stats
);
880 for (i
= optind
; i
< argc
; ++i
)
882 if (stat (argv
[i
], &stats
[i
- optind
]))
884 error (0, errno
, "%s", quote (argv
[i
]));
885 exit_status
= EXIT_FAILURE
;
896 read_file_system_list ((fs_select_list
!= NULL
897 || fs_exclude_list
!= NULL
901 if (mount_list
== NULL
)
903 /* Couldn't read the table of mounted file systems.
904 Fail if df was invoked with no file name arguments;
905 Otherwise, merely give a warning and proceed. */
906 const char *warning
= (optind
< argc
? _("Warning: ") : "");
907 int status
= (optind
< argc
? 0 : EXIT_FAILURE
);
908 error (status
, errno
,
909 _("%scannot read table of mounted file systems"), warning
);
919 /* Display explicitly requested empty file systems. */
920 show_listed_fs
= true;
922 if (n_valid_args
> 0)
925 for (i
= optind
; i
< argc
; ++i
)
927 show_entry (argv
[i
], &stats
[i
- optind
]);