RPM Package Manager, CVS Repository http://rpm5.org/cvs/ ____________________________________________________________________________
Server: rpm5.org Name: Jeff Johnson Root: /v/rpm/cvs Email: j...@rpm5.org Module: rpm Date: 14-Dec-2009 19:19:23 Branch: HEAD Handle: 2009121418192201 Modified files: rpm CHANGES rpm/lib rpmfi.h rpm/rpmdb fprint.c fprint.h Log: - rpm.org: port a copy of fpLookupSubdir. Summary: Revision Changes Path 1.3200 +1 -0 rpm/CHANGES 2.77 +3 -0 rpm/lib/rpmfi.h 1.32 +249 -1 rpm/rpmdb/fprint.c 1.18 +20 -0 rpm/rpmdb/fprint.h ____________________________________________________________________________ patch -p0 <<'@@ .' Index: rpm/CHANGES ============================================================================ $ cvs diff -u -r1.3199 -r1.3200 CHANGES --- rpm/CHANGES 14 Dec 2009 01:52:09 -0000 1.3199 +++ rpm/CHANGES 14 Dec 2009 18:19:22 -0000 1.3200 @@ -1,5 +1,6 @@ 5.2b1 -> 5.3a1 + - rpm.org: port a copy of fpLookupSubdir. - jbj: rpmdb: Stub-in RPMDBI_REPACKAGES/RPMDBI_REPOSITORY stores. - jbj: rpmdb: Eliminate RPMDBI_LABEL. Use RPMTAG_NVRA instead. - jbj: rpmmi: Prepare for multiple primary stores w mi_index -> mi_primary. @@ . patch -p0 <<'@@ .' Index: rpm/lib/rpmfi.h ============================================================================ $ cvs diff -u -r2.76 -r2.77 rpmfi.h --- rpm/lib/rpmfi.h 11 Jul 2009 21:32:34 -0000 2.76 +++ rpm/lib/rpmfi.h 14 Dec 2009 18:19:23 -0000 2.77 @@ -189,6 +189,9 @@ /*...@unused@*/ rpmuint32_t * odil; /*!< Original dirindex(s) (from header) */ +/*...@only@*/ /*...@null@*/ + void * _fps; /*!< File fingerprint(s). */ + /*...@only@*/ /*...@relnull@*/ unsigned char * digests; /*!< File digest(s) in binary. */ rpmuint32_t digestalgo; /*!< File digest algorithm. */ @@ . patch -p0 <<'@@ .' Index: rpm/rpmdb/fprint.c ============================================================================ $ cvs diff -u -r1.31 -r1.32 fprint.c --- rpm/rpmdb/fprint.c 27 Mar 2009 17:42:00 -0000 1.31 +++ rpm/rpmdb/fprint.c 14 Dec 2009 18:19:23 -0000 1.32 @@ -11,7 +11,9 @@ #include <rpmtag.h> #include <rpmdb.h> +#define _FPRINT_INTERNAL #include "fprint.h" + #include "debug.h" /*...@access hashTable @*/ @@ -156,7 +158,7 @@ fp.subDir++; if (fp.subDir[0] == '\0' || /* XXX don't bother saving '/' as subdir */ - (fp.subDir[0] == '/' && fp.subDir[1] == '\0')) + (fp.subDir[0] == '/' && fp.subDir[1] == '\0')) fp.subDir = NULL; fp.baseName = baseName; if (!scareMem && fp.subDir != NULL) @@ -287,3 +289,249 @@ baseNames = _free(baseNames); } #endif + +#define _RPMFI_INTERNAL +#include "rpmfi.h" +#define _RPMTE_INTERNAL +#include "rpmte.h" + +static inline /*...@null@*/ +struct fingerPrint_s * __rpmfiFpsIndex(rpmfi fi, int ix) +{ + struct fingerPrint_s * fps = NULL; + if (fi != NULL && fi->fps != NULL && ix >= 0 && ix < (int)fi->fc) { + struct fingerPrint_s * fi_fps = fi->_fps; + fps = fi_fps + ix; + } + return fps; +} + +static inline +int __rpmfiFX(rpmfi fi) +{ + return (fi != NULL ? fi->i : -1); +} + +static inline +int __rpmfiSetFX(rpmfi fi, int fx) +{ + int i = -1; + + if (fi != NULL && fx >= 0 && fx < (int)fi->fc) { + i = fi->i; + fi->i = fx; + fi->j = fi->dil[fi->i]; + } + return i; +} + +static inline +const char * __rpmfiFLink(rpmfi fi) +{ + const char * flink = NULL; + + if (fi != NULL && fi->i >= 0 && fi->i < (int)fi->fc) { + if (fi->flinks != NULL) + flink = fi->flinks[fi->i]; + } + return flink; +} + +static inline +rpmfi __rpmteFI(rpmte te, rpmTag tag) +{ + /*...@-compdef -refcounttrans -retalias -retexpose -usereleased @*/ + if (te == NULL) + return NULL; + + if (tag == RPMTAG_BASENAMES) + return te->fi; + else + return NULL; + /*...@=compdef =refcounttrans =retalias =retexpose =usereleased @*/ +} + +/* + * Concatenate strings with dynamically (re)allocated + * memory what prevents static buffer overflows by design. + * *dest is reallocated to the size of strings to concatenate. + * List of strings has to be NULL terminated. + * + * Note: + * 1) char *buf = rstrscat(NULL,"string",NULL); is the same like rstrscat(&buf,"string",NULL); + * 2) rstrscat(&buf,NULL) returns buf + * 3) rstrscat(NULL,NULL) returns NULL + * 4) *dest and argument strings can overlap + */ +static char * rstrscat(char **dest, const char *arg, ...) +{ + va_list ap; + size_t arg_size, dst_size; + const char *s; + char *dst, *p; + + dst = dest ? *dest : NULL; + + if ( arg == NULL ) { + return dst; + } + + va_start(ap, arg); + for (arg_size=0, s=arg; s; s = va_arg(ap, const char *)) + arg_size += strlen(s); + va_end(ap); + + dst_size = dst ? strlen(dst) : 0; + dst = xrealloc(dst, dst_size+arg_size+1); /* include '\0' */ + p = &dst[dst_size]; + + va_start(ap, arg); + for (s = arg; s; s = va_arg(ap, const char *)) { + size_t size = strlen(s); + memmove(p, s, size); + p += size; + } + *p = '\0'; + + if ( dest ) { + *dest = dst; + } + + return dst; +} + +void fpLookupSubdir(hashTable symlinks, hashTable fphash, fingerPrintCache fpc, + void * _p, int filenr) +{ + rpmte p = _p; + rpmfi fi = __rpmteFI(p, RPMTAG_BASENAMES); + struct fingerPrint_s current_fp; + char * endsubdir; + char * endbasename; + char * currentsubdir; + size_t lensubDir; + + struct rpmffi_s * recs; + int numRecs; + int i, fiFX; + fingerPrint * fp = __rpmfiFpsIndex(fi, filenr); + int symlinkcount = 0; + + struct rpmffi_s * ffi = alloca(sizeof(*ffi)); + ffi->p = p; + ffi->fileno = filenr; + + if (fp->subDir == NULL) { + htAddEntry(fphash, fp, ffi); + return; + } + + lensubDir = strlen(fp->subDir); + current_fp = *fp; + currentsubdir = xstrdup(fp->subDir); + + /* Set baseName to the upper most dir */ + current_fp.baseName = endbasename = currentsubdir; + while (*endbasename != '/' && endbasename < currentsubdir + lensubDir - 1) + endbasename++; + *endbasename = '\0'; + + current_fp.subDir = endsubdir = NULL; // no subDir for now + + while (endbasename < currentsubdir + lensubDir - 1) { + char found; + found = 0; + + htGetEntry(symlinks, ¤t_fp, + &recs, &numRecs, NULL); + + for (i = 0; i < numRecs; i++) { + rpmfi foundfi; + int filenr; + char const *linktarget; + char *link; + + foundfi = __rpmteFI(recs[i].p, RPMTAG_BASENAMES); + fiFX = __rpmfiFX(foundfi); + + filenr = recs[i].fileno; + __rpmfiSetFX(foundfi, filenr); + linktarget = __rpmfiFLink(foundfi); + + if (linktarget && *linktarget != '\0') { + /* this "directory" is a symlink */ + link = NULL; + if (*linktarget != '/') { + rstrscat(&link, current_fp.entry->dirName, + current_fp.subDir ? "/" : "", + current_fp.subDir ? current_fp.subDir : "", + "/", NULL); + } + rstrscat(&link, linktarget, "/", NULL); + if (strlen(endbasename+1)) { + rstrscat(&link, endbasename+1, "/", NULL); + } + + *fp = fpLookup(fpc, link, fp->baseName, 0); + + free(link); + free(currentsubdir); + symlinkcount++; + + /* setup current_fp for the new path */ + found = 1; + current_fp = *fp; + if (fp->subDir == NULL) { + /* directory exists - no need to look for symlinks */ + htAddEntry(fphash, fp, ffi); + return; + } + lensubDir = strlen(fp->subDir); + currentsubdir = xstrdup(fp->subDir); + current_fp.subDir = endsubdir = NULL; // no subDir for now + + /* Set baseName to the upper most dir */ + current_fp.baseName = currentsubdir; + endbasename = currentsubdir; + while (*endbasename != '/' && + endbasename < currentsubdir + lensubDir - 1) + endbasename++; + *endbasename = '\0'; + break; + + } + __rpmfiSetFX(foundfi, fiFX); + } + + if (symlinkcount > 50) { + // found too many symlinks in the path + // most likley a symlink cicle + // giving up + // TODO warning/error + break; + } + + if (found) { + continue; // restart loop after symlink + } + + if (current_fp.subDir == NULL) { + /* after first round set former baseName as subDir */ + current_fp.subDir = currentsubdir; + } else { + *endsubdir = '/'; // rejoin the former baseName with subDir + } + endsubdir = endbasename; + + /* set baseName to the next lower dir */ + endbasename++; + while (*endbasename != '\0' && *endbasename != '/') + endbasename++; + *endbasename = '\0'; + current_fp.baseName = endsubdir + 1; + + } + free(currentsubdir); + htAddEntry(fphash, fp, ffi); + +} @@ . patch -p0 <<'@@ .' Index: rpm/rpmdb/fprint.h ============================================================================ $ cvs diff -u -r1.17 -r1.18 fprint.h --- rpm/rpmdb/fprint.h 27 Mar 2009 17:42:00 -0000 1.17 +++ rpm/rpmdb/fprint.h 14 Dec 2009 18:19:23 -0000 1.18 @@ -36,6 +36,13 @@ hashTable ht; /*!< hashed by dirName */ }; +#if defined(_FPRINT_INTERNAL) +struct rpmffi_s { + rpmte p; + int fileno; +}; +#endif /* _FPRINT_INTERNAL */ + /** * Associates a trailing sub-directory and final base name with an existing * directory finger print. @@ -155,6 +162,19 @@ /*...@globals fileSystem, internalState @*/ /*...@modifies cache, *fpList, fileSystem, internalState @*/; +/** + * Check file for to be installed symlinks in their path, + * correct their fingerprint and add it to newht. + * @param ht hash table containing all files fingerprints + * @param newht hash table to add the corrected fingerprints + * @param fpc fingerprint cache + * @param _p transaction element + * @param filenr the number of the file we are dealing with + */ +void fpLookupSubdir(hashTable symlinks, hashTable fphash, fingerPrintCache fpc, + void * _p, int filenr) + /*...@*/; + #ifdef __cplusplus } #endif @@ . ______________________________________________________________________ RPM Package Manager http://rpm5.org CVS Sources Repository rpm-cvs@rpm5.org