From 9f619f70533967a5266e61aa8657c332f9fd0327 Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Thu, 14 Mar 2019 09:42:18 -0500 Subject: renameat: bring behaviour closer to POSIX - Fail if old or new is longer than PATH_MAX with ENAMETOOLONG. - Fail if old or new is 0 bytes long. - Fail if old or new has dot or dot-dot as the last component of their path name. The Linux kernel provides none of these behaviours. --- src/unistd/renameat.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/unistd/renameat.c b/src/unistd/renameat.c index c3b40a25..07386407 100644 --- a/src/unistd/renameat.c +++ b/src/unistd/renameat.c @@ -1,11 +1,38 @@ +#include +#include +#include #include +#include #include "syscall.h" int renameat(int oldfd, const char *old, int newfd, const char *new) { -#ifdef SYS_renameat + char old_copy[PATH_MAX+1], new_copy[PATH_MAX+1]; + char *base; + + if (strlen(old) > PATH_MAX || strlen(new) > PATH_MAX) { + errno = ENAMETOOLONG; + return -1; + } + + if (strlen(old) == 0 || strlen(new) == 0) { + errno = ENOENT; + return -1; + } + + strcpy(old_copy, old); + strcpy(new_copy, new); + + base = basename(old_copy); + strncpy(old_copy, base, sizeof(old_copy)); + base = basename(new_copy); + strncpy(new_copy, base, sizeof(new_copy)); + + if (strcmp(old_copy, ".") == 0 || strcmp(old_copy, "..") == 0 || + strcmp(new_copy, ".") == 0 || strcmp(new_copy, "..") == 0) { + errno = EINVAL; + return -1; + } + return syscall(SYS_renameat, oldfd, old, newfd, new); -#else - return syscall(SYS_renameat2, oldfd, old, newfd, new, 0); -#endif } -- cgit v1.2.3-60-g2f50