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
This commit is contained in:
Colin Walters authored and Atomic Bot committed 2017-10-04 20:42:39 +00:00
1 parent c511ca0fae
commit 5c7d2dd8be
10 files changed
+131 -172

No files matched your search

+6 -18
View File
@@ -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);