From 0d7d0dd6b6c5ec2fc29009001cb70c7b5a666257 Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Mon, 18 Mar 2019 23:19:22 +0000 Subject: system/musl: more POSIX stuff --- system/musl/amalgamation.patch | 366 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 366 insertions(+) (limited to 'system/musl/amalgamation.patch') diff --git a/system/musl/amalgamation.patch b/system/musl/amalgamation.patch index d4d4465dc..fa118c910 100644 --- a/system/musl/amalgamation.patch +++ b/system/musl/amalgamation.patch @@ -280,3 +280,369 @@ index 03c5a77b..c423b825 100644 int ret = __clock_gettime(CLOCK_REALTIME, ts); return ret < 0 ? 0 : base; } +diff --git a/src/stdio/setvbuf.c b/src/stdio/setvbuf.c +index 06ea296c..523dddc8 100644 +--- a/src/stdio/setvbuf.c ++++ b/src/stdio/setvbuf.c +@@ -12,13 +12,15 @@ int setvbuf(FILE *restrict f, char *restrict buf, int type, size_t size) + + if (type == _IONBF) { + f->buf_size = 0; +- } else { ++ } else if (type == _IOLBF || type == _IOFBF) { + if (buf && size >= UNGET) { + f->buf = (void *)(buf + UNGET); + f->buf_size = size - UNGET; + } + if (type == _IOLBF && f->buf_size) + f->lbf = '\n'; ++ } else { ++ return -1; + } + + f->flags |= F_SVB; +diff --git a/src/unistd/getcwd.c b/src/unistd/getcwd.c +index f407ffe0..4fd3a60c 100644 +--- a/src/unistd/getcwd.c ++++ b/src/unistd/getcwd.c +@@ -15,8 +15,11 @@ char *getcwd(char *buf, size_t size) + return 0; + } + long ret = syscall(SYS_getcwd, buf, size); +- if (ret < 0) ++ if (ret < 0) { ++ if (errno == ENAMETOOLONG) ++ errno = ENOMEM; + return 0; ++ } + if (ret == 0 || buf[0] != '/') { + errno = ENOENT; + return 0; +diff --git a/include/tar.h b/include/tar.h +index 2eba66ec..d15bd9b4 100644 +--- a/include/tar.h ++++ b/include/tar.h +@@ -5,9 +5,7 @@ + + #define TSUID 04000 + #define TSGID 02000 +-#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE) + #define TSVTX 01000 +-#endif + #define TUREAD 00400 + #define TUWRITE 00200 + #define TUEXEC 00100 +diff --git a/src/conf/fpathconf.c b/src/conf/fpathconf.c +index b6a9d63e..83e47e87 100644 +--- a/src/conf/fpathconf.c ++++ b/src/conf/fpathconf.c +@@ -5,7 +5,7 @@ + long fpathconf(int fd, int name) + { + static const long values[] = { +- [_PC_LINK_MAX] = _POSIX_LINK_MAX, ++ [_PC_LINK_MAX] = -1, + [_PC_MAX_CANON] = _POSIX_MAX_CANON, + [_PC_MAX_INPUT] = _POSIX_MAX_INPUT, + [_PC_NAME_MAX] = NAME_MAX, +diff --git a/include/unistd.h b/include/unistd.h +index 1bdd3292..cdb16c19 100644 +--- a/include/unistd.h ++++ b/include/unistd.h +@@ -33,16 +33,23 @@ extern "C" { + #include + + int pipe(int [2]); +-int pipe2(int [2], int); + int close(int); +-int posix_close(int, int); + int dup(int); + int dup2(int, int); +-int dup3(int, int, int); + off_t lseek(int, off_t, int); + int fsync(int); + int fdatasync(int); + ++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) \ ++ || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 > 700) \ ++ || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE+0 > 200809L) ++int pipe2(int [2], int); ++int dup3(int, int, int); ++int posix_close(int, int); ++ ++#define POSIX_CLOSE_RESTART 0 ++#endif ++ + ssize_t read(int, void *, size_t); + ssize_t write(int, const void *, size_t); + ssize_t pread(int, void *, size_t, off_t); +@@ -200,8 +207,6 @@ int eaccess(const char *, int); + #define off64_t off_t + #endif + +-#define POSIX_CLOSE_RESTART 0 +- + #define _XOPEN_VERSION 700 + #define _XOPEN_UNIX 1 + #define _XOPEN_ENH_I18N 1 +diff --git a/src/misc/forkpty.c b/src/misc/forkpty.c +index caf13adb..047eb7d6 100644 +--- a/src/misc/forkpty.c ++++ b/src/misc/forkpty.c +@@ -1,3 +1,4 @@ ++#define _GNU_SOURCE + #include + #include + #include +diff --git a/src/misc/wordexp.c b/src/misc/wordexp.c +index db83a69f..1ae03f9f 100644 +--- a/src/misc/wordexp.c ++++ b/src/misc/wordexp.c +@@ -1,3 +1,4 @@ ++#define _GNU_SOURCE + #include + #include + #include +diff --git a/src/stdio/popen.c b/src/stdio/popen.c +index 92cb57ee..1ff9e0d9 100644 +--- a/src/stdio/popen.c ++++ b/src/stdio/popen.c +@@ -1,3 +1,4 @@ ++#define _GNU_SOURCE + #include + #include + #include +diff --git a/src/unistd/faccessat.c b/src/unistd/faccessat.c +index 76bbd4c7..d5e70608 100644 +--- a/src/unistd/faccessat.c ++++ b/src/unistd/faccessat.c +@@ -1,3 +1,4 @@ ++#define _GNU_SOURCE + #include + #include + #include +diff --git a/include/fcntl.h b/include/fcntl.h +index 4d91338b..04321887 100644 +--- a/include/fcntl.h ++++ b/include/fcntl.h +@@ -36,8 +36,9 @@ int openat(int, const char *, int, ...); + int posix_fadvise(int, off_t, off_t, int); + int posix_fallocate(int, off_t, off_t); + +-#define O_SEARCH O_PATH +-#define O_EXEC O_PATH ++#define O_SEARCH O_PATH ++#define O_EXEC O_PATH ++#define O_TTY_INIT 0 + + #define O_ACCMODE (03|O_SEARCH) + #define O_RDONLY 00 +diff --git a/src/dirent/fdopendir.c b/src/dirent/fdopendir.c +index c377271d..d78fb87f 100644 +--- a/src/dirent/fdopendir.c ++++ b/src/dirent/fdopendir.c +@@ -13,6 +13,10 @@ DIR *fdopendir(int fd) + if (fstat(fd, &st) < 0) { + return 0; + } ++ if (fcntl(fd, F_GETFL) & O_PATH) { ++ errno = EBADF; ++ return 0; ++ } + if (!S_ISDIR(st.st_mode)) { + errno = ENOTDIR; + return 0; +diff --git a/src/unistd/renameat.c b/src/unistd/renameat.c +index 12574822..07386407 100644 +--- a/src/unistd/renameat.c ++++ b/src/unistd/renameat.c +@@ -1,7 +1,38 @@ ++#include ++#include ++#include + #include ++#include + #include "syscall.h" + + int renameat(int oldfd, const char *old, int newfd, const char *new) + { ++ 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); + } +diff --git a/src/unistd/renameat.c b/src/unistd/renameat.c +index 07386407..7e850401 100644 +--- a/src/unistd/renameat.c ++++ b/src/unistd/renameat.c +@@ -1,16 +1,23 @@ + #include ++#include + #include + #include + #include + #include ++#include ++#include ++#include + #include "syscall.h" + + int renameat(int oldfd, const char *old, int newfd, const char *new) + { + char old_copy[PATH_MAX+1], new_copy[PATH_MAX+1]; + char *base; ++ size_t old_size, new_size; ++ struct stat statbuf; + +- if (strlen(old) > PATH_MAX || strlen(new) > PATH_MAX) { ++ if ((old_size = strlen(old)) > PATH_MAX || \ ++ (new_size = strlen(new)) > PATH_MAX) { + errno = ENAMETOOLONG; + return -1; + } +@@ -34,5 +41,31 @@ int renameat(int oldfd, const char *old, int newfd, const char *new) + return -1; + } + ++ /* The Linux kernel will fail when attempting to rename a symlink of a ++ directory with a trailing slash. We therefore have to handle this ++ case ourselves. */ ++ if (old[old_size - 1] == '/') { ++ /* Calling stat(2) on a symlink to a dir with the trailing ++ slash causes stat(2) to return the actual directory instead ++ of the symlink itself. */ ++ strcpy(old_copy, old); ++ old_copy[old_size - 1] = '\0'; ++ if (fstatat(oldfd, old_copy, &statbuf, AT_SYMLINK_NOFOLLOW) == -1) { ++ return -1; ++ } ++ if (S_ISLNK(statbuf.st_mode)) { ++ if (fstatat(oldfd, old, &statbuf, 0) == -1) { ++ return -1; ++ } ++ if (S_ISDIR(statbuf.st_mode)) { ++ old = old_copy; ++ } else { ++ /* may as well not waste the syscall */ ++ errno = ENOTDIR; ++ return -1; ++ } ++ } ++ } ++ + return syscall(SYS_renameat, oldfd, old, newfd, new); + } +diff --git a/src/unistd/renameat.c b/src/unistd/renameat.c +index d0f31c21..e2f03d39 100644 +--- a/src/unistd/renameat.c ++++ b/src/unistd/renameat.c +@@ -9,12 +9,31 @@ + #include + #include "syscall.h" + ++static inline int test_symlink_dirness(int fd, const char *pathname) ++{ ++ struct stat statbuf; ++ if (fstatat(fd, pathname, &statbuf, AT_SYMLINK_NOFOLLOW) == -1) { ++ return 1; ++ } ++ if (S_ISLNK(statbuf.st_mode)) { ++ if (fstatat(fd, pathname, &statbuf, 0) == -1) return 1; ++ ++ if (S_ISDIR(statbuf.st_mode)) return 0; ++ else { ++ errno = ENOTDIR; ++ return -1; ++ } ++ } ++ return 1; ++} ++ + int renameat(int oldfd, const char *old, int newfd, const char *new) + { + char old_copy[PATH_MAX+1], new_copy[PATH_MAX+1]; + char *base; + size_t old_size, new_size; +- struct stat statbuf; ++ struct stat oldstat, newstat; ++ int r; + + if ((old_size = strlen(old)) > PATH_MAX || \ + (new_size = strlen(new)) > PATH_MAX) { +@@ -22,11 +41,18 @@ int renameat(int oldfd, const char *old, int newfd, const char *new) + return -1; + } + +- if (strlen(old) == 0 || strlen(new) == 0) { ++ if (old_size == 0 || new_size == 0) { + errno = ENOENT; + return -1; + } + ++ /* Test equality of old and new. ++ If they both resolve to the same dentry, we do nothing. */ ++ if (fstatat(oldfd, old, &oldstat, 0) == 0 && \ ++ fstatat(newfd, new, &newstat, 0) == 0 && \ ++ oldstat.st_dev == newstat.st_dev && \ ++ oldstat.st_ino == newstat.st_ino) return 0; ++ + strcpy(old_copy, old); + strcpy(new_copy, new); + +@@ -50,21 +76,17 @@ int renameat(int oldfd, const char *old, int newfd, const char *new) + of the symlink itself. */ + strcpy(old_copy, old); + old_copy[old_size - 1] = '\0'; +- if (fstatat(oldfd, old_copy, &statbuf, AT_SYMLINK_NOFOLLOW) == -1) { +- return -1; +- } +- if (S_ISLNK(statbuf.st_mode)) { +- if (fstatat(oldfd, old, &statbuf, 0) == -1) { +- return -1; +- } +- if (S_ISDIR(statbuf.st_mode)) { +- old = old_copy; +- } else { +- /* may as well not waste the syscall */ +- errno = ENOTDIR; +- return -1; +- } +- } ++ r = test_symlink_dirness(oldfd, old_copy); ++ if (r == 0) old = old_copy; ++ else if (r == -1) return -1; ++ } ++ ++ if (new[new_size - 1] == '/') { ++ strcpy(new_copy, new); ++ new_copy[new_size - 1] = '\0'; ++ r = test_symlink_dirness(newfd, new_copy); ++ if (r == 0) new = new_copy; ++ else if (r == -1) return -1; + } + + return syscall(SYS_renameat, oldfd, old, newfd, new); -- cgit v1.2.3-60-g2f50