| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
#include <stdio.h> |
|---|
| 4 |
#include <unistd.h> |
|---|
| 5 |
#include <stdlib.h> |
|---|
| 6 |
#include <sys/stat.h> |
|---|
| 7 |
#include <fcntl.h> |
|---|
| 8 |
#include <errno.h> |
|---|
| 9 |
#include <string.h> |
|---|
| 10 |
#include <zlib.h> |
|---|
| 11 |
#if defined(__FreeBSD__) |
|---|
| 12 |
#include <sys/endian.h> |
|---|
| 13 |
#include <netinet/in.h> |
|---|
| 14 |
typedef uint64_t loff_t; |
|---|
| 15 |
#ifndef be64toh |
|---|
| 16 |
static __inline __uint64_t |
|---|
| 17 |
__bswap64(__uint64_t _x) |
|---|
| 18 |
{ |
|---|
| 19 |
|
|---|
| 20 |
return ((_x >> 56) | ((_x >> 40) & 0xff00) | ((_x >> 24) & 0xff0000) | |
|---|
| 21 |
((_x >> 8) & 0xff000000) | ((_x << 8) & ((__uint64_t)0xff << 32)) | |
|---|
| 22 |
((_x << 24) & ((__uint64_t)0xff << 40)) | |
|---|
| 23 |
((_x << 40) & ((__uint64_t)0xff << 48)) | ((_x << 56))); |
|---|
| 24 |
} |
|---|
| 25 |
#if BYTE_ORDER == LITTLE_ENDIAN |
|---|
| 26 |
#define be64toh(x) __bswap64(x) |
|---|
| 27 |
#else |
|---|
| 28 |
#define be64toh(x) |
|---|
| 29 |
#endif |
|---|
| 30 |
#endif |
|---|
| 31 |
#define __be64_to_cpu be64toh |
|---|
| 32 |
#else |
|---|
| 33 |
#include <asm/byteorder.h> |
|---|
| 34 |
#endif |
|---|
| 35 |
#include "compressed_loop.h" |
|---|
| 36 |
|
|---|
| 37 |
struct compressed_block |
|---|
| 38 |
{ |
|---|
| 39 |
size_t size; |
|---|
| 40 |
void *data; |
|---|
| 41 |
}; |
|---|
| 42 |
|
|---|
| 43 |
int main(int argc, char *argv[]) |
|---|
| 44 |
{ |
|---|
| 45 |
int handle; |
|---|
| 46 |
struct cloop_head head; |
|---|
| 47 |
unsigned int i; |
|---|
| 48 |
unsigned char *buffer, *clear_buffer; |
|---|
| 49 |
|
|---|
| 50 |
if (argc != 2) { |
|---|
| 51 |
fprintf(stderr, "Need filename\n"); |
|---|
| 52 |
exit(1); |
|---|
| 53 |
} |
|---|
| 54 |
|
|---|
| 55 |
handle = open(argv[1], O_RDONLY); |
|---|
| 56 |
if (handle < 0) { |
|---|
| 57 |
perror("Opening compressed file\n"); |
|---|
| 58 |
exit(1); |
|---|
| 59 |
} |
|---|
| 60 |
|
|---|
| 61 |
if (read(handle, &head, sizeof(head)) != sizeof(head)) { |
|---|
| 62 |
perror("Reading compressed file header\n"); |
|---|
| 63 |
exit(1); |
|---|
| 64 |
} |
|---|
| 65 |
|
|---|
| 66 |
buffer = malloc(ntohl(head.block_size) + ntohl(head.block_size)/1000 |
|---|
| 67 |
+ 12 + 4); |
|---|
| 68 |
clear_buffer = malloc(ntohl(head.block_size)); |
|---|
| 69 |
fprintf(stderr, "%u blocks of size %u. Preamble:\n%s\n", |
|---|
| 70 |
ntohl(head.num_blocks), ntohl(head.block_size), head.preamble); |
|---|
| 71 |
|
|---|
| 72 |
for (i = 0; i < ntohl(head.num_blocks); i++) { |
|---|
| 73 |
int currpos; |
|---|
| 74 |
unsigned long destlen = ntohl(head.block_size); |
|---|
| 75 |
loff_t offset[2]; |
|---|
| 76 |
unsigned int size; |
|---|
| 77 |
|
|---|
| 78 |
read(handle, &offset, 2*sizeof(loff_t)); |
|---|
| 79 |
lseek(handle, -sizeof(loff_t), SEEK_CUR); |
|---|
| 80 |
|
|---|
| 81 |
currpos = lseek(handle, 0, SEEK_CUR); |
|---|
| 82 |
if (lseek(handle, __be64_to_cpu(offset[0]), SEEK_SET) < 0) { |
|---|
| 83 |
fprintf(stderr, "lseek to %Lu: %s\n", |
|---|
| 84 |
__be64_to_cpu(offset[0]), strerror(errno)); |
|---|
| 85 |
exit(1); |
|---|
| 86 |
} |
|---|
| 87 |
|
|---|
| 88 |
size=__be64_to_cpu(offset[1])-__be64_to_cpu(offset[0]); |
|---|
| 89 |
if (size > ntohl(head.block_size) + ntohl(head.block_size)/1000 |
|---|
| 90 |
+ 12 + 4) { |
|---|
| 91 |
fprintf(stderr, |
|---|
| 92 |
"Size %u for block %u (offset %Lu) too big\n", |
|---|
| 93 |
size, i, __be64_to_cpu(offset[0])); |
|---|
| 94 |
exit(1); |
|---|
| 95 |
} |
|---|
| 96 |
read(handle, buffer, size); |
|---|
| 97 |
if (lseek(handle, currpos, SEEK_SET) < 0) { |
|---|
| 98 |
perror("seeking"); |
|---|
| 99 |
exit(1); |
|---|
| 100 |
} |
|---|
| 101 |
|
|---|
| 102 |
fprintf(stderr, "Block %u length %u => %lu\n", |
|---|
| 103 |
i, size, destlen); |
|---|
| 104 |
if (i == 3) { |
|---|
| 105 |
fprintf(stderr, |
|---|
| 106 |
"Block head:%02X%02X%02X%02X%02X%02X%02X%02X\n", |
|---|
| 107 |
buffer[0], |
|---|
| 108 |
buffer[1], |
|---|
| 109 |
buffer[2], |
|---|
| 110 |
buffer[3], |
|---|
| 111 |
buffer[4], |
|---|
| 112 |
buffer[5], |
|---|
| 113 |
buffer[6], |
|---|
| 114 |
buffer[7]); |
|---|
| 115 |
fprintf(stderr, |
|---|
| 116 |
"Block tail:%02X%02X%02X%02X%02X%02X%02X%02X\n", |
|---|
| 117 |
buffer[3063], |
|---|
| 118 |
buffer[3064], |
|---|
| 119 |
buffer[3065], |
|---|
| 120 |
buffer[3066], |
|---|
| 121 |
buffer[3067], |
|---|
| 122 |
buffer[3068], |
|---|
| 123 |
buffer[3069], |
|---|
| 124 |
buffer[3070]); |
|---|
| 125 |
} |
|---|
| 126 |
switch (uncompress(clear_buffer, &destlen, |
|---|
| 127 |
buffer, size)) { |
|---|
| 128 |
case Z_OK: |
|---|
| 129 |
break; |
|---|
| 130 |
|
|---|
| 131 |
case Z_MEM_ERROR: |
|---|
| 132 |
fprintf(stderr, "Uncomp: oom block %u\n", i); |
|---|
| 133 |
exit(1); |
|---|
| 134 |
|
|---|
| 135 |
case Z_BUF_ERROR: |
|---|
| 136 |
fprintf(stderr, "Uncomp: not enough out room %u\n", i); |
|---|
| 137 |
exit(1); |
|---|
| 138 |
|
|---|
| 139 |
case Z_DATA_ERROR: |
|---|
| 140 |
fprintf(stderr, "Uncomp: input corrupt %u\n", i); |
|---|
| 141 |
exit(1); |
|---|
| 142 |
|
|---|
| 143 |
default: |
|---|
| 144 |
fprintf(stderr, "Uncomp: unknown error %u\n", i); |
|---|
| 145 |
exit(1); |
|---|
| 146 |
} |
|---|
| 147 |
if (destlen != ntohl(head.block_size)) { |
|---|
| 148 |
fprintf(stderr, "Uncomp: bad len %u (%lu not %u)\n", i, |
|---|
| 149 |
destlen, ntohl(head.block_size)); |
|---|
| 150 |
exit(1); |
|---|
| 151 |
} |
|---|
| 152 |
write(STDOUT_FILENO, clear_buffer, ntohl(head.block_size)); |
|---|
| 153 |
} |
|---|
| 154 |
return 0; |
|---|
| 155 |
} |
|---|