changeset 747:68d6c1ce7bba

Add stat submission to new "pending" directory, along with infrastructure to support pending.
author Rob Landley <rob@landley.net>
date Mon, 10 Dec 2012 21:08:42 -0600
parents 5caa4035c1c8
children 8947c0d35e58
files scripts/genconfig.sh toys.h toys/pending/README toys/pending/stat.c
diffstat 4 files changed, 324 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/genconfig.sh	Mon Dec 10 01:48:02 2012 -0600
+++ b/scripts/genconfig.sh	Mon Dec 10 21:08:42 2012 -0600
@@ -29,11 +29,13 @@
   # and capitalization in the menu
   for j in toys/*/README
   do
+    DIR="$(dirname "$j")"
+
+    [ $(ls "$DIR" | wc -l) -lt 2 ] && continue
+
     echo "menu \"$(head -n 1 $j)\""
     echo
 
-    DIR="$(dirname "$j")"
-
     # extract config stanzas from each source file, in alphabetical order
     for i in $(ls -1 $DIR/*.c)
     do
--- a/toys.h	Mon Dec 10 01:48:02 2012 -0600
+++ b/toys.h	Mon Dec 10 21:08:42 2012 -0600
@@ -34,6 +34,7 @@
 #include <sys/mount.h>
 #include <sys/resource.h>
 #include <sys/stat.h>
+#include <sys/statfs.h>
 #include <sys/statvfs.h>
 #include <sys/sysinfo.h>
 #include <sys/swap.h>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/pending/README	Mon Dec 10 21:08:42 2012 -0600
@@ -0,0 +1,3 @@
+pending
+
+These commands await additional review and/or cleanup.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/pending/stat.c	Mon Dec 10 21:08:42 2012 -0600
@@ -0,0 +1,316 @@
+/* vi: set sw=4 ts=4
+*
+* stat.c : display file or file system status
+* anand.sinha85@gmail.com
+* Copyright 2012 <warior.linux@gmail.com>
+*
+* See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/stat.html
+USE_STAT(NEWTOY(stat, "LZfc", TOYFLAG_BIN)) 
+config STAT
+    bool st
+    default n
+    help
+        Usage: stat [OPTION] FILE...
+        display file or file system status
+        -Z, --context
+             print the security context information if available
+        -f, --file-system
+            display file system status instead of file status
+        -c  --format=FORMAT
+            use the specified FORMAT instead of the default; output a newline after each use of FORMAT
+        --help display this help and exit
+        The valid format sequences for files (without --file-system):
+        %a     Access rights in octal
+        %A     Access rights in human readable form
+        %b     Number of blocks allocated (see
+        %B     The size in bytes of each block reported by
+        %d     Device number in decimal
+        %D     Device number in hex
+        %f     Raw mode in hex
+        %F     File type
+        %G     Group name of owner
+        %h     Number of hard links
+        %i     Inode number
+        %n     File name
+        %N     Quoted file name with dereference if symbolic link
+        %o     I/O block size
+        %s     Total size, in bytes
+        %t     Major device type in hex
+        %T     Minor device type in hex
+        %u     User ID of owner
+        %U     User name of owner
+        %x     Time of last access
+        %X     Time of last access as seconds since Epoch
+        %y     Time of last modification
+        %Y     Time of last modification as seconds since Epoch
+        %z     Time of last change
+        %Z     Time of last change as seconds since Epoch
+*/
+
+#define FOR_stat
+#include "toys.h"
+#define SIZE_DATE_TIME_STAT 36
+#define access_string(x, s, i)  if((x&7) & 1)           \
+                                s[9 - i * 3] = 'x';       \
+                           else                             \
+                               s[9 - i * 3] = '-';             \
+                           if(((x&7) >> 1) & 1)                 \
+                               s[9 - (i * 3 + 1)] = 'w';            \
+                           else                     \
+                               s[9 - (i * 3 + 1)] = '-';            \
+                           if(((x&7) >> 2) & 1)     \
+                               s[9 - (i * 3 + 2)] = 'r';            \
+                           else                     \
+                               s[9 - (i * 3 + 2)] = '-';
+
+static char * check_type_file(mode_t, size_t);
+static char * get_access_str(unsigned long, mode_t);
+static char * date_stat_format(time_t );
+static int do_stat(const char *);
+static int do_statfs(const char *);
+inline void print_stat_format(char *, int);
+
+GLOBALS(
+	char * access_str;
+	char * file_type;
+	struct passwd * user_name; struct group * group_name; struct tm *time_toy;
+	struct stat * toystat;
+	struct statfs * toystatfs;
+	int toy_obj_file_arg;
+)
+
+
+static int do_stat(const char * file_name){
+    TT.toystat = (struct stat*)malloc(sizeof(struct stat));
+    if(stat(file_name, TT.toystat) < 0){
+        perror_msg("Error: unable to get information about the file, stat\n", file_name);
+        toys.exitval = EXIT_FAILURE;
+    }
+    return 0;
+}
+
+static int do_statfs(const char * file_name){
+    TT.toystatfs = (struct statfs *)malloc(sizeof(struct statfs));
+    if(statfs(file_name, TT.toystatfs) < 0){
+        perror_msg("Error: unable to get information about the file, statfs\n", file_name);
+        toys.exitval = EXIT_FAILURE;
+    }
+    return 0;
+}
+
+static char * check_type_file(mode_t mode, size_t size){
+    if(S_ISREG(mode)){
+        if(size)
+            return "regular file";
+            return "regular empty file";
+    }
+    if(S_ISDIR(mode))
+        return "directory"; 
+    if(S_ISCHR(mode))
+        return "character device";
+    if(S_ISBLK(mode))
+        return "block device";
+    if(S_ISFIFO(mode))
+        return "FIFO (named pipe)";
+    if(S_ISLNK(mode))
+        return "symbolic link";
+    if(S_ISSOCK(mode))
+        return "socket";
+}
+
+static char * get_access_str(unsigned long pernission, mode_t mode){
+    static char access_string[10];
+    int i;
+    if(S_ISDIR(mode))
+        access_string[0] = 'd';
+    else
+        access_string[0] = '-';
+    for(i = 0; i < 3; i++){
+        access_string(pernission >> (i * 3) & 7, access_string, i);
+    }
+    access_string[10] = '\0';
+    return access_string;
+}
+
+static char * date_stat_format(time_t time){
+    static char buf[SIZE_DATE_TIME_STAT];
+    strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S.000000000", localtime(&time));
+    return buf;
+}
+
+inline void print_stat_format(char *format, int flag){
+    format++;
+    switch(*format){
+        case 'a':
+            if(flag)
+                xprintf("%lu\n", TT.toystatfs->f_bavail);
+            else
+                xprintf("%04lo\n",TT.toystat->st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO));
+            break;
+        case 'A':
+            xprintf("%s\n",TT.access_str);
+            break;
+        case 'b':
+            if(flag)
+                xprintf("%lu\n", TT.toystatfs->f_blocks);
+            else
+                xprintf("%llu\n", TT.toystat->st_blocks);
+            break;
+        case 'B':
+            xprintf("%lu\n", TT.toystat->st_blksize);
+            break;
+        case 'c':
+            if(flag)
+                xprintf("%lu\n", TT.toystatfs->f_files);
+            break;
+        case 'C':
+            xprintf("Currently feature is not supported\n");
+            break;
+        case 'd':
+            if(flag)
+                xprintf("%lu\n", TT.toystatfs->f_ffree);
+            else
+                xprintf("%ldd\n", TT.toystat->st_dev);
+            break;
+        case 'D':
+            xprintf("%llxh\n", TT.toystat->st_dev);
+            break;
+        case 'f':
+            if(flag)
+                xprintf("%lu\n", TT.toystatfs->f_bfree);
+            else
+                xprintf("%lx\n", TT.toystat->st_mode);
+            break;
+        case 'F':
+            xprintf("%s\n", TT.file_type);
+            break;
+        case 'g':
+            xprintf("%lu\n", TT.toystat->st_uid);
+            break;
+        case 'G':
+            xprintf("%8s\n", TT.user_name->pw_name);
+            break;
+        case 'h':
+            xprintf("%lu\n", TT.toystat->st_nlink);
+            break;
+        case 'i':
+            if(flag)
+                xprintf("%d%d\n", TT.toystatfs->f_fsid.__val[0], TT.toystatfs->f_fsid.__val[1]);
+            else
+                xprintf("%llu\n", TT.toystat->st_ino);
+            break;
+        case 'l':
+            if(flag)
+                xprintf("need to implement\n");
+            break;
+        case 'n':
+            xprintf("%s\n", toys.optargs[TT.toy_obj_file_arg]);
+            break;
+        case 'N':
+            xprintf("`%s\n'", toys.optargs[TT.toy_obj_file_arg]);
+            break;
+        case 'o':
+            xprintf("%lu\n", TT.toystat->st_blksize);
+            break;
+        case 's':
+            if(flag)
+                xprintf("%d\n", TT.toystatfs->f_frsize);
+            else
+                xprintf("%llu\n", TT.toystat->st_size);
+            break;
+        case 'S':
+            if(flag)
+                xprintf("%d\n", TT.toystatfs->f_bsize);
+            break;
+        case 't':
+            if(flag)
+                xprintf("%lx\n", TT.toystatfs->f_type);
+            break;
+        case 'T':
+            if(flag)
+                xprintf("Needs to be implemented\n");
+            break;
+        case 'u':
+            xprintf("%lu\n", TT.toystat->st_uid);
+            break;
+        case 'U':
+            xprintf("%8s\n", TT.user_name->pw_name);
+            break;
+        case 'x':
+            xprintf("%s\n", date_stat_format(TT.toystat->st_atime));
+            break;
+        case 'X':
+            xprintf("%llu\n", TT.toystat->st_atime);
+            break;
+        case 'y':
+            xprintf("%s\n", date_stat_format(TT.toystat->st_mtime));
+            break;
+        case 'Y':
+            xprintf("%llu\n", TT.toystat->st_mtime);
+            break;
+        case 'z':
+            xprintf("%s\n", date_stat_format(TT.toystat->st_ctime));
+            break;
+        case 'Z':
+            xprintf("%llu\n", TT.toystat->st_ctime);
+        default:
+            xprintf("%c\n", *format);
+            break;
+    }
+    exit(0);
+}
+
+void stat_main(void){
+    int stat_flag_Z = 0, stat_flag_f = 0, stat_flag_c = 0, stat_format = 0;
+    if(toys.optargs){
+        if(toys.optflags & 1){
+            stat_flag_c = 1;
+            TT.toy_obj_file_arg = 1;
+            stat_format = 1;
+        }
+        if(toys.optflags & (1 << 1)){
+            stat_flag_f = 1;
+            if(do_statfs(toys.optargs[TT.toy_obj_file_arg]) != 0)
+                xprintf("Error STATFS\n");
+        }else
+            if(do_stat(toys.optargs[TT.toy_obj_file_arg]) != 0)
+                xprintf("Error STAT\n");
+        if(toys.optflags & (1 << 2)){
+            stat_flag_Z = 1;
+            xprintf("SELinux feature has not been implemented so far..\n");
+        }
+    }
+// function to check the type/mode of file
+    if(!stat_flag_f){
+        TT.file_type = check_type_file(TT.toystat->st_mode, TT.toystat->st_size);
+// check user and group name
+        TT.user_name = getpwuid(TT.toystat->st_uid);
+        TT.group_name = getgrgid(TT.toystat->st_gid);
+// function to get access in human readable format
+        TT.access_str = get_access_str((TT.toystat->st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)), TT.toystat->st_mode);
+        TT.time_toy = gmtime(&(TT.toystat->st_atime));
+    }
+    if(!(stat_flag_f |stat_flag_Z)){
+        if(stat_format)
+            print_stat_format(toys.optargs[0], stat_flag_f);
+        xprintf(" File: `%s'\n", toys.optargs[TT.toy_obj_file_arg]);
+        xprintf(" Size: %llu\t Blocks: %llu\t IO Blocks: %lu\t", TT.toystat->st_size, TT.toystat->st_blocks, TT.toystat->st_blksize);
+        xprintf("%s\n", TT.file_type);
+        xprintf("Device: %llxh\t Inode: %llu\t Links: %lu\n", TT.toystat->st_dev, TT.toystat->st_ino, TT.toystat->st_nlink);
+        xprintf("Access: (%04lo/%s)\tUid: (%lu/%8s)\tGid: (%lu/%8s)\n", (TT.toystat->st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)), TT.access_str, TT.toystat->st_uid, TT.user_name->pw_name, TT.toystat->st_gid, TT.group_name->gr_name);
+        xprintf("Access: %s\nModify: %s\nChange: %s\n", date_stat_format(TT.toystat->st_atime), date_stat_format(TT.toystat->st_mtime), date_stat_format(TT.toystat->st_ctime));
+    }else if(stat_flag_f){
+        // implementation of statfs -f, file system
+        if(stat_format)
+            print_stat_format(toys.optargs[0], stat_flag_f);
+        xprintf(" File: \"%s\"\n", toys.optargs[TT.toy_obj_file_arg]);
+        xprintf("   ID: %d%d Namelen: %ld    Type: %lx\n", TT.toystatfs->f_fsid.__val[0], TT.toystatfs->f_fsid.__val[1], TT.toystatfs->f_namelen, TT.toystatfs->f_type);
+        xprintf("Block Size: %d    Fundamental block size: %d\n", TT.toystatfs->f_bsize, TT.toystatfs->f_frsize);
+        xprintf("Blocks: Total: %lu\t", TT.toystatfs->f_blocks);
+        xprintf("Free: %lu\t", TT.toystatfs->f_bfree);
+        xprintf("Available: %lu\n", TT.toystatfs->f_bavail);
+        xprintf("Inodes: Total: %lu\t", TT.toystatfs->f_files);
+        xprintf("\tFree: %d\n", TT.toystatfs->f_ffree);
+    }
+}
+