Skip to content

Commit

Permalink
vfs: implement renameat()
Browse files Browse the repository at this point in the history
This patch implements the renameat() function and enhances
tst-rename.cc to unit test it.

This patch also exposes renameat as a syscall.

#Refs 1188

Signed-off-by: Waldemar Kozaczuk <[email protected]>
  • Loading branch information
wkozaczuk committed May 27, 2022
1 parent 6716ad9 commit 1097dfa
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 2 deletions.
1 change: 1 addition & 0 deletions exported_symbols/osv_ld-musl.so.1.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,7 @@ remquo
remquof
remquol
rename
renameat
res_init
res_mkquery
rewind
Expand Down
1 change: 1 addition & 0 deletions exported_symbols/osv_libc.so.6.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,7 @@ register_printf_specifier
register_printf_type
remove
rename
renameat
__res_init
rewind
rewinddir
Expand Down
30 changes: 30 additions & 0 deletions fs/vfs/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,36 @@ int rename(const char *oldpath, const char *newpath)
return -1;
}

OSV_LIBC_API
int renameat(int olddirfd, const char *oldpath,
int newdirfd, const char *newpath)
{
if (!oldpath || !newpath) {
errno = EINVAL;
return -1;
}

if (newpath[0] == '/' || newdirfd == AT_FDCWD) {
return vfs_fun_at2(olddirfd, oldpath, [newpath](const char *path) {
return rename(path, newpath);
});
} else {
char absolute_newpath[PATH_MAX];
auto error = vfs_fun_at(newdirfd, newpath, [&absolute_newpath](const char *absolute_path) {
strcpy(absolute_newpath, absolute_path);
return 0;
});

if (error) {
return error;
} else {
return vfs_fun_at2(olddirfd, oldpath, [absolute_newpath](const char *path) {
return rename(path, absolute_newpath);
});
}
}
}

TRACEPOINT(trace_vfs_chdir, "\"%s\"", const char*);
TRACEPOINT(trace_vfs_chdir_ret, "");
TRACEPOINT(trace_vfs_chdir_err, "%d", int);
Expand Down
1 change: 1 addition & 0 deletions linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,7 @@ OSV_LIBC_API long syscall(long number, ...)
SYSCALL3(unlinkat, int, const char *, int);
SYSCALL3(symlinkat, const char *, int, const char *);
SYSCALL3(sys_getdents64, int, void *, size_t);
SYSCALL4(renameat, int, const char *, int, const char *);
}

debug_always("syscall(): unimplemented system call %d\n", number);
Expand Down
48 changes: 46 additions & 2 deletions tests/tst-rename.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ static void assert_rename_fails(const fs::path &src, const fs::path &dst, std::v
BOOST_TEST_MESSAGE("Renaming " + src.string() + " to " + dst.string());
BOOST_REQUIRE(rename(src.c_str(), dst.c_str()) == -1);
assert_one_of(errno, errnos);
BOOST_TEST_MESSAGE("Renaming(at) " + src.string() + " to " + dst.string());
BOOST_REQUIRE(renameat(AT_FDCWD, src.c_str(), AT_FDCWD, dst.c_str()) == -1);
assert_one_of(errno, errnos);
}

static void assert_renames(const fs::path src, const fs::path dst)
Expand All @@ -82,11 +85,27 @@ static void assert_renames(const fs::path src, const fs::path dst)
BOOST_REQUIRE_MESSAGE(result == 0, fmt("Rename should succeed, errno=%d") % errno);
}

static void test_rename(const fs::path &src, const fs::path &dst)
static void assert_renames_at(const fs::path src, const fs::path dst)
{
BOOST_TEST_MESSAGE("Renaming " + src.string() + " to " + dst.string());
auto src_dir_fd = open(src.parent_path().c_str(), O_DIRECTORY);
auto dst_dir_fd = open(dst.parent_path().c_str(), O_DIRECTORY);
int result = renameat(src_dir_fd, src.filename().c_str(), dst_dir_fd, dst.filename().c_str());
BOOST_REQUIRE_MESSAGE(result == 0, fmt("Renameat should succeed, errno=%d") % errno);
close(src_dir_fd);
close(dst_dir_fd);
}

static void test_rename(const fs::path &src, const fs::path &dst, bool at = false)
{
prepare_file(src);

assert_renames(src, dst);
if (at) {
assert_renames_at(src, dst);
}
else {
assert_renames(src, dst);
}

check_file(dst);
BOOST_CHECK_MESSAGE(!fs::exists(src), "Old file should not exist");
Expand Down Expand Up @@ -136,6 +155,10 @@ BOOST_AUTO_TEST_CASE(test_renaming_in_the_same_directory)
dir / "file1",
dir / "file2");

test_rename(
dir / "file1",
dir / "file2", true);

test_rename_from_open_file(
dir / "file1",
dir / "file2");
Expand All @@ -148,9 +171,17 @@ BOOST_AUTO_TEST_CASE(test_renaming_in_the_same_directory)
dir / "a",
dir / "aaaaa");

test_rename(
dir / "a",
dir / "aaaaa", true);

test_rename(
dir / "aaaaaaaaa",
dir / "aa");

test_rename(
dir / "aaaaaaaaa",
dir / "aa", true);
}

BOOST_AUTO_TEST_CASE(test_renaming_to_child_path_should_fail) {
Expand All @@ -169,13 +200,25 @@ BOOST_AUTO_TEST_CASE(test_moving_file_to_another_directory)
dir / "file",
dir / sub / "file");

test_rename(
dir / "file",
dir / sub / "file", true);

test_rename(
dir / sub / "file2",
dir / "file2");

test_rename(
dir / sub / "file2",
dir / "file2", true);

test_rename(
dir / sub / "a",
dir / "aaaa");

test_rename(
dir / sub / "a",
dir / "aaaa", true);
}

BOOST_AUTO_TEST_CASE(test_renaming_when_destination_is_substring)
Expand All @@ -201,6 +244,7 @@ BOOST_AUTO_TEST_CASE(test_renaming_works_with_non_uniform_paths)

test_rename(file, dir / "/file2");
test_rename(file, dir / "/sub///file2");
test_rename(file, dir / "/sub///file2", true);
}

BOOST_AUTO_TEST_CASE(test_file_can_be_located_using_different_paths_after_rename)
Expand Down

0 comments on commit 1097dfa

Please sign in to comment.