blob: ef739c1890bad15909fdeb97f47178da8a05dc20 [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 Collet0809a882016-07-09 18:25:10 +02008
Yann Collet0809a882016-07-09 18:25:10 +02009
Yann Collet0809a882016-07-09 18:25:10 +020010
11#include <stdlib.h> // malloc, exit
Yann Collet974f52f2016-07-07 14:08:00 +020012#include <stdio.h> // printf
13#include <string.h> // strerror
14#include <errno.h> // errno
15#include <sys/stat.h> // stat
Yann Collet45960372017-02-15 12:00:03 -080016#define ZSTD_STATIC_LINKING_ONLY // ZSTD_findDecompressedSize
Yann Collet0809a882016-07-09 18:25:10 +020017#include <zstd.h> // presumes zstd library is installed
Yann Collet974f52f2016-07-07 14:08:00 +020018
19
Yann Collet373d4f92016-08-01 17:36:11 +020020static off_t fsize_orDie(const char *filename)
Yann Collet974f52f2016-07-07 14:08:00 +020021{
22 struct stat st;
23 if (stat(filename, &st) == 0) return st.st_size;
24 /* error */
Yann Collet373d4f92016-08-01 17:36:11 +020025 perror(filename);
Yann Collet974f52f2016-07-07 14:08:00 +020026 exit(1);
27}
28
Yann Collet373d4f92016-08-01 17:36:11 +020029static FILE* fopen_orDie(const char *filename, const char *instruction)
Yann Collet974f52f2016-07-07 14:08:00 +020030{
31 FILE* const inFile = fopen(filename, instruction);
32 if (inFile) return inFile;
33 /* error */
Yann Collet373d4f92016-08-01 17:36:11 +020034 perror(filename);
Yann Collet974f52f2016-07-07 14:08:00 +020035 exit(2);
36}
37
Yann Collet373d4f92016-08-01 17:36:11 +020038static void* malloc_orDie(size_t size)
Yann Collet974f52f2016-07-07 14:08:00 +020039{
40 void* const buff = malloc(size);
41 if (buff) return buff;
42 /* error */
Yann Collet373d4f92016-08-01 17:36:11 +020043 perror("malloc");
Yann Collet974f52f2016-07-07 14:08:00 +020044 exit(3);
45}
46
Yann Collet373d4f92016-08-01 17:36:11 +020047static void* loadFile_orDie(const char* fileName, size_t* size)
Yann Collet974f52f2016-07-07 14:08:00 +020048{
Yann Collet373d4f92016-08-01 17:36:11 +020049 off_t const buffSize = fsize_orDie(fileName);
50 FILE* const inFile = fopen_orDie(fileName, "rb");
51 void* const buffer = malloc_orDie(buffSize);
Yann Collet974f52f2016-07-07 14:08:00 +020052 size_t const readSize = fread(buffer, 1, buffSize, inFile);
53 if (readSize != (size_t)buffSize) {
Yann Collet373d4f92016-08-01 17:36:11 +020054 fprintf(stderr, "fread: %s : %s \n", fileName, strerror(errno));
Yann Collet974f52f2016-07-07 14:08:00 +020055 exit(4);
56 }
57 fclose(inFile);
58 *size = buffSize;
59 return buffer;
60}
61
Yann Collete66708d2016-07-09 22:56:12 +020062/* createDict() :
63 `dictFileName` is supposed to have been created using `zstd --train` */
Yann Collet373d4f92016-08-01 17:36:11 +020064static ZSTD_DDict* createDict_orDie(const char* dictFileName)
Yann Collet974f52f2016-07-07 14:08:00 +020065{
66 size_t dictSize;
Yann Collet5e80dd32016-07-13 17:38:39 +020067 printf("loading dictionary %s \n", dictFileName);
Yann Collet373d4f92016-08-01 17:36:11 +020068 void* const dictBuffer = loadFile_orDie(dictFileName, &dictSize);
69 ZSTD_DDict* const ddict = ZSTD_createDDict(dictBuffer, dictSize);
70 if (ddict==NULL) { fprintf(stderr, "ZSTD_createDDict error \n"); exit(5); }
Yann Collet974f52f2016-07-07 14:08:00 +020071 free(dictBuffer);
72 return ddict;
73}
74
75
Yann Collet974f52f2016-07-07 14:08:00 +020076static void decompress(const char* fname, const ZSTD_DDict* ddict)
77{
78 size_t cSize;
Yann Collet373d4f92016-08-01 17:36:11 +020079 void* const cBuff = loadFile_orDie(fname, &cSize);
Sean Purcell4e709712017-02-07 13:50:09 -080080 unsigned long long const rSize = ZSTD_findDecompressedSize(cBuff, cSize);
Soojin Nam971c1612017-02-22 16:04:48 +090081 if (rSize==ZSTD_CONTENTSIZE_ERROR) {
82 fprintf(stderr, "%s : it was not compressed by zstd.\n", fname);
83 exit(5);
84 } else if (rSize==ZSTD_CONTENTSIZE_UNKNOWN) {
Yann Collet373d4f92016-08-01 17:36:11 +020085 fprintf(stderr, "%s : original size unknown \n", fname);
86 exit(6);
Yann Collet974f52f2016-07-07 14:08:00 +020087 }
Soojin Nam971c1612017-02-22 16:04:48 +090088
Yann Colleta2664642016-09-09 19:33:56 +020089 void* const rBuff = malloc_orDie((size_t)rSize);
Yann Collet974f52f2016-07-07 14:08:00 +020090
91 ZSTD_DCtx* const dctx = ZSTD_createDCtx();
Yann Colleta2664642016-09-09 19:33:56 +020092 if (dctx==NULL) { fprintf(stderr, "ZSTD_createDCtx() error \n"); exit(10); }
Yann Collet974f52f2016-07-07 14:08:00 +020093 size_t const dSize = ZSTD_decompress_usingDDict(dctx, rBuff, rSize, cBuff, cSize, ddict);
Yann Collet974f52f2016-07-07 14:08:00 +020094 if (dSize != rSize) {
Yann Collet373d4f92016-08-01 17:36:11 +020095 fprintf(stderr, "error decoding %s : %s \n", fname, ZSTD_getErrorName(dSize));
Yann Collet974f52f2016-07-07 14:08:00 +020096 exit(7);
97 }
98
99 /* success */
100 printf("%25s : %6u -> %7u \n", fname, (unsigned)cSize, (unsigned)rSize);
101
102 ZSTD_freeDCtx(dctx);
103 free(rBuff);
104 free(cBuff);
105}
106
107
108int main(int argc, const char** argv)
109{
110 const char* const exeName = argv[0];
111
112 if (argc<3) {
113 printf("wrong arguments\n");
114 printf("usage:\n");
115 printf("%s [FILES] dictionary\n", exeName);
116 return 1;
117 }
118
119 /* load dictionary only once */
120 const char* const dictName = argv[argc-1];
Yann Collet373d4f92016-08-01 17:36:11 +0200121 ZSTD_DDict* const dictPtr = createDict_orDie(dictName);
Yann Collet974f52f2016-07-07 14:08:00 +0200122
123 int u;
124 for (u=1; u<argc-1; u++) decompress(argv[u], dictPtr);
125
Yann Collet373d4f92016-08-01 17:36:11 +0200126 ZSTD_freeDDict(dictPtr);
Yann Colletcadd7cd2016-07-15 18:52:37 +0200127 printf("All %u files correctly decoded (in memory) \n", argc-2);
Yann Collet07639052016-08-03 01:57:57 +0200128 return 0;
Yann Collet974f52f2016-07-07 14:08:00 +0200129}