X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=examples%2Fsolv.c;h=7ca97297e3037e34bd661d2eef618be28c78a610;hb=f6d2b5c95e7e49ab9dde3d81d1b4442c82d627ed;hp=d8cd4c77981c2cbc232ebf73cfbd118c57678f3a;hpb=6ff10d16956d835ca597b082f448c2a06b9426ee;p=platform%2Fupstream%2Flibsolv.git diff --git a/examples/solv.c b/examples/solv.c index d8cd4c7..7ca9729 100644 --- a/examples/solv.c +++ b/examples/solv.c @@ -57,26 +57,33 @@ #include "solverdebug.h" #include "chksum.h" #include "repo_solv.h" +#include "selection.h" #include "repo_write.h" -#ifndef DEBIAN +#ifdef ENABLE_RPMDB #include "repo_rpmdb.h" -#else +#include "pool_fileconflicts.h" +#endif +#ifdef ENABLE_DEBIAN #include "repo_deb.h" #endif -#include "repo_products.h" +#ifdef ENABLE_RPMMD #include "repo_rpmmd.h" -#include "repo_susetags.h" #include "repo_repomdxml.h" #include "repo_updateinfoxml.h" #include "repo_deltainfoxml.h" +#endif +#ifdef ENABLE_SUSEREPO +#include "repo_products.h" +#include "repo_susetags.h" #include "repo_content.h" -#include "pool_fileconflicts.h" -#include "sat_xfopen.h" +#endif +#include "solv_xfopen.h" #ifdef FEDORA # define REPOINFO_PATH "/etc/yum.repos.d" -#else +#endif +#ifdef SUSE # define REPOINFO_PATH "/etc/zypp/repos.d" # define PRODUCTS_PATH "/etc/products.d" # define SOFTLOCKS_PATH "/var/lib/zypp/SoftLocks" @@ -84,7 +91,7 @@ #define SOLVCACHE_PATH "/var/cache/solv" -#define METADATA_EXPIRE (60 * 90) +#define METADATA_EXPIRE (60 * 15) struct repoinfo { Repo *repo; @@ -108,6 +115,7 @@ struct repoinfo { unsigned char cookie[32]; unsigned char extcookie[32]; + int incomplete; }; #ifdef FEDORA @@ -120,9 +128,9 @@ yum_substitute(Pool *pool, char *line) if (!line) { - sat_free(releaseevr); + solv_free(releaseevr); releaseevr = 0; - sat_free(basearch); + solv_free(basearch); basearch = 0; return 0; } @@ -134,14 +142,15 @@ yum_substitute(Pool *pool, char *line) if (!releaseevr) { Queue q; + const char *rootdir = pool_get_rootdir(pool); queue_init(&q); - rpm_installedrpmdbids(0, "Providename", "redhat-release", &q); + rpm_installedrpmdbids(rootdir, "Providename", "redhat-release", &q); if (q.count) { void *handle, *state = 0; char *p; - handle = rpm_byrpmdbid(q.elements[0], 0, &state); + handle = rpm_byrpmdbid(q.elements[0], rootdir, &state); releaseevr = rpm_query(handle, SOLVABLE_EVR); rpm_byrpmdbid(0, 0, &state); if ((p = strchr(releaseevr, '-')) != 0) @@ -149,7 +158,10 @@ yum_substitute(Pool *pool, char *line) } queue_free(&q); if (!releaseevr) - releaseevr = strdup("?"); + { + fprintf(stderr, "no installed package provides 'redhat-release', cannot determine $releasever\n"); + exit(1); + } } *p2 = 0; p = pool_tmpjoin(pool, line, releaseevr, p2 + 11); @@ -191,6 +203,7 @@ yum_substitute(Pool *pool, char *line) #define TYPE_PLAINDIR 3 #define TYPE_DEBIAN 4 +#ifndef NOSYSTEM static int read_repoinfos_sort(const void *ap, const void *bp) { @@ -198,12 +211,14 @@ read_repoinfos_sort(const void *ap, const void *bp) const struct repoinfo *b = bp; return strcmp(a->alias, b->alias); } +#endif -#ifndef DEBIAN +#if defined(SUSE) || defined(FEDORA) struct repoinfo * -read_repoinfos(Pool *pool, const char *reposdir, int *nrepoinfosp) +read_repoinfos(Pool *pool, int *nrepoinfosp) { + const char *reposdir = REPOINFO_PATH; char buf[4096]; char buf2[4096], *kp, *vp, *kpe; DIR *dir; @@ -256,7 +271,7 @@ read_repoinfos(Pool *pool, const char *reposdir, int *nrepoinfosp) if (!vp) continue; *vp = 0; - repoinfos = sat_extend(repoinfos, nrepoinfos, 1, sizeof(*repoinfos), 15); + repoinfos = solv_extend(repoinfos, nrepoinfos, 1, sizeof(*repoinfos), 15); cinfo = repoinfos + nrepoinfos++; memset(cinfo, 0, sizeof(*cinfo)); cinfo->alias = strdup(kp + 1); @@ -332,10 +347,12 @@ read_repoinfos(Pool *pool, const char *reposdir, int *nrepoinfosp) return repoinfos; } -#else +#endif + +#ifdef DEBIAN struct repoinfo * -read_repoinfos(Pool *pool, const char *reposdir, int *nrepoinfosp) +read_repoinfos(Pool *pool, int *nrepoinfosp) { FILE *fp; char buf[4096]; @@ -411,11 +428,11 @@ read_repoinfos(Pool *pool, const char *reposdir, int *nrepoinfosp) kp++; if (!*kp) continue; - repoinfos = sat_extend(repoinfos, nrepoinfos, 1, sizeof(*repoinfos), 15); + repoinfos = solv_extend(repoinfos, nrepoinfos, 1, sizeof(*repoinfos), 15); cinfo = repoinfos + nrepoinfos++; memset(cinfo, 0, sizeof(*cinfo)); cinfo->baseurl = strdup(url); - cinfo->alias = sat_dupjoin(url, "/", distro); + cinfo->alias = solv_dupjoin(url, "/", distro); cinfo->name = strdup(distro); cinfo->type = TYPE_DEBIAN; cinfo->enabled = 1; @@ -434,7 +451,7 @@ read_repoinfos(Pool *pool, const char *reposdir, int *nrepoinfosp) kp++; if (*kp) *kp++ = 0; - cinfo->components = sat_extend(cinfo->components, cinfo->ncomponents, 1, sizeof(*cinfo->components), 15); + cinfo->components = solv_extend(cinfo->components, cinfo->ncomponents, 1, sizeof(*cinfo->components), 15); cinfo->components[cinfo->ncomponents++] = strdup(compo); } } @@ -448,6 +465,16 @@ read_repoinfos(Pool *pool, const char *reposdir, int *nrepoinfosp) #endif +#ifdef NOSYSTEM +struct repoinfo * +read_repoinfos(Pool *pool, int *nrepoinfosp) +{ + *nrepoinfosp = 0; + return 0; +} +#endif + + void free_repoinfos(struct repoinfo *repoinfos, int nrepoinfos) { @@ -455,17 +482,17 @@ free_repoinfos(struct repoinfo *repoinfos, int nrepoinfos) for (i = 0; i < nrepoinfos; i++) { struct repoinfo *cinfo = repoinfos + i; - sat_free(cinfo->name); - sat_free(cinfo->alias); - sat_free(cinfo->path); - sat_free(cinfo->metalink); - sat_free(cinfo->mirrorlist); - sat_free(cinfo->baseurl); + solv_free(cinfo->name); + solv_free(cinfo->alias); + solv_free(cinfo->path); + solv_free(cinfo->metalink); + solv_free(cinfo->mirrorlist); + solv_free(cinfo->baseurl); for (j = 0; j < cinfo->ncomponents; j++) - sat_free(cinfo->components[j]); - sat_free(cinfo->components); + solv_free(cinfo->components[j]); + solv_free(cinfo->components); } - sat_free(repoinfos); + solv_free(repoinfos); } static inline int @@ -493,24 +520,24 @@ verify_checksum(int fd, const char *file, const unsigned char *chksum, Id chksum void *h; int l; - h = sat_chksum_create(chksumtype); + h = solv_chksum_create(chksumtype); if (!h) { printf("%s: unknown checksum type\n", file); return 0; } while ((l = read(fd, buf, sizeof(buf))) > 0) - sat_chksum_add(h, buf, l); + solv_chksum_add(h, buf, l); lseek(fd, 0, SEEK_SET); l = 0; - sum = sat_chksum_get(h, &l); + sum = solv_chksum_get(h, &l); if (memcmp(sum, chksum, l)) { printf("%s: checksum mismatch\n", file); - sat_chksum_free(h, 0); + solv_chksum_free(h, 0); return 0; } - sat_chksum_free(h, 0); + solv_chksum_free(h, 0); return 1; } @@ -524,8 +551,8 @@ findfastest(char **urls, int nurls) char portstr[16]; struct addrinfo hints, *result;; - fds = sat_calloc(nurls, sizeof(*fds)); - socks = sat_calloc(nurls, sizeof(*socks)); + fds = solv_calloc(nurls, sizeof(*fds)); + socks = solv_calloc(nurls, sizeof(*socks)); for (i = 0; i < nurls; i++) { socks[i] = -1; @@ -665,23 +692,8 @@ findmetalinkurl(FILE *fp, unsigned char *chksump, Id *chksumtypep) bp++; if (chksumtypep && !*chksumtypep && !strncmp(bp, "", 20)) { - int i; - bp += 20; - memset(chksump, 0, 32); - for (i = 0; i < 64; i++) - { - int c = *bp++; - if (c >= '0' && c <= '9') - chksump[i / 2] = chksump[i / 2] * 16 + (c - '0'); - else if (c >= 'a' && c <= 'f') - chksump[i / 2] = chksump[i / 2] * 16 + (c - ('a' - 10)); - else if (c >= 'A' && c <= 'F') - chksump[i / 2] = chksump[i / 2] * 16 + (c - ('A' - 10)); - else - break; - } - if (i == 64) + if (solv_hex2bin((const char **)&bp, chksump, 32) == 32) *chksumtypep = REPOKEY_TYPE_SHA256; continue; } @@ -697,7 +709,7 @@ findmetalinkurl(FILE *fp, unsigned char *chksump, Id *chksumtypep) *ep = 0; if (strncmp(bp, "http", 4)) continue; - urls = sat_extend(urls, nurls, 1, sizeof(*urls), 15); + urls = solv_extend(urls, nurls, 1, sizeof(*urls), 15); urls[nurls++] = strdup(bp); } if (nurls) @@ -707,8 +719,8 @@ findmetalinkurl(FILE *fp, unsigned char *chksump, Id *chksumtypep) bp = urls[0]; urls[0] = 0; for (i = 0; i < nurls; i++) - sat_free(urls[i]); - sat_free(urls); + solv_free(urls[i]); + solv_free(urls); ep = strchr(bp, '/'); if ((ep = strchr(ep + 2, '/')) != 0) { @@ -738,7 +750,7 @@ findmirrorlisturl(FILE *fp) l = strlen(bp); while (l > 0 && (bp[l - 1] == ' ' || bp[l - 1] == '\t' || bp[l - 1] == '\n')) bp[--l] = 0; - urls = sat_extend(urls, nurls, 1, sizeof(*urls), 15); + urls = solv_extend(urls, nurls, 1, sizeof(*urls), 15); urls[nurls++] = strdup(bp); } if (nurls) @@ -748,8 +760,8 @@ findmirrorlisturl(FILE *fp) bp = urls[0]; urls[0] = 0; for (i = 0; i < nurls; i++) - sat_free(urls[i]); - sat_free(urls); + solv_free(urls[i]); + solv_free(urls); ep = strchr(bp, '/'); if ((ep = strchr(ep + 2, '/')) != 0) { @@ -762,9 +774,16 @@ findmirrorlisturl(FILE *fp) return 0; } +static inline int +iscompressed(const char *name) +{ + return solv_xfopen_iscompressed(name) != 0; +} + FILE * -curlfopen(struct repoinfo *cinfo, const char *file, int uncompress, const unsigned char *chksum, Id chksumtype, int *badchecksump) +curlfopen(struct repoinfo *cinfo, const char *file, int uncompress, const unsigned char *chksum, Id chksumtype, int markincomplete) { + FILE *fp; pid_t pid; int fd, l; int status; @@ -777,8 +796,8 @@ curlfopen(struct repoinfo *cinfo, const char *file, int uncompress, const unsign return 0; if (file != cinfo->metalink && file != cinfo->mirrorlist) { - FILE *fp = curlfopen(cinfo, cinfo->metalink ? cinfo->metalink : cinfo->mirrorlist, 0, 0, 0, 0); unsigned char mlchksum[32]; + fp = curlfopen(cinfo, cinfo->metalink ? cinfo->metalink : cinfo->mirrorlist, 0, 0, 0, 0); Id mlchksumtype = 0; if (!fp) return 0; @@ -802,7 +821,7 @@ curlfopen(struct repoinfo *cinfo, const char *file, int uncompress, const unsign chksumtype = mlchksumtype; chksum = mlchksum; } - return curlfopen(cinfo, file, uncompress, chksum, chksumtype, badchecksump); + return curlfopen(cinfo, file, uncompress, chksum, chksumtype, markincomplete); } snprintf(url, sizeof(url), "%s", file); } @@ -845,22 +864,36 @@ curlfopen(struct repoinfo *cinfo, const char *file, int uncompress, const unsign if (status) { printf("%s: download error %d\n", file, status >> 8 ? status >> 8 : status); - if (badchecksump) - *badchecksump = 1; + if (markincomplete) + cinfo->incomplete = 1; close(fd); return 0; } if (chksumtype && !verify_checksum(fd, file, chksum, chksumtype)) { - if (badchecksump) - *badchecksump = 1; + if (markincomplete) + cinfo->incomplete = 1; close(fd); return 0; } - if (uncompress) - return sat_xfopen_fd(".gz", fd); fcntl(fd, F_SETFD, FD_CLOEXEC); - return fdopen(fd, "r"); + if (uncompress) + { + if (solv_xfopen_iscompressed(file) < 0) + { + printf("%s: unsupported compression\n", file); + if (markincomplete) + cinfo->incomplete = 1; + close(fd); + return 0; + } + fp = solv_xfopen_fd(file, fd, "r"); + } + else + fp = fdopen(fd, "r"); + if (!fp) + close(fd); + return fp; } #ifndef DEBIAN @@ -949,7 +982,7 @@ checksig(Pool *sigpool, FILE *fp, FILE *sigfp) #else -int +static int checksig(Pool *sigpool, FILE *fp, FILE *sigfp) { char cmd[256]; @@ -966,32 +999,67 @@ checksig(Pool *sigpool, FILE *fp, FILE *sigfp) #endif +static Pool * +read_sigs() +{ + Pool *sigpool = pool_create(); +#if defined(ENABLE_RPMDB_PUBKEY) + Repo *repo = repo_create(sigpool, "rpmdbkeys"); + repo_add_rpmdb_pubkeys(repo, 0); +#endif + return sigpool; +} + +static int +downloadchecksig(struct repoinfo *cinfo, FILE *fp, const char *sigurl, Pool **sigpool) +{ + FILE *sigfp; + sigfp = curlfopen(cinfo, sigurl, 0, 0, 0, 0); + if (!sigfp) + { + printf(" unsigned, skipped\n"); + return 0; + } + if (!*sigpool) + *sigpool = read_sigs(); + if (!checksig(*sigpool, fp, sigfp)) + { + printf(" checksig failed, skipped\n"); + fclose(sigfp); + return 0; + } + fclose(sigfp); + return 1; +} + #define CHKSUM_IDENT "1.1" void calc_checksum_fp(FILE *fp, Id chktype, unsigned char *out) { char buf[4096]; - void *h = sat_chksum_create(chktype); + void *h = solv_chksum_create(chktype); int l; - sat_chksum_add(h, CHKSUM_IDENT, strlen(CHKSUM_IDENT)); + solv_chksum_add(h, CHKSUM_IDENT, strlen(CHKSUM_IDENT)); while ((l = fread(buf, 1, sizeof(buf), fp)) > 0) - sat_chksum_add(h, buf, l); + solv_chksum_add(h, buf, l); rewind(fp); - sat_chksum_free(h, out); + solv_chksum_free(h, out); } void -calc_checksum_stat(struct stat *stb, Id chktype, unsigned char *out) +calc_checksum_stat(struct stat *stb, Id chktype, unsigned char *cookie, unsigned char *out) { - void *h = sat_chksum_create(chktype); - sat_chksum_add(h, CHKSUM_IDENT, strlen(CHKSUM_IDENT)); - sat_chksum_add(h, &stb->st_dev, sizeof(stb->st_dev)); - sat_chksum_add(h, &stb->st_ino, sizeof(stb->st_ino)); - sat_chksum_add(h, &stb->st_size, sizeof(stb->st_size)); - sat_chksum_add(h, &stb->st_mtime, sizeof(stb->st_mtime)); - sat_chksum_free(h, out); + void *h = solv_chksum_create(chktype); + solv_chksum_add(h, CHKSUM_IDENT, strlen(CHKSUM_IDENT)); + if (cookie) + solv_chksum_add(h, cookie, 32); + solv_chksum_add(h, &stb->st_dev, sizeof(stb->st_dev)); + solv_chksum_add(h, &stb->st_ino, sizeof(stb->st_ino)); + solv_chksum_add(h, &stb->st_size, sizeof(stb->st_size)); + solv_chksum_add(h, &stb->st_mtime, sizeof(stb->st_mtime)); + solv_chksum_free(h, out); } void @@ -1011,11 +1079,11 @@ char *calccachepath(Repo *repo, const char *repoext) char *q, *p = pool_tmpjoin(repo->pool, SOLVCACHE_PATH, "/", repo->name); if (repoext) { - p = pool_tmpjoin(repo->pool, p, "_", repoext); - p = pool_tmpjoin(repo->pool, p, ".solvx", 0); + p = pool_tmpappend(repo->pool, p, "_", repoext); + p = pool_tmpappend(repo->pool, p, ".solvx", 0); } else - p = pool_tmpjoin(repo->pool, p, ".solv", 0); + p = pool_tmpappend(repo->pool, p, ".solv", 0); q = p + strlen(SOLVCACHE_PATH) + 1; if (*q == '.') *q = '_'; @@ -1065,7 +1133,7 @@ usecachedrepo(Repo *repo, const char *repoext, unsigned char *cookie, int mark) flags |= REPO_LOCALPOOL; /* no local pool for DL so that we can compare IDs */ } - if (repo_add_solv_flags(repo, fp, flags)) + if (repo_add_solv(repo, fp, flags)) { fclose(fp); return 0; @@ -1091,8 +1159,11 @@ writecachedrepo(Repo *repo, Repodata *info, const char *repoext, unsigned char * int onepiece; cinfo = repo->appdata; + if (cinfo && cinfo->incomplete) + return; mkdir(SOLVCACHE_PATH, 0755); - tmpl = sat_dupjoin(SOLVCACHE_PATH, "/", ".newsolv-XXXXXX"); + /* use dupjoin instead of tmpjoin because tmpl must survive repo_write */ + tmpl = solv_dupjoin(SOLVCACHE_PATH, "/", ".newsolv-XXXXXX"); fd = mkstemp(tmpl); if (fd < 0) { @@ -1116,14 +1187,14 @@ writecachedrepo(Repo *repo, Repodata *info, const char *repoext, unsigned char * onepiece = 0; if (!info) - repo_write(repo, fp, repo_write_stdkeyfilter, 0, 0); + repo_write(repo, fp); else if (repoext) - repodata_write(info, fp, repo_write_stdkeyfilter, 0); + repodata_write(info, fp); else { int oldnrepodata = repo->nrepodata; - repo->nrepodata = 1; /* XXX: do this right */ - repo_write(repo, fp, repo_write_stdkeyfilter, 0, 0); + repo->nrepodata = oldnrepodata > 2 ? 2 : oldnrepodata; /* XXX: do this right */ + repo_write(repo, fp); repo->nrepodata = oldnrepodata; onepiece = 0; } @@ -1136,13 +1207,8 @@ writecachedrepo(Repo *repo, Repodata *info, const char *repoext, unsigned char * /* we just need some unique ID */ struct stat stb; if (!fstat(fileno(fp), &stb)) - { - int i; - - calc_checksum_stat(&stb, REPOKEY_TYPE_SHA256, cinfo->extcookie); - for (i = 0; i < 32; i++) - cinfo->extcookie[i] ^= cookie[i]; - } + memset(&stb, 0, sizeof(stb)); + calc_checksum_stat(&stb, REPOKEY_TYPE_SHA256, cookie, cinfo->extcookie); if (cinfo->extcookie[0] == 0) cinfo->extcookie[0] = 1; } @@ -1178,7 +1244,7 @@ writecachedrepo(Repo *repo, Repodata *info, const char *repoext, unsigned char * { /* main repo */ repo_empty(repo, 1); - if (repo_add_solv_flags(repo, fp, SOLV_ADD_NO_STUBS)) + if (repo_add_solv(repo, fp, SOLV_ADD_NO_STUBS)) { /* oops, no way to recover from here */ fprintf(stderr, "internal error\n"); @@ -1187,12 +1253,14 @@ writecachedrepo(Repo *repo, Repodata *info, const char *repoext, unsigned char * } else { + int flags = REPO_USE_LOADING|REPO_EXTEND_SOLVABLES; /* make sure repodata contains complete repo */ /* (this is how repodata_write saves it) */ repodata_extend_block(info, repo->start, repo->end - repo->start); info->state = REPODATA_LOADING; - /* no need for LOCALPOOL as pool already contains ids */ - repo_add_solv_flags(repo, fp, REPO_USE_LOADING|REPO_EXTEND_SOLVABLES); + if (strcmp(repoext, "DL") != 0) + flags |= REPO_LOCALPOOL; + repo_add_solv(repo, fp, flags); info->state = REPODATA_AVAILABLE; /* in case the load failed */ } fclose(fp); @@ -1204,18 +1272,7 @@ writecachedrepo(Repo *repo, Repodata *info, const char *repoext, unsigned char * } -static Pool * -read_sigs() -{ - Pool *sigpool = pool_create(); -#ifndef DEBIAN - Repo *repo = repo_create(sigpool, "rpmdbkeys"); - repo_add_rpmdb_pubkeys(repo, 0, 0); -#endif - return sigpool; -} - - +#ifdef ENABLE_RPMMD /* repomd helpers */ static inline const char * @@ -1275,7 +1332,59 @@ repomd_add_ext(Repo *repo, Repodata *data, const char *what) return 1; } +int +repomd_load_ext(Repo *repo, Repodata *data) +{ + const char *filename, *repomdtype; + char ext[3]; + FILE *fp; + struct repoinfo *cinfo; + const unsigned char *filechksum; + Id filechksumtype; + int r = 0; + + cinfo = repo->appdata; + repomdtype = repodata_lookup_str(data, SOLVID_META, REPOSITORY_REPOMD_TYPE); + if (!repomdtype) + return 0; + if (!strcmp(repomdtype, "filelists")) + strcpy(ext, "FL"); + else if (!strcmp(repomdtype, "deltainfo")) + strcpy(ext, "DL"); + else + return 0; +#if 1 + printf("[%s:%s", repo->name, ext); +#endif + if (usecachedrepo(repo, ext, cinfo->extcookie, 0)) + { + printf(" cached]\n");fflush(stdout); + return 1; + } + printf(" fetching]\n"); fflush(stdout); + filename = repodata_lookup_str(data, SOLVID_META, REPOSITORY_REPOMD_LOCATION); + filechksumtype = 0; + filechksum = repodata_lookup_bin_checksum(data, SOLVID_META, REPOSITORY_REPOMD_CHECKSUM, &filechksumtype); + if ((fp = curlfopen(cinfo, filename, iscompressed(filename), filechksum, filechksumtype, 0)) == 0) + return 0; + if (!strcmp(ext, "FL")) + r = repo_add_rpmmd(repo, fp, ext, REPO_USE_LOADING|REPO_EXTEND_SOLVABLES|REPO_LOCALPOOL); + else if (!strcmp(ext, "DL")) + r = repo_add_deltainfoxml(repo, fp, REPO_USE_LOADING); + fclose(fp); + if (r) + { + printf("%s\n", pool_errstr(repo->pool)); + return 0; + } + writecachedrepo(repo, data, ext, cinfo->extcookie); + return 1; +} + +#endif + +#ifdef ENABLE_SUSEREPO /* susetags helpers */ static inline const char * @@ -1369,137 +1478,86 @@ susetags_add_ext(Repo *repo, Repodata *data) dataiterator_free(&di); } - -static inline int -iscompressed(const char *name) -{ - int l = strlen(name); - return l > 3 && !strcmp(name + l - 3, ".gz") ? 1 : 0; -} - - -/* load callback */ - int -load_stub(Pool *pool, Repodata *data, void *dp) +susetags_load_ext(Repo *repo, Repodata *data) { - const char *filename, *descrdir, *repomdtype; - const unsigned char *filechksum; - Id filechksumtype; - struct repoinfo *cinfo; - FILE *fp; + const char *filename, *descrdir; Id defvendor; char ext[3]; + FILE *fp; + struct repoinfo *cinfo; + const unsigned char *filechksum; + Id filechksumtype; + int flags; - cinfo = data->repo->appdata; - + cinfo = repo->appdata; filename = repodata_lookup_str(data, SOLVID_META, SUSETAGS_FILE_NAME); - if (filename) - { - /* susetags load */ - ext[0] = filename[9]; - ext[1] = filename[10]; - ext[2] = 0; -#if 1 - printf("[%s:%s", data->repo->name, ext); -#endif - if (usecachedrepo(data->repo, ext, cinfo->extcookie, 0)) - { - printf(" cached]\n"); fflush(stdout); - return 1; - } + if (!filename) + return 0; + /* susetags load */ + ext[0] = filename[9]; + ext[1] = filename[10]; + ext[2] = 0; #if 1 - printf(" fetching]\n"); fflush(stdout); + printf("[%s:%s", repo->name, ext); #endif - defvendor = repo_lookup_id(data->repo, SOLVID_META, SUSETAGS_DEFAULTVENDOR); - descrdir = repo_lookup_str(data->repo, SOLVID_META, SUSETAGS_DESCRDIR); - if (!descrdir) - descrdir = "suse/setup/descr"; - filechksumtype = 0; - filechksum = repodata_lookup_bin_checksum(data, SOLVID_META, SUSETAGS_FILE_CHECKSUM, &filechksumtype); - if ((fp = curlfopen(cinfo, pool_tmpjoin(pool, descrdir, "/", filename), iscompressed(filename), filechksum, filechksumtype, 0)) == 0) - return 0; - repo_add_susetags(data->repo, fp, defvendor, ext, REPO_USE_LOADING|REPO_EXTEND_SOLVABLES); - fclose(fp); - writecachedrepo(data->repo, data, ext, cinfo->extcookie); + if (usecachedrepo(repo, ext, cinfo->extcookie, 0)) + { + printf(" cached]\n"); fflush(stdout); return 1; } - - repomdtype = repodata_lookup_str(data, SOLVID_META, REPOSITORY_REPOMD_TYPE); - if (repomdtype) - { - if (!strcmp(repomdtype, "filelists")) - strcpy(ext, "FL"); - else if (!strcmp(repomdtype, "deltainfo")) - strcpy(ext, "DL"); - else - return 0; #if 1 - printf("[%s:%s", data->repo->name, ext); + printf(" fetching]\n"); fflush(stdout); #endif - if (usecachedrepo(data->repo, ext, cinfo->extcookie, 0)) - { - printf(" cached]\n");fflush(stdout); - return 1; - } - printf(" fetching]\n"); fflush(stdout); - filename = repodata_lookup_str(data, SOLVID_META, REPOSITORY_REPOMD_LOCATION); - filechksumtype = 0; - filechksum = repodata_lookup_bin_checksum(data, SOLVID_META, REPOSITORY_REPOMD_CHECKSUM, &filechksumtype); - if ((fp = curlfopen(cinfo, filename, iscompressed(filename), filechksum, filechksumtype, 0)) == 0) - return 0; - if (!strcmp(ext, "FL")) - repo_add_rpmmd(data->repo, fp, ext, REPO_USE_LOADING|REPO_EXTEND_SOLVABLES); - else if (!strcmp(ext, "DL")) - repo_add_deltainfoxml(data->repo, fp, REPO_USE_LOADING); + defvendor = repo_lookup_id(repo, SOLVID_META, SUSETAGS_DEFAULTVENDOR); + descrdir = repo_lookup_str(repo, SOLVID_META, SUSETAGS_DESCRDIR); + if (!descrdir) + descrdir = "suse/setup/descr"; + filechksumtype = 0; + filechksum = repodata_lookup_bin_checksum(data, SOLVID_META, SUSETAGS_FILE_CHECKSUM, &filechksumtype); + if ((fp = curlfopen(cinfo, pool_tmpjoin(repo->pool, descrdir, "/", filename), iscompressed(filename), filechksum, filechksumtype, 0)) == 0) + return 0; + flags = REPO_USE_LOADING|REPO_EXTEND_SOLVABLES; + if (strcmp(ext, "DL") != 0) + flags |= REPO_LOCALPOOL; + if (repo_add_susetags(repo, fp, defvendor, ext, flags)) + { fclose(fp); - writecachedrepo(data->repo, data, ext, cinfo->extcookie); - return 1; + printf("%s\n", pool_errstr(repo->pool)); + return 0; } - - return 0; + fclose(fp); + writecachedrepo(repo, data, ext, cinfo->extcookie); + return 1; } +#endif -static unsigned char installedcookie[32]; -#ifdef DEBIAN -void -repo_add_debdb(Repo *repo, int flags) + +/* load callback */ + +int +load_stub(Pool *pool, Repodata *data, void *dp) { - FILE *fp; - if ((fp = fopen("/var/lib/dpkg/status", "r")) == 0) + struct repoinfo *cinfo = data->repo->appdata; + switch (cinfo->type) { - perror("/var/lib/dpkg/status"); - exit(1); +#ifdef ENABLE_SUSEREPO + case TYPE_SUSETAGS: + return susetags_load_ext(data->repo, data); +#endif +#ifdef ENABLE_RPMMD + case TYPE_RPMMD: + return repomd_load_ext(data->repo, data); +#endif + default: + return 0; } - repo_add_debpackages(repo, fp, flags); - fclose(fp); } -static int -hexstr2bytes(unsigned char *buf, const char *str, int buflen) -{ - int i; - for (i = 0; i < buflen; i++) - { -#define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \ - : ((c)>='a' && (c)<='f') ? ((c)-('a'-10)) \ - : ((c)>='A' && (c)<='F') ? ((c)-('A'-10)) \ - : -1) - int v = c2h(*str); - str++; - if (v < 0) - return 0; - buf[i] = v; - v = c2h(*str); - str++; - if (v < 0) - return 0; - buf[i] = (buf[i] << 4) | v; -#undef c2h - } - return buflen; -} +static unsigned char installedcookie[32]; + +#ifdef ENABLE_DEBIAN const char * debian_find_component(struct repoinfo *cinfo, FILE *fp, char *comp, const unsigned char **chksump, Id *chksumtypep) @@ -1527,13 +1585,13 @@ debian_find_component(struct repoinfo *cinfo, FILE *fp, char *comp, const unsign if (basearch[0] == 'i' && basearch[1] && !strcmp(basearch + 2, "86")) basearch[1] = '3'; } - binarydir = sat_dupjoin("binary-", basearch, "/"); + binarydir = solv_dupjoin("binary-", basearch, "/"); lbinarydir = strlen(binarydir); compl = strlen(comp); rewind(fp); curchksumtype = 0; filename = 0; - chksum = sat_malloc(32); + chksum = solv_malloc(32); chksumtype = 0; while(fgets(buf, sizeof(buf), fp)) { @@ -1588,27 +1646,31 @@ debian_find_component(struct repoinfo *cinfo, FILE *fp, char *comp, const unsign bp += lbinarydir; if (!strcmp(bp, "Packages") || !strcmp(bp, "Packages.gz")) { + unsigned char curchksum[32]; + int curl; if (filename && !strcmp(bp, "Packages")) continue; - if (chksumtype && sat_chksum_len(chksumtype) > sat_chksum_len(curchksumtype)) + curl = solv_chksum_len(curchksumtype); + if (!curl || (chksumtype && solv_chksum_len(chksumtype) > curl)) continue; - if (!hexstr2bytes(chksum, ch, sat_chksum_len(curchksumtype))) + if (solv_hex2bin((const char **)&ch, curchksum, sizeof(curchksum)) != curl) continue; - sat_free(filename); + solv_free(filename); filename = strdup(fn); chksumtype = curchksumtype; + memcpy(chksum, curchksum, curl); } } free(binarydir); if (filename) { - fn = sat_dupjoin("/", filename, 0); - sat_free(filename); - filename = sat_dupjoin("dists/", cinfo->name, fn); - sat_free(fn); + fn = solv_dupjoin("/", filename, 0); + solv_free(filename); + filename = solv_dupjoin("dists/", cinfo->name, fn); + solv_free(fn); } if (!chksumtype) - chksum = sat_free(chksum); + chksum = solv_free(chksum); *chksump = chksum; *chksumtypep = chksumtype; return filename; @@ -1622,62 +1684,82 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) struct repoinfo *cinfo; int i; FILE *fp; - FILE *sigfp; const char *filename; const unsigned char *filechksum; Id filechksumtype; +#ifdef ENABLE_SUSEREPO const char *descrdir; int defvendor; +#endif struct stat stb; Pool *sigpool = 0; +#if defined(ENABLE_SUSEREPO) || defined(ENABLE_RPMMD) Repodata *data; - int badchecksum; +#endif int dorefresh; -#ifdef DEBIAN +#if defined(ENABLE_DEBIAN) FILE *fpr; int j; #endif repo = repo_create(pool, "@System"); -#ifndef DEBIAN +#if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA)) printf("rpm database:"); - if (stat("/var/lib/rpm/Packages", &stb)) + if (stat(pool_prepend_rootdir_tmp(pool, "/var/lib/rpm/Packages"), &stb)) memset(&stb, 0, sizeof(&stb)); -#else +#endif +#if defined(ENABLE_DEBIAN) && defined(DEBIAN) printf("dpgk database:"); - if (stat("/var/lib/dpkg/status", &stb)) + if (stat(pool_prepend_rootdir_tmp(pool, "/var/lib/dpkg/status"), &stb)) memset(&stb, 0, sizeof(&stb)); #endif - calc_checksum_stat(&stb, REPOKEY_TYPE_SHA256, installedcookie); +#ifdef NOSYSTEM + printf("no installed database:"); + memset(&stb, 0, sizeof(&stb)); +#endif + calc_checksum_stat(&stb, REPOKEY_TYPE_SHA256, 0, installedcookie); if (usecachedrepo(repo, 0, installedcookie, 0)) printf(" cached\n"); else { -#ifndef DEBIAN +#if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA)) FILE *ofp; - int done = 0; + Repo *ref = 0; #endif printf(" reading\n"); -#ifdef PRODUCTS_PATH - repo_add_products(repo, PRODUCTS_PATH, 0, REPO_NO_INTERNALIZE); -#endif -#ifndef DEBIAN +#if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA)) +# if defined(ENABLE_SUSEREPO) && defined(PRODUCTS_PATH) + if (repo_add_products(repo, PRODUCTS_PATH, REPO_NO_INTERNALIZE | REPO_USE_ROOTDIR)) + { + fprintf(stderr, "product reading failed: %s\n", pool_errstr(pool)); + exit(1); + } +# endif if ((ofp = fopen(calccachepath(repo, 0), "r")) != 0) { - Repo *ref = repo_create(pool, "@System.old"); - if (!repo_add_solv(ref, ofp)) + ref = repo_create(pool, "@System.old"); + if (repo_add_solv(ref, ofp, 0)) { - repo_add_rpmdb(repo, ref, 0, REPO_REUSE_REPODATA); - done = 1; + repo_free(ref, 1); + ref = 0; } fclose(ofp); - repo_free(ref, 1); } - if (!done) - repo_add_rpmdb(repo, 0, 0, REPO_REUSE_REPODATA); -#else - repo_add_debdb(repo, REPO_REUSE_REPODATA); + if (repo_add_rpmdb(repo, ref, REPO_REUSE_REPODATA | REPO_USE_ROOTDIR)) + { + fprintf(stderr, "installed db: %s\n", pool_errstr(pool)); + exit(1); + } + if (ref) + repo_free(ref, 1); +#endif +#if defined(ENABLE_DEBIAN) && defined(DEBIAN) + if (repo_add_debdb(repo, REPO_REUSE_REPODATA | REPO_USE_ROOTDIR)) + { + fprintf(stderr, "installed db: %s\n", pool_errstr(pool)); + exit(1); + } #endif writecachedrepo(repo, 0, 0, installedcookie); } @@ -1706,9 +1788,9 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) printf(" cached\n"); continue; } - badchecksum = 0; switch (cinfo->type) { +#ifdef ENABLE_RPMMD case TYPE_RPMMD: printf("rpmmd repo '%s':", cinfo->alias); fflush(stdout); @@ -1726,42 +1808,40 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) fclose(fp); break; } - if (cinfo->repo_gpgcheck) + if (cinfo->repo_gpgcheck && !downloadchecksig(cinfo, fp, "repodata/repomd.xml.asc", &sigpool)) { - sigfp = curlfopen(cinfo, "repodata/repomd.xml.asc", 0, 0, 0, 0); - if (!sigfp) - { - printf(" unsigned, skipped\n"); - fclose(fp); - break; - } - if (!sigpool) - sigpool = read_sigs(); - if (!checksig(sigpool, fp, sigfp)) - { - printf(" checksig failed, skipped\n"); - fclose(sigfp); - fclose(fp); - break; - } - fclose(sigfp); + fclose(fp); + break; + } + if (repo_add_repomdxml(repo, fp, 0)) + { + printf("repomd.xml: %s\n", pool_errstr(pool)); + fclose(fp); + break; /* hopeless */ } - repo_add_repomdxml(repo, fp, 0); fclose(fp); printf(" fetching\n"); filename = repomd_find(repo, "primary", &filechksum, &filechksumtype); - if (filename && (fp = curlfopen(cinfo, filename, iscompressed(filename), filechksum, filechksumtype, &badchecksum)) != 0) + if (filename && (fp = curlfopen(cinfo, filename, iscompressed(filename), filechksum, filechksumtype, 1)) != 0) { - repo_add_rpmmd(repo, fp, 0, 0); + if (repo_add_rpmmd(repo, fp, 0, 0)) + { + printf("primary: %s\n", pool_errstr(pool)); + cinfo->incomplete = 1; + } fclose(fp); } - if (badchecksum) + if (cinfo->incomplete) break; /* hopeless */ filename = repomd_find(repo, "updateinfo", &filechksum, &filechksumtype); - if (filename && (fp = curlfopen(cinfo, filename, iscompressed(filename), filechksum, filechksumtype, &badchecksum)) != 0) + if (filename && (fp = curlfopen(cinfo, filename, iscompressed(filename), filechksum, filechksumtype, 1)) != 0) { - repo_add_updateinfoxml(repo, fp, 0); + if (repo_add_updateinfoxml(repo, fp, 0)) + { + printf("updateinfo: %s\n", pool_errstr(pool)); + cinfo->incomplete = 1; + } fclose(fp); } @@ -1770,11 +1850,13 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) repomd_add_ext(repo, data, "prestodelta"); repomd_add_ext(repo, data, "filelists"); repodata_internalize(data); - if (!badchecksum) + if (!cinfo->incomplete) writecachedrepo(repo, 0, 0, cinfo->cookie); repodata_create_stubs(repo_last_repodata(repo)); break; +#endif +#ifdef ENABLE_SUSEREPO case TYPE_SUSETAGS: printf("susetags repo '%s':", cinfo->alias); fflush(stdout); @@ -1794,30 +1876,17 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) fclose(fp); break; } - if (cinfo->repo_gpgcheck) + if (cinfo->repo_gpgcheck && !downloadchecksig(cinfo, fp, "content.asc", &sigpool)) { - sigfp = curlfopen(cinfo, "content.asc", 0, 0, 0, 0); - if (!sigfp) - { - printf(" unsigned, skipped\n"); - fclose(fp); - break; - } - if (sigfp) - { - if (!sigpool) - sigpool = read_sigs(); - if (!checksig(sigpool, fp, sigfp)) - { - printf(" checksig failed, skipped\n"); - fclose(sigfp); - fclose(fp); - break; - } - fclose(sigfp); - } + fclose(fp); + break; + } + if (repo_add_content(repo, fp, 0)) + { + printf("content: %s\n", pool_errstr(pool)); + fclose(fp); + break; /* hopeless */ } - repo_add_content(repo, fp, 0); fclose(fp); defvendor = repo_lookup_id(repo, SOLVID_META, SUSETAGS_DEFAULTVENDOR); descrdir = repo_lookup_str(repo, SOLVID_META, SUSETAGS_DESCRDIR); @@ -1832,9 +1901,15 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) break; } printf(" fetching\n"); - if ((fp = curlfopen(cinfo, pool_tmpjoin(pool, descrdir, "/", filename), iscompressed(filename), filechksum, filechksumtype, &badchecksum)) == 0) + if ((fp = curlfopen(cinfo, pool_tmpjoin(pool, descrdir, "/", filename), iscompressed(filename), filechksum, filechksumtype, 1)) == 0) break; /* hopeless */ - repo_add_susetags(repo, fp, defvendor, 0, REPO_NO_INTERNALIZE|SUSETAGS_RECORD_SHARES); + if (repo_add_susetags(repo, fp, defvendor, 0, REPO_NO_INTERNALIZE|SUSETAGS_RECORD_SHARES)) + { + printf("packages: %s\n", pool_errstr(pool)); + fclose(fp); + cinfo->incomplete = 1; + break; /* hopeless */ + } fclose(fp); /* add default language */ filename = susetags_find(repo, "packages.en.gz", &filechksum, &filechksumtype); @@ -1842,26 +1917,59 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) filename = susetags_find(repo, "packages.en", &filechksum, &filechksumtype); if (filename) { - if ((fp = curlfopen(cinfo, pool_tmpjoin(pool, descrdir, "/", filename), iscompressed(filename), filechksum, filechksumtype, &badchecksum)) != 0) + if ((fp = curlfopen(cinfo, pool_tmpjoin(pool, descrdir, "/", filename), iscompressed(filename), filechksum, filechksumtype, 1)) != 0) { - repo_add_susetags(repo, fp, defvendor, 0, REPO_NO_INTERNALIZE|REPO_REUSE_REPODATA|REPO_EXTEND_SOLVABLES); + if (repo_add_susetags(repo, fp, defvendor, 0, REPO_NO_INTERNALIZE|REPO_REUSE_REPODATA|REPO_EXTEND_SOLVABLES)) + { + printf("packages.en: %s\n", pool_errstr(pool)); + cinfo->incomplete = 1; + } fclose(fp); } } - repo_internalize(repo); - data = repo_add_repodata(repo, 0); - susetags_add_ext(repo, data); - repodata_internalize(data); - if (!badchecksum) - writecachedrepo(repo, 0, 0, cinfo->cookie); - repodata_create_stubs(repo_last_repodata(repo)); + filename = susetags_find(repo, "patterns", &filechksum, &filechksumtype); + if (filename) + { + if ((fp = curlfopen(cinfo, pool_tmpjoin(pool, descrdir, "/", filename), iscompressed(filename), filechksum, filechksumtype, 1)) != 0) + { + char pbuf[256]; + while (fgets(pbuf, sizeof(pbuf), fp)) + { + int l = strlen(pbuf); + FILE *fp2; + if (l && pbuf[l - 1] == '\n') + pbuf[--l] = 0; + if (!*pbuf || *pbuf == '.' || strchr(pbuf, '/') != 0) + continue; + filename = susetags_find(repo, pbuf, &filechksum, &filechksumtype); + if (filename && (fp2 = curlfopen(cinfo, pool_tmpjoin(pool, descrdir, "/", filename), iscompressed(filename), filechksum, filechksumtype, 1)) != 0) + { + if (repo_add_susetags(repo, fp2, defvendor, 0, REPO_NO_INTERNALIZE)) + { + printf("%s: %s\n", pbuf, pool_errstr(pool)); + cinfo->incomplete = 1; + } + fclose(fp2); + } + } + fclose(fp); + } + } + repo_internalize(repo); + data = repo_add_repodata(repo, 0); + susetags_add_ext(repo, data); + repodata_internalize(data); + if (!cinfo->incomplete) + writecachedrepo(repo, 0, 0, cinfo->cookie); + repodata_create_stubs(repo_last_repodata(repo)); break; +#endif -#ifdef DEBIAN +#if defined(ENABLE_DEBIAN) case TYPE_DEBIAN: printf("debian repo '%s':", cinfo->alias); fflush(stdout); - filename = sat_dupjoin("dists/", cinfo->name, "/Release"); + filename = solv_dupjoin("dists/", cinfo->name, "/Release"); if ((fpr = curlfopen(cinfo, filename, 0, 0, 0, 0)) == 0) { printf(" no Release file, skipped\n"); @@ -1870,28 +1978,17 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) free((char *)filename); break; } - sat_free((char *)filename); + solv_free((char *)filename); if (cinfo->repo_gpgcheck) { - filename = sat_dupjoin("dists/", cinfo->name, "/Release.gpg"); - sigfp = curlfopen(cinfo, filename, 0, 0, 0, 0); - sat_free((char *)filename); - if (!sigfp) - { - printf(" unsigned, skipped\n"); - fclose(fpr); - break; - } - if (!sigpool) - sigpool = read_sigs(); - if (!checksig(sigpool, fpr, sigfp)) + filename = solv_dupjoin("dists/", cinfo->name, "/Release.gpg"); + if (!downloadchecksig(cinfo, fpr, filename, &sigpool)) { - printf(" checksig failed, skipped\n"); - fclose(sigfp); fclose(fpr); + solv_free((char *)filename); break; } - fclose(sigfp); + solv_free((char *)filename); } calc_checksum_fp(fpr, REPOKEY_TYPE_SHA256, cinfo->cookie); if (usecachedrepo(repo, 0, cinfo->cookie, 1)) @@ -1908,16 +2005,20 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) printf("[component %s not found]\n", cinfo->components[j]); continue; } - if ((fp = curlfopen(cinfo, filename, iscompressed(filename), filechksum, filechksumtype, &badchecksum)) != 0) + if ((fp = curlfopen(cinfo, filename, iscompressed(filename), filechksum, filechksumtype, 1)) != 0) { - repo_add_debpackages(repo, fp, 0); + if (repo_add_debpackages(repo, fp, 0)) + { + printf("component %s: %s\n", cinfo->components[j], pool_errstr(pool)); + cinfo->incomplete = 1; + } fclose(fp); } - sat_free((char *)filechksum); - sat_free((char *)filename); + solv_free((char *)filechksum); + solv_free((char *)filename); } fclose(fpr); - if (!badchecksum) + if (!cinfo->incomplete) writecachedrepo(repo, 0, 0, cinfo->cookie); break; #endif @@ -1933,338 +2034,6 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) pool_free(sigpool); } - -int -str2archid(Pool *pool, char *arch) -{ - Id id; - if (!*arch) - return 0; - id = str2id(pool, arch, 0); - if (id == ARCH_SRC || id == ARCH_NOSRC || id == ARCH_NOARCH) - return id; - if (pool->id2arch && (id > pool->lastarch || !pool->id2arch[id])) - return 0; - return id; -} - - -#define DEPGLOB_NAME 1 -#define DEPGLOB_DEP 2 -#define DEPGLOB_NAMEDEP 3 - -int -depglob(Pool *pool, char *name, Queue *job, int what) -{ - Id p, pp; - Id id = str2id(pool, name, 0); - int i, match = 0; - - if (id) - { - FOR_PROVIDES(p, pp, id) - { - Solvable *s = pool->solvables + p; - match = 1; - if (s->name == id && (what & DEPGLOB_NAME) != 0) - { - queue_push2(job, SOLVER_SOLVABLE_NAME, id); - return 1; - } - } - if (match) - { - if (what == DEPGLOB_NAMEDEP) - printf("[using capability match for '%s']\n", name); - queue_push2(job, SOLVER_SOLVABLE_PROVIDES, id); - return 1; - } - } - - if (strpbrk(name, "[*?") == 0) - return 0; - - if ((what & DEPGLOB_NAME) != 0) - { - /* looks like a name glob. hard work. */ - for (p = 1; p < pool->nsolvables; p++) - { - Solvable *s = pool->solvables + p; - if (!s->repo || !pool_installable(pool, s)) - continue; - id = s->name; - if (fnmatch(name, id2str(pool, id), 0) == 0) - { - for (i = 0; i < job->count; i += 2) - if (job->elements[i] == SOLVER_SOLVABLE_NAME && job->elements[i + 1] == id) - break; - if (i == job->count) - queue_push2(job, SOLVER_SOLVABLE_NAME, id); - match = 1; - } - } - if (match) - return 1; - } - if ((what & DEPGLOB_DEP)) - { - /* looks like a dep glob. really hard work. */ - for (id = 1; id < pool->ss.nstrings; id++) - { - if (!pool->whatprovides[id]) - continue; - if (fnmatch(name, id2str(pool, id), 0) == 0) - { - if (!match && what == DEPGLOB_NAMEDEP) - printf("[using capability match for '%s']\n", name); - for (i = 0; i < job->count; i += 2) - if (job->elements[i] == SOLVER_SOLVABLE_PROVIDES && job->elements[i + 1] == id) - break; - if (i == job->count) - queue_push2(job, SOLVER_SOLVABLE_PROVIDES, id); - match = 1; - } - } - if (match) - return 1; - } - return 0; -} - -int -limitrelation(Pool *pool, Queue *job, int flags, Id evr) -{ - int i, j; - Id p, pp; - for (i = j = 0; i < job->count; i += 2) - { - Id select = job->elements[i] & SOLVER_SELECTMASK; - if (select != SOLVER_SOLVABLE_NAME && select != SOLVER_SOLVABLE_PROVIDES) - { - fprintf(stderr, "limitrelation only works on name/provides jobs\n"); - exit(1); - } - job->elements[i + 1] = rel2id(pool, job->elements[i + 1], evr, flags, 1); - if (flags == REL_ARCH) - job->elements[i] |= SOLVER_SETARCH; - if (flags == REL_EQ && select == SOLVER_SOLVABLE_NAME && job->elements[i]) - { -#ifndef DEBIAN - const char *evrstr = id2str(pool, evr); - if (!strchr(evrstr, '-')) - job->elements[i] |= SOLVER_SETEV; - else -#endif - job->elements[i] |= SOLVER_SETEVR; - } - /* make sure we still have matches */ - FOR_JOB_SELECT(p, pp, job->elements[i], job->elements[i + 1]) - break; - if (p) - { - job->elements[j] = job->elements[i]; - job->elements[j + 1] = job->elements[i + 1]; - j += 2; - } - } - queue_truncate(job, j); - return j / 2; -} - -int -limitrelation_arch(Pool *pool, Queue *job, int flags, char *evr) -{ - char *r; - Id archid; - if ((r = strrchr(evr, '.')) != 0 && r[1] && (archid = str2archid(pool, r + 1)) != 0) - { - *r = 0; - limitrelation(pool, job, REL_ARCH, archid); - limitrelation(pool, job, flags, str2id(pool, evr, 1)); - *r = '.'; - } - else - limitrelation(pool, job, flags, str2id(pool, evr, 1)); - return job->count / 2; -} - -int -limitrepo(Pool *pool, Id repofilter, Queue *job) -{ - Queue mq; - Id p, pp; - int i, j; - Solvable *s; - - queue_init(&mq); - for (i = j = 0; i < job->count; i += 2) - { - queue_empty(&mq); - FOR_JOB_SELECT(p, pp, job->elements[i], job->elements[i + 1]) - { - s = pool_id2solvable(pool, p); - if (s->repo && s->repo->repoid == repofilter) - queue_push(&mq, p); - } - if (mq.count) - { - /* here we assume that repo == vendor, so we also set SOLVER_SETVENDOR */ - if (mq.count == 1) - { - job->elements[j] = SOLVER_SOLVABLE | (job->elements[i] & SOLVER_SETMASK) | SOLVER_SETVENDOR | SOLVER_SETREPO | SOLVER_NOAUTOSET; - job->elements[j + 1] = mq.elements[0]; - } - else - { - job->elements[j] = SOLVER_SOLVABLE_ONE_OF | (job->elements[i] & SOLVER_SETMASK) | SOLVER_SETVENDOR | SOLVER_SETREPO; - job->elements[j + 1] = pool_queuetowhatprovides(pool, &mq); - } - j += 2; - } - } - queue_truncate(job, j); - queue_free(&mq); - return j / 2; -} - -int -mkselect(Pool *pool, int mode, char *name, Queue *job) -{ - char *r, *r2; - Id archid; - - if (*name == '/') - { - Dataiterator di; - int type = strpbrk(name, "[*?") == 0 ? SEARCH_STRING : SEARCH_GLOB; - Queue q; - queue_init(&q); - dataiterator_init(&di, pool, mode == SOLVER_ERASE ? pool->installed : 0, 0, SOLVABLE_FILELIST, name, type|SEARCH_FILES|SEARCH_COMPLETE_FILELIST); - while (dataiterator_step(&di)) - { - Solvable *s = pool->solvables + di.solvid; - if (!s->repo || !pool_installable(pool, s)) - continue; - queue_push(&q, di.solvid); - dataiterator_skip_solvable(&di); - } - dataiterator_free(&di); - if (q.count) - { - printf("[using file list match for '%s']\n", name); - if (q.count > 1) - queue_push2(job, SOLVER_SOLVABLE_ONE_OF, pool_queuetowhatprovides(pool, &q)); - else - queue_push2(job, SOLVER_SOLVABLE | SOLVER_NOAUTOSET, q.elements[0]); - queue_free(&q); - return job->count / 2; - } - } - if ((r = strpbrk(name, "<=>")) != 0) - { - /* relation case, support: - * depglob rel - * depglob.arch rel - */ - int rflags = 0; - int nend = r - name; - char oldnend; - for (; *r; r++) - { - if (*r == '<') - rflags |= REL_LT; - else if (*r == '=') - rflags |= REL_EQ; - else if (*r == '>') - rflags |= REL_GT; - else - break; - } - while (*r && *r == ' ' && *r == '\t') - r++; - while (nend && (name[nend - 1] == ' ' || name[nend -1 ] == '\t')) - nend--; - if (!*name || !*r) - { - fprintf(stderr, "bad relation\n"); - exit(1); - } - oldnend = name[nend]; - name[nend] = 0; - if (depglob(pool, name, job, DEPGLOB_NAMEDEP)) - { - name[nend] = oldnend; - limitrelation(pool, job, rflags, str2id(pool, r, 1)); - return job->count / 2; - } - if ((r2 = strrchr(name, '.')) != 0 && r2[1] && (archid = str2archid(pool, r2 + 1)) != 0) - { - *r2 = 0; - if (depglob(pool, name, job, DEPGLOB_NAMEDEP)) - { - name[nend] = oldnend; - *r2 = '.'; - limitrelation(pool, job, REL_ARCH, archid); - limitrelation(pool, job, rflags, str2id(pool, r, 1)); - return job->count / 2; - } - *r2 = '.'; - } - name[nend] = oldnend; - } - else - { - /* no relation case, support: - * depglob - * depglob.arch - * nameglob-version - * nameglob-version.arch - * nameglob-version-release - * nameglob-version-release.arch - */ - if (depglob(pool, name, job, DEPGLOB_NAMEDEP)) - return job->count / 2; - if ((r = strrchr(name, '.')) != 0 && r[1] && (archid = str2archid(pool, r + 1)) != 0) - { - *r = 0; - if (depglob(pool, name, job, DEPGLOB_NAMEDEP)) - { - *r = '.'; - limitrelation(pool, job, REL_ARCH, archid); - return job->count / 2; - } - *r = '.'; - } - if ((r = strrchr(name, '-')) != 0) - { - *r = 0; - if (depglob(pool, name, job, DEPGLOB_NAME)) - { - /* have just the version */ - limitrelation_arch(pool, job, REL_EQ, r + 1); - *r = '-'; - return job->count / 2; - } - if ((r2 = strrchr(name, '-')) != 0) - { - *r = '-'; - *r2 = 0; - r = r2; - if (depglob(pool, name, job, DEPGLOB_NAME)) - { - /* have version-release */ - limitrelation_arch(pool, job, REL_EQ, r + 1); - *r = '-'; - return job->count / 2; - } - } - *r = '-'; - } - } - return 0; -} - - int yesno(const char *str) { @@ -2292,7 +2061,7 @@ yesno(const char *str) } } -#ifndef DEBIAN +#if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA)) struct fcstate { FILE **newpkgsfps; @@ -2334,12 +2103,12 @@ fileconflict_cb(Pool *pool, Id p, void *cbdata) if (!fp) return 0; rewind(fp); - return rpm_byfp(fp, solvable2str(pool, s), &fcstate->rpmdbstate); + return rpm_byfp(fp, pool_solvable2str(pool, s), &fcstate->rpmdbstate); } void -runrpm(const char *arg, const char *name, int dupfd3) +runrpm(const char *arg, const char *name, int dupfd3, const char *rootdir) { pid_t pid; int status; @@ -2351,6 +2120,8 @@ runrpm(const char *arg, const char *name, int dupfd3) } if (pid == 0) { + if (!rootdir) + rootdir = "/"; if (dupfd3 != -1 && dupfd3 != 3) { dup2(dupfd3, 3); @@ -2359,9 +2130,9 @@ runrpm(const char *arg, const char *name, int dupfd3) if (dupfd3 != -1) fcntl(3, F_SETFD, 0); /* clear CLOEXEC */ if (strcmp(arg, "-e") == 0) - execlp("rpm", "rpm", arg, "--nodeps", "--nodigest", "--nosignature", name, (char *)0); + execlp("rpm", "rpm", arg, "--nodeps", "--nodigest", "--nosignature", "--root", rootdir, name, (char *)0); else - execlp("rpm", "rpm", arg, "--force", "--nodeps", "--nodigest", "--nosignature", name, (char *)0); + execlp("rpm", "rpm", arg, "--force", "--nodeps", "--nodigest", "--nosignature", "--root", rootdir, name, (char *)0); perror("rpm"); _exit(0); } @@ -2376,10 +2147,10 @@ runrpm(const char *arg, const char *name, int dupfd3) #endif -#ifdef DEBIAN +#if defined(ENABLE_DEBIAN) && defined(DEBIAN) void -rundpkg(const char *arg, const char *name, int dupfd3) +rundpkg(const char *arg, const char *name, int dupfd3, const char *rootdir) { pid_t pid; int status; @@ -2391,6 +2162,8 @@ rundpkg(const char *arg, const char *name, int dupfd3) } if (pid == 0) { + if (!rootdir) + rootdir = "/"; if (dupfd3 != -1 && dupfd3 != 3) { dup2(dupfd3, 3); @@ -2399,9 +2172,9 @@ rundpkg(const char *arg, const char *name, int dupfd3) if (dupfd3 != -1) fcntl(3, F_SETFD, 0); /* clear CLOEXEC */ if (strcmp(arg, "--install") == 0) - execlp("dpkg", "dpkg", "--install", "--force", "all", name, (char *)0); + execlp("dpkg", "dpkg", "--install", "--root", rootdir, "--force", "all", name, (char *)0); else - execlp("dpkg", "dpkg", "--remove", "--force", "all", name, (char *)0); + execlp("dpkg", "dpkg", "--remove", "--root", rootdir, "--force", "all", name, (char *)0); perror("dpkg"); _exit(0); } @@ -2420,24 +2193,26 @@ static Id nscallback(Pool *pool, void *data, Id name, Id evr) { if (name == NAMESPACE_PRODUCTBUDDY) - { + { /* SUSE specific hack: each product has an associated rpm */ - Solvable *s = pool->solvables + evr; - Id p, pp, cap; - - cap = str2id(pool, pool_tmpjoin(pool, "product(", id2str(pool, s->name) + 8, ")"), 0); + Solvable *s = pool->solvables + evr; + Id p, pp, cap; + Id bestp = 0; + + cap = pool_str2id(pool, pool_tmpjoin(pool, "product(", pool_id2str(pool, s->name) + 8, ")"), 0); if (!cap) return 0; - cap = rel2id(pool, cap, s->evr, REL_EQ, 0); + cap = pool_rel2id(pool, cap, s->evr, REL_EQ, 0); if (!cap) return 0; - FOR_PROVIDES(p, pp, cap) + FOR_PROVIDES(p, pp, cap) { - Solvable *ps = pool->solvables + p; + Solvable *ps = pool->solvables + p; if (ps->repo == s->repo && ps->arch == s->arch) - break; + if (!bestp || pool_evrcmp(pool, pool->solvables[bestp].evr, ps->evr, EVRCMP_COMPARE) < 0) + bestp = p; } - return p; + return bestp; } return 0; } @@ -2469,7 +2244,7 @@ addsoftlocks(Pool *pool, Queue *job) type = SOLVER_SOLVABLE_PROVIDES; bp += 9; } - id = str2id(pool, bp, 1); + id = pool_str2id(pool, bp, 1); if (pool->installed) { FOR_JOB_SELECT(p, pp, type, id) @@ -2487,41 +2262,64 @@ addsoftlocks(Pool *pool, Queue *job) void -rewrite_repos(Pool *pool, Id *addedfileprovides) +rewrite_repos(Pool *pool, Queue *addedfileprovides, Queue *addedfileprovides_inst) { Repo *repo; Repodata *data; Map providedids; Queue fileprovidesq; - Id id; - int i, j, n, nprovidedids; + int i, j, n; struct repoinfo *cinfo; map_init(&providedids, pool->ss.nstrings); queue_init(&fileprovidesq); - for (nprovidedids = 0; (id = addedfileprovides[nprovidedids]) != 0; nprovidedids++) - MAPSET(&providedids, id); + for (i = 0; i < addedfileprovides->count; i++) + MAPSET(&providedids, addedfileprovides->elements[i]); FOR_REPOS(i, repo) { - /* make sure this repo has just one main repodata */ - if (!repo->nrepodata) + /* make sure all repodatas but the first are extensions */ + if (repo->nrepodata < 2) continue; cinfo = repo->appdata; - data = repo->repodata + 0; - if (data->store.pagefd == -1) + if (cinfo && cinfo->incomplete) continue; + data = repo_id2repodata(repo, 1); + if (data->loadcallback) + continue; + for (j = 2; j < repo->nrepodata; j++) + { + Repodata *edata = repo_id2repodata(repo, j); + if (!edata->loadcallback) + break; + } + if (j < repo->nrepodata) + continue; /* found a non-externsion repodata, can't rewrite */ if (repodata_lookup_idarray(data, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, &fileprovidesq)) { + if (repo == pool->installed && addedfileprovides_inst) + { + for (j = 0; j < addedfileprovides->count; j++) + MAPCLR(&providedids, addedfileprovides->elements[j]); + for (j = 0; j < addedfileprovides_inst->count; j++) + MAPSET(&providedids, addedfileprovides_inst->elements[j]); + } n = 0; for (j = 0; j < fileprovidesq.count; j++) if (MAPTST(&providedids, fileprovidesq.elements[j])) n++; - if (n == nprovidedids) + if (repo == pool->installed && addedfileprovides_inst) + { + for (j = 0; j < addedfileprovides_inst->count; j++) + MAPCLR(&providedids, addedfileprovides_inst->elements[j]); + for (j = 0; j < addedfileprovides->count; j++) + MAPSET(&providedids, addedfileprovides->elements[j]); + if (n == addedfileprovides_inst->count) + continue; /* nothing new added */ + } + else if (n == addedfileprovides->count) continue; /* nothing new added */ } - /* oh my! */ - for (j = 0; addedfileprovides[j]; j++) - repodata_add_idarray(data, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, addedfileprovides[j]); + repodata_set_idarray(data, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, repo == pool->installed && addedfileprovides_inst ? addedfileprovides_inst : addedfileprovides); repodata_internalize(data); writecachedrepo(repo, data, 0, cinfo ? cinfo->cookie : installedcookie); } @@ -2529,6 +2327,61 @@ rewrite_repos(Pool *pool, Id *addedfileprovides) map_free(&providedids); } +static void +select_patches(Pool *pool, Queue *job) +{ + Id p, pp; + int pruneyou = 0; + Map installedmap, noobsmap; + Solvable *s; + + map_init(&noobsmap, 0); + map_init(&installedmap, pool->nsolvables); + solver_calculate_noobsmap(pool, job, &noobsmap); + if (pool->installed) + FOR_REPO_SOLVABLES(pool->installed, p, s) + MAPSET(&installedmap, p); + + /* install all patches */ + for (p = 1; p < pool->nsolvables; p++) + { + const char *type; + int r; + Id p2; + + s = pool->solvables + p; + if (strncmp(pool_id2str(pool, s->name), "patch:", 6) != 0) + continue; + FOR_PROVIDES(p2, pp, s->name) + { + Solvable *s2 = pool->solvables + p2; + if (s2->name != s->name) + continue; + r = pool_evrcmp(pool, s->evr, s2->evr, EVRCMP_COMPARE); + if (r < 0 || (r == 0 && p > p2)) + break; + } + if (p2) + continue; + type = solvable_lookup_str(s, SOLVABLE_PATCHCATEGORY); + if (type && !strcmp(type, "optional")) + continue; + r = solvable_trivial_installable_map(s, &installedmap, 0, &noobsmap); + if (r == -1) + continue; + if (solvable_lookup_bool(s, UPDATE_RESTART) && r == 0) + { + if (!pruneyou++) + queue_empty(job); + } + else if (pruneyou) + continue; + queue_push2(job, SOLVER_SOLVABLE, p); + } + map_free(&installedmap); + map_free(&noobsmap); +} + #define MODE_LIST 0 #define MODE_INSTALL 1 #define MODE_ERASE 2 @@ -2539,7 +2392,6 @@ rewrite_repos(Pool *pool, Id *addedfileprovides) #define MODE_INFO 7 #define MODE_REPOLIST 8 #define MODE_SEARCH 9 -#define MODE_ERASECLEAN 10 void usage(int r) @@ -2575,10 +2427,13 @@ main(int argc, char **argv) Solver *solv = 0; Transaction *trans; char inbuf[128], *ip; - int allpkgs = 0; FILE **newpkgsfps; - Id *addedfileprovides = 0; - Id repofilter = 0; + Queue addedfileprovides; + Queue addedfileprovides_inst; + Queue repofilter; + int cleandeps = 0; + int forcebest = 0; + char *rootdir = 0; argc--; argv++; @@ -2599,11 +2454,6 @@ main(int argc, char **argv) mainmode = MODE_ERASE; mode = SOLVER_ERASE; } - else if (!strcmp(argv[0], "eraseclean") || !strcmp(argv[0], "rmclean")) - { - mainmode = MODE_ERASECLEAN; - mode = SOLVER_ERASE; - } else if (!strcmp(argv[0], "list")) { mainmode = MODE_LIST; @@ -2632,7 +2482,7 @@ main(int argc, char **argv) else if (!strcmp(argv[0], "dist-upgrade") || !strcmp(argv[0], "dup")) { mainmode = MODE_DISTUPGRADE; - mode = SOLVER_UPDATE; + mode = SOLVER_DISTUPGRADE; } else if (!strcmp(argv[0], "repos") || !strcmp(argv[0], "repolist") || !strcmp(argv[0], "lr")) { @@ -2642,7 +2492,33 @@ main(int argc, char **argv) else usage(1); + for (;;) + { + if (argc > 2 && !strcmp(argv[1], "--root")) + { + rootdir = argv[2]; + argc -= 2; + argv += 2; + } + + else if (argc > 1 && !strcmp(argv[1], "--clean")) + { + cleandeps = 1; + argc--; + argv++; + } + else if (argc > 1 && !strcmp(argv[1], "--best")) + { + forcebest = 1; + argc--; + argv++; + } + else + break; + } + pool = pool_create(); + pool_set_rootdir(pool, rootdir); #if 0 { @@ -2651,14 +2527,11 @@ main(int argc, char **argv) } #endif -#ifdef FEDORA - pool->obsoleteusescolors = 1; -#endif pool_setloadcallback(pool, load_stub, 0); pool->nscallback = nscallback; // pool_setdebuglevel(pool, 2); setarch(pool); - repoinfos = read_repoinfos(pool, REPOINFO_PATH, &nrepoinfos); + repoinfos = read_repoinfos(pool, &nrepoinfos); if (mainmode == MODE_REPOLIST) { @@ -2675,9 +2548,11 @@ main(int argc, char **argv) read_repos(pool, repoinfos, nrepoinfos); - if (argc > 2 && !strcmp(argv[1], "-r")) + queue_init(&repofilter); + while (argc > 2 && !strcmp(argv[1], "-r")) { const char *rname = argv[2], *rp; + Id repoid = 0; for (rp = rname; *rp; rp++) if (*rp <= '0' || *rp >= '9') break; @@ -2691,7 +2566,7 @@ main(int argc, char **argv) if (!cinfo->enabled) continue; if (--rnum == 0) - repofilter = cinfo->repo->repoid; + repoid = cinfo->repo->repoid; } } else @@ -2701,14 +2576,16 @@ main(int argc, char **argv) FOR_REPOS(i, repo) { if (!strcasecmp(rname, repo->name)) - repofilter = repo->repoid; + repoid = repo->repoid; } } - if (!repofilter) + if (!repoid) { fprintf(stderr, "%s: no such repo\n", rname); exit(1); } + /* SETVENDOR is actually wrong but useful */ + queue_push2(&repofilter, SOLVER_SOLVABLE_REPO | SOLVER_SETREPO | SOLVER_SETVENDOR, repoid); argc -= 2; argv += 2; } @@ -2739,7 +2616,7 @@ main(int argc, char **argv) Solvable *s = pool_id2solvable(pool, p); if (!MAPTST(&m, p)) continue; - printf(" - %s: %s\n", solvable2str(pool, s), solvable_lookup_str(s, SOLVABLE_SUMMARY)); + printf(" - %s: %s\n", pool_solvable2str(pool, s), solvable_lookup_str(s, SOLVABLE_SUMMARY)); } map_free(&m); exit(0); @@ -2752,10 +2629,11 @@ main(int argc, char **argv) { int l; l = strlen(argv[i]); -#ifndef DEBIAN +#if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA)) if (l <= 4 || strcmp(argv[i] + l - 4, ".rpm")) continue; -#else +#endif +#if defined(ENABLE_DEBIAN) && defined(DEBIAN) if (l <= 4 || strcmp(argv[i] + l - 4, ".deb")) continue; #endif @@ -2765,14 +2643,21 @@ main(int argc, char **argv) exit(1); } if (!commandlinepkgs) - commandlinepkgs = sat_calloc(argc, sizeof(Id)); + commandlinepkgs = solv_calloc(argc, sizeof(Id)); if (!commandlinerepo) commandlinerepo = repo_create(pool, "@commandline"); -#ifndef DEBIAN + p = 0; +#if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA)) p = repo_add_rpm(commandlinerepo, (const char *)argv[i], REPO_REUSE_REPODATA|REPO_NO_INTERNALIZE); -#else +#endif +#if defined(ENABLE_DEBIAN) && defined(DEBIAN) p = repo_add_deb(commandlinerepo, (const char *)argv[i], REPO_REUSE_REPODATA|REPO_NO_INTERNALIZE); #endif + if (!p) + { + fprintf(stderr, "could not add '%s'\n", argv[i]); + exit(1); + } commandlinepkgs[i] = p; } if (commandlinerepo) @@ -2781,18 +2666,20 @@ main(int argc, char **argv) // FOR_REPOS(i, repo) // printf("%s: %d solvables\n", repo->name, repo->nsolvables); - addedfileprovides = 0; - pool_addfileprovides_ids(pool, pool->installed, &addedfileprovides); - if (addedfileprovides && *addedfileprovides) - rewrite_repos(pool, addedfileprovides); - sat_free(addedfileprovides); + queue_init(&addedfileprovides); + queue_init(&addedfileprovides_inst); + pool_addfileprovides_queue(pool, &addedfileprovides, &addedfileprovides_inst); + if (addedfileprovides.count || addedfileprovides_inst.count) + rewrite_repos(pool, &addedfileprovides, &addedfileprovides_inst); + queue_free(&addedfileprovides); + queue_free(&addedfileprovides_inst); pool_createwhatprovides(pool); queue_init(&job); for (i = 1; i < argc; i++) { Queue job2; - int j; + int j, flags, rflags; if (commandlinepkgs && commandlinepkgs[i]) { @@ -2800,43 +2687,68 @@ main(int argc, char **argv) continue; } queue_init(&job2); - if (!mkselect(pool, mode, argv[i], &job2)) + flags = SELECTION_NAME|SELECTION_PROVIDES|SELECTION_GLOB; + if (mode == MODE_LIST) + flags |= SELECTION_WITH_SOURCE; + if (argv[i][0] == '/') + flags |= SELECTION_FILELIST | (mode == MODE_ERASE ? SELECTION_INSTALLED_ONLY : 0); + rflags = selection_make(pool, &job2, argv[i], flags); + if (repofilter.count) + selection_limit(pool, &job2, &repofilter); + if (!job2.count) + { + flags |= SELECTION_NOCASE; + rflags = selection_make(pool, &job2, argv[i], flags); + if (repofilter.count) + selection_limit(pool, &job2, &repofilter); + if (job2.count) + printf("[ignoring case for '%s']\n", argv[i]); + } + if (!job2.count) { fprintf(stderr, "nothing matches '%s'\n", argv[i]); exit(1); } - if (repofilter && !limitrepo(pool, repofilter, &job2)) - { - fprintf(stderr, "nothing in repo matches '%s'\n", argv[i]); - exit(1); - } + if (rflags & SELECTION_FILELIST) + printf("[using file list match for '%s']\n", argv[i]); + if (rflags & SELECTION_PROVIDES) + printf("[using capability match for '%s']\n", argv[i]); for (j = 0; j < job2.count; j++) queue_push(&job, job2.elements[j]); queue_free(&job2); } - if (!job.count && mainmode != MODE_UPDATE && mainmode != MODE_DISTUPGRADE && mainmode != MODE_VERIFY && mainmode != MODE_PATCH) + if (!job.count && (mainmode == MODE_UPDATE || mainmode == MODE_DISTUPGRADE || mainmode == MODE_VERIFY || repofilter.count)) + { + queue_push2(&job, SOLVER_SOLVABLE_ALL, 0); + if (repofilter.count) + selection_limit(pool, &job, &repofilter); + } + queue_free(&repofilter); + + if (!job.count && MODE_PATCH) { printf("no package matched\n"); exit(1); } - if (!job.count) - allpkgs = 1; - if (mainmode == MODE_LIST || mainmode == MODE_INFO) { /* list mode, no solver needed */ + Queue q; + queue_init(&q); for (i = 0; i < job.count; i += 2) { - Id how = job.elements[i] & SOLVER_SELECTMASK; - FOR_JOB_SELECT(p, pp, how, job.elements[i + 1]) + int j; + queue_empty(&q); + pool_job2solvables(pool, &q, job.elements[i], job.elements[i + 1]); + for (j = 0; j < q.count; j++) { - Solvable *s = pool_id2solvable(pool, p); + Solvable *s = pool_id2solvable(pool, q.elements[j]); if (mainmode == MODE_INFO) { const char *str; - printf("Name: %s\n", solvable2str(pool, s)); + printf("Name: %s\n", pool_solvable2str(pool, s)); printf("Repo: %s\n", s->repo->name); printf("Summary: %s\n", solvable_lookup_str(s, SOLVABLE_SUMMARY)); str = solvable_lookup_str(s, SOLVABLE_URL); @@ -2855,16 +2767,17 @@ main(int argc, char **argv) #else const char *sum = solvable_lookup_str_poollang(s, SOLVABLE_SUMMARY); #endif - printf(" - %s [%s]\n", solvable2str(pool, s), s->repo->name); + printf(" - %s [%s]\n", pool_solvable2str(pool, s), s->repo->name); if (sum) printf(" %s\n", sum); } } } + queue_free(&q); queue_free(&job); pool_free(pool); free_repoinfos(repoinfos, nrepoinfos); - sat_free(commandlinepkgs); + solv_free(commandlinepkgs); #ifdef FEDORA yum_substitute(pool, 0); #endif @@ -2872,88 +2785,30 @@ main(int argc, char **argv) } if (mainmode == MODE_PATCH) - { - int pruneyou = 0; - Map installedmap; - Solvable *s; - - map_init(&installedmap, pool->nsolvables); - if (pool->installed) - FOR_REPO_SOLVABLES(pool->installed, p, s) - MAPSET(&installedmap, p); - - /* install all patches */ - for (p = 1; p < pool->nsolvables; p++) - { - const char *type; - int r; - Id p2; - - s = pool->solvables + p; - if (strncmp(id2str(pool, s->name), "patch:", 6) != 0) - continue; - FOR_PROVIDES(p2, pp, s->name) - { - Solvable *s2 = pool->solvables + p2; - if (s2->name != s->name) - continue; - r = evrcmp(pool, s->evr, s2->evr, EVRCMP_COMPARE); - if (r < 0 || (r == 0 && p > p2)) - break; - } - if (p2) - continue; - type = solvable_lookup_str(s, SOLVABLE_PATCHCATEGORY); - if (type && !strcmp(type, "optional")) - continue; - r = solvable_trivial_installable_map(s, &installedmap, 0); - if (r == -1) - continue; - if (solvable_lookup_bool(s, UPDATE_RESTART) && r == 0) - { - if (!pruneyou++) - queue_empty(&job); - } - else if (pruneyou) - continue; - queue_push2(&job, SOLVER_SOLVABLE, p); - } - map_free(&installedmap); - } + select_patches(pool, &job); // add mode for (i = 0; i < job.count; i += 2) { - if (mode == SOLVER_UPDATE) - { - /* make update of not installed packages an install */ - FOR_JOB_SELECT(p, pp, job.elements[i], job.elements[i + 1]) - if (pool->installed && pool->solvables[p].repo == pool->installed) - break; - if (!p) - { - job.elements[i] |= SOLVER_INSTALL; - continue; - } - } job.elements[i] |= mode; - if (mainmode == MODE_ERASECLEAN) + if (mode == SOLVER_UPDATE && pool_isemptyupdatejob(pool, job.elements[i], job.elements[i + 1])) + job.elements[i] ^= SOLVER_UPDATE ^ SOLVER_INSTALL; + if (cleandeps) job.elements[i] |= SOLVER_CLEANDEPS; + if (forcebest) + job.elements[i] |= SOLVER_FORCEBEST; } - if (mainmode == MODE_DISTUPGRADE && allpkgs && repofilter) - queue_push2(&job, SOLVER_DISTUPGRADE|SOLVER_SOLVABLE_REPO, repofilter); - // multiversion test - // queue_push2(&job, SOLVER_NOOBSOLETES|SOLVER_SOLVABLE_NAME, str2id(pool, "kernel-pae", 1)); - // queue_push2(&job, SOLVER_NOOBSOLETES|SOLVER_SOLVABLE_NAME, str2id(pool, "kernel-pae-base", 1)); - // queue_push2(&job, SOLVER_NOOBSOLETES|SOLVER_SOLVABLE_NAME, str2id(pool, "kernel-pae-extra", 1)); + // queue_push2(&job, SOLVER_NOOBSOLETES|SOLVER_SOLVABLE_NAME, pool_str2id(pool, "kernel-pae", 1)); + // queue_push2(&job, SOLVER_NOOBSOLETES|SOLVER_SOLVABLE_NAME, pool_str2id(pool, "kernel-pae-base", 1)); + // queue_push2(&job, SOLVER_NOOBSOLETES|SOLVER_SOLVABLE_NAME, pool_str2id(pool, "kernel-pae-extra", 1)); #ifdef SOFTLOCKS_PATH addsoftlocks(pool, &job); #endif -#ifndef DEBIAN +#if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA)) rerunsolver: #endif for (;;) @@ -2962,22 +2817,12 @@ rerunsolver: int pcnt, scnt; solv = solver_create(pool); - solv->ignorealreadyrecommended = 1; - solv->updatesystem = allpkgs && !repofilter && (mainmode == MODE_UPDATE || mainmode == MODE_DISTUPGRADE); - solv->dosplitprovides = solv->updatesystem; - solv->fixsystem = allpkgs && !repofilter && mainmode == MODE_VERIFY; - if (mainmode == MODE_DISTUPGRADE && allpkgs && !repofilter) - { - solv->distupgrade = 1; - solv->allowdowngrade = 1; - solv->allowarchchange = 1; - solv->allowvendorchange = 1; - } - if (mainmode == MODE_ERASE || mainmode == MODE_ERASECLEAN) - solv->allowuninstall = 1; /* don't nag */ - - solver_solve(solv, &job); - if (!solv->problems.count) + solver_set_flag(solv, SOLVER_FLAG_SPLITPROVIDES, 1); + if (mainmode == MODE_ERASE) + solver_set_flag(solv, SOLVER_FLAG_ALLOW_UNINSTALL, 1); /* don't nag */ + solver_set_flag(solv, SOLVER_FLAG_BEST_OBEY_POLICY, 1); + + if (!solver_solve(solv, &job)) break; pcnt = solver_problem_count(solv); printf("Found %d problems:\n", pcnt); @@ -3031,15 +2876,16 @@ rerunsolver: solv = 0; } - trans = &solv->trans; + trans = solver_create_transaction(solv); if (!trans->steps.count) { printf("Nothing to do.\n"); + transaction_free(trans); solver_free(solv); queue_free(&job); pool_free(pool); free_repoinfos(repoinfos, nrepoinfos); - sat_free(commandlinepkgs); + solv_free(commandlinepkgs); #ifdef FEDORA yum_substitute(pool, 0); #endif @@ -3047,9 +2893,9 @@ rerunsolver: } printf("\n"); printf("Transaction summary:\n\n"); - solver_printtransaction(solv); + transaction_print(trans); -#if !defined(FEDORA) && !defined(DEBIAN) +#if defined(SUSE) if (1) { DUChanges duc[4]; @@ -3070,11 +2916,12 @@ rerunsolver: if (!yesno("OK to continue (y/n)? ")) { printf("Abort.\n"); + transaction_free(trans); solver_free(solv); queue_free(&job); pool_free(pool); free_repoinfos(repoinfos, nrepoinfos); - sat_free(commandlinepkgs); + solv_free(commandlinepkgs); #ifdef FEDORA yum_substitute(pool, 0); #endif @@ -3094,14 +2941,14 @@ rerunsolver: p = checkq.elements[i]; s = pool_id2solvable(pool, p); - downloadsize += solvable_lookup_num(s, SOLVABLE_DOWNLOADSIZE, 0); + downloadsize += solvable_lookup_sizek(s, SOLVABLE_DOWNLOADSIZE, 0); } printf("Downloading %d packages, %d K\n", newpkgs, downloadsize); - newpkgsfps = sat_calloc(newpkgs, sizeof(*newpkgsfps)); + newpkgsfps = solv_calloc(newpkgs, sizeof(*newpkgsfps)); for (i = 0; i < newpkgs; i++) { unsigned int medianr; - char *loc; + const char *loc; Solvable *s; struct repoinfo *cinfo; const unsigned char *chksum; @@ -3112,7 +2959,7 @@ rerunsolver: s = pool_id2solvable(pool, p); if (s->repo == commandlinerepo) { - loc = solvable_get_location(s, &medianr); + loc = solvable_lookup_location(s, &medianr); if (!(newpkgsfps[i] = fopen(loc, "r"))) { perror(loc); @@ -3127,14 +2974,14 @@ rerunsolver: printf("%s: no repository information\n", s->repo->name); exit(1); } - loc = solvable_get_location(s, &medianr); + loc = solvable_lookup_location(s, &medianr); if (!loc) continue; if (pool->installed && pool->installed->nsolvables) { /* try a delta first */ - char *matchname = strdup(id2str(pool, s->name)); + char *matchname = strdup(pool_id2str(pool, s->name)); dataiterator_init(&di, pool, s->repo, SOLVID_META, DELTA_PACKAGE_NAME, matchname, SEARCH_STRING); dataiterator_prepend_keyname(&di, REPOSITORY_DELTAINFO); while (dataiterator_step(&di)) @@ -3160,37 +3007,48 @@ rerunsolver: const char *seqnum; const char *seq; const char *dloc; + const char *archstr; FILE *fp; char cmd[128]; int newfd; + archstr = pool_id2str(pool, s->arch); + if (strlen(archstr) > 10 || strchr(archstr, '\'') != 0) + continue; + seqname = pool_lookup_str(pool, SOLVID_POS, DELTA_SEQ_NAME); seqevr = pool_lookup_str(pool, SOLVID_POS, DELTA_SEQ_EVR); seqnum = pool_lookup_str(pool, SOLVID_POS, DELTA_SEQ_NUM); seq = pool_tmpjoin(pool, seqname, "-", seqevr); - seq = pool_tmpjoin(pool, seq, "-", seqnum); + seq = pool_tmpappend(pool, seq, "-", seqnum); + if (strchr(seq, '\'') != 0) + continue; #ifdef FEDORA - sprintf(cmd, "/usr/bin/applydeltarpm -a %s -c -s ", id2str(pool, s->arch)); + sprintf(cmd, "/usr/bin/applydeltarpm -a '%s' -c -s '", archstr); #else - sprintf(cmd, "/usr/bin/applydeltarpm -c -s "); + sprintf(cmd, "/usr/bin/applydeltarpm -c -s '"); #endif - if (system(pool_tmpjoin(pool, cmd, seq, 0)) != 0) + if (system(pool_tmpjoin(pool, cmd, seq, "'")) != 0) continue; /* didn't match */ /* looks good, download delta */ chksumtype = 0; chksum = pool_lookup_bin_checksum(pool, SOLVID_POS, DELTA_CHECKSUM, &chksumtype); if (!chksumtype) continue; /* no way! */ - dloc = pool_lookup_str(pool, SOLVID_POS, DELTA_LOCATION_DIR); - dloc = pool_tmpjoin(pool, dloc, "/", pool_lookup_str(pool, SOLVID_POS, DELTA_LOCATION_NAME)); - dloc = pool_tmpjoin(pool, dloc, "-", pool_lookup_str(pool, SOLVID_POS, DELTA_LOCATION_EVR)); - dloc = pool_tmpjoin(pool, dloc, ".", pool_lookup_str(pool, SOLVID_POS, DELTA_LOCATION_SUFFIX)); + dloc = pool_lookup_deltalocation(pool, SOLVID_POS, 0); + if (!dloc) + continue; + if (cinfo->type == TYPE_SUSETAGS) + { + const char *datadir = repo_lookup_str(cinfo->repo, SOLVID_META, SUSETAGS_DATADIR); + dloc = pool_tmpjoin(pool, datadir ? datadir : "suse", "/", dloc); + } if ((fp = curlfopen(cinfo, dloc, 0, chksum, chksumtype, 0)) == 0) continue; /* got it, now reconstruct */ newfd = opentmpfile(); #ifdef FEDORA - sprintf(cmd, "applydeltarpm -a %s /dev/fd/%d /dev/fd/%d", id2str(pool, s->arch), fileno(fp), newfd); + sprintf(cmd, "applydeltarpm -a '%s' /dev/fd/%d /dev/fd/%d", archstr, fileno(fp), newfd); #else sprintf(cmd, "applydeltarpm /dev/fd/%d /dev/fd/%d", fileno(fp), newfd); #endif @@ -3216,9 +3074,9 @@ rerunsolver: } } dataiterator_free(&di); - sat_free(matchname); + solv_free(matchname); } - + if (newpkgsfps[i]) { putchar('d'); @@ -3243,7 +3101,7 @@ rerunsolver: putchar('\n'); } -#ifndef DEBIAN +#if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA)) if (newpkgs) { Queue conflicts; @@ -3260,14 +3118,14 @@ rerunsolver: { printf("\n"); for (i = 0; i < conflicts.count; i += 5) - printf("file %s of package %s conflicts with package %s\n", id2str(pool, conflicts.elements[i]), solvid2str(pool, conflicts.elements[i + 1]), solvid2str(pool, conflicts.elements[i + 3])); + printf("file %s of package %s conflicts with package %s\n", pool_id2str(pool, conflicts.elements[i]), pool_solvid2str(pool, conflicts.elements[i + 1]), pool_solvid2str(pool, conflicts.elements[i + 3])); printf("\n"); if (yesno("Re-run solver (y/n/q)? ")) { for (i = 0; i < newpkgs; i++) if (newpkgsfps[i]) fclose(newpkgsfps[i]); - newpkgsfps = sat_free(newpkgsfps); + newpkgsfps = solv_free(newpkgsfps); solver_free(solv); pool_add_fileconflicts_deps(pool, &conflicts); pool_createwhatprovides(pool); /* Hmm... */ @@ -3282,7 +3140,7 @@ rerunsolver: transaction_order(trans, 0); for (i = 0; i < trans->steps.count; i++) { -#ifndef DEBIAN +#if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA)) const char *evr, *evrp, *nvra; #endif Solvable *s; @@ -3295,26 +3153,27 @@ rerunsolver: switch(type) { case SOLVER_TRANSACTION_ERASE: - printf("erase %s\n", solvid2str(pool, p)); -#ifndef DEBIAN + printf("erase %s\n", pool_solvid2str(pool, p)); +#if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA)) if (!s->repo->rpmdbid || !s->repo->rpmdbid[p - s->repo->start]) continue; /* strip epoch from evr */ - evr = evrp = id2str(pool, s->evr); + evr = evrp = pool_id2str(pool, s->evr); while (*evrp >= '0' && *evrp <= '9') evrp++; if (evrp > evr && evrp[0] == ':' && evrp[1]) evr = evrp + 1; - nvra = pool_tmpjoin(pool, id2str(pool, s->name), "-", evr); - nvra = pool_tmpjoin(pool, nvra, ".", id2str(pool, s->arch)); - runrpm("-e", nvra, -1); /* too bad that --querybynumber doesn't work */ -#else - rundpkg("--remove", id2str(pool, s->name), 0); + nvra = pool_tmpjoin(pool, pool_id2str(pool, s->name), "-", evr); + nvra = pool_tmpappend(pool, nvra, ".", pool_id2str(pool, s->arch)); + runrpm("-e", nvra, -1, rootdir); /* too bad that --querybynumber doesn't work */ +#endif +#if defined(ENABLE_DEBIAN) && defined(DEBIAN) + rundpkg("--remove", pool_id2str(pool, s->name), 0, rootdir); #endif break; case SOLVER_TRANSACTION_INSTALL: case SOLVER_TRANSACTION_MULTIINSTALL: - printf("install %s\n", solvid2str(pool, p)); + printf("install %s\n", pool_solvid2str(pool, p)); for (j = 0; j < newpkgs; j++) if (checkq.elements[j] == p) break; @@ -3323,10 +3182,11 @@ rerunsolver: continue; rewind(fp); lseek(fileno(fp), 0, SEEK_SET); -#ifndef DEBIAN - runrpm(type == SOLVER_TRANSACTION_MULTIINSTALL ? "-i" : "-U", "/dev/fd/3", fileno(fp)); -#else - rundpkg("--install", "/dev/fd/3", fileno(fp)); +#if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA)) + runrpm(type == SOLVER_TRANSACTION_MULTIINSTALL ? "-i" : "-U", "/dev/fd/3", fileno(fp), rootdir); +#endif +#if defined(ENABLE_DEBIAN) && defined(DEBIAN) + rundpkg("--install", "/dev/fd/3", fileno(fp), rootdir); #endif fclose(fp); newpkgsfps[j] = 0; @@ -3339,13 +3199,14 @@ rerunsolver: for (i = 0; i < newpkgs; i++) if (newpkgsfps[i]) fclose(newpkgsfps[i]); - sat_free(newpkgsfps); + solv_free(newpkgsfps); queue_free(&checkq); + transaction_free(trans); solver_free(solv); queue_free(&job); pool_free(pool); free_repoinfos(repoinfos, nrepoinfos); - sat_free(commandlinepkgs); + solv_free(commandlinepkgs); #ifdef FEDORA yum_substitute(pool, 0); #endif