6 #include "rpmio_internal.h"
8 #include <rpmmacro.h> /* XXX for %_i18ndomains */
19 /*@access pgpDigParams @*/
22 * Identify type of trigger.
23 * @param type tag type
24 * @param data tag value
25 * @param formatPrefix (unused)
26 * @param padding (unused)
27 * @param element (unused)
28 * @return formatted string
30 static /*@only@*/ char * triggertypeFormat(int_32 type, const void * data,
31 /*@unused@*/ char * formatPrefix, /*@unused@*/ int padding,
32 /*@unused@*/ int element)
33 /*@requires maxRead(data) >= 0 @*/
35 const int_32 * item = data;
38 if (type != RPM_INT32_TYPE)
39 val = xstrdup(_("(not a number)"));
40 else if (*item & RPMSENSE_TRIGGERPREIN)
41 val = xstrdup("prein");
42 else if (*item & RPMSENSE_TRIGGERIN)
44 else if (*item & RPMSENSE_TRIGGERUN)
46 else if (*item & RPMSENSE_TRIGGERPOSTUN)
47 val = xstrdup("postun");
54 * Format file permissions for display.
55 * @param type tag type
56 * @param data tag value
59 * @param element (unused)
60 * @return formatted string
62 static /*@only@*/ char * permsFormat(int_32 type, const void * data,
63 char * formatPrefix, int padding, /*@unused@*/ int element)
64 /*@modifies formatPrefix @*/
65 /*@requires maxRead(data) >= 0 @*/
70 if (type != RPM_INT32_TYPE) {
71 val = xstrdup(_("(not a number)"));
73 val = xmalloc(15 + padding);
75 strcat(formatPrefix, "s");
77 buf = rpmPermsString(*((int_32 *) data));
79 sprintf(val, formatPrefix, buf);
88 * Format file flags for display.
89 * @param type tag type
90 * @param data tag value
93 * @param element (unused)
94 * @return formatted string
96 static /*@only@*/ char * fflagsFormat(int_32 type, const void * data,
97 char * formatPrefix, int padding, /*@unused@*/ int element)
98 /*@modifies formatPrefix @*/
99 /*@requires maxRead(data) >= 0 @*/
103 int anint = *((int_32 *) data);
105 if (type != RPM_INT32_TYPE) {
106 val = xstrdup(_("(not a number)"));
110 if (anint & RPMFILE_DOC)
112 if (anint & RPMFILE_CONFIG)
114 if (anint & RPMFILE_SPECFILE)
116 if (anint & RPMFILE_MISSINGOK)
118 if (anint & RPMFILE_NOREPLACE)
120 if (anint & RPMFILE_GHOST)
122 if (anint & RPMFILE_LICENSE)
124 if (anint & RPMFILE_README)
128 val = xmalloc(5 + padding);
130 strcat(formatPrefix, "s");
133 sprintf(val, formatPrefix, buf);
141 * Wrap a pubkey in ascii armor for display.
142 * @todo Permit selectable display formats (i.e. binary).
143 * @param type tag type
144 * @param data tag value
145 * @param formatPrefix (unused)
146 * @param padding (unused)
147 * @param element no. bytes of binary data
148 * @return formatted string
150 static /*@only@*/ char * armorFormat(int_32 type, const void * data,
151 /*@unused@*/ char * formatPrefix, /*@unused@*/ int padding,
156 const unsigned char * s;
163 /* XXX HACK ALERT: element field abused as no. bytes of binary data. */
165 atype = PGPARMOR_SIGNATURE; /* XXX check pkt for signature */
167 case RPM_STRING_TYPE:
168 case RPM_STRING_ARRAY_TYPE:
170 if (b64decode(enc, (void **)&s, &ns))
171 return xstrdup(_("(not base64)"));
172 atype = PGPARMOR_PUBKEY; /* XXX check pkt for pubkey */
179 case RPM_I18NSTRING_TYPE:
181 return xstrdup(_("(invalid type)"));
182 /*@notreached@*/ break;
185 /* XXX this doesn't use padding directly, assumes enough slop in retval. */
186 return pgpArmorWrap(atype, s, ns);
190 * Encode binary data in base64 for display.
191 * @todo Permit selectable display formats (i.e. binary).
192 * @param type tag type
193 * @param data tag value
194 * @param formatPrefix (unused)
197 * @return formatted string
199 static /*@only@*/ char * base64Format(int_32 type, const void * data,
200 /*@unused@*/ char * formatPrefix, int padding, int element)
205 if (type != RPM_BIN_TYPE) {
206 val = xstrdup(_("(not a blob)"));
211 /* XXX HACK ALERT: element field abused as no. bytes of binary data. */
213 size_t nt = ((ns + 2) / 3) * 4;
217 /* Add additional bytes necessary for eol string(s). */
218 if (b64encode_chars_per_line > 0 && b64encode_eolstr != NULL) {
219 lc = (nt + b64encode_chars_per_line - 1) / b64encode_chars_per_line;
220 if (((nt + b64encode_chars_per_line - 1) % b64encode_chars_per_line) != 0)
222 nt += lc * strlen(b64encode_eolstr);
226 val = t = xmalloc(nt + padding + 1);
229 if ((enc = b64encode(data, ns)) != NULL) {
241 static size_t xmlstrlen(const char * s)
248 while ((c = *s++) != '\0')
252 case '<': case '>': len += 4; /*@switchbreak@*/ break;
253 case '&': len += 5; /*@switchbreak@*/ break;
254 default: len += 1; /*@switchbreak@*/ break;
262 static char * xmlstrcpy(/*@returned@*/ char * t, const char * s)
269 while ((c = *s++) != '\0') {
271 case '<': te = stpcpy(te, "<"); /*@switchbreak@*/ break;
272 case '>': te = stpcpy(te, ">"); /*@switchbreak@*/ break;
273 case '&': te = stpcpy(te, "&"); /*@switchbreak@*/ break;
274 default: *te++ = c; /*@switchbreak@*/ break;
283 * Wrap tag data in simple header xml markup.
284 * @param type tag type
285 * @param data tag value
286 * @param formatPrefix
288 * @param element (unused)
289 * @return formatted string
292 static /*@only@*/ char * xmlFormat(int_32 type, const void * data,
293 char * formatPrefix, int padding,
294 /*@unused@*/ int element)
295 /*@modifies formatPrefix @*/
297 const char * xtag = NULL;
300 const char * s = NULL;
302 unsigned long anint = 0;
307 case RPM_I18NSTRING_TYPE:
308 case RPM_STRING_TYPE:
313 { int cpl = b64encode_chars_per_line;
315 b64encode_chars_per_line = 0;
318 s = base64Format(type, data, formatPrefix, padding, element);
321 b64encode_chars_per_line = cpl;
327 anint = *((uint_8 *) data);
330 anint = *((uint_16 *) data);
333 anint = *((uint_32 *) data);
336 case RPM_STRING_ARRAY_TYPE:
338 return xstrdup(_("(invalid xml type)"));
339 /*@notreached@*/ break;
346 t = memset(alloca(tlen+1), 0, tlen+1);
347 xx = snprintf(t, tlen, "%lu", anint);
353 nb = 2 * strlen(xtag) + sizeof("\t<></>") + xmlstrlen(s);
355 te = stpcpy( stpcpy( stpcpy(te, "\t<"), xtag), ">");
356 te = xmlstrcpy(te, s);
358 te = stpcpy( stpcpy( stpcpy(te, "</"), xtag), ">");
360 /* XXX s was malloc'd */
362 if (!strcmp(xtag, "base64"))
369 strcat(formatPrefix, "s");
372 xx = snprintf(val, nb, formatPrefix, t);
381 * Display signature fingerprint and time.
382 * @param type tag type
383 * @param data tag value
384 * @param formatPrefix (unused)
386 * @param element (unused)
387 * @return formatted string
389 static /*@only@*/ char * pgpsigFormat(int_32 type, const void * data,
390 /*@unused@*/ char * formatPrefix, /*@unused@*/ int padding,
391 /*@unused@*/ int element)
392 /*@globals fileSystem, internalState @*/
393 /*@modifies fileSystem, internalState @*/
397 if (type != RPM_BIN_TYPE) {
398 val = xstrdup(_("(not a blob)"));
400 unsigned char * pkt = (byte *) data;
401 unsigned int pktlen = 0;
403 unsigned int v = *pkt;
407 unsigned int hlen = 0;
412 plen = pgpLen(pkt+1, &hlen);
414 tag = (v >> 2) & 0xf;
415 plen = (1 << (v & 0x3));
416 hlen = pgpGrab(pkt+1, plen);
419 pktlen = 1 + plen + hlen;
422 if (pktlen == 0 || tag != PGPTAG_SIGNATURE) {
423 val = xstrdup(_("(not an OpenPGP signature)"));
425 pgpDig dig = pgpNewDig();
426 pgpDigParams sigp = &dig->signature;
429 (void) pgpPrtPkts(pkt, pktlen, dig, 0);
431 val = t = xmalloc(nb + 1);
434 switch (sigp->pubkey_algo) {
435 case PGPPUBKEYALGO_DSA:
436 t = stpcpy(t, "DSA");
438 case PGPPUBKEYALGO_RSA:
439 t = stpcpy(t, "RSA");
442 sprintf(t, "%d", sigp->pubkey_algo);
447 switch (sigp->hash_algo) {
448 case PGPHASHALGO_MD5:
449 t = stpcpy(t, "MD5");
451 case PGPHASHALGO_SHA1:
452 t = stpcpy(t, "SHA1");
455 sprintf(t, "%d", sigp->hash_algo);
462 /* this is important if sizeof(int_32) ! sizeof(time_t) */
463 { time_t dateint = pgpGrab(sigp->time, sizeof(sigp->time));
464 struct tm * tstruct = localtime(&dateint);
466 (void) strftime(t, (nb - (t - val)), "%c", tstruct);
469 t = stpcpy(t, ", Key ID ");
470 t = stpcpy(t, pgpHexStr(sigp->signid, sizeof(sigp->signid)));
473 dig = pgpFreeDig(dig);
481 * Format dependency flags for display.
482 * @param type tag type
483 * @param data tag value
484 * @param formatPrefix
486 * @param element (unused)
487 * @return formatted string
489 static /*@only@*/ char * depflagsFormat(int_32 type, const void * data,
490 char * formatPrefix, int padding, /*@unused@*/ int element)
491 /*@modifies formatPrefix @*/
492 /*@requires maxRead(data) >= 0 @*/
498 if (type != RPM_INT32_TYPE) {
499 val = xstrdup(_("(not a number)"));
501 anint = *((int_32 *) data);
505 if (anint & RPMSENSE_LESS)
507 if (anint & RPMSENSE_GREATER)
509 if (anint & RPMSENSE_EQUAL)
513 val = xmalloc(5 + padding);
515 strcat(formatPrefix, "s");
518 sprintf(val, formatPrefix, buf);
526 * Retrieve mounted file system paths.
528 * @retval *type tag type
529 * @retval *data tag value
530 * @retval *count no. of data items
531 * @retval *freeData data-was-malloc'ed indicator
532 * @return 0 on success
534 static int fsnamesTag( /*@unused@*/ Header h, /*@out@*/ int_32 * type,
535 /*@out@*/ void ** data, /*@out@*/ int_32 * count,
536 /*@out@*/ int * freeData)
537 /*@globals fileSystem, internalState @*/
538 /*@modifies *type, *data, *count, *freeData,
539 fileSystem, internalState @*/
540 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
541 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
546 if (rpmGetFilesystemList(&list, count))
550 if (type) *type = RPM_STRING_ARRAY_TYPE;
551 if (data) *((const char ***) data) = list;
552 if (freeData) *freeData = 0;
558 * Retrieve install prefixes.
560 * @retval *type tag type
561 * @retval *data tag value
562 * @retval *count no. of data items
563 * @retval *freeData data-was-malloc'ed indicator
564 * @return 0 on success
566 static int instprefixTag(Header h, /*@null@*/ /*@out@*/ rpmTagType * type,
567 /*@null@*/ /*@out@*/ const void ** data,
568 /*@null@*/ /*@out@*/ int_32 * count,
569 /*@null@*/ /*@out@*/ int * freeData)
570 /*@modifies *type, *data, *freeData @*/
571 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
572 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
574 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
575 HFD_t hfd = headerFreeData;
579 if (hge(h, RPMTAG_INSTALLPREFIX, type, (void **)data, count)) {
580 if (freeData) *freeData = 0;
582 } else if (hge(h, RPMTAG_INSTPREFIXES, &ipt, (void **) &array, count)) {
583 if (type) *type = RPM_STRING_TYPE;
585 if (data) *data = xstrdup(array[0]);
587 if (freeData) *freeData = 1;
588 array = hfd(array, ipt);
596 * Retrieve mounted file system space.
598 * @retval *type tag type
599 * @retval *data tag value
600 * @retval *count no. of data items
601 * @retval *freeData data-was-malloc'ed indicator
602 * @return 0 on success
604 static int fssizesTag(Header h, /*@out@*/ rpmTagType * type,
605 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
606 /*@out@*/ int * freeData)
607 /*@globals rpmGlobalMacroContext,
608 fileSystem, internalState @*/
609 /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext,
610 fileSystem, internalState @*/
611 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
612 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
614 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
615 const char ** filenames;
620 if (!hge(h, RPMTAG_FILESIZES, NULL, (void **) &filesizes, &numFiles)) {
625 rpmfiBuildFNames(h, RPMTAG_BASENAMES, &filenames, &numFiles);
629 if (rpmGetFilesystemList(NULL, count))
633 *type = RPM_INT32_TYPE;
636 if (filenames == NULL) {
637 usages = xcalloc((*count), sizeof(usages));
644 if (rpmGetFilesystemUsage(filenames, filesizes, numFiles, &usages, 0))
650 filenames = _free(filenames);
656 * Retrieve trigger info.
658 * @retval *type tag type
659 * @retval *data tag value
660 * @retval *count no. of data items
661 * @retval *freeData data-was-malloc'ed indicator
662 * @return 0 on success
664 static int triggercondsTag(Header h, /*@out@*/ rpmTagType * type,
665 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
666 /*@out@*/ int * freeData)
667 /*@modifies *type, *data, *count, *freeData @*/
668 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
669 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
671 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
672 HFD_t hfd = headerFreeData;
673 rpmTagType tnt, tvt, tst;
674 int_32 * indices, * flags;
675 char ** names, ** versions;
676 int numNames, numScripts;
678 char * item, * flagsStr;
683 if (!hge(h, RPMTAG_TRIGGERNAME, &tnt, (void **) &names, &numNames)) {
688 xx = hge(h, RPMTAG_TRIGGERINDEX, NULL, (void **) &indices, NULL);
689 xx = hge(h, RPMTAG_TRIGGERFLAGS, NULL, (void **) &flags, NULL);
690 xx = hge(h, RPMTAG_TRIGGERVERSION, &tvt, (void **) &versions, NULL);
691 xx = hge(h, RPMTAG_TRIGGERSCRIPTS, &tst, (void **) &s, &numScripts);
695 *data = conds = xmalloc(sizeof(*conds) * numScripts);
697 *type = RPM_STRING_ARRAY_TYPE;
699 for (i = 0; i < numScripts; i++) {
702 for (j = 0; j < numNames; j++) {
704 /*@innercontinue@*/ continue;
706 item = xmalloc(strlen(names[j]) + strlen(versions[j]) + 20);
707 if (flags[j] & RPMSENSE_SENSEMASK) {
708 buf[0] = '%', buf[1] = '\0';
709 flagsStr = depflagsFormat(RPM_INT32_TYPE, flags, buf, 0, j);
710 sprintf(item, "%s %s %s", names[j], flagsStr, versions[j]);
711 flagsStr = _free(flagsStr);
713 strcpy(item, names[j]);
716 chptr = xrealloc(chptr, strlen(chptr) + strlen(item) + 5);
717 if (*chptr != '\0') strcat(chptr, ", ");
726 names = hfd(names, tnt);
727 versions = hfd(versions, tvt);
733 * Retrieve trigger type info.
735 * @retval *type tag type
736 * @retval *data tag value
737 * @retval *count no. of data items
738 * @retval *freeData data-was-malloc'ed indicator
739 * @return 0 on success
741 static int triggertypeTag(Header h, /*@out@*/ rpmTagType * type,
742 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
743 /*@out@*/ int * freeData)
744 /*@modifies *type, *data, *count, *freeData @*/
745 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
746 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
748 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
749 HFD_t hfd = headerFreeData;
751 int_32 * indices, * flags;
755 int numScripts, numNames;
757 if (!hge(h, RPMTAG_TRIGGERINDEX, NULL, (void **) &indices, &numNames)) {
762 xx = hge(h, RPMTAG_TRIGGERFLAGS, NULL, (void **) &flags, NULL);
763 xx = hge(h, RPMTAG_TRIGGERSCRIPTS, &tst, (void **) &s, &numScripts);
767 *data = conds = xmalloc(sizeof(*conds) * numScripts);
769 *type = RPM_STRING_ARRAY_TYPE;
771 for (i = 0; i < numScripts; i++) {
772 for (j = 0; j < numNames; j++) {
774 /*@innercontinue@*/ continue;
776 if (flags[j] & RPMSENSE_TRIGGERPREIN)
777 conds[i] = xstrdup("prein");
778 else if (flags[j] & RPMSENSE_TRIGGERIN)
779 conds[i] = xstrdup("in");
780 else if (flags[j] & RPMSENSE_TRIGGERUN)
781 conds[i] = xstrdup("un");
782 else if (flags[j] & RPMSENSE_TRIGGERPOSTUN)
783 conds[i] = xstrdup("postun");
785 conds[i] = xstrdup("");
786 /*@innerbreak@*/ break;
795 * Retrieve file paths.
797 * @retval *type tag type
798 * @retval *data tag value
799 * @retval *count no. of data items
800 * @retval *freeData data-was-malloc'ed indicator
801 * @return 0 on success
803 static int filenamesTag(Header h, /*@out@*/ rpmTagType * type,
804 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
805 /*@out@*/ int * freeData)
806 /*@modifies *type, *data, *count, *freeData @*/
807 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
808 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
810 *type = RPM_STRING_ARRAY_TYPE;
812 rpmfiBuildFNames(h, RPMTAG_BASENAMES, (const char ***) data, count);
815 *freeData = 0; /* XXX WTFO? */
821 * Retrieve file classes.
823 * @retval *type tag type
824 * @retval *data tag value
825 * @retval *count no. of data items
826 * @retval *freeData data-was-malloc'ed indicator
827 * @return 0 on success
829 static int fileclassTag(Header h, /*@out@*/ rpmTagType * type,
830 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
831 /*@out@*/ int * freeData)
832 /*@globals fileSystem @*/
833 /*@modifies h, *type, *data, *count, *freeData, fileSystem @*/
834 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
835 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
837 *type = RPM_STRING_ARRAY_TYPE;
838 rpmfiBuildFClasses(h, (const char ***) data, count);
844 * Retrieve file provides.
846 * @retval *type tag type
847 * @retval *data tag value
848 * @retval *count no. of data items
849 * @retval *freeData data-was-malloc'ed indicator
850 * @return 0 on success
852 static int fileprovideTag(Header h, /*@out@*/ rpmTagType * type,
853 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
854 /*@out@*/ int * freeData)
855 /*@globals fileSystem @*/
856 /*@modifies h, *type, *data, *count, *freeData, fileSystem @*/
857 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
858 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
860 *type = RPM_STRING_ARRAY_TYPE;
861 rpmfiBuildFDeps(h, RPMTAG_PROVIDENAME, (const char ***) data, count);
867 * Retrieve file requires.
869 * @retval *type tag type
870 * @retval *data tag value
871 * @retval *count no. of data items
872 * @retval *freeData data-was-malloc'ed indicator
873 * @return 0 on success
875 static int filerequireTag(Header h, /*@out@*/ rpmTagType * type,
876 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
877 /*@out@*/ int * freeData)
878 /*@globals fileSystem @*/
879 /*@modifies h, *type, *data, *count, *freeData, fileSystem @*/
880 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
881 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
883 *type = RPM_STRING_ARRAY_TYPE;
884 rpmfiBuildFDeps(h, RPMTAG_REQUIRENAME, (const char ***) data, count);
889 /* I18N look aside diversions */
891 /*@-exportlocal -exportheadervar@*/
893 int _nl_msg_cat_cntr; /* XXX GNU gettext voodoo */
894 /*@=exportlocal =exportheadervar@*/
895 /*@observer@*/ /*@unchecked@*/
896 static const char * language = "LANGUAGE";
898 /*@observer@*/ /*@unchecked@*/
899 static const char * _macro_i18ndomains = "%{?_i18ndomains}";
902 * Retrieve i18n text.
905 * @retval *type tag type
906 * @retval *data tag value
907 * @retval *count no. of data items
908 * @retval *freeData data-was-malloc'ed indicator
909 * @return 0 on success
911 static int i18nTag(Header h, int_32 tag, /*@out@*/ rpmTagType * type,
912 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
913 /*@out@*/ int * freeData)
914 /*@globals rpmGlobalMacroContext @*/
915 /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
916 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
917 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
919 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
920 char * dstring = rpmExpand(_macro_i18ndomains, NULL);
923 *type = RPM_STRING_TYPE;
928 if (dstring && *dstring) {
930 const char * langval;
934 { const char * tn = tagName(tag);
937 (void) headerNVR(h, &n, NULL, NULL);
938 mk = alloca(strlen(n) + strlen(tn) + sizeof("()"));
939 sprintf(mk, "%s(%s)", n, tn);
943 /* change to en_US for msgkey -> msgid resolution */
944 langval = getenv(language);
945 (void) setenv(language, "en_US", 1);
946 /*@i@*/ ++_nl_msg_cat_cntr;
950 for (domain = dstring; domain != NULL; domain = de) {
951 de = strchr(domain, ':');
952 if (de) *de++ = '\0';
953 msgid = /*@-unrecog@*/ dgettext(domain, msgkey) /*@=unrecog@*/;
954 if (msgid != msgkey) break;
958 /* restore previous environment for msgid -> msgstr resolution */
960 (void) setenv(language, langval, 1);
963 /*@i@*/ ++_nl_msg_cat_cntr;
965 if (domain && msgid) {
966 *data = /*@-unrecog@*/ dgettext(domain, msgid) /*@=unrecog@*/;
967 *data = xstrdup(*data); /* XXX xstrdup has side effects. */
971 dstring = _free(dstring);
976 dstring = _free(dstring);
978 rc = hge(h, tag, type, (void **)data, count);
980 if (rc && (*data) != NULL) {
981 *data = xstrdup(*data);
993 * Retrieve summary text.
995 * @retval *type tag type
996 * @retval *data tag value
997 * @retval *count no. of data items
998 * @retval *freeData data-was-malloc'ed indicator
999 * @return 0 on success
1001 static int summaryTag(Header h, /*@out@*/ rpmTagType * type,
1002 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
1003 /*@out@*/ int * freeData)
1004 /*@globals rpmGlobalMacroContext @*/
1005 /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
1006 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
1007 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
1009 return i18nTag(h, RPMTAG_SUMMARY, type, data, count, freeData);
1013 * Retrieve description text.
1015 * @retval *type tag type
1016 * @retval *data tag value
1017 * @retval *count no. of data items
1018 * @retval *freeData data-was-malloc'ed indicator
1019 * @return 0 on success
1021 static int descriptionTag(Header h, /*@out@*/ rpmTagType * type,
1022 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
1023 /*@out@*/ int * freeData)
1024 /*@globals rpmGlobalMacroContext @*/
1025 /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
1026 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
1027 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
1029 return i18nTag(h, RPMTAG_DESCRIPTION, type, data, count, freeData);
1033 * Retrieve group text.
1035 * @retval *type tag type
1036 * @retval *data tag value
1037 * @retval *count no. of data items
1038 * @retval *freeData data-was-malloc'ed indicator
1039 * @return 0 on success
1041 static int groupTag(Header h, /*@out@*/ rpmTagType * type,
1042 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
1043 /*@out@*/ int * freeData)
1044 /*@globals rpmGlobalMacroContext @*/
1045 /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
1046 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
1047 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
1049 return i18nTag(h, RPMTAG_GROUP, type, data, count, freeData);
1052 /*@-type@*/ /* FIX: cast? */
1053 const struct headerSprintfExtension_s rpmHeaderFormats[] = {
1054 { HEADER_EXT_TAG, "RPMTAG_GROUP", { groupTag } },
1055 { HEADER_EXT_TAG, "RPMTAG_DESCRIPTION", { descriptionTag } },
1056 { HEADER_EXT_TAG, "RPMTAG_SUMMARY", { summaryTag } },
1057 { HEADER_EXT_TAG, "RPMTAG_FILECLASS", { fileclassTag } },
1058 { HEADER_EXT_TAG, "RPMTAG_FILENAMES", { filenamesTag } },
1059 { HEADER_EXT_TAG, "RPMTAG_FILEPROVIDE", { fileprovideTag } },
1060 { HEADER_EXT_TAG, "RPMTAG_FILEREQUIRE", { filerequireTag } },
1061 { HEADER_EXT_TAG, "RPMTAG_FSSIZES", { fssizesTag } },
1062 { HEADER_EXT_TAG, "RPMTAG_FSNAMES", { fsnamesTag } },
1063 { HEADER_EXT_TAG, "RPMTAG_INSTALLPREFIX", { instprefixTag } },
1064 { HEADER_EXT_TAG, "RPMTAG_TRIGGERCONDS", { triggercondsTag } },
1065 { HEADER_EXT_TAG, "RPMTAG_TRIGGERTYPE", { triggertypeTag } },
1066 { HEADER_EXT_FORMAT, "armor", { armorFormat } },
1067 { HEADER_EXT_FORMAT, "base64", { base64Format } },
1068 { HEADER_EXT_FORMAT, "pgpsig", { pgpsigFormat } },
1069 { HEADER_EXT_FORMAT, "depflags", { depflagsFormat } },
1070 { HEADER_EXT_FORMAT, "fflags", { fflagsFormat } },
1071 { HEADER_EXT_FORMAT, "perms", { permsFormat } },
1072 { HEADER_EXT_FORMAT, "permissions", { permsFormat } },
1073 { HEADER_EXT_FORMAT, "triggertype", { triggertypeFormat } },
1074 { HEADER_EXT_FORMAT, "xml", { xmlFormat } },
1075 { HEADER_EXT_MORE, NULL, { (void *) headerDefaultFormats } }