}
#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:
* @self: An #OstreeRepo
g_autofree guchar *tmp_csum = NULL;
int r;
+
while (TRUE)
{
r = archive_read_next_header (a, &entry);
*/
if (opts->autocreate_parents && !tmp_csum)
{
- g_autoptr(GFileInfo) tmp_dir_info = g_file_info_new ();
-
- g_file_info_set_attribute_uint32 (tmp_dir_info, "unix::uid", archive_entry_uid (entry));
- 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 (!_ostree_repo_write_directory_meta (self, tmp_dir_info, NULL, &tmp_csum, cancellable, error))
+ /* Here, we auto-pick the first uid/gid we find in the
+ * archive. Realistically this is probably always going to
+ * be root, but eh, at least we try to match.
+ */
+ if (!create_empty_dir_with_uidgid (self, archive_entry_uid (entry),
+ archive_entry_gid (entry),
+ &tmp_csum, cancellable, error))
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;
out:
return ret;
typedef struct {
OstreeRepo *repo;
int fd;
+ int fd_empty;
char *tmpd;
} TestData;
g_assert_cmpint (ARCHIVE_OK, ==, archive_write_close (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");
td->repo = ostree_repo_new (repopath);
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
test_libarchive_error_device_file (gconstpointer data)
{
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/ignore-device-file", &td, test_libarchive_ignore_device_file);