aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/fileio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/fileio.c')
-rw-r--r--src/nvim/fileio.c111
1 files changed, 47 insertions, 64 deletions
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index df9c4928c9..724d754ca7 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -27,6 +27,7 @@
#include "nvim/diff.h"
#include "nvim/drawscreen.h"
#include "nvim/edit.h"
+#include "nvim/errors.h"
#include "nvim/eval.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_eval.h"
@@ -887,10 +888,7 @@ retry:
// Use buffer >= 64K. Add linerest to double the size if the
// line gets very long, to avoid a lot of copying. But don't
// read more than 1 Mbyte at a time, so we can be interrupted.
- size = 0x10000 + linerest;
- if (size > 0x100000) {
- size = 0x100000;
- }
+ size = MIN(0x10000 + linerest, 0x100000);
}
// Protect against the argument of lalloc() going negative.
@@ -2418,7 +2416,7 @@ char *modname(const char *fname, const char *ext, bool prepend_dot)
// the file name has at most BASENAMELEN characters.
if (strlen(ptr) > BASENAMELEN) {
- ptr[BASENAMELEN] = '\0';
+ ptr[BASENAMELEN] = NUL;
}
char *s = ptr + strlen(ptr);
@@ -2656,7 +2654,6 @@ static int rename_with_tmp(const char *const from, const char *const to)
int vim_rename(const char *from, const char *to)
FUNC_ATTR_NONNULL_ALL
{
- char *errmsg = NULL;
bool use_tmp_file = false;
// When the names are identical, there is nothing to do. When they refer
@@ -2700,61 +2697,57 @@ int vim_rename(const char *from, const char *to)
}
// Rename() failed, try copying the file.
- int perm = os_getperm(from);
- // For systems that support ACL: get the ACL from the original file.
- vim_acl_T acl = os_get_acl(from);
- int fd_in = os_open(from, O_RDONLY, 0);
- if (fd_in < 0) {
- os_free_acl(acl);
+ int ret = vim_copyfile(from, to);
+ if (ret != OK) {
return -1;
}
- // Create the new file with same permissions as the original.
- int fd_out = os_open(to, O_CREAT|O_EXCL|O_WRONLY|O_NOFOLLOW, perm);
- if (fd_out < 0) {
- close(fd_in);
- os_free_acl(acl);
- return -1;
+ if (os_fileinfo(from, &from_info)) {
+ os_remove(from);
}
- // Avoid xmalloc() here as vim_rename() is called by buf_write() when nvim
- // is `preserve_exit()`ing.
- char *buffer = try_malloc(WRITEBUFSIZE);
- if (buffer == NULL) {
- close(fd_out);
- close(fd_in);
- os_free_acl(acl);
- return -1;
- }
+ return 0;
+}
- int n;
- while ((n = read_eintr(fd_in, buffer, WRITEBUFSIZE)) > 0) {
- if (write_eintr(fd_out, buffer, (size_t)n) != n) {
- errmsg = _("E208: Error writing to \"%s\"");
- break;
+/// Create the new file with same permissions as the original.
+/// Return FAIL for failure, OK for success.
+int vim_copyfile(const char *from, const char *to)
+{
+ char *errmsg = NULL;
+
+#ifdef HAVE_READLINK
+ FileInfo from_info;
+ if (os_fileinfo_link(from, &from_info) && S_ISLNK(from_info.stat.st_mode)) {
+ int ret = -1;
+
+ char linkbuf[MAXPATHL + 1];
+ ssize_t len = readlink(from, linkbuf, MAXPATHL);
+ if (len > 0) {
+ linkbuf[len] = NUL;
+
+ // Create link
+ ret = symlink(linkbuf, to);
}
- }
- xfree(buffer);
- close(fd_in);
- if (close(fd_out) < 0) {
- errmsg = _("E209: Error closing \"%s\"");
- }
- if (n < 0) {
- errmsg = _("E210: Error reading \"%s\"");
- to = from;
+ return ret == 0 ? OK : FAIL;
}
-#ifndef UNIX // For Unix os_open() already set the permission.
- os_setperm(to, perm);
#endif
+
+ // For systems that support ACL: get the ACL from the original file.
+ vim_acl_T acl = os_get_acl(from);
+
+ if (os_copy(from, to, UV_FS_COPYFILE_EXCL) != 0) {
+ os_free_acl(acl);
+ return FAIL;
+ }
+
os_set_acl(to, acl);
os_free_acl(acl);
if (errmsg != NULL) {
semsg(errmsg, to);
- return -1;
+ return FAIL;
}
- os_remove(from);
- return 0;
+ return OK;
}
static bool already_warned = false;
@@ -2799,9 +2792,7 @@ int check_timestamps(int focus)
bufref_T bufref;
set_bufref(&bufref, buf);
const int n = buf_check_timestamp(buf);
- if (didit < n) {
- didit = n;
- }
+ didit = MAX(didit, n);
if (n > 0 && !bufref_valid(&bufref)) {
// Autocommands have removed the buffer, start at the first one again.
buf = firstbuf;
@@ -3191,11 +3182,7 @@ void buf_reload(buf_T *buf, int orig_mode, bool reload_options)
// Restore the topline and cursor position and check it (lines may
// have been removed).
- if (old_topline > curbuf->b_ml.ml_line_count) {
- curwin->w_topline = curbuf->b_ml.ml_line_count;
- } else {
- curwin->w_topline = old_topline;
- }
+ curwin->w_topline = MIN(old_topline, curbuf->b_ml.ml_line_count);
curwin->w_cursor = old_cursor;
check_cursor(curwin);
update_topline(curwin);
@@ -3277,18 +3264,12 @@ static void vim_mktempdir(void)
char tmp[TEMP_FILE_PATH_MAXLEN];
char path[TEMP_FILE_PATH_MAXLEN];
char user[40] = { 0 };
- char appname[40] = { 0 };
os_get_username(user, sizeof(user));
// Usernames may contain slashes! #19240
memchrsub(user, '/', '_', sizeof(user));
memchrsub(user, '\\', '_', sizeof(user));
- // Appname may be a relative path, replace slashes to make it name-like.
- xstrlcpy(appname, get_appname(), sizeof(appname));
- memchrsub(appname, '/', '%', sizeof(appname));
- memchrsub(appname, '\\', '%', sizeof(appname));
-
// Make sure the umask doesn't remove the executable bit.
// "repl" has been reported to use "0177".
mode_t umask_save = umask(0077);
@@ -3296,14 +3277,15 @@ static void vim_mktempdir(void)
// Expand environment variables, leave room for "/tmp/nvim.<user>/XXXXXX/999999999".
expand_env((char *)temp_dirs[i], tmp, TEMP_FILE_PATH_MAXLEN - 64);
if (!os_isdir(tmp)) {
+ if (strequal("$TMPDIR", temp_dirs[i])) {
+ WLOG("$TMPDIR tempdir not a directory (or does not exist): %s", tmp);
+ }
continue;
}
// "/tmp/" exists, now try to create "/tmp/nvim.<user>/".
add_pathsep(tmp);
-
- xstrlcat(tmp, appname, sizeof(tmp));
- xstrlcat(tmp, ".", sizeof(tmp));
+ xstrlcat(tmp, "nvim.", sizeof(tmp));
xstrlcat(tmp, user, sizeof(tmp));
os_mkdir(tmp, 0700); // Always create, to avoid a race.
bool owned = os_file_owned(tmp);
@@ -3329,7 +3311,7 @@ static void vim_mktempdir(void)
#endif
// If our "root" tempdir is invalid or fails, proceed without "<user>/".
// Else user1 could break user2 by creating "/tmp/nvim.user2/".
- tmp[strlen(tmp) - strlen(user)] = '\0';
+ tmp[strlen(tmp) - strlen(user)] = NUL;
}
// Now try to create "/tmp/nvim.<user>/XXXXXX".
@@ -3636,6 +3618,7 @@ bool match_file_list(char *list, char *sfname, char *ffname)
/// @param pat_end first char after pattern or NULL
/// @param allow_dirs Result passed back out in here
/// @param no_bslash Don't use a backward slash as pathsep
+/// (only makes a difference when BACKSLASH_IN_FILENAME in defined)
///
/// @return NULL on failure.
char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs, int no_bslash)