1 /*
2 * Copyright (c) 2007, Novell Inc.
3 *
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
6 */
7
8 /* pack/unpack functions for key data */
9
10 #ifndef LIBSOLV_REPOPACK_H
11 #define LIBSOLV_REPOPACK_H
12
13 static inline unsigned char *
data_read_id(unsigned char * dp,Id * idp)14 data_read_id(unsigned char *dp, Id *idp)
15 {
16 Id x;
17 unsigned char c;
18 if (!(dp[0] & 0x80))
19 {
20 *idp = dp[0];
21 return dp + 1;
22 }
23 if (!(dp[1] & 0x80))
24 {
25 *idp = dp[0] << 7 ^ dp[1] ^ 0x4000;
26 return dp + 2;
27 }
28 if (!(dp[2] & 0x80))
29 {
30 *idp = dp[0] << 14 ^ dp[1] << 7 ^ dp[2] ^ 0x204000;
31 return dp + 3;
32 }
33 if (!(dp[3] & 0x80))
34 {
35 *idp = dp[0] << 21 ^ dp[1] << 14 ^ dp[2] << 7 ^ dp[3] ^ 0x10204000;
36 return dp + 4;
37 }
38 x = dp[0] << 28 ^ dp[1] << 21 ^ dp[2] << 14 ^ dp[3] << 7 ^ dp[4] ^ 0x10204000;
39 if (!(dp[4] & 0x80))
40 {
41 *idp = x;
42 return dp + 5;
43 }
44 x ^= 80;
45 dp += 5;
46 for (;;)
47 {
48 c = *dp++;
49 if (!(c & 0x80))
50 {
51 *idp = (x << 7) ^ c;
52 return dp;
53 }
54 x = (x << 7) ^ (c ^ 128);
55 }
56 }
57
58 static inline unsigned char *
data_read_num64(unsigned char * dp,unsigned int * low,unsigned int * high)59 data_read_num64(unsigned char *dp, unsigned int *low, unsigned int *high)
60 {
61 unsigned long long int x;
62 unsigned char c;
63
64 *high = 0;
65 if (!(dp[0] & 0x80))
66 {
67 *low = dp[0];
68 return dp + 1;
69 }
70 if (!(dp[1] & 0x80))
71 {
72 *low = dp[0] << 7 ^ dp[1] ^ 0x4000;
73 return dp + 2;
74 }
75 if (!(dp[2] & 0x80))
76 {
77 *low = dp[0] << 14 ^ dp[1] << 7 ^ dp[2] ^ 0x204000;
78 return dp + 3;
79 }
80 if (!(dp[3] & 0x80))
81 {
82 *low = dp[0] << 21 ^ dp[1] << 14 ^ dp[2] << 7 ^ dp[3] ^ 0x10204000;
83 return dp + 4;
84 }
85 if (!(dp[4] & 0x80))
86 {
87 *low = dp[0] << 28 ^ dp[1] << 21 ^ dp[2] << 14 ^ dp[3] << 7 ^ dp[4] ^ 0x10204000;
88 *high = (dp[0] ^ 0x80) >> 4;
89 return dp + 5;
90 }
91 x = (unsigned long long)(dp[0] ^ 0x80) << 28 ^ (unsigned int)(dp[1] << 21 ^ dp[2] << 14 ^ dp[3] << 7 ^ dp[4] ^ 0x10204080);
92 dp += 5;
93 for (;;)
94 {
95 c = *dp++;
96 if (!(c & 0x80))
97 {
98 x = (x << 7) ^ c;
99 *low = x;
100 *high = x >> 32;
101 return dp;
102 }
103 x = (x << 7) ^ (c ^ 128);
104 }
105 }
106
107 static inline unsigned char *
data_read_ideof(unsigned char * dp,Id * idp,int * eof)108 data_read_ideof(unsigned char *dp, Id *idp, int *eof)
109 {
110 Id x = 0;
111 unsigned char c;
112 for (;;)
113 {
114 c = *dp++;
115 if (!(c & 0x80))
116 {
117 if (c & 0x40)
118 {
119 c ^= 0x40;
120 *eof = 0;
121 }
122 else
123 *eof = 1;
124 *idp = (x << 6) ^ c;
125 return dp;
126 }
127 x = (x << 7) ^ c ^ 128;
128 }
129 }
130
131 static inline unsigned char *
data_read_u32(unsigned char * dp,unsigned int * nump)132 data_read_u32(unsigned char *dp, unsigned int *nump)
133 {
134 *nump = (dp[0] << 24) | (dp[1] << 16) | (dp[2] << 8) | dp[3];
135 return dp + 4;
136 }
137
138 static inline unsigned char *
data_fetch(unsigned char * dp,KeyValue * kv,Repokey * key)139 data_fetch(unsigned char *dp, KeyValue *kv, Repokey *key)
140 {
141 kv->eof = 1;
142 if (!dp)
143 return 0;
144 switch (key->type)
145 {
146 case REPOKEY_TYPE_VOID:
147 return dp;
148 case REPOKEY_TYPE_CONSTANT:
149 kv->num2 = 0;
150 kv->num = key->size;
151 return dp;
152 case REPOKEY_TYPE_CONSTANTID:
153 kv->id = key->size;
154 return dp;
155 case REPOKEY_TYPE_STR:
156 kv->str = (const char *)dp;
157 return dp + strlen(kv->str) + 1;
158 case REPOKEY_TYPE_ID:
159 case REPOKEY_TYPE_DIR:
160 return data_read_id(dp, &kv->id);
161 case REPOKEY_TYPE_NUM:
162 return data_read_num64(dp, &kv->num, &kv->num2);
163 case REPOKEY_TYPE_U32:
164 kv->num2 = 0;
165 return data_read_u32(dp, &kv->num);
166 case REPOKEY_TYPE_MD5:
167 kv->num = 0; /* not stringified yet */
168 kv->str = (const char *)dp;
169 return dp + SIZEOF_MD5;
170 case REPOKEY_TYPE_SHA1:
171 kv->num = 0; /* not stringified yet */
172 kv->str = (const char *)dp;
173 return dp + SIZEOF_SHA1;
174 case REPOKEY_TYPE_SHA256:
175 kv->num = 0; /* not stringified yet */
176 kv->str = (const char *)dp;
177 return dp + SIZEOF_SHA256;
178 case REPOKEY_TYPE_BINARY:
179 dp = data_read_id(dp, (Id *)&kv->num);
180 kv->str = (const char *)dp;
181 return dp + kv->num;
182 case REPOKEY_TYPE_IDARRAY:
183 return data_read_ideof(dp, &kv->id, &kv->eof);
184 case REPOKEY_TYPE_DIRSTRARRAY:
185 dp = data_read_ideof(dp, &kv->id, &kv->eof);
186 kv->num = 0; /* not stringified yet */
187 kv->str = (const char *)dp;
188 return dp + strlen(kv->str) + 1;
189 case REPOKEY_TYPE_DIRNUMNUMARRAY:
190 dp = data_read_id(dp, &kv->id);
191 dp = data_read_id(dp, (Id *)&kv->num);
192 return data_read_ideof(dp, (Id *)&kv->num2, &kv->eof);
193 case REPOKEY_TYPE_FIXARRAY:
194 dp = data_read_id(dp, (Id *)&kv->num);
195 return data_read_id(dp, &kv->id);
196 case REPOKEY_TYPE_FLEXARRAY:
197 return data_read_id(dp, (Id *)&kv->num);
198 default:
199 return 0;
200 }
201 }
202
203 static inline unsigned char *
data_skip(unsigned char * dp,int type)204 data_skip(unsigned char *dp, int type)
205 {
206 unsigned char x;
207 switch (type)
208 {
209 case REPOKEY_TYPE_VOID:
210 case REPOKEY_TYPE_CONSTANT:
211 case REPOKEY_TYPE_CONSTANTID:
212 case REPOKEY_TYPE_DELETED:
213 return dp;
214 case REPOKEY_TYPE_ID:
215 case REPOKEY_TYPE_NUM:
216 case REPOKEY_TYPE_DIR:
217 while ((*dp & 0x80) != 0)
218 dp++;
219 return dp + 1;
220 case REPOKEY_TYPE_U32:
221 return dp + 4;
222 case REPOKEY_TYPE_MD5:
223 return dp + SIZEOF_MD5;
224 case REPOKEY_TYPE_SHA1:
225 return dp + SIZEOF_SHA1;
226 case REPOKEY_TYPE_SHA256:
227 return dp + SIZEOF_SHA256;
228 case REPOKEY_TYPE_IDARRAY:
229 case REPOKEY_TYPE_REL_IDARRAY:
230 while ((*dp & 0xc0) != 0)
231 dp++;
232 return dp + 1;
233 case REPOKEY_TYPE_STR:
234 while ((*dp) != 0)
235 dp++;
236 return dp + 1;
237 case REPOKEY_TYPE_BINARY:
238 {
239 unsigned int len;
240 dp = data_read_id(dp, (Id *)&len);
241 return dp + len;
242 }
243 case REPOKEY_TYPE_DIRSTRARRAY:
244 for (;;)
245 {
246 while ((*dp & 0x80) != 0)
247 dp++;
248 x = *dp++;
249 while ((*dp) != 0)
250 dp++;
251 dp++;
252 if (!(x & 0x40))
253 return dp;
254 }
255 case REPOKEY_TYPE_DIRNUMNUMARRAY:
256 for (;;)
257 {
258 while ((*dp & 0x80) != 0)
259 dp++;
260 dp++;
261 while ((*dp & 0x80) != 0)
262 dp++;
263 dp++;
264 while ((*dp & 0x80) != 0)
265 dp++;
266 if (!(*dp & 0x40))
267 return dp + 1;
268 dp++;
269 }
270 default:
271 return 0;
272 }
273 }
274
275 static inline unsigned char *
data_skip_verify(unsigned char * dp,int type,int maxid,int maxdir)276 data_skip_verify(unsigned char *dp, int type, int maxid, int maxdir)
277 {
278 Id id;
279 int eof;
280
281 switch (type)
282 {
283 case REPOKEY_TYPE_VOID:
284 case REPOKEY_TYPE_CONSTANT:
285 case REPOKEY_TYPE_CONSTANTID:
286 case REPOKEY_TYPE_DELETED:
287 return dp;
288 case REPOKEY_TYPE_NUM:
289 while ((*dp & 0x80) != 0)
290 dp++;
291 return dp + 1;
292 case REPOKEY_TYPE_U32:
293 return dp + 4;
294 case REPOKEY_TYPE_MD5:
295 return dp + SIZEOF_MD5;
296 case REPOKEY_TYPE_SHA1:
297 return dp + SIZEOF_SHA1;
298 case REPOKEY_TYPE_SHA256:
299 return dp + SIZEOF_SHA256;
300 case REPOKEY_TYPE_ID:
301 dp = data_read_id(dp, &id);
302 if (id >= maxid)
303 return 0;
304 return dp;
305 case REPOKEY_TYPE_DIR:
306 dp = data_read_id(dp, &id);
307 if (id >= maxdir)
308 return 0;
309 return dp;
310 case REPOKEY_TYPE_IDARRAY:
311 for (;;)
312 {
313 dp = data_read_ideof(dp, &id, &eof);
314 if (id >= maxid)
315 return 0;
316 if (eof)
317 return dp;
318 }
319 case REPOKEY_TYPE_STR:
320 while ((*dp) != 0)
321 dp++;
322 return dp + 1;
323 case REPOKEY_TYPE_BINARY:
324 {
325 unsigned int len;
326 dp = data_read_id(dp, (Id *)&len);
327 return dp + len;
328 }
329 case REPOKEY_TYPE_DIRSTRARRAY:
330 for (;;)
331 {
332 dp = data_read_ideof(dp, &id, &eof);
333 if (id >= maxdir)
334 return 0;
335 while ((*dp) != 0)
336 dp++;
337 dp++;
338 if (eof)
339 return dp;
340 }
341 case REPOKEY_TYPE_DIRNUMNUMARRAY:
342 for (;;)
343 {
344 dp = data_read_id(dp, &id);
345 if (id >= maxdir)
346 return 0;
347 while ((*dp & 0x80) != 0)
348 dp++;
349 dp++;
350 while ((*dp & 0x80) != 0)
351 dp++;
352 if (!(*dp & 0x40))
353 return dp + 1;
354 dp++;
355 }
356 default:
357 return 0;
358 }
359 }
360
361 #endif /* LIBSOLV_REPOPACK */
362