diff options
Diffstat (limited to '')
-rw-r--r-- | doc/examples/01_compress_easy.c | 7 | ||||
-rw-r--r-- | doc/examples/02_decompress.c | 5 | ||||
-rw-r--r-- | doc/examples/03_compress_custom.c | 5 | ||||
-rw-r--r-- | doc/examples/04_compress_easy_mt.c | 5 | ||||
-rw-r--r-- | doc/examples/11_file_info.c | 205 | ||||
-rw-r--r-- | doc/examples/Makefile | 6 | ||||
-rw-r--r-- | doc/examples_old/xz_pipe_comp.c | 127 | ||||
-rw-r--r-- | doc/examples_old/xz_pipe_decomp.c | 123 |
8 files changed, 215 insertions, 268 deletions
diff --git a/doc/examples/01_compress_easy.c b/doc/examples/01_compress_easy.c index ec32a37..31bcf92 100644 --- a/doc/examples/01_compress_easy.c +++ b/doc/examples/01_compress_easy.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: 0BSD + /////////////////////////////////////////////////////////////////////////////// // /// \file 01_compress_easy.c @@ -9,9 +11,6 @@ // // Author: Lasse Collin // -// This file has been put into the public domain. -// You can do whatever you want with this file. -// /////////////////////////////////////////////////////////////////////////////// #include <stdbool.h> @@ -27,7 +26,7 @@ show_usage_and_exit(const char *argv0) { fprintf(stderr, "Usage: %s PRESET < INFILE > OUTFILE\n" "PRESET is a number 0-9 and can optionally be " - "followed by `e' to indicate extreme preset\n", + "followed by 'e' to indicate extreme preset\n", argv0); exit(EXIT_FAILURE); } diff --git a/doc/examples/02_decompress.c b/doc/examples/02_decompress.c index 98339be..a87a5d3 100644 --- a/doc/examples/02_decompress.c +++ b/doc/examples/02_decompress.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: 0BSD + /////////////////////////////////////////////////////////////////////////////// // /// \file 02_decompress.c @@ -9,9 +11,6 @@ // // Author: Lasse Collin // -// This file has been put into the public domain. -// You can do whatever you want with this file. -// /////////////////////////////////////////////////////////////////////////////// #include <stdbool.h> diff --git a/doc/examples/03_compress_custom.c b/doc/examples/03_compress_custom.c index 40c85e3..57797b8 100644 --- a/doc/examples/03_compress_custom.c +++ b/doc/examples/03_compress_custom.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: 0BSD + /////////////////////////////////////////////////////////////////////////////// // /// \file 03_compress_custom.c @@ -9,9 +11,6 @@ // // Author: Lasse Collin // -// This file has been put into the public domain. -// You can do whatever you want with this file. -// /////////////////////////////////////////////////////////////////////////////// #include <stdbool.h> diff --git a/doc/examples/04_compress_easy_mt.c b/doc/examples/04_compress_easy_mt.c index efe5697..c721a66 100644 --- a/doc/examples/04_compress_easy_mt.c +++ b/doc/examples/04_compress_easy_mt.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: 0BSD + /////////////////////////////////////////////////////////////////////////////// // /// \file 04_compress_easy_mt.c @@ -9,9 +11,6 @@ // // Author: Lasse Collin // -// This file has been put into the public domain. -// You can do whatever you want with this file. -// /////////////////////////////////////////////////////////////////////////////// #include <stdbool.h> diff --git a/doc/examples/11_file_info.c b/doc/examples/11_file_info.c new file mode 100644 index 0000000..caadd98 --- /dev/null +++ b/doc/examples/11_file_info.c @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: 0BSD + +/////////////////////////////////////////////////////////////////////////////// +// +/// \file 11_file_info.c +/// \brief Get uncompressed size of .xz file(s) +/// +/// Usage: ./11_file_info INFILE1.xz [INFILEn.xz]... +/// +/// Example: ./11_file_info foo.xz +// +// Author: Lasse Collin +// +/////////////////////////////////////////////////////////////////////////////// + +#include <stdbool.h> +#include <inttypes.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <lzma.h> + + +static bool +print_file_size(lzma_stream *strm, FILE *infile, const char *filename) +{ + // Get the file size. In standard C it can be done by seeking to + // the end of the file and then getting the file position. + // In POSIX one can use fstat() and then st_size from struct stat. + // Also note that fseek() and ftell() use long and thus don't support + // large files on 32-bit systems (POSIX versions fseeko() and + // ftello() can support large files). + if (fseek(infile, 0, SEEK_END)) { + fprintf(stderr, "Error seeking the file '%s': %s\n", + filename, strerror(errno)); + return false; + } + + const long file_size = ftell(infile); + + // The decoder wants to start from the beginning of the .xz file. + rewind(infile); + + // Initialize the decoder. + lzma_index *i; + lzma_ret ret = lzma_file_info_decoder(strm, &i, UINT64_MAX, + (uint64_t)file_size); + switch (ret) { + case LZMA_OK: + // Initialization succeeded. + break; + + case LZMA_MEM_ERROR: + fprintf(stderr, "Out of memory when initializing " + "the .xz file info decoder\n"); + return false; + + case LZMA_PROG_ERROR: + default: + fprintf(stderr, "Unknown error, possibly a bug\n"); + return false; + } + + // This example program reuses the same lzma_stream structure + // for multiple files, so we need to reset this when starting + // a new file. + strm->avail_in = 0; + + // Buffer for input data. + uint8_t inbuf[BUFSIZ]; + + // Pass data to the decoder and seek when needed. + while (true) { + if (strm->avail_in == 0) { + strm->next_in = inbuf; + strm->avail_in = fread(inbuf, 1, sizeof(inbuf), + infile); + + if (ferror(infile)) { + fprintf(stderr, + "Error reading from '%s': %s\n", + filename, strerror(errno)); + return false; + } + + // We don't need to care about hitting the end of + // the file so no need to check for feof(). + } + + ret = lzma_code(strm, LZMA_RUN); + + switch (ret) { + case LZMA_OK: + break; + + case LZMA_SEEK_NEEDED: + // The cast is safe because liblzma won't ask us to + // seek past the known size of the input file which + // did fit into a long. + // + // NOTE: Remember to change these to off_t if you + // switch fseeko() or lseek(). + if (fseek(infile, (long)(strm->seek_pos), SEEK_SET)) { + fprintf(stderr, "Error seeking the " + "file '%s': %s\n", + filename, strerror(errno)); + return false; + } + + // The old data in the inbuf is useless now. Set + // avail_in to zero so that we will read new input + // from the new file position on the next iteration + // of this loop. + strm->avail_in = 0; + break; + + case LZMA_STREAM_END: + // File information was successfully decoded. + // See <lzma/index.h> for functions that can be + // used on it. In this example we just print + // the uncompressed size (in bytes) of + // the .xz file followed by its file name. + printf("%10" PRIu64 " %s\n", + lzma_index_uncompressed_size(i), + filename); + + // Free the memory of the lzma_index structure. + lzma_index_end(i, NULL); + + return true; + + case LZMA_FORMAT_ERROR: + // .xz magic bytes weren't found. + fprintf(stderr, "The file '%s' is not " + "in the .xz format\n", filename); + return false; + + case LZMA_OPTIONS_ERROR: + fprintf(stderr, "The file '%s' has .xz headers that " + "are not supported by this liblzma " + "version\n", filename); + return false; + + case LZMA_DATA_ERROR: + fprintf(stderr, "The file '%s' is corrupt\n", + filename); + return false; + + case LZMA_MEM_ERROR: + fprintf(stderr, "Memory allocation failed when " + "decoding the file '%s'\n", filename); + return false; + + // LZMA_MEMLIMIT_ERROR shouldn't happen because we used + // UINT64_MAX as the limit. + // + // LZMA_BUF_ERROR shouldn't happen because we always provide + // new input when the input buffer is empty. The decoder + // knows the input file size and thus won't try to read past + // the end of the file. + case LZMA_MEMLIMIT_ERROR: + case LZMA_BUF_ERROR: + case LZMA_PROG_ERROR: + default: + fprintf(stderr, "Unknown error, possibly a bug\n"); + return false; + } + } + + // This line is never reached. +} + + +extern int +main(int argc, char **argv) +{ + bool success = true; + lzma_stream strm = LZMA_STREAM_INIT; + + for (int i = 1; i < argc; ++i) { + FILE *infile = fopen(argv[i], "rb"); + + if (infile == NULL) { + fprintf(stderr, "Cannot open the file '%s': %s\n", + argv[i], strerror(errno)); + success = false; + } + + success &= print_file_size(&strm, infile, argv[i]); + + (void)fclose(infile); + } + + lzma_end(&strm); + + // Close stdout to catch possible write errors that can occur + // when pending data is flushed from the stdio buffers. + if (fclose(stdout)) { + fprintf(stderr, "Write error: %s\n", strerror(errno)); + success = false; + } + + return success ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/doc/examples/Makefile b/doc/examples/Makefile index e8839d8..f5b9878 100644 --- a/doc/examples/Makefile +++ b/doc/examples/Makefile @@ -1,9 +1,5 @@ -# +# SPDX-License-Identifier: 0BSD # Author: Lasse Collin -# -# This file has been put into the public domain. -# You can do whatever you want with this file. -# CC = c99 CFLAGS = -g diff --git a/doc/examples_old/xz_pipe_comp.c b/doc/examples_old/xz_pipe_comp.c deleted file mode 100644 index 9f9224b..0000000 --- a/doc/examples_old/xz_pipe_comp.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * xz_pipe_comp.c - * A simple example of pipe-only xz compressor implementation. - * version: 2010-07-12 - by Daniel Mealha Cabrita - * Not copyrighted -- provided to the public domain. - * - * Compiling: - * Link with liblzma. GCC example: - * $ gcc -llzma xz_pipe_comp.c -o xz_pipe_comp - * - * Usage example: - * $ cat some_file | ./xz_pipe_comp > some_file.xz - */ - -#include <stdio.h> -#include <stdint.h> -#include <inttypes.h> -#include <stdbool.h> -#include <lzma.h> - - -/* COMPRESSION SETTINGS */ - -/* analogous to xz CLI options: -0 to -9 */ -#define COMPRESSION_LEVEL 6 - -/* boolean setting, analogous to xz CLI option: -e */ -#define COMPRESSION_EXTREME true - -/* see: /usr/include/lzma/check.h LZMA_CHECK_* */ -#define INTEGRITY_CHECK LZMA_CHECK_CRC64 - - -/* read/write buffer sizes */ -#define IN_BUF_MAX 4096 -#define OUT_BUF_MAX 4096 - -/* error codes */ -#define RET_OK 0 -#define RET_ERROR_INIT 1 -#define RET_ERROR_INPUT 2 -#define RET_ERROR_OUTPUT 3 -#define RET_ERROR_COMPRESSION 4 - - -/* note: in_file and out_file must be open already */ -int xz_compress (FILE *in_file, FILE *out_file) -{ - uint32_t preset = COMPRESSION_LEVEL | (COMPRESSION_EXTREME ? LZMA_PRESET_EXTREME : 0); - lzma_check check = INTEGRITY_CHECK; - lzma_stream strm = LZMA_STREAM_INIT; /* alloc and init lzma_stream struct */ - uint8_t in_buf [IN_BUF_MAX]; - uint8_t out_buf [OUT_BUF_MAX]; - size_t in_len; /* length of useful data in in_buf */ - size_t out_len; /* length of useful data in out_buf */ - bool in_finished = false; - bool out_finished = false; - lzma_action action; - lzma_ret ret_xz; - int ret; - - ret = RET_OK; - - /* initialize xz encoder */ - ret_xz = lzma_easy_encoder (&strm, preset, check); - if (ret_xz != LZMA_OK) { - fprintf (stderr, "lzma_easy_encoder error: %d\n", (int) ret_xz); - return RET_ERROR_INIT; - } - - while ((! in_finished) && (! out_finished)) { - /* read incoming data */ - in_len = fread (in_buf, 1, IN_BUF_MAX, in_file); - - if (feof (in_file)) { - in_finished = true; - } - if (ferror (in_file)) { - in_finished = true; - ret = RET_ERROR_INPUT; - } - - strm.next_in = in_buf; - strm.avail_in = in_len; - - /* if no more data from in_buf, flushes the - internal xz buffers and closes the xz data - with LZMA_FINISH */ - action = in_finished ? LZMA_FINISH : LZMA_RUN; - - /* loop until there's no pending compressed output */ - do { - /* out_buf is clean at this point */ - strm.next_out = out_buf; - strm.avail_out = OUT_BUF_MAX; - - /* compress data */ - ret_xz = lzma_code (&strm, action); - - if ((ret_xz != LZMA_OK) && (ret_xz != LZMA_STREAM_END)) { - fprintf (stderr, "lzma_code error: %d\n", (int) ret_xz); - out_finished = true; - ret = RET_ERROR_COMPRESSION; - } else { - /* write compressed data */ - out_len = OUT_BUF_MAX - strm.avail_out; - fwrite (out_buf, 1, out_len, out_file); - if (ferror (out_file)) { - out_finished = true; - ret = RET_ERROR_OUTPUT; - } - } - } while (strm.avail_out == 0); - } - - lzma_end (&strm); - return ret; -} - -int main () -{ - int ret; - - ret = xz_compress (stdin, stdout); - return ret; -} - diff --git a/doc/examples_old/xz_pipe_decomp.c b/doc/examples_old/xz_pipe_decomp.c deleted file mode 100644 index fb5ad89..0000000 --- a/doc/examples_old/xz_pipe_decomp.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * xz_pipe_decomp.c - * A simple example of pipe-only xz decompressor implementation. - * version: 2012-06-14 - by Daniel Mealha Cabrita - * Not copyrighted -- provided to the public domain. - * - * Compiling: - * Link with liblzma. GCC example: - * $ gcc -llzma xz_pipe_decomp.c -o xz_pipe_decomp - * - * Usage example: - * $ cat some_file.xz | ./xz_pipe_decomp > some_file - */ - -#include <stdio.h> -#include <stdint.h> -#include <inttypes.h> -#include <stdbool.h> -#include <lzma.h> - - -/* read/write buffer sizes */ -#define IN_BUF_MAX 4096 -#define OUT_BUF_MAX 4096 - -/* error codes */ -#define RET_OK 0 -#define RET_ERROR_INIT 1 -#define RET_ERROR_INPUT 2 -#define RET_ERROR_OUTPUT 3 -#define RET_ERROR_DECOMPRESSION 4 - - -/* note: in_file and out_file must be open already */ -int xz_decompress (FILE *in_file, FILE *out_file) -{ - lzma_stream strm = LZMA_STREAM_INIT; /* alloc and init lzma_stream struct */ - const uint32_t flags = LZMA_TELL_UNSUPPORTED_CHECK | LZMA_CONCATENATED; - const uint64_t memory_limit = UINT64_MAX; /* no memory limit */ - uint8_t in_buf [IN_BUF_MAX]; - uint8_t out_buf [OUT_BUF_MAX]; - size_t in_len; /* length of useful data in in_buf */ - size_t out_len; /* length of useful data in out_buf */ - bool in_finished = false; - bool out_finished = false; - lzma_action action; - lzma_ret ret_xz; - int ret; - - ret = RET_OK; - - /* initialize xz decoder */ - ret_xz = lzma_stream_decoder (&strm, memory_limit, flags); - if (ret_xz != LZMA_OK) { - fprintf (stderr, "lzma_stream_decoder error: %d\n", (int) ret_xz); - return RET_ERROR_INIT; - } - - while ((! in_finished) && (! out_finished)) { - /* read incoming data */ - in_len = fread (in_buf, 1, IN_BUF_MAX, in_file); - - if (feof (in_file)) { - in_finished = true; - } - if (ferror (in_file)) { - in_finished = true; - ret = RET_ERROR_INPUT; - } - - strm.next_in = in_buf; - strm.avail_in = in_len; - - /* if no more data from in_buf, flushes the - internal xz buffers and closes the decompressed data - with LZMA_FINISH */ - action = in_finished ? LZMA_FINISH : LZMA_RUN; - - /* loop until there's no pending decompressed output */ - do { - /* out_buf is clean at this point */ - strm.next_out = out_buf; - strm.avail_out = OUT_BUF_MAX; - - /* decompress data */ - ret_xz = lzma_code (&strm, action); - - if ((ret_xz != LZMA_OK) && (ret_xz != LZMA_STREAM_END)) { - fprintf (stderr, "lzma_code error: %d\n", (int) ret_xz); - out_finished = true; - ret = RET_ERROR_DECOMPRESSION; - } else { - /* write decompressed data */ - out_len = OUT_BUF_MAX - strm.avail_out; - fwrite (out_buf, 1, out_len, out_file); - if (ferror (out_file)) { - out_finished = true; - ret = RET_ERROR_OUTPUT; - } - } - } while (strm.avail_out == 0); - } - - /* Bug fix (2012-06-14): If no errors were detected, check - that the last lzma_code() call returned LZMA_STREAM_END. - If not, the file is probably truncated. */ - if ((ret == RET_OK) && (ret_xz != LZMA_STREAM_END)) { - fprintf (stderr, "Input truncated or corrupt\n"); - ret = RET_ERROR_DECOMPRESSION; - } - - lzma_end (&strm); - return ret; -} - -int main () -{ - int ret; - - ret = xz_decompress (stdin, stdout); - return ret; -} - |