0
0
mirror of https://github.com/vim/vim.git synced 2025-09-07 22:03:36 -04:00

patch 8.0.1305: writefile() never calls fsync()

Problem:    Writefile() never calls fsync().
Solution:   Follow the 'fsync' option with override to enable or disable.
This commit is contained in:
Bram Moolenaar 2017-11-16 23:04:15 +01:00
parent d048009717
commit 7567d0b115
6 changed files with 38 additions and 4 deletions

View File

@ -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")
<
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.
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 File

@ -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 File

@ -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

View File

@ -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) \

View File

@ -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 File

@ -766,6 +766,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1305,
/**/
1304,
/**/