From: glepnir Date: Sat, 27 Dec 2025 14:26:38 +0000 (+0000) Subject: patch 9.1.2024: 'fsync' option cannot be set per buffer X-Git-Url: https://git.feebdaed.xyz/?a=commitdiff_plain;h=4d5b30372663e8ea356b25fe94334558c6ae283f;p=0xmirror%2Fvim.git patch 9.1.2024: 'fsync' option cannot be set per buffer Problem: 'fsync' option cannot be set per buffer Solution: Make 'fsync' option global-local (glepnir) closes: #19019 Signed-off-by: glepnir Signed-off-by: Christian Brabandt --- diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index b1550dfcc..67c8b2904 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 9.1. Last change: 2025 Dec 23 +*options.txt* For Vim version 9.1. Last change: 2025 Dec 27 VIM REFERENCE MANUAL by Bram Moolenaar @@ -4274,7 +4274,7 @@ A jump table for the options with a short description can be found at |Q_op|. *'fsync'* *'fs'* *'nofsync'* *'nofs'* 'fsync' 'fs' boolean (default on) - global + global or local to buffer |global-local| When on, the library function fsync() will be called after writing a file. This will flush a file to disk, ensuring that it is safely written even on filesystems which do metadata-only journaling. This @@ -4283,6 +4283,8 @@ A jump table for the options with a short description can be found at |Q_op|. turning this off increases the chances of data loss after a crash. On systems without an fsync() implementation, this variable is always off. + This is a |global-local| option, so it can be set per buffer, for + example when writing to a slow filesystem. Also see 'swapsync' for controlling fsync() on swap files. 'fsync' also applies to |writefile()| (unless a flag is used to overrule it) and when writing undo files (see |undo-persistence|). diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index f1cfd0979..b626f2dea 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -1,4 +1,4 @@ -*version9.txt* For Vim version 9.1. Last change: 2025 Dec 21 +*version9.txt* For Vim version 9.1. Last change: 2025 Dec 27 VIM REFERENCE MANUAL by Bram Moolenaar @@ -41727,6 +41727,7 @@ Options: ~ - 'guioptions': New value |'go-s'| to support fullscreen on MS-Windows GUI (see also the below platform specific change). - 'completepopup': Add more values to style popup windows. +- 'fsync' is now a |global-local| option. Ex commands: ~ - allow to specify a priority when defining a new sign |:sign-define| diff --git a/src/buffer.c b/src/buffer.c index 52aa13de2..7dca75307 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -2538,6 +2538,9 @@ free_buf_options( clear_string_option(&buf->b_p_qe); buf->b_p_ac = -1; buf->b_p_ar = -1; +#ifdef HAVE_FSYNC + buf->b_p_fs = -1; +#endif buf->b_p_ul = NO_LOCAL_UNDOLEVEL; clear_string_option(&buf->b_p_lw); clear_string_option(&buf->b_p_bkc); diff --git a/src/bufwrite.c b/src/bufwrite.c index 342b5f36f..c1a495318 100644 --- a/src/bufwrite.c +++ b/src/bufwrite.c @@ -2199,7 +2199,8 @@ restore_backup: // For a device do try the fsync() but don't complain if it does not // work (could be a pipe). // If the 'fsync' option is FALSE, don't fsync(). Useful for laptops. - if (p_fs && vim_fsync(fd) != 0 && !device) + if ((buf->b_p_fs >= 0 ? buf->b_p_fs : p_fs) && vim_fsync(fd) != 0 + && !device) { errmsg = (char_u *)_(e_fsync_failed); end = 0; diff --git a/src/option.c b/src/option.c index b5594dd6e..1ec7efbf8 100644 --- a/src/option.c +++ b/src/option.c @@ -698,6 +698,9 @@ set_init_1(int clean_arg) curbuf->b_p_initialized = TRUE; curbuf->b_p_ac = -1; curbuf->b_p_ar = -1; // no local 'autoread' value +#ifdef HAVE_FSYNC + curbuf->b_p_fs = -1; // no local 'fsync' value +#endif curbuf->b_p_ul = NO_LOCAL_UNDOLEVEL; check_buf_options(curbuf); check_win_options(curwin); @@ -2216,6 +2219,10 @@ do_set_option_bool( value = -1; else if ((int *)varp == &curbuf->b_p_ac && opt_flags == OPT_LOCAL) value = -1; +#ifdef HAVE_FSYNC + else if ((int *)varp == &curbuf->b_p_fs && opt_flags == OPT_LOCAL) + value = -1; +#endif else value = *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL); } @@ -6479,6 +6486,11 @@ unset_global_local_option(char_u *name, void *from) case PV_AR: buf->b_p_ar = -1; break; +#ifdef HAVE_FSYNC + case PV_FS: + buf->b_p_fs = -1; + break; +#endif case PV_BKC: clear_string_option(&buf->b_p_bkc); buf->b_bkc_flags = 0; @@ -6613,6 +6625,9 @@ get_varp_scope(struct vimoption *p, int scope) switch ((int)p->indir) { case PV_FP: return (char_u *)&(curbuf->b_p_fp); +#ifdef HAVE_FSYNC + case PV_FS: return (char_u *)&(curbuf->b_p_fs); +#endif #ifdef FEAT_EVAL case PV_FFU: return (char_u *)&(curbuf->b_p_ffu); #endif @@ -6737,6 +6752,10 @@ get_varp(struct vimoption *p) #endif case PV_FP: return *curbuf->b_p_fp != NUL ? (char_u *)&(curbuf->b_p_fp) : p->var; +#ifdef HAVE_FSYNC + case PV_FS: return curbuf->b_p_fs >= 0 + ? (char_u *)&(curbuf->b_p_fs) : p->var; +#endif #ifdef FEAT_EVAL case PV_FFU: return *curbuf->b_p_ffu != NUL ? (char_u *)&(curbuf->b_p_ffu) : p->var; @@ -7540,6 +7559,9 @@ buf_copy_options(buf_T *buf, int flags) // are not copied, start using the global value buf->b_p_ac = -1; buf->b_p_ar = -1; +#ifdef HAVE_FSYNC + buf->b_p_fs = -1; +#endif buf->b_p_ul = NO_LOCAL_UNDOLEVEL; buf->b_p_bkc = empty_option; buf->b_bkc_flags = 0; diff --git a/src/option.h b/src/option.h index f5c36ad89..7372ba924 100644 --- a/src/option.h +++ b/src/option.h @@ -1223,6 +1223,9 @@ enum , BV_FF , BV_FLP , BV_FO +#ifdef HAVE_FSYNC + , BV_FS +#endif , BV_FT , BV_IMI , BV_IMS diff --git a/src/optiondefs.h b/src/optiondefs.h index d888615f5..9e5612470 100644 --- a/src/optiondefs.h +++ b/src/optiondefs.h @@ -82,6 +82,9 @@ #define PV_FF OPT_BUF(BV_FF) #define PV_FLP OPT_BUF(BV_FLP) #define PV_FO OPT_BUF(BV_FO) +#ifdef HAVE_FSYNC +# define PV_FS OPT_BOTH(OPT_BUF(BV_FS)) +#endif #define PV_FT OPT_BUF(BV_FT) #define PV_IMI OPT_BUF(BV_IMI) #define PV_IMS OPT_BUF(BV_IMS) @@ -1172,7 +1175,7 @@ static struct vimoption options[] = {(char_u *)"", (char_u *)0L} SCTX_INIT}, {"fsync", "fs", P_BOOL|P_SECURE|P_VI_DEF, #ifdef HAVE_FSYNC - (char_u *)&p_fs, PV_NONE, NULL, NULL, + (char_u *)&p_fs, PV_FS, NULL, NULL, {(char_u *)TRUE, (char_u *)0L} #else (char_u *)NULL, PV_NONE, NULL, NULL, diff --git a/src/structs.h b/src/structs.h index 9b095c328..37f9cf5d1 100644 --- a/src/structs.h +++ b/src/structs.h @@ -3380,6 +3380,9 @@ struct file_buffer char_u *b_p_fex; // 'formatexpr' long_u b_p_fex_flags; // flags for 'formatexpr' #endif +#ifdef HAVE_FSYNC + int b_p_fs; // 'fsync' +#endif #ifdef FEAT_CRYPT char_u *b_p_key; // 'key' #endif diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim index 2e4e9f727..c6c83bb98 100644 --- a/src/testdir/test_options.vim +++ b/src/testdir/test_options.vim @@ -1681,25 +1681,34 @@ endfunc " Test for setting boolean global-local option value func Test_set_boolean_global_local_option() - setglobal autoread - setlocal noautoread + CheckUnix + + setglobal autoread fsync + setlocal noautoread nofsync call assert_equal(1, &g:autoread) call assert_equal(0, &l:autoread) call assert_equal(0, &autoread) + call assert_equal(1, &g:fsync) + call assert_equal(0, &l:fsync) + call assert_equal(0, &fsync) " :set {option}< set the effective value of {option} to its global value. - set autoread< + set autoread< fsync< call assert_equal(1, &l:autoread) call assert_equal(1, &autoread) + call assert_equal(1, &l:fsync) + call assert_equal(1, &fsync) " :setlocal {option}< removes the local value, so that the global value will be used. - setglobal noautoread - setlocal autoread - setlocal autoread< + setglobal noautoread nofsync + setlocal autoread fsync + setlocal autoread< fsync< call assert_equal(-1, &l:autoread) call assert_equal(0, &autoread) + call assert_equal(-1, &l:fsync) + call assert_equal(0, &fsync) - set autoread& + set autoread& fsync& endfunc func Test_set_in_sandbox() diff --git a/src/undo.c b/src/undo.c index b1747996b..f40aca660 100644 --- a/src/undo.c +++ b/src/undo.c @@ -1774,7 +1774,8 @@ u_write_undo( #endif #if defined(UNIX) && defined(HAVE_FSYNC) - if (p_fs && fflush(fp) == 0 && vim_fsync(fd) != 0) + if ((buf->b_p_fs >= 0 ? buf->b_p_fs : p_fs) && fflush(fp) == 0 + && vim_fsync(fd) != 0) write_ok = FALSE; #endif diff --git a/src/version.c b/src/version.c index fad0bdd58..f09ff1791 100644 --- a/src/version.c +++ b/src/version.c @@ -734,6 +734,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2024, /**/ 2023, /**/