mirror of
https://github.com/neovim/neovim.git
synced 2024-12-24 13:15:09 -07:00
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)
b58a4b938c
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
parent
2f1ea1133a
commit
a89088b7a0
@ -566,7 +566,8 @@ static int mf_write(memfile_T *mfp, bhdr_T *hp)
|
|||||||
bhdr_T *hp2;
|
bhdr_T *hp2;
|
||||||
unsigned page_count; // number of pages written
|
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;
|
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.
|
// TODO(elmart): Check (page_size * nr) within off_T bounds.
|
||||||
off_T offset = (off_T)(page_size * nr); // offset in the file
|
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
|
if (hp2 == NULL) { // freed block, fill with dummy data
|
||||||
page_count = 1;
|
page_count = 1;
|
||||||
} else {
|
} else {
|
||||||
page_count = hp2->bh_page_count;
|
page_count = hp2->bh_page_count;
|
||||||
}
|
}
|
||||||
unsigned size = page_size * page_count; // number of bytes written
|
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) {
|
for (int attempt = 1; attempt <= 2; attempt++) {
|
||||||
/// Avoid repeating the error message, this mostly happens when the
|
if (mfp->mf_fd >= 0) {
|
||||||
/// disk is full. We give the message again only after a successful
|
if (vim_lseek(mfp->mf_fd, offset, SEEK_SET) != offset) {
|
||||||
/// write or when hitting a key. We keep on trying, in case some
|
PERROR(_("E296: Seek error in swap file write"));
|
||||||
/// space becomes available.
|
return FAIL;
|
||||||
if (!did_swapwrite_msg) {
|
}
|
||||||
emsg(_("E297: Write error in swap file"));
|
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;
|
did_swapwrite_msg = false;
|
||||||
if (hp2 != NULL) { // written a non-dummy block
|
if (hp2 != NULL) { // written a non-dummy block
|
||||||
hp2->bh_flags &= ~BH_DIRTY;
|
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?)"));
|
emsg(_("E300: Swap file already exists (symlink attack?)"));
|
||||||
} else {
|
} else {
|
||||||
// try to open the file
|
// 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
|
// If the file cannot be opened, use memory only
|
||||||
|
@ -46,6 +46,8 @@ typedef struct {
|
|||||||
char *mf_fname; ///< name of the file
|
char *mf_fname; ///< name of the file
|
||||||
char *mf_ffname; ///< idem, full path
|
char *mf_ffname; ///< idem, full path
|
||||||
int mf_fd; ///< file descriptor
|
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
|
bhdr_T *mf_free_first; ///< first block header in free list
|
||||||
|
|
||||||
/// The used blocks are kept in mf_hash.
|
/// The used blocks are kept in mf_hash.
|
||||||
|
Loading…
Reference in New Issue
Block a user