SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
SDDS_lzma.c File Reference

Detailed Description

Implementation of LZMA-compressed file handling functions.

This file provides a set of functions to work with files compressed using the LZMA compression algorithm. It abstracts the complexities of LZMA stream handling, offering a simple file-like interface for reading from and writing to compressed files.

Features:

  • Open and close LZMA-compressed files.
  • Read and write data with automatic compression/decompression.
  • Support for reading lines and formatted output.
  • Error handling with descriptive messages.
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Authors
R. Soliday

Definition in file SDDS_lzma.c.

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
#include <lzma.h>

Go to the source code of this file.

Functions

void * lzma_open (const char *path, const char *mode)
 
int lzma_close (struct lzmafile *file)
 
long lzma_read (struct lzmafile *file, void *buf, size_t count)
 
char * lzma_gets (char *s, int size, struct lzmafile *file)
 
long lzma_write (struct lzmafile *file, const void *buf, size_t count)
 
int lzma_puts (const char *s, struct lzmafile *file)
 
int lzma_putc (int c, struct lzmafile *file)
 
int lzma_printf (struct lzmafile *file, const char *format,...)
 
int lzma_eof (struct lzmafile *file)
 
long lzma_tell (struct lzmafile *file)
 
int lzma_seek (struct lzmafile *file, long offset, int whence)
 
void * UnpackLZMAOpen (char *filename)
 

Function Documentation

◆ lzma_close()

int lzma_close ( struct lzmafile * file)

Definition at line 100 of file SDDS_lzma.c.

100 {
101 int ret, outsize;
102 unsigned char buf[BUF_SIZE]; /* buffer used when flushing remaining
103 output data in write mode */
104 if (!file)
105 return -1;
106 if (file->mode == 'w') {
107 /* flush LZMA output buffer */
108 for (;;) {
109 file->str.next_out = buf;
110 file->str.avail_out = BUF_SIZE;
111 ret = lzma_code(&file->str, LZMA_FINISH);
112 if (ret != LZMA_STREAM_END && ret != LZMA_OK) {
113 fprintf(stderr, "lzma_close error: encoding failed: %d\n", ret);
114 lzma_end(&file->str);
115 fclose(file->fp);
116 free(file);
117 return EOF;
118 }
119 outsize = BUF_SIZE - file->str.avail_out;
120 if (fwrite(buf, 1, outsize, file->fp) != outsize) {
121 lzma_end(&file->str);
122 fclose(file->fp);
123 free(file);
124 return EOF;
125 }
126 if (ret == LZMA_STREAM_END)
127 break;
128 }
129 }
130 lzma_end(&file->str);
131 ret = fclose(file->fp);
132 free(file);
133 return ret;
134}

◆ lzma_eof()

int lzma_eof ( struct lzmafile * file)

Definition at line 379 of file SDDS_lzma.c.

379 {
380 lzma_stream *lstr;
381 lstr = &file->str;
382 if (lstr->avail_in == 0) {
383 return feof(file->fp);
384 } else {
385 return 0;
386 }
387}

◆ lzma_gets()

char * lzma_gets ( char * s,
int size,
struct lzmafile * file )

Definition at line 181 of file SDDS_lzma.c.

181 {
182 int ret;
183 int i = 0;
184 lzma_stream *lstr;
185 if (file->mode != 'r')
186 return NULL;
187 if (s == NULL || size < 1)
188 return NULL;
189 s[0] = '\0';
190 lstr = &file->str;
191 lstr->next_out = (void *)s;
192
193 /* decompress until newline or EOF or output buffer is full */
194 while (1) {
195 if (lstr->avail_in == 0) {
196 /* refill input buffer */
197 ret = fread(file->rdbuf, 1, BUF_SIZE, file->fp);
198 if (ret == 0) {
199 break; /* EOF */
200 }
201 lstr->next_in = file->rdbuf; /* buffer containing lzma data just read */
202 lstr->avail_in = ret; /* number of bytes read */
203 }
204 if (i + 1 == size) {
205 s[i] = '\0';
206 break;
207 }
208 lstr->avail_out = 1;
209 ret = lzma_code(lstr, LZMA_RUN);
210 /* this fills up lstr->next_out and decreases lstr->avail_out */
211 /* it also emptys lstr->next_in and decreases lstr->avail_in */
212 if (ret != LZMA_OK && ret != LZMA_STREAM_END) {
213 fprintf(stderr, "lzma_gets error: decoding failed: %d\n", ret);
214 return NULL;
215 }
216 if (ret == LZMA_STREAM_END) { /* EOF */
217 s[i + 1] = '\0';
218 break;
219 }
220 if (s[i] == 10) { /* 10 is the value for \n */
221 if (i > 0) { /* we sometimes get \10\10 */
222 if ((i == 1) && (s[0] == 32)) {
223 /* when uncompressing the lzma stream we some times end
224 up with \10\32\10 instead of a simple \10 */
225 } else {
226 s[i + 1] = '\0';
227 break;
228 }
229 }
230 }
231 i++;
232 }
233 return s;
234}

◆ lzma_open()

void * lzma_open ( const char * path,
const char * mode )

Definition at line 70 of file SDDS_lzma.c.

70 {
71 int ret;
72
73 /* initialize LZMA stream */
74 struct lzmafile *lf = malloc(sizeof(struct lzmafile));
75 lf->fp = fopen(path, mode);
76 lf->str = lzma_stream_init;
77 lf->mode = mode[0];
78 if (mode[0] == 'r') {
79#if LZMA_VERSION <= UINT32_C(49990030)
80 ret = lzma_auto_decoder(&lf->str, NULL, NULL);
81#else
82 ret = lzma_auto_decoder(&lf->str, -1, 0);
83#endif
84 lf->str.avail_in = 0;
85 } else {
86 /* I decided to use level 2 encoding */
87 /* Perhaps this should be user configurable in an environment variable */
88 ret = LZMA_EASY_ENCODER(&lf->str, 2);
89 }
90 if (ret != LZMA_OK) {
91 fprintf(stderr, "lzma_open error: %d\n", ret);
92 return NULL;
93 }
94 return (void *)lf;
95}

◆ lzma_printf()

int lzma_printf ( struct lzmafile * file,
const char * format,
... )

Definition at line 356 of file SDDS_lzma.c.

356 {
357 size_t size = 32768;
358 int len;
359 unsigned char in[32768];
360 va_list va;
361 va_start(va, format);
362
363 in[size - 1] = 0;
364 (void)vsnprintf((char *)in, size, format, va);
365 va_end(va);
366 len = strlen((char *)in);
367
368 /* check that printf() results fit in buffer */
369 if (len <= 0 || len >= (int)size || in[size - 1] != 0) {
370 fprintf(stderr, "lzma_printf error: the printf results do not fit in the buffer\n");
371 return -1;
372 }
373 in[len] = '\0';
374 len = lzma_write(file, in, len);
375
376 return len;
377}

◆ lzma_putc()

int lzma_putc ( int c,
struct lzmafile * file )

Definition at line 320 of file SDDS_lzma.c.

320 {
321 int ret;
322 lzma_stream *lstr = &file->str;
323
324 unsigned char bufout[1]; /* compressed output buffer */
325 char buf[1];
326
327 if (file->mode != 'w') {
328 fprintf(stderr, "lzma_putc error: file was not opened for writting\n");
329 return EOF;
330 }
331 buf[0] = c;
332
333 lstr->next_in = (void *)buf;
334 lstr->avail_in = 1;
335 while (lstr->avail_in) {
336 lstr->next_out = bufout;
337 lstr->avail_out = 1;
338 ret = lzma_code(lstr, LZMA_RUN);
339 if (ret != LZMA_OK) {
340 fprintf(stderr, "lzma_putc error: encoding failed: %d\n", ret);
341 return EOF;
342 }
343 ret = fwrite(bufout, 1, 1 - lstr->avail_out, file->fp);
344 if (ret != 1 - lstr->avail_out) {
345 fprintf(stderr, "lzma_putc error\n");
346 return EOF;
347 }
348 }
349 return (unsigned char)c;
350}

◆ lzma_puts()

int lzma_puts ( const char * s,
struct lzmafile * file )

Definition at line 275 of file SDDS_lzma.c.

275 {
276 int ret;
277 lzma_stream *lstr = &file->str;
278 int count;
279 unsigned char *bufout; /* compressed output buffer */
280 char *buf;
281
282 if (file->mode != 'w') {
283 fprintf(stderr, "lzma_puts error: file was not opened for writting\n");
284 return EOF;
285 }
286 count = strlen(s);
287 bufout = malloc(sizeof(unsigned char) * count);
288 buf = malloc(sizeof(char) * count);
289 //strncpy(buf, s, count);
290 memcpy(buf, s, count);
291
292 lstr->next_in = (void *)buf;
293 lstr->avail_in = count;
294 while (lstr->avail_in) {
295 lstr->next_out = bufout;
296 lstr->avail_out = count;
297 ret = lzma_code(lstr, LZMA_RUN);
298 if (ret != LZMA_OK) {
299 fprintf(stderr, "lzma_puts error: encoding failed: %d\n", ret);
300 free(bufout);
301 free(buf);
302 return EOF;
303 }
304 ret = fwrite(bufout, 1, count - lstr->avail_out, file->fp);
305 if (ret != count - lstr->avail_out) {
306 fprintf(stderr, "lzma_puts error\n");
307 free(bufout);
308 free(buf);
309 return EOF;
310 }
311 }
312 free(bufout);
313 free(buf);
314 return count;
315}

◆ lzma_read()

long lzma_read ( struct lzmafile * file,
void * buf,
size_t count )

Definition at line 140 of file SDDS_lzma.c.

140 {
141 int ret;
142 lzma_stream *lstr;
143 if (file->mode != 'r')
144 return -1;
145
146 lstr = &file->str;
147 lstr->next_out = buf;
148 lstr->avail_out = count;
149
150 /* decompress until EOF or output buffer is full */
151 while (lstr->avail_out) {
152 if (lstr->avail_in == 0) {
153 /* refill input buffer */
154 ret = fread(file->rdbuf, 1, BUF_SIZE, file->fp);
155 if (ret == 0) {
156 break; /* EOF */
157 }
158 lstr->next_in = file->rdbuf; /* buffer containing lzma data just read */
159 lstr->avail_in = ret; /* number of bytes read */
160 }
161 ret = lzma_code(lstr, LZMA_RUN);
162 /* this fills up lstr->next_out and decreases lstr->avail_out */
163 /* it also emptys lstr->next_in and decreases lstr->avail_in */
164 if (ret != LZMA_OK && ret != LZMA_STREAM_END) {
165 fprintf(stderr, "lzma_read error: decoding failed: %d\n", ret);
166 return -1;
167 }
168 if (ret == LZMA_STREAM_END) {
169 break; /* EOF */
170 }
171 }
172 return count - lstr->avail_out; /* length of buf that has valid data */
173}

◆ lzma_seek()

int lzma_seek ( struct lzmafile * file,
long offset,
int whence )

Definition at line 398 of file SDDS_lzma.c.

398 {
399 return fseek(file->fp, offset, whence);
400}

◆ lzma_tell()

long lzma_tell ( struct lzmafile * file)

Definition at line 394 of file SDDS_lzma.c.

394 {
395 return ftell(file->fp);
396}

◆ lzma_write()

long lzma_write ( struct lzmafile * file,
const void * buf,
size_t count )

Definition at line 239 of file SDDS_lzma.c.

239 {
240 int ret;
241 lzma_stream *lstr = &file->str;
242 unsigned char *bufout; /* compressed output buffer */
243 bufout = malloc(sizeof(char) * count);
244
245 if (file->mode != 'w') {
246 fprintf(stderr, "lzma_write error: file was not opened for writting\n");
247 free(bufout);
248 return -1;
249 }
250 lstr->next_in = buf;
251 lstr->avail_in = count;
252 while (lstr->avail_in) {
253 lstr->next_out = bufout;
254 lstr->avail_out = count;
255 ret = lzma_code(lstr, LZMA_RUN);
256 if (ret != LZMA_OK) {
257 fprintf(stderr, "lzma_write error: encoding failed: %d\n", ret);
258 free(bufout);
259 return -1;
260 }
261 ret = fwrite(bufout, 1, count - lstr->avail_out, file->fp);
262 if (ret != count - lstr->avail_out) {
263 fprintf(stderr, "lzma_write error\n");
264 free(bufout);
265 return -1;
266 }
267 }
268 free(bufout);
269 return count;
270}

◆ UnpackLZMAOpen()

void * UnpackLZMAOpen ( char * filename)

Definition at line 402 of file SDDS_lzma.c.

402 {
403 if (!filename)
404 return NULL;
405 return lzma_open(filename, "rb");
406}