Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/coreutils/stat.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 816 - (hide annotations) (download)
Fri Apr 24 18:33:46 2009 UTC (15 years, 1 month ago) by niro
File MIME type: text/plain
File size: 19765 byte(s)
-updated to busybox-1.13.4
1 niro 532 /* vi: set sw=4 ts=4: */
2     /*
3     * stat -- display file or file system status
4     *
5     * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation.
6     * Copyright (C) 2005 by Erik Andersen <andersen@codepoet.org>
7     * Copyright (C) 2005 by Mike Frysinger <vapier@gentoo.org>
8 niro 816 * Copyright (C) 2006 by Yoshinori Sato <ysato@users.sourceforge.jp>
9 niro 532 *
10     * Written by Michael Meskes
11     * Taken from coreutils and turned into a busybox applet by Mike Frysinger
12     *
13     * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
14     */
15    
16 niro 816 #include "libbb.h"
17 niro 532
18     /* vars to control behavior */
19 niro 816 #define OPT_FILESYS (1 << 0)
20     #define OPT_TERSE (1 << 1)
21     #define OPT_DEREFERENCE (1 << 2)
22     #define OPT_SELINUX (1 << 3)
23 niro 532
24 niro 816 #if ENABLE_FEATURE_STAT_FORMAT
25     typedef bool (*statfunc_ptr)(const char *, const char *);
26     #else
27     typedef bool (*statfunc_ptr)(const char *);
28     #endif
29    
30     static const char *file_type(const struct stat *st)
31 niro 532 {
32     /* See POSIX 1003.1-2001 XCU Table 4-8 lines 17093-17107
33     * for some of these formats.
34     * To keep diagnostics grammatical in English, the
35     * returned string must start with a consonant.
36     */
37     if (S_ISREG(st->st_mode)) return st->st_size == 0 ? "regular empty file" : "regular file";
38     if (S_ISDIR(st->st_mode)) return "directory";
39     if (S_ISBLK(st->st_mode)) return "block special file";
40     if (S_ISCHR(st->st_mode)) return "character special file";
41     if (S_ISFIFO(st->st_mode)) return "fifo";
42     if (S_ISLNK(st->st_mode)) return "symbolic link";
43     if (S_ISSOCK(st->st_mode)) return "socket";
44     if (S_TYPEISMQ(st)) return "message queue";
45     if (S_TYPEISSEM(st)) return "semaphore";
46     if (S_TYPEISSHM(st)) return "shared memory object";
47     #ifdef S_TYPEISTMO
48     if (S_TYPEISTMO(st)) return "typed memory object";
49     #endif
50     return "weird file";
51     }
52    
53 niro 816 static const char *human_time(time_t t)
54 niro 532 {
55     /* Old
56     static char *str;
57     str = ctime(&t);
58     str[strlen(str)-1] = '\0';
59     return str;
60     */
61     /* coreutils 6.3 compat: */
62 niro 816
63     /*static char buf[sizeof("YYYY-MM-DD HH:MM:SS.000000000")] ALIGN1;*/
64     #define buf bb_common_bufsiz1
65    
66 niro 532 strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S.000000000", localtime(&t));
67     return buf;
68 niro 816 #undef buf
69 niro 532 }
70    
71     /* Return the type of the specified file system.
72     * Some systems have statfvs.f_basetype[FSTYPSZ]. (AIX, HP-UX, and Solaris)
73     * Others have statfs.f_fstypename[MFSNAMELEN]. (NetBSD 1.5.2)
74     * Still others have neither and have to get by with f_type (Linux).
75     */
76 niro 816 static const char *human_fstype(uint32_t f_type)
77 niro 532 {
78     static const struct types {
79 niro 816 uint32_t type;
80     const char *const fs;
81 niro 532 } humantypes[] = {
82     { 0xADFF, "affs" },
83     { 0x1Cd1, "devpts" },
84     { 0x137D, "ext" },
85     { 0xEF51, "ext2" },
86     { 0xEF53, "ext2/ext3" },
87     { 0x3153464a, "jfs" },
88     { 0x58465342, "xfs" },
89     { 0xF995E849, "hpfs" },
90     { 0x9660, "isofs" },
91     { 0x4000, "isofs" },
92     { 0x4004, "isofs" },
93     { 0x137F, "minix" },
94     { 0x138F, "minix (30 char.)" },
95     { 0x2468, "minix v2" },
96     { 0x2478, "minix v2 (30 char.)" },
97     { 0x4d44, "msdos" },
98     { 0x4006, "fat" },
99     { 0x564c, "novell" },
100     { 0x6969, "nfs" },
101     { 0x9fa0, "proc" },
102     { 0x517B, "smb" },
103     { 0x012FF7B4, "xenix" },
104     { 0x012FF7B5, "sysv4" },
105     { 0x012FF7B6, "sysv2" },
106     { 0x012FF7B7, "coh" },
107     { 0x00011954, "ufs" },
108     { 0x012FD16D, "xia" },
109     { 0x5346544e, "ntfs" },
110     { 0x1021994, "tmpfs" },
111     { 0x52654973, "reiserfs" },
112     { 0x28cd3d45, "cramfs" },
113     { 0x7275, "romfs" },
114     { 0x858458f6, "romfs" },
115     { 0x73717368, "squashfs" },
116     { 0x62656572, "sysfs" },
117     { 0, "UNKNOWN" }
118     };
119 niro 816
120     int i;
121    
122     for (i = 0; humantypes[i].type; ++i)
123 niro 532 if (humantypes[i].type == f_type)
124     break;
125     return humantypes[i].fs;
126     }
127    
128 niro 816 #if ENABLE_FEATURE_STAT_FORMAT
129     static void strcatc(char *str, char c)
130     {
131     int len = strlen(str);
132     str[len++] = c;
133     str[len] = '\0';
134     }
135    
136     static void printfs(char *pformat, const char *msg)
137     {
138     strcatc(pformat, 's');
139     printf(pformat, msg);
140     }
141    
142 niro 532 /* print statfs info */
143 niro 816 static void print_statfs(char *pformat, const char m,
144     const char *const filename, const void *data
145     USE_SELINUX(, security_context_t scontext))
146 niro 532 {
147 niro 816 const struct statfs *statfsbuf = data;
148     if (m == 'n') {
149     printfs(pformat, filename);
150     } else if (m == 'i') {
151     strcat(pformat, "Lx");
152 niro 532 printf(pformat, statfsbuf->f_fsid);
153 niro 816 } else if (m == 'l') {
154     strcat(pformat, "lu");
155 niro 532 printf(pformat, statfsbuf->f_namelen);
156 niro 816 } else if (m == 't') {
157     strcat(pformat, "lx");
158     printf(pformat, (unsigned long) (statfsbuf->f_type)); /* no equiv */
159     } else if (m == 'T') {
160     printfs(pformat, human_fstype(statfsbuf->f_type));
161     } else if (m == 'b') {
162     strcat(pformat, "jd");
163 niro 532 printf(pformat, (intmax_t) (statfsbuf->f_blocks));
164 niro 816 } else if (m == 'f') {
165     strcat(pformat, "jd");
166 niro 532 printf(pformat, (intmax_t) (statfsbuf->f_bfree));
167 niro 816 } else if (m == 'a') {
168     strcat(pformat, "jd");
169 niro 532 printf(pformat, (intmax_t) (statfsbuf->f_bavail));
170 niro 816 } else if (m == 's' || m == 'S') {
171     strcat(pformat, "lu");
172     printf(pformat, (unsigned long) (statfsbuf->f_bsize));
173     } else if (m == 'c') {
174     strcat(pformat, "jd");
175 niro 532 printf(pformat, (intmax_t) (statfsbuf->f_files));
176 niro 816 } else if (m == 'd') {
177     strcat(pformat, "jd");
178 niro 532 printf(pformat, (intmax_t) (statfsbuf->f_ffree));
179 niro 816 #if ENABLE_SELINUX
180     } else if (m == 'C' && (option_mask32 & OPT_SELINUX)) {
181     printfs(pformat, scontext);
182     #endif
183     } else {
184     strcatc(pformat, 'c');
185 niro 532 printf(pformat, m);
186     }
187     }
188    
189     /* print stat info */
190 niro 816 static void print_stat(char *pformat, const char m,
191     const char *const filename, const void *data
192     USE_SELINUX(, security_context_t scontext))
193 niro 532 {
194     #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
195     struct stat *statbuf = (struct stat *) data;
196     struct passwd *pw_ent;
197     struct group *gw_ent;
198    
199 niro 816 if (m == 'n') {
200     printfs(pformat, filename);
201     } else if (m == 'N') {
202     strcatc(pformat, 's');
203 niro 532 if (S_ISLNK(statbuf->st_mode)) {
204 niro 816 char *linkname = xmalloc_readlink_or_warn(filename);
205     if (linkname == NULL)
206 niro 532 return;
207     /*printf("\"%s\" -> \"%s\"", filename, linkname); */
208     printf(pformat, filename);
209     printf(" -> ");
210     printf(pformat, linkname);
211 niro 816 free(linkname);
212 niro 532 } else {
213     printf(pformat, filename);
214     }
215 niro 816 } else if (m == 'd') {
216     strcat(pformat, "ju");
217 niro 532 printf(pformat, (uintmax_t) statbuf->st_dev);
218 niro 816 } else if (m == 'D') {
219     strcat(pformat, "jx");
220 niro 532 printf(pformat, (uintmax_t) statbuf->st_dev);
221 niro 816 } else if (m == 'i') {
222     strcat(pformat, "ju");
223 niro 532 printf(pformat, (uintmax_t) statbuf->st_ino);
224 niro 816 } else if (m == 'a') {
225     strcat(pformat, "lo");
226     printf(pformat, (unsigned long) (statbuf->st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)));
227     } else if (m == 'A') {
228     printfs(pformat, bb_mode_string(statbuf->st_mode));
229     } else if (m == 'f') {
230     strcat(pformat, "lx");
231     printf(pformat, (unsigned long) statbuf->st_mode);
232     } else if (m == 'F') {
233     printfs(pformat, file_type(statbuf));
234     } else if (m == 'h') {
235     strcat(pformat, "lu");
236     printf(pformat, (unsigned long) statbuf->st_nlink);
237     } else if (m == 'u') {
238     strcat(pformat, "lu");
239     printf(pformat, (unsigned long) statbuf->st_uid);
240     } else if (m == 'U') {
241 niro 532 setpwent();
242     pw_ent = getpwuid(statbuf->st_uid);
243 niro 816 printfs(pformat, (pw_ent != NULL) ? pw_ent->pw_name : "UNKNOWN");
244     } else if (m == 'g') {
245     strcat(pformat, "lu");
246     printf(pformat, (unsigned long) statbuf->st_gid);
247     } else if (m == 'G') {
248 niro 532 setgrent();
249     gw_ent = getgrgid(statbuf->st_gid);
250 niro 816 printfs(pformat, (gw_ent != NULL) ? gw_ent->gr_name : "UNKNOWN");
251     } else if (m == 't') {
252     strcat(pformat, "lx");
253     printf(pformat, (unsigned long) major(statbuf->st_rdev));
254     } else if (m == 'T') {
255     strcat(pformat, "lx");
256     printf(pformat, (unsigned long) minor(statbuf->st_rdev));
257     } else if (m == 's') {
258     strcat(pformat, "ju");
259 niro 532 printf(pformat, (uintmax_t) (statbuf->st_size));
260 niro 816 } else if (m == 'B') {
261     strcat(pformat, "lu");
262     printf(pformat, (unsigned long) 512); //ST_NBLOCKSIZE
263     } else if (m == 'b') {
264     strcat(pformat, "ju");
265 niro 532 printf(pformat, (uintmax_t) statbuf->st_blocks);
266 niro 816 } else if (m == 'o') {
267     strcat(pformat, "lu");
268     printf(pformat, (unsigned long) statbuf->st_blksize);
269     } else if (m == 'x') {
270     printfs(pformat, human_time(statbuf->st_atime));
271     } else if (m == 'X') {
272     strcat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu");
273     printf(pformat, (unsigned long) statbuf->st_atime);
274     } else if (m == 'y') {
275     printfs(pformat, human_time(statbuf->st_mtime));
276     } else if (m == 'Y') {
277     strcat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu");
278     printf(pformat, (unsigned long) statbuf->st_mtime);
279     } else if (m == 'z') {
280     printfs(pformat, human_time(statbuf->st_ctime));
281     } else if (m == 'Z') {
282     strcat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu");
283     printf(pformat, (unsigned long) statbuf->st_ctime);
284     #if ENABLE_SELINUX
285     } else if (m == 'C' && (option_mask32 & OPT_SELINUX)) {
286     printfs(pformat, scontext);
287     #endif
288     } else {
289     strcatc(pformat, 'c');
290 niro 532 printf(pformat, m);
291     }
292     }
293    
294 niro 816 static void print_it(const char *masterformat, const char *filename,
295     void (*print_func) (char*, char, const char*, const void* USE_SELINUX(, security_context_t scontext)),
296     const void *data
297     USE_SELINUX(, security_context_t scontext) )
298 niro 532 {
299 niro 816 /* Create a working copy of the format string */
300 niro 532 char *format = xstrdup(masterformat);
301     /* Add 2 to accomodate our conversion of the stat '%s' format string
302     * to the printf '%llu' one. */
303 niro 816 char *dest = xmalloc(strlen(format) + 2 + 1);
304     char *b;
305 niro 532
306     b = format;
307     while (b) {
308     size_t len;
309     char *p = strchr(b, '%');
310     if (!p) {
311 niro 816 /* coreutils 6.3 always prints <cr> at the end */
312 niro 532 /*fputs(b, stdout);*/
313     puts(b);
314     break;
315     }
316     *p++ = '\0';
317     fputs(b, stdout);
318    
319 niro 816 /* dest = "%<modifiers>" */
320 niro 532 len = strspn(p, "#-+.I 0123456789");
321     dest[0] = '%';
322     memcpy(dest + 1, p, len);
323 niro 816 dest[1 + len] = '\0';
324 niro 532 p += len;
325    
326     b = p + 1;
327     switch (*p) {
328     case '\0':
329     b = NULL;
330     /* fall through */
331     case '%':
332 niro 816 bb_putchar('%');
333 niro 532 break;
334     default:
335 niro 816 /* Completes "%<modifiers>" with specifier and printfs */
336     print_func(dest, *p, filename, data USE_SELINUX(,scontext));
337 niro 532 break;
338     }
339     }
340    
341     free(format);
342     free(dest);
343     }
344     #endif
345    
346     /* Stat the file system and print what we find. */
347 niro 816 #if !ENABLE_FEATURE_STAT_FORMAT
348     #define do_statfs(filename, format) do_statfs(filename)
349     #endif
350     static bool do_statfs(const char *filename, const char *format)
351 niro 532 {
352 niro 816 #if !ENABLE_FEATURE_STAT_FORMAT
353     const char *format;
354     #endif
355 niro 532 struct statfs statfsbuf;
356 niro 816 #if ENABLE_SELINUX
357     security_context_t scontext = NULL;
358 niro 532
359 niro 816 if (option_mask32 & OPT_SELINUX) {
360     if ((option_mask32 & OPT_DEREFERENCE
361     ? lgetfilecon(filename, &scontext)
362     : getfilecon(filename, &scontext)
363     ) < 0
364     ) {
365     bb_perror_msg(filename);
366     return 0;
367     }
368     }
369     #endif
370 niro 532 if (statfs(filename, &statfsbuf) != 0) {
371     bb_perror_msg("cannot read file system information for '%s'", filename);
372     return 0;
373     }
374    
375 niro 816 #if ENABLE_FEATURE_STAT_FORMAT
376     if (format == NULL) {
377     #if !ENABLE_SELINUX
378     format = (option_mask32 & OPT_TERSE
379 niro 532 ? "%n %i %l %t %s %b %f %a %c %d\n"
380     : " File: \"%n\"\n"
381     " ID: %-8i Namelen: %-7l Type: %T\n"
382     "Block size: %-10s\n"
383     "Blocks: Total: %-10b Free: %-10f Available: %a\n"
384     "Inodes: Total: %-10c Free: %d");
385     #else
386 niro 816 format = (option_mask32 & OPT_TERSE
387     ? (option_mask32 & OPT_SELINUX ? "%n %i %l %t %s %b %f %a %c %d %C\n":
388     "%n %i %l %t %s %b %f %a %c %d\n")
389     : (option_mask32 & OPT_SELINUX ?
390     " File: \"%n\"\n"
391     " ID: %-8i Namelen: %-7l Type: %T\n"
392     "Block size: %-10s\n"
393     "Blocks: Total: %-10b Free: %-10f Available: %a\n"
394     "Inodes: Total: %-10c Free: %d"
395     " S_context: %C\n":
396     " File: \"%n\"\n"
397     " ID: %-8i Namelen: %-7l Type: %T\n"
398     "Block size: %-10s\n"
399     "Blocks: Total: %-10b Free: %-10f Available: %a\n"
400     "Inodes: Total: %-10c Free: %d\n")
401     );
402     #endif /* SELINUX */
403     }
404     print_it(format, filename, print_statfs, &statfsbuf USE_SELINUX(, scontext));
405     #else /* FEATURE_STAT_FORMAT */
406     format = (option_mask32 & OPT_TERSE
407 niro 532 ? "%s %llx %lu "
408     : " File: \"%s\"\n"
409     " ID: %-8Lx Namelen: %-7lu ");
410     printf(format,
411     filename,
412     statfsbuf.f_fsid,
413     statfsbuf.f_namelen);
414    
415 niro 816 if (option_mask32 & OPT_TERSE)
416     printf("%lx ", (unsigned long) (statfsbuf.f_type));
417 niro 532 else
418     printf("Type: %s\n", human_fstype(statfsbuf.f_type));
419    
420 niro 816 #if !ENABLE_SELINUX
421     format = (option_mask32 & OPT_TERSE
422 niro 532 ? "%lu %ld %ld %ld %ld %ld\n"
423     : "Block size: %-10lu\n"
424     "Blocks: Total: %-10jd Free: %-10jd Available: %jd\n"
425     "Inodes: Total: %-10jd Free: %jd\n");
426     printf(format,
427 niro 816 (unsigned long) (statfsbuf.f_bsize),
428 niro 532 (intmax_t) (statfsbuf.f_blocks),
429     (intmax_t) (statfsbuf.f_bfree),
430     (intmax_t) (statfsbuf.f_bavail),
431     (intmax_t) (statfsbuf.f_files),
432     (intmax_t) (statfsbuf.f_ffree));
433 niro 816 #else
434     format = (option_mask32 & OPT_TERSE
435     ? (option_mask32 & OPT_SELINUX ? "%lu %ld %ld %ld %ld %ld %C\n":
436     "%lu %ld %ld %ld %ld %ld\n")
437     : (option_mask32 & OPT_SELINUX ?
438     "Block size: %-10lu\n"
439     "Blocks: Total: %-10jd Free: %-10jd Available: %jd\n"
440     "Inodes: Total: %-10jd Free: %jd"
441     "S_context: %C\n":
442     "Block size: %-10lu\n"
443     "Blocks: Total: %-10jd Free: %-10jd Available: %jd\n"
444     "Inodes: Total: %-10jd Free: %jd\n"));
445     printf(format,
446     (unsigned long) (statfsbuf.f_bsize),
447     (intmax_t) (statfsbuf.f_blocks),
448     (intmax_t) (statfsbuf.f_bfree),
449     (intmax_t) (statfsbuf.f_bavail),
450     (intmax_t) (statfsbuf.f_files),
451     (intmax_t) (statfsbuf.f_ffree),
452     scontext);
453    
454     if (scontext)
455     freecon(scontext);
456 niro 532 #endif
457 niro 816 #endif /* FEATURE_STAT_FORMAT */
458 niro 532 return 1;
459     }
460    
461     /* stat the file and print what we find */
462 niro 816 #if !ENABLE_FEATURE_STAT_FORMAT
463     #define do_stat(filename, format) do_stat(filename)
464     #endif
465     static bool do_stat(const char *filename, const char *format)
466 niro 532 {
467     struct stat statbuf;
468 niro 816 #if ENABLE_SELINUX
469     security_context_t scontext = NULL;
470 niro 532
471 niro 816 if (option_mask32 & OPT_SELINUX) {
472     if ((option_mask32 & OPT_DEREFERENCE
473     ? lgetfilecon(filename, &scontext)
474     : getfilecon(filename, &scontext)
475     ) < 0
476     ) {
477     bb_perror_msg(filename);
478     return 0;
479     }
480     }
481     #endif
482     if ((option_mask32 & OPT_DEREFERENCE ? stat : lstat) (filename, &statbuf) != 0) {
483 niro 532 bb_perror_msg("cannot stat '%s'", filename);
484     return 0;
485     }
486    
487 niro 816 #if ENABLE_FEATURE_STAT_FORMAT
488 niro 532 if (format == NULL) {
489 niro 816 #if !ENABLE_SELINUX
490     if (option_mask32 & OPT_TERSE) {
491 niro 532 format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o";
492     } else {
493     if (S_ISBLK(statbuf.st_mode) || S_ISCHR(statbuf.st_mode)) {
494     format =
495     " File: \"%N\"\n"
496     " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
497     "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
498     " Device type: %t,%T\n"
499     "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
500     "Access: %x\n" "Modify: %y\n" "Change: %z\n";
501     } else {
502     format =
503     " File: \"%N\"\n"
504     " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
505     "Device: %Dh/%dd\tInode: %-10i Links: %h\n"
506     "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
507     "Access: %x\n" "Modify: %y\n" "Change: %z\n";
508     }
509     }
510 niro 816 #else
511     if (option_mask32 & OPT_TERSE) {
512     format = (option_mask32 & OPT_SELINUX ?
513     "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o %C\n":
514     "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o\n");
515     } else {
516     if (S_ISBLK(statbuf.st_mode) || S_ISCHR(statbuf.st_mode)) {
517     format = (option_mask32 & OPT_SELINUX ?
518     " File: \"%N\"\n"
519     " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
520     "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
521     " Device type: %t,%T\n"
522     "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
523     " S_Context: %C\n"
524     "Access: %x\n" "Modify: %y\n" "Change: %z\n":
525     " File: \"%N\"\n"
526     " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
527     "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
528     " Device type: %t,%T\n"
529     "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
530     "Access: %x\n" "Modify: %y\n" "Change: %z\n");
531     } else {
532     format = (option_mask32 & OPT_SELINUX ?
533     " File: \"%N\"\n"
534     " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
535     "Device: %Dh/%dd\tInode: %-10i Links: %h\n"
536     "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
537     "S_Context: %C\n"
538     "Access: %x\n" "Modify: %y\n" "Change: %z\n":
539     " File: \"%N\"\n"
540     " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
541     "Device: %Dh/%dd\tInode: %-10i Links: %h\n"
542     "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
543     "Access: %x\n" "Modify: %y\n" "Change: %z\n");
544     }
545     }
546     #endif
547 niro 532 }
548 niro 816 print_it(format, filename, print_stat, &statbuf USE_SELINUX(, scontext));
549     #else /* FEATURE_STAT_FORMAT */
550     if (option_mask32 & OPT_TERSE) {
551     printf("%s %ju %ju %lx %lu %lu %jx %ju %lu %lx %lx %lu %lu %lu %lu"
552     SKIP_SELINUX("\n"),
553 niro 532 filename,
554     (uintmax_t) (statbuf.st_size),
555     (uintmax_t) statbuf.st_blocks,
556 niro 816 (unsigned long) statbuf.st_mode,
557     (unsigned long) statbuf.st_uid,
558     (unsigned long) statbuf.st_gid,
559 niro 532 (uintmax_t) statbuf.st_dev,
560     (uintmax_t) statbuf.st_ino,
561 niro 816 (unsigned long) statbuf.st_nlink,
562     (unsigned long) major(statbuf.st_rdev),
563     (unsigned long) minor(statbuf.st_rdev),
564     (unsigned long) statbuf.st_atime,
565     (unsigned long) statbuf.st_mtime,
566     (unsigned long) statbuf.st_ctime,
567     (unsigned long) statbuf.st_blksize
568 niro 532 );
569 niro 816 #if ENABLE_SELINUX
570     if (option_mask32 & OPT_SELINUX)
571     printf(" %lc\n", *scontext);
572     else
573     bb_putchar('\n');
574     #endif
575 niro 532 } else {
576     char *linkname = NULL;
577    
578     struct passwd *pw_ent;
579     struct group *gw_ent;
580     setgrent();
581     gw_ent = getgrgid(statbuf.st_gid);
582     setpwent();
583     pw_ent = getpwuid(statbuf.st_uid);
584    
585     if (S_ISLNK(statbuf.st_mode))
586 niro 816 linkname = xmalloc_readlink_or_warn(filename);
587 niro 532 if (linkname)
588     printf(" File: \"%s\" -> \"%s\"\n", filename, linkname);
589     else
590     printf(" File: \"%s\"\n", filename);
591    
592     printf(" Size: %-10ju\tBlocks: %-10ju IO Block: %-6lu %s\n"
593     "Device: %jxh/%jud\tInode: %-10ju Links: %-5lu",
594     (uintmax_t) (statbuf.st_size),
595     (uintmax_t) statbuf.st_blocks,
596 niro 816 (unsigned long) statbuf.st_blksize,
597 niro 532 file_type(&statbuf),
598     (uintmax_t) statbuf.st_dev,
599     (uintmax_t) statbuf.st_dev,
600     (uintmax_t) statbuf.st_ino,
601 niro 816 (unsigned long) statbuf.st_nlink);
602 niro 532 if (S_ISBLK(statbuf.st_mode) || S_ISCHR(statbuf.st_mode))
603     printf(" Device type: %lx,%lx\n",
604 niro 816 (unsigned long) major(statbuf.st_rdev),
605     (unsigned long) minor(statbuf.st_rdev));
606 niro 532 else
607 niro 816 bb_putchar('\n');
608     printf("Access: (%04lo/%10.10s) Uid: (%5lu/%8s) Gid: (%5lu/%8s)\n",
609     (unsigned long) (statbuf.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)),
610 niro 532 bb_mode_string(statbuf.st_mode),
611 niro 816 (unsigned long) statbuf.st_uid,
612     (pw_ent != NULL) ? pw_ent->pw_name : "UNKNOWN",
613     (unsigned long) statbuf.st_gid,
614     (gw_ent != NULL) ? gw_ent->gr_name : "UNKNOWN");
615     #if ENABLE_SELINUX
616     printf(" S_Context: %lc\n", *scontext);
617     #endif
618     printf("Access: %s\n" "Modify: %s\n" "Change: %s\n",
619 niro 532 human_time(statbuf.st_atime),
620     human_time(statbuf.st_mtime),
621     human_time(statbuf.st_ctime));
622     }
623 niro 816 #endif /* FEATURE_STAT_FORMAT */
624 niro 532 return 1;
625     }
626    
627 niro 816 int stat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
628 niro 532 int stat_main(int argc, char **argv)
629     {
630 niro 816 USE_FEATURE_STAT_FORMAT(char *format = NULL;)
631 niro 532 int i;
632     int ok = 1;
633 niro 816 statfunc_ptr statfunc = do_stat;
634 niro 532
635 niro 816 getopt32(argv, "ftL"
636     USE_SELINUX("Z")
637 niro 532 USE_FEATURE_STAT_FORMAT("c:", &format)
638     );
639    
640 niro 816 if (option_mask32 & OPT_FILESYS) /* -f */
641 niro 532 statfunc = do_statfs;
642     if (argc == optind) /* files */
643     bb_show_usage();
644    
645 niro 816 #if ENABLE_SELINUX
646     if (option_mask32 & OPT_SELINUX) {
647     selinux_or_die();
648     }
649     #endif /* ENABLE_SELINUX */
650 niro 532 for (i = optind; i < argc; ++i)
651 niro 816 ok &= statfunc(argv[i] USE_FEATURE_STAT_FORMAT(, format));
652 niro 532
653     return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
654     }