some more testing
[opensuse:clicfs.git] / doenerfs_common.c
1 #include "doenerfs.h"
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <lzma.h>
5 #include <string.h>
6 #include <assert.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <unistd.h>
10
11 int preset = 0;
12 FILE *packfile = 0;
13 FILE *cowfile = 0;
14
15 char thefile[PATH_MAX];
16 size_t thefilesize = 0;
17 uint64_t *sizes = 0;
18 uint64_t *offs = 0;
19 uint32_t parts = 0;
20 uint32_t pindex = 0;
21 size_t bsize = 0;
22 unsigned char **blockmap;
23 size_t num_pages = 0;
24 size_t cow_pages = 0;
25
26 uint32_t doener_readindex(FILE *f)
27 {
28     uint32_t stringlen;
29     if (fread((char*)&stringlen, sizeof(uint32_t), 1, f) != 1) {
30         perror("read");
31         return -1;
32     }
33     return stringlen;
34 }
35
36 int doenerfs_read_cow(const char *cowfilename)
37 {
38     cowfile = fopen(cowfilename, "a+");
39     if (!cowfile) {
40         fprintf(stderr, "cowfile %s can't be opened\n", cowfilename);
41         return 1;
42     }
43     struct stat st;
44     stat(cowfilename, &st);
45     fseek(cowfile, st.st_size - sizeof(uint32_t), SEEK_SET);
46     uint32_t indexlen = doener_readindex(cowfile) + sizeof(uint32_t);
47     fprintf(stderr, "index %ld %ld\n", (long)indexlen, ftell(cowfile));
48     if (fseek(cowfile, st.st_size - indexlen, SEEK_SET ))
49         perror("seek");
50     fprintf(stderr, "index %ld %ld\n", (long)indexlen, ftell(cowfile));
51     thefilesize = doener_readindex(cowfile);
52     fprintf(stderr, "size %ld\n", (long)thefilesize);
53     uint32_t newpages = thefilesize / 4096;
54     blockmap = realloc(blockmap, sizeof(unsigned char*)*newpages);
55     uint32_t i;
56     for (i = num_pages; i < newpages; ++i)
57         blockmap[i] = 0;
58     cow_pages = doener_readindex(cowfile);
59     fprintf(stderr, "cows %ld\n", (long)cow_pages);
60     for (i = 0; i < cow_pages; ++i)
61     {
62         uint32_t pageindex = doener_readindex(cowfile);
63         assert(pageindex < num_pages);
64         blockmap[i] = (unsigned char*)(long)(pageindex << 2) + 2;
65     }
66     return 0;
67 }
68
69 int doenerfs_read_pack(const char *packfilename)
70 {
71     packfile = fopen(packfilename, "r");
72     if (!packfile) {
73         fprintf(stderr, "packfile %s can't be opened\n", packfilename);
74         return 1;
75     }
76     char head[5];
77     char expected[5];
78     fread(head, 1, 4, packfile);
79     head[4] = 0;
80     sprintf(expected, "SK%02d", DOENER_MAGIC);
81     if (strcmp(head,expected)) {
82         fprintf(stderr, "wrong magic: %s vs %s\n", head, expected);
83         return 1;
84     }
85
86     uint32_t stringlen = doener_readindex(packfile);
87     if (stringlen == 0) {
88         fprintf(stderr, "abnormal len 0\n"); 
89         return 1;
90     }
91     if (fread(thefile, 1, stringlen, packfile) != stringlen) {
92         fprintf(stderr, "short read\n");
93         return 1;
94     }
95     thefile[stringlen] = 0;
96
97     size_t oparts = doener_readindex(packfile);
98     bsize = doener_readindex(packfile);
99     thefilesize = doener_readindex(packfile);
100     preset = doener_readindex(packfile);
101     num_pages = doener_readindex(packfile);
102     blockmap = malloc(sizeof(unsigned char*)*num_pages);
103
104     uint32_t i;
105     for (i = 0; i < num_pages; ++i) {
106         // make sure it's odd to diff between pointer and block
107         blockmap[i] = (unsigned char*)(long)((doener_readindex(packfile) << 2) + 1);
108     }
109
110     parts = doener_readindex(packfile);
111     sizes = malloc(sizeof(uint64_t)*parts);
112     offs = malloc(sizeof(uint64_t)*parts);
113
114     for (i = 0; i < parts; ++i)
115     {
116         if (fread((char*)(sizes + i), sizeof(uint64_t), 1, packfile) != 1)
117                 parts = 0;
118         if (!sizes[i]) {
119                 fprintf(stderr, "unreasonable size 0 for part %d\n", i);
120                 return 1;
121         }
122         if (fread((char*)(offs + i), sizeof(uint64_t), 1, packfile) != 1)
123                 parts = 0;
124     }
125     if (parts == 0) {
126         fprintf(stderr, "unreasonable part number 0\n");
127         return 1;
128     }
129     fseek(packfile, (oparts-parts)*sizeof(uint64_t)*2, SEEK_CUR);
130
131     return 0;
132 }
133
134 off_t doener_map_block(off_t block)
135 {
136     unsigned char *ptr = blockmap[block];
137     size_t ret = (long)ptr;
138     // calling map_block for detached blocks is bogus
139     assert((ret & 0x3) == 1);
140     return ret >> 2;
141 }
142
143 size_t doener_readpart(unsigned char *buffer, int part)
144 {
145     if (fseek(packfile, offs[part], SEEK_SET)) {
146         fprintf(stderr, "seek failed %d %ld\n", part, (long)offs[part]);
147         return 0;
148     }
149 #if defined(DEBUG)
150     fprintf(logger, "uncompress part=%d/%d com=%d off=%ld size=%ld ioff=%ld size=%ld\n", part, parts, com->index, offs[part], sizes[part], ioff, size );
151 #endif
152     size_t readin = fread(buffer, 1, sizes[part], packfile);
153     if (readin != sizes[part]) {
154         fprintf(stderr, "short read: %d %ld %ld %ld\n", part, (long)offs[part], (long)sizes[part], (long)readin);
155     }
156     return readin;
157 }
158
159 void doener_decompress_part(unsigned char *out, const unsigned char *in, size_t readin)
160 {
161     const uint32_t flags = LZMA_TELL_UNSUPPORTED_CHECK | LZMA_CONCATENATED;
162     lzma_stream strm = LZMA_STREAM_INIT;
163
164     lzma_ret ret = lzma_auto_decoder(&strm, lzma_easy_decoder_memusage(preset), flags); 
165
166     strm.next_in = in;
167     strm.avail_in = readin;
168     strm.next_out = out;
169     strm.avail_out = bsize;
170
171     while (1) {
172         ret = lzma_code(&strm, LZMA_RUN);
173 //      fprintf(logger, "ret %d\n", ret);
174         if (ret != LZMA_OK)
175             break;
176     }
177
178     //assert (ret == LZMA_OK);
179     lzma_end(&strm);
180 }