libutil: Add a helper for O_TMPFILE + mmap()
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
This commit is contained in:
parent
9d10bdfd0d
commit
6f2ea23e8a
|
|
@ -437,31 +437,15 @@ get_unpacked_unlinked_content (OstreeRepo *repo,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
g_auto(GLnxTmpfile) tmpf = { 0, };
|
|
||||||
g_autoptr(GBytes) ret_content = NULL;
|
|
||||||
g_autoptr(GInputStream) istream = 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,
|
if (!ostree_repo_load_file (repo, checksum, &istream, NULL, NULL,
|
||||||
cancellable, error))
|
cancellable, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
out = g_unix_output_stream_new (tmpf.fd, FALSE);
|
*out_content = ot_map_anonymous_tmpfile_from_content (istream, cancellable, error);
|
||||||
if (g_output_stream_splice (out, istream, G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
|
if (!*out_content)
|
||||||
cancellable, error) < 0)
|
|
||||||
return FALSE;
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -473,41 +473,14 @@ _ostree_static_delta_part_open (GInputStream *part_in,
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
{
|
{
|
||||||
g_autofree char *tmppath = g_strdup ("/var/tmp/ostree-delta-XXXXXX");
|
|
||||||
g_autoptr(GConverter) decomp = (GConverter*) _ostree_lzma_decompressor_new ();
|
g_autoptr(GConverter) decomp = (GConverter*) _ostree_lzma_decompressor_new ();
|
||||||
g_autoptr(GInputStream) convin = g_converter_input_stream_new (source_in, decomp);
|
g_autoptr(GInputStream) convin = g_converter_input_stream_new (source_in, decomp);
|
||||||
g_autoptr(GOutputStream) unpacked_out = NULL;
|
g_autoptr(GBytes) buf = ot_map_anonymous_tmpfile_from_content (convin, cancellable, error);
|
||||||
glnx_fd_close int unpacked_fd = -1;
|
if (!buf)
|
||||||
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)
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!ot_util_variant_map_fd (unpacked_fd, 0, G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
|
ret_part = g_variant_new_from_bytes (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
|
||||||
trusted, &ret_part, error))
|
buf, FALSE);
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include "libglnx.h"
|
#include "libglnx.h"
|
||||||
#include <sys/xattr.h>
|
#include <sys/xattr.h>
|
||||||
#include <gio/gunixinputstream.h>
|
#include <gio/gunixinputstream.h>
|
||||||
|
#include <gio/gunixoutputstream.h>
|
||||||
|
|
||||||
/* Convert a fd-relative path to a GFile* - use
|
/* Convert a fd-relative path to a GFile* - use
|
||||||
* for legacy code.
|
* for legacy code.
|
||||||
|
|
@ -181,3 +182,29 @@ ot_file_mapat_bytes (int dfd,
|
||||||
|
|
||||||
return g_mapped_file_get_bytes (mfile);
|
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);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,11 @@ gboolean ot_dfd_iter_init_allow_noent (int dfd,
|
||||||
gboolean *out_exists,
|
gboolean *out_exists,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
GBytes *
|
||||||
|
ot_map_anonymous_tmpfile_from_content (GInputStream *instream,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
GBytes *ot_file_mapat_bytes (int dfd,
|
GBytes *ot_file_mapat_bytes (int dfd,
|
||||||
const char *path,
|
const char *path,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue