X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=ext%2Frepo_deb.c;h=5af0c70b942b5537410b59f3d9da5c8d12c90296;hb=2d84f3efc00621de607022f3d7bb91f6c109fc69;hp=9aaa3c1d5dbf7e7fc0a802bb5202b4da3e935db5;hpb=9bbaf91bc428daef376f80a030909546e237b64d;p=platform%2Fupstream%2Flibsolv.git diff --git a/ext/repo_deb.c b/ext/repo_deb.c index 9aaa3c1..5af0c70 100644 --- a/ext/repo_deb.c +++ b/ext/repo_deb.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "pool.h" #include "repo.h" @@ -29,7 +30,7 @@ decompress(unsigned char *in, int inl, int *outlp) memset(&strm, 0, sizeof(strm)); strm.next_in = in; strm.avail_in = inl; - out = sat_malloc(4096); + out = solv_malloc(4096); strm.next_out = out; strm.avail_out = 4096; outl = 0; @@ -44,7 +45,7 @@ decompress(unsigned char *in, int inl, int *outlp) if (strm.avail_out == 0) { outl += 4096; - out = sat_realloc(out, outl + 4096); + out = solv_realloc(out, outl + 4096); strm.next_out = out + outl; strm.avail_out = 4096; } @@ -63,88 +64,101 @@ decompress(unsigned char *in, int inl, int *outlp) return out; } -static unsigned int -makedeps(Repo *repo, char *deps, unsigned int olddeps, Id marker) +static Id +parseonedep(Pool *pool, char *p) { - Pool *pool = repo->pool; - char *p, *n, *ne, *e, *ee; - Id id, name, evr; + char *n, *ne, *e, *ee; + Id name, evr; int flags; - while ((p = strchr(deps, ',')) != 0) + while (*p == ' ' || *p == '\t' || *p == '\n') + p++; + if (!*p || *p == '(') + return 0; + n = p; + /* find end of name */ + while (*p && *p != ' ' && *p != '\t' && *p != '\n' && *p != '(' && *p != '|') + p++; + ne = p; + while (*p == ' ' || *p == '\t' || *p == '\n') + p++; + evr = 0; + flags = 0; + e = ee = 0; + if (*p == '(') { - *p++ = 0; - olddeps = makedeps(repo, deps, olddeps, marker); - deps = p; - } - id = 0; - p = deps; - for (;;) - { - while (*p == ' ' || *p == '\t' || *p == '\n') - p++; - if (!*p || *p == '(') - break; - n = p; - while (*p && *p != ' ' && *p != '\t' && *p != '\n' && *p != '(' && *p != '|') - p++; - ne = p; + p++; while (*p == ' ' || *p == '\t' || *p == '\n') p++; - evr = 0; - flags = 0; - e = ee = 0; - if (*p == '(') + if (*p == '>') + flags |= REL_GT; + else if (*p == '=') + flags |= REL_EQ; + else if (*p == '<') + flags |= REL_LT; + if (flags) { p++; - while (*p == ' ' || *p == '\t' || *p == '\n') - p++; if (*p == '>') flags |= REL_GT; else if (*p == '=') flags |= REL_EQ; else if (*p == '<') flags |= REL_LT; - if (flags) - { - p++; - if (*p == '>') - flags |= REL_GT; - else if (*p == '=') - flags |= REL_EQ; - else if (*p == '<') - flags |= REL_LT; - else - p--; - p++; - } - while (*p == ' ' || *p == '\t' || *p == '\n') - p++; - e = p; - while (*p && *p != ' ' && *p != '\t' && *p != '\n' && *p != ')') - p++; - ee = p; - while (*p && *p != ')') - p++; - if (*p) - p++; - while (*p == ' ' || *p == '\t' || *p == '\n') - p++; - } - name = strn2id(pool, n, ne - n, 1); - if (e) - { - evr = strn2id(pool, e, ee - e, 1); - name = rel2id(pool, name, evr, flags, 1); + else + p--; + p++; } - if (!id) - id = name; - else - id = rel2id(pool, id, name, REL_OR, 1); - if (*p != '|') - break; - p++; + while (*p == ' ' || *p == '\t' || *p == '\n') + p++; + e = p; + while (*p && *p != ' ' && *p != '\t' && *p != '\n' && *p != ')') + p++; + ee = p; + while (*p && *p != ')') + p++; + if (*p) + p++; + while (*p == ' ' || *p == '\t' || *p == '\n') + p++; + } + if (ne - n > 4 && ne[-4] == ':' && !strncmp(ne - 4, ":any", 4)) + { + /* multiarch annotation */ + name = pool_strn2id(pool, n, ne - n - 4, 1); + name = pool_rel2id(pool, name, ARCH_ANY, REL_MULTIARCH, 1); + } + else + name = pool_strn2id(pool, n, ne - n, 1); + if (e) + { + evr = pool_strn2id(pool, e, ee - e, 1); + name = pool_rel2id(pool, name, evr, flags, 1); + } + if (*p == '|') + { + Id id = parseonedep(pool, p + 1); + if (id) + name = pool_rel2id(pool, name, id, REL_OR, 1); + } + return name; +} + +static unsigned int +makedeps(Repo *repo, char *deps, unsigned int olddeps, Id marker) +{ + Pool *pool = repo->pool; + char *p; + Id id; + + while ((p = strchr(deps, ',')) != 0) + { + *p = 0; + olddeps = makedeps(repo, deps, olddeps, marker); + *p = ','; + deps = p + 1; } + id = parseonedep(pool, deps); if (!id) return olddeps; return repo_addid_dep(repo, olddeps, id, marker); @@ -160,6 +174,10 @@ control2solvable(Solvable *s, Repodata *data, char *control) Pool *pool = repo->pool; char *p, *q, *end, *tag; int x, l; + int havesource = 0; + char checksum[32 * 2 + 1]; + Id checksumtype = 0; + Id newtype; p = control; while (*p) @@ -202,7 +220,7 @@ control2solvable(Solvable *s, Repodata *data, char *control) { case 'A' << 8 | 'R': if (!strcasecmp(tag, "architecture")) - s->arch = str2id(pool, q, 1); + s->arch = pool_str2id(pool, q, 1); break; case 'B' << 8 | 'R': if (!strcasecmp(tag, "breaks")) @@ -232,17 +250,28 @@ control2solvable(Solvable *s, Repodata *data, char *control) if (!strcasecmp(tag, "enhances")) s->enhances = makedeps(repo, q, s->enhances, 0); break; + case 'F' << 8 | 'I': + if (!strcasecmp(tag, "filename")) + repodata_set_location(data, s - pool->solvables, 0, 0, q); + break; case 'H' << 8 | 'O': if (!strcasecmp(tag, "homepage")) repodata_set_str(data, s - pool->solvables, SOLVABLE_URL, q); break; case 'I' << 8 | 'N': if (!strcasecmp(tag, "installed-size")) - repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLSIZE, atoi(q)); + repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLSIZE, strtoull(q, 0, 10) << 10); + break; + case 'M' << 8 | 'D': + if (!strcasecmp(tag, "md5sum") && !checksumtype && strlen(q) == 16 * 2) + { + strcpy(checksum, q); + checksumtype = REPOKEY_TYPE_MD5; + } break; case 'P' << 8 | 'A': if (!strcasecmp(tag, "package")) - s->name = str2id(pool, q, 1); + s->name = pool_str2id(pool, q, 1); break; case 'P' << 8 | 'R': if (!strcasecmp(tag, "pre-depends")) @@ -252,29 +281,89 @@ control2solvable(Solvable *s, Repodata *data, char *control) break; case 'R' << 8 | 'E': if (!strcasecmp(tag, "replaces")) - s->obsoletes = makedeps(repo, q, s->conflicts, 0); + s->obsoletes = makedeps(repo, q, s->obsoletes, 0); else if (!strcasecmp(tag, "recommends")) s->recommends = makedeps(repo, q, s->recommends, 0); break; + case 'S' << 8 | 'H': + newtype = solv_chksum_str2type(tag); + if (!newtype || solv_chksum_len(newtype) * 2 != strlen(q)) + break; + if (!checksumtype || (newtype == REPOKEY_TYPE_SHA1 && checksumtype != REPOKEY_TYPE_SHA256) || newtype == REPOKEY_TYPE_SHA256) + { + strcpy(checksum, q); + checksumtype = newtype; + } + break; + case 'S' << 8 | 'O': + if (!strcasecmp(tag, "source")) + { + char *q2; + /* ignore version for now */ + for (q2 = q; *q2; q2++) + if (*q2 == ' ' || *q2 == '\t') + { + *q2 = 0; + break; + } + if (s->name && !strcmp(q, pool_id2str(pool, s->name))) + repodata_set_void(data, s - pool->solvables, SOLVABLE_SOURCENAME); + else + repodata_set_id(data, s - pool->solvables, SOLVABLE_SOURCENAME, pool_str2id(pool, q, 1)); + havesource = 1; + } + break; case 'S' << 8 | 'U': if (!strcasecmp(tag, "suggests")) s->suggests = makedeps(repo, q, s->suggests, 0); break; case 'V' << 8 | 'E': if (!strcasecmp(tag, "version")) - s->evr = str2id(pool, q, 1); + s->evr = pool_str2id(pool, q, 1); break; } } + if (checksumtype) + repodata_set_checksum(data, s - pool->solvables, SOLVABLE_CHECKSUM, checksumtype, checksum); if (!s->arch) s->arch = ARCH_ALL; if (!s->evr) s->evr = ID_EMPTY; if (s->name) - s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); + s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); + if (s->name && !havesource) + repodata_set_void(data, s - pool->solvables, SOLVABLE_SOURCENAME); + if (s->obsoletes) + { + /* obsoletes only count when the packages also conflict */ + /* XXX: should not transcode here */ + int i, j, k; + Id d, cid; + for (i = j = s->obsoletes; (d = repo->idarraydata[i]) != 0; i++) + { + if (!s->conflicts) + continue; + for (k = s->conflicts; (cid = repo->idarraydata[k]) != 0; k++) + { + if (repo->idarraydata[k] == cid) + break; + if (ISRELDEP(cid)) + { + Reldep *rd = GETRELDEP(pool, cid); + if (rd->flags < 8 && rd->name == d) + break; /* specialize obsoletes */ + } + } + if (cid) + repo->idarraydata[j++] = cid; + } + repo->idarraydata[j] = 0; + if (j == s->obsoletes) + s->obsoletes = 0; + } } -void +int repo_add_debpackages(Repo *repo, FILE *fp, int flags) { Pool *pool = repo->pool; @@ -284,7 +373,7 @@ repo_add_debpackages(Repo *repo, FILE *fp, int flags) Solvable *s; data = repo_add_repodata(repo, flags); - buf = sat_malloc(4096); + buf = solv_malloc(4096); bufl = 4096; l = 0; buf[l] = 0; @@ -296,7 +385,7 @@ repo_add_debpackages(Repo *repo, FILE *fp, int flags) int l3; if (l + 1024 >= bufl) { - buf = sat_realloc(buf, bufl + 4096); + buf = solv_realloc(buf, bufl + 4096); bufl += 4096; p = buf + l; continue; @@ -319,7 +408,7 @@ repo_add_debpackages(Repo *repo, FILE *fp, int flags) s = pool_id2solvable(pool, repo_add_solvable(repo)); control2solvable(s, data, buf); if (!s->name) - repo_free_solvable_block(repo, s - pool->solvables, 1, 1); + repo_free_solvable(repo, s - pool->solvables, 1); if (l > ll) memmove(buf, p + 1, l - ll); l -= ll; @@ -331,20 +420,35 @@ repo_add_debpackages(Repo *repo, FILE *fp, int flags) s = pool_id2solvable(pool, repo_add_solvable(repo)); control2solvable(s, data, buf); if (!s->name) - repo_free_solvable_block(repo, s - pool->solvables, 1, 1); + repo_free_solvable(repo, s - pool->solvables, 1); } - sat_free(buf); + solv_free(buf); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); + return 0; } -void -repo_add_debs(Repo *repo, const char **debs, int ndebs, int flags) +int +repo_add_debdb(Repo *repo, int flags) +{ + FILE *fp; + const char *path = "/var/lib/dpkg/status"; + if (flags & REPO_USE_ROOTDIR) + path = pool_prepend_rootdir_tmp(repo->pool, path); + if ((fp = fopen(path, "r")) == 0) + return pool_error(repo->pool, -1, "%s: %s", path, strerror(errno)); + repo_add_debpackages(repo, fp, flags); + fclose(fp); + return 0; +} + +Id +repo_add_deb(Repo *repo, const char *deb, int flags) { Pool *pool = repo->pool; Repodata *data; unsigned char buf[4096], *bp; - int i, l, l2, vlen, clen, ctarlen; + int l, l2, vlen, clen, ctarlen; unsigned char *ctgz; unsigned char pkgid[16]; unsigned char *ctar; @@ -354,158 +458,158 @@ repo_add_debs(Repo *repo, const char **debs, int ndebs, int flags) struct stat stb; data = repo_add_repodata(repo, flags); - for (i = 0; i < ndebs; i++) + if ((fp = fopen(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(pool, deb) : deb, "r")) == 0) { - if ((fp = fopen(debs[i], "r")) == 0) - { - perror(debs[i]); - continue; - } - if (fstat(fileno(fp), &stb)) - { - perror("stat"); - continue; - } - l = fread(buf, 1, sizeof(buf), fp); - if (l < 8 + 60 || strncmp((char *)buf, "!\ndebian-binary ", 8 + 16) != 0) - { - fprintf(stderr, "%s: not a deb package\n", debs[i]); - fclose(fp); - continue; - } - vlen = atoi((char *)buf + 8 + 48); - if (vlen < 0 || vlen > l) - { - fprintf(stderr, "%s: not a deb package\n", debs[i]); - fclose(fp); - continue; - } - vlen += vlen & 1; - if (l < 8 + 60 + vlen + 60) - { - fprintf(stderr, "%s: unhandled deb package\n", debs[i]); - fclose(fp); - continue; - } - if (strncmp((char *)buf + 8 + 60 + vlen, "control.tar.gz ", 16) != 0) - { - fprintf(stderr, "%s: control.tar.gz is not second entry\n", debs[i]); - fclose(fp); - continue; - } - clen = atoi((char *)buf + 8 + 60 + vlen + 48); - if (clen <= 0) - { - fprintf(stderr, "%s: control.tar.gz has illegal size\n", debs[i]); - fclose(fp); - continue; - } - ctgz = sat_calloc(1, clen + 4); - bp = buf + 8 + 60 + vlen + 60; - l -= 8 + 60 + vlen + 60; - if (l > clen) - l = clen; - if (l) - memcpy(ctgz, bp, l); - if (l < clen) - { - if (fread(ctgz + l, clen - l, 1, fp) != 1) - { - fprintf(stderr, "%s: unexpected EOF\n", debs[i]); - sat_free(ctgz); - fclose(fp); - continue; - } - } + pool_error(pool, -1, "%s: %s", deb, strerror(errno)); + return 0; + } + if (fstat(fileno(fp), &stb)) + { + pool_error(pool, -1, "fstat: %s", strerror(errno)); fclose(fp); - gotpkgid = 0; - if (flags & DEBS_ADD_WITH_PKGID) - { - void *handle = sat_chksum_create(REPOKEY_TYPE_MD5); - sat_chksum_add(handle, ctgz, clen); - sat_chksum_free(handle, pkgid); - gotpkgid = 1; - } - if (ctgz[0] != 0x1f || ctgz[1] != 0x8b) - { - fprintf(stderr, "%s: control.tar.gz is not gzipped\n", debs[i]); - sat_free(ctgz); - continue; - } - if (ctgz[2] != 8 || (ctgz[3] & 0xe0) != 0) - { - fprintf(stderr, "%s: control.tar.gz is compressed in a strange way\n", debs[i]); - sat_free(ctgz); - continue; - } - bp = ctgz + 4; - bp += 6; /* skip time, xflags and OS code */ - if (ctgz[3] & 0x04) + return 0; + } + l = fread(buf, 1, sizeof(buf), fp); + if (l < 8 + 60 || strncmp((char *)buf, "!\ndebian-binary ", 8 + 16) != 0) + { + pool_error(pool, -1, "%s: not a deb package", deb); + fclose(fp); + return 0; + } + vlen = atoi((char *)buf + 8 + 48); + if (vlen < 0 || vlen > l) + { + pool_error(pool, -1, "%s: not a deb package", deb); + fclose(fp); + return 0; + } + vlen += vlen & 1; + if (l < 8 + 60 + vlen + 60) + { + pool_error(pool, -1, "%s: unhandled deb package", deb); + fclose(fp); + return 0; + } + if (strncmp((char *)buf + 8 + 60 + vlen, "control.tar.gz ", 16) != 0) + { + pool_error(pool, -1, "%s: control.tar.gz is not second entry", deb); + fclose(fp); + return 0; + } + clen = atoi((char *)buf + 8 + 60 + vlen + 48); + if (clen <= 0 || clen >= 0x100000) + { + pool_error(pool, -1, "%s: control.tar.gz has illegal size", deb); + fclose(fp); + return 0; + } + ctgz = solv_calloc(1, clen + 4); + bp = buf + 8 + 60 + vlen + 60; + l -= 8 + 60 + vlen + 60; + if (l > clen) + l = clen; + if (l) + memcpy(ctgz, bp, l); + if (l < clen) + { + if (fread(ctgz + l, clen - l, 1, fp) != 1) { - /* skip extra field */ - l = bp[0] | bp[1] << 8; - bp += l + 2; - if (bp >= ctgz + clen) - { - fprintf(stderr, "%s: corrupt gzip\n", debs[i]); - sat_free(ctgz); - continue; - } + pool_error(pool, -1, "%s: unexpected EOF", deb); + solv_free(ctgz); + fclose(fp); + return 0; } - if (ctgz[3] & 0x08) /* orig filename */ - while (*bp) - bp++; - if (ctgz[3] & 0x10) /* file comment */ - while (*bp) - bp++; - if (ctgz[3] & 0x02) /* header crc */ - bp += 2; + } + fclose(fp); + gotpkgid = 0; + if (flags & DEBS_ADD_WITH_PKGID) + { + Chksum *chk = solv_chksum_create(REPOKEY_TYPE_MD5); + solv_chksum_add(chk, ctgz, clen); + solv_chksum_free(chk, pkgid); + gotpkgid = 1; + } + if (ctgz[0] != 0x1f || ctgz[1] != 0x8b) + { + pool_error(pool, -1, "%s: control.tar.gz is not gzipped", deb); + solv_free(ctgz); + return 0; + } + if (ctgz[2] != 8 || (ctgz[3] & 0xe0) != 0) + { + pool_error(pool, -1, "%s: control.tar.gz is compressed in a strange way", deb); + solv_free(ctgz); + return 0; + } + bp = ctgz + 4; + bp += 6; /* skip time, xflags and OS code */ + if (ctgz[3] & 0x04) + { + /* skip extra field */ + l = bp[0] | bp[1] << 8; + bp += l + 2; if (bp >= ctgz + clen) { - fprintf(stderr, "%s: corrupt control.tar.gz\n", debs[i]); - sat_free(ctgz); - continue; - } - ctar = decompress(bp, ctgz + clen - bp, &ctarlen); - sat_free(ctgz); - if (!ctar) - { - fprintf(stderr, "%s: corrupt control.tar.gz\n", debs[i]); - continue; - } - bp = ctar; - l = ctarlen; - while (l > 512) - { - int j; - l2 = 0; - for (j = 124; j < 124 + 12; j++) - if (bp[j] >= '0' && bp[j] <= '7') - l2 = l2 * 8 + (bp[j] - '0'); - if (!strcmp((char *)bp, "./control")) - break; - l2 = 512 + ((l2 + 511) & ~511); - l -= l2; - bp += l2; - } - if (l <= 512 || l - 512 - l2 <= 0 || l2 <= 0) - { - fprintf(stderr, "%s: control.tar.gz contains no ./control file\n", debs[i]); - free(ctar); - continue; + pool_error(pool, -1, "%s: control.tar.gz is corrupt", deb); + solv_free(ctgz); + return 0; } - memmove(ctar, bp + 512, l2); - ctar = sat_realloc(ctar, l2 + 1); - ctar[l2] = 0; - s = pool_id2solvable(pool, repo_add_solvable(repo)); - control2solvable(s, data, (char *)ctar); - repodata_set_location(data, s - pool->solvables, 0, 0, debs[i]); - if (S_ISREG(stb.st_mode)) - repodata_set_num(data, s - pool->solvables, SOLVABLE_DOWNLOADSIZE, (unsigned int)((stb.st_size + 1023) / 1024)); - if (gotpkgid) - repodata_set_bin_checksum(data, s - pool->solvables, SOLVABLE_PKGID, REPOKEY_TYPE_MD5, pkgid); - sat_free(ctar); } + if (ctgz[3] & 0x08) /* orig filename */ + while (*bp) + bp++; + if (ctgz[3] & 0x10) /* file comment */ + while (*bp) + bp++; + if (ctgz[3] & 0x02) /* header crc */ + bp += 2; + if (bp >= ctgz + clen) + { + pool_error(pool, -1, "%s: control.tar.gz is corrupt", deb); + solv_free(ctgz); + return 0; + } + ctar = decompress(bp, ctgz + clen - bp, &ctarlen); + solv_free(ctgz); + if (!ctar) + { + pool_error(pool, -1, "%s: control.tar.gz is corrupt", deb); + return 0; + } + bp = ctar; + l = ctarlen; + while (l > 512) + { + int j; + l2 = 0; + for (j = 124; j < 124 + 12; j++) + if (bp[j] >= '0' && bp[j] <= '7') + l2 = l2 * 8 + (bp[j] - '0'); + if (!strcmp((char *)bp, "./control") || !strcmp((char *)bp, "control")) + break; + l2 = 512 + ((l2 + 511) & ~511); + l -= l2; + bp += l2; + } + if (l <= 512 || l - 512 - l2 <= 0 || l2 <= 0) + { + pool_error(pool, -1, "%s: control.tar.gz contains no control file", deb); + free(ctar); + return 0; + } + memmove(ctar, bp + 512, l2); + ctar = solv_realloc(ctar, l2 + 1); + ctar[l2] = 0; + s = pool_id2solvable(pool, repo_add_solvable(repo)); + control2solvable(s, data, (char *)ctar); + if (!(flags & REPO_NO_LOCATION)) + repodata_set_location(data, s - pool->solvables, 0, 0, deb); + if (S_ISREG(stb.st_mode)) + repodata_set_num(data, s - pool->solvables, SOLVABLE_DOWNLOADSIZE, (unsigned long long)stb.st_size); + if (gotpkgid) + repodata_set_bin_checksum(data, s - pool->solvables, SOLVABLE_PKGID, REPOKEY_TYPE_MD5, pkgid); + solv_free(ctar); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); + return s - pool->solvables; }