fetcher: Always open tmpfiles in repo (except on FUSE)
authorColin Walters <walters@verbum.org>
Thu, 29 Jun 2023 06:42:04 +0000 (02:42 -0400)
committerColin Walters <walters@verbum.org>
Wed, 5 Jul 2023 08:27:36 +0000 (04:27 -0400)
This reverts commit 4e61e6f7d0d6aebd6abcdc455ec53164afe39e8d
and re-instates the fix for ensuring that we download temporary
files into the repository location.

However in order to ensure we don't re-introduce
https://github.com/ostreedev/ostree/issues/2900
we detect the case where we're writing to a FUSE mount
and keep the prior behavior.

I've verified that this works with flatpak.

Note a downside of this is the change needs to be triplicated
across the 3 http backends.

This then again
Closes: https://github.com/ostreedev/ostree/issues/2571
src/libostree/ostree-fetcher-curl.c
src/libostree/ostree-fetcher-soup.c
src/libostree/ostree-fetcher-soup3.c
src/libostree/ostree-fetcher-util.h
src/libostree/ostree-fetcher.h
src/libostree/ostree-repo-private.h
src/libostree/ostree-repo-pull.c
src/libostree/ostree-repo.c

index 9d07e5e10c32a08748c7618cb333d81cc340f29c..be88c4ef9fbc592c29ba9d4c4095bd3087c81811 100644 (file)
@@ -24,6 +24,7 @@
 #include <gio/gfiledescriptorbased.h>
 #include <gio/gunixoutputstream.h>
 #include <glib-unix.h>
+#include <stdbool.h>
 
 /* These macros came from 7.43.0, but we want to check
  * for versions a bit earlier than that (to work on CentOS 7),
@@ -76,6 +77,7 @@ struct OstreeFetcher
   char *proxy;
   struct curl_slist *extra_headers;
   int tmpdir_dfd;
+  bool force_anonymous;
   char *custom_user_agent;
 
   GMainContext *mainctx;
@@ -250,6 +252,12 @@ _ostree_fetcher_new (int tmpdir_dfd, const char *remote_name, OstreeFetcherConfi
   return fetcher;
 }
 
+void
+_ostree_fetcher_set_force_anonymous_tmpfiles (OstreeFetcher *self)
+{
+  self->force_anonymous = true;
+}
+
 static void
 destroy_and_unref_source (GSource *source)
 {
@@ -271,13 +279,12 @@ request_get_uri (FetcherRequest *req, GUri *baseuri)
 static gboolean
 ensure_tmpfile (FetcherRequest *req, GError **error)
 {
-  if (!req->tmpf.initialized)
-    {
-      if (!_ostree_fetcher_tmpf_from_flags (req->flags, req->fetcher->tmpdir_dfd, &req->tmpf,
-                                            error))
-        return FALSE;
-    }
-  return TRUE;
+  if (req->tmpf.initialized)
+    return TRUE;
+  if (req->fetcher->force_anonymous)
+    return glnx_open_anonymous_tmpfile (O_RDWR | O_CLOEXEC, &req->tmpf, error);
+  else
+    return _ostree_fetcher_tmpf (req->fetcher->tmpdir_dfd, &req->tmpf, error);
 }
 
 /* Check for completed transfers, and remove their easy handles */
index dbba2f002c2a60721e43286b4fe7f69d49ba24bf..629065fffe561e3ea255c770bcef819df0d17926 100644 (file)
@@ -25,6 +25,7 @@
 #include <gio/gfiledescriptorbased.h>
 #include <gio/gio.h>
 #include <gio/gunixoutputstream.h>
+#include <stdbool.h>
 #define LIBSOUP_USE_UNSTABLE_REQUEST_API
 #include <libsoup/soup-request-http.h>
 #include <libsoup/soup-requester.h>
@@ -59,6 +60,7 @@ typedef struct
 
   char *remote_name;
   int base_tmpdir_dfd;
+  bool force_anonymous;
 
   GVariant *extra_headers;
   gboolean transfer_gzip;
@@ -681,6 +683,12 @@ _ostree_fetcher_new (int tmpdir_dfd, const char *remote_name, OstreeFetcherConfi
   return self;
 }
 
+void
+_ostree_fetcher_set_force_anonymous_tmpfiles (OstreeFetcher *self)
+{
+  self->thread_closure->force_anonymous = true;
+}
+
 int
 _ostree_fetcher_get_dfd (OstreeFetcher *fetcher)
 {
@@ -888,9 +896,13 @@ on_stream_read (GObject *object, GAsyncResult *result, gpointer user_data)
     {
       if (!pending->is_membuf)
         {
-          if (!_ostree_fetcher_tmpf_from_flags (pending->flags,
-                                                pending->thread_closure->base_tmpdir_dfd,
-                                                &pending->tmpf, &local_error))
+          if (pending->thread_closure->force_anonymous)
+            {
+              if (!glnx_open_anonymous_tmpfile (O_RDWR | O_CLOEXEC, &pending->tmpf, &local_error))
+                goto out;
+            }
+          else if (!_ostree_fetcher_tmpf (pending->thread_closure->base_tmpdir_dfd, &pending->tmpf,
+                                          &local_error))
             goto out;
           pending->out_stream = g_unix_output_stream_new (pending->tmpf.fd, FALSE);
         }
index f6ada17abf969cf5848fe84ab3c0c4de7355935a..380168023f2071b6dcfb5e19413cb94de4eb7519 100644 (file)
@@ -28,6 +28,7 @@
 #include <gio/gio.h>
 #include <gio/gunixoutputstream.h>
 #include <libsoup/soup.h>
+#include <stdbool.h>
 
 #include "libglnx.h"
 #include "ostree-enumtypes.h"
@@ -72,6 +73,7 @@ struct OstreeFetcher
   OstreeFetcherConfigFlags config_flags;
   char *remote_name;
   int tmpdir_dfd;
+  bool force_anonymous;
 
   GHashTable *sessions; /* (element-type GMainContext SoupSession ) */
   GProxyResolver *proxy_resolver;
@@ -292,6 +294,12 @@ _ostree_fetcher_new (int tmpdir_dfd, const char *remote_name, OstreeFetcherConfi
   return self;
 }
 
+void
+_ostree_fetcher_set_force_anonymous_tmpfiles (OstreeFetcher *self)
+{
+  self->force_anonymous = true;
+}
+
 int
 _ostree_fetcher_get_dfd (OstreeFetcher *self)
 {
@@ -448,8 +456,16 @@ on_stream_read (GObject *object, GAsyncResult *result, gpointer user_data)
     {
       if (!request->is_membuf)
         {
-          if (!_ostree_fetcher_tmpf_from_flags (request->flags, request->fetcher->tmpdir_dfd,
-                                                &request->tmpf, &local_error))
+          if (request->fetcher->force_anonymous)
+            {
+              if (!glnx_open_anonymous_tmpfile (O_RDWR | O_CLOEXEC, &request->tmpf, &local_error))
+                {
+                  g_task_return_error (task, local_error);
+                  return;
+                }
+            }
+          else if (!_ostree_fetcher_tmpf (request->fetcher->tmpdir_dfd, &request->tmpf,
+                                          &local_error))
             {
               g_task_return_error (task, local_error);
               return;
index c3243801ce17b140955f2343ff985587c97447b2..97233e1f337707c4ff16bf99eb5b685bfe79c645 100644 (file)
@@ -32,17 +32,10 @@ G_BEGIN_DECLS
 #define OSTREE_FETCHER_USERAGENT_STRING (PACKAGE_NAME "/" PACKAGE_VERSION)
 
 static inline gboolean
-_ostree_fetcher_tmpf_from_flags (OstreeFetcherRequestFlags flags, int dfd, GLnxTmpfile *tmpf,
-                                 GError **error)
+_ostree_fetcher_tmpf (int dfd, GLnxTmpfile *tmpf, GError **error)
 {
-  if ((flags & OSTREE_FETCHER_REQUEST_LINKABLE) > 0)
-    {
-      if (!glnx_open_tmpfile_linkable_at (dfd, ".", O_RDWR | O_CLOEXEC, tmpf, error))
-        return FALSE;
-    }
-  else if (!glnx_open_anonymous_tmpfile (O_RDWR | O_CLOEXEC, tmpf, error))
+  if (!glnx_open_tmpfile_linkable_at (dfd, ".", O_RDWR | O_CLOEXEC, tmpf, error))
     return FALSE;
-
   if (!glnx_fchmod (tmpf->fd, 0644, error))
     return FALSE;
   return TRUE;
index 42ff3a17d37b79d9145455c241ae6a6d2d824501..6a555e09622d8ffac5c81ad875aa0412e1a9b340 100644 (file)
@@ -88,6 +88,8 @@ GType _ostree_fetcher_get_type (void) G_GNUC_CONST;
 OstreeFetcher *_ostree_fetcher_new (int tmpdir_dfd, const char *remote_name,
                                     OstreeFetcherConfigFlags flags);
 
+void _ostree_fetcher_set_force_anonymous_tmpfiles (OstreeFetcher *fetcher);
+
 int _ostree_fetcher_get_dfd (OstreeFetcher *fetcher);
 
 void _ostree_fetcher_set_cookie_jar (OstreeFetcher *self, const char *jar_path);
index 6d3f21e61fe51aa224c2f33cead9da66eeb1999c..d8ca057ddb0ac26340db1b7679f9a35368514605 100644 (file)
@@ -193,6 +193,7 @@ struct OstreeRepo
 
   gboolean inited;
   gboolean writable;
+  gboolean is_on_fuse; /* TRUE if the repository is on a FUSE filesystem */
   OstreeRepoSysrootKind sysroot_kind;
   GError *writable_error;
   gboolean in_transaction;
index 6d69d79ee56b075836261779e9f6d9e948d4c742..2ad9215aa2cda04166c5e9a24c03d85caa0efb1a 100644 (file)
@@ -2966,6 +2966,8 @@ _ostree_repo_remote_new_fetcher (OstreeRepo *self, const char *remote_name, gboo
   }
 
   fetcher = _ostree_fetcher_new (self->tmp_dir_fd, remote_name, fetcher_flags);
+  if (self->is_on_fuse)
+    _ostree_fetcher_set_force_anonymous_tmpfiles (fetcher);
 
   {
     g_autofree char *tls_client_cert_path = NULL;
index 8633701f40d6c39bace7d3347ed7dce40ebbd53d..fc15cb7873c7244d98d1563fdcf39dbffd414764 100644 (file)
@@ -3426,6 +3426,17 @@ ostree_repo_open (OstreeRepo *self, GCancellable *cancellable, GError **error)
       /* Note - we don't return this error yet! */
     }
 
+  {
+    struct statfs fsstbuf;
+    if (fstatfs (self->repo_dir_fd, &fsstbuf) < 0)
+      return glnx_throw_errno_prefix (error, "fstatfs");
+#ifndef FUSE_SUPER_MAGIC
+#define FUSE_SUPER_MAGIC 0x65735546
+#endif
+    self->is_on_fuse = (fsstbuf.f_type == FUSE_SUPER_MAGIC);
+    g_debug ("using fuse: %d", self->is_on_fuse);
+  }
+
   if (!glnx_fstat (self->objects_dir_fd, &stbuf, error))
     return FALSE;
   self->owner_uid = stbuf.st_uid;