diff options
Diffstat (limited to 'Src/Modules/stat.c')
-rw-r--r-- | Src/Modules/stat.c | 148 |
1 files changed, 117 insertions, 31 deletions
diff --git a/Src/Modules/stat.c b/Src/Modules/stat.c index 09245b52f..d0f80829c 100644 --- a/Src/Modules/stat.c +++ b/Src/Modules/stat.c @@ -34,18 +34,21 @@ enum statnum { ST_DEV, ST_INO, ST_MODE, ST_NLINK, ST_UID, ST_GID, ST_RDEV, ST_SIZE, ST_ATIM, ST_MTIM, ST_CTIM, ST_BLKSIZE, ST_BLOCKS, ST_READLINK, ST_COUNT }; enum statflags { STF_NAME = 1, STF_FILE = 2, STF_STRING = 4, STF_RAW = 8, - STF_PICK = 16, STF_ARRAY = 32, STF_GMT = 64 }; + STF_PICK = 16, STF_ARRAY = 32, STF_GMT = 64, + STF_HASH = 128, STF_OCTAL = 256 }; static char *statelts[] = { "device", "inode", "mode", "nlink", "uid", "gid", "rdev", "size", "atime", "mtime", "ctime", "blksize", "blocks", "link", NULL }; +#define HNAMEKEY "name" /**/ static void statmodeprint(mode_t mode, char *outbuf, int flags) { if (flags & STF_RAW) { - sprintf(outbuf, "%lu", (unsigned long)mode); + sprintf(outbuf, (flags & STF_OCTAL) ? "0%lo" : "%lu", + (unsigned long)mode); if (flags & STF_STRING) strcat(outbuf, " ("); } @@ -64,6 +67,8 @@ statmodeprint(mode_t mode, char *outbuf, int flags) *pm = 'c'; else if (S_ISDIR(mode)) *pm = 'd'; + else if (S_ISDOOR(mode)) + *pm = 'D'; else if (S_ISFIFO(mode)) *pm = 'p'; else if (S_ISLNK(mode)) @@ -85,6 +90,7 @@ statmodeprint(mode_t mode, char *outbuf, int flags) for (i = 1; i <= 9; i++) pm[i] = (mode & *mfp++) ? modes[i] : '-'; + pm[10] = '\0'; if (mode & S_ISUID) pm[3] = (mode & S_IXUSR) ? 's' : 'S'; @@ -210,7 +216,13 @@ statprint(struct stat *sbuf, char *outbuf, char *fname, int iwhich, int flags) break; case ST_INO: +#ifdef INO_T_IS_64_BIT + convbase(optr, sbuf->st_ino, 0); +#else + DPUTS(sizeof(sbuf->st_ino) > 4, + "Shell compiled with wrong ino_t size"); statulprint((unsigned long)sbuf->st_ino, optr); +#endif break; case ST_MODE: @@ -234,7 +246,13 @@ statprint(struct stat *sbuf, char *outbuf, char *fname, int iwhich, int flags) break; case ST_SIZE: +#ifdef OFF_T_IS_64_BIT + convbase(optr, sbuf->st_size, 0); +#else + DPUTS(sizeof(sbuf->st_size) > 4, + "Shell compiled with wrong off_t size"); statulprint((unsigned long)sbuf->st_size, optr); +#endif break; case ST_ATIM: @@ -286,6 +304,8 @@ statprint(struct stat *sbuf, char *outbuf, char *fname, int iwhich, int flags) * file names are returned as a separate array element, type names as * prefix to element. Note the formatting deliberately contains * fewer frills when -A is used. + * -H hash: as for -A array, but returns a hash with the keys being those + * from stat -l * -F fmt: specify a $TIME-like format for printing times; the default * is the (CTIME-like) "%a %b %e %k:%M:%S". This option implies * -s as it is not useful for numerical times. @@ -304,6 +324,7 @@ static int bin_stat(char *name, char **args, char *ops, int func) { char **aptr, *arrnam = NULL, **array = NULL, **arrptr = NULL; + char *hashnam = NULL, **hash = NULL, **hashptr = NULL; int len, iwhich = -1, ret = 0, flags = 0, arrsize = 0, fd = 0; struct stat statbuf; int found = 0, nargs; @@ -327,10 +348,10 @@ bin_stat(char *name, char **args, char *ops, int func) iwhich = aptr - statelts; } if (found > 1) { - zerrnam(name, "%s: ambiguous stat element", arg, 0); + zwarnnam(name, "%s: ambiguous stat element", arg, 0); return 1; } else if (found == 0) { - zerrnam(name, "%s: no such stat element", arg, 0); + zwarnnam(name, "%s: no such stat element", arg, 0); return 1; } /* if name of link requested, turn on lstat */ @@ -339,30 +360,40 @@ bin_stat(char *name, char **args, char *ops, int func) flags |= STF_PICK; } else { for (; *arg; arg++) { - if (strchr("glLnNrstT", *arg)) - ops[*arg] = 1; + if (strchr("glLnNorstT", *arg)) + ops[STOUC(*arg)] = 1; else if (*arg == 'A') { if (arg[1]) { arrnam = arg+1; } else if (!(arrnam = *++args)) { - zerrnam(name, "missing parameter name\n", + zwarnnam(name, "missing parameter name", NULL, 0); return 1; } flags |= STF_ARRAY; break; + } else if (*arg == 'H') { + if (arg[1]) { + hashnam = arg+1; + } else if (!(hashnam = *++args)) { + zwarnnam(name, "missing parameter name", + NULL, 0); + return 1; + } + flags |= STF_HASH; + break; } else if (*arg == 'f') { char *sfd; ops['f'] = 1; if (arg[1]) { sfd = arg+1; } else if (!(sfd = *++args)) { - zerrnam(name, "missing file descriptor\n", NULL, 0); + zwarnnam(name, "missing file descriptor", NULL, 0); return 1; } fd = zstrtol(sfd, &sfd, 10); if (*sfd) { - zerrnam(name, "bad file descriptor\n", NULL, 0); + zwarnnam(name, "bad file descriptor", NULL, 0); return 1; } break; @@ -370,20 +401,29 @@ bin_stat(char *name, char **args, char *ops, int func) if (arg[1]) { timefmt = arg+1; } else if (!(timefmt = *++args)) { - zerrnam(name, "missing time format\n", NULL, 0); + zwarnnam(name, "missing time format", NULL, 0); return 1; } /* force string format in order to use time format */ ops['s'] = 1; break; } else { - zerrnam(name, "bad option: -%c", NULL, *arg); + zwarnnam(name, "bad option: -%c", NULL, *arg); return 1; } } } } + if ((flags & STF_ARRAY) && (flags & STF_HASH)) { + /* We don't implement setting multiple variables at once */ + zwarnnam(name, "both array and hash requested", NULL, 0); + return 1; + /* Alternate method would be to make -H blank arrnam etc etc * + * and so get 'silent loss' of earlier choice, which would * + * be similar to stat -A foo -A bar filename */ + } + if (ops['l']) { /* list types and return: can also list to array */ if (arrnam) { @@ -423,18 +463,22 @@ bin_stat(char *name, char **args, char *ops, int func) for (aptr = args; *aptr; aptr++) nargs++; + if (ops['g']) { + flags |= STF_GMT; + ops['s'] = 1; + } if (ops['s'] || ops['r']) flags |= STF_STRING; if (ops['r'] || !ops['s']) flags |= STF_RAW; if (ops['n']) flags |= STF_FILE; + if (ops['o']) + flags |= STF_OCTAL; if (ops['t']) flags |= STF_NAME; - if (ops['g']) - flags |= STF_GMT; - if (!arrnam) { + if (!(arrnam || hashnam)) { if (nargs > 1) flags |= STF_FILE; if (!(flags & STF_PICK)) @@ -443,9 +487,20 @@ bin_stat(char *name, char **args, char *ops, int func) if (ops['N'] || ops['f']) flags &= ~STF_FILE; - if (ops['T']) + if (ops['T'] || ops['H']) flags &= ~STF_NAME; + if (hashnam) { + if (nargs > 1) { + zwarnnam(name, "only one file allowed with -H", NULL, 0); + return 1; + } + arrsize = (flags & STF_PICK) ? 1 : ST_COUNT; + if (flags & STF_FILE) + arrsize++; + hashptr = hash = (char **)zcalloc((arrsize+1)*2*sizeof(char *)); + } + if (arrnam) { arrsize = (flags & STF_PICK) ? 1 : ST_COUNT; if (flags & STF_FILE) @@ -469,16 +524,24 @@ bin_stat(char *name, char **args, char *ops, int func) continue; } - if (flags & STF_FILE) + if (flags & STF_FILE) { if (arrnam) *arrptr++ = ztrdup(*args); - else + else if (hashnam) { + *hashptr++ = ztrdup(HNAMEKEY); + *hashptr++ = ztrdup(*args); + } else printf("%s%s", *args, (flags & STF_PICK) ? " " : ":\n"); + } if (iwhich > -1) { statprint(&statbuf, outbuf, *args, iwhich, flags); if (arrnam) *arrptr++ = ztrdup(outbuf); - else + else if (hashnam) { + /* STF_NAME explicitly turned off for ops['H'] above */ + *hashptr++ = ztrdup(statelts[iwhich]); + *hashptr++ = ztrdup(outbuf); + } else printf("%s\n", outbuf); } else { int i; @@ -486,27 +549,40 @@ bin_stat(char *name, char **args, char *ops, int func) statprint(&statbuf, outbuf, *args, i, flags); if (arrnam) *arrptr++= ztrdup(outbuf); - else + else if (hashnam) { + /* STF_NAME explicitly turned off for ops['H'] above */ + *hashptr++ = ztrdup(statelts[i]); + *hashptr++ = ztrdup(outbuf); + } else printf("%s\n", outbuf); } } if (ops['f']) break; - if (!arrnam && args[1] && !(flags & STF_PICK)) + if (!arrnam && !hashnam && args[1] && !(flags & STF_PICK)) putchar('\n'); } - if (arrnam) - if (ret) { - for (aptr = array; *aptr; aptr++) - zsfree(*aptr); - zfree(array, arrsize+1); - } else { + if (arrnam) { + if (ret) + freearray(array); + else { setaparam(arrnam, array); if (errflag) return 1; } + } + + if (hashnam) { + if (ret) + freearray(hash); + else { + sethparam(hashnam, hash); + if (errflag) + return 1; + } + } return ret; } @@ -517,19 +593,29 @@ static struct builtin bintab[] = { /**/ int -boot_stat(Module m) +setup_(Module m) { - return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); + return 0; } -#ifdef MODULE +/**/ +int +boot_(Module m) +{ + return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); +} /**/ int -cleanup_stat(Module m) +cleanup_(Module m) { deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); return 0; } -#endif +/**/ +int +finish_(Module m) +{ + return 0; +} |