>From f530e59fd363722a7a4fa9fd60b2da2241c1a9fc Mon Sep 17 00:00:00 2001
From: Yclept Nemo <pscjtwjdjtAhnbjm/dpn>
Date: Wed, 20 May 2015 23:18:15 -0400
Subject: [PATCH] Workaround: open() ignores 'mode' with O_TMPFILE

---
 configure.ac                   | 51
++++++++++++++++++++++++++++++++++++++++++
 src/fs/io/FileOutputStream.cxx |  8 ++-----
 src/system/FileDescriptor.cxx  |  4 ++++
 src/system/FileDescriptor.hxx  |  9 ++++++++
 4 files changed, 66 insertions(+), 6 deletions(-)

diff --git a/configure.ac b/configure.ac
index 82f814d..ed76f51 100644
--- a/configure.ac
+++ b/configure.ac
@@ -561,6 +561,57 @@ if test x$enable_largefile != xno; then
 fi

 dnl
---------------------------------------------------------------------------
+dnl LIBC Workarounds
+dnl
---------------------------------------------------------------------------
+if test "x$host_is_linux" = xyes && test "x$ac_cv_func_linkat" = xyes &&
test "x$enable_largefile" != xno; then
+    AC_MSG_CHECKING( [if O_TMPFILE requires fchmod])
+    AC_RUN_IFELSE(
+          [AC_LANG_PROGRAM(
+              [[#define _FILE_OFFSET_BITS 64
+                #include <fcntl.h>
+                #include <limits.h>
+                #include <sys/types.h>
+                #include <sys/stat.h>
+              ]]
+            , [[struct stat statbuf;
+                int fd;
+                int mode = 0666;
+                if ((fd = open(".", O_TMPFILE|O_WRONLY, mode)) < 0)
+                    return 1;
+                if (fstat(fd, &statbuf) < 0)
+                    return 1;
+                if (close(fd) < 0)
+                    return 1;
+                if ((statbuf.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != mode)
+                    return 1;
+                return 0;
+              ]]
+            )
+          ]
+        , open_tmpfile_fchmod=no
+        , open_tmpfile_fchmod=yes
+        , open_tmpfile_fchmod=yes
+        )
+    if test "x$open_tmpfile_fchmod" = xyes; then
+        AC_MSG_RESULT([yes])
+        AC_CHECK_FUNCS(
+              [fchmod]
+            , [ AC_DEFINE([OPEN_TMPFILE_FCHMOD],
+                          [1],
+                          [Workaround: _LARGE_FILE + O_TMPFILE -> mode ==
0])
+                AC_MSG_NOTICE([Enabling open/tmpfile workaround using
fchmod])
+              ]
+            , [ AC_DEFINE([HAVE_LINKAT],
+                          [0])
+                AC_MSG_NOTICE([Disabling linkat support])
+              ]
+            )
+    else
+        AC_MSG_RESULT([no])
+    fi
+fi
+
+dnl
---------------------------------------------------------------------------
 dnl Miscellaneous Libraries
 dnl
---------------------------------------------------------------------------

diff --git a/src/fs/io/FileOutputStream.cxx b/src/fs/io/FileOutputStream.cxx
index a4ef8f6..6451b8c 100644
--- a/src/fs/io/FileOutputStream.cxx
+++ b/src/fs/io/FileOutputStream.cxx
@@ -106,13 +106,10 @@ FileOutputStream::Cancel()
 #include <errno.h>

 #ifdef HAVE_LINKAT
-#ifndef O_TMPFILE
-/* supported since Linux 3.11 */
-#define __O_TMPFILE 020000000
-#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
 #include <stdio.h>
 #endif

+#ifdef HAVE_LINKAT
 /**
  * Open a file using Linux's O_TMPFILE for writing the given file.
  */
@@ -125,8 +122,7 @@ OpenTempFile(FileDescriptor &fd, Path path)

     return fd.Open(directory.c_str(), O_TMPFILE|O_WRONLY, 0666);
 }
-
-#endif /* HAVE_LINKAT */
+#endif

 FileOutputStream::FileOutputStream(Path _path, Error &error)
     :BaseFileOutputStream(_path)
diff --git a/src/system/FileDescriptor.cxx b/src/system/FileDescriptor.cxx
index db258e1..f30c9c2 100644
--- a/src/system/FileDescriptor.cxx
+++ b/src/system/FileDescriptor.cxx
@@ -61,6 +61,10 @@ bool
 FileDescriptor::Open(const char *pathname, int flags, mode_t mode)
 {
     fd = ::open(pathname, flags | O_NOCTTY | O_CLOEXEC, mode);
+#ifdef OPEN_TMPFILE_FCHMOD
+    if ((flags & O_TMPFILE) && IsDefined())
+        fchmod(fd, mode);
+#endif
     return IsDefined();
 }

diff --git a/src/system/FileDescriptor.hxx b/src/system/FileDescriptor.hxx
index 75a7684..43cb857 100644
--- a/src/system/FileDescriptor.hxx
+++ b/src/system/FileDescriptor.hxx
@@ -36,11 +36,20 @@
 #include <assert.h>
 #include <unistd.h>
 #include <sys/types.h>
+#include <fcntl.h>

 #ifdef USE_SIGNALFD
 #include <signal.h>
 #endif

+#ifdef HAVE_LINKAT
+#ifndef O_TMPFILE
+/* supported since Linux 3.11 */
+#define __O_TMPFILE 020000000
+#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
+#endif
+#endif
+
 /**
  * An OO wrapper for a UNIX file descriptor.
  *
-- 
2.1.4
From f530e59fd363722a7a4fa9fd60b2da2241c1a9fc Mon Sep 17 00:00:00 2001
From: Yclept Nemo <pscjtwjdjtAhnbjm/dpn>
Date: Wed, 20 May 2015 23:18:15 -0400
Subject: [PATCH] Workaround: open() ignores 'mode' with O_TMPFILE

---
 configure.ac                   | 51 ++++++++++++++++++++++++++++++++++++++++++
 src/fs/io/FileOutputStream.cxx |  8 ++-----
 src/system/FileDescriptor.cxx  |  4 ++++
 src/system/FileDescriptor.hxx  |  9 ++++++++
 4 files changed, 66 insertions(+), 6 deletions(-)

diff --git a/configure.ac b/configure.ac
index 82f814d..ed76f51 100644
--- a/configure.ac
+++ b/configure.ac
@@ -561,6 +561,57 @@ if test x$enable_largefile != xno; then
 fi
 
 dnl ---------------------------------------------------------------------------
+dnl LIBC Workarounds
+dnl ---------------------------------------------------------------------------
+if test "x$host_is_linux" = xyes && test "x$ac_cv_func_linkat" = xyes && test "x$enable_largefile" != xno; then
+    AC_MSG_CHECKING( [if O_TMPFILE requires fchmod])
+    AC_RUN_IFELSE(
+          [AC_LANG_PROGRAM(
+              [[#define _FILE_OFFSET_BITS 64
+                #include <fcntl.h>
+                #include <limits.h>
+                #include <sys/types.h>
+                #include <sys/stat.h>
+              ]]  
+            , [[struct stat statbuf;
+                int fd;
+                int mode = 0666;
+                if ((fd = open(".", O_TMPFILE|O_WRONLY, mode)) < 0)
+                    return 1;
+                if (fstat(fd, &statbuf) < 0)
+                    return 1;
+                if (close(fd) < 0)
+                    return 1;
+                if ((statbuf.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != mode)
+                    return 1;
+                return 0;
+              ]]
+            )
+          ]
+        , open_tmpfile_fchmod=no
+        , open_tmpfile_fchmod=yes
+        , open_tmpfile_fchmod=yes
+        )
+    if test "x$open_tmpfile_fchmod" = xyes; then
+        AC_MSG_RESULT([yes])
+        AC_CHECK_FUNCS(
+              [fchmod]
+            , [ AC_DEFINE([OPEN_TMPFILE_FCHMOD],
+                          [1],
+                          [Workaround: _LARGE_FILE + O_TMPFILE -> mode == 0])
+                AC_MSG_NOTICE([Enabling open/tmpfile workaround using fchmod])
+              ]
+            , [ AC_DEFINE([HAVE_LINKAT],
+                          [0])
+                AC_MSG_NOTICE([Disabling linkat support])
+              ]
+            )
+    else
+        AC_MSG_RESULT([no])
+    fi
+fi
+
+dnl ---------------------------------------------------------------------------
 dnl Miscellaneous Libraries
 dnl ---------------------------------------------------------------------------
 
diff --git a/src/fs/io/FileOutputStream.cxx b/src/fs/io/FileOutputStream.cxx
index a4ef8f6..6451b8c 100644
--- a/src/fs/io/FileOutputStream.cxx
+++ b/src/fs/io/FileOutputStream.cxx
@@ -106,13 +106,10 @@ FileOutputStream::Cancel()
 #include <errno.h>
 
 #ifdef HAVE_LINKAT
-#ifndef O_TMPFILE
-/* supported since Linux 3.11 */
-#define __O_TMPFILE 020000000
-#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
 #include <stdio.h>
 #endif
 
+#ifdef HAVE_LINKAT
 /**
  * Open a file using Linux's O_TMPFILE for writing the given file.
  */
@@ -125,8 +122,7 @@ OpenTempFile(FileDescriptor &fd, Path path)
 
 	return fd.Open(directory.c_str(), O_TMPFILE|O_WRONLY, 0666);
 }
-
-#endif /* HAVE_LINKAT */
+#endif
 
 FileOutputStream::FileOutputStream(Path _path, Error &error)
 	:BaseFileOutputStream(_path)
diff --git a/src/system/FileDescriptor.cxx b/src/system/FileDescriptor.cxx
index db258e1..f30c9c2 100644
--- a/src/system/FileDescriptor.cxx
+++ b/src/system/FileDescriptor.cxx
@@ -61,6 +61,10 @@ bool
 FileDescriptor::Open(const char *pathname, int flags, mode_t mode)
 {
 	fd = ::open(pathname, flags | O_NOCTTY | O_CLOEXEC, mode);
+#ifdef OPEN_TMPFILE_FCHMOD
+    if ((flags & O_TMPFILE) && IsDefined())
+        fchmod(fd, mode);
+#endif
 	return IsDefined();
 }
 
diff --git a/src/system/FileDescriptor.hxx b/src/system/FileDescriptor.hxx
index 75a7684..43cb857 100644
--- a/src/system/FileDescriptor.hxx
+++ b/src/system/FileDescriptor.hxx
@@ -36,11 +36,20 @@
 #include <assert.h>
 #include <unistd.h>
 #include <sys/types.h>
+#include <fcntl.h>
 
 #ifdef USE_SIGNALFD
 #include <signal.h>
 #endif
 
+#ifdef HAVE_LINKAT
+#ifndef O_TMPFILE
+/* supported since Linux 3.11 */
+#define __O_TMPFILE 020000000
+#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
+#endif
+#endif
+
 /**
  * An OO wrapper for a UNIX file descriptor.
  *
-- 
2.1.4

_______________________________________________
mpd-devel mailing list
[email protected]
http://mailman.blarg.de/listinfo/mpd-devel

Reply via email to