bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

tmpfile: Add support for Android


From: Bruno Haible
Subject: tmpfile: Add support for Android
Date: Sun, 27 Jan 2019 22:10:46 +0100
User-agent: KMail/5.1.3 (Linux/4.4.0-141-generic; KDE/5.18.0; x86_64; ; )

On Android 4.3, I'm seeing this test failure:

FAIL: test-argv-iter
====================

../../gltests/test-argv-iter.c:35: assertion 'fp' failed
FAIL test-argv-iter (exit status: 139)


The cause is that tmpfile() returns NULL, because /tmp does not exist.
This patch fixes it (borrowing code from glibc/stdio-common/tmpfile.c).


2019-01-27  Bruno Haible  <address@hidden>

        tmpfile: Add support for Android.
        * m4/tmpfile.m4 (gl_FUNC_TMPFILE): Add a runtime test whether tmpfile()
        works.
        * lib/tmpfile.c (tmpfile): Add an alternative implementation for
        Android.
        * modules/tmpfile (Depends-on): Add 'stdbool'.
        * doc/posix-functions/tmpfile.texi: Mention the Android bug.
        * modules/argv-iter-tests (Depends-on): Add 'tmpfile'.

diff --git a/doc/posix-functions/tmpfile.texi b/doc/posix-functions/tmpfile.texi
index c5510af..2792458 100644
--- a/doc/posix-functions/tmpfile.texi
+++ b/doc/posix-functions/tmpfile.texi
@@ -9,6 +9,9 @@ Gnulib module: tmpfile
 Portability problems fixed by Gnulib:
 @itemize
 @item
+This function always fails on some platforms:
+Android 4.3.
address@hidden
 This function often fails for trivial reasons on some platforms:
 mingw, MSVC 14.
 @item
diff --git a/lib/tmpfile.c b/lib/tmpfile.c
index 1a6cef7..45d652d 100644
--- a/lib/tmpfile.c
+++ b/lib/tmpfile.c
@@ -21,24 +21,36 @@
 /* Specification.  */
 #include <stdio.h>
 
-/* This replacement is used only on native Windows platforms.  */
+#include <stdbool.h>
 
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/stat.h>
+#if defined _WIN32 && ! defined __CYGWIN__
+/* A native Windows platforms.  */
 
-#include <io.h>
+# include <errno.h>
+# include <fcntl.h>
+# include <string.h>
+# include <sys/stat.h>
 
-#define WIN32_LEAN_AND_MEAN  /* avoid including junk */
-#include <windows.h>
+# include <io.h>
+
+# define WIN32_LEAN_AND_MEAN  /* avoid including junk */
+# include <windows.h>
+
+#else
+
+# include <unistd.h>
+
+#endif
 
 #include "pathmax.h"
 #include "tempname.h"
 #include "tmpdir.h"
 
 /* PATH_MAX is guaranteed to be defined, because this replacement is only
-   used on native Windows.  */
+   used on native Windows and Android.  */
+
+#if defined _WIN32 && ! defined __CYGWIN__
+/* A native Windows platforms.  */
 
 /* On Windows, opening a file with _O_TEMPORARY has the effect of passing
    the FILE_FLAG_DELETE_ON_CLOSE flag to CreateFile(), which has the effect
@@ -130,3 +142,38 @@ tmpfile (void)
 
   return NULL;
 }
+
+#else
+
+FILE *
+tmpfile (void)
+{
+  char buf[PATH_MAX];
+  int fd;
+  FILE *fp;
+
+  /* Try $TMPDIR first, not /tmp nor P_tmpdir, because we need this replacement
+     on Android, and /tmp does not exist on Android.  */
+
+  if (path_search (buf, sizeof buf, NULL, "tmpf", true))
+    return NULL;
+
+  fd = gen_tempname (buf, 0, 0, GT_FILE);
+  if (fd < 0)
+    return NULL;
+
+  /* Note that this relies on the Unix semantics that
+     a file is not really removed until it is closed.  */
+  (void) unlink (buf);
+
+  if ((fp = fdopen (fd, "w+b")) == NULL)
+    {
+      int saved_errno = errno;
+      close (fd);
+      errno = saved_errno;
+    }
+
+  return fp;
+}
+
+#endif
diff --git a/m4/tmpfile.m4 b/m4/tmpfile.m4
index faef23e..e648d37 100644
--- a/m4/tmpfile.m4
+++ b/m4/tmpfile.m4
@@ -1,4 +1,4 @@
-# tmpfile.m4 serial 3
+# tmpfile.m4 serial 4
 # Copyright (C) 2007, 2009-2019 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -18,20 +18,44 @@
 # directory, even though tmpfile wouldn't work in general.  Instead,
 # just test for a Windows platform (excluding Cygwin).
 
+# On Android 4.3, tmpfile() always returns NULL, even if TMPDIR is set
+# to a writable directory.
+
 AC_DEFUN([gl_FUNC_TMPFILE], [
   AC_REQUIRE([gl_STDIO_H_DEFAULTS])
-  AC_CACHE_CHECK([whether tmpfile should be overridden],
-    [gl_cv_func_tmpfile_unusable],
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether tmpfile works],
+    [gl_cv_func_tmpfile_works],
     [AC_EGREP_CPP([choke me], [
 #if defined _WIN32 && !defined __CYGWIN__
 choke me
 #endif
        ],
-       [gl_cv_func_tmpfile_unusable=yes],
-       [gl_cv_func_tmpfile_unusable=no])])
-  if test $gl_cv_func_tmpfile_unusable = yes; then
-    REPLACE_TMPFILE=1
-  fi
+       [gl_cv_func_tmpfile_works=no],
+       [AC_RUN_IFELSE(
+          [AC_LANG_SOURCE([[
+#include <stdio.h>
+#include <stdlib.h>
+int
+main (void)
+{
+  return tmpfile () == NULL;
+}]])],
+          [gl_cv_func_tmpfile_works=yes],
+          [gl_cv_func_tmpfile_works=no],
+          [case "$host_os" in
+                              # Guess no on Android.
+             linux*-android*) gl_cv_func_tmpfile_works="guessing no" ;;
+                              # Guess yes otherwise.
+             *)               gl_cv_func_tmpfile_works="guessing yes" ;;
+           esac
+          ])
+       ])
+    ])
+  case "$gl_cv_func_tmpfile_works" in
+    *yes) ;;
+    *) REPLACE_TMPFILE=1 ;;
+  esac
 ])
 
 # Prerequisites of lib/tmpfile.c.
diff --git a/modules/argv-iter-tests b/modules/argv-iter-tests
index 92c5c82..f32587e 100644
--- a/modules/argv-iter-tests
+++ b/modules/argv-iter-tests
@@ -3,6 +3,7 @@ tests/test-argv-iter.c
 tests/macros.h
 
 Depends-on:
+tmpfile
 
 configure.ac:
 
diff --git a/modules/tmpfile b/modules/tmpfile
index e98a8ee..884f284 100644
--- a/modules/tmpfile
+++ b/modules/tmpfile
@@ -9,6 +9,7 @@ Depends-on:
 stdio
 largefile
 pathmax         [test $REPLACE_TMPFILE = 1]
+stdbool         [test $REPLACE_TMPFILE = 1]
 tempname        [test $REPLACE_TMPFILE = 1]
 tmpdir          [test $REPLACE_TMPFILE = 1]
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]