diff options
-rw-r--r-- | lib/formats.c | 8 | ||||
-rw-r--r-- | lib/fprint.c | 202 | ||||
-rw-r--r-- | lib/fprint.h | 41 | ||||
-rw-r--r-- | lib/install.c | 6 | ||||
-rw-r--r-- | lib/rpmdb.c | 88 | ||||
-rw-r--r-- | lib/transaction.c | 82 |
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. */ |