blob: 51340bae7879e78d03674abd35658167747e74a7 [file] [log] [blame]
Yann Collet4ded9e52016-08-30 10:04:33 -07001/**
2 * Copyright 2016-present, Yann Collet, Facebook, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the license found in the
6 * LICENSE-examples file in the root directory of this source tree.
7 */
Yann Collet9f9f1fc2016-08-12 18:56:27 +02008
Yann Collet9f9f1fc2016-08-12 18:56:27 +02009
10#include <stdlib.h> // malloc, exit
11#include <stdio.h> // fprintf, perror, feof
12#include <string.h> // strerror
13#include <errno.h> // errno
Yann Collet9f9f1fc2016-08-12 18:56:27 +020014#include <zstd.h> // presumes zstd library is installed
15
16
17static void* malloc_orDie(size_t size)
18{
19 void* const buff = malloc(size);
20 if (buff) return buff;
21 /* error */
22 perror("malloc:");
23 exit(1);
24}
25
26static FILE* fopen_orDie(const char *filename, const char *instruction)
27{
28 FILE* const inFile = fopen(filename, instruction);
29 if (inFile) return inFile;
30 /* error */
31 perror(filename);
32 exit(3);
33}
34
35static size_t fread_orDie(void* buffer, size_t sizeToRead, FILE* file)
36{
37 size_t const readSize = fread(buffer, 1, sizeToRead, file);
38 if (readSize == sizeToRead) return readSize; /* good */
39 if (feof(file)) return readSize; /* good, reached end of file */
40 /* error */
41 perror("fread");
42 exit(4);
43}
44
Yann Collet01c19922016-09-08 19:29:04 +020045static size_t fwrite_orDie(const void* buffer, size_t sizeToWrite, FILE* file)
46{
47 size_t const writtenSize = fwrite(buffer, 1, sizeToWrite, file);
48 if (writtenSize == sizeToWrite) return sizeToWrite; /* good */
49 /* error */
50 perror("fwrite");
51 exit(5);
52}
53
Yann Collet9f9f1fc2016-08-12 18:56:27 +020054static size_t fclose_orDie(FILE* file)
55{
56 if (!fclose(file)) return 0;
57 /* error */
58 perror("fclose");
59 exit(6);
60}
61
62
63static void decompressFile_orDie(const char* fname)
64{
65 FILE* const fin = fopen_orDie(fname, "rb");
Yann Collet01c19922016-09-08 19:29:04 +020066 size_t const buffInSize = ZSTD_DStreamInSize();
Yann Collet9f9f1fc2016-08-12 18:56:27 +020067 void* const buffIn = malloc_orDie(buffInSize);
Yann Colletb94fcc82016-09-08 19:48:04 +020068 FILE* const fout = stdout;
Yann Collet01c19922016-09-08 19:29:04 +020069 size_t const buffOutSize = ZSTD_DStreamOutSize(); /* Guarantee to successfully flush at least one complete compressed block in all circumstances. */
Yann Collet9f9f1fc2016-08-12 18:56:27 +020070 void* const buffOut = malloc_orDie(buffOutSize);
Yann Collet9f9f1fc2016-08-12 18:56:27 +020071
72 ZSTD_DStream* const dstream = ZSTD_createDStream();
73 if (dstream==NULL) { fprintf(stderr, "ZSTD_createDStream() error \n"); exit(10); }
74 size_t const initResult = ZSTD_initDStream(dstream);
Yann Colletb94fcc82016-09-08 19:48:04 +020075 if (ZSTD_isError(initResult)) { fprintf(stderr, "ZSTD_initDStream() error : %s \n", ZSTD_getErrorName(initResult)); exit(11); }
Yann Collet9f9f1fc2016-08-12 18:56:27 +020076
Yann Colletb94fcc82016-09-08 19:48:04 +020077 size_t read, toRead = initResult;
Yann Collet01c19922016-09-08 19:29:04 +020078 while ( (read = fread_orDie(buffIn, toRead, fin)) ) {
Yann Collet20658792016-08-17 01:48:43 +020079 ZSTD_inBuffer input = { buffIn, read, 0 };
80 while (input.pos < input.size) {
81 ZSTD_outBuffer output = { buffOut, buffOutSize, 0 };
Yann Collet01c19922016-09-08 19:29:04 +020082 toRead = ZSTD_decompressStream(dstream, &output , &input); /* toRead : size of next compressed block */
83 fwrite_orDie(buffOut, output.pos, fout);
Yann Collet9f9f1fc2016-08-12 18:56:27 +020084 }
85 }
86
Yann Colleta2664642016-09-09 19:33:56 +020087 ZSTD_freeDStream(dstream);
Yann Collet9f9f1fc2016-08-12 18:56:27 +020088 fclose_orDie(fin);
Yann Collet01c19922016-09-08 19:29:04 +020089 fclose_orDie(fout);
Yann Collet9f9f1fc2016-08-12 18:56:27 +020090 free(buffIn);
91 free(buffOut);
92}
93
94
95int main(int argc, const char** argv)
96{
97 const char* const exeName = argv[0];
98 const char* const inFilename = argv[1];
99
100 if (argc!=2) {
Yann Collet264c7332016-09-08 19:39:00 +0200101 fprintf(stderr, "wrong arguments\n");
102 fprintf(stderr, "usage:\n");
103 fprintf(stderr, "%s FILE\n", exeName);
Yann Collet9f9f1fc2016-08-12 18:56:27 +0200104 return 1;
105 }
106
107 decompressFile_orDie(inFilename);
Yann Collet9f9f1fc2016-08-12 18:56:27 +0200108 return 0;
109}