forked from aniani/vim
		
	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:
		| @@ -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 | 		  VIM REFERENCE MANUAL	  by Bram Moolenaar | ||||||
| @@ -8721,7 +8721,7 @@ winwidth({nr})						*winwidth()* | |||||||
| 		Examples: > | 		Examples: > | ||||||
|   :echo "The current window has " . winwidth(0) . " columns." |   :echo "The current window has " . winwidth(0) . " columns." | ||||||
|   :if winwidth(0) <= 50 |   :if winwidth(0) <= 50 | ||||||
|   :  exe "normal 50\<C-W>|" |   :  50 wincmd | | ||||||
|   :endif |   :endif | ||||||
| <		For getting the terminal or screen size, see the 'columns' | <		For getting the terminal or screen size, see the 'columns' | ||||||
| 		option. | 		option. | ||||||
| @@ -8762,8 +8762,17 @@ writefile({list}, {fname} [, {flags}]) | |||||||
| 		appended to the file: > | 		appended to the file: > | ||||||
| 			:call writefile(["foo"], "event.log", "a") | 			:call writefile(["foo"], "event.log", "a") | ||||||
| 			:call writefile(["bar"], "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} | 		Inserting CR characters needs to be done before passing {list} | ||||||
| 		to writefile(). | 		to writefile(). | ||||||
| 		An existing file is overwritten, if possible. | 		An existing file is overwritten, if possible. | ||||||
|   | |||||||
| @@ -13348,6 +13348,9 @@ f_writefile(typval_T *argvars, typval_T *rettv) | |||||||
| { | { | ||||||
|     int		binary = FALSE; |     int		binary = FALSE; | ||||||
|     int		append = FALSE; |     int		append = FALSE; | ||||||
|  | #ifdef HAVE_FSYNC | ||||||
|  |     int		do_fsync = p_fs; | ||||||
|  | #endif | ||||||
|     char_u	*fname; |     char_u	*fname; | ||||||
|     FILE	*fd; |     FILE	*fd; | ||||||
|     int		ret = 0; |     int		ret = 0; | ||||||
| @@ -13380,6 +13383,12 @@ f_writefile(typval_T *argvars, typval_T *rettv) | |||||||
| 	    binary = TRUE; | 	    binary = TRUE; | ||||||
| 	if (vim_strchr(arg2, 'a') != NULL) | 	if (vim_strchr(arg2, 'a') != NULL) | ||||||
| 	    append = TRUE; | 	    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]); |     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) | 	if (write_list(fd, list, binary) == FAIL) | ||||||
| 	    ret = -1; | 	    ret = -1; | ||||||
|  | #ifdef HAVE_FSYNC | ||||||
|  | 	else if (do_fsync && fsync(fileno(fd)) != 0) | ||||||
|  | 	    EMSG(_(e_fsync)); | ||||||
|  | #endif | ||||||
| 	fclose(fd); | 	fclose(fd); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4771,7 +4771,7 @@ restore_backup: | |||||||
| 	 */ | 	 */ | ||||||
| 	if (p_fs && fsync(fd) != 0 && !device) | 	if (p_fs && fsync(fd) != 0 && !device) | ||||||
| 	{ | 	{ | ||||||
| 	    errmsg = (char_u *)_("E667: Fsync failed"); | 	    errmsg = (char_u *)_(e_fsync); | ||||||
| 	    end = 0; | 	    end = 0; | ||||||
| 	} | 	} | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -1449,6 +1449,9 @@ EXTERN char_u e_isadir2[]	INIT(= N_("E17: \"%s\" is a directory")); | |||||||
| #ifdef FEAT_LIBCALL | #ifdef FEAT_LIBCALL | ||||||
| EXTERN char_u e_libcall[]	INIT(= N_("E364: Library call failed for \"%s()\"")); | EXTERN char_u e_libcall[]	INIT(= N_("E364: Library call failed for \"%s()\"")); | ||||||
| #endif | #endif | ||||||
|  | #ifdef HAVE_FSYNC | ||||||
|  | EXTERN char_u e_fsync[]		INIT(= N_("E667: Fsync failed")); | ||||||
|  | #endif | ||||||
| #if defined(DYNAMIC_PERL) \ | #if defined(DYNAMIC_PERL) \ | ||||||
| 	|| defined(DYNAMIC_PYTHON) || defined(DYNAMIC_PYTHON3) \ | 	|| defined(DYNAMIC_PYTHON) || defined(DYNAMIC_PYTHON3) \ | ||||||
| 	|| defined(DYNAMIC_RUBY) \ | 	|| defined(DYNAMIC_RUBY) \ | ||||||
|   | |||||||
| @@ -93,3 +93,10 @@ func Test_nowrite_quit_split() | |||||||
|   endif |   endif | ||||||
|   bwipe Xfile |   bwipe Xfile | ||||||
| endfunc | 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 | ||||||
|   | |||||||
| @@ -766,6 +766,8 @@ static char *(features[]) = | |||||||
|  |  | ||||||
| static int included_patches[] = | static int included_patches[] = | ||||||
| {   /* Add new patch number below this line */ | {   /* Add new patch number below this line */ | ||||||
|  | /**/ | ||||||
|  |     1305, | ||||||
| /**/ | /**/ | ||||||
|     1304, |     1304, | ||||||
| /**/ | /**/ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user