tools/rpmtool.c

Go to the documentation of this file.
00001 #include "system.h"
00002 const char *__progname;
00003 
00004 #include <rpmcli.h>
00005 #include <rpmxp.h>
00006 
00007 #include <rpmlead.h>
00008 #include <signature.h>
00009 #include "header_internal.h"
00010 #include "misc.h"
00011 #include "debug.h"
00012 
00013 static int _rpmtool_debug = 0;
00014 
00015 typedef struct rpmavi_s * rpmavi;
00016 
00017 struct rpmavi_s {
00018     const char ** av;
00019     int flags;
00020 };
00021 
00022 static rpmavi rpmaviFree(rpmavi avi)
00023 {
00024     if (avi) {
00025         memset(avi, 0, sizeof(*avi));
00026         avi = _free(avi);
00027     }
00028     return NULL;
00029 }
00030 
00031 static rpmavi rpmaviNew(const char ** av, int flags)
00032 {
00033     rpmavi avi = xcalloc(1, sizeof(*avi));
00034     if (avi) {
00035         avi->av = av;
00036         avi->flags = flags;
00037     }
00038     return avi;
00039 }
00040 
00041 static const char * rpmaviNext(rpmavi avi)
00042 {
00043     const char * a = NULL;
00044 
00045     if (avi && avi->av && *avi->av)
00046         a = *avi->av++;
00047     return a;
00048 }
00049 
00050 /*@observer@*/ /*@unchecked@*/
00051 static const struct headerTagTableEntry_s rpmSTagTbl[] = {
00052         { "RPMTAG_HEADERIMAGE", HEADER_IMAGE, RPM_BIN_TYPE },
00053         { "RPMTAG_HEADERSIGNATURES", HEADER_SIGNATURES, RPM_BIN_TYPE },
00054         { "RPMTAG_HEADERIMMUTABLE", HEADER_IMMUTABLE, RPM_BIN_TYPE },
00055         { "RPMTAG_HEADERREGIONS", HEADER_REGIONS, RPM_BIN_TYPE },
00056         { "RPMTAG_SIGSIZE", 999+1, RPM_INT32_TYPE },
00057         { "RPMTAG_SIGLEMD5_1", 999+2, RPM_BIN_TYPE },
00058         { "RPMTAG_SIGPGP", 999+3, RPM_BIN_TYPE },
00059         { "RPMTAG_SIGLEMD5_2", 999+4, RPM_BIN_TYPE },
00060         { "RPMTAG_SIGMD5", 999+5, RPM_BIN_TYPE },
00061         { "RPMTAG_SIGGPG", 999+6, RPM_BIN_TYPE },
00062         { "RPMTAG_SIGPGP5", 999+7, RPM_BIN_TYPE },
00063         { "RPMTAG_SIGPAYLOADSIZE", 999+8, RPM_INT32_TYPE },
00064         { "RPMTAG_BADSHA1_1", HEADER_SIGBASE+8, RPM_STRING_TYPE },
00065         { "RPMTAG_BADSHA1_2", HEADER_SIGBASE+9, RPM_STRING_TYPE },
00066         { "RPMTAG_PUBKEYS", HEADER_SIGBASE+10, RPM_STRING_ARRAY_TYPE },
00067         { "RPMTAG_DSAHEADER", HEADER_SIGBASE+11, RPM_BIN_TYPE },
00068         { "RPMTAG_RSAHEADER", HEADER_SIGBASE+12, RPM_BIN_TYPE },
00069         { "RPMTAG_SHA1HEADER", HEADER_SIGBASE+13, RPM_STRING_TYPE },
00070         { NULL, 0 }
00071 };
00072 
00073 /*@observer@*/ /*@unchecked@*/
00074 const struct headerTagTableEntry_s * rpmSTagTable = rpmSTagTbl;
00075 
00076 
00077 typedef enum rpmtoolIOBits_e {
00078     RPMIOBITS_NONE      = 0,
00079     RPMIOBITS_LEAD      = (1 <<  0),
00080     RPMIOBITS_SHEADER   = (1 <<  1),
00081     RPMIOBITS_HEADER    = (1 <<  2),
00082     RPMIOBITS_PAYLOAD   = (1 <<  3),
00083     RPMIOBITS_FDIO      = (1 <<  4),
00084     RPMIOBITS_UFDIO     = (1 <<  5),
00085     RPMIOBITS_GZDIO     = (1 <<  6),
00086     RPMIOBITS_BZDIO     = (1 <<  7),
00087     RPMIOBITS_UNCOMPRESS= (1 <<  8),
00088     RPMIOBITS_BINARY    = (1 <<  9),
00089     RPMIOBITS_DUMP      = (1 << 10),
00090     RPMIOBITS_XML       = (1 << 11)
00091 } rpmtoolIOBits;
00092 
00093 static const char * iav[] = { "-", NULL };
00094 static const char * ifmt = NULL;
00095 static const char * ipath = NULL;
00096 static const char * imode = NULL;
00097 static rpmtoolIOBits ibits = RPMIOBITS_NONE;
00098 
00099 static const char * oav[] = { "-", NULL };
00100 static const char * ofmt = NULL;
00101 static const char * opath = NULL;
00102 static const char * omode = NULL;
00103 static rpmtoolIOBits obits = RPMIOBITS_NONE;
00104 
00105 static struct iobits_s {
00106     const char * name;
00107     rpmtoolIOBits bits;
00108 } iobits[] = {
00109     { "lead",           RPMIOBITS_LEAD },
00110     { "sheader",        RPMIOBITS_SHEADER },
00111     { "header",         RPMIOBITS_HEADER },
00112     { "payload",        RPMIOBITS_PAYLOAD },
00113 #define _RPMIOBITS_PKGMASK \
00114     (RPMIOBITS_LEAD|RPMIOBITS_SHEADER|RPMIOBITS_HEADER|RPMIOBITS_PAYLOAD)
00115 
00116     { "fdio",           RPMIOBITS_FDIO },
00117     { "ufdio",          RPMIOBITS_UFDIO },
00118     { "gzdio",          RPMIOBITS_GZDIO },
00119     { "bzdio",          RPMIOBITS_BZDIO },
00120 #define _RPMIOBITS_MODEMASK \
00121     (RPMIOBITS_FDIO|RPMIOBITS_UFDIO|RPMIOBITS_GZDIO|RPMIOBITS_BZDIO)
00122 
00123     { "uncompress",     RPMIOBITS_UNCOMPRESS },
00124     { "binary",         RPMIOBITS_BINARY },
00125     { "dump",           RPMIOBITS_DUMP },
00126     { "xml",            RPMIOBITS_XML },
00127     { NULL,     0 },
00128 };
00129 
00130 static int parseFmt(const char * fmt, rpmtoolIOBits * bits, const char ** mode)
00131 {
00132     const char *f, *fe;
00133 
00134     if (fmt != NULL)
00135     for (f = fmt; f && *f; f = fe) {
00136         struct iobits_s * iop;
00137         size_t nfe;
00138         
00139         if ((fe = strchr(f, ',')) == NULL)
00140             fe = f + strlen(f);
00141         nfe = (fe - f);
00142 
00143         for (iop = iobits; iop->name != NULL; iop++) {
00144             if (strncmp(iop->name, f, nfe))
00145                 continue;
00146             *bits |= iop->bits;
00147             if ((iop->bits & _RPMIOBITS_MODEMASK) && mode && *mode) {
00148                 char * t = xmalloc(2 + strlen(iop->name) + 1);
00149                 t[0] = (*mode)[0];
00150                 t[1] = (*mode)[1];
00151                 (void) stpcpy(t+2, iop->name);
00152                 *mode = _free(*mode);
00153                 *mode = t;
00154             }
00155             break;
00156         }
00157 
00158         if (iop->name == NULL) {
00159             fprintf(stderr, _("%s: unknown format token \"%*s\", ignored\n"),
00160                         __progname, nfe, f);
00161         }
00162 
00163         if (*fe == ',') fe++;   /* skip ',' */
00164     }
00165     return 0;
00166 }
00167 
00168 
00169 static struct poptOption optionsTable[] = {
00170  { "debug", 'd', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN,  &_rpmtool_debug, -1,
00171         NULL, NULL },
00172 
00173  { "lead", 'L', POPT_BIT_SET,   &obits, RPMIOBITS_LEAD,
00174         N_("extract lead"), NULL},
00175  { "sheader", 'S', POPT_BIT_SET,&obits, RPMIOBITS_SHEADER,
00176         N_("extract signature header"), NULL},
00177  { "header", 'H', POPT_BIT_SET, &obits, RPMIOBITS_HEADER,
00178         N_("extract metadata header"), NULL},
00179  { "dump", 'D', POPT_BIT_SET,   &obits, (RPMIOBITS_HEADER|RPMIOBITS_DUMP),
00180         N_("dump metadata header"), NULL},
00181  { "xml", 'X', POPT_BIT_SET,    &obits, (RPMIOBITS_HEADER|RPMIOBITS_XML),
00182         N_("dump metadata header in xml"), NULL},
00183  { "archive", 'A', POPT_BIT_SET,&obits, RPMIOBITS_PAYLOAD,
00184         N_("extract compressed payload"), NULL},
00185  { "payload", 'P', POPT_BIT_SET,&obits, RPMIOBITS_PAYLOAD|RPMIOBITS_UNCOMPRESS,
00186         N_("extract uncompressed payload"), NULL},
00187 
00188  { "ipath", 0, POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, &ipath, 0,
00189         N_("input PATH"), N_("PATH") },
00190  { "imode", 0, POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, &imode, 0,
00191         N_("input MODE"), N_("MODE") },
00192  { "ifmt", 'I', POPT_ARG_STRING,                        &ifmt, 0,
00193         N_("input format, FMT is comma separated list of (lead|sheader|header|payload), (ufdio|gzdio|bzdio), (binary|xml)"), N_("FMT") },
00194 
00195  { "opath", 0, POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, &opath, 0,
00196         N_("output PATH"), N_("PATH") },
00197  { "omode", 0, POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, &omode, 0,
00198         N_("output MODE"), N_("MODE") },
00199  { "ofmt", 'O', POPT_ARG_STRING,                        &ofmt, 0,
00200         N_("ouput format, FMT is comma separated list of (lead|sheader|header|payload), (ufdio|gzdio|bzdio), (binary|xml|dump)"), N_("FMT") },
00201 
00202  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
00203         N_("Common options for all rpm modes and executables:"),
00204         NULL }, 
00205 
00206    POPT_AUTOALIAS
00207    POPT_AUTOHELP
00208    POPT_TABLEEND
00209 };
00210 
00211 static void initTool(const char * argv0)
00212 {
00213     setprogname(argv0);
00214     /* XXX glibc churn sanity */
00215     if (__progname == NULL) {
00216         if ((__progname = strrchr(argv0, '/')) != NULL) __progname++;
00217         else __progname = argv0;
00218     }
00219 
00220     if (!strcmp(__progname, "rpmlead")) {
00221         ibits = _RPMIOBITS_PKGMASK;
00222         obits = RPMIOBITS_LEAD;
00223     }
00224     if (!strcmp(__progname, "rpmsignature")) {
00225         ibits = _RPMIOBITS_PKGMASK;
00226         obits = RPMIOBITS_SHEADER;
00227     }
00228     if (!strcmp(__progname, "rpmheader")) {
00229         ibits = _RPMIOBITS_PKGMASK;
00230         obits = RPMIOBITS_HEADER;
00231     }
00232     if (!strcmp(__progname, "rpm2cpio")) {
00233         ibits = _RPMIOBITS_PKGMASK;
00234         obits = RPMIOBITS_PAYLOAD | RPMIOBITS_UNCOMPRESS;
00235     }
00236     if (!strcmp(__progname, "rpmarchive")) {
00237         ibits = _RPMIOBITS_PKGMASK;
00238         obits = RPMIOBITS_PAYLOAD;
00239     }
00240     if (!strcmp(__progname, "dump")) {
00241         ibits = _RPMIOBITS_PKGMASK;
00242         obits = RPMIOBITS_HEADER | RPMIOBITS_DUMP;
00243     }
00244     if (!strcmp(__progname, "rpmdump")) {
00245         ibits = _RPMIOBITS_PKGMASK;
00246         obits = RPMIOBITS_HEADER | RPMIOBITS_DUMP;
00247     }
00248 }
00249 
00250 static void spewHeader(FD_t fdo, Header h)
00251 {
00252     headerTagTableEntry tbl = (headerIsEntry(h, RPMTAG_HEADERI18NTABLE))
00253                                 ? rpmTagTable : rpmSTagTable;
00254 
00255     if (obits & RPMIOBITS_DUMP) {
00256         headerDump(h, stdout, HEADER_DUMP_INLINE, tbl);
00257     } else if (obits & RPMIOBITS_XML) {
00258         const char * errstr = NULL;
00259         const char * fmt = "[%{*:xml}\n]";
00260         char * t;
00261 
00262         t = headerSprintf(h, fmt, tbl, rpmHeaderFormats, &errstr);
00263                 
00264         if (t != NULL) {
00265             if (rpmxpDTD != NULL && *rpmxpDTD != '\0')
00266                 Fwrite(rpmxpDTD, strlen(rpmxpDTD), 1, fdo);
00267             Fwrite(t, strlen(t), 1, fdo);
00268         }
00269         t = _free(t);
00270     } else
00271         headerWrite(fdo, h, HEADER_MAGIC_YES);
00272 }
00273 
00274 int
00275 main(int argc, char *const argv[])
00276 {
00277     struct rpmlead lead;
00278     Header sigh = NULL;
00279     Header h = NULL;
00280     FD_t fdi = NULL;
00281     FD_t fdo = NULL;
00282     const char ** av = NULL;
00283     rpmavi avi = NULL;
00284     const char * ifn = NULL;
00285     const char * ofn = NULL;
00286     const char * s;
00287     char * t, *te;
00288     poptContext optCon;
00289     rpmRC rc = RPMRC_OK;
00290     int ec = 0;
00291     int xx;
00292 
00293     imode = xstrdup("r.ufdio");
00294     omode = xstrdup("w.ufdio");
00295 
00296     initTool(argv[0]);       /* Retrofit glibc __progname */
00297 
00298     /* Parse CLI options and args. */
00299     optCon = rpmcliInit(argc, argv, optionsTable);
00300     if (optCon == NULL)
00301         exit(EXIT_FAILURE);
00302 
00303     av = poptGetArgs(optCon);
00304 if (_rpmtool_debug)
00305 fprintf(stderr, "*** av %p av[0] %p av[1] %p\n", av,
00306 (av && av[0] ? av[0] : NULL),
00307 (av && av[0] && av[1] ? av[1] : NULL));
00308     if (av == NULL) av = iav;
00309 
00310     /* Parse input and output format. */
00311     parseFmt(ifmt, &ibits, &imode);
00312     if (!(ibits & _RPMIOBITS_PKGMASK))
00313         ibits |= _RPMIOBITS_PKGMASK;
00314 
00315     parseFmt(ofmt, &obits, &omode);
00316     if (!(obits & _RPMIOBITS_PKGMASK))
00317         obits |= RPMIOBITS_HEADER;
00318 
00319     /* Insure desired output is possible. */
00320     if (((ibits & obits) & _RPMIOBITS_PKGMASK) != (obits & _RPMIOBITS_PKGMASK))
00321     {
00322         fprintf(stderr, _("%s: no input(0x%x) for output(0x%x) components\n"),
00323                 __progname, ibits, obits);
00324         ec++;
00325         goto bottom;
00326     }
00327 
00328     avi = rpmaviNew(av, 0);
00329     while ((ifn = rpmaviNext(avi)) != NULL) {
00330 
00331         /* Open input file. */
00332         if (fdi == NULL) {
00333 if (_rpmtool_debug)
00334 fprintf(stderr, "*** Fopen(%s,%s)\n", ifn, imode);
00335             fdi = Fopen(ifn, imode);
00336             if (fdi == NULL || Ferror(fdi)) {
00337                 fprintf(stderr, _("%s: input  Fopen(%s, \"%s\"): %s\n"),
00338                         __progname, ifn, imode, Fstrerror(fdi));
00339                 ec++;
00340                 goto bottom;
00341             }
00342         }
00343 
00344         /* Read package components. */
00345         if (ibits & RPMIOBITS_LEAD) {
00346             rc = readLead(fdi, &lead);
00347             if (rc != RPMRC_OK) {
00348                 fprintf(stderr, _("%s: readLead(%s) failed(%d)\n"),
00349                         __progname, ifn, rc);
00350                 ec++;
00351                 goto bottom;
00352             }
00353         }
00354 
00355         if (ibits & RPMIOBITS_SHEADER) {
00356             const char * msg = NULL;
00357             rc = rpmReadSignature(fdi, &sigh, RPMSIGTYPE_HEADERSIG, &msg);
00358             if (rc != RPMRC_OK) {
00359                 fprintf(stderr, _("%s: rpmReadSignature(%s) failed(%d): %s\n"),
00360                         __progname, ifn, rc, msg);
00361                 msg = _free(msg);
00362                 ec++;
00363                 goto bottom;
00364             }
00365         }
00366 
00367         if (ibits & RPMIOBITS_HEADER) {
00368             h = headerRead(fdi, HEADER_MAGIC_YES);
00369             if (h == NULL) {
00370                 fprintf(stderr, _("%s: headerRead(%s) failed\n"),
00371                         __progname, ifn);
00372                 ec++;
00373                 goto bottom;
00374             }
00375         }
00376 
00377         /* Determine output file name, and create directories in path. */
00378         if (fdo == NULL) {
00379             if (opath != NULL) {
00380                 const char * errstr = "(unkown error)";
00381                 int ut;
00382 
00383                 /* Macro and --queryformat expanded file path. */
00384                 s = rpmGetPath(opath, NULL);
00385                 ofn = headerSprintf(h, s, rpmTagTable, rpmHeaderFormats, &errstr);
00386                 s = _free(s);
00387                 if (ofn == NULL) {
00388                     fprintf(stderr, _("%s: headerSprintf(%s) failed: %s\n"),
00389                                 __progname, ofn, errstr);
00390                     ec++;
00391                     goto bottom;
00392                 }
00393 
00394                 /* Create directories in path. */
00395                 s = xstrdup(ofn);
00396                 ut = urlPath(s, (const char **)&t);
00397                 if (t != NULL)
00398                 for (te=strchr(t+1,'/'); (t=te) != NULL; te = strchr(t+1,'/')) {
00399                     *t = '\0';
00400                     rc = rpmMkdirPath(s, "opath");
00401                     *t = '/';
00402                     if (rc != RPMRC_OK) break;
00403                 }
00404                 s = _free(s);
00405                 if (rc != RPMRC_OK) {
00406                     fprintf(stderr, _("%s: rpmMkdirPath(%s) failed.\n"),
00407                                 __progname, ofn);
00408                     ec++;
00409                     goto bottom;
00410                 }
00411             }
00412 
00413             /* Open output file. */
00414 if (_rpmtool_debug)
00415 fprintf(stderr, "*** Fopen(%s,%s)\n", (ofn != NULL ? ofn : "-"), omode);
00416             fdo = (ofn != NULL ? Fopen(ofn, omode) : fdDup(STDOUT_FILENO));
00417             if (fdo == NULL || Ferror(fdo)) {
00418                 fprintf(stderr, _("%s: output Fopen(%s, \"%s\"): %s\n"),
00419                         __progname, (ofn != NULL ? ofn : "<stdout>"),
00420                         omode, Fstrerror(fdo));
00421                 ec++;
00422                 goto bottom;
00423             }
00424         }
00425 
00426         /* Write package components. */
00427         if (obits & RPMIOBITS_LEAD)
00428             writeLead(fdo, &lead);
00429 
00430         if (obits & RPMIOBITS_SHEADER)
00431             spewHeader(fdo, sigh);
00432 
00433         if (obits & RPMIOBITS_HEADER)
00434             spewHeader(fdo, h);
00435 
00436         if (obits & RPMIOBITS_PAYLOAD)
00437         {
00438             if (obits & RPMIOBITS_UNCOMPRESS) {
00439                 const char * payload_compressor = NULL;
00440                 const char * rpmio_flags;
00441                 FD_t gzdi;
00442 
00443                 /* Retrieve type of payload compression. */
00444                 if (!headerGetEntry(h, RPMTAG_PAYLOADCOMPRESSOR, NULL,
00445                             (void **) &payload_compressor, NULL))
00446                     payload_compressor = "gzip";
00447                 rpmio_flags = t = alloca(sizeof("r.gzdio"));
00448                 *t++ = 'r';
00449                 if (!strcmp(payload_compressor, "gzip"))
00450                     t = stpcpy(t, ".gzdio");
00451                 if (!strcmp(payload_compressor, "bzip2"))
00452                     t = stpcpy(t, ".bzdio");
00453 
00454                 gzdi = Fdopen(fdi, rpmio_flags);        /* XXX gzdi == fdi */
00455                 if (gzdi == NULL) {
00456                     fprintf(stderr, _("%s: output Fdopen(%s, \"%s\"): %s\n"),
00457                         __progname, (ofn != NULL ? ofn : "-"),
00458                         rpmio_flags, Fstrerror(fdo));
00459                     ec++;
00460                     goto bottom;
00461                 }
00462 
00463                 rc = ufdCopy(gzdi, fdo);
00464                 xx = Fclose(gzdi);      /* XXX gzdi == fdi */
00465                 if (rc <= 0) {
00466                     ec++;
00467                     goto bottom;
00468                 }
00469             } else {
00470                 char buffer[BUFSIZ];
00471                 int ct;
00472                 while ((ct = Fread(buffer, sizeof(buffer), 1, fdi)))
00473                     Fwrite(buffer, ct, 1, fdo);
00474             }
00475         }
00476 
00477 bottom:
00478         sigh = headerFree(sigh);
00479         h = headerFree(h);
00480         ofn = _free(ofn);
00481 
00482         if (fdi != NULL && Fileno(fdi) != STDIN_FILENO) {
00483             xx = Fclose(fdi);
00484             fdi = NULL;
00485         }
00486         if (fdo != NULL && Fileno(fdo) != STDOUT_FILENO) {
00487             xx = Fclose(fdo);
00488             fdo = NULL;
00489         }
00490     }
00491     avi = rpmaviFree(avi);
00492 
00493 exit:
00494     sigh = headerFree(sigh);
00495     h = headerFree(h);
00496     ofn = _free(ofn);
00497 
00498     if (fdi != NULL && Fileno(fdi) != STDIN_FILENO) {
00499         xx = Fclose(fdi);
00500         fdi = NULL;
00501     }
00502     if (fdo != NULL && Fileno(fdo) != STDOUT_FILENO) {
00503         xx = Fclose(fdi);
00504         fdi = NULL;
00505     }
00506     optCon = rpmcliFini(optCon);
00507 
00508     imode = _free(imode);
00509     omode = _free(omode);
00510 
00511     return ec;
00512 }

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