lib/repo: Immediately error creating bare-user repo on tmpfs

And in general, if for some reason we can't write `user.` xattrs, provide an
error immediately rather than doing it during a later pull. This way the failure
cause is a lot more obvious.

Related: https://github.com/ostreedev/ostree/issues/991

Closes: #993
Approved by: jlebon
This commit is contained in:
Colin Walters 2017-07-05 10:50:34 -04:00 committed by Atomic Bot
parent 3234295324
commit 23b93a3eb6
4 changed files with 61 additions and 24 deletions

View File

@ -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

View File

@ -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,

View File

@ -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;

View File

@ -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"