From 732e023fb16b92aeb61e59d2100c67174e239555 Mon Sep 17 00:00:00 2001 From: chantra Date: Feb 09 2022 17:27:15 +0000 Subject: sync with latest CoW patch. Ensure directories are created before creating files. --- diff --git a/SOURCES/cow...cow_signvalidation.diff b/SOURCES/cow...cow_signvalidation.diff index 1dd40fb..a76b5a8 100644 --- a/SOURCES/cow...cow_signvalidation.diff +++ b/SOURCES/cow...cow_signvalidation.diff @@ -11,62 +11,173 @@ index 288668819..96542c8c8 100644 rpmconfig_DATA = rpmrc rpmrc: $(top_srcdir)/rpmrc.in +diff --git a/lib/Makefile.am b/lib/Makefile.am +index 5a1b6ca9b..2f1b3597f 100644 +--- a/lib/Makefile.am ++++ b/lib/Makefile.am +@@ -40,7 +40,8 @@ librpm_la_SOURCES = \ + rpmscript.h rpmscript.c \ + rpmchroot.c rpmchroot.h \ + rpmplugins.c rpmplugins.h rpmplugin.h rpmug.c rpmug.h \ +- rpmtriggers.h rpmtriggers.c rpmvs.c rpmvs.h ++ rpmtriggers.h rpmtriggers.c rpmvs.c rpmvs.h \ ++ rpmextents.c rpmextents_internal.h + + librpm_la_LDFLAGS = -version-info $(rpm_version_info) + +diff --git a/lib/depends.c b/lib/depends.c +index 8998afcd3..30234df3d 100644 +--- a/lib/depends.c ++++ b/lib/depends.c +@@ -81,8 +81,6 @@ static rpmRC headerCheckPayloadFormat(Header h) { + */ + if (!payloadfmt) return rc; + +- if (rstreq(payloadfmt, "clon")) return rc; +- + if (!rstreq(payloadfmt, "cpio")) { + char *nevra = headerGetAsString(h, RPMTAG_NEVRA); + if (payloadfmt && rstreq(payloadfmt, "drpm")) { +diff --git a/lib/fsm.c b/lib/fsm.c +index feda3750c..6972602e0 100644 +--- a/lib/fsm.c ++++ b/lib/fsm.c +@@ -19,7 +19,6 @@ + + #include "rpmio/rpmio_internal.h" /* fdInit/FiniDigest */ + #include "lib/fsm.h" +-#include "lib/rpmlib.h" + #include "lib/rpmte_internal.h" /* XXX rpmfs */ + #include "lib/rpmplugins.h" /* rpm plugins hooks */ + #include "lib/rpmug.h" +@@ -53,7 +52,6 @@ struct filedata_s { + int stage; + int setmeta; + int skip; +- int plugin_contents; + rpmFileAction action; + const char *suffix; + char *fpath; +@@ -893,14 +891,6 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files, + struct filedata_s *fdata = xcalloc(fc, sizeof(*fdata)); + struct filedata_s *firstlink = NULL; + +- Header h = rpmteHeader(te); +- const char *payloadfmt = headerGetString(h, RPMTAG_PAYLOADFORMAT); +- int cpio = 1; +- +- if (payloadfmt && rstreq(payloadfmt, "clon")) { +- cpio = 0; +- } +- + /* transaction id used for temporary path suffix while installing */ + rasprintf(&tid, ";%08x", (unsigned)rpmtsGetTid(ts)); + +@@ -921,23 +911,12 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files, + /* Remap file perms, owner, and group. */ + rc = rpmfiStat(fi, 1, &fp->sb); + ++ setFileState(fs, fx); + fsmDebug(fp->fpath, fp->action, &fp->sb); + + /* Run fsm file pre hook for all plugins */ + rc = rpmpluginsCallFsmFilePre(plugins, fi, fp->fpath, + fp->sb.st_mode, fp->action); +- fp->plugin_contents = 0; +- switch (rc) { +- case RPMRC_OK: +- setFileState(fs, fx); +- break; +- case RPMRC_PLUGIN_CONTENTS: +- fp->plugin_contents = 1; +- // reduce reads on cpio to this value. Could be zero if +- // this is from a hard link. +- rc = RPMRC_OK; +- break; +- } + fp->stage = FILE_PRE; + } + fi = rpmfiFree(fi); +@@ -945,14 +924,24 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files, + if (rc) + goto exit; + +- if (cpio) { +- fi = rpmfiNewArchiveReader(payload, files, RPMFI_ITER_READ_ARCHIVE); +- if (fi == NULL) { +- rc = RPMERR_BAD_MAGIC; +- goto exit; +- } +- } else { +- fi = rpmfilesIter(files, RPMFI_ITER_FWD); ++ rpmRC plugin_rc = rpmpluginsCallFsmFileArchiveReader(plugins, payload, files, &fi); ++ switch(plugin_rc) { ++ case RPMRC_PLUGIN_CONTENTS: ++ if(fi == NULL) { ++ rc = RPMERR_BAD_MAGIC; ++ goto exit; ++ } ++ rc = RPMRC_OK; ++ break; ++ case RPMRC_OK: ++ fi = rpmfiNewArchiveReader(payload, files, RPMFI_ITER_READ_ARCHIVE); ++ if (fi == NULL) { ++ rc = RPMERR_BAD_MAGIC; ++ goto exit; ++ } ++ break; ++ default: ++ rc = RPMRC_FAIL; + } + + /* Detect and create directories not explicitly in package. */ +@@ -992,14 +981,15 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files, + if (fp->action == FA_TOUCH) + continue; + +- if (S_ISREG(fp->sb.st_mode)) { ++ rpmRC plugin_rc = rpmpluginsCallFsmFileInstall(plugins, fi, fp->fpath, fp->sb.st_mode, fp->action); ++ if(!(plugin_rc == RPMRC_PLUGIN_CONTENTS || plugin_rc == RPMRC_OK)){ ++ rc = plugin_rc; ++ } else if(plugin_rc == RPMRC_PLUGIN_CONTENTS){ ++ rc = RPMRC_OK; ++ } else if (S_ISREG(fp->sb.st_mode)) { + if (rc == RPMERR_ENOENT) { +- if(fp->plugin_contents) { +- rc = RPMRC_OK; +- }else { +- rc = fsmMkfile(fi, fp, files, psm, nodigest, +- &firstlink, &firstlinkfile); +- } ++ rc = fsmMkfile(fi, fp, files, psm, nodigest, ++ &firstlink, &firstlinkfile); + } + } else if (S_ISDIR(fp->sb.st_mode)) { + if (rc == RPMERR_ENOENT) { +@@ -1107,7 +1097,6 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files, + rpmswAdd(rpmtsOp(ts, RPMTS_OP_DIGEST), fdOp(payload, FDSTAT_DIGEST)); + + exit: +- h = headerFree(h); + fi = rpmfiFree(fi); + Fclose(payload); + free(tid); diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c -index 40a3ab83f..6164d012c 100644 +index 40a3ab83f..dc1726a18 100644 --- a/lib/rpmchecksig.c +++ b/lib/rpmchecksig.c -@@ -24,6 +24,11 @@ - - int _print_pkts = 0; +@@ -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" -+/* magic value at end of file (64 bits) that indicates this is a transcoded -+ * rpm. -+ */ -+#define MAGIC 3472329499408095051 -+ - static int doImport(rpmts ts, const char *fn, char *buf, ssize_t blen) - { - char const * const pgpmark = "-----BEGIN PGP "; -@@ -220,6 +225,107 @@ rpmRC rpmpkgRead(struct rpmvs_s *vs, FD_t fd, + #include "debug.h" +@@ -220,6 +221,71 @@ rpmRC rpmpkgRead(struct rpmvs_s *vs, FD_t fd, return rc; } -+static rpmRC isTranscodedRpm(FD_t fd) { -+ rpmRC rc = RPMRC_NOTFOUND; -+ rpm_loff_t current; -+ uint64_t magic; -+ size_t len; -+ -+ // If the file is not seekable, we cannot detect whether or not it is transcoded. -+ if(Fseek(fd, 0, SEEK_CUR) < 0) { -+ return RPMRC_FAIL; -+ } -+ current = Ftell(fd); -+ -+ if(Fseek(fd, -(sizeof(magic)), SEEK_END) < 0) { -+ rpmlog(RPMLOG_ERR, _("isTranscodedRpm: failed to seek for magic\n")); -+ rc = RPMRC_FAIL; -+ goto exit; -+ } -+ len = sizeof(magic); -+ if (Fread(&magic, len, 1, fd) != len) { -+ rpmlog(RPMLOG_ERR, _("isTranscodedRpm: unable to read magic\n")); -+ rc = RPMRC_FAIL; -+ goto exit; -+ } -+ if (magic != MAGIC) { -+ rpmlog(RPMLOG_DEBUG, _("isTranscodedRpm: not transcoded\n")); -+ rc = RPMRC_NOTFOUND; -+ goto exit; -+ } -+ rc = RPMRC_OK; -+exit: -+ if (Fseek(fd, current, SEEK_SET) < 0) { -+ rpmlog(RPMLOG_ERR, _("isTranscodedRpm: unable to seek back to original location\n")); -+ } -+ return rc; -+} -+ +static int rpmpkgVerifySigsTranscoded(FD_t fd){ + rpm_loff_t current; + uint64_t magic; @@ -135,7 +246,7 @@ index 40a3ab83f..6164d012c 100644 static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags, FD_t fd, const char *fn) { -@@ -229,10 +335,14 @@ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags, +@@ -229,10 +295,14 @@ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags, .verbose = rpmIsVerbose(), }; int rc; @@ -151,7 +262,7 @@ index 40a3ab83f..6164d012c 100644 rc = rpmpkgRead(vs, fd, NULL, NULL, &msg); if (rc) -@@ -260,6 +370,29 @@ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags, +@@ -260,6 +330,29 @@ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags, return rc; } @@ -181,7 +292,7 @@ index 40a3ab83f..6164d012c 100644 /* Wrapper around rpmkVerifySigs to preserve API */ int rpmVerifySignatures(QVA_t qva, rpmts ts, FD_t fd, const char * fn) { -@@ -304,3 +437,53 @@ int rpmcliVerifySignatures(rpmts ts, ARGV_const_t argv) +@@ -304,3 +397,53 @@ int rpmcliVerifySignatures(rpmts ts, ARGV_const_t argv) rpmKeyringFree(keyring); return res; } @@ -256,8 +367,354 @@ index 906fe9951..7ff48b37a 100644 #ifdef __cplusplus } #endif +diff --git a/lib/rpmextents.c b/lib/rpmextents.c +new file mode 100644 +index 000000000..015277751 +--- /dev/null ++++ b/lib/rpmextents.c +@@ -0,0 +1,46 @@ ++ ++#include "system.h" ++ ++#include ++#include ++ ++#include "lib/rpmextents_internal.h" ++ ++rpmRC isTranscodedRpm(FD_t fd) { ++ rpmRC rc = RPMRC_NOTFOUND; ++ rpm_loff_t current; ++ extents_magic_t magic; ++ size_t len; ++ ++ // If the file is not seekable, we cannot detect whether or not it is transcoded. ++ if(Fseek(fd, 0, SEEK_CUR) < 0) { ++ return RPMRC_FAIL; ++ } ++ current = Ftell(fd); ++ ++ if(Fseek(fd, -(sizeof(magic)), SEEK_END) < 0) { ++ rpmlog(RPMLOG_ERR, _("isTranscodedRpm: failed to seek for magic\n")); ++ rc = RPMRC_FAIL; ++ goto exit; ++ } ++ len = sizeof(magic); ++ if (Fread(&magic, len, 1, fd) != len) { ++ rpmlog(RPMLOG_ERR, _("isTranscodedRpm: unable to read magic\n")); ++ rc = RPMRC_FAIL; ++ goto exit; ++ } ++ if (magic != EXTENTS_MAGIC) { ++ rpmlog(RPMLOG_DEBUG, _("isTranscodedRpm: not transcoded\n")); ++ rc = RPMRC_NOTFOUND; ++ goto exit; ++ } ++ rc = RPMRC_OK; ++exit: ++ if (Fseek(fd, current, SEEK_SET) < 0) { ++ rpmlog(RPMLOG_ERR, _("isTranscodedRpm: unable to seek back to original location\n")); ++ rc = RPMRC_FAIL; ++ } ++ return rc; ++} ++ ++ +diff --git a/lib/rpmextents_internal.h b/lib/rpmextents_internal.h +new file mode 100644 +index 000000000..57cecfc31 +--- /dev/null ++++ b/lib/rpmextents_internal.h +@@ -0,0 +1,22 @@ ++#ifndef _RPMEXTENTS_INTERNAL_H ++#define _RPMEXTENTS_INTERNAL_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include ++ ++/* magic value at end of file (64 bits) that indicates this is a transcoded ++ * rpm. ++ */ ++#define EXTENTS_MAGIC 3472329499408095051 ++ ++typedef uint64_t extents_magic_t; ++ ++rpmRC isTranscodedRpm(FD_t fd); ++ ++#ifdef __cplusplus ++} ++#endif ++#endif +diff --git a/lib/rpmplugin.h b/lib/rpmplugin.h +index fd81aec8d..6dbbcff35 100644 +--- a/lib/rpmplugin.h ++++ b/lib/rpmplugin.h +@@ -60,6 +60,13 @@ typedef rpmRC (*plugin_fsm_file_prepare_func)(rpmPlugin plugin, rpmfi fi, + const char* path, + const char *dest, + mode_t file_mode, rpmFsmOp op); ++typedef rpmRC (*plugin_fsm_file_install_func)(rpmPlugin plugin, rpmfi fi, ++ const char* path, ++ mode_t file_mode, rpmFsmOp op); ++typedef rpmRC (*plugin_fsm_file_archive_reader_func)(rpmPlugin plugin, ++ FD_t payload, ++ rpmfiles files, rpmfi *fi); ++ + + typedef struct rpmPluginHooks_s * rpmPluginHooks; + struct rpmPluginHooks_s { +@@ -80,6 +87,8 @@ struct rpmPluginHooks_s { + plugin_fsm_file_pre_func fsm_file_pre; + plugin_fsm_file_post_func fsm_file_post; + plugin_fsm_file_prepare_func fsm_file_prepare; ++ plugin_fsm_file_install_func fsm_file_install; ++ plugin_fsm_file_archive_reader_func fsm_file_archive_reader; + }; + + #ifdef __cplusplus +diff --git a/lib/rpmplugins.c b/lib/rpmplugins.c +index 3da3097af..901af1ac5 100644 +--- a/lib/rpmplugins.c ++++ b/lib/rpmplugins.c +@@ -421,3 +421,74 @@ rpmRC rpmpluginsCallFsmFilePrepare(rpmPlugins plugins, rpmfi fi, + + return rc; + } ++ ++rpmRC rpmpluginsCallFsmFileInstall(rpmPlugins plugins, rpmfi fi, ++ const char *path, mode_t file_mode, ++ rpmFsmOp op) ++{ ++ plugin_fsm_file_install_func hookFunc; ++ int i; ++ rpmRC rc = RPMRC_OK; ++ rpmRC hook_rc; ++ ++ for (i = 0; i < plugins->count; i++) { ++ rpmPlugin plugin = plugins->plugins[i]; ++ RPMPLUGINS_SET_HOOK_FUNC(fsm_file_install); ++ if (hookFunc) { ++ hook_rc = hookFunc(plugin, fi, path, file_mode, op); ++ if (hook_rc == RPMRC_FAIL) { ++ rpmlog(RPMLOG_ERR, "Plugin %s: hook fsm_file_install failed\n", plugin->name); ++ rc = RPMRC_FAIL; ++ } else if (hook_rc == RPMRC_PLUGIN_CONTENTS && rc != RPMRC_FAIL) { ++ if (rc == RPMRC_PLUGIN_CONTENTS) { ++ /* Another plugin already said it'd handle contents. It's ++ * undefined how these would combine, so treat this as a ++ * failure condition. ++ */ ++ rc = RPMRC_FAIL; ++ } else { ++ /* Plugin will handle content */ ++ rc = RPMRC_PLUGIN_CONTENTS; ++ } ++ } ++ } ++ } ++ ++ return rc; ++} ++ ++rpmRC rpmpluginsCallFsmFileArchiveReader(rpmPlugins plugins, FD_t payload, ++ rpmfiles files, rpmfi *fi) ++{ ++ plugin_fsm_file_archive_reader_func hookFunc; ++ int i; ++ rpmRC rc = RPMRC_OK; ++ rpmRC hook_rc; ++ ++ for (i = 0; i < plugins->count; i++) { ++ rpmPlugin plugin = plugins->plugins[i]; ++ RPMPLUGINS_SET_HOOK_FUNC(fsm_file_archive_reader); ++ if (hookFunc) { ++ hook_rc = hookFunc(plugin, payload, files, fi); ++ if (hook_rc == RPMRC_FAIL) { ++ rpmlog(RPMLOG_ERR, "Plugin %s: hook fsm_file_archive_reader failed\n", plugin->name); ++ rc = RPMRC_FAIL; ++ } else if (hook_rc == RPMRC_PLUGIN_CONTENTS && rc != RPMRC_FAIL) { ++ if (rc == RPMRC_PLUGIN_CONTENTS) { ++ /* Another plugin already said it'd handle contents. It's ++ * undefined how these would combine, so treat this as a ++ * failure condition. ++ */ ++ rc = RPMRC_FAIL; ++ } else { ++ /* Plugin will handle content */ ++ rc = RPMRC_PLUGIN_CONTENTS; ++ } ++ } ++ } ++ } ++ ++ return rc; ++} ++ ++ +diff --git a/lib/rpmplugins.h b/lib/rpmplugins.h +index 39762c376..88807c53c 100644 +--- a/lib/rpmplugins.h ++++ b/lib/rpmplugins.h +@@ -167,6 +167,23 @@ rpmRC rpmpluginsCallFsmFilePrepare(rpmPlugins plugins, rpmfi fi, + const char *path, const char *dest, + mode_t mode, rpmFsmOp op); + ++/** \ingroup rpmplugins ++ * Call the fsm file install plugin hook ++ * @param plugins plugins structure ++ * @param fi file info iterator (or NULL) ++ * @param path file object path ++ * @param file_mode file object mode ++ * @param op file operation + associated flags ++ * @return RPMRC_OK on success, RPMRC_FAIL otherwise ++ */ ++RPM_GNUC_INTERNAL ++rpmRC rpmpluginsCallFsmFileInstall(rpmPlugins plugins, rpmfi fi, ++ const char* path, mode_t file_mode, ++ rpmFsmOp op); ++ ++RPM_GNUC_INTERNAL ++rpmRC rpmpluginsCallFsmFileArchiveReader(rpmPlugins plugins, FD_t payload, ++ rpmfiles files, rpmfi *fi); + #ifdef __cplusplus + } + #endif +diff --git a/plugins/reflink.c b/plugins/reflink.c +index 513887604..d5e6db27a 100644 +--- a/plugins/reflink.c ++++ b/plugins/reflink.c +@@ -13,6 +13,7 @@ + #include + #include "lib/rpmlib.h" + #include "lib/rpmplugin.h" ++#include "lib/rpmextents_internal.h" + #include "lib/rpmte_internal.h" + #include + #include "rpmio/rpmio_internal.h" +@@ -40,11 +41,6 @@ + + #define BUFFER_SIZE (1024 * 128) + +-/* magic value at end of file (64 bits) that indicates this is a transcoded +- * rpm. +- */ +-#define MAGIC 3472329499408095051 +- + struct reflink_state_s { + /* Stuff that's used across rpms */ + long fundamental_block_size; +@@ -58,6 +54,7 @@ struct reflink_state_s { + FD_t fd; + rpmfiles files; + inodeIndexHash inodeIndexes; ++ int transcoded; + }; + + typedef struct reflink_state_s * reflink_state; +@@ -96,51 +93,35 @@ static void reflink_cleanup(rpmPlugin plugin) { + } + + static rpmRC reflink_psm_pre(rpmPlugin plugin, rpmte te) { ++ rpmRC rc; ++ size_t len; ++ + reflink_state state = rpmPluginGetData(plugin); + state->fd = rpmteFd(te); + if (state->fd == 0) { + rpmlog(RPMLOG_DEBUG, _("reflink: fd = 0, no install\n")); + return RPMRC_OK; + } ++ + rpm_loff_t current = Ftell(state->fd); +- uint64_t magic; +- if (Fseek(state->fd, -(sizeof(magic)), SEEK_END) < 0) { +- rpmlog(RPMLOG_ERR, _("reflink: failed to seek for magic\n")); +- if (Fseek(state->fd, current, SEEK_SET) < 0) { +- /* yes this gets a bit repetitive */ +- rpmlog(RPMLOG_ERR, +- _("reflink: unable to seek back to original location\n")); +- } +- return RPMRC_FAIL; +- } +- size_t len = sizeof(magic); +- if (Fread(&magic, len, 1, state->fd) != len) { +- rpmlog(RPMLOG_ERR, _("reflink: unable to read magic\n")); +- if (Fseek(state->fd, current, SEEK_SET) < 0) { +- rpmlog(RPMLOG_ERR, +- _("reflink: unable to seek back to original location\n")); +- } +- return RPMRC_FAIL; +- } +- if (magic != MAGIC) { +- rpmlog(RPMLOG_DEBUG, _("reflink: not transcoded\n")); +- if (Fseek(state->fd, current, SEEK_SET) < 0) { +- rpmlog(RPMLOG_ERR, +- _("reflink: unable to seek back to original location\n")); ++ rc = isTranscodedRpm(state->fd); ++ ++ switch(rc){ ++ // Fail to parse the file, fail the plugin. ++ case RPMRC_FAIL: + return RPMRC_FAIL; +- } +- return RPMRC_OK; ++ // This is not a transcoded file, do nothing. ++ case RPMRC_NOTFOUND: ++ return RPMRC_OK; ++ default: ++ break; + } + rpmlog(RPMLOG_DEBUG, _("reflink: *is* transcoded\n")); +- Header h = rpmteHeader(te); ++ state->transcoded = 1; + +- /* replace/add header that main fsm.c can read */ +- headerDel(h, RPMTAG_PAYLOADFORMAT); +- headerPutString(h, RPMTAG_PAYLOADFORMAT, "clon"); +- headerFree(h); + state->files = rpmteFiles(te); + /* tail of file contains offset_table, offset_checksums then magic */ +- if (Fseek(state->fd, -(sizeof(rpm_loff_t) * 2 + sizeof(magic)), SEEK_END) < 0) { ++ if (Fseek(state->fd, -(sizeof(rpm_loff_t) * 2 + sizeof(extents_magic_t)), SEEK_END) < 0) { + rpmlog(RPMLOG_ERR, _("reflink: failed to seek for tail %p\n"), + state->fd); + return RPMRC_FAIL; +@@ -239,7 +220,7 @@ rpm_loff_t find(const unsigned char *digest, reflink_state state) { + return offset; + } + +-static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path, ++static rpmRC reflink_fsm_file_install(rpmPlugin plugin, rpmfi fi, const char* path, + mode_t file_mode, rpmFsmOp op) + { + struct file_clone_range fcr; +@@ -366,10 +347,21 @@ static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path, + return RPMRC_OK; + } + ++static rpmRC reflink_fsm_file_archive_reader(rpmPlugin plugin, FD_t payload, ++ rpmfiles files, rpmfi *fi) { ++ reflink_state state = rpmPluginGetData(plugin); ++ if(state->transcoded) { ++ *fi = rpmfilesIter(files, RPMFI_ITER_FWD); ++ return RPMRC_PLUGIN_CONTENTS; ++ } ++ return RPMRC_OK; ++} ++ + struct rpmPluginHooks_s reflink_hooks = { + .init = reflink_init, + .cleanup = reflink_cleanup, + .psm_pre = reflink_psm_pre, + .psm_post = reflink_psm_post, +- .fsm_file_pre = reflink_fsm_file_pre, ++ .fsm_file_install = reflink_fsm_file_install, ++ .fsm_file_archive_reader = reflink_fsm_file_archive_reader, + }; diff --git a/rpm2extents.c b/rpm2extents.c -index c111be0a2..e316a2834 100644 +index c111be0a2..a326e3857 100644 --- a/rpm2extents.c +++ b/rpm2extents.c @@ -2,7 +2,9 @@ @@ -270,15 +727,30 @@ index c111be0a2..e316a2834 100644 #include #include #include -@@ -10,6 +12,7 @@ +@@ -10,8 +12,10 @@ #include #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" -@@ -51,38 +54,47 @@ rpm_loff_t pad_to(rpm_loff_t pos, rpm_loff_t unit) + + #include +@@ -34,11 +38,6 @@ + #include "lib/rpmhash.H" + #include "lib/rpmhash.C" + +-/* magic value at end of file (64 bits) that indicates this is a transcoded +- * rpm. +- */ +-#define MAGIC 3472329499408095051 +- + struct digestoffset { + const unsigned char * digest; + rpm_loff_t pos; +@@ -51,38 +50,47 @@ rpm_loff_t pad_to(rpm_loff_t pos, rpm_loff_t unit) return (unit - (pos % unit)) % unit; } @@ -342,7 +814,7 @@ index c111be0a2..e316a2834 100644 goto exit; } for (algo = 0; algo < algos_len; algo++) { -@@ -93,24 +105,24 @@ static int digestor( +@@ -93,24 +101,24 @@ static int digestor( algo_digest_len = (uint32_t)filedigest_len; len = sizeof(algo_name_len); @@ -375,7 +847,7 @@ index c111be0a2..e316a2834 100644 algo_digest_len, filedigest_len); goto exit; } -@@ -120,7 +132,69 @@ static int digestor( +@@ -120,7 +128,69 @@ static int digestor( return rc; } @@ -446,7 +918,7 @@ index c111be0a2..e316a2834 100644 { uint32_t diglen; /* GNU C extension: can use diglen from outer context */ -@@ -148,7 +222,7 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) +@@ -148,7 +218,7 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) rpm_mode_t mode; char *rpmio_flags = NULL, *zeros; const unsigned char *digest; @@ -455,7 +927,7 @@ index c111be0a2..e316a2834 100644 uint32_t offset_ix = 0; size_t len; int next = 0; -@@ -253,6 +327,16 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) +@@ -253,6 +323,16 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) qsort(offsets, (size_t)offset_ix, sizeof(struct digestoffset), digestoffsetCmp); @@ -472,7 +944,7 @@ index c111be0a2..e316a2834 100644 len = sizeof(offset_ix); if (Fwrite(&offset_ix, len, 1, fdo) != len) { fprintf(stderr, _("Unable to write length of table\n")); -@@ -278,17 +362,18 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) +@@ -278,17 +358,18 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) goto exit; } } @@ -495,7 +967,7 @@ index c111be0a2..e316a2834 100644 /* add more padding so the last file can be cloned. It doesn't matter that * the table and validation etc are in this space. In fact, it's pretty * efficient if it is. -@@ -302,12 +387,17 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) +@@ -302,17 +383,22 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) goto exit; } zeros = _free(zeros); @@ -515,7 +987,13 @@ index c111be0a2..e316a2834 100644 fprintf(stderr, _("Unable to write offset of validation table\n")); rc = RPMRC_FAIL; goto exit; -@@ -327,104 +417,200 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) + } +- uint64_t magic = MAGIC; ++ extents_magic_t magic = EXTENTS_MAGIC; + len = sizeof(magic); + if (Fwrite(&magic, len, 1, fdo) != len) { + fprintf(stderr, _("Unable to write magic\n")); +@@ -327,104 +413,200 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) return rc; } @@ -900,7 +1378,7 @@ diff --git a/tests/Makefile.am b/tests/Makefile.am index f78e17c3e..fc8a24a5e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am -@@ -36,6 +36,7 @@ TESTSUITE_AT += rpmsigdig.at +@@ -36,6 +36,7 @@ TESTSUITE_AT += rpmio.at TESTSUITE_AT += rpmio.at TESTSUITE_AT += rpmorder.at TESTSUITE_AT += rpmvfylevel.at @@ -908,12 +1386,51 @@ index f78e17c3e..fc8a24a5e 100644 EXTRA_DIST += $(TESTSUITE_AT) ## testsuite data +diff --git a/tests/atlocal.in b/tests/atlocal.in +index c3189d327..a110564e2 100644 +--- a/tests/atlocal.in ++++ b/tests/atlocal.in +@@ -29,6 +29,19 @@ else + + RPM_XFAIL=${RPM_XFAIL-1} + ++FSTYPE=$(stat -f -c %T /) ++REFLINKABLE_FS=("xfs" "brtfs") ++ ++REFLINK_DISABLED=true; ++for item in "${REFLINKABLE_FS[@]}" ++do ++ if test "${FSTYPE}" = "${item}" ++ then ++ REFLINK_DISABLED=false; ++ break ++ fi ++done ++ + function run() + { + "$@" --define "_tmppath ${RPMTEST}/tmp" --define "_topdir ${TOPDIR}" --dbpath="${RPMTEST}/var/lib/rpm/" +@@ -40,6 +53,14 @@ function runroot() + ) + } + ++function runroot_plugins() ++{ ++ (unset RPM_CONFIGDIR RPM_POPTEXEC_PATH; cd ${RPMTEST} && \ ++ MAGIC="/magic/magic" FAKECHROOT_BASE="${RPMTEST}" fakechroot "$@" --define "_buildhost testhost" --define "_topdir /build" --nouserns ++ ) ++} ++ ++ + function runroot_other() + { + (unset RPM_CONFIGDIR RPM_POPTEXEC_PATH; cd ${RPMTEST} && \ diff --git a/tests/rpm2extents.at b/tests/rpm2extents.at new file mode 100644 -index 000000000..18accfc75 +index 000000000..9e1b1559f --- /dev/null +++ b/tests/rpm2extents.at -@@ -0,0 +1,96 @@ +@@ -0,0 +1,110 @@ +# rpm2extents.at: Some very basic checks +# +# Copyright (C) 2022 Manu Bretelle @@ -1010,11 +1527,25 @@ index 000000000..18accfc75 +], +[]) +AT_CLEANUP ++ ++AT_SETUP([rpm2extents install package]) ++AT_KEYWORDS([rpm2extents install package]) ++AT_SKIP_IF([$REFLINK_DISABLED]) ++AT_CHECK([ ++RPMDB_INIT ++ ++runroot_other cat /data/RPMS/hello-2.0-1.x86_64.rpm | runroot_other rpm2extents SHA256 > ${RPMTEST}/tmp/hello-2.0-1.x86_64.rpm 2> /dev/null ++runroot_plugins rpm -i --nodigest --nodeps --undefine=%__transaction_dbus_announce /tmp/hello-2.0-1.x86_64.rpm ++], ++[0], ++[], ++[]) ++AT_CLEANUP diff --git a/tests/rpmtests.at b/tests/rpmtests.at index a1adab8e0..205fed6a3 100644 --- a/tests/rpmtests.at +++ b/tests/rpmtests.at -@@ -21,3 +21,4 @@ m4_include([rpmconfig3.at]) +@@ -21,3 +21,4 @@ m4_include([rpmreplace.at]) m4_include([rpmmacro.at]) m4_include([rpmpython.at]) m4_include([rpmdepmatch.at])