From 05abf2143f967cd85b1b1b777ee412a581979cf1 Mon Sep 17 00:00:00 2001
From: Colin Walters <walters@verbum.org>
Date: Mon, 12 Jun 2017 17:00:53 -0400
Subject: [PATCH] fdio: Add glnx_try_fallocate()

The glibc `posix_fallocate()` implementation has a bad fallback,
and further we need to handle `EOPNOTSUPP` for musl.
https://github.com/flatpak/flatpak/issues/802
---
 glnx-fdio.c | 13 ++-----------
 glnx-fdio.h | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+), 11 deletions(-)

diff --git a/glnx-fdio.c b/glnx-fdio.c
index 19de9ec21..87e2dbb98 100644
--- a/glnx-fdio.c
+++ b/glnx-fdio.c
@@ -920,7 +920,6 @@ glnx_file_replace_contents_with_perms_at (int                   dfd,
                                           GCancellable         *cancellable,
                                           GError              **error)
 {
-  int r;
   char *dnbuf = strdupa (subpath);
   const char *dn = dirname (dnbuf);
 
@@ -940,16 +939,8 @@ glnx_file_replace_contents_with_perms_at (int                   dfd,
   if (len == -1)
     len = strlen ((char*)buf);
 
-  /* Note that posix_fallocate does *not* set errno but returns it. */
-  if (len > 0)
-    {
-      r = posix_fallocate (tmpf.fd, 0, len);
-      if (r != 0)
-        {
-          errno = r;
-          return glnx_throw_errno_prefix (error, "fallocate");
-        }
-    }
+  if (!glnx_try_fallocate (tmpf.fd, 0, len, error))
+    return FALSE;
 
   if (glnx_loop_write (tmpf.fd, buf, len) < 0)
     return glnx_throw_errno (error);
diff --git a/glnx-fdio.h b/glnx-fdio.h
index dda32d1a7..e52c82377 100644
--- a/glnx-fdio.h
+++ b/glnx-fdio.h
@@ -166,6 +166,38 @@ int glnx_renameat2_noreplace (int olddirfd, const char *oldpath,
 int glnx_renameat2_exchange (int olddirfd, const char *oldpath,
                              int newdirfd, const char *newpath);
 
+/**
+ * glnx_try_fallocate:
+ * @fd: File descriptor
+ * @size: Size
+ * @error: Error
+ *
+ * Wrapper for Linux fallocate().  Explicitly ignores a @size of zero.
+ * Also, will silently do nothing if the underlying filesystem doesn't
+ * support it.  Use this instead of posix_fallocate(), since the glibc fallback
+ * is bad: https://sourceware.org/bugzilla/show_bug.cgi?id=18515
+ */
+static inline gboolean
+glnx_try_fallocate (int      fd,
+                    off_t    offset,
+                    off_t    size,
+                    GError **error)
+{
+  /* This is just nicer than throwing an error */
+  if (size == 0)
+    return TRUE;
+
+  if (fallocate (fd, 0, offset, size) < 0)
+    {
+      if (errno == ENOSYS || errno == EOPNOTSUPP)
+        ; /* Ignore */
+      else
+        return glnx_throw_errno_prefix (error, "fallocate");
+    }
+
+  return TRUE;
+}
+
 /**
  * glnx_fstat:
  * @fd: FD to stat
-- 
GitLab