2 * Copyright (c) 2012, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
21 #include "solv_xfopen.h"
22 #include "repo_arch.h"
24 static long long parsenum(unsigned char *p, int cnt)
32 x = *p & 0x40 ? (-1 << 8 | *p) : (*p ^ 0x80);
37 while (cnt > 0 && (*p == ' ' || *p == '\t'))
41 for (; cnt > 0 && *p >= '0' && *p < '8'; cnt--, p++)
42 x = (x << 3) | (*p - '0');
46 static int readblock(FILE *fp, unsigned char *blk)
51 r = fread(blk + l, 1, 512 - l, fp);
61 unsigned char blk[512];
71 static char *getsentry(struct tarhead *th, char *s, int size)
74 if (th->eof || size <= 1)
76 size--; /* terminating 0 */
80 for (i = th->off; i < th->end; i++)
84 if (!size || th->blk[i] == '\n')
94 if (readblock(th->fp, th->blk))
100 th->end = th->length > 512 ? 512 : th->length;
101 th->length -= th->end;
105 static void skipentry(struct tarhead *th)
107 for (; th->length > 0; th->length -= 512)
109 if (readblock(th->fp, th->blk))
117 th->off = th->end = 0;
120 static void inittarhead(struct tarhead *th, FILE *fp)
122 memset(th, 0, sizeof(*th));
126 static void freetarhead(struct tarhead *th)
131 static int gettarhead(struct tarhead *th)
136 th->path = solv_free(th->path);
146 int r = readblock(th->fp, th->blk);
161 length = parsenum(th->blk + 124, 12);
165 switch (th->blk[156])
171 /* hard link, special length magic... */
178 case '2': case '3': case '4': case '6':
181 case 'X': case 'x': case 'L':
184 if (length < 1 || length >= 1024 * 1024)
187 data = pp = solv_malloc(l + 512);
188 for (; l > 0; l -= 512, pp += 512)
189 if (readblock(th->fp, (unsigned char *)pp))
194 type = 3; /* extension */
195 if (th->blk[156] == 'L')
207 for (l = 0; l < length && pp[l] >= '0' && pp[l] <= '9'; l++)
208 ll = ll * 10 + (pp[l] - '0');
209 if (l == length || pp[l] != ' ' || ll < 1 || ll > length || pp[ll - 1] != '\n')
218 if (!strncmp(pp, "path=", 5))
221 th->path = solv_strdup(pp + 5);
231 type = 3; /* extension */
234 if ((type == 1 || type == 2) && !th->path)
237 memcpy(path, th->blk, 156);
239 if (!memcmp(th->blk + 257, "ustar\0\060\060", 8) && !th->path && th->blk[345])
241 /* POSIX ustar with prefix */
243 memcpy(prefix, th->blk + 345, 155);
246 if (prefix[l - 1] == '/')
248 th->path = solv_dupjoin(prefix, "/", path);
251 th->path = solv_dupjoin(path, 0, 0);
253 if (type == 1 || type == 2)
255 l = strlen(th->path);
256 if (l && th->path[l - 1] == '/')
267 r = readblock(th->fp, th->blk);
279 adddep(Repo *repo, Offset olddeps, char *line)
281 Pool *pool = repo->pool;
285 while (*line == ' ' && *line == '\t')
288 while (*p && *p != ' ' && *p != '\t' && *p != '<' && *p != '=' && *p != '>')
290 id = pool_strn2id(pool, line, p - line, 1);
291 while (*p == ' ' && *p == '\t')
293 if (*p == '<' || *p == '=' || *p == '>')
307 while (*p == ' ' && *p == '\t')
310 while (*p && *p != ' ' && *p != '\t')
312 id = pool_rel2id(pool, id, pool_strn2id(pool, line, p - line, 1), flags, 1);
314 return repo_addid_dep(repo, olddeps, id, 0);
318 repo_add_arch_pkg(Repo *repo, const char *fn, int flags)
320 Pool *pool = repo->pool;
329 void *pkgidhandle = 0;
331 data = repo_add_repodata(repo, flags);
332 if ((fd = open(fn, O_RDONLY, 0)) < 0)
334 pool_debug(pool, SOLV_ERROR, "repo_add_arch_pkg: %s: %s\n", fn, strerror(errno));
339 pool_debug(pool, SOLV_ERROR, "repo_add_arch_pkg: %s: fstat failed\n", fn);
343 if (!(fp = solv_xfopen_fd(fn, fd, "r")))
345 pool_debug(pool, SOLV_ERROR, "repo_add_arch_pkg: %s: fdopen failed\n", fn);
350 inittarhead(&th, fp);
351 while (gettarhead(&th) > 0)
353 if (th.type != 1 || strcmp(th.path, ".PKGINFO") != 0)
359 s = pool_id2solvable(pool, repo_add_solvable(repo));
360 if (flags & ARCH_ADD_WITH_PKGID)
361 pkgidhandle = solv_chksum_create(REPOKEY_TYPE_MD5);
362 while (getsentry(&th, line, sizeof(line)))
368 solv_chksum_add(pkgidhandle, line, l);
369 if (line[l - 1] != '\n')
380 if (l == 0 || line[0] == '#')
382 if (!strncmp(line, "pkgname = ", 10))
383 s->name = pool_str2id(pool, line + 10, 1);
384 else if (!strncmp(line, "pkgver = ", 9))
385 s->evr = pool_str2id(pool, line + 9, 1);
386 else if (!strncmp(line, "pkgdesc = ", 10))
388 repodata_set_str(data, s - pool->solvables, SOLVABLE_SUMMARY, line + 10);
389 repodata_set_str(data, s - pool->solvables, SOLVABLE_DESCRIPTION, line + 10);
391 else if (!strncmp(line, "url = ", 6))
392 repodata_set_str(data, s - pool->solvables, SOLVABLE_URL, line + 6);
393 else if (!strncmp(line, "builddate = ", 12))
394 repodata_set_num(data, s - pool->solvables, SOLVABLE_BUILDTIME, strtoull(line + 12, 0, 10));
395 else if (!strncmp(line, "packager = ", 11))
396 repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_PACKAGER, line + 11);
397 else if (!strncmp(line, "size = ", 7))
398 repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLSIZE, strtoull(line + 7, 0, 10));
399 else if (!strncmp(line, "arch = ", 7))
400 s->arch = pool_str2id(pool, line + 7, 1);
401 else if (!strncmp(line, "license = ", 10))
402 repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_LICENSE, line + 10);
403 else if (!strncmp(line, "replaces = ", 11))
404 s->obsoletes = adddep(repo, s->obsoletes, line + 11);
405 else if (!strncmp(line, "group = ", 8))
406 repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_GROUP, line + 8);
407 else if (!strncmp(line, "depend = ", 9))
408 s->requires = adddep(repo, s->requires, line + 9);
409 else if (!strncmp(line, "optdepend = ", 12))
411 char *p = strchr(line, ':');
414 s->suggests = adddep(repo, s->suggests, line + 12);
416 else if (!strncmp(line, "conflict = ", 11))
417 s->conflicts = adddep(repo, s->conflicts, line + 11);
418 else if (!strncmp(line, "provides = ", 11))
419 s->provides = adddep(repo, s->provides, line + 11);
427 repo_free_solvable_block(repo, s - pool->solvables, 1, 1);
433 s->arch = ARCH_NOARCH;
436 s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
437 repodata_set_location(data, s - pool->solvables, 0, 0, fn);
438 repodata_set_num(data, s - pool->solvables, SOLVABLE_DOWNLOADSIZE, (unsigned long long)stb.st_size);
441 unsigned char pkgid[16];
442 solv_chksum_free(pkgidhandle, pkgid);
443 repodata_set_bin_checksum(data, s - pool->solvables, SOLVABLE_PKGID, REPOKEY_TYPE_MD5, pkgid);
448 solv_chksum_free(pkgidhandle, 0);
449 if (!(flags & REPO_NO_INTERNALIZE))
450 repodata_internalize(data);
451 return s ? s - pool->solvables : 0;
454 static char *getsentrynl(struct tarhead *th, char *s, int size)
457 if (!getsentry(th, s, size))
465 if (l && s[l - 1] == '\n')
470 while (getsentry(th, s, size))
473 if (!l || s[l - 1] == '\n')
481 repo_add_arch_repo(Repo *repo, FILE *fp, int flags)
483 Pool *pool = repo->pool;
485 data = repo_add_repodata(repo, flags);
488 int l, lastdnlen = 0;
493 inittarhead(&th, fp);
494 while (gettarhead(&th) > 0)
502 bn = strrchr(th.path, '/');
503 if (!bn || (strcmp(bn + 1, "desc") != 0 && strcmp(bn + 1, "depends") != 0))
508 if (!lastdn || (bn - th.path) != lastdnlen || strncmp(lastdn, th.path, lastdnlen) != 0)
514 repo_free_solvable_block(repo, s - pool->solvables, 1, 1);
520 s->arch = ARCH_NOARCH;
523 s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
527 lastdn = solv_strdup(th.path);
528 lastdnlen = bn - th.path;
529 s = pool_id2solvable(pool, repo_add_solvable(repo));
532 while (getsentry(&th, line, sizeof(line)))
535 if (l == 0 || line[l - 1] != '\n')
538 if (l <= 2 || line[0] != '%' || line[l - 1] != '%')
540 if (!strcmp(line, "%FILENAME%"))
542 if (getsentrynl(&th, line, sizeof(line)))
543 repodata_set_location(data, s - pool->solvables, 0, 0, line);
545 else if (!strcmp(line, "%NAME%"))
547 if (getsentrynl(&th, line, sizeof(line)))
548 s->name = pool_str2id(pool, line, 1);
550 else if (!strcmp(line, "%VERSION%"))
552 if (getsentrynl(&th, line, sizeof(line)))
553 s->evr = pool_str2id(pool, line, 1);
555 else if (!strcmp(line, "%DESC%"))
557 if (getsentrynl(&th, line, sizeof(line)))
559 repodata_set_str(data, s - pool->solvables, SOLVABLE_SUMMARY, line);
560 repodata_set_str(data, s - pool->solvables, SOLVABLE_DESCRIPTION, line);
563 else if (!strcmp(line, "%GROUPS%"))
565 if (getsentrynl(&th, line, sizeof(line)))
566 repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_GROUP, line);
568 else if (!strcmp(line, "%CSIZE%"))
570 if (getsentrynl(&th, line, sizeof(line)))
571 repodata_set_num(data, s - pool->solvables, SOLVABLE_DOWNLOADSIZE, strtoull(line, 0, 10));
573 else if (!strcmp(line, "%ISIZE%"))
575 if (getsentrynl(&th, line, sizeof(line)))
576 repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLSIZE, strtoull(line, 0, 10));
578 else if (!strcmp(line, "%MD5SUM%"))
580 if (getsentrynl(&th, line, sizeof(line)) && !havesha256)
581 repodata_set_checksum(data, s - pool->solvables, SOLVABLE_CHECKSUM, REPOKEY_TYPE_MD5, line);
583 else if (!strcmp(line, "%SHA256SUM%"))
585 if (getsentrynl(&th, line, sizeof(line)))
587 repodata_set_checksum(data, s - pool->solvables, SOLVABLE_CHECKSUM, REPOKEY_TYPE_SHA256, line);
591 else if (!strcmp(line, "%URL%"))
593 if (getsentrynl(&th, line, sizeof(line)))
594 repodata_set_str(data, s - pool->solvables, SOLVABLE_URL, line);
596 else if (!strcmp(line, "%LICENSE%"))
598 if (getsentrynl(&th, line, sizeof(line)))
599 repodata_set_str(data, s - pool->solvables, SOLVABLE_LICENSE, line);
601 else if (!strcmp(line, "%ARCH%"))
603 if (getsentrynl(&th, line, sizeof(line)))
604 s->arch = pool_str2id(pool, line, 1);
606 else if (!strcmp(line, "%BUILDDATE%"))
608 if (getsentrynl(&th, line, sizeof(line)))
609 repodata_set_num(data, s - pool->solvables, SOLVABLE_BUILDTIME, strtoull(line, 0, 10));
611 else if (!strcmp(line, "%PACKAGER%"))
613 if (getsentrynl(&th, line, sizeof(line)))
614 repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_PACKAGER, line);
616 else if (!strcmp(line, "%REPLACES%"))
618 while (getsentrynl(&th, line, sizeof(line)) && *line)
619 s->obsoletes = adddep(repo, s->obsoletes, line);
621 else if (!strcmp(line, "%DEPENDS%"))
623 while (getsentrynl(&th, line, sizeof(line)) && *line)
624 s->requires = adddep(repo, s->requires, line);
626 else if (!strcmp(line, "%CONFLICTS%"))
628 while (getsentrynl(&th, line, sizeof(line)) && *line)
629 s->conflicts = adddep(repo, s->conflicts, line);
631 else if (!strcmp(line, "%PROVIDES%"))
633 while (getsentrynl(&th, line, sizeof(line)) && *line)
634 s->provides = adddep(repo, s->provides, line);
636 else if (!strcmp(line, "%OPTDEPENDS%"))
638 while (getsentrynl(&th, line, sizeof(line)) && *line)
640 char *p = strchr(line, ':');
643 s->suggests = adddep(repo, s->suggests, line);
647 getsentrynl(&th, line, sizeof(line));
654 repo_free_solvable_block(repo, s - pool->solvables, 1, 1);
660 s->arch = ARCH_NOARCH;
663 s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
666 if (!(flags & REPO_NO_INTERNALIZE))
667 repodata_internalize(data);