X-Git-Url: https://pd.if.org/git/?a=blobdiff_plain;f=src%2Fstat.c;fp=src%2Fstat.c;h=d9f5aa115a8985ab24beaffc8cc58f50f63254e8;hb=5dd3c3e64a9574112dda77a5afc167f5daa53fd8;hp=0000000000000000000000000000000000000000;hpb=bd21f0a1265b43ad5f05353a39db31c16826f05c;p=zpackage diff --git a/src/stat.c b/src/stat.c new file mode 100644 index 0000000..d9f5aa1 --- /dev/null +++ b/src/stat.c @@ -0,0 +1,215 @@ +#define _POSIX_C_SOURCE 200112L + +#include +#include +#include +#include +#include +#include + +#include "zpm.h" + +/* + * a generic printf style format string parser + * takes a character pointer, returns pointer to next non + * parsed character, next token, optionally + * does a callback, fills in a format struct + */ + +#if 0 +char *fmt; +struct format f; + +while (*fmt) { + fmt = parse_format_str(fmt, &f); + if (!f.found) break; /* done */ + if (!f.flags) { + /* literal/noformat */ + putchar(f.found); /* or whatever */ + continue; + } + switch (f.found) { + case 'a': /* handle %a */ + break; + default: /* handle unknown formatting character */ + break; + } +} +#endif + +struct format_string { + int found; /* the 'd' in '%d' */ + unsigned flags; /* 1 = found, 0 = none found */ +}; + +char *format_string_parse(char *s, struct format_string *f) { + f->found = 0; + f->flags = 0; + + if (!*s) return s; /* done */ + + /* literal non-format specifier */ + if (*s != '%') { + f->found = *s++; + return s; + } + s++; + + f->flags = 1; + f->found = *s++; + return s; +} + +void stat_one(char *fmt, char *timefmt, int zeroterm, char *filename, struct + stat *buf) { + struct tm *tm; + char timestr[1024]; + struct format_string f; + struct passwd *pw; + struct group *gr; + + while (*fmt) { + fmt = format_string_parse(fmt, &f); + if (!f.found) break; /* done */ + if (!f.flags) { + if (f.found == '\\') { + switch (*fmt) { + case 0: + continue; break; + case 'n': + putchar('\n'); break; + case 't': + putchar('\t'); break; + default: + putchar(*fmt); + break; + } + fmt++; + continue; + } + /* literal/noformat */ + putchar(f.found); /* or whatever */ + continue; + } + switch (f.found) { + case 'y': /* handle mtime */ + tm = gmtime(&buf->st_mtime); + strftime(timestr, 1023, timefmt, tm); + timestr[1023] = 0; + printf("%s", timestr); + break; + case 's': + printf("%jd", (intmax_t)buf->st_size); + break; + case 'a': /* octal mode */ + printf("%o", (int)buf->st_mode & 07777); + break; + case 't': + if (S_ISBLK(buf->st_mode)) { + printf("block"); + } else if (S_ISCHR(buf->st_mode)) { + printf("character"); + } else if (S_ISDIR(buf->st_mode)) { + printf("directory"); + } else if (S_ISFIFO(buf->st_mode)) { + printf("fifo"); + } else if (S_ISREG(buf->st_mode)) { + printf("regular"); + } else if (S_ISLNK(buf->st_mode)) { + printf("symlink"); + } else if (S_ISSOCK(buf->st_mode)) { + printf("socket"); + } else { + printf("unknown"); + } + break; + case 'u': /* handle uid */ + printf("%0d", buf->st_uid); + break; + case 'U': /* handle username */ + pw = getpwuid(buf->st_uid); + if (!pw) exit(1); + printf("%s", pw->pw_name); + break; + case 'g': /* handle gid */ + printf("%0d", buf->st_gid); + break; + case 'G': /* handle groupname */ + gr = getgrgid(buf->st_gid); + if (!gr) exit(1); + printf("%s", gr->gr_name); + break; + case 'n': + printf("%s", filename); + break; + case 'z': + putchar(0); break; + case '%': + putchar('%'); + break; + default: /* handle unknown formatting character */ + printf("%c", f.found); + break; + } + } + if (zeroterm & 2) { + return; + } + + if (zeroterm & 1 ) { + putchar(0); + } else { + putchar('\n'); + } +} + +int main(int ac, char *av[]) { + char *fmt = "%y"; /* default stat is mtime */ + char *timefmt = "%s"; /* default time fmt is unix ts */ + int errflg = 0; + int c; + int uselstat = 0; + int zeroterm = 0; + + while ((c = getopt(ac, av, "lf:t:0")) != -1) { + switch(c) { + case 'f': + fmt = optarg; + break; + case 't': + timefmt = optarg; + break; + case ':': /* -f or -t without operand */ + fprintf(stderr, + "Option -%c requires an operand\n", optopt); + errflg++; + break; + case 'z': + zeroterm |= 2; + case '0': + zeroterm |= 1; + break; + case 'l': + uselstat = 1; + break; + case '?': + fprintf(stderr, + "Unrecognized option: '-%c'\n", optopt); + errflg++; + } + } + if (errflg) { + fprintf(stderr, "zpm-stat [-f ] [-t ]\n"); + exit(2); + } + for ( ; optind < ac; optind++) { + struct stat buf; + if (uselstat) { + lstat(av[optind], &buf); + } else { + stat(av[optind], &buf); + } + stat_one(fmt, timefmt, zeroterm, av[optind], &buf); + } + return 0; +}