Module Name:    src
Committed By:   christos
Date:           Sat Dec 19 18:28:54 UTC 2015

Modified Files:
        src/bin/pax: options.c tar.1 tar.c

Log Message:
PR/50119: Thomas Klausner: Add --timestamp option to tar.


To generate a diff of this commit:
cvs rdiff -u -r1.116 -r1.117 src/bin/pax/options.c
cvs rdiff -u -r1.35 -r1.36 src/bin/pax/tar.1
cvs rdiff -u -r1.72 -r1.73 src/bin/pax/tar.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/bin/pax/options.c
diff -u src/bin/pax/options.c:1.116 src/bin/pax/options.c:1.117
--- src/bin/pax/options.c:1.116	Sat Apr 11 11:41:33 2015
+++ src/bin/pax/options.c	Sat Dec 19 13:28:54 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: options.c,v 1.116 2015/04/11 15:41:33 christos Exp $	*/
+/*	$NetBSD: options.c,v 1.117 2015/12/19 18:28:54 christos Exp $	*/
 
 /*-
  * Copyright (c) 1992 Keith Muller.
@@ -42,7 +42,7 @@
 #if 0
 static char sccsid[] = "@(#)options.c	8.2 (Berkeley) 4/18/94";
 #else
-__RCSID("$NetBSD: options.c,v 1.116 2015/04/11 15:41:33 christos Exp $");
+__RCSID("$NetBSD: options.c,v 1.117 2015/12/19 18:28:54 christos Exp $");
 #endif
 #endif /* not lint */
 
@@ -64,6 +64,7 @@ __RCSID("$NetBSD: options.c,v 1.116 2015
 #include <unistd.h>
 #include <inttypes.h>
 #include <paths.h>
+#include <util.h>
 #include "pax.h"
 #include "options.h"
 #include "cpio.h"
@@ -76,6 +77,7 @@ __RCSID("$NetBSD: options.c,v 1.116 2015
 /*
  * Routines which handle command line options
  */
+struct stat tst;		/* Timestamp to set if non-0 */
 
 static int nopids;		/* tar mode: suppress "pids" for -p option */
 static char flgch[] = FLGCH;	/* list of all possible flags (pax) */
@@ -88,6 +90,9 @@ static void printflg(unsigned int);
 static int c_frmt(const void *, const void *);
 static off_t str_offt(char *);
 static char *get_line(FILE *fp);
+#ifndef SMALL
+static int set_tstamp(const char *, struct stat *);
+#endif
 static void pax_options(int, char **);
 __dead static void pax_usage(void);
 static void tar_options(int, char **);
@@ -129,8 +134,9 @@ static int get_line_error;
 #define	OPT_SPARSE			16
 #define OPT_XZ				17
 #define OPT_GNU				18
+#define	OPT_TIMESTAMP			19
 #if !HAVE_NBTOOL_CONFIG_H
-#define	OPT_CHROOT			19
+#define	OPT_CHROOT			20
 #endif
 
 /*
@@ -803,6 +809,8 @@ struct option tar_longopts[] = {
 	{ "chroot",		no_argument,		0,
 						OPT_CHROOT },
 #endif
+	{ "timestamp",		required_argument,	0,
+						OPT_TIMESTAMP },
 #if 0 /* Not implemented */
 	{ "catenate",		no_argument,		0,	'A' },	/* F */
 	{ "concatenate",	no_argument,		0,	'A' },	/* F */
@@ -1144,6 +1152,14 @@ tar_options(int argc, char **argv)
 			do_chroot = 1;
 			break;
 #endif
+#ifndef SMALL
+		case OPT_TIMESTAMP:
+			if (set_tstamp(optarg, &tst) == -1) {
+				tty_warn(1, "Invalid timestamp `%s'", optarg);
+				tar_usage();
+			}
+			break;
+#endif
 		default:
 			tar_usage();
 			break;
@@ -2083,6 +2099,43 @@ get_line(FILE *f)
 	return temp;
 }
 
+#ifndef SMALL
+/*
+ * set_tstamp()
+ *	Use a specific timestamp for all individual files created in the
+ *	archive
+ */
+static int
+set_tstamp(const char *b, struct stat *st)
+{
+	time_t when;
+	char *eb;
+	long long l;
+
+	if (stat(b, st) != -1)
+		return 0;
+
+#ifndef HAVE_NBTOOL_CONFIG_H
+	errno = 0;
+	if ((when = parsedate(b, NULL, NULL)) == -1 && errno != 0)
+#endif
+	{
+		errno = 0;
+		l = strtoll(b, &eb, 0);
+		if (b == eb || *eb || errno)
+			return -1;
+		when = (time_t)l;
+	}
+
+	st->st_ino = 1;
+#if HAVE_STRUCT_STAT_BIRTHTIME 
+	st->st_birthtime =
+#endif
+	st->st_mtime = st->st_ctime = st->st_atime = when;
+	return 0;
+}
+#endif
+
 /*
  * no_op()
  *	for those option functions where the archive format has nothing to do.

Index: src/bin/pax/tar.1
diff -u src/bin/pax/tar.1:1.35 src/bin/pax/tar.1:1.36
--- src/bin/pax/tar.1:1.35	Sat Apr 11 12:22:07 2015
+++ src/bin/pax/tar.1	Sat Dec 19 13:28:54 2015
@@ -1,4 +1,4 @@
-.\" $NetBSD: tar.1,v 1.35 2015/04/11 16:22:07 wiz Exp $
+.\" $NetBSD: tar.1,v 1.36 2015/12/19 18:28:54 christos Exp $
 .\"
 .\" Copyright (c) 1996 SigmaSoft, Th. Lockert
 .\" All rights reserved.
@@ -25,7 +25,7 @@
 .\"
 .\"	OpenBSD: tar.1,v 1.28 2000/11/09 23:58:56 aaron Exp
 .\"
-.Dd April 11, 2015
+.Dd December 19, 2015
 .Dt TAR 1
 .Os
 .Sh NAME
@@ -297,6 +297,19 @@ can be processed.
 Cause files of type directory being copied or archived, or archive members of
 type directory being extracted, to match only the directory file or archive
 member and not the file hierarchy rooted at the directory.
+.It Fl Fl timestamp Ar timestamp
+Store all modification times in the archive with the
+.Ar timestamp
+given instead of the actual modification time of the individual archive member
+so that repeatable builds are possible.
+The
+.Ar timestamp
+can be a
+.Pa pathname ,
+where the timestamps are derived from that file, a parseable date for
+.Xr parsedate 3
+(this option is not yet available in the tools build), or an integer value
+interpreted as the number of seconds from the Epoch.
 .El
 .Pp
 The options

Index: src/bin/pax/tar.c
diff -u src/bin/pax/tar.c:1.72 src/bin/pax/tar.c:1.73
--- src/bin/pax/tar.c:1.72	Tue Jun 16 18:31:08 2015
+++ src/bin/pax/tar.c	Sat Dec 19 13:28:54 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: tar.c,v 1.72 2015/06/16 22:31:08 christos Exp $	*/
+/*	$NetBSD: tar.c,v 1.73 2015/12/19 18:28:54 christos Exp $	*/
 
 /*-
  * Copyright (c) 1992 Keith Muller.
@@ -42,7 +42,7 @@
 #if 0
 static char sccsid[] = "@(#)tar.c	8.2 (Berkeley) 4/18/94";
 #else
-__RCSID("$NetBSD: tar.c,v 1.72 2015/06/16 22:31:08 christos Exp $");
+__RCSID("$NetBSD: tar.c,v 1.73 2015/12/19 18:28:54 christos Exp $");
 #endif
 #endif /* not lint */
 
@@ -64,6 +64,8 @@ __RCSID("$NetBSD: tar.c,v 1.72 2015/06/1
 #include "extern.h"
 #include "tar.h"
 
+extern struct stat tst;
+
 /*
  * Routines for reading, writing and header identify of various versions of tar
  */
@@ -587,6 +589,7 @@ tar_wr(ARCHD *arcn)
 {
 	HD_TAR *hd;
 	int len;
+	uintmax_t mtime;
 	char hdblk[sizeof(HD_TAR)];
 
 	/*
@@ -695,10 +698,11 @@ tar_wr(ARCHD *arcn)
 	/*
 	 * copy those fields that are independent of the type
 	 */
+	mtime = tst.st_ino ? tst.st_mtime : arcn->sb.st_mtime;
 	if (u32_oct((uintmax_t)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) ||
 	    u32_oct((uintmax_t)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) ||
 	    u32_oct((uintmax_t)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) ||
-	    u32_oct((uintmax_t)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1))
+	    u32_oct(mtime, hd->mtime, sizeof(hd->mtime), 1))
 		goto out;
 
 	/*
@@ -1046,6 +1050,7 @@ ustar_wr(ARCHD *arcn)
 {
 	HD_USTAR *hd;
 	char *pt;
+	uintmax_t mtime;
 	char hdblk[sizeof(HD_USTAR)];
 	const char *user, *group;
 
@@ -1210,7 +1215,8 @@ ustar_wr(ARCHD *arcn)
 		return size_err("UID", arcn);
 	if (u32_oct((uintmax_t)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3))
 		return size_err("GID", arcn);
-	if (u32_oct((uintmax_t)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3))
+	mtime = tst.st_ino ? tst.st_mtime : arcn->sb.st_mtime;
+	if (u32_oct(mtime, hd->mtime, sizeof(hd->mtime), 3))
 		return size_err("MTIME", arcn);
 	user = user_from_uid(arcn->sb.st_uid, 1);
 	group = group_from_gid(arcn->sb.st_gid, 1);

Reply via email to