diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-08-08 16:11:53 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-08 08:11:53 +0000 |
commit | a89088b7a02b70d15ccd6f17402c36f2ff7b7a81 (patch) | |
tree | 8da31fa94786ac266c2c7945b4517e4a2caf725a | |
parent | 2f1ea1133a47df782925ac88bc3cecb649fb0b23 (diff) | |
download | rneovim-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.c | 55 | ||||
-rw-r--r-- | src/nvim/memfile_defs.h | 2 |
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. |