- 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
- 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.
./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 \
./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 \
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:
}
}
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",
#!/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)\
distdir install:\
\
db3_install: all install_setip \\' > Makefile
-
-make -s listobjs > db3lobjs
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
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
} 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;
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;
+++ /dev/null
-/**
- * \file lib/fprint.c
- */
-
-#include "system.h"
-#include <rpmlib.h>
-#include <rpmmacro.h> /* 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);
-}
+++ /dev/null
-#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
+++ /dev/null
-/**
- * \file lib/hash.c
- * Hash table implemenation
- */
-
-#include "system.h"
-#include <rpmlib.h>
-#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;
-}
+++ /dev/null
-#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
mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES, NULL, 0);
(void) rpmdbAppendIterator(mi, offsets, num);
+ (void) rpmdbSetIteratorRewrite(mi, 1);
sfi = replaced;
while ((h = rpmdbNextIterator(mi)) != NULL) {
while ((h = rpmdbNextIterator(mi)) != NULL) {
int rc;
+ /*@-nullpass@*/
if ((rc = showPackage(qva, rpmdbGetIteratorRpmDB(mi), h)) != 0)
ec = rc;
+ /*@=nullpass@*/
}
mi = rpmdbFreeIterator(mi);
return ec;
* @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.
/*@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
#include "psm.h"
#include "fprint.h"
-#include "hash.h"
+#include "rpmhash.h"
#include "md5.h"
#include "misc.h"
#include "rpmdb.h"
RPMCANONOS = @RPMCANONOS@
RPMCANONVENDOR = @RPMCANONVENDOR@
RPMCONFIGDIR = @RPMCONFIGDIR@
+RPMGID = @RPMGID@
+RPMGROUP = @RPMGROUP@
+RPMUID = @RPMUID@
+RPMUSER = @RPMUSER@
SYSCONFIGDIR = @SYSCONFIGDIR@
U = @U@
UNZIPBIN = @UNZIPBIN@
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
rpmdb/db3.c
rpmdb/dbconfig.c
rpmdb/falloc.c
+rpmdb/fprint.c
+rpmdb/rpmhash.c
rpmdb/rpmdb.c
rpmio/base64.c
rpmio/digest.c
%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
%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
%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
pkgincdir = $(pkgincludedir)
pkginc_HEADERS = rpmdb.h
-noinst_HEADERS = falloc.h
+noinst_HEADERS = falloc.h fprint.h rpmhash.h
mylibpaths = \
-L$(top_builddir)/lib/.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
/** \ingroup db1
- * \file lib/db1.c
+ * \file rpmdb/db1.c
*/
#include "system.h"
/** \ingroup db2
- * \file lib/db2.c
+ * \file rpmdb/db2.c
*/
static int _debug = 1; /* XXX if < 0 debugging, > 0 unusual error returns */
/** \ingroup db3
- * \file lib/db3.c
+ * \file rpmdb/db3.c
*/
static int _debug = 1; /* XXX if < 0 debugging, > 0 unusual error returns */
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"),
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;
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;
int rc = 0;
/* XXX per-iterator cursors */
- if (flags == 1)
+ if (flags & DBI_ITERATOR)
return db3c_close(dbi, dbcursor);
if (!dbi->dbi_use_cursors)
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;
}
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;
}
* 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);
}
}
* 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;
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) {
_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);
} 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;
? 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"),
/** \ingroup rpmdb
- * \file lib/dbconfig.c
+ * \file rpmdb/dbconfig.c
*/
#include "system.h"
/** \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.
#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
/** \ingroup rpmdb dbi
- * \file lib/rpmdb.c
+ * \file rpmdb/rpmdb.c
*/
#include "system.h"
/*@-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);
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);
}
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;
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;
}
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);
}
}
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 */
/* 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;
goto exit;
}
- if (!version && !release) {
+ if (version == NULL && release == NULL) {
rc = 0;
goto exit;
}
goto exit;
}
+ /*@-nullpass@*/
(void) headerNVR(h, NULL, &pkgVersion, &pkgRelease);
+ /*@=nullpass@*/
goodRelease = goodVersion = 1;
chptr = (localarg + strlen(localarg)) - 1;
while (chptr > localarg && *chptr != '-') chptr--;
+ /*@-nullstate@*/ /* FIX: *matches may be NULL. */
if (chptr == localarg) return 1;
*chptr = '\0';
*chptr = '\0';
return dbiFindMatches(dbi, dbcursor, localarg, chptr + 1, release, matches);
+ /*@=nullstate@*/
}
/**
int mi_setx;
/*@null@*/ Header mi_h;
int mi_sorted;
+ int mi_cflags;
int mi_modified;
unsigned int mi_prevoffset;
unsigned int mi_offset;
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;
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);
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)
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:
/* 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;
}
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;
}
#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);
}
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;
mi->mi_dbnum = 0;
mi->mi_version = NULL;
mi->mi_release = NULL;
+ /*@-nullret@*/
return mi;
+ /*@=nullret@*/
}
/**
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);
dbi = dbiOpen(rpmdb, rpmtag, 0);
if (dbi != NULL) {
- xx = dbiCopen(dbi, &dbcursor, 0);
+ xx = dbiCopen(dbi, &dbcursor, DBI_WRITECURSOR);
if (rpmtype == RPM_STRING_TYPE) {
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)
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. */
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;
}
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);
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));
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)
_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;
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;
#define H_RPMDB
/** \ingroup rpmdb dbi db1 db3
- * \file lib/rpmdb.h
+ * \file rpmdb/rpmdb.h
* Access RPM indices using Berkeley DB interface(s).
*/
/** \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)
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;
/**
* @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, ...)
/*@*/;
/**
* @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)
/*@*/;