pbzip2 に対応
id:ichii386 に頼まれた件を黙々と遂行中。もうちょっとだよ。
#ifndef __GNUC__ #error ぐにゅ〜 #endif /* __GNUC__ */ #include <stdio.h> #include <stdlib.h> #include <bzlib.h> #define UNUSED(def) def __attribute__((unused)) #ifndef TRUE # define TRUE 1 #endif /* TRUE */ #ifndef FALSE # define FALSE 0 #endif /* FALSE */ int doit(FILE *out_strm, FILE *in_strm) { int err = 0; int bzerr; unsigned char in_buf[4096]; unsigned char out_buf[4096]; size_t nelems_read; size_t total_alloc_sz = 0; bz_stream bzs; int uninitialized = TRUE; void *alloc(UNUSED(void *opaque), int sz, int nelems) { size_t r = (size_t)sz * (size_t)nelems; if (r / (size_t)sz != (size_t)nelems) return NULL; /* ! */ total_alloc_sz += sz; return malloc(r); } void release(UNUSED(void *opaque), void *ptr) { free(ptr); } bzs.bzalloc = alloc; bzs.bzfree = release; for (;;) { if (uninitialized) { bzerr = BZ2_bzDecompressInit(&bzs, 1, 0); if (bzerr) goto out; bzs.avail_in = 0; uninitialized = FALSE; } if (bzs.avail_in == 0) { nelems_read = fread(in_buf, sizeof(*in_buf), sizeof(in_buf) / sizeof(*in_buf), in_strm); if (nelems_read == 0) { if (ferror(in_strm)) { err = 1; goto out; } else { break; /* end of file */ } } bzs.next_in = in_buf; bzs.avail_in = nelems_read * sizeof(*in_buf); } bzs.next_out = out_buf; bzs.avail_out = sizeof(out_buf); fprintf(stderr, "avail_in=%tu\n", bzs.avail_in); bzerr = BZ2_bzDecompress(&bzs); fprintf(stderr, " bzerr=%d\n", bzerr); if (bzerr < 0) { err = 1; goto out; } fprintf(stderr, " avail_in=%tu\n", bzs.avail_in); fprintf(stderr, " avail_out=%tu\n", bzs.avail_out); { size_t nelems_written; unsigned char *p = out_buf; while (p < (unsigned char *)bzs.next_out) { nelems_written = fwrite(p, sizeof(*out_buf), (unsigned char *)bzs.next_out - p, out_strm); if (nelems_written == 0) { err = 1; goto out; } p += nelems_written; } } /* reinitialize decompressor */ if (bzerr == BZ_STREAM_END) { if (BZ2_bzDecompressEnd(&bzs)) fprintf(stderr, "WARN: BZ2_bzDecompressEnd returned error status\n"); uninitialized = TRUE; } } out: fprintf(stderr, "Total number of bytes allocated: %tu\n", total_alloc_sz); if (!uninitialized) { if (BZ2_bzDecompressEnd(&bzs)) fprintf(stderr, "WARN: BZ2_bzDecompressEnd returned error status\n"); } return err; } int main(UNUSED(int argc), UNUSED(void *argv)) { return doit(stdout, stdin) ? 1: 0; }