Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 11 Jan 2011 20:08:34 +0000 (UTC)
From:      Doug Barton <dougb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r217283 - stable/8/usr.bin/stat
Message-ID:  <201101112008.p0BK8YYo033829@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: dougb
Date: Tue Jan 11 20:08:34 2011
New Revision: 217283
URL: http://svn.freebsd.org/changeset/base/217283

Log:
  For stat.c
  ==========
  
  MFC r216196:
  
  Bring in the change from NetBSD 1.18:
  
  "If using stat (the -L flag) and it fails, fall back to lstat().  It
  may be the case that we're examining a broken symlink, and anything is
  better than nothing."
  
  The changes in 1.14 through 1.17 were not relevant to us.
  
  Obtained from:	atatat@NetBSD.org
  
  MFC r216202:
  
  Bring in the change from NetBSD 1.22:
  
  "Fix a trivial truncation case, and eliminate a corner case that might
  print a nul character."
  
  I am purposely bypassing the following versions:
  1.19	A build infrastructure change that does not apply to us
  1.20	A feature I am not interested in, but don't object if someone else
  	wants to pick it up
  1.21	A build infrastructure change that does not apply to us
  
  Obtained from:	atatat@NetBSD.org
  
  MFC r216203:
  
  Bring in a new feature, adding a -f option to readlink to print the path
  of the target, similar to realpath(1). See the discussion at:
  http://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=34662
  
  This brings in the following changes:
  1.24
  "PR/34662: martijnb at atlas dot ipv6 dot stack dot nl: readlink doesn't
  grok -f, and there's no alternative (+fix)
  
  Patch applied with minor tweak (%y -> %R, as it was already taken) plus
  some nits from myself. Thanks!"
  
  Obtained from:	elad@NetBSD.org
  
  1.25
  "Fix a segfault when doing 'stat -f %R' on the stdin file handle, instead
  fake the filename '(stdin)' like the %N format."
  
  Obtained from:	mlelstv@NetBSD.org
  
  1.27
  "The ofmt variable is actually a bit mask (not the character that was
  in the format string) so that we can "or" it with the bits in the
  formats variable.  This fixes the missing " -> " in front of the real
  path (when you use %SR).
  
  Also, the ?: needs another space."
  
  Obtained from:	atatat@NetBSD.org
  
  I am purposely omitting the following changes:
  1.23	A humanize_number(3) clone that should better be implemented by
  	actually using humanize_number(3)
  1.26	This is the removal of license clause 3 and 4, already handled
  	by imp in r203971
  
  MFC 216205:
  
  Bring in the update from NetBSD 1.28:
  
  "Fix WARNS=4 issues (-Wcast-qual -Wsign-compare)"
  
  Because of code differences I had to hand-apply parts of the patch,
  so responsibility for errors goes to me.
  
  Obtained from:	lukem@NetBSD.org
  
  MFC 216206:	[ Also applies to Makefile ]
  
  Fix an "unused variable" error that gets us all the way to WARNS=6
  
  MFC 216207:
  
  Bring in the following changes from NetBSD. See the discussion at:
  http://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=44128
  
  1.29
  "Don't printf time_t with %d; fixes PR 44128 from yamt. With this change it
  successfully prints mtimes after 2038."
  
  1.30
  "Improve previous with comments."
  
  Obtained from:	dholland@NetBSD.org (both)
  
  MFC 216343:
  
  Bring in the change from OpenBSD's 1.14:
  
  "synchronize synopsis and usage; "-l", "-r", "-s" and "-x" are mutually
  exclusive; while here, slightly improve spacing in the source code
  so it fits on a 80-column display again.
  
  diff greatly improved by martynas@"
  
  Obtained from:	sobrado@OpenBSD.org
  
  MFC 216512:
  
  Bring in the relevant changes from NetBSD's 1.31:
  
  "Use strlcpy, not strncpy, when the desired semantics are strlcpy's
  rather than strncpy's."
  
  Note: NetBSD's 1.32 is their adoption of our r216206
  
  Obtained from:	dholland@NetBSD.org
  
  For stat.1
  ==========
  
  MFC 216197:
  
  Add my own documentation for the change in our r216196, aka NetBSD's 1.18
  For -L if stat(2) fails, fall back to lstat(2).
  
  .Dd purposely not bumped because more changes are coming.
  
  MFC 216204:
  
  Bring in the update from NetBSD 1.19, the documentation of readlink -f
  
  "PR/34662: martijnb at atlas dot ipv6 dot stack dot nl: readlink doesn't
  grok -f, and there's no alternative (+fix)
  
  Patch applied with minor tweak (%y -> %R, as it was already taken) plus
  some nits from myself. Thanks!"
  
  Obtained from:	elad@NetBSD.org
  
  MFC 216209:
  
  Bring in the change from NetBSD 1.12:
  
  "document default format."
  
  Obtained from:	yamt@NetBSD.org
  
  MFC 216213:
  
  Bring in the changes from NetBSD 1.13 that we did not already have, with
  some differences.
  
  "Sort options. Use more mdoc macros. Some nit fixes. Bump date."
  
  Obtained from:	wiz@NetBSD.org
  
  MFC 216215:
  
  Bring in the changes from NetBSD 1.16 that we did not already have.
  
  "Some fixes from jmc@openbsd."
  
  Obtained from:	wiz@NetBSD.org
  
  MFC 216216:
  
  Bring in the change from NetBSD 1.20:
  
  "Make sentence easier to parse. From jsing@openbsd via jmc@openbsd."
  
  Obtained from:	wiz@NetBSD.org
  
  MFC 216218:
  
  Bring in the following changes from NetBSD:
  
  1.21
  "Document the flags displayed by the default format, and mention their short
  names. From espie@openbsd via jmc@openbsd."
  
  1.24
  "Fix three variable names.
  From Todd T. Fries via Jason McIntyre."
  
  Obtained from:	wiz@NetBSD.org (previous 2)
  
  1.25
  "Be consistent: document the birthtime field of struct stat for
  the "B" field specifier."
  
  Obtained from:	reed@NetBSD.org
  
  1.26
  "Drop trailing space."
  
  Obtained from:	wiz@NetBSD.org
  
  1.27
  "Since we have st_birthtime in struct stat, it is in default display."
  
  Obtained from:	enami@NetBSD.org
  
  Purposely skipping the following revisions:
  1.22	NetBSD-specific change
  1.23	Removal of license clauses 3 and 4, already handled by imp
  	in our r203971
  
  MFC 216219:
  
  Bring in the change from NetBSD 1.28:
  
  "\\ -> \e"
  
  Obtained from:	joerg@NetBSD.org
  
  Bump .Dd because we're now up to date with the latest NetBSD version

Modified:
  stable/8/usr.bin/stat/Makefile
  stable/8/usr.bin/stat/stat.1
  stable/8/usr.bin/stat/stat.c
Directory Properties:
  stable/8/usr.bin/stat/   (props changed)

Modified: stable/8/usr.bin/stat/Makefile
==============================================================================
--- stable/8/usr.bin/stat/Makefile	Tue Jan 11 20:05:53 2011	(r217282)
+++ stable/8/usr.bin/stat/Makefile	Tue Jan 11 20:08:34 2011	(r217283)
@@ -1,7 +1,6 @@
 # $FreeBSD$
 
 PROG=	stat
-WARNS?=	2
 
 LINKS=	${BINDIR}/stat ${BINDIR}/readlink
 MLINKS=	stat.1 readlink.1

Modified: stable/8/usr.bin/stat/stat.1
==============================================================================
--- stable/8/usr.bin/stat/stat.1	Tue Jan 11 20:05:53 2011	(r217282)
+++ stable/8/usr.bin/stat/stat.1	Tue Jan 11 20:08:34 2011	(r217283)
@@ -1,4 +1,4 @@
-.\"	$NetBSD: stat.1,v 1.11 2003/05/08 13:07:10 wiz Exp $
+.\"	$NetBSD: stat.1,v 1.28 2010/04/05 21:25:01 joerg Exp $
 .\"
 .\" Copyright (c) 2002 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -29,7 +29,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd April 24, 2010
+.Dd December 5, 2010
 .Dt STAT 1
 .Os
 .Sh NAME
@@ -43,15 +43,15 @@
 .Op Fl t Ar timefmt
 .Op Ar
 .Nm readlink
-.Op Fl n
+.Op Fl fn
 .Op Ar
 .Sh DESCRIPTION
 The
 .Nm
 utility displays information about the file pointed to by
 .Ar file .
-Read, write or execute permissions of the named file are not required, but
-all directories listed in the path name leading to the file must be
+Read, write, or execute permissions of the named file are not required, but
+all directories listed in the pathname leading to the file must be
 searchable.
 If no argument is given,
 .Nm
@@ -60,13 +60,42 @@ displays information about the file desc
 When invoked as
 .Nm readlink ,
 only the target of the symbolic link is printed.
-If the given argument is not a symbolic link,
+If the given argument is not a symbolic link and the
+.Fl f
+option is not specified,
 .Nm readlink
 will print nothing and exit with an error.
+If the
+.Fl f
+option is specified, the output is canonicalized by following every symlink
+in every component of the given path recursively.
+.Nm readlink
+will resolve both absolute and relative paths, and return the absolute pathname
+corresponding to
+.Ar file .
+In this case, the argument does not need to be a symbolic link.
 .Pp
 The information displayed is obtained by calling
 .Xr lstat 2
 with the given argument and evaluating the returned structure.
+The default format displays the
+.Fa st_dev ,
+.Fa st_ino ,
+.Fa st_mode ,
+.Fa st_nlink ,
+.Fa st_uid ,
+.Fa st_gid ,
+.Fa st_rdev ,
+.Fa st_size ,
+.Fa st_atime ,
+.Fa st_mtime ,
+.Fa st_ctime ,
+.Fa st_birthtime ,
+.Fa st_blksize ,
+.Fa st_blocks ,
+and
+.Fa st_flags
+fields, in that order.
 .Pp
 The options are as follows:
 .Bl -tag -width indent
@@ -107,6 +136,14 @@ will refer to the target of
 if file is a symbolic link, and not to
 .Ar file
 itself.
+If the link is broken or the target does not exist,
+fall back on
+.Xr lstat 2
+and report information about the link.
+.It Fl l
+Display output in
+.Ic ls Fl lT
+format.
 .It Fl n
 Do not force a newline to appear at the end of each piece of output.
 .It Fl q
@@ -136,7 +173,8 @@ display the raw, numerical value (for ex
 epoch, etc.).
 .It Fl s
 Display information in
-.Dq "shell output" ,
+.Dq shell output
+format,
 suitable for initializing variables.
 .It Fl x
 Display information in a more verbose way as known from some
@@ -334,49 +372,62 @@ A required field specifier, being one of
 .It Cm d
 Device upon which
 .Ar file
-resides.
+resides
+.Pq Fa st_dev .
 .It Cm i
 .Ar file Ns 's
-inode number.
+inode number
+.Pq Fa st_ino .
 .It Cm p
-File type and permissions.
+File type and permissions
+.Pq Fa st_mode .
 .It Cm l
 Number of hard links to
-.Ar file .
+.Ar file
+.Pq Fa st_nlink .
 .It Cm u , g
 User ID and group ID of
 .Ar file Ns 's
-owner.
+owner
+.Pq Fa st_uid , st_gid .
 .It Cm r
-Device number for character and block device special files.
+Device number for character and block device special files
+.Pq Fa st_rdev .
 .It Cm a , m , c , B
 The time
 .Ar file
-was last accessed or modified, of when the inode was last changed, or
-the birth time of the inode.
+was last accessed or modified, or when the inode was last changed, or
+the birth time of the inode
+.Pq Fa st_atime , st_mtime , st_ctime , st_birthtime .
 .It Cm z
 The size of
 .Ar file
-in bytes.
+in bytes
+.Pq Fa st_size .
 .It Cm b
 Number of blocks allocated for
-.Ar file .
+.Ar file
+.Pq Fa st_blocks .
 .It Cm k
-Optimal file system I/O operation block size.
+Optimal file system I/O operation block size
+.Pq Fa st_blksize .
 .It Cm f
 User defined flags for
 .Ar file .
 .It Cm v
-Inode generation number.
+Inode generation number
+.Pq Fa st_gen .
 .El
 .Pp
-The following four field specifiers are not drawn directly from the
+The following five field specifiers are not drawn directly from the
 data in
 .Vt "struct stat" ,
 but are:
 .Bl -tag -width indent
 .It Cm N
 The name of the file.
+.It Cm R
+The absolute pathname corresponding to the file.
 .It Cm T
 The file type, either as in
 .Nm ls Fl F
@@ -406,12 +457,12 @@ as an output form, with the
 exception of
 .Cm p
 which defaults to
-.Cm O ,
+.Cm O ;
 .Cm a , m ,
 and
 .Cm c
 which default to
-.Cm D ,
+.Cm D ;
 and
 .Cm Y , T ,
 and
@@ -421,8 +472,15 @@ which default to
 .Sh EXIT STATUS
 .Ex -std stat readlink
 .Sh EXAMPLES
+If no options are specified, the default format is
+"%d %i %Sp %l %Su %Sg %r %z \e"%Sa\e" \e"%Sm\e" \e"%Sc\e" \e"%SB\e" %k %b %#Xf %N".
+.Bd -literal -offset indent
+\*[Gt] stat /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
+.Pp
 Given a symbolic link
-.Pa foo
+.Dq foo
 that points from
 .Pa /tmp/foo
 to

Modified: stable/8/usr.bin/stat/stat.c
==============================================================================
--- stable/8/usr.bin/stat/stat.c	Tue Jan 11 20:05:53 2011	(r217282)
+++ stable/8/usr.bin/stat/stat.c	Tue Jan 11 20:08:34 2011	(r217283)
@@ -30,7 +30,8 @@
 #include <sys/cdefs.h>
 #if 0
 #ifndef lint
-__RCSID("$NetBSD: stat.c,v 1.13 2003/07/25 03:21:17 atatat Exp $");
+__RCSID("$NetBSD: stat.c,v 1.31 2010/12/16 05:30:16 dholland Exp $"
+"$OpenBSD: stat.c,v 1.14 2009/06/24 09:44:25 sobrado Exp $");
 #endif
 #endif
 
@@ -52,6 +53,7 @@ __FBSDID("$FreeBSD$");
 
 #include <ctype.h>
 #include <err.h>
+#include <errno.h>
 #include <grp.h>
 #include <limits.h>
 #include <paths.h>
@@ -152,6 +154,7 @@ __FBSDID("$FreeBSD$");
 #define MIDDLE_PIECE	'M'
 #define LOW_PIECE	'L'
 
+#define	SHOW_realpath	'R'
 #define SHOW_st_dev	'd'
 #define SHOW_st_ino	'i'
 #define SHOW_st_mode	'p'
@@ -175,7 +178,7 @@ __FBSDID("$FreeBSD$");
 
 void	usage(const char *);
 void	output(const struct stat *, const char *,
-	    const char *, int, int, int);
+	    const char *, int, int);
 int	format1(const struct stat *,	/* stat info */
 	    const char *,		/* the file name */
 	    const char *, int,		/* the format string itself */
@@ -186,7 +189,7 @@ int	format1(const struct stat *,	/* stat
 char   *xfflagstostr(unsigned long);
 #endif
 
-char *timefmt;
+const char *timefmt;
 int linkfail;
 
 #define addchar(s, c, nl) \
@@ -201,7 +204,7 @@ main(int argc, char *argv[])
 	struct stat st;
 	int ch, rc, errs, am_readlink;
 	int lsF, fmtchar, usestat, fn, nonl, quiet;
-	char *statfmt, *options, *synopsis;
+	const char *statfmt, *options, *synopsis;
 	char dname[sizeof _PATH_DEV + SPECNAMELEN] = _PATH_DEV;
 	const char *file;
 
@@ -217,14 +220,15 @@ main(int argc, char *argv[])
 
 	if (strcmp(getprogname(), "readlink") == 0) {
 		am_readlink = 1;
-		options = "n";
-		synopsis = "[-n] [file ...]";
+		options = "fn";
+		synopsis = "[-fn] [file ...]";
 		statfmt = "%Y";
 		fmtchar = 'f';
 		quiet = 1;
 	} else {
 		options = "f:FlLnqrst:x";
-		synopsis = "[-FlLnqrsx] [-f format] [-t timefmt] [file ...]";
+		synopsis = "[-FLnq] [-f format | -l | -r | -s | -x] "
+		    "[-t timefmt] [file ...]";
 	}
 
 	while ((ch = getopt(argc, argv, options)) != -1)
@@ -242,6 +246,10 @@ main(int argc, char *argv[])
 			quiet = 1;
 			break;
 		case 'f':
+			if (am_readlink) {
+				statfmt = "%R";
+				break;
+			}
 			statfmt = optarg;
 			/* FALLTHROUGH */
 		case 'l':
@@ -313,8 +321,17 @@ main(int argc, char *argv[])
 			rc = fstat(STDIN_FILENO, &st);
 		} else {
 			file = argv[0];
-			if (usestat)
-				rc = stat(file, &st);
+			if (usestat) {
+				/*
+				 * Try stat() and if it fails, fall back to
+				 * lstat() just in case we're examining a
+				 * broken symlink.
+				 */
+				if ((rc = stat(file, &st)) == -1 &&
+				    errno == ENOENT &&
+				    (rc = lstat(file, &st)) == -1)
+					errno = ENOENT;
+			}
 			else
 				rc = lstat(file, &st);
 		}
@@ -326,7 +343,7 @@ main(int argc, char *argv[])
 				warn("%s: stat", file);
 		}
 		else
-			output(&st, file, statfmt, fn, nonl, quiet);
+			output(&st, file, statfmt, fn, nonl);
 
 		argv++;
 		argc--;
@@ -368,10 +385,10 @@ usage(const char *synopsis)
  */
 void
 output(const struct stat *st, const char *file,
-    const char *statfmt, int fn, int nonl, int quiet)
+    const char *statfmt, int fn, int nonl)
 {
 	int flags, size, prec, ofmt, hilo, what;
-	char buf[PATH_MAX];
+	char buf[PATH_MAX + 4 + 1];
 	const char *subfmt;
 	int nl, t, i;
 
@@ -508,6 +525,7 @@ output(const struct stat *st, const char
 		}
 
 		switch (*statfmt) {
+			fmtcase(what, SHOW_realpath);
 			fmtcase(what, SHOW_st_dev);
 			fmtcase(what, SHOW_st_ino);
 			fmtcase(what, SHOW_st_mode);
@@ -540,7 +558,7 @@ output(const struct stat *st, const char
 		     buf, sizeof(buf),
 		     flags, size, prec, ofmt, hilo, what);
 
-		for (i = 0; i < t && i < sizeof(buf); i++)
+		for (i = 0; i < t && i < (int)(sizeof(buf) - 1); i++)
 			addchar(stdout, buf[i], &nl);
 
 		continue;
@@ -567,7 +585,8 @@ format1(const struct stat *st,
     int hilo, int what)
 {
 	u_int64_t data;
-	char *sdata, lfmt[24], tmp[20];
+	char *stmp, lfmt[24], tmp[20];
+	const char *sdata;
 	char smode[12], sid[12], path[PATH_MAX + 4];
 	struct passwd *pw;
 	struct group *gr;
@@ -628,28 +647,29 @@ format1(const struct stat *st,
 		small = (sizeof(st->st_mode) == 4);
 		data = st->st_mode;
 		strmode(st->st_mode, smode);
-		sdata = smode;
-		l = strlen(sdata);
-		if (sdata[l - 1] == ' ')
-			sdata[--l] = '\0';
+		stmp = smode;
+		l = strlen(stmp);
+		if (stmp[l - 1] == ' ')
+			stmp[--l] = '\0';
 		if (hilo == HIGH_PIECE) {
 			data >>= 12;
-			sdata += 1;
-			sdata[3] = '\0';
+			stmp += 1;
+			stmp[3] = '\0';
 			hilo = 0;
 		}
 		else if (hilo == MIDDLE_PIECE) {
 			data = (data >> 9) & 07;
-			sdata += 4;
-			sdata[3] = '\0';
+			stmp += 4;
+			stmp[3] = '\0';
 			hilo = 0;
 		}
 		else if (hilo == LOW_PIECE) {
 			data &= 0777;
-			sdata += 7;
-			sdata[3] = '\0';
+			stmp += 7;
+			stmp[3] = '\0';
 			hilo = 0;
 		}
+		sdata = stmp;
 		formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX |
 		    FMTF_STRING;
 		if (ofmt == 0)
@@ -710,7 +730,6 @@ format1(const struct stat *st,
 		ts = *tsp;		/* copy so we can muck with it */
 		small = (sizeof(ts.tv_sec) == 4);
 		data = ts.tv_sec;
-		small = 1;
 		tm = localtime(&ts.tv_sec);
 		(void)strftime(path, sizeof(path), timefmt, tm);
 		sdata = path;
@@ -766,6 +785,26 @@ format1(const struct stat *st,
 			ofmt = FMTF_UNSIGNED;
 		break;
 #endif /* HAVE_STRUCT_STAT_ST_GEN */
+	case SHOW_realpath:
+		small = 0;
+		data = 0;
+		if (file == NULL) {
+			(void)strlcpy(path, "(stdin)", sizeof(path));
+			sdata = path;
+		} else {
+			snprintf(path, sizeof(path), " -> ");
+			if (realpath(file, path + 4) == NULL) {
+				linkfail = 1;
+				l = 0;
+				path[0] = '\0';
+			}
+			sdata = path + (ofmt == FMTF_STRING ? 0 : 4);
+		}
+
+		formats = FMTF_STRING;
+		if (ofmt == 0)
+			ofmt = FMTF_STRING;
+		break;
 	case SHOW_symlink:
 		small = 0;
 		data = 0;
@@ -791,24 +830,23 @@ format1(const struct stat *st,
 	case SHOW_filetype:
 		small = 0;
 		data = 0;
-		sdata = smode;
-		sdata[0] = '\0';
+		sdata = "";
 		if (hilo == 0 || hilo == LOW_PIECE) {
 			switch (st->st_mode & S_IFMT) {
-			case S_IFIFO:	(void)strcat(sdata, "|");	break;
-			case S_IFDIR:	(void)strcat(sdata, "/");	break;
+			case S_IFIFO:	sdata = "|";	break;
+			case S_IFDIR:	sdata = "/";	break;
 			case S_IFREG:
 				if (st->st_mode &
 				    (S_IXUSR | S_IXGRP | S_IXOTH))
-					(void)strcat(sdata, "*");
+					sdata = "*";
 				break;
-			case S_IFLNK:	(void)strcat(sdata, "@");	break;
-			case S_IFSOCK:	(void)strcat(sdata, "=");	break;
+			case S_IFLNK:	sdata = "@";	break;
+			case S_IFSOCK:	sdata = "=";	break;
 #ifdef S_IFWHT
-			case S_IFWHT:	(void)strcat(sdata, "%");	break;
+			case S_IFWHT:	sdata = "%";	break;
 #endif /* S_IFWHT */
 #ifdef S_IFDOOR
-			case S_IFDOOR:	(void)strcat(sdata, ">");	break;
+			case S_IFDOOR:	sdata = ">";	break;
 #endif /* S_IFDOOR */
 			}
 			hilo = 0;
@@ -839,7 +877,7 @@ format1(const struct stat *st,
 	case SHOW_filename:
 		small = 0;
 		data = 0;
-		(void)strncpy(path, file, sizeof(path));
+		(void)strlcpy(path, file, sizeof(path));
 		sdata = path;
 		formats = FMTF_STRING;
 		if (ofmt == 0)
@@ -914,8 +952,9 @@ format1(const struct stat *st,
 				(void)snprintf(tmp, sizeof(tmp), "%d", size);
 				(void)strcat(lfmt, tmp);
 			}
-			(void)strcat(lfmt, "d");
-			return (snprintf(buf, blen, lfmt, ts.tv_sec));
+			(void)strcat(lfmt, "lld");
+			return (snprintf(buf, blen, lfmt,
+			    (long long)ts.tv_sec));
 		}
 
 		/*
@@ -938,7 +977,8 @@ format1(const struct stat *st,
 			(void)snprintf(tmp, sizeof(tmp), "%d", size);
 			(void)strcat(lfmt, tmp);
 		}
-		(void)strcat(lfmt, "d");
+		/* Seconds: time_t cast to long long. */
+		(void)strcat(lfmt, "lld");
 
 		/*
 		 * The stuff after the decimal point always needs zero
@@ -949,8 +989,10 @@ format1(const struct stat *st,
 		/*
 		 * We can "print" at most nine digits of precision.  The
 		 * rest we will pad on at the end.
+		 *
+		 * Nanoseconds: long.
 		 */
-		(void)snprintf(tmp, sizeof(tmp), "%dd", prec > 9 ? 9 : prec);
+		(void)snprintf(tmp, sizeof(tmp), "%dld", prec > 9 ? 9 : prec);
 		(void)strcat(lfmt, tmp);
 
 		/*
@@ -964,8 +1006,8 @@ format1(const struct stat *st,
 		 * Use the format, and then tack on any zeroes that
 		 * might be required to make up the requested precision.
 		 */
-		l = snprintf(buf, blen, lfmt, ts.tv_sec, ts.tv_nsec);
-		for (; prec > 9 && l < blen; prec--, l++)
+		l = snprintf(buf, blen, lfmt, (long long)ts.tv_sec, ts.tv_nsec);
+		for (; prec > 9 && l < (int)blen; prec--, l++)
 			(void)strcat(buf, "0");
 		return (l);
 	}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201101112008.p0BK8YYo033829>