diff --git a/sbin/newfs_msdos/mkfs_msdos.c b/sbin/newfs_msdos/mkfs_msdos.c index b961e25c431..5a6406ce422 100644 --- a/sbin/newfs_msdos/mkfs_msdos.c +++ b/sbin/newfs_msdos/mkfs_msdos.c @@ -566,9 +566,17 @@ mkfs_msdos(const char *fname, const char *dtype, const struct msdos_options *op) } print_bpb(&bpb); if (!o.no_create) { - gettimeofday(&tv, NULL); - now = tv.tv_sec; - tm = localtime(&now); + if (o.timestamp_set) { + tv.tv_sec = now = o.timestamp; + tv.tv_usec = 0; + tm = gmtime(&now); + } else { + gettimeofday(&tv, NULL); + now = tv.tv_sec; + tm = localtime(&now); + } + + if (!(img = malloc(bpb.bpbBytesPerSec))) { warn(NULL); goto done; diff --git a/sbin/newfs_msdos/mkfs_msdos.h b/sbin/newfs_msdos/mkfs_msdos.h index 970af3612c9..2f5d7dcb12a 100644 --- a/sbin/newfs_msdos/mkfs_msdos.h +++ b/sbin/newfs_msdos/mkfs_msdos.h @@ -42,6 +42,7 @@ AOPT('L', const char *, volume_label, -1, "Volume Label") \ AOPT('N', bool, no_create, -2, "Don't create filesystem, print params only") \ AOPT('O', const char *, OEM_string, -1, "OEM string") \ AOPT('S', uint16_t, bytes_per_sector, 1, "Bytes per sector") \ +AOPT('T', time_t, timestamp, 0, "Timestamp") \ AOPT('a', uint32_t, sectors_per_fat, 1, "Sectors per FAT") \ AOPT('b', uint32_t, block_size, 1, "Block size") \ AOPT('c', uint8_t, sectors_per_cluster, 1, "Sectors per cluster") \ @@ -61,6 +62,7 @@ struct msdos_options { #define AOPT(_opt, _type, _name, _min, _desc) _type _name; ALLOPTS #undef AOPT + uint32_t timestamp_set:1; uint32_t volume_id_set:1; uint32_t media_descriptor_set:1; uint32_t hidden_sectors_set:1; diff --git a/sbin/newfs_msdos/newfs_msdos.8 b/sbin/newfs_msdos/newfs_msdos.8 index 967e1513556..44d5f21426b 100644 --- a/sbin/newfs_msdos/newfs_msdos.8 +++ b/sbin/newfs_msdos/newfs_msdos.8 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 9, 2015 +.Dd May 16, 2017 .Dt NEWFS_MSDOS 8 .Os .Sh NAME @@ -55,6 +55,7 @@ .Op Fl o Ar hidden .Op Fl r Ar reserved .Op Fl s Ar total +.Op Fl T Ar timestamp .Op Fl u Ar track-size .Ar special .Op Ar disktype @@ -159,6 +160,12 @@ Number of hidden sectors. Number of reserved sectors. .It Fl s Ar total File system size. +.It Fl T Ar timestamp +Specify a timestamp to be used for filesystem creation so that +it can be consistent for reproducible builds. +The timestamp can be a pathname (where the timestamps are derived from +that file) or an integer value interpreted +as the number of seconds since the Epoch. .It Fl u Ar track-size Number of sectors per track. .El diff --git a/sbin/newfs_msdos/newfs_msdos.c b/sbin/newfs_msdos/newfs_msdos.c index 0d3340d0c3f..5677568c97e 100644 --- a/sbin/newfs_msdos/newfs_msdos.c +++ b/sbin/newfs_msdos/newfs_msdos.c @@ -31,7 +31,7 @@ static const char rcsid[] = #endif /* not lint */ #include - +#include #include #include #include @@ -51,13 +51,30 @@ static u_int argtou(const char *, u_int, u_int, const char *); static off_t argtooff(const char *, const char *); static void usage(void); +static time_t +get_tstamp(const char *b) +{ + struct stat st; + char *eb; + long long l; + + if (stat(b, &st) != -1) + return (time_t)st.st_mtime; + + errno = 0; + l = strtoll(b, &eb, 0); + if (b == eb || *eb || errno) + errx(EXIT_FAILURE, "Can't parse timestamp '%s'", b); + return (time_t)l; +} + /* * Construct a FAT12, FAT16, or FAT32 file system. */ int main(int argc, char *argv[]) { - static const char opts[] = "@:NB:C:F:I:L:O:S:a:b:c:e:f:h:i:k:m:n:o:r:s:u:"; + static const char opts[] = "@:NB:C:F:I:L:O:S:a:b:c:e:f:h:i:k:m:n:o:r:s:T:u:"; struct msdos_options o; const char *fname, *dtype; char buf[MAXPATHLEN]; @@ -142,6 +159,10 @@ main(int argc, char *argv[]) case 's': o.size = argto4(optarg, 1, "file system size"); break; + case 'T': + o.timestamp_set = 1; + o.timestamp = get_tstamp(optarg); + break; case 'u': o.sectors_per_track = argto2(optarg, 1, "sectors/track"); break;