libutil: Add a helper for O_TMPFILE + mmap()
authorColin Walters <walters@verbum.org>
Wed, 28 Jun 2017 17:41:52 +0000 (13:41 -0400)
committerAtomic Bot <atomic-devel@projectatomic.io>
Thu, 29 Jun 2017 14:46:18 +0000 (14:46 +0000)
I added `glnx_open_anonymous_tmpfile()`, but then later noticed
that the usage of this was really to be combined with `mmap()`,
and we had two versions of that in the delta code.  Add a helper.

(Bigger picture...how is this different from glibc's "mmap() of /dev/zero"
 approach for large chunks? One advantage is the storage can be "swapped" to
 `/var/tmp`, but still deleted automatically, rather than requiring swap space)

Closes: #973
Approved by: jlebon

src/libostree/ostree-repo-static-delta-compilation.c
src/libostree/ostree-repo-static-delta-core.c
src/libotutil/ot-fs-utils.c
src/libotutil/ot-fs-utils.h

index 8a1bb1d2ba233b84bc8e985925ab0438e25deb6a..851f3fcbfa7ebf5aa6c0f68f7fc1218cc81c8b36 100644 (file)
@@ -437,31 +437,15 @@ get_unpacked_unlinked_content (OstreeRepo       *repo,
                                GCancellable     *cancellable,
                                GError          **error)
 {
-  g_auto(GLnxTmpfile) tmpf = { 0, };
-  g_autoptr(GBytes) ret_content = NULL;
   g_autoptr(GInputStream) istream = NULL;
-  g_autoptr(GOutputStream) out = NULL;
-
-  if (!glnx_open_anonymous_tmpfile (O_RDWR | O_CLOEXEC, &tmpf, error))
-    return FALSE;
 
   if (!ostree_repo_load_file (repo, checksum, &istream, NULL, NULL,
                               cancellable, error))
     return 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)
+  *out_content = ot_map_anonymous_tmpfile_from_content (istream, cancellable, error);
+  if (!*out_content)
     return FALSE;
-
-  { 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);
-  }
-
-  if (out_content)
-    *out_content = g_steal_pointer (&ret_content);
   return TRUE;
 }
 
index 878d607d097351997c603ca85affbd09455052c2..a409f9b68a450d003bb241c771fad7df03247ffc 100644 (file)
@@ -473,41 +473,14 @@ _ostree_static_delta_part_open (GInputStream   *part_in,
       break;
     case 'x':
       {
-        g_autofree char *tmppath = g_strdup ("/var/tmp/ostree-delta-XXXXXX");
         g_autoptr(GConverter) decomp = (GConverter*) _ostree_lzma_decompressor_new ();
         g_autoptr(GInputStream) convin = g_converter_input_stream_new (source_in, decomp);
-        g_autoptr(GOutputStream) unpacked_out = NULL;
-        glnx_fd_close int unpacked_fd = -1;
-        gssize n_bytes_written;
-
-        unpacked_fd = g_mkstemp_full (tmppath, O_RDWR | O_CLOEXEC, 0640);
-        if (unpacked_fd < 0)
-          {
-            glnx_set_error_from_errno (error);
-            goto out;
-          }
-        
-        /* Now make it autocleanup on process exit - in the future, we
-         * should consider caching unpacked deltas as well.
-         */
-        if (unlink (tmppath) < 0)
-          {
-            glnx_set_error_from_errno (error);
-            goto out;
-          }
-        
-        unpacked_out = g_unix_output_stream_new (unpacked_fd, FALSE);
-
-        n_bytes_written = g_output_stream_splice (unpacked_out, convin,
-                                                  G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
-                                                  G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
-                                                  cancellable, error);
-        if (n_bytes_written < 0)
+        g_autoptr(GBytes) buf = ot_map_anonymous_tmpfile_from_content (convin, cancellable, error);
+        if (!buf)
           goto out;
 
-        if (!ot_util_variant_map_fd (unpacked_fd, 0, G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
-                                     trusted, &ret_part, error))
-          goto out;
+        ret_part = g_variant_new_from_bytes (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
+                                             buf, FALSE);
       }
       break;
     default:
index d2bde837c650cce732234af5fb4e28033c8ccc38..2f0ae19cbcfcc755f77c3f8f0b5cc076ceed5b22 100644 (file)
@@ -24,6 +24,7 @@
 #include "libglnx.h"
 #include <sys/xattr.h>
 #include <gio/gunixinputstream.h>
+#include <gio/gunixoutputstream.h>
 
 /* Convert a fd-relative path to a GFile* - use
  * for legacy code.
@@ -181,3 +182,29 @@ ot_file_mapat_bytes (int dfd,
 
   return g_mapped_file_get_bytes (mfile);
 }
+
+/* Given an input stream, splice it to an anonymous file (O_TMPFILE).
+ * Useful for potentially large but transient files.
+ */
+GBytes *
+ot_map_anonymous_tmpfile_from_content (GInputStream *instream,
+                                       GCancellable *cancellable,
+                                       GError      **error)
+{
+  g_auto(GLnxTmpfile) tmpf = { 0, };
+  if (!glnx_open_anonymous_tmpfile (O_RDWR | O_CLOEXEC, &tmpf, error))
+    return NULL;
+
+  g_autoptr(GOutputStream) out = g_unix_output_stream_new (tmpf.fd, FALSE);
+  gssize n_bytes_written = g_output_stream_splice (out, instream,
+                                                   G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
+                                                   G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
+                                                   cancellable, error);
+  if (n_bytes_written < 0)
+    return NULL;
+
+  g_autoptr(GMappedFile) mfile = g_mapped_file_new_from_fd (tmpf.fd, FALSE, error);
+  if (!mfile)
+    return NULL;
+  return g_mapped_file_get_bytes (mfile);
+}
index 3b40d3379f9618bb4b954dc29fc202347923f1c3..43bc6942137a931e0015620c7e0b39ba4726c16e 100644 (file)
@@ -86,6 +86,11 @@ gboolean ot_dfd_iter_init_allow_noent (int dfd,
                                        gboolean *out_exists,
                                        GError **error);
 
+GBytes *
+ot_map_anonymous_tmpfile_from_content (GInputStream *instream,
+                                       GCancellable *cancellable,
+                                       GError      **error);
+
 GBytes *ot_file_mapat_bytes (int dfd,
                              const char *path,
                              GError **error);