diff options
author | Colin Walters <walters@verbum.org> | 2016-08-02 14:49:42 -0400 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2016-08-03 08:10:27 +0000 |
commit | f66906c40179ae9fe047be5412fe368f29a98290 (patch) | |
tree | deb3f7db432a46888be14379f01ddb719b2857f2 /src/libostree/ostree-repo-static-delta-compilation.c | |
parent | a843d16de22343bc55f0f584a77b5f5587e4ea23 (diff) | |
download | ostree-f66906c40179ae9fe047be5412fe368f29a98290.tar.gz |
deltas: Port compilation to libglnx/fd-relative
This was the last use of libgsystem tmpfile APIs. The change here is
a bit uglier than it needs to be because we support creating the delta
in place as well as in the repo, so we needed to abstract over
locations.
Closes: #424
Approved by: giuseppe
Diffstat (limited to 'src/libostree/ostree-repo-static-delta-compilation.c')
-rw-r--r-- | src/libostree/ostree-repo-static-delta-compilation.c | 104 |
1 files changed, 73 insertions, 31 deletions
diff --git a/src/libostree/ostree-repo-static-delta-compilation.c b/src/libostree/ostree-repo-static-delta-compilation.c index 4e4e7f9c..a6bc3206 100644 --- a/src/libostree/ostree-repo-static-delta-compilation.c +++ b/src/libostree/ostree-repo-static-delta-compilation.c @@ -1258,19 +1258,19 @@ ostree_repo_static_delta_generate (OstreeRepo *self, guint64 total_compressed_size = 0; guint64 total_uncompressed_size = 0; g_autoptr(GVariantBuilder) part_headers = NULL; - g_autoptr(GPtrArray) part_tempfiles = NULL; + g_autoptr(GArray) part_temp_fds = NULL; + g_autoptr(GPtrArray) part_temp_paths = NULL; g_autoptr(GVariant) delta_descriptor = NULL; g_autoptr(GVariant) to_commit = NULL; const char *opt_filename; - g_autofree char *descriptor_relpath = NULL; - g_autoptr(GFile) descriptor_path = NULL; - g_autoptr(GFile) descriptor_dir = NULL; + g_autofree char *descriptor_name = NULL; + glnx_fd_close int descriptor_dfd = -1; g_autoptr(GVariant) tmp_metadata = NULL; g_autoptr(GVariant) fallback_headers = NULL; g_autoptr(GVariant) detached = NULL; gboolean inline_parts; - guint endianness = G_BYTE_ORDER; - g_autoptr(GFile) tmp_dir = NULL; + guint endianness = G_BYTE_ORDER; + glnx_fd_close int tmp_dfd = NULL; builder.parts = g_ptr_array_new_with_free_func ((GDestroyNotify)ostree_static_delta_part_builder_unref); builder.fallback_objects = g_ptr_array_new_with_free_func ((GDestroyNotify)g_variant_unref); @@ -1355,16 +1355,24 @@ ostree_repo_static_delta_generate (OstreeRepo *self, if (opt_filename) { - g_autoptr(GFile) f = g_file_new_for_path (opt_filename); - tmp_dir = g_file_get_parent (f); + g_autofree char *dnbuf = g_strdup (opt_filename); + const char *dn = dirname (dnbuf); + if (!glnx_opendirat (AT_FDCWD, dn, TRUE, &tmp_dfd, error)) + goto out; } else { - tmp_dir = g_object_ref (self->tmp_dir); + tmp_dfd = fcntl (self->tmp_dir_fd, F_DUPFD_CLOEXEC); + if (tmp_dfd < 0) + { + glnx_set_error_from_errno (error); + goto out; + } } part_headers = g_variant_builder_new (G_VARIANT_TYPE ("a" OSTREE_STATIC_DELTA_META_ENTRY_FORMAT)); - part_tempfiles = g_ptr_array_new_with_free_func (g_object_unref); + part_temp_paths = g_ptr_array_new_with_free_func (g_free); + part_temp_fds = g_array_new (FALSE, TRUE, sizeof(int)); for (i = 0; i < builder.parts->len; i++) { OstreeStaticDeltaPartBuilder *part_builder = builder.parts->pdata[i]; @@ -1374,7 +1382,6 @@ ostree_repo_static_delta_generate (OstreeRepo *self, g_autoptr(GChecksum) checksum = NULL; g_autoptr(GBytes) objtype_checksum_array = NULL; g_autoptr(GBytes) checksum_bytes = NULL; - g_autoptr(GFile) part_tempfile = NULL; g_autoptr(GOutputStream) part_temp_outstream = NULL; g_autoptr(GInputStream) part_in = NULL; g_autoptr(GInputStream) part_payload_in = NULL; @@ -1436,10 +1443,21 @@ ostree_repo_static_delta_generate (OstreeRepo *self, g_autofree char *part_relpath = _ostree_get_relative_static_delta_part_path (from, to, i); g_variant_builder_add (&metadata_builder, "{sv}", part_relpath, delta_part); } - else if (!gs_file_open_in_tmpdir (tmp_dir, 0644, - &part_tempfile, &part_temp_outstream, - cancellable, error)) - goto out; + else + { + char *part_tempfile; + int part_temp_fd; + + if (!glnx_open_tmpfile_linkable_at (tmp_dfd, ".", O_WRONLY | O_CLOEXEC, + &part_temp_fd, &part_tempfile, error)) + goto out; + + /* Transfer tempfile ownership to arrays */ + g_array_append_val (part_temp_fds, part_temp_fd); + g_ptr_array_add (part_temp_paths, g_steal_pointer (&part_tempfile)); + part_temp_outstream = g_unix_output_stream_new (part_temp_fd, FALSE); + } + part_in = ot_variant_read (delta_part); if (!ot_gio_splice_get_checksum (part_temp_outstream, part_in, &part_checksum, @@ -1456,9 +1474,7 @@ ostree_repo_static_delta_generate (OstreeRepo *self, ot_gvariant_new_ay_bytes (objtype_checksum_array)); g_variant_builder_add_value (part_headers, g_variant_ref (delta_part_header)); - if (part_tempfile) - g_ptr_array_add (part_tempfiles, g_object_ref (part_tempfile)); - + total_compressed_size += g_variant_get_size (delta_part); total_uncompressed_size += part_builder->uncompressed_size; @@ -1473,27 +1489,43 @@ ostree_repo_static_delta_generate (OstreeRepo *self, if (opt_filename) { - descriptor_path = g_file_new_for_path (opt_filename); + g_autofree char *dnbuf = g_strdup (opt_filename); + const char *dn = dirname (dnbuf); + descriptor_name = g_strdup (opt_filename); + + if (!glnx_opendirat (AT_FDCWD, dn, TRUE, &descriptor_dfd, error)) + goto out; } else { - descriptor_relpath = _ostree_get_relative_static_delta_superblock_path (from, to); - descriptor_path = g_file_resolve_relative_path (self->repodir, descriptor_relpath); - } + g_autofree char *descriptor_relpath = _ostree_get_relative_static_delta_superblock_path (from, to); + g_autofree char *dnbuf = g_strdup (descriptor_relpath); + const char *dn = dirname (dnbuf); - descriptor_dir = g_file_get_parent (descriptor_path); + if (!glnx_shutil_mkdir_p_at (self->repo_dir_fd, dn, 0755, cancellable, error)) + goto out; + if (!glnx_opendirat (self->repo_dir_fd, dn, TRUE, &descriptor_dfd, error)) + goto out; - if (!glnx_shutil_mkdir_p_at (AT_FDCWD, gs_file_get_path_cached (descriptor_dir), 0755, - cancellable, error)) - goto out; + descriptor_name = g_strdup (basename (descriptor_relpath)); + } - for (i = 0; i < part_tempfiles->len; i++) + for (i = 0; i < part_temp_paths->len; i++) { - GFile *tempfile = part_tempfiles->pdata[i]; g_autofree char *partstr = g_strdup_printf ("%u", i); - g_autoptr(GFile) part_path = g_file_resolve_relative_path (descriptor_dir, partstr); + /* Take ownership of the path/fd here */ + g_autofree char *path = g_steal_pointer (&part_temp_paths->pdata[i]); + glnx_fd_close int fd = g_array_index (part_temp_fds, int, i); + g_array_index (part_temp_fds, int, i) = -1; - if (!gs_file_rename (tempfile, part_path, cancellable, error)) + if (fchmod (fd, 0644) < 0) + { + glnx_set_error_from_errno (error); + goto out; + } + + if (!glnx_link_tmpfile_at (tmp_dfd, GLNX_LINK_TMPFILE_REPLACE, fd, path, + descriptor_dfd, partstr, error)) goto out; } @@ -1544,11 +1576,21 @@ ostree_repo_static_delta_generate (OstreeRepo *self, g_printerr ("bsdiff=%u objects\n", builder.n_bsdiff); } - if (!ot_util_variant_save (descriptor_path, delta_descriptor, cancellable, error)) + if (!glnx_file_replace_contents_at (descriptor_dfd, descriptor_name, + g_variant_get_data (delta_descriptor), + g_variant_get_size (delta_descriptor), + 0, cancellable, error)) goto out; ret = TRUE; out: + for (i = 0; i < part_temp_fds->len; i++) + { + int fd = g_array_index (part_temp_fds, int, i); + if (fd == -1) + continue; + (void) close (fd); + } g_clear_pointer (&builder.parts, g_ptr_array_unref); g_clear_pointer (&builder.fallback_objects, g_ptr_array_unref); return ret; |