summaryrefslogtreecommitdiffstats
path: root/usr.bin/ar
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2010-10-09 05:31:08 +0000
committerkientzle <kientzle@FreeBSD.org>2010-10-09 05:31:08 +0000
commit8ce8087ba56f15605e6ed0f895712ba21962ec78 (patch)
tree2553e2bcd168f62d37e7f3fd998d5ea9a1b01f29 /usr.bin/ar
parent55194e796cd9e8eb27d9bb4ec9f07184e390d01a (diff)
downloadFreeBSD-src-8ce8087ba56f15605e6ed0f895712ba21962ec78.zip
FreeBSD-src-8ce8087ba56f15605e6ed0f895712ba21962ec78.tar.gz
Add -D (deterministic) option to ar.
When set, it forces all timestamps and owners to zero and modes to 0644. Useful for producing libraries that are bitwise identical across multiple build runs. Submitted by: Erik Cederstrand Reviewed by: Kai Wang
Diffstat (limited to 'usr.bin/ar')
-rw-r--r--usr.bin/ar/ar.111
-rw-r--r--usr.bin/ar/ar.c13
-rw-r--r--usr.bin/ar/ar.h1
-rw-r--r--usr.bin/ar/write.c24
4 files changed, 40 insertions, 9 deletions
diff --git a/usr.bin/ar/ar.1 b/usr.bin/ar/ar.1
index 3a8b753..c64c7f6 100644
--- a/usr.bin/ar/ar.1
+++ b/usr.bin/ar/ar.1
@@ -62,6 +62,7 @@
.Op Fl a Ar position-after
.Op Fl b Ar position-before
.Op Fl c
+.Op Fl D
.Op Fl i Ar position-before
.Op Fl j
.Op Fl s
@@ -179,6 +180,16 @@ from the archive specified by argument
.Ar archive .
The archive's symbol table, if present, is updated to reflect
the new contents of the archive.
+.It Fl D
+When used in combination with the
+.Fl r
+or
+.Fl q
+option, insert 0's instead of the real mtime, uid and gid values
+and 0644 instead of file mode from the members named by arguments
+.Ar files ... .
+This ensures that checksums on the resulting archives are reproducible
+when member contents are identical.
.It Fl f
Synonymous with option
.Fl T .
diff --git a/usr.bin/ar/ar.c b/usr.bin/ar/ar.c
index 1fe92fb..e5bc1d2 100644
--- a/usr.bin/ar/ar.c
+++ b/usr.bin/ar/ar.c
@@ -154,7 +154,7 @@ main(int argc, char **argv)
}
}
- while ((opt = getopt_long(argc, argv, "abCcdfijlMmopqrSsTtuVvxz",
+ while ((opt = getopt_long(argc, argv, "abCcdDfijlMmopqrSsTtuVvxz",
longopts, NULL)) != -1) {
switch(opt) {
case 'a':
@@ -173,6 +173,9 @@ main(int argc, char **argv)
case 'd':
set_mode(bsdar, opt);
break;
+ case 'D':
+ bsdar->options |= AR_D;
+ break;
case 'f':
case 'T':
bsdar->options |= AR_TR;
@@ -269,6 +272,8 @@ main(int argc, char **argv)
only_mode(bsdar, "-c", "qr");
if (bsdar->options & AR_CC)
only_mode(bsdar, "-C", "x");
+ if (bsdar->options & AR_D)
+ only_mode(bsdar, "-D", "qr");
if (bsdar->options & AR_O)
only_mode(bsdar, "-o", "x");
if (bsdar->options & AR_SS)
@@ -356,9 +361,9 @@ bsdar_usage(void)
(void)fprintf(stderr, "\tar -m [-Tjsvz] archive file ...\n");
(void)fprintf(stderr, "\tar -m [-Tabijsvz] position archive file ...\n");
(void)fprintf(stderr, "\tar -p [-Tv] archive [file ...]\n");
- (void)fprintf(stderr, "\tar -q [-Tcjsvz] archive file ...\n");
- (void)fprintf(stderr, "\tar -r [-Tcjsuvz] archive file ...\n");
- (void)fprintf(stderr, "\tar -r [-Tabcijsuvz] position archive file ...\n");
+ (void)fprintf(stderr, "\tar -q [-TcDjsvz] archive file ...\n");
+ (void)fprintf(stderr, "\tar -r [-TcDjsuvz] archive file ...\n");
+ (void)fprintf(stderr, "\tar -r [-TabcDijsuvz] position archive file ...\n");
(void)fprintf(stderr, "\tar -s [-jz] archive\n");
(void)fprintf(stderr, "\tar -t [-Tv] archive [file ...]\n");
(void)fprintf(stderr, "\tar -x [-CTouv] archive [file ...]\n");
diff --git a/usr.bin/ar/ar.h b/usr.bin/ar/ar.h
index 60fe8e8..77dd492 100644
--- a/usr.bin/ar/ar.h
+++ b/usr.bin/ar/ar.h
@@ -43,6 +43,7 @@
#define AR_U 0x0200 /* only extract or update newer members.*/
#define AR_V 0x0400 /* verbose mode */
#define AR_Z 0x0800 /* gzip compression */
+#define AR_D 0x1000 /* insert dummy mode, mtime, uid and gid */
#define DEF_BLKSZ 10240 /* default block size */
diff --git a/usr.bin/ar/write.c b/usr.bin/ar/write.c
index 8b6fbdf..d27a767 100644
--- a/usr.bin/ar/write.c
+++ b/usr.bin/ar/write.c
@@ -163,11 +163,24 @@ create_obj_from_file(struct bsdar *bsdar, const char *name, time_t mtime)
if (mtime != 0 && bsdar->options & AR_U && sb.st_mtime <= mtime)
goto giveup;
- obj->uid = sb.st_uid;
- obj->gid = sb.st_gid;
- obj->md = sb.st_mode;
+ /*
+ * When option '-D' is specified, mtime and UID / GID from the file
+ * will be replaced with 0, and file mode with 644. This ensures that
+ * checksums will match for two archives containing the exact same
+ * files.
+ */
+ if (bsdar->options & AR_D) {
+ obj->uid = 0;
+ obj->gid = 0;
+ obj->mtime = 0;
+ obj->md = S_IFREG | 0644;
+ } else {
+ obj->uid = sb.st_uid;
+ obj->gid = sb.st_gid;
+ obj->mtime = sb.st_mtime;
+ obj->md = sb.st_mode;
+ }
obj->size = sb.st_size;
- obj->mtime = sb.st_mtime;
obj->dev = sb.st_dev;
obj->ino = sb.st_ino;
@@ -621,7 +634,8 @@ write_objs(struct bsdar *bsdar)
bsdar->options & AR_S) {
entry = archive_entry_new();
archive_entry_copy_pathname(entry, "/");
- archive_entry_set_mtime(entry, time(NULL), 0);
+ if ((bsdar->options & AR_D) == 0)
+ archive_entry_set_mtime(entry, time(NULL), 0);
archive_entry_set_size(entry, (bsdar->s_cnt + 1) *
sizeof(uint32_t) + bsdar->s_sn_sz);
AC(archive_write_header(a, entry));
OpenPOWER on IntegriCloud