/* stat.c -- display file or file system status This is the stat utility
Copyright (C) 2001-2018 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Written by Michael Meskes. */ The GNUv3 license
#include <config.h> Provides system specific information
/* Keep this conditional in sync with the similar conditional in
../m4/stat-prog.m4. */
#if ((STAT_STATVFS || STAT_STATVFS64) \ Line 23
&& (HAVE_STRUCT_STATVFS_F_BASETYPE || HAVE_STRUCT_STATVFS_F_FSTYPENAME \ Line 24
|| (! HAVE_STRUCT_STATFS_F_FSTYPENAME && HAVE_STRUCT_STATVFS_F_TYPE))) Line 25
# define USE_STATVFS 1 Line 26
#else Line 27
# define USE_STATVFS 0 Line 28
#endif Line 29
#include <stddef.h> ...!includes auto-comment...
#include <stdio.h> Provides standard I/O capability
#include <stdalign.h> ...!includes auto-comment...
#include <sys/types.h> Provides system data types
#include <pwd.h> ...!includes auto-comment...
#include <grp.h> ...!includes auto-comment...
#if USE_STATVFS Line 37
# include <sys/statvfs.h> ...!includes auto-comment...
#elif HAVE_SYS_VFS_H Line 39
# include <sys/vfs.h> ...!includes auto-comment...
#elif HAVE_SYS_MOUNT_H && HAVE_SYS_PARAM_H Line 41
/* NOTE: freebsd5.0 needs sys/param.h and sys/mount.h for statfs.
It does have statvfs.h, but shouldn't use it, since it doesn't
HAVE_STRUCT_STATVFS_F_BASETYPE. So find a clean way to fix it. */
/* NetBSD 1.5.2 needs these, for the declaration of struct statfs. */
# include <sys/param.h> Line 46
# include <sys/mount.h> Line 47
# if HAVE_NFS_NFS_CLNT_H && HAVE_NFS_VFS_H Line 48
/* Ultrix 4.4 needs these for the declaration of struct statfs. */
# include <netinet/in.h> Line 50
# include <nfs/nfs_clnt.h> Line 51
# include <nfs/vfs.h> ...!includes auto-comment...
# endif Line 53
#elif HAVE_OS_H /* BeOS */ Line 54
# include <fs_info.h> Line 55
#endif Line 56
#include <selinux/selinux.h> ...!includes auto-comment......!includes auto-comment...
#include "system.h" ...!includes auto-comment...
#include "areadlink.h" ...!includes auto-comment...
#include "argmatch.h" ...!includes auto-comment...
#include "die.h" ...!includes auto-comment...
#include "error.h" ...!includes auto-comment...
#include "file-type.h" ...!includes auto-comment...
#include "filemode.h" ...!includes auto-comment...
#include "fs.h" ...!includes auto-comment...
#include "getopt.h" ...!includes auto-comment...
#include "mountlist.h" ...!includes auto-comment...
#include "quote.h" ...!includes auto-comment...
#include "stat-size.h" ...!includes auto-comment...
#include "stat-time.h" ...!includes auto-comment...
#include "strftime.h" ...!includes auto-comment...
#include "find-mount-point.h" ...!includes auto-comment...
#include "xvasprintf.h" ...!includes auto-comment...
#if USE_STATVFS Line 77
# define STRUCT_STATXFS_F_FSID_IS_INTEGER STRUCT_STATVFS_F_FSID_IS_INTEGER Line 78
# define HAVE_STRUCT_STATXFS_F_TYPE HAVE_STRUCT_STATVFS_F_TYPE Line 79
# if HAVE_STRUCT_STATVFS_F_NAMEMAX Line 80
# define SB_F_NAMEMAX(S) ((S)->f_namemax) Line 81
# endif Line 82
# if ! STAT_STATVFS && STAT_STATVFS64 Line 83
# define STRUCT_STATVFS struct statvfs64 Line 84
# define STATFS statvfs64 Line 85
# else Line 86
# define STRUCT_STATVFS struct statvfs Line 87
# define STATFS statvfs Line 88
# endif Line 89
# define STATFS_FRSIZE(S) ((S)->f_frsize) Line 90
#else Line 91
# define HAVE_STRUCT_STATXFS_F_TYPE HAVE_STRUCT_STATFS_F_TYPE Line 92
# if HAVE_STRUCT_STATFS_F_NAMELEN Line 93
# define SB_F_NAMEMAX(S) ((S)->f_namelen) Line 94
# elif HAVE_STRUCT_STATFS_F_NAMEMAX Line 95
# define SB_F_NAMEMAX(S) ((S)->f_namemax) Line 96
# endif Line 97
# define STATFS statfs Line 98
# if HAVE_OS_H /* BeOS */ Line 99
/* BeOS has a statvfs function, but it does not return sensible values
for f_files, f_ffree and f_favail, and lacks f_type, f_basetype and
f_fstypename. Use 'struct fs_info' instead. */
static int ATTRIBUTE_WARN_UNUSED_RESULT Line 103
statfs (char const *filename, struct fs_info *buf) Line 104
{
dev_t device = dev_for_path (filename); Line 106
if (device < 0) Line 107
{
errno = (device == B_ENTRY_NOT_FOUND ? ENOENT Line 109
: device == B_BAD_VALUE ? EINVAL Line 110
: device == B_NAME_TOO_LONG ? ENAMETOOLONG Line 111
: device == B_NO_MEMORY ? ENOMEM Line 112
: device == B_FILE_ERROR ? EIO Line 113
: 0); Line 114
return -1; Line 115
}
/* If successful, buf->dev will be == device. */
return fs_stat_dev (device, buf); Line 118
} Block 1
# define f_fsid dev Line 120
# define f_blocks total_blocks Line 121
# define f_bfree free_blocks Line 122
# define f_bavail free_blocks Line 123
# define f_bsize io_size Line 124
# define f_files total_nodes Line 125
# define f_ffree free_nodes Line 126
# define STRUCT_STATVFS struct fs_info Line 127
# define STRUCT_STATXFS_F_FSID_IS_INTEGER true Line 128
# define STATFS_FRSIZE(S) ((S)->block_size) Line 129
# else Line 130
# define STRUCT_STATVFS struct statfs Line 131
# define STRUCT_STATXFS_F_FSID_IS_INTEGER STRUCT_STATFS_F_FSID_IS_INTEGER Line 132
# if HAVE_STRUCT_STATFS_F_FRSIZE Line 133
# define STATFS_FRSIZE(S) ((S)->f_frsize) Line 134
# else Line 135
# define STATFS_FRSIZE(S) 0 Line 136
# endif Line 137
# endif Line 138
#endif Line 139
#ifdef SB_F_NAMEMAX Line 141
# define OUT_NAMEMAX out_uint Line 142
#else Line 143
/* Depending on whether statvfs or statfs is used,
neither f_namemax or f_namelen may be available. */
# define SB_F_NAMEMAX(S) "?" Line 146
# define OUT_NAMEMAX out_string Line 147
#endif Line 148
#if HAVE_STRUCT_STATVFS_F_BASETYPE Line 150
# define STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME f_basetype Line 151
#else Line 152
# if HAVE_STRUCT_STATVFS_F_FSTYPENAME || HAVE_STRUCT_STATFS_F_FSTYPENAME Line 153
# define STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME f_fstypename Line 154
# elif HAVE_OS_H /* BeOS */ Line 155
# define STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME fsh_name Line 156
# endif Line 157
#endif Line 158
#if HAVE_GETATTRAT Line 160
# include <attr.h> Line 161
# include <sys/nvpair.h> Line 162
#endif Line 163
/* FIXME: these are used by printf.c, too */
#define isodigit(c) ('0' <= (c) && (c) <= '7') Line 166
#define octtobin(c) ((c) - '0') Line 167
#define hextobin(c) ((c) >= 'a' && (c) <= 'f' ? (c) - 'a' + 10 : \ Line 168
(c) >= 'A' && (c) <= 'F' ? (c) - 'A' + 10 : (c) - '0') Line 169
static char const digits[] = "0123456789"; Line 171
/* Flags that are portable for use in printf, for at least one
conversion specifier; make_format removes unportable flags as
needed for particular specifiers. The glibc 2.2 extension "I" is
listed here; it is removed by make_format because it has undefined
behavior elsewhere and because it is incompatible with
out_epoch_sec. */
static char const printf_flags[] = "'-+ #0I"; Line 179
/* Formats for the --terse option. */
static char const fmt_terse_fs[] = "%n %i %l %t %s %S %b %f %a %c %d\n"; Line 182
static char const fmt_terse_regular[] = "%n %s %b %f %u %g %D %i %h %t %T" Line 183
" %X %Y %Z %W %o\n"; Line 184
static char const fmt_terse_selinux[] = "%n %s %b %f %u %g %D %i %h %t %T" Line 185
" %X %Y %Z %W %o %C\n"; Line 186
#define PROGRAM_NAME "stat" Line 188
#define AUTHORS proper_name ("Michael Meskes") Line 190
enum Line 192
{
PRINTF_OPTION = CHAR_MAX + 1 Line 194
}; Block 2
static struct option const long_options[] = Line 197
{
{"dereference", no_argument, NULL, 'L'}, Line 199
{"file-system", no_argument, NULL, 'f'}, Line 200
{"format", required_argument, NULL, 'c'}, Line 201
{"printf", required_argument, NULL, PRINTF_OPTION}, Line 202
{"terse", no_argument, NULL, 't'}, Line 203
{GETOPT_HELP_OPTION_DECL}, Line 204
{GETOPT_VERSION_OPTION_DECL}, Line 205
{NULL, 0, NULL, 0} Line 206
}; Block 3
/* Whether to follow symbolic links; True for --dereference (-L). */
static bool follow_links; Line 210
/* Whether to interpret backslash-escape sequences.
True for --printf=FMT, not for --format=FMT (-c). */
static bool interpret_backslash_escapes; Line 214
/* The trailing delimiter string:
"" for --printf=FMT, "\n" for --format=FMT (-c). */
static char const *trailing_delim = ""; Line 218
/* The representation of the decimal point in the current locale. */
static char const *decimal_point; Line 221
static size_t decimal_point_len; Line 222
/* Return the type of the specified file system.
Some systems have statfvs.f_basetype[FSTYPSZ] (AIX, HP-UX, and Solaris).
Others have statvfs.f_fstypename[_VFS_NAMELEN] (NetBSD 3.0).
Others have statfs.f_fstypename[MFSNAMELEN] (NetBSD 1.5.2).
Still others have neither and have to get by with f_type (GNU/Linux).
But f_type may only exist in statfs (Cygwin). */
static char const * ATTRIBUTE_WARN_UNUSED_RESULT Line 230
human_fstype (STRUCT_STATVFS const *statfsbuf) Line 231
{
#ifdef STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME Line 233
return statfsbuf->STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME; Line 234
#else Line 235
switch (statfsbuf->f_type) Line 236
{
# if defined __linux__ Line 238
/* Compare with what's in libc:
f=/a/libc/sysdeps/unix/sysv/linux/linux_fsinfo.h
sed -n '/ADFS_SUPER_MAGIC/,/SYSFS_MAGIC/p' $f \
| perl -n -e '/#define (.*?)_(?:SUPER_)MAGIC\s+0x(\S+)/' \
-e 'and print "case S_MAGIC_$1: /\* 0x" . uc($2) . " *\/\n"' \
| sort > sym_libc
perl -ne '/^\s+(case S_MAGIC_.*?): \/\* 0x(\S+) \*\//' \
-e 'and do { $v=uc$2; print "$1: /\* 0x$v *\/\n"}' stat.c \
| sort > sym_stat
diff -u sym_stat sym_libc
*/
/* Also compare with the list in "man 2 statfs" using the
fs-magic-compare make target. */
/* IMPORTANT NOTE: Each of the following 'case S_MAGIC_...:'
statements must be followed by a hexadecimal constant in
a comment. The S_MAGIC_... name and constant are automatically
combined to produce the #define directives in fs.h. */
case S_MAGIC_AAFS: /* 0x5A3C69F0 local */ Line 260
return "aafs"; Line 261
case S_MAGIC_ACFS: /* 0x61636673 remote */ Line 262
return "acfs"; Line 263
case S_MAGIC_ADFS: /* 0xADF5 local */ Line 264
return "adfs"; Line 265
case S_MAGIC_AFFS: /* 0xADFF local */ Line 266
return "affs"; Line 267
case S_MAGIC_AFS: /* 0x5346414F remote */ Line 268
return "afs"; Line 269
case S_MAGIC_ANON_INODE_FS: /* 0x09041934 local */ Line 270
return "anon-inode FS"; Line 271
case S_MAGIC_AUFS: /* 0x61756673 remote */ Line 272
/* FIXME: change syntax or add an optional attribute like "inotify:no".
The above is labeled as "remote" so that tail always uses polling,
but this isn't really a remote file system type. */
return "aufs"; Line 276
case S_MAGIC_AUTOFS: /* 0x0187 local */ Line 277
return "autofs"; Line 278
case S_MAGIC_BALLOON_KVM: /* 0x13661366 local */ Line 279
return "balloon-kvm-fs"; Line 280
case S_MAGIC_BEFS: /* 0x42465331 local */ Line 281
return "befs"; Line 282
case S_MAGIC_BDEVFS: /* 0x62646576 local */ Line 283
return "bdevfs"; Line 284
case S_MAGIC_BFS: /* 0x1BADFACE local */ Line 285
return "bfs"; Line 286
case S_MAGIC_BPF_FS: /* 0xCAFE4A11 local */ Line 287
return "bpf_fs"; Line 288
case S_MAGIC_BINFMTFS: /* 0x42494E4D local */ Line 289
return "binfmt_misc"; Line 290
case S_MAGIC_BTRFS: /* 0x9123683E local */ Line 291
return "btrfs"; Line 292
case S_MAGIC_BTRFS_TEST: /* 0x73727279 local */ Line 293
return "btrfs_test"; Line 294
case S_MAGIC_CEPH: /* 0x00C36400 remote */ Line 295
return "ceph"; Line 296
case S_MAGIC_CGROUP: /* 0x0027E0EB local */ Line 297
return "cgroupfs"; Line 298
case S_MAGIC_CGROUP2: /* 0x63677270 local */ Line 299
return "cgroup2fs"; Line 300
case S_MAGIC_CIFS: /* 0xFF534D42 remote */ Line 301
return "cifs"; Line 302
case S_MAGIC_CODA: /* 0x73757245 remote */ Line 303
return "coda"; Line 304
case S_MAGIC_COH: /* 0x012FF7B7 local */ Line 305
return "coh"; Line 306
case S_MAGIC_CONFIGFS: /* 0x62656570 local */ Line 307
return "configfs"; Line 308
case S_MAGIC_CRAMFS: /* 0x28CD3D45 local */ Line 309
return "cramfs"; Line 310
case S_MAGIC_CRAMFS_WEND: /* 0x453DCD28 local */ Line 311
return "cramfs-wend"; Line 312
case S_MAGIC_DAXFS: /* 0x64646178 local */ Line 313
return "daxfs"; Line 314
case S_MAGIC_DEBUGFS: /* 0x64626720 local */ Line 315
return "debugfs"; Line 316
case S_MAGIC_DEVFS: /* 0x1373 local */ Line 317
return "devfs"; Line 318
case S_MAGIC_DEVPTS: /* 0x1CD1 local */ Line 319
return "devpts"; Line 320
case S_MAGIC_ECRYPTFS: /* 0xF15F local */ Line 321
return "ecryptfs"; Line 322
case S_MAGIC_EFIVARFS: /* 0xDE5E81E4 local */ Line 323
return "efivarfs"; Line 324
case S_MAGIC_EFS: /* 0x00414A53 local */ Line 325
return "efs"; Line 326
case S_MAGIC_EXFS: /* 0x45584653 local */ Line 327
return "exfs"; Line 328
case S_MAGIC_EXOFS: /* 0x5DF5 local */ Line 329
return "exofs"; Line 330
case S_MAGIC_EXT: /* 0x137D local */ Line 331
return "ext"; Line 332
case S_MAGIC_EXT2: /* 0xEF53 local */ Line 333
return "ext2/ext3"; Line 334
case S_MAGIC_EXT2_OLD: /* 0xEF51 local */ Line 335
return "ext2"; Line 336
case S_MAGIC_F2FS: /* 0xF2F52010 local */ Line 337
return "f2fs"; Line 338
case S_MAGIC_FAT: /* 0x4006 local */ Line 339
return "fat"; Line 340
case S_MAGIC_FHGFS: /* 0x19830326 remote */ Line 341
return "fhgfs"; Line 342
case S_MAGIC_FUSEBLK: /* 0x65735546 remote */ Line 343
return "fuseblk"; Line 344
case S_MAGIC_FUSECTL: /* 0x65735543 remote */ Line 345
return "fusectl"; Line 346
case S_MAGIC_FUTEXFS: /* 0x0BAD1DEA local */ Line 347
return "futexfs"; Line 348
case S_MAGIC_GFS: /* 0x01161970 remote */ Line 349
return "gfs/gfs2"; Line 350
case S_MAGIC_GPFS: /* 0x47504653 remote */ Line 351
return "gpfs"; Line 352
case S_MAGIC_HFS: /* 0x4244 local */ Line 353
return "hfs"; Line 354
case S_MAGIC_HFS_PLUS: /* 0x482B local */ Line 355
return "hfs+"; Line 356
case S_MAGIC_HFS_X: /* 0x4858 local */ Line 357
return "hfsx"; Line 358
case S_MAGIC_HOSTFS: /* 0x00C0FFEE local */ Line 359
return "hostfs"; Line 360
case S_MAGIC_HPFS: /* 0xF995E849 local */ Line 361
return "hpfs"; Line 362
case S_MAGIC_HUGETLBFS: /* 0x958458F6 local */ Line 363
return "hugetlbfs"; Line 364
case S_MAGIC_MTD_INODE_FS: /* 0x11307854 local */ Line 365
return "inodefs"; Line 366
case S_MAGIC_IBRIX: /* 0x013111A8 remote */ Line 367
return "ibrix"; Line 368
case S_MAGIC_INOTIFYFS: /* 0x2BAD1DEA local */ Line 369
return "inotifyfs"; Line 370
case S_MAGIC_ISOFS: /* 0x9660 local */ Line 371
return "isofs"; Line 372
case S_MAGIC_ISOFS_R_WIN: /* 0x4004 local */ Line 373
return "isofs"; Line 374
case S_MAGIC_ISOFS_WIN: /* 0x4000 local */ Line 375
return "isofs"; Line 376
case S_MAGIC_JFFS: /* 0x07C0 local */ Line 377
return "jffs"; Line 378
case S_MAGIC_JFFS2: /* 0x72B6 local */ Line 379
return "jffs2"; Line 380
case S_MAGIC_JFS: /* 0x3153464A local */ Line 381
return "jfs"; Line 382
case S_MAGIC_KAFS: /* 0x6B414653 remote */ Line 383
return "k-afs"; Line 384
case S_MAGIC_LOGFS: /* 0xC97E8168 local */ Line 385
return "logfs"; Line 386
case S_MAGIC_LUSTRE: /* 0x0BD00BD0 remote */ Line 387
return "lustre"; Line 388
case S_MAGIC_M1FS: /* 0x5346314D local */ Line 389
return "m1fs"; Line 390
case S_MAGIC_MINIX: /* 0x137F local */ Line 391
return "minix"; Line 392
case S_MAGIC_MINIX_30: /* 0x138F local */ Line 393
return "minix (30 char.)"; Line 394
case S_MAGIC_MINIX_V2: /* 0x2468 local */ Line 395
return "minix v2"; Line 396
case S_MAGIC_MINIX_V2_30: /* 0x2478 local */ Line 397
return "minix v2 (30 char.)"; Line 398
case S_MAGIC_MINIX_V3: /* 0x4D5A local */ Line 399
return "minix3"; Line 400
case S_MAGIC_MQUEUE: /* 0x19800202 local */ Line 401
return "mqueue"; Line 402
case S_MAGIC_MSDOS: /* 0x4D44 local */ Line 403
return "msdos"; Line 404
case S_MAGIC_NCP: /* 0x564C remote */ Line 405
return "novell"; Line 406
case S_MAGIC_NFS: /* 0x6969 remote */ Line 407
return "nfs"; Line 408
case S_MAGIC_NFSD: /* 0x6E667364 remote */ Line 409
return "nfsd"; Line 410
case S_MAGIC_NILFS: /* 0x3434 local */ Line 411
return "nilfs"; Line 412
case S_MAGIC_NSFS: /* 0x6E736673 local */ Line 413
return "nsfs"; Line 414
case S_MAGIC_NTFS: /* 0x5346544E local */ Line 415
return "ntfs"; Line 416
case S_MAGIC_OPENPROM: /* 0x9FA1 local */ Line 417
return "openprom"; Line 418
case S_MAGIC_OCFS2: /* 0x7461636F remote */ Line 419
return "ocfs2"; Line 420
case S_MAGIC_OVERLAYFS: /* 0x794C7630 remote */ Line 421
/* This may overlay remote file systems.
Also there have been issues reported with inotify and overlayfs,
so mark as "remote" so that polling is used. */
return "overlayfs"; Line 425
case S_MAGIC_PANFS: /* 0xAAD7AAEA remote */ Line 426
return "panfs"; Line 427
case S_MAGIC_PIPEFS: /* 0x50495045 remote */ Line 428
/* FIXME: change syntax or add an optional attribute like "inotify:no".
pipefs and prlfs are labeled as "remote" so that tail always polls,
but these aren't really remote file system types. */
return "pipefs"; Line 432
case S_MAGIC_PRL_FS: /* 0x7C7C6673 remote */ Line 433
return "prl_fs"; Line 434
case S_MAGIC_PROC: /* 0x9FA0 local */ Line 435
return "proc"; Line 436
case S_MAGIC_PSTOREFS: /* 0x6165676C local */ Line 437
return "pstorefs"; Line 438
case S_MAGIC_QNX4: /* 0x002F local */ Line 439
return "qnx4"; Line 440
case S_MAGIC_QNX6: /* 0x68191122 local */ Line 441
return "qnx6"; Line 442
case S_MAGIC_RAMFS: /* 0x858458F6 local */ Line 443
return "ramfs"; Line 444
case S_MAGIC_RDTGROUP: /* 0x07655821 local */ Line 445
return "rdt"; Line 446
case S_MAGIC_REISERFS: /* 0x52654973 local */ Line 447
return "reiserfs"; Line 448
case S_MAGIC_ROMFS: /* 0x7275 local */ Line 449
return "romfs"; Line 450
case S_MAGIC_RPC_PIPEFS: /* 0x67596969 local */ Line 451
return "rpc_pipefs"; Line 452
case S_MAGIC_SECURITYFS: /* 0x73636673 local */ Line 453
return "securityfs"; Line 454
case S_MAGIC_SELINUX: /* 0xF97CFF8C local */ Line 455
return "selinux"; Line 456
case S_MAGIC_SMACK: /* 0x43415D53 local */ Line 457
return "smackfs"; Line 458
case S_MAGIC_SMB: /* 0x517B remote */ Line 459
return "smb"; Line 460
case S_MAGIC_SMB2: /* 0xFE534D42 remote */ Line 461
return "smb2"; Line 462
case S_MAGIC_SNFS: /* 0xBEEFDEAD remote */ Line 463
return "snfs"; Line 464
case S_MAGIC_SOCKFS: /* 0x534F434B local */ Line 465
return "sockfs"; Line 466
case S_MAGIC_SQUASHFS: /* 0x73717368 local */ Line 467
return "squashfs"; Line 468
case S_MAGIC_SYSFS: /* 0x62656572 local */ Line 469
return "sysfs"; Line 470
case S_MAGIC_SYSV2: /* 0x012FF7B6 local */ Line 471
return "sysv2"; Line 472
case S_MAGIC_SYSV4: /* 0x012FF7B5 local */ Line 473
return "sysv4"; Line 474
case S_MAGIC_TMPFS: /* 0x01021994 local */ Line 475
return "tmpfs"; Line 476
case S_MAGIC_TRACEFS: /* 0x74726163 local */ Line 477
return "tracefs"; Line 478
case S_MAGIC_UBIFS: /* 0x24051905 local */ Line 479
return "ubifs"; Line 480
case S_MAGIC_UDF: /* 0x15013346 local */ Line 481
return "udf"; Line 482
case S_MAGIC_UFS: /* 0x00011954 local */ Line 483
return "ufs"; Line 484
case S_MAGIC_UFS_BYTESWAPPED: /* 0x54190100 local */ Line 485
return "ufs"; Line 486
case S_MAGIC_USBDEVFS: /* 0x9FA2 local */ Line 487
return "usbdevfs"; Line 488
case S_MAGIC_V9FS: /* 0x01021997 local */ Line 489
return "v9fs"; Line 490
case S_MAGIC_VMHGFS: /* 0xBACBACBC remote */ Line 491
return "vmhgfs"; Line 492
case S_MAGIC_VXFS: /* 0xA501FCF5 remote */ Line 493
/* Veritas File System can run in single instance or clustered mode,
so mark as remote to cater for the latter case. */
return "vxfs"; Line 496
case S_MAGIC_VZFS: /* 0x565A4653 local */ Line 497
return "vzfs"; Line 498
case S_MAGIC_WSLFS: /* 0x53464846 local */ Line 499
return "wslfs"; Line 500
case S_MAGIC_XENFS: /* 0xABBA1974 local */ Line 501
return "xenfs"; Line 502
case S_MAGIC_XENIX: /* 0x012FF7B4 local */ Line 503
return "xenix"; Line 504
case S_MAGIC_XFS: /* 0x58465342 local */ Line 505
return "xfs"; Line 506
case S_MAGIC_XIAFS: /* 0x012FD16D local */ Line 507
return "xia"; Line 508
case S_MAGIC_ZFS: /* 0x2FC12FC1 local */ Line 509
return "zfs"; Line 510
case S_MAGIC_ZSMALLOC: /* 0x58295829 local */ Line 511
return "zsmallocfs"; Line 512
# elif __GNU__ Line 515
case FSTYPE_UFS: Line 516
return "ufs"; Line 517
case FSTYPE_NFS: Line 518
return "nfs"; Line 519
case FSTYPE_GFS: Line 520
return "gfs"; Line 521
case FSTYPE_LFS: Line 522
return "lfs"; Line 523
case FSTYPE_SYSV: Line 524
return "sysv"; Line 525
case FSTYPE_FTP: Line 526
return "ftp"; Line 527
case FSTYPE_TAR: Line 528
return "tar"; Line 529
case FSTYPE_AR: Line 530
return "ar"; Line 531
case FSTYPE_CPIO: Line 532
return "cpio"; Line 533
case FSTYPE_MSLOSS: Line 534
return "msloss"; Line 535
case FSTYPE_CPM: Line 536
return "cpm"; Line 537
case FSTYPE_HFS: Line 538
return "hfs"; Line 539
case FSTYPE_DTFS: Line 540
return "dtfs"; Line 541
case FSTYPE_GRFS: Line 542
return "grfs"; Line 543
case FSTYPE_TERM: Line 544
return "term"; Line 545
case FSTYPE_DEV: Line 546
return "dev"; Line 547
case FSTYPE_PROC: Line 548
return "proc"; Line 549
case FSTYPE_IFSOCK: Line 550
return "ifsock"; Line 551
case FSTYPE_AFS: Line 552
return "afs"; Line 553
case FSTYPE_DFS: Line 554
return "dfs"; Line 555
case FSTYPE_PROC9: Line 556
return "proc9"; Line 557
case FSTYPE_SOCKET: Line 558
return "socket"; Line 559
case FSTYPE_MISC: Line 560
return "misc"; Line 561
case FSTYPE_EXT2FS: Line 562
return "ext2/ext3"; Line 563
case FSTYPE_HTTP: Line 564
return "http"; Line 565
case FSTYPE_MEMFS: Line 566
return "memfs"; Line 567
case FSTYPE_ISO9660: Line 568
return "iso9660"; Line 569
# endif Line 570
default: Line 571
{
unsigned long int type = statfsbuf->f_type; Line 573
static char buf[sizeof "UNKNOWN (0x%lx)" - 3 Line 574
+ (sizeof type * CHAR_BIT + 3) / 4]; Line 575
sprintf (buf, "UNKNOWN (0x%lx)", type); Line 576
return buf; Line 577
}
}
#endif Line 580
} Block 4
static char * ATTRIBUTE_WARN_UNUSED_RESULT Line 583
human_access (struct stat const *statbuf) Line 584
{
static char modebuf[12]; Line 586
filemodestring (statbuf, modebuf); Line 587
modebuf[10] = 0; Line 588
return modebuf; Line 589
} Block 5
static char * ATTRIBUTE_WARN_UNUSED_RESULT Line 592
human_time (struct timespec t) Line 593
{
/* STR must be at least INT_BUFSIZE_BOUND (intmax_t) big, either
because localtime_rz fails, or because the time zone is truly
outlandish so that %z expands to a long string. */
static char str[INT_BUFSIZE_BOUND (intmax_t) Line 598
+ INT_STRLEN_BOUND (int) /* YYYY */ Line 599
+ 1 /* because YYYY might equal INT_MAX + 1900 */ Line 600
+ sizeof "-MM-DD HH:MM:SS.NNNNNNNNN +"]; Line 601
static timezone_t tz; Line 602
if (!tz) Line 603
tz = tzalloc (getenv ("TZ")); Line 604
struct tm tm; Line 605
int ns = t.tv_nsec; Line 606
if (localtime_rz (tz, &t.tv_sec, &tm)) Line 607
nstrftime (str, sizeof str, "%Y-%m-%d %H:%M:%S.%N %z", &tm, tz, ns); Line 608
else Line 609
{
char secbuf[INT_BUFSIZE_BOUND (intmax_t)]; Line 611
sprintf (str, "%s.%09d", timetostr (t.tv_sec, secbuf), ns); Line 612
}
return str; Line 614
}
/* PFORMAT points to a '%' followed by a prefix of a format, all of
size PREFIX_LEN. The flags allowed for this format are
ALLOWED_FLAGS; remove other printf flags from the prefix, then
append SUFFIX. */
static void Line 621
make_format (char *pformat, size_t prefix_len, char const *allowed_flags, Line 622
char const *suffix) Line 623
{
char *dst = pformat + 1; Line 625
char const *src; Line 626
char const *srclim = pformat + prefix_len; Line 627
for (src = dst; src < srclim && strchr (printf_flags, *src); src++) Line 628
if (strchr (allowed_flags, *src)) Line 629
*dst++ = *src; Line 630
while (src < srclim) Line 631
*dst++ = *src++; Line 632
strcpy (dst, suffix); Line 633
} Block 7
static void Line 636
out_string (char *pformat, size_t prefix_len, char const *arg) Line 637
{
make_format (pformat, prefix_len, "-", "s"); Line 639
printf (pformat, arg); Line 640
} Block 8
static int Line 642
out_int (char *pformat, size_t prefix_len, intmax_t arg) Line 643
{
make_format (pformat, prefix_len, "'-+ 0", PRIdMAX); Line 645
return printf (pformat, arg); Line 646
} Block 9
static int Line 648
out_uint (char *pformat, size_t prefix_len, uintmax_t arg) Line 649
{
make_format (pformat, prefix_len, "'-0", PRIuMAX); Line 651
return printf (pformat, arg); Line 652
} Block 10
static void Line 654
out_uint_o (char *pformat, size_t prefix_len, uintmax_t arg) Line 655
{
make_format (pformat, prefix_len, "-#0", PRIoMAX); Line 657
printf (pformat, arg); Line 658
} Block 11
static void Line 660
out_uint_x (char *pformat, size_t prefix_len, uintmax_t arg) Line 661
{
make_format (pformat, prefix_len, "-#0", PRIxMAX); Line 663
printf (pformat, arg); Line 664
} Block 12
static int Line 666
out_minus_zero (char *pformat, size_t prefix_len) Line 667
{
make_format (pformat, prefix_len, "'-+ 0", ".0f"); Line 669
return printf (pformat, -0.25); Line 670
} Block 13
/* Output the number of seconds since the Epoch, using a format that
acts like printf's %f format. */
static void Line 675
out_epoch_sec (char *pformat, size_t prefix_len, Line 676
struct stat const *statbuf _GL_UNUSED, Line 677
struct timespec arg) Line 678
{
char *dot = memchr (pformat, '.', prefix_len); Line 680
size_t sec_prefix_len = prefix_len; Line 681
int width = 0; Line 682
int precision = 0; Line 683
bool frac_left_adjust = false; Line 684
if (dot) Line 686
{
sec_prefix_len = dot - pformat; Line 688
pformat[prefix_len] = '\0'; Line 689
if (ISDIGIT (dot[1])) Line 691
{
long int lprec = strtol (dot + 1, NULL, 10); Line 693
precision = (lprec <= INT_MAX ? lprec : INT_MAX); Line 694
}
else Line 696
{
precision = 9; Line 698
}
if (precision && ISDIGIT (dot[-1])) Line 701
{
/* If a nontrivial width is given, subtract the width of the
decimal point and PRECISION digits that will be output
later. */
char *p = dot; Line 706
*dot = '\0'; Line 707
do
--p; Line 710
while (ISDIGIT (p[-1])); Line 711
long int lwidth = strtol (p, NULL, 10); Line 713
width = (lwidth <= INT_MAX ? lwidth : INT_MAX); Line 714
if (1 < width) Line 715
{
p += (*p == '0'); Line 717
sec_prefix_len = p - pformat; Line 718
int w_d = (decimal_point_len < width Line 719
? width - decimal_point_len Line 720
: 0); Line 721
if (1 < w_d) Line 722
{
int w = w_d - precision; Line 724
if (1 < w) Line 725
{
char *dst = pformat; Line 727
for (char const *src = dst; src < p; src++) Line 728
{
if (*src == '-') Line 730
frac_left_adjust = true; Line 731
else Line 732
*dst++ = *src; Line 733
}
sec_prefix_len = Line 735
(dst - pformat Line 736
+ (frac_left_adjust ? 0 : sprintf (dst, "%d", w))); Line 737
}
}
}
}
}
int divisor = 1; Line 744
for (int i = precision; i < 9; i++) Line 745
divisor *= 10; Line 746
int frac_sec = arg.tv_nsec / divisor; Line 747
int int_len; Line 748
if (TYPE_SIGNED (time_t)) Line 750
{
bool minus_zero = false; Line 752
if (arg.tv_sec < 0 && arg.tv_nsec != 0) Line 753
{
int frac_sec_modulus = 1000000000 / divisor; Line 755
frac_sec = (frac_sec_modulus - frac_sec Line 756
- (arg.tv_nsec % divisor != 0)); Line 757
arg.tv_sec += (frac_sec != 0); Line 758
minus_zero = (arg.tv_sec == 0); Line 759
}
int_len = (minus_zero Line 761
? out_minus_zero (pformat, sec_prefix_len) Line 762
: out_int (pformat, sec_prefix_len, arg.tv_sec)); Line 763
}
else Line 765
int_len = out_uint (pformat, sec_prefix_len, arg.tv_sec); Line 766
if (precision) Line 768
{
int prec = (precision < 9 ? precision : 9); Line 770
int trailing_prec = precision - prec; Line 771
int ilen = (int_len < 0 ? 0 : int_len); Line 772
int trailing_width = (ilen < width && decimal_point_len < width - ilen Line 773
? width - ilen - decimal_point_len - prec Line 774
: 0); Line 775
printf ("%s%.*d%-*.*d", decimal_point, prec, frac_sec, Line 776
trailing_width, trailing_prec, 0); Line 777
}
} Block 14
/* Print the context information of FILENAME, and return true iff the
context could not be obtained. */
static bool ATTRIBUTE_WARN_UNUSED_RESULT Line 783
out_file_context (char *pformat, size_t prefix_len, char const *filename) Line 784
{
char *scontext; Line 786
bool fail = false; Line 787
if ((follow_links Line 789
? getfilecon (filename, &scontext) Line 790
: lgetfilecon (filename, &scontext)) < 0) Line 791
{
error (0, errno, _("failed to get security context of %s"), Line 793
quoteaf (filename)); Line 794
scontext = NULL; Line 795
fail = true; Line 796
}
strcpy (pformat + prefix_len, "s"); Line 798
printf (pformat, (scontext ? scontext : "?")); Line 799
if (scontext) Line 800
freecon (scontext); Line 801
return fail; Line 802
} Block 15
/* Print statfs info. Return zero upon success, nonzero upon failure. */
static bool ATTRIBUTE_WARN_UNUSED_RESULT Line 806
print_statfs (char *pformat, size_t prefix_len, unsigned int m, Line 807
int fd, char const *filename, Line 808
void const *data) Line 809
{
STRUCT_STATVFS const *statfsbuf = data; Line 811
bool fail = false; Line 812
switch (m) Line 814
{
case 'n': Line 816
out_string (pformat, prefix_len, filename); Line 817
break; Line 818
case 'i': Line 820
{
#if STRUCT_STATXFS_F_FSID_IS_INTEGER Line 822
uintmax_t fsid = statfsbuf->f_fsid; Line 823
#else Line 824
typedef unsigned int fsid_word; Line 825
verify (alignof (STRUCT_STATVFS) % alignof (fsid_word) == 0); Line 826
verify (offsetof (STRUCT_STATVFS, f_fsid) % alignof (fsid_word) == 0); Line 827
verify (sizeof statfsbuf->f_fsid % alignof (fsid_word) == 0); Line 828
fsid_word const *p = (fsid_word *) &statfsbuf->f_fsid; Line 829
/* Assume a little-endian word order, as that is compatible
with glibc's statvfs implementation. */
uintmax_t fsid = 0; Line 833
int words = sizeof statfsbuf->f_fsid / sizeof *p; Line 834
for (int i = 0; i < words && i * sizeof *p < sizeof fsid; i++) Line 835
{
uintmax_t u = p[words - 1 - i]; Line 837
fsid |= u << (i * CHAR_BIT * sizeof *p); Line 838
}
#endif Line 840
out_uint_x (pformat, prefix_len, fsid); Line 841
}
break; Line 843
case 'l': Line 845
OUT_NAMEMAX (pformat, prefix_len, SB_F_NAMEMAX (statfsbuf)); Line 846
break; Line 847
case 't': Line 848
#if HAVE_STRUCT_STATXFS_F_TYPE Line 849
out_uint_x (pformat, prefix_len, statfsbuf->f_type); Line 850
#else Line 851
fputc ('?', stdout); Line 852
#endif Line 853
break; Line 854
case 'T': Line 855
out_string (pformat, prefix_len, human_fstype (statfsbuf)); Line 856
break; Line 857
case 'b': Line 858
out_int (pformat, prefix_len, statfsbuf->f_blocks); Line 859
break; Line 860
case 'f': Line 861
out_int (pformat, prefix_len, statfsbuf->f_bfree); Line 862
break; Line 863
case 'a': Line 864
out_int (pformat, prefix_len, statfsbuf->f_bavail); Line 865
break; Line 866
case 's': Line 867
out_uint (pformat, prefix_len, statfsbuf->f_bsize); Line 868
break; Line 869
case 'S': Line 870
{
uintmax_t frsize = STATFS_FRSIZE (statfsbuf); Line 872
if (! frsize) Line 873
frsize = statfsbuf->f_bsize; Line 874
out_uint (pformat, prefix_len, frsize); Line 875
}
break; Line 877
case 'c': Line 878
out_uint (pformat, prefix_len, statfsbuf->f_files); Line 879
break; Line 880
case 'd': Line 881
out_int (pformat, prefix_len, statfsbuf->f_ffree); Line 882
break; Line 883
default: Line 884
fputc ('?', stdout); Line 885
break; Line 886
}
return fail; Line 888
} Block 16
/* Return any bind mounted source for a path.
The caller should not free the returned buffer.
Return NULL if no bind mount found. */
static char const * ATTRIBUTE_WARN_UNUSED_RESULT Line 894
find_bind_mount (char const * name) Line 895
{
char const * bind_mount = NULL; Line 897
static struct mount_entry *mount_list; Line 899
static bool tried_mount_list = false; Line 900
if (!tried_mount_list) /* attempt/warn once per process. */ Line 901
{
if (!(mount_list = read_file_system_list (false))) Line 903
error (0, errno, "%s", _("cannot read table of mounted file systems")); Line 904
tried_mount_list = true; Line 905
}
struct stat name_stats; Line 908
if (stat (name, &name_stats) != 0) Line 909...!syscalls auto-comment...
return NULL; Line 910
struct mount_entry *me; Line 912
for (me = mount_list; me; me = me->me_next) Line 913
{
if (me->me_dummy && me->me_devname[0] == '/' Line 915
&& STREQ (me->me_mountdir, name)) Line 916
{
struct stat dev_stats; Line 918
if (stat (me->me_devname, &dev_stats) == 0 Line 920...!syscalls auto-comment...
&& SAME_INODE (name_stats, dev_stats)) Line 921
{
bind_mount = me->me_devname; Line 923
break; Line 924
}
}
}
return bind_mount; Line 929
} Block 17
/* Print mount point. Return zero upon success, nonzero upon failure. */
static bool ATTRIBUTE_WARN_UNUSED_RESULT Line 933
out_mount_point (char const *filename, char *pformat, size_t prefix_len, Line 934
const struct stat *statp) Line 935
{
char const *np = "?", *bp = NULL; Line 938
char *mp = NULL; Line 939
bool fail = true; Line 940
/* Look for bind mounts first. Note we output the immediate alias,
rather than further resolving to a base device mount point. */
if (follow_links || !S_ISLNK (statp->st_mode)) Line 944
{
char *resolved = canonicalize_file_name (filename); Line 946
if (!resolved) Line 947
{
error (0, errno, _("failed to canonicalize %s"), quoteaf (filename)); Line 949
goto print_mount_point; Line 950
}
bp = find_bind_mount (resolved); Line 952
free (resolved); Line 953
if (bp) Line 954
{
fail = false; Line 956
goto print_mount_point; Line 957
}
}
/* If there is no direct bind mount, then navigate
back up the tree looking for a device change.
Note we don't detect if any of the directory components
are bind mounted to the same device, but that's OK
since we've not directly queried them. */
if ((mp = find_mount_point (filename, statp))) Line 966
{
/* This dir might be bind mounted to another device,
so we resolve the bound source in that case also. */
bp = find_bind_mount (mp); Line 970
fail = false; Line 971
}
print_mount_point: Line 974
out_string (pformat, prefix_len, bp ? bp : mp ? mp : np); Line 976
free (mp); Line 977
return fail; Line 978
}
static struct timespec Line 981
get_birthtime (int fd, char const *filename, struct stat const *st) Line 982
{
struct timespec ts = get_stat_birthtime (st); Line 984
#if HAVE_GETATTRAT Line 986
if (ts.tv_nsec < 0) Line 987
{
nvlist_t *response; Line 989
if ((fd < 0 Line 990
? getattrat (AT_FDCWD, XATTR_VIEW_READWRITE, filename, &response) Line 991
: fgetattr (fd, XATTR_VIEW_READWRITE, &response)) Line 992
== 0) Line 993
{
uint64_t *val; Line 995
uint_t n; Line 996
if (nvlist_lookup_uint64_array (response, A_CRTIME, &val, &n) == 0 Line 997
&& 2 <= n Line 998
&& val[0] <= TYPE_MAXIMUM (time_t) Line 999
&& val[1] < 1000000000 * 2 /* for leap seconds */) Line 1000
{
ts.tv_sec = val[0]; Line 1002
ts.tv_nsec = val[1]; Line 1003
}
nvlist_free (response); Line 1005
}
}
#endif Line 1008
return ts; Line 1010
} Block 19
/* Map a TS with negative TS.tv_nsec to {0,0}. */
static inline struct timespec Line 1014
neg_to_zero (struct timespec ts) Line 1015
{
if (0 <= ts.tv_nsec) Line 1017
return ts; Line 1018
struct timespec z = {0, 0}; Line 1019
return z; Line 1020
} Block 20
/* Set the quoting style default if the environment variable
QUOTING_STYLE is set. */
static void Line 1026
getenv_quoting_style (void) Line 1027
{
char const *q_style = getenv ("QUOTING_STYLE"); Line 1029
if (q_style) Line 1030
{
int i = ARGMATCH (q_style, quoting_style_args, quoting_style_vals); Line 1032
if (0 <= i) Line 1033
set_quoting_style (NULL, quoting_style_vals[i]); Line 1034
else Line 1035
{
set_quoting_style (NULL, shell_escape_always_quoting_style); Line 1037
error (0, 0, _("ignoring invalid value of environment " Line 1038
"variable QUOTING_STYLE: %s"), quote (q_style)); Line 1039
}
}
else Line 1042
set_quoting_style (NULL, shell_escape_always_quoting_style); Line 1043
} Block 21
/* Equivalent to quotearg(), but explicit to avoid syntax checks. */
#define quoteN(x) quotearg_style (get_quoting_style (NULL), x) Line 1047
/* Print stat info. Return zero upon success, nonzero upon failure. */
static bool Line 1050
print_stat (char *pformat, size_t prefix_len, unsigned int m, Line 1051...!syscalls auto-comment...
int fd, char const *filename, void const *data) Line 1052
{
struct stat *statbuf = (struct stat *) data; Line 1054
struct passwd *pw_ent; Line 1055
struct group *gw_ent; Line 1056
bool fail = false; Line 1057
switch (m) Line 1059
{
case 'n': Line 1061
out_string (pformat, prefix_len, filename); Line 1062
break; Line 1063
case 'N': Line 1064
out_string (pformat, prefix_len, quoteN (filename)); Line 1065
if (S_ISLNK (statbuf->st_mode)) Line 1066
{
char *linkname = areadlink_with_size (filename, statbuf->st_size); Line 1068
if (linkname == NULL) Line 1069
{
error (0, errno, _("cannot read symbolic link %s"), Line 1071
quoteaf (filename)); Line 1072
return true; Line 1073
}
printf (" -> "); Line 1075
out_string (pformat, prefix_len, quoteN (linkname)); Line 1076
free (linkname); Line 1077
}
break; Line 1079
case 'd': Line 1080
out_uint (pformat, prefix_len, statbuf->st_dev); Line 1081
break; Line 1082
case 'D': Line 1083
out_uint_x (pformat, prefix_len, statbuf->st_dev); Line 1084
break; Line 1085
case 'i': Line 1086
out_uint (pformat, prefix_len, statbuf->st_ino); Line 1087
break; Line 1088
case 'a': Line 1089
out_uint_o (pformat, prefix_len, statbuf->st_mode & CHMOD_MODE_BITS); Line 1090
break; Line 1091
case 'A': Line 1092
out_string (pformat, prefix_len, human_access (statbuf)); Line 1093
break; Line 1094
case 'f': Line 1095
out_uint_x (pformat, prefix_len, statbuf->st_mode); Line 1096
break; Line 1097
case 'F': Line 1098
out_string (pformat, prefix_len, file_type (statbuf)); Line 1099
break; Line 1100
case 'h': Line 1101
out_uint (pformat, prefix_len, statbuf->st_nlink); Line 1102
break; Line 1103
case 'u': Line 1104
out_uint (pformat, prefix_len, statbuf->st_uid); Line 1105
break; Line 1106
case 'U': Line 1107
pw_ent = getpwuid (statbuf->st_uid); Line 1108
out_string (pformat, prefix_len, Line 1109
pw_ent ? pw_ent->pw_name : "UNKNOWN"); Line 1110
break; Line 1111
case 'g': Line 1112
out_uint (pformat, prefix_len, statbuf->st_gid); Line 1113
break; Line 1114
case 'G': Line 1115
gw_ent = getgrgid (statbuf->st_gid); Line 1116
out_string (pformat, prefix_len, Line 1117
gw_ent ? gw_ent->gr_name : "UNKNOWN"); Line 1118
break; Line 1119
case 't': Line 1120
out_uint_x (pformat, prefix_len, major (statbuf->st_rdev)); Line 1121
break; Line 1122
case 'm': Line 1123
fail |= out_mount_point (filename, pformat, prefix_len, statbuf); Line 1124
break; Line 1125
case 'T': Line 1126
out_uint_x (pformat, prefix_len, minor (statbuf->st_rdev)); Line 1127
break; Line 1128
case 's': Line 1129
out_int (pformat, prefix_len, statbuf->st_size); Line 1130
break; Line 1131
case 'B': Line 1132
out_uint (pformat, prefix_len, ST_NBLOCKSIZE); Line 1133
break; Line 1134
case 'b': Line 1135
out_uint (pformat, prefix_len, ST_NBLOCKS (*statbuf)); Line 1136
break; Line 1137
case 'o': Line 1138
out_uint (pformat, prefix_len, ST_BLKSIZE (*statbuf)); Line 1139
break; Line 1140
case 'w': Line 1141
{
struct timespec t = get_birthtime (fd, filename, statbuf); Line 1143
if (t.tv_nsec < 0) Line 1144
out_string (pformat, prefix_len, "-"); Line 1145
else Line 1146
out_string (pformat, prefix_len, human_time (t)); Line 1147
}
break; Line 1149
case 'W': Line 1150
out_epoch_sec (pformat, prefix_len, statbuf, Line 1151
neg_to_zero (get_birthtime (fd, filename, statbuf))); Line 1152
break; Line 1153
case 'x': Line 1154
out_string (pformat, prefix_len, human_time (get_stat_atime (statbuf))); Line 1155
break; Line 1156
case 'X': Line 1157
out_epoch_sec (pformat, prefix_len, statbuf, get_stat_atime (statbuf)); Line 1158
break; Line 1159
case 'y': Line 1160
out_string (pformat, prefix_len, human_time (get_stat_mtime (statbuf))); Line 1161
break; Line 1162
case 'Y': Line 1163
out_epoch_sec (pformat, prefix_len, statbuf, get_stat_mtime (statbuf)); Line 1164
break; Line 1165
case 'z': Line 1166
out_string (pformat, prefix_len, human_time (get_stat_ctime (statbuf))); Line 1167
break; Line 1168
case 'Z': Line 1169
out_epoch_sec (pformat, prefix_len, statbuf, get_stat_ctime (statbuf)); Line 1170
break; Line 1171
case 'C': Line 1172
fail |= out_file_context (pformat, prefix_len, filename); Line 1173
break; Line 1174
default: Line 1175
fputc ('?', stdout); Line 1176
break; Line 1177
}
return fail; Line 1179
} Block 22
/* Output a single-character \ escape. */
static void Line 1184
print_esc_char (char c) Line 1185
{
switch (c) Line 1187
{
case 'a': /* Alert. */ Line 1189
c ='\a'; Line 1190
break; Line 1191
case 'b': /* Backspace. */ Line 1192
c ='\b'; Line 1193
break; Line 1194
case 'e': /* Escape. */ Line 1195
c ='\x1B'; Line 1196
break; Line 1197
case 'f': /* Form feed. */ Line 1198
c ='\f'; Line 1199
break; Line 1200
case 'n': /* New line. */ Line 1201
c ='\n'; Line 1202
break; Line 1203
case 'r': /* Carriage return. */ Line 1204
c ='\r'; Line 1205
break; Line 1206
case 't': /* Horizontal tab. */ Line 1207
c ='\t'; Line 1208
break; Line 1209
case 'v': /* Vertical tab. */ Line 1210
c ='\v'; Line 1211
break; Line 1212
case '"': Line 1213
case '\\': Line 1214
break; Line 1215
default: Line 1216
error (0, 0, _("warning: unrecognized escape '\\%c'"), c); Line 1217
break; Line 1218
}
putchar (c); Line 1220
} Block 23
/* Print the information specified by the format string, FORMAT,
calling PRINT_FUNC for each %-directive encountered.
Return zero upon success, nonzero upon failure. */
static bool ATTRIBUTE_WARN_UNUSED_RESULT Line 1226
print_it (char const *format, int fd, char const *filename, Line 1227
bool (*print_func) (char *, size_t, unsigned int, Line 1228
int, char const *, void const *), Line 1229
void const *data) Line 1230
{
bool fail = false; Line 1232
/* Add 2 to accommodate our conversion of the stat '%s' format string
to the longer printf '%llu' one. */
enum Line 1236
{
MAX_ADDITIONAL_BYTES = Line 1238
(MAX (sizeof PRIdMAX, Line 1239
MAX (sizeof PRIoMAX, MAX (sizeof PRIuMAX, sizeof PRIxMAX))) Line 1240
- 1) Line 1241
};
size_t n_alloc = strlen (format) + MAX_ADDITIONAL_BYTES + 1; Line 1243
char *dest = xmalloc (n_alloc); Line 1244
char const *b; Line 1245
for (b = format; *b; b++) Line 1246
{
switch (*b) Line 1248
{
case '%': Line 1250
{
size_t len = strspn (b + 1, printf_flags); Line 1252
char const *fmt_char = b + len + 1; Line 1253
fmt_char += strspn (fmt_char, digits); Line 1254
if (*fmt_char == '.') Line 1255
fmt_char += 1 + strspn (fmt_char + 1, digits); Line 1256
len = fmt_char - (b + 1); Line 1257
unsigned int fmt_code = *fmt_char; Line 1258
memcpy (dest, b, len + 1); Line 1259
b = fmt_char; Line 1261
switch (fmt_code) Line 1262
{
case '\0': Line 1264
--b; Line 1265
FALLTHROUGH; Line 1266
case '%': Line 1267
if (0 < len) Line 1268
{
dest[len + 1] = *fmt_char; Line 1270
dest[len + 2] = '\0'; Line 1271
die (EXIT_FAILURE, 0, _("%s: invalid directive"), Line 1272
quote (dest)); Line 1273
}
putchar ('%'); Line 1275
break; Line 1276
default: Line 1277
fail |= print_func (dest, len + 1, fmt_code, Line 1278
fd, filename, data); Line 1279
break; Line 1280
}
break; Line 1282
}
case '\\': Line 1285
if ( ! interpret_backslash_escapes) Line 1286
{
putchar ('\\'); Line 1288
break; Line 1289
}
++b; Line 1291
if (isodigit (*b)) Line 1292
{
int esc_value = octtobin (*b); Line 1294
int esc_length = 1; /* number of octal digits */ Line 1295
for (++b; esc_length < 3 && isodigit (*b); Line 1296
++esc_length, ++b) Line 1297
{
esc_value = esc_value * 8 + octtobin (*b); Line 1299
}
putchar (esc_value); Line 1301
--b; Line 1302
}
else if (*b == 'x' && isxdigit (to_uchar (b[1]))) Line 1304
{
int esc_value = hextobin (b[1]); /* Value of \xhh escape. */ Line 1306
/* A hexadecimal \xhh escape sequence must have
1 or 2 hex. digits. */
++b; Line 1309
if (isxdigit (to_uchar (b[1]))) Line 1310
{
++b; Line 1312
esc_value = esc_value * 16 + hextobin (*b); Line 1313
}
putchar (esc_value); Line 1315
}
else if (*b == '\0') Line 1317
{
error (0, 0, _("warning: backslash at end of format")); Line 1319
putchar ('\\'); Line 1320
/* Arrange to exit the loop. */
--b; Line 1322
}
else Line 1324
{
print_esc_char (*b); Line 1326
}
break; Line 1328
default: Line 1330
putchar (*b); Line 1331
break; Line 1332
}
}
free (dest); Line 1335
fputs (trailing_delim, stdout); Line 1337
return fail; Line 1339
} Block 24
/* Stat the file system and print what we find. */
static bool ATTRIBUTE_WARN_UNUSED_RESULT Line 1343
do_statfs (char const *filename, char const *format) Line 1344
{
STRUCT_STATVFS statfsbuf; Line 1346
if (STREQ (filename, "-")) Line 1348
{
error (0, 0, _("using %s to denote standard input does not work" Line 1350
" in file system mode"), quoteaf (filename)); Line 1351
return false; Line 1352
}
if (STATFS (filename, &statfsbuf) != 0) Line 1355
{
error (0, errno, _("cannot read file system information for %s"), Line 1357
quoteaf (filename)); Line 1358
return false; Line 1359
}
bool fail = print_it (format, -1, filename, print_statfs, &statfsbuf); Line 1362
return ! fail; Line 1363
} Block 25
/* stat the file and print what we find */
static bool ATTRIBUTE_WARN_UNUSED_RESULT Line 1367
do_stat (char const *filename, char const *format, Line 1368...!syscalls auto-comment...
char const *format2) Line 1369
{
int fd = STREQ (filename, "-") ? 0 : -1; Line 1371
struct stat statbuf; Line 1372
if (0 <= fd) Line 1374
{
if (fstat (fd, &statbuf) != 0) Line 1376...!syscalls auto-comment......!syscalls auto-comment...
{
error (0, errno, _("cannot stat standard input")); Line 1378
return false; Line 1379
}
}
/* We can't use the shorter
(follow_links?stat:lstat) (filename, &statbug)
since stat might be a function-like macro. */
else if ((follow_links Line 1385
? stat (filename, &statbuf) Line 1386...!syscalls auto-comment...
: lstat (filename, &statbuf)) != 0) Line 1387...!syscalls auto-comment...
{
error (0, errno, _("cannot stat %s"), quoteaf (filename)); Line 1389
return false; Line 1390
}
if (S_ISBLK (statbuf.st_mode) || S_ISCHR (statbuf.st_mode)) Line 1393
format = format2; Line 1394
bool fail = print_it (format, fd, filename, print_stat, &statbuf); Line 1396
return ! fail; Line 1397
} Block 26
/* Return an allocated format string in static storage that
corresponds to whether FS and TERSE options were declared. */
static char * Line 1402
default_format (bool fs, bool terse, bool device) Line 1403
{
char *format; Line 1405
if (fs) Line 1406
{
if (terse) Line 1408
format = xstrdup (fmt_terse_fs); Line 1409
else Line 1410
{
/* TRANSLATORS: This string uses format specifiers from
'stat --help' with --file-system, and NOT from printf. */
format = xstrdup (_(" File: \"%n\"\n" Line 1414
" ID: %-8i Namelen: %-7l Type: %T\n" Line 1415
"Block size: %-10s Fundamental block size: %S\n" Line 1416
"Blocks: Total: %-10b Free: %-10f Available: %a\n"Line 1417
"Inodes: Total: %-10c Free: %d\n")); Line 1418
}
}
else /* ! fs */ Line 1421
{
if (terse) Line 1423
{
if (0 < is_selinux_enabled ()) ...!common auto-comment...
format = xstrdup (fmt_terse_selinux); Line 1426
else Line 1427
format = xstrdup (fmt_terse_regular); Line 1428
}
else Line 1430
{
char *temp; Line 1432
/* TRANSLATORS: This string uses format specifiers from
'stat --help' without --file-system, and NOT from printf. */
format = xstrdup (_("\ Line 1435
File: %N\n\ Line 1436
Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n\ Line 1437
")); Line 1438
temp = format; Line 1440
if (device) Line 1441
{
/* TRANSLATORS: This string uses format specifiers from
'stat --help' without --file-system, and NOT from printf. */
format = xasprintf ("%s%s", format, _("\ Line 1445
" "Device: %Dh/%dd\tInode: %-10i Links: %-5h Device type: %t,%T\n\ Line 1446
")); Line 1447
}
else Line 1449
{
/* TRANSLATORS: This string uses format specifiers from
'stat --help' without --file-system, and NOT from printf. */
format = xasprintf ("%s%s", format, _("\ Line 1453
" "Device: %Dh/%dd\tInode: %-10i Links: %h\n\ Line 1454
")); Line 1455
}
free (temp); Line 1457
temp = format; Line 1459
/* TRANSLATORS: This string uses format specifiers from
'stat --help' without --file-system, and NOT from printf. */
format = xasprintf ("%s%s", format, _("\ Line 1462
" "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n\ Line 1463
")); Line 1464
free (temp); Line 1465
if (0 < is_selinux_enabled ()) ...!common auto-comment...
{
temp = format; Line 1469
/* TRANSLATORS: This string uses format specifiers from
'stat --help' without --file-system, and NOT from printf. */
format = xasprintf ("%s%s", format, _("Context: %C\n")); Line 1472
free (temp); Line 1473
}
temp = format; Line 1476
/* TRANSLATORS: This string uses format specifiers from
'stat --help' without --file-system, and NOT from printf. */
format = xasprintf ("%s%s", format, Line 1479
_("Access: %x\n" Line 1480
"Modify: %y\n" Line 1481
"Change: %z\n" Line 1482
" Birth: %w\n")); Line 1483
free (temp); Line 1484
}
}
return format; Line 1487
} Block 27
void Line 1490
usage (int status) Line 1491
{
if (status != EXIT_SUCCESS) Line 1493
emit_try_help (); ...!common auto-comment...
else Line 1495
{
printf (_("Usage: %s [OPTION]... FILE...\n"), program_name); Line 1497
fputs (_("\ Line 1498
Display file or file system status.\n\ Line 1499
"), stdout); Line 1500
emit_mandatory_arg_note (); ...!common auto-comment...
fputs (_("\ Line 1504
-L, --dereference follow links\n\ Line 1505
-f, --file-system display file system status instead of file status\n\ Line 1506
"), stdout); Line 1507
fputs (_("\ Line 1508
-c --format=FORMAT use the specified FORMAT instead of the default;\n\ Line 1509
output a newline after each use of FORMAT\n\ Line 1510
--printf=FORMAT like --format, but interpret backslash escapes,\n\ Line 1511
and do not output a mandatory trailing newline;\n\ Line 1512
if you want a newline, include \\n in FORMAT\n\ Line 1513
-t, --terse print the information in terse form\n\ Line 1514
"), stdout); Line 1515
fputs (HELP_OPTION_DESCRIPTION, stdout); Line 1516
fputs (VERSION_OPTION_DESCRIPTION, stdout); Line 1517
fputs (_("\n\ Line 1519
The valid format sequences for files (without --file-system):\n\ Line 1520
\n\
%a access rights in octal (note '#' and '0' printf flags)\n\ Line 1522
%A access rights in human readable form\n\ Line 1523
%b number of blocks allocated (see %B)\n\ Line 1524
%B the size in bytes of each block reported by %b\n\ Line 1525
%C SELinux security context string\n\ Line 1526
"), stdout); Line 1527
fputs (_("\ Line 1528
%d device number in decimal\n\ Line 1529
%D device number in hex\n\ Line 1530
%f raw mode in hex\n\ Line 1531
%F file type\n\ Line 1532
%g group ID of owner\n\ Line 1533
%G group name of owner\n\ Line 1534
"), stdout); Line 1535
fputs (_("\ Line 1536
%h number of hard links\n\ Line 1537
%i inode number\n\ Line 1538
%m mount point\n\ Line 1539
%n file name\n\ Line 1540
%N quoted file name with dereference if symbolic link\n\ Line 1541
%o optimal I/O transfer size hint\n\ Line 1542
%s total size, in bytes\n\ Line 1543
%t major device type in hex, for character/block device special files\n\ Line 1544
%T minor device type in hex, for character/block device special files\n\ Line 1545
"), stdout); Line 1546
fputs (_("\ Line 1547
%u user ID of owner\n\ Line 1548
%U user name of owner\n\ Line 1549
%w time of file birth, human-readable; - if unknown\n\ Line 1550
%W time of file birth, seconds since Epoch; 0 if unknown\n\ Line 1551
%x time of last access, human-readable\n\ Line 1552
%X time of last access, seconds since Epoch\n\ Line 1553
%y time of last data modification, human-readable\n\ Line 1554
%Y time of last data modification, seconds since Epoch\n\ Line 1555
%z time of last status change, human-readable\n\ Line 1556
%Z time of last status change, seconds since Epoch\n\ Line 1557
\n\
"), stdout); Line 1559
fputs (_("\ Line 1561
Valid format sequences for file systems:\n\ Line 1562
\n\
%a free blocks available to non-superuser\n\ Line 1564
%b total data blocks in file system\n\ Line 1565
%c total file nodes in file system\n\ Line 1566
%d free file nodes in file system\n\ Line 1567
%f free blocks in file system\n\ Line 1568
"), stdout); Line 1569
fputs (_("\ Line 1570
%i file system ID in hex\n\ Line 1571
%l maximum length of filenames\n\ Line 1572
%n file name\n\ Line 1573
%s block size (for faster transfers)\n\ Line 1574
%S fundamental block size (for block counts)\n\ Line 1575
%t file system type in hex\n\ Line 1576
%T file system type in human readable form\n\ Line 1577
"), stdout); Line 1578
printf (_("\n\ Line 1580
--terse is equivalent to the following FORMAT:\n\ Line 1581
%s\
"), Line 1583
#if HAVE_SELINUX_SELINUX_H Line 1584
fmt_terse_selinux Line 1585
#else Line 1586
fmt_terse_regular Line 1587
#endif Line 1588
);
printf (_("\ Line 1591
--terse --file-system is equivalent to the following FORMAT:\n\ Line 1592
%s\
"), fmt_terse_fs); Line 1594
printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME); Line 1596
emit_ancillary_info (PROGRAM_NAME); Line 1597
}
exit (status); Line 1599
} Block 28
int
main (int argc, char *argv[]) Line 1603
{
int c; Line 1605
bool fs = false; Line 1606
bool terse = false; Line 1607
char *format = NULL; Line 1608
char *format2; Line 1609
bool ok = true; Line 1610
initialize_main (&argc, &argv); VMS-specific entry point handling wildcard expansion
set_program_name (argv[0]); Retains program name and discards path
setlocale (LC_ALL, ""); Sets up internationalization (i18n)
bindtextdomain (PACKAGE, LOCALEDIR); Assigns i18n directorySets text domain for _() [gettext()] function
textdomain (PACKAGE); Sets text domain for _() [gettext()] function
struct lconv const *locale = localeconv (); Line 1618
decimal_point = (locale->decimal_point[0] ? locale->decimal_point : "."); Line 1619
decimal_point_len = strlen (decimal_point); Line 1620
atexit (close_stdout); Close stdout on exit (see gnulib)
while ((c = getopt_long (argc, argv, "c:fLt", long_options, NULL)) != -1) Line 1624
{
switch (c) Line 1626
{
case PRINTF_OPTION: Line 1628
format = optarg; Line 1629
interpret_backslash_escapes = true; Line 1630
trailing_delim = ""; Line 1631
break; Line 1632
case 'c': Line 1634
format = optarg; Line 1635
interpret_backslash_escapes = false; Line 1636
trailing_delim = "\n"; Line 1637
break; Line 1638
case 'L': Line 1640
follow_links = true; Line 1641
break; Line 1642
case 'f': Line 1644
fs = true; Line 1645
break; Line 1646
case 't': Line 1648
terse = true; Line 1649
break; Line 1650
case_GETOPT_HELP_CHAR; Line 1652
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); Line 1654
default: Line 1656
usage (EXIT_FAILURE); Line 1657
}
}
if (argc == optind) Line 1661
{
error (0, 0, _("missing operand")); Line 1663
usage (EXIT_FAILURE); Line 1664
}
if (format) Line 1667
{
if (strstr (format, "%N")) Line 1669
getenv_quoting_style (); Line 1670
format2 = format; Line 1671
}
else Line 1673
{
format = default_format (fs, terse, /* device= */ false); Line 1675
format2 = default_format (fs, terse, /* device= */ true); Line 1676
}
for (int i = optind; i < argc; i++) Line 1679
ok &= (fs Line 1680
? do_statfs (argv[i], format) Line 1681
: do_stat (argv[i], format, format2)); Line 1682...!syscalls auto-comment...
return ok ? EXIT_SUCCESS : EXIT_FAILURE; Line 1684
} Block 29