Skip to content

Commit 7567d0b

Browse files
committed
patch 8.0.1305: writefile() never calls fsync()
Problem: Writefile() never calls fsync(). Solution: Follow the 'fsync' option with override to enable or disable.
1 parent d048009 commit 7567d0b

6 files changed

Lines changed: 39 additions & 5 deletions

File tree

runtime/doc/eval.txt

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*eval.txt* For Vim version 8.0. Last change: 2017 Oct 28
1+
*eval.txt* For Vim version 8.0. Last change: 2017 Nov 16
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -8721,7 +8721,7 @@ winwidth({nr}) *winwidth()*
87218721
Examples: >
87228722
:echo "The current window has " . winwidth(0) . " columns."
87238723
:if winwidth(0) <= 50
8724-
: exe "normal 50\<C-W>|"
8724+
: 50 wincmd |
87258725
:endif
87268726
< For getting the terminal or screen size, see the 'columns'
87278727
option.
@@ -8762,8 +8762,17 @@ writefile({list}, {fname} [, {flags}])
87628762
appended to the file: >
87638763
:call writefile(["foo"], "event.log", "a")
87648764
:call writefile(["bar"], "event.log", "a")
8765-
8766-
< All NL characters are replaced with a NUL character.
8765+
<
8766+
When {flags} contains "s" then fsync() is called after writing
8767+
the file. This flushes the file to disk, if possible. This
8768+
takes more time but avoids losing the file if the system
8769+
crashes.
8770+
When {flags} does not contain "S" or "s" then fsync is called
8771+
if the 'fsync' option is set.
8772+
When {flags} contains "S" then fsync() is not called, even
8773+
when 'fsync' is set.
8774+
8775+
All NL characters are replaced with a NUL character.
87678776
Inserting CR characters needs to be done before passing {list}
87688777
to writefile().
87698778
An existing file is overwritten, if possible.

src/evalfunc.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13348,6 +13348,9 @@ f_writefile(typval_T *argvars, typval_T *rettv)
1334813348
{
1334913349
int binary = FALSE;
1335013350
int append = FALSE;
13351+
#ifdef HAVE_FSYNC
13352+
int do_fsync = p_fs;
13353+
#endif
1335113354
char_u *fname;
1335213355
FILE *fd;
1335313356
int ret = 0;
@@ -13380,6 +13383,12 @@ f_writefile(typval_T *argvars, typval_T *rettv)
1338013383
binary = TRUE;
1338113384
if (vim_strchr(arg2, 'a') != NULL)
1338213385
append = TRUE;
13386+
#ifdef HAVE_FSYNC
13387+
if (vim_strchr(arg2, 's') != NULL)
13388+
do_fsync = TRUE;
13389+
else if (vim_strchr(arg2, 'S') != NULL)
13390+
do_fsync = FALSE;
13391+
#endif
1338313392
}
1338413393

1338513394
fname = get_tv_string_chk(&argvars[1]);
@@ -13398,6 +13407,10 @@ f_writefile(typval_T *argvars, typval_T *rettv)
1339813407
{
1339913408
if (write_list(fd, list, binary) == FAIL)
1340013409
ret = -1;
13410+
#ifdef HAVE_FSYNC
13411+
else if (do_fsync && fsync(fileno(fd)) != 0)
13412+
EMSG(_(e_fsync));
13413+
#endif
1340113414
fclose(fd);
1340213415
}
1340313416

src/fileio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4771,7 +4771,7 @@ buf_write(
47714771
*/
47724772
if (p_fs && fsync(fd) != 0 && !device)
47734773
{
4774-
errmsg = (char_u *)_("E667: Fsync failed");
4774+
errmsg = (char_u *)_(e_fsync);
47754775
end = 0;
47764776
}
47774777
#endif

src/globals.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,6 +1449,9 @@ EXTERN char_u e_isadir2[] INIT(= N_("E17: \"%s\" is a directory"));
14491449
#ifdef FEAT_LIBCALL
14501450
EXTERN char_u e_libcall[] INIT(= N_("E364: Library call failed for \"%s()\""));
14511451
#endif
1452+
#ifdef HAVE_FSYNC
1453+
EXTERN char_u e_fsync[] INIT(= N_("E667: Fsync failed"));
1454+
#endif
14521455
#if defined(DYNAMIC_PERL) \
14531456
|| defined(DYNAMIC_PYTHON) || defined(DYNAMIC_PYTHON3) \
14541457
|| defined(DYNAMIC_RUBY) \

src/testdir/test_writefile.vim

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,10 @@ func Test_nowrite_quit_split()
9393
endif
9494
bwipe Xfile
9595
endfunc
96+
97+
func Test_writefile_sync_arg()
98+
" This doesn't check if fsync() works, only that the argument is accepted.
99+
call writefile(['one'], 'Xtest', 's')
100+
call writefile(['two'], 'Xtest', 'S')
101+
call delete('Xtest')
102+
endfunc

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,8 @@ static char *(features[]) =
766766

767767
static int included_patches[] =
768768
{ /* Add new patch number below this line */
769+
/**/
770+
1305,
769771
/**/
770772
1304,
771773
/**/

0 commit comments

Comments
 (0)