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