Den 06/10/2010 kl. 13.07 skrev Erik Cederstrand:

> Is something like the following acceptable? Without risking changes to 
> buildworld/distribution just now, this would allow me to dump contents of an 
> archive and re-insert them with '0' for mtime, uid and gid before checking 
> checksums, without affecting normal ar behaviour.

Great, I didn't even see the discussion on this list recently: 
http://lists.freebsd.org/pipermail/freebsd-hackers/2010-September/033005.html

Anyway, I added file mode to the patch. Apparently recent binutils also added 
this feature. I haven't looked at their patch, but chance has it I used the 
same option '-D'.

I'm sure the file mode I'm setting in line 175 of write.c is wrong (obj->md = 
100644), but I couldn't quite figure out how to set the value to rw-r--r--. 
Here's the new patch:

Index: ar.1
===================================================================
--- ar.1        (revision 213478)
+++ ar.1        (working copy)
@@ -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,14 @@
 .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
+option, insterts 0's instead of the real mtime, uid and gid values 
+and 644 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 .
Index: ar.c
===================================================================
--- ar.c        (revision 213478)
+++ ar.c        (working copy)
@@ -154,7 +154,7 @@
                }
        }
 
-       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 @@
                case 'd':
                        set_mode(bsdar, opt);
                        break;
+               case 'D':
+                       bsdar->options |= AR_D;
+                       break;
                case 'f':
                case 'T':
                        bsdar->options |= AR_TR;
@@ -357,8 +360,8 @@
        (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 -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");
Index: ar.h
===================================================================
--- ar.h        (revision 213478)
+++ ar.h        (working copy)
@@ -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 members with dummy mode, mtime, uid 
and gid */
 
 #define DEF_BLKSZ 10240                /* default block size */
 
Index: write.c
===================================================================
--- write.c     (revision 213478)
+++ write.c     (working copy)
@@ -163,11 +163,23 @@
        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 = 100644;
+       } 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 +633,10 @@
            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_O)
+                       archive_entry_set_mtime(entry, 0, 0);
+               else
+                       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));



Thanks,
Erik

Reply via email to