diff options
-rw-r--r-- | src/nvim/fileio.c | 6 | ||||
-rw-r--r-- | src/nvim/os/fs.c | 9 | ||||
-rw-r--r-- | test/unit/os/fs_spec.lua | 14 |
3 files changed, 26 insertions, 3 deletions
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 245590e7ce..b2d27bd0d1 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -2712,7 +2712,7 @@ buf_write ( * - it's a symbolic link * - we don't have write permission in the directory */ - if (file_info_old.stat.st_nlink > 1 + if (os_fileinfo_hardlinks(&file_info_old) > 1 || !os_get_file_info_link((char *)fname, &file_info) || !os_file_info_id_equal(&file_info, &file_info_old)) { backup_copy = TRUE; @@ -2770,7 +2770,7 @@ buf_write ( /* Hardlinks. */ if ((bkc_flags & BKC_BREAKHARDLINK) - && file_info_old.stat.st_nlink > 1 + && os_fileinfo_hardlinks(&file_info_old) > 1 && (!file_info_link_ok || os_file_info_id_equal(&file_info, &file_info_old))) { backup_copy = FALSE; @@ -3201,7 +3201,7 @@ nobackup: FileInfo file_info; /* Don't delete the file when it's a hard or symbolic link. */ - if ((!newfile && file_info_old.stat.st_nlink > 1) + if ((!newfile && os_fileinfo_hardlinks(&file_info) > 1) || (os_get_file_info_link((char *)fname, &file_info) && !os_file_info_id_equal(&file_info, &file_info_old))) { errmsg = (char_u *)_("E166: Can't open linked file for writing"); diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 9347afb9bc..70a53edb1c 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -403,6 +403,15 @@ off_t os_fileinfo_size(const FileInfo *file_info) return file_info->stat.st_size; } +/// Get the number of hardlinks from a `FileInfo`. +/// +/// @return number of hardlinks. +uint64_t os_fileinfo_hardlinks(const FileInfo *file_info) + FUNC_ATTR_NONNULL_ALL +{ + return file_info->stat.st_nlink; +} + /// Get the `FileID` for a given path /// /// @param path Path to the file. diff --git a/test/unit/os/fs_spec.lua b/test/unit/os/fs_spec.lua index c92c1513b7..9f6d110e8f 100644 --- a/test/unit/os/fs_spec.lua +++ b/test/unit/os/fs_spec.lua @@ -47,6 +47,7 @@ describe('fs function', function() os.remove('unit-test-directory/test.file') os.remove('unit-test-directory/test_2.file') os.remove('unit-test-directory/test_link.file') + os.remove('unit-test-directory/test_hlink.file') lfs.rmdir('unit-test-directory') end) @@ -611,6 +612,19 @@ describe('fs function', function() end) end) + describe('os_fileinfo_hardlinks', function() + it('returns the correct number of hardlinks', function() + local path = 'unit-test-directory/test.file' + local path_link = 'unit-test-directory/test_hlink.file' + local file_info = file_info_new() + assert.is_true(fs.os_get_file_info(path, file_info)) + eq(1, fs.os_fileinfo_hardlinks(file_info)) + lfs.link(path, path_link) + assert.is_true(fs.os_get_file_info(path, file_info)) + eq(2, fs.os_fileinfo_hardlinks(file_info)) + end) + end) + describe('os_get_file_id', function() it('returns false if given an non-existing file', function() local file_id = file_id_new() |