summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-05-07 18:37:03 +0200
committerBram Moolenaar <Bram@vim.org>2020-05-07 18:37:03 +0200
commitb2d0e51366dea6843f991f31a457f5456d162678 (patch)
treec220d988cb585427bf0e4eae0fc648ec3d0524d5
parent4a070cc82e00618db279526797564cb2b4e9b060 (diff)
downloadvim-git-b2d0e51366dea6843f991f31a457f5456d162678.tar.gz
patch 8.2.0711: temp directory might be clearedv8.2.0711
Problem: With a long running Vim the temp directory might be cleared on some systems. Solution: Lock the temp directory. (closes #6044)
-rwxr-xr-xsrc/auto/configure47
-rw-r--r--src/config.h.in6
-rw-r--r--src/configure.ac15
-rw-r--r--src/fileio.c42
-rw-r--r--src/globals.h3
-rw-r--r--src/os_unix.h4
-rw-r--r--src/version.c2
7 files changed, 119 insertions, 0 deletions
diff --git a/src/auto/configure b/src/auto/configure
index 6087e0e5a..659ef82c9 100755
--- a/src/auto/configure
+++ b/src/auto/configure
@@ -13823,6 +13823,53 @@ fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dirfd" >&5
+$as_echo_n "checking for dirfd... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <dirent.h>
+int
+main ()
+{
+DIR * dir=opendir("dirname"); dirfd(dir);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }; $as_echo "#define HAVE_DIRFD 1" >>confdefs.h
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not usable" >&5
+$as_echo "not usable" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for flock" >&5
+$as_echo_n "checking for flock... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/file.h>
+int
+main ()
+{
+flock(10, LOCK_SH);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }; $as_echo "#define HAVE_FLOCK 1" >>confdefs.h
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not usable" >&5
+$as_echo "not usable" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysctl" >&5
$as_echo_n "checking for sysctl... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
diff --git a/src/config.h.in b/src/config.h.in
index de53ffb03..5c8c7e556 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -484,5 +484,11 @@
/* Define if we have isnan() */
#undef HAVE_ISNAN
+/* Define if we have dirfd() */
+#undef HAVE_DIRFD
+
+/* Define if we have flock() */
+#undef HAVE_FLOCK
+
/* Define to inline symbol or empty */
#undef inline
diff --git a/src/configure.ac b/src/configure.ac
index 687bdf95d..8751b2e63 100644
--- a/src/configure.ac
+++ b/src/configure.ac
@@ -4060,6 +4060,21 @@ AC_TRY_LINK([#include <stdio.h>], [rename("this", "that")],
AC_MSG_RESULT(yes); AC_DEFINE(HAVE_RENAME),
AC_MSG_RESULT(no))
+dnl check for dirfd()
+AC_MSG_CHECKING(for dirfd)
+AC_TRY_COMPILE(
+[#include <sys/types.h>
+#include <dirent.h>],
+[DIR * dir=opendir("dirname"); dirfd(dir);],
+AC_MSG_RESULT(yes); AC_DEFINE(HAVE_DIRFD), AC_MSG_RESULT(not usable))
+
+dnl check for flock()
+AC_MSG_CHECKING(for flock)
+AC_TRY_COMPILE(
+[#include <sys/file.h>],
+[flock(10, LOCK_SH);],
+AC_MSG_RESULT(yes); AC_DEFINE(HAVE_FLOCK), AC_MSG_RESULT(not usable))
+
dnl sysctl() may exist but not the arguments we use
AC_MSG_CHECKING(for sysctl)
AC_TRY_COMPILE(
diff --git a/src/fileio.c b/src/fileio.c
index f05abe68c..613f92359 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -4620,6 +4620,42 @@ delete_recursive(char_u *name)
#if defined(TEMPDIRNAMES) || defined(PROTO)
static long temp_count = 0; // Temp filename counter.
+# if defined(UNIX) && defined(HAVE_FLOCK) && defined(HAVE_DIRFD)
+/*
+ * Open temporary directory and take file lock to prevent
+ * to be auto-cleaned.
+ */
+ static void
+vim_opentempdir(void)
+{
+ DIR *dp = NULL;
+
+ if (vim_tempdir_dp != NULL)
+ return;
+
+ dp = opendir((const char*)vim_tempdir);
+
+ if (dp != NULL)
+ {
+ vim_tempdir_dp = dp;
+ flock(dirfd(vim_tempdir_dp), LOCK_SH);
+ }
+}
+
+/*
+ * Close temporary directory - it automatically release file lock.
+ */
+ static void
+vim_closetempdir(void)
+{
+ if (vim_tempdir_dp != NULL)
+ {
+ closedir(vim_tempdir_dp);
+ vim_tempdir_dp = NULL;
+ }
+}
+# endif
+
/*
* Delete the temp directory and all files it contains.
*/
@@ -4628,6 +4664,9 @@ vim_deltempdir(void)
{
if (vim_tempdir != NULL)
{
+# if defined(UNIX) && defined(HAVE_FLOCK) && defined(HAVE_DIRFD)
+ vim_closetempdir();
+# endif
// remove the trailing path separator
gettail(vim_tempdir)[-1] = NUL;
delete_recursive(vim_tempdir);
@@ -4652,6 +4691,9 @@ vim_settempdir(char_u *tempdir)
STRCPY(buf, tempdir);
add_pathsep(buf);
vim_tempdir = vim_strsave(buf);
+# if defined(UNIX) && defined(HAVE_FLOCK) && defined(HAVE_DIRFD)
+ vim_opentempdir();
+# endif
vim_free(buf);
}
}
diff --git a/src/globals.h b/src/globals.h
index 9180befcb..5dfb6ff3f 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -758,6 +758,9 @@ EXTERN int ru_wid; // 'rulerfmt' width of ruler when non-zero
EXTERN int sc_col; // column for shown command
#ifdef TEMPDIRNAMES
+# if defined(UNIX) && defined(HAVE_FLOCK) && defined(HAVE_DIRFD)
+EXTERN DIR *vim_tempdir_dp INIT(= NULL); // File descriptor of temp dir
+# endif
EXTERN char_u *vim_tempdir INIT(= NULL); // Name of Vim's own temp dir.
// Ends in a slash.
#endif
diff --git a/src/os_unix.h b/src/os_unix.h
index 485e05775..9b7337ac1 100644
--- a/src/os_unix.h
+++ b/src/os_unix.h
@@ -204,6 +204,10 @@
# endif
#endif
+#ifdef HAVE_FLOCK
+# include <sys/file.h>
+#endif
+
#endif // PROTO
#ifdef VMS
diff --git a/src/version.c b/src/version.c
index 2004f564d..d63cc8b8c 100644
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 711,
+/**/
710,
/**/
709,