+/* vi:set ts=4:*/
/*
* stat -- display file or file system status
*
* Written by Michael Meskes
* Taken from coreutils and turned into a busybox applet by Mike Frysinger
*
- * 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
#include <stdio.h>
+#include <stdint.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <sys/vfs.h>
#include <time.h>
-#include <getopt.h>
+#include <getopt.h> /* optind */
#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/statvfs.h>
#include <string.h>
#include "busybox.h"
/* vars to control behavior */
-static int follow_links = 0;
-static int terse = 0;
+#define OPT_TERSE 2
+#define OPT_DEREFERENCE 4
+static long flags;
static char const *file_type(struct stat const *st)
{
- /* See POSIX 1003.1-2001 XCU Table 4-8 lines 17093-17107
+ /* See POSIX 1003.1-2001 XCU Table 4-8 lines 17093-17107
* for some of these formats.
- * To keep diagnostics grammatical in English, the
+ * To keep diagnostics grammatical in English, the
* returned string must start with a consonant.
*/
if (S_ISREG(st->st_mode)) return st->st_size == 0 ? "regular empty file" : "regular file";
*/
static char const *human_fstype(long f_type)
{
-#define S_MAGIC_AFFS 0xADFF
-#define S_MAGIC_DEVPTS 0x1CD1
-#define S_MAGIC_EXT 0x137D
-#define S_MAGIC_EXT2_OLD 0xEF51
-#define S_MAGIC_EXT2 0xEF53
-#define S_MAGIC_JFS 0x3153464a
-#define S_MAGIC_XFS 0x58465342
-#define S_MAGIC_HPFS 0xF995E849
-#define S_MAGIC_ISOFS 0x9660
-#define S_MAGIC_ISOFS_WIN 0x4000
-#define S_MAGIC_ISOFS_R_WIN 0x4004
-#define S_MAGIC_MINIX 0x137F
-#define S_MAGIC_MINIX_30 0x138F
-#define S_MAGIC_MINIX_V2 0x2468
-#define S_MAGIC_MINIX_V2_30 0x2478
-#define S_MAGIC_MSDOS 0x4d44
-#define S_MAGIC_FAT 0x4006
-#define S_MAGIC_NCP 0x564c
-#define S_MAGIC_NFS 0x6969
-#define S_MAGIC_PROC 0x9fa0
-#define S_MAGIC_SMB 0x517B
-#define S_MAGIC_XENIX 0x012FF7B4
-#define S_MAGIC_SYSV4 0x012FF7B5
-#define S_MAGIC_SYSV2 0x012FF7B6
-#define S_MAGIC_COH 0x012FF7B7
-#define S_MAGIC_UFS 0x00011954
-#define S_MAGIC_XIAFS 0x012FD16D
-#define S_MAGIC_NTFS 0x5346544e
-#define S_MAGIC_TMPFS 0x1021994
-#define S_MAGIC_REISERFS 0x52654973
-#define S_MAGIC_CRAMFS 0x28cd3d45
-#define S_MAGIC_ROMFS 0x7275
-#define S_MAGIC_RAMFS 0x858458f6
-#define S_MAGIC_SQUASHFS 0x73717368
-#define S_MAGIC_SYSFS 0x62656572
- switch (f_type) {
- case S_MAGIC_AFFS: return "affs";
- case S_MAGIC_DEVPTS: return "devpts";
- case S_MAGIC_EXT: return "ext";
- case S_MAGIC_EXT2_OLD: return "ext2";
- case S_MAGIC_EXT2: return "ext2/ext3";
- case S_MAGIC_JFS: return "jfs";
- case S_MAGIC_XFS: return "xfs";
- case S_MAGIC_HPFS: return "hpfs";
- case S_MAGIC_ISOFS: return "isofs";
- case S_MAGIC_ISOFS_WIN: return "isofs";
- case S_MAGIC_ISOFS_R_WIN: return "isofs";
- case S_MAGIC_MINIX: return "minix";
- case S_MAGIC_MINIX_30: return "minix (30 char.)";
- case S_MAGIC_MINIX_V2: return "minix v2";
- case S_MAGIC_MINIX_V2_30: return "minix v2 (30 char.)";
- case S_MAGIC_MSDOS: return "msdos";
- case S_MAGIC_FAT: return "fat";
- case S_MAGIC_NCP: return "novell";
- case S_MAGIC_NFS: return "nfs";
- case S_MAGIC_PROC: return "proc";
- case S_MAGIC_SMB: return "smb";
- case S_MAGIC_XENIX: return "xenix";
- case S_MAGIC_SYSV4: return "sysv4";
- case S_MAGIC_SYSV2: return "sysv2";
- case S_MAGIC_COH: return "coh";
- case S_MAGIC_UFS: return "ufs";
- case S_MAGIC_XIAFS: return "xia";
- case S_MAGIC_NTFS: return "ntfs";
- case S_MAGIC_TMPFS: return "tmpfs";
- case S_MAGIC_REISERFS: return "reiserfs";
- case S_MAGIC_CRAMFS: return "cramfs";
- case S_MAGIC_ROMFS: return "romfs";
- case S_MAGIC_RAMFS: return "ramfs";
- case S_MAGIC_SQUASHFS: return "squashfs";
- case S_MAGIC_SYSFS: return "sysfs";
- default: {
- static char buf[sizeof("UNKNOWN (0x%lx)") - 3
- + (sizeof(f_type) * CHAR_BIT + 3) / 4];
- sprintf(buf, "UNKNOWN (0x%lx)", f_type);
- return buf;
- }
- }
+ int i;
+ static const struct types {
+ long type;
+ const char *fs;
+ } humantypes[] = {
+ { 0xADFF, "affs" },
+ { 0x1Cd1, "devpts" },
+ { 0x137D, "ext" },
+ { 0xEF51, "ext2" },
+ { 0xEF53, "ext2/ext3" },
+ { 0x3153464a, "jfs" },
+ { 0x58465342, "xfs" },
+ { 0xF995E849, "hpfs" },
+ { 0x9660, "isofs" },
+ { 0x4000, "isofs" },
+ { 0x4004, "isofs" },
+ { 0x137F, "minix" },
+ { 0x138F, "minix (30 char.)" },
+ { 0x2468, "minix v2" },
+ { 0x2478, "minix v2 (30 char.)" },
+ { 0x4d44, "msdos" },
+ { 0x4006, "fat" },
+ { 0x564c, "novell" },
+ { 0x6969, "nfs" },
+ { 0x9fa0, "proc" },
+ { 0x517B, "smb" },
+ { 0x012FF7B4, "xenix" },
+ { 0x012FF7B5, "sysv4" },
+ { 0x012FF7B6, "sysv2" },
+ { 0x012FF7B7, "coh" },
+ { 0x00011954, "ufs" },
+ { 0x012FD16D, "xia" },
+ { 0x5346544e, "ntfs" },
+ { 0x1021994, "tmpfs" },
+ { 0x52654973, "reiserfs" },
+ { 0x28cd3d45, "cramfs" },
+ { 0x7275, "romfs" },
+ { 0x858458f6, "romfs" },
+ { 0x73717368, "squashfs" },
+ { 0x62656572, "sysfs" },
+ { 0, "UNKNOWN" }
+ };
+ for (i=0; humantypes[i].type; ++i)
+ if (humantypes[i].type == f_type)
+ break;
+ return humantypes[i].fs;
}
#ifdef CONFIG_FEATURE_STAT_FORMAT
/* print statfs info */
-static void print_statfs(char *pformat, size_t buf_len, char m,
- char const *filename, void const *data)
+static void print_statfs(char *pformat, size_t buf_len, char m,
+ char const *filename, void const *data)
{
struct statfs const *statfsbuf = data;
printf(pformat, human_fstype(statfsbuf->f_type));
break;
case 'b':
- strncat(pformat, "ld", buf_len);
+ strncat(pformat, "jd", buf_len);
printf(pformat, (intmax_t) (statfsbuf->f_blocks));
break;
case 'f':
- strncat(pformat, "ld", buf_len);
+ strncat(pformat, "jd", buf_len);
printf(pformat, (intmax_t) (statfsbuf->f_bfree));
break;
case 'a':
- strncat(pformat, "ld", buf_len);
+ strncat(pformat, "jd", buf_len);
printf(pformat, (intmax_t) (statfsbuf->f_bavail));
break;
+ case 'S':
case 's':
strncat(pformat, "lu", buf_len);
printf(pformat, (unsigned long int) (statfsbuf->f_bsize));
break;
- case 'S': {
- unsigned long int frsize = statfsbuf->f_frsize;
- if (!frsize)
- frsize = statfsbuf->f_bsize;
- strncat(pformat, "lu", buf_len);
- printf(pformat, frsize);
- break;
- }
case 'c':
- strncat(pformat, "ld", buf_len);
+ strncat(pformat, "jd", buf_len);
printf(pformat, (intmax_t) (statfsbuf->f_files));
break;
case 'd':
- strncat(pformat, "ld", buf_len);
+ strncat(pformat, "jd", buf_len);
printf(pformat, (intmax_t) (statfsbuf->f_ffree));
break;
default:
}
/* print stat info */
-static void print_stat(char *pformat, size_t buf_len, char m,
- char const *filename, void const *data)
+static void print_stat(char *pformat, size_t buf_len, char m,
+ char const *filename, void const *data)
{
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
struct stat *statbuf = (struct stat *) data;
}
break;
case 'd':
- strncat(pformat, "lu", buf_len);
+ strncat(pformat, "ju", buf_len);
printf(pformat, (uintmax_t) statbuf->st_dev);
break;
case 'D':
- strncat(pformat, "lx", buf_len);
+ strncat(pformat, "jx", buf_len);
printf(pformat, (uintmax_t) statbuf->st_dev);
break;
case 'i':
- strncat(pformat, "lu", buf_len);
+ strncat(pformat, "ju", buf_len);
printf(pformat, (uintmax_t) statbuf->st_ino);
break;
case 'a':
printf(pformat, (unsigned long int) minor(statbuf->st_rdev));
break;
case 's':
- strncat(pformat, "lu", buf_len);
+ strncat(pformat, "ju", buf_len);
printf(pformat, (uintmax_t) (statbuf->st_size));
break;
case 'B':
printf(pformat, (unsigned long int) 512); //ST_NBLOCKSIZE
break;
case 'b':
- strncat(pformat, "lu", buf_len);
+ strncat(pformat, "ju", buf_len);
printf(pformat, (uintmax_t) statbuf->st_blocks);
break;
case 'o':
}
}
-static void print_it(char const *masterformat, char const *filename,
- void (*print_func) (char *, size_t, char, char const *, void const *),
- void const *data)
+static void print_it(char const *masterformat, char const *filename,
+ void (*print_func) (char *, size_t, char, char const *, void const *),
+ void const *data)
{
char *b;
#ifdef CONFIG_FEATURE_STAT_FORMAT
if (format == NULL)
- format = (terse
- ? "%n %i %l %t %s %S %b %f %a %c %d\n"
+ format = (flags & OPT_TERSE
+ ? "%n %i %l %t %s %b %f %a %c %d\n"
: " File: \"%n\"\n"
" ID: %-8i Namelen: %-7l Type: %T\n"
- "Block size: %-10s Fundamental block size: %S\n"
+ "Block size: %-10s\n"
"Blocks: Total: %-10b Free: %-10f Available: %a\n"
"Inodes: Total: %-10c Free: %d\n");
print_it(format, filename, print_statfs, &statfsbuf);
#else
- format = (terse
- ? "%s %Lx %lu "
+ format = (flags & OPT_TERSE
+ ? "%s %llx %lu "
: " File: \"%s\"\n"
" ID: %-8Lx Namelen: %-7lu ");
printf(format,
statfsbuf.f_fsid,
statfsbuf.f_namelen);
- if (terse)
+ if (flags & OPT_TERSE)
printf("%lx ", (unsigned long int) (statfsbuf.f_type));
else
printf("Type: %s\n", human_fstype(statfsbuf.f_type));
- format = (terse
- ? "%lu %lu %ld %ld %ld %ld %ld\n"
- : "Block size: %-10lu Fundamental block size: %lu\n"
- "Blocks: Total: %-10ld Free: %-10ld Available: %ld\n"
- "Inodes: Total: %-10ld Free: %ld\n");
+ format = (flags & OPT_TERSE
+ ? "%lu %ld %ld %ld %ld %ld\n"
+ : "Block size: %-10lu\n"
+ "Blocks: Total: %-10jd Free: %-10jd Available: %jd\n"
+ "Inodes: Total: %-10jd Free: %jd\n");
printf(format,
(unsigned long int) (statfsbuf.f_bsize),
- statfsbuf.f_frsize ? statfsbuf.f_frsize : statfsbuf.f_bsize,
(intmax_t) (statfsbuf.f_blocks),
(intmax_t) (statfsbuf.f_bfree),
(intmax_t) (statfsbuf.f_bavail),
{
struct stat statbuf;
- if ((follow_links ? stat : lstat) (filename, &statbuf) != 0) {
+ if ((flags & OPT_DEREFERENCE ? stat : lstat) (filename, &statbuf) != 0) {
bb_perror_msg("cannot stat '%s'", filename);
return 0;
}
#ifdef CONFIG_FEATURE_STAT_FORMAT
if (format == NULL) {
- if (terse) {
+ if (flags & OPT_TERSE) {
format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o\n";
} else {
if (S_ISBLK(statbuf.st_mode) || S_ISCHR(statbuf.st_mode)) {
}
print_it(format, filename, print_stat, &statbuf);
#else
- if (terse) {
- printf("%s %lu %lu %lx %lu %lu %lx %lu %lu %lx %lx %lu %lu %lu %lu\n",
+ if (flags & OPT_TERSE) {
+ printf("%s %ju %ju %lx %lu %lu %jx %ju %lu %lx %lx %lu %lu %lu %lu\n",
filename,
(uintmax_t) (statbuf.st_size),
(uintmax_t) statbuf.st_blocks,
else
printf(" File: \"%s\"\n", filename);
- printf(" Size: %-10lu\tBlocks: %-10lu IO Block: %-6lu %s\n"
- "Device: %lxh/%lud\tInode: %-10lu Links: %-5lu",
+ printf(" Size: %-10ju\tBlocks: %-10ju IO Block: %-6lu %s\n"
+ "Device: %jxh/%jud\tInode: %-10ju Links: %-5lu",
(uintmax_t) (statbuf.st_size),
(uintmax_t) statbuf.st_blocks,
(unsigned long int) statbuf.st_blksize,
int i;
char *format = NULL;
int ok = 1;
- long flags;
int (*statfunc)(char const *, char const *) = do_stat;
- flags = bb_getopt_ulflags(argc, argv, "fLlt"
-#ifdef CONFIG_FEATURE_STAT_FORMAT
- "c:", &format
-#endif
+ flags = bb_getopt_ulflags(argc, argv, "ftL"
+ USE_FEATURE_STAT_FORMAT("c:", &format)
);
if (flags & 1) /* -f */
statfunc = do_statfs;
- if (flags & 2 || flags & 4) /* -L, -l */
- follow_links = 1;
- if (flags & 8) /* -t */
- terse = 1;
if (argc == optind) /* files */
bb_show_usage();