diff options
Diffstat (limited to 'doc/examples')
-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 |
6 files changed, 215 insertions, 18 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 |