rpm
4.5
|
00001 00005 #include "system.h" 00006 00007 #include "rpmio_internal.h" 00008 #include <rpmlib.h> 00009 #include <rpmmacro.h> /* XXX for %_i18ndomains */ 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 /*@access pgpDig @*/ 00025 /*@access pgpDigParams @*/ 00026 00027 /* XXX FIXME: static for now, refactor from manifest.c later. */ 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 /*@-unrecog@*/ 00042 else if (S_ISSOCK(mode)) 00043 perms[0] = 's'; 00044 /*@=unrecog@*/ 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 /*@only@*/ char * triggertypeFormat(HE_t he, /*@null@*/ 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 /*@only@*/ char * permsFormat(HE_t he, /*@null@*/ 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 /*@only@*/ char * fflagsFormat(HE_t he, /*@null@*/ 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 /*@only@*/ char * armorFormat(HE_t he, /*@null@*/ 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: /* XXX WRONG */ 00192 case RPM_BIN_TYPE: 00193 s = data.ui8p; 00194 ns = he->c; 00195 atype = PGPARMOR_SIGNATURE; /* XXX check pkt for 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 /*@-moduncon@*/ 00203 if (b64decode(enc, (void **)&s, &ns)) 00204 return xstrdup(_("(not base64)")); 00205 /*@=moduncon@*/ 00206 atype = PGPARMOR_PUBKEY; /* XXX check pkt for 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 /*@notreached@*/ 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 /*@only@*/ char * base64Format(HE_t he, /*@null@*/ 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 /*@-globs@*/ 00251 /* Add additional bytes necessary for eol string(s). */ 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 /*@=globs@*/ 00259 00260 val = t = xcalloc(1, nt + 1); 00261 *t = '\0'; 00262 00263 /* XXX b64encode accesses uninitialized memory. */ 00264 { unsigned char * _data = xcalloc(1, ns+1); 00265 memcpy(_data, data.ptr, ns); 00266 /*@-moduncon@*/ 00267 if ((enc = b64encode(_data, ns)) != NULL) { 00268 t = stpcpy(t, enc); 00269 enc = _free(enc); 00270 } 00271 /*@=moduncon@*/ 00272 _data = _free(_data); 00273 } 00274 } 00275 00276 /*@-globstate@*/ 00277 return val; 00278 /*@=globstate@*/ 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; /*@switchbreak@*/ break; 00297 case '&': len += sizeof("&") - 1; /*@switchbreak@*/ break; 00298 default: len += 1; /*@switchbreak@*/ break; 00299 } 00300 } 00301 return len; 00302 } 00303 00310 static char * xmlstrcpy(/*@returned@*/ char * t, const char * s) 00311 /*@modifies t @*/ 00312 { 00313 char * te = t; 00314 int c; 00315 00316 while ((c = *s++) != '\0') { 00317 switch (c) { 00318 case '<': te = stpcpy(te, "<"); /*@switchbreak@*/ break; 00319 case '>': te = stpcpy(te, ">"); /*@switchbreak@*/ break; 00320 case '&': te = stpcpy(te, "&"); /*@switchbreak@*/ break; 00321 default: *te++ = c; /*@switchbreak@*/ break; 00322 } 00323 } 00324 *te = '\0'; 00325 return t; 00326 } 00327 00328 static /*@only@*/ /*@null@*/ char * 00329 strdup_locale_convert (/*@null@*/ const char * buffer, 00330 /*@null@*/ 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 /*@-type@*/ 00346 fromcode = nl_langinfo (CODESET); 00347 /*@=type@*/ 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 /*@switchbreak@*/ 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 } /*@switchbreak@*/ break; 00388 case EILSEQ: 00389 is_error = 1; 00390 /*@switchbreak@*/ break; 00391 default: 00392 is_error = 1; 00393 /*@switchbreak@*/ 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 /*@only@*/ char * cdataFormat(HE_t he, /*@null@*/ 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 /*@-globstate@*/ 00446 return val; 00447 /*@=globstate@*/ 00448 } 00449 00456 static /*@only@*/ char * iconvFormat(HE_t he, /*@null@*/ 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 /*@-globstate@*/ 00470 return val; 00471 /*@=globstate@*/ 00472 } 00473 00480 static /*@only@*/ char * xmlFormat(HE_t he, /*@null@*/ 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 /* XXX Force utf8 strings. */ 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 /* XXX Force utf8 strings. */ 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 /*@-globs -mods@*/ 00518 { int cpl = b64encode_chars_per_line; 00519 b64encode_chars_per_line = 0; 00520 /*@-formatconst@*/ 00521 s = base64Format(he, NULL); 00522 /*@=formatconst@*/ 00523 b64encode_chars_per_line = cpl; 00524 xtag = "base64"; 00525 freeit = 1; 00526 } break; 00527 /*@=globs =mods@*/ 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]; /* XXX note unsigned */ 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 /*@notreached@*/ break; 00545 } 00546 00547 if (s == NULL) { 00548 int tlen = 64; 00549 t = memset(alloca(tlen+1), 0, tlen+1); 00550 /*@-duplicatequals@*/ 00551 if (anint != 0) 00552 xx = snprintf(t, tlen, "%llu", anint); 00553 /*@=duplicatequals@*/ 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(/*@out@*/ /*@returned@*/ char * t, const char * s, int lvl) 00614 /*@modifies t @*/ 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 /*@only@*/ char * yamlFormat(HE_t he, /*@null@*/ 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: /* XXX currently never happens */ 00664 case RPM_I18NSTRING_TYPE: /* XXX currently never happens */ 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])) /* leading [ */ 00668 xx = 1; 00669 if (xx == 0) 00670 while ((c = (int) *s++) != (int) '\0') { 00671 switch (c) { 00672 default: 00673 continue; 00674 case '\n': /* multiline */ 00675 xx = 1; 00676 /*@switchbreak@*/ break; 00677 case '-': /* leading "- \"" */ 00678 case ':': /* embedded ": " or ":" at EOL */ 00679 if (s[0] != ' ' && s[0] != '\0' && s[1] != '"') 00680 continue; 00681 xx = 1; 00682 /*@switchbreak@*/ break; 00683 } 00684 /*@loopbreak@*/ 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++; /* XXX extra indent for array[1] */ 00694 } 00695 } else { 00696 xtag = (element >= 0 ? "- " : NULL); 00697 } 00698 00699 /* XXX Force utf8 strings. */ 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 /*@-globs -mods@*/ 00708 { int cpl = b64encode_chars_per_line; 00709 b64encode_chars_per_line = 0; 00710 /*@-formatconst@*/ 00711 s = base64Format(he, NULL); 00712 element = -element; /* XXX skip " " indent. */ 00713 /*@=formatconst@*/ 00714 b64encode_chars_per_line = cpl; 00715 xtag = "!!binary "; 00716 freeit = 1; 00717 } break; 00718 /*@=globs =mods@*/ 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 /*@notreached@*/ break; 00736 } 00737 00738 if (s == NULL) { 00739 int tlen = 64; 00740 t = memset(alloca(tlen+1), 0, tlen+1); 00741 /*@-duplicatequals@*/ 00742 xx = snprintf(t, tlen, "%llu", (unsigned long long)anint); 00743 /*@=duplicatequals@*/ 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 /* XXX s was malloc'd */ 00774 if (freeit) 00775 s = _free(s); 00776 00777 val = xstrdup(t); 00778 00779 return val; 00780 } 00781 00788 static /*@only@*/ char * pgpsigFormat(HE_t he, /*@null@*/ const char ** av) 00789 /*@globals fileSystem, internalState @*/ 00790 /*@modifies fileSystem, internalState @*/ 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 /* this is important if sizeof(int_32) ! sizeof(time_t) */ 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 /*@only@*/ char * depflagsFormat(HE_t he, /*@null@*/ 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 /* XXX appending markers breaks :depflags format. */ 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 /*@modifies he @*/ 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 /*@modifies he @*/ 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; /* preserve version, clear time_hi nibble */ 00993 he->p.ui8p[8] &= 0x3f; /* preserve reserved, clear clock */ 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 /* XXX Jigger up a non-zero (but constant) clock value. Is this needed? */ 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 /*@modifies he @*/ 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 /*@modifies he @*/ 01040 { 01041 he->tag = RPMTAG_INSTALLTIME; 01042 return tag2uuidv1(h, he); 01043 } 01044 01051 static int buildtime_uuidTag(Header h, HE_t he) 01052 /*@modifies he @*/ 01053 { 01054 he->tag = RPMTAG_BUILDTIME; 01055 return tag2uuidv1(h, he); 01056 } 01057 01064 static int origintime_uuidTag(Header h, HE_t he) 01065 /*@modifies he @*/ 01066 { 01067 he->tag = RPMTAG_ORIGINTIME; 01068 return tag2uuidv1(h, he); 01069 } 01070 01077 static int installtid_uuidTag(Header h, HE_t he) 01078 /*@modifies he @*/ 01079 { 01080 he->tag = RPMTAG_INSTALLTID; 01081 return tag2uuidv1(h, he); 01082 } 01083 01090 static int removetid_uuidTag(Header h, HE_t he) 01091 /*@modifies he @*/ 01092 { 01093 he->tag = RPMTAG_REMOVETID; 01094 return tag2uuidv1(h, he); 01095 } 01096 01103 static int origintid_uuidTag(Header h, HE_t he) 01104 /*@modifies he @*/ 01105 { 01106 he->tag = RPMTAG_ORIGINTID; 01107 return tag2uuidv1(h, he); 01108 } 01109 01110 /*@unchecked@*/ /*@observer@*/ 01111 static const char uuid_ns[] = "ns:URL"; 01112 /*@unchecked@*/ /*@observer@*/ 01113 static const char uuid_auth[] = "%{?_uuid_auth}%{!?_uuid_auth:http://rpm5.org}"; 01114 /*@unchecked@*/ /*@observer@*/ 01115 static const char uuid_path[] = "%{?_uuid_path}%{!?_uuid_path:/package}"; 01116 /*@unchecked@*/ /*@observer@*/ 01117 static int uuid_version = 5; 01118 01127 static int str2uuid(HE_t he, /*@null@*/ const char ** av, 01128 int version, /*@null@*/ char * val) 01129 /*@modifies he @*/ 01130 { 01131 const char * ns = NULL; 01132 const char * tagn = tagName(he->tag); 01133 const char * s = NULL; 01134 int rc; 01135 01136 /* XXX Substitute Pkgid & Hdrid strings for aliases. */ 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 /*@fallthrough@*/ 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 /*@fallthrough@*/ 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 /*@modifies he @*/ 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 /*@notreached@*/ break; 01185 case RPM_BIN_TYPE: { /* Convert RPMTAG_PKGID from binary => hex. */ 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 /*@modifies he @*/ 01217 { 01218 he->tag = RPMTAG_PKGID; 01219 return tag2uuidv5(h, he); 01220 } 01221 01228 static int sourcepkguuidTag(Header h, HE_t he) 01229 /*@modifies he @*/ 01230 { 01231 he->tag = RPMTAG_SOURCEPKGID; 01232 return tag2uuidv5(h, he); 01233 } 01234 01241 static int hdruuidTag(Header h, HE_t he) 01242 /*@modifies he @*/ 01243 { 01244 he->tag = RPMTAG_HDRID; 01245 return tag2uuidv5(h, he); 01246 } 01247 01254 static int triggercondsTag(Header h, HE_t he) 01255 /*@modifies he @*/ 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 /*@innercontinue@*/ 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 /*@modifies he @*/ 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 /*@innercontinue@*/ 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 /*@innerbreak@*/ break; 01366 } 01367 } 01368 01369 s.ptr = headerFreeData(s.ptr, -1); 01370 return 0; 01371 } 01372 01373 /* I18N look aside diversions */ 01374 01375 #if defined(ENABLE_NLS) 01376 /*@-exportlocal -exportheadervar@*/ 01377 /*@unchecked@*/ 01378 extern int _nl_msg_cat_cntr; /* XXX GNU gettext voodoo */ 01379 /*@=exportlocal =exportheadervar@*/ 01380 #endif 01381 /*@observer@*/ /*@unchecked@*/ 01382 static const char * language = "LANGUAGE"; 01383 01384 /*@observer@*/ /*@unchecked@*/ 01385 static const char * _macro_i18ndomains = "%{?_i18ndomains}"; 01386 01393 static int i18nTag(Header h, HE_t he) 01394 /*@globals rpmGlobalMacroContext, h_errno @*/ 01395 /*@modifies he, rpmGlobalMacroContext @*/ 01396 { 01397 char * dstring = rpmExpand(_macro_i18ndomains, NULL); 01398 int rc = 1; /* assume failure */ 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; /* XXX keep gcc quiet */ 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 /* change to en_US for msgkey -> msgid resolution */ 01425 langval = getenv(language); 01426 (void) setenv(language, "en_US", 1); 01427 #if defined(ENABLE_NLS) 01428 /*@i@*/ ++_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 = /*@-unrecog@*/ dgettext(domain, msgkey) /*@=unrecog@*/; 01436 if (msgid != msgkey) break; 01437 } 01438 01439 /* restore previous environment for msgid -> msgstr resolution */ 01440 if (langval) 01441 (void) setenv(language, langval, 1); 01442 else 01443 unsetenv(language); 01444 #if defined(ENABLE_NLS) 01445 /*@i@*/ ++_nl_msg_cat_cntr; 01446 #endif 01447 01448 if (domain && msgid) { 01449 const char * s = /*@-unrecog@*/ dgettext(domain, msgid) /*@=unrecog@*/; 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 /*@-dependenttrans@*/ 01460 dstring = _free(dstring); 01461 /*@=dependenttrans@*/ 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 /*@-nullstate@*/ 01472 return rc; 01473 /*@=nullstate@*/ 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 /*@modifies he @*/ 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 /*@globals rpmGlobalMacroContext, h_errno @*/ 01547 /*@modifies he, rpmGlobalMacroContext @*/ 01548 { 01549 he->tag = RPMTAG_SUMMARY; 01550 return i18nTag(h, he); 01551 } 01552 01559 static int descriptionTag(Header h, HE_t he) 01560 /*@globals rpmGlobalMacroContext, h_errno @*/ 01561 /*@modifies he, rpmGlobalMacroContext @*/ 01562 { 01563 he->tag = RPMTAG_DESCRIPTION; 01564 return i18nTag(h, he); 01565 } 01566 01567 static int changelognameTag(Header h, HE_t he) 01568 /*@modifies he @*/ 01569 { 01570 he->tag = RPMTAG_CHANGELOGNAME; 01571 return localeTag(h, he); 01572 } 01573 01574 static int changelogtextTag(Header h, HE_t he) 01575 /*@modifies he @*/ 01576 { 01577 he->tag = RPMTAG_CHANGELOGTEXT; 01578 return localeTag(h, he); 01579 } 01580 01587 static int groupTag(Header h, HE_t he) 01588 /*@globals rpmGlobalMacroContext, h_errno @*/ 01589 /*@modifies he, rpmGlobalMacroContext @*/ 01590 { 01591 he->tag = RPMTAG_GROUP; 01592 return i18nTag(h, he); 01593 } 01594 01601 /*@-globuse@*/ 01602 static int dbinstanceTag(Header h, HE_t he) 01603 /*@globals rpmGlobalMacroContext, h_errno, 01604 fileSystem, internalState @*/ 01605 /*@modifies he, rpmGlobalMacroContext, 01606 fileSystem, internalState @*/ 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 /*@=globuse@*/ 01617 01624 /*@-globuse@*/ 01625 static int headerstartoffTag(Header h, HE_t he) 01626 /*@globals rpmGlobalMacroContext, h_errno, 01627 fileSystem, internalState @*/ 01628 /*@modifies he, rpmGlobalMacroContext, 01629 fileSystem, internalState @*/ 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 /*@=globuse@*/ 01640 01647 /*@-globuse@*/ 01648 static int headerendoffTag(Header h, HE_t he) 01649 /*@globals rpmGlobalMacroContext, h_errno, 01650 fileSystem, internalState @*/ 01651 /*@modifies he, rpmGlobalMacroContext, 01652 fileSystem, internalState @*/ 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 /*@=globuse@*/ 01663 01670 /*@-globuse@*/ 01671 static int pkgoriginTag(Header h, HE_t he) 01672 /*@globals rpmGlobalMacroContext, h_errno, 01673 fileSystem, internalState @*/ 01674 /*@modifies he, rpmGlobalMacroContext, 01675 fileSystem, internalState @*/ 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 /*@=globuse@*/ 01691 01698 /*@-globuse@*/ 01699 static int pkgbaseurlTag(Header h, HE_t he) 01700 /*@globals rpmGlobalMacroContext, h_errno, 01701 fileSystem, internalState @*/ 01702 /*@modifies he, rpmGlobalMacroContext, 01703 fileSystem, internalState @*/ 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 /*@=globuse@*/ 01721 01728 /*@-globuse@*/ 01729 static int pkgdigestTag(Header h, HE_t he) 01730 /*@globals rpmGlobalMacroContext, h_errno, 01731 fileSystem, internalState @*/ 01732 /*@modifies he, rpmGlobalMacroContext, 01733 fileSystem, internalState @*/ 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 /*@=globuse@*/ 01750 01757 /*@-globuse@*/ 01758 static int pkgmtimeTag(Header h, HE_t he) 01759 /*@globals rpmGlobalMacroContext, h_errno, 01760 fileSystem, internalState @*/ 01761 /*@modifies he, rpmGlobalMacroContext, 01762 fileSystem, internalState @*/ 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 /*@=globuse@*/ 01774 01781 /*@-globuse@*/ 01782 static int pkgsizeTag(Header h, HE_t he) 01783 /*@globals rpmGlobalMacroContext, h_errno, 01784 fileSystem, internalState @*/ 01785 /*@modifies he, rpmGlobalMacroContext, 01786 fileSystem, internalState @*/ 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 /*@=globuse@*/ 01798 01804 /*@only@*/ 01805 static char * hGetNVRA(Header h) 01806 /*@modifies h @*/ 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 /*@-globuse@*/ 01837 static int nvraTag(Header h, HE_t he) 01838 /*@globals rpmGlobalMacroContext, h_errno, 01839 fileSystem, internalState @*/ 01840 /*@modifies h, he, rpmGlobalMacroContext, 01841 fileSystem, internalState @*/ 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 /*@=globuse@*/ 01850 01857 static int _fnTag(Header h, HE_t he) 01858 /*@modifies he @*/ 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 /*@modifies he @*/ 01868 { 01869 he->tag = RPMTAG_BASENAMES; 01870 return _fnTag(h, he); 01871 } 01872 01873 static int origpathsTag(Header h, HE_t he) 01874 /*@modifies he @*/ 01875 { 01876 he->tag = RPMTAG_ORIGBASENAMES; 01877 return _fnTag(h, he); 01878 } 01879 01886 static int fsnamesTag( /*@unused@*/ Header h, HE_t he) 01887 /*@globals fileSystem, internalState @*/ 01888 /*@modifies he, fileSystem, internalState @*/ 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 /*@globals rpmGlobalMacroContext, h_errno, 01910 fileSystem, internalState @*/ 01911 /*@modifies he, rpmGlobalMacroContext, 01912 fileSystem, internalState @*/ 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; /* assume error */ 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 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01957 /*@modifies h, he, 01958 rpmGlobalMacroContext, fileSystem, internalState @*/ 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 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01974 /*@modifies h, he, 01975 rpmGlobalMacroContext, fileSystem, internalState @*/ 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 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01991 /*@modifies h, he, 01992 rpmGlobalMacroContext, fileSystem, internalState @*/ 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 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 02008 /*@modifies h, he, 02009 rpmGlobalMacroContext, fileSystem, internalState @*/ 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 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 02025 /*@modifies h, he, 02026 rpmGlobalMacroContext, fileSystem, internalState @*/ 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 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 02042 /*@modifies h, he, 02043 rpmGlobalMacroContext, fileSystem, internalState @*/ 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 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 02059 /*@modifies h, he, 02060 rpmGlobalMacroContext, fileSystem, internalState @*/ 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 /* Collect dependencies marked as hints. */ 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); /* final argv NULL */ 02087 02088 /* Create contiguous header string array. */ 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 /* XXX perhaps return "(none)" inband if no suggests/enhances <shrug>. */ 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 /*@modifies he @*/ 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; /* assume failure */ 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); /* XXX hack: leave slop */ 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 /*@modifies he @*/ 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 /*@modifies he @*/ 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 /*@modifies he @*/ 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 /*@modifies he @*/ 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; /*@fallthrough@*/ 02273 default: len += 1; /*@switchbreak@*/ break; 02274 } 02275 } 02276 return len; 02277 } 02278 02285 static char * sqlstrcpy(/*@returned@*/ char * t, const char * s) 02286 /*@modifies t @*/ 02287 { 02288 char * te = t; 02289 int c; 02290 02291 while ((c = (int) *s++) != (int) '\0') { 02292 switch (c) { 02293 case '\'': *te++ = (char) c; /*@fallthrough@*/ 02294 default: *te++ = (char) c; /*@switchbreak@*/ break; 02295 } 02296 } 02297 *te = '\0'; 02298 return t; 02299 } 02300 02307 static /*@only@*/ char * sqlescapeFormat(HE_t he, /*@null@*/ 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 /*@-globstate@*/ 02328 return val; 02329 /*@=globstate@*/ 02330 } 02331 02332 static int PRCOsqlTag(Header h, HE_t he, rpmTag EVRtag, rpmTag Ftag) 02333 /*@modifies he @*/ 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; /* assume failure */ 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); /* XXX hack: leave slop */ 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 /*@modifies he @*/ 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 /*@modifies he @*/ 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 /*@modifies he @*/ 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 /*@modifies he @*/ 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 /*@modifies he @*/ 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; /* assume failure */ 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) /* XXX RPMFILE_GHOST */ 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 /* FIXME: Files, then dirs, finally ghosts breaks sort order. */ 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) /* XXX RPMFILE_GHOST */ 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) /* XXX RPMFILE_GHOST */ 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)) /* XXX RPMFILE_GHOST */ 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 /*@modifies he @*/ 02589 { 02590 he->tag = RPMTAG_BASENAMES; 02591 return FDGxmlTag(h, he, 1); 02592 } 02593 02594 static int F2xmlTag(Header h, HE_t he) 02595 /*@modifies he @*/ 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 /*@modifies he @*/ 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; /* assume failure */ 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) /* XXX RPMFILE_GHOST */ 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 /* FIXME: Files, then dirs, finally ghosts breaks sort order. */ 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) /* XXX RPMFILE_GHOST */ 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) /* XXX RPMFILE_GHOST */ 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)) /* XXX RPMFILE_GHOST */ 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 /*@modifies he @*/ 02722 { 02723 he->tag = RPMTAG_BASENAMES; 02724 return FDGsqlTag(h, he, 1); 02725 } 02726 02727 static int F2sqlTag(Header h, HE_t he) 02728 /*@modifies he @*/ 02729 { 02730 he->tag = RPMTAG_BASENAMES; 02731 return FDGsqlTag(h, he, 2); 02732 } 02733 02740 static /*@only@*/ char * bncdataFormat(HE_t he, /*@null@*/ 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 /* Get rightmost '/' in string (i.e. basename(3) behavior). */ 02754 if ((bn = strrchr(he->p.str, '/')) != NULL) 02755 bn++; 02756 else 02757 bn = he->p.str; 02758 02759 /* Convert to utf8, escape for XML CDATA. */ 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 /*@-globstate@*/ 02769 return val; 02770 /*@=globstate@*/ 02771 } 02772 02773 typedef struct key_s { 02774 /*@observer@*/ 02775 const char *name; /* key name */ 02776 uint32_t value; 02777 } KEY; 02778 02779 /*@unchecked@*/ /*@observer@*/ 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 /*@unchecked@*/ 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 /*@unchecked@*/ /*@observer@*/ 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 /*@unchecked@*/ 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 /*@unchecked@*/ /*@observer@*/ 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 /*@unchecked@*/ 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, /*@null@*/ 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 /*@only@*/ char * digestFormat(HE_t he, /*@null@*/ 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 /*@notreached@*/ 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 /*@-globstate@*/ 02980 return val; 02981 /*@=globstate@*/ 02982 } 02983 02990 static /*@only@*/ char * statFormat(HE_t he, /*@null@*/ const char ** av) 02991 /*@*/ 02992 { 02993 /*@unchecked@*/ 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 /* XXX limit to RPMTAG_PACKAGESTAT ... */ 03006 if (he->tag == RPMTAG_PACKAGESTAT) 03007 if (he->c == sizeof(*st)) { 03008 st = (struct stat *)he->p.ptr; 03009 break; 03010 } 03011 /*@fallthrough @*/ 03012 default: 03013 val = xstrdup(_("(invalid type :stat)")); 03014 goto exit; 03015 /*@notreached@*/ 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 /*@notreached@*/ 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 /*@-globstate@*/ 03142 return val; 03143 /*@=globstate@*/ 03144 } 03145 03152 static /*@only@*/ char * uuidFormat(HE_t he, /*@null@*/ const char ** av) 03153 /*@*/ 03154 { 03155 /*@unchecked@*/ 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 /*@notreached@*/ 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 /* XXX use private tag container to avoid memory issues for now. */ 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 /*@-globstate@*/ 03204 return val; 03205 /*@=globstate@*/ 03206 } 03207 03214 static /*@only@*/ char * rpnFormat(HE_t he, /*@null@*/ 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 /*@notreached@*/ 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 /* do nothing */ 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 /*@-globstate@*/ 03302 return val; 03303 /*@=globstate@*/ 03304 } 03305 03306 /*@-type@*/ /* FIX: cast? */ 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 /*@=type@*/