1*0a6a1f1dSLionel Sambuc /*
2*0a6a1f1dSLionel Sambuc * xz_pipe_comp.c
3*0a6a1f1dSLionel Sambuc * A simple example of pipe-only xz compressor implementation.
4*0a6a1f1dSLionel Sambuc * version: 2010-07-12 - by Daniel Mealha Cabrita
5*0a6a1f1dSLionel Sambuc * Not copyrighted -- provided to the public domain.
6*0a6a1f1dSLionel Sambuc *
7*0a6a1f1dSLionel Sambuc * Compiling:
8*0a6a1f1dSLionel Sambuc * Link with liblzma. GCC example:
9*0a6a1f1dSLionel Sambuc * $ gcc -llzma xz_pipe_comp.c -o xz_pipe_comp
10*0a6a1f1dSLionel Sambuc *
11*0a6a1f1dSLionel Sambuc * Usage example:
12*0a6a1f1dSLionel Sambuc * $ cat some_file | ./xz_pipe_comp > some_file.xz
13*0a6a1f1dSLionel Sambuc */
14*0a6a1f1dSLionel Sambuc
15*0a6a1f1dSLionel Sambuc #include <stdio.h>
16*0a6a1f1dSLionel Sambuc #include <stdint.h>
17*0a6a1f1dSLionel Sambuc #include <inttypes.h>
18*0a6a1f1dSLionel Sambuc #include <stdbool.h>
19*0a6a1f1dSLionel Sambuc #include <lzma.h>
20*0a6a1f1dSLionel Sambuc
21*0a6a1f1dSLionel Sambuc
22*0a6a1f1dSLionel Sambuc /* COMPRESSION SETTINGS */
23*0a6a1f1dSLionel Sambuc
24*0a6a1f1dSLionel Sambuc /* analogous to xz CLI options: -0 to -9 */
25*0a6a1f1dSLionel Sambuc #define COMPRESSION_LEVEL 6
26*0a6a1f1dSLionel Sambuc
27*0a6a1f1dSLionel Sambuc /* boolean setting, analogous to xz CLI option: -e */
28*0a6a1f1dSLionel Sambuc #define COMPRESSION_EXTREME true
29*0a6a1f1dSLionel Sambuc
30*0a6a1f1dSLionel Sambuc /* see: /usr/include/lzma/check.h LZMA_CHECK_* */
31*0a6a1f1dSLionel Sambuc #define INTEGRITY_CHECK LZMA_CHECK_CRC64
32*0a6a1f1dSLionel Sambuc
33*0a6a1f1dSLionel Sambuc
34*0a6a1f1dSLionel Sambuc /* read/write buffer sizes */
35*0a6a1f1dSLionel Sambuc #define IN_BUF_MAX 4096
36*0a6a1f1dSLionel Sambuc #define OUT_BUF_MAX 4096
37*0a6a1f1dSLionel Sambuc
38*0a6a1f1dSLionel Sambuc /* error codes */
39*0a6a1f1dSLionel Sambuc #define RET_OK 0
40*0a6a1f1dSLionel Sambuc #define RET_ERROR_INIT 1
41*0a6a1f1dSLionel Sambuc #define RET_ERROR_INPUT 2
42*0a6a1f1dSLionel Sambuc #define RET_ERROR_OUTPUT 3
43*0a6a1f1dSLionel Sambuc #define RET_ERROR_COMPRESSION 4
44*0a6a1f1dSLionel Sambuc
45*0a6a1f1dSLionel Sambuc
46*0a6a1f1dSLionel Sambuc /* note: in_file and out_file must be open already */
xz_compress(FILE * in_file,FILE * out_file)47*0a6a1f1dSLionel Sambuc int xz_compress (FILE *in_file, FILE *out_file)
48*0a6a1f1dSLionel Sambuc {
49*0a6a1f1dSLionel Sambuc uint32_t preset = COMPRESSION_LEVEL | (COMPRESSION_EXTREME ? LZMA_PRESET_EXTREME : 0);
50*0a6a1f1dSLionel Sambuc lzma_check check = INTEGRITY_CHECK;
51*0a6a1f1dSLionel Sambuc lzma_stream strm = LZMA_STREAM_INIT; /* alloc and init lzma_stream struct */
52*0a6a1f1dSLionel Sambuc uint8_t in_buf [IN_BUF_MAX];
53*0a6a1f1dSLionel Sambuc uint8_t out_buf [OUT_BUF_MAX];
54*0a6a1f1dSLionel Sambuc size_t in_len; /* length of useful data in in_buf */
55*0a6a1f1dSLionel Sambuc size_t out_len; /* length of useful data in out_buf */
56*0a6a1f1dSLionel Sambuc bool in_finished = false;
57*0a6a1f1dSLionel Sambuc bool out_finished = false;
58*0a6a1f1dSLionel Sambuc lzma_action action;
59*0a6a1f1dSLionel Sambuc lzma_ret ret_xz;
60*0a6a1f1dSLionel Sambuc int ret;
61*0a6a1f1dSLionel Sambuc
62*0a6a1f1dSLionel Sambuc ret = RET_OK;
63*0a6a1f1dSLionel Sambuc
64*0a6a1f1dSLionel Sambuc /* initialize xz encoder */
65*0a6a1f1dSLionel Sambuc ret_xz = lzma_easy_encoder (&strm, preset, check);
66*0a6a1f1dSLionel Sambuc if (ret_xz != LZMA_OK) {
67*0a6a1f1dSLionel Sambuc fprintf (stderr, "lzma_easy_encoder error: %d\n", (int) ret_xz);
68*0a6a1f1dSLionel Sambuc return RET_ERROR_INIT;
69*0a6a1f1dSLionel Sambuc }
70*0a6a1f1dSLionel Sambuc
71*0a6a1f1dSLionel Sambuc while ((! in_finished) && (! out_finished)) {
72*0a6a1f1dSLionel Sambuc /* read incoming data */
73*0a6a1f1dSLionel Sambuc in_len = fread (in_buf, 1, IN_BUF_MAX, in_file);
74*0a6a1f1dSLionel Sambuc
75*0a6a1f1dSLionel Sambuc if (feof (in_file)) {
76*0a6a1f1dSLionel Sambuc in_finished = true;
77*0a6a1f1dSLionel Sambuc }
78*0a6a1f1dSLionel Sambuc if (ferror (in_file)) {
79*0a6a1f1dSLionel Sambuc in_finished = true;
80*0a6a1f1dSLionel Sambuc ret = RET_ERROR_INPUT;
81*0a6a1f1dSLionel Sambuc }
82*0a6a1f1dSLionel Sambuc
83*0a6a1f1dSLionel Sambuc strm.next_in = in_buf;
84*0a6a1f1dSLionel Sambuc strm.avail_in = in_len;
85*0a6a1f1dSLionel Sambuc
86*0a6a1f1dSLionel Sambuc /* if no more data from in_buf, flushes the
87*0a6a1f1dSLionel Sambuc internal xz buffers and closes the xz data
88*0a6a1f1dSLionel Sambuc with LZMA_FINISH */
89*0a6a1f1dSLionel Sambuc action = in_finished ? LZMA_FINISH : LZMA_RUN;
90*0a6a1f1dSLionel Sambuc
91*0a6a1f1dSLionel Sambuc /* loop until there's no pending compressed output */
92*0a6a1f1dSLionel Sambuc do {
93*0a6a1f1dSLionel Sambuc /* out_buf is clean at this point */
94*0a6a1f1dSLionel Sambuc strm.next_out = out_buf;
95*0a6a1f1dSLionel Sambuc strm.avail_out = OUT_BUF_MAX;
96*0a6a1f1dSLionel Sambuc
97*0a6a1f1dSLionel Sambuc /* compress data */
98*0a6a1f1dSLionel Sambuc ret_xz = lzma_code (&strm, action);
99*0a6a1f1dSLionel Sambuc
100*0a6a1f1dSLionel Sambuc if ((ret_xz != LZMA_OK) && (ret_xz != LZMA_STREAM_END)) {
101*0a6a1f1dSLionel Sambuc fprintf (stderr, "lzma_code error: %d\n", (int) ret_xz);
102*0a6a1f1dSLionel Sambuc out_finished = true;
103*0a6a1f1dSLionel Sambuc ret = RET_ERROR_COMPRESSION;
104*0a6a1f1dSLionel Sambuc } else {
105*0a6a1f1dSLionel Sambuc /* write compressed data */
106*0a6a1f1dSLionel Sambuc out_len = OUT_BUF_MAX - strm.avail_out;
107*0a6a1f1dSLionel Sambuc fwrite (out_buf, 1, out_len, out_file);
108*0a6a1f1dSLionel Sambuc if (ferror (out_file)) {
109*0a6a1f1dSLionel Sambuc out_finished = true;
110*0a6a1f1dSLionel Sambuc ret = RET_ERROR_OUTPUT;
111*0a6a1f1dSLionel Sambuc }
112*0a6a1f1dSLionel Sambuc }
113*0a6a1f1dSLionel Sambuc } while (strm.avail_out == 0);
114*0a6a1f1dSLionel Sambuc }
115*0a6a1f1dSLionel Sambuc
116*0a6a1f1dSLionel Sambuc lzma_end (&strm);
117*0a6a1f1dSLionel Sambuc return ret;
118*0a6a1f1dSLionel Sambuc }
119*0a6a1f1dSLionel Sambuc
main()120*0a6a1f1dSLionel Sambuc int main ()
121*0a6a1f1dSLionel Sambuc {
122*0a6a1f1dSLionel Sambuc int ret;
123*0a6a1f1dSLionel Sambuc
124*0a6a1f1dSLionel Sambuc ret = xz_compress (stdin, stdout);
125*0a6a1f1dSLionel Sambuc return ret;
126*0a6a1f1dSLionel Sambuc }
127*0a6a1f1dSLionel Sambuc
128