diff options
author | Michael Schroeder <mls@suse.de> | 2020-02-13 11:48:33 +0100 |
---|---|---|
committer | Panu Matilainen <pmatilai@redhat.com> | 2020-02-14 12:45:59 +0200 |
commit | 879dbdc0201f02fc0a04516be6f4c3e4a7a4fdd4 (patch) | |
tree | bcc6fb1599818b375b9d6f77f63a6cb1f3c91028 /lib/fprint.c | |
parent | e929bf318a716a0470b9cf9076fab16296e496fb (diff) | |
download | rpm-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.c | 135 |
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, ¤t_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, ¤t_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, |