# HG changeset patch # User Rob Landley # Date 1370152495 18000 # Node ID eea4c1b3595906016de02892b97f58a479a4eb87 # Parent b2697351ce6d4aa1bb92a303ce791d14c5cf7584 Move stat from pending to other, default y. diff -r b2697351ce6d -r eea4c1b35959 toys/other/stat.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toys/other/stat.c Sun Jun 02 00:54:55 2013 -0500 @@ -0,0 +1,163 @@ +/* stat.c : display file or file system status + * Copyright 2012 + * Copyright 2013 + +USE_STAT(NEWTOY(stat, "c:f", TOYFLAG_BIN)) + +config STAT + bool stat + default y + help + usage: stat [-f] [-c FORMAT] FILE... + + Display status of files or filesystems. + + -f display filesystem status instead of file status + -c Output specified FORMAT string instead of default + + The valid format escape sequences for files: + %a Access bits (octal) |%A Access bits (flags)|%b Blocks allocated + %B Bytes per block |%d Device ID (dec) |%D Device ID (hex) + %f All mode bits (hex) |%F File type |%g Group ID + %G Group name |%h Hard links |%i Inode + %n Filename |%N Long filename |%o I/O block size + %s Size (bytes) |%u User ID |%U User name + %x Access time |%X Access unix time |%y File write time + %Y File write unix time|%z Dir change time |%Z Dir change unix time + + The valid format escape sequences for filesystems: + %a Available blocks |%b Total blocks |%c Total inodes + %d Free inodes |%f Free blocks |%i File system ID + %l Max filename length |%n File name |%s Fragment size + %S Best transfer size |%t File system type +*/ + +#define FOR_stat +#include "toys.h" + +GLOBALS( + char *fmt; + + union { + struct stat st; + struct statfs sf; + } stat; + struct passwd *user_name; + struct group *group_name; +) + + +// Note: the atime, mtime, and ctime fields in struct stat are the start +// of embedded struct timespec, but posix won't let them use that +// struct definition for legacy/namespace reasons. + +static void date_stat_format(struct timespec *ts) +{ + strftime(toybuf, sizeof(toybuf), "%Y-%m-%d %H:%M:%S", + localtime(&(ts->tv_sec))); + xprintf("%s.%09d", toybuf, ts->tv_nsec); +} + +static void print_stat(char type) +{ + struct stat *stat = (struct stat *)&TT.stat; + + if (type == 'a') xprintf("%04lo", stat->st_mode & ~S_IFMT); + else if (type == 'A') { + char str[11]; + + mode_to_string(stat->st_mode, str); + xprintf("%s", str); + } else if (type == 'b') xprintf("%llu", stat->st_blocks); + else if (type == 'B') xprintf("%lu", stat->st_blksize); + else if (type == 'd') xprintf("%ldd", stat->st_dev); + else if (type == 'D') xprintf("%llxh", stat->st_dev); + else if (type == 'f') xprintf("%lx", stat->st_mode); + else if (type == 'F') { + char *t = "character device\0directory\0block device\0" \ + "regular file\0symbolic link\0socket\0FIFO (named pipe)"; + int i, filetype = stat->st_mode & S_IFMT; + + for (i = 1; filetype != (i*8192) && i < 7; i++) t += strlen(t)+1; + if (!stat->st_size && filetype == S_IFREG) t = "regular empty file"; + xprintf("%s", t); + } else if (type == 'g') xprintf("%lu", stat->st_gid); + else if (type == 'G') xprintf("%8s", TT.user_name->pw_name); + else if (type == 'h') xprintf("%lu", stat->st_nlink); + else if (type == 'i') xprintf("%llu", stat->st_ino); + else if (type == 'N') { + xprintf("`%s'", *toys.optargs); + if (S_ISLNK(stat->st_mode)) + if (0 `%s'", toybuf); + } else if (type == 'o') xprintf("%lu", stat->st_blksize); + else if (type == 's') xprintf("%llu", stat->st_size); + else if (type == 'u') xprintf("%lu", stat->st_uid); + else if (type == 'U') xprintf("%8s", TT.user_name->pw_name); + else if (type == 'x') date_stat_format((void *)&stat->st_atime); + else if (type == 'X') xprintf("%llu", (long long)stat->st_atime); + else if (type == 'y') date_stat_format((void *)&stat->st_mtime); + else if (type == 'Y') xprintf("%llu", (long long)stat->st_mtime); + else if (type == 'z') date_stat_format((void *)&stat->st_ctime); + else if (type == 'Z') xprintf("%llu", (long long)stat->st_ctime); + else xprintf("?"); +} + +static void print_statfs(char type) { + struct statfs *statfs = (struct statfs *)&TT.stat; + + if (type == 'a') xprintf("%lu", statfs->f_bavail); + else if (type == 'b') xprintf("%lu", statfs->f_blocks); + else if (type == 'c') xprintf("%lu", statfs->f_files); + else if (type == 'd') xprintf("%lu", statfs->f_ffree); + else if (type == 'f') xprintf("%lu", statfs->f_bfree); + else if (type == 'l') xprintf("%ld", statfs->f_namelen); + else if (type == 't') xprintf("%lx", statfs->f_type); + else if (type == 'i') + xprintf("%08x%08x", statfs->f_fsid.__val[0], statfs->f_fsid.__val[1]); + else if (type == 's') xprintf("%d", statfs->f_frsize); + else if (type == 'S') xprintf("%d", statfs->f_bsize); + else xprintf("?"); +} + +void stat_main(void) +{ + int flagf = toys.optflags & FLAG_f; + char *format = flagf + ? " File: \"%n\"\n ID: %i Namelen: %l Type: %t\n" + "Block Size: %s Fundamental block size: %S\n" + "Blocks: Total: %b\tFree: %f\tAvailable: %a\n" + "Inodes: Total: %c\tFree: %d" + : " File: %N\n Size: %s\t Blocks: %b\t IO Blocks: %B\t%F\n" + "Device: %D\t Inode: %i\t Links: %h\n" + "Access: (%a/%A)\tUid: (%u/%U)\tGid: (%g/%G)\n" + "Access: %x\nModify: %y\nChange: %z"; + + if (toys.optflags & FLAG_c) format = TT.fmt; + + for (; *toys.optargs; toys.optargs++) { + char *f; + + if (flagf && !statfs(*toys.optargs, (void *)&TT.stat)); + else if (!flagf && !lstat(*toys.optargs, (void *)&TT.stat)) { + struct stat *stat = (struct stat*)&TT.stat; + + // check user and group name + TT.user_name = getpwuid(stat->st_uid); + TT.group_name = getgrgid(stat->st_gid); + } else { + perror_msg("'%s'", *toys.optargs); + continue; + } + + for (f = format; *f; f++) { + if (*f != '%') putchar(*f); + else { + if (*++f == 'n') xprintf("%s", *toys.optargs); + else if (flagf) print_statfs(*f); + else print_stat(*f); + } + } + xputc('\n'); + } +} diff -r b2697351ce6d -r eea4c1b35959 toys/pending/stat.c --- a/toys/pending/stat.c Sun Jun 02 00:52:14 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,163 +0,0 @@ -/* stat.c : display file or file system status - * Copyright 2012 - * Copyright 2013 - -USE_STAT(NEWTOY(stat, "c:f", TOYFLAG_BIN)) - -config STAT - bool stat - default n - help - usage: stat [-f] [-c FORMAT] FILE... - - Display status of files or filesystems. - - -f display filesystem status instead of file status - -c Output specified FORMAT string instead of default - - The valid format escape sequences for files: - %a Access bits (octal) |%A Access bits (flags)|%b Blocks allocated - %B Bytes per block |%d Device ID (dec) |%D Device ID (hex) - %f All mode bits (hex) |%F File type |%g Group ID - %G Group name |%h Hard links |%i Inode - %n Filename |%N Long filename |%o I/O block size - %s Size (bytes) |%u User ID |%U User name - %x Access time |%X Access unix time |%y File write time - %Y File write unix time|%z Dir change time |%Z Dir change unix time - - The valid format escape sequences for filesystems: - %a Available blocks |%b Total blocks |%c Total inodes - %d Free inodes |%f Free blocks |%i File system ID - %l Max filename length |%n File name |%s Fragment size - %S Best transfer size |%t File system type -*/ - -#define FOR_stat -#include "toys.h" - -GLOBALS( - char *fmt; - - union { - struct stat st; - struct statfs sf; - } stat; - struct passwd *user_name; - struct group *group_name; -) - - -// Note: the atime, mtime, and ctime fields in struct stat are the start -// of embedded struct timespec, but posix won't let them use that -// struct definition for legacy/namespace reasons. - -static void date_stat_format(struct timespec *ts) -{ - strftime(toybuf, sizeof(toybuf), "%Y-%m-%d %H:%M:%S", - localtime(&(ts->tv_sec))); - xprintf("%s.%09d", toybuf, ts->tv_nsec); -} - -static void print_stat(char type) -{ - struct stat *stat = (struct stat *)&TT.stat; - - if (type == 'a') xprintf("%04lo", stat->st_mode & ~S_IFMT); - else if (type == 'A') { - char str[11]; - - mode_to_string(stat->st_mode, str); - xprintf("%s", str); - } else if (type == 'b') xprintf("%llu", stat->st_blocks); - else if (type == 'B') xprintf("%lu", stat->st_blksize); - else if (type == 'd') xprintf("%ldd", stat->st_dev); - else if (type == 'D') xprintf("%llxh", stat->st_dev); - else if (type == 'f') xprintf("%lx", stat->st_mode); - else if (type == 'F') { - char *t = "character device\0directory\0block device\0" \ - "regular file\0symbolic link\0socket\0FIFO (named pipe)"; - int i, filetype = stat->st_mode & S_IFMT; - - for (i = 1; filetype != (i*8192) && i < 7; i++) t += strlen(t)+1; - if (!stat->st_size && filetype == S_IFREG) t = "regular empty file"; - xprintf("%s", t); - } else if (type == 'g') xprintf("%lu", stat->st_gid); - else if (type == 'G') xprintf("%8s", TT.user_name->pw_name); - else if (type == 'h') xprintf("%lu", stat->st_nlink); - else if (type == 'i') xprintf("%llu", stat->st_ino); - else if (type == 'N') { - xprintf("`%s'", *toys.optargs); - if (S_ISLNK(stat->st_mode)) - if (0 `%s'", toybuf); - } else if (type == 'o') xprintf("%lu", stat->st_blksize); - else if (type == 's') xprintf("%llu", stat->st_size); - else if (type == 'u') xprintf("%lu", stat->st_uid); - else if (type == 'U') xprintf("%8s", TT.user_name->pw_name); - else if (type == 'x') date_stat_format((void *)&stat->st_atime); - else if (type == 'X') xprintf("%llu", (long long)stat->st_atime); - else if (type == 'y') date_stat_format((void *)&stat->st_mtime); - else if (type == 'Y') xprintf("%llu", (long long)stat->st_mtime); - else if (type == 'z') date_stat_format((void *)&stat->st_ctime); - else if (type == 'Z') xprintf("%llu", (long long)stat->st_ctime); - else xprintf("?"); -} - -static void print_statfs(char type) { - struct statfs *statfs = (struct statfs *)&TT.stat; - - if (type == 'a') xprintf("%lu", statfs->f_bavail); - else if (type == 'b') xprintf("%lu", statfs->f_blocks); - else if (type == 'c') xprintf("%lu", statfs->f_files); - else if (type == 'd') xprintf("%lu", statfs->f_ffree); - else if (type == 'f') xprintf("%lu", statfs->f_bfree); - else if (type == 'l') xprintf("%ld", statfs->f_namelen); - else if (type == 't') xprintf("%lx", statfs->f_type); - else if (type == 'i') - xprintf("%08x%08x", statfs->f_fsid.__val[0], statfs->f_fsid.__val[1]); - else if (type == 's') xprintf("%d", statfs->f_frsize); - else if (type == 'S') xprintf("%d", statfs->f_bsize); - else xprintf("?"); -} - -void stat_main(void) -{ - int flagf = toys.optflags & FLAG_f; - char *format = flagf - ? " File: \"%n\"\n ID: %i Namelen: %l Type: %t\n" - "Block Size: %s Fundamental block size: %S\n" - "Blocks: Total: %b\tFree: %f\tAvailable: %a\n" - "Inodes: Total: %c\tFree: %d" - : " File: %N\n Size: %s\t Blocks: %b\t IO Blocks: %B\t%F\n" - "Device: %D\t Inode: %i\t Links: %h\n" - "Access: (%a/%A)\tUid: (%u/%U)\tGid: (%g/%G)\n" - "Access: %x\nModify: %y\nChange: %z"; - - if (toys.optflags & FLAG_c) format = TT.fmt; - - for (; *toys.optargs; toys.optargs++) { - char *f; - - if (flagf && !statfs(*toys.optargs, (void *)&TT.stat)); - else if (!flagf && !lstat(*toys.optargs, (void *)&TT.stat)) { - struct stat *stat = (struct stat*)&TT.stat; - - // check user and group name - TT.user_name = getpwuid(stat->st_uid); - TT.group_name = getgrgid(stat->st_gid); - } else { - perror_msg("'%s'", *toys.optargs); - continue; - } - - for (f = format; *f; f++) { - if (*f != '%') putchar(*f); - else { - if (*++f == 'n') xprintf("%s", *toys.optargs); - else if (flagf) print_statfs(*f); - else print_stat(*f); - } - } - xputc('\n'); - } -}