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

RPM with Copy on Write #1470

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ pkginclude_HEADERS += build/rpmfc.h
pkginclude_HEADERS += build/rpmspec.h


bin_PROGRAMS = rpm rpm2cpio rpmbuild rpmdb rpmkeys rpmsign rpmspec
bin_PROGRAMS = rpm rpm2cpio rpmbuild rpmdb rpmkeys rpmsign rpmspec rpm2extents
if WITH_ARCHIVE
bin_PROGRAMS += rpm2archive
endif
Expand Down Expand Up @@ -159,6 +159,10 @@ rpm2cpio_SOURCES = rpm2cpio.c debug.h system.h
rpm2cpio_LDADD = lib/librpm.la rpmio/librpmio.la
rpm2cpio_LDADD += @WITH_POPT_LIB@

rpm2extents_SOURCES = rpm2extents.c debug.h system.h
rpm2extents_LDADD = lib/librpm.la rpmio/librpmio.la
rpm2extents_LDADD += @WITH_POPT_LIB@

rpm2archive_SOURCES = rpm2archive.c debug.h system.h
rpm2archive_LDADD = lib/librpm.la rpmio/librpmio.la
rpm2archive_LDADD += @WITH_POPT_LIB@ @WITH_ARCHIVE_LIB@
Expand Down
2 changes: 2 additions & 0 deletions lib/depends.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ 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")) {
Expand Down
49 changes: 39 additions & 10 deletions lib/fsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#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"
Expand Down Expand Up @@ -835,7 +836,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
rpmpsm psm, char ** failedFile)
{
FD_t payload = rpmtePayload(te);
rpmfi fi = rpmfiNewArchiveReader(payload, files, RPMFI_ITER_READ_ARCHIVE);
rpmfi fi;
rpmfs fs = rpmteGetFileStates(te);
rpmPlugins plugins = rpmtsPlugins(ts);
struct stat sb;
Expand All @@ -850,10 +851,21 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
char *tid = NULL;
const char *suffix;
char *fpath = NULL;
Header h = rpmteHeader(te);
const char *payloadfmt = headerGetString(h, RPMTAG_PAYLOADFORMAT);
int cpio = 1;

if (fi == NULL) {
rc = RPMERR_BAD_MAGIC;
goto exit;
if (payloadfmt && rstreq(payloadfmt, "clon")) {
cpio = 0;
}
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);
}

/* transaction id used for temporary path suffix while installing */
Expand Down Expand Up @@ -893,10 +905,20 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
/* Run fsm file pre hook for all plugins */
rc = rpmpluginsCallFsmFilePre(plugins, fi, fpath,
sb.st_mode, action);
if (rc) {
skip = 1;
} else {
skip = skip || rpmfiFFlags(fi) & RPMFILE_GHOST;
int plugin_contents = 0;
switch (rc) {
case RPMRC_OK:
setFileState(fs, rpmfiFX(fi));
break;
case RPMRC_PLUGIN_CONTENTS:
plugin_contents = 1;
// reduce reads on cpio to this value. Could be zero if
// this is from a hard link.
rc = RPMRC_OK;
break;
default:
skip = 1;
}

if (!skip) {
Expand Down Expand Up @@ -926,8 +948,12 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,

if (S_ISREG(sb.st_mode)) {
if (rc == RPMERR_ENOENT) {
rc = fsmMkfile(fi, fpath, files, psm, nodigest,
&setmeta, &firsthardlink, &firstlinkfile);
if (plugin_contents) {
rc = RPMRC_OK;
} else {
rc = fsmMkfile(fi, fpath, files, psm, nodigest,
&setmeta, &firsthardlink, &firstlinkfile);
}
}
} else if (S_ISDIR(sb.st_mode)) {
if (rc == RPMERR_ENOENT) {
Expand Down Expand Up @@ -1011,7 +1037,10 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
exit:

/* No need to bother with close errors on read */
rpmfiArchiveClose(fi);
if (cpio) {
rpmfiArchiveClose(fi);
}
h = headerFree(h);
rpmfiFree(fi);
Fclose(payload);
free(tid);
Expand Down
40 changes: 40 additions & 0 deletions lib/package.c
Original file line number Diff line number Diff line change
Expand Up @@ -407,5 +407,45 @@ rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
return rc;
}

rpmRC rpmReadPackageRaw(FD_t fd, Header * sigp, Header * hdrp)
{
char *msg = NULL;
hdrblob sigblob = hdrblobCreate();
hdrblob blob = hdrblobCreate();
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);
if (rc != RPMRC_OK)
goto exit;

rc = hdrblobRead(fd, 1, 1, RPMTAG_HEADERIMMUTABLE, blob, &msg);
if (rc != RPMRC_OK)
goto exit;

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);
hdrblobFree(sigblob);
hdrblobFree(blob);
headerFree(sigh);
headerFree(h);
free(msg);

return rc;
}
9 changes: 9 additions & 0 deletions lib/rpmlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,15 @@ rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, char ** msg);
rpmRC rpmReadPackageFile(rpmts ts, FD_t fd,
const char * fn, Header * hdrp);

/** \ingroup header
* Return package signature, header from file handle, no verification.
* @param fd file handle
* @param[out] sigp address of header (or NULL)
* @param[out] hdrp address of header (or NULL)
* @return RPMRC_OK on success
*/
rpmRC rpmReadPackageRaw(FD_t fd, Header * sigp, Header * hdrp);

/** \ingroup rpmtrans
* Install source package.
* @param ts transaction set
Expand Down
21 changes: 18 additions & 3 deletions lib/rpmplugins.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,13 +356,28 @@ rpmRC rpmpluginsCallFsmFilePre(rpmPlugins plugins, rpmfi fi, const char *path,
plugin_fsm_file_pre_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_pre);
if (hookFunc && hookFunc(plugin, fi, path, 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.
*/
malmond77 marked this conversation as resolved.
Show resolved Hide resolved
rc = RPMRC_FAIL;
} else {
/* Plugin will handle content */
rc = RPMRC_PLUGIN_CONTENTS;
}
}
}
}

Expand Down
5 changes: 5 additions & 0 deletions lib/rpmte.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,11 @@ FD_t rpmteSetFd(rpmte te, FD_t fd)
return NULL;
}

FD_t rpmteFd(rpmte te)
{
return (te != NULL ? te->fd : NULL);
}

fnpyKey rpmteKey(rpmte te)
{
return (te != NULL ? te->key : NULL);
Expand Down
2 changes: 2 additions & 0 deletions lib/rpmte.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ const char * rpmteNEVR(rpmte te);
*/
const char * rpmteNEVRA(rpmte te);

FD_t rpmteFd(rpmte te);

/** \ingroup rpmte
* Retrieve key from transaction element.
* @param te transaction element
Expand Down
3 changes: 2 additions & 1 deletion lib/rpmtypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ typedef enum rpmRC_e {
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_NOKEY = 4, /*!< Public key is unavailable. */
RPMRC_PLUGIN_CONTENTS = 5 /*!< fsm_file_pre plugin is handling content */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NAK for adding what effectively is an internal corner case to the highly visible RPMRC enum.
RPMRC was originally supposed to be a package open result, but is (mis)used for all sorts of bad and worse purposes throughout rpm, more likely we should move the plugins to use a separate error code system.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did an attempt at decoupling plugins from rpmRC in #1909 .

} rpmRC;

#ifdef __cplusplus
Expand Down
1 change: 1 addition & 0 deletions macros.in
Original file line number Diff line number Diff line change
Expand Up @@ -1175,6 +1175,7 @@ package or when debugging this package.\

# Transaction plugin macros
%__plugindir %{_libdir}/rpm-plugins
%__transaction_reflink %{__plugindir}/reflink.so
%__transaction_systemd_inhibit %{__plugindir}/systemd_inhibit.so
%__transaction_selinux %{__plugindir}/selinux.so
%__transaction_syslog %{__plugindir}/syslog.so
Expand Down
4 changes: 4 additions & 0 deletions plugins/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ prioreset_la_SOURCES = prioreset.c
prioreset_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
plugins_LTLIBRARIES += prioreset.la

reflink_la_SOURCES = reflink.c
reflink_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
plugins_LTLIBRARIES += reflink.la

syslog_la_SOURCES = syslog.c
syslog_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
plugins_LTLIBRARIES += syslog.la
Expand Down