summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/formats.c8
-rw-r--r--lib/fprint.c202
-rw-r--r--lib/fprint.h41
-rw-r--r--lib/install.c6
-rw-r--r--lib/rpmdb.c88
-rw-r--r--lib/transaction.c82
6 files changed, 247 insertions, 180 deletions
diff --git a/lib/formats.c b/lib/formats.c
index 607ae6e71..7179e97e4 100644
--- a/lib/formats.c
+++ b/lib/formats.c
@@ -200,13 +200,13 @@ static int fssizesTag(Header h, int_32 * type, void ** data, int_32 * count,
uint_32 * usages;
int numFiles;
- if (!headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, (void **) &filenames, NULL))
- filenames = NULL;
-
if (!headerGetEntry(h, RPMTAG_FILESIZES, NULL, (void **) &filesizes,
&numFiles)) {
filesizes = NULL;
numFiles = 0;
+ filenames = NULL;
+ } else {
+ buildFileList(h, (char ***) &filenames, &numFiles);
}
if (rpmGetFilesystemList(NULL, count)) {
@@ -228,6 +228,8 @@ static int fssizesTag(Header h, int_32 * type, void ** data, int_32 * count,
*data = usages;
+ if (filenames) free(filenames);
+
return 0;
}
diff --git a/lib/fprint.c b/lib/fprint.c
index 73afd6ea0..cdac7eb4a 100644
--- a/lib/fprint.c
+++ b/lib/fprint.c
@@ -3,26 +3,30 @@
#include <rpmlib.h>
#include "fprint.h"
-struct lookupCache {
- char * match;
- int pathsStripped;
- int matchLength;
- int stripLength;
- dev_t dev;
- ino_t ino;
-};
-
-static int strCompare(const void * a, const void * b)
-{
- const char * const * one = a;
- const char * const * two = b;
+fingerPrintCache fpCacheCreate(int sizeHint) {
+ fingerPrintCache fpc;
- return strcmp(*one, *two);
+ fpc = malloc(sizeof(*fpc));
+ fpc->ht = htCreate(sizeHint * 2, sizeof(char *), hashFunctionString,
+ hashEqualityString);
+ return fpc;
}
-static fingerPrint doLookup(const char * fullName, int scareMemory,
- struct lookupCache * cache)
-{
+void fpCacheFree(fingerPrintCache cache) {
+}
+
+static const struct fprintCacheEntry_s * cacheContainsDirectory(
+ fingerPrintCache cache,
+ const char * dirName) {
+ const void ** data;
+ int count;
+
+ if (htGetEntry(cache->ht, dirName, &data, &count, NULL)) return NULL;
+ return data[0];
+}
+
+static fingerPrint doLookup(fingerPrintCache cache, const char * dirName,
+ char * baseName, int scareMemory) {
char dir[PATH_MAX];
const char * chptr1;
char * end, * bn;
@@ -30,88 +34,69 @@ static fingerPrint doLookup(const char * fullName, int scareMemory,
struct stat sb;
char * buf;
int stripCount;
+ const struct fprintCacheEntry_s * cacheHit;
+ struct fprintCacheEntry_s * newEntry;
- /* assert(*fullName == '/' || !scareMemory); */
-
- /* FIXME: a better cache might speed things up? */
-
- if (cache && cache->pathsStripped &&
- !strncmp(fullName, cache->match, cache->matchLength)) {
- chptr1 = fullName + cache->matchLength;
- if (*chptr1 == '/') {
- chptr1++;
- stripCount = cache->pathsStripped - 1;
- while (*chptr1) {
- if (*chptr1 == '/') stripCount--;
- chptr1++;
- }
-
- chptr1 = fullName + cache->matchLength + 1;
- if (stripCount == 0 && !(cache->stripLength > 0 &&
- strncmp(cache->match+cache->matchLength+1, chptr1, cache->stripLength))) {
- if (scareMemory)
- fp.basename = chptr1;
- else
- fp.basename = xstrdup(chptr1);
- fp.ino = cache->ino;
- fp.dev = cache->dev;
- return fp;
- }
- }
- }
+ /* assert(*dirName == '/' || !scareMemory); */
- if (*fullName != '/') {
+ if (*dirName != '/') {
scareMemory = 0;
/* Using realpath on the arg isn't correct if the arg is a symlink,
- * especially if the symlink is a dangling link. What we should
- * instead do is use realpath() on `.' and then append arg to
- * it.
+ * especially if the symlink is a dangling link. What we
+ * do instaed 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) {
- char *s = alloca(strlen(dir) + strlen(fullName) + 2);
- sprintf(s, "%s/%s", dir, fullName);
- fullName = chptr1 = s;
+ char *s = alloca(strlen(dir) + strlen(dirName) + 2);
+ sprintf(s, "%s/%s", dir, dirName);
+ dirName = chptr1 = s;
}
}
/* FIXME: perhaps we should collapse //, /./, and /../ stuff if
!scareMemory?? */
- buf = alloca(strlen(fullName) + 1);
- strcpy(buf, fullName);
+ buf = alloca(strlen(dirName) + 1);
+ strcpy(buf, dirName);
end = bn = strrchr(buf, '/');
stripCount = 0;
+ fp.entry = NULL;
while (*buf) {
*end = '\0';
stripCount++;
/* as we're stating paths here, we want to follow symlinks */
- if (!stat(*buf ? buf : "/", &sb)) {
- chptr1 = fullName + (end - buf) + 1;
+
+ if ((cacheHit = cacheContainsDirectory(cache, *buf ? buf : "/"))) {
+ fp.entry = cacheHit;
+ } else if (!stat(*buf ? buf : "/", &sb)) {
+ newEntry = malloc(sizeof(*fp.entry));
+ newEntry->ino = sb.st_ino;
+ newEntry->dev = sb.st_dev;
+ newEntry->isFake = 0;
+ newEntry->dirName = strdup(*buf ? buf : "/");
+ fp.entry = newEntry;
+
+ /* XXX FIXME: memory leak */
+ htAddEntry(cache->ht, strdup(*buf ? buf : "/"), fp.entry);
+ }
+
+ if (fp.entry) {
+ chptr1 = dirName + (end - buf) + 1;
if (scareMemory)
- fp.basename = chptr1;
+ fp.subdir = chptr1;
else
- fp.basename = xstrdup(chptr1); /* XXX memory leak */
- fp.ino = sb.st_ino;
- fp.dev = sb.st_dev;
-
- if (cache) {
- strcpy(cache->match, fullName);
- cache->match[strlen(fullName)+1] = '\0';
- cache->matchLength = (end-buf);
- cache->match[cache->matchLength] = '\0';
- cache->stripLength = (bn - (end+1));
- cache->match[bn-buf] = '\0';
- cache->pathsStripped = stripCount;
- cache->dev = sb.st_dev;
- cache->ino = sb.st_ino;
- }
-
+ fp.subdir = xstrdup(chptr1); /* XXX memory leak, but how
+ do we know we can free it?
+ Using the (new) cache would
+ work if hash tables allowed
+ traversal. */
+ fp.basename = baseName;
return fp;
}
@@ -119,13 +104,18 @@ static fingerPrint doLookup(const char * fullName, int scareMemory,
while ((end > buf) && *end != '/') end--;
}
- /* this can't happen, or stat('/') just failed! */
- fp.basename = 0;
- fp.ino = fp.dev = 0;
+ /* This can't happen, or stat('/') just failed! */
+ abort();
return fp;
}
+fingerPrint fpLookup(fingerPrintCache cache, const char * fullName,
+ int scareMemory) {
+ /* XXX FIXME */
+ abort();
+}
+
unsigned int fpHashFunction(const void * key)
{
const fingerPrint * fp = key;
@@ -138,8 +128,8 @@ unsigned int fpHashFunction(const void * key)
while (*chptr) ch ^= *chptr++;
hash |= ((unsigned)ch) << 24;
- hash |= (((((unsigned)fp->dev) >> 8) ^ fp->dev) & 0xFF) << 16;
- hash |= fp->ino & 0xFFFF;
+ hash |= (((((unsigned)fp->entry->dev) >> 8) ^ fp->entry->dev) & 0xFF) << 16;
+ hash |= fp->entry->ino & 0xFFFF;
return hash;
}
@@ -149,36 +139,36 @@ int fpEqual(const void * key1, const void * key2)
return FP_EQUAL(*((const fingerPrint *) key1), *((fingerPrint *) key2));
}
-fingerPrint fpLookup(const char * fullName, int scareMemory)
-{
- return doLookup(fullName, scareMemory, NULL);
-}
-
-void fpLookupList(const char ** fullNames, fingerPrint * fpList, int numItems,
- int alreadySorted)
-{
- int i, j;
- struct lookupCache cache;
- int maxLen = 0;
-
- if (!alreadySorted) {
- qsort(fullNames, numItems, sizeof(char *), strCompare);
+void fpLookupList(fingerPrintCache cache, char ** dirNames, char ** baseNames,
+ 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);
+ }
}
+}
- for (i = 0; i < numItems; i++) {
- j = strlen(fullNames[i]);
- if (j > maxLen) maxLen = j;
- }
+void fpLookupHeader(fingerPrintCache cache, Header h, fingerPrint * fpList) {
+ int fileCount;
+ char ** baseNames, ** dirNames;
+ int_32 * dirIndexes;
- cache.match = alloca(maxLen + 2);
- *cache.match = '\0';
- cache.matchLength = 0;
- cache.pathsStripped = 0;
- cache.stripLength = 0;
- cache.dev = 0;
- cache.ino = 0;
+ if (!headerGetEntry(h, RPMTAG_COMPFILELIST, NULL, (void **) &baseNames,
+ &fileCount)) return;
+ headerGetEntry(h, RPMTAG_COMPDIRLIST, NULL, (void **) &dirNames, NULL);
+ headerGetEntry(h, RPMTAG_COMPFILEDIRS, NULL, (void **) &dirIndexes, NULL);
+
+ fpLookupList(cache, dirNames, baseNames, dirIndexes, fileCount, fpList);
- for (i = 0; i < numItems; i++) {
- fpList[i] = doLookup(fullNames[i], 1, &cache);
- }
+ free(dirNames);
+ free(baseNames);
}
diff --git a/lib/fprint.h b/lib/fprint.h
index d1ba65ff2..aa0efc998 100644
--- a/lib/fprint.h
+++ b/lib/fprint.h
@@ -1,9 +1,26 @@
#ifndef H_FINGERPRINT
#define H_FINGERPRINT
-typedef struct fingerprint_s {
+#include "hash.h"
+#include "header.h"
+
+/* 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 {
+ char * dirName;
dev_t dev;
ino_t ino;
+ int isFake;
+};
+
+typedef struct fprintCache_s {
+ hashTable ht; /* hashed by dirName */
+} * fingerPrintCache;
+
+typedef struct fingerprint_s {
+ const struct fprintCacheEntry_s * entry;
+ const char * subdir;
const char * basename;
} fingerPrint;
@@ -11,8 +28,8 @@ typedef struct fingerprint_s {
#define fpFree(a) free((void *)(a).basename)
#define FP_EQUAL(a, b) ((&(a) == &(b)) || \
- (((a).dev == (b).dev) && \
- ((a).ino == (b).ino) && \
+ (((a).entry == (b).entry) && \
+ !strcmp((a).subdir, (b).subdir) && \
!strcmp((a).basename, (b).basename)))
#ifdef __cplusplus
@@ -20,12 +37,20 @@ extern "C" {
#endif
/* Be carefull with the memory... assert(*fullName == '/' || !scareMemory) */
-fingerPrint fpLookup(const char * fullName, int scareMemory);
-unsigned int fpHashFunction(const void * string);
+fingerPrintCache fpCacheCreate(int sizeHint);
+void fpCacheFree(fingerPrintCache cache);
+fingerPrint fpLookup(fingerPrintCache cache, const char * fullName,
+ int scareMemory);
+
+/* Hash based on dev and inode only! */
+unsigned int fpHashFunction(const void * key);
+/* exactly equivalent to FP_EQUAL */
int fpEqual(const void * key1, const void * key2);
-/* scareMemory is assumed here! */
-void fpLookupList(const char ** fullNames, fingerPrint * fpList, int numItems,
- int alreadySorted);
+
+/* scareMemory is assumed for both of these! */
+void fpLookupList(fingerPrintCache cache, char ** dirNames, char ** baseNames,
+ int * dirIndexes, int fileCount, fingerPrint * fpList);
+void fpLookupHeader(fingerPrintCache cache, Header h, fingerPrint * fpList);
#ifdef __cplusplus
}
diff --git a/lib/install.c b/lib/install.c
index c451f5759..4bc53d74e 100644
--- a/lib/install.c
+++ b/lib/install.c
@@ -448,7 +448,7 @@ static int installSources(Header h, const char * rootdir, FD_t fd,
}
rpmMessage(RPMMESS_DEBUG, _("spec file in: %s\n"), realSpecDir);
- if (h != NULL && headerIsEntry(h, RPMTAG_OLDFILENAMES)) {
+ if (h != NULL && headerIsEntry(h, RPMTAG_COMPFILENAMES)) {
/* we can't remap v1 packages */
assembleFileList(h, &fileMem, &fileCount, &files, 0, NULL);
@@ -717,7 +717,7 @@ int installBinaryPackage(const char * rootdir, rpmdb db, FD_t fd, Header h,
/*@-unrecog@*/ chroot(rootdir); /*@=unrecog@*/
}
- if (!(flags & RPMTRANS_FLAG_JUSTDB) && headerIsEntry(h, RPMTAG_OLDFILENAMES)) {
+ if (!(flags & RPMTRANS_FLAG_JUSTDB) && headerIsEntry(h, RPMTAG_COMPFILENAMES)) {
const char * defaultPrefix;
/* old format relocateable packages need the entire default
prefix stripped to form the cpio list, while all other packages
@@ -847,7 +847,7 @@ int installBinaryPackage(const char * rootdir, rpmdb db, FD_t fd, Header h,
if (fileMem) freeFileMemory(fileMem);
fileMem = NULL;
} else if (flags & RPMTRANS_FLAG_JUSTDB) {
- if (headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, NULL, &fileCount)) {
+ if (headerGetEntry(h, RPMTAG_COMPFILENAMES, NULL, NULL, &fileCount)) {
fileStates = xmalloc(sizeof(*fileStates) * fileCount);
memset(fileStates, RPMFILE_STATE_NORMAL, fileCount);
headerAddEntry(h, RPMTAG_FILESTATES, RPM_CHAR_TYPE, fileStates,
diff --git a/lib/rpmdb.c b/lib/rpmdb.c
index 1a817f18c..d71bf2f84 100644
--- a/lib/rpmdb.c
+++ b/lib/rpmdb.c
@@ -365,8 +365,10 @@ int rpmdbFindByFile(rpmdb db, const char * filespec, dbiIndexSet * matches)
char ** baseNames, ** dirNames;
int_32 * dirIndexes;
char * otherFile;
+ fingerPrintCache fpc;
- fp1 = fpLookup(filespec, 0);
+ fpc = fpCacheCreate(20);
+ fp1 = fpLookup(fpc, filespec, 0);
basename = strrchr(filespec, '/');
if (!basename)
@@ -375,7 +377,10 @@ int rpmdbFindByFile(rpmdb db, const char * filespec, dbiIndexSet * matches)
basename++;
rc = dbiSearchIndex(db->fileIndex, basename, &allMatches);
- if (rc) return rc;
+ if (rc) {
+ fpCacheFree(fpc);
+ return rc;
+ }
*matches = dbiCreateIndexRecord();
i = 0;
@@ -399,7 +404,7 @@ int rpmdbFindByFile(rpmdb db, const char * filespec, dbiIndexSet * matches)
strcpy(otherFile, dirNames[dirIndexes[num]]);
strcat(otherFile, baseNames[num]);
- fp2 = fpLookup(otherFile, 1);
+ fp2 = fpLookup(fpc, otherFile, 1);
if (FP_EQUAL(fp1, fp2))
dbiAppendIndexRecord(matches, allMatches.recs[i]);
@@ -416,6 +421,8 @@ int rpmdbFindByFile(rpmdb db, const char * filespec, dbiIndexSet * matches)
dbiFreeIndexRecord(allMatches);
+ fpCacheFree(fpc);
+
if (!matches->count) {
dbiFreeIndexRecord(*matches);
return 1;
@@ -484,10 +491,9 @@ int rpmdbRemove(rpmdb db, unsigned int offset, int tolerant)
int type;
unsigned int count;
dbiIndexRecord rec;
- char ** fileList, ** providesList, ** requiredbyList;
+ char ** baseFileNames, ** providesList, ** requiredbyList;
char ** conflictList, ** triggerList;
int i;
- char * basename;
/* structure assignment */
rec = dbiReturnIndexRecordInstance(offset, 0);
@@ -564,23 +570,17 @@ int rpmdbRemove(rpmdb db, unsigned int offset, int tolerant)
free(conflictList);
}
- if (headerGetEntry(h, RPMTAG_OLDFILENAMES, &type, (void **) &fileList,
+ if (headerGetEntry(h, RPMTAG_COMPFILELIST, &type, (void **) &baseFileNames,
&count)) {
for (i = 0; i < count; i++) {
- basename = strrchr(fileList[i], '/');
- if (!basename)
- basename = fileList[i];
- else
- basename++;
-
rpmMessage(RPMMESS_DEBUG, _("removing file index for %s\n"),
- basename);
+ baseFileNames[i]);
/* structure assignment */
rec = dbiReturnIndexRecordInstance(offset, i);
- removeIndexEntry(db->fileIndex, basename, rec, tolerant,
+ removeIndexEntry(db->fileIndex, baseFileNames[i], rec, tolerant,
"file index");
}
- free(fileList);
+ free(baseFileNames);
} else {
rpmMessage(RPMMESS_DEBUG, _("package has no files\n"));
}
@@ -624,7 +624,7 @@ int rpmdbAdd(rpmdb db, Header dbentry)
{
unsigned int dboffset;
unsigned int i, j;
- const char ** fileList;
+ const char ** baseFileNames;
const char ** providesList;
const char ** requiredbyList;
const char ** conflictList;
@@ -642,8 +642,8 @@ int rpmdbAdd(rpmdb db, Header dbentry)
if (!group) group = "Unknown";
count = 0;
- headerGetEntry(dbentry, RPMTAG_OLDFILENAMES, &type, (void **) &fileList,
- &count);
+ headerGetEntry(dbentry, RPMTAG_COMPFILELIST, &type, (void **)
+ &baseFileNames, &count);
headerGetEntry(dbentry, RPMTAG_PROVIDENAME, &type, (void **) &providesList,
&providesCount);
headerGetEntry(dbentry, RPMTAG_REQUIRENAME, &type,
@@ -693,14 +693,7 @@ int rpmdbAdd(rpmdb db, Header dbentry)
rc += addIndexEntry(db->providesIndex, providesList[i], dboffset, 0);
for (i = 0; i < count; i++) {
- const char * basename;
- basename = strrchr(fileList[i], '/');
- if (!basename)
- basename = fileList[i];
- else
- basename++;
- if (*basename)
- rc += addIndexEntry(db->fileIndex, basename, dboffset, i);
+ rc += addIndexEntry(db->fileIndex, baseFileNames[i], dboffset, i);
}
dbiSyncIndex(db->nameIndex);
@@ -717,7 +710,7 @@ exit:
if (providesCount) free(providesList);
if (conflictCount) free(conflictList);
if (triggerCount) free(triggerList);
- if (count) free(fileList);
+ if (count) free(baseFileNames);
return rc;
}
@@ -849,6 +842,10 @@ int rpmdbFindFpList(rpmdb db, fingerPrint * fpList, dbiIndexSet * matchList,
int i, j;
int start, end;
int num;
+ int_32 fc;
+ char ** dirNames, ** fullBaseNames, ** baseNames;
+ int_32 * dirIndexes, * fullDirIndexes;
+ fingerPrintCache fpc;
/* this may be worth batching by basename, but probably not as
basenames are quite unique as it is */
@@ -890,6 +887,8 @@ int rpmdbFindFpList(rpmdb db, fingerPrint * fpList, dbiIndexSet * matchList,
for (i = 0; i < numItems; i++)
matchList[i] = dbiCreateIndexRecord();
+ fpc = fpCacheCreate(numIntMatches);
+
/* For each set of files matched in a package ... */
for (start = 0; start < numIntMatches; start = end) {
struct intMatch * im;
@@ -912,21 +911,28 @@ int rpmdbFindFpList(rpmdb db, fingerPrint * fpList, dbiIndexSet * matchList,
return 1;
}
- { const char ** fullfl, **fl;
- int_32 fc;
-
- headerGetEntryMinMemory(h, RPMTAG_OLDFILENAMES, NULL,
- (void **) &fullfl, &fc);
-
- fl = xcalloc(num, sizeof(*fl));
- for (i = 0; i < num; i++)
- fl[i] = fullfl[im[i].rec.fileNumber];
- free(fullfl);
- fps = xcalloc(num, sizeof(*fps));
- fpLookupList(fl, fps, num, 1);
- free(fl);
+ headerGetEntryMinMemory(h, RPMTAG_COMPDIRLIST, NULL,
+ (void **) &dirNames, NULL);
+ headerGetEntryMinMemory(h, RPMTAG_COMPFILELIST, NULL,
+ (void **) &fullBaseNames, &fc);
+ headerGetEntryMinMemory(h, RPMTAG_COMPFILEDIRS, NULL,
+ (void **) &fullDirIndexes, NULL);
+
+ baseNames = xcalloc(num, sizeof(*baseNames));
+ dirIndexes = xcalloc(num, sizeof(*dirIndexes));
+ for (i = 0; i < num; i++) {
+ baseNames[i] = fullBaseNames[im[i].rec.fileNumber];
+ dirIndexes[i] = fullDirIndexes[im[i].rec.fileNumber];
}
+ fps = xcalloc(num, sizeof(*fps));
+ fpLookupList(fpc, dirNames, baseNames, dirIndexes, num, fps);
+
+ free(dirNames);
+ free(fullBaseNames);
+ free(baseNames);
+ free(dirIndexes);
+
/* Add db (recnum,filenum) to list for fingerprint matches. */
for (i = 0; i < num; i++) {
j = im[i].fpNum;
@@ -937,9 +943,9 @@ int rpmdbFindFpList(rpmdb db, fingerPrint * fpList, dbiIndexSet * matchList,
headerFree(h);
free(fps);
-
}
+ fpCacheFree(fpc);
free(intMatches);
return 0;
diff --git a/lib/transaction.c b/lib/transaction.c
index 7318985e6..7334c9c5c 100644
--- a/lib/transaction.c
+++ b/lib/transaction.c
@@ -41,7 +41,9 @@ typedef struct transactionFileInfo {
enum fileActions * actions;
fingerPrint * fps;
uint_32 * fflags, * fsizes;
- const char ** fl;
+ const char ** bnl; /* base names */
+ const char ** dnl; /* dir names */
+ const int * dil; /* dir index list */
char ** fmd5s;
uint_16 * fmodes;
Header h;
@@ -89,8 +91,10 @@ static void freeFi(TFI_t *fi)
if (fi->replaced) {
free(fi->replaced); fi->replaced = NULL;
}
- if (fi->fl) {
- free(fi->fl); fi->fl = NULL;
+ if (fi->bnl) {
+ free(fi->bnl); fi->bnl = NULL;
+ free(fi->dnl); fi->dnl = NULL;
+ fi->dil = NULL;
}
if (fi->flinks) {
free(fi->flinks); fi->flinks = NULL;
@@ -175,6 +179,16 @@ static void psAppend(rpmProblemSet probs, rpmProblemType type,
probs->probs[probs->numProblems++].ignoreProblem = 0;
}
+static void psAppendFile(rpmProblemSet probs, rpmProblemType type,
+ const void * key, Header h, const char * dirName,
+ const char * baseName, Header altH, unsigned long ulong1)
+{
+ char * str = alloca(strlen(dirName) + strlen(baseName) + 2);
+
+ sprintf(str, "%s/%s", dirName, baseName);
+ psAppend(probs, type, key, h, str, altH, ulong1);
+}
+
static int archOkay(Header h)
{
int_8 * pkgArchNum;
@@ -600,10 +614,11 @@ static enum fileTypes whatis(short mode)
return result;
}
-static enum fileActions decideFileFate(const char * filespec, short dbMode,
+static enum fileActions decideFileFate(const char * dirName,
+ const char * baseName, short dbMode,
const char * dbMd5, const char * dbLink, short newMode,
const char * newMd5, const char * newLink, int newFlags,
- int brokenMd5, int transFlags)
+ int brokenMd5, int transFlags)
{
char buffer[1024];
const char * dbAttr, * newAttr;
@@ -611,6 +626,9 @@ static enum fileActions decideFileFate(const char * filespec, short dbMode,
struct stat sb;
int i, rc;
int save = (newFlags & RPMFILE_NOREPLACE) ? FA_ALTNAME : FA_SAVE;
+ char * filespec = alloca(strlen(dirName) + strlen(baseName) + 2);
+
+ sprintf(filespec, "%s/%s", dirName, baseName);
if (lstat(filespec, &sb)) {
/*
@@ -758,8 +776,9 @@ static int handleInstInstalledFiles(TFI_t * fi, rpmdb db,
fi->fmd5s[fileNum],
fi->flinks[fileNum])) {
if (reportConflicts)
- psAppend(probs, RPMPROB_FILE_CONFLICT, fi->ap->key,
- fi->ap->h, fi->fl[fileNum], h,0 );
+ psAppendFile(probs, RPMPROB_FILE_CONFLICT, fi->ap->key,
+ fi->ap->h, fi->dnl[fi->dil[fileNum]],
+ fi->bnl[fileNum], h,0 );
if (!(otherFlags[otherFileNum] | fi->fflags[fileNum])
& RPMFILE_CONFIG) {
if (!shared->isRemoved)
@@ -768,7 +787,9 @@ static int handleInstInstalledFiles(TFI_t * fi, rpmdb db,
}
if ((otherFlags[otherFileNum] | fi->fflags[fileNum]) & RPMFILE_CONFIG) {
- fi->actions[fileNum] = decideFileFate(fi->fl[fileNum],
+ fi->actions[fileNum] = decideFileFate(
+ fi->dnl[fi->dil[fileNum]],
+ fi->bnl[fileNum],
otherModes[otherFileNum],
otherMd5s[otherFileNum],
otherLinks[otherFileNum],
@@ -830,6 +851,8 @@ static void handleOverlappedFiles(TFI_t * fi, hashTable ht,
int i, j;
struct diskspaceInfo * ds = NULL;
uint_32 fixupSize = 0;
+ char * filespec = NULL;
+ int fileSpecAlloced = 0;
for (i = 0; i < fi->fc; i++) {
int otherPkgNum, otherFileNum;
@@ -839,9 +862,17 @@ static void handleOverlappedFiles(TFI_t * fi, hashTable ht,
if (XFA_SKIPPING(fi->actions[i]))
continue;
+ j = strlen(strlen(fi->dnl[fi->dil[i]]) + fi->bnl[i] + 2);
+ if (j > fileSpecAlloced) {
+ fileSpecAlloced = j * 2;
+ filespec = xrealloc(filespec, fileSpecAlloced);
+ }
+
+ sprintf(filespec, "%s/%s", fi->dnl[fi->dil[i]], fi->bnl[i]);
+
if (dsl) {
ds = dsl;
- while (ds->block && ds->dev != fi->fps[i].dev) ds++;
+ while (ds->block && ds->dev != fi->fps[i].entry->dev) ds++;
if (!ds->block) ds = NULL;
fixupSize = 0;
}
@@ -903,7 +934,8 @@ static void handleOverlappedFiles(TFI_t * fi, hashTable ht,
/* XXX is this test still necessary? */
if (fi->actions[i] != FA_UNKNOWN)
break;
- if ((fi->fflags[i] & RPMFILE_CONFIG) && !lstat(fi->fl[i], &sb)) {
+ if ((fi->fflags[i] & RPMFILE_CONFIG) &&
+ !lstat(filespec, &sb)) {
/* Here is a non-overlapped pre-existing config file. */
fi->actions[i] = (fi->fflags[i] & RPMFILE_NOREPLACE)
? FA_ALTNAME : FA_BACKUP;
@@ -921,13 +953,13 @@ static void handleOverlappedFiles(TFI_t * fi, hashTable ht,
fi->fmd5s[i],
fi->flinks[i])) {
psAppend(probs, RPMPROB_NEW_FILE_CONFLICT, fi->ap->key,
- fi->ap->h, fi->fl[i], recs[otherPkgNum]->ap->h, 0);
+ fi->ap->h, filespec, recs[otherPkgNum]->ap->h, 0);
}
/* Try to get the disk accounting correct even if a conflict. */
fixupSize = recs[otherPkgNum]->fsizes[otherFileNum];
- if ((fi->fflags[i] & RPMFILE_CONFIG) && !lstat(fi->fl[i], &sb)) {
+ if ((fi->fflags[i] & RPMFILE_CONFIG) && !lstat(filespec, &sb)) {
/* Here is an overlapped pre-existing config file. */
fi->actions[i] = (fi->fflags[i] & RPMFILE_NOREPLACE)
? FA_ALTNAME : FA_SKIP;
@@ -962,7 +994,7 @@ static void handleOverlappedFiles(TFI_t * fi, hashTable ht,
/* Here is a pre-existing modified config file that needs saving. */
{ char mdsum[50];
- if (!mdfile(fi->fl[i], mdsum) && strcmp(fi->fmd5s[i], mdsum)) {
+ if (!mdfile(filespec, mdsum) && strcmp(fi->fmd5s[i], mdsum)) {
fi->actions[i] = FA_BACKUP;
break;
}
@@ -1073,12 +1105,14 @@ static void skipFiles(TFI_t * fi, int noDocs)
*/
for (nsp = netsharedPaths; nsp && *nsp; nsp++) {
int len;
+ const char * dir = fi->dnl[fi->dil[i]];
+
len = strlen(*nsp);
- if (strncmp(fi->fl[i], *nsp, len))
+ if (strncmp(dir, *nsp, len))
continue;
/* Only directories or complete file paths can be net shared */
- if (!(fi->fl[i][len] == '/' || fi->fl[i][len] == '\0'))
+ if (!(dir[len] == '/' || dir[len] == '\0'))
continue;
break;
}
@@ -1152,6 +1186,7 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify,
int filesystemCount;
struct diskspaceInfo * di = NULL;
int oc;
+ fingerPrintCache fpc;
/* FIXME: what if the same package is included in ts twice? */
@@ -1309,13 +1344,18 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify,
break;
}
- if (!headerGetEntry(fi->h, RPMTAG_OLDFILENAMES, NULL,
- (void **) &fi->fl, &fi->fc)) {
+ if (!headerGetEntry(fi->h, RPMTAG_COMPFILELIST, NULL,
+ (void **) &fi->bnl, &fi->fc)) {
/* This catches removed packages w/ no file lists */
fi->fc = 0;
continue;
}
+ headerGetEntry(fi->h, RPMTAG_COMPFILEDIRS, NULL, (void **) &fi->dil,
+ &fi->fc);
+ headerGetEntry(fi->h, RPMTAG_COMPDIRLIST, NULL, (void **) &fi->dnl,
+ &fi->fc);
+
/* actions is initialized earlier for added packages */
if (fi->actions == NULL)
fi->actions = xcalloc(fi->fc, sizeof(*fi->actions));
@@ -1375,12 +1415,13 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify,
chroot(ts->root);
ht = htCreate(totalFileCount * 2, 0, fpHashFunction, fpEqual);
+ fpc = fpCacheCreate(totalFileCount);
/* ===============================================
* Add fingerprint for each file not skipped.
*/
for (fi = flList; (fi - flList) < flEntries; fi++) {
- fpLookupList(fi->fl, fi->fps, fi->fc, 1);
+ fpLookupHeader(fpc, fi->h, fi->fps);
for (i = 0; i < fi->fc; i++) {
if (XFA_SKIPPING(fi->actions[i]))
continue;
@@ -1516,7 +1557,8 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify,
for (oc = 0, fi = flList; oc < ts->orderCount; oc++, fi++) {
if (fi->fc == 0)
continue;
- free(fi->fl); fi->fl = NULL;
+ free(fi->dnl); fi->dnl = NULL;
+ free(fi->bnl); fi->bnl = NULL;
switch (fi->type) {
case TR_ADDED:
free(fi->fmd5s); fi->fmd5s = NULL;
@@ -1529,6 +1571,8 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify,
}
}
+ fpCacheFree(fpc);
+
/* ===============================================
* If unfiltered problems exist, free memory and return.
*/