summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoremaste <emaste@FreeBSD.org>2016-06-14 14:03:28 +0000
committeremaste <emaste@FreeBSD.org>2016-06-14 14:03:28 +0000
commit728901b3b7ed5cafc156ad58ad5bce4beb2029a4 (patch)
tree2a194c6c4afc05452a5270a24c894c98540da020
parent8973af476616ee5432c22df068e23462a6958e19 (diff)
downloadFreeBSD-src-728901b3b7ed5cafc156ad58ad5bce4beb2029a4.zip
FreeBSD-src-728901b3b7ed5cafc156ad58ad5bce4beb2029a4.tar.gz
makefs: Provide a -T option to set timestamps to a consistent value
This is taken from the NetBSD versions listed below and adapted to the makefs version in FreeBSD, along with a bug fix from cem@ that will be sent to NetBSD. Reviewed by: pfg Approved by: re (gjb) Obtained from: NetBSD MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D6835
-rw-r--r--usr.sbin/makefs/cd9660.c30
-rw-r--r--usr.sbin/makefs/ffs.c60
-rw-r--r--usr.sbin/makefs/ffs/mkfs.c12
-rw-r--r--usr.sbin/makefs/ffs/newfs_extern.h4
-rw-r--r--usr.sbin/makefs/makefs.815
-rw-r--r--usr.sbin/makefs/makefs.c47
-rw-r--r--usr.sbin/makefs/makefs.h1
-rw-r--r--usr.sbin/makefs/walk.c14
8 files changed, 129 insertions, 54 deletions
diff --git a/usr.sbin/makefs/cd9660.c b/usr.sbin/makefs/cd9660.c
index 3f55b8d..5d85a2f 100644
--- a/usr.sbin/makefs/cd9660.c
+++ b/usr.sbin/makefs/cd9660.c
@@ -442,7 +442,7 @@ cd9660_parse_opts(const char *option, fsinfo_t *fsopts)
*/
void
cd9660_makefs(const char *image, const char *dir, fsnode *root,
- fsinfo_t *fsopts)
+ fsinfo_t *fsopts)
{
int64_t startoffset;
int numDirectories;
@@ -619,7 +619,7 @@ typedef int (*cd9660node_func)(cd9660node *);
static void
cd9660_finalize_PVD(void)
{
- time_t tim;
+ time_t tstamp = stampst.st_ino ? stampst.st_mtime : time(NULL);
/* root should be a fixed size of 34 bytes since it has no name */
memcpy(diskStructure.primaryDescriptor.root_directory_record,
@@ -668,26 +668,26 @@ cd9660_finalize_PVD(void)
diskStructure.primaryDescriptor.bibliographic_file_id, 37);
/* Setup dates */
- time(&tim);
cd9660_time_8426(
(unsigned char *)diskStructure.primaryDescriptor.creation_date,
- tim);
+ tstamp);
cd9660_time_8426(
(unsigned char *)diskStructure.primaryDescriptor.modification_date,
- tim);
+ tstamp);
- /*
- cd9660_set_date(diskStructure.primaryDescriptor.expiration_date, now);
- */
+#if 0
+ cd9660_set_date(diskStructure.primaryDescriptor.expiration_date,
+ tstamp);
+#endif
memset(diskStructure.primaryDescriptor.expiration_date, '0', 16);
diskStructure.primaryDescriptor.expiration_date[16] = 0;
cd9660_time_8426(
(unsigned char *)diskStructure.primaryDescriptor.effective_date,
- tim);
+ tstamp);
/* make this sane */
cd9660_time_915(diskStructure.rootNode->dot_record->isoDirRecord->date,
- tim);
+ tstamp);
}
static void
@@ -808,7 +808,7 @@ cd9660_fill_extended_attribute_record(cd9660node *node)
static int
cd9660_translate_node_common(cd9660node *newnode)
{
- time_t tim;
+ time_t tstamp = stampst.st_ino ? stampst.st_mtime : time(NULL);
int test;
u_char flag;
char temp[ISO_FILENAME_MAXLENGTH_WITH_PADDING];
@@ -829,9 +829,8 @@ cd9660_translate_node_common(cd9660node *newnode)
/* Set the various dates */
/* If we want to use the current date and time */
- time(&tim);
- cd9660_time_915(newnode->isoDirRecord->date, tim);
+ cd9660_time_915(newnode->isoDirRecord->date, tstamp);
cd9660_bothendian_dword(newnode->fileDataLength,
newnode->isoDirRecord->size);
@@ -876,7 +875,8 @@ cd9660_translate_node(fsnode *node, cd9660node *newnode)
return 0;
/* Finally, overwrite some of the values that are set by default */
- cd9660_time_915(newnode->isoDirRecord->date, node->inode->st.st_mtime);
+ cd9660_time_915(newnode->isoDirRecord->date,
+ stampst.st_ino ? stampst.st_mtime : node->inode->st.st_mtime);
return 1;
}
@@ -1261,6 +1261,8 @@ cd9660_rrip_move_directory(cd9660node *dir)
diskStructure.rootNode, dir);
if (diskStructure.rr_moved_dir == NULL)
return 0;
+ cd9660_time_915(diskStructure.rr_moved_dir->isoDirRecord->date,
+ stampst.st_ino ? stampst.st_mtime : start_time.tv_sec);
}
/* Create a file with the same ORIGINAL name */
diff --git a/usr.sbin/makefs/ffs.c b/usr.sbin/makefs/ffs.c
index dc749dc..6a89442 100644
--- a/usr.sbin/makefs/ffs.c
+++ b/usr.sbin/makefs/ffs.c
@@ -482,6 +482,7 @@ ffs_create_image(const char *image, fsinfo_t *fsopts)
char *buf;
int i, bufsize;
off_t bufrem;
+ time_t tstamp;
assert (image != NULL);
assert (fsopts != NULL);
@@ -541,7 +542,15 @@ ffs_create_image(const char *image, fsinfo_t *fsopts)
/* make the file system */
if (debug & DEBUG_FS_CREATE_IMAGE)
printf("calling mkfs(\"%s\", ...)\n", image);
- fs = ffs_mkfs(image, fsopts);
+
+ if (stampst.st_ino != 0)
+ tstamp = stampst.st_ctime;
+ else
+ tstamp = start_time.tv_sec;
+
+ srandom(tstamp);
+
+ fs = ffs_mkfs(image, fsopts, tstamp);
fsopts->superblock = (void *)fs;
if (debug & DEBUG_FS_CREATE_IMAGE) {
time_t t;
@@ -648,19 +657,12 @@ ffs_build_dinode1(struct ufs1_dinode *dinp, dirbuf_t *dbufp, fsnode *cur,
{
int slen;
void *membuf;
+ struct stat *st = stampst.st_ino != 0 ? &stampst : &cur->inode->st;
memset(dinp, 0, sizeof(*dinp));
dinp->di_mode = cur->inode->st.st_mode;
dinp->di_nlink = cur->inode->nlink;
dinp->di_size = cur->inode->st.st_size;
- dinp->di_atime = cur->inode->st.st_atime;
- dinp->di_mtime = cur->inode->st.st_mtime;
- dinp->di_ctime = cur->inode->st.st_ctime;
-#if HAVE_STRUCT_STAT_ST_MTIMENSEC
- dinp->di_atimensec = cur->inode->st.st_atimensec;
- dinp->di_mtimensec = cur->inode->st.st_mtimensec;
- dinp->di_ctimensec = cur->inode->st.st_ctimensec;
-#endif
#if HAVE_STRUCT_STAT_ST_FLAGS
dinp->di_flags = cur->inode->st.st_flags;
#endif
@@ -669,6 +671,15 @@ ffs_build_dinode1(struct ufs1_dinode *dinp, dirbuf_t *dbufp, fsnode *cur,
#endif
dinp->di_uid = cur->inode->st.st_uid;
dinp->di_gid = cur->inode->st.st_gid;
+
+ dinp->di_atime = st->st_atime;
+ dinp->di_mtime = st->st_mtime;
+ dinp->di_ctime = st->st_ctime;
+#if HAVE_STRUCT_STAT_ST_MTIMENSEC
+ dinp->di_atimensec = st->st_atimensec;
+ dinp->di_mtimensec = st->st_mtimensec;
+ dinp->di_ctimensec = st->st_ctimensec;
+#endif
/* not set: di_db, di_ib, di_blocks, di_spare */
membuf = NULL;
@@ -696,31 +707,33 @@ ffs_build_dinode2(struct ufs2_dinode *dinp, dirbuf_t *dbufp, fsnode *cur,
{
int slen;
void *membuf;
+ struct stat *st = stampst.st_ino != 0 ? &stampst : &cur->inode->st;
memset(dinp, 0, sizeof(*dinp));
dinp->di_mode = cur->inode->st.st_mode;
dinp->di_nlink = cur->inode->nlink;
dinp->di_size = cur->inode->st.st_size;
- dinp->di_atime = cur->inode->st.st_atime;
- dinp->di_mtime = cur->inode->st.st_mtime;
- dinp->di_ctime = cur->inode->st.st_ctime;
-#if HAVE_STRUCT_STAT_ST_MTIMENSEC
- dinp->di_atimensec = cur->inode->st.st_atimensec;
- dinp->di_mtimensec = cur->inode->st.st_mtimensec;
- dinp->di_ctimensec = cur->inode->st.st_ctimensec;
-#endif
#if HAVE_STRUCT_STAT_ST_FLAGS
dinp->di_flags = cur->inode->st.st_flags;
#endif
#if HAVE_STRUCT_STAT_ST_GEN
dinp->di_gen = cur->inode->st.st_gen;
#endif
-#if HAVE_STRUCT_STAT_BIRTHTIME
- dinp->di_birthtime = cur->inode->st.st_birthtime;
- dinp->di_birthnsec = cur->inode->st.st_birthtimensec;
-#endif
dinp->di_uid = cur->inode->st.st_uid;
dinp->di_gid = cur->inode->st.st_gid;
+
+ dinp->di_atime = st->st_atime;
+ dinp->di_mtime = st->st_mtime;
+ dinp->di_ctime = st->st_ctime;
+#if HAVE_STRUCT_STAT_ST_MTIMENSEC
+ dinp->di_atimensec = st->st_atimensec;
+ dinp->di_mtimensec = st->st_mtimensec;
+ dinp->di_ctimensec = st->st_ctimensec;
+#endif
+#if HAVE_STRUCT_STAT_BIRTHTIME
+ dinp->di_birthtime = st->st_birthtime;
+ dinp->di_birthnsec = st->st_birthtimensec;
+#endif
/* not set: di_db, di_ib, di_blocks, di_spare */
membuf = NULL;
@@ -1125,11 +1138,6 @@ ffs_write_inode(union dinode *dp, uint32_t ino, const fsinfo_t *fsopts)
initediblk < ufs_rw32(cgp->cg_niblk, fsopts->needswap)) {
memset(buf, 0, fs->fs_bsize);
dip = (struct ufs2_dinode *)buf;
- /*
- * XXX: Time-based seeds should be avoided for
- * reproduceable builds.
- */
- srandom(time(NULL));
for (i = 0; i < INOPB(fs); i++) {
dip->di_gen = random();
dip++;
diff --git a/usr.sbin/makefs/ffs/mkfs.c b/usr.sbin/makefs/ffs/mkfs.c
index eca58eb..a6cb2e2 100644
--- a/usr.sbin/makefs/ffs/mkfs.c
+++ b/usr.sbin/makefs/ffs/mkfs.c
@@ -113,7 +113,7 @@ static int avgfilesize; /* expected average file size */
static int avgfpdir; /* expected number of files per directory */
struct fs *
-ffs_mkfs(const char *fsys, const fsinfo_t *fsopts)
+ffs_mkfs(const char *fsys, const fsinfo_t *fsopts, time_t tstamp)
{
int fragsperinode, optimalfpg, origdensity, minfpg, lastminfpg;
int32_t cylno, i, csfrags;
@@ -434,7 +434,7 @@ ffs_mkfs(const char *fsys, const fsinfo_t *fsopts)
sblock.fs_state = 0;
sblock.fs_clean = FS_ISCLEAN;
sblock.fs_ronly = 0;
- sblock.fs_id[0] = start_time.tv_sec;
+ sblock.fs_id[0] = tstamp;
sblock.fs_id[1] = random();
sblock.fs_fsmnt[0] = '\0';
csfrags = howmany(sblock.fs_cssize, sblock.fs_fsize);
@@ -450,9 +450,9 @@ ffs_mkfs(const char *fsys, const fsinfo_t *fsopts)
sblock.fs_cstotal.cs_nifree = sblock.fs_ncg * sblock.fs_ipg - ROOTINO;
sblock.fs_cstotal.cs_ndir = 0;
sblock.fs_dsize -= csfrags;
- sblock.fs_time = start_time.tv_sec;
+ sblock.fs_time = tstamp;
if (Oflag <= 1) {
- sblock.fs_old_time = start_time.tv_sec;
+ sblock.fs_old_time = tstamp;
sblock.fs_old_dsize = sblock.fs_dsize;
sblock.fs_old_csaddr = sblock.fs_csaddr;
sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir;
@@ -508,7 +508,7 @@ ffs_mkfs(const char *fsys, const fsinfo_t *fsopts)
printf("super-block backups (for fsck -b #) at:");
for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
- initcg(cylno, start_time.tv_sec, fsopts);
+ initcg(cylno, tstamp, fsopts);
if (cylno % nprintcols == 0)
printf("\n");
printf(" %*lld,", printcolwidth,
@@ -521,7 +521,7 @@ ffs_mkfs(const char *fsys, const fsinfo_t *fsopts)
* Now construct the initial file system,
* then write out the super-block.
*/
- sblock.fs_time = start_time.tv_sec;
+ sblock.fs_time = tstamp;
if (Oflag <= 1) {
sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir;
sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree;
diff --git a/usr.sbin/makefs/ffs/newfs_extern.h b/usr.sbin/makefs/ffs/newfs_extern.h
index a54c0e2..a135541 100644
--- a/usr.sbin/makefs/ffs/newfs_extern.h
+++ b/usr.sbin/makefs/ffs/newfs_extern.h
@@ -1,4 +1,4 @@
-/* $NetBSD: newfs_extern.h,v 1.3 2009/10/21 01:07:47 snj Exp $ */
+/* $NetBSD: newfs_extern.h,v 1.4 2015/12/21 00:58:08 christos Exp $ */
/* From: NetBSD: extern.h,v 1.3 2000/12/01 12:03:27 simonb Exp $ */
/*
@@ -28,7 +28,7 @@
*/
/* prototypes */
-struct fs *ffs_mkfs(const char *, const fsinfo_t *);
+struct fs *ffs_mkfs(const char *, const fsinfo_t *, time_t);
void ffs_write_superblock(struct fs *, const fsinfo_t *);
void ffs_rdfs(daddr_t, int, void *, const fsinfo_t *);
void ffs_wtfs(daddr_t, int, void *, const fsinfo_t *);
diff --git a/usr.sbin/makefs/makefs.8 b/usr.sbin/makefs/makefs.8
index f80dc53..3c3fd2b 100644
--- a/usr.sbin/makefs/makefs.8
+++ b/usr.sbin/makefs/makefs.8
@@ -35,7 +35,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 9, 2015
+.Dd June 14, 2016
.Dt MAKEFS 8
.Os
.Sh NAME
@@ -56,6 +56,7 @@
.Op Fl R Ar roundup-size
.Op Fl S Ar sector-size
.Op Fl s Ar image-size
+.Op Fl T Ar timestamp
.Op Fl t Ar fs-type
.Ar image-file
.Ar directory | manifest
@@ -212,6 +213,18 @@ Defaults to 512.
.It Fl s Ar image-size
Set the size of the file system image to
.Ar image-size .
+.It Fl T Ar timestamp
+Specify a timestamp to be set for all filesystem files and directories
+created so that repeatable builds are possible.
+The
+.Ar timestamp
+can be a
+.Pa pathname ,
+where the timestamps are derived from that file, or an integer
+value interpreted as the number of seconds from the Epoch.
+Note that timestamps specified in an
+.Xr mtree 5
+spec file, override the default timestamp.
.It Fl t Ar fs-type
Create an
.Ar fs-type
diff --git a/usr.sbin/makefs/makefs.c b/usr.sbin/makefs/makefs.c
index a7ca751..c1cf502 100644
--- a/usr.sbin/makefs/makefs.c
+++ b/usr.sbin/makefs/makefs.c
@@ -78,8 +78,10 @@ static fstype_t fstypes[] = {
u_int debug;
int dupsok;
struct timespec start_time;
+struct stat stampst;
static fstype_t *get_fstype(const char *);
+static int get_tstamp(const char *, struct stat *);
static void usage(void);
int main(int, char *[]);
@@ -110,13 +112,15 @@ main(int argc, char *argv[])
fstype->prepare_options(&fsoptions);
specfile = NULL;
- if (gettimeofday(&start, NULL) == -1)
- err(1, "Unable to get system time");
-
+ ch = gettimeofday(&start, NULL);
start_time.tv_sec = start.tv_sec;
start_time.tv_nsec = start.tv_usec * 1000;
- while ((ch = getopt(argc, argv, "B:b:Dd:f:F:M:m:N:o:pR:s:S:t:xZ")) != -1) {
+ if (ch == -1)
+ err(1, "Unable to get system time");
+
+
+ while ((ch = getopt(argc, argv, "B:b:Dd:f:F:M:m:N:o:pR:s:S:t:T:xZ")) != -1) {
switch (ch) {
case 'B':
@@ -239,6 +243,12 @@ main(int argc, char *argv[])
fstype->prepare_options(&fsoptions);
break;
+ case 'T':
+ if (get_tstamp(optarg, &stampst) == -1)
+ errx(1, "Cannot get timestamp from `%s'",
+ optarg);
+ break;
+
case 'x':
fsoptions.onlyspec = 1;
break;
@@ -360,6 +370,32 @@ get_fstype(const char *type)
return (NULL);
}
+static int
+get_tstamp(const char *b, struct stat *st)
+{
+ time_t when;
+ char *eb;
+ long long l;
+
+ if (stat(b, st) != -1)
+ return 0;
+
+ {
+ errno = 0;
+ l = strtoll(b, &eb, 0);
+ if (b == eb || *eb || errno)
+ return -1;
+ when = (time_t)l;
+ }
+
+ st->st_ino = 1;
+#ifdef HAVE_STRUCT_STAT_BIRTHTIME
+ st->st_birthtime =
+#endif
+ st->st_mtime = st->st_ctime = st->st_atime = when;
+ return 0;
+}
+
static void
usage(void)
{
@@ -370,7 +406,8 @@ usage(void)
"usage: %s [-t fs-type] [-o fs-options] [-d debug-mask] [-B endian]\n"
"\t[-S sector-size] [-M minimum-size] [-m maximum-size] [-R roundup-size]\n"
"\t[-s image-size] [-b free-blocks] [-f free-files] [-F mtree-specfile]\n"
-"\t[-xZ] [-N userdb-dir] image-file directory | manifest [extra-directory ...]\n",
+"\t[-xZ] [-N userdb-dir] [-T <timestamp/file>]\n"
+"\timage-file directory | manifest [extra-directory ...]\n",
prog);
exit(1);
}
diff --git a/usr.sbin/makefs/makefs.h b/usr.sbin/makefs/makefs.h
index ba80f74..13752b8 100644
--- a/usr.sbin/makefs/makefs.h
+++ b/usr.sbin/makefs/makefs.h
@@ -172,6 +172,7 @@ void cd9660_makefs(const char *, const char *, fsnode *, fsinfo_t *);
extern u_int debug;
extern int dupsok;
extern struct timespec start_time;
+extern struct stat stampst;
/*
* If -x is specified, we want to exclude nodes which do not appear
diff --git a/usr.sbin/makefs/walk.c b/usr.sbin/makefs/walk.c
index 2fc964a..7110170 100644
--- a/usr.sbin/makefs/walk.c
+++ b/usr.sbin/makefs/walk.c
@@ -229,6 +229,20 @@ create_fsnode(const char *root, const char *path, const char *name,
cur->type = stbuf->st_mode & S_IFMT;
cur->inode->nlink = 1;
cur->inode->st = *stbuf;
+ if (stampst.st_ino) {
+ cur->inode->st.st_atime = stampst.st_atime;
+ cur->inode->st.st_mtime = stampst.st_mtime;
+ cur->inode->st.st_ctime = stampst.st_ctime;
+#if HAVE_STRUCT_STAT_ST_MTIMENSEC
+ cur->inode->st.st_atimensec = stampst.st_atimensec;
+ cur->inode->st.st_mtimensec = stampst.st_mtimensec;
+ cur->inode->st.st_ctimensec = stampst.st_ctimensec;
+#endif
+#if HAVE_STRUCT_STAT_BIRTHTIME
+ cur->inode->st.st_birthtime = stampst.st_birthtime;
+ cur->inode->st.st_birthtimensec = stampst.st_birthtimensec;
+#endif
+ }
return (cur);
}
OpenPOWER on IntegriCloud