lib/formats.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 #include "rpmio_internal.h"
00007 #include <rpmlib.h>
00008 #include <rpmmacro.h>   /* XXX for %_i18ndomains */
00009 
00010 #include <rpmfi.h>
00011 
00012 #include "legacy.h"
00013 #include "manifest.h"
00014 #include "misc.h"
00015 
00016 #include "debug.h"
00017 
00018 /*@access pgpDig @*/
00019 /*@access pgpDigParams @*/
00020 
00030 static /*@only@*/ char * triggertypeFormat(int_32 type, const void * data, 
00031                 /*@unused@*/ char * formatPrefix, /*@unused@*/ int padding,
00032                 /*@unused@*/ int element)
00033         /*@requires maxRead(data) >= 0 @*/
00034 {
00035     const int_32 * item = data;
00036     char * val;
00037 
00038     if (type != RPM_INT32_TYPE)
00039         val = xstrdup(_("(not a number)"));
00040     else if (*item & RPMSENSE_TRIGGERPREIN)
00041         val = xstrdup("prein");
00042     else if (*item & RPMSENSE_TRIGGERIN)
00043         val = xstrdup("in");
00044     else if (*item & RPMSENSE_TRIGGERUN)
00045         val = xstrdup("un");
00046     else if (*item & RPMSENSE_TRIGGERPOSTUN)
00047         val = xstrdup("postun");
00048     else
00049         val = xstrdup("");
00050     return val;
00051 }
00052 
00062 static /*@only@*/ char * permsFormat(int_32 type, const void * data,
00063                 char * formatPrefix, int padding, /*@unused@*/ int element)
00064         /*@modifies formatPrefix @*/
00065         /*@requires maxRead(data) >= 0 @*/
00066 {
00067     char * val;
00068     char * buf;
00069 
00070     if (type != RPM_INT32_TYPE) {
00071         val = xstrdup(_("(not a number)"));
00072     } else {
00073         val = xmalloc(15 + padding);
00074 /*@-boundswrite@*/
00075         strcat(formatPrefix, "s");
00076 /*@=boundswrite@*/
00077         buf = rpmPermsString(*((int_32 *) data));
00078         /*@-formatconst@*/
00079         sprintf(val, formatPrefix, buf);
00080         /*@=formatconst@*/
00081         buf = _free(buf);
00082     }
00083 
00084     return val;
00085 }
00086 
00096 static /*@only@*/ char * fflagsFormat(int_32 type, const void * data, 
00097                 char * formatPrefix, int padding, /*@unused@*/ int element)
00098         /*@modifies formatPrefix @*/
00099         /*@requires maxRead(data) >= 0 @*/
00100 {
00101     char * val;
00102     char buf[15];
00103     int anint = *((int_32 *) data);
00104 
00105     if (type != RPM_INT32_TYPE) {
00106         val = xstrdup(_("(not a number)"));
00107     } else {
00108         buf[0] = '\0';
00109 /*@-boundswrite@*/
00110         if (anint & RPMFILE_DOC)
00111             strcat(buf, "d");
00112         if (anint & RPMFILE_CONFIG)
00113             strcat(buf, "c");
00114         if (anint & RPMFILE_SPECFILE)
00115             strcat(buf, "s");
00116         if (anint & RPMFILE_MISSINGOK)
00117             strcat(buf, "m");
00118         if (anint & RPMFILE_NOREPLACE)
00119             strcat(buf, "n");
00120         if (anint & RPMFILE_GHOST)
00121             strcat(buf, "g");
00122         if (anint & RPMFILE_LICENSE)
00123             strcat(buf, "l");
00124         if (anint & RPMFILE_README)
00125             strcat(buf, "r");
00126 /*@=boundswrite@*/
00127 
00128         val = xmalloc(5 + padding);
00129 /*@-boundswrite@*/
00130         strcat(formatPrefix, "s");
00131 /*@=boundswrite@*/
00132         /*@-formatconst@*/
00133         sprintf(val, formatPrefix, buf);
00134         /*@=formatconst@*/
00135     }
00136 
00137     return val;
00138 }
00139 
00150 static /*@only@*/ char * armorFormat(int_32 type, const void * data, 
00151                 /*@unused@*/ char * formatPrefix, /*@unused@*/ int padding,
00152                 int element)
00153         /*@*/
00154 {
00155     const char * enc;
00156     const unsigned char * s;
00157     size_t ns;
00158     int atype;
00159 
00160     switch (type) {
00161     case RPM_BIN_TYPE:
00162         s = data;
00163         /* XXX HACK ALERT: element field abused as no. bytes of binary data. */
00164         ns = element;
00165         atype = PGPARMOR_SIGNATURE;     /* XXX check pkt for signature */
00166         break;
00167     case RPM_STRING_TYPE:
00168     case RPM_STRING_ARRAY_TYPE:
00169         enc = data;
00170         if (b64decode(enc, (void **)&s, &ns))
00171             return xstrdup(_("(not base64)"));
00172         atype = PGPARMOR_PUBKEY;        /* XXX check pkt for pubkey */
00173         break;
00174     case RPM_NULL_TYPE:
00175     case RPM_CHAR_TYPE:
00176     case RPM_INT8_TYPE:
00177     case RPM_INT16_TYPE:
00178     case RPM_INT32_TYPE:
00179     case RPM_I18NSTRING_TYPE:
00180     default:
00181         return xstrdup(_("(invalid type)"));
00182         /*@notreached@*/ break;
00183     }
00184 
00185     /* XXX this doesn't use padding directly, assumes enough slop in retval. */
00186     return pgpArmorWrap(atype, s, ns);
00187 }
00188 
00199 static /*@only@*/ char * base64Format(int_32 type, const void * data, 
00200                 /*@unused@*/ char * formatPrefix, int padding, int element)
00201         /*@*/
00202 {
00203     char * val;
00204 
00205     if (type != RPM_BIN_TYPE) {
00206         val = xstrdup(_("(not a blob)"));
00207     } else {
00208         const char * enc;
00209         char * t;
00210         int lc;
00211         /* XXX HACK ALERT: element field abused as no. bytes of binary data. */
00212         size_t ns = element;
00213         size_t nt = ((ns + 2) / 3) * 4;
00214 
00215 /*@-boundswrite@*/
00216         /*@-globs@*/
00217         /* Add additional bytes necessary for eol string(s). */
00218         if (b64encode_chars_per_line > 0 && b64encode_eolstr != NULL) {
00219             lc = (nt + b64encode_chars_per_line - 1) / b64encode_chars_per_line;
00220         if (((nt + b64encode_chars_per_line - 1) % b64encode_chars_per_line) != 0)
00221             ++lc;
00222             nt += lc * strlen(b64encode_eolstr);
00223         }
00224         /*@=globs@*/
00225 
00226         val = t = xmalloc(nt + padding + 1);
00227 
00228         *t = '\0';
00229         if ((enc = b64encode(data, ns)) != NULL) {
00230             t = stpcpy(t, enc);
00231             enc = _free(enc);
00232         }
00233 /*@=boundswrite@*/
00234     }
00235 
00236     return val;
00237 }
00238 
00241 static size_t xmlstrlen(const char * s)
00242         /*@*/
00243 {
00244     size_t len = 0;
00245     int c;
00246 
00247 /*@-boundsread@*/
00248     while ((c = *s++) != '\0')
00249 /*@=boundsread@*/
00250     {
00251         switch (c) {
00252         case '<': case '>':     len += 4;       /*@switchbreak@*/ break;
00253         case '&':               len += 5;       /*@switchbreak@*/ break;
00254         default:                len += 1;       /*@switchbreak@*/ break;
00255         }
00256     }
00257     return len;
00258 }
00259 
00262 static char * xmlstrcpy(/*@returned@*/ char * t, const char * s)
00263         /*@modifies t @*/
00264 {
00265     char * te = t;
00266     int c;
00267 
00268 /*@-bounds@*/
00269     while ((c = *s++) != '\0') {
00270         switch (c) {
00271         case '<':       te = stpcpy(te, "&lt;");        /*@switchbreak@*/ break;
00272         case '>':       te = stpcpy(te, "&gt;");        /*@switchbreak@*/ break;
00273         case '&':       te = stpcpy(te, "&amp;");       /*@switchbreak@*/ break;
00274         default:        *te++ = c;                      /*@switchbreak@*/ break;
00275         }
00276     }
00277     *te = '\0';
00278 /*@=bounds@*/
00279     return t;
00280 }
00281 
00291 /*@-bounds@*/
00292 static /*@only@*/ char * xmlFormat(int_32 type, const void * data, 
00293                 char * formatPrefix, int padding,
00294                 /*@unused@*/ int element)
00295         /*@modifies formatPrefix @*/
00296 {
00297     const char * xtag = NULL;
00298     size_t nb;
00299     char * val;
00300     const char * s = NULL;
00301     char * t, * te;
00302     unsigned long anint = 0;
00303     int xx;
00304     int freeit = 0;
00305 
00306 /*@-branchstate@*/
00307     switch (type) {
00308     case RPM_I18NSTRING_TYPE:
00309     case RPM_STRING_TYPE:
00310         s = data;
00311         xtag = "string";
00312         /* XXX Force utf8 strings. */
00313         s = xstrdup(s);
00314         s = xstrtolocale(s);
00315         freeit = 1;
00316         break;
00317     case RPM_BIN_TYPE:
00318     {   int cpl = b64encode_chars_per_line;
00319 /*@-mods@*/
00320         b64encode_chars_per_line = 0;
00321 /*@=mods@*/
00322 /*@-formatconst@*/
00323         s = base64Format(type, data, formatPrefix, padding, element);
00324 /*@=formatconst@*/
00325 /*@-mods@*/
00326         b64encode_chars_per_line = cpl;
00327 /*@=mods@*/
00328         xtag = "base64";
00329         freeit = 1;
00330     }   break;
00331     case RPM_CHAR_TYPE:
00332     case RPM_INT8_TYPE:
00333         anint = *((uint_8 *) data);
00334         break;
00335     case RPM_INT16_TYPE:
00336         anint = *((uint_16 *) data);
00337         break;
00338     case RPM_INT32_TYPE:
00339         anint = *((uint_32 *) data);
00340         break;
00341     case RPM_NULL_TYPE:
00342     case RPM_STRING_ARRAY_TYPE:
00343     default:
00344         return xstrdup(_("(invalid xml type)"));
00345         /*@notreached@*/ break;
00346     }
00347 /*@=branchstate@*/
00348 
00349 /*@-branchstate@*/
00350     if (s == NULL) {
00351         int tlen = 32;
00352         t = memset(alloca(tlen+1), 0, tlen+1);
00353         if (anint != 0)
00354             xx = snprintf(t, tlen, "%lu", anint);
00355         s = t;
00356         xtag = "integer";
00357     }
00358 /*@=branchstate@*/
00359 
00360     nb = xmlstrlen(s);
00361     if (nb == 0) {
00362         nb += strlen(xtag) + sizeof("\t</>");
00363         te = t = alloca(nb);
00364         te = stpcpy( stpcpy( stpcpy(te, "\t<"), xtag), "/>");
00365     } else {
00366         nb += 2 * strlen(xtag) + sizeof("\t<></>");
00367         te = t = alloca(nb);
00368         te = stpcpy( stpcpy( stpcpy(te, "\t<"), xtag), ">");
00369         te = xmlstrcpy(te, s);
00370         te += strlen(te);
00371         te = stpcpy( stpcpy( stpcpy(te, "</"), xtag), ">");
00372     }
00373 
00374     /* XXX s was malloc'd */
00375 /*@-branchstate@*/
00376     if (freeit)
00377         s = _free(s);
00378 /*@=branchstate@*/
00379 
00380     nb += padding;
00381     val = xmalloc(nb+1);
00382 /*@-boundswrite@*/
00383     strcat(formatPrefix, "s");
00384 /*@=boundswrite@*/
00385 /*@-formatconst@*/
00386     xx = snprintf(val, nb, formatPrefix, t);
00387 /*@=formatconst@*/
00388     val[nb] = '\0';
00389 
00390     return val;
00391 }
00392 /*@=bounds@*/
00393 
00403 static /*@only@*/ char * pgpsigFormat(int_32 type, const void * data, 
00404                 /*@unused@*/ char * formatPrefix, /*@unused@*/ int padding,
00405                 /*@unused@*/ int element)
00406         /*@globals fileSystem, internalState @*/
00407         /*@modifies fileSystem, internalState @*/
00408 {
00409     char * val, * t;
00410 
00411     if (type != RPM_BIN_TYPE) {
00412         val = xstrdup(_("(not a blob)"));
00413     } else {
00414         unsigned char * pkt = (byte *) data;
00415         unsigned int pktlen = 0;
00416 /*@-boundsread@*/
00417         unsigned int v = *pkt;
00418 /*@=boundsread@*/
00419         pgpTag tag = 0;
00420         unsigned int plen;
00421         unsigned int hlen = 0;
00422 
00423         if (v & 0x80) {
00424             if (v & 0x40) {
00425                 tag = (v & 0x3f);
00426                 plen = pgpLen(pkt+1, &hlen);
00427             } else {
00428                 tag = (v >> 2) & 0xf;
00429                 plen = (1 << (v & 0x3));
00430                 hlen = pgpGrab(pkt+1, plen);
00431             }
00432         
00433             pktlen = 1 + plen + hlen;
00434         }
00435 
00436         if (pktlen == 0 || tag != PGPTAG_SIGNATURE) {
00437             val = xstrdup(_("(not an OpenPGP signature)"));
00438         } else {
00439             pgpDig dig = pgpNewDig();
00440             pgpDigParams sigp = &dig->signature;
00441             size_t nb = 0;
00442             const char *tempstr;
00443 
00444             (void) pgpPrtPkts(pkt, pktlen, dig, 0);
00445 
00446             val = NULL;
00447         again:
00448             nb += 100;
00449             val = t = xrealloc(val, nb + 1);
00450 
00451 /*@-boundswrite@*/
00452             switch (sigp->pubkey_algo) {
00453             case PGPPUBKEYALGO_DSA:
00454                 t = stpcpy(t, "DSA");
00455                 break;
00456             case PGPPUBKEYALGO_RSA:
00457                 t = stpcpy(t, "RSA");
00458                 break;
00459             default:
00460                 (void) snprintf(t, nb - (t - val), "%d", sigp->pubkey_algo);
00461                 t += strlen(t);
00462                 break;
00463             }
00464             if (t + 5 >= val + nb)
00465                 goto again;
00466             *t++ = '/';
00467             switch (sigp->hash_algo) {
00468             case PGPHASHALGO_MD5:
00469                 t = stpcpy(t, "MD5");
00470                 break;
00471             case PGPHASHALGO_SHA1:
00472                 t = stpcpy(t, "SHA1");
00473                 break;
00474             default:
00475                 (void) snprintf(t, nb - (t - val), "%d", sigp->hash_algo);
00476                 t += strlen(t);
00477                 break;
00478             }
00479             if (t + strlen (", ") + 1 >= val + nb)
00480                 goto again;
00481 
00482             t = stpcpy(t, ", ");
00483 
00484             /* this is important if sizeof(int_32) ! sizeof(time_t) */
00485             {   time_t dateint = pgpGrab(sigp->time, sizeof(sigp->time));
00486                 struct tm * tstruct = localtime(&dateint);
00487                 if (tstruct)
00488                     (void) strftime(t, (nb - (t - val)), "%c", tstruct);
00489             }
00490             t += strlen(t);
00491             if (t + strlen (", Key ID ") + 1 >= val + nb)
00492                 goto again;
00493             t = stpcpy(t, ", Key ID ");
00494             tempstr = pgpHexStr(sigp->signid, sizeof(sigp->signid));
00495             if (t + strlen (tempstr) > val + nb)
00496                 goto again;
00497             t = stpcpy(t, tempstr);
00498 /*@=boundswrite@*/
00499 
00500             dig = pgpFreeDig(dig);
00501         }
00502     }
00503 
00504     return val;
00505 }
00506 
00516 static /*@only@*/ char * depflagsFormat(int_32 type, const void * data, 
00517                 char * formatPrefix, int padding, /*@unused@*/ int element)
00518         /*@modifies formatPrefix @*/
00519         /*@requires maxRead(data) >= 0 @*/
00520 {
00521     char * val;
00522     char buf[10];
00523     int anint;
00524 
00525     if (type != RPM_INT32_TYPE) {
00526         val = xstrdup(_("(not a number)"));
00527     } else {
00528         anint = *((int_32 *) data);
00529         buf[0] = '\0';
00530 
00531 /*@-boundswrite@*/
00532         if (anint & RPMSENSE_LESS) 
00533             strcat(buf, "<");
00534         if (anint & RPMSENSE_GREATER)
00535             strcat(buf, ">");
00536         if (anint & RPMSENSE_EQUAL)
00537             strcat(buf, "=");
00538 /*@=boundswrite@*/
00539 
00540         val = xmalloc(5 + padding);
00541 /*@-boundswrite@*/
00542         strcat(formatPrefix, "s");
00543 /*@=boundswrite@*/
00544         /*@-formatconst@*/
00545         sprintf(val, formatPrefix, buf);
00546         /*@=formatconst@*/
00547     }
00548 
00549     return val;
00550 }
00551 
00561 static int fsnamesTag( /*@unused@*/ Header h, /*@out@*/ int_32 * type,
00562                 /*@out@*/ void ** data, /*@out@*/ int_32 * count,
00563                 /*@out@*/ int * freeData)
00564         /*@globals fileSystem, internalState @*/
00565         /*@modifies *type, *data, *count, *freeData,
00566                 fileSystem, internalState @*/
00567         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00568                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00569 {
00570     const char ** list;
00571 
00572 /*@-boundswrite@*/
00573     if (rpmGetFilesystemList(&list, count))
00574         return 1;
00575 /*@=boundswrite@*/
00576 
00577     if (type) *type = RPM_STRING_ARRAY_TYPE;
00578     if (data) *((const char ***) data) = list;
00579     if (freeData) *freeData = 0;
00580 
00581     return 0; 
00582 }
00583 
00593 static int instprefixTag(Header h, /*@null@*/ /*@out@*/ rpmTagType * type,
00594                 /*@null@*/ /*@out@*/ const void ** data,
00595                 /*@null@*/ /*@out@*/ int_32 * count,
00596                 /*@null@*/ /*@out@*/ int * freeData)
00597         /*@modifies *type, *data, *freeData @*/
00598         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00599                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00600 {
00601     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00602     HFD_t hfd = headerFreeData;
00603     rpmTagType ipt;
00604     char ** array;
00605 
00606     if (hge(h, RPMTAG_INSTALLPREFIX, type, (void **)data, count)) {
00607         if (freeData) *freeData = 0;
00608         return 0;
00609     } else if (hge(h, RPMTAG_INSTPREFIXES, &ipt, (void **) &array, count)) {
00610         if (type) *type = RPM_STRING_TYPE;
00611 /*@-boundsread@*/
00612         if (data) *data = xstrdup(array[0]);
00613 /*@=boundsread@*/
00614         if (freeData) *freeData = 1;
00615         array = hfd(array, ipt);
00616         return 0;
00617     }
00618 
00619     return 1;
00620 }
00621 
00631 static int fssizesTag(Header h, /*@out@*/ rpmTagType * type,
00632                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00633                 /*@out@*/ int * freeData)
00634         /*@globals rpmGlobalMacroContext, h_errno,
00635                 fileSystem, internalState @*/
00636         /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext,
00637                 fileSystem, internalState @*/
00638         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00639                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00640 {
00641     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00642     const char ** filenames;
00643     int_32 * filesizes;
00644     uint_32 * usages;
00645     int numFiles;
00646 
00647     if (!hge(h, RPMTAG_FILESIZES, NULL, (void **) &filesizes, &numFiles)) {
00648         filesizes = NULL;
00649         numFiles = 0;
00650         filenames = NULL;
00651     } else {
00652         rpmfiBuildFNames(h, RPMTAG_BASENAMES, &filenames, &numFiles);
00653     }
00654 
00655 /*@-boundswrite@*/
00656     if (rpmGetFilesystemList(NULL, count))
00657         return 1;
00658 /*@=boundswrite@*/
00659 
00660     *type = RPM_INT32_TYPE;
00661     *freeData = 1;
00662 
00663     if (filenames == NULL) {
00664         usages = xcalloc((*count), sizeof(usages));
00665         *data = usages;
00666 
00667         return 0;
00668     }
00669 
00670 /*@-boundswrite@*/
00671     if (rpmGetFilesystemUsage(filenames, filesizes, numFiles, &usages, 0))      
00672         return 1;
00673 /*@=boundswrite@*/
00674 
00675     *data = usages;
00676 
00677     filenames = _free(filenames);
00678 
00679     return 0;
00680 }
00681 
00691 static int triggercondsTag(Header h, /*@out@*/ rpmTagType * type,
00692                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00693                 /*@out@*/ int * freeData)
00694         /*@modifies *type, *data, *count, *freeData @*/
00695         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00696                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00697 {
00698     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00699     HFD_t hfd = headerFreeData;
00700     rpmTagType tnt, tvt, tst;
00701     int_32 * indices, * flags;
00702     char ** names, ** versions;
00703     int numNames, numScripts;
00704     char ** conds, ** s;
00705     char * item, * flagsStr;
00706     char * chptr;
00707     int i, j, xx;
00708     char buf[5];
00709 
00710     if (!hge(h, RPMTAG_TRIGGERNAME, &tnt, (void **) &names, &numNames)) {
00711         *freeData = 0;
00712         return 0;
00713     }
00714 
00715     xx = hge(h, RPMTAG_TRIGGERINDEX, NULL, (void **) &indices, NULL);
00716     xx = hge(h, RPMTAG_TRIGGERFLAGS, NULL, (void **) &flags, NULL);
00717     xx = hge(h, RPMTAG_TRIGGERVERSION, &tvt, (void **) &versions, NULL);
00718     xx = hge(h, RPMTAG_TRIGGERSCRIPTS, &tst, (void **) &s, &numScripts);
00719     s = hfd(s, tst);
00720 
00721     *freeData = 1;
00722     *data = conds = xmalloc(sizeof(*conds) * numScripts);
00723     *count = numScripts;
00724     *type = RPM_STRING_ARRAY_TYPE;
00725 /*@-bounds@*/
00726     for (i = 0; i < numScripts; i++) {
00727         chptr = xstrdup("");
00728 
00729         for (j = 0; j < numNames; j++) {
00730             if (indices[j] != i)
00731                 /*@innercontinue@*/ continue;
00732 
00733             item = xmalloc(strlen(names[j]) + strlen(versions[j]) + 20);
00734             if (flags[j] & RPMSENSE_SENSEMASK) {
00735                 buf[0] = '%', buf[1] = '\0';
00736                 flagsStr = depflagsFormat(RPM_INT32_TYPE, flags, buf, 0, j);
00737                 sprintf(item, "%s %s %s", names[j], flagsStr, versions[j]);
00738                 flagsStr = _free(flagsStr);
00739             } else {
00740                 strcpy(item, names[j]);
00741             }
00742 
00743             chptr = xrealloc(chptr, strlen(chptr) + strlen(item) + 5);
00744             if (*chptr != '\0') strcat(chptr, ", ");
00745             strcat(chptr, item);
00746             item = _free(item);
00747         }
00748 
00749         conds[i] = chptr;
00750     }
00751 /*@=bounds@*/
00752 
00753     names = hfd(names, tnt);
00754     versions = hfd(versions, tvt);
00755 
00756     return 0;
00757 }
00758 
00768 static int triggertypeTag(Header h, /*@out@*/ rpmTagType * type,
00769                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00770                 /*@out@*/ int * freeData)
00771         /*@modifies *type, *data, *count, *freeData @*/
00772         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00773                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00774 {
00775     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00776     HFD_t hfd = headerFreeData;
00777     rpmTagType tst;
00778     int_32 * indices, * flags;
00779     const char ** conds;
00780     const char ** s;
00781     int i, j, xx;
00782     int numScripts, numNames;
00783 
00784     if (!hge(h, RPMTAG_TRIGGERINDEX, NULL, (void **) &indices, &numNames)) {
00785         *freeData = 0;
00786         return 1;
00787     }
00788 
00789     xx = hge(h, RPMTAG_TRIGGERFLAGS, NULL, (void **) &flags, NULL);
00790     xx = hge(h, RPMTAG_TRIGGERSCRIPTS, &tst, (void **) &s, &numScripts);
00791     s = hfd(s, tst);
00792 
00793     *freeData = 1;
00794     *data = conds = xmalloc(sizeof(*conds) * numScripts);
00795     *count = numScripts;
00796     *type = RPM_STRING_ARRAY_TYPE;
00797 /*@-bounds@*/
00798     for (i = 0; i < numScripts; i++) {
00799         for (j = 0; j < numNames; j++) {
00800             if (indices[j] != i)
00801                 /*@innercontinue@*/ continue;
00802 
00803             if (flags[j] & RPMSENSE_TRIGGERPREIN)
00804                 conds[i] = xstrdup("prein");
00805             else if (flags[j] & RPMSENSE_TRIGGERIN)
00806                 conds[i] = xstrdup("in");
00807             else if (flags[j] & RPMSENSE_TRIGGERUN)
00808                 conds[i] = xstrdup("un");
00809             else if (flags[j] & RPMSENSE_TRIGGERPOSTUN)
00810                 conds[i] = xstrdup("postun");
00811             else
00812                 conds[i] = xstrdup("");
00813             /*@innerbreak@*/ break;
00814         }
00815     }
00816 /*@=bounds@*/
00817 
00818     return 0;
00819 }
00820 
00830 static int filenamesTag(Header h, /*@out@*/ rpmTagType * type,
00831                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00832                 /*@out@*/ int * freeData)
00833         /*@modifies *type, *data, *count, *freeData @*/
00834         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00835                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00836 {
00837     *type = RPM_STRING_ARRAY_TYPE;
00838     rpmfiBuildFNames(h, RPMTAG_BASENAMES, (const char ***) data, count);
00839     *freeData = 1;
00840     return 0; 
00841 }
00842 
00852 static int fileclassTag(Header h, /*@out@*/ rpmTagType * type,
00853                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00854                 /*@out@*/ int * freeData)
00855         /*@globals rpmGlobalMacroContext, h_errno, fileSystem @*/
00856         /*@modifies h, *type, *data, *count, *freeData,
00857                 rpmGlobalMacroContext, fileSystem @*/
00858         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00859                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00860 {
00861     *type = RPM_STRING_ARRAY_TYPE;
00862     rpmfiBuildFClasses(h, (const char ***) data, count);
00863     *freeData = 1;
00864     return 0; 
00865 }
00866 
00876 static int filecontextsTag(Header h, /*@out@*/ rpmTagType * type,
00877                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00878                 /*@out@*/ int * freeData)
00879         /*@globals rpmGlobalMacroContext, h_errno, fileSystem @*/
00880         /*@modifies h, *type, *data, *count, *freeData,
00881                 rpmGlobalMacroContext, fileSystem @*/
00882         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00883                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00884 {
00885     *type = RPM_STRING_ARRAY_TYPE;
00886     rpmfiBuildFContexts(h, (const char ***) data, count);
00887     *freeData = 1;
00888     return 0; 
00889 }
00890 
00900 static int fscontextsTag(Header h, /*@out@*/ rpmTagType * type,
00901                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00902                 /*@out@*/ int * freeData)
00903         /*@globals rpmGlobalMacroContext, h_errno, fileSystem @*/
00904         /*@modifies h, *type, *data, *count, *freeData,
00905                 rpmGlobalMacroContext, fileSystem @*/
00906         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00907                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00908 {
00909     *type = RPM_STRING_ARRAY_TYPE;
00910     rpmfiBuildFSContexts(h, (const char ***) data, count);
00911     *freeData = 1;
00912     return 0; 
00913 }
00914 
00924 static int recontextsTag(Header h, /*@out@*/ rpmTagType * type,
00925                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00926                 /*@out@*/ int * freeData)
00927         /*@globals rpmGlobalMacroContext, h_errno, fileSystem @*/
00928         /*@modifies h, *type, *data, *count, *freeData,
00929                 rpmGlobalMacroContext, fileSystem @*/
00930         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00931                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00932 {
00933     *type = RPM_STRING_ARRAY_TYPE;
00934     rpmfiBuildREContexts(h, (const char ***) data, count);
00935     *freeData = 1;
00936     return 0; 
00937 }
00938 
00948 static int fileprovideTag(Header h, /*@out@*/ rpmTagType * type,
00949                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00950                 /*@out@*/ int * freeData)
00951         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00952         /*@modifies h, *type, *data, *count, *freeData,
00953                 rpmGlobalMacroContext, fileSystem, internalState @*/
00954         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00955                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00956 {
00957     *type = RPM_STRING_ARRAY_TYPE;
00958     rpmfiBuildFDeps(h, RPMTAG_PROVIDENAME, (const char ***) data, count);
00959     *freeData = 1;
00960     return 0; 
00961 }
00962 
00972 static int filerequireTag(Header h, /*@out@*/ rpmTagType * type,
00973                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00974                 /*@out@*/ int * freeData)
00975         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00976         /*@modifies h, *type, *data, *count, *freeData,
00977                 rpmGlobalMacroContext, fileSystem, internalState @*/
00978         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00979                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00980 {
00981     *type = RPM_STRING_ARRAY_TYPE;
00982     rpmfiBuildFDeps(h, RPMTAG_REQUIRENAME, (const char ***) data, count);
00983     *freeData = 1;
00984     return 0; 
00985 }
00986 
00987 /* I18N look aside diversions */
00988 
00989 #if defined(ENABLE_NLS)
00990 /*@-exportlocal -exportheadervar@*/
00991 /*@unchecked@*/
00992 extern int _nl_msg_cat_cntr;    /* XXX GNU gettext voodoo */
00993 /*@=exportlocal =exportheadervar@*/
00994 #endif
00995 /*@observer@*/ /*@unchecked@*/
00996 static const char * language = "LANGUAGE";
00997 
00998 /*@observer@*/ /*@unchecked@*/
00999 static const char * _macro_i18ndomains = "%{?_i18ndomains}";
01000 
01011 static int i18nTag(Header h, int_32 tag, /*@out@*/ rpmTagType * type,
01012                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
01013                 /*@out@*/ int * freeData)
01014         /*@globals rpmGlobalMacroContext, h_errno @*/
01015         /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
01016         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
01017                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
01018 {
01019     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
01020     char * dstring = rpmExpand(_macro_i18ndomains, NULL);
01021     int rc;
01022 
01023     *type = RPM_STRING_TYPE;
01024     *data = NULL;
01025     *count = 0;
01026     *freeData = 0;
01027 
01028     if (dstring && *dstring) {
01029         char *domain, *de;
01030         const char * langval;
01031         const char * msgkey;
01032         const char * msgid;
01033 
01034         {   const char * tn = tagName(tag);
01035             const char * n;
01036             char * mk;
01037             (void) headerNVR(h, &n, NULL, NULL);
01038             mk = alloca(strlen(n) + strlen(tn) + sizeof("()"));
01039             sprintf(mk, "%s(%s)", n, tn);
01040             msgkey = mk;
01041         }
01042 
01043         /* change to en_US for msgkey -> msgid resolution */
01044         langval = getenv(language);
01045         (void) setenv(language, "en_US", 1);
01046 #if defined(ENABLE_NLS)
01047 /*@i@*/ ++_nl_msg_cat_cntr;
01048 #endif
01049 
01050         msgid = NULL;
01051         /*@-branchstate@*/
01052         for (domain = dstring; domain != NULL; domain = de) {
01053             de = strchr(domain, ':');
01054             if (de) *de++ = '\0';
01055             msgid = /*@-unrecog@*/ dgettext(domain, msgkey) /*@=unrecog@*/;
01056             if (msgid != msgkey) break;
01057         }
01058         /*@=branchstate@*/
01059 
01060         /* restore previous environment for msgid -> msgstr resolution */
01061         if (langval)
01062             (void) setenv(language, langval, 1);
01063         else
01064             unsetenv(language);
01065 #if defined(ENABLE_NLS)
01066 /*@i@*/ ++_nl_msg_cat_cntr;
01067 #endif
01068 
01069         if (domain && msgid) {
01070             *data = /*@-unrecog@*/ dgettext(domain, msgid) /*@=unrecog@*/;
01071             *data = xstrdup(*data);     /* XXX xstrdup has side effects. */
01072             *count = 1;
01073             *freeData = 1;
01074         }
01075         dstring = _free(dstring);
01076         if (*data)
01077             return 0;
01078     }
01079 
01080     dstring = _free(dstring);
01081 
01082     rc = hge(h, tag, type, (void **)data, count);
01083 
01084     if (rc && (*data) != NULL) {
01085         *data = xstrdup(*data);
01086         *data = xstrtolocale(*data);
01087         *freeData = 1;
01088         return 0;
01089     }
01090 
01091     *freeData = 0;
01092     *data = NULL;
01093     *count = 0;
01094     return 1;
01095 }
01096 
01106 static int summaryTag(Header h, /*@out@*/ rpmTagType * type,
01107                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
01108                 /*@out@*/ int * freeData)
01109         /*@globals rpmGlobalMacroContext, h_errno @*/
01110         /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
01111         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
01112                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
01113 {
01114     return i18nTag(h, RPMTAG_SUMMARY, type, data, count, freeData);
01115 }
01116 
01126 static int descriptionTag(Header h, /*@out@*/ rpmTagType * type,
01127                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
01128                 /*@out@*/ int * freeData)
01129         /*@globals rpmGlobalMacroContext, h_errno @*/
01130         /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
01131         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
01132                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
01133 {
01134     return i18nTag(h, RPMTAG_DESCRIPTION, type, data, count, freeData);
01135 }
01136 
01146 static int groupTag(Header h, /*@out@*/ rpmTagType * type,
01147                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
01148                 /*@out@*/ int * freeData)
01149         /*@globals rpmGlobalMacroContext, h_errno @*/
01150         /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
01151         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
01152                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
01153 {
01154     return i18nTag(h, RPMTAG_GROUP, type, data, count, freeData);
01155 }
01156 
01157 /*@-type@*/ /* FIX: cast? */
01158 const struct headerSprintfExtension_s rpmHeaderFormats[] = {
01159     { HEADER_EXT_TAG, "RPMTAG_GROUP",           { groupTag } },
01160     { HEADER_EXT_TAG, "RPMTAG_DESCRIPTION",     { descriptionTag } },
01161     { HEADER_EXT_TAG, "RPMTAG_SUMMARY",         { summaryTag } },
01162     { HEADER_EXT_TAG, "RPMTAG_FILECLASS",       { fileclassTag } },
01163     { HEADER_EXT_TAG, "RPMTAG_FILECONTEXTS",    { filecontextsTag } },
01164     { HEADER_EXT_TAG, "RPMTAG_FILENAMES",       { filenamesTag } },
01165     { HEADER_EXT_TAG, "RPMTAG_FILEPROVIDE",     { fileprovideTag } },
01166     { HEADER_EXT_TAG, "RPMTAG_FILEREQUIRE",     { filerequireTag } },
01167     { HEADER_EXT_TAG, "RPMTAG_FSCONTEXTS",      { fscontextsTag } },
01168     { HEADER_EXT_TAG, "RPMTAG_FSNAMES",         { fsnamesTag } },
01169     { HEADER_EXT_TAG, "RPMTAG_FSSIZES",         { fssizesTag } },
01170     { HEADER_EXT_TAG, "RPMTAG_INSTALLPREFIX",   { instprefixTag } },
01171     { HEADER_EXT_TAG, "RPMTAG_RECONTEXTS",      { recontextsTag } },
01172     { HEADER_EXT_TAG, "RPMTAG_TRIGGERCONDS",    { triggercondsTag } },
01173     { HEADER_EXT_TAG, "RPMTAG_TRIGGERTYPE",     { triggertypeTag } },
01174     { HEADER_EXT_FORMAT, "armor",               { armorFormat } },
01175     { HEADER_EXT_FORMAT, "base64",              { base64Format } },
01176     { HEADER_EXT_FORMAT, "pgpsig",              { pgpsigFormat } },
01177     { HEADER_EXT_FORMAT, "depflags",            { depflagsFormat } },
01178     { HEADER_EXT_FORMAT, "fflags",              { fflagsFormat } },
01179     { HEADER_EXT_FORMAT, "perms",               { permsFormat } },
01180     { HEADER_EXT_FORMAT, "permissions",         { permsFormat } },
01181     { HEADER_EXT_FORMAT, "triggertype",         { triggertypeFormat } },
01182     { HEADER_EXT_FORMAT, "xml",                 { xmlFormat } },
01183     { HEADER_EXT_MORE, NULL,            { (void *) headerDefaultFormats } }
01184 } ;
01185 /*@=type@*/

Generated on Tue Feb 19 22:26:56 2008 for rpm by  doxygen 1.5.1