5 #ifdef HAVE_SYS_SYSMACROS_H
6 # include <sys/sysmacros.h>
27 #include "xreadlink.h"
30 # include <selinux/fs_secure.h>
31 # include <linux/flask/security.h>
32 # include <selinux/flask_util.h> /* for is_flask_enabled() */
33 # define SECURITY_ID_T security_id_t
35 # define SECURITY_ID_T int
36 # define is_flask_enabled() 0
37 # define stat_secure(a,b,c) stat(a,b)
38 # define lstat_secure(a,b,c) lstat(a,b)
41 #define PROGRAM_NAME "stat"
43 #define AUTHORS "Michael Meskes"
45 static struct option const long_options[] = {
46 {"link", no_argument, 0, 'l'},
47 {"format", required_argument, 0, 'c'},
48 {"filesystem", no_argument, 0, 'f'},
49 {"secure", no_argument, 0, 's'},
50 {"terse", no_argument, 0, 't'},
51 {GETOPT_HELP_OPTION_DECL},
52 {GETOPT_VERSION_OPTION_DECL},
56 static char *program_name;
59 print_human_type (mode_t mode)
62 switch (mode & S_IFMT)
68 type = "Character Device";
71 type = "Block Device";
74 type = "Regular File";
77 type = "Symbolic Link";
92 print_human_fstype (struct statfs const *statfsbuf)
96 switch (statfsbuf->f_type)
98 #if defined (__linux__)
105 case S_MAGIC_EXT2_OLD:
117 case S_MAGIC_ISOFS_WIN:
120 case S_MAGIC_ISOFS_R_WIN:
125 case S_MAGIC_MINIX_30:
126 type = "minix (30 char.)";
128 case S_MAGIC_MINIX_V2:
131 case S_MAGIC_MINIX_V2_30:
132 type = "minix v2 (30 char.)";
176 case S_MAGIC_REISERFS:
274 fputs (type, stdout);
276 printf ("UNKNOWN (0x%x)\n", statfsbuf->f_type);
280 print_human_access (struct stat const *statbuf)
283 mode_string (statbuf->st_mode, modebuf);
285 fputs (modebuf, stdout);
289 print_human_time (time_t const *t)
293 if (strftime (str, 40, "%c", localtime (t)) > 0) fputs (str, stdout);
294 else printf ("Cannot calculate human readable time, sorry");
297 /* print statfs info */
299 print_statfs (char *pformat, char m, char const *filename,
300 void const *data, SECURITY_ID_T sid)
302 struct statfs const *statfsbuf = data;
306 unsigned int sbuflen = sizeof(sbuf);
311 strcat(pformat, "s");
312 printf(pformat, filename);
316 #if !defined(__linux__) && defined (__GNU__)
317 strcat(pformat, "Lx");
318 printf(pformat, statfsbuf->f_fsid);
320 strcat(pformat, "x %-8x");
321 printf(pformat, statfsbuf->f_fsid.__val[0],
322 statfsbuf->f_fsid.__val[1]);
327 strcat(pformat, "llu");
328 printf(pformat, (uintmax_t) (statfsbuf->f_namelen));
331 strcat(pformat, "lx");
332 printf(pformat, (long int) (statfsbuf->f_type));
335 /* print_human_fstype(statfsbuf, pformat);*/
336 print_human_fstype(statfsbuf);
339 strcat(pformat, "lld");
340 printf(pformat, (intmax_t) (statfsbuf->f_blocks));
343 strcat(pformat, "lld");
344 printf(pformat, (intmax_t) (statfsbuf->f_bfree));
347 strcat(pformat, "lld");
348 printf(pformat, (intmax_t) (statfsbuf->f_bavail));
351 strcat(pformat, "ld");
352 printf(pformat, (long int) (statfsbuf->f_bsize));
355 strcat(pformat, "lld");
356 printf(pformat, (intmax_t) (statfsbuf->f_files));
359 strcat(pformat, "lld");
360 printf(pformat, (intmax_t) (statfsbuf->f_ffree));
364 strcat(pformat, "d");
365 printf(pformat, sid);
368 rv = security_sid_to_context(sid, (security_context_t *) &sbuf,
371 sprintf(sbuf, "<error finding security context %d>", sid);
376 strcat(pformat, "c");
382 /* print stat info */
384 print_stat (char *pformat, char m, char const *filename,
385 void const *data, SECURITY_ID_T sid)
389 struct stat *statbuf = (struct stat*)data;
390 struct passwd *pw_ent;
391 struct group *gw_ent;
395 unsigned int sbuflen = sizeof(sbuf);
400 strcat(pformat, "s");
401 printf(pformat, filename);
404 strcat(pformat, "s");
405 if ((statbuf->st_mode & S_IFMT) == S_IFLNK) {
406 if ((i = readlink(filename, linkname, 256)) == -1) {
410 linkname[(i >= 256) ? 255 : i] = '\0';
411 /*printf("\"%s\" -> \"%s\"", filename, linkname);*/
413 printf(pformat, filename);
415 printf(pformat, linkname);
419 printf(pformat, filename);
424 strcat(pformat, "d");
425 printf(pformat, (int)statbuf->st_dev);
428 strcat(pformat, "x");
429 printf(pformat, (int)statbuf->st_dev);
432 strcat(pformat, "d");
433 printf(pformat, (int)statbuf->st_ino);
436 strcat(pformat, "o");
437 printf(pformat, statbuf->st_mode & 07777);
440 print_human_access(statbuf);
443 strcat(pformat, "x");
444 printf(pformat, statbuf->st_mode);
447 print_human_type(statbuf->st_mode);
450 strcat(pformat, "d");
451 printf(pformat, (int)statbuf->st_nlink);
455 strcat(pformat, "d");
456 printf(pformat, sid);
459 rv = security_sid_to_context(sid, (security_context_t *) &sbuf,
462 sprintf(sbuf, "<error finding security context %d>", sid);
467 strcat(pformat, "d");
468 printf(pformat, statbuf->st_uid);
471 strcat(pformat, "s");
473 pw_ent = getpwuid(statbuf->st_uid);
475 (pw_ent != 0L) ? pw_ent->pw_name : "UNKNOWN");
478 strcat(pformat, "d");
479 printf(pformat, statbuf->st_gid);
482 strcat(pformat, "s");
484 gw_ent = getgrgid(statbuf->st_gid);
486 (gw_ent != 0L) ? gw_ent->gr_name : "UNKNOWN");
489 strcat(pformat, "x");
490 printf(pformat, major(statbuf->st_rdev));
493 strcat(pformat, "x");
494 printf(pformat, minor(statbuf->st_rdev));
497 #ifdef __USE_FILE_OFFSET64
498 strcat(pformat, "llu");
499 printf(pformat, (unsigned long long)statbuf->st_size);
501 strcat(pformat, "u");
502 printf(pformat, (unsigned int)statbuf->st_size);
506 strcat(pformat, "u");
507 printf(pformat, (unsigned int)statbuf->st_blocks);
510 strcat(pformat, "d");
511 printf(pformat, (int)statbuf->st_blksize);
514 print_human_time(&(statbuf->st_atime));
517 strcat(pformat, "d");
518 printf(pformat, (int)statbuf->st_atime);
521 print_human_time(&(statbuf->st_mtime));
524 strcat(pformat, "d");
525 printf(pformat, (int)statbuf->st_mtime);
528 print_human_time(&(statbuf->st_ctime));
531 strcat(pformat, "d");
532 printf(pformat, (int)statbuf->st_ctime);
535 strcat(pformat, "c");
542 print_it (char const *masterformat, char const *filename,
543 void (*print_func) (char *, char, char const *,
544 void const *, SECURITY_ID_T),
545 void const *data, SECURITY_ID_T sid)
547 char *m, *b, *format;
550 /* create a working copy of the format string */
551 format = strdup(masterformat);
560 if ((m = strchr(b, (int)'%')) != NULL)
562 strcpy (pformat, "%");
566 /* copy all format specifiers to our format string */
567 while (isdigit(*m) || strchr("#0-+. I", *m))
572 /* make sure the format specifier is not too long */
573 if (strlen (pformat) > 63)
574 fprintf(stderr, "Warning: Format specifier too long, truncating: %s\n", pformat);
576 strcat (pformat, copy);
586 print_func(pformat, *m, filename, data, sid);
601 /* stat the filesystem and print what we find */
603 do_statfs (char const *filename, int terse, int secure, char const *format)
605 struct statfs statfsbuf;
606 SECURITY_ID_T sid = -1;
611 i = statfs_secure(filename, &statfsbuf, &sid);
614 i = statfs(filename, &statfsbuf);
626 format = "%n %i %l %t %b %f %a %s %c %d %S %C";
628 format = "%n %i %l %t %b %f %a %s %c %d";
633 format = " File: \"%n\"\n"
634 " ID: %-8i Namelen: %-7l Type: %T\n"
635 "Blocks: Total: %-10b Free: %-10f Available: %-10a Size: %s\n"
636 "Inodes: Total: %-10c Free: %-10d\n"
637 " SID: %-14S S_Context: %C\n";
639 format = " File: \"%n\"\n"
640 " ID: %-8i Namelen: %-7l Type: %T\n"
641 "Blocks: Total: %-10b Free: %-10f Available: %-10a Size: %s\n"
642 "Inodes: Total: %-10c Free: %-10d";
646 print_it (format, filename, print_statfs, &statfsbuf, sid);
649 /* stat the file and print what we find */
651 do_stat (char const *filename, int follow_links, int terse, int secure, char const *format)
655 SECURITY_ID_T sid = -1;
658 i = ((follow_links == 1)
659 ? stat_secure(filename, &statbuf, &sid)
660 : lstat_secure(filename, &statbuf, &sid));
662 i = ((follow_links == 1)
663 ? stat(filename, &statbuf)
664 : lstat(filename, &statbuf));
677 format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o %S %C";
679 format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o";
683 /* tmp hack to match orignal output until conditional implemented */
684 i = statbuf.st_mode & S_IFMT;
685 if (i == S_IFCHR || i == S_IFBLK) {
689 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
690 "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
691 " Device type: %t,%T\n"
692 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
693 " SID: %-14S S_Context: %C\n"
700 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
701 "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
702 " Device type: %t,%T\n"
703 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
713 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
714 "Device: %Dh/%dd\tInode: %-10i Links: %-5h\n"
715 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
716 " SID: %-14S S_Context: %C\n"
723 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
724 "Device: %Dh/%dd\tInode: %-10i Links: %-5h\n"
725 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
732 print_it(format, filename, print_stat, &statbuf, sid);
739 fprintf (stderr, _("Try %s --help' for more information.\n"),
743 printf (_("Usage: %s [OPTION] FILE...\n"), program_name);
745 Display file or filesystem status.\n\
747 -f, --filesystem display filesystem status instead of file status\n\
748 -c --format=FORMAT FIXME\n\
749 -l, --link follow links\n\
750 -s, --secure FIXME\n\
751 -t, --terse print the information in terse form\n\
753 fputs (HELP_OPTION_DESCRIPTION, stdout);
754 fputs (VERSION_OPTION_DESCRIPTION, stdout);
757 The valid format sequences for files (without --filesystem):\n\
759 %A - Access rights in human readable form\n\
760 %a - Access rights in octal\n\
761 %b - Number of blocks allocated\n\
762 %C - Security context in SE-Linux\n\
765 %D - Device number in hex\n\
766 %d - Device number in decimal\n\
768 %f - raw mode in hex\n\
769 %G - Group name of owner\n\
770 %g - Group ID of owner\n\
773 %h - Number of hard links\n\
775 %N - Quoted File name with dereference if symbolic link\n\
777 %o - IO block size\n\
778 %S - Security ID in SE-Linux\n\
779 %s - Total size, in bytes\n\
780 %T - Minor device type in hex\n\
781 %t - Major device type in hex\n\
784 %U - User name of owner\n\
785 %u - User ID of owner\n\
786 %X - Time of last access as seconds since Epoch\n\
787 %x - Time of last access\n\
788 %Y - Time of last modification as seconds since Epoch\n\
789 %y - Time of last modification\n\
790 %Z - Time of last change as seconds since Epoch\n\
791 %z - Time of last change\n\
796 Valid format sequences for file systems:\n\
798 %a - Free blocks available to non-superuser\n\
799 %b - Total data blocks in file system\n\
800 %C - Security context in SE-Linux\n\
801 %c - Total file nodes in file system\n\
802 %d - Free file nodes in file system\n\
803 %f - Free blocks in file system\n\
806 %i - File System id in hex\n\
807 %l - Maximum length of filenames\n\
809 %S - Security ID in SE-Linux\n\
810 %s - Optimal transfer block size\n\
811 %T - Type in human readable form\n\
814 puts (_("\nReport bugs to <bug-fileutils@gnu.org>."));
820 main (int argc, char *argv[])
824 int follow_links = 0;
830 program_name = argv[0];
831 setlocale (LC_ALL, "");
832 bindtextdomain (PACKAGE, LOCALEDIR);
833 textdomain (PACKAGE);
835 atexit (close_stdout);
837 while ((c = getopt_long (argc, argv, "c:flst", long_options, NULL)) != -1)
857 case_GETOPT_HELP_CHAR;
859 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
862 usage (EXIT_FAILURE);
868 error (0, 0, _("too few arguments"));
869 usage (EXIT_FAILURE);
872 if (!is_flask_enabled ())
875 for (i = optind; i < argc; i++)
878 do_stat (argv[i], follow_links, terse, secure, format);
880 do_statfs (argv[i], terse, secure, format);