summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/memfile.c58
-rw-r--r--src/structs.h42
-rw-r--r--src/testdir/test_startup.vim16
-rw-r--r--src/version.c2
4 files changed, 73 insertions, 45 deletions
diff --git a/src/memfile.c b/src/memfile.c
index 9a1b4cb1c..5bc587c1f 100644
--- a/src/memfile.c
+++ b/src/memfile.c
@@ -994,7 +994,8 @@ mf_write(memfile_T *mfp, bhdr_T *hp)
unsigned page_count; /* number of pages 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;
if (hp->bh_bnum < 0) /* must assign file block number */
@@ -1011,6 +1012,8 @@ mf_write(memfile_T *mfp, bhdr_T *hp)
*/
for (;;)
{
+ int attempt;
+
nr = hp->bh_bnum;
if (nr > mfp->mf_infile_count) /* beyond end of file */
{
@@ -1021,29 +1024,49 @@ mf_write(memfile_T *mfp, bhdr_T *hp)
hp2 = hp;
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 */
page_count = 1;
else
page_count = hp2->bh_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)
{
- /*
- * 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;
+ 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;
+ }
+ 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)
+ emsg(_("E297: Write error in swap file"));
+ did_swapwrite_msg = TRUE;
+ return FAIL;
+ }
}
+
did_swapwrite_msg = FALSE;
if (hp2 != NULL) /* written a non-dummy block */
hp2->bh_flags &= ~BH_DIRTY;
@@ -1271,6 +1294,7 @@ mf_do_open(
* the file) */
flags |= O_NOINHERIT;
#endif
+ mfp->mf_flags = flags;
mfp->mf_fd = mch_open_rw((char *)mfp->mf_fname, flags);
}
diff --git a/src/structs.h b/src/structs.h
index 07dc7e3be..79681cc2a 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -604,28 +604,30 @@ typedef struct
struct memfile
{
- char_u *mf_fname; /* name of the file */
- char_u *mf_ffname; /* idem, full path */
- int mf_fd; /* file descriptor */
- bhdr_T *mf_free_first; /* first block_hdr in free list */
- bhdr_T *mf_used_first; /* mru block_hdr in used list */
- bhdr_T *mf_used_last; /* lru block_hdr in used list */
- unsigned mf_used_count; /* number of pages in used list */
- unsigned mf_used_count_max; /* maximum number of pages in memory */
- 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 */
- int mf_dirty; /* TRUE if there are dirty blocks */
+ char_u *mf_fname; // name of the file
+ char_u *mf_ffname; // idem, full path
+ int mf_fd; // file descriptor
+ int mf_flags; // flags used when opening this memfile
+ int mf_reopen; // mf_fd was closed, retry opening
+ bhdr_T *mf_free_first; // first block_hdr in free list
+ bhdr_T *mf_used_first; // mru block_hdr in used list
+ bhdr_T *mf_used_last; // lru block_hdr in used list
+ unsigned mf_used_count; // number of pages in used list
+ unsigned mf_used_count_max; // maximum number of pages in memory
+ 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
+ int mf_dirty; // TRUE if there are dirty blocks
#ifdef FEAT_CRYPT
- buf_T *mf_buffer; /* buffer this memfile is for */
- char_u mf_seed[MF_SEED_LEN]; /* seed for encryption */
+ buf_T *mf_buffer; // buffer this memfile is for
+ char_u mf_seed[MF_SEED_LEN]; // seed for encryption
- /* 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. */
+ // 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.
char_u *mf_old_key;
int mf_old_cm;
char_u mf_old_seed[MF_SEED_LEN];
diff --git a/src/testdir/test_startup.vim b/src/testdir/test_startup.vim
index 33257f79f..0ce8c81e6 100644
--- a/src/testdir/test_startup.vim
+++ b/src/testdir/test_startup.vim
@@ -288,24 +288,24 @@ func Test_q_arg()
" Test with default argument '-q'.
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')
let lines = readfile('Xtestout')
call assert_equal(['errors.err',
- \ '[0, 1482, 5, 0]',
- \ source_file . "|1482 col 5| error: expected ';' before '}' token"],
+ \ '[0, 208, 5, 0]',
+ \ source_file . "|208 col 5| error: expected ';' before '}' token"],
\ lines)
endif
call delete('Xtestout')
call delete('errors.err')
" 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')
let lines = readfile('Xtestout')
call assert_equal(['Xerrors',
- \ '[0, 1482, 5, 0]',
- \ source_file . "|1482 col 5| error: expected ';' before '}' token"],
+ \ '[0, 208, 5, 0]',
+ \ source_file . "|208 col 5| error: expected ';' before '}' token"],
\ lines)
endif
call delete('Xtestout')
@@ -314,8 +314,8 @@ func Test_q_arg()
if RunVim([], after, '-qXerrors')
let lines = readfile('Xtestout')
call assert_equal(['Xerrors',
- \ '[0, 1482, 5, 0]',
- \ source_file . "|1482 col 5| error: expected ';' before '}' token"],
+ \ '[0, 208, 5, 0]',
+ \ source_file . "|208 col 5| error: expected ';' before '}' token"],
\ lines)
endif
diff --git a/src/version.c b/src/version.c
index d5221414f..240aa702c 100644
--- a/src/version.c
+++ b/src/version.c
@@ -768,6 +768,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1413,
+/**/
1412,
/**/
1411,