diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2014-08-16 08:33:21 -0400 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2014-08-16 08:33:21 -0400 |
commit | 640bced2f8bf64098d52841947a3145554d41041 (patch) | |
tree | 1787f0df28059d27fe32885bc4b972384ff09c2e | |
parent | 19207762fd6dccd83b89c96bb1163b0d0440defb (diff) | |
parent | 8f4ada5a2a5c1bfe546cf7d67d3531551ff6026c (diff) | |
download | rneovim-640bced2f8bf64098d52841947a3145554d41041.tar.gz rneovim-640bced2f8bf64098d52841947a3145554d41041.tar.bz2 rneovim-640bced2f8bf64098d52841947a3145554d41041.zip |
Merge pull request #950 from Hinidu/os_fchown
Implement os_fchown and remove HAVE_FCHOWN
-rw-r--r-- | .ci/clang-asan.sh | 4 | ||||
-rw-r--r-- | .travis.yml | 10 | ||||
-rw-r--r-- | config/CMakeLists.txt | 1 | ||||
-rw-r--r-- | config/config.h.in | 1 | ||||
-rw-r--r-- | src/nvim/ex_cmds.c | 4 | ||||
-rw-r--r-- | src/nvim/fileio.c | 22 | ||||
-rw-r--r-- | src/nvim/os/fs.c | 15 | ||||
-rw-r--r-- | src/nvim/undo.c | 5 | ||||
-rw-r--r-- | test/unit/os/fs_spec.moon | 43 |
9 files changed, 75 insertions, 30 deletions
diff --git a/.ci/clang-asan.sh b/.ci/clang-asan.sh index cb6cfc8f41..3217f754d6 100644 --- a/.ci/clang-asan.sh +++ b/.ci/clang-asan.sh @@ -12,10 +12,8 @@ if [ ! -d /usr/local/clang-$clang_version ]; then sudo mkdir /usr/local/clang-$clang_version wget -q -O - http://llvm.org/releases/$clang_version/clang+llvm-$clang_version-x86_64-unknown-ubuntu12.04.xz \ | sudo tar xJf - --strip-components=1 -C /usr/local/clang-$clang_version - export CC=/usr/local/clang-$clang_version/bin/clang -else - export CC=clang fi +export CC=/usr/local/clang-$clang_version/bin/clang symbolizer=/usr/local/clang-$clang_version/bin/llvm-symbolizer export SANITIZE=1 diff --git a/.travis.yml b/.travis.yml index 4af91446ec..1965fb72b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,5 +13,13 @@ env: - CI_TARGET=clint - CI_TARGET=api-python - CI_TARGET=coverity +before_install: + # Adds user to a dummy group. + # That allows to test changing the group of the file by `os_fchown`. + - sudo groupadd chown_test + - sudo usermod -a -G chown_test ${USER} script: - - sh -e "${CI_SCRIPTS}/${CI_TARGET}.sh" + # This will pass the environment variables down to a bash process which runs + # as $USER, while retaining the environment variables defined and belonging + # to secondary groups given above in usermod. + - sudo -E su ${USER} -c "sh -e \"${CI_SCRIPTS}/${CI_TARGET}.sh\"" diff --git a/config/CMakeLists.txt b/config/CMakeLists.txt index 8e1b0239d4..330bd4bc37 100644 --- a/config/CMakeLists.txt +++ b/config/CMakeLists.txt @@ -38,7 +38,6 @@ check_include_files(unistd.h HAVE_UNISTD_H) check_include_files(utime.h HAVE_UTIME_H) # Functions -check_function_exists(fchown HAVE_FCHOWN) check_function_exists(fseeko HAVE_FSEEKO) check_function_exists(fsync HAVE_FSYNC) check_function_exists(getpwent HAVE_GETPWENT) diff --git a/config/config.h.in b/config/config.h.in index a85961858c..ba0945cf56 100644 --- a/config/config.h.in +++ b/config/config.h.in @@ -18,7 +18,6 @@ #cmakedefine HAVE__NSGETENVIRON #cmakedefine HAVE_CRT_EXTERNS_H #cmakedefine HAVE_DIRENT_H -#cmakedefine HAVE_FCHOWN #cmakedefine HAVE_FCNTL_H #cmakedefine HAVE_FD_CLOEXEC #cmakedefine HAVE_FSEEKO diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 180a786ed6..0a26026d7b 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -1606,13 +1606,13 @@ void write_viminfo(char_u *file, int forceit) fp_out = mch_fopen((char *)tempname, WRITEBIN); } -#if defined(UNIX) && defined(HAVE_FCHOWN) +#ifdef UNIX /* * Make sure the owner can read/write it. This only works for * root. */ if (fp_out != NULL) { - fchown(fileno(fp_out), old_info.stat.st_uid, old_info.stat.st_gid); + os_fchown(fileno(fp_out), old_info.stat.st_uid, old_info.stat.st_gid); } #endif } diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 7a8d28b230..e1f9454b52 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -2711,16 +2711,10 @@ buf_write ( * - it's a hard link * - it's a symbolic link * - we don't have write permission in the directory - * - we can't set the owner/group of the new file */ if (file_info_old.stat.st_nlink > 1 || !os_get_file_info_link((char *)fname, &file_info) - || !os_file_info_id_equal(&file_info, &file_info_old) -# ifndef HAVE_FCHOWN - || file_info.stat.st_uid != file_info_old.stat.st_uid - || file_info.stat.st_gid != file_info_old.stat.st_gid -# endif - ) { + || !os_file_info_id_equal(&file_info, &file_info_old)) { backup_copy = TRUE; } else # endif @@ -2744,9 +2738,7 @@ buf_write ( backup_copy = TRUE; else { # ifdef UNIX -# ifdef HAVE_FCHOWN - fchown(fd, file_info_old.stat.st_uid, file_info_old.stat.st_gid); -# endif + os_fchown(fd, file_info_old.stat.st_uid, file_info_old.stat.st_gid); if (!os_get_file_info((char *)IObuff, &file_info) || file_info.stat.st_uid != file_info_old.stat.st_uid || file_info.stat.st_gid != file_info_old.stat.st_gid @@ -2909,10 +2901,7 @@ buf_write ( * others. */ if (file_info_new.stat.st_gid != file_info_old.stat.st_gid -# ifdef HAVE_FCHOWN /* sequent-ptx lacks fchown() */ - && fchown(bfd, (uid_t)-1, file_info_old.stat.st_gid) != 0 -# endif - ) { + && os_fchown(bfd, -1, file_info_old.stat.st_gid) != 0) { os_setperm(backup, (perm & 0707) | ((perm & 07) << 3)); } # ifdef HAVE_SELINUX @@ -3424,19 +3413,16 @@ restore_backup: /* When creating a new file, set its owner/group to that of the original * file. Get the new device and inode number. */ if (backup != NULL && !backup_copy) { -# ifdef HAVE_FCHOWN - /* don't change the owner when it's already OK, some systems remove * permission or ACL stuff */ FileInfo file_info; if (!os_get_file_info((char *)wfname, &file_info) || file_info.stat.st_uid != file_info_old.stat.st_uid || file_info.stat.st_gid != file_info_old.stat.st_gid) { - fchown(fd, file_info_old.stat.st_uid, file_info_old.stat.st_gid); + os_fchown(fd, file_info_old.stat.st_uid, file_info_old.stat.st_gid); if (perm >= 0) /* set permission again, may have changed */ (void)os_setperm(wfname, perm); } -# endif buf_set_file_id(buf); } else if (!buf->file_id_valid) { // Set the file_id when creating a new file. diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 4820a4d165..aca7005064 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -210,6 +210,21 @@ int os_setperm(const char_u *name, int perm) return FAIL; } +/// Changes the ownership of the file referred to by the open file descriptor. +/// +/// @return `0` on success, a libuv error code on failure. +/// +/// @note If the `owner` or `group` is specified as `-1`, then that ID is not +/// changed. +int os_fchown(int file_descriptor, uv_uid_t owner, uv_gid_t group) +{ + uv_fs_t request; + int result = uv_fs_fchown(uv_default_loop(), &request, file_descriptor, + owner, group, NULL); + uv_fs_req_cleanup(&request); + return result; +} + /// Check if a file exists. /// /// @return `true` if `name` exists. diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 96b83a3e2d..8c7b5b38e9 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -1119,10 +1119,7 @@ void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash) if (os_get_file_info((char *)buf->b_ffname, &file_info_old) && os_get_file_info((char *)file_name, &file_info_new) && file_info_old.stat.st_gid != file_info_new.stat.st_gid -# ifdef HAVE_FCHOWN /* sequent-ptx lacks fchown() */ - && fchown(fd, (uid_t)-1, file_info_old.stat.st_gid) != 0 -# endif - ) { + && os_fchown(fd, -1, file_info_old.stat.st_gid) != 0) { os_setperm(file_name, (perm & 0707) | ((perm & 07) << 3)); } # ifdef HAVE_SELINUX diff --git a/test/unit/os/fs_spec.moon b/test/unit/os/fs_spec.moon index 52f587d6f9..dd787e76cd 100644 --- a/test/unit/os/fs_spec.moon +++ b/test/unit/os/fs_spec.moon @@ -112,6 +112,12 @@ describe 'fs function', -> os_setperm = (filename, perm) -> fs.os_setperm (to_cstr filename), perm + os_fchown = (filename, user_id, group_id) -> + fd = ffi.C.open filename, 0 + res = fs.os_fchown fd, user_id, group_id + ffi.C.close fd + return res + os_file_is_readonly = (filename) -> fs.os_file_is_readonly (to_cstr filename) @@ -158,6 +164,43 @@ describe 'fs function', -> perm = ffi.C.kS_IXUSR eq FAIL, (os_setperm 'non-existing-file', perm) + describe 'os_fchown', -> + filename = 'unit-test-directory/test.file' + + it 'does not change owner and group if respective IDs are equal to -1', -> + uid = lfs.attributes filename, 'uid' + gid = lfs.attributes filename, 'gid' + eq 0, os_fchown filename, -1, -1 + eq uid, lfs.attributes filename, 'uid' + eq gid, lfs.attributes filename, 'gid' + + it 'owner of a file may change the group of the file + to any group of which that owner is a member', -> + -- Some systems may not have `id` utility. + if (os.execute('id -G &> /dev/null') == 0) + file_gid = lfs.attributes filename, 'gid' + + -- Gets ID of any group of which current user is a member except the + -- group that owns the file. + id_fd = io.popen('id -G') + new_gid = id_fd\read '*n' + if (new_gid == file_gid) + new_gid = id_fd\read '*n' + id_fd\close! + + -- User can be a member of only one group. + -- In that case we can not perform this test. + if new_gid + eq 0, (os_fchown filename, -1, new_gid) + eq new_gid, (lfs.attributes filename, 'gid') + + it 'returns nonzero if process has not enough permissions', -> + -- On Windows `os_fchown` always returns 0 + -- because `uv_fs_chown` is no-op on this platform. + if (ffi.os != 'Windows' and ffi.C.geteuid! != 0) + -- chown to root + neq 0, os_fchown filename, 0, 0 + describe 'os_file_is_readonly', -> it 'returns true if the file is readonly', -> perm = os_getperm 'unit-test-directory/test.file' |