diff --git a/src/nvim/bufwrite.c b/src/nvim/bufwrite.c index 62c72ace3e..cf248ebd52 100644 --- a/src/nvim/bufwrite.c +++ b/src/nvim/bufwrite.c @@ -743,7 +743,7 @@ static int buf_write_make_backup(char *fname, bool append, FileInfo *file_info_o || !os_fileinfo_id_equal(&file_info, file_info_old)) { *backup_copyp = true; } else { - // Check if we can create a file and set the owner/group to + // Check if we can create a file and set the owner/group/mode to // the ones from the original file. // First find a file name that doesn't exist yet (use some // arbitrary numbers). @@ -764,6 +764,7 @@ static int buf_write_make_backup(char *fname, bool append, FileInfo *file_info_o } else { #ifdef UNIX os_fchown(fd, (uv_uid_t)file_info_old->stat.st_uid, (uv_gid_t)file_info_old->stat.st_gid); + os_fsetperm(fd, perm); if (!os_fileinfo(tmp_fname, &file_info) || file_info.stat.st_uid != file_info_old->stat.st_uid || file_info.stat.st_gid != file_info_old->stat.st_gid diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 820e5cdc3d..bceb4a867b 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -804,6 +804,16 @@ int os_setperm(const char *const name, int perm) return (r == kLibuvSuccess ? OK : FAIL); } +/// Set the permission of the file referred to by the open file descriptor. +/// +/// @return `OK` for success, `FAIL` for failure. +int os_fsetperm(int fd, int perm) +{ + int r; + RUN_UV_FS_FUNC(r, uv_fs_fchmod, fd, perm, NULL); + return (r == kLibuvSuccess ? OK : FAIL); +} + #ifdef HAVE_XATTR /// Copy extended attributes from_file to to_file void os_copy_xattr(const char *from_file, const char *to_file) diff --git a/test/old/testdir/test_writefile.vim b/test/old/testdir/test_writefile.vim index ad5abd9b9f..4b28703046 100644 --- a/test/old/testdir/test_writefile.vim +++ b/test/old/testdir/test_writefile.vim @@ -1013,4 +1013,24 @@ func Test_write_with_xattr_support() bw! endfunc +func Test_backupcopy_auto_restrictive_umask() + CheckUnix + call writefile(['FOO'], 'Xumaskfile', 'D') + call setfperm('Xumaskfile', 'rw-r--r--') + let inode_before = systemlist('ls -i Xumaskfile')[0]->matchstr('^\s*\zs\d\+') + call writefile([ + \ 'set backupcopy=auto writebackup nobackup backupskip=', + \ 'edit Xumaskfile', + \ 'call setline(1, ["BAR"])', + \ 'write', + \ 'qall!' + \ ], 'Xumaskscript', 'D') + call system('umask 0077; ' .. GetVimCommand() .. ' -i NONE -n -S Xumaskscript') + call assert_equal(0, v:shell_error) + call assert_equal(['BAR'], readfile('Xumaskfile')) + call assert_equal('rw-r--r--', getfperm('Xumaskfile')) + call assert_notequal(inode_before, + \ systemlist('ls -i Xumaskfile')[0]->matchstr('^\s*\zs\d\+')) +endfunc + " vim: shiftwidth=2 sts=2 expandtab