usr.bin/stat Update

Change-Id: I029160c73baab1b3465bc5397a36c55886db225b
This commit is contained in:
Lionel Sambuc 2013-04-19 13:16:51 +02:00
parent f84d21b043
commit 474b24f91c
3 changed files with 131 additions and 35 deletions

View file

@ -228,7 +228,7 @@
2012/10/17 12:00:00,usr.bin/soelim 2012/10/17 12:00:00,usr.bin/soelim
2012/10/17 12:00:00,usr.bin/sort 2012/10/17 12:00:00,usr.bin/sort
2012/10/17 12:00:00,usr.bin/split 2012/10/17 12:00:00,usr.bin/split
2011/01/15 22:54:10,usr.bin/stat 2012/10/17 12:00:00,usr.bin/stat
2012/02/10 16:16:12,usr.bin/su 2012/02/10 16:16:12,usr.bin/su
2013/10/06 12:00:00,usr.bin/tee 2013/10/06 12:00:00,usr.bin/tee
2012/06/01 12:08:40,usr.bin/tic 2012/06/01 12:08:40,usr.bin/tic

View file

@ -1,6 +1,6 @@
.\" $NetBSD: stat.1,v 1.28 2010/04/05 21:25:01 joerg Exp $ .\" $NetBSD: stat.1,v 1.34 2011/09/22 20:23:55 apb Exp $
.\" .\"
.\" Copyright (c) 2002-2005 The NetBSD Foundation, Inc. .\" Copyright (c) 2002-2011 The NetBSD Foundation, Inc.
.\" All rights reserved. .\" All rights reserved.
.\" .\"
.\" This code is derived from software contributed to The NetBSD Foundation .\" This code is derived from software contributed to The NetBSD Foundation
@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE. .\" POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.Dd November 7, 2008 .Dd September 22, 2011
.Dt STAT 1 .Dt STAT 1
.Os .Os
.Sh NAME .Sh NAME
@ -47,7 +47,7 @@
.Op Fl t Ar timefmt .Op Fl t Ar timefmt
.Op Ar .Op Ar
.Nm readlink .Nm readlink
.Op Fl fn .Op Fl fnqsv
.Op Ar .Op Ar
.Sh DESCRIPTION .Sh DESCRIPTION
The The
@ -165,11 +165,16 @@ epoch, etc.)
Display information in Display information in
.Dq shell output , .Dq shell output ,
suitable for initializing variables. suitable for initializing variables.
When run as
.Nm readlink ,
suppress error messages.
.It Fl t Ar timefmt .It Fl t Ar timefmt
Display timestamps using the specified format. Display timestamps using the specified format.
This format is This format is
passed directly to passed directly to
.Xr strftime 3 . .Xr strftime 3 .
.It Fl v
Turn off quiet mode.
.It Fl x .It Fl x
Display information in a more verbose way as known from some Linux Display information in a more verbose way as known from some Linux
distributions. distributions.
@ -197,9 +202,12 @@ examined for the following:
Any of the following optional flags: Any of the following optional flags:
.Bl -tag -width Ds .Bl -tag -width Ds
.It Cm # .It Cm #
Selects an alternate output form for octal and hexadecimal output. Selects an alternate output form for string, octal and hexadecimal output.
Non-zero octal output will have a leading zero, and non-zero String output will be encoded in
hexadecimal output will have .Xr vis 3
style.
Non-zero octal output will have a leading zero.
Non-zero hexadecimal output will have
.Dq 0x .Dq 0x
prepended to it. prepended to it.
.It Cm + .It Cm +
@ -430,7 +438,7 @@ is given.
The target of a symbolic link. The target of a symbolic link.
.It Cm Z .It Cm Z
Expands to Expands to
.Dq major,minor .Dq Ar major , Ns Ar minor
from the rdev field for character or block from the rdev field for character or block
special devices and gives size output for all others. special devices and gives size output for all others.
.El .El
@ -468,6 +476,41 @@ If no options are specified, the default format is
0 78852 -rw-r--r-- 1 root wheel 0 0 "Jul 8 10:26:03 2004" "Jul 8 10:26:03 2004" "Jul 8 10:28:13 2004" "Jan 1 09:00:00 1970" 16384 0 0 /tmp/bar 0 78852 -rw-r--r-- 1 root wheel 0 0 "Jul 8 10:26:03 2004" "Jul 8 10:26:03 2004" "Jul 8 10:28:13 2004" "Jan 1 09:00:00 1970" 16384 0 0 /tmp/bar
.Ed .Ed
.Pp .Pp
This example produces output very similar to that from
.Ic find ... -ls
(except that
.Xr find 1
displays the time in a different format, and
.Xr find 1
sometimes adds one or more spaces after the comma in
.Dq Ar major , Ns Ar minor
for device nodes):
.Bd -literal -offset indent
\*[Gt] stat -f "%7i %6b %-11Sp %3l %-17Su %-17Sg %9Z %Sm %N%SY" /tmp/bar
78852 0 -rw-r--r-- 1 root wheel 0 Jul 8 10:26:03 2004 /tmp/bar
\*[Gt] find /tmp/bar -ls -exit
78852 0 -rw-r--r-- 1 root wheel 0 Jul 8 2004 /tmp/bar
.Ed
.Pp
This example produces output very similar to that from
.Ic ls -lTd
(except that
.Xr ls 1
adjusts the column spacing differently when listing multiple files,
and
.Xr ls 1
adds at least one space after the comma in
.Dq Ar major , Ns Ar minor
for device nodes):
.Bd -literal -offset indent
\*[Gt] stat -f "%-11Sp %l %Su %Sg %Z %Sm %N%SY" /tmp/bar
-rw-r--r-- 1 root wheel 0 Jul 8 10:26:03 2004 /tmp/bar
\*[Gt] ls -lTd /tmp/bar
-rw-r--r-- 1 root wheel 0 Jul 8 10:26:03 2004 /tmp/bar
.Ed
.Pp
Given a symbolic link Given a symbolic link
.Dq foo .Dq foo
that points from that points from
@ -542,6 +585,18 @@ Apr 25 11:47:00 2002 /tmp/blah
Apr 25 10:36:34 2002 /tmp/bar Apr 25 10:36:34 2002 /tmp/bar
Apr 24 16:47:35 2002 /tmp/foo Apr 24 16:47:35 2002 /tmp/foo
.Ed .Ed
.Pp
User names, group names, and file names that contain spaces
or other special characters may be encoded in
.Xr vis 3
style, using the
.Cm \&#
modifier:
.Bd -literal -offset indent
\*[Gt] ln -s 'target with spaces' 'link with spaces'
\*[Gt] stat -f "%#N%#SY" 'link with spaces'
link\eswith\esspaces -\*[Gt] target\eswith\esspaces
.Ed
.Sh SEE ALSO .Sh SEE ALSO
.Xr basename 1 , .Xr basename 1 ,
.Xr dirname 1 , .Xr dirname 1 ,

View file

@ -1,7 +1,7 @@
/* $NetBSD: stat.c,v 1.33 2011/01/15 22:54:10 njoly Exp $ */ /* $NetBSD: stat.c,v 1.36 2011/09/22 20:23:56 apb Exp $ */
/* /*
* Copyright (c) 2002 The NetBSD Foundation, Inc. * Copyright (c) 2002-2011 The NetBSD Foundation, Inc.
* All rights reserved. * All rights reserved.
* *
* This code is derived from software contributed to The NetBSD Foundation * This code is derived from software contributed to The NetBSD Foundation
@ -35,7 +35,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#if !defined(lint) #if !defined(lint)
__RCSID("$NetBSD: stat.c,v 1.33 2011/01/15 22:54:10 njoly Exp $"); __RCSID("$NetBSD: stat.c,v 1.36 2011/09/22 20:23:56 apb Exp $");
#endif #endif
#if ! HAVE_NBTOOL_CONFIG_H #if ! HAVE_NBTOOL_CONFIG_H
@ -46,7 +46,7 @@ __RCSID("$NetBSD: stat.c,v 1.33 2011/01/15 22:54:10 njoly Exp $");
#define HAVE_STRUCT_STAT_ST_MTIMENSEC 1 #define HAVE_STRUCT_STAT_ST_MTIMENSEC 1
#ifdef __minix #ifdef __minix
/* Not supported in Minix. */ /* Not supported in Minix. */
#define HAVE_DEVNAME 0 #define HAVE_DEVNAME 0
#else /* __minix */ #else /* __minix */
#define HAVE_DEVNAME 1 #define HAVE_DEVNAME 1
#endif /* __minx */ #endif /* __minx */
@ -66,6 +66,7 @@ __RCSID("$NetBSD: stat.c,v 1.33 2011/01/15 22:54:10 njoly Exp $");
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <vis.h>
#if HAVE_STRUCT_STAT_ST_FLAGS #if HAVE_STRUCT_STAT_ST_FLAGS
#define DEF_F "%#Xf " #define DEF_F "%#Xf "
@ -179,18 +180,18 @@ __RCSID("$NetBSD: stat.c,v 1.33 2011/01/15 22:54:10 njoly Exp $");
#define SHOW_filename 'N' #define SHOW_filename 'N'
#define SHOW_sizerdev 'Z' #define SHOW_sizerdev 'Z'
void usage(const char *); static void usage(const char *) __dead;
void output(const struct stat *, const char *, static void output(const struct stat *, const char *,
const char *, int, int); const char *, int, int, int);
int format1(const struct stat *, /* stat info */ static int format1(const struct stat *, /* stat info */
const char *, /* the file name */ const char *, /* the file name */
const char *, int, /* the format string itself */ const char *, int, /* the format string itself */
char *, size_t, /* a place to put the output */ char *, size_t, /* a place to put the output */
int, int, int, int, /* the parsed format */ int, int, int, int, /* the parsed format */
int, int); int, int, int);
const char *timefmt; static const char *timefmt;
int linkfail; static int linkfail;
#define addchar(s, c, nl) \ #define addchar(s, c, nl) \
do { \ do { \
@ -216,10 +217,12 @@ main(int argc, char *argv[])
statfmt = NULL; statfmt = NULL;
timefmt = NULL; timefmt = NULL;
setprogname(argv[0]);
if (strcmp(getprogname(), "readlink") == 0) { if (strcmp(getprogname(), "readlink") == 0) {
am_readlink = 1; am_readlink = 1;
options = "fn"; options = "fnqsv";
synopsis = "[-fn] [file ...]"; synopsis = "[-fnqsv] [file ...]";
statfmt = "%Y"; statfmt = "%Y";
fmtchar = 'f'; fmtchar = 'f';
quiet = 1; quiet = 1;
@ -252,6 +255,11 @@ main(int argc, char *argv[])
case 'l': case 'l':
case 'r': case 'r':
case 's': case 's':
if (am_readlink) {
quiet = 1;
break;
}
/*FALLTHROUGH*/
case 'x': case 'x':
if (fmtchar != 0) if (fmtchar != 0)
errx(1, "can't use format '%c' with '%c'", errx(1, "can't use format '%c' with '%c'",
@ -261,6 +269,9 @@ main(int argc, char *argv[])
case 't': case 't':
timefmt = optarg; timefmt = optarg;
break; break;
case 'v':
quiet = 0;
break;
default: default:
usage(synopsis); usage(synopsis);
} }
@ -334,7 +345,7 @@ main(int argc, char *argv[])
usestat ? "stat" : "lstat"); usestat ? "stat" : "lstat");
} }
else else
output(&st, argv[0], statfmt, fn, nonl); output(&st, argv[0], statfmt, fn, nonl, quiet);
argv++; argv++;
argc--; argc--;
@ -344,7 +355,7 @@ main(int argc, char *argv[])
return (am_readlink ? linkfail : errs); return (am_readlink ? linkfail : errs);
} }
void static void
usage(const char *synopsis) usage(const char *synopsis)
{ {
@ -355,12 +366,17 @@ usage(const char *synopsis)
/* /*
* Parses a format string. * Parses a format string.
*/ */
void static void
output(const struct stat *st, const char *file, output(const struct stat *st, const char *file,
const char *statfmt, int fn, int nonl) const char *statfmt, int fn, int nonl, int quiet)
{ {
int flags, size, prec, ofmt, hilo, what; int flags, size, prec, ofmt, hilo, what;
char buf[PATH_MAX + 4 + 1]; /*
* buf size is enough for an item of length PATH_MAX,
* multiplied by 4 for vis encoding, plus 4 for symlink
* " -> " prefix, plus 1 for \0 terminator.
*/
char buf[PATH_MAX * 4 + 4 + 1];
const char *subfmt; const char *subfmt;
int nl, t, i; int nl, t, i;
@ -431,6 +447,7 @@ output(const struct stat *st, const char *file,
* the leading " -> " if STRING is explicitly specified. The * the leading " -> " if STRING is explicitly specified. The
* sizerdev datum will generate rdev output for character or * sizerdev datum will generate rdev output for character or
* block devices, and size output for all others. * block devices, and size output for all others.
* For STRING output, the # format requests vis encoding.
*/ */
flags = 0; flags = 0;
do { do {
@ -528,7 +545,7 @@ output(const struct stat *st, const char *file,
file, file,
subfmt, statfmt - subfmt, subfmt, statfmt - subfmt,
buf, sizeof(buf), buf, sizeof(buf),
flags, size, prec, ofmt, hilo, what); flags, size, prec, ofmt, hilo, what, quiet);
for (i = 0; i < t && i < (int)(sizeof(buf) - 1); i++) for (i = 0; i < t && i < (int)(sizeof(buf) - 1); i++)
addchar(stdout, buf[i], &nl); addchar(stdout, buf[i], &nl);
@ -548,24 +565,29 @@ output(const struct stat *st, const char *file,
/* /*
* Arranges output according to a single parsed format substring. * Arranges output according to a single parsed format substring.
*/ */
int static int
format1(const struct stat *st, format1(const struct stat *st,
const char *file, const char *file,
const char *fmt, int flen, const char *fmt, int flen,
char *buf, size_t blen, char *buf, size_t blen,
int flags, int size, int prec, int ofmt, int flags, int size, int prec, int ofmt,
int hilo, int what) int hilo, int what, int quiet)
{ {
u_int64_t data; u_int64_t data;
char *stmp, lfmt[24], tmp[20]; char *stmp, lfmt[24], tmp[20];
const char *sdata; const char *sdata;
char smode[12], sid[12], path[PATH_MAX + 4]; char smode[12], sid[12], path[PATH_MAX + 4], visbuf[PATH_MAX * 4 + 4];
struct passwd *pw; struct passwd *pw;
struct group *gr; struct group *gr;
struct tm *tm; struct tm *tm;
time_t secs; time_t secs;
long nsecs; long nsecs;
int l, small, formats, gottime, shift; int l;
int formats; /* bitmap of allowed formats for this datum */
int small; /* true if datum is a small integer */
int gottime; /* true if secs and nsecs are valid */
int shift; /* powers of 2 to scale numbers before printing */
size_t prefixlen; /* length of constant prefix for string data */
formats = 0; formats = 0;
small = 0; small = 0;
@ -573,6 +595,7 @@ format1(const struct stat *st,
secs = 0; secs = 0;
nsecs = 0; nsecs = 0;
shift = 0; shift = 0;
prefixlen = 0;
/* /*
* First, pick out the data and tweak it based on hilo or * First, pick out the data and tweak it based on hilo or
@ -802,11 +825,14 @@ format1(const struct stat *st,
} else { } else {
snprintf(path, sizeof(path), " -> "); snprintf(path, sizeof(path), " -> ");
if (realpath(file, path + 4) == NULL) { if (realpath(file, path + 4) == NULL) {
if (!quiet)
warn("realpath `%s'", file);
linkfail = 1; linkfail = 1;
l = 0; l = 0;
path[0] = '\0'; path[0] = '\0';
} }
sdata = path + (ofmt == FMTF_STRING ? 0 : 4); sdata = path + (ofmt == FMTF_STRING ? 0 : 4);
prefixlen = (ofmt == FMTF_STRING ? 4 : 0);
} }
formats = FMTF_STRING; formats = FMTF_STRING;
@ -820,12 +846,15 @@ format1(const struct stat *st,
snprintf(path, sizeof(path), " -> "); snprintf(path, sizeof(path), " -> ");
l = readlink(file, path + 4, sizeof(path) - 4 - 1); l = readlink(file, path + 4, sizeof(path) - 4 - 1);
if (l == -1) { if (l == -1) {
if (!quiet)
warn("readlink `%s'", file);
linkfail = 1; linkfail = 1;
l = 0; l = 0;
path[0] = '\0'; path[0] = '\0';
} }
path[l + 4] = '\0'; path[l + 4] = '\0';
sdata = path + (ofmt == FMTF_STRING ? 0 : 4); sdata = path + (ofmt == FMTF_STRING ? 0 : 4);
prefixlen = (ofmt == FMTF_STRING ? 4 : 0);
} }
else { else {
linkfail = 1; linkfail = 1;
@ -938,13 +967,13 @@ format1(const struct stat *st,
fmt, flen, fmt, flen,
majdev, sizeof(majdev), majdev, sizeof(majdev),
flags, size, prec, flags, size, prec,
ofmt, HIGH_PIECE, SHOW_st_rdev); ofmt, HIGH_PIECE, SHOW_st_rdev, quiet);
l2 = format1(st, l2 = format1(st,
file, file,
fmt, flen, fmt, flen,
mindev, sizeof(mindev), mindev, sizeof(mindev),
flags, size, prec, flags, size, prec,
ofmt, LOW_PIECE, SHOW_st_rdev); ofmt, LOW_PIECE, SHOW_st_rdev, quiet);
return (snprintf(buf, blen, "%.*s,%.*s", return (snprintf(buf, blen, "%.*s,%.*s",
l1, majdev, l2, mindev)); l1, majdev, l2, mindev));
} }
@ -954,7 +983,7 @@ format1(const struct stat *st,
fmt, flen, fmt, flen,
buf, blen, buf, blen,
flags, size, prec, flags, size, prec,
ofmt, 0, SHOW_st_size)); ofmt, 0, SHOW_st_size, quiet));
} }
/*NOTREACHED*/ /*NOTREACHED*/
default: default:
@ -968,6 +997,18 @@ format1(const struct stat *st,
if (hilo != 0 || (ofmt & formats) == 0) if (hilo != 0 || (ofmt & formats) == 0)
errx(1, "%.*s: bad format", (int)flen, fmt); errx(1, "%.*s: bad format", (int)flen, fmt);
/*
* FLAG_POUND with FMTF_STRING means use vis(3) encoding.
* First prefixlen chars are not encoded.
*/
if ((flags & FLAG_POUND) != 0 && ofmt == FMTF_STRING) {
flags &= !FLAG_POUND;
strncpy(visbuf, sdata, prefixlen);
strnvis(visbuf + prefixlen, sizeof(visbuf) - prefixlen,
sdata + prefixlen, VIS_WHITE | VIS_OCTAL | VIS_CSTYLE);
sdata = visbuf;
}
/* /*
* Assemble the format string for passing to printf(3). * Assemble the format string for passing to printf(3).
*/ */