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, h_errno,
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;
811 rpmfiBuildFNames(h, RPMTAG_BASENAMES, (const char ***) data, count);
817 * Retrieve file classes.
819 * @retval *type tag type
820 * @retval *data tag value
821 * @retval *count no. of data items
822 * @retval *freeData data-was-malloc'ed indicator
823 * @return 0 on success
825 static int fileclassTag(Header h, /*@out@*/ rpmTagType * type,
826 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
827 /*@out@*/ int * freeData)
828 /*@globals rpmGlobalMacroContext, h_errno, fileSystem @*/
829 /*@modifies h, *type, *data, *count, *freeData,
830 rpmGlobalMacroContext, fileSystem @*/
831 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
832 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
834 *type = RPM_STRING_ARRAY_TYPE;
835 rpmfiBuildFClasses(h, (const char ***) data, count);
841 * Retrieve file contexts from header.
843 * @retval *type tag type
844 * @retval *data tag value
845 * @retval *count no. of data items
846 * @retval *freeData data-was-malloc'ed indicator
847 * @return 0 on success
849 static int filecontextsTag(Header h, /*@out@*/ rpmTagType * type,
850 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
851 /*@out@*/ int * freeData)
852 /*@globals rpmGlobalMacroContext, h_errno, fileSystem @*/
853 /*@modifies h, *type, *data, *count, *freeData,
854 rpmGlobalMacroContext, fileSystem @*/
855 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
856 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
858 *type = RPM_STRING_ARRAY_TYPE;
859 rpmfiBuildFContexts(h, (const char ***) data, count);
865 * Retrieve file contexts from file system.
867 * @retval *type tag type
868 * @retval *data tag value
869 * @retval *count no. of data items
870 * @retval *freeData data-was-malloc'ed indicator
871 * @return 0 on success
873 static int fscontextsTag(Header h, /*@out@*/ rpmTagType * type,
874 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
875 /*@out@*/ int * freeData)
876 /*@globals rpmGlobalMacroContext, h_errno, fileSystem @*/
877 /*@modifies h, *type, *data, *count, *freeData,
878 rpmGlobalMacroContext, fileSystem @*/
879 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
880 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
882 *type = RPM_STRING_ARRAY_TYPE;
883 rpmfiBuildFSContexts(h, (const char ***) data, count);
889 * Retrieve file contexts from policy RE's.
891 * @retval *type tag type
892 * @retval *data tag value
893 * @retval *count no. of data items
894 * @retval *freeData data-was-malloc'ed indicator
895 * @return 0 on success
897 static int recontextsTag(Header h, /*@out@*/ rpmTagType * type,
898 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
899 /*@out@*/ int * freeData)
900 /*@globals rpmGlobalMacroContext, h_errno, fileSystem @*/
901 /*@modifies h, *type, *data, *count, *freeData,
902 rpmGlobalMacroContext, fileSystem @*/
903 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
904 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
906 *type = RPM_STRING_ARRAY_TYPE;
907 rpmfiBuildREContexts(h, (const char ***) data, count);
913 * Retrieve file provides.
915 * @retval *type tag type
916 * @retval *data tag value
917 * @retval *count no. of data items
918 * @retval *freeData data-was-malloc'ed indicator
919 * @return 0 on success
921 static int fileprovideTag(Header h, /*@out@*/ rpmTagType * type,
922 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
923 /*@out@*/ int * freeData)
924 /*@globals rpmGlobalMacroContext, h_errno, fileSystem @*/
925 /*@modifies h, *type, *data, *count, *freeData,
926 rpmGlobalMacroContext, fileSystem @*/
927 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
928 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
930 *type = RPM_STRING_ARRAY_TYPE;
931 rpmfiBuildFDeps(h, RPMTAG_PROVIDENAME, (const char ***) data, count);
937 * Retrieve file requires.
939 * @retval *type tag type
940 * @retval *data tag value
941 * @retval *count no. of data items
942 * @retval *freeData data-was-malloc'ed indicator
943 * @return 0 on success
945 static int filerequireTag(Header h, /*@out@*/ rpmTagType * type,
946 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
947 /*@out@*/ int * freeData)
948 /*@globals rpmGlobalMacroContext, h_errno, fileSystem @*/
949 /*@modifies h, *type, *data, *count, *freeData,
950 rpmGlobalMacroContext, fileSystem @*/
951 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
952 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
954 *type = RPM_STRING_ARRAY_TYPE;
955 rpmfiBuildFDeps(h, RPMTAG_REQUIRENAME, (const char ***) data, count);
960 /* I18N look aside diversions */
962 /*@-exportlocal -exportheadervar@*/
964 int _nl_msg_cat_cntr; /* XXX GNU gettext voodoo */
965 /*@=exportlocal =exportheadervar@*/
966 /*@observer@*/ /*@unchecked@*/
967 static const char * language = "LANGUAGE";
969 /*@observer@*/ /*@unchecked@*/
970 static const char * _macro_i18ndomains = "%{?_i18ndomains}";
973 * Retrieve i18n text.
976 * @retval *type tag type
977 * @retval *data tag value
978 * @retval *count no. of data items
979 * @retval *freeData data-was-malloc'ed indicator
980 * @return 0 on success
982 static int i18nTag(Header h, int_32 tag, /*@out@*/ rpmTagType * type,
983 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
984 /*@out@*/ int * freeData)
985 /*@globals rpmGlobalMacroContext, h_errno @*/
986 /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
987 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
988 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
990 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
991 char * dstring = rpmExpand(_macro_i18ndomains, NULL);
994 *type = RPM_STRING_TYPE;
999 if (dstring && *dstring) {
1001 const char * langval;
1002 const char * msgkey;
1005 { const char * tn = tagName(tag);
1008 (void) headerNVR(h, &n, NULL, NULL);
1009 mk = alloca(strlen(n) + strlen(tn) + sizeof("()"));
1010 sprintf(mk, "%s(%s)", n, tn);
1014 /* change to en_US for msgkey -> msgid resolution */
1015 langval = getenv(language);
1016 (void) setenv(language, "en_US", 1);
1017 /*@i@*/ ++_nl_msg_cat_cntr;
1021 for (domain = dstring; domain != NULL; domain = de) {
1022 de = strchr(domain, ':');
1023 if (de) *de++ = '\0';
1024 msgid = /*@-unrecog@*/ dgettext(domain, msgkey) /*@=unrecog@*/;
1025 if (msgid != msgkey) break;
1029 /* restore previous environment for msgid -> msgstr resolution */
1031 (void) setenv(language, langval, 1);
1034 /*@i@*/ ++_nl_msg_cat_cntr;
1036 if (domain && msgid) {
1037 *data = /*@-unrecog@*/ dgettext(domain, msgid) /*@=unrecog@*/;
1038 *data = xstrdup(*data); /* XXX xstrdup has side effects. */
1042 dstring = _free(dstring);
1047 dstring = _free(dstring);
1049 rc = hge(h, tag, type, (void **)data, count);
1051 if (rc && (*data) != NULL) {
1052 *data = xstrdup(*data);
1064 * Retrieve summary text.
1066 * @retval *type tag type
1067 * @retval *data tag value
1068 * @retval *count no. of data items
1069 * @retval *freeData data-was-malloc'ed indicator
1070 * @return 0 on success
1072 static int summaryTag(Header h, /*@out@*/ rpmTagType * type,
1073 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
1074 /*@out@*/ int * freeData)
1075 /*@globals rpmGlobalMacroContext, h_errno @*/
1076 /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
1077 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
1078 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
1080 return i18nTag(h, RPMTAG_SUMMARY, type, data, count, freeData);
1084 * Retrieve description text.
1086 * @retval *type tag type
1087 * @retval *data tag value
1088 * @retval *count no. of data items
1089 * @retval *freeData data-was-malloc'ed indicator
1090 * @return 0 on success
1092 static int descriptionTag(Header h, /*@out@*/ rpmTagType * type,
1093 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
1094 /*@out@*/ int * freeData)
1095 /*@globals rpmGlobalMacroContext, h_errno @*/
1096 /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
1097 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
1098 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
1100 return i18nTag(h, RPMTAG_DESCRIPTION, type, data, count, freeData);
1104 * Retrieve group text.
1106 * @retval *type tag type
1107 * @retval *data tag value
1108 * @retval *count no. of data items
1109 * @retval *freeData data-was-malloc'ed indicator
1110 * @return 0 on success
1112 static int groupTag(Header h, /*@out@*/ rpmTagType * type,
1113 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
1114 /*@out@*/ int * freeData)
1115 /*@globals rpmGlobalMacroContext, h_errno @*/
1116 /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
1117 /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
1118 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
1120 return i18nTag(h, RPMTAG_GROUP, type, data, count, freeData);
1123 /*@-type@*/ /* FIX: cast? */
1124 const struct headerSprintfExtension_s rpmHeaderFormats[] = {
1125 { HEADER_EXT_TAG, "RPMTAG_GROUP", { groupTag } },
1126 { HEADER_EXT_TAG, "RPMTAG_DESCRIPTION", { descriptionTag } },
1127 { HEADER_EXT_TAG, "RPMTAG_SUMMARY", { summaryTag } },
1128 { HEADER_EXT_TAG, "RPMTAG_FILECLASS", { fileclassTag } },
1129 { HEADER_EXT_TAG, "RPMTAG_FILECONTEXTS", { filecontextsTag } },
1130 { HEADER_EXT_TAG, "RPMTAG_FILENAMES", { filenamesTag } },
1131 { HEADER_EXT_TAG, "RPMTAG_FILEPROVIDE", { fileprovideTag } },
1132 { HEADER_EXT_TAG, "RPMTAG_FILEREQUIRE", { filerequireTag } },
1133 { HEADER_EXT_TAG, "RPMTAG_FSCONTEXTS", { fscontextsTag } },
1134 { HEADER_EXT_TAG, "RPMTAG_FSNAMES", { fsnamesTag } },
1135 { HEADER_EXT_TAG, "RPMTAG_FSSIZES", { fssizesTag } },
1136 { HEADER_EXT_TAG, "RPMTAG_INSTALLPREFIX", { instprefixTag } },
1137 { HEADER_EXT_TAG, "RPMTAG_RECONTEXTS", { recontextsTag } },
1138 { HEADER_EXT_TAG, "RPMTAG_TRIGGERCONDS", { triggercondsTag } },
1139 { HEADER_EXT_TAG, "RPMTAG_TRIGGERTYPE", { triggertypeTag } },
1140 { HEADER_EXT_FORMAT, "armor", { armorFormat } },
1141 { HEADER_EXT_FORMAT, "base64", { base64Format } },
1142 { HEADER_EXT_FORMAT, "pgpsig", { pgpsigFormat } },
1143 { HEADER_EXT_FORMAT, "depflags", { depflagsFormat } },
1144 { HEADER_EXT_FORMAT, "fflags", { fflagsFormat } },
1145 { HEADER_EXT_FORMAT, "perms", { permsFormat } },
1146 { HEADER_EXT_FORMAT, "permissions", { permsFormat } },
1147 { HEADER_EXT_FORMAT, "triggertype", { triggertypeFormat } },
1148 { HEADER_EXT_FORMAT, "xml", { xmlFormat } },
1149 { HEADER_EXT_MORE, NULL, { (void *) headerDefaultFormats } }