xref: /aosp_15_r20/external/lz4/examples/fileCompress.c (revision 27162e4e17433d5aa7cb38e7b6a433a09405fc7f)
1*27162e4eSAndroid Build Coastguard Worker /* LZ4file API example : compress a file
2*27162e4eSAndroid Build Coastguard Worker  * Modified from an example code by anjiahao
3*27162e4eSAndroid Build Coastguard Worker  *
4*27162e4eSAndroid Build Coastguard Worker  * This example will demonstrate how
5*27162e4eSAndroid Build Coastguard Worker  * to manipulate lz4 compressed files like
6*27162e4eSAndroid Build Coastguard Worker  * normal files */
7*27162e4eSAndroid Build Coastguard Worker 
8*27162e4eSAndroid Build Coastguard Worker #include <assert.h>
9*27162e4eSAndroid Build Coastguard Worker #include <stdio.h>
10*27162e4eSAndroid Build Coastguard Worker #include <stdlib.h>
11*27162e4eSAndroid Build Coastguard Worker #include <string.h>
12*27162e4eSAndroid Build Coastguard Worker #include <sys/stat.h>
13*27162e4eSAndroid Build Coastguard Worker 
14*27162e4eSAndroid Build Coastguard Worker #include <lz4file.h>
15*27162e4eSAndroid Build Coastguard Worker 
16*27162e4eSAndroid Build Coastguard Worker 
17*27162e4eSAndroid Build Coastguard Worker #define CHUNK_SIZE (16*1024)
18*27162e4eSAndroid Build Coastguard Worker 
get_file_size(char * filename)19*27162e4eSAndroid Build Coastguard Worker static size_t get_file_size(char *filename)
20*27162e4eSAndroid Build Coastguard Worker {
21*27162e4eSAndroid Build Coastguard Worker     struct stat statbuf;
22*27162e4eSAndroid Build Coastguard Worker 
23*27162e4eSAndroid Build Coastguard Worker     if (filename == NULL) {
24*27162e4eSAndroid Build Coastguard Worker         return 0;
25*27162e4eSAndroid Build Coastguard Worker     }
26*27162e4eSAndroid Build Coastguard Worker 
27*27162e4eSAndroid Build Coastguard Worker     if(stat(filename,&statbuf)) {
28*27162e4eSAndroid Build Coastguard Worker         return 0;
29*27162e4eSAndroid Build Coastguard Worker     }
30*27162e4eSAndroid Build Coastguard Worker 
31*27162e4eSAndroid Build Coastguard Worker     return statbuf.st_size;
32*27162e4eSAndroid Build Coastguard Worker }
33*27162e4eSAndroid Build Coastguard Worker 
compress_file(FILE * f_in,FILE * f_out)34*27162e4eSAndroid Build Coastguard Worker static int compress_file(FILE* f_in, FILE* f_out)
35*27162e4eSAndroid Build Coastguard Worker {
36*27162e4eSAndroid Build Coastguard Worker     assert(f_in != NULL); assert(f_out != NULL);
37*27162e4eSAndroid Build Coastguard Worker 
38*27162e4eSAndroid Build Coastguard Worker     LZ4F_errorCode_t ret = LZ4F_OK_NoError;
39*27162e4eSAndroid Build Coastguard Worker     size_t len;
40*27162e4eSAndroid Build Coastguard Worker     LZ4_writeFile_t* lz4fWrite;
41*27162e4eSAndroid Build Coastguard Worker     void* const buf = malloc(CHUNK_SIZE);
42*27162e4eSAndroid Build Coastguard Worker     if (!buf) {
43*27162e4eSAndroid Build Coastguard Worker         printf("error: memory allocation failed \n");
44*27162e4eSAndroid Build Coastguard Worker         return 1;
45*27162e4eSAndroid Build Coastguard Worker     }
46*27162e4eSAndroid Build Coastguard Worker 
47*27162e4eSAndroid Build Coastguard Worker     /* Of course, you can also use prefsPtr to
48*27162e4eSAndroid Build Coastguard Worker      * set the parameters of the compressed file
49*27162e4eSAndroid Build Coastguard Worker      * NULL is use default
50*27162e4eSAndroid Build Coastguard Worker      */
51*27162e4eSAndroid Build Coastguard Worker     ret = LZ4F_writeOpen(&lz4fWrite, f_out, NULL);
52*27162e4eSAndroid Build Coastguard Worker     if (LZ4F_isError(ret)) {
53*27162e4eSAndroid Build Coastguard Worker         printf("LZ4F_writeOpen error: %s\n", LZ4F_getErrorName(ret));
54*27162e4eSAndroid Build Coastguard Worker         free(buf);
55*27162e4eSAndroid Build Coastguard Worker         return 1;
56*27162e4eSAndroid Build Coastguard Worker     }
57*27162e4eSAndroid Build Coastguard Worker 
58*27162e4eSAndroid Build Coastguard Worker     while (1) {
59*27162e4eSAndroid Build Coastguard Worker         len = fread(buf, 1, CHUNK_SIZE, f_in);
60*27162e4eSAndroid Build Coastguard Worker 
61*27162e4eSAndroid Build Coastguard Worker         if (ferror(f_in)) {
62*27162e4eSAndroid Build Coastguard Worker             printf("fread error\n");
63*27162e4eSAndroid Build Coastguard Worker             goto out;
64*27162e4eSAndroid Build Coastguard Worker         }
65*27162e4eSAndroid Build Coastguard Worker 
66*27162e4eSAndroid Build Coastguard Worker         /* nothing to read */
67*27162e4eSAndroid Build Coastguard Worker         if (len == 0) {
68*27162e4eSAndroid Build Coastguard Worker             break;
69*27162e4eSAndroid Build Coastguard Worker         }
70*27162e4eSAndroid Build Coastguard Worker 
71*27162e4eSAndroid Build Coastguard Worker         ret = LZ4F_write(lz4fWrite, buf, len);
72*27162e4eSAndroid Build Coastguard Worker         if (LZ4F_isError(ret)) {
73*27162e4eSAndroid Build Coastguard Worker             printf("LZ4F_write: %s\n", LZ4F_getErrorName(ret));
74*27162e4eSAndroid Build Coastguard Worker             goto out;
75*27162e4eSAndroid Build Coastguard Worker         }
76*27162e4eSAndroid Build Coastguard Worker     }
77*27162e4eSAndroid Build Coastguard Worker 
78*27162e4eSAndroid Build Coastguard Worker out:
79*27162e4eSAndroid Build Coastguard Worker     free(buf);
80*27162e4eSAndroid Build Coastguard Worker     if (LZ4F_isError(LZ4F_writeClose(lz4fWrite))) {
81*27162e4eSAndroid Build Coastguard Worker         printf("LZ4F_writeClose: %s\n", LZ4F_getErrorName(ret));
82*27162e4eSAndroid Build Coastguard Worker         return 1;
83*27162e4eSAndroid Build Coastguard Worker     }
84*27162e4eSAndroid Build Coastguard Worker 
85*27162e4eSAndroid Build Coastguard Worker     return 0;
86*27162e4eSAndroid Build Coastguard Worker }
87*27162e4eSAndroid Build Coastguard Worker 
decompress_file(FILE * f_in,FILE * f_out)88*27162e4eSAndroid Build Coastguard Worker static int decompress_file(FILE* f_in, FILE* f_out)
89*27162e4eSAndroid Build Coastguard Worker {
90*27162e4eSAndroid Build Coastguard Worker     assert(f_in != NULL); assert(f_out != NULL);
91*27162e4eSAndroid Build Coastguard Worker 
92*27162e4eSAndroid Build Coastguard Worker     LZ4F_errorCode_t ret = LZ4F_OK_NoError;
93*27162e4eSAndroid Build Coastguard Worker     LZ4_readFile_t* lz4fRead;
94*27162e4eSAndroid Build Coastguard Worker     void* const buf= malloc(CHUNK_SIZE);
95*27162e4eSAndroid Build Coastguard Worker     if (!buf) {
96*27162e4eSAndroid Build Coastguard Worker         printf("error: memory allocation failed \n");
97*27162e4eSAndroid Build Coastguard Worker     }
98*27162e4eSAndroid Build Coastguard Worker 
99*27162e4eSAndroid Build Coastguard Worker     ret = LZ4F_readOpen(&lz4fRead, f_in);
100*27162e4eSAndroid Build Coastguard Worker     if (LZ4F_isError(ret)) {
101*27162e4eSAndroid Build Coastguard Worker         printf("LZ4F_readOpen error: %s\n", LZ4F_getErrorName(ret));
102*27162e4eSAndroid Build Coastguard Worker         free(buf);
103*27162e4eSAndroid Build Coastguard Worker         return 1;
104*27162e4eSAndroid Build Coastguard Worker     }
105*27162e4eSAndroid Build Coastguard Worker 
106*27162e4eSAndroid Build Coastguard Worker     while (1) {
107*27162e4eSAndroid Build Coastguard Worker         ret = LZ4F_read(lz4fRead, buf, CHUNK_SIZE);
108*27162e4eSAndroid Build Coastguard Worker         if (LZ4F_isError(ret)) {
109*27162e4eSAndroid Build Coastguard Worker             printf("LZ4F_read error: %s\n", LZ4F_getErrorName(ret));
110*27162e4eSAndroid Build Coastguard Worker             goto out;
111*27162e4eSAndroid Build Coastguard Worker         }
112*27162e4eSAndroid Build Coastguard Worker 
113*27162e4eSAndroid Build Coastguard Worker         /* nothing to read */
114*27162e4eSAndroid Build Coastguard Worker         if (ret == 0) {
115*27162e4eSAndroid Build Coastguard Worker             break;
116*27162e4eSAndroid Build Coastguard Worker         }
117*27162e4eSAndroid Build Coastguard Worker 
118*27162e4eSAndroid Build Coastguard Worker         if(fwrite(buf, 1, ret, f_out) != ret) {
119*27162e4eSAndroid Build Coastguard Worker             printf("write error!\n");
120*27162e4eSAndroid Build Coastguard Worker             goto out;
121*27162e4eSAndroid Build Coastguard Worker         }
122*27162e4eSAndroid Build Coastguard Worker     }
123*27162e4eSAndroid Build Coastguard Worker 
124*27162e4eSAndroid Build Coastguard Worker out:
125*27162e4eSAndroid Build Coastguard Worker     free(buf);
126*27162e4eSAndroid Build Coastguard Worker     if (LZ4F_isError(LZ4F_readClose(lz4fRead))) {
127*27162e4eSAndroid Build Coastguard Worker         printf("LZ4F_readClose: %s\n", LZ4F_getErrorName(ret));
128*27162e4eSAndroid Build Coastguard Worker         return 1;
129*27162e4eSAndroid Build Coastguard Worker     }
130*27162e4eSAndroid Build Coastguard Worker 
131*27162e4eSAndroid Build Coastguard Worker     if (ret) {
132*27162e4eSAndroid Build Coastguard Worker         return 1;
133*27162e4eSAndroid Build Coastguard Worker     }
134*27162e4eSAndroid Build Coastguard Worker 
135*27162e4eSAndroid Build Coastguard Worker     return 0;
136*27162e4eSAndroid Build Coastguard Worker }
137*27162e4eSAndroid Build Coastguard Worker 
compareFiles(FILE * fp0,FILE * fp1)138*27162e4eSAndroid Build Coastguard Worker int compareFiles(FILE* fp0, FILE* fp1)
139*27162e4eSAndroid Build Coastguard Worker {
140*27162e4eSAndroid Build Coastguard Worker     int result = 0;
141*27162e4eSAndroid Build Coastguard Worker 
142*27162e4eSAndroid Build Coastguard Worker     while (result==0) {
143*27162e4eSAndroid Build Coastguard Worker         char b0[1024];
144*27162e4eSAndroid Build Coastguard Worker         char b1[1024];
145*27162e4eSAndroid Build Coastguard Worker         size_t const r0 = fread(b0, 1, sizeof(b0), fp0);
146*27162e4eSAndroid Build Coastguard Worker         size_t const r1 = fread(b1, 1, sizeof(b1), fp1);
147*27162e4eSAndroid Build Coastguard Worker 
148*27162e4eSAndroid Build Coastguard Worker         result = (r0 != r1);
149*27162e4eSAndroid Build Coastguard Worker         if (!r0 || !r1) break;
150*27162e4eSAndroid Build Coastguard Worker         if (!result) result = memcmp(b0, b1, r0);
151*27162e4eSAndroid Build Coastguard Worker     }
152*27162e4eSAndroid Build Coastguard Worker 
153*27162e4eSAndroid Build Coastguard Worker     return result;
154*27162e4eSAndroid Build Coastguard Worker }
155*27162e4eSAndroid Build Coastguard Worker 
main(int argc,const char ** argv)156*27162e4eSAndroid Build Coastguard Worker int main(int argc, const char **argv) {
157*27162e4eSAndroid Build Coastguard Worker     char inpFilename[256] = { 0 };
158*27162e4eSAndroid Build Coastguard Worker     char lz4Filename[256] = { 0 };
159*27162e4eSAndroid Build Coastguard Worker     char decFilename[256] = { 0 };
160*27162e4eSAndroid Build Coastguard Worker 
161*27162e4eSAndroid Build Coastguard Worker     if (argc < 2) {
162*27162e4eSAndroid Build Coastguard Worker         printf("Please specify input filename\n");
163*27162e4eSAndroid Build Coastguard Worker         return 0;
164*27162e4eSAndroid Build Coastguard Worker     }
165*27162e4eSAndroid Build Coastguard Worker 
166*27162e4eSAndroid Build Coastguard Worker     snprintf(inpFilename, 256, "%s", argv[1]);
167*27162e4eSAndroid Build Coastguard Worker     snprintf(lz4Filename, 256, "%s.lz4", argv[1]);
168*27162e4eSAndroid Build Coastguard Worker     snprintf(decFilename, 256, "%s.lz4.dec", argv[1]);
169*27162e4eSAndroid Build Coastguard Worker 
170*27162e4eSAndroid Build Coastguard Worker     printf("inp = [%s]\n", inpFilename);
171*27162e4eSAndroid Build Coastguard Worker     printf("lz4 = [%s]\n", lz4Filename);
172*27162e4eSAndroid Build Coastguard Worker     printf("dec = [%s]\n", decFilename);
173*27162e4eSAndroid Build Coastguard Worker 
174*27162e4eSAndroid Build Coastguard Worker     /* compress */
175*27162e4eSAndroid Build Coastguard Worker     {   FILE* const inpFp = fopen(inpFilename, "rb");
176*27162e4eSAndroid Build Coastguard Worker         FILE* const outFp = fopen(lz4Filename, "wb");
177*27162e4eSAndroid Build Coastguard Worker         printf("compress : %s -> %s\n", inpFilename, lz4Filename);
178*27162e4eSAndroid Build Coastguard Worker         LZ4F_errorCode_t ret = compress_file(inpFp, outFp);
179*27162e4eSAndroid Build Coastguard Worker         fclose(inpFp);
180*27162e4eSAndroid Build Coastguard Worker         fclose(outFp);
181*27162e4eSAndroid Build Coastguard Worker 
182*27162e4eSAndroid Build Coastguard Worker         if (ret) {
183*27162e4eSAndroid Build Coastguard Worker             printf("compression error: %s\n", LZ4F_getErrorName(ret));
184*27162e4eSAndroid Build Coastguard Worker             return 1;
185*27162e4eSAndroid Build Coastguard Worker         }
186*27162e4eSAndroid Build Coastguard Worker 
187*27162e4eSAndroid Build Coastguard Worker         printf("%s: %zu → %zu bytes, %.1f%%\n",
188*27162e4eSAndroid Build Coastguard Worker             inpFilename,
189*27162e4eSAndroid Build Coastguard Worker             get_file_size(inpFilename),
190*27162e4eSAndroid Build Coastguard Worker             get_file_size(lz4Filename), /* might overflow is size_t is 32 bits and size_{in,out} > 4 GB */
191*27162e4eSAndroid Build Coastguard Worker             (double)get_file_size(lz4Filename) / get_file_size(inpFilename) * 100);
192*27162e4eSAndroid Build Coastguard Worker 
193*27162e4eSAndroid Build Coastguard Worker         printf("compress : done\n");
194*27162e4eSAndroid Build Coastguard Worker     }
195*27162e4eSAndroid Build Coastguard Worker 
196*27162e4eSAndroid Build Coastguard Worker     /* decompress */
197*27162e4eSAndroid Build Coastguard Worker     {
198*27162e4eSAndroid Build Coastguard Worker         FILE* const inpFp = fopen(lz4Filename, "rb");
199*27162e4eSAndroid Build Coastguard Worker         FILE* const outFp = fopen(decFilename, "wb");
200*27162e4eSAndroid Build Coastguard Worker 
201*27162e4eSAndroid Build Coastguard Worker         printf("decompress : %s -> %s\n", lz4Filename, decFilename);
202*27162e4eSAndroid Build Coastguard Worker         LZ4F_errorCode_t ret = decompress_file(inpFp, outFp);
203*27162e4eSAndroid Build Coastguard Worker 
204*27162e4eSAndroid Build Coastguard Worker         fclose(outFp);
205*27162e4eSAndroid Build Coastguard Worker         fclose(inpFp);
206*27162e4eSAndroid Build Coastguard Worker 
207*27162e4eSAndroid Build Coastguard Worker         if (ret) {
208*27162e4eSAndroid Build Coastguard Worker             printf("compression error: %s\n", LZ4F_getErrorName(ret));
209*27162e4eSAndroid Build Coastguard Worker             return 1;
210*27162e4eSAndroid Build Coastguard Worker         }
211*27162e4eSAndroid Build Coastguard Worker 
212*27162e4eSAndroid Build Coastguard Worker         printf("decompress : done\n");
213*27162e4eSAndroid Build Coastguard Worker     }
214*27162e4eSAndroid Build Coastguard Worker 
215*27162e4eSAndroid Build Coastguard Worker     /* verify */
216*27162e4eSAndroid Build Coastguard Worker     {   FILE* const inpFp = fopen(inpFilename, "rb");
217*27162e4eSAndroid Build Coastguard Worker         FILE* const decFp = fopen(decFilename, "rb");
218*27162e4eSAndroid Build Coastguard Worker 
219*27162e4eSAndroid Build Coastguard Worker         printf("verify : %s <-> %s\n", inpFilename, decFilename);
220*27162e4eSAndroid Build Coastguard Worker         int const cmp = compareFiles(inpFp, decFp);
221*27162e4eSAndroid Build Coastguard Worker 
222*27162e4eSAndroid Build Coastguard Worker         fclose(decFp);
223*27162e4eSAndroid Build Coastguard Worker         fclose(inpFp);
224*27162e4eSAndroid Build Coastguard Worker 
225*27162e4eSAndroid Build Coastguard Worker         if (cmp) {
226*27162e4eSAndroid Build Coastguard Worker             printf("corruption detected : decompressed file differs from original\n");
227*27162e4eSAndroid Build Coastguard Worker             return cmp;
228*27162e4eSAndroid Build Coastguard Worker         }
229*27162e4eSAndroid Build Coastguard Worker 
230*27162e4eSAndroid Build Coastguard Worker         printf("verify : OK\n");
231*27162e4eSAndroid Build Coastguard Worker     }
232*27162e4eSAndroid Build Coastguard Worker 
233*27162e4eSAndroid Build Coastguard Worker }
234