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, ×); // 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