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:
parent
265f55fd58
commit
b4a2b47b64
3 changed files with 144 additions and 39 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue