7 #include <rpm/rpmtag.h>
8 #include <rpm/rpmlib.h> /* rpmGetFilesystem*() */
10 #include <rpm/rpmmacro.h> /* XXX for %_i18ndomains */
11 #include <rpm/rpmfi.h>
12 #include <rpm/rpmstring.h>
14 #include "rpmio/digest.h"
15 #include "lib/manifest.h"
20 * Define header tag output formats.
23 struct headerFormatFunc_s {
24 rpmtdFormats fmt; /*!< Value of extension */
25 const char *name; /*!< Name of extension. */
26 void *func; /*!< Pointer to formatter function. */
29 struct headerTagFunc_s {
30 rpmTag tag; /*!< Tag of extension. */
31 void *func; /*!< Pointer to formatter function. */
34 /* forward declarations */
35 static const struct headerFormatFunc_s rpmHeaderFormats[];
36 static const struct headerTagFunc_s rpmHeaderTagExtensions[];
38 void *rpmHeaderFormatFuncByName(const char *fmt);
39 void *rpmHeaderFormatFuncByValue(rpmtdFormats fmt);
40 void *rpmHeaderTagFunc(rpmTag tag);
43 * barebones string representation with no extra formatting
44 * @param td tag data container
45 * @param formatPrefix sprintf format string
46 * @return formatted string
48 static char * stringFormat(rpmtd td, char *formatPrefix)
50 const char *str = NULL;
51 char *val = NULL, *buf = NULL;
53 switch (rpmtdType(td)) {
56 strcat(formatPrefix, "hhu");
57 rasprintf(&val, formatPrefix, *rpmtdGetChar(td));
60 strcat(formatPrefix, "hu");
61 rasprintf(&val, formatPrefix, *rpmtdGetUint16(td));
64 strcat(formatPrefix, "u");
65 rasprintf(&val, formatPrefix, *rpmtdGetUint32(td));
68 case RPM_STRING_ARRAY_TYPE:
69 case RPM_I18NSTRING_TYPE:
70 str = rpmtdGetString(td);
71 strcat(formatPrefix, "s");
72 rasprintf(&val, formatPrefix, str);
75 buf = pgpHexStr(td->data, td->count);
76 strcat(formatPrefix, "s");
77 rasprintf(&val, formatPrefix, buf);
81 val = xstrdup("(unknown type)");
89 * @param td tag data container
90 * @param formatPrefix sprintf format string
91 * @return formatted string
93 static char * octalFormat(rpmtd td, char * formatPrefix)
97 if (rpmtdType(td) != RPM_INT32_TYPE) {
98 val = xstrdup(_("(not a number)"));
100 strcat(formatPrefix, "o");
101 rasprintf(&val, formatPrefix, *rpmtdGetUint32(td));
109 * @param td tag data container
110 * @param formatPrefix sprintf format string
111 * @return formatted string
113 static char * hexFormat(rpmtd td, char * formatPrefix)
117 if (rpmtdType(td) != RPM_INT32_TYPE) {
118 val = xstrdup(_("(not a number)"));
120 strcat(formatPrefix, "x");
121 rasprintf(&val, formatPrefix, *rpmtdGetUint32(td));
128 * @param td tag data container
129 * @param formatPrefix sprintf format string
130 * @return formatted string
132 static char * realDateFormat(rpmtd td, char * formatPrefix,
133 const char * strftimeFormat)
137 if (rpmtdType(td) != RPM_INT32_TYPE) {
138 val = xstrdup(_("(not a number)"));
143 strcat(formatPrefix, "s");
145 /* this is important if sizeof(rpm_time_t) ! sizeof(time_t) */
146 { rpm_time_t *rt = rpmtdGetUint32(td);
147 time_t dateint = *rt;
148 tstruct = localtime(&dateint);
152 (void) strftime(buf, sizeof(buf) - 1, strftimeFormat, tstruct);
153 rasprintf(&val, formatPrefix, buf);
161 * @param td tag data container
162 * @param formatPrefix sprintf format string
163 * @return formatted string
165 static char * dateFormat(rpmtd td, char * formatPrefix)
167 return realDateFormat(td, formatPrefix, _("%c"));
172 * @param td tag data container
173 * @param formatPrefix sprintf format string
174 * @return formatted string
176 static char * dayFormat(rpmtd td, char * formatPrefix)
178 return realDateFormat(td, formatPrefix, _("%a %b %d %Y"));
182 * Return shell escape formatted data.
183 * @param td tag data container
184 * @param formatPrefix sprintf format string
185 * @return formatted string
187 static char * shescapeFormat(rpmtd td, char * formatPrefix)
189 char * result = NULL, * dst, * src;
191 if (rpmtdType(td) == RPM_INT32_TYPE) {
192 strcat(formatPrefix, "d");
193 rasprintf(&result, formatPrefix, *rpmtdGetUint32(td));
196 strcat(formatPrefix, "s");
197 rasprintf(&buf, formatPrefix, rpmtdGetString(td));
199 result = dst = xmalloc(strlen(buf) * 4 + 3);
201 for (src = buf; *src != '\0'; src++) {
221 * Identify type of trigger.
222 * @param td tag data container
223 * @param formatPrefix sprintf format string
224 * @return formatted string
226 static char * triggertypeFormat(rpmtd td, char * formatPrefix)
228 const uint32_t * item = rpmtdGetUint32(td);
231 if (rpmtdType(td) != RPM_INT32_TYPE)
232 val = xstrdup(_("(not a number)"));
233 else if (*item & RPMSENSE_TRIGGERPREIN)
234 val = xstrdup("prein");
235 else if (*item & RPMSENSE_TRIGGERIN)
237 else if (*item & RPMSENSE_TRIGGERUN)
239 else if (*item & RPMSENSE_TRIGGERPOSTUN)
240 val = xstrdup("postun");
247 * Format file permissions for display.
248 * @param td tag data container
249 * @param formatPrefix sprintf format string
250 * @return formatted string
252 static char * permsFormat(rpmtd td, char * formatPrefix)
257 if (rpmtdType(td) != RPM_INT32_TYPE) {
258 val = xstrdup(_("(not a number)"));
260 strcat(formatPrefix, "s");
261 buf = rpmPermsString(*rpmtdGetUint32(td));
262 rasprintf(&val, formatPrefix, buf);
270 * Format file flags for display.
271 * @param td tag data container
272 * @param formatPrefix sprintf format string
273 * @return formatted string
275 static char * fflagsFormat(rpmtd td, char * formatPrefix)
280 if (rpmtdType(td) != RPM_INT32_TYPE) {
281 val = xstrdup(_("(not a number)"));
283 rpm_flag_t *rf = rpmtdGetUint32(td);
284 rpmfileAttrs anint = *rf;
286 if (anint & RPMFILE_DOC)
288 if (anint & RPMFILE_CONFIG)
290 if (anint & RPMFILE_SPECFILE)
292 if (anint & RPMFILE_MISSINGOK)
294 if (anint & RPMFILE_NOREPLACE)
296 if (anint & RPMFILE_GHOST)
298 if (anint & RPMFILE_LICENSE)
300 if (anint & RPMFILE_README)
303 strcat(formatPrefix, "s");
304 rasprintf(&val, formatPrefix, buf);
311 * Wrap a pubkey in ascii armor for display.
312 * @todo Permit selectable display formats (i.e. binary).
313 * @param td tag data container
314 * @param formatPrefix sprintf format string
315 * @return formatted string
317 static char * armorFormat(rpmtd td, char * formatPrefix)
320 const unsigned char * s;
321 unsigned char * bs = NULL;
326 switch (rpmtdType(td)) {
329 /* XXX HACK ALERT: element field abused as no. bytes of binary data. */
331 atype = PGPARMOR_SIGNATURE; /* XXX check pkt for signature */
333 case RPM_STRING_TYPE:
334 case RPM_STRING_ARRAY_TYPE:
335 enc = rpmtdGetString(td);
336 if (b64decode(enc, (void **)&bs, &ns))
337 return xstrdup(_("(not base64)"));
339 atype = PGPARMOR_PUBKEY; /* XXX check pkt for pubkey */
346 case RPM_I18NSTRING_TYPE:
348 return xstrdup(_("(invalid type)"));
352 /* XXX this doesn't use padding directly, assumes enough slop in retval. */
353 val = pgpArmorWrap(atype, s, ns);
354 if (atype == PGPARMOR_PUBKEY) {
361 * Encode binary data in base64 for display.
362 * @todo Permit selectable display formats (i.e. binary).
363 * @param td tag data container
364 * @param formatPrefix sprintf format string
365 * @return formatted string
367 static char * base64Format(rpmtd td, char * formatPrefix)
371 if (rpmtdType(td) != RPM_BIN_TYPE) {
372 val = xstrdup(_("(not a blob)"));
375 if ((enc = b64encode(td->data, td->count, -1)) != NULL) {
376 strcat(formatPrefix, "s");
377 rasprintf(&val, formatPrefix, enc ? enc : "");
386 * Wrap tag data in simple header xml markup.
387 * @param td tag data container
388 * @param formatPrefix sprintf format string
389 * @return formatted string
391 static char * xmlFormat(rpmtd td, char * formatPrefix)
393 const char *xtag = NULL;
396 rpmtdFormats fmt = RPMTD_FORMAT_STRING;
398 switch (rpmtdType(td)) {
399 case RPM_I18NSTRING_TYPE:
400 case RPM_STRING_TYPE:
401 case RPM_STRING_ARRAY_TYPE:
405 fmt = RPMTD_FORMAT_BASE64;
416 return xstrdup(_("(invalid xml type)"));
420 /* XXX TODO: handle errors */
421 s = rpmtdFormat(td, fmt, NULL);
424 val = rstrscat(NULL, "\t<", xtag, "/>", NULL);
427 size_t i, s_size = strlen(s);
429 for (i=0; i<s_size; i++) {
431 case '<': rstrcat(&new_s, "<"); break;
432 case '>': rstrcat(&new_s, ">"); break;
433 case '&': rstrcat(&new_s, "&"); break;
443 val = rstrscat(NULL, "\t<", xtag, ">", new_s, "</", xtag, ">", NULL);
448 strcat(formatPrefix, "s");
453 * Display signature fingerprint and time.
454 * @param td tag data container
455 * @param formatPrefix sprintf format string
456 * @return formatted string
458 static char * pgpsigFormat(rpmtd td, char * formatPrefix)
462 if (rpmtdType(td) != RPM_BIN_TYPE) {
463 val = xstrdup(_("(not a blob)"));
465 const uint8_t * pkt = td->data;
467 unsigned int v = *pkt;
475 plen = pgpLen(pkt+1, &hlen);
477 tag = (v >> 2) & 0xf;
478 plen = (1 << (v & 0x3));
479 hlen = pgpGrab(pkt+1, plen);
482 pktlen = 1 + plen + hlen;
485 if (pktlen == 0 || tag != PGPTAG_SIGNATURE) {
486 val = xstrdup(_("(not an OpenPGP signature)"));
488 pgpDig dig = pgpNewDig();
489 pgpDigParams sigp = &dig->signature;
491 char *tempstr = NULL;
493 (void) pgpPrtPkts(pkt, pktlen, dig, 0);
498 val = t = xrealloc(val, nb + 1);
500 switch (sigp->pubkey_algo) {
501 case PGPPUBKEYALGO_DSA:
502 t = stpcpy(t, "DSA");
504 case PGPPUBKEYALGO_RSA:
505 t = stpcpy(t, "RSA");
508 (void) snprintf(t, nb - (t - val), "%d", sigp->pubkey_algo);
512 if (t + 5 >= val + nb)
515 switch (sigp->hash_algo) {
516 case PGPHASHALGO_MD5:
517 t = stpcpy(t, "MD5");
519 case PGPHASHALGO_SHA1:
520 t = stpcpy(t, "SHA1");
523 (void) snprintf(t, nb - (t - val), "%d", sigp->hash_algo);
527 if (t + strlen (", ") + 1 >= val + nb)
532 /* this is important if sizeof(int32_t) ! sizeof(time_t) */
533 { time_t dateint = pgpGrab(sigp->time, sizeof(sigp->time));
534 struct tm * tstruct = localtime(&dateint);
536 (void) strftime(t, (nb - (t - val)), "%c", tstruct);
539 if (t + strlen (", Key ID ") + 1 >= val + nb)
541 t = stpcpy(t, ", Key ID ");
542 tempstr = pgpHexStr(sigp->signid, sizeof(sigp->signid));
543 if (t + strlen (tempstr) > val + nb)
545 t = stpcpy(t, tempstr);
548 dig = pgpFreeDig(dig);
556 * Format dependency flags for display.
557 * @param td tag data container
558 * @param formatPrefix sprintf format string
559 * @return formatted string
561 static char * depflagsFormat(rpmtd td, char * formatPrefix)
567 if (rpmtdType(td) != RPM_INT32_TYPE) {
568 val = xstrdup(_("(not a number)"));
570 rpm_flag_t *rf = rpmtdGetUint32(td);
574 if (anint & RPMSENSE_LESS)
576 if (anint & RPMSENSE_GREATER)
578 if (anint & RPMSENSE_EQUAL)
581 strcat(formatPrefix, "s");
582 rasprintf(&val, formatPrefix, buf);
589 * Return tag container array size.
590 * @param td tag data container
591 * @param formatPrefix sprintf format string
592 * @return formatted string
594 static char * arraysizeFormat(rpmtd td, char * formatPrefix)
597 strcat(formatPrefix, "u");
598 rasprintf(&val, formatPrefix, rpmtdCount(td));
603 * Retrieve mounted file system paths.
605 * @retval td tag data container
606 * @return 0 on success
608 static int fsnamesTag(Header h, rpmtd td)
612 if (rpmGetFilesystemList(&list, &(td->count)))
615 td->type = RPM_STRING_ARRAY_TYPE;
622 * Retrieve install prefixes.
624 * @retval td tag data container
625 * @return 0 on success
627 static int instprefixTag(Header h, rpmtd td)
629 struct rpmtd_s prefixes;
630 int flags = HEADERGET_MINMEM;
632 if (headerGet(h, RPMTAG_INSTALLPREFIX, td, flags)) {
634 } else if (headerGet(h, RPMTAG_INSTPREFIXES, &prefixes, flags)) {
635 /* only return the first prefix of the array */
636 td->type = RPM_STRING_TYPE;
637 td->data = xstrdup(rpmtdGetString(&prefixes));
638 td->flags = RPMTD_ALLOCED;
639 rpmtdFreeData(&prefixes);
647 * Retrieve mounted file system space.
649 * @retval td tag data container
650 * @return 0 on success
652 static int fssizesTag(Header h, rpmtd td)
654 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
655 const char ** filenames;
656 rpm_off_t * filesizes;
658 rpm_count_t numFiles;
660 if (!hge(h, RPMTAG_FILESIZES, NULL, (rpm_data_t *) &filesizes, &numFiles)) {
665 rpmfiBuildFNames(h, RPMTAG_BASENAMES, &filenames, &numFiles);
668 if (rpmGetFilesystemList(NULL, &(td->count)))
671 td->type = RPM_INT32_TYPE;
672 td->flags = RPMTD_ALLOCED;
674 if (filenames == NULL) {
675 usages = xcalloc((td->count), sizeof(usages));
681 if (rpmGetFilesystemUsage(filenames, filesizes, numFiles, &usages, 0))
686 filenames = _free(filenames);
692 * Retrieve trigger info.
694 * @retval td tag data container
695 * @return 0 on success
697 static int triggercondsTag(Header h, rpmtd td)
703 struct rpmtd_s nametd, indextd, flagtd, versiontd, scripttd;
704 int hgeflags = HEADERGET_MINMEM;
706 td->type = RPM_STRING_ARRAY_TYPE;
707 if (!headerGet(h, RPMTAG_TRIGGERNAME, &nametd, hgeflags)) {
711 headerGet(h, RPMTAG_TRIGGERINDEX, &indextd, hgeflags);
712 headerGet(h, RPMTAG_TRIGGERFLAGS, &flagtd, hgeflags);
713 headerGet(h, RPMTAG_TRIGGERVERSION, &versiontd, hgeflags);
714 headerGet(h, RPMTAG_TRIGGERSCRIPTS, &scripttd, hgeflags);
716 td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED;
717 td->data = conds = xmalloc(sizeof(*conds) * rpmtdCount(&scripttd));
718 td->count = rpmtdCount(&scripttd);
720 indices = indextd.data;
723 while ((i = rpmtdNext(&scripttd)) >= 0) {
725 char *flagStr, *item;
728 rpmtdInit(&nametd); rpmtdInit(&flagtd);
729 while ((j = rpmtdNext(&nametd)) >= 0) {
730 /* flag and version arrays match name array size always */
731 rpmtdNext(&flagtd); rpmtdNext(&versiontd);
736 flag = rpmtdGetUint32(&flagtd);
737 if (*flag & RPMSENSE_SENSEMASK) {
738 flagStr = rpmtdFormat(&flagtd, RPMTD_FORMAT_DEPFLAGS, NULL);
739 rasprintf(&item, "%s %s %s", rpmtdGetString(&nametd),
741 rpmtdGetString(&versiontd));
744 item = xstrdup(rpmtdGetString(&nametd));
747 argvAdd(&items, item);
751 conds[i] = argvJoin(items, ", ");
755 rpmtdFreeData(&nametd);
756 rpmtdFreeData(&versiontd);
757 rpmtdFreeData(&flagtd);
758 rpmtdFreeData(&indextd);
759 rpmtdFreeData(&scripttd);
764 * Retrieve trigger type info.
766 * @retval td tag data container
767 * @return 0 on success
769 static int triggertypeTag(Header h, rpmtd td)
771 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
772 HFD_t hfd = headerFreeData;
778 rpm_count_t numScripts, numNames;
782 if (!hge(h, RPMTAG_TRIGGERINDEX, NULL, (rpm_data_t *) &indices, &numNames)) {
786 xx = hge(h, RPMTAG_TRIGGERFLAGS, NULL, (rpm_data_t *) &flags, NULL);
787 xx = hge(h, RPMTAG_TRIGGERSCRIPTS, &tst, (rpm_data_t *) &s, &numScripts);
790 td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED;
791 td->data = conds = xmalloc(sizeof(*conds) * numScripts);
792 td->count = numScripts;
793 td->type = RPM_STRING_ARRAY_TYPE;
794 for (i = 0; i < numScripts; i++) {
795 for (j = 0; j < numNames; j++) {
799 if (flags[j] & RPMSENSE_TRIGGERPREIN)
800 conds[i] = xstrdup("prein");
801 else if (flags[j] & RPMSENSE_TRIGGERIN)
802 conds[i] = xstrdup("in");
803 else if (flags[j] & RPMSENSE_TRIGGERUN)
804 conds[i] = xstrdup("un");
805 else if (flags[j] & RPMSENSE_TRIGGERPOSTUN)
806 conds[i] = xstrdup("postun");
808 conds[i] = xstrdup("");
817 * Retrieve file paths.
819 * @retval td tag data container
820 * @return 0 on success
822 static int filenamesTag(Header h, rpmtd td)
824 td->type = RPM_STRING_ARRAY_TYPE;
825 rpmfiBuildFNames(h, RPMTAG_BASENAMES,
826 (const char ***) &(td->data), &(td->count));
827 td->flags = RPMTD_ALLOCED;
832 * Retrieve file classes.
834 * @retval td tag data container
835 * @return 0 on success
837 static int fileclassTag(Header h, rpmtd td)
839 td->type = RPM_STRING_ARRAY_TYPE;
840 rpmfiBuildFClasses(h, (const char ***) &(td->data), &(td->count));
841 td->flags = RPMTD_ALLOCED;
846 * Retrieve file provides.
848 * @retval td tag data container
849 * @return 0 on success
851 static int fileprovideTag(Header h, rpmtd td)
853 td->type = RPM_STRING_ARRAY_TYPE;
854 rpmfiBuildFDeps(h, RPMTAG_PROVIDENAME,
855 (const char ***) &(td->data), &(td->count));
856 td->flags = RPMTD_ALLOCED;
861 * Retrieve file requires.
863 * @retval td tag data container
864 * @return 0 on success
866 static int filerequireTag(Header h, rpmtd td)
868 td->type = RPM_STRING_ARRAY_TYPE;
869 rpmfiBuildFDeps(h, RPMTAG_REQUIRENAME,
870 (const char ***) &(td->data), &(td->count));
871 td->flags = RPMTD_ALLOCED;
875 /* I18N look aside diversions */
877 #if defined(ENABLE_NLS)
878 extern int _nl_msg_cat_cntr; /* XXX GNU gettext voodoo */
880 static const char * const language = "LANGUAGE";
882 static const char * const _macro_i18ndomains = "%{?_i18ndomains}";
885 * Retrieve i18n text.
888 * @retval td tag data container
889 * @return 0 on success
891 static int i18nTag(Header h, rpmTag tag, rpmtd td)
893 char * dstring = rpmExpand(_macro_i18ndomains, NULL);
896 td->type = RPM_STRING_TYPE;
900 if (dstring && *dstring) {
902 const char * langval;
908 xx = headerNVR(h, &n, NULL, NULL);
909 rasprintf(&msgkey, "%s(%s)", n, rpmTagGetName(tag));
911 /* change to en_US for msgkey -> msgid resolution */
912 langval = getenv(language);
913 (void) setenv(language, "en_US", 1);
914 #if defined(ENABLE_NLS)
919 for (domain = dstring; domain != NULL; domain = de) {
920 de = strchr(domain, ':');
921 if (de) *de++ = '\0';
922 msgid = dgettext(domain, msgkey);
923 if (msgid != msgkey) break;
926 /* restore previous environment for msgid -> msgstr resolution */
928 (void) setenv(language, langval, 1);
931 #if defined(ENABLE_NLS)
935 if (domain && msgid) {
936 td->data = dgettext(domain, msgid);
937 td->data = xstrdup(td->data); /* XXX xstrdup has side effects. */
939 td->flags = RPMTD_ALLOCED;
941 dstring = _free(dstring);
947 dstring = _free(dstring);
949 rc = headerGet(h, tag, td, HEADERGET_DEFAULT);
950 /* XXX fix the mismatch between headerGet and tag format returns */
955 * Retrieve summary text.
957 * @retval td tag data container
958 * @return 0 on success
960 static int summaryTag(Header h, rpmtd td)
962 return i18nTag(h, RPMTAG_SUMMARY, td);
966 * Retrieve description text.
968 * @retval td tag data container
969 * @return 0 on success
971 static int descriptionTag(Header h, rpmtd td)
973 return i18nTag(h, RPMTAG_DESCRIPTION, td);
977 * Retrieve group text.
979 * @retval td tag data container
980 * @return 0 on success
982 static int groupTag(Header h, rpmtd td)
984 return i18nTag(h, RPMTAG_GROUP, td);
987 void *rpmHeaderTagFunc(rpmTag tag)
989 const struct headerTagFunc_s * ext;
992 for (ext = rpmHeaderTagExtensions; ext->func != NULL; ext++) {
993 if (ext->tag == tag) {
1001 void *rpmHeaderFormatFuncByName(const char *fmt)
1003 const struct headerFormatFunc_s * ext;
1006 for (ext = rpmHeaderFormats; ext->name != NULL; ext++) {
1007 if (!strcmp(ext->name, fmt)) {
1015 void *rpmHeaderFormatFuncByValue(rpmtdFormats fmt)
1017 const struct headerFormatFunc_s * ext;
1020 for (ext = rpmHeaderFormats; ext->name != NULL; ext++) {
1021 if (fmt == ext->fmt) {
1028 static const struct headerTagFunc_s rpmHeaderTagExtensions[] = {
1029 { RPMTAG_GROUP, groupTag },
1030 { RPMTAG_DESCRIPTION, descriptionTag },
1031 { RPMTAG_SUMMARY, summaryTag },
1032 { RPMTAG_FILECLASS, fileclassTag },
1033 { RPMTAG_FILENAMES, filenamesTag },
1034 { RPMTAG_FILEPROVIDE, fileprovideTag },
1035 { RPMTAG_FILEREQUIRE, filerequireTag },
1036 { RPMTAG_FSNAMES, fsnamesTag },
1037 { RPMTAG_FSSIZES, fssizesTag },
1038 { RPMTAG_INSTALLPREFIX, instprefixTag },
1039 { RPMTAG_TRIGGERCONDS, triggercondsTag },
1040 { RPMTAG_TRIGGERTYPE, triggertypeTag },
1044 static const struct headerFormatFunc_s rpmHeaderFormats[] = {
1045 { RPMTD_FORMAT_STRING, "string", stringFormat },
1046 { RPMTD_FORMAT_ARMOR, "armor", armorFormat },
1047 { RPMTD_FORMAT_BASE64, "base64", base64Format },
1048 { RPMTD_FORMAT_PGPSIG, "pgpsig", pgpsigFormat },
1049 { RPMTD_FORMAT_DEPFLAGS, "depflags", depflagsFormat },
1050 { RPMTD_FORMAT_FFLAGS, "fflags", fflagsFormat },
1051 { RPMTD_FORMAT_PERMS, "perms", permsFormat },
1052 { RPMTD_FORMAT_PERMS, "permissions", permsFormat },
1053 { RPMTD_FORMAT_TRIGGERTYPE, "triggertype", triggertypeFormat },
1054 { RPMTD_FORMAT_XML, "xml", xmlFormat },
1055 { RPMTD_FORMAT_OCTAL, "octal", octalFormat },
1056 { RPMTD_FORMAT_HEX, "hex", hexFormat },
1057 { RPMTD_FORMAT_DATE, "date", dateFormat },
1058 { RPMTD_FORMAT_DAY, "day", dayFormat },
1059 { RPMTD_FORMAT_SHESCAPE, "shescape", shescapeFormat },
1060 { RPMTD_FORMAT_ARRAYSIZE, "arraysize", arraysizeFormat },