|
|
|
@ -2,14 +2,13 @@
|
|
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#define CHUNKSIZE 32
|
|
|
|
|
#define CHUNKSIZE 4096 // Approximate
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool pixz_index_is_prefix(const char *name);
|
|
|
|
|
static void pixz_index_add_record(pixz_index *i, size_t offset, const char *name);
|
|
|
|
|
|
|
|
|
|
typedef struct pixz_index_write_state pixz_index_write_state;
|
|
|
|
|
static size_t pixz_index_write_buf(pixz_index_write_state *state, uint8_t *buf);
|
|
|
|
|
static uint8_t *pixz_index_write_buf(pixz_index_record **rec, size_t *outsize);
|
|
|
|
|
|
|
|
|
|
pixz_index *pixz_index_new(void) {
|
|
|
|
|
pixz_index *i = malloc(sizeof(pixz_index));
|
|
|
|
@ -76,121 +75,81 @@ void pixz_index_dump(pixz_index *i, FILE *out) {
|
|
|
|
|
fprintf(out, "Total: %zu\n", rec->offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
|
PIXZ_WRITE_NAME,
|
|
|
|
|
PIXZ_WRITE_LONG_NAME,
|
|
|
|
|
PIXZ_WRITE_SIZE,
|
|
|
|
|
} pixz_index_write_part;
|
|
|
|
|
|
|
|
|
|
struct pixz_index_write_state {
|
|
|
|
|
pixz_index_write_part part;
|
|
|
|
|
pixz_index_record *rec;
|
|
|
|
|
size_t namepos; // Position within a long-name
|
|
|
|
|
size_t namelen; // Total length of a long-name
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static size_t pixz_index_write_buf(pixz_index_write_state *state, uint8_t *buf) {
|
|
|
|
|
uint8_t *end = buf + CHUNKSIZE;
|
|
|
|
|
bool done = false;
|
|
|
|
|
while (!done) {
|
|
|
|
|
switch (state->part) {
|
|
|
|
|
case PIXZ_WRITE_SIZE:
|
|
|
|
|
if (buf + sizeof(uint64_t) + 1 > end) {
|
|
|
|
|
done = true;
|
|
|
|
|
} else {
|
|
|
|
|
pixz_offset_write(state->rec->offset, buf);
|
|
|
|
|
buf += sizeof(uint64_t);
|
|
|
|
|
*buf++ = '\0';
|
|
|
|
|
|
|
|
|
|
state->rec = state->rec->next;
|
|
|
|
|
state->part = PIXZ_WRITE_NAME;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PIXZ_WRITE_NAME:
|
|
|
|
|
if (!state->rec) {
|
|
|
|
|
done = true;
|
|
|
|
|
} else { // We have a record
|
|
|
|
|
const char *name = state->rec->name;
|
|
|
|
|
if (!name)
|
|
|
|
|
name = ""; // End record
|
|
|
|
|
printf("%s\n", name);
|
|
|
|
|
|
|
|
|
|
size_t len = strlen(name) + 1;
|
|
|
|
|
if (len > CHUNKSIZE) {
|
|
|
|
|
state->namelen = len;
|
|
|
|
|
state->namepos = 0;
|
|
|
|
|
state->part = PIXZ_WRITE_LONG_NAME;
|
|
|
|
|
} else {
|
|
|
|
|
memcpy(buf, name, len);
|
|
|
|
|
buf += len;
|
|
|
|
|
state->part = PIXZ_WRITE_SIZE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PIXZ_WRITE_LONG_NAME: {
|
|
|
|
|
size_t todo = state->namelen + 1 - state->namepos;
|
|
|
|
|
if (todo > end - buf)
|
|
|
|
|
todo = end - buf;
|
|
|
|
|
memcpy(buf, state->rec->name + state->namepos, todo);
|
|
|
|
|
buf += todo;
|
|
|
|
|
state->namepos += todo;
|
|
|
|
|
|
|
|
|
|
state->part = state->namepos == state->namelen
|
|
|
|
|
? PIXZ_WRITE_SIZE : PIXZ_WRITE_LONG_NAME;
|
|
|
|
|
done = true;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
static uint8_t *pixz_index_write_buf(pixz_index_record **rec, size_t *outsize) {
|
|
|
|
|
// How much space do we need?
|
|
|
|
|
size_t space = 0;
|
|
|
|
|
pixz_index_record *end = *rec;
|
|
|
|
|
do {
|
|
|
|
|
if (end->name)
|
|
|
|
|
space += strlen(end->name);
|
|
|
|
|
space += 2 + sizeof(uint64_t); // offset and two nulls
|
|
|
|
|
end = end->next;
|
|
|
|
|
} while (end && space < CHUNKSIZE);
|
|
|
|
|
|
|
|
|
|
// Write it!
|
|
|
|
|
uint8_t *buf, *pos;
|
|
|
|
|
buf = pos = malloc(space);
|
|
|
|
|
for (; *rec != end; *rec = (*rec)->next) {
|
|
|
|
|
const char *name = (*rec)->name;
|
|
|
|
|
if (!name)
|
|
|
|
|
name = "";
|
|
|
|
|
printf("%s\n", name);
|
|
|
|
|
|
|
|
|
|
size_t len = strlen(name);
|
|
|
|
|
strncpy((char*)pos, name, len + 1);
|
|
|
|
|
pos += len + 1;
|
|
|
|
|
pixz_offset_write((*rec)->offset, pos);
|
|
|
|
|
pos += sizeof(uint64_t);
|
|
|
|
|
*pos++ = '\0';
|
|
|
|
|
}
|
|
|
|
|
return CHUNKSIZE - (end - buf);
|
|
|
|
|
|
|
|
|
|
*outsize = space;
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fixme_err pixz_index_write(pixz_index *i, FILE *out, pixz_encode_options *opts) {
|
|
|
|
|
lzma_block block;
|
|
|
|
|
pixz_encode_initialize_block(&block, opts->check, opts->filters);
|
|
|
|
|
|
|
|
|
|
uint8_t inbuf[CHUNKSIZE], outbuf[CHUNKSIZE];
|
|
|
|
|
pixz_encode_block_header(&block, outbuf, CHUNKSIZE);
|
|
|
|
|
if (fwrite(outbuf, block.header_size, 1, out) != 1)
|
|
|
|
|
uint8_t buf[CHUNKSIZE];
|
|
|
|
|
pixz_encode_block_header(&block, buf, CHUNKSIZE);
|
|
|
|
|
if (fwrite(buf, block.header_size, 1, out) != 1)
|
|
|
|
|
pixz_die("Error writing file index header\n");
|
|
|
|
|
|
|
|
|
|
lzma_stream stream = LZMA_STREAM_INIT;
|
|
|
|
|
lzma_ret err = lzma_block_encoder(&stream, &block);
|
|
|
|
|
if (err != LZMA_OK)
|
|
|
|
|
pixz_die("Error #%d creating file index block encoder.\n", err);
|
|
|
|
|
stream.avail_in = 0;
|
|
|
|
|
|
|
|
|
|
pixz_index_write_state state = { .part = PIXZ_WRITE_NAME,
|
|
|
|
|
.rec = i->first, .namepos = 0 };
|
|
|
|
|
while (true) {
|
|
|
|
|
uint8_t *inbuf = NULL;
|
|
|
|
|
stream.avail_in = 0;
|
|
|
|
|
pixz_index_record *rec = i->first;
|
|
|
|
|
while (rec) {
|
|
|
|
|
if (stream.avail_in == 0) {
|
|
|
|
|
stream.avail_in = pixz_index_write_buf(&state, inbuf);
|
|
|
|
|
if (stream.avail_in == 0) {
|
|
|
|
|
free(inbuf);
|
|
|
|
|
stream.next_in = inbuf = pixz_index_write_buf(&rec, &stream.avail_in);
|
|
|
|
|
if (!inbuf) {
|
|
|
|
|
if (lzma_code(&stream, LZMA_FINISH) != LZMA_STREAM_END)
|
|
|
|
|
pixz_die("Error finishing file index\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
stream.next_in = inbuf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stream.next_out = outbuf;
|
|
|
|
|
stream.next_out = buf;
|
|
|
|
|
stream.avail_out = CHUNKSIZE;
|
|
|
|
|
if (lzma_code(&stream, LZMA_RUN) != LZMA_OK)
|
|
|
|
|
pixz_die("Error encoding file index\n");
|
|
|
|
|
if (stream.next_out != outbuf) {
|
|
|
|
|
printf("%ld\n", stream.next_out - outbuf);
|
|
|
|
|
if (fwrite(outbuf, stream.next_out - outbuf, 1, out) != 1)
|
|
|
|
|
size_t wr = stream.next_out - buf;
|
|
|
|
|
if (wr) {
|
|
|
|
|
if (fwrite(buf, wr, 1, out) != 1)
|
|
|
|
|
pixz_die("Error writing file index\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
lzma_end(&stream);
|
|
|
|
|
|
|
|
|
|
return 31337;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fixme_err pixz_index_read_in_place(pixz_index **i, FILE *in) {
|
|
|
|
|
uint8_t inbuf[CHUNKSIZE], outbuf[CHUNKSIZE];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 31337;
|
|
|
|
|
}
|
|
|
|
|