X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=ext%2Frepo_deb.c;h=05d731b3d00cc76b17c07c2d16ff33c1c89f8b88;hb=40d5592805eaa650df84c50b9fed3cbdc4823fc5;hp=6e18acba3bba028e00bd4cb8ad742179a6839728;hpb=e362e8eb31ade170f6b02822e77db5b5a0f057ca;p=platform%2Fupstream%2Flibsolv.git diff --git a/ext/repo_deb.c b/ext/repo_deb.c index 6e18acb..05d731b 100644 --- a/ext/repo_deb.c +++ b/ext/repo_deb.c @@ -12,10 +12,12 @@ #include #include #include +#include #include "pool.h" #include "repo.h" #include "util.h" +#include "solver.h" /* for GET_USERINSTALLED_ flags */ #include "chksum.h" #include "repo_deb.h" @@ -29,7 +31,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 +46,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; } @@ -121,17 +123,24 @@ parseonedep(Pool *pool, char *p) while (*p == ' ' || *p == '\t' || *p == '\n') p++; } - name = strn2id(pool, n, ne - n, 1); + 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 = strn2id(pool, e, ee - e, 1); - name = rel2id(pool, name, evr, flags, 1); + 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 = rel2id(pool, name, id, REL_OR, 1); + name = pool_rel2id(pool, name, id, REL_OR, 1); } return name; } @@ -167,6 +176,9 @@ control2solvable(Solvable *s, Repodata *data, char *control) 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) @@ -193,7 +205,7 @@ control2solvable(Solvable *s, Repodata *data, char *control) if (*p) *p++ = 0; /* strip trailing space */ - while (end >= control && *end == ' ' && *end == '\t') + while (end >= control && (*end == ' ' || *end == '\t')) *end-- = 0; tag = control; control = p; @@ -209,7 +221,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")) @@ -249,11 +261,18 @@ control2solvable(Solvable *s, Repodata *data, char *control) 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")) @@ -263,10 +282,20 @@ 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")) { @@ -278,54 +307,68 @@ control2solvable(Solvable *s, Repodata *data, char *control) *q2 = 0; break; } - if (s->name && !strcmp(q, id2str(pool, s->name))) + 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, str2id(pool, q, 1)); + repodata_set_id(data, s - pool->solvables, SOLVABLE_SOURCENAME, pool_str2id(pool, q, 1)); havesource = 1; } break; + case 'S' << 8 | 'T': + if (!strcasecmp(tag, "status")) + repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_INSTALLSTATUS, q); + 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; + Id d, cid; for (i = j = s->obsoletes; (d = repo->idarraydata[i]) != 0; i++) { - if (s->conflicts) + if (!s->conflicts) + continue; + for (k = s->conflicts; (cid = repo->idarraydata[k]) != 0; k++) { - for (k = s->conflicts; repo->idarraydata[k] != 0; k++) - if (repo->idarraydata[k] == d) - break; - if (repo->idarraydata[k]) + if (repo->idarraydata[k] == cid) + break; + if (ISRELDEP(cid)) { - repo->idarraydata[j++] = d; + 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; @@ -335,7 +378,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; @@ -347,7 +390,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; @@ -370,7 +413,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; @@ -382,20 +425,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; @@ -405,158 +463,247 @@ 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) + 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); + 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) { - fprintf(stderr, "%s: control.tar.gz has illegal size\n", debs[i]); + pool_error(pool, -1, "%s: unexpected EOF", deb); + solv_free(ctgz); 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; - } + return 0; } - fclose(fp); - gotpkgid = 0; - if (flags & DEBS_ADD_WITH_PKGID) + } + 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) { - void *handle = sat_chksum_create(REPOKEY_TYPE_MD5); - sat_chksum_add(handle, ctgz, clen); - sat_chksum_free(handle, pkgid); - gotpkgid = 1; + pool_error(pool, -1, "%s: control.tar.gz is corrupt", deb); + solv_free(ctgz); + return 0; } - if (ctgz[0] != 0x1f || ctgz[1] != 0x8b) + } + 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; +} + +void +pool_deb_get_autoinstalled(Pool *pool, FILE *fp, Queue *q, int flags) +{ + Id name = 0, arch = 0; + int autoinstalled = -1; + char *buf, *bp; + int x, l, bufl, eof = 0; + Id p, pp; + + queue_empty(q); + buf = solv_malloc(4096); + bufl = 4096; + l = 0; + while (!eof) + { + while (bufl - l < 1024) { - fprintf(stderr, "%s: control.tar.gz is not gzipped\n", debs[i]); - sat_free(ctgz); - continue; + bufl += 4096; + if (bufl > 1024 * 64) + break; /* hmm? */ + buf = solv_realloc(buf, bufl); } - if (ctgz[2] != 8 || (ctgz[3] & 0xe0) != 0) + if (!fgets(buf + l, bufl - l, fp)) { - fprintf(stderr, "%s: control.tar.gz is compressed in a strange way\n", debs[i]); - sat_free(ctgz); - continue; + eof = 1; + buf[l] = '\n'; + buf[l + 1] = 0; } - bp = ctgz + 4; - bp += 6; /* skip time, xflags and OS code */ - if (ctgz[3] & 0x04) + l = strlen(buf); + if (l && buf[l - 1] == '\n') + buf[--l] = 0; + if (!*buf || eof) { - /* skip extra field */ - l = bp[0] | bp[1] << 8; - bp += l + 2; - if (bp >= ctgz + clen) + l = 0; + if (name && autoinstalled > 0) { - fprintf(stderr, "%s: corrupt gzip\n", debs[i]); - sat_free(ctgz); - continue; + if ((flags & GET_USERINSTALLED_NAMES) != 0) + queue_push(q, name); + else + { + FOR_PROVIDES(p, pp, name) + { + Solvable *s = pool->solvables + p; + if (s->name != name) + continue; + if (arch && s->arch != arch) + continue; + queue_push(q, p); + } + } } - } - 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) - { - 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]); + name = arch = 0; + autoinstalled = -1; 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) + /* strip trailing space */ + while (l && (buf[l - 1] == ' ' || buf[l - 1] == '\t')) + buf[--l] = 0; + l = 0; + + bp = strchr(buf, ':'); + if (!bp || bp - buf < 4) + continue; + *bp++ = 0; + while (*bp == ' ' || *bp == '\t') + bp++; + x = '@' + (buf[0] & 0x1f); + x = (x << 8) + '@' + (buf[1] & 0x1f); + switch(x) { - fprintf(stderr, "%s: control.tar.gz contains no ./control file\n", debs[i]); - free(ctar); - continue; + case 'P' << 8 | 'A': + if (!strcasecmp(buf, "package")) + name = pool_str2id(pool, bp, 1); + break; + case 'A' << 8 | 'R': + if (!strcasecmp(buf, "architecture")) + arch = pool_str2id(pool, bp, 1); + break; + case 'A' << 8 | 'U': + if (!strcasecmp(buf, "auto-installed")) + autoinstalled = atoi(bp); + break; + default: + break; } - 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 (!(flags & REPO_NO_INTERNALIZE)) - repodata_internalize(data); } +