From 5a26a86cec424d728d43523988ca70aa56ee76c9 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 2 Jun 2013 00:24:24 -0500 Subject: Stat cleanup. lib: rename format_mode() to mode_to_string() (echoing string_to_mode), make it take a normal char * argument. stat: collapse big switch/case statements that only have one line each into if/else staircase (much fewer lines of code). Remove return type (other stat implementations print ? for unknown escapes, so do that here). Inline do_stat() and do_statfs(). Set default string in normal local variable "format". Remove unnecessary struct d. Restructure stat logic to "if (flagf && !statfs()) else if (!flagf && !stat()) else perror_msg();" Teach %N to add -> symlink. Judicious use of putchar() instead of xputc to let FILE * do its job collating output. --- lib/lib.c | 10 +- lib/lib.h | 2 +- toys/pending/stat.c | 262 +++++++++++++++++----------------------------------- toys/posix/ls.c | 2 +- 4 files changed, 93 insertions(+), 183 deletions(-) diff --git a/lib/lib.c b/lib/lib.c index 7b0cf1a1..af820e22 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -1205,13 +1205,13 @@ barf: error_exit("bad mode '%s'", modestr); } -// Format a mode for ls and stat -void format_mode(char (*buf)[11], mode_t mode) +// Format access mode into a drwxrwxrwx string +void mode_to_string(mode_t mode, char *buf) { char c, d; int i, bit; - (*buf)[10]=0; + buf[10]=0; for (i=0; i<9; i++) { bit = mode & (1<tv_nsec); } -static int print_stat(char type) +static void print_stat(char type) { struct stat *stat = (struct stat *)&TT.stat; - switch (type) { - case 'a': - xprintf("%04lo", stat->st_mode & ~S_IFMT); - break; - case 'A': - xprintf("%s", TT.access_str); - break; - - case 'b': - xprintf("%llu", stat->st_blocks); - break; - - case 'B': - xprintf("%lu", stat->st_blksize); - break; - case 'd': - xprintf("%ldd", stat->st_dev); - break; - case 'D': - xprintf("%llxh", stat->st_dev); - break; - case 'f': - xprintf("%lx", stat->st_mode); - break; - case 'F': - xprintf("%s", TT.ftname); - break; - case 'g': - xprintf("%lu", stat->st_gid); - break; - case 'G': - xprintf("%8s", TT.user_name->pw_name); - break; - case 'h': - xprintf("%lu", stat->st_nlink); - break; - case 'i': - xprintf("%llu", stat->st_ino); - break; - case 'N': - xprintf("`%s'", *toys.optargs); - break; - case 'o': - xprintf("%lu", stat->st_blksize); - break; - case 's': - xprintf("%llu", stat->st_size); - break; - case 'u': - xprintf("%lu", stat->st_uid); - break; - case 'U': - xprintf("%8s", TT.user_name->pw_name); - break; - - case 'x': - date_stat_format((void *)&stat->st_atime); - break; - case 'X': - xprintf("%llu", (long long)stat->st_atime); - break; - case 'y': - date_stat_format((void *)&stat->st_mtime); - break; - case 'Y': - xprintf("%llu", (long long)stat->st_mtime); - break; - case 'z': - date_stat_format((void *)&stat->st_ctime); - break; - case 'Z': - xprintf("%llu", (long long)stat->st_ctime); - break; - - default: - return 1; - } - return 0; + 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') xprintf("%s", TT.ftname); + 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 int print_statfs(char type) { +static void print_statfs(char type) { struct statfs *statfs = (struct statfs *)&TT.stat; - switch (type) { - case 'a': - xprintf("%lu", statfs->f_bavail); - break; - case 'b': - xprintf("%lu", statfs->f_blocks); - break; - case 'c': - xprintf("%lu", statfs->f_files); - break; - case 'd': - xprintf("%lu", statfs->f_ffree); - break; - case 'f': - xprintf("%lu", statfs->f_bfree); - break; - case 'i': - xprintf("%x%x", statfs->f_fsid.__val[0], statfs->f_fsid.__val[1]); - break; - case 'l': - xprintf("%ld", statfs->f_namelen); - break; - case 's': - xprintf("%d", statfs->f_frsize); - break; - case 'S': - xprintf("%d", statfs->f_bsize); - break; - case 't': - xprintf("%lx", statfs->f_type); - break; - default: - return 1; - } - return 0; -} - -static int do_stat(char *path) -{ - struct stat *statf = (struct stat*)&TT.stat; - char *types = "character device\0directory\0block device\0" \ - "regular file\0symbolic link\0socket\0FIFO (named pipe)"; - int i, filetype; - - if (stat(path, statf) < 0) return 1; - - filetype = statf->st_mode & S_IFMT; - TT.ftname = types; - for (i = 1; filetype != (i*8192) && i < 7; i++) - TT.ftname += strlen(TT.ftname)+1; - if (!statf->st_size && filetype == S_IFREG) - TT.ftname = "regular empty file"; - - // check user and group name - TT.user_name = getpwuid(statf->st_uid); - TT.group_name = getgrgid(statf->st_gid); - // function to get access in human readable format - format_mode(&TT.access_str, statf->st_mode); - - return 0; -} - -static int do_statfs(char *path) -{ - return statfs(path, (void *)&TT.stat) < 0; + 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("%x%x", 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) { - struct { - char *fmt; - int (*do_it)(char*); - int (*print_it)(char); - } d, ds[2] = { - {" 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", - do_stat, print_stat}, - {" 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", - do_statfs, print_statfs} - }; - - d = ds[toys.optflags & FLAG_f]; - if (toys.optflags & FLAG_c) d.fmt = TT.fmt; + 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 *format = d.fmt; - if (d.do_it(*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; + char *types = "character device\0directory\0block device\0" \ + "regular file\0symbolic link\0socket\0FIFO (named pipe)"; + int i, filetype; + + filetype = stat->st_mode & S_IFMT; + TT.ftname = types; + for (i = 1; filetype != (i*8192) && i < 7; i++) + TT.ftname += strlen(TT.ftname)+1; + if (!stat->st_size && filetype == S_IFREG) + TT.ftname = "regular empty file"; + + // 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 (; *format; format++) { - if (*format != '%') { - xputc(*format); - 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); } - format++; - if (*format == 'n') xprintf("%s", *toys.optargs); - else if (d.print_it(*format)) xputc(*format); } xputc('\n'); } diff --git a/toys/posix/ls.c b/toys/posix/ls.c index 76fb7947..caabe7df 100644 --- a/toys/posix/ls.c +++ b/toys/posix/ls.c @@ -337,7 +337,7 @@ static void listfiles(int dirfd, struct dirtree *indir) struct tm *tm; char perm[11], thyme[64], *usr, *upad, *grp, *grpad; - format_mode(&perm, mode); + mode_to_string(mode, perm); tm = localtime(&(st->st_mtime)); strftime(thyme, sizeof(thyme), "%F %H:%M", tm); -- cgit v1.2.3