diff options
author | Colin Walters <walters@verbum.org> | 2017-10-04 15:06:31 -0400 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2017-10-04 20:42:39 +0000 |
commit | 5c7d2dd8be3606d9aec1e6835086f6b4dfcdb6a7 (patch) | |
tree | f796da733316a3dc1b36779d889140a624ed50df /src/libostree/ostree-repo-commit.c | |
parent | c511ca0fae0e352d52bb7d1a24b4c1d08c5a8ec9 (diff) | |
download | ostree-5c7d2dd8be3606d9aec1e6835086f6b4dfcdb6a7.tar.gz |
Deduplicate and fix up our use of mmap()
Buried in this large patch is a logical fix:
```
- if (!map)
- return glnx_throw_errno_prefix (error, "mmap");
+ if (map == (void*)-1)
+ return glnx_null_throw_errno_prefix (error, "mmap");
```
Which would have helped me debug another patch I was working
on. But it turns out that actually correctly checking for
errors from `mmap()` triggers lots of other bugs - basically
because we sometimes handle zero-length variants (in detached
metadata). When we start actually returning errors due to
this, things break. (It wasn't a problem in practice before
because most things looked at the zero size, not the data).
Anyways there's a bigger picture issue here - a while ago
we made a fix to only use `mmap()` for reading metadata from disk
only if it was large enough (i.e. `>16k`). But that didn't
help various other paths in the pull code and others that were
directly doing the `mmap()`.
Fix this by having a proper low level fs helper that does "read all data from
fd+offset into GBytes", which handles the size check. Then the `GVariant` bits
are just a clean layer on top of this. (At the small cost of an additional
allocation)
Side note: I had to remind myself, but the reason we can't just use
`GMappedFile` here is it doesn't support passing an offset into `mmap()`.
Closes: #1251
Approved by: jlebon
Diffstat (limited to 'src/libostree/ostree-repo-commit.c')
-rw-r--r-- | src/libostree/ostree-repo-commit.c | 41 |
1 files changed, 22 insertions, 19 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; } |