diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/.lclintrc | 3 | ||||
-rw-r--r-- | lib/Makefile.am | 42 | ||||
-rw-r--r-- | lib/cpio.c | 470 | ||||
-rw-r--r-- | lib/cpio.h | 29 | ||||
-rw-r--r-- | lib/db0.c | 327 | ||||
-rw-r--r-- | lib/db0.h | 64 | ||||
-rw-r--r-- | lib/db1.c | 326 | ||||
-rw-r--r-- | lib/db1.h | 68 | ||||
-rw-r--r-- | lib/db2.c | 329 | ||||
-rw-r--r-- | lib/db2.h | 68 | ||||
-rw-r--r-- | lib/dbindex.c | 251 | ||||
-rw-r--r-- | lib/dbindex.h | 170 | ||||
-rw-r--r-- | lib/depends.c | 79 | ||||
-rw-r--r-- | lib/fprint.c | 4 | ||||
-rw-r--r-- | lib/hash.c | 36 | ||||
-rw-r--r-- | lib/hash.h | 68 | ||||
-rw-r--r-- | lib/install.c | 37 | ||||
-rw-r--r-- | lib/lookup.c | 47 | ||||
-rw-r--r-- | lib/lookup.h | 3 | ||||
-rw-r--r-- | lib/md5.c | 2 | ||||
-rw-r--r-- | lib/misc.c | 3 | ||||
-rw-r--r-- | lib/misc.h | 3 | ||||
-rw-r--r-- | lib/query.c | 12 | ||||
-rw-r--r-- | lib/rebuilddb.c | 9 | ||||
-rw-r--r-- | lib/rpmdb.c | 162 | ||||
-rw-r--r-- | lib/rpmdb.h | 26 | ||||
-rw-r--r-- | lib/rpminstall.c | 24 | ||||
-rw-r--r-- | lib/rpmio.h | 12 | ||||
-rw-r--r-- | lib/rpmlib.h | 45 | ||||
-rw-r--r-- | lib/rpmrc.c | 63 | ||||
-rw-r--r-- | lib/transaction.c | 48 | ||||
-rw-r--r-- | lib/uninstall.c | 86 | ||||
-rw-r--r-- | lib/verify.c | 2 |
33 files changed, 2318 insertions, 600 deletions
diff --git a/lib/.lclintrc b/lib/.lclintrc index 5ff453c20..d4ad2d041 100644 --- a/lib/.lclintrc +++ b/lib/.lclintrc @@ -7,6 +7,9 @@ +unixlib +# XXX ignore doxygen markings +-unrecogcomments + # don't-bother-me-yet parameters -branchstate #-immediatetrans diff --git a/lib/Makefile.am b/lib/Makefile.am index e6abb9c14..ee21c3ee7 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -4,6 +4,8 @@ AUTOMAKE_OPTIONS = 1.4 foreign INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/build -I$(top_srcdir)/popt @INCPATH@ +EXTRA_DIST = db0.[ch] db1.[ch] db2.[ch] + pkgincdir = $(pkgincludedir) pkginc_HEADERS = \ dbindex.h header.h misc.h rpmio.h rpmlib.h rpmmacro.h rpmurl.h stringbuf.h @@ -17,15 +19,53 @@ mylibs= -lrpm -lpopt @INTLLIBS@ @LIBMISC@ lib_LTLIBRARIES = librpm.la librpm_la_SOURCES = \ - cpio.c dbindex.c depends.c falloc.c \ + cpio.c $(DBLIBOBJS) dbindex.c depends.c falloc.c \ formats.c fprint.c fs.c hash.c header.c install.c \ lookup.c macro.c md5.c md5sum.c \ messages.c misc.c oldheader.c package.c problems.c query.c \ rebuilddb.c rpmchecksig.c rpmdb.c rpmerr.c rpminstall.c \ rpmio.c rpmlead.c rpmmalloc.c rpmrc.c signature.c stringbuf.c stubs.c \ tagName.c tagtable.c transaction.c uninstall.c url.c verify.c +librpm_la_LIBADD = $(subst .c,.lo,$(DBLIBOBJS)) #librpm_la_LIBADD = -lpopt +Xdb0.o: db0.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + @__LD@ -r -o $@.o $@ -L/usr/lib -ldb1 + @__OBJCOPY@ `\ + @__NM@ -g --defined-only $@.o | \ + sed -e '/ [TWD] /!d' -e 's/.* [TWD] /-L /' | \ + grep -v '^-L $*'` $@.o $@ + rm -f $@.o + +db0.lo: db0.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp + @__LD@ -r -o $*.o.o $*.o -L/usr/lib -ldb1 + @__OBJCOPY@ `\ + @__NM@ -g --defined-only $*.o.o | \ + sed -e '/ [TWD] /!d' -e 's/.* [TWD] /-L /' | \ + grep -v '^-L $*'` $*.o.o $*.o + rm -f $*.o.o + @__LD@ -r -o $@.o $@ -L/usr/lib -ldb1 + @__OBJCOPY@ `\ + @__NM@ -g --defined-only $@.o | \ + sed -e '/ [TWD] /!d' -e 's/.* [TWD] /-L /' | \ + grep -v '^-L $*'` $@.o $@ + rm -f $@.o + tagtable.c: rpmlib.h @echo '#include "system.h"' > tagtable.c @echo '#include "rpmlib.h"' >> tagtable.c diff --git a/lib/cpio.c b/lib/cpio.c index 93c49728f..5babb3955 100644 --- a/lib/cpio.c +++ b/lib/cpio.c @@ -1,16 +1,22 @@ +/** \file lib/cpio.c + * Handle cpio payloads within rpm packages. + * + * @warning FIXME: We don't translate between cpio and system mode bits! These + * should both be the same, but really odd things are going to happen if + * that's not true! + */ + #include "system.h" #include <rpmio.h> #include "cpio.h" +#define xfree(_p) free((void *)_p) + #define CPIO_NEWC_MAGIC "070701" #define CPIO_CRC_MAGIC "070702" #define TRAILER "TRAILER!!!" -/* FIXME: We don't translate between cpio and system mode bits! These - should both be the same, but really odd things are going to happen if - that's not true! */ - /** */ struct hardLink { struct hardLink * next; @@ -18,12 +24,14 @@ struct hardLink { int * fileMaps; /* used by build */ dev_t dev; ino_t inode; - int nlink; + int nlink; int linksLeft; int createdPath; struct stat sb; }; +enum hardLinkType { HARDLINK_INSTALL=1, HARDLINK_BUILD }; + /** */ struct cpioCrcPhysicalHeader { char magic[6]; @@ -46,15 +54,8 @@ struct cpioCrcPhysicalHeader { /** */ struct cpioHeader { - ino_t inode; - mode_t mode; - uid_t uid; - gid_t gid; - int nlink; - time_t mtime; - long size; - dev_t dev, rdev; - /*@owned@*/char * path; + /*@owned@*/ const char * path; + struct stat sb; }; /** */ @@ -92,7 +93,7 @@ static inline void padinfd(FD_t cfd, int modulo) { int buf[10]; int amount; - + amount = (modulo - fdGetCpioPos(cfd) % modulo) % modulo; (void)ourread(cfd, buf, amount); } @@ -116,7 +117,7 @@ static inline off_t safewrite(FD_t cfd, const void * vbuf, size_t amount) amount -= nb; } - return rc; + return rc; } /** */ @@ -124,11 +125,11 @@ static inline int padoutfd(FD_t cfd, size_t * where, int modulo) { static int buf[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int amount; - + amount = (modulo - *where % modulo) % modulo; *where += amount; - if (safewrite(cfd, buf, amount) != amount) + if (safewrite(cfd, buf, amount) != amount) return CPIOERR_WRITE_FAILED; return 0; } @@ -160,46 +161,49 @@ static int strntoul(const char *str, /*@out@*/char **endptr, int base, int num) memcpy(phys, space, 8); /** */ -static int getNextHeader(FD_t cfd, /*@out@*/ struct cpioHeader * chPtr) +static int getNextHeader(FD_t cfd, struct cpioHeader * hdr) { struct cpioCrcPhysicalHeader physHeader; + struct stat * st = &hdr->sb; int nameSize; char * end; int major, minor; - if (ourread(cfd, &physHeader, PHYS_HDR_SIZE) != PHYS_HDR_SIZE) + if (ourread(cfd, &physHeader, PHYS_HDR_SIZE) != PHYS_HDR_SIZE) return CPIOERR_READ_FAILED; if (strncmp(CPIO_CRC_MAGIC, physHeader.magic, sizeof(CPIO_CRC_MAGIC)-1) && strncmp(CPIO_NEWC_MAGIC, physHeader.magic, sizeof(CPIO_NEWC_MAGIC)-1)) return CPIOERR_BAD_MAGIC; - GET_NUM_FIELD(physHeader.inode, chPtr->inode); - GET_NUM_FIELD(physHeader.mode, chPtr->mode); - GET_NUM_FIELD(physHeader.uid, chPtr->uid); - GET_NUM_FIELD(physHeader.gid, chPtr->gid); - GET_NUM_FIELD(physHeader.nlink, chPtr->nlink); - GET_NUM_FIELD(physHeader.mtime, chPtr->mtime); - GET_NUM_FIELD(physHeader.filesize, chPtr->size); + GET_NUM_FIELD(physHeader.inode, st->st_ino); + GET_NUM_FIELD(physHeader.mode, st->st_mode); + GET_NUM_FIELD(physHeader.uid, st->st_uid); + GET_NUM_FIELD(physHeader.gid, st->st_gid); + GET_NUM_FIELD(physHeader.nlink, st->st_nlink); + GET_NUM_FIELD(physHeader.mtime, st->st_mtime); + GET_NUM_FIELD(physHeader.filesize, st->st_size); GET_NUM_FIELD(physHeader.devMajor, major); GET_NUM_FIELD(physHeader.devMinor, minor); - chPtr->dev = /*@-shiftsigned@*/ makedev(major, minor) /*@=shiftsigned@*/ ; + st->st_dev = /*@-shiftsigned@*/ makedev(major, minor) /*@=shiftsigned@*/ ; GET_NUM_FIELD(physHeader.rdevMajor, major); GET_NUM_FIELD(physHeader.rdevMinor, minor); - chPtr->rdev = /*@-shiftsigned@*/ makedev(major, minor) /*@=shiftsigned@*/ ; + st->st_rdev = /*@-shiftsigned@*/ makedev(major, minor) /*@=shiftsigned@*/ ; GET_NUM_FIELD(physHeader.namesize, nameSize); - chPtr->path = xmalloc(nameSize + 1); - if (ourread(cfd, chPtr->path, nameSize) != nameSize) { - free(chPtr->path); - chPtr->path = NULL; - return CPIOERR_BAD_HEADER; + { char * t = xmalloc(nameSize + 1); + if (ourread(cfd, t, nameSize) != nameSize) { + free(t); + hdr->path = NULL; + return CPIOERR_BAD_HEADER; + } + hdr->path = t; } - /* this is unecessary chPtr->path[nameSize] = '\0'; */ + /* this is unecessary hdr->path[nameSize] = '\0'; */ padinfd(cfd, 4); @@ -217,7 +221,7 @@ int cpioFileMapCmp(const void * a, const void * b) /* This could trash files in the path! I'm not sure that's a good thing */ /** */ -static int createDirectory(char * path, mode_t perms) +static int createDirectory(const char * path, mode_t perms) { struct stat sb; @@ -227,7 +231,7 @@ static int createDirectory(char * path, mode_t perms) return 0; } else if (S_ISLNK(sb.st_mode)) { if (stat(path, &sb)) { - if (errno != ENOENT) + if (errno != ENOENT) return CPIOERR_STAT_FAILED; dounlink = 1; } else { @@ -258,20 +262,21 @@ static int setInfo(struct cpioHeader * hdr) { int rc = 0; struct utimbuf stamp; + struct stat * st = &hdr->sb; - stamp.actime = hdr->mtime; - stamp.modtime = hdr->mtime; + stamp.actime = st->st_mtime; + stamp.modtime = st->st_mtime; - if (!S_ISLNK(hdr->mode)) { - if (!getuid() && chown(hdr->path, hdr->uid, hdr->gid)) + if (!S_ISLNK(st->st_mode)) { + if (!getuid() && chown(hdr->path, st->st_uid, st->st_gid)) rc = CPIOERR_CHOWN_FAILED; - if (!rc && chmod(hdr->path, hdr->mode & 07777)) + if (!rc && chmod(hdr->path, st->st_mode & 07777)) rc = CPIOERR_CHMOD_FAILED; if (!rc && utime(hdr->path, &stamp)) rc = CPIOERR_UTIME_FAILED; } else { # if ! CHOWN_FOLLOWS_SYMLINK - if (!getuid() && !rc && lchown(hdr->path, hdr->uid, hdr->gid)) + if (!getuid() && !rc && lchown(hdr->path, st->st_uid, st->st_gid)) rc = CPIOERR_CHOWN_FAILED; # endif } @@ -332,7 +337,8 @@ static int expandRegular(FD_t cfd, struct cpioHeader * hdr, FD_t ofd; char buf[BUFSIZ]; int bytesRead; - int left = hdr->size; + struct stat * st = &hdr->sb; + int left = st->st_size; int rc = 0; struct cpioCallbackInfo cbInfo = { NULL, 0, 0, 0 }; struct stat sb; @@ -361,7 +367,7 @@ static int expandRegular(FD_t cfd, struct cpioHeader * hdr, return CPIOERR_OPEN_FAILED; cbInfo.file = hdr->path; - cbInfo.fileSize = hdr->size; + cbInfo.fileSize = st->st_size; while (left) { bytesRead = ourread(cfd, buf, left < sizeof(buf) ? left : sizeof(buf)); @@ -379,14 +385,14 @@ static int expandRegular(FD_t cfd, struct cpioHeader * hdr, /* don't call this with fileSize == fileComplete */ if (!rc && cb && left) { - cbInfo.fileComplete = hdr->size - left; + cbInfo.fileComplete = st->st_size - left; cbInfo.bytesProcessed = fdGetCpioPos(cfd); cb(&cbInfo, cbData); } } Fclose(ofd); - + return rc; } @@ -395,15 +401,16 @@ static int expandSymlink(FD_t cfd, struct cpioHeader * hdr) { char buf[2048], buf2[2048]; struct stat sb; + struct stat * st = &hdr->sb; int len; - if ((hdr->size + 1)> sizeof(buf)) + if ((st->st_size + 1)> sizeof(buf)) return CPIOERR_HDR_SIZE; - if (ourread(cfd, buf, hdr->size) != hdr->size) + if (ourread(cfd, buf, st->st_size) != st->st_size) return CPIOERR_READ_FAILED; - buf[hdr->size] = '\0'; + buf[st->st_size] = '\0'; if (!lstat(hdr->path, &sb)) { if (S_ISLNK(sb.st_mode)) { @@ -439,50 +446,87 @@ static int expandFifo( /*@unused@*/ FD_t cfd, struct cpioHeader * hdr) if (mkfifo(hdr->path, 0)) return CPIOERR_MKFIFO_FAILED; - return 0; + return 0; } /** */ static int expandDevice( /*@unused@*/ FD_t cfd, struct cpioHeader * hdr) { + struct stat * st = &hdr->sb; struct stat sb; if (!lstat(hdr->path, &sb)) { - if ((S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) && - (sb.st_rdev == hdr->rdev)) + if ((S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) && + (sb.st_rdev == st->st_rdev)) return 0; if (unlink(hdr->path)) return CPIOERR_UNLINK_FAILED; } - if ( /*@-unrecog@*/ mknod(hdr->path, hdr->mode & (~0777), hdr->rdev) /*@=unrecog@*/ ) + if ( /*@-unrecog@*/ mknod(hdr->path, st->st_mode & (~0777), st->st_rdev) /*@=unrecog@*/ ) return CPIOERR_MKNOD_FAILED; - + return 0; } /** */ -static void freeLink( /*@only@*/ struct hardLink * li) +static /*@only@*/ struct hardLink * newHardLink(const struct stat * st, + enum hardLinkType hltype) { - int i; + struct hardLink * li = xmalloc(sizeof(*li)); + + li->next = NULL; + li->nlink = st->st_nlink; + li->dev = st->st_dev; + li->inode = st->st_ino; + li->createdPath = -1; + + switch (hltype) { + case HARDLINK_INSTALL: + li->linksLeft = st->st_nlink; + li->fileMaps = xmalloc(sizeof(li->fileMaps[0]) * st->st_nlink); + li->files = NULL; + break; + case HARDLINK_BUILD: + li->linksLeft = 0; + li->fileMaps = NULL; + li->files = xcalloc(st->st_nlink, sizeof(*li->files)); + break; + } + li->sb = *st; /* structure assignment */ + return li; +} - for (i = 0; i < li->nlink; i++) { - if (li->files[i] == NULL) continue; - /*@-unqualifiedtrans@*/ free((void *)li->files[i]) /*@=unqualifiedtrans@*/ ; - li->files[i] = NULL; +/** */ +static void freeHardLink( /*@only@*/ struct hardLink * li) +{ + + if (li->files) { + int i; + for (i = 0; i < li->nlink; i++) { + if (li->files[i] == NULL) continue; + /*@-unqualifiedtrans@*/ free((void *)li->files[i]) /*@=unqualifiedtrans@*/ ; + li->files[i] = NULL; + } + free(li->files); + li->files = NULL; + } + if (li->fileMaps) { + free(li->fileMaps); + li->fileMaps = NULL; } - free(li->files); + free(li); } /** */ -static int createLinks(struct hardLink * li, /*@out@*/const char ** failedFile) +static int createLinks(struct hardLink * li, /*@out@*/ const char ** failedFile) { int i; struct stat sb; for (i = 0; i < li->nlink; i++) { if (i == li->createdPath) continue; - if (!li->files[i]) continue; + if (li->files[i] == NULL) continue; if (!lstat(li->files[i], &sb)) { if (unlink(li->files[i])) { @@ -511,7 +555,7 @@ static int eatBytes(FD_t cfd, int amount) { char buf[4096]; int bite; - + while (amount) { bite = (amount > sizeof(buf)) ? sizeof(buf) : amount; if (ourread(cfd, buf, bite) != bite) @@ -523,16 +567,14 @@ static int eatBytes(FD_t cfd, int amount) } /** */ -int cpioInstallArchive(FD_t cfd, struct cpioFileMapping * mappings, +int cpioInstallArchive(FD_t cfd, struct cpioFileMapping * mappings, int numMappings, cpioCallback cb, void * cbData, const char ** failedFile) { - struct cpioHeader ch; + struct cpioHeader ch, *hdr = &ch; int rc = 0; - int linkNum = 0; struct cpioFileMapping * map = NULL; struct cpioFileMapping needle; - mode_t cpioMode; int olderr; struct cpioCallbackInfo cbInfo = { NULL, 0, 0, 0 }; struct hardLink * links = NULL; @@ -542,74 +584,71 @@ int cpioInstallArchive(FD_t cfd, struct cpioFileMapping * mappings, if (failedFile) *failedFile = NULL; - ch.path = NULL; - do { - if ((rc = getNextHeader(cfd, &ch))) { + memset(hdr, 0, sizeof(*hdr)); + hdr->path = NULL; + rc = 0; + while (rc == 0) { + struct stat * st; + + if (hdr->path) { + xfree(hdr->path); + hdr->path = NULL; + } + if ((rc = getNextHeader(cfd, hdr))) { #if 0 /* XXX this is the failure point for an unreadable rpm */ fprintf(stderr, _("getNextHeader: %s\n"), cpioStrerror(rc)); #endif return rc; } + st = &hdr->sb; - if (!strcmp(ch.path, TRAILER)) { - if (ch.path) free(ch.path); + if (!strcmp(hdr->path, TRAILER)) break; - } if (mappings) { - needle.archivePath = ch.path; + needle.archivePath = hdr->path; map = bsearch(&needle, mappings, numMappings, sizeof(needle), cpioFileMapCmp); } if (mappings && !map) { - eatBytes(cfd, ch.size); + eatBytes(cfd, st->st_size); } else { - cpioMode = ch.mode; - if (map) { if (map->mapFlags & CPIO_MAP_PATH) { - if (ch.path) free(ch.path); - ch.path = xstrdup(map->fsPath); - } + if (hdr->path) xfree(hdr->path); + hdr->path = xstrdup(map->fsPath); + } if (map->mapFlags & CPIO_MAP_MODE) - ch.mode = map->finalMode; + st->st_mode = map->finalMode; if (map->mapFlags & CPIO_MAP_UID) - ch.uid = map->finalUid; + st->st_uid = map->finalUid; if (map->mapFlags & CPIO_MAP_GID) - ch.gid = map->finalGid; + st->st_gid = map->finalGid; } - /* This won't get hard linked symlinks right, but I can't seem + /* This won't get hard linked symlinks right, but I can't seem to create those anyway */ - if (S_ISREG(ch.mode) && ch.nlink > 1) { + if (S_ISREG(st->st_mode) && st->st_nlink > 1) { for (li = links; li; li = li->next) { - if (li->inode == ch.inode && li->dev == ch.dev) break; + if (li->inode == st->st_ino && li->dev == st->st_dev) break; } if (li == NULL) { - li = xmalloc(sizeof(*li)); - li->inode = ch.inode; - li->dev = ch.dev; - li->nlink = ch.nlink; - li->linksLeft = ch.nlink; - li->createdPath = -1; - li->files = xcalloc(li->nlink,(sizeof(*li->files))); + li = newHardLink(st, HARDLINK_BUILD); li->next = links; links = li; } - for (linkNum = 0; linkNum < li->nlink; linkNum++) - if (!li->files[linkNum]) break; - li->files[linkNum] = xstrdup(ch.path); + li->files[li->linksLeft++] = xstrdup(hdr->path); } - - if ((ch.nlink > 1) && S_ISREG(ch.mode) && !ch.size && + + if ((st->st_nlink > 1) && S_ISREG(st->st_mode) && !st->st_size && li->createdPath == -1) { /* defer file creation */ - } else if ((ch.nlink > 1) && S_ISREG(ch.mode) && + } else if ((st->st_nlink > 1) && S_ISREG(st->st_mode) && (li->createdPath != -1)) { createLinks(li, failedFile); @@ -618,44 +657,43 @@ int cpioInstallArchive(FD_t cfd, struct cpioFileMapping * mappings, listed (intead of the data being given just once. This shouldn't happen, but I've made it happen w/ buggy code, so what the heck? GNU cpio handles this well fwiw */ - if (ch.size) eatBytes(cfd, ch.size); + if (st->st_size) eatBytes(cfd, st->st_size); } else { - rc = checkDirectory(ch.path); + rc = checkDirectory(hdr->path); if (!rc) { - if (S_ISREG(ch.mode)) - rc = expandRegular(cfd, &ch, cb, cbData); - else if (S_ISDIR(ch.mode)) - rc = createDirectory(ch.path, 000); - else if (S_ISLNK(ch.mode)) - rc = expandSymlink(cfd, &ch); - else if (S_ISFIFO(ch.mode)) - rc = expandFifo(cfd, &ch); - else if (S_ISCHR(ch.mode) || S_ISBLK(ch.mode)) - rc = expandDevice(cfd, &ch); - else if (S_ISSOCK(ch.mode)) { + if (S_ISREG(st->st_mode)) + rc = expandRegular(cfd, hdr, cb, cbData); + else if (S_ISDIR(st->st_mode)) + rc = createDirectory(hdr->path, 000); + else if (S_ISLNK(st->st_mode)) + rc = expandSymlink(cfd, hdr); + else if (S_ISFIFO(st->st_mode)) + rc = expandFifo(cfd, hdr); + else if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) + rc = expandDevice(cfd, hdr); + else if (S_ISSOCK(st->st_mode)) { /* this mimicks cpio but probably isnt' right */ - rc = expandFifo(cfd, &ch); + rc = expandFifo(cfd, hdr); } else { rc = CPIOERR_UNKNOWN_FILETYPE; } } if (!rc) - rc = setInfo(&ch); + rc = setInfo(hdr); - if (S_ISREG(ch.mode) && ch.nlink > 1) { - li->createdPath = linkNum; - li->linksLeft--; + if (S_ISREG(st->st_mode) && st->st_nlink > 1) { + li->createdPath = li->linksLeft--; rc = createLinks(li, failedFile); } } if (rc && failedFile && *failedFile == NULL) { - *failedFile = xstrdup(ch.path); + *failedFile = xstrdup(hdr->path); olderr = errno; - unlink(ch.path); + unlink(hdr->path); errno = olderr; } } @@ -663,49 +701,41 @@ int cpioInstallArchive(FD_t cfd, struct cpioFileMapping * mappings, padinfd(cfd, 4); if (!rc && cb) { - cbInfo.file = ch.path; - cbInfo.fileSize = ch.size; - cbInfo.fileComplete = ch.size; + cbInfo.file = hdr->path; + cbInfo.fileSize = st->st_size; + cbInfo.fileComplete = st->st_size; cbInfo.bytesProcessed = fdGetCpioPos(cfd); cb(&cbInfo, cbData); } - if (ch.path) free(ch.path); - ch.path = NULL; - } while (1 && !rc); + } + + if (hdr->path) { + xfree(hdr->path); + hdr->path = NULL; + } + + /* Create any remaining links (if no error), and clean up. */ + while ((li = links) != NULL) { + links = li->next; + li->next = NULL; - li = links; - while (li && !rc) { - if (li->linksLeft) { + if (rc == 0 && li->linksLeft) { if (li->createdPath == -1) rc = CPIOERR_MISSING_HARDLINK; - else + else rc = createLinks(li, failedFile); } - freeLink(li); - - links = li; - li = li->next; - free(links); - links = li; - } - - li = links; - /* if an error got us here links will still be eating some memory */ - while (li) { - freeLink(li); - links = li; - li = li->next; - free(links); + freeHardLink(li); } return rc; } /** */ -static int writeFile(FD_t cfd, struct stat sb, struct cpioFileMapping * map, - /*@out@*/size_t * sizep, int writeData) +static int writeFile(FD_t cfd, struct stat * st, + struct cpioFileMapping * map, /*@out@*/ size_t * sizep, int writeData) { struct cpioCrcPhysicalHeader hdr; char buf[8192], symbuf[2048]; @@ -717,15 +747,15 @@ static int writeFile(FD_t cfd, struct stat sb, struct cpioFileMapping * map, if (!(map->mapFlags & CPIO_MAP_PATH)) map->archivePath = map->fsPath; if (map->mapFlags & CPIO_MAP_MODE) - sb.st_mode = (sb.st_mode & S_IFMT) | map->finalMode; + st->st_mode = (st->st_mode & S_IFMT) | map->finalMode; if (map->mapFlags & CPIO_MAP_UID) - sb.st_uid = map->finalUid; + st->st_uid = map->finalUid; if (map->mapFlags & CPIO_MAP_GID) - sb.st_gid = map->finalGid; + st->st_gid = map->finalGid; - if (!writeData || S_ISDIR(sb.st_mode)) { - sb.st_size = 0; - } else if (S_ISLNK(sb.st_mode)) { + if (!writeData || S_ISDIR(st->st_mode)) { + st->st_size = 0; + } else if (S_ISLNK(st->st_mode)) { /* While linux puts the size of a symlink in the st_size field, I don't think that's a specified standard */ @@ -734,22 +764,22 @@ static int writeFile(FD_t cfd, struct stat sb, struct cpioFileMapping * map, return CPIOERR_READLINK_FAILED; } - sb.st_size = amount; + st->st_size = amount; } memcpy(hdr.magic, CPIO_NEWC_MAGIC, sizeof(hdr.magic)); - SET_NUM_FIELD(hdr.inode, sb.st_ino, buf); - SET_NUM_FIELD(hdr.mode, sb.st_mode, buf); - SET_NUM_FIELD(hdr.uid, sb.st_uid, buf); - SET_NUM_FIELD(hdr.gid, sb.st_gid, buf); - SET_NUM_FIELD(hdr.nlink, sb.st_nlink, buf); - SET_NUM_FIELD(hdr.mtime, sb.st_mtime, buf); - SET_NUM_FIELD(hdr.filesize, sb.st_size, buf); - - num = major((unsigned)sb.st_dev); SET_NUM_FIELD(hdr.devMajor, num, buf); - num = minor((unsigned)sb.st_dev); SET_NUM_FIELD(hdr.devMinor, num, buf); - num = major((unsigned)sb.st_rdev); SET_NUM_FIELD(hdr.rdevMajor, num, buf); - num = minor((unsigned)sb.st_rdev); SET_NUM_FIELD(hdr.rdevMinor, num, buf); + SET_NUM_FIELD(hdr.inode, st->st_ino, buf); + SET_NUM_FIELD(hdr.mode, st->st_mode, buf); + SET_NUM_FIELD(hdr.uid, st->st_uid, buf); + SET_NUM_FIELD(hdr.gid, st->st_gid, buf); + SET_NUM_FIELD(hdr.nlink, st->st_nlink, buf); + SET_NUM_FIELD(hdr.mtime, st->st_mtime, buf); + SET_NUM_FIELD(hdr.filesize, st->st_size, buf); + + num = major((unsigned)st->st_dev); SET_NUM_FIELD(hdr.devMajor, num, buf); + num = minor((unsigned)st->st_dev); SET_NUM_FIELD(hdr.devMinor, num, buf); + num = major((unsigned)st->st_rdev); SET_NUM_FIELD(hdr.rdevMajor, num, buf); + num = minor((unsigned)st->st_rdev); SET_NUM_FIELD(hdr.rdevMinor, num, buf); num = strlen(map->archivePath) + 1; SET_NUM_FIELD(hdr.namesize, num, buf); memcpy(hdr.checksum, "00000000", 8); @@ -761,8 +791,8 @@ static int writeFile(FD_t cfd, struct stat sb, struct cpioFileMapping * map, size = PHYS_HDR_SIZE + num; if ((rc = padoutfd(cfd, &size, 4))) return rc; - - if (writeData && S_ISREG(sb.st_mode)) { + + if (writeData && S_ISREG(st->st_mode)) { char *b; #if HAVE_MMAP void *mapped; @@ -776,19 +806,19 @@ static int writeFile(FD_t cfd, struct stat sb, struct cpioFileMapping * map, #if HAVE_MMAP nmapped = 0; - mapped = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, Fileno(datafd), 0); + mapped = mmap(NULL, st->st_size, PROT_READ, MAP_SHARED, Fileno(datafd), 0); if (mapped != (void *)-1) { b = (char *)mapped; - nmapped = sb.st_size; + nmapped = st->st_size; } else #endif { b = buf; } - size += sb.st_size; + size += st->st_size; - while (sb.st_size) { + while (st->st_size) { #if HAVE_MMAP if (mapped != (void *)-1) { amount = nmapped; @@ -796,7 +826,7 @@ static int writeFile(FD_t cfd, struct stat sb, struct cpioFileMapping * map, #endif { amount = Fread(b, sizeof(buf[0]), - (sb.st_size > sizeof(buf) ? sizeof(buf) : sb.st_size), + (st->st_size > sizeof(buf) ? sizeof(buf) : st->st_size), datafd); if (amount <= 0) { olderrno = errno; @@ -813,17 +843,17 @@ static int writeFile(FD_t cfd, struct stat sb, struct cpioFileMapping * map, return rc; } - sb.st_size -= amount; + st->st_size -= amount; } #if HAVE_MMAP if (mapped != (void *)-1) { - munmap(mapped, nmapped); + /*@-noeffect@*/ munmap(mapped, nmapped) /*@=noeffect@*/; } #endif Fclose(datafd); - } else if (writeData && S_ISLNK(sb.st_mode)) { + } else if (writeData && S_ISLNK(st->st_mode)) { if ((rc = safewrite(cfd, symbuf, amount)) != amount) return rc; size += amount; @@ -840,7 +870,7 @@ static int writeFile(FD_t cfd, struct stat sb, struct cpioFileMapping * map, } /** */ -static int writeLinkedFile(FD_t cfd, struct hardLink * hlink, +static int writeLinkedFile(FD_t cfd, struct hardLink * hlink, struct cpioFileMapping * mappings, cpioCallback cb, void * cbData, /*@out@*/size_t * sizep, @@ -853,7 +883,7 @@ static int writeLinkedFile(FD_t cfd, struct hardLink * hlink, total = 0; for (i = hlink->nlink - 1; i > hlink->linksLeft; i--) { - if ((rc = writeFile(cfd, hlink->sb, mappings + hlink->fileMaps[i], + if ((rc = writeFile(cfd, &hlink->sb, mappings + hlink->fileMaps[i], &size, 0))) { if (failedFile) *failedFile = xstrdup(mappings[hlink->fileMaps[i]].fsPath); @@ -868,12 +898,12 @@ static int writeLinkedFile(FD_t cfd, struct hardLink * hlink, } } - if ((rc = writeFile(cfd, hlink->sb, - mappings + hlink->fileMaps[hlink->linksLeft], + if ((rc = writeFile(cfd, &hlink->sb, + mappings + hlink->fileMaps[hlink->linksLeft], &size, 1))) { if (sizep) *sizep = total; - if (failedFile) + if (failedFile) *failedFile = xstrdup(mappings[hlink->fileMaps[hlink->linksLeft]].fsPath); return rc; } @@ -891,7 +921,7 @@ static int writeLinkedFile(FD_t cfd, struct hardLink * hlink, } /** */ -int cpioBuildArchive(FD_t cfd, struct cpioFileMapping * mappings, +int cpioBuildArchive(FD_t cfd, struct cpioFileMapping * mappings, int numMappings, cpioCallback cb, void * cbData, unsigned int * archiveSize, const char ** failedFile) { @@ -900,19 +930,19 @@ int cpioBuildArchive(FD_t cfd, struct cpioFileMapping * mappings, int i; struct cpioCallbackInfo cbInfo = { NULL, 0, 0, 0 }; struct cpioCrcPhysicalHeader hdr; - struct stat sb; /*@-fullinitblock@*/ struct hardLink hlinkList = { NULL }; /*@=fullinitblock@*/ - struct hardLink * hlink, * parent; + struct stat * st = &hlinkList.sb; + struct hardLink * hlink; hlinkList.next = NULL; for (i = 0; i < numMappings; i++) { if (mappings[i].mapFlags & CPIO_FOLLOW_SYMLINKS) - rc = Stat(mappings[i].fsPath, &sb); + rc = Stat(mappings[i].fsPath, st); else - rc = Lstat(mappings[i].fsPath, &sb); + rc = Lstat(mappings[i].fsPath, st); if (rc) { if (failedFile) @@ -920,42 +950,40 @@ int cpioBuildArchive(FD_t cfd, struct cpioFileMapping * mappings, return CPIOERR_STAT_FAILED; } - if (!S_ISDIR(sb.st_mode) && sb.st_nlink > 1) { + if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) { hlink = hlinkList.next; - while (hlink && - (hlink->dev != sb.st_dev || hlink->inode != sb.st_ino)) - hlink = hlink->next; - if (!hlink) { - hlink = xmalloc(sizeof(*hlink)); + while (hlink && + (hlink->dev != st->st_dev || hlink->inode != st->st_ino)) + hlink = hlink->next; + if (hlink == NULL) { + hlink = newHardLink(st, HARDLINK_INSTALL); hlink->next = hlinkList.next; hlinkList.next = hlink; - hlink->sb = sb; /* structure assignment */ - hlink->dev = sb.st_dev; - hlink->inode = sb.st_ino; - hlink->nlink = sb.st_nlink; - hlink->linksLeft = sb.st_nlink; - hlink->fileMaps = xmalloc(sizeof(*hlink->fileMaps) * - sb.st_nlink); } hlink->fileMaps[--hlink->linksLeft] = i; - if (!hlink->linksLeft) { + if (hlink->linksLeft == 0) { + struct hardLink * prev; if ((rc = writeLinkedFile(cfd, hlink, mappings, cb, cbData, &size, failedFile))) return rc; totalsize += size; - free(hlink->fileMaps); - - parent = &hlinkList; - while (parent->next != hlink) parent = parent->next; - parent->next = parent->next->next; - free(hlink); + prev = &hlinkList; + do { + if (prev->next != hlink) + continue; + prev->next = hlink->next; + hlink->next = NULL; + freeHardLink(hlink); + hlink = NULL; + break; + } while ((prev = prev->next) != NULL); } } else { - if ((rc = writeFile(cfd, sb, mappings + i, &size, 1))) { + if ((rc = writeFile(cfd, st, mappings + i, &size, 1))) { if (failedFile) *failedFile = xstrdup(mappings[i].fsPath); return rc; @@ -968,20 +996,22 @@ int cpioBuildArchive(FD_t cfd, struct cpioFileMapping * mappings, totalsize += size; } - } + } - hlink = hlinkList.next; - while (hlink) { - if ((rc = writeLinkedFile(cfd, hlink, mappings, cb, cbData, - &size, failedFile))) - return rc; - free(hlink->fileMaps); - parent = hlink; - hlink = hlink->next; - free(parent); + rc = 0; + while ((hlink = hlinkList.next) != NULL) { + hlinkList.next = hlink->next; + hlink->next = NULL; - totalsize += size; + if (rc == 0) { + rc = writeLinkedFile(cfd, hlink, mappings, cb, cbData, + &size, failedFile); + totalsize += size; + } + freeHardLink(hlink); } + if (rc) + return rc; memset(&hdr, '0', PHYS_HDR_SIZE); memcpy(hdr.magic, CPIO_NEWC_MAGIC, sizeof(hdr.magic)); @@ -995,7 +1025,7 @@ int cpioBuildArchive(FD_t cfd, struct cpioFileMapping * mappings, /* GNU cpio pads to 512 bytes here, but we don't. I'm not sure if it matters or not */ - + if ((rc = padoutfd(cfd, &totalsize, 4))) return rc; diff --git a/lib/cpio.h b/lib/cpio.h index ed19f89d8..fb95c72eb 100644 --- a/lib/cpio.h +++ b/lib/cpio.h @@ -8,7 +8,7 @@ * standard cpio. * The implementation is pretty close, but it has some behaviors which are * more to RPM's liking. I tried to document the differing behavior in cpio.c, - * but I may have missed some. + * but I may have missed some (ewt). * */ @@ -52,35 +52,36 @@ #define CPIO_MAP_GID (1 << 3) #define CPIO_FOLLOW_SYMLINKS (1 << 4) /* only for building */ -/** The structure used to define a cpio payload file. */ +/** + * Defines a single file to be included in a cpio payload. + */ struct cpioFileMapping { -/*@{*/ - /*@owned@*/ const char * archivePath; /*!< Path to store in cpio archive. */ - /*@owned@*/ const char * fsPath; /*!< Location of payload file. */ +/*@dependent@*/ const char * archivePath; /*!< Path to store in cpio archive. */ +/*@dependent@*/ const char * fsPath; /*!< Location of payload file. */ mode_t finalMode; /*!< Mode of payload file (from header). */ uid_t finalUid; /*!< Uid of payload file (from header). */ gid_t finalGid; /*!< Gid of payload file (from header). */ int mapFlags; -/*@}*/ }; -/** The structure passed as first argument during a cpio progress callback. +/** + * The first argument passed in a cpio progress callback. * * Note: When building the cpio payload, only "file" is filled in. */ struct cpioCallbackInfo { -/*@{*/ - /*@dependent@*/ const char * file; /*!< File name being installed. */ +/*@dependent@*/ const char * file; /*!< File name being installed. */ long fileSize; /*!< Total file size. */ long fileComplete; /*!< Amount of file unpacked. */ long bytesProcessed; /*!< No. bytes in archive read. */ -/*@}*/ }; #ifdef __cplusplus extern "C" { #endif +/** + */ typedef void (*cpioCallback) (struct cpioCallbackInfo * filespec, void * data); /** @@ -103,10 +104,14 @@ int cpioBuildArchive(FD_t cfd, struct cpioFileMapping * mappings, int numMappings, cpioCallback cb, void * cbData, unsigned int * archiveSize, /*@out@*/const char ** failedFile); -/** This is designed to be qsort/bsearch compatible */ +/** + * Compare two cpio file map entries. + * This is designed to be qsort/bsearch compatible. + */ int cpioFileMapCmp(const void * a, const void * b); -/** */ +/** + */ /*@observer@*/ const char *cpioStrerror(int rc); #ifdef __cplusplus diff --git a/lib/db0.c b/lib/db0.c new file mode 100644 index 000000000..008967a43 --- /dev/null +++ b/lib/db0.c @@ -0,0 +1,327 @@ +#include "system.h" + +#include <db1/db.h> + +#define DB_VERSION_MAJOR 0 +#define DB_VERSION_MINOR 0 +#define DB_VERSION_PATCH 0 + +#define _mymemset(_a, _b, _c) + +#include <rpmlib.h> + +#include "dbindex.h" +/*@access dbiIndex@*/ +/*@access dbiIndexSet@*/ + +#include "db0.h" + +static inline DBTYPE dbi_to_dbtype(DBI_TYPE dbitype) +{ + switch(dbitype) { + case DBI_BTREE: return DB_BTREE; + case DBI_HASH: return DB_HASH; + case DBI_RECNO: return DB_RECNO; + } + /*@notreached@*/ return DB_HASH; +} + +static inline /*@observer@*/ /*@null@*/ DB * GetDB(dbiIndex dbi) { + return ((DB *)dbi->dbi_db); +} + +#if defined(__USE_DB2) +static int db_init(const char *home, int dbflags, + DB_ENV **dbenvp, DB_INFO **dbinfop) +{ + DB_ENV *dbenv = xcalloc(1, sizeof(*dbenv)); + DB_INFO *dbinfo = xcalloc(1, sizeof(*dbinfo)); + int rc; + + if (dbenvp) *dbenvp = NULL; + if (dbinfop) *dbinfop = NULL; + + dbenv->db_errfile = stderr; + dbenv->db_errpfx = "rpmdb"; + dbenv->mp_size = 1024 * 1024; + + rc = db_appinit(home, NULL, dbenv, dbflags); + if (rc) + goto errxit; + + dbinfo->db_pagesize = 1024; + + if (dbenvp) + *dbenvp = dbenv; + else + free(dbenv); + + if (dbinfop) + *dbinfop = dbinfo; + else + free(dbinfo); + + return 0; + +errxit: + if (dbenv) free(dbenv); + if (dbinfo) free(dbinfo); + return rc; +} +#endif + +int db0open(dbiIndex dbi) +{ + int rc; + +#if defined(__USE_DB2) + char * dbhome = NULL; + DB_ENV * dbenv = NULL; + DB_INFO * dbinfo = NULL; + u_int32_t dbflags; + + dbflags = ( !(dbi->dbi_flags & O_RDWR) ? DB_RDONLY : + ((dbi->dbi_flags & O_CREAT) ? DB_CREATE : 0)); + + rc = db_init(dbhome, dbflags, &dbenv, &dbinfo); + dbi->dbi_dbenv = dbenv; + dbi->dbi_dbinfo = dbinfo; + + if (rc == 0) + rc = db_open(dbi->dbi_file, dbi_to_dbtype(dbi->dbi_type), dbflags, + dbi->dbi_perms, dbenv, dbinfo, &dbi->dbi_db); + + if (rc) + dbi->dbi_db = NULL; +#else + dbi->dbi_db = dbopen(dbi->dbi_file, dbi->dbi_flags, dbi->dbi_perms, + dbi_to_dbtype(dbi->dbi_type), dbi->dbi_openinfo); +#endif + + if (dbi->dbi_db) { + rc = 0; + dbi->dbi_major = DB_VERSION_MAJOR; + dbi->dbi_minor = DB_VERSION_MINOR; + dbi->dbi_patch = DB_VERSION_PATCH; + } else + rc = 1; + + return rc; +} + +int db0close(dbiIndex dbi, unsigned int flags) { + DB * db = GetDB(dbi); + int rc; + +#if defined(__USE_DB2) + DB_ENV * dbenv = (DB_ENV *)dbi->dbi_dbenv; + DB_INFO * dbinfo = (DB_INFO *)dbi->dbi_dbinfo; + DBC * dbcursor = (DBC *)dbi->dbi_cursor; + + if (dbcursor) { + dbcursor->c_close(dbcursor) + dbi->dbi_cursor = NULL; + } + + rc = db->close(db, 0); + dbi->dbi_db = NULL; + + if (dbinfo) { + free(dbinfo); + dbi->dbi_dbinfo = NULL; + } + if (dbenv) { + (void) db_appexit(dbenv); + free(dbenv); + dbi->dbi_dbenv = NULL; + } +#else + rc = db->close(db); +#endif + + switch (rc) { + default: + case RET_ERROR: /* -1 */ + rc = -1; + break; + case RET_SPECIAL: /* 1 */ + rc = 1; + break; + case RET_SUCCESS: /* 0 */ + rc = 0; + break; + } + + return rc; +} + +int db0sync(dbiIndex dbi, unsigned int flags) { + DB * db = GetDB(dbi); + int rc; + +#if defined(__USE_DB2) + rc = db->sync(db, flags); +#else + rc = db->sync(db, flags); +#endif + + switch (rc) { + default: + case RET_ERROR: /* -1 */ + rc = -1; + break; + case RET_SPECIAL: /* 1 */ + rc = 1; + break; + case RET_SUCCESS: /* 0 */ + rc = 0; + break; + } + + return rc; +} + +int db0GetFirstKey(dbiIndex dbi, const char ** keyp) { + DBT key, data; + DB * db; + int rc; + + if (dbi == NULL || dbi->dbi_db == NULL) + return 1; + + db = GetDB(dbi); + _mymemset(&key, 0, sizeof(key)); + _mymemset(&data, 0, sizeof(data)); + + key.data = NULL; + key.size = 0; + +#if defined(__USE_DB2) + { DBC * dbcursor = NULL; + rc = dbp->cursor(dbp, NULL, &dbcursor, 0); + if (rc == 0) + rc = dbc->c_get(dbcp, &key, &data, DB_FIRST) + if (dbcursor) + dbcp->c_close(dbcursor) + } +#else + rc = db->seq(db, &key, &data, R_FIRST); +#endif + + switch (rc) { + default: + case RET_ERROR: /* -1 */ + case RET_SPECIAL: /* 1 */ + rc = 1; + break; + case RET_SUCCESS: /* 0 */ + rc = 0; + if (keyp) { + char *k = xmalloc(key.size + 1); + memcpy(k, key.data, key.size); + k[key.size] = '\0'; + *keyp = k; + } + break; + } + + return rc; +} + +int db0SearchIndex(dbiIndex dbi, const char * str, dbiIndexSet * set) { + DBT key, data; + DB * db = GetDB(dbi); + int rc; + + if (set) *set = NULL; + _mymemset(&key, 0, sizeof(key)); + _mymemset(&data, 0, sizeof(data)); + + key.data = (void *)str; + key.size = strlen(str); + data.data = NULL; + data.size = 0; + +#if defined(__USE_DB2) + rc = db->get(db, NULL, &key, &data, 0); +#else + rc = db->get(db, &key, &data, 0); +#endif + + switch (rc) { + default: + case RET_ERROR: /* -1 */ + rc = -1; + break; + case RET_SPECIAL: /* 1 */ + rc = 1; + break; + case RET_SUCCESS: /* 0 */ + rc = 0; + if (set) { + *set = dbiCreateIndexSet(); + (*set)->recs = xmalloc(data.size); + memcpy((*set)->recs, data.data, data.size); + (*set)->count = data.size / sizeof(*(*set)->recs); + } + break; + } + return rc; +} + +/*@-compmempass@*/ +int db0UpdateIndex(dbiIndex dbi, const char * str, dbiIndexSet set) { + DBT key; + DB * db = GetDB(dbi); + int rc; + + _mymemset(&key, 0, sizeof(key)); + key.data = (void *)str; + key.size = strlen(str); + + if (set->count) { + DBT data; + + _mymemset(&data, 0, sizeof(data)); + data.data = set->recs; + data.size = set->count * sizeof(*(set->recs)); + +#if defined(__USE_DB2) + rc = db->put(db, NULL, &key, &data, 0); +#else + rc = db->put(db, &key, &data, 0); +#endif + + switch (rc) { + default: + case RET_ERROR: /* -1 */ + case RET_SPECIAL: /* 1 */ + rc = 1; + break; + case RET_SUCCESS: /* 0 */ + rc = 0; + break; + } + } else { + +#if defined(__USE_DB2) + rc = db->del(db, NULL, &key, 0); +#else + rc = db->del(db, &key, 0); +#endif + + switch (rc) { + default: + case RET_ERROR: /* -1 */ + case RET_SPECIAL: /* 1 */ + rc = 1; + break; + case RET_SUCCESS: /* 0 */ + rc = 0; + break; + } + } + + return rc; +} +/*@=compmempass@*/ diff --git a/lib/db0.h b/lib/db0.h new file mode 100644 index 000000000..08f038da5 --- /dev/null +++ b/lib/db0.h @@ -0,0 +1,64 @@ +#ifndef H_DB1 +#define H_DB1 + +/** \file lib/db0.h + * Access RPM indices using Berkeley db-1.85 format and API. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Return handle for an index database. + * @param dbi index database handle + * @return 0 success 1 fail + */ +int db0open(dbiIndex dbi); + +/** + * Close index database. + * @param dbi index database handle + * @param flags + */ +int db0close(dbiIndex dbi, unsigned int flags); + +/** + * Flush pending operations to disk. + * @param dbi index database handle + * @param flags + */ +int db0sync(dbiIndex dbi, unsigned int flags); + +/** + * Return first index database key. + * @param dbi index database handle + * @param key address of first key + * @return 0 success - fails if rec is not found + */ +int db0GetFirstKey(dbiIndex dbi, const char ** keyp); + +/** + * Return items that match criteria. + * @param dbi index database handle + * @param str search key + * @param set items retrieved from index database + * @return -1 error, 0 success, 1 not found + */ +int db0SearchIndex(dbiIndex dbi, const char * str, dbiIndexSet * set); + +/** + * Change/delete items that match criteria. + * @param dbi index database handle + * @param str update key + * @param set items to update in index database + * @return 0 success, 1 not found + */ +int db0UpdateIndex(dbiIndex dbi, const char * str, dbiIndexSet set); + +#ifdef __cplusplus +} +#endif + +#endif /* H_DB1 */ + diff --git a/lib/db1.c b/lib/db1.c new file mode 100644 index 000000000..e57b9ec3f --- /dev/null +++ b/lib/db1.c @@ -0,0 +1,326 @@ +#include "system.h" + +#ifdef HAVE_DB_185_H +#include <db_185.h> + +#define _mymemset(_a, _b, _c) + +#include <rpmlib.h> + +#include "dbindex.h" +/*@access dbiIndex@*/ +/*@access dbiIndexSet@*/ + +#include "db1.h" + +static inline DBTYPE dbi_to_dbtype(DBI_TYPE dbitype) +{ + switch(dbitype) { + case DBI_BTREE: return DB_BTREE; + case DBI_HASH: return DB_HASH; + case DBI_RECNO: return DB_RECNO; + } + /*@notreached@*/ return DB_HASH; +} + +static inline /*@observer@*/ /*@null@*/ DB * GetDB(dbiIndex dbi) { + return ((DB *)dbi->dbi_db); +} + +#if defined(__USE_DB2) +static int db_init(const char *home, int dbflags, + DB_ENV **dbenvp, DB_INFO **dbinfop) +{ + DB_ENV *dbenv = xcalloc(1, sizeof(*dbenv)); + DB_INFO *dbinfo = xcalloc(1, sizeof(*dbinfo)); + int rc; + + if (dbenvp) *dbenvp = NULL; + if (dbinfop) *dbinfop = NULL; + + dbenv->db_errfile = stderr; + dbenv->db_errpfx = "rpmdb"; + dbenv->mp_size = 1024 * 1024; + + rc = db_appinit(home, NULL, dbenv, dbflags); + if (rc) + goto errxit; + + dbinfo->db_pagesize = 1024; + + if (dbenvp) + *dbenvp = dbenv; + else + free(dbenv); + + if (dbinfop) + *dbinfop = dbinfo; + else + free(dbinfo); + + return 0; + +errxit: + if (dbenv) free(dbenv); + if (dbinfo) free(dbinfo); + return rc; +} +#endif + +int db1open(dbiIndex dbi) +{ + int rc; + +#if defined(__USE_DB2) + char * dbhome = NULL; + DB_ENV * dbenv = NULL; + DB_INFO * dbinfo = NULL; + u_int32_t dbflags; + + dbflags = ( !(dbi->dbi_flags & O_RDWR) ? DB_RDONLY : + ((dbi->dbi_flags & O_CREAT) ? DB_CREATE : 0)); + + rc = db_init(dbhome, dbflags, &dbenv, &dbinfo); + dbi->dbi_dbenv = dbenv; + dbi->dbi_dbinfo = dbinfo; + + if (rc == 0) + rc = db_open(dbi->dbi_file, dbi_to_dbtype(dbi->dbi_type), dbflags, + dbi->dbi_perms, dbenv, dbinfo, &dbi->dbi_db); + + if (rc) + dbi->dbi_db = NULL; +#else + dbi->dbi_db = dbopen(dbi->dbi_file, dbi->dbi_flags, dbi->dbi_perms, + dbi_to_dbtype(dbi->dbi_type), dbi->dbi_openinfo); +#endif + + if (dbi->dbi_db) { + rc = 0; + dbi->dbi_major = DB_VERSION_MAJOR; + dbi->dbi_minor = DB_VERSION_MINOR; + dbi->dbi_patch = DB_VERSION_PATCH; + } else + rc = 1; + + return rc; +} + +int db1close(dbiIndex dbi, unsigned int flags) { + DB * db = GetDB(dbi); + int rc; + +#if defined(__USE_DB2) + DB_ENV * dbenv = (DB_ENV *)dbi->dbi_dbenv; + DB_INFO * dbinfo = (DB_INFO *)dbi->dbi_dbinfo; + DBC * dbcursor = (DBC *)dbi->dbi_cursor; + + if (dbcursor) { + dbcursor->c_close(dbcursor) + dbi->dbi_cursor = NULL; + } + + rc = db->close(db, 0); + dbi->dbi_db = NULL; + + if (dbinfo) { + free(dbinfo); + dbi->dbi_dbinfo = NULL; + } + if (dbenv) { + (void) db_appexit(dbenv); + free(dbenv); + dbi->dbi_dbenv = NULL; + } +#else + rc = db->close(db); +#endif + + switch (rc) { + default: + case RET_ERROR: /* -1 */ + rc = -1; + break; + case RET_SPECIAL: /* 1 */ + rc = 1; + break; + case RET_SUCCESS: /* 0 */ + rc = 0; + break; + } + + return rc; +} + +int db1sync(dbiIndex dbi, unsigned int flags) { + DB * db = GetDB(dbi); + int rc; + +#if defined(__USE_DB2) + rc = db->sync(db, flags); +#else + rc = db->sync(db, flags); +#endif + + switch (rc) { + default: + case RET_ERROR: /* -1 */ + rc = -1; + break; + case RET_SPECIAL: /* 1 */ + rc = 1; + break; + case RET_SUCCESS: /* 0 */ + rc = 0; + break; + } + + return rc; +} + +int db1GetFirstKey(dbiIndex dbi, const char ** keyp) { + DBT key, data; + DB * db; + int rc; + + if (dbi == NULL || dbi->dbi_db == NULL) + return 1; + + db = GetDB(dbi); + _mymemset(&key, 0, sizeof(key)); + _mymemset(&data, 0, sizeof(data)); + + key.data = NULL; + key.size = 0; + +#if defined(__USE_DB2) + { DBC * dbcursor = NULL; + rc = dbp->cursor(dbp, NULL, &dbcursor, 0); + if (rc == 0) + rc = dbc->c_get(dbcp, &key, &data, DB_FIRST) + if (dbcursor) + dbcp->c_close(dbcursor) + } +#else + rc = db->seq(db, &key, &data, R_FIRST); +#endif + + switch (rc) { + default: + case RET_ERROR: /* -1 */ + case RET_SPECIAL: /* 1 */ + rc = 1; + break; + case RET_SUCCESS: /* 0 */ + rc = 0; + if (keyp) { + char *k = xmalloc(key.size + 1); + memcpy(k, key.data, key.size); + k[key.size] = '\0'; + *keyp = k; + } + break; + } + + return rc; +} + +int db1SearchIndex(dbiIndex dbi, const char * str, dbiIndexSet * set) { + DBT key, data; + DB * db = GetDB(dbi); + int rc; + + if (set) *set = NULL; + _mymemset(&key, 0, sizeof(key)); + _mymemset(&data, 0, sizeof(data)); + + key.data = (void *)str; + key.size = strlen(str); + data.data = NULL; + data.size = 0; + +#if defined(__USE_DB2) + rc = db->get(db, NULL, &key, &data, 0); +#else + rc = db->get(db, &key, &data, 0); +#endif + + switch (rc) { + default: + case RET_ERROR: /* -1 */ + rc = -1; + break; + case RET_SPECIAL: /* 1 */ + rc = 1; + break; + case RET_SUCCESS: /* 0 */ + rc = 0; + if (set) { + *set = dbiCreateIndexSet(); + (*set)->recs = xmalloc(data.size); + memcpy((*set)->recs, data.data, data.size); + (*set)->count = data.size / sizeof(*(*set)->recs); + } + break; + } + return rc; +} + +/*@-compmempass@*/ +int db1UpdateIndex(dbiIndex dbi, const char * str, dbiIndexSet set) { + DBT key; + DB * db = GetDB(dbi); + int rc; + + _mymemset(&key, 0, sizeof(key)); + key.data = (void *)str; + key.size = strlen(str); + + if (set->count) { + DBT data; + + _mymemset(&data, 0, sizeof(data)); + data.data = set->recs; + data.size = set->count * sizeof(*(set->recs)); + +#if defined(__USE_DB2) + rc = db->put(db, NULL, &key, &data, 0); +#else + rc = db->put(db, &key, &data, 0); +#endif + + switch (rc) { + default: + case RET_ERROR: /* -1 */ + case RET_SPECIAL: /* 1 */ + rc = 1; + break; + case RET_SUCCESS: /* 0 */ + rc = 0; + break; + } + } else { + +#if defined(__USE_DB2) + rc = db->del(db, NULL, &key, 0); +#else + rc = db->del(db, &key, 0); +#endif + + switch (rc) { + default: + case RET_ERROR: /* -1 */ + case RET_SPECIAL: /* 1 */ + rc = 1; + break; + case RET_SUCCESS: /* 0 */ + rc = 0; + break; + } + } + + return rc; +} +/*@=compmempass@*/ + +#endif /* HABE_DB_185_H */ diff --git a/lib/db1.h b/lib/db1.h new file mode 100644 index 000000000..35d9aa785 --- /dev/null +++ b/lib/db1.h @@ -0,0 +1,68 @@ +#ifndef H_DB185 +#define H_DB185 + +/** \file lib/db1.h + * Access RPM indices using Berkeley db2 with db-1.85 API. + */ + +#define DB_VERSION_MAJOR 1 +#define DB_VERSION_MINOR 85 +#define DB_VERSION_PATCH 0 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Return handle for an index database. + * @param dbi index database handle + * @return 0 success 1 fail + */ +int db1open(dbiIndex dbi); + +/** + * Close index database. + * @param dbi index database handle + * @param flags + */ +int db1close(dbiIndex dbi, unsigned int flags); + +/** + * Flush pending operations to disk. + * @param dbi index database handle + * @param flags + */ +int db1sync(dbiIndex dbi, unsigned int flags); + +/** + * Return first index database key. + * @param dbi index database handle + * @param key address of first key + * @return 0 success - fails if rec is not found + */ +int db1GetFirstKey(dbiIndex dbi, const char ** keyp); + +/** + * Return items that match criteria. + * @param dbi index database handle + * @param str search key + * @param set items retrieved from index database + * @return -1 error, 0 success, 1 not found + */ +int db1SearchIndex(dbiIndex dbi, const char * str, dbiIndexSet * set); + +/** + * Change/delete items that match criteria. + * @param dbi index database handle + * @param str update key + * @param set items to update in index database + * @return 0 success, 1 not found + */ +int db1UpdateIndex(dbiIndex dbi, const char * str, dbiIndexSet set); + +#ifdef __cplusplus +} +#endif + +#endif /* H_DB185 */ + diff --git a/lib/db2.c b/lib/db2.c new file mode 100644 index 000000000..fa5e01f0e --- /dev/null +++ b/lib/db2.c @@ -0,0 +1,329 @@ +#include "system.h" + +#include <db.h> + + +#include <rpmlib.h> + +#include "dbindex.h" +/*@access dbiIndex@*/ +/*@access dbiIndexSet@*/ + +#include "db2.h" + +#if DB_VERSION_MAJOR == 2 +#define __USE_DB2 1 +#define _mymemset(_a, _b, _c) memset((_a), (_b), (_c)) + +static inline DBTYPE dbi_to_dbtype(DBI_TYPE dbitype) +{ + switch(dbitype) { + case DBI_BTREE: return DB_BTREE; + case DBI_HASH: return DB_HASH; + case DBI_RECNO: return DB_RECNO; + } + /*@notreached@*/ return DB_HASH; +} + +static inline /*@observer@*/ /*@null@*/ DB * GetDB(dbiIndex dbi) { + return ((DB *)dbi->dbi_db); +} + +#if defined(__USE_DB2) +static int db_init(dbiIndex dbi, const char *home, int dbflags, + DB_ENV **dbenvp, DB_INFO **dbinfop) +{ + DB_ENV *dbenv = xcalloc(1, sizeof(*dbenv)); + DB_INFO *dbinfo = xcalloc(1, sizeof(*dbinfo)); + int rc; + + if (dbenvp) *dbenvp = NULL; + if (dbinfop) *dbinfop = NULL; + + dbenv->db_errfile = stderr; + dbenv->db_errpfx = "rpmdb"; + dbenv->mp_size = 1024 * 1024; + +#define _DBFMASK (DB_CREATE|DB_NOMMAP|DB_THREAD) + rc = db_appinit(home, NULL, dbenv, (dbflags & _DBFMASK)); + if (rc) + goto errxit; + + dbinfo->db_pagesize = 1024; + + if (dbenvp) + *dbenvp = dbenv; + else + free(dbenv); + + if (dbinfop) + *dbinfop = dbinfo; + else + free(dbinfo); + + return 0; + +errxit: + if (dbenv) free(dbenv); + if (dbinfo) free(dbinfo); + return rc; +} +#endif + +int db2open(dbiIndex dbi) +{ + int rc = 0; + +#if defined(__USE_DB2) + char * dbhome = NULL; + DB * db = NULL; + DB_ENV * dbenv = NULL; + DB_INFO * dbinfo = NULL; + u_int32_t dbflags; + + dbflags = ( !(dbi->dbi_flags & O_RDWR) ? DB_RDONLY : + ((dbi->dbi_flags & O_CREAT) ? DB_CREATE : 0)); + + rc = db_init(dbi, dbhome, dbflags, &dbenv, &dbinfo); + + if (rc == 0) + rc = db_open(dbi->dbi_file, dbi_to_dbtype(dbi->dbi_type), dbflags, + dbi->dbi_perms, dbenv, dbinfo, &db); + + dbi->dbi_db = db; + dbi->dbi_dbenv = dbenv; + dbi->dbi_dbinfo = dbinfo; + +#else + dbi->dbi_db = dbopen(dbi->dbi_file, dbi->dbi_flags, dbi->dbi_perms, + dbi_to_dbtype(dbi->dbi_type), dbi->dbi_openinfo); +#endif + + if (rc == 0 && dbi->dbi_db != NULL) { + rc = 0; + dbi->dbi_major = DB_VERSION_MAJOR; + dbi->dbi_minor = DB_VERSION_MINOR; + dbi->dbi_patch = DB_VERSION_PATCH; + } else + rc = 1; + + return rc; +} + +int db2close(dbiIndex dbi, unsigned int flags) { + DB * db = GetDB(dbi); + int rc; + +#if defined(__USE_DB2) + DB_ENV * dbenv = (DB_ENV *)dbi->dbi_dbenv; + DB_INFO * dbinfo = (DB_INFO *)dbi->dbi_dbinfo; + DBC * dbcursor = (DBC *)dbi->dbi_dbcursor; + + if (dbcursor) { + (void)dbcursor->c_close(dbcursor); + dbi->dbi_dbcursor = NULL; + } + + rc = db->close(db, 0); + dbi->dbi_db = NULL; + + if (dbinfo) { + free(dbinfo); + dbi->dbi_dbinfo = NULL; + } + if (dbenv) { + (void) db_appexit(dbenv); + free(dbenv); + dbi->dbi_dbenv = NULL; + } +#else + rc = db->close(db); +#endif + + switch (rc) { + default: + case RET_ERROR: /* -1 */ + rc = -1; + break; + case RET_SPECIAL: /* 1 */ + rc = 1; + break; + case RET_SUCCESS: /* 0 */ + rc = 0; + break; + } + + return rc; +} + +int db2sync(dbiIndex dbi, unsigned int flags) { + DB * db = GetDB(dbi); + int rc; + +#if defined(__USE_DB2) + rc = db->sync(db, flags); +#else + rc = db->sync(db, flags); +#endif + + switch (rc) { + default: + case RET_ERROR: /* -1 */ + rc = -1; + break; + case RET_SPECIAL: /* 1 */ + rc = 1; + break; + case RET_SUCCESS: /* 0 */ + rc = 0; + break; + } + + return rc; +} + +int db2GetFirstKey(dbiIndex dbi, const char ** keyp) { + DBT key, data; + DB * db; + int rc; + + if (dbi == NULL || dbi->dbi_db == NULL) + return 1; + + db = GetDB(dbi); + _mymemset(&key, 0, sizeof(key)); + _mymemset(&data, 0, sizeof(data)); + + key.data = NULL; + key.size = 0; + +#if defined(__USE_DB2) + { DBC * dbcursor = NULL; + rc = db->cursor(db, NULL, &dbcursor); + if (rc == 0) + rc = dbcursor->c_get(dbcursor, &key, &data, DB_FIRST); + if (dbcursor) + (void)dbcursor->c_close(dbcursor); + } +#else + rc = db->seq(db, &key, &data, R_FIRST); +#endif + + switch (rc) { + default: + case RET_ERROR: /* -1 */ + case RET_SPECIAL: /* 1 */ + rc = 1; + break; + case RET_SUCCESS: /* 0 */ + rc = 0; + if (keyp) { + char *k = xmalloc(key.size + 1); + memcpy(k, key.data, key.size); + k[key.size] = '\0'; + *keyp = k; + } + break; + } + + return rc; +} + +int db2SearchIndex(dbiIndex dbi, const char * str, dbiIndexSet * set) { + DBT key, data; + DB * db = GetDB(dbi); + int rc; + + if (set) *set = NULL; + _mymemset(&key, 0, sizeof(key)); + _mymemset(&data, 0, sizeof(data)); + + key.data = (void *)str; + key.size = strlen(str); + data.data = NULL; + data.size = 0; + +#if defined(__USE_DB2) + rc = db->get(db, NULL, &key, &data, 0); +#else + rc = db->get(db, &key, &data, 0); +#endif + + switch (rc) { + default: + case RET_ERROR: /* -1 */ + rc = -1; + break; + case RET_SPECIAL: /* 1 */ + rc = 1; + break; + case RET_SUCCESS: /* 0 */ + rc = 0; + if (set) { + *set = dbiCreateIndexSet(); + (*set)->recs = xmalloc(data.size); + memcpy((*set)->recs, data.data, data.size); + (*set)->count = data.size / sizeof(*(*set)->recs); + } + break; + } + return rc; +} + +/*@-compmempass@*/ +int db2UpdateIndex(dbiIndex dbi, const char * str, dbiIndexSet set) { + DBT key; + DB * db = GetDB(dbi); + int rc; + + _mymemset(&key, 0, sizeof(key)); + key.data = (void *)str; + key.size = strlen(str); + + if (set->count) { + DBT data; + + _mymemset(&data, 0, sizeof(data)); + data.data = set->recs; + data.size = set->count * sizeof(*(set->recs)); + +#if defined(__USE_DB2) + rc = db->put(db, NULL, &key, &data, 0); +#else + rc = db->put(db, &key, &data, 0); +#endif + + switch (rc) { + default: + case RET_ERROR: /* -1 */ + case RET_SPECIAL: /* 1 */ + rc = 1; + break; + case RET_SUCCESS: /* 0 */ + rc = 0; + break; + } + } else { + +#if defined(__USE_DB2) + rc = db->del(db, NULL, &key, 0); +#else + rc = db->del(db, &key, 0); +#endif + + switch (rc) { + default: + case RET_ERROR: /* -1 */ + case RET_SPECIAL: /* 1 */ + rc = 1; + break; + case RET_SUCCESS: /* 0 */ + rc = 0; + break; + } + } + + return rc; +} +/*@=compmempass@*/ +#endif /* DB_VERSION_MAJOR == 2 */ diff --git a/lib/db2.h b/lib/db2.h new file mode 100644 index 000000000..eeaff4509 --- /dev/null +++ b/lib/db2.h @@ -0,0 +1,68 @@ +#ifndef H_DB2 +#define H_DB2 + +/** \file lib/db2.h + * Access RPM indices using Berkeley db-2.x API. + */ + +#define RET_ERROR 1 +#define RET_SUCCESS 0 +#define RET_SPECIAL -1 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Return handle for an index database. + * @param dbi index database handle + * @return 0 success 1 fail + */ +int db2open(dbiIndex dbi); + +/** + * Close index database. + * @param dbi index database handle + * @param flags + */ +int db2close(dbiIndex dbi, unsigned int flags); + +/** + * Flush pending operations to disk. + * @param dbi index database handle + * @param flags + */ +int db2sync(dbiIndex dbi, unsigned int flags); + +/** + * Return first index database key. + * @param dbi index database handle + * @param key address of first key + * @return 0 success - fails if rec is not found + */ +int db2GetFirstKey(dbiIndex dbi, const char ** keyp); + +/** + * Return items that match criteria. + * @param dbi index database handle + * @param str search key + * @param set items retrieved from index database + * @return -1 error, 0 success, 1 not found + */ +int db2SearchIndex(dbiIndex dbi, const char * str, dbiIndexSet * set); + +/** + * Change/delete items that match criteria. + * @param dbi index database handle + * @param str update key + * @param set items to update in index database + * @return 0 success, 1 not found + */ +int db2UpdateIndex(dbiIndex dbi, const char * str, dbiIndexSet set); + +#ifdef __cplusplus +} +#endif + +#endif /* H_DB2 */ + diff --git a/lib/dbindex.c b/lib/dbindex.c index 5e8659f47..3a497113c 100644 --- a/lib/dbindex.c +++ b/lib/dbindex.c @@ -3,167 +3,242 @@ #include <rpmlib.h> #include <rpmurl.h> +#include "dbindex.h" +/*@access dbiIndex@*/ +/*@access dbiIndexSet@*/ +/*@access dbiIndexRecord@*/ + +#include "db0.h" +#include "db1.h" +#include "db2.h" + unsigned int dbiIndexSetCount(dbiIndexSet set) { - return set.count; + return set->count; } -/* structure return */ dbiIndexRecord dbiReturnIndexRecordInstance(unsigned int recOffset, unsigned int fileNumber) { - dbiIndexRecord rec; - rec.recOffset = recOffset; - rec.fileNumber = fileNumber; + dbiIndexRecord rec = xmalloc(sizeof(*rec)); + rec->recOffset = recOffset; + rec->fileNumber = fileNumber; return rec; } +void dbiFreeIndexRecordInstance(dbiIndexRecord rec) { + if (rec) free(rec); +} + unsigned int dbiIndexRecordOffset(dbiIndexSet set, int recno) { - return set.recs[recno].recOffset; + return set->recs[recno].recOffset; } unsigned int dbiIndexRecordFileNumber(dbiIndexSet set, int recno) { - return set.recs[recno].fileNumber; + return set->recs[recno].fileNumber; +} + +void dbiIndexRecordOffsetSave(dbiIndexSet set, int recno, unsigned int recoff) { + set->recs[recno].recOffset = recoff; } -dbiIndex * dbiOpenIndex(const char * urlfn, int flags, int perms, DBTYPE type) { - dbiIndex * dbi; +static dbiIndex newDBI(void) { + dbiIndex dbi = xcalloc(1, sizeof(*dbi)); + return dbi; +} + +static void freeDBI( /*@only@*/ /*@null@*/ dbiIndex dbi) { + if (dbi) { + if (dbi->dbi_dbenv) free(dbi->dbi_dbenv); + if (dbi->dbi_dbinfo) free(dbi->dbi_dbinfo); + if (dbi->dbi_file) xfree(dbi->dbi_file); + xfree(dbi); + } +} + +dbiIndex dbiOpenIndex(const char * urlfn, int flags, int perms, DBI_TYPE type) { + dbiIndex dbi; const char * filename; - + int rc; + (void) urlPath(urlfn, &filename); - dbi = xmalloc(sizeof(*dbi)); - if (*filename == '\0' || - (dbi->db = dbopen(filename, flags, perms, type, NULL)) == NULL) { - free(dbi); - rpmError(RPMERR_DBOPEN, _("cannot open file %s: %s"), urlfn, + if (*filename == '\0') { + rpmError(RPMERR_DBOPEN, _("bad db file %s"), urlfn); + return NULL; + } + + dbi = newDBI(); + dbi->dbi_file = xstrdup(filename); + dbi->dbi_flags = flags; + dbi->dbi_perms = perms; + dbi->dbi_type = type; + dbi->dbi_openinfo = NULL; + dbi->dbi_major = 1; + + rc = db0open(dbi); + + if (rc) { + freeDBI(dbi); + rpmError(RPMERR_DBOPEN, _("cannot open file %s: %s"), urlfn, strerror(errno)); return NULL; } - dbi->indexname = xstrdup(filename); return dbi; } -void dbiCloseIndex(dbiIndex * dbi) { - dbi->db->close(dbi->db); - xfree(dbi->indexname); - free(dbi); +int dbiCloseIndex(dbiIndex dbi) { + int rc; + + switch (dbi->dbi_major) { + case 2: + rc = db2close(dbi, 0); + break; + case 1: + rc = db1close(dbi, 0); + break; + default: + case 0: + rc = db0close(dbi, 0); + break; + } + freeDBI(dbi); + return rc; } -void dbiSyncIndex(dbiIndex * dbi) { - dbi->db->sync(dbi->db, 0); +int dbiSyncIndex(dbiIndex dbi) { + int rc; + + switch (dbi->dbi_major) { + case 2: + rc = db2sync(dbi, 0); + break; + case 1: + rc = db1sync(dbi, 0); + break; + default: + case 0: + rc = db0sync(dbi, 0); + break; + } + return rc; } -int dbiGetFirstKey(dbiIndex * dbi, const char ** keyp) { - DBT key, data; +int dbiGetFirstKey(dbiIndex dbi, const char ** keyp) { int rc; - if (dbi == NULL || dbi->db == NULL) + if (dbi == NULL) return 1; - - key.data = NULL; - key.size = 0; - rc = dbi->db->seq(dbi->db, &key, &data, R_FIRST); - if (rc) { - return 1; - } - { char *k = xmalloc(key.size + 1); - memcpy(k, key.data, key.size); - k[key.size] = '\0'; - *keyp = k; + switch (dbi->dbi_major) { + case 2: + rc = db2GetFirstKey(dbi, keyp); + break; + case 1: + rc = db1GetFirstKey(dbi, keyp); + break; + default: + case 0: + rc = db0GetFirstKey(dbi, keyp); + break; } - - return 0; + return rc; } -int dbiSearchIndex(dbiIndex * dbi, const char * str, dbiIndexSet * set) { - DBT key, data; +int dbiSearchIndex(dbiIndex dbi, const char * str, dbiIndexSet * set) { int rc; - key.data = (void *)str; - key.size = strlen(str); - data.data = NULL; - data.size = 0; + switch (dbi->dbi_major) { + case 2: + rc = db2SearchIndex(dbi, str, set); + break; + case 1: + rc = db1SearchIndex(dbi, str, set); + break; + default: + case 0: + rc = db0SearchIndex(dbi, str, set); + break; + } - rc = dbi->db->get(dbi->db, &key, &data, 0); - if (rc == -1) { + switch (rc) { + case -1: rpmError(RPMERR_DBGETINDEX, _("error getting record %s from %s"), - str, dbi->indexname); - return -1; - } else if (rc == 1) { - return 1; - } - - set->recs = xmalloc(data.size); - memcpy(set->recs, data.data, data.size); - set->count = data.size / sizeof(dbiIndexRecord); - return 0; + str, dbi->dbi_file); + break; + } + return rc; } -int dbiUpdateIndex(dbiIndex * dbi, const char * str, dbiIndexSet * set) { - /* 0 on success */ - DBT key, data; +int dbiUpdateIndex(dbiIndex dbi, const char * str, dbiIndexSet set) { int rc; - key.data = (void *)str; - key.size = strlen(str); + switch (dbi->dbi_major) { + default: + case 2: + rc = db2UpdateIndex(dbi, str, set); + break; + case 1: + rc = db1UpdateIndex(dbi, str, set); + break; + case 0: + rc = db0UpdateIndex(dbi, str, set); + break; + } if (set->count) { - data.data = set->recs; - data.size = set->count * sizeof(dbiIndexRecord); - - rc = dbi->db->put(dbi->db, &key, &data, 0); if (rc) { rpmError(RPMERR_DBPUTINDEX, _("error storing record %s into %s"), - str, dbi->indexname); - return 1; + str, dbi->dbi_file); } } else { - rc = dbi->db->del(dbi->db, &key, 0); if (rc) { rpmError(RPMERR_DBPUTINDEX, _("error removing record %s into %s"), - str, dbi->indexname); - return 1; + str, dbi->dbi_file); } } - return 0; + return rc; } -int dbiAppendIndexRecord(dbiIndexSet * set, dbiIndexRecord rec) { +int dbiAppendIndexRecord(dbiIndexSet set, + unsigned int recOffset, unsigned int fileNumber) +{ set->count++; if (set->count == 1) { - set->recs = xmalloc(set->count * sizeof(dbiIndexRecord)); + set->recs = xmalloc(set->count * sizeof(*(set->recs))); } else { - set->recs = xrealloc(set->recs, set->count * sizeof(dbiIndexRecord)); + set->recs = xrealloc(set->recs, set->count * sizeof(*(set->recs))); } - set->recs[set->count - 1] = rec; + set->recs[set->count - 1].recOffset = recOffset; + set->recs[set->count - 1].fileNumber = fileNumber; return 0; } -/* structure return */ -dbiIndexSet dbiCreateIndexRecord(void) { - dbiIndexSet set; +dbiIndexSet dbiCreateIndexSet(void) { + dbiIndexSet set = xmalloc(sizeof(*set)); - set.recs = NULL; - set.count = 0; + set->recs = NULL; + set->count = 0; return set; } - -void dbiFreeIndexRecord(dbiIndexSet set) { - if (set.recs) free(set.recs); - set.recs = NULL; + +void dbiFreeIndexSet(dbiIndexSet set) { + if (set) { + if (set->recs) free(set->recs); + free(set); + } } /* returns 1 on failure */ -int dbiRemoveIndexRecord(dbiIndexSet * set, dbiIndexRecord rec) { +int dbiRemoveIndexRecord(dbiIndexSet set, dbiIndexRecord rec) { int from; int to = 0; int num = set->count; int numCopied = 0; - + for (from = 0; from < num; from++) { - if (rec.recOffset != set->recs[from].recOffset || - rec.fileNumber != set->recs[from].fileNumber) { + if (rec->recOffset != set->recs[from].recOffset || + rec->fileNumber != set->recs[from].fileNumber) { + /* structure assignment */ if (from != to) set->recs[to] = set->recs[from]; to++; numCopied++; diff --git a/lib/dbindex.h b/lib/dbindex.h index b7e15caca..694d39e54 100644 --- a/lib/dbindex.h +++ b/lib/dbindex.h @@ -1,60 +1,140 @@ #ifndef H_DBINDEX #define H_DBINDEX -#ifdef HAVE_DB1_DB_H -#include <db1/db.h> -#else -#ifdef HAVE_DB_185_H -#include <db_185.h> -#else -#include <db.h> -#endif -#endif +/** \file lib/dbindex.h + * Access RPM indices using Berkeley db[123] interface. + */ -/* this will break if sizeof(int) != 4 */ +typedef void DBI_t; +typedef enum { DBI_BTREE, DBI_HASH, DBI_RECNO } DBI_TYPE; -typedef /*@abstract@*/ struct { - unsigned int recOffset; - unsigned int fileNumber; -} dbiIndexRecord; +typedef /*@abstract@*/ struct _dbiIndexRecord * dbiIndexRecord; +typedef /*@abstract@*/ struct _dbiIndex * dbiIndex; -typedef /*@abstract@*/ struct { - /*@only@*/ dbiIndexRecord * recs; - int count; -} dbiIndexSet; +/* this will break if sizeof(int) != 4 */ +/** + * A single item in an index database. + * Note: In rpm-3.0.4 and earlier, this structure was passed by value. + */ +struct _dbiIndexRecord { + unsigned int recOffset; /*!< byte offset of header in db */ + unsigned int fileNumber; /*!< file array index */ +}; -typedef /*@abstract@*/ struct { - DB * db; - const char * indexname; -} dbiIndex; +/** + * Items retrieved from the index database. + */ +struct _dbiIndexSet { +/*@owned@*/ struct _dbiIndexRecord * recs; /*!< array of records */ + int count; /*!< number of records */ +}; + +/** + * Describes an index database (implemented on Berkeley db[123] API). + */ +struct _dbiIndex { + void * dbi_db; /*<! Berkeley db[123] handle */ + void * dbi_dbenv; + void * dbi_dbinfo; + void * dbi_dbcursor; + const char * dbi_file; /*<! name of index database */ + int dbi_flags; /*<! flags to use on open */ + int dbi_perms; /*<! file permission to use on open */ + DBI_TYPE dbi_type; /*<! type of access */ + const void * dbi_openinfo; /*<! private data passed on open */ + int dbi_major; /*<! Berkeley db version major */ + int dbi_minor; /*<! Berkeley db version minor */ + int dbi_patch; /*<! Berkeley db version patch */ +}; #ifdef __cplusplus extern "C" { #endif -/*@only@*/ dbiIndex * dbiOpenIndex(const char * filename, int flags, int perms, DBTYPE type); -void dbiCloseIndex( /*@only@*/ dbiIndex * dbi); -void dbiSyncIndex(dbiIndex * dbi); -int dbiSearchIndex(dbiIndex * dbi, const char * str, /*@out@*/ dbiIndexSet * set); - /* -1 error, 0 success, 1 not found */ -int dbiUpdateIndex(dbiIndex * dbi, const char * str, dbiIndexSet * set); - /* 0 on success */ -int dbiAppendIndexRecord( /*@out@*/ dbiIndexSet * set, dbiIndexRecord rec); - /* 0 on success - should never fail */ -int dbiRemoveIndexRecord(dbiIndexSet * set, dbiIndexRecord rec); - /* 0 on success - fails if rec is not found */ -dbiIndexSet dbiCreateIndexRecord(void); -void dbiFreeIndexRecord(dbiIndexSet set); -int dbiGetFirstKey(dbiIndex * dbi, /*@out@*/ const char ** key); - -extern unsigned int dbiIndexSetCount(dbiIndexSet set); - -/* structure return */ -extern dbiIndexRecord dbiReturnIndexRecordInstance(unsigned int recOffset, unsigned int fileNumber); - -extern unsigned int dbiIndexRecordOffset(dbiIndexSet set, int recno); - -extern unsigned int dbiIndexRecordFileNumber(dbiIndexSet set, int recno); +/** + * Return handle for an index database. + * @param filename file name of database + * @param flags type of open + * @param perm permissions on database file + * @param type one of { DBI_BTREE, DBI_HASH, DBI_RECNO } + * @return index database handle + */ +/*@only@*/ dbiIndex dbiOpenIndex(const char * filename, int flags, int perms, + DBI_TYPE type); + +/** + * Close index database. + * @param dbi index database handle + */ +int dbiCloseIndex( /*@only@*/ dbiIndex dbi); + +/** + * Flush pending operations to disk. + * @param dbi index database handle + */ +int dbiSyncIndex(dbiIndex dbi); + +/** + * Return items that match criteria. + * @param dbi index database handle + * @param str search key + * @param set items retrieved from index database + * @return -1 error, 0 success, 1 not found + */ +int dbiSearchIndex(dbiIndex dbi, const char * str, /*@out@*/ dbiIndexSet * set); + +/** + * Change/delete items that match criteria. + * @param dbi index database handle + * @param str update key + * @param set items to update in index database + * @return 0 success, 1 not found + */ +int dbiUpdateIndex(dbiIndex dbi, const char * str, dbiIndexSet set); + +/** + * Append element to set of index database items. + * @param set set of index database items + * @param rec item to append to set + * @return 0 success (always) + */ +int dbiAppendIndexRecord( /*@out@*/ dbiIndexSet set, unsigned int recOffset, unsigned int fileNumber); + +/** + * Create empty set of index database items. + * @return empty set of index database items + */ +/*@only@*/ dbiIndexSet dbiCreateIndexSet(void); + +/** + * Remove element from set of index database items. + * @param set set of index database items + * @param rec item to remove from set + * @return 0 success, 1 failure + */ +int dbiRemoveIndexRecord(dbiIndexSet set, dbiIndexRecord rec); + +/** + * Return first index database key. + * @param dbi index database handle + * @param key address of first key + * @return 0 success - fails if rec is not found + */ +int dbiGetFirstKey(dbiIndex dbi, /*@out@*/ const char ** key); + +/** + * Create and initialize element of index database set. + * @param recOffset byte offset of header in db + * @param fileNumber file array index + * @return new element + */ +/*@only@*/ dbiIndexRecord dbiReturnIndexRecordInstance(unsigned int recOffset, + unsigned int fileNumber); +/** + * Destroy element of index database set. + * @param rec element of index database set. + */ +void dbiFreeIndexRecordInstance( /*@only@*/ dbiIndexRecord rec); #ifdef __cplusplus } diff --git a/lib/depends.c b/lib/depends.c index 38722f7a7..c0e706c95 100644 --- a/lib/depends.c +++ b/lib/depends.c @@ -610,7 +610,7 @@ int rpmtransAddPackage(rpmTransactionSet rpmdep, Header h, FD_t fd, const void * key, int upgrade, rpmRelocation * relocs) { /* this is an install followed by uninstalls */ - dbiIndexSet matches; + dbiIndexSet matches = NULL; char * name; int count, i, j; const char ** obsoletes; @@ -658,8 +658,6 @@ int rpmtransAddPackage(rpmTransactionSet rpmdep, Header h, FD_t fd, removePackage(rpmdep, dbiIndexRecordOffset(matches, i), alNum); headerFree(h2); } - - dbiFreeIndexRecord(matches); } if (headerGetEntry(h, RPMTAG_OBSOLETENAME, NULL, (void **) &obsoletes, &count)) { @@ -671,12 +669,19 @@ int rpmtransAddPackage(rpmTransactionSet rpmdep, Header h, FD_t fd, for (j = 0; j < count; j++) { + if (matches) { + dbiFreeIndexSet(matches); + matches = NULL; + } + /* XXX avoid self-obsoleting packages. */ if (!strcmp(name, obsoletes[j])) continue; - if (rpmdbFindPackage(rpmdep->db, obsoletes[j], &matches)) + if (rpmdbFindPackage(rpmdep->db, obsoletes[j], &matches)) { continue; + } + for (i = 0; i < dbiIndexSetCount(matches); i++) { unsigned int recOffset = dbiIndexRecordOffset(matches, i); if (bsearch(&recOffset, @@ -695,14 +700,17 @@ int rpmtransAddPackage(rpmTransactionSet rpmdep, Header h, FD_t fd, removePackage(rpmdep, recOffset, alNum); } } - - dbiFreeIndexRecord(matches); } if (obsoletesEVR) free(obsoletesEVR); free(obsoletes); } + if (matches) { + dbiFreeIndexSet(matches); + matches = NULL; + } + return 0; } @@ -855,7 +863,7 @@ static int unsatisfiedDepend(rpmTransactionSet rpmdep, const char * keyName, const char * keyEVR, int keyFlags, /*@out@*/ struct availablePackage ** suggestion) { - dbiIndexSet matches; + dbiIndexSet matches = NULL; int rc = 0; /* assume dependency is satisfied */ int i; @@ -894,13 +902,16 @@ static int unsatisfiedDepend(rpmTransactionSet rpmdep, break; } - dbiFreeIndexRecord(matches); if (i < dbiIndexSetCount(matches)) { rpmMessage(RPMMESS_DEBUG, _("%s: %s satisfied by db file lists.\n"), keyType, keyDepend); goto exit; } } } + if (matches) { + dbiFreeIndexSet(matches); + matches = NULL; + } if (!rpmdbFindByProvides(rpmdep->db, keyName, &matches)) { for (i = 0; i < dbiIndexSetCount(matches); i++) { @@ -916,12 +927,15 @@ static int unsatisfiedDepend(rpmTransactionSet rpmdep, } } - dbiFreeIndexRecord(matches); if (i < dbiIndexSetCount(matches)) { rpmMessage(RPMMESS_DEBUG, _("%s: %s satisfied by db provides.\n"), keyType, keyDepend); goto exit; } } + if (matches) { + dbiFreeIndexSet(matches); + matches = NULL; + } if (!rpmdbFindPackage(rpmdep->db, keyName, &matches)) { for (i = 0; i < dbiIndexSetCount(matches); i++) { @@ -938,12 +952,15 @@ static int unsatisfiedDepend(rpmTransactionSet rpmdep, } } - dbiFreeIndexRecord(matches); if (i < dbiIndexSetCount(matches)) { rpmMessage(RPMMESS_DEBUG, _("%s: %s satisfied by db packages.\n"), keyType, keyDepend); goto exit; } } + if (matches) { + dbiFreeIndexSet(matches); + matches = NULL; + } /* * New features in rpm spec files add implicit dependencies on rpm @@ -967,6 +984,10 @@ static int unsatisfiedDepend(rpmTransactionSet rpmdep, rc = 1; /* dependency is unsatisfied */ exit: + if (matches) { + dbiFreeIndexSet(matches); + matches = NULL; + } return rc; } @@ -1114,13 +1135,13 @@ static int checkPackageDeps(rpmTransactionSet rpmdep, struct problemsSet * psp, /* Adding: check name/provides key against each conflict match. */ /* Erasing: check name/provides/filename key against each requiredby match. */ static int checkPackageSet(rpmTransactionSet rpmdep, struct problemsSet * psp, - const char * key, dbiIndexSet * matches) + const char * key, dbiIndexSet matches) { Header h; int i; - for (i = 0; i < matches->count; i++) { - unsigned int recOffset = dbiIndexRecordOffset(*matches, i); + for (i = 0; i < dbiIndexSetCount(matches); i++) { + unsigned int recOffset = dbiIndexRecordOffset(matches, i); if (bsearch(&recOffset, rpmdep->removedPackages, rpmdep->numRemovedPackages, sizeof(int), intcmp)) continue; @@ -1148,15 +1169,13 @@ static int checkPackageSet(rpmTransactionSet rpmdep, struct problemsSet * psp, static int checkDependentPackages(rpmTransactionSet rpmdep, struct problemsSet * psp, const char * key) { - dbiIndexSet matches; - int rc; - - if (rpmdbFindByRequiredBy(rpmdep->db, key, &matches)) - return 0; - - rc = checkPackageSet(rpmdep, psp, key, &matches); - dbiFreeIndexRecord(matches); + dbiIndexSet matches = NULL; + int rc = 0; + if (!rpmdbFindByRequiredBy(rpmdep->db, key, &matches)) + rc = checkPackageSet(rpmdep, psp, key, matches); + if (matches) + dbiFreeIndexSet(matches); return rc; } @@ -1164,17 +1183,15 @@ static int checkDependentPackages(rpmTransactionSet rpmdep, static int checkDependentConflicts(rpmTransactionSet rpmdep, struct problemsSet * psp, const char * key) { - dbiIndexSet matches; - int rc; - - if (rpmdep->db == NULL) - return 0; - - if (rpmdbFindByConflicts(rpmdep->db, key, &matches)) - return 0; + int rc = 0; - rc = checkPackageSet(rpmdep, psp, key, &matches); - dbiFreeIndexRecord(matches); + if (rpmdep->db) { + dbiIndexSet matches = NULL; + if (!rpmdbFindByConflicts(rpmdep->db, key, &matches)) + rc = checkPackageSet(rpmdep, psp, key, matches); + if (matches) + dbiFreeIndexSet(matches); + } return rc; } diff --git a/lib/fprint.c b/lib/fprint.c index c08c472fd..c2ba5b7fc 100644 --- a/lib/fprint.c +++ b/lib/fprint.c @@ -85,7 +85,7 @@ static fingerPrint doLookup(fingerPrintCache cache, if (end[-1] != '/') *end++ = '/'; end = stpncpy(end, cleanDirName, sizeof(dir) - (end - dir)); *end = '\0'; - rpmCleanPath(dir); /* XXX possible /../ from concatenation */ + (void)rpmCleanPath(dir); /* XXX possible /../ from concatenation */ end = dir + strlen(dir); if (end[-1] != '/') *end++ = '/'; *end = '\0'; @@ -104,6 +104,8 @@ static fingerPrint doLookup(fingerPrintCache cache, } fp.entry = NULL; + fp.subDir = NULL; + fp.baseName = NULL; while (1) { /* as we're stating paths here, we want to follow symlinks */ diff --git a/lib/hash.c b/lib/hash.c index 3b1c98036..73f37a24b 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -1,24 +1,38 @@ +/** \file lib/hash.c + * Hash table implemenation + */ + #include "system.h" #include <rpmlib.h> #include "hash.h" +typedef /*@owned@*/ const void * voidptr; + +/** */ struct hashBucket { - /*@owned@*/const void * key; - /*@owned@*/const void ** data; - int dataCount; - /*@dependent@*/struct hashBucket * next; + voidptr key; /*!< hash key */ +/*@owned@*/ voidptr * data; /*!< pointer to hashed data */ + int dataCount; /*!< length of data (0 if unknown) */ +/*@dependent@*/struct hashBucket * next;/*!< pointer to next item in bucket */ }; +/** */ struct hashTable_s { - int numBuckets; - int keySize; - int freeData; - struct hashBucket ** buckets; - hashFunctionType fn; - hashEqualityType eq; + int numBuckets; /*!< number of hash buckets */ + int keySize; /*!< size of key (0 if unknown) */ + int freeData; /*!< should data be freed when table is destroyed? */ + struct hashBucket ** buckets; /*!< hash bucket array */ + hashFunctionType fn; /*!< generate hash value for key */ + hashEqualityType eq; /*!< compare hash keys for equality */ }; +/** + * Find entry in hash table. + * @param ht pointer to hash table + * @param key pointer to key value + * @return pointer to hash bucket of key (or NULL) + */ static /*@shared@*/ struct hashBucket * findEntry(hashTable ht, const void * key) { unsigned int hash; @@ -142,7 +156,7 @@ int htGetEntry(hashTable ht, const void * key, const void *** data, return 1; if (data) - *data = b->data; + *data = (const void **) b->data; if (dataCount) *dataCount = b->dataCount; if (tableKey) diff --git a/lib/hash.h b/lib/hash.h index b5e0af295..eb8d8fd47 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -1,28 +1,82 @@ #ifndef H_HASH #define H_HASH +/** \file lib/hash.h + * Hash table implemenation + */ + typedef struct hashTable_s * hashTable; #ifdef __cplusplus extern "C" { #endif -typedef unsigned int (*hashFunctionType)(const void * string); -typedef int (*hashEqualityType)(const void * key1, const void * key2); +/** */ +typedef unsigned int (*hashFunctionType) (const void * string); +/** */ +typedef int (*hashEqualityType) (const void * key1, const void * key2); +/** + * Return hash value of a string + * @param string string on which to calculate hash value + * @return hash value + */ unsigned int hashFunctionString(const void * string); + +/** + * Compare two hash table entries for equality. + * @param key1 entry 1 + * @param key2 entry 2 + * @return 0 if entries are equal + */ int hashEqualityString(const void * key1, const void * key2); -/* if keySize > 0, the key is duplicated within the table (which costs - memory, but may be usefull anyway */ +/** + * Create hash table. + * If keySize > 0, the key is duplicated within the table (which costs + * memory, but may be useful anyway. + * @param numBuckets number of hash buckets + * @param keySize size of key (0 if unknown) + * @param freeData should data be freed when table is destroyed? + * @param fn function to generate hash value for key + * @param eq function to compare hash keys for equality + * @return pointer to initialized hash table + */ hashTable htCreate(int numBuckets, int keySize, int freeData, hashFunctionType fn, hashEqualityType eq); -void htAddEntry(hashTable ht, const void * key, const void * data); + +/** + * Destroy hash table. + * @param ht pointer to hash table + */ void htFree( /*@only@*/ hashTable ht); -/* returns 0 on success, 1 if the item is not found. tableKey may be NULL */ + +/** + * Add item to hash table. + * @param ht pointer to hash table + * @param key pointer to key + * @param data pointer to data value + */ +void htAddEntry(hashTable ht, /*@owned@*/ const void * key, /*@owned@*/ const void * data); + +/** + * Retrieve item from hash table. + * @param ht pointer to hash table + * @param key pointer to key value + * @retval data address to store data value from bucket + * @retval dataCount address to store data value size from bucket + * @retval tableKey address to store key value from bucket (may be NULL) + * @return 0 on success, 1 if the item is not found. + */ int htGetEntry(hashTable ht, const void * key, /*@out@*/ const void *** data, /*@out@*/ int * dataCount, /*@out@*/const void ** tableKey); -/* returns 1 if the item is present, 0 otherwise */ + +/** + * Check for key in hash table. + * @param ht pointer to hash table + * @param key pointer to key value + * @return 1 if the key is present, 0 otherwise + */ int htHasEntry(hashTable ht, const void * key); #ifdef __cplusplus diff --git a/lib/install.c b/lib/install.c index 2864d6008..572ad7033 100644 --- a/lib/install.c +++ b/lib/install.c @@ -19,14 +19,14 @@ struct callbackInfo { }; struct fileMemory { - /*@owned@*/ const char ** names; - /*@owned@*/ const char ** cpioNames; - /*@owned@*/ struct fileInfo * files; +/*@owned@*/ const char ** names; +/*@owned@*/ const char ** cpioNames; +/*@owned@*/ struct fileInfo * files; }; struct fileInfo { - /*@dependent@*/ const char * cpioPath; - /*@dependent@*/ const char * relativePath; /* relative to root */ +/*@dependent@*/ const char * cpioPath; +/*@dependent@*/ const char * relativePath; /* relative to root */ uid_t uid; gid_t gid; uint_32 flags; @@ -51,6 +51,7 @@ static struct tagMacro { { NULL, 0 } }; +/** */ static int rpmInstallLoadMacros(Header h) { struct tagMacro *tagm; @@ -74,6 +75,7 @@ static int rpmInstallLoadMacros(Header h) return 0; } +/** */ static /*@only@*/ struct fileMemory *newFileMemory(void) { struct fileMemory *fileMem = xmalloc(sizeof(*fileMem)); @@ -83,6 +85,7 @@ static /*@only@*/ struct fileMemory *newFileMemory(void) return fileMem; } +/** */ static void freeFileMemory( /*@only@*/ struct fileMemory *fileMem) { if (fileMem->files) free(fileMem->files); @@ -92,6 +95,7 @@ static void freeFileMemory( /*@only@*/ struct fileMemory *fileMem) } /* files should not be preallocated */ +/** */ static int assembleFileList(Header h, /*@out@*/ struct fileMemory ** memPtr, /*@out@*/ int * fileCountPtr, /*@out@*/ struct fileInfo ** filesPtr, int stripPrefixLength, enum fileActions * actions) @@ -146,6 +150,7 @@ static int assembleFileList(Header h, /*@out@*/ struct fileMemory ** memPtr, return 0; } +/** */ static void setFileOwners(Header h, struct fileInfo * files, int fileCount) { char ** fileOwners; @@ -177,6 +182,7 @@ static void setFileOwners(Header h, struct fileInfo * files, int fileCount) free(fileGroups); } +/** */ static void trimChangelog(Header h) { int * times; @@ -227,6 +233,7 @@ static void trimChangelog(Header h) free(texts); } +/** */ static int markReplacedFiles(rpmdb db, struct sharedFileInfo * replList) { struct sharedFileInfo * fileInfo; @@ -273,6 +280,7 @@ static int markReplacedFiles(rpmdb db, struct sharedFileInfo * replList) return 0; } +/** */ static void callback(struct cpioCallbackInfo * cpioInfo, void * data) { struct callbackInfo * ourInfo = data; @@ -292,6 +300,7 @@ static void callback(struct cpioCallbackInfo * cpioInfo, void * data) } /* NULL files means install all files */ +/** */ static int installArchive(FD_t fd, struct fileInfo * files, int fileCount, rpmCallbackFunction notify, void * notifyData, const void * pkgKey, Header h, @@ -383,6 +392,7 @@ static int installArchive(FD_t fd, struct fileInfo * files, /* 0 success */ /* 1 bad magic */ /* 2 error */ +/** */ static int installSources(Header h, const char * rootdir, FD_t fd, const char ** specFilePtr, rpmCallbackFunction notify, void * notifyData) @@ -686,7 +696,7 @@ int installBinaryPackage(const char * rootdir, rpmdb db, FD_t fd, Header h, char * fileStates = NULL; int i; int otherOffset = 0; - dbiIndexSet matches; + dbiIndexSet matches = NULL; int scriptArg; int stripSize = 1; /* strip at least first / for cpio */ struct fileMemory *fileMem = NULL; @@ -708,16 +718,21 @@ int installBinaryPackage(const char * rootdir, rpmdb db, FD_t fd, Header h, /*@notreached@*/ break; case 0: scriptArg = dbiIndexSetCount(matches) + 1; - dbiFreeIndexRecord(matches); break; default: scriptArg = 1; break; } + if (matches) { + dbiFreeIndexSet(matches); + matches = NULL; + } - if (!rpmdbFindByHeader(db, h, &matches)) { + if (!rpmdbFindByHeader(db, h, &matches)) otherOffset = dbiIndexRecordOffset(matches, 0); - dbiFreeIndexRecord(matches); + if (matches) { + dbiFreeIndexSet(matches); + matches = NULL; } if (rootdir) { @@ -927,6 +942,10 @@ int installBinaryPackage(const char * rootdir, rpmdb db, FD_t fd, Header h, rc = 0; exit: + if (matches) { + dbiFreeIndexSet(matches); + matches = NULL; + } if (rootdir && currDir) { /*@-unrecog@*/ chroot("."); /*@=unrecog@*/ chdir(currDir); diff --git a/lib/lookup.c b/lib/lookup.c index fea5efc07..14b99be9a 100644 --- a/lib/lookup.c +++ b/lib/lookup.c @@ -1,6 +1,8 @@ #include "system.h" #include <rpmlib.h> + +#include "dbindex.h" /* XXX prototypes */ #include "lookup.h" /* XXX used in transaction.c */ @@ -13,29 +15,36 @@ int findMatches(rpmdb db, const char * name, const char * version, int gotMatches; int rc; int i; - const char * pkgRelease, * pkgVersion; - int goodRelease, goodVersion; - Header h; if ((rc = rpmdbFindPackage(db, name, matches))) { - if (rc == -1) return 2; else return 1; + rc = ((rc == -1) ? 2 : 1); + goto exit; } - if (!version && !release) return 0; + if (!version && !release) { + rc = 0; + goto exit; + } gotMatches = 0; /* make sure the version and releases match */ - for (i = 0; i < matches->count; i++) { - if (matches->recs[i].recOffset == 0) + for (i = 0; i < dbiIndexSetCount(*matches); i++) { + unsigned int recoff = dbiIndexRecordOffset(*matches, i); + int goodRelease, goodVersion; + const char * pkgVersion; + const char * pkgRelease; + Header h; + + if (recoff == 0) continue; - h = rpmdbGetRecord(db, matches->recs[i].recOffset); + h = rpmdbGetRecord(db, recoff); if (h == NULL) { rpmError(RPMERR_DBCORRUPT,_("cannot read header at %d for lookup"), - matches->recs[i].recOffset); - dbiFreeIndexRecord(*matches); - return 2; + recoff); + rc = 2; + goto exit; } headerNVR(h, NULL, &pkgVersion, &pkgRelease); @@ -48,17 +57,23 @@ int findMatches(rpmdb db, const char * name, const char * version, if (goodRelease && goodVersion) gotMatches = 1; else - matches->recs[i].recOffset = 0; + dbiIndexRecordOffsetSave(*matches, i, 0); headerFree(h); } if (!gotMatches) { - dbiFreeIndexRecord(*matches); - return 1; + rc = 1; + goto exit; } - - return 0; + rc = 0; + +exit: + if (rc && matches && *matches) { + dbiFreeIndexSet(*matches); + *matches = NULL; + } + return rc; } /* 0 found matches */ diff --git a/lib/lookup.h b/lib/lookup.h index 7ba2a160d..8a364b85b 100644 --- a/lib/lookup.h +++ b/lib/lookup.h @@ -7,8 +7,9 @@ extern "C" { #endif +/* XXX only for the benefit of runTransactions() */ int findMatches(rpmdb db, const char * name, const char * version, - const char * release, /*@out@*/dbiIndexSet * matches); + const char * release, /*@out@*/ dbiIndexSet * matches); #ifdef __cplusplus } @@ -20,7 +20,7 @@ #include "md5.h" static int _ie = 0x44332211; -static union _endian { int i; char b[4]; } *_endian = (union _endian *)&_ie; +static union _mendian { int i; char b[4]; } *_endian = (union _mendian *)&_ie; #define IS_BIG_ENDIAN() (_endian->b[0] == '\x44') #define IS_LITTLE_ENDIAN() (_endian->b[0] == '\x11') diff --git a/lib/misc.c b/lib/misc.c index 456c3a7af..344830f60 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -728,7 +728,7 @@ fprintf(stderr, "*** rpmGlob argv[%d] \"%s\"\n", argc, av[j]); globRoot += nb; *globRoot = '\0'; if (_debug) -fprintf(stderr, "*** GLOB maxb %d diskURL %d %*s globURL %p %s\n", maxb, nb, nb, av[j], globURL, globURL); +fprintf(stderr, "*** GLOB maxb %d diskURL %d %*s globURL %p %s\n", (int)maxb, (int)nb, (int)nb, av[j], globURL, globURL); if (argc == 0) argv = xmalloc((gl.gl_pathc+1) * sizeof(*argv)); @@ -781,6 +781,7 @@ int rpmHeaderGetEntry(Header h, int_32 tag, int_32 *type, if (count > 0) { *p = fl; if (c) *c = count; + if (type) *type = RPM_STRING_ARRAY_TYPE; return 1; } if (c) *c = 0; diff --git a/lib/misc.h b/lib/misc.h index b4f15c71c..30afc9c76 100644 --- a/lib/misc.h +++ b/lib/misc.h @@ -41,7 +41,8 @@ void buildOrigFileList(Header h, /*@out@*/ const char *** fileListPtr, /*@out@*/ int * fileCountPtr); int myGlobPatternP (const char *patternURL); -int rpmGlob(const char * patterns, int * argcPtr, const char *** argvPtr); +int rpmGlob(const char * patterns, /*@out@*/ int * argcPtr, + /*@out@*/ const char *** argvPtr); #ifdef __cplusplus } diff --git a/lib/query.c b/lib/query.c index 1b1a8439b..ef0b7dd90 100644 --- a/lib/query.c +++ b/lib/query.c @@ -455,7 +455,7 @@ void (*freeSpecVec) (Spec spec) = NULL; int rpmQueryVerify(QVA_t *qva, enum rpmQVSources source, const char * arg, rpmdb db, QVF_t showPackage) { - dbiIndexSet matches; + dbiIndexSet matches = NULL; Header h; int offset; int rc; @@ -582,7 +582,6 @@ int rpmQueryVerify(QVA_t *qva, enum rpmQVSources source, const char * arg, retcode = 1; } else { retcode = showMatches(qva, db, matches, showPackage); - dbiFreeIndexRecord(matches); } break; @@ -592,7 +591,6 @@ int rpmQueryVerify(QVA_t *qva, enum rpmQVSources source, const char * arg, retcode = 1; } else { retcode = showMatches(qva, db, matches, showPackage); - dbiFreeIndexRecord(matches); } break; @@ -602,7 +600,6 @@ int rpmQueryVerify(QVA_t *qva, enum rpmQVSources source, const char * arg, retcode = 1; } else { retcode = showMatches(qva, db, matches, showPackage); - dbiFreeIndexRecord(matches); } break; @@ -613,7 +610,6 @@ int rpmQueryVerify(QVA_t *qva, enum rpmQVSources source, const char * arg, retcode = 1; } else { retcode = showMatches(qva, db, matches, showPackage); - dbiFreeIndexRecord(matches); } break; } @@ -634,7 +630,6 @@ int rpmQueryVerify(QVA_t *qva, enum rpmQVSources source, const char * arg, retcode = 1; } else { retcode = showMatches(qva, db, matches, showPackage); - dbiFreeIndexRecord(matches); } break; @@ -665,11 +660,14 @@ int rpmQueryVerify(QVA_t *qva, enum rpmQVSources source, const char * arg, fprintf(stderr, _("error looking for package %s\n"), arg); } else { retcode = showMatches(qva, db, matches, showPackage); - dbiFreeIndexRecord(matches); } break; } + if (matches) { + dbiFreeIndexSet(matches); + matches = NULL; + } return retcode; } diff --git a/lib/rebuilddb.c b/lib/rebuilddb.c index 82a740d9e..e909419c9 100644 --- a/lib/rebuilddb.c +++ b/lib/rebuilddb.c @@ -38,7 +38,7 @@ int rpmdbRebuild(const char * rootdir) char *t; sprintf(pidbuf, "rebuilddb.%d", (int) getpid()); t = xmalloc(strlen(dbpath) + strlen(pidbuf) + 1); - stpcpy(stpcpy(t, dbpath), pidbuf); + (void)stpcpy(stpcpy(t, dbpath), pidbuf); if (tfn) xfree(tfn); tfn = t; nocleanup = 0; @@ -92,7 +92,7 @@ int rpmdbRebuild(const char * rootdir) headerIsEntry(h, RPMTAG_VERSION) && headerIsEntry(h, RPMTAG_RELEASE) && headerIsEntry(h, RPMTAG_BUILDTIME)) { - dbiIndexSet matches; + dbiIndexSet matches = NULL; int skip; /* XXX always eliminate duplicate entries */ @@ -104,9 +104,12 @@ int rpmdbRebuild(const char * rootdir) _("duplicated database entry: %s-%s-%s -- skipping."), name, version, release); skip = 1; - dbiFreeIndexRecord(matches); } else skip = 0; + if (matches) { + dbiFreeIndexSet(matches); + matches = NULL; + } if (skip == 0 && rpmdbAdd(newdb, h)) { rpmError(RPMERR_INTERNAL, diff --git a/lib/rpmdb.c b/lib/rpmdb.c index ea86399e8..ccb4f1777 100644 --- a/lib/rpmdb.c +++ b/lib/rpmdb.c @@ -8,14 +8,15 @@ #include <rpmurl.h> #include <rpmmacro.h> /* XXX for rpmGetPath */ +#include "dbindex.h" +/*@access dbiIndexSet@*/ +/*@access dbiIndexRecord@*/ + #include "falloc.h" #include "fprint.h" #include "misc.h" #include "rpmdb.h" -/*@access dbiIndexSet@*/ -/*@access dbiIndexRecord@*/ - extern int _noDirTokens; const char *rpmdb_filenames[] = { @@ -43,8 +44,8 @@ const char *rpmdb_filenames[] = { struct rpmdb_s { FD_t pkgs; - dbiIndex * nameIndex, * fileIndex, * groupIndex, * providesIndex; - dbiIndex * requiredbyIndex, * conflictsIndex, * triggerIndex; + dbiIndex nameIndex, fileIndex, groupIndex, providesIndex; + dbiIndex requiredbyIndex, conflictsIndex, triggerIndex; }; static sigset_t signalMask; @@ -63,7 +64,7 @@ static void unblockSignals(void) } static int openDbFile(const char * prefix, const char * dbpath, const char * shortName, - int justCheck, int mode, int perms, dbiIndex ** db, DBTYPE type) + int justCheck, int mode, int perms, dbiIndex * db, DBI_TYPE type) { int len = (prefix ? strlen(prefix) : 0) + strlen(dbpath) + strlen(shortName) + 1; char * filename = alloca(len); @@ -80,10 +81,8 @@ static int openDbFile(const char * prefix, const char * dbpath, const char * sho strcat(filename, shortName); if (!justCheck || !rpmfileexists(filename)) { - *db = dbiOpenIndex(filename, mode, perms, type); - if (!*db) { + if ((*db = dbiOpenIndex(filename, mode, perms, type)) == NULL) return 1; - } } return 0; @@ -143,7 +142,7 @@ int openDatabase(const char * prefix, const char * dbpath, rpmdb *rpmdbp, int mo break; } strcat(filename, dbpath); - rpmCleanPath(filename); + (void)rpmCleanPath(filename); rpmMessage(RPMMESS_DEBUG, _("opening database mode 0x%x in %s\n"), mode, filename); @@ -188,7 +187,7 @@ int openDatabase(const char * prefix, const char * dbpath, rpmdb *rpmdbp, int mo } rc = openDbFile(prefix, dbpath, "nameindex.rpm", justcheck, mode, perms, - &db->nameIndex, DB_HASH); + &db->nameIndex, DBI_HASH); if (minimal) { *rpmdbp = xmalloc(sizeof(struct rpmdb_s)); @@ -201,7 +200,7 @@ int openDatabase(const char * prefix, const char * dbpath, rpmdb *rpmdbp, int mo if (!rc) rc = openDbFile(prefix, dbpath, "fileindex.rpm", justcheck, mode, perms, - &db->fileIndex, DB_HASH); + &db->fileIndex, DBI_HASH); /* We used to store the fileindexes as complete paths, rather then plain basenames. Let's see which version we are... */ @@ -220,19 +219,19 @@ int openDatabase(const char * prefix, const char * dbpath, rpmdb *rpmdbp, int mo if (!rc) rc = openDbFile(prefix, dbpath, "providesindex.rpm", justcheck, mode, perms, - &db->providesIndex, DB_HASH); + &db->providesIndex, DBI_HASH); if (!rc) rc = openDbFile(prefix, dbpath, "requiredby.rpm", justcheck, mode, perms, - &db->requiredbyIndex, DB_HASH); + &db->requiredbyIndex, DBI_HASH); if (!rc) rc = openDbFile(prefix, dbpath, "conflictsindex.rpm", justcheck, mode, perms, - &db->conflictsIndex, DB_HASH); + &db->conflictsIndex, DBI_HASH); if (!rc) rc = openDbFile(prefix, dbpath, "groupindex.rpm", justcheck, mode, perms, - &db->groupIndex, DB_HASH); + &db->groupIndex, DBI_HASH); if (!rc) rc = openDbFile(prefix, dbpath, "triggerindex.rpm", justcheck, mode, perms, - &db->triggerIndex, DB_HASH); + &db->triggerIndex, DBI_HASH); if (rc || justcheck || rpmdbp == NULL) rpmdbClose(db); @@ -361,10 +360,11 @@ int rpmdbFindByFile(rpmdb db, const char * filespec, dbiIndexSet * matches) const char * dirName; const char * baseName; fingerPrint fp1, fp2; - dbiIndexSet allMatches; + dbiIndexSet allMatches = NULL; int i, rc; fingerPrintCache fpc; + *matches = NULL; if ((baseName = strrchr(filespec, '/')) != NULL) { char * t; size_t len; @@ -384,18 +384,22 @@ int rpmdbFindByFile(rpmdb db, const char * filespec, dbiIndexSet * matches) rc = dbiSearchIndex(db->fileIndex, baseName, &allMatches); if (rc) { + dbiFreeIndexSet(allMatches); + allMatches = NULL; fpCacheFree(fpc); return rc; } - *matches = dbiCreateIndexRecord(); + *matches = dbiCreateIndexSet(); i = 0; - while (i < allMatches.count) { + while (i < dbiIndexSetCount(allMatches)) { const char ** baseNames, ** dirNames; int_32 * dirIndexes; + unsigned int recoff = dbiIndexRecordOffset(allMatches, i); + unsigned int prevoff; Header h; - if ((h = rpmdbGetRecord(db, allMatches.recs[i].recOffset)) == NULL) { + if ((h = rpmdbGetRecord(db, recoff)) == NULL) { i++; continue; } @@ -408,28 +412,33 @@ int rpmdbFindByFile(rpmdb db, const char * filespec, dbiIndexSet * matches) (void **) &dirNames, NULL); do { - int num = allMatches.recs[i].fileNumber; + int num = dbiIndexRecordFileNumber(allMatches, i); fp2 = fpLookup(fpc, dirNames[dirIndexes[num]], baseNames[num], 1); if (FP_EQUAL(fp1, fp2)) - dbiAppendIndexRecord(matches, allMatches.recs[i]); + dbiAppendIndexRecord(*matches, dbiIndexRecordOffset(allMatches, i), dbiIndexRecordFileNumber(allMatches, i)); + prevoff = recoff; i++; - } while ((i < allMatches.count) && - ((i == 0) || (allMatches.recs[i].recOffset == - allMatches.recs[i - 1].recOffset))); + recoff = dbiIndexRecordOffset(allMatches, i); + } while (i < dbiIndexSetCount(allMatches) && + (i == 0 || recoff == prevoff)); free(baseNames); free(dirNames); headerFree(h); } - dbiFreeIndexRecord(allMatches); + if (allMatches) { + dbiFreeIndexSet(allMatches); + allMatches = NULL; + } fpCacheFree(fpc); - if (!matches->count) { - dbiFreeIndexRecord(*matches); + if (dbiIndexSetCount(*matches) == 0) { + dbiFreeIndexSet(*matches); + *matches = NULL; return 1; } @@ -460,24 +469,22 @@ int rpmdbFindPackage(rpmdb db, const char * name, dbiIndexSet * matches) { return dbiSearchIndex(db->nameIndex, name, matches); } -static void removeIndexEntry(dbiIndex * dbi, char * key, dbiIndexRecord rec, - int tolerant, char * idxName) +static void removeIndexEntry(dbiIndex dbi, const char * key, dbiIndexRecord rec, + int tolerant, const char * idxName) { + dbiIndexSet matches = NULL; int rc; - dbiIndexSet matches; rc = dbiSearchIndex(dbi, key, &matches); switch (rc) { case 0: - if (dbiRemoveIndexRecord(&matches, rec) && !tolerant) { + if (dbiRemoveIndexRecord(matches, rec) && !tolerant) { rpmError(RPMERR_DBCORRUPT, _("package %s not listed in %s"), key, idxName); } else { - dbiUpdateIndex(dbi, key, &matches); + dbiUpdateIndex(dbi, key, matches); /* errors from above will be reported from dbindex.c */ } - - dbiFreeIndexRecord(matches); break; case 1: if (!tolerant) @@ -487,6 +494,10 @@ static void removeIndexEntry(dbiIndex * dbi, char * key, dbiIndexRecord rec, case 2: break; /* error message already generated from dbindex.c */ } + if (matches) { + dbiFreeIndexSet(matches); + matches = NULL; + } } int rpmdbRemove(rpmdb db, unsigned int offset, int tolerant) @@ -500,8 +511,6 @@ int rpmdbRemove(rpmdb db, unsigned int offset, int tolerant) char ** conflictList, ** triggerList; int i; - /* structure assignment */ - rec = dbiReturnIndexRecordInstance(offset, 0); h = rpmdbGetRecord(db, offset); if (h == NULL) { @@ -510,6 +519,8 @@ int rpmdbRemove(rpmdb db, unsigned int offset, int tolerant) return 1; } + rec = dbiReturnIndexRecordInstance(offset, 0); + blockSignals(); if (!headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count)) { @@ -598,30 +609,43 @@ int rpmdbRemove(rpmdb db, unsigned int offset, int tolerant) unblockSignals(); + dbiFreeIndexRecordInstance(rec); headerFree(h); return 0; } -static int addIndexEntry(dbiIndex *idx, const char *index, unsigned int offset, +static int addIndexEntry(dbiIndex idx, const char *index, unsigned int offset, unsigned int fileNumber) { - dbiIndexSet set; - dbiIndexRecord irec; + dbiIndexSet set = NULL; int rc; - irec = dbiReturnIndexRecordInstance(offset, fileNumber); - rc = dbiSearchIndex(idx, index, &set); - if (rc == -1) /* error */ + switch (rc) { + case -1: /* error */ + if (set) { + dbiFreeIndexSet(set); + set = NULL; + } return 1; + /*@notreached@*/ break; + case 1: /* new item */ + set = dbiCreateIndexSet(); + break; + default: + break; + } + + dbiAppendIndexRecord(set, offset, fileNumber); + if (dbiUpdateIndex(idx, index, set)) + exit(EXIT_FAILURE); /* XXX W2DO? return 1; */ + + if (set) { + dbiFreeIndexSet(set); + set = NULL; + } - if (rc == 1) /* new item */ - set = dbiCreateIndexRecord(); - dbiAppendIndexRecord(&set, irec); - if (dbiUpdateIndex(idx, index, &set)) - exit(EXIT_FAILURE); - dbiFreeIndexRecord(set); return 0; } @@ -852,7 +876,8 @@ int rpmdbMoveDatabase(const char * rootdir, const char * olddbpath, const char * } struct intMatch { - dbiIndexRecord rec; + unsigned int recOffset; + unsigned int fileNumber; int fpNum; }; @@ -861,9 +886,9 @@ static int intMatchCmp(const void * one, const void * two) const struct intMatch * a = one; const struct intMatch * b = two; - if (a->rec.recOffset < b->rec.recOffset) + if (a->recOffset < b->recOffset) return -1; - else if (a->rec.recOffset > b->rec.recOffset) + else if (a->recOffset > b->recOffset) return 1; return 0; @@ -891,11 +916,15 @@ int rpmdbFindFpList(rpmdb db, fingerPrint * fpList, dbiIndexSet * matchList, /* Gather all matches from the database */ for (i = 0; i < numItems; i++) { - dbiIndexSet matches; + dbiIndexSet matches = NULL; switch (dbiSearchIndex(db->fileIndex, fpList[i].baseName, &matches)) { default: break; case 2: + if (matches) { + dbiFreeIndexSet(matches); + matches = NULL; + } free(intMatches); return 1; /*@notreached@*/ break; @@ -908,21 +937,26 @@ int rpmdbFindFpList(rpmdb db, fingerPrint * fpList, dbiIndexSet * matchList, } for (j = 0; j < dbiIndexSetCount(matches); j++) { - /* structure assignment */ - intMatches[numIntMatches].rec = matches.recs[j]; - intMatches[numIntMatches++].fpNum = i; + + intMatches[numIntMatches].recOffset = dbiIndexRecordOffset(matches, j); + intMatches[numIntMatches].fileNumber = dbiIndexRecordFileNumber(matches, j); + intMatches[numIntMatches].fpNum = i; + numIntMatches++; } - dbiFreeIndexRecord(matches); break; } + if (matches) { + dbiFreeIndexSet(matches); + matches = NULL; + } } qsort(intMatches, numIntMatches, sizeof(*intMatches), intMatchCmp); /* intMatches is now sorted by (recnum, filenum) */ for (i = 0; i < numItems; i++) - matchList[i] = dbiCreateIndexRecord(); + matchList[i] = dbiCreateIndexSet(); fpc = fpCacheCreate(numIntMatches); @@ -936,13 +970,13 @@ int rpmdbFindFpList(rpmdb db, fingerPrint * fpList, dbiIndexSet * matchList, /* Find the end of the set of matched files in this package. */ for (end = start + 1; end < numIntMatches; end++) { - if (im->rec.recOffset != intMatches[end].rec.recOffset) + if (im->recOffset != intMatches[end].recOffset) break; } num = end - start; /* Compute fingerprints for each file match in this package. */ - h = rpmdbGetRecord(db, im->rec.recOffset); + h = rpmdbGetRecord(db, im->recOffset); if (h == NULL) { free(intMatches); return 1; @@ -958,8 +992,8 @@ int rpmdbFindFpList(rpmdb db, fingerPrint * fpList, dbiIndexSet * matchList, baseNames = xcalloc(num, sizeof(*baseNames)); dirIndexes = xcalloc(num, sizeof(*dirIndexes)); for (i = 0; i < num; i++) { - baseNames[i] = fullBaseNames[im[i].rec.fileNumber]; - dirIndexes[i] = fullDirIndexes[im[i].rec.fileNumber]; + baseNames[i] = fullBaseNames[im[i].fileNumber]; + dirIndexes[i] = fullDirIndexes[im[i].fileNumber]; } fps = xcalloc(num, sizeof(*fps)); @@ -974,7 +1008,7 @@ int rpmdbFindFpList(rpmdb db, fingerPrint * fpList, dbiIndexSet * matchList, for (i = 0; i < num; i++) { j = im[i].fpNum; if (FP_EQUAL_DIFFERENT_CACHE(fps[i], fpList[j])) - dbiAppendIndexRecord(&matchList[j], im[i].rec); + dbiAppendIndexRecord(matchList[j], im[i].recOffset, im[i].fileNumber); } headerFree(h); diff --git a/lib/rpmdb.h b/lib/rpmdb.h index b02fd837f..ec275008d 100644 --- a/lib/rpmdb.h +++ b/lib/rpmdb.h @@ -1,7 +1,11 @@ #ifndef H_RPMDB #define H_RPMDB +/** \file lib/rpmdb.h + */ + #include <rpmlib.h> + #include "fprint.h" /* for RPM's internal use only */ @@ -13,14 +17,34 @@ extern "C" { #endif +/** + */ int openDatabase(const char * prefix, const char * dbpath, /*@out@*/rpmdb *rpmdbp, int mode, int perms, int flags); + +/** + */ int rpmdbRemove(rpmdb db, unsigned int offset, int tolerant); + +/** + */ int rpmdbAdd(rpmdb db, Header dbentry); + +/** + */ int rpmdbUpdateRecord(rpmdb db, int secOffset, Header secHeader); + +/** + */ void rpmdbRemoveDatabase(const char * rootdir, const char * dbpath); + +/** + */ int rpmdbMoveDatabase(const char * rootdir, const char * olddbpath, const char * newdbpath); -/* matchList must be preallocated!!! */ + +/** + * matchList must be preallocated!!! + */ int rpmdbFindFpList(rpmdb db, fingerPrint * fpList, /*@out@*/dbiIndexSet * matchList, int numItems); diff --git a/lib/rpminstall.c b/lib/rpminstall.c index 9053d16cd..45c1bb126 100644 --- a/lib/rpminstall.c +++ b/lib/rpminstall.c @@ -375,8 +375,8 @@ int rpmInstall(const char * rootdir, const char ** fileArgv, int transFlags, Unlink(tmppkgURL[i]); xfree(tmppkgURL[i]); } - xfree(tmppkgURL); - xfree(pkgURL); + xfree(tmppkgURL); tmppkgURL = NULL; + xfree(pkgURL); pkgURL = NULL; /* FIXME how do we close our various fd's? */ @@ -397,9 +397,10 @@ errxit: } int rpmErase(const char * rootdir, const char ** argv, int transFlags, - int interfaceFlags) { + int interfaceFlags) +{ rpmdb db; - dbiIndexSet matches; + dbiIndexSet matches = NULL; int i, j; int mode; int rc; @@ -459,9 +460,12 @@ int rpmErase(const char * rootdir, const char ** argv, int transFlags, } } - dbiFreeIndexRecord(matches); break; } + if (matches) { + dbiFreeIndexSet(matches); + matches = NULL; + } } if (!(interfaceFlags & UNINSTALL_NODEPS)) { @@ -510,8 +514,14 @@ int rpmInstallSource(const char * rootdir, const char * arg, const char ** specF cookie); if (rc == 1) { rpmMessage(RPMMESS_ERROR, _("%s cannot be installed\n"), arg); - if (specFile && *specFile) xfree(*specFile); - if (cookie && *cookie) free(*cookie); + if (specFile && *specFile) { + xfree(*specFile); + *specFile = NULL; + } + if (cookie && *cookie) { + free(*cookie); + *cookie = NULL; + } } Fclose(fd); diff --git a/lib/rpmio.h b/lib/rpmio.h index bc23b8c84..0fee66ee5 100644 --- a/lib/rpmio.h +++ b/lib/rpmio.h @@ -93,13 +93,13 @@ int Link (const char * oldpath, const char * newpath); int Unlink (const char * path); int Readlink(const char * path, char * buf, size_t bufsiz); -int Stat (const char * path, struct stat * st); -int Lstat (const char * path, struct stat * st); +int Stat (const char * path, /*@out@*/ struct stat * st); +int Lstat (const char * path, /*@out@*/ struct stat * st); int Access (const char * path, int amode); int Glob (const char * pattern, int flags, - int errfunc(const char * epath, int eerrno), glob_t * pglob); -void Globfree(glob_t * pglob); + int errfunc(const char * epath, int eerrno), /*@out@*/ glob_t * pglob); +void Globfree( /*@only@*/ glob_t * pglob); DIR * Opendir (const char * name); struct dirent * Readdir (DIR * dir); @@ -124,9 +124,9 @@ int fdGetRdTimeoutSecs(FD_t fd); long int fdGetCpioPos(FD_t fd); void fdSetCpioPos(FD_t fd, long int cpioPos); -extern /*@null@*/ FD_t fdDup(int fdno); +/*@null@*/ FD_t fdDup(int fdno); #ifdef UNUSED -extern /*@null@*/ FILE *fdFdopen( /*@only@*/ void * cookie, const char * mode); +/*@null@*/ FILE *fdFdopen( /*@only@*/ void * cookie, const char * mode); #endif /* XXX legacy interface used in rpm2html */ diff --git a/lib/rpmlib.h b/lib/rpmlib.h index 525cd67f1..8d3d51e8d 100644 --- a/lib/rpmlib.h +++ b/lib/rpmlib.h @@ -6,14 +6,57 @@ /* and it shouldn't need these :-( */ #include <rpmio.h> -#include <dbindex.h> #include <header.h> #include <popt.h> +#if DEAD +typedef /*@abstract@*/ struct _dbiIndexRecord * dbiIndexRecord; +typedef /*@abstract@*/ struct _dbiIndex * dbiIndex; +#endif + +typedef /*@abstract@*/ struct _dbiIndexSet * dbiIndexSet; + #ifdef __cplusplus extern "C" { #endif +/** + * Destroy set of index database items. + * @param set set of index database items + */ +void dbiFreeIndexSet(/*@only@*/ /*@null@*/ dbiIndexSet set); + +/** + * Count items in index database set. + * @param set set of index database items + * @return number of items + */ +unsigned int dbiIndexSetCount(dbiIndexSet set); + +/** + * Return record offset of header from element in index database set. + * @param set set of index database items + * @param recno index of item in set + * @return record offset of header + */ +unsigned int dbiIndexRecordOffset(dbiIndexSet set, int recno); + +/** + * Return file index from element in index database set. + * @param set set of index database items + * @param recno index of item in set + * @return file index + */ +unsigned int dbiIndexRecordFileNumber(dbiIndexSet set, int recno); + +/** + * Change record offset of header within element in index database set. + * @param set set of index database items + * @param recno index of item in set + * @param recoff new record offset + */ +void dbiIndexRecordOffsetSave(dbiIndexSet set, int recno, unsigned int recoff); + int rpmReadPackageInfo(FD_t fd, /*@out@*/ Header * signatures, /*@out@*/ Header * hdr); int rpmReadPackageHeader(FD_t fd, /*@out@*/ Header * hdr, diff --git a/lib/rpmrc.c b/lib/rpmrc.c index b70d0726a..837676633 100644 --- a/lib/rpmrc.c +++ b/lib/rpmrc.c @@ -15,10 +15,12 @@ static const char *defrcfiles = LIBRPMRC_FILENAME ":/etc/rpmrc:~/.rpmrc"; +typedef /*@owned@*/ const char * cptr_t; + struct machCacheEntry { const char * name; int count; - const char ** equivs; + cptr_t * equivs; int visited; }; @@ -52,19 +54,20 @@ struct rpmOption { }; struct defaultEntry { - char *name; - char *defName; +/*@owned@*/ const char * name; +/*@owned@*/ const char * defName; }; struct canonEntry { - char *name; - char *short_name; +/*@owned@*/ const char * name; +/*@owned@*/ const char * short_name; short num; }; /* tags are 'key'canon, 'key'translate, 'key'compat - - for giggles, 'key'_canon, 'key'_compat, and 'key'_canon will also work */ + * + * for giggles, 'key'_canon, 'key'_compat, and 'key'_canon will also work + */ struct tableType { const char * const key; const int hasCanon; @@ -100,13 +103,13 @@ static int optionTableSize = sizeof(optionTable) / sizeof(*optionTable); #define OS 0 #define ARCH 1 -static char * current[2]; +static cptr_t current[2]; static int currTables[2] = { RPM_MACHTABLE_INSTOS, RPM_MACHTABLE_INSTARCH }; static struct rpmvarValue values[RPMVAR_NUM]; static int defaultsInitialized = 0; /* prototypes */ -static int doReadRC(FD_t fd, const char * urlfn); +static int doReadRC( /*@killref@*/ FD_t fd, const char * urlfn); static void rpmSetVarArch(int var, const char * val, const char * arch); static void rebuildCompatTables(int type, const char *name); @@ -117,8 +120,8 @@ static int optionCompare(const void * a, const void * b) { static void rpmRebuildTargetVars(const char **target, const char ** canontarget); -static struct machCacheEntry * machCacheFindEntry(struct machCache * cache, - const char * key) +static /*@observer@*/ struct machCacheEntry * +machCacheFindEntry(struct machCache * cache, const char * key) { int i; @@ -196,8 +199,8 @@ static int machCompatCacheAdd(char * name, const char * fn, int linenum, return 0; } -static struct machEquivInfo * machEquivSearch( - struct machEquivTable * table, const char * name) +static /*@observer@*/ struct machEquivInfo * + machEquivSearch(const struct machEquivTable * table, const char * name) { int i; @@ -366,9 +369,9 @@ static int addDefault(struct defaultEntry **table, int *tableLen, char *line, return 0; } -static struct canonEntry *lookupInCanonTable(char *name, - struct canonEntry *table, - int tableLen) { +static /*@null@*/ const struct canonEntry *lookupInCanonTable(const char *name, + const struct canonEntry *table, int tableLen) +{ while (tableLen) { tableLen--; if (!strcmp(name, table[tableLen].name)) { @@ -379,8 +382,9 @@ static struct canonEntry *lookupInCanonTable(char *name, return NULL; } -static const char *lookupInDefaultTable(const char *name, struct defaultEntry *table, - int tableLen) { +static /*@observer@*/ const char * lookupInDefaultTable(const char *name, + const struct defaultEntry *table, int tableLen) +{ while (tableLen) { tableLen--; if (!strcmp(name, table[tableLen].name)) { @@ -800,11 +804,12 @@ static int doReadRC( /*@killref@*/ FD_t fd, const char * urlfn) return 0; } -static void defaultMachine(const char ** arch, const char ** os) { +static void defaultMachine(/*@out@*/ const char ** arch, /*@out@*/ const char ** os) +{ static struct utsname un; static int gotDefaults = 0; char * chptr; - struct canonEntry * canon; + const struct canonEntry * canon; if (!gotDefaults) { uname(&un); @@ -977,7 +982,7 @@ static void defaultMachine(const char ** arch, const char ** os) { if (os) *os = un.sysname; } -static const char * rpmGetVarArch(int var, char * arch) { +static const char * rpmGetVarArch(int var, const char * arch) { struct rpmvarValue * next; if (!arch) arch = current[ARCH]; @@ -1110,14 +1115,14 @@ void rpmSetMachine(const char * arch, const char * os) { } if (!current[ARCH] || strcmp(arch, current[ARCH])) { - if (current[ARCH]) free(current[ARCH]); + if (current[ARCH]) xfree(current[ARCH]); current[ARCH] = xstrdup(arch); rebuildCompatTables(ARCH, host_cpu); } if (!current[OS] || strcmp(os, current[OS])) { - if (current[OS]) free(current[OS]); - current[OS] = xstrdup(os); + char * t = xstrdup(os); + if (current[OS]) xfree(current[OS]); /* * XXX Capitalizing the 'L' is needed to insure that old * XXX os-from-uname (e.g. "Linux") is compatible with the new @@ -1126,8 +1131,10 @@ void rpmSetMachine(const char * arch, const char * os) { * XXX used by rpmInstallPackage->{os,arch}Okay->rpmMachineScore-> * XXX to verify correct arch/os from headers. */ - if (!strcmp(current[OS], "linux")) - *current[OS]= 'L'; + if (!strcmp(t, "linux")) + *t = 'L'; + current[OS] = t; + rebuildCompatTables(OS, host_os); } } @@ -1138,10 +1145,10 @@ static void rebuildCompatTables(int type, const char * name) { name); } -static void getMachineInfo(int type, /*@only@*/ /*@out@*/ const char ** name, +static void getMachineInfo(int type, /*@out@*/ const char ** name, /*@out@*/int * num) { - struct canonEntry * canon; + const struct canonEntry * canon; int which = currTables[type]; /* use the normal canon tables, even if we're looking up build stuff */ diff --git a/lib/transaction.c b/lib/transaction.c index cc6f58092..c456a6f72 100644 --- a/lib/transaction.c +++ b/lib/transaction.c @@ -1190,7 +1190,7 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify, int rc, ourrc = 0; struct availablePackage * alp; rpmProblemSet probs; - dbiIndexSet dbi, * matches; + dbiIndexSet dbi = NULL; Header * hdrs; int fileCount; int totalFileCount = 0; @@ -1280,25 +1280,49 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify, if (!(ignoreSet & RPMPROB_FILTER_OLDPACKAGE)) { rc = rpmdbFindPackage(ts->db, alp->name, &dbi); - if (rc == 2) { + switch (rc) { + case 2: + if (dbi) { + dbiFreeIndexSet(dbi); + dbi = NULL; + } return -1; - } else if (!rc) { + /*@notreached@*/ break; + case 0: for (i = 0; i < dbiIndexSetCount(dbi); i++) ensureOlder(ts->db, alp->h, dbiIndexRecordOffset(dbi, i), probs, alp->key); - dbiFreeIndexRecord(dbi); + break; + default: + break; + } + if (dbi) { + dbiFreeIndexSet(dbi); + dbi = NULL; } } rc = findMatches(ts->db, alp->name, alp->version, alp->release, &dbi); - if (rc == 2) { + switch (rc) { + case 2: + if (dbi) { + dbiFreeIndexSet(dbi); + dbi = NULL; + } return -1; - } else if (!rc) { + /*@notreached@*/ break; + case 0: if (!(ignoreSet & RPMPROB_FILTER_REPLACEPKG)) psAppend(probs, RPMPROB_PKG_INSTALLED, alp->key, alp->h, NULL, NULL, 0); - dbiFreeIndexRecord(dbi); + break; + default: + break; + } + if (dbi) { + dbiFreeIndexSet(dbi); + dbi = NULL; } if (headerGetEntry(alp->h, RPMTAG_BASENAMES, NULL, NULL, @@ -1454,13 +1478,14 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify, * Compute file disposition for each package in transaction set. */ for (fi = flList; (fi - flList) < flEntries; fi++) { + dbiIndexSet * matches; int knownBad; NOTIFY((NULL, RPMCALLBACK_TRANS_PROGRESS, (fi - flList), flEntries, NULL, notifyData)); /* Extract file info for all files in this package from the database. */ - matches = xmalloc(sizeof(*matches) * fi->fc); + matches = xcalloc(sizeof(*matches), fi->fc); if (rpmdbFindFpList(ts->db, fi->fps, matches, fi->fc)) return 1; numShared = 0; @@ -1495,11 +1520,14 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify, shared->isRemoved = (knownBad == ro); shared++; } - dbiFreeIndexRecord(matches[i]); + if (matches[i]) { + dbiFreeIndexSet(matches[i]); + matches[i] = NULL; + } } numShared = shared - sharedList; shared->otherPkg = -1; - free(matches); + xfree(matches); /* Sort file info by other package index (otherPkg) */ qsort(sharedList, numShared, sizeof(*shared), sharedCmp); diff --git a/lib/uninstall.c b/lib/uninstall.c index 0d711d0c8..fbb0db8a8 100644 --- a/lib/uninstall.c +++ b/lib/uninstall.c @@ -4,6 +4,7 @@ #include <rpmurl.h> #include <rpmmacro.h> /* XXX for rpmExpand */ +#include "dbindex.h" /* XXX prototypes */ #include "depends.h" #include "install.h" #include "md5.h" @@ -24,7 +25,7 @@ static int removeFile(const char * file, unsigned int flags, short mode, case FA_BACKUP: newfile = alloca(strlen(file) + sizeof(SUFFIX_RPMSAVE)); - stpcpy(stpcpy(newfile, file), SUFFIX_RPMSAVE); + (void)stpcpy(stpcpy(newfile, file), SUFFIX_RPMSAVE); if (rename(file, newfile)) { rpmError(RPMERR_RENAME, _("rename of %s to %s failed: %s"), @@ -103,12 +104,12 @@ int removeBinaryPackage(const char * prefix, rpmdb db, unsigned int offset, if (rpmdbFindPackage(db, name, &matches)) { rpmError(RPMERR_DBCORRUPT, _("cannot read packages named %s for uninstall"), name); - dbiFreeIndexRecord(matches); + dbiFreeIndexSet(matches); rc = 1; goto exit; } scriptArg = dbiIndexSetCount(matches) - 1; - dbiFreeIndexRecord(matches); + dbiFreeIndexSet(matches); } if (!(flags & RPMTRANS_FLAG_NOTRIGGERS)) { @@ -170,7 +171,7 @@ int removeBinaryPackage(const char * prefix, rpmdb db, unsigned int offset, if (prefixlen) { strcpy(fileName, prefix); - rpmCleanPath(fileName); + (void)rpmCleanPath(fileName); prefixlen = strlen(fileName); } else *fileName = '\0'; @@ -186,7 +187,7 @@ int removeBinaryPackage(const char * prefix, rpmdb db, unsigned int offset, for (i = fileCount - 1; i >= 0; i--) { /* XXX this assumes that dirNames always starts/ends with '/' */ - stpcpy(stpcpy(fileName+prefixlen, dirNames[dirIndexes[i]]), baseNames[i]); + (void)stpcpy(stpcpy(fileName+prefixlen, dirNames[dirIndexes[i]]), baseNames[i]); rpmMessage(RPMMESS_DEBUG, _(" file: %s action: %s\n"), fileName, fileActionString(actions[i])); @@ -228,9 +229,8 @@ int removeBinaryPackage(const char * prefix, rpmdb db, unsigned int offset, rc = 0; exit: - if (h) { + if (h) headerFree(h); - } return rc; } @@ -453,7 +453,6 @@ static int handleOneTrigger(const char * root, rpmdb db, int sense, Header sourc int rc = 0; int i; int index; - dbiIndexSet matches; int skip; if (!headerGetEntry(triggeredH, RPMTAG_TRIGGERNAME, NULL, @@ -470,6 +469,8 @@ static int handleOneTrigger(const char * root, rpmdb db, int sense, Header sourc (void **) &triggerEVR, NULL); for (i = 0; i < numTriggers; i++) { + dbiIndexSet matches; + if (!(triggerFlags[i] & sense)) continue; if (strcmp(triggerNames[i], sourceName)) continue; @@ -497,8 +498,9 @@ static int handleOneTrigger(const char * root, rpmdb db, int sense, Header sourc headerGetEntry(triggeredH, RPMTAG_NAME, NULL, (void **) &triggerPackageName, NULL); + + matches = NULL; rpmdbFindPackage(db, triggerPackageName, &matches); - dbiFreeIndexRecord(matches); index = triggerIndices[i]; if (!triggersAlreadyRun || !triggersAlreadyRun[index]) { @@ -509,6 +511,10 @@ static int handleOneTrigger(const char * root, rpmdb db, int sense, Header sourc if (triggersAlreadyRun) triggersAlreadyRun[index] = 1; } + if (matches) { + dbiFreeIndexSet(matches); + matches = NULL; + } free(triggerScripts); free(triggerProgs); @@ -526,8 +532,8 @@ static int handleOneTrigger(const char * root, rpmdb db, int sense, Header sourc int runTriggers(const char * root, rpmdb db, int sense, Header h, int countCorrection, FD_t scriptFd) { - char * packageName; - dbiIndexSet matches, otherMatches; + const char * packageName; + dbiIndexSet matches; Header triggeredH; int numPackage; int rc; @@ -535,20 +541,31 @@ int runTriggers(const char * root, rpmdb db, int sense, Header h, headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &packageName, NULL); - if ((rc = rpmdbFindByTriggeredBy(db, packageName, &matches)) < 0) - return 1; - else if (rc) - return 0; + matches = NULL; + if ((rc = rpmdbFindByTriggeredBy(db, packageName, &matches)) < 0) { + rc = 1; + goto exit; + } else if (rc) { + rc = 0; + goto exit; + } - rpmdbFindPackage(db, packageName, &otherMatches); - numPackage = dbiIndexSetCount(otherMatches) + countCorrection; - dbiFreeIndexRecord(otherMatches); + { dbiIndexSet otherMatches = NULL; + rpmdbFindPackage(db, packageName, &otherMatches); + if (otherMatches) { + numPackage = dbiIndexSetCount(otherMatches) + countCorrection; + dbiFreeIndexSet(otherMatches); + } else + numPackage = 0; + } rc = 0; for (i = 0; i < dbiIndexSetCount(matches); i++) { unsigned int recOffset = dbiIndexRecordOffset(matches, i); - if ((triggeredH = rpmdbGetRecord(db, recOffset)) == NULL) - return 1; + if ((triggeredH = rpmdbGetRecord(db, recOffset)) == NULL) { + rc = 1; + break; + } rc |= handleOneTrigger(root, db, sense, h, triggeredH, 0, numPackage, NULL, scriptFd); @@ -556,18 +573,21 @@ int runTriggers(const char * root, rpmdb db, int sense, Header h, headerFree(triggeredH); } - dbiFreeIndexRecord(matches); +exit: + if (matches) { + dbiFreeIndexSet(matches); + matches = NULL; + } return rc; - } /** */ int runImmedTriggers(const char * root, rpmdb db, int sense, Header h, int countCorrection, FD_t scriptFd) { - int rc = 0; dbiIndexSet matches; + int rc = 0; char ** triggerNames; int numTriggers; int i, j; @@ -583,7 +603,14 @@ int runImmedTriggers(const char * root, rpmdb db, int sense, Header h, triggersRun = alloca(sizeof(*triggersRun) * i); memset(triggersRun, 0, sizeof(*triggersRun) * i); + matches = NULL; for (i = 0; i < numTriggers; i++) { + + if (matches) { + dbiFreeIndexSet(matches); + matches = NULL; + } + if (triggersRun[triggerIndices[i]]) continue; if ((j = rpmdbFindPackage(db, triggerNames[i], &matches))) { @@ -593,17 +620,22 @@ int runImmedTriggers(const char * root, rpmdb db, int sense, Header h, for (j = 0; j < dbiIndexSetCount(matches); j++) { unsigned int recOffset = dbiIndexRecordOffset(matches, j); - if ((sourceH = rpmdbGetRecord(db, recOffset)) == NULL) - return 1; + if ((sourceH = rpmdbGetRecord(db, recOffset)) == NULL) { + rc = 1; + goto exit; + } rc |= handleOneTrigger(root, db, sense, sourceH, h, countCorrection, dbiIndexSetCount(matches), triggersRun, scriptFd); headerFree(sourceH); if (triggersRun[triggerIndices[i]]) break; } - - dbiFreeIndexRecord(matches); } +exit: + if (matches) { + dbiFreeIndexSet(matches); + matches = NULL; + } return rc; } diff --git a/lib/verify.c b/lib/verify.c index af3180e44..ca148f4d4 100644 --- a/lib/verify.c +++ b/lib/verify.c @@ -10,7 +10,7 @@ #include <rpmurl.h> static int _ie = 0x44332211; -static union _endian { int i; char b[4]; } *_endian = (union _endian *)&_ie; +static union _vendian { int i; char b[4]; } *_endian = (union _vendian *)&_ie; #define IS_BIG_ENDIAN() (_endian->b[0] == '\x44') #define IS_LITTLE_ENDIAN() (_endian->b[0] == '\x11') |