diff options
Diffstat (limited to 'src/nvim/fileio.c')
-rw-r--r-- | src/nvim/fileio.c | 111 |
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) |