示例#1
0
	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;
	}
示例#2
0
文件: common.c 项目: hornos/pixz
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;
}
示例#3
0
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;
}
示例#4
0
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);
}