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");
88 case S_MAGIC_MINIX_30:
89 type = strdup("minix (30 char.)");
91 case S_MAGIC_MINIX_V2:
92 type = strdup("minix v2");
94 case S_MAGIC_MINIX_V2_30:
95 type = strdup("minix v2 (30 char.)");
98 type = strdup("msdos");
101 type = strdup("fat");
104 type = strdup("novell");
107 type = strdup("nfs");
110 type = strdup("proc");
113 type = strdup("smb");
116 type = strdup("xenix");
119 type = strdup("sysv4");
122 type = strdup("sysv2");
125 type = strdup("coh");
128 type = strdup("ufs");
131 type = strdup("xia");
134 type = strdup("ntfs");
137 type = strdup("tmpfs");
139 case S_MAGIC_REISERFS:
140 type = strdup("reiserfs");
143 type = strdup("cramfs");
146 type = strdup("romfs");
150 type = strdup("ufs");
153 type = strdup("nfs");
156 type = strdup("gfs");
159 type = strdup("lfs");
162 type = strdup("sysv");
165 type = strdup("ftp");
168 type = strdup("tar");
174 type = strdup("cpio");
177 type = strdup("msloss");
180 type = strdup("cpm");
183 type = strdup("hfs");
186 type = strdup("dtfs");
189 type = strdup("grfs");
192 type = strdup("term");
195 type = strdup("dev");
198 type = strdup("proc");
201 type = strdup("ifsock");
204 type = strdup("afs");
207 type = strdup("dfs");
210 type = strdup("proc9");
213 type = strdup("socket");
216 type = strdup("misc");
219 type = strdup("ext2/ext3");
222 type = strdup("http");
225 type = strdup("memfs");
228 type = strdup("iso9660");
232 if ((type = (char*)malloc(30 * sizeof(char))) == NULL) {
233 perror("malloc error");
236 sprintf (type, "UNKNOWN (0x%x)\n", (int)statfsbuf->f_type);
243 void print_human_access(struct stat *statbuf)
248 access[9] = (statbuf->st_mode & S_IXOTH) ?
249 ((statbuf->st_mode & S_ISVTX) ? 't' : 'x') :
250 ((statbuf->st_mode & S_ISVTX) ? 'T' : '-');
251 access[8] = (statbuf->st_mode & S_IWOTH) ? 'w' : '-';
252 access[7] = (statbuf->st_mode & S_IROTH) ? 'r' : '-';
253 access[6] = (statbuf->st_mode & S_IXGRP) ?
254 ((statbuf->st_mode & S_ISGID) ? 's' : 'x') :
255 ((statbuf->st_mode & S_ISGID) ? 'S' : '-');
256 access[5] = (statbuf->st_mode & S_IWGRP) ? 'w' : '-';
257 access[4] = (statbuf->st_mode & S_IRGRP) ? 'r' : '-';
258 access[3] = (statbuf->st_mode & S_IXUSR) ?
259 ((statbuf->st_mode & S_ISUID) ? 's' : 'x') :
260 ((statbuf->st_mode & S_ISUID) ? 'S' : '-');
261 access[2] = (statbuf->st_mode & S_IWUSR) ? 'w' : '-';
262 access[1] = (statbuf->st_mode & S_IRUSR) ? 'r' : '-';
264 switch (statbuf->st_mode & S_IFMT)
293 void print_human_time(time_t *t)
297 if (strftime(str, 40, "%c", localtime(t)) > 0) printf(str);
298 else printf("Cannot calculate human readable time, sorry");
301 /* print statfs info */
302 void print_statfs(char *pformat, char m, char *filename, void *data, SECURITY_ID_T sid)
304 struct statfs *statfsbuf = (struct statfs*)data;
308 unsigned int sbuflen = sizeof(sbuf);
313 strcat(pformat, "s");
314 printf(pformat, filename);
316 #if !defined(__linux__) && defined (__GNU__)
318 strcat(pformat, "Lx");
319 printf(pformat, statfsbuf->f_fsid);
323 strcat(pformat, "x %-8x");
324 printf(pformat, statfsbuf->f_fsid.__val[0], statfsbuf->f_fsid.__val[1]);
329 #ifdef __USE_FILE_OFFSET64
330 strcat(pformat, "lu");
332 strcat(pformat, "d");
334 printf(pformat, statfsbuf->f_namelen);
337 #ifdef __USE_FILE_OFFSET64
338 strcat(pformat, "lx");
340 strcat(pformat, "x");
342 printf(pformat, statfsbuf->f_type);
345 /* print_human_fstype(statfsbuf, pformat);*/
346 print_human_fstype(statfsbuf);
349 #ifdef __USE_FILE_OFFSET64
350 strcat(pformat, "lld");
352 #if !defined(__linux__) && defined (__GNU__)
353 strcat(pformat, "d");
355 strcat(pformat, "ld");
358 printf(pformat, statfsbuf->f_blocks);
361 #ifdef __USE_FILE_OFFSET64
362 strcat(pformat, "lld");
364 #if !defined(__linux__) && defined (__GNU__)
365 strcat(pformat, "d");
367 strcat(pformat, "ld");
370 printf(pformat, statfsbuf->f_bfree);
373 #ifdef __USE_FILE_OFFSET64
374 strcat(pformat, "lld");
376 #if !defined(__linux__) && defined (__GNU__)
377 strcat(pformat, "d");
379 strcat(pformat, "ld");
382 printf(pformat, statfsbuf->f_bavail);
385 #ifdef __USE_FILE_OFFSET64
386 strcat(pformat, "ld");
388 strcat(pformat, "d");
390 printf(pformat, statfsbuf->f_bsize);
393 #ifdef __USE_FILE_OFFSET64
394 strcat(pformat, "lld");
396 #if !defined(__linux__) && defined (__GNU__)
397 strcat(pformat, "d");
399 strcat(pformat, "ld");
402 printf(pformat, statfsbuf->f_files);
405 #ifdef __USE_FILE_OFFSET64
406 strcat(pformat, "lld");
408 #if !defined(__linux__) && defined (__GNU__)
409 strcat(pformat, "d");
411 strcat(pformat, "ld");
414 printf(pformat, statfsbuf->f_ffree);
418 strcat(pformat, "d");
419 printf(pformat, sid);
422 rv = security_sid_to_context(sid, (security_context_t *) &sbuf, &sbuflen);
424 sprintf(sbuf, "<error finding security context %d>", sid);
429 strcat(pformat, "c");
435 /* print stat info */
436 void print_stat(char *pformat, char m, char *filename, void *data, SECURITY_ID_T sid)
440 struct stat *statbuf = (struct stat*)data;
441 struct passwd *pw_ent;
442 struct group *gw_ent;
446 unsigned int sbuflen = sizeof(sbuf);
451 strcat(pformat, "s");
452 printf(pformat, filename);
455 strcat(pformat, "s");
456 if ((statbuf->st_mode & S_IFMT) == S_IFLNK) {
457 if ((i = readlink(filename, linkname, 256)) == -1) {
461 linkname[(i >= 256) ? 255 : i] = '\0';
462 /*printf("\"%s\" -> \"%s\"", filename, linkname);*/
464 printf(pformat, filename);
466 printf(pformat, linkname);
470 printf(pformat, filename);
475 strcat(pformat, "d");
476 printf(pformat, (int)statbuf->st_dev);
479 strcat(pformat, "x");
480 printf(pformat, (int)statbuf->st_dev);
483 strcat(pformat, "d");
484 printf(pformat, (int)statbuf->st_ino);
487 strcat(pformat, "o");
488 printf(pformat, statbuf->st_mode & 07777);
491 print_human_access(statbuf);
494 strcat(pformat, "x");
495 printf(pformat, statbuf->st_mode);
498 print_human_type(statbuf->st_mode);
501 strcat(pformat, "d");
502 printf(pformat, (int)statbuf->st_nlink);
506 strcat(pformat, "d");
507 printf(pformat, sid);
510 rv = security_sid_to_context(sid, (security_context_t *) &sbuf, &sbuflen);
512 sprintf(sbuf, "<error finding security context %d>", sid);
517 strcat(pformat, "d");
518 printf(pformat, statbuf->st_uid);
521 strcat(pformat, "s");
523 pw_ent = getpwuid(statbuf->st_uid);
525 (pw_ent != 0L) ? pw_ent->pw_name : "UNKNOWN");
528 strcat(pformat, "d");
529 printf(pformat, statbuf->st_gid);
532 strcat(pformat, "s");
534 gw_ent = getgrgid(statbuf->st_gid);
536 (gw_ent != 0L) ? gw_ent->gr_name : "UNKNOWN");
539 strcat(pformat, "x");
540 printf(pformat, major(statbuf->st_rdev));
543 strcat(pformat, "x");
544 printf(pformat, minor(statbuf->st_rdev));
547 #ifdef __USE_FILE_OFFSET64
548 strcat(pformat, "llu");
549 printf(pformat, (unsigned long long)statbuf->st_size);
551 strcat(pformat, "u");
552 printf(pformat, (unsigned int)statbuf->st_size);
556 strcat(pformat, "u");
557 printf(pformat, (unsigned int)statbuf->st_blocks);
560 strcat(pformat, "d");
561 printf(pformat, (int)statbuf->st_blksize);
564 print_human_time(&(statbuf->st_atime));
567 strcat(pformat, "d");
568 printf(pformat, (int)statbuf->st_atime);
571 print_human_time(&(statbuf->st_mtime));
574 strcat(pformat, "d");
575 printf(pformat, (int)statbuf->st_mtime);
578 print_human_time(&(statbuf->st_ctime));
581 strcat(pformat, "d");
582 printf(pformat, (int)statbuf->st_ctime);
585 strcat(pformat, "c");
591 void print_it(char *masterformat, char *filename,
592 void (*print_func)(char*, char, char*, void*, SECURITY_ID_T), void *data, SECURITY_ID_T sid)
594 char *m, *b, *format;
597 /* create a working copy of the format string */
598 format = strdup(masterformat);
607 if ((m = strchr(b, (int)'%')) != NULL)
609 strcpy (pformat, "%");
613 /* copy all format specifiers to our format string */
614 while (isdigit(*m) || strchr("#0-+. I", *m))
619 /* make sure the format specifier is not too long */
620 if (strlen (pformat) > 63)
621 fprintf(stderr, "Warning: Format specifier too long, truncating: %s\n", pformat);
623 strcat (pformat, copy);
633 print_func(pformat, *m, filename, data, sid);
648 /* stat the filesystem and print what we find */
650 do_statfs (char *filename, int terse, int secure, char *format)
652 struct statfs statfsbuf;
653 SECURITY_ID_T sid = -1;
657 if(!is_flask_enabled())
660 i = statfs_secure(filename, &statfsbuf, &sid);
663 i = statfs(filename, &statfsbuf);
676 format = "%n %i %l %t %b %f %a %s %c %d %S %C";
679 format = "%n %i %l %t %b %f %a %s %c %d";
685 format = " File: \"%n\"\n"
686 " ID: %-8i Namelen: %-7l Type: %T\n"
687 "Blocks: Total: %-10b Free: %-10f Available: %-10a Size: %s\n"
688 "Inodes: Total: %-10c Free: %-10d\n"
689 " SID: %-14S S_Context: %C\n";
692 format = " File: \"%n\"\n"
693 " ID: %-8i Namelen: %-7l Type: %T\n"
694 "Blocks: Total: %-10b Free: %-10f Available: %-10a Size: %s\n"
695 "Inodes: Total: %-10c Free: %-10d";
699 print_it(format, filename, print_statfs, &statfsbuf, sid);
702 /* stat the file and print what we find */
704 do_stat (char *filename, int link, int terse, int secure, char *format)
708 SECURITY_ID_T sid = -1;
711 if(!is_flask_enabled())
714 i = (link == 1) ? stat_secure(filename, &statbuf, &sid) : lstat_secure(filename, &statbuf, &sid);
717 i = (link == 1) ? stat(filename, &statbuf) : lstat(filename, &statbuf);
731 format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o %S %C";
734 format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o";
738 /* tmp hack to match orignal output until conditional implemented */
739 i = statbuf.st_mode & S_IFMT;
740 if (i == S_IFCHR || i == S_IFBLK) {
745 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
746 "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
747 " Device type: %t,%T\n"
748 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
749 " SID: %-14S S_Context: %C\n"
757 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
758 "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
759 " Device type: %t,%T\n"
760 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
771 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
772 "Device: %Dh/%dd\tInode: %-10i Links: %-5h\n"
773 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
774 " SID: %-14S S_Context: %C\n"
782 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
783 "Device: %Dh/%dd\tInode: %-10i Links: %-5h\n"
784 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
791 print_it(format, filename, print_stat, &statbuf, sid);
795 usage (char *progname)
797 fprintf (stderr, "Usage: %s [-l] [-f] [-s] [-v] [-h] [-t] [-c format] file1 [file2 ...]\n", progname);
801 void verbose_usage(char *progname)
803 fprintf(stderr, "Usage: %s [-l] [-f] [-s] [-v] [-h] [-t] [-c format] file1 [file2 ...]\n", progname);
804 fprintf(stderr, "\tformat interpreted sequences for file stat are:\n");
805 fprintf(stderr, "\t\t%%n - File name\n");
806 fprintf(stderr, "\t\t%%N - Quoted File name with dereference if symbolic link\n");
807 fprintf(stderr, "\t\t%%d - Device number in decimal\n");
808 fprintf(stderr, "\t\t%%D - Device number in hex\n");
809 fprintf(stderr, "\t\t%%i - Inode number\n");
810 fprintf(stderr, "\t\t%%a - Access rights in octal\n");
811 fprintf(stderr, "\t\t%%A - Access rights in human readable form\n");
812 fprintf(stderr, "\t\t%%f - raw mode in hex\n");
813 fprintf(stderr, "\t\t%%F - File type\n");
814 fprintf(stderr, "\t\t%%h - Number of hard links\n");
815 fprintf(stderr, "\t\t%%u - User Id of owner\n");
816 fprintf(stderr, "\t\t%%U - User name of owner\n");
817 fprintf(stderr, "\t\t%%g - Group Id of owner\n");
818 fprintf(stderr, "\t\t%%G - Group name of owner\n");
819 fprintf(stderr, "\t\t%%t - Major device type in hex\n");
820 fprintf(stderr, "\t\t%%T - Minor device type in hex\n");
821 fprintf(stderr, "\t\t%%s - Total size, in bytes\n");
822 fprintf(stderr, "\t\t%%b - Number of blocks allocated\n");
823 fprintf(stderr, "\t\t%%o - IO block size\n");
824 fprintf(stderr, "\t\t%%x - Time of last access\n");
825 fprintf(stderr, "\t\t%%X - Time of last access as seconds since Epoch\n");
826 fprintf(stderr, "\t\t%%y - Time of last modification\n");
827 fprintf(stderr, "\t\t%%Y - Time of last modification as seconds since Epoch\n");
828 fprintf(stderr, "\t\t%%z - Time of last change\n");
829 fprintf(stderr, "\t\t%%Z - Time of last change as seconds since Epoch\n");
830 fprintf(stderr, "\t\t%%S - Security ID in SE-Linux\n");
831 fprintf(stderr, "\t\t%%C - Security context in SE-Linux\n");
832 fprintf(stderr, "\tformat interpreted sequences for filesystem stat are:\n");
833 fprintf(stderr, "\t\t%%n - File name\n");
834 fprintf(stderr, "\t\t%%i - File System id in hex\n");
835 fprintf(stderr, "\t\t%%l - Maximum length of filenames\n");
836 fprintf(stderr, "\t\t%%t - Type in hex\n");
837 fprintf(stderr, "\t\t%%T - Type in human readable form\n");
838 fprintf(stderr, "\t\t%%b - Total data blocks in file system\n");
839 fprintf(stderr, "\t\t%%f - Free blocks in file system\n");
840 fprintf(stderr, "\t\t%%a - Free blocks available to non-superuser\n");
841 fprintf(stderr, "\t\t%%s - Optimal transfer block size\n");
842 fprintf(stderr, "\t\t%%c - Total file nodes in file system\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, "\t\t%%d - Free file nodes in file system\n");
851 main (int argc, char *argv[])
853 int c, i, link = 0, fs = 0, terse = 0, secure = 0;
856 while ((c = getopt (argc, argv, "lsfvthc:")) != EOF)
876 printf ("stat version: 3.0\n");
877 verbose_usage(argv[0]);
880 printf ("stat version: 3.0\n");
888 for (i = optind; i < argc; i++)
889 (fs == 0) ? do_stat (argv[i], link, terse, secure, format) :
890 do_statfs (argv[i], terse, secure, format);