Header headerFree(Header h) { (void) headerUnlink(h); if (h == NULL || h->nrefs > 0) return NULL; if (h->index) { indexEntry entry = h->index; int i; for (i = 0; i < h->indexUsed; i++, entry++) { if ((h->flags & HEADERFLAG_ALLOCATED) && ENTRY_IS_REGION(entry)) { if (entry->length > 0) { int32_t * ei = entry->data; if ((ei - 2) == h->blob) h->blob = _free(h->blob); entry->data = NULL; } } else if (!ENTRY_IN_REGION(entry)) { entry->data = _free(entry->data); } entry->data = NULL; } h->index = _free(h->index); } h = _free(h); return NULL; }
int headerMod(Header h, rpmtd td) { indexEntry entry; rpm_data_t oldData; rpm_data_t data; int length; /* First find the tag */ entry = findEntry(h, td->tag, td->type); if (!entry) return 0; length = 0; data = grabData(td->type, td->data, td->count, &length); if (data == NULL || length <= 0) return 0; /* make sure entry points to the first occurence of this tag */ while (entry > h->index && (entry - 1)->info.tag == td->tag) entry--; /* free after we've grabbed the new data in case the two are intertwined; that's a bad idea but at least we won't break */ oldData = entry->data; entry->info.count = td->count; entry->info.type = td->type; entry->data = data; entry->length = length; if (ENTRY_IN_REGION(entry)) { entry->info.offset = 0; } else oldData = _free(oldData); return 1; }
int headerDel(Header h, rpmTagVal tag) { indexEntry last = h->index + h->indexUsed; indexEntry entry, first; int ne; entry = findEntry(h, tag, RPM_NULL_TYPE); if (!entry) return 1; /* Make sure entry points to the first occurrence of this tag. */ while (entry > h->index && (entry - 1)->info.tag == tag) entry--; /* Free data for tags being removed. */ for (first = entry; first < last; first++) { rpm_data_t data; if (first->info.tag != tag) break; data = first->data; first->data = NULL; first->length = 0; if (ENTRY_IN_REGION(first)) continue; free(data); } ne = (first - entry); if (ne > 0) { h->indexUsed -= ne; ne = last - first; if (ne > 0) memmove(entry, first, (ne * sizeof(*entry))); } return 0; }
static int intAppendEntry(Header h, rpmtd td) { indexEntry entry; int length; if (td->type == RPM_STRING_TYPE || td->type == RPM_I18NSTRING_TYPE) { /* we can't do this */ return 0; } /* Find the tag entry in the header. */ entry = findEntry(h, td->tag, td->type); if (!entry) return 0; length = dataLength(td->type, td->data, td->count, 0, NULL); if (length < 0) return 0; if (ENTRY_IN_REGION(entry)) { char * t = xmalloc(entry->length + length); memcpy(t, entry->data, entry->length); entry->data = t; entry->info.offset = 0; } else entry->data = xrealloc(entry->data, entry->length + length); copyData(td->type, ((char *) entry->data) + entry->length, td->data, td->count, length); entry->length += length; entry->info.count += td->count; return 1; }
int headerAddI18NString(Header h, rpmTagVal tag, const char * string, const char * lang) { indexEntry table, entry; const char ** strArray; int length; int ghosts; rpm_count_t i, langNum; char * buf; table = findEntry(h, RPMTAG_HEADERI18NTABLE, RPM_STRING_ARRAY_TYPE); entry = findEntry(h, tag, RPM_I18NSTRING_TYPE); if (!table && entry) return 0; /* this shouldn't ever happen!! */ if (!table && !entry) { const char * charArray[2]; rpm_count_t count = 0; struct rpmtd_s td; if (!lang || (lang[0] == 'C' && lang[1] == '\0')) { charArray[count++] = "C"; } else { charArray[count++] = "C"; charArray[count++] = lang; } rpmtdReset(&td); td.tag = RPMTAG_HEADERI18NTABLE; td.type = RPM_STRING_ARRAY_TYPE; td.data = (void *) charArray; td.count = count; if (!headerPut(h, &td, HEADERPUT_DEFAULT)) return 0; table = findEntry(h, RPMTAG_HEADERI18NTABLE, RPM_STRING_ARRAY_TYPE); } if (!table) return 0; if (!lang) lang = "C"; { const char * l = table->data; for (langNum = 0; langNum < table->info.count; langNum++) { if (rstreq(l, lang)) break; l += strlen(l) + 1; } } if (langNum >= table->info.count) { length = strlen(lang) + 1; if (ENTRY_IN_REGION(table)) { char * t = xmalloc(table->length + length); memcpy(t, table->data, table->length); table->data = t; table->info.offset = 0; } else table->data = xrealloc(table->data, table->length + length); memmove(((char *)table->data) + table->length, lang, length); table->length += length; table->info.count++; } if (!entry) { int rc; struct rpmtd_s td; strArray = xmalloc(sizeof(*strArray) * (langNum + 1)); for (i = 0; i < langNum; i++) strArray[i] = ""; strArray[langNum] = string; rpmtdReset(&td); td.tag = tag; td.type = RPM_I18NSTRING_TYPE; td.data = strArray; td.count = langNum + 1; rc = headerPut(h, &td, HEADERPUT_DEFAULT); free(strArray); return rc; } else if (langNum >= entry->info.count) { ghosts = langNum - entry->info.count; length = strlen(string) + 1 + ghosts; if (ENTRY_IN_REGION(entry)) { char * t = xmalloc(entry->length + length); memcpy(t, entry->data, entry->length); entry->data = t; entry->info.offset = 0; } else entry->data = xrealloc(entry->data, entry->length + length); memset(((char *)entry->data) + entry->length, '\0', ghosts); memmove(((char *)entry->data) + entry->length + ghosts, string, strlen(string)+1); entry->length += length; entry->info.count = langNum + 1; } else { char *b, *be, *e, *ee, *t; size_t bn, sn, en; /* Set beginning/end pointers to previous data */ b = be = e = ee = entry->data; for (i = 0; i < table->info.count; i++) { if (i == langNum) be = ee; ee += strlen(ee) + 1; if (i == langNum) e = ee; } /* Get storage for new buffer */ bn = (be-b); sn = strlen(string) + 1; en = (ee-e); length = bn + sn + en; t = buf = xmalloc(length); /* Copy values into new storage */ memcpy(t, b, bn); t += bn; memcpy(t, string, sn); t += sn; memcpy(t, e, en); t += en; /* Replace i18N string array */ entry->length -= strlen(be) + 1; entry->length += sn; if (ENTRY_IN_REGION(entry)) { entry->info.offset = 0; } else entry->data = _free(entry->data); entry->data = buf; } return 0; }