mirror of
https://github.com/vim/vim.git
synced 2025-09-26 04:04:07 -04:00
patch 8.1.1413: error when the drive of the swap file was disconnected
Problem: Error when the drive of the swap file was disconnected. Solution: Try closing and re-opening the swap file. (closes #4378)
This commit is contained in:
@@ -994,7 +994,8 @@ mf_write(memfile_T *mfp, bhdr_T *hp)
|
|||||||
unsigned page_count; /* number of pages written */
|
unsigned page_count; /* number of pages written */
|
||||||
unsigned size; /* number of bytes written */
|
unsigned size; /* number of bytes 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;
|
||||||
|
|
||||||
if (hp->bh_bnum < 0) /* must assign file block number */
|
if (hp->bh_bnum < 0) /* must assign file block number */
|
||||||
@@ -1011,6 +1012,8 @@ mf_write(memfile_T *mfp, bhdr_T *hp)
|
|||||||
*/
|
*/
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
int attempt;
|
||||||
|
|
||||||
nr = hp->bh_bnum;
|
nr = hp->bh_bnum;
|
||||||
if (nr > mfp->mf_infile_count) /* beyond end of file */
|
if (nr > mfp->mf_infile_count) /* beyond end of file */
|
||||||
{
|
{
|
||||||
@@ -1021,29 +1024,49 @@ mf_write(memfile_T *mfp, bhdr_T *hp)
|
|||||||
hp2 = hp;
|
hp2 = hp;
|
||||||
|
|
||||||
offset = (off_T)page_size * nr;
|
offset = (off_T)page_size * nr;
|
||||||
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;
|
||||||
size = page_size * page_count;
|
size = page_size * page_count;
|
||||||
if (mf_write_block(mfp, hp2 == NULL ? hp : hp2, offset, size) == FAIL)
|
|
||||||
|
for (attempt = 1; attempt <= 2; ++attempt)
|
||||||
{
|
{
|
||||||
/*
|
if (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
|
if (vim_lseek(mfp->mf_fd, offset, SEEK_SET) != offset)
|
||||||
* write or when hitting a key. We keep on trying, in case some
|
{
|
||||||
* space becomes available.
|
PERROR(_("E296: Seek error in swap file write"));
|
||||||
*/
|
return FAIL;
|
||||||
|
}
|
||||||
|
if (mf_write_block(mfp,
|
||||||
|
hp2 == NULL ? hp : hp2, offset, size) == OK)
|
||||||
|
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 = mch_open_rw((char *)mfp->mf_fname, mfp->mf_flags);
|
||||||
|
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)
|
if (!did_swapwrite_msg)
|
||||||
emsg(_("E297: Write error in swap file"));
|
emsg(_("E297: Write error in swap file"));
|
||||||
did_swapwrite_msg = TRUE;
|
did_swapwrite_msg = TRUE;
|
||||||
return FAIL;
|
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;
|
||||||
@@ -1271,6 +1294,7 @@ mf_do_open(
|
|||||||
* the file) */
|
* the file) */
|
||||||
flags |= O_NOINHERIT;
|
flags |= O_NOINHERIT;
|
||||||
#endif
|
#endif
|
||||||
|
mfp->mf_flags = flags;
|
||||||
mfp->mf_fd = mch_open_rw((char *)mfp->mf_fname, flags);
|
mfp->mf_fd = mch_open_rw((char *)mfp->mf_fname, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -604,28 +604,30 @@ typedef struct
|
|||||||
|
|
||||||
struct memfile
|
struct memfile
|
||||||
{
|
{
|
||||||
char_u *mf_fname; /* name of the file */
|
char_u *mf_fname; // name of the file
|
||||||
char_u *mf_ffname; /* idem, full path */
|
char_u *mf_ffname; // idem, full path
|
||||||
int mf_fd; /* file descriptor */
|
int mf_fd; // file descriptor
|
||||||
bhdr_T *mf_free_first; /* first block_hdr in free list */
|
int mf_flags; // flags used when opening this memfile
|
||||||
bhdr_T *mf_used_first; /* mru block_hdr in used list */
|
int mf_reopen; // mf_fd was closed, retry opening
|
||||||
bhdr_T *mf_used_last; /* lru block_hdr in used list */
|
bhdr_T *mf_free_first; // first block_hdr in free list
|
||||||
unsigned mf_used_count; /* number of pages in used list */
|
bhdr_T *mf_used_first; // mru block_hdr in used list
|
||||||
unsigned mf_used_count_max; /* maximum number of pages in memory */
|
bhdr_T *mf_used_last; // lru block_hdr in used list
|
||||||
mf_hashtab_T mf_hash; /* hash lists */
|
unsigned mf_used_count; // number of pages in used list
|
||||||
mf_hashtab_T mf_trans; /* trans lists */
|
unsigned mf_used_count_max; // maximum number of pages in memory
|
||||||
blocknr_T mf_blocknr_max; /* highest positive block number + 1*/
|
mf_hashtab_T mf_hash; // hash lists
|
||||||
blocknr_T mf_blocknr_min; /* lowest negative block number - 1 */
|
mf_hashtab_T mf_trans; // trans lists
|
||||||
blocknr_T mf_neg_count; /* number of negative blocks numbers */
|
blocknr_T mf_blocknr_max; // highest positive block number + 1
|
||||||
blocknr_T mf_infile_count; /* number of pages in the file */
|
blocknr_T mf_blocknr_min; // lowest negative block number - 1
|
||||||
unsigned mf_page_size; /* number of bytes in a page */
|
blocknr_T mf_neg_count; // number of negative blocks numbers
|
||||||
int mf_dirty; /* TRUE if there are dirty blocks */
|
blocknr_T mf_infile_count; // number of pages in the file
|
||||||
|
unsigned mf_page_size; // number of bytes in a page
|
||||||
|
int mf_dirty; // TRUE if there are dirty blocks
|
||||||
#ifdef FEAT_CRYPT
|
#ifdef FEAT_CRYPT
|
||||||
buf_T *mf_buffer; /* buffer this memfile is for */
|
buf_T *mf_buffer; // buffer this memfile is for
|
||||||
char_u mf_seed[MF_SEED_LEN]; /* seed for encryption */
|
char_u mf_seed[MF_SEED_LEN]; // seed for encryption
|
||||||
|
|
||||||
/* Values for key, method and seed used for reading data blocks when
|
// Values for key, method and seed used for reading data blocks when
|
||||||
* updating for a newly set key or method. Only when mf_old_key != NULL. */
|
// updating for a newly set key or method. Only when mf_old_key != NULL.
|
||||||
char_u *mf_old_key;
|
char_u *mf_old_key;
|
||||||
int mf_old_cm;
|
int mf_old_cm;
|
||||||
char_u mf_old_seed[MF_SEED_LEN];
|
char_u mf_old_seed[MF_SEED_LEN];
|
||||||
|
@@ -288,24 +288,24 @@ func Test_q_arg()
|
|||||||
|
|
||||||
" Test with default argument '-q'.
|
" Test with default argument '-q'.
|
||||||
call assert_equal('errors.err', &errorfile)
|
call assert_equal('errors.err', &errorfile)
|
||||||
call writefile(["../memfile.c:1482:5: error: expected ';' before '}' token"], 'errors.err')
|
call writefile(["../memfile.c:208:5: error: expected ';' before '}' token"], 'errors.err')
|
||||||
if RunVim([], after, '-q')
|
if RunVim([], after, '-q')
|
||||||
let lines = readfile('Xtestout')
|
let lines = readfile('Xtestout')
|
||||||
call assert_equal(['errors.err',
|
call assert_equal(['errors.err',
|
||||||
\ '[0, 1482, 5, 0]',
|
\ '[0, 208, 5, 0]',
|
||||||
\ source_file . "|1482 col 5| error: expected ';' before '}' token"],
|
\ source_file . "|208 col 5| error: expected ';' before '}' token"],
|
||||||
\ lines)
|
\ lines)
|
||||||
endif
|
endif
|
||||||
call delete('Xtestout')
|
call delete('Xtestout')
|
||||||
call delete('errors.err')
|
call delete('errors.err')
|
||||||
|
|
||||||
" Test with explicit argument '-q Xerrors' (with space).
|
" Test with explicit argument '-q Xerrors' (with space).
|
||||||
call writefile(["../memfile.c:1482:5: error: expected ';' before '}' token"], 'Xerrors')
|
call writefile(["../memfile.c:208:5: error: expected ';' before '}' token"], 'Xerrors')
|
||||||
if RunVim([], after, '-q Xerrors')
|
if RunVim([], after, '-q Xerrors')
|
||||||
let lines = readfile('Xtestout')
|
let lines = readfile('Xtestout')
|
||||||
call assert_equal(['Xerrors',
|
call assert_equal(['Xerrors',
|
||||||
\ '[0, 1482, 5, 0]',
|
\ '[0, 208, 5, 0]',
|
||||||
\ source_file . "|1482 col 5| error: expected ';' before '}' token"],
|
\ source_file . "|208 col 5| error: expected ';' before '}' token"],
|
||||||
\ lines)
|
\ lines)
|
||||||
endif
|
endif
|
||||||
call delete('Xtestout')
|
call delete('Xtestout')
|
||||||
@@ -314,8 +314,8 @@ func Test_q_arg()
|
|||||||
if RunVim([], after, '-qXerrors')
|
if RunVim([], after, '-qXerrors')
|
||||||
let lines = readfile('Xtestout')
|
let lines = readfile('Xtestout')
|
||||||
call assert_equal(['Xerrors',
|
call assert_equal(['Xerrors',
|
||||||
\ '[0, 1482, 5, 0]',
|
\ '[0, 208, 5, 0]',
|
||||||
\ source_file . "|1482 col 5| error: expected ';' before '}' token"],
|
\ source_file . "|208 col 5| error: expected ';' before '}' token"],
|
||||||
\ lines)
|
\ lines)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@@ -767,6 +767,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1413,
|
||||||
/**/
|
/**/
|
||||||
1412,
|
1412,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user