aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZyX <kp-pav@yandex.ru>2015-07-06 01:14:17 +0300
committerZyX <kp-pav@yandex.ru>2015-10-08 22:00:05 +0300
commit602efe856a20df22a69c2bfc5de211064248034c (patch)
tree7ee027c6b33cd2c7d41cdb765bd8a550f54758bd /src
parent55712dcdb43cf8ace896e955d41c22156cd79cc4 (diff)
downloadrneovim-602efe856a20df22a69c2bfc5de211064248034c.tar.gz
rneovim-602efe856a20df22a69c2bfc5de211064248034c.tar.bz2
rneovim-602efe856a20df22a69c2bfc5de211064248034c.zip
shada: Use “write then rename” variant by default for writing shada
Diffstat (limited to 'src')
-rw-r--r--src/nvim/shada.c86
1 files changed, 73 insertions, 13 deletions
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index 72933df9a4..8a383b08a6 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -44,6 +44,7 @@
#include "nvim/version.h"
#include "nvim/path.h"
#include "nvim/lib/ringbuf.h"
+#include "nvim/fileio.h"
#include "nvim/strings.h"
#include "nvim/lib/khash.h"
#include "nvim/lib/kvec.h"
@@ -69,6 +70,8 @@ KHASH_MAP_INIT_STR(fnamebufs, buf_T *)
#define emsgu(a, ...) emsgu((char_u *) a, __VA_ARGS__)
#define home_replace_save(a, b) \
((char *)home_replace_save(a, (char_u *)b))
+#define vim_rename(a, b) \
+ (vim_rename((char_u *)a, (char_u *)b))
#define has_non_ascii(a) (has_non_ascii((char_u *)a))
#define string_convert(a, b, c) \
((char *)string_convert((vimconv_T *)a, (char_u *)b, c))
@@ -395,7 +398,7 @@ open_file_start:
if (fd < 0) {
if (-fd == ENOENT) {
- return -1;
+ return fd;
}
if (-fd == ENOMEM && !did_try_to_free) {
try_to_free_memory();
@@ -405,9 +408,11 @@ open_file_start:
if (-fd == EINTR) {
goto open_file_start;
}
- emsg3("System error while opening ShaDa file %s: %s",
- fname, strerror(-fd));
- return -1;
+ if (-fd != EEXIST) {
+ emsg3("System error while opening ShaDa file %s: %s",
+ fname, strerror(-fd));
+ }
+ return fd;
}
return fd;
}
@@ -424,7 +429,7 @@ static int open_shada_file_for_reading(const char *const fname,
{
const intptr_t fd = (intptr_t) open_file(fname, O_RDONLY, 0);
- if (fd == -1) {
+ if (fd < 0) {
return FAIL;
}
@@ -436,6 +441,8 @@ static int open_shada_file_for_reading(const char *const fname,
.cookie = (void *) fd,
};
+ convert_setup(&sd_reader->sd_conv, "utf-8", p_enc);
+
return OK;
}
@@ -531,8 +538,6 @@ int shada_read_file(const char *const file, const int flags)
return of_ret;
}
- convert_setup(&sd_reader.sd_conv, "utf-8", p_enc);
-
shada_read(&sd_reader, flags);
close_file((int)(intptr_t) sd_reader.cookie);
@@ -1712,17 +1717,58 @@ static void shada_write(ShaDaWriteDef *const sd_writer,
/// @param[in] nomerge If true then old file is ignored.
///
/// @return OK if writing was successfull, FAIL otherwise.
-int shada_write_file(const char *const file, const bool nomerge)
+int shada_write_file(const char *const file, bool nomerge)
{
char *const fname = shada_filename(file);
+ char *tempname = NULL;
ShaDaWriteDef sd_writer = (ShaDaWriteDef) {
.write = &write_file,
.error = NULL,
};
+ ShaDaReadDef sd_reader;
- const intptr_t fd = (intptr_t) open_file(fname,
- O_CREAT|O_WRONLY|O_NOFOLLOW|O_TRUNC,
- 0600);
+ intptr_t fd;
+
+ if (!nomerge) {
+ if (open_shada_file_for_reading(fname, &sd_reader) != OK) {
+ nomerge = true;
+ goto shada_write_file_nomerge;
+ }
+ tempname = modname(fname, ".tmp.a", false);
+ if (tempname == NULL) {
+ nomerge = true;
+ goto shada_write_file_nomerge;
+ }
+
+shada_write_file_open:
+ fd = (intptr_t) open_file(tempname, O_CREAT|O_WRONLY|O_NOFOLLOW|O_EXCL,
+ 0600);
+ if (fd < 0) {
+ if (-fd == EEXIST
+#ifdef ELOOP
+ || -fd == ELOOP
+#endif
+ ) {
+ // File already exists, try another name
+ char *const wp = tempname + strlen(tempname) - 1;
+ if (*wp == 'z') {
+ // Tried names from .tmp.a to .tmp.z, all failed. Something must be
+ // wrong then.
+ xfree(fname);
+ xfree(tempname);
+ return FAIL;
+ } else {
+ (*wp)++;
+ goto shada_write_file_open;
+ }
+ }
+ }
+ }
+ if (nomerge) {
+shada_write_file_nomerge:
+ fd = (intptr_t) open_file(fname, O_CREAT|O_WRONLY|O_TRUNC,
+ 0600);
+ }
if (p_verbose > 0) {
verbose_enter();
@@ -1730,8 +1776,9 @@ int shada_write_file(const char *const file, const bool nomerge)
verbose_leave();
}
- xfree(fname);
- if (fd == -1) {
+ if (fd < 0) {
+ xfree(fname);
+ xfree(tempname);
return FAIL;
}
@@ -1742,6 +1789,19 @@ int shada_write_file(const char *const file, const bool nomerge)
shada_write(&sd_writer, NULL);
close_file((int)(intptr_t) sd_writer.cookie);
+
+ if (!nomerge) {
+ close_file((int)(intptr_t) sd_reader.cookie);
+ if (vim_rename(tempname, fname) == -1) {
+ EMSG3(_("E886: Can't rename viminfo file from %s to %s!"),
+ tempname, fname);
+ } else {
+ os_remove(tempname);
+ }
+ xfree(tempname);
+ }
+
+ xfree(fname);
return OK;
}