| |
@@ -1,7 +1,7 @@
|
| |
- From 7bd31ce85b2ed377f495c31fcea2422a07739e24 Mon Sep 17 00:00:00 2001
|
| |
+ From 55de6f0be10d96b56de214b677ed185bf12d15ee Mon Sep 17 00:00:00 2001
|
| |
From: Matthew Almond <malmond@fb.com>
|
| |
Date: Fri, 8 Nov 2019 09:29:43 -0800
|
| |
- Subject: [PATCH 01/30] RPM with Copy on Write
|
| |
+ Subject: [PATCH] RPM with Copy on Write
|
| |
|
| |
This is part of https://fedoraproject.org/wiki/Changes/RPMCoW
|
| |
|
| |
@@ -85,28 +85,48 @@
|
| |
Nothing has been removed, and none of the changes are intended to be
|
| |
used externally, so I don't think a soname bump is warranted here.
|
| |
---
|
| |
- .gitignore | 1 +
|
| |
- Makefile.am | 6 +-
|
| |
- lib/depends.c | 2 +
|
| |
- lib/fsm.c | 61 +++++-
|
| |
- lib/package.c | 40 ++++
|
| |
- lib/rpmlib.h | 9 +
|
| |
- lib/rpmplugins.c | 21 +-
|
| |
- lib/rpmte.c | 5 +
|
| |
- lib/rpmte.h | 2 +
|
| |
- lib/rpmtypes.h | 3 +-
|
| |
- macros.in | 1 +
|
| |
- plugins/Makefile.am | 4 +
|
| |
- plugins/reflink.c | 340 +++++++++++++++++++++++++++++
|
| |
- rpm2extents.c | 519 ++++++++++++++++++++++++++++++++++++++++++++
|
| |
- rpmio/rpmpgp.c | 10 +
|
| |
- rpmio/rpmpgp.h | 9 +
|
| |
- 16 files changed, 1020 insertions(+), 13 deletions(-)
|
| |
+ Makefile.am | 8 +-
|
| |
+ build/pack.c | 2 +-
|
| |
+ lib/Makefile.am | 3 +-
|
| |
+ lib/Makefile.in | 51 +--
|
| |
+ lib/fsm.c | 45 ++-
|
| |
+ lib/package.c | 36 ++
|
| |
+ lib/rpmchecksig.c | 117 +++++--
|
| |
+ lib/rpmcli.h | 10 +
|
| |
+ lib/rpmextents.c | 110 ++++++
|
| |
+ lib/rpmextents_internal.h | 58 ++++
|
| |
+ lib/rpmlead.c | 43 ++-
|
| |
+ lib/rpmlead.h | 37 +-
|
| |
+ lib/rpmlib.h | 9 +
|
| |
+ lib/rpmplugin.h | 9 +
|
| |
+ lib/rpmplugins.c | 92 ++++-
|
| |
+ lib/rpmplugins.h | 17 +
|
| |
+ lib/rpmte.c | 5 +
|
| |
+ lib/rpmte.h | 2 +
|
| |
+ lib/rpmtypes.h | 3 +-
|
| |
+ lib/transaction.c | 29 +-
|
| |
+ macros.in | 1 +
|
| |
+ plugins/Makefile.am | 4 +
|
| |
+ plugins/reflink.c | 401 +++++++++++++++++++++
|
| |
+ rpm2extents.c | 708 ++++++++++++++++++++++++++++++++++++++
|
| |
+ rpmio/rpmpgp.c | 10 +
|
| |
+ rpmio/rpmpgp.h | 9 +
|
| |
+ scripts/rpm2extents_dump | 94 +++++
|
| |
+ sign/rpmgensig.c | 2 +-
|
| |
+ tests/Makefile.am | 1 +
|
| |
+ tests/atlocal.in | 22 ++
|
| |
+ tests/rpm2extents.at | 151 ++++++++
|
| |
+ tests/rpmtests.at | 1 +
|
| |
+ 32 files changed, 1996 insertions(+), 94 deletions(-)
|
| |
+ create mode 100644 lib/rpmextents.c
|
| |
+ create mode 100644 lib/rpmextents_internal.h
|
| |
create mode 100644 plugins/reflink.c
|
| |
create mode 100644 rpm2extents.c
|
| |
+ create mode 100755 scripts/rpm2extents_dump
|
| |
+ create mode 100644 tests/rpm2extents.at
|
| |
|
| |
diff --git a/Makefile.am b/Makefile.am
|
| |
- index e5c75d7b4..288668819 100644
|
| |
+ index 78bc131..43fbd94 100644
|
| |
--- a/Makefile.am
|
| |
+++ b/Makefile.am
|
| |
@@ -106,7 +106,7 @@ pkginclude_HEADERS += build/rpmfc.h
|
| |
@@ -129,109 +149,198 @@
|
| |
rpm2archive_SOURCES = rpm2archive.c debug.h system.h
|
| |
rpm2archive_LDADD = lib/librpm.la rpmio/librpmio.la
|
| |
rpm2archive_LDADD += @WITH_POPT_LIB@ @WITH_ARCHIVE_LIB@
|
| |
- diff --git a/lib/depends.c b/lib/depends.c
|
| |
- index 30234df3d..8998afcd3 100644
|
| |
- --- a/lib/depends.c
|
| |
- +++ b/lib/depends.c
|
| |
- @@ -80,6 +80,8 @@ static rpmRC headerCheckPayloadFormat(Header h) {
|
| |
- */
|
| |
- if (!payloadfmt) return rc;
|
| |
+ @@ -199,7 +203,7 @@ bin_PROGRAMS += rpmgraph
|
| |
+ rpmgraph_SOURCES = tools/rpmgraph.c
|
| |
+ rpmgraph_LDADD = lib/librpm.la rpmio/librpmio.la @WITH_POPT_LIB@
|
| |
|
| |
- + if (rstreq(payloadfmt, "clon")) return rc;
|
| |
- +
|
| |
- if (!rstreq(payloadfmt, "cpio")) {
|
| |
- char *nevra = headerGetAsString(h, RPMTAG_NEVRA);
|
| |
- if (payloadfmt && rstreq(payloadfmt, "drpm")) {
|
| |
+ -dist_bin_SCRIPTS = scripts/gendiff
|
| |
+ +dist_bin_SCRIPTS = scripts/gendiff scripts/rpm2extents_dump
|
| |
+
|
| |
+ rpmconfig_DATA = rpmrc
|
| |
+ rpmrc: $(top_srcdir)/rpmrc.in
|
| |
+ diff --git a/build/pack.c b/build/pack.c
|
| |
+ index 8d6f749..e2f05b6 100644
|
| |
+ --- a/build/pack.c
|
| |
+ +++ b/build/pack.c
|
| |
+ @@ -493,7 +493,7 @@ static rpmRC writeRPM(Package pkg, unsigned char ** pkgidp,
|
| |
+ }
|
| |
+
|
| |
+ /* Write the lead section into the package. */
|
| |
+ - if (rpmLeadWrite(fd, pkg->header)) {
|
| |
+ + if (rpmLeadWriteFromHeader(fd, pkg->header)) {
|
| |
+ rpmlog(RPMLOG_ERR, _("Unable to write package: %s\n"), Fstrerror(fd));
|
| |
+ goto exit;
|
| |
+ }
|
| |
+ diff --git a/lib/Makefile.am b/lib/Makefile.am
|
| |
+ index c561ad5..4a83e9a 100644
|
| |
+ --- a/lib/Makefile.am
|
| |
+ +++ b/lib/Makefile.am
|
| |
+ @@ -41,7 +41,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/Makefile.in b/lib/Makefile.in
|
| |
+ index 1aafaac..bf911fa 100644
|
| |
+ --- a/lib/Makefile.in
|
| |
+ +++ b/lib/Makefile.in
|
| |
+ @@ -173,10 +173,11 @@ am__librpm_la_SOURCES_DIST = backend/dbi.c backend/dbi.h \
|
| |
+ rpmlock.c rpmlock.h misc.h relocation.c 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 backend/db3.c backend/bdb_ro.c \
|
| |
+ - backend/ndb/glue.c backend/ndb/rpmpkg.c backend/ndb/rpmpkg.h \
|
| |
+ - backend/ndb/rpmidx.c backend/ndb/rpmidx.h backend/ndb/rpmxdb.c \
|
| |
+ - backend/ndb/rpmxdb.h backend/sqlite.c
|
| |
+ + rpmvs.c rpmvs.h rpmextents.c rpmextents_internal.h \
|
| |
+ + backend/db3.c backend/bdb_ro.c backend/ndb/glue.c \
|
| |
+ + backend/ndb/rpmpkg.c backend/ndb/rpmpkg.h backend/ndb/rpmidx.c \
|
| |
+ + backend/ndb/rpmidx.h backend/ndb/rpmxdb.c backend/ndb/rpmxdb.h \
|
| |
+ + backend/sqlite.c
|
| |
+ am__dirstamp = $(am__leading_dot)dirstamp
|
| |
+ @BDB_TRUE@am__objects_1 = backend/db3.lo
|
| |
+ @BDB_RO_TRUE@am__objects_2 = backend/bdb_ro.lo
|
| |
+ @@ -192,8 +193,8 @@ am_librpm_la_OBJECTS = backend/dbi.lo backend/dummydb.lo \
|
| |
+ rpmlead.lo rpmps.lo rpmprob.lo rpmrc.lo rpmte.lo rpmts.lo \
|
| |
+ rpmfs.lo signature.lo transaction.lo verify.lo rpmlock.lo \
|
| |
+ relocation.lo rpmscript.lo rpmchroot.lo rpmplugins.lo rpmug.lo \
|
| |
+ - rpmtriggers.lo rpmvs.lo $(am__objects_1) $(am__objects_2) \
|
| |
+ - $(am__objects_3) $(am__objects_4)
|
| |
+ + rpmtriggers.lo rpmvs.lo rpmextents.lo $(am__objects_1) \
|
| |
+ + $(am__objects_2) $(am__objects_3) $(am__objects_4)
|
| |
+ librpm_la_OBJECTS = $(am_librpm_la_OBJECTS)
|
| |
+ AM_V_lt = $(am__v_lt_@AM_V@)
|
| |
+ am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
| |
+ @@ -228,21 +229,21 @@ am__depfiles_remade = ./$(DEPDIR)/cpio.Plo ./$(DEPDIR)/depends.Plo \
|
| |
+ ./$(DEPDIR)/relocation.Plo ./$(DEPDIR)/rpmal.Plo \
|
| |
+ ./$(DEPDIR)/rpmchecksig.Plo ./$(DEPDIR)/rpmchroot.Plo \
|
| |
+ ./$(DEPDIR)/rpmdb.Plo ./$(DEPDIR)/rpmds.Plo \
|
| |
+ - ./$(DEPDIR)/rpmfi.Plo ./$(DEPDIR)/rpmfs.Plo \
|
| |
+ - ./$(DEPDIR)/rpmgi.Plo ./$(DEPDIR)/rpminstall.Plo \
|
| |
+ - ./$(DEPDIR)/rpmlead.Plo ./$(DEPDIR)/rpmlock.Plo \
|
| |
+ - ./$(DEPDIR)/rpmplugins.Plo ./$(DEPDIR)/rpmprob.Plo \
|
| |
+ - ./$(DEPDIR)/rpmps.Plo ./$(DEPDIR)/rpmrc.Plo \
|
| |
+ - ./$(DEPDIR)/rpmscript.Plo ./$(DEPDIR)/rpmtd.Plo \
|
| |
+ - ./$(DEPDIR)/rpmte.Plo ./$(DEPDIR)/rpmtriggers.Plo \
|
| |
+ - ./$(DEPDIR)/rpmts.Plo ./$(DEPDIR)/rpmug.Plo \
|
| |
+ - ./$(DEPDIR)/rpmvs.Plo ./$(DEPDIR)/signature.Plo \
|
| |
+ - ./$(DEPDIR)/tagexts.Plo ./$(DEPDIR)/tagname.Plo \
|
| |
+ - ./$(DEPDIR)/transaction.Plo ./$(DEPDIR)/verify.Plo \
|
| |
+ - backend/$(DEPDIR)/bdb_ro.Plo backend/$(DEPDIR)/db3.Plo \
|
| |
+ - backend/$(DEPDIR)/dbi.Plo backend/$(DEPDIR)/dbiset.Plo \
|
| |
+ - backend/$(DEPDIR)/dummydb.Plo backend/$(DEPDIR)/sqlite.Plo \
|
| |
+ - backend/ndb/$(DEPDIR)/glue.Plo \
|
| |
+ + ./$(DEPDIR)/rpmextents.Plo ./$(DEPDIR)/rpmfi.Plo \
|
| |
+ + ./$(DEPDIR)/rpmfs.Plo ./$(DEPDIR)/rpmgi.Plo \
|
| |
+ + ./$(DEPDIR)/rpminstall.Plo ./$(DEPDIR)/rpmlead.Plo \
|
| |
+ + ./$(DEPDIR)/rpmlock.Plo ./$(DEPDIR)/rpmplugins.Plo \
|
| |
+ + ./$(DEPDIR)/rpmprob.Plo ./$(DEPDIR)/rpmps.Plo \
|
| |
+ + ./$(DEPDIR)/rpmrc.Plo ./$(DEPDIR)/rpmscript.Plo \
|
| |
+ + ./$(DEPDIR)/rpmtd.Plo ./$(DEPDIR)/rpmte.Plo \
|
| |
+ + ./$(DEPDIR)/rpmtriggers.Plo ./$(DEPDIR)/rpmts.Plo \
|
| |
+ + ./$(DEPDIR)/rpmug.Plo ./$(DEPDIR)/rpmvs.Plo \
|
| |
+ + ./$(DEPDIR)/signature.Plo ./$(DEPDIR)/tagexts.Plo \
|
| |
+ + ./$(DEPDIR)/tagname.Plo ./$(DEPDIR)/transaction.Plo \
|
| |
+ + ./$(DEPDIR)/verify.Plo backend/$(DEPDIR)/bdb_ro.Plo \
|
| |
+ + backend/$(DEPDIR)/db3.Plo backend/$(DEPDIR)/dbi.Plo \
|
| |
+ + backend/$(DEPDIR)/dbiset.Plo backend/$(DEPDIR)/dummydb.Plo \
|
| |
+ + backend/$(DEPDIR)/sqlite.Plo backend/ndb/$(DEPDIR)/glue.Plo \
|
| |
+ backend/ndb/$(DEPDIR)/rpmidx.Plo \
|
| |
+ backend/ndb/$(DEPDIR)/rpmpkg.Plo \
|
| |
+ backend/ndb/$(DEPDIR)/rpmxdb.Plo
|
| |
+ @@ -586,8 +587,9 @@ librpm_la_SOURCES = backend/dbi.c backend/dbi.h backend/dummydb.c \
|
| |
+ signature.h transaction.c verify.c rpmlock.c rpmlock.h misc.h \
|
| |
+ relocation.c 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 $(am__append_1) \
|
| |
+ - $(am__append_4) $(am__append_5) $(am__append_8)
|
| |
+ + rpmtriggers.h rpmtriggers.c rpmvs.c rpmvs.h rpmextents.c \
|
| |
+ + rpmextents_internal.h $(am__append_1) $(am__append_4) \
|
| |
+ + $(am__append_5) $(am__append_8)
|
| |
+ librpm_la_LDFLAGS = -version-info $(rpm_version_info)
|
| |
+ librpm_la_LIBADD = $(top_builddir)/rpmio/librpmio.la @WITH_POPT_LIB@ \
|
| |
+ @WITH_CAP_LIB@ @WITH_ACL_LIB@ @LIBINTL@ $(am__append_2) \
|
| |
+ @@ -748,6 +750,7 @@ distclean-compile:
|
| |
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmchroot.Plo@am__quote@ # am--include-marker
|
| |
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmdb.Plo@am__quote@ # am--include-marker
|
| |
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmds.Plo@am__quote@ # am--include-marker
|
| |
+ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmextents.Plo@am__quote@ # am--include-marker
|
| |
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmfi.Plo@am__quote@ # am--include-marker
|
| |
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmfs.Plo@am__quote@ # am--include-marker
|
| |
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmgi.Plo@am__quote@ # am--include-marker
|
| |
+ @@ -978,6 +981,7 @@ distclean: distclean-am
|
| |
+ -rm -f ./$(DEPDIR)/rpmchroot.Plo
|
| |
+ -rm -f ./$(DEPDIR)/rpmdb.Plo
|
| |
+ -rm -f ./$(DEPDIR)/rpmds.Plo
|
| |
+ + -rm -f ./$(DEPDIR)/rpmextents.Plo
|
| |
+ -rm -f ./$(DEPDIR)/rpmfi.Plo
|
| |
+ -rm -f ./$(DEPDIR)/rpmfs.Plo
|
| |
+ -rm -f ./$(DEPDIR)/rpmgi.Plo
|
| |
+ @@ -1077,6 +1081,7 @@ maintainer-clean: maintainer-clean-am
|
| |
+ -rm -f ./$(DEPDIR)/rpmchroot.Plo
|
| |
+ -rm -f ./$(DEPDIR)/rpmdb.Plo
|
| |
+ -rm -f ./$(DEPDIR)/rpmds.Plo
|
| |
+ + -rm -f ./$(DEPDIR)/rpmextents.Plo
|
| |
+ -rm -f ./$(DEPDIR)/rpmfi.Plo
|
| |
+ -rm -f ./$(DEPDIR)/rpmfs.Plo
|
| |
+ -rm -f ./$(DEPDIR)/rpmgi.Plo
|
| |
diff --git a/lib/fsm.c b/lib/fsm.c
|
| |
- index 935a0a5c6..90193c749 100644
|
| |
+ index 9dd50b7..e562220 100644
|
| |
--- a/lib/fsm.c
|
| |
+++ b/lib/fsm.c
|
| |
- @@ -8,6 +8,7 @@
|
| |
- #include <inttypes.h>
|
| |
- #include <utime.h>
|
| |
- #include <errno.h>
|
| |
- +#include <stdbool.h>
|
| |
- #include <fcntl.h>
|
| |
- #ifdef WITH_CAP
|
| |
- #include <sys/capability.h>
|
| |
- @@ -17,6 +18,7 @@
|
| |
- #include <rpm/rpmts.h>
|
| |
- #include <rpm/rpmlog.h>
|
| |
- #include <rpm/rpmmacro.h>
|
| |
- +#include <rpm/rpmlib.h>
|
| |
-
|
| |
- #include "rpmio/rpmio_internal.h" /* fdInit/FiniDigest */
|
| |
- #include "fsm.h"
|
| |
- @@ -54,6 +56,7 @@ struct filedata_s {
|
| |
- int stage;
|
| |
- int setmeta;
|
| |
- int skip;
|
| |
- + bool plugin_contents;
|
| |
- rpmFileAction action;
|
| |
- const char *suffix;
|
| |
- char *fpath;
|
| |
- @@ -885,6 +888,13 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
| |
- struct filedata_s *fdata = xcalloc(fc, sizeof(*fdata));
|
| |
- struct filedata_s *firstlink = NULL;
|
| |
- struct diriter_s di = { -1, -1 };
|
| |
- + Header h = rpmteHeader(te);
|
| |
- + const char *payloadfmt = headerGetString(h, RPMTAG_PAYLOADFORMAT);
|
| |
- + bool cpio = true;
|
| |
- +
|
| |
- + if (payloadfmt && rstreq(payloadfmt, "clon")) {
|
| |
- + cpio = false;
|
| |
- + }
|
| |
-
|
| |
- /* transaction id used for temporary path suffix while installing */
|
| |
- rasprintf(&tid, ";%08x", (unsigned)rpmtsGetTid(ts));
|
| |
- @@ -909,7 +919,20 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
| |
- fp->setmeta = (fp->skip == 0) &&
|
| |
- (fp->sb.st_nlink == 1 || fp->action == FA_TOUCH);
|
| |
+ @@ -868,6 +868,24 @@ static rpmfi fsmIterFini(rpmfi fi, struct diriter_s *di)
|
| |
+ return rpmfiFree(fi);
|
| |
+ }
|
| |
|
| |
- - setFileState(fs, fx);
|
| |
- + switch (rc) {
|
| |
- + case RPMRC_OK:
|
| |
- + setFileState(fs, fx);
|
| |
- + break;
|
| |
+ +static int fiIterator(rpmPlugins plugins, FD_t payload, rpmfiles files, rpmfi *fi)
|
| |
+ +{
|
| |
+ + rpmRC plugin_rc = rpmpluginsCallFsmFileArchiveReader(plugins, payload, files, fi);
|
| |
+ + switch (plugin_rc) {
|
| |
+ case RPMRC_PLUGIN_CONTENTS:
|
| |
- + fp->plugin_contents = true;
|
| |
- + // reduce reads on cpio to this value. Could be zero if
|
| |
- + // this is from a hard link.
|
| |
- + rc = RPMRC_OK;
|
| |
- + break;
|
| |
+ + if (*fi == NULL)
|
| |
+ + return RPMERR_BAD_MAGIC;
|
| |
+ + return RPMRC_OK;
|
| |
+ + case RPMRC_OK:
|
| |
+ + *fi = rpmfiNewArchiveReader(payload, files, RPMFI_ITER_READ_ARCHIVE);
|
| |
+ + if (*fi == NULL)
|
| |
+ + return RPMERR_BAD_MAGIC;
|
| |
+ + return RPMRC_OK;
|
| |
+ default:
|
| |
- + fp->action = FA_SKIP;
|
| |
- + fp->skip = XFA_SKIPPING(fp->action);
|
| |
- + }
|
| |
- fsmDebug(rpmfiDN(fi), fp->fpath, fp->action, &fp->sb);
|
| |
-
|
| |
- fp->stage = FILE_PRE;
|
| |
- @@ -919,8 +942,12 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
| |
+ + return RPMRC_FAIL;
|
| |
+ + }
|
| |
+ +}
|
| |
+ +
|
| |
+ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
| |
+ rpmpsm psm, char ** failedFile)
|
| |
+ {
|
| |
+ @@ -919,8 +937,9 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
| |
if (rc)
|
| |
goto exit;
|
| |
|
| |
- fi = fsmIter(payload, files,
|
| |
- payload ? RPMFI_ITER_READ_ARCHIVE : RPMFI_ITER_FWD, &di);
|
| |
- + if (cpio) {
|
| |
- + fi = fsmIter(payload, files,
|
| |
- + payload ? RPMFI_ITER_READ_ARCHIVE : RPMFI_ITER_FWD, &di);
|
| |
- + } else {
|
| |
- + fi = rpmfilesIter(files, RPMFI_ITER_FWD);
|
| |
- + }
|
| |
+ + rc = fiIterator(plugins, payload, files, &fi);
|
| |
+ + if (rc)
|
| |
+ + goto exit;
|
| |
|
| |
if (fi == NULL) {
|
| |
rc = RPMERR_BAD_MAGIC;
|
| |
- @@ -943,6 +970,9 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
| |
+ @@ -943,6 +962,9 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
| |
if (!fp->skip) {
|
| |
int mayopen = 0;
|
| |
int fd = -1;
|
| |
+
|
| |
- + if (!cpio && di.dirfd >= 0)
|
| |
+ + if (di.dirfd >= 0)
|
| |
+ fsmClose(&di.dirfd);
|
| |
rc = ensureDir(plugins, rpmfiDN(fi), 0,
|
| |
(fp->action == FA_CREATE), 0, &di.dirfd);
|
| |
|
| |
- @@ -952,9 +982,14 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
| |
+ @@ -952,9 +974,10 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
| |
}
|
| |
|
| |
/* Run fsm file pre hook for all plugins */
|
| |
@@ -239,55 +348,51 @@
|
| |
+ if (!rc) {
|
| |
rc = rpmpluginsCallFsmFilePre(plugins, fi, fp->fpath,
|
| |
fp->sb.st_mode, fp->action);
|
| |
- + if (rc == RPMRC_PLUGIN_CONTENTS) {
|
| |
- + fp->plugin_contents = true;
|
| |
- + rc = RPMRC_OK;
|
| |
- + }
|
| |
+ }
|
| |
if (rc)
|
| |
goto setmeta; /* for error notification */
|
| |
|
| |
- @@ -984,9 +1019,13 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
| |
+ @@ -982,11 +1005,18 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
| |
+ if (fp->action == FA_TOUCH)
|
| |
+ goto setmeta;
|
| |
|
| |
- if (S_ISREG(fp->sb.st_mode)) {
|
| |
+ - 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;
|
| |
+ + /* The reflink plugins handles hardlink differently, metadata has to be set. */
|
| |
+ + fp->setmeta = 1;
|
| |
+ + } else if (S_ISREG(fp->sb.st_mode)) {
|
| |
if (rc == RPMERR_ENOENT) {
|
| |
- - rc = fsmMkfile(di.dirfd, fi, fp, files, psm, nodigest,
|
| |
+ rc = fsmMkfile(di.dirfd, fi, fp, files, psm, nodigest,
|
| |
- &firstlink, &firstlinkfile, &di.firstdir,
|
| |
- &fd);
|
| |
- + if (fp->plugin_contents) {
|
| |
- + rc = RPMRC_OK;
|
| |
- + } else {
|
| |
- + rc = fsmMkfile(di.dirfd, fi, fp, files, psm, nodigest,
|
| |
- + &firstlink, &firstlinkfile,
|
| |
- + &di.firstdir, &fd);
|
| |
- + }
|
| |
+ + &firstlink, &firstlinkfile,
|
| |
+ + &di.firstdir, &fd);
|
| |
}
|
| |
} else if (S_ISDIR(fp->sb.st_mode)) {
|
| |
if (rc == RPMERR_ENOENT) {
|
| |
- @@ -1054,11 +1093,17 @@ setmeta:
|
| |
- rc = fx;
|
| |
+ @@ -1055,10 +1085,13 @@ setmeta:
|
| |
|
| |
/* If all went well, commit files to final destination */
|
| |
- - fi = fsmIter(NULL, files, RPMFI_ITER_FWD, &di);
|
| |
- + if (cpio) {
|
| |
- + fi = fsmIter(NULL, files, RPMFI_ITER_FWD, &di);
|
| |
- + } else {
|
| |
- + fi = rpmfilesIter(files, RPMFI_ITER_FWD);
|
| |
- + }
|
| |
+ fi = fsmIter(NULL, files, RPMFI_ITER_FWD, &di);
|
| |
+ +
|
| |
while (!rc && (fx = rpmfiNext(fi)) >= 0) {
|
| |
struct filedata_s *fp = &fdata[fx];
|
| |
|
| |
if (!fp->skip) {
|
| |
- + if (!cpio && di.dirfd >= 0)
|
| |
+ + if (di.dirfd >= 0)
|
| |
+ fsmClose(&di.dirfd);
|
| |
if (!rc)
|
| |
rc = ensureDir(NULL, rpmfiDN(fi), 0, 0, 0, &di.dirfd);
|
| |
|
| |
diff --git a/lib/package.c b/lib/package.c
|
| |
- index 281275029..90bd0d8a7 100644
|
| |
+ index 8c2b66b..fb7ec7b 100644
|
| |
--- a/lib/package.c
|
| |
+++ b/lib/package.c
|
| |
- @@ -402,5 +402,45 @@ exit:
|
| |
+ @@ -402,5 +402,41 @@ exit:
|
| |
return rc;
|
| |
}
|
| |
|
| |
@@ -299,11 +404,7 @@
|
| |
+ Header h = NULL;
|
| |
+ Header sigh = NULL;
|
| |
+
|
| |
- + rpmRC rc = rpmLeadRead(fd, &msg);
|
| |
- + if (rc != RPMRC_OK)
|
| |
- + goto exit;
|
| |
- +
|
| |
- + rc = hdrblobRead(fd, 1, 0, RPMTAG_HEADERSIGNATURES, sigblob, &msg);
|
| |
+ + rpmRC rc = hdrblobRead(fd, 1, 0, RPMTAG_HEADERSIGNATURES, sigblob, &msg);
|
| |
+ if (rc != RPMRC_OK)
|
| |
+ goto exit;
|
| |
+
|
| |
@@ -314,14 +415,14 @@
|
| |
+ rc = hdrblobImport(sigblob, 0, &sigh, &msg);
|
| |
+ if (rc)
|
| |
+ goto exit;
|
| |
-
|
| |
+ +
|
| |
+ rc = hdrblobImport(blob, 0, &h, &msg);
|
| |
+ if (rc)
|
| |
+ goto exit;
|
| |
-
|
| |
+ +
|
| |
+ *sigp = headerLink(sigh);
|
| |
+ *hdrp = headerLink(h);
|
| |
- +
|
| |
+
|
| |
+exit:
|
| |
+ if (rc != RPMRC_OK && msg)
|
| |
+ rpmlog(RPMLOG_ERR, "%s: %s\n", Fdescr(fd), msg);
|
| |
@@ -330,11 +431,534 @@
|
| |
+ headerFree(sigh);
|
| |
+ headerFree(h);
|
| |
+ free(msg);
|
| |
+
|
| |
+ + return rc;
|
| |
+ +}
|
| |
+ diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c
|
| |
+ index 40a3ab8..7f85615 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"
|
| |
+ @@ -221,36 +222,24 @@ exit:
|
| |
+ }
|
| |
+
|
| |
+ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags,
|
| |
+ - FD_t fd, const char *fn)
|
| |
+ + FD_t fd, rpmsinfoCb cb, void *cbdata)
|
| |
+ {
|
| |
+ char *msg = NULL;
|
| |
+ - struct vfydata_s vd = { .seen = 0,
|
| |
+ - .bad = 0,
|
| |
+ - .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 extentsVerifySigs(fd, 1);
|
| |
+ + }
|
| |
+ +
|
| |
+ + 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, vfyCb, &vd);
|
| |
+ -
|
| |
+ - if (!vd.verbose) {
|
| |
+ - if (vd.seen & RPMSIG_DIGEST_TYPE) {
|
| |
+ - rpmlog(RPMLOG_NOTICE, " %s", (vd.bad & RPMSIG_DIGEST_TYPE) ?
|
| |
+ - _("DIGESTS") : _("digests"));
|
| |
+ - }
|
| |
+ - if (vd.seen & RPMSIG_SIGNATURE_TYPE) {
|
| |
+ - rpmlog(RPMLOG_NOTICE, " %s", (vd.bad & RPMSIG_SIGNATURE_TYPE) ?
|
| |
+ - _("SIGNATURES") : _("signatures"));
|
| |
+ - }
|
| |
+ - rpmlog(RPMLOG_NOTICE, " %s\n", rc ? _("NOT OK") : _("OK"));
|
| |
+ - }
|
| |
+ + rc = rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, cb, cbdata);
|
| |
+
|
| |
+ exit:
|
| |
+ if (rc && msg)
|
| |
+ @@ -260,15 +249,39 @@ exit:
|
| |
+ return rc;
|
| |
+ }
|
| |
+
|
| |
+ +static void rpmkgVerifySigsPreLogging(struct vfydata_s *vd, const char *fn){
|
| |
+ + rpmlog(RPMLOG_NOTICE, "%s:%s", fn, vd->verbose ? "\n" : "");
|
| |
+ +}
|
| |
+ +
|
| |
+ +static void rpmkgVerifySigsPostLogging(struct vfydata_s *vd, int rc){
|
| |
+ + if (!vd->verbose) {
|
| |
+ + if (vd->seen & RPMSIG_DIGEST_TYPE) {
|
| |
+ + rpmlog(RPMLOG_NOTICE, " %s", (vd->bad & RPMSIG_DIGEST_TYPE) ?
|
| |
+ + _("DIGESTS") : _("digests"));
|
| |
+ + }
|
| |
+ + if (vd->seen & RPMSIG_SIGNATURE_TYPE) {
|
| |
+ + rpmlog(RPMLOG_NOTICE, " %s", (vd->bad & RPMSIG_SIGNATURE_TYPE) ?
|
| |
+ + _("SIGNATURES") : _("signatures"));
|
| |
+ + }
|
| |
+ + rpmlog(RPMLOG_NOTICE, " %s\n", rc ? _("NOT OK") : _("OK"));
|
| |
+ + }
|
| |
+ +}
|
| |
+ +
|
| |
+ /* Wrapper around rpmkVerifySigs to preserve API */
|
| |
+ int rpmVerifySignatures(QVA_t qva, rpmts ts, FD_t fd, const char * fn)
|
| |
+ {
|
| |
+ int rc = 1; /* assume failure */
|
| |
+ + struct vfydata_s vd = { .seen = 0,
|
| |
+ + .bad = 0,
|
| |
+ + .verbose = rpmIsVerbose(),
|
| |
+ + };
|
| |
+ if (ts && qva && fd && fn) {
|
| |
+ rpmKeyring keyring = rpmtsGetKeyring(ts, 1);
|
| |
+ rpmVSFlags vsflags = rpmtsVfyFlags(ts);
|
| |
+ int vfylevel = rpmtsVfyLevel(ts);
|
| |
+ - rc = rpmpkgVerifySigs(keyring, vfylevel, vsflags, fd, fn);
|
| |
+ + rpmkgVerifySigsPreLogging(&vd, fn);
|
| |
+ + rc = rpmpkgVerifySigs(keyring, vfylevel, vsflags, fd, vfyCb, &vd);
|
| |
+ + rpmkgVerifySigsPostLogging(&vd, rc);
|
| |
+ rpmKeyringFree(keyring);
|
| |
+ }
|
| |
+ return rc;
|
| |
+ @@ -290,12 +303,22 @@ int rpmcliVerifySignatures(rpmts ts, ARGV_const_t argv)
|
| |
+
|
| |
+ while ((arg = *argv++) != NULL) {
|
| |
+ FD_t fd = Fopen(arg, "r.ufdio");
|
| |
+ + struct vfydata_s vd = { .seen = 0,
|
| |
+ + .bad = 0,
|
| |
+ + .verbose = rpmIsVerbose(),
|
| |
+ + };
|
| |
+ if (fd == NULL || Ferror(fd)) {
|
| |
+ rpmlog(RPMLOG_ERR, _("%s: open failed: %s\n"),
|
| |
+ arg, Fstrerror(fd));
|
| |
+ res++;
|
| |
+ - } else if (rpmpkgVerifySigs(keyring, vfylevel, vsflags, fd, arg)) {
|
| |
+ + } else {
|
| |
+ + rpmkgVerifySigsPreLogging(&vd, arg);
|
| |
+ + int rc = rpmpkgVerifySigs(keyring, vfylevel, vsflags, fd,
|
| |
+ + vfyCb, &vd);
|
| |
+ + rpmkgVerifySigsPostLogging(&vd, rc);
|
| |
+ + if (rc) {
|
| |
+ res++;
|
| |
+ + }
|
| |
+ }
|
| |
+
|
| |
+ Fclose(fd);
|
| |
+ @@ -304,3 +327,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 >= 0 ? BUFSIZ - vd->len : 0;
|
| |
+ +
|
| |
+ + 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 (!rpmpkgVerifySigs(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 3961418..450f7be 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 0000000..ac43264
|
| |
+ --- /dev/null
|
| |
+ +++ b/lib/rpmextents.c
|
| |
+ @@ -0,0 +1,110 @@
|
| |
+ +
|
| |
+ +#include "system.h"
|
| |
+ +
|
| |
+ +#include <rpm/rpmlog.h>
|
| |
+ +#include <rpm/rpmio.h>
|
| |
+ +#include <string.h>
|
| |
+ +#include <errno.h>
|
| |
+ +
|
| |
+ +
|
| |
+ +#include "lib/rpmextents_internal.h"
|
| |
+ +
|
| |
+ +
|
| |
+ +int extentsVerifySigs(FD_t fd, int print_content){
|
| |
+ + rpm_loff_t current;
|
| |
+ + int32_t rc;
|
| |
+ + size_t len;
|
| |
+ + uint64_t content_len;
|
| |
+ + char *content = NULL;
|
| |
+ + struct extents_footer_t footer;
|
| |
+ +
|
| |
+ + current = Ftell(fd);
|
| |
+ +
|
| |
+ + if(extentsFooterFromFD(fd, &footer) != RPMRC_OK) {
|
| |
+ + rc = -1;
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ + if(Fseek(fd, footer.offsets.checksig_offset, SEEK_SET) < 0) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("extentsVerifySigs: Failed to seek signature verification offset\n"));
|
| |
+ + rc = -1;
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ + len = sizeof(rc);
|
| |
+ + if (Fread(&rc, len, 1, fd) != len) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("extentsVerifySigs: Failed to read Signature Verification RC\n"));
|
| |
+ + rc = -1;
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ +
|
| |
+ + if(print_content) {
|
| |
+ + len = sizeof(content_len);
|
| |
+ + if (Fread(&content_len, len, 1, fd) != len) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("extentsVerifySigs: Failed to read signature content length\n"));
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ +
|
| |
+ + content = rmalloc(content_len + 1);
|
| |
+ + if(content == NULL) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("extentsVerifySigs: 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, _("extentsVerifySigs: Failed to read signature content\n"));
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ +
|
| |
+ + rpmlog(RPMLOG_NOTICE, "%s", content);
|
| |
+ + }
|
| |
+ +exit:
|
| |
+ + if(content){
|
| |
+ + rfree(content);
|
| |
+ + }
|
| |
+ + if (Fseek(fd, current, SEEK_SET) < 0) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("extentsVerifySigs: unable to seek back to original location\n"));
|
| |
+ + }
|
| |
+ + return rc;
|
| |
+ +
|
| |
+ +}
|
| |
+ +
|
| |
+ +rpmRC extentsFooterFromFD(FD_t fd, struct extents_footer_t *footer) {
|
| |
+ +
|
| |
+ + rpmRC rc = RPMRC_NOTFOUND;
|
| |
+ + rpm_loff_t current;
|
| |
+ + 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);
|
| |
+ +
|
| |
+ + len = sizeof(struct extents_footer_t);
|
| |
+ + if(Fseek(fd, -len, SEEK_END) < 0) {
|
| |
+ + rc = RPMRC_FAIL;
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ + if (Fread(footer, len, 1, fd) != len) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("isTranscodedRpm: unable to read footer\n"));
|
| |
+ + rc = RPMRC_FAIL;
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ + if (footer->magic != EXTENTS_MAGIC) {
|
| |
+ + 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;
|
| |
+ +}
|
| |
+ +
|
| |
+ +rpmRC isTranscodedRpm(FD_t fd) {
|
| |
+ + struct extents_footer_t footer;
|
| |
+ + return extentsFooterFromFD(fd, &footer);
|
| |
+ +}
|
| |
+ +
|
| |
+ +
|
| |
+ diff --git a/lib/rpmextents_internal.h b/lib/rpmextents_internal.h
|
| |
+ new file mode 100644
|
| |
+ index 0000000..0a3318c
|
| |
+ --- /dev/null
|
| |
+ +++ b/lib/rpmextents_internal.h
|
| |
+ @@ -0,0 +1,58 @@
|
| |
+ +#ifndef _RPMEXTENTS_INTERNAL_H
|
| |
+ +#define _RPMEXTENTS_INTERNAL_H
|
| |
+ +
|
| |
+ +#ifdef __cplusplus
|
| |
+ +extern "C" {
|
| |
+ +#endif
|
| |
+ +
|
| |
+ +#include <stdint.h>
|
| |
+ +
|
| |
+ +/** \ingroup rpmextents
|
| |
+ + * RPM extents library
|
| |
+ + */
|
| |
+ +
|
| |
+ +/* 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;
|
| |
+ +
|
| |
+ +struct __attribute__ ((__packed__)) extents_footer_offsets_t {
|
| |
+ + off64_t checksig_offset;
|
| |
+ + off64_t table_offset;
|
| |
+ + off64_t csum_offset;
|
| |
+ +};
|
| |
+ +
|
| |
+ +struct __attribute__ ((__packed__)) extents_footer_t {
|
| |
+ + struct extents_footer_offsets_t offsets;
|
| |
+ + extents_magic_t magic;
|
| |
+ +};
|
| |
+ +
|
| |
+ +/** \ingroup rpmextents
|
| |
+ + * Checks the results of the signature verification ran during transcoding.
|
| |
+ + * @param fd The FD_t of the transcoded RPM
|
| |
+ + * @param print_content Whether or not to print the result from rpmsig
|
| |
+ + * @return The number of checks that `rpmvsVerify` failed during transcoding.
|
| |
+ + */
|
| |
+ +int extentsVerifySigs(FD_t fd, int print_content);
|
| |
+ +
|
| |
+ +/** \ingroup rpmextents
|
| |
+ + * Read the RPM Extents footer from a file descriptor.
|
| |
+ + * @param fd The FD_t of the transcoded RPM
|
| |
+ + * @param[out] footer A pointer to an allocated extents_footer_t with a copy of the footer.
|
| |
+ + * @return RPMRC_OK on success, RPMRC_NOTFOUND if not a transcoded file, RPMRC_FAIL on any failure.
|
| |
+ + */
|
| |
+ +rpmRC extentsFooterFromFD(FD_t fd, struct extents_footer_t *footer);
|
| |
+ +
|
| |
+ +/** \ingroup rpmextents
|
| |
+ + * Check if a RPM is a transcoded RPM
|
| |
+ + * @param fd The FD_t of the transcoded RPM
|
| |
+ + * return RPMRC_OK on success, RPMRC_NOTFOUND if not a transcoded file, RPMRC_FAIL on any failure.
|
| |
+ + */
|
| |
+ +rpmRC isTranscodedRpm(FD_t fd);
|
| |
+ +
|
| |
+ +#ifdef __cplusplus
|
| |
+ +}
|
| |
+ +#endif
|
| |
+ +#endif /* _RPMEXTENTS_INTERNAL_H */
|
| |
+ diff --git a/lib/rpmlead.c b/lib/rpmlead.c
|
| |
+ index 45b1c6f..8210512 100644
|
| |
+ --- a/lib/rpmlead.c
|
| |
+ +++ b/lib/rpmlead.c
|
| |
+ @@ -24,24 +24,6 @@ static unsigned char const lead_magic[] = {
|
| |
+ RPMLEAD_MAGIC0, RPMLEAD_MAGIC1, RPMLEAD_MAGIC2, RPMLEAD_MAGIC3
|
| |
+ };
|
| |
+
|
| |
+ -/** \ingroup lead
|
| |
+ - * The lead data structure.
|
| |
+ - * The lead needs to be 8 byte aligned.
|
| |
+ - * @deprecated The lead (except for signature_type) is legacy.
|
| |
+ - * @todo Don't use any information from lead.
|
| |
+ - */
|
| |
+ -struct rpmlead_s {
|
| |
+ - unsigned char magic[4];
|
| |
+ - unsigned char major;
|
| |
+ - unsigned char minor;
|
| |
+ - short type;
|
| |
+ - short archnum;
|
| |
+ - char name[66];
|
| |
+ - short osnum;
|
| |
+ - short signature_type; /*!< Signature header type (RPMSIG_HEADERSIG) */
|
| |
+ - char reserved[16]; /*!< Pad to 96 bytes -- 8 byte aligned! */
|
| |
+ -};
|
| |
+ -
|
| |
+ static int rpmLeadFromHeader(Header h, struct rpmlead_s *l)
|
| |
+ {
|
| |
+ if (h != NULL) {
|
| |
+ @@ -70,13 +52,23 @@ static int rpmLeadFromHeader(Header h, struct rpmlead_s *l)
|
| |
+ }
|
| |
+
|
| |
+ /* The lead needs to be 8 byte aligned */
|
| |
+ -rpmRC rpmLeadWrite(FD_t fd, Header h)
|
| |
+ +rpmRC rpmLeadWriteFromHeader(FD_t fd, Header h)
|
| |
+ {
|
| |
+ rpmRC rc = RPMRC_FAIL;
|
| |
+ struct rpmlead_s l;
|
| |
+
|
| |
+ - if (rpmLeadFromHeader(h, &l)) {
|
| |
+ -
|
| |
+ + if (rpmLeadFromHeader(h, &l)) {
|
| |
+ + rc = rpmLeadWrite(fd, l);
|
| |
+ + }
|
| |
+ +
|
| |
+ + return rc;
|
| |
+ +}
|
| |
+ +
|
| |
+ +/* The lead needs to be 8 byte aligned */
|
| |
+ +rpmRC rpmLeadWrite(FD_t fd, struct rpmlead_s l)
|
| |
+ +{
|
| |
+ + rpmRC rc = RPMRC_FAIL;
|
| |
+ +
|
| |
+ l.type = htons(l.type);
|
| |
+ l.archnum = htons(l.archnum);
|
| |
+ l.osnum = htons(l.osnum);
|
| |
+ @@ -84,7 +76,6 @@ rpmRC rpmLeadWrite(FD_t fd, Header h)
|
| |
+
|
| |
+ if (Fwrite(&l, 1, sizeof(l), fd) == sizeof(l))
|
| |
+ rc = RPMRC_OK;
|
| |
+ - }
|
| |
+
|
| |
+ return rc;
|
| |
+ }
|
| |
+ @@ -107,6 +98,11 @@ static rpmRC rpmLeadCheck(struct rpmlead_s *lead, char **msg)
|
| |
+ }
|
| |
+
|
| |
+ rpmRC rpmLeadRead(FD_t fd, char **emsg)
|
| |
+ +{
|
| |
+ + return rpmLeadReadAndReturn(fd, emsg, NULL);
|
| |
+ +}
|
| |
+ +
|
| |
+ +rpmRC rpmLeadReadAndReturn(FD_t fd, char **emsg, struct rpmlead_s * ret)
|
| |
+ {
|
| |
+ rpmRC rc = RPMRC_OK;
|
| |
+ struct rpmlead_s l;
|
| |
+ @@ -136,5 +132,8 @@ rpmRC rpmLeadRead(FD_t fd, char **emsg)
|
| |
+ free(err);
|
| |
+ }
|
| |
+
|
| |
+ + if (ret)
|
| |
+ + *ret = l;
|
| |
+ +
|
| |
+ return rc;
|
| |
+ }
|
| |
+ diff --git a/lib/rpmlead.h b/lib/rpmlead.h
|
| |
+ index b344ed4..cc63512 100644
|
| |
+ --- a/lib/rpmlead.h
|
| |
+ +++ b/lib/rpmlead.h
|
| |
+ @@ -19,13 +19,39 @@ extern "C" {
|
| |
+
|
| |
+ #define RPMLEAD_SIZE 96 /*!< Don't rely on sizeof(struct) */
|
| |
+
|
| |
+ +/** \ingroup lead
|
| |
+ + * The lead data structure.
|
| |
+ + * The lead needs to be 8 byte aligned.
|
| |
+ + * @deprecated The lead (except for signature_type) is legacy.
|
| |
+ + * @todo Don't use any information from lead.
|
| |
+ + */
|
| |
+ +struct rpmlead_s {
|
| |
+ + unsigned char magic[4];
|
| |
+ + unsigned char major;
|
| |
+ + unsigned char minor;
|
| |
+ + short type;
|
| |
+ + short archnum;
|
| |
+ + char name[66];
|
| |
+ + short osnum;
|
| |
+ + short signature_type; /*!< Signature header type (RPMSIG_HEADERSIG) */
|
| |
+ + char reserved[16]; /*!< Pad to 96 bytes -- 8 byte aligned! */
|
| |
+ +};
|
| |
+ +
|
| |
+ /** \ingroup lead
|
| |
+ * Write lead to file handle.
|
| |
+ * @param fd file handle
|
| |
+ * @param h package header
|
| |
+ * @return RPMRC_OK on success, RPMRC_FAIL on error
|
| |
+ */
|
| |
+ -rpmRC rpmLeadWrite(FD_t fd, Header h);
|
| |
+ +rpmRC rpmLeadWriteFromHeader(FD_t fd, Header h);
|
| |
+ +
|
| |
+ +/** \ingroup lead
|
| |
+ + * Write lead to file handle.
|
| |
+ + * @param fd file handle
|
| |
+ + * @param l lead
|
| |
+ + * @return RPMRC_OK on success, RPMRC_FAIL on error
|
| |
+ + */
|
| |
+ +rpmRC rpmLeadWrite(FD_t fd, struct rpmlead_s l);
|
| |
+
|
| |
+ /** \ingroup lead
|
| |
+ * Read lead from file handle.
|
| |
+ @@ -35,6 +61,15 @@ rpmRC rpmLeadWrite(FD_t fd, Header h);
|
| |
+ */
|
| |
+ rpmRC rpmLeadRead(FD_t fd, char **emsg);
|
| |
+
|
| |
+ +/** \ingroup lead
|
| |
+ + * Read lead from file handle and return it.
|
| |
+ + * @param fd file handle
|
| |
+ + * @param[out] emsg failure message on error (malloced)
|
| |
+ + * @param[out] ret address of lead
|
| |
+ + * @return RPMRC_OK on success, RPMRC_FAIL/RPMRC_NOTFOUND on error
|
| |
+ + */
|
| |
+ +rpmRC rpmLeadReadAndReturn(FD_t fd, char **emsg, struct rpmlead_s * ret);
|
| |
+ +
|
| |
+ #ifdef __cplusplus
|
| |
+ }
|
| |
+ #endif
|
| |
diff --git a/lib/rpmlib.h b/lib/rpmlib.h
|
| |
- index 0879d04e5..a09ba0daf 100644
|
| |
+ index cee47df..af61379 100644
|
| |
--- a/lib/rpmlib.h
|
| |
+++ b/lib/rpmlib.h
|
| |
@@ -156,6 +156,15 @@ rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, char ** msg);
|
| |
@@ -353,8 +977,35 @@
|
| |
/** \ingroup rpmtrans
|
| |
* Install source package.
|
| |
* @param ts transaction set
|
| |
+ diff --git a/lib/rpmplugin.h b/lib/rpmplugin.h
|
| |
+ index fab4b3e..c82d6be 100644
|
| |
+ --- a/lib/rpmplugin.h
|
| |
+ +++ b/lib/rpmplugin.h
|
| |
+ @@ -60,6 +60,13 @@ typedef rpmRC (*plugin_fsm_file_prepare_func)(rpmPlugin plugin, rpmfi fi,
|
| |
+ int fd, 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 62d75c4cf..c5084d398 100644
|
| |
+ index f06fd78..1e0c345 100644
|
| |
--- a/lib/rpmplugins.c
|
| |
+++ b/lib/rpmplugins.c
|
| |
@@ -364,14 +364,29 @@ rpmRC rpmpluginsCallFsmFilePre(rpmPlugins plugins, rpmfi fi, const char *path,
|
| |
@@ -390,8 +1041,111 @@
|
| |
}
|
| |
}
|
| |
free(apath);
|
| |
+ @@ -420,3 +435,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 ddf5d70..db01bff 100644
|
| |
+ --- a/lib/rpmplugins.h
|
| |
+ +++ b/lib/rpmplugins.h
|
| |
+ @@ -168,6 +168,23 @@ rpmRC rpmpluginsCallFsmFilePrepare(rpmPlugins plugins, rpmfi fi,
|
| |
+ int fd, 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/lib/rpmte.c b/lib/rpmte.c
|
| |
- index 3663604e7..d43dc41ad 100644
|
| |
+ index 0551a0f..61b3905 100644
|
| |
--- a/lib/rpmte.c
|
| |
+++ b/lib/rpmte.c
|
| |
@@ -421,6 +421,11 @@ FD_t rpmteSetFd(rpmte te, FD_t fd)
|
| |
@@ -407,7 +1161,7 @@
|
| |
{
|
| |
return (te != NULL ? te->key : NULL);
|
| |
diff --git a/lib/rpmte.h b/lib/rpmte.h
|
| |
- index 81acf7a19..6fc0a9f91 100644
|
| |
+ index 188c3c1..47dec4b 100644
|
| |
--- a/lib/rpmte.h
|
| |
+++ b/lib/rpmte.h
|
| |
@@ -209,6 +209,8 @@ const char * rpmteNEVR(rpmte te);
|
| |
@@ -420,7 +1174,7 @@
|
| |
* Retrieve key from transaction element.
|
| |
* @param te transaction element
|
| |
diff --git a/lib/rpmtypes.h b/lib/rpmtypes.h
|
| |
- index e8e69b506..af2611e9e 100644
|
| |
+ index e8e69b5..af2611e 100644
|
| |
--- a/lib/rpmtypes.h
|
| |
+++ b/lib/rpmtypes.h
|
| |
@@ -106,7 +106,8 @@ typedef enum rpmRC_e {
|
| |
@@ -433,8 +1187,57 @@
|
| |
} rpmRC;
|
| |
|
| |
#ifdef __cplusplus
|
| |
+ diff --git a/lib/transaction.c b/lib/transaction.c
|
| |
+ index 55bc2d9..9603d5e 100644
|
| |
+ --- a/lib/transaction.c
|
| |
+ +++ b/lib/transaction.c
|
| |
+ @@ -37,6 +37,7 @@
|
| |
+ #include "lib/rpmfi_internal.h" /* only internal apis */
|
| |
+ #include "lib/rpmte_internal.h" /* only internal apis */
|
| |
+ #include "lib/rpmts_internal.h"
|
| |
+ +#include "lib/rpmextents_internal.h"
|
| |
+ #include "lib/rpmvs.h"
|
| |
+ #include "rpmio/rpmhook.h"
|
| |
+ #include "lib/rpmtriggers.h"
|
| |
+ @@ -1286,19 +1287,25 @@ static int verifyPackageFiles(rpmts ts, rpm_loff_t total)
|
| |
+
|
| |
+ rpmtsNotify(ts, p, RPMCALLBACK_VERIFY_PROGRESS, oc++, total);
|
| |
+ FD_t fd = rpmtsNotify(ts, p, RPMCALLBACK_INST_OPEN_FILE, 0, 0);
|
| |
+ - if (fd != NULL) {
|
| |
+ - prc = rpmpkgRead(vs, fd, NULL, NULL, &vd.msg);
|
| |
+ - rpmtsNotify(ts, p, RPMCALLBACK_INST_CLOSE_FILE, 0, 0);
|
| |
+ + if(fd != NULL && isTranscodedRpm(fd) == RPMRC_OK) {
|
| |
+ + /* Transcoded RPMs are validated at transcoding time */
|
| |
+ + prc = RPMRC_OK;
|
| |
+ + verified = 1;
|
| |
+ + } else {
|
| |
+ + if (fd != NULL) {
|
| |
+ + prc = rpmpkgRead(vs, fd, NULL, NULL, &vd.msg);
|
| |
+ + rpmtsNotify(ts, p, RPMCALLBACK_INST_CLOSE_FILE, 0, 0);
|
| |
+ + }
|
| |
+ + if (prc == RPMRC_OK)
|
| |
+ + prc = rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, vfyCb, &vd);
|
| |
+ +
|
| |
+ + /* Record verify result */
|
| |
+ + if (vd.type[RPMSIG_SIGNATURE_TYPE] == RPMRC_OK)
|
| |
+ + verified |= RPMSIG_SIGNATURE_TYPE;
|
| |
+ + if (vd.type[RPMSIG_DIGEST_TYPE] == RPMRC_OK)
|
| |
+ + verified |= RPMSIG_DIGEST_TYPE;
|
| |
+ }
|
| |
+
|
| |
+ - if (prc == RPMRC_OK)
|
| |
+ - prc = rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, vfyCb, &vd);
|
| |
+ -
|
| |
+ - /* Record verify result */
|
| |
+ - if (vd.type[RPMSIG_SIGNATURE_TYPE] == RPMRC_OK)
|
| |
+ - verified |= RPMSIG_SIGNATURE_TYPE;
|
| |
+ - if (vd.type[RPMSIG_DIGEST_TYPE] == RPMRC_OK)
|
| |
+ - verified |= RPMSIG_DIGEST_TYPE;
|
| |
+ rpmteSetVerified(p, verified);
|
| |
+
|
| |
+ if (prc)
|
| |
diff --git a/macros.in b/macros.in
|
| |
- index e90cefa9a..363252b0f 100644
|
| |
+ index 877f3ed..a9cc673 100644
|
| |
--- a/macros.in
|
| |
+++ b/macros.in
|
| |
@@ -1189,6 +1189,7 @@ package or when debugging this package.\
|
| |
@@ -446,7 +1249,7 @@
|
| |
%__transaction_selinux %{__plugindir}/selinux.so
|
| |
%__transaction_syslog %{__plugindir}/syslog.so
|
| |
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
|
| |
- index 3a929d0ce..ad0d3bce7 100644
|
| |
+ index f7b95a4..154acb0 100644
|
| |
--- a/plugins/Makefile.am
|
| |
+++ b/plugins/Makefile.am
|
| |
@@ -33,6 +33,10 @@ prioreset_la_SOURCES = prioreset.c
|
| |
@@ -462,10 +1265,10 @@
|
| |
plugins_LTLIBRARIES += syslog.la
|
| |
diff --git a/plugins/reflink.c b/plugins/reflink.c
|
| |
new file mode 100644
|
| |
- index 000000000..d7f19acd9
|
| |
+ index 0000000..127888e
|
| |
--- /dev/null
|
| |
+++ b/plugins/reflink.c
|
| |
- @@ -0,0 +1,340 @@
|
| |
+ @@ -0,0 +1,401 @@
|
| |
+#include "system.h"
|
| |
+
|
| |
+#include <errno.h>
|
| |
@@ -481,6 +1284,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"
|
| |
@@ -496,38 +1300,79 @@
|
| |
+#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"
|
| |
+
|
| |
- +/*
|
| |
- +We use this in find to indicate a key wasn't found. This is an unrecoverable
|
| |
- +error, but we can at least show a decent error. 0 is never a valid offset
|
| |
- +because it's the offset of the start of the file.
|
| |
- +*/
|
| |
+ +/* We use this in find to indicate a key wasn't found. This is an
|
| |
+ + * unrecoverable error, but we can at least show a decent error. 0 is never a
|
| |
+ + * valid offset because it's the offset of the start of the file.
|
| |
+ + */
|
| |
+#define NOT_FOUND 0
|
| |
+
|
| |
+#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;
|
| |
- + char *buffer;
|
| |
- +
|
| |
- + /* stuff that's used/updated per psm */
|
| |
- + uint32_t keys, keysize;
|
| |
- +
|
| |
- + // table for current rpm, keys * (keysize + sizeof(rpm_loff_t))
|
| |
- + unsigned char *table;
|
| |
- + FD_t fd;
|
| |
- + rpmfiles files;
|
| |
- + inodeIndexHash inodeIndexes;
|
| |
+ + /* Stuff that's used across rpms */
|
| |
+ + long fundamental_block_size;
|
| |
+ + char *buffer;
|
| |
+ +
|
| |
+ + /* stuff that's used/updated per psm */
|
| |
+ + uint32_t keys, keysize;
|
| |
+ +
|
| |
+ + /* table for current rpm, keys * (keysize + sizeof(rpm_loff_t)) */
|
| |
+ + unsigned char *table;
|
| |
+ + FD_t fd;
|
| |
+ + rpmfiles files;
|
| |
+ + inodeIndexHash inodeIndexes;
|
| |
+ + int transcoded;
|
| |
+};
|
| |
+
|
| |
- +typedef struct reflink_state_s * reflink_state;
|
| |
+ +typedef struct reflink_state_s * reflink_state;
|
| |
+ +
|
| |
+ +/*
|
| |
+ + * bsearch_r: implements a re-entrant version of stdlib's bsearch.
|
| |
+ + * code taken and adapted from /usr/include/bits/stdlib-bsearch.h
|
| |
+ + */
|
| |
+ +inline void *
|
| |
+ +bsearch_r (const void *__key, const void *__base, size_t __nmemb, size_t __size,
|
| |
+ + __compar_d_fn_t __compar, void *__arg)
|
| |
+ +{
|
| |
+ + size_t __l, __u, __idx;
|
| |
+ + const void *__p;
|
| |
+ + int __comparison;
|
| |
+ +
|
| |
+ + __l = 0;
|
| |
+ + __u = __nmemb;
|
| |
+ + while (__l < __u)
|
| |
+ + {
|
| |
+ + __idx = (__l + __u) / 2;
|
| |
+ + __p = (const void *) (((const char *) __base) + (__idx * __size));
|
| |
+ + __comparison = (*__compar) (__key, __p, __arg);
|
| |
+ + if (__comparison < 0)
|
| |
+ + __u = __idx;
|
| |
+ + else if (__comparison > 0)
|
| |
+ + __l = __idx + 1;
|
| |
+ + else
|
| |
+ + {
|
| |
+ +#if __GNUC_PREREQ(4, 6)
|
| |
+ +# pragma GCC diagnostic push
|
| |
+ +# pragma GCC diagnostic ignored "-Wcast-qual"
|
| |
+ +#endif
|
| |
+ + return (void *) __p;
|
| |
+ +#if __GNUC_PREREQ(4, 6)
|
| |
+ +# pragma GCC diagnostic pop
|
| |
+ +#endif
|
| |
+ + }
|
| |
+ + }
|
| |
+ +
|
| |
+ + return NULL;
|
| |
+ +}
|
| |
+ +
|
| |
+ +static int cmpdigest(const void *k1, const void *k2, void *data) {
|
| |
+ + rpmlog(RPMLOG_DEBUG, _("reflink: cmpdigest k1=%p k2=%p\n"), k1, k2);
|
| |
+ + return memcmp(k1, k2, *(int *)data);
|
| |
+ +}
|
| |
+
|
| |
+static int inodeCmp(rpm_ino_t a, rpm_ino_t b)
|
| |
+{
|
| |
@@ -541,116 +1386,109 @@
|
| |
+}
|
| |
+
|
| |
+static rpmRC reflink_init(rpmPlugin plugin, rpmts ts) {
|
| |
- + reflink_state state = rcalloc(1, sizeof(struct reflink_state_s));
|
| |
- +
|
| |
- + /*
|
| |
- + IOCTL-FICLONERANGE(2): ...Disk filesystems generally require the offset and
|
| |
- + length arguments to be aligned to the fundamental block size.
|
| |
+ + reflink_state state = rcalloc(1, sizeof(struct reflink_state_s));
|
| |
+ +
|
| |
+ + /* IOCTL-FICLONERANGE(2): ...Disk filesystems generally require the offset
|
| |
+ + * and length arguments to be aligned to the fundamental block size.
|
| |
+ + *
|
| |
+ + * The value of "fundamental block size" is directly related to the
|
| |
+ + * system's page size, so we should use that.
|
| |
+ + */
|
| |
+ + state->fundamental_block_size = sysconf(_SC_PAGESIZE);
|
| |
+ + state->buffer = rcalloc(1, BUFFER_SIZE);
|
| |
+ + rpmPluginSetData(plugin, state);
|
| |
+
|
| |
- + The value of "fundamental block size" is directly related to the system's
|
| |
- + page size, so we should use that.
|
| |
- + */
|
| |
- + state->fundamental_block_size = sysconf(_SC_PAGESIZE);
|
| |
- + state->buffer = rcalloc(1, BUFFER_SIZE);
|
| |
- + rpmPluginSetData(plugin, state);
|
| |
- +
|
| |
- + return RPMRC_OK;
|
| |
+ + return RPMRC_OK;
|
| |
+}
|
| |
+
|
| |
+static void reflink_cleanup(rpmPlugin plugin) {
|
| |
- + reflink_state state = rpmPluginGetData(plugin);
|
| |
- + free(state->buffer);
|
| |
- + free(state);
|
| |
+ + reflink_state state = rpmPluginGetData(plugin);
|
| |
+ + free(state->buffer);
|
| |
+ + free(state);
|
| |
+}
|
| |
+
|
| |
+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;
|
| |
+ + 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"));
|
| |
- + return RPMRC_FAIL;
|
| |
- + }
|
| |
- + return RPMRC_OK;
|
| |
+ + rc = isTranscodedRpm(state->fd);
|
| |
+ +
|
| |
+ + switch(rc){
|
| |
+ + // Fail to parse the file, fail the plugin.
|
| |
+ + case RPMRC_FAIL:
|
| |
+ + return RPMRC_FAIL;
|
| |
+ + // 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) {
|
| |
- + rpmlog(RPMLOG_ERR, _("reflink: failed to seek for tail %p\n"), state->fd);
|
| |
- + return RPMRC_FAIL;
|
| |
+ + /* tail of file contains offset_table, offset_checksums then magic */
|
| |
+ + 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;
|
| |
+ }
|
| |
+ rpm_loff_t table_start;
|
| |
+ len = sizeof(table_start);
|
| |
+ if (Fread(&table_start, len, 1, state->fd) != len) {
|
| |
- + rpmlog(RPMLOG_ERR, _("reflink: unable to read table_start\n"));
|
| |
- + return RPMRC_FAIL;
|
| |
+ + rpmlog(RPMLOG_ERR, _("reflink: unable to read table_start\n"));
|
| |
+ + return RPMRC_FAIL;
|
| |
+ }
|
| |
+ if (Fseek(state->fd, table_start, SEEK_SET) < 0) {
|
| |
- + rpmlog(RPMLOG_ERR, _("reflink: unable to seek to table_start\n"));
|
| |
- + return RPMRC_FAIL;
|
| |
+ + rpmlog(RPMLOG_ERR, _("reflink: unable to seek to table_start\n"));
|
| |
+ + return RPMRC_FAIL;
|
| |
+ }
|
| |
+ len = sizeof(state->keys);
|
| |
+ if (Fread(&state->keys, len, 1, state->fd) != len) {
|
| |
- + rpmlog(RPMLOG_ERR, _("reflink: unable to read number of keys\n"));
|
| |
- + return RPMRC_FAIL;
|
| |
+ + rpmlog(RPMLOG_ERR, _("reflink: unable to read number of keys\n"));
|
| |
+ + return RPMRC_FAIL;
|
| |
+ }
|
| |
+ len = sizeof(state->keysize);
|
| |
+ if (Fread(&state->keysize, len, 1, state->fd) != len) {
|
| |
- + rpmlog(RPMLOG_ERR, _("reflink: unable to read keysize\n"));
|
| |
- + return RPMRC_FAIL;
|
| |
+ + rpmlog(RPMLOG_ERR, _("reflink: unable to read keysize\n"));
|
| |
+ + return RPMRC_FAIL;
|
| |
+ }
|
| |
- + rpmlog(RPMLOG_DEBUG, _("reflink: table_start=0x%lx, keys=%d, keysize=%d\n"), table_start, state->keys, state->keysize);
|
| |
- + // now get digest table if there is a reason to have one.
|
| |
+ + rpmlog(
|
| |
+ + RPMLOG_DEBUG,
|
| |
+ + _("reflink: table_start=0x%lx, keys=%d, keysize=%d\n"),
|
| |
+ + table_start, state->keys, state->keysize
|
| |
+ + );
|
| |
+ + /* now get digest table if there is a reason to have one. */
|
| |
+ if (state->keys == 0 || state->keysize == 0) {
|
| |
- + // no files (or no digests(!))
|
| |
- + state->table = NULL;
|
| |
+ + /* no files (or no digests(!)) */
|
| |
+ + state->table = NULL;
|
| |
+ } else {
|
| |
- + int table_size = state->keys * (state->keysize + sizeof(rpm_loff_t));
|
| |
- + state->table = rcalloc(1, table_size);
|
| |
- + if (Fread(state->table, table_size, 1, state->fd) != table_size) {
|
| |
- + rpmlog(RPMLOG_ERR, _("reflink: unable to read table\n"));
|
| |
- + return RPMRC_FAIL;
|
| |
- + }
|
| |
- + state->inodeIndexes = inodeIndexHashCreate(state->keys, inodeId, inodeCmp, NULL, NULL);
|
| |
+ + int table_size = state->keys * (state->keysize + sizeof(rpm_loff_t));
|
| |
+ + state->table = rcalloc(1, table_size);
|
| |
+ + if (Fread(state->table, table_size, 1, state->fd) != table_size) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("reflink: unable to read table\n"));
|
| |
+ + return RPMRC_FAIL;
|
| |
+ + }
|
| |
+ + state->inodeIndexes = inodeIndexHashCreate(
|
| |
+ + state->keys, inodeId, inodeCmp, NULL, (inodeIndexHashFreeData)rfree
|
| |
+ + );
|
| |
+ }
|
| |
+
|
| |
- + // seek back to original location
|
| |
- + // might not be needed if we seek to offset immediately
|
| |
+ + /* Seek back to original location.
|
| |
+ + * Might not be needed if we seek to offset immediately
|
| |
+ + */
|
| |
+ if (Fseek(state->fd, current, SEEK_SET) < 0) {
|
| |
- + rpmlog(RPMLOG_ERR, _("reflink: unable to seek back to original location\n"));
|
| |
- + return RPMRC_FAIL;
|
| |
+ + rpmlog(RPMLOG_ERR,
|
| |
+ + _("reflink: unable to seek back to original location\n"));
|
| |
+ + return RPMRC_FAIL;
|
| |
+ }
|
| |
+ return RPMRC_OK;
|
| |
+}
|
| |
@@ -660,141 +1498,166 @@
|
| |
+ reflink_state state = rpmPluginGetData(plugin);
|
| |
+ state->files = rpmfilesFree(state->files);
|
| |
+ if (state->table) {
|
| |
- + free(state->table);
|
| |
- + state->table = NULL;
|
| |
+ + free(state->table);
|
| |
+ + state->table = NULL;
|
| |
+ }
|
| |
+ if (state->inodeIndexes) {
|
| |
- + inodeIndexHashFree(state->inodeIndexes);
|
| |
- + state->inodeIndexes = NULL;
|
| |
+ + inodeIndexHashFree(state->inodeIndexes);
|
| |
+ + state->inodeIndexes = NULL;
|
| |
+ }
|
| |
+ + state->transcoded = 0;
|
| |
+ return RPMRC_OK;
|
| |
+}
|
| |
+
|
| |
+
|
| |
- +// have a prototype, warnings system
|
| |
+ +/* have a prototype, warnings system */
|
| |
+rpm_loff_t find(const unsigned char *digest, reflink_state state);
|
| |
+
|
| |
+rpm_loff_t find(const unsigned char *digest, reflink_state state) {
|
| |
- +# if defined(__GNUC__)
|
| |
- + /* GCC nested function because bsearch's comparison function can't access
|
| |
- + state-keysize otherwise
|
| |
- + */
|
| |
- + int cmpdigest(const void *k1, const void *k2) {
|
| |
- + rpmlog(RPMLOG_DEBUG, _("reflink: cmpdigest k1=%p k2=%p\n"), k1, k2);
|
| |
- + return memcmp(k1, k2, state->keysize);
|
| |
- + }
|
| |
- +# endif
|
| |
- + rpmlog(RPMLOG_DEBUG, _("reflink: bsearch(key=%p, base=%p, nmemb=%d, size=%lu)\n"), digest, state->table, state->keys, state->keysize + sizeof(rpm_loff_t));
|
| |
- + char *entry = bsearch(digest, state->table, state->keys, state->keysize + sizeof(rpm_loff_t), cmpdigest);
|
| |
- + if (entry == NULL) {
|
| |
- + return NOT_FOUND;
|
| |
- + }
|
| |
- + rpm_loff_t offset = *(rpm_loff_t *)(entry + state->keysize);
|
| |
- + return offset;
|
| |
+ + rpmlog(RPMLOG_DEBUG,
|
| |
+ + _("reflink: bsearch_r(key=%p, base=%p, nmemb=%d, size=%lu)\n"),
|
| |
+ + digest, state->table, state->keys,
|
| |
+ + state->keysize + sizeof(rpm_loff_t));
|
| |
+ + char *entry = bsearch_r(digest, state->table, state->keys,
|
| |
+ + state->keysize + sizeof(rpm_loff_t), cmpdigest,
|
| |
+ + &state->keysize);
|
| |
+ + if (entry == NULL) {
|
| |
+ + return NOT_FOUND;
|
| |
+ + }
|
| |
+ + rpm_loff_t offset = *(rpm_loff_t *)(entry + state->keysize);
|
| |
+ + return offset;
|
| |
+}
|
| |
+
|
| |
- +static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path, mode_t file_mode, rpmFsmOp op)
|
| |
+ +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) {
|
| |
- + // no table means rpm is not in reflink format, so leave. Now.
|
| |
- + return RPMRC_OK;
|
| |
+ + /* no table means rpm is not in reflink format, so leave. Now. */
|
| |
+ + return RPMRC_OK;
|
| |
+ }
|
| |
+ if (op == FA_TOUCH) {
|
| |
- + // we're not overwriting an existing file
|
| |
- + return RPMRC_OK;
|
| |
+ + /* we're not overwriting an existing file. */
|
| |
+ + return RPMRC_OK;
|
| |
+ }
|
| |
+ fcr.dest_offset = 0;
|
| |
+ if (S_ISREG(file_mode) && !(rpmfiFFlags(fi) & RPMFILE_GHOST)) {
|
| |
- + rpm_ino_t inode = rpmfiFInode(fi);
|
| |
- + /* 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)) {
|
| |
- + // entry is in table, use hard link
|
| |
- + char *fn = rpmfilesFN(state->files, hlix[0]);
|
| |
- + if (link(fn, path) != 0) {
|
| |
- + rpmlog(RPMLOG_ERR, _("reflink: Unable to hard link %s -> %s due to %s\n"), fn, path, strerror(errno));
|
| |
- + free(fn);
|
| |
- + return RPMRC_FAIL;
|
| |
- + }
|
| |
- + free(fn);
|
| |
- + return RPMRC_PLUGIN_CONTENTS;
|
| |
- + }
|
| |
- + /* if we didn't hard link, then we'll track this inode as being created soon */
|
| |
- + if (rpmfiFNlink(fi) > 1) {
|
| |
- + /* minor optimization: only store files with more than one link */
|
| |
- + inodeIndexHashAddEntry(state->inodeIndexes, inode, rpmfiFX(fi));
|
| |
- + }
|
| |
- + /* derived from wfd_open in fsm.c */
|
| |
- + mode_t old_umask = umask(0577);
|
| |
- + dst = open(path, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR);
|
| |
- + umask(old_umask);
|
| |
- + if (dst == -1) {
|
| |
- + rpmlog(RPMLOG_ERR, _("reflink: Unable to open %s for writing due to %s, flags = %x\n"), path, strerror(errno), rpmfiFFlags(fi));
|
| |
- + return RPMRC_FAIL;
|
| |
- + }
|
| |
- + size = rpmfiFSize(fi);
|
| |
- + if (size > 0) {
|
| |
- + /* round src_length down to fundamental_block_size multiple */
|
| |
- + fcr.src_length = size / state->fundamental_block_size * state->fundamental_block_size;
|
| |
- + if ((size % state->fundamental_block_size) > 0) {
|
| |
- + /* round up to next fundamental_block_size. We expect the data in the rpm to be similarly padded */
|
| |
- + fcr.src_length += state->fundamental_block_size;
|
| |
- + }
|
| |
- + fcr.src_fd = Fileno(state->fd);
|
| |
- + if (fcr.src_fd == -1) {
|
| |
- + close(dst);
|
| |
- + rpmlog(RPMLOG_ERR, _("reflink: src fd lookup failed\n"));
|
| |
- + return RPMRC_FAIL;
|
| |
- + }
|
| |
- + fcr.src_offset = find(rpmfiFDigest(fi, NULL, NULL), state);
|
| |
- + if (fcr.src_offset == NOT_FOUND) {
|
| |
- + close(dst);
|
| |
- + rpmlog(RPMLOG_ERR, _("reflink: digest not found\n"));
|
| |
- + return RPMRC_FAIL;
|
| |
- + }
|
| |
- + rpmlog(RPMLOG_DEBUG, _("reflink: Reflinking %lu bytes at %lu to %s orig size=%lu, file=%ld\n"), fcr.src_length, fcr.src_offset, path, size, fcr.src_fd);
|
| |
- + rc = ioctl(dst, FICLONERANGE, &fcr);
|
| |
- + if (rc) {
|
| |
- + rpmlog(RPMLOG_WARNING, _("reflink: falling back to copying bits for %s due to %d, %d = %s\n"), path, rc, errno, strerror(errno));
|
| |
- + if (Fseek(state->fd, fcr.src_offset, SEEK_SET) < 0) {
|
| |
- + close(dst);
|
| |
- + rpmlog(RPMLOG_ERR, _("reflink: unable to seek on copying bits\n"));
|
| |
- + return RPMRC_FAIL;
|
| |
- + }
|
| |
- + rpm_loff_t left = size;
|
| |
- + size_t len, read, written;
|
| |
- + while (left) {
|
| |
- + len = (left > BUFFER_SIZE ? BUFFER_SIZE : left);
|
| |
- + read = Fread(state->buffer, len, 1, state->fd);
|
| |
- + if (read != len) {
|
| |
- + close(dst);
|
| |
- + rpmlog(RPMLOG_ERR, _("reflink: short read on copying bits\n"));
|
| |
- + return RPMRC_FAIL;
|
| |
- + }
|
| |
- + written = write(dst, state->buffer, len);
|
| |
- + if (read != written) {
|
| |
- + close(dst);
|
| |
- + rpmlog(RPMLOG_ERR, _("reflink: short write on copying bits\n"));
|
| |
- + return RPMRC_FAIL;
|
| |
- + }
|
| |
- + left -= len;
|
| |
- + }
|
| |
- + } else {
|
| |
- + /* reflink worked, so truncate */
|
| |
- + rc = ftruncate(dst, size);
|
| |
- + if (rc) {
|
| |
- + rpmlog(RPMLOG_ERR, _("reflink: Unable to truncate %s to %ld due to %s\n"), path, size, strerror(errno));
|
| |
- + return RPMRC_FAIL;
|
| |
- + }
|
| |
- + }
|
| |
- + }
|
| |
- + close(dst);
|
| |
- + return RPMRC_PLUGIN_CONTENTS;
|
| |
+ + rpm_ino_t inode = rpmfiFInode(fi);
|
| |
+ + /* check for hard link entry in table. GetEntry overwrites hlix with
|
| |
+ + * the address of the first match.
|
| |
+ + */
|
| |
+ + if (inodeIndexHashGetEntry(state->inodeIndexes, inode, &hl_target,
|
| |
+ + NULL, NULL)) {
|
| |
+ + /* entry is in table, use hard link */
|
| |
+ + if (link(hl_target[0], path) != 0) {
|
| |
+ + rpmlog(RPMLOG_ERR,
|
| |
+ + _("reflink: Unable to hard link %s -> %s due to %s\n"),
|
| |
+ + hl_target[0], path, strerror(errno));
|
| |
+ + return RPMRC_FAIL;
|
| |
+ + }
|
| |
+ + return RPMRC_PLUGIN_CONTENTS;
|
| |
+ + }
|
| |
+ + /* if we didn't hard link, then we'll track this inode as being
|
| |
+ + * created soon
|
| |
+ + */
|
| |
+ + if (rpmfiFNlink(fi) > 1) {
|
| |
+ + /* minor optimization: only store files with more than one link */
|
| |
+ + inodeIndexHashAddEntry(state->inodeIndexes, inode, rstrdup(path));
|
| |
+ + }
|
| |
+ + /* derived from wfd_open in fsm.c */
|
| |
+ + mode_t old_umask = umask(0577);
|
| |
+ + dst = open(path, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR);
|
| |
+ + umask(old_umask);
|
| |
+ + if (dst == -1) {
|
| |
+ + rpmlog(RPMLOG_ERR,
|
| |
+ + _("reflink: Unable to open %s for writing due to %s, flags = %x\n"),
|
| |
+ + path, strerror(errno), rpmfiFFlags(fi));
|
| |
+ + return RPMRC_FAIL;
|
| |
+ + }
|
| |
+ + size = rpmfiFSize(fi);
|
| |
+ + if (size > 0) {
|
| |
+ + /* round src_length down to fundamental_block_size multiple */
|
| |
+ + fcr.src_length = size / state->fundamental_block_size * state->fundamental_block_size;
|
| |
+ + if ((size % state->fundamental_block_size) > 0) {
|
| |
+ + /* round up to next fundamental_block_size. We expect the data
|
| |
+ + * in the rpm to be similarly padded.
|
| |
+ + */
|
| |
+ + fcr.src_length += state->fundamental_block_size;
|
| |
+ + }
|
| |
+ + fcr.src_fd = Fileno(state->fd);
|
| |
+ + if (fcr.src_fd == -1) {
|
| |
+ + close(dst);
|
| |
+ + rpmlog(RPMLOG_ERR, _("reflink: src fd lookup failed\n"));
|
| |
+ + return RPMRC_FAIL;
|
| |
+ + }
|
| |
+ + fcr.src_offset = find(rpmfiFDigest(fi, NULL, NULL), state);
|
| |
+ + if (fcr.src_offset == NOT_FOUND) {
|
| |
+ + close(dst);
|
| |
+ + rpmlog(RPMLOG_ERR, _("reflink: digest not found\n"));
|
| |
+ + return RPMRC_FAIL;
|
| |
+ + }
|
| |
+ + rpmlog(RPMLOG_DEBUG,
|
| |
+ + _("reflink: Reflinking %llu bytes at %llu to %s orig size=%ld, file=%lld\n"),
|
| |
+ + fcr.src_length, fcr.src_offset, path, size, fcr.src_fd);
|
| |
+ + rc = ioctl(dst, FICLONERANGE, &fcr);
|
| |
+ + if (rc) {
|
| |
+ + rpmlog(RPMLOG_WARNING,
|
| |
+ + _("reflink: falling back to copying bits for %s due to %d, %d = %s\n"),
|
| |
+ + path, rc, errno, strerror(errno));
|
| |
+ + if (Fseek(state->fd, fcr.src_offset, SEEK_SET) < 0) {
|
| |
+ + close(dst);
|
| |
+ + rpmlog(RPMLOG_ERR,
|
| |
+ + _("reflink: unable to seek on copying bits\n"));
|
| |
+ + return RPMRC_FAIL;
|
| |
+ + }
|
| |
+ + rpm_loff_t left = size;
|
| |
+ + size_t len, read, written;
|
| |
+ + while (left) {
|
| |
+ + len = (left > BUFFER_SIZE ? BUFFER_SIZE : left);
|
| |
+ + read = Fread(state->buffer, len, 1, state->fd);
|
| |
+ + if (read != len) {
|
| |
+ + close(dst);
|
| |
+ + rpmlog(RPMLOG_ERR,
|
| |
+ + _("reflink: short read on copying bits\n"));
|
| |
+ + return RPMRC_FAIL;
|
| |
+ + }
|
| |
+ + written = write(dst, state->buffer, len);
|
| |
+ + if (read != written) {
|
| |
+ + close(dst);
|
| |
+ + rpmlog(RPMLOG_ERR,
|
| |
+ + _("reflink: short write on copying bits\n"));
|
| |
+ + return RPMRC_FAIL;
|
| |
+ + }
|
| |
+ + left -= len;
|
| |
+ + }
|
| |
+ + } else {
|
| |
+ + /* reflink worked, so truncate */
|
| |
+ + rc = ftruncate(dst, size);
|
| |
+ + if (rc) {
|
| |
+ + rpmlog(RPMLOG_ERR,
|
| |
+ + _("reflink: Unable to truncate %s to %ld due to %s\n"),
|
| |
+ + path, size, strerror(errno));
|
| |
+ + return RPMRC_FAIL;
|
| |
+ + }
|
| |
+ + }
|
| |
+ + }
|
| |
+ + close(dst);
|
| |
+ + return RPMRC_PLUGIN_CONTENTS;
|
| |
+ + }
|
| |
+ + 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;
|
| |
+}
|
| |
@@ -804,19 +1667,22 @@
|
| |
+ .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
|
| |
new file mode 100644
|
| |
- index 000000000..5662b86a6
|
| |
+ index 0000000..c29831d
|
| |
--- /dev/null
|
| |
+++ b/rpm2extents.c
|
| |
- @@ -0,0 +1,519 @@
|
| |
+ @@ -0,0 +1,708 @@
|
| |
+/* rpm2extents: convert payload to inline extents */
|
| |
+
|
| |
+#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>
|
| |
@@ -824,8 +1690,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>
|
| |
@@ -838,7 +1706,7 @@
|
| |
+#include "debug.h"
|
| |
+
|
| |
+/* hash of void * (pointers) to file digests to offsets within output.
|
| |
- + The length of the key depends on what the FILEDIGESTALGO is.
|
| |
+ + * The length of the key depends on what the FILEDIGESTALGO is.
|
| |
+ */
|
| |
+#undef HASHTYPE
|
| |
+#undef HTKEYTYPE
|
| |
@@ -848,9 +1716,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;
|
| |
@@ -863,119 +1728,221 @@
|
| |
+ 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)
|
| |
- + {
|
| |
- + fprintf(stderr, _("Unable to write input length %zd\n"), fdilength);
|
| |
- + goto exit;
|
| |
+ + if (Fwrite(&fdilength, len, 1, fdo) != len) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Unable to write input length %zd: %d, %s\n"),
|
| |
+ + fdilength, errno, strerror(errno));
|
| |
+ + goto exit;
|
| |
+ }
|
| |
+ len = sizeof(algos_len);
|
| |
- + if (Fwrite(&algos_len, len, 1, validationo) != len)
|
| |
- + {
|
| |
- + fprintf(stderr, _("Unable to write number of validation digests\n"));
|
| |
- + goto exit;
|
| |
+ + if (Fwrite(&algos_len, len, 1, fdo) != len) {
|
| |
+ + algo_digest_len = (uint32_t)filedigest_len;
|
| |
+ + rpmlog(RPMLOG_ERR, _("Unable to write number of digests: %d, %s\n"),
|
| |
+ + errno, strerror(errno));
|
| |
+ + goto exit;
|
| |
+ }
|
| |
- + for (algo = 0; algo < algos_len; algo++)
|
| |
- + {
|
| |
- + fdFiniDigest(fdi, algos[algo], (void **)&filedigest, &filedigest_len, 0);
|
| |
- +
|
| |
- + algo_name = pgpValString(PGPVAL_HASHALGO, algos[algo]);
|
| |
- + algo_name_len = (uint32_t)strlen(algo_name);
|
| |
- + algo_digest_len = (uint32_t)filedigest_len;
|
| |
- +
|
| |
- + len = sizeof(algo_name_len);
|
| |
- + if (Fwrite(&algo_name_len, len, 1, validationo) != len)
|
| |
- + {
|
| |
- + fprintf(
|
| |
- + stderr,
|
| |
- + _("Unable to write validation algo name length\n")
|
| |
- + );
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + len = sizeof(algo_digest_len);
|
| |
- + if (Fwrite(&algo_digest_len, len, 1, validationo) != len)
|
| |
- + {
|
| |
- + fprintf(
|
| |
- + stderr,
|
| |
- + _("Unable to write number of bytes for validation 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"));
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + if (
|
| |
- + Fwrite(
|
| |
- + filedigest,
|
| |
- + algo_digest_len,
|
| |
- + 1,
|
| |
- + validationo
|
| |
- + ) != algo_digest_len
|
| |
- + )
|
| |
- + {
|
| |
- + fprintf(
|
| |
- + stderr,
|
| |
- + _("Unable to write validation digest value %u, %zu\n"),
|
| |
- + algo_digest_len,
|
| |
- + filedigest_len
|
| |
- + );
|
| |
- + goto exit;
|
| |
- + }
|
| |
+ + for (algo = 0; algo < algos_len; algo++) {
|
| |
+ + fdFiniDigest(fdi, algos[algo], (void **)&filedigest, &filedigest_len, 0);
|
| |
+ +
|
| |
+ + algo_name = pgpValString(PGPVAL_HASHALGO, algos[algo]);
|
| |
+ + algo_name_len = (uint32_t)strlen(algo_name);
|
| |
+ + algo_digest_len = (uint32_t)filedigest_len;
|
| |
+ +
|
| |
+ + len = sizeof(algo_name_len);
|
| |
+ + if (Fwrite(&algo_name_len, len, 1, fdo) != len) {
|
| |
+ + rpmlog(RPMLOG_ERR,
|
| |
+ + _("Unable to write digest algo name length: %d, %s\n"),
|
| |
+ + errno, strerror(errno));
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ + len = sizeof(algo_digest_len);
|
| |
+ + if (Fwrite(&algo_digest_len, len, 1, fdo) != len) {
|
| |
+ + rpmlog(RPMLOG_ERR,
|
| |
+ + _("Unable to write number of bytes for digest: %d, %s\n"),
|
| |
+ + errno, strerror(errno));
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ + if (Fwrite(algo_name, algo_name_len, 1, fdo) != algo_name_len) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Unable to write digest algo name: %d, %s\n"),
|
| |
+ + errno, strerror(errno));
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ + if (Fwrite(filedigest, algo_digest_len, 1, fdo ) != algo_digest_len) {
|
| |
+ + rpmlog(RPMLOG_ERR,
|
| |
+ + _("Unable to write digest value %u, %zu: %d, %s\n"),
|
| |
+ + algo_digest_len, filedigest_len,
|
| |
+ + errno, strerror(errno));
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ + }
|
| |
+ + rc = RPMRC_OK;
|
| |
+ +exit:
|
| |
+ + return rc;
|
| |
+ +}
|
| |
+ +
|
| |
+ +/**
|
| |
+ + * Check if package is in deny list.
|
| |
+ + * @param package_name package name
|
| |
+ + * @return true if package is in deny list
|
| |
+ + */
|
| |
+ +static inline int isInDenyList(char *package_name)
|
| |
+ +{
|
| |
+ + int is_in_deny_list = 0;
|
| |
+ + if (package_name) {
|
| |
+ + char *e_denylist = getenv("LIBREPO_TRANSCODE_RPMS_DENYLIST");
|
| |
+ + char *denytlist_item = strtok(e_denylist, ",");
|
| |
+ + while (denytlist_item) {
|
| |
+ + if (strstr(package_name, denytlist_item)) {
|
| |
+ + is_in_deny_list = 1;
|
| |
+ + break;
|
| |
+ + }
|
| |
+ + denytlist_item = strtok(NULL, ",");
|
| |
+ + }
|
| |
+ + }
|
| |
+ + return is_in_deny_list;
|
| |
+ +}
|
| |
+ +
|
| |
+ +static rpmRC FDWriteSignaturesValidation(FD_t fdo, int rpmvsrc, char *msg) {
|
| |
+ + size_t len;
|
| |
+ + rpmRC rc = RPMRC_FAIL;
|
| |
+ +
|
| |
+ + if(rpmvsrc){
|
| |
+ + rpmlog(RPMLOG_WARNING,
|
| |
+ + _("Error verifying package signatures:\n%s\n"), msg);
|
| |
+ + }
|
| |
+ +
|
| |
+ + len = sizeof(rpmvsrc);
|
| |
+ + if (Fwrite(&rpmvsrc, len, 1, fdo) != len) {
|
| |
+ + rpmlog(RPMLOG_ERR,
|
| |
+ + _("Unable to write signature verification RC code %d: %d, %s\n"),
|
| |
+ + rpmvsrc, errno, strerror(errno));
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ + size_t content_len = msg ? strlen(msg) : 0;
|
| |
+ + len = sizeof(content_len);
|
| |
+ + if (Fwrite(&content_len, len, 1, fdo) != len) {
|
| |
+ + rpmlog(RPMLOG_ERR,
|
| |
+ + _("Unable to write signature verification output length %zd: %d, %s\n"),
|
| |
+ + content_len, errno, strerror(errno));
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ + if (Fwrite(msg, content_len, 1, fdo) != content_len) {
|
| |
+ + rpmlog(RPMLOG_ERR,
|
| |
+ + _("Unable to write signature verification output %s: %d, %s\n"),
|
| |
+ + msg, errno, strerror(errno));
|
| |
+ + 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) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Failed to write digests: %d, %s\n"),
|
| |
+ + errno, strerror(errno));
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ +
|
| |
+ + // Write result of signature validation.
|
| |
+ + if(FDWriteSignaturesValidation(sigo, rpmvsrc, msg)) {
|
| |
+ + rpmlog(RPMLOG_ERR,
|
| |
+ + _("Failed to write signature verification result: %d, %s\n"),
|
| |
+ + errno, strerror(errno));
|
| |
+ + goto exit;
|
| |
+ }
|
| |
+ rc = RPMRC_OK;
|
| |
+exit:
|
| |
+ + if(msg) {
|
| |
+ + free(msg);
|
| |
+ + }
|
| |
+ + rpmtsFree(ts);
|
| |
+ return rc;
|
| |
+}
|
| |
+
|
| |
- +static rpmRC process_package(FD_t fdi, FD_t validationi)
|
| |
+ +static void sanitizeSignatureHeader(Header * sigh)
|
| |
+ +{
|
| |
+ + struct rpmtd_s td;
|
| |
+ +
|
| |
+ + /* This is inspired by the code in unloadImmutableRegion. See https://github.com/rpm-software-management/rpm/pull/1330 */
|
| |
+ + if (!headerGet(*sigh, RPMTAG_HEADERSIGNATURES, &td, HEADERGET_DEFAULT)) {
|
| |
+ + /* Signature header corrupt/missing */
|
| |
+ + rpmlog(RPMLOG_WARNING, _("Error verifying signature header\n"));
|
| |
+ + rpmtdFreeData(&td);
|
| |
+ + Header nh = headerCopy(*sigh);
|
| |
+ + headerFree(*sigh);
|
| |
+ + *sigh = headerLink(nh);
|
| |
+ + headerFree(nh);
|
| |
+ + }
|
| |
+ + rpmtdFreeData(&td);
|
| |
+ +}
|
| |
+ +
|
| |
+ +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 */
|
| |
- + int digestSetCmp(const unsigned char * a, const unsigned char * b)
|
| |
- + {
|
| |
- + return memcmp(a, b, diglen);
|
| |
+ + int digestSetCmp(const unsigned char * a, const unsigned char * b) {
|
| |
+ + return memcmp(a, b, diglen);
|
| |
+ }
|
| |
+
|
| |
- + unsigned int digestSetHash(const unsigned char * digest)
|
| |
- + {
|
| |
+ + unsigned int digestSetHash(const unsigned char * digest) {
|
| |
+ /* assumes sizeof(unsigned int) < diglen */
|
| |
+ return *(unsigned int *)digest;
|
| |
+ }
|
| |
+
|
| |
- + int digestoffsetCmp(const void * a, const void * b)
|
| |
- + {
|
| |
- + return digestSetCmp(
|
| |
- + ((struct digestoffset *)a)->digest,
|
| |
- + ((struct digestoffset *)b)->digest
|
| |
- + );
|
| |
+ + int digestoffsetCmp(const void * a, const void * b) {
|
| |
+ + return digestSetCmp(
|
| |
+ + ((struct digestoffset *)a)->digest,
|
| |
+ + ((struct digestoffset *)b)->digest
|
| |
+ + );
|
| |
+ }
|
| |
+
|
| |
+ FD_t fdo;
|
| |
@@ -986,353 +1953,439 @@
|
| |
+ 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;
|
| |
+ + struct rpmlead_s l;
|
| |
+ + rpmfiles files = NULL;
|
| |
+ + rpmfi fi = NULL;
|
| |
+ + char *msg = NULL;
|
| |
+ + struct digestoffset *offsets = NULL;
|
| |
+ + digestSet ds = NULL;
|
| |
+
|
| |
+ fdo = fdDup(STDOUT_FILENO);
|
| |
+
|
| |
- + if (rpmReadPackageRaw(fdi, &sigh, &h))
|
| |
- + {
|
| |
- + fprintf(stderr, _("Error reading package\n"));
|
| |
- + exit(EXIT_FAILURE);
|
| |
- + }
|
| |
+ + rc = rpmLeadReadAndReturn(fdi, &msg, &l);
|
| |
+ + if (rc != RPMRC_OK)
|
| |
+ + goto exit;
|
| |
+
|
| |
- + if (rpmLeadWrite(fdo, h))
|
| |
- + {
|
| |
- + fprintf(
|
| |
- + stderr,
|
| |
- + _("Unable to write package lead: %s\n"),
|
| |
- + Fstrerror(fdo)
|
| |
- + );
|
| |
- + exit(EXIT_FAILURE);
|
| |
- + }
|
| |
+ + /* Skip conversion if package is in deny list */
|
| |
+ + if (isInDenyList(l.name)) {
|
| |
+ + rpmlog(RPMLOG_WARNING, _("package %s is in deny list: conversion skipped\n"), l.name);
|
| |
+ + if (rpmLeadWrite(fdo, l)) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Unable to write package lead: %s\n"),
|
| |
+ + Fstrerror(fdo));
|
| |
+ + rc = RPMRC_FAIL;
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+
|
| |
- + if (rpmWriteSignature(fdo, sigh))
|
| |
- + {
|
| |
- + fprintf(stderr, _("Unable to write signature: %s\n"), Fstrerror(fdo));
|
| |
- + exit(EXIT_FAILURE);
|
| |
- + }
|
| |
+ + ssize_t fdilength = ufdCopy(fdi, fdo);
|
| |
+ + if (fdilength == -1) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("process_package cat failed\n"));
|
| |
+ + rc = RPMRC_FAIL;
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+
|
| |
- + if (headerWrite(fdo, h, HEADER_MAGIC_YES))
|
| |
- + {
|
| |
- + fprintf(stderr, _("Unable to write headers: %s\n"), Fstrerror(fdo));
|
| |
- + exit(EXIT_FAILURE);
|
| |
- + }
|
| |
+ + goto exit;
|
| |
+ + } else {
|
| |
+ + if (rpmReadPackageRaw(fdi, &sigh, &h)) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Error reading package\n"));
|
| |
+ + exit(EXIT_FAILURE);
|
| |
+ + }
|
| |
+
|
| |
- + /* Retrieve payload size and compression type. */
|
| |
- + { const char *compr = headerGetString(h, RPMTAG_PAYLOADCOMPRESSOR);
|
| |
- + rpmio_flags = rstrscat(NULL, "r.", compr ? compr : "gzip", NULL);
|
| |
- + }
|
| |
+ + sanitizeSignatureHeader(&sigh);
|
| |
+
|
| |
- + gzdi = Fdopen(fdi, rpmio_flags); /* XXX gzdi == fdi */
|
| |
- + free(rpmio_flags);
|
| |
+ + if (rpmLeadWriteFromHeader(fdo, h)) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Unable to write package lead: %s\n"),
|
| |
+ + Fstrerror(fdo));
|
| |
+ + exit(EXIT_FAILURE);
|
| |
+ + }
|
| |
+
|
| |
- + if (gzdi == NULL)
|
| |
- + {
|
| |
- + fprintf(stderr, _("cannot re-open payload: %s\n"), Fstrerror(gzdi));
|
| |
- + exit(EXIT_FAILURE);
|
| |
- + }
|
| |
+ + if (rpmWriteSignature(fdo, sigh)) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Unable to write signature: %s\n"),
|
| |
+ + Fstrerror(fdo));
|
| |
+ + exit(EXIT_FAILURE);
|
| |
+ + }
|
| |
+
|
| |
- + rpmfiles files = rpmfilesNew(NULL, h, 0, RPMFI_KEEPHEADER);
|
| |
- + rpmfi fi = rpmfiNewArchiveReader(
|
| |
- + gzdi,
|
| |
- + files,
|
| |
- + RPMFI_ITER_READ_ARCHIVE_CONTENT_FIRST
|
| |
- + );
|
| |
+ + if (headerWrite(fdo, h, HEADER_MAGIC_YES)) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Unable to write headers: %s\n"),
|
| |
+ + Fstrerror(fdo));
|
| |
+ + exit(EXIT_FAILURE);
|
| |
+ + }
|
| |
+
|
| |
- + /* this is encoded in the file format, so needs to be fixed size (for
|
| |
- + now?)
|
| |
- + */
|
| |
- + diglen = (uint32_t)rpmDigestLength(rpmfiDigestAlgo(fi));
|
| |
- + digestSet ds = digestSetCreate(
|
| |
- + rpmfiFC(fi),
|
| |
- + digestSetHash,
|
| |
- + digestSetCmp,
|
| |
- + NULL
|
| |
- + );
|
| |
- + struct digestoffset offsets[rpmfiFC(fi)];
|
| |
- + pos = RPMLEAD_SIZE + headerSizeof(sigh, HEADER_MAGIC_YES);
|
| |
+ + /* Retrieve payload size and compression type. */
|
| |
+ + {
|
| |
+ + const char *compr =
|
| |
+ + headerGetString(h, RPMTAG_PAYLOADCOMPRESSOR);
|
| |
+ + rpmio_flags =
|
| |
+ + rstrscat(NULL, "r.", compr ? compr : "gzip", NULL);
|
| |
+ + }
|
| |
+
|
| |
- + /* main headers are aligned to 8 byte boundry */
|
| |
- + pos += pad_to(pos, 8);
|
| |
- + pos += headerSizeof(h, HEADER_MAGIC_YES);
|
| |
+ + gzdi = Fdopen(fdi, rpmio_flags); /* XXX gzdi == fdi */
|
| |
+ + free(rpmio_flags);
|
| |
+
|
| |
- + zeros = xcalloc(fundamental_block_size, 1);
|
| |
+ + if (gzdi == NULL) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("cannot re-open payload: %s\n"),
|
| |
+ + Fstrerror(gzdi));
|
| |
+ + exit(EXIT_FAILURE);
|
| |
+ + }
|
| |
+
|
| |
- + while (next >= 0)
|
| |
- + {
|
| |
- + next = rpmfiNext(fi);
|
| |
- + if (next == RPMERR_ITER_END)
|
| |
- + {
|
| |
- + rc = RPMRC_OK;
|
| |
- + break;
|
| |
- + }
|
| |
- + mode = rpmfiFMode(fi);
|
| |
- + if (!S_ISREG(mode) || !rpmfiArchiveHasContent(fi))
|
| |
- + {
|
| |
- + /* not a regular file, or the archive doesn't contain any content for
|
| |
- + this entry
|
| |
- + */
|
| |
- + continue;
|
| |
- + }
|
| |
- + digest = rpmfiFDigest(fi, NULL, NULL);
|
| |
- + if (digestSetGetEntry(ds, digest, NULL))
|
| |
- + {
|
| |
- + /* This specific digest has already been included, so skip it */
|
| |
- + continue;
|
| |
- + }
|
| |
- + pad = pad_to(pos, fundamental_block_size);
|
| |
- + if (Fwrite(zeros, sizeof(char), pad, fdo) != pad)
|
| |
- + {
|
| |
- + fprintf(stderr, _("Unable to write padding\n"));
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + /* round up to next fundamental_block_size */
|
| |
- + pos += pad;
|
| |
- + digestSetAddEntry(ds, digest);
|
| |
- + offsets[offset_ix].digest = digest;
|
| |
- + offsets[offset_ix].pos = pos;
|
| |
- + offset_ix++;
|
| |
- + size = rpmfiFSize(fi);
|
| |
- + rc = rpmfiArchiveReadToFile(fi, fdo, 0);
|
| |
- + if (rc != RPMRC_OK)
|
| |
- + {
|
| |
- + fprintf(stderr, _("rpmfiArchiveReadToFile failed with %d\n"), rc);
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + pos += size;
|
| |
- + }
|
| |
- + Fclose(gzdi); /* XXX gzdi == fdi */
|
| |
+ + files = rpmfilesNew(NULL, h, 0, RPMFI_KEEPHEADER);
|
| |
+ + fi = rpmfiNewArchiveReader(gzdi, files,
|
| |
+ + RPMFI_ITER_READ_ARCHIVE_CONTENT_FIRST);
|
| |
+ +
|
| |
+ + /* this is encoded in the file format, so needs to be fixed size (for
|
| |
+ + * now?)
|
| |
+ + */
|
| |
+ + diglen = (uint32_t) rpmDigestLength(rpmfiDigestAlgo(fi));
|
| |
+ + ds = digestSetCreate(rpmfiFC(fi), digestSetHash, digestSetCmp, NULL);
|
| |
+ + offsets = xcalloc(rpmfiFC(fi), sizeof(*offsets));
|
| |
+ + pos = RPMLEAD_SIZE + headerSizeof(sigh, HEADER_MAGIC_YES);
|
| |
+ +
|
| |
+ + /* main headers are aligned to 8 byte boundry */
|
| |
+ + pos += pad_to(pos, 8);
|
| |
+ + pos += headerSizeof(h, HEADER_MAGIC_YES);
|
| |
+ +
|
| |
+ + zeros = xcalloc(fundamental_block_size, 1);
|
| |
+ +
|
| |
+ + while (next >= 0) {
|
| |
+ + next = rpmfiNext(fi);
|
| |
+ + if (next == RPMERR_ITER_END) {
|
| |
+ + rc = RPMRC_OK;
|
| |
+ + break;
|
| |
+ + }
|
| |
+ + mode = rpmfiFMode(fi);
|
| |
+ + if (!S_ISREG(mode) || !rpmfiArchiveHasContent(fi)) {
|
| |
+ + /* not a regular file, or the archive doesn't contain any content
|
| |
+ + * for this entry.
|
| |
+ + */
|
| |
+ + continue;
|
| |
+ + }
|
| |
+ + digest = rpmfiFDigest(fi, NULL, NULL);
|
| |
+ + if (digestSetGetEntry(ds, digest, NULL)) {
|
| |
+ + /* This specific digest has already been included, so skip it. */
|
| |
+ + continue;
|
| |
+ + }
|
| |
+ + pad = pad_to(pos, fundamental_block_size);
|
| |
+ + if (Fwrite(zeros, sizeof(char), pad, fdo) != pad) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Unable to write padding\n"));
|
| |
+ + rc = RPMRC_FAIL;
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ + /* round up to next fundamental_block_size */
|
| |
+ + pos += pad;
|
| |
+ + digestSetAddEntry(ds, digest);
|
| |
+ + offsets[offset_ix].digest = digest;
|
| |
+ + offsets[offset_ix].pos = pos;
|
| |
+ + offset_ix++;
|
| |
+ + size = rpmfiFSize(fi);
|
| |
+ + rc = rpmfiArchiveReadToFile(fi, fdo, 0);
|
| |
+ + if (rc != RPMRC_OK) {
|
| |
+ + char *errstr = rpmfileStrerror(rc);
|
| |
+ + rpmlog(RPMLOG_ERR,
|
| |
+ + _("rpmfiArchiveReadToFile failed while extracting "
|
| |
+ + "\"%s\" with RC %d: %s\n"),
|
| |
+ + rpmfiFN(fi), rc, errstr);
|
| |
+ + free(errstr);
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ + pos += size;
|
| |
+ + }
|
| |
+ + Fclose(gzdi); /* XXX gzdi == fdi */
|
| |
+
|
| |
- + qsort(
|
| |
- + offsets,
|
| |
- + (size_t)offset_ix,
|
| |
- + sizeof(struct digestoffset),
|
| |
- + digestoffsetCmp
|
| |
- + );
|
| |
+ + qsort(offsets, (size_t) offset_ix, sizeof(struct digestoffset),
|
| |
+ + digestoffsetCmp);
|
| |
+
|
| |
- + len = sizeof(offset_ix);
|
| |
- + if (Fwrite(&offset_ix, len, 1, fdo) != len)
|
| |
- + {
|
| |
- + fprintf(stderr, _("Unable to write length of table\n"));
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + len = sizeof(diglen);
|
| |
- + if (Fwrite(&diglen, len, 1, fdo) != len)
|
| |
- + {
|
| |
- + fprintf(stderr, _("Unable to write length of digest\n"));
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + len = sizeof(rpm_loff_t);
|
| |
- + for (int x = 0; x < offset_ix; x++)
|
| |
- + {
|
| |
- + if (Fwrite(offsets[x].digest, diglen, 1, fdo) != diglen)
|
| |
- + {
|
| |
- + fprintf(stderr, _("Unable to write digest\n"));
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + if (Fwrite(&offsets[x].pos, len, 1, fdo) != len)
|
| |
- + {
|
| |
- + fprintf(stderr, _("Unable to write offset\n"));
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + }
|
| |
- + validation_pos = (
|
| |
- + pos + sizeof(offset_ix) + sizeof(diglen) +
|
| |
- + offset_ix * (diglen + sizeof(rpm_loff_t))
|
| |
- + );
|
| |
+ + validation_pos = pos;
|
| |
+ + ssize_t validation_len = ufdCopy(validationi, fdo);
|
| |
+ + if (validation_len == -1) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("validation output ufdCopy failed\n"));
|
| |
+ + rc = RPMRC_FAIL;
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+
|
| |
- + ssize_t validation_len = ufdCopy(validationi, fdo);
|
| |
- + if (validation_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
|
| |
- + */
|
| |
- +
|
| |
- + pad = pad_to(
|
| |
- + (
|
| |
- + validation_pos + validation_len + 2 * sizeof(rpm_loff_t) +
|
| |
- + sizeof(uint64_t)
|
| |
- + ),
|
| |
- + fundamental_block_size
|
| |
- + );
|
| |
- + if (Fwrite(zeros, sizeof(char), pad, fdo) != pad)
|
| |
- + {
|
| |
- + fprintf(stderr, _("Unable to write final padding\n"));
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + zeros = _free(zeros);
|
| |
- + if (Fwrite(&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)
|
| |
- + {
|
| |
- + fprintf(stderr, _("Unable to write offset of validation table\n"));
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + goto exit;
|
| |
- + }
|
| |
- + uint64_t magic = MAGIC;
|
| |
- + len = sizeof(magic);
|
| |
- + if (Fwrite(&magic, len, 1, fdo) != len)
|
| |
- + {
|
| |
- + fprintf(stderr, _("Unable to write magic\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) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Unable to write length of table\n"));
|
| |
+ + rc = RPMRC_FAIL;
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ + len = sizeof(diglen);
|
| |
+ + if (Fwrite(&diglen, len, 1, fdo) != len) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Unable to write length of digest\n"));
|
| |
+ + rc = RPMRC_FAIL;
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ + len = sizeof(rpm_loff_t);
|
| |
+ + for (int x = 0; x < offset_ix; x++) {
|
| |
+ + if (Fwrite(offsets[x].digest, diglen, 1, fdo) != diglen) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Unable to write digest\n"));
|
| |
+ + rc = RPMRC_FAIL;
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ + if (Fwrite(&offsets[x].pos, len, 1, fdo) != len) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Unable to write offset\n"));
|
| |
+ + rc = RPMRC_FAIL;
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ + }
|
| |
+ + digest_pos =
|
| |
+ + (digest_table_pos + sizeof(offset_ix) + sizeof(diglen) +
|
| |
+ + offset_ix * (diglen + sizeof(rpm_loff_t))
|
| |
+ + );
|
| |
+ +
|
| |
+ + ssize_t digest_len = ufdCopy(digestori, fdo);
|
| |
+ + if (digest_len == -1) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("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.
|
| |
+ + */
|
| |
+ +
|
| |
+ + pad =
|
| |
+ + pad_to((validation_pos + validation_len +
|
| |
+ + 2 * sizeof(rpm_loff_t) + sizeof(uint64_t)),
|
| |
+ + fundamental_block_size);
|
| |
+ + if (Fwrite(zeros, sizeof(char), pad, fdo) != pad) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Unable to write final padding\n"));
|
| |
+ + rc = RPMRC_FAIL;
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ + zeros = _free(zeros);
|
| |
+ + struct extents_footer_t footer = {.offsets =
|
| |
+ + { validation_pos, digest_table_pos, digest_pos },.magic =
|
| |
+ + EXTENTS_MAGIC };
|
| |
+ + len = sizeof(footer);
|
| |
+ + if (Fwrite(&footer, len, 1, fdo) != len) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Unable to write footer\n"));
|
| |
+ + rc = RPMRC_FAIL;
|
| |
+ + goto exit;
|
| |
+ + }
|
| |
+ }
|
| |
+
|
| |
- +exit:
|
| |
+ + exit:
|
| |
+ rpmfilesFree(files);
|
| |
+ rpmfiFree(fi);
|
| |
+ headerFree(h);
|
| |
+ + headerFree(sigh);
|
| |
+ + free(offsets);
|
| |
+ + Fclose(fdo);
|
| |
+ + digestSetFree(ds);
|
| |
+ return rc;
|
| |
+}
|
| |
+
|
| |
- +int main(int argc, char *argv[])
|
| |
+ +static off_t ufdTee(FD_t sfd, FD_t *fds, int len)
|
| |
+{
|
| |
- + rpmRC rc;
|
| |
- + int cprc = 0;
|
| |
- + uint8_t algos[argc - 1];
|
| |
- + int mainpipefd[2];
|
| |
- + int metapipefd[2];
|
| |
- + pid_t cpid, w;
|
| |
+ + 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) {
|
| |
+ + rpmlog(RPMLOG_ERR,
|
| |
+ + _("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;
|
| |
+ + }
|
| |
+ + }
|
| |
+ +
|
| |
+ + return total;
|
| |
+ +}
|
| |
+ +
|
| |
+ +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];
|
| |
+
|
| |
- + xsetprogname(argv[0]); /* Portability call -- see system.h */
|
| |
- + rpmReadConfigFiles(NULL, NULL);
|
| |
+ + if (pipe(processorpipefd) == -1) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Processor pipe failure\n"));
|
| |
+ + return RPMRC_FAIL;
|
| |
+ + }
|
| |
+
|
| |
- + if (argc > 1 && (rstreq(argv[1], "-h") || rstreq(argv[1], "--help")))
|
| |
- + {
|
| |
- + fprintf(stderr, _("Usage: %s [DIGESTALGO]...\n"), argv[0]);
|
| |
- + exit(EXIT_FAILURE);
|
| |
+ + if (pipe(validatorpipefd) == -1) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Validator pipe failure\n"));
|
| |
+ + return RPMRC_FAIL;
|
| |
+ }
|
| |
+
|
| |
- + if (argc == 1)
|
| |
- + {
|
| |
- + fprintf(
|
| |
- + stderr,
|
| |
- + _("Need at least one DIGESTALGO parameter, e.g. 'SHA256'\n")
|
| |
- + );
|
| |
- + exit(EXIT_FAILURE);
|
| |
+ + if (pipe(meta_digestpipefd) == -1) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Meta digest 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(meta_rpmsignpipefd) == -1) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Meta rpm signature pipe failure\n"));
|
| |
+ + return RPMRC_FAIL;
|
| |
+ }
|
| |
+
|
| |
+ + 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) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Validator failed with RC %d\n"), rc);
|
| |
+ + }
|
| |
+ + Fclose(fdi);
|
| |
+ + Fclose(digesto);
|
| |
+ + Fclose(sigo);
|
| |
+ + if (rc != RPMRC_OK) {
|
| |
+ + exit(EXIT_FAILURE);
|
| |
+ + }
|
| |
+ + exit(EXIT_SUCCESS);
|
| |
+ + } else {
|
| |
+ + /* parent: main program */
|
| |
+ + 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) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("Package processor failed: %d\n"), rc);
|
| |
+ + }
|
| |
+ + Fclose(digestori);
|
| |
+ + Fclose(sigi);
|
| |
+ + /* fdi is normally closed through the stacked file gzdi in the
|
| |
+ + * function
|
| |
+ + */
|
| |
+ +
|
| |
+ + if (rc != RPMRC_OK) {
|
| |
+ + exit(EXIT_FAILURE);
|
| |
+ + }
|
| |
+ + exit(EXIT_SUCCESS);
|
| |
+ +
|
| |
+ +
|
| |
+ + } else {
|
| |
+ + /* 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]);
|
| |
+
|
| |
- + if (pipe(mainpipefd) == -1)
|
| |
- + {
|
| |
- + fprintf(stderr, _("Main pipe failure\n"));
|
| |
- + exit(EXIT_FAILURE);
|
| |
+ + rc = RPMRC_OK;
|
| |
+ + offt = ufdTee(fdi, fds, 2);
|
| |
+ + if(offt == -1){
|
| |
+ + rpmlog(RPMLOG_ERR, _("Failed to tee RPM\n"));
|
| |
+ + rc = RPMRC_FAIL;
|
| |
+ + }
|
| |
+ + Fclose(fds[0]);
|
| |
+ + Fclose(fds[1]);
|
| |
+ + w = waitpid(cpids[0], &wstatus, 0);
|
| |
+ + if (w == -1) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("waitpid cpids[0] failed\n"));
|
| |
+ + rc = RPMRC_FAIL;
|
| |
+ + }
|
| |
+ + w = waitpid(cpids[1], &wstatus, 0);
|
| |
+ + if (w == -1) {
|
| |
+ + rpmlog(RPMLOG_ERR, _("waitpid cpids[1] failed\n"));
|
| |
+ + rc = RPMRC_FAIL;
|
| |
+ + }
|
| |
+ + }
|
| |
+ }
|
| |
- + if (pipe(metapipefd) == -1)
|
| |
- + {
|
| |
- + fprintf(stderr, _("Meta pipe failure\n"));
|
| |
- + exit(EXIT_FAILURE);
|
| |
+ +
|
| |
+ + 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) {
|
| |
+ + rpmlog(RPMLOG_ERR,
|
| |
+ + _("Need at least one DIGESTALGO parameter, e.g. 'SHA256'\n"));
|
| |
+ + poptPrintUsage(optCon, stderr, 0);
|
| |
+ + exit(EXIT_FAILURE);
|
| |
+ }
|
| |
- + 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);
|
| |
- + Fclose(fdi);
|
| |
- + } 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)
|
| |
- + );
|
| |
- + }
|
| |
- + }
|
| |
- + 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
|
| |
- + );
|
| |
- + }
|
| |
- + } else if (WIFSIGNALED(wstatus))
|
| |
- + {
|
| |
- + fprintf(
|
| |
- + stderr,
|
| |
- + _("Digest process was terminated with a signal: %d\n"),
|
| |
- + WTERMSIG(wstatus)
|
| |
- + );
|
| |
- + cprc = EXIT_FAILURE;
|
| |
- + } else
|
| |
- + {
|
| |
- + /* don't think this can happen, but covering all bases */
|
| |
- + fprintf(stderr, _("Unhandled circumstance in waitpid\n"));
|
| |
- + cprc = EXIT_FAILURE;
|
| |
- + }
|
| |
- + if (cprc != EXIT_SUCCESS)
|
| |
- + {
|
| |
- + rc = RPMRC_FAIL;
|
| |
- + }
|
| |
+ +
|
| |
+ + 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)
|
| |
+ + {
|
| |
+ + rpmlog(RPMLOG_ERR,
|
| |
+ + _("Unable to resolve '%s' as a digest algorithm, exiting\n"),
|
| |
+ + args[x]);
|
| |
+ + exit(EXIT_FAILURE);
|
| |
+ + }
|
| |
+ }
|
| |
- + if (rc != RPMRC_OK)
|
| |
- + {
|
| |
- + /* translate rpmRC into generic failure return code. */
|
| |
- + return EXIT_FAILURE;
|
| |
+ +
|
| |
+ + FD_t fdi = fdDup(STDIN_FILENO);
|
| |
+ + rc = teeRpm(fdi, algos, nb_algos);
|
| |
+ + Fclose(fdi);
|
| |
+ + if (rc != RPMRC_OK) {
|
| |
+ + /* translate rpmRC into generic failure return code. */
|
| |
+ + return EXIT_FAILURE;
|
| |
+ }
|
| |
+ return EXIT_SUCCESS;
|
| |
+}
|
| |
diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
|
| |
- index 015c15a5c..7b972b4a6 100644
|
| |
+ index 43a2a99..f8d5562 100644
|
| |
--- a/rpmio/rpmpgp.c
|
| |
+++ b/rpmio/rpmpgp.c
|
| |
@@ -298,6 +298,16 @@ int pgpValTok(pgpValTbl vs, const char * s, const char * se)
|
| |
@@ -1353,7 +2406,7 @@
|
| |
* Decode length from 1, 2, or 5 octet body length encoding, used in
|
| |
* new format packet headers and V4 signature subpackets.
|
| |
diff --git a/rpmio/rpmpgp.h b/rpmio/rpmpgp.h
|
| |
- index c53e29b01..2b57318ba 100644
|
| |
+ index 469b5b3..7a1fefd 100644
|
| |
--- a/rpmio/rpmpgp.h
|
| |
+++ b/rpmio/rpmpgp.h
|
| |
@@ -973,6 +973,15 @@ typedef rpmFlags rpmDigestFlags;
|
| |
@@ -1372,6 +2425,337 @@
|
| |
/** \ingroup rpmpgp
|
| |
* Return (native-endian) integer from big-endian representation.
|
| |
* @param s pointer to big-endian integer
|
| |
+ diff --git a/scripts/rpm2extents_dump b/scripts/rpm2extents_dump
|
| |
+ new file mode 100755
|
| |
+ index 0000000..596a59a
|
| |
+ --- /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/sign/rpmgensig.c b/sign/rpmgensig.c
|
| |
+ index 4608e1a..6159088 100644
|
| |
+ --- a/sign/rpmgensig.c
|
| |
+ +++ b/sign/rpmgensig.c
|
| |
+ @@ -610,7 +610,7 @@ static int rpmSign(const char *rpm, int deleting, int flags)
|
| |
+ }
|
| |
+
|
| |
+ /* Write the lead/signature of the output rpm */
|
| |
+ - rc = rpmLeadWrite(ofd, h);
|
| |
+ + rc = rpmLeadWriteFromHeader(ofd, h);
|
| |
+ if (rc != RPMRC_OK) {
|
| |
+ rpmlog(RPMLOG_ERR, _("%s: writeLead failed: %s\n"), trpm,
|
| |
+ Fstrerror(ofd));
|
| |
+ diff --git a/tests/Makefile.am b/tests/Makefile.am
|
| |
+ index 6d9f1f8..4a588a6 100644
|
| |
+ --- a/tests/Makefile.am
|
| |
+ +++ b/tests/Makefile.am
|
| |
+ @@ -36,6 +36,7 @@ TESTSUITE_AT += rpmspec.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 7d1deb8..ff0703a 100644
|
| |
+ --- a/tests/atlocal.in
|
| |
+ +++ b/tests/atlocal.in
|
| |
+ @@ -50,6 +50,19 @@ else
|
| |
+ CAP_DISABLED=true;
|
| |
+ fi
|
| |
+
|
| |
+ +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 setup_env()
|
| |
+ {
|
| |
+ if [ -d testing ]; then
|
| |
+ @@ -82,6 +95,15 @@ function runroot()
|
| |
+ )
|
| |
+ }
|
| |
+
|
| |
+ +function runroot_plugins()
|
| |
+ +{
|
| |
+ + setup_env
|
| |
+ + (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()
|
| |
+ {
|
| |
+ setup_env
|
| |
+ diff --git a/tests/rpm2extents.at b/tests/rpm2extents.at
|
| |
+ new file mode 100644
|
| |
+ index 0000000..c9c79c5
|
| |
+ --- /dev/null
|
| |
+ +++ b/tests/rpm2extents.at
|
| |
+ @@ -0,0 +1,151 @@
|
| |
+ +# 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
|
| |
+ +
|
| |
+ +# check that package in denylist is not transcoded
|
| |
+ +AT_SETUP([rpm2extents denylist])
|
| |
+ +AT_KEYWORDS([rpm2extents])
|
| |
+ +AT_CHECK([
|
| |
+ +export LIBREPO_TRANSCODE_RPMS_DENYLIST="vim,hello,cowsay"
|
| |
+ +runroot_other cat /data/RPMS/hello-2.0-1.x86_64.rpm | runroot_other rpm2extents SHA256 | runroot_other cmp /data/RPMS/hello-2.0-1.x86_64.rpm -],
|
| |
+ +[0],
|
| |
+ +[],
|
| |
+ +[ignore])
|
| |
+ +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 --nodeps --undefine=%__transaction_dbus_announce /tmp/hello-2.0-1.x86_64.rpm
|
| |
+ +test -f ${RPMTEST}/usr/bin/hello
|
| |
+ +],
|
| |
+ +[0],
|
| |
+ +[],
|
| |
+ +[])
|
| |
+ +AT_CLEANUP
|
| |
+ +
|
| |
+ +AT_SETUP([reflink ignores non-transcoded package])
|
| |
+ +AT_KEYWORDS([reflink])
|
| |
+ +AT_CHECK([
|
| |
+ +RPMDB_INIT
|
| |
+ +
|
| |
+ +runroot_plugins rpm -i --nodeps --undefine=%__transaction_dbus_announce /data/RPMS/hello-2.0-1.x86_64.rpm && exit $?
|
| |
+ +# Check that the file is properly installed in chroot
|
| |
+ +test -f ${RPMTEST}/usr/bin/hello
|
| |
+ +],
|
| |
+ +[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 --nodeps --undefine=%__transaction_dbus_announce /tmp/${PKG}
|
| |
+ +],
|
| |
+ +[0],
|
| |
+ +[],
|
| |
+ +[])
|
| |
+ +AT_CLEANUP
|
| |
+ diff --git a/tests/rpmtests.at b/tests/rpmtests.at
|
| |
+ index 48b86bd..e219a16 100644
|
| |
+ --- a/tests/rpmtests.at
|
| |
+ +++ b/tests/rpmtests.at
|
| |
+ @@ -22,3 +22,4 @@ m4_include([rpmreplace.at])
|
| |
+ m4_include([rpmconfig.at])
|
| |
+ m4_include([rpmconfig2.at])
|
| |
+ m4_include([rpmconfig3.at])
|
| |
+ +m4_include([rpm2extents.at])
|
| |
--
|
| |
- 2.35.1
|
| |
+ 2.47.0
|
| |
|
| |
Squash all 35 patches in one, and fix a potential problem when interacting with other plugins