lib: Move bareuseronly verification into commit/core
Conceptually `ostree-repo-pull.c` should be be written using just public APIs; we theoretically support building without HTTP for people who just want to use the object store portion and do their own fetching. We have some nontrivial behaviors in the pull layer though; one of those is the "bareuseronly" verification. Make a new internal API that accepts flags, move it into `commit.c`. This is prep for further work in changing object import to support reflinks. Closes: #1193 Approved by: jlebon
This commit is contained in:
1 parent
d4c7093e37
commit
160864d557
9 files changed
+316
-288
No files matched your search
+4
-204
@@ -3367,114 +3367,6 @@ ostree_repo_delete_object (OstreeRepo *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
copy_detached_metadata (OstreeRepo *self,
|
||||
OstreeRepo *source,
|
||||
const char *checksum,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GVariant) detached_meta = NULL;
|
||||
if (!ostree_repo_read_commit_detached_metadata (source,
|
||||
checksum, &detached_meta,
|
||||
cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
if (detached_meta)
|
||||
{
|
||||
if (!ostree_repo_write_commit_detached_metadata (self,
|
||||
checksum, detached_meta,
|
||||
cancellable, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Special case between bare-user and bare-user-only,
|
||||
* mostly for https://github.com/flatpak/flatpak/issues/845
|
||||
* see below for any more comments.
|
||||
*/
|
||||
static gboolean
|
||||
import_is_bareuser_only_conversion (OstreeRepo *src_repo,
|
||||
OstreeRepo *dest_repo,
|
||||
OstreeObjectType objtype)
|
||||
{
|
||||
return src_repo->mode == OSTREE_REPO_MODE_BARE_USER
|
||||
&& dest_repo->mode == OSTREE_REPO_MODE_BARE_USER_ONLY
|
||||
&& objtype == OSTREE_OBJECT_TYPE_FILE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
import_one_object_link (OstreeRepo *self,
|
||||
OstreeRepo *source,
|
||||
const char *checksum,
|
||||
OstreeObjectType objtype,
|
||||
gboolean *out_was_supported,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
const char *errprefix = glnx_strjoina ("Importing ", checksum, ".",
|
||||
ostree_object_type_to_string (objtype));
|
||||
GLNX_AUTO_PREFIX_ERROR (errprefix, error);
|
||||
char loose_path_buf[_OSTREE_LOOSE_PATH_MAX];
|
||||
_ostree_loose_path (loose_path_buf, checksum, objtype, self->mode);
|
||||
|
||||
/* Hardlinking between bare-user → bare-user-only is only possible for regular
|
||||
* files, *not* symlinks, which in bare-user are stored as regular files. At
|
||||
* this point we need to parse the file to see the difference.
|
||||
*/
|
||||
if (import_is_bareuser_only_conversion (source, self, objtype))
|
||||
{
|
||||
struct stat stbuf;
|
||||
|
||||
if (!_ostree_repo_load_file_bare (source, checksum, NULL, &stbuf,
|
||||
NULL, NULL, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
if (S_ISREG (stbuf.st_mode))
|
||||
{
|
||||
/* This is OK, we'll drop through and try a hardlink */
|
||||
}
|
||||
else if (S_ISLNK (stbuf.st_mode))
|
||||
{
|
||||
/* NOTE early return */
|
||||
*out_was_supported = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
if (!_ostree_repo_ensure_loose_objdir_at (self->objects_dir_fd, loose_path_buf, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
*out_was_supported = TRUE;
|
||||
if (linkat (source->objects_dir_fd, loose_path_buf, self->objects_dir_fd, loose_path_buf, 0) != 0)
|
||||
{
|
||||
if (errno == EEXIST)
|
||||
return TRUE;
|
||||
else if (errno == EMLINK || errno == EXDEV || errno == EPERM)
|
||||
{
|
||||
/* EMLINK, EXDEV and EPERM shouldn't be fatal; we just can't do the
|
||||
* optimization of hardlinking instead of copying.
|
||||
*/
|
||||
*out_was_supported = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return glnx_throw_errno_prefix (error, "linkat");
|
||||
}
|
||||
|
||||
if (objtype == OSTREE_OBJECT_TYPE_COMMIT)
|
||||
{
|
||||
if (!copy_detached_metadata (self, source, checksum, cancellable, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_repo_import_object_from:
|
||||
* @self: Destination repo
|
||||
@@ -3504,28 +3396,6 @@ ostree_repo_import_object_from (OstreeRepo *self,
|
||||
checksum, TRUE, cancellable, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
import_via_hardlink_is_possible (OstreeRepo *src_repo,
|
||||
OstreeRepo *dest_repo,
|
||||
OstreeObjectType objtype)
|
||||
{
|
||||
/* We need the ability to make hardlinks */
|
||||
if (src_repo->owner_uid != dest_repo->owner_uid)
|
||||
return FALSE;
|
||||
/* Equal modes are always compatible */
|
||||
if (src_repo->mode == dest_repo->mode)
|
||||
return TRUE;
|
||||
/* Metadata is identical between all modes */
|
||||
if (OSTREE_OBJECT_TYPE_IS_META (objtype))
|
||||
return TRUE;
|
||||
/* And now a special case between bare-user and bare-user-only,
|
||||
* mostly for https://github.com/flatpak/flatpak/issues/845
|
||||
*/
|
||||
if (import_is_bareuser_only_conversion (src_repo, dest_repo, objtype))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_repo_import_object_from_with_trust:
|
||||
* @self: Destination repo
|
||||
@@ -3552,82 +3422,12 @@ ostree_repo_import_object_from_with_trust (OstreeRepo *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
/* We try to import via hardlink. If the remote is explicitly not trusted
|
||||
* (i.e.) their checksums may be incorrect, we skip that. Also, we require the
|
||||
* repository modes to match, as well as the owner uid (since we need to be
|
||||
* able to make hardlinks).
|
||||
*/
|
||||
if (trusted && import_via_hardlink_is_possible (source, self, objtype))
|
||||
{
|
||||
gboolean hardlink_was_supported = FALSE;
|
||||
|
||||
if (!import_one_object_link (self, source, checksum, objtype,
|
||||
&hardlink_was_supported,
|
||||
cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
/* If we hardlinked, we're done! */
|
||||
if (hardlink_was_supported)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* The copy path */
|
||||
|
||||
/* First, do we have the object already? */
|
||||
gboolean has_object;
|
||||
if (!ostree_repo_has_object (self, objtype, checksum, &has_object,
|
||||
cancellable, error))
|
||||
return FALSE;
|
||||
/* If we have it, we're done */
|
||||
if (has_object)
|
||||
return TRUE;
|
||||
|
||||
if (OSTREE_OBJECT_TYPE_IS_META (objtype))
|
||||
{
|
||||
/* Metadata object */
|
||||
g_autoptr(GVariant) variant = NULL;
|
||||
|
||||
if (objtype == OSTREE_OBJECT_TYPE_COMMIT)
|
||||
{
|
||||
/* FIXME - cleanup detached metadata if copy below fails */
|
||||
if (!copy_detached_metadata (self, source, checksum, cancellable, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!ostree_repo_load_variant (source, objtype, checksum,
|
||||
&variant, error))
|
||||
return FALSE;
|
||||
|
||||
g_autofree guchar *real_csum = NULL;
|
||||
if (!ostree_repo_write_metadata (self, objtype,
|
||||
checksum, variant,
|
||||
trusted ? NULL : &real_csum,
|
||||
cancellable, error))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Content object */
|
||||
guint64 length;
|
||||
g_autoptr(GInputStream) object_stream = NULL;
|
||||
|
||||
if (!ostree_repo_load_object_stream (source, objtype, checksum,
|
||||
&object_stream, &length,
|
||||
cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
g_autofree guchar *real_csum = NULL;
|
||||
if (!ostree_repo_write_content (self, checksum,
|
||||
object_stream, length,
|
||||
trusted ? NULL : &real_csum,
|
||||
cancellable, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
/* This just wraps a currently internal API, may make it public later */
|
||||
OstreeRepoImportFlags flags = trusted ? _OSTREE_REPO_IMPORT_FLAGS_TRUSTED : 0;
|
||||
return _ostree_repo_import_object (self, source, objtype, checksum,
|
||||
flags, cancellable, error);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ostree_repo_query_object_storage_size:
|
||||
* @self: Repo
|
||||
|
||||
Reference in new issue
Block a user