Main Page Modules Data Structures File List Data Fields Globals Related Pages

# 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 #include "manifest.h"
    00010 #include "misc.h"
    00011 #include "debug.h"
    00012
    00013 /*@access pgpDig @*/
    00014 /*@access pgpDigParams @*/
    00015
    00025 static /*@only@*/ char * triggertypeFormat(int_32 type, const void * data,
    00026                 /*@unused@*/ char * formatPrefix, /*@unused@*/ int padding,
    00027                 /*@unused@*/ int element)
    00028         /*@requires maxRead(data) >= 0 @*/
    00029 {
    00030     const int_32 * item = data;
    00031     char * val;
    00032
    00033     if (type != RPM_INT32_TYPE)
    00034         val = xstrdup(_("(not a number)"));
    00035     else if (*item & RPMSENSE_TRIGGERIN)
    00036         val = xstrdup("in");
    00037     else
    00038         val = xstrdup("un");
    00039     return val;
    00040 }
    00041
    00051 static /*@only@*/ char * permsFormat(int_32 type, const void * data,
    00052                 char * formatPrefix, int padding, /*@unused@*/ int element)
    00053         /*@modifies formatPrefix @*/
    00054         /*@requires maxRead(data) >= 0 @*/
    00055 {
    00056     char * val;
    00057     char * buf;
    00058
    00059     if (type != RPM_INT32_TYPE) {
    00060         val = xstrdup(_("(not a number)"));
    00061     } else {
    00062         val = xmalloc(15 + padding);
    00063 /*@-boundswrite@*/
    00064         strcat(formatPrefix, "s");
    00065 /*@=boundswrite@*/
    00066         buf = rpmPermsString(*((int_32 *) data));
    00067         /*@-formatconst@*/
    00068         sprintf(val, formatPrefix, buf);
    00069         /*@=formatconst@*/
    00070         buf = _free(buf);
    00071     }
    00072
    00073     return val;
    00074 }
    00075
    00085 static /*@only@*/ char * fflagsFormat(int_32 type, const void * data,
    00086                 char * formatPrefix, int padding, /*@unused@*/ int element)
    00087         /*@modifies formatPrefix @*/
    00088         /*@requires maxRead(data) >= 0 @*/
    00089 {
    00090     char * val;
    00091     char buf[15];
    00092     int anint = *((int_32 *) data);
    00093
    00094     if (type != RPM_INT32_TYPE) {
    00095         val = xstrdup(_("(not a number)"));
    00096     } else {
    00097         buf[0] = '\0';
    00098 /*@-boundswrite@*/
    00099         if (anint & RPMFILE_DOC)
    00100             strcat(buf, "d");
    00101         if (anint & RPMFILE_CONFIG)
    00102             strcat(buf, "c");
    00103         if (anint & RPMFILE_SPECFILE)
    00104             strcat(buf, "s");
    00105         if (anint & RPMFILE_MISSINGOK)
    00106             strcat(buf, "m");
    00107         if (anint & RPMFILE_NOREPLACE)
    00108             strcat(buf, "n");
    00109         if (anint & RPMFILE_GHOST)
    00110             strcat(buf, "g");
    00111         if (anint & RPMFILE_LICENSE)
    00112             strcat(buf, "l");
    00113         if (anint & RPMFILE_README)
    00114             strcat(buf, "r");
    00115 /*@=boundswrite@*/
    00116
    00117         val = xmalloc(5 + padding);
    00118 /*@-boundswrite@*/
    00119         strcat(formatPrefix, "s");
    00120 /*@=boundswrite@*/
    00121         /*@-formatconst@*/
    00122         sprintf(val, formatPrefix, buf);
    00123         /*@=formatconst@*/
    00124     }
    00125
    00126     return val;
    00127 }
    00128
    00139 static /*@only@*/ char * armorFormat(int_32 type, const void * data,
    00140                 /*@unused@*/ char * formatPrefix, int padding, int element)
    00141         /*@*/
    00142 {
    00143     const char * enc;
    00144     const char * s;
    00145     char * t;
    00146     char * val;
    00147     int atype;
    00148     int lc, ns, nt;
    00149
    00150     switch (type) {
    00151     case RPM_BIN_TYPE:
    00152         s = data;
    00153         ns = element;
    00154         atype = PGPARMOR_SIGNATURE;     /* XXX check pkt for signature */
    00155         break;
    00156     case RPM_STRING_TYPE:
    00157     case RPM_STRING_ARRAY_TYPE:
    00158         enc = data;
    00159         if (b64decode(enc, (void **)&s, &ns))
    00160             return xstrdup(_("(not base64)"));
    00161         atype = PGPARMOR_PUBKEY;        /* XXX check pkt for pubkey */
    00162         break;
    00163     case RPM_NULL_TYPE:
    00164     case RPM_CHAR_TYPE:
    00165     case RPM_INT8_TYPE:
    00166     case RPM_INT16_TYPE:
    00167     case RPM_INT32_TYPE:
    00168     case RPM_I18NSTRING_TYPE:
    00169     default:
    00170         return xstrdup(_("(invalid type)"));
    00171         /*@notreached@*/ break;
    00172     }
    00173
    00174     nt = ((ns + 2) / 3) * 4;
    00175     /*@-globs@*/
    00176     /* Add additional bytes necessary for eol string(s). */
    00177     if (b64encode_chars_per_line > 0 && b64encode_eolstr != NULL) {
    00178         lc = (nt + b64encode_chars_per_line - 1) / b64encode_chars_per_line;
    00179        if (((nt + b64encode_chars_per_line - 1) % b64encode_chars_per_line) != 0)
    00180         ++lc;
    00181         nt += lc * strlen(b64encode_eolstr);
    00182     }
    00183     /*@=globs@*/
    00184
    00185     nt += 512;  /* XXX slop for armor and crc */
    00186
    00187 /*@-boundswrite@*/
    00188     val = t = xmalloc(nt + padding + 1);
    00189     *t = '\0';
    00190     t = stpcpy(t, "-----BEGIN PGP ");
    00191     t = stpcpy(t, pgpValStr(pgpArmorTbl, atype));
    00192     /*@-globs@*/
    00193     t = stpcpy( stpcpy(t, "-----\nVersion: rpm-"), RPMVERSION);
    00194     /*@=globs@*/
    00195     t = stpcpy(t, " (beecrypt-2.2.0)\n\n");
    00196
    00197     if ((enc = b64encode(s, ns)) != NULL) {
    00198         t = stpcpy(t, enc);
    00199         enc = _free(enc);
    00200         if ((enc = b64crc(s, ns)) != NULL) {
    00201             *t++ = '=';
    00202             t = stpcpy(t, enc);
    00203             enc = _free(enc);
    00204         }
    00205     }
    00206
    00207     t = stpcpy(t, "-----END PGP ");
    00208     t = stpcpy(t, pgpValStr(pgpArmorTbl, atype));
    00209     t = stpcpy(t, "-----\n");
    00210 /*@=boundswrite@*/
    00211
    00212     /*@-branchstate@*/
    00213     if (s != data) s = _free(s);
    00214     /*@=branchstate@*/
    00215
    00216     return val;
    00217 }
    00218
    00229 static /*@only@*/ char * base64Format(int_32 type, const void * data,
    00230                 /*@unused@*/ char * formatPrefix, int padding, int element)
    00231         /*@*/
    00232 {
    00233     char * val;
    00234
    00235     if (type != RPM_BIN_TYPE) {
    00236         val = xstrdup(_("(not a blob)"));
    00237     } else {
    00238         const char * enc;
    00239         char * t;
    00240         int lc;
    00241         int nt = ((element + 2) / 3) * 4;
    00242
    00243 /*@-boundswrite@*/
    00244         /*@-globs@*/
    00245         /* Add additional bytes necessary for eol string(s). */
    00246         if (b64encode_chars_per_line > 0 && b64encode_eolstr != NULL) {
    00247             lc = (nt + b64encode_chars_per_line - 1) / b64encode_chars_per_line;
    00248         if (((nt + b64encode_chars_per_line - 1) % b64encode_chars_per_line) != 0)
    00249             ++lc;
    00250             nt += lc * strlen(b64encode_eolstr);
    00251         }
    00252         /*@=globs@*/
    00253
    00254         val = t = xmalloc(nt + padding + 1);
    00255
    00256         *t = '\0';
    00257         if ((enc = b64encode(data, element)) != NULL) {
    00258             t = stpcpy(t, enc);
    00259             enc = _free(enc);
    00260         }
    00261 /*@=boundswrite@*/
    00262     }
    00263
    00264     return val;
    00265 }
    00266
    00276 static /*@only@*/ char * pgpsigFormat(int_32 type, const void * data,
    00277                 /*@unused@*/ char * formatPrefix, /*@unused@*/ int padding,
    00278                 /*@unused@*/ int element)
    00279         /*@globals fileSystem @*/
    00280         /*@modifies fileSystem @*/
    00281 {
    00282     char * val, * t;
    00283
    00284     if (type != RPM_BIN_TYPE) {
    00285         val = xstrdup(_("(not a blob)"));
    00286     } else {
    00287         unsigned char * pkt = (byte *) data;
    00288         unsigned int pktlen = 0;
    00289 /*@-boundsread@*/
    00290         unsigned int v = *pkt;
    00291 /*@=boundsread@*/
    00292         pgpTag tag = 0;
    00293         unsigned int plen;
    00294         unsigned int hlen = 0;
    00295
    00296         if (v & 0x80) {
    00297             if (v & 0x40) {
    00298                 tag = (v & 0x3f);
    00299                 plen = pgpLen(pkt+1, &hlen);
    00300             } else {
    00301                 tag = (v >> 2) & 0xf;
    00302                 plen = (1 << (v & 0x3));
    00303                 hlen = pgpGrab(pkt+1, plen);
    00304             }
    00305
    00306             pktlen = 1 + plen + hlen;
    00307         }
    00308
    00309         if (pktlen == 0 || tag != PGPTAG_SIGNATURE) {
    00310             val = xstrdup(_("(not an OpenPGP signature)"));
    00311         } else {
    00312             pgpDig dig = pgpNewDig();
    00313             pgpDigParams sigp = &dig->signature;
    00314             size_t nb = 80;
    00315
    00316             (void) pgpPrtPkts(pkt, pktlen, dig, 0);
    00317
    00318             val = t = xmalloc(nb + 1);
    00319
    00320 /*@-boundswrite@*/
    00321             switch (sigp->pubkey_algo) {
    00322             case PGPPUBKEYALGO_DSA:
    00323                 t = stpcpy(t, "DSA");
    00324                 break;
    00325             case PGPPUBKEYALGO_RSA:
    00326                 t = stpcpy(t, "RSA");
    00327                 break;
    00328             default:
    00329                 sprintf(t, "%d", sigp->pubkey_algo);
    00330                 t += strlen(t);
    00331                 break;
    00332             }
    00333             *t++ = '/';
    00334             switch (sigp->hash_algo) {
    00335             case PGPHASHALGO_MD5:
    00336                 t = stpcpy(t, "MD5");
    00337                 break;
    00338             case PGPHASHALGO_SHA1:
    00339                 t = stpcpy(t, "SHA1");
    00340                 break;
    00341             default:
    00342                 sprintf(t, "%d", sigp->hash_algo);
    00343                 t += strlen(t);
    00344                 break;
    00345             }
    00346
    00347             t = stpcpy(t, ", ");
    00348
    00349             /* this is important if sizeof(int_32) ! sizeof(time_t) */
    00350             {   time_t dateint = pgpGrab(sigp->time, sizeof(sigp->time));
    00351                 struct tm * tstruct = localtime(&dateint);
    00352                 if (tstruct)
    00353                     (void) strftime(t, (nb - (t - val)), "%c", tstruct);
    00354             }
    00355             t += strlen(t);
    00356             t = stpcpy(t, ", Key ID ");
    00357             t = stpcpy(t, pgpHexStr(sigp->signid, sizeof(sigp->signid)));
    00358 /*@=boundswrite@*/
    00359
    00360             dig = pgpFreeDig(dig);
    00361         }
    00362     }
    00363
    00364     return val;
    00365 }
    00366
    00376 static /*@only@*/ char * depflagsFormat(int_32 type, const void * data,
    00377                 char * formatPrefix, int padding, /*@unused@*/ int element)
    00378         /*@modifies formatPrefix @*/
    00379         /*@requires maxRead(data) >= 0 @*/
    00380 {
    00381     char * val;
    00382     char buf[10];
    00383     int anint = *((int_32 *) data);
    00384
    00385     if (type != RPM_INT32_TYPE) {
    00386         val = xstrdup(_("(not a number)"));
    00387     } else {
    00388         buf[0] = '\0';
    00389
    00390 /*@-boundswrite@*/
    00391         if (anint & RPMSENSE_LESS)
    00392             strcat(buf, "<");
    00393         if (anint & RPMSENSE_GREATER)
    00394             strcat(buf, ">");
    00395         if (anint & RPMSENSE_EQUAL)
    00396             strcat(buf, "=");
    00397 /*@=boundswrite@*/
    00398
    00399         val = xmalloc(5 + padding);
    00400 /*@-boundswrite@*/
    00401         strcat(formatPrefix, "s");
    00402 /*@=boundswrite@*/
    00403         /*@-formatconst@*/
    00404         sprintf(val, formatPrefix, buf);
    00405         /*@=formatconst@*/
    00406     }
    00407
    00408     return val;
    00409 }
    00410
    00420 static int fsnamesTag( /*@unused@*/ Header h, /*@out@*/ int_32 * type,
    00421                 /*@out@*/ void ** data, /*@out@*/ int_32 * count,
    00422                 /*@out@*/ int * freeData)
    00423         /*@globals fileSystem, internalState @*/
    00424         /*@modifies *type, *data, *count, *freeData,
    00425                 fileSystem, internalState @*/
    00426         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
    00427                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
    00428 {
    00429     const char ** list;
    00430
    00431 /*@-boundswrite@*/
    00432     if (rpmGetFilesystemList(&list, count))
    00433         return 1;
    00434 /*@=boundswrite@*/
    00435
    00436     if (type) *type = RPM_STRING_ARRAY_TYPE;
    00437     if (data) *((const char ***) data) = list;
    00438     if (freeData) *freeData = 0;
    00439
    00440     return 0;
    00441 }
    00442
    00452 static int instprefixTag(Header h, /*@null@*/ /*@out@*/ rpmTagType * type,
    00453                 /*@null@*/ /*@out@*/ const void ** data,
    00454                 /*@null@*/ /*@out@*/ int_32 * count,
    00455                 /*@null@*/ /*@out@*/ int * freeData)
    00456         /*@modifies *type, *data, *freeData @*/
    00457         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
    00458                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
    00459 {
    00460     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
    00461     HFD_t hfd = headerFreeData;
    00462     rpmTagType ipt;
    00463     char ** array;
    00464
    00465     if (hge(h, RPMTAG_INSTALLPREFIX, type, (void **)data, count)) {
    00466         if (freeData) *freeData = 0;
    00467         return 0;
    00468     } else if (hge(h, RPMTAG_INSTPREFIXES, &ipt, (void **) &array, count)) {
    00469         if (type) *type = RPM_STRING_TYPE;
    00470 /*@-boundsread@*/
    00471         if (data) *data = xstrdup(array[0]);
    00472 /*@=boundsread@*/
    00473         if (freeData) *freeData = 1;
    00474         array = hfd(array, ipt);
    00475         return 0;
    00476     }
    00477
    00478     return 1;
    00479 }
    00480
    00490 static int fssizesTag(Header h, /*@out@*/ rpmTagType * type,
    00491                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
    00492                 /*@out@*/ int * freeData)
    00493         /*@globals rpmGlobalMacroContext,
    00494                 fileSystem, internalState @*/
    00495         /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext,
    00496                 fileSystem, internalState @*/
    00497         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
    00498                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
    00499 {
    00500     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
    00501     const char ** filenames;
    00502     int_32 * filesizes;
    00503     uint_32 * usages;
    00504     int numFiles;
    00505
    00506     if (!hge(h, RPMTAG_FILESIZES, NULL, (void **) &filesizes, &numFiles)) {
    00507         filesizes = NULL;
    00508         numFiles = 0;
    00509         filenames = NULL;
    00510     } else {
    00511         rpmBuildFileList(h, &filenames, &numFiles);
    00512     }
    00513
    00514 /*@-boundswrite@*/
    00515     if (rpmGetFilesystemList(NULL, count))
    00516         return 1;
    00517 /*@=boundswrite@*/
    00518
    00519     *type = RPM_INT32_TYPE;
    00520     *freeData = 1;
    00521
    00522     if (filenames == NULL) {
    00523         usages = xcalloc((*count), sizeof(usages));
    00524         *data = usages;
    00525
    00526         return 0;
    00527     }
    00528
    00529 /*@-boundswrite@*/
    00530     if (rpmGetFilesystemUsage(filenames, filesizes, numFiles, &usages, 0))
    00531         return 1;
    00532 /*@=boundswrite@*/
    00533
    00534     *data = usages;
    00535
    00536     filenames = _free(filenames);
    00537
    00538     return 0;
    00539 }
    00540
    00550 /*@-bounds@*/   /* LCL: segfault */
    00551 static int triggercondsTag(Header h, /*@out@*/ rpmTagType * type,
    00552                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
    00553                 /*@out@*/ int * freeData)
    00554         /*@modifies *type, *data, *count, *freeData @*/
    00555         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
    00556                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
    00557 {
    00558     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
    00559     HFD_t hfd = headerFreeData;
    00560     rpmTagType tnt, tvt, tst;
    00561     int_32 * indices, * flags;
    00562     char ** names, ** versions;
    00563     int numNames, numScripts;
    00564     char ** conds, ** s;
    00565     char * item, * flagsStr;
    00566     char * chptr;
    00567     int i, j, xx;
    00568     char buf[5];
    00569
    00570     if (!hge(h, RPMTAG_TRIGGERNAME, &tnt, (void **) &names, &numNames)) {
    00571         *freeData = 0;
    00572         return 0;
    00573     }
    00574
    00575     xx = hge(h, RPMTAG_TRIGGERINDEX, NULL, (void **) &indices, NULL);
    00576     xx = hge(h, RPMTAG_TRIGGERFLAGS, NULL, (void **) &flags, NULL);
    00577     xx = hge(h, RPMTAG_TRIGGERVERSION, &tvt, (void **) &versions, NULL);
    00578     xx = hge(h, RPMTAG_TRIGGERSCRIPTS, &tst, (void **) &s, &numScripts);
    00579     s = hfd(s, tst);
    00580
    00581     *freeData = 1;
    00582     *data = conds = xmalloc(sizeof(*conds) * numScripts);
    00583     *count = numScripts;
    00584     *type = RPM_STRING_ARRAY_TYPE;
    00585     for (i = 0; i < numScripts; i++) {
    00586         chptr = xstrdup("");
    00587
    00588         for (j = 0; j < numNames; j++) {
    00589             if (indices[j] != i)
    00590                 /*@innercontinue@*/ continue;
    00591
    00592             item = xmalloc(strlen(names[j]) + strlen(versions[j]) + 20);
    00593             if (flags[j] & RPMSENSE_SENSEMASK) {
    00594                 buf[0] = '%', buf[1] = '\0';
    00595                 flagsStr = depflagsFormat(RPM_INT32_TYPE, flags, buf, 0, j);
    00596                 sprintf(item, "%s %s %s", names[j], flagsStr, versions[j]);
    00597                 flagsStr = _free(flagsStr);
    00598             } else {
    00599                 strcpy(item, names[j]);
    00600             }
    00601
    00602             chptr = xrealloc(chptr, strlen(chptr) + strlen(item) + 5);
    00603             if (*chptr != '\0') strcat(chptr, ", ");
    00604             strcat(chptr, item);
    00605             item = _free(item);
    00606         }
    00607
    00608         conds[i] = chptr;
    00609     }
    00610
    00611     names = hfd(names, tnt);
    00612     versions = hfd(versions, tvt);
    00613
    00614     return 0;
    00615 }
    00616 /*@=bounds@*/
    00617
    00627 static int triggertypeTag(Header h, /*@out@*/ rpmTagType * type,
    00628                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
    00629                 /*@out@*/ int * freeData)
    00630         /*@modifies *type, *data, *count, *freeData @*/
    00631         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
    00632                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
    00633 {
    00634     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
    00635     HFD_t hfd = headerFreeData;
    00636     rpmTagType tst;
    00637     int_32 * indices, * flags;
    00638     const char ** conds;
    00639     const char ** s;
    00640     int i, j, xx;
    00641     int numScripts, numNames;
    00642
    00643     if (!hge(h, RPMTAG_TRIGGERINDEX, NULL, (void **) &indices, &numNames)) {
    00644         *freeData = 0;
    00645         return 1;
    00646     }
    00647
    00648     xx = hge(h, RPMTAG_TRIGGERFLAGS, NULL, (void **) &flags, NULL);
    00649     xx = hge(h, RPMTAG_TRIGGERSCRIPTS, &tst, (void **) &s, &numScripts);
    00650     s = hfd(s, tst);
    00651
    00652     *freeData = 1;
    00653     *data = conds = xmalloc(sizeof(*conds) * numScripts);
    00654     *count = numScripts;
    00655     *type = RPM_STRING_ARRAY_TYPE;
    00656     for (i = 0; i < numScripts; i++) {
    00657         for (j = 0; j < numNames; j++) {
    00658             if (indices[j] != i)
    00659                 /*@innercontinue@*/ continue;
    00660
    00661             if (flags[j] & RPMSENSE_TRIGGERIN)
    00662                 conds[i] = xstrdup("in");
    00663             else if (flags[j] & RPMSENSE_TRIGGERUN)
    00664                 conds[i] = xstrdup("un");
    00665             else
    00666                 conds[i] = xstrdup("postun");
    00667             /*@innerbreak@*/ break;
    00668         }
    00669     }
    00670
    00671     return 0;
    00672 }
    00673
    00683 static int filenamesTag(Header h, /*@out@*/ rpmTagType * type,
    00684                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
    00685                 /*@out@*/ int * freeData)
    00686         /*@modifies *type, *data, *count, *freeData @*/
    00687         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
    00688                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
    00689 {
    00690     *type = RPM_STRING_ARRAY_TYPE;
    00691
    00692     rpmBuildFileList(h, (const char ***) data, count);
    00693     *freeData = 1;
    00694
    00695     *freeData = 0;      /* XXX WTFO? */
    00696
    00697     return 0;
    00698 }
    00699
    00700 /* I18N look aside diversions */
    00701
    00702 /*@-exportlocal -exportheadervar@*/
    00703 /*@unchecked@*/
    00704 int _nl_msg_cat_cntr;   /* XXX GNU gettext voodoo */
    00705 /*@=exportlocal =exportheadervar@*/
    00706 /*@observer@*/ /*@unchecked@*/
    00707 static const char * language = "LANGUAGE";
    00708
    00709 /*@observer@*/ /*@unchecked@*/
    00710 static const char * _macro_i18ndomains =
    00711                 "%{?_i18ndomains:%{_i18ndomains}}";
    00712
    00723 static int i18nTag(Header h, int_32 tag, /*@out@*/ rpmTagType * type,
    00724                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
    00725                 /*@out@*/ int * freeData)
    00726         /*@globals rpmGlobalMacroContext @*/
    00727         /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
    00728         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
    00729                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
    00730 {
    00731     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
    00732     char * dstring = rpmExpand(_macro_i18ndomains, NULL);
    00733     int rc;
    00734
    00735     *type = RPM_STRING_TYPE;
    00736     *data = NULL;
    00737     *count = 0;
    00738     *freeData = 0;
    00739
    00740     if (dstring && *dstring) {
    00741         char *domain, *de;
    00742         const char * langval;
    00743         const char * msgkey;
    00744         const char * msgid;
    00745
    00746         {   const char * tn = tagName(tag);
    00747             const char * n;
    00748             char * mk;
    00749             (void) headerNVR(h, &n, NULL, NULL);
    00750             mk = alloca(strlen(n) + strlen(tn) + sizeof("()"));
    00751             sprintf(mk, "%s(%s)", n, tn);
    00752             msgkey = mk;
    00753         }
    00754
    00755         /* change to en_US for msgkey -> msgid resolution */
    00756         langval = getenv(language);
    00757         (void) setenv(language, "en_US", 1);
    00758 /*@i@*/ ++_nl_msg_cat_cntr;
    00759
    00760         msgid = NULL;
    00761         /*@-branchstate@*/
    00762         for (domain = dstring; domain != NULL; domain = de) {
    00763             de = strchr(domain, ':');
    00764             if (de) *de++ = '\0';
    00765             msgid = /*@-unrecog@*/ dgettext(domain, msgkey) /*@=unrecog@*/;
    00766             if (msgid != msgkey) break;
    00767         }
    00768         /*@=branchstate@*/
    00769
    00770         /* restore previous environment for msgid -> msgstr resolution */
    00771         if (langval)
    00772             (void) setenv(language, langval, 1);
    00773         else
    00774             unsetenv(language);
    00775 /*@i@*/ ++_nl_msg_cat_cntr;
    00776
    00777         if (domain && msgid) {
    00778             *data = /*@-unrecog@*/ dgettext(domain, msgid) /*@=unrecog@*/;
    00779             *data = xstrdup(*data);     /* XXX xstrdup has side effects. */
    00780             *count = 1;
    00781             *freeData = 1;
    00782         }
    00783         dstring = _free(dstring);
    00784         if (*data)
    00785             return 0;
    00786     }
    00787
    00788     dstring = _free(dstring);
    00789
    00790     rc = hge(h, tag, type, (void **)data, count);
    00791
    00792     if (rc && (*data) != NULL) {
    00793         *data = xstrdup(*data);
    00794         *freeData = 1;
    00795         return 0;
    00796     }
    00797
    00798     *freeData = 0;
    00799     *data = NULL;
    00800     *count = 0;
    00801     return 1;
    00802 }
    00803
    00813 static int summaryTag(Header h, /*@out@*/ rpmTagType * type,
    00814                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
    00815                 /*@out@*/ int * freeData)
    00816         /*@globals rpmGlobalMacroContext @*/
    00817         /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
    00818         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
    00819                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
    00820 {
    00821     return i18nTag(h, RPMTAG_SUMMARY, type, data, count, freeData);
    00822 }
    00823
    00833 static int descriptionTag(Header h, /*@out@*/ rpmTagType * type,
    00834                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
    00835                 /*@out@*/ int * freeData)
    00836         /*@globals rpmGlobalMacroContext @*/
    00837         /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
    00838         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
    00839                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
    00840 {
    00841     return i18nTag(h, RPMTAG_DESCRIPTION, type, data, count, freeData);
    00842 }
    00843
    00853 static int groupTag(Header h, /*@out@*/ rpmTagType * type,
    00854                 /*@out@*/ const void ** data, /*@out@*/ int_32 * count,
    00855                 /*@out@*/ int * freeData)
    00856         /*@globals rpmGlobalMacroContext @*/
    00857         /*@modifies *type, *data, *count, *freeData, rpmGlobalMacroContext @*/
    00858         /*@requires maxSet(type) >= 0 /\ maxSet(data) >= 0
    00859                 /\ maxSet(count) >= 0 /\ maxSet(freeData) >= 0 @*/
    00860 {
    00861     return i18nTag(h, RPMTAG_GROUP, type, data, count, freeData);
    00862 }
    00863
    00864 /*@-type@*/ /* FIX: cast? */
    00865 const struct headerSprintfExtension_s rpmHeaderFormats[] = {
    00866     { HEADER_EXT_TAG, "RPMTAG_GROUP", { groupTag } },
    00867     { HEADER_EXT_TAG, "RPMTAG_DESCRIPTION", { descriptionTag } },
    00868     { HEADER_EXT_TAG, "RPMTAG_SUMMARY", { summaryTag } },
    00869     { HEADER_EXT_TAG, "RPMTAG_FILENAMES", { filenamesTag } },
    00870     { HEADER_EXT_TAG, "RPMTAG_FSSIZES", { fssizesTag } },
    00871     { HEADER_EXT_TAG, "RPMTAG_FSNAMES", { fsnamesTag } },
    00872     { HEADER_EXT_TAG, "RPMTAG_INSTALLPREFIX", { instprefixTag } },
    00873     { HEADER_EXT_TAG, "RPMTAG_TRIGGERCONDS", { triggercondsTag } },
    00874     { HEADER_EXT_TAG, "RPMTAG_TRIGGERTYPE", { triggertypeTag } },
    00875     { HEADER_EXT_FORMAT, "armor", { armorFormat } },
    00876     { HEADER_EXT_FORMAT, "base64", { base64Format } },
    00877     { HEADER_EXT_FORMAT, "pgpsig", { pgpsigFormat } },
    00878     { HEADER_EXT_FORMAT, "depflags", { depflagsFormat } },
    00879     { HEADER_EXT_FORMAT, "fflags", { fflagsFormat } },
    00880     { HEADER_EXT_FORMAT, "perms", { permsFormat } },
    00881     { HEADER_EXT_FORMAT, "permissions", { permsFormat } },
    00882     { HEADER_EXT_FORMAT, "triggertype", { triggertypeFormat } },
    00883     { HEADER_EXT_MORE, NULL, { (void *) headerDefaultFormats } }
    00884 } ;
    00885 /*@=type@*/