| |
@@ -1,1640 +0,0 @@
|
| |
- diff --git a/Makefile.am b/Makefile.am
|
| |
- index 288668819..96542c8c8 100644
|
| |
- --- a/Makefile.am
|
| |
- +++ b/Makefile.am
|
| |
- @@ -185,7 +185,7 @@ bin_PROGRAMS += rpmgraph
|
| |
- rpmgraph_SOURCES = tools/rpmgraph.c
|
| |
- rpmgraph_LDADD = lib/librpm.la rpmio/librpmio.la @WITH_POPT_LIB@
|
| |
-
|
| |
- -dist_bin_SCRIPTS = scripts/gendiff
|
| |
- +dist_bin_SCRIPTS = scripts/gendiff scripts/rpm2extents_dump
|
| |
-
|
| |
- rpmconfig_DATA = rpmrc
|
| |
- rpmrc: $(top_srcdir)/rpmrc.in
|
| |
- diff --git a/lib/Makefile.am b/lib/Makefile.am
|
| |
- index 5a1b6ca9b..2f1b3597f 100644
|
| |
- --- a/lib/Makefile.am
|
| |
- +++ b/lib/Makefile.am
|
| |
- @@ -40,7 +40,8 @@ librpm_la_SOURCES = \
|
| |
- rpmscript.h rpmscript.c \
|
| |
- rpmchroot.c rpmchroot.h \
|
| |
- rpmplugins.c rpmplugins.h rpmplugin.h rpmug.c rpmug.h \
|
| |
- - rpmtriggers.h rpmtriggers.c rpmvs.c rpmvs.h
|
| |
- + rpmtriggers.h rpmtriggers.c rpmvs.c rpmvs.h \
|
| |
- + rpmextents.c rpmextents_internal.h
|
| |
-
|
| |
- librpm_la_LDFLAGS = -version-info $(rpm_version_info)
|
| |
-
|
| |
- diff --git a/lib/depends.c b/lib/depends.c
|
| |
- index 8998afcd3..30234df3d 100644
|
| |
- --- a/lib/depends.c
|
| |
- +++ b/lib/depends.c
|
| |
- @@ -81,8 +81,6 @@ static rpmRC headerCheckPayloadFormat(Header h) {
|
| |
- */
|
| |
- if (!payloadfmt) return rc;
|
| |
-
|
| |
- - if (rstreq(payloadfmt, "clon")) return rc;
|
| |
- -
|
| |
- if (!rstreq(payloadfmt, "cpio")) {
|
| |
- char *nevra = headerGetAsString(h, RPMTAG_NEVRA);
|
| |
- if (payloadfmt && rstreq(payloadfmt, "drpm")) {
|
| |
- diff --git a/lib/fsm.c b/lib/fsm.c
|
| |
- index feda3750c..6972602e0 100644
|
| |
- --- a/lib/fsm.c
|
| |
- +++ b/lib/fsm.c
|
| |
- @@ -19,7 +19,6 @@
|
| |
-
|
| |
- #include "rpmio/rpmio_internal.h" /* fdInit/FiniDigest */
|
| |
- #include "lib/fsm.h"
|
| |
- -#include "lib/rpmlib.h"
|
| |
- #include "lib/rpmte_internal.h" /* XXX rpmfs */
|
| |
- #include "lib/rpmplugins.h" /* rpm plugins hooks */
|
| |
- #include "lib/rpmug.h"
|
| |
- @@ -53,7 +52,6 @@ struct filedata_s {
|
| |
- int stage;
|
| |
- int setmeta;
|
| |
- int skip;
|
| |
- - int plugin_contents;
|
| |
- rpmFileAction action;
|
| |
- const char *suffix;
|
| |
- char *fpath;
|
| |
- @@ -893,14 +891,6 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
| |
- struct filedata_s *fdata = xcalloc(fc, sizeof(*fdata));
|
| |
- struct filedata_s *firstlink = NULL;
|
| |
-
|
| |
- - Header h = rpmteHeader(te);
|
| |
- - const char *payloadfmt = headerGetString(h, RPMTAG_PAYLOADFORMAT);
|
| |
- - int cpio = 1;
|
| |
- -
|
| |
- - if (payloadfmt && rstreq(payloadfmt, "clon")) {
|
| |
- - cpio = 0;
|
| |
- - }
|
| |
- -
|
| |
- /* transaction id used for temporary path suffix while installing */
|
| |
- rasprintf(&tid, ";%08x", (unsigned)rpmtsGetTid(ts));
|
| |
-
|
| |
- @@ -921,23 +911,12 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
| |
- /* Remap file perms, owner, and group. */
|
| |
- rc = rpmfiStat(fi, 1, &fp->sb);
|
| |
-
|
| |
- + setFileState(fs, fx);
|
| |
- fsmDebug(fp->fpath, fp->action, &fp->sb);
|
| |
-
|
| |
- /* Run fsm file pre hook for all plugins */
|
| |
- rc = rpmpluginsCallFsmFilePre(plugins, fi, fp->fpath,
|
| |
- fp->sb.st_mode, fp->action);
|
| |
- - fp->plugin_contents = 0;
|
| |
- - switch (rc) {
|
| |
- - case RPMRC_OK:
|
| |
- - setFileState(fs, fx);
|
| |
- - break;
|
| |
- - case RPMRC_PLUGIN_CONTENTS:
|
| |
- - fp->plugin_contents = 1;
|
| |
- - // reduce reads on cpio to this value. Could be zero if
|
| |
- - // this is from a hard link.
|
| |
- - rc = RPMRC_OK;
|
| |
- - break;
|
| |
- - }
|
| |
- fp->stage = FILE_PRE;
|
| |
- }
|
| |
- fi = rpmfiFree(fi);
|
| |
- @@ -945,14 +924,24 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
| |
- if (rc)
|
| |
- goto exit;
|
| |
-
|
| |
- - if (cpio) {
|
| |
- - fi = rpmfiNewArchiveReader(payload, files, RPMFI_ITER_READ_ARCHIVE);
|
| |
- - if (fi == NULL) {
|
| |
- - rc = RPMERR_BAD_MAGIC;
|
| |
- - goto exit;
|
| |
- - }
|
| |
- - } else {
|
| |
- - fi = rpmfilesIter(files, RPMFI_ITER_FWD);
|
| |
- + rpmRC plugin_rc = rpmpluginsCallFsmFileArchiveReader(plugins, payload, files, &fi);
|
| |
- + switch(plugin_rc) {
|
| |
- + case RPMRC_PLUGIN_CONTENTS:
|
| |
- + if(fi == NULL) {
|
| |
- + rc = RPMERR_BAD_MAGIC;
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + rc = RPMRC_OK;
|
| |
- + break;
|
| |
- + case RPMRC_OK:
|
| |
- + fi = rpmfiNewArchiveReader(payload, files, RPMFI_ITER_READ_ARCHIVE);
|
| |
- + if (fi == NULL) {
|
| |
- + rc = RPMERR_BAD_MAGIC;
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + break;
|
| |
- + default:
|
| |
- + rc = RPMRC_FAIL;
|
| |
- }
|
| |
-
|
| |
- /* Detect and create directories not explicitly in package. */
|
| |
- @@ -992,14 +981,15 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
| |
- if (fp->action == FA_TOUCH)
|
| |
- continue;
|
| |
-
|
| |
- - if (S_ISREG(fp->sb.st_mode)) {
|
| |
- + rpmRC plugin_rc = rpmpluginsCallFsmFileInstall(plugins, fi, fp->fpath, fp->sb.st_mode, fp->action);
|
| |
- + if(!(plugin_rc == RPMRC_PLUGIN_CONTENTS || plugin_rc == RPMRC_OK)){
|
| |
- + rc = plugin_rc;
|
| |
- + } else if(plugin_rc == RPMRC_PLUGIN_CONTENTS){
|
| |
- + rc = RPMRC_OK;
|
| |
- + } else if (S_ISREG(fp->sb.st_mode)) {
|
| |
- if (rc == RPMERR_ENOENT) {
|
| |
- - if(fp->plugin_contents) {
|
| |
- - rc = RPMRC_OK;
|
| |
- - }else {
|
| |
- - rc = fsmMkfile(fi, fp, files, psm, nodigest,
|
| |
- - &firstlink, &firstlinkfile);
|
| |
- - }
|
| |
- + rc = fsmMkfile(fi, fp, files, psm, nodigest,
|
| |
- + &firstlink, &firstlinkfile);
|
| |
- }
|
| |
- } else if (S_ISDIR(fp->sb.st_mode)) {
|
| |
- if (rc == RPMERR_ENOENT) {
|
| |
- @@ -1107,7 +1097,6 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
| |
- rpmswAdd(rpmtsOp(ts, RPMTS_OP_DIGEST), fdOp(payload, FDSTAT_DIGEST));
|
| |
-
|
| |
- exit:
|
| |
- - h = headerFree(h);
|
| |
- fi = rpmfiFree(fi);
|
| |
- Fclose(payload);
|
| |
- free(tid);
|
| |
- diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c
|
| |
- index 40a3ab83f..dc1726a18 100644
|
| |
- --- a/lib/rpmchecksig.c
|
| |
- +++ b/lib/rpmchecksig.c
|
| |
- @@ -20,6 +20,7 @@
|
| |
- #include "rpmio/rpmio_internal.h" /* fdSetBundle() */
|
| |
- #include "lib/rpmlead.h"
|
| |
- #include "lib/header_internal.h"
|
| |
- +#include "lib/rpmextents_internal.h"
|
| |
- #include "lib/rpmvs.h"
|
| |
-
|
| |
- #include "debug.h"
|
| |
- @@ -220,6 +221,71 @@ rpmRC rpmpkgRead(struct rpmvs_s *vs, FD_t fd,
|
| |
- return rc;
|
| |
- }
|
| |
-
|
| |
- +static int rpmpkgVerifySigsTranscoded(FD_t fd){
|
| |
- + rpm_loff_t current;
|
| |
- + uint64_t magic;
|
| |
- + rpm_loff_t offset;
|
| |
- + int32_t rc;
|
| |
- + size_t len;
|
| |
- + uint64_t content_len;
|
| |
- + char *content = NULL;
|
| |
- +
|
| |
- + current = Ftell(fd);
|
| |
- +
|
| |
- + if(Fseek(fd, -(sizeof(magic) + 3 * sizeof(offset) ), SEEK_END) < 0) {
|
| |
- + rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: failed to seek for offset\n"));
|
| |
- + rc = -1;
|
| |
- + goto exit;
|
| |
- + }
|
| |
- +
|
| |
- + len = sizeof(offset);
|
| |
- + if (Fread(&offset, len, 1, fd) != len) {
|
| |
- + rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read Signature Verification offset\n"));
|
| |
- + rc = -1;
|
| |
- + goto exit;
|
| |
- + }
|
| |
- +
|
| |
- + if(Fseek(fd, offset, SEEK_SET) < 0) {
|
| |
- + rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to seek signature verification offset\n"));
|
| |
- + rc = -1;
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + len = sizeof(rc);
|
| |
- + if (Fread(&rc, len, 1, fd) != len) {
|
| |
- + rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read Signature Verification RC\n"));
|
| |
- + rc = -1;
|
| |
- + goto exit;
|
| |
- + }
|
| |
- +
|
| |
- + len = sizeof(content_len);
|
| |
- + if (Fread(&content_len, len, 1, fd) != len) {
|
| |
- + rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read signature content length\n"));
|
| |
- + goto exit;
|
| |
- + }
|
| |
- +
|
| |
- + content = malloc(content_len + 1);
|
| |
- + if(content == NULL) {
|
| |
- + rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to allocate memory to read signature content\n"));
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + content[content_len] = 0;
|
| |
- + if (Fread(content, content_len, 1, fd) != content_len) {
|
| |
- + rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read signature content\n"));
|
| |
- + goto exit;
|
| |
- + }
|
| |
- +
|
| |
- + rpmlog(RPMLOG_NOTICE, "%s", content);
|
| |
- +exit:
|
| |
- + if(content){
|
| |
- + free(content);
|
| |
- + }
|
| |
- + if (Fseek(fd, current, SEEK_SET) < 0) {
|
| |
- + rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: unable to seek back to original location\n"));
|
| |
- + }
|
| |
- + return rc;
|
| |
- +
|
| |
- +}
|
| |
- +
|
| |
- static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags,
|
| |
- FD_t fd, const char *fn)
|
| |
- {
|
| |
- @@ -229,10 +295,14 @@ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags,
|
| |
- .verbose = rpmIsVerbose(),
|
| |
- };
|
| |
- int rc;
|
| |
- - struct rpmvs_s *vs = rpmvsCreate(vfylevel, flags, keyring);
|
| |
-
|
| |
- rpmlog(RPMLOG_NOTICE, "%s:%s", fn, vd.verbose ? "\n" : "");
|
| |
-
|
| |
- + if(isTranscodedRpm(fd) == RPMRC_OK){
|
| |
- + return rpmpkgVerifySigsTranscoded(fd);
|
| |
- + }
|
| |
- + struct rpmvs_s *vs = rpmvsCreate(vfylevel, flags, keyring);
|
| |
- +
|
| |
- rc = rpmpkgRead(vs, fd, NULL, NULL, &msg);
|
| |
-
|
| |
- if (rc)
|
| |
- @@ -260,6 +330,29 @@ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags,
|
| |
- return rc;
|
| |
- }
|
| |
-
|
| |
- +static int rpmpkgVerifySigsFD(rpmKeyring keyring, int vfylevel, rpmVSFlags flags,
|
| |
- + FD_t fd, rpmsinfoCb cb, void *cbdata)
|
| |
- +{
|
| |
- + char *msg = NULL;
|
| |
- + int rc;
|
| |
- + struct rpmvs_s *vs = rpmvsCreate(vfylevel, flags, keyring);
|
| |
- +
|
| |
- + rc = rpmpkgRead(vs, fd, NULL, NULL, &msg);
|
| |
- +
|
| |
- + if (rc)
|
| |
- + goto exit;
|
| |
- +
|
| |
- + rc = rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, cb, cbdata);
|
| |
- +
|
| |
- +exit:
|
| |
- + if (rc && msg)
|
| |
- + rpmlog(RPMLOG_ERR, "%s\n", msg);
|
| |
- + rpmvsFree(vs);
|
| |
- + free(msg);
|
| |
- + return rc;
|
| |
- +}
|
| |
- +
|
| |
- +
|
| |
- /* Wrapper around rpmkVerifySigs to preserve API */
|
| |
- int rpmVerifySignatures(QVA_t qva, rpmts ts, FD_t fd, const char * fn)
|
| |
- {
|
| |
- @@ -304,3 +397,53 @@ int rpmcliVerifySignatures(rpmts ts, ARGV_const_t argv)
|
| |
- rpmKeyringFree(keyring);
|
| |
- return res;
|
| |
- }
|
| |
- +
|
| |
- +struct vfydatafd_s {
|
| |
- + size_t len;
|
| |
- + char msg[BUFSIZ];
|
| |
- +};
|
| |
- +
|
| |
- +
|
| |
- +static int vfyFDCb(struct rpmsinfo_s *sinfo, void *cbdata)
|
| |
- +{
|
| |
- + struct vfydatafd_s *vd = cbdata;
|
| |
- + char *vmsg, *msg;
|
| |
- + size_t n;
|
| |
- + size_t remainder = BUFSIZ - vd->len;
|
| |
- +
|
| |
- + vmsg = rpmsinfoMsg(sinfo);
|
| |
- + rasprintf(&msg, " %s\n", vmsg);
|
| |
- + n = rstrlcpy(vd->msg + vd->len, msg, remainder);
|
| |
- + free(vmsg);
|
| |
- + free(msg);
|
| |
- + if(n <= remainder){
|
| |
- + vd->len += n;
|
| |
- + }
|
| |
- + return 1;
|
| |
- +}
|
| |
- +
|
| |
- +
|
| |
- +int rpmcliVerifySignaturesFD(rpmts ts, FD_t fdi, char **msg)
|
| |
- +{
|
| |
- + rpmRC rc = RPMRC_FAIL;
|
| |
- + rpmKeyring keyring = rpmtsGetKeyring(ts, 1);
|
| |
- + rpmVSFlags vsflags = rpmtsVfyFlags(ts);
|
| |
- + int vfylevel = rpmtsVfyLevel(ts);
|
| |
- + struct vfydatafd_s vd = {.len = 0};
|
| |
- +
|
| |
- + vsflags |= rpmcliVSFlags;
|
| |
- + if (rpmcliVfyLevelMask) {
|
| |
- + vfylevel &= ~rpmcliVfyLevelMask;
|
| |
- + rpmtsSetVfyLevel(ts, vfylevel);
|
| |
- + }
|
| |
- +
|
| |
- + if (!rpmpkgVerifySigsFD(keyring, vfylevel, vsflags, fdi, vfyFDCb, &vd)) {
|
| |
- + rc = RPMRC_OK;
|
| |
- + }
|
| |
- + *msg = strdup(vd.msg);
|
| |
- + rpmsqPoll();
|
| |
- +
|
| |
- + rpmKeyringFree(keyring);
|
| |
- + return rc;
|
| |
- +}
|
| |
- +
|
| |
- diff --git a/lib/rpmcli.h b/lib/rpmcli.h
|
| |
- index 906fe9951..7ff48b37a 100644
|
| |
- --- a/lib/rpmcli.h
|
| |
- +++ b/lib/rpmcli.h
|
| |
- @@ -411,6 +411,16 @@ int rpmcliImportPubkeys(rpmts ts, ARGV_const_t argv);
|
| |
- */
|
| |
- int rpmcliVerifySignatures(rpmts ts, ARGV_const_t argv);
|
| |
-
|
| |
- +
|
| |
- +/** \ingroup rpmcli
|
| |
- + * Verify package signatures.
|
| |
- + * @param ts transaction set
|
| |
- + * @param fd a file descriptor to verify
|
| |
- + * @param msg a string containing textual information about the verification, similar to rpmcliVerifySignatures output.
|
| |
- + * @return 0 on success
|
| |
- + */
|
| |
- +int rpmcliVerifySignaturesFD(rpmts ts, FD_t fd, char **msg);
|
| |
- +
|
| |
- #ifdef __cplusplus
|
| |
- }
|
| |
- #endif
|
| |
- diff --git a/lib/rpmextents.c b/lib/rpmextents.c
|
| |
- new file mode 100644
|
| |
- index 000000000..015277751
|
| |
- --- /dev/null
|
| |
- +++ b/lib/rpmextents.c
|
| |
- @@ -0,0 +1,46 @@
|
| |
- +
|
| |
- +#include "system.h"
|
| |
- +
|
| |
- +#include <rpm/rpmlog.h>
|
| |
- +#include <rpm/rpmio.h>
|
| |
- +
|
| |
- +#include "lib/rpmextents_internal.h"
|
| |
- +
|
| |
- +rpmRC isTranscodedRpm(FD_t fd) {
|
| |
- + rpmRC rc = RPMRC_NOTFOUND;
|
| |
- + rpm_loff_t current;
|
| |
- + extents_magic_t magic;
|
| |
- + size_t len;
|
| |
- +
|
| |
- + // If the file is not seekable, we cannot detect whether or not it is transcoded.
|
| |
- + if(Fseek(fd, 0, SEEK_CUR) < 0) {
|
| |
- + return RPMRC_FAIL;
|
| |
- + }
|
| |
- + current = Ftell(fd);
|
| |
- +
|
| |
- + if(Fseek(fd, -(sizeof(magic)), SEEK_END) < 0) {
|
| |
- + rpmlog(RPMLOG_ERR, _("isTranscodedRpm: failed to seek for magic\n"));
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + len = sizeof(magic);
|
| |
- + if (Fread(&magic, len, 1, fd) != len) {
|
| |
- + rpmlog(RPMLOG_ERR, _("isTranscodedRpm: unable to read magic\n"));
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + if (magic != EXTENTS_MAGIC) {
|
| |
- + rpmlog(RPMLOG_DEBUG, _("isTranscodedRpm: not transcoded\n"));
|
| |
- + rc = RPMRC_NOTFOUND;
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + rc = RPMRC_OK;
|
| |
- +exit:
|
| |
- + if (Fseek(fd, current, SEEK_SET) < 0) {
|
| |
- + rpmlog(RPMLOG_ERR, _("isTranscodedRpm: unable to seek back to original location\n"));
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + }
|
| |
- + return rc;
|
| |
- +}
|
| |
- +
|
| |
- +
|
| |
- diff --git a/lib/rpmextents_internal.h b/lib/rpmextents_internal.h
|
| |
- new file mode 100644
|
| |
- index 000000000..57cecfc31
|
| |
- --- /dev/null
|
| |
- +++ b/lib/rpmextents_internal.h
|
| |
- @@ -0,0 +1,22 @@
|
| |
- +#ifndef _RPMEXTENTS_INTERNAL_H
|
| |
- +#define _RPMEXTENTS_INTERNAL_H
|
| |
- +
|
| |
- +#ifdef __cplusplus
|
| |
- +extern "C" {
|
| |
- +#endif
|
| |
- +
|
| |
- +#include <stdint.h>
|
| |
- +
|
| |
- +/* magic value at end of file (64 bits) that indicates this is a transcoded
|
| |
- + * rpm.
|
| |
- + */
|
| |
- +#define EXTENTS_MAGIC 3472329499408095051
|
| |
- +
|
| |
- +typedef uint64_t extents_magic_t;
|
| |
- +
|
| |
- +rpmRC isTranscodedRpm(FD_t fd);
|
| |
- +
|
| |
- +#ifdef __cplusplus
|
| |
- +}
|
| |
- +#endif
|
| |
- +#endif
|
| |
- diff --git a/lib/rpmplugin.h b/lib/rpmplugin.h
|
| |
- index fd81aec8d..6dbbcff35 100644
|
| |
- --- a/lib/rpmplugin.h
|
| |
- +++ b/lib/rpmplugin.h
|
| |
- @@ -60,6 +60,13 @@ typedef rpmRC (*plugin_fsm_file_prepare_func)(rpmPlugin plugin, rpmfi fi,
|
| |
- const char* path,
|
| |
- const char *dest,
|
| |
- mode_t file_mode, rpmFsmOp op);
|
| |
- +typedef rpmRC (*plugin_fsm_file_install_func)(rpmPlugin plugin, rpmfi fi,
|
| |
- + const char* path,
|
| |
- + mode_t file_mode, rpmFsmOp op);
|
| |
- +typedef rpmRC (*plugin_fsm_file_archive_reader_func)(rpmPlugin plugin,
|
| |
- + FD_t payload,
|
| |
- + rpmfiles files, rpmfi *fi);
|
| |
- +
|
| |
-
|
| |
- typedef struct rpmPluginHooks_s * rpmPluginHooks;
|
| |
- struct rpmPluginHooks_s {
|
| |
- @@ -80,6 +87,8 @@ struct rpmPluginHooks_s {
|
| |
- plugin_fsm_file_pre_func fsm_file_pre;
|
| |
- plugin_fsm_file_post_func fsm_file_post;
|
| |
- plugin_fsm_file_prepare_func fsm_file_prepare;
|
| |
- + plugin_fsm_file_install_func fsm_file_install;
|
| |
- + plugin_fsm_file_archive_reader_func fsm_file_archive_reader;
|
| |
- };
|
| |
-
|
| |
- #ifdef __cplusplus
|
| |
- diff --git a/lib/rpmplugins.c b/lib/rpmplugins.c
|
| |
- index 3da3097af..901af1ac5 100644
|
| |
- --- a/lib/rpmplugins.c
|
| |
- +++ b/lib/rpmplugins.c
|
| |
- @@ -421,3 +421,74 @@ rpmRC rpmpluginsCallFsmFilePrepare(rpmPlugins plugins, rpmfi fi,
|
| |
-
|
| |
- return rc;
|
| |
- }
|
| |
- +
|
| |
- +rpmRC rpmpluginsCallFsmFileInstall(rpmPlugins plugins, rpmfi fi,
|
| |
- + const char *path, mode_t file_mode,
|
| |
- + rpmFsmOp op)
|
| |
- +{
|
| |
- + plugin_fsm_file_install_func hookFunc;
|
| |
- + int i;
|
| |
- + rpmRC rc = RPMRC_OK;
|
| |
- + rpmRC hook_rc;
|
| |
- +
|
| |
- + for (i = 0; i < plugins->count; i++) {
|
| |
- + rpmPlugin plugin = plugins->plugins[i];
|
| |
- + RPMPLUGINS_SET_HOOK_FUNC(fsm_file_install);
|
| |
- + if (hookFunc) {
|
| |
- + hook_rc = hookFunc(plugin, fi, path, file_mode, op);
|
| |
- + if (hook_rc == RPMRC_FAIL) {
|
| |
- + rpmlog(RPMLOG_ERR, "Plugin %s: hook fsm_file_install failed\n", plugin->name);
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + } else if (hook_rc == RPMRC_PLUGIN_CONTENTS && rc != RPMRC_FAIL) {
|
| |
- + if (rc == RPMRC_PLUGIN_CONTENTS) {
|
| |
- + /* Another plugin already said it'd handle contents. It's
|
| |
- + * undefined how these would combine, so treat this as a
|
| |
- + * failure condition.
|
| |
- + */
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + } else {
|
| |
- + /* Plugin will handle content */
|
| |
- + rc = RPMRC_PLUGIN_CONTENTS;
|
| |
- + }
|
| |
- + }
|
| |
- + }
|
| |
- + }
|
| |
- +
|
| |
- + return rc;
|
| |
- +}
|
| |
- +
|
| |
- +rpmRC rpmpluginsCallFsmFileArchiveReader(rpmPlugins plugins, FD_t payload,
|
| |
- + rpmfiles files, rpmfi *fi)
|
| |
- +{
|
| |
- + plugin_fsm_file_archive_reader_func hookFunc;
|
| |
- + int i;
|
| |
- + rpmRC rc = RPMRC_OK;
|
| |
- + rpmRC hook_rc;
|
| |
- +
|
| |
- + for (i = 0; i < plugins->count; i++) {
|
| |
- + rpmPlugin plugin = plugins->plugins[i];
|
| |
- + RPMPLUGINS_SET_HOOK_FUNC(fsm_file_archive_reader);
|
| |
- + if (hookFunc) {
|
| |
- + hook_rc = hookFunc(plugin, payload, files, fi);
|
| |
- + if (hook_rc == RPMRC_FAIL) {
|
| |
- + rpmlog(RPMLOG_ERR, "Plugin %s: hook fsm_file_archive_reader failed\n", plugin->name);
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + } else if (hook_rc == RPMRC_PLUGIN_CONTENTS && rc != RPMRC_FAIL) {
|
| |
- + if (rc == RPMRC_PLUGIN_CONTENTS) {
|
| |
- + /* Another plugin already said it'd handle contents. It's
|
| |
- + * undefined how these would combine, so treat this as a
|
| |
- + * failure condition.
|
| |
- + */
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + } else {
|
| |
- + /* Plugin will handle content */
|
| |
- + rc = RPMRC_PLUGIN_CONTENTS;
|
| |
- + }
|
| |
- + }
|
| |
- + }
|
| |
- + }
|
| |
- +
|
| |
- + return rc;
|
| |
- +}
|
| |
- +
|
| |
- +
|
| |
- diff --git a/lib/rpmplugins.h b/lib/rpmplugins.h
|
| |
- index 39762c376..88807c53c 100644
|
| |
- --- a/lib/rpmplugins.h
|
| |
- +++ b/lib/rpmplugins.h
|
| |
- @@ -167,6 +167,23 @@ rpmRC rpmpluginsCallFsmFilePrepare(rpmPlugins plugins, rpmfi fi,
|
| |
- const char *path, const char *dest,
|
| |
- mode_t mode, rpmFsmOp op);
|
| |
-
|
| |
- +/** \ingroup rpmplugins
|
| |
- + * Call the fsm file install plugin hook
|
| |
- + * @param plugins plugins structure
|
| |
- + * @param fi file info iterator (or NULL)
|
| |
- + * @param path file object path
|
| |
- + * @param file_mode file object mode
|
| |
- + * @param op file operation + associated flags
|
| |
- + * @return RPMRC_OK on success, RPMRC_FAIL otherwise
|
| |
- + */
|
| |
- +RPM_GNUC_INTERNAL
|
| |
- +rpmRC rpmpluginsCallFsmFileInstall(rpmPlugins plugins, rpmfi fi,
|
| |
- + const char* path, mode_t file_mode,
|
| |
- + rpmFsmOp op);
|
| |
- +
|
| |
- +RPM_GNUC_INTERNAL
|
| |
- +rpmRC rpmpluginsCallFsmFileArchiveReader(rpmPlugins plugins, FD_t payload,
|
| |
- + rpmfiles files, rpmfi *fi);
|
| |
- #ifdef __cplusplus
|
| |
- }
|
| |
- #endif
|
| |
- diff --git a/plugins/reflink.c b/plugins/reflink.c
|
| |
- index 513887604..4fc1d74d1 100644
|
| |
- --- a/plugins/reflink.c
|
| |
- +++ b/plugins/reflink.c
|
| |
- @@ -13,6 +13,7 @@
|
| |
- #include <rpm/rpmlog.h>
|
| |
- #include "lib/rpmlib.h"
|
| |
- #include "lib/rpmplugin.h"
|
| |
- +#include "lib/rpmextents_internal.h"
|
| |
- #include "lib/rpmte_internal.h"
|
| |
- #include <rpm/rpmfileutil.h>
|
| |
- #include "rpmio/rpmio_internal.h"
|
| |
- @@ -28,7 +29,7 @@
|
| |
- #undef HTDATATYPE
|
| |
- #define HASHTYPE inodeIndexHash
|
| |
- #define HTKEYTYPE rpm_ino_t
|
| |
- -#define HTDATATYPE int
|
| |
- +#define HTDATATYPE const char *
|
| |
- #include "lib/rpmhash.H"
|
| |
- #include "lib/rpmhash.C"
|
| |
-
|
| |
- @@ -40,11 +41,6 @@
|
| |
-
|
| |
- #define BUFFER_SIZE (1024 * 128)
|
| |
-
|
| |
- -/* magic value at end of file (64 bits) that indicates this is a transcoded
|
| |
- - * rpm.
|
| |
- - */
|
| |
- -#define MAGIC 3472329499408095051
|
| |
- -
|
| |
- struct reflink_state_s {
|
| |
- /* Stuff that's used across rpms */
|
| |
- long fundamental_block_size;
|
| |
- @@ -58,6 +54,7 @@ struct reflink_state_s {
|
| |
- FD_t fd;
|
| |
- rpmfiles files;
|
| |
- inodeIndexHash inodeIndexes;
|
| |
- + int transcoded;
|
| |
- };
|
| |
-
|
| |
- typedef struct reflink_state_s * reflink_state;
|
| |
- @@ -96,51 +93,35 @@ static void reflink_cleanup(rpmPlugin plugin) {
|
| |
- }
|
| |
-
|
| |
- static rpmRC reflink_psm_pre(rpmPlugin plugin, rpmte te) {
|
| |
- + rpmRC rc;
|
| |
- + size_t len;
|
| |
- +
|
| |
- reflink_state state = rpmPluginGetData(plugin);
|
| |
- state->fd = rpmteFd(te);
|
| |
- if (state->fd == 0) {
|
| |
- rpmlog(RPMLOG_DEBUG, _("reflink: fd = 0, no install\n"));
|
| |
- return RPMRC_OK;
|
| |
- }
|
| |
- +
|
| |
- rpm_loff_t current = Ftell(state->fd);
|
| |
- - uint64_t magic;
|
| |
- - if (Fseek(state->fd, -(sizeof(magic)), SEEK_END) < 0) {
|
| |
- - rpmlog(RPMLOG_ERR, _("reflink: failed to seek for magic\n"));
|
| |
- - if (Fseek(state->fd, current, SEEK_SET) < 0) {
|
| |
- - /* yes this gets a bit repetitive */
|
| |
- - rpmlog(RPMLOG_ERR,
|
| |
- - _("reflink: unable to seek back to original location\n"));
|
| |
- - }
|
| |
- - return RPMRC_FAIL;
|
| |
- - }
|
| |
- - size_t len = sizeof(magic);
|
| |
- - if (Fread(&magic, len, 1, state->fd) != len) {
|
| |
- - rpmlog(RPMLOG_ERR, _("reflink: unable to read magic\n"));
|
| |
- - if (Fseek(state->fd, current, SEEK_SET) < 0) {
|
| |
- - rpmlog(RPMLOG_ERR,
|
| |
- - _("reflink: unable to seek back to original location\n"));
|
| |
- - }
|
| |
- - return RPMRC_FAIL;
|
| |
- - }
|
| |
- - if (magic != MAGIC) {
|
| |
- - rpmlog(RPMLOG_DEBUG, _("reflink: not transcoded\n"));
|
| |
- - if (Fseek(state->fd, current, SEEK_SET) < 0) {
|
| |
- - rpmlog(RPMLOG_ERR,
|
| |
- - _("reflink: unable to seek back to original location\n"));
|
| |
- + rc = isTranscodedRpm(state->fd);
|
| |
- +
|
| |
- + switch(rc){
|
| |
- + // Fail to parse the file, fail the plugin.
|
| |
- + case RPMRC_FAIL:
|
| |
- return RPMRC_FAIL;
|
| |
- - }
|
| |
- - return RPMRC_OK;
|
| |
- + // This is not a transcoded file, do nothing.
|
| |
- + case RPMRC_NOTFOUND:
|
| |
- + return RPMRC_OK;
|
| |
- + default:
|
| |
- + break;
|
| |
- }
|
| |
- rpmlog(RPMLOG_DEBUG, _("reflink: *is* transcoded\n"));
|
| |
- - Header h = rpmteHeader(te);
|
| |
- + state->transcoded = 1;
|
| |
-
|
| |
- - /* replace/add header that main fsm.c can read */
|
| |
- - headerDel(h, RPMTAG_PAYLOADFORMAT);
|
| |
- - headerPutString(h, RPMTAG_PAYLOADFORMAT, "clon");
|
| |
- - headerFree(h);
|
| |
- state->files = rpmteFiles(te);
|
| |
- /* tail of file contains offset_table, offset_checksums then magic */
|
| |
- - if (Fseek(state->fd, -(sizeof(rpm_loff_t) * 2 + sizeof(magic)), SEEK_END) < 0) {
|
| |
- + if (Fseek(state->fd, -(sizeof(rpm_loff_t) * 2 + sizeof(extents_magic_t)), SEEK_END) < 0) {
|
| |
- rpmlog(RPMLOG_ERR, _("reflink: failed to seek for tail %p\n"),
|
| |
- state->fd);
|
| |
- return RPMRC_FAIL;
|
| |
- @@ -182,7 +163,7 @@ static rpmRC reflink_psm_pre(rpmPlugin plugin, rpmte te) {
|
| |
- return RPMRC_FAIL;
|
| |
- }
|
| |
- state->inodeIndexes = inodeIndexHashCreate(
|
| |
- - state->keys, inodeId, inodeCmp, NULL, NULL
|
| |
- + state->keys, inodeId, inodeCmp, NULL, (inodeIndexHashFreeData)rfree
|
| |
- );
|
| |
- }
|
| |
-
|
| |
- @@ -239,13 +220,13 @@ rpm_loff_t find(const unsigned char *digest, reflink_state state) {
|
| |
- return offset;
|
| |
- }
|
| |
-
|
| |
- -static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path,
|
| |
- +static rpmRC reflink_fsm_file_install(rpmPlugin plugin, rpmfi fi, const char* path,
|
| |
- mode_t file_mode, rpmFsmOp op)
|
| |
- {
|
| |
- struct file_clone_range fcr;
|
| |
- rpm_loff_t size;
|
| |
- int dst, rc;
|
| |
- - int *hlix;
|
| |
- + const char **hl_target = NULL;
|
| |
-
|
| |
- reflink_state state = rpmPluginGetData(plugin);
|
| |
- if (state->table == NULL) {
|
| |
- @@ -262,18 +243,15 @@ static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path,
|
| |
- /* check for hard link entry in table. GetEntry overwrites hlix with
|
| |
- * the address of the first match.
|
| |
- */
|
| |
- - if (inodeIndexHashGetEntry(state->inodeIndexes, inode, &hlix, NULL,
|
| |
- - NULL)) {
|
| |
- + if (inodeIndexHashGetEntry(state->inodeIndexes, inode, &hl_target,
|
| |
- + NULL, NULL)) {
|
| |
- /* entry is in table, use hard link */
|
| |
- - char *fn = rpmfilesFN(state->files, hlix[0]);
|
| |
- - if (link(fn, path) != 0) {
|
| |
- + if (link(hl_target[0], path) != 0) {
|
| |
- rpmlog(RPMLOG_ERR,
|
| |
- _("reflink: Unable to hard link %s -> %s due to %s\n"),
|
| |
- - fn, path, strerror(errno));
|
| |
- - free(fn);
|
| |
- + hl_target[0], path, strerror(errno));
|
| |
- return RPMRC_FAIL;
|
| |
- }
|
| |
- - free(fn);
|
| |
- return RPMRC_PLUGIN_CONTENTS;
|
| |
- }
|
| |
- /* if we didn't hard link, then we'll track this inode as being
|
| |
- @@ -281,7 +259,7 @@ static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path,
|
| |
- */
|
| |
- if (rpmfiFNlink(fi) > 1) {
|
| |
- /* minor optimization: only store files with more than one link */
|
| |
- - inodeIndexHashAddEntry(state->inodeIndexes, inode, rpmfiFX(fi));
|
| |
- + inodeIndexHashAddEntry(state->inodeIndexes, inode, rstrdup(path));
|
| |
- }
|
| |
- /* derived from wfd_open in fsm.c */
|
| |
- mode_t old_umask = umask(0577);
|
| |
- @@ -366,10 +344,21 @@ static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path,
|
| |
- return RPMRC_OK;
|
| |
- }
|
| |
-
|
| |
- +static rpmRC reflink_fsm_file_archive_reader(rpmPlugin plugin, FD_t payload,
|
| |
- + rpmfiles files, rpmfi *fi) {
|
| |
- + reflink_state state = rpmPluginGetData(plugin);
|
| |
- + if(state->transcoded) {
|
| |
- + *fi = rpmfilesIter(files, RPMFI_ITER_FWD);
|
| |
- + return RPMRC_PLUGIN_CONTENTS;
|
| |
- + }
|
| |
- + return RPMRC_OK;
|
| |
- +}
|
| |
- +
|
| |
- struct rpmPluginHooks_s reflink_hooks = {
|
| |
- .init = reflink_init,
|
| |
- .cleanup = reflink_cleanup,
|
| |
- .psm_pre = reflink_psm_pre,
|
| |
- .psm_post = reflink_psm_post,
|
| |
- - .fsm_file_pre = reflink_fsm_file_pre,
|
| |
- + .fsm_file_install = reflink_fsm_file_install,
|
| |
- + .fsm_file_archive_reader = reflink_fsm_file_archive_reader,
|
| |
- };
|
| |
- diff --git a/rpm2extents.c b/rpm2extents.c
|
| |
- index c111be0a2..a326e3857 100644
|
| |
- --- a/rpm2extents.c
|
| |
- +++ b/rpm2extents.c
|
| |
- @@ -2,7 +2,9 @@
|
| |
-
|
| |
- #include "system.h"
|
| |
-
|
| |
- +#include <rpm/rpmcli.h>
|
| |
- #include <rpm/rpmlib.h> /* rpmReadPackageFile .. */
|
| |
- +#include <rpm/rpmlog.h>
|
| |
- #include <rpm/rpmfi.h>
|
| |
- #include <rpm/rpmtag.h>
|
| |
- #include <rpm/rpmio.h>
|
| |
- @@ -10,8 +12,10 @@
|
| |
-
|
| |
- #include <rpm/rpmts.h>
|
| |
- #include "lib/rpmlead.h"
|
| |
- +#include "lib/rpmts.h"
|
| |
- #include "lib/signature.h"
|
| |
- #include "lib/header_internal.h"
|
| |
- +#include "lib/rpmextents_internal.h"
|
| |
- #include "rpmio/rpmio_internal.h"
|
| |
-
|
| |
- #include <unistd.h>
|
| |
- @@ -34,11 +38,6 @@
|
| |
- #include "lib/rpmhash.H"
|
| |
- #include "lib/rpmhash.C"
|
| |
-
|
| |
- -/* magic value at end of file (64 bits) that indicates this is a transcoded
|
| |
- - * rpm.
|
| |
- - */
|
| |
- -#define MAGIC 3472329499408095051
|
| |
- -
|
| |
- struct digestoffset {
|
| |
- const unsigned char * digest;
|
| |
- rpm_loff_t pos;
|
| |
- @@ -51,38 +50,47 @@ rpm_loff_t pad_to(rpm_loff_t pos, rpm_loff_t unit)
|
| |
- return (unit - (pos % unit)) % unit;
|
| |
- }
|
| |
-
|
| |
- -static int digestor(
|
| |
- +static struct poptOption optionsTable[] = {
|
| |
- + { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
|
| |
- + N_("Common options for all rpm modes and executables:"), NULL },
|
| |
- +
|
| |
- + POPT_AUTOALIAS
|
| |
- + POPT_AUTOHELP
|
| |
- + POPT_TABLEEND
|
| |
- +};
|
| |
- +
|
| |
- +
|
| |
- +static void FDDigestInit(FD_t fdi, uint8_t algos[], uint32_t algos_len){
|
| |
- + int algo;
|
| |
- +
|
| |
- + for (algo = 0; algo < algos_len; algo++) {
|
| |
- + fdInitDigest(fdi, algos[algo], 0);
|
| |
- + }
|
| |
- +}
|
| |
- +
|
| |
- +static int FDWriteDigests(
|
| |
- FD_t fdi,
|
| |
- FD_t fdo,
|
| |
- - FD_t validationo,
|
| |
- uint8_t algos[],
|
| |
- - uint32_t algos_len
|
| |
- -)
|
| |
- + uint32_t algos_len)
|
| |
- {
|
| |
- - ssize_t fdilength;
|
| |
- const char *filedigest, *algo_name;
|
| |
- size_t filedigest_len, len;
|
| |
- uint32_t algo_name_len, algo_digest_len;
|
| |
- int algo;
|
| |
- rpmRC rc = RPMRC_FAIL;
|
| |
-
|
| |
- - for (algo = 0; algo < algos_len; algo++) {
|
| |
- - fdInitDigest(fdi, algos[algo], 0);
|
| |
- - }
|
| |
- - fdilength = ufdCopy(fdi, fdo);
|
| |
- - if (fdilength == -1) {
|
| |
- - fprintf(stderr, _("digest cat failed\n"));
|
| |
- - goto exit;
|
| |
- - }
|
| |
- + ssize_t fdilength = fdOp(fdi, FDSTAT_READ)->bytes;
|
| |
-
|
| |
- len = sizeof(fdilength);
|
| |
- - if (Fwrite(&fdilength, len, 1, validationo) != len) {
|
| |
- + if (Fwrite(&fdilength, len, 1, fdo) != len) {
|
| |
- fprintf(stderr, _("Unable to write input length %zd\n"), fdilength);
|
| |
- goto exit;
|
| |
- }
|
| |
- len = sizeof(algos_len);
|
| |
- - if (Fwrite(&algos_len, len, 1, validationo) != len) {
|
| |
- - fprintf(stderr, _("Unable to write number of validation digests\n"));
|
| |
- + if (Fwrite(&algos_len, len, 1, fdo) != len) {
|
| |
- + algo_digest_len = (uint32_t)filedigest_len;
|
| |
- + fprintf(stderr, _("Unable to write number of digests\n"));
|
| |
- goto exit;
|
| |
- }
|
| |
- for (algo = 0; algo < algos_len; algo++) {
|
| |
- @@ -93,24 +101,24 @@ static int digestor(
|
| |
- algo_digest_len = (uint32_t)filedigest_len;
|
| |
-
|
| |
- len = sizeof(algo_name_len);
|
| |
- - if (Fwrite(&algo_name_len, len, 1, validationo) != len) {
|
| |
- + if (Fwrite(&algo_name_len, len, 1, fdo) != len) {
|
| |
- fprintf(stderr,
|
| |
- - _("Unable to write validation algo name length\n"));
|
| |
- + _("Unable to write digest algo name length\n"));
|
| |
- goto exit;
|
| |
- }
|
| |
- len = sizeof(algo_digest_len);
|
| |
- - if (Fwrite(&algo_digest_len, len, 1, validationo) != len) {
|
| |
- + if (Fwrite(&algo_digest_len, len, 1, fdo) != len) {
|
| |
- fprintf(stderr,
|
| |
- - _("Unable to write number of bytes for validation digest\n"));
|
| |
- + _("Unable to write number of bytes for digest\n"));
|
| |
- goto exit;
|
| |
- }
|
| |
- - if (Fwrite(algo_name, algo_name_len, 1, validationo) != algo_name_len) {
|
| |
- - fprintf(stderr, _("Unable to write validation algo name\n"));
|
| |
- + if (Fwrite(algo_name, algo_name_len, 1, fdo) != algo_name_len) {
|
| |
- + fprintf(stderr, _("Unable to write digest algo name\n"));
|
| |
- goto exit;
|
| |
- }
|
| |
- - if (Fwrite(filedigest, algo_digest_len, 1, validationo ) != algo_digest_len) {
|
| |
- + if (Fwrite(filedigest, algo_digest_len, 1, fdo ) != algo_digest_len) {
|
| |
- fprintf(stderr,
|
| |
- - _("Unable to write validation digest value %u, %zu\n"),
|
| |
- + _("Unable to write digest value %u, %zu\n"),
|
| |
- algo_digest_len, filedigest_len);
|
| |
- goto exit;
|
| |
- }
|
| |
- @@ -120,7 +128,69 @@ static int digestor(
|
| |
- return rc;
|
| |
- }
|
| |
-
|
| |
- -static rpmRC process_package(FD_t fdi, FD_t validationi)
|
| |
- +static rpmRC FDWriteSignaturesValidation(FD_t fdo, int rpmvsrc, char *msg) {
|
| |
- + size_t len;
|
| |
- + rpmRC rc = RPMRC_FAIL;
|
| |
- +
|
| |
- + if(rpmvsrc){
|
| |
- + fprintf(stderr, _("Error verifying package signatures\n"));
|
| |
- + }
|
| |
- +
|
| |
- + len = sizeof(rpmvsrc);
|
| |
- + if (Fwrite(&rpmvsrc, len, 1, fdo) != len) {
|
| |
- + fprintf(stderr, _("Unable to write signature verification RC code %d\n"), rpmvsrc);
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + size_t content_len = msg ? strlen(msg) : 0;
|
| |
- + len = sizeof(content_len);
|
| |
- + if (Fwrite(&content_len, len, 1, fdo) != len) {
|
| |
- + fprintf(stderr, _("Unable to write signature verification output length %zd\n"), content_len);
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + if (Fwrite(msg, content_len, 1, fdo) != content_len) {
|
| |
- + fprintf(stderr, _("Unable to write signature verification output %s\n"), msg);
|
| |
- + goto exit;
|
| |
- + }
|
| |
- +
|
| |
- + rc = RPMRC_OK;
|
| |
- +exit:
|
| |
- +
|
| |
- + return rc;
|
| |
- +}
|
| |
- +
|
| |
- +static rpmRC validator(FD_t fdi, FD_t digesto, FD_t sigo,
|
| |
- + uint8_t algos[],
|
| |
- + uint32_t algos_len){
|
| |
- + int rpmvsrc;
|
| |
- + rpmRC rc = RPMRC_FAIL;
|
| |
- + char *msg = NULL;
|
| |
- + rpmts ts = rpmtsCreate();
|
| |
- +
|
| |
- + rpmtsSetRootDir(ts, rpmcliRootDir);
|
| |
- +
|
| |
- + FDDigestInit(fdi, algos, algos_len);
|
| |
- +
|
| |
- + rpmvsrc = rpmcliVerifySignaturesFD(ts, fdi, &msg);
|
| |
- +
|
| |
- + // Write result of digest computation
|
| |
- + if(FDWriteDigests(fdi, digesto, algos, algos_len) != RPMRC_OK) {
|
| |
- + fprintf(stderr, _("Failed to write digests"));
|
| |
- + goto exit;
|
| |
- + }
|
| |
- +
|
| |
- + // Write result of signature validation.
|
| |
- + if(FDWriteSignaturesValidation(sigo, rpmvsrc, msg)) {
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + rc = RPMRC_OK;
|
| |
- +exit:
|
| |
- + if(msg) {
|
| |
- + free(msg);
|
| |
- + }
|
| |
- + return rc;
|
| |
- +}
|
| |
- +
|
| |
- +static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
|
| |
- {
|
| |
- uint32_t diglen;
|
| |
- /* GNU C extension: can use diglen from outer context */
|
| |
- @@ -148,7 +218,7 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
|
| |
- rpm_mode_t mode;
|
| |
- char *rpmio_flags = NULL, *zeros;
|
| |
- const unsigned char *digest;
|
| |
- - rpm_loff_t pos, size, pad, validation_pos;
|
| |
- + rpm_loff_t pos, size, pad, digest_pos, validation_pos, digest_table_pos;
|
| |
- uint32_t offset_ix = 0;
|
| |
- size_t len;
|
| |
- int next = 0;
|
| |
- @@ -253,6 +323,16 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
|
| |
- qsort(offsets, (size_t)offset_ix, sizeof(struct digestoffset),
|
| |
- digestoffsetCmp);
|
| |
-
|
| |
- + validation_pos = pos;
|
| |
- + ssize_t validation_len = ufdCopy(validationi, fdo);
|
| |
- + if (validation_len == -1) {
|
| |
- + fprintf(stderr, _("validation output ufdCopy failed\n"));
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + goto exit;
|
| |
- + }
|
| |
- +
|
| |
- + digest_table_pos = validation_pos + validation_len;
|
| |
- +
|
| |
- len = sizeof(offset_ix);
|
| |
- if (Fwrite(&offset_ix, len, 1, fdo) != len) {
|
| |
- fprintf(stderr, _("Unable to write length of table\n"));
|
| |
- @@ -278,17 +358,18 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
|
| |
- goto exit;
|
| |
- }
|
| |
- }
|
| |
- - validation_pos = (
|
| |
- - pos + sizeof(offset_ix) + sizeof(diglen) +
|
| |
- + digest_pos = (
|
| |
- + digest_table_pos + sizeof(offset_ix) + sizeof(diglen) +
|
| |
- offset_ix * (diglen + sizeof(rpm_loff_t))
|
| |
- );
|
| |
-
|
| |
- - ssize_t validation_len = ufdCopy(validationi, fdo);
|
| |
- - if (validation_len == -1) {
|
| |
- + ssize_t digest_len = ufdCopy(digestori, fdo);
|
| |
- + if (digest_len == -1) {
|
| |
- fprintf(stderr, _("digest table ufdCopy failed\n"));
|
| |
- rc = RPMRC_FAIL;
|
| |
- goto exit;
|
| |
- }
|
| |
- +
|
| |
- /* add more padding so the last file can be cloned. It doesn't matter that
|
| |
- * the table and validation etc are in this space. In fact, it's pretty
|
| |
- * efficient if it is.
|
| |
- @@ -302,17 +383,22 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
|
| |
- goto exit;
|
| |
- }
|
| |
- zeros = _free(zeros);
|
| |
- - if (Fwrite(&pos, len, 1, fdo) != len) {
|
| |
- + if (Fwrite(&validation_pos, len, 1, fdo) != len) {
|
| |
- + fprintf(stderr, _("Unable to write offset of validation output\n"));
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + if (Fwrite(&digest_table_pos, len, 1, fdo) != len) {
|
| |
- fprintf(stderr, _("Unable to write offset of digest table\n"));
|
| |
- rc = RPMRC_FAIL;
|
| |
- goto exit;
|
| |
- }
|
| |
- - if (Fwrite(&validation_pos, len, 1, fdo) != len) {
|
| |
- + if (Fwrite(&digest_pos, len, 1, fdo) != len) {
|
| |
- fprintf(stderr, _("Unable to write offset of validation table\n"));
|
| |
- rc = RPMRC_FAIL;
|
| |
- goto exit;
|
| |
- }
|
| |
- - uint64_t magic = MAGIC;
|
| |
- + extents_magic_t magic = EXTENTS_MAGIC;
|
| |
- len = sizeof(magic);
|
| |
- if (Fwrite(&magic, len, 1, fdo) != len) {
|
| |
- fprintf(stderr, _("Unable to write magic\n"));
|
| |
- @@ -327,104 +413,200 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
|
| |
- return rc;
|
| |
- }
|
| |
-
|
| |
- -int main(int argc, char *argv[]) {
|
| |
- - rpmRC rc;
|
| |
- - int cprc = 0;
|
| |
- - uint8_t algos[argc - 1];
|
| |
- - int mainpipefd[2];
|
| |
- - int metapipefd[2];
|
| |
- - pid_t cpid, w;
|
| |
- - int wstatus;
|
| |
- +static off_t ufdTee(FD_t sfd, FD_t *fds, int len)
|
| |
- +{
|
| |
- + char buf[BUFSIZ];
|
| |
- + ssize_t rdbytes, wrbytes;
|
| |
- + off_t total = 0;
|
| |
- +
|
| |
- + while (1) {
|
| |
- + rdbytes = Fread(buf, sizeof(buf[0]), sizeof(buf), sfd);
|
| |
- +
|
| |
- + if (rdbytes > 0) {
|
| |
- + for(int i=0; i < len; i++) {
|
| |
- + wrbytes = Fwrite(buf, sizeof(buf[0]), rdbytes, fds[i]);
|
| |
- + if (wrbytes != rdbytes) {
|
| |
- + fprintf(stderr, "Error wriing to FD %d: %s\n", i, Fstrerror(fds[i]));
|
| |
- + total = -1;
|
| |
- + break;
|
| |
- + }
|
| |
- + }
|
| |
- + if(total == -1){
|
| |
- + break;
|
| |
- + }
|
| |
- + total += wrbytes;
|
| |
- + } else {
|
| |
- + if (rdbytes < 0)
|
| |
- + total = -1;
|
| |
- + break;
|
| |
- + }
|
| |
- + }
|
| |
-
|
| |
- - xsetprogname(argv[0]); /* Portability call -- see system.h */
|
| |
- - rpmReadConfigFiles(NULL, NULL);
|
| |
- + return total;
|
| |
- +}
|
| |
-
|
| |
- - if (argc > 1 && (rstreq(argv[1], "-h") || rstreq(argv[1], "--help"))) {
|
| |
- - fprintf(stderr, _("Usage: %s [DIGESTALGO]...\n"), argv[0]);
|
| |
- - exit(EXIT_FAILURE);
|
| |
- - }
|
| |
- +static rpmRC teeRpm(FD_t fdi, uint8_t algos[], uint32_t algos_len) {
|
| |
- + rpmRC rc = RPMRC_FAIL;
|
| |
- + off_t offt = -1;
|
| |
- + // tee-ed stdin
|
| |
- + int processorpipefd[2];
|
| |
- + int validatorpipefd[2];
|
| |
- + // metadata
|
| |
- + int meta_digestpipefd[2];
|
| |
- + int meta_rpmsignpipefd[2];
|
| |
- +
|
| |
- + pid_t cpids[2], w;
|
| |
- + int wstatus;
|
| |
- + FD_t fds[2];
|
| |
-
|
| |
- - if (argc == 1) {
|
| |
- - fprintf(stderr,
|
| |
- - _("Need at least one DIGESTALGO parameter, e.g. 'SHA256'\n"));
|
| |
- - exit(EXIT_FAILURE);
|
| |
- + if (pipe(processorpipefd) == -1) {
|
| |
- + fprintf(stderr, _("Processor pipe failure\n"));
|
| |
- + return RPMRC_FAIL;
|
| |
- }
|
| |
-
|
| |
- - for (int x = 0; x < (argc - 1); x++) {
|
| |
- - if (pgpStringVal(PGPVAL_HASHALGO, argv[x + 1], &algos[x]) != 0)
|
| |
- - {
|
| |
- - fprintf(stderr,
|
| |
- - _("Unable to resolve '%s' as a digest algorithm, exiting\n"),
|
| |
- - argv[x + 1]);
|
| |
- - exit(EXIT_FAILURE);
|
| |
- - }
|
| |
- + if (pipe(validatorpipefd) == -1) {
|
| |
- + fprintf(stderr, _("Validator pipe failure\n"));
|
| |
- + return RPMRC_FAIL;
|
| |
- }
|
| |
-
|
| |
- -
|
| |
- - if (pipe(mainpipefd) == -1) {
|
| |
- - fprintf(stderr, _("Main pipe failure\n"));
|
| |
- - exit(EXIT_FAILURE);
|
| |
- + if (pipe(meta_digestpipefd) == -1) {
|
| |
- + fprintf(stderr, _("Meta digest pipe failure\n"));
|
| |
- + return RPMRC_FAIL;
|
| |
- }
|
| |
- - if (pipe(metapipefd) == -1) {
|
| |
- - fprintf(stderr, _("Meta pipe failure\n"));
|
| |
- - exit(EXIT_FAILURE);
|
| |
- +
|
| |
- + if (pipe(meta_rpmsignpipefd) == -1) {
|
| |
- + fprintf(stderr, _("Meta rpm signature pipe failure\n"));
|
| |
- + return RPMRC_FAIL;
|
| |
- }
|
| |
- - cpid = fork();
|
| |
- - if (cpid == 0) {
|
| |
- - /* child: digestor */
|
| |
- - close(mainpipefd[0]);
|
| |
- - close(metapipefd[0]);
|
| |
- - FD_t fdi = fdDup(STDIN_FILENO);
|
| |
- - FD_t fdo = fdDup(mainpipefd[1]);
|
| |
- - FD_t validationo = fdDup(metapipefd[1]);
|
| |
- - rc = digestor(fdi, fdo, validationo, algos, argc - 1);
|
| |
- - Fclose(validationo);
|
| |
- - Fclose(fdo);
|
| |
- +
|
| |
- + cpids[0] = fork();
|
| |
- + if (cpids[0] == 0) {
|
| |
- + /* child: validator */
|
| |
- + close(processorpipefd[0]);
|
| |
- + close(processorpipefd[1]);
|
| |
- + close(validatorpipefd[1]);
|
| |
- + close(meta_digestpipefd[0]);
|
| |
- + close(meta_rpmsignpipefd[0]);
|
| |
- + FD_t fdi = fdDup(validatorpipefd[0]);
|
| |
- + FD_t digesto = fdDup(meta_digestpipefd[1]);
|
| |
- + FD_t sigo = fdDup(meta_rpmsignpipefd[1]);
|
| |
- + close(meta_digestpipefd[1]);
|
| |
- + close(meta_rpmsignpipefd[1]);
|
| |
- + rc = validator(fdi, digesto, sigo, algos, algos_len);
|
| |
- + if(rc != RPMRC_OK) {
|
| |
- + fprintf(stderr, _("Validator failed\n"));
|
| |
- + }
|
| |
- Fclose(fdi);
|
| |
- + Fclose(digesto);
|
| |
- + Fclose(sigo);
|
| |
- + if (rc != RPMRC_OK) {
|
| |
- + exit(EXIT_FAILURE);
|
| |
- + }
|
| |
- + exit(EXIT_SUCCESS);
|
| |
- } else {
|
| |
- /* parent: main program */
|
| |
- - close(mainpipefd[1]);
|
| |
- - close(metapipefd[1]);
|
| |
- - FD_t fdi = fdDup(mainpipefd[0]);
|
| |
- - FD_t validationi = fdDup(metapipefd[0]);
|
| |
- - rc = process_package(fdi, validationi);
|
| |
- - Fclose(validationi);
|
| |
- - /* fdi is normally closed through the stacked file gzdi in the
|
| |
- - * function.
|
| |
- - * Wait for child process (digestor for stdin) to complete.
|
| |
- - */
|
| |
- - if (rc != RPMRC_OK) {
|
| |
- - if (kill(cpid, SIGTERM) != 0) {
|
| |
- - fprintf(stderr,
|
| |
- - _("Failed to kill digest process when main process failed: %s\n"),
|
| |
- - strerror(errno));
|
| |
- + cpids[1] = fork();
|
| |
- + if (cpids[1] == 0) {
|
| |
- + /* child: process_package */
|
| |
- + close(validatorpipefd[0]);
|
| |
- + close(validatorpipefd[1]);
|
| |
- + close(processorpipefd[1]);
|
| |
- + close(meta_digestpipefd[1]);
|
| |
- + close(meta_rpmsignpipefd[1]);
|
| |
- + FD_t fdi = fdDup(processorpipefd[0]);
|
| |
- + close(processorpipefd[0]);
|
| |
- + FD_t sigi = fdDup(meta_rpmsignpipefd[0]);
|
| |
- + close(meta_rpmsignpipefd[0]);
|
| |
- + FD_t digestori = fdDup(meta_digestpipefd[0]);
|
| |
- + close(meta_digestpipefd[0]);
|
| |
- +
|
| |
- + rc = process_package(fdi, digestori, sigi);
|
| |
- + if(rc != RPMRC_OK) {
|
| |
- + fprintf(stderr, _("Validator failed\n"));
|
| |
- }
|
| |
- - }
|
| |
- - w = waitpid(cpid, &wstatus, 0);
|
| |
- - if (w == -1) {
|
| |
- - fprintf(stderr, _("waitpid failed\n"));
|
| |
- - cprc = EXIT_FAILURE;
|
| |
- - } else if (WIFEXITED(wstatus)) {
|
| |
- - cprc = WEXITSTATUS(wstatus);
|
| |
- - if (cprc != 0) {
|
| |
- - fprintf(stderr,
|
| |
- - _("Digest process non-zero exit code %d\n"),
|
| |
- - cprc);
|
| |
- + Fclose(digestori);
|
| |
- + Fclose(sigi);
|
| |
- + /* fdi is normally closed through the stacked file gzdi in the
|
| |
- + * function
|
| |
- + */
|
| |
- +
|
| |
- + if (rc != RPMRC_OK) {
|
| |
- + exit(EXIT_FAILURE);
|
| |
- }
|
| |
- - } else if (WIFSIGNALED(wstatus)) {
|
| |
- - fprintf(stderr,
|
| |
- - _("Digest process was terminated with a signal: %d\n"),
|
| |
- - WTERMSIG(wstatus));
|
| |
- - cprc = EXIT_FAILURE;
|
| |
- + exit(EXIT_SUCCESS);
|
| |
- +
|
| |
- +
|
| |
- } else {
|
| |
- - /* Don't think this can happen, but covering all bases */
|
| |
- - fprintf(stderr, _("Unhandled circumstance in waitpid\n"));
|
| |
- - cprc = EXIT_FAILURE;
|
| |
- + /* Actual parent. Read from fdi and write to both processes */
|
| |
- + close(processorpipefd[0]);
|
| |
- + close(validatorpipefd[0]);
|
| |
- + fds[0] = fdDup(processorpipefd[1]);
|
| |
- + fds[1] = fdDup(validatorpipefd[1]);
|
| |
- + close(validatorpipefd[1]);
|
| |
- + close(processorpipefd[1]);
|
| |
- + close(meta_digestpipefd[0]);
|
| |
- + close(meta_digestpipefd[1]);
|
| |
- + close(meta_rpmsignpipefd[0]);
|
| |
- + close(meta_rpmsignpipefd[1]);
|
| |
- +
|
| |
- + rc = RPMRC_OK;
|
| |
- + offt = ufdTee(fdi, fds, 2);
|
| |
- + if(offt == -1){
|
| |
- + fprintf(stderr, _("Failed to tee RPM\n"));
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + }
|
| |
- + Fclose(fds[0]);
|
| |
- + Fclose(fds[1]);
|
| |
- + w = waitpid(cpids[0], &wstatus, 0);
|
| |
- + if (w == -1) {
|
| |
- + fprintf(stderr, _("waitpid cpids[0] failed\n"));
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + }
|
| |
- + w = waitpid(cpids[1], &wstatus, 0);
|
| |
- + if (w == -1) {
|
| |
- + fprintf(stderr, _("waitpid cpids[1] failed\n"));
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + }
|
| |
- }
|
| |
- - if (cprc != EXIT_SUCCESS) {
|
| |
- - rc = RPMRC_FAIL;
|
| |
- + }
|
| |
- +
|
| |
- + return rc;
|
| |
- +}
|
| |
- +
|
| |
- +int main(int argc, char *argv[]) {
|
| |
- + rpmRC rc;
|
| |
- + poptContext optCon = NULL;
|
| |
- + const char **args = NULL;
|
| |
- + int nb_algos = 0;
|
| |
- +
|
| |
- + xsetprogname(argv[0]); /* Portability call -- see system.h */
|
| |
- + rpmReadConfigFiles(NULL, NULL);
|
| |
- + optCon = rpmcliInit(argc, argv, optionsTable);
|
| |
- + poptSetOtherOptionHelp(optCon, "[OPTIONS]* <DIGESTALGO>");
|
| |
- +
|
| |
- + if (poptPeekArg(optCon) == NULL) {
|
| |
- + fprintf(stderr,
|
| |
- + _("Need at least one DIGESTALGO parameter, e.g. 'SHA256'\n"));
|
| |
- + poptPrintUsage(optCon, stderr, 0);
|
| |
- + exit(EXIT_FAILURE);
|
| |
- + }
|
| |
- +
|
| |
- + args = poptGetArgs(optCon);
|
| |
- +
|
| |
- + for (nb_algos=0; args[nb_algos]; nb_algos++);
|
| |
- + uint8_t algos[nb_algos];
|
| |
- + for (int x = 0; x < nb_algos; x++) {
|
| |
- + if (pgpStringVal(PGPVAL_HASHALGO, args[x], &algos[x]) != 0)
|
| |
- + {
|
| |
- + fprintf(stderr,
|
| |
- + _("Unable to resolve '%s' as a digest algorithm, exiting\n"),
|
| |
- + args[x]);
|
| |
- + exit(EXIT_FAILURE);
|
| |
- }
|
| |
- }
|
| |
- +
|
| |
- + FD_t fdi = fdDup(STDIN_FILENO);
|
| |
- + rc = teeRpm(fdi, algos, nb_algos);
|
| |
- if (rc != RPMRC_OK) {
|
| |
- /* translate rpmRC into generic failure return code. */
|
| |
- return EXIT_FAILURE;
|
| |
- diff --git a/scripts/rpm2extents_dump b/scripts/rpm2extents_dump
|
| |
- new file mode 100755
|
| |
- index 000000000..596a59a49
|
| |
- --- /dev/null
|
| |
- +++ b/scripts/rpm2extents_dump
|
| |
- @@ -0,0 +1,94 @@
|
| |
- +#!/usr/bin/env python3
|
| |
- +
|
| |
- +import argparse
|
| |
- +import binascii
|
| |
- +import os
|
| |
- +import struct
|
| |
- +import sys
|
| |
- +
|
| |
- +MAGIC_SIZE = 8
|
| |
- +MAGIC_STR = b'KWTSH100'
|
| |
- +
|
| |
- +POS_SIZE = 8
|
| |
- +
|
| |
- +def keep_position(func):
|
| |
- + def wrapper(*args, **kwargs):
|
| |
- + curr = args[0].tell()
|
| |
- + res = func(*args, **kwargs)
|
| |
- + f.seek(curr, os.SEEK_SET)
|
| |
- + return res
|
| |
- + return wrapper
|
| |
- +
|
| |
- +def read_validation_digest(f, validation_offset):
|
| |
- + digests = []
|
| |
- + # validation
|
| |
- + f.seek(validation_offset, os.SEEK_SET)
|
| |
- + val_content_len, val_digests_num = struct.unpack('=QI', f.read(8+4))
|
| |
- + for i in range(val_digests_num):
|
| |
- + algo_name_len, digest_len = struct.unpack('=II', f.read(8))
|
| |
- + algo_name, digest = struct.unpack(f'{algo_name_len}s{digest_len}s', f.read(algo_name_len+digest_len))
|
| |
- + digests.append((algo_name, binascii.hexlify(digest)))
|
| |
- + return digests
|
| |
- +
|
| |
- +
|
| |
- +def read_digests_table(f, digest_offset):
|
| |
- + digests = []
|
| |
- + # validation
|
| |
- + f.seek(digest_offset, os.SEEK_SET)
|
| |
- + table_len, digest_len = struct.unpack('=II', f.read(8))
|
| |
- +
|
| |
- + for i in range(table_len):
|
| |
- + digest, pos = struct.unpack(f'{digest_len}sQ', f.read(digest_len + 8))
|
| |
- + digests.append((pos, binascii.hexlify(digest)))
|
| |
- + return digests
|
| |
- +
|
| |
- +def read_signature_output(f, signature_offset):
|
| |
- + f.seek(signature_offset, os.SEEK_SET)
|
| |
- + signature_rc, signature_output_len = struct.unpack('=IQ', f.read(12))
|
| |
- + return signature_rc, f.read(signature_output_len)
|
| |
- +
|
| |
- +@keep_position
|
| |
- +def parse_file(f):
|
| |
- + digests = []
|
| |
- + pos_table_offset = f.seek(-8 - 3*POS_SIZE, os.SEEK_END)
|
| |
- + signature_offset, digest_offset, validation_offset = struct.unpack('=QQQ', f.read(3*POS_SIZE))
|
| |
- +
|
| |
- + validation_digests = read_validation_digest(f, validation_offset)
|
| |
- + digests_table = read_digests_table(f, digest_offset)
|
| |
- + signature_ouput = read_signature_output(f, signature_offset)
|
| |
- +
|
| |
- + return validation_digests, digests_table, signature_ouput
|
| |
- +
|
| |
- +@keep_position
|
| |
- +def is_transcoded(f):
|
| |
- + f.seek(-MAGIC_SIZE, os.SEEK_END)
|
| |
- + magic = f.read(MAGIC_SIZE)
|
| |
- + return magic == MAGIC_STR
|
| |
- +
|
| |
- +def arg_parse():
|
| |
- + parser = argparse.ArgumentParser()
|
| |
- + parser.add_argument('--dump-signature', action='store_true')
|
| |
- + parser.add_argument('--dump-file-digest-table', action='store_true')
|
| |
- + parser.add_argument('--dump-digests', action='store_true')
|
| |
- + parser.add_argument('file')
|
| |
- +
|
| |
- + return parser.parse_args()
|
| |
- +
|
| |
- +if __name__ == '__main__':
|
| |
- + args = arg_parse()
|
| |
- + f = open(args.file, 'rb')
|
| |
- + if not is_transcoded(f):
|
| |
- + sys.exit(1)
|
| |
- +
|
| |
- + validation_digests, digests_table, signature_output = parse_file(f)
|
| |
- + if(args.dump_file_digest_table):
|
| |
- + for digest in digests_table:
|
| |
- + print(f"FileDigest {hex(digest[0])}: {digest[1]}")
|
| |
- +
|
| |
- + if(args.dump_digests):
|
| |
- + for validation_digest in validation_digests:
|
| |
- + print(f"HeaderDigest {validation_digest[0]} {validation_digest[1]}")
|
| |
- +
|
| |
- + if(args.dump_signature):
|
| |
- + print(f"RPMSignOutput RC {signature_output[0]}\nRPMSignOutput Content {signature_output[1].decode()}")
|
| |
- +
|
| |
- diff --git a/tests/Makefile.am b/tests/Makefile.am
|
| |
- index f78e17c3e..fc8a24a5e 100644
|
| |
- --- a/tests/Makefile.am
|
| |
- +++ b/tests/Makefile.am
|
| |
- @@ -36,6 +36,7 @@ TESTSUITE_AT += rpmio.at
|
| |
- TESTSUITE_AT += rpmio.at
|
| |
- TESTSUITE_AT += rpmorder.at
|
| |
- TESTSUITE_AT += rpmvfylevel.at
|
| |
- +TESTSUITE_AT += rpm2extents.at
|
| |
- EXTRA_DIST += $(TESTSUITE_AT)
|
| |
-
|
| |
- ## testsuite data
|
| |
- diff --git a/tests/atlocal.in b/tests/atlocal.in
|
| |
- index c3189d327..a110564e2 100644
|
| |
- --- a/tests/atlocal.in
|
| |
- +++ b/tests/atlocal.in
|
| |
- @@ -29,6 +29,19 @@ else
|
| |
-
|
| |
- RPM_XFAIL=${RPM_XFAIL-1}
|
| |
-
|
| |
- +FSTYPE=$(stat -f -c %T /)
|
| |
- +REFLINKABLE_FS=("xfs" "brtfs")
|
| |
- +
|
| |
- +REFLINK_DISABLED=true;
|
| |
- +for item in "${REFLINKABLE_FS[@]}"
|
| |
- +do
|
| |
- + if test "${FSTYPE}" = "${item}"
|
| |
- + then
|
| |
- + REFLINK_DISABLED=false;
|
| |
- + break
|
| |
- + fi
|
| |
- +done
|
| |
- +
|
| |
- function run()
|
| |
- {
|
| |
- "$@" --define "_tmppath ${RPMTEST}/tmp" --define "_topdir ${TOPDIR}" --dbpath="${RPMTEST}/var/lib/rpm/"
|
| |
- @@ -40,6 +53,14 @@ function runroot()
|
| |
- )
|
| |
- }
|
| |
-
|
| |
- +function runroot_plugins()
|
| |
- +{
|
| |
- + (unset RPM_CONFIGDIR RPM_POPTEXEC_PATH; cd ${RPMTEST} && \
|
| |
- + MAGIC="/magic/magic" FAKECHROOT_BASE="${RPMTEST}" fakechroot "$@" --define "_buildhost testhost" --define "_topdir /build" --nouserns
|
| |
- + )
|
| |
- +}
|
| |
- +
|
| |
- +
|
| |
- function runroot_other()
|
| |
- {
|
| |
- (unset RPM_CONFIGDIR RPM_POPTEXEC_PATH; cd ${RPMTEST} && \
|
| |
- diff --git a/tests/rpm2extents.at b/tests/rpm2extents.at
|
| |
- new file mode 100644
|
| |
- index 000000000..29165c1b9
|
| |
- --- /dev/null
|
| |
- +++ b/tests/rpm2extents.at
|
| |
- @@ -0,0 +1,141 @@
|
| |
- +# rpm2extents.at: Some very basic checks
|
| |
- +#
|
| |
- +# Copyright (C) 2022 Manu Bretelle <chantr4@gmail.com>
|
| |
- +#
|
| |
- +# This program is free software; you can redistribute it and/or modify
|
| |
- +# it under the terms of the GNU General Public License as published by
|
| |
- +# the Free Software Foundation; either version 2 of the License, or
|
| |
- +# (at your option) any later version.
|
| |
- +#
|
| |
- +# This program is distributed in the hope that it will be useful,
|
| |
- +# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| |
- +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| |
- +# GNU General Public License for more details.
|
| |
- +#
|
| |
- +# You should have received a copy of the GNU General Public License
|
| |
- +# along with this program; if not, write to the Free Software
|
| |
- +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
| |
- +
|
| |
- +AT_BANNER([rpm2extents tests])
|
| |
- +
|
| |
- +# ------------------------------
|
| |
- +
|
| |
- +# check that transcoder write magic at the end
|
| |
- +AT_SETUP([rpm2extents magic])
|
| |
- +AT_KEYWORDS([rpm2extents])
|
| |
- +AT_CHECK([runroot_other cat /data/RPMS/hello-2.0-1.x86_64.rpm | runroot_other rpm2extents SHA256 | tail -c8],
|
| |
- +[0],
|
| |
- +[KWTSH100],
|
| |
- +[ignore])
|
| |
- +AT_CLEANUP
|
| |
- +
|
| |
- +# Check that transcoder writes checksig return code and content.
|
| |
- +#
|
| |
- +AT_SETUP([rpm2extents signature])
|
| |
- +AT_KEYWORDS([rpm2extents])
|
| |
- +AT_CHECK([
|
| |
- +RPMDB_INIT
|
| |
- +
|
| |
- +runroot_other cat /data/RPMS/hello-2.0-1.x86_64-signed.rpm | runroot_other rpm2extents SHA256 > /tmp/hello-2.0-1.x86_64-signed.rpm 2> /dev/null
|
| |
- +rpm2extents_dump --dump-signature /tmp/hello-2.0-1.x86_64-signed.rpm
|
| |
- +runroot rpmkeys --import /data/keys/rpm.org-rsa-2048-test.pub
|
| |
- +runroot_other cat /data/RPMS/hello-2.0-1.x86_64-signed.rpm | runroot_other rpm2extents SHA256 > /tmp/hello-2.0-1.x86_64-signed.rpm
|
| |
- +rpm2extents_dump --dump-signature /tmp/hello-2.0-1.x86_64-signed.rpm
|
| |
- +],
|
| |
- +[0],
|
| |
- +[RPMSignOutput RC 2
|
| |
- +RPMSignOutput Content Header V4 RSA/SHA256 Signature, key ID 1964c5fc: NOKEY
|
| |
- + Header SHA256 digest: OK
|
| |
- + Header SHA1 digest: OK
|
| |
- + Payload SHA256 digest: OK
|
| |
- + V4 RSA/SHA256 Signature, key ID 1964c5fc: NOKEY
|
| |
- + MD5 digest: OK
|
| |
- +
|
| |
- +RPMSignOutput RC 0
|
| |
- +RPMSignOutput Content Header V4 RSA/SHA256 Signature, key ID 1964c5fc: OK
|
| |
- + Header SHA256 digest: OK
|
| |
- + Header SHA1 digest: OK
|
| |
- + Payload SHA256 digest: OK
|
| |
- + V4 RSA/SHA256 Signature, key ID 1964c5fc: OK
|
| |
- + MD5 digest: OK
|
| |
- +
|
| |
- +],
|
| |
- +[])
|
| |
- +AT_CLEANUP
|
| |
- +
|
| |
- +AT_SETUP([rpm2extents signature verification])
|
| |
- +AT_KEYWORDS([rpm2extents])
|
| |
- +AT_CHECK([
|
| |
- +RPMDB_INIT
|
| |
- +
|
| |
- +runroot_other cat /data/RPMS/hello-2.0-1.x86_64-signed.rpm | runroot_other rpm2extents SHA256 > ${RPMTEST}/tmp/hello-2.0-1.x86_64-signed.rpm 2> /dev/null
|
| |
- +runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64-signed.rpm; echo $?
|
| |
- +runroot rpmkeys --import /data/keys/rpm.org-rsa-2048-test.pub
|
| |
- +runroot_other cat /data/RPMS/hello-2.0-1.x86_64-signed.rpm | runroot_other rpm2extents SHA256 > ${RPMTEST}/tmp/hello-2.0-1.x86_64-signed.rpm
|
| |
- +runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64-signed.rpm; echo $?
|
| |
- +],
|
| |
- +[0],
|
| |
- +[/tmp/hello-2.0-1.x86_64-signed.rpm:
|
| |
- + Header V4 RSA/SHA256 Signature, key ID 1964c5fc: NOKEY
|
| |
- + Header SHA256 digest: OK
|
| |
- + Header SHA1 digest: OK
|
| |
- + Payload SHA256 digest: OK
|
| |
- + V4 RSA/SHA256 Signature, key ID 1964c5fc: NOKEY
|
| |
- + MD5 digest: OK
|
| |
- +1
|
| |
- +/tmp/hello-2.0-1.x86_64-signed.rpm:
|
| |
- + Header V4 RSA/SHA256 Signature, key ID 1964c5fc: OK
|
| |
- + Header SHA256 digest: OK
|
| |
- + Header SHA1 digest: OK
|
| |
- + Payload SHA256 digest: OK
|
| |
- + V4 RSA/SHA256 Signature, key ID 1964c5fc: OK
|
| |
- + MD5 digest: OK
|
| |
- +0
|
| |
- +],
|
| |
- +[])
|
| |
- +AT_CLEANUP
|
| |
- +
|
| |
- +AT_SETUP([rpm2extents install package])
|
| |
- +AT_KEYWORDS([rpm2extents reflink])
|
| |
- +AT_SKIP_IF([$REFLINK_DISABLED])
|
| |
- +AT_CHECK([
|
| |
- +RPMDB_INIT
|
| |
- +
|
| |
- +runroot_other cat /data/RPMS/hello-2.0-1.x86_64.rpm | runroot_other rpm2extents SHA256 > ${RPMTEST}/tmp/hello-2.0-1.x86_64.rpm 2> /dev/null
|
| |
- +runroot_plugins rpm -i --nodigest --nodeps --undefine=%__transaction_dbus_announce /tmp/hello-2.0-1.x86_64.rpm
|
| |
- +],
|
| |
- +[0],
|
| |
- +[],
|
| |
- +[])
|
| |
- +AT_CLEANUP
|
| |
- +
|
| |
- +AT_SETUP([reflink hardlink package])
|
| |
- +AT_KEYWORDS([reflink hardlink])
|
| |
- +AT_SKIP_IF([$REFLINK_DISABLED])
|
| |
- +AT_CHECK([
|
| |
- +RPMDB_INIT
|
| |
- +
|
| |
- +PKG=hlinktest-1.0-1.noarch.rpm
|
| |
- +runroot_other cat /data/RPMS/${PKG} | runroot_other rpm2extents SHA256 > ${RPMTEST}/tmp/${PKG} 2> /dev/null
|
| |
- +runroot_plugins rpm -i --nodigest --nodeps --undefine=%__transaction_dbus_announce /tmp/${PKG}
|
| |
- +],
|
| |
- +[0],
|
| |
- +[],
|
| |
- +[])
|
| |
- +AT_CLEANUP
|
| |
- +
|
| |
- +AT_SETUP([rpm2extents install package])
|
| |
- +AT_KEYWORDS([rpm2extents reflink])
|
| |
- +AT_SKIP_IF([$REFLINK_DISABLED])
|
| |
- +AT_CHECK([
|
| |
- +RPMDB_INIT
|
| |
- +
|
| |
- +runroot_other cat /data/RPMS/hello-2.0-1.x86_64.rpm | runroot_other rpm2extents SHA256 > ${RPMTEST}/tmp/hello-2.0-1.x86_64.rpm 2> /dev/null
|
| |
- +runroot_plugins rpm -i --nodigest --nodeps --undefine=%__transaction_dbus_announce /tmp/hello-2.0-1.x86_64.rpm
|
| |
- +],
|
| |
- +[0],
|
| |
- +[],
|
| |
- +[])
|
| |
- +AT_CLEANUP
|
| |
- +
|
| |
- +
|
| |
- diff --git a/tests/rpmtests.at b/tests/rpmtests.at
|
| |
- index a1adab8e0..205fed6a3 100644
|
| |
- --- a/tests/rpmtests.at
|
| |
- +++ b/tests/rpmtests.at
|
| |
- @@ -21,3 +21,4 @@ m4_include([rpmreplace.at])
|
| |
- m4_include([rpmmacro.at])
|
| |
- m4_include([rpmpython.at])
|
| |
- m4_include([rpmdepmatch.at])
|
| |
- +m4_include([rpm2extents.at])
|
| |
4.14.3-18 to 4.14.3-21