changeset 40160:5c7e0484c1e9

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'.
author Bruno Haible <bruno@clisp.org>
date Sun, 27 Jan 2019 22:03:14 +0100
parents 069b50a66104
children 71ec1d2c1db9
files ChangeLog doc/posix-functions/tmpfile.texi lib/tmpfile.c m4/tmpfile.m4 modules/argv-iter-tests modules/tmpfile
diffstat 6 files changed, 104 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sun Jan 27 18:49:36 2019 +0100
+++ b/ChangeLog	Sun Jan 27 22:03:14 2019 +0100
@@ -1,3 +1,14 @@
+2019-01-27  Bruno Haible  <bruno@clisp.org>
+
+	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'.
+
 2019-01-27  Akim Demaille  <akim@lrde.epita.fr>
 
 	bitsetv: allow free on NULL.
--- a/doc/posix-functions/tmpfile.texi	Sun Jan 27 18:49:36 2019 +0100
+++ b/doc/posix-functions/tmpfile.texi	Sun Jan 27 22:03:14 2019 +0100
@@ -9,6 +9,9 @@
 Portability problems fixed by Gnulib:
 @itemize
 @item
+This function always fails on some platforms:
+Android 4.3.
+@item
 This function often fails for trivial reasons on some platforms:
 mingw, MSVC 14.
 @item
--- a/lib/tmpfile.c	Sun Jan 27 18:49:36 2019 +0100
+++ b/lib/tmpfile.c	Sun Jan 27 22:03:14 2019 +0100
@@ -21,24 +21,36 @@
 /* Specification.  */
 #include <stdio.h>
 
-/* This replacement is used only on native Windows platforms.  */
+#include <stdbool.h>
+
+#if defined _WIN32 && ! defined __CYGWIN__
+/* A native Windows platforms.  */
+
+# include <errno.h>
+# include <fcntl.h>
+# include <string.h>
+# include <sys/stat.h>
 
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/stat.h>
+# include <io.h>
+
+# define WIN32_LEAN_AND_MEAN  /* avoid including junk */
+# include <windows.h>
 
-#include <io.h>
+#else
 
-#define WIN32_LEAN_AND_MEAN  /* avoid including junk */
-#include <windows.h>
+# 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 @@
 
   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
--- a/m4/tmpfile.m4	Sun Jan 27 18:49:36 2019 +0100
+++ b/m4/tmpfile.m4	Sun Jan 27 22:03:14 2019 +0100
@@ -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.
--- a/modules/argv-iter-tests	Sun Jan 27 18:49:36 2019 +0100
+++ b/modules/argv-iter-tests	Sun Jan 27 22:03:14 2019 +0100
@@ -3,6 +3,7 @@
 tests/macros.h
 
 Depends-on:
+tmpfile
 
 configure.ac:
 
--- a/modules/tmpfile	Sun Jan 27 18:49:36 2019 +0100
+++ b/modules/tmpfile	Sun Jan 27 22:03:14 2019 +0100
@@ -9,6 +9,7 @@
 stdio
 largefile
 pathmax         [test $REPLACE_TMPFILE = 1]
+stdbool         [test $REPLACE_TMPFILE = 1]
 tempname        [test $REPLACE_TMPFILE = 1]
 tmpdir          [test $REPLACE_TMPFILE = 1]