4 #include <rpm/rpmstring.h>
5 #include <rpm/rpmpgp.h>
9 typedef char * (*headerTagFormatFunction) (rpmtd td, char *formatPrefix);
11 extern void *rpmHeaderFormatFuncByValue(rpmtdFormats fmt);
15 rpmtd td = xmalloc(sizeof(*td));
20 rpmtd rpmtdFree(rpmtd td)
22 /* permit free on NULL td */
24 /* XXX should we free data too - a flag maybe? */
30 void rpmtdReset(rpmtd td)
34 memset(td, 0, sizeof(*td));
38 void rpmtdFreeData(rpmtd td)
42 if (td->flags & RPMTD_ALLOCED) {
43 if (td->flags & RPMTD_PTR_ALLOCED) {
44 assert(td->data != NULL);
45 char **data = td->data;
46 for (int i = 0; i < td->count; i++) {
55 rpm_count_t rpmtdCount(rpmtd td)
58 /* fix up for binary type abusing count as data length */
59 return (td->type == RPM_BIN_TYPE) ? 1 : td->count;
62 rpmTag rpmtdTag(rpmtd td)
68 rpmTagType rpmtdType(rpmtd td)
74 rpmTagClass rpmtdClass(rpmtd td)
77 return rpmTagTypeGetClass(td->type);
80 int rpmtdGetIndex(rpmtd td)
86 int rpmtdSetIndex(rpmtd td, int index)
90 if (index < 0 || index >= rpmtdCount(td)) {
97 int rpmtdInit(rpmtd td)
101 /* XXX check that this is an array type? */
106 int rpmtdNext(rpmtd td)
113 if (td->ix < rpmtdCount(td)) {
122 uint32_t *rpmtdNextUint32(rpmtd td)
125 uint32_t *res = NULL;
126 if (rpmtdNext(td) >= 0) {
127 res = rpmtdGetUint32(td);
132 uint64_t *rpmtdNextUint64(rpmtd td)
135 uint64_t *res = NULL;
136 if (rpmtdNext(td) >= 0) {
137 res = rpmtdGetUint64(td);
142 const char *rpmtdNextString(rpmtd td)
145 const char *res = NULL;
146 if (rpmtdNext(td) >= 0) {
147 res = rpmtdGetString(td);
152 char * rpmtdGetChar(rpmtd td)
158 if (td->type == RPM_CHAR_TYPE) {
159 int ix = (td->ix >= 0 ? td->ix : 0);
160 res = (char *) td->data + ix;
164 uint16_t * rpmtdGetUint16(rpmtd td)
166 uint16_t *res = NULL;
170 if (td->type == RPM_INT16_TYPE) {
171 int ix = (td->ix >= 0 ? td->ix : 0);
172 res = (uint16_t *) td->data + ix;
177 uint32_t * rpmtdGetUint32(rpmtd td)
179 uint32_t *res = NULL;
183 if (td->type == RPM_INT32_TYPE) {
184 int ix = (td->ix >= 0 ? td->ix : 0);
185 res = (uint32_t *) td->data + ix;
190 uint64_t * rpmtdGetUint64(rpmtd td)
192 uint64_t *res = NULL;
196 if (td->type == RPM_INT64_TYPE) {
197 int ix = (td->ix >= 0 ? td->ix : 0);
198 res = (uint64_t *) td->data + ix;
203 const char * rpmtdGetString(rpmtd td)
205 const char *str = NULL;
209 if (td->type == RPM_STRING_TYPE) {
210 str = (const char *) td->data;
211 } else if (td->type == RPM_STRING_ARRAY_TYPE ||
212 td->type == RPM_I18NSTRING_TYPE) {
213 /* XXX TODO: check for array bounds */
214 int ix = (td->ix >= 0 ? td->ix : 0);
215 str = *((const char**) td->data + ix);
220 uint64_t rpmtdGetNumber(rpmtd td)
224 int ix = (td->ix >= 0 ? td->ix : 0);
228 val = *((uint64_t *) td->data + ix);
231 val = *((uint32_t *) td->data + ix);
234 val = *((uint16_t *) td->data + ix);
238 val = *((uint8_t *) td->data + ix);
246 char *rpmtdFormat(rpmtd td, rpmtdFormats fmt, const char *errmsg)
248 headerTagFormatFunction func = rpmHeaderFormatFuncByValue(fmt);
249 const char *err = NULL;
253 char fmtbuf[50]; /* yuck, get rid of this */
255 str = func(td, fmtbuf);
257 err = _("Unknown format");
267 int rpmtdSetTag(rpmtd td, rpmTag tag)
270 rpmTagType newtype = rpmTagGetType(tag);
275 * - is the new tag valid at all
276 * - if changing tag of non-empty container, require matching type
278 if (newtype == RPM_NULL_TYPE)
281 if (td->data || td->count > 0) {
282 if (rpmTagGetType(td->tag) != rpmTagGetType(tag)) {
288 td->type = newtype & RPM_MASK_TYPE;
295 static inline int rpmtdSet(rpmtd td, rpmTag tag, rpmTagType type,
296 rpm_constdata_t data, rpm_count_t count)
303 * Discards const, but we won't touch the data (even rpmtdFreeData()
304 * wont free it as allocation flags aren't set) so it's "ok".
305 * XXX: Should there be a separate RPMTD_FOO flag for "user data"?
307 td->data = (void *) data;
311 int rpmtdFromUint8(rpmtd td, rpmTag tag, uint8_t *data, rpm_count_t count)
313 rpmTagType type = rpmTagGetType(tag) & RPM_MASK_TYPE;
314 rpmTagReturnType retype = rpmTagGetType(tag) & RPM_MASK_RETURN_TYPE;
320 * BIN type is really just an uint8_t array internally, it's just
321 * treated specially otherwise.
326 if (retype != RPM_ARRAY_RETURN_TYPE && count > 1)
335 return rpmtdSet(td, tag, type, data, count);
338 int rpmtdFromUint16(rpmtd td, rpmTag tag, uint16_t *data, rpm_count_t count)
340 rpmTagType type = rpmTagGetType(tag) & RPM_MASK_TYPE;
341 rpmTagReturnType retype = rpmTagGetType(tag) & RPM_MASK_RETURN_TYPE;
342 if (type != RPM_INT16_TYPE || count < 1)
344 if (retype != RPM_ARRAY_RETURN_TYPE && count > 1)
347 return rpmtdSet(td, tag, type, data, count);
350 int rpmtdFromUint32(rpmtd td, rpmTag tag, uint32_t *data, rpm_count_t count)
352 rpmTagType type = rpmTagGetType(tag) & RPM_MASK_TYPE;
353 rpmTagReturnType retype = rpmTagGetType(tag) & RPM_MASK_RETURN_TYPE;
354 if (type != RPM_INT32_TYPE || count < 1)
356 if (retype != RPM_ARRAY_RETURN_TYPE && count > 1)
359 return rpmtdSet(td, tag, type, data, count);
362 int rpmtdFromUint64(rpmtd td, rpmTag tag, uint64_t *data, rpm_count_t count)
364 rpmTagType type = rpmTagGetType(tag) & RPM_MASK_TYPE;
365 rpmTagReturnType retype = rpmTagGetType(tag) & RPM_MASK_RETURN_TYPE;
366 if (type != RPM_INT64_TYPE || count < 1)
368 if (retype != RPM_ARRAY_RETURN_TYPE && count > 1)
371 return rpmtdSet(td, tag, type, data, count);
374 int rpmtdFromString(rpmtd td, rpmTag tag, const char *data)
376 rpmTagType type = rpmTagGetType(tag) & RPM_MASK_TYPE;
379 if (type == RPM_STRING_TYPE) {
380 rc = rpmtdSet(td, tag, type, data, 1);
381 } else if (type == RPM_STRING_ARRAY_TYPE) {
382 rc = rpmtdSet(td, tag, type, &data, 1);
388 int rpmtdFromStringArray(rpmtd td, rpmTag tag, const char **data, rpm_count_t count)
390 rpmTagType type = rpmTagGetType(tag) & RPM_MASK_TYPE;
391 if (type != RPM_STRING_ARRAY_TYPE || count < 1)
393 if (type == RPM_STRING_TYPE && count != 1)
396 return rpmtdSet(td, tag, type, data, count);
399 int rpmtdFromArgv(rpmtd td, rpmTag tag, ARGV_t argv)
401 int count = argvCount(argv);
402 rpmTagType type = rpmTagGetType(tag) & RPM_MASK_TYPE;
404 if (type != RPM_STRING_ARRAY_TYPE || count < 1)
407 return rpmtdSet(td, tag, type, argv, count);
410 int rpmtdFromArgi(rpmtd td, rpmTag tag, ARGI_t argi)
412 int count = argiCount(argi);
413 rpmTagType type = rpmTagGetType(tag) & RPM_MASK_TYPE;
414 rpmTagReturnType retype = rpmTagGetType(tag) & RPM_MASK_RETURN_TYPE;
416 if (type != RPM_INT32_TYPE || retype != RPM_ARRAY_RETURN_TYPE || count < 1)
419 return rpmtdSet(td, tag, type, argiData(argi), count);
422 rpmtd rpmtdDup(rpmtd td)
429 /* TODO: permit other types too */
430 if (td->type != RPM_STRING_ARRAY_TYPE && td->type != RPM_I18NSTRING_TYPE) {
434 /* deep-copy container and data, drop immutable flag */
436 memcpy(newtd, td, sizeof(*td));
437 newtd->flags &= ~(RPMTD_IMMUTABLE);
439 newtd->flags |= (RPMTD_ALLOCED | RPMTD_PTR_ALLOCED);
440 newtd->data = data = xmalloc(td->count * sizeof(*data));
441 while ((i = rpmtdNext(td)) >= 0) {
442 data[i] = xstrdup(rpmtdGetString(td));