diff options
author | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2019-03-14 09:42:18 -0500 |
---|---|---|
committer | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2023-05-05 21:21:39 -0500 |
commit | 9f619f70533967a5266e61aa8657c332f9fd0327 (patch) | |
tree | 55d0e031b49c9895706dc1be1a9f41cac5419628 /src | |
parent | 1cedfe0875b4f4be57787ee5183ce8c843954361 (diff) | |
download | musl-9f619f70533967a5266e61aa8657c332f9fd0327.tar.gz musl-9f619f70533967a5266e61aa8657c332f9fd0327.tar.bz2 musl-9f619f70533967a5266e61aa8657c332f9fd0327.tar.xz musl-9f619f70533967a5266e61aa8657c332f9fd0327.zip |
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/unistd/renameat.c | 35 |
1 files 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 <errno.h> +#include <libgen.h> +#include <limits.h> #include <stdio.h> +#include <string.h> #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 } |