Skip to content

Commit

Permalink
core: Initial implementation of %posttrans using bwrap+rofiles-fuse
Browse files Browse the repository at this point in the history
In order to make many things work, we need to run scripts.  Short version:
For now, we:

 - Run `%posttrans`
 - Treat most `%post` as the same as `%posttrans`
 - Ignore `%preun` and such since we never uninstall

Most importantly though, we start to build up an "override" list
for script handling.  Currently it's just a blacklist of scripts
we don't need.

Significant work here would be needed to run Lua scripts, so far I've
been able to just skip them.
  • Loading branch information
cgwalters committed Jun 21, 2016
1 parent 3c77c36 commit d8236fe
Show file tree
Hide file tree
Showing 7 changed files with 537 additions and 75 deletions.
16 changes: 16 additions & 0 deletions Makefile-libpriv.am
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ librpmostreepriv_la_SOURCES = \
src/libpriv/rpmostree-refts.c \
src/libpriv/rpmostree-core.c \
src/libpriv/rpmostree-core.h \
src/libpriv/rpmostree-scripts.c \
src/libpriv/rpmostree-scripts.h \
src/libpriv/rpmostree-refsack.h \
src/libpriv/rpmostree-refsack.c \
src/libpriv/rpmostree-cleanup.h \
Expand Down Expand Up @@ -57,3 +59,17 @@ librpmostreepriv_la_LIBADD = \
libglnx.la \
$(CAP_LIBS) \
$(NULL)

gperf_gperf_sources = src/libpriv/rpmostree-script-gperf.gperf
BUILT_SOURCES += $(gperf_gperf_sources:-gperf.gperf=-gperf.c)
CLEANFILES += $(gperf_gperf_sources:-gperf.gperf=-gperf.c)

nodist_librpmostreepriv_la_SOURCES = src/libpriv/rpmostree-script-gperf.c

AM_V_GPERF = $(AM_V_GPERF_$(V))
AM_V_GPERF_ = $(AM_V_GPERF_$(AM_DEFAULT_VERBOSITY))
AM_V_GPERF_0 = @echo " GPERF " $@;

src/%.c: src/%.gperf Makefile
$(AM_V_at)$(MKDIR_P) $(dir $@)
$(AM_V_GPERF)$(GPERF) < $< > $@.tmp && mv $@.tmp $@
6 changes: 6 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ AC_SEARCH_LIBS([rpmsqSetInterruptSafety], [rpmio],
PKG_CHECK_MODULES(PKGDEP_GIO_UNIX, [gio-unix-2.0])
PKG_CHECK_MODULES(PKGDEP_RPMOSTREE, [gio-unix-2.0 >= 2.40.0 json-glib-1.0
ostree-1 >= 2015.1 libgsystem >= 2015.1
libsystemd
rpm libhif librepo
libarchive])
save_LIBS=$LIBS
Expand All @@ -74,6 +75,11 @@ AC_PATH_PROG([XSLTPROC], [xsltproc])

GLIB_TESTS

AC_CHECK_TOOL(GPERF, gperf)
AS_IF([test -z "$GPERF"],
AC_MSG_ERROR([*** gperf not found])
)

m4_ifdef([GOBJECT_INTROSPECTION_CHECK], [
GOBJECT_INTROSPECTION_CHECK([1.34.0])
])
Expand Down
2 changes: 1 addition & 1 deletion src/app/rpmostree-container-builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ rpmostree_container_builtin_assemble (int argc,
goto out;

if (!rpmostree_context_assemble_commit (rocctx->ctx, tmprootfs_dfd, NULL,
NULL, TRUE, &commit, cancellable, error))
NULL, FALSE, &commit, cancellable, error))
goto out;

glnx_shutil_rm_rf_at (rocctx->userroot_dfd, tmprootfs, cancellable, NULL);
Expand Down
139 changes: 65 additions & 74 deletions src/libpriv/rpmostree-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "rpmostree-core.h"
#include "rpmostree-postprocess.h"
#include "rpmostree-rpm-util.h"
#include "rpmostree-scripts.h"
#include "rpmostree-unpacker.h"
#include "rpmostree-output.h"

Expand Down Expand Up @@ -1897,100 +1898,47 @@ ts_callback (const void * h,
return NULL;
}

typedef struct {
const char *desc;
rpmsenseFlags sense;
rpmTagVal tag;
rpmTagVal progtag;
rpmTagVal flagtag;
} KnownRpmScriptKind;

static const KnownRpmScriptKind known_scripts[] = {
{ "%prein", 0,
RPMTAG_PREIN, RPMTAG_PREINPROG, RPMTAG_PREINFLAGS },
{ "%preun", 0,
RPMTAG_PREUN, RPMTAG_PREUNPROG, RPMTAG_PREUNFLAGS },
{ "%post", 0,
RPMTAG_POSTIN, RPMTAG_POSTINPROG, RPMTAG_POSTINFLAGS },
{ "%postun", 0,
RPMTAG_POSTUN, RPMTAG_POSTUNPROG, RPMTAG_POSTUNFLAGS },
{ "%pretrans", 0,
RPMTAG_PRETRANS, RPMTAG_PRETRANSPROG, RPMTAG_PRETRANSFLAGS },
{ "%posttrans", 0,
RPMTAG_POSTTRANS, RPMTAG_POSTTRANSPROG, RPMTAG_POSTTRANSFLAGS },
{ "%triggerprein", RPMSENSE_TRIGGERPREIN,
RPMTAG_TRIGGERPREIN, 0, 0 },
{ "%triggerun", RPMSENSE_TRIGGERUN,
RPMTAG_TRIGGERUN, 0, 0 },
{ "%triggerin", RPMSENSE_TRIGGERIN,
RPMTAG_TRIGGERIN, 0, 0 },
{ "%triggerpostun", RPMSENSE_TRIGGERPOSTUN,
RPMTAG_TRIGGERPOSTUN, 0, 0 },
{ "%verify", 0,
RPMTAG_VERIFYSCRIPT, RPMTAG_VERIFYSCRIPTPROG, RPMTAG_VERIFYSCRIPTFLAGS},
};

/*
* We aren't yet running %posts, so let's not lie and say we support
* it.
*/
static gboolean
check_package_is_post_posts (Header hdr,
const char *name,
GError **error)
static Header
get_header_for_package (int tmp_metadata_dfd,
HifPackage *pkg,
GError **error)
{
gboolean ret = FALSE;
guint i;

for (i = 0; i < G_N_ELEMENTS (known_scripts); i++)
{
rpmTagVal tagval = known_scripts[i].tag;
rpmTagVal progtagval = known_scripts[i].progtag;
Header hdr = NULL;
glnx_fd_close int metadata_fd = -1;

if (headerIsEntry (hdr, tagval) || headerIsEntry (hdr, progtagval))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Package '%s' has (currently) unsupported script of type '%s'",
name, known_scripts[i].desc);
goto out;
}
if ((metadata_fd = openat (tmp_metadata_dfd, hif_package_get_nevra (pkg), O_RDONLY | O_CLOEXEC)) < 0)
{
glnx_set_error_from_errno (error);
return NULL;
}

ret = TRUE;
out:
return ret;
if (!rpmostree_unpacker_read_metainfo (metadata_fd, &hdr, NULL, NULL, error))
return NULL;

return hdr;
}

static gboolean
add_to_transaction (rpmts ts,
HifPackage *pkg,
int tmp_metadata_dfd,
gboolean noscripts,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
int r;
Header hdr = NULL;
glnx_fd_close int metadata_fd = -1;

if ((metadata_fd = openat (tmp_metadata_dfd, hif_package_get_nevra (pkg), O_RDONLY | O_CLOEXEC)) < 0)
{
glnx_set_error_from_errno (error);
goto out;
}
int r;

if (!rpmostree_unpacker_read_metainfo (metadata_fd, &hdr, NULL, NULL, error))
hdr = get_header_for_package (tmp_metadata_dfd, pkg, error);
if (!hdr)
goto out;

/* TODO uncomment once upgrade understands this or we implement post
handling better */
#if 0
if (!noscripts)
{
if (!check_package_is_post_posts (hdr, hif_package_get_nevra (pkg), error))
if (!rpmostree_script_txn_validate (pkg, hdr, cancellable, error))
goto out;
}
#endif

r = rpmtsAddInstallElement (ts, hdr, (char*)hif_package_get_nevra (pkg), TRUE, NULL);
if (r != 0)
Expand All @@ -2010,6 +1958,31 @@ add_to_transaction (rpmts ts,
return ret;
}

static gboolean
run_posttrans_sync (int tmp_metadata_dfd,
int rootfs_dfd,
HifPackage *pkg,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
Header hdr;

hdr = get_header_for_package (tmp_metadata_dfd, pkg, error);
if (!hdr)
goto out;

if (!rpmostree_posttrans_run_sync (pkg, hdr, rootfs_dfd,
cancellable, error))
goto out;

ret = TRUE;
out:
if (hdr)
headerFree (hdr);
return ret;
}

/* FIXME: This is a copy of ot_admin_checksum_version */
static char *
checksum_version (GVariant *checksum)
Expand Down Expand Up @@ -2129,7 +2102,8 @@ rpmostree_context_assemble_commit (RpmOstreeContext *self,
cancellable, error))
goto out;

if (!add_to_transaction (ordering_ts, pkg, tmp_metadata_dfd, noscripts, error))
if (!add_to_transaction (ordering_ts, pkg, tmp_metadata_dfd, noscripts,
cancellable, error))
goto out;
}

Expand Down Expand Up @@ -2212,6 +2186,21 @@ rpmostree_context_assemble_commit (RpmOstreeContext *self,
}

rpmostree_output_task_end ("done");

if (!noscripts)
{
for (i = 0; i < n_rpmts_elements; i++)
{
rpmte te = rpmtsElement (ordering_ts, i);
const char *tekey = rpmteKey (te);
HifPackage *pkg = g_hash_table_lookup (nevra_to_pkg, tekey);

if (!run_posttrans_sync (tmp_metadata_dfd, tmprootfs_dfd, pkg,
cancellable, error))
goto out;
}
}

rpmostree_output_percent_progress_end ();

g_clear_pointer (&ordering_ts, rpmtsFree);
Expand Down Expand Up @@ -2254,7 +2243,9 @@ rpmostree_context_assemble_commit (RpmOstreeContext *self,
{
HifPackage *pkg = k;

if (!add_to_transaction (rpmdb_ts, pkg, tmp_metadata_dfd, noscripts, error))
/* Set noscripts since we already validated them above */
if (!add_to_transaction (rpmdb_ts, pkg, tmp_metadata_dfd, TRUE,
cancellable, error))
goto out;
}
}
Expand Down
24 changes: 24 additions & 0 deletions src/libpriv/rpmostree-script-gperf.gperf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
%{
#include "config.h"
#include "rpmostree-scripts.h"
%}
struct RpmOstreePackageScriptHandler;
%language=ANSI-C
%define slot-name package_script
%define hash-function-name rpmostree_script_gperf_hash
%define lookup-function-name rpmostree_script_gperf_lookup
%readonly-tables
%omit-struct-type
%struct-type
%includes
%%
glibc.prein, RPMOSTREE_SCRIPT_ACTION_IGNORE
coreutils.prein, RPMOSTREE_SCRIPT_ACTION_IGNORE /* workaround for old bug? */
ca-certificates.prein, RPMOSTREE_SCRIPT_ACTION_IGNORE /* Looks like legacy... */
filesystem.pretrans, RPMOSTREE_SCRIPT_ACTION_IGNORE
libgcc.post, RPMOSTREE_SCRIPT_ACTION_IGNORE
setup.post, RPMOSTREE_SCRIPT_ACTION_IGNORE
fedora-release.post, RPMOSTREE_SCRIPT_ACTION_IGNORE
fedora-release.posttrans, RPMOSTREE_SCRIPT_ACTION_IGNORE
bash.post, RPMOSTREE_SCRIPT_ACTION_TODO_SHELL_POSTTRANS
glibc-common.post, RPMOSTREE_SCRIPT_ACTION_TODO_SHELL_POSTTRANS

0 comments on commit d8236fe

Please sign in to comment.