bool seekBlockFor(int64_t offset, std::string &error) { bool matchingBlock = (position >= 0 && offset >= (int64_t)iter.block.uncompressed_file_offset && offset < (int64_t)(iter.block.uncompressed_file_offset + iter.block.uncompressed_size)); if (matchingBlock && position <= offset) { /* we already are in the needed block, and still before the requested data; just continue from here */ LOG_VERBOSE("continue reading for offset %i (current position: %i)\n", (int) offset, (int) position); } else { if (matchingBlock) { /* already passed the index we wanted, but same block */ LOG_VERBOSE("restarting block: %i (current position: %i)\n", (int) offset, (int) position); } else { LOG_VERBOSE("searching for offset: %i (current position: %i)\n", (int) offset, (int) position); position = -1; if (lzma_index_iter_locate(&iter, offset)) { error.assign("couldn't find offset in index"); return false; } // LOG_VERBOSE("seeking to new block\n"); } discard_output(); /* restart decoder */ if (!loadBlock(error)) return false; } return true; }
lzma_vli find_file_index(void **bdatap) { if (!gIndex) decode_index(); // find the last block lzma_index_iter iter; lzma_index_iter_init(&iter, gIndex); lzma_vli loc = lzma_index_uncompressed_size(gIndex) - 1; if (lzma_index_iter_locate(&iter, loc)) die("Can't locate file index block"); void *bdata = decode_block_start(iter.block.compressed_file_offset); gFileIndexBuf = malloc(gFIBSize); gStream.avail_out = gFIBSize; gStream.avail_in = 0; // Check if this is really an index read_file_index_data(); lzma_vli ret = iter.block.compressed_file_offset; if (xle64dec(gFileIndexBuf + gFIBPos) != PIXZ_INDEX_MAGIC) ret = 0; gFIBPos += sizeof(uint64_t); if (bdatap && ret) { *bdatap = bdata; } else { // Just looking, don't keep things around if (bdatap) *bdatap = NULL; free(bdata); free(gFileIndexBuf); gLastFile = gFileIndex = NULL; lzma_end(&gStream); } return ret; }
static file_ptr lzma_pread (struct bfd *nbfd, void *stream, void *buf, file_ptr nbytes, file_ptr offset) { struct lzma_stream *lstream = stream; bfd_size_type chunk_size; lzma_index_iter iter; gdb_byte *compressed, *uncompressed; file_ptr block_offset; lzma_filter filters[LZMA_FILTERS_MAX + 1]; lzma_block block; size_t compressed_pos, uncompressed_pos; file_ptr res; res = 0; while (nbytes > 0) { if (lstream->data == NULL || lstream->data_start > offset || offset >= lstream->data_end) { asection *section = lstream->section; lzma_index_iter_init (&iter, lstream->index); if (lzma_index_iter_locate (&iter, offset)) break; compressed = xmalloc (iter.block.total_size); block_offset = section->filepos + iter.block.compressed_file_offset; if (bfd_seek (section->owner, block_offset, SEEK_SET) != 0 || bfd_bread (compressed, iter.block.total_size, section->owner) != iter.block.total_size) { xfree (compressed); break; } uncompressed = xmalloc (iter.block.uncompressed_size); memset (&block, 0, sizeof (block)); block.filters = filters; block.header_size = lzma_block_header_size_decode (compressed[0]); if (lzma_block_header_decode (&block, &gdb_lzma_allocator, compressed) != LZMA_OK) { xfree (compressed); xfree (uncompressed); break; } compressed_pos = block.header_size; uncompressed_pos = 0; if (lzma_block_buffer_decode (&block, &gdb_lzma_allocator, compressed, &compressed_pos, iter.block.total_size, uncompressed, &uncompressed_pos, iter.block.uncompressed_size) != LZMA_OK) { xfree (compressed); xfree (uncompressed); break; } xfree (compressed); xfree (lstream->data); lstream->data = uncompressed; lstream->data_start = iter.block.uncompressed_file_offset; lstream->data_end = (iter.block.uncompressed_file_offset + iter.block.uncompressed_size); } chunk_size = min (nbytes, lstream->data_end - offset); memcpy (buf, lstream->data + offset - lstream->data_start, chunk_size); buf = (gdb_byte *) buf + chunk_size; offset += chunk_size; nbytes -= chunk_size; res += chunk_size; } return res; }
static void test_locate(void) { lzma_index *i = lzma_index_init(NULL); expect(i != NULL); lzma_index_iter r; lzma_index_iter_init(&r, i); // Cannot locate anything from an empty Index. expect(lzma_index_iter_locate(&r, 0)); expect(lzma_index_iter_locate(&r, 555)); // One empty Record: nothing is found since there's no uncompressed // data. expect(lzma_index_append(i, NULL, 16, 0) == LZMA_OK); expect(lzma_index_iter_locate(&r, 0)); // Non-empty Record and we can find something. expect(lzma_index_append(i, NULL, 32, 5) == LZMA_OK); expect(!lzma_index_iter_locate(&r, 0)); expect(r.block.total_size == 32); expect(r.block.uncompressed_size == 5); expect(r.block.compressed_file_offset == LZMA_STREAM_HEADER_SIZE + 16); expect(r.block.uncompressed_file_offset == 0); // Still cannot find anything past the end. expect(lzma_index_iter_locate(&r, 5)); // Add the third Record. expect(lzma_index_append(i, NULL, 40, 11) == LZMA_OK); expect(!lzma_index_iter_locate(&r, 0)); expect(r.block.total_size == 32); expect(r.block.uncompressed_size == 5); expect(r.block.compressed_file_offset == LZMA_STREAM_HEADER_SIZE + 16); expect(r.block.uncompressed_file_offset == 0); expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)); expect(r.block.total_size == 40); expect(r.block.uncompressed_size == 11); expect(r.block.compressed_file_offset == LZMA_STREAM_HEADER_SIZE + 16 + 32); expect(r.block.uncompressed_file_offset == 5); expect(!lzma_index_iter_locate(&r, 2)); expect(r.block.total_size == 32); expect(r.block.uncompressed_size == 5); expect(r.block.compressed_file_offset == LZMA_STREAM_HEADER_SIZE + 16); expect(r.block.uncompressed_file_offset == 0); expect(!lzma_index_iter_locate(&r, 5)); expect(r.block.total_size == 40); expect(r.block.uncompressed_size == 11); expect(r.block.compressed_file_offset == LZMA_STREAM_HEADER_SIZE + 16 + 32); expect(r.block.uncompressed_file_offset == 5); expect(!lzma_index_iter_locate(&r, 5 + 11 - 1)); expect(r.block.total_size == 40); expect(r.block.uncompressed_size == 11); expect(r.block.compressed_file_offset == LZMA_STREAM_HEADER_SIZE + 16 + 32); expect(r.block.uncompressed_file_offset == 5); expect(lzma_index_iter_locate(&r, 5 + 11)); expect(lzma_index_iter_locate(&r, 5 + 15)); // Large Index lzma_index_end(i, NULL); i = lzma_index_init(NULL); expect(i != NULL); lzma_index_iter_init(&r, i); for (size_t n = 4; n <= 4 * 5555; n += 4) expect(lzma_index_append(i, NULL, n + 8, n) == LZMA_OK); expect(lzma_index_block_count(i) == 5555); // First Record expect(!lzma_index_iter_locate(&r, 0)); expect(r.block.total_size == 4 + 8); expect(r.block.uncompressed_size == 4); expect(r.block.compressed_file_offset == LZMA_STREAM_HEADER_SIZE); expect(r.block.uncompressed_file_offset == 0); expect(!lzma_index_iter_locate(&r, 3)); expect(r.block.total_size == 4 + 8); expect(r.block.uncompressed_size == 4); expect(r.block.compressed_file_offset == LZMA_STREAM_HEADER_SIZE); expect(r.block.uncompressed_file_offset == 0); // Second Record expect(!lzma_index_iter_locate(&r, 4)); expect(r.block.total_size == 2 * 4 + 8); expect(r.block.uncompressed_size == 2 * 4); expect(r.block.compressed_file_offset == LZMA_STREAM_HEADER_SIZE + 4 + 8); expect(r.block.uncompressed_file_offset == 4); // Last Record expect(!lzma_index_iter_locate( &r, lzma_index_uncompressed_size(i) - 1)); expect(r.block.total_size == 4 * 5555 + 8); expect(r.block.uncompressed_size == 4 * 5555); expect(r.block.compressed_file_offset == lzma_index_total_size(i) + LZMA_STREAM_HEADER_SIZE - 4 * 5555 - 8); expect(r.block.uncompressed_file_offset == lzma_index_uncompressed_size(i) - 4 * 5555); // Allocation chunk boundaries. See INDEX_GROUP_SIZE in // liblzma/common/index.c. const size_t group_multiple = 256 * 4; const size_t radius = 8; const size_t start = group_multiple - radius; lzma_vli ubase = 0; lzma_vli tbase = 0; size_t n; for (n = 1; n < start; ++n) { ubase += n * 4; tbase += n * 4 + 8; } while (n < start + 2 * radius) { expect(!lzma_index_iter_locate(&r, ubase + n * 4)); expect(r.block.compressed_file_offset == tbase + n * 4 + 8 + LZMA_STREAM_HEADER_SIZE); expect(r.block.uncompressed_file_offset == ubase + n * 4); tbase += n * 4 + 8; ubase += n * 4; ++n; expect(r.block.total_size == n * 4 + 8); expect(r.block.uncompressed_size == n * 4); } // Do it also backwards. while (n > start) { expect(!lzma_index_iter_locate(&r, ubase + (n - 1) * 4)); expect(r.block.total_size == n * 4 + 8); expect(r.block.uncompressed_size == n * 4); --n; tbase -= n * 4 + 8; ubase -= n * 4; expect(r.block.compressed_file_offset == tbase + n * 4 + 8 + LZMA_STREAM_HEADER_SIZE); expect(r.block.uncompressed_file_offset == ubase + n * 4); } // Test locating in concatenated Index. lzma_index_end(i, NULL); i = lzma_index_init(NULL); expect(i != NULL); lzma_index_iter_init(&r, i); for (n = 0; n < group_multiple; ++n) expect(lzma_index_append(i, NULL, 8, 0) == LZMA_OK); expect(lzma_index_append(i, NULL, 16, 1) == LZMA_OK); expect(!lzma_index_iter_locate(&r, 0)); expect(r.block.total_size == 16); expect(r.block.uncompressed_size == 1); expect(r.block.compressed_file_offset == LZMA_STREAM_HEADER_SIZE + group_multiple * 8); expect(r.block.uncompressed_file_offset == 0); lzma_index_end(i, NULL); }