Author: emaste
Date: Tue Jun 14 14:03:28 2016
New Revision: 301879
URL: https://svnweb.freebsd.org/changeset/base/301879

Log:
  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

Modified:
  head/usr.sbin/makefs/cd9660.c
  head/usr.sbin/makefs/ffs.c
  head/usr.sbin/makefs/ffs/mkfs.c
  head/usr.sbin/makefs/ffs/newfs_extern.h
  head/usr.sbin/makefs/makefs.8
  head/usr.sbin/makefs/makefs.c
  head/usr.sbin/makefs/makefs.h
  head/usr.sbin/makefs/walk.c

Modified: head/usr.sbin/makefs/cd9660.c
==============================================================================
--- head/usr.sbin/makefs/cd9660.c       Tue Jun 14 06:21:51 2016        
(r301878)
+++ head/usr.sbin/makefs/cd9660.c       Tue Jun 14 14:03:28 2016        
(r301879)
@@ -442,7 +442,7 @@ cd9660_parse_opts(const char *option, fs
  */
 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)(cd9660nod
 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(cd
 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 
        /* 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, cd96
                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 *d
                                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 */

Modified: head/usr.sbin/makefs/ffs.c
==============================================================================
--- head/usr.sbin/makefs/ffs.c  Tue Jun 14 06:21:51 2016        (r301878)
+++ head/usr.sbin/makefs/ffs.c  Tue Jun 14 14:03:28 2016        (r301879)
@@ -482,6 +482,7 @@ ffs_create_image(const char *image, fsin
        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, fsin
                /* 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 *di
 {
        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 *di
 #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 *di
 {
        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
            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++;

Modified: head/usr.sbin/makefs/ffs/mkfs.c
==============================================================================
--- head/usr.sbin/makefs/ffs/mkfs.c     Tue Jun 14 06:21:51 2016        
(r301878)
+++ head/usr.sbin/makefs/ffs/mkfs.c     Tue Jun 14 14:03:28 2016        
(r301879)
@@ -113,7 +113,7 @@ static int     avgfilesize;    /* expect
 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_
        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_
        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_
 
        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_
         * 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;

Modified: head/usr.sbin/makefs/ffs/newfs_extern.h
==============================================================================
--- head/usr.sbin/makefs/ffs/newfs_extern.h     Tue Jun 14 06:21:51 2016        
(r301878)
+++ head/usr.sbin/makefs/ffs/newfs_extern.h     Tue Jun 14 14:03:28 2016        
(r301879)
@@ -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 *);

Modified: head/usr.sbin/makefs/makefs.8
==============================================================================
--- head/usr.sbin/makefs/makefs.8       Tue Jun 14 06:21:51 2016        
(r301878)
+++ head/usr.sbin/makefs/makefs.8       Tue Jun 14 14:03:28 2016        
(r301879)
@@ -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

Modified: head/usr.sbin/makefs/makefs.c
==============================================================================
--- head/usr.sbin/makefs/makefs.c       Tue Jun 14 06:21:51 2016        
(r301878)
+++ head/usr.sbin/makefs/makefs.c       Tue Jun 14 14:03:28 2016        
(r301879)
@@ -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);
 }

Modified: head/usr.sbin/makefs/makefs.h
==============================================================================
--- head/usr.sbin/makefs/makefs.h       Tue Jun 14 06:21:51 2016        
(r301878)
+++ head/usr.sbin/makefs/makefs.h       Tue Jun 14 14:03:28 2016        
(r301879)
@@ -172,6 +172,7 @@ void                cd9660_makefs(const char *, const 
 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

Modified: head/usr.sbin/makefs/walk.c
==============================================================================
--- head/usr.sbin/makefs/walk.c Tue Jun 14 06:21:51 2016        (r301878)
+++ head/usr.sbin/makefs/walk.c Tue Jun 14 14:03:28 2016        (r301879)
@@ -229,6 +229,20 @@ create_fsnode(const char *root, const ch
        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);
 }
 
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to