summaryrefslogtreecommitdiff
path: root/lib/fprint.c
diff options
context:
space:
mode:
authorMichael Schroeder <mls@suse.de>2020-02-13 11:48:33 +0100
committerPanu Matilainen <pmatilai@redhat.com>2020-02-14 12:45:59 +0200
commit879dbdc0201f02fc0a04516be6f4c3e4a7a4fdd4 (patch)
treebcc6fb1599818b375b9d6f77f63a6cb1f3c91028 /lib/fprint.c
parente929bf318a716a0470b9cf9076fab16296e496fb (diff)
downloadrpm-879dbdc0201f02fc0a04516be6f4c3e4a7a4fdd4.tar.gz
Remove duplicated code in fpLookupSubdir
When we encounter a symlink, we have to restart the function from the beginning. Instead of duplicating the setup code, add a new loop and make the code do a iteration for each symlink.
Diffstat (limited to 'lib/fprint.c')
-rw-r--r--lib/fprint.c135
1 files changed, 61 insertions, 74 deletions
diff --git a/lib/fprint.c b/lib/fprint.c
index 72254e739..5cae13b3c 100644
--- a/lib/fprint.c
+++ b/lib/fprint.c
@@ -344,47 +344,50 @@ static void fpLookupSubdir(rpmFpHash symlinks, fingerPrintCache fpc, fingerPrint
int i;
int symlinkcount = 0;
- if (fp->subDirId == 0)
- return;
-
- currentsubdir = rpmstrPoolStr(fpc->pool, fp->subDirId);
- lensubDir = rpmstrPoolStrlen(fpc->pool, fp->subDirId);
- current_fp = *fp;
-
- /* Set baseName to the upper most dir */
- bnStart = bnEnd = 1;
- while (bnEnd < lensubDir && currentsubdir[bnEnd] != '/')
- bnEnd++;
- /* no subDir for now */
- current_fp.subDirId = 0;
-
- while (bnEnd < lensubDir) {
- char found = 0;
-
- current_fp.baseNameId = rpmstrPoolIdn(fpc->pool,
- currentsubdir + bnStart,
- bnEnd - bnStart, 1);
-
- rpmFpHashGetEntry(symlinks, &current_fp, &recs, &numRecs, NULL);
-
- for (i = 0; i < numRecs; i++) {
- rpmfiles foundfi = rpmteFiles(recs[i].p);
- char const *linktarget = rpmfilesFLink(foundfi, recs[i].fileno);
- char *link;
-
- /* Ignore already removed (by eg %pretrans) links */
- if (linktarget && rpmteType(recs[i].p) == TR_REMOVED) {
- char *path = rpmfilesFN(foundfi, recs[i].fileno);
- struct stat sb;
- if (lstat(path, &sb) == -1)
- linktarget = NULL;
- free(path);
- }
+ for (;;) {
+ int found = 0;
+
+ if (fp->subDirId == 0)
+ break; /* directory exists - no need to look for symlinks */
+
+ currentsubdir = rpmstrPoolStr(fpc->pool, fp->subDirId);
+ lensubDir = rpmstrPoolStrlen(fpc->pool, fp->subDirId);
+ current_fp = *fp;
+
+ /* Set baseName to the upper most dir */
+ bnStart = bnEnd = 1;
+ while (bnEnd < lensubDir && currentsubdir[bnEnd] != '/')
+ bnEnd++;
+ /* no subDir for now */
+ current_fp.subDirId = 0;
+
+ while (bnEnd < lensubDir) {
+ current_fp.baseNameId = rpmstrPoolIdn(fpc->pool,
+ currentsubdir + bnStart,
+ bnEnd - bnStart, 1);
- foundfi = rpmfilesFree(foundfi);
+ rpmFpHashGetEntry(symlinks, &current_fp, &recs, &numRecs, NULL);
- if (linktarget && *linktarget != '\0') {
+ for (i = 0; i < numRecs; i++) {
+ rpmfiles foundfi = rpmteFiles(recs[i].p);
+ char const *linktarget = rpmfilesFLink(foundfi, recs[i].fileno);
+ char *link;
const char *bn;
+
+ /* Ignore already removed (by eg %pretrans) links */
+ if (linktarget && rpmteType(recs[i].p) == TR_REMOVED) {
+ char *path = rpmfilesFN(foundfi, recs[i].fileno);
+ struct stat sb;
+ if (lstat(path, &sb) == -1)
+ linktarget = NULL;
+ free(path);
+ }
+
+ foundfi = rpmfilesFree(foundfi);
+
+ if (!linktarget || *linktarget == '\0')
+ continue;
+
/* this "directory" is a symlink */
link = NULL;
if (*linktarget != '/') {
@@ -401,52 +404,36 @@ static void fpLookupSubdir(rpmFpHash symlinks, fingerPrintCache fpc, fingerPrint
}
bn = rpmstrPoolStr(fpc->pool, fp->baseNameId);
- doLookup(fpc, link, bn, fp); /* modifies fingerprint */
+ doLookup(fpc, link, bn, fp); /* modifies the fingerprint! */
free(link);
- symlinkcount++;
- /* setup current_fp for the new path */
found = 1;
- current_fp = *fp;
- if (fp->subDirId == 0) {
- /* directory exists - no need to look for symlinks */
- return;
- }
- currentsubdir = rpmstrPoolStr(fpc->pool, fp->subDirId);
- lensubDir = rpmstrPoolStrlen(fpc->pool, fp->subDirId);
- /* no subDir for now */
- current_fp.subDirId = 0;
-
- /* Set baseName to the upper most dir */
- bnStart = bnEnd = 1;
- while (bnEnd < lensubDir && currentsubdir[bnEnd] != '/')
- bnEnd++;
break;
-
}
- }
- 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
- }
- /* Set former baseName as subDir */
- bnEnd++;
- current_fp.subDirId = rpmstrPoolIdn(fpc->pool, currentsubdir, bnEnd, 1);
+ if (found)
+ break;
- /* set baseName to the next lower dir */
- bnStart = bnEnd;
- while (bnEnd < lensubDir && currentsubdir[bnEnd] != '/')
+ /* Set former baseName as subDir */
bnEnd++;
- }
+ current_fp.subDirId = rpmstrPoolIdn(fpc->pool, currentsubdir, bnEnd, 1);
+ /* set baseName to the next lower dir */
+ bnStart = bnEnd;
+ while (bnEnd < lensubDir && currentsubdir[bnEnd] != '/')
+ bnEnd++;
+ }
+
+ if (!found)
+ break; /* no symlink found, we are done */
+
+ if (++symlinkcount > 50) {
+ /* we followed too many symlinks, there is most likely a cycle */
+ /* TODO: warning/error */
+ break;
+ }
+ }
}
fingerPrint * fpCacheGetByFp(fingerPrintCache cache,