aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/config.h.in2
-rw-r--r--runtime/doc/if_lua.txt31
-rw-r--r--runtime/lua/vim/shared.lua11
-rw-r--r--src/nvim/fileio.c148
-rw-r--r--src/nvim/lua/vim.lua13
-rw-r--r--src/nvim/memfile.c3
-rw-r--r--src/nvim/os/fs.c35
-rw-r--r--src/nvim/os_unix.c53
-rw-r--r--src/nvim/undo.c4
-rw-r--r--test/functional/core/fileio_spec.lua23
-rw-r--r--test/unit/helpers.lua5
11 files changed, 121 insertions, 207 deletions
diff --git a/config/config.h.in b/config/config.h.in
index ef2fea4042..15881c4430 100644
--- a/config/config.h.in
+++ b/config/config.h.in
@@ -29,8 +29,6 @@
#cmakedefine HAVE_NL_MSG_CAT_CNTR
#cmakedefine HAVE_PWD_H
#cmakedefine HAVE_READLINK
-// TODO: add proper cmake check
-// #define HAVE_SELINUX 1
#cmakedefine HAVE_SETPGID
#cmakedefine HAVE_SETSID
#cmakedefine HAVE_SIGACTION
diff --git a/runtime/doc/if_lua.txt b/runtime/doc/if_lua.txt
index 7f90074ff0..e2d1f0f675 100644
--- a/runtime/doc/if_lua.txt
+++ b/runtime/doc/if_lua.txt
@@ -374,11 +374,6 @@ For example, to use the "nvim_get_current_line()" API function, call
------------------------------------------------------------------------------
VIM *lua-util*
-vim.inspect({object}, {options}) *vim.inspect*
- Return a human-readable representation of the passed object. See
- https://github.com/kikito/inspect.lua
- for details and possible options.
-
vim.stricmp(a, b) *lua-vim.stricmp*
Function used for case-insensitive string comparison. Takes two
string arguments and returns 0, 1 or -1 if strings are equal, a is
@@ -422,18 +417,11 @@ vim.types *lua-vim.types*
==============================================================================
Lua module: vim *lua-vim*
-trim({s}) *vim.trim()*
- Trim whitespace (Lua pattern "%%s") from both sides of a
- string.
-
- Parameters: ~
- {s} String to trim
-
- Return: ~
- String with whitespace removed from its beginning and end
+inspect({object}, {options}) *vim.inspect()*
+ Return a human-readable representation of the given object.
See also: ~
- https://www.lua.org/pil/20.2.html
+ https://github.com/kikito/inspect.lua
@@ -521,4 +509,17 @@ tbl_flatten({t}) *vim.tbl_flatten()*
Return: ~
Flattened copy of the given list-like table.
+trim({s}) *vim.trim()*
+ Trim whitespace (Lua pattern "%%s") from both sides of a
+ string.
+
+ Parameters: ~
+ {s} String to trim
+
+ Return: ~
+ String with whitespace removed from its beginning and end
+
+ See also: ~
+ https://www.lua.org/pil/20.2.html
+
vim:tw=78:ts=8:ft=help:norl:
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index 07145c6e3f..1038a95dd3 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -168,6 +168,16 @@ local function tbl_flatten(t)
return result
end
+--- Trim whitespace (Lua pattern "%%s") from both sides of a string.
+---
+--@see https://www.lua.org/pil/20.2.html
+--@param s String to trim
+--@returns String with whitespace removed from its beginning and end
+local function trim(s)
+ assert(type(s) == 'string', 'Only strings can be trimmed')
+ return s:match('^%s*(.*%S)') or ''
+end
+
local module = {
deepcopy = deepcopy,
gsplit = gsplit,
@@ -175,5 +185,6 @@ local module = {
tbl_contains = tbl_contains,
tbl_extend = tbl_extend,
tbl_flatten = tbl_flatten,
+ trim = trim,
}
return module
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 8e4a210b66..b468b7bb8c 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -2781,20 +2781,12 @@ buf_write (
else
backup_ext = p_bex;
- if (backup_copy && (fd = os_open((char *)fname, O_RDONLY, 0)) >= 0) {
- int bfd;
- char_u *copybuf, *wp;
- int some_error = FALSE;
+ if (backup_copy) {
+ char_u *wp;
+ int some_error = false;
char_u *dirp;
char_u *rootname;
- copybuf = verbose_try_malloc(BUFSIZE + 1);
- if (copybuf == NULL) {
- // out of memory
- some_error = TRUE;
- goto nobackup;
- }
-
/*
* Try to make the backup in each directory in the 'bdir' option.
*
@@ -2812,8 +2804,8 @@ buf_write (
/*
* Isolate one directory name, using an entry in 'bdir'.
*/
- (void)copy_option_part(&dirp, copybuf, BUFSIZE, ",");
- rootname = get_file_in_dir(fname, copybuf);
+ (void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
+ rootname = get_file_in_dir(fname, IObuff);
if (rootname == NULL) {
some_error = TRUE; /* out of memory */
goto nobackup;
@@ -2875,87 +2867,44 @@ buf_write (
if (backup != NULL) {
/* remove old backup, if present */
os_remove((char *)backup);
- /* Open with O_EXCL to avoid the file being created while
- * we were sleeping (symlink hacker attack?) */
- bfd = os_open((char *)backup,
- O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW,
- perm & 0777);
- if (bfd < 0) {
- xfree(backup);
- backup = NULL;
- } else {
- // set file protection same as original file, but
- // strip s-bit.
- (void)os_setperm((const char *)backup, perm & 0777);
+
+ // set file protection same as original file, but
+ // strip s-bit.
+ (void)os_setperm((const char *)backup, perm & 0777);
#ifdef UNIX
- /*
- * Try to set the group of the backup same as the
- * original file. If this fails, set the protection
- * bits for the group same as the protection bits for
- * others.
- */
- if (file_info_new.stat.st_gid != file_info_old.stat.st_gid
- && os_fchown(bfd, -1, file_info_old.stat.st_gid) != 0) {
- os_setperm((const char *)backup,
- (perm & 0707) | ((perm & 07) << 3));
- }
-# ifdef HAVE_SELINUX
- mch_copy_sec(fname, backup);
-# endif
+ //
+ // Try to set the group of the backup same as the original file. If
+ // this fails, set the protection bits for the group same as the
+ // protection bits for others.
+ //
+ if (file_info_new.stat.st_gid != file_info_old.stat.st_gid
+ && os_chown((char *)backup, -1, file_info_old.stat.st_gid) != 0) {
+ os_setperm((const char *)backup,
+ (perm & 0707) | ((perm & 07) << 3));
+ }
#endif
- /*
- * copy the file.
- */
- write_info.bw_fd = bfd;
- write_info.bw_buf = copybuf;
-#ifdef HAS_BW_FLAGS
- write_info.bw_flags = FIO_NOCONVERT;
-#endif
- while ((write_info.bw_len = read_eintr(fd, copybuf,
- BUFSIZE)) > 0) {
- if (buf_write_bytes(&write_info) == FAIL) {
- SET_ERRMSG(_(
- "E506: Can't write to backup file (add ! to override)"));
- break;
- }
- os_breakcheck();
- if (got_int) {
- SET_ERRMSG(_(e_interr));
- break;
- }
- }
+ // copy the file
+ if (os_copy((char *)fname, (char *)backup, UV_FS_COPYFILE_FICLONE)
+ != 0) {
+ SET_ERRMSG(_("E506: Can't write to backup file "
+ "(add ! to override)"));
+ }
- int error;
- if ((error = os_close(bfd)) != 0 && errmsg == NULL) {
- SET_ERRMSG_ARG(_("E507: Close error for backup file "
- "(add ! to override): %s"),
- error);
- }
- if (write_info.bw_len < 0) {
- SET_ERRMSG(_(
- "E508: Can't read file for backup (add ! to override)"));
- }
#ifdef UNIX
- set_file_time(backup,
- file_info_old.stat.st_atim.tv_sec,
- file_info_old.stat.st_mtim.tv_sec);
+ set_file_time(backup,
+ file_info_old.stat.st_atim.tv_sec,
+ file_info_old.stat.st_mtim.tv_sec);
#endif
#ifdef HAVE_ACL
- mch_set_acl(backup, acl);
-#endif
-#ifdef HAVE_SELINUX
- mch_copy_sec(fname, backup);
+ mch_set_acl(backup, acl);
#endif
- break;
- }
+ break;
}
}
-nobackup:
- os_close(fd); // Ignore errors for closing read file.
- xfree(copybuf);
+nobackup:
if (backup == NULL && errmsg == NULL) {
SET_ERRMSG(_(
"E509: Cannot create backup file (add ! to override)"));
@@ -3433,13 +3382,6 @@ restore_backup:
end = 0;
}
-#ifdef HAVE_SELINUX
- // Probably need to set the security context.
- if (!backup_copy) {
- mch_copy_sec(backup, wfname);
- }
-#endif
-
#ifdef UNIX
// When creating a new file, set its owner/group to that of the original
// file. Get the new device and inode number.
@@ -3537,28 +3479,11 @@ restore_backup:
MSG(_(e_interr));
ui_flush();
}
- if ((fd = os_open((char *)backup, O_RDONLY, 0)) >= 0) {
- if ((write_info.bw_fd = os_open((char *)fname,
- O_WRONLY | O_CREAT | O_TRUNC,
- perm & 0777)) >= 0) {
- // copy the file.
- write_info.bw_buf = smallbuf;
-#ifdef HAS_BW_FLAGS
- write_info.bw_flags = FIO_NOCONVERT;
-#endif
- while ((write_info.bw_len = read_eintr(fd, smallbuf,
- SMBUFSIZE)) > 0) {
- if (buf_write_bytes(&write_info) == FAIL) {
- break;
- }
- }
- if (close(write_info.bw_fd) >= 0
- && write_info.bw_len == 0) {
- end = 1; // success
- }
- }
- close(fd); // ignore errors for closing read file
+ // copy the file.
+ if (os_copy((char *)backup, (char *)fname, UV_FS_COPYFILE_FICLONE)
+ == 0) {
+ end = 1; // success
}
} else {
if (vim_rename(backup, fname) == 0) {
@@ -4825,9 +4750,6 @@ int vim_rename(const char_u *from, const char_u *to)
mch_set_acl(to, acl);
mch_free_acl(acl);
#endif
-#ifdef HAVE_SELINUX
- mch_copy_sec(from, to);
-#endif
if (errmsg != NULL) {
EMSG2(errmsg, to);
return -1;
diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua
index 38a8795680..848bccaae6 100644
--- a/src/nvim/lua/vim.lua
+++ b/src/nvim/lua/vim.lua
@@ -154,15 +154,11 @@ local function _update_package_paths()
last_nvim_paths = cur_nvim_paths
end
---- Trim whitespace (Lua pattern "%%s") from both sides of a string.
+--- Return a human-readable representation of the given object.
---
---@see https://www.lua.org/pil/20.2.html
---@param s String to trim
---@returns String with whitespace removed from its beginning and end
-local function trim(s)
- assert(type(s) == 'string', 'Only strings can be trimmed')
- local result = s:gsub('^%s+', ''):gsub('%s+$', '')
- return result
+--@see https://github.com/kikito/inspect.lua
+local function inspect(object, options) -- luacheck: no unused
+ error(object, options) -- Stub for gen_vimdoc.py
end
local function __index(t, key)
@@ -181,7 +177,6 @@ local module = {
_os_proc_children = _os_proc_children,
_os_proc_info = _os_proc_info,
_system = _system,
- trim = trim,
}
setmetatable(module, {
diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c
index 0a16f8aafb..5a64c82e0e 100644
--- a/src/nvim/memfile.c
+++ b/src/nvim/memfile.c
@@ -785,9 +785,6 @@ static bool mf_do_open(memfile_T *mfp, char_u *fname, int flags)
}
(void)os_set_cloexec(mfp->mf_fd);
-#ifdef HAVE_SELINUX
- mch_copy_sec(fname, mfp->mf_fname);
-#endif
return true;
}
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index 8d9de1253e..d5500b230c 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -643,6 +643,21 @@ ptrdiff_t os_write(const int fd, const char *const buf, const size_t size,
return (ptrdiff_t)written_bytes;
}
+/// Copies a file from `path` to `new_path`.
+///
+/// @see http://docs.libuv.org/en/v1.x/fs.html#c.uv_fs_copyfile
+///
+/// @param path Path of file to be copied
+/// @param path_new Path of new file
+/// @param flags Bitwise OR of flags defined in <uv.h>
+/// @return 0 on success, or libuv error code on failure.
+int os_copy(const char *path, const char *new_path, int flags)
+{
+ int r;
+ RUN_UV_FS_FUNC(r, uv_fs_copyfile, path, new_path, flags, NULL);
+ return r;
+}
+
/// Flushes file modifications to disk.
///
/// @param fd the file descriptor of the file to flush to disk.
@@ -697,12 +712,24 @@ int os_setperm(const char *const name, int perm)
return (r == kLibuvSuccess ? OK : FAIL);
}
-/// Changes the ownership of the file referred to by the open file descriptor.
+/// Changes the owner and group of a file, like chown(2).
///
-/// @return `0` on success, a libuv error code on failure.
+/// @return 0 on success, or libuv error code on failure.
+///
+/// @note If `owner` or `group` is -1, then that ID is not changed.
+int os_chown(const char *path, uv_uid_t owner, uv_gid_t group)
+{
+ int r;
+ RUN_UV_FS_FUNC(r, uv_fs_chown, path, owner, group, NULL);
+ return r;
+}
+
+/// Changes the owner and group of the file referred to by the open file
+/// descriptor, like fchown(2).
+///
+/// @return 0 on success, or libuv error code on failure.
///
-/// @note If the `owner` or `group` is specified as `-1`, then that ID is not
-/// changed.
+/// @note If `owner` or `group` is -1, then that ID is not changed.
int os_fchown(int fd, uv_uid_t owner, uv_gid_t group)
{
int r;
diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c
index 351350d939..8180a2e8ac 100644
--- a/src/nvim/os_unix.c
+++ b/src/nvim/os_unix.c
@@ -45,12 +45,6 @@
#include "nvim/os/signal.h"
#include "nvim/msgpack_rpc/helpers.h"
-#ifdef HAVE_SELINUX
-# include <selinux/selinux.h>
-static int selinux_enabled = -1;
-#endif
-
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os_unix.c.generated.h"
#endif
@@ -64,53 +58,6 @@ static int selinux_enabled = -1;
# endif
-#if defined(HAVE_SELINUX)
-// Copy security info from "from_file" to "to_file".
-void mch_copy_sec(char_u *from_file, char_u *to_file)
-{
- if (from_file == NULL)
- return;
-
- if (selinux_enabled == -1)
- selinux_enabled = is_selinux_enabled();
-
- if (selinux_enabled > 0) {
- security_context_t from_context = NULL;
- security_context_t to_context = NULL;
-
- if (getfilecon((char *)from_file, &from_context) < 0) {
- // If the filesystem doesn't support extended attributes,
- // the original had no special security context and the
- // target cannot have one either.
- if (errno == EOPNOTSUPP) {
- return;
- }
-
- MSG_PUTS(_("\nCould not get security context for "));
- msg_outtrans(from_file);
- msg_putchar('\n');
- return;
- }
- if (getfilecon((char *)to_file, &to_context) < 0) {
- MSG_PUTS(_("\nCould not get security context for "));
- msg_outtrans(to_file);
- msg_putchar('\n');
- freecon (from_context);
- return;
- }
- if (strcmp(from_context, to_context) != 0) {
- if (setfilecon((char *)to_file, from_context) < 0) {
- MSG_PUTS(_("\nCould not set security context for "));
- msg_outtrans(to_file);
- msg_putchar('\n');
- }
- }
- freecon(to_context);
- freecon(from_context);
- }
-}
-#endif // HAVE_SELINUX
-
// Return a pointer to the ACL of file "fname" in allocated memory.
// Return NULL if the ACL is not available for whatever reason.
vim_acl_T mch_get_acl(const char_u *fname)
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 10996d99d5..2cc3e928f7 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -1169,10 +1169,6 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
&& 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));
}
-# ifdef HAVE_SELINUX
- if (buf->b_ffname != NULL)
- mch_copy_sec(buf->b_ffname, file_name);
-# endif
#endif
fp = fdopen(fd, "w");
diff --git a/test/functional/core/fileio_spec.lua b/test/functional/core/fileio_spec.lua
index 09533e4e60..c74eb3bb02 100644
--- a/test/functional/core/fileio_spec.lua
+++ b/test/functional/core/fileio_spec.lua
@@ -10,6 +10,8 @@ local request = helpers.request
local retry = helpers.retry
local rmdir = helpers.rmdir
local sleep = helpers.sleep
+local read_file = helpers.read_file
+local trim = helpers.trim
describe('fileio', function()
before_each(function()
@@ -18,6 +20,7 @@ describe('fileio', function()
command(':qall!')
os.remove('Xtest_startup_shada')
os.remove('Xtest_startup_file1')
+ os.remove('Xtest_startup_file1~')
os.remove('Xtest_startup_file2')
rmdir('Xtest_startup_swapdir')
end)
@@ -64,5 +67,25 @@ describe('fileio', function()
command('write')
eq(4, request('nvim__stats').fsync)
end)
+
+ it('backup #9709', function()
+ clear({ args={ '-i', 'Xtest_startup_shada',
+ '--cmd', 'set directory=Xtest_startup_swapdir' } })
+
+ command('write Xtest_startup_file1')
+ feed('ifoo<esc>')
+ command('set backup')
+ command('set backupcopy=yes')
+ command('write')
+ feed('Abar<esc>')
+ command('write')
+
+ local foobar_contents = trim(read_file('Xtest_startup_file1'))
+ local bar_contents = trim(read_file('Xtest_startup_file1~'))
+
+ eq('foobar', foobar_contents);
+ eq('foo', bar_contents);
+
+ end)
end)
diff --git a/test/unit/helpers.lua b/test/unit/helpers.lua
index e634b7296e..b5d3dd9f47 100644
--- a/test/unit/helpers.lua
+++ b/test/unit/helpers.lua
@@ -15,6 +15,7 @@ local dedent = global_helpers.dedent
local neq = global_helpers.neq
local map = global_helpers.map
local eq = global_helpers.eq
+local trim = global_helpers.trim
-- C constants.
local NULL = ffi.cast('void*', 0)
@@ -119,10 +120,6 @@ local deinit = only_separate(function()
end
end)
-local function trim(s)
- return s:match('^%s*(.*%S)') or ''
-end
-
-- a Set that keeps around the lines we've already seen
local cdefs_init = Set:new()
local cdefs_mod = nil