mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
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)
3a2a60ce4a
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
parent
b46f61ac05
commit
7a8402ac31
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user