Support ZIP_STORE and fix check
authorRobert Pengelly <robertapengelly@hotmail.com>
Wed, 1 Oct 2025 12:16:00 +0000 (13:16 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Wed, 1 Oct 2025 12:16:00 +0000 (13:16 +0100)
inflate.c
unzip.c
unzip.h

index eebdd2b0de63242c10c2baddbc7e856cb7d1c875..e1d163435d6b94ef33785c3f2f92e520c5e1b441 100644 (file)
--- a/inflate.c
+++ b/inflate.c
@@ -446,7 +446,7 @@ static inf_stat_t inf_noncomp_block (istream_t *is, FILE *outfile, uint64_t dst_
     len = array_to_integer (p, 2, 0), p += 2;
     nlen = array_to_integer (p, 2, 0), p += 2;
     
-    if (nlen != (-len & 0xffff)) {
+    if (nlen != (~len & 0xffff)) {
         return HWINF_ERR;
     }
     
@@ -458,6 +458,10 @@ static inf_stat_t inf_noncomp_block (istream_t *is, FILE *outfile, uint64_t dst_
         return HWINF_ERR;               /* Not enough room to output. */
     }
     
+    if (fseek (outfile, *dst_pos, SEEK_SET)) {
+        return HWINF_ERR;
+    }
+    
     if (fwrite (p, 1, len, outfile) != len) {
         return HWINF_ERR;               /* Something went wrong. */
     }
diff --git a/unzip.c b/unzip.c
index 6ac3c788c73430c8cc87527d9d5dda366ff77354..20c684d7c10ba4e4c141e79185b4aa86ab02f1eb 100755 (executable)
--- a/unzip.c
+++ b/unzip.c
@@ -1,6 +1,7 @@
 /******************************************************************************
  * @file            unzip.c
  *****************************************************************************/
+#include    <assert.h>
 #include    <stdio.h>
 #include    <stdlib.h>
 #include    <string.h>
@@ -205,7 +206,7 @@ static int find_eocdr (struct eocdr *r) {
 struct cfh {
 
     uint16_t made_by_ver;               /* Version made by. */
-    uint16_t extrcat_ver;               /* Version needed to extract. */
+    uint16_t extract_ver;               /* Version needed to extract. */
     uint16_t gp_flag;                   /* General-purpose bit flag. */
     uint16_t method;                    /* Compression method. */
     uint16_t mod_time;                  /* Modification time. */
@@ -250,7 +251,7 @@ static int read_cfh (struct cfh *cfh) {
     }
     
     cfh->made_by_ver = array_to_integer (p, 2, 0), p += 2;
-    cfh->extrcat_ver = array_to_integer (p, 2, 0), p += 2;
+    cfh->extract_ver = array_to_integer (p, 2, 0), p += 2;
     cfh->gp_flag = array_to_integer (p, 2, 0), p += 2;
     cfh->method = array_to_integer (p, 2, 0), p += 2;
     cfh->mod_time = array_to_integer (p, 2, 0), p += 2;
@@ -490,7 +491,7 @@ static int is_relative (const char *name, uint64_t name_len) {
 
 struct lfh {
 
-    uint16_t extrcat_ver;               /* Version needed to extract. */
+    uint16_t extract_ver;               /* Version needed to extract. */
     uint16_t gp_flag;                   /* General-purpose bit flag. */
     uint16_t method;                    /* Compression method. */
     uint16_t mod_time;                  /* Modification time. */
@@ -526,7 +527,7 @@ static int read_lfh (struct lfh *lfh) {
         return -1;
     }
     
-    lfh->extrcat_ver = array_to_integer (p, 2, 0), p += 2;
+    lfh->extract_ver = array_to_integer (p, 2, 0), p += 2;
     lfh->gp_flag = array_to_integer (p, 2, 0), p += 2;
     lfh->method = array_to_integer (p, 2, 0), p += 2;
     lfh->mod_time = array_to_integer (p, 2, 0), p += 2;
@@ -578,7 +579,7 @@ static int read_lfh (struct lfh *lfh) {
 
 static int validate_structs (struct cfh *cfh, struct lfh *lfh) {
 
-    if (cfh->extrcat_ver != lfh->extrcat_ver) {
+    if (cfh->extract_ver != lfh->extract_ver) {
         return -1;
     }
     
@@ -870,9 +871,9 @@ static void extract_zip (const char *path) {
             continue;
         }
         
-        if (cfh.method != ZIP_DEFLATE) {
+        if (cfh.method != ZIP_STORE && cfh.method != ZIP_DEFLATE) {
         
-            report_at (program_name, 0, REPORT_ERROR, "currently only ZIP_DEFLATE is supported");
+            report_at (program_name, 0, REPORT_ERROR, "currently only ZIP_STORE && ZIP_DEFLATE are supported");
             break;
         
         }
@@ -914,7 +915,7 @@ static void extract_zip (const char *path) {
         
             report_at (program_name, 0, REPORT_ERROR, "failed to process Local File Header");
             
-            fseek (fp, cfh.lfh_offset, SEEK_SET);
+            fseek (fp, orig_offset, SEEK_SET);
             free (temp);
             
             break;
@@ -924,9 +925,8 @@ static void extract_zip (const char *path) {
         if (validate_structs (&cfh, &lfh)) {
         
             report_at (program_name, 0, REPORT_ERROR, "Centeral File Header and Local File Header mismatch");
-            fseek (fp, cfh.lfh_offset, SEEK_SET);
             
-            free (data);
+            fseek (fp, orig_offset, SEEK_SET);
             free (temp);
             
             break;
@@ -935,7 +935,7 @@ static void extract_zip (const char *path) {
         
         if (!(data = malloc (cfh.comp_size))) {
         
-            fseek (fp, cfh.lfh_offset, SEEK_SET);
+            fseek (fp, orig_offset, SEEK_SET);
             free (temp);
             
             break;
@@ -944,7 +944,7 @@ static void extract_zip (const char *path) {
         
         if (fread (data, 1, lfh.comp_size, fp) != lfh.comp_size) {
         
-            fseek (fp, cfh.lfh_offset, SEEK_SET);
+            fseek (fp, orig_offset, SEEK_SET);
             
             free (data);
             free (temp);
@@ -962,7 +962,38 @@ static void extract_zip (const char *path) {
         
         }
         
-        if (cfh.method == ZIP_DEFLATE) {
+        if (cfh.method == ZIP_STORE) {
+        
+            assert (lfh.comp_size == lfh.uncomp_size);
+            
+            if (!(outfile = fopen (temp, "w+b"))) {
+            
+                report_at (program_name, 0, REPORT_ERROR, "failed to open '%s' for writing", temp);
+                remove (temp);
+                
+                free (data);
+                free (temp);
+                
+                break;
+            
+            }
+            
+            if (fwrite (data, 1, lfh.uncomp_size, outfile) != lfh.uncomp_size) {
+            
+                report_at (program_name, 0, REPORT_ERROR, "failed to extract %s", temp);
+                fclose (outfile);
+                
+                free (data);
+                remove (temp);
+                
+                break;
+            
+            }
+            
+            free (data);
+            fclose (outfile);
+        
+        } else if (cfh.method == ZIP_DEFLATE) {
         
             if (!(outfile = fopen (temp, "w+b"))) {
             
diff --git a/unzip.h b/unzip.h
index 15f44ffb348fef729772de840d8aa9631c7d6ab2..ee4bdd0d8707ce759e6567f3cedd1f99c7f88216 100755 (executable)
--- a/unzip.h
+++ b/unzip.h
@@ -25,6 +25,7 @@ extern const char *program_name;
 #define     EXT_ATTR_DIR                (1U << 4)
 #define     EXT_ATTR_ARC                (1U << 5);
 
+#define     ZIP_STORE                   0
 #define     ZIP_DEFLATE                 8
 
 typedef enum {