From e5bfdb99b6500daf953e4b6c21a500d175d45052 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 8 Jan 2017 01:32:49 -0800 Subject: [PATCH] Enable mkostemp to be weak-linked mkostemp is not available on some older versions of macOS. In order for our built binaries to run on them, mkostemp must be weak-linked. On other systems, we use the autoconf check. Introduce a function fish_mkstemp_cloexec which uses mkostemp if it was detected and is available at runtime, else falls back to mkstemp. This isolates some logic that is currently duplicated in two places. See #3138 for more on weak linking. --- src/env_universal_common.cpp | 10 +--------- src/fallback.cpp | 14 ++++++++++++++ src/fallback.h | 5 +++++ src/history.cpp | 14 +++----------- 4 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/env_universal_common.cpp b/src/env_universal_common.cpp index d60bb705c..399c6d011 100644 --- a/src/env_universal_common.cpp +++ b/src/env_universal_common.cpp @@ -535,15 +535,7 @@ bool env_universal_t::open_temporary_file(const wcstring &directory, wcstring *o for (size_t attempt = 0; attempt < 10 && !success; attempt++) { char *narrow_str = wcs2str(tmp_name_template.c_str()); -#if HAVE_MKOSTEMP - int result_fd = mkostemp(narrow_str, O_CLOEXEC); -#else - int result_fd = mkstemp(narrow_str); - if (result_fd != -1) { - fcntl(result_fd, F_SETFD, FD_CLOEXEC); - } -#endif - + int result_fd = fish_mkstemp_cloexec(narrow_str); saved_errno = errno; success = result_fd != -1; *out_fd = result_fd; diff --git a/src/fallback.cpp b/src/fallback.cpp index 8abb133c2..757327e31 100644 --- a/src/fallback.cpp +++ b/src/fallback.cpp @@ -91,6 +91,20 @@ char *tparm_solaris_kludge(char *str, ...) { #endif +int fish_mkstemp_cloexec(char *name_template) { +#if HAVE_MKOSTEMP + // null check because mkostemp may be a weak symbol + if (&mkostemp != nullptr) { + return mkostemp(name_template, O_CLOEXEC); + } +#endif + int result_fd = mkstemp(name_template); + if (result_fd != -1) { + fcntl(result_fd, F_SETFD, FD_CLOEXEC); + } + return result_fd; +} + /// Fallback implementations of wcsdup and wcscasecmp. On systems where these are not needed (e.g. /// building on Linux) these should end up just being stripped, as they are static functions that /// are not referenced in this file. diff --git a/src/fallback.h b/src/fallback.h index 5a808834a..cb5775c35 100644 --- a/src/fallback.h +++ b/src/fallback.h @@ -23,6 +23,11 @@ int fish_wcwidth(wchar_t wc); int fish_wcswidth(const wchar_t *str, size_t n); +// Replacement for mkostemp(str, O_CLOEXEC) +// This uses mkostemp if available, +// otherwise it uses mkstemp followed by fcntl +int fish_mkstemp_cloexec(char *); + #ifndef WCHAR_MAX /// This _should_ be defined by wchar.h, but e.g. OpenBSD doesn't. #define WCHAR_MAX INT_MAX diff --git a/src/history.cpp b/src/history.cpp index 2eb7c311a..a3e326976 100644 --- a/src/history.cpp +++ b/src/history.cpp @@ -1230,24 +1230,16 @@ bool history_t::save_internal_via_rewrite() { signal_block(); - // Try to create a temporary file, up to 10 times. We don't use mkstemps because we want to - // open it CLO_EXEC. This should almost always succeed on the first try. + // Try to create a CLO_EXEC temporary file, up to 10 times. + // This should almost always succeed on the first try. int out_fd = -1; wcstring tmp_name; for (size_t attempt = 0; attempt < 10 && out_fd == -1; attempt++) { char *narrow_str = wcs2str(tmp_name_template.c_str()); -#if HAVE_MKOSTEMP - out_fd = mkostemp(narrow_str, O_CLOEXEC); + out_fd = fish_mkstemp_cloexec(narrow_str); if (out_fd >= 0) { tmp_name = str2wcstring(narrow_str); } -#else - if (narrow_str && mktemp(narrow_str)) { - // It was successfully templated; try opening it atomically. - tmp_name = str2wcstring(narrow_str); - out_fd = wopen_cloexec(tmp_name, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, 0600); - } -#endif free(narrow_str); }