From c7ee57336766b4411f3aeaaa78dd3778cfea3244 Mon Sep 17 00:00:00 2001 From: jbj Date: Fri, 11 May 2001 04:01:04 +0000 Subject: [PATCH] - rpm database has rpm.rpm g+w permissions to share db3 mutexes. - expose more db3 macro configuration tokens. - move fprint.[ch] and hash.[ch] to rpmdb directory. - detect and fiddle incompatible mixtures of db3 env/open flags. - add DBI_WRITECURSOR to map to db3 flags with CDB database model. - add rpmdbSetIteratorRewrite to warn of pending lazy (re-)writes. CVS patchset: 4765 CVS date: 2001/05/11 04:01:04 --- CHANGES | 6 +- Doxyfile.in | 8 +- Makefile.am | 13 +++ db/os/os_map.c | 2 +- db3/configure | 10 +-- lib/Makefile.am | 6 +- lib/depends.c | 4 +- lib/fprint.c | 249 ------------------------------------------------------ lib/fprint.h | 136 ----------------------------- lib/hash.c | 169 ------------------------------------ lib/hash.h | 91 -------------------- lib/psm.c | 1 + lib/query.c | 2 + lib/rpmlib.h | 14 ++- lib/transaction.c | 2 +- perl/Makefile.in | 4 + po/POTFILES.in | 4 +- rpm.spec.in | 6 +- rpmdb/Makefile.am | 4 +- rpmdb/db1.c | 2 +- rpmdb/db2.c | 2 +- rpmdb/db3.c | 105 +++++++++++++++-------- rpmdb/dbconfig.c | 2 +- rpmdb/falloc.c | 2 +- rpmdb/falloc.h | 2 +- rpmdb/rpmdb.c | 154 +++++++++++++++++++++++---------- rpmdb/rpmdb.h | 11 ++- rpmio/rpmerr.h | 3 +- rpmio/rpmmacro.h | 4 +- 29 files changed, 258 insertions(+), 760 deletions(-) delete mode 100644 lib/fprint.c delete mode 100644 lib/fprint.h delete mode 100644 lib/hash.c delete mode 100644 lib/hash.h diff --git a/CHANGES b/CHANGES index 37a09fe..9a4c034 100644 --- a/CHANGES +++ b/CHANGES @@ -48,8 +48,12 @@ - use internal db-3.2.9 sources to build by default. - don't build db1 support by default. - create rpmdb.la so that linkage against rpm's db-3.2.9 is possible. - - rpm executables now setuid rpm to share write locks. + - rpm database has rpm.rpm g+w permissions to share db3 mutexes. - expose more db3 macro configuration tokens. + - move fprint.[ch] and hash.[ch] to rpmdb directory. + - detect and fiddle incompatible mixtures of db3 env/open flags. + - add DBI_WRITECURSOR to map to db3 flags with CDB database model. + - add rpmdbSetIteratorRewrite to warn of pending lazy (re-)writes. 4.0 -> 4.0.[12] - add doxygen and lclint annotations most everywhere. diff --git a/Doxyfile.in b/Doxyfile.in index 2e4cbf0..8240872 100644 --- a/Doxyfile.in +++ b/Doxyfile.in @@ -356,13 +356,9 @@ INPUT = \ ./lib/depends.c \ ./lib/depends.h \ ./lib/formats.c \ - ./lib/fprint.c \ - ./lib/fprint.h \ ./lib/fs.c \ ./lib/fsm.c \ ./lib/fsm.h \ - ./lib/hash.c \ - ./lib/hash.h \ ./lib/header.c \ ./lib/header.h \ ./lib/manifest.c \ @@ -400,6 +396,10 @@ INPUT = \ ./rpmdb/dbconfig.c \ ./rpmdb/falloc.c \ ./rpmdb/falloc.h \ + ./rpmdb/fprint.c \ + ./rpmdb/fprint.h \ + ./rpmdb/rpmhash.c \ + ./rpmdb/rpmhash.h \ ./rpmdb/rpmdb.c \ ./rpmdb/rpmdb.h \ ./rpmio/base64.c \ diff --git a/Makefile.am b/Makefile.am index 1a47937..8d3978c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -180,6 +180,19 @@ setperms: done @$(__CHOWN) ${RPMUSER}.${RPMGROUP} $(DESTDIR)$(pkglibdir) @$(__CHOWN) -R ${RPMUSER}.${RPMGROUP} $(DESTDIR)$(varprefix)/lib/rpm + -@$(__CHMOD) 0664 $(DESTDIR)$(varprefix)/lib/rpm/[A-Z]* + -@$(__CHMOD) 0775 $(DESTDIR)$(varprefix)/lib/rpm + -@$(__CHMOD) 0755 $(DESTDIR)$(varprefix)/lib/rpm/Desktop + -@$(__CHMOD) 0664 $(DESTDIR)$(varprefix)/lib/rpm/__db.* + +.PHONY: unsetuid +unsetuid: + @for f in $(rpmbin_PROGRAMS) ; do\ + $(__CHMOD) u-s $(DESTDIR)$(rpmbindir)/$$f ;\ + done + @for f in $(pkglib_PROGRAMS) ; do\ + $(__CHMOD) u-s $(DESTDIR)$(pkglibdir)/$$f ;\ + done .PHONY: tar tar: diff --git a/db/os/os_map.c b/db/os/os_map.c index bb96a91..590ebc5 100644 --- a/db/os/os_map.c +++ b/db/os/os_map.c @@ -110,7 +110,7 @@ __os_r_sysattach(dbenv, infop, rp) } } if ((id = - shmget(segid, rp->size, IPC_CREAT | 0600)) == -1) { + shmget(segid, rp->size, IPC_CREAT | 0660)) == -1) { ret = __os_get_errno(); __db_err(dbenv, "shmget: key: %ld: unable to create shared system memory region: %s", diff --git a/db3/configure b/db3/configure index 16f8f8e..3128c6f 100755 --- a/db3/configure +++ b/db3/configure @@ -1,11 +1,13 @@ #!/bin/sh #set -x db_dist="../db/dist" -CFLAGS="$CFLAGS" $db_dist/configure \ - $(echo $* | sed -e "s% --srcdir=[^ ]*% --enable-shared --enable-static --srcdir=$db_dist%") + +rm -f config.cache +CFALGS="-O2" $db_dist/configure \ + $(echo $* | sed -e "s% --cache-file=.*$% --enable-shared --enable-static --enable-debug --enable-rpc --srcdir=$db_dist%") mv Makefile Makefile.orig -cat Makefile.orig | sed -e '/^install:/c\ +cat Makefile.orig | sed -e 's/ -g$/ -g -O2/' -e '/^install:/c\ .PHONY: listobjs\ listobjs:\ @echo $(OBJS)\ @@ -13,5 +15,3 @@ listobjs:\ distdir install:\ \ db3_install: all install_setip \\' > Makefile - -make -s listobjs > db3lobjs diff --git a/lib/Makefile.am b/lib/Makefile.am index a1b4974..7a112e6 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -16,7 +16,7 @@ pkgincdir = $(pkgincludedir) pkginc_HEADERS = \ header.h misc.h rpmlib.h stringbuf.h noinst_HEADERS = \ - cpio.h depends.h fprint.h fsm.h hash.h \ + cpio.h depends.h fsm.h \ manifest.h md5.h psm.h \ rpmlead.h signature.h @@ -31,8 +31,8 @@ LIBS = lib_LTLIBRARIES = librpm.la librpm_la_SOURCES = \ - cpio.c depends.c formats.c fprint.c fs.c fsm.c getdate.c \ - hash.c header.c manifest.c md5.c md5sum.c misc.c package.c \ + cpio.c depends.c formats.c fs.c fsm.c getdate.c \ + header.c manifest.c md5.c md5sum.c misc.c package.c \ problems.c poptBT.c poptQV.c psm.c query.c rpmchecksig.c \ rpminstall.c rpmlead.c rpmlibprov.c rpmrc.c signature.c \ stringbuf.c tagName.c tagtable.c transaction.c verify.c diff --git a/lib/depends.c b/lib/depends.c index 437e784..477837e 100644 --- a/lib/depends.c +++ b/lib/depends.c @@ -1191,7 +1191,7 @@ exit: } else { DBC * dbcursor = NULL; int xx; - xx = dbiCopen(dbi, &dbcursor, 0); + xx = dbiCopen(dbi, &dbcursor, DBI_WRITECURSOR); xx = dbiPut(dbi, dbcursor, keyDepend, strlen(keyDepend), &rc, sizeof(rc), 0); if (xx) _cacheDependsRC = 0; @@ -1199,7 +1199,7 @@ exit: else rpmMessage(RPMMESS_DEBUG, _("%s: (%s, %s) added to Depends cache.\n"), keyType, keyDepend, (rc ? _("NO ") : _("YES"))); #endif - xx = dbiCclose(dbi, dbcursor, 0); + xx = dbiCclose(dbi, dbcursor, DBI_WRITECURSOR); } } return rc; diff --git a/lib/fprint.c b/lib/fprint.c deleted file mode 100644 index 1a9e4c8..0000000 --- a/lib/fprint.c +++ /dev/null @@ -1,249 +0,0 @@ -/** - * \file lib/fprint.c - */ - -#include "system.h" -#include -#include /* XXX for rpmCleanPath */ - -#include "fprint.h" -#include "debug.h" - -fingerPrintCache fpCacheCreate(int sizeHint) -{ - fingerPrintCache fpc; - - fpc = xmalloc(sizeof(*fpc)); - fpc->ht = htCreate(sizeHint * 2, 0, 1, hashFunctionString, - hashEqualityString); - return fpc; -} - -void fpCacheFree(fingerPrintCache cache) -{ - htFree(cache->ht); - free(cache); -} - -/** - * Find directory name entry in cache. - * @param cache pointer to fingerprint cache - * @param dirName string to locate in cache - * @return pointer to directory name entry (or NULL if not found). - */ -static const struct fprintCacheEntry_s * cacheContainsDirectory( - fingerPrintCache cache, - const char * dirName) -{ - const void ** data; - - if (htGetEntry(cache->ht, dirName, &data, NULL, NULL)) - return NULL; - return data[0]; -} - -/** - * Return finger print of a file path. - * @param cache pointer to fingerprint cache - * @param dirName leading directory name of path - * @param baseName file name of path - * @param scareMemory - * @return pointer to the finger print associated with a file path. - */ -static fingerPrint doLookup(fingerPrintCache cache, - const char * dirName, const char * baseName, int scareMemory) -{ - char dir[PATH_MAX]; - const char * cleanDirName; - size_t cdnl; - char * end; /* points to the '\0' at the end of "buf" */ - fingerPrint fp; - struct stat sb; - char * buf; - const struct fprintCacheEntry_s * cacheHit; - - /* assert(*dirName == '/' || !scareMemory); */ - - /* XXX WATCHOUT: fp.subDir is set below from relocated dirName arg */ - cleanDirName = dirName; - cdnl = strlen(cleanDirName); - - if (*cleanDirName == '/') { - if (!scareMemory) - cleanDirName = - rpmCleanPath(strcpy(alloca(cdnl+1), dirName)); - } else { - scareMemory = 0; /* XXX causes memory leak */ - - /* Using realpath on the arg isn't correct if the arg is a symlink, - * especially if the symlink is a dangling link. What we - * do instead is use realpath() on `.' and then append arg to - * the result. - */ - - /* if the current directory doesn't exist, we might fail. - oh well. likewise if it's too long. */ - dir[0] = '\0'; - if ( /*@-unrecog@*/ realpath(".", dir) /*@=unrecog@*/ != NULL) { - end = dir + strlen(dir); - if (end[-1] != '/') *end++ = '/'; - end = stpncpy(end, cleanDirName, sizeof(dir) - (end - dir)); - *end = '\0'; - (void)rpmCleanPath(dir); /* XXX possible /../ from concatenation */ - end = dir + strlen(dir); - if (end[-1] != '/') *end++ = '/'; - *end = '\0'; - cleanDirName = dir; - cdnl = end - dir; - } - } - fp.entry = NULL; - fp.subDir = NULL; - fp.baseName = NULL; - if (cleanDirName == NULL) return fp; /* XXX can't happen */ - - buf = strcpy(alloca(cdnl + 1), cleanDirName); - end = buf + cdnl; - - /* no need to pay attention to that extra little / at the end of dirName */ - if (buf[1] && end[-1] == '/') { - end--; - *end = '\0'; - } - - while (1) { - - /* as we're stating paths here, we want to follow symlinks */ - - cacheHit = cacheContainsDirectory(cache, (*buf != '\0' ? buf : "/")); - if (cacheHit != NULL) { - fp.entry = cacheHit; - } else if (!stat((*buf != '\0' ? buf : "/"), &sb)) { - size_t nb = sizeof(*fp.entry) + (*buf != '\0' ? (end-buf) : 1) + 1; - char * dn = xmalloc(nb); - struct fprintCacheEntry_s * newEntry = (void *)dn; - - dn += sizeof(*newEntry); - strcpy(dn, (*buf != '\0' ? buf : "/")); - newEntry->ino = sb.st_ino; - newEntry->dev = sb.st_dev; - newEntry->isFake = 0; - newEntry->dirName = dn; - fp.entry = newEntry; - - /*@-kepttrans@*/ - htAddEntry(cache->ht, dn, fp.entry); - /*@@kepttrans@*/ - } - - if (fp.entry) { - fp.subDir = cleanDirName + (end - buf); - if (fp.subDir[0] == '/' && fp.subDir[1] != '\0') - fp.subDir++; - if (fp.subDir[0] == '\0' || - /* XXX don't bother saving '/' as subdir */ - (fp.subDir[0] == '/' && fp.subDir[1] == '\0')) - fp.subDir = NULL; - fp.baseName = baseName; - if (!scareMemory && fp.subDir != NULL) - fp.subDir = xstrdup(fp.subDir); - return fp; - } - - /* stat of '/' just failed! */ - if (end == buf + 1) - abort(); - - end--; - while ((end > buf) && *end != '/') end--; - if (end == buf) /* back to stat'ing just '/' */ - end++; - - *end = '\0'; - } - - /*@notreached@*/ - - /*@-nullret@*/ return fp; /*@=nullret@*/ /* LCL: can't happen. */ -} - -fingerPrint fpLookup(fingerPrintCache cache, const char * dirName, - const char * baseName, int scareMemory) -{ - return doLookup(cache, dirName, baseName, scareMemory); -} - -unsigned int fpHashFunction(const void * key) -{ - const fingerPrint * fp = key; - unsigned int hash = 0; - char ch; - const char * chptr; - - ch = 0; - chptr = fp->baseName; - while (*chptr != '\0') ch ^= *chptr++; - - hash |= ((unsigned)ch) << 24; - hash |= (((((unsigned)fp->entry->dev) >> 8) ^ fp->entry->dev) & 0xFF) << 16; - hash |= fp->entry->ino & 0xFFFF; - - return hash; -} - -int fpEqual(const void * key1, const void * key2) -{ - const fingerPrint *k1 = key1; - const fingerPrint *k2 = key2; - - /* If the addresses are the same, so are the values. */ - if (k1 == k2) - return 0; - - /* Otherwise, compare fingerprints by value. */ - /*@-nullpass@*/ /* LCL: whines about (*k2).subdir */ - if (FP_EQUAL(*k1, *k2)) - return 0; - /*@=nullpass@*/ - return 1; - -} - -void fpLookupList(fingerPrintCache cache, const char ** dirNames, - const char ** baseNames, const int * dirIndexes, - int fileCount, fingerPrint * fpList) -{ - int i; - - for (i = 0; i < fileCount; i++) { - /* If this is in the same directory as the last file, don't bother - redoing all of this work */ - if (i > 0 && dirIndexes[i - 1] == dirIndexes[i]) { - fpList[i].entry = fpList[i - 1].entry; - fpList[i].subDir = fpList[i - 1].subDir; - fpList[i].baseName = baseNames[i]; - } else { - fpList[i] = doLookup(cache, dirNames[dirIndexes[i]], baseNames[i], - 1); - } - } -} - -void fpLookupHeader(fingerPrintCache cache, Header h, fingerPrint * fpList) -{ - HGE_t hge = (HGE_t)headerGetEntryMinMemory; - HFD_t hfd = headerFreeData; - const char ** baseNames, ** dirNames; - int bnt, dnt; - int_32 * dirIndexes; - int fileCount; - - if (!hge(h, RPMTAG_BASENAMES, &bnt, (void **) &baseNames, &fileCount)) - return; - - (void) hge(h, RPMTAG_DIRNAMES, &dnt, (void **) &dirNames, NULL); - (void) hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &dirIndexes, NULL); - fpLookupList(cache, dirNames, baseNames, dirIndexes, fileCount, fpList); - dirNames = hfd(dirNames, dnt); - baseNames = hfd(baseNames, bnt); -} diff --git a/lib/fprint.h b/lib/fprint.h deleted file mode 100644 index baa6e11..0000000 --- a/lib/fprint.h +++ /dev/null @@ -1,136 +0,0 @@ -#ifndef H_FINGERPRINT -#define H_FINGERPRINT - -/** \ingroup rpmtrans - * \file lib/fprint.h - * Identify a file name path by a unique "finger print". - */ - -#include "hash.h" -#include "header.h" - -/** - * Finger print cache entry. - * This is really a directory and symlink cache. We don't differentiate between - * the two. We can prepopulate it, which allows us to easily conduct "fake" - * installs of a system w/o actually mounting filesystems. - */ -struct fprintCacheEntry_s { - const char * dirName; /*!< path to existing directory */ - dev_t dev; /*!< stat(2) device number */ - ino_t ino; /*!< stat(2) inode number */ - int isFake; /*!< (currently unused) */ -}; - -/** - * Finger print cache. - */ -typedef /*@abstract@*/ struct fprintCache_s { - hashTable ht; /*!< hashed by dirName */ -} * fingerPrintCache; - -/** - * Associates a trailing sub-directory and final base name with an existing - * directory finger print. - */ -typedef struct fingerPrint_s { -/*! directory finger print entry (the directory path is stat(2)-able */ - const struct fprintCacheEntry_s * entry; -/*! trailing sub-directory path (directories that are not stat(2)-able */ -/*@owned@*/ /*@null@*/ const char * subDir; -/*@dependent@*/ const char * baseName; /*!< file base name */ -} fingerPrint; - -/* only if !scarceMemory */ -/** */ -#define fpFree(a) free((void *)(a).baseName) - -/** */ -#define FP_ENTRY_EQUAL(a, b) (((a)->dev == (b)->dev) && ((a)->ino == (b)->ino)) - -/** */ -#define FP_EQUAL(a, b) ( \ - FP_ENTRY_EQUAL((a).entry, (b).entry) && \ - !strcmp((a).baseName, (b).baseName) && ( \ - ((a).subDir == (b).subDir) || \ - ((a).subDir && (b).subDir && !strcmp((a).subDir, (b).subDir)) \ - ) \ - ) - -#ifdef __cplusplus -extern "C" { -#endif - -/* Be carefull with the memory... assert(*fullName == '/' || !scareMemory) */ - -/** - * Create finger print cache. - * @param sizeHint number of elements expected - * @return pointer to initialized fingerprint cache - */ -/*@only@*/ fingerPrintCache fpCacheCreate(int sizeHint) /*@*/; - -/** - * Destroy finger print cache. - * @param cache pointer to fingerprint cache - */ -void fpCacheFree(/*@only@*/ fingerPrintCache cache); - -/** - * Return finger print of a file path. - * @param cache pointer to fingerprint cache - * @param dirName leading directory name of file path - * @param baseName base name of file path - * @param scareMemory - * @return pointer to the finger print associated with a file path. - */ -fingerPrint fpLookup(fingerPrintCache cache, const char * dirName, - const char * baseName, int scareMemory) /*@*/; - -/** - * Return hash value for a finger print. - * Hash based on dev and inode only! - * @param key pointer to finger print entry - * @return hash value - */ -unsigned int fpHashFunction(const void * key) /*@*/; - -/** - * Compare two finger print entries. - * exactly equivalent to FP_EQUAL macro. - * @param key1 finger print 1 - * @param key2 finger print 2 - * @return result of comparing key1 and key2 - */ -int fpEqual(const void * key1, const void * key2) /*@*/; - -/** - * Return finger prints of an array of file paths. - * @warning: scareMemory is assumed! - * @param cache pointer to fingerprint cache - * @param dirNames directory names - * @param baseNames file base names - * @param dirIndexes index into dirNames for each baseNames - * @param fileCount number of file entries - * @retval fpList pointer to array of finger prints - */ -void fpLookupList(fingerPrintCache cache, const char ** dirNames, - const char ** baseNames, const int * dirIndexes, - int fileCount, fingerPrint * fpList) - /*@modifies cache, *fpList @*/; - -/** - * Return finger prints of all file names in header. - * @warning: scareMemory is assumed! - * @param cache pointer to fingerprint cache - * @param h package header - * @retval fpList pointer to array of finger prints - */ -void fpLookupHeader(fingerPrintCache cache, Header h, fingerPrint * fpList) - /*@modifies h, cache, *fpList @*/; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/hash.c b/lib/hash.c deleted file mode 100644 index e333954..0000000 --- a/lib/hash.c +++ /dev/null @@ -1,169 +0,0 @@ -/** - * \file lib/hash.c - * Hash table implemenation - */ - -#include "system.h" -#include -#include "hash.h" -#include "debug.h" - -typedef /*@owned@*/ const void * voidptr; - -/** */ -struct hashBucket { - 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; /*!< 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@*/ /*@null@*/ -struct hashBucket *findEntry(hashTable ht, const void * key) -{ - unsigned int hash; - struct hashBucket * b; - - hash = ht->fn(key) % ht->numBuckets; - b = ht->buckets[hash]; - - while (b && b->key && ht->eq(b->key, key)) - b = b->next; - - return b; -} - -int hashEqualityString(const void * key1, const void * key2) -{ - const char *k1 = (const char *)key1; - const char *k2 = (const char *)key2; - return strcmp(k1, k2); -} - -unsigned int hashFunctionString(const void * string) -{ - char xorValue = 0; - char sum = 0; - short len; - int i; - const char * chp = string; - - len = strlen(string); - for (i = 0; i < len; i++, chp++) { - xorValue ^= *chp; - sum += *chp; - } - - return ((((unsigned)len) << 16) + (((unsigned)sum) << 8) + xorValue); -} - -hashTable htCreate(int numBuckets, int keySize, int freeData, hashFunctionType fn, - hashEqualityType eq) -{ - hashTable ht; - - ht = xmalloc(sizeof(*ht)); - ht->numBuckets = numBuckets; - ht->buckets = xcalloc(numBuckets, sizeof(*ht->buckets)); - ht->keySize = keySize; - ht->freeData = freeData; - ht->fn = fn; - ht->eq = eq; - - return ht; -} - -void htAddEntry(hashTable ht, const void * key, const void * data) -{ - unsigned int hash; - struct hashBucket * b; - - hash = ht->fn(key) % ht->numBuckets; - b = ht->buckets[hash]; - - while (b && b->key && ht->eq(b->key, key)) - b = b->next; - - if (b == NULL) { - b = xmalloc(sizeof(*b)); - if (ht->keySize) { - char *k = xmalloc(ht->keySize); - memcpy(k, key, ht->keySize); - b->key = k; - } else { - b->key = key; - } - b->dataCount = 0; - b->next = ht->buckets[hash]; - b->data = NULL; - ht->buckets[hash] = b; - } - - b->data = xrealloc(b->data, sizeof(*b->data) * (b->dataCount + 1)); - b->data[b->dataCount++] = data; -} - -void htFree(hashTable ht) -{ - struct hashBucket * b, * n; - int i; - - for (i = 0; i < ht->numBuckets; i++) { - b = ht->buckets[i]; - if (ht->keySize && b) free((void *)b->key); - while (b) { - n = b->next; - if (b->data) { - if (ht->freeData) - *b->data = _free(*b->data); - b->data = _free(b->data); - } - b = _free(b); - b = n; - } - } - - ht->buckets = _free(ht->buckets); - ht = _free(ht); -} - -int htHasEntry(hashTable ht, const void * key) -{ - struct hashBucket * b; - - if (!(b = findEntry(ht, key))) return 0; else return 1; -} - -int htGetEntry(hashTable ht, const void * key, const void *** data, - int * dataCount, const void ** tableKey) -{ - struct hashBucket * b; - - if ((b = findEntry(ht, key)) == NULL) - return 1; - - if (data) - *data = (const void **) b->data; - if (dataCount) - *dataCount = b->dataCount; - if (tableKey) - *tableKey = b->key; - - return 0; -} diff --git a/lib/hash.h b/lib/hash.h deleted file mode 100644 index 402cd29..0000000 --- a/lib/hash.h +++ /dev/null @@ -1,91 +0,0 @@ -#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) /*@*/; - -/** - * 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) /*@*/; - -/** - * 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) /*@*/; - -/** - * Destroy hash table. - * @param ht pointer to hash table - */ -void htFree( /*@only@*/ hashTable ht); - -/** - * 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) /*@modifies ht */; - -/** - * 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, - /*@null@*/ /*@out@*/ const void *** data, - /*@null@*/ /*@out@*/ int * dataCount, - /*@null@*/ /*@out@*/ const void ** tableKey) - /*@modifies *data, *dataCount, *tableKey @*/; - -/** - * 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 -} -#endif - -#endif diff --git a/lib/psm.c b/lib/psm.c index 022651d..778a8e4 100644 --- a/lib/psm.c +++ b/lib/psm.c @@ -499,6 +499,7 @@ static int markReplacedFiles(PSM_t psm) mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES, NULL, 0); (void) rpmdbAppendIterator(mi, offsets, num); + (void) rpmdbSetIteratorRewrite(mi, 1); sfi = replaced; while ((h = rpmdbNextIterator(mi)) != NULL) { diff --git a/lib/query.c b/lib/query.c index b8f6c78..c74b69d 100644 --- a/lib/query.c +++ b/lib/query.c @@ -460,8 +460,10 @@ int showMatches(QVA_t qva, rpmdbMatchIterator mi, QVF_t showPackage) while ((h = rpmdbNextIterator(mi)) != NULL) { int rc; + /*@-nullpass@*/ if ((rc = showPackage(qva, rpmdbGetIteratorRpmDB(mi), h)) != 0) ec = rc; + /*@=nullpass@*/ } mi = rpmdbFreeIterator(mi); return ec; diff --git a/lib/rpmlib.h b/lib/rpmlib.h index e32f58e..2f733d2 100644 --- a/lib/rpmlib.h +++ b/lib/rpmlib.h @@ -650,7 +650,9 @@ typedef /*@abstract@*/ struct _rpmdbMatchIterator * rpmdbMatchIterator; * @param mi rpm database iterator * @return rpm database handle */ -/*@kept@*/ rpmdb rpmdbGetIteratorRpmDB(/*@null@*/ rpmdbMatchIterator mi) /*@*/; +/*@kept@*/ /*@null@*/ rpmdb rpmdbGetIteratorRpmDB( + /*@null@*/ rpmdbMatchIterator mi) + /*@*/; /** \ingroup rpmdb * Return join key for current position of rpm database iterator. @@ -710,6 +712,16 @@ void rpmdbSetIteratorRelease(/*@null@*/ rpmdbMatchIterator mi, /*@modifies mi @*/; /** \ingroup rpmdb + * Prepare iterator for lazy writes. + * @note: must be called before rpmdbNextIterator() in CDB model database. + * @param mi rpm database iterator + * @param rewrite new value of rewrite + * @return previous value + */ +int rpmdbSetIteratorRewrite(/*@null@*/ rpmdbMatchIterator mi, int rewrite) + /*@modifies mi @*/; + +/** \ingroup rpmdb * Modify iterator to mark header for lazy write. * @param mi rpm database iterator * @param modified new value of modified diff --git a/lib/transaction.c b/lib/transaction.c index b1dd2f4..c61ec3d 100644 --- a/lib/transaction.c +++ b/lib/transaction.c @@ -9,7 +9,7 @@ #include "psm.h" #include "fprint.h" -#include "hash.h" +#include "rpmhash.h" #include "md5.h" #include "misc.h" #include "rpmdb.h" diff --git a/perl/Makefile.in b/perl/Makefile.in index 547b2bb..a46fcc9 100644 --- a/perl/Makefile.in +++ b/perl/Makefile.in @@ -123,6 +123,10 @@ RPMCANONARCH = @RPMCANONARCH@ RPMCANONOS = @RPMCANONOS@ RPMCANONVENDOR = @RPMCANONVENDOR@ RPMCONFIGDIR = @RPMCONFIGDIR@ +RPMGID = @RPMGID@ +RPMGROUP = @RPMGROUP@ +RPMUID = @RPMUID@ +RPMUSER = @RPMUSER@ SYSCONFIGDIR = @SYSCONFIGDIR@ U = @U@ UNZIPBIN = @UNZIPBIN@ diff --git a/po/POTFILES.in b/po/POTFILES.in index 1d51241..9708164 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -27,10 +27,8 @@ build/spec.c lib/cpio.c lib/depends.c lib/formats.c -lib/fprint.c lib/fs.c lib/fsm.c -lib/hash.c lib/header.c lib/manifest.c lib/md5.c @@ -55,6 +53,8 @@ rpmdb/db2.c rpmdb/db3.c rpmdb/dbconfig.c rpmdb/falloc.c +rpmdb/fprint.c +rpmdb/rpmhash.c rpmdb/rpmdb.c rpmio/base64.c rpmio/digest.c diff --git a/rpm.spec.in b/rpm.spec.in index f3da260..de9137b 100644 --- a/rpm.spec.in +++ b/rpm.spec.in @@ -207,7 +207,7 @@ fi %files %defattr(-,root,root) %doc RPM-PGP-KEY RPM-GPG-KEY CHANGES GROUPS doc/manual/[a-z]* -%attr(4755, @@RPMUSER@@, @@RPMGROUP@@) /bin/rpm +%attr(0755, @@RPMUSER@@, @@RPMGROUP@@) /bin/rpm %dir /etc/rpm %config(missingok) /etc/rpm/macros.db1 %attr(0755, @@RPMUSER@@, @@RPMGROUP@@) %{__prefix}/bin/rpm2cpio @@ -228,7 +228,7 @@ fi %attr(0755, @@RPMUSER@@, @@RPMGROUP@@) %{__prefix}/lib/rpm/convertrpmrc.sh %attr(0644, @@RPMUSER@@, @@RPMGROUP@@) %{__prefix}/lib/rpm/macros %attr(0755, @@RPMUSER@@, @@RPMGROUP@@) %{__prefix}/lib/rpm/mkinstalldirs -%attr(4755, @@RPMUSER@@, @@RPMGROUP@@) %{__prefix}/lib/rpm/rpm[deiukqv] +%attr(0755, @@RPMUSER@@, @@RPMGROUP@@) %{__prefix}/lib/rpm/rpm[deiukqv] %attr(0644, @@RPMUSER@@, @@RPMGROUP@@) %{__prefix}/lib/rpm/rpmpopt* %attr(0644, @@RPMUSER@@, @@RPMGROUP@@) %{__prefix}/lib/rpm/rpmrc @@ -322,7 +322,7 @@ fi %attr(0755, @@RPMUSER@@, @@RPMGROUP@@) %{__prefix}/lib/rpm/magic.req %attr(0755, @@RPMUSER@@, @@RPMGROUP@@) %{__prefix}/lib/rpm/perl.prov %attr(0755, @@RPMUSER@@, @@RPMGROUP@@) %{__prefix}/lib/rpm/perl.req -%attr(4755, @@RPMUSER@@, @@RPMGROUP@@) %{__prefix}/lib/rpm/rpm[bt] +%attr(0755, @@RPMUSER@@, @@RPMGROUP@@) %{__prefix}/lib/rpm/rpm[bt] %attr(0755, @@RPMUSER@@, @@RPMGROUP@@) %{__prefix}/lib/rpm/rpmdiff %attr(0755, @@RPMUSER@@, @@RPMGROUP@@) %{__prefix}/lib/rpm/rpmdiff.cgi %attr(0755, @@RPMUSER@@, @@RPMGROUP@@) %{__prefix}/lib/rpm/u_pkg.sh diff --git a/rpmdb/Makefile.am b/rpmdb/Makefile.am index 8de1f01..c3a8df3 100644 --- a/rpmdb/Makefile.am +++ b/rpmdb/Makefile.am @@ -14,7 +14,7 @@ EXTRA_DIST = db3.c db2.c db1.c falloc.c pkgincdir = $(pkgincludedir) pkginc_HEADERS = rpmdb.h -noinst_HEADERS = falloc.h +noinst_HEADERS = falloc.h fprint.h rpmhash.h mylibpaths = \ -L$(top_builddir)/lib/.libs \ @@ -27,7 +27,7 @@ LIBS = DB3LOBJS = $(shell cat $(top_builddir)/$(WITH_DB_SUBDIR)/db3lobjs) lib_LTLIBRARIES = librpmdb.la -librpmdb_la_SOURCES = $(DBLIBSRCS) dbconfig.c rpmdb.c +librpmdb_la_SOURCES = $(DBLIBSRCS) dbconfig.c fprint.c rpmhash.c rpmdb.c librpmdb_la_LDFLAGS = @libdb3@ @libdb2@ @libdb1@ librpmdb_la_LIBADD = $(DBLIBOBJS) $(DB3LOBJS) librpmdb_la_DEPENDENCIES = $(DBLIBOBJS) createlinks diff --git a/rpmdb/db1.c b/rpmdb/db1.c index 4162afb..cb88f37 100644 --- a/rpmdb/db1.c +++ b/rpmdb/db1.c @@ -1,5 +1,5 @@ /** \ingroup db1 - * \file lib/db1.c + * \file rpmdb/db1.c */ #include "system.h" diff --git a/rpmdb/db2.c b/rpmdb/db2.c index e70f409..7a59e87 100644 --- a/rpmdb/db2.c +++ b/rpmdb/db2.c @@ -1,5 +1,5 @@ /** \ingroup db2 - * \file lib/db2.c + * \file rpmdb/db2.c */ static int _debug = 1; /* XXX if < 0 debugging, > 0 unusual error returns */ diff --git a/rpmdb/db3.c b/rpmdb/db3.c index 7f6eb53..3a0e585 100644 --- a/rpmdb/db3.c +++ b/rpmdb/db3.c @@ -1,5 +1,5 @@ /** \ingroup db3 - * \file lib/db3.c + * \file rpmdb/db3.c */ static int _debug = 1; /* XXX if < 0 debugging, > 0 unusual error returns */ @@ -184,6 +184,7 @@ static int db_init(dbiIndex dbi, const char *dbhome, rpmdb->db_errfile = stderr; eflags = (dbi->dbi_oeflags | dbi->dbi_eflags); + if (eflags & DB_JOINENV) eflags &= DB_JOINENV; if (dbfile) rpmMessage(RPMMESS_DEBUG, _("opening db environment %s/%s %s\n"), @@ -381,7 +382,7 @@ static inline int db3c_close(dbiIndex dbi, /*@only@*/ /*@null@*/ DBC * dbcursor) return rc; } -static inline int db3c_open(dbiIndex dbi, /*@out@*/ DBC ** dbcp) +static inline int db3c_open(dbiIndex dbi, /*@out@*/ DBC ** dbcp, int dbiflags) { DB * db = dbi->dbi_db; DB_TXN * txnid = NULL; @@ -390,7 +391,10 @@ static inline int db3c_open(dbiIndex dbi, /*@out@*/ DBC ** dbcp) if (db == NULL) return -2; #if defined(__USE_DB3) - if ((dbi->dbi_eflags & DB_INIT_CDB) && !(dbi->dbi_oflags & DB_RDONLY)) { + if ((dbiflags & DBI_WRITECURSOR) && + (dbi->dbi_eflags & DB_INIT_CDB) && !(dbi->dbi_oflags & DB_RDONLY)) + { +fprintf(stderr, "D: *** WRITECURSOR\n"); flags = DB_WRITECURSOR; } else flags = 0; @@ -409,7 +413,7 @@ static int db3cclose(dbiIndex dbi, /*@only@*/ /*@null@*/ DBC * dbcursor, int rc = 0; /* XXX per-iterator cursors */ - if (flags == 1) + if (flags & DBI_ITERATOR) return db3c_close(dbi, dbcursor); if (!dbi->dbi_use_cursors) @@ -431,8 +435,8 @@ static int db3copen(dbiIndex dbi, /*@out@*/ DBC ** dbcp, unsigned int flags) int rc = 0; /* XXX per-iterator cursors */ - if (flags == 1) - return db3c_open(dbi, dbcp); + if (flags & DBI_ITERATOR) + return db3c_open(dbi, dbcp, flags); if (!dbi->dbi_use_cursors) { if (dbcp) *dbcp = NULL; @@ -440,7 +444,7 @@ static int db3copen(dbiIndex dbi, /*@out@*/ DBC ** dbcp, unsigned int flags) } if ((dbcursor = dbi->dbi_rmw) == NULL) { - if ((rc = db3c_open(dbi, &dbcursor)) == 0) + if ((rc = db3c_open(dbi, &dbcursor, flags)) == 0) dbi->dbi_rmw = dbcursor; } @@ -719,26 +723,40 @@ static int db3open(/*@keep@*/ rpmdb rpmdb, int rpmtag, dbiIndex * dbip) * Avoid incompatible DB_CREATE/DB_RDONLY flags on DBENV->open. */ if (dbi->dbi_use_dbenv) { - if (access(dbhome, W_OK|F_OK) == -1) { + if (access(dbhome, W_OK) == -1) { /* dbhome is unwritable, don't attempt DB_CREATE on DB->open ... */ oflags &= ~DB_CREATE; /* ... but DBENV->open might still need DB_CREATE ... */ - if (!(dbi->dbi_eflags & DB_PRIVATE)) { + if (dbi->dbi_eflags & DB_PRIVATE) { + dbi->dbi_eflags &= ~DB_JOINENV; + } else { + dbi->dbi_eflags |= DB_JOINENV; dbi->dbi_oeflags &= ~DB_CREATE; dbi->dbi_oeflags &= ~DB_THREAD; - dbi->dbi_eflags = 0; - dbi->dbi_eflags |= DB_JOINENV; + /* ... but, unless DB_PRIVATE is used, skip DBENV. */ + dbi->dbi_use_dbenv = 0; } - /* ... DB_RDONLY seems OK ... */ + /* ... DB_RDONLY maps dphome perms across files ... */ oflags |= DB_RDONLY; - /* ... so DB_WRITECURSOR won't be needed ... */ + /* ... and DB_WRITECURSOR won't be needed ... */ dbi->dbi_oflags |= DB_RDONLY; - } else { - dbi->dbi_eflags &= ~DB_JOINENV; + } else { /* dbhome is writable, check for persistent dbenv. */ + const char * dbf = rpmGetPath(dbhome, "/__db.001", NULL); + + if (access(dbf, F_OK) == -1) { + /* ... non-existent (or unwritable) DBENV, will create ... */ + dbi->dbi_oeflags |= DB_CREATE; + dbi->dbi_eflags &= ~DB_JOINENV; + } else { + /* ... pre-existent (or bogus) DBENV, will join ... */ + dbi->dbi_oeflags &= ~DB_CREATE; + dbi->dbi_eflags |= DB_JOINENV; + } + dbf = _free(dbf); } } @@ -746,31 +764,25 @@ static int db3open(/*@keep@*/ rpmdb rpmdb, int rpmtag, dbiIndex * dbip) * Avoid incompatible DB_CREATE/DB_RDONLY flags on DB->open. */ if ((oflags & DB_CREATE) && (oflags & DB_RDONLY)) { - /* Otherwise dbhome is writable, and DB->open flags may conflict. */ - const char * dbfullpath; - const char * sdn = (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)); - char * t; - int nb; - - nb = strlen(dbhome) + 1 + strlen(sdn); - dbfullpath = t = alloca(nb + 1); - t = stpcpy( stpcpy( stpcpy( t, dbhome), "/"), sdn); - - if (access(dbfullpath, F_OK) == -1) { - /* If file does not exist, DB->open might create ... */ + /* dbhome is writable, and DB->open flags may conflict. */ + const char * dbfn = (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)); + const char * dbf = rpmGetPath(dbhome, "/", dbfn, NULL); + + if (access(dbf, F_OK) == -1) { + /* File does not exist, DB->open might create ... */ oflags &= ~DB_RDONLY; } else { - /* If file exists, DB->open need not create ... */ + /* File exists, DB->open need not create ... */ oflags &= ~DB_CREATE; } /* Only writers need DB_WRITECURSOR ... */ - if (!(oflags & DB_RDONLY) && access(dbfullpath, W_OK) == 0) { + if (!(oflags & DB_RDONLY) && access(dbf, W_OK) == 0) { dbi->dbi_oflags &= ~DB_RDONLY; } else { dbi->dbi_oflags |= DB_RDONLY; } - + dbf = _free(dbf); } dbi->dbi_dbinfo = NULL; @@ -784,6 +796,8 @@ static int db3open(/*@keep@*/ rpmdb rpmdb, int rpmtag, dbiIndex * dbip) if (rc == 0) { #if defined(__USE_DB3) + static int _lockdbfd = 0; + rc = db_create(&db, dbenv, dbi->dbi_cflags); rc = cvtdberr(dbi, "db_create", rc, _debug); if (rc == 0 && db != NULL) { @@ -900,8 +914,9 @@ static int db3open(/*@keep@*/ rpmdb rpmdb, int rpmtag, dbiIndex * dbip) _printit = (rc > 0 ? 0 : _debug); xx = cvtdberr(dbi, "db->open", rc, _printit); - if (rc == 0 && dbi->dbi_get_rmw_cursor) { + if (rc == 0 && dbi->dbi_use_dbenv && (dbi->dbi_eflags & DB_INIT_CDB) && dbi->dbi_get_rmw_cursor) { DBC * dbcursor = NULL; +fprintf(stderr, "D: *** rmw WRITECURSOR\n"); xx = db->cursor(db, txnid, &dbcursor, ((oflags & DB_RDONLY) ? 0 : DB_WRITECURSOR)); xx = cvtdberr(dbi, "db->cursor", xx, _debug); @@ -909,13 +924,31 @@ static int db3open(/*@keep@*/ rpmdb rpmdb, int rpmtag, dbiIndex * dbip) } else dbi->dbi_rmw = NULL; - if (rc == 0 && dbi->dbi_lockdbfd) { + /* + * Lock a file using fcntl(2). Traditionally this is Packages, + * the file used * to store metadata of installed header(s), + * as Packages is always opened, and should be opened first, + * for any rpmdb access. + * + * If no DBENV is used, then access is protected with a + * shared/exclusive locking scheme, as always. + * + * With a DBENV, the fcntl(2) lock is necessary only to keep + * the riff-raff from playing where they don't belong, as + * the DBENV should provide it's own locking scheme. So try to + * acquire a lock, but permit failures, as some other + * DBENV player may already have acquired the lock. + */ + if (rc == 0 && dbi->dbi_lockdbfd && + (!dbi->dbi_use_dbenv || _lockdbfd++ == 0)) + { int fdno = -1; if (!(db->fd(db, &fdno) == 0 && fdno >= 0)) { rc = 1; } else { struct flock l; + memset(&l, 0, sizeof(l)); l.l_whence = 0; l.l_start = 0; l.l_len = 0; @@ -923,13 +956,15 @@ static int db3open(/*@keep@*/ rpmdb rpmdb, int rpmtag, dbiIndex * dbip) ? F_WRLCK : F_RDLCK; l.l_pid = 0; - if (fcntl(fdno, F_SETLK, (void *) &l)) { - rpmError(RPMERR_FLOCK, + rc = fcntl(fdno, F_SETLK, (void *) &l); + if (rc) { + rpmError( + (!dbi->dbi_use_dbenv ? RPMERR_FLOCK : RPMWARN_FLOCK), _("cannot get %s lock on %s/%s\n"), ((dbi->dbi_mode & (O_RDWR|O_WRONLY)) ? _("exclusive") : _("shared")), dbhome, (dbfile ? dbfile : "")); - rc = 1; + rc = (!dbi->dbi_use_dbenv ? 1 : 0); } else if (dbfile) { rpmMessage(RPMMESS_DEBUG, _("locked db index %s/%s\n"), diff --git a/rpmdb/dbconfig.c b/rpmdb/dbconfig.c index 5042324..061956c 100644 --- a/rpmdb/dbconfig.c +++ b/rpmdb/dbconfig.c @@ -1,5 +1,5 @@ /** \ingroup rpmdb - * \file lib/dbconfig.c + * \file rpmdb/dbconfig.c */ #include "system.h" diff --git a/rpmdb/falloc.c b/rpmdb/falloc.c index c882079..f1d0af2 100644 --- a/rpmdb/falloc.c +++ b/rpmdb/falloc.c @@ -1,5 +1,5 @@ /** \ingroup rpmio db1 - * \file lib/falloc.c + * \file rpmdb/falloc.c * * The entire file space is thus divided into blocks with a "struct fablock" * at the header of each. The size fields doubly link this block list. diff --git a/rpmdb/falloc.h b/rpmdb/falloc.h index 8468681..621f98c 100644 --- a/rpmdb/falloc.h +++ b/rpmdb/falloc.h @@ -2,7 +2,7 @@ #define H_FALLOC /** \ingroup db1 - * \file lib/falloc.h + * \file rpmdb/falloc.h * File space allocation routines. * * Best fit allocation is used, free blocks are compacted. Minimal diff --git a/rpmdb/rpmdb.c b/rpmdb/rpmdb.c index c94ae5d..b3a4ff0 100644 --- a/rpmdb/rpmdb.c +++ b/rpmdb/rpmdb.c @@ -1,5 +1,5 @@ /** \ingroup rpmdb dbi - * \file lib/rpmdb.c + * \file rpmdb/rpmdb.c */ #include "system.h" @@ -70,11 +70,11 @@ static void dbiTagsInit(void) /*@-nullpass@*/ dbiTagStr = rpmExpand("%{_dbi_tags}", NULL); - /*@=nullpass@*/ if (!(dbiTagStr && *dbiTagStr && *dbiTagStr != '%')) { dbiTagStr = _free(dbiTagStr); dbiTagStr = xstrdup(_dbiTagStr_default); } + /*@=nullpass@*/ if (dbiTagsMax || dbiTags) { dbiTags = _free(dbiTags); @@ -155,7 +155,7 @@ INLINE int XdbiCopen(dbiIndex dbi, /*@out@*/ DBC ** dbcp, unsigned int flags, const char * f, unsigned int l) { if (_debug < 0 || dbi->dbi_debug) -fprintf(stderr, "+++ RMW %s (%s:%u)\n", tagName(dbi->dbi_rpmtag), f, l); +fprintf(stderr, "+++ RMW %s %s (%s:%u)\n", tagName(dbi->dbi_rpmtag), ((flags & DBI_WRITECURSOR) ? "WRITECURSOR" : ""), f, l); return (*dbi->dbi_vec->copen) (dbi, dbcp, flags); } @@ -167,6 +167,8 @@ fprintf(stderr, "--- RMW %s (%s:%u)\n", tagName(dbi->dbi_rpmtag), f, l); return (*dbi->dbi_vec->cclose) (dbi, dbcursor, flags); } +#define printable(_c) (((_c) >= ' ') && ((_c) <= '\177')) + INLINE int dbiDel(dbiIndex dbi, DBC * dbcursor, const void * keyp, size_t keylen, unsigned int flags) { int NULkey; @@ -198,22 +200,33 @@ INLINE int dbiGet(dbiIndex dbi, DBC * dbcursor, void ** keypp, size_t * keylenp, if (NULkey && keylenp) (*keylenp)--; /*@=nullderef =nullpass@*/ +/*@-nullderef -nullpass@*/ if (_debug < 0 || dbi->dbi_debug) { -char keyval[32]; -int dataval = 0xdeadbeef; -if (dbi->dbi_rpmtag == RPMDBI_PACKAGES && keypp && *keypp && keylenp && *keylenp <= sizeof(int)) { + int dataval = 0xdeadbeef; + const char * kvp; + char keyval[64]; + keyval[0] = '\0'; + if (keypp && *keypp && keylenp) { + if (*keylenp <= sizeof(int) && + !( printable( ((unsigned char *)(*keypp))[0] ) && printable( ((unsigned char *)(*keypp))[1] ) && + printable( ((unsigned char *)(*keypp))[2] ) && printable( ((unsigned char *)(*keypp))[3] ))) { int keyint = 0; memcpy(&keyint, *keypp, sizeof(keyint)); sprintf(keyval, "#%d", keyint); -} else keyval[0] = '\0'; -if (rc == 0 && datapp && *datapp && datalenp && *datalenp >= sizeof(dataval)) { + kvp = keyval; + } else { + kvp = *keypp; + } + } else + kvp = keyval; + if (rc == 0 && datapp && *datapp && datalenp && *datalenp >= sizeof(dataval)) { memcpy(&dataval, *datapp, sizeof(dataval)); - dataval = ntohl(dataval); -} -fprintf(stderr, " Get %s key (%p,%ld) data (%p,%ld) \"%s\" %x rc %d\n", + } + fprintf(stderr, " Get %s key (%p,%ld) data (%p,%ld) \"%s\" %x rc %d\n", tagName(dbi->dbi_rpmtag), *keypp, (long)*keylenp, *datapp, (long)*datalenp, - (dbi->dbi_rpmtag != RPMDBI_PACKAGES ? (char *)*keypp : keyval), (unsigned)dataval, rc); + kvp, (unsigned)dataval, rc); } +/*@=nullderef =nullpass@*/ return rc; } @@ -229,18 +242,38 @@ INLINE int dbiPut(dbiIndex dbi, DBC * dbcursor, const void * keyp, size_t keylen rc = (*dbi->dbi_vec->cput) (dbi, dbcursor, keyp, keylen, datap, datalen, flags); if (NULkey) keylen--; +/*@-nullderef -nullpass@*/ if (_debug < 0 || dbi->dbi_debug) { -int dataval = 0xdeadbeef; -if (datap) memcpy(&dataval, datap, sizeof(dataval)); -fprintf(stderr, " Put %s key (%p,%ld) data (%p,%ld) \"%s\" %x rc %d\n", tagName(dbi->dbi_rpmtag), keyp, (long)keylen, (datap ? datap : NULL), (long)datalen, (dbi->dbi_rpmtag != RPMDBI_PACKAGES ? (char *)keyp : ""), (unsigned)dataval, rc); + int dataval = 0xdeadbeef; + const char * kvp; + char keyval[64]; + keyval[0] = '\0'; + if (keyp) { + if (keylen == sizeof(int) && + !( printable( ((unsigned char *)keyp)[0] ) && printable( ((unsigned char *)keyp)[1] ) && + printable( ((unsigned char *)keyp)[2] ) && printable( ((unsigned char *)keyp)[3] ))){ + int keyint = 0; + memcpy(&keyint, keyp, sizeof(keyint)); + sprintf(keyval, "#%d", keyint); + kvp = keyval; + } else { + kvp = keyp; + } + } else + kvp = keyval; + if (rc == 0 && datap && datalen >= sizeof(dataval)) { + memcpy(&dataval, datap, sizeof(dataval)); + } + fprintf(stderr, " Put %s key (%p,%ld) data (%p,%ld) \"%s\" %x rc %d\n", tagName(dbi->dbi_rpmtag), keyp, (long)keylen, (datap ? datap : NULL), (long)datalen, kvp, (unsigned)dataval, rc); } +/*@=nullderef =nullpass@*/ return rc; } INLINE int dbiClose(dbiIndex dbi, unsigned int flags) { if (_debug < 0 || dbi->dbi_debug) -fprintf(stderr, " %s Close\n", tagName(dbi->dbi_rpmtag)); +fprintf(stderr, " Close %s\n", tagName(dbi->dbi_rpmtag)); return (*dbi->dbi_vec->close) (dbi, flags); } @@ -1051,7 +1084,9 @@ int rpmdbCountPackages(rpmdb rpmdb, const char * name) } if (rc == 0) /* success */ + /*@-nullpass@*/ rc = dbiIndexSetCount(matches); + /*@=nullpass@*/ else if (rc > 0) /* error */ rpmError(RPMERR_DBCORRUPT, _("error(%d) counting packages\n"), rc); else /* not found */ @@ -1068,8 +1103,10 @@ int rpmdbCountPackages(rpmdb rpmdb, const char * name) /* 1 no matches */ /* 2 error */ static int dbiFindMatches(dbiIndex dbi, DBC * dbcursor, - const char * name, const char * version, const char * release, - /*@out@*/ dbiIndexSet * matches) + const char * name, + /*@null@*/ const char * version, + /*@null@*/ const char * release, + /*@out@*/ dbiIndexSet * matches) { int gotMatches; int rc; @@ -1082,7 +1119,7 @@ static int dbiFindMatches(dbiIndex dbi, DBC * dbcursor, goto exit; } - if (!version && !release) { + if (version == NULL && release == NULL) { rc = 0; goto exit; } @@ -1115,7 +1152,9 @@ static int dbiFindMatches(dbiIndex dbi, DBC * dbcursor, goto exit; } + /*@-nullpass@*/ (void) headerNVR(h, NULL, &pkgVersion, &pkgRelease); + /*@=nullpass@*/ goodRelease = goodVersion = 1; @@ -1177,6 +1216,7 @@ static int dbiFindByLabel(dbiIndex dbi, DBC * dbcursor, chptr = (localarg + strlen(localarg)) - 1; while (chptr > localarg && *chptr != '-') chptr--; + /*@-nullstate@*/ /* FIX: *matches may be NULL. */ if (chptr == localarg) return 1; *chptr = '\0'; @@ -1195,6 +1235,7 @@ static int dbiFindByLabel(dbiIndex dbi, DBC * dbcursor, *chptr = '\0'; return dbiFindMatches(dbi, dbcursor, localarg, chptr + 1, release, matches); + /*@=nullstate@*/ } /** @@ -1239,6 +1280,7 @@ struct _rpmdbMatchIterator { int mi_setx; /*@null@*/ Header mi_h; int mi_sorted; + int mi_cflags; int mi_modified; unsigned int mi_prevoffset; unsigned int mi_offset; @@ -1259,12 +1301,8 @@ rpmdbMatchIterator rpmdbFreeIterator(rpmdbMatchIterator mi) dbi = dbiOpen(mi->mi_rpmdb, RPMDBI_PACKAGES, 0); if (mi->mi_h) { - if (dbi && mi->mi_modified && mi->mi_prevoffset) { - DBC * dbcursor = NULL; - xx = dbiCopen(dbi, &dbcursor, 0); - (void) dbiUpdateRecord(dbi, dbcursor, mi->mi_prevoffset, mi->mi_h); - xx = dbiCclose(dbi, dbcursor, 0); - dbcursor = NULL; + if (dbi && mi->mi_dbc && mi->mi_modified && mi->mi_prevoffset) { + xx = dbiUpdateRecord(dbi, mi->mi_dbc, mi->mi_prevoffset, mi->mi_h); } headerFree(mi->mi_h); mi->mi_h = NULL; @@ -1278,7 +1316,7 @@ rpmdbMatchIterator rpmdbFreeIterator(rpmdbMatchIterator mi) mi->mi_release = _free(mi->mi_release); mi->mi_version = _free(mi->mi_version); if (dbi && mi->mi_dbc) - xx = dbiCclose(dbi, mi->mi_dbc, 1); + xx = dbiCclose(dbi, mi->mi_dbc, DBI_ITERATOR); mi->mi_dbc = NULL; if (mi->mi_set) dbiFreeIndexSet(mi->mi_set); @@ -1326,6 +1364,18 @@ void rpmdbSetIteratorVersion(rpmdbMatchIterator mi, const char * version) { mi->mi_version = (version ? xstrdup(version) : NULL); } +int rpmdbSetIteratorRewrite(rpmdbMatchIterator mi, int rewrite) { + int rc; + if (mi == NULL) + return 0; + rc = (mi->mi_cflags & DBI_WRITECURSOR) ? 1 : 0; + if (rewrite) + mi->mi_cflags |= DBI_WRITECURSOR; + else + mi->mi_cflags &= ~DBI_WRITECURSOR; + return rc; +} + int rpmdbSetIteratorModified(rpmdbMatchIterator mi, int modified) { int rc; if (mi == NULL) @@ -1351,10 +1401,15 @@ Header XrpmdbNextIterator(rpmdbMatchIterator mi, const char * f, unsigned l) dbi = dbiOpen(mi->mi_rpmdb, RPMDBI_PACKAGES, 0); if (dbi == NULL) return NULL; - /* XXX cursors need to be per-iterator, not per-dbi. Get a cursor now. */ - if (mi->mi_dbc == NULL) { - xx = XdbiCopen(dbi, &mi->mi_dbc, 1, f, l); - } + + /* + * Cursors are per-iterator, not per-dbi, so get a cursor for the + * iterator on 1st call. If the iteration is to rewrite headers, and the + * CDB model is used for the database, then the cursor needs to + * marked with DB_WRITECURSOR as well. + */ + if (mi->mi_dbc == NULL) + xx = XdbiCopen(dbi, &mi->mi_dbc, (mi->mi_cflags | DBI_ITERATOR), f, l); dbi->dbi_lastoffset = mi->mi_prevoffset; top: @@ -1410,7 +1465,7 @@ if (dbi->dbi_api == 1 && dbi->dbi_rpmtag == RPMDBI_PACKAGES && rc == EFAULT) { /* Free current header */ if (mi->mi_h) { if (mi->mi_modified && mi->mi_prevoffset) - (void) dbiUpdateRecord(dbi, mi->mi_dbc, mi->mi_prevoffset, mi->mi_h); + (void)dbiUpdateRecord(dbi, mi->mi_dbc, mi->mi_prevoffset, mi->mi_h); headerFree(mi->mi_h); mi->mi_h = NULL; } @@ -1420,15 +1475,19 @@ if (dbi->dbi_api == 1 && dbi->dbi_rpmtag == RPMDBI_PACKAGES && rc == EFAULT) { if (dbi->dbi_api <= 1) uh = _free(uh); if (mi->mi_h && mi->mi_release) { - const char *release; + const char * release; + /*@-nullpass@*/ (void) headerNVR(mi->mi_h, NULL, NULL, &release); + /*@=nullpass@*/ if (mi->mi_release && strcmp(mi->mi_release, release)) goto top; } if (mi->mi_h && mi->mi_version) { - const char *version; + const char * version; + /*@-nullpass@*/ (void) headerNVR(mi->mi_h, NULL, &version, NULL); + /*@=nullpass@*/ if (mi->mi_version && strcmp(mi->mi_version, version)) goto top; } @@ -1440,7 +1499,9 @@ exit: #ifdef NOTNOW if (mi->mi_h) { const char *n, *v, *r; + /*@-nullpass@*/ headerNVR(mi->mi_h, &n, &v, &r); + /*@=nullpass@*/ rpmMessage(RPMMESS_DEBUG, "%s-%s-%s at 0x%x, h %p\n", n, v, r, mi->mi_offset, mi->mi_h); } @@ -1608,6 +1669,7 @@ fprintf(stderr, "*** RMW %s %p\n", tagName(rpmtag), dbi->dbi_rmw); mi->mi_setx = 0; mi->mi_h = NULL; mi->mi_sorted = 0; + mi->mi_cflags = 0; mi->mi_modified = 0; mi->mi_prevoffset = 0; mi->mi_offset = 0; @@ -1616,7 +1678,9 @@ fprintf(stderr, "*** RMW %s %p\n", tagName(rpmtag), dbi->dbi_rmw); mi->mi_dbnum = 0; mi->mi_version = NULL; mi->mi_release = NULL; + /*@-nullret@*/ return mi; + /*@=nullret@*/ } /** @@ -1718,9 +1782,9 @@ int rpmdbRemove(rpmdb rpmdb, int rid, unsigned int hdrNum) case RPMDBI_PACKAGES: dbi = dbiOpen(rpmdb, rpmtag, 0); if (dbi != NULL) { - xx = dbiCopen(dbi, &dbcursor, 0); + xx = dbiCopen(dbi, &dbcursor, DBI_WRITECURSOR); xx = dbiDel(dbi, dbcursor, &hdrNum, sizeof(hdrNum), 0); - xx = dbiCclose(dbi, dbcursor, 0); + xx = dbiCclose(dbi, dbcursor, DBI_WRITECURSOR); dbcursor = NULL; if (!dbi->dbi_no_dbsync) xx = dbiSync(dbi, 0); @@ -1734,7 +1798,7 @@ int rpmdbRemove(rpmdb rpmdb, int rid, unsigned int hdrNum) dbi = dbiOpen(rpmdb, rpmtag, 0); if (dbi != NULL) { - xx = dbiCopen(dbi, &dbcursor, 0); + xx = dbiCopen(dbi, &dbcursor, DBI_WRITECURSOR); if (rpmtype == RPM_STRING_TYPE) { @@ -1796,7 +1860,7 @@ int rpmdbRemove(rpmdb rpmdb, int rid, unsigned int hdrNum) xx = removeIndexEntry(dbi, dbcursor, valp, vallen, rec); } - xx = dbiCclose(dbi, dbcursor, 0); + xx = dbiCclose(dbi, dbcursor, DBI_WRITECURSOR); dbcursor = NULL; if (!dbi->dbi_no_dbsync) @@ -1907,7 +1971,7 @@ int rpmdbAdd(rpmdb rpmdb, int iid, Header h) datap = h; datalen = headerSizeof(h, HEADER_MAGIC_NO); - xx = dbiCopen(dbi, &dbcursor, 0); + xx = dbiCopen(dbi, &dbcursor, DBI_WRITECURSOR); /* Retrieve join key for next header instance. */ @@ -1929,7 +1993,7 @@ int rpmdbAdd(rpmdb rpmdb, int iid, Header h) rc = dbiPut(dbi, dbcursor, keyp, keylen, datap, datalen, 0); xx = dbiSync(dbi, 0); - xx = dbiCclose(dbi, dbcursor, 0); + xx = dbiCclose(dbi, dbcursor, DBI_WRITECURSOR); dbcursor = NULL; } @@ -1972,9 +2036,9 @@ int rpmdbAdd(rpmdb rpmdb, int iid, Header h) case RPMDBI_PACKAGES: dbi = dbiOpen(rpmdb, rpmtag, 0); if (dbi != NULL) { - xx = dbiCopen(dbi, &dbcursor, 0); + xx = dbiCopen(dbi, &dbcursor, DBI_WRITECURSOR); xx = dbiUpdateRecord(dbi, dbcursor, hdrNum, h); - xx = dbiCclose(dbi, dbcursor, 0); + xx = dbiCclose(dbi, dbcursor, DBI_WRITECURSOR); dbcursor = NULL; if (!dbi->dbi_no_dbsync) xx = dbiSync(dbi, 0); @@ -2013,7 +2077,7 @@ int rpmdbAdd(rpmdb rpmdb, int iid, Header h) dbi = dbiOpen(rpmdb, rpmtag, 0); if (dbi != NULL) { - xx = dbiCopen(dbi, &dbcursor, 0); + xx = dbiCopen(dbi, &dbcursor, DBI_WRITECURSOR); if (rpmtype == RPM_STRING_TYPE) { rpmMessage(RPMMESS_DEBUG, _("adding \"%s\" to %s index.\n"), (const char *)rpmvals, tagName(dbi->dbi_rpmtag)); @@ -2095,7 +2159,7 @@ int rpmdbAdd(rpmdb rpmdb, int iid, Header h) rc += addIndexEntry(dbi, dbcursor, valp, vallen, rec); } - xx = dbiCclose(dbi, dbcursor, 0); + xx = dbiCclose(dbi, dbcursor, DBI_WRITECURSOR); dbcursor = NULL; if (!dbi->dbi_no_dbsync) @@ -2434,7 +2498,9 @@ int rpmdbRebuild(const char * rootdir) _dbapi = rpmExpandNumeric("%{_dbapi}"); _dbapi_rebuild = rpmExpandNumeric("%{_dbapi_rebuild}"); + /*@-nullpass@*/ tfn = rpmGetPath("%{_dbpath}", NULL); + /*@=nullpass@*/ if (!(tfn && tfn[0] != '%')) { rpmMessage(RPMMESS_DEBUG, _("no dbpath has been set")); rc = 1; @@ -2445,7 +2511,9 @@ int rpmdbRebuild(const char * rootdir) dbpath += strlen(rootdir); tfn = _free(tfn); + /*@-nullpass@*/ tfn = rpmGetPath("%{_dbpath_rebuild}", NULL); + /*@=nullpass@*/ if (!(tfn && tfn[0] != '%' && strcmp(tfn, dbpath))) { char pidbuf[20]; char *t; diff --git a/rpmdb/rpmdb.h b/rpmdb/rpmdb.h index b3889d6..c7130dd 100644 --- a/rpmdb/rpmdb.h +++ b/rpmdb/rpmdb.h @@ -2,7 +2,7 @@ #define H_RPMDB /** \ingroup rpmdb dbi db1 db3 - * \file lib/rpmdb.h + * \file rpmdb/rpmdb.h * Access RPM indices using Berkeley DB interface(s). */ @@ -319,13 +319,16 @@ void db3Free( /*@only@*/ /*@null@*/ dbiIndex dbi); /** \ingroup dbi * @param dbi index database handle - * @param flags (unused) + * @param dbiflags DBI_WRITECURSOR or DBI_ITERATOR */ -int dbiCopen(dbiIndex dbi, /*@out@*/ DBC ** dbcp, unsigned int flags); -int XdbiCopen(dbiIndex dbi, /*@out@*/ DBC ** dbcp, unsigned int flags, const char *f, unsigned int l); +int dbiCopen(dbiIndex dbi, /*@out@*/ DBC ** dbcp, unsigned int dbiflags); +int XdbiCopen(dbiIndex dbi, /*@out@*/ DBC ** dbcp, unsigned int dbiflags, const char *f, unsigned int l); #define dbiCopen(_a,_b,_c) \ XdbiCopen(_a, _b, _c, __FILE__, __LINE__) +#define DBI_WRITECURSOR (1 << 0) +#define DBI_ITERATOR (1 << 1) + /** \ingroup dbi * @param dbi index database handle * @param flags (unused) diff --git a/rpmio/rpmerr.h b/rpmio/rpmerr.h index acbb311..a19934e 100644 --- a/rpmio/rpmerr.h +++ b/rpmio/rpmerr.h @@ -102,7 +102,8 @@ typedef enum rpmerrCode_e { RPMERR_SIGVFY = _nm(202), /*!< */ RPMWARN_UNLINK = _wm(512u+16), /*!< unlink(2) failed */ - RPMWARN_RMDIR = _wm(512u+17) /*!< rmdir(2) failed */ + RPMWARN_RMDIR = _wm(512u+17), /*!< rmdir(2) failed */ + RPMWARN_FLOCK = _wm(512u+27) /*!< locking the database failed */ } rpmerrCode; /** diff --git a/rpmio/rpmmacro.h b/rpmio/rpmmacro.h index 252aea0..c14dfa7 100644 --- a/rpmio/rpmmacro.h +++ b/rpmio/rpmmacro.h @@ -157,7 +157,7 @@ char * rpmExpand (/*@null@*/ const char * arg, ...) * @param path macro(s) to expand (NULL terminates list) * @return canonicalized path (malloc'ed) */ -const char *rpmGetPath (/*@null@*/ const char * path, ...) +const char * rpmGetPath (/*@null@*/ const char * path, ...) /*@*/; /** @@ -170,7 +170,7 @@ const char *rpmGetPath (/*@null@*/ const char * path, ...) * @param file file URL (often a file, or NULL) * @return expanded, merged, canonicalized path (malloc'ed) */ -const char *rpmGenPath (/*@null@*/ const char * root, +const char * rpmGenPath (/*@null@*/ const char * root, /*@null@*/ const char * mdir, /*@null@*/ const char * file) /*@*/; -- 2.7.4