aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-05-28 08:06:30 +0800
committerGitHub <noreply@github.com>2023-05-28 08:06:30 +0800
commit7a8402ac31aa2e155baafbc925c48527511c1e92 (patch)
treed69c2541099318c6f6cb3bf3847f158b654b6911
parentb46f61ac050e6eb530ceb4d4b510b612596427c5 (diff)
downloadrneovim-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.c11
-rw-r--r--src/nvim/fileio.c63
-rw-r--r--src/nvim/memfile.c19
-rw-r--r--src/nvim/memfile_defs.h68
-rw-r--r--src/nvim/memline.c4
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