From 34151a9e35122d90bdc1863dc5dc5e1fec786afe Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Wed, 21 May 2008 09:02:10 +0300 Subject: [PATCH] Turn rpmtd freeData into flag bitfield, allowing more precise control - headerGet() returns even array data in a single allocation block, but regular (string) arrays need to have the pointers in array freed too - set immutable flag on header data --- lib/formats.c | 22 +++++++++------------- lib/header.c | 6 +++++- lib/rpmtd.c | 9 ++++++++- lib/rpmtd.h | 9 ++++++++- 4 files changed, 30 insertions(+), 16 deletions(-) diff --git a/lib/formats.c b/lib/formats.c index cee6b9b05..3e08fa6f0 100644 --- a/lib/formats.c +++ b/lib/formats.c @@ -614,7 +614,6 @@ static int fsnamesTag(Header h, rpmtd td) td->type = RPM_STRING_ARRAY_TYPE; td->data = list; - td->freeData = 0; return 0; } @@ -636,7 +635,7 @@ static int instprefixTag(Header h, rpmtd td) /* only return the first prefix of the array */ td->type = RPM_STRING_TYPE; td->data = xstrdup(rpmtdGetString(&prefixes)); - td->freeData = 1; + td->flags = RPMTD_ALLOCED; rpmtdFreeData(&prefixes); return 0; } @@ -670,7 +669,7 @@ static int fssizesTag(Header h, rpmtd td) return 1; td->type = RPM_INT32_TYPE; - td->freeData = 1; + td->flags = RPMTD_ALLOCED; if (filenames == NULL) { usages = xcalloc((td->count), sizeof(usages)); @@ -714,7 +713,6 @@ static int triggercondsTag(Header h, rpmtd td) char buf[5]; if (!hge(h, RPMTAG_TRIGGERNAME, &tnt, (rpm_data_t *) &names, &numNames)) { - td->freeData = 0; return 0; } @@ -724,7 +722,7 @@ static int triggercondsTag(Header h, rpmtd td) xx = hge(h, RPMTAG_TRIGGERSCRIPTS, &tst, (rpm_data_t *) &s, &numScripts); s = hfd(s, tst); - td->freeData = 1; + td->flags = RPMTD_ALLOCED; td->data = conds = xmalloc(sizeof(*conds) * numScripts); td->count = numScripts; td->type = RPM_STRING_ARRAY_TYPE; @@ -782,7 +780,6 @@ static int triggertypeTag(Header h, rpmtd td) rpm_flag_t * flags; if (!hge(h, RPMTAG_TRIGGERINDEX, NULL, (rpm_data_t *) &indices, &numNames)) { - td->freeData = 0; return 1; } @@ -790,7 +787,7 @@ static int triggertypeTag(Header h, rpmtd td) xx = hge(h, RPMTAG_TRIGGERSCRIPTS, &tst, (rpm_data_t *) &s, &numScripts); s = hfd(s, tst); - td->freeData = 1; + td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED; td->data = conds = xmalloc(sizeof(*conds) * numScripts); td->count = numScripts; td->type = RPM_STRING_ARRAY_TYPE; @@ -827,7 +824,7 @@ static int filenamesTag(Header h, rpmtd td) td->type = RPM_STRING_ARRAY_TYPE; rpmfiBuildFNames(h, RPMTAG_BASENAMES, (const char ***) &(td->data), &(td->count)); - td->freeData = 1; + td->flags = RPMTD_ALLOCED; return 0; } @@ -841,7 +838,7 @@ static int fileclassTag(Header h, rpmtd td) { td->type = RPM_STRING_ARRAY_TYPE; rpmfiBuildFClasses(h, (const char ***) &(td->data), &(td->count)); - td->freeData = 1; + td->flags = RPMTD_ALLOCED; return 0; } @@ -856,7 +853,7 @@ static int fileprovideTag(Header h, rpmtd td) td->type = RPM_STRING_ARRAY_TYPE; rpmfiBuildFDeps(h, RPMTAG_PROVIDENAME, (const char ***) &(td->data), &(td->count)); - td->freeData = 1; + td->flags = RPMTD_ALLOCED; return 0; } @@ -871,7 +868,7 @@ static int filerequireTag(Header h, rpmtd td) td->type = RPM_STRING_ARRAY_TYPE; rpmfiBuildFDeps(h, RPMTAG_REQUIRENAME, (const char ***) &(td->data), &(td->count)); - td->freeData = 1; + td->flags = RPMTD_ALLOCED; return 0; } @@ -899,7 +896,6 @@ static int i18nTag(Header h, rpmTag tag, rpmtd td) td->type = RPM_STRING_TYPE; td->data = NULL; td->count = 0; - td->freeData = 0; if (dstring && *dstring) { char *domain, *de; @@ -940,7 +936,7 @@ static int i18nTag(Header h, rpmTag tag, rpmtd td) td->data = dgettext(domain, msgid); td->data = xstrdup(td->data); /* XXX xstrdup has side effects. */ td->count = 1; - td->freeData = 1; + td->flags = RPMTD_ALLOCED; } dstring = _free(dstring); free(msgkey); diff --git a/lib/header.c b/lib/header.c index 6b0d28821..dfd6df7fa 100644 --- a/lib/header.c +++ b/lib/header.c @@ -1208,7 +1208,11 @@ static int copyTdEntry(const indexEntry entry, rpmtd td, int minMem) } td->type = entry->info.type; td->count = count; - td->freeData = (entry->data == td->data) ? 0 : 1; + + td->flags = RPMTD_IMMUTABLE; + if (entry->data != td->data) { + td->flags |= RPMTD_ALLOCED; + } return rc; } diff --git a/lib/rpmtd.c b/lib/rpmtd.c index 90cc566ed..998dd321f 100644 --- a/lib/rpmtd.c +++ b/lib/rpmtd.c @@ -39,7 +39,14 @@ void rpmtdFreeData(rpmtd td) { assert(td != NULL); - if (td->freeData) { + if (td->flags & RPMTD_ALLOCED) { + assert(td->data != NULL); + if (td->flags & RPMTD_PTR_ALLOCED) { + char **data = td->data; + for (int i = 0; i < td->count; i++) { + free(data[i]); + } + } free(td->data); } rpmtdReset(td); diff --git a/lib/rpmtd.h b/lib/rpmtd.h index c7b4562ee..1a441e4cb 100644 --- a/lib/rpmtd.h +++ b/lib/rpmtd.h @@ -4,6 +4,13 @@ #include #include +typedef enum rpmtdFlags_e { + RPMTD_NONE = 0, + RPMTD_ALLOCED = (1 << 0), /* was memory allocated? */ + RPMTD_PTR_ALLOCED = (1 << 1), /* were array pointers allocated? */ + RPMTD_IMMUTABLE = (1 << 2), /* header data or modifiable? */ +} rpmtdFlags; + /** \ingroup rpmtd * Container for rpm tag data (from headers or extensions). * @todo Make this opaque (at least outside rpm itself) @@ -13,7 +20,7 @@ struct rpmtd_s { rpmTagType type; /* data type */ rpm_count_t count; /* number of entries */ rpm_data_t data; /* pointer to actual data */ - int freeData; /* was data malloced */ + rpmtdFlags flags; /* flags on memory allocation etc */ int ix; /* iteration index */ };