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

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

Generated on Mon Mar 5 13:30:24 2007 for rpm by  doxygen 1.4.4