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 
00305 /*@-branchstate@*/
00306     switch (type) {
00307     case RPM_I18NSTRING_TYPE:
00308     case RPM_STRING_TYPE:
00309         s = data;
00310         xtag = "string";
00311         break;
00312     case RPM_BIN_TYPE:
00313     {   int cpl = b64encode_chars_per_line;
00314 /*@-mods@*/
00315         b64encode_chars_per_line = 0;
00316 /*@=mods@*/
00317 /*@-formatconst@*/
00318         s = base64Format(type, data, formatPrefix, padding, element);
00319 /*@=formatconst@*/
00320 /*@-mods@*/
00321         b64encode_chars_per_line = cpl;
00322 /*@=mods@*/
00323         xtag = "base64";
00324     }   break;
00325     case RPM_CHAR_TYPE:
00326     case RPM_INT8_TYPE:
00327         anint = *((uint_8 *) data);
00328         break;
00329     case RPM_INT16_TYPE:
00330         anint = *((uint_16 *) data);
00331         break;
00332     case RPM_INT32_TYPE:
00333         anint = *((uint_32 *) data);
00334         break;
00335     case RPM_NULL_TYPE:
00336     case RPM_STRING_ARRAY_TYPE:
00337     default:
00338         return xstrdup(_("(invalid xml type)"));
00339         /*@notreached@*/ break;
00340     }
00341 /*@=branchstate@*/
00342 
00343 /*@-branchstate@*/
00344     if (s == NULL) {
00345         int tlen = 32;
00346         t = memset(alloca(tlen+1), 0, tlen+1);
00347         if (anint != 0)
00348             xx = snprintf(t, tlen, "%lu", anint);
00349         s = t;
00350         xtag = "integer";
00351     }
00352 /*@=branchstate@*/
00353 
00354     nb = xmlstrlen(s);
00355     if (nb == 0) {
00356         nb += strlen(xtag) + sizeof("\t</>");
00357         te = t = alloca(nb);
00358         te = stpcpy( stpcpy( stpcpy(te, "\t<"), xtag), "/>");
00359     } else {
00360         nb += 2 * strlen(xtag) + sizeof("\t<></>");
00361         te = t = alloca(nb);
00362         te = stpcpy( stpcpy( stpcpy(te, "\t<"), xtag), ">");
00363         te = xmlstrcpy(te, s);
00364         te += strlen(te);
00365         te = stpcpy( stpcpy( stpcpy(te, "</"), xtag), ">");
00366     }
00367 
00368     /* XXX s was malloc'd */
00369 /*@-branchstate@*/
00370     if (!strcmp(xtag, "base64"))
00371         s = _free(s);
00372 /*@=branchstate@*/
00373 
00374     nb += padding;
00375     val = xmalloc(nb+1);
00376 /*@-boundswrite@*/
00377     strcat(formatPrefix, "s");
00378 /*@=boundswrite@*/
00379 /*@-formatconst@*/
00380     xx = snprintf(val, nb, formatPrefix, t);
00381 /*@=formatconst@*/
00382     val[nb] = '\0';
00383 
00384     return val;
00385 }
00386 /*@=bounds@*/
00387 
00397 static /*@only@*/ char * pgpsigFormat(int_32 type, const void * data, 
00398                 /*@unused@*/ char * formatPrefix, /*@unused@*/ int padding,
00399                 /*@unused@*/ int element)
00400         /*@globals fileSystem, internalState @*/
00401         /*@modifies fileSystem, internalState @*/
00402 {
00403     char * val, * t;
00404 
00405     if (type != RPM_BIN_TYPE) {
00406         val = xstrdup(_("(not a blob)"));
00407     } else {
00408         unsigned char * pkt = (byte *) data;
00409         unsigned int pktlen = 0;
00410 /*@-boundsread@*/
00411         unsigned int v = *pkt;
00412 /*@=boundsread@*/
00413         pgpTag tag = 0;
00414         unsigned int plen;
00415         unsigned int hlen = 0;
00416 
00417         if (v & 0x80) {
00418             if (v & 0x40) {
00419                 tag = (v & 0x3f);
00420                 plen = pgpLen(pkt+1, &hlen);
00421             } else {
00422                 tag = (v >> 2) & 0xf;
00423                 plen = (1 << (v & 0x3));
00424                 hlen = pgpGrab(pkt+1, plen);
00425             }
00426         
00427             pktlen = 1 + plen + hlen;
00428         }
00429 
00430         if (pktlen == 0 || tag != PGPTAG_SIGNATURE) {
00431             val = xstrdup(_("(not an OpenPGP signature)"));
00432         } else {
00433             pgpDig dig = pgpNewDig();
00434             pgpDigParams sigp = &dig->signature;
00435             size_t nb = 0;
00436             const char *tempstr;
00437 
00438             (void) pgpPrtPkts(pkt, pktlen, dig, 0);
00439 
00440             val = NULL;
00441         again:
00442             nb += 100;
00443             val = t = xrealloc(val, nb + 1);
00444 
00445 /*@-boundswrite@*/
00446             switch (sigp->pubkey_algo) {
00447             case PGPPUBKEYALGO_DSA:
00448                 t = stpcpy(t, "DSA");
00449                 break;
00450             case PGPPUBKEYALGO_RSA:
00451                 t = stpcpy(t, "RSA");
00452                 break;
00453             default:
00454                 (void) snprintf(t, nb - (t - val), "%d", sigp->pubkey_algo);
00455                 t += strlen(t);
00456                 break;
00457             }
00458             if (t + 5 >= val + nb)
00459                 goto again;
00460             *t++ = '/';
00461             switch (sigp->hash_algo) {
00462             case PGPHASHALGO_MD5:
00463                 t = stpcpy(t, "MD5");
00464                 break;
00465             case PGPHASHALGO_SHA1:
00466                 t = stpcpy(t, "SHA1");
00467                 break;
00468             default:
00469                 (void) snprintf(t, nb - (t - val), "%d", sigp->hash_algo);
00470                 t += strlen(t);
00471                 break;
00472             }
00473             if (t + strlen (", ") + 1 >= val + nb)
00474                 goto again;
00475 
00476             t = stpcpy(t, ", ");
00477 
00478             /* this is important if sizeof(int_32) ! sizeof(time_t) */
00479             {   time_t dateint = pgpGrab(sigp->time, sizeof(sigp->time));
00480                 struct tm * tstruct = localtime(&dateint);
00481                 if (tstruct)
00482                     (void) strftime(t, (nb - (t - val)), "%c", tstruct);
00483             }
00484             t += strlen(t);
00485             if (t + strlen (", Key ID ") + 1 >= val + nb)
00486                 goto again;
00487             t = stpcpy(t, ", Key ID ");
00488             tempstr = pgpHexStr(sigp->signid, sizeof(sigp->signid));
00489             if (t + strlen (tempstr) > val + nb)
00490                 goto again;
00491             t = stpcpy(t, tempstr);
00492 /*@=boundswrite@*/
00493 
00494             dig = pgpFreeDig(dig);
00495         }
00496     }
00497 
00498     return val;
00499 }
00500 
00510 static /*@only@*/ char * depflagsFormat(int_32 type, const void * data, 
00511                 char * formatPrefix, int padding, /*@unused@*/ int element)
00512         /*@modifies formatPrefix @*/
00513         /*@requires maxRead(data) >= 0 @*/
00514 {
00515     char * val;
00516     char buf[10];
00517     int anint;
00518 
00519     if (type != RPM_INT32_TYPE) {
00520         val = xstrdup(_("(not a number)"));
00521     } else {
00522         anint = *((int_32 *) data);
00523         buf[0] = '\0';
00524 
00525 /*@-boundswrite@*/
00526         if (anint & RPMSENSE_LESS) 
00527             strcat(buf, "<");
00528         if (anint & RPMSENSE_GREATER)
00529             strcat(buf, ">");
00530         if (anint & RPMSENSE_EQUAL)
00531             strcat(buf, "=");
00532 /*@=boundswrite@*/
00533 
00534         val = xmalloc(5 + padding);
00535 /*@-boundswrite@*/
00536         strcat(formatPrefix, "s");
00537 /*@=boundswrite@*/
00538         /*@-formatconst@*/
00539         sprintf(val, formatPrefix, buf);
00540         /*@=formatconst@*/
00541     }
00542 
00543     return val;
00544 }
00545 
00555 static int fsnamesTag( /*@unused@*/ Header h, /*@out@*/ int_32 * type,
00556                 /*@out@*/ void ** data, /*@out@*/ int_32 * count,
00557                 /*@out@*/ int * freeData)
00558         /*@globals fileSystem, internalState @*/
00559         /*@modifies *type, *data, *count, *freeData,
00560                 fileSystem, internalState @*/
00561         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00562                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00563 {
00564     const char ** list;
00565 
00566 /*@-boundswrite@*/
00567     if (rpmGetFilesystemList(&list, count))
00568         return 1;
00569 /*@=boundswrite@*/
00570 
00571     if (type) *type = RPM_STRING_ARRAY_TYPE;
00572     if (data) *((const char ***) data) = list;
00573     if (freeData) *freeData = 0;
00574 
00575     return 0; 
00576 }
00577 
00587 static int instprefixTag(Header h, /*@null@*/ /*@out@*/ rpmTagType * type,
00588                 /*@null@*/ /*@out@*/ const void ** data,
00589                 /*@null@*/ /*@out@*/ int_32 * count,
00590                 /*@null@*/ /*@out@*/ int * freeData)
00591         /*@modifies *type, *data, *freeData @*/
00592         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00593                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00594 {
00595     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00596     HFD_t hfd = headerFreeData;
00597     rpmTagType ipt;
00598     char ** array;
00599 
00600     if (hge(h, RPMTAG_INSTALLPREFIX, type, (void **)data, count)) {
00601         if (freeData) *freeData = 0;
00602         return 0;
00603     } else if (hge(h, RPMTAG_INSTPREFIXES, &ipt, (void **) &array, count)) {
00604         if (type) *type = RPM_STRING_TYPE;
00605 /*@-boundsread@*/
00606         if (data) *data = xstrdup(array[0]);
00607 /*@=boundsread@*/
00608         if (freeData) *freeData = 1;
00609         array = hfd(array, ipt);
00610         return 0;
00611     }
00612 
00613     return 1;
00614 }
00615 
00625 static int fssizesTag(Header h, /*@out@*/ rpmTagType * type,
00626                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00627                 /*@out@*/ int * freeData)
00628         /*@globals rpmGlobalMacroContext, h_errno,
00629                 fileSystem, internalState @*/
00630         /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext,
00631                 fileSystem, internalState @*/
00632         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00633                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00634 {
00635     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00636     const char ** filenames;
00637     int_32 * filesizes;
00638     uint_32 * usages;
00639     int numFiles;
00640 
00641     if (!hge(h, RPMTAG_FILESIZES, NULL, (void **) &filesizes, &numFiles)) {
00642         filesizes = NULL;
00643         numFiles = 0;
00644         filenames = NULL;
00645     } else {
00646         rpmfiBuildFNames(h, RPMTAG_BASENAMES, &filenames, &numFiles);
00647     }
00648 
00649 /*@-boundswrite@*/
00650     if (rpmGetFilesystemList(NULL, count))
00651         return 1;
00652 /*@=boundswrite@*/
00653 
00654     *type = RPM_INT32_TYPE;
00655     *freeData = 1;
00656 
00657     if (filenames == NULL) {
00658         usages = xcalloc((*count), sizeof(usages));
00659         *data = usages;
00660 
00661         return 0;
00662     }
00663 
00664 /*@-boundswrite@*/
00665     if (rpmGetFilesystemUsage(filenames, filesizes, numFiles, &usages, 0))      
00666         return 1;
00667 /*@=boundswrite@*/
00668 
00669     *data = usages;
00670 
00671     filenames = _free(filenames);
00672 
00673     return 0;
00674 }
00675 
00685 static int triggercondsTag(Header h, /*@out@*/ rpmTagType * type,
00686                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00687                 /*@out@*/ int * freeData)
00688         /*@modifies *type, *data, *count, *freeData @*/
00689         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00690                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00691 {
00692     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00693     HFD_t hfd = headerFreeData;
00694     rpmTagType tnt, tvt, tst;
00695     int_32 * indices, * flags;
00696     char ** names, ** versions;
00697     int numNames, numScripts;
00698     char ** conds, ** s;
00699     char * item, * flagsStr;
00700     char * chptr;
00701     int i, j, xx;
00702     char buf[5];
00703 
00704     if (!hge(h, RPMTAG_TRIGGERNAME, &tnt, (void **) &names, &numNames)) {
00705         *freeData = 0;
00706         return 0;
00707     }
00708 
00709     xx = hge(h, RPMTAG_TRIGGERINDEX, NULL, (void **) &indices, NULL);
00710     xx = hge(h, RPMTAG_TRIGGERFLAGS, NULL, (void **) &flags, NULL);
00711     xx = hge(h, RPMTAG_TRIGGERVERSION, &tvt, (void **) &versions, NULL);
00712     xx = hge(h, RPMTAG_TRIGGERSCRIPTS, &tst, (void **) &s, &numScripts);
00713     s = hfd(s, tst);
00714 
00715     *freeData = 1;
00716     *data = conds = xmalloc(sizeof(*conds) * numScripts);
00717     *count = numScripts;
00718     *type = RPM_STRING_ARRAY_TYPE;
00719 /*@-bounds@*/
00720     for (i = 0; i < numScripts; i++) {
00721         chptr = xstrdup("");
00722 
00723         for (j = 0; j < numNames; j++) {
00724             if (indices[j] != i)
00725                 /*@innercontinue@*/ continue;
00726 
00727             item = xmalloc(strlen(names[j]) + strlen(versions[j]) + 20);
00728             if (flags[j] & RPMSENSE_SENSEMASK) {
00729                 buf[0] = '%', buf[1] = '\0';
00730                 flagsStr = depflagsFormat(RPM_INT32_TYPE, flags, buf, 0, j);
00731                 sprintf(item, "%s %s %s", names[j], flagsStr, versions[j]);
00732                 flagsStr = _free(flagsStr);
00733             } else {
00734                 strcpy(item, names[j]);
00735             }
00736 
00737             chptr = xrealloc(chptr, strlen(chptr) + strlen(item) + 5);
00738             if (*chptr != '\0') strcat(chptr, ", ");
00739             strcat(chptr, item);
00740             item = _free(item);
00741         }
00742 
00743         conds[i] = chptr;
00744     }
00745 /*@=bounds@*/
00746 
00747     names = hfd(names, tnt);
00748     versions = hfd(versions, tvt);
00749 
00750     return 0;
00751 }
00752 
00762 static int triggertypeTag(Header h, /*@out@*/ rpmTagType * type,
00763                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00764                 /*@out@*/ int * freeData)
00765         /*@modifies *type, *data, *count, *freeData @*/
00766         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00767                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00768 {
00769     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00770     HFD_t hfd = headerFreeData;
00771     rpmTagType tst;
00772     int_32 * indices, * flags;
00773     const char ** conds;
00774     const char ** s;
00775     int i, j, xx;
00776     int numScripts, numNames;
00777 
00778     if (!hge(h, RPMTAG_TRIGGERINDEX, NULL, (void **) &indices, &numNames)) {
00779         *freeData = 0;
00780         return 1;
00781     }
00782 
00783     xx = hge(h, RPMTAG_TRIGGERFLAGS, NULL, (void **) &flags, NULL);
00784     xx = hge(h, RPMTAG_TRIGGERSCRIPTS, &tst, (void **) &s, &numScripts);
00785     s = hfd(s, tst);
00786 
00787     *freeData = 1;
00788     *data = conds = xmalloc(sizeof(*conds) * numScripts);
00789     *count = numScripts;
00790     *type = RPM_STRING_ARRAY_TYPE;
00791 /*@-bounds@*/
00792     for (i = 0; i < numScripts; i++) {
00793         for (j = 0; j < numNames; j++) {
00794             if (indices[j] != i)
00795                 /*@innercontinue@*/ continue;
00796 
00797             if (flags[j] & RPMSENSE_TRIGGERPREIN)
00798                 conds[i] = xstrdup("prein");
00799             else if (flags[j] & RPMSENSE_TRIGGERIN)
00800                 conds[i] = xstrdup("in");
00801             else if (flags[j] & RPMSENSE_TRIGGERUN)
00802                 conds[i] = xstrdup("un");
00803             else if (flags[j] & RPMSENSE_TRIGGERPOSTUN)
00804                 conds[i] = xstrdup("postun");
00805             else
00806                 conds[i] = xstrdup("");
00807             /*@innerbreak@*/ break;
00808         }
00809     }
00810 /*@=bounds@*/
00811 
00812     return 0;
00813 }
00814 
00824 static int filenamesTag(Header h, /*@out@*/ rpmTagType * type,
00825                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00826                 /*@out@*/ int * freeData)
00827         /*@modifies *type, *data, *count, *freeData @*/
00828         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00829                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00830 {
00831     *type = RPM_STRING_ARRAY_TYPE;
00832     rpmfiBuildFNames(h, RPMTAG_BASENAMES, (const char ***) data, count);
00833     *freeData = 1;
00834     return 0; 
00835 }
00836 
00846 static int fileclassTag(Header h, /*@out@*/ rpmTagType * type,
00847                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00848                 /*@out@*/ int * freeData)
00849         /*@globals rpmGlobalMacroContext, h_errno, fileSystem @*/
00850         /*@modifies h, *type, *data, *count, *freeData,
00851                 rpmGlobalMacroContext, fileSystem @*/
00852         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00853                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00854 {
00855     *type = RPM_STRING_ARRAY_TYPE;
00856     rpmfiBuildFClasses(h, (const char ***) data, count);
00857     *freeData = 1;
00858     return 0; 
00859 }
00860 
00870 static int filecontextsTag(Header h, /*@out@*/ rpmTagType * type,
00871                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00872                 /*@out@*/ int * freeData)
00873         /*@globals rpmGlobalMacroContext, h_errno, fileSystem @*/
00874         /*@modifies h, *type, *data, *count, *freeData,
00875                 rpmGlobalMacroContext, fileSystem @*/
00876         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00877                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00878 {
00879     *type = RPM_STRING_ARRAY_TYPE;
00880     rpmfiBuildFContexts(h, (const char ***) data, count);
00881     *freeData = 1;
00882     return 0; 
00883 }
00884 
00894 static int fscontextsTag(Header h, /*@out@*/ rpmTagType * type,
00895                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00896                 /*@out@*/ int * freeData)
00897         /*@globals rpmGlobalMacroContext, h_errno, fileSystem @*/
00898         /*@modifies h, *type, *data, *count, *freeData,
00899                 rpmGlobalMacroContext, fileSystem @*/
00900         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00901                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00902 {
00903     *type = RPM_STRING_ARRAY_TYPE;
00904     rpmfiBuildFSContexts(h, (const char ***) data, count);
00905     *freeData = 1;
00906     return 0; 
00907 }
00908 
00918 static int recontextsTag(Header h, /*@out@*/ rpmTagType * type,
00919                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00920                 /*@out@*/ int * freeData)
00921         /*@globals rpmGlobalMacroContext, h_errno, fileSystem @*/
00922         /*@modifies h, *type, *data, *count, *freeData,
00923                 rpmGlobalMacroContext, fileSystem @*/
00924         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00925                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00926 {
00927     *type = RPM_STRING_ARRAY_TYPE;
00928     rpmfiBuildREContexts(h, (const char ***) data, count);
00929     *freeData = 1;
00930     return 0; 
00931 }
00932 
00942 static int fileprovideTag(Header h, /*@out@*/ rpmTagType * type,
00943                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00944                 /*@out@*/ int * freeData)
00945         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00946         /*@modifies h, *type, *data, *count, *freeData,
00947                 rpmGlobalMacroContext, fileSystem, internalState @*/
00948         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00949                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00950 {
00951     *type = RPM_STRING_ARRAY_TYPE;
00952     rpmfiBuildFDeps(h, RPMTAG_PROVIDENAME, (const char ***) data, count);
00953     *freeData = 1;
00954     return 0; 
00955 }
00956 
00966 static int filerequireTag(Header h, /*@out@*/ rpmTagType * type,
00967                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
00968                 /*@out@*/ int * freeData)
00969         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00970         /*@modifies h, *type, *data, *count, *freeData,
00971                 rpmGlobalMacroContext, fileSystem, internalState @*/
00972         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
00973                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
00974 {
00975     *type = RPM_STRING_ARRAY_TYPE;
00976     rpmfiBuildFDeps(h, RPMTAG_REQUIRENAME, (const char ***) data, count);
00977     *freeData = 1;
00978     return 0; 
00979 }
00980 
00981 /* I18N look aside diversions */
00982 
00983 #if defined(ENABLE_NLS)
00984 /*@-exportlocal -exportheadervar@*/
00985 /*@unchecked@*/
00986 extern int _nl_msg_cat_cntr;    /* XXX GNU gettext voodoo */
00987 /*@=exportlocal =exportheadervar@*/
00988 #endif
00989 /*@observer@*/ /*@unchecked@*/
00990 static const char * language = "LANGUAGE";
00991 
00992 /*@observer@*/ /*@unchecked@*/
00993 static const char * _macro_i18ndomains = "%{?_i18ndomains}";
00994 
01005 static int i18nTag(Header h, int_32 tag, /*@out@*/ rpmTagType * type,
01006                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
01007                 /*@out@*/ int * freeData)
01008         /*@globals rpmGlobalMacroContext, h_errno @*/
01009         /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
01010         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
01011                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
01012 {
01013     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
01014     char * dstring = rpmExpand(_macro_i18ndomains, NULL);
01015     int rc;
01016 
01017     *type = RPM_STRING_TYPE;
01018     *data = NULL;
01019     *count = 0;
01020     *freeData = 0;
01021 
01022     if (dstring && *dstring) {
01023         char *domain, *de;
01024         const char * langval;
01025         const char * msgkey;
01026         const char * msgid;
01027 
01028         {   const char * tn = tagName(tag);
01029             const char * n;
01030             char * mk;
01031             size_t nb = sizeof("()");
01032             int xx = headerNVR(h, &n, NULL, NULL);
01033             if (tn)     nb += strlen(tn);
01034             if (n)      nb += strlen(n);
01035             mk = alloca(nb);
01036             sprintf(mk, "%s(%s)", n, tn);
01037             msgkey = mk;
01038         }
01039 
01040         /* change to en_US for msgkey -> msgid resolution */
01041         langval = getenv(language);
01042         (void) setenv(language, "en_US", 1);
01043 #if defined(ENABLE_NLS)
01044 /*@i@*/ ++_nl_msg_cat_cntr;
01045 #endif
01046 
01047         msgid = NULL;
01048         /*@-branchstate@*/
01049         for (domain = dstring; domain != NULL; domain = de) {
01050             de = strchr(domain, ':');
01051             if (de) *de++ = '\0';
01052             msgid = /*@-unrecog@*/ dgettext(domain, msgkey) /*@=unrecog@*/;
01053             if (msgid != msgkey) break;
01054         }
01055         /*@=branchstate@*/
01056 
01057         /* restore previous environment for msgid -> msgstr resolution */
01058         if (langval)
01059             (void) setenv(language, langval, 1);
01060         else
01061             unsetenv(language);
01062 #if defined(ENABLE_NLS)
01063 /*@i@*/ ++_nl_msg_cat_cntr;
01064 #endif
01065 
01066         if (domain && msgid) {
01067             *data = /*@-unrecog@*/ dgettext(domain, msgid) /*@=unrecog@*/;
01068             *data = xstrdup(*data);     /* XXX xstrdup has side effects. */
01069             *count = 1;
01070             *freeData = 1;
01071         }
01072         dstring = _free(dstring);
01073         if (*data)
01074             return 0;
01075     }
01076 
01077     dstring = _free(dstring);
01078 
01079     rc = hge(h, tag, type, (void **)data, count);
01080 
01081     if (rc && (*data) != NULL) {
01082         *data = xstrdup(*data);
01083         *freeData = 1;
01084         return 0;
01085     }
01086 
01087     *freeData = 0;
01088     *data = NULL;
01089     *count = 0;
01090     return 1;
01091 }
01092 
01102 static int summaryTag(Header h, /*@out@*/ rpmTagType * type,
01103                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
01104                 /*@out@*/ int * freeData)
01105         /*@globals rpmGlobalMacroContext, h_errno @*/
01106         /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
01107         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
01108                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
01109 {
01110     return i18nTag(h, RPMTAG_SUMMARY, type, data, count, freeData);
01111 }
01112 
01122 static int descriptionTag(Header h, /*@out@*/ rpmTagType * type,
01123                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
01124                 /*@out@*/ int * freeData)
01125         /*@globals rpmGlobalMacroContext, h_errno @*/
01126         /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
01127         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
01128                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
01129 {
01130     return i18nTag(h, RPMTAG_DESCRIPTION, type, data, count, freeData);
01131 }
01132 
01142 static int groupTag(Header h, /*@out@*/ rpmTagType * type,
01143                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
01144                 /*@out@*/ int * freeData)
01145         /*@globals rpmGlobalMacroContext, h_errno @*/
01146         /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
01147         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
01148                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
01149 {
01150     return i18nTag(h, RPMTAG_GROUP, type, data, count, freeData);
01151 }
01152 
01153 /*@-type@*/ /* FIX: cast? */
01154 const struct headerSprintfExtension_s rpmHeaderFormats[] = {
01155     { HEADER_EXT_TAG, "RPMTAG_GROUP",           { groupTag } },
01156     { HEADER_EXT_TAG, "RPMTAG_DESCRIPTION",     { descriptionTag } },
01157     { HEADER_EXT_TAG, "RPMTAG_SUMMARY",         { summaryTag } },
01158     { HEADER_EXT_TAG, "RPMTAG_FILECLASS",       { fileclassTag } },
01159     { HEADER_EXT_TAG, "RPMTAG_FILECONTEXTS",    { filecontextsTag } },
01160     { HEADER_EXT_TAG, "RPMTAG_FILENAMES",       { filenamesTag } },
01161     { HEADER_EXT_TAG, "RPMTAG_FILEPROVIDE",     { fileprovideTag } },
01162     { HEADER_EXT_TAG, "RPMTAG_FILEREQUIRE",     { filerequireTag } },
01163     { HEADER_EXT_TAG, "RPMTAG_FSCONTEXTS",      { fscontextsTag } },
01164     { HEADER_EXT_TAG, "RPMTAG_FSNAMES",         { fsnamesTag } },
01165     { HEADER_EXT_TAG, "RPMTAG_FSSIZES",         { fssizesTag } },
01166     { HEADER_EXT_TAG, "RPMTAG_INSTALLPREFIX",   { instprefixTag } },
01167     { HEADER_EXT_TAG, "RPMTAG_RECONTEXTS",      { recontextsTag } },
01168     { HEADER_EXT_TAG, "RPMTAG_TRIGGERCONDS",    { triggercondsTag } },
01169     { HEADER_EXT_TAG, "RPMTAG_TRIGGERTYPE",     { triggertypeTag } },
01170     { HEADER_EXT_FORMAT, "armor",               { armorFormat } },
01171     { HEADER_EXT_FORMAT, "base64",              { base64Format } },
01172     { HEADER_EXT_FORMAT, "pgpsig",              { pgpsigFormat } },
01173     { HEADER_EXT_FORMAT, "depflags",            { depflagsFormat } },
01174     { HEADER_EXT_FORMAT, "fflags",              { fflagsFormat } },
01175     { HEADER_EXT_FORMAT, "perms",               { permsFormat } },
01176     { HEADER_EXT_FORMAT, "permissions",         { permsFormat } },
01177     { HEADER_EXT_FORMAT, "triggertype",         { triggertypeFormat } },
01178     { HEADER_EXT_FORMAT, "xml",                 { xmlFormat } },
01179     { HEADER_EXT_MORE, NULL,            { (void *) headerDefaultFormats } }
01180 } ;
01181 /*@=type@*/

Generated on Fri Oct 12 08:44:53 2007 for rpm by  doxygen 1.5.2