svn commit: r217300 - stable/7/usr.bin/stat

Doug Barton dougb at FreeBSD.org
Wed Jan 12 07:38:49 UTC 2011


Author: dougb
Date: Wed Jan 12 07:38:48 2011
New Revision: 217300
URL: http://svn.freebsd.org/changeset/base/217300

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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at NetBSD.org
  
  MFC 216209:
  
  Bring in the change from NetBSD 1.12:
  
  "document default format."
  
  Obtained from:	yamt at 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 at NetBSD.org
  
  MFC 216215:
  
  Bring in the changes from NetBSD 1.16 that we did not already have.
  
  "Some fixes from jmc at openbsd."
  
  Obtained from:	wiz at NetBSD.org
  
  MFC 216216:
  
  Bring in the change from NetBSD 1.20:
  
  "Make sentence easier to parse. From jsing at openbsd via jmc at openbsd."
  
  Obtained from:	wiz at 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 at openbsd via jmc at openbsd."
  
  1.24
  "Fix three variable names.
  From Todd T. Fries via Jason McIntyre."
  
  Obtained from:	wiz at NetBSD.org (previous 2)
  
  1.25
  "Be consistent: document the birthtime field of struct stat for
  the "B" field specifier."
  
  Obtained from:	reed at NetBSD.org
  
  1.26
  "Drop trailing space."
  
  Obtained from:	wiz at NetBSD.org
  
  1.27
  "Since we have st_birthtime in struct stat, it is in default display."
  
  Obtained from:	enami at 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 at NetBSD.org
  
  Bump .Dd because we're now up to date with the latest NetBSD version

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

Modified: stable/7/usr.bin/stat/Makefile
==============================================================================
--- stable/7/usr.bin/stat/Makefile	Wed Jan 12 07:27:30 2011	(r217299)
+++ stable/7/usr.bin/stat/Makefile	Wed Jan 12 07:38:48 2011	(r217300)
@@ -1,7 +1,7 @@
 # $FreeBSD$
 
 PROG=	stat
-WARNS?=	2
+WARNS?=	6
 
 LINKS=	${BINDIR}/stat ${BINDIR}/readlink
 MLINKS=	stat.1 readlink.1

Modified: stable/7/usr.bin/stat/stat.1
==============================================================================
--- stable/7/usr.bin/stat/stat.1	Wed Jan 12 07:27:30 2011	(r217299)
+++ stable/7/usr.bin/stat/stat.1	Wed Jan 12 07:38:48 2011	(r217300)
@@ -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/7/usr.bin/stat/stat.c
==============================================================================
--- stable/7/usr.bin/stat/stat.c	Wed Jan 12 07:27:30 2011	(r217299)
+++ stable/7/usr.bin/stat/stat.c	Wed Jan 12 07:38:48 2011	(r217300)
@@ -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
 
@@ -51,6 +52,7 @@ __FBSDID("$FreeBSD$");
 
 #include <ctype.h>
 #include <err.h>
+#include <errno.h>
 #include <grp.h>
 #include <limits.h>
 #include <pwd.h>
@@ -150,6 +152,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'
@@ -173,7 +176,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 */
@@ -184,7 +187,7 @@ int	format1(const struct stat *,	/* stat
 char   *xfflagstostr(unsigned long);
 #endif
 
-char *timefmt;
+const char *timefmt;
 int linkfail;
 
 #define addchar(s, c, nl) \
@@ -199,7 +202,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;
 	const char *file;
 
 	am_readlink = 0;
@@ -214,14 +217,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)
@@ -239,6 +243,10 @@ main(int argc, char *argv[])
 			quiet = 1;
 			break;
 		case 'f':
+			if (am_readlink) {
+				statfmt = "%R";
+				break;
+			}
 			statfmt = optarg;
 			/* FALLTHROUGH */
 		case 'l':
@@ -306,8 +314,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);
 		}
@@ -319,7 +336,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--;
@@ -361,10 +378,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;
 
@@ -501,6 +518,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);
@@ -533,7 +551,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;
@@ -560,7 +578,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;
@@ -621,28 +640,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)
@@ -703,7 +723,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;
@@ -759,6 +778,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;
@@ -784,24 +823,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;
@@ -832,7 +870,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)
@@ -907,8 +945,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));
 		}
 
 		/*
@@ -931,7 +970,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
@@ -942,8 +982,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);
 
 		/*
@@ -957,8 +999,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);
 	}


More information about the svn-src-all mailing list