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 * 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 * 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 * 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 * 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 * 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 * 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 * 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