From 2babb6be593f7a7995769ed8f6de671b0b187c66 Mon Sep 17 00:00:00 2001 From: TJ Date: Sat, 14 Nov 2015 04:10:06 +0000 Subject: [PATCH] Decode and apply MSDOS file timestamps --- installshield_main.c | 39 +++++++++++++++++++++++++++++++++++++-- installshield_z.h | 3 ++- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/installshield_main.c b/installshield_main.c index 4b1fa8e..bb6654a 100644 --- a/installshield_main.c +++ b/installshield_main.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include "implode.h" #include "installshield_z.h" @@ -32,6 +34,20 @@ usage(const char *name) ); } +time_t msdos2unixtime(uint16_t time, uint16_t date) +{ + if (debug) printf("Date: %04x Time %04x\n", date, time); + struct tm dt; + dt.tm_year =((date & 0xFE00) >> 9) + 80; + dt.tm_mon = (date & 0x01E0) >> 5; + dt.tm_mday = (date & 0x001F) >> 0; + dt.tm_hour = (time & 0xF800) >> 11; + dt.tm_min = (time & 0x07E0) >> 5; + dt.tm_sec = (time & 0x001F) >> 0; + + return mktime(&dt); +} + int headers_decode(int z_fd) { @@ -81,7 +97,9 @@ headers_decode(int z_fd) printf("File entries: %d ( %08x bytes @ 0x%08x)\n", header->files_entries, header->files_bytes, header->files_offset); for (int i = 0; i < header->files_entries; ++i) { - printf(" Entry %4d uses %06x bytes @ %08x. file-size %08x (payload %08x @ %08x)", i, q->entry_bytes, header->files_offset +(uint32_t)((void *)q - (void *)fileent), q->file_bytes, q->payload_bytes, q->payload_offset); + time_t timestamp = msdos2unixtime(q->timestamp, q->datestamp); + char *datetime = ctime(×tamp); + printf(" Entry %4d uses %06x bytes @ %08x. Date %s File-size %08x (payload %08x @ %08x)", i, q->entry_bytes, header->files_offset +(uint32_t)((void *)q - (void *)fileent), datetime, q->file_bytes, q->payload_bytes, q->payload_offset); if (debug) { printf(" next @ %08x", q->payload_offset + q->payload_bytes); @@ -146,7 +164,12 @@ headers_decode(int z_fd) unsigned int z_filename_len = strlen(q->name) + 4; char z_filename[z_filename_len]; strncpy(z_filename, q->name, z_filename_len); - strncat(z_filename, ".z", 2); + strncat(z_filename, ".z", 3); + + char filepath[strlen(dir_name) + z_filename_len]; + strncpy(filepath, dir_name, strlen(dir_name) + 1); + strncat(filepath, "/", 2); + strncat(filepath, z_filename, z_filename_len); if (debug) printf(" Creating payload file '%s/%s'\n", dir_name, z_filename); @@ -154,6 +177,9 @@ headers_decode(int z_fd) if ((offset = lseek(z_fd, q->payload_offset, SEEK_SET)) == q->payload_offset) { void *buffer; if ((buffer = calloc(q->payload_bytes, 1)) != 0) { + struct utimbuf filetime; + filetime.actime = timestamp; + filetime.modtime = timestamp; int pay_fd; if ((pay_fd = openat(dir_fd, z_filename, O_WRONLY | O_CREAT | O_TRUNC, 0644))) { ssize_t z_qty, pay_qty; @@ -170,6 +196,10 @@ headers_decode(int z_fd) } else fprintf(stderr, "Error: whilst reading payload expected %d bytes but read %ld\n", q->payload_bytes, z_qty); close(pay_fd); + if(utime(filepath, &filetime) == -1) { + fprintf(stderr, "Error: unable to set timestamp on '%s' (%d) ", filepath, errno); + perror(NULL); + } } if (q->payload_bytes >= 4) { uint8_t comp_type = *(uint8_t *)buffer; @@ -190,6 +220,11 @@ headers_decode(int z_fd) if ((decomp_qty = write(decomp_fd, buffer_decomp, q->file_bytes)) != q->file_bytes) fprintf(stderr, "Error: whilst writing decompressed data expected %d bytes but wrote %ld\n", q->file_bytes, decomp_qty); close(decomp_fd); + filepath[strlen(filepath) - 2] = 0; + if(utime(filepath, &filetime) == -1) { + fprintf(stderr, "Error: unable to set timestamp on '%s' (%d) ", filepath, errno); + perror(NULL); + } } } else { fprintf(stderr, "Error: failed to decompress '%s', payload: %d decompressed: %d\n", q->name, q->payload_bytes, decomp_bytes); diff --git a/installshield_z.h b/installshield_z.h index d55277c..e49b7a4 100644 --- a/installshield_z.h +++ b/installshield_z.h @@ -54,7 +54,8 @@ struct __attribute__((packed)) fileent_prefix { uint32_t file_bytes; uint32_t payload_bytes; uint32_t payload_offset; - uint32_t __crc32; + uint16_t datestamp; + uint16_t timestamp; uint32_t __unknown13; uint16_t entry_bytes; uint32_t __unknown01; -- 2.17.1