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;
}
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 9cfb918..fe98c10 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -98,6 +98,7 @@
int execlp(const char* __file, const char* __arg0, ...) __attribute__((__sentinel__));
int execle(const char* __path, const char* __arg0, ... /*, char* const* __envp */)
__attribute__((__sentinel__(1)));
+int fexecve(int __fd, char* const* __argv, char* const* __envp) __INTRODUCED_IN_FUTURE;
int nice(int __incr);
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 981dd59..af4efb9 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1325,6 +1325,7 @@
endhostent;
endnetent;
endprotoent;
+ fexecve;
getentropy;
getnetent;
getprotoent;
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index 29c5235..5c7f726 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1245,6 +1245,7 @@
endhostent;
endnetent;
endprotoent;
+ fexecve;
getentropy;
getnetent;
getprotoent;
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index eafbbd7..33ecbed 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1350,6 +1350,7 @@
endhostent;
endnetent;
endprotoent;
+ fexecve;
getentropy;
getnetent;
getprotoent;
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index a32131f..579491a 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1309,6 +1309,7 @@
endhostent;
endnetent;
endprotoent;
+ fexecve;
getentropy;
getnetent;
getprotoent;
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index 29c5235..5c7f726 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1245,6 +1245,7 @@
endhostent;
endnetent;
endprotoent;
+ fexecve;
getentropy;
getnetent;
getprotoent;
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index f1308ea..7d1d3ef 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1307,6 +1307,7 @@
endhostent;
endnetent;
endprotoent;
+ fexecve;
getentropy;
getnetent;
getprotoent;
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index 29c5235..5c7f726 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1245,6 +1245,7 @@
endhostent;
endnetent;
endprotoent;
+ fexecve;
getentropy;
getnetent;
getprotoent;
diff --git a/libc/private/FdPath.h b/libc/private/FdPath.h
new file mode 100644
index 0000000..4a6a2d5
--- /dev/null
+++ b/libc/private/FdPath.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+class FdPath {
+ public:
+ explicit FdPath(int fd) {
+ snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
+ }
+
+ const char* c_str() {
+ return buf;
+ }
+
+ private:
+ char buf[40];
+};