1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-11-30 03:50:56 +01:00

stat -o shows file modes in octal

This commit is contained in:
Peter Stephenson 2000-04-07 20:07:10 +00:00
parent 265f55fd58
commit b4a2b47b64
3 changed files with 144 additions and 39 deletions

View file

@ -1,3 +1,8 @@
2000-04-07 Peter Stephenson <pws@pwstephenson.fsnet.co.uk>
* 10584: Doc/Zsh/mod_stat.yo, Src/Modules/stat.c: -o shows
numeric file modes in octal.
2000-04-07 Bart Schaefer <schaefer@zsh.org>
* 10582: Src/exec.c: Apply STTY only to process group leaders.

View file

@ -1,12 +1,14 @@
texinode(The stat Module)(The zle Module)(The sched Module)(Zsh Modules)
sect(The stat Module)
The tt(stat) module makes available one builtin command:
COMMENT(!MOD!zsh/stat
A builtin command interface to the tt(stat) system call.
!MOD!)
The tt(zsh/stat) module makes available one builtin command:
startitem()
findex(stat)
cindex(files, listing)
cindex(files, examining)
item(tt(stat) [ tt(-gnNlLtTrs) ] [ tt(-f) var(fd) ] [ tt(-A) var(array) ] \
item(tt(stat) [ tt(-gnNolLtTrs) ] [ tt(-f) var(fd) ] \
[ tt(-H) var(hash) ] [ tt(-A) var(array) ] \
[ tt(-F) var(fmt) ] [ tt(PLUS())var(element) ] [ var(file) ... ])(
The command acts as a front end to the tt(stat) system call (see
manref(stat)(2)).
@ -84,13 +86,18 @@ item(tt(-A) var(array))(
Instead of displaying the results on standard
output, assign them to an var(array), one tt(struct stat) element per array
element for each file in order. In this case neither the name
of the element nor the name of the files is provided unless the
tt(-t) or tt(-n) options are provided, respectively. In the
former case the element name appears as a prefix to the
appropriate array element and in the latter case the file name
of the element nor the name of the files appears in var(array) unless the
tt(-t) or tt(-n) options were given, respectively. If tt(-t) is given,
the element name appears as a prefix to the
appropriate array element; if tt(-n) is given, the file name
appears as a separate array element preceding all the others.
Other formatting options are respected.
)
item(tt(-H) var(hash))(
Similar to tt(-A), but instead assign the values to var(hash). The keys
are the elements listed above. If the tt(-n) option is provided then the
name of the file is included in the hash with key tt(name).
)
item(tt(-f) var(fd))(
Use the file on file descriptor var(fd) instead of
named files; no list of file names is allowed in this case.
@ -122,6 +129,13 @@ than one file in the list.
item(tt(-N))(
Never show the names of files.
)
item(tt(-o))(
If a raw file mode is printed, show it in octal, which is more useful for
human consumption than the default of decimal. A leading zero will be
printed in this case. Note that this does not affect whether a raw or
formatted file mode is shown, which is controlled by the tt(-r) and tt(-s)
options, nor whether a mode is shown at all.
)
item(tt(-r))(
Print raw data (the default format) alongside string
data (the tt(-s) format); the string data appears in parentheses

View file

@ -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 0;
}
/**/
int
boot_(Module m)
{
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
}
#ifdef MODULE
/**/
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;
}