aboutsummaryrefslogtreecommitdiff
path: root/toys/pending/stat.c
diff options
context:
space:
mode:
Diffstat (limited to 'toys/pending/stat.c')
-rw-r--r--toys/pending/stat.c316
1 files changed, 316 insertions, 0 deletions
diff --git a/toys/pending/stat.c b/toys/pending/stat.c
new file mode 100644
index 00000000..e8dd7218
--- /dev/null
+++ b/toys/pending/stat.c
@@ -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);
+ }
+}
+