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