use fingerprinting for path lookups

CVS patchset: 2614
CVS date: 1998/12/26 17:13:34
This commit is contained in:
ewt 1998-12-26 17:13:34 +00:00
parent a2c96ed1f5
commit 429557f9d6
1 changed files with 14 additions and 58 deletions

View File

@ -7,6 +7,7 @@
#include "rpmlib.h"
#include "falloc.h"
#include "fprint.h"
#include "misc.h"
#include "rpmdb.h"
@ -239,32 +240,13 @@ Header rpmdbGetRecord(rpmdb db, unsigned int offset) {
int rpmdbFindByFile(rpmdb db, char * filespec, dbiIndexSet * matches) {
char * basename;
fingerPrint fp1, fp2;
dbiIndexSet allMatches;
int rc;
char * targPath, * possPath = NULL;
int possPathAlloced = 0;
int i, j;
char ** fileList;
int gotOne = 0;
char * chptr1, * chptr2;
int i, rc;
Header h;
struct stat sb1, sb2;
char path[PATH_MAX];
char ** fileList;
if (*filespec != '/') {
/* 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.
*/
if (realpath(".", path) != NULL) {
/* if the current directory doesn't exist, we might fail.
oh well. likewise if it's too long. */
chptr1 = alloca(strlen(path) + strlen(filespec) + 2);
sprintf(chptr1, "%s/%s", path, filespec);
filespec = chptr1;
}
}
fp1 = fpLookup(filespec, 0);
basename = strrchr(filespec, '/');
if (!basename)
@ -275,46 +257,21 @@ int rpmdbFindByFile(rpmdb db, char * filespec, dbiIndexSet * matches) {
rc = dbiSearchIndex(db->fileIndex, basename, &allMatches);
if (rc) return rc;
/* This is pretty easy if both files are in the filesystem, as we can
do a direct comparison of the dev/ino numbers of the "ideal" filespec.
If that isn't the case, we need to walk through the paths, backwards,
until we figure out whether or not these files would be the same
or not <sigh>. Symbolic links are such a pain in the ass. */
targPath = alloca(strlen(filespec) + 1);
i = 0;
*matches = dbiCreateIndexRecord();
i = 0;
while (i < allMatches.count) {
if (!(h = rpmdbGetRecord(db, allMatches.recs[i].recOffset))) {
i++;
continue;
}
headerGetEntry(h, RPMTAG_FILENAMES, NULL, (void **) &fileList, NULL);
headerGetEntryMinMemory(h, RPMTAG_FILENAMES, NULL,
(void **) &fileList, NULL);
do {
strcpy(targPath, filespec);
j = strlen(fileList[allMatches.recs[i].fileNumber]) + 1;
if (j > possPathAlloced) {
possPath = realloc(possPath, j);
possPathAlloced = j;
}
strcpy(possPath, fileList[allMatches.recs[i].fileNumber]);
while (*targPath && *possPath) {
if (!(chptr1 = strrchr(targPath, '/')) ||
!(chptr2 = strrchr(possPath, '/')))
break;
*chptr1 = *chptr2 = '\0';
/* as we're stating paths here, we want to follow symlinks */
if (!stat(targPath, &sb1) && !stat(possPath, &sb2) &&
sb1.st_ino == sb2.st_ino && sb1.st_dev == sb2.st_dev) {
/* got a match */
dbiAppendIndexRecord(matches, allMatches.recs[i]);
gotOne = 1;
break;
}
}
fp2 = fpLookup(fileList[allMatches.recs[i].fileNumber], 1);
if (FP_EQUAL(fp1, fp2))
dbiAppendIndexRecord(matches, allMatches.recs[i]);
i++;
} while ((i < allMatches.count) &&
@ -322,13 +279,12 @@ int rpmdbFindByFile(rpmdb db, char * filespec, dbiIndexSet * matches) {
allMatches.recs[i - 1].recOffset)));
free(fileList);
headerFree(h);
}
if (possPath) free(possPath);
dbiFreeIndexRecord(allMatches);
if (!gotOne) {
if (!matches->count) {
dbiFreeIndexRecord(*matches);
return 1;
}