3 #include <sys/sysmacros.h>
15 #include <selinux/fs_secure.h>
16 #include <linux/flask/security.h>
17 #include <selinux/flask_util.h> /* for is_flask_enabled() */
18 #define SECURITY_ID_T security_id_t
20 #define SECURITY_ID_T int
25 void print_human_type(unsigned short mode)
27 switch (mode & S_IFMT)
33 printf ("Character Device");
36 printf ("Block Device");
39 printf ("Regular File");
42 printf ("Symbolic Link");
55 void print_human_fstype(struct statfs *statfsbuf)
59 switch (statfsbuf->f_type)
60 #if defined (__linux__)
63 type = strdup("affs");
68 case S_MAGIC_EXT2_OLD:
69 type = strdup("ext2");
72 type = strdup("ext2/ext3");
75 type = strdup("hpfs");
78 type = strdup("isofs");
80 case S_MAGIC_ISOFS_WIN:
81 type = strdup("isofs");
83 case S_MAGIC_ISOFS_R_WIN:
84 type = strdup("isofs");
87 type = strdup("minix");
89 case S_MAGIC_MINIX_30:
90 type = strdup("minix (30 char.)");
92 case S_MAGIC_MINIX_V2:
93 type = strdup("minix v2");
95 case S_MAGIC_MINIX_V2_30:
96 type = strdup("minix v2 (30 char.)");
99 type = strdup("msdos");
102 type = strdup("fat");
105 type = strdup("novell");
108 type = strdup("nfs");
111 type = strdup("proc");
114 type = strdup("smb");
117 type = strdup("xenix");
120 type = strdup("sysv4");
123 type = strdup("sysv2");
126 type = strdup("coh");
129 type = strdup("ufs");
132 type = strdup("xia");
135 type = strdup("ntfs");
138 type = strdup("tmpfs");
140 case S_MAGIC_REISERFS:
141 type = strdup("reiserfs");
144 type = strdup("cramfs");
147 type = strdup("romfs");
150 type = strdup("lustre");
154 type = strdup("ufs");
157 type = strdup("nfs");
160 type = strdup("gfs");
163 type = strdup("lfs");
166 type = strdup("sysv");
169 type = strdup("ftp");
172 type = strdup("tar");
178 type = strdup("cpio");
181 type = strdup("msloss");
184 type = strdup("cpm");
187 type = strdup("hfs");
190 type = strdup("dtfs");
193 type = strdup("grfs");
196 type = strdup("term");
199 type = strdup("dev");
202 type = strdup("proc");
205 type = strdup("ifsock");
208 type = strdup("afs");
211 type = strdup("dfs");
214 type = strdup("proc9");
217 type = strdup("socket");
220 type = strdup("misc");
223 type = strdup("ext2/ext3");
226 type = strdup("http");
229 type = strdup("memfs");
232 type = strdup("iso9660");
236 if ((type = (char*)malloc(30 * sizeof(char))) == NULL) {
237 perror("malloc error");
240 sprintf (type, "UNKNOWN (0x%x)\n", (int)statfsbuf->f_type);
247 void print_human_access(struct stat *statbuf)
252 access[9] = (statbuf->st_mode & S_IXOTH) ?
253 ((statbuf->st_mode & S_ISVTX) ? 't' : 'x') :
254 ((statbuf->st_mode & S_ISVTX) ? 'T' : '-');
255 access[8] = (statbuf->st_mode & S_IWOTH) ? 'w' : '-';
256 access[7] = (statbuf->st_mode & S_IROTH) ? 'r' : '-';
257 access[6] = (statbuf->st_mode & S_IXGRP) ?
258 ((statbuf->st_mode & S_ISGID) ? 's' : 'x') :
259 ((statbuf->st_mode & S_ISGID) ? 'S' : '-');
260 access[5] = (statbuf->st_mode & S_IWGRP) ? 'w' : '-';
261 access[4] = (statbuf->st_mode & S_IRGRP) ? 'r' : '-';
262 access[3] = (statbuf->st_mode & S_IXUSR) ?
263 ((statbuf->st_mode & S_ISUID) ? 's' : 'x') :
264 ((statbuf->st_mode & S_ISUID) ? 'S' : '-');
265 access[2] = (statbuf->st_mode & S_IWUSR) ? 'w' : '-';
266 access[1] = (statbuf->st_mode & S_IRUSR) ? 'r' : '-';
268 switch (statbuf->st_mode & S_IFMT)
297 /* trick gcc into being unable to recognize the %c format so it doesn't
298 * issue its inane warning about %c and two-digit year representations. */
299 static size_t strftime_wrapper(char *s, size_t max, const char *fmt,
301 return strftime(s, max, fmt, tm);
304 void print_human_time(time_t *t)
308 if (strftime_wrapper(str, 40, "%c", localtime(t)) > 0)
311 printf("Cannot calculate human readable time, sorry");
314 /* print statfs info */
315 void print_statfs(char *pformat, char m, char *filename, void *data, SECURITY_ID_T sid)
317 struct statfs *statfsbuf = (struct statfs*)data;
321 unsigned int sbuflen = sizeof(sbuf);
326 strcat(pformat, "s");
327 printf(pformat, filename);
329 #if !defined(__linux__) && defined (__GNU__)
331 strcat(pformat, "Lx");
332 printf(pformat, statfsbuf->f_fsid);
336 strcat(pformat, "x %-8x");
337 printf(pformat, statfsbuf->f_fsid.__val[0], statfsbuf->f_fsid.__val[1]);
342 #ifdef __USE_FILE_OFFSET64
343 strcat(pformat, "lu");
345 strcat(pformat, "d");
347 printf(pformat, statfsbuf->f_namelen);
350 #ifdef __USE_FILE_OFFSET64
351 strcat(pformat, "lx");
353 strcat(pformat, "x");
355 printf(pformat, statfsbuf->f_type);
358 /* print_human_fstype(statfsbuf, pformat);*/
359 print_human_fstype(statfsbuf);
362 #ifdef __USE_FILE_OFFSET64
363 strcat(pformat, "lld");
365 #if !defined(__linux__) && defined (__GNU__)
366 strcat(pformat, "d");
368 strcat(pformat, "ld");
371 printf(pformat, statfsbuf->f_blocks);
374 #ifdef __USE_FILE_OFFSET64
375 strcat(pformat, "lld");
377 #if !defined(__linux__) && defined (__GNU__)
378 strcat(pformat, "d");
380 strcat(pformat, "ld");
383 printf(pformat, statfsbuf->f_bfree);
386 #ifdef __USE_FILE_OFFSET64
387 strcat(pformat, "lld");
389 #if !defined(__linux__) && defined (__GNU__)
390 strcat(pformat, "d");
392 strcat(pformat, "ld");
395 printf(pformat, statfsbuf->f_bavail);
398 #ifdef __USE_FILE_OFFSET64
399 strcat(pformat, "ld");
401 strcat(pformat, "d");
403 printf(pformat, statfsbuf->f_bsize);
406 #ifdef __USE_FILE_OFFSET64
407 strcat(pformat, "lld");
409 #if !defined(__linux__) && defined (__GNU__)
410 strcat(pformat, "d");
412 strcat(pformat, "ld");
415 printf(pformat, statfsbuf->f_files);
418 #ifdef __USE_FILE_OFFSET64
419 strcat(pformat, "lld");
421 #if !defined(__linux__) && defined (__GNU__)
422 strcat(pformat, "d");
424 strcat(pformat, "ld");
427 printf(pformat, statfsbuf->f_ffree);
431 strcat(pformat, "d");
432 printf(pformat, sid);
435 rv = security_sid_to_context(sid, (security_context_t *) &sbuf, &sbuflen);
437 sprintf(sbuf, "<error finding security context %d>", sid);
442 strcat(pformat, "c");
448 /* print stat info */
449 void print_stat(char *pformat, char m, char *filename, void *data, SECURITY_ID_T sid)
453 struct stat *statbuf = (struct stat*)data;
454 struct passwd *pw_ent;
455 struct group *gw_ent;
459 unsigned int sbuflen = sizeof(sbuf);
464 strcat(pformat, "s");
465 printf(pformat, filename);
468 strcat(pformat, "s");
469 if ((statbuf->st_mode & S_IFMT) == S_IFLNK) {
470 if ((i = readlink(filename, linkname, 256)) == -1) {
474 linkname[(i >= 256) ? 255 : i] = '\0';
475 /*printf("\"%s\" -> \"%s\"", filename, linkname);*/
477 printf(pformat, filename);
479 printf(pformat, linkname);
483 printf(pformat, filename);
488 strcat(pformat, "d");
489 printf(pformat, (int)statbuf->st_dev);
492 strcat(pformat, "x");
493 printf(pformat, (int)statbuf->st_dev);
496 strcat(pformat, "d");
497 printf(pformat, (int)statbuf->st_ino);
500 strcat(pformat, "o");
501 printf(pformat, statbuf->st_mode & 07777);
504 print_human_access(statbuf);
507 strcat(pformat, "x");
508 printf(pformat, statbuf->st_mode);
511 print_human_type(statbuf->st_mode);
514 strcat(pformat, "d");
515 printf(pformat, (int)statbuf->st_nlink);
519 strcat(pformat, "d");
520 printf(pformat, sid);
523 rv = security_sid_to_context(sid, (security_context_t *) &sbuf, &sbuflen);
525 sprintf(sbuf, "<error finding security context %d>", sid);
530 strcat(pformat, "d");
531 printf(pformat, statbuf->st_uid);
534 strcat(pformat, "s");
536 pw_ent = getpwuid(statbuf->st_uid);
538 (pw_ent != 0L) ? pw_ent->pw_name : "UNKNOWN");
541 strcat(pformat, "d");
542 printf(pformat, statbuf->st_gid);
545 strcat(pformat, "s");
547 gw_ent = getgrgid(statbuf->st_gid);
549 (gw_ent != 0L) ? gw_ent->gr_name : "UNKNOWN");
552 strcat(pformat, "x");
553 printf(pformat, major(statbuf->st_rdev));
556 strcat(pformat, "x");
557 printf(pformat, minor(statbuf->st_rdev));
560 #ifdef __USE_FILE_OFFSET64
561 strcat(pformat, "llu");
562 printf(pformat, (unsigned long long)statbuf->st_size);
564 strcat(pformat, "u");
565 printf(pformat, (unsigned int)statbuf->st_size);
569 strcat(pformat, "u");
570 printf(pformat, (unsigned int)statbuf->st_blocks);
573 strcat(pformat, "d");
574 printf(pformat, (int)statbuf->st_blksize);
577 print_human_time(&(statbuf->st_atime));
580 strcat(pformat, "d");
581 printf(pformat, (int)statbuf->st_atime);
584 print_human_time(&(statbuf->st_mtime));
587 strcat(pformat, "d");
588 printf(pformat, (int)statbuf->st_mtime);
591 print_human_time(&(statbuf->st_ctime));
594 strcat(pformat, "d");
595 printf(pformat, (int)statbuf->st_ctime);
598 strcat(pformat, "c");
604 void print_it(char *masterformat, char *filename,
605 void (*print_func)(char*, char, char*, void*, SECURITY_ID_T), void *data, SECURITY_ID_T sid)
607 char *m, *b, *format;
610 /* create a working copy of the format string */
611 format = strdup(masterformat);
620 if ((m = strchr(b, (int)'%')) != NULL)
622 strcpy (pformat, "%");
626 /* copy all format specifiers to our format string */
627 while (isdigit(*m) || strchr("#0-+. I", *m))
632 /* make sure the format specifier is not too long */
633 if (strlen (pformat) > 63)
634 fprintf(stderr, "Warning: Format specifier too long, truncating: %s\n", pformat);
636 strcat (pformat, copy);
646 print_func(pformat, *m, filename, data, sid);
661 /* stat the filesystem and print what we find */
663 do_statfs (char *filename, int terse, int secure, char *format)
665 struct statfs statfsbuf;
666 SECURITY_ID_T sid = -1;
670 if(!is_flask_enabled())
673 i = statfs_secure(filename, &statfsbuf, &sid);
676 i = statfs(filename, &statfsbuf);
689 format = "%n %i %l %t %b %f %a %s %c %d %S %C";
692 format = "%n %i %l %t %b %f %a %s %c %d";
698 format = " File: \"%n\"\n"
699 " ID: %-8i Namelen: %-7l Type: %T\n"
700 "Blocks: Total: %-10b Free: %-10f Available: %-10a Size: %s\n"
701 "Inodes: Total: %-10c Free: %-10d\n"
702 " SID: %-14S S_Context: %C\n";
705 format = " File: \"%n\"\n"
706 " ID: %-8i Namelen: %-7l Type: %T\n"
707 "Blocks: Total: %-10b Free: %-10f Available: %-10a Size: %s\n"
708 "Inodes: Total: %-10c Free: %-10d";
712 print_it(format, filename, print_statfs, &statfsbuf, sid);
715 /* stat the file and print what we find */
717 do_stat (char *filename, int link, int terse, int secure, char *format)
721 SECURITY_ID_T sid = -1;
724 if(!is_flask_enabled())
727 i = (link == 1) ? stat_secure(filename, &statbuf, &sid) : lstat_secure(filename, &statbuf, &sid);
730 i = (link == 1) ? stat(filename, &statbuf) : lstat(filename, &statbuf);
744 format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o %S %C";
747 format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o";
751 /* tmp hack to match orignal output until conditional implemented */
752 i = statbuf.st_mode & S_IFMT;
753 if (i == S_IFCHR || i == S_IFBLK) {
758 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
759 "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
760 " Device type: %t,%T\n"
761 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
762 " SID: %-14S S_Context: %C\n"
770 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
771 "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
772 " Device type: %t,%T\n"
773 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
784 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
785 "Device: %Dh/%dd\tInode: %-10i Links: %-5h\n"
786 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
787 " SID: %-14S S_Context: %C\n"
795 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
796 "Device: %Dh/%dd\tInode: %-10i Links: %-5h\n"
797 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
804 print_it(format, filename, print_stat, &statbuf, sid);
808 usage (char *progname)
810 fprintf (stderr, "Usage: %s [-l] [-f] [-s] [-v] [-h] [-t] [-c format] file1 [file2 ...]\n", progname);
814 void verbose_usage(char *progname)
816 fprintf(stderr, "Usage: %s [-l] [-f] [-s] [-v] [-h] [-t] [-c format] file1 [file2 ...]\n", progname);
817 fprintf(stderr, "\tformat interpreted sequences for file stat are:\n");
818 fprintf(stderr, "\t\t%%n - File name\n");
819 fprintf(stderr, "\t\t%%N - Quoted File name with dereference if symbolic link\n");
820 fprintf(stderr, "\t\t%%d - Device number in decimal\n");
821 fprintf(stderr, "\t\t%%D - Device number in hex\n");
822 fprintf(stderr, "\t\t%%i - Inode number\n");
823 fprintf(stderr, "\t\t%%a - Access rights in octal\n");
824 fprintf(stderr, "\t\t%%A - Access rights in human readable form\n");
825 fprintf(stderr, "\t\t%%f - raw mode in hex\n");
826 fprintf(stderr, "\t\t%%F - File type\n");
827 fprintf(stderr, "\t\t%%h - Number of hard links\n");
828 fprintf(stderr, "\t\t%%u - User Id of owner\n");
829 fprintf(stderr, "\t\t%%U - User name of owner\n");
830 fprintf(stderr, "\t\t%%g - Group Id of owner\n");
831 fprintf(stderr, "\t\t%%G - Group name of owner\n");
832 fprintf(stderr, "\t\t%%t - Major device type in hex\n");
833 fprintf(stderr, "\t\t%%T - Minor device type in hex\n");
834 fprintf(stderr, "\t\t%%s - Total size, in bytes\n");
835 fprintf(stderr, "\t\t%%b - Number of blocks allocated\n");
836 fprintf(stderr, "\t\t%%o - IO block size\n");
837 fprintf(stderr, "\t\t%%x - Time of last access\n");
838 fprintf(stderr, "\t\t%%X - Time of last access as seconds since Epoch\n");
839 fprintf(stderr, "\t\t%%y - Time of last modification\n");
840 fprintf(stderr, "\t\t%%Y - Time of last modification as seconds since Epoch\n");
841 fprintf(stderr, "\t\t%%z - Time of last change\n");
842 fprintf(stderr, "\t\t%%Z - Time of last change as seconds since Epoch\n");
843 fprintf(stderr, "\t\t%%S - Security ID in SE-Linux\n");
844 fprintf(stderr, "\t\t%%C - Security context in SE-Linux\n");
845 fprintf(stderr, "\tformat interpreted sequences for filesystem stat are:\n");
846 fprintf(stderr, "\t\t%%n - File name\n");
847 fprintf(stderr, "\t\t%%i - File System id in hex\n");
848 fprintf(stderr, "\t\t%%l - Maximum length of filenames\n");
849 fprintf(stderr, "\t\t%%t - Type in hex\n");
850 fprintf(stderr, "\t\t%%T - Type in human readable form\n");
851 fprintf(stderr, "\t\t%%b - Total data blocks in file system\n");
852 fprintf(stderr, "\t\t%%f - Free blocks in file system\n");
853 fprintf(stderr, "\t\t%%a - Free blocks available to non-superuser\n");
854 fprintf(stderr, "\t\t%%s - Optimal transfer block size\n");
855 fprintf(stderr, "\t\t%%c - Total file nodes in file system\n");
856 fprintf(stderr, "\t\t%%S - Security ID in SE-Linux\n");
857 fprintf(stderr, "\t\t%%C - Security context in SE-Linux\n");
858 fprintf(stderr, "\t\t%%d - Free file nodes in file system\n");
864 main (int argc, char *argv[])
866 int c, i, link = 0, fs = 0, terse = 0, secure = 0;
869 while ((c = getopt (argc, argv, "lsfvthc:")) != EOF)
889 printf ("stat version: 3.0\n");
890 verbose_usage(argv[0]);
893 printf ("stat version: 3.0\n");
901 for (i = optind; i < argc; i++)
902 (fs == 0) ? do_stat (argv[i], link, terse, secure, format) :
903 do_statfs (argv[i], terse, secure, format);