use bb_xbind/bb_xlisten
[oweals/busybox.git] / coreutils / stat.c
index 536873fdc8e2c113abd67ff5237c26615359dc48..d58eae10e156edcd45f22aeb6bae0cc2a50c82fa 100644 (file)
@@ -1,3 +1,4 @@
+/* vi:set ts=4:*/
 /*
  * stat -- display file or file system status
  *
@@ -8,43 +9,33 @@
  * 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 */
 #define OPT_TERSE 2
-#define OPT_DEREFERNCE 4
+#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";
@@ -78,90 +69,58 @@ static char const *human_time(time_t t)
  */
 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;
 
@@ -187,35 +146,28 @@ static void print_statfs(char *pformat, size_t buf_len, char m,
                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:
@@ -226,8 +178,8 @@ static void print_statfs(char *pformat, size_t buf_len, char m,
 }
 
 /* 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;
@@ -256,15 +208,15 @@ static void print_stat(char *pformat, size_t buf_len, char m,
                }
                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':
@@ -316,7 +268,7 @@ static void print_stat(char *pformat, size_t buf_len, char m,
                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':
@@ -324,7 +276,7 @@ static void print_stat(char *pformat, size_t buf_len, char m,
                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':
@@ -362,9 +314,9 @@ static void print_stat(char *pformat, size_t buf_len, char m,
        }
 }
 
-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;
 
@@ -427,17 +379,17 @@ static int do_statfs(char const *filename, char const *format)
 #ifdef CONFIG_FEATURE_STAT_FORMAT
        if (format == NULL)
                format = (flags & OPT_TERSE
-                       ? "%n %i %l %t %s %S %b %f %a %c %d\n"
+                       ? "%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 = (flags & OPT_TERSE
-               ? "%s %Lx %lu "
+               ? "%s %llx %lu "
                : "  File: \"%s\"\n"
                  "    ID: %-8Lx Namelen: %-7lu ");
        printf(format,
@@ -451,13 +403,12 @@ static int do_statfs(char const *filename, char const *format)
                printf("Type: %s\n", human_fstype(statfsbuf.f_type));
 
        format = (flags & OPT_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");
+               ? "%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),
@@ -473,7 +424,7 @@ static int do_stat(char const *filename, char const *format)
 {
        struct stat statbuf;
 
-       if ((flags & OPT_DEREFERNCE ? stat : lstat) (filename, &statbuf) != 0) {
+       if ((flags & OPT_DEREFERENCE ? stat : lstat) (filename, &statbuf) != 0) {
                bb_perror_msg("cannot stat '%s'", filename);
                return 0;
        }
@@ -504,7 +455,7 @@ static int do_stat(char const *filename, char const *format)
        print_it(format, filename, print_stat, &statbuf);
 #else
        if (flags & OPT_TERSE) {
-               printf("%s %lu %lu %lx %lu %lu %lx %lu %lu %lx %lx %lu %lu %lu %lu\n",
+               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,
@@ -538,8 +489,8 @@ static int do_stat(char const *filename, char const *format)
                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,
@@ -578,9 +529,7 @@ int stat_main(int argc, char **argv)
        int (*statfunc)(char const *, char const *) = do_stat;
 
        flags = bb_getopt_ulflags(argc, argv, "ftL"
-#ifdef CONFIG_FEATURE_STAT_FORMAT
-       "c:", &format
-#endif
+       USE_FEATURE_STAT_FORMAT("c:", &format)
        );
 
        if (flags & 1)                /* -f */