1 /* stat.c -- display file or file system status
2 Copyright (C) 2001-2008 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 Michael Meskes. */
21 /* Keep this conditional in sync with the similar conditional in
22 ../m4/stat-prog.m4. */
24 && (HAVE_STRUCT_STATVFS_F_BASETYPE || HAVE_STRUCT_STATVFS_F_FSTYPENAME \
25 || (! HAVE_STRUCT_STATFS_F_FSTYPENAME && HAVE_STRUCT_STATVFS_F_TYPE)))
26 # define USE_STATVFS 1
28 # define USE_STATVFS 0
33 #include <sys/types.h>
37 # include <sys/statvfs.h>
40 #elif HAVE_SYS_MOUNT_H && HAVE_SYS_PARAM_H
41 /* NOTE: freebsd5.0 needs sys/param.h and sys/mount.h for statfs.
42 It does have statvfs.h, but shouldn't use it, since it doesn't
43 HAVE_STRUCT_STATVFS_F_BASETYPE. So find a clean way to fix it. */
44 /* NetBSD 1.5.2 needs these, for the declaration of struct statfs. */
45 # include <sys/param.h>
46 # include <sys/mount.h>
47 # if HAVE_NETINET_IN_H && HAVE_NFS_NFS_CLNT_H && HAVE_NFS_VFS_H
48 /* Ultrix 4.4 needs these for the declaration of struct statfs. */
49 # include <netinet/in.h>
50 # include <nfs/nfs_clnt.h>
53 #elif HAVE_OS_H /* BeOS */
56 #include <selinux/selinux.h>
62 #include "file-type.h"
68 #include "stat-time.h"
70 #include "areadlink.h"
72 #define alignof(type) offsetof (struct { char c; type x; }, x)
75 # define STRUCT_STATVFS struct statvfs
76 # define STRUCT_STATXFS_F_FSID_IS_INTEGER STRUCT_STATVFS_F_FSID_IS_INTEGER
77 # define HAVE_STRUCT_STATXFS_F_TYPE HAVE_STRUCT_STATVFS_F_TYPE
78 # if HAVE_STRUCT_STATVFS_F_NAMEMAX
79 # define SB_F_NAMEMAX(S) ((S)->f_namemax)
81 # define STATFS statvfs
82 # define STATFS_FRSIZE(S) ((S)->f_frsize)
84 # define HAVE_STRUCT_STATXFS_F_TYPE HAVE_STRUCT_STATFS_F_TYPE
85 # if HAVE_STRUCT_STATFS_F_NAMELEN
86 # define SB_F_NAMEMAX(S) ((S)->f_namelen)
88 # define STATFS statfs
89 # if HAVE_OS_H /* BeOS */
90 /* BeOS has a statvfs function, but it does not return sensible values
91 for f_files, f_ffree and f_favail, and lacks f_type, f_basetype and
92 f_fstypename. Use 'struct fs_info' instead. */
94 statfs (char const *filename, struct fs_info *buf)
96 dev_t device = dev_for_path (filename);
99 errno = (device == B_ENTRY_NOT_FOUND ? ENOENT
100 : device == B_BAD_VALUE ? EINVAL
101 : device == B_NAME_TOO_LONG ? ENAMETOOLONG
102 : device == B_NO_MEMORY ? ENOMEM
103 : device == B_FILE_ERROR ? EIO
107 /* If successful, buf->dev will be == device. */
108 return fs_stat_dev (device, buf);
111 # define f_blocks total_blocks
112 # define f_bfree free_blocks
113 # define f_bavail free_blocks
114 # define f_bsize io_size
115 # define f_files total_nodes
116 # define f_ffree free_nodes
117 # define STRUCT_STATVFS struct fs_info
118 # define STRUCT_STATXFS_F_FSID_IS_INTEGER true
119 # define STATFS_FRSIZE(S) ((S)->block_size)
121 # define STRUCT_STATVFS struct statfs
122 # define STRUCT_STATXFS_F_FSID_IS_INTEGER STRUCT_STATFS_F_FSID_IS_INTEGER
123 # define STATFS_FRSIZE(S) 0
128 # define OUT_NAMEMAX out_uint
130 /* NetBSD 1.5.2 has neither f_namemax nor f_namelen. */
131 # define SB_F_NAMEMAX(S) "*"
132 # define OUT_NAMEMAX out_string
135 #if HAVE_STRUCT_STATVFS_F_BASETYPE
136 # define STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME f_basetype
138 # if HAVE_STRUCT_STATVFS_F_FSTYPENAME || HAVE_STRUCT_STATFS_F_FSTYPENAME
139 # define STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME f_fstypename
140 # elif HAVE_OS_H /* BeOS */
141 # define STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME fsh_name
145 /* FIXME: these are used by printf.c, too */
146 #define isodigit(c) ('0' <= (c) && (c) <= '7')
147 #define octtobin(c) ((c) - '0')
148 #define hextobin(c) ((c) >= 'a' && (c) <= 'f' ? (c) - 'a' + 10 : \
149 (c) >= 'A' && (c) <= 'F' ? (c) - 'A' + 10 : (c) - '0')
151 #define PROGRAM_NAME "stat"
153 #define AUTHORS proper_name ("Michael Meskes")
157 PRINTF_OPTION = CHAR_MAX + 1
160 static struct option const long_options[] =
162 {"context", no_argument, 0, 'Z'},
163 {"dereference", no_argument, NULL, 'L'},
164 {"file-system", no_argument, NULL, 'f'},
166 /* obsolete and undocumented alias: FIXME: remove in 2009 */
167 {"filesystem", no_argument, NULL, 'f'},
169 {"format", required_argument, NULL, 'c'},
170 {"printf", required_argument, NULL, PRINTF_OPTION},
171 {"terse", no_argument, NULL, 't'},
172 {GETOPT_HELP_OPTION_DECL},
173 {GETOPT_VERSION_OPTION_DECL},
177 /* Whether to follow symbolic links; True for --dereference (-L). */
178 static bool follow_links;
180 /* Whether to interpret backslash-escape sequences.
181 True for --printf=FMT, not for --format=FMT (-c). */
182 static bool interpret_backslash_escapes;
184 /* The trailing delimiter string:
185 "" for --printf=FMT, "\n" for --format=FMT (-c). */
186 static char const *trailing_delim = "";
188 /* Return the type of the specified file system.
189 Some systems have statfvs.f_basetype[FSTYPSZ] (AIX, HP-UX, and Solaris).
190 Others have statvfs.f_fstypename[_VFS_NAMELEN] (NetBSD 3.0).
191 Others have statfs.f_fstypename[MFSNAMELEN] (NetBSD 1.5.2).
192 Still others have neither and have to get by with f_type (Linux).
193 But f_type may only exist in statfs (Cygwin). */
195 human_fstype (STRUCT_STATVFS const *statfsbuf)
197 #ifdef STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME
198 return statfsbuf->STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME;
200 switch (statfsbuf->f_type)
202 # if defined __linux__
204 /* Compare with what's in libc:
205 f=/a/libc/sysdeps/unix/sysv/linux/linux_fsinfo.h
206 sed -n '/ADFS_SUPER_MAGIC/,/SYSFS_MAGIC/p' $f \
207 | perl -n -e '/#define (.*?)_(?:SUPER_)MAGIC\s+0x(\S+)/' \
208 -e 'and print "case S_MAGIC_$1: /\* 0x" . uc($2) . " *\/\n"' \
210 perl -ne '/^\s+(case S_MAGIC_.*?): \/\* 0x(\S+) \*\//' \
211 -e 'and do { $v=uc$2; print "$1: /\* 0x$v *\/\n"}' stat.c \
213 diff -u sym_stat sym_libc
216 /* Also sync from the list in "man 2 statfs". */
218 /* IMPORTANT NOTE: Each of the following `case S_MAGIC_...:'
219 statements must be followed by a hexadecimal constant in
220 a comment. The S_MAGIC_... name and constant are automatically
221 combined to produce the #define directives in fs.h. */
223 case S_MAGIC_ADFS: /* 0xADF5 */
225 case S_MAGIC_AFFS: /* 0xADFF */
227 case S_MAGIC_AUTOFS: /* 0x187 */
229 case S_MAGIC_BEFS: /* 0x42465331 */
231 case S_MAGIC_BFS: /* 0x1BADFACE */
233 case S_MAGIC_BINFMT_MISC: /* 0x42494e4d */
234 return "binfmt_misc";
235 case S_MAGIC_CODA: /* 0x73757245 */
237 case S_MAGIC_COH: /* 0x012FF7B7 */
239 case S_MAGIC_CRAMFS: /* 0x28CD3D45 */
241 case S_MAGIC_DEVFS: /* 0x1373 */
243 case S_MAGIC_DEVPTS: /* 0x1CD1 */
245 case S_MAGIC_EFS: /* 0x414A53 */
247 case S_MAGIC_EXT: /* 0x137D */
249 case S_MAGIC_EXT2: /* 0xEF53 */
251 case S_MAGIC_EXT2_OLD: /* 0xEF51 */
253 case S_MAGIC_FAT: /* 0x4006 */
255 case S_MAGIC_FUSECTL: /* 0x65735543 */
257 case S_MAGIC_HPFS: /* 0xF995E849 */
259 case S_MAGIC_HUGETLBFS: /* 0x958458f6 */
261 case S_MAGIC_ISOFS: /* 0x9660 */
263 case S_MAGIC_ISOFS_R_WIN: /* 0x4004 */
265 case S_MAGIC_ISOFS_WIN: /* 0x4000 */
267 case S_MAGIC_JFFS2: /* 0x72B6 */
269 case S_MAGIC_JFFS: /* 0x07C0 */
271 case S_MAGIC_JFS: /* 0x3153464A */
273 case S_MAGIC_MINIX: /* 0x137F */
275 case S_MAGIC_MINIX_30: /* 0x138F */
276 return "minix (30 char.)";
277 case S_MAGIC_MINIX_V2: /* 0x2468 */
279 case S_MAGIC_MINIX_V2_30: /* 0x2478 */
280 return "minix v2 (30 char.)";
281 case S_MAGIC_MSDOS: /* 0x4D44 */
283 case S_MAGIC_NCP: /* 0x564C */
285 case S_MAGIC_NFS: /* 0x6969 */
287 case S_MAGIC_NFSD: /* 0x6E667364 */
289 case S_MAGIC_NTFS: /* 0x5346544E */
291 case S_MAGIC_OPENPROM: /* 0x9fa1 */
293 case S_MAGIC_PROC: /* 0x9FA0 */
295 case S_MAGIC_QNX4: /* 0x002F */
297 case S_MAGIC_RAMFS: /* 0x858458F6 */
299 case S_MAGIC_REISERFS: /* 0x52654973 */
301 case S_MAGIC_ROMFS: /* 0x7275 */
303 case S_MAGIC_SMB: /* 0x517B */
305 case S_MAGIC_SQUASHFS: /* 0x73717368 */
307 case S_MAGIC_SYSFS: /* 0x62656572 */
309 case S_MAGIC_SYSV2: /* 0x012FF7B6 */
311 case S_MAGIC_SYSV4: /* 0x012FF7B5 */
313 case S_MAGIC_TMPFS: /* 0x1021994 */
315 case S_MAGIC_UDF: /* 0x15013346 */
317 case S_MAGIC_UFS: /* 0x00011954 */
319 case S_MAGIC_UFS_BYTESWAPPED: /* 0x54190100 */
321 case S_MAGIC_USBDEVFS: /* 0x9FA2 */
323 case S_MAGIC_VXFS: /* 0xA501FCF5 */
325 case S_MAGIC_XENIX: /* 0x012FF7B4 */
327 case S_MAGIC_XFS: /* 0x58465342 */
329 case S_MAGIC_XIAFS: /* 0x012FD16D */
390 unsigned long int type = statfsbuf->f_type;
391 static char buf[sizeof "UNKNOWN (0x%lx)" - 3
392 + (sizeof type * CHAR_BIT + 3) / 4];
393 sprintf (buf, "UNKNOWN (0x%lx)", type);
401 human_access (struct stat const *statbuf)
403 static char modebuf[12];
404 filemodestring (statbuf, modebuf);
410 human_time (struct timespec t)
412 static char str[MAX (INT_BUFSIZE_BOUND (intmax_t),
413 (INT_STRLEN_BOUND (int) /* YYYY */
414 + 1 /* because YYYY might equal INT_MAX + 1900 */
415 + sizeof "-MM-DD HH:MM:SS.NNNNNNNNN +ZZZZ"))];
416 struct tm const *tm = localtime (&t.tv_sec);
418 return (TYPE_SIGNED (time_t)
419 ? imaxtostr (t.tv_sec, str)
420 : umaxtostr (t.tv_sec, str));
421 nstrftime (str, sizeof str, "%Y-%m-%d %H:%M:%S.%N %z", tm, 0, t.tv_nsec);
426 out_string (char *pformat, size_t prefix_len, char const *arg)
428 strcpy (pformat + prefix_len, "s");
429 printf (pformat, arg);
432 out_int (char *pformat, size_t prefix_len, intmax_t arg)
434 strcpy (pformat + prefix_len, PRIdMAX);
435 printf (pformat, arg);
438 out_uint (char *pformat, size_t prefix_len, uintmax_t arg)
440 strcpy (pformat + prefix_len, PRIuMAX);
441 printf (pformat, arg);
444 out_uint_o (char *pformat, size_t prefix_len, uintmax_t arg)
446 strcpy (pformat + prefix_len, PRIoMAX);
447 printf (pformat, arg);
450 out_uint_x (char *pformat, size_t prefix_len, uintmax_t arg)
452 strcpy (pformat + prefix_len, PRIxMAX);
453 printf (pformat, arg);
456 /* Very specialized function (modifies FORMAT), just so as to avoid
457 duplicating this code between both print_statfs and print_stat. */
459 out_file_context (char const *filename, char *pformat, size_t prefix_len)
463 ? getfilecon (filename, &scontext)
464 : lgetfilecon (filename, &scontext)) < 0)
466 error (0, errno, _("failed to get security context of %s"),
470 strcpy (pformat + prefix_len, "s");
471 printf (pformat, (scontext ? scontext : "?"));
476 /* print statfs info */
478 print_statfs (char *pformat, size_t prefix_len, char m, char const *filename,
481 STRUCT_STATVFS const *statfsbuf = data;
486 out_string (pformat, prefix_len, filename);
491 #if STRUCT_STATXFS_F_FSID_IS_INTEGER
492 uintmax_t fsid = statfsbuf->f_fsid;
494 typedef unsigned int fsid_word;
495 verify (alignof (STRUCT_STATVFS) % alignof (fsid_word) == 0);
496 verify (offsetof (STRUCT_STATVFS, f_fsid) % alignof (fsid_word) == 0);
497 verify (sizeof statfsbuf->f_fsid % alignof (fsid_word) == 0);
498 fsid_word const *p = (fsid_word *) &statfsbuf->f_fsid;
500 /* Assume a little-endian word order, as that is compatible
501 with glibc's statvfs implementation. */
503 int words = sizeof statfsbuf->f_fsid / sizeof *p;
505 for (i = 0; i < words && i * sizeof *p < sizeof fsid; i++)
507 uintmax_t u = p[words - 1 - i];
508 fsid |= u << (i * CHAR_BIT * sizeof *p);
511 out_uint_x (pformat, prefix_len, fsid);
516 OUT_NAMEMAX (pformat, prefix_len, SB_F_NAMEMAX (statfsbuf));
519 #if HAVE_STRUCT_STATXFS_F_TYPE
520 out_uint_x (pformat, prefix_len, statfsbuf->f_type);
526 out_string (pformat, prefix_len, human_fstype (statfsbuf));
529 out_int (pformat, prefix_len, statfsbuf->f_blocks);
532 out_int (pformat, prefix_len, statfsbuf->f_bfree);
535 out_int (pformat, prefix_len, statfsbuf->f_bavail);
538 out_uint (pformat, prefix_len, statfsbuf->f_bsize);
542 uintmax_t frsize = STATFS_FRSIZE (statfsbuf);
544 frsize = statfsbuf->f_bsize;
545 out_uint (pformat, prefix_len, frsize);
549 out_int (pformat, prefix_len, statfsbuf->f_files);
552 out_int (pformat, prefix_len, statfsbuf->f_ffree);
555 out_file_context (filename, pformat, prefix_len);
563 /* print stat info */
565 print_stat (char *pformat, size_t prefix_len, char m,
566 char const *filename, void const *data)
568 struct stat *statbuf = (struct stat *) data;
569 struct passwd *pw_ent;
570 struct group *gw_ent;
575 out_string (pformat, prefix_len, filename);
578 out_string (pformat, prefix_len, quote (filename));
579 if (S_ISLNK (statbuf->st_mode))
581 char *linkname = areadlink_with_size (filename, statbuf->st_size);
582 if (linkname == NULL)
584 error (0, errno, _("cannot read symbolic link %s"),
589 out_string (pformat, prefix_len, quote (linkname));
593 out_uint (pformat, prefix_len, statbuf->st_dev);
596 out_uint_x (pformat, prefix_len, statbuf->st_dev);
599 out_uint (pformat, prefix_len, statbuf->st_ino);
602 out_uint_o (pformat, prefix_len, statbuf->st_mode & CHMOD_MODE_BITS);
605 out_string (pformat, prefix_len, human_access (statbuf));
608 out_uint_x (pformat, prefix_len, statbuf->st_mode);
611 out_string (pformat, prefix_len, file_type (statbuf));
614 out_uint (pformat, prefix_len, statbuf->st_nlink);
617 out_uint (pformat, prefix_len, statbuf->st_uid);
621 pw_ent = getpwuid (statbuf->st_uid);
622 out_string (pformat, prefix_len,
623 pw_ent ? pw_ent->pw_name : "UNKNOWN");
626 out_uint (pformat, prefix_len, statbuf->st_gid);
630 gw_ent = getgrgid (statbuf->st_gid);
631 out_string (pformat, prefix_len,
632 gw_ent ? gw_ent->gr_name : "UNKNOWN");
635 out_uint_x (pformat, prefix_len, major (statbuf->st_rdev));
638 out_uint_x (pformat, prefix_len, minor (statbuf->st_rdev));
641 out_uint (pformat, prefix_len, statbuf->st_size);
644 out_uint (pformat, prefix_len, ST_NBLOCKSIZE);
647 out_uint (pformat, prefix_len, ST_NBLOCKS (*statbuf));
650 out_uint (pformat, prefix_len, statbuf->st_blksize);
653 out_string (pformat, prefix_len, human_time (get_stat_atime (statbuf)));
656 if (TYPE_SIGNED (time_t))
657 out_int (pformat, prefix_len, statbuf->st_atime);
659 out_uint (pformat, prefix_len, statbuf->st_atime);
662 out_string (pformat, prefix_len, human_time (get_stat_mtime (statbuf)));
665 if (TYPE_SIGNED (time_t))
666 out_int (pformat, prefix_len, statbuf->st_mtime);
668 out_uint (pformat, prefix_len, statbuf->st_mtime);
671 out_string (pformat, prefix_len, human_time (get_stat_ctime (statbuf)));
674 if (TYPE_SIGNED (time_t))
675 out_int (pformat, prefix_len, statbuf->st_ctime);
677 out_uint (pformat, prefix_len, statbuf->st_ctime);
680 out_file_context (filename, pformat, prefix_len);
688 /* Output a single-character \ escape. */
691 print_esc_char (char c)
695 case 'a': /* Alert. */
698 case 'b': /* Backspace. */
701 case 'f': /* Form feed. */
704 case 'n': /* New line. */
707 case 'r': /* Carriage return. */
710 case 't': /* Horizontal tab. */
713 case 'v': /* Vertical tab. */
720 error (0, 0, _("warning: unrecognized escape `\\%c'"), c);
727 print_it (char const *format, char const *filename,
728 void (*print_func) (char *, size_t, char, char const *, void const *),
731 /* Add 2 to accommodate our conversion of the stat `%s' format string
732 to the longer printf `%llu' one. */
735 MAX_ADDITIONAL_BYTES =
736 (MAX (sizeof PRIdMAX,
737 MAX (sizeof PRIoMAX, MAX (sizeof PRIuMAX, sizeof PRIxMAX)))
740 size_t n_alloc = strlen (format) + MAX_ADDITIONAL_BYTES + 1;
741 char *dest = xmalloc (n_alloc);
743 for (b = format; *b; b++)
749 size_t len = strspn (b + 1, "#-+.I 0123456789");
750 char const *fmt_char = b + len + 1;
751 memcpy (dest, b, len + 1);
762 dest[len + 1] = *fmt_char;
763 dest[len + 2] = '\0';
764 error (EXIT_FAILURE, 0, _("%s: invalid directive"),
765 quotearg_colon (dest));
770 print_func (dest, len + 1, *fmt_char, filename, data);
777 if ( ! interpret_backslash_escapes)
785 int esc_value = octtobin (*b);
786 int esc_length = 1; /* number of octal digits */
787 for (++b; esc_length < 3 && isodigit (*b);
790 esc_value = esc_value * 8 + octtobin (*b);
795 else if (*b == 'x' && isxdigit (to_uchar (b[1])))
797 int esc_value = hextobin (b[1]); /* Value of \xhh escape. */
798 /* A hexadecimal \xhh escape sequence must have
799 1 or 2 hex. digits. */
801 if (isxdigit (to_uchar (b[1])))
804 esc_value = esc_value * 16 + hextobin (*b);
810 error (0, 0, _("warning: backslash at end of format"));
812 /* Arrange to exit the loop. */
828 fputs (trailing_delim, stdout);
831 /* Stat the file system and print what we find. */
833 do_statfs (char const *filename, bool terse, char const *format)
835 STRUCT_STATVFS statfsbuf;
837 if (STATFS (filename, &statfsbuf) != 0)
839 error (0, errno, _("cannot read file system information for %s"),
847 ? "%n %i %l %t %s %S %b %f %a %c %d\n"
849 " ID: %-8i Namelen: %-7l Type: %T\n"
850 "Block size: %-10s Fundamental block size: %S\n"
851 "Blocks: Total: %-10b Free: %-10f Available: %a\n"
852 "Inodes: Total: %-10c Free: %d\n");
855 print_it (format, filename, print_statfs, &statfsbuf);
859 /* stat the file and print what we find */
861 do_stat (char const *filename, bool terse, char const *format)
865 if ((follow_links ? stat : lstat) (filename, &statbuf) != 0)
867 error (0, errno, _("cannot stat %s"), quote (filename));
875 format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o\n";
879 /* Temporary hack to match original output until conditional
881 if (S_ISBLK (statbuf.st_mode) || S_ISCHR (statbuf.st_mode))
885 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
886 "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
887 " Device type: %t,%T\n"
888 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
889 "Access: %x\n" "Modify: %y\n" "Change: %z\n";
895 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
896 "Device: %Dh/%dd\tInode: %-10i Links: %h\n"
897 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
898 "Access: %x\n" "Modify: %y\n" "Change: %z\n";
902 print_it (format, filename, print_stat, &statbuf);
909 if (status != EXIT_SUCCESS)
910 fprintf (stderr, _("Try `%s --help' for more information.\n"),
914 printf (_("Usage: %s [OPTION] FILE...\n"), program_name);
916 Display file or file system status.\n\
918 -L, --dereference follow links\n\
919 -f, --file-system display file system status instead of file status\n\
922 -c --format=FORMAT use the specified FORMAT instead of the default;\n\
923 output a newline after each use of FORMAT\n\
924 --printf=FORMAT like --format, but interpret backslash escapes,\n\
925 and do not output a mandatory trailing newline.\n\
926 If you want a newline, include \\n in FORMAT.\n\
927 -t, --terse print the information in terse form\n\
929 fputs (HELP_OPTION_DESCRIPTION, stdout);
930 fputs (VERSION_OPTION_DESCRIPTION, stdout);
933 The valid format sequences for files (without --file-system):\n\
935 %a Access rights in octal\n\
936 %A Access rights in human readable form\n\
937 %b Number of blocks allocated (see %B)\n\
938 %B The size in bytes of each block reported by %b\n\
939 %C SELinux security context string\n\
942 %d Device number in decimal\n\
943 %D Device number in hex\n\
944 %f Raw mode in hex\n\
946 %g Group ID of owner\n\
947 %G Group name of owner\n\
950 %h Number of hard links\n\
953 %N Quoted file name with dereference if symbolic link\n\
955 %s Total size, in bytes\n\
956 %t Major device type in hex\n\
957 %T Minor device type in hex\n\
960 %u User ID of owner\n\
961 %U User name of owner\n\
962 %x Time of last access\n\
963 %X Time of last access as seconds since Epoch\n\
964 %y Time of last modification\n\
965 %Y Time of last modification as seconds since Epoch\n\
966 %z Time of last change\n\
967 %Z Time of last change as seconds since Epoch\n\
972 Valid format sequences for file systems:\n\
974 %a Free blocks available to non-superuser\n\
975 %b Total data blocks in file system\n\
976 %c Total file nodes in file system\n\
977 %d Free file nodes in file system\n\
978 %f Free blocks in file system\n\
979 %C SELinux security context string\n\
982 %i File System ID in hex\n\
983 %l Maximum length of filenames\n\
985 %s Block size (for faster transfers)\n\
986 %S Fundamental block size (for block counts)\n\
988 %T Type in human readable form\n\
990 printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
991 emit_bug_reporting_address ();
997 main (int argc, char *argv[])
1003 char *format = NULL;
1006 initialize_main (&argc, &argv);
1007 set_program_name (argv[0]);
1008 setlocale (LC_ALL, "");
1009 bindtextdomain (PACKAGE, LOCALEDIR);
1010 textdomain (PACKAGE);
1012 atexit (close_stdout);
1014 while ((c = getopt_long (argc, argv, "c:fLtZ", long_options, NULL)) != -1)
1020 interpret_backslash_escapes = true;
1021 trailing_delim = "";
1026 interpret_backslash_escapes = false;
1027 trailing_delim = "\n";
1031 follow_links = true;
1042 case 'Z': /* FIXME: remove in 2010 */
1043 /* Ignore, for compatibility with distributions
1044 that implemented this before upstream.
1045 But warn of impending removal. */
1047 _("the --context (-Z) option is obsolete and will be removed\n"
1048 "in a future release"));
1051 case_GETOPT_HELP_CHAR;
1053 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1056 usage (EXIT_FAILURE);
1062 error (0, 0, _("missing operand"));
1063 usage (EXIT_FAILURE);
1066 for (i = optind; i < argc; i++)
1068 ? do_statfs (argv[i], terse, format)
1069 : do_stat (argv[i], terse, format));
1071 exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);