125 |
return humantypes[i].fs; |
return humantypes[i].fs; |
126 |
} |
} |
127 |
|
|
128 |
|
/* "man statfs" says that statfsbuf->f_fsid is a mess */ |
129 |
|
/* coreutils treats it as an array of ints, most significant first */ |
130 |
|
static unsigned long long get_f_fsid(const struct statfs *statfsbuf) |
131 |
|
{ |
132 |
|
const unsigned *p = (const void*) &statfsbuf->f_fsid; |
133 |
|
unsigned sz = sizeof(statfsbuf->f_fsid) / sizeof(unsigned); |
134 |
|
unsigned long long r = 0; |
135 |
|
|
136 |
|
do |
137 |
|
r = (r << (sizeof(unsigned)*8)) | *p++; |
138 |
|
while (--sz > 0); |
139 |
|
return r; |
140 |
|
} |
141 |
|
|
142 |
#if ENABLE_FEATURE_STAT_FORMAT |
#if ENABLE_FEATURE_STAT_FORMAT |
143 |
static void strcatc(char *str, char c) |
static void strcatc(char *str, char c) |
144 |
{ |
{ |
156 |
/* print statfs info */ |
/* print statfs info */ |
157 |
static void print_statfs(char *pformat, const char m, |
static void print_statfs(char *pformat, const char m, |
158 |
const char *const filename, const void *data |
const char *const filename, const void *data |
159 |
USE_SELINUX(, security_context_t scontext)) |
IF_SELINUX(, security_context_t scontext)) |
160 |
{ |
{ |
161 |
const struct statfs *statfsbuf = data; |
const struct statfs *statfsbuf = data; |
162 |
if (m == 'n') { |
if (m == 'n') { |
163 |
printfs(pformat, filename); |
printfs(pformat, filename); |
164 |
} else if (m == 'i') { |
} else if (m == 'i') { |
165 |
strcat(pformat, "Lx"); |
strcat(pformat, "llx"); |
166 |
printf(pformat, statfsbuf->f_fsid); |
printf(pformat, get_f_fsid(statfsbuf)); |
167 |
} else if (m == 'l') { |
} else if (m == 'l') { |
168 |
strcat(pformat, "lu"); |
strcat(pformat, "lu"); |
169 |
printf(pformat, statfsbuf->f_namelen); |
printf(pformat, (unsigned long) (statfsbuf->f_namelen)); |
170 |
} else if (m == 't') { |
} else if (m == 't') { |
171 |
strcat(pformat, "lx"); |
strcat(pformat, "lx"); |
172 |
printf(pformat, (unsigned long) (statfsbuf->f_type)); /* no equiv */ |
printf(pformat, (unsigned long) (statfsbuf->f_type)); /* no equiv */ |
203 |
/* print stat info */ |
/* print stat info */ |
204 |
static void print_stat(char *pformat, const char m, |
static void print_stat(char *pformat, const char m, |
205 |
const char *const filename, const void *data |
const char *const filename, const void *data |
206 |
USE_SELINUX(, security_context_t scontext)) |
IF_SELINUX(, security_context_t scontext)) |
207 |
{ |
{ |
208 |
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) |
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) |
209 |
struct stat *statbuf = (struct stat *) data; |
struct stat *statbuf = (struct stat *) data; |
306 |
} |
} |
307 |
|
|
308 |
static void print_it(const char *masterformat, const char *filename, |
static void print_it(const char *masterformat, const char *filename, |
309 |
void (*print_func) (char*, char, const char*, const void* USE_SELINUX(, security_context_t scontext)), |
void (*print_func) (char*, char, const char*, const void* IF_SELINUX(, security_context_t scontext)), |
310 |
const void *data |
const void *data |
311 |
USE_SELINUX(, security_context_t scontext) ) |
IF_SELINUX(, security_context_t scontext) ) |
312 |
{ |
{ |
313 |
/* Create a working copy of the format string */ |
/* Create a working copy of the format string */ |
314 |
char *format = xstrdup(masterformat); |
char *format = xstrdup(masterformat); |
347 |
break; |
break; |
348 |
default: |
default: |
349 |
/* Completes "%<modifiers>" with specifier and printfs */ |
/* Completes "%<modifiers>" with specifier and printfs */ |
350 |
print_func(dest, *p, filename, data USE_SELINUX(,scontext)); |
print_func(dest, *p, filename, data IF_SELINUX(,scontext)); |
351 |
break; |
break; |
352 |
} |
} |
353 |
} |
} |
363 |
#endif |
#endif |
364 |
static bool do_statfs(const char *filename, const char *format) |
static bool do_statfs(const char *filename, const char *format) |
365 |
{ |
{ |
366 |
|
struct statfs statfsbuf; |
367 |
|
|
368 |
#if !ENABLE_FEATURE_STAT_FORMAT |
#if !ENABLE_FEATURE_STAT_FORMAT |
369 |
const char *format; |
const char *format; |
370 |
#endif |
#endif |
|
struct statfs statfsbuf; |
|
371 |
#if ENABLE_SELINUX |
#if ENABLE_SELINUX |
372 |
security_context_t scontext = NULL; |
security_context_t scontext = NULL; |
373 |
|
|
383 |
} |
} |
384 |
#endif |
#endif |
385 |
if (statfs(filename, &statfsbuf) != 0) { |
if (statfs(filename, &statfsbuf) != 0) { |
386 |
bb_perror_msg("cannot read file system information for '%s'", filename); |
bb_perror_msg("can't read file system information for '%s'", filename); |
387 |
return 0; |
return 0; |
388 |
} |
} |
389 |
|
|
416 |
); |
); |
417 |
#endif /* SELINUX */ |
#endif /* SELINUX */ |
418 |
} |
} |
419 |
print_it(format, filename, print_statfs, &statfsbuf USE_SELINUX(, scontext)); |
print_it(format, filename, print_statfs, &statfsbuf IF_SELINUX(, scontext)); |
420 |
#else /* FEATURE_STAT_FORMAT */ |
#else /* FEATURE_STAT_FORMAT */ |
421 |
format = (option_mask32 & OPT_TERSE |
format = (option_mask32 & OPT_TERSE |
422 |
? "%s %llx %lu " |
? "%s %llx %lu " |
423 |
: " File: \"%s\"\n" |
: " File: \"%s\"\n" |
424 |
" ID: %-8Lx Namelen: %-7lu "); |
" ID: %-8llx Namelen: %-7lu "); |
425 |
printf(format, |
printf(format, |
426 |
filename, |
filename, |
427 |
statfsbuf.f_fsid, |
get_f_fsid(&statfsbuf), |
428 |
statfsbuf.f_namelen); |
statfsbuf.f_namelen); |
429 |
|
|
430 |
if (option_mask32 & OPT_TERSE) |
if (option_mask32 & OPT_TERSE) |
495 |
} |
} |
496 |
#endif |
#endif |
497 |
if ((option_mask32 & OPT_DEREFERENCE ? stat : lstat) (filename, &statbuf) != 0) { |
if ((option_mask32 & OPT_DEREFERENCE ? stat : lstat) (filename, &statbuf) != 0) { |
498 |
bb_perror_msg("cannot stat '%s'", filename); |
bb_perror_msg("can't stat '%s'", filename); |
499 |
return 0; |
return 0; |
500 |
} |
} |
501 |
|
|
560 |
} |
} |
561 |
#endif |
#endif |
562 |
} |
} |
563 |
print_it(format, filename, print_stat, &statbuf USE_SELINUX(, scontext)); |
print_it(format, filename, print_stat, &statbuf IF_SELINUX(, scontext)); |
564 |
#else /* FEATURE_STAT_FORMAT */ |
#else /* FEATURE_STAT_FORMAT */ |
565 |
if (option_mask32 & OPT_TERSE) { |
if (option_mask32 & OPT_TERSE) { |
566 |
printf("%s %ju %ju %lx %lu %lu %jx %ju %lu %lx %lx %lu %lu %lu %lu" |
printf("%s %ju %ju %lx %lu %lu %jx %ju %lu %lx %lx %lu %lu %lu %lu" |
567 |
SKIP_SELINUX("\n"), |
IF_NOT_SELINUX("\n"), |
568 |
filename, |
filename, |
569 |
(uintmax_t) (statbuf.st_size), |
(uintmax_t) (statbuf.st_size), |
570 |
(uintmax_t) statbuf.st_blocks, |
(uintmax_t) statbuf.st_blocks, |
640 |
} |
} |
641 |
|
|
642 |
int stat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
int stat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
643 |
int stat_main(int argc, char **argv) |
int stat_main(int argc UNUSED_PARAM, char **argv) |
644 |
{ |
{ |
645 |
USE_FEATURE_STAT_FORMAT(char *format = NULL;) |
IF_FEATURE_STAT_FORMAT(char *format = NULL;) |
646 |
int i; |
int i; |
647 |
int ok = 1; |
int ok; |
648 |
|
unsigned opts; |
649 |
statfunc_ptr statfunc = do_stat; |
statfunc_ptr statfunc = do_stat; |
650 |
|
|
651 |
getopt32(argv, "ftL" |
opt_complementary = "-1"; /* min one arg */ |
652 |
USE_SELINUX("Z") |
opts = getopt32(argv, "ftL" |
653 |
USE_FEATURE_STAT_FORMAT("c:", &format) |
IF_SELINUX("Z") |
654 |
|
IF_FEATURE_STAT_FORMAT("c:", &format) |
655 |
); |
); |
656 |
|
if (opts & OPT_FILESYS) /* -f */ |
|
if (option_mask32 & OPT_FILESYS) /* -f */ |
|
657 |
statfunc = do_statfs; |
statfunc = do_statfs; |
|
if (argc == optind) /* files */ |
|
|
bb_show_usage(); |
|
|
|
|
658 |
#if ENABLE_SELINUX |
#if ENABLE_SELINUX |
659 |
if (option_mask32 & OPT_SELINUX) { |
if (opts & OPT_SELINUX) { |
660 |
selinux_or_die(); |
selinux_or_die(); |
661 |
} |
} |
662 |
#endif /* ENABLE_SELINUX */ |
#endif |
663 |
for (i = optind; i < argc; ++i) |
ok = 1; |
664 |
ok &= statfunc(argv[i] USE_FEATURE_STAT_FORMAT(, format)); |
argv += optind; |
665 |
|
for (i = 0; argv[i]; ++i) |
666 |
|
ok &= statfunc(argv[i] IF_FEATURE_STAT_FORMAT(, format)); |
667 |
|
|
668 |
return (ok ? EXIT_SUCCESS : EXIT_FAILURE); |
return (ok ? EXIT_SUCCESS : EXIT_FAILURE); |
669 |
} |
} |