mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-12-04 08:09:08 +00:00
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:
parent
eaca863dd1
commit
7b03d164da
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=301879
@ -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 */
|
||||
|
@ -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++;
|
||||
|
@ -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;
|
||||
|
@ -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 *);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user