]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
gzstd: decompresses .gz files
authorPrzemyslaw Skibinski <inikep@gmail.com>
Wed, 30 Nov 2016 14:05:54 +0000 (15:05 +0100)
committerPrzemyslaw Skibinski <inikep@gmail.com>
Wed, 30 Nov 2016 14:05:54 +0000 (15:05 +0100)
programs/Makefile
programs/fileio.c

index b72cebdb1689f7adb8b74f3a207f9620c6943ac7..4f5a00d5b78209a86ba2334b4750370a2ca2921f 100644 (file)
@@ -82,7 +82,7 @@ zstd  : $(ZSTDDECOMP_O) $(ZSTD_FILES) $(ZSTDLEGACY_FILES) $(ZDICT_FILES) \
 ifneq (,$(filter Windows%,$(OS)))
        windres\generate_res.bat
 endif
-       $(CC)      $(FLAGS) $^ $(RES_FILE) -o $@$(EXT)
+       $(CC)      $(FLAGS) $^ $(RES_FILE) -o $@$(EXT) $(LDFLAGS)
 
 
 zstd32 : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)
@@ -124,6 +124,9 @@ zstd-decompress: clean_decomp_o
 zstd-compress: $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES) zstdcli.c fileio.c
        $(CC)      $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NODECOMPRESS $^ -o $@$(EXT)
 
+gzstd: clean_decomp_o
+       CFLAGS+=-DZSTD_GZDECOMPRESS LDFLAGS+=-lz $(MAKE) zstd
+
 generate_res:
        windres\generate_res.bat
 
index a11f928688f4add06027a3e7f27a5be8a38f4504..733abe01dfe208fa4ab176d6f6b0b99a417762ba 100644 (file)
@@ -34,6 +34,9 @@
 #include "fileio.h"
 #define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_magicNumber, ZSTD_frameHeaderSize_max */
 #include "zstd.h"
+#ifdef ZSTD_GZDECOMPRESS
+#include "zlib.h"
+#endif
 
 
 /*-*************************************
@@ -657,56 +660,74 @@ static int FIO_decompressSrcFile(dRess_t ress, const char* srcFileName)
 {
     unsigned long long filesize = 0;
     FILE* const dstFile = ress.dstFile;
-    FILE* srcFile;
     unsigned readSomething = 0;
     size_t const suffixSize = strlen(GZ_EXTENSION);
     size_t const sfnSize = strlen(srcFileName);
     const char* const suffixPtr = srcFileName + sfnSize - suffixSize;
 
-    if (sfnSize > suffixSize && strcmp(suffixPtr, GZ_EXTENSION) == 0) {
-        DISPLAYLEVEL(1, "zstd: %s: gz file cannot be uncompressed -- ignored \n", srcFileName);
-        return 1;
-    }
-
     if (UTIL_isDirectory(srcFileName)) {
         DISPLAYLEVEL(1, "zstd: %s is a directory -- ignored \n", srcFileName);
         return 1;
     }
 
-    srcFile = FIO_openSrcFile(srcFileName);
-    if (srcFile==0) return 1;
-
-    /* for each frame */
-    for ( ; ; ) {
-        /* check magic number -> version */
-        size_t const toRead = 4;
-        size_t const sizeCheck = fread(ress.srcBuffer, (size_t)1, toRead, srcFile);
-        if (sizeCheck==0) {
-            if (readSomething==0) { DISPLAY("zstd: %s: unexpected end of file \n", srcFileName); fclose(srcFile); return 1; }  /* srcFileName is empty */
-            break;   /* no more input */
+    if (sfnSize <= suffixSize || strcmp(suffixPtr, GZ_EXTENSION) != 0) {
+        FILE* srcFile = FIO_openSrcFile(srcFileName);
+        if (srcFile==0) return 1;
+
+        /* for each frame */
+        for ( ; ; ) {
+            /* check magic number -> version */
+            size_t const toRead = 4;
+            size_t const sizeCheck = fread(ress.srcBuffer, (size_t)1, toRead, srcFile);
+            if (sizeCheck==0) {
+                if (readSomething==0) { DISPLAY("zstd: %s: unexpected end of file \n", srcFileName); fclose(srcFile); return 1; }  /* srcFileName is empty */
+                break;   /* no more input */
+            }
+            readSomething = 1;   /* there is at least >= 4 bytes in srcFile */
+            if (sizeCheck != toRead) { DISPLAY("zstd: %s: unknown header \n", srcFileName); fclose(srcFile); return 1; }  /* srcFileName is empty */
+            if (!ZSTD_isFrame(ress.srcBuffer, toRead)) {
+                if ((g_overwrite) && !strcmp (srcFileName, stdinmark)) {  /* pass-through mode */
+                    unsigned const result = FIO_passThrough(dstFile, srcFile, ress.srcBuffer, ress.srcBufferSize);
+                    if (fclose(srcFile)) EXM_THROW(32, "zstd: %s close error", srcFileName);  /* error should never happen */
+                    return result;
+                } else {
+                    DISPLAYLEVEL(1, "zstd: %s: not in zstd format \n", srcFileName);
+                    fclose(srcFile);
+                    return 1;
+            }   }
+            filesize += FIO_decompressFrame(ress, dstFile, srcFile, toRead, filesize);
         }
-        readSomething = 1;   /* there is at least >= 4 bytes in srcFile */
-        if (sizeCheck != toRead) { DISPLAY("zstd: %s: unknown header \n", srcFileName); fclose(srcFile); return 1; }  /* srcFileName is empty */
-        if (!ZSTD_isFrame(ress.srcBuffer, toRead)) {
-            if ((g_overwrite) && !strcmp (srcFileName, stdinmark)) {  /* pass-through mode */
-                unsigned const result = FIO_passThrough(dstFile, srcFile, ress.srcBuffer, ress.srcBufferSize);
-                if (fclose(srcFile)) EXM_THROW(32, "zstd: %s close error", srcFileName);  /* error should never happen */
-                return result;
-            } else {
-                DISPLAYLEVEL(1, "zstd: %s: not in zstd format \n", srcFileName);
-                fclose(srcFile);
-                return 1;
-        }   }
-        filesize += FIO_decompressFrame(ress, dstFile, srcFile, toRead, filesize);
+        /* Close file */
+        if (fclose(srcFile)) EXM_THROW(33, "zstd: %s close error", srcFileName);  /* error should never happen */
+    } else {
+#ifndef ZSTD_GZDECOMPRESS
+        DISPLAYLEVEL(1, "zstd: %s: gz file cannot be uncompressed (zstd compiled without ZSTD_GZDECOMPRESS) -- ignored \n", srcFileName);
+        return 1;
+#else
+        int readBytes;
+        gzFile gzSrcFile = gzopen(srcFileName, "rb");
+        if (gzSrcFile == NULL) { DISPLAY("zstd: %s: gzopen error \n", srcFileName); return 1; }
+
+        do {
+            readBytes = gzread(gzSrcFile, ress.dstBuffer, ress.dstBufferSize);
+            if (readBytes < 0) { DISPLAY("zstd: %s: gzread error \n", srcFileName); return 1; }
+            if (readBytes > 0) { 
+                size_t const sizeCheck = fwrite(ress.dstBuffer, 1, readBytes, dstFile);
+                if (sizeCheck != (size_t)readBytes) EXM_THROW(34, "Write error : cannot write to output file"); 
+            }
+            filesize += readBytes;
+        } while ((size_t)readBytes == ress.dstBufferSize);
+
+        if (gzclose(gzSrcFile) != Z_OK) { DISPLAY("zstd: %s: gzclose error \n", srcFileName); return 1; }
+#endif
     }
 
     /* Final Status */
     DISPLAYLEVEL(2, "\r%79s\r", "");
     DISPLAYLEVEL(2, "%-20s: %llu bytes \n", srcFileName, filesize);
 
-    /* Close */
-    if (fclose(srcFile)) EXM_THROW(33, "zstd: %s close error", srcFileName);  /* error should never happen */
-    if (g_removeSrcFile) { if (remove(srcFileName)) EXM_THROW(34, "zstd: %s: %s", srcFileName, strerror(errno)); };
+    /* Remove source file */
+    if (g_removeSrcFile) { if (remove(srcFileName)) EXM_THROW(35, "zstd: %s: %s", srcFileName, strerror(errno)); };
     return 0;
 }