aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2024-08-08 16:11:53 +0800
committerGitHub <noreply@github.com>2024-08-08 08:11:53 +0000
commita89088b7a02b70d15ccd6f17402c36f2ff7b7a81 (patch)
tree8da31fa94786ac266c2c7945b4517e4a2caf725a
parent2f1ea1133a47df782925ac88bc3cecb649fb0b23 (diff)
downloadrneovim-a89088b7a02b70d15ccd6f17402c36f2ff7b7a81.tar.gz
rneovim-a89088b7a02b70d15ccd6f17402c36f2ff7b7a81.tar.bz2
rneovim-a89088b7a02b70d15ccd6f17402c36f2ff7b7a81.zip
vim-patch:8.1.1413: error when the drive of the swap file was disconnected (#30009)
Problem: Error when the drive of the swap file was disconnected. Solution: Try closing and re-opening the swap file. (closes vim/vim#4378) https://github.com/vim/vim/commit/b58a4b938c4bc7e0499700859bd7abba9acc5b11 Co-authored-by: Bram Moolenaar <Bram@vim.org>
-rw-r--r--src/nvim/memfile.c55
-rw-r--r--src/nvim/memfile_defs.h2
2 files changed, 41 insertions, 16 deletions
diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c
index 498d212da3..d032caa3be 100644
--- a/src/nvim/memfile.c
+++ b/src/nvim/memfile.c
@@ -566,7 +566,8 @@ static int mf_write(memfile_T *mfp, bhdr_T *hp)
bhdr_T *hp2;
unsigned page_count; // number of pages written
- if (mfp->mf_fd < 0) { // there is no file, can't write
+ if (mfp->mf_fd < 0 && !mfp->mf_reopen) {
+ // there is no file and there was no file, can't write
return FAIL;
}
@@ -593,28 +594,48 @@ static int mf_write(memfile_T *mfp, bhdr_T *hp)
// TODO(elmart): Check (page_size * nr) within off_T bounds.
off_T offset = (off_T)(page_size * nr); // offset in the file
- if (vim_lseek(mfp->mf_fd, offset, SEEK_SET) != offset) {
- PERROR(_("E296: Seek error in swap file write"));
- return FAIL;
- }
if (hp2 == NULL) { // freed block, fill with dummy data
page_count = 1;
} else {
page_count = hp2->bh_page_count;
}
unsigned size = page_size * page_count; // number of bytes written
- void *data = (hp2 == NULL) ? hp->bh_data : hp2->bh_data;
- if ((unsigned)write_eintr(mfp->mf_fd, data, size) != size) {
- /// Avoid repeating the error message, this mostly happens when the
- /// disk is full. We give the message again only after a successful
- /// write or when hitting a key. We keep on trying, in case some
- /// space becomes available.
- if (!did_swapwrite_msg) {
- emsg(_("E297: Write error in swap file"));
+
+ for (int attempt = 1; attempt <= 2; attempt++) {
+ if (mfp->mf_fd >= 0) {
+ if (vim_lseek(mfp->mf_fd, offset, SEEK_SET) != offset) {
+ PERROR(_("E296: Seek error in swap file write"));
+ return FAIL;
+ }
+ void *data = (hp2 == NULL) ? hp->bh_data : hp2->bh_data;
+ if ((unsigned)write_eintr(mfp->mf_fd, data, size) == size) {
+ break;
+ }
+ }
+
+ if (attempt == 1) {
+ // If the swap file is on a network drive, and the network
+ // gets disconnected and then re-connected, we can maybe fix it
+ // by closing and then re-opening the file.
+ if (mfp->mf_fd >= 0) {
+ close(mfp->mf_fd);
+ }
+ mfp->mf_fd = os_open(mfp->mf_fname, mfp->mf_flags, S_IREAD | S_IWRITE);
+ mfp->mf_reopen = (mfp->mf_fd < 0);
+ }
+ if (attempt == 2 || mfp->mf_fd < 0) {
+ // Avoid repeating the error message, this mostly happens when the
+ // disk is full. We give the message again only after a successful
+ // write or when hitting a key. We keep on trying, in case some
+ // space becomes available.
+ if (!did_swapwrite_msg) {
+ emsg(_("E297: Write error in swap file"));
+ }
+ did_swapwrite_msg = true;
+ return FAIL;
}
- did_swapwrite_msg = true;
- return FAIL;
}
+
did_swapwrite_msg = false;
if (hp2 != NULL) { // written a non-dummy block
hp2->bh_flags &= ~BH_DIRTY;
@@ -751,7 +772,9 @@ static bool mf_do_open(memfile_T *mfp, char *fname, int flags)
emsg(_("E300: Swap file already exists (symlink attack?)"));
} else {
// try to open the file
- mfp->mf_fd = os_open(mfp->mf_fname, flags | O_NOFOLLOW, S_IREAD | S_IWRITE);
+ flags |= O_NOFOLLOW;
+ mfp->mf_flags = flags;
+ mfp->mf_fd = os_open(mfp->mf_fname, flags, S_IREAD | S_IWRITE);
}
// If the file cannot be opened, use memory only
diff --git a/src/nvim/memfile_defs.h b/src/nvim/memfile_defs.h
index 5caf13c9fb..5f2468c947 100644
--- a/src/nvim/memfile_defs.h
+++ b/src/nvim/memfile_defs.h
@@ -46,6 +46,8 @@ typedef struct {
char *mf_fname; ///< name of the file
char *mf_ffname; ///< idem, full path
int mf_fd; ///< file descriptor
+ int mf_flags; ///< flags used when opening this memfile
+ bool mf_reopen; ///< mf_fd was closed, retry opening
bhdr_T *mf_free_first; ///< first block header in free list
/// The used blocks are kept in mf_hash.