diff --git a/libglnx b/libglnx index 32231fdb52..9c26c122a7 160000 --- a/libglnx +++ b/libglnx @@ -1 +1 @@ -Subproject commit 32231fdb5273dd2a812c61549d6c0e681c0f5d59 +Subproject commit 9c26c122a7a351afcb4cca6e06f21ad79388b49d diff --git a/src/libostree/ostree-fetcher-curl.c b/src/libostree/ostree-fetcher-curl.c index 829f44474d..1250e1542f 100644 --- a/src/libostree/ostree-fetcher-curl.c +++ b/src/libostree/ostree-fetcher-curl.c @@ -99,8 +99,7 @@ struct FetcherRequest { OstreeFetcherRequestFlags flags; gboolean is_membuf; GError *caught_write_error; - char *out_tmpfile; - int out_tmpfile_fd; + GLnxTmpfile tmpfile; GString *output_buf; CURL *easy; @@ -269,11 +268,10 @@ request_get_uri (FetcherRequest *req, guint idx) static gboolean ensure_tmpfile (FetcherRequest *req, GError **error) { - if (req->out_tmpfile_fd == -1) + if (req->tmpfile.fd == -1) { if (!glnx_open_tmpfile_linkable_at (req->fetcher->tmpdir_dfd, ".", - O_WRONLY, &req->out_tmpfile_fd, - &req->out_tmpfile, + O_WRONLY | O_CLOEXEC, &req->tmpfile, error)) return FALSE; } @@ -387,18 +385,15 @@ check_multi_info (OstreeFetcher *fetcher) { g_task_return_error (task, g_steal_pointer (&local_error)); } - else if (fchmod (req->out_tmpfile_fd, 0644) < 0) + else if (fchmod (req->tmpfile.fd, 0644) < 0) { glnx_set_error_from_errno (error); g_task_return_error (task, g_steal_pointer (&local_error)); } - else if (!glnx_link_tmpfile_at (fetcher->tmpdir_dfd, - GLNX_LINK_TMPFILE_REPLACE, - req->out_tmpfile_fd, - req->out_tmpfile, - fetcher->tmpdir_dfd, - tmpfile_path, - error)) + else if (!glnx_link_tmpfile_at (&req->tmpfile, + GLNX_LINK_TMPFILE_REPLACE, + fetcher->tmpdir_dfd, tmpfile_path, + error)) g_task_return_error (task, g_steal_pointer (&local_error)); else { @@ -586,8 +581,8 @@ write_cb (void *ptr, size_t size, size_t nmemb, void *data) { if (!ensure_tmpfile (req, &req->caught_write_error)) return -1; - g_assert (req->out_tmpfile_fd >= 0); - if (glnx_loop_write (req->out_tmpfile_fd, ptr, realsize) < 0) + g_assert (req->tmpfile.fd >= 0); + if (glnx_loop_write (req->tmpfile.fd, ptr, realsize) < 0) { glnx_set_error_from_errno (&req->caught_write_error); return -1; @@ -622,9 +617,7 @@ request_unref (FetcherRequest *req) g_ptr_array_unref (req->mirrorlist); g_free (req->filename); g_clear_error (&req->caught_write_error); - if (req->out_tmpfile_fd != -1) - (void) close (req->out_tmpfile_fd); - g_free (req->out_tmpfile); + glnx_tmpfile_clear (&req->tmpfile); if (req->output_buf) g_string_free (req->output_buf, TRUE); curl_easy_cleanup (req->easy); @@ -847,7 +840,7 @@ _ostree_fetcher_request_async (OstreeFetcher *self, /* We'll allocate the tmpfile on demand, so we handle * file I/O errors just in the write func. */ - req->out_tmpfile_fd = -1; + req->tmpfile.src_dfd = -1; if (req->is_membuf) req->output_buf = g_string_new (""); diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index f6e91498f3..c91c6761fe 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -60,13 +60,11 @@ checkout_object_for_uncompressed_cache (OstreeRepo *self, guint32 file_mode = g_file_info_get_attribute_uint32 (src_info, "unix::mode"); file_mode &= ~(S_ISUID|S_ISGID); - glnx_fd_close int fd = -1; - g_autofree char *temp_filename = NULL; + g_auto(GLnxTmpfile) tmpf = GLNX_TMPFILE_INIT; if (!glnx_open_tmpfile_linkable_at (self->tmp_dir_fd, ".", O_WRONLY | O_CLOEXEC, - &fd, &temp_filename, - error)) + &tmpf, error)) return FALSE; - g_autoptr(GOutputStream) temp_out = g_unix_output_stream_new (fd, FALSE); + g_autoptr(GOutputStream) temp_out = g_unix_output_stream_new (tmpf.fd, FALSE); if (g_output_stream_splice (temp_out, content, 0, cancellable, error) < 0) return FALSE; @@ -76,14 +74,14 @@ checkout_object_for_uncompressed_cache (OstreeRepo *self, if (!self->disable_fsync) { - if (TEMP_FAILURE_RETRY (fsync (fd)) < 0) + if (TEMP_FAILURE_RETRY (fsync (tmpf.fd)) < 0) return glnx_throw_errno (error); } if (!g_output_stream_close (temp_out, cancellable, error)) return FALSE; - if (fchmod (fd, file_mode) < 0) + if (fchmod (tmpf.fd, file_mode) < 0) return glnx_throw_errno (error); if (!_ostree_repo_ensure_loose_objdir_at (self->uncompressed_objects_dir_fd, @@ -91,8 +89,7 @@ checkout_object_for_uncompressed_cache (OstreeRepo *self, cancellable, error)) return FALSE; - if (!glnx_link_tmpfile_at (self->tmp_dir_fd, GLNX_LINK_TMPFILE_NOREPLACE_IGNORE_EXIST, - fd, temp_filename, + if (!glnx_link_tmpfile_at (&tmpf, GLNX_LINK_TMPFILE_NOREPLACE_IGNORE_EXIST, self->uncompressed_objects_dir_fd, loose_path, error)) return FALSE; @@ -185,7 +182,6 @@ create_file_copy_from_input_at (OstreeRepo *repo, GCancellable *cancellable, GError **error) { - g_autofree char *temp_filename = NULL; const gboolean union_mode = options->overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES; const gboolean add_mode = options->overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_ADD_FILES; const gboolean sepolicy_enabled = options->sepolicy && !repo->disable_xattrs; @@ -252,7 +248,6 @@ create_file_copy_from_input_at (OstreeRepo *repo, } else if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR) { - glnx_fd_close int temp_fd = -1; guint32 file_mode; GLnxLinkTmpfileReplaceMode replace_mode; @@ -261,9 +256,9 @@ create_file_copy_from_input_at (OstreeRepo *repo, if (options->mode == OSTREE_REPO_CHECKOUT_MODE_USER) file_mode &= ~(S_ISUID|S_ISGID); + g_auto(GLnxTmpfile) tmpf = GLNX_TMPFILE_INIT; if (!glnx_open_tmpfile_linkable_at (destination_dfd, ".", O_WRONLY | O_CLOEXEC, - &temp_fd, &temp_filename, - error)) + &tmpf, error)) return FALSE; if (sepolicy_enabled) @@ -274,11 +269,11 @@ create_file_copy_from_input_at (OstreeRepo *repo, g_file_info_get_attribute_uint32 (file_info, "unix::mode"), &label, cancellable, error)) return FALSE; - if (fsetxattr (temp_fd, "security.selinux", label, strlen (label), 0) < 0) + if (fsetxattr (tmpf.fd, "security.selinux", label, strlen (label), 0) < 0) return glnx_throw_errno_prefix (error, "Setting security.selinux"); } - if (!write_regular_file_content (repo, options, temp_fd, file_info, xattrs, input, + if (!write_regular_file_content (repo, options, tmpf.fd, file_info, xattrs, input, cancellable, error)) return FALSE; @@ -290,9 +285,8 @@ create_file_copy_from_input_at (OstreeRepo *repo, else replace_mode = GLNX_LINK_TMPFILE_NOREPLACE; - if (!glnx_link_tmpfile_at (destination_dfd, replace_mode, - temp_fd, temp_filename, destination_dfd, - destination_name, + if (!glnx_link_tmpfile_at (&tmpf, replace_mode, + destination_dfd, destination_name, error)) return FALSE; } diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index ce45a91124..2a518fee28 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -160,8 +160,13 @@ _ostree_repo_commit_loose_final (OstreeRepo *self, if (fd != -1) { - if (!glnx_link_tmpfile_at (temp_dfd, GLNX_LINK_TMPFILE_NOREPLACE_IGNORE_EXIST, - fd, temp_filename, dest_dfd, tmpbuf, error)) + /* FIXME: We'll unlink the tmpfile here in the non-O_TMPFILE case, and + * then go to unlink it again up the stack. Need to fix this with an + * OstreeTempObject struct or so that handles both regfiles and symlinks. + */ + GLnxTmpfile tmpfile = { temp_dfd, fd, temp_filename ? g_strdup (temp_filename) : NULL }; + if (!glnx_link_tmpfile_at (&tmpfile, GLNX_LINK_TMPFILE_NOREPLACE_IGNORE_EXIST, + dest_dfd, tmpbuf, error)) return FALSE; } else @@ -494,16 +499,18 @@ _ostree_repo_open_content_bare (OstreeRepo *self, if (!have_obj) { - int fd; - + /* TODO - raise this struct into OstreeRepoContentBareCommit */ + g_auto(GLnxTmpfile) tmpf = GLNX_TMPFILE_INIT; if (!glnx_open_tmpfile_linkable_at (self->tmp_dir_fd, ".", O_WRONLY|O_CLOEXEC, - &fd, &temp_filename, error)) + &tmpf, error)) goto out; - if (!ot_fallocate (fd, content_len, error)) + if (!ot_fallocate (tmpf.fd, content_len, error)) goto out; - ret_stream = g_unix_output_stream_new (fd, TRUE); + /* Destructure and transfer ownership */ + temp_filename = g_steal_pointer (&tmpf.path); + ret_stream = g_unix_output_stream_new (tmpf.fd, TRUE); tmpf.fd = -1; } ret = TRUE; @@ -558,36 +565,36 @@ create_regular_tmpfile_linkable_with_content (OstreeRepo *self, GCancellable *cancellable, GError **error) { - glnx_fd_close int temp_fd = -1; - g_autofree char *temp_filename = NULL; - + g_auto(GLnxTmpfile) tmpf = GLNX_TMPFILE_INIT; if (!glnx_open_tmpfile_linkable_at (self->tmp_dir_fd, ".", O_WRONLY|O_CLOEXEC, - &temp_fd, &temp_filename, - error)) + &tmpf, error)) return FALSE; - if (!ot_fallocate (temp_fd, length, error)) + if (!ot_fallocate (tmpf.fd, length, error)) return FALSE; if (G_IS_FILE_DESCRIPTOR_BASED (input)) { int infd = g_file_descriptor_based_get_fd ((GFileDescriptorBased*) input); - if (glnx_regfile_copy_bytes (infd, temp_fd, (off_t)length, TRUE) < 0) + if (glnx_regfile_copy_bytes (infd, tmpf.fd, (off_t)length, TRUE) < 0) return glnx_throw_errno_prefix (error, "regfile copy"); } else { - g_autoptr(GOutputStream) temp_out = g_unix_output_stream_new (temp_fd, FALSE); + g_autoptr(GOutputStream) temp_out = g_unix_output_stream_new (tmpf.fd, FALSE); if (g_output_stream_splice (temp_out, input, 0, cancellable, error) < 0) return FALSE; } - if (fchmod (temp_fd, 0644) < 0) + if (fchmod (tmpf.fd, 0644) < 0) return glnx_throw_errno_prefix (error, "fchmod"); - *out_fd = temp_fd; temp_fd = -1; - *out_path = g_steal_pointer (&temp_filename); + /* Deconstruct and return. It's hard to return the tmpf directly since some + * bits of the commit path also use the temp path for symlinks. + */ + *out_fd = tmpf.fd; tmpf.fd = -1; + *out_path = g_steal_pointer (&tmpf.path); return TRUE; } @@ -716,10 +723,15 @@ write_object (OstreeRepo *self, if (self->generate_sizes) indexable = TRUE; + GLnxTmpfile tmpf; /* Not auto, see below */ if (!glnx_open_tmpfile_linkable_at (self->tmp_dir_fd, ".", O_WRONLY|O_CLOEXEC, - &temp_fd, &temp_filename, - error)) + &tmpf, error)) goto out; + /* We destructure it here to avoid having to churn too much code; + * perhaps down the line we could pass the tmpfile struct down. + */ + temp_fd = tmpf.fd; tmpf.fd = -1; + temp_filename = g_steal_pointer (&tmpf.path); temp_file_is_regular = TRUE; temp_out = g_unix_output_stream_new (temp_fd, FALSE); diff --git a/src/libostree/ostree-repo-static-delta-compilation.c b/src/libostree/ostree-repo-static-delta-compilation.c index 47fae9f59a..342b2eb789 100644 --- a/src/libostree/ostree-repo-static-delta-compilation.c +++ b/src/libostree/ostree-repo-static-delta-compilation.c @@ -449,29 +449,25 @@ get_unpacked_unlinked_content (OstreeRepo *repo, GCancellable *cancellable, GError **error) { - g_autofree char *tmpname = NULL; - glnx_fd_close int fd = -1; + g_auto(GLnxTmpfile) tmpf = GLNX_TMPFILE_INIT; g_autoptr(GBytes) ret_content = NULL; g_autoptr(GInputStream) istream = NULL; g_autoptr(GOutputStream) out = NULL; if (!glnx_open_tmpfile_linkable_at (AT_FDCWD, "/tmp", O_RDWR | O_CLOEXEC, - &fd, &tmpname, error)) + &tmpf, error)) return FALSE; - /* We don't need the file name */ - if (tmpname) - (void) unlinkat (AT_FDCWD, tmpname, 0); if (!ostree_repo_load_file (repo, checksum, &istream, NULL, NULL, cancellable, error)) return FALSE; - out = g_unix_output_stream_new (fd, FALSE); + out = g_unix_output_stream_new (tmpf.fd, FALSE); if (g_output_stream_splice (out, istream, G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, cancellable, error) < 0) return FALSE; - { g_autoptr(GMappedFile) mfile = g_mapped_file_new_from_fd (fd, FALSE, error); + { g_autoptr(GMappedFile) mfile = g_mapped_file_new_from_fd (tmpf.fd, FALSE, error); if (!mfile) return FALSE; ret_content = g_mapped_file_get_bytes (mfile); @@ -1273,8 +1269,7 @@ 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(GArray) part_temp_fds = NULL; - g_autoptr(GPtrArray) part_temp_paths = NULL; + g_autoptr(GArray) part_tempf = NULL; g_autoptr(GVariant) delta_descriptor = NULL; g_autoptr(GVariant) to_commit = NULL; const char *opt_filename; @@ -1385,8 +1380,8 @@ ostree_repo_static_delta_generate (OstreeRepo *self, } part_headers = g_variant_builder_new (G_VARIANT_TYPE ("a" OSTREE_STATIC_DELTA_META_ENTRY_FORMAT)); - part_temp_paths = g_ptr_array_new_with_free_func (g_free); - part_temp_fds = g_array_new (FALSE, TRUE, sizeof(int)); + part_tempf = g_array_new (FALSE, TRUE, sizeof(GLnxTmpfile)); + g_array_set_clear_func (part_tempf, (GDestroyNotify)glnx_tmpfile_clear); for (i = 0; i < builder.parts->len; i++) { OstreeStaticDeltaPartBuilder *part_builder = builder.parts->pdata[i]; @@ -1459,17 +1454,12 @@ ostree_repo_static_delta_generate (OstreeRepo *self, } else { - char *part_tempfile; - int part_temp_fd; - + g_array_set_size (part_tempf, part_tempf->len + 1); + GLnxTmpfile *tmpf = &g_array_index(part_tempf, GLnxTmpfile, part_tempf->len-1); if (!glnx_open_tmpfile_linkable_at (tmp_dfd, ".", O_WRONLY | O_CLOEXEC, - &part_temp_fd, &part_tempfile, error)) + tmpf, 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_temp_outstream = g_unix_output_stream_new (tmpf->fd, FALSE); } part_in = ot_variant_read (delta_part); @@ -1524,21 +1514,19 @@ ostree_repo_static_delta_generate (OstreeRepo *self, descriptor_name = g_strdup (basename (descriptor_relpath)); } - for (i = 0; i < part_temp_paths->len; i++) + for (i = 0; i < part_tempf->len; i++) { + GLnxTmpfile *tmpf = &g_array_index(part_tempf, GLnxTmpfile, i); g_autofree char *partstr = g_strdup_printf ("%u", i); /* 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 (fchmod (fd, 0644) < 0) + if (fchmod (tmpf->fd, 0644) < 0) { glnx_set_error_from_errno (error); goto out; } - if (!glnx_link_tmpfile_at (tmp_dfd, GLNX_LINK_TMPFILE_REPLACE, fd, path, + if (!glnx_link_tmpfile_at (tmpf, GLNX_LINK_TMPFILE_REPLACE, descriptor_dfd, partstr, error)) goto out; } @@ -1598,14 +1586,6 @@ ostree_repo_static_delta_generate (OstreeRepo *self, ret = TRUE; out: - if (part_temp_fds) - 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; diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index b7d1324c68..2d5ce1ec00 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -3804,8 +3804,7 @@ sign_data (OstreeRepo *self, GError **error) { gboolean ret = FALSE; - glnx_fd_close int tmp_fd = -1; - g_autofree char *tmp_path = NULL; + g_auto(GLnxTmpfile) tmpf = GLNX_TMPFILE_INIT; g_autoptr(GOutputStream) tmp_signature_output = NULL; gpgme_ctx_t context = NULL; g_autoptr(GBytes) ret_signature = NULL; @@ -3814,11 +3813,11 @@ sign_data (OstreeRepo *self, gpgme_data_t commit_buffer = NULL; gpgme_data_t signature_buffer = NULL; g_autoptr(GMappedFile) signature_file = NULL; - + if (!glnx_open_tmpfile_linkable_at (self->tmp_dir_fd, ".", O_RDWR | O_CLOEXEC, - &tmp_fd, &tmp_path, error)) + &tmpf, error)) goto out; - tmp_signature_output = g_unix_output_stream_new (tmp_fd, FALSE); + tmp_signature_output = g_unix_output_stream_new (tmpf.fd, FALSE); context = ot_gpgme_new_ctx (homedir, error); if (!context) @@ -3872,7 +3871,7 @@ sign_data (OstreeRepo *self, if (!g_output_stream_close (tmp_signature_output, cancellable, error)) goto out; - signature_file = g_mapped_file_new_from_fd (tmp_fd, FALSE, error); + signature_file = g_mapped_file_new_from_fd (tmpf.fd, FALSE, error); if (!signature_file) goto out; ret_signature = g_mapped_file_get_bytes (signature_file); diff --git a/src/ostree/ot-remote-cookie-util.c b/src/ostree/ot-remote-cookie-util.c index e3ca9eac26..c520f258be 100644 --- a/src/ostree/ot-remote-cookie-util.c +++ b/src/ostree/ot-remote-cookie-util.c @@ -202,8 +202,7 @@ ot_delete_cookie_at (int dfd, const char *jar_path, { gboolean found = FALSE; #ifdef HAVE_LIBCURL - glnx_fd_close int tempfile_fd = -1; - g_autofree char *tempfile_path = NULL; + g_auto(GLnxTmpfile) tmpf = GLNX_TMPFILE_INIT; g_autofree char *dnbuf = NULL; const char *dn = NULL; g_autoptr(OtCookieParser) parser = NULL; @@ -214,8 +213,7 @@ ot_delete_cookie_at (int dfd, const char *jar_path, dnbuf = g_strdup (jar_path); dn = dirname (dnbuf); if (!glnx_open_tmpfile_linkable_at (AT_FDCWD, dn, O_WRONLY | O_CLOEXEC, - &tempfile_fd, &tempfile_path, - error)) + &tmpf, error)) return FALSE; while (ot_parse_cookies_next (parser)) @@ -229,17 +227,15 @@ ot_delete_cookie_at (int dfd, const char *jar_path, continue; } - if (glnx_loop_write (tempfile_fd, parser->line, strlen (parser->line)) < 0 || - glnx_loop_write (tempfile_fd, "\n", 1) < 0) + if (glnx_loop_write (tmpf.fd, parser->line, strlen (parser->line)) < 0 || + glnx_loop_write (tmpf.fd, "\n", 1) < 0) { glnx_set_error_from_errno (error); return FALSE; } } - if (!glnx_link_tmpfile_at (AT_FDCWD, GLNX_LINK_TMPFILE_REPLACE, - tempfile_fd, - tempfile_path, + if (!glnx_link_tmpfile_at (&tmpf, GLNX_LINK_TMPFILE_REPLACE, AT_FDCWD, jar_path, error)) return FALSE; @@ -279,22 +275,11 @@ gboolean ot_list_cookies_at (int dfd, const char *jar_path, GError **error) { #ifdef HAVE_LIBCURL - glnx_fd_close int tempfile_fd = -1; - g_autofree char *tempfile_path = NULL; - g_autofree char *dnbuf = NULL; - const char *dn = NULL; g_autoptr(OtCookieParser) parser = NULL; if (!ot_parse_cookies_at (AT_FDCWD, jar_path, &parser, NULL, error)) return FALSE; - dnbuf = dirname (g_strdup (jar_path)); - dn = dnbuf; - if (!glnx_open_tmpfile_linkable_at (AT_FDCWD, dn, O_WRONLY | O_CLOEXEC, - &tempfile_fd, &tempfile_path, - error)) - return FALSE; - while (ot_parse_cookies_next (parser)) { g_autoptr(GDateTime) expires = g_date_time_new_from_unix_utc (parser->expiration);