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

This commit is contained in:
christos 2015-12-19 18:28:54 +00:00
parent d8a9f2abfc
commit 9158fb657d
3 changed files with 81 additions and 9 deletions

View File

@ -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/04/11 15:41:33 christos Exp $");
#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/04/11 15:41:33 christos Exp $");
/*
* 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 */
@ -1143,6 +1151,14 @@ tar_options(int argc, char **argv)
case OPT_CHROOT:
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();
@ -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.

View File

@ -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

View File

@ -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/16 22:31:08 christos Exp $");
#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);