summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2002-04-13 13:47:14 +0000
committerJim Meyering <jim@meyering.net>2002-04-13 13:47:14 +0000
commit8d8acf4b3c5d61b1102cdd04047370c371a9d29e (patch)
tree5497d034a0384778f08c9df0359c8e45082bdc1c /src
parentfadc4d4786744d01a86868059a024f359ec4981e (diff)
downloadcoreutils-8d8acf4b3c5d61b1102cdd04047370c371a9d29e.tar.xz
Direct from Debian's stat_3.3-1, modulo trailing blanks (removed)
and cpp directive (indented via cppi).
Diffstat (limited to 'src')
-rw-r--r--src/stat.c895
1 files changed, 895 insertions, 0 deletions
diff --git a/src/stat.c b/src/stat.c
new file mode 100644
index 000000000..f3b96b08c
--- /dev/null
+++ b/src/stat.c
@@ -0,0 +1,895 @@
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/vfs.h>
+#include <string.h>
+#include <malloc.h>
+#include <ctype.h>
+
+#ifdef FLASK_LINUX
+# include <selinux/fs_secure.h>
+# include <linux/flask/security.h>
+# include <selinux/flask_util.h> /* for is_flask_enabled() */
+# define SECURITY_ID_T security_id_t
+#else
+# define SECURITY_ID_T int
+#endif
+
+#include "fs.h"
+
+void print_human_type(unsigned short mode)
+{
+ switch (mode & S_IFMT)
+ {
+ case S_IFDIR:
+ printf ("Directory");
+ break;
+ case S_IFCHR:
+ printf ("Character Device");
+ break;
+ case S_IFBLK:
+ printf ("Block Device");
+ break;
+ case S_IFREG:
+ printf ("Regular File");
+ break;
+ case S_IFLNK:
+ printf ("Symbolic Link");
+ break;
+ case S_IFSOCK:
+ printf ("Socket");
+ break;
+ case S_IFIFO:
+ printf ("Fifo File");
+ break;
+ default:
+ printf ("Unknown");
+ }
+}
+
+void print_human_fstype(struct statfs *statfsbuf)
+{
+ char *type;
+
+ switch (statfsbuf->f_type)
+#if defined (__linux__)
+ {
+ case S_MAGIC_AFFS:
+ type = strdup("affs");
+ break;
+ case S_MAGIC_EXT:
+ type = strdup("ext");
+ break;
+ case S_MAGIC_EXT2_OLD:
+ type = strdup("ext2");
+ break;
+ case S_MAGIC_EXT2:
+ type = strdup("ext2/ext3");
+ break;
+ case S_MAGIC_HPFS:
+ type = strdup("hpfs");
+ break;
+ case S_MAGIC_ISOFS:
+ type = strdup("isofs");
+ break;
+ case S_MAGIC_ISOFS_WIN:
+ type = strdup("isofs");
+ break;
+ case S_MAGIC_ISOFS_R_WIN:
+ type = strdup("isofs");
+ break;
+ case S_MAGIC_MINIX:
+ type = strdup("minix");
+ case S_MAGIC_MINIX_30:
+ type = strdup("minix (30 char.)");
+ break;
+ case S_MAGIC_MINIX_V2:
+ type = strdup("minix v2");
+ break;
+ case S_MAGIC_MINIX_V2_30:
+ type = strdup("minix v2 (30 char.)");
+ break;
+ case S_MAGIC_MSDOS:
+ type = strdup("msdos");
+ break;
+ case S_MAGIC_FAT:
+ type = strdup("fat");
+ break;
+ case S_MAGIC_NCP:
+ type = strdup("novell");
+ break;
+ case S_MAGIC_NFS:
+ type = strdup("nfs");
+ break;
+ case S_MAGIC_PROC:
+ type = strdup("proc");
+ break;
+ case S_MAGIC_SMB:
+ type = strdup("smb");
+ break;
+ case S_MAGIC_XENIX:
+ type = strdup("xenix");
+ break;
+ case S_MAGIC_SYSV4:
+ type = strdup("sysv4");
+ break;
+ case S_MAGIC_SYSV2:
+ type = strdup("sysv2");
+ break;
+ case S_MAGIC_COH:
+ type = strdup("coh");
+ break;
+ case S_MAGIC_UFS:
+ type = strdup("ufs");
+ break;
+ case S_MAGIC_XIAFS:
+ type = strdup("xia");
+ break;
+ case S_MAGIC_NTFS:
+ type = strdup("ntfs");
+ break;
+ case S_MAGIC_TMPFS:
+ type = strdup("tmpfs");
+ break;
+ case S_MAGIC_REISERFS:
+ type = strdup("reiserfs");
+ break;
+ case S_MAGIC_CRAMFS:
+ type = strdup("cramfs");
+ break;
+ case S_MAGIC_ROMFS:
+ type = strdup("romfs");
+ break;
+#elif __GNU__
+ case FSTYPE_UFS:
+ type = strdup("ufs");
+ break;
+ case FSTYPE_NFS:
+ type = strdup("nfs");
+ break;
+ case FSTYPE_GFS:
+ type = strdup("gfs");
+ break;
+ case FSTYPE_LFS:
+ type = strdup("lfs");
+ break;
+ case FSTYPE_SYSV:
+ type = strdup("sysv");
+ break;
+ case FSTYPE_FTP:
+ type = strdup("ftp");
+ break;
+ case FSTYPE_TAR:
+ type = strdup("tar");
+ break;
+ case FSTYPE_AR:
+ type = strdup("ar");
+ break;
+ case FSTYPE_CPIO:
+ type = strdup("cpio");
+ break;
+ case FSTYPE_MSLOSS:
+ type = strdup("msloss");
+ break;
+ case FSTYPE_CPM:
+ type = strdup("cpm");
+ break;
+ case FSTYPE_HFS:
+ type = strdup("hfs");
+ break;
+ case FSTYPE_DTFS:
+ type = strdup("dtfs");
+ break;
+ case FSTYPE_GRFS:
+ type = strdup("grfs");
+ break;
+ case FSTYPE_TERM:
+ type = strdup("term");
+ break;
+ case FSTYPE_DEV:
+ type = strdup("dev");
+ break;
+ case FSTYPE_PROC:
+ type = strdup("proc");
+ break;
+ case FSTYPE_IFSOCK:
+ type = strdup("ifsock");
+ break;
+ case FSTYPE_AFS:
+ type = strdup("afs");
+ break;
+ case FSTYPE_DFS:
+ type = strdup("dfs");
+ break;
+ case FSTYPE_PROC9:
+ type = strdup("proc9");
+ break;
+ case FSTYPE_SOCKET:
+ type = strdup("socket");
+ break;
+ case FSTYPE_MISC:
+ type = strdup("misc");
+ break;
+ case FSTYPE_EXT2FS:
+ type = strdup("ext2/ext3");
+ break;
+ case FSTYPE_HTTP:
+ type = strdup("http");
+ break;
+ case FSTYPE_MEMFS:
+ type = strdup("memfs");
+ break;
+ case FSTYPE_ISO9660:
+ type = strdup("iso9660");
+ break;
+#endif
+ default:
+ if ((type = (char*)malloc(30 * sizeof(char))) == NULL) {
+ perror("malloc error");
+ return;
+ }
+#ifdef __USE_FILE_OFFSET64
+ sprintf (type, "UNKNOWN (0x%x)\n", statfsbuf->f_type);
+#else
+ sprintf (type, "UNKNOWN (0x%x)\n", statfsbuf->f_type);
+#endif
+ }
+
+ printf("%s", type);
+ free(type);
+}
+
+void print_human_access(struct stat *statbuf)
+{
+ char access[10];
+
+ access[9] = (statbuf->st_mode & S_IXOTH) ?
+ ((statbuf->st_mode & S_ISVTX) ? 't' : 'x') :
+ ((statbuf->st_mode & S_ISVTX) ? 'T' : '-');
+ access[8] = (statbuf->st_mode & S_IWOTH) ? 'w' : '-';
+ access[7] = (statbuf->st_mode & S_IROTH) ? 'r' : '-';
+ access[6] = (statbuf->st_mode & S_IXGRP) ?
+ ((statbuf->st_mode & S_ISGID) ? 's' : 'x') :
+ ((statbuf->st_mode & S_ISGID) ? 'S' : '-');
+ access[5] = (statbuf->st_mode & S_IWGRP) ? 'w' : '-';
+ access[4] = (statbuf->st_mode & S_IRGRP) ? 'r' : '-';
+ access[3] = (statbuf->st_mode & S_IXUSR) ?
+ ((statbuf->st_mode & S_ISUID) ? 's' : 'x') :
+ ((statbuf->st_mode & S_ISUID) ? 'S' : '-');
+ access[2] = (statbuf->st_mode & S_IWUSR) ? 'w' : '-';
+ access[1] = (statbuf->st_mode & S_IRUSR) ? 'r' : '-';
+
+ switch (statbuf->st_mode & S_IFMT)
+ {
+ case S_IFDIR:
+ access[0] = 'd';
+ break;
+ case S_IFCHR:
+ access[0] = 'c';
+ break;
+ case S_IFBLK:
+ access[0] = 'b';
+ break;
+ case S_IFREG:
+ access[0] = '-';
+ break;
+ case S_IFLNK:
+ access[0] = 'l';
+ break;
+ case S_IFSOCK:
+ access[0] = 's';
+ break;
+ case S_IFIFO:
+ access[0] = 'p';
+ break;
+ default:
+ access[0] = '?';
+ }
+ printf (access);
+}
+
+void print_human_time(time_t *t)
+{
+ char str[40];
+
+ if (strftime(str, 40, "%c", localtime(t)) > 0) printf(str);
+ else printf("Cannot calculate human readable time, sorry");
+}
+
+/* print statfs info */
+void print_statfs(char *pformat, char m, char *filename, void *data, SECURITY_ID_T sid)
+{
+ struct statfs *statfsbuf = (struct statfs*)data;
+#ifdef FLASK_LINUX
+ char sbuf[256];
+ int rv;
+ unsigned int sbuflen = sizeof(sbuf);
+#endif
+
+ switch(m) {
+ case 'n':
+ strcat(pformat, "s");
+ printf(pformat, filename);
+ break;
+#if !defined(__linux__) && defined (__GNU__)
+ case 'i':
+ strcat(pformat, "Lx");
+ printf(pformat, statfsbuf->f_fsid);
+ break;
+#else
+ case 'i':
+ strcat(pformat, "x %-8x");
+ printf(pformat, statfsbuf->f_fsid.__val[0], statfsbuf->f_fsid.__val[1]);
+ break;
+#endif
+
+ case 'l':
+#ifdef __USE_FILE_OFFSET64
+ strcat(pformat, "lu");
+#else
+ strcat(pformat, "d");
+#endif
+ printf(pformat, statfsbuf->f_namelen);
+ break;
+ case 't':
+#ifdef __USE_FILE_OFFSET64
+ strcat(pformat, "lx");
+#else
+ strcat(pformat, "x");
+#endif
+ printf(pformat, statfsbuf->f_type);
+ break;
+ case 'T':
+/* print_human_fstype(statfsbuf, pformat);*/
+ print_human_fstype(statfsbuf);
+ break;
+ case 'b':
+#ifdef __USE_FILE_OFFSET64
+ strcat(pformat, "lld");
+#else
+# if !defined(__linux__) && defined (__GNU__)
+ strcat(pformat, "d");
+# else
+ strcat(pformat, "ld");
+# endif
+#endif
+ printf(pformat, statfsbuf->f_blocks);
+ break;
+ case 'f':
+#ifdef __USE_FILE_OFFSET64
+ strcat(pformat, "lld");
+#else
+# if !defined(__linux__) && defined (__GNU__)
+ strcat(pformat, "d");
+# else
+ strcat(pformat, "ld");
+# endif
+#endif
+ printf(pformat, statfsbuf->f_bfree);
+ break;
+ case 'a':
+#ifdef __USE_FILE_OFFSET64
+ strcat(pformat, "lld");
+#else
+# if !defined(__linux__) && defined (__GNU__)
+ strcat(pformat, "d");
+# else
+ strcat(pformat, "ld");
+# endif
+#endif
+ printf(pformat, statfsbuf->f_bavail);
+ break;
+ case 's':
+#ifdef __USE_FILE_OFFSET64
+ strcat(pformat, "ld");
+#else
+ strcat(pformat, "d");
+#endif
+ printf(pformat, statfsbuf->f_bsize);
+ break;
+ case 'c':
+#ifdef __USE_FILE_OFFSET64
+ strcat(pformat, "lld");
+#else
+# if !defined(__linux__) && defined (__GNU__)
+ strcat(pformat, "d");
+# else
+ strcat(pformat, "ld");
+# endif
+#endif
+ printf(pformat, statfsbuf->f_files);
+ break;
+ case 'd':
+#ifdef __USE_FILE_OFFSET64
+ strcat(pformat, "lld");
+#else
+# if !defined(__linux__) && defined (__GNU__)
+ strcat(pformat, "d");
+# else
+ strcat(pformat, "ld");
+# endif
+#endif
+ printf(pformat, statfsbuf->f_ffree);
+ break;
+#ifdef FLASK_LINUX
+ case 'S':
+ strcat(pformat, "d");
+ printf(pformat, sid);
+ break;
+ case 'C':
+ rv = security_sid_to_context(sid, (security_context_t *) &sbuf, &sbuflen);
+ if ( rv < 0 )
+ sprintf(sbuf, "<error finding security context %d>", sid);
+ printf(sbuf);
+ break;
+#endif
+ default:
+ strcat(pformat, "c");
+ printf(pformat, m);
+ break;
+ }
+}
+
+/* print stat info */
+void print_stat(char *pformat, char m, char *filename, void *data, SECURITY_ID_T sid)
+{
+ char linkname[256];
+ int i;
+ struct stat *statbuf = (struct stat*)data;
+ struct passwd *pw_ent;
+ struct group *gw_ent;
+#ifdef FLASK_LINUX
+ char sbuf[256];
+ int rv;
+ unsigned int sbuflen = sizeof(sbuf);
+#endif
+
+ switch(m) {
+ case 'n':
+ strcat(pformat, "s");
+ printf(pformat, filename);
+ break;
+ case 'N':
+ strcat(pformat, "s");
+ if ((statbuf->st_mode & S_IFMT) == S_IFLNK) {
+ if ((i = readlink(filename, linkname, 256)) == -1) {
+ perror(filename);
+ return;
+ }
+ linkname[(i >= 256) ? 255 : i] = '\0';
+ /*printf("\"%s\" -> \"%s\"", filename, linkname);*/
+ printf("\"");
+ printf(pformat, filename);
+ printf("\" -> \"");
+ printf(pformat, linkname);
+ printf("\"");
+ } else {
+ printf("\"");
+ printf(pformat, filename);
+ printf("\"");
+ }
+ break;
+ case 'd':
+ strcat(pformat, "d");
+ printf(pformat, (int)statbuf->st_dev);
+ break;
+ case 'D':
+ strcat(pformat, "x");
+ printf(pformat, (int)statbuf->st_dev);
+ break;
+ case 'i':
+ strcat(pformat, "d");
+ printf(pformat, (int)statbuf->st_ino);
+ break;
+ case 'a':
+ strcat(pformat, "o");
+ printf(pformat, statbuf->st_mode & 07777);
+ break;
+ case 'A':
+ print_human_access(statbuf);
+ break;
+ case 'f':
+ strcat(pformat, "x");
+ printf(pformat, statbuf->st_mode);
+ break;
+ case 'F':
+ print_human_type(statbuf->st_mode);
+ break;
+ case 'h':
+ strcat(pformat, "d");
+ printf(pformat, (int)statbuf->st_nlink);
+ break;
+#ifdef FLASK_LINUX
+ case 'S':
+ strcat(pformat, "d");
+ printf(pformat, sid);
+ break;
+ case 'C':
+ rv = security_sid_to_context(sid, (security_context_t *) &sbuf, &sbuflen);
+ if ( rv < 0 )
+ sprintf(sbuf, "<error finding security context %d>", sid);
+ printf(sbuf);
+ break;
+#endif
+ case 'u':
+ strcat(pformat, "d");
+ printf(pformat, statbuf->st_uid);
+ break;
+ case 'U':
+ strcat(pformat, "s");
+ setpwent();
+ pw_ent = getpwuid(statbuf->st_uid);
+ printf(pformat,
+ (pw_ent != 0L) ? pw_ent->pw_name : "UNKNOWN");
+ break;
+ case 'g':
+ strcat(pformat, "d");
+ printf(pformat, statbuf->st_gid);
+ break;
+ case 'G':
+ strcat(pformat, "s");
+ setgrent();
+ gw_ent = getgrgid(statbuf->st_gid);
+ printf(pformat,
+ (gw_ent != 0L) ? gw_ent->gr_name : "UNKNOWN");
+ break;
+ case 't':
+ strcat(pformat, "x");
+ printf(pformat, major(statbuf->st_rdev));
+ break;
+ case 'T':
+ strcat(pformat, "x");
+ printf(pformat, minor(statbuf->st_rdev));
+ break;
+ case 's':
+#ifdef __USE_FILE_OFFSET64
+ strcat(pformat, "llu");
+ printf(pformat, (unsigned long long)statbuf->st_size);
+#else
+ strcat(pformat, "u");
+ printf(pformat, (unsigned int)statbuf->st_size);
+#endif
+ break;
+ case 'b':
+ strcat(pformat, "u");
+ printf(pformat, (unsigned int)statbuf->st_blocks);
+ break;
+ case 'o':
+ strcat(pformat, "d");
+ printf(pformat, (int)statbuf->st_blksize);
+ break;
+ case 'x':
+ print_human_time(&(statbuf->st_atime));
+ break;
+ case 'X':
+ strcat(pformat, "d");
+ printf(pformat, (int)statbuf->st_atime);
+ break;
+ case 'y':
+ print_human_time(&(statbuf->st_mtime));
+ break;
+ case 'Y':
+ strcat(pformat, "d");
+ printf(pformat, (int)statbuf->st_mtime);
+ break;
+ case 'z':
+ print_human_time(&(statbuf->st_ctime));
+ break;
+ case 'Z':
+ strcat(pformat, "d");
+ printf(pformat, (int)statbuf->st_ctime);
+ break;
+ default:
+ strcat(pformat, "c");
+ printf(pformat, m);
+ break;
+ }
+}
+
+void print_it(char *masterformat, char *filename,
+ void (*print_func)(char*, char, char*, void*, SECURITY_ID_T), void *data, SECURITY_ID_T sid)
+{
+ char *m, *b, *format;
+ char pformat[65];
+
+ /* create a working copy of the format string */
+ format = strdup(masterformat);
+ if (!format) {
+ perror(filename);
+ return;
+ }
+
+ b = format;
+ while (b)
+ {
+ if ((m = strchr(b, (int)'%')) != NULL)
+ {
+ strcpy (pformat, "%");
+ *m++ = '\0';
+ printf(b);
+
+ /* copy all format specifiers to our format string */
+ while (isdigit(*m) || strchr("#0-+. I", *m))
+ {
+ char copy[2]="a";
+
+ *copy = *m;
+ /* make sure the format specifier is not too long */
+ if (strlen (pformat) > 63)
+ fprintf(stderr, "Warning: Format specifier too long, truncating: %s\n", pformat);
+ else
+ strcat (pformat, copy);
+ m++;
+ }
+
+ switch(*m) {
+ case '\0':
+ case '%':
+ printf("%%");
+ break;
+ default:
+ print_func(pformat, *m, filename, data, sid);
+ break;
+ }
+ b = m + 1;
+ }
+ else
+ {
+ printf(b);
+ b = NULL;
+ }
+ }
+ free(format);
+ printf("\n");
+}
+
+/* stat the filesystem and print what we find */
+void
+do_statfs (char *filename, int terse, int secure, char *format)
+{
+ struct statfs statfsbuf;
+ SECURITY_ID_T sid = -1;
+ int i;
+
+#ifdef FLASK_LINUX
+ if(!is_flask_enabled())
+ secure = 0;
+ if(secure)
+ i = statfs_secure(filename, &statfsbuf, &sid);
+ else
+#endif
+ i = statfs(filename, &statfsbuf);
+ if(i == -1)
+ {
+ perror (filename);
+ return;
+ }
+
+ if (format == NULL)
+ {
+ if (terse != 0)
+ {
+#ifdef FLASK_LINUX
+ if(secure)
+ format = "%n %i %l %t %b %f %a %s %c %d %S %C";
+ else
+#endif
+ format = "%n %i %l %t %b %f %a %s %c %d";
+ }
+ else
+ {
+#ifdef FLASK_LINUX
+ if(secure)
+ format = " File: \"%n\"\n"
+ " ID: %-8i Namelen: %-7l Type: %T\n"
+ "Blocks: Total: %-10b Free: %-10f Available: %-10a Size: %s\n"
+ "Inodes: Total: %-10c Free: %-10d\n"
+ " SID: %-14S S_Context: %C\n";
+ else
+#endif
+ format = " File: \"%n\"\n"
+ " ID: %-8i Namelen: %-7l Type: %T\n"
+ "Blocks: Total: %-10b Free: %-10f Available: %-10a Size: %s\n"
+ "Inodes: Total: %-10c Free: %-10d";
+ }
+ }
+
+ print_it(format, filename, print_statfs, &statfsbuf, sid);
+}
+
+/* stat the file and print what we find */
+void
+do_stat (char *filename, int link, int terse, int secure, char *format)
+{
+ struct stat statbuf;
+ int i;
+ SECURITY_ID_T sid = -1;
+
+#ifdef FLASK_LINUX
+ if(!is_flask_enabled())
+ secure = 0;
+ if(secure)
+ i = (link == 1) ? stat_secure(filename, &statbuf, &sid) : lstat_secure(filename, &statbuf, &sid);
+ else
+#endif
+ i = (link == 1) ? stat(filename, &statbuf) : lstat(filename, &statbuf);
+
+ if (i == -1)
+ {
+ perror (filename);
+ return;
+ }
+
+ if (format == NULL)
+ {
+ if (terse != 0)
+ {
+#ifdef FLASK_LINUX
+ if (secure)
+ format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o %S %C";
+ else
+#endif
+ format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o";
+ }
+ else
+ {
+ /* tmp hack to match orignal output until conditional implemented */
+ i = statbuf.st_mode & S_IFMT;
+ if (i == S_IFCHR || i == S_IFBLK) {
+#ifdef FLASK_LINUX
+ if (secure)
+ format =
+ " File: %N\n"
+ " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
+ "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
+ " Device type: %t,%T\n"
+ "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
+ " SID: %-14S S_Context: %C\n"
+ "Access: %x\n"
+ "Modify: %y\n"
+ "Change: %z\n";
+ else
+#endif
+ format =
+ " File: %N\n"
+ " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
+ "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
+ " Device type: %t,%T\n"
+ "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
+ "Access: %x\n"
+ "Modify: %y\n"
+ "Change: %z\n";
+ }
+ else
+ {
+#ifdef FLASK_LINUX
+ if (secure)
+ format =
+ " File: %N\n"
+ " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
+ "Device: %Dh/%dd\tInode: %-10i Links: %-5h\n"
+ "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
+ " SID: %-14S S_Context: %C\n"
+ "Access: %x\n"
+ "Modify: %y\n"
+ "Change: %z\n";
+ else
+#endif
+ format =
+ " File: %N\n"
+ " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
+ "Device: %Dh/%dd\tInode: %-10i Links: %-5h\n"
+ "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
+ "Access: %x\n"
+ "Modify: %y\n"
+ "Change: %z\n";
+ }
+ }
+ }
+ print_it(format, filename, print_stat, &statbuf, sid);
+}
+
+void
+usage (char *progname)
+{
+ fprintf (stderr, "Usage: %s [-l] [-f] [-s] [-v] [-h] [-t] [-c format] file1 [file2 ...]\n", progname);
+ exit (1);
+}
+
+void verbose_usage(char *progname)
+{
+ fprintf(stderr, "Usage: %s [-l] [-f] [-s] [-v] [-h] [-t] [-c format] file1 [file2 ...]\n", progname);
+ fprintf(stderr, "\tformat interpreted sequences for file stat are:\n");
+ fprintf(stderr, "\t\t%%n - File name\n");
+ fprintf(stderr, "\t\t%%N - Quoted File name with dereference if symbolic link\n");
+ fprintf(stderr, "\t\t%%d - Device number in decimal\n");
+ fprintf(stderr, "\t\t%%D - Device number in hex\n");
+ fprintf(stderr, "\t\t%%i - Inode number\n");
+ fprintf(stderr, "\t\t%%a - Access rights in octal\n");
+ fprintf(stderr, "\t\t%%A - Access rights in human readable form\n");
+ fprintf(stderr, "\t\t%%f - raw mode in hex\n");
+ fprintf(stderr, "\t\t%%F - File type\n");
+ fprintf(stderr, "\t\t%%h - Number of hard links\n");
+ fprintf(stderr, "\t\t%%u - User Id of owner\n");
+ fprintf(stderr, "\t\t%%U - User name of owner\n");
+ fprintf(stderr, "\t\t%%g - Group Id of owner\n");
+ fprintf(stderr, "\t\t%%G - Group name of owner\n");
+ fprintf(stderr, "\t\t%%t - Major device type in hex\n");
+ fprintf(stderr, "\t\t%%T - Minor device type in hex\n");
+ fprintf(stderr, "\t\t%%s - Total size, in bytes\n");
+ fprintf(stderr, "\t\t%%b - Number of blocks allocated\n");
+ fprintf(stderr, "\t\t%%o - IO block size\n");
+ fprintf(stderr, "\t\t%%x - Time of last access\n");
+ fprintf(stderr, "\t\t%%X - Time of last access as seconds since Epoch\n");
+ fprintf(stderr, "\t\t%%y - Time of last modification\n");
+ fprintf(stderr, "\t\t%%Y - Time of last modification as seconds since Epoch\n");
+ fprintf(stderr, "\t\t%%z - Time of last change\n");
+ fprintf(stderr, "\t\t%%Z - Time of last change as seconds since Epoch\n");
+ fprintf(stderr, "\t\t%%S - Security ID in SE-Linux\n");
+ fprintf(stderr, "\t\t%%C - Security context in SE-Linux\n");
+ fprintf(stderr, "\tformat interpreted sequences for filesystem stat are:\n");
+ fprintf(stderr, "\t\t%%n - File name\n");
+ fprintf(stderr, "\t\t%%i - File System id in hex\n");
+ fprintf(stderr, "\t\t%%l - Maximum length of filenames\n");
+ fprintf(stderr, "\t\t%%t - Type in hex\n");
+ fprintf(stderr, "\t\t%%T - Type in human readable form\n");
+ fprintf(stderr, "\t\t%%b - Total data blocks in file system\n");
+ fprintf(stderr, "\t\t%%f - Free blocks in file system\n");
+ fprintf(stderr, "\t\t%%a - Free blocks available to non-superuser\n");
+ fprintf(stderr, "\t\t%%s - Optimal transfer block size\n");
+ fprintf(stderr, "\t\t%%c - Total file nodes in file system\n");
+ fprintf(stderr, "\t\t%%S - Security ID in SE-Linux\n");
+ fprintf(stderr, "\t\t%%C - Security context in SE-Linux\n");
+ fprintf(stderr, "\t\t%%d - Free file nodes in file system\n");
+ exit(1);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ int c, i, link = 0, fs = 0, terse = 0, secure = 0;
+ char *format = NULL;
+
+ while ((c = getopt (argc, argv, "lsfvthc:")) != EOF)
+ {
+ switch (c)
+ {
+ case 'l':
+ link = 1;
+ break;
+ case 's':
+ secure = 1;
+ break;
+ case 'f':
+ fs = 1;
+ break;
+ case 't':
+ terse = 1;
+ break;
+ case 'c':
+ format = optarg;
+ break;
+ case 'h':
+ printf ("stat version: 3.0\n");
+ verbose_usage(argv[0]);
+ break;
+ case 'v':
+ printf ("stat version: 3.0\n");
+ default:
+ usage (argv[0]);
+ }
+ }
+ if (argc == optind)
+ usage (argv[0]);
+
+ for (i = optind; i < argc; i++)
+ (fs == 0) ? do_stat (argv[i], link, terse, secure, format) :
+ do_statfs (argv[i], terse, secure, format);
+
+ return (0);
+}