diff options
author | ewt <devnull@localhost> | 1998-12-30 16:56:28 +0000 |
---|---|---|
committer | ewt <devnull@localhost> | 1998-12-30 16:56:28 +0000 |
commit | d7ad76b4fcea79a327c5ef49ad28d1c116c66117 (patch) | |
tree | 9c4655e2068829cbc0d09a82ceddac3b4e70edec | |
parent | 61a2cbcabfaea2b3f36d7eb1759aab61a935ce80 (diff) | |
download | rpm-d7ad76b4fcea79a327c5ef49ad28d1c116c66117.tar.gz rpm-d7ad76b4fcea79a327c5ef49ad28d1c116c66117.tar.bz2 rpm-d7ad76b4fcea79a327c5ef49ad28d1c116c66117.zip |
added fpLookupList()
CVS patchset: 2623
CVS date: 1998/12/30 16:56:28
-rw-r--r-- | lib/fprint.c | 85 | ||||
-rw-r--r-- | lib/fprint.h | 3 |
2 files changed, 87 insertions, 1 deletions
diff --git a/lib/fprint.c b/lib/fprint.c index 87c1c49e8..7a6ff8af4 100644 --- a/lib/fprint.c +++ b/lib/fprint.c @@ -4,18 +4,65 @@ #include "fprint.h" +struct lookupCache { + char * match; + int pathsStripped; + int matchLength; + dev_t dev; + ino_t ino; +}; + +static fingerPrint doLookup(char * fullName, int scareMemory, + struct lookupCache * cache); + +static int strCompare(const void * a, const void * b) { + const char * const * one = a; + const char * const * two = a; + + return strcmp(*one, *two); +}; + fingerPrint fpLookup(char * fullName, int scareMemory) { + return doLookup(fullName, scareMemory, NULL); +} + +static fingerPrint doLookup(char * fullName, int scareMemory, + struct lookupCache * cache) { char dir[PATH_MAX]; char * chptr1, * end; fingerPrint fp; struct stat sb; char * buf; + int stripCount; /* assert(*fullName == '/' || !scareMemory); */ /* FIXME: a directory stat cache could *really* speed things up. we'd have to be sure to flush it, but... */ + 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++; + } + if (!stripCount) { + chptr1 = fullName + cache->matchLength + 1; + if (scareMemory) + fp.basename = strdup(chptr1); + else + fp.basename = chptr1; + fp.ino = cache->ino; + fp.dev = cache->dev; + return fp; + } + } + } + if (*fullName != '/') { scareMemory = 0; @@ -40,8 +87,10 @@ fingerPrint fpLookup(char * fullName, int scareMemory) { buf = alloca(strlen(fullName) + 1); strcpy(buf, fullName); end = strrchr(buf, '/'); + stripCount = 0; while (*buf) { *end = '\0'; + stripCount++; /* as we're stating paths here, we want to follow symlinks */ if (!stat(buf, &sb)) { @@ -52,10 +101,19 @@ fingerPrint fpLookup(char * fullName, int scareMemory) { fp.basename = chptr1; fp.ino = sb.st_ino; fp.dev = sb.st_dev; + + if (cache) { + strcpy(cache->match, buf); + cache->matchLength = strlen(buf); + cache->pathsStripped = stripCount; + cache->dev = sb.st_dev; + cache->ino = sb.st_ino; + } + return fp; } - buf--; + end--; while ((end > buf) && *end != '/') end--; } @@ -86,3 +144,28 @@ unsigned int fpHashFunction(const void * key) { int fpEqual(const void * key1, const void * key2) { return FP_EQUAL(*((const fingerPrint *) key1), *((fingerPrint *) key2)); } + +void fpLookupList(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); + } + + for (i = 0; i < numItems; i++) { + j = strlen(fullNames[i]); + if (j > maxLen) maxLen = j; + } + + cache.match = alloca(maxLen + 1); + *cache.match = '\0'; + cache.matchLength = 0; + cache.pathsStripped = 0; + + for (i = 0; i < numItems; i++) { + fpList[i] = doLookup(fullNames[i], 1, &cache); + } +} diff --git a/lib/fprint.h b/lib/fprint.h index fab0a3fe0..aafb0a81d 100644 --- a/lib/fprint.h +++ b/lib/fprint.h @@ -11,6 +11,9 @@ typedef struct fingerprint_s { fingerPrint fpLookup(char * fullName, int scareMemory); unsigned int fpHashFunction(const void * string); int fpEqual(const void * key1, const void * key2); +/* scareMemory is assumed here! */ +void fpLookupList(char ** fullNames, fingerPrint * fpList, int numItems, + int alreadySorted); /* only if !scarceMemory */ #define fpFree(a) free((a).basename) |