Hi,

It would be nice to keep the timestamp from gunzipped files.

The proposed patch adds an 'mtime' argument for unpackers to fill out,
which gets stamped in via utime.  I imagine the other unpackers can
use it if they care, and it could be expanded to a struct of other
useful information if it was ever required.

Where the gzip unpacker is used in a streaming manner for other tools,
there is a _simple() function which ignores the mtime argument.

Testing:
 - passes all of the compression related testsuite tests

 $ ls -l foo
 -rw-r--r-- 1 ianw ianw 0 2008-10-28 12:23 foo
 $ gzip foo
 $ ./busybox gunzip foo.gz
 $ ls -l foo
 -rw-r--r-- 1 ianw ianw 0 2008-10-28 12:23 foo

-i

 archival/bbunzip.c                        |   32 ++++++++++++++++++++++--------
 archival/libunarchive/decompress_unzip.c  |   29 ++++++++++++++++++++-------
 archival/libunarchive/get_header_tar_gz.c |    2 -
 archival/rpm.c                            |    2 -
 archival/rpm2cpio.c                       |    2 -
 include/libbb.h                           |    2 -
 include/unarchive.h                       |    3 +-
 libbb/read.c                              |    2 -
 8 files changed, 53 insertions(+), 21 deletions(-)

Index: archival/rpm.c
===================================================================
--- archival/rpm.c      (revision 23853)
+++ archival/rpm.c      (working copy)
@@ -215,7 +215,7 @@
 
        xread(archive_handle->src_fd, &magic, 2);
 #if BB_MMU
-       xformer = unpack_gz_stream;
+       xformer = unpack_gz_stream_simple;
 #else
        xformer_prog = "gunzip";
 #endif
Index: archival/bbunzip.c
===================================================================
--- archival/bbunzip.c  (revision 23853)
+++ archival/bbunzip.c  (working copy)
@@ -30,13 +30,14 @@
 
 int FAST_FUNC bbunpack(char **argv,
        char* (*make_new_name)(char *filename),
-       USE_DESKTOP(long long) int (*unpacker)(void)
+       USE_DESKTOP(long long) int (*unpacker)(time_t *mtime)
 )
 {
        struct stat stat_buf;
        USE_DESKTOP(long long) int status;
        char *filename, *new_name;
        smallint exitcode = 0;
+       time_t mtime;
 
        do {
                /* NB: new_name is *maybe* malloc'ed! */
@@ -92,14 +93,25 @@
                                        "use -f to force it");
                }
 
-               status = unpacker();
+               status = unpacker(&mtime);
                if (status < 0)
                        exitcode = 1;
 
                if (filename) {
                        char *del = new_name;
                        if (status >= 0) {
-                               /* TODO: restore user/group/times here? */
+                               /* TODO: restore other things? */
+                               if (mtime > 0) {
+                                       struct utimbuf times;
+                                       /* Done with this.  On some
+                                       systems calling utime then
+                                       closing resets the mtime. */
+                                       close(STDOUT_FILENO);
+                                       times.actime = mtime;
+                                       times.modtime = mtime;
+                                       utime(new_name, &times); // don't worry 
about errors
+                               }
+
                                /* Delete _compressed_ file */
                                del = filename;
                                /* restore extension (unless tgz -> tar case) */
@@ -159,8 +171,9 @@
 }
 
 static
-USE_DESKTOP(long long) int unpack_bunzip2(void)
+USE_DESKTOP(long long) int unpack_bunzip2(time_t *mtime)
 {
+       *mtime = 0; // not handled yet
        return unpack_bz2_stream_prime(STDIN_FILENO, STDOUT_FILENO);
 }
 
@@ -235,7 +248,7 @@
 }
 
 static
-USE_DESKTOP(long long) int unpack_gunzip(void)
+USE_DESKTOP(long long) int unpack_gunzip(time_t *mtime)
 {
        USE_DESKTOP(long long) int status = -1;
 
@@ -245,9 +258,10 @@
 
                magic2 = xread_char(STDIN_FILENO);
                if (ENABLE_FEATURE_SEAMLESS_Z && magic2 == 0x9d) {
+                       mtime = NULL;
                        status = unpack_Z_stream(STDIN_FILENO, STDOUT_FILENO);
                } else if (magic2 == 0x8b) {
-                       status = unpack_gz_stream(STDIN_FILENO, STDOUT_FILENO);
+                       status = unpack_gz_stream(STDIN_FILENO, STDOUT_FILENO, 
mtime);
                } else {
                        goto bad_magic;
                }
@@ -309,8 +323,9 @@
 }
 
 static
-USE_DESKTOP(long long) int unpack_unlzma(void)
+USE_DESKTOP(long long) int unpack_unlzma(time_t *mtime)
 {
+       *mtime = 0;
        return unpack_lzma_stream(STDIN_FILENO, STDOUT_FILENO);
 }
 
@@ -344,10 +359,11 @@
 }
 
 static
-USE_DESKTOP(long long) int unpack_uncompress(void)
+USE_DESKTOP(long long) int unpack_uncompress(time_t *mtime)
 {
        USE_DESKTOP(long long) int status = -1;
 
+       *mtime = 0;
        if ((xread_char(STDIN_FILENO) != 0x1f) || (xread_char(STDIN_FILENO) != 
0x9d)) {
                bb_error_msg("invalid magic");
        } else {
Index: archival/libunarchive/decompress_unzip.c
===================================================================
--- archival/libunarchive/decompress_unzip.c    (revision 23853)
+++ archival/libunarchive/decompress_unzip.c    (working copy)
@@ -1108,17 +1108,17 @@
        return res;
 }
 
-static int check_header_gzip(STATE_PARAM_ONLY)
+static int check_header_gzip(STATE_PARAM time_t *mtime)
 {
        union {
                unsigned char raw[8];
                struct {
                        uint8_t gz_method;
                        uint8_t flags;
-                       //uint32_t mtime; - unused fields
-                       //uint8_t xtra_flags;
-                       //uint8_t os_flags;
-               } formatted; /* packed */
+                       uint32_t mtime;
+                       uint8_t xtra_flags;
+                       uint8_t os_flags;
+               } __attribute__((packed)) formatted;
        } header;
 
        /*
@@ -1167,6 +1167,15 @@
                }
        }
 
+       if (mtime) {
+#if BB_LITTLE_ENDIAN
+               /* gzip data always in le */
+               header.formatted.mtime =
+                       SWAP_LE32(header.formatted.mtime);
+#endif
+               *mtime = header.formatted.mtime;
+       }
+
        /* Read the header checksum */
        if (header.formatted.flags & 0x02) {
                if (!top_up(PASS_STATE 2))
@@ -1177,7 +1186,7 @@
 }
 
 USE_DESKTOP(long long) int FAST_FUNC
-unpack_gz_stream(int in, int out)
+unpack_gz_stream(int in, int out, time_t *mtime)
 {
        uint32_t v32;
        USE_DESKTOP(long long) int n;
@@ -1192,7 +1201,7 @@
        gunzip_src_fd = in;
 
  again:
-       if (!check_header_gzip(PASS_STATE_ONLY)) {
+       if (!check_header_gzip(PASS_STATE mtime)) {
                bb_error_msg("corrupted data");
                n = -1;
                goto ret;
@@ -1239,3 +1248,9 @@
        DEALLOC_STATE;
        return n;
 }
+
+USE_DESKTOP(long long) int FAST_FUNC
+unpack_gz_stream_simple(int in, int out)
+{
+       return unpack_gz_stream(in, out, NULL);
+}
Index: archival/libunarchive/get_header_tar_gz.c
===================================================================
--- archival/libunarchive/get_header_tar_gz.c   (revision 23853)
+++ archival/libunarchive/get_header_tar_gz.c   (working copy)
@@ -26,7 +26,7 @@
        }
 #endif
 
-       open_transformer(archive_handle->src_fd, unpack_gz_stream, "gunzip");
+       open_transformer(archive_handle->src_fd, unpack_gz_stream_simple, 
"gunzip");
        archive_handle->offset = 0;
        while (get_header_tar(archive_handle) == EXIT_SUCCESS)
                continue;
Index: archival/rpm2cpio.c
===================================================================
--- archival/rpm2cpio.c (revision 23853)
+++ archival/rpm2cpio.c (working copy)
@@ -79,7 +79,7 @@
                bb_error_msg_and_die("invalid gzip magic");
        }
 
-       if (unpack_gz_stream(rpm_fd, STDOUT_FILENO) < 0) {
+       if (unpack_gz_stream(rpm_fd, STDOUT_FILENO, NULL) < 0) {
                bb_error_msg("error inflating");
        }
 
Index: libbb/read.c
===================================================================
--- libbb/read.c        (revision 23853)
+++ libbb/read.c        (working copy)
@@ -340,7 +340,7 @@
                        xread(fd, &magic, 2);
 #if ENABLE_FEATURE_SEAMLESS_GZ
 #if BB_MMU
-                       xformer = unpack_gz_stream;
+                       xformer = unpack_gz_stream_simple;
 #else
                        xformer_prog = "gunzip";
 #endif
Index: include/libbb.h
===================================================================
--- include/libbb.h     (revision 23853)
+++ include/libbb.h     (working copy)
@@ -914,7 +914,7 @@
 int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int bbunpack(char **argv,
        char* (*make_new_name)(char *filename),
-       USE_DESKTOP(long long) int (*unpacker)(void)
+       USE_DESKTOP(long long) int (*unpacker)(time_t *mtime)
 ) FAST_FUNC;
 #if ENABLE_ROUTE
 void bb_displayroutes(int noresolve, int netstatfmt) FAST_FUNC;
Index: include/unarchive.h
===================================================================
--- include/unarchive.h (revision 23853)
+++ include/unarchive.h (working copy)
@@ -125,7 +125,8 @@
 USE_DESKTOP(long long) int unpack_lzma_stream(int src_fd, int dst_fd) 
FAST_FUNC;
 /* the rest wants 2 first bytes already skipped by the caller */
 USE_DESKTOP(long long) int unpack_bz2_stream(int src_fd, int dst_fd) FAST_FUNC;
-USE_DESKTOP(long long) int unpack_gz_stream(int src_fd, int dst_fd) FAST_FUNC;
+USE_DESKTOP(long long) int unpack_gz_stream(int src_fd, int dst_fd, time_t 
*mtime) FAST_FUNC;
+USE_DESKTOP(long long) int unpack_gz_stream_simple(int src_fd, int dst_fd) 
FAST_FUNC;
 USE_DESKTOP(long long) int unpack_Z_stream(int fd_in, int fd_out) FAST_FUNC;
 /* wrapper which checks first two bytes to be "BZ" */
 USE_DESKTOP(long long) int unpack_bz2_stream_prime(int src_fd, int dst_fd) 
FAST_FUNC;

_______________________________________________
busybox mailing list
[email protected]
http://busybox.net/cgi-bin/mailman/listinfo/busybox

Reply via email to