00001
00005 #include "system.h"
00006
00007 #include "rpmio_internal.h"
00008 #include <rpmlib.h>
00009 #include <rpmmacro.h>
00010 #include <rpmuuid.h>
00011
00012 #define _RPMEVR_INTERNAL
00013 #include <rpmds.h>
00014 #include <rpmfi.h>
00015
00016 #include "legacy.h"
00017 #include "argv.h"
00018 #include "ugid.h"
00019 #include "misc.h"
00020 #include "fs.h"
00021
00022 #include "debug.h"
00023
00024
00025
00026
00027
00028 static char * rpmPermsString(int mode)
00029
00030 {
00031 char *perms = xstrdup("----------");
00032
00033 if (S_ISREG(mode))
00034 perms[0] = '-';
00035 else if (S_ISDIR(mode))
00036 perms[0] = 'd';
00037 else if (S_ISLNK(mode))
00038 perms[0] = 'l';
00039 else if (S_ISFIFO(mode))
00040 perms[0] = 'p';
00041
00042 else if (S_ISSOCK(mode))
00043 perms[0] = 's';
00044
00045 else if (S_ISCHR(mode))
00046 perms[0] = 'c';
00047 else if (S_ISBLK(mode))
00048 perms[0] = 'b';
00049 else
00050 perms[0] = '?';
00051
00052 if (mode & S_IRUSR) perms[1] = 'r';
00053 if (mode & S_IWUSR) perms[2] = 'w';
00054 if (mode & S_IXUSR) perms[3] = 'x';
00055
00056 if (mode & S_IRGRP) perms[4] = 'r';
00057 if (mode & S_IWGRP) perms[5] = 'w';
00058 if (mode & S_IXGRP) perms[6] = 'x';
00059
00060 if (mode & S_IROTH) perms[7] = 'r';
00061 if (mode & S_IWOTH) perms[8] = 'w';
00062 if (mode & S_IXOTH) perms[9] = 'x';
00063
00064 if (mode & S_ISUID)
00065 perms[3] = ((mode & S_IXUSR) ? 's' : 'S');
00066
00067 if (mode & S_ISGID)
00068 perms[6] = ((mode & S_IXGRP) ? 's' : 'S');
00069
00070 if (mode & S_ISVTX)
00071 perms[9] = ((mode & S_IXOTH) ? 't' : 'T');
00072
00073 return perms;
00074 }
00075
00082 static char * triggertypeFormat(HE_t he, const char ** av)
00083 {
00084 rpmTagData data = { .ptr = he->p.ptr };
00085 int ix = (he->ix > 0 ? he->ix : 0);
00086 char * val;
00087
00088 assert(ix == 0);
00089 if (he->t != RPM_INT64_TYPE)
00090 val = xstrdup(_("(invalid type)"));
00091 else {
00092 int anint = data.i64p[ix];
00093 if (anint & RPMSENSE_TRIGGERPREIN)
00094 val = xstrdup("prein");
00095 else if (anint & RPMSENSE_TRIGGERIN)
00096 val = xstrdup("in");
00097 else if (anint & RPMSENSE_TRIGGERUN)
00098 val = xstrdup("un");
00099 else if (anint & RPMSENSE_TRIGGERPOSTUN)
00100 val = xstrdup("postun");
00101 else
00102 val = xstrdup("");
00103 }
00104 return val;
00105 }
00106
00113 static char * permsFormat(HE_t he, const char ** av)
00114 {
00115 int ix = (he->ix > 0 ? he->ix : 0);
00116 char * val;
00117
00118 assert(ix == 0);
00119 if (he->t != RPM_INT64_TYPE) {
00120 val = xstrdup(_("(invalid type)"));
00121 } else {
00122 int_32 anint = he->p.i64p[0];
00123 val = rpmPermsString(anint);
00124 }
00125
00126 return val;
00127 }
00128
00135 static char * fflagsFormat(HE_t he, const char ** av)
00136 {
00137 rpmTagData data = { .ptr = he->p.ptr };
00138 int ix = (he->ix >= 0 ? he->ix : 0);
00139 char * val;
00140
00141 assert(ix == 0);
00142 if (he->t != RPM_INT64_TYPE) {
00143 val = xstrdup(_("(invalid type)"));
00144 } else {
00145 char buf[15];
00146 unsigned anint = data.i64p[ix];
00147 buf[0] = '\0';
00148 if (anint & RPMFILE_DOC)
00149 strcat(buf, "d");
00150 if (anint & RPMFILE_CONFIG)
00151 strcat(buf, "c");
00152 if (anint & RPMFILE_SPECFILE)
00153 strcat(buf, "s");
00154 if (anint & RPMFILE_MISSINGOK)
00155 strcat(buf, "m");
00156 if (anint & RPMFILE_NOREPLACE)
00157 strcat(buf, "n");
00158 if (anint & RPMFILE_GHOST)
00159 strcat(buf, "g");
00160 if (anint & RPMFILE_LICENSE)
00161 strcat(buf, "l");
00162 if (anint & RPMFILE_README)
00163 strcat(buf, "r");
00164 val = xstrdup(buf);
00165 }
00166
00167 return val;
00168 }
00169
00177 static char * armorFormat(HE_t he, const char ** av)
00178
00179 {
00180 rpmTagData data = { .ptr = he->p.ptr };
00181 int ix = (he->ix > 0 ? he->ix : 0);
00182 const char * enc;
00183 const unsigned char * s;
00184 size_t ns;
00185 int atype;
00186 char * val;
00187
00188 assert(ix == 0);
00189 switch (he->t) {
00190 case RPM_OPENPGP_TYPE:
00191 case RPM_ASN1_TYPE:
00192 case RPM_BIN_TYPE:
00193 s = data.ui8p;
00194 ns = he->c;
00195 atype = PGPARMOR_SIGNATURE;
00196 break;
00197 case RPM_STRING_TYPE:
00198 case RPM_STRING_ARRAY_TYPE:
00199 enc = data.str;
00200 s = NULL;
00201 ns = 0;
00202
00203 if (b64decode(enc, (void **)&s, &ns))
00204 return xstrdup(_("(not base64)"));
00205
00206 atype = PGPARMOR_PUBKEY;
00207 break;
00208 case RPM_NULL_TYPE:
00209 case RPM_CHAR_TYPE:
00210 case RPM_INT8_TYPE:
00211 case RPM_INT16_TYPE:
00212 case RPM_INT32_TYPE:
00213 case RPM_INT64_TYPE:
00214 case RPM_I18NSTRING_TYPE:
00215 default:
00216 return xstrdup(_("(invalid type)"));
00217 break;
00218 }
00219
00220 val = pgpArmorWrap(atype, s, ns);
00221 if (atype == PGPARMOR_PUBKEY)
00222 s = _free(s);
00223 return val;
00224 }
00225
00233 static char * base64Format(HE_t he, const char ** av)
00234
00235 {
00236 rpmTagData data = { .ptr = he->p.ptr };
00237 int ix = (he->ix > 0 ? he->ix : 0);
00238 char * val;
00239
00240 assert(ix == 0);
00241 if (!(he->t == RPM_BIN_TYPE || he->t == RPM_ASN1_TYPE || he->t == RPM_OPENPGP_TYPE)) {
00242 val = xstrdup(_("(not a blob)"));
00243 } else {
00244 const char * enc;
00245 char * t;
00246 int lc;
00247 size_t ns = he->c;
00248 size_t nt = ((ns + 2) / 3) * 4;
00249
00250
00251
00252 if (b64encode_chars_per_line > 0 && b64encode_eolstr != NULL) {
00253 lc = (nt + b64encode_chars_per_line - 1) / b64encode_chars_per_line;
00254 if (((nt + b64encode_chars_per_line - 1) % b64encode_chars_per_line) != 0)
00255 ++lc;
00256 nt += lc * strlen(b64encode_eolstr);
00257 }
00258
00259
00260 val = t = xcalloc(1, nt + 1);
00261 *t = '\0';
00262
00263
00264 { unsigned char * _data = xcalloc(1, ns+1);
00265 memcpy(_data, data.ptr, ns);
00266
00267 if ((enc = b64encode(_data, ns)) != NULL) {
00268 t = stpcpy(t, enc);
00269 enc = _free(enc);
00270 }
00271
00272 _data = _free(_data);
00273 }
00274 }
00275
00276
00277 return val;
00278
00279 }
00280
00286 static size_t xmlstrlen(const char * s)
00287
00288 {
00289 size_t len = 0;
00290 int c;
00291
00292 while ((c = *s++) != '\0')
00293 {
00294 switch (c) {
00295 case '<':
00296 case '>': len += sizeof("<") - 1; break;
00297 case '&': len += sizeof("&") - 1; break;
00298 default: len += 1; break;
00299 }
00300 }
00301 return len;
00302 }
00303
00310 static char * xmlstrcpy( char * t, const char * s)
00311
00312 {
00313 char * te = t;
00314 int c;
00315
00316 while ((c = *s++) != '\0') {
00317 switch (c) {
00318 case '<': te = stpcpy(te, "<"); break;
00319 case '>': te = stpcpy(te, ">"); break;
00320 case '&': te = stpcpy(te, "&"); break;
00321 default: *te++ = c; break;
00322 }
00323 }
00324 *te = '\0';
00325 return t;
00326 }
00327
00328 static char *
00329 strdup_locale_convert ( const char * buffer,
00330 const char * tocode)
00331
00332 {
00333 char *dest_str;
00334 #if defined(HAVE_ICONV)
00335 char *fromcode = NULL;
00336 iconv_t fd;
00337
00338 if (buffer == NULL)
00339 return NULL;
00340
00341 if (tocode == NULL)
00342 tocode = "UTF-8";
00343
00344 #ifdef HAVE_LANGINFO_H
00345
00346 fromcode = nl_langinfo (CODESET);
00347
00348 #endif
00349
00350 if (fromcode != NULL && strcmp(tocode, fromcode) != 0
00351 && (fd = iconv_open(tocode, fromcode)) != (iconv_t)-1)
00352 {
00353 const char *pin = buffer;
00354 char *pout = NULL;
00355 size_t ib, ob, dest_size;
00356 int done;
00357 int is_error;
00358 size_t err;
00359 const char *shift_pin = NULL;
00360 int xx;
00361
00362 err = iconv(fd, NULL, &ib, &pout, &ob);
00363 dest_size = ob = ib = strlen(buffer);
00364 dest_str = pout = malloc((dest_size + 1) * sizeof(*dest_str));
00365 if (dest_str)
00366 *dest_str = '\0';
00367 done = is_error = 0;
00368 if (pout != NULL)
00369 while (done == 0 && is_error == 0) {
00370 err = iconv(fd, (char **)&pin, &ib, &pout, &ob);
00371
00372 if (err == (size_t)-1) {
00373 switch (errno) {
00374 case EINVAL:
00375 done = 1;
00376 break;
00377 case E2BIG:
00378 { size_t used = (size_t)(pout - dest_str);
00379 dest_size *= 2;
00380 dest_str = realloc(dest_str, (dest_size + 1) * sizeof(*dest_str));
00381 if (dest_str == NULL) {
00382 is_error = 1;
00383 continue;
00384 }
00385 pout = dest_str + used;
00386 ob = dest_size - used;
00387 } break;
00388 case EILSEQ:
00389 is_error = 1;
00390 break;
00391 default:
00392 is_error = 1;
00393 break;
00394 }
00395 } else {
00396 if (shift_pin == NULL) {
00397 shift_pin = pin;
00398 pin = NULL;
00399 ib = 0;
00400 } else {
00401 done = 1;
00402 }
00403 }
00404 }
00405 xx = iconv_close(fd);
00406 if (pout)
00407 *pout = '\0';
00408 if (dest_str != NULL)
00409 dest_str = xstrdup(dest_str);
00410 } else
00411 #endif
00412 {
00413 dest_str = xstrdup((buffer ? buffer : ""));
00414 }
00415
00416 return dest_str;
00417 }
00418
00425 static char * cdataFormat(HE_t he, const char ** av)
00426
00427 {
00428 int ix = (he->ix > 0 ? he->ix : 0);
00429 char * val;
00430
00431 assert(ix == 0);
00432 if (he->t != RPM_STRING_TYPE) {
00433 val = xstrdup(_("(not a string)"));
00434 } else {
00435 const char * s = strdup_locale_convert(he->p.str, (av ? av[0] : NULL));
00436 size_t nb = xmlstrlen(s);
00437 char * t;
00438
00439 val = t = xcalloc(1, nb + 1);
00440 t = xmlstrcpy(t, s); t += strlen(t);
00441 *t = '\0';
00442 s = _free(s);
00443 }
00444
00445
00446 return val;
00447
00448 }
00449
00456 static char * iconvFormat(HE_t he, const char ** av)
00457
00458 {
00459 int ix = (he->ix > 0 ? he->ix : 0);
00460 char * val;
00461
00462 assert(ix == 0);
00463 if (he->t != RPM_STRING_TYPE) {
00464 val = xstrdup(_("(not a string)"));
00465 } else {
00466 val = strdup_locale_convert(he->p.str, (av ? av[0] : NULL));
00467 }
00468
00469
00470 return val;
00471
00472 }
00473
00480 static char * xmlFormat(HE_t he, const char ** av)
00481
00482 {
00483 rpmTagData data = { .ptr = he->p.ptr };
00484 int ix = (he->ix > 0 ? he->ix : 0);
00485 const char * xtag = NULL;
00486 size_t nb;
00487 char * val;
00488 const char * s = NULL;
00489 char * t, * te;
00490 unsigned long long anint = 0;
00491 int freeit = 0;
00492 int xx;
00493
00494 assert(ix == 0);
00495 assert(he->t == RPM_STRING_TYPE || he->t == RPM_INT64_TYPE || he->t == RPM_BIN_TYPE);
00496 switch (he->t) {
00497 case RPM_STRING_ARRAY_TYPE:
00498 s = data.argv[ix];
00499 xtag = "string";
00500
00501 s = xstrdup(s);
00502 s = xstrtolocale(s);
00503 freeit = 1;
00504 break;
00505 case RPM_I18NSTRING_TYPE:
00506 case RPM_STRING_TYPE:
00507 s = data.str;
00508 xtag = "string";
00509
00510 s = xstrdup(s);
00511 s = xstrtolocale(s);
00512 freeit = 1;
00513 break;
00514 case RPM_OPENPGP_TYPE:
00515 case RPM_ASN1_TYPE:
00516 case RPM_BIN_TYPE:
00517
00518 { int cpl = b64encode_chars_per_line;
00519 b64encode_chars_per_line = 0;
00520
00521 s = base64Format(he, NULL);
00522
00523 b64encode_chars_per_line = cpl;
00524 xtag = "base64";
00525 freeit = 1;
00526 } break;
00527
00528 case RPM_CHAR_TYPE:
00529 case RPM_INT8_TYPE:
00530 anint = data.i8p[ix];
00531 break;
00532 case RPM_INT16_TYPE:
00533 anint = data.ui16p[ix];
00534 break;
00535 case RPM_INT32_TYPE:
00536 anint = data.i32p[ix];
00537 break;
00538 case RPM_INT64_TYPE:
00539 anint = data.i64p[ix];
00540 break;
00541 case RPM_NULL_TYPE:
00542 default:
00543 return xstrdup(_("(invalid xml type)"));
00544 break;
00545 }
00546
00547 if (s == NULL) {
00548 int tlen = 64;
00549 t = memset(alloca(tlen+1), 0, tlen+1);
00550
00551 if (anint != 0)
00552 xx = snprintf(t, tlen, "%llu", anint);
00553
00554 s = t;
00555 xtag = "integer";
00556 }
00557
00558 nb = xmlstrlen(s);
00559 if (nb == 0) {
00560 nb += strlen(xtag) + sizeof("\t</>");
00561 te = t = alloca(nb);
00562 te = stpcpy( stpcpy( stpcpy(te, "\t<"), xtag), "/>");
00563 } else {
00564 nb += 2 * strlen(xtag) + sizeof("\t<></>");
00565 te = t = alloca(nb);
00566 te = stpcpy( stpcpy( stpcpy(te, "\t<"), xtag), ">");
00567 te = xmlstrcpy(te, s);
00568 te += strlen(te);
00569 te = stpcpy( stpcpy( stpcpy(te, "</"), xtag), ">");
00570 }
00571
00572 if (freeit)
00573 s = _free(s);
00574
00575 val = xstrdup(t);
00576
00577 return val;
00578 }
00579
00586 static size_t yamlstrlen(const char * s, int lvl)
00587
00588 {
00589 size_t len = 0;
00590 int indent = (lvl > 0);
00591 int c;
00592
00593 while ((c = (int) *s++) != (int) '\0')
00594 {
00595 if (indent) {
00596 len += 2 * lvl;
00597 indent = 0;
00598 }
00599 if (c == (int) '\n')
00600 indent = (lvl > 0);
00601 len++;
00602 }
00603 return len;
00604 }
00605
00613 static char * yamlstrcpy( char * t, const char * s, int lvl)
00614
00615 {
00616 char * te = t;
00617 int indent = (lvl > 0);
00618 int c;
00619
00620 while ((c = (int) *s++) != (int) '\0') {
00621 if (indent) {
00622 int i;
00623 for (i = 0; i < lvl; i++) {
00624 *te++ = ' ';
00625 *te++ = ' ';
00626 }
00627 indent = 0;
00628 }
00629 if (c == (int) '\n')
00630 indent = (lvl > 0);
00631 *te++ = (char) c;
00632 }
00633 *te = '\0';
00634 return t;
00635 }
00636
00643 static char * yamlFormat(HE_t he, const char ** av)
00644
00645 {
00646 int element = he->ix;
00647 int ix = (he->ix > 0 ? he->ix : 0);
00648 const char * xtag = NULL;
00649 size_t nb;
00650 char * val;
00651 const char * s = NULL;
00652 char * t, * te;
00653 unsigned long long anint = 0;
00654 int freeit = 0;
00655 int lvl = 0;
00656 int xx;
00657 int c;
00658
00659 assert(ix == 0);
00660 assert(he->t == RPM_STRING_TYPE || he->t == RPM_UINT64_TYPE || he->t == RPM_BIN_TYPE);
00661 xx = 0;
00662 switch (he->t) {
00663 case RPM_STRING_ARRAY_TYPE:
00664 case RPM_I18NSTRING_TYPE:
00665 case RPM_STRING_TYPE:
00666 s = (he->t == RPM_STRING_ARRAY_TYPE ? he->p.argv[ix] : he->p.str);
00667 if (strchr("[", s[0]))
00668 xx = 1;
00669 if (xx == 0)
00670 while ((c = (int) *s++) != (int) '\0') {
00671 switch (c) {
00672 default:
00673 continue;
00674 case '\n':
00675 xx = 1;
00676 break;
00677 case '-':
00678 case ':':
00679 if (s[0] != ' ' && s[0] != '\0' && s[1] != '"')
00680 continue;
00681 xx = 1;
00682 break;
00683 }
00684 break;
00685 }
00686 if (xx) {
00687 if (element >= 0) {
00688 xtag = "- |-\n";
00689 lvl = 3;
00690 } else {
00691 xtag = "|-\n";
00692 lvl = 2;
00693 if (he->ix < 0) lvl++;
00694 }
00695 } else {
00696 xtag = (element >= 0 ? "- " : NULL);
00697 }
00698
00699
00700 s = xstrdup(he->p.str);
00701 s = xstrtolocale(s);
00702 freeit = 1;
00703 break;
00704 case RPM_OPENPGP_TYPE:
00705 case RPM_ASN1_TYPE:
00706 case RPM_BIN_TYPE:
00707
00708 { int cpl = b64encode_chars_per_line;
00709 b64encode_chars_per_line = 0;
00710
00711 s = base64Format(he, NULL);
00712 element = -element;
00713
00714 b64encode_chars_per_line = cpl;
00715 xtag = "!!binary ";
00716 freeit = 1;
00717 } break;
00718
00719 case RPM_CHAR_TYPE:
00720 case RPM_UINT8_TYPE:
00721 anint = he->p.ui8p[ix];
00722 break;
00723 case RPM_UINT16_TYPE:
00724 anint = he->p.ui16p[ix];
00725 break;
00726 case RPM_UINT32_TYPE:
00727 anint = he->p.ui32p[ix];
00728 break;
00729 case RPM_UINT64_TYPE:
00730 anint = he->p.ui64p[ix];
00731 break;
00732 case RPM_NULL_TYPE:
00733 default:
00734 return xstrdup(_("(invalid yaml type)"));
00735 break;
00736 }
00737
00738 if (s == NULL) {
00739 int tlen = 64;
00740 t = memset(alloca(tlen+1), 0, tlen+1);
00741
00742 xx = snprintf(t, tlen, "%llu", (unsigned long long)anint);
00743
00744 s = t;
00745 xtag = (element >= 0 ? "- " : NULL);
00746 }
00747
00748 nb = yamlstrlen(s, lvl);
00749 if (nb == 0) {
00750 if (element >= 0)
00751 nb += sizeof(" ") - 1;
00752 nb += sizeof("- ~") - 1;
00753 nb++;
00754 te = t = alloca(nb);
00755 if (element >= 0)
00756 te = stpcpy(te, " ");
00757 te = stpcpy(te, "- ~");
00758 } else {
00759 if (element >= 0)
00760 nb += sizeof(" ") - 1;
00761 if (xtag)
00762 nb += strlen(xtag);
00763 nb++;
00764 te = t = alloca(nb);
00765 if (element >= 0)
00766 te = stpcpy(te, " ");
00767 if (xtag)
00768 te = stpcpy(te, xtag);
00769 te = yamlstrcpy(te, s, lvl);
00770 te += strlen(te);
00771 }
00772
00773
00774 if (freeit)
00775 s = _free(s);
00776
00777 val = xstrdup(t);
00778
00779 return val;
00780 }
00781
00788 static char * pgpsigFormat(HE_t he, const char ** av)
00789
00790
00791 {
00792 rpmTagData data = { .ptr = he->p.ptr };
00793 int ix = (he->ix > 0 ? he->ix : 0);
00794 char * val, * t;
00795
00796 assert(ix == 0);
00797 if (!(he->t == RPM_BIN_TYPE || he->t == RPM_ASN1_TYPE || he->t == RPM_OPENPGP_TYPE)) {
00798 val = xstrdup(_("(not a blob)"));
00799 } else {
00800 unsigned char * pkt = (byte *) data.ptr;
00801 unsigned int pktlen = 0;
00802 unsigned int v = *pkt;
00803 pgpTag tag = 0;
00804 unsigned int plen;
00805 unsigned int hlen = 0;
00806
00807 if (v & 0x80) {
00808 if (v & 0x40) {
00809 tag = (v & 0x3f);
00810 plen = pgpLen(pkt+1, &hlen);
00811 } else {
00812 tag = (v >> 2) & 0xf;
00813 plen = (1 << (v & 0x3));
00814 hlen = pgpGrab(pkt+1, plen);
00815 }
00816
00817 pktlen = 1 + plen + hlen;
00818 }
00819
00820 if (pktlen == 0 || tag != PGPTAG_SIGNATURE) {
00821 val = xstrdup(_("(not an OpenPGP signature)"));
00822 } else {
00823 pgpDig dig = pgpNewDig();
00824 pgpDigParams sigp = &dig->signature;
00825 size_t nb = 0;
00826 const char *tempstr;
00827
00828 (void) pgpPrtPkts(pkt, pktlen, dig, 0);
00829
00830 val = NULL;
00831 again:
00832 nb += 100;
00833 val = t = xrealloc(val, nb + 1);
00834
00835 switch (sigp->pubkey_algo) {
00836 case PGPPUBKEYALGO_DSA:
00837 t = stpcpy(t, "DSA");
00838 break;
00839 case PGPPUBKEYALGO_RSA:
00840 t = stpcpy(t, "RSA");
00841 break;
00842 default:
00843 (void) snprintf(t, nb - (t - val), "%d", sigp->pubkey_algo);
00844 t += strlen(t);
00845 break;
00846 }
00847 if (t + 5 >= val + nb)
00848 goto again;
00849 *t++ = '/';
00850 switch (sigp->hash_algo) {
00851 case PGPHASHALGO_MD5:
00852 t = stpcpy(t, "MD5");
00853 break;
00854 case PGPHASHALGO_SHA1:
00855 t = stpcpy(t, "SHA1");
00856 break;
00857 default:
00858 (void) snprintf(t, nb - (t - val), "%d", sigp->hash_algo);
00859 t += strlen(t);
00860 break;
00861 }
00862 if (t + strlen (", ") + 1 >= val + nb)
00863 goto again;
00864
00865 t = stpcpy(t, ", ");
00866
00867
00868 { time_t dateint = pgpGrab(sigp->time, sizeof(sigp->time));
00869 struct tm * tstruct = localtime(&dateint);
00870 if (tstruct)
00871 (void) strftime(t, (nb - (t - val)), "%c", tstruct);
00872 }
00873 t += strlen(t);
00874 if (t + strlen (", Key ID ") + 1 >= val + nb)
00875 goto again;
00876 t = stpcpy(t, ", Key ID ");
00877 tempstr = pgpHexStr(sigp->signid, sizeof(sigp->signid));
00878 if (t + strlen (tempstr) > val + nb)
00879 goto again;
00880 t = stpcpy(t, tempstr);
00881
00882 dig = pgpFreeDig(dig);
00883 }
00884 }
00885
00886 return val;
00887 }
00888
00895 static char * depflagsFormat(HE_t he, const char ** av)
00896
00897 {
00898 rpmTagData data = { .ptr = he->p.ptr };
00899 int ix = (he->ix > 0 ? he->ix : 0);;
00900 char * val;
00901
00902 assert(ix == 0);
00903 if (he->t != RPM_INT64_TYPE) {
00904 val = xstrdup(_("(invalid type)"));
00905 } else {
00906 int anint = data.i64p[ix];
00907 char *t, *buf;
00908
00909 t = buf = alloca(32);
00910 *t = '\0';
00911
00912 #ifdef NOTYET
00913 if (anint & RPMSENSE_SCRIPT_PRE)
00914 t = stpcpy(t, "(pre)");
00915 else if (anint & RPMSENSE_SCRIPT_POST)
00916 t = stpcpy(t, "(post)");
00917 else if (anint & RPMSENSE_SCRIPT_PREUN)
00918 t = stpcpy(t, "(preun)");
00919 else if (anint & RPMSENSE_SCRIPT_POSTUN)
00920 t = stpcpy(t, "(postun)");
00921 #endif
00922 if (anint & RPMSENSE_SENSEMASK)
00923 *t++ = ' ';
00924 if (anint & RPMSENSE_LESS)
00925 *t++ = '<';
00926 if (anint & RPMSENSE_GREATER)
00927 *t++ = '>';
00928 if (anint & RPMSENSE_EQUAL)
00929 *t++ = '=';
00930 if (anint & RPMSENSE_SENSEMASK)
00931 *t++ = ' ';
00932 *t = '\0';
00933
00934 val = xstrdup(buf);
00935 }
00936
00937 return val;
00938 }
00939
00946 static int instprefixTag(Header h, HE_t he)
00947
00948 {
00949 rpmTagType ipt;
00950 rpmTagData array;
00951
00952 he->tag = RPMTAG_INSTALLPREFIX;
00953 if (headerGetEntry(h, RPMTAG_INSTALLPREFIX, (hTYP_t)&he->t, &he->p, &he->c)) {
00954 he->freeData = 0;
00955 return 0;
00956 }
00957 he->tag = RPMTAG_INSTPREFIXES;
00958 if (headerGetEntry(h, he->tag, (hTYP_t)&ipt, &array, &he->c)) {
00959 he->t = RPM_STRING_TYPE;
00960 he->c = 1;
00961 he->p.str = xstrdup(array.argv[0]);
00962 he->freeData = 1;
00963 array.ptr = headerFreeData(array.ptr, ipt);
00964 return 0;
00965 }
00966 return 1;
00967 }
00968
00976 static int tv2uuidv1(Header h, HE_t he, struct timeval *tv)
00977
00978 {
00979 uint64_t uuid_time = ((uint64_t)tv->tv_sec * 10000000) +
00980 (tv->tv_usec * 10) + 0x01B21DD213814000ULL;
00981
00982 he->t = RPM_BIN_TYPE;
00983 he->c = 128/8;
00984 he->p.ptr = xcalloc(1, he->c);
00985 he->freeData = 1;
00986 if (rpmuuidMake(1, NULL, NULL, NULL, (unsigned char *)he->p.ui8p)) {
00987 he->p.ptr = _free(he->p.ptr);
00988 he->freeData = 0;
00989 return 1;
00990 }
00991
00992 he->p.ui8p[6] &= 0xf0;
00993 he->p.ui8p[8] &= 0x3f;
00994 he->p.ui8p[9] &= 0x00;
00995
00996 he->p.ui8p[3] = (uuid_time >> 0);
00997 he->p.ui8p[2] = (uuid_time >> 8);
00998 he->p.ui8p[1] = (uuid_time >> 16);
00999 he->p.ui8p[0] = (uuid_time >> 24);
01000 he->p.ui8p[5] = (uuid_time >> 32);
01001 he->p.ui8p[4] = (uuid_time >> 40);
01002 he->p.ui8p[6] |= (uuid_time >> 56) & 0x0f;
01003
01004 #ifdef NOTYET
01005
01006 he->p.ui8p[8] |= (he->p.ui8p[2] & 0x3f);
01007 he->p.ui8p[9] |= he->p.ui8p[3]
01008 #endif
01009
01010 return 0;
01011 }
01012
01019 static int tag2uuidv1(Header h, HE_t he)
01020
01021 {
01022 struct timeval tv;
01023
01024 if (!headerGetEntry(h, he->tag, (hTYP_t)&he->t, &he->p, &he->c))
01025 return 1;
01026 tv.tv_sec = he->p.ui32p[0];
01027 tv.tv_usec = (he->c > 1 ? he->p.ui32p[1] : 0);
01028 he->p.ptr = headerFreeData(he->p.ptr, he->t);
01029 return tv2uuidv1(h, he, &tv);
01030 }
01031
01038 static int installtime_uuidTag(Header h, HE_t he)
01039
01040 {
01041 he->tag = RPMTAG_INSTALLTIME;
01042 return tag2uuidv1(h, he);
01043 }
01044
01051 static int buildtime_uuidTag(Header h, HE_t he)
01052
01053 {
01054 he->tag = RPMTAG_BUILDTIME;
01055 return tag2uuidv1(h, he);
01056 }
01057
01064 static int origintime_uuidTag(Header h, HE_t he)
01065
01066 {
01067 he->tag = RPMTAG_ORIGINTIME;
01068 return tag2uuidv1(h, he);
01069 }
01070
01077 static int installtid_uuidTag(Header h, HE_t he)
01078
01079 {
01080 he->tag = RPMTAG_INSTALLTID;
01081 return tag2uuidv1(h, he);
01082 }
01083
01090 static int removetid_uuidTag(Header h, HE_t he)
01091
01092 {
01093 he->tag = RPMTAG_REMOVETID;
01094 return tag2uuidv1(h, he);
01095 }
01096
01103 static int origintid_uuidTag(Header h, HE_t he)
01104
01105 {
01106 he->tag = RPMTAG_ORIGINTID;
01107 return tag2uuidv1(h, he);
01108 }
01109
01110
01111 static const char uuid_ns[] = "ns:URL";
01112
01113 static const char uuid_auth[] = "%{?_uuid_auth}%{!?_uuid_auth:http://rpm5.org}";
01114
01115 static const char uuid_path[] = "%{?_uuid_path}%{!?_uuid_path:/package}";
01116
01117 static int uuid_version = 5;
01118
01127 static int str2uuid(HE_t he, const char ** av,
01128 int version, char * val)
01129
01130 {
01131 const char * ns = NULL;
01132 const char * tagn = tagName(he->tag);
01133 const char * s = NULL;
01134 int rc;
01135
01136
01137 if (!strcmp("Sigmd5", tagn))
01138 tagn = "Pkgid";
01139 else if (!strcmp("Sha1header", tagn))
01140 tagn = "Hdrid";
01141
01142 switch (version) {
01143 default:
01144 version = uuid_version;
01145
01146 case 3:
01147 case 5:
01148 assert(he->t == RPM_STRING_TYPE);
01149 ns = uuid_ns;
01150 s = rpmGetPath(uuid_auth, "/", uuid_path, "/", tagn, "/",
01151 he->p.str, NULL);
01152
01153 case 4:
01154 break;
01155 }
01156 he->p.ptr = headerFreeData(he->p.ptr, he->t);
01157 he->t = RPM_BIN_TYPE;
01158 he->c = 128/8;
01159 he->p.ptr = xcalloc(1, he->c);
01160 he->freeData = 1;
01161 rc = rpmuuidMake(version, ns, s, val, (unsigned char *)he->p.ui8p);
01162 if (rc) {
01163 he->p.ptr = _free(he->p.ptr);
01164 he->freeData = 0;
01165 }
01166 s = _free(s);
01167 return rc;
01168 }
01169
01176 static int tag2uuidv5(Header h, HE_t he)
01177
01178 {
01179 if (!headerGetEntry(h, he->tag, (hTYP_t)&he->t, &he->p, &he->c))
01180 return 1;
01181 switch (he->t) {
01182 default:
01183 assert(0);
01184 break;
01185 case RPM_BIN_TYPE: {
01186 static const char hex[] = "0123456789abcdef";
01187 char * t;
01188 char * te;
01189 uint32_t i;
01190
01191 t = te = xmalloc (2*he->c + 1);
01192 for (i = 0; i < he->c; i++) {
01193 *te++ = hex[ ((he->p.ui8p[i] >> 4) & 0x0f) ];
01194 *te++ = hex[ ((he->p.ui8p[i] ) & 0x0f) ];
01195 }
01196 *te = '\0';
01197 he->p.ptr = headerFreeData(he->p.ptr, he->t);
01198 he->t = RPM_STRING_TYPE;
01199 he->p.ptr = t;
01200 he->c = 1;
01201 he->freeData = 1;
01202 } break;
01203 case RPM_STRING_TYPE:
01204 break;
01205 }
01206 return str2uuid(he, NULL, 0, NULL);
01207 }
01208
01215 static int pkguuidTag(Header h, HE_t he)
01216
01217 {
01218 he->tag = RPMTAG_PKGID;
01219 return tag2uuidv5(h, he);
01220 }
01221
01228 static int sourcepkguuidTag(Header h, HE_t he)
01229
01230 {
01231 he->tag = RPMTAG_SOURCEPKGID;
01232 return tag2uuidv5(h, he);
01233 }
01234
01241 static int hdruuidTag(Header h, HE_t he)
01242
01243 {
01244 he->tag = RPMTAG_HDRID;
01245 return tag2uuidv5(h, he);
01246 }
01247
01254 static int triggercondsTag(Header h, HE_t he)
01255
01256 {
01257 HE_t _he = memset(alloca(sizeof(*_he)), 0, sizeof(*_he));
01258 rpmTagData flags;
01259 rpmTagData indices;
01260 rpmTagData names;
01261 rpmTagData versions;
01262 int numNames, numScripts;
01263 const char ** conds;
01264 rpmTagData s;
01265 char * item, * flagsStr;
01266 char * chptr;
01267 int i, j, xx;
01268
01269 he->freeData = 0;
01270 xx = headerGetEntry(h, RPMTAG_TRIGGERNAME, NULL, &names, &numNames);
01271 if (!xx)
01272 return 0;
01273
01274 _he->tag = he->tag;
01275 _he->t = RPM_INT32_TYPE;
01276 _he->p.i32p = NULL;
01277 _he->c = 1;
01278 _he->freeData = -1;
01279
01280 xx = headerGetEntry(h, RPMTAG_TRIGGERINDEX, NULL, &indices, NULL);
01281 xx = headerGetEntry(h, RPMTAG_TRIGGERFLAGS, NULL, &flags, NULL);
01282 xx = headerGetEntry(h, RPMTAG_TRIGGERVERSION, NULL, &versions, NULL);
01283 xx = headerGetEntry(h, RPMTAG_TRIGGERSCRIPTS, NULL, &s, &numScripts);
01284
01285 he->t = RPM_STRING_ARRAY_TYPE;
01286 he->c = numScripts;
01287
01288 he->freeData = 1;
01289 he->p.argv = conds = xmalloc(sizeof(*conds) * numScripts);
01290 for (i = 0; i < numScripts; i++) {
01291 chptr = xstrdup("");
01292
01293 for (j = 0; j < numNames; j++) {
01294 if (indices.i32p[j] != i)
01295 continue;
01296
01297 item = xmalloc(strlen(names.argv[j]) + strlen(versions.argv[j]) + 20);
01298 if (flags.i32p[j] & RPMSENSE_SENSEMASK) {
01299 _he->p.i32p = &flags.i32p[j];
01300 flagsStr = depflagsFormat(_he, NULL);
01301 sprintf(item, "%s %s %s", names.argv[j], flagsStr, versions.argv[j]);
01302 flagsStr = _free(flagsStr);
01303 } else
01304 strcpy(item, names.argv[j]);
01305
01306 chptr = xrealloc(chptr, strlen(chptr) + strlen(item) + 5);
01307 if (*chptr != '\0') strcat(chptr, ", ");
01308 strcat(chptr, item);
01309 item = _free(item);
01310 }
01311
01312 conds[i] = chptr;
01313 }
01314
01315 names.ptr = headerFreeData(names.ptr, -1);
01316 versions.ptr = headerFreeData(versions.ptr, -1);
01317 s.ptr = headerFreeData(s.ptr, -1);
01318
01319 return 0;
01320 }
01321
01328 static int triggertypeTag(Header h, HE_t he)
01329
01330 {
01331 rpmTagData indices;
01332 rpmTagData flags;
01333 const char ** conds;
01334 rpmTagData s;
01335 int i, j, xx;
01336 int numScripts, numNames;
01337
01338 he->freeData = 0;
01339 if (!headerGetEntry(h, RPMTAG_TRIGGERINDEX, NULL, &indices, &numNames))
01340 return 1;
01341
01342 xx = headerGetEntry(h, RPMTAG_TRIGGERFLAGS, NULL, &flags, NULL);
01343 xx = headerGetEntry(h, RPMTAG_TRIGGERSCRIPTS, NULL, &s, &numScripts);
01344
01345 he->t = RPM_STRING_ARRAY_TYPE;
01346 he->c = numScripts;
01347
01348 he->freeData = 1;
01349 he->p.argv = conds = xmalloc(sizeof(*conds) * numScripts);
01350 for (i = 0; i < numScripts; i++) {
01351 for (j = 0; j < numNames; j++) {
01352 if (indices.i32p[j] != i)
01353 continue;
01354
01355 if (flags.i32p[j] & RPMSENSE_TRIGGERPREIN)
01356 conds[i] = xstrdup("prein");
01357 else if (flags.i32p[j] & RPMSENSE_TRIGGERIN)
01358 conds[i] = xstrdup("in");
01359 else if (flags.i32p[j] & RPMSENSE_TRIGGERUN)
01360 conds[i] = xstrdup("un");
01361 else if (flags.i32p[j] & RPMSENSE_TRIGGERPOSTUN)
01362 conds[i] = xstrdup("postun");
01363 else
01364 conds[i] = xstrdup("");
01365 break;
01366 }
01367 }
01368
01369 s.ptr = headerFreeData(s.ptr, -1);
01370 return 0;
01371 }
01372
01373
01374
01375 #if defined(ENABLE_NLS)
01376
01377
01378 extern int _nl_msg_cat_cntr;
01379
01380 #endif
01381
01382 static const char * language = "LANGUAGE";
01383
01384
01385 static const char * _macro_i18ndomains = "%{?_i18ndomains}";
01386
01393 static int i18nTag(Header h, HE_t he)
01394
01395
01396 {
01397 char * dstring = rpmExpand(_macro_i18ndomains, NULL);
01398 int rc = 1;
01399
01400 he->t = RPM_STRING_TYPE;
01401 he->p.str = NULL;
01402 he->c = 0;
01403 he->freeData = 0;
01404
01405 if (dstring && *dstring) {
01406 char *domain, *de;
01407 const char * langval;
01408 const char * msgkey;
01409 const char * msgid;
01410
01411 { const char * tn = tagName(he->tag);
01412 rpmTagData n = { .ptr = NULL };
01413 char * mk;
01414 size_t nb = sizeof("()");
01415 int xx = headerGetEntry(h, RPMTAG_NAME, NULL, &n, NULL);
01416 xx = 0;
01417 if (tn) nb += strlen(tn);
01418 if (n.str) nb += strlen(n.str);
01419 mk = alloca(nb);
01420 sprintf(mk, "%s(%s)", (n.str ? n.str : ""), (tn ? tn : ""));
01421 msgkey = mk;
01422 }
01423
01424
01425 langval = getenv(language);
01426 (void) setenv(language, "en_US", 1);
01427 #if defined(ENABLE_NLS)
01428 ++_nl_msg_cat_cntr;
01429 #endif
01430
01431 msgid = NULL;
01432 for (domain = dstring; domain != NULL; domain = de) {
01433 de = strchr(domain, ':');
01434 if (de) *de++ = '\0';
01435 msgid = dgettext(domain, msgkey) ;
01436 if (msgid != msgkey) break;
01437 }
01438
01439
01440 if (langval)
01441 (void) setenv(language, langval, 1);
01442 else
01443 unsetenv(language);
01444 #if defined(ENABLE_NLS)
01445 ++_nl_msg_cat_cntr;
01446 #endif
01447
01448 if (domain && msgid) {
01449 const char * s = dgettext(domain, msgid) ;
01450 if (s) {
01451 rc = 0;
01452 he->p.str = xstrdup(s);
01453 he->c = 1;
01454 he->freeData = 1;
01455 }
01456 }
01457 }
01458
01459
01460 dstring = _free(dstring);
01461
01462 if (!rc)
01463 return rc;
01464
01465 rc = headerGetEntry(h, he->tag, (hTYP_t)&he->t, &he->p, &he->c);
01466 if (rc) {
01467 rc = 0;
01468 he->p.str = xstrdup(he->p.str);
01469 he->p.str = xstrtolocale(he->p.str);
01470 he->freeData = 1;
01471
01472 return rc;
01473
01474 }
01475
01476 he->t = RPM_STRING_TYPE;
01477 he->p.str = NULL;
01478 he->c = 0;
01479 he->freeData = 0;
01480
01481 return 1;
01482 }
01483
01487 static int localeTag(Header h, HE_t he)
01488
01489 {
01490 rpmTagType t;
01491 rpmTagData p;
01492 rpmTagCount c;
01493 const char ** argv;
01494 char * te;
01495 int rc;
01496
01497 rc = headerGetEntry(h, he->tag, (hTYP_t)&t, &p, &c);
01498 if (!rc || p.ptr == NULL || c == 0) {
01499 he->t = RPM_STRING_TYPE;
01500 he->p.str = NULL;
01501 he->c = 0;
01502 he->freeData = 0;
01503 return 1;
01504 }
01505
01506 if (t == RPM_STRING_TYPE) {
01507 p.str = xstrdup(p.str);
01508 p.str = xstrtolocale(p.str);
01509 he->freeData = 1;
01510 } else if (t == RPM_STRING_ARRAY_TYPE) {
01511 size_t l = 0;
01512 int i;
01513 for (i = 0; i < c; i++) {
01514 p.argv[i] = xstrdup(p.argv[i]);
01515 p.argv[i] = xstrtolocale(p.argv[i]);
01516 assert(p.argv[i] != NULL);
01517 l += strlen(p.argv[i]) + 1;
01518 }
01519 argv = xmalloc(c * sizeof(*argv) + l);
01520 te = (char *)&argv[c];
01521 for (i = 0; i < c; i++) {
01522 argv[i] = te;
01523 te = stpcpy(te, p.argv[i]);
01524 te++;
01525 p.argv[i] = _free(p.argv[i]);
01526 }
01527 p.ptr = _free(p.ptr);
01528 p.argv = argv;
01529 he->freeData = 1;
01530 } else
01531 he->freeData = 0;
01532
01533 he->t = t;
01534 he->p.ptr = p.ptr;
01535 he->c = c;
01536 return 0;
01537 }
01538
01545 static int summaryTag(Header h, HE_t he)
01546
01547
01548 {
01549 he->tag = RPMTAG_SUMMARY;
01550 return i18nTag(h, he);
01551 }
01552
01559 static int descriptionTag(Header h, HE_t he)
01560
01561
01562 {
01563 he->tag = RPMTAG_DESCRIPTION;
01564 return i18nTag(h, he);
01565 }
01566
01567 static int changelognameTag(Header h, HE_t he)
01568
01569 {
01570 he->tag = RPMTAG_CHANGELOGNAME;
01571 return localeTag(h, he);
01572 }
01573
01574 static int changelogtextTag(Header h, HE_t he)
01575
01576 {
01577 he->tag = RPMTAG_CHANGELOGTEXT;
01578 return localeTag(h, he);
01579 }
01580
01587 static int groupTag(Header h, HE_t he)
01588
01589
01590 {
01591 he->tag = RPMTAG_GROUP;
01592 return i18nTag(h, he);
01593 }
01594
01601
01602 static int dbinstanceTag(Header h, HE_t he)
01603
01604
01605
01606
01607 {
01608 he->tag = RPMTAG_DBINSTANCE;
01609 he->t = RPM_INT32_TYPE;
01610 he->p.i32p = xmalloc(sizeof(*he->p.i32p));
01611 he->p.i32p[0] = headerGetInstance(h);
01612 he->freeData = 1;
01613 he->c = 1;
01614 return 0;
01615 }
01616
01617
01624
01625 static int headerstartoffTag(Header h, HE_t he)
01626
01627
01628
01629
01630 {
01631 he->tag = RPMTAG_HEADERSTARTOFF;
01632 he->t = RPM_INT64_TYPE;
01633 he->p.ui64p = xmalloc(sizeof(*he->p.ui64p));
01634 he->p.ui64p[0] = headerGetStartOff(h);
01635 he->freeData = 1;
01636 he->c = 1;
01637 return 0;
01638 }
01639
01640
01647
01648 static int headerendoffTag(Header h, HE_t he)
01649
01650
01651
01652
01653 {
01654 he->tag = RPMTAG_HEADERENDOFF;
01655 he->t = RPM_INT64_TYPE;
01656 he->p.ui64p = xmalloc(sizeof(*he->p.ui64p));
01657 he->p.ui64p[0] = headerGetEndOff(h);
01658 he->freeData = 1;
01659 he->c = 1;
01660 return 0;
01661 }
01662
01663
01670
01671 static int pkgoriginTag(Header h, HE_t he)
01672
01673
01674
01675
01676 {
01677 const char * origin;
01678
01679 he->tag = RPMTAG_PACKAGEORIGIN;
01680 if (!headerGetEntry(h, he->tag, NULL, &origin, NULL)
01681 && (origin = headerGetOrigin(h)) != NULL)
01682 {
01683 he->t = RPM_STRING_TYPE;
01684 he->p.str = xstrdup(origin);
01685 he->c = 1;
01686 he->freeData = 1;
01687 }
01688 return 0;
01689 }
01690
01691
01698
01699 static int pkgbaseurlTag(Header h, HE_t he)
01700
01701
01702
01703
01704 {
01705 const char * baseurl;
01706 int rc = 1;
01707
01708 he->tag = RPMTAG_PACKAGEBASEURL;
01709 if (!headerGetEntry(h, he->tag, NULL, &baseurl, NULL)
01710 && (baseurl = headerGetBaseURL(h)) != NULL)
01711 {
01712 he->t = RPM_STRING_TYPE;
01713 he->p.str = xstrdup(baseurl);
01714 he->c = 1;
01715 he->freeData = 1;
01716 rc = 0;
01717 }
01718 return rc;
01719 }
01720
01721
01728
01729 static int pkgdigestTag(Header h, HE_t he)
01730
01731
01732
01733
01734 {
01735 const char * digest;
01736 int rc = 1;
01737
01738 he->tag = RPMTAG_PACKAGEDIGEST;
01739 if ((digest = headerGetDigest(h)) != NULL)
01740 {
01741 he->t = RPM_STRING_TYPE;
01742 he->p.str = xstrdup(digest);
01743 he->c = 1;
01744 he->freeData = 1;
01745 rc = 0;
01746 }
01747 return rc;
01748 }
01749
01750
01757
01758 static int pkgmtimeTag(Header h, HE_t he)
01759
01760
01761
01762
01763 {
01764 struct stat * st = headerGetStatbuf(h);
01765 he->tag = RPMTAG_PACKAGETIME;
01766 he->t = RPM_UINT64_TYPE;
01767 he->p.ui64p = xmalloc(sizeof(*he->p.ui64p));
01768 he->p.ui64p[0] = st->st_mtime;
01769 he->freeData = 1;
01770 he->c = 1;
01771 return 0;
01772 }
01773
01774
01781
01782 static int pkgsizeTag(Header h, HE_t he)
01783
01784
01785
01786
01787 {
01788 struct stat * st = headerGetStatbuf(h);
01789 he->tag = RPMTAG_PACKAGESIZE;
01790 he->t = RPM_UINT64_TYPE;
01791 he->p.ui64p = xmalloc(sizeof(*he->p.ui64p));
01792 he->p.ui64p[0] = st->st_size;
01793 he->freeData = 1;
01794 he->c = 1;
01795 return 0;
01796 }
01797
01798
01804
01805 static char * hGetNVRA(Header h)
01806
01807 {
01808 const char * N = NULL;
01809 const char * V = NULL;
01810 const char * R = NULL;
01811 const char * A = NULL;
01812 size_t nb = 0;
01813 char * NVRA, * t;
01814
01815 (void) headerNEVRA(h, &N, NULL, &V, &R, &A);
01816 if (N) nb += strlen(N);
01817 if (V) nb += strlen(V) + 1;
01818 if (R) nb += strlen(R) + 1;
01819 if (A) nb += strlen(A) + 1;
01820 nb++;
01821 NVRA = t = xmalloc(nb);
01822 *t = '\0';
01823 if (N) t = stpcpy(t, N);
01824 if (V) t = stpcpy( stpcpy(t, "-"), V);
01825 if (R) t = stpcpy( stpcpy(t, "-"), R);
01826 if (A) t = stpcpy( stpcpy(t, "."), A);
01827 return NVRA;
01828 }
01829
01836
01837 static int nvraTag(Header h, HE_t he)
01838
01839
01840
01841
01842 {
01843 he->t = RPM_STRING_TYPE;
01844 he->p.str = hGetNVRA(h);
01845 he->c = 1;
01846 he->freeData = 1;
01847 return 0;
01848 }
01849
01850
01857 static int _fnTag(Header h, HE_t he)
01858
01859 {
01860 he->t = RPM_STRING_ARRAY_TYPE;
01861 rpmfiBuildFNames(h, he->tag, &he->p.argv, &he->c);
01862 he->freeData = 1;
01863 return 0;
01864 }
01865
01866 static int filepathsTag(Header h, HE_t he)
01867
01868 {
01869 he->tag = RPMTAG_BASENAMES;
01870 return _fnTag(h, he);
01871 }
01872
01873 static int origpathsTag(Header h, HE_t he)
01874
01875 {
01876 he->tag = RPMTAG_ORIGBASENAMES;
01877 return _fnTag(h, he);
01878 }
01879
01886 static int fsnamesTag( Header h, HE_t he)
01887
01888
01889 {
01890 const char ** list;
01891
01892 if (rpmGetFilesystemList(&list, &he->c))
01893 return 1;
01894
01895 he->t = RPM_STRING_ARRAY_TYPE;
01896 he->p.argv = list;
01897 he->freeData = 0;
01898
01899 return 0;
01900 }
01901
01908 static int fssizesTag(Header h, HE_t he)
01909
01910
01911
01912
01913 {
01914 HE_t vhe = memset(alloca(sizeof(*vhe)), 0, sizeof(*vhe));
01915 const char ** fnames;
01916 uint_64 * usages;
01917 int numFiles;
01918 int rc = 1;
01919 int xx;
01920
01921 vhe->tag = RPMTAG_FILESIZES;
01922 xx = headerGetEntry(h, vhe->tag, (hTYP_t)&vhe->t, &vhe->p.ptr, &vhe->c);
01923 if (!xx) {
01924 numFiles = 0;
01925 fnames = NULL;
01926 } else
01927 rpmfiBuildFNames(h, RPMTAG_BASENAMES, &fnames, &numFiles);
01928
01929 if (rpmGetFilesystemList(NULL, &he->c))
01930 goto exit;
01931
01932 he->t = RPM_INT64_TYPE;
01933 he->freeData = 1;
01934
01935 if (fnames == NULL)
01936 he->p.ui64p = xcalloc(he->c, sizeof(*usages));
01937 else
01938 if (rpmGetFilesystemUsage(fnames, vhe->p.ui32p, numFiles, &he->p.ui64p, 0))
01939 goto exit;
01940
01941 rc = 0;
01942
01943 exit:
01944 fnames = _free(fnames);
01945
01946 return rc;
01947 }
01948
01955 static int fileclassTag(Header h, HE_t he)
01956
01957
01958
01959 {
01960 he->t = RPM_STRING_ARRAY_TYPE;
01961 rpmfiBuildFClasses(h, &he->p.argv, &he->c);
01962 he->freeData = 1;
01963 return 0;
01964 }
01965
01972 static int filecontextsTag(Header h, HE_t he)
01973
01974
01975
01976 {
01977 he->t = RPM_STRING_ARRAY_TYPE;
01978 rpmfiBuildFContexts(h, &he->p.argv, &he->c);
01979 he->freeData = 1;
01980 return 0;
01981 }
01982
01989 static int fscontextsTag(Header h, HE_t he)
01990
01991
01992
01993 {
01994 he->t = RPM_STRING_ARRAY_TYPE;
01995 rpmfiBuildFSContexts(h, &he->p.argv, &he->c);
01996 he->freeData = 1;
01997 return 0;
01998 }
01999
02006 static int recontextsTag(Header h, HE_t he)
02007
02008
02009
02010 {
02011 he->t = RPM_STRING_ARRAY_TYPE;
02012 rpmfiBuildREContexts(h, &he->p.argv, &he->c);
02013 he->freeData = 1;
02014 return 0;
02015 }
02016
02023 static int fileprovideTag(Header h, HE_t he)
02024
02025
02026
02027 {
02028 he->t = RPM_STRING_ARRAY_TYPE;
02029 rpmfiBuildFDeps(h, RPMTAG_PROVIDENAME, &he->p.argv, &he->c);
02030 he->freeData = 1;
02031 return 0;
02032 }
02033
02040 static int filerequireTag(Header h, HE_t he)
02041
02042
02043
02044 {
02045 he->t = RPM_STRING_ARRAY_TYPE;
02046 rpmfiBuildFDeps(h, RPMTAG_REQUIRENAME, &he->p.argv, &he->c);
02047 he->freeData = 1;
02048 return 0;
02049 }
02050
02057 static int missingokTag(Header h, HE_t he)
02058
02059
02060
02061 {
02062 rpmds ds = rpmdsNew(h, RPMTAG_REQUIRENAME, 0);
02063 ARGV_t av = NULL;
02064 ARGV_t argv;
02065 int argc = 0;
02066 char * t;
02067 size_t nb = 0;
02068 int i;
02069
02070 assert(ds != NULL);
02071
02072 ds = rpmdsInit(ds);
02073 if (ds != NULL)
02074 while (rpmdsNext(ds) >= 0) {
02075 int Flags = rpmdsFlags(ds);
02076 const char * DNEVR;
02077 if (!(Flags & RPMSENSE_MISSINGOK))
02078 continue;
02079 DNEVR = rpmdsDNEVR(ds);
02080 if (DNEVR == NULL)
02081 continue;
02082 nb += sizeof(*argv) + strlen(DNEVR+2) + 1;
02083 (void) argvAdd(&av, DNEVR+2);
02084 argc++;
02085 }
02086 nb += sizeof(*argv);
02087
02088
02089 argv = (ARGV_t) xcalloc(nb, 1);
02090 t = (char *)(argv + argc);
02091 for (i = 0; i < argc; i++) {
02092 argv[i] = t;
02093 t = stpcpy(t, av[i]);
02094 *t++ = '\0';
02095 }
02096 av = argvFree(av);
02097 ds = rpmdsFree(ds);
02098
02099
02100
02101 he->t = RPM_STRING_ARRAY_TYPE;
02102 he->p.argv = argv;
02103 he->c = argc;
02104 he->freeData = 1;
02105 return 0;
02106 }
02107
02108 static int PRCOSkip(rpmTag tag, rpmTagData N, rpmTagData EVR, rpmTagData F,
02109 uint32_t i)
02110
02111 {
02112 int a = -2, b = -2;
02113
02114 if (N.argv[i] == NULL || *N.argv[i] == '\0')
02115 return 1;
02116 if (tag == RPMTAG_REQUIRENAME && i > 0
02117 && !(a=strcmp(N.argv[i], N.argv[i-1]))
02118 && !(b=strcmp(EVR.argv[i], EVR.argv[i-1]))
02119 && (F.ui32p[i] & 0x4e) == ((F.ui32p[i-1] & 0x4e)))
02120 return 1;
02121 return 0;
02122 }
02123
02124 static int PRCOxmlTag(Header h, HE_t he, rpmTag EVRtag, rpmTag Ftag)
02125
02126 {
02127 rpmTag tag = he->tag;
02128 rpmTagData N = { .ptr = NULL };
02129 rpmTagData EVR = { .ptr = NULL };
02130 rpmTagData F = { .ptr = NULL };
02131 size_t nb;
02132 uint32_t ac;
02133 uint32_t c;
02134 uint32_t i;
02135 char *t;
02136 int rc = 1;
02137 int xx;
02138
02139 xx = headerGetEntry(h, he->tag, (hTYP_t)&he->t, &he->p, &he->c);
02140 if (xx == 0) goto exit;
02141 N.argv = he->p.argv;
02142 c = he->c;
02143
02144 he->tag = EVRtag;
02145 xx = headerGetEntry(h, he->tag, (hTYP_t)&he->t, &he->p, &he->c);
02146 if (xx == 0) goto exit;
02147 EVR.argv = he->p.argv;
02148
02149 he->tag = Ftag;
02150 xx = headerGetEntry(h, he->tag, (hTYP_t)&he->t, &he->p, &he->c);
02151 if (xx == 0) goto exit;
02152 F.ui32p = he->p.ui32p;
02153
02154 nb = sizeof(*he->p.argv);
02155 ac = 0;
02156 for (i = 0; i < c; i++) {
02157 if (PRCOSkip(tag, N, EVR, F, i))
02158 continue;
02159 ac++;
02160 nb += sizeof(*he->p.argv);
02161 nb += sizeof("<rpm:entry name=\"\"/>");
02162 if (*N.argv[i] == '/')
02163 nb += xmlstrlen(N.argv[i]);
02164 else
02165 nb += strlen(N.argv[i]);
02166 if (EVR.argv != NULL && EVR.argv[i] != NULL && *EVR.argv[i] != '\0') {
02167 nb += sizeof(" flags=\"EQ\" epoch=\"0\" ver=\"\"") - 1;
02168 nb += strlen(EVR.argv[i]);
02169 if (strchr(EVR.argv[i], ':') != NULL)
02170 nb -= 2;
02171 if (strchr(EVR.argv[i], '-') != NULL)
02172 nb += sizeof(" rel=\"\"") - 2;
02173 }
02174 #ifdef NOTNOW
02175 if (tag == RPMTAG_REQUIRENAME && (F.ui32p[i] & 0x40))
02176 nb += sizeof(" pre=\"1\"") - 1;
02177 #endif
02178 }
02179
02180 he->t = RPM_STRING_ARRAY_TYPE;
02181 he->c = ac;
02182 he->freeData = 1;
02183 he->p.argv = xmalloc(nb + BUFSIZ);
02184 t = (char *) &he->p.argv[he->c + 1];
02185 ac = 0;
02186 for (i = 0; i < c; i++) {
02187 if (PRCOSkip(tag, N, EVR, F, i))
02188 continue;
02189 he->p.argv[ac++] = t;
02190 t = stpcpy(t, "<rpm:entry");
02191 t = stpcpy(t, " name=\"");
02192 if (*N.argv[i] == '/') {
02193 t = xmlstrcpy(t, N.argv[i]); t += strlen(t);
02194 } else
02195 t = stpcpy(t, N.argv[i]);
02196 t = stpcpy(t, "\"");
02197 if (EVR.argv != NULL && EVR.argv[i] != NULL && *EVR.argv[i] != '\0') {
02198 static char *Fstr[] = { "?0","LT","GT","?3","EQ","LE","GE","?7" };
02199 int Fx = ((F.ui32p[i] >> 1) & 0x7);
02200 const char *E, *V, *R;
02201 char *f, *fe;
02202 t = stpcpy( stpcpy( stpcpy(t, " flags=\""), Fstr[Fx]), "\"");
02203 f = (char *) EVR.argv[i];
02204 for (fe = f; *fe != '\0' && *fe >= '0' && *fe <= '9'; fe++);
02205 if (*fe == ':') { *fe++ = '\0'; E = f; f = fe; } else E = NULL;
02206 V = f;
02207 for (fe = f; *fe != '\0' && *fe != '-'; fe++);
02208 if (*fe == '-') { *fe++ = '\0'; R = fe; } else R = NULL;
02209 t = stpcpy( stpcpy( stpcpy(t, " epoch=\""), (E && *E ? E : "0")), "\"");
02210 t = stpcpy( stpcpy( stpcpy(t, " ver=\""), V), "\"");
02211 if (R != NULL)
02212 t = stpcpy( stpcpy( stpcpy(t, " rel=\""), R), "\"");
02213 }
02214 #ifdef NOTNOW
02215 if (tag == RPMTAG_REQUIRENAME && (F.ui32p[i] & 0x40))
02216 t = stpcpy(t, " pre=\"1\"");
02217 #endif
02218 t = stpcpy(t, "/>");
02219 *t++ = '\0';
02220 }
02221 he->p.argv[he->c] = NULL;
02222 rc = 0;
02223
02224 exit:
02225 N.argv = _free(N.argv);
02226 EVR.argv = _free(EVR.argv);
02227 return rc;
02228 }
02229
02230 static int PxmlTag(Header h, HE_t he)
02231
02232 {
02233 he->tag = RPMTAG_PROVIDENAME;
02234 return PRCOxmlTag(h, he, RPMTAG_PROVIDEVERSION, RPMTAG_PROVIDEFLAGS);
02235 }
02236
02237 static int RxmlTag(Header h, HE_t he)
02238
02239 {
02240 he->tag = RPMTAG_REQUIRENAME;
02241 return PRCOxmlTag(h, he, RPMTAG_REQUIREVERSION, RPMTAG_REQUIREFLAGS);
02242 }
02243
02244 static int CxmlTag(Header h, HE_t he)
02245
02246 {
02247 he->tag = RPMTAG_CONFLICTNAME;
02248 return PRCOxmlTag(h, he, RPMTAG_CONFLICTVERSION, RPMTAG_CONFLICTFLAGS);
02249 }
02250
02251 static int OxmlTag(Header h, HE_t he)
02252
02253 {
02254 he->tag = RPMTAG_OBSOLETENAME;
02255 return PRCOxmlTag(h, he, RPMTAG_OBSOLETEVERSION, RPMTAG_OBSOLETEFLAGS);
02256 }
02257
02263 static size_t sqlstrlen(const char * s)
02264
02265 {
02266 size_t len = 0;
02267 int c;
02268
02269 while ((c = (int) *s++) != (int) '\0')
02270 {
02271 switch (c) {
02272 case '\'': len += 1;
02273 default: len += 1; break;
02274 }
02275 }
02276 return len;
02277 }
02278
02285 static char * sqlstrcpy( char * t, const char * s)
02286
02287 {
02288 char * te = t;
02289 int c;
02290
02291 while ((c = (int) *s++) != (int) '\0') {
02292 switch (c) {
02293 case '\'': *te++ = (char) c;
02294 default: *te++ = (char) c; break;
02295 }
02296 }
02297 *te = '\0';
02298 return t;
02299 }
02300
02307 static char * sqlescapeFormat(HE_t he, const char ** av)
02308
02309 {
02310 int ix = (he->ix > 0 ? he->ix : 0);
02311 char * val;
02312
02313 assert(ix == 0);
02314 if (he->t != RPM_STRING_TYPE) {
02315 val = xstrdup(_("(not a string)"));
02316 } else {
02317 const char * s = strdup_locale_convert(he->p.str, (av ? av[0] : NULL));
02318 size_t nb = sqlstrlen(s);
02319 char * t;
02320
02321 val = t = xcalloc(1, nb + 1);
02322 t = sqlstrcpy(t, s); t += strlen(t);
02323 *t = '\0';
02324 s = _free(s);
02325 }
02326
02327
02328 return val;
02329
02330 }
02331
02332 static int PRCOsqlTag(Header h, HE_t he, rpmTag EVRtag, rpmTag Ftag)
02333
02334 {
02335 rpmTag tag = he->tag;
02336 rpmTagData N = { .ptr = NULL };
02337 rpmTagData EVR = { .ptr = NULL };
02338 rpmTagData F = { .ptr = NULL };
02339 char instance[64];
02340 size_t nb;
02341 uint32_t ac;
02342 uint32_t c;
02343 uint32_t i;
02344 char *t;
02345 int rc = 1;
02346 int xx;
02347
02348 xx = headerGetEntry(h, he->tag, (hTYP_t)&he->t, &he->p, &he->c);
02349 if (xx == 0) goto exit;
02350 N.argv = he->p.argv;
02351 c = he->c;
02352
02353 he->tag = EVRtag;
02354 xx = headerGetEntry(h, he->tag, (hTYP_t)&he->t, &he->p, &he->c);
02355 if (xx == 0) goto exit;
02356 EVR.argv = he->p.argv;
02357
02358 he->tag = Ftag;
02359 xx = headerGetEntry(h, he->tag, (hTYP_t)&he->t, &he->p, &he->c);
02360 if (xx == 0) goto exit;
02361 F.ui32p = he->p.ui32p;
02362
02363 xx = snprintf(instance, sizeof(instance), "'%d'", headerGetInstance(h));
02364 nb = sizeof(*he->p.argv);
02365 ac = 0;
02366 for (i = 0; i < c; i++) {
02367 if (PRCOSkip(tag, N, EVR, F, i))
02368 continue;
02369 ac++;
02370 nb += sizeof(*he->p.argv);
02371 nb += strlen(instance) + sizeof(", '', '', '', '', ''");
02372 if (tag == RPMTAG_REQUIRENAME)
02373 nb += sizeof(", ''") - 1;
02374 nb += strlen(N.argv[i]);
02375 if (EVR.argv != NULL && EVR.argv[i] != NULL && *EVR.argv[i] != '\0') {
02376 nb += strlen(EVR.argv[i]);
02377 nb += sizeof("EQ0") - 1;
02378 }
02379 #ifdef NOTNOW
02380 if (tag == RPMTAG_REQUIRENAME && (F.ui32p[i] & 0x40))
02381 nb += sizeof("1") - 1;
02382 #endif
02383 }
02384
02385 he->t = RPM_STRING_ARRAY_TYPE;
02386 he->c = ac;
02387 he->freeData = 1;
02388 he->p.argv = xmalloc(nb + BUFSIZ);
02389 t = (char *) &he->p.argv[he->c + 1];
02390 ac = 0;
02391 for (i = 0; i < c; i++) {
02392 if (PRCOSkip(tag, N, EVR, F, i))
02393 continue;
02394 he->p.argv[ac++] = t;
02395 t = stpcpy(t, instance);
02396 t = stpcpy( stpcpy( stpcpy(t, ", '"), N.argv[i]), "'");
02397 if (EVR.argv != NULL && EVR.argv[i] != NULL && *EVR.argv[i] != '\0') {
02398 static char *Fstr[] = { "?0","LT","GT","?3","EQ","LE","GE","?7" };
02399 int Fx = ((F.ui32p[i] >> 1) & 0x7);
02400 const char *E, *V, *R;
02401 char *f, *fe;
02402 t = stpcpy( stpcpy( stpcpy(t, ", '"), Fstr[Fx]), "'");
02403 f = (char *) EVR.argv[i];
02404 for (fe = f; *fe != '\0' && *fe >= '0' && *fe <= '9'; fe++);
02405 if (*fe == ':') { *fe++ = '\0'; E = f; f = fe; } else E = NULL;
02406 V = f;
02407 for (fe = f; *fe != '\0' && *fe != '-'; fe++);
02408 if (*fe == '-') { *fe++ = '\0'; R = fe; } else R = NULL;
02409 t = stpcpy( stpcpy( stpcpy(t, ", '"), (E && *E ? E : "0")), "'");
02410 t = stpcpy( stpcpy( stpcpy(t, ", '"), V), "'");
02411 t = stpcpy( stpcpy( stpcpy(t, ", '"), (R ? R : "")), "'");
02412 } else
02413 t = stpcpy(t, ", '', '', '', ''");
02414 #ifdef NOTNOW
02415 if (tag == RPMTAG_REQUIRENAME)
02416 t = stpcpy(stpcpy(stpcpy(t, ", '"),(F.ui32p[i] & 0x40) ? "1" : "0"), "'");
02417 #endif
02418 *t++ = '\0';
02419 }
02420 he->p.argv[he->c] = NULL;
02421 rc = 0;
02422
02423 exit:
02424 N.argv = _free(N.argv);
02425 EVR.argv = _free(EVR.argv);
02426 return rc;
02427 }
02428
02429 static int PsqlTag(Header h, HE_t he)
02430
02431 {
02432 he->tag = RPMTAG_PROVIDENAME;
02433 return PRCOsqlTag(h, he, RPMTAG_PROVIDEVERSION, RPMTAG_PROVIDEFLAGS);
02434 }
02435
02436 static int RsqlTag(Header h, HE_t he)
02437
02438 {
02439 he->tag = RPMTAG_REQUIRENAME;
02440 return PRCOsqlTag(h, he, RPMTAG_REQUIREVERSION, RPMTAG_REQUIREFLAGS);
02441 }
02442
02443 static int CsqlTag(Header h, HE_t he)
02444
02445 {
02446 he->tag = RPMTAG_CONFLICTNAME;
02447 return PRCOsqlTag(h, he, RPMTAG_CONFLICTVERSION, RPMTAG_CONFLICTFLAGS);
02448 }
02449
02450 static int OsqlTag(Header h, HE_t he)
02451
02452 {
02453 he->tag = RPMTAG_OBSOLETENAME;
02454 return PRCOsqlTag(h, he, RPMTAG_OBSOLETEVERSION, RPMTAG_OBSOLETEFLAGS);
02455 }
02456
02457 static int FDGSkip(rpmTagData DN, rpmTagData BN, rpmTagData DI, uint32_t i)
02458
02459 {
02460 const char * dn = DN.argv[DI.ui32p[i]];
02461 size_t dnlen = strlen(dn);
02462
02463 if (strstr(dn, "bin/") != NULL)
02464 return 1;
02465 if (dnlen >= sizeof("/etc/")-1 && !strncmp(dn, "/etc/", dnlen))
02466 return 1;
02467 if (!strcmp(dn, "/usr/lib/") && !strcmp(BN.argv[i], "sendmail"))
02468 return 1;
02469 return 2;
02470 }
02471
02472 static int FDGxmlTag(Header h, HE_t he, int lvl)
02473
02474 {
02475 rpmTagData BN = { .ptr = NULL };
02476 rpmTagData DN = { .ptr = NULL };
02477 rpmTagData DI = { .ptr = NULL };
02478 rpmTagData FMODES = { .ptr = NULL };
02479 rpmTagData FFLAGS = { .ptr = NULL };
02480 size_t nb;
02481 uint32_t ac;
02482 uint32_t c;
02483 uint32_t i;
02484 char *t;
02485 int rc = 1;
02486 int xx;
02487
02488 he->tag = RPMTAG_BASENAMES;
02489 xx = headerGetEntry(h, he->tag, (hTYP_t)&he->t, &he->p, &he->c);
02490 if (xx == 0) goto exit;
02491 BN.argv = he->p.argv;
02492 c = he->c;
02493
02494 he->tag = RPMTAG_DIRNAMES;
02495 xx = headerGetEntry(h, he->tag, (hTYP_t)&he->t, &he->p, &he->c);
02496 if (xx == 0) goto exit;
02497 DN.argv = he->p.argv;
02498
02499 he->tag = RPMTAG_DIRINDEXES;
02500 xx = headerGetEntry(h, he->tag, (hTYP_t)&he->t, &he->p, &he->c);
02501 if (xx == 0) goto exit;
02502 DI.ui32p = he->p.ui32p;
02503
02504 he->tag = RPMTAG_FILEMODES;
02505 xx = headerGetEntry(h, he->tag, (hTYP_t)&he->t, &he->p, &he->c);
02506 if (xx == 0) goto exit;
02507 FMODES.ui16p = he->p.ui16p;
02508
02509 he->tag = RPMTAG_FILEFLAGS;
02510 xx = headerGetEntry(h, he->tag, (hTYP_t)&he->t, &he->p, &he->c);
02511 if (xx == 0) goto exit;
02512 FFLAGS.ui32p = he->p.ui32p;
02513
02514 nb = sizeof(*he->p.argv);
02515 ac = 0;
02516 for (i = 0; i < c; i++) {
02517 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
02518 continue;
02519 ac++;
02520 nb += sizeof(*he->p.argv);
02521 nb += sizeof("<file></file>");
02522 nb += xmlstrlen(DN.argv[DI.ui32p[i]]);
02523 nb += xmlstrlen(BN.argv[i]);
02524 if (FFLAGS.ui32p[i] & 0x40)
02525 nb += sizeof(" type=\"ghost\"") - 1;
02526 else if (S_ISDIR(FMODES.ui16p[i]))
02527 nb += sizeof(" type=\"dir\"") - 1;
02528 }
02529
02530 he->t = RPM_STRING_ARRAY_TYPE;
02531 he->c = ac;
02532 he->freeData = 1;
02533 he->p.argv = xmalloc(nb);
02534 t = (char *) &he->p.argv[he->c + 1];
02535 ac = 0;
02536
02537 for (i = 0; i < c; i++) {
02538 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
02539 continue;
02540 if (FFLAGS.ui32p[i] & 0x40)
02541 continue;
02542 if (S_ISDIR(FMODES.ui16p[i]))
02543 continue;
02544 he->p.argv[ac++] = t;
02545 t = stpcpy(t, "<file>");
02546 t = xmlstrcpy(t, DN.argv[DI.ui32p[i]]); t += strlen(t);
02547 t = xmlstrcpy(t, BN.argv[i]); t += strlen(t);
02548 t = stpcpy(t, "</file>");
02549 *t++ = '\0';
02550 }
02551 for (i = 0; i < c; i++) {
02552 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
02553 continue;
02554 if (FFLAGS.ui32p[i] & 0x40)
02555 continue;
02556 if (!S_ISDIR(FMODES.ui16p[i]))
02557 continue;
02558 he->p.argv[ac++] = t;
02559 t = stpcpy(t, "<file type=\"dir\">");
02560 t = xmlstrcpy(t, DN.argv[DI.ui32p[i]]); t += strlen(t);
02561 t = xmlstrcpy(t, BN.argv[i]); t += strlen(t);
02562 t = stpcpy(t, "</file>");
02563 *t++ = '\0';
02564 }
02565 for (i = 0; i < c; i++) {
02566 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
02567 continue;
02568 if (!(FFLAGS.ui32p[i] & 0x40))
02569 continue;
02570 he->p.argv[ac++] = t;
02571 t = stpcpy(t, "<file type=\"ghost\">");
02572 t = xmlstrcpy(t, DN.argv[DI.ui32p[i]]); t += strlen(t);
02573 t = xmlstrcpy(t, BN.argv[i]); t += strlen(t);
02574 t = stpcpy(t, "</file>");
02575 *t++ = '\0';
02576 }
02577
02578 he->p.argv[he->c] = NULL;
02579 rc = 0;
02580
02581 exit:
02582 BN.argv = _free(BN.argv);
02583 DN.argv = _free(DN.argv);
02584 return rc;
02585 }
02586
02587 static int F1xmlTag(Header h, HE_t he)
02588
02589 {
02590 he->tag = RPMTAG_BASENAMES;
02591 return FDGxmlTag(h, he, 1);
02592 }
02593
02594 static int F2xmlTag(Header h, HE_t he)
02595
02596 {
02597 he->tag = RPMTAG_BASENAMES;
02598 return FDGxmlTag(h, he, 2);
02599 }
02600
02601 static int FDGsqlTag(Header h, HE_t he, int lvl)
02602
02603 {
02604 rpmTagData BN = { .ptr = NULL };
02605 rpmTagData DN = { .ptr = NULL };
02606 rpmTagData DI = { .ptr = NULL };
02607 rpmTagData FMODES = { .ptr = NULL };
02608 rpmTagData FFLAGS = { .ptr = NULL };
02609 char instance[64];
02610 size_t nb;
02611 uint32_t ac;
02612 uint32_t c;
02613 uint32_t i;
02614 char *t;
02615 int rc = 1;
02616 int xx;
02617
02618 he->tag = RPMTAG_BASENAMES;
02619 xx = headerGetEntry(h, he->tag, (hTYP_t)&he->t, &he->p, &he->c);
02620 if (xx == 0) goto exit;
02621 BN.argv = he->p.argv;
02622 c = he->c;
02623
02624 he->tag = RPMTAG_DIRNAMES;
02625 xx = headerGetEntry(h, he->tag, (hTYP_t)&he->t, &he->p, &he->c);
02626 if (xx == 0) goto exit;
02627 DN.argv = he->p.argv;
02628
02629 he->tag = RPMTAG_DIRINDEXES;
02630 xx = headerGetEntry(h, he->tag, (hTYP_t)&he->t, &he->p, &he->c);
02631 if (xx == 0) goto exit;
02632 DI.ui32p = he->p.ui32p;
02633
02634 he->tag = RPMTAG_FILEMODES;
02635 xx = headerGetEntry(h, he->tag, (hTYP_t)&he->t, &he->p, &he->c);
02636 if (xx == 0) goto exit;
02637 FMODES.ui16p = he->p.ui16p;
02638
02639 he->tag = RPMTAG_FILEFLAGS;
02640 xx = headerGetEntry(h, he->tag, (hTYP_t)&he->t, &he->p, &he->c);
02641 if (xx == 0) goto exit;
02642 FFLAGS.ui32p = he->p.ui32p;
02643
02644 xx = snprintf(instance, sizeof(instance), "'%d'", headerGetInstance(h));
02645 nb = sizeof(*he->p.argv);
02646 ac = 0;
02647 for (i = 0; i < c; i++) {
02648 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
02649 continue;
02650 ac++;
02651 nb += sizeof(*he->p.argv);
02652 nb += strlen(instance) + sizeof(", '', ''");
02653 nb += strlen(DN.argv[DI.ui32p[i]]);
02654 nb += strlen(BN.argv[i]);
02655 if (FFLAGS.ui32p[i] & 0x40)
02656 nb += sizeof("ghost") - 1;
02657 else if (S_ISDIR(FMODES.ui16p[i]))
02658 nb += sizeof("dir") - 1;
02659 else
02660 nb += sizeof("file") - 1;
02661 }
02662
02663 he->t = RPM_STRING_ARRAY_TYPE;
02664 he->c = ac;
02665 he->freeData = 1;
02666 he->p.argv = xmalloc(nb);
02667 t = (char *) &he->p.argv[he->c + 1];
02668 ac = 0;
02669
02670 for (i = 0; i < c; i++) {
02671 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
02672 continue;
02673 if (FFLAGS.ui32p[i] & 0x40)
02674 continue;
02675 if (S_ISDIR(FMODES.ui16p[i]))
02676 continue;
02677 he->p.argv[ac++] = t;
02678 t = stpcpy( stpcpy(t, instance), ", '");
02679 t = strcpy(t, DN.argv[DI.ui32p[i]]); t += strlen(t);
02680 t = strcpy(t, BN.argv[i]); t += strlen(t);
02681 t = stpcpy(t, "', 'file'");
02682 *t++ = '\0';
02683 }
02684 for (i = 0; i < c; i++) {
02685 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
02686 continue;
02687 if (FFLAGS.ui32p[i] & 0x40)
02688 continue;
02689 if (!S_ISDIR(FMODES.ui16p[i]))
02690 continue;
02691 he->p.argv[ac++] = t;
02692 t = stpcpy( stpcpy(t, instance), ", '");
02693 t = strcpy(t, DN.argv[DI.ui32p[i]]); t += strlen(t);
02694 t = strcpy(t, BN.argv[i]); t += strlen(t);
02695 t = stpcpy(t, "', 'dir'");
02696 *t++ = '\0';
02697 }
02698 for (i = 0; i < c; i++) {
02699 if (lvl > 0 && FDGSkip(DN, BN, DI, i) != lvl)
02700 continue;
02701 if (!(FFLAGS.ui32p[i] & 0x40))
02702 continue;
02703 he->p.argv[ac++] = t;
02704 t = stpcpy( stpcpy(t, instance), ", '");
02705 t = strcpy(t, DN.argv[DI.ui32p[i]]); t += strlen(t);
02706 t = strcpy(t, BN.argv[i]); t += strlen(t);
02707 t = stpcpy(t, "', 'ghost'");
02708 *t++ = '\0';
02709 }
02710
02711 he->p.argv[he->c] = NULL;
02712 rc = 0;
02713
02714 exit:
02715 BN.argv = _free(BN.argv);
02716 DN.argv = _free(DN.argv);
02717 return rc;
02718 }
02719
02720 static int F1sqlTag(Header h, HE_t he)
02721
02722 {
02723 he->tag = RPMTAG_BASENAMES;
02724 return FDGsqlTag(h, he, 1);
02725 }
02726
02727 static int F2sqlTag(Header h, HE_t he)
02728
02729 {
02730 he->tag = RPMTAG_BASENAMES;
02731 return FDGsqlTag(h, he, 2);
02732 }
02733
02740 static char * bncdataFormat(HE_t he, const char ** av)
02741
02742 {
02743 char * val;
02744
02745 if (he->t != RPM_STRING_TYPE) {
02746 val = xstrdup(_("(not a string)"));
02747 } else {
02748 const char * bn;
02749 const char * s;
02750 size_t nb;
02751 char * t;
02752
02753
02754 if ((bn = strrchr(he->p.str, '/')) != NULL)
02755 bn++;
02756 else
02757 bn = he->p.str;
02758
02759
02760 s = strdup_locale_convert(bn, (av ? av[0] : NULL));
02761 nb = xmlstrlen(s);
02762 val = t = xcalloc(1, nb + 1);
02763 t = xmlstrcpy(t, s); t += strlen(t);
02764 *t = '\0';
02765 s = _free(s);
02766 }
02767
02768
02769 return val;
02770
02771 }
02772
02773 typedef struct key_s {
02774
02775 const char *name;
02776 uint32_t value;
02777 } KEY;
02778
02779
02780 static KEY keyDigests[] = {
02781 { "adler32", PGPHASHALGO_ADLER32 },
02782 { "crc32", PGPHASHALGO_CRC32 },
02783 { "crc64", PGPHASHALGO_CRC64 },
02784 { "haval160", PGPHASHALGO_HAVAL_5_160 },
02785 { "jlu32", PGPHASHALGO_JLU32 },
02786 { "md2", PGPHASHALGO_MD2 },
02787 { "md4", PGPHASHALGO_MD4 },
02788 { "md5", PGPHASHALGO_MD5 },
02789 { "rmd128", PGPHASHALGO_RIPEMD128 },
02790 { "rmd160", PGPHASHALGO_RIPEMD160 },
02791 { "rmd256", PGPHASHALGO_RIPEMD256 },
02792 { "rmd320", PGPHASHALGO_RIPEMD320 },
02793 { "salsa10", PGPHASHALGO_SALSA10 },
02794 { "salsa20", PGPHASHALGO_SALSA20 },
02795 { "sha1", PGPHASHALGO_SHA1 },
02796 { "sha224", PGPHASHALGO_SHA224 },
02797 { "sha256", PGPHASHALGO_SHA256 },
02798 { "sha384", PGPHASHALGO_SHA384 },
02799 { "sha512", PGPHASHALGO_SHA512 },
02800 { "tiger192", PGPHASHALGO_TIGER192 },
02801 };
02802
02803 static size_t nkeyDigests = sizeof(keyDigests) / sizeof(keyDigests[0]);
02804
02808 enum keyStat_e {
02809 STAT_KEYS_NONE = 0,
02810 STAT_KEYS_DEV = (1U << 0),
02811 STAT_KEYS_INO = (1U << 1),
02812 STAT_KEYS_MODE = (1U << 2),
02813 STAT_KEYS_NLINK = (1U << 3),
02814 STAT_KEYS_UID = (1U << 4),
02815 STAT_KEYS_GID = (1U << 5),
02816 STAT_KEYS_RDEV = (1U << 6),
02817 STAT_KEYS_SIZE = (1U << 7),
02818 STAT_KEYS_BLKSIZE = (1U << 8),
02819 STAT_KEYS_BLOCKS = (1U << 9),
02820 STAT_KEYS_ATIME = (1U << 10),
02821 STAT_KEYS_CTIME = (1U << 11),
02822 STAT_KEYS_MTIME = (1U << 12),
02823 #ifdef NOTYET
02824 STAT_KEYS_FLAGS = (1U << 13),
02825 #endif
02826 STAT_KEYS_SLINK = (1U << 14),
02827 STAT_KEYS_DIGEST = (1U << 15),
02828 #ifdef NOTYET
02829 STAT_KEYS_FCONTEXT = (1U << 16),
02830 #endif
02831 STAT_KEYS_UNAME = (1U << 17),
02832 STAT_KEYS_GNAME = (1U << 18),
02833 };
02834
02835
02836 static KEY keyStat[] = {
02837 { "adler32", STAT_KEYS_DIGEST },
02838 { "atime", STAT_KEYS_ATIME },
02839 { "ctime", STAT_KEYS_CTIME },
02840 { "blksize", STAT_KEYS_BLKSIZE },
02841 { "blocks", STAT_KEYS_BLOCKS },
02842 { "crc32", STAT_KEYS_DIGEST },
02843 { "crc64", STAT_KEYS_DIGEST },
02844 { "dev", STAT_KEYS_DEV },
02845 #ifdef NOTYET
02846 { "digest", STAT_KEYS_DIGEST },
02847 { "fcontext", STAT_KEYS_FCONTEXT },
02848 { "flags", STAT_KEYS_FLAGS },
02849 #endif
02850 { "gid", STAT_KEYS_GID },
02851 { "gname", STAT_KEYS_GNAME },
02852 { "haval160", STAT_KEYS_DIGEST },
02853 { "ino", STAT_KEYS_INO },
02854 { "jlu32", STAT_KEYS_DIGEST },
02855 { "link", STAT_KEYS_SLINK },
02856 { "md2", STAT_KEYS_DIGEST },
02857 { "md4", STAT_KEYS_DIGEST },
02858 { "md5", STAT_KEYS_DIGEST },
02859 { "mode", STAT_KEYS_MODE },
02860 { "mtime", STAT_KEYS_MTIME },
02861 { "nlink", STAT_KEYS_NLINK },
02862 { "rdev", STAT_KEYS_RDEV },
02863 { "rmd128", STAT_KEYS_DIGEST },
02864 { "rmd160", STAT_KEYS_DIGEST },
02865 { "rmd256", STAT_KEYS_DIGEST },
02866 { "rmd320", STAT_KEYS_DIGEST },
02867 { "salsa10", STAT_KEYS_DIGEST },
02868 { "salsa20", STAT_KEYS_DIGEST },
02869 { "sha1", STAT_KEYS_DIGEST },
02870 { "sha224", STAT_KEYS_DIGEST },
02871 { "sha256", STAT_KEYS_DIGEST },
02872 { "sha384", STAT_KEYS_DIGEST },
02873 { "sha512", STAT_KEYS_DIGEST },
02874 { "size", STAT_KEYS_SIZE },
02875 { "tiger192", STAT_KEYS_DIGEST },
02876 { "uid", STAT_KEYS_UID },
02877 { "uname", STAT_KEYS_UNAME },
02878 };
02879
02880 static size_t nkeyStat = sizeof(keyStat) / sizeof(keyStat[0]);
02881
02885 enum keyUuids_e {
02886 UUID_KEYS_NONE = (0U << 0),
02887 UUID_KEYS_V1 = (1U << 0),
02888 UUID_KEYS_V3 = (3U << 0),
02889 UUID_KEYS_V4 = (4U << 0),
02890 UUID_KEYS_V5 = (5U << 0),
02891 #ifdef NOTYET
02892 UUID_KEYS_STRING = (0U << 4),
02893 UUID_KEYS_SIV = (1U << 4),
02894 UUID_KEYS_BINARY = (2U << 4),
02895 UUID_KEYS_TEXT = (3U << 4),
02896 #endif
02897 };
02898
02899
02900 static KEY keyUuids[] = {
02901 #ifdef NOTYET
02902 { "binary", UUID_KEYS_BINARY },
02903 { "siv", UUID_KEYS_SIV },
02904 { "string", UUID_KEYS_STRING },
02905 { "text", UUID_KEYS_TEXT },
02906 #endif
02907 { "v1", UUID_KEYS_V1 },
02908 { "v3", UUID_KEYS_V3 },
02909 { "v4", UUID_KEYS_V4 },
02910 { "v5", UUID_KEYS_V5 },
02911 };
02912
02913 static size_t nkeyUuids = sizeof(keyUuids) / sizeof(keyUuids[0]);
02914
02917 static int
02918 keyCmp(const void * a, const void * b)
02919
02920 {
02921 return strcmp(((KEY *)a)->name, ((KEY *)b)->name);
02922 }
02923
02926 static uint32_t
02927 keyValue(KEY * keys, size_t nkeys, const char *name)
02928
02929 {
02930 uint32_t keyval = 0;
02931
02932 if (name && * name) {
02933 KEY needle = { .name = name };
02934 KEY *k = (KEY *)bsearch(&needle, keys, nkeys, sizeof(*keys), keyCmp);
02935 if (k)
02936 keyval = k->value;
02937 }
02938 return keyval;
02939 }
02940
02947 static char * digestFormat(HE_t he, const char ** av)
02948
02949 {
02950 int ix = (he->ix > 0 ? he->ix : 0);
02951 char * val = NULL;
02952 size_t ns;
02953
02954 assert(ix == 0);
02955 switch(he->t) {
02956 default:
02957 val = xstrdup(_("(invalid type :digest)"));
02958 goto exit;
02959 break;
02960 case RPM_UINT64_TYPE:
02961 ns = sizeof(he->p.ui64p[0]);
02962 break;
02963 case RPM_STRING_TYPE:
02964 ns = strlen(he->p.str);
02965 break;
02966 case RPM_BIN_TYPE:
02967 ns = he->c;
02968 break;
02969 }
02970
02971 { uint32_t keyval = keyValue(keyDigests, nkeyDigests, (av ? av[0] : NULL));
02972 uint32_t algo = (keyval ? keyval : PGPHASHALGO_SHA1);
02973 DIGEST_CTX ctx = rpmDigestInit(algo, 0);
02974 int xx = rpmDigestUpdate(ctx, he->p.ptr, ns);
02975 xx = rpmDigestFinal(ctx, &val, NULL, 1);
02976 }
02977
02978 exit:
02979
02980 return val;
02981
02982 }
02983
02990 static char * statFormat(HE_t he, const char ** av)
02991
02992 {
02993
02994 static const char *avdefault[] = { "mode", NULL };
02995 const char * fn = NULL;
02996 struct stat sb, *st = &sb;
02997 int ix = (he->ix > 0 ? he->ix : 0);
02998 char * val = NULL;
02999 int xx;
03000 int i;
03001
03002 assert(ix == 0);
03003 switch(he->t) {
03004 case RPM_BIN_TYPE:
03005
03006 if (he->tag == RPMTAG_PACKAGESTAT)
03007 if (he->c == sizeof(*st)) {
03008 st = (struct stat *)he->p.ptr;
03009 break;
03010 }
03011
03012 default:
03013 val = xstrdup(_("(invalid type :stat)"));
03014 goto exit;
03015 break;
03016 case RPM_STRING_TYPE:
03017 fn = he->p.str;
03018 if (Lstat(fn, st) == 0)
03019 break;
03020 val = rpmExpand("(Lstat:", fn, ":", strerror(errno), ")", NULL);
03021 goto exit;
03022 break;
03023 }
03024
03025 if (!(av && av[0] && *av[0]))
03026 av = avdefault;
03027 for (i = 0; av[i] != NULL; i++) {
03028 char b[BUFSIZ];
03029 size_t nb = sizeof(b);
03030 char * nval;
03031 uint32_t keyval = keyValue(keyStat, nkeyStat, av[i]);
03032
03033 nval = NULL;
03034 b[0] = '\0';
03035 switch (keyval) {
03036 default:
03037 break;
03038 case STAT_KEYS_NONE:
03039 break;
03040 case STAT_KEYS_DEV:
03041 xx = snprintf(b, nb, "0x%lx", (unsigned long)st->st_dev);
03042 break;
03043 case STAT_KEYS_INO:
03044 xx = snprintf(b, nb, "0x%lx", (unsigned long)st->st_ino);
03045 break;
03046 case STAT_KEYS_MODE:
03047 xx = snprintf(b, nb, "%06o", (unsigned)st->st_mode);
03048 break;
03049 case STAT_KEYS_NLINK:
03050 xx = snprintf(b, nb, "0x%ld", (unsigned long)st->st_nlink);
03051 break;
03052 case STAT_KEYS_UID:
03053 xx = snprintf(b, nb, "%ld", (unsigned long)st->st_uid);
03054 break;
03055 case STAT_KEYS_GID:
03056 xx = snprintf(b, nb, "%ld", (unsigned long)st->st_gid);
03057 break;
03058 case STAT_KEYS_RDEV:
03059 xx = snprintf(b, nb, "0x%lx", (unsigned long)st->st_rdev);
03060 break;
03061 case STAT_KEYS_SIZE:
03062 xx = snprintf(b, nb, "%ld", (unsigned long)st->st_size);
03063 break;
03064 case STAT_KEYS_BLKSIZE:
03065 xx = snprintf(b, nb, "%ld", (unsigned long)st->st_blksize);
03066 break;
03067 case STAT_KEYS_BLOCKS:
03068 xx = snprintf(b, nb, "%ld", (unsigned long)st->st_blocks);
03069 break;
03070 case STAT_KEYS_ATIME:
03071 (void) stpcpy(b, ctime(&st->st_atime));
03072 break;
03073 case STAT_KEYS_CTIME:
03074 (void) stpcpy(b, ctime(&st->st_ctime));
03075 break;
03076 case STAT_KEYS_MTIME:
03077 (void) stpcpy(b, ctime(&st->st_mtime));
03078 break;
03079 #ifdef NOTYET
03080 case STAT_KEYS_FLAGS:
03081 break;
03082 #endif
03083 case STAT_KEYS_SLINK:
03084 if (fn != NULL && S_ISLNK(st->st_mode)) {
03085 ssize_t size = Readlink(fn, b, nb);
03086 if (size == -1) {
03087 nval = rpmExpand("(Readlink:", fn, ":", strerror(errno), ")", NULL);
03088 stpcpy(b, nval);
03089 nval = _free(nval);
03090 } else
03091 b[size] = '\0';
03092 }
03093 break;
03094 case STAT_KEYS_DIGEST:
03095 if (fn != NULL && S_ISREG(st->st_mode)) {
03096 uint32_t digval = keyValue(keyDigests, nkeyDigests, av[i]);
03097 uint32_t algo = (digval ? digval : PGPHASHALGO_SHA1);
03098 FD_t fd = Fopen(fn, "r%{?_rpmgio}");
03099 if (fd == NULL || Ferror(fd)) {
03100 nval = rpmExpand("(Fopen:", fn, ":", Fstrerror(fd), ")", NULL);
03101 } else {
03102 static int asAscii = 1;
03103 char buffer[16 * 1024];
03104 fdInitDigest(fd, algo, 0);
03105 while (Fread(buffer, sizeof(buffer[0]), sizeof(buffer), fd) > 0)
03106 {};
03107 if (Ferror(fd))
03108 nval = rpmExpand("(Fread:", fn, ":", Fstrerror(fd), ")", NULL);
03109 else
03110 fdFiniDigest(fd, algo, &nval, NULL, asAscii);
03111 }
03112 if (nval) {
03113 stpcpy(b, nval);
03114 nval = _free(nval);
03115 }
03116 if (fd != NULL)
03117 xx = Fclose(fd);
03118 }
03119 break;
03120 case STAT_KEYS_UNAME:
03121 (void) stpcpy(b, uidToUname(st->st_uid));
03122 break;
03123 case STAT_KEYS_GNAME:
03124 (void) stpcpy(b, gidToGname(st->st_gid));
03125 break;
03126 }
03127 if (b[0] == '\0')
03128 continue;
03129 b[nb-1] = '\0';
03130
03131 if (val == NULL)
03132 val = xstrdup(b);
03133 else {
03134 nval = rpmExpand(val, " | ", b, NULL);
03135 val = _free(val);
03136 val = nval;
03137 }
03138 }
03139
03140 exit:
03141
03142 return val;
03143
03144 }
03145
03152 static char * uuidFormat(HE_t he, const char ** av)
03153
03154 {
03155
03156 static const char *avdefault[] = { "v5", NULL };
03157 int version = 0;
03158 int ix = (he->ix > 0 ? he->ix : 0);
03159 char * val = NULL;
03160 int i;
03161
03162 assert(ix == 0);
03163 switch(he->t) {
03164 default:
03165 val = xstrdup(_("(invalid type :uuid)"));
03166 goto exit;
03167 break;
03168 case RPM_STRING_TYPE:
03169 break;
03170 }
03171
03172 if (!(av && av[0] && *av[0]))
03173 av = avdefault;
03174
03175 for (i = 0; av[i] != NULL; i++) {
03176 uint32_t keyval = keyValue(keyUuids, nkeyUuids, av[i]);
03177
03178 switch (keyval) {
03179 default:
03180 break;
03181 case UUID_KEYS_V1:
03182 case UUID_KEYS_V3:
03183 case UUID_KEYS_V4:
03184 case UUID_KEYS_V5:
03185 version = keyval;
03186 break;
03187 }
03188 }
03189
03190
03191 { HE_t nhe = memset(alloca(sizeof(*nhe)), 0, sizeof(*nhe));
03192 int xx;
03193 nhe->tag = he->tag;
03194 nhe->t = he->t;
03195 nhe->p.str = xstrdup(he->p.str);
03196 nhe->c = he->c;
03197 val = xmalloc((128/4 + 4) + 1);
03198 xx = str2uuid(nhe, NULL, version, val);
03199 nhe->p.ptr = _free(nhe->p.ptr);
03200 }
03201
03202 exit:
03203
03204 return val;
03205
03206 }
03207
03214 static char * rpnFormat(HE_t he, const char ** av)
03215
03216 {
03217 int ac = argvCount(av) + 1;
03218 int64_t * stack = memset(alloca(ac*sizeof(*stack)), 0, (ac*sizeof(*stack)));
03219 char * end;
03220 char * val = NULL;
03221 int ix = 0;
03222 int i;
03223
03224 switch(he->t) {
03225 default:
03226 val = xstrdup(_("(invalid type :rpn)"));
03227 goto exit;
03228 break;
03229 case RPM_UINT64_TYPE:
03230 stack[ix] = he->p.ui64p[0];
03231 break;
03232 case RPM_STRING_TYPE:
03233 end = NULL;
03234 stack[ix] = strtoll(he->p.str, &end, 0);
03235 if (*end != '\0') {
03236 val = xstrdup(_("(invalid string :rpn)"));
03237 goto exit;
03238 }
03239 break;
03240 }
03241
03242 if (av != NULL)
03243 for (i = 0; av[i] != NULL; i++) {
03244 const char * arg = av[i];
03245 size_t len = strlen(arg);
03246 int c = *arg;
03247
03248 if (len == 0) {
03249
03250 } else if (len > 1) {
03251 if (!(xisdigit(c) || (c == '-' && xisdigit(arg[1])))) {
03252 val = xstrdup(_("(expected number :rpn)"));
03253 goto exit;
03254 }
03255 if (++ix == ac) {
03256 val = xstrdup(_("(stack overflow :rpn)"));
03257 goto exit;
03258 }
03259 end = NULL;
03260 stack[ix] = strtoll(arg, &end, 0);
03261 if (*end != '\0') {
03262 val = xstrdup(_("(invalid number :rpn)"));
03263 goto exit;
03264 }
03265 } else {
03266 if (ix-- < 1) {
03267 val = xstrdup(_("(stack underflow :rpn)"));
03268 goto exit;
03269 }
03270 switch (c) {
03271 case '&': stack[ix] &= stack[ix+1]; break;
03272 case '|': stack[ix] |= stack[ix+1]; break;
03273 case '^': stack[ix] ^= stack[ix+1]; break;
03274 case '+': stack[ix] += stack[ix+1]; break;
03275 case '-': stack[ix] -= stack[ix+1]; break;
03276 case '*': stack[ix] *= stack[ix+1]; break;
03277 case '%':
03278 case '/':
03279 if (stack[ix+1] == 0) {
03280 val = xstrdup(_("(divide by zero :rpn)"));
03281 goto exit;
03282 }
03283 if (c == '%')
03284 stack[ix] %= stack[ix+1];
03285 else
03286 stack[ix] /= stack[ix+1];
03287 break;
03288 }
03289 }
03290 }
03291
03292 { HE_t nhe = memset(alloca(sizeof(*nhe)), 0, sizeof(*nhe));
03293 nhe->tag = he->tag;
03294 nhe->t = RPM_UINT64_TYPE;
03295 nhe->p.ui64p = (uint64_t *)&stack[ix];
03296 nhe->c = 1;
03297 val = intFormat(nhe, NULL, NULL);
03298 }
03299
03300 exit:
03301
03302 return val;
03303
03304 }
03305
03306
03307 const struct headerSprintfExtension_s rpmHeaderFormats[] = {
03308 { HEADER_EXT_TAG, "RPMTAG_BUILDTIMEUUID",
03309 { .tagFunction = buildtime_uuidTag } },
03310 { HEADER_EXT_TAG, "RPMTAG_CHANGELOGNAME",
03311 { .tagFunction = changelognameTag } },
03312 { HEADER_EXT_TAG, "RPMTAG_CHANGELOGTEXT",
03313 { .tagFunction = changelogtextTag } },
03314 { HEADER_EXT_TAG, "RPMTAG_DESCRIPTION",
03315 { .tagFunction = descriptionTag } },
03316 { HEADER_EXT_TAG, "RPMTAG_ENHANCES",
03317 { .tagFunction = missingokTag } },
03318 { HEADER_EXT_TAG, "RPMTAG_FILECLASS",
03319 { .tagFunction = fileclassTag } },
03320 { HEADER_EXT_TAG, "RPMTAG_FILECONTEXTS",
03321 { .tagFunction = filecontextsTag } },
03322 { HEADER_EXT_TAG, "RPMTAG_FILENAMES",
03323 { .tagFunction = filepathsTag } },
03324 { HEADER_EXT_TAG, "RPMTAG_ORIGPATHS",
03325 { .tagFunction = origpathsTag } },
03326 { HEADER_EXT_TAG, "RPMTAG_FILEPROVIDE",
03327 { .tagFunction = fileprovideTag } },
03328 { HEADER_EXT_TAG, "RPMTAG_FILEREQUIRE",
03329 { .tagFunction = filerequireTag } },
03330 { HEADER_EXT_TAG, "RPMTAG_FSCONTEXTS",
03331 { .tagFunction = fscontextsTag } },
03332 { HEADER_EXT_TAG, "RPMTAG_FSNAMES",
03333 { .tagFunction = fsnamesTag } },
03334 { HEADER_EXT_TAG, "RPMTAG_FSSIZES",
03335 { .tagFunction = fssizesTag } },
03336 { HEADER_EXT_TAG, "RPMTAG_GROUP",
03337 { .tagFunction = groupTag } },
03338 { HEADER_EXT_TAG, "RPMTAG_HDRUUID",
03339 { .tagFunction = hdruuidTag } },
03340 { HEADER_EXT_TAG, "RPMTAG_INSTALLPREFIX",
03341 { .tagFunction = instprefixTag } },
03342 { HEADER_EXT_TAG, "RPMTAG_INSTALLTIDUUID",
03343 { .tagFunction = installtid_uuidTag } },
03344 { HEADER_EXT_TAG, "RPMTAG_INSTALLTIMEUUID",
03345 { .tagFunction = installtime_uuidTag } },
03346 { HEADER_EXT_TAG, "RPMTAG_ORIGINTIDUUID",
03347 { .tagFunction = origintid_uuidTag } },
03348 { HEADER_EXT_TAG, "RPMTAG_ORIGINTIMEUUID",
03349 { .tagFunction = origintime_uuidTag } },
03350 { HEADER_EXT_TAG, "RPMTAG_PKGUUID",
03351 { .tagFunction = pkguuidTag } },
03352 { HEADER_EXT_TAG, "RPMTAG_RECONTEXTS",
03353 { .tagFunction = recontextsTag } },
03354 { HEADER_EXT_TAG, "RPMTAG_REMOVETIDUUID",
03355 { .tagFunction = removetid_uuidTag } },
03356 { HEADER_EXT_TAG, "RPMTAG_SUGGESTS",
03357 { .tagFunction = missingokTag } },
03358 { HEADER_EXT_TAG, "RPMTAG_SOURCEPKGUUID",
03359 { .tagFunction = sourcepkguuidTag } },
03360 { HEADER_EXT_TAG, "RPMTAG_SUMMARY",
03361 { .tagFunction = summaryTag } },
03362 { HEADER_EXT_TAG, "RPMTAG_TRIGGERCONDS",
03363 { .tagFunction = triggercondsTag } },
03364 { HEADER_EXT_TAG, "RPMTAG_TRIGGERTYPE",
03365 { .tagFunction = triggertypeTag } },
03366 { HEADER_EXT_TAG, "RPMTAG_DBINSTANCE",
03367 { .tagFunction = dbinstanceTag } },
03368 { HEADER_EXT_TAG, "RPMTAG_HEADERSTARTOFF",
03369 { .tagFunction = headerstartoffTag } },
03370 { HEADER_EXT_TAG, "RPMTAG_HEADERENDOFF",
03371 { .tagFunction = headerendoffTag } },
03372 { HEADER_EXT_TAG, "RPMTAG_PACKAGEBASEURL",
03373 { .tagFunction = pkgbaseurlTag } },
03374 { HEADER_EXT_TAG, "RPMTAG_PACKAGEDIGEST",
03375 { .tagFunction = pkgdigestTag } },
03376 { HEADER_EXT_TAG, "RPMTAG_PACKAGEORIGIN",
03377 { .tagFunction = pkgoriginTag } },
03378 { HEADER_EXT_TAG, "RPMTAG_PACKAGESIZE",
03379 { .tagFunction = pkgsizeTag } },
03380 { HEADER_EXT_TAG, "RPMTAG_PACKAGETIME",
03381 { .tagFunction = pkgmtimeTag } },
03382 { HEADER_EXT_TAG, "RPMTAG_NVRA",
03383 { .tagFunction = nvraTag } },
03384 { HEADER_EXT_TAG, "RPMTAG_PROVIDEXMLENTRY",
03385 { .tagFunction = PxmlTag } },
03386 { HEADER_EXT_TAG, "RPMTAG_REQUIREXMLENTRY",
03387 { .tagFunction = RxmlTag } },
03388 { HEADER_EXT_TAG, "RPMTAG_CONFLICTXMLENTRY",
03389 { .tagFunction = CxmlTag } },
03390 { HEADER_EXT_TAG, "RPMTAG_OBSOLETEXMLENTRY",
03391 { .tagFunction = OxmlTag } },
03392 { HEADER_EXT_TAG, "RPMTAG_FILESXMLENTRY1",
03393 { .tagFunction = F1xmlTag } },
03394 { HEADER_EXT_TAG, "RPMTAG_FILESXMLENTRY2",
03395 { .tagFunction = F2xmlTag } },
03396 { HEADER_EXT_TAG, "RPMTAG_PROVIDESQLENTRY",
03397 { .tagFunction = PsqlTag } },
03398 { HEADER_EXT_TAG, "RPMTAG_REQUIRESQLENTRY",
03399 { .tagFunction = RsqlTag } },
03400 { HEADER_EXT_TAG, "RPMTAG_CONFLICTSQLENTRY",
03401 { .tagFunction = CsqlTag } },
03402 { HEADER_EXT_TAG, "RPMTAG_OBSOLETESQLENTRY",
03403 { .tagFunction = OsqlTag } },
03404 { HEADER_EXT_TAG, "RPMTAG_FILESSQLENTRY1",
03405 { .tagFunction = F1sqlTag } },
03406 { HEADER_EXT_TAG, "RPMTAG_FILESSQLENTRY2",
03407 { .tagFunction = F2sqlTag } },
03408 { HEADER_EXT_FORMAT, "armor",
03409 { .fmtFunction = armorFormat } },
03410 { HEADER_EXT_FORMAT, "base64",
03411 { .fmtFunction = base64Format } },
03412 { HEADER_EXT_FORMAT, "bncdata",
03413 { .fmtFunction = bncdataFormat } },
03414 { HEADER_EXT_FORMAT, "cdata",
03415 { .fmtFunction = cdataFormat } },
03416 { HEADER_EXT_FORMAT, "depflags",
03417 { .fmtFunction = depflagsFormat } },
03418 { HEADER_EXT_FORMAT, "digest",
03419 { .fmtFunction = digestFormat } },
03420 { HEADER_EXT_FORMAT, "fflags",
03421 { .fmtFunction = fflagsFormat } },
03422 { HEADER_EXT_FORMAT, "iconv",
03423 { .fmtFunction = iconvFormat } },
03424 { HEADER_EXT_FORMAT, "perms",
03425 { .fmtFunction = permsFormat } },
03426 { HEADER_EXT_FORMAT, "permissions",
03427 { .fmtFunction = permsFormat } },
03428 { HEADER_EXT_FORMAT, "pgpsig",
03429 { .fmtFunction = pgpsigFormat } },
03430 { HEADER_EXT_FORMAT, "rpn",
03431 { .fmtFunction = rpnFormat } },
03432 { HEADER_EXT_FORMAT, "sqlescape",
03433 { .fmtFunction = sqlescapeFormat } },
03434 { HEADER_EXT_FORMAT, "stat",
03435 { .fmtFunction = statFormat } },
03436 { HEADER_EXT_FORMAT, "triggertype",
03437 { .fmtFunction = triggertypeFormat } },
03438 { HEADER_EXT_FORMAT, "utf8",
03439 { .fmtFunction = iconvFormat } },
03440 { HEADER_EXT_FORMAT, "uuid",
03441 { .fmtFunction = uuidFormat } },
03442 { HEADER_EXT_FORMAT, "xml",
03443 { .fmtFunction = xmlFormat } },
03444 { HEADER_EXT_FORMAT, "yaml",
03445 { .fmtFunction = yamlFormat } },
03446 { HEADER_EXT_MORE, NULL,
03447 { .more = (void *) headerDefaultFormats } }
03448 } ;
03449