aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/eval.c7
-rw-r--r--src/nvim/ex_docmd.c4
-rw-r--r--src/nvim/memline.c2
-rw-r--r--src/nvim/option.c8
-rw-r--r--src/nvim/os/stdpaths.c8
-rw-r--r--src/nvim/undo.c172
6 files changed, 120 insertions, 81 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index a1ac713a75..7685e422fc 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -16678,10 +16678,11 @@ static void f_undofile(typval_T *argvars, typval_T *rettv)
/* If there is no file name there will be no undo file. */
rettv->vval.v_string = NULL;
} else {
- char_u *ffname = (char_u *)FullName_save((char *)fname, FALSE);
+ char *ffname = FullName_save((char *)fname, false);
- if (ffname != NULL)
- rettv->vval.v_string = u_get_undo_file_name(ffname, FALSE);
+ if (ffname != NULL) {
+ rettv->vval.v_string = (char_u *)u_get_undo_file_name(ffname, false);
+ }
xfree(ffname);
}
}
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index e160281145..70cf5fd029 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -7193,7 +7193,7 @@ static void ex_wundo(exarg_T *eap)
char_u hash[UNDO_HASH_SIZE];
u_compute_hash(hash);
- u_write_undo(eap->arg, eap->forceit, curbuf, hash);
+ u_write_undo((char *) eap->arg, eap->forceit, curbuf, hash);
}
static void ex_rundo(exarg_T *eap)
@@ -7201,7 +7201,7 @@ static void ex_rundo(exarg_T *eap)
char_u hash[UNDO_HASH_SIZE];
u_compute_hash(hash);
- u_read_undo(eap->arg, hash, NULL);
+ u_read_undo((char *) eap->arg, hash, NULL);
}
/*
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index dbb24e67a1..85f545f960 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -2990,7 +2990,7 @@ static void ml_lineadd(buf_T *buf, int count)
* If it worked returns OK and the resolved link in "buf[MAXPATHL]".
* Otherwise returns FAIL.
*/
-int resolve_symlink(char_u *fname, char_u *buf)
+int resolve_symlink(const char_u *fname, char_u *buf)
{
char_u tmp[MAXPATHL];
int ret;
diff --git a/src/nvim/option.c b/src/nvim/option.c
index f30d10d0bb..cc4df28837 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -685,9 +685,13 @@ void set_init_1(void)
#endif
false);
+ char *backupdir = stdpaths_user_data_subpath("backup", 0);
+ const size_t backupdir_len = strlen(backupdir);
+ backupdir = xrealloc(backupdir, backupdir_len + 3);
+ memmove(backupdir + 2, backupdir, backupdir_len + 1);
+ memmove(backupdir, ".,", 2);
set_string_default("viewdir", stdpaths_user_data_subpath("view", 0), true);
- set_string_default("backupdir", stdpaths_user_data_subpath("backup", 0),
- true);
+ set_string_default("backupdir", backupdir, true);
set_string_default("directory", stdpaths_user_data_subpath("swap", 2), true);
set_string_default("undodir", stdpaths_user_data_subpath("undo", 0), true);
// Set default for &runtimepath. All necessary expansions are performed in
diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c
index ce374828f9..c9631a434c 100644
--- a/src/nvim/os/stdpaths.c
+++ b/src/nvim/os/stdpaths.c
@@ -25,7 +25,7 @@ static const char *const xdg_defaults[] = {
[kXDGConfigHome] = "$LOCALAPPDATA\\nvim\\config",
[kXDGDataHome] = "$LOCALAPPDATA\\nvim\\data",
[kXDGCacheHome] = "$LOCALAPPDATA\\nvim\\cache",
- [kXDGRuntimeDir] = "",
+ [kXDGRuntimeDir] = NULL,
[kXDGConfigDirs] = NULL,
[kXDGDataDirs] = NULL,
#else
@@ -33,7 +33,7 @@ static const char *const xdg_defaults[] = {
[kXDGConfigHome] = "~/.config",
[kXDGDataHome] = "~/.local/share",
[kXDGCacheHome] = "~/.cache",
- [kXDGRuntimeDir] = "",
+ [kXDGRuntimeDir] = NULL,
[kXDGConfigDirs] = "/etc/xdg/",
[kXDGDataDirs] = "/usr/local/share/:/usr/share/",
#endif
@@ -82,7 +82,7 @@ static char *get_xdg_home(const XDGVarType idx)
///
/// @return [allocated] `$XDG_CONFIG_HOME/nvim/{fname}`
char *stdpaths_user_conf_subpath(const char *fname)
- FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{
return concat_fnames_realloc(get_xdg_home(kXDGConfigHome), fname, true);
}
@@ -95,7 +95,7 @@ char *stdpaths_user_conf_subpath(const char *fname)
/// @return [allocated] `$XDG_DATA_HOME/nvim/{fname}`
char *stdpaths_user_data_subpath(const char *fname,
const size_t trailing_pathseps)
- FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{
char *ret = concat_fnames_realloc(get_xdg_home(kXDGDataHome), fname, true);
if (trailing_pathseps) {
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 2b0ffefa7e..d8158bf7cd 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -638,64 +638,89 @@ void u_compute_hash(char_u *hash)
sha256_finish(&ctx, hash);
}
-/*
- * Return an allocated string of the full path of the target undofile.
- * When "reading" is TRUE find the file to read, go over all directories in
- * 'undodir'.
- * When "reading" is FALSE use the first name where the directory exists.
- * Returns NULL when there is no place to write or no file to read.
- */
-char_u *u_get_undo_file_name(char_u *buf_ffname, int reading)
+/// Return an allocated string of the full path of the target undofile.
+///
+/// @param[in] buf_ffname Full file name for which undo file location should
+/// be found.
+/// @param[in] reading If true, find the file to read by traversing all of the
+/// directories in &undodir. If false use the first
+/// existing directory. If none of the directories in
+/// &undodir option exist then last directory in the list
+/// will be automatically created.
+///
+/// @return [allocated] File name to read from/write to or NULL.
+char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
- char_u *dirp;
- char_u dir_name[IOSIZE + 1];
- char_u *munged_name = NULL;
- char_u *undo_file_name = NULL;
- char_u *p;
- char_u *ffname = buf_ffname;
+ char *dirp;
+ char dir_name[MAXPATHL + 1];
+ char *munged_name = NULL;
+ char *undo_file_name = NULL;
+ const char *ffname = buf_ffname;
#ifdef HAVE_READLINK
- char_u fname_buf[MAXPATHL];
+ char fname_buf[MAXPATHL];
#endif
- if (ffname == NULL)
+ if (ffname == NULL) {
return NULL;
+ }
#ifdef HAVE_READLINK
- /* Expand symlink in the file name, so that we put the undo file with the
- * actual file instead of with the symlink. */
- if (resolve_symlink(ffname, fname_buf) == OK)
+ // Expand symlink in the file name, so that we put the undo file with the
+ // actual file instead of with the symlink.
+ if (resolve_symlink((const char_u *)ffname, (char_u *)fname_buf) == OK) {
ffname = fname_buf;
+ }
#endif
- /* Loop over 'undodir'. When reading find the first file that exists.
- * When not reading use the first directory that exists or ".". */
- dirp = p_udir;
+ // Loop over 'undodir'. When reading find the first file that exists.
+ // When not reading use the first directory that exists or ".".
+ dirp = (char *) p_udir;
while (*dirp != NUL) {
- size_t dir_len = copy_option_part(&dirp, dir_name, IOSIZE, ",");
+ size_t dir_len = copy_option_part((char_u **)&dirp, (char_u *)dir_name,
+ MAXPATHL, ",");
if (dir_len == 1 && dir_name[0] == '.') {
- /* Use same directory as the ffname,
- * "dir/name" -> "dir/.name.un~" */
- undo_file_name = vim_strnsave(ffname, STRLEN(ffname) + 5);
- p = path_tail(undo_file_name);
- memmove(p + 1, p, STRLEN(p) + 1);
- *p = '.';
- STRCAT(p, ".un~");
+ // Use same directory as the ffname,
+ // "dir/name" -> "dir/.name.un~"
+ const size_t ffname_len = strlen(ffname);
+ undo_file_name = xmalloc(ffname_len + 6);
+ memmove(undo_file_name, ffname, ffname_len + 1);
+ char *const tail = (char *) path_tail((char_u *) undo_file_name);
+ const size_t tail_len = strlen(tail);
+ memmove(tail + 1, tail, tail_len + 1);
+ *tail = '.';
+ memmove(tail + tail_len + 1, ".un~", sizeof(".un~"));
} else {
dir_name[dir_len] = NUL;
- if (os_isdir(dir_name)) {
+ bool has_directory = os_isdir((char_u *)dir_name);
+ if (!has_directory && *dirp == NUL && !reading) {
+ // Last directory in the list does not exist, create it.
+ int ret;
+ char *failed_dir;
+ if ((ret = os_mkdir_recurse(dir_name, 0755, &failed_dir)) != 0) {
+ EMSG3(_("E926: Unable to create directory \"%s\" for undo file: %s"),
+ failed_dir, os_strerror(ret));
+ xfree(failed_dir);
+ } else {
+ has_directory = true;
+ }
+ }
+ if (has_directory) {
if (munged_name == NULL) {
- munged_name = vim_strsave(ffname);
- for (p = munged_name; *p != NUL; mb_ptr_adv(p))
- if (vim_ispathsep(*p))
+ munged_name = xstrdup(ffname);
+ for (char *p = munged_name; *p != NUL; mb_ptr_adv(p)) {
+ if (vim_ispathsep(*p)) {
*p = '%';
+ }
+ }
}
- undo_file_name = (char_u *)concat_fnames((char *)dir_name, (char *)munged_name, TRUE);
+ undo_file_name = concat_fnames(dir_name, munged_name, true);
}
}
// When reading check if the file exists.
- if (undo_file_name != NULL &&
- (!reading || os_file_exists(undo_file_name))) {
+ if (undo_file_name != NULL
+ && (!reading || os_file_exists((char_u *)undo_file_name))) {
break;
}
xfree(undo_file_name);
@@ -706,7 +731,13 @@ char_u *u_get_undo_file_name(char_u *buf_ffname, int reading)
return undo_file_name;
}
-static void corruption_error(char *mesg, char_u *file_name)
+/// Display an error for corrupted undo file
+///
+/// @param[in] mesg Identifier of the corruption kind.
+/// @param[in] file_name File in which error occurred.
+static void corruption_error(const char *const mesg,
+ const char *const file_name)
+ FUNC_ATTR_NONNULL_ALL
{
EMSG3(_("E825: Corrupted undo file (%s): %s"), mesg, file_name);
}
@@ -821,7 +852,8 @@ static bool serialize_uhp(bufinfo_T *bi, u_header_T *uhp)
return true;
}
-static u_header_T *unserialize_uhp(bufinfo_T *bi, char_u *file_name)
+static u_header_T *unserialize_uhp(bufinfo_T *bi,
+ const char *file_name)
{
u_header_T *uhp = xmalloc(sizeof(u_header_T));
memset(uhp, 0, sizeof(u_header_T));
@@ -918,7 +950,8 @@ static bool serialize_uep(bufinfo_T *bi, u_entry_T *uep)
return true;
}
-static u_entry_T *unserialize_uep(bufinfo_T * bi, bool *error, char_u *file_name)
+static u_entry_T *unserialize_uep(bufinfo_T * bi, bool *error,
+ const char *file_name)
{
u_entry_T *uep = xmalloc(sizeof(u_entry_T));
memset(uep, 0, sizeof(u_entry_T));
@@ -1000,19 +1033,20 @@ static void unserialize_visualinfo(bufinfo_T *bi, visualinfo_T *info)
info->vi_curswant = undo_read_4c(bi);
}
-/*
- * Write the undo tree in an undo file.
- * When "name" is not NULL, use it as the name of the undo file.
- * Otherwise use buf->b_ffname to generate the undo file name.
- * "buf" must never be null, buf->b_ffname is used to obtain the original file
- * permissions.
- * "forceit" is TRUE for ":wundo!", FALSE otherwise.
- * "hash[UNDO_HASH_SIZE]" must be the hash value of the buffer text.
- */
-void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash)
+/// Write the undo tree in an undo file.
+///
+/// @param[in] name Name of the undo file or NULL if this function needs to
+/// generate the undo file name based on buf->b_ffname.
+/// @param[in] forceit True for `:wundo!`, false otherwise.
+/// @param[in] buf Buffer for which undo file is written.
+/// @param[in] hash Hash value of the buffer text. Must have #UNDO_HASH_SIZE
+/// size.
+void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
+ char_u *const hash)
+ FUNC_ATTR_NONNULL_ARG(3, 4)
{
u_header_T *uhp;
- char_u *file_name;
+ char *file_name;
int mark;
#ifdef U_DEBUG
int headers_written = 0;
@@ -1024,7 +1058,7 @@ void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash)
bufinfo_T bi;
if (name == NULL) {
- file_name = u_get_undo_file_name(buf->b_ffname, FALSE);
+ file_name = u_get_undo_file_name((char *) buf->b_ffname, false);
if (file_name == NULL) {
if (p_verbose > 0) {
verbose_enter();
@@ -1033,8 +1067,9 @@ void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash)
}
return;
}
- } else
- file_name = name;
+ } else {
+ file_name = (char *) name;
+ }
/*
* Decide about the permission to use for the undo file. If the buffer
@@ -1054,10 +1089,10 @@ void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash)
/* If the undo file already exists, verify that it actually is an undo
* file, and delete it. */
- if (os_file_exists(file_name)) {
+ if (os_file_exists((char_u *)file_name)) {
if (name == NULL || !forceit) {
/* Check we can read it and it's an undo file. */
- fd = os_open((char *)file_name, O_RDONLY, 0);
+ fd = os_open(file_name, O_RDONLY, 0);
if (fd < 0) {
if (name != NULL || p_verbose > 0) {
if (name == NULL)
@@ -1086,7 +1121,7 @@ void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash)
}
}
}
- os_remove((char *)file_name);
+ os_remove(file_name);
}
/* If there is no undo information at all, quit here after deleting any
@@ -1097,13 +1132,12 @@ void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash)
goto theend;
}
- fd = os_open((char *)file_name,
- O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, perm);
+ fd = os_open(file_name, O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, perm);
if (fd < 0) {
EMSG2(_(e_not_open), file_name);
goto theend;
}
- (void)os_setperm(file_name, perm);
+ (void)os_setperm((char_u *)file_name, perm);
if (p_verbose > 0) {
verbose_enter();
smsg(_("Writing undo file: %s"), file_name);
@@ -1125,10 +1159,10 @@ void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash)
FileInfo file_info_new;
if (buf->b_ffname != NULL
&& os_fileinfo((char *)buf->b_ffname, &file_info_old)
- && os_fileinfo((char *)file_name, &file_info_new)
+ && os_fileinfo(file_name, &file_info_new)
&& file_info_old.stat.st_gid != file_info_new.stat.st_gid
&& os_fchown(fd, (uv_uid_t)-1, (uv_gid_t)file_info_old.stat.st_gid)) {
- os_setperm(file_name, (perm & 0707) | ((perm & 07) << 3));
+ os_setperm((char_u *)file_name, (perm & 0707) | ((perm & 07) << 3));
}
# ifdef HAVE_SELINUX
if (buf->b_ffname != NULL)
@@ -1140,7 +1174,7 @@ void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash)
if (fp == NULL) {
EMSG2(_(e_not_open), file_name);
close(fd);
- os_remove((char *)file_name);
+ os_remove(file_name);
goto theend;
}
@@ -1209,7 +1243,7 @@ write_error:
/* For systems that support ACL: get the ACL from the original file. */
acl = mch_get_acl(buf->b_ffname);
- mch_set_acl(file_name, acl);
+ mch_set_acl((char_u *)file_name, acl);
mch_free_acl(acl);
}
#endif
@@ -1224,15 +1258,15 @@ theend:
/// a bit more verbose.
/// Otherwise use curbuf->b_ffname to generate the undo file name.
/// "hash[UNDO_HASH_SIZE]" must be the hash value of the buffer text.
-void u_read_undo(char_u *name, char_u *hash, char_u *orig_name)
+void u_read_undo(char *name, char_u *hash, char_u *orig_name)
FUNC_ATTR_NONNULL_ARG(2)
{
u_header_T **uhp_table = NULL;
char_u *line_ptr = NULL;
- char_u *file_name;
+ char *file_name;
if (name == NULL) {
- file_name = u_get_undo_file_name(curbuf->b_ffname, TRUE);
+ file_name = u_get_undo_file_name((char *) curbuf->b_ffname, true);
if (file_name == NULL) {
return;
}
@@ -1256,7 +1290,7 @@ void u_read_undo(char_u *name, char_u *hash, char_u *orig_name)
}
#endif
} else {
- file_name = name;
+ file_name = (char *) name;
}
if (p_verbose > 0) {
@@ -1265,7 +1299,7 @@ void u_read_undo(char_u *name, char_u *hash, char_u *orig_name)
verbose_leave();
}
- FILE *fp = mch_fopen((char *)file_name, "r");
+ FILE *fp = mch_fopen(file_name, "r");
if (fp == NULL) {
if (name != NULL || p_verbose > 0) {
EMSG2(_("E822: Cannot open undo file for reading: %s"), file_name);