Add decompression support using the implode library
[installshield_z.git] / installshield_main.c
index 9e95071..4b1fa8e 100644 (file)
@@ -16,6 +16,7 @@
 #include <errno.h>
 #include <string.h>
 
+#include "implode.h"
 #include "installshield_z.h"
 
 static const size_t BUFFER_SIZE = 0x4000;
@@ -64,7 +65,7 @@ headers_decode(int z_fd)
 
                        printf("Directory entries: %d ( %08x bytes @ 0x%08x)\n", header->directories_entries, header->directories_bytes, header->directories_offset);
 
-                       struct ll_dirents dirents[header->directories_entries];
+                       struct dirent dirents[header->directories_entries];
                        for (int i = 0; i < header->directories_entries; ++i) {
                                printf(" Entry %4d Size %x @ %08x    \"%s\"\n", i, p->entry_bytes, header->directories_offset + (uint32_t)((void *)p - (void *)dirent), p->name);
                                dirents[i].entry = p;
@@ -170,6 +171,39 @@ headers_decode(int z_fd)
                                                                                fprintf(stderr, "Error: whilst reading payload expected %d bytes but read %ld\n", q->payload_bytes, z_qty);
                                                                        close(pay_fd);
                                                                }
+                                                               if (q->payload_bytes >= 4) {
+                                                                       uint8_t comp_type = *(uint8_t *)buffer;
+                                                                       uint8_t dict_size = *(uint8_t *)(buffer + 1);
+                                                                       if (comp_type >= IMPLODE_BINARY && comp_type <= IMPLODE_ASCII && dict_size >= IMPLODE_DICT_1K && dict_size <= IMPLODE_DICT_4K) {
+                                                                               void * buffer_decomp;
+                                                                               if ((buffer_decomp = calloc(q->file_bytes, 1)) != 0) {
+                                                                                       uint32_t decomp_bytes = q->file_bytes;
+                                                                                       if (explode(buffer, q->payload_bytes, buffer_decomp, &decomp_bytes)) {
+                                                                                               if (decomp_bytes > q->file_bytes) {
+                                                                                                       fprintf(stderr, "Expected %d uncompressed bytes but got %d\n", q->file_bytes, decomp_bytes);
+                                                                                               }
+                                                                                               int decomp_fd;
+                                                                                               if ((decomp_fd = openat(dir_fd, q->name, O_WRONLY | O_CREAT | O_TRUNC, 0644))) {
+                                                                                                       ssize_t decomp_qty;
+                                                                                                       if (debug)
+                                                                                                               printf("Creating uncompressed file '%s/%s'\n",dir_name,  q->name);
+                                                                                                       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);
+                                                                                               }
+                                                                                       } else {
+                                                                                               fprintf(stderr, "Error: failed to decompress '%s', payload: %d decompressed: %d\n", q->name, q->payload_bytes, decomp_bytes);
+                                                                                       }
+                                                                                       free(buffer_decomp);
+                                                                               } else {
+                                                                                       fprintf(stderr, "Error: unable to allocate %d bytes for decompression buffer\n", q->file_bytes);
+                                                                               }
+                                                                       } else {
+                                                                               fprintf(stderr, "Does not look like TTComp compressed data. header: %04x\n", *(uint16_t *)buffer);
+                                                                       }
+                                                               } else {
+                                                                       fprintf(stderr, "Error: payload %d bytes smaller than minimum allowed TTComp of 4\n", q->payload_bytes);
+                                                               }
                                                                free(buffer);
                                                        }
                                                } else {