Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plugins: extend API to allow file install #3466

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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, apath, 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 */
Loading