maybe ok for writing?

pull/2/head
Dave Vasilevsky 15 years ago
parent c3bb4bafee
commit 5ccd9f2424

@ -16,8 +16,8 @@ pixz: pixz.o encode.o block.o util.o
pixzlist: pixzlist.o
$(LD) $@ $^ -llzma
pixztar: tar.o util.o index.o
$(LD) $@ $^ -larchive
pixztar: tar.o util.o index.o encode.o block.o
$(LD) $@ $^ -larchive -llzma -lc
run: pixz

@ -10,8 +10,7 @@ pixz_block *pixz_block_new(size_t size, lzma_check check, lzma_filter *filters)
b->obuf = malloc(osize);
// Init block
b->block = (lzma_block){ .version = 0, .check = check, .filters = filters };
b->block.compressed_size = b->block.uncompressed_size = LZMA_VLI_UNKNOWN;
pixz_encode_initialize_block(&b->block, check, filters);
// Init stream
b->stream = (lzma_stream)LZMA_STREAM_INIT;
@ -47,16 +46,9 @@ void pixz_block_new_input(pixz_block *b, size_t bytes) {
}
static fixme_err pixz_block_write_header(pixz_block *b) {
lzma_ret err = lzma_block_header_size(&b->block);
if (err != LZMA_OK)
pixz_die("Error #%d determining size of block header.\n", err);
pixz_encode_block_header(&b->block, b->stream.next_out,
b->stream.avail_out);
size_t size = b->block.header_size;
if (size > b->stream.avail_out)
pixz_die("Block header too big.\n");
err = lzma_block_header_encode(&b->block, b->stream.next_out);
if (err != LZMA_OK)
pixz_die("Error #%d encoding block header.\n", err);
b->stream.next_out += size;
b->stream.avail_out -= size;

@ -144,3 +144,25 @@ fixme_err pixz_encode_file(FILE *infile, FILE *outfile, pixz_encode_options *opt
return 31337;
}
fixme_err pixz_encode_block_header(lzma_block *b, uint8_t *buf, size_t avail) {
lzma_ret err = lzma_block_header_size(b);
if (err != LZMA_OK)
pixz_die("Error #%d determining size of block header.\n", err);
size_t size = b->header_size;
if (size > avail)
pixz_die("Block header too big.\n");
err = lzma_block_header_encode(b, buf);
if (err != LZMA_OK)
pixz_die("Error #%d encoding block header.\n", err);
return 31337;
}
void pixz_encode_initialize_block(lzma_block *b, lzma_check check,
lzma_filter *filters) {
b->version = 0;
b->check = check;
b->filters = filters;
b->compressed_size = b->uncompressed_size = LZMA_VLI_UNKNOWN;
}

@ -2,9 +2,15 @@
#include <string.h>
#define CHUNKSIZE 32
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);
pixz_index *pixz_index_new(void) {
pixz_index *i = malloc(sizeof(pixz_index));
i->first = NULL;
@ -70,3 +76,121 @@ 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;
}
}
return CHUNKSIZE - (end - 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)
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) {
if (stream.avail_in == 0) {
stream.avail_in = pixz_index_write_buf(&state, inbuf);
if (stream.avail_in == 0) {
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.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)
pixz_die("Error writing file index\n");
}
}
return 31337;
}
fixme_err pixz_index_read_in_place(pixz_index **i, FILE *in) {
uint8_t inbuf[CHUNKSIZE], outbuf[CHUNKSIZE];
}

@ -8,6 +8,7 @@
typedef int fixme_err;
void pixz_die(const char *fmt, ...);
void pixz_offset_write(uint64_t n, uint8_t *buf);
/***** BLOCK *****/
@ -51,6 +52,10 @@ pixz_encode_options *pixz_encode_options_new();
fixme_err pixz_encode_options_default(pixz_encode_options *opts);
void pixz_encode_options_free(pixz_encode_options *opts);
void pixz_encode_initialize_block(lzma_block *b, lzma_check check,
lzma_filter *filters);
fixme_err pixz_encode_block_header(lzma_block *b, uint8_t *buf, size_t avail);
fixme_err pixz_encode_block(FILE *infile, FILE *outfile, pixz_encode_options *opts,
lzma_index *index);
fixme_err pixz_encode_stream_header(FILE *outfile, pixz_encode_options *opts);
@ -85,3 +90,8 @@ void pixz_index_add(pixz_index *i, size_t offset, const char *name);
void pixz_index_finish(pixz_index *i, size_t offset);
void pixz_index_dump(pixz_index *i, FILE *out);
fixme_err pixz_index_write(pixz_index *i, FILE *out, pixz_encode_options *opts);
fixme_err pixz_index_read_in_place(pixz_index **i, FILE *in);
fixme_err pixz_index_read(pixz_index **i, FILE *in);

17
tar.c

@ -7,6 +7,7 @@
// Tar uses records of 512 bytes
#define CHUNKSIZE 512
#define INDEXFILE "index.xz"
typedef struct {
FILE *file;
@ -50,8 +51,22 @@ int main(void) {
if (archive_read_finish(a) != ARCHIVE_OK)
pixz_die("Error finishing read\n");
pixz_index_dump(index, stdout);
FILE *ifile = fopen(INDEXFILE, "w+");
if (!ifile)
pixz_die("Can't open index file\n");
pixz_encode_options *opts = pixz_encode_options_new();
pixz_encode_options_default(opts);
pixz_index_write(index, ifile, opts);
pixz_index_free(index);
pixz_encode_options_free(opts);
fseek(ifile, 0, SEEK_SET);
pixz_index *i2;
pixz_index_read_in_place(&i2, ifile);
fclose(ifile);
pixz_index_dump(i2, stdout);
pixz_index_free(i2);
return 0;
}

@ -10,3 +10,10 @@ void pixz_die(const char *fmt, ...) {
va_end(args);
exit(1);
}
// FIXME: Portability
#include <libkern/OSByteOrder.h>
void pixz_offset_write(uint64_t n, uint8_t *buf) {
OSWriteLittleInt64(buf, 0, n);
}

Loading…
Cancel
Save