1 /* stat.c -- display file or file system status
2 Copyright (C) 2001-2010 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_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>
61 #include "areadlink.h"
63 #include "file-type.h"
69 #include "stat-time.h"
73 # define STRUCT_STATVFS struct statvfs
74 # define STRUCT_STATXFS_F_FSID_IS_INTEGER STRUCT_STATVFS_F_FSID_IS_INTEGER
75 # define HAVE_STRUCT_STATXFS_F_TYPE HAVE_STRUCT_STATVFS_F_TYPE
76 # if HAVE_STRUCT_STATVFS_F_NAMEMAX
77 # define SB_F_NAMEMAX(S) ((S)->f_namemax)
79 # define STATFS statvfs
80 # define STATFS_FRSIZE(S) ((S)->f_frsize)
82 # define HAVE_STRUCT_STATXFS_F_TYPE HAVE_STRUCT_STATFS_F_TYPE
83 # if HAVE_STRUCT_STATFS_F_NAMELEN
84 # define SB_F_NAMEMAX(S) ((S)->f_namelen)
86 # define STATFS statfs
87 # if HAVE_OS_H /* BeOS */
88 /* BeOS has a statvfs function, but it does not return sensible values
89 for f_files, f_ffree and f_favail, and lacks f_type, f_basetype and
90 f_fstypename. Use 'struct fs_info' instead. */
91 static int ATTRIBUTE_WARN_UNUSED_RESULT
92 statfs (char const *filename
, struct fs_info
*buf
)
94 dev_t device
= dev_for_path (filename
);
97 errno
= (device
== B_ENTRY_NOT_FOUND
? ENOENT
98 : device
== B_BAD_VALUE
? EINVAL
99 : device
== B_NAME_TOO_LONG
? ENAMETOOLONG
100 : device
== B_NO_MEMORY
? ENOMEM
101 : device
== B_FILE_ERROR
? EIO
105 /* If successful, buf->dev will be == device. */
106 return fs_stat_dev (device
, buf
);
109 # define f_blocks total_blocks
110 # define f_bfree free_blocks
111 # define f_bavail free_blocks
112 # define f_bsize io_size
113 # define f_files total_nodes
114 # define f_ffree free_nodes
115 # define STRUCT_STATVFS struct fs_info
116 # define STRUCT_STATXFS_F_FSID_IS_INTEGER true
117 # define STATFS_FRSIZE(S) ((S)->block_size)
119 # define STRUCT_STATVFS struct statfs
120 # define STRUCT_STATXFS_F_FSID_IS_INTEGER STRUCT_STATFS_F_FSID_IS_INTEGER
121 # define STATFS_FRSIZE(S) 0
126 # define OUT_NAMEMAX out_uint
128 /* NetBSD 1.5.2 has neither f_namemax nor f_namelen. */
129 # define SB_F_NAMEMAX(S) "*"
130 # define OUT_NAMEMAX out_string
133 #if HAVE_STRUCT_STATVFS_F_BASETYPE
134 # define STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME f_basetype
136 # if HAVE_STRUCT_STATVFS_F_FSTYPENAME || HAVE_STRUCT_STATFS_F_FSTYPENAME
137 # define STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME f_fstypename
138 # elif HAVE_OS_H /* BeOS */
139 # define STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME fsh_name
143 /* FIXME: these are used by printf.c, too */
144 #define isodigit(c) ('0' <= (c) && (c) <= '7')
145 #define octtobin(c) ((c) - '0')
146 #define hextobin(c) ((c) >= 'a' && (c) <= 'f' ? (c) - 'a' + 10 : \
147 (c) >= 'A' && (c) <= 'F' ? (c) - 'A' + 10 : (c) - '0')
149 #define PROGRAM_NAME "stat"
151 #define AUTHORS proper_name ("Michael Meskes")
155 PRINTF_OPTION
= CHAR_MAX
+ 1
158 static struct option
const long_options
[] =
160 {"context", no_argument
, 0, 'Z'},
161 {"dereference", no_argument
, NULL
, 'L'},
162 {"file-system", no_argument
, NULL
, 'f'},
163 {"format", required_argument
, NULL
, 'c'},
164 {"printf", required_argument
, NULL
, PRINTF_OPTION
},
165 {"terse", no_argument
, NULL
, 't'},
166 {GETOPT_HELP_OPTION_DECL
},
167 {GETOPT_VERSION_OPTION_DECL
},
171 /* Whether to follow symbolic links; True for --dereference (-L). */
172 static bool follow_links
;
174 /* Whether to interpret backslash-escape sequences.
175 True for --printf=FMT, not for --format=FMT (-c). */
176 static bool interpret_backslash_escapes
;
178 /* The trailing delimiter string:
179 "" for --printf=FMT, "\n" for --format=FMT (-c). */
180 static char const *trailing_delim
= "";
182 /* Return the type of the specified file system.
183 Some systems have statfvs.f_basetype[FSTYPSZ] (AIX, HP-UX, and Solaris).
184 Others have statvfs.f_fstypename[_VFS_NAMELEN] (NetBSD 3.0).
185 Others have statfs.f_fstypename[MFSNAMELEN] (NetBSD 1.5.2).
186 Still others have neither and have to get by with f_type (GNU/Linux).
187 But f_type may only exist in statfs (Cygwin). */
188 static char const * ATTRIBUTE_WARN_UNUSED_RESULT
189 human_fstype (STRUCT_STATVFS
const *statfsbuf
)
191 #ifdef STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME
192 return statfsbuf
->STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME
;
194 switch (statfsbuf
->f_type
)
196 # if defined __linux__
198 /* Compare with what's in libc:
199 f=/a/libc/sysdeps/unix/sysv/linux/linux_fsinfo.h
200 sed -n '/ADFS_SUPER_MAGIC/,/SYSFS_MAGIC/p' $f \
201 | perl -n -e '/#define (.*?)_(?:SUPER_)MAGIC\s+0x(\S+)/' \
202 -e 'and print "case S_MAGIC_$1: /\* 0x" . uc($2) . " *\/\n"' \
204 perl -ne '/^\s+(case S_MAGIC_.*?): \/\* 0x(\S+) \*\//' \
205 -e 'and do { $v=uc$2; print "$1: /\* 0x$v *\/\n"}' stat.c \
207 diff -u sym_stat sym_libc
210 /* Also compare with the list in "man 2 statfs" using the
211 fs-magic-compare make target. */
213 /* IMPORTANT NOTE: Each of the following `case S_MAGIC_...:'
214 statements must be followed by a hexadecimal constant in
215 a comment. The S_MAGIC_... name and constant are automatically
216 combined to produce the #define directives in fs.h. */
218 case S_MAGIC_ADFS
: /* 0xADF5 */
220 case S_MAGIC_AFFS
: /* 0xADFF */
222 case S_MAGIC_AFS
: /* 0x5346414F */
224 case S_MAGIC_ANON_INODE_FS
: /* 0x09041934 */
225 return "anon-inode FS";
226 case S_MAGIC_AUTOFS
: /* 0x0187 */
228 case S_MAGIC_BEFS
: /* 0x42465331 */
230 case S_MAGIC_BFS
: /* 0x1BADFACE */
232 case S_MAGIC_BINFMT_MISC
: /* 0x42494E4D */
233 return "binfmt_misc";
234 case S_MAGIC_BTRFS
: /* 0x9123683E */
236 case S_MAGIC_CGROUP
: /* 0x0027E0EB */
238 case S_MAGIC_CIFS
: /* 0xFF534D42 */
240 case S_MAGIC_CODA
: /* 0x73757245 */
242 case S_MAGIC_COH
: /* 0x012FF7B7 */
244 case S_MAGIC_CRAMFS
: /* 0x28CD3D45 */
246 case S_MAGIC_CRAMFS_WEND
: /* 0x453DCD28 */
247 return "cramfs-wend";
248 case S_MAGIC_DEBUGFS
: /* 0x64626720 */
250 case S_MAGIC_DEVFS
: /* 0x1373 */
252 case S_MAGIC_DEVPTS
: /* 0x1CD1 */
254 case S_MAGIC_EFS
: /* 0x00414A53 */
256 case S_MAGIC_EXT
: /* 0x137D */
258 case S_MAGIC_EXT2
: /* 0xEF53 */
260 case S_MAGIC_EXT2_OLD
: /* 0xEF51 */
262 case S_MAGIC_FAT
: /* 0x4006 */
264 case S_MAGIC_FUSEBLK
: /* 0x65735546 */
266 case S_MAGIC_FUSECTL
: /* 0x65735543 */
268 case S_MAGIC_FUTEXFS
: /* 0x0BAD1DEA */
270 case S_MAGIC_GFS
: /* 0x1161970 */
272 case S_MAGIC_HFS
: /* 0x4244 */
274 case S_MAGIC_HPFS
: /* 0xF995E849 */
276 case S_MAGIC_HUGETLBFS
: /* 0x958458F6 */
278 case S_MAGIC_INOTIFYFS
: /* 0x2BAD1DEA */
280 case S_MAGIC_ISOFS
: /* 0x9660 */
282 case S_MAGIC_ISOFS_R_WIN
: /* 0x4004 */
284 case S_MAGIC_ISOFS_WIN
: /* 0x4000 */
286 case S_MAGIC_JFFS
: /* 0x07C0 */
288 case S_MAGIC_JFFS2
: /* 0x72B6 */
290 case S_MAGIC_JFS
: /* 0x3153464A */
292 case S_MAGIC_KAFS
: /* 0x6B414653 */
294 case S_MAGIC_LUSTRE
: /* 0x0BD00BD0 */
296 case S_MAGIC_MINIX
: /* 0x137F */
298 case S_MAGIC_MINIX_30
: /* 0x138F */
299 return "minix (30 char.)";
300 case S_MAGIC_MINIX_V2
: /* 0x2468 */
302 case S_MAGIC_MINIX_V2_30
: /* 0x2478 */
303 return "minix v2 (30 char.)";
304 case S_MAGIC_MINIX_V3
: /* 0x4D5A */
306 case S_MAGIC_MSDOS
: /* 0x4D44 */
308 case S_MAGIC_NCP
: /* 0x564C */
310 case S_MAGIC_NFS
: /* 0x6969 */
312 case S_MAGIC_NFSD
: /* 0x6E667364 */
314 case S_MAGIC_NILFS
: /* 0x3434 */
316 case S_MAGIC_NTFS
: /* 0x5346544E */
318 case S_MAGIC_OPENPROM
: /* 0x9FA1 */
320 case S_MAGIC_OCFS2
: /* 0x7461636f */
322 case S_MAGIC_PROC
: /* 0x9FA0 */
324 case S_MAGIC_QNX4
: /* 0x002F */
326 case S_MAGIC_RAMFS
: /* 0x858458F6 */
328 case S_MAGIC_REISERFS
: /* 0x52654973 */
330 case S_MAGIC_ROMFS
: /* 0x7275 */
332 case S_MAGIC_RPC_PIPEFS
: /* 0x67596969 */
334 case S_MAGIC_SECURITYFS
: /* 0x73636673 */
336 case S_MAGIC_SELINUX
: /* 0xF97CFF8C */
338 case S_MAGIC_SMB
: /* 0x517B */
340 case S_MAGIC_SOCKFS
: /* 0x534F434B */
342 case S_MAGIC_SQUASHFS
: /* 0x73717368 */
344 case S_MAGIC_SYSFS
: /* 0x62656572 */
346 case S_MAGIC_SYSV2
: /* 0x012FF7B6 */
348 case S_MAGIC_SYSV4
: /* 0x012FF7B5 */
350 case S_MAGIC_TMPFS
: /* 0x01021994 */
352 case S_MAGIC_UDF
: /* 0x15013346 */
354 case S_MAGIC_UFS
: /* 0x00011954 */
356 case S_MAGIC_UFS_BYTESWAPPED
: /* 0x54190100 */
358 case S_MAGIC_USBDEVFS
: /* 0x9FA2 */
360 case S_MAGIC_VXFS
: /* 0xA501FCF5 */
362 case S_MAGIC_XENFS
: /* 0xABBA1974 */
364 case S_MAGIC_XENIX
: /* 0x012FF7B4 */
366 case S_MAGIC_XFS
: /* 0x58465342 */
368 case S_MAGIC_XIAFS
: /* 0x012FD16D */
429 unsigned long int type
= statfsbuf
->f_type
;
430 static char buf
[sizeof "UNKNOWN (0x%lx)" - 3
431 + (sizeof type
* CHAR_BIT
+ 3) / 4];
432 sprintf (buf
, "UNKNOWN (0x%lx)", type
);
439 static char * ATTRIBUTE_WARN_UNUSED_RESULT
440 human_access (struct stat
const *statbuf
)
442 static char modebuf
[12];
443 filemodestring (statbuf
, modebuf
);
448 static char * ATTRIBUTE_WARN_UNUSED_RESULT
449 human_time (struct timespec t
)
451 static char str
[MAX (INT_BUFSIZE_BOUND (intmax_t),
452 (INT_STRLEN_BOUND (int) /* YYYY */
453 + 1 /* because YYYY might equal INT_MAX + 1900 */
454 + sizeof "-MM-DD HH:MM:SS.NNNNNNNNN +ZZZZ"))];
455 struct tm
const *tm
= localtime (&t
.tv_sec
);
457 return timetostr (t
.tv_sec
, str
);
458 nstrftime (str
, sizeof str
, "%Y-%m-%d %H:%M:%S.%N %z", tm
, 0, t
.tv_nsec
);
463 out_string (char *pformat
, size_t prefix_len
, char const *arg
)
465 strcpy (pformat
+ prefix_len
, "s");
466 printf (pformat
, arg
);
469 out_int (char *pformat
, size_t prefix_len
, intmax_t arg
)
471 strcpy (pformat
+ prefix_len
, PRIdMAX
);
472 printf (pformat
, arg
);
475 out_uint (char *pformat
, size_t prefix_len
, uintmax_t arg
)
477 strcpy (pformat
+ prefix_len
, PRIuMAX
);
478 printf (pformat
, arg
);
481 out_uint_o (char *pformat
, size_t prefix_len
, uintmax_t arg
)
483 strcpy (pformat
+ prefix_len
, PRIoMAX
);
484 printf (pformat
, arg
);
487 out_uint_x (char *pformat
, size_t prefix_len
, uintmax_t arg
)
489 strcpy (pformat
+ prefix_len
, PRIxMAX
);
490 printf (pformat
, arg
);
493 /* Very specialized function (modifies FORMAT), just so as to avoid
494 duplicating this code between both print_statfs and print_stat.
495 Return zero upon success, nonzero upon failure. */
496 static bool ATTRIBUTE_WARN_UNUSED_RESULT
497 out_file_context (char const *filename
, char *pformat
, size_t prefix_len
)
503 ? getfilecon (filename
, &scontext
)
504 : lgetfilecon (filename
, &scontext
)) < 0)
506 error (0, errno
, _("failed to get security context of %s"),
511 strcpy (pformat
+ prefix_len
, "s");
512 printf (pformat
, (scontext
? scontext
: "?"));
518 /* Print statfs info. Return zero upon success, nonzero upon failure. */
519 static bool ATTRIBUTE_WARN_UNUSED_RESULT
520 print_statfs (char *pformat
, size_t prefix_len
, char m
, char const *filename
,
523 STRUCT_STATVFS
const *statfsbuf
= data
;
529 out_string (pformat
, prefix_len
, filename
);
534 #if STRUCT_STATXFS_F_FSID_IS_INTEGER
535 uintmax_t fsid
= statfsbuf
->f_fsid
;
537 typedef unsigned int fsid_word
;
538 verify (alignof (STRUCT_STATVFS
) % alignof (fsid_word
) == 0);
539 verify (offsetof (STRUCT_STATVFS
, f_fsid
) % alignof (fsid_word
) == 0);
540 verify (sizeof statfsbuf
->f_fsid
% alignof (fsid_word
) == 0);
541 fsid_word
const *p
= (fsid_word
*) &statfsbuf
->f_fsid
;
543 /* Assume a little-endian word order, as that is compatible
544 with glibc's statvfs implementation. */
546 int words
= sizeof statfsbuf
->f_fsid
/ sizeof *p
;
548 for (i
= 0; i
< words
&& i
* sizeof *p
< sizeof fsid
; i
++)
550 uintmax_t u
= p
[words
- 1 - i
];
551 fsid
|= u
<< (i
* CHAR_BIT
* sizeof *p
);
554 out_uint_x (pformat
, prefix_len
, fsid
);
559 OUT_NAMEMAX (pformat
, prefix_len
, SB_F_NAMEMAX (statfsbuf
));
562 #if HAVE_STRUCT_STATXFS_F_TYPE
563 out_uint_x (pformat
, prefix_len
, statfsbuf
->f_type
);
569 out_string (pformat
, prefix_len
, human_fstype (statfsbuf
));
572 out_int (pformat
, prefix_len
, statfsbuf
->f_blocks
);
575 out_int (pformat
, prefix_len
, statfsbuf
->f_bfree
);
578 out_int (pformat
, prefix_len
, statfsbuf
->f_bavail
);
581 out_uint (pformat
, prefix_len
, statfsbuf
->f_bsize
);
585 uintmax_t frsize
= STATFS_FRSIZE (statfsbuf
);
587 frsize
= statfsbuf
->f_bsize
;
588 out_uint (pformat
, prefix_len
, frsize
);
592 out_uint (pformat
, prefix_len
, statfsbuf
->f_files
);
595 out_int (pformat
, prefix_len
, statfsbuf
->f_ffree
);
598 fail
|= out_file_context (filename
, pformat
, prefix_len
);
607 /* Print stat info. Return zero upon success, nonzero upon failure. */
609 print_stat (char *pformat
, size_t prefix_len
, char m
,
610 char const *filename
, void const *data
)
612 struct stat
*statbuf
= (struct stat
*) data
;
613 struct passwd
*pw_ent
;
614 struct group
*gw_ent
;
620 out_string (pformat
, prefix_len
, filename
);
623 out_string (pformat
, prefix_len
, quote (filename
));
624 if (S_ISLNK (statbuf
->st_mode
))
626 char *linkname
= areadlink_with_size (filename
, statbuf
->st_size
);
627 if (linkname
== NULL
)
629 error (0, errno
, _("cannot read symbolic link %s"),
634 out_string (pformat
, prefix_len
, quote (linkname
));
639 out_uint (pformat
, prefix_len
, statbuf
->st_dev
);
642 out_uint_x (pformat
, prefix_len
, statbuf
->st_dev
);
645 out_uint (pformat
, prefix_len
, statbuf
->st_ino
);
648 out_uint_o (pformat
, prefix_len
, statbuf
->st_mode
& CHMOD_MODE_BITS
);
651 out_string (pformat
, prefix_len
, human_access (statbuf
));
654 out_uint_x (pformat
, prefix_len
, statbuf
->st_mode
);
657 out_string (pformat
, prefix_len
, file_type (statbuf
));
660 out_uint (pformat
, prefix_len
, statbuf
->st_nlink
);
663 out_uint (pformat
, prefix_len
, statbuf
->st_uid
);
667 pw_ent
= getpwuid (statbuf
->st_uid
);
668 out_string (pformat
, prefix_len
,
669 pw_ent
? pw_ent
->pw_name
: "UNKNOWN");
672 out_uint (pformat
, prefix_len
, statbuf
->st_gid
);
676 gw_ent
= getgrgid (statbuf
->st_gid
);
677 out_string (pformat
, prefix_len
,
678 gw_ent
? gw_ent
->gr_name
: "UNKNOWN");
681 out_uint_x (pformat
, prefix_len
, major (statbuf
->st_rdev
));
684 out_uint_x (pformat
, prefix_len
, minor (statbuf
->st_rdev
));
687 out_uint (pformat
, prefix_len
, statbuf
->st_size
);
690 out_uint (pformat
, prefix_len
, ST_NBLOCKSIZE
);
693 out_uint (pformat
, prefix_len
, ST_NBLOCKS (*statbuf
));
696 out_uint (pformat
, prefix_len
, statbuf
->st_blksize
);
699 out_string (pformat
, prefix_len
, human_time (get_stat_atime (statbuf
)));
702 if (TYPE_SIGNED (time_t))
703 out_int (pformat
, prefix_len
, statbuf
->st_atime
);
705 out_uint (pformat
, prefix_len
, statbuf
->st_atime
);
708 out_string (pformat
, prefix_len
, human_time (get_stat_mtime (statbuf
)));
711 if (TYPE_SIGNED (time_t))
712 out_int (pformat
, prefix_len
, statbuf
->st_mtime
);
714 out_uint (pformat
, prefix_len
, statbuf
->st_mtime
);
717 out_string (pformat
, prefix_len
, human_time (get_stat_ctime (statbuf
)));
720 if (TYPE_SIGNED (time_t))
721 out_int (pformat
, prefix_len
, statbuf
->st_ctime
);
723 out_uint (pformat
, prefix_len
, statbuf
->st_ctime
);
726 fail
|= out_file_context (filename
, pformat
, prefix_len
);
735 /* Output a single-character \ escape. */
738 print_esc_char (char c
)
742 case 'a': /* Alert. */
745 case 'b': /* Backspace. */
748 case 'e': /* Escape. */
751 case 'f': /* Form feed. */
754 case 'n': /* New line. */
757 case 'r': /* Carriage return. */
760 case 't': /* Horizontal tab. */
763 case 'v': /* Vertical tab. */
770 error (0, 0, _("warning: unrecognized escape `\\%c'"), c
);
776 /* Print the information specified by the format string, FORMAT,
777 calling PRINT_FUNC for each %-directive encountered.
778 Return zero upon success, nonzero upon failure. */
779 static bool ATTRIBUTE_WARN_UNUSED_RESULT
780 print_it (char const *format
, char const *filename
,
781 bool (*print_func
) (char *, size_t, char, char const *, void const *),
786 /* Add 2 to accommodate our conversion of the stat `%s' format string
787 to the longer printf `%llu' one. */
790 MAX_ADDITIONAL_BYTES
=
791 (MAX (sizeof PRIdMAX
,
792 MAX (sizeof PRIoMAX
, MAX (sizeof PRIuMAX
, sizeof PRIxMAX
)))
795 size_t n_alloc
= strlen (format
) + MAX_ADDITIONAL_BYTES
+ 1;
796 char *dest
= xmalloc (n_alloc
);
798 for (b
= format
; *b
; b
++)
804 size_t len
= strspn (b
+ 1, "#-+.I 0123456789");
805 char const *fmt_char
= b
+ len
+ 1;
806 memcpy (dest
, b
, len
+ 1);
817 dest
[len
+ 1] = *fmt_char
;
818 dest
[len
+ 2] = '\0';
819 error (EXIT_FAILURE
, 0, _("%s: invalid directive"),
820 quotearg_colon (dest
));
825 fail
|= print_func (dest
, len
+ 1, *fmt_char
, filename
, data
);
832 if ( ! interpret_backslash_escapes
)
840 int esc_value
= octtobin (*b
);
841 int esc_length
= 1; /* number of octal digits */
842 for (++b
; esc_length
< 3 && isodigit (*b
);
845 esc_value
= esc_value
* 8 + octtobin (*b
);
850 else if (*b
== 'x' && isxdigit (to_uchar (b
[1])))
852 int esc_value
= hextobin (b
[1]); /* Value of \xhh escape. */
853 /* A hexadecimal \xhh escape sequence must have
854 1 or 2 hex. digits. */
856 if (isxdigit (to_uchar (b
[1])))
859 esc_value
= esc_value
* 16 + hextobin (*b
);
865 error (0, 0, _("warning: backslash at end of format"));
867 /* Arrange to exit the loop. */
883 fputs (trailing_delim
, stdout
);
888 /* Stat the file system and print what we find. */
889 static bool ATTRIBUTE_WARN_UNUSED_RESULT
890 do_statfs (char const *filename
, bool terse
, char const *format
)
892 STRUCT_STATVFS statfsbuf
;
894 if (STREQ (filename
, "-"))
896 error (0, 0, _("using %s to denote standard input does not work"
897 " in file system mode"), quote (filename
));
901 if (STATFS (filename
, &statfsbuf
) != 0)
903 error (0, errno
, _("cannot read file system information for %s"),
911 ? "%n %i %l %t %s %S %b %f %a %c %d\n"
913 " ID: %-8i Namelen: %-7l Type: %T\n"
914 "Block size: %-10s Fundamental block size: %S\n"
915 "Blocks: Total: %-10b Free: %-10f Available: %a\n"
916 "Inodes: Total: %-10c Free: %d\n");
919 bool fail
= print_it (format
, filename
, print_statfs
, &statfsbuf
);
923 /* stat the file and print what we find */
924 static bool ATTRIBUTE_WARN_UNUSED_RESULT
925 do_stat (char const *filename
, bool terse
, char const *format
)
929 if (STREQ (filename
, "-"))
931 if (fstat (STDIN_FILENO
, &statbuf
) != 0)
933 error (0, errno
, _("cannot stat standard input"));
937 /* We can't use the shorter
938 (follow_links?stat:lstat) (filename, &statbug)
939 since stat might be a function-like macro. */
940 else if ((follow_links
941 ? stat (filename
, &statbuf
)
942 : lstat (filename
, &statbuf
)) != 0)
944 error (0, errno
, _("cannot stat %s"), quote (filename
));
952 format
= "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o\n";
956 /* Temporary hack to match original output until conditional
958 if (S_ISBLK (statbuf
.st_mode
) || S_ISCHR (statbuf
.st_mode
))
962 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
963 "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
964 " Device type: %t,%T\n"
965 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
966 "Access: %x\n" "Modify: %y\n" "Change: %z\n";
972 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
973 "Device: %Dh/%dd\tInode: %-10i Links: %h\n"
974 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
975 "Access: %x\n" "Modify: %y\n" "Change: %z\n";
979 bool fail
= print_it (format
, filename
, print_stat
, &statbuf
);
986 if (status
!= EXIT_SUCCESS
)
987 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
991 printf (_("Usage: %s [OPTION]... FILE...\n"), program_name
);
993 Display file or file system status.\n\
995 -L, --dereference follow links\n\
996 -f, --file-system display file system status instead of file status\n\
999 -c --format=FORMAT use the specified FORMAT instead of the default;\n\
1000 output a newline after each use of FORMAT\n\
1001 --printf=FORMAT like --format, but interpret backslash escapes,\n\
1002 and do not output a mandatory trailing newline.\n\
1003 If you want a newline, include \\n in FORMAT\n\
1004 -t, --terse print the information in terse form\n\
1006 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
1007 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
1010 The valid format sequences for files (without --file-system):\n\
1012 %a Access rights in octal\n\
1013 %A Access rights in human readable form\n\
1014 %b Number of blocks allocated (see %B)\n\
1015 %B The size in bytes of each block reported by %b\n\
1016 %C SELinux security context string\n\
1019 %d Device number in decimal\n\
1020 %D Device number in hex\n\
1021 %f Raw mode in hex\n\
1023 %g Group ID of owner\n\
1024 %G Group name of owner\n\
1027 %h Number of hard links\n\
1030 %N Quoted file name with dereference if symbolic link\n\
1031 %o I/O block size\n\
1032 %s Total size, in bytes\n\
1033 %t Major device type in hex\n\
1034 %T Minor device type in hex\n\
1037 %u User ID of owner\n\
1038 %U User name of owner\n\
1039 %x Time of last access\n\
1040 %X Time of last access as seconds since Epoch\n\
1041 %y Time of last modification\n\
1042 %Y Time of last modification as seconds since Epoch\n\
1043 %z Time of last change\n\
1044 %Z Time of last change as seconds since Epoch\n\
1049 Valid format sequences for file systems:\n\
1051 %a Free blocks available to non-superuser\n\
1052 %b Total data blocks in file system\n\
1053 %c Total file nodes in file system\n\
1054 %d Free file nodes in file system\n\
1055 %f Free blocks in file system\n\
1056 %C SELinux security context string\n\
1059 %i File System ID in hex\n\
1060 %l Maximum length of filenames\n\
1062 %s Block size (for faster transfers)\n\
1063 %S Fundamental block size (for block counts)\n\
1065 %T Type in human readable form\n\
1067 printf (USAGE_BUILTIN_WARNING
, PROGRAM_NAME
);
1068 emit_ancillary_info ();
1074 main (int argc
, char *argv
[])
1080 char *format
= NULL
;
1083 initialize_main (&argc
, &argv
);
1084 set_program_name (argv
[0]);
1085 setlocale (LC_ALL
, "");
1086 bindtextdomain (PACKAGE
, LOCALEDIR
);
1087 textdomain (PACKAGE
);
1089 atexit (close_stdout
);
1091 while ((c
= getopt_long (argc
, argv
, "c:fLt", long_options
, NULL
)) != -1)
1097 interpret_backslash_escapes
= true;
1098 trailing_delim
= "";
1103 interpret_backslash_escapes
= false;
1104 trailing_delim
= "\n";
1108 follow_links
= true;
1119 case_GETOPT_HELP_CHAR
;
1121 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
1124 usage (EXIT_FAILURE
);
1130 error (0, 0, _("missing operand"));
1131 usage (EXIT_FAILURE
);
1134 for (i
= optind
; i
< argc
; i
++)
1136 ? do_statfs (argv
[i
], terse
, format
)
1137 : do_stat (argv
[i
], terse
, format
));
1139 exit (ok
? EXIT_SUCCESS
: EXIT_FAILURE
);