don't set page size by default
[tridge/junkcode.git] / sccs_uncomp.c
1 #define _GNU_SOURCE
2 #include <stdio.h>
3 #include <string.h>
4 #include <zlib.h>
5 #include <fcntl.h>
6 #include <unistd.h>
7 #include <sys/mman.h>
8 #include <sys/stat.h>
9
10 /*
11   calculate a simple checksum
12 */
13 static unsigned sccs_checksum(const unsigned char *buf, size_t len)
14 {
15         unsigned ret=0;
16         int i;
17         for (i=0;i<len;i++) {
18                 ret += buf[i];
19         }
20         return ret & 0xFFFF;
21 }
22
23 static void *map_file(const char *fname, size_t *size)
24 {
25         int fd = open(fname, O_RDONLY);
26         struct stat st;
27         void *p;
28
29         fstat(fd, &st);
30         p = mmap(0, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
31         close(fd);
32
33         *size = st.st_size;
34         return p;
35 }
36
37
38 static int uncompress_one(const char *fname)
39 {
40         unsigned char *buf;
41         size_t size;
42         unsigned char *p;
43         struct z_stream_s zs;
44         int ret, len;
45         char outbuf[1024];
46         char *tmpname;
47         FILE *f;
48         unsigned sum;
49         
50         buf = map_file(fname, &size);
51
52         p = memmem(buf, size, "\1f e 4\n", 7);
53         if (p == NULL) {
54                 p = memmem(buf, size, "\1f e 5\n", 7);
55         }
56         if (p == NULL) {
57                 printf("%s not compressed (no e 4)\n", fname);
58                 return 0;
59         }
60
61         if (p[5] == '4') {
62                 p[5] = '0';
63         } else {
64                 p[5] = '1';
65         }
66
67         p = memmem(buf, size, "\1T\nx", 4);
68
69         if (p == NULL) {
70                 printf("%s not compressed\n", fname);
71                 return 0;
72         }
73
74         asprintf(&tmpname, "%s.tmpz", fname);
75         
76         f = fopen(tmpname, "w");
77
78         len = 3+(int)(p-buf);
79         fwrite(buf, 1, len, f);
80
81         memset(&zs, 0, sizeof(zs));
82
83         zs.avail_in = size-len-2;
84         zs.next_in = p+5;
85         zs.next_out = outbuf;
86         zs.avail_out = sizeof(outbuf);
87
88         ret = inflateInit2(&zs, -15);
89         if (ret != Z_OK) {
90                 fprintf(stderr,"inflateInit2 error %d\n", ret);
91                 goto failed;
92         }
93
94         while (1) {
95                 if (zs.avail_in == 0) break;
96
97                 ret = inflate(&zs, Z_SYNC_FLUSH);
98
99                 if (zs.avail_out < sizeof(outbuf)) {
100                         fwrite(outbuf, 1, sizeof(outbuf) - zs.avail_out, f);
101                         zs.avail_out = sizeof(outbuf);
102                         zs.next_out = outbuf;
103                 }
104
105                 if (ret == Z_STREAM_END) break;
106                 if (ret != Z_OK) {
107                         fprintf(stderr,"inflate error %d\n", ret);
108                         goto failed;
109                 }
110         }
111
112         fflush(f);
113         rewind(f);
114
115         buf = map_file(tmpname, &size);
116
117         sum = sccs_checksum(buf+8, size-8);
118
119         printf("sum=%05u\n", sum);
120
121         fprintf(f, "\1H%05u", sum);
122         fclose(f);
123
124         rename(tmpname, fname);
125         
126         return 0;
127
128 failed:
129         printf("failed\n");
130         return -1;
131 }
132
133
134 int main(int argc, const char *argv[])
135 {
136         int i;
137         for (i=1;i<argc;i++) {
138                 if (uncompress_one(argv[i]) != 0) return -1;
139         }
140         return 0;
141 }