diff options
Diffstat (limited to 'src/libotutil')
-rw-r--r-- | src/libotutil/ot-fs-utils.c | 60 | ||||
-rw-r--r-- | src/libotutil/ot-fs-utils.h | 5 | ||||
-rw-r--r-- | src/libotutil/ot-variant-utils.c | 94 | ||||
-rw-r--r-- | src/libotutil/ot-variant-utils.h | 24 |
4 files changed, 72 insertions, 111 deletions
diff --git a/src/libotutil/ot-fs-utils.c b/src/libotutil/ot-fs-utils.c index 253de5b3..79ba3cf7 100644 --- a/src/libotutil/ot-fs-utils.c +++ b/src/libotutil/ot-fs-utils.c @@ -22,6 +22,7 @@ #include "ot-fs-utils.h" #include "libglnx.h" #include <sys/xattr.h> +#include <sys/mman.h> #include <gio/gunixinputstream.h> #include <gio/gunixoutputstream.h> @@ -144,22 +145,57 @@ ot_dfd_iter_init_allow_noent (int dfd, return TRUE; } -GBytes * -ot_file_mapat_bytes (int dfd, - const char *path, - GError **error) -{ - glnx_fd_close int fd = openat (dfd, path, O_RDONLY | O_CLOEXEC); - g_autoptr(GMappedFile) mfile = NULL; +typedef struct { + gpointer addr; + gsize len; +} MapData; - if (fd < 0) - return glnx_null_throw_errno_prefix (error, "openat(%s)", path); +static void +map_data_destroy (gpointer data) +{ + MapData *mdata = data; + (void) munmap (mdata->addr, mdata->len); + g_free (mdata); +} - mfile = g_mapped_file_new_from_fd (fd, FALSE, error); - if (!mfile) +/* Return a newly-allocated GBytes that refers to the contents of the file + * starting at offset @start. If the file is large enough, mmap() may be used. + */ +GBytes * +ot_fd_readall_or_mmap (int fd, + goffset start, + GError **error) +{ + struct stat stbuf; + if (!glnx_fstat (fd, &stbuf, error)) return FALSE; - return g_mapped_file_get_bytes (mfile); + /* http://stackoverflow.com/questions/258091/when-should-i-use-mmap-for-file-access */ + if (start > stbuf.st_size) + return g_bytes_new_static (NULL, 0); + const gsize len = stbuf.st_size - start; + if (len > 16*1024) + { + /* The reason we don't use g_mapped_file_new_from_fd() here + * is it doesn't support passing an offset, which is actually + * used by the static delta code. + */ + gpointer map = mmap (NULL, len, PROT_READ, MAP_PRIVATE, fd, start); + if (map == (void*)-1) + return glnx_null_throw_errno_prefix (error, "mmap"); + + MapData *mdata = g_new (MapData, 1); + mdata->addr = map; + mdata->len = len; + + return g_bytes_new_with_free_func (map, len, map_data_destroy, mdata); + } + + /* Fall through to plain read into a malloc buffer */ + if (lseek (fd, start, SEEK_SET) < 0) + return glnx_null_throw_errno_prefix (error, "lseek"); + /* Not cancellable since this should be small */ + return glnx_fd_readall_bytes (fd, NULL, error); } /* Given an input stream, splice it to an anonymous file (O_TMPFILE). diff --git a/src/libotutil/ot-fs-utils.h b/src/libotutil/ot-fs-utils.h index 98fcd6a2..7eb811cd 100644 --- a/src/libotutil/ot-fs-utils.h +++ b/src/libotutil/ot-fs-utils.h @@ -85,8 +85,7 @@ ot_map_anonymous_tmpfile_from_content (GInputStream *instream, GCancellable *cancellable, GError **error); -GBytes *ot_file_mapat_bytes (int dfd, - const char *path, - GError **error); +GBytes *ot_fd_readall_or_mmap (int fd, goffset offset, + GError **error); G_END_DECLS diff --git a/src/libotutil/ot-variant-utils.c b/src/libotutil/ot-variant-utils.c index d1981c8b..d4ae7d9d 100644 --- a/src/libotutil/ot-variant-utils.c +++ b/src/libotutil/ot-variant-utils.c @@ -25,7 +25,6 @@ #include <gio/gfiledescriptorbased.h> #include <string.h> -#include <sys/mman.h> #include "otutil.h" @@ -85,86 +84,25 @@ ot_util_variant_take_ref (GVariant *variant) return g_variant_take_ref (variant); } +/* Create a GVariant in @out_variant that is backed by + * the data from @fd, starting at @start. If the data is + * large enough, mmap() may be used. @trusted is used + * by the GVariant core; see g_variant_new_from_data(). + */ gboolean -ot_util_variant_map_at (int dfd, - const char *path, - const GVariantType *type, - OtVariantMapFlags flags, - GVariant **out_variant, - GError **error) -{ - glnx_fd_close int fd = -1; - const gboolean trusted = (flags & OT_VARIANT_MAP_TRUSTED) > 0; - - fd = openat (dfd, path, O_RDONLY | O_CLOEXEC); - if (fd < 0) - { - if (errno == ENOENT && (flags & OT_VARIANT_MAP_ALLOW_NOENT) > 0) - { - *out_variant = NULL; - return TRUE; - } - else - { - glnx_set_error_from_errno (error); - g_prefix_error (error, "Opening %s: ", path); - return FALSE; - } - } - - return ot_util_variant_map_fd (fd, 0, type, trusted, out_variant, error); -} - -typedef struct { - gpointer addr; - gsize len; -} VariantMapData; - -static void -variant_map_data_destroy (gpointer data) -{ - VariantMapData *mdata = data; - (void) munmap (mdata->addr, mdata->len); - g_free (mdata); -} - -gboolean -ot_util_variant_map_fd (int fd, - goffset start, - const GVariantType *type, - gboolean trusted, - GVariant **out_variant, - GError **error) +ot_variant_read_fd (int fd, + goffset start, + const GVariantType *type, + gboolean trusted, + GVariant **out_variant, + GError **error) { - gboolean ret = FALSE; - gpointer map; - struct stat stbuf; - VariantMapData *mdata = NULL; - gsize len; - - if (fstat (fd, &stbuf) != 0) - { - glnx_set_error_from_errno (error); - goto out; - } - - len = stbuf.st_size - start; - map = mmap (NULL, len, PROT_READ, MAP_PRIVATE, fd, start); - if (!map) - { - glnx_set_error_from_errno (error); - goto out; - } - - mdata = g_new (VariantMapData, 1); - mdata->addr = map; - mdata->len = len; + g_autoptr(GBytes) bytes = ot_fd_readall_or_mmap (fd, start, error); + if (!bytes) + return FALSE; - ret = TRUE; - *out_variant = g_variant_ref_sink (g_variant_new_from_data (type, map, len, trusted, - variant_map_data_destroy, mdata)); - out: - return ret; + *out_variant = g_variant_ref_sink (g_variant_new_from_bytes (type, bytes, trusted)); + return TRUE; } GInputStream * diff --git a/src/libotutil/ot-variant-utils.h b/src/libotutil/ot-variant-utils.h index 135ae5d0..379e19ac 100644 --- a/src/libotutil/ot-variant-utils.h +++ b/src/libotutil/ot-variant-utils.h @@ -36,24 +36,12 @@ GHashTable *ot_util_variant_asv_to_hash_table (GVariant *variant); GVariant * ot_util_variant_take_ref (GVariant *variant); -typedef enum { - OT_VARIANT_MAP_TRUSTED = (1 << 0), - OT_VARIANT_MAP_ALLOW_NOENT = (1 << 1) -} OtVariantMapFlags; - -gboolean ot_util_variant_map_at (int dfd, - const char *path, - const GVariantType *type, - OtVariantMapFlags flags, - GVariant **out_variant, - GError **error); - -gboolean ot_util_variant_map_fd (int fd, - goffset offset, - const GVariantType *type, - gboolean trusted, - GVariant **out_variant, - GError **error); +gboolean ot_variant_read_fd (int fd, + goffset offset, + const GVariantType *type, + gboolean trusted, + GVariant **out_variant, + GError **error); GInputStream *ot_variant_read (GVariant *variant); |