mirror of
https://github.com/ostreedev/ostree.git
synced 2024-12-22 17:35:55 +03:00
libarchive: Make autocreate_parents imply autocreating root dir
Some Docker layers are just metadata in the `layer.json`. If one is mapping Docker layers to OSTree commits, one needs to create a dummy root directory, because OSTree doesn't support metadata-only commits. Let's just push that logic down here because it's easier than special casing it in higher levels.
This commit is contained in:
parent
11b3050fd7
commit
30c5fb1a51
@ -292,6 +292,23 @@ write_libarchive_entry_to_mtree (OstreeRepo *self,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
create_empty_dir_with_uidgid (OstreeRepo *self,
|
||||||
|
guint32 uid,
|
||||||
|
guint32 gid,
|
||||||
|
guint8 **out_csum,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_autoptr(GFileInfo) tmp_dir_info = g_file_info_new ();
|
||||||
|
|
||||||
|
g_file_info_set_attribute_uint32 (tmp_dir_info, "unix::uid", uid);
|
||||||
|
g_file_info_set_attribute_uint32 (tmp_dir_info, "unix::gid", gid);
|
||||||
|
g_file_info_set_attribute_uint32 (tmp_dir_info, "unix::mode", 0755 | S_IFDIR);
|
||||||
|
|
||||||
|
return _ostree_repo_write_directory_meta (self, tmp_dir_info, NULL, out_csum, cancellable, error);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ostree_repo_import_archive_to_mtree:
|
* ostree_repo_import_archive_to_mtree:
|
||||||
* @self: An #OstreeRepo
|
* @self: An #OstreeRepo
|
||||||
@ -320,6 +337,7 @@ ostree_repo_import_archive_to_mtree (OstreeRepo *self,
|
|||||||
g_autofree guchar *tmp_csum = NULL;
|
g_autofree guchar *tmp_csum = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
r = archive_read_next_header (a, &entry);
|
r = archive_read_next_header (a, &entry);
|
||||||
@ -336,13 +354,13 @@ ostree_repo_import_archive_to_mtree (OstreeRepo *self,
|
|||||||
*/
|
*/
|
||||||
if (opts->autocreate_parents && !tmp_csum)
|
if (opts->autocreate_parents && !tmp_csum)
|
||||||
{
|
{
|
||||||
g_autoptr(GFileInfo) tmp_dir_info = g_file_info_new ();
|
/* Here, we auto-pick the first uid/gid we find in the
|
||||||
|
* archive. Realistically this is probably always going to
|
||||||
g_file_info_set_attribute_uint32 (tmp_dir_info, "unix::uid", archive_entry_uid (entry));
|
* be root, but eh, at least we try to match.
|
||||||
g_file_info_set_attribute_uint32 (tmp_dir_info, "unix::gid", archive_entry_gid (entry));
|
*/
|
||||||
g_file_info_set_attribute_uint32 (tmp_dir_info, "unix::mode", 0755 | S_IFDIR);
|
if (!create_empty_dir_with_uidgid (self, archive_entry_uid (entry),
|
||||||
|
archive_entry_gid (entry),
|
||||||
if (!_ostree_repo_write_directory_meta (self, tmp_dir_info, NULL, &tmp_csum, cancellable, error))
|
&tmp_csum, cancellable, error))
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,6 +370,26 @@ ostree_repo_import_archive_to_mtree (OstreeRepo *self,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we didn't import anything at all, and autocreation of parents
|
||||||
|
* is enabled, automatically create a root directory. This is
|
||||||
|
* useful primarily when importing Docker image layers, which can
|
||||||
|
* just be metadata.
|
||||||
|
*/
|
||||||
|
if (!ostree_mutable_tree_get_metadata_checksum (mtree) && opts->autocreate_parents)
|
||||||
|
{
|
||||||
|
char tmp_checksum[65];
|
||||||
|
|
||||||
|
if (!tmp_csum)
|
||||||
|
{
|
||||||
|
/* We didn't have any archive entries to match, so pick uid 0, gid 0. */
|
||||||
|
if (!create_empty_dir_with_uidgid (self, 0, 0, &tmp_csum, cancellable, error))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ostree_checksum_inplace_from_bytes (tmp_csum, tmp_checksum);
|
||||||
|
ostree_mutable_tree_set_metadata_checksum (mtree, tmp_checksum);
|
||||||
|
}
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
OstreeRepo *repo;
|
OstreeRepo *repo;
|
||||||
int fd;
|
int fd;
|
||||||
|
int fd_empty;
|
||||||
char *tmpd;
|
char *tmpd;
|
||||||
} TestData;
|
} TestData;
|
||||||
|
|
||||||
@ -88,6 +89,19 @@ test_data_init (TestData *td)
|
|||||||
g_assert_cmpint (ARCHIVE_OK, ==, archive_write_close (a));
|
g_assert_cmpint (ARCHIVE_OK, ==, archive_write_close (a));
|
||||||
g_assert_cmpint (ARCHIVE_OK, ==, archive_write_free (a));
|
g_assert_cmpint (ARCHIVE_OK, ==, archive_write_free (a));
|
||||||
|
|
||||||
|
td->fd_empty = openat (AT_FDCWD, "empty.tar.gz", O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, 0644);
|
||||||
|
g_assert (td->fd_empty >= 0);
|
||||||
|
(void) unlink ("empty.tar.gz");
|
||||||
|
|
||||||
|
a = archive_write_new ();
|
||||||
|
g_assert (a);
|
||||||
|
|
||||||
|
g_assert_cmpint (0, ==, archive_write_set_format_pax (a));
|
||||||
|
g_assert_cmpint (0, ==, archive_write_add_filter_gzip (a));
|
||||||
|
g_assert_cmpint (0, ==, archive_write_open_fd (a, td->fd_empty));
|
||||||
|
g_assert_cmpint (ARCHIVE_OK, ==, archive_write_close (a));
|
||||||
|
g_assert_cmpint (ARCHIVE_OK, ==, archive_write_free (a));
|
||||||
|
|
||||||
{ g_autoptr(GFile) repopath = g_file_new_for_path ("repo");
|
{ g_autoptr(GFile) repopath = g_file_new_for_path ("repo");
|
||||||
td->repo = ostree_repo_new (repopath);
|
td->repo = ostree_repo_new (repopath);
|
||||||
|
|
||||||
@ -109,6 +123,46 @@ spawn_cmdline (const char *cmd, GError **error)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_libarchive_noautocreate_empty (gconstpointer data)
|
||||||
|
{
|
||||||
|
TestData *td = (void*)data;
|
||||||
|
GError *error = NULL;
|
||||||
|
struct archive *a = archive_read_new ();
|
||||||
|
OstreeRepoImportArchiveOptions opts = { 0, };
|
||||||
|
glnx_unref_object OstreeMutableTree *mtree = ostree_mutable_tree_new ();
|
||||||
|
|
||||||
|
g_assert_cmpint (0, ==, lseek (td->fd_empty, 0, SEEK_SET));
|
||||||
|
g_assert_cmpint (0, ==, archive_read_support_format_all (a));
|
||||||
|
g_assert_cmpint (0, ==, archive_read_support_filter_all (a));
|
||||||
|
g_assert_cmpint (0, ==, archive_read_open_fd (a, td->fd_empty, 8192));
|
||||||
|
|
||||||
|
(void)ostree_repo_import_archive_to_mtree (td->repo, &opts, a, mtree, NULL, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ostree_mutable_tree_get_metadata_checksum (mtree) == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_libarchive_autocreate_empty (gconstpointer data)
|
||||||
|
{
|
||||||
|
TestData *td = (void*)data;
|
||||||
|
GError *error = NULL;
|
||||||
|
struct archive *a = archive_read_new ();
|
||||||
|
OstreeRepoImportArchiveOptions opts = { 0, };
|
||||||
|
glnx_unref_object OstreeMutableTree *mtree = ostree_mutable_tree_new ();
|
||||||
|
|
||||||
|
opts.autocreate_parents = 1;
|
||||||
|
|
||||||
|
g_assert_cmpint (0, ==, lseek (td->fd_empty, 0, SEEK_SET));
|
||||||
|
g_assert_cmpint (0, ==, archive_read_support_format_all (a));
|
||||||
|
g_assert_cmpint (0, ==, archive_read_support_filter_all (a));
|
||||||
|
g_assert_cmpint (0, ==, archive_read_open_fd (a, td->fd_empty, 8192));
|
||||||
|
|
||||||
|
(void)ostree_repo_import_archive_to_mtree (td->repo, &opts, a, mtree, NULL, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ostree_mutable_tree_get_metadata_checksum (mtree) != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_libarchive_error_device_file (gconstpointer data)
|
test_libarchive_error_device_file (gconstpointer data)
|
||||||
{
|
{
|
||||||
@ -189,6 +243,8 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
g_test_init (&argc, &argv, NULL);
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
|
||||||
|
g_test_add_data_func ("/libarchive/noautocreate-empty", &td, test_libarchive_noautocreate_empty);
|
||||||
|
g_test_add_data_func ("/libarchive/autocreate-empty", &td, test_libarchive_autocreate_empty);
|
||||||
g_test_add_data_func ("/libarchive/error-device-file", &td, test_libarchive_error_device_file);
|
g_test_add_data_func ("/libarchive/error-device-file", &td, test_libarchive_error_device_file);
|
||||||
g_test_add_data_func ("/libarchive/ignore-device-file", &td, test_libarchive_ignore_device_file);
|
g_test_add_data_func ("/libarchive/ignore-device-file", &td, test_libarchive_ignore_device_file);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user