Permalink
Browse files

patch 8.0.1305: writefile() never calls fsync()

Problem:    Writefile() never calls fsync().
Solution:   Follow the 'fsync' option with override to enable or disable.
  • Loading branch information...
brammool committed Nov 16, 2017
1 parent d048009 commit 7567d0b115e332f61a9f390aaccdf7825b891227
Showing with 39 additions and 5 deletions.
  1. +13 −4 runtime/doc/eval.txt
  2. +13 −0 src/evalfunc.c
  3. +1 −1 src/fileio.c
  4. +3 −0 src/globals.h
  5. +7 −0 src/testdir/test_writefile.vim
  6. +2 −0 src/version.c
View
@@ -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.
View
@@ -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);
}
View
@@ -4771,7 +4771,7 @@ buf_write(
*/
if (p_fs && fsync(fd) != 0 && !device)
{
errmsg = (char_u *)_("E667: Fsync failed");
errmsg = (char_u *)_(e_fsync);
end = 0;
}
#endif
View
@@ -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) \
@@ -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
View
@@ -766,6 +766,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1305,
/**/
1304,
/**/

0 comments on commit 7567d0b

Please sign in to comment.