mirror of
https://github.com/ostreedev/ostree.git
synced 2025-01-26 14:04:12 +03:00
main: Also automatically remount rw /sysroot for ostree pull
etc.
See https://github.com/coreos/fedora-coreos-tracker/issues/343 When we added the read-only sysroot support it broke using "raw" `ostree pull` and `ostree refs --create` and all of the core repo CLIs that just operate on a repo and not a sysroot. Fixing this is a bit ugly as it "layer crosses" things even more. Extract a helper function that works in both cases.
This commit is contained in:
parent
2d901957b8
commit
6a27dff941
@ -28,6 +28,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/mount.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
#include "ot-main.h"
|
||||
#include "ostree.h"
|
||||
@ -100,6 +102,49 @@ ostree_usage (OstreeCommand *commands,
|
||||
return (is_error ? 1 : 0);
|
||||
}
|
||||
|
||||
/* If we're running as root, booted into an OSTree system and have a read-only
|
||||
* /sysroot, then assume we may need write access. Create a new mount namespace
|
||||
* if so, and return *out_ns = TRUE. Otherwise, *out_ns = FALSE.
|
||||
*/
|
||||
static gboolean
|
||||
maybe_setup_mount_namespace (gboolean *out_ns,
|
||||
GError **error)
|
||||
{
|
||||
*out_ns = FALSE;
|
||||
|
||||
/* If we're not root, then we almost certainly can't be remounting anything */
|
||||
if (getuid () != 0)
|
||||
return TRUE;
|
||||
|
||||
/* If the system isn't booted via libostree, also nothing to do */
|
||||
if (!glnx_fstatat_allow_noent (AT_FDCWD, "/run/ostree-booted", NULL, 0, error))
|
||||
return FALSE;
|
||||
if (errno == ENOENT)
|
||||
return TRUE;
|
||||
|
||||
glnx_autofd int sysroot_subdir_fd = glnx_opendirat_with_errno (AT_FDCWD, "/sysroot", TRUE);
|
||||
if (sysroot_subdir_fd < 0)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
return glnx_throw_errno_prefix (error, "opendirat");
|
||||
/* No /sysroot - nothing to do */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
struct statvfs stvfs;
|
||||
if (fstatvfs (sysroot_subdir_fd, &stvfs) < 0)
|
||||
return glnx_throw_errno_prefix (error, "fstatvfs");
|
||||
if (stvfs.f_flag & ST_RDONLY)
|
||||
{
|
||||
if (unshare (CLONE_NEWNS) < 0)
|
||||
return glnx_throw_errno_prefix (error, "preparing writable sysroot: unshare (CLONE_NEWNS)");
|
||||
|
||||
*out_ns = TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
message_handler (const gchar *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
@ -220,6 +265,19 @@ parse_repo_option (GOptionContext *context,
|
||||
{
|
||||
g_autoptr(OstreeRepo) repo = NULL;
|
||||
|
||||
/* This is a bit of a brutal hack; we set up a mount
|
||||
* namespace if it appears that we may need it. It'd
|
||||
* be better to do this more precisely in the future.
|
||||
*/
|
||||
gboolean setup_ns = FALSE;
|
||||
if (!maybe_setup_mount_namespace (&setup_ns, error))
|
||||
return FALSE;
|
||||
if (setup_ns)
|
||||
{
|
||||
if (mount ("/sysroot", "/sysroot", NULL, MS_REMOUNT | MS_SILENT, NULL) < 0)
|
||||
return glnx_null_throw_errno_prefix (error, "Remounting /sysroot read-write");
|
||||
}
|
||||
|
||||
if (repo_path == NULL)
|
||||
{
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
@ -452,27 +510,11 @@ ostree_admin_option_context_parse (GOptionContext *context,
|
||||
*/
|
||||
if (ostree_sysroot_is_booted (sysroot))
|
||||
{
|
||||
int sysroot_fd = ostree_sysroot_get_fd (sysroot);
|
||||
g_assert_cmpint (sysroot_fd, !=, -1);
|
||||
|
||||
glnx_autofd int sysroot_subdir_fd = glnx_opendirat_with_errno (sysroot_fd, "sysroot", TRUE);
|
||||
if (sysroot_subdir_fd < 0)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
return glnx_throw_errno_prefix (error, "opendirat");
|
||||
}
|
||||
else if (getuid () == 0)
|
||||
{
|
||||
struct statvfs stvfs;
|
||||
if (fstatvfs (sysroot_subdir_fd, &stvfs) < 0)
|
||||
return glnx_throw_errno_prefix (error, "fstatvfs");
|
||||
if (stvfs.f_flag & ST_RDONLY)
|
||||
{
|
||||
if (unshare (CLONE_NEWNS) < 0)
|
||||
return glnx_throw_errno_prefix (error, "preparing writable sysroot: unshare (CLONE_NEWNS)");
|
||||
ostree_sysroot_set_mount_namespace_in_use (sysroot);
|
||||
}
|
||||
}
|
||||
gboolean setup_ns = FALSE;
|
||||
if (!maybe_setup_mount_namespace (&setup_ns, error))
|
||||
return FALSE;
|
||||
if (setup_ns)
|
||||
ostree_sysroot_set_mount_namespace_in_use (sysroot);
|
||||
}
|
||||
|
||||
/* Released when sysroot is finalized, or on process exit */
|
||||
|
Loading…
x
Reference in New Issue
Block a user