diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/CMakeLists.txt | 101 | ||||
-rw-r--r-- | tools/pool_fileconflicts.c | 423 | ||||
-rw-r--r-- | tools/pool_fileconflicts.h | 8 | ||||
-rw-r--r-- | tools/repo_content.c | 465 | ||||
-rw-r--r-- | tools/repo_content.h | 8 | ||||
-rw-r--r-- | tools/repo_deltainfoxml.c | 608 | ||||
-rw-r--r-- | tools/repo_deltainfoxml.h | 8 | ||||
-rw-r--r-- | tools/repo_products.c | 556 | ||||
-rw-r--r-- | tools/repo_products.h | 9 | ||||
-rw-r--r-- | tools/repo_releasefile_products.c | 156 | ||||
-rw-r--r-- | tools/repo_releasefile_products.h | 8 | ||||
-rw-r--r-- | tools/repo_repomdxml.c | 456 | ||||
-rw-r--r-- | tools/repo_repomdxml.h | 8 | ||||
-rw-r--r-- | tools/repo_rpmdb.c | 2248 | ||||
-rw-r--r-- | tools/repo_rpmdb.h | 21 | ||||
-rw-r--r-- | tools/repo_rpmmd.c | 1158 | ||||
-rw-r--r-- | tools/repo_rpmmd.h | 10 | ||||
-rw-r--r-- | tools/repo_susetags.c | 963 | ||||
-rw-r--r-- | tools/repo_susetags.h | 15 | ||||
-rw-r--r-- | tools/repo_updateinfoxml.c | 616 | ||||
-rw-r--r-- | tools/repo_updateinfoxml.h | 8 | ||||
-rw-r--r-- | tools/repo_write.c | 1936 | ||||
-rw-r--r-- | tools/repo_write.h | 38 | ||||
-rw-r--r-- | tools/repo_zyppdb.c | 394 | ||||
-rw-r--r-- | tools/repo_zyppdb.h | 8 | ||||
-rw-r--r-- | tools/tools_util.h | 117 |
26 files changed, 42 insertions, 10304 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 576dae4..6502f4a 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -2,77 +2,60 @@ # CMakeLists.txt for sat-solver/tools # -# Let's not compile the same files ten times; this library is not installed -ADD_LIBRARY( toolstuff STATIC repo_write.c common_write.c ) +ADD_LIBRARY( toolstuff STATIC common_write.c ) -SET(rpmdb2solv_REPOS - rpmdb2solv.c - repo_rpmdb.c - repo_products.c - repo_zyppdb.c - repo_releasefile_products.c -) +ADD_EXECUTABLE(rpmdb2solv rpmdb2solv.c) +TARGET_LINK_LIBRARIES(rpmdb2solv toolstuff satsolverext satsolver ${RPMDB_LIBRARY} ${EXPAT_LIBRARY}) -ADD_EXECUTABLE( rpmdb2solv ${rpmdb2solv_REPOS} ) -TARGET_LINK_LIBRARIES( rpmdb2solv satsolver toolstuff ${RPMDB_LIBRARY} ${EXPAT_LIBRARY}) +ADD_EXECUTABLE(rpms2solv rpms2solv.c) +TARGET_LINK_LIBRARIES(rpms2solv toolstuff satsolverext satsolver ${RPMDB_LIBRARY}) -SET(rpms2solv_REPOS rpms2solv.c repo_rpmdb.c ) -ADD_EXECUTABLE( rpms2solv ${rpms2solv_REPOS} ) -TARGET_LINK_LIBRARIES( rpms2solv satsolver toolstuff ${RPMDB_LIBRARY}) +ADD_EXECUTABLE(rpmmd2solv rpmmd2solv.c) +TARGET_LINK_LIBRARIES(rpmmd2solv toolstuff satsolverext satsolver ${EXPAT_LIBRARY} ${ZLIB_LIBRARY}) -SET(rpmmd2solv_REPOS rpmmd2solv.c repo_rpmmd.c ) -ADD_EXECUTABLE( rpmmd2solv ${rpmmd2solv_REPOS} ) -TARGET_LINK_LIBRARIES( rpmmd2solv satsolver toolstuff ${EXPAT_LIBRARY} ${ZLIB_LIBRARY}) +ADD_EXECUTABLE(helix2solv helix2solv.c ${helix2solv_REPOS} ) +TARGET_LINK_LIBRARIES(helix2solv toolstuff satsolverext satsolver ${EXPAT_LIBRARY}) -SET(helix2solv_REPOS helix2solv.c ) -ADD_EXECUTABLE( helix2solv ${helix2solv_REPOS} ) -TARGET_LINK_LIBRARIES( helix2solv satsolver toolstuff ${EXPAT_LIBRARY}) +ADD_EXECUTABLE(susetags2solv susetags2solv.c) +TARGET_LINK_LIBRARIES(susetags2solv toolstuff satsolverext satsolver ${ZLIB_LIBRARY}) -SET(susetags2solv_REPOS susetags2solv.c repo_susetags.c repo_content.c ) -ADD_EXECUTABLE( susetags2solv ${susetags2solv_REPOS} ) -TARGET_LINK_LIBRARIES( susetags2solv satsolver toolstuff ${ZLIB_LIBRARY}) +ADD_EXECUTABLE(updateinfoxml2solv updateinfoxml2solv.c) +TARGET_LINK_LIBRARIES(updateinfoxml2solv toolstuff satsolverext satsolver ${EXPAT_LIBRARY}) -SET(updateinfoxml2solv_REPOS updateinfoxml2solv.c repo_updateinfoxml.c) -ADD_EXECUTABLE( updateinfoxml2solv ${updateinfoxml2solv_REPOS} ) -TARGET_LINK_LIBRARIES( updateinfoxml2solv satsolver toolstuff ${EXPAT_LIBRARY}) +ADD_EXECUTABLE(deltainfoxml2solv deltainfoxml2solv.c) +TARGET_LINK_LIBRARIES(deltainfoxml2solv toolstuff satsolverext satsolver ${EXPAT_LIBRARY}) -SET(deltainfoxml2solv_REPOS deltainfoxml2solv.c repo_deltainfoxml.c) -ADD_EXECUTABLE( deltainfoxml2solv ${deltainfoxml2solv_REPOS} ) -TARGET_LINK_LIBRARIES( deltainfoxml2solv satsolver toolstuff ${EXPAT_LIBRARY}) +ADD_EXECUTABLE(repomdxml2solv repomdxml2solv.c) +TARGET_LINK_LIBRARIES(repomdxml2solv toolstuff satsolverext satsolver ${EXPAT_LIBRARY}) -SET(repomdxml2solv_REPOS repomdxml2solv.c repo_repomdxml.c) -ADD_EXECUTABLE( repomdxml2solv ${repomdxml2solv_REPOS} ) -TARGET_LINK_LIBRARIES( repomdxml2solv satsolver toolstuff ${EXPAT_LIBRARY}) +ADD_EXECUTABLE(installcheck installcheck.c) +TARGET_LINK_LIBRARIES(installcheck satsolverext satsolver ${EXPAT_LIBRARY} ${ZLIB_LIBRARY}) -SET(installcheck_SOURCES installcheck.c repo_rpmmd.c repo_susetags.c) -ADD_EXECUTABLE(installcheck ${installcheck_SOURCES}) -TARGET_LINK_LIBRARIES(installcheck satsolver ${EXPAT_LIBRARY} ${ZLIB_LIBRARY}) +ADD_EXECUTABLE(patchcheck patchcheck.c) +TARGET_LINK_LIBRARIES(patchcheck satsolverext satsolver ${EXPAT_LIBRARY} ${ZLIB_LIBRARY}) -SET(patchcheck_SOURCES patchcheck.c repo_rpmmd.c repo_susetags.c repo_updateinfoxml.c) -ADD_EXECUTABLE(patchcheck ${patchcheck_SOURCES}) -TARGET_LINK_LIBRARIES(patchcheck satsolver ${EXPAT_LIBRARY} ${ZLIB_LIBRARY}) +ADD_EXECUTABLE(dumpsolv dumpsolv.c ) +TARGET_LINK_LIBRARIES(dumpsolv satsolver) -ADD_EXECUTABLE( dumpsolv dumpsolv.c ) -TARGET_LINK_LIBRARIES( dumpsolv satsolver) +ADD_EXECUTABLE(mergesolv mergesolv.c ) +TARGET_LINK_LIBRARIES(mergesolv toolstuff satsolverext satsolver) -ADD_EXECUTABLE( mergesolv mergesolv.c ) -TARGET_LINK_LIBRARIES( mergesolv satsolver toolstuff) - -SET(findfileconflicts_SOURCES findfileconflicts.c pool_fileconflicts.c repo_rpmdb.c ) -ADD_EXECUTABLE( findfileconflicts ${findfileconflicts_SOURCES} ) -TARGET_LINK_LIBRARIES( findfileconflicts satsolver ${RPMDB_LIBRARY} ${EXPAT_LIBRARY} ) +ADD_EXECUTABLE(findfileconflicts findfileconflicts.c) +TARGET_LINK_LIBRARIES(findfileconflicts satsolverext satsolver ${RPMDB_LIBRARY}) install(TARGETS - mergesolv - dumpsolv - susetags2solv - helix2solv - rpmmd2solv - rpmdb2solv - rpms2solv - updateinfoxml2solv - deltainfoxml2solv - repomdxml2solv - DESTINATION ${BIN_INSTALL_DIR} ) - -install(PROGRAMS repo2solv.sh DESTINATION ${BIN_INSTALL_DIR} ) + mergesolv + dumpsolv + susetags2solv + helix2solv + rpmmd2solv + rpmdb2solv + rpms2solv + updateinfoxml2solv + deltainfoxml2solv + repomdxml2solv + DESTINATION ${BIN_INSTALL_DIR}) + +install(PROGRAMS + repo2solv.sh + DESTINATION ${BIN_INSTALL_DIR}) diff --git a/tools/pool_fileconflicts.c b/tools/pool_fileconflicts.c deleted file mode 100644 index 1858df4..0000000 --- a/tools/pool_fileconflicts.c +++ /dev/null @@ -1,423 +0,0 @@ -#include <stdio.h> -#include <sys/stat.h> - -#include "pool.h" -#include "repo.h" -#include "hash.h" -#include "repo_rpmdb.h" -#include "pool_fileconflicts.h" - -struct cbdata { - Pool *pool; - int create; - - Queue lookat; - Queue lookat_dir; - - Hashval *cflmap; - Hashmask cflmapn; - unsigned int cflmapused; - - Hashval *dirmap; - Hashmask dirmapn; - unsigned int dirmapused; - int dirconflicts; - - Map idxmap; - - Hashval idx; - unsigned int hx; - - Queue files; - unsigned char *filesspace; - unsigned int filesspacen; -}; - -#define FILESSPACE_BLOCK 255 - -static Hashval * -doublehash(Hashval *map, Hashmask *mapnp) -{ - Hashmask mapn = *mapnp; - Hashmask i, hx, qx, h, hh; - Hashmask nn = (mapn + 1) * 2 - 1; - Hashmask *m; - - m = sat_calloc(nn + 1, 2 * sizeof(Id)); - for (i = 0; i <= mapn; i++) - { - hx = map[2 * i]; - if (!hx) - continue; - h = hx & nn; - hh = HASHCHAIN_START; - for (;;) - { - qx = m[2 * h]; - if (!qx) - break; - h = HASHCHAIN_NEXT(h, hh, nn); - } - m[2 * h] = hx; - m[2 * h + 1] = map[2 * i + 1]; - } - sat_free(map); - *mapnp = nn; - return m; -} - -static void -finddirs_cb(void *cbdatav, const char *fn, int fmode, const char *md5) -{ - struct cbdata *cbdata = cbdatav; - Hashmask h, hh, hx, qx; - Hashval idx = cbdata->idx; - - hx = strhash(fn); - if (!hx) - hx = strlen(fn) + 1; - h = hx & cbdata->dirmapn; - hh = HASHCHAIN_START; - for (;;) - { - qx = cbdata->dirmap[2 * h]; - if (!qx) - break; - if (qx == hx) - break; - h = HASHCHAIN_NEXT(h, hh, cbdata->dirmapn); - } - if (!qx) - { - /* a miss */ - if (!cbdata->create) - return; - cbdata->dirmap[2 * h] = hx; - cbdata->dirmap[2 * h + 1] = idx; - cbdata->dirmapused++; - if (cbdata->dirmapused * 2 > cbdata->dirmapn) - cbdata->dirmap = doublehash(cbdata->dirmap, &cbdata->dirmapn); - return; - } - if (cbdata->dirmap[2 * h + 1] == idx) - return; - /* found a conflict, this dir is used in multiple packages */ - if (cbdata->dirmap[2 * h + 1] != -1) - { - cbdata->dirmap[2 * h + 1] = -1; - cbdata->dirconflicts++; - } - MAPSET(&cbdata->idxmap, idx); -} - -static inline int -isindirmap(struct cbdata *cbdata, Hashmask hx) -{ - Hashmask h, hh, qx; - - h = hx & cbdata->dirmapn; - hh = HASHCHAIN_START; - for (;;) - { - qx = cbdata->dirmap[2 * h]; - if (!qx) - return 0; - if (qx == hx) - return cbdata->dirmap[2 * h + 1] == -1 ? 1 : 0; - h = HASHCHAIN_NEXT(h, hh, cbdata->dirmapn); - } -} - -static void -findfileconflicts_cb(void *cbdatav, const char *fn, int fmode, const char *md5) -{ - struct cbdata *cbdata = cbdatav; - int isdir = S_ISDIR(fmode); - char *dp; - Hashval idx, qidx; - Hashmask qx, h, hx, hh, dhx; - - idx = cbdata->idx; - - dp = strrchr(fn, '/'); - if (!dp) - return; - dhx = strnhash(fn, dp + 1 - fn); - if (!dhx) - dhx = 1 + dp + 1 - fn; -#if 1 - if (!isindirmap(cbdata, dhx)) - return; -#endif - - hx = strhash_cont(dp + 1, dhx); - if (!hx) - hx = strlen(fn) + 1; - - h = hx & cbdata->cflmapn; - hh = HASHCHAIN_START; - for (;;) - { - qx = cbdata->cflmap[2 * h]; - if (!qx) - break; - if (qx == hx) - break; - h = HASHCHAIN_NEXT(h, hh, cbdata->cflmapn); - } - if (!qx) - { - /* a miss */ - if (!cbdata->create) - return; - cbdata->cflmap[2 * h] = hx; - cbdata->cflmap[2 * h + 1] = (isdir ? ~idx : idx); - cbdata->cflmapused++; - if (cbdata->cflmapused * 2 > cbdata->cflmapn) - cbdata->cflmap = doublehash(cbdata->cflmap, &cbdata->cflmapn); - return; - } - qidx = cbdata->cflmap[2 * h + 1]; - if ((int)qidx < 0) - { - int i; - qidx = ~qidx; - if (isdir) - { - /* delay the conflict */ - queue_push2(&cbdata->lookat_dir, hx, qidx); - queue_push2(&cbdata->lookat_dir, hx, idx); - return; - } - cbdata->cflmap[2 * h + 1] = qidx; - for (i = 0; i < cbdata->lookat_dir.count; i += 2) - if (cbdata->lookat_dir.elements[i] == hx) - queue_push2(&cbdata->lookat, hx, cbdata->lookat_dir.elements[i + 1]); - } - if (qidx == idx) - return; /* no conflicts with ourself, please */ - queue_push2(&cbdata->lookat, hx, qidx); - queue_push2(&cbdata->lookat, hx, idx); -} - -static inline void -addfilesspace(struct cbdata *cbdata, unsigned char *data, int len) -{ - cbdata->filesspace = sat_extend(cbdata->filesspace, cbdata->filesspacen, len, 1, FILESSPACE_BLOCK); - memcpy(cbdata->filesspace + cbdata->filesspacen, data, len); - cbdata->filesspacen += len; -} - -static void -findfileconflicts2_cb(void *cbdatav, const char *fn, int fmode, const char *md5) -{ - struct cbdata *cbdata = cbdatav; - unsigned int hx = strhash(fn); - char md5padded[33]; - - if (!hx) - hx = strlen(fn) + 1; - if (hx != cbdata->hx) - return; - strncpy(md5padded, md5, 32); - md5padded[32] = 0; - // printf("%d, hx %x -> %s %d %s\n", cbdata->idx, hx, fn, fmode, md5); - queue_push(&cbdata->files, cbdata->filesspacen); - addfilesspace(cbdata, (unsigned char *)md5padded, 33); - addfilesspace(cbdata, (unsigned char *)fn, strlen(fn) + 1); -} - -static int cand_sort(const void *ap, const void *bp, void *dp) -{ - const Id *a = ap; - const Id *b = bp; - - unsigned int ax = (unsigned int)a[0]; - unsigned int bx = (unsigned int)b[0]; - if (ax < bx) - return -1; - if (ax > bx) - return 1; - return (a[1] < 0 ? -a[1] : a[1]) - (b[1] < 0 ? -b[1] : b[1]); -} - -static int conflicts_cmp(const void *ap, const void *bp, void *dp) -{ - Pool *pool = dp; - const Id *a = ap; - const Id *b = bp; - if (a[0] != b[0]) - return strcmp(id2str(pool, a[0]), id2str(pool, b[0])); - if (a[1] != b[1]) - return a[1] - b[1]; - if (a[3] != b[3]) - return a[3] - b[3]; - return 0; -} - -int -pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, void *(*handle_cb)(Pool *, Id, void *) , void *handle_cbdata) -{ - int i, j, cflmapn, idxmapset; - unsigned int hx; - struct cbdata cbdata; - unsigned int now, start; - void *handle; - Id p; - - queue_empty(conflicts); - if (!pkgs->count) - return 0; - - now = start = sat_timems(0); - POOL_DEBUG(SAT_DEBUG_STATS, "searching for file conflicts\n"); - POOL_DEBUG(SAT_DEBUG_STATS, "packages: %d, cutoff %d\n", pkgs->count, cutoff); - - memset(&cbdata, 0, sizeof(cbdata)); - cbdata.pool = pool; - queue_init(&cbdata.lookat); - queue_init(&cbdata.lookat_dir); - queue_init(&cbdata.files); - map_init(&cbdata.idxmap, pkgs->count); - - if (cutoff <= 0) - cutoff = pkgs->count; - - /* avarage file list size: 200 files per package */ - /* avarage dir count: 20 dirs per package */ - - /* first pass: scan dirs */ - cflmapn = (cutoff + 3) * 64; - while ((cflmapn & (cflmapn - 1)) != 0) - cflmapn = cflmapn & (cflmapn - 1); - cbdata.dirmap = sat_calloc(cflmapn, 2 * sizeof(Id)); - cbdata.dirmapn = cflmapn - 1; /* make it a mask */ - cbdata.create = 1; - idxmapset = 0; - for (i = 0; i < pkgs->count; i++) - { - p = pkgs->elements[i]; - cbdata.idx = i; - if (i == cutoff) - cbdata.create = 0; - handle = (*handle_cb)(pool, p, handle_cbdata); - if (handle) - rpm_iterate_filelist(handle, RPM_ITERATE_FILELIST_ONLYDIRS, finddirs_cb, &cbdata); - if (MAPTST(&cbdata.idxmap, i)) - idxmapset++; - } - - POOL_DEBUG(SAT_DEBUG_STATS, "dirmap size: %d used %d\n", cbdata.dirmapn + 1, cbdata.dirmapused); - POOL_DEBUG(SAT_DEBUG_STATS, "dirmap memory usage: %d K\n", (cbdata.dirmapn + 1) * 2 * (int)sizeof(Id) / 1024); - POOL_DEBUG(SAT_DEBUG_STATS, "dirmap creation took %d ms\n", sat_timems(now)); - POOL_DEBUG(SAT_DEBUG_STATS, "dir conflicts found: %d, idxmap %d of %d\n", cbdata.dirconflicts, idxmapset, pkgs->count); - - /* second pass: scan files */ - now = sat_timems(0); - cflmapn = (cutoff + 3) * 128; - while ((cflmapn & (cflmapn - 1)) != 0) - cflmapn = cflmapn & (cflmapn - 1); - cbdata.cflmap = sat_calloc(cflmapn, 2 * sizeof(Id)); - cbdata.cflmapn = cflmapn - 1; /* make it a mask */ - cbdata.create = 1; - for (i = 0; i < pkgs->count; i++) - { - if (!MAPTST(&cbdata.idxmap, i)) - continue; - p = pkgs->elements[i]; - cbdata.idx = i; - if (i == cutoff) - cbdata.create = 0; - handle = (*handle_cb)(pool, p, handle_cbdata); - if (handle) - rpm_iterate_filelist(handle, 0, findfileconflicts_cb, &cbdata); - } - - POOL_DEBUG(SAT_DEBUG_STATS, "filemap size: %d used %d\n", cbdata.cflmapn + 1, cbdata.cflmapused); - POOL_DEBUG(SAT_DEBUG_STATS, "filemap memory usage: %d K\n", (cbdata.cflmapn + 1) * 2 * (int)sizeof(Id) / 1024); - POOL_DEBUG(SAT_DEBUG_STATS, "filemap creation took %d ms\n", sat_timems(now)); - - cbdata.dirmap = sat_free(cbdata.dirmap); - cbdata.dirmapn = 0; - cbdata.dirmapused = 0; - cbdata.cflmap = sat_free(cbdata.cflmap); - cbdata.cflmapn = 0; - cbdata.cflmapused = 0; - map_free(&cbdata.idxmap); - - now = sat_timems(0); - POOL_DEBUG(SAT_DEBUG_STATS, "lookat_dir size: %d\n", cbdata.lookat_dir.count); - queue_free(&cbdata.lookat_dir); - sat_sort(cbdata.lookat.elements, cbdata.lookat.count / 2, sizeof(Id) * 2, &cand_sort, pool); - /* unify */ - for (i = j = 0; i < cbdata.lookat.count; i += 2) - { - hx = cbdata.lookat.elements[i]; - Id idx = cbdata.lookat.elements[i + 1]; - if (j && hx == cbdata.lookat.elements[j - 2] && idx == cbdata.lookat.elements[j - 1]) - continue; - cbdata.lookat.elements[j++] = hx; - cbdata.lookat.elements[j++] = idx; - } - POOL_DEBUG(SAT_DEBUG_STATS, "candidates: %d\n", cbdata.lookat.count / 2); - - /* third pass: scan candidates */ - for (i = 0; i < cbdata.lookat.count - 2; i += 2) - { - int pend, ii, jj; - int pidx = cbdata.lookat.elements[i + 1]; - p = pkgs->elements[pidx]; - hx = cbdata.lookat.elements[i]; - if (cbdata.lookat.elements[i + 2] != hx) - continue; /* no package left */ - queue_empty(&cbdata.files); - cbdata.filesspace = sat_free(cbdata.filesspace); - cbdata.filesspacen = 0; - - cbdata.idx = p; - cbdata.hx = cbdata.lookat.elements[i]; - handle = (*handle_cb)(pool, p, handle_cbdata); - if (!handle) - continue; - rpm_iterate_filelist(handle, RPM_ITERATE_FILELIST_WITHMD5, findfileconflicts2_cb, &cbdata); - - pend = cbdata.files.count; - for (j = i + 2; j < cbdata.lookat.count && cbdata.lookat.elements[j] == hx; j++) - { - int qidx = cbdata.lookat.elements[j + 1]; - Id q = pkgs->elements[qidx]; - if (pidx >= cutoff && qidx >= cutoff) - continue; /* no conflicts between packages with idx >= cutoff */ - cbdata.idx = q; - handle = (*handle_cb)(pool, q, handle_cbdata); - if (!handle) - continue; - rpm_iterate_filelist(handle, RPM_ITERATE_FILELIST_WITHMD5, findfileconflicts2_cb, &cbdata); - for (ii = 0; ii < pend; ii++) - for (jj = pend; jj < cbdata.files.count; jj++) - { - if (strcmp((char *)cbdata.filesspace + cbdata.files.elements[ii] + 33, (char *)cbdata.filesspace + cbdata.files.elements[jj] + 33)) - continue; - if (!strcmp((char *)cbdata.filesspace + cbdata.files.elements[ii], (char *)cbdata.filesspace + cbdata.files.elements[jj])) - continue; - queue_push(conflicts, str2id(pool, (char *)cbdata.filesspace + cbdata.files.elements[ii] + 33, 1)); - queue_push(conflicts, p); - queue_push(conflicts, str2id(pool, (char *)cbdata.filesspace + cbdata.files.elements[ii], 1)); - queue_push(conflicts, q); - queue_push(conflicts, str2id(pool, (char *)cbdata.filesspace + cbdata.files.elements[jj], 1)); - } - } - } - cbdata.filesspace = sat_free(cbdata.filesspace); - cbdata.filesspacen = 0; - queue_free(&cbdata.lookat); - queue_free(&cbdata.files); - POOL_DEBUG(SAT_DEBUG_STATS, "candidate check took %d ms\n", sat_timems(now)); - if (conflicts->count > 5) - sat_sort(conflicts->elements, conflicts->count / 5, 5 * sizeof(Id), conflicts_cmp, pool); - (*handle_cb)(pool, 0, handle_cbdata); - POOL_DEBUG(SAT_DEBUG_STATS, "found %d file conflicts\n", conflicts->count / 5); - POOL_DEBUG(SAT_DEBUG_STATS, "file conflict detection took %d ms\n", sat_timems(start)); - return conflicts->count; -} - diff --git a/tools/pool_fileconflicts.h b/tools/pool_fileconflicts.h deleted file mode 100644 index f1c2282..0000000 --- a/tools/pool_fileconflicts.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef POOL_FILECONFLICTS_H -#define POOL_FILECONFLICTS_H - -#include "pool.h" - -extern int pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, void *(*handle_cb)(Pool *, Id, void *) , void *handle_cbdata); - -#endif diff --git a/tools/repo_content.c b/tools/repo_content.c deleted file mode 100644 index 4c71c42..0000000 --- a/tools/repo_content.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * repo_content.c - * - * Parses 'content' file into .solv - * See http://en.opensuse.org/Standards/YaST2_Repository_Metadata/content for a description - * of the syntax - * - * - * Copyright (c) 2007, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -#include <sys/types.h> -#include <limits.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -#include "pool.h" -#include "repo.h" -#include "util.h" -#include "repo_content.h" -#define DISABLE_SPLIT -#include "tools_util.h" - -/* split off a word, return null terminated pointer to it. - * return NULL if there is no word left. */ -static char * -splitword(char **lp) -{ - char *w, *l = *lp; - - while (*l == ' ' || *l == '\t') - l++; - w = *l ? l : 0; - while (*l && *l != ' ' && *l != '\t') - l++; - if (*l) - *l++ = 0; /* terminate word */ - while (*l == ' ' || *l == '\t') - l++; /* convenience: advance to next word */ - *lp = l; - return w; -} - -struct parsedata { - Repo *repo; - char *tmp; - int tmpl; - - const char *tmpvers; - const char *tmprel; -}; - -/* - * dependency relations - */ - -static char *flagtab[] = { - ">", - "=", - ">=", - "<", - "!=", - "<=" -}; - - -/* - * join up to three strings into one - */ - -static char * -join(struct parsedata *pd, const char *s1, const char *s2, const char *s3) -{ - int l = 1; - char *p; - - if (s1) - l += strlen(s1); - if (s2) - l += strlen(s2); - if (s3) - l += strlen(s3); - if (l > pd->tmpl) - { - pd->tmpl = l + 256; - pd->tmp = sat_realloc(pd->tmp, pd->tmpl); - } - p = pd->tmp; - if (s1) - { - strcpy(p, s1); - p += strlen(s1); - } - if (s2) - { - strcpy(p, s2); - p += strlen(s2); - } - if (s3) - { - strcpy(p, s3); - p += strlen(s3); - } - return pd->tmp; -} - - -/* - * add dependency to pool - * OBSOLETES product:SUSE_LINUX product:openSUSE < 11.0 package:openSUSE < 11.0 - */ - -static unsigned int -adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, char *line, Id marker) -{ - char *name; - Id id; - - while ((name = splitword(&line)) != 0) - { - /* Hack, as the content file adds 'package:' for package - dependencies sometimes. */ - if (!strncmp (name, "package:", 8)) - name += 8; - id = str2id(pool, name, 1); - if (*line == '<' || *line == '>' || *line == '=') /* rel follows */ - { - char *rel = splitword(&line); - char *evr = splitword(&line); - int flags; - - if (!rel || !evr) - { - pool_debug(pool, SAT_FATAL, "repo_content: bad relation '%s %s'\n", name, rel); - exit(1); - } - for (flags = 0; flags < 6; flags++) - if (!strcmp(rel, flagtab[flags])) - break; - if (flags == 6) - { - pool_debug(pool, SAT_FATAL, "repo_content: unknown relation '%s'\n", rel); - exit(1); - } - id = rel2id(pool, id, str2id(pool, evr, 1), flags + 1, 1); - } - olddeps = repo_addid_dep(pd->repo, olddeps, id, marker); - } - return olddeps; -} - - -/* - * split value and add to pool - */ - -static void -add_multiple_strings(Repodata *data, Id handle, Id name, char *value) -{ - char *str; - - while ((str = splitword(&value)) != 0) - repodata_add_poolstr_array(data, handle, name, str); -} - -/* - * split value and add to pool - */ - -static void -add_multiple_urls(Repodata *data, Id handle, char *value, Id type) -{ - char *url; - - while ((url = splitword(&value)) != 0) - { - repodata_add_poolstr_array(data, handle, PRODUCT_URL, url); - repodata_add_idarray(data, handle, PRODUCT_URL_TYPE, type); - } -} - - - -/* - * add 'content' to repo - * - */ - -void -repo_add_content(Repo *repo, FILE *fp, int flags) -{ - Pool *pool = repo->pool; - char *line, *linep; - int aline; - Solvable *s; - struct parsedata pd; - Repodata *data; - Id handle = 0; - int contentstyle = 0; - - int i = 0; - - /* architectures - we use the first architecture in BASEARCHS or noarch - for the product. At the end we create (clone) the product - for each one of the remaining architectures - we allow max 4 archs - */ - unsigned int numotherarchs = 0; - Id *otherarchs = 0; - - if (!(flags & REPO_REUSE_REPODATA)) - data = repo_add_repodata(repo, 0); - else - data = repo_last_repodata(repo); - - memset(&pd, 0, sizeof(pd)); - line = sat_malloc(1024); - aline = 1024; - - if (repo->nrepodata) - /* use last repodata */ - data = repo->repodata + repo->nrepodata - 1; - else - data = repo_add_repodata(repo, 0); - - pd.repo = repo; - linep = line; - s = 0; - - for (;;) - { - char *key, *value; - - /* read line into big-enough buffer */ - if (linep - line + 16 > aline) - { - aline = linep - line; - line = sat_realloc(line, aline + 512); - linep = line + aline; - aline += 512; - } - if (!fgets(linep, aline - (linep - line), fp)) - break; - linep += strlen(linep); - if (linep == line || linep[-1] != '\n') - continue; - while ( --linep > line && ( linep[-1] == ' ' || linep[-1] == '\t' ) ) - ; /* skip trailing ws */ - *linep = 0; - linep = line; - - /* expect "key value" lines */ - value = line; - key = splitword(&value); - - if (key) - { -#if 0 - fprintf (stderr, "key %s, value %s\n", key, value); -#endif - -#define istag(x) (!strcmp (key, x)) -#define code10 (contentstyle == 10) -#define code11 (contentstyle == 11) - - if (contentstyle == 0) - { - if (istag ("CONTENTSTYLE")) - { - contentstyle = atoi(value); - continue; - } - else - contentstyle = 10; - } - - if ((code10 && istag ("PRODUCT")) - || (code11 && istag ("NAME"))) - { - if (s && !s->name) - { - /* this solvable was created without seeing a - PRODUCT entry, just set the name and continue */ - s->name = str2id(pool, join(&pd, "product", ":", value), 1); - continue; - } - if (s) - { - /* finish old solvable */ - if (!s->arch) - s->arch = ARCH_NOARCH; - if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) - s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); - if (code10) - s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0); - } - /* create new solvable */ - s = pool_id2solvable(pool, repo_add_solvable(repo)); - repodata_extend(data, s - pool->solvables); - handle = s - pool->solvables; - s->name = str2id(pool, join(&pd, "product", ":", value), 1); - continue; - } - - /* Sometimes PRODUCT/NAME is not the first entry, but we need a solvable - from here on. */ - if (!s) - { - s = pool_id2solvable(pool, repo_add_solvable(repo)); - repodata_extend(data, s - pool->solvables); - handle = s - pool->solvables; - } - - if (istag ("VERSION")) - pd.tmpvers = strdup(value); - else if (istag ("RELEASE")) - pd.tmprel = strdup(value); - else if (code11 && istag ("DISTRIBUTION")) - repo_set_str(repo, s - pool->solvables, SOLVABLE_DISTRIBUTION, value); - else if (istag ("DATADIR")) - repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, value); - else if (istag ("UPDATEURLS")) - add_multiple_urls(data, handle, value, str2id(pool, "update", 1)); - else if (istag ("EXTRAURLS")) - add_multiple_urls(data, handle, value, str2id(pool, "extra", 1)); - else if (istag ("OPTIONALURLS")) - add_multiple_urls(data, handle, value, str2id(pool, "optional", 1)); - else if (istag ("RELNOTESURL")) - add_multiple_urls(data, handle, value, str2id(pool, "releasenotes", 1)); - else if (istag ("SHORTLABEL")) - repo_set_str(repo, s - pool->solvables, PRODUCT_SHORTLABEL, value); - else if (istag ("LABEL")) /* LABEL is the products SUMMARY. */ - repo_set_str(repo, s - pool->solvables, SOLVABLE_SUMMARY, value); - else if (!strncmp (key, "LABEL.", 6)) - repo_set_str(repo, s - pool->solvables, pool_id2langid(pool, SOLVABLE_SUMMARY, key + 6, 1), value); - else if (istag ("FLAGS")) - add_multiple_strings(data, handle, PRODUCT_FLAGS, value); - else if (istag ("VENDOR")) - s->vendor = str2id(pool, value, 1); - else if (istag ("BASEARCHS")) - { - char *arch; - - if ((arch = splitword(&value)) != 0) - { - s->arch = str2id(pool, arch, 1); - while ((arch = splitword(&value)) != 0) - { - otherarchs = sat_extend(otherarchs, numotherarchs, 1, sizeof(Id), 7); - otherarchs[numotherarchs++] = str2id(pool, arch, 1); - } - } - } - - /* - * Every tag below is Code10 only - * - */ - - else if (code10 && istag ("CONTENTSTYLE")) - /* CONTENTSTYLE must be first line */ - pool_debug(pool, SAT_ERROR, "repo_content: 'CONTENTSTYLE' must be first line of 'content'\n"); - else if (code10 && istag ("DISTPRODUCT")) - /* DISTPRODUCT is for registration and Yast, not for the solver. */ - repo_set_str(repo, s - pool->solvables, PRODUCT_DISTPRODUCT, value); - else if (code10 && istag ("DISTVERSION")) - /* DISTVERSION is for registration and Yast, not for the solver. */ - repo_set_str(repo, s - pool->solvables, PRODUCT_DISTVERSION, value); - else if (code10 && istag ("ARCH")) - /* Theoretically we want to have the best arch of the given - modifiers which still is compatible with the system - arch. We don't know the latter here, though. */ - s->arch = ARCH_NOARCH; - else if (code10 && istag ("PREREQUIRES")) - s->requires = adddep(pool, &pd, s->requires, value, SOLVABLE_PREREQMARKER); - else if (code10 && istag ("REQUIRES")) - s->requires = adddep(pool, &pd, s->requires, value, -SOLVABLE_PREREQMARKER); - else if (code10 && istag ("PROVIDES")) - s->provides = adddep(pool, &pd, s->provides, value, 0); - else if (code10 && istag ("CONFLICTS")) - s->conflicts = adddep(pool, &pd, s->conflicts, value, 0); - else if (code10 && istag ("OBSOLETES")) - s->obsoletes = adddep(pool, &pd, s->obsoletes, value, 0); - else if (code10 && istag ("RECOMMENDS")) - s->recommends = adddep(pool, &pd, s->recommends, value, 0); - else if (code10 && istag ("SUGGESTS")) - s->suggests = adddep(pool, &pd, s->suggests, value, 0); - else if (code10 && istag ("SUPPLEMENTS")) - s->supplements = adddep(pool, &pd, s->supplements, value, 0); - else if (code10 && istag ("ENHANCES")) - s->enhances = adddep(pool, &pd, s->enhances, value, 0); - /* FRESHENS doesn't seem to exist. */ - else if (code10 && istag ("TYPE")) - repo_set_str(repo, s - pool->solvables, PRODUCT_TYPE, value); - - /* XXX do something about LINGUAS and ARCH? - * <ma>: Don't think so. zypp does not use or propagate them. - */ -#undef istag - } - else - pool_debug(pool, SAT_ERROR, "repo_content: malformed line: %s\n", line); - } - - if (!s || !s->name) - { - pool_debug(pool, SAT_FATAL, "repo_content: 'content' incomplete, no product solvable created !\n"); - exit(1); - } - - if (pd.tmpvers) - { - if (pd.tmprel) - s->evr = makeevr(pool, join2(pd.tmpvers, "-", pd.tmprel)); - else - s->evr = makeevr(pool, pd.tmpvers); - } - else if (pd.tmprel) - { - s->evr = makeevr(pool, join2("", "-", pd.tmprel)); - } - pd.tmpvers = sat_free((void *)pd.tmpvers); - pd.tmprel = sat_free((void *)pd.tmprel); - - if (!s->arch) - s->arch = ARCH_NOARCH; - if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) - { - s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); - if (code10) - s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0); - } - - /* now for every other arch, clone the product except the architecture */ - for (i = 0; i < numotherarchs; ++i) - { - Solvable *p = pool_id2solvable(pool, repo_add_solvable(repo)); - repodata_extend(data, p - pool->solvables); - p->name = s->name; - p->evr = s->evr; - p->vendor = s->vendor; - p->arch = otherarchs[i]; - - /* self provides */ - if (p->arch != ARCH_SRC && p->arch != ARCH_NOSRC) - p->provides = repo_addid_dep(repo, p->provides, rel2id(pool, p->name, p->evr, REL_EQ, 1), 0); - - /* now merge the attributes */ - repodata_merge_attrs(data, p - pool->solvables, s - pool->solvables); - } - - if (pd.tmp) - sat_free(pd.tmp); - sat_free(line); - sat_free(otherarchs); - if (!(flags & REPO_NO_INTERNALIZE)) - repodata_internalize(data); -} diff --git a/tools/repo_content.h b/tools/repo_content.h deleted file mode 100644 index c2e79bc..0000000 --- a/tools/repo_content.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2007, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -void repo_add_content(Repo *repo, FILE *fp, int flags); diff --git a/tools/repo_deltainfoxml.c b/tools/repo_deltainfoxml.c deleted file mode 100644 index 6bc0cc9..0000000 --- a/tools/repo_deltainfoxml.c +++ /dev/null @@ -1,608 +0,0 @@ -/* - * Copyright (c) 2007, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -#define DO_ARRAY 1 - -#define _GNU_SOURCE -#include <sys/types.h> -#include <limits.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <expat.h> - -#include "pool.h" -#include "repo.h" -#include "repo_updateinfoxml.h" - -#define DISABLE_SPLIT -#include "tools_util.h" - -/* #define DUMPOUT 1 */ - -/* - * <deltainfo> - * <newpackage name="libtool" epoch="0" version="1.5.24" release="6.fc9" arch="i386"> - * <delta oldepoch="0" oldversion="1.5.24" oldrelease="3.fc8"> - * <filename>DRPMS/libtool-1.5.24-3.fc8_1.5.24-6.fc9.i386.drpm</filename> - * <sequence>libtool-1.5.24-3.fc8-d3571f98b048b1a870e40241bb46c67ab4</sequence> - * <size>22452</size> - * <checksum type="sha">8f05394695dee9399c204614e21e5f6848990ab7</checksum> - * </delta> - * <delta oldepoch="0" oldversion="1.5.22" oldrelease="11.fc7"> - * <filename>DRPMS/libtool-1.5.22-11.fc7_1.5.24-6.fc9.i386.drpm</filename> - * <sequence>libtool-1.5.22-11.fc7-e82691677eee1e83b4812572c5c9ce8eb</sequence> - * <size>110362</size> - * <checksum type="sha">326658fee45c0baec1e70231046dbaf560f941ce</checksum> - * </delta> - * </newpackage> - * </deltainfo> - */ - -enum state { - STATE_START, - STATE_NEWPACKAGE, /* 1 */ - STATE_DELTA, /* 2 */ - STATE_FILENAME, /* 3 */ - STATE_SEQUENCE, /* 4 */ - STATE_SIZE, /* 5 */ - STATE_CHECKSUM, /* 6 */ - STATE_LOCATION, /* 7 */ - NUMSTATES -}; - -struct stateswitch { - enum state from; - char *ename; - enum state to; - int docontent; -}; - -/* !! must be sorted by first column !! */ -static struct stateswitch stateswitches[] = { - /* compatibility with old yum-presto */ - { STATE_START, "prestodelta", STATE_START, 0 }, - { STATE_START, "deltainfo", STATE_START, 0 }, - { STATE_START, "newpackage", STATE_NEWPACKAGE, 0 }, - { STATE_NEWPACKAGE, "delta", STATE_DELTA, 0 }, - /* compatibility with yum-presto */ - { STATE_DELTA, "filename", STATE_FILENAME, 1 }, - { STATE_DELTA, "location", STATE_LOCATION, 0 }, - { STATE_DELTA, "sequence", STATE_SEQUENCE, 1 }, - { STATE_DELTA, "size", STATE_SIZE, 1 }, - { STATE_DELTA, "checksum", STATE_CHECKSUM, 1 }, - { NUMSTATES } -}; - -/* Cumulated info about the current deltarpm or patchrpm */ -struct deltarpm { - Id locdir; - Id locname; - Id locevr; - Id locsuffix; - unsigned buildtime; - unsigned downloadsize, archivesize; - char *filechecksum; - int filechecksumtype; - /* Baseversion. deltarpm only has one. */ - Id *bevr; - unsigned nbevr; - Id seqname; - Id seqevr; - char *seqnum; -}; - -struct parsedata { - int depth; - enum state state; - int statedepth; - char *content; - int lcontent; - int acontent; - int docontent; - Pool *pool; - Repo *repo; - Repodata *data; - - struct stateswitch *swtab[NUMSTATES]; - enum state sbtab[NUMSTATES]; - char *tempstr; - int ltemp; - int atemp; - struct deltarpm delta; - Id newpkgevr; - Id newpkgname; - Id newpkgarch; - - Id *handles; - int nhandles; -}; - -/* - * find attribute - */ - -static const char * -find_attr(const char *txt, const char **atts) -{ - for (; *atts; atts += 2) - { - if (!strcmp(*atts, txt)) - return atts[1]; - } - return 0; -} - - -/* - * create evr (as Id) from 'epoch', 'version' and 'release' attributes - */ - -static Id -makeevr_atts(Pool *pool, struct parsedata *pd, const char **atts) -{ - const char *e, *v, *r, *v2; - char *c; - int l; - - e = v = r = 0; - for (; *atts; atts += 2) - { - if (!strcmp(*atts, "oldepoch")) - e = atts[1]; - else if (!strcmp(*atts, "epoch")) - e = atts[1]; - else if (!strcmp(*atts, "version")) - v = atts[1]; - else if (!strcmp(*atts, "oldversion")) - v = atts[1]; - else if (!strcmp(*atts, "release")) - r = atts[1]; - else if (!strcmp(*atts, "oldrelease")) - r = atts[1]; - } - if (e && !strcmp(e, "0")) - e = 0; - if (v && !e) - { - for (v2 = v; *v2 >= '0' && *v2 <= '9'; v2++) - ; - if (v2 > v && *v2 == ':') - e = "0"; - } - l = 1; - if (e) - l += strlen(e) + 1; - if (v) - l += strlen(v); - if (r) - l += strlen(r) + 1; - if (l > pd->acontent) - { - pd->content = sat_realloc(pd->content, l + 256); - pd->acontent = l + 256; - } - c = pd->content; - if (e) - { - strcpy(c, e); - c += strlen(c); - *c++ = ':'; - } - if (v) - { - strcpy(c, v); - c += strlen(c); - } - if (r) - { - *c++ = '-'; - strcpy(c, r); - c += strlen(c); - } - *c = 0; - if (!*pd->content) - return 0; -#if 0 - fprintf(stderr, "evr: %s\n", pd->content); -#endif - return str2id(pool, pd->content, 1); -} - -static void parse_delta_location( struct parsedata *pd, - const char* str ) -{ - Pool *pool = pd->pool; - if (str) - { - /* Separate the filename into its different parts. - rpm/x86_64/alsa-1.0.14-31_31.2.x86_64.delta.rpm - --> dir = rpm/x86_64 - name = alsa - evr = 1.0.14-31_31.2 - suffix = x86_64.delta.rpm. */ - char *real_str = strdup(str); - char *s = real_str; - char *s1, *s2; - s1 = strrchr (s, '/'); - if (s1) - { - pd->delta.locdir = strn2id(pool, s, s1 - s, 1); - s = s1 + 1; - } - /* Guess suffix. */ - s1 = strrchr (s, '.'); - if (s1) - { - for (s2 = s1 - 1; s2 > s; s2--) - if (*s2 == '.') - break; - if (!strcmp (s2, ".delta.rpm") || !strcmp (s2, ".patch.rpm")) - { - s1 = s2; - /* We accept one more item as suffix. */ - for (s2 = s1 - 1; s2 > s; s2--) - if (*s2 == '.') - break; - s1 = s2; - } - if (*s1 == '.') - *s1++ = 0; - pd->delta.locsuffix = str2id(pool, s1, 1); - } - /* Last '-'. */ - s1 = strrchr (s, '-'); - if (s1) - { - /* Second to last '-'. */ - for (s2 = s1 - 1; s2 > s; s2--) - if (*s2 == '-') - break; - } - else - s2 = 0; - if (s2 > s && *s2 == '-') - { - *s2++ = 0; - pd->delta.locevr = str2id(pool, s2, 1); - } - pd->delta.locname = str2id(pool, s, 1); - free(real_str); - } -} - -static void XMLCALL -startElement(void *userData, const char *name, const char **atts) -{ - struct parsedata *pd = userData; - Pool *pool = pd->pool; - struct stateswitch *sw; - const char *str; - -#if 0 - fprintf(stderr, "start: [%d]%s\n", pd->state, name); -#endif - if (pd->depth != pd->statedepth) - { - pd->depth++; - return; - } - - pd->depth++; - if (!pd->swtab[pd->state]) - return; - for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) /* find name in statetable */ - if (!strcmp(sw->ename, name)) - break; - if (sw->from != pd->state) - { -#if 0 - fprintf(stderr, "into unknown: [%d]%s (from: %d)\n", sw->to, name, sw->from); - exit( 1 ); -#endif - return; - } - pd->state = sw->to; - pd->docontent = sw->docontent; - pd->statedepth = pd->depth; - pd->lcontent = 0; - *pd->content = 0; - - switch(pd->state) - { - case STATE_START: - break; - case STATE_NEWPACKAGE: - if ((str = find_attr("name", atts)) != 0) - { - pd->newpkgname = str2id(pool, str, 1); - } - pd->newpkgevr = makeevr_atts(pool, pd, atts); - if ((str = find_attr("arch", atts)) != 0) - { - pd->newpkgarch = str2id(pool, str, 1); - } - break; - - case STATE_DELTA: - memset(&pd->delta, 0, sizeof(pd->delta)); - *pd->tempstr = 0; - pd->ltemp = 0; - pd->delta.bevr = sat_extend(pd->delta.bevr, pd->delta.nbevr, 1, sizeof(Id), 7); - pd->delta.bevr[pd->delta.nbevr++] = makeevr_atts(pool, pd, atts); - break; - case STATE_FILENAME: - break; - case STATE_LOCATION: - parse_delta_location(pd, find_attr("href", atts)); - break; - case STATE_SIZE: - break; - case STATE_CHECKSUM: - pd->delta.filechecksum = 0; - pd->delta.filechecksumtype = REPOKEY_TYPE_SHA1; - if ((str = find_attr("type", atts)) != 0) - { - if (!strcasecmp(str, "sha")) - pd->delta.filechecksumtype = REPOKEY_TYPE_SHA1; - else if (!strcasecmp(str, "sha256")) - pd->delta.filechecksumtype = REPOKEY_TYPE_SHA256; - else if (!strcasecmp(str, "md5")) - pd->delta.filechecksumtype = REPOKEY_TYPE_MD5; - else - pool_debug(pool, SAT_ERROR, "unknown checksum type: '%s'\n", str); - } - case STATE_SEQUENCE: - break; - default: - break; - } -} - - -static void XMLCALL -endElement(void *userData, const char *name) -{ - struct parsedata *pd = userData; - Pool *pool = pd->pool; - const char *str; - -#if 0 - fprintf(stderr, "end: %s\n", name); -#endif - if (pd->depth != pd->statedepth) - { - pd->depth--; -#if 0 - fprintf(stderr, "back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth); -#endif - return; - } - - pd->depth--; - pd->statedepth--; - switch (pd->state) - { - case STATE_START: - break; - case STATE_NEWPACKAGE: - break; - case STATE_DELTA: - { - /* read all data for a deltarpm. commit into attributes */ - Id handle; - struct deltarpm *d = &pd->delta; -#ifdef DUMPOUT - int i; -#endif - -#ifdef DUMPOUT - - fprintf (stderr, "found deltarpm for %s:\n", id2str(pool, pd->newpkgname)); -#endif - handle = repodata_new_handle(pd->data); - /* we commit all handles later on in one go so that the - * repodata code doesn't need to realloc every time */ - pd->handles = sat_extend(pd->handles, pd->nhandles, 1, sizeof(Id), 63); - pd->handles[pd->nhandles++] = handle; - repodata_set_id(pd->data, handle, DELTA_PACKAGE_NAME, pd->newpkgname); - repodata_set_id(pd->data, handle, DELTA_PACKAGE_EVR, pd->newpkgevr); - repodata_set_id(pd->data, handle, DELTA_PACKAGE_ARCH, pd->newpkgarch); - repodata_set_id(pd->data, handle, DELTA_LOCATION_NAME, d->locname); - repodata_set_id(pd->data, handle, DELTA_LOCATION_DIR, d->locdir); - repodata_set_id(pd->data, handle, DELTA_LOCATION_EVR, d->locevr); - repodata_set_id(pd->data, handle, DELTA_LOCATION_SUFFIX, d->locsuffix); - if (d->downloadsize) - repodata_set_num(pd->data, handle, DELTA_DOWNLOADSIZE, (d->downloadsize + 1023) / 1024); - if (d->filechecksum) - repodata_set_checksum(pd->data, handle, DELTA_CHECKSUM, d->filechecksumtype, d->filechecksum); -#ifdef DUMPOUT - fprintf (stderr, " loc: %s %s %s %s\n", id2str(pool, d->locdir), - id2str(pool, d->locname), id2str(pool, d->locevr), - id2str(pool, d->locsuffix)); - fprintf (stderr, " size: %d down\n", d->downloadsize); - fprintf (stderr, " chek: %s\n", d->filechecksum); -#endif - - if (d->seqnum) - { -#ifdef DUMPOUT - fprintf (stderr, " base: %s\n", - id2str(pool, d->bevr[0])); - fprintf (stderr, " seq: %s\n", - id2str(pool, d->seqname)); - fprintf (stderr, " %s\n", - id2str(pool, d->seqevr)); - fprintf (stderr, " %s\n", - d->seqnum); -#endif - repodata_set_id(pd->data, handle, DELTA_BASE_EVR, d->bevr[0]); - repodata_set_id(pd->data, handle, DELTA_SEQ_NAME, d->seqname); - repodata_set_id(pd->data, handle, DELTA_SEQ_EVR, d->seqevr); - /* should store as binary blob! */ - repodata_set_str(pd->data, handle, DELTA_SEQ_NUM, d->seqnum); - -#ifdef DUMPOUT - fprintf(stderr, "OK\n"); -#endif - -#ifdef DUMPOUT - if (d->seqevr != d->bevr[0]) - fprintf (stderr, "XXXXX evr\n"); - /* Name of package ("xxxx") should match the sequence info - name. */ - if (strcmp(id2str(pool, d->seqname), id2str(pool, pd->newpkgname))) - fprintf (stderr, "XXXXX name\n"); -#endif - } - else - { - -#ifdef DUMPOUT - fprintf (stderr, " base:"); - for (i = 0; i < d->nbevr; i++) - fprintf (stderr, " %s", id2str(pool, d->bevr[i])); - fprintf (stderr, "\n"); -#endif - } - - } - pd->delta.filechecksum = sat_free(pd->delta.filechecksum); - pd->delta.bevr = sat_free(pd->delta.bevr); - pd->delta.nbevr = 0; - pd->delta.seqnum = sat_free(pd->delta.seqnum); - break; - case STATE_FILENAME: - parse_delta_location(pd, pd->content); - break; - case STATE_CHECKSUM: - pd->delta.filechecksum = strdup(pd->content); - break; - case STATE_SIZE: - pd->delta.downloadsize = atoi(pd->content); - break; - case STATE_SEQUENCE: - if ((str = pd->content)) - { - const char *s1, *s2; - s1 = strrchr(str, '-'); - if (s1) - { - for (s2 = s1 - 1; s2 > str; s2--) - if (*s2 == '-') - break; - if (*s2 == '-') - { - for (s2 = s2 - 1; s2 > str; s2--) - if (*s2 == '-') - break; - if (*s2 == '-') - { - pd->delta.seqevr = strn2id(pool, s2 + 1, s1 - s2 - 1, 1); - pd->delta.seqname = strn2id(pool, str, s2 - str, 1); - str = s1 + 1; - } - } - } - pd->delta.seqnum = strdup(str); - } - default: - break; - } - - pd->state = pd->sbtab[pd->state]; - pd->docontent = 0; -} - - -static void XMLCALL -characterData(void *userData, const XML_Char *s, int len) -{ - struct parsedata *pd = userData; - int l; - char *c; - if (!pd->docontent) - return; - l = pd->lcontent + len + 1; - if (l > pd->acontent) - { - pd->content = sat_realloc(pd->content, l + 256); - pd->acontent = l + 256; - } - c = pd->content + pd->lcontent; - pd->lcontent += len; - while (len-- > 0) - *c++ = *s++; - *c = 0; -} - -#define BUFF_SIZE 8192 - -void -repo_add_deltainfoxml(Repo *repo, FILE *fp, int flags) -{ - Pool *pool = repo->pool; - struct parsedata pd; - char buf[BUFF_SIZE]; - int i, l; - struct stateswitch *sw; - Repodata *data; - - if (!(flags & REPO_REUSE_REPODATA)) - data = repo_add_repodata(repo, 0); - else - data = repo_last_repodata(repo); - - memset(&pd, 0, sizeof(pd)); - for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++) - { - if (!pd.swtab[sw->from]) - pd.swtab[sw->from] = sw; - pd.sbtab[sw->to] = sw->from; - } - pd.pool = pool; - pd.repo = repo; - pd.data = data; - - pd.content = sat_malloc(256); - pd.acontent = 256; - pd.lcontent = 0; - pd.tempstr = malloc(256); - pd.atemp = 256; - pd.ltemp = 0; - - XML_Parser parser = XML_ParserCreate(NULL); - XML_SetUserData(parser, &pd); - XML_SetElementHandler(parser, startElement, endElement); - XML_SetCharacterDataHandler(parser, characterData); - for (;;) - { - l = fread(buf, 1, sizeof(buf), fp); - if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR) - { - pool_debug(pool, SAT_FATAL, "repo_updateinfoxml: %s at line %u:%u\n", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser)); - exit(1); - } - if (l == 0) - break; - } - XML_ParserFree(parser); - sat_free(pd.content); - sat_free(pd.tempstr); - join_freemem(); - - /* now commit all handles */ - for (i = 0; i < pd.nhandles; i++) - repodata_add_flexarray(pd.data, SOLVID_META, REPOSITORY_DELTAINFO, pd.handles[i]); - sat_free(pd.handles); - - if (!(flags & REPO_NO_INTERNALIZE)) - repodata_internalize(data); -} - -/* EOF */ diff --git a/tools/repo_deltainfoxml.h b/tools/repo_deltainfoxml.h deleted file mode 100644 index 6621565..0000000 --- a/tools/repo_deltainfoxml.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2007, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -void repo_add_deltainfoxml(Repo *repo, FILE *fp, int flags); diff --git a/tools/repo_products.c b/tools/repo_products.c deleted file mode 100644 index 5cdcc19..0000000 --- a/tools/repo_products.c +++ /dev/null @@ -1,556 +0,0 @@ -/* - * repo_products.c - * - * Parses all files below 'proddir' - * See http://en.opensuse.org/Product_Management/Code11 - * - * - * Copyright (c) 2008, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <limits.h> -#include <fcntl.h> -#include <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <dirent.h> -#include <expat.h> - -#include "pool.h" -#include "repo.h" -#include "util.h" -#define DISABLE_SPLIT -#include "tools_util.h" -#include "repo_content.h" -#include "repo_zyppdb.h" -#include "repo_releasefile_products.h" - - -//#define DUMPOUT 0 - -enum state { - STATE_START, // 0 - STATE_PRODUCT, // 1 - STATE_VENDOR, // 2 - STATE_NAME, // 3 - STATE_VERSION, // 4 - STATE_RELEASE, // 5 - STATE_ARCH, // 6 - STATE_SUMMARY, // 7 - STATE_DESCRIPTION, // 8 - STATE_UPDATEREPOKEY, // 9 should go away - STATE_CPEID, // 9 - STATE_URLS, // 10 - STATE_URL, // 11 - STATE_RUNTIMECONFIG, // 12 - STATE_LINGUAS, // 13 - STATE_LANG, // 14 - STATE_REGISTER, // 15 - STATE_TARGET, // 16 - STATE_REGRELEASE, // 18 - STATE_PRODUCTLINE, // 19 - NUMSTATES // 0 -}; - -struct stateswitch { - enum state from; - char *ename; - enum state to; - int docontent; -}; - -/* !! must be sorted by first column !! */ -static struct stateswitch stateswitches[] = { - { STATE_START, "product", STATE_PRODUCT, 0 }, - { STATE_PRODUCT, "vendor", STATE_VENDOR, 1 }, - { STATE_PRODUCT, "name", STATE_NAME, 1 }, - { STATE_PRODUCT, "version", STATE_VERSION, 1 }, - { STATE_PRODUCT, "release", STATE_RELEASE, 1 }, - { STATE_PRODUCT, "arch", STATE_ARCH, 1 }, - { STATE_PRODUCT, "productline", STATE_PRODUCTLINE, 1 }, - { STATE_PRODUCT, "summary", STATE_SUMMARY, 1 }, - { STATE_PRODUCT, "description", STATE_DESCRIPTION, 1 }, - { STATE_PRODUCT, "register", STATE_REGISTER, 0 }, - { STATE_PRODUCT, "urls", STATE_URLS, 0 }, - { STATE_PRODUCT, "runtimeconfig", STATE_RUNTIMECONFIG, 0 }, - { STATE_PRODUCT, "linguas", STATE_LINGUAS, 0 }, - { STATE_PRODUCT, "updaterepokey", STATE_UPDATEREPOKEY, 1 }, - { STATE_PRODUCT, "cpeid", STATE_CPEID, 1 }, - { STATE_URLS, "url", STATE_URL, 1 }, - { STATE_LINGUAS, "lang", STATE_LANG, 0 }, - { STATE_REGISTER, "target", STATE_TARGET, 1 }, - { STATE_REGISTER, "release", STATE_REGRELEASE, 1 }, - { NUMSTATES } -}; - -struct parsedata { - const char *filename; - const char *basename; - int depth; - enum state state; - int statedepth; - char *content; - int lcontent; - int acontent; - int docontent; - Pool *pool; - Repo *repo; - Repodata *data; - - struct stateswitch *swtab[NUMSTATES]; - enum state sbtab[NUMSTATES]; - - const char *tmplang; - - const char *tmpvers; - const char *tmprel; - const char *tmpurltype; - - unsigned int ctime; - - Solvable *solvable; - Id handle; - - ino_t baseproduct; - ino_t currentproduct; - int productscheme; - - Id langcache[ID_NUM_INTERNAL]; -}; - - -/* - * find_attr - * find value for xml attribute - * I: txt, name of attribute - * I: atts, list of key/value attributes - * I: dup, strdup it - * O: pointer to value of matching key, or NULL - * - */ - -static inline const char * -find_attr(const char *txt, const char **atts, int dup) -{ - for (; *atts; atts += 2) - { - if (!strcmp(*atts, txt)) - return dup ? strdup(atts[1]) : atts[1]; - } - return 0; -} - - -/* - * create localized tag - */ - -static Id -langtag(struct parsedata *pd, Id tag, const char *language) -{ - if (language && !language[0]) - language = 0; - if (!language || tag >= ID_NUM_INTERNAL) - return pool_id2langid(pd->repo->pool, tag, language, 1); - if (!pd->langcache[tag]) - pd->langcache[tag] = pool_id2langid(pd->repo->pool, tag, language, 1); - return pd->langcache[tag]; -} - - -/* - * XML callback: startElement - */ - -static void XMLCALL -startElement(void *userData, const char *name, const char **atts) -{ - struct parsedata *pd = userData; - Pool *pool = pd->pool; - Solvable *s = pd->solvable; - struct stateswitch *sw; - -#if 0 - fprintf(stderr, "start: [%d]%s\n", pd->state, name); -#endif - if (pd->depth != pd->statedepth) - { - pd->depth++; - return; - } - - pd->depth++; - if (!pd->swtab[pd->state]) /* no statetable -> no substates */ - { -#if 0 - fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state); -#endif - return; - } - for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) /* find name in statetable */ - if (!strcmp(sw->ename, name)) - break; - - if (sw->from != pd->state) - { -#if 0 - fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state); -#endif - return; - } - pd->state = sw->to; - pd->docontent = sw->docontent; - pd->statedepth = pd->depth; - pd->lcontent = 0; - *pd->content = 0; - - switch(pd->state) - { - case STATE_PRODUCT: - /* parse 'schemeversion' and store in global variable */ - { - const char * scheme = find_attr("schemeversion", atts, 0); - pd->productscheme = (scheme && *scheme) ? atoi(scheme) : -1; - } - if (!s) - { - s = pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo)); - pd->handle = s - pool->solvables; - } - break; - - /* <summary lang="xy">... */ - case STATE_SUMMARY: - pd->tmplang = find_attr("lang", atts, 1); - break; - case STATE_DESCRIPTION: - pd->tmplang = find_attr("lang", atts, 1); - break; - case STATE_URL: - pd->tmpurltype = find_attr("name", atts, 1); - break; - default: - break; - } -} - - -static void XMLCALL -endElement(void *userData, const char *name) -{ - struct parsedata *pd = userData; - Solvable *s = pd->solvable; - -#if 0 - fprintf(stderr, "end: [%d]%s\n", pd->state, name); -#endif - if (pd->depth != pd->statedepth) - { - pd->depth--; -#if 0 - fprintf(stderr, "back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth); -#endif - return; - } - - pd->depth--; - pd->statedepth--; - - switch (pd->state) - { - case STATE_PRODUCT: - /* product done, finish solvable */ - if (pd->ctime) - repodata_set_num(pd->data, pd->handle, SOLVABLE_INSTALLTIME, pd->ctime); - - if (pd->basename) - repodata_set_str(pd->data, pd->handle, PRODUCT_REFERENCEFILE, pd->basename); - - /* this is where <productsdir>/baseproduct points to */ - if (pd->currentproduct == pd->baseproduct) - repodata_set_str(pd->data, pd->handle, PRODUCT_TYPE, "base"); - - if (pd->tmprel) - { - if (pd->tmpvers) - s->evr = makeevr(pd->pool, join2(pd->tmpvers, "-", pd->tmprel)); - else - { - fprintf(stderr, "Seen <release> but no <version>\n"); - } - } - else if (pd->tmpvers) - s->evr = makeevr(pd->pool, pd->tmpvers); /* just version, no release */ - pd->tmpvers = sat_free((void *)pd->tmpvers); - pd->tmprel = sat_free((void *)pd->tmprel); - if (!s->arch) - s->arch = ARCH_NOARCH; - if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) - s->provides = repo_addid_dep(pd->repo, s->provides, rel2id(pd->pool, s->name, s->evr, REL_EQ, 1), 0); - pd->solvable = 0; - break; - case STATE_VENDOR: - s->vendor = str2id(pd->pool, pd->content, 1); - break; - case STATE_NAME: - s->name = str2id(pd->pool, join2("product", ":", pd->content), 1); - break; - case STATE_VERSION: - pd->tmpvers = strdup(pd->content); - break; - case STATE_RELEASE: - pd->tmprel = strdup(pd->content); - break; - case STATE_ARCH: - s->arch = str2id(pd->pool, pd->content, 1); - break; - case STATE_PRODUCTLINE: - repodata_set_str(pd->data, pd->handle, PRODUCT_PRODUCTLINE, pd->content); - break; - case STATE_UPDATEREPOKEY: - /** obsolete **/ - break; - case STATE_SUMMARY: - repodata_set_str(pd->data, pd->handle, langtag(pd, SOLVABLE_SUMMARY, pd->tmplang), pd->content); - pd->tmplang = sat_free((void *)pd->tmplang); - break; - case STATE_DESCRIPTION: - repodata_set_str(pd->data, pd->handle, langtag(pd, SOLVABLE_DESCRIPTION, pd->tmplang), pd->content ); - pd->tmplang = sat_free((void *)pd->tmplang); - break; - case STATE_URL: - if (pd->tmpurltype) - { - repodata_add_poolstr_array(pd->data, pd->handle, PRODUCT_URL, pd->content); - repodata_add_idarray(pd->data, pd->handle, PRODUCT_URL_TYPE, str2id(pd->pool, pd->tmpurltype, 1)); - } - pd->tmpurltype = sat_free((void *)pd->tmpurltype); - break; - case STATE_TARGET: - repodata_set_str(pd->data, pd->handle, PRODUCT_REGISTER_TARGET, pd->content); - break; - case STATE_REGRELEASE: - repodata_set_str(pd->data, pd->handle, PRODUCT_REGISTER_RELEASE, pd->content); - break; - case STATE_CPEID: - if (pd->content) - repodata_set_str(pd->data, pd->handle, SOLVABLE_CPE_ID, pd->content); - default: - break; - } - - pd->state = pd->sbtab[pd->state]; - pd->docontent = 0; - -#if 0 - fprintf(stderr, "end: [%s] -> %d\n", name, pd->state); -#endif -} - - -static void XMLCALL -characterData(void *userData, const XML_Char *s, int len) -{ - struct parsedata *pd = userData; - int l; - char *c; - if (!pd->docontent) - return; - l = pd->lcontent + len + 1; - if (l > pd->acontent) - { - pd->content = sat_realloc(pd->content, l + 256); - pd->acontent = l + 256; - } - c = pd->content + pd->lcontent; - pd->lcontent += len; - while (len-- > 0) - *c++ = *s++; - *c = 0; -} - -#define BUFF_SIZE 8192 - - -/* - * add single product to repo - * - */ - -static void -add_code11_product(struct parsedata *pd, FILE *fp) -{ - char buf[BUFF_SIZE]; - int l; - struct stat st; - - if (!fstat(fileno(fp), &st)) - { - pd->currentproduct = st.st_ino; - pd->ctime = (unsigned int)st.st_ctime; - } - else - { - pd->currentproduct = pd->baseproduct + 1; /* make it != baseproduct if stat fails */ - perror("fstat"); - pd->ctime = 0; - } - - XML_Parser parser = XML_ParserCreate(NULL); - XML_SetUserData(parser, pd); - XML_SetElementHandler(parser, startElement, endElement); - XML_SetCharacterDataHandler(parser, characterData); - - for (;;) - { - l = fread(buf, 1, sizeof(buf), fp); - if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR) - { - pool_debug(pd->pool, SAT_ERROR, "%s: %s at line %u:%u\n", pd->filename, XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser)); - pool_debug(pd->pool, SAT_ERROR, "skipping this product\n"); - XML_ParserFree(parser); - return; - } - if (l == 0) - break; - } - XML_ParserFree(parser); -} - - -void -repo_add_code11_products(Repo *repo, const char *dirpath, int flags) -{ - Repodata *data; - struct parsedata pd; - struct stateswitch *sw; - DIR *dir; - int i; - - if (!(flags & REPO_REUSE_REPODATA)) - data = repo_add_repodata(repo, 0); - else - data = repo_last_repodata(repo); - - memset(&pd, 0, sizeof(pd)); - pd.repo = repo; - pd.pool = repo->pool; - pd.data = data; - - pd.content = sat_malloc(256); - pd.acontent = 256; - - for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++) - { - if (!pd.swtab[sw->from]) - pd.swtab[sw->from] = sw; - pd.sbtab[sw->to] = sw->from; - } - - dir = opendir(dirpath); - if (dir) - { - struct dirent *entry; - struct stat st; - char *fullpath; - - /* check for <productsdir>/baseproduct on code11 and remember its target inode */ - if (stat(join2(dirpath, "/", "baseproduct"), &st) == 0) /* follow symlink */ - pd.baseproduct = st.st_ino; - else - pd.baseproduct = 0; - - while ((entry = readdir(dir))) - { - int len = strlen(entry->d_name); - if (len <= 5 || strcmp(entry->d_name + len - 5, ".prod") != 0) - continue; - fullpath = join2(dirpath, "/", entry->d_name); - FILE *fp = fopen(fullpath, "r"); - if (!fp) - { - perror(fullpath); - continue; - } - pd.filename = fullpath; - pd.basename = entry->d_name; - add_code11_product(&pd, fp); - fclose(fp); - } - closedir(dir); - } - sat_free((void *)pd.tmplang); - sat_free(pd.content); - join_freemem(); - - if (!(flags & REPO_NO_INTERNALIZE)) - repodata_internalize(data); -} - - -/******************************************************************************************/ - - -/* - * read all installed products - * - * try proddir (reading all .xml files from this directory) first - * if not available, assume non-code11 layout and parse /etc/xyz-release - * - * parse each one as a product - */ - -/* Oh joy! Three parsers for the price of one! */ - -void -repo_add_products(Repo *repo, const char *proddir, const char *root, int flags) -{ - const char *fullpath; - DIR *dir; - - dir = opendir(proddir); - if (dir) - { - /* assume code11 stype products */ - closedir(dir); - repo_add_code11_products(repo, proddir, flags); - return; - } - - /* code11 didn't work, try old zyppdb */ - fullpath = root ? join2(root, "", "/var/lib/zypp/db/products") : "/var/lib/zypp/db/products"; - dir = opendir(fullpath); - if (dir) - { - closedir(dir); - /* assume code10 style products */ - repo_add_zyppdb_products(repo, fullpath, flags); - join_freemem(); - return; - } - - /* code11 didn't work, try -release files parsing */ - fullpath = root ? join2(root, "", "/etc") : "/etc"; - dir = opendir(fullpath); - if (dir) - { - closedir(dir); - repo_add_releasefile_products(repo, fullpath, flags); - join_freemem(); - return; - } - - /* no luck. print an error message in case the root argument is wrong */ - perror(fullpath); - join_freemem(); -} - -/* EOF */ diff --git a/tools/repo_products.h b/tools/repo_products.h deleted file mode 100644 index 6f4ce85..0000000 --- a/tools/repo_products.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright (c) 2007-2009, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -void repo_add_code11_products(Repo *repo, const char *dirpath, int flags); -void repo_add_products(Repo *repo, const char *proddir, const char *root, int flags); diff --git a/tools/repo_releasefile_products.c b/tools/repo_releasefile_products.c deleted file mode 100644 index 2413d20..0000000 --- a/tools/repo_releasefile_products.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * repo_products.c - * - * Parses all files below 'proddir' - * See http://en.opensuse.org/Product_Management/Code11 - * - * - * Copyright (c) 2008, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -#include <sys/types.h> -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <dirent.h> -#include <ctype.h> - -#include "pool.h" -#include "repo.h" -#include "util.h" -#define DISABLE_SPLIT -#include "tools_util.h" -#include "repo_releasefile_products.h" - -#define BUFF_SIZE 8192 - -static void -add_releasefile_product(Repo *repo, FILE *fp) -{ - Pool *pool = repo->pool; - char buf[BUFF_SIZE]; - Id name = 0; - Id arch = 0; - Id version = 0; - int lnum = 0; /* line number */ - char *ptr, *ptr1; - - /* parse /etc/<xyz>-release file */ - while (fgets(buf, sizeof(buf), fp)) - { - /* remove trailing \n */ - int l = strlen(buf); - if (l && buf[l - 1] == '\n') - buf[--l] = 0; - ++lnum; - - if (lnum == 1) - { - /* 1st line, <name> [(<arch>)] */ - ptr = strchr(buf, '('); - if (ptr) - { - ptr1 = ptr - 1; - *ptr++ = 0; - } - else - ptr1 = buf + l - 1; - - /* track back until non-blank, non-digit */ - while (ptr1 > buf - && (*ptr1 == ' ' || isdigit(*ptr1) || *ptr1 == '.')) - --ptr1; - *(++ptr1) = 0; - name = str2id(pool, join2("product", ":", buf), 1); - - if (ptr) - { - /* have arch */ - char *ptr1 = strchr(ptr, ')'); - if (ptr1) - { - *ptr1 = 0; - /* downcase arch */ - ptr1 = ptr; - while (*ptr1) - { - if (isupper(*ptr1)) - *ptr1 = tolower(*ptr1); - ++ptr1; - } - arch = str2id(pool, ptr, 1); - } - } - } - else if (strncmp(buf, "VERSION", 7) == 0) - { - ptr = strchr(buf + 7, '='); - if (ptr) - { - while (*++ptr == ' ') - ; - version = makeevr(pool, ptr); - } - } - } - if (name) - { - Solvable *s = pool_id2solvable(pool, repo_add_solvable(repo)); - s->name = name; - if (version) - s->evr = version; - if (arch) - s->arch = arch; - if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) - s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); - } -} - - -void -repo_add_releasefile_products(Repo *repo, const char *dirpath, int flags) -{ - DIR *dir; - struct dirent *entry; - FILE *fp; - char *fullpath; - - dir = opendir(dirpath); - if (!dir) - return; - - while ((entry = readdir(dir))) - { - int len = strlen(entry->d_name); - if (len > 8 && !strcmp(entry->d_name + len - 8, "-release")) - { - /* skip /etc/lsb-release, thats not a product per-se */ - if (strcmp(entry->d_name, "lsb-release") == 0) - continue; - fullpath = join2(dirpath, "/", entry->d_name); - if ((fp = fopen(fullpath, "r")) == 0) - { - perror(fullpath); - continue; - } - add_releasefile_product(repo, fp); - } - } - closedir(dir); - join_freemem(); - - if (!(flags & REPO_NO_INTERNALIZE)) - { - if (!(flags & REPO_REUSE_REPODATA)) - { - Repodata *data = repo_add_repodata(repo, 0); - repodata_internalize(data); - } - } -} - diff --git a/tools/repo_releasefile_products.h b/tools/repo_releasefile_products.h deleted file mode 100644 index 34311ac..0000000 --- a/tools/repo_releasefile_products.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2007, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -void repo_add_releasefile_products(Repo *repo, const char *dirpath, int flags); diff --git a/tools/repo_repomdxml.c b/tools/repo_repomdxml.c deleted file mode 100644 index c6a1ae2..0000000 --- a/tools/repo_repomdxml.c +++ /dev/null @@ -1,456 +0,0 @@ -/* - * Copyright (c) 2007, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -#define DO_ARRAY 1 - -#define _GNU_SOURCE -#include <sys/types.h> -#include <limits.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <expat.h> - -#include "pool.h" -#include "repo.h" -#include "repo_updateinfoxml.h" - -//#define DUMPOUT 0 - -/* -<repomd> - - <!-- these tags are available in create repo > 0.9.6 --> - <revision>timestamp_or_arbitrary_user_supplied_string</revision> - <tags> - <content>opensuse</content> - <content>i386</content> - <content>other string</content> - <distro cpeid="cpe://o:opensuse_project:opensuse:11">openSUSE 11.0</distro> - </tags> - <!-- end --> - - <data type="primary"> - <location href="repodata/primary.xml.gz"/> - <checksum type="sha">e9162516fa25fec8d60caaf4682d2e49967786cc</checksum> - <timestamp>1215708444</timestamp> - <open-checksum type="sha">c796c48184cd5abc260e4ba929bdf01be14778a7</open-checksum> - </data> - <data type="filelists"> - <location href="repodata/filelists.xml.gz"/> - <checksum type="sha">1c638295c49e9707c22810004ebb0799791fcf45</checksum> - <timestamp>1215708445</timestamp> - <open-checksum type="sha">54a40d5db3df0813b8acbe58cea616987eb9dc16</open-checksum> - </data> - <data type="other"> - <location href="repodata/other.xml.gz"/> - <checksum type="sha">a81ef39eaa70e56048f8351055119d8c82af2491</checksum> - <timestamp>1215708447</timestamp> - <open-checksum type="sha">4d1ee867c8864025575a2fb8fde3b85371d51978</open-checksum> - </data> - <data type="deltainfo"> - <location href="repodata/deltainfo.xml.gz"/> - <checksum type="sha">5880cfa5187026a24a552d3c0650904a44908c28</checksum> - <timestamp>1215708447</timestamp> - <open-checksum type="sha">7c964a2c3b17df5bfdd962c3be952c9ca6978d8b</open-checksum> - </data> - <data type="updateinfo"> - <location href="repodata/updateinfo.xml.gz"/> - <checksum type="sha">4097f7e25c7bb0770ae31b2471a9c8c077ee904b</checksum> - <timestamp>1215708447</timestamp> - <open-checksum type="sha">24f8252f3dd041e37e7c3feb2d57e02b4422d316</open-checksum> - </data> - <data type="diskusage"> - <location href="repodata/diskusage.xml.gz"/> - <checksum type="sha">4097f7e25c7bb0770ae31b2471a9c8c077ee904b</checksum> - <timestamp>1215708447</timestamp> - <open-checksum type="sha">24f8252f3dd041e37e7c3feb2d57e02b4422d316</open-checksum> - </data> -</repomd> - -support also extension suseinfo format -<suseinfo> - <expire>timestamp</expire> - <products> - <id>...</id> - </products> - <kewwords> - <k>...</k> - </keywords> -</suseinfo> - -*/ - -enum state { - STATE_START, - /* extension tags */ - STATE_SUSEINFO, - STATE_EXPIRE, - STATE_KEYWORDS, - STATE_KEYWORD, - /* normal repomd.xml */ - STATE_REPOMD, - STATE_REVISION, - STATE_TAGS, - STATE_CONTENT, - STATE_DISTRO, - STATE_UPDATES, - STATE_DATA, - STATE_LOCATION, - STATE_CHECKSUM, - STATE_TIMESTAMP, - STATE_OPENCHECKSUM, - NUMSTATES -}; - -struct stateswitch { - enum state from; - char *ename; - enum state to; - int docontent; -}; - -/* !! must be sorted by first column !! */ -static struct stateswitch stateswitches[] = { - /* suseinfo tags */ - { STATE_START, "repomd", STATE_REPOMD, 0 }, - { STATE_START, "suseinfo", STATE_SUSEINFO, 0 }, - /* we support the tags element in suseinfo in case - createrepo version does not support it yet */ - { STATE_SUSEINFO, "tags", STATE_TAGS, 0 }, - { STATE_SUSEINFO, "expire", STATE_EXPIRE, 1 }, - { STATE_SUSEINFO, "keywords", STATE_KEYWORDS, 0 }, - /* keywords is the suse extension equivalent of - tags/content when this one was not yet available. - therefore we parse both */ - { STATE_KEYWORDS, "k", STATE_KEYWORD, 1 }, - /* standard tags */ - { STATE_REPOMD, "revision", STATE_REVISION, 1 }, - { STATE_REPOMD, "tags", STATE_TAGS, 0 }, - { STATE_REPOMD, "data", STATE_DATA, 0 }, - - { STATE_TAGS, "content", STATE_CONTENT, 1 }, - { STATE_TAGS, "distro", STATE_DISTRO, 1 }, - /* this tag is only valid in suseinfo.xml for now */ - { STATE_TAGS, "updates", STATE_UPDATES, 1 }, - - { STATE_DATA, "location", STATE_LOCATION, 0 }, - { STATE_DATA, "checksum", STATE_CHECKSUM, 1 }, - { STATE_DATA, "timestamp", STATE_TIMESTAMP, 1 }, - { STATE_DATA, "open-checksum", STATE_OPENCHECKSUM, 1 }, - { NUMSTATES } -}; - - -struct parsedata { - int depth; - enum state state; - int statedepth; - char *content; - int lcontent; - int acontent; - int docontent; - Pool *pool; - Repo *repo; - Repodata *data; - - struct stateswitch *swtab[NUMSTATES]; - enum state sbtab[NUMSTATES]; - int timestamp; - /* handles for collection - structures */ - /* repo updates */ - Id ruhandle; - /* repo products */ - Id rphandle; -}; - -/* - * find attribute - */ - -static inline const char * -find_attr(const char *txt, const char **atts) -{ - for (; *atts; atts += 2) - { - if (!strcmp(*atts, txt)) - return atts[1]; - } - return 0; -} - - -static void XMLCALL -startElement(void *userData, const char *name, const char **atts) -{ - struct parsedata *pd = userData; - /*Pool *pool = pd->pool;*/ - struct stateswitch *sw; - -#if 0 - fprintf(stderr, "start: [%d]%s\n", pd->state, name); -#endif - if (pd->depth != pd->statedepth) - { - pd->depth++; - return; - } - - pd->depth++; - if (!pd->swtab[pd->state]) - return; - for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) /* find name in statetable */ - if (!strcmp(sw->ename, name)) - break; - - if (sw->from != pd->state) - { -#if 0 - fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state); -#endif - return; - } - pd->state = sw->to; - pd->docontent = sw->docontent; - pd->statedepth = pd->depth; - pd->lcontent = 0; - *pd->content = 0; - - switch(pd->state) - { - case STATE_START: break; - case STATE_REPOMD: - { - const char *updstr; - - /* this should be OBSOLETE soon */ - updstr = find_attr("updates", atts); - if (updstr) - { - char *value = strdup(updstr); - char *fvalue = value; /* save the first */ - while (value) - { - char *p = strchr(value, ','); - if (*p) - *p++ = 0; - if (*value) - repo_add_poolstr_array(pd->repo, SOLVID_META, REPOSITORY_UPDATES, value); - value = p; - } - free(fvalue); - } - break; - } - case STATE_SUSEINFO: break; - case STATE_EXPIRE: break; - case STATE_KEYWORDS: break; - case STATE_KEYWORD: break; - case STATE_CONTENT: break; - case STATE_REVISION: break; - case STATE_DISTRO: - { - /* this is extra metadata about the product this repository - was designed for */ - const char *cpeid = find_attr("cpeid", atts); - pd->rphandle = repodata_new_handle(pd->data); - /* set the cpeid for the product - the label is set in the content of the tag */ - if (cpeid) - repodata_set_poolstr(pd->data, pd->rphandle, REPOSITORY_PRODUCT_CPEID, cpeid); - break; - } - case STATE_UPDATES: - { - /* this is extra metadata about the product this repository - was designed for */ - const char *cpeid = find_attr("cpeid", atts); - pd->ruhandle = repodata_new_handle(pd->data); - /* set the cpeid for the product - the label is set in the content of the tag */ - if (cpeid) - repodata_set_poolstr(pd->data, pd->ruhandle, REPOSITORY_PRODUCT_CPEID, cpeid); - break; - } - case STATE_DATA: break; - case STATE_LOCATION: break; - case STATE_CHECKSUM: break; - case STATE_TIMESTAMP: break; - case STATE_OPENCHECKSUM: break; - case NUMSTATES: break; - default: break; - } - return; -} - -static void XMLCALL -endElement(void *userData, const char *name) -{ - struct parsedata *pd = userData; - /* Pool *pool = pd->pool; */ - -#if 0 - fprintf(stderr, "endElement: %s\n", name); -#endif - if (pd->depth != pd->statedepth) - { - pd->depth--; -#if 0 - fprintf(stderr, "back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth); -#endif - return; - } - - pd->depth--; - pd->statedepth--; - switch (pd->state) - { - case STATE_START: break; - case STATE_REPOMD: - if (pd->timestamp > 0) - repodata_set_num(pd->data, SOLVID_META, REPOSITORY_TIMESTAMP, pd->timestamp); - break; - case STATE_DATA: break; - case STATE_LOCATION: break; - case STATE_CHECKSUM: break; - case STATE_OPENCHECKSUM: break; - case STATE_TIMESTAMP: - { - /** - * we want to look for the newest timestamp - * of all resources to save it as the time - * the metadata was generated - */ - int timestamp = atoi(pd->content); - if (timestamp > pd->timestamp) - pd->timestamp = timestamp; - break; - } - case STATE_EXPIRE: - { - int expire = atoi(pd->content); - if (expire > 0) - repodata_set_num(pd->data, SOLVID_META, REPOSITORY_EXPIRE, expire); - break; - } - /* repomd.xml content and suseinfo.xml keywords are equivalent */ - case STATE_CONTENT: - case STATE_KEYWORD: - if (pd->content) - repodata_add_poolstr_array(pd->data, SOLVID_META, REPOSITORY_KEYWORDS, pd->content); - break; - case STATE_REVISION: - if (pd->content) - repodata_add_poolstr_array(pd->data, SOLVID_META, REPOSITORY_REVISION, pd->content); - break; - case STATE_DISTRO: - /* distro tag is used in repomd.xml to say the product this repo is - made for */ - if (pd->content) - repodata_set_str(pd->data, pd->rphandle, REPOSITORY_PRODUCT_LABEL, pd->content); - repodata_add_flexarray(pd->data, SOLVID_META, REPOSITORY_DISTROS, pd->rphandle); - break; - case STATE_UPDATES: - /* distro tag is used in suseinfo.xml to say the repo updates a product - however it s not yet a tag standarized for repomd.xml */ - if (pd->content) - repodata_set_str(pd->data, pd->ruhandle, REPOSITORY_PRODUCT_LABEL, pd->content); - repodata_add_flexarray(pd->data, SOLVID_META, REPOSITORY_UPDATES, pd->ruhandle); - break; - case STATE_SUSEINFO: break; - case STATE_KEYWORDS: break; - case NUMSTATES: break; - default: - break; - } - - pd->state = pd->sbtab[pd->state]; - pd->docontent = 0; - - return; -} - - -static void XMLCALL -characterData(void *userData, const XML_Char *s, int len) -{ - struct parsedata *pd = userData; - int l; - char *c; - if (!pd->docontent) - return; - l = pd->lcontent + len + 1; - if (l > pd->acontent) - { - pd->content = realloc(pd->content, l + 256); - pd->acontent = l + 256; - } - c = pd->content + pd->lcontent; - pd->lcontent += len; - while (len-- > 0) - *c++ = *s++; - *c = 0; -} - -#define BUFF_SIZE 8192 - -void -repo_add_repomdxml(Repo *repo, FILE *fp, int flags) -{ - Pool *pool = repo->pool; - struct parsedata pd; - Repodata *data; - char buf[BUFF_SIZE]; - int i, l; - struct stateswitch *sw; - - if (!(flags & REPO_REUSE_REPODATA)) - data = repo_add_repodata(repo, 0); - else - data = repo_last_repodata(repo); - - memset(&pd, 0, sizeof(pd)); - pd.timestamp = 0; - for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++) - { - if (!pd.swtab[sw->from]) - pd.swtab[sw->from] = sw; - pd.sbtab[sw->to] = sw->from; - } - pd.pool = pool; - pd.repo = repo; - pd.data = data; - - pd.content = malloc(256); - pd.acontent = 256; - pd.lcontent = 0; - XML_Parser parser = XML_ParserCreate(NULL); - XML_SetUserData(parser, &pd); - XML_SetElementHandler(parser, startElement, endElement); - XML_SetCharacterDataHandler(parser, characterData); - for (;;) - { - l = fread(buf, 1, sizeof(buf), fp); - if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR) - { - pool_debug(pool, SAT_FATAL, "repo_repomdxml: %s at line %u:%u\n", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser)); - exit(1); - } - if (l == 0) - break; - } - XML_ParserFree(parser); - - if (!(flags & REPO_NO_INTERNALIZE)) - repodata_internalize(data); - - free(pd.content); -} - -/* EOF */ diff --git a/tools/repo_repomdxml.h b/tools/repo_repomdxml.h deleted file mode 100644 index 49d86fb..0000000 --- a/tools/repo_repomdxml.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2007, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -void repo_add_repomdxml(Repo *repo, FILE *fp, int flags); diff --git a/tools/repo_rpmdb.c b/tools/repo_rpmdb.c deleted file mode 100644 index 826fa13..0000000 --- a/tools/repo_rpmdb.c +++ /dev/null @@ -1,2248 +0,0 @@ -/* - * Copyright (c) 2007, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -/* - * repo_rpmdb - * - * convert rpm db to repo - * - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <limits.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <assert.h> - -#ifdef FEDORA -#include <db4/db.h> -#else -#include <rpm/db.h> -#endif - -#include "pool.h" -#include "repo.h" -#include "hash.h" -#include "util.h" -#include "queue.h" -#include "repo_rpmdb.h" - -#define RPMDB_COOKIE_VERSION 2 - -#define TAG_NAME 1000 -#define TAG_VERSION 1001 -#define TAG_RELEASE 1002 -#define TAG_EPOCH 1003 -#define TAG_SUMMARY 1004 -#define TAG_DESCRIPTION 1005 -#define TAG_BUILDTIME 1006 -#define TAG_BUILDHOST 1007 -#define TAG_INSTALLTIME 1008 -#define TAG_SIZE 1009 -#define TAG_DISTRIBUTION 1010 -#define TAG_VENDOR 1011 -#define TAG_LICENSE 1014 -#define TAG_PACKAGER 1015 -#define TAG_GROUP 1016 -#define TAG_URL 1020 -#define TAG_ARCH 1022 -#define TAG_FILESIZES 1028 -#define TAG_FILEMODES 1030 -#define TAG_FILEMD5S 1035 -#define TAG_FILELINKTOS 1036 -#define TAG_SOURCERPM 1044 -#define TAG_PROVIDENAME 1047 -#define TAG_REQUIREFLAGS 1048 -#define TAG_REQUIRENAME 1049 -#define TAG_REQUIREVERSION 1050 -#define TAG_NOSOURCE 1051 -#define TAG_NOPATCH 1052 -#define TAG_CONFLICTFLAGS 1053 -#define TAG_CONFLICTNAME 1054 -#define TAG_CONFLICTVERSION 1055 -#define TAG_OBSOLETENAME 1090 -#define TAG_FILEDEVICES 1095 -#define TAG_FILEINODES 1096 -#define TAG_PROVIDEFLAGS 1112 -#define TAG_PROVIDEVERSION 1113 -#define TAG_OBSOLETEFLAGS 1114 -#define TAG_OBSOLETEVERSION 1115 -#define TAG_DIRINDEXES 1116 -#define TAG_BASENAMES 1117 -#define TAG_DIRNAMES 1118 -#define TAG_PAYLOADFORMAT 1124 -#define TAG_PATCHESNAME 1133 -#define TAG_FILECOLORS 1140 -#define TAG_SUGGESTSNAME 1156 -#define TAG_SUGGESTSVERSION 1157 -#define TAG_SUGGESTSFLAGS 1158 -#define TAG_ENHANCESNAME 1159 -#define TAG_ENHANCESVERSION 1160 -#define TAG_ENHANCESFLAGS 1161 - -#define DEP_LESS (1 << 1) -#define DEP_GREATER (1 << 2) -#define DEP_EQUAL (1 << 3) -#define DEP_STRONG (1 << 27) -#define DEP_PRE ((1 << 6) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12)) - - -struct rpmid { - unsigned int dbid; - char *name; -}; - -typedef struct rpmhead { - int cnt; - int dcnt; - unsigned char *dp; - unsigned char data[1]; -} RpmHead; - -static int -headexists(RpmHead *h, int tag) -{ - unsigned int i; - unsigned char *d, taga[4]; - - d = h->dp - 16; - taga[0] = tag >> 24; - taga[1] = tag >> 16; - taga[2] = tag >> 8; - taga[3] = tag; - for (i = 0; i < h->cnt; i++, d -= 16) - if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0]) - return 1; - return 0; -} - -static unsigned int * -headint32array(RpmHead *h, int tag, int *cnt) -{ - unsigned int i, o, *r; - unsigned char *d, taga[4]; - - d = h->dp - 16; - taga[0] = tag >> 24; - taga[1] = tag >> 16; - taga[2] = tag >> 8; - taga[3] = tag; - for (i = 0; i < h->cnt; i++, d -= 16) - if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0]) - break; - if (i >= h->cnt) - return 0; - if (d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 4) - return 0; - o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; - i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15]; - if (o + 4 * i > h->dcnt) - return 0; - d = h->dp + o; - r = sat_calloc(i ? i : 1, sizeof(unsigned int)); - if (cnt) - *cnt = i; - for (o = 0; o < i; o++, d += 4) - r[o] = d[0] << 24 | d[1] << 16 | d[2] << 8 | d[3]; - return r; -} - -static unsigned int -headint32(RpmHead *h, int tag) -{ - unsigned int i, o; - unsigned char *d, taga[4]; - - d = h->dp - 16; - taga[0] = tag >> 24; - taga[1] = tag >> 16; - taga[2] = tag >> 8; - taga[3] = tag; - for (i = 0; i < h->cnt; i++, d -= 16) - if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0]) - break; - if (i >= h->cnt) - return 0; - if (d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 4) - return 0; - o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; - i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15]; - if (i == 0 || o + 4 * i > h->dcnt) - return 0; - d = h->dp + o; - return d[0] << 24 | d[1] << 16 | d[2] << 8 | d[3]; -} - -static unsigned int * -headint16array(RpmHead *h, int tag, int *cnt) -{ - unsigned int i, o, *r; - unsigned char *d, taga[4]; - - d = h->dp - 16; - taga[0] = tag >> 24; - taga[1] = tag >> 16; - taga[2] = tag >> 8; - taga[3] = tag; - for (i = 0; i < h->cnt; i++, d -= 16) - if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0]) - break; - if (i >= h->cnt) - return 0; - if (d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 3) - return 0; - o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; - i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15]; - if (o + 4 * i > h->dcnt) - return 0; - d = h->dp + o; - r = sat_calloc(i ? i : 1, sizeof(unsigned int)); - if (cnt) - *cnt = i; - for (o = 0; o < i; o++, d += 2) - r[o] = d[0] << 8 | d[1]; - return r; -} - -static char * -headstring(RpmHead *h, int tag) -{ - unsigned int i, o; - unsigned char *d, taga[4]; - d = h->dp - 16; - taga[0] = tag >> 24; - taga[1] = tag >> 16; - taga[2] = tag >> 8; - taga[3] = tag; - for (i = 0; i < h->cnt; i++, d -= 16) - if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0]) - break; - if (i >= h->cnt) - return 0; - /* 6: STRING, 9: I18NSTRING */ - if (d[4] != 0 || d[5] != 0 || d[6] != 0 || (d[7] != 6 && d[7] != 9)) - return 0; - o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; - return (char *)h->dp + o; -} - -static char ** -headstringarray(RpmHead *h, int tag, int *cnt) -{ - unsigned int i, o; - unsigned char *d, taga[4]; - char **r; - - d = h->dp - 16; - taga[0] = tag >> 24; - taga[1] = tag >> 16; - taga[2] = tag >> 8; - taga[3] = tag; - for (i = 0; i < h->cnt; i++, d -= 16) - if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0]) - break; - if (i >= h->cnt) - return 0; - if (d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 8) - return 0; - o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; - i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15]; - r = sat_calloc(i ? i : 1, sizeof(char *)); - if (cnt) - *cnt = i; - d = h->dp + o; - for (o = 0; o < i; o++) - { - r[o] = (char *)d; - if (o + 1 < i) - d += strlen((char *)d) + 1; - if (d >= h->dp + h->dcnt) - { - sat_free(r); - return 0; - } - } - return r; -} - -static char *headtoevr(RpmHead *h) -{ - unsigned int epoch; - char *version, *v; - char *release; - char *evr; - - version = headstring(h, TAG_VERSION); - release = headstring(h, TAG_RELEASE); - epoch = headint32(h, TAG_EPOCH); - if (!version || !release) - { - fprintf(stderr, "headtoevr: bad rpm header\n"); - exit(1); - } - for (v = version; *v >= 0 && *v <= '9'; v++) - ; - if (epoch || (v != version && *v == ':')) - { - char epochbuf[11]; /* 32bit decimal will fit in */ - sprintf(epochbuf, "%u", epoch); - evr = sat_malloc(strlen(epochbuf) + 1 + strlen(version) + 1 + strlen(release) + 1); - sprintf(evr, "%s:%s-%s", epochbuf, version, release); - } - else - { - evr = sat_malloc(strlen(version) + 1 + strlen(release) + 1); - sprintf(evr, "%s-%s", version, release); - } - return evr; -} - - -static void -setutf8string(Repodata *repodata, Id handle, Id tag, const char *str) -{ - const unsigned char *cp; - int state = 0; - int c; - unsigned char *buf = 0, *bp; - - /* check if it's already utf8, code taken from screen ;-) */ - cp = (const unsigned char *)str; - while ((c = *cp++) != 0) - { - if (state) - { - if ((c & 0xc0) != 0x80) - break; /* encoding error */ - c = (c & 0x3f) | (state << 6); - if (!(state & 0x40000000)) - { - /* check for overlong sequences */ - if ((c & 0x820823e0) == 0x80000000) - c = 0xfdffffff; - else if ((c & 0x020821f0) == 0x02000000) - c = 0xfff7ffff; - else if ((c & 0x000820f8) == 0x00080000) - c = 0xffffd000; - else if ((c & 0x0000207c) == 0x00002000) - c = 0xffffff70; - } - } - else - { - /* new sequence */ - if (c >= 0xfe) - break; - else if (c >= 0xfc) - c = (c & 0x01) | 0xbffffffc; /* 5 bytes to follow */ - else if (c >= 0xf8) - c = (c & 0x03) | 0xbfffff00; /* 4 */ - else if (c >= 0xf0) - c = (c & 0x07) | 0xbfffc000; /* 3 */ - else if (c >= 0xe0) - c = (c & 0x0f) | 0xbff00000; /* 2 */ - else if (c >= 0xc2) - c = (c & 0x1f) | 0xfc000000; /* 1 */ - else if (c >= 0x80) - break; - } - state = (c & 0x80000000) ? c : 0; - } - if (c) - { - /* not utf8, assume latin1 */ - buf = sat_malloc(2 * strlen(str) + 1); - cp = (const unsigned char *)str; - str = (char *)buf; - bp = buf; - while ((c = *cp++) != 0) - { - if (c >= 0xc0) - { - *bp++ = 0xc3; - c ^= 0x80; - } - else if (c >= 0x80) - *bp++ = 0xc2; - *bp++ = c; - } - *bp++ = 0; - } - repodata_set_str(repodata, handle, tag, str); - if (buf) - sat_free(buf); -} - -static unsigned int -makedeps(Pool *pool, Repo *repo, RpmHead *rpmhead, int tagn, int tagv, int tagf, int strong) -{ - char **n, **v; - unsigned int *f; - int i, cc, nc, vc, fc; - int haspre = 0; - unsigned int olddeps; - Id *ida; - - n = headstringarray(rpmhead, tagn, &nc); - if (!n) - return 0; - v = headstringarray(rpmhead, tagv, &vc); - if (!v) - { - sat_free(n); - return 0; - } - f = headint32array(rpmhead, tagf, &fc); - if (!f) - { - sat_free(n); - free(v); - return 0; - } - if (nc != vc || nc != fc) - { - fprintf(stderr, "bad dependency entries\n"); - exit(1); - } - - cc = nc; - if (strong) - { - cc = 0; - for (i = 0; i < nc; i++) - if ((f[i] & DEP_STRONG) == (strong == 1 ? 0 : DEP_STRONG)) - { - cc++; - if ((f[i] & DEP_PRE) != 0) - haspre = 1; - } - } - else - { - for (i = 0; i < nc; i++) - if ((f[i] & DEP_PRE) != 0) - { - haspre = 1; - break; - } - } - if (tagn != TAG_REQUIRENAME) - haspre = 0; - if (cc == 0) - { - sat_free(n); - sat_free(v); - sat_free(f); - return 0; - } - cc += haspre; - olddeps = repo_reserve_ids(repo, 0, cc); - ida = repo->idarraydata + olddeps; - for (i = 0; ; i++) - { - if (i == nc) - { - if (haspre != 1) - break; - haspre = 2; - i = 0; - *ida++ = SOLVABLE_PREREQMARKER; - } - if (strong && (f[i] & DEP_STRONG) != (strong == 1 ? 0 : DEP_STRONG)) - continue; - if (haspre == 1 && (f[i] & DEP_PRE) != 0) - continue; - if (haspre == 2 && (f[i] & DEP_PRE) == 0) - continue; - if (f[i] & (DEP_LESS|DEP_GREATER|DEP_EQUAL)) - { - Id name, evr; - int flags = 0; - if ((f[i] & DEP_LESS) != 0) - flags |= 4; - if ((f[i] & DEP_EQUAL) != 0) - flags |= 2; - if ((f[i] & DEP_GREATER) != 0) - flags |= 1; - name = str2id(pool, n[i], 1); - if (v[i][0] == '0' && v[i][1] == ':' && v[i][2]) - evr = str2id(pool, v[i] + 2, 1); - else - evr = str2id(pool, v[i], 1); - *ida++ = rel2id(pool, name, evr, flags, 1); - } - else - *ida++ = str2id(pool, n[i], 1); - } - *ida++ = 0; - repo->idarraysize += cc + 1; - sat_free(n); - sat_free(v); - sat_free(f); - return olddeps; -} - - -#ifdef USE_FILEFILTER - -#define FILEFILTER_EXACT 0 -#define FILEFILTER_STARTS 1 -#define FILEFILTER_CONTAINS 2 - -struct filefilter { - int dirmatch; - char *dir; - char *base; -}; - -static struct filefilter filefilters[] = { - { FILEFILTER_CONTAINS, "/bin/", 0}, - { FILEFILTER_CONTAINS, "/sbin/", 0}, - { FILEFILTER_CONTAINS, "/lib/", 0}, - { FILEFILTER_CONTAINS, "/lib64/", 0}, - { FILEFILTER_CONTAINS, "/etc/", 0}, - { FILEFILTER_STARTS, "/usr/games/", 0}, - { FILEFILTER_EXACT, "/usr/share/dict/", "words"}, - { FILEFILTER_STARTS, "/usr/share/", "magic.mime"}, - { FILEFILTER_STARTS, "/opt/gnome/games/", 0}, -}; - -#endif - -static void -adddudata(Pool *pool, Repo *repo, Repodata *data, Solvable *s, RpmHead *rpmhead, char **dn, unsigned int *di, int fc, int dic) -{ - Id handle, did; - int i, fszc; - unsigned int *fkb, *fn, *fsz, *fm, *fino; - unsigned int inotest[256], inotestok; - - if (!fc) - return; - fsz = headint32array(rpmhead, TAG_FILESIZES, &fszc); - if (!fsz || fc != fszc) - { - sat_free(fsz); - return; - } - /* stupid rpm recodrs sizes of directories, so we have to check the mode */ - fm = headint16array(rpmhead, TAG_FILEMODES, &fszc); - if (!fm || fc != fszc) - { - sat_free(fsz); - sat_free(fm); - return; - } - fino = headint32array(rpmhead, TAG_FILEINODES, &fszc); - if (!fino || fc != fszc) - { - sat_free(fsz); - sat_free(fm); - sat_free(fino); - return; - } - inotestok = 0; - if (fc < sizeof(inotest)) - { - memset(inotest, 0, sizeof(inotest)); - for (i = 0; i < fc; i++) - { - int off, bit; - if (fsz[i] == 0 || !S_ISREG(fm[i])) - continue; - off = (fino[i] >> 5) & (sizeof(inotest)/sizeof(*inotest) - 1); - bit = 1 << (fino[i] & 31); - if ((inotest[off] & bit) != 0) - break; - inotest[off] |= bit; - } - if (i == fc) - inotestok = 1; - } - if (!inotestok) - { - unsigned int *fdev = headint32array(rpmhead, TAG_FILEDEVICES, &fszc); - unsigned int *fx, j; - unsigned int mask, hash, hh; - if (!fdev || fc != fszc) - { - sat_free(fsz); - sat_free(fm); - sat_free(fdev); - sat_free(fino); - return; - } - mask = fc; - while ((mask & (mask - 1)) != 0) - mask = mask & (mask - 1); - mask <<= 2; - if (mask > sizeof(inotest)/sizeof(*inotest)) - fx = sat_calloc(mask, sizeof(unsigned int)); - else - { - fx = inotest; - memset(fx, 0, mask * sizeof(unsigned int)); - } - mask--; - for (i = 0; i < fc; i++) - { - if (fsz[i] == 0 || !S_ISREG(fm[i])) - continue; - hash = (fino[i] + fdev[i] * 31) & mask; - hh = 7; - while ((j = fx[hash]) != 0) - { - if (fino[j - 1] == fino[i] && fdev[j - 1] == fdev[i]) - { - fsz[i] = 0; /* kill entry */ - break; - } - hash = (hash + hh++) & mask; - } - if (!j) - fx[hash] = i + 1; - } - if (fx != inotest) - sat_free(fx); - sat_free(fdev); - } - sat_free(fino); - fn = sat_calloc(dic, sizeof(unsigned int)); - fkb = sat_calloc(dic, sizeof(unsigned int)); - for (i = 0; i < fc; i++) - { - if (fsz[i] == 0 || !S_ISREG(fm[i])) - continue; - if (di[i] >= dic) - continue; - fn[di[i]]++; - fkb[di[i]] += fsz[i] / 1024 + 1; - } - sat_free(fsz); - sat_free(fm); - /* commit */ - handle = s - pool->solvables; - for (i = 0; i < fc; i++) - { - if (!fn[i]) - continue; - if (!*dn[i] && (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)) - did = repodata_str2dir(data, "/usr/src", 1); - else - did = repodata_str2dir(data, dn[i], 1); - repodata_add_dirnumnum(data, handle, SOLVABLE_DISKUSAGE, did, fkb[i], fn[i]); - } - sat_free(fn); - sat_free(fkb); -} - -/* assumes last processed array is provides! */ -static unsigned int -addfileprovides(Pool *pool, Repo *repo, Repodata *data, Solvable *s, RpmHead *rpmhead, unsigned int olddeps) -{ - char **bn; - char **dn; - unsigned int *di; - int bnc, dnc, dic; - int i; -#ifdef USE_FILEFILTER - int j; - struct filefilter *ff; -#endif -#if 0 - char *fn = 0; - int fna = 0; -#endif - - if (!data) - return olddeps; - bn = headstringarray(rpmhead, TAG_BASENAMES, &bnc); - if (!bn) - return olddeps; - dn = headstringarray(rpmhead, TAG_DIRNAMES, &dnc); - if (!dn) - { - sat_free(bn); - return olddeps; - } - di = headint32array(rpmhead, TAG_DIRINDEXES, &dic); - if (!di) - { - sat_free(bn); - sat_free(dn); - return olddeps; - } - if (bnc != dic) - { - fprintf(stderr, "bad filelist\n"); - exit(1); - } - - if (data) - adddudata(pool, repo, data, s, rpmhead, dn, di, bnc, dic); - - for (i = 0; i < bnc; i++) - { -#ifdef USE_FILEFILTER - ff = filefilters; - for (j = 0; j < sizeof(filefilters)/sizeof(*filefilters); j++, ff++) - { - if (ff->dir) - { - switch (ff->dirmatch) - { - case FILEFILTER_STARTS: - if (strncmp(dn[di[i]], ff->dir, strlen(ff->dir))) - continue; - break; - case FILEFILTER_CONTAINS: - if (!strstr(dn[di[i]], ff->dir)) - continue; - break; - case FILEFILTER_EXACT: - default: - if (strcmp(dn[di[i]], ff->dir)) - continue; - break; - } - } - if (ff->base) - { - if (strcmp(bn[i], ff->base)) - continue; - } - break; - } - if (j == sizeof(filefilters)/sizeof(*filefilters)) - continue; -#endif -#if 0 - j = strlen(bn[i]) + strlen(dn[di[i]]) + 1; - if (j > fna) - { - fna = j + 256; - fn = sat_realloc(fn, fna); - } - strcpy(fn, dn[di[i]]); - strcat(fn, bn[i]); - olddeps = repo_addid_dep(repo, olddeps, str2id(pool, fn, 1), SOLVABLE_FILEMARKER); -#endif - if (data) - { - Id handle, did; - handle = s - pool->solvables; - did = repodata_str2dir(data, dn[di[i]], 1); - if (!did) - did = repodata_str2dir(data, "/", 1); - repodata_add_dirstr(data, handle, SOLVABLE_FILELIST, did, bn[i]); - } - } -#if 0 - if (fn) - sat_free(fn); -#endif - sat_free(bn); - sat_free(dn); - sat_free(di); - return olddeps; -} - -static void -addsourcerpm(Pool *pool, Repodata *data, Id handle, char *sourcerpm, char *name, char *evr) -{ - const char *p, *sevr, *sarch; - - p = strrchr(sourcerpm, '.'); - if (!p || strcmp(p, ".rpm") != 0) - return; - p--; - while (p > sourcerpm && *p != '.') - p--; - if (*p != '.' || p == sourcerpm) - return; - sarch = p-- + 1; - while (p > sourcerpm && *p != '-') - p--; - if (*p != '-' || p == sourcerpm) - return; - p--; - while (p > sourcerpm && *p != '-') - p--; - if (*p != '-' || p == sourcerpm) - return; - sevr = p + 1; - if (!strcmp(sarch, "src.rpm")) - repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, ARCH_SRC); - else if (!strcmp(sarch, "nosrc.rpm")) - repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, ARCH_NOSRC); - else - repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, strn2id(pool, sarch, strlen(sarch) - 4, 1)); - if (evr && !strncmp(sevr, evr, sarch - sevr - 1) && evr[sarch - sevr - 1] == 0) - repodata_set_void(data, handle, SOLVABLE_SOURCEEVR); - else - repodata_set_id(data, handle, SOLVABLE_SOURCEEVR, strn2id(pool, sevr, sarch - sevr - 1, 1)); - if (name && !strncmp(sourcerpm, name, sevr - sourcerpm - 1) && name[sevr - sourcerpm - 1] == 0) - repodata_set_void(data, handle, SOLVABLE_SOURCENAME); - else - repodata_set_id(data, handle, SOLVABLE_SOURCENAME, strn2id(pool, sourcerpm, sevr - sourcerpm - 1, 1)); -} - -static int -rpm2solv(Pool *pool, Repo *repo, Repodata *data, Solvable *s, RpmHead *rpmhead) -{ - char *name; - char *evr; - char *sourcerpm; - - name = headstring(rpmhead, TAG_NAME); - if (!strcmp(name, "gpg-pubkey")) - return 0; - s->name = str2id(pool, name, 1); - if (!s->name) - { - fprintf(stderr, "package has no name\n"); - exit(1); - } - sourcerpm = headstring(rpmhead, TAG_SOURCERPM); - if (sourcerpm) - s->arch = str2id(pool, headstring(rpmhead, TAG_ARCH), 1); - else - { - if (headexists(rpmhead, TAG_NOSOURCE) || headexists(rpmhead, TAG_NOPATCH)) - s->arch = ARCH_NOSRC; - else - s->arch = ARCH_SRC; - } - if (!s->arch) - s->arch = ARCH_NOARCH; - evr = headtoevr(rpmhead); - s->evr = str2id(pool, evr, 1); - s->vendor = str2id(pool, headstring(rpmhead, TAG_VENDOR), 1); - - s->provides = makedeps(pool, repo, rpmhead, TAG_PROVIDENAME, TAG_PROVIDEVERSION, TAG_PROVIDEFLAGS, 0); - s->provides = addfileprovides(pool, repo, data, s, rpmhead, s->provides); - if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) - s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); - s->requires = makedeps(pool, repo, rpmhead, TAG_REQUIRENAME, TAG_REQUIREVERSION, TAG_REQUIREFLAGS, 0); - s->conflicts = makedeps(pool, repo, rpmhead, TAG_CONFLICTNAME, TAG_CONFLICTVERSION, TAG_CONFLICTFLAGS, 0); - s->obsoletes = makedeps(pool, repo, rpmhead, TAG_OBSOLETENAME, TAG_OBSOLETEVERSION, TAG_OBSOLETEFLAGS, 0); - - s->recommends = makedeps(pool, repo, rpmhead, TAG_SUGGESTSNAME, TAG_SUGGESTSVERSION, TAG_SUGGESTSFLAGS, 2); - s->suggests = makedeps(pool, repo, rpmhead, TAG_SUGGESTSNAME, TAG_SUGGESTSVERSION, TAG_SUGGESTSFLAGS, 1); - s->supplements = makedeps(pool, repo, rpmhead, TAG_ENHANCESNAME, TAG_ENHANCESVERSION, TAG_ENHANCESFLAGS, 2); - s->enhances = makedeps(pool, repo, rpmhead, TAG_ENHANCESNAME, TAG_ENHANCESVERSION, TAG_ENHANCESFLAGS, 1); - s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0); - s->conflicts = repo_fix_conflicts(repo, s->conflicts); - - if (data) - { - Id handle; - char *str; - unsigned int u32; - - handle = s - pool->solvables; - str = headstring(rpmhead, TAG_SUMMARY); - if (str) - setutf8string(data, handle, SOLVABLE_SUMMARY, str); - str = headstring(rpmhead, TAG_DESCRIPTION); - if (str) - { - char *aut, *p; - for (aut = str; (aut = strchr(aut, '\n')) != 0; aut++) - if (!strncmp(aut, "\nAuthors:\n--------\n", 19)) - break; - if (aut) - { - /* oh my, found SUSE special author section */ - int l = aut - str; - str = strdup(str); - aut = str + l; - str[l] = 0; - while (l > 0 && str[l - 1] == '\n') - str[--l] = 0; - if (l) - setutf8string(data, handle, SOLVABLE_DESCRIPTION, str); - p = aut + 19; - aut = str; /* copy over */ - while (*p == ' ' || *p == '\n') - p++; - while (*p) - { - if (*p == '\n') - { - *aut++ = *p++; - while (*p == ' ') - p++; - continue; - } - *aut++ = *p++; - } - while (aut != str && aut[-1] == '\n') - aut--; - *aut = 0; - if (*str) - setutf8string(data, handle, SOLVABLE_AUTHORS, str); - free(str); - } - else if (*str) - setutf8string(data, handle, SOLVABLE_DESCRIPTION, str); - } - str = headstring(rpmhead, TAG_GROUP); - if (str) - repodata_set_poolstr(data, handle, SOLVABLE_GROUP, str); - str = headstring(rpmhead, TAG_LICENSE); - if (str) - repodata_set_poolstr(data, handle, SOLVABLE_LICENSE, str); - str = headstring(rpmhead, TAG_URL); - if (str) - repodata_set_str(data, handle, SOLVABLE_URL, str); - str = headstring(rpmhead, TAG_DISTRIBUTION); - if (str) - repodata_set_poolstr(data, handle, SOLVABLE_DISTRIBUTION, str); - str = headstring(rpmhead, TAG_PACKAGER); - if (str) - repodata_set_poolstr(data, handle, SOLVABLE_PACKAGER, str); - u32 = headint32(rpmhead, TAG_BUILDTIME); - if (u32) - repodata_set_num(data, handle, SOLVABLE_BUILDTIME, u32); - u32 = headint32(rpmhead, TAG_INSTALLTIME); - if (u32) - repodata_set_num(data, handle, SOLVABLE_INSTALLTIME, u32); - u32 = headint32(rpmhead, TAG_SIZE); - if (u32) - repodata_set_num(data, handle, SOLVABLE_INSTALLSIZE, (u32 + 1023) / 1024); - if (sourcerpm) - addsourcerpm(pool, data, handle, sourcerpm, name, evr); - } - sat_free(evr); - return 1; -} - -static Id -copyreldep(Pool *pool, Pool *frompool, Id id) -{ - Reldep *rd = GETRELDEP(frompool, id); - Id name = rd->name, evr = rd->evr; - if (ISRELDEP(name)) - name = copyreldep(pool, frompool, name); - else - name = str2id(pool, id2str(frompool, name), 1); - if (ISRELDEP(evr)) - evr = copyreldep(pool, frompool, evr); - else - evr = str2id(pool, id2str(frompool, evr), 1); - return rel2id(pool, name, evr, rd->flags, 1); -} - -static Offset -copydeps(Pool *pool, Repo *repo, Offset fromoff, Repo *fromrepo) -{ - int cc; - Id id, *ida, *from; - Offset ido; - Pool *frompool = fromrepo->pool; - - if (!fromoff) - return 0; - from = fromrepo->idarraydata + fromoff; - for (ida = from, cc = 0; *ida; ida++, cc++) - ; - if (cc == 0) - return 0; - ido = repo_reserve_ids(repo, 0, cc); - ida = repo->idarraydata + ido; - if (frompool && pool != frompool) - { - while (*from) - { - id = *from++; - if (ISRELDEP(id)) - id = copyreldep(pool, frompool, id); - else - id = str2id(pool, id2str(frompool, id), 1); - *ida++ = id; - } - *ida = 0; - } - else - memcpy(ida, from, (cc + 1) * sizeof(Id)); - repo->idarraysize += cc + 1; - return ido; -} - -#define COPYDIR_DIRCACHE_SIZE 512 - -static Id copydir_complex(Pool *pool, Repodata *data, Stringpool *fromspool, Repodata *fromdata, Id did, Id *cache); - -static inline Id -copydir(Pool *pool, Repodata *data, Stringpool *fromspool, Repodata *fromdata, Id did, Id *cache) -{ - if (cache && cache[did & 255] == did) - return cache[(did & 255) + 256]; - return copydir_complex(pool, data, fromspool, fromdata, did, cache); -} - -static Id -copydir_complex(Pool *pool, Repodata *data, Stringpool *fromspool, Repodata *fromdata, Id did, Id *cache) -{ - Id parent = dirpool_parent(&fromdata->dirpool, did); - Id compid = dirpool_compid(&fromdata->dirpool, did); - if (parent) - parent = copydir(pool, data, fromspool, fromdata, parent, cache); - if (fromspool != &pool->ss) - compid = str2id(pool, stringpool_id2str(fromspool, compid), 1); - compid = dirpool_add_dir(&data->dirpool, parent, compid, 1); - if (cache) - { - cache[did & 255] = did; - cache[(did & 255) + 256] = compid; - } - return compid; -} - -struct solvable_copy_cbdata { - Repodata *data; - Id handle; - Id *dircache; -}; - -static int -solvable_copy_cb(void *vcbdata, Solvable *r, Repodata *fromdata, Repokey *key, KeyValue *kv) -{ - struct solvable_copy_cbdata *cbdata = vcbdata; - Id id, keyname; - Repodata *data = cbdata->data; - Id handle = cbdata->handle; - Pool *pool = data->repo->pool, *frompool = fromdata->repo->pool; - Stringpool *fromspool = fromdata->localpool ? &fromdata->spool : &frompool->ss; - - keyname = key->name; - if (keyname >= ID_NUM_INTERNAL) - keyname = str2id(pool, id2str(frompool, keyname), 1); - switch(key->type) - { - case REPOKEY_TYPE_ID: - case REPOKEY_TYPE_CONSTANTID: - id = kv->id; - assert(!data->localpool); /* implement me! */ - if (pool != frompool || fromdata->localpool) - { - if (ISRELDEP(id)) - id = copyreldep(pool, frompool, id); - else - id = str2id(pool, stringpool_id2str(fromspool, id), 1); - } - if (key->type == REPOKEY_TYPE_ID) - repodata_set_id(data, handle, keyname, id); - else - repodata_set_constantid(data, handle, keyname, id); - break; - case REPOKEY_TYPE_STR: - repodata_set_str(data, handle, keyname, kv->str); - break; - case REPOKEY_TYPE_VOID: - repodata_set_void(data, handle, keyname); - break; - case REPOKEY_TYPE_NUM: - repodata_set_num(data, handle, keyname, kv->num); - break; - case REPOKEY_TYPE_CONSTANT: - repodata_set_constant(data, handle, keyname, kv->num); - break; - case REPOKEY_TYPE_DIRNUMNUMARRAY: - id = kv->id; - assert(!data->localpool); /* implement me! */ - id = copydir(pool, data, fromspool, fromdata, id, cbdata->dircache); - repodata_add_dirnumnum(data, handle, keyname, id, kv->num, kv->num2); - break; - case REPOKEY_TYPE_DIRSTRARRAY: - id = kv->id; - assert(!data->localpool); /* implement me! */ - id = copydir(pool, data, fromspool, fromdata, id, cbdata->dircache); - repodata_add_dirstr(data, handle, keyname, id, kv->str); - break; - default: - break; - } - return 0; -} - -static void -solvable_copy(Solvable *s, Solvable *r, Repodata *data, Id *dircache) -{ - Repo *repo = s->repo; - Repo *fromrepo = r->repo; - Pool *pool = repo->pool; - struct solvable_copy_cbdata cbdata; - - /* copy solvable data */ - if (pool == fromrepo->pool) - { - s->name = r->name; - s->evr = r->evr; - s->arch = r->arch; - s->vendor = r->vendor; - } - else - { - if (r->name) - s->name = str2id(pool, id2str(fromrepo->pool, r->name), 1); - if (r->evr) - s->evr = str2id(pool, id2str(fromrepo->pool, r->evr), 1); - if (r->arch) - s->arch = str2id(pool, id2str(fromrepo->pool, r->arch), 1); - if (r->vendor) - s->vendor = str2id(pool, id2str(fromrepo->pool, r->vendor), 1); - } - s->provides = copydeps(pool, repo, r->provides, fromrepo); - s->requires = copydeps(pool, repo, r->requires, fromrepo); - s->conflicts = copydeps(pool, repo, r->conflicts, fromrepo); - s->obsoletes = copydeps(pool, repo, r->obsoletes, fromrepo); - s->recommends = copydeps(pool, repo, r->recommends, fromrepo); - s->suggests = copydeps(pool, repo, r->suggests, fromrepo); - s->supplements = copydeps(pool, repo, r->supplements, fromrepo); - s->enhances = copydeps(pool, repo, r->enhances, fromrepo); - - /* copy all attributes */ - if (!data) - return; - cbdata.data = data; - cbdata.handle = s - pool->solvables; - cbdata.dircache = dircache; - repo_search(fromrepo, (r - fromrepo->pool->solvables), 0, 0, SEARCH_NO_STORAGE_SOLVABLE, solvable_copy_cb, &cbdata); -} - -/* used to sort entries returned in some database order */ -static int -rpmids_sort_cmp(const void *va, const void *vb, void *dp) -{ - struct rpmid const *a = va, *b = vb; - int r; - r = strcmp(a->name, b->name); - if (r) - return r; - return a->dbid - b->dbid; -} - -static int -pkgids_sort_cmp(const void *va, const void *vb, void *dp) -{ - Repo *repo = dp; - Pool *pool = repo->pool; - Solvable *a = pool->solvables + *(Id *)va; - Solvable *b = pool->solvables + *(Id *)vb; - Id *rpmdbid; - - if (a->name != b->name) - return strcmp(id2str(pool, a->name), id2str(pool, b->name)); - rpmdbid = repo->rpmdbid; - return rpmdbid[(a - pool->solvables) - repo->start] - rpmdbid[(b - pool->solvables) - repo->start]; -} - -static void -swap_solvables(Repo *repo, Repodata *data, Id pa, Id pb) -{ - Pool *pool = repo->pool; - Solvable tmp; - - tmp = pool->solvables[pa]; - pool->solvables[pa] = pool->solvables[pb]; - pool->solvables[pb] = tmp; - if (repo->rpmdbid) - { - Id tmpid = repo->rpmdbid[pa - repo->start]; - repo->rpmdbid[pa - repo->start] = repo->rpmdbid[pb - repo->start]; - repo->rpmdbid[pb - repo->start] = tmpid; - } - /* only works if nothing is already internalized! */ - if (data && data->attrs) - { - Id *tmpattrs = data->attrs[pa - data->start]; - data->attrs[pa - data->start] = data->attrs[pb - data->start]; - data->attrs[pb - data->start] = tmpattrs; - } -} - -static void -mkrpmdbcookie(struct stat *st, unsigned char *cookie) -{ - memset(cookie, 0, 32); - cookie[3] = RPMDB_COOKIE_VERSION; - memcpy(cookie + 16, &st->st_ino, sizeof(st->st_ino)); - memcpy(cookie + 24, &st->st_dev, sizeof(st->st_dev)); -} - -static int -count_headers(const char *rootdir, DB_ENV *dbenv) -{ - char dbpath[PATH_MAX]; - struct stat statbuf; - int byteswapped; - DB *db = 0; - DBC *dbc = 0; - int count = 0; - DBT dbkey; - DBT dbdata; - - snprintf(dbpath, PATH_MAX, "%s/var/lib/rpm/Name", rootdir); - if (stat(dbpath, &statbuf)) - return 0; - memset(&dbkey, 0, sizeof(dbkey)); - memset(&dbdata, 0, sizeof(dbdata)); - if (db_create(&db, dbenv, 0)) - { - perror("db_create"); - exit(1); - } - if (db->open(db, 0, "Name", 0, DB_UNKNOWN, DB_RDONLY, 0664)) - { - perror("db->open Name index"); - exit(1); - } - if (db->get_byteswapped(db, &byteswapped)) - { - perror("db->get_byteswapped"); - exit(1); - } - if (db->cursor(db, NULL, &dbc, 0)) - { - perror("db->cursor"); - exit(1); - } - while (dbc->c_get(dbc, &dbkey, &dbdata, DB_NEXT) == 0) - count += dbdata.size >> 3; - dbc->c_close(dbc); - db->close(db, 0); - return count; -} - -/* - * read rpm db as repo - * - */ - -void -repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir, int flags) -{ - Pool *pool = repo->pool; - unsigned char buf[16]; - DB *db = 0; - DBC *dbc = 0; - int byteswapped; - unsigned int dbid; - unsigned char *dp, *dbidp; - int dl, nrpmids; - struct rpmid *rpmids, *rp; - int i; - int rpmheadsize; - RpmHead *rpmhead; - Solvable *s; - Id id, *refhash; - unsigned int refmask, h; - char dbpath[PATH_MAX]; - DB_ENV *dbenv = 0; - DBT dbkey; - DBT dbdata; - struct stat packagesstat; - unsigned char newcookie[32]; - const unsigned char *oldcookie = 0; - Id oldcookietype = 0; - Repodata *data; - int count = 0, done = 0; - unsigned int now; - - now = sat_timems(0); - memset(&dbkey, 0, sizeof(dbkey)); - memset(&dbdata, 0, sizeof(dbdata)); - - if (!rootdir) - rootdir = ""; - - if (!(flags & REPO_REUSE_REPODATA)) - data = repo_add_repodata(repo, 0); - else - data = repo_last_repodata(repo); - - if (ref && !(ref->nsolvables && ref->rpmdbid)) - ref = 0; - - if (db_env_create(&dbenv, 0)) - { - perror("db_env_create"); - exit(1); - } - snprintf(dbpath, PATH_MAX, "%s/var/lib/rpm", rootdir); - /* should look in /usr/lib/rpm/macros instead, but we want speed... */ -#ifdef FEDORA - if (dbenv->open(dbenv, dbpath, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL, 0)) -#else - if (dbenv->open(dbenv, dbpath, DB_CREATE|DB_PRIVATE|DB_INIT_MPOOL, 0)) -#endif - { - perror("dbenv open"); - exit(1); - } - - /* XXX: should get ro lock of Packages database! */ - snprintf(dbpath, PATH_MAX, "%s/var/lib/rpm/Packages", rootdir); - if (stat(dbpath, &packagesstat)) - { - perror(dbpath); - exit(1); - } - mkrpmdbcookie(&packagesstat, newcookie); - repodata_set_bin_checksum(data, SOLVID_META, REPOSITORY_RPMDBCOOKIE, REPOKEY_TYPE_SHA256, newcookie); - - if (ref) - oldcookie = repo_lookup_bin_checksum(ref, SOLVID_META, REPOSITORY_RPMDBCOOKIE, &oldcookietype); - if (!ref || !oldcookie || oldcookietype != REPOKEY_TYPE_SHA256 || memcmp(oldcookie, newcookie, 32) != 0) - { - Id *pkgids; - - if ((flags & RPMDB_REPORT_PROGRESS) != 0) - count = count_headers(rootdir, dbenv); - if (db_create(&db, dbenv, 0)) - { - perror("db_create"); - exit(1); - } - if (db->open(db, 0, "Packages", 0, DB_UNKNOWN, DB_RDONLY, 0664)) - { - perror("db->open Packages index"); - exit(1); - } - if (db->get_byteswapped(db, &byteswapped)) - { - perror("db->get_byteswapped"); - exit(1); - } - if (db->cursor(db, NULL, &dbc, 0)) - { - perror("db->cursor"); - exit(1); - } - dbidp = (unsigned char *)&dbid; - rpmheadsize = 0; - rpmhead = 0; - i = 0; - s = 0; - while (dbc->c_get(dbc, &dbkey, &dbdata, DB_NEXT) == 0) - { - if (!s) - s = pool_id2solvable(pool, repo_add_solvable(repo)); - if (!repo->rpmdbid) - repo->rpmdbid = repo_sidedata_create(repo, sizeof(Id)); - if (dbkey.size != 4) - { - fprintf(stderr, "corrupt Packages database (key size)\n"); - exit(1); - } - dp = dbkey.data; - if (byteswapped) - { - dbidp[0] = dp[3]; - dbidp[1] = dp[2]; - dbidp[2] = dp[1]; - dbidp[3] = dp[0]; - } - else - memcpy(dbidp, dp, 4); - if (dbid == 0) /* the join key */ - continue; - if (dbdata.size < 8) - { - fprintf(stderr, "corrupt rpm database (size %u)\n", dbdata.size); - exit(1); - } - if (dbdata.size > rpmheadsize) - { - rpmheadsize = dbdata.size + 128; - rpmhead = sat_realloc(rpmhead, sizeof(*rpmhead) + rpmheadsize); - } - memcpy(buf, dbdata.data, 8); - rpmhead->cnt = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; - rpmhead->dcnt = buf[4] << 24 | buf[5] << 16 | buf[6] << 8 | buf[7]; - if (8 + rpmhead->cnt * 16 + rpmhead->dcnt > dbdata.size) - { - fprintf(stderr, "corrupt rpm database (data size)\n"); - exit(1); - } - memcpy(rpmhead->data, (unsigned char *)dbdata.data + 8, rpmhead->cnt * 16 + rpmhead->dcnt); - rpmhead->dp = rpmhead->data + rpmhead->cnt * 16; - repo->rpmdbid[(s - pool->solvables) - repo->start] = dbid; - if (rpm2solv(pool, repo, data, s, rpmhead)) - { - i++; - s = 0; - } - else - { - /* We can reuse this solvable, but make sure it's still - associated with this repo. */ - memset(s, 0, sizeof(*s)); - s->repo = repo; - } - if ((flags & RPMDB_REPORT_PROGRESS) != 0) - { - if (done < count) - done++; - if (done < count && (done - 1) * 100 / count != done * 100 / count) - pool_debug(pool, SAT_ERROR, "%%%% %d\n", done * 100 / count); - } - } - if (s) - { - /* oops, could not reuse. free it instead */ - repo_free_solvable_block(repo, s - pool->solvables, 1, 1); - s = 0; - } - dbc->c_close(dbc); - db->close(db, 0); - db = 0; - /* now sort all solvables */ - if (repo->end - repo->start > 1) - { - pkgids = sat_malloc2(repo->end - repo->start, sizeof(Id)); - for (i = repo->start; i < repo->end; i++) - pkgids[i - repo->start] = i; - sat_sort(pkgids, repo->end - repo->start, sizeof(Id), pkgids_sort_cmp, repo); - /* adapt order */ - for (i = repo->start; i < repo->end; i++) - { - int j = pkgids[i - repo->start]; - while (j < i) - j = pkgids[i - repo->start] = pkgids[j - repo->start]; - if (j != i) - swap_solvables(repo, data, i, j); - } - sat_free(pkgids); - } - } - else - { - Id dircache[COPYDIR_DIRCACHE_SIZE]; /* see copydir */ - - memset(dircache, 0, sizeof(dircache)); - if (db_create(&db, dbenv, 0)) - { - perror("db_create"); - exit(1); - } - if (db->open(db, 0, "Name", 0, DB_UNKNOWN, DB_RDONLY, 0664)) - { - perror("db->open Name index"); - exit(1); - } - if (db->get_byteswapped(db, &byteswapped)) - { - perror("db->get_byteswapped"); - exit(1); - } - if (db->cursor(db, NULL, &dbc, 0)) - { - perror("db->cursor"); - exit(1); - } - dbidp = (unsigned char *)&dbid; - nrpmids = 0; - rpmids = 0; - while (dbc->c_get(dbc, &dbkey, &dbdata, DB_NEXT) == 0) - { - if (dbkey.size == 10 && !memcmp(dbkey.data, "gpg-pubkey", 10)) - continue; - dl = dbdata.size; - dp = dbdata.data; - while(dl >= 8) - { - if (byteswapped) - { - dbidp[0] = dp[3]; - dbidp[1] = dp[2]; - dbidp[2] = dp[1]; - dbidp[3] = dp[0]; - } - else - memcpy(dbidp, dp, 4); - rpmids = sat_extend(rpmids, nrpmids, 1, sizeof(*rpmids), 255); - rpmids[nrpmids].dbid = dbid; - rpmids[nrpmids].name = sat_malloc((int)dbkey.size + 1); - memcpy(rpmids[nrpmids].name, dbkey.data, (int)dbkey.size); - rpmids[nrpmids].name[(int)dbkey.size] = 0; - nrpmids++; - dp += 8; - dl -= 8; - } - } - dbc->c_close(dbc); - db->close(db, 0); - db = 0; - - /* sort rpmids */ - sat_sort(rpmids, nrpmids, sizeof(*rpmids), rpmids_sort_cmp, 0); - - dbidp = (unsigned char *)&dbid; - rpmheadsize = 0; - rpmhead = 0; - - /* create hash from dbid to ref */ - refmask = mkmask(ref->nsolvables); - refhash = sat_calloc(refmask + 1, sizeof(Id)); - for (i = 0; i < ref->end - ref->start; i++) - { - if (!ref->rpmdbid[i]) - continue; - h = ref->rpmdbid[i] & refmask; - while (refhash[h]) - h = (h + 317) & refmask; - refhash[h] = i + 1; /* make it non-zero */ - } - - /* count the misses, they will cost us time */ - if ((flags & RPMDB_REPORT_PROGRESS) != 0) - { - for (i = 0, rp = rpmids; i < nrpmids; i++, rp++) - { - dbid = rp->dbid; - if (refhash) - { - h = dbid & refmask; - while ((id = refhash[h])) - { - if (ref->rpmdbid[id - 1] == dbid) - break; - h = (h + 317) & refmask; - } - if (id) - continue; - } - count++; - } - } - - s = pool_id2solvable(pool, repo_add_solvable_block(repo, nrpmids)); - if (!repo->rpmdbid) - repo->rpmdbid = repo_sidedata_create(repo, sizeof(Id)); - - for (i = 0, rp = rpmids; i < nrpmids; i++, rp++, s++) - { - dbid = rp->dbid; - repo->rpmdbid[(s - pool->solvables) - repo->start] = dbid; - if (refhash) - { - h = dbid & refmask; - while ((id = refhash[h])) - { - if (ref->rpmdbid[id - 1] == dbid) - break; - h = (h + 317) & refmask; - } - if (id) - { - Solvable *r = ref->pool->solvables + ref->start + (id - 1); - if (r->repo == ref) - { - solvable_copy(s, r, data, dircache); - continue; - } - } - } - if (!db) - { - if (db_create(&db, dbenv, 0)) - { - perror("db_create"); - exit(1); - } - if (db->open(db, 0, "Packages", 0, DB_UNKNOWN, DB_RDONLY, 0664)) - { - perror("db->open var/lib/rpm/Packages"); - exit(1); - } - if (db->get_byteswapped(db, &byteswapped)) - { - perror("db->get_byteswapped"); - exit(1); - } - } - if (byteswapped) - { - buf[0] = dbidp[3]; - buf[1] = dbidp[2]; - buf[2] = dbidp[1]; - buf[3] = dbidp[0]; - } - else - memcpy(buf, dbidp, 4); - dbkey.data = buf; - dbkey.size = 4; - dbdata.data = 0; - dbdata.size = 0; - if (db->get(db, NULL, &dbkey, &dbdata, 0)) - { - perror("db->get"); - fprintf(stderr, "corrupt rpm database, key %d not found\n", dbid); - fprintf(stderr, "please run 'rpm --rebuilddb' to recreate the database index files\n"); - exit(1); - } - if (dbdata.size < 8) - { - fprintf(stderr, "corrupt rpm database (size)\n"); - exit(1); - } - if (dbdata.size > rpmheadsize) - { - rpmheadsize = dbdata.size + 128; - rpmhead = sat_realloc(rpmhead, sizeof(*rpmhead) + rpmheadsize); - } - memcpy(buf, dbdata.data, 8); - rpmhead->cnt = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; - rpmhead->dcnt = buf[4] << 24 | buf[5] << 16 | buf[6] << 8 | buf[7]; - if (8 + rpmhead->cnt * 16 + rpmhead->dcnt > dbdata.size) - { - fprintf(stderr, "corrupt rpm database (data size)\n"); - exit(1); - } - memcpy(rpmhead->data, (unsigned char *)dbdata.data + 8, rpmhead->cnt * 16 + rpmhead->dcnt); - rpmhead->dp = rpmhead->data + rpmhead->cnt * 16; - - rpm2solv(pool, repo, data, s, rpmhead); - if ((flags & RPMDB_REPORT_PROGRESS) != 0) - { - if (done < count) - done++; - if (done < count && (done - 1) * 100 / count != done * 100 / count) - pool_debug(pool, SAT_ERROR, "%%%% %d\n", done * 100 / count); - } - } - - if (refhash) - sat_free(refhash); - if (rpmids) - { - for (i = 0; i < nrpmids; i++) - sat_free(rpmids[i].name); - sat_free(rpmids); - } - } - if (db) - db->close(db, 0); - dbenv->close(dbenv, 0); - if (rpmhead) - sat_free(rpmhead); - if (!(flags & REPO_NO_INTERNALIZE)) - repodata_internalize(data); - if ((flags & RPMDB_REPORT_PROGRESS) != 0) - pool_debug(pool, SAT_ERROR, "%%%% 100\n"); - POOL_DEBUG(SAT_DEBUG_STATS, "repo_add_rpmdb took %d ms\n", sat_timems(now)); - POOL_DEBUG(SAT_DEBUG_STATS, "repo size: %d solvables\n", repo->nsolvables); - POOL_DEBUG(SAT_DEBUG_STATS, "repo memory used: %d K incore, %d K idarray\n", data->incoredatalen/1024, repo->idarraysize / (int)(1024/sizeof(Id))); -} - - -static inline unsigned int -getu32(unsigned char *dp) -{ - return dp[0] << 24 | dp[1] << 16 | dp[2] << 8 | dp[3]; -} - - -void -repo_add_rpms(Repo *repo, const char **rpms, int nrpms, int flags) -{ - int i, sigdsize, sigcnt, l; - Pool *pool = repo->pool; - Solvable *s; - RpmHead *rpmhead = 0; - int rpmheadsize = 0; - char *payloadformat; - FILE *fp; - unsigned char lead[4096]; - int headerstart, headerend; - struct stat stb; - Repodata *data; - - if (!(flags & REPO_REUSE_REPODATA)) - data = repo_add_repodata(repo, 0); - else - data = repo_last_repodata(repo); - - if (nrpms <= 0) - return; - - for (i = 0; i < nrpms; i++) - { - if ((fp = fopen(rpms[i], "r")) == 0) - { - perror(rpms[i]); - continue; - } - if (fstat(fileno(fp), &stb)) - { - perror("stat"); - continue; - } - if (fread(lead, 96 + 16, 1, fp) != 1 || getu32(lead) != 0xedabeedb) - { - fprintf(stderr, "%s: not a rpm\n", rpms[i]); - fclose(fp); - continue; - } - if (lead[78] != 0 || lead[79] != 5) - { - fprintf(stderr, "%s: not a V5 header\n", rpms[i]); - fclose(fp); - continue; - } - if (getu32(lead + 96) != 0x8eade801) - { - fprintf(stderr, "%s: bad signature header\n", rpms[i]); - fclose(fp); - continue; - } - sigcnt = getu32(lead + 96 + 8); - sigdsize = getu32(lead + 96 + 12); - if (sigcnt >= 0x4000000 || sigdsize >= 0x40000000) - { - fprintf(stderr, "%s: bad signature header\n", rpms[i]); - fclose(fp); - continue; - } - sigdsize += sigcnt * 16; - sigdsize = (sigdsize + 7) & ~7; - headerstart = 96 + 16 + sigdsize; - while (sigdsize) - { - l = sigdsize > 4096 ? 4096 : sigdsize; - if (fread(lead, l, 1, fp) != 1) - { - fprintf(stderr, "%s: unexpected EOF\n", rpms[i]); - fclose(fp); - continue; - } - sigdsize -= l; - } - if (fread(lead, 16, 1, fp) != 1) - { - fprintf(stderr, "%s: unexpected EOF\n", rpms[i]); - fclose(fp); - continue; - } - if (getu32(lead) != 0x8eade801) - { - fprintf(stderr, "%s: bad header\n", rpms[i]); - fclose(fp); - continue; - } - sigcnt = getu32(lead + 8); - sigdsize = getu32(lead + 12); - if (sigcnt >= 0x4000000 || sigdsize >= 0x40000000) - { - fprintf(stderr, "%s: bad header\n", rpms[i]); - fclose(fp); - continue; - } - l = sigdsize + sigcnt * 16; - headerend = headerstart + 16 + l; - if (l > rpmheadsize) - { - rpmheadsize = l + 128; - rpmhead = sat_realloc(rpmhead, sizeof(*rpmhead) + rpmheadsize); - } - if (fread(rpmhead->data, l, 1, fp) != 1) - { - fprintf(stderr, "%s: unexpected EOF\n", rpms[i]); - fclose(fp); - continue; - } - rpmhead->cnt = sigcnt; - rpmhead->dcnt = sigdsize; - rpmhead->dp = rpmhead->data + rpmhead->cnt * 16; - if (headexists(rpmhead, TAG_PATCHESNAME)) - { - /* this is a patch rpm, ignore */ - fclose(fp); - continue; - } - payloadformat = headstring(rpmhead, TAG_PAYLOADFORMAT); - if (payloadformat && !strcmp(payloadformat, "drpm")) - { - /* this is a delta rpm */ - fclose(fp); - continue; - } - fclose(fp); - s = pool_id2solvable(pool, repo_add_solvable(repo)); - rpm2solv(pool, repo, data, s, rpmhead); - if (data) - { - Id handle = s - pool->solvables; - repodata_set_location(data, handle, 0, 0, rpms[i]); - repodata_set_num(data, handle, SOLVABLE_DOWNLOADSIZE, (unsigned int)((stb.st_size + 1023) / 1024)); - repodata_set_num(data, handle, SOLVABLE_HEADEREND, headerend); - } - } - if (rpmhead) - sat_free(rpmhead); - if (!(flags & REPO_NO_INTERNALIZE)) - repodata_internalize(data); -} - -static inline void -linkhash(const char *lt, char *hash) -{ - unsigned int r = 0; - const unsigned char *str = (const unsigned char *)lt; - int l, c; - - l = strlen(lt); - while ((c = *str++) != 0) - r += (r << 3) + c; - sprintf(hash, "%08x", r); - sprintf(hash + 8, "%08x", l); - sprintf(hash + 16, "%08x", 0); - sprintf(hash + 24, "%08x", 0); -} - -void -rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char *, int, const char *), void *cbdata) -{ - RpmHead *rpmhead = rpmhandle; - char **bn; - char **dn; - char **md = 0; - char **lt = 0; - unsigned int *di, diidx; - unsigned int lastdir; - int lastdirl; - unsigned int *fm; - int cnt, dcnt, cnt2; - int i, l1, l; - char *space = 0; - int spacen = 0; - char md5[33], *md5p = 0; - - dn = headstringarray(rpmhead, TAG_DIRNAMES, &dcnt); - if (!dn) - return; - if ((flags & RPM_ITERATE_FILELIST_ONLYDIRS) != 0) - { - for (i = 0; i < dcnt; i++) - (*cb)(cbdata, dn[i], 0, (char *)0); - sat_free(dn); - return; - } - bn = headstringarray(rpmhead, TAG_BASENAMES, &cnt); - if (!bn) - { - sat_free(dn); - return; - } - di = headint32array(rpmhead, TAG_DIRINDEXES, &cnt2); - if (!di || cnt != cnt2) - { - sat_free(di); - sat_free(bn); - sat_free(dn); - return; - } - fm = headint16array(rpmhead, TAG_FILEMODES, &cnt2); - if (!fm || cnt != cnt2) - { - sat_free(fm); - sat_free(di); - sat_free(bn); - sat_free(dn); - return; - } - if ((flags & RPM_ITERATE_FILELIST_WITHMD5) != 0) - { - md = headstringarray(rpmhead, TAG_FILEMD5S, &cnt2); - if (!md || cnt != cnt2) - { - sat_free(md); - sat_free(fm); - sat_free(di); - sat_free(bn); - sat_free(dn); - return; - } - } - lastdir = dcnt; - lastdirl = 0; - for (i = 0; i < cnt; i++) - { - diidx = di[i]; - if (diidx >= dcnt) - continue; - l1 = lastdir == diidx ? lastdirl : strlen(dn[diidx]); - if (l1 == 0) - continue; - l = l1 + strlen(bn[i]) + 1; - if (l > spacen) - { - spacen = l + 16; - space = sat_realloc(space, spacen); - } - if (lastdir != diidx) - { - strcpy(space, dn[diidx]); - lastdir = diidx; - lastdirl = l1; - } - strcpy(space + l1, bn[i]); - if (md) - { - md5p = md[i]; - if (S_ISLNK(fm[i])) - { - md5p = 0; - if (!lt) - { - lt = headstringarray(rpmhead, TAG_FILELINKTOS, &cnt2); - if (cnt != cnt2) - lt = sat_free(lt); - } - if (lt) - { - linkhash(lt[i], md5); - md5p = md5; - } - } - if (!md5p) - md5p = ""; - } - (*cb)(cbdata, space, fm[i], md5p); - } - sat_free(space); - sat_free(lt); - sat_free(md); - sat_free(fm); - sat_free(di); - sat_free(bn); - sat_free(dn); -} - - -struct rpm_by_state { - RpmHead *rpmhead; - int rpmheadsize; - - int dbopened; - DB_ENV *dbenv; - DB *db; - int byteswapped; -}; - -int -rpm_installedrpmdbids(const char *rootdir, Queue *rpmdbidq) -{ - char dbpath[PATH_MAX]; - DB_ENV *dbenv = 0; - DB *db = 0; - DBC *dbc = 0; - int byteswapped; - DBT dbkey; - DBT dbdata; - Id rpmdbid; - unsigned char *dp; - int dl, cnt; - - if (rpmdbidq) - queue_empty(rpmdbidq); - cnt = 0; - - if (db_env_create(&dbenv, 0)) - { - perror("db_env_create"); - return 0; - } - snprintf(dbpath, PATH_MAX, "%s/var/lib/rpm", rootdir ? rootdir : ""); -#ifdef FEDORA - if (dbenv->open(dbenv, dbpath, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL, 0)) -#else - if (dbenv->open(dbenv, dbpath, DB_CREATE|DB_PRIVATE|DB_INIT_MPOOL, 0)) -#endif - { - perror("dbenv open"); - dbenv->close(dbenv, 0); - return 0; - } - if (db_create(&db, dbenv, 0)) - { - perror("db_create"); - dbenv->close(dbenv, 0); - return 0; - } - if (db->open(db, 0, "Name", 0, DB_UNKNOWN, DB_RDONLY, 0664)) - { - perror("db->open Name index"); - db->close(db, 0); - dbenv->close(dbenv, 0); - return 0; - } - if (db->get_byteswapped(db, &byteswapped)) - { - perror("db->get_byteswapped"); - db->close(db, 0); - dbenv->close(dbenv, 0); - return 0; - } - if (db->cursor(db, NULL, &dbc, 0)) - { - perror("db->cursor"); - db->close(db, 0); - dbenv->close(dbenv, 0); - return 0; - } - memset(&dbkey, 0, sizeof(dbkey)); - memset(&dbdata, 0, sizeof(dbdata)); - while (dbc->c_get(dbc, &dbkey, &dbdata, DB_NEXT) == 0) - { - if (dbkey.size == 10 && !memcmp(dbkey.data, "gpg-pubkey", 10)) - continue; - dl = dbdata.size; - dp = dbdata.data; - while(dl >= 8) - { - if (byteswapped) - { - ((char *)&rpmdbid)[0] = dp[3]; - ((char *)&rpmdbid)[1] = dp[2]; - ((char *)&rpmdbid)[2] = dp[1]; - ((char *)&rpmdbid)[3] = dp[0]; - } - else - memcpy((char *)&rpmdbid, dp, 4); - if (rpmdbidq) - queue_push(rpmdbidq, rpmdbid); - cnt++; - dp += 8; - dl -= 8; - } - } - dbc->c_close(dbc); - db->close(db, 0); - dbenv->close(dbenv, 0); - return cnt; -} - -void * -rpm_byrpmdbid(Id rpmdbid, const char *rootdir, void **statep) -{ - struct rpm_by_state *state = *statep; - unsigned char buf[16]; - DBT dbkey; - DBT dbdata; - RpmHead *rpmhead; - - if (!rpmdbid) - { - /* close down */ - if (!state) - return 0; - if (state->db) - state->db->close(state->db, 0); - if (state->dbenv) - state->dbenv->close(state->dbenv, 0); - sat_free(state->rpmhead); - sat_free(state); - *statep = (void *)0; - return 0; - } - - if (!state) - { - state = sat_calloc(1, sizeof(*state)); - *statep = state; - } - if (!state->dbopened) - { - char dbpath[PATH_MAX]; - state->dbopened = 1; - if (db_env_create(&state->dbenv, 0)) - { - perror("db_env_create"); - state->dbenv = 0; - return 0; - } - if (!rootdir) - rootdir = ""; - snprintf(dbpath, PATH_MAX, "%s/var/lib/rpm", rootdir); -#ifdef FEDORA - if (state->dbenv->open(state->dbenv, dbpath, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL, 0)) -#else - if (state->dbenv->open(state->dbenv, dbpath, DB_CREATE|DB_PRIVATE|DB_INIT_MPOOL, 0)) -#endif - { - perror("dbenv open"); - state->dbenv->close(state->dbenv, 0); - state->dbenv = 0; - return 0; - } - if (db_create(&state->db, state->dbenv, 0)) - { - perror("db_create"); - state->db = 0; - state->dbenv->close(state->dbenv, 0); - state->dbenv = 0; - return 0; - } - if (state->db->open(state->db, 0, "Packages", 0, DB_UNKNOWN, DB_RDONLY, 0664)) - { - perror("db->open var/lib/rpm/Packages"); - state->db->close(state->db, 0); - state->db = 0; - state->dbenv->close(state->dbenv, 0); - state->dbenv = 0; - return 0; - } - if (state->db->get_byteswapped(state->db, &state->byteswapped)) - { - perror("db->get_byteswapped"); - state->db->close(state->db, 0); - state->db = 0; - state->dbenv->close(state->dbenv, 0); - state->dbenv = 0; - return 0; - } - } - memcpy(buf, &rpmdbid, 4); - if (state->byteswapped) - { - unsigned char bx; - bx = buf[0]; buf[0] = buf[3]; buf[3] = bx; - bx = buf[1]; buf[1] = buf[2]; buf[2] = bx; - } - memset(&dbkey, 0, sizeof(dbkey)); - memset(&dbdata, 0, sizeof(dbdata)); - dbkey.data = buf; - dbkey.size = 4; - dbdata.data = 0; - dbdata.size = 0; - if (state->db->get(state->db, NULL, &dbkey, &dbdata, 0)) - { - perror("db->get"); - return 0; - } - if (dbdata.size < 8) - { - fprintf(stderr, "corrupt rpm database (size)\n"); - return 0; - } - if (dbdata.size > state->rpmheadsize) - { - state->rpmheadsize = dbdata.size + 128; - state->rpmhead = sat_realloc(state->rpmhead, sizeof(*rpmhead) + state->rpmheadsize); - } - rpmhead = state->rpmhead; - memcpy(buf, dbdata.data, 8); - rpmhead->cnt = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; - rpmhead->dcnt = buf[4] << 24 | buf[5] << 16 | buf[6] << 8 | buf[7]; - if (8 + rpmhead->cnt * 16 + rpmhead->dcnt > dbdata.size) - { - fprintf(stderr, "corrupt rpm database (data size)\n"); - return 0; - } - memcpy(rpmhead->data, (unsigned char *)dbdata.data + 8, rpmhead->cnt * 16 + rpmhead->dcnt); - rpmhead->dp = rpmhead->data + rpmhead->cnt * 16; - return rpmhead; -} - -void * -rpm_byfp(FILE *fp, const char *name, void **statep) -{ - struct rpm_by_state *state = *statep; - int headerstart, headerend; - RpmHead *rpmhead; - int sigdsize, sigcnt, l; - unsigned char lead[4096]; - - if (!fp) - return rpm_byrpmdbid(0, 0, statep); - if (!state) - { - state = sat_calloc(1, sizeof(*state)); - *statep = state; - } - if (fread(lead, 96 + 16, 1, fp) != 1 || getu32(lead) != 0xedabeedb) - { - fprintf(stderr, "%s: not a rpm\n", name); - return 0; - } - if (lead[78] != 0 || lead[79] != 5) - { - fprintf(stderr, "%s: not a V5 header\n", name); - return 0; - } - if (getu32(lead + 96) != 0x8eade801) - { - fprintf(stderr, "%s: bad signature header\n", name); - return 0; - } - sigcnt = getu32(lead + 96 + 8); - sigdsize = getu32(lead + 96 + 12); - if (sigcnt >= 0x4000000 || sigdsize >= 0x40000000) - { - fprintf(stderr, "%s: bad signature header\n", name); - return 0; - } - sigdsize += sigcnt * 16; - sigdsize = (sigdsize + 7) & ~7; - headerstart = 96 + 16 + sigdsize; - while (sigdsize) - { - l = sigdsize > 4096 ? 4096 : sigdsize; - if (fread(lead, l, 1, fp) != 1) - { - fprintf(stderr, "%s: unexpected EOF\n", name); - return 0; - } - sigdsize -= l; - } - if (fread(lead, 16, 1, fp) != 1) - { - fprintf(stderr, "%s: unexpected EOF\n", name); - return 0; - } - if (getu32(lead) != 0x8eade801) - { - fprintf(stderr, "%s: bad header\n", name); - fclose(fp); - return 0; - } - sigcnt = getu32(lead + 8); - sigdsize = getu32(lead + 12); - if (sigcnt >= 0x4000000 || sigdsize >= 0x40000000) - { - fprintf(stderr, "%s: bad header\n", name); - fclose(fp); - return 0; - } - l = sigdsize + sigcnt * 16; - headerend = headerstart + 16 + l; - if (l > state->rpmheadsize) - { - state->rpmheadsize = l + 128; - state->rpmhead = sat_realloc(state->rpmhead, sizeof(*state->rpmhead) + state->rpmheadsize); - } - rpmhead = state->rpmhead; - if (fread(rpmhead->data, l, 1, fp) != 1) - { - fprintf(stderr, "%s: unexpected EOF\n", name); - fclose(fp); - return 0; - } - rpmhead->cnt = sigcnt; - rpmhead->dcnt = sigdsize; - rpmhead->dp = rpmhead->data + rpmhead->cnt * 16; - return rpmhead; -} - diff --git a/tools/repo_rpmdb.h b/tools/repo_rpmdb.h deleted file mode 100644 index 3e80302..0000000 --- a/tools/repo_rpmdb.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2007-2008, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -#include "queue.h" - -extern void repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir, int flags); -extern void repo_add_rpms(Repo *repo, const char **rpms, int nrpms, int flags); - -#define RPMDB_REPORT_PROGRESS (1 << 8) - -#define RPM_ITERATE_FILELIST_ONLYDIRS (1 << 0) -#define RPM_ITERATE_FILELIST_WITHMD5 (1 << 1) - -void *rpm_byrpmdbid(Id rpmdbid, const char *rootdir, void **statep); -void *rpm_byfp(FILE *fp, const char *name, void **statep); -void rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char *, int, const char *), void *cbdata); -int rpm_installedrpmdbids(const char *rootdir, Queue *rpmdbidq); diff --git a/tools/repo_rpmmd.c b/tools/repo_rpmmd.c deleted file mode 100644 index 18dbf70..0000000 --- a/tools/repo_rpmmd.c +++ /dev/null @@ -1,1158 +0,0 @@ -/* - * Copyright (c) 2007, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -#include <sys/types.h> -#include <limits.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <expat.h> - -#include "pool.h" -#include "repo.h" -#define DISABLE_SPLIT -#include "tools_util.h" -#include "repo_rpmmd.h" - - -enum state { - STATE_START, - - STATE_SOLVABLE, - - STATE_NAME, - STATE_ARCH, - STATE_VERSION, - - // package rpm-md - STATE_LOCATION, - STATE_CHECKSUM, - STATE_RPM_GROUP, - STATE_RPM_LICENSE, - - /* resobject attributes */ - STATE_SUMMARY, - STATE_DESCRIPTION, - STATE_DISTRIBUTION, - STATE_PACKAGER, - STATE_URL, - STATE_INSNOTIFY, - STATE_DELNOTIFY, - STATE_VENDOR, - STATE_SIZE, - STATE_TIME, - STATE_DOWNLOADSIZE, - STATE_INSTALLTIME, - STATE_INSTALLONLY, - - /* Novell/SUSE extended attributes */ - STATE_EULA, - STATE_KEYWORD, - STATE_DISKUSAGE, - STATE_DIRS, - STATE_DIR, - - /* patch */ - STATE_ID, - STATE_TIMESTAMP, - STATE_AFFECTSPKG, - STATE_REBOOTNEEDED, - - // pattern attributes - STATE_CATEGORY, /* pattern and patches */ - STATE_SCRIPT, - STATE_ICON, - STATE_USERVISIBLE, - STATE_DEFAULT, - STATE_INSTALL_TIME, - - /* product */ - STATE_SHORTNAME, - STATE_DISTNAME, // obsolete - STATE_DISTEDITION, // obsolete - STATE_SOURCE, - STATE_TYPE, - STATE_RELNOTESURL, - STATE_UPDATEURL, - STATE_OPTIONALURL, - STATE_FLAG, - - /* rpm-md dependencies inside the - format tag */ - STATE_PROVIDES, - STATE_REQUIRES, - STATE_OBSOLETES, - STATE_CONFLICTS, - STATE_RECOMMENDS, - STATE_SUPPLEMENTS, - STATE_SUGGESTS, - STATE_ENHANCES, - STATE_FRESHENS, - STATE_SOURCERPM, - STATE_HEADERRANGE, - - STATE_PROVIDESENTRY, - STATE_REQUIRESENTRY, - STATE_OBSOLETESENTRY, - STATE_CONFLICTSENTRY, - STATE_RECOMMENDSENTRY, - STATE_SUPPLEMENTSENTRY, - STATE_SUGGESTSENTRY, - STATE_ENHANCESENTRY, - STATE_FRESHENSENTRY, - - STATE_FILE, - - // general - NUMSTATES -}; - -struct stateswitch { - enum state from; - char *ename; - enum state to; - int docontent; -}; - -static struct stateswitch stateswitches[] = { - /** fake tag used to enclose 2 different xml files in one **/ - { STATE_START, "rpmmd", STATE_START, 0 }, - - /** tags for different package data, we just ignore the tag **/ - { STATE_START, "metadata", STATE_START, 0 }, - { STATE_START, "otherdata", STATE_START, 0 }, - { STATE_START, "diskusagedata", STATE_START, 0 }, - { STATE_START, "susedata", STATE_START, 0 }, - - { STATE_START, "product", STATE_SOLVABLE, 0 }, - { STATE_START, "pattern", STATE_SOLVABLE, 0 }, - { STATE_START, "patch", STATE_SOLVABLE, 0 }, - { STATE_START, "package", STATE_SOLVABLE, 0 }, - - { STATE_SOLVABLE, "name", STATE_NAME, 1 }, - { STATE_SOLVABLE, "arch", STATE_ARCH, 1 }, - { STATE_SOLVABLE, "version", STATE_VERSION, 0 }, - - // package attributes rpm-md - { STATE_SOLVABLE, "location", STATE_LOCATION, 0 }, - { STATE_SOLVABLE, "checksum", STATE_CHECKSUM, 1 }, - - /* resobject attributes */ - - { STATE_SOLVABLE, "summary", STATE_SUMMARY, 1 }, - { STATE_SOLVABLE, "description", STATE_DESCRIPTION, 1 }, - { STATE_SOLVABLE, "distribution", STATE_DISTRIBUTION, 1 }, - { STATE_SOLVABLE, "url", STATE_URL, 1 }, - { STATE_SOLVABLE, "packager", STATE_PACKAGER, 1 }, - //{ STATE_SOLVABLE, "???", STATE_INSNOTIFY, 1 }, - //{ STATE_SOLVABLE, "??", STATE_DELNOTIFY, 1 }, - { STATE_SOLVABLE, "vendor", STATE_VENDOR, 1 }, - { STATE_SOLVABLE, "size", STATE_SIZE, 0 }, - { STATE_SOLVABLE, "archive-size", STATE_DOWNLOADSIZE, 1 }, - { STATE_SOLVABLE, "install-time", STATE_INSTALLTIME, 1 }, - { STATE_SOLVABLE, "install-only", STATE_INSTALLONLY, 1 }, - { STATE_SOLVABLE, "time", STATE_TIME, 0 }, - - /* extended Novell/SUSE attributes (susedata.xml) */ - { STATE_SOLVABLE, "eula", STATE_EULA, 1 }, - { STATE_SOLVABLE, "keyword", STATE_KEYWORD, 1 }, - { STATE_SOLVABLE, "diskusage", STATE_DISKUSAGE, 0 }, - - // pattern attribute - { STATE_SOLVABLE, "script", STATE_SCRIPT, 1 }, - { STATE_SOLVABLE, "icon", STATE_ICON, 1 }, - { STATE_SOLVABLE, "uservisible", STATE_USERVISIBLE, 1 }, - { STATE_SOLVABLE, "category", STATE_CATEGORY, 1 }, - { STATE_SOLVABLE, "default", STATE_DEFAULT, 1 }, - { STATE_SOLVABLE, "install-time", STATE_INSTALL_TIME, 1 }, - - /* product attributes */ - /* note the product type is an attribute */ - { STATE_SOLVABLE, "release-notes-url", STATE_RELNOTESURL, 1 }, - { STATE_SOLVABLE, "update-url", STATE_UPDATEURL, 1 }, - { STATE_SOLVABLE, "optional-url", STATE_OPTIONALURL, 1 }, - { STATE_SOLVABLE, "flag", STATE_FLAG, 1 }, - - { STATE_SOLVABLE, "rpm:vendor", STATE_VENDOR, 1 }, - { STATE_SOLVABLE, "rpm:group", STATE_RPM_GROUP, 1 }, - { STATE_SOLVABLE, "rpm:license", STATE_RPM_LICENSE, 1 }, - - /* rpm-md dependencies */ - { STATE_SOLVABLE, "rpm:provides", STATE_PROVIDES, 0 }, - { STATE_SOLVABLE, "rpm:requires", STATE_REQUIRES, 0 }, - { STATE_SOLVABLE, "rpm:obsoletes", STATE_OBSOLETES, 0 }, - { STATE_SOLVABLE, "rpm:conflicts", STATE_CONFLICTS, 0 }, - { STATE_SOLVABLE, "rpm:recommends", STATE_RECOMMENDS , 0 }, - { STATE_SOLVABLE, "rpm:supplements", STATE_SUPPLEMENTS, 0 }, - { STATE_SOLVABLE, "rpm:suggests", STATE_SUGGESTS, 0 }, - { STATE_SOLVABLE, "rpm:enhances", STATE_ENHANCES, 0 }, - { STATE_SOLVABLE, "rpm:freshens", STATE_FRESHENS, 0 }, - { STATE_SOLVABLE, "rpm:sourcerpm", STATE_SOURCERPM, 1 }, - { STATE_SOLVABLE, "rpm:header-range", STATE_HEADERRANGE, 0 }, - { STATE_SOLVABLE, "file", STATE_FILE, 1 }, - - /* extended Novell/SUSE diskusage attributes (susedata.xml) */ - { STATE_DISKUSAGE, "dirs", STATE_DIRS, 0 }, - { STATE_DIRS, "dir", STATE_DIR, 0 }, - - { STATE_PROVIDES, "rpm:entry", STATE_PROVIDESENTRY, 0 }, - { STATE_REQUIRES, "rpm:entry", STATE_REQUIRESENTRY, 0 }, - { STATE_OBSOLETES, "rpm:entry", STATE_OBSOLETESENTRY, 0 }, - { STATE_CONFLICTS, "rpm:entry", STATE_CONFLICTSENTRY, 0 }, - { STATE_RECOMMENDS, "rpm:entry", STATE_RECOMMENDSENTRY, 0 }, - { STATE_SUPPLEMENTS, "rpm:entry", STATE_SUPPLEMENTSENTRY, 0 }, - { STATE_SUGGESTS, "rpm:entry", STATE_SUGGESTSENTRY, 0 }, - { STATE_ENHANCES, "rpm:entry", STATE_ENHANCESENTRY, 0 }, - { STATE_FRESHENS, "rpm:entry", STATE_FRESHENSENTRY, 0 }, - - { NUMSTATES} -}; - -/* maxmum initial size of - the checksum cache */ -#define MAX_CSCACHE 32768 -#define CSREALLOC_STEP 1024 - -struct parsedata { - struct parsedata_common common; - char *kind; - int depth; - enum state state; - int statedepth; - char *content; - int lcontent; - int acontent; - int docontent; - Solvable *solvable; - Offset freshens; - struct stateswitch *swtab[NUMSTATES]; - enum state sbtab[NUMSTATES]; - /* temporal to store attribute tag language */ - const char *tmplang; - const char *capkind; - // used to store tmp attributes - // while the tag ends - const char *tmpattr; - Repodata *data; - Id handle; - XML_Parser *parser; - Id (*dirs)[3]; // dirid, size, nfiles - int ndirs; - Id langcache[ID_NUM_INTERNAL]; - /** system language */ - const char *language; - - /** Hash to maps checksums to solv */ - Stringpool cspool; - /** Cache of known checksums to solvable id */ - Id *cscache; - /* the current longest index in the table */ - int ncscache; -}; - -static Id -langtag(struct parsedata *pd, Id tag, const char *language) -{ - if (language && !language[0]) - language = 0; - if (!language || tag >= ID_NUM_INTERNAL) - return pool_id2langid(pd->common.repo->pool, tag, language, 1); - return pool_id2langid(pd->common.repo->pool, tag, language, 1); - if (!pd->langcache[tag]) - pd->langcache[tag] = pool_id2langid(pd->common.repo->pool, tag, language, 1); - return pd->langcache[tag]; -} - -static int -id3_cmp (const void *v1, const void *v2, void *dp) -{ - Id *i1 = (Id*)v1; - Id *i2 = (Id*)v2; - return i1[0] - i2[0]; -} - -static void -commit_diskusage (struct parsedata *pd, unsigned handle) -{ - unsigned i; - Dirpool *dp = &pd->data->dirpool; - /* Now sort in dirid order. This ensures that parents come before - their children. */ - if (pd->ndirs > 1) - sat_sort(pd->dirs, pd->ndirs, sizeof (pd->dirs[0]), id3_cmp, 0); - /* Substract leaf numbers from all parents to make the numbers - non-cumulative. This must be done post-order (i.e. all leafs - adjusted before parents). We ensure this by starting at the end of - the array moving to the start, hence seeing leafs before parents. */ - for (i = pd->ndirs; i--;) - { - unsigned p = dirpool_parent(dp, pd->dirs[i][0]); - unsigned j = i; - for (; p; p = dirpool_parent(dp, p)) - { - for (; j--;) - if (pd->dirs[j][0] == p) - break; - if (j < pd->ndirs) - { - if (pd->dirs[j][1] < pd->dirs[i][1]) - pd->dirs[j][1] = 0; - else - pd->dirs[j][1] -= pd->dirs[i][1]; - if (pd->dirs[j][2] < pd->dirs[i][2]) - pd->dirs[j][2] = 0; - else - pd->dirs[j][2] -= pd->dirs[i][2]; - } - else - /* Haven't found this parent in the list, look further if - we maybe find the parents parent. */ - j = i; - } - } -#if 0 - char sbuf[1024]; - char *buf = sbuf; - unsigned slen = sizeof (sbuf); - for (i = 0; i < pd->ndirs; i++) - { - dir2str (attr, pd->dirs[i][0], &buf, &slen); - fprintf (stderr, "have dir %d %d %d %s\n", pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2], buf); - } - if (buf != sbuf) - free (buf); -#endif - for (i = 0; i < pd->ndirs; i++) - if (pd->dirs[i][1] || pd->dirs[i][2]) - { - repodata_add_dirnumnum(pd->data, handle, SOLVABLE_DISKUSAGE, pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2]); - } - pd->ndirs = 0; -} - - -/* - * makeevr_atts - * parse 'epoch', 'ver' and 'rel', return evr Id - * - */ - -static Id -makeevr_atts(Pool *pool, struct parsedata *pd, const char **atts) -{ - const char *e, *v, *r, *v2; - char *c; - int l; - - e = v = r = 0; - for (; *atts; atts += 2) - { - if (!strcmp(*atts, "epoch")) - e = atts[1]; - else if (!strcmp(*atts, "ver")) - v = atts[1]; - else if (!strcmp(*atts, "rel")) - r = atts[1]; - } - if (e && !strcmp(e, "0")) - e = 0; - if (v && !e) - { - for (v2 = v; *v2 >= '0' && *v2 <= '9'; v2++) - ; - if (v2 > v && *v2 == ':') - e = "0"; - } - l = 1; - if (e) - l += strlen(e) + 1; - if (v) - l += strlen(v); - if (r) - l += strlen(r) + 1; - if (l > pd->acontent) - { - pd->content = sat_realloc(pd->content, l + 256); - pd->acontent = l + 256; - } - c = pd->content; - if (e) - { - strcpy(c, e); - c += strlen(c); - *c++ = ':'; - } - if (v) - { - strcpy(c, v); - c += strlen(c); - } - if (r) - { - *c++ = '-'; - strcpy(c, r); - c += strlen(c); - } - *c = 0; - if (!*pd->content) - return 0; -#if 0 - fprintf(stderr, "evr: %s\n", pd->content); -#endif - return str2id(pool, pd->content, 1); -} - - -/* - * find_attr - * find value for xml attribute - * I: txt, name of attribute - * I: atts, list of key/value attributes - * O: pointer to value of matching key, or NULL - * - */ - -static inline const char * -find_attr(const char *txt, const char **atts) -{ - for (; *atts; atts += 2) - { - if (!strcmp(*atts, txt)) - return atts[1]; - } - return 0; -} - - -/* - * dependency relations - */ - -static char *flagtab[] = { - "GT", - "EQ", - "GE", - "LT", - "NE", - "LE" -}; - - -/* - * adddep - * parse attributes to reldep Id - * - */ - -static unsigned int -adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, const char **atts, int isreq) -{ - Id id, name, marker; - const char *n, *f, *k; - const char **a; - - n = f = k = 0; - marker = isreq ? -SOLVABLE_PREREQMARKER : 0; - for (a = atts; *a; a += 2) - { - if (!strcmp(*a, "name")) - n = a[1]; - else if (!strcmp(*a, "flags")) - f = a[1]; - else if (!strcmp(*a, "kind")) - k = a[1]; - else if (isreq && !strcmp(*a, "pre") && a[1][0] == '1') - marker = SOLVABLE_PREREQMARKER; - } - if (!n) - return olddeps; - if (k && !strcmp(k, "package")) - k = 0; - if (k) - { - int l = strlen(k) + 1 + strlen(n) + 1; - if (l > pd->acontent) - { - pd->content = sat_realloc(pd->content, l + 256); - pd->acontent = l + 256; - } - sprintf(pd->content, "%s:%s", k, n); - name = str2id(pool, pd->content, 1); - } - else - name = str2id(pool, (char *)n, 1); - if (f) - { - Id evr = makeevr_atts(pool, pd, atts); - int flags; - for (flags = 0; flags < 6; flags++) - if (!strcmp(f, flagtab[flags])) - break; - flags = flags < 6 ? flags + 1 : 0; - id = rel2id(pool, name, evr, flags, 1); - } - else - id = name; -#if 0 - fprintf(stderr, "new dep %s%s%s\n", id2str(pool, d), id2rel(pool, d), id2evr(pool, d)); -#endif - return repo_addid_dep(pd->common.repo, olddeps, id, marker); -} - - -/* - * set_desciption_author - * - */ - -static void -set_desciption_author(Repodata *data, Id handle, char *str) -{ - char *aut, *p; - - if (!str || !*str) - return; - for (aut = str; (aut = strchr(aut, '\n')) != 0; aut++) - if (!strncmp(aut, "\nAuthors:\n--------\n", 19)) - break; - if (aut) - { - /* oh my, found SUSE special author section */ - int l = aut - str; - str[l] = 0; - while (l > 0 && str[l - 1] == '\n') - str[--l] = 0; - if (l) - repodata_set_str(data, handle, SOLVABLE_DESCRIPTION, str); - p = aut + 19; - aut = str; /* copy over */ - while (*p == ' ' || *p == '\n') - p++; - while (*p) - { - if (*p == '\n') - { - *aut++ = *p++; - while (*p == ' ') - p++; - continue; - } - *aut++ = *p++; - } - while (aut != str && aut[-1] == '\n') - aut--; - *aut = 0; - if (*str) - repodata_set_str(data, handle, SOLVABLE_AUTHORS, str); - } - else if (*str) - repodata_set_str(data, handle, SOLVABLE_DESCRIPTION, str); -} - - -/* - * set_sourcerpm - * - */ - -static void -set_sourcerpm(Repodata *data, Solvable *s, Id handle, char *sourcerpm) -{ - const char *p, *sevr, *sarch, *name, *evr; - Pool *pool; - - p = strrchr(sourcerpm, '.'); - if (!p || strcmp(p, ".rpm") != 0) - return; - p--; - while (p > sourcerpm && *p != '.') - p--; - if (*p != '.' || p == sourcerpm) - return; - sarch = p-- + 1; - while (p > sourcerpm && *p != '-') - p--; - if (*p != '-' || p == sourcerpm) - return; - p--; - while (p > sourcerpm && *p != '-') - p--; - if (*p != '-' || p == sourcerpm) - return; - sevr = p + 1; - pool = s->repo->pool; - if (!strcmp(sarch, "src.rpm")) - repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, ARCH_SRC); - else if (!strcmp(sarch, "nosrc.rpm")) - repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, ARCH_NOSRC); - else - repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, strn2id(pool, sarch, strlen(sarch) - 4, 1)); - evr = id2str(pool, s->evr); - if (evr && !strncmp(sevr, evr, sarch - sevr - 1) && evr[sarch - sevr - 1] == 0) - repodata_set_void(data, handle, SOLVABLE_SOURCEEVR); - else - repodata_set_id(data, handle, SOLVABLE_SOURCEEVR, strn2id(pool, sevr, sarch - sevr - 1, 1)); - name = id2str(pool, s->name); - if (name && !strncmp(sourcerpm, name, sevr - sourcerpm - 1) && name[sevr - sourcerpm - 1] == 0) - repodata_set_void(data, handle, SOLVABLE_SOURCENAME); - else - repodata_set_id(data, handle, SOLVABLE_SOURCENAME, strn2id(pool, sourcerpm, sevr - sourcerpm - 1, 1)); -} - -/*-----------------------------------------------*/ -/* XML callbacks */ - -/* - * startElement - * XML callback - * - */ - -static void XMLCALL -startElement(void *userData, const char *name, const char **atts) -{ - //fprintf(stderr,"+tag: %s\n", name); - struct parsedata *pd = userData; - Pool *pool = pd->common.pool; - Solvable *s = pd->solvable; - struct stateswitch *sw; - const char *str; - Id handle = pd->handle; - - // fprintf(stderr, "into %s, from %d, depth %d, statedepth %d\n", name, pd->state, pd->depth, pd->statedepth); - - if (pd->depth != pd->statedepth) - { - pd->depth++; - return; - } - - if (pd->state == STATE_START && !strcmp(name, "patterns")) - return; - //if (pd->state == STATE_START && !strcmp(name, "metadata")) - // return; - if (pd->state == STATE_SOLVABLE && !strcmp(name, "format")) - return; - - pd->depth++; - if (!pd->swtab[pd->state]) - return; - for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) - if (!strcmp(sw->ename, name)) - break; - if (sw->from != pd->state) - { -#if 0 - fprintf(stderr, "into unknown: %s\n", name); -#endif - return; - } - pd->state = sw->to; - pd->docontent = sw->docontent; - pd->statedepth = pd->depth; - pd->lcontent = 0; - *pd->content = 0; - switch(pd->state) - { - case STATE_SOLVABLE: - pd->kind = 0; - if (name[2] == 't' && name[3] == 't') - pd->kind = "pattern"; - else if (name[1] == 'r') - pd->kind = "product"; - else if (name[2] == 't' && name[3] == 'c') - pd->kind = "patch"; - - /* to support extension metadata files like others.xml which - have the following structure: - - <otherdata xmlns="http://linux.duke.edu/metadata/other" - packages="101"> - <package pkgid="b78f8664cd90efe42e09a345e272997ef1b53c18" - name="zaptel-kmp-default" - arch="i586"><version epoch="0" - ver="1.2.10_2.6.22_rc4_git6_2" rel="70"/> - ... - - we need to check if the pkgid is there and if it matches - an already seen package, that means we don't need to create - a new solvable but just append the attributes to the existing - one. - */ - const char *pkgid; - if ((pkgid = find_attr("pkgid", atts)) != NULL) - { - // look at the checksum cache - Id index = stringpool_str2id(&pd->cspool, pkgid, 0); - if (!index || index >= pd->ncscache || !pd->cscache[index]) - { - fprintf(stderr, "error, the repository specifies extra information about package with checksum '%s', which does not exist in the repository.\n", pkgid); - exit(1); - } - pd->solvable = pool_id2solvable(pool, pd->cscache[index]); - } - else - { - /* this is a new package */ - pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->common.repo)); - pd->freshens = 0; - } - pd->handle = pd->solvable - pool->solvables; -#if 0 - fprintf(stderr, "package #%d\n", pd->solvable - pool->solvables); -#endif - - break; - case STATE_VERSION: - s->evr = makeevr_atts(pool, pd, atts); - break; - case STATE_PROVIDES: - s->provides = 0; - break; - case STATE_PROVIDESENTRY: - s->provides = adddep(pool, pd, s->provides, atts, 0); - break; - case STATE_REQUIRES: - s->requires = 0; - break; - case STATE_REQUIRESENTRY: - s->requires = adddep(pool, pd, s->requires, atts, 1); - break; - case STATE_OBSOLETES: - s->obsoletes = 0; - break; - case STATE_OBSOLETESENTRY: - s->obsoletes = adddep(pool, pd, s->obsoletes, atts, 0); - break; - case STATE_CONFLICTS: - s->conflicts = 0; - break; - case STATE_CONFLICTSENTRY: - s->conflicts = adddep(pool, pd, s->conflicts, atts, 0); - break; - case STATE_RECOMMENDS: - s->recommends = 0; - break; - case STATE_RECOMMENDSENTRY: - s->recommends = adddep(pool, pd, s->recommends, atts, 0); - break; - case STATE_SUPPLEMENTS: - s->supplements= 0; - break; - case STATE_SUPPLEMENTSENTRY: - s->supplements = adddep(pool, pd, s->supplements, atts, 0); - break; - case STATE_SUGGESTS: - s->suggests = 0; - break; - case STATE_SUGGESTSENTRY: - s->suggests = adddep(pool, pd, s->suggests, atts, 0); - break; - case STATE_ENHANCES: - s->enhances = 0; - break; - case STATE_ENHANCESENTRY: - s->enhances = adddep(pool, pd, s->enhances, atts, 0); - break; - case STATE_FRESHENS: - pd->freshens = 0; - break; - case STATE_FRESHENSENTRY: - pd->freshens = adddep(pool, pd, pd->freshens, atts, 0); - break; - case STATE_SUMMARY: - case STATE_DESCRIPTION: - pd->tmplang = find_attr("lang", atts); - break; - case STATE_LOCATION: - str = find_attr("href", atts); - if (str) - repodata_set_location(pd->data, handle, 0, 0, str); - break; - case STATE_CHECKSUM: - pd->tmpattr = find_attr("type", atts); - break; - case STATE_TIME: - { - unsigned int t; - str = find_attr("build", atts); - if (str && (t = atoi(str)) != 0) - repodata_set_num(pd->data, handle, SOLVABLE_BUILDTIME, t); - break; - } - case STATE_SIZE: - { - unsigned int k; - str = find_attr("installed", atts); - if (str && (k = atoi(str)) != 0) - repodata_set_num(pd->data, handle, SOLVABLE_INSTALLSIZE, (k + 1023) / 1024); - /* XXX the "package" attribute gives the size of the rpm file, - i.e. the download size. Except on packman, there it seems to be - something else entirely, it has a value near to the other two - values, as if the rpm is uncompressed. */ - str = find_attr("package", atts); - if (str && (k = atoi(str)) != 0) - repodata_set_num(pd->data, handle, SOLVABLE_DOWNLOADSIZE, (k + 1023) / 1024); - break; - } - case STATE_HEADERRANGE: - { - unsigned int end; - str = find_attr("end", atts); - if (str && (end = atoi(str)) != 0) - repodata_set_num(pd->data, handle, SOLVABLE_HEADEREND, end); - } - /* - <diskusage> - <dirs> - <dir name="/" size="56" count="11"/> - <dir name="usr/" size="56" count="11"/> - <dir name="usr/bin/" size="38" count="10"/> - <dir name="usr/share/" size="18" count="1"/> - <dir name="usr/share/doc/" size="18" count="1"/> - </dirs> - </diskusage> - */ - case STATE_DISKUSAGE: - { - /* Really, do nothing, wat for <dir> tag */ - break; - } - case STATE_DIR: - { - long filesz = 0, filenum = 0; - unsigned dirid; - if ( (str = find_attr("name", atts)) ) - { - dirid = repodata_str2dir(pd->data, str, 1); - } - else - { - fprintf( stderr, "<dir .../> tag without 'name' attribute, atts = %p, *atts = %p\n", - (void *)atts, *atts); - break; - } - if ( (str = find_attr("size", atts)) ) - { - filesz = strtol (str, 0, 0); - } - if ( (str = find_attr("count", atts)) ) - { - filenum = strtol (str, 0, 0); - } - pd->dirs = sat_extend(pd->dirs, pd->ndirs, 1, sizeof(pd->dirs[0]), 31); - pd->dirs[pd->ndirs][0] = dirid; - pd->dirs[pd->ndirs][1] = filesz; - pd->dirs[pd->ndirs][2] = filenum; - pd->ndirs++; - break; - } - default: - break; - } -} - - -/* - * endElement - * XML callback - * - */ - -static void XMLCALL -endElement(void *userData, const char *name) -{ - //fprintf(stderr,"-tag: %s\n", name); - struct parsedata *pd = userData; - Pool *pool = pd->common.pool; - Solvable *s = pd->solvable; - Repo *repo = pd->common.repo; - Id handle = pd->handle; - Id id; - char *p; - - if (pd->depth != pd->statedepth) - { - pd->depth--; - // printf("back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth); - return; - } - - /* ignore patterns & metadata */ - if (pd->state == STATE_START && !strcmp(name, "patterns")) - return; - //if (pd->state == STATE_START && !strcmp(name, "metadata")) - // return; - if (pd->state == STATE_SOLVABLE && !strcmp(name, "format")) - return; - - pd->depth--; - pd->statedepth--; - switch (pd->state) - { - case STATE_SOLVABLE: - if ( pd->kind && !s->name ) /* add namespace in case of NULL name */ - s->name = str2id(pool, join2( pd->kind, ":", ""), 1); - if (!s->arch) - s->arch = ARCH_NOARCH; - if (!s->evr) - s->evr = ID_EMPTY; /* some patterns have this */ - if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) - s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); - s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, pd->freshens); - s->conflicts = repo_fix_conflicts(repo, s->conflicts); - pd->freshens = 0; - pd->kind = 0; - break; - case STATE_NAME: - if ( pd->kind ) - s->name = str2id(pool, join2( pd->kind, ":", pd->content), 1); - else - s->name = str2id(pool, pd->content, 1); - break; - case STATE_ARCH: - s->arch = str2id(pool, pd->content, 1); - break; - case STATE_VENDOR: - s->vendor = str2id(pool, pd->content, 1); - break; - case STATE_RPM_GROUP: - repodata_set_poolstr(pd->data, handle, SOLVABLE_GROUP, pd->content); - break; - case STATE_RPM_LICENSE: - repodata_set_poolstr(pd->data, handle, SOLVABLE_LICENSE, pd->content); - break; - case STATE_CHECKSUM: - { - int l; - Id type, index; - if (!strcasecmp (pd->tmpattr, "sha") || !strcasecmp (pd->tmpattr, "sha1")) - l = SIZEOF_SHA1 * 2, type = REPOKEY_TYPE_SHA1; - else if (!strcasecmp (pd->tmpattr, "sha256")) - l = SIZEOF_SHA256 * 2, type = REPOKEY_TYPE_SHA256; - else if (!strcasecmp (pd->tmpattr, "md5")) - l = SIZEOF_MD5 * 2, type = REPOKEY_TYPE_MD5; - else - { - fprintf(stderr, "Unknown checksum type: %d: %s\n", (unsigned int)XML_GetCurrentLineNumber(*pd->parser), pd->tmpattr); - exit(1); - } - if (strlen(pd->content) != l) - { - fprintf(stderr, "Invalid checksum length: %d: for %s\n", (unsigned int)XML_GetCurrentLineNumber(*pd->parser), pd->tmpattr); - exit(1); - } - repodata_set_checksum(pd->data, handle, SOLVABLE_CHECKSUM, type, pd->content); - /* we save the checksum to solvable id relationship for extended - metadata */ - index = stringpool_str2id(&pd->cspool, pd->content, 1 /* create it */); - if (index >= pd->ncscache) - { - pd->cscache = sat_zextend(pd->cscache, pd->ncscache, index + 1 - pd->ncscache, sizeof(Id), 255); - pd->ncscache = index + 1; - } - /* add the checksum to the cache */ - pd->cscache[index] = s - pool->solvables; - break; - } - case STATE_FILE: -#if 0 - id = str2id(pool, pd->content, 1); - s->provides = repo_addid_dep(repo, s->provides, id, SOLVABLE_FILEMARKER); -#endif - if ((p = strrchr(pd->content, '/')) != 0) - { - *p++ = 0; - id = repodata_str2dir(pd->data, pd->content, 1); - } - else - { - p = pd->content; - id = 0; - } - if (!id) - id = repodata_str2dir(pd->data, "/", 1); - repodata_add_dirstr(pd->data, handle, SOLVABLE_FILELIST, id, p); - break; - case STATE_SUMMARY: - pd->tmplang = 0; - repodata_set_str(pd->data, handle, SOLVABLE_SUMMARY, pd->content); - break; - case STATE_DESCRIPTION: - pd->tmplang = 0; - set_desciption_author(pd->data, handle, pd->content); - break; - case STATE_DISTRIBUTION: - repodata_set_poolstr(pd->data, handle, SOLVABLE_DISTRIBUTION, pd->content); - break; - case STATE_URL: - if (pd->content[0]) - repodata_set_str(pd->data, handle, SOLVABLE_URL, pd->content); - break; - case STATE_PACKAGER: - if (pd->content[0]) - repodata_set_poolstr(pd->data, handle, SOLVABLE_PACKAGER, pd->content); - break; - case STATE_SOURCERPM: - set_sourcerpm(pd->data, s, handle, pd->content); - break; - case STATE_RELNOTESURL: - if (pd->content[0]) - { - repodata_add_poolstr_array(pd->data, pd->handle, PRODUCT_URL, pd->content); - repodata_add_idarray(pd->data, pd->handle, PRODUCT_URL_TYPE, str2id(pool, "releasenotes", 1)); - } - break; - case STATE_UPDATEURL: - if (pd->content[0]) - { - repodata_add_poolstr_array(pd->data, pd->handle, PRODUCT_URL, pd->content); - repodata_add_idarray(pd->data, pd->handle, PRODUCT_URL_TYPE, str2id(pool, "update", 1)); - } - break; - case STATE_OPTIONALURL: - if (pd->content[0]) - { - repodata_add_poolstr_array(pd->data, pd->handle, PRODUCT_URL, pd->content); - repodata_add_idarray(pd->data, pd->handle, PRODUCT_URL_TYPE, str2id(pool, "optional", 1)); - } - break; - case STATE_FLAG: - if (pd->content[0]) - repodata_set_poolstr(pd->data, handle, PRODUCT_FLAGS, pd->content); - break; - case STATE_EULA: - if (pd->content[0]) - repodata_set_str(pd->data, handle, langtag(pd, SOLVABLE_EULA, pd->language), pd->content); - break; - case STATE_KEYWORD: - if (pd->content[0]) - repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_KEYWORDS, pd->content); - break; - case STATE_DISKUSAGE: - if (pd->ndirs) - commit_diskusage (pd, pd->handle); - break; - default: - break; - } - pd->state = pd->sbtab[pd->state]; - pd->docontent = 0; - // fprintf(stderr, "back from known %d %d %d\n", pd->state, pd->depth, pd->statedepth); -} - - -/* - * characterData - * XML callback - * - */ - -static void XMLCALL -characterData(void *userData, const XML_Char *s, int len) -{ - struct parsedata *pd = userData; - int l; - char *c; - - if (!pd->docontent) - return; - l = pd->lcontent + len + 1; - if (l > pd->acontent) - { - pd->content = sat_realloc(pd->content, l + 256); - pd->acontent = l + 256; - } - c = pd->content + pd->lcontent; - pd->lcontent += len; - while (len-- > 0) - *c++ = *s++; - *c = 0; -} - - -/*-----------------------------------------------*/ -/* 'main' */ - -#define BUFF_SIZE 8192 - -/* - * repo_add_rpmmd - * parse rpm-md metadata (primary, others) - * - */ - -void -repo_add_rpmmd(Repo *repo, FILE *fp, const char *language, int flags) -{ - Pool *pool = repo->pool; - struct parsedata pd; - char buf[BUFF_SIZE]; - int i, l; - struct stateswitch *sw; - Repodata *data; - unsigned int now; - - now = sat_timems(0); - if (!(flags & REPO_REUSE_REPODATA)) - data = repo_add_repodata(repo, 0); - else - data = repo_last_repodata(repo); - - memset(&pd, 0, sizeof(pd)); - for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++) - { - if (!pd.swtab[sw->from]) - pd.swtab[sw->from] = sw; - pd.sbtab[sw->to] = sw->from; - } - pd.common.pool = pool; - pd.common.repo = repo; - - pd.data = data; - - pd.content = sat_malloc(256); - pd.acontent = 256; - pd.lcontent = 0; - pd.common.tmp = 0; - pd.common.tmpl = 0; - pd.kind = 0; - pd.language = language; - - /* initialize the string pool where we will store - the package checksums we know about, to get an Id - we can use in a cache */ - stringpool_init_empty(&pd.cspool); - - XML_Parser parser = XML_ParserCreate(NULL); - XML_SetUserData(parser, &pd); - pd.parser = &parser; - XML_SetElementHandler(parser, startElement, endElement); - XML_SetCharacterDataHandler(parser, characterData); - for (;;) - { - l = fread(buf, 1, sizeof(buf), fp); - if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR) - { - pool_debug(pool, SAT_FATAL, "repo_rpmmd: %s at line %u:%u\n", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser)); - exit(1); - } - if (l == 0) - break; - } - XML_ParserFree(parser); - sat_free(pd.content); - join_freemem(); - stringpool_free(&pd.cspool); - sat_free(pd.cscache); - if (!(flags & REPO_NO_INTERNALIZE)) - repodata_internalize(data); - POOL_DEBUG(SAT_DEBUG_STATS, "repo_add_rpmmd took %d ms\n", sat_timems(now)); - POOL_DEBUG(SAT_DEBUG_STATS, "repo size: %d solvables\n", repo->nsolvables); - POOL_DEBUG(SAT_DEBUG_STATS, "repo memory used: %d K incore, %d K idarray\n", data->incoredatalen/1024, repo->idarraysize / (int)(1024/sizeof(Id))); -} diff --git a/tools/repo_rpmmd.h b/tools/repo_rpmmd.h deleted file mode 100644 index 9b021b2..0000000 --- a/tools/repo_rpmmd.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (c) 2007, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -#define RPMMD_KINDS_SEPARATELY (1 << 2) - -extern void repo_add_rpmmd(Repo *repo, FILE *fp, const char *language, int flags); diff --git a/tools/repo_susetags.c b/tools/repo_susetags.c deleted file mode 100644 index 66880fc..0000000 --- a/tools/repo_susetags.c +++ /dev/null @@ -1,963 +0,0 @@ -/* - * Copyright (c) 2007, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -#include <sys/types.h> -#include <limits.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "pool.h" -#include "repo.h" -#include "tools_util.h" -#include "repo_susetags.h" - -struct parsedata { - char *kind; - Repo *repo; - Repodata *data; - struct parsedata_common common; - int last_found_source; - char **share_with; - int nshare; - Id (*dirs)[3]; // dirid, size, nfiles - int ndirs; - Id langcache[ID_NUM_INTERNAL]; - int lineno; -}; - -static char *flagtab[] = { - ">", - "=", - ">=", - "<", - "!=", - "<=" -}; - - -static Id -langtag(struct parsedata *pd, Id tag, const char *language) -{ - if (language && !language[0]) - language = 0; - if (!language || tag >= ID_NUM_INTERNAL) - return pool_id2langid(pd->repo->pool, tag, language, 1); - return pool_id2langid(pd->repo->pool, tag, language, 1); - if (!pd->langcache[tag]) - pd->langcache[tag] = pool_id2langid(pd->repo->pool, tag, language, 1); - return pd->langcache[tag]; -} - -/* - * adddep - * create and add dependency - */ - -static unsigned int -adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, char *line, Id marker, char *kind) -{ - int i, flags; - Id id, evrid; - char *sp[4]; - - if (line[6] == '/') - { - /* A file dependency. Do not try to parse it */ - id = str2id(pool, line + 6, 1); - } - else - { - i = split(line + 6, sp, 4); /* name, <op>, evr, ? */ - if (i != 1 && i != 3) /* expect either 'name' or 'name' <op> 'evr' */ - { - pool_debug(pool, SAT_FATAL, "susetags: bad dependency line: %d: %s\n", pd->lineno, line); - exit(1); - } - if (kind) - id = str2id(pool, join2(kind, ":", sp[0]), 1); - else - id = str2id(pool, sp[0], 1); - if (i == 3) - { - evrid = makeevr(pool, sp[2]); - for (flags = 0; flags < 6; flags++) - if (!strcmp(sp[1], flagtab[flags])) - break; - if (flags == 6) - { - pool_debug(pool, SAT_FATAL, "susetags: unknown relation in %d: '%s'\n", pd->lineno, sp[1]); - exit(1); - } - id = rel2id(pool, id, evrid, flags + 1, 1); - } - } - return repo_addid_dep(pd->repo, olddeps, id, marker); -} - - -/* - * add_source - * - */ - -static void -add_source(struct parsedata *pd, char *line, Solvable *s, Id handle) -{ - Repo *repo = s->repo; - Pool *pool = repo->pool; - char *sp[5]; - - if (split(line, sp, 5) != 4) - { - pool_debug(pool, SAT_FATAL, "susetags: bad source line: %d: %s\n", pd->lineno, line); - exit(1); - } - - Id name = str2id(pool, sp[0], 1); - Id evr = makeevr(pool, join2(sp[1], "-", sp[2])); - Id arch = str2id(pool, sp[3], 1); - /* XXX: could record a dep here, depends on where we want to store the data */ - if (name == s->name) - repodata_set_void(pd->data, handle, SOLVABLE_SOURCENAME); - else - repodata_set_id(pd->data, handle, SOLVABLE_SOURCENAME, name); - if (evr == s->evr) - repodata_set_void(pd->data, handle, SOLVABLE_SOURCEEVR); - else - repodata_set_id(pd->data, handle, SOLVABLE_SOURCEEVR, evr); - repodata_set_constantid(pd->data, handle, SOLVABLE_SOURCEARCH, arch); -} - -/* - * add_dirline - * add a line with directory information - * - */ - -static void -add_dirline(struct parsedata *pd, char *line) -{ - char *sp[6]; - if (split(line, sp, 6) != 5) - return; - pd->dirs = sat_extend(pd->dirs, pd->ndirs, 1, sizeof(pd->dirs[0]), 31); - long filesz = strtol(sp[1], 0, 0); - filesz += strtol(sp[2], 0, 0); - long filenum = strtol(sp[3], 0, 0); - filenum += strtol(sp[4], 0, 0); - /* hack: we know that there's room for a / */ - if (*sp[0] != '/') - *--sp[0] = '/'; - unsigned dirid = repodata_str2dir(pd->data, sp[0], 1); -#if 0 -fprintf(stderr, "%s -> %d\n", sp[0], dirid); -#endif - pd->dirs[pd->ndirs][0] = dirid; - pd->dirs[pd->ndirs][1] = filesz; - pd->dirs[pd->ndirs][2] = filenum; - pd->ndirs++; -} - -static void -set_checksum(struct parsedata *pd, Repodata *data, Id handle, Id keyname, char *line) -{ - char *sp[3]; - int l; - Id type; - if (split(line, sp, 3) != 2) - { - pool_debug(pd->repo->pool, SAT_FATAL, "susetags: bad checksum line: %d: %s\n", pd->lineno, line); - exit(1); - } - if (!strcasecmp(sp[0], "sha1")) - l = SIZEOF_SHA1 * 2, type = REPOKEY_TYPE_SHA1; - else if (!strcasecmp(sp[0], "sha256")) - l = SIZEOF_SHA256 * 2, type = REPOKEY_TYPE_SHA256; - else if (!strcasecmp(sp[0], "md5")) - l = SIZEOF_MD5 * 2, type = REPOKEY_TYPE_MD5; - else - { - pool_debug(pd->repo->pool, SAT_FATAL, "susetags: unknown checksum type: %d: %s\n", pd->lineno, sp[0]); - exit(1); - } - if (strlen(sp[1]) != l) - { - pool_debug(pd->repo->pool, SAT_FATAL, "susetags: bad checksum length: %d: for %s: %s\n", pd->lineno, sp[0], sp[1]); - exit(1); - } - repodata_set_checksum(data, handle, keyname, type, sp[1]); -} - -/* - * id3_cmp - * compare - * - */ - -static int -id3_cmp(const void *v1, const void *v2, void *dp) -{ - Id *i1 = (Id*)v1; - Id *i2 = (Id*)v2; - return i1[0] - i2[0]; -} - - -/* - * commit_diskusage - * - */ - -static void -commit_diskusage(struct parsedata *pd, Id handle) -{ - unsigned i; - Dirpool *dp = &pd->data->dirpool; - /* Now sort in dirid order. This ensures that parents come before - their children. */ - if (pd->ndirs > 1) - sat_sort(pd->dirs, pd->ndirs, sizeof(pd->dirs[0]), id3_cmp, 0); - /* Substract leaf numbers from all parents to make the numbers - non-cumulative. This must be done post-order (i.e. all leafs - adjusted before parents). We ensure this by starting at the end of - the array moving to the start, hence seeing leafs before parents. */ - for (i = pd->ndirs; i--;) - { - unsigned p = dirpool_parent(dp, pd->dirs[i][0]); - unsigned j = i; - for (; p; p = dirpool_parent(dp, p)) - { - for (; j--;) - if (pd->dirs[j][0] == p) - break; - if (j < pd->ndirs) - { - if (pd->dirs[j][1] < pd->dirs[i][1]) - pd->dirs[j][1] = 0; - else - pd->dirs[j][1] -= pd->dirs[i][1]; - if (pd->dirs[j][2] < pd->dirs[i][2]) - pd->dirs[j][2] = 0; - else - pd->dirs[j][2] -= pd->dirs[i][2]; - } - else - /* Haven't found this parent in the list, look further if - we maybe find the parents parent. */ - j = i; - } - } -#if 0 - char sbuf[1024]; - char *buf = sbuf; - unsigned slen = sizeof(sbuf); - for (i = 0; i < pd->ndirs; i++) - { - dir2str(attr, pd->dirs[i][0], &buf, &slen); - fprintf(stderr, "have dir %d %d %d %s\n", pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2], buf); - } - if (buf != sbuf) - free (buf); -#endif - for (i = 0; i < pd->ndirs; i++) - if (pd->dirs[i][1] || pd->dirs[i][2]) - { - repodata_add_dirnumnum(pd->data, handle, SOLVABLE_DISKUSAGE, pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2]); - } - pd->ndirs = 0; -} - - -/* Unfortunately "a"[0] is no constant expression in the C languages, - so we need to pass the four characters individually :-/ */ -#define CTAG(a,b,c,d) ((unsigned)(((unsigned char)a) << 24) \ - | ((unsigned char)b << 16) \ - | ((unsigned char)c << 8) \ - | ((unsigned char)d)) - -/* - * tag_from_string - * - */ - -static inline unsigned -tag_from_string(char *cs) -{ - unsigned char *s = (unsigned char *)cs; - return ((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]); -} - - -/* - * repo_add_susetags - * Parse susetags file passed in fp, fill solvables into repo - * - * susetags is key,value based - * for short values - * =key: value - * is used - * for long (multi-line) values, - * +key: - * value - * value - * -key: - * is used - * - * See http://en.opensuse.org/Standards/YaST2_Repository_Metadata - * and http://en.opensuse.org/Standards/YaST2_Repository_Metadata/packages - * and http://en.opensuse.org/Standards/YaST2_Repository_Metadata/pattern - * - * Assumptions: - * All keys have 3 characters and end in ':' - */ - -static void -finish_solvable(struct parsedata *pd, Solvable *s, Id handle, Offset freshens) -{ - Pool *pool = pd->repo->pool; - -#if 1 - /* move file provides to filelist */ - /* relies on the fact that rpm inserts self-provides at the end */ - if (s->provides) - { - Id *p, *lastreal, did; - const char *str, *sp; - lastreal = pd->repo->idarraydata + s->provides; - for (p = lastreal; *p; p++) - if (ISRELDEP(*p)) - lastreal = p + 1; - for (p = lastreal; *p; p++) - { - str = id2str(pool, *p); - if (*str != '/') - lastreal = p + 1; - } - if (*lastreal) - { - for (p = lastreal; *p; p++) - { - char fname_buf[128]; - const char *fname; - str = id2str(pool, *p); - sp = strrchr(str, '/'); - /* Need to copy filename now, before we add string that could - realloc the stringspace (and hence invalidate str). */ - fname = sp + 1; - if (strlen(fname) >= 128) - fname = strdup(fname); - else - { - memcpy(fname_buf, fname, strlen(fname) + 1); - fname = fname_buf; - } - if (sp - str >= 128) - { - char *sdup = strdup(str); - sdup[sp - str] = 0; - did = repodata_str2dir(pd->data, sdup, 1); - free(sdup); - } - else - { - char sdup[128]; - strncpy(sdup, str, sp - str); - sdup[sp - str] = 0; - did = repodata_str2dir(pd->data, sdup, 1); - } - if (!did) - did = repodata_str2dir(pd->data, "/", 1); - repodata_add_dirstr(pd->data, handle, SOLVABLE_FILELIST, did, fname); - if (fname != fname_buf) - free((char*)fname); - *p = 0; - } - } - } -#endif - /* A self provide, except for source packages. This is harmless - to do twice (in case we see the same package twice). */ - if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) - s->provides = repo_addid_dep(pd->repo, s->provides, - rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); - /* XXX This uses repo_addid_dep internally, so should also be - harmless to do twice. */ - s->supplements = repo_fix_supplements(pd->repo, s->provides, s->supplements, freshens); - s->conflicts = repo_fix_conflicts(pd->repo, s->conflicts); - if (pd->ndirs) - commit_diskusage(pd, handle); -} - - -/* - * parse susetags - * - * fp: file to read from - * product: solvable representing the product (0 if none) - * language: current language (0 if none) - * flags: flags - */ - -void -repo_add_susetags(Repo *repo, FILE *fp, Id product, const char *language, int flags) -{ - Pool *pool = repo->pool; - char *line, *linep; - int aline; - Solvable *s; - Offset freshens; - int intag = 0; - int cummulate = 0; - int indesc = 0; - int last_found_pack = 0; - char *sp[5]; - struct parsedata pd; - Repodata *data = 0; - Id handle = 0; - Id vendor = 0; - - if ((flags & SUSETAGS_EXTEND) && repo->nrepodata) - indesc = 1; - - if (!(flags & REPO_REUSE_REPODATA)) - data = repo_add_repodata(repo, 0); - else - data = repo_last_repodata(repo); - - if (product) - { - if (!strncmp(id2str(pool, pool->solvables[product].name), "product:", 8)) - vendor = pool->solvables[product].vendor; - } - - memset(&pd, 0, sizeof(pd)); - line = malloc(1024); - aline = 1024; - - pd.repo = pd.common.repo = repo; - pd.data = data; - pd.common.pool = pool; - - linep = line; - s = 0; - freshens = 0; - - /* - * read complete file - * - * collect values in 'struct parsedata pd' - * then build .solv (and .attr) file - */ - - for (;;) - { - unsigned tag; - char *olinep; /* old line pointer */ - char line_lang[6]; - int keylen = 3; - if (linep - line + 16 > aline) /* (re-)alloc buffer */ - { - aline = linep - line; - line = realloc(line, aline + 512); - linep = line + aline; - aline += 512; - } - if (!fgets(linep, aline - (linep - line), fp)) /* read line */ - break; - olinep = linep; - linep += strlen(linep); - if (linep == line || linep[-1] != '\n') - continue; - pd.lineno++; - *--linep = 0; - if (linep == olinep) - continue; - - if (intag) - { - /* check for multi-line value tags (+Key:/-Key:) */ - - int is_end = (linep[-intag - keylen + 1] == '-') - && (linep[-1] == ':') - && (linep == line + 1 + intag + 1 + 1 + 1 + intag + 1 || linep[-intag - keylen] == '\n'); - if (is_end - && strncmp(linep - 1 - intag, line + 1, intag)) - { - pool_debug(pool, SAT_ERROR, "susetags: Nonmatching multi-line tags: %d: '%s' '%s' %d\n", pd.lineno, linep - 1 - intag, line + 1, intag); - } - if (cummulate && !is_end) - { - *linep++ = '\n'; - continue; - } - if (cummulate && is_end) - { - linep[-intag - keylen + 1] = 0; - if (linep[-intag - keylen] == '\n') - linep[-intag - keylen] = 0; - linep = line; - intag = 0; - } - if (!cummulate && is_end) - { - intag = 0; - linep = line; - continue; - } - if (!cummulate && !is_end) - linep = line + intag + keylen; - } - else - linep = line; - - if (!intag && line[0] == '+' && line[1] && line[1] != ':') /* start of +Key:/-Key: tag */ - { - char *tagend = strchr(line, ':'); - if (!tagend) - { - pool_debug(pool, SAT_FATAL, "susetags: bad line: %d: %s\n", pd.lineno, line); - exit(1); - } - intag = tagend - (line + 1); - cummulate = 0; - switch (tag_from_string(line)) /* check if accumulation is needed */ - { - case CTAG('+', 'P', 'r', 'q'): - case CTAG('+', 'P', 'r', 'c'): - case CTAG('+', 'P', 's', 'g'): - if (!pd.kind || !(flags & SUSETAGS_KINDS_SEPARATELY)) - break; - case CTAG('+', 'D', 'e', 's'): - case CTAG('+', 'E', 'u', 'l'): - case CTAG('+', 'I', 'n', 's'): - case CTAG('+', 'D', 'e', 'l'): - case CTAG('+', 'A', 'u', 't'): - if (line[4] == ':') - cummulate = 1; - } - line[0] = '='; /* handle lines between +Key:/-Key: as =Key: */ - line[intag + keylen - 1] = ' '; - linep = line + intag + keylen; - continue; - } - if (*line == '#' || !*line) - continue; - if (! (line[0] && line[1] && line[2] && line[3] && (line[4] == ':' || line[4] == '.'))) - continue; - if (line[4] == '.') - { - char *endlang; - endlang = strchr(line + 5, ':'); - if (endlang) - { - keylen = endlang - line - 1; - strncpy(line_lang, line + 5, 5); - line_lang[endlang - line - 5] = 0; - } - } - else - line_lang[0] = 0; - tag = tag_from_string(line); - - - /* - * start of (next) package or pattern - * - * =Pkg: <name> <version> <release> <architecture> - * (=Pat: ...) - */ - - if ((tag == CTAG('=', 'P', 'k', 'g') - || tag == CTAG('=', 'P', 'a', 't'))) - { - Id name, evr, arch; - /* If we have an old solvable, complete it by filling in some - default stuff. */ - if (s) - finish_solvable(&pd, s, handle, freshens); - - /* - * define kind - */ - - pd.kind = 0; - if (line[3] == 't') - pd.kind = "pattern"; - - /* - * parse nevra - */ - - if (split(line + 5, sp, 5) != 4) - { - pool_debug(pool, SAT_FATAL, "susetags: bad line: %d: %s\n", pd.lineno, line); - exit(1); - } - /* Lookup (but don't construct) the name and arch. */ - if (pd.kind) - name = str2id(pool, join2(pd.kind, ":", sp[0]), 0); - else - name = str2id(pool, sp[0], 0); - arch = str2id(pool, sp[3], 0); - evr = makeevr(pool, join2(sp[1], "-", sp[2])); - - s = 0; - freshens = 0; - - /* Now see if we know this solvable already. If we found neither - the name nor the arch at all in this repo - there's no chance of finding the exact solvable either. */ - if (name && arch && (indesc >= 2)) - { - int n, nn; - /* Now look for a solvable with the given name,evr,arch. - Our input is structured so, that the second set of =Pkg - lines comes in roughly the same order as the first set, so we - have a hint at where to start our search, namely were we found - the last entry. */ - for (n = repo->start, nn = n + last_found_pack; n < repo->end; n++, nn++) - { - if (nn >= repo->end) - nn = repo->start; - s = pool->solvables + nn; - if (s->repo == repo && s->name == name && s->evr == evr && s->arch == arch) - break; - } - if (n == repo->end) - s = 0; - else - { - last_found_pack = nn - repo->start; - handle = nn; - } - } - - - /* And if we still don't have a solvable, create a new one. */ - if (!s) - { - s = pool_id2solvable(pool, repo_add_solvable(repo)); - last_found_pack = (s - pool->solvables) - repo->start; - if (data) - handle = s - pool->solvables; - if (name) - s->name = name; - else if (pd.kind) - s->name = str2id(pool, join2(pd.kind, ":", sp[0]), 1); - else - s->name = str2id(pool, sp[0], 1); - s->evr = evr; - if (arch) - s->arch = arch; - else - s->arch = str2id(pool, sp[3], 1); - s->vendor = vendor; /* default to product vendor */ - } - } - - /* If we have no current solvable to add to, ignore all further lines - for it. Probably invalid input data in the second set of - solvables. */ - if (indesc >= 2 && !s) - { - pool_debug(pool, SAT_ERROR, "susetags: huh %d: %s?\n", pd.lineno, line); - continue; - } - switch (tag) - { - case CTAG('=', 'P', 'r', 'v'): /* provides */ - s->provides = adddep(pool, &pd, s->provides, line, 0, pd.kind); - continue; - case CTAG('=', 'R', 'e', 'q'): /* requires */ - s->requires = adddep(pool, &pd, s->requires, line, -SOLVABLE_PREREQMARKER, pd.kind); - continue; - case CTAG('=', 'P', 'r', 'q'): /* pre-requires / packages required */ - if (pd.kind) - { - if (flags & SUSETAGS_KINDS_SEPARATELY) - repodata_set_poolstr(data, handle, str2id(pool, "solvable:must", 1), line + 6); - else - s->requires = adddep(pool, &pd, s->requires, line, 0, 0); /* patterns: a required package */ - } - else - s->requires = adddep(pool, &pd, s->requires, line, SOLVABLE_PREREQMARKER, 0); /* package: pre-requires */ - continue; - case CTAG('=', 'O', 'b', 's'): /* obsoletes */ - s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, pd.kind); - continue; - case CTAG('=', 'C', 'o', 'n'): /* conflicts */ - s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, pd.kind); - continue; - case CTAG('=', 'R', 'e', 'c'): /* recommends */ - s->recommends = adddep(pool, &pd, s->recommends, line, 0, pd.kind); - continue; - case CTAG('=', 'S', 'u', 'p'): /* supplements */ - s->supplements = adddep(pool, &pd, s->supplements, line, 0, pd.kind); - continue; - case CTAG('=', 'E', 'n', 'h'): /* enhances */ - s->enhances = adddep(pool, &pd, s->enhances, line, 0, pd.kind); - continue; - case CTAG('=', 'S', 'u', 'g'): /* suggests */ - s->suggests = adddep(pool, &pd, s->suggests, line, 0, pd.kind); - continue; - case CTAG('=', 'F', 'r', 'e'): /* freshens */ - freshens = adddep(pool, &pd, freshens, line, 0, pd.kind); - continue; - case CTAG('=', 'P', 'r', 'c'): /* packages recommended */ - if (flags & SUSETAGS_KINDS_SEPARATELY) - repodata_set_poolstr(data, handle, str2id(pool, "solvable:should", 1), line + 6); - else - s->recommends = adddep(pool, &pd, s->recommends, line, 0, 0); - continue; - case CTAG('=', 'P', 's', 'g'): /* packages suggested */ - if (flags & SUSETAGS_KINDS_SEPARATELY) - repodata_set_poolstr(data, handle, str2id(pool, "solvable:may", 1), line + 6); - else - s->suggests = adddep(pool, &pd, s->suggests, line, 0, 0); - continue; - case CTAG('=', 'P', 'c', 'n'): /* pattern: package conflicts */ - if (flags & SUSETAGS_KINDS_SEPARATELY) - fprintf(stderr, "Unsupported: pattern -> package conflicts\n"); - else - s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, 0); - continue; - case CTAG('=', 'P', 'o', 'b'): /* pattern: package obsoletes */ - if (flags & SUSETAGS_KINDS_SEPARATELY) - fprintf(stderr, "Unsupported: pattern -> package obsoletes\n"); - else - s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, 0); - continue; - case CTAG('=', 'P', 'f', 'r'): /* pattern: package freshens */ - if (flags & SUSETAGS_KINDS_SEPARATELY) - fprintf(stderr, "Unsupported: pattern -> package freshens\n"); - else - freshens = adddep(pool, &pd, freshens, line, 0, 0); - continue; - case CTAG('=', 'P', 's', 'p'): /* pattern: package supplements */ - if (flags & SUSETAGS_KINDS_SEPARATELY) - fprintf(stderr, "Unsupported: pattern -> package supplements\n"); - else - s->supplements = adddep(pool, &pd, s->supplements, line, 0, 0); - continue; - case CTAG('=', 'P', 'e', 'n'): /* pattern: package enhances */ - if (flags & SUSETAGS_KINDS_SEPARATELY) - fprintf(stderr, "Unsupported: pattern -> package enhances\n"); - else - s->enhances = adddep(pool, &pd, s->enhances, line, 0, 0); - continue; - case CTAG('=', 'V', 'e', 'r'): /* - version - */ - last_found_pack = 0; - handle = 0; - indesc++; - continue; - case CTAG('=', 'V', 'n', 'd'): /* vendor */ - s->vendor = str2id(pool, line + 6, 1); - continue; - - /* From here it's the attribute tags. */ - case CTAG('=', 'G', 'r', 'p'): - repodata_set_poolstr(data, handle, SOLVABLE_GROUP, line + 6); - continue; - case CTAG('=', 'L', 'i', 'c'): - repodata_set_poolstr(data, handle, SOLVABLE_LICENSE, line + 6); - continue; - case CTAG('=', 'L', 'o', 'c'): - { - int i = split(line + 6, sp, 3); - if (i != 2 && i != 3) - { - pool_debug(pool, SAT_FATAL, "susetags: bad location line: %d: %s\n", pd.lineno, line); - exit(1); - } - repodata_set_location(data, handle, atoi(sp[0]), i == 3 ? sp[2] : id2str(pool, s->arch), sp[1]); - } - continue; - case CTAG('=', 'S', 'r', 'c'): - add_source(&pd, line + 6, s, handle); - continue; - case CTAG('=', 'S', 'i', 'z'): - if (split(line + 6, sp, 3) == 2) - { - repodata_set_num(data, handle, SOLVABLE_DOWNLOADSIZE, (unsigned int)(atoi(sp[0]) + 1023) / 1024); - repodata_set_num(data, handle, SOLVABLE_INSTALLSIZE, (unsigned int)(atoi(sp[1]) + 1023) / 1024); - } - continue; - case CTAG('=', 'T', 'i', 'm'): - { - unsigned int t = atoi(line + 6); - if (t) - repodata_set_num(data, handle, SOLVABLE_BUILDTIME, t); - } - continue; - case CTAG('=', 'K', 'w', 'd'): - repodata_add_poolstr_array(data, handle, SOLVABLE_KEYWORDS, line + 6); - continue; - case CTAG('=', 'A', 'u', 't'): - repodata_set_str(data, handle, SOLVABLE_AUTHORS, line + 6); - continue; - case CTAG('=', 'S', 'u', 'm'): - repodata_set_str(data, handle, langtag(&pd, SOLVABLE_SUMMARY, language ? language : line_lang), line + 3 + keylen ); - continue; - case CTAG('=', 'D', 'e', 's'): - repodata_set_str(data, handle, langtag(&pd, SOLVABLE_DESCRIPTION, language ? language : line_lang), line + 3 + keylen ); - continue; - case CTAG('=', 'E', 'u', 'l'): - repodata_set_str(data, handle, langtag(&pd, SOLVABLE_EULA, language), line + 6); - continue; - case CTAG('=', 'I', 'n', 's'): - repodata_set_str(data, handle, langtag(&pd, SOLVABLE_MESSAGEINS, language), line + 6); - continue; - case CTAG('=', 'D', 'e', 'l'): - repodata_set_str(data, handle, langtag(&pd, SOLVABLE_MESSAGEDEL, language), line + 6); - continue; - case CTAG('=', 'V', 'i', 's'): - { - /* Accept numbers and textual bools. */ - unsigned k; - k = atoi(line + 6); - if (k || !strcasecmp(line + 6, "true")) - repodata_set_void(data, handle, SOLVABLE_ISVISIBLE ); - } - continue; - case CTAG('=', 'S', 'h', 'r'): - if (last_found_pack >= pd.nshare) - { - pd.share_with = sat_realloc2(pd.share_with, last_found_pack + 256, sizeof(*pd.share_with)); - memset(pd.share_with + pd.nshare, 0, (last_found_pack + 256 - pd.nshare) * sizeof(*pd.share_with)); - pd.nshare = last_found_pack + 256; - } - pd.share_with[last_found_pack] = strdup(line + 6); - continue; - case CTAG('=', 'D', 'i', 'r'): - add_dirline(&pd, line + 6); - continue; - case CTAG('=', 'C', 'a', 't'): - repodata_set_poolstr(data, handle, langtag(&pd, SOLVABLE_CATEGORY, line_lang), line + 3 + keylen); - break; - case CTAG('=', 'O', 'r', 'd'): - /* Order is a string not a number, so we can retroactively insert - new patterns in the middle, i.e. 1 < 15 < 2. */ - repodata_set_str(data, handle, SOLVABLE_ORDER, line + 6); - break; - case CTAG('=', 'I', 'c', 'o'): - repodata_set_str(data, handle, SOLVABLE_ICON, line + 6); - break; - case CTAG('=', 'E', 'x', 't'): - repodata_add_poolstr_array(data, handle, SOLVABLE_EXTENDS, join2("pattern", ":", line + 6)); - break; - case CTAG('=', 'I', 'n', 'c'): - repodata_add_poolstr_array(data, handle, SOLVABLE_INCLUDES, join2("pattern", ":", line + 6)); - break; - case CTAG('=', 'C', 'k', 's'): - set_checksum(&pd, data, handle, SOLVABLE_CHECKSUM, line + 6); - break; - case CTAG('=', 'L', 'a', 'n'): - language = strdup(line + 6); - break; - - case CTAG('=', 'F', 'l', 's'): - { - char *p = strrchr(line + 6, '/'); - Id did; - if (p && p != line + 6 && !p[1]) - { - *p = 0; - p = strrchr(line + 6, '/'); - } - if (p) - { - *p++ = 0; - did = repodata_str2dir(data, line + 6, 1); - } - else - { - p = line + 6; - did = 0; - } - if (!did) - did = repodata_str2dir(data, "/", 1); - repodata_add_dirstr(data, handle, SOLVABLE_FILELIST, did, p); - break; - } - case CTAG('=', 'H', 'd', 'r'): - /* rpm header range */ - if (split(line + 6, sp, 3) == 2) - { - /* we ignore the start value */ - unsigned int end = (unsigned int)atoi(sp[1]); - if (end) - repodata_set_num(data, handle, SOLVABLE_HEADEREND, end); - } - break; - - case CTAG('=', 'P', 'a', 't'): - case CTAG('=', 'P', 'k', 'g'): - break; - - default: - pool_debug(pool, SAT_ERROR, "susetags: unknown line: %d: %s\n", pd.lineno, line); - break; - } - - } /* for(;;) */ - - if (s) - finish_solvable(&pd, s, handle, freshens); - - /* Shared attributes - * (e.g. multiple binaries built from same source) - */ - if (pd.nshare) - { - int i, last_found; - last_found = 0; - for (i = 0; i < pd.nshare; i++) - if (pd.share_with[i]) - { - if (split(pd.share_with[i], sp, 5) != 4) - { - pool_debug(pool, SAT_FATAL, "susetags: bad =Shr line: %s\n", pd.share_with[i]); - exit(1); - } - - Id name = str2id(pool, sp[0], 1); - Id evr = makeevr(pool, join2(sp[1], "-", sp[2])); - Id arch = str2id(pool, sp[3], 1); - unsigned n, nn; - Solvable *found = 0; - for (n = repo->start, nn = repo->start + last_found; - n < repo->end; n++, nn++) - { - if (nn >= repo->end) - nn = repo->start; - found = pool->solvables + nn; - if (found->repo == repo - && found->name == name - && found->evr == evr - && found->arch == arch) - { - last_found = nn - repo->start; - break; - } - } - if (n != repo->end) - repodata_merge_attrs(data, repo->start + i, repo->start + last_found); - free(pd.share_with[i]); - } - free(pd.share_with); - } - - if (!(flags & REPO_NO_INTERNALIZE)) - repodata_internalize(data); - - if (pd.common.tmp) - free(pd.common.tmp); - free(line); - join_freemem(); -} diff --git a/tools/repo_susetags.h b/tools/repo_susetags.h deleted file mode 100644 index a617c65..0000000 --- a/tools/repo_susetags.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2007, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -/* read susetags file <fp> into <repo> - * if <attrname> given, write attributes as '<attrname>.attr' - */ - -#define SUSETAGS_KINDS_SEPARATELY (1 << 2) -#define SUSETAGS_EXTEND (1 << 3) - -extern void repo_add_susetags(Repo *repo, FILE *fp, Id product, const char *language, int flags); diff --git a/tools/repo_updateinfoxml.c b/tools/repo_updateinfoxml.c deleted file mode 100644 index 5e4b1f8..0000000 --- a/tools/repo_updateinfoxml.c +++ /dev/null @@ -1,616 +0,0 @@ -/* - * Copyright (c) 2007, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -#define _GNU_SOURCE -#include <sys/types.h> -#include <limits.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <expat.h> - -#include "pool.h" -#include "repo.h" -#include "repo_updateinfoxml.h" -#define DISABLE_SPLIT -#include "tools_util.h" - -/* - * <updates> - * <update from="rel-eng@fedoraproject.org" status="stable" type="security" version="1.4"> - * <id>FEDORA-2007-4594</id> - * <title>imlib-1.9.15-6.fc8</title> - * <release>Fedora 8</release> - * <issued date="2007-12-28 16:42:30"/> - * <references> - * <reference href="https://bugzilla.redhat.com/show_bug.cgi?id=426091" id="426091" title="CVE-2007-3568 imlib: infinite loop DoS using crafted BMP image" type="bugzilla"/> - * </references> - * <description>This update includes a fix for a denial-of-service issue (CVE-2007-3568) whereby an attacker who could get an imlib-using user to view a specially-crafted BMP image could cause the user's CPU to go into an infinite loop.</description> - * <pkglist> - * <collection short="F8"> - * <name>Fedora 8</name> - * <package arch="ppc64" name="imlib-debuginfo" release="6.fc8" src="http://download.fedoraproject.org/pub/fedora/linux/updates/8/ppc64/imlib-debuginfo-1.9.15-6.fc8.ppc64.rpm" version="1.9.15"> - * <filename>imlib-debuginfo-1.9.15-6.fc8.ppc64.rpm</filename> - * <reboot_suggested>True</reboot_suggested> - * </package> - * </collection> - * </pkglist> - * </update> - * </updates> -*/ - -enum state { - STATE_START, - STATE_UPDATES, /* 1 */ - STATE_UPDATE, /* 2 */ - STATE_ID, /* 3 */ - STATE_TITLE, /* 4 */ - STATE_RELEASE, /* 5 */ - STATE_ISSUED, /* 6 */ - STATE_MESSAGE, /* 7 */ - STATE_REFERENCES, /* 8 */ - STATE_REFERENCE, /* 9 */ - STATE_DESCRIPTION, /* 10 */ - STATE_PKGLIST, /* 11 */ - STATE_COLLECTION, /* 12 */ - STATE_NAME, /* 13 */ - STATE_PACKAGE, /* 14 */ - STATE_FILENAME, /* 15 */ - STATE_REBOOT, /* 16 */ - STATE_RESTART, /* 17 */ - STATE_RELOGIN, /* 18 */ - NUMSTATES -}; - -struct stateswitch { - enum state from; - char *ename; - enum state to; - int docontent; -}; - - -/* !! must be sorted by first column !! */ -static struct stateswitch stateswitches[] = { - { STATE_START, "updates", STATE_UPDATES, 0 }, - { STATE_START, "update", STATE_UPDATE, 0 }, - { STATE_UPDATES, "update", STATE_UPDATE, 0 }, - { STATE_UPDATE, "id", STATE_ID, 1 }, - { STATE_UPDATE, "title", STATE_TITLE, 1 }, - { STATE_UPDATE, "release", STATE_RELEASE, 1 }, - { STATE_UPDATE, "issued", STATE_ISSUED, 1 }, - { STATE_UPDATE, "description", STATE_DESCRIPTION, 1 }, - { STATE_UPDATE, "message", STATE_MESSAGE , 1 }, - { STATE_UPDATE, "references", STATE_REFERENCES, 0 }, - { STATE_UPDATE, "pkglist", STATE_PKGLIST, 0 }, - { STATE_REFERENCES, "reference", STATE_REFERENCE, 0 }, - { STATE_PKGLIST, "collection", STATE_COLLECTION, 0 }, - { STATE_COLLECTION, "name", STATE_NAME, 1 }, - { STATE_COLLECTION, "package", STATE_PACKAGE, 0 }, - { STATE_PACKAGE, "filename", STATE_FILENAME, 1 }, - { STATE_PACKAGE, "reboot_suggested",STATE_REBOOT, 1 }, - { STATE_PACKAGE, "restart_suggested",STATE_RESTART, 1 }, - { STATE_PACKAGE, "relogin_suggested",STATE_RELOGIN, 1 }, - { NUMSTATES } -}; - -struct parsedata { - int depth; - enum state state; - int statedepth; - char *content; - int lcontent; - int acontent; - int docontent; - Pool *pool; - Repo *repo; - Repodata *data; - unsigned int datanum; - Solvable *solvable; - Id collhandle; - - struct stateswitch *swtab[NUMSTATES]; - enum state sbtab[NUMSTATES]; -}; - -/* - * if we have seen a <filename>... - * inside of <package>... - * - * - * If not, we must insert an empty filename to UPDATE_COLLECTION_FILENAME - * at </package> in order to keep all UPDATE_COLLECTION_* arrays in sync - */ - -/* - * create evr (as Id) from 'epoch', 'version' and 'release' attributes - */ - -static Id -makeevr_atts(Pool *pool, struct parsedata *pd, const char **atts) -{ - const char *e, *v, *r, *v2; - char *c; - int l; - - e = v = r = 0; - for (; *atts; atts += 2) - { - if (!strcmp(*atts, "epoch")) - e = atts[1]; - else if (!strcmp(*atts, "version")) - v = atts[1]; - else if (!strcmp(*atts, "release")) - r = atts[1]; - } - if (e && !strcmp(e, "0")) - e = 0; - if (v && !e) - { - for (v2 = v; *v2 >= '0' && *v2 <= '9'; v2++) - ; - if (v2 > v && *v2 == ':') - e = "0"; - } - l = 1; - if (e) - l += strlen(e) + 1; - if (v) - l += strlen(v); - if (r) - l += strlen(r) + 1; - if (l > pd->acontent) - { - pd->content = realloc(pd->content, l + 256); - pd->acontent = l + 256; - } - c = pd->content; - if (e) - { - strcpy(c, e); - c += strlen(c); - *c++ = ':'; - } - if (v) - { - strcpy(c, v); - c += strlen(c); - } - if (r) - { - *c++ = '-'; - strcpy(c, r); - c += strlen(c); - } - *c = 0; - if (!*pd->content) - return 0; -#if 0 - fprintf(stderr, "evr: %s\n", pd->content); -#endif - return str2id(pool, pd->content, 1); -} - - - -static void XMLCALL -startElement(void *userData, const char *name, const char **atts) -{ - struct parsedata *pd = userData; - Pool *pool = pd->pool; - Solvable *solvable = pd->solvable; - struct stateswitch *sw; - /*const char *str; */ - -#if 0 - fprintf(stderr, "start: [%d]%s\n", pd->state, name); -#endif - if (pd->depth != pd->statedepth) - { - pd->depth++; - return; - } - - pd->depth++; - if (!pd->swtab[pd->state]) - return; - for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) /* find name in statetable */ - if (!strcmp(sw->ename, name)) - break; - - if (sw->from != pd->state) - { -#if 0 - fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state); - exit( 1 ); -#endif - return; - } - pd->state = sw->to; - pd->docontent = sw->docontent; - pd->statedepth = pd->depth; - pd->lcontent = 0; - *pd->content = 0; - - switch(pd->state) - { - case STATE_START: - break; - case STATE_UPDATES: - break; - /* - * <update from="rel-eng@fedoraproject.org" - * status="stable" - * type="bugfix" (enhancement, security) - * version="1.4"> - */ - case STATE_UPDATE: - { - const char *from = 0, *status = 0, *type = 0, *version = 0; - for (; *atts; atts += 2) - { - if (!strcmp(*atts, "from")) - from = atts[1]; - else if (!strcmp(*atts, "status")) - status = atts[1]; - else if (!strcmp(*atts, "type")) - type = atts[1]; - else if (!strcmp(*atts, "version")) - version = atts[1]; - } - - - solvable = pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo)); - pd->datanum = pd->solvable - pool->solvables; - - solvable->vendor = str2id(pool, from, 1); - solvable->evr = str2id(pool, version, 1); - solvable->arch = ARCH_NOARCH; - if (type) - repodata_set_str(pd->data, pd->datanum, SOLVABLE_PATCHCATEGORY, type); - } - break; - /* <id>FEDORA-2007-4594</id> */ - case STATE_ID: - break; - /* <title>imlib-1.9.15-6.fc8</title> */ - case STATE_TITLE: - break; - /* <release>Fedora 8</release> */ - case STATE_RELEASE: - break; - /* <issued date="2008-03-21 21:36:55"/> - */ - case STATE_ISSUED: - { - const char *date = 0; - for (; *atts; atts += 2) - { - if (!strcmp(*atts, "date")) - date = atts[1]; - } - if (date) - { - if (strlen(date) == strspn(date, "0123456789")) - repodata_set_num(pd->data, pd->datanum, SOLVABLE_BUILDTIME, atoi(date)); - else - { - /* FIXME: must convert to interger! */ - repodata_set_str(pd->data, pd->datanum, SOLVABLE_BUILDTIME, date); - } - } - } - break; - case STATE_REFERENCES: - break; - /* <reference href="https://bugzilla.redhat.com/show_bug.cgi?id=330471" - * id="330471" - * title="LDAP schema file missing for dhcpd" - * type="bugzilla"/> - */ - case STATE_REFERENCE: - { - const char *href = 0, *id = 0, *title = 0, *type = 0; - Id handle; - for (; *atts; atts += 2) - { - if (!strcmp(*atts, "href")) - href = atts[1]; - else if (!strcmp(*atts, "id")) - id = atts[1]; - else if (!strcmp(*atts, "title")) - title = atts[1]; - else if (!strcmp(*atts, "type")) - type = atts[1]; - } - handle = repodata_new_handle(pd->data); - if (href) - repodata_set_str(pd->data, handle, UPDATE_REFERENCE_HREF, href); - if (id) - repodata_set_str(pd->data, handle, UPDATE_REFERENCE_ID, id); - if (title) - repodata_set_str(pd->data, handle, UPDATE_REFERENCE_TITLE, title); - if (type) - repodata_set_poolstr(pd->data, handle, UPDATE_REFERENCE_TYPE, type); - repodata_add_flexarray(pd->data, pd->datanum, UPDATE_REFERENCE, handle); - } - break; - /* <description>This update ...</description> */ - case STATE_DESCRIPTION: - break; - /* <message type="confirm">This update ...</message> */ - case STATE_MESSAGE: - break; - case STATE_PKGLIST: - break; - /* <collection short="F8" */ - case STATE_COLLECTION: - break; - /* <name>Fedora 8</name> */ - case STATE_NAME: - break; - /* <package arch="ppc64" name="imlib-debuginfo" release="6.fc8" - * src="http://download.fedoraproject.org/pub/fedora/linux/updates/8/ppc64/imlib-debuginfo-1.9.15-6.fc8.ppc64.rpm" - * version="1.9.15"> - * - * - * -> patch.conflicts: {name} < {version}.{release} - */ - case STATE_PACKAGE: - { - const char *arch = 0, *name = 0, *src = 0; - Id evr = makeevr_atts(pool, pd, atts); /* parse "epoch", "version", "release" */ - Id n, a = 0; - Id rel_id; - - for (; *atts; atts += 2) - { - if (!strcmp(*atts, "arch")) - arch = atts[1]; - else if (!strcmp(*atts, "name")) - name = atts[1]; - else if (!strcmp(*atts, "src")) - src = atts[1]; - } - /* generated Id for name */ - n = str2id(pool, name, 1); - rel_id = n; - if (arch) - { - /* generate Id for arch and combine with name */ - a = str2id(pool, arch, 1); - rel_id = rel2id(pool, n, a, REL_ARCH, 1); - } - rel_id = rel2id(pool, rel_id, evr, REL_LT, 1); - - solvable->conflicts = repo_addid_dep(pd->repo, solvable->conflicts, rel_id, 0); - - /* who needs the collection anyway? */ - pd->collhandle = repodata_new_handle(pd->data); - repodata_set_id(pd->data, pd->collhandle, UPDATE_COLLECTION_NAME, n); - repodata_set_id(pd->data, pd->collhandle, UPDATE_COLLECTION_EVR, evr); - repodata_set_id(pd->data, pd->collhandle, UPDATE_COLLECTION_ARCH, a); - break; - } - /* <filename>libntlm-0.4.2-1.fc8.x86_64.rpm</filename> */ - /* <filename>libntlm-0.4.2-1.fc8.x86_64.rpm</filename> */ - case STATE_FILENAME: - break; - /* <reboot_suggested>True</reboot_suggested> */ - case STATE_REBOOT: - break; - /* <restart_suggested>True</restart_suggested> */ - case STATE_RESTART: - break; - /* <relogin_suggested>True</relogin_suggested> */ - case STATE_RELOGIN: - break; - default: - break; - } - return; -} - - -static void XMLCALL -endElement(void *userData, const char *name) -{ - struct parsedata *pd = userData; - Pool *pool = pd->pool; - Solvable *s = pd->solvable; - Repo *repo = pd->repo; - -#if 0 - fprintf(stderr, "end: %s\n", name); -#endif - if (pd->depth != pd->statedepth) - { - pd->depth--; -#if 0 - fprintf(stderr, "back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth); -#endif - return; - } - - pd->depth--; - pd->statedepth--; - switch (pd->state) - { - case STATE_START: - break; - case STATE_UPDATES: - break; - case STATE_UPDATE: - s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); - break; - case STATE_ID: - s->name = str2id(pool, join2("patch", ":", pd->content), 1); - break; - /* <title>imlib-1.9.15-6.fc8</title> */ - case STATE_TITLE: - while (pd->lcontent > 0 && pd->content[pd->lcontent - 1] == '\n') - pd->content[--pd->lcontent] = 0; - repodata_set_str(pd->data, pd->datanum, SOLVABLE_SUMMARY, pd->content); - break; - /* - * <release>Fedora 8</release> - */ - case STATE_RELEASE: - break; - case STATE_ISSUED: - break; - case STATE_REFERENCES: - break; - case STATE_REFERENCE: - break; - /* - * <description>This update ...</description> - */ - case STATE_DESCRIPTION: - repodata_set_str(pd->data, pd->datanum, SOLVABLE_DESCRIPTION, pd->content); - break; - /* - * <message>Warning! ...</message> - */ - case STATE_MESSAGE: - repodata_set_str(pd->data, pd->datanum, UPDATE_MESSAGE, pd->content); - break; - case STATE_PKGLIST: - break; - case STATE_COLLECTION: - break; - case STATE_NAME: - break; - case STATE_PACKAGE: - repodata_add_flexarray(pd->data, pd->datanum, UPDATE_COLLECTION, pd->collhandle); - pd->collhandle = 0; - break; - /* <filename>libntlm-0.4.2-1.fc8.x86_64.rpm</filename> */ - /* <filename>libntlm-0.4.2-1.fc8.x86_64.rpm</filename> */ - case STATE_FILENAME: - repodata_set_str(pd->data, pd->collhandle, UPDATE_COLLECTION_FILENAME, pd->content); - break; - /* <reboot_suggested>True</reboot_suggested> */ - case STATE_REBOOT: - if (pd->content[0] == 'T' || pd->content[0] == 't'|| pd->content[0] == '1') - { - /* FIXME: this is per-package, the global flag should be computed at runtime */ - repodata_set_void(pd->data, pd->datanum, UPDATE_REBOOT); - repodata_set_void(pd->data, pd->collhandle, UPDATE_REBOOT); - } - break; - /* <restart_suggested>True</restart_suggested> */ - case STATE_RESTART: - if (pd->content[0] == 'T' || pd->content[0] == 't'|| pd->content[0] == '1') - { - /* FIXME: this is per-package, the global flag should be computed at runtime */ - repodata_set_void(pd->data, pd->datanum, UPDATE_RESTART); - repodata_set_void(pd->data, pd->collhandle, UPDATE_RESTART); - } - break; - /* <relogin_suggested>True</relogin_suggested> */ - case STATE_RELOGIN: - if (pd->content[0] == 'T' || pd->content[0] == 't'|| pd->content[0] == '1') - { - /* FIXME: this is per-package, the global flag should be computed at runtime */ - repodata_set_void(pd->data, pd->datanum, UPDATE_RELOGIN); - repodata_set_void(pd->data, pd->collhandle, UPDATE_RELOGIN); - } - break; - default: - break; - } - - pd->state = pd->sbtab[pd->state]; - pd->docontent = 0; -} - - -static void XMLCALL -characterData(void *userData, const XML_Char *s, int len) -{ - struct parsedata *pd = userData; - int l; - char *c; - - if (!pd->docontent) - { -#if 0 - fprintf(stderr, "Content: [%d]'%.*s'\n", pd->state, len, s); -#endif - return; - } - l = pd->lcontent + len + 1; - if (l > pd->acontent) - { - pd->content = realloc(pd->content, l + 256); - pd->acontent = l + 256; - } - c = pd->content + pd->lcontent; - pd->lcontent += len; - while (len-- > 0) - *c++ = *s++; - *c = 0; -} - - -#define BUFF_SIZE 8192 - -void -repo_add_updateinfoxml(Repo *repo, FILE *fp, int flags) -{ - Pool *pool = repo->pool; - struct parsedata pd; - char buf[BUFF_SIZE]; - int i, l; - struct stateswitch *sw; - Repodata *data; - - if (!(flags & REPO_REUSE_REPODATA)) - data = repo_add_repodata(repo, 0); - else - data = repo_last_repodata(repo); - - memset(&pd, 0, sizeof(pd)); - for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++) - { - if (!pd.swtab[sw->from]) - pd.swtab[sw->from] = sw; - pd.sbtab[sw->to] = sw->from; - } - pd.pool = pool; - pd.repo = repo; - pd.data = data; - - pd.content = malloc(256); - pd.acontent = 256; - pd.lcontent = 0; - XML_Parser parser = XML_ParserCreate(NULL); - XML_SetUserData(parser, &pd); - XML_SetElementHandler(parser, startElement, endElement); - XML_SetCharacterDataHandler(parser, characterData); - for (;;) - { - l = fread(buf, 1, sizeof(buf), fp); - if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR) - { - pool_debug(pool, SAT_FATAL, "repo_updateinfoxml: %s at line %u:%u\n", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser)); - exit(1); - } - if (l == 0) - break; - } - XML_ParserFree(parser); - free(pd.content); - join_freemem(); - - if (!(flags & REPO_NO_INTERNALIZE)) - repodata_internalize(data); -} - -/* EOF */ diff --git a/tools/repo_updateinfoxml.h b/tools/repo_updateinfoxml.h deleted file mode 100644 index b20bb60..0000000 --- a/tools/repo_updateinfoxml.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2007, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -void repo_add_updateinfoxml(Repo *repo, FILE *fp, int flags); diff --git a/tools/repo_write.c b/tools/repo_write.c deleted file mode 100644 index 6d48942..0000000 --- a/tools/repo_write.c +++ /dev/null @@ -1,1936 +0,0 @@ -/* - * Copyright (c) 2007, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -/* - * repo_write.c - * - * Write Repo data out to binary file - * - * See doc/README.format for a description - * of the binary file format - * - */ - -#include <sys/types.h> -#include <limits.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -#include "pool.h" -#include "util.h" -#include "repo_write.h" -#include "repopage.h" - -/*------------------------------------------------------------------*/ -/* Id map optimizations */ - -typedef struct needid { - Id need; - Id map; -} NeedId; - - -#define RELOFF(id) (needid[0].map + GETRELID(id)) - -/* - * increment need Id - * idarray: array of Ids, ID_NULL terminated - * needid: array of Id->NeedId - * - * return count - * - */ - -static void -incneedid(Pool *pool, Id id, NeedId *needid) -{ - while (ISRELDEP(id)) - { - Reldep *rd = GETRELDEP(pool, id); - needid[RELOFF(id)].need++; - if (ISRELDEP(rd->evr)) - incneedid(pool, rd->evr, needid); - else - needid[rd->evr].need++; - id = rd->name; - } - needid[id].need++; -} - -static int -incneedidarray(Pool *pool, Id *idarray, NeedId *needid) -{ - Id id; - int n = 0; - - if (!idarray) - return 0; - while ((id = *idarray++) != 0) - { - n++; - while (ISRELDEP(id)) - { - Reldep *rd = GETRELDEP(pool, id); - needid[RELOFF(id)].need++; - if (ISRELDEP(rd->evr)) - incneedid(pool, rd->evr, needid); - else - needid[rd->evr].need++; - id = rd->name; - } - needid[id].need++; - } - return n + 1; -} - - -/* - * - */ - -static int -needid_cmp_need(const void *ap, const void *bp, void *dp) -{ - const NeedId *a = ap; - const NeedId *b = bp; - int r; - r = b->need - a->need; - if (r) - return r; - return a->map - b->map; -} - -static int -needid_cmp_need_s(const void *ap, const void *bp, void *dp) -{ - const NeedId *a = ap; - const NeedId *b = bp; - Stringpool *spool = dp; - - int r; - r = b->need - a->need; - if (r) - return r; - const char *as = spool->stringspace + spool->strings[a->map]; - const char *bs = spool->stringspace + spool->strings[b->map]; - return strcmp(as, bs); -} - - -/*------------------------------------------------------------------*/ -/* output helper routines */ - -/* - * unsigned 32-bit - */ - -static void -write_u32(FILE *fp, unsigned int x) -{ - if (putc(x >> 24, fp) == EOF || - putc(x >> 16, fp) == EOF || - putc(x >> 8, fp) == EOF || - putc(x, fp) == EOF) - { - perror("write error u32"); - exit(1); - } -} - - -/* - * unsigned 8-bit - */ - -static void -write_u8(FILE *fp, unsigned int x) -{ - if (putc(x, fp) == EOF) - { - perror("write error u8"); - exit(1); - } -} - -/* - * data blob - */ - -static void -write_blob(FILE *fp, void *data, int len) -{ - if (len && fwrite(data, len, 1, fp) != 1) - { - perror("write error blob"); - exit(1); - } -} - -/* - * Id - */ - -static void -write_id(FILE *fp, Id x) -{ - if (x >= (1 << 14)) - { - if (x >= (1 << 28)) - putc((x >> 28) | 128, fp); - if (x >= (1 << 21)) - putc((x >> 21) | 128, fp); - putc((x >> 14) | 128, fp); - } - if (x >= (1 << 7)) - putc((x >> 7) | 128, fp); - if (putc(x & 127, fp) == EOF) - { - perror("write error id"); - exit(1); - } -} - -static inline void -write_id_eof(FILE *fp, Id x, int eof) -{ - if (x >= 64) - x = (x & 63) | ((x & ~63) << 1); - write_id(fp, x | (eof ? 0 : 64)); -} - - - -#if 0 -static void -write_str(FILE *fp, const char *str) -{ - if (fputs (str, fp) == EOF || putc (0, fp) == EOF) - { - perror("write error"); - exit(1); - } -} -#endif - -/* - * Array of Ids - */ - -static void -write_idarray(FILE *fp, Pool *pool, NeedId *needid, Id *ids) -{ - Id id; - if (!ids) - return; - if (!*ids) - { - write_u8(fp, 0); - return; - } - for (;;) - { - id = *ids++; - if (needid) - id = needid[ISRELDEP(id) ? RELOFF(id) : id].need; - if (id >= 64) - id = (id & 63) | ((id & ~63) << 1); - if (!*ids) - { - write_id(fp, id); - return; - } - write_id(fp, id | 64); - } -} - -static int -cmp_ids (const void *pa, const void *pb, void *dp) -{ - Id a = *(Id *)pa; - Id b = *(Id *)pb; - return a - b; -} - -#if 0 -static void -write_idarray_sort(FILE *fp, Pool *pool, NeedId *needid, Id *ids, Id marker) -{ - int len, i; - Id lids[64], *sids; - - if (!ids) - return; - if (!*ids) - { - write_u8(fp, 0); - return; - } - for (len = 0; len < 64 && ids[len]; len++) - { - Id id = ids[len]; - if (needid) - id = needid[ISRELDEP(id) ? RELOFF(id) : id].need; - lids[len] = id; - } - if (ids[len]) - { - for (i = len + 1; ids[i]; i++) - ; - sids = sat_malloc2(i, sizeof(Id)); - memcpy(sids, lids, 64 * sizeof(Id)); - for (; ids[len]; len++) - { - Id id = ids[len]; - if (needid) - id = needid[ISRELDEP(id) ? RELOFF(id) : id].need; - sids[len] = id; - } - } - else - sids = lids; - - /* That bloody solvable:prereqmarker needs to stay in position :-( */ - if (needid) - marker = needid[marker].need; - for (i = 0; i < len; i++) - if (sids[i] == marker) - break; - if (i > 1) - sat_sort(sids, i, sizeof (Id), cmp_ids, 0); - if ((len - i) > 2) - sat_sort(sids + i + 1, len - i - 1, sizeof(Id), cmp_ids, 0); - - Id id, old = 0; - - /* The differencing above produces many runs of ones and twos. I tried - fairly elaborate schemes to RLE those, but they give only very mediocre - improvements in compression, as coding the escapes costs quite some - space. Even if they are coded only as bits in IDs. The best improvement - was about 2.7% for the whole .solv file. It's probably better to - invest some complexity into sharing idarrays, than RLEing. */ - for (i = 0; i < len - 1; i++) - { - id = sids[i]; - /* Ugly PREREQ handling. A "difference" of 0 is the prereq marker, - hence all real differences are offsetted by 1. Otherwise we would - have to handle negative differences, which would cost code space for - the encoding of the sign. We loose the exact mapping of prereq here, - but we know the result, so we can recover from that in the reader. */ - if (id == marker) - id = old = 0; - else - { - id = id - old + 1; - old = sids[i]; - } - /* XXX If difference is zero we have multiple equal elements, - we might want to skip writing them out. */ - if (id >= 64) - id = (id & 63) | ((id & ~63) << 1); - write_id(fp, id | 64); - } - id = sids[i]; - if (id == marker) - id = 0; - else - id = id - old + 1; - if (id >= 64) - id = (id & 63) | ((id & ~63) << 1); - write_id(fp, id); - if (sids != lids) - sat_free(sids); -} -#endif - - -struct extdata { - unsigned char *buf; - int len; -}; - -struct cbdata { - Repo *repo; - - Stringpool *ownspool; - Dirpool *owndirpool; - - Repokey *mykeys; - int nmykeys; - - Id *keymap; - int nkeymap; - Id *keymapstart; - - NeedId *needid; - - Id *schema; /* schema construction space */ - Id *sp; /* pointer in above */ - Id *oldschema, *oldsp; - - Id *myschemata; - int nmyschemata; - - Id *myschemadata; - int myschemadatalen; - - Id schematacache[256]; - - Id *solvschemata; - Id *extraschemata; - Id *subschemata; - int nsubschemata; - int current_sub; - - struct extdata *extdata; - - Id *dirused; - - Id vstart; - - Id maxdata; - Id lastlen; - - int doingsolvables; /* working on solvables data */ -}; - -#define NEEDED_BLOCK 1023 -#define SCHEMATA_BLOCK 31 -#define SCHEMATADATA_BLOCK 255 -#define EXTDATA_BLOCK 4095 - -static inline void -data_addid(struct extdata *xd, Id x) -{ - unsigned char *dp; - xd->buf = sat_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK); - dp = xd->buf + xd->len; - - if (x >= (1 << 14)) - { - if (x >= (1 << 28)) - *dp++ = (x >> 28) | 128; - if (x >= (1 << 21)) - *dp++ = (x >> 21) | 128; - *dp++ = (x >> 14) | 128; - } - if (x >= (1 << 7)) - *dp++ = (x >> 7) | 128; - *dp++ = x & 127; - xd->len = dp - xd->buf; -} - -static inline void -data_addideof(struct extdata *xd, Id x, int eof) -{ - if (x >= 64) - x = (x & 63) | ((x & ~63) << 1); - data_addid(xd, (eof ? x: x | 64)); -} - -static void -data_addidarray_sort(struct extdata *xd, Pool *pool, NeedId *needid, Id *ids, Id marker) -{ - int len, i; - Id lids[64], *sids; - - if (!ids) - return; - if (!*ids) - { - data_addid(xd, 0); - return; - } - for (len = 0; len < 64 && ids[len]; len++) - { - Id id = ids[len]; - if (needid) - id = needid[ISRELDEP(id) ? RELOFF(id) : id].need; - lids[len] = id; - } - if (ids[len]) - { - for (i = len + 1; ids[i]; i++) - ; - sids = sat_malloc2(i, sizeof(Id)); - memcpy(sids, lids, 64 * sizeof(Id)); - for (; ids[len]; len++) - { - Id id = ids[len]; - if (needid) - id = needid[ISRELDEP(id) ? RELOFF(id) : id].need; - sids[len] = id; - } - } - else - sids = lids; - - /* That bloody solvable:prereqmarker needs to stay in position :-( */ - if (needid) - marker = needid[marker].need; - for (i = 0; i < len; i++) - if (sids[i] == marker) - break; - if (i > 1) - sat_sort(sids, i, sizeof (Id), cmp_ids, 0); - if ((len - i) > 2) - sat_sort(sids + i + 1, len - i - 1, sizeof(Id), cmp_ids, 0); - - Id id, old = 0; - - /* The differencing above produces many runs of ones and twos. I tried - fairly elaborate schemes to RLE those, but they give only very mediocre - improvements in compression, as coding the escapes costs quite some - space. Even if they are coded only as bits in IDs. The best improvement - was about 2.7% for the whole .solv file. It's probably better to - invest some complexity into sharing idarrays, than RLEing. */ - for (i = 0; i < len - 1; i++) - { - id = sids[i]; - /* Ugly PREREQ handling. A "difference" of 0 is the prereq marker, - hence all real differences are offsetted by 1. Otherwise we would - have to handle negative differences, which would cost code space for - the encoding of the sign. We loose the exact mapping of prereq here, - but we know the result, so we can recover from that in the reader. */ - if (id == marker) - id = old = 0; - else - { - id = id - old + 1; - old = sids[i]; - } - /* XXX If difference is zero we have multiple equal elements, - we might want to skip writing them out. */ - if (id >= 64) - id = (id & 63) | ((id & ~63) << 1); - data_addid(xd, id | 64); - } - id = sids[i]; - if (id == marker) - id = 0; - else - id = id - old + 1; - if (id >= 64) - id = (id & 63) | ((id & ~63) << 1); - data_addid(xd, id); - if (sids != lids) - sat_free(sids); -} - -static inline void -data_addblob(struct extdata *xd, unsigned char *blob, int len) -{ - xd->buf = sat_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK); - memcpy(xd->buf + xd->len, blob, len); - xd->len += len; -} - -static inline void -data_addu32(struct extdata *xd, unsigned int num) -{ - unsigned char d[4]; - d[0] = num >> 24; - d[1] = num >> 16; - d[2] = num >> 8; - d[3] = num; - data_addblob(xd, d, 4); -} - -static Id -addschema(struct cbdata *cbdata, Id *schema) -{ - int h, len; - Id *sp, cid; - - for (sp = schema, len = 0, h = 0; *sp; len++) - h = h * 7 + *sp++; - h &= 255; - len++; - - cid = cbdata->schematacache[h]; - if (cid) - { - if (!memcmp(cbdata->myschemadata + cbdata->myschemata[cid], schema, len * sizeof(Id))) - return cid; - /* cache conflict */ - for (cid = 1; cid < cbdata->nmyschemata; cid++) - if (!memcmp(cbdata->myschemadata + cbdata->myschemata[cid], schema, len * sizeof(Id))) - return cid; - } - /* a new one. make room. */ - if (!cbdata->nmyschemata) - { - /* allocate schema 0, it is always empty */ - cbdata->myschemadata = sat_extend(cbdata->myschemadata, cbdata->myschemadatalen, 1, sizeof(Id), SCHEMATADATA_BLOCK); - cbdata->myschemata = sat_extend(cbdata->myschemata, cbdata->nmyschemata, 1, sizeof(Id), SCHEMATA_BLOCK); - cbdata->myschemata[0] = 0; - cbdata->myschemadata[0] = 0; - cbdata->nmyschemata = 1; - cbdata->myschemadatalen = 1; - } - /* add schema */ - cbdata->myschemadata = sat_extend(cbdata->myschemadata, cbdata->myschemadatalen, len, sizeof(Id), SCHEMATADATA_BLOCK); - cbdata->myschemata = sat_extend(cbdata->myschemata, cbdata->nmyschemata, 1, sizeof(Id), SCHEMATA_BLOCK); - memcpy(cbdata->myschemadata + cbdata->myschemadatalen, schema, len * sizeof(Id)); - cbdata->myschemata[cbdata->nmyschemata] = cbdata->myschemadatalen; - cbdata->myschemadatalen += len; - cbdata->schematacache[h] = cbdata->nmyschemata; - return cbdata->nmyschemata++; -} - -static Id -putinownpool(struct cbdata *cbdata, Stringpool *ss, Id id) -{ - const char *str = stringpool_id2str(ss, id); - id = stringpool_str2id(cbdata->ownspool, str, 1); - if (id >= cbdata->needid[0].map) - { - int oldoff = cbdata->needid[0].map; - int newoff = (id + 1 + NEEDED_BLOCK) & ~NEEDED_BLOCK; - int nrels = cbdata->repo->pool->nrels; - cbdata->needid = sat_realloc2(cbdata->needid, newoff + nrels, sizeof(NeedId)); - if (nrels) - memmove(cbdata->needid + newoff, cbdata->needid + oldoff, nrels * sizeof(NeedId)); - memset(cbdata->needid + oldoff, 0, (newoff - oldoff) * sizeof(NeedId)); - cbdata->needid[0].map = newoff; - } - return id; -} - -static Id -putinowndirpool(struct cbdata *cbdata, Repodata *data, Dirpool *dp, Id dir) -{ - Id compid, parent; - - parent = dirpool_parent(dp, dir); - if (parent) - parent = putinowndirpool(cbdata, data, dp, parent); - compid = dp->dirs[dir]; - if (cbdata->ownspool && compid > 1) - compid = putinownpool(cbdata, data->localpool ? &data->spool : &data->repo->pool->ss, compid); - return dirpool_add_dir(cbdata->owndirpool, parent, compid, 1); -} - -static inline void -setdirused(struct cbdata *cbdata, Dirpool *dp, Id dir) -{ - if (cbdata->dirused[dir]) - return; - cbdata->dirused[dir] = 1; - while ((dir = dirpool_parent(dp, dir)) != 0) - { - if (cbdata->dirused[dir] == 2) - return; - if (cbdata->dirused[dir]) - { - cbdata->dirused[dir] = 2; - return; - } - cbdata->dirused[dir] = 2; - } - cbdata->dirused[0] = 2; -} - -static int -repo_write_collect_needed(struct cbdata *cbdata, Repo *repo, Repodata *data, Repokey *key, KeyValue *kv) -{ - Id id; - int rm; - - if (key->name == REPOSITORY_SOLVABLES) - return SEARCH_NEXT_KEY; /* we do not want this one */ - if (data != data->repo->repodata + data->repo->nrepodata - 1) - if (key->name == REPOSITORY_ADDEDFILEPROVIDES || key->name == REPOSITORY_EXTERNAL || key->name == REPOSITORY_LOCATION || key->name == REPOSITORY_KEYS) - return SEARCH_NEXT_KEY; - - rm = cbdata->keymap[cbdata->keymapstart[data - data->repo->repodata] + (key - data->keys)]; - if (!rm) - return SEARCH_NEXT_KEY; /* we do not want this one */ - /* record key in schema */ - if ((key->type != REPOKEY_TYPE_FIXARRAY || kv->eof == 0) - && (cbdata->sp == cbdata->schema || cbdata->sp[-1] != rm)) - *cbdata->sp++ = rm; - switch(key->type) - { - case REPOKEY_TYPE_ID: - case REPOKEY_TYPE_IDARRAY: - id = kv->id; - if (!ISRELDEP(id) && cbdata->ownspool && id > 1) - id = putinownpool(cbdata, data->localpool ? &data->spool : &repo->pool->ss, id); - incneedid(repo->pool, id, cbdata->needid); - break; - case REPOKEY_TYPE_DIR: - case REPOKEY_TYPE_DIRNUMNUMARRAY: - case REPOKEY_TYPE_DIRSTRARRAY: - id = kv->id; - if (cbdata->owndirpool) - putinowndirpool(cbdata, data, &data->dirpool, id); - else - setdirused(cbdata, &data->dirpool, id); - break; - case REPOKEY_TYPE_FIXARRAY: - if (kv->eof == 0) - { - if (cbdata->oldschema) - { - fprintf(stderr, "nested structs not yet implemented\n"); - exit(1); - } - cbdata->oldschema = cbdata->schema; - cbdata->oldsp = cbdata->sp; - cbdata->schema = sat_calloc(cbdata->nmykeys, sizeof(Id)); - cbdata->sp = cbdata->schema; - } - else if (kv->eof == 1) - { - cbdata->current_sub++; - *cbdata->sp = 0; - cbdata->subschemata = sat_extend(cbdata->subschemata, cbdata->nsubschemata, 1, sizeof(Id), SCHEMATA_BLOCK); - cbdata->subschemata[cbdata->nsubschemata++] = addschema(cbdata, cbdata->schema); -#if 0 - fprintf(stderr, "Have schema %d\n", cbdata->subschemata[cbdata->nsubschemata-1]); -#endif - cbdata->sp = cbdata->schema; - } - else - { - sat_free(cbdata->schema); - cbdata->schema = cbdata->oldschema; - cbdata->sp = cbdata->oldsp; - cbdata->oldsp = cbdata->oldschema = 0; - } - break; - case REPOKEY_TYPE_FLEXARRAY: - if (kv->entry == 0) - { - if (kv->eof != 2) - *cbdata->sp++ = 0; /* mark start */ - } - else - { - /* just finished a schema, rewind */ - Id *sp = cbdata->sp - 1; - *sp = 0; - while (sp[-1]) - sp--; - cbdata->subschemata = sat_extend(cbdata->subschemata, cbdata->nsubschemata, 1, sizeof(Id), SCHEMATA_BLOCK); - cbdata->subschemata[cbdata->nsubschemata++] = addschema(cbdata, sp); - cbdata->sp = kv->eof == 2 ? sp - 1: sp; - } - break; - default: - break; - } - return 0; -} - -static int -repo_write_cb_needed(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv) -{ - struct cbdata *cbdata = vcbdata; - Repo *repo = data->repo; - -#if 0 - if (s) - fprintf(stderr, "solvable %d (%s): key (%d)%s %d\n", s ? s - repo->pool->solvables : 0, s ? id2str(repo->pool, s->name) : "", key->name, id2str(repo->pool, key->name), key->type); -#endif - return repo_write_collect_needed(cbdata, repo, data, key, kv); -} - -static int -repo_write_adddata(struct cbdata *cbdata, Repodata *data, Repokey *key, KeyValue *kv) -{ - int rm; - Id id; - unsigned int u32; - unsigned char v[4]; - struct extdata *xd; - - if (key->name == REPOSITORY_SOLVABLES) - return SEARCH_NEXT_KEY; - if (data != data->repo->repodata + data->repo->nrepodata - 1) - if (key->name == REPOSITORY_ADDEDFILEPROVIDES || key->name == REPOSITORY_EXTERNAL || key->name == REPOSITORY_LOCATION || key->name == REPOSITORY_KEYS) - return SEARCH_NEXT_KEY; - - rm = cbdata->keymap[cbdata->keymapstart[data - data->repo->repodata] + (key - data->keys)]; - if (!rm) - return SEARCH_NEXT_KEY; /* we do not want this one */ - - if (cbdata->mykeys[rm].storage == KEY_STORAGE_VERTICAL_OFFSET) - { - xd = cbdata->extdata + rm; /* vertical buffer */ - if (cbdata->vstart == -1) - cbdata->vstart = xd->len; - } - else - xd = cbdata->extdata + 0; /* incore buffer */ - switch(key->type) - { - case REPOKEY_TYPE_VOID: - case REPOKEY_TYPE_CONSTANT: - case REPOKEY_TYPE_CONSTANTID: - break; - case REPOKEY_TYPE_ID: - id = kv->id; - if (!ISRELDEP(id) && cbdata->ownspool && id > 1) - id = putinownpool(cbdata, data->localpool ? &data->spool : &data->repo->pool->ss, id); - id = cbdata->needid[id].need; - data_addid(xd, id); - break; - case REPOKEY_TYPE_IDARRAY: - id = kv->id; - if (cbdata->ownspool && id > 1) - id = putinownpool(cbdata, data->localpool ? &data->spool : &data->repo->pool->ss, id); - id = cbdata->needid[id].need; - data_addideof(xd, id, kv->eof); - break; - case REPOKEY_TYPE_STR: - data_addblob(xd, (unsigned char *)kv->str, strlen(kv->str) + 1); - break; - case REPOKEY_TYPE_MD5: - data_addblob(xd, (unsigned char *)kv->str, SIZEOF_MD5); - break; - case REPOKEY_TYPE_SHA1: - data_addblob(xd, (unsigned char *)kv->str, SIZEOF_SHA1); - break; - case REPOKEY_TYPE_SHA256: - data_addblob(xd, (unsigned char *)kv->str, SIZEOF_SHA256); - break; - case REPOKEY_TYPE_U32: - u32 = kv->num; - v[0] = u32 >> 24; - v[1] = u32 >> 16; - v[2] = u32 >> 8; - v[3] = u32; - data_addblob(xd, v, 4); - break; - case REPOKEY_TYPE_NUM: - data_addid(xd, kv->num); - break; - case REPOKEY_TYPE_DIR: - id = kv->id; - if (cbdata->owndirpool) - id = putinowndirpool(cbdata, data, &data->dirpool, id); - id = cbdata->dirused[id]; - data_addid(xd, id); - break; - case REPOKEY_TYPE_DIRNUMNUMARRAY: - id = kv->id; - if (cbdata->owndirpool) - id = putinowndirpool(cbdata, data, &data->dirpool, id); - id = cbdata->dirused[id]; - data_addid(xd, id); - data_addid(xd, kv->num); - data_addideof(xd, kv->num2, kv->eof); - break; - case REPOKEY_TYPE_DIRSTRARRAY: - id = kv->id; - if (cbdata->owndirpool) - id = putinowndirpool(cbdata, data, &data->dirpool, id); - id = cbdata->dirused[id]; - data_addideof(xd, id, kv->eof); - data_addblob(xd, (unsigned char *)kv->str, strlen(kv->str) + 1); - break; - case REPOKEY_TYPE_FIXARRAY: - if (kv->eof == 0) - { - if (kv->num) - { - data_addid(xd, kv->num); - data_addid(xd, cbdata->subschemata[cbdata->current_sub]); -#if 0 - fprintf(stderr, "writing %d %d\n", kv->num, cbdata->subschemata[cbdata->current_sub]); -#endif - } - } - else if (kv->eof == 1) - { - cbdata->current_sub++; - } - else - { - } - break; - case REPOKEY_TYPE_FLEXARRAY: - if (!kv->entry) - data_addid(xd, kv->num); - if (kv->eof != 2) - data_addid(xd, cbdata->subschemata[cbdata->current_sub++]); - if (xd == cbdata->extdata + 0 && !kv->parent && !cbdata->doingsolvables) - { - if (xd->len - cbdata->lastlen > cbdata->maxdata) - cbdata->maxdata = xd->len - cbdata->lastlen; - cbdata->lastlen = xd->len; - } - break; - default: - fprintf(stderr, "unknown type for %d: %d\n", key->name, key->type); - exit(1); - } - if (cbdata->mykeys[rm].storage == KEY_STORAGE_VERTICAL_OFFSET && kv->eof) - { - /* we can re-use old data in the blob here! */ - data_addid(cbdata->extdata + 0, cbdata->vstart); /* add offset into incore data */ - data_addid(cbdata->extdata + 0, xd->len - cbdata->vstart); /* add length into incore data */ - cbdata->vstart = -1; - } - return 0; -} - -static int -repo_write_cb_adddata(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv) -{ - struct cbdata *cbdata = vcbdata; - return repo_write_adddata(cbdata, data, key, kv); -} - -static int -traverse_dirs(Dirpool *dp, Id *dirmap, Id n, Id dir, Id *used) -{ - Id sib, child; - Id parent, lastn; - - parent = n; - /* special case for '/', which has to come first */ - if (parent == 1) - dirmap[n++] = 1; - for (sib = dir; sib; sib = dirpool_sibling(dp, sib)) - { - if (used && !used[sib]) - continue; - if (sib == 1 && parent == 1) - continue; /* already did that one above */ - dirmap[n++] = sib; - } - lastn = n; - for (; parent < lastn; parent++) - { - sib = dirmap[parent]; - if (used && used[sib] != 2) - continue; - child = dirpool_child(dp, sib); - if (child) - { - dirmap[n++] = -parent; - n = traverse_dirs(dp, dirmap, n, child, used); - } - } - return n; -} - -static void -write_compressed_page(FILE *fp, unsigned char *page, int len) -{ - int clen; - unsigned char cpage[BLOB_PAGESIZE]; - - clen = repopagestore_compress_page(page, len, cpage, len - 1); - if (!clen) - { - write_u32(fp, len * 2); - write_blob(fp, page, len); - } - else - { - write_u32(fp, clen * 2 + 1); - write_blob(fp, cpage, clen); - } -} - - -#if 0 -static Id subfilekeys[] = { - REPODATA_INFO, REPOKEY_TYPE_VOID, - REPODATA_EXTERNAL, REPOKEY_TYPE_VOID, - REPODATA_KEYS, REPOKEY_TYPE_IDARRAY, - REPODATA_LOCATION, REPOKEY_TYPE_STR, - REPODATA_ADDEDFILEPROVIDES, REPOKEY_TYPE_REL_IDARRAY, - REPODATA_RPMDBCOOKIE, REPOKEY_TYPE_SHA256, - 0, -}; -#endif - -/* - * Repo - */ - -void -repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Id **keyarrayp) -{ - Pool *pool = repo->pool; - int i, j, k, n; - Solvable *s; - NeedId *needid; - int nstrings, nrels; - unsigned int sizeid; - unsigned int solv_flags; - Reldep *ran; - Id *idarraydata; - - Id id, *sp; - - Id *dirmap; - int ndirmap; - Id *keyused; - unsigned char *repodataused; - int anyrepodataused; - - struct cbdata cbdata; - int needrels; - Repokey *key; - int poolusage, dirpoolusage, idused, dirused; - int reloff; - - Repodata *data, *dirpooldata = 0; - Stringpool ownspool, *spool; - Dirpool owndirpool, *dirpool; - - Id *repodataschemata = 0; - Id mainschema; - - struct extdata *xd; - - Id type_constantid = 0; - - memset(&cbdata, 0, sizeof(cbdata)); - cbdata.repo = repo; - - /* go through all repodata and find the keys we need */ - /* also unify keys */ - /* creates: mykeys - key array, still has global pool ids */ - /* keymapstart - maps repo number to keymap offset */ - /* keymap - maps repo key to my key, 0 -> not used */ - - /* start with all KEY_STORAGE_SOLVABLE ids */ - - n = ID_NUM_INTERNAL; - for (i = 0; i < repo->nrepodata; i++) - n += repo->repodata[i].nkeys; - cbdata.mykeys = sat_calloc(n, sizeof(Repokey)); - cbdata.keymap = sat_calloc(n, sizeof(Id)); - cbdata.keymapstart = sat_calloc(repo->nrepodata, sizeof(Id)); - repodataused = sat_calloc(repo->nrepodata, 1); - - cbdata.nmykeys = 1; - needrels = 0; - poolusage = 0; - for (i = SOLVABLE_NAME; i <= RPM_RPMDBID; i++) - { - key = cbdata.mykeys + i; - key->name = i; - if (i < SOLVABLE_PROVIDES) - key->type = REPOKEY_TYPE_ID; - else if (i < RPM_RPMDBID) - key->type = REPOKEY_TYPE_REL_IDARRAY; - else - key->type = REPOKEY_TYPE_U32; - key->size = 0; - key->storage = KEY_STORAGE_SOLVABLE; - if (keyfilter) - { - key->storage = keyfilter(repo, key, kfdata); - if (key->storage == KEY_STORAGE_DROPPED) - continue; - key->storage = KEY_STORAGE_SOLVABLE; - } - poolusage = 1; - if (key->type == REPOKEY_TYPE_IDARRAY || key->type == REPOKEY_TYPE_REL_IDARRAY) - needrels = 1; - cbdata.keymap[i] = i; - } - cbdata.nmykeys = i; - - if (repo->nsolvables) - { - key = cbdata.mykeys + cbdata.nmykeys; - key->name = REPOSITORY_SOLVABLES; - key->type = REPOKEY_TYPE_FLEXARRAY; - key->size = 0; - key->storage = KEY_STORAGE_INCORE; - cbdata.keymap[key->name] = cbdata.nmykeys++; - } - -#if 0 - /* If we store subfile info, generate the necessary keys. */ - if (nsubfiles) - { - for (i = 0; subfilekeys[i]; i += 2) - { - key = cbdata.mykeys + cbdata.nmykeys; - key->name = subfilekeys[i]; - key->type = subfilekeys[i + 1]; - key->size = 0; - key->storage = KEY_STORAGE_SOLVABLE; - cbdata.keymap[key->name] = cbdata.nmykeys++; - } - } -#endif - - dirpoolusage = 0; - - spool = 0; - dirpool = 0; - n = ID_NUM_INTERNAL; - for (i = 0; i < repo->nrepodata; i++) - { - data = repo->repodata + i; - cbdata.keymapstart[i] = n; - cbdata.keymap[n++] = 0; /* key 0 */ - idused = 0; - dirused = 0; - for (j = 1; j < data->nkeys; j++, n++) - { - key = data->keys + j; - /* see if we already had this one, should use hash for fast miss */ - for (k = 0; k < cbdata.nmykeys; k++) - { - if (key->name == cbdata.mykeys[k].name && key->type == cbdata.mykeys[k].type) - { - if ((key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID) && key->size != cbdata.mykeys[k].size) - continue; - break; - } - } - if (k < cbdata.nmykeys) - cbdata.keymap[n] = k; - else - { - /* found a new key! */ - cbdata.mykeys[cbdata.nmykeys] = *key; - key = cbdata.mykeys + cbdata.nmykeys; - key->storage = KEY_STORAGE_INCORE; - if (key->type != REPOKEY_TYPE_CONSTANT && key->type != REPOKEY_TYPE_CONSTANTID) - key->size = 0; - if (keyfilter) - { - key->storage = keyfilter(repo, key, kfdata); - if (key->storage == KEY_STORAGE_DROPPED) - { - cbdata.keymap[n] = 0; - continue; - } - } - cbdata.keymap[n] = cbdata.nmykeys++; - } - /* load repodata if not already loaded */ - if (data->state == REPODATA_STUB) - { - if (data->loadcallback) - data->loadcallback(data); - else - data->state = REPODATA_ERROR; - if (data->state != REPODATA_ERROR) - { - /* redo this repodata! */ - j = 0; - n = cbdata.keymapstart[i]; - continue; - } - } - if (data->state == REPODATA_ERROR) - { - /* too bad! */ - cbdata.keymap[n] = 0; - continue; - } - - repodataused[i] = 1; - anyrepodataused = 1; - if (key->type != REPOKEY_TYPE_STR - && key->type != REPOKEY_TYPE_U32 - && key->type != REPOKEY_TYPE_MD5 - && key->type != REPOKEY_TYPE_SHA1) - idused = 1; - if (key->type == REPOKEY_TYPE_DIR || key->type == REPOKEY_TYPE_DIRNUMNUMARRAY || key->type == REPOKEY_TYPE_DIRSTRARRAY) - dirused = 1; - /* make sure we know that key */ - if (data->localpool) - { - stringpool_str2id(&data->spool, id2str(pool, key->name), 1); - stringpool_str2id(&data->spool, id2str(pool, key->type), 1); - if (key->type == REPOKEY_TYPE_CONSTANTID) - stringpool_str2id(&data->spool, id2str(pool, key->size), 1); - } - } - if (idused) - { - if (data->localpool) - { - if (poolusage) - poolusage = 3; /* need local pool */ - else - { - poolusage = 2; - spool = &data->spool; - } - } - else - { - if (poolusage == 0) - poolusage = 1; - else if (poolusage != 1) - poolusage = 3; /* need local pool */ - } - } - if (dirused) - { - if (dirpoolusage) - dirpoolusage = 3; /* need local dirpool */ - else - { - dirpoolusage = 2; - dirpool = &data->dirpool; - dirpooldata = data; - } - } - } - cbdata.nkeymap = n; - - /* 0: no pool needed at all */ - /* 1: use global pool */ - /* 2: use repodata local pool */ - /* 3: need own pool */ - if (poolusage == 3) - { - spool = &ownspool; - if (needrels) - { - /* hack: reuse global pool so we don't have to map rel ids */ - stringpool_clone(spool, &repo->pool->ss); - } - else - stringpool_init_empty(spool); - cbdata.ownspool = spool; - } - else if (poolusage == 0 || poolusage == 1) - { - poolusage = 1; - spool = &repo->pool->ss; - } - if (dirpoolusage == 3) - { - dirpool = &owndirpool; - dirpooldata = 0; - dirpool_init(dirpool); - cbdata.owndirpool = dirpool; - } - else if (dirpool) - cbdata.dirused = sat_calloc(dirpool->ndirs, sizeof(Id)); - - -/********************************************************************/ -#if 0 -fprintf(stderr, "poolusage: %d\n", poolusage); -fprintf(stderr, "dirpoolusage: %d\n", dirpoolusage); -fprintf(stderr, "nmykeys: %d\n", cbdata.nmykeys); -for (i = 1; i < cbdata.nmykeys; i++) - fprintf(stderr, " %2d: %s[%d] %d %d %d\n", i, id2str(pool, cbdata.mykeys[i].name), cbdata.mykeys[i].name, cbdata.mykeys[i].type, cbdata.mykeys[i].size, cbdata.mykeys[i].storage); -#endif - -/********************************************************************/ - - /* set needed count of all strings and rels, - * find which keys are used in the solvables - * put all strings in own spool - */ - - reloff = spool->nstrings; - if (poolusage == 3) - reloff = (reloff + NEEDED_BLOCK) & ~NEEDED_BLOCK; - - needid = calloc(reloff + pool->nrels, sizeof(*needid)); - needid[0].map = reloff; - - cbdata.needid = needid; - cbdata.schema = sat_calloc(cbdata.nmykeys, sizeof(Id)); - cbdata.sp = cbdata.schema; - cbdata.solvschemata = sat_calloc(repo->nsolvables, sizeof(Id)); -#if 0 - cbdata.extraschemata = sat_calloc(repo->nextra, sizeof(Id)); -#endif - - /* create main schema */ - cbdata.sp = cbdata.schema; - /* collect all other data from all repodatas */ - /* XXX: merge arrays of equal keys? */ - for (j = 0, data = repo->repodata; j < repo->nrepodata; j++, data++) - repodata_search(data, SOLVID_META, 0, SEARCH_SUB|SEARCH_ARRAYSENTINEL, repo_write_cb_needed, &cbdata); - sp = cbdata.sp; - /* add solvables if needed */ - if (repo->nsolvables) - { - *sp++ = cbdata.keymap[REPOSITORY_SOLVABLES]; - cbdata.mykeys[cbdata.keymap[REPOSITORY_SOLVABLES]].size++; - } - *sp = 0; - mainschema = addschema(&cbdata, cbdata.schema); - - - idarraydata = repo->idarraydata; - - cbdata.doingsolvables = 1; - for (i = repo->start, s = pool->solvables + i, n = 0; i < repo->end; i++, s++) - { - if (s->repo != repo) - continue; - - /* set schema info, keep in sync with further down */ - sp = cbdata.schema; - if (cbdata.keymap[SOLVABLE_NAME]) - { - *sp++ = SOLVABLE_NAME; - needid[s->name].need++; - } - if (cbdata.keymap[SOLVABLE_ARCH]) - { - *sp++ = SOLVABLE_ARCH; - needid[s->arch].need++; - } - if (cbdata.keymap[SOLVABLE_EVR]) - { - *sp++ = SOLVABLE_EVR; - needid[s->evr].need++; - } - if (s->vendor && cbdata.keymap[SOLVABLE_VENDOR]) - { - *sp++ = SOLVABLE_VENDOR; - needid[s->vendor].need++; - } - if (s->provides && cbdata.keymap[SOLVABLE_PROVIDES]) - { - *sp++ = SOLVABLE_PROVIDES; - cbdata.mykeys[SOLVABLE_PROVIDES].size += incneedidarray(pool, idarraydata + s->provides, needid); - } - if (s->obsoletes && cbdata.keymap[SOLVABLE_OBSOLETES]) - { - *sp++ = SOLVABLE_OBSOLETES; - cbdata.mykeys[SOLVABLE_OBSOLETES].size += incneedidarray(pool, idarraydata + s->obsoletes, needid); - } - if (s->conflicts && cbdata.keymap[SOLVABLE_CONFLICTS]) - { - *sp++ = SOLVABLE_CONFLICTS; - cbdata.mykeys[SOLVABLE_CONFLICTS].size += incneedidarray(pool, idarraydata + s->conflicts, needid); - } - if (s->requires && cbdata.keymap[SOLVABLE_REQUIRES]) - { - *sp++ = SOLVABLE_REQUIRES; - cbdata.mykeys[SOLVABLE_REQUIRES].size += incneedidarray(pool, idarraydata + s->requires, needid); - } - if (s->recommends && cbdata.keymap[SOLVABLE_RECOMMENDS]) - { - *sp++ = SOLVABLE_RECOMMENDS; - cbdata.mykeys[SOLVABLE_RECOMMENDS].size += incneedidarray(pool, idarraydata + s->recommends, needid); - } - if (s->suggests && cbdata.keymap[SOLVABLE_SUGGESTS]) - { - *sp++ = SOLVABLE_SUGGESTS; - cbdata.mykeys[SOLVABLE_SUGGESTS].size += incneedidarray(pool, idarraydata + s->suggests, needid); - } - if (s->supplements && cbdata.keymap[SOLVABLE_SUPPLEMENTS]) - { - *sp++ = SOLVABLE_SUPPLEMENTS; - cbdata.mykeys[SOLVABLE_SUPPLEMENTS].size += incneedidarray(pool, idarraydata + s->supplements, needid); - } - if (s->enhances && cbdata.keymap[SOLVABLE_ENHANCES]) - { - *sp++ = SOLVABLE_ENHANCES; - cbdata.mykeys[SOLVABLE_ENHANCES].size += incneedidarray(pool, idarraydata + s->enhances, needid); - } - if (repo->rpmdbid && cbdata.keymap[RPM_RPMDBID]) - { - *sp++ = RPM_RPMDBID; - cbdata.mykeys[RPM_RPMDBID].size++; - } - cbdata.sp = sp; - - if (anyrepodataused) - { - for (j = 0, data = repo->repodata; j < repo->nrepodata; j++, data++) - { - if (!repodataused[j]) - continue; - if (i < data->start || i >= data->end) - continue; - repodata_search(data, i, 0, SEARCH_SUB|SEARCH_ARRAYSENTINEL, repo_write_cb_needed, &cbdata); - needid = cbdata.needid; - } - } - *cbdata.sp = 0; - cbdata.solvschemata[n] = addschema(&cbdata, cbdata.schema); - n++; - } - cbdata.doingsolvables = 0; - assert(n == repo->nsolvables); - -#if 0 - if (repo->nextra && anyrepodataused) - for (i = -1; i >= -repo->nextra; i--) - { - Dataiterator di; - dataiterator_init(&di, repo, i, 0, 0, SEARCH_EXTRA | SEARCH_NO_STORAGE_SOLVABLE); - cbdata.sp = cbdata.schema; - while (dataiterator_step(&di)) - repo_write_collect_needed(&cbdata, repo, di.data, di.key, &di.kv); - *cbdata.sp = 0; - cbdata.extraschemata[-1 - i] = addschema(&cbdata, cbdata.schema); - } - - /* If we have fileinfos to write, setup schemas and increment needid[] - of the right strings. */ - for (i = 0; i < nsubfiles; i++) - { - int j; - Id schema[4], *sp; - - sp = schema; - if (fileinfo[i].addedfileprovides || fileinfo[i].rpmdbcookie) - { - /* extra info about this file */ - *sp++ = cbdata.keymap[REPODATA_INFO]; - if (fileinfo[i].addedfileprovides) - { - *sp++ = cbdata.keymap[REPODATA_ADDEDFILEPROVIDES]; - for (j = 0; fileinfo[i].addedfileprovides[j]; j++) - ; - cbdata.mykeys[cbdata.keymap[REPODATA_ADDEDFILEPROVIDES]].size += j + 1; - } - if (fileinfo[i].rpmdbcookie) - *sp++ = cbdata.keymap[REPODATA_RPMDBCOOKIE]; - } - else - { - *sp++ = cbdata.keymap[REPODATA_EXTERNAL]; - *sp++ = cbdata.keymap[REPODATA_KEYS]; - if (fileinfo[i].location) - *sp++ = cbdata.keymap[REPODATA_LOCATION]; - } - *sp = 0; - repodataschemata[i] = addschema(&cbdata, schema); - cbdata.mykeys[cbdata.keymap[REPODATA_KEYS]].size += 2 * fileinfo[i].nkeys + 1; - for (j = 1; j < fileinfo[i].nkeys; j++) - { - needid[fileinfo[i].keys[j].type].need++; - needid[fileinfo[i].keys[j].name].need++; - } - } -#endif - -/********************************************************************/ - - /* remove unused keys, convert ids to local ids and increment their needid */ - keyused = sat_calloc(cbdata.nmykeys, sizeof(Id)); - for (i = 0; i < cbdata.myschemadatalen; i++) - keyused[cbdata.myschemadata[i]] = 1; - keyused[0] = 0; - for (n = i = 1; i < cbdata.nmykeys; i++) - { - if (!keyused[i]) - continue; - keyused[i] = n; - if (i != n) - cbdata.mykeys[n] = cbdata.mykeys[i]; - if (cbdata.mykeys[n].type == REPOKEY_TYPE_CONSTANTID) - { - if (!type_constantid) - type_constantid = poolusage > 1 ? stringpool_str2id(spool, id2str(repo->pool, cbdata.mykeys[n].type), 1) : REPOKEY_TYPE_CONSTANTID; - if (poolusage > 1) - cbdata.mykeys[n].size = stringpool_str2id(spool, id2str(repo->pool, cbdata.mykeys[n].size), 1); - needid[cbdata.mykeys[n].size].need++; - } - if (poolusage > 1) - { - cbdata.mykeys[n].name = stringpool_str2id(spool, id2str(repo->pool, cbdata.mykeys[n].name), 1); - cbdata.mykeys[n].type = stringpool_str2id(spool, id2str(repo->pool, cbdata.mykeys[n].type), 1); - } - needid[cbdata.mykeys[n].name].need++; - needid[cbdata.mykeys[n].type].need++; - n++; - } - cbdata.nmykeys = n; - for (i = 0; i < cbdata.myschemadatalen; i++) - cbdata.myschemadata[i] = keyused[cbdata.myschemadata[i]]; - for (i = 0; i < cbdata.nkeymap; i++) - cbdata.keymap[i] = keyused[cbdata.keymap[i]]; - keyused = sat_free(keyused); - -/********************************************************************/ - - /* increment need id for used dir components */ - if (cbdata.dirused && !cbdata.dirused[0]) - { - /* no dirs used at all */ - cbdata.dirused = sat_free(cbdata.dirused); - dirpool = 0; - } - if (dirpool) - { - for (i = 1; i < dirpool->ndirs; i++) - { -#if 0 -fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); -#endif - id = dirpool->dirs[i]; - if (id <= 0) - continue; - if (cbdata.dirused && !cbdata.dirused[i]) - continue; - if (cbdata.ownspool && dirpooldata && id > 1) - { - id = putinownpool(&cbdata, dirpooldata->localpool ? &dirpooldata->spool : &pool->ss, id); - needid = cbdata.needid; - } - needid[id].need++; - } - } - - reloff = needid[0].map; - - -/********************************************************************/ - - /* - * create mapping table, new keys are sorted by needid[].need - * - * needid[key].need : old key -> new key - * needid[key].map : new key -> old key - */ - - /* zero out id 0 and rel 0 just in case */ - - needid[0].need = 0; - needid[reloff].need = 0; - - for (i = 1; i < reloff + pool->nrels; i++) - needid[i].map = i; - -#if 0 - sat_sort(needid + 1, spool->nstrings - 1, sizeof(*needid), needid_cmp_need_s, spool); -#else - /* make first entry '' */ - needid[1].need = 1; - sat_sort(needid + 2, spool->nstrings - 2, sizeof(*needid), needid_cmp_need_s, spool); -#endif - sat_sort(needid + reloff, pool->nrels, sizeof(*needid), needid_cmp_need, 0); - - sizeid = 0; - for (i = 1; i < reloff; i++) - { - if (!needid[i].need) - break; - needid[i].need = 0; - sizeid += strlen(spool->stringspace + spool->strings[needid[i].map]) + 1; - } - - nstrings = i; - for (i = 1; i < nstrings; i++) - needid[needid[i].map].need = i; - - for (i = 0; i < pool->nrels; i++) - { - if (!needid[reloff + i].need) - break; - else - needid[reloff + i].need = 0; - } - - nrels = i; - for (i = 0; i < nrels; i++) - needid[needid[reloff + i].map].need = nstrings + i; - - -/********************************************************************/ - - /* create dir map */ - ndirmap = 0; - dirmap = 0; - if (dirpool) - { - if (cbdata.dirused && !cbdata.dirused[1]) - cbdata.dirused[1] = 1; /* always want / entry */ - dirmap = sat_calloc(dirpool->ndirs, sizeof(Id)); - dirmap[0] = 0; - ndirmap = traverse_dirs(dirpool, dirmap, 1, dirpool_child(dirpool, 0), cbdata.dirused); - if (!cbdata.dirused) - cbdata.dirused = sat_malloc2(dirpool->ndirs, sizeof(Id)); - memset(cbdata.dirused, 0, dirpool->ndirs * sizeof(Id)); - for (i = 1; i < ndirmap; i++) - { - if (dirmap[i] <= 0) - continue; - cbdata.dirused[dirmap[i]] = i; - id = dirpool->dirs[dirmap[i]]; - if (cbdata.ownspool && dirpooldata && id > 1) - id = putinownpool(&cbdata, dirpooldata->localpool ? &dirpooldata->spool : &pool->ss, id); - dirmap[i] = needid[id].need; - } - } - -/********************************************************************/ - cbdata.extdata = sat_calloc(cbdata.nmykeys, sizeof(struct extdata)); - - xd = cbdata.extdata; - cbdata.current_sub = 0; - /* write main schema */ - cbdata.lastlen = 0; - data_addid(xd, mainschema); - -#if 1 - for (j = 0, data = repo->repodata; j < repo->nrepodata; j++, data++) - repodata_search(data, SOLVID_META, 0, SEARCH_SUB|SEARCH_ARRAYSENTINEL, repo_write_cb_adddata, &cbdata); -#endif - - if (xd->len - cbdata.lastlen > cbdata.maxdata) - cbdata.maxdata = xd->len - cbdata.lastlen; - cbdata.lastlen = xd->len; - - if (repo->nsolvables) - data_addid(xd, repo->nsolvables); /* FLEXARRAY nentries */ - cbdata.doingsolvables = 1; - for (i = repo->start, s = pool->solvables + i, n = 0; i < repo->end; i++, s++) - { - if (s->repo != repo) - continue; - data_addid(xd, cbdata.solvschemata[n]); - if (cbdata.keymap[SOLVABLE_NAME]) - data_addid(xd, needid[s->name].need); - if (cbdata.keymap[SOLVABLE_ARCH]) - data_addid(xd, needid[s->arch].need); - if (cbdata.keymap[SOLVABLE_EVR]) - data_addid(xd, needid[s->evr].need); - if (s->vendor && cbdata.keymap[SOLVABLE_VENDOR]) - data_addid(xd, needid[s->vendor].need); - if (s->provides && cbdata.keymap[SOLVABLE_PROVIDES]) - data_addidarray_sort(xd, pool, needid, idarraydata + s->provides, SOLVABLE_FILEMARKER); - if (s->obsoletes && cbdata.keymap[SOLVABLE_OBSOLETES]) - data_addidarray_sort(xd, pool, needid, idarraydata + s->obsoletes, 0); - if (s->conflicts && cbdata.keymap[SOLVABLE_CONFLICTS]) - data_addidarray_sort(xd, pool, needid, idarraydata + s->conflicts, 0); - if (s->requires && cbdata.keymap[SOLVABLE_REQUIRES]) - data_addidarray_sort(xd, pool, needid, idarraydata + s->requires, SOLVABLE_PREREQMARKER); - if (s->recommends && cbdata.keymap[SOLVABLE_RECOMMENDS]) - data_addidarray_sort(xd, pool, needid, idarraydata + s->recommends, 0); - if (s->suggests && cbdata.keymap[SOLVABLE_SUGGESTS]) - data_addidarray_sort(xd, pool, needid, idarraydata + s->suggests, 0); - if (s->supplements && cbdata.keymap[SOLVABLE_SUPPLEMENTS]) - data_addidarray_sort(xd, pool, needid, idarraydata + s->supplements, 0); - if (s->enhances && cbdata.keymap[SOLVABLE_ENHANCES]) - data_addidarray_sort(xd, pool, needid, idarraydata + s->enhances, 0); - if (repo->rpmdbid && cbdata.keymap[RPM_RPMDBID]) - data_addu32(xd, repo->rpmdbid[i - repo->start]); - if (anyrepodataused) - { - cbdata.vstart = -1; - for (j = 0, data = repo->repodata; j < repo->nrepodata; j++, data++) - { - if (!repodataused[j]) - continue; - if (i < data->start || i >= data->end) - continue; - repodata_search(data, i, 0, SEARCH_SUB|SEARCH_ARRAYSENTINEL, repo_write_cb_adddata, &cbdata); - } - } - if (xd->len - cbdata.lastlen > cbdata.maxdata) - cbdata.maxdata = xd->len - cbdata.lastlen; - cbdata.lastlen = xd->len; - n++; - } - cbdata.doingsolvables = 0; - - assert(cbdata.current_sub == cbdata.nsubschemata); - if (cbdata.subschemata) - { - cbdata.subschemata = sat_free(cbdata.subschemata); - cbdata.nsubschemata = 0; - } - -#if 0 - if (repo->nextra && anyrepodataused) - for (i = -1; i >= -repo->nextra; i--) - { - Dataiterator di; - dataiterator_init(&di, repo, i, 0, 0, SEARCH_EXTRA | SEARCH_NO_STORAGE_SOLVABLE); - entrysize = xd->len; - data_addid(xd, cbdata.extraschemata[-1 - i]); - cbdata.vstart = -1; - while (dataiterator_step(&di)) - repo_write_adddata(&cbdata, di.data, di.key, &di.kv); - entrysize = xd->len - entrysize; - if (entrysize > maxentrysize) - maxentrysize = entrysize; - } -#endif - -/********************************************************************/ - - /* write header */ - - /* write file header */ - write_u32(fp, 'S' << 24 | 'O' << 16 | 'L' << 8 | 'V'); - write_u32(fp, SOLV_VERSION_8); - - - /* write counts */ - write_u32(fp, nstrings); - write_u32(fp, nrels); - write_u32(fp, ndirmap); - write_u32(fp, repo->nsolvables); - write_u32(fp, cbdata.nmykeys); - write_u32(fp, cbdata.nmyschemata); - solv_flags = 0; - solv_flags |= SOLV_FLAG_PREFIX_POOL; - write_u32(fp, solv_flags); - - /* Build the prefix-encoding of the string pool. We need to know - the size of that before writing it to the file, so we have to - build a separate buffer for that. As it's temporarily possible - that this actually is an expansion we can't easily reuse the - stringspace for this. The max expansion per string is 1 byte, - so it will fit into sizeid+nstrings bytes. */ - char *prefix = sat_malloc(sizeid + nstrings); - char *pp = prefix; - char *old_str = ""; - for (i = 1; i < nstrings; i++) - { - char *str = spool->stringspace + spool->strings[needid[i].map]; - int same; - size_t len; - for (same = 0; same < 255; same++) - if (!old_str[same] || !str[same] || old_str[same] != str[same]) - break; - *pp++ = same; - len = strlen(str + same) + 1; - memcpy (pp, str + same, len); - pp += len; - old_str = str; - } - - /* - * write strings - */ - write_u32(fp, sizeid); - write_u32(fp, pp - prefix); - if (pp != prefix) - { - if (fwrite(prefix, pp - prefix, 1, fp) != 1) - { - perror("write error prefix"); - exit(1); - } - } - sat_free(prefix); - - /* - * write RelDeps - */ - for (i = 0; i < nrels; i++) - { - ran = pool->rels + (needid[reloff + i].map - reloff); - write_id(fp, needid[ISRELDEP(ran->name) ? RELOFF(ran->name) : ran->name].need); - write_id(fp, needid[ISRELDEP(ran->evr) ? RELOFF(ran->evr) : ran->evr].need); - write_u8(fp, ran->flags); - } - - /* - * write dirs (skip both root and / entry) - */ - for (i = 2; i < ndirmap; i++) - { - if (dirmap[i] > 0) - write_id(fp, dirmap[i]); - else - write_id(fp, nstrings - dirmap[i]); - } - sat_free(dirmap); - - /* - * write keys - */ - if (keyarrayp) - *keyarrayp = sat_calloc(2 * cbdata.nmykeys + 1, sizeof(Id)); - for (i = 1; i < cbdata.nmykeys; i++) - { - write_id(fp, needid[cbdata.mykeys[i].name].need); - write_id(fp, needid[cbdata.mykeys[i].type].need); - if (cbdata.mykeys[i].storage != KEY_STORAGE_VERTICAL_OFFSET) - { - if (cbdata.mykeys[i].type == type_constantid) - write_id(fp, needid[cbdata.mykeys[i].size].need); - else - write_id(fp, cbdata.mykeys[i].size); - } - else - write_id(fp, cbdata.extdata[i].len); - write_id(fp, cbdata.mykeys[i].storage); - if (keyarrayp) - { - (*keyarrayp)[2 * i - 2] = cbdata.mykeys[i].name; - (*keyarrayp)[2 * i - 1] = cbdata.mykeys[i].type; - } - } - - /* - * write schemata - */ - write_id(fp, cbdata.myschemadatalen); - if (cbdata.nmyschemata) - { - for (i = 1; i < cbdata.nmyschemata; i++) - write_idarray(fp, pool, 0, cbdata.myschemadata + cbdata.myschemata[i]); - } - -#if 0 - /* - * write info block - */ - if (nsubfiles) - { - struct extdata xd; - xd.buf = 0; - xd.len = 0; - int max = 0; - int cur; - - for (i = 0; i < nsubfiles; i++) - { - int j; - - cur = xd.len; - data_addid(&xd, repodataschemata[i]); - if (fileinfo[i].addedfileprovides || fileinfo[i].rpmdbcookie) - { - if (fileinfo[i].addedfileprovides) - data_addidarray_sort(&xd, pool, needid, fileinfo[i].addedfileprovides, 0); - if (fileinfo[i].rpmdbcookie) - data_addblob(&xd, fileinfo[i].rpmdbcookie, 32); - } - else - { - /* key,type array + location, write idarray */ - for (j = 1; j < fileinfo[i].nkeys; j++) - { - data_addideof(&xd, needid[fileinfo[i].keys[j].name].need, 0); - data_addideof(&xd, needid[fileinfo[i].keys[j].type].need, j == fileinfo[i].nkeys - 1); - } - if (fileinfo[i].location) - data_addblob(&xd, (unsigned char *)fileinfo[i].location, strlen(fileinfo[i].location) + 1); - } - cur = xd.len - cur; - if (cur > max) - max = cur; - } - write_id(fp, max); - write_id(fp, xd.len); - write_blob(fp, xd.buf, xd.len); - sat_free(xd.buf); - } -#endif - -/********************************************************************/ - - write_id(fp, cbdata.maxdata); - write_id(fp, cbdata.extdata[0].len); - if (cbdata.extdata[0].len) - write_blob(fp, cbdata.extdata[0].buf, cbdata.extdata[0].len); - sat_free(cbdata.extdata[0].buf); - -#if 0 - /* - * write Solvable data - */ - if (repo->nsolvables || repo->nextra) - { - write_id(fp, maxentrysize); - write_id(fp, cbdata.extdata[0].len); - write_blob(fp, cbdata.extdata[0].buf, cbdata.extdata[0].len); - } - sat_free(cbdata.extdata[0].buf); -#endif - - /* write vertical data */ - for (i = 1; i < cbdata.nmykeys; i++) - if (cbdata.extdata[i].len) - break; - if (i < cbdata.nmykeys) - { - unsigned char *dp, vpage[BLOB_PAGESIZE]; - int l, ll, lpage = 0; - - write_u32(fp, BLOB_PAGESIZE); - for (i = 1; i < cbdata.nmykeys; i++) - { - if (!cbdata.extdata[i].len) - continue; - l = cbdata.extdata[i].len; - dp = cbdata.extdata[i].buf; - while (l) - { - ll = BLOB_PAGESIZE - lpage; - if (l < ll) - ll = l; - memcpy(vpage + lpage, dp, ll); - dp += ll; - lpage += ll; - l -= ll; - if (lpage == BLOB_PAGESIZE) - { - write_compressed_page(fp, vpage, lpage); - lpage = 0; - } - } - } - if (lpage) - write_compressed_page(fp, vpage, lpage); - } - -#if 0 - /* write vertical_offset entries */ - write_u32(fp, 0); /* no paging */ - for (i = 1; i < cbdata.nmykeys; i++) - if (cbdata.extdata[i].len) - write_blob(fp, cbdata.extdata[i].buf, cbdata.extdata[i].len); - - /* Fill fileinfo for our caller. */ - if (setfileinfo) - { - fileinfo->checksum = 0; - fileinfo->nchecksum = 0; - fileinfo->checksumtype = 0; - fileinfo->location = 0; - } -#endif - - for (i = 1; i < cbdata.nmykeys; i++) - sat_free(cbdata.extdata[i].buf); - sat_free(cbdata.extdata); - - if (cbdata.ownspool) - { - sat_free(cbdata.ownspool->strings); - sat_free(cbdata.ownspool->stringspace); - sat_free(cbdata.ownspool->stringhashtbl); - } - if (cbdata.owndirpool) - { - sat_free(cbdata.owndirpool->dirs); - sat_free(cbdata.owndirpool->dirtraverse); - } - sat_free(needid); - sat_free(cbdata.extraschemata); - sat_free(cbdata.solvschemata); - sat_free(cbdata.myschemadata); - sat_free(cbdata.myschemata); - sat_free(cbdata.schema); - - sat_free(cbdata.mykeys); - sat_free(cbdata.keymap); - sat_free(cbdata.keymapstart); - sat_free(cbdata.dirused); - sat_free(repodataused); - sat_free(repodataschemata); -} diff --git a/tools/repo_write.h b/tools/repo_write.h deleted file mode 100644 index fd622d4..0000000 --- a/tools/repo_write.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2007, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -/* - * repo_write.h - * - */ - -#ifndef REPO_WRITE_H -#define REPO_WRITE_H - -#include <stdio.h> - -#include "pool.h" -#include "repo.h" - -/* Describes a repodata file */ -typedef struct _Repodatafile -{ - /* These have the same meaning as the equally named fields in - Repodata. */ - char *location; - char *checksum; - unsigned int nchecksum; - unsigned int checksumtype; - struct _Repokey *keys; - unsigned int nkeys; - Id *addedfileprovides; - unsigned char *rpmdbcookie; -} Repodatafile; - -void repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Id **keyarrayp); - -#endif diff --git a/tools/repo_zyppdb.c b/tools/repo_zyppdb.c deleted file mode 100644 index 13086d9..0000000 --- a/tools/repo_zyppdb.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - * repo_zyppdb.c - * - * Parses legacy /var/lib/zypp/db/products/... files. - * They are old (pre Code11) product descriptions. See bnc#429177 - * - * - * Copyright (c) 2008, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <limits.h> -#include <fcntl.h> -#include <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <dirent.h> -#include <expat.h> - -#include "pool.h" -#include "repo.h" -#include "util.h" -#define DISABLE_SPLIT -#include "tools_util.h" -#include "repo_content.h" - - -//#define DUMPOUT 0 - -enum state { - STATE_START, // 0 - STATE_PRODUCT, // 1 - STATE_NAME, // 2 - STATE_VERSION, // 3 - STATE_ARCH, // 4 - STATE_SUMMARY, // 5 - STATE_VENDOR, // 6 - STATE_INSTALLTIME, // 7 - NUMSTATES // 0 -}; - -struct stateswitch { - enum state from; - char *ename; - enum state to; - int docontent; -}; - -/* !! must be sorted by first column !! */ -static struct stateswitch stateswitches[] = { - { STATE_START, "product", STATE_PRODUCT, 0 }, - { STATE_PRODUCT, "name", STATE_NAME, 1 }, - { STATE_PRODUCT, "version", STATE_VERSION, 0 }, - { STATE_PRODUCT, "arch", STATE_ARCH, 1 }, - { STATE_PRODUCT, "summary", STATE_SUMMARY, 1 }, - { STATE_PRODUCT, "install-time", STATE_INSTALLTIME, 1 }, - { STATE_PRODUCT, "vendor", STATE_VENDOR, 1 }, - { NUMSTATES } -}; - -struct parsedata { - int depth; - enum state state; - int statedepth; - char *content; - int lcontent; - int acontent; - int docontent; - Pool *pool; - Repo *repo; - Repodata *data; - - struct stateswitch *swtab[NUMSTATES]; - enum state sbtab[NUMSTATES]; - - const char *tmplang; - - Solvable *solvable; - Id handle; - - Id langcache[ID_NUM_INTERNAL]; -}; - - -/* - * find_attr - * find value for xml attribute - * I: txt, name of attribute - * I: atts, list of key/value attributes - * I: dup, strdup it - * O: pointer to value of matching key, or NULL - * - */ - -static inline const char * -find_attr(const char *txt, const char **atts, int dup) -{ - for (; *atts; atts += 2) - { - if (!strcmp(*atts, txt)) - return dup ? strdup(atts[1]) : atts[1]; - } - return 0; -} - - -/* - * create localized tag - */ - -static Id -langtag(struct parsedata *pd, Id tag, const char *language) -{ - if (language && !language[0]) - language = 0; - if (!language || tag >= ID_NUM_INTERNAL) - return pool_id2langid(pd->repo->pool, tag, language, 1); - if (!pd->langcache[tag]) - pd->langcache[tag] = pool_id2langid(pd->repo->pool, tag, language, 1); - return pd->langcache[tag]; -} - - -/* - * XML callback: startElement - */ - -static void XMLCALL -startElement(void *userData, const char *name, const char **atts) -{ - struct parsedata *pd = userData; - Pool *pool = pd->pool; - Solvable *s = pd->solvable; - struct stateswitch *sw; - -#if 0 - fprintf(stderr, "start: [%d]%s\n", pd->state, name); -#endif - if (pd->depth != pd->statedepth) - { - pd->depth++; - return; - } - - pd->depth++; - if (!pd->swtab[pd->state]) /* no statetable -> no substates */ - { -#if 0 - fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state); -#endif - return; - } - for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) /* find name in statetable */ - if (!strcmp(sw->ename, name)) - break; - - if (sw->from != pd->state) - { -#if 0 - fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state); -#endif - return; - } - pd->state = sw->to; - pd->docontent = sw->docontent; - pd->statedepth = pd->depth; - pd->lcontent = 0; - *pd->content = 0; - - switch(pd->state) - { - case STATE_PRODUCT: - { - /* parse 'type' */ - const char *type = find_attr("type", atts, 0); - s = pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo)); - repodata_extend(pd->data, s - pool->solvables); - pd->handle = s - pool->solvables; - if (type) - { - repodata_set_str(pd->data, pd->handle, PRODUCT_TYPE, type); - } - } - break; - case STATE_VERSION: - { - const char *ver = find_attr("ver", atts, 0); - const char *rel = find_attr("rel", atts, 0); - /* const char *epoch = find_attr("epoch", atts, 1); ignored */ - s->evr = makeevr(pd->pool, join2(ver, "-", rel)); - } - break; - /* <summary lang="xy">... */ - case STATE_SUMMARY: - pd->tmplang = find_attr("lang", atts, 1); - break; - default: - break; - } -} - - -static void XMLCALL -endElement(void *userData, const char *name) -{ - struct parsedata *pd = userData; - Solvable *s = pd->solvable; - -#if 0 - fprintf(stderr, "end: [%d]%s\n", pd->state, name); -#endif - if (pd->depth != pd->statedepth) - { - pd->depth--; -#if 0 - fprintf(stderr, "back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth); -#endif - return; - } - - pd->depth--; - pd->statedepth--; - - switch (pd->state) - { - case STATE_PRODUCT: - - if (!s->arch) - s->arch = ARCH_NOARCH; - if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) - s->provides = repo_addid_dep(pd->repo, s->provides, rel2id(pd->pool, s->name, s->evr, REL_EQ, 1), 0); - pd->solvable = 0; - break; - case STATE_NAME: - s->name = str2id(pd->pool, join2("product", ":", pd->content), 1); - break; - case STATE_ARCH: - s->arch = str2id(pd->pool, pd->content, 1); - break; - case STATE_SUMMARY: - repodata_set_str(pd->data, pd->handle, langtag(pd, SOLVABLE_SUMMARY, pd->tmplang), pd->content); - pd->tmplang = sat_free((void *)pd->tmplang); - break; - case STATE_VENDOR: - s->vendor = str2id(pd->pool, pd->content, 1); - break; - case STATE_INSTALLTIME: - repodata_set_num(pd->data, pd->handle, SOLVABLE_INSTALLTIME, atol(pd->content)); - default: - break; - } - - pd->state = pd->sbtab[pd->state]; - pd->docontent = 0; - -#if 0 - fprintf(stderr, "end: [%s] -> %d\n", name, pd->state); -#endif -} - - -static void XMLCALL -characterData(void *userData, const XML_Char *s, int len) -{ - struct parsedata *pd = userData; - int l; - char *c; - if (!pd->docontent) { -#if 0 - char *dup = strndup( s, len ); - fprintf(stderr, "Content: [%d]'%s'\n", pd->state, dup ); - free( dup ); -#endif - return; - } - l = pd->lcontent + len + 1; - if (l > pd->acontent) - { - pd->content = realloc(pd->content, l + 256); - pd->acontent = l + 256; - } - c = pd->content + pd->lcontent; - pd->lcontent += len; - while (len-- > 0) - *c++ = *s++; - *c = 0; -} - -#define BUFF_SIZE 8192 - - -/* - * add single product to repo - * - */ - -static void -add_zyppdb_product(struct parsedata *pd, FILE *fp) -{ - char buf[BUFF_SIZE]; - int l; - - XML_Parser parser = XML_ParserCreate(NULL); - XML_SetUserData(parser, pd); - XML_SetElementHandler(parser, startElement, endElement); - XML_SetCharacterDataHandler(parser, characterData); - - for (;;) - { - l = fread(buf, 1, sizeof(buf), fp); - if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR) - { - pool_debug(pd->pool, SAT_ERROR, "repo_zyppdb: %s at line %u:%u\n", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser)); - return; - } - if (l == 0) - break; - } - XML_ParserFree(parser); -} - - -/* - * read all installed products - * - * parse each one as a product - */ - -void -repo_add_zyppdb_products(Repo *repo, const char *dirpath, int flags) -{ - int i; - struct parsedata pd; - struct stateswitch *sw; - struct dirent *entry; - char *fullpath; - DIR *dir; - FILE *fp; - Repodata *data; - - if (!(flags & REPO_REUSE_REPODATA)) - data = repo_add_repodata(repo, 0); - else - data = repo_last_repodata(repo); - - memset(&pd, 0, sizeof(pd)); - pd.repo = repo; - pd.pool = repo->pool; - pd.data = data; - - pd.content = malloc(256); - pd.acontent = 256; - - for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++) - { - if (!pd.swtab[sw->from]) - pd.swtab[sw->from] = sw; - pd.sbtab[sw->to] = sw->from; - } - - dir = opendir(dirpath); - if (dir) - { - while ((entry = readdir(dir))) - { - if (strlen(entry->d_name) < 3) - continue; /* skip '.' and '..' */ - fullpath = join2(dirpath, "/", entry->d_name); - if ((fp = fopen(fullpath, "r")) == 0) - { - perror(fullpath); - continue; - } - add_zyppdb_product(&pd, fp); - fclose(fp); - } - } - closedir(dir); - - sat_free((void *)pd.tmplang); - free(pd.content); - join_freemem(); - if (!(flags & REPO_NO_INTERNALIZE)) - repodata_internalize(data); -} - -/* EOF */ diff --git a/tools/repo_zyppdb.h b/tools/repo_zyppdb.h deleted file mode 100644 index 8c4a5da..0000000 --- a/tools/repo_zyppdb.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2007, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -void repo_add_zyppdb_products(Repo *repo, const char *dirpath, int flags); diff --git a/tools/tools_util.h b/tools/tools_util.h deleted file mode 100644 index ed7022d..0000000 --- a/tools/tools_util.h +++ /dev/null @@ -1,117 +0,0 @@ - -/* - * Copyright (c) 2007, Novell Inc. - * - * This program is licensed under the BSD license, read LICENSE.BSD - * for further information - */ - -/* - * util.h - * - */ - -#ifndef SATSOLVER_TOOLS_UTIL_H -#define SATSOLVER_TOOLS_UTIL_H - -static char *_join_tmp; -static int _join_tmpl; - -struct parsedata_common { - char *tmp; - int tmpl; - Pool *pool; - Repo *repo; -}; - -static inline Id -makeevr(Pool *pool, const char *s) -{ - if (!strncmp(s, "0:", 2) && s[2]) - s += 2; - return str2id(pool, s, 1); -} - -/** - * split a string - */ -#ifndef DISABLE_SPLIT -static int -split(char *l, char **sp, int m) -{ - int i; - for (i = 0; i < m;) - { - while (*l == ' ') - l++; - if (!*l) - break; - sp[i++] = l; - while (*l && *l != ' ') - l++; - if (!*l) - break; - *l++ = 0; - } - return i; -} -#endif - -/* this join does not depend on parsedata */ -static char * -join2(const char *s1, const char *s2, const char *s3) -{ - int l = 1; - char *p; - - if (s1) - l += strlen(s1); - if (s2) - l += strlen(s2); - if (s3) - l += strlen(s3); - if (l > _join_tmpl) - { - _join_tmpl = l + 256; - if (!_join_tmp) - _join_tmp = malloc(_join_tmpl); - else - _join_tmp = realloc(_join_tmp, _join_tmpl); - } - p = _join_tmp; - if (s1) - { - strcpy(p, s1); - p += strlen(s1); - } - if (s2) - { - strcpy(p, s2); - p += strlen(s2); - } - if (s3) - { - strcpy(p, s3); - p += strlen(s3); - } - return _join_tmp; -} - -static inline void -join_freemem(void) -{ - if (_join_tmp) - free(_join_tmp); - _join_tmp = 0; - _join_tmpl = 0; -} - -/* util function to set a translated string */ -static inline void repodata_set_tstr(Repodata *data, Id handle, const char *attrname, const char *lang, const char *str) -{ - Id attrid; - attrid = str2id(data->repo->pool, join2(attrname, ":", lang), 1); - repodata_set_str(data, handle, attrid, str); -} - -#endif /* SATSOLVER_TOOLS_UTIL_H */ |