00001
00005 #include "system.h"
00006
00007
00008 #if defined(HAVE_ICONV)
00009 #include <iconv.h>
00010 #if defined(__LCLINT__)
00011
00012 extern iconv_t iconv_open(const char *__tocode, const char *__fromcode)
00013 ;
00014
00015 extern size_t iconv(iconv_t __cd, char ** __inbuf,
00016 size_t * __inbytesleft,
00017 char ** __outbuf,
00018 size_t * __outbytesleft)
00019
00020 ;
00021
00022 extern int iconv_close( iconv_t __cd)
00023 ;
00024
00025 #endif
00026 #endif
00027
00028 #if defined(HAVE_LANGINFO_H)
00029 #include <langinfo.h>
00030 #if defined(__LCLINT__)
00031
00032 extern char *nl_langinfo (nl_item __item)
00033 ;
00034
00035 #endif
00036 #endif
00037
00038 #define _MIRE_INTERNAL
00039 #include "rpmio_internal.h"
00040 #include <rpmbc.h>
00041 #include <rpmcb.h>
00042 #include <rpmmacro.h>
00043 #include <rpmuuid.h>
00044 #include <argv.h>
00045 #include <ugid.h>
00046
00047 #define _RPMTAG_INTERNAL
00048 #include <rpmtag.h>
00049 #define _RPMEVR_INTERNAL
00050 #include <rpmevr.h>
00051 #include <rpmns.h>
00052 #include <rpmdb.h>
00053
00054 #include <rpmtypes.h>
00055 #include "misc.h"
00056 #include <rpmfi.h>
00057
00058 #include "legacy.h"
00059 #include "misc.h"
00060
00061 #include "debug.h"
00062
00063
00064 int _hdrqf_debug;
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00082 static char * intFormat(HE_t he, const char ** av,
00083 const char *fmt)
00084
00085 {
00086 rpmuint32_t ix = (he->ix > 0 ? he->ix : 0);
00087 rpmuint64_t ival = 0;
00088 const char * istr = NULL;
00089 char * b;
00090 size_t nb = 0;
00091 int xx;
00092
00093 if (fmt == NULL || *fmt == '\0')
00094 fmt = "d";
00095
00096 switch (he->t) {
00097 default:
00098 return xstrdup(_("(not a number)"));
00099 break;
00100 case RPM_UINT8_TYPE:
00101 ival = (rpmuint64_t) he->p.ui8p[ix];
00102 break;
00103 case RPM_UINT16_TYPE:
00104 ival = (rpmuint64_t) he->p.ui16p[ix];
00105 break;
00106 case RPM_UINT32_TYPE:
00107 ival = (rpmuint64_t) he->p.ui32p[ix];
00108 break;
00109 case RPM_UINT64_TYPE:
00110 ival = he->p.ui64p[ix];
00111 break;
00112 case RPM_STRING_TYPE:
00113 istr = he->p.str;
00114 break;
00115 case RPM_STRING_ARRAY_TYPE:
00116 istr = he->p.argv[ix];
00117 break;
00118 case RPM_BIN_TYPE:
00119 { static char hex[] = "0123456789abcdef";
00120 const char * s = he->p.str;
00121 rpmTagCount c = he->c;
00122 char * t;
00123
00124 nb = 2 * c + 1;
00125 t = b = alloca(nb+1);
00126 while (c-- > 0) {
00127 unsigned i;
00128 i = (unsigned) *s++;
00129 *t++ = hex[ (i >> 4) & 0xf ];
00130 *t++ = hex[ (i ) & 0xf ];
00131 }
00132 *t = '\0';
00133 } break;
00134 }
00135
00136 if (istr) {
00137 b = (char *)istr;
00138 } else
00139 if (nb == 0) {
00140 char myfmt[] = "%llX";
00141 myfmt[3] = ((fmt != NULL && *fmt != '\0') ? *fmt : 'd');
00142 nb = 64;
00143 b = alloca(nb);
00144
00145 xx = snprintf(b, nb, myfmt, ival);
00146
00147 b[nb-1] = '\0';
00148 }
00149
00150 return xstrdup(b);
00151 }
00152
00159 static char * octFormat(HE_t he, const char ** av)
00160
00161 {
00162 return intFormat(he, av, "o");
00163 }
00164
00171 static char * hexFormat(HE_t he, const char ** av)
00172
00173 {
00174 return intFormat(he, av, "x");
00175 }
00176
00183 static char * decFormat(HE_t he, const char ** av)
00184
00185 {
00186 return intFormat(he, av, "d");
00187 }
00188
00196 static char * realDateFormat(HE_t he, const char ** av,
00197 const char * strftimeFormat)
00198
00199 {
00200 char * val;
00201
00202 if (he->t != RPM_UINT64_TYPE) {
00203 val = xstrdup(_("(not a number)"));
00204 } else {
00205 struct tm * tstruct;
00206 char buf[50];
00207
00208
00209 { time_t dateint = he->p.ui64p[0];
00210 tstruct = localtime(&dateint);
00211 }
00212 buf[0] = '\0';
00213 if (tstruct)
00214 (void) strftime(buf, sizeof(buf) - 1, strftimeFormat, tstruct);
00215 buf[sizeof(buf) - 1] = '\0';
00216 val = xstrdup(buf);
00217 }
00218
00219 return val;
00220 }
00221
00228 static char * dateFormat(HE_t he, const char ** av)
00229
00230 {
00231 return realDateFormat(he, av, _("%c"));
00232 }
00233
00240 static char * dayFormat(HE_t he, const char ** av)
00241
00242 {
00243 return realDateFormat(he, av, _("%a %b %d %Y"));
00244 }
00245
00252 static char * shescapeFormat(HE_t he, const char ** av)
00253
00254 {
00255 char * val;
00256 size_t nb;
00257 int xx;
00258
00259
00260 if (he->t == RPM_UINT32_TYPE) {
00261 nb = 20;
00262 val = xmalloc(nb);
00263 xx = snprintf(val, nb, "%u", (unsigned) he->p.ui32p[0]);
00264 val[nb-1] = '\0';
00265 } else if (he->t == RPM_UINT64_TYPE) {
00266 nb = 40;
00267 val = xmalloc(40);
00268
00269 xx = snprintf(val, nb, "%llu", (unsigned long long)he->p.ui64p[0]);
00270
00271 val[nb-1] = '\0';
00272 } else if (he->t == RPM_STRING_TYPE) {
00273 const char * s = he->p.str;
00274 char * t;
00275 int c;
00276
00277 nb = 0;
00278 for (s = he->p.str; (c = (int)*s) != 0; s++) {
00279 nb++;
00280 if (c == (int)'\'')
00281 nb += 3;
00282 }
00283 nb += 3;
00284 t = val = xmalloc(nb);
00285 *t++ = '\'';
00286 for (s = he->p.str; (c = (int)*s) != 0; s++) {
00287 if (c == (int)'\'') {
00288 *t++ = '\'';
00289 *t++ = '\\';
00290 *t++ = '\'';
00291 }
00292 *t++ = (char) c;
00293 }
00294 *t++ = '\'';
00295 *t = '\0';
00296 } else
00297 val = xstrdup(_("invalid type"));
00298
00299 return val;
00300 }
00301
00302 static struct headerSprintfExtension_s _headerDefaultFormats[] = {
00303 { HEADER_EXT_FORMAT, "octal",
00304 { .fmtFunction = octFormat } },
00305 { HEADER_EXT_FORMAT, "oct",
00306 { .fmtFunction = octFormat } },
00307 { HEADER_EXT_FORMAT, "hex",
00308 { .fmtFunction = hexFormat } },
00309 { HEADER_EXT_FORMAT, "decimal",
00310 { .fmtFunction = decFormat } },
00311 { HEADER_EXT_FORMAT, "dec",
00312 { .fmtFunction = decFormat } },
00313 { HEADER_EXT_FORMAT, "date",
00314 { .fmtFunction = dateFormat } },
00315 { HEADER_EXT_FORMAT, "day",
00316 { .fmtFunction = dayFormat } },
00317 { HEADER_EXT_FORMAT, "shescape",
00318 { .fmtFunction = shescapeFormat } },
00319 { HEADER_EXT_LAST, NULL, { NULL } }
00320 };
00321
00322 headerSprintfExtension headerDefaultFormats = &_headerDefaultFormats[0];
00323
00324
00325 static char * rpmPermsString(int mode)
00326
00327 {
00328 char *perms = xstrdup("----------");
00329
00330 if (S_ISREG(mode))
00331 perms[0] = '-';
00332 else if (S_ISDIR(mode))
00333 perms[0] = 'd';
00334 else if (S_ISLNK(mode))
00335 perms[0] = 'l';
00336 else if (S_ISFIFO(mode))
00337 perms[0] = 'p';
00338
00339 else if (S_ISSOCK(mode))
00340 perms[0] = 's';
00341
00342 else if (S_ISCHR(mode))
00343 perms[0] = 'c';
00344 else if (S_ISBLK(mode))
00345 perms[0] = 'b';
00346 else
00347 perms[0] = '?';
00348
00349 if (mode & S_IRUSR) perms[1] = 'r';
00350 if (mode & S_IWUSR) perms[2] = 'w';
00351 if (mode & S_IXUSR) perms[3] = 'x';
00352
00353 if (mode & S_IRGRP) perms[4] = 'r';
00354 if (mode & S_IWGRP) perms[5] = 'w';
00355 if (mode & S_IXGRP) perms[6] = 'x';
00356
00357 if (mode & S_IROTH) perms[7] = 'r';
00358 if (mode & S_IWOTH) perms[8] = 'w';
00359 if (mode & S_IXOTH) perms[9] = 'x';
00360
00361 if (mode & S_ISUID)
00362 perms[3] = ((mode & S_IXUSR) ? 's' : 'S');
00363
00364 if (mode & S_ISGID)
00365 perms[6] = ((mode & S_IXGRP) ? 's' : 'S');
00366
00367 if (mode & S_ISVTX)
00368 perms[9] = ((mode & S_IXOTH) ? 't' : 'T');
00369
00370 return perms;
00371 }
00372
00379 static char * triggertypeFormat(HE_t he, const char ** av)
00380
00381 {
00382 int ix = (he->ix > 0 ? he->ix : 0);
00383 char * val;
00384
00385 assert(ix == 0);
00386 if (he->t != RPM_UINT64_TYPE)
00387 val = xstrdup(_("(invalid type)"));
00388 else {
00389 rpmuint64_t anint = he->p.ui64p[ix];
00390 if (anint & RPMSENSE_TRIGGERPREIN)
00391 val = xstrdup("prein");
00392 else if (anint & RPMSENSE_TRIGGERIN)
00393 val = xstrdup("in");
00394 else if (anint & RPMSENSE_TRIGGERUN)
00395 val = xstrdup("un");
00396 else if (anint & RPMSENSE_TRIGGERPOSTUN)
00397 val = xstrdup("postun");
00398 else
00399 val = xstrdup("");
00400 }
00401 return val;
00402 }
00403
00410 static char * permsFormat(HE_t he, const char ** av)
00411
00412 {
00413 int ix = (he->ix > 0 ? he->ix : 0);
00414 char * val;
00415
00416 assert(ix == 0);
00417 if (he->t != RPM_UINT64_TYPE) {
00418 val = xstrdup(_("(invalid type)"));
00419 } else {
00420 rpmuint64_t anint = he->p.ui64p[0];
00421 val = rpmPermsString((int)anint);
00422 }
00423
00424 return val;
00425 }
00426
00433 static char * fflagsFormat(HE_t he, const char ** av)
00434
00435 {
00436 int ix = (he->ix >= 0 ? he->ix : 0);
00437 char * val;
00438
00439 assert(ix == 0);
00440 if (he->t != RPM_UINT64_TYPE) {
00441 val = xstrdup(_("(invalid type)"));
00442 } else {
00443 char buf[15];
00444 rpmuint64_t anint = he->p.ui64p[ix];
00445 buf[0] = '\0';
00446 if (anint & RPMFILE_DOC)
00447 strcat(buf, "d");
00448 if (anint & RPMFILE_CONFIG)
00449 strcat(buf, "c");
00450 if (anint & RPMFILE_SPECFILE)
00451 strcat(buf, "s");
00452 if (anint & RPMFILE_MISSINGOK)
00453 strcat(buf, "m");
00454 if (anint & RPMFILE_NOREPLACE)
00455 strcat(buf, "n");
00456 if (anint & RPMFILE_GHOST)
00457 strcat(buf, "g");
00458 if (anint & RPMFILE_LICENSE)
00459 strcat(buf, "l");
00460 if (anint & RPMFILE_README)
00461 strcat(buf, "r");
00462 val = xstrdup(buf);
00463 }
00464
00465 return val;
00466 }
00467
00475 static char * armorFormat(HE_t he, const char ** av)
00476
00477 {
00478 int ix = (he->ix > 0 ? he->ix : 0);
00479 const char * enc;
00480 const unsigned char * s;
00481 size_t ns;
00482 rpmuint8_t atype;
00483 char * val;
00484
00485 assert(ix == 0);
00486 switch (he->t) {
00487 case RPM_BIN_TYPE:
00488 s = (unsigned char *) he->p.ui8p;
00489 ns = he->c;
00490 atype = (rpmuint8_t)PGPARMOR_SIGNATURE;
00491 break;
00492 case RPM_STRING_TYPE:
00493 case RPM_STRING_ARRAY_TYPE:
00494 enc = he->p.str;
00495 s = NULL;
00496 ns = 0;
00497
00498 if (b64decode(enc, (void **)&s, &ns))
00499 return xstrdup(_("(not base64)"));
00500
00501 atype = (rpmuint8_t)PGPARMOR_PUBKEY;
00502 break;
00503 case RPM_UINT8_TYPE:
00504 case RPM_UINT16_TYPE:
00505 case RPM_UINT32_TYPE:
00506 case RPM_UINT64_TYPE:
00507 case RPM_I18NSTRING_TYPE:
00508 default:
00509 return xstrdup(_("(invalid type)"));
00510 break;
00511 }
00512
00513 val = pgpArmorWrap(atype, s, ns);
00514 if (atype == (rpmuint8_t)PGPARMOR_PUBKEY)
00515 s = _free(s);
00516 return val;
00517 }
00518
00526 static char * base64Format(HE_t he, const char ** av)
00527
00528 {
00529 int ix = (he->ix > 0 ? he->ix : 0);
00530 char * val;
00531 const char * enc;
00532 char * t;
00533 int lc;
00534 size_t ns;
00535 size_t nt;
00536
00537 assert(ix == 0);
00538 switch(he->t) {
00539 default:
00540 val = xstrdup(_("(invalid type :base64)"));
00541 goto exit;
00542 break;
00543 case RPM_UINT64_TYPE:
00544 ns = sizeof(he->p.ui64p[0]);
00545 break;
00546 case RPM_STRING_TYPE:
00547 ns = strlen(he->p.str);
00548 break;
00549 case RPM_BIN_TYPE:
00550 ns = he->c;
00551 break;
00552 }
00553
00554 nt = ((ns + 2) / 3) * 4;
00555
00556
00557
00558 if (b64encode_chars_per_line > 0 && b64encode_eolstr != NULL) {
00559 lc = (nt + b64encode_chars_per_line - 1) / b64encode_chars_per_line;
00560 if (((nt + b64encode_chars_per_line - 1) % b64encode_chars_per_line) != 0)
00561 ++lc;
00562 nt += lc * strlen(b64encode_eolstr);
00563 }
00564
00565
00566 val = t = xcalloc(1, nt + 1);
00567 *t = '\0';
00568
00569
00570 { unsigned char * _data = xcalloc(1, ns+1);
00571 assert(he->p.ptr != NULL);
00572 memcpy(_data, he->p.ptr, ns);
00573
00574 if ((enc = b64encode(_data, ns)) != NULL) {
00575 t = stpcpy(t, enc);
00576 enc = _free(enc);
00577 }
00578
00579 _data = _free(_data);
00580 }
00581
00582 exit:
00583
00584 return val;
00585
00586 }
00587
00593 static size_t xmlstrlen(const char * s)
00594
00595 {
00596 size_t len = 0;
00597 int c;
00598
00599 while ((c = (int) *s++) != (int) '\0') {
00600 switch (c) {
00601 case '<':
00602 case '>': len += sizeof("<") - 1; break;
00603 case '&': len += sizeof("&") - 1; break;
00604 default: len += 1; break;
00605 }
00606 }
00607 return len;
00608 }
00609
00616 static char * xmlstrcpy( char * t, const char * s)
00617
00618 {
00619 char * te = t;
00620 int c;
00621
00622 while ((c = (int) *s++) != (int) '\0') {
00623 switch (c) {
00624 case '<': te = stpcpy(te, "<"); break;
00625 case '>': te = stpcpy(te, ">"); break;
00626 case '&': te = stpcpy(te, "&"); break;
00627 default: *te++ = (char) c; break;
00628 }
00629 }
00630 *te = '\0';
00631 return t;
00632 }
00633
00634 static char *
00635 strdup_locale_convert ( const char * buffer,
00636 const char * tocode)
00637
00638 {
00639 char *dest_str;
00640 #if defined(HAVE_ICONV)
00641 char *fromcode = NULL;
00642 iconv_t fd;
00643
00644 if (buffer == NULL)
00645 return NULL;
00646
00647 if (tocode == NULL)
00648 tocode = "UTF-8";
00649
00650 #ifdef HAVE_LANGINFO_H
00651 fromcode = nl_langinfo (CODESET);
00652 #endif
00653
00654 if (fromcode != NULL && strcmp(tocode, fromcode) != 0
00655 && (fd = iconv_open(tocode, fromcode)) != (iconv_t)-1)
00656 {
00657 const char *pin = buffer;
00658 char *pout = NULL;
00659 size_t ib, ob, dest_size;
00660 int done;
00661 int is_error;
00662 size_t err;
00663 const char *shift_pin = NULL;
00664 int xx;
00665
00666 err = iconv(fd, NULL, &ib, &pout, &ob);
00667 dest_size = ob = ib = strlen(buffer);
00668 dest_str = pout = malloc((dest_size + 1) * sizeof(*dest_str));
00669 if (dest_str)
00670 *dest_str = '\0';
00671 done = is_error = 0;
00672 if (pout != NULL)
00673 while (done == 0 && is_error == 0) {
00674 err = iconv(fd, (char **)&pin, &ib, &pout, &ob);
00675
00676 if (err == (size_t)-1) {
00677 switch (errno) {
00678 case EINVAL:
00679 done = 1;
00680 break;
00681 case E2BIG:
00682 { size_t used = (size_t)(pout - dest_str);
00683 dest_size *= 2;
00684 dest_str = realloc(dest_str, (dest_size + 1) * sizeof(*dest_str));
00685 if (dest_str == NULL) {
00686 is_error = 1;
00687 continue;
00688 }
00689 pout = dest_str + used;
00690 ob = dest_size - used;
00691 } break;
00692 case EILSEQ:
00693 is_error = 1;
00694 break;
00695 default:
00696 is_error = 1;
00697 break;
00698 }
00699 } else {
00700 if (shift_pin == NULL) {
00701 shift_pin = pin;
00702 pin = NULL;
00703 ib = 0;
00704 } else {
00705 done = 1;
00706 }
00707 }
00708 }
00709 xx = iconv_close(fd);
00710 if (pout)
00711 *pout = '\0';
00712 if (dest_str != NULL)
00713 dest_str = xstrdup(dest_str);
00714 } else
00715 #endif
00716 {
00717 dest_str = xstrdup((buffer ? buffer : ""));
00718 }
00719
00720 return dest_str;
00721 }
00722
00729 static char * cdataFormat(HE_t he, const char ** av)
00730
00731 {
00732 int ix = (he->ix > 0 ? he->ix : 0);
00733 char * val;
00734
00735 assert(ix == 0);
00736 if (he->t != RPM_STRING_TYPE) {
00737 val = xstrdup(_("(not a string)"));
00738 } else {
00739 const char * s = strdup_locale_convert(he->p.str, (av ? av[0] : NULL));
00740 size_t nb;
00741 char * t;
00742
00743 if (s == NULL) {
00744
00745 val = xstrdup(_("(not a string)"));
00746 goto exit;
00747 }
00748 nb = xmlstrlen(s);
00749 val = t = xcalloc(1, nb + 1);
00750 t = xmlstrcpy(t, s); t += strlen(t);
00751 *t = '\0';
00752 s = _free(s);
00753 }
00754
00755 exit:
00756 return val;
00757 }
00758
00765 static char * iconvFormat(HE_t he, const char ** av)
00766
00767 {
00768 int ix = (he->ix > 0 ? he->ix : 0);
00769 char * val = NULL;
00770
00771 assert(ix == 0);
00772 if (he->t == RPM_STRING_TYPE)
00773 val = strdup_locale_convert(he->p.str, (av ? av[0] : NULL));
00774 if (val == NULL)
00775 val = xstrdup(_("(not a string)"));
00776
00777 return val;
00778 }
00779
00786 static char * xmlFormat(HE_t he, const char ** av)
00787
00788 {
00789 int ix = (he->ix > 0 ? he->ix : 0);
00790 const char * xtag = NULL;
00791 size_t nb;
00792 char * val;
00793 const char * s = NULL;
00794 char * t, * te;
00795 rpmuint64_t anint = 0;
00796 int freeit = 0;
00797 int xx;
00798
00799 assert(ix == 0);
00800 assert(he->t == RPM_STRING_TYPE || he->t == RPM_UINT64_TYPE || he->t == RPM_BIN_TYPE);
00801 switch (he->t) {
00802 case RPM_STRING_ARRAY_TYPE:
00803 s = he->p.argv[ix];
00804 xtag = "string";
00805
00806 s = xstrdup(s);
00807 s = xstrtolocale(s);
00808 freeit = 1;
00809 break;
00810 case RPM_I18NSTRING_TYPE:
00811 case RPM_STRING_TYPE:
00812 s = he->p.str;
00813 xtag = "string";
00814
00815 s = xstrdup(s);
00816 s = xstrtolocale(s);
00817 freeit = 1;
00818 break;
00819 case RPM_BIN_TYPE:
00820
00821 { int cpl = b64encode_chars_per_line;
00822 b64encode_chars_per_line = 0;
00823
00824 s = base64Format(he, NULL);
00825
00826 b64encode_chars_per_line = cpl;
00827 xtag = "base64";
00828 freeit = 1;
00829 } break;
00830
00831 case RPM_UINT8_TYPE:
00832 anint = (rpmuint64_t)he->p.ui8p[ix];
00833 break;
00834 case RPM_UINT16_TYPE:
00835 anint = (rpmuint64_t)he->p.ui16p[ix];
00836 break;
00837 case RPM_UINT32_TYPE:
00838 anint = (rpmuint64_t)he->p.ui32p[ix];
00839 break;
00840 case RPM_UINT64_TYPE:
00841 anint = he->p.ui64p[ix];
00842 break;
00843 default:
00844 return xstrdup(_("(invalid xml type)"));
00845 break;
00846 }
00847
00848 if (s == NULL) {
00849 int tlen = 64;
00850 t = memset(alloca(tlen+1), 0, tlen+1);
00851
00852 if (anint != 0)
00853 xx = snprintf(t, tlen, "%llu", (unsigned long long)anint);
00854
00855 s = t;
00856 xtag = "integer";
00857 }
00858
00859 nb = xmlstrlen(s);
00860 if (nb == 0) {
00861 nb += strlen(xtag) + sizeof("\t</>");
00862 te = t = alloca(nb);
00863 te = stpcpy( stpcpy( stpcpy(te, "\t<"), xtag), "/>");
00864 } else {
00865 nb += 2 * strlen(xtag) + sizeof("\t<></>");
00866 te = t = alloca(nb);
00867 te = stpcpy( stpcpy( stpcpy(te, "\t<"), xtag), ">");
00868 te = xmlstrcpy(te, s);
00869 te += strlen(te);
00870 te = stpcpy( stpcpy( stpcpy(te, "</"), xtag), ">");
00871 }
00872
00873 if (freeit)
00874 s = _free(s);
00875
00876 val = xstrdup(t);
00877
00878 return val;
00879 }
00880
00887 static size_t yamlstrlen(const char * s, int lvl)
00888
00889 {
00890 size_t len = 0;
00891 int indent = (lvl > 0);
00892 int c;
00893
00894 while ((c = (int) *s++) != (int) '\0')
00895 {
00896 if (indent) {
00897 len += 2 * lvl;
00898 indent = 0;
00899 }
00900 if (c == (int) '\n')
00901 indent = (lvl > 0);
00902 len++;
00903 }
00904 return len;
00905 }
00906
00914 static char * yamlstrcpy( char * t, const char * s, int lvl)
00915
00916 {
00917 char * te = t;
00918 int indent = (lvl > 0);
00919 int c;
00920
00921 while ((c = (int) *s++) != (int) '\0') {
00922 if (indent) {
00923 int i;
00924 for (i = 0; i < lvl; i++) {
00925 *te++ = ' ';
00926 *te++ = ' ';
00927 }
00928 indent = 0;
00929 }
00930 if (c == (int) '\n')
00931 indent = (lvl > 0);
00932 *te++ = (char) c;
00933 }
00934 *te = '\0';
00935 return t;
00936 }
00937
00944 static char * yamlFormat(HE_t he, const char ** av)
00945
00946 {
00947 int element = he->ix;
00948 int ix = (he->ix > 0 ? he->ix : 0);
00949 const char * xtag = NULL;
00950 int freetag = 0;
00951 size_t nb;
00952 char * val;
00953 const char * s = NULL;
00954 char * t, * te;
00955 rpmuint64_t anint = 0;
00956 int freeit = 0;
00957 int lvl = 0;
00958 int xx;
00959 int ls;
00960 int c;
00961
00962 assert(ix == 0);
00963 assert(he->t == RPM_STRING_TYPE || he->t == RPM_UINT64_TYPE || he->t == RPM_BIN_TYPE);
00964 xx = 0;
00965 ls = 0;
00966 switch (he->t) {
00967 case RPM_STRING_ARRAY_TYPE:
00968 case RPM_I18NSTRING_TYPE:
00969 case RPM_STRING_TYPE:
00970 s = (he->t == RPM_STRING_ARRAY_TYPE ? he->p.argv[ix] : he->p.str);
00971 if (strchr("[", s[0]))
00972 xx = 1;
00973 if (xx == 0)
00974 while ((c = (int) *s++) != (int) '\0') {
00975 switch (c) {
00976 default:
00977 continue;
00978 case '\n':
00979 xx = 1;
00980 if (s[0] == ' ' || s[0] == '\t')
00981 ls = 1;
00982 continue;
00983 case '-':
00984 case ':':
00985 if (s[0] != ' ' && s[0] != '\0' && s[1] != '"')
00986 continue;
00987 xx = 1;
00988 break;
00989 }
00990 break;
00991 }
00992 if (xx) {
00993 if (ls) {
00994 xtag = xmalloc(strlen("- |##-\n") + 1);
00995 freetag = 1;
00996 if (element >= 0) {
00997 lvl = 3;
00998 sprintf((char *)xtag, "- |%d-\n", lvl);
00999 } else {
01000 lvl = 2;
01001 if (he->ix < 0) lvl++;
01002 sprintf((char *)xtag, "|%d-\n", lvl);
01003 }
01004 } else {
01005 if (element >= 0) {
01006 xtag = "- |-\n";
01007 lvl = 3;
01008 } else {
01009 xtag = "|-\n";
01010 lvl = 2;
01011 if (he->ix < 0) lvl++;
01012 }
01013 }
01014 } else {
01015 xtag = (element >= 0 ? "- " : NULL);
01016 }
01017
01018
01019 s = xstrdup(he->p.str);
01020 s = xstrtolocale(s);
01021 freeit = 1;
01022 break;
01023 case RPM_BIN_TYPE:
01024
01025 { int cpl = b64encode_chars_per_line;
01026 b64encode_chars_per_line = 0;
01027
01028 s = base64Format(he, NULL);
01029 element = -element;
01030
01031 b64encode_chars_per_line = cpl;
01032 xtag = "!!binary ";
01033 freeit = 1;
01034 } break;
01035
01036 case RPM_UINT8_TYPE:
01037 anint = (rpmuint64_t)he->p.ui8p[ix];
01038 break;
01039 case RPM_UINT16_TYPE:
01040 anint = (rpmuint64_t)he->p.ui16p[ix];
01041 break;
01042 case RPM_UINT32_TYPE:
01043 anint = (rpmuint64_t)he->p.ui32p[ix];
01044 break;
01045 case RPM_UINT64_TYPE:
01046 anint = he->p.ui64p[ix];
01047 break;
01048 default:
01049 return xstrdup(_("(invalid yaml type)"));
01050 break;
01051 }
01052
01053 if (s == NULL) {
01054 int tlen = 64;
01055 t = memset(alloca(tlen+1), 0, tlen+1);
01056
01057 xx = snprintf(t, tlen, "%llu", (unsigned long long)anint);
01058
01059 s = t;
01060 xtag = (element >= 0 ? "- " : NULL);
01061 }
01062
01063 nb = yamlstrlen(s, lvl);
01064 if (nb == 0) {
01065 if (element >= 0)
01066 nb += sizeof(" ") - 1;
01067 nb += sizeof("- ~") - 1;
01068 nb++;
01069 te = t = alloca(nb);
01070 if (element >= 0)
01071 te = stpcpy(te, " ");
01072 te = stpcpy(te, "- ~");
01073 } else {
01074 if (element >= 0)
01075 nb += sizeof(" ") - 1;
01076 if (xtag)
01077 nb += strlen(xtag);
01078 nb++;
01079 te = t = alloca(nb);
01080 if (element >= 0)
01081 te = stpcpy(te, " ");
01082 if (xtag)
01083 te = stpcpy(te, xtag);
01084
01085 if (freetag)
01086 xtag = _free(xtag);
01087
01088 te = yamlstrcpy(te, s, lvl);
01089 te += strlen(te);
01090 }
01091
01092
01093 if (freeit)
01094 s = _free(s);
01095
01096 val = xstrdup(t);
01097
01098 return val;
01099 }
01100
01107 static char * pgpsigFormat(HE_t he, const char ** av)
01108
01109
01110 {
01111 int ix = (he->ix > 0 ? he->ix : 0);
01112 char * val, * t;
01113
01114 assert(ix == 0);
01115 if (!(he->t == RPM_BIN_TYPE)) {
01116 val = xstrdup(_("(not a blob)"));
01117 } else {
01118 rpmuint8_t * pkt = he->p.ui8p;
01119 unsigned int pktlen = 0;
01120 unsigned int v = (unsigned int) *pkt;
01121 pgpTag tag = 0;
01122 unsigned int plen;
01123 unsigned int hlen = 0;
01124
01125 if (v & 0x80) {
01126 if (v & 0x40) {
01127 tag = (v & 0x3f);
01128 plen = pgpLen(pkt+1, &hlen);
01129 } else {
01130 tag = (v >> 2) & 0xf;
01131 plen = (1 << (v & 0x3));
01132 hlen = pgpGrab(pkt+1, plen);
01133 }
01134
01135 pktlen = 1 + plen + hlen;
01136 }
01137
01138 if (pktlen == 0 || tag != PGPTAG_SIGNATURE) {
01139 val = xstrdup(_("(not an OpenPGP signature)"));
01140 } else {
01141 pgpDig dig = pgpDigNew(0);
01142 pgpDigParams sigp = pgpGetSignature(dig);
01143 size_t nb = 0;
01144 const char *tempstr;
01145
01146 (void) pgpPrtPkts(pkt, pktlen, dig, 0);
01147
01148 val = NULL;
01149 again:
01150 nb += 100;
01151 val = t = xrealloc(val, nb + 1);
01152
01153 switch (sigp->pubkey_algo) {
01154 case PGPPUBKEYALGO_DSA:
01155 t = stpcpy(t, "DSA");
01156 break;
01157 case PGPPUBKEYALGO_RSA:
01158 t = stpcpy(t, "RSA");
01159 break;
01160 default:
01161 (void) snprintf(t, nb - (t - val), "%u", (unsigned)sigp->pubkey_algo);
01162 t += strlen(t);
01163 break;
01164 }
01165 if (t + 5 >= val + nb)
01166 goto again;
01167 *t++ = '/';
01168 switch (sigp->hash_algo) {
01169 case PGPHASHALGO_MD5:
01170 t = stpcpy(t, "MD5");
01171 break;
01172 case PGPHASHALGO_SHA1:
01173 t = stpcpy(t, "SHA1");
01174 break;
01175 default:
01176 (void) snprintf(t, nb - (t - val), "%u", (unsigned)sigp->hash_algo);
01177 t += strlen(t);
01178 break;
01179 }
01180 if (t + strlen (", ") + 1 >= val + nb)
01181 goto again;
01182
01183 t = stpcpy(t, ", ");
01184
01185
01186 { time_t dateint = pgpGrab(sigp->time, sizeof(sigp->time));
01187 struct tm * tstruct = localtime(&dateint);
01188 if (tstruct)
01189 (void) strftime(t, (nb - (t - val)), "%c", tstruct);
01190 }
01191 t += strlen(t);
01192 if (t + strlen (", Key ID ") + 1 >= val + nb)
01193 goto again;
01194 t = stpcpy(t, ", Key ID ");
01195 tempstr = pgpHexStr(sigp->signid, sizeof(sigp->signid));
01196 if (t + strlen (tempstr) > val + nb)
01197 goto again;
01198 t = stpcpy(t, tempstr);
01199
01200 dig = pgpDigFree(dig, "pgpsigFormat");
01201 }
01202 }
01203
01204 return val;
01205 }
01206
01213 static
01214 char * depflagsFormat(HE_t he, const char ** av)
01215
01216 {
01217 int ix = (he->ix > 0 ? he->ix : 0);
01218 char * val;
01219
01220 assert(ix == 0);
01221 if (he->t != RPM_UINT64_TYPE) {
01222 val = xstrdup(_("(invalid type)"));
01223 } else {
01224 rpmuint64_t anint = he->p.ui64p[ix];
01225 char *t, *buf;
01226
01227 t = buf = alloca(32);
01228 *t = '\0';
01229
01230 #ifdef NOTYET
01231 if (anint & RPMSENSE_SCRIPT_PRE)
01232 t = stpcpy(t, "(pre)");
01233 else if (anint & RPMSENSE_SCRIPT_POST)
01234 t = stpcpy(t, "(post)");
01235 else if (anint & RPMSENSE_SCRIPT_PREUN)
01236 t = stpcpy(t, "(preun)");
01237 else if (anint & RPMSENSE_SCRIPT_POSTUN)
01238 t = stpcpy(t, "(postun)");
01239 #endif
01240 if (anint & RPMSENSE_SENSEMASK)
01241 *t++ = ' ';
01242 if (anint & RPMSENSE_LESS)
01243 *t++ = '<';
01244 if (anint & RPMSENSE_GREATER)
01245 *t++ = '>';
01246 if (anint & RPMSENSE_EQUAL)
01247 *t++ = '=';
01248 if (anint & RPMSENSE_SENSEMASK)
01249 *t++ = ' ';
01250 *t = '\0';
01251
01252 val = xstrdup(buf);
01253 }
01254
01255 return val;
01256 }
01257
01265 static
01266 char * deptypeFormat(HE_t he, const char ** av)
01267
01268 {
01269 int ix = (he->ix > 0 ? he->ix : 0);
01270 char * val;
01271
01272 assert(ix == 0);
01273 if (he->t != RPM_UINT64_TYPE) {
01274 val = xstrdup(_("(invalid type)"));
01275 } else {
01276 rpmuint64_t anint = he->p.ui64p[ix];
01277 char *t, *buf;
01278
01279 t = buf = alloca(32);
01280 *t = '\0';
01281
01282 if (anint & RPMSENSE_SCRIPT_PRE)
01283 t = stpcpy(t, "pre");
01284 else if (anint & RPMSENSE_SCRIPT_POST)
01285 t = stpcpy(t, "post");
01286 else if (anint & RPMSENSE_SCRIPT_PREUN)
01287 t = stpcpy(t, "preun");
01288 else if (anint & RPMSENSE_SCRIPT_POSTUN)
01289 t = stpcpy(t, "postun");
01290 else if (anint & RPMSENSE_SCRIPT_VERIFY)
01291 t = stpcpy(t, "verify");
01292 else if (anint & RPMSENSE_RPMLIB)
01293 t = stpcpy(t, "rpmlib");
01294 else if (anint & RPMSENSE_INTERP)
01295 t = stpcpy(t, "interp");
01296 else if (anint & (RPMSENSE_FIND_PROVIDES | RPMSENSE_FIND_REQUIRES))
01297 t = stpcpy(t, "auto");
01298 else
01299 t = stpcpy(t, "manual");
01300 *t = '\0';
01301
01302 val = xstrdup(buf);
01303 }
01304
01305 return val;
01306 }
01307
01314 static int instprefixTag(Header h, HE_t he)
01315
01316
01317 {
01318 he->tag = RPMTAG_INSTALLPREFIX;
01319 if (headerGet(h, he, 0))
01320 return 0;
01321
01322 he->tag = RPMTAG_INSTPREFIXES;
01323 if (headerGet(h, he, 0)) {
01324 rpmTagData array = { .argv = he->p.argv };
01325 he->t = RPM_STRING_TYPE;
01326 he->c = 1;
01327 he->p.str = xstrdup(array.argv[0]);
01328 he->freeData = 1;
01329 array.ptr = _free(array.ptr);
01330 return 0;
01331 }
01332 return 1;
01333 }
01334
01342 static int tv2uuidv1( Header h, HE_t he, struct timeval *tv)
01343
01344 {
01345 rpmuint64_t uuid_time = ((rpmuint64_t)tv->tv_sec * 10000000) +
01346 (tv->tv_usec * 10) + 0x01B21DD213814000ULL;
01347
01348 he->t = RPM_BIN_TYPE;
01349 he->c = 128/8;
01350 he->p.ptr = xcalloc(1, he->c);
01351 he->freeData = 1;
01352 if (rpmuuidMake(1, NULL, NULL, NULL, (unsigned char *)he->p.ui8p)) {
01353 he->p.ptr = _free(he->p.ptr);
01354 he->freeData = 0;
01355 return 1;
01356 }
01357
01358 he->p.ui8p[6] &= 0xf0;
01359 he->p.ui8p[8] &= 0x3f;
01360 he->p.ui8p[9] &= 0x00;
01361
01362 he->p.ui8p[3] = (rpmuint8_t)(uuid_time >> 0);
01363 he->p.ui8p[2] = (rpmuint8_t)(uuid_time >> 8);
01364 he->p.ui8p[1] = (rpmuint8_t)(uuid_time >> 16);
01365 he->p.ui8p[0] = (rpmuint8_t)(uuid_time >> 24);
01366 he->p.ui8p[5] = (rpmuint8_t)(uuid_time >> 32);
01367 he->p.ui8p[4] = (rpmuint8_t)(uuid_time >> 40);
01368 he->p.ui8p[6] |= (rpmuint8_t)(uuid_time >> 56) & 0x0f;
01369
01370 #ifdef NOTYET
01371
01372 he->p.ui8p[8] |= (he->p.ui8p[2] & 0x3f);
01373 he->p.ui8p[9] |= he->p.ui8p[3]
01374 #endif
01375
01376 return 0;
01377 }
01378
01385 static int tag2uuidv1(Header h, HE_t he)
01386
01387
01388 {
01389 struct timeval tv;
01390
01391 if (!headerGet(h, he, 0))
01392 return 1;
01393 tv.tv_sec = (long) he->p.ui32p[0];
01394 tv.tv_usec = (long) (he->c > 1 ? he->p.ui32p[1] : 0);
01395 he->p.ptr = _free(he->p.ptr);
01396 return tv2uuidv1(h, he, &tv);
01397 }
01398
01405 static int installtime_uuidTag(Header h, HE_t he)
01406
01407
01408 {
01409 he->tag = RPMTAG_INSTALLTIME;
01410 return tag2uuidv1(h, he);
01411 }
01412
01419 static int buildtime_uuidTag(Header h, HE_t he)
01420
01421
01422 {
01423 he->tag = RPMTAG_BUILDTIME;
01424 return tag2uuidv1(h, he);
01425 }
01426
01433 static int origintime_uuidTag(Header h, HE_t he)
01434
01435
01436 {
01437 he->tag = RPMTAG_ORIGINTIME;
01438 return tag2uuidv1(h, he);
01439 }
01440
01447 static int installtid_uuidTag(Header h, HE_t he)
01448
01449
01450 {
01451 he->tag = RPMTAG_INSTALLTID;
01452 return tag2uuidv1(h, he);
01453 }
01454
01461 static int removetid_uuidTag(Header h, HE_t he)
01462
01463
01464 {
01465 he->tag = RPMTAG_REMOVETID;
01466 return tag2uuidv1(h, he);
01467 }
01468
01475 static int origintid_uuidTag(Header h, HE_t he)
01476
01477
01478 {
01479 he->tag = RPMTAG_ORIGINTID;
01480 return tag2uuidv1(h, he);
01481 }
01482
01483
01484 static const char uuid_ns[] = "ns:URL";
01485
01486 static const char uuid_auth[] = "%{?_uuid_auth}%{!?_uuid_auth:http://rpm5.org}";
01487
01488 static const char uuid_path[] = "%{?_uuid_path}%{!?_uuid_path:/package}";
01489
01490 static rpmuint32_t uuid_version = 5;
01491
01500 static int str2uuid(HE_t he, const char ** av,
01501 rpmuint32_t version, char * val)
01502
01503
01504 {
01505 const char * ns = NULL;
01506 const char * tagn = tagName(he->tag);
01507 const char * s = NULL;
01508 int rc;
01509
01510
01511 if (!strcmp("Sigmd5", tagn))
01512 tagn = "Pkgid";
01513 else if (!strcmp("Sha1header", tagn))
01514 tagn = "Hdrid";
01515
01516 switch (version) {
01517 default:
01518 version = uuid_version;
01519
01520 case 3:
01521 case 5:
01522 assert(he->t == RPM_STRING_TYPE);
01523 ns = uuid_ns;
01524 s = rpmGetPath(uuid_auth, "/", uuid_path, "/", tagn, "/",
01525 he->p.str, NULL);
01526
01527 case 4:
01528 break;
01529 }
01530 he->p.ptr = _free(he->p.ptr);
01531 he->t = RPM_BIN_TYPE;
01532 he->c = 128/8;
01533 he->p.ptr = xcalloc(1, he->c);
01534 he->freeData = 1;
01535 rc = rpmuuidMake((int)version, ns, s, val, (unsigned char *)he->p.ui8p);
01536 if (rc) {
01537 he->p.ptr = _free(he->p.ptr);
01538 he->freeData = 0;
01539 }
01540 s = _free(s);
01541 return rc;
01542 }
01543
01550 static int tag2uuidv5(Header h, HE_t he)
01551
01552
01553 {
01554 if (!headerGet(h, he, 0))
01555 return 1;
01556 switch (he->t) {
01557 default:
01558 assert(0);
01559 break;
01560 case RPM_BIN_TYPE: {
01561 static const char hex[] = "0123456789abcdef";
01562 char * t;
01563 char * te;
01564 rpmuint32_t i;
01565
01566 t = te = xmalloc (2*he->c + 1);
01567 for (i = 0; i < he->c; i++) {
01568 *te++ = hex[ (int)((he->p.ui8p[i] >> 4) & 0x0f) ];
01569 *te++ = hex[ (int)((he->p.ui8p[i] ) & 0x0f) ];
01570 }
01571 *te = '\0';
01572 he->p.ptr = _free(he->p.ptr);
01573 he->t = RPM_STRING_TYPE;
01574 he->p.ptr = t;
01575 he->c = 1;
01576 he->freeData = 1;
01577 } break;
01578 case RPM_STRING_TYPE:
01579 break;
01580 }
01581 return str2uuid(he, NULL, 0, NULL);
01582 }
01583
01590 static int pkguuidTag(Header h, HE_t he)
01591
01592
01593 {
01594 he->tag = RPMTAG_PKGID;
01595 return tag2uuidv5(h, he);
01596 }
01597
01604 static int sourcepkguuidTag(Header h, HE_t he)
01605
01606
01607 {
01608 he->tag = RPMTAG_SOURCEPKGID;
01609 return tag2uuidv5(h, he);
01610 }
01611
01618 static int hdruuidTag(Header h, HE_t he)
01619
01620
01621 {
01622 he->tag = RPMTAG_HDRID;
01623 return tag2uuidv5(h, he);
01624 }
01625
01632 static int triggercondsTag(Header h, HE_t he)
01633
01634
01635 {
01636 HE_t _he = memset(alloca(sizeof(*_he)), 0, sizeof(*_he));
01637 HE_t Fhe = memset(alloca(sizeof(*Fhe)), 0, sizeof(*Fhe));
01638 HE_t Ihe = memset(alloca(sizeof(*Ihe)), 0, sizeof(*Ihe));
01639 HE_t Nhe = memset(alloca(sizeof(*Nhe)), 0, sizeof(*Nhe));
01640 HE_t Vhe = memset(alloca(sizeof(*Vhe)), 0, sizeof(*Vhe));
01641 HE_t She = memset(alloca(sizeof(*She)), 0, sizeof(*She));
01642 rpmuint64_t anint;
01643 unsigned i, j;
01644 int rc = 1;
01645 int xx;
01646
01647 he->freeData = 0;
01648
01649 Nhe->tag = RPMTAG_TRIGGERNAME;
01650 xx = headerGet(h, Nhe, 0);
01651 if (!xx) {
01652 rc = 0;
01653 goto exit;
01654 }
01655
01656 Ihe->tag = RPMTAG_TRIGGERINDEX;
01657 xx = headerGet(h, Ihe, 0);
01658 if (!xx) goto exit;
01659
01660 Fhe->tag = RPMTAG_TRIGGERFLAGS;
01661 xx = headerGet(h, Fhe, 0);
01662 if (!xx) goto exit;
01663
01664 Vhe->tag = RPMTAG_TRIGGERVERSION;
01665 xx = headerGet(h, Vhe, 0);
01666 if (!xx) goto exit;
01667
01668 She->tag = RPMTAG_TRIGGERSCRIPTS;
01669 xx = headerGet(h, She, 0);
01670 if (!xx) goto exit;
01671
01672 _he->tag = he->tag;
01673 _he->t = RPM_UINT64_TYPE;
01674 _he->p.ui64p = &anint;
01675 _he->c = 1;
01676 _he->freeData = 0;
01677
01678 he->t = RPM_STRING_ARRAY_TYPE;
01679 he->c = She->c;
01680
01681 he->freeData = 1;
01682 he->p.argv = xmalloc(sizeof(*he->p.argv) * he->c);
01683 for (i = 0; i < (unsigned) he->c; i++) {
01684 char * item, * flagsStr;
01685 char * chptr;
01686
01687 chptr = xstrdup("");
01688
01689 for (j = 0; j < Nhe->c; j++) {
01690 if (Ihe->p.ui32p[j] != i)
01691 continue;
01692
01693 item = xmalloc(strlen(Nhe->p.argv[j]) + strlen(Vhe->p.argv[j]) + 20);
01694
01695 if (Fhe->p.ui32p[j] & RPMSENSE_SENSEMASK) {
01696 anint = Fhe->p.ui32p[j];
01697 flagsStr = depflagsFormat(_he, NULL);
01698 sprintf(item, "%s%s%s", Nhe->p.argv[j], flagsStr, Vhe->p.argv[j]);
01699 flagsStr = _free(flagsStr);
01700 } else
01701 strcpy(item, Nhe->p.argv[j]);
01702
01703
01704 chptr = xrealloc(chptr, strlen(chptr) + strlen(item) + 5);
01705 if (*chptr != '\0') strcat(chptr, ", ");
01706 strcat(chptr, item);
01707 item = _free(item);
01708 }
01709
01710 he->p.argv[i] = chptr;
01711 }
01712 rc = 0;
01713
01714 exit:
01715 Ihe->p.ptr = _free(Ihe->p.ptr);
01716 Fhe->p.ptr = _free(Fhe->p.ptr);
01717 Nhe->p.ptr = _free(Nhe->p.ptr);
01718 Vhe->p.ptr = _free(Vhe->p.ptr);
01719 She->p.ptr = _free(She->p.ptr);
01720
01721 return rc;
01722 }
01723
01730 static int triggertypeTag(Header h, HE_t he)
01731
01732
01733 {
01734 HE_t _he = memset(alloca(sizeof(*_he)), 0, sizeof(*_he));
01735 rpmTagData indices = { .ptr = NULL };
01736 rpmTagData flags = { .ptr = NULL };
01737 rpmTagData s = { .ptr = NULL };
01738 rpmTagCount numNames;
01739 rpmTagCount numScripts;
01740 unsigned i, j;
01741 int rc = 1;
01742 int xx;
01743
01744 he->freeData = 0;
01745
01746
01747 _he->tag = RPMTAG_TRIGGERINDEX;
01748 xx = headerGet(h, _he, 0);
01749 if (!xx) goto exit;
01750 indices.ui32p = _he->p.ui32p;
01751 numNames = _he->c;
01752
01753 _he->tag = RPMTAG_TRIGGERFLAGS;
01754 xx = headerGet(h, _he, 0);
01755 if (!xx) goto exit;
01756 flags.ui32p = _he->p.ui32p;
01757
01758 _he->tag = RPMTAG_TRIGGERSCRIPTS;
01759 xx = headerGet(h, _he, 0);
01760 if (!xx) goto exit;
01761 s.argv = _he->p.argv;
01762 numScripts = _he->c;
01763
01764
01765 he->t = RPM_STRING_ARRAY_TYPE;
01766 he->c = numScripts;
01767
01768 he->freeData = 1;
01769 he->p.argv = xmalloc(sizeof(*he->p.argv) * he->c);
01770 for (i = 0; i < (unsigned) he->c; i++) {
01771 for (j = 0; j < (unsigned) numNames; j++) {
01772 if (indices.ui32p[j] != i)
01773 continue;
01774
01775
01776 if (flags.ui32p[j] & RPMSENSE_TRIGGERPREIN)
01777 he->p.argv[i] = xstrdup("prein");
01778 else if (flags.ui32p[j] & RPMSENSE_TRIGGERIN)
01779 he->p.argv[i] = xstrdup("in");
01780 else if (flags.ui32p[j] & RPMSENSE_TRIGGERUN)
01781 he->p.argv[i] = xstrdup("un");
01782 else if (flags.ui32p[j] & RPMSENSE_TRIGGERPOSTUN)
01783 he->p.argv[i] = xstrdup("postun");
01784 else
01785 he->p.argv[i] = xstrdup("");
01786 break;
01787 }
01788 }
01789 rc = 0;
01790
01791 exit:
01792 indices.ptr = _free(indices.ptr);
01793 flags.ptr = _free(flags.ptr);
01794 s.ptr = _free(s.ptr);
01795 return 0;
01796 }
01797
01798
01799
01800 #if defined(ENABLE_NLS)
01801
01802
01803 extern int _nl_msg_cat_cntr;
01804
01805 #endif
01806
01807 static const char * language = "LANGUAGE";
01808
01809
01810 static const char * _macro_i18ndomains = "%{?_i18ndomains}";
01811
01818 static int i18nTag(Header h, HE_t he)
01819
01820
01821 {
01822 char * dstring = rpmExpand(_macro_i18ndomains, NULL);
01823 int rc = 1;
01824
01825 he->t = RPM_STRING_TYPE;
01826 he->p.str = NULL;
01827 he->c = 0;
01828 he->freeData = 0;
01829
01830 if (dstring && *dstring) {
01831 char *domain, *de;
01832 const char * langval;
01833 const char * msgkey;
01834 const char * msgid;
01835
01836 { HE_t nhe = memset(alloca(sizeof(*nhe)), 0, sizeof(*nhe));
01837 const char * tn;
01838 char * mk;
01839 size_t nb = sizeof("()");
01840 int xx;
01841
01842 nhe->tag = RPMTAG_NAME;
01843 xx = headerGet(h, nhe, 0);
01844
01845
01846
01847
01848
01849 tn = tagName(he->tag);
01850 if (tn) nb += strlen(tn);
01851 if (nhe->p.str) nb += strlen(nhe->p.str);
01852 mk = alloca(nb);
01853 (void) snprintf(mk, nb, "%s(%s)",
01854 (nhe->p.str ? nhe->p.str : ""), (tn ? tn : ""));
01855 mk[nb-1] = '\0';
01856 nhe->p.ptr = _free(nhe->p.ptr);
01857 msgkey = mk;
01858 }
01859
01860
01861 langval = getenv(language);
01862 (void) setenv(language, "en_US", 1);
01863 #if defined(ENABLE_NLS)
01864 ++_nl_msg_cat_cntr;
01865 #endif
01866
01867 msgid = NULL;
01868 for (domain = dstring; domain != NULL; domain = de) {
01869 de = strchr(domain, ':');
01870 if (de) *de++ = '\0';
01871
01872 msgid = dgettext(domain, msgkey);
01873
01874 if (msgid != msgkey) break;
01875 }
01876
01877
01878 if (langval)
01879 (void) setenv(language, langval, 1);
01880 else
01881 unsetenv(language);
01882 #if defined(ENABLE_NLS)
01883 ++_nl_msg_cat_cntr;
01884 #endif
01885
01886 if (domain && msgid) {
01887
01888 const char * s = dgettext(domain, msgid);
01889
01890 if (s) {
01891 rc = 0;
01892 he->p.str = xstrdup(s);
01893 he->c = 1;
01894 he->freeData = 1;
01895 }
01896 }
01897 }
01898
01899
01900 dstring = _free(dstring);
01901
01902 if (!rc)
01903 return rc;
01904
01905 rc = headerGet(h, he, HEADERGET_NOEXTENSION);
01906 if (rc) {
01907 rc = 0;
01908 he->p.str = xstrtolocale(he->p.str);
01909 he->freeData = 1;
01910 return rc;
01911 }
01912
01913 he->t = RPM_STRING_TYPE;
01914 he->p.str = NULL;
01915 he->c = 0;
01916 he->freeData = 0;
01917
01918 return 1;
01919 }
01920
01924 static int localeTag(Header h, HE_t he)
01925
01926
01927 {
01928 int rc;
01929
01930 rc = headerGet(h, he, HEADERGET_NOEXTENSION);
01931 if (!rc || he->p.str == NULL || he->c == 0) {
01932 he->t = RPM_STRING_TYPE;
01933 he->freeData = 0;
01934 return 1;
01935 }
01936
01937 switch (he->t) {
01938 default:
01939 he->freeData = 0;
01940 break;
01941 case RPM_STRING_TYPE:
01942 he->p.str = xstrtolocale(he->p.str);
01943 he->freeData = 1;
01944 break;
01945 case RPM_STRING_ARRAY_TYPE:
01946 { const char ** argv;
01947 char * te;
01948 size_t l = 0;
01949 unsigned i;
01950 for (i = 0; i < (unsigned) he->c; i++) {
01951 he->p.argv[i] = xstrdup(he->p.argv[i]);
01952 he->p.argv[i] = xstrtolocale(he->p.argv[i]);
01953 assert(he->p.argv[i] != NULL);
01954 l += strlen(he->p.argv[i]) + 1;
01955 }
01956 argv = xmalloc(he->c * sizeof(*argv) + l);
01957 te = (char *)&argv[he->c];
01958 for (i = 0; i < (unsigned) he->c; i++) {
01959 argv[i] = te;
01960 te = stpcpy(te, he->p.argv[i]);
01961 te++;
01962 he->p.argv[i] = _free(he->p.argv[i]);
01963 }
01964 he->p.ptr = _free(he->p.ptr);
01965 he->p.argv = argv;
01966 he->freeData = 1;
01967 } break;
01968 }
01969
01970 return 0;
01971 }
01972
01979 static int summaryTag(Header h, HE_t he)
01980
01981
01982 {
01983 he->tag = RPMTAG_SUMMARY;
01984 return i18nTag(h, he);
01985 }
01986
01993 static int descriptionTag(Header h, HE_t he)
01994
01995
01996 {
01997 he->tag = RPMTAG_DESCRIPTION;
01998 return i18nTag(h, he);
01999 }
02000
02001 static int changelognameTag(Header h, HE_t he)
02002
02003
02004 {
02005 he->tag = RPMTAG_CHANGELOGNAME;
02006 return localeTag(h, he);
02007 }
02008
02009 static int changelogtextTag(Header h, HE_t he)
02010
02011
02012 {
02013 he->tag = RPMTAG_CHANGELOGTEXT;
02014 return localeTag(h, he);
02015 }
02016
02023 static int groupTag(Header h, HE_t he)
02024
02025
02026 {
02027 he->tag = RPMTAG_GROUP;
02028 return i18nTag(h, he);
02029 }
02030
02037 static int dbinstanceTag(Header h, HE_t he)
02038
02039 {
02040 he->tag = RPMTAG_DBINSTANCE;
02041 he->t = RPM_UINT32_TYPE;
02042 he->p.ui32p = xmalloc(sizeof(*he->p.ui32p));
02043 he->p.ui32p[0] = headerGetInstance(h);
02044 he->freeData = 1;
02045 he->c = 1;
02046 return 0;
02047 }
02048
02055 static int headerstartoffTag(Header h, HE_t he)
02056
02057 {
02058 he->tag = RPMTAG_HEADERSTARTOFF;
02059 he->t = RPM_UINT64_TYPE;
02060 he->p.ui64p = xmalloc(sizeof(*he->p.ui64p));
02061 he->p.ui64p[0] = headerGetStartOff(h);
02062 he->freeData = 1;
02063 he->c = 1;
02064 return 0;
02065 }
02066
02073 static int headerendoffTag(Header h, HE_t he)
02074
02075 {
02076 he->tag = RPMTAG_HEADERENDOFF;
02077 he->t = RPM_UINT64_TYPE;
02078 he->p.ui64p = xmalloc(sizeof(*he->p.ui64p));
02079 he->p.ui64p[0] = headerGetEndOff(h);
02080 he->freeData = 1;
02081 he->c = 1;
02082 return 0;
02083 }
02084
02091 static int pkgoriginTag(Header h, HE_t he)
02092
02093
02094 {
02095 const char * origin;
02096 int rc = 1;
02097
02098 he->tag = RPMTAG_PACKAGEORIGIN;
02099 if (!headerGet(h, he, HEADERGET_NOEXTENSION)
02100 && (origin = headerGetOrigin(h)) != NULL)
02101 {
02102 he->t = RPM_STRING_TYPE;
02103 he->p.str = xstrdup(origin);
02104 he->c = 1;
02105 he->freeData = 1;
02106 rc = 0;
02107 }
02108 return rc;
02109 }
02110
02117 static int pkgbaseurlTag(Header h, HE_t he)
02118
02119
02120 {
02121 const char * baseurl;
02122 int rc = 1;
02123
02124 he->tag = RPMTAG_PACKAGEBASEURL;
02125 if (!headerGet(h, he, HEADERGET_NOEXTENSION)
02126 && (baseurl = headerGetBaseURL(h)) != NULL)
02127 {
02128 he->t = RPM_STRING_TYPE;
02129 he->p.str = xstrdup(baseurl);
02130 he->c = 1;
02131 he->freeData = 1;
02132 rc = 0;
02133 }
02134 return rc;
02135 }
02136
02143 static int pkgdigestTag(Header h, HE_t he)
02144
02145 {
02146 const char * digest;
02147 int rc = 1;
02148
02149 he->tag = RPMTAG_PACKAGEDIGEST;
02150 if ((digest = headerGetDigest(h)) != NULL)
02151 {
02152 he->t = RPM_STRING_TYPE;
02153 he->p.str = xstrdup(digest);
02154 he->c = 1;
02155 he->freeData = 1;
02156 rc = 0;
02157 }
02158 return rc;
02159 }
02160
02167 static int pkgmtimeTag(Header h, HE_t he)
02168
02169 {
02170 struct stat * st = headerGetStatbuf(h);
02171 he->tag = RPMTAG_PACKAGETIME;
02172 he->t = RPM_UINT64_TYPE;
02173 he->p.ui64p = xmalloc(sizeof(*he->p.ui64p));
02174
02175 he->p.ui64p[0] = (rpmuint64_t)st->st_mtime;
02176
02177 he->freeData = 1;
02178 he->c = 1;
02179 return 0;
02180 }
02181
02188 static int pkgsizeTag(Header h, HE_t he)
02189
02190 {
02191 struct stat * st = headerGetStatbuf(h);
02192 he->tag = RPMTAG_PACKAGESIZE;
02193 he->t = RPM_UINT64_TYPE;
02194 he->p.ui64p = xmalloc(sizeof(*he->p.ui64p));
02195 he->p.ui64p[0] = (rpmuint64_t)st->st_size;
02196 he->freeData = 1;
02197 he->c = 1;
02198 return 0;
02199 }
02200
02206
02207 static char * hGetNVRA(Header h)
02208
02209
02210 {
02211 const char * N = NULL;
02212 const char * V = NULL;
02213 const char * R = NULL;
02214 const char * A = NULL;
02215 size_t nb = 0;
02216 char * NVRA, * t;
02217
02218 (void) headerNEVRA(h, &N, NULL, &V, &R, &A);
02219 if (N) nb += strlen(N);
02220 if (V) nb += strlen(V) + 1;
02221 if (R) nb += strlen(R) + 1;
02222 #if defined(RPM_VENDOR_OPENPKG)
02223
02224
02225
02226
02227
02228 #else
02229 if (A) nb += strlen(A) + 1;
02230 #endif
02231 nb++;
02232 NVRA = t = xmalloc(nb);
02233 *t = '\0';
02234 if (N) t = stpcpy(t, N);
02235 if (V) t = stpcpy( stpcpy(t, "-"), V);
02236 if (R) t = stpcpy( stpcpy(t, "-"), R);
02237 #if defined(RPM_VENDOR_OPENPKG)
02238
02239
02240
02241
02242
02243 #else
02244 if (A) t = stpcpy( stpcpy(t, "."), A);
02245 #endif
02246 N = _free(N);
02247 V = _free(V);
02248 R = _free(R);
02249 A = _free(A);
02250 return NVRA;
02251 }
02252
02259 static int nvraTag(Header h, HE_t he)
02260
02261
02262 {
02263 he->t = RPM_STRING_TYPE;
02264 he->p.str = hGetNVRA(h);
02265 he->c = 1;
02266 he->freeData = 1;
02267 return 0;
02268 }
02269
02287 static void rpmfiBuildFNames(Header h, rpmTag tagN,
02288 const char *** fnp,
02289 rpmTagCount * fcp)
02290
02291
02292 {
02293 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
02294 rpmTag dirNameTag = 0;
02295 rpmTag dirIndexesTag = 0;
02296 rpmTagData baseNames = { .ptr = NULL };
02297 rpmTagData dirNames = { .ptr = NULL };
02298 rpmTagData dirIndexes = { .ptr = NULL };
02299 rpmTagData fileNames;
02300 rpmTagCount count;
02301 size_t size;
02302 int isSource =
02303 (headerIsEntry(h, RPMTAG_SOURCERPM) == 0 &&
02304 headerIsEntry(h, RPMTAG_ARCH) != 0);
02305 char * t;
02306 unsigned i;
02307 int xx;
02308
02309 if (tagN == RPMTAG_BASENAMES) {
02310 dirNameTag = RPMTAG_DIRNAMES;
02311 dirIndexesTag = RPMTAG_DIRINDEXES;
02312 } else if (tagN == RPMTAG_ORIGBASENAMES) {
02313 dirNameTag = RPMTAG_ORIGDIRNAMES;
02314 dirIndexesTag = RPMTAG_ORIGDIRINDEXES;
02315 } else {
02316 if (fnp) *fnp = NULL;
02317 if (fcp) *fcp = 0;
02318 return;
02319 }
02320
02321
02322 he->tag = tagN;
02323 xx = headerGet(h, he, 0);
02324
02325 if (xx == 0 && isSource) {
02326 he->tag = RPMTAG_OLDFILENAMES;
02327 xx = headerGet(h, he, 0);
02328 if (xx) {
02329 dirNames.argv = xcalloc(3, sizeof(*dirNames.argv));
02330 dirNames.argv[0] = (const char *)&dirNames.argv[2];
02331 dirIndexes.ui32p = xcalloc(he->c, sizeof(*dirIndexes.ui32p));
02332 }
02333 }
02334 baseNames.argv = he->p.argv;
02335 count = he->c;
02336
02337 if (!xx) {
02338 if (fnp) *fnp = NULL;
02339 if (fcp) *fcp = 0;
02340 return;
02341 }
02342
02343 he->tag = dirNameTag;
02344 if ((xx = headerGet(h, he, 0)) != 0)
02345 dirNames.argv = he->p.argv;
02346
02347 he->tag = dirIndexesTag;
02348 if ((xx = headerGet(h, he, 0)) != 0)
02349 dirIndexes.ui32p = he->p.ui32p;
02350
02351
02352 size = sizeof(*fileNames.argv) * count;
02353 for (i = 0; i < (unsigned)count; i++) {
02354 const char * dn = NULL;
02355 (void) urlPath(dirNames.argv[dirIndexes.ui32p[i]], &dn);
02356 size += strlen(baseNames.argv[i]) + strlen(dn) + 1;
02357 }
02358
02359 fileNames.argv = xmalloc(size);
02360 t = (char *)&fileNames.argv[count];
02361 for (i = 0; i < (unsigned)count; i++) {
02362 const char * dn = NULL;
02363 (void) urlPath(dirNames.argv[dirIndexes.ui32p[i]], &dn);
02364 fileNames.argv[i] = t;
02365 t = stpcpy( stpcpy(t, dn), baseNames.argv[i]);
02366 *t++ = '\0';
02367 }
02368 baseNames.ptr = _free(baseNames.ptr);
02369 dirNames.ptr = _free(dirNames.ptr);
02370 dirIndexes.ptr = _free(dirIndexes.ptr);
02371
02372
02373 if (fnp)
02374 *fnp = fileNames.argv;
02375 else
02376 fileNames.ptr = _free(fileNames.ptr);
02377
02378 if (fcp) *fcp = count;
02379 }
02380
02388 static int _fnTag(Header h, HE_t he, rpmTag tag)
02389
02390
02391 {
02392 he->t = RPM_STRING_ARRAY_TYPE;
02393 rpmfiBuildFNames(h, tag, &he->p.argv, &he->c);
02394 he->freeData = 1;
02395 return 0;
02396 }
02397
02398 static int filenamesTag(Header h, HE_t he)
02399
02400
02401 {
02402 he->tag = tagValue("Filenames");
02403 return _fnTag(h, he, RPMTAG_BASENAMES);
02404 }
02405
02406 static int filepathsTag(Header h, HE_t he)
02407
02408
02409 {
02410 he->tag = RPMTAG_FILEPATHS;
02411 return _fnTag(h, he, RPMTAG_BASENAMES);
02412 }
02413
02414 static int origpathsTag(Header h, HE_t he)
02415
02416
02417 {
02418 he->tag = RPMTAG_ORIGPATHS;
02419 return _fnTag(h, he, RPMTAG_ORIGBASENAMES);
02420 }
02421
02431 static int debevrfmtTag( Header h, HE_t he,
02432 HE_t Nhe, HE_t EVRhe, HE_t Fhe)
02433
02434
02435 {
02436 char * t, * te;
02437 size_t nb = 0;
02438 int rc = 1;
02439
02440 he->t = RPM_STRING_ARRAY_TYPE;
02441 he->c = 0;
02442 he->freeData = 1;
02443 for (Nhe->ix = 0; Nhe->ix < (int)Nhe->c; Nhe->ix++) {
02444 nb += sizeof(*he->p.argv);
02445 nb += strlen(Nhe->p.argv[Nhe->ix]) + 1;
02446 if (*EVRhe->p.argv[Nhe->ix] != '\0')
02447 nb += strlen(EVRhe->p.argv[Nhe->ix]) + (sizeof(" (== )")-1);
02448 he->c++;
02449 }
02450 nb += sizeof(*he->p.argv);
02451
02452 he->p.argv = xmalloc(nb);
02453 te = (char *) &he->p.argv[he->c+1];
02454
02455 he->c = 0;
02456 for (Nhe->ix = 0; Nhe->ix < (int)Nhe->c; Nhe->ix++) {
02457 he->p.argv[he->c++] = te;
02458 if (*EVRhe->p.argv[Nhe->ix] != '\0') {
02459 char opstr[4], * op = opstr;
02460 if (Fhe->p.ui32p[Nhe->ix] & RPMSENSE_LESS)
02461 *op++ = '<';
02462 if (Fhe->p.ui32p[Nhe->ix] & RPMSENSE_GREATER)
02463 *op++ = '>';
02464 if (Fhe->p.ui32p[Nhe->ix] & RPMSENSE_EQUAL)
02465 *op++ = '=';
02466 *op = '\0';
02467 t = rpmExpand(Nhe->p.argv[Nhe->ix],
02468 " (", opstr, " ", EVRhe->p.argv[Nhe->ix], ")", NULL);
02469 } else
02470 t = rpmExpand(Nhe->p.argv[Nhe->ix], NULL);
02471 te = stpcpy(te, t);
02472 te++;
02473 t = _free(t);
02474 }
02475 he->p.argv[he->c] = NULL;
02476 rc = 0;
02477
02478 return rc;
02479 }
02480
02490 static int debevrTag(Header h, HE_t he, rpmTag tagN, rpmTag tagEVR, rpmTag tagF)
02491
02492
02493 {
02494 HE_t Nhe = memset(alloca(sizeof(*Nhe)), 0, sizeof(*Nhe));
02495 HE_t EVRhe = memset(alloca(sizeof(*EVRhe)), 0, sizeof(*EVRhe));
02496 HE_t Fhe = memset(alloca(sizeof(*Fhe)), 0, sizeof(*Fhe));
02497 int rc = 1;
02498 int xx;
02499
02500 Nhe->tag = tagN;
02501 if (!(xx = headerGet(h, Nhe, 0)))
02502 goto exit;
02503 EVRhe->tag = tagEVR;
02504 if (!(xx = headerGet(h, EVRhe, 0)))
02505 goto exit;
02506 assert(EVRhe->c == Nhe->c);
02507 Fhe->tag = tagF;
02508 if (!(xx = headerGet(h, Fhe, 0)))
02509 goto exit;
02510 assert(Fhe->c == Nhe->c);
02511
02512 rc = debevrfmtTag(h, he, Nhe, EVRhe, Fhe);
02513
02514 exit:
02515 Nhe->p.ptr = _free(Nhe->p.ptr);
02516 EVRhe->p.ptr = _free(EVRhe->p.ptr);
02517 Fhe->p.ptr = _free(Fhe->p.ptr);
02518 return rc;
02519 }
02520
02527 static int debconflictsTag(Header h, HE_t he)
02528
02529
02530 {
02531 he->tag = tagValue("Debconflicts");
02532 return debevrTag(h, he,
02533 RPMTAG_CONFLICTNAME, RPMTAG_CONFLICTVERSION, RPMTAG_CONFLICTFLAGS);
02534 }
02535
02536 static int debdependsTag(Header h, HE_t he)
02537
02538
02539 {
02540 he->tag = tagValue("Debdepends");
02541 return debevrTag(h, he,
02542 RPMTAG_REQUIRENAME, RPMTAG_REQUIREVERSION, RPMTAG_REQUIREFLAGS);
02543 }
02544
02545 static int debobsoletesTag(Header h, HE_t he)
02546
02547
02548 {
02549 he->tag = tagValue("Debobsoletes");
02550 return debevrTag(h, he,
02551 RPMTAG_OBSOLETENAME, RPMTAG_OBSOLETEVERSION, RPMTAG_OBSOLETEFLAGS);
02552 }
02553
02554 static int debprovidesTag(Header h, HE_t he)
02555
02556
02557 {
02558 he->tag = tagValue("Debprovides");
02559 return debevrTag(h, he,
02560 RPMTAG_PROVIDENAME, RPMTAG_PROVIDEVERSION, RPMTAG_PROVIDEFLAGS);
02561 }
02562
02569 static int debmd5sumsTag(Header h, HE_t he)
02570
02571
02572 {
02573 HE_t Nhe = memset(alloca(sizeof(*Nhe)), 0, sizeof(*Nhe));
02574 HE_t Dhe = memset(alloca(sizeof(*Dhe)), 0, sizeof(*Dhe));
02575 char * t, * te;
02576 size_t nb = 0;
02577 int rc = 1;
02578 int xx;
02579
02580 Nhe->tag = RPMTAG_FILEPATHS;
02581 if (!(xx = headerGet(h, Nhe, 0)))
02582 goto exit;
02583 Dhe->tag = RPMTAG_FILEDIGESTS;
02584 if (!(xx = headerGet(h, Dhe, 0)))
02585 goto exit;
02586 assert(Dhe->c == Nhe->c);
02587
02588 he->tag = tagValue("Debmd5sums");
02589 he->t = RPM_STRING_ARRAY_TYPE;
02590 he->c = 0;
02591 he->freeData = 1;
02592 for (Dhe->ix = 0; Dhe->ix < (int)Dhe->c; Dhe->ix++) {
02593 if (!(Dhe->p.argv[Dhe->ix] && *Dhe->p.argv[Dhe->ix]))
02594 continue;
02595 nb += sizeof(*he->p.argv);
02596 nb += strlen(Dhe->p.argv[Dhe->ix]) + sizeof(" ") + strlen(Nhe->p.argv[Dhe->ix]) - 1;
02597 he->c++;
02598 }
02599 nb += sizeof(*he->p.argv);
02600
02601 he->p.argv = xmalloc(nb);
02602 te = (char *) &he->p.argv[he->c+1];
02603
02604 he->c = 0;
02605 for (Dhe->ix = 0; Dhe->ix < (int)Dhe->c; Dhe->ix++) {
02606 if (!(Dhe->p.argv[Dhe->ix] && *Dhe->p.argv[Dhe->ix]))
02607 continue;
02608 he->p.argv[he->c++] = te;
02609 t = rpmExpand(Dhe->p.argv[Dhe->ix], " ", Nhe->p.argv[Dhe->ix]+1, NULL);
02610 te = stpcpy(te, t);
02611 te++;
02612 t = _free(t);
02613 }
02614 he->p.argv[he->c] = NULL;
02615 rc = 0;
02616
02617 exit:
02618 Nhe->p.ptr = _free(Nhe->p.ptr);
02619 Dhe->p.ptr = _free(Dhe->p.ptr);
02620 return rc;
02621 }
02622
02623 static int filestatTag(Header h, HE_t he)
02624
02625
02626 {
02627 rpmTagData paths = { .ptr = NULL };
02628
02629 rpmTagData _ino = { .ptr = NULL };
02630 rpmTagData _mode = { .ptr = NULL };
02631
02632
02633
02634 rpmTagData _rdev = { .ptr = NULL };
02635 rpmTagData _size = { .ptr = NULL };
02636
02637
02638
02639 rpmTagData _mtime = { .ptr = NULL };
02640
02641 int rc;
02642
02643 he->tag = RPMTAG_FILEPATHS;
02644 if ((rc = _fnTag(h, he, RPMTAG_BASENAMES)) != 0 || he->c == 0)
02645 goto exit;
02646
02647 exit:
02648 paths.ptr = _free(paths.ptr);
02649 _ino.ptr = _free(_ino.ptr);
02650 _mode.ptr = _free(_mode.ptr);
02651 _rdev.ptr = _free(_rdev.ptr);
02652 _size.ptr = _free(_size.ptr);
02653 _mtime.ptr = _free(_mtime.ptr);
02654 return rc;
02655 }
02656
02657 static int wnlookupTag(Header h, rpmTag tagNVRA, ARGV_t *avp, ARGI_t *hitp,
02658 HE_t PNhe, HE_t PEVRhe, HE_t PFhe)
02659
02660
02661
02662
02663 {
02664 HE_t NVRAhe = memset(alloca(sizeof(*NVRAhe)), 0, sizeof(*NVRAhe));
02665 HE_t RNhe = memset(alloca(sizeof(*RNhe)), 0, sizeof(*RNhe));
02666 HE_t REVRhe = memset(alloca(sizeof(*REVRhe)), 0, sizeof(*REVRhe));
02667 HE_t RFhe = memset(alloca(sizeof(*RFhe)), 0, sizeof(*RFhe));
02668 rpmdb _rpmdb = (rpmdb) headerGetRpmdb(h);
02669 const char * key = PNhe->p.argv[PNhe->ix];
02670 size_t keylen = 0;
02671 rpmmi mi;
02672 rpmTag tagN = RPMTAG_REQUIRENAME;
02673 rpmTag tagEVR = RPMTAG_REQUIREVERSION;
02674 rpmTag tagF = RPMTAG_REQUIREFLAGS;
02675 rpmuint32_t PFlags;
02676 rpmuint32_t RFlags;
02677 EVR_t Pevr;
02678 Header oh;
02679 int rc = 0;
02680 int xx;
02681
02682 if (tagNVRA == 0)
02683 tagNVRA = RPMTAG_NVRA;
02684
02685 PFlags = (PFhe != NULL ? (PFhe->p.ui32p[PNhe->ix] & RPMSENSE_SENSEMASK) : 0);
02686 Pevr = rpmEVRnew(PFlags, 1);
02687
02688 if (PEVRhe != NULL)
02689 xx = rpmEVRparse(xstrdup(PEVRhe->p.argv[PNhe->ix]), Pevr);
02690
02691 RNhe->tag = tagN;
02692 REVRhe->tag = tagEVR;
02693 RFhe->tag = tagF;
02694
02695 mi = rpmmiInit(_rpmdb, tagN, key, keylen);
02696 if (hitp && *hitp)
02697 xx = rpmmiPrune(mi, (int *)argiData(*hitp), argiCount(*hitp), 0);
02698 while ((oh = rpmmiNext(mi)) != NULL) {
02699 if (!headerGet(oh, RNhe, 0))
02700 goto bottom;
02701 if (PEVRhe != NULL) {
02702 if (!headerGet(oh, REVRhe, 0))
02703 goto bottom;
02704 assert(REVRhe->c == RNhe->c);
02705 if (!headerGet(oh, RFhe, 0))
02706 goto bottom;
02707 assert(RFhe->c == RNhe->c);
02708 }
02709
02710 for (RNhe->ix = 0; RNhe->ix < (int)RNhe->c; RNhe->ix++) {
02711 if (strcmp(PNhe->p.argv[PNhe->ix], RNhe->p.argv[RNhe->ix]))
02712 continue;
02713 if (PEVRhe == NULL)
02714 goto bingo;
02715 RFlags = RFhe->p.ui32p[RNhe->ix] & RPMSENSE_SENSEMASK;
02716 { EVR_t Revr = rpmEVRnew(RFlags, 1);
02717 if (!(PFlags && RFlags))
02718 xx = 1;
02719 else {
02720 xx = rpmEVRparse(REVRhe->p.argv[RNhe->ix], Revr);
02721 xx = rpmEVRoverlap(Pevr, Revr);
02722 }
02723 Revr = rpmEVRfree(Revr);
02724 }
02725 if (xx)
02726 goto bingo;
02727 }
02728 goto bottom;
02729
02730 bingo:
02731 NVRAhe->tag = tagNVRA;
02732 xx = headerGet(oh, NVRAhe, 0);
02733 if (!(*avp != NULL && argvSearch(*avp, NVRAhe->p.str, NULL) != NULL)) {
02734 xx = argvAdd(avp, NVRAhe->p.str);
02735 xx = argvSort(*avp, NULL);
02736 if (hitp != NULL)
02737 xx = argiAdd(hitp, -1, rpmmiInstance(mi));
02738 rc++;
02739 }
02740
02741 bottom:
02742 RNhe->p.ptr = _free(RNhe->p.ptr);
02743 REVRhe->p.ptr = _free(REVRhe->p.ptr);
02744 RFhe->p.ptr = _free(RFhe->p.ptr);
02745 NVRAhe->p.ptr = _free(NVRAhe->p.ptr);
02746 }
02747 mi = rpmmiFree(mi);
02748
02749 Pevr = rpmEVRfree(Pevr);
02750
02751 return rc;
02752 }
02753
02754 static int whatneedsTag(Header h, HE_t he)
02755
02756
02757 {
02758 HE_t NVRAhe = memset(alloca(sizeof(*NVRAhe)), 0, sizeof(*NVRAhe));
02759 HE_t PNhe = memset(alloca(sizeof(*PNhe)), 0, sizeof(*PNhe));
02760 HE_t PEVRhe = memset(alloca(sizeof(*PEVRhe)), 0, sizeof(*PEVRhe));
02761 HE_t PFhe = memset(alloca(sizeof(*PFhe)), 0, sizeof(*PFhe));
02762 HE_t FNhe = memset(alloca(sizeof(*FNhe)), 0, sizeof(*FNhe));
02763 rpmTag tagNVRA = RPMTAG_NVRA;
02764 ARGV_t pkgs = NULL;
02765 ARGI_t hits = NULL;
02766 int rc = 1;
02767
02768 PNhe->tag = RPMTAG_PROVIDENAME;
02769 if (!headerGet(h, PNhe, 0))
02770 goto exit;
02771 PEVRhe->tag = RPMTAG_PROVIDEVERSION;
02772 if (!headerGet(h, PEVRhe, 0))
02773 goto exit;
02774 assert(PEVRhe->c == PNhe->c);
02775 PFhe->tag = RPMTAG_PROVIDEFLAGS;
02776 if (!headerGet(h, PFhe, 0))
02777 goto exit;
02778 assert(PFhe->c == PNhe->c);
02779
02780 FNhe->tag = RPMTAG_FILEPATHS;
02781 if (!headerGet(h, FNhe, 0))
02782 goto exit;
02783
02784 NVRAhe->tag = tagNVRA;;
02785 if (!headerGet(h, NVRAhe, 0))
02786 goto exit;
02787
02788 (void) argvAdd(&pkgs, NVRAhe->p.str);
02789
02790 for (PNhe->ix = 0; PNhe->ix < (int)PNhe->c; PNhe->ix++)
02791 (void) wnlookupTag(h, tagNVRA, &pkgs, &hits, PNhe, PEVRhe, PFhe);
02792 for (FNhe->ix = 0; FNhe->ix < (int)FNhe->c; FNhe->ix++)
02793 (void) wnlookupTag(h, tagNVRA, &pkgs, &hits, FNhe, NULL, NULL);
02794
02795
02796 { size_t nb = 0;
02797 char * te;
02798 rpmuint32_t i;
02799
02800 he->t = RPM_STRING_ARRAY_TYPE;
02801 he->c = argvCount(pkgs);
02802 nb = 0;
02803 for (i = 0; i < he->c; i++) {
02804 nb += sizeof(*he->p.argv);
02805 nb += strlen(pkgs[i]) + 1;
02806 }
02807 nb += sizeof(*he->p.argv);
02808
02809 he->p.argv = xmalloc(nb);
02810 te = (char *) &he->p.argv[he->c+1];
02811
02812 for (i = 0; i < he->c; i++) {
02813 he->p.argv[i] = te;
02814 te = stpcpy(te, pkgs[i]);
02815 te++;
02816 }
02817 he->p.argv[he->c] = NULL;
02818 }
02819
02820 hits = argiFree(hits);
02821 pkgs = argvFree(pkgs);
02822 rc = 0;
02823
02824 exit:
02825 NVRAhe->p.ptr = _free(NVRAhe->p.ptr);
02826 PNhe->p.ptr = _free(PNhe->p.ptr);
02827 PEVRhe->p.ptr = _free(PEVRhe->p.ptr);
02828 PFhe->p.ptr = _free(PFhe->p.ptr);
02829 FNhe->p.ptr = _free(FNhe->p.ptr);
02830 return rc;
02831 }
02832
02833 static int nwlookupTag(Header h, rpmTag tagNVRA, ARGV_t *avp, ARGI_t *hitp,
02834 HE_t RNhe, HE_t REVRhe, HE_t RFhe)
02835
02836
02837
02838
02839 {
02840 HE_t NVRAhe = memset(alloca(sizeof(*NVRAhe)), 0, sizeof(*NVRAhe));
02841 HE_t PNhe = memset(alloca(sizeof(*PNhe)), 0, sizeof(*PNhe));
02842 HE_t PEVRhe = memset(alloca(sizeof(*PEVRhe)), 0, sizeof(*PEVRhe));
02843 HE_t PFhe = memset(alloca(sizeof(*PFhe)), 0, sizeof(*PFhe));
02844 rpmdb _rpmdb = (rpmdb) headerGetRpmdb(h);
02845 const char * key = RNhe->p.argv[RNhe->ix];
02846 size_t keylen = 0;
02847 rpmmi mi;
02848 rpmTag tagN = tagN = (*RNhe->p.argv[RNhe->ix] == '/')
02849 ? RPMTAG_BASENAMES : RPMTAG_PROVIDENAME;
02850 rpmTag tagEVR = RPMTAG_PROVIDEVERSION;
02851 rpmTag tagF = RPMTAG_PROVIDEFLAGS;
02852 rpmuint32_t PFlags;
02853 rpmuint32_t RFlags;
02854 EVR_t Revr;
02855 Header oh;
02856 int rc = 0;
02857 int xx;
02858
02859 if (tagNVRA == 0)
02860 tagNVRA = RPMTAG_NVRA;
02861
02862 RFlags = (RFhe != NULL ? (RFhe->p.ui32p[RNhe->ix] & RPMSENSE_SENSEMASK) : 0);
02863 Revr = rpmEVRnew(RFlags, 1);
02864
02865 if (REVRhe != NULL)
02866 xx = rpmEVRparse(REVRhe->p.argv[RNhe->ix], Revr);
02867
02868 PNhe->tag = tagN;
02869 PEVRhe->tag = tagEVR;
02870 PFhe->tag = tagF;
02871
02872 mi = rpmmiInit(_rpmdb, tagN, key, keylen);
02873 if (hitp && *hitp)
02874 xx = rpmmiPrune(mi, (int *)argiData(*hitp), argiCount(*hitp), 0);
02875 while ((oh = rpmmiNext(mi)) != NULL) {
02876 if (!headerGet(oh, PNhe, 0))
02877 goto bottom;
02878 if (REVRhe != NULL) {
02879 if (!headerGet(oh, PEVRhe, 0))
02880 goto bottom;
02881 assert(PEVRhe->c == PNhe->c);
02882 if (!headerGet(oh, PFhe, 0))
02883 goto bottom;
02884 assert(PFhe->c == PNhe->c);
02885 }
02886
02887 for (PNhe->ix = 0; PNhe->ix < (int)PNhe->c; PNhe->ix++) {
02888 if (strcmp(RNhe->p.argv[RNhe->ix], PNhe->p.argv[PNhe->ix]))
02889 continue;
02890 if (REVRhe == NULL)
02891 goto bingo;
02892 PFlags = PFhe->p.ui32p[PNhe->ix] & RPMSENSE_SENSEMASK;
02893 { EVR_t Pevr = rpmEVRnew(PFlags, 1);
02894 if (!(PFlags && RFlags))
02895 xx = 1;
02896 else {
02897 xx = rpmEVRparse(PEVRhe->p.argv[PNhe->ix], Pevr);
02898 xx = rpmEVRoverlap(Revr, Pevr);
02899 }
02900 Pevr = rpmEVRfree(Pevr);
02901 }
02902 if (xx)
02903 goto bingo;
02904 }
02905 goto bottom;
02906
02907 bingo:
02908 NVRAhe->tag = tagNVRA;
02909 xx = headerGet(oh, NVRAhe, 0);
02910 if (!(*avp != NULL && argvSearch(*avp, NVRAhe->p.str, NULL) != NULL)) {
02911 xx = argvAdd(avp, NVRAhe->p.str);
02912 xx = argvSort(*avp, NULL);
02913 if (hitp != NULL)
02914 xx = argiAdd(hitp, -1, rpmmiInstance(mi));
02915 rc++;
02916 }
02917
02918 bottom:
02919 PNhe->p.ptr = _free(PNhe->p.ptr);
02920 PEVRhe->p.ptr = _free(PEVRhe->p.ptr);
02921 PFhe->p.ptr = _free(PFhe->p.ptr);
02922 NVRAhe->p.ptr = _free(NVRAhe->p.ptr);
02923 }
02924 mi = rpmmiFree(mi);
02925
02926 Revr = rpmEVRfree(Revr);
02927
02928 return rc;
02929 }
02930
02931 static int needswhatTag(Header h, HE_t he)
02932
02933
02934 {
02935 HE_t NVRAhe = memset(alloca(sizeof(*NVRAhe)), 0, sizeof(*NVRAhe));
02936 HE_t RNhe = memset(alloca(sizeof(*RNhe)), 0, sizeof(*RNhe));
02937 HE_t REVRhe = memset(alloca(sizeof(*REVRhe)), 0, sizeof(*REVRhe));
02938 HE_t RFhe = memset(alloca(sizeof(*RFhe)), 0, sizeof(*RFhe));
02939 rpmTag tagNVRA = RPMTAG_NVRA;
02940 ARGV_t pkgs = NULL;
02941 ARGI_t hits = NULL;
02942 int rc = 1;
02943
02944 RNhe->tag = RPMTAG_REQUIRENAME;
02945 if (!headerGet(h, RNhe, 0))
02946 goto exit;
02947 REVRhe->tag = RPMTAG_REQUIREVERSION;
02948 if (!headerGet(h, REVRhe, 0))
02949 goto exit;
02950 assert(REVRhe->c == RNhe->c);
02951 RFhe->tag = RPMTAG_REQUIREFLAGS;
02952 if (!headerGet(h, RFhe, 0))
02953 goto exit;
02954 assert(RFhe->c == RNhe->c);
02955
02956 NVRAhe->tag = tagNVRA;;
02957 if (!headerGet(h, NVRAhe, 0))
02958 goto exit;
02959
02960 (void) argvAdd(&pkgs, NVRAhe->p.str);
02961
02962 for (RNhe->ix = 0; RNhe->ix < (int)RNhe->c; RNhe->ix++) {
02963 if (*RNhe->p.argv[RNhe->ix] == '/' || *REVRhe->p.argv[RNhe->ix] == '\0')
02964 (void) nwlookupTag(h, tagNVRA, &pkgs, &hits, RNhe, NULL, NULL);
02965 else
02966 (void) nwlookupTag(h, tagNVRA, &pkgs, &hits, RNhe, REVRhe, RFhe);
02967 }
02968
02969
02970 { size_t nb = 0;
02971 char * te;
02972 rpmuint32_t i;
02973
02974 he->t = RPM_STRING_ARRAY_TYPE;
02975 he->c = argvCount(pkgs);
02976 nb = 0;
02977 for (i = 0; i < he->c; i++) {
02978 nb += sizeof(*he->p.argv);
02979 nb += strlen(pkgs[i]) + 1;
02980 }
02981 nb += sizeof(*he->p.argv);
02982
02983 he->p.argv = xmalloc(nb);
02984 te = (char *) &he->p.argv[he->c+1];
02985
02986 for (i = 0; i < he->c; i++) {
02987 he->p.argv[i] = te;
02988 te = stpcpy(te, pkgs[i]);
02989 te++;
02990 }
02991 he->p.argv[he->c] = NULL;
02992 }
02993
02994 hits = argiFree(hits);
02995 pkgs = argvFree(pkgs);
02996 rc = 0;
02997
02998 exit:
02999 NVRAhe->p.ptr = _free(NVRAhe->p.ptr);
03000 RNhe->p.ptr = _free(RNhe->p.ptr);
03001 REVRhe->p.ptr = _free(REVRhe->p.ptr);
03002 RFhe->p.ptr = _free(RFhe->p.ptr);
03003 return rc;
03004 }
03005
03006 static int PRCOSkip(rpmTag tag, rpmTagData N, rpmTagData EVR, rpmTagData F,
03007 rpmuint32_t i)
03008
03009 {
03010 int a = -2, b = -2;
03011
03012 if (N.argv[i] == NULL || *N.argv[i] == '\0')
03013 return 1;
03014 if (tag == RPMTAG_REQUIRENAME && i > 0
03015 && !(a=strcmp(N.argv[i], N.argv[i-1]))
03016 && !(b=strcmp(EVR.argv[i], EVR.argv[i-1]))
03017 && (F.ui32p[i] & 0x4e) == ((F.ui32p[i-1] & 0x4e)))
03018 return 1;
03019 return 0;
03020 }
03021
03022 static int PRCOxmlTag(Header h, HE_t he, rpmTag EVRtag, rpmTag Ftag)
03023
03024
03025 {
03026 rpmTag tag = he->tag;
03027 rpmTagData N = { .ptr = NULL };
03028 rpmTagData EVR = { .ptr = NULL };
03029 rpmTagData F = { .ptr = NULL };
03030 size_t nb;
03031 rpmuint32_t ac;
03032 rpmuint32_t c;
03033 rpmuint32_t i;
03034 char *t;
03035 int rc = 1;
03036 int xx;
03037
03038
03039 xx = headerGet(h, he, 0);
03040 if (xx == 0) goto exit;
03041 N.argv = he->p.argv;
03042 c = he->c;
03043
03044 he->tag = EVRtag;
03045 xx = headerGet(h, he, 0);
03046 if (xx == 0) goto exit;
03047 EVR.argv = he->p.argv;
03048
03049 he->tag = Ftag;
03050 xx = headerGet(h, he, 0);
03051 if (xx == 0) goto exit;
03052 F.ui32p = he->p.ui32p;
03053
03054 nb = sizeof(*he->p.argv);
03055 ac = 0;
03056 for (i = 0; i < c; i++) {
03057
03058 if (PRCOSkip(tag, N, EVR, F, i))
03059 continue;
03060
03061 ac++;
03062 nb += sizeof(*he->p.argv);
03063 nb += sizeof("<rpm:entry name=\"\"/>");
03064 if (*N.argv[i] == '/')
03065 nb += xmlstrlen(N.argv[i]);
03066 else
03067 nb += strlen(N.argv[i]);
03068 if (EVR.argv != NULL && EVR.argv[i] != NULL && *EVR.argv[i] != '\0') {
03069 nb += sizeof(" flags=\"EQ\" epoch=\"0\" ver=\"\"") - 1;
03070 nb += strlen(EVR.argv[i]);
03071 if (strchr(EVR.argv[i], ':') != NULL)
03072 nb -= 2;
03073 if (strchr(EVR.argv[i], '-') != NULL)
03074 nb += sizeof(" rel=\"\"") - 2;
03075 }
03076 #ifdef NOTNOW
03077 if (tag == RPMTAG_REQUIRENAME && (F.ui32p[i] & 0x40))
03078 nb += sizeof(" pre=\"1\"") - 1;
03079 #endif
03080 }
03081
03082 he->t = RPM_STRING_ARRAY_TYPE;
03083 he->c = ac;
03084 he->freeData = 1;
03085 he->p.argv = xmalloc(nb + BUFSIZ);
03086 t = (char *) &he->p.argv[he->c + 1];
03087 ac = 0;
03088 for (i = 0; i < c; i++) {
03089
03090 if (PRCOSkip(tag, N, EVR, F, i))
03091 continue;
03092
03093 he->p.argv[ac++] = t;
03094 t = stpcpy(t, "<rpm:entry");
03095 t = stpcpy(t, " name=\"");
03096 if (*N.argv[i] == '/') {
03097 t = xmlstrcpy(t, N.argv[i]); t += strlen(t);
03098 } else
03099 t = stpcpy(t, N.argv[i]);
03100 t = stpcpy(t, "\"");
03101
03102 if (EVR.argv != NULL && EVR.argv[i] != NULL && *EVR.argv[i] != '\0') {
03103 static char *Fstr[] = { "?0","LT","GT","?3","EQ","LE","GE","?7" };
03104 rpmuint32_t Fx = ((F.ui32p[i] >> 1) & 0x7);
03105 const char *E, *V, *R;
03106 char *f, *fe;
03107 t = stpcpy( stpcpy( stpcpy(t, " flags=\""), Fstr[Fx]), "\"");
03108 f = (char *) EVR.argv[i];
03109 for (fe = f; *fe != '\0' && *fe >= '0' && *fe <= '9'; fe++)
03110 {};
03111 if (*fe == ':') { *fe++ = '\0'; E = f; f = fe; } else E = NULL;
03112 V = f;
03113 for (fe = f; *fe != '\0' && *fe != '-'; fe++)
03114 {};
03115 if (*fe == '-') { *fe++ = '\0'; R = fe; } else R = NULL;
03116 t = stpcpy( stpcpy( stpcpy(t, " epoch=\""), (E && *E ? E : "0")), "\"");
03117 t = stpcpy( stpcpy( stpcpy(t, " ver=\""), V), "\"");
03118 if (R != NULL)
03119 t = stpcpy( stpcpy( stpcpy(t, " rel=\""), R), "\"");
03120 }
03121
03122 #ifdef NOTNOW
03123 if (tag == RPMTAG_REQUIRENAME && (F.ui32p[i] & 0x40))
03124 t = stpcpy(t, " pre=\"1\"");
03125 #endif
03126 t = stpcpy(t, "/>");
03127 *t++ = '\0';
03128 }
03129 he->p.argv[he->c] = NULL;
03130
03131 rc = 0;
03132
03133 exit:
03134
03135 N.argv = _free(N.argv);
03136
03137
03138 EVR.argv = _free(EVR.argv);
03139
03140 F.ui32p = _free(F.ui32p);
03141 return rc;
03142 }
03143
03144 static int PxmlTag(Header h, HE_t he)
03145
03146
03147 {
03148 he->tag = RPMTAG_PROVIDENAME;
03149 return PRCOxmlTag(h, he, RPMTAG_PROVIDEVERSION, RPMTAG_PROVIDEFLAGS);
03150 }
03151
03152 static int RxmlTag(Header h, HE_t he)
03153
03154
03155 {
03156 he->tag = RPMTAG_REQUIRENAME;
03157 return PRCOxmlTag(h, he, RPMTAG_REQUIREVERSION, RPMTAG_REQUIREFLAGS);
03158 }
03159
03160 static int CxmlTag(Header h, HE_t he)
03161
03162
03163 {
03164 he->tag = RPMTAG_CONFLICTNAME;
03165 return PRCOxmlTag(h, he, RPMTAG_CONFLICTVERSION, RPMTAG_CONFLICTFLAGS);
03166 }
03167
03168 static int OxmlTag(Header h, HE_t he)
03169
03170
03171 {
03172 he->tag = RPMTAG_OBSOLETENAME;
03173 return PRCOxmlTag(h, he, RPMTAG_OBSOLETEVERSION, RPMTAG_OBSOLETEFLAGS);
03174 }
03175
03181 static size_t sqlstrlen(const char * s)
03182
03183 {
03184 size_t len = 0;
03185 int c;
03186
03187 while ((c = (int) *s++) != (int) '\0') {
03188 switch (c) {
03189 case '\'': len += 1;
03190 default: len += 1; break;
03191 }
03192 }
03193 return len;
03194 }
03195
03202 static char * sqlstrcpy( char * t, const char * s)
03203
03204 {
03205 char * te = t;
03206 int c;
03207
03208 while ((c = (int) *s++) != (int) '\0') {
03209 switch (c) {
03210 case '\'': *te++ = (char) c;
03211 default: *te++ = (char) c; break;
03212 }
03213 }
03214 *te = '\0';
03215 return t;
03216 }
03217
03224 static char * sqlescapeFormat(HE_t he, const char ** av)
03225
03226 {
03227 int ix = (he->ix > 0 ? he->ix : 0);
03228 char * val;
03229
03230 assert(ix == 0);
03231 if (he->t != RPM_STRING_TYPE) {
03232 val = xstrdup(_("(not a string)"));
03233 } else {
03234 const char * s = strdup_locale_convert(he->p.str, (av ? av[0] : NULL));
03235 size_t nb;
03236 char * t;
03237
03238 if (s == NULL) {
03239
03240 val = xstrdup(_("(not a string)"));
03241 goto exit;
03242 }
03243
03244 nb = sqlstrlen(s);
03245 val = t = xcalloc(1, nb + 1);
03246 t = sqlstrcpy(t, s); t += strlen(t);
03247 *t = '\0';
03248 s = _free(s);
03249 }
03250
03251 exit:
03252 return val;
03253 }
03254
03255
03256 static int PRCOsqlTag(Header h, HE_t he, rpmTag EVRtag, rpmTag Ftag)
03257
03258
03259 {
03260 rpmTag tag = he->tag;
03261 rpmTagData N = { .ptr = NULL };
03262 rpmTagData EVR = { .ptr = NULL };
03263 rpmTagData F = { .ptr = NULL };
03264 char instance[64];
03265 size_t nb;
03266 rpmuint32_t ac;
03267 rpmuint32_t c;
03268 rpmuint32_t i;
03269 char *t;
03270 int rc = 1;
03271 int xx;
03272
03273
03274 xx = headerGet(h, he, 0);
03275 if (xx == 0) goto exit;
03276 N.argv = he->p.argv;
03277 c = he->c;
03278
03279 he->tag = EVRtag;
03280 xx = headerGet(h, he, 0);
03281 if (xx == 0) goto exit;
03282 EVR.argv = he->p.argv;
03283
03284 he->tag = Ftag;
03285 xx = headerGet(h, he, 0);
03286 if (xx == 0) goto exit;
03287 F.ui32p = he->p.ui32p;
03288
03289 xx = snprintf(instance, sizeof(instance), "'%u'", (unsigned)headerGetInstance(h));
03290 nb = sizeof(*he->p.argv);
03291 ac = 0;
03292 for (i = 0; i < c; i++) {
03293
03294 if (PRCOSkip(tag, N, EVR, F, i))
03295 continue;
03296
03297 ac++;
03298 nb += sizeof(*he->p.argv);
03299 nb += strlen(instance) + sizeof(", '', '', '', '', ''");
03300 if (tag == RPMTAG_REQUIRENAME)
03301 nb += sizeof(", ''") - 1;
03302 nb += strlen(N.argv[i]);
03303 if (EVR.argv != NULL && EVR.argv[i] != NULL && *EVR.argv[i] != '\0') {
03304 nb += strlen(EVR.argv[i]);
03305 nb += sizeof("EQ0") - 1;
03306 }
03307 #ifdef NOTNOW
03308 if (tag == RPMTAG_REQUIRENAME && (F.ui32p[i] & 0x40))
03309 nb += sizeof("1") - 1;
03310 #endif
03311 }
03312
03313 he->t = RPM_STRING_ARRAY_TYPE;
03314 he->c = ac;
03315 he->freeData = 1;
03316 he->p.argv = xmalloc(nb + BUFSIZ);
03317 t = (char *) &he->p.argv[he->c + 1];
03318 ac = 0;
03319 for (i = 0; i < c; i++) {
03320
03321 if (PRCOSkip(tag, N, EVR, F, i))
03322 continue;
03323
03324 he->p.argv[ac++] = t;
03325 t = stpcpy(t, instance);
03326 t = stpcpy( stpcpy( stpcpy(t, ", '"), N.argv[i]), "'");
03327
03328 if (EVR.argv != NULL && EVR.argv[i] != NULL && *EVR.argv[i] != '\0') {
03329 static char *Fstr[] = { "?0","LT","GT","?3","EQ","LE","GE","?7" };
03330 rpmuint32_t Fx = ((F.ui32p[i] >> 1) & 0x7);
03331 const char *E, *V, *R;
03332 char *f, *fe;
03333 t = stpcpy( stpcpy( stpcpy(t, ", '"), Fstr[Fx]), "'");
03334 f = (char *) EVR.argv[i];
03335 for (fe = f; *fe != '\0' && *fe >= '0' && *fe <= '9'; fe++)
03336 {};
03337 if (*fe == ':') { *fe++ = '\0'; E = f; f = fe; } else E = NULL;
03338 V = f;
03339 for (fe = f; *fe != '\0' && *fe != '-'; fe++)
03340 {};
03341 if (*fe == '-') { *fe++ = '\0'; R = fe; } else R = NULL;
03342 t = stpcpy( stpcpy( stpcpy(t, ", '"), (E && *E ? E : "0")), "'");
03343 t = stpcpy( stpcpy( stpcpy(t, ", '"), V), "'");
03344 t = stpcpy( stpcpy( stpcpy(t, ", '"), (R ? R : "")), "'");
03345 } else
03346 t = stpcpy(t, ", '', '', '', ''");
03347
03348 #ifdef NOTNOW
03349 if (tag == RPMTAG_REQUIRENAME)
03350 t = stpcpy(stpcpy(stpcpy(t, ", '"),(F.ui32p[i] & 0x40) ? "1" : "0"), "'");
03351 #endif
03352 *t++ = '\0';
03353 }
03354 he->p.argv[he->c] = NULL;
03355
03356 rc = 0;
03357
03358 exit:
03359
03360 N.argv = _free(N.argv);
03361
03362
03363 EVR.argv = _free(EVR.argv);
03364
03365 F.ui32p = _free(F.ui32p);
03366 return rc;
03367 }
03368
03369 static int PsqlTag(Header h, HE_t he)
03370
03371
03372 {
03373 he->tag = RPMTAG_PROVIDENAME;
03374 return PRCOsqlTag(h, he, RPMTAG_PROVIDEVERSION, RPMTAG_PROVIDEFLAGS);
03375 }
03376
03377 static int RsqlTag(Header h, HE_t he)
03378
03379
03380 {
03381 he->tag = RPMTAG_REQUIRENAME;
03382 return PRCOsqlTag(h, he, RPMTAG_REQUIREVERSION, RPMTAG_REQUIREFLAGS);
03383 }
03384
03385 static int CsqlTag(Header h, HE_t he)
03386
03387
03388 {
03389 he->tag = RPMTAG_CONFLICTNAME;
03390 return PRCOsqlTag(h, he, RPMTAG_CONFLICTVERSION, RPMTAG_CONFLICTFLAGS);
03391 }
03392
03393 static int OsqlTag(Header h, HE_t he)
03394
03395
03396 {
03397 he->tag = RPMTAG_OBSOLETENAME;
03398 return PRCOsqlTag(h, he, RPMTAG_OBSOLETEVERSION, RPMTAG_OBSOLETEFLAGS);
03399 }
03400
03401 static int PRCOyamlTag(Header h, HE_t he, rpmTag EVRtag, rpmTag Ftag)
03402
03403
03404 {
03405 rpmTag tag = he->tag;
03406 rpmTagData N = { .ptr = NULL };
03407 rpmTagData EVR = { .ptr = NULL };
03408 rpmTagData F = { .ptr = NULL };
03409 size_t nb;
03410 rpmuint32_t ac;
03411 rpmuint32_t c;
03412 rpmuint32_t i;
03413 char *t;
03414 int rc = 1;
03415 int indent = 0;
03416 int xx;
03417
03418
03419 xx = headerGet(h, he, 0);
03420 if (xx == 0) goto exit;
03421 N.argv = he->p.argv;
03422 c = he->c;
03423
03424 he->tag = EVRtag;
03425 xx = headerGet(h, he, 0);
03426 if (xx == 0) goto exit;
03427 EVR.argv = he->p.argv;
03428
03429 he->tag = Ftag;
03430 xx = headerGet(h, he, 0);
03431 if (xx == 0) goto exit;
03432 F.ui32p = he->p.ui32p;
03433
03434 nb = sizeof(*he->p.argv);
03435 ac = 0;
03436 for (i = 0; i < c; i++) {
03437
03438 if (PRCOSkip(tag, N, EVR, F, i))
03439 continue;
03440
03441 ac++;
03442 nb += sizeof(*he->p.argv);
03443 nb += sizeof("- ");
03444 if (*N.argv[i] == '/')
03445 nb += yamlstrlen(N.argv[i], indent);
03446 else
03447 nb += strlen(N.argv[i]);
03448 if (EVR.argv != NULL && EVR.argv[i] != NULL && *EVR.argv[i] != '\0') {
03449 nb += sizeof(" >= ") - 1;
03450 nb += strlen(EVR.argv[i]);
03451 }
03452 }
03453
03454 he->t = RPM_STRING_ARRAY_TYPE;
03455 he->c = ac;
03456 he->freeData = 1;
03457 he->p.argv = xmalloc(nb + BUFSIZ);
03458 t = (char *) &he->p.argv[he->c + 1];
03459 ac = 0;
03460 for (i = 0; i < c; i++) {
03461
03462 if (PRCOSkip(tag, N, EVR, F, i))
03463 continue;
03464
03465 he->p.argv[ac++] = t;
03466 t = stpcpy(t, "- ");
03467 if (*N.argv[i] == '/') {
03468 t = yamlstrcpy(t, N.argv[i], indent); t += strlen(t);
03469 } else
03470 t = stpcpy(t, N.argv[i]);
03471
03472 if (EVR.argv != NULL && EVR.argv[i] != NULL && *EVR.argv[i] != '\0') {
03473 static char *Fstr[] = { "?0","<",">","?3","=","<=",">=","?7" };
03474 rpmuint32_t Fx = ((F.ui32p[i] >> 1) & 0x7);
03475 t = stpcpy( stpcpy( stpcpy(t, " "), Fstr[Fx]), " ");
03476 t = stpcpy(t, EVR.argv[i]);
03477 }
03478
03479 *t++ = '\0';
03480 }
03481 he->p.argv[he->c] = NULL;
03482
03483 rc = 0;
03484
03485 exit:
03486
03487 N.argv = _free(N.argv);
03488
03489
03490 EVR.argv = _free(EVR.argv);
03491
03492 F.ui32p = _free(F.ui32p);
03493 return rc;
03494 }
03495
03496 static int PyamlTag(Header h, HE_t he)
03497
03498
03499 {
03500 he->tag = RPMTAG_PROVIDENAME;
03501 return PRCOyamlTag(h, he, RPMTAG_PROVIDEVERSION, RPMTAG_PROVIDEFLAGS);
03502 }
03503
03504 static int RyamlTag(Header h, HE_t he)
03505
03506
03507 {
03508 he->tag = RPMTAG_REQUIRENAME;
03509 return PRCOyamlTag(h, he, RPMTAG_REQUIREVERSION, RPMTAG_REQUIREFLAGS);
03510 }
03511
03512 static int CyamlTag(Header h, HE_t he)
03513
03514
03515 {
03516 he->tag = RPMTAG_CONFLICTNAME;
03517 return PRCOyamlTag(h, he, RPMTAG_CONFLICTVERSION, RPMTAG_CONFLICTFLAGS);
03518 }
03519
03520 static int OyamlTag(Header h, HE_t he)
03521
03522
03523 {
03524 he->tag = RPMTAG_OBSOLETENAME;
03525 return PRCOyamlTag(h, he, RPMTAG_OBSOLETEVERSION, RPMTAG_OBSOLETEFLAGS);
03526 }
03527
03528 static int FDGSkip(rpmTagData DN, rpmTagData BN, rpmTagData DI, rpmuint32_t i)
03529
03530 {
03531 const char * dn = DN.argv[DI.ui32p[i]];
03532 size_t dnlen = strlen(dn);
03533
03534 assert(dn != NULL);
03535 if (strstr(dn, "bin/") != NULL)
03536 return 1;
03537 if (dnlen >= sizeof("/etc/")-1 && !strncmp(dn, "/etc/", dnlen))
03538 return 1;
03539 if (!strcmp(dn, "/usr/lib/") && !strcmp(BN.argv[i], "sendmail"))
03540 return 1;
03541 return 2;
03542 }
03543
03544 static int FDGxmlTag(Header h, HE_t he, int lvl)
03545
03546
03547 {
03548 rpmTagData BN = { .ptr = NULL };
03549 rpmTagData DN = { .ptr = NULL };
03550 rpmTagData DI = { .ptr = NULL };
03551 rpmTagData FMODES = { .ptr = NULL };
03552 rpmTagData FFLAGS = { .ptr = NULL };
03553 size_t nb;
03554 rpmuint32_t ac;
03555 rpmuint32_t c;
03556 rpmuint32_t i;
03557 char *t;
03558 int rc = 1;
03559 int xx;
03560
03561
03562 he->tag = RPMTAG_BASENAMES;
03563 xx = headerGet(h, he, 0);
03564 if (xx == 0) goto exit;
03565 BN.argv = he->p.argv;
03566 c = he->c;
03567
03568 he->tag = RPMTAG_DIRNAMES;
03569 xx = headerGet(h, he, 0);
03570 if (xx == 0) goto exit;
03571 DN.argv = he->p.argv;
03572
03573 he->tag = RPMTAG_DIRINDEXES;
03574 xx = headerGet(h, he, 0);
03575 if (xx == 0) goto exit;
03576 DI.ui32p = he->p.ui32p;
03577
03578 he->tag = RPMTAG_FILEMODES;
03579 xx = headerGet(h, he, 0);
03580 if (xx == 0) goto exit;
03581 FMODES.ui16p = he->p.ui16p;
03582
03583 he->tag = RPMTAG_FILEFLAGS;
03584 xx = headerGet(h, he, 0);
03585 if (xx == 0) goto exit;
03586 FFLAGS.ui32p = he->p.ui32p;
03587
03588 nb = sizeof(*he->p.argv);
03589 ac = 0;
03590 for (i = 0; i < c; i++) {
03591 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
03592 continue;
03593 ac++;
03594 nb += sizeof(*he->p.argv);
03595 nb += sizeof("<file></file>");
03596 nb += xmlstrlen(DN.argv[DI.ui32p[i]]);
03597 nb += xmlstrlen(BN.argv[i]);
03598 if (FFLAGS.ui32p[i] & 0x40)
03599 nb += sizeof(" type=\"ghost\"") - 1;
03600 else if (S_ISDIR(FMODES.ui16p[i])) {
03601 nb += sizeof(" type=\"dir\"") - 1;
03602 #ifdef NOTYET
03603 nb += sizeof("/") - 1;
03604 #endif
03605 }
03606 }
03607
03608 he->t = RPM_STRING_ARRAY_TYPE;
03609 he->c = ac;
03610 he->freeData = 1;
03611 he->p.argv = xmalloc(nb);
03612 t = (char *) &he->p.argv[he->c + 1];
03613 ac = 0;
03614
03615 for (i = 0; i < c; i++) {
03616 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
03617 continue;
03618 if (FFLAGS.ui32p[i] & 0x40)
03619 continue;
03620 if (S_ISDIR(FMODES.ui16p[i]))
03621 continue;
03622 he->p.argv[ac++] = t;
03623 t = stpcpy(t, "<file>");
03624 t = xmlstrcpy(t, DN.argv[DI.ui32p[i]]); t += strlen(t);
03625 t = xmlstrcpy(t, BN.argv[i]); t += strlen(t);
03626 t = stpcpy(t, "</file>");
03627 *t++ = '\0';
03628 }
03629 for (i = 0; i < c; i++) {
03630 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
03631 continue;
03632 if (FFLAGS.ui32p[i] & 0x40)
03633 continue;
03634 if (!S_ISDIR(FMODES.ui16p[i]))
03635 continue;
03636 he->p.argv[ac++] = t;
03637 t = stpcpy(t, "<file type=\"dir\">");
03638 t = xmlstrcpy(t, DN.argv[DI.ui32p[i]]); t += strlen(t);
03639 t = xmlstrcpy(t, BN.argv[i]); t += strlen(t);
03640 #ifdef NOTYET
03641
03642 if (t[-1] != '/')
03643 t = stpcpy(t, "/");
03644 #endif
03645 t = stpcpy(t, "</file>");
03646 *t++ = '\0';
03647 }
03648 for (i = 0; i < c; i++) {
03649 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
03650 continue;
03651 if (!(FFLAGS.ui32p[i] & 0x40))
03652 continue;
03653 he->p.argv[ac++] = t;
03654 t = stpcpy(t, "<file type=\"ghost\">");
03655 t = xmlstrcpy(t, DN.argv[DI.ui32p[i]]); t += strlen(t);
03656 t = xmlstrcpy(t, BN.argv[i]); t += strlen(t);
03657 t = stpcpy(t, "</file>");
03658 *t++ = '\0';
03659 }
03660
03661 he->p.argv[he->c] = NULL;
03662
03663 rc = 0;
03664
03665 exit:
03666
03667 BN.argv = _free(BN.argv);
03668
03669 DN.argv = _free(DN.argv);
03670
03671 DI.ui32p = _free(DI.ui32p);
03672
03673 FMODES.ui16p = _free(FMODES.ui16p);
03674
03675 FFLAGS.ui32p = _free(FFLAGS.ui32p);
03676
03677 return rc;
03678 }
03679
03680 static int F1xmlTag(Header h, HE_t he)
03681
03682
03683 {
03684 he->tag = RPMTAG_BASENAMES;
03685 return FDGxmlTag(h, he, 1);
03686 }
03687
03688 static int F2xmlTag(Header h, HE_t he)
03689
03690
03691 {
03692 he->tag = RPMTAG_BASENAMES;
03693 return FDGxmlTag(h, he, 2);
03694 }
03695
03696 static int FDGsqlTag(Header h, HE_t he, int lvl)
03697
03698
03699 {
03700 rpmTagData BN = { .ptr = NULL };
03701 rpmTagData DN = { .ptr = NULL };
03702 rpmTagData DI = { .ptr = NULL };
03703 rpmTagData FMODES = { .ptr = NULL };
03704 rpmTagData FFLAGS = { .ptr = NULL };
03705 char instance[64];
03706 size_t nb;
03707 rpmuint32_t ac;
03708 rpmuint32_t c;
03709 rpmuint32_t i;
03710 char *t;
03711 int rc = 1;
03712 int xx;
03713
03714
03715 he->tag = RPMTAG_BASENAMES;
03716 xx = headerGet(h, he, 0);
03717 if (xx == 0) goto exit;
03718 BN.argv = he->p.argv;
03719 c = he->c;
03720
03721 he->tag = RPMTAG_DIRNAMES;
03722 xx = headerGet(h, he, 0);
03723 if (xx == 0) goto exit;
03724 DN.argv = he->p.argv;
03725
03726 he->tag = RPMTAG_DIRINDEXES;
03727 xx = headerGet(h, he, 0);
03728 if (xx == 0) goto exit;
03729 DI.ui32p = he->p.ui32p;
03730
03731 he->tag = RPMTAG_FILEMODES;
03732 xx = headerGet(h, he, 0);
03733 if (xx == 0) goto exit;
03734 FMODES.ui16p = he->p.ui16p;
03735
03736 he->tag = RPMTAG_FILEFLAGS;
03737 xx = headerGet(h, he, 0);
03738 if (xx == 0) goto exit;
03739 FFLAGS.ui32p = he->p.ui32p;
03740
03741 xx = snprintf(instance, sizeof(instance), "'%u'", (unsigned)headerGetInstance(h));
03742 nb = sizeof(*he->p.argv);
03743 ac = 0;
03744 for (i = 0; i < c; i++) {
03745 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
03746 continue;
03747 ac++;
03748 nb += sizeof(*he->p.argv);
03749 nb += strlen(instance) + sizeof(", '', ''");
03750 nb += strlen(DN.argv[DI.ui32p[i]]);
03751 nb += strlen(BN.argv[i]);
03752 if (FFLAGS.ui32p[i] & 0x40)
03753 nb += sizeof("ghost") - 1;
03754 else if (S_ISDIR(FMODES.ui16p[i])) {
03755 nb += sizeof("dir") - 1;
03756 #ifdef NOTYET
03757 nb += sizeof("/") - 1;
03758 #endif
03759 } else
03760 nb += sizeof("file") - 1;
03761 }
03762
03763 he->t = RPM_STRING_ARRAY_TYPE;
03764 he->c = ac;
03765 he->freeData = 1;
03766 he->p.argv = xmalloc(nb);
03767 t = (char *) &he->p.argv[he->c + 1];
03768 ac = 0;
03769
03770 for (i = 0; i < c; i++) {
03771 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
03772 continue;
03773 if (FFLAGS.ui32p[i] & 0x40)
03774 continue;
03775 if (S_ISDIR(FMODES.ui16p[i]))
03776 continue;
03777 he->p.argv[ac++] = t;
03778 t = stpcpy( stpcpy(t, instance), ", '");
03779 t = strcpy(t, DN.argv[DI.ui32p[i]]); t += strlen(t);
03780 t = strcpy(t, BN.argv[i]); t += strlen(t);
03781 t = stpcpy(t, "', 'file'");
03782 *t++ = '\0';
03783 }
03784 for (i = 0; i < c; i++) {
03785 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
03786 continue;
03787 if (FFLAGS.ui32p[i] & 0x40)
03788 continue;
03789 if (!S_ISDIR(FMODES.ui16p[i]))
03790 continue;
03791 he->p.argv[ac++] = t;
03792 t = stpcpy( stpcpy(t, instance), ", '");
03793 t = strcpy(t, DN.argv[DI.ui32p[i]]); t += strlen(t);
03794 t = strcpy(t, BN.argv[i]); t += strlen(t);
03795 #ifdef NOTYET
03796
03797 if (t[-1] != '/')
03798 t = stpcpy(t, "/");
03799 #endif
03800 t = stpcpy(t, "', 'dir'");
03801 *t++ = '\0';
03802 }
03803 for (i = 0; i < c; i++) {
03804 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
03805 continue;
03806 if (!(FFLAGS.ui32p[i] & 0x40))
03807 continue;
03808 he->p.argv[ac++] = t;
03809 t = stpcpy( stpcpy(t, instance), ", '");
03810 t = strcpy(t, DN.argv[DI.ui32p[i]]); t += strlen(t);
03811 t = strcpy(t, BN.argv[i]); t += strlen(t);
03812 t = stpcpy(t, "', 'ghost'");
03813 *t++ = '\0';
03814 }
03815
03816 he->p.argv[he->c] = NULL;
03817
03818 rc = 0;
03819
03820 exit:
03821
03822 BN.argv = _free(BN.argv);
03823
03824 DN.argv = _free(DN.argv);
03825
03826 DI.ui32p = _free(DI.ui32p);
03827
03828 FMODES.ui16p = _free(FMODES.ui16p);
03829
03830 FFLAGS.ui32p = _free(FFLAGS.ui32p);
03831
03832 return rc;
03833 }
03834
03835 static int F1sqlTag(Header h, HE_t he)
03836
03837
03838 {
03839 he->tag = RPMTAG_BASENAMES;
03840 return FDGsqlTag(h, he, 1);
03841 }
03842
03843 static int F2sqlTag(Header h, HE_t he)
03844
03845
03846 {
03847 he->tag = RPMTAG_BASENAMES;
03848 return FDGsqlTag(h, he, 2);
03849 }
03850
03851 static int FDGyamlTag(Header h, HE_t he, int lvl)
03852
03853
03854 {
03855 rpmTagData BN = { .ptr = NULL };
03856 rpmTagData DN = { .ptr = NULL };
03857 rpmTagData DI = { .ptr = NULL };
03858 rpmTagData FMODES = { .ptr = NULL };
03859 rpmTagData FFLAGS = { .ptr = NULL };
03860 size_t nb;
03861 rpmuint32_t ac;
03862 rpmuint32_t c;
03863 rpmuint32_t i;
03864 char *t;
03865 int rc = 1;
03866 int indent = 0;
03867 int xx;
03868
03869
03870 he->tag = RPMTAG_BASENAMES;
03871 xx = headerGet(h, he, 0);
03872 if (xx == 0) goto exit;
03873 BN.argv = he->p.argv;
03874 c = he->c;
03875
03876 he->tag = RPMTAG_DIRNAMES;
03877 xx = headerGet(h, he, 0);
03878 if (xx == 0) goto exit;
03879 DN.argv = he->p.argv;
03880
03881 he->tag = RPMTAG_DIRINDEXES;
03882 xx = headerGet(h, he, 0);
03883 if (xx == 0) goto exit;
03884 DI.ui32p = he->p.ui32p;
03885
03886 he->tag = RPMTAG_FILEMODES;
03887 xx = headerGet(h, he, 0);
03888 if (xx == 0) goto exit;
03889 FMODES.ui16p = he->p.ui16p;
03890
03891 he->tag = RPMTAG_FILEFLAGS;
03892 xx = headerGet(h, he, 0);
03893 if (xx == 0) goto exit;
03894 FFLAGS.ui32p = he->p.ui32p;
03895
03896 nb = sizeof(*he->p.argv);
03897 ac = 0;
03898 for (i = 0; i < c; i++) {
03899 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
03900 continue;
03901 ac++;
03902 nb += sizeof(*he->p.argv);
03903 nb += sizeof("- ");
03904 nb += yamlstrlen(DN.argv[DI.ui32p[i]], indent);
03905 nb += yamlstrlen(BN.argv[i], indent);
03906 if (FFLAGS.ui32p[i] & 0x40)
03907 nb += sizeof("") - 1;
03908 else if (S_ISDIR(FMODES.ui16p[i]))
03909 nb += sizeof("/") - 1;
03910 }
03911
03912 he->t = RPM_STRING_ARRAY_TYPE;
03913 he->c = ac;
03914 he->freeData = 1;
03915 he->p.argv = xmalloc(nb);
03916 t = (char *) &he->p.argv[he->c + 1];
03917 ac = 0;
03918
03919 for (i = 0; i < c; i++) {
03920 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
03921 continue;
03922 if (FFLAGS.ui32p[i] & 0x40)
03923 continue;
03924 if (S_ISDIR(FMODES.ui16p[i]))
03925 continue;
03926 he->p.argv[ac++] = t;
03927 t = stpcpy(t, "- ");
03928 t = yamlstrcpy(t, DN.argv[DI.ui32p[i]], indent); t += strlen(t);
03929 t = yamlstrcpy(t, BN.argv[i], indent); t += strlen(t);
03930 t = stpcpy(t, "");
03931 *t++ = '\0';
03932 }
03933 for (i = 0; i < c; i++) {
03934 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
03935 continue;
03936 if (FFLAGS.ui32p[i] & 0x40)
03937 continue;
03938 if (!S_ISDIR(FMODES.ui16p[i]))
03939 continue;
03940 he->p.argv[ac++] = t;
03941 t = stpcpy(t, "- ");
03942 t = yamlstrcpy(t, DN.argv[DI.ui32p[i]], indent); t += strlen(t);
03943 t = yamlstrcpy(t, BN.argv[i], indent); t += strlen(t);
03944
03945 if (t[-1] != '/')
03946 t = stpcpy(t, "/");
03947 *t++ = '\0';
03948 }
03949 for (i = 0; i < c; i++) {
03950 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
03951 continue;
03952 if (!(FFLAGS.ui32p[i] & 0x40))
03953 continue;
03954 he->p.argv[ac++] = t;
03955 t = stpcpy(t, "- ");
03956 t = yamlstrcpy(t, DN.argv[DI.ui32p[i]], indent); t += strlen(t);
03957 t = yamlstrcpy(t, BN.argv[i], indent); t += strlen(t);
03958 *t++ = '\0';
03959 }
03960
03961 he->p.argv[he->c] = NULL;
03962
03963 rc = 0;
03964
03965 exit:
03966
03967 BN.argv = _free(BN.argv);
03968
03969 DN.argv = _free(DN.argv);
03970
03971 DI.ui32p = _free(DI.ui32p);
03972
03973 FMODES.ui16p = _free(FMODES.ui16p);
03974
03975 FFLAGS.ui32p = _free(FFLAGS.ui32p);
03976
03977 return rc;
03978 }
03979
03980 static int F1yamlTag(Header h, HE_t he)
03981
03982
03983 {
03984 he->tag = RPMTAG_BASENAMES;
03985 return FDGyamlTag(h, he, 1);
03986 }
03987
03988 static int F2yamlTag(Header h, HE_t he)
03989
03990
03991 {
03992 he->tag = RPMTAG_BASENAMES;
03993 return FDGyamlTag(h, he, 2);
03994 }
03995
04002 static char * bncdataFormat(HE_t he, const char ** av)
04003
04004 {
04005 char * val;
04006
04007 if (he->t != RPM_STRING_TYPE) {
04008 val = xstrdup(_("(not a string)"));
04009 } else {
04010 const char * bn;
04011 const char * s;
04012 size_t nb;
04013 char * t;
04014
04015 assert(he->p.str != NULL);
04016
04017 if ((bn = strrchr(he->p.str, '/')) != NULL)
04018 bn++;
04019 else
04020 bn = he->p.str;
04021
04022
04023 s = strdup_locale_convert(bn, (av ? av[0] : NULL));
04024 if (s == NULL) {
04025
04026 val = xstrdup(_("(not a string)"));
04027 goto exit;
04028 }
04029
04030 nb = xmlstrlen(s);
04031 val = t = xcalloc(1, nb + 1);
04032 t = xmlstrcpy(t, s); t += strlen(t);
04033 *t = '\0';
04034 s = _free(s);
04035 }
04036
04037 exit:
04038 return val;
04039 }
04040
04041 typedef struct key_s {
04042
04043 const char *name;
04044 rpmuint32_t value;
04045 } KEY;
04046
04047
04048 static KEY keyDigests[] = {
04049 { "adler32", PGPHASHALGO_ADLER32 },
04050 { "crc32", PGPHASHALGO_CRC32 },
04051 { "crc64", PGPHASHALGO_CRC64 },
04052 { "haval160", PGPHASHALGO_HAVAL_5_160 },
04053 { "jlu32", PGPHASHALGO_JLU32 },
04054 { "md2", PGPHASHALGO_MD2 },
04055 { "md4", PGPHASHALGO_MD4 },
04056 { "md5", PGPHASHALGO_MD5 },
04057 { "rmd128", PGPHASHALGO_RIPEMD128 },
04058 { "rmd160", PGPHASHALGO_RIPEMD160 },
04059 { "rmd256", PGPHASHALGO_RIPEMD256 },
04060 { "rmd320", PGPHASHALGO_RIPEMD320 },
04061 { "salsa10", PGPHASHALGO_SALSA10 },
04062 { "salsa20", PGPHASHALGO_SALSA20 },
04063 { "sha1", PGPHASHALGO_SHA1 },
04064 { "sha224", PGPHASHALGO_SHA224 },
04065 { "sha256", PGPHASHALGO_SHA256 },
04066 { "sha384", PGPHASHALGO_SHA384 },
04067 { "sha512", PGPHASHALGO_SHA512 },
04068 { "tiger192", PGPHASHALGO_TIGER192 },
04069 };
04070
04071 static size_t nkeyDigests = sizeof(keyDigests) / sizeof(keyDigests[0]);
04072
04076 enum keyStat_e {
04077 STAT_KEYS_NONE = 0,
04078 STAT_KEYS_DEV = (1U << 0),
04079 STAT_KEYS_INO = (1U << 1),
04080 STAT_KEYS_MODE = (1U << 2),
04081 STAT_KEYS_NLINK = (1U << 3),
04082 STAT_KEYS_UID = (1U << 4),
04083 STAT_KEYS_GID = (1U << 5),
04084 STAT_KEYS_RDEV = (1U << 6),
04085 STAT_KEYS_SIZE = (1U << 7),
04086 STAT_KEYS_BLKSIZE = (1U << 8),
04087 STAT_KEYS_BLOCKS = (1U << 9),
04088 STAT_KEYS_ATIME = (1U << 10),
04089 STAT_KEYS_CTIME = (1U << 11),
04090 STAT_KEYS_MTIME = (1U << 12),
04091 #ifdef NOTYET
04092 STAT_KEYS_FLAGS = (1U << 13),
04093 #endif
04094 STAT_KEYS_SLINK = (1U << 14),
04095 STAT_KEYS_DIGEST = (1U << 15),
04096 #ifdef NOTYET
04097 STAT_KEYS_FCONTEXT = (1U << 16),
04098 #endif
04099 STAT_KEYS_UNAME = (1U << 17),
04100 STAT_KEYS_GNAME = (1U << 18),
04101 };
04102
04103
04104 static KEY keyStat[] = {
04105 { "adler32", STAT_KEYS_DIGEST },
04106 { "atime", STAT_KEYS_ATIME },
04107 { "ctime", STAT_KEYS_CTIME },
04108 { "blksize", STAT_KEYS_BLKSIZE },
04109 { "blocks", STAT_KEYS_BLOCKS },
04110 { "crc32", STAT_KEYS_DIGEST },
04111 { "crc64", STAT_KEYS_DIGEST },
04112 { "dev", STAT_KEYS_DEV },
04113 #ifdef NOTYET
04114 { "digest", STAT_KEYS_DIGEST },
04115 { "fcontext", STAT_KEYS_FCONTEXT },
04116 { "flags", STAT_KEYS_FLAGS },
04117 #endif
04118 { "gid", STAT_KEYS_GID },
04119 { "gname", STAT_KEYS_GNAME },
04120 { "haval160", STAT_KEYS_DIGEST },
04121 { "ino", STAT_KEYS_INO },
04122 { "jlu32", STAT_KEYS_DIGEST },
04123 { "link", STAT_KEYS_SLINK },
04124 { "md2", STAT_KEYS_DIGEST },
04125 { "md4", STAT_KEYS_DIGEST },
04126 { "md5", STAT_KEYS_DIGEST },
04127 { "mode", STAT_KEYS_MODE },
04128 { "mtime", STAT_KEYS_MTIME },
04129 { "nlink", STAT_KEYS_NLINK },
04130 { "rdev", STAT_KEYS_RDEV },
04131 { "rmd128", STAT_KEYS_DIGEST },
04132 { "rmd160", STAT_KEYS_DIGEST },
04133 { "rmd256", STAT_KEYS_DIGEST },
04134 { "rmd320", STAT_KEYS_DIGEST },
04135 { "salsa10", STAT_KEYS_DIGEST },
04136 { "salsa20", STAT_KEYS_DIGEST },
04137 { "sha1", STAT_KEYS_DIGEST },
04138 { "sha224", STAT_KEYS_DIGEST },
04139 { "sha256", STAT_KEYS_DIGEST },
04140 { "sha384", STAT_KEYS_DIGEST },
04141 { "sha512", STAT_KEYS_DIGEST },
04142 { "size", STAT_KEYS_SIZE },
04143 { "tiger192", STAT_KEYS_DIGEST },
04144 { "uid", STAT_KEYS_UID },
04145 { "uname", STAT_KEYS_UNAME },
04146 };
04147
04148 static size_t nkeyStat = sizeof(keyStat) / sizeof(keyStat[0]);
04149
04153 enum keyUuids_e {
04154 UUID_KEYS_NONE = (0U << 0),
04155 UUID_KEYS_V1 = (1U << 0),
04156 UUID_KEYS_V3 = (3U << 0),
04157 UUID_KEYS_V4 = (4U << 0),
04158 UUID_KEYS_V5 = (5U << 0),
04159 #ifdef NOTYET
04160 UUID_KEYS_STRING = (0U << 4),
04161 UUID_KEYS_SIV = (1U << 4),
04162 UUID_KEYS_BINARY = (2U << 4),
04163 UUID_KEYS_TEXT = (3U << 4),
04164 #endif
04165 };
04166
04167
04168 static KEY keyUuids[] = {
04169 #ifdef NOTYET
04170 { "binary", UUID_KEYS_BINARY },
04171 { "siv", UUID_KEYS_SIV },
04172 { "string", UUID_KEYS_STRING },
04173 { "text", UUID_KEYS_TEXT },
04174 #endif
04175 { "v1", UUID_KEYS_V1 },
04176 { "v3", UUID_KEYS_V3 },
04177 { "v4", UUID_KEYS_V4 },
04178 { "v5", UUID_KEYS_V5 },
04179 };
04180
04181 static size_t nkeyUuids = sizeof(keyUuids) / sizeof(keyUuids[0]);
04182
04185 static int
04186 keyCmp(const void * a, const void * b)
04187
04188 {
04189 return strcmp(((KEY *)a)->name, ((KEY *)b)->name);
04190 }
04191
04194 static rpmuint32_t
04195 keyValue(KEY * keys, size_t nkeys, const char *name)
04196
04197 {
04198 rpmuint32_t keyval = 0;
04199
04200 if (name && * name) {
04201 KEY needle = { .name = name, .value = 0 };
04202 KEY *k = (KEY *)bsearch(&needle, keys, nkeys, sizeof(*keys), keyCmp);
04203 if (k)
04204 keyval = k->value;
04205 }
04206 return keyval;
04207 }
04208
04215 static char * digestFormat(HE_t he, const char ** av)
04216
04217 {
04218 int ix = (he->ix > 0 ? he->ix : 0);
04219 char * val = NULL;
04220 size_t ns;
04221
04222 assert(ix == 0);
04223 switch(he->t) {
04224 default:
04225 val = xstrdup(_("(invalid type :digest)"));
04226 goto exit;
04227 break;
04228 case RPM_UINT64_TYPE:
04229 ns = sizeof(he->p.ui64p[0]);
04230 break;
04231 case RPM_STRING_TYPE:
04232 ns = strlen(he->p.str);
04233 break;
04234 case RPM_BIN_TYPE:
04235 ns = he->c;
04236 break;
04237 }
04238
04239 assert(he->p.ptr != NULL);
04240 { rpmuint32_t keyval = keyValue(keyDigests, nkeyDigests, (av ? av[0] : NULL));
04241 rpmuint32_t algo = (keyval ? keyval : PGPHASHALGO_SHA1);
04242 DIGEST_CTX ctx = rpmDigestInit(algo, 0);
04243 int xx = rpmDigestUpdate(ctx, he->p.ptr, ns);
04244 xx = rpmDigestFinal(ctx, &val, NULL, 1);
04245 }
04246
04247 exit:
04248 return val;
04249 }
04250
04257 static char * statFormat(HE_t he, const char ** av)
04258
04259
04260 {
04261
04262
04263 static const char *avdefault[] = { "mode", NULL };
04264
04265 const char * fn = NULL;
04266 struct stat sb, *st = &sb;
04267 int ix = (he->ix > 0 ? he->ix : 0);
04268 char * val = NULL;
04269 int xx;
04270 int i;
04271
04272 memset(st, 0, sizeof(*st));
04273 assert(ix == 0);
04274 switch(he->t) {
04275 case RPM_BIN_TYPE:
04276
04277 if (he->tag == RPMTAG_PACKAGESTAT)
04278 if ((size_t)he->c == sizeof(*st)) {
04279 st = (struct stat *)he->p.ptr;
04280 break;
04281 }
04282
04283 default:
04284 val = xstrdup(_("(invalid type :stat)"));
04285 goto exit;
04286 break;
04287 case RPM_STRING_TYPE:
04288 fn = he->p.str;
04289 if (Lstat(fn, st) == 0)
04290 break;
04291
04292 val = rpmExpand("(Lstat:", fn, ":", strerror(errno), ")", NULL);
04293
04294 goto exit;
04295 break;
04296 }
04297
04298 if (!(av && av[0] && *av[0]))
04299 av = avdefault;
04300 for (i = 0; av[i] != NULL; i++) {
04301 char b[BUFSIZ];
04302 size_t nb = sizeof(b);
04303 char * nval;
04304 rpmuint32_t keyval = keyValue(keyStat, nkeyStat, av[i]);
04305
04306 nval = NULL;
04307 b[0] = '\0';
04308 switch (keyval) {
04309 default:
04310 break;
04311 case STAT_KEYS_NONE:
04312 break;
04313 case STAT_KEYS_DEV:
04314 xx = snprintf(b, nb, "0x%lx", (unsigned long)st->st_dev);
04315 break;
04316 case STAT_KEYS_INO:
04317 xx = snprintf(b, nb, "0x%lx", (unsigned long)st->st_ino);
04318 break;
04319 case STAT_KEYS_MODE:
04320 xx = snprintf(b, nb, "%06o", (unsigned)st->st_mode);
04321 break;
04322 case STAT_KEYS_NLINK:
04323 xx = snprintf(b, nb, "0x%ld", (unsigned long)st->st_nlink);
04324 break;
04325 case STAT_KEYS_UID:
04326 xx = snprintf(b, nb, "%ld", (unsigned long)st->st_uid);
04327 break;
04328 case STAT_KEYS_GID:
04329 xx = snprintf(b, nb, "%ld", (unsigned long)st->st_gid);
04330 break;
04331 case STAT_KEYS_RDEV:
04332 xx = snprintf(b, nb, "0x%lx", (unsigned long)st->st_rdev);
04333 break;
04334 case STAT_KEYS_SIZE:
04335 xx = snprintf(b, nb, "%ld", (unsigned long)st->st_size);
04336 break;
04337 case STAT_KEYS_BLKSIZE:
04338 xx = snprintf(b, nb, "%ld", (unsigned long)st->st_blksize);
04339 break;
04340 case STAT_KEYS_BLOCKS:
04341 xx = snprintf(b, nb, "%ld", (unsigned long)st->st_blocks);
04342 break;
04343 case STAT_KEYS_ATIME:
04344 (void) stpcpy(b, ctime((time_t *)&st->st_atime));
04345 break;
04346 case STAT_KEYS_CTIME:
04347 (void) stpcpy(b, ctime((time_t *)&st->st_ctime));
04348 break;
04349 case STAT_KEYS_MTIME:
04350 (void) stpcpy(b, ctime((time_t *)&st->st_mtime));
04351 break;
04352 #ifdef NOTYET
04353 case STAT_KEYS_FLAGS:
04354 break;
04355 #endif
04356 case STAT_KEYS_SLINK:
04357 if (fn != NULL && S_ISLNK(st->st_mode)) {
04358 ssize_t size = Readlink(fn, b, nb);
04359 if (size == -1) {
04360 nval = rpmExpand("(Readlink:", fn, ":", strerror(errno), ")", NULL);
04361 (void) stpcpy(b, nval);
04362 nval = _free(nval);
04363 } else
04364 b[size] = '\0';
04365 }
04366 break;
04367 case STAT_KEYS_DIGEST:
04368 if (fn != NULL && S_ISREG(st->st_mode)) {
04369 rpmuint32_t digval = keyValue(keyDigests, nkeyDigests, av[i]);
04370 rpmuint32_t algo = (digval ? digval : PGPHASHALGO_SHA1);
04371 FD_t fd = Fopen(fn, "r%{?_rpmgio}");
04372 if (fd == NULL || Ferror(fd)) {
04373 nval = rpmExpand("(Fopen:", fn, ":", Fstrerror(fd), ")", NULL);
04374 } else {
04375 static int asAscii = 1;
04376 char buffer[16 * 1024];
04377 fdInitDigest(fd, algo, 0);
04378 while (Fread(buffer, sizeof(buffer[0]), sizeof(buffer), fd) > 0)
04379 {};
04380 if (Ferror(fd))
04381 nval = rpmExpand("(Fread:", fn, ":", Fstrerror(fd), ")", NULL);
04382 else
04383 fdFiniDigest(fd, algo, &nval, NULL, asAscii);
04384 }
04385 if (nval) {
04386 (void) stpcpy(b, nval);
04387 nval = _free(nval);
04388 }
04389 if (fd != NULL)
04390 xx = Fclose(fd);
04391 }
04392 break;
04393 case STAT_KEYS_UNAME:
04394 { const char * uname = uidToUname(st->st_uid);
04395 if (uname != NULL)
04396 (void) stpcpy(b, uname);
04397 else
04398 xx = snprintf(b, nb, "%u", (unsigned)st->st_uid);
04399 } break;
04400 case STAT_KEYS_GNAME:
04401 { const char * gname = gidToGname(st->st_gid);
04402 if (gname != NULL)
04403 (void) stpcpy(b, gname);
04404 else
04405 xx = snprintf(b, nb, "%u", (unsigned)st->st_gid);
04406 } break;
04407 }
04408 if (b[0] == '\0')
04409 continue;
04410 b[nb-1] = '\0';
04411
04412 if (val == NULL)
04413 val = xstrdup(b);
04414 else {
04415 nval = rpmExpand(val, " | ", b, NULL);
04416 val = _free(val);
04417 val = nval;
04418 }
04419 }
04420
04421 exit:
04422 return val;
04423 }
04424
04431 static char * uuidFormat(HE_t he, const char ** av)
04432
04433
04434 {
04435
04436
04437 static const char *avdefault[] = { "v5", NULL };
04438
04439 rpmuint32_t version = 0;
04440 int ix = (he->ix > 0 ? he->ix : 0);
04441 char * val = NULL;
04442 int i;
04443
04444 assert(ix == 0);
04445 switch(he->t) {
04446 default:
04447 val = xstrdup(_("(invalid type :uuid)"));
04448 goto exit;
04449 break;
04450 case RPM_STRING_TYPE:
04451 break;
04452 }
04453
04454 if (!(av && av[0] && *av[0]))
04455 av = avdefault;
04456
04457 for (i = 0; av[i] != NULL; i++) {
04458 rpmuint32_t keyval = keyValue(keyUuids, nkeyUuids, av[i]);
04459
04460 switch (keyval) {
04461 default:
04462 break;
04463 case UUID_KEYS_V1:
04464 case UUID_KEYS_V3:
04465 case UUID_KEYS_V4:
04466 case UUID_KEYS_V5:
04467 version = keyval;
04468 break;
04469 }
04470 }
04471
04472
04473 { HE_t nhe = memset(alloca(sizeof(*nhe)), 0, sizeof(*nhe));
04474 int xx;
04475 nhe->tag = he->tag;
04476 nhe->t = he->t;
04477 nhe->p.str = xstrdup(he->p.str);
04478 nhe->c = he->c;
04479 val = xmalloc((128/4 + 4) + 1);
04480 *val = '\0';
04481 xx = str2uuid(nhe, NULL, version, val);
04482 nhe->p.ptr = _free(nhe->p.ptr);
04483 }
04484
04485 exit:
04486 return val;
04487 }
04488
04495 static char * rpnFormat(HE_t he, const char ** av)
04496
04497 {
04498 int ac = argvCount(av) + 1;
04499 int64_t * stack = memset(alloca(ac*sizeof(*stack)), 0, (ac*sizeof(*stack)));
04500 char * end;
04501 char * val = NULL;
04502 int ix = 0;
04503 int i;
04504
04505 switch(he->t) {
04506 default:
04507 val = xstrdup(_("(invalid type :rpn)"));
04508 goto exit;
04509 break;
04510 case RPM_UINT64_TYPE:
04511 stack[ix] = he->p.ui64p[0];
04512 break;
04513 case RPM_STRING_TYPE:
04514 end = NULL;
04515
04516 stack[ix] = strtoll(he->p.str, &end, 0);
04517
04518 if (end && *end != '\0') {
04519 val = xstrdup(_("(invalid string :rpn)"));
04520 goto exit;
04521 }
04522 break;
04523 }
04524
04525 if (av != NULL)
04526 for (i = 0; av[i] != NULL; i++) {
04527 const char * arg = av[i];
04528 size_t len = strlen(arg);
04529 int c = (int) *arg;
04530
04531 if (len == 0) {
04532
04533 } else if (len > 1) {
04534 if (!(xisdigit(c) || (c == (int)'-' && xisdigit((int) arg[1])))) {
04535 val = xstrdup(_("(expected number :rpn)"));
04536 goto exit;
04537 }
04538 if (++ix == ac) {
04539 val = xstrdup(_("(stack overflow :rpn)"));
04540 goto exit;
04541 }
04542 end = NULL;
04543 stack[ix] = strtoll(arg, &end, 0);
04544 if (end && *end != '\0') {
04545 val = xstrdup(_("(invalid number :rpn)"));
04546 goto exit;
04547 }
04548 } else {
04549 if (ix-- < 1) {
04550 val = xstrdup(_("(stack underflow :rpn)"));
04551 goto exit;
04552 }
04553 switch (c) {
04554 case '&': stack[ix] &= stack[ix+1]; break;
04555 case '|': stack[ix] |= stack[ix+1]; break;
04556 case '^': stack[ix] ^= stack[ix+1]; break;
04557 case '+': stack[ix] += stack[ix+1]; break;
04558 case '-': stack[ix] -= stack[ix+1]; break;
04559 case '*': stack[ix] *= stack[ix+1]; break;
04560 case '%':
04561 case '/':
04562 if (stack[ix+1] == 0) {
04563 val = xstrdup(_("(divide by zero :rpn)"));
04564 goto exit;
04565 }
04566 if (c == (int)'%')
04567 stack[ix] %= stack[ix+1];
04568 else
04569 stack[ix] /= stack[ix+1];
04570 break;
04571 }
04572 }
04573 }
04574
04575 { HE_t nhe = memset(alloca(sizeof(*nhe)), 0, sizeof(*nhe));
04576 nhe->tag = he->tag;
04577 nhe->t = RPM_UINT64_TYPE;
04578 nhe->p.ui64p = (rpmuint64_t *)&stack[ix];
04579 nhe->c = 1;
04580 val = intFormat(nhe, NULL, NULL);
04581 }
04582
04583 exit:
04584 return val;
04585 }
04586
04593 static char * strsubFormat(HE_t he, const char ** av)
04594
04595
04596 {
04597 char * val = NULL;
04598 int ac = argvCount(av);
04599 miRE mires = NULL;
04600 int nmires = 0;
04601 int xx;
04602 int i;
04603
04604 switch(he->t) {
04605 default:
04606 val = xstrdup(_("(invalid type :strsub)"));
04607 goto exit;
04608 break;
04609 case RPM_STRING_TYPE:
04610 if (ac < 2 || (ac % 2) != 0) {
04611 val = xstrdup(_("(invalid args :strsub)"));
04612 goto exit;
04613 }
04614 break;
04615 }
04616 if (av == NULL)
04617 goto noop;
04618
04619
04620 for (i = 0; av[i] != NULL; i += 2)
04621 xx = mireAppend(RPMMIRE_REGEX, 0, av[i], NULL, &mires, &nmires);
04622
04623
04624 if (mires != NULL) {
04625 int noffsets = 3;
04626 int offsets[3];
04627 const char * s, * se;
04628 char * t, * te;
04629 char * nval;
04630 size_t slen;
04631 size_t nb;
04632
04633 for (i = 0; i < nmires; i++) {
04634 miRE mire = mires + i;
04635
04636 s = he->p.str;
04637 slen = strlen(s);
04638 if ((xx = mireRegexec(mire, s, slen)) < 0)
04639 continue;
04640 xx = mireSetEOptions(mire, offsets, noffsets);
04641
04642
04643 val = xstrdup("");
04644 while (*s != '\0') {
04645 nb = strlen(s);
04646 if ((se = strchr(s, '\n')) == NULL)
04647 se = s + nb;
04648 else
04649 se++;
04650
04651 offsets[0] = offsets[1] = -1;
04652 xx = mireRegexec(mire, s, nb);
04653
04654 nb = 1;
04655
04656 if (xx == 0)
04657 nb += offsets[0] + strlen(av[2*i+1]);
04658
04659 if (xx != 0 || offsets[1] == offsets[0])
04660 nb += (se - (s + offsets[1]));
04661
04662 te = t = xmalloc(nb);
04663
04664
04665 if (xx == 0) {
04666 te = stpcpy( stpncpy(te, s, offsets[0]), av[2*i+1]);
04667 s += offsets[1];
04668 }
04669
04670 if (xx != 0 || offsets[1] == offsets[0]) {
04671 s += offsets[1];
04672 te = stpncpy(te, s, (se - s));
04673 s = se;
04674 }
04675 *te = '\0';
04676
04677 nval = rpmExpand(val, t, NULL);
04678 val = _free(val);
04679 val = nval;
04680 t = _free(t);
04681 }
04682 }
04683 mires = mireFreeAll(mires, nmires);
04684 }
04685
04686 noop:
04687 if (val == NULL)
04688 val = xstrdup(he->p.str);
04689 exit:
04690 return val;
04691 }
04692
04693 static struct headerSprintfExtension_s _headerCompoundFormats[] = {
04694 { HEADER_EXT_TAG, "RPMTAG_BUILDTIMEUUID",
04695 { .tagFunction = buildtime_uuidTag } },
04696 { HEADER_EXT_TAG, "RPMTAG_CHANGELOGNAME",
04697 { .tagFunction = changelognameTag } },
04698 { HEADER_EXT_TAG, "RPMTAG_CHANGELOGTEXT",
04699 { .tagFunction = changelogtextTag } },
04700 { HEADER_EXT_TAG, "RPMTAG_DESCRIPTION",
04701 { .tagFunction = descriptionTag } },
04702 { HEADER_EXT_TAG, "RPMTAG_GROUP",
04703 { .tagFunction = groupTag } },
04704 { HEADER_EXT_TAG, "RPMTAG_HDRUUID",
04705 { .tagFunction = hdruuidTag } },
04706 { HEADER_EXT_TAG, "RPMTAG_INSTALLPREFIX",
04707 { .tagFunction = instprefixTag } },
04708 { HEADER_EXT_TAG, "RPMTAG_INSTALLTIDUUID",
04709 { .tagFunction = installtid_uuidTag } },
04710 { HEADER_EXT_TAG, "RPMTAG_INSTALLTIMEUUID",
04711 { .tagFunction = installtime_uuidTag } },
04712 { HEADER_EXT_TAG, "RPMTAG_ORIGINTIDUUID",
04713 { .tagFunction = origintid_uuidTag } },
04714 { HEADER_EXT_TAG, "RPMTAG_ORIGINTIMEUUID",
04715 { .tagFunction = origintime_uuidTag } },
04716 { HEADER_EXT_TAG, "RPMTAG_PKGUUID",
04717 { .tagFunction = pkguuidTag } },
04718 { HEADER_EXT_TAG, "RPMTAG_REMOVETIDUUID",
04719 { .tagFunction = removetid_uuidTag } },
04720 { HEADER_EXT_TAG, "RPMTAG_SOURCEPKGUUID",
04721 { .tagFunction = sourcepkguuidTag } },
04722 { HEADER_EXT_TAG, "RPMTAG_SUMMARY",
04723 { .tagFunction = summaryTag } },
04724 { HEADER_EXT_TAG, "RPMTAG_TRIGGERCONDS",
04725 { .tagFunction = triggercondsTag } },
04726 { HEADER_EXT_TAG, "RPMTAG_TRIGGERTYPE",
04727 { .tagFunction = triggertypeTag } },
04728 { HEADER_EXT_TAG, "RPMTAG_DBINSTANCE",
04729 { .tagFunction = dbinstanceTag } },
04730 { HEADER_EXT_TAG, "RPMTAG_HEADERSTARTOFF",
04731 { .tagFunction = headerstartoffTag } },
04732 { HEADER_EXT_TAG, "RPMTAG_HEADERENDOFF",
04733 { .tagFunction = headerendoffTag } },
04734 { HEADER_EXT_TAG, "RPMTAG_PACKAGEBASEURL",
04735 { .tagFunction = pkgbaseurlTag } },
04736 { HEADER_EXT_TAG, "RPMTAG_PACKAGEDIGEST",
04737 { .tagFunction = pkgdigestTag } },
04738 { HEADER_EXT_TAG, "RPMTAG_PACKAGEORIGIN",
04739 { .tagFunction = pkgoriginTag } },
04740 { HEADER_EXT_TAG, "RPMTAG_PACKAGESIZE",
04741 { .tagFunction = pkgsizeTag } },
04742 { HEADER_EXT_TAG, "RPMTAG_PACKAGETIME",
04743 { .tagFunction = pkgmtimeTag } },
04744 { HEADER_EXT_TAG, "RPMTAG_NVRA",
04745 { .tagFunction = nvraTag } },
04746 { HEADER_EXT_TAG, "RPMTAG_FILENAMES",
04747 { .tagFunction = filenamesTag } },
04748 { HEADER_EXT_TAG, "RPMTAG_FILEPATHS",
04749 { .tagFunction = filepathsTag } },
04750 { HEADER_EXT_TAG, "RPMTAG_ORIGPATHS",
04751 { .tagFunction = origpathsTag } },
04752 { HEADER_EXT_TAG, "RPMTAG_FILESTAT",
04753 { .tagFunction = filestatTag } },
04754 { HEADER_EXT_TAG, "RPMTAG_PROVIDEXMLENTRY",
04755 { .tagFunction = PxmlTag } },
04756 { HEADER_EXT_TAG, "RPMTAG_REQUIREXMLENTRY",
04757 { .tagFunction = RxmlTag } },
04758 { HEADER_EXT_TAG, "RPMTAG_CONFLICTXMLENTRY",
04759 { .tagFunction = CxmlTag } },
04760 { HEADER_EXT_TAG, "RPMTAG_OBSOLETEXMLENTRY",
04761 { .tagFunction = OxmlTag } },
04762 { HEADER_EXT_TAG, "RPMTAG_FILESXMLENTRY1",
04763 { .tagFunction = F1xmlTag } },
04764 { HEADER_EXT_TAG, "RPMTAG_FILESXMLENTRY2",
04765 { .tagFunction = F2xmlTag } },
04766 { HEADER_EXT_TAG, "RPMTAG_PROVIDEYAMLENTRY",
04767 { .tagFunction = PyamlTag } },
04768 { HEADER_EXT_TAG, "RPMTAG_REQUIREYAMLENTRY",
04769 { .tagFunction = RyamlTag } },
04770 { HEADER_EXT_TAG, "RPMTAG_CONFLICTYAMLENTRY",
04771 { .tagFunction = CyamlTag } },
04772 { HEADER_EXT_TAG, "RPMTAG_OBSOLETEYAMLENTRY",
04773 { .tagFunction = OyamlTag } },
04774 { HEADER_EXT_TAG, "RPMTAG_FILESYAMLENTRY1",
04775 { .tagFunction = F1yamlTag } },
04776 { HEADER_EXT_TAG, "RPMTAG_FILESYAMLENTRY2",
04777 { .tagFunction = F2yamlTag } },
04778 { HEADER_EXT_TAG, "RPMTAG_PROVIDESQLENTRY",
04779 { .tagFunction = PsqlTag } },
04780 { HEADER_EXT_TAG, "RPMTAG_REQUIRESQLENTRY",
04781 { .tagFunction = RsqlTag } },
04782 { HEADER_EXT_TAG, "RPMTAG_CONFLICTSQLENTRY",
04783 { .tagFunction = CsqlTag } },
04784 { HEADER_EXT_TAG, "RPMTAG_OBSOLETESQLENTRY",
04785 { .tagFunction = OsqlTag } },
04786 { HEADER_EXT_TAG, "RPMTAG_FILESSQLENTRY1",
04787 { .tagFunction = F1sqlTag } },
04788 { HEADER_EXT_TAG, "RPMTAG_FILESSQLENTRY2",
04789 { .tagFunction = F2sqlTag } },
04790 { HEADER_EXT_TAG, "RPMTAG_DEBCONFLICTS",
04791 { .tagFunction = debconflictsTag } },
04792 { HEADER_EXT_TAG, "RPMTAG_DEBDEPENDS",
04793 { .tagFunction = debdependsTag } },
04794 { HEADER_EXT_TAG, "RPMTAG_DEBMD5SUMS",
04795 { .tagFunction = debmd5sumsTag } },
04796 { HEADER_EXT_TAG, "RPMTAG_DEBOBSOLETES",
04797 { .tagFunction = debobsoletesTag } },
04798 { HEADER_EXT_TAG, "RPMTAG_DEBPROVIDES",
04799 { .tagFunction = debprovidesTag } },
04800 { HEADER_EXT_TAG, "RPMTAG_NEEDSWHAT",
04801 { .tagFunction = needswhatTag } },
04802 { HEADER_EXT_TAG, "RPMTAG_WHATNEEDS",
04803 { .tagFunction = whatneedsTag } },
04804 { HEADER_EXT_FORMAT, "armor",
04805 { .fmtFunction = armorFormat } },
04806 { HEADER_EXT_FORMAT, "base64",
04807 { .fmtFunction = base64Format } },
04808 { HEADER_EXT_FORMAT, "bncdata",
04809 { .fmtFunction = bncdataFormat } },
04810 { HEADER_EXT_FORMAT, "cdata",
04811 { .fmtFunction = cdataFormat } },
04812 { HEADER_EXT_FORMAT, "depflags",
04813 { .fmtFunction = depflagsFormat } },
04814 { HEADER_EXT_FORMAT, "deptype",
04815 { .fmtFunction = deptypeFormat } },
04816 { HEADER_EXT_FORMAT, "digest",
04817 { .fmtFunction = digestFormat } },
04818 { HEADER_EXT_FORMAT, "fflags",
04819 { .fmtFunction = fflagsFormat } },
04820 { HEADER_EXT_FORMAT, "iconv",
04821 { .fmtFunction = iconvFormat } },
04822 { HEADER_EXT_FORMAT, "perms",
04823 { .fmtFunction = permsFormat } },
04824 { HEADER_EXT_FORMAT, "permissions",
04825 { .fmtFunction = permsFormat } },
04826 { HEADER_EXT_FORMAT, "pgpsig",
04827 { .fmtFunction = pgpsigFormat } },
04828 { HEADER_EXT_FORMAT, "rpn",
04829 { .fmtFunction = rpnFormat } },
04830 { HEADER_EXT_FORMAT, "sqlescape",
04831 { .fmtFunction = sqlescapeFormat } },
04832 { HEADER_EXT_FORMAT, "stat",
04833 { .fmtFunction = statFormat } },
04834 { HEADER_EXT_FORMAT, "strsub",
04835 { .fmtFunction = strsubFormat } },
04836 { HEADER_EXT_FORMAT, "triggertype",
04837 { .fmtFunction = triggertypeFormat } },
04838 { HEADER_EXT_FORMAT, "utf8",
04839 { .fmtFunction = iconvFormat } },
04840 { HEADER_EXT_FORMAT, "uuid",
04841 { .fmtFunction = uuidFormat } },
04842 { HEADER_EXT_FORMAT, "xml",
04843 { .fmtFunction = xmlFormat } },
04844 { HEADER_EXT_FORMAT, "yaml",
04845 { .fmtFunction = yamlFormat } },
04846 { HEADER_EXT_MORE, NULL, { (void *) &headerDefaultFormats } }
04847 } ;
04848
04849 headerSprintfExtension headerCompoundFormats = &_headerCompoundFormats[0];
04850
04851
04852
04853 void rpmDisplayQueryTags(FILE * fp, headerTagTableEntry _rpmTagTable, headerSprintfExtension _rpmHeaderFormats)
04854 {
04855 const struct headerTagTableEntry_s * t;
04856 headerSprintfExtension exts;
04857 headerSprintfExtension ext;
04858 int extNum;
04859
04860 if (fp == NULL)
04861 fp = stdout;
04862 if (_rpmTagTable == NULL)
04863 _rpmTagTable = rpmTagTable;
04864
04865
04866 if (_rpmHeaderFormats == NULL)
04867 _rpmHeaderFormats = headerCompoundFormats;
04868
04869 for (t = _rpmTagTable; t && t->name; t++) {
04870
04871 static const char * tagtypes[] = {
04872 "", "char", "uint8", "uint16", "uint32", "uint64",
04873 "string", "octets", "argv", "i18nstring",
04874 };
04875 rpmuint32_t ttype;
04876
04877 if (rpmIsVerbose()) {
04878 fprintf(fp, "%-20s %6d", t->name + 7, t->val);
04879 ttype = t->type & RPM_MASK_TYPE;
04880 if (ttype < RPM_MIN_TYPE || ttype > RPM_MAX_TYPE)
04881 continue;
04882 if (t->type & RPM_OPENPGP_RETURN_TYPE)
04883 fprintf(fp, " openpgp");
04884 if (t->type & RPM_X509_RETURN_TYPE)
04885 fprintf(fp, " x509");
04886 if (t->type & RPM_ASN1_RETURN_TYPE)
04887 fprintf(fp, " asn1");
04888 if (t->type & RPM_OPAQUE_RETURN_TYPE)
04889 fprintf(fp, " opaque");
04890 fprintf(fp, " %s", tagtypes[ttype]);
04891 if (t->type & RPM_ARRAY_RETURN_TYPE)
04892 fprintf(fp, " array");
04893 if (t->type & RPM_MAPPING_RETURN_TYPE)
04894 fprintf(fp, " mapping");
04895 if (t->type & RPM_PROBE_RETURN_TYPE)
04896 fprintf(fp, " probe");
04897 if (t->type & RPM_TREE_RETURN_TYPE)
04898 fprintf(fp, " tree");
04899 } else
04900 fprintf(fp, "%s", t->name + 7);
04901 fprintf(fp, "\n");
04902 }
04903
04904 exts = _rpmHeaderFormats;
04905 for (ext = exts, extNum = 0; ext != NULL && ext->type != HEADER_EXT_LAST;
04906 ext = (ext->type == HEADER_EXT_MORE ? *ext->u.more : ext+1), extNum++)
04907 {
04908 if (ext->name == NULL || ext->type != HEADER_EXT_TAG)
04909 continue;
04910
04911
04912 if (tagValue(ext->name) > 0)
04913 continue;
04914 fprintf(fp, "%s\n", ext->name + 7);
04915 }
04916 }
04917
04918
04919
04920 #define PARSER_BEGIN 0
04921 #define PARSER_IN_ARRAY 1
04922 #define PARSER_IN_EXPR 2
04923
04926 typedef struct sprintfTag_s * sprintfTag;
04927
04930 struct sprintfTag_s {
04931 HE_s he;
04932
04933 headerTagFormatFunction * fmtfuncs;
04934
04935 headerTagTagFunction ext;
04936 int extNum;
04937
04938 rpmTag * tagno;
04939 int justOne;
04940 int arrayCount;
04941
04942 char * format;
04943
04944 ARGV_t av;
04945
04946 ARGV_t params;
04947 unsigned pad;
04948 };
04949
04952 typedef struct sprintfToken_s * sprintfToken;
04953
04956 struct sprintfToken_s {
04957 enum {
04958 PTOK_NONE = 0,
04959 PTOK_TAG = 1,
04960 PTOK_ARRAY = 2,
04961 PTOK_STRING = 3,
04962 PTOK_COND = 4
04963 } type;
04964 union {
04965 struct sprintfTag_s tag;
04966 struct {
04967
04968 sprintfToken format;
04969 size_t numTokens;
04970 } array;
04971 struct {
04972
04973 char * string;
04974 size_t len;
04975 } string;
04976 struct {
04977
04978 sprintfToken ifFormat;
04979 size_t numIfTokens;
04980
04981 sprintfToken elseFormat;
04982 size_t numElseTokens;
04983 struct sprintfTag_s tag;
04984 } cond;
04985 } u;
04986 };
04987
04990 typedef struct headerSprintfArgs_s * headerSprintfArgs;
04991
04994 struct headerSprintfArgs_s {
04995 Header h;
04996 char * fmt;
04997
04998 headerTagTableEntry tags;
04999
05000 headerSprintfExtension exts;
05001
05002 const char * errmsg;
05003 HE_t ec;
05004 int nec;
05005 sprintfToken format;
05006
05007 HeaderIterator hi;
05008
05009 char * val;
05010 size_t vallen;
05011 size_t alloced;
05012 size_t numTokens;
05013 size_t i;
05014 };
05015
05016
05017
05018
05019
05022 static char escapedChar(const char ch)
05023
05024 {
05025
05026 if (_hdrqf_debug)
05027 fprintf(stderr, "\t\t\\%c\n", ch);
05028
05029 switch (ch) {
05030 case 'a': return '\a';
05031 case 'b': return '\b';
05032 case 'f': return '\f';
05033 case 'n': return '\n';
05034 case 'r': return '\r';
05035 case 't': return '\t';
05036 case 'v': return '\v';
05037 default: return ch;
05038 }
05039 }
05040
05045
05046 static HE_t rpmheClean( HE_t he)
05047
05048 {
05049 if (he) {
05050 if (he->freeData && he->p.ptr != NULL)
05051 he->p.ptr = _free(he->p.ptr);
05052 memset(he, 0, sizeof(*he));
05053 }
05054 return he;
05055 }
05056
05063 static sprintfToken
05064 freeFormat( sprintfToken format, size_t num)
05065
05066 {
05067 unsigned i;
05068
05069 if (format == NULL) return NULL;
05070
05071 for (i = 0; i < (unsigned) num; i++) {
05072 switch (format[i].type) {
05073 case PTOK_TAG:
05074 (void) rpmheClean(&format[i].u.tag.he);
05075 format[i].u.tag.tagno = _free(format[i].u.tag.tagno);
05076 format[i].u.tag.av = argvFree(format[i].u.tag.av);
05077 format[i].u.tag.params = argvFree(format[i].u.tag.params);
05078
05079 format[i].u.tag.fmtfuncs = _free(format[i].u.tag.fmtfuncs);
05080
05081 break;
05082 case PTOK_ARRAY:
05083 format[i].u.array.format =
05084 freeFormat(format[i].u.array.format,
05085 format[i].u.array.numTokens);
05086 break;
05087 case PTOK_COND:
05088 format[i].u.cond.ifFormat =
05089 freeFormat(format[i].u.cond.ifFormat,
05090 format[i].u.cond.numIfTokens);
05091 format[i].u.cond.elseFormat =
05092 freeFormat(format[i].u.cond.elseFormat,
05093 format[i].u.cond.numElseTokens);
05094 (void) rpmheClean(&format[i].u.cond.tag.he);
05095 format[i].u.cond.tag.tagno = _free(format[i].u.cond.tag.tagno);
05096 format[i].u.cond.tag.av = argvFree(format[i].u.cond.tag.av);
05097 format[i].u.cond.tag.params = argvFree(format[i].u.cond.tag.params);
05098
05099 format[i].u.cond.tag.fmtfuncs = _free(format[i].u.cond.tag.fmtfuncs);
05100
05101 break;
05102 case PTOK_NONE:
05103 case PTOK_STRING:
05104 default:
05105 break;
05106 }
05107 }
05108 format = _free(format);
05109 return NULL;
05110 }
05111
05117 static headerSprintfArgs hsaInit( headerSprintfArgs hsa)
05118
05119
05120 {
05121 sprintfTag tag =
05122 (hsa->format->type == PTOK_TAG
05123 ? &hsa->format->u.tag :
05124 (hsa->format->type == PTOK_ARRAY
05125 ? &hsa->format->u.array.format->u.tag :
05126 NULL));
05127
05128 if (hsa != NULL) {
05129 hsa->i = 0;
05130 if (tag != NULL && tag->tagno != NULL && tag->tagno[0] == (rpmTag)-2)
05131 hsa->hi = headerInit(hsa->h);
05132 }
05133
05134 return hsa;
05135
05136 }
05137
05143
05144 static sprintfToken hsaNext( headerSprintfArgs hsa)
05145
05146
05147 {
05148 sprintfToken fmt = NULL;
05149 sprintfTag tag =
05150 (hsa->format->type == PTOK_TAG
05151 ? &hsa->format->u.tag :
05152 (hsa->format->type == PTOK_ARRAY
05153 ? &hsa->format->u.array.format->u.tag :
05154 NULL));
05155
05156 if (hsa != NULL && hsa->i < hsa->numTokens) {
05157 fmt = hsa->format + hsa->i;
05158 if (hsa->hi == NULL) {
05159 hsa->i++;
05160 } else {
05161 HE_t he = rpmheClean(&tag->he);
05162 if (!headerNext(hsa->hi, he, 0))
05163 {
05164 tag->tagno[0] = 0;
05165 return NULL;
05166 }
05167 he->avail = 1;
05168 tag->tagno[0] = he->tag;
05169 }
05170 }
05171
05172
05173 return fmt;
05174
05175 }
05176
05182 static headerSprintfArgs hsaFini( headerSprintfArgs hsa)
05183
05184
05185 {
05186 if (hsa != NULL) {
05187 hsa->hi = headerFini(hsa->hi);
05188 hsa->i = 0;
05189 }
05190
05191 return hsa;
05192
05193 }
05194
05201
05202 static char * hsaReserve(headerSprintfArgs hsa, size_t need)
05203
05204 {
05205 if ((hsa->vallen + need) >= hsa->alloced) {
05206 if (hsa->alloced <= need)
05207 hsa->alloced += need;
05208 hsa->alloced <<= 1;
05209 hsa->val = xrealloc(hsa->val, hsa->alloced+1);
05210 }
05211 return hsa->val + hsa->vallen;
05212 }
05213
05221
05222 static const char * myTagName(headerTagTableEntry tbl, rpmuint32_t val,
05223 rpmuint32_t *typep)
05224
05225 {
05226 static char name[128];
05227 const char * s;
05228 char *t;
05229
05230
05231 if (tbl == NULL || tbl == rpmTagTable) {
05232 s = tagName(val);
05233 if (s != NULL && typep != NULL)
05234 *typep = tagType(val);
05235 return s;
05236 }
05237
05238 for (; tbl->name != NULL; tbl++) {
05239 if (tbl->val == val)
05240 break;
05241 }
05242 if ((s = tbl->name) == NULL)
05243 return NULL;
05244 s += sizeof("RPMTAG_") - 1;
05245 t = name;
05246 *t++ = *s++;
05247 while (*s != '\0')
05248 *t++ = (char)xtolower((int)*s++);
05249 *t = '\0';
05250 if (typep)
05251 *typep = tbl->type;
05252 return name;
05253 }
05254
05261 static rpmuint32_t myTagValue(headerTagTableEntry tbl, const char * name)
05262
05263 {
05264 rpmuint32_t val = 0;
05265
05266
05267 if (tbl == NULL || tbl == rpmTagTable)
05268 val = tagValue(name);
05269 else
05270 for (; tbl->name != NULL; tbl++) {
05271 if (xstrcasecmp(tbl->name, name))
05272 continue;
05273 val = tbl->val;
05274 break;
05275 }
05276 return val;
05277 }
05278
05286 static int findTag(headerSprintfArgs hsa, sprintfToken token, const char * name)
05287
05288 {
05289 headerSprintfExtension exts = hsa->exts;
05290 headerSprintfExtension ext;
05291 sprintfTag stag = (token->type == PTOK_COND
05292 ? &token->u.cond.tag : &token->u.tag);
05293 int extNum;
05294 rpmTag tagno = (rpmTag)-1;
05295
05296 stag->fmtfuncs = NULL;
05297 stag->ext = NULL;
05298 stag->extNum = 0;
05299
05300 if (!strcmp(name, "*")) {
05301 tagno = (rpmTag)-2;
05302 goto bingo;
05303 }
05304
05305 if (strncmp("RPMTAG_", name, sizeof("RPMTAG_")-1)) {
05306 char * t = alloca(strlen(name) + sizeof("RPMTAG_"));
05307 (void) stpcpy( stpcpy(t, "RPMTAG_"), name);
05308 name = t;
05309 }
05310
05311
05312 for (ext = exts, extNum = 0; ext != NULL && ext->type != HEADER_EXT_LAST;
05313 ext = (ext->type == HEADER_EXT_MORE ? *ext->u.more : ext+1), extNum++)
05314 {
05315 if (ext->name == NULL || ext->type != HEADER_EXT_TAG)
05316 continue;
05317 if (!xstrcasecmp(ext->name, name)) {
05318 stag->ext = ext->u.tagFunction;
05319 stag->extNum = extNum;
05320 tagno = tagValue(name);
05321 goto bingo;
05322 }
05323 }
05324
05325
05326 tagno = myTagValue(hsa->tags, name);
05327 if (tagno != 0)
05328 goto bingo;
05329
05330 return 1;
05331
05332 bingo:
05333 stag->tagno = xcalloc(1, sizeof(*stag->tagno));
05334 stag->tagno[0] = tagno;
05335
05336 if (stag->av != NULL) {
05337 int i;
05338
05339 stag->fmtfuncs = xcalloc(argvCount(stag->av) + 1, sizeof(*stag->fmtfuncs));
05340
05341 for (i = 0; stag->av[i] != NULL; i++) {
05342 for (ext = exts; ext != NULL && ext->type != HEADER_EXT_LAST;
05343 ext = (ext->type == HEADER_EXT_MORE ? *ext->u.more : ext+1))
05344 {
05345 if (ext->name == NULL || ext->type != HEADER_EXT_FORMAT)
05346 continue;
05347 if (strcmp(ext->name, stag->av[i]+1))
05348 continue;
05349 stag->fmtfuncs[i] = ext->u.fmtFunction;
05350 break;
05351 }
05352 }
05353 }
05354 return 0;
05355 }
05356
05357
05366 static int parseExpression(headerSprintfArgs hsa, sprintfToken token,
05367 char * str, char ** endPtr)
05368
05369 ;
05370
05381 static int parseFormat(headerSprintfArgs hsa, char * str,
05382 sprintfToken * formatPtr,
05383 size_t * numTokensPtr,
05384 char ** endPtr, int state)
05385
05386
05387
05388 {
05389
05390 static const char *pstates[] = {
05391 "NORMAL", "ARRAY", "EXPR", "WTF?"
05392 };
05393 char * chptr, * start, * next, * dst;
05394 sprintfToken format;
05395 sprintfToken token;
05396 size_t numTokens;
05397 unsigned i;
05398 int done = 0;
05399 int xx;
05400
05401
05402 if (_hdrqf_debug)
05403 fprintf(stderr, "--> parseFormat(%p, \"%.20s...\", %p, %p, %p, %s)\n", hsa, str, formatPtr, numTokensPtr, endPtr, pstates[(state & 0x3)]);
05404
05405
05406
05407 numTokens = 0;
05408 if (str != NULL)
05409 for (chptr = str; *chptr != '\0'; chptr++)
05410 if (*chptr == '%') numTokens++;
05411 numTokens = numTokens * 2 + 1;
05412
05413 format = xcalloc(numTokens, sizeof(*format));
05414 if (endPtr) *endPtr = NULL;
05415
05416
05417 dst = start = str;
05418 numTokens = 0;
05419 token = NULL;
05420 if (start != NULL)
05421 while (*start != '\0') {
05422 switch (*start) {
05423 case '%':
05424
05425 if (*(start + 1) == '%') {
05426 if (token == NULL || token->type != PTOK_STRING) {
05427 token = format + numTokens++;
05428 token->type = PTOK_STRING;
05429
05430 dst = token->u.string.string = start;
05431
05432 }
05433 start++;
05434 *dst++ = *start++;
05435 break;
05436 }
05437
05438 token = format + numTokens++;
05439 *dst++ = '\0';
05440 start++;
05441
05442 if (*start == '|') {
05443 char * newEnd;
05444
05445 start++;
05446 if (parseExpression(hsa, token, start, &newEnd))
05447 {
05448 format = freeFormat(format, numTokens);
05449 return 1;
05450 }
05451 start = newEnd;
05452 break;
05453 }
05454
05455
05456 token->u.tag.format = start;
05457
05458 token->u.tag.pad = 0;
05459 token->u.tag.justOne = 0;
05460 token->u.tag.arrayCount = 0;
05461
05462 chptr = start;
05463 while (*chptr && *chptr != '{' && *chptr != '%') chptr++;
05464 if (!*chptr || *chptr == '%') {
05465 hsa->errmsg = _("missing { after %");
05466 format = freeFormat(format, numTokens);
05467 return 1;
05468 }
05469
05470
05471 if (_hdrqf_debug)
05472 fprintf(stderr, "\tchptr *%p = NUL\n", chptr);
05473
05474 *chptr++ = '\0';
05475
05476 while (start < chptr) {
05477 if (xisdigit((int)*start)) {
05478 i = strtoul(start, &start, 10);
05479 token->u.tag.pad += i;
05480 start = chptr;
05481 break;
05482 } else {
05483 start++;
05484 }
05485 }
05486
05487 if (*start == '=') {
05488 token->u.tag.justOne = 1;
05489 start++;
05490 } else if (*start == '#') {
05491 token->u.tag.justOne = 1;
05492 token->u.tag.arrayCount = 1;
05493 start++;
05494 }
05495
05496 next = start;
05497 while (*next && *next != '}') next++;
05498 if (!*next) {
05499 hsa->errmsg = _("missing } after %{");
05500 format = freeFormat(format, numTokens);
05501 return 1;
05502 }
05503
05504 if (_hdrqf_debug)
05505 fprintf(stderr, "\tnext *%p = NUL\n", next);
05506
05507 *next++ = '\0';
05508
05509 #define isSEP(_c) ((_c) == ':' || (_c) == '|')
05510 chptr = start;
05511 while (!(*chptr == '\0' || isSEP(*chptr))) chptr++;
05512
05513 while (isSEP(*chptr)) {
05514 if (chptr[1] == '\0' || isSEP(chptr[1])) {
05515 hsa->errmsg = _("empty tag format");
05516 format = freeFormat(format, numTokens);
05517 return 1;
05518 }
05519
05520 { char * te = chptr + 1;
05521 char * t = strchr(te, '(');
05522 char c;
05523
05524 while (!(*te == '\0' || isSEP(*te))) {
05525 #ifdef NOTYET
05526 if (te[0] == '\\' && te[1] != '\0') te++;
05527 #endif
05528 te++;
05529 }
05530 c = *te; *te = '\0';
05531
05532 if (t != NULL) {
05533 *t++ = '\0';
05534 if (te <= t || te[-1] != ')') {
05535 hsa->errmsg = _("malformed parameter list");
05536 format = freeFormat(format, numTokens);
05537 return 1;
05538 }
05539 te[-1] = '\0';
05540 xx = argvAdd(&token->u.tag.params, t);
05541 } else
05542 xx = argvAdd(&token->u.tag.params, "");
05543
05544 if (_hdrqf_debug)
05545 fprintf(stderr, "\tformat \"%s\" params \"%s\"\n", chptr, (t ? t : ""));
05546
05547 xx = argvAdd(&token->u.tag.av, chptr);
05548 *te = c;
05549 *chptr = '\0';
05550 chptr = te;
05551 }
05552 }
05553 #undef isSEP
05554
05555 if (*start == '\0') {
05556 hsa->errmsg = _("empty tag name");
05557 format = freeFormat(format, numTokens);
05558 return 1;
05559 }
05560
05561 i = 0;
05562 token->type = PTOK_TAG;
05563
05564 if (findTag(hsa, token, start)) {
05565 hsa->errmsg = _("unknown tag");
05566 format = freeFormat(format, numTokens);
05567 return 1;
05568 }
05569
05570 dst = start = next;
05571
05572 if (_hdrqf_debug)
05573 fprintf(stderr, "\tdst = start = next %p\n", dst);
05574
05575 break;
05576
05577 case '[':
05578
05579 if (_hdrqf_debug)
05580 fprintf(stderr, "\t%s => %s *%p = NUL\n", pstates[(state & 0x3)], pstates[PARSER_IN_ARRAY], start);
05581
05582 *start++ = '\0';
05583 token = format + numTokens++;
05584
05585 if (parseFormat(hsa, start,
05586 &token->u.array.format,
05587 &token->u.array.numTokens,
05588 &start, PARSER_IN_ARRAY))
05589 {
05590 format = freeFormat(format, numTokens);
05591 return 1;
05592 }
05593
05594 if (!start) {
05595 hsa->errmsg = _("] expected at end of array");
05596 format = freeFormat(format, numTokens);
05597 return 1;
05598 }
05599
05600 dst = start;
05601
05602 if (_hdrqf_debug)
05603 fprintf(stderr, "\tdst = start %p\n", dst);
05604
05605
05606 token->type = PTOK_ARRAY;
05607
05608 break;
05609
05610 case ']':
05611 if (state != PARSER_IN_ARRAY) {
05612 hsa->errmsg = _("unexpected ]");
05613 format = freeFormat(format, numTokens);
05614 return 1;
05615 }
05616 *start++ = '\0';
05617
05618 if (_hdrqf_debug)
05619 fprintf(stderr, "\t<= %s %p[-1] = NUL\n", pstates[(state & 0x3)], start);
05620
05621 if (endPtr) *endPtr = start;
05622 done = 1;
05623 break;
05624
05625 case '}':
05626 if (state != PARSER_IN_EXPR) {
05627 hsa->errmsg = _("unexpected }");
05628 format = freeFormat(format, numTokens);
05629 return 1;
05630 }
05631 *start++ = '\0';
05632
05633 if (_hdrqf_debug)
05634 fprintf(stderr, "\t<= %s %p[-1] = NUL\n", pstates[(state & 0x3)], start);
05635
05636 if (endPtr) *endPtr = start;
05637 done = 1;
05638 break;
05639
05640 default:
05641 if (token == NULL || token->type != PTOK_STRING) {
05642 token = format + numTokens++;
05643 token->type = PTOK_STRING;
05644
05645 dst = token->u.string.string = start;
05646
05647 }
05648
05649
05650 if (_hdrqf_debug)
05651 fprintf(stderr, "\t*%p = *%p \"%.30s\"\n", dst, start, start);
05652
05653 if (start[0] == '\\' && start[1] != '\0') {
05654 start++;
05655 *dst++ = escapedChar(*start);
05656 *start++ = '\0';
05657 } else {
05658 *dst++ = *start++;
05659 }
05660 break;
05661 }
05662 if (dst < start) *dst = '\0';
05663 if (done)
05664 break;
05665 }
05666
05667
05668 if (dst != NULL)
05669 *dst = '\0';
05670
05671 for (i = 0; i < (unsigned) numTokens; i++) {
05672 token = format + i;
05673 switch(token->type) {
05674 default:
05675 break;
05676 case PTOK_STRING:
05677 token->u.string.len = strlen(token->u.string.string);
05678 break;
05679 }
05680 }
05681
05682 if (numTokensPtr != NULL)
05683 *numTokensPtr = numTokens;
05684 if (formatPtr != NULL)
05685 *formatPtr = format;
05686
05687 return 0;
05688 }
05689
05690 static int parseExpression(headerSprintfArgs hsa, sprintfToken token,
05691 char * str, char ** endPtr)
05692 {
05693 char * chptr;
05694 char * end;
05695
05696
05697 if (_hdrqf_debug)
05698 fprintf(stderr, "--> parseExpression(%p, %p, \"%.20s...\", %p)\n", hsa, token, str, endPtr);
05699
05700
05701 hsa->errmsg = NULL;
05702 chptr = str;
05703 while (*chptr && *chptr != '?') chptr++;
05704
05705 if (*chptr != '?') {
05706 hsa->errmsg = _("? expected in expression");
05707 return 1;
05708 }
05709
05710 *chptr++ = '\0';
05711
05712 if (*chptr != '{') {
05713 hsa->errmsg = _("{ expected after ? in expression");
05714 return 1;
05715 }
05716
05717 chptr++;
05718
05719 if (parseFormat(hsa, chptr, &token->u.cond.ifFormat,
05720 &token->u.cond.numIfTokens, &end, PARSER_IN_EXPR))
05721 return 1;
05722
05723
05724 if (!(end && *end)) {
05725 hsa->errmsg = _("} expected in expression");
05726 token->u.cond.ifFormat =
05727 freeFormat(token->u.cond.ifFormat, token->u.cond.numIfTokens);
05728 return 1;
05729 }
05730
05731 chptr = end;
05732 if (*chptr != ':' && *chptr != '|') {
05733 hsa->errmsg = _(": expected following ? subexpression");
05734 token->u.cond.ifFormat =
05735 freeFormat(token->u.cond.ifFormat, token->u.cond.numIfTokens);
05736 return 1;
05737 }
05738
05739 if (*chptr == '|') {
05740 if (parseFormat(hsa, NULL, &token->u.cond.elseFormat,
05741 &token->u.cond.numElseTokens, &end, PARSER_IN_EXPR))
05742 {
05743 token->u.cond.ifFormat =
05744 freeFormat(token->u.cond.ifFormat, token->u.cond.numIfTokens);
05745 return 1;
05746 }
05747 } else {
05748 chptr++;
05749
05750 if (*chptr != '{') {
05751 hsa->errmsg = _("{ expected after : in expression");
05752 token->u.cond.ifFormat =
05753 freeFormat(token->u.cond.ifFormat, token->u.cond.numIfTokens);
05754 return 1;
05755 }
05756
05757 chptr++;
05758
05759 if (parseFormat(hsa, chptr, &token->u.cond.elseFormat,
05760 &token->u.cond.numElseTokens, &end, PARSER_IN_EXPR))
05761 return 1;
05762
05763
05764 if (!(end && *end)) {
05765 hsa->errmsg = _("} expected in expression");
05766 token->u.cond.ifFormat =
05767 freeFormat(token->u.cond.ifFormat, token->u.cond.numIfTokens);
05768 return 1;
05769 }
05770
05771 chptr = end;
05772 if (*chptr != '|') {
05773 hsa->errmsg = _("| expected at end of expression");
05774 token->u.cond.ifFormat =
05775 freeFormat(token->u.cond.ifFormat, token->u.cond.numIfTokens);
05776 token->u.cond.elseFormat =
05777 freeFormat(token->u.cond.elseFormat, token->u.cond.numElseTokens);
05778 return 1;
05779 }
05780 }
05781
05782 chptr++;
05783
05784 *endPtr = chptr;
05785
05786 token->type = PTOK_COND;
05787
05788 (void) findTag(hsa, token, str);
05789
05790 return 0;
05791 }
05792
05801 static int getExtension(headerSprintfArgs hsa, headerTagTagFunction fn,
05802 HE_t he, HE_t ec)
05803
05804 {
05805 int rc = 0;
05806 if (!ec->avail) {
05807 he = rpmheClean(he);
05808 rc = fn(hsa->h, he);
05809 *ec = *he;
05810 if (!rc)
05811 ec->avail = 1;
05812 } else
05813 *he = *ec;
05814 he->freeData = 0;
05815 rc = (rc == 0);
05816 return rc;
05817 }
05818
05826
05827 static char * formatValue(headerSprintfArgs hsa, sprintfTag tag,
05828 size_t element)
05829
05830
05831 {
05832 HE_t vhe = memset(alloca(sizeof(*vhe)), 0, sizeof(*vhe));
05833 HE_t he = &tag->he;
05834 char * val = NULL;
05835 size_t need = 0;
05836 char * t, * te;
05837 rpmuint64_t ival = 0;
05838 rpmTagCount countBuf;
05839 int xx;
05840
05841 if (!he->avail) {
05842 if (tag->ext)
05843 xx = getExtension(hsa, tag->ext, he, hsa->ec + tag->extNum);
05844 else {
05845 he->tag = tag->tagno[0];
05846 xx = headerGet(hsa->h, he, 0);
05847 }
05848 if (!xx) {
05849 (void) rpmheClean(he);
05850 he->t = RPM_STRING_TYPE;
05851 he->p.str = xstrdup("(none)");
05852 he->c = 1;
05853 he->freeData = 1;
05854 }
05855 he->avail = 1;
05856 }
05857
05858 if (tag->arrayCount) {
05859 countBuf = he->c;
05860 he = rpmheClean(he);
05861 he->t = RPM_UINT32_TYPE;
05862 he->p.ui32p = &countBuf;
05863 he->c = 1;
05864 he->freeData = 0;
05865 }
05866
05867 vhe->tag = he->tag;
05868
05869 if (he->p.ptr)
05870 switch (he->t) {
05871 default:
05872 val = xstrdup("(unknown type)");
05873 need = strlen(val) + 1;
05874 goto exit;
05875 break;
05876 case RPM_I18NSTRING_TYPE:
05877 case RPM_STRING_ARRAY_TYPE:
05878 vhe->t = RPM_STRING_TYPE;
05879 vhe->p.str = he->p.argv[element];
05880 vhe->c = he->c;
05881 vhe->ix = (he->t == RPM_STRING_ARRAY_TYPE || he->c > 1 ? 0 : -1);
05882 break;
05883 case RPM_STRING_TYPE:
05884 vhe->p.str = he->p.str;
05885 vhe->t = RPM_STRING_TYPE;
05886 vhe->c = 0;
05887 vhe->ix = -1;
05888 break;
05889 case RPM_UINT8_TYPE:
05890 case RPM_UINT16_TYPE:
05891 case RPM_UINT32_TYPE:
05892 case RPM_UINT64_TYPE:
05893 switch (he->t) {
05894 default:
05895 assert(0);
05896 break;
05897 case RPM_UINT8_TYPE:
05898 ival = (rpmuint64_t)he->p.ui8p[element];
05899 break;
05900 case RPM_UINT16_TYPE:
05901 ival = (rpmuint64_t)he->p.ui16p[element];
05902 break;
05903 case RPM_UINT32_TYPE:
05904 ival = (rpmuint64_t)he->p.ui32p[element];
05905 break;
05906 case RPM_UINT64_TYPE:
05907 ival = he->p.ui64p[element];
05908 break;
05909 }
05910 vhe->t = RPM_UINT64_TYPE;
05911 vhe->p.ui64p = &ival;
05912 vhe->c = he->c;
05913 vhe->ix = (he->c > 1 ? 0 : -1);
05914 if ((tagType(he->tag) & RPM_MASK_RETURN_TYPE) == RPM_ARRAY_RETURN_TYPE)
05915 vhe->ix = 0;
05916 break;
05917
05918 case RPM_BIN_TYPE:
05919 vhe->t = RPM_BIN_TYPE;
05920 vhe->p.ptr = he->p.ptr;
05921 vhe->c = he->c;
05922 vhe->ix = -1;
05923 break;
05924 }
05925
05926
05927 if (tag->fmtfuncs) {
05928 char * nval;
05929 int i;
05930 for (i = 0; tag->av[i] != NULL; i++) {
05931 headerTagFormatFunction fmt;
05932 ARGV_t av;
05933 if ((fmt = tag->fmtfuncs[i]) == NULL)
05934 continue;
05935
05936 if (val != NULL && *tag->av[i] == '|') {
05937 int ix = vhe->ix;
05938 vhe = rpmheClean(vhe);
05939 vhe->tag = he->tag;
05940 vhe->t = RPM_STRING_TYPE;
05941 vhe->p.str = xstrdup(val);
05942 vhe->c = he->c;
05943 vhe->ix = ix;
05944 vhe->freeData = 1;
05945 }
05946 av = NULL;
05947 if (tag->params && tag->params[i] && *tag->params[i] != '\0')
05948 xx = argvSplit(&av, tag->params[i], ",");
05949
05950 nval = fmt(vhe, av);
05951
05952
05953 if (_hdrqf_debug)
05954 fprintf(stderr, "\t%s(%s) %p(%p,%p) ret \"%s\"\n", tag->av[i], (tag->params ? tag->params[i] : NULL), (void *)fmt, (void *)vhe, (void *)(av ? av : NULL), (val ? val : "(null)"));
05955
05956
05957
05958 if (val == NULL)
05959 val = xstrdup((nval ? nval : ""));
05960 else {
05961 char * oval = val;
05962
05963 val = rpmExpand(val, (*val != '\0' ? " | " : ""), nval, NULL);
05964 oval = _free(oval);
05965 }
05966 nval = _free(nval);
05967 av = argvFree(av);
05968 }
05969 }
05970 if (val == NULL)
05971 val = intFormat(vhe, NULL, NULL);
05972
05973 assert(val != NULL);
05974 if (val)
05975 need = strlen(val) + 1;
05976
05977 exit:
05978 if (val && need > 0) {
05979 if (tag->format && *tag->format && tag->pad > 0) {
05980 size_t nb;
05981 nb = strlen(tag->format) + sizeof("%s");
05982 t = alloca(nb);
05983 (void) stpcpy( stpcpy( stpcpy(t, "%"), tag->format), "s");
05984 nb = tag->pad + strlen(val) + 1;
05985 te = xmalloc(nb);
05986
05987 (void) snprintf(te, nb, t, val);
05988
05989 te[nb-1] = '\0';
05990 val = _free(val);
05991 val = te;
05992 need += tag->pad;
05993 }
05994 t = hsaReserve(hsa, need);
05995 te = stpcpy(t, val);
05996 hsa->vallen += (te - t);
05997 val = _free(val);
05998 }
05999
06000 return (hsa->val + hsa->vallen);
06001 }
06002
06010
06011 static char * singleSprintf(headerSprintfArgs hsa, sprintfToken token,
06012 size_t element)
06013
06014
06015 {
06016 char * t, * te;
06017 size_t i, j;
06018 size_t numElements;
06019 sprintfToken spft;
06020 sprintfTag tag = NULL;
06021 HE_t he = NULL;
06022 size_t condNumFormats;
06023 size_t need;
06024 int xx;
06025
06026
06027
06028 switch (token->type) {
06029 case PTOK_NONE:
06030 break;
06031
06032 case PTOK_STRING:
06033 need = token->u.string.len;
06034 if (need == 0) break;
06035 t = hsaReserve(hsa, need);
06036 te = stpcpy(t, token->u.string.string);
06037 hsa->vallen += (te - t);
06038 break;
06039
06040 case PTOK_TAG:
06041 t = hsa->val + hsa->vallen;
06042
06043 te = formatValue(hsa, &token->u.tag,
06044 (token->u.tag.justOne ? 0 : element));
06045
06046 if (te == NULL)
06047 return NULL;
06048 break;
06049
06050 case PTOK_COND:
06051 if (token->u.cond.tag.ext
06052 || headerIsEntry(hsa->h, token->u.cond.tag.tagno[0]))
06053 {
06054 spft = token->u.cond.ifFormat;
06055 condNumFormats = token->u.cond.numIfTokens;
06056 } else {
06057 spft = token->u.cond.elseFormat;
06058 condNumFormats = token->u.cond.numElseTokens;
06059 }
06060
06061 need = condNumFormats * 20;
06062 if (spft == NULL || need == 0) break;
06063
06064 t = hsaReserve(hsa, need);
06065 for (i = 0; i < condNumFormats; i++, spft++) {
06066
06067 te = singleSprintf(hsa, spft, element);
06068
06069 if (te == NULL)
06070 return NULL;
06071 }
06072 break;
06073
06074 case PTOK_ARRAY:
06075 numElements = 0;
06076 spft = token->u.array.format;
06077 for (i = 0; i < token->u.array.numTokens; i++, spft++)
06078 {
06079 tag = &spft->u.tag;
06080 if (spft->type != PTOK_TAG || tag->arrayCount || tag->justOne)
06081 continue;
06082 he = &tag->he;
06083 if (!he->avail) {
06084 he->tag = tag->tagno[0];
06085 if (tag->ext)
06086 xx = getExtension(hsa, tag->ext, he, hsa->ec + tag->extNum);
06087 else
06088 xx = headerGet(hsa->h, he, 0);
06089 if (!xx) {
06090 (void) rpmheClean(he);
06091 continue;
06092 }
06093 he->avail = 1;
06094 }
06095
06096
06097 switch (he->t) {
06098 default:
06099 if (numElements == 0) {
06100 numElements = he->c;
06101 break;
06102 }
06103 if ((size_t)he->c == numElements)
06104 break;
06105 hsa->errmsg =
06106 _("array iterator used with different sized arrays");
06107 he = rpmheClean(he);
06108 return NULL;
06109 break;
06110 case RPM_BIN_TYPE:
06111 case RPM_STRING_TYPE:
06112 if (numElements == 0)
06113 numElements = 1;
06114 break;
06115 }
06116 }
06117 spft = token->u.array.format;
06118
06119 if (numElements == 0) {
06120 #ifdef DYING
06121 need = sizeof("(none)\n") - 1;
06122 t = hsaReserve(hsa, need);
06123 te = stpcpy(t, "(none)\n");
06124 hsa->vallen += (te - t);
06125 #endif
06126 } else {
06127 int isxml;
06128 int isyaml;
06129
06130 need = numElements * token->u.array.numTokens;
06131 if (need == 0) break;
06132
06133 tag = &spft->u.tag;
06134
06135
06136 isxml = (spft->type == PTOK_TAG && tag->av != NULL &&
06137 tag->av[0] != NULL && !strcmp(tag->av[0]+1, "xml"));
06138 isyaml = (spft->type == PTOK_TAG && tag->av != NULL &&
06139 tag->av[0] != NULL && !strcmp(tag->av[0]+1, "yaml"));
06140
06141 if (isxml) {
06142 const char * tagN;
06143
06144 if (tag->tagno != NULL && tag->tagno[0] & 0x40000000) {
06145 tagN = myTagName(hsa->tags, tag->tagno[0], NULL);
06146 } else
06147 tagN = myTagName(hsa->tags, tag->tagno[0], NULL);
06148 assert(tagN != NULL);
06149 need = sizeof(" <rpmTag name=\"\">\n") + strlen(tagN);
06150 te = t = hsaReserve(hsa, need);
06151 te = stpcpy( stpcpy( stpcpy(te, " <rpmTag name=\""), tagN), "\">\n");
06152 hsa->vallen += (te - t);
06153 }
06154 if (isyaml) {
06155 rpmTagReturnType tagT = 0;
06156 const char * tagN;
06157
06158 if (tag->tagno != NULL && tag->tagno[0] & 0x40000000) {
06159 tagN = myTagName(hsa->tags, tag->tagno[0], NULL);
06160 tagT = numElements > 1
06161 ? RPM_ARRAY_RETURN_TYPE : RPM_SCALAR_RETURN_TYPE;
06162 } else
06163 tagN = myTagName(hsa->tags, tag->tagno[0], &tagT);
06164 assert(tagN != NULL);
06165 need = sizeof(" : - ") + strlen(tagN);
06166 te = t = hsaReserve(hsa, need);
06167 *te++ = ' ';
06168 *te++ = ' ';
06169 te = stpcpy(te, tagN);
06170 *te++ = ':';
06171 *te++ = (((tagT & RPM_MASK_RETURN_TYPE) == RPM_ARRAY_RETURN_TYPE)
06172 ? '\n' : ' ');
06173 *te = '\0';
06174 hsa->vallen += (te - t);
06175 }
06176
06177 need = numElements * token->u.array.numTokens * 10;
06178 t = hsaReserve(hsa, need);
06179 for (j = 0; j < numElements; j++) {
06180 spft = token->u.array.format;
06181 for (i = 0; i < token->u.array.numTokens; i++, spft++) {
06182
06183 te = singleSprintf(hsa, spft, j);
06184
06185 if (te == NULL)
06186 return NULL;
06187 }
06188 }
06189
06190 if (isxml) {
06191 need = sizeof(" </rpmTag>\n") - 1;
06192 te = t = hsaReserve(hsa, need);
06193 te = stpcpy(te, " </rpmTag>\n");
06194 hsa->vallen += (te - t);
06195 }
06196 if (isyaml) {
06197 #if 0
06198 need = sizeof("\n") - 1;
06199 te = t = hsaReserve(hsa, need);
06200 te = stpcpy(te, "\n");
06201 hsa->vallen += (te - t);
06202 #endif
06203 }
06204
06205 }
06206 break;
06207 }
06208
06209 return (hsa->val + hsa->vallen);
06210 }
06211
06218 static HE_t
06219 rpmecNew(const headerSprintfExtension exts, int * necp)
06220
06221 {
06222 headerSprintfExtension ext;
06223 HE_t ec;
06224 int extNum = 0;
06225
06226 if (exts != NULL)
06227 for (ext = exts, extNum = 0; ext != NULL && ext->type != HEADER_EXT_LAST;
06228 ext = (ext->type == HEADER_EXT_MORE ? *ext->u.more : ext+1), extNum++)
06229 {
06230 ;
06231 }
06232 if (necp)
06233 *necp = extNum;
06234 ec = xcalloc(extNum+1, sizeof(*ec));
06235 return ec;
06236 }
06237
06244 static HE_t
06245 rpmecFree(const headerSprintfExtension exts, HE_t ec)
06246
06247 {
06248 headerSprintfExtension ext;
06249 int extNum;
06250
06251 for (ext = exts, extNum = 0; ext != NULL && ext->type != HEADER_EXT_LAST;
06252 ext = (ext->type == HEADER_EXT_MORE ? *ext->u.more : ext+1), extNum++)
06253 {
06254 (void) rpmheClean(&ec[extNum]);
06255 }
06256
06257 ec = _free(ec);
06258 return NULL;
06259 }
06260
06261 char * headerSprintf(Header h, const char * fmt,
06262 headerTagTableEntry tags,
06263 headerSprintfExtension exts,
06264 errmsg_t * errmsg)
06265 {
06266 headerSprintfArgs hsa = memset(alloca(sizeof(*hsa)), 0, sizeof(*hsa));
06267 sprintfToken nextfmt;
06268 sprintfTag tag;
06269 char * t, * te;
06270 int isxml;
06271 int isyaml;
06272 int need;
06273
06274
06275 if (_hdrqf_debug)
06276 fprintf(stderr, "==> headerSprintf(%p, \"%s\", %p, %p, %p)\n", h, fmt, tags, exts, errmsg);
06277
06278
06279
06280 if (tags == NULL)
06281 tags = rpmTagTable;
06282
06283 if (exts == NULL)
06284 exts = headerCompoundFormats;
06285
06286
06287 hsa->h = headerLink(h);
06288
06289 hsa->fmt = xstrdup(fmt);
06290
06291 hsa->exts = exts;
06292 hsa->tags = tags;
06293
06294 hsa->errmsg = NULL;
06295
06296 if (parseFormat(hsa, hsa->fmt, &hsa->format, &hsa->numTokens, NULL, PARSER_BEGIN))
06297 goto exit;
06298
06299 hsa->nec = 0;
06300 hsa->ec = rpmecNew(hsa->exts, &hsa->nec);
06301 hsa->val = xstrdup("");
06302
06303 tag =
06304 (hsa->format->type == PTOK_TAG
06305 ? &hsa->format->u.tag :
06306 (hsa->format->type == PTOK_ARRAY
06307 ? &hsa->format->u.array.format->u.tag :
06308 NULL));
06309
06310
06311 isxml = (tag != NULL && tag->tagno != NULL && tag->tagno[0] == (rpmTag)-2 && tag->av != NULL
06312 && tag->av[0] != NULL && !strcmp(tag->av[0]+1, "xml"));
06313 isyaml = (tag != NULL && tag->tagno != NULL && tag->tagno[0] == (rpmTag)-2 && tag->av != NULL
06314 && tag->av[0] != NULL && !strcmp(tag->av[0]+1, "yaml"));
06315
06316 if (isxml) {
06317 need = sizeof("<rpmHeader>\n") - 1;
06318 t = hsaReserve(hsa, need);
06319 te = stpcpy(t, "<rpmHeader>\n");
06320 hsa->vallen += (te - t);
06321 }
06322 if (isyaml) {
06323 need = sizeof("- !!omap\n") - 1;
06324 t = hsaReserve(hsa, need);
06325 te = stpcpy(t, "- !!omap\n");
06326 hsa->vallen += (te - t);
06327 }
06328
06329 hsa = hsaInit(hsa);
06330 while ((nextfmt = hsaNext(hsa)) != NULL) {
06331
06332 te = singleSprintf(hsa, nextfmt, 0);
06333
06334 if (te == NULL) {
06335 hsa->val = _free(hsa->val);
06336 break;
06337 }
06338 }
06339 hsa = hsaFini(hsa);
06340
06341 if (isxml) {
06342 need = sizeof("</rpmHeader>\n") - 1;
06343 t = hsaReserve(hsa, need);
06344 te = stpcpy(t, "</rpmHeader>\n");
06345 hsa->vallen += (te - t);
06346 }
06347 if (isyaml) {
06348 need = sizeof("\n") - 1;
06349 t = hsaReserve(hsa, need);
06350 te = stpcpy(t, "\n");
06351 hsa->vallen += (te - t);
06352 }
06353
06354 if (hsa->val != NULL && hsa->vallen < hsa->alloced)
06355 hsa->val = xrealloc(hsa->val, hsa->vallen+1);
06356
06357 hsa->ec = rpmecFree(hsa->exts, hsa->ec);
06358 hsa->nec = 0;
06359 hsa->format = freeFormat(hsa->format, hsa->numTokens);
06360
06361 exit:
06362
06363 if (errmsg)
06364 *errmsg = hsa->errmsg;
06365
06366 (void)headerFree(hsa->h);
06367 hsa->h = NULL;
06368 hsa->fmt = _free(hsa->fmt);
06369
06370 return hsa->val;
06371
06372 }