diff options
-rw-r--r-- | src/libostree/ostree-repo-commit.c | 41 | ||||
-rw-r--r-- | src/libostree/ostree-repo-pull.c | 8 | ||||
-rw-r--r-- | src/libostree/ostree-repo-static-delta-core.c | 17 | ||||
-rw-r--r-- | src/libostree/ostree-repo.c | 48 | ||||
-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 | ||||
-rw-r--r-- | src/ostree/ot-builtin-show.c | 5 | ||||
-rw-r--r-- | src/ostree/ot-builtin-summary.c | 5 |
10 files changed, 133 insertions, 174 deletions
diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 029dd01b..a9ae4af2 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -2212,26 +2212,29 @@ ostree_repo_read_commit_detached_metadata (OstreeRepo *self, char buf[_OSTREE_LOOSE_PATH_MAX]; _ostree_loose_path (buf, checksum, OSTREE_OBJECT_TYPE_COMMIT_META, self->mode); - g_autoptr(GVariant) ret_metadata = NULL; - if (self->commit_stagedir.initialized && - !ot_util_variant_map_at (self->commit_stagedir.fd, buf, - G_VARIANT_TYPE ("a{sv}"), - OT_VARIANT_MAP_ALLOW_NOENT | OT_VARIANT_MAP_TRUSTED, &ret_metadata, error)) - return glnx_prefix_error (error, "Unable to read existing detached metadata"); - - if (ret_metadata == NULL && - !ot_util_variant_map_at (self->objects_dir_fd, buf, - G_VARIANT_TYPE ("a{sv}"), - OT_VARIANT_MAP_ALLOW_NOENT | OT_VARIANT_MAP_TRUSTED, &ret_metadata, error)) - return glnx_prefix_error (error, "Unable to read existing detached metadata"); - - if (ret_metadata == NULL && self->parent_repo) + if (self->commit_stagedir.initialized) + { + glnx_fd_close int fd = -1; + if (!ot_openat_ignore_enoent (self->commit_stagedir.fd, buf, &fd, error)) + return FALSE; + if (fd != -1) + return ot_variant_read_fd (fd, 0, G_VARIANT_TYPE ("a{sv}"), TRUE, + out_metadata, error); + } + + glnx_fd_close int fd = -1; + if (!ot_openat_ignore_enoent (self->objects_dir_fd, buf, &fd, error)) + return FALSE; + if (fd != -1) + return ot_variant_read_fd (fd, 0, G_VARIANT_TYPE ("a{sv}"), TRUE, + out_metadata, error); + + if (self->parent_repo) return ostree_repo_read_commit_detached_metadata (self->parent_repo, - checksum, - out_metadata, - cancellable, - error); - ot_transfer_out_value (out_metadata, &ret_metadata); + checksum, out_metadata, + cancellable, error); + /* Nothing found */ + *out_metadata = NULL; return TRUE; } diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index a404b8a7..57bb1985 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -1228,8 +1228,8 @@ meta_fetch_on_complete (GObject *object, if (fetch_data->is_detached_meta) { - if (!ot_util_variant_map_fd (fd, 0, G_VARIANT_TYPE ("a{sv}"), - FALSE, &metadata, error)) + if (!ot_variant_read_fd (fd, 0, G_VARIANT_TYPE ("a{sv}"), + FALSE, &metadata, error)) goto out; if (!ostree_repo_write_commit_detached_metadata (pull_data->repo, checksum, metadata, @@ -1245,8 +1245,8 @@ meta_fetch_on_complete (GObject *object, } else { - if (!ot_util_variant_map_fd (fd, 0, ostree_metadata_variant_type (objtype), - FALSE, &metadata, error)) + if (!ot_variant_read_fd (fd, 0, ostree_metadata_variant_type (objtype), + FALSE, &metadata, error)) goto out; /* Write the commitpartial file now while we're still fetching data */ diff --git a/src/libostree/ostree-repo-static-delta-core.c b/src/libostree/ostree-repo-static-delta-core.c index 85952b6a..e5133a2b 100644 --- a/src/libostree/ostree-repo-static-delta-core.c +++ b/src/libostree/ostree-repo-static-delta-core.c @@ -246,8 +246,8 @@ ostree_repo_static_delta_execute_offline (OstreeRepo *self, return glnx_throw_errno_prefix (error, "openat(%s)", basename); g_autoptr(GVariant) meta = NULL; - if (!ot_util_variant_map_fd (meta_fd, 0, G_VARIANT_TYPE (OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT), - FALSE, &meta, error)) + if (!ot_variant_read_fd (meta_fd, 0, G_VARIANT_TYPE (OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT), + FALSE, &meta, error)) return FALSE; /* Parsing OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT */ @@ -448,8 +448,8 @@ _ostree_static_delta_part_open (GInputStream *part_in, int part_fd = g_file_descriptor_based_get_fd ((GFileDescriptorBased*)part_in); /* No compression, no checksums - a fast path */ - if (!ot_util_variant_map_fd (part_fd, 1, G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0), - trusted, &ret_part, error)) + if (!ot_variant_read_fd (part_fd, 1, G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0), + trusted, &ret_part, error)) return FALSE; } else @@ -767,9 +767,12 @@ _ostree_repo_static_delta_dump (OstreeRepo *self, superblock_path = _ostree_get_relative_static_delta_superblock_path (from, to); - if (!ot_util_variant_map_at (self->repo_dir_fd, superblock_path, - (GVariantType*)OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT, - OT_VARIANT_MAP_TRUSTED, &delta_superblock, error)) + glnx_fd_close int superblock_fd = -1; + if (!glnx_openat_rdonly (self->repo_dir_fd, superblock_path, TRUE, &superblock_fd, error)) + return FALSE; + if (!ot_variant_read_fd (superblock_fd, 0, + (GVariantType*)OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT, + TRUE, &delta_superblock, error)) return FALSE; g_print ("Delta: %s\n", delta_id); diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 50829152..4357d562 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -2811,7 +2811,6 @@ load_metadata_internal (OstreeRepo *self, GError **error) { char loose_path_buf[_OSTREE_LOOSE_PATH_MAX]; - struct stat stbuf; glnx_fd_close int fd = -1; g_autoptr(GInputStream) ret_stream = NULL; g_autoptr(GVariant) ret_variant = NULL; @@ -2853,36 +2852,14 @@ load_metadata_internal (OstreeRepo *self, if (fd != -1) { + struct stat stbuf; if (!glnx_fstat (fd, &stbuf, error)) return FALSE; - if (out_variant) { - /* http://stackoverflow.com/questions/258091/when-should-i-use-mmap-for-file-access */ - if (stbuf.st_size > 16*1024) - { - GMappedFile *mfile; - - mfile = g_mapped_file_new_from_fd (fd, FALSE, error); - if (!mfile) - return FALSE; - ret_variant = g_variant_new_from_data (ostree_metadata_variant_type (objtype), - g_mapped_file_get_contents (mfile), - g_mapped_file_get_length (mfile), - TRUE, - (GDestroyNotify) g_mapped_file_unref, - mfile); - g_variant_ref_sink (ret_variant); - } - else - { - g_autoptr(GBytes) data = glnx_fd_readall_bytes (fd, cancellable, error); - if (!data) - return FALSE; - ret_variant = g_variant_new_from_bytes (ostree_metadata_variant_type (objtype), - data, TRUE); - g_variant_ref_sink (ret_variant); - } + if (!ot_variant_read_fd (fd, 0, ostree_metadata_variant_type (objtype), TRUE, + &ret_variant, error)) + return FALSE; /* Now, let's put it in the cache */ if (is_dirmeta_cachable) @@ -4202,15 +4179,24 @@ ostree_repo_add_gpg_signature_summary (OstreeRepo *self, GCancellable *cancellable, GError **error) { - g_autoptr(GBytes) summary_data = ot_file_mapat_bytes (self->repo_dir_fd, "summary", error); + glnx_fd_close int fd = -1; + if (!glnx_openat_rdonly (self->repo_dir_fd, "summary", TRUE, &fd, error)) + return FALSE; + g_autoptr(GBytes) summary_data = ot_fd_readall_or_mmap (fd, 0, error); if (!summary_data) return FALSE; + /* Note that fd is reused below */ + (void) close (glnx_steal_fd (&fd)); g_autoptr(GVariant) existing_signatures = NULL; - if (!ot_util_variant_map_at (self->repo_dir_fd, "summary.sig", - G_VARIANT_TYPE (OSTREE_SUMMARY_SIG_GVARIANT_STRING), - OT_VARIANT_MAP_ALLOW_NOENT, &existing_signatures, error)) + if (!ot_openat_ignore_enoent (self->repo_dir_fd, "summary.sig", &fd, error)) return FALSE; + if (fd != -1) + { + if (!ot_variant_read_fd (fd, 0, G_VARIANT_TYPE (OSTREE_SUMMARY_SIG_GVARIANT_STRING), + FALSE, &existing_signatures, error)) + return FALSE; + } g_autoptr(GVariant) new_metadata = NULL; for (guint i = 0; key_id[i]; i++) 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); diff --git a/src/ostree/ot-builtin-show.c b/src/ostree/ot-builtin-show.c index f197d7c3..3ab56eb2 100644 --- a/src/ostree/ot-builtin-show.c +++ b/src/ostree/ot-builtin-show.c @@ -58,7 +58,10 @@ do_print_variant_generic (const GVariantType *type, { g_autoptr(GVariant) variant = NULL; - if (!ot_util_variant_map_at (AT_FDCWD, filename, type, TRUE, &variant, error)) + glnx_fd_close int fd = -1; + if (!glnx_openat_rdonly (AT_FDCWD, filename, TRUE, &fd, error)) + return FALSE; + if (!ot_variant_read_fd (fd, 0, type, FALSE, &variant, error)) return FALSE; ot_dump_variant (variant); diff --git a/src/ostree/ot-builtin-summary.c b/src/ostree/ot-builtin-summary.c index abd1f86c..ed9e0b3d 100644 --- a/src/ostree/ot-builtin-summary.c +++ b/src/ostree/ot-builtin-summary.c @@ -217,7 +217,10 @@ ostree_builtin_summary (int argc, char **argv, GCancellable *cancellable, GError if (opt_raw) flags |= OSTREE_DUMP_RAW; - summary_data = ot_file_mapat_bytes (repo->repo_dir_fd, "summary", error); + glnx_fd_close int fd = -1; + if (!glnx_openat_rdonly (repo->repo_dir_fd, "summary", TRUE, &fd, error)) + return FALSE; + summary_data = ot_fd_readall_or_mmap (fd, 0, error); if (!summary_data) return FALSE; |