Modify eu-strip option to perform strip in post script of rpm package & add option...
[platform/upstream/rpm.git] / lib / rpmtd.c
1 #include "system.h"
2
3 #include <rpm/rpmtd.h>
4 #include <rpm/rpmstring.h>
5 #include <rpm/rpmpgp.h>
6 #include <rpm/rpmstrpool.h>
7 #include "lib/misc.h"           /* format function prototypes */
8
9 #include "debug.h"
10
11 rpmtd rpmtdNew(void)
12 {
13     rpmtd td = xmalloc(sizeof(*td));
14     rpmtdReset(td);
15     return td;
16 }
17
18 rpmtd rpmtdFree(rpmtd td)
19 {
20     /* permit free on NULL td */
21     if (td != NULL) {
22         /* XXX should we free data too - a flag maybe? */
23         free(td);
24     }
25     return NULL;
26 }
27
28 void rpmtdReset(rpmtd td)
29 {
30     assert(td != NULL);
31
32     memset(td, 0, sizeof(*td));
33     td->ix = -1;
34 }
35
36 void rpmtdFreeData(rpmtd td)
37 {
38     assert(td != NULL);
39
40     if (td->flags & RPMTD_ALLOCED) {
41         if (td->flags & RPMTD_PTR_ALLOCED) {
42             assert(td->data != NULL);
43             char **data = td->data;
44             for (int i = 0; i < td->count; i++) {
45                 free(data[i]);
46             }
47         }
48         free(td->data);
49     }
50     rpmtdReset(td);
51 }
52
53 rpm_count_t rpmtdCount(rpmtd td)
54 {
55     assert(td != NULL);
56     /* fix up for binary type abusing count as data length */
57     return (td->type == RPM_BIN_TYPE) ? 1 : td->count;
58 }
59
60 rpmTagVal rpmtdTag(rpmtd td)
61 {
62     assert(td != NULL);
63     return td->tag;
64 }
65
66 rpmTagType rpmtdType(rpmtd td)
67 {
68     assert(td != NULL);
69     return td->type;
70 }
71
72 rpmTagClass rpmtdClass(rpmtd td)
73 {
74     assert(td != NULL);
75     return rpmTagTypeGetClass(td->type);
76 }
77
78 rpmtdFlags rpmtdGetFlags(rpmtd td)
79 {
80     return (td != NULL) ? td->flags : 0;
81 }
82
83 int rpmtdGetIndex(rpmtd td)
84 {
85     assert(td != NULL);
86     return td->ix;
87 }
88
89 int rpmtdSetIndex(rpmtd td, int index)
90 {
91     assert(td != NULL);
92
93     if (index < 0 || index >= rpmtdCount(td)) {
94         return -1;
95     }
96     td->ix = index;
97     return td->ix;
98 }
99
100 int rpmtdInit(rpmtd td)
101 {
102     assert(td != NULL);
103
104     /* XXX check that this is an array type? */
105     td->ix = -1;
106     return 0;
107 }
108
109 int rpmtdNext(rpmtd td)
110 {
111     assert(td != NULL);
112
113     int i = -1;
114     
115     if (++td->ix >= 0) {
116         if (td->ix < rpmtdCount(td)) {
117             i = td->ix;
118         } else {
119             td->ix = i;
120         }
121     }
122     return i;
123 }
124
125 uint32_t *rpmtdNextUint32(rpmtd td)
126 {
127     assert(td != NULL);
128     uint32_t *res = NULL;
129     if (rpmtdNext(td) >= 0) {
130         res = rpmtdGetUint32(td);
131     }
132     return res;
133 }
134
135 uint64_t *rpmtdNextUint64(rpmtd td)
136 {
137     assert(td != NULL);
138     uint64_t *res = NULL;
139     if (rpmtdNext(td) >= 0) {
140         res = rpmtdGetUint64(td);
141     }
142     return res;
143 }
144
145 const char *rpmtdNextString(rpmtd td)
146 {
147     assert(td != NULL);
148     const char *res = NULL;
149     if (rpmtdNext(td) >= 0) {
150         res = rpmtdGetString(td);
151     }
152     return res;
153 }
154
155 char * rpmtdGetChar(rpmtd td)
156 {
157     char *res = NULL;
158
159     assert(td != NULL);
160
161     if (td->type == RPM_CHAR_TYPE) {
162         int ix = (td->ix >= 0 ? td->ix : 0);
163         res = (char *) td->data + ix;
164     } 
165     return res;
166 }
167 uint16_t * rpmtdGetUint16(rpmtd td)
168 {
169     uint16_t *res = NULL;
170
171     assert(td != NULL);
172
173     if (td->type == RPM_INT16_TYPE) {
174         int ix = (td->ix >= 0 ? td->ix : 0);
175         res = (uint16_t *) td->data + ix;
176     } 
177     return res;
178 }
179
180 uint32_t * rpmtdGetUint32(rpmtd td)
181 {
182     uint32_t *res = NULL;
183
184     assert(td != NULL);
185
186     if (td->type == RPM_INT32_TYPE) {
187         int ix = (td->ix >= 0 ? td->ix : 0);
188         res = (uint32_t *) td->data + ix;
189     } 
190     return res;
191 }
192
193 uint64_t * rpmtdGetUint64(rpmtd td)
194 {
195     uint64_t *res = NULL;
196
197     assert(td != NULL);
198
199     if (td->type == RPM_INT64_TYPE) {
200         int ix = (td->ix >= 0 ? td->ix : 0);
201         res = (uint64_t *) td->data + ix;
202     } 
203     return res;
204 }
205
206 const char * rpmtdGetString(rpmtd td)
207 {
208     const char *str = NULL;
209
210     assert(td != NULL);
211
212     if (td->type == RPM_STRING_TYPE) {
213         str = (const char *) td->data;
214     } else if (td->type == RPM_STRING_ARRAY_TYPE ||
215                td->type == RPM_I18NSTRING_TYPE) {
216         /* XXX TODO: check for array bounds */
217         int ix = (td->ix >= 0 ? td->ix : 0);
218         str = *((const char**) td->data + ix);
219     } 
220     return str;
221 }
222
223 uint64_t rpmtdGetNumber(rpmtd td)
224 {
225     assert(td != NULL);
226     uint64_t val = 0;
227     int ix = (td->ix >= 0 ? td->ix : 0);
228
229     switch (td->type) {
230     case RPM_INT64_TYPE:
231         val = *((uint64_t *) td->data + ix);
232         break;
233     case RPM_INT32_TYPE:
234         val = *((uint32_t *) td->data + ix);
235         break;
236     case RPM_INT16_TYPE:
237         val = *((uint16_t *) td->data + ix);
238         break;
239     case RPM_INT8_TYPE:
240     case RPM_CHAR_TYPE:
241         val = *((uint8_t *) td->data + ix);
242         break;
243     default:
244         break;
245     }
246     return val;
247 }
248
249 char *rpmtdFormat(rpmtd td, rpmtdFormats fmt, const char *errmsg)
250 {
251     headerTagFormatFunction func = rpmHeaderFormatFuncByValue(fmt);
252     const char *err = NULL;
253     char *str = NULL;
254
255     if (func) {
256         str = func(td);
257     } else {
258         err = _("Unknown format");
259     }
260     
261     if (err && errmsg) {
262         errmsg = err;
263     }
264
265     return str;
266 }
267
268 int rpmtdSetTag(rpmtd td, rpmTagVal tag)
269 {
270     assert(td != NULL);
271     rpmTagType newtype = rpmTagGetTagType(tag);
272     int rc = 0;
273
274     /* 
275      * Sanity checks: 
276      * - is the new tag valid at all
277      * - if changing tag of non-empty container, require matching type 
278      */
279     if (newtype == RPM_NULL_TYPE)
280         goto exit;
281
282     if (td->data || td->count > 0) {
283         if (rpmTagGetTagType(td->tag) != rpmTagGetTagType(tag)) {
284             goto exit;
285         }
286     } 
287
288     td->tag = tag;
289     td->type = newtype;
290     rc = 1;
291     
292 exit:
293     return rc;
294 }
295
296 static inline int rpmtdSet(rpmtd td, rpmTagVal tag, rpmTagType type, 
297                             rpm_constdata_t data, rpm_count_t count)
298 {
299     rpmtdReset(td);
300     td->tag = tag;
301     td->type = type;
302     td->count = count;
303     /* 
304      * Discards const, but we won't touch the data (even rpmtdFreeData()
305      * wont free it as allocation flags aren't set) so it's "ok". 
306      * XXX: Should there be a separate RPMTD_FOO flag for "user data"?
307      */
308     td->data = (void *) data;
309     return 1;
310 }
311
312 int rpmtdFromUint8(rpmtd td, rpmTagVal tag, uint8_t *data, rpm_count_t count)
313 {
314     rpmTagType type = rpmTagGetTagType(tag);
315     rpmTagReturnType retype = rpmTagGetReturnType(tag);
316     
317     if (count < 1)
318         return 0;
319
320     /*
321      * BIN type is really just an uint8_t array internally, it's just
322      * treated specially otherwise.
323      */
324     switch (type) {
325     case RPM_CHAR_TYPE:
326     case RPM_INT8_TYPE:
327         if (retype != RPM_ARRAY_RETURN_TYPE && count > 1) 
328             return 0;
329         /* fallthrough */
330     case RPM_BIN_TYPE:
331         break;
332     default:
333         return 0;
334     }
335     
336     return rpmtdSet(td, tag, type, data, count);
337 }
338
339 int rpmtdFromUint16(rpmtd td, rpmTagVal tag, uint16_t *data, rpm_count_t count)
340 {
341     rpmTagType type = rpmTagGetTagType(tag);
342     rpmTagReturnType retype = rpmTagGetReturnType(tag);
343     if (type != RPM_INT16_TYPE || count < 1) 
344         return 0;
345     if (retype != RPM_ARRAY_RETURN_TYPE && count > 1) 
346         return 0;
347     
348     return rpmtdSet(td, tag, type, data, count);
349 }
350
351 int rpmtdFromUint32(rpmtd td, rpmTagVal tag, uint32_t *data, rpm_count_t count)
352 {
353     rpmTagType type = rpmTagGetTagType(tag);
354     rpmTagReturnType retype = rpmTagGetReturnType(tag);
355     if (type != RPM_INT32_TYPE || count < 1) 
356         return 0;
357     if (retype != RPM_ARRAY_RETURN_TYPE && count > 1) 
358         return 0;
359     
360     return rpmtdSet(td, tag, type, data, count);
361 }
362
363 int rpmtdFromUint64(rpmtd td, rpmTagVal tag, uint64_t *data, rpm_count_t count)
364 {
365     rpmTagType type = rpmTagGetTagType(tag);
366     rpmTagReturnType retype = rpmTagGetReturnType(tag);
367     if (type != RPM_INT64_TYPE || count < 1) 
368         return 0;
369     if (retype != RPM_ARRAY_RETURN_TYPE && count > 1) 
370         return 0;
371     
372     return rpmtdSet(td, tag, type, data, count);
373 }
374
375 int rpmtdFromString(rpmtd td, rpmTagVal tag, const char *data)
376 {
377     rpmTagType type = rpmTagGetTagType(tag);
378     int rc = 0;
379
380     if (type == RPM_STRING_TYPE) {
381         rc = rpmtdSet(td, tag, type, data, 1);
382     } else if (type == RPM_STRING_ARRAY_TYPE) {
383         rc = rpmtdSet(td, tag, type, &data, 1);
384     }
385
386     return rc;
387 }
388
389 int rpmtdFromStringArray(rpmtd td, rpmTagVal tag, const char **data, rpm_count_t count)
390 {
391     rpmTagType type = rpmTagGetTagType(tag);
392     if (type != RPM_STRING_ARRAY_TYPE || count < 1)
393         return 0;
394     if (type == RPM_STRING_TYPE && count != 1)
395         return 0;
396
397     return rpmtdSet(td, tag, type, data, count);
398 }
399
400 int rpmtdFromArgv(rpmtd td, rpmTagVal tag, ARGV_t argv)
401 {
402     int count = argvCount(argv);
403     rpmTagType type = rpmTagGetTagType(tag);
404
405     if (type != RPM_STRING_ARRAY_TYPE || count < 1)
406         return 0;
407
408     return rpmtdSet(td, tag, type, argv, count);
409 }
410
411 int rpmtdFromArgi(rpmtd td, rpmTagVal tag, ARGI_t argi)
412 {
413     int count = argiCount(argi);
414     rpmTagType type = rpmTagGetTagType(tag);
415     rpmTagReturnType retype = rpmTagGetReturnType(tag);
416
417     if (type != RPM_INT32_TYPE || retype != RPM_ARRAY_RETURN_TYPE || count < 1)
418         return 0;
419
420     return rpmtdSet(td, tag, type, argiData(argi), count);
421 }
422
423 rpmtd rpmtdDup(rpmtd td)
424 {
425     rpmtd newtd = NULL;
426     char **data = NULL;
427     int i;
428     
429     assert(td != NULL);
430     /* TODO: permit other types too */
431     if (td->type != RPM_STRING_ARRAY_TYPE && td->type != RPM_I18NSTRING_TYPE) {
432         return NULL;
433     }
434
435     /* deep-copy container and data, drop immutable flag */
436     newtd = rpmtdNew();
437     memcpy(newtd, td, sizeof(*td));
438     newtd->flags &= ~(RPMTD_IMMUTABLE);
439
440     newtd->flags |= (RPMTD_ALLOCED | RPMTD_PTR_ALLOCED);
441     newtd->data = data = xmalloc(td->count * sizeof(*data));
442     while ((i = rpmtdNext(td)) >= 0) {
443         data[i] = xstrdup(rpmtdGetString(td));
444     }
445
446     return newtd;
447 }
448
449 rpmsid * rpmtdToPool(rpmtd td, rpmstrPool pool)
450 {
451     rpmsid *sids = NULL;
452
453     if (pool && td) {
454         const char **strings = td->data;
455         switch (td->type) {
456         case RPM_STRING_ARRAY_TYPE:
457         case RPM_I18NSTRING_TYPE:
458             sids = xmalloc(td->count * sizeof(*sids));
459             for (rpm_count_t i = 0; i < td->count; i++)
460                 sids[i] = rpmstrPoolId(pool, strings[i], 1);
461             break;
462         }
463     }
464     return sids;
465 }