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
This commit is contained in:
Ed Maste 2016-06-14 14:03:28 +00:00
parent eaca863dd1
commit 7b03d164da
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=301879
8 changed files with 129 additions and 54 deletions

View File

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

View File

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

View File

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

View File

@ -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 *);

View File

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

View File

@ -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);
}

View File

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

View File

@ -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);
}