diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 185ab82f..baeef3f9 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -82,31 +82,21 @@ create_file_metadata (guint32 uid, return ret_metadata; } -static gboolean -write_file_metadata_to_xattr (int fd, - guint32 uid, - guint32 gid, - guint32 mode, - GVariant *xattrs, - GError **error) +gboolean +_ostree_write_bareuser_metadata (int fd, + guint32 uid, + guint32 gid, + guint32 mode, + GVariant *xattrs, + GError **error) { - g_autoptr(GVariant) filemeta = NULL; - int res; + g_autoptr(GVariant) filemeta = create_file_metadata (uid, gid, mode, xattrs); - filemeta = create_file_metadata (uid, gid, mode, xattrs); - - do - res = fsetxattr (fd, "user.ostreemeta", - (char*)g_variant_get_data (filemeta), - g_variant_get_size (filemeta), - 0); - while (G_UNLIKELY (res == -1 && errno == EINTR)); - if (G_UNLIKELY (res == -1)) - { - glnx_set_error_from_errno (error); - g_prefix_error (error, "Unable to set xattr: "); - return FALSE; - } + if (TEMP_FAILURE_RETRY (fsetxattr (fd, "user.ostreemeta", + (char*)g_variant_get_data (filemeta), + g_variant_get_size (filemeta), + 0)) != 0) + return glnx_throw_errno_prefix (error, "fsetxattr(user.ostreemeta)"); return TRUE; } @@ -248,7 +238,7 @@ commit_loose_regfile_object (OstreeRepo *self, } else if (self->mode == OSTREE_REPO_MODE_BARE_USER) { - if (!write_file_metadata_to_xattr (tmpf->fd, uid, gid, mode, xattrs, error)) + if (!_ostree_write_bareuser_metadata (tmpf->fd, uid, gid, mode, xattrs, error)) return FALSE; /* Note that previously this path added `| 0755` which made every diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index 9e00cf40..407e2cb3 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -216,6 +216,14 @@ _ostree_repo_has_loose_object (OstreeRepo *self, GCancellable *cancellable, GError **error); +gboolean +_ostree_write_bareuser_metadata (int fd, + guint32 uid, + guint32 gid, + guint32 mode, + GVariant *xattrs, + GError **error); + gboolean _ostree_repo_write_directory_meta (OstreeRepo *self, GFileInfo *file_info, diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index e29b8fca..815d2d65 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -1752,6 +1752,21 @@ ostree_repo_create (OstreeRepo *self, } } + /* Test that the fs supports user xattrs now, so we get an error early rather + * than during an object write later. + */ + if (mode == OSTREE_REPO_MODE_BARE_USER) + { + g_auto(GLnxTmpfile) tmpf = { 0, }; + + if (!glnx_open_tmpfile_linkable_at (dfd, ".", O_RDWR|O_CLOEXEC, &tmpf, error)) + return FALSE; + if (fchmod (tmpf.fd, 0600) < 0) + return glnx_throw_errno_prefix (error, "fchmod"); + if (!_ostree_write_bareuser_metadata (tmpf.fd, 0, 0, 644, NULL, error)) + return FALSE; + } + if (!ostree_repo_open (self, cancellable, error)) return FALSE; diff --git a/tests/installed/itest-bareuser-nouserxattrs.sh b/tests/installed/itest-bareuser-nouserxattrs.sh new file mode 100755 index 00000000..06d3e109 --- /dev/null +++ b/tests/installed/itest-bareuser-nouserxattrs.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Test that initializing a bare-user repo on tmpfs fails +# Maybe at some point this will be fixed in the kernel +# but I doubt it'll be soon +# https://www.spinics.net/lists/linux-mm/msg109775.html + +set -xeuo pipefail + +dn=$(dirname $0) +. ${dn}/libinsttest.sh + +test_tmpdir=$(prepare_tmpdir) +trap _tmpdir_cleanup EXIT +cd ${test_tmpdir} + +mkdir mnt +mount -t tmpfs tmpfs mnt +if ostree --repo=mnt/repo init --mode=bare-user 2>err.txt; then + umount mnt + assert_not_reached "bare-user on tmpfs worked?" +fi +umount mnt +assert_file_has_content err.txt "Operation not supported"