shada: Use “write then rename” variant by default for writing shada

This commit is contained in:
ZyX 2015-07-06 01:14:17 +03:00
parent 55712dcdb4
commit 602efe856a

View File

@ -44,6 +44,7 @@
#include "nvim/version.h" #include "nvim/version.h"
#include "nvim/path.h" #include "nvim/path.h"
#include "nvim/lib/ringbuf.h" #include "nvim/lib/ringbuf.h"
#include "nvim/fileio.h"
#include "nvim/strings.h" #include "nvim/strings.h"
#include "nvim/lib/khash.h" #include "nvim/lib/khash.h"
#include "nvim/lib/kvec.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 emsgu(a, ...) emsgu((char_u *) a, __VA_ARGS__)
#define home_replace_save(a, b) \ #define home_replace_save(a, b) \
((char *)home_replace_save(a, (char_u *)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 has_non_ascii(a) (has_non_ascii((char_u *)a))
#define string_convert(a, b, c) \ #define string_convert(a, b, c) \
((char *)string_convert((vimconv_T *)a, (char_u *)b, c)) ((char *)string_convert((vimconv_T *)a, (char_u *)b, c))
@ -395,7 +398,7 @@ open_file_start:
if (fd < 0) { if (fd < 0) {
if (-fd == ENOENT) { if (-fd == ENOENT) {
return -1; return fd;
} }
if (-fd == ENOMEM && !did_try_to_free) { if (-fd == ENOMEM && !did_try_to_free) {
try_to_free_memory(); try_to_free_memory();
@ -405,9 +408,11 @@ open_file_start:
if (-fd == EINTR) { if (-fd == EINTR) {
goto open_file_start; goto open_file_start;
} }
emsg3("System error while opening ShaDa file %s: %s", if (-fd != EEXIST) {
fname, strerror(-fd)); emsg3("System error while opening ShaDa file %s: %s",
return -1; fname, strerror(-fd));
}
return 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); const intptr_t fd = (intptr_t) open_file(fname, O_RDONLY, 0);
if (fd == -1) { if (fd < 0) {
return FAIL; return FAIL;
} }
@ -436,6 +441,8 @@ static int open_shada_file_for_reading(const char *const fname,
.cookie = (void *) fd, .cookie = (void *) fd,
}; };
convert_setup(&sd_reader->sd_conv, "utf-8", p_enc);
return OK; return OK;
} }
@ -531,8 +538,6 @@ int shada_read_file(const char *const file, const int flags)
return of_ret; return of_ret;
} }
convert_setup(&sd_reader.sd_conv, "utf-8", p_enc);
shada_read(&sd_reader, flags); shada_read(&sd_reader, flags);
close_file((int)(intptr_t) sd_reader.cookie); 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. /// @param[in] nomerge If true then old file is ignored.
/// ///
/// @return OK if writing was successfull, FAIL otherwise. /// @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 *const fname = shada_filename(file);
char *tempname = NULL;
ShaDaWriteDef sd_writer = (ShaDaWriteDef) { ShaDaWriteDef sd_writer = (ShaDaWriteDef) {
.write = &write_file, .write = &write_file,
.error = NULL, .error = NULL,
}; };
ShaDaReadDef sd_reader;
const intptr_t fd = (intptr_t) open_file(fname, intptr_t fd;
O_CREAT|O_WRONLY|O_NOFOLLOW|O_TRUNC,
0600); 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) { if (p_verbose > 0) {
verbose_enter(); verbose_enter();
@ -1730,8 +1776,9 @@ int shada_write_file(const char *const file, const bool nomerge)
verbose_leave(); verbose_leave();
} }
xfree(fname); if (fd < 0) {
if (fd == -1) { xfree(fname);
xfree(tempname);
return FAIL; return FAIL;
} }
@ -1742,6 +1789,19 @@ int shada_write_file(const char *const file, const bool nomerge)
shada_write(&sd_writer, NULL); shada_write(&sd_writer, NULL);
close_file((int)(intptr_t) sd_writer.cookie); 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; return OK;
} }