Skip to content

Commit

Permalink
plugins: extend API to allow file install
Browse files Browse the repository at this point in the history
Extend the plugin API with two new methods:
- plugin_fsm_file_install_func
- plugin_fsm_file_archive_reader_func

The first one allows a plugin to take care of the file install,
the second instead allows a plugin to handle the archive read.
  • Loading branch information
teknoraver committed Nov 22, 2024
1 parent fe9a914 commit 4502c2d
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 15 deletions.
8 changes: 8 additions & 0 deletions include/rpm/rpmplugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ 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, int dirfd,
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 {
Expand All @@ -80,6 +86,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
Expand Down
11 changes: 6 additions & 5 deletions include/rpm/rpmtypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,12 @@ typedef struct FD_s * FD_t;
* Package read return codes.
*/
typedef enum rpmRC_e {
RPMRC_OK = 0, /*!< Generic success code */
RPMRC_NOTFOUND = 1, /*!< Generic not found code. */
RPMRC_FAIL = 2, /*!< Generic failure code. */
RPMRC_NOTTRUSTED = 3, /*!< Signature is OK, but key is not trusted. */
RPMRC_NOKEY = 4 /*!< Public key is unavailable. */
RPMRC_OK = 0, /*!< Generic success code */
RPMRC_NOTFOUND = 1, /*!< Generic not found code. */
RPMRC_FAIL = 2, /*!< Generic failure code. */
RPMRC_NOTTRUSTED = 3, /*!< Signature is OK, but key is not trusted. */
RPMRC_NOKEY = 4, /*!< Public key is unavailable. */
RPMRC_PLUGIN_CONTENTS = 5, /*!< fsm_file_pre plugin is handling content */
} rpmRC;

#ifdef __cplusplus
Expand Down
37 changes: 30 additions & 7 deletions lib/fsm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
struct filedata_s *fdata = (struct filedata_s *)xcalloc(fc, sizeof(*fdata));
struct filedata_s *firstlink = NULL;
struct diriter_s di = { -1, -1 };
rpmRC plugin_rc;

/* transaction id used for temporary path suffix while installing */
rasprintf(&tid, ";%08x", (unsigned)rpmtsGetTid(ts));
Expand Down Expand Up @@ -926,12 +927,27 @@ 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 (fi == NULL) {
rc = RPMERR_BAD_MAGIC;
goto exit;
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 = fsmIter(payload, files,
payload ? RPMFI_ITER_READ_ARCHIVE : RPMFI_ITER_FWD, &di);
if (fi == NULL) {
rc = RPMERR_BAD_MAGIC;
goto exit;
}
rc = RPMRC_OK;
break;
default:
rc = RPMRC_FAIL;
goto exit;
}

/* Process the payload */
Expand Down Expand Up @@ -989,7 +1005,14 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
if (fp->action == FA_TOUCH)
goto setmeta;

if (S_ISREG(fp->sb.st_mode)) {
plugin_rc = rpmpluginsCallFsmFileInstall(plugins, fi, di.dirfd, 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;
/* A plugin could handle hardlink differently, set metadata to be safe. */
fp->setmeta = 1;
} else if (S_ISREG(fp->sb.st_mode)) {
if (rc == RPMERR_ENOENT) {
rc = fsmMkfile(di.dirfd, fi, fp, files, psm, nodigest,
&firstlink, &firstlinkfile, &di.firstdir,
Expand Down
85 changes: 82 additions & 3 deletions lib/rpmplugins.cc
Original file line number Diff line number Diff line change
Expand Up @@ -352,13 +352,28 @@ rpmRC rpmpluginsCallFsmFilePre(rpmPlugins plugins, rpmfi fi, const char *path,
{
plugin_fsm_file_pre_func hookFunc;
rpmRC rc = RPMRC_OK;
rpmRC hook_rc;
char *apath = abspath(fi, path);

for (auto & plugin : plugins->plugins) {
RPMPLUGINS_SET_HOOK_FUNC(fsm_file_pre);
if (hookFunc && hookFunc(plugin, fi, apath, file_mode, op) == RPMRC_FAIL) {
rpmlog(RPMLOG_ERR, "Plugin %s: hook fsm_file_pre failed\n", plugin->name);
rc = RPMRC_FAIL;
if (hookFunc) {
hook_rc = hookFunc(plugin, fi, path, file_mode, op);
if (hook_rc == RPMRC_FAIL) {
rpmlog(RPMLOG_ERR, "Plugin %s: hook fsm_file_pre 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;
}
}
}
}
free(apath);
Expand Down Expand Up @@ -403,3 +418,67 @@ rpmRC rpmpluginsCallFsmFilePrepare(rpmPlugins plugins, rpmfi fi,

return rc;
}

rpmRC rpmpluginsCallFsmFileInstall(rpmPlugins plugins, rpmfi fi, int dirfd,
const char *path, mode_t file_mode, rpmFsmOp op)
{
plugin_fsm_file_install_func hookFunc;
rpmRC rc = RPMRC_OK;
rpmRC hook_rc;

for (auto & plugin : plugins->plugins) {
RPMPLUGINS_SET_HOOK_FUNC(fsm_file_install);
if (hookFunc) {
hook_rc = hookFunc(plugin, fi, dirfd, 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;
rpmRC rc = RPMRC_OK;
rpmRC hook_rc;

for (auto & plugin : plugins->plugins) {
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;
}
19 changes: 19 additions & 0 deletions lib/rpmplugins.hh
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,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 dirfd file object directory file descriptor
* @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,
int dirfd, const char *path,
mode_t file_mode, rpmFsmOp op);

RPM_GNUC_INTERNAL
rpmRC rpmpluginsCallFsmFileArchiveReader(rpmPlugins plugins, FD_t payload,
rpmfiles files, rpmfi *fi);

#endif /* _PLUGINS_H */

0 comments on commit 4502c2d

Please sign in to comment.