summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-11-16 23:04:15 +0100
committerBram Moolenaar <Bram@vim.org>2017-11-16 23:04:15 +0100
commit7567d0b115e332f61a9f390aaccdf7825b891227 (patch)
treee4ab87bf66391ca7243d819c768dc907cdd411da
parentd0480097177369a6ed91d47aba189ae647afcd68 (diff)
downloadvim-git-7567d0b115e332f61a9f390aaccdf7825b891227.tar.gz
patch 8.0.1305: writefile() never calls fsync()v8.0.1305
Problem: Writefile() never calls fsync(). Solution: Follow the 'fsync' option with override to enable or disable.
-rw-r--r--runtime/doc/eval.txt17
-rw-r--r--src/evalfunc.c13
-rw-r--r--src/fileio.c2
-rw-r--r--src/globals.h3
-rw-r--r--src/testdir/test_writefile.vim7
-rw-r--r--src/version.c2
6 files changed, 39 insertions, 5 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index f754892ca..c001f6f2b 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1,4 +1,4 @@
-*eval.txt* For Vim version 8.0. Last change: 2017 Oct 28
+*eval.txt* For Vim version 8.0. Last change: 2017 Nov 16
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -8721,7 +8721,7 @@ winwidth({nr}) *winwidth()*
Examples: >
:echo "The current window has " . winwidth(0) . " columns."
:if winwidth(0) <= 50
- : exe "normal 50\<C-W>|"
+ : 50 wincmd |
:endif
< For getting the terminal or screen size, see the 'columns'
option.
@@ -8762,8 +8762,17 @@ writefile({list}, {fname} [, {flags}])
appended to the file: >
:call writefile(["foo"], "event.log", "a")
:call writefile(["bar"], "event.log", "a")
-
-< All NL characters are replaced with a NUL character.
+<
+ When {flags} contains "s" then fsync() is called after writing
+ the file. This flushes the file to disk, if possible. This
+ takes more time but avoids losing the file if the system
+ crashes.
+ When {flags} does not contain "S" or "s" then fsync is called
+ if the 'fsync' option is set.
+ When {flags} contains "S" then fsync() is not called, even
+ when 'fsync' is set.
+
+ All NL characters are replaced with a NUL character.
Inserting CR characters needs to be done before passing {list}
to writefile().
An existing file is overwritten, if possible.
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 1991aa7c6..25b28bb3a 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -13348,6 +13348,9 @@ f_writefile(typval_T *argvars, typval_T *rettv)
{
int binary = FALSE;
int append = FALSE;
+#ifdef HAVE_FSYNC
+ int do_fsync = p_fs;
+#endif
char_u *fname;
FILE *fd;
int ret = 0;
@@ -13380,6 +13383,12 @@ f_writefile(typval_T *argvars, typval_T *rettv)
binary = TRUE;
if (vim_strchr(arg2, 'a') != NULL)
append = TRUE;
+#ifdef HAVE_FSYNC
+ if (vim_strchr(arg2, 's') != NULL)
+ do_fsync = TRUE;
+ else if (vim_strchr(arg2, 'S') != NULL)
+ do_fsync = FALSE;
+#endif
}
fname = get_tv_string_chk(&argvars[1]);
@@ -13398,6 +13407,10 @@ f_writefile(typval_T *argvars, typval_T *rettv)
{
if (write_list(fd, list, binary) == FAIL)
ret = -1;
+#ifdef HAVE_FSYNC
+ else if (do_fsync && fsync(fileno(fd)) != 0)
+ EMSG(_(e_fsync));
+#endif
fclose(fd);
}
diff --git a/src/fileio.c b/src/fileio.c
index fbc164a91..e76e3d19a 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -4771,7 +4771,7 @@ restore_backup:
*/
if (p_fs && fsync(fd) != 0 && !device)
{
- errmsg = (char_u *)_("E667: Fsync failed");
+ errmsg = (char_u *)_(e_fsync);
end = 0;
}
#endif
diff --git a/src/globals.h b/src/globals.h
index 318363230..ae62710d5 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -1449,6 +1449,9 @@ EXTERN char_u e_isadir2[] INIT(= N_("E17: \"%s\" is a directory"));
#ifdef FEAT_LIBCALL
EXTERN char_u e_libcall[] INIT(= N_("E364: Library call failed for \"%s()\""));
#endif
+#ifdef HAVE_FSYNC
+EXTERN char_u e_fsync[] INIT(= N_("E667: Fsync failed"));
+#endif
#if defined(DYNAMIC_PERL) \
|| defined(DYNAMIC_PYTHON) || defined(DYNAMIC_PYTHON3) \
|| defined(DYNAMIC_RUBY) \
diff --git a/src/testdir/test_writefile.vim b/src/testdir/test_writefile.vim
index f462d049c..9703323b0 100644
--- a/src/testdir/test_writefile.vim
+++ b/src/testdir/test_writefile.vim
@@ -93,3 +93,10 @@ func Test_nowrite_quit_split()
endif
bwipe Xfile
endfunc
+
+func Test_writefile_sync_arg()
+ " This doesn't check if fsync() works, only that the argument is accepted.
+ call writefile(['one'], 'Xtest', 's')
+ call writefile(['two'], 'Xtest', 'S')
+ call delete('Xtest')
+endfunc
diff --git a/src/version.c b/src/version.c
index 1dd52da35..1cffd6181 100644
--- a/src/version.c
+++ b/src/version.c
@@ -767,6 +767,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1305,
+/**/
1304,
/**/
1303,