00001
00005 #include "system.h"
00006
00007 #include <rpmdb.h>
00008 #include <rpmmacro.h>
00009
00010 #include "fprint.h"
00011 #include "debug.h"
00012
00013 fingerPrintCache fpCacheCreate(int sizeHint)
00014 {
00015 fingerPrintCache fpc;
00016
00017 fpc = xmalloc(sizeof(*fpc));
00018 fpc->ht = htCreate(sizeHint * 2, 0, 1, hashFunctionString,
00019 hashEqualityString);
00020 return fpc;
00021 }
00022
00023 fingerPrintCache fpCacheFree(fingerPrintCache cache)
00024 {
00025 cache->ht = htFree(cache->ht);
00026 free(cache);
00027 return NULL;
00028 }
00029
00036 static const struct fprintCacheEntry_s * cacheContainsDirectory(
00037 fingerPrintCache cache,
00038 const char * dirName)
00039
00040 {
00041 const void ** data;
00042
00043 if (htGetEntry(cache->ht, dirName, &data, NULL, NULL))
00044 return NULL;
00045
00046 return data[0];
00047
00048 }
00049
00058
00059 static fingerPrint doLookup(fingerPrintCache cache,
00060 const char * dirName, const char * baseName, int scareMemory)
00061
00062 {
00063 char dir[PATH_MAX];
00064 const char * cleanDirName;
00065 size_t cdnl;
00066 char * end;
00067 fingerPrint fp;
00068 struct stat sb;
00069 char * buf;
00070 const struct fprintCacheEntry_s * cacheHit;
00071
00072
00073
00074
00075 cleanDirName = dirName;
00076 cdnl = strlen(cleanDirName);
00077
00078 if (*cleanDirName == '/') {
00079
00080 if (!scareMemory)
00081 cleanDirName =
00082 rpmCleanPath(strcpy(alloca(cdnl+1), dirName));
00083
00084 } else {
00085 scareMemory = 0;
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 dir[0] = '\0';
00096
00097 if (realpath(".", dir) != NULL) {
00098 end = dir + strlen(dir);
00099 if (end[-1] != '/') *end++ = '/';
00100 end = stpncpy(end, cleanDirName, sizeof(dir) - (end - dir));
00101 *end = '\0';
00102 (void)rpmCleanPath(dir);
00103 end = dir + strlen(dir);
00104 if (end[-1] != '/') *end++ = '/';
00105 *end = '\0';
00106 cleanDirName = dir;
00107 cdnl = end - dir;
00108 }
00109
00110 }
00111 fp.entry = NULL;
00112 fp.subDir = NULL;
00113 fp.baseName = NULL;
00114
00115 if (cleanDirName == NULL) return fp;
00116
00117
00118 buf = strcpy(alloca(cdnl + 1), cleanDirName);
00119 end = buf + cdnl;
00120
00121
00122 if (buf[1] && end[-1] == '/') {
00123 end--;
00124 *end = '\0';
00125 }
00126
00127 while (1) {
00128
00129
00130
00131 cacheHit = cacheContainsDirectory(cache, (*buf != '\0' ? buf : "/"));
00132 if (cacheHit != NULL) {
00133 fp.entry = cacheHit;
00134 } else if (!stat((*buf != '\0' ? buf : "/"), &sb)) {
00135 size_t nb = sizeof(*fp.entry) + (*buf != '\0' ? (end-buf) : 1) + 1;
00136 char * dn = xmalloc(nb);
00137 struct fprintCacheEntry_s * newEntry = (void *)dn;
00138
00139
00140 dn += sizeof(*newEntry);
00141 strcpy(dn, (*buf != '\0' ? buf : "/"));
00142 newEntry->ino = sb.st_ino;
00143 newEntry->dev = sb.st_dev;
00144 newEntry->dirName = dn;
00145 fp.entry = newEntry;
00146
00147
00148 htAddEntry(cache->ht, dn, fp.entry);
00149
00150
00151 }
00152
00153 if (fp.entry) {
00154 fp.subDir = cleanDirName + (end - buf);
00155 if (fp.subDir[0] == '/' && fp.subDir[1] != '\0')
00156 fp.subDir++;
00157 if (fp.subDir[0] == '\0' ||
00158
00159 (fp.subDir[0] == '/' && fp.subDir[1] == '\0'))
00160 fp.subDir = NULL;
00161 fp.baseName = baseName;
00162 if (!scareMemory && fp.subDir != NULL)
00163 fp.subDir = xstrdup(fp.subDir);
00164
00165 return fp;
00166
00167 }
00168
00169
00170 if (end == buf + 1)
00171 abort();
00172
00173 end--;
00174 while ((end > buf) && *end != '/') end--;
00175 if (end == buf)
00176 end++;
00177
00178 *end = '\0';
00179 }
00180
00181
00182
00183
00184 return fp;
00185
00186 }
00187
00188
00189 fingerPrint fpLookup(fingerPrintCache cache, const char * dirName,
00190 const char * baseName, int scareMemory)
00191 {
00192 return doLookup(cache, dirName, baseName, scareMemory);
00193 }
00194
00195 unsigned int fpHashFunction(const void * key)
00196 {
00197 const fingerPrint * fp = key;
00198 unsigned int hash = 0;
00199 char ch;
00200 const char * chptr;
00201
00202 ch = 0;
00203 chptr = fp->baseName;
00204
00205 while (*chptr != '\0') ch ^= *chptr++;
00206
00207
00208 hash |= ((unsigned)ch) << 24;
00209 hash |= (((((unsigned)fp->entry->dev) >> 8) ^ fp->entry->dev) & 0xFF) << 16;
00210 hash |= fp->entry->ino & 0xFFFF;
00211
00212 return hash;
00213 }
00214
00215
00216 int fpEqual(const void * key1, const void * key2)
00217 {
00218 const fingerPrint *k1 = key1;
00219 const fingerPrint *k2 = key2;
00220
00221
00222 if (k1 == k2)
00223 return 0;
00224
00225
00226
00227 if (FP_EQUAL(*k1, *k2))
00228 return 0;
00229
00230 return 1;
00231
00232 }
00233
00234
00235
00236 void fpLookupList(fingerPrintCache cache, const char ** dirNames,
00237 const char ** baseNames, const int * dirIndexes,
00238 int fileCount, fingerPrint * fpList)
00239 {
00240 int i;
00241
00242 for (i = 0; i < fileCount; i++) {
00243
00244
00245 if (i > 0 && dirIndexes[i - 1] == dirIndexes[i]) {
00246 fpList[i].entry = fpList[i - 1].entry;
00247 fpList[i].subDir = fpList[i - 1].subDir;
00248 fpList[i].baseName = baseNames[i];
00249 } else {
00250 fpList[i] = doLookup(cache, dirNames[dirIndexes[i]], baseNames[i],
00251 1);
00252 }
00253 }
00254 }
00255
00256
00257 #ifdef UNUSED
00258
00265 static
00266 void fpLookupHeader(fingerPrintCache cache, Header h, fingerPrint * fpList)
00267 ;
00268 {
00269 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00270 HFD_t hfd = headerFreeData;
00271 const char ** baseNames, ** dirNames;
00272 rpmTagType bnt, dnt;
00273 int_32 * dirIndexes;
00274 int fileCount;
00275 int xx;
00276
00277 if (!hge(h, RPMTAG_BASENAMES, &bnt, (void **) &baseNames, &fileCount))
00278 return;
00279
00280 xx = hge(h, RPMTAG_DIRNAMES, &dnt, (void **) &dirNames, NULL);
00281 xx = hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &dirIndexes, NULL);
00282 fpLookupList(cache, dirNames, baseNames, dirIndexes, fileCount, fpList);
00283 dirNames = hfd(dirNames, dnt);
00284 baseNames = hfd(baseNames, bnt);
00285 }
00286 #endif