00001
00005 #include "system.h"
00006
00007 #include "rpmio_internal.h"
00008 #include <rpmlib.h>
00009 #include <rpmmacro.h>
00010
00011 #define _RPMEVR_INTERNAL
00012 #include <rpmds.h>
00013 #include <rpmfi.h>
00014
00015 #include "legacy.h"
00016 #include "manifest.h"
00017 #include "argv.h"
00018 #include "misc.h"
00019 #include "fs.h"
00020
00021 #include "debug.h"
00022
00023
00024
00025
00035 static char * triggertypeFormat(int_32 type, const void * data,
00036 char * formatPrefix, int padding,
00037 int element)
00038
00039 {
00040 const int_32 * item = data;
00041 char * val;
00042
00043 if (type != RPM_INT32_TYPE)
00044 val = xstrdup(_("(invalid type)"));
00045 else if (*item & RPMSENSE_TRIGGERPREIN)
00046 val = xstrdup("prein");
00047 else if (*item & RPMSENSE_TRIGGERIN)
00048 val = xstrdup("in");
00049 else if (*item & RPMSENSE_TRIGGERUN)
00050 val = xstrdup("un");
00051 else if (*item & RPMSENSE_TRIGGERPOSTUN)
00052 val = xstrdup("postun");
00053 else
00054 val = xstrdup("");
00055 return val;
00056 }
00057
00067 static char * permsFormat(int_32 type, const void * data,
00068 char * formatPrefix, int padding, int element)
00069
00070
00071 {
00072 char * val;
00073 char * buf;
00074
00075 if (type != RPM_INT32_TYPE) {
00076 val = xstrdup(_("(invalid type)"));
00077 } else {
00078 val = xmalloc(15 + padding);
00079
00080 strcat(formatPrefix, "s");
00081
00082 buf = rpmPermsString(*((int_32 *) data));
00083
00084 sprintf(val, formatPrefix, buf);
00085
00086 buf = _free(buf);
00087 }
00088
00089 return val;
00090 }
00091
00101 static char * fflagsFormat(int_32 type, const void * data,
00102 char * formatPrefix, int padding, int element)
00103
00104
00105 {
00106 char * val;
00107 char buf[15];
00108 int anint = *((int_32 *) data);
00109
00110 if (type != RPM_INT32_TYPE) {
00111 val = xstrdup(_("(invalid type)"));
00112 } else {
00113 buf[0] = '\0';
00114
00115 if (anint & RPMFILE_DOC)
00116 strcat(buf, "d");
00117 if (anint & RPMFILE_CONFIG)
00118 strcat(buf, "c");
00119 if (anint & RPMFILE_SPECFILE)
00120 strcat(buf, "s");
00121 if (anint & RPMFILE_MISSINGOK)
00122 strcat(buf, "m");
00123 if (anint & RPMFILE_NOREPLACE)
00124 strcat(buf, "n");
00125 if (anint & RPMFILE_GHOST)
00126 strcat(buf, "g");
00127 if (anint & RPMFILE_LICENSE)
00128 strcat(buf, "l");
00129 if (anint & RPMFILE_README)
00130 strcat(buf, "r");
00131
00132
00133 val = xmalloc(5 + padding);
00134
00135 strcat(formatPrefix, "s");
00136
00137
00138 sprintf(val, formatPrefix, buf);
00139
00140 }
00141
00142 return val;
00143 }
00144
00155 static char * armorFormat(int_32 type, const void * data,
00156 char * formatPrefix, int padding,
00157 int element)
00158
00159 {
00160 const char * enc;
00161 const unsigned char * s;
00162 size_t ns;
00163 int atype;
00164
00165 switch (type) {
00166 case RPM_OPENPGP_TYPE:
00167 case RPM_ASN1_TYPE:
00168 case RPM_BIN_TYPE:
00169 s = data;
00170
00171 ns = element;
00172 atype = PGPARMOR_SIGNATURE;
00173 break;
00174 case RPM_STRING_TYPE:
00175 case RPM_STRING_ARRAY_TYPE:
00176 enc = data;
00177 if (b64decode(enc, (void **)&s, &ns))
00178 return xstrdup(_("(not base64)"));
00179 atype = PGPARMOR_PUBKEY;
00180 break;
00181 case RPM_NULL_TYPE:
00182 case RPM_CHAR_TYPE:
00183 case RPM_INT8_TYPE:
00184 case RPM_INT16_TYPE:
00185 case RPM_INT32_TYPE:
00186 case RPM_INT64_TYPE:
00187 case RPM_I18NSTRING_TYPE:
00188 default:
00189 return xstrdup(_("(invalid type)"));
00190 break;
00191 }
00192
00193
00194 return pgpArmorWrap(atype, s, ns);
00195 }
00196
00207 static char * base64Format(int_32 type, const void * data,
00208 char * formatPrefix, int padding, int element)
00209
00210 {
00211 char * val;
00212
00213 if (!(type == RPM_BIN_TYPE || type == RPM_ASN1_TYPE || type == RPM_OPENPGP_TYPE)) {
00214 val = xstrdup(_("(not a blob)"));
00215 } else {
00216 const char * enc;
00217 char * t;
00218 int lc;
00219
00220 size_t ns = element;
00221 size_t nt = ((ns + 2) / 3) * 4;
00222
00223
00224
00225
00226 if (b64encode_chars_per_line > 0 && b64encode_eolstr != NULL) {
00227 lc = (nt + b64encode_chars_per_line - 1) / b64encode_chars_per_line;
00228 if (((nt + b64encode_chars_per_line - 1) % b64encode_chars_per_line) != 0)
00229 ++lc;
00230 nt += lc * strlen(b64encode_eolstr);
00231 }
00232
00233
00234 val = t = xcalloc(1, nt + padding + 1);
00235 *t = '\0';
00236
00237
00238 { unsigned char * _data = xcalloc(1, ns+1);
00239 memcpy(_data, data, ns);
00240 if ((enc = b64encode(_data, ns)) != NULL) {
00241 t = stpcpy(t, enc);
00242 enc = _free(enc);
00243 }
00244 _data = _free(_data);
00245 }
00246
00247 }
00248
00249 return val;
00250 }
00251
00257 static size_t xmlstrlen(const char * s)
00258
00259 {
00260 size_t len = 0;
00261 int c;
00262
00263
00264 while ((c = *s++) != '\0')
00265
00266 {
00267 switch (c) {
00268 case '<':
00269 case '>': len += sizeof("<") - 1; break;
00270 case '&': len += sizeof("&") - 1; break;
00271 default: len += 1; break;
00272 }
00273 }
00274 return len;
00275 }
00276
00283 static char * xmlstrcpy( char * t, const char * s)
00284
00285 {
00286 char * te = t;
00287 int c;
00288
00289
00290 while ((c = *s++) != '\0') {
00291 switch (c) {
00292 case '<': te = stpcpy(te, "<"); break;
00293 case '>': te = stpcpy(te, ">"); break;
00294 case '&': te = stpcpy(te, "&"); break;
00295 default: *te++ = c; break;
00296 }
00297 }
00298 *te = '\0';
00299
00300 return t;
00301 }
00302
00312
00313 static char * xmlFormat(int_32 type, const void * data,
00314 char * formatPrefix, int padding,
00315 int element)
00316
00317 {
00318 const char * xtag = NULL;
00319 size_t nb;
00320 char * val;
00321 const char * s = NULL;
00322 char * t, * te;
00323 unsigned long long anint = 0;
00324 int freeit = 0;
00325 int xx;
00326
00327
00328 switch (type) {
00329 case RPM_I18NSTRING_TYPE:
00330 case RPM_STRING_TYPE:
00331 s = data;
00332 xtag = "string";
00333
00334 s = xstrdup(s);
00335 s = xstrtolocale(s);
00336 freeit = 1;
00337 break;
00338 case RPM_OPENPGP_TYPE:
00339 case RPM_ASN1_TYPE:
00340 case RPM_BIN_TYPE:
00341 { int cpl = b64encode_chars_per_line;
00342
00343 b64encode_chars_per_line = 0;
00344
00345
00346 s = base64Format(type, data, formatPrefix, padding, element);
00347
00348
00349 b64encode_chars_per_line = cpl;
00350
00351 xtag = "base64";
00352 freeit = 1;
00353 } break;
00354 case RPM_CHAR_TYPE:
00355 case RPM_INT8_TYPE:
00356 anint = *((uint_8 *) data);
00357 break;
00358 case RPM_INT16_TYPE:
00359 anint = *((uint_16 *) data);
00360 break;
00361 case RPM_INT32_TYPE:
00362 anint = *((uint_32 *) data);
00363 break;
00364 case RPM_INT64_TYPE:
00365 anint = *((uint_64 *) data);
00366 break;
00367 case RPM_NULL_TYPE:
00368 case RPM_STRING_ARRAY_TYPE:
00369 default:
00370 return xstrdup(_("(invalid xml type)"));
00371 break;
00372 }
00373
00374
00375
00376 if (s == NULL) {
00377 int tlen = 64;
00378 t = memset(alloca(tlen+1), 0, tlen+1);
00379
00380 if (anint != 0)
00381 xx = snprintf(t, tlen, "%llu", anint);
00382
00383 s = t;
00384 xtag = "integer";
00385 }
00386
00387
00388 nb = xmlstrlen(s);
00389 if (nb == 0) {
00390 nb += strlen(xtag) + sizeof("\t</>");
00391 te = t = alloca(nb);
00392 te = stpcpy( stpcpy( stpcpy(te, "\t<"), xtag), "/>");
00393 } else {
00394 nb += 2 * strlen(xtag) + sizeof("\t<></>");
00395 te = t = alloca(nb);
00396 te = stpcpy( stpcpy( stpcpy(te, "\t<"), xtag), ">");
00397 te = xmlstrcpy(te, s);
00398 te += strlen(te);
00399 te = stpcpy( stpcpy( stpcpy(te, "</"), xtag), ">");
00400 }
00401
00402
00403 if (freeit)
00404 s = _free(s);
00405
00406
00407 nb += padding;
00408 val = xmalloc(nb+1);
00409
00410 strcat(formatPrefix, "s");
00411
00412
00413 xx = snprintf(val, nb, formatPrefix, t);
00414
00415 val[nb] = '\0';
00416
00417 return val;
00418 }
00419
00420
00427 static size_t yamlstrlen(const char * s, int lvl)
00428
00429 {
00430 size_t len = 0;
00431 int indent = (lvl > 0);
00432 int c;
00433
00434
00435 while ((c = *s++) != '\0')
00436
00437 {
00438 if (indent) {
00439 len += 2 * lvl;
00440 indent = 0;
00441 }
00442 if (c == '\n')
00443 indent = (lvl > 0);
00444 len++;
00445 }
00446 return len;
00447 }
00448
00456 static char * yamlstrcpy( char * t, const char * s, int lvl)
00457
00458 {
00459 char * te = t;
00460 int indent = (lvl > 0);
00461 int c;
00462
00463
00464 while ((c = *s++) != '\0') {
00465 if (indent) {
00466 int i;
00467 for (i = 0; i < lvl; i++) {
00468 *te++ = ' ';
00469 *te++ = ' ';
00470 }
00471 indent = 0;
00472 }
00473 if (c == '\n')
00474 indent = (lvl > 0);
00475 *te++ = c;
00476 }
00477 *te = '\0';
00478
00479 return t;
00480 }
00481
00491
00492 static char * yamlFormat(int_32 type, const void * data,
00493 char * formatPrefix, int padding,
00494 int element)
00495
00496 {
00497 const char * xtag = NULL;
00498 const char * ytag = NULL;
00499 size_t nb;
00500 char * val;
00501 const char * s = NULL;
00502 char * t, * te;
00503 unsigned long long anint = 0;
00504 int freeit = 0;
00505 int lvl = 0;
00506 int xx;
00507 int c;
00508
00509
00510 switch (type) {
00511 case RPM_I18NSTRING_TYPE:
00512 case RPM_STRING_TYPE:
00513 xx = 0;
00514 s = data;
00515 if (strchr("[", s[0]))
00516 xx = 1;
00517 if (xx == 0)
00518 while ((c = *s++) != '\0') {
00519 switch (c) {
00520 default:
00521 continue;
00522 case '\n':
00523 xx = 1;
00524 break;
00525 case '-':
00526 case ':':
00527 if (s[0] != ' ' && s[0] != '\0' && s[1] != '"')
00528 continue;
00529 xx = 1;
00530 break;
00531 }
00532 break;
00533 }
00534 if (xx) {
00535 if (element >= 0) {
00536 xtag = "- |-\n";
00537 lvl = 3;
00538 } else {
00539 xtag = "|-\n";
00540 lvl = 2;
00541 }
00542 } else {
00543 xtag = (element >= 0 ? "- " : NULL);
00544 }
00545
00546
00547 s = xstrdup(data);
00548 s = xstrtolocale(s);
00549 freeit = 1;
00550 break;
00551 case RPM_OPENPGP_TYPE:
00552 case RPM_ASN1_TYPE:
00553 case RPM_BIN_TYPE:
00554 { int cpl = b64encode_chars_per_line;
00555
00556 b64encode_chars_per_line = 0;
00557
00558
00559 s = base64Format(type, data, formatPrefix, padding, element);
00560 element = -element;
00561
00562
00563 b64encode_chars_per_line = cpl;
00564
00565 xtag = "!!binary ";
00566 freeit = 1;
00567 } break;
00568 case RPM_CHAR_TYPE:
00569 case RPM_INT8_TYPE:
00570 anint = *((uint_8 *) data);
00571 break;
00572 case RPM_INT16_TYPE:
00573 anint = *((uint_16 *) data);
00574 break;
00575 case RPM_INT32_TYPE:
00576 anint = *((uint_32 *) data);
00577 break;
00578 case RPM_INT64_TYPE:
00579 anint = *((uint_64 *) data);
00580 break;
00581 case RPM_NULL_TYPE:
00582 case RPM_STRING_ARRAY_TYPE:
00583 default:
00584 return xstrdup(_("(invalid yaml type)"));
00585 break;
00586 }
00587
00588
00589
00590 if (s == NULL) {
00591 int tlen = 64;
00592 t = memset(alloca(tlen+1), 0, tlen+1);
00593
00594 xx = snprintf(t, tlen, "%llu", anint);
00595
00596 s = t;
00597 xtag = (element >= 0 ? "- " : NULL);
00598 }
00599
00600
00601 nb = yamlstrlen(s, lvl);
00602 if (nb == 0) {
00603 if (element >= 0)
00604 nb += sizeof(" ") - 1;
00605 nb += sizeof("- ~") - 1;
00606 nb++;
00607 te = t = alloca(nb);
00608 if (element >= 0)
00609 te = stpcpy(te, " ");
00610 te = stpcpy(te, "- ~");
00611 } else {
00612 if (element >= 0)
00613 nb += sizeof(" ") - 1;
00614 if (xtag)
00615 nb += strlen(xtag);
00616 if (ytag)
00617 nb += strlen(ytag);
00618 nb++;
00619 te = t = alloca(nb);
00620 if (element >= 0)
00621 te = stpcpy(te, " ");
00622 if (xtag)
00623 te = stpcpy(te, xtag);
00624 te = yamlstrcpy(te, s, lvl);
00625 te += strlen(te);
00626 if (ytag)
00627 te = stpcpy(te, ytag);
00628 }
00629
00630
00631
00632 if (freeit)
00633 s = _free(s);
00634
00635
00636 nb += padding;
00637 val = xmalloc(nb+1);
00638
00639 strcat(formatPrefix, "s");
00640
00641
00642 xx = snprintf(val, nb, formatPrefix, t);
00643
00644 val[nb] = '\0';
00645
00646 return val;
00647 }
00648
00649
00659 static char * pgpsigFormat(int_32 type, const void * data,
00660 char * formatPrefix, int padding,
00661 int element)
00662
00663
00664 {
00665 char * val, * t;
00666
00667 if (!(type == RPM_BIN_TYPE || type == RPM_ASN1_TYPE || type == RPM_OPENPGP_TYPE)) {
00668 val = xstrdup(_("(not a blob)"));
00669 } else {
00670 unsigned char * pkt = (byte *) data;
00671 unsigned int pktlen = 0;
00672
00673 unsigned int v = *pkt;
00674
00675 pgpTag tag = 0;
00676 unsigned int plen;
00677 unsigned int hlen = 0;
00678
00679 if (v & 0x80) {
00680 if (v & 0x40) {
00681 tag = (v & 0x3f);
00682 plen = pgpLen(pkt+1, &hlen);
00683 } else {
00684 tag = (v >> 2) & 0xf;
00685 plen = (1 << (v & 0x3));
00686 hlen = pgpGrab(pkt+1, plen);
00687 }
00688
00689 pktlen = 1 + plen + hlen;
00690 }
00691
00692 if (pktlen == 0 || tag != PGPTAG_SIGNATURE) {
00693 val = xstrdup(_("(not an OpenPGP signature)"));
00694 } else {
00695 pgpDig dig = pgpNewDig();
00696 pgpDigParams sigp = &dig->signature;
00697 size_t nb = 0;
00698 const char *tempstr;
00699
00700 (void) pgpPrtPkts(pkt, pktlen, dig, 0);
00701
00702 val = NULL;
00703 again:
00704 nb += 100;
00705 val = t = xrealloc(val, nb + 1);
00706
00707
00708 switch (sigp->pubkey_algo) {
00709 case PGPPUBKEYALGO_DSA:
00710 t = stpcpy(t, "DSA");
00711 break;
00712 case PGPPUBKEYALGO_RSA:
00713 t = stpcpy(t, "RSA");
00714 break;
00715 default:
00716 (void) snprintf(t, nb - (t - val), "%d", sigp->pubkey_algo);
00717 t += strlen(t);
00718 break;
00719 }
00720 if (t + 5 >= val + nb)
00721 goto again;
00722 *t++ = '/';
00723 switch (sigp->hash_algo) {
00724 case PGPHASHALGO_MD5:
00725 t = stpcpy(t, "MD5");
00726 break;
00727 case PGPHASHALGO_SHA1:
00728 t = stpcpy(t, "SHA1");
00729 break;
00730 default:
00731 (void) snprintf(t, nb - (t - val), "%d", sigp->hash_algo);
00732 t += strlen(t);
00733 break;
00734 }
00735 if (t + strlen (", ") + 1 >= val + nb)
00736 goto again;
00737
00738 t = stpcpy(t, ", ");
00739
00740
00741 { time_t dateint = pgpGrab(sigp->time, sizeof(sigp->time));
00742 struct tm * tstruct = localtime(&dateint);
00743 if (tstruct)
00744 (void) strftime(t, (nb - (t - val)), "%c", tstruct);
00745 }
00746 t += strlen(t);
00747 if (t + strlen (", Key ID ") + 1 >= val + nb)
00748 goto again;
00749 t = stpcpy(t, ", Key ID ");
00750 tempstr = pgpHexStr(sigp->signid, sizeof(sigp->signid));
00751 if (t + strlen (tempstr) > val + nb)
00752 goto again;
00753 t = stpcpy(t, tempstr);
00754
00755
00756 dig = pgpFreeDig(dig);
00757 }
00758 }
00759
00760 return val;
00761 }
00762
00772 static char * depflagsFormat(int_32 type, const void * data,
00773 char * formatPrefix, int padding, int element)
00774
00775
00776 {
00777 char * val;
00778
00779 if (type != RPM_INT32_TYPE) {
00780 val = xstrdup(_("(invalid type)"));
00781 } else {
00782 int anint = *((int_32 *) data);
00783 char *t, *buf;
00784
00785 t = buf = alloca(32);
00786 *t = '\0';
00787
00788
00789 #ifdef NOTYET
00790 if (anint & RPMSENSE_SCRIPT_PRE)
00791 t = stpcpy(t, "(pre)");
00792 if (anint & RPMSENSE_SCRIPT_POST)
00793 t = stpcpy(t, "(post)");
00794 if (anint & RPMSENSE_SCRIPT_PREUN)
00795 t = stpcpy(t, "(preun)");
00796 if (anint & RPMSENSE_SCRIPT_POSTUN)
00797 t = stpcpy(t, "(postun)");
00798 #endif
00799 if (anint & RPMSENSE_SENSEMASK)
00800 *t++ = ' ';
00801 if (anint & RPMSENSE_LESS)
00802 *t++ = '<';
00803 if (anint & RPMSENSE_GREATER)
00804 *t++ = '>';
00805 if (anint & RPMSENSE_EQUAL)
00806 *t++ = '=';
00807 if (anint & RPMSENSE_SENSEMASK)
00808 *t++ = ' ';
00809 *t = '\0';
00810
00811
00812 val = xmalloc(5 + padding);
00813
00814 strcat(formatPrefix, "s");
00815
00816
00817 sprintf(val, formatPrefix, buf);
00818
00819 }
00820
00821 return val;
00822 }
00823
00833 static int fsnamesTag( Header h, int_32 * type,
00834 void ** data, int_32 * count,
00835 int * freeData)
00836
00837
00838
00839
00840
00841 {
00842 const char ** list;
00843
00844
00845 if (rpmGetFilesystemList(&list, count))
00846 return 1;
00847
00848
00849 if (type) *type = RPM_STRING_ARRAY_TYPE;
00850 if (data) *((const char ***) data) = list;
00851 if (freeData) *freeData = 0;
00852
00853 return 0;
00854 }
00855
00865 static int instprefixTag(Header h, rpmTagType * type,
00866 const void ** data,
00867 int_32 * count,
00868 int * freeData)
00869
00870
00871
00872 {
00873 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00874 HFD_t hfd = headerFreeData;
00875 rpmTagType ipt;
00876 char ** array;
00877
00878 if (hge(h, RPMTAG_INSTALLPREFIX, type, data, count)) {
00879 if (freeData) *freeData = 0;
00880 return 0;
00881 } else if (hge(h, RPMTAG_INSTPREFIXES, &ipt, &array, count)) {
00882 if (type) *type = RPM_STRING_TYPE;
00883
00884 if (data) *data = xstrdup(array[0]);
00885
00886 if (freeData) *freeData = 1;
00887 array = hfd(array, ipt);
00888 return 0;
00889 }
00890
00891 return 1;
00892 }
00893
00903 static int fssizesTag(Header h, rpmTagType * type,
00904 const void ** data, int_32 * count,
00905 int * freeData)
00906
00907
00908
00909
00910
00911
00912 {
00913 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00914 const char ** filenames;
00915 int_32 * filesizes;
00916 uint_64 * usages;
00917 int numFiles;
00918
00919 if (!hge(h, RPMTAG_FILESIZES, NULL, &filesizes, &numFiles)) {
00920 filesizes = NULL;
00921 numFiles = 0;
00922 filenames = NULL;
00923 } else {
00924 rpmfiBuildFNames(h, RPMTAG_BASENAMES, &filenames, &numFiles);
00925 }
00926
00927
00928 if (rpmGetFilesystemList(NULL, count))
00929 return 1;
00930
00931
00932 *type = RPM_INT64_TYPE;
00933 *freeData = 1;
00934
00935 if (filenames == NULL) {
00936 usages = xcalloc((*count), sizeof(*usages));
00937 *data = usages;
00938
00939 return 0;
00940 }
00941
00942
00943 if (rpmGetFilesystemUsage(filenames, filesizes, numFiles, &usages, 0))
00944 return 1;
00945
00946
00947 *data = usages;
00948
00949 filenames = _free(filenames);
00950
00951 return 0;
00952 }
00953
00963 static int triggercondsTag(Header h, rpmTagType * type,
00964 const void ** data, int_32 * count,
00965 int * freeData)
00966
00967
00968
00969 {
00970 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00971 HFD_t hfd = headerFreeData;
00972 rpmTagType tnt, tvt, tst;
00973 int_32 * indices, * flags;
00974 char ** names, ** versions;
00975 int numNames, numScripts;
00976 char ** conds, ** s;
00977 char * item, * flagsStr;
00978 char * chptr;
00979 int i, j, xx;
00980 char buf[5];
00981
00982 if (!hge(h, RPMTAG_TRIGGERNAME, &tnt, &names, &numNames)) {
00983 *freeData = 0;
00984 return 0;
00985 }
00986
00987 xx = hge(h, RPMTAG_TRIGGERINDEX, NULL, &indices, NULL);
00988 xx = hge(h, RPMTAG_TRIGGERFLAGS, NULL, &flags, NULL);
00989 xx = hge(h, RPMTAG_TRIGGERVERSION, &tvt, &versions, NULL);
00990 xx = hge(h, RPMTAG_TRIGGERSCRIPTS, &tst, &s, &numScripts);
00991 s = hfd(s, tst);
00992
00993 *freeData = 1;
00994 *data = conds = xmalloc(sizeof(*conds) * numScripts);
00995 *count = numScripts;
00996 *type = RPM_STRING_ARRAY_TYPE;
00997
00998 for (i = 0; i < numScripts; i++) {
00999 chptr = xstrdup("");
01000
01001 for (j = 0; j < numNames; j++) {
01002 if (indices[j] != i)
01003 continue;
01004
01005 item = xmalloc(strlen(names[j]) + strlen(versions[j]) + 20);
01006 if (flags[j] & RPMSENSE_SENSEMASK) {
01007 buf[0] = '%', buf[1] = '\0';
01008 flagsStr = depflagsFormat(RPM_INT32_TYPE, flags, buf, 0, j);
01009 sprintf(item, "%s %s %s", names[j], flagsStr, versions[j]);
01010 flagsStr = _free(flagsStr);
01011 } else {
01012 strcpy(item, names[j]);
01013 }
01014
01015 chptr = xrealloc(chptr, strlen(chptr) + strlen(item) + 5);
01016 if (*chptr != '\0') strcat(chptr, ", ");
01017 strcat(chptr, item);
01018 item = _free(item);
01019 }
01020
01021 conds[i] = chptr;
01022 }
01023
01024
01025 names = hfd(names, tnt);
01026 versions = hfd(versions, tvt);
01027
01028 return 0;
01029 }
01030
01040 static int triggertypeTag(Header h, rpmTagType * type,
01041 const void ** data, int_32 * count,
01042 int * freeData)
01043
01044
01045
01046 {
01047 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
01048 HFD_t hfd = headerFreeData;
01049 rpmTagType tst;
01050 int_32 * indices, * flags;
01051 const char ** conds;
01052 const char ** s;
01053 int i, j, xx;
01054 int numScripts, numNames;
01055
01056 if (!hge(h, RPMTAG_TRIGGERINDEX, NULL, &indices, &numNames)) {
01057 *freeData = 0;
01058 return 1;
01059 }
01060
01061 xx = hge(h, RPMTAG_TRIGGERFLAGS, NULL, &flags, NULL);
01062 xx = hge(h, RPMTAG_TRIGGERSCRIPTS, &tst, &s, &numScripts);
01063 s = hfd(s, tst);
01064
01065 *freeData = 1;
01066 *data = conds = xmalloc(sizeof(*conds) * numScripts);
01067 *count = numScripts;
01068 *type = RPM_STRING_ARRAY_TYPE;
01069
01070 for (i = 0; i < numScripts; i++) {
01071 for (j = 0; j < numNames; j++) {
01072 if (indices[j] != i)
01073 continue;
01074
01075 if (flags[j] & RPMSENSE_TRIGGERPREIN)
01076 conds[i] = xstrdup("prein");
01077 else if (flags[j] & RPMSENSE_TRIGGERIN)
01078 conds[i] = xstrdup("in");
01079 else if (flags[j] & RPMSENSE_TRIGGERUN)
01080 conds[i] = xstrdup("un");
01081 else if (flags[j] & RPMSENSE_TRIGGERPOSTUN)
01082 conds[i] = xstrdup("postun");
01083 else
01084 conds[i] = xstrdup("");
01085 break;
01086 }
01087 }
01088
01089
01090 return 0;
01091 }
01092
01102 static int filenamesTag(Header h, rpmTagType * type,
01103 const void ** data, int_32 * count,
01104 int * freeData)
01105
01106
01107
01108 {
01109 *type = RPM_STRING_ARRAY_TYPE;
01110 rpmfiBuildFNames(h, RPMTAG_BASENAMES, (const char ***) data, count);
01111 *freeData = 1;
01112 return 0;
01113 }
01114
01124 static int fileclassTag(Header h, rpmTagType * type,
01125 const void ** data, int_32 * count,
01126 int * freeData)
01127
01128
01129
01130
01131
01132 {
01133 *type = RPM_STRING_ARRAY_TYPE;
01134 rpmfiBuildFClasses(h, (const char ***) data, count);
01135 *freeData = 1;
01136 return 0;
01137 }
01138
01148 static int filecontextsTag(Header h, rpmTagType * type,
01149 const void ** data, int_32 * count,
01150 int * freeData)
01151
01152
01153
01154
01155
01156 {
01157 *type = RPM_STRING_ARRAY_TYPE;
01158 rpmfiBuildFContexts(h, (const char ***) data, count);
01159 *freeData = 1;
01160 return 0;
01161 }
01162
01172 static int fscontextsTag(Header h, rpmTagType * type,
01173 const void ** data, int_32 * count,
01174 int * freeData)
01175
01176
01177
01178
01179
01180 {
01181 *type = RPM_STRING_ARRAY_TYPE;
01182 rpmfiBuildFSContexts(h, (const char ***) data, count);
01183 *freeData = 1;
01184 return 0;
01185 }
01186
01196 static int recontextsTag(Header h, rpmTagType * type,
01197 const void ** data, int_32 * count,
01198 int * freeData)
01199
01200
01201
01202
01203
01204 {
01205 *type = RPM_STRING_ARRAY_TYPE;
01206 rpmfiBuildREContexts(h, (const char ***) data, count);
01207 *freeData = 1;
01208 return 0;
01209 }
01210
01220 static int fileprovideTag(Header h, rpmTagType * type,
01221 const void ** data, int_32 * count,
01222 int * freeData)
01223
01224
01225
01226
01227
01228 {
01229 *type = RPM_STRING_ARRAY_TYPE;
01230 rpmfiBuildFDeps(h, RPMTAG_PROVIDENAME, (const char ***) data, count);
01231 *freeData = 1;
01232 return 0;
01233 }
01234
01244 static int filerequireTag(Header h, rpmTagType * type,
01245 const void ** data, int_32 * count,
01246 int * freeData)
01247
01248
01249
01250
01251
01252 {
01253 *type = RPM_STRING_ARRAY_TYPE;
01254 rpmfiBuildFDeps(h, RPMTAG_REQUIRENAME, (const char ***) data, count);
01255 *freeData = 1;
01256 return 0;
01257 }
01258
01268 static int missingokTag(Header h, rpmTagType * type,
01269 const void ** data, int_32 * count,
01270 int * freeData)
01271
01272
01273
01274
01275
01276 {
01277 rpmds ds = rpmdsNew(h, RPMTAG_REQUIRENAME, 0);
01278 ARGV_t av = NULL;
01279 ARGV_t argv;
01280 int argc = 0;
01281 char * t;
01282 size_t nb = 0;
01283 int i;
01284
01285 assert(ds != NULL);
01286
01287 ds = rpmdsInit(ds);
01288 if (ds != NULL)
01289 while (rpmdsNext(ds) >= 0) {
01290 int Flags = rpmdsFlags(ds);
01291 const char * DNEVR;
01292 if (!(Flags & RPMSENSE_MISSINGOK))
01293 continue;
01294 DNEVR = rpmdsDNEVR(ds);
01295 if (DNEVR == NULL)
01296 continue;
01297 nb += sizeof(*argv) + strlen(DNEVR+2) + 1;
01298 (void) argvAdd(&av, DNEVR+2);
01299 argc++;
01300 }
01301 nb += sizeof(*argv);
01302
01303
01304 argv = (ARGV_t) xcalloc(nb, 1);
01305 t = (char *)(argv + argc);
01306 for (i = 0; i < argc; i++) {
01307 argv[i] = t;
01308 t = stpcpy(t, av[i]);
01309 *t++ = '\0';
01310 }
01311 av = argvFree(av);
01312 ds = rpmdsFree(ds);
01313
01314
01315
01316 *type = RPM_STRING_ARRAY_TYPE;
01317 *data = argv;
01318 *count = argc;
01319 *freeData = 1;
01320 return 0;
01321 }
01322
01323
01324
01325 #if defined(ENABLE_NLS)
01326
01327
01328 extern int _nl_msg_cat_cntr;
01329
01330 #endif
01331
01332 static const char * language = "LANGUAGE";
01333
01334
01335 static const char * _macro_i18ndomains = "%{?_i18ndomains}";
01336
01347 static int i18nTag(Header h, int_32 tag, rpmTagType * type,
01348 const void ** data, int_32 * count,
01349 int * freeData)
01350
01351
01352
01353
01354 {
01355 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
01356 char * dstring = rpmExpand(_macro_i18ndomains, NULL);
01357 int rc;
01358
01359 *type = RPM_STRING_TYPE;
01360 *data = NULL;
01361 *count = 0;
01362 *freeData = 0;
01363
01364 if (dstring && *dstring) {
01365 char *domain, *de;
01366 const char * langval;
01367 const char * msgkey;
01368 const char * msgid;
01369
01370 { const char * tn = tagName(tag);
01371 const char * n = NULL;
01372 char * mk;
01373 size_t nb = sizeof("()");
01374 int xx = headerNVR(h, &n, NULL, NULL);
01375 xx = 0;
01376 if (tn) nb += strlen(tn);
01377 if (n) nb += strlen(n);
01378 mk = alloca(nb);
01379 sprintf(mk, "%s(%s)", (n?n:""), (tn?tn:""));
01380 msgkey = mk;
01381 }
01382
01383
01384 langval = getenv(language);
01385 (void) setenv(language, "en_US", 1);
01386 #if defined(ENABLE_NLS)
01387 ++_nl_msg_cat_cntr;
01388 #endif
01389
01390 msgid = NULL;
01391
01392 for (domain = dstring; domain != NULL; domain = de) {
01393 de = strchr(domain, ':');
01394 if (de) *de++ = '\0';
01395 msgid = dgettext(domain, msgkey) ;
01396 if (msgid != msgkey) break;
01397 }
01398
01399
01400
01401 if (langval)
01402 (void) setenv(language, langval, 1);
01403 else
01404 unsetenv(language);
01405 #if defined(ENABLE_NLS)
01406 ++_nl_msg_cat_cntr;
01407 #endif
01408
01409 if (domain && msgid) {
01410 *data = dgettext(domain, msgid) ;
01411 *data = xstrdup(*data);
01412 *count = 1;
01413 *freeData = 1;
01414 }
01415 dstring = _free(dstring);
01416 if (*data)
01417 return 0;
01418 }
01419
01420 dstring = _free(dstring);
01421
01422 rc = hge(h, tag, type, (void **)data, count);
01423
01424 if (rc && (*data) != NULL) {
01425 *data = xstrdup(*data);
01426 *data = xstrtolocale(*data);
01427 *freeData = 1;
01428 return 0;
01429 }
01430
01431 *freeData = 0;
01432 *data = NULL;
01433 *count = 0;
01434 return 1;
01435 }
01436
01440 static int localeTag(Header h, int_32 tag, rpmTagType * type,
01441 const void ** data, int_32 * count,
01442 int * freeData)
01443
01444 {
01445 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
01446 rpmTagType t;
01447 char **d, **d2, *dp;
01448 int rc, i, l;
01449
01450 rc = hge(h, tag, &t, &d, count);
01451 if (!rc || d == NULL || *count == 0) {
01452 *freeData = 0;
01453 *data = NULL;
01454 *count = 0;
01455 return 1;
01456 }
01457 if (type)
01458 *type = t;
01459 if (t == RPM_STRING_TYPE) {
01460 d = (char **)xstrdup((char *)d);
01461 d = (char **)xstrtolocale((char *)d);
01462 *freeData = 1;
01463 } else if (t == RPM_STRING_ARRAY_TYPE) {
01464 l = 0;
01465 for (i = 0; i < *count; i++) {
01466 d[i] = xstrdup(d[i]);
01467 d[i] = (char *)xstrtolocale(d[i]);
01468 assert(d[i] != NULL);
01469 l += strlen(d[i]) + 1;
01470 }
01471 d2 = xmalloc(*count * sizeof(*d2) + l);
01472 dp = (char *)(d2 + *count);
01473 for (i = 0; i < *count; i++) {
01474 d2[i] = dp;
01475 strcpy(dp, d[i]);
01476 dp += strlen(dp) + 1;
01477 d[i] = _free(d[i]);
01478 }
01479 d = _free(d);
01480 d = d2;
01481 *freeData = 1;
01482 } else
01483 *freeData = 0;
01484 *data = (void **)d;
01485 return 0;
01486 }
01487
01497 static int summaryTag(Header h, rpmTagType * type,
01498 const void ** data, int_32 * count,
01499 int * freeData)
01500
01501
01502
01503
01504 {
01505 return i18nTag(h, RPMTAG_SUMMARY, type, data, count, freeData);
01506 }
01507
01517 static int descriptionTag(Header h, rpmTagType * type,
01518 const void ** data, int_32 * count,
01519 int * freeData)
01520
01521
01522
01523
01524 {
01525 return i18nTag(h, RPMTAG_DESCRIPTION, type, data, count, freeData);
01526 }
01527
01528 static int changelognameTag(Header h, rpmTagType * type,
01529 const void ** data, int_32 * count,
01530 int * freeData)
01531
01532
01533
01534 {
01535 return localeTag(h, RPMTAG_CHANGELOGNAME, type, data, count, freeData);
01536 }
01537
01538 static int changelogtextTag(Header h, rpmTagType * type,
01539 const void ** data, int_32 * count,
01540 int * freeData)
01541
01542
01543
01544 {
01545 return localeTag(h, RPMTAG_CHANGELOGTEXT, type, data, count, freeData);
01546 }
01547
01557 static int groupTag(Header h, rpmTagType * type,
01558 const void ** data, int_32 * count,
01559 int * freeData)
01560
01561
01562
01563
01564 {
01565 return i18nTag(h, RPMTAG_GROUP, type, data, count, freeData);
01566 }
01567
01568
01569 const struct headerSprintfExtension_s rpmHeaderFormats[] = {
01570 { HEADER_EXT_TAG, "RPMTAG_CHANGELOGNAME", { changelognameTag } },
01571 { HEADER_EXT_TAG, "RPMTAG_CHANGELOGTEXT", { changelogtextTag } },
01572 { HEADER_EXT_TAG, "RPMTAG_DESCRIPTION", { descriptionTag } },
01573 { HEADER_EXT_TAG, "RPMTAG_ENHANCES", { missingokTag } },
01574 { HEADER_EXT_TAG, "RPMTAG_FILECLASS", { fileclassTag } },
01575 { HEADER_EXT_TAG, "RPMTAG_FILECONTEXTS", { filecontextsTag } },
01576 { HEADER_EXT_TAG, "RPMTAG_FILENAMES", { filenamesTag } },
01577 { HEADER_EXT_TAG, "RPMTAG_FILEPROVIDE", { fileprovideTag } },
01578 { HEADER_EXT_TAG, "RPMTAG_FILEREQUIRE", { filerequireTag } },
01579 { HEADER_EXT_TAG, "RPMTAG_FSCONTEXTS", { fscontextsTag } },
01580 { HEADER_EXT_TAG, "RPMTAG_FSNAMES", { fsnamesTag } },
01581 { HEADER_EXT_TAG, "RPMTAG_FSSIZES", { fssizesTag } },
01582 { HEADER_EXT_TAG, "RPMTAG_GROUP", { groupTag } },
01583 { HEADER_EXT_TAG, "RPMTAG_INSTALLPREFIX", { instprefixTag } },
01584 { HEADER_EXT_TAG, "RPMTAG_RECONTEXTS", { recontextsTag } },
01585 { HEADER_EXT_TAG, "RPMTAG_SUGGESTS", { missingokTag } },
01586 { HEADER_EXT_TAG, "RPMTAG_SUMMARY", { summaryTag } },
01587 { HEADER_EXT_TAG, "RPMTAG_TRIGGERCONDS", { triggercondsTag } },
01588 { HEADER_EXT_TAG, "RPMTAG_TRIGGERTYPE", { triggertypeTag } },
01589 { HEADER_EXT_FORMAT, "armor", { armorFormat } },
01590 { HEADER_EXT_FORMAT, "base64", { base64Format } },
01591 { HEADER_EXT_FORMAT, "depflags", { depflagsFormat } },
01592 { HEADER_EXT_FORMAT, "fflags", { fflagsFormat } },
01593 { HEADER_EXT_FORMAT, "perms", { permsFormat } },
01594 { HEADER_EXT_FORMAT, "permissions", { permsFormat } },
01595 { HEADER_EXT_FORMAT, "pgpsig", { pgpsigFormat } },
01596 { HEADER_EXT_FORMAT, "triggertype", { triggertypeFormat } },
01597 { HEADER_EXT_FORMAT, "xml", { xmlFormat } },
01598 { HEADER_EXT_FORMAT, "yaml", { yamlFormat } },
01599 { HEADER_EXT_MORE, NULL, { (void *) headerDefaultFormats } }
01600 } ;
01601