nicer formatting
[tridge/junkcode.git] / gz_extract.c
1 #define _GNU_SOURCE
2
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <sys/mman.h>
10 #include <sys/stat.h>
11
12 #define GZIP_HEADER "\037\213\008"
13
14 static void *map_file(const char *fname, off_t *size)
15 {
16         int fd;
17         struct stat st;
18         void *p;
19
20         fd = open(fname, O_RDONLY);
21         if (fd == -1) {
22                 perror(fname);
23                 return NULL;
24         }
25
26         fstat(fd, &st);
27         p = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
28         close(fd);
29
30         *size = st.st_size;
31         return p;
32 }
33
34
35 static void file_save(const char *fname, const char *p, off_t size)
36 {
37         int fd;
38         fd = open(fname, O_CREAT|O_TRUNC|O_WRONLY, 0666);
39         if (fd == -1) {
40                 perror(fname);
41                 return;
42         }
43         if (write(fd, p, size) != size) {
44                 fprintf(stderr, "Failed to save %d bytes to %s\n", (int)size, fname);
45                 return;
46         }
47         close(fd);
48 }
49
50 static void scan_memory(int i, unsigned char *p, off_t size)
51 {
52         unsigned char *p0 = p;
53         int found = 0;
54         
55         while ((p = memmem(p, size - (p-p0), GZIP_HEADER, strlen(GZIP_HEADER)))) {
56                 char *fname=NULL;
57
58                 if (p[8] > 4) {
59                         p++;
60                         continue;
61                 }
62
63                 /* only want unix gzip output */
64                 if (p[9] > 11) {
65                         p++;
66                         continue;
67                 }
68
69                 found++;
70                 asprintf(&fname, "extract-%d-%d.gz", i, found);
71                 file_save(fname, p, size - (p-p0));
72                 printf("Extracted %d bytes to %s\n", (int)(size - (p-p0)), fname);
73                 free(fname);
74                 p++;
75         }
76 }
77
78 int main(int argc, const char *argv[])
79 {
80         int i;
81
82         for (i=1;i<argc;i++) {
83                 unsigned char *p;
84                 off_t size;
85
86                 printf("Scanning %s\n", argv[i]);
87
88                 p = map_file(argv[i], &size);
89                 if (p) {
90                         scan_memory(i, p, size);
91                 }
92         }
93
94         return 0;
95 }