diff options
Diffstat (limited to 'src/lzma/list.c')
-rw-r--r-- | src/lzma/list.c | 477 |
1 files changed, 0 insertions, 477 deletions
diff --git a/src/lzma/list.c b/src/lzma/list.c deleted file mode 100644 index 8728d47b..00000000 --- a/src/lzma/list.c +++ /dev/null @@ -1,477 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -/// \file list.c -/// \brief Listing information about .lzma files -// -// Copyright (C) 2007 Lasse Collin -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -/////////////////////////////////////////////////////////////////////////////// - -#include "private.h" - - -/* - -1. Check the file type: native, alone, unknown - -Alone: -1. Show info about header. Don't look for concatenated parts. - -Native: -1. Check that Stream Header is valid. -2. Seek to the end of the file. -3. Skip padding. -4. Reverse decode Stream Footer. -5. Seek Backward Size bytes. -6. - -*/ - - -static void -unsupported_file(file_handle *handle) -{ - errmsg(V_ERROR, "%s: Unsupported file type", handle->name); - set_exit_status(ERROR); - (void)io_close(handle); - return; -} - - -/// Primitive escaping function, that escapes only ASCII control characters. -static void -print_escaped(const uint8_t *str) -{ - while (*str != '\0') { - if (*str <= 0x1F || *str == 0x7F) - printf("\\x%02X", *str); - else - putchar(*str); - - ++str; - } - - return; -} - - -static void -list_native(file_handle *handle) -{ - lzma_stream strm = LZMA_STREAM_INIT; - lzma_stream_flags flags; - lzma_ret ret = lzma_stream_header_decoder(&strm, &flags); - -} - - -static void -list_alone(const listing_handle *handle) -{ - if (handle->buffer[0] > (4 * 5 + 4) * 9 + 8) { - unsupported_file(handle); - return; - } - - const unsigned int pb = handle->buffer[0] / (9 * 5); - handle->buffer[0] -= pb * 9 * 5; - const unsigned int lp = handle->buffer[0] / 9; - const unsigned int lc = handle->buffer[0] - lp * 9; - - uint32_t dict = 0; - for (size_t i = 1; i < 5; ++i) { - dict <<= 8; - dict |= header[i]; - } - - if (dict > LZMA_DICTIONARY_SIZE_MAX) { - unsupported_file(handle); - return; - } - - uint64_t uncompressed_size = 0; - for (size_t i = 5; i < 13; ++i) { - uncompressed_size <<= 8; - uncompressed_size |= header[i]; - } - - // Reject files with uncompressed size of 256 GiB or more. It's - // an arbitrary limit trying to avoid at least some false positives. - if (uncompressed_size != UINT64_MAX - && uncompressed_size >= (UINT64_C(1) << 38)) { - unsupported_file(handle); - return; - } - - if (verbosity < V_WARNING) { - printf("name="); - print_escaped(handle->name); - printf("\nformat=alone\n"); - - if (uncompressed_size == UINT64_MAX) - printf("uncompressed_size=unknown\n"); - else - printf("uncompressed_size=%" PRIu64 "\n", - uncompressed_size); - - printf("dict=%" PRIu32 "\n", dict); - - printf("lc=%u\nlp=%u\npb=%u\n\n", lc, lp, pb); - - } else { - printf("File name: "); - print_escaped(handle->name); - printf("\nFile format: LZMA_Alone\n") - - printf("Uncompressed size: "); - if (uncompressed_size == UINT64_MAX) - printf("unknown\n"); - else - printf("%," PRIu64 " bytes (%" PRIu64 " MiB)\n", - uncompressed_size, - (uncompressed_size + 1024 * 512) - / (1024 * 1024)); - - printf("Dictionary size: %," PRIu32 " bytes " - "(%" PRIu32 " MiB)\n", - dict, (dict + 1024 * 512) / (1024 * 1024)); - - printf("Literal context bits (lc): %u\n", lc); - printf("Literal position bits (lc): %u\n", lp); - printf("Position bits (pb): %u\n", pb); - } - - return; -} - - - - -typedef struct { - const char *filename; - struct stat st; - int fd; - - lzma_stream strm; - lzma_stream_flags stream_flags; - lzma_info *info; - - lzma_vli backward_size; - lzma_vli uncompressed_size; - - size_t buffer_size; - uint8_t buffer[IO_BUFFER_SIZE]; -} listing_handle; - - -static bool -listing_pread(listing_handle *handle, uint64_t offset) -{ - if (offset >= (uint64_t)(handle->st.st_size)) { - errmsg(V_ERROR, "%s: Trying to read past the end of " - "the file.", handle->filename); - return true; - } - -#ifdef HAVE_PREAD - const ssize_t ret = pread(handle->fd, handle->buffer, IO_BUFFER_SIZE, - (off_t)(offset)); -#else - // Use lseek() + read() since we don't have pread(). We don't care - // to which offset the reading position is left. - if (lseek(handle->fd, (off_t)(offset), SEEK_SET) == -1) { - errmsg(V_ERROR, "%s: %s", handle->filename, strerror(errno)); - return true; - } - - const ssize_t ret = read(handle->fd, handle->buffer, IO_BUFFER_SIZE); -#endif - - if (ret == -1) { - errmsg(V_ERROR, "%s: %s", handle->filename, strerror(errno)); - return true; - } - - if (ret == 0) { - errmsg(V_ERROR, "%s: Trying to read past the end of " - "the file.", handle->filename); - return true; - } - - handle->buffer_size = (size_t)(ret); - return false; -} - - - -static bool -parse_stream_header(listing_handle *handle) -{ - if (listing_pread(handle, 0)) - return true; - - // TODO Got enough input? - - lzma_ret ret = lzma_stream_header_decoder( - &handle->strm, &handle->stream_flags); - if (ret != LZMA_OK) { - errmsg(V_ERROR, "%s: %s", handle->name, str_strm_error(ret)); - return true; - } - - handle->strm.next_in = handle->buffer; - handle->strm.avail_in = handle->buffer_size; - ret = lzma_code(&handle->strm, LZMA_RUN); - if (ret != LZMA_STREAM_END) { - assert(ret != LZMA_OK); - errmsg(V_ERROR, "%s: %s", handle->name, str_strm_error(ret)); - return true; - } - - return false; -} - - -static bool -parse_stream_tail(listing_handle *handle) -{ - uint64_t offset = (uint64_t)(handle->st.st_size); - - // Skip padding - do { - if (offset == 0) { - errmsg(V_ERROR, "%s: %s", handle->name, - str_strm_error(LZMA_DATA_ERROR)); - return true; - } - - if (offset < IO_BUFFER_SIZE) - offset = 0; - else - offset -= IO_BUFFER_SIZE; - - if (listing_pread(handle, offset)) - return true; - - while (handle->buffer_size > 0 - && handle->buffer[handle->buffer_size - 1] - == '\0') - --handle->buffer_size; - - } while (handle->buffer_size == 0); - - if (handle->buffer_size < LZMA_STREAM_TAIL_SIZE) { - // TODO - } - - lzma_stream_flags stream_flags; - lzma_ret ret = lzma_stream_tail_decoder(&handle->strm, &stream_flags); - if (ret != LZMA_OK) { - errmsg(V_ERROR, "%s: %s", handle->name, str_strm_error(ret)); - return true; - } - - handle->strm.next_in = handle->buffer + handle->buffer_size - - LZMA_STREAM_TAIL_SIZE; - handle->strm.avail_in = LZMA_STREAM_TAIL_SIZE; - handle->buffer_size -= LZMA_STREAM_TAIL_SIZE; - ret = lzma_code(&handle->strm, LZMA_RUN); - if (ret != LZMA_OK) { - assert(ret != LZMA_OK); - errmsg(V_ERROR, "%s: %s", handle->name, str_strm_error(ret)); - return true; - } - - if (!lzma_stream_flags_is_equal(handle->stream_flags, stream_flags)) { - // TODO - // Possibly corrupt, possibly concatenated file. - } - - handle->backward_size = 0; - ret = lzma_vli_reverse_decode(&handle->backward_size, handle->buffer, - &handle->buffer_size); - if (ret != LZMA_OK) { - // It may be LZMA_BUF_ERROR too, but it doesn't make sense - // as an error message displayed to the user. - errmsg(V_ERROR, "%s: %s", handle->name, - str_strm_error(LZMA_DATA_ERROR)); - return true; - } - - if (!stream_flags.is_multi) { - handle->uncompressed_size = 0; - size_t tmp = handle->buffer_size; - ret = lzma_vli_reverse_decode(&handle->uncompressed_size, - handle->buffer, &tmp); - if (ret != LZMA_OK) - handle->uncompressed_size = LZMA_VLI_UNKNOWN; - } - - // Calculate the Header Metadata Block start offset. - - - return false; -} - - - -static void -list_native(listing_handle *handle) -{ - lzma_memory_limiter *limiter - = lzma_memory_limiter_create(opt_memory); - if (limiter == NULL) { - errmsg(V_ERROR, - } - lzma_info *info = - - - // Parse Stream Header - // - // Single-Block Stream: - // - Parse Block Header - // - Parse Stream Footer - // - If Backward Size doesn't match, error out - // - // Multi-Block Stream: - // - Parse Header Metadata Block, if any - // - Parse Footer Metadata Block - // - Parse Stream Footer - // - If Footer Metadata Block doesn't match the Stream, error out - // - // In other words, we don't support concatened files. - if (parse_stream_header(handle)) - return; - - if (parse_block_header(handle)) - return; - - if (handle->stream_flags.is_multi) { - if (handle->block_options.is_metadata) { - if (parse_metadata(handle) - return; - } - - if (my_seek(handle, - - } else { - if (handle->block_options.is_metadata) { - FILE_IS_CORRUPT(); - return; - } - - if (parse_stream_footer(handle)) - return; - - // If Uncompressed Size isn't present in Block Header, - // it must be present in Stream Footer. - if (handle->block_options.uncompressed_size - == LZMA_VLI_UNKNOWN - && handle->stream_flags.uncompressed_size - == LZMA_VLI_UNKNOWN) { - FILE_IS_CORRUPT(); - return; - } - - // Construct a single-Record Index. - lzma_index *index = malloc(sizeof(lzma_index)); - if (index == NULL) { - out_of_memory(); - return; - } - - // Pohdintaa: - // Jos Block coder hoitaisi Uncompressed ja Backward Sizet, - // voisi index->total_sizeksi laittaa suoraan Backward Sizen. - index->total_size = - - if () { - - } - } - - - if (handle->block_options.is_metadata) { - if (!handle->stream_flags.is_multi) { - FILE_IS_CORRUPT(); - return; - } - - if (parse_metadata(handle)) - return; - - } -} - - - -extern void -list(const char *filename) -{ - if (strcmp(filename, "-") == 0) { - errmsg(V_ERROR, "%s: --list does not support reading from " - "standard input", filename); - return; - } - - if (is_empty_filename(filename)) - return; - - listing_handle handle; - handle.filename = filename; - - handle.fd = open(filename, O_RDONLY | O_NOCTTY); - if (handle.fd == -1) { - errmsg(V_ERROR, "%s: %s", filename, strerror(errno)); - return; - } - - if (fstat(handle.fd, &handle.st)) { - errmsg(V_ERROR, "%s: %s", filename, strerror(errno)); - goto out; - } - - if (!S_ISREG(handle.st.st_mode)) { - errmsg(V_WARNING, _("%s: Not a regular file, skipping"), - filename); - goto out; - } - - if (handle.st.st_size <= 0) { - errmsg(V_ERROR, _("%s: File is empty"), filename); - goto out; - } - - if (listing_pread(&handle, 0)) - goto out; - - if (handle.buffer[0] == 0xFF) { - if (opt_header == HEADER_ALONE) { - errmsg(V_ERROR, "%s: FIXME", filename); // FIXME - goto out; - } - - list_native(&handle); - } else { - if (opt_header != HEADER_AUTO && opt_header != HEADER_ALONE) { - errmsg(V_ERROR, "%s: FIXME", filename); // FIXME - goto out; - } - - list_alone(&handle); - } - -out: - (void)close(fd); - return; -} |