diff --git a/Kernel/API/Syscall.h b/Kernel/API/Syscall.h index cabc347576..d31e79afe1 100644 --- a/Kernel/API/Syscall.h +++ b/Kernel/API/Syscall.h @@ -418,7 +418,9 @@ struct SC_symlink_params { }; struct SC_rename_params { + int olddirfd; StringArgument old_path; + int newdirfd; StringArgument new_path; }; diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp index 52ec729898..cb38d361b9 100644 --- a/Kernel/FileSystem/VirtualFileSystem.cpp +++ b/Kernel/FileSystem/VirtualFileSystem.cpp @@ -577,14 +577,14 @@ ErrorOr VirtualFileSystem::chmod(Credentials const& credentials, StringVie return chmod(credentials, custody, mode); } -ErrorOr VirtualFileSystem::rename(Credentials const& credentials, StringView old_path, StringView new_path, Custody& base) +ErrorOr VirtualFileSystem::rename(Credentials const& credentials, Custody& old_base, StringView old_path, Custody& new_base, StringView new_path) { RefPtr old_parent_custody; - auto old_custody = TRY(resolve_path(credentials, old_path, base, &old_parent_custody, O_NOFOLLOW_NOERROR)); + auto old_custody = TRY(resolve_path(credentials, old_path, old_base, &old_parent_custody, O_NOFOLLOW_NOERROR)); auto& old_inode = old_custody->inode(); RefPtr new_parent_custody; - auto new_custody_or_error = resolve_path(credentials, new_path, base, &new_parent_custody); + auto new_custody_or_error = resolve_path(credentials, new_path, new_base, &new_parent_custody); if (new_custody_or_error.is_error()) { if (new_custody_or_error.error().code() != ENOENT || !new_parent_custody) return new_custody_or_error.release_error(); diff --git a/Kernel/FileSystem/VirtualFileSystem.h b/Kernel/FileSystem/VirtualFileSystem.h index cd6ea83944..9a6be3362c 100644 --- a/Kernel/FileSystem/VirtualFileSystem.h +++ b/Kernel/FileSystem/VirtualFileSystem.h @@ -67,7 +67,7 @@ public: ErrorOr lookup_metadata(Credentials const&, StringView path, Custody& base, int options = 0); ErrorOr utime(Credentials const&, StringView path, Custody& base, time_t atime, time_t mtime); ErrorOr utimensat(Credentials const&, StringView path, Custody& base, timespec const& atime, timespec const& mtime, int options = 0); - ErrorOr rename(Credentials const&, StringView oldpath, StringView newpath, Custody& base); + ErrorOr rename(Credentials const&, Custody& old_base, StringView oldpath, Custody& new_base, StringView newpath); ErrorOr mknod(Credentials const&, StringView path, mode_t, dev_t, Custody& base); ErrorOr> open_directory(Credentials const&, StringView path, Custody& base); diff --git a/Kernel/Syscalls/rename.cpp b/Kernel/Syscalls/rename.cpp index 7ebcb3d4d0..102295d2fe 100644 --- a/Kernel/Syscalls/rename.cpp +++ b/Kernel/Syscalls/rename.cpp @@ -17,7 +17,7 @@ ErrorOr Process::sys$rename(Userspace auto params = TRY(copy_typed_from_user(user_params)); auto old_path = TRY(get_syscall_path_argument(params.old_path)); auto new_path = TRY(get_syscall_path_argument(params.new_path)); - TRY(VirtualFileSystem::the().rename(credentials(), old_path->view(), new_path->view(), current_directory())); + TRY(VirtualFileSystem::the().rename(credentials(), TRY(custody_for_dirfd(params.olddirfd)), old_path->view(), TRY(custody_for_dirfd(params.newdirfd)), new_path->view())); return 0; } diff --git a/Userland/Libraries/LibC/stdio.cpp b/Userland/Libraries/LibC/stdio.cpp index e73c64c856..ed34dd8101 100644 --- a/Userland/Libraries/LibC/stdio.cpp +++ b/Userland/Libraries/LibC/stdio.cpp @@ -1125,12 +1125,18 @@ int fclose(FILE* stream) // https://pubs.opengroup.org/onlinepubs/9699919799/functions/rename.html int rename(char const* oldpath, char const* newpath) +{ + return renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath); +} + +// https://pubs.opengroup.org/onlinepubs/9699919799/functions/renameat.html +int renameat(int olddirfd, char const* oldpath, int newdirfd, char const* newpath) { if (!oldpath || !newpath) { errno = EFAULT; return -1; } - Syscall::SC_rename_params params { { oldpath, strlen(oldpath) }, { newpath, strlen(newpath) } }; + Syscall::SC_rename_params params { olddirfd, { oldpath, strlen(oldpath) }, newdirfd, { newpath, strlen(newpath) } }; int rc = syscall(SC_rename, ¶ms); __RETURN_WITH_ERRNO(rc, rc, -1); } diff --git a/Userland/Libraries/LibC/stdio.h b/Userland/Libraries/LibC/stdio.h index 4b9a769f87..83c349f57d 100644 --- a/Userland/Libraries/LibC/stdio.h +++ b/Userland/Libraries/LibC/stdio.h @@ -96,6 +96,7 @@ int setvbuf(FILE*, char* buf, int mode, size_t); void setbuf(FILE*, char* buf); void setlinebuf(FILE*); int rename(char const* oldpath, char const* newpath); +int renameat(int olddirfd, char const* oldpath, int newdirfd, char const* newpath); FILE* tmpfile(void); char* tmpnam(char*); FILE* popen(char const* command, char const* type); diff --git a/Userland/Libraries/LibCore/System.cpp b/Userland/Libraries/LibCore/System.cpp index 11c8ea9b02..f96519ebf4 100644 --- a/Userland/Libraries/LibCore/System.cpp +++ b/Userland/Libraries/LibCore/System.cpp @@ -920,7 +920,9 @@ ErrorOr rename(StringView old_path, StringView new_path) #ifdef AK_OS_SERENITY Syscall::SC_rename_params params { + .olddirfd = AT_FDCWD, .old_path = { old_path.characters_without_null_termination(), old_path.length() }, + .newdirfd = AT_FDCWD, .new_path = { new_path.characters_without_null_termination(), new_path.length() }, }; int rc = syscall(SC_rename, ¶ms);