diff options
author | Panu Matilainen <pmatilai@redhat.com> | 2012-08-22 12:40:00 +0300 |
---|---|---|
committer | Panu Matilainen <pmatilai@redhat.com> | 2012-08-22 12:43:20 +0300 |
commit | 80ee39da35544253cab12abd54af8754335ac945 (patch) | |
tree | 808f41ea4df7d5e9453fef4d27e6924f4e3f67cf /lib | |
parent | a3a08a4b0aa96ae03c33050920baf894cc706c9e (diff) | |
download | rpm-80ee39da35544253cab12abd54af8754335ac945.tar.gz rpm-80ee39da35544253cab12abd54af8754335ac945.tar.bz2 rpm-80ee39da35544253cab12abd54af8754335ac945.zip |
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.
Diffstat (limited to 'lib')
-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 ea1769650..afc115f67 100644 --- a/lib/rpmfi.c +++ b/lib/rpmfi.c @@ -703,24 +703,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) { @@ -728,21 +737,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) == 0) - 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) |