Add POSIX fexecve.
I'm skeptical about the usefulness of this, but it's in POSIX, it's
in glibc (but not iOS), and it is used in some internal source (test
runners and container code).
Bug: N/A
Test: ran tests
Change-Id: I92c5398f2a679b21a33fba92bc8e67e3ae2eb76f
diff --git a/libc/bionic/exec.cpp b/libc/bionic/exec.cpp
index 2001106..1cf3a58 100644
--- a/libc/bionic/exec.cpp
+++ b/libc/bionic/exec.cpp
@@ -39,6 +39,8 @@
#include <string.h>
#include <unistd.h>
+#include "private/FdPath.h"
+
extern "C" char** environ;
enum ExecVariant { kIsExecL, kIsExecLE, kIsExecLP };
@@ -170,3 +172,10 @@
if (saw_EACCES) errno = EACCES;
return -1;
}
+
+int fexecve(int fd, char* const* argv, char* const* envp) {
+ // execveat with AT_EMPTY_PATH (>= 3.19) seems to offer no advantages.
+ execve(FdPath(fd).c_str(), argv, envp);
+ if (errno == ENOENT) errno = EBADF;
+ return -1;
+}
diff --git a/libc/bionic/fchmod.cpp b/libc/bionic/fchmod.cpp
index ace8c6b..a486aae 100644
--- a/libc/bionic/fchmod.cpp
+++ b/libc/bionic/fchmod.cpp
@@ -33,13 +33,14 @@
#include <unistd.h>
#include <stdio.h>
+#include "private/FdPath.h"
+
extern "C" int ___fchmod(int, mode_t);
int fchmod(int fd, mode_t mode) {
int saved_errno = errno;
int result = ___fchmod(fd, mode);
-
- if ((result == 0) || (errno != EBADF)) {
+ if (result == 0 || errno != EBADF) {
return result;
}
@@ -52,16 +53,14 @@
// on an O_PATH file descriptor, and "man open" documents fchmod
// on O_PATH file descriptors as returning EBADF.
int fd_flag = fcntl(fd, F_GETFL);
- if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) {
+ if (fd_flag == -1 || (fd_flag & O_PATH) == 0) {
errno = EBADF;
return -1;
}
- char buf[40];
- snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
errno = saved_errno;
- result = chmod(buf, mode);
- if ((result == -1) && (errno == ELOOP)) {
+ result = chmod(FdPath(fd).c_str(), mode);
+ if (result == -1 && errno == ELOOP) {
// Linux does not support changing the mode of a symlink.
// For fchmodat(AT_SYMLINK_NOFOLLOW), POSIX requires a return
// value of ENOTSUP. Assume that's true here too.
diff --git a/libc/bionic/fgetxattr.cpp b/libc/bionic/fgetxattr.cpp
index 6d999bf..38b7ac3 100644
--- a/libc/bionic/fgetxattr.cpp
+++ b/libc/bionic/fgetxattr.cpp
@@ -33,13 +33,15 @@
#include <fcntl.h>
#include <stdio.h>
+#include "private/FdPath.h"
+
extern "C" ssize_t ___fgetxattr(int, const char*, void*, size_t);
ssize_t fgetxattr(int fd, const char *name, void *value, size_t size) {
int saved_errno = errno;
ssize_t result = ___fgetxattr(fd, name, value, size);
- if ((result != -1) || (errno != EBADF)) {
+ if (result != -1 || errno != EBADF) {
return result;
}
@@ -47,13 +49,11 @@
// may not directly support fgetxattr() on such a file descriptor.
// Use /proc/self/fd instead to emulate this support.
int fd_flag = fcntl(fd, F_GETFL);
- if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) {
+ if (fd_flag == -1 || (fd_flag & O_PATH) == 0) {
errno = EBADF;
return -1;
}
- char buf[40];
- snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
errno = saved_errno;
- return getxattr(buf, name, value, size);
+ return getxattr(FdPath(fd).c_str(), name, value, size);
}
diff --git a/libc/bionic/flistxattr.cpp b/libc/bionic/flistxattr.cpp
index 05a96d2..8ad9b85 100644
--- a/libc/bionic/flistxattr.cpp
+++ b/libc/bionic/flistxattr.cpp
@@ -33,13 +33,14 @@
#include <fcntl.h>
#include <stdio.h>
+#include "private/FdPath.h"
+
extern "C" ssize_t ___flistxattr(int, char*, size_t);
ssize_t flistxattr(int fd, char *list, size_t size) {
int saved_errno = errno;
ssize_t result = ___flistxattr(fd, list, size);
-
- if ((result != -1) || (errno != EBADF)) {
+ if (result != -1 || errno != EBADF) {
return result;
}
@@ -47,13 +48,11 @@
// may not directly support fgetxattr() on such a file descriptor.
// Use /proc/self/fd instead to emulate this support.
int fd_flag = fcntl(fd, F_GETFL);
- if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) {
+ if (fd_flag == -1 || (fd_flag & O_PATH) == 0) {
errno = EBADF;
return -1;
}
- char buf[40];
- snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
errno = saved_errno;
- return listxattr(buf, list, size);
+ return listxattr(FdPath(fd).c_str(), list, size);
}
diff --git a/libc/bionic/fsetxattr.cpp b/libc/bionic/fsetxattr.cpp
index 6d2e868..9ad0c76 100644
--- a/libc/bionic/fsetxattr.cpp
+++ b/libc/bionic/fsetxattr.cpp
@@ -33,13 +33,14 @@
#include <fcntl.h>
#include <stdio.h>
+#include "private/FdPath.h"
+
extern "C" int ___fsetxattr(int, const char*, const void*, size_t, int);
int fsetxattr(int fd, const char* name, const void* value, size_t size, int flags) {
int saved_errno = errno;
int result = ___fsetxattr(fd, name, value, size, flags);
-
- if ((result == 0) || (errno != EBADF)) {
+ if (result == 0 || errno != EBADF) {
return result;
}
@@ -47,13 +48,11 @@
// may not directly support fsetxattr() on such a file descriptor.
// Use /proc/self/fd instead to emulate this support.
int fd_flag = fcntl(fd, F_GETFL);
- if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) {
+ if (fd_flag == -1 || (fd_flag & O_PATH) == 0) {
errno = EBADF;
return -1;
}
- char buf[40];
- snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
errno = saved_errno;
- return setxattr(buf, name, value, size, flags);
+ return setxattr(FdPath(fd).c_str(), name, value, size, flags);
}
diff --git a/libc/bionic/pty.cpp b/libc/bionic/pty.cpp
index bdabf36..599cbd2 100644
--- a/libc/bionic/pty.cpp
+++ b/libc/bionic/pty.cpp
@@ -37,6 +37,7 @@
#include <utmp.h>
#include "bionic/pthread_internal.h"
+#include "private/FdPath.h"
int getpt() {
return posix_openpt(O_RDWR|O_NOCTTY);
@@ -94,10 +95,7 @@
return errno;
}
- char path[64];
- snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
-
- ssize_t count = readlink(path, buf, len);
+ ssize_t count = readlink(FdPath(fd).c_str(), buf, len);
if (count == -1) {
return errno;
}