diff options
author | Panu Matilainen <pmatilai@redhat.com> | 2012-08-22 12:40:00 +0300 |
---|---|---|
committer | Panu Matilainen <pmatilai@redhat.com> | 2012-10-03 10:17:05 +0300 |
commit | f2719855ecfb0fa19253daee20c3c3d0ac95af9f (patch) | |
tree | bacbe6a225397dfc9b60f3579264d9b114579050 | |
parent | 46357627706b19cd0f80707944444b539b83fdad (diff) | |
download | rpm-f2719855ecfb0fa19253daee20c3c3d0ac95af9f.tar.gz |
Fix a massive memleak from rpmfiConfigConflictIndex() and optimize it
- rpmfiFNIndex() returns a malloced string since commit
11116a67864c119e420297984bd9ec4b83fdadd7 but this wasn't taken into
account in commit 3f996a588a56141df146c33583a13c0542323977, causing
a massive memory leak on transaction preparations.
- Optimize the entry by avoiding rpmfiFNIndex() and lstat() until
really necessary, and use a central exit point beyond that so
we can free fn. Besides fixing the memleak, this gives a small
but measurable performance improvement on this rather busy path.
- Backported from commit 80ee39da35544253cab12abd54af8754335ac945
-rw-r--r-- | lib/rpmfi.c | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/lib/rpmfi.c b/lib/rpmfi.c index 40162023f..34d8e2780 100644 --- a/lib/rpmfi.c +++ b/lib/rpmfi.c @@ -677,24 +677,33 @@ rpmFileAction rpmfiDecideFateIndex(rpmfi ofi, int oix, rpmfi nfi, int nix, int rpmfiConfigConflictIndex(rpmfi fi, int ix) { - const char * fn = rpmfiFNIndex(fi, ix); + char * fn = NULL; rpmfileAttrs flags = rpmfiFFlagsIndex(fi, ix); char buffer[1024]; rpmFileTypes newWhat, diskWhat; struct stat sb; + int rc = 0; - if (!(flags & RPMFILE_CONFIG) || lstat(fn, &sb)) { + if (!(flags & RPMFILE_CONFIG)) return 0; - } - diskWhat = rpmfiWhatis((rpm_mode_t)sb.st_mode); + /* Only links and regular files can be %config, this is kinda moot */ + /* XXX: Why are we returning 1 here? */ newWhat = rpmfiWhatis(rpmfiFModeIndex(fi, ix)); - if (newWhat != LINK && newWhat != REG) return 1; - if (diskWhat != newWhat) - return 1; + /* If it's not on disk, there's nothing to be saved */ + fn = rpmfiFNIndex(fi, ix); + if (lstat(fn, &sb)) + goto exit; + + /* Files of different types obviously are not identical */ + diskWhat = rpmfiWhatis((rpm_mode_t)sb.st_mode); + if (diskWhat != newWhat) { + rc = 1; + goto exit; + } memset(buffer, 0, sizeof(buffer)); if (newWhat == REG) { @@ -702,21 +711,25 @@ int rpmfiConfigConflictIndex(rpmfi fi, int ix) size_t diglen; const unsigned char *ndigest = rpmfiFDigestIndex(fi,ix, &algo, &diglen); if (rpmDoDigest(algo, fn, 0, (unsigned char *)buffer, NULL)) - return 0; /* assume file has been removed */ + goto exit; /* assume file has been removed */ if (ndigest && !memcmp(ndigest, buffer, diglen)) - return 0; /* unmodified config file */ + goto exit; /* unmodified config file */ } else /* newWhat == LINK */ { const char * nFLink; ssize_t link_len = readlink(fn, buffer, sizeof(buffer) - 1); if (link_len == -1) - return 0; /* assume file has been removed */ + goto exit; /* assume file has been removed */ buffer[link_len] = '\0'; nFLink = rpmfiFLinkIndex(fi, ix); if (nFLink && rstreq(nFLink, buffer)) - return 0; /* unmodified config file */ + goto exit; /* unmodified config file */ } - return 1; + rc = 1; + +exit: + free(fn); + return rc; } static char **duparray(char ** src, int size) |