diff --git a/repos/libports/src/lib/libc/file_operations.cc b/repos/libports/src/lib/libc/file_operations.cc index bb4d274ad..c15ea104d 100644 --- a/repos/libports/src/lib/libc/file_operations.cc +++ b/repos/libports/src/lib/libc/file_operations.cc @@ -386,6 +386,7 @@ extern "C" int mkdir(const char *path, mode_t mode) try { Absolute_path resolved_path; resolve_symlinks_except_last_element(path, resolved_path); + resolved_path.remove_trailing('/'); FNAME_FUNC_WRAPPER(mkdir, resolved_path.base(), mode); } catch(Symlink_resolve_error) { return -1; @@ -608,6 +609,10 @@ extern "C" int rename(const char *oldpath, const char *newpath) Absolute_path resolved_oldpath, resolved_newpath; resolve_symlinks_except_last_element(oldpath, resolved_oldpath); resolve_symlinks_except_last_element(newpath, resolved_newpath); + + resolved_oldpath.remove_trailing('/'); + resolved_newpath.remove_trailing('/'); + FNAME_FUNC_WRAPPER(rename, resolved_oldpath.base(), resolved_newpath.base()); } catch(Symlink_resolve_error) { return -1; @@ -617,19 +622,21 @@ extern "C" int rename(const char *oldpath, const char *newpath) extern "C" int rmdir(const char *path) { - struct stat stat_buf; - - if (stat(path, &stat_buf) == -1) - return -1; - - if (!S_ISDIR(stat_buf.st_mode)) { - errno = ENOTDIR; - return -1; - } - try { Absolute_path resolved_path; resolve_symlinks_except_last_element(path, resolved_path); + resolved_path.remove_trailing('/'); + + struct stat stat_buf { }; + + if (stat(resolved_path.base(), &stat_buf) == -1) + return -1; + + if (!S_ISDIR(stat_buf.st_mode)) { + errno = ENOTDIR; + return -1; + } + FNAME_FUNC_WRAPPER(rmdir, resolved_path.base()); } catch(Symlink_resolve_error) { return -1; diff --git a/repos/libports/src/test/libc_vfs/main.cc b/repos/libports/src/test/libc_vfs/main.cc index ae3514859..b3659705f 100644 --- a/repos/libports/src/test/libc_vfs/main.cc +++ b/repos/libports/src/test/libc_vfs/main.cc @@ -97,16 +97,18 @@ static void test(Genode::Xml_node node) int ret, fd; ssize_t count; - char const *dir_name = "testdir"; - char const *dir_name2 = "testdir2"; - char const *file_name = "test.tst"; - char const *file_name2 = "test2.tst"; - char const *file_name3 = "test3.tst"; - char const *file_name4 = "test4.tst"; - char const *file_name5 = "test5.tst"; - char const *pattern = "a single line of text"; + char const *trailing_slash_dir_name = "testdir/"; - size_t pattern_size = strlen(pattern) + 1; + char const *dir_name = "testdir"; + char const *dir_name2 = "testdir2"; + char const *file_name = "test.tst"; + char const *file_name2 = "test2.tst"; + char const *file_name3 = "test3.tst"; + char const *file_name4 = "test4.tst"; + char const *file_name5 = "test5.tst"; + char const *pattern = "a single line of text"; + + size_t const pattern_size = strlen(pattern) + 1; unsigned int iterations = 1; @@ -116,6 +118,12 @@ static void test(Genode::Xml_node node) for (unsigned int i = 0; i < iterations; i++) { + /* create directory given with a trailing slash */ + CALL_AND_CHECK(ret, mkdir(trailing_slash_dir_name, 0777), (ret == 0), "dir_name=%s", dir_name); + + /* remove directory given with a trailing slash */ + CALL_AND_CHECK(ret, rmdir(trailing_slash_dir_name), (ret == 0), "dir_name=%s", dir_name); + /* create directory (short name) */ CALL_AND_CHECK(ret, mkdir(dir_name, 0777), ((ret == 0) || (errno == EEXIST)), "dir_name=%s", dir_name);