diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-05-28 08:06:30 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-28 08:06:30 +0800 |
commit | 7a8402ac31aa2e155baafbc925c48527511c1e92 (patch) | |
tree | d69c2541099318c6f6cb3bf3847f158b654b6911 | |
parent | b46f61ac050e6eb530ceb4d4b510b612596427c5 (diff) | |
download | rneovim-7a8402ac31aa2e155baafbc925c48527511c1e92.tar.gz rneovim-7a8402ac31aa2e155baafbc925c48527511c1e92.tar.bz2 rneovim-7a8402ac31aa2e155baafbc925c48527511c1e92.zip |
vim-patch:9.0.1583: get E304 when using 'cryptmethod' "xchacha20v2" (#23790)
Problem: Get E304 when using 'cryptmethod' "xchacha20v2". (Steve Mynott)
Solution: Add 4th crypt method to block zero ID check. Avoid syncing a swap
file before reading the file. (closes vim/vim#12433)
https://github.com/vim/vim/commit/3a2a60ce4a8e73594bca16814672fcc243d093ac
Co-authored-by: Bram Moolenaar <Bram@vim.org>
-rw-r--r-- | src/nvim/buffer.c | 11 | ||||
-rw-r--r-- | src/nvim/fileio.c | 63 | ||||
-rw-r--r-- | src/nvim/memfile.c | 19 | ||||
-rw-r--r-- | src/nvim/memfile_defs.h | 68 | ||||
-rw-r--r-- | src/nvim/memline.c | 4 |
5 files changed, 100 insertions, 65 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index dab07487cd..bc52ab0771 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -248,6 +248,11 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg) return FAIL; } + // Do not sync this buffer yet, may first want to read the file. + if (curbuf->b_ml.ml_mfp != NULL) { + curbuf->b_ml.ml_mfp->mf_dirty = MF_DIRTY_YES_NOSYNC; + } + // The autocommands in readfile() may change the buffer, but only AFTER // reading the file. set_bufref(&old_curbuf, curbuf); @@ -316,6 +321,12 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg) } } + // Can now sync this buffer in ml_sync_all(). + if (curbuf->b_ml.ml_mfp != NULL + && curbuf->b_ml.ml_mfp->mf_dirty == MF_DIRTY_YES_NOSYNC) { + curbuf->b_ml.ml_mfp->mf_dirty = MF_DIRTY_YES; + } + // if first time loading this buffer, init b_chartab[] if (curbuf->b_flags & BF_NEVERLOADED) { (void)buf_init_chartab(curbuf, false); diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index e60007bf88..d24ac1c233 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -153,6 +153,7 @@ void filemess(buf_T *buf, char *name, char *s, int attr) int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, linenr_T lines_to_read, exarg_T *eap, int flags, bool silent) { + int retval = FAIL; // jump to "theend" instead of returning int fd = stdin_fd >= 0 ? stdin_fd : 0; int newfile = (flags & READ_NEW); int check_readonly; @@ -240,7 +241,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, && vim_strchr(p_cpo, CPO_FNAMER) != NULL && !(flags & READ_DUMMY)) { if (set_rw_fname(fname, sfname) == FAIL) { - return FAIL; + goto theend; } } @@ -284,10 +285,9 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, if (newfile) { if (apply_autocmds_exarg(EVENT_BUFREADCMD, NULL, sfname, false, curbuf, eap)) { - int status = OK; - + retval = OK; if (aborting()) { - status = FAIL; + retval = FAIL; } // The BufReadCmd code usually uses ":read" to get the text and @@ -295,14 +295,15 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, // consider this to work like ":edit", thus reset the // BF_NOTEDITED flag. Then ":write" will work to overwrite the // same file. - if (status == OK) { + if (retval == OK) { curbuf->b_flags &= ~BF_NOTEDITED; } - return status; + goto theend; } } else if (apply_autocmds_exarg(EVENT_FILEREADCMD, sfname, sfname, false, NULL, eap)) { - return aborting() ? FAIL : OK; + retval = aborting() ? FAIL : OK; + goto theend; } curbuf->b_op_start = orig_start; @@ -310,7 +311,8 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, if (flags & READ_NOFILE) { // Return NOTDONE instead of FAIL so that BufEnter can be triggered // and other operations don't fail. - return NOTDONE; + retval = NOTDONE; + goto theend; } } @@ -328,7 +330,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, filemess(curbuf, fname, _("Illegal file name"), 0); msg_end(); msg_scroll = msg_save; - return FAIL; + goto theend; } // If the name ends in a path separator, we can't open it. Check here, @@ -340,7 +342,8 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, } msg_end(); msg_scroll = msg_save; - return NOTDONE; + retval = NOTDONE; + goto theend; } } @@ -365,12 +368,13 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, if (!silent) { filemess(curbuf, fname, _(msg_is_a_directory), 0); } + retval = NOTDONE; } else { filemess(curbuf, fname, _("is not a file"), 0); } msg_end(); msg_scroll = msg_save; - return S_ISDIR(perm) ? NOTDONE : FAIL; + goto theend; } } @@ -431,7 +435,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, if (fd < 0) { // cannot open at all msg_scroll = msg_save; if (!newfile) { - return FAIL; + goto theend; } if (perm == UV_ENOENT) { // check if the file exists // Set the 'new-file' flag, so that when the file has @@ -450,7 +454,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, || (using_b_fname && (old_b_fname != curbuf->b_fname))) { emsg(_(e_auchangedbuf)); - return FAIL; + goto theend; } } if (!silent) { @@ -472,10 +476,10 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, // remember the current fileformat save_file_ff(curbuf); - if (aborting()) { // autocmds may abort script processing - return FAIL; + if (!aborting()) { // autocmds may abort script processing + retval = OK; // a new file is not an error } - return OK; // a new file is not an error + goto theend; } #if defined(UNIX) && defined(EOVERFLOW) filemess(curbuf, sfname, ((fd == UV_EFBIG) ? _("[File too big]") : @@ -491,7 +495,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, #endif curbuf->b_p_ro = true; // must use "w!" now - return FAIL; + goto theend; } // Only set the 'ro' flag for readonly files the first time they are @@ -526,7 +530,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, if (!read_buffer) { close(fd); } - return FAIL; + goto theend; } #ifdef UNIX // Set swap file protection bits after creating it. @@ -561,7 +565,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, if (!read_buffer && !read_stdin) { close(fd); } - return FAIL; + goto theend; } no_wait_return++; // don't wait for return yet @@ -617,7 +621,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, no_wait_return--; msg_scroll = msg_save; curbuf->b_p_ro = true; // must use "w!" now - return FAIL; + goto theend; } // Don't allow the autocommands to change the current buffer. // Try to re-open the file. @@ -636,7 +640,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, emsg(_("E201: *ReadPre autocommands must not change current buffer")); } curbuf->b_p_ro = true; // must use "w!" now - return FAIL; + goto theend; } } @@ -1684,7 +1688,8 @@ failed: } msg_scroll = msg_save; check_marks_read(); - return OK; // an interrupt isn't really an error + retval = OK; // an interrupt isn't really an error + goto theend; } if (!filtering && !(flags & READ_DUMMY) && !silent) { @@ -1860,10 +1865,18 @@ failed: } } - if (recoverymode && error) { - return FAIL; + if (!(recoverymode && error)) { + retval = OK; } - return OK; + +theend: + if (curbuf->b_ml.ml_mfp != NULL + && curbuf->b_ml.ml_mfp->mf_dirty == MF_DIRTY_YES_NOSYNC) { + // OK to sync the swap file now + curbuf->b_ml.ml_mfp->mf_dirty = MF_DIRTY_YES; + } + + return retval; } #ifdef OPEN_CHR_FILES diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c index bd8314c679..5d6c58c387 100644 --- a/src/nvim/memfile.c +++ b/src/nvim/memfile.c @@ -103,7 +103,7 @@ memfile_T *mf_open(char *fname, int flags) mfp->mf_free_first = NULL; // free list is empty mfp->mf_used_first = NULL; // used list is empty mfp->mf_used_last = NULL; - mfp->mf_dirty = false; + mfp->mf_dirty = MF_DIRTY_NO; mf_hash_init(&mfp->mf_hash); mf_hash_init(&mfp->mf_trans); mfp->mf_page_size = MEMFILE_PAGE_SIZE; @@ -159,7 +159,7 @@ memfile_T *mf_open(char *fname, int flags) int mf_open_file(memfile_T *mfp, char *fname) { if (mf_do_open(mfp, fname, O_RDWR | O_CREAT | O_EXCL)) { - mfp->mf_dirty = true; + mfp->mf_dirty = MF_DIRTY_YES; return OK; } @@ -269,7 +269,7 @@ bhdr_T *mf_new(memfile_T *mfp, bool negative, unsigned page_count) } } hp->bh_flags = BH_LOCKED | BH_DIRTY; // new block is always dirty - mfp->mf_dirty = true; + mfp->mf_dirty = MF_DIRTY_YES; hp->bh_page_count = page_count; mf_ins_used(mfp, hp); mf_ins_hash(mfp, hp); @@ -342,7 +342,9 @@ void mf_put(memfile_T *mfp, bhdr_T *hp, bool dirty, bool infile) flags &= ~BH_LOCKED; if (dirty) { flags |= BH_DIRTY; - mfp->mf_dirty = true; + if (mfp->mf_dirty != MF_DIRTY_YES_NOSYNC) { + mfp->mf_dirty = MF_DIRTY_YES; + } } hp->bh_flags = flags; if (infile) { @@ -382,8 +384,9 @@ int mf_sync(memfile_T *mfp, int flags) { int got_int_save = got_int; - if (mfp->mf_fd < 0) { // there is no file, nothing to do - mfp->mf_dirty = false; + if (mfp->mf_fd < 0) { + // there is no file, nothing to do + mfp->mf_dirty = MF_DIRTY_NO; return FAIL; } @@ -426,7 +429,7 @@ int mf_sync(memfile_T *mfp, int flags) // If the whole list is flushed, the memfile is not dirty anymore. // In case of an error, dirty flag is also set, to avoid trying all the time. if (hp == NULL || status == FAIL) { - mfp->mf_dirty = false; + mfp->mf_dirty = MF_DIRTY_NO; } if (flags & MFS_FLUSH) { @@ -449,7 +452,7 @@ void mf_set_dirty(memfile_T *mfp) hp->bh_flags |= BH_DIRTY; } } - mfp->mf_dirty = true; + mfp->mf_dirty = MF_DIRTY_YES; } /// Insert block in front of memfile's hash list. diff --git a/src/nvim/memfile_defs.h b/src/nvim/memfile_defs.h index 53152c28f8..917dd6a905 100644 --- a/src/nvim/memfile_defs.h +++ b/src/nvim/memfile_defs.h @@ -38,13 +38,13 @@ typedef struct mf_hashitem { /// mf_hashitem_T which contains the key and linked list pointers. List of items /// in each bucket is doubly-linked. typedef struct mf_hashtab { - size_t mht_mask; /// mask used to mod hash value to array index - /// (nr of items in array is 'mht_mask + 1') - size_t mht_count; /// number of items inserted - mf_hashitem_T **mht_buckets; /// points to the array of buckets (can be - /// mht_small_buckets or a newly allocated array - /// when mht_small_buckets becomes too small) - mf_hashitem_T *mht_small_buckets[MHT_INIT_SIZE]; /// initial buckets + size_t mht_mask; ///< mask used to mod hash value to array index + ///< (nr of items in array is 'mht_mask + 1') + size_t mht_count; ///< number of items inserted + mf_hashitem_T **mht_buckets; ///< points to the array of buckets (can be + ///< mht_small_buckets or a newly allocated array + ///< when mht_small_buckets becomes too small) + mf_hashitem_T *mht_small_buckets[MHT_INIT_SIZE]; ///< initial buckets } mf_hashtab_T; /// A block header. @@ -61,17 +61,17 @@ typedef struct mf_hashtab { /// The blocks in the free list have no block of memory allocated and /// the contents of the block in the file (if any) is irrelevant. typedef struct bhdr { - mf_hashitem_T bh_hashitem; /// header for hash table and key -#define bh_bnum bh_hashitem.mhi_key /// block number, part of bh_hashitem + mf_hashitem_T bh_hashitem; ///< header for hash table and key +#define bh_bnum bh_hashitem.mhi_key ///< block number, part of bh_hashitem - struct bhdr *bh_next; /// next block header in free or used list - struct bhdr *bh_prev; /// previous block header in used list - void *bh_data; /// pointer to memory (for used block) - unsigned bh_page_count; /// number of pages in this block + struct bhdr *bh_next; ///< next block header in free or used list + struct bhdr *bh_prev; ///< previous block header in used list + void *bh_data; ///< pointer to memory (for used block) + unsigned bh_page_count; ///< number of pages in this block #define BH_DIRTY 1U #define BH_LOCKED 2U - unsigned bh_flags; // BH_DIRTY or BH_LOCKED + unsigned bh_flags; ///< BH_DIRTY or BH_LOCKED } bhdr_T; /// A block number translation list item. @@ -81,27 +81,33 @@ typedef struct bhdr { /// number, we remember the translation to the new positive number in the /// double linked trans lists. The structure is the same as the hash lists. typedef struct mf_blocknr_trans_item { - mf_hashitem_T nt_hashitem; /// header for hash table and key -#define nt_old_bnum nt_hashitem.mhi_key /// old, negative, number - blocknr_T nt_new_bnum; /// new, positive, number + mf_hashitem_T nt_hashitem; ///< header for hash table and key +#define nt_old_bnum nt_hashitem.mhi_key ///< old, negative, number + blocknr_T nt_new_bnum; ///< new, positive, number } mf_blocknr_trans_item_T; +typedef enum { + MF_DIRTY_NO = 0, ///< no dirty blocks + MF_DIRTY_YES, ///< there are dirty blocks + MF_DIRTY_YES_NOSYNC, ///< there are dirty blocks, do not sync yet +} mfdirty_T; + /// A memory file. typedef struct memfile { - char *mf_fname; /// name of the file - char *mf_ffname; /// idem, full path - int mf_fd; /// file descriptor - bhdr_T *mf_free_first; /// first block header in free list - bhdr_T *mf_used_first; /// mru block header in used list - bhdr_T *mf_used_last; /// lru block header in used list - mf_hashtab_T mf_hash; /// hash lists - mf_hashtab_T mf_trans; /// trans lists - blocknr_T mf_blocknr_max; /// highest positive block number + 1 - blocknr_T mf_blocknr_min; /// lowest negative block number - 1 - blocknr_T mf_neg_count; /// number of negative blocks numbers - blocknr_T mf_infile_count; /// number of pages in the file - unsigned mf_page_size; /// number of bytes in a page - bool mf_dirty; /// true if there are dirty blocks + char *mf_fname; ///< name of the file + char *mf_ffname; ///< idem, full path + int mf_fd; ///< file descriptor + bhdr_T *mf_free_first; ///< first block header in free list + bhdr_T *mf_used_first; ///< mru block header in used list + bhdr_T *mf_used_last; ///< lru block header in used list + mf_hashtab_T mf_hash; ///< hash lists + mf_hashtab_T mf_trans; ///< trans lists + blocknr_T mf_blocknr_max; ///< highest positive block number + 1 + blocknr_T mf_blocknr_min; ///< lowest negative block number - 1 + blocknr_T mf_neg_count; ///< number of negative blocks numbers + blocknr_T mf_infile_count; ///< number of pages in the file + unsigned mf_page_size; ///< number of bytes in a page + mfdirty_T mf_dirty; } memfile_T; #endif // NVIM_MEMFILE_DEFS_H diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 0815ba411c..eb2afc60b2 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -510,6 +510,8 @@ void ml_open_file(buf_T *buf) continue; } if (mf_open_file(mfp, fname) == OK) { // consumes fname! + // don't sync yet in ml_sync_all() + mfp->mf_dirty = MF_DIRTY_YES_NOSYNC; ml_upd_block0(buf, UB_SAME_DIR); // Flush block zero, so others can read it @@ -1714,7 +1716,7 @@ void ml_sync_all(int check_file, int check_char, bool do_fsync) need_check_timestamps = true; // give message later } } - if (buf->b_ml.ml_mfp->mf_dirty) { + if (buf->b_ml.ml_mfp->mf_dirty == MF_DIRTY_YES) { (void)mf_sync(buf->b_ml.ml_mfp, (check_char ? MFS_STOP : 0) | (do_fsync && bufIsChanged(buf) ? MFS_FLUSH : 0)); if (check_char && os_char_avail()) { // character available now |