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
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
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++;
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
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]);
00297
00298
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
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
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
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
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
00378 if (fdo == NULL) {
00379 if (opath != NULL) {
00380 const char * errstr = "(unkown error)";
00381 int ut;
00382
00383
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
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
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
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
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);
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);
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 }