root/morphix/trunk/cloop/extract_compressed_fs.c

Revision 2, 3.6 kB (checked in by nextime, 2 years ago)

Initial import, branching from morphix svn

Line 
1 /* Extracts a filesystem back from a compressed fs file */
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 }
Note: See TracBrowser for help on using the browser.