Merge "Make __libc_init_main_thread and android_set_abort_message weak"
diff --git a/docs/status.md b/docs/status.md
index c119439..7d2f3b6 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -72,9 +72,6 @@
aio_suspend
aio_write
fexecve
-fmtmsg
-getdate
-getdate_err
lio_listio
pthread_attr_getinheritsched
pthread_attr_setinheritsched
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/bits/posix_limits.h b/libc/include/bits/posix_limits.h
index e5846d6..2688cc5 100644
--- a/libc/include/bits/posix_limits.h
+++ b/libc/include/bits/posix_limits.h
@@ -70,7 +70,7 @@
#define _POSIX_SHELL 1 /* system. */
#define _POSIX_SPAWN __BIONIC_POSIX_FEATURE_SINCE(28) /* <spawn.h> */
#define _POSIX_SPIN_LOCKS __BIONIC_POSIX_FEATURE_SINCE(24) /* pthread_spin_*. */
-#define _POSIX_SPORADIC_SERVER _POSIX_VERSION /* sched_setparam/sched_setscheduler. */
+#define _POSIX_SPORADIC_SERVER __BIONIC_POSIX_FEATURE_MISSING /* No SCHED_SPORADIC. */
#define _POSIX_SYNCHRONIZED_IO _POSIX_VERSION
#define _POSIX_THREAD_ATTR_STACKADDR _POSIX_VERSION /* Strictly, we're missing the deprecated pthread_attr_getstackaddr/pthread_attr_setstackaddr, but we do have pthread_attr_getstack/pthread_attr_setstack. */
#define _POSIX_THREAD_ATTR_STACKSIZE _POSIX_VERSION /* pthread_attr_getstack/pthread_attr_getstacksize/pthread_attr_setstack/pthread_attr_setstacksize. */
@@ -82,7 +82,7 @@
#define _POSIX_THREAD_ROBUST_PRIO_INHERIT __BIONIC_POSIX_FEATURE_MISSING
#define _POSIX_THREAD_ROBUST_PRIO_PROTECT __BIONIC_POSIX_FEATURE_MISSING
#define _POSIX_THREAD_SAFE_FUNCTIONS _POSIX_VERSION
-#define _POSIX_THREAD_SPORADIC_SERVER _POSIX_VERSION /* sched_setparam/sched_setscheduler. */
+#define _POSIX_THREAD_SPORADIC_SERVER __BIONIC_POSIX_FEATURE_MISSING /* No SCHED_SPORADIC. */
#define _POSIX_THREADS _POSIX_VERSION /* Strictly, pthread_cancel/pthread_testcancel are missing. */
#define _POSIX_TIMEOUTS __BIONIC_POSIX_FEATURE_SINCE(21) /* pthread_mutex_timedlock arrived late. */
#define _POSIX_TIMERS _POSIX_VERSION /* clock_getres/clock_gettime/clock_settime/nanosleep/timer_create/timer_delete/timer_gettime/timer_getoverrun/timer_settime. */
@@ -94,6 +94,15 @@
#define _POSIX_VDISABLE '\0'
+#define _POSIX2_C_BIND _POSIX_VERSION
+#define _POSIX2_C_DEV __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX2_CHAR_TERM _POSIX_VERSION
+#define _POSIX2_FORT_DEV __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX2_FORT_RUN __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX2_LOCALEDEF __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX2_SW_DEV __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX2_UPE __BIONIC_POSIX_FEATURE_MISSING
+
#if defined(__LP64__)
#define _POSIX_V7_ILP32_OFF32 -1
#define _POSIX_V7_ILP32_OFFBIG -1
@@ -106,16 +115,26 @@
#define _POSIX_V7_LPBIG_OFFBIG -1
#endif
+#define _XOPEN_CRYPT __BIONIC_POSIX_FEATURE_MISSING
+#define _XOPEN_ENH_I18N 1
+#define _XOPEN_LEGACY __BIONIC_POSIX_FEATURE_MISSING
+#define _XOPEN_REALTIME 1
+#define _XOPEN_REALTIME_THREADS 1
+#define _XOPEN_SHM 1
+#define _XOPEN_STREAMS __BIONIC_POSIX_FEATURE_MISSING
+#define _XOPEN_UNIX 1
+
/* Minimum values for other maxima. These numbers are simply lower bounds mandated by POSIX. */
-/* Any constant values here other than -1 or 200809L are explicitly specified by POSIX.1-2008. */
+/* The constant values here are explicitly specified by POSIX, not implementation dependent. */
#define _POSIX_AIO_LISTIO_MAX 2
#define _POSIX_AIO_MAX 1
#define _POSIX_ARG_MAX 4096
#define _POSIX_CHILD_MAX 25
+#define _POSIX_CLOCKRES_MIN 20000000
#define _POSIX_DELAYTIMER_MAX 32
#define _POSIX_HOST_NAME_MAX 255
#define _POSIX_LINK_MAX 8
-#define _POSIX_LOGIN_NAME_MAX 9 /* includes trailing NUL */
+#define _POSIX_LOGIN_NAME_MAX 9
#define _POSIX_MAX_CANON 255
#define _POSIX_MAX_INPUT 255
#define _POSIX_MQ_OPEN_MAX 8
@@ -126,45 +145,36 @@
#define _POSIX_PATH_MAX 256
#define _POSIX_PIPE_BUF 512
#define _POSIX_RE_DUP_MAX 255
+#define _POSIX_RTSIG_MAX 8
#define _POSIX_SEM_NSEMS_MAX 256
#define _POSIX_SEM_VALUE_MAX 32767
#define _POSIX_SIGQUEUE_MAX 32
#define _POSIX_SSIZE_MAX 32767
#define _POSIX_STREAM_MAX 8
+#define _POSIX_SS_REPL_MAX 4
#define _POSIX_SYMLINK_MAX 255
#define _POSIX_SYMLOOP_MAX 8
#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
#define _POSIX_THREAD_KEYS_MAX 128
#define _POSIX_THREAD_THREADS_MAX 64
#define _POSIX_TIMER_MAX 32
+#define _POSIX_TRACE_EVENT_NAME_MAX 30
#define _POSIX_TRACE_NAME_MAX 8
#define _POSIX_TRACE_SYS_MAX 8
#define _POSIX_TRACE_USER_EVENT_MAX 32
-#define _POSIX_TTY_NAME_MAX 9 /* includes trailing NUL */
+#define _POSIX_TTY_NAME_MAX 9
#define _POSIX_TZNAME_MAX 6
#define _POSIX2_BC_BASE_MAX 99
#define _POSIX2_BC_DIM_MAX 2048
#define _POSIX2_BC_SCALE_MAX 99
#define _POSIX2_BC_STRING_MAX 1000
#define _POSIX2_CHARCLASS_NAME_MAX 14
-#define _POSIX2_CHAR_TERM -1 /* not implemented */
#define _POSIX2_COLL_WEIGHTS_MAX 2
-#define _POSIX2_C_BIND _POSIX_VERSION
-#define _POSIX2_C_DEV -1 /* c dev utilities not implemented */
#define _POSIX2_EXPR_NEST_MAX 32
#define _POSIX2_LINE_MAX 2048
-#define _POSIX2_LOCALEDEF -1 /* localedef utilitiy not implemented */
-#define _POSIX2_RE_DUP_MAX _POSIX_RE_DUP_MAX
-#define _POSIX2_SW_DEV -1 /* software dev utilities not implemented */
-#define _POSIX2_UPE -1 /* user portability utilities not implemented */
-
-#define _XOPEN_ENH_I18N -1 /* we don't support internationalization in the C library */
-#define _XOPEN_CRYPT -1 /* don't support X/Open Encryption */
+#define _POSIX2_RE_DUP_MAX 255
#define _XOPEN_IOV_MAX 16
-#define _XOPEN_LEGACY -1 /* not support all */
-#define _XOPEN_REALTIME -1 /* we don't support all these functions */
-#define _XOPEN_REALTIME_THREADS -1 /* same here */
-#define _XOPEN_SHM -1
-#define _XOPEN_UNIX 1
+#define _XOPEN_NAME_MAX 255
+#define _XOPEN_PATH_MAX 1024
#endif
diff --git a/libc/include/limits.h b/libc/include/limits.h
index 4384f6f..48e7ea9 100644
--- a/libc/include/limits.h
+++ b/libc/include/limits.h
@@ -61,6 +61,7 @@
#else
# define LONG_BIT 32
#endif
+#define WORD_BIT 32
#define SCHAR_MAX 0x7f /* max value for a signed char */
#define SCHAR_MIN (-0x7f-1) /* min value for a signed char */
@@ -130,6 +131,8 @@
#define MB_LEN_MAX 4
+#define NZERO 20
+
#define IOV_MAX 1024
#define SEM_VALUE_MAX 0x3fffffff
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/CachedProperty.h b/libc/private/CachedProperty.h
index 417a855..84ead01 100644
--- a/libc/private/CachedProperty.h
+++ b/libc/private/CachedProperty.h
@@ -42,7 +42,9 @@
: property_name_(property_name),
prop_info_(nullptr),
cached_area_serial_(0),
- cached_property_serial_(0) {
+ cached_property_serial_(0),
+ is_read_only_(strncmp(property_name, "ro.", 3) == 0),
+ read_only_property_(nullptr) {
cached_value_[0] = '\0';
}
@@ -76,7 +78,9 @@
__system_property_read_callback(prop_info_, &CachedProperty::Callback, this);
}
}
-
+ if (is_read_only_ && read_only_property_ != nullptr) {
+ return read_only_property_;
+ }
return cached_value_;
}
@@ -86,10 +90,18 @@
uint32_t cached_area_serial_;
uint32_t cached_property_serial_;
char cached_value_[PROP_VALUE_MAX];
+ bool is_read_only_;
+ const char* read_only_property_;
static void Callback(void* data, const char*, const char* value, uint32_t serial) {
CachedProperty* instance = reinterpret_cast<CachedProperty*>(data);
instance->cached_property_serial_ = serial;
- strcpy(instance->cached_value_, value);
+ // Read only properties can be larger than PROP_VALUE_MAX, but also never change value or
+ // location, thus we return the pointer from the shared memory directly.
+ if (instance->is_read_only_) {
+ instance->read_only_property_ = value;
+ } else {
+ strlcpy(instance->cached_value_, value, PROP_VALUE_MAX);
+ }
}
};
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];
+};
diff --git a/libc/tools/check-symbols-glibc.py b/libc/tools/check-symbols-glibc.py
index 7657925..31a7484 100755
--- a/libc/tools/check-symbols-glibc.py
+++ b/libc/tools/check-symbols-glibc.py
@@ -184,13 +184,17 @@
])
# POSIX has some stuff that's too stupid for words (a64l) or not actually
# implemented in glibc unless you count always failing with ENOSYS as
-# being implemented (fattach).
+# being implemented (fattach). Other stuff (fmtmsg) isn't used in any
+# codebase I have access to, internal or external.
in_posix_and_glibc_but_dead_or_useless = set([
'a64l', # obsolete
'confstr', # obsolete
'endutxent', # no utmp on Android
'fattach', # obsolete
'fdetach', # obsolete
+ 'fmtmsg', # unused
+ 'getdate', # unused
+ 'getdate_err', # unused
'gethostid', # obsolete
'getmsg', # obsolete
'getpmsg', # obsolete
diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp
index 2133a2c..d56b017 100644
--- a/tests/dl_test.cpp
+++ b/tests/dl_test.cpp
@@ -181,12 +181,8 @@
#endif
#if defined(__BIONIC__)
-static bool is_user_build() {
- std::string build_type = android::base::GetProperty("ro.build.type", "user");
- if (build_type == "userdebug" || build_type == "eng") {
- return false;
- }
- return true;
+static bool is_debuggable_build() {
+ return android::base::GetBoolProperty("ro.debuggable", false);
}
#endif
@@ -194,7 +190,7 @@
// whose search paths include the 'ns2/' subdir.
TEST(dl, exec_with_ld_config_file) {
#if defined(__BIONIC__)
- if (is_user_build()) {
+ if (!is_debuggable_build()) {
// LD_CONFIG_FILE is not supported on user build
return;
}
@@ -216,7 +212,7 @@
// additional namespaces other than the default namespace.
TEST(dl, exec_with_ld_config_file_with_ld_preload) {
#if defined(__BIONIC__)
- if (is_user_build()) {
+ if (!is_debuggable_build()) {
// LD_CONFIG_FILE is not supported on user build
return;
}
@@ -244,7 +240,7 @@
// This test is only for CTS.
return;
}
- if (!is_user_build()) {
+ if (is_debuggable_build()) {
// Skip the test for non production devices
return;
}
diff --git a/tests/limits_test.cpp b/tests/limits_test.cpp
index 1d48ffe..ed42dbb 100644
--- a/tests/limits_test.cpp
+++ b/tests/limits_test.cpp
@@ -19,9 +19,9 @@
#include <limits.h>
TEST(limits, macros) {
-#if CHAR_BIT != 8
-#error Insane CHAR_BIT
-#endif
+ ASSERT_EQ(8, CHAR_BIT);
+ ASSERT_EQ(static_cast<int>(sizeof(int)), WORD_BIT);
+ ASSERT_EQ(20, NZERO);
#if !defined(MB_LEN_MAX)
#error MB_LEN_MAX
#endif
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index ced0315..c79ed59 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -686,104 +686,131 @@
ASSERT_TRUE(rc > 0 && powerof2(rc));
}
-
-TEST(UNISTD_TEST, _POSIX_macros_smoke) {
+TEST(UNISTD_TEST, _POSIX_constants) {
// Make a tight verification of _POSIX_* / _POSIX2_* / _XOPEN_* macros, to prevent change by mistake.
// Verify according to POSIX.1-2008.
EXPECT_EQ(200809L, _POSIX_VERSION);
+ EXPECT_EQ(2, _POSIX_AIO_LISTIO_MAX);
+ EXPECT_EQ(1, _POSIX_AIO_MAX);
+ EXPECT_EQ(4096, _POSIX_ARG_MAX);
+ EXPECT_EQ(25, _POSIX_CHILD_MAX);
+ EXPECT_EQ(20000000, _POSIX_CLOCKRES_MIN);
+ EXPECT_EQ(32, _POSIX_DELAYTIMER_MAX);
+ EXPECT_EQ(255, _POSIX_HOST_NAME_MAX);
+ EXPECT_EQ(8, _POSIX_LINK_MAX);
+ EXPECT_EQ(9, _POSIX_LOGIN_NAME_MAX);
+ EXPECT_EQ(255, _POSIX_MAX_CANON);
+ EXPECT_EQ(255, _POSIX_MAX_INPUT);
+ EXPECT_EQ(8, _POSIX_MQ_OPEN_MAX);
+ EXPECT_EQ(32, _POSIX_MQ_PRIO_MAX);
+ EXPECT_EQ(14, _POSIX_NAME_MAX);
+ EXPECT_EQ(8, _POSIX_NGROUPS_MAX);
+ EXPECT_EQ(20, _POSIX_OPEN_MAX);
+ EXPECT_EQ(256, _POSIX_PATH_MAX);
+ EXPECT_EQ(512, _POSIX_PIPE_BUF);
+ EXPECT_EQ(255, _POSIX_RE_DUP_MAX);
+ EXPECT_EQ(8, _POSIX_RTSIG_MAX);
+ EXPECT_EQ(256, _POSIX_SEM_NSEMS_MAX);
+ EXPECT_EQ(32767, _POSIX_SEM_VALUE_MAX);
+ EXPECT_EQ(32, _POSIX_SIGQUEUE_MAX);
+ EXPECT_EQ(32767, _POSIX_SSIZE_MAX);
+ EXPECT_EQ(8, _POSIX_STREAM_MAX);
+#if !defined(__GLIBC__)
+ EXPECT_EQ(4, _POSIX_SS_REPL_MAX);
+#endif
+ EXPECT_EQ(255, _POSIX_SYMLINK_MAX);
+ EXPECT_EQ(8, _POSIX_SYMLOOP_MAX);
+ EXPECT_EQ(4, _POSIX_THREAD_DESTRUCTOR_ITERATIONS);
+ EXPECT_EQ(128, _POSIX_THREAD_KEYS_MAX);
+ EXPECT_EQ(64, _POSIX_THREAD_THREADS_MAX);
+ EXPECT_EQ(32, _POSIX_TIMER_MAX);
+#if !defined(__GLIBC__)
+ EXPECT_EQ(30, _POSIX_TRACE_EVENT_NAME_MAX);
+ EXPECT_EQ(8, _POSIX_TRACE_NAME_MAX);
+ EXPECT_EQ(8, _POSIX_TRACE_SYS_MAX);
+ EXPECT_EQ(32, _POSIX_TRACE_USER_EVENT_MAX);
+#endif
+ EXPECT_EQ(9, _POSIX_TTY_NAME_MAX);
+ EXPECT_EQ(6, _POSIX_TZNAME_MAX);
+ EXPECT_EQ(99, _POSIX2_BC_BASE_MAX);
+ EXPECT_EQ(2048, _POSIX2_BC_DIM_MAX);
+ EXPECT_EQ(99, _POSIX2_BC_SCALE_MAX);
+ EXPECT_EQ(1000, _POSIX2_BC_STRING_MAX);
+ EXPECT_EQ(14, _POSIX2_CHARCLASS_NAME_MAX);
+ EXPECT_EQ(2, _POSIX2_COLL_WEIGHTS_MAX);
+ EXPECT_EQ(32, _POSIX2_EXPR_NEST_MAX);
+ EXPECT_EQ(2048, _POSIX2_LINE_MAX);
+ EXPECT_EQ(255, _POSIX2_RE_DUP_MAX);
+
+ EXPECT_EQ(16, _XOPEN_IOV_MAX);
+#if !defined(__GLIBC__)
+ EXPECT_EQ(255, _XOPEN_NAME_MAX);
+ EXPECT_EQ(1024, _XOPEN_PATH_MAX);
+#endif
+}
+
+TEST(UNISTD_TEST, _POSIX_options) {
EXPECT_EQ(_POSIX_VERSION, _POSIX_ADVISORY_INFO);
- EXPECT_GT(_POSIX_AIO_LISTIO_MAX, 0);
- EXPECT_GT(_POSIX_AIO_MAX, 0);
- EXPECT_GT(_POSIX_ARG_MAX, 0);
EXPECT_GT(_POSIX_BARRIERS, 0);
EXPECT_GT(_POSIX_SPIN_LOCKS, 0);
- EXPECT_GT(_POSIX_CHILD_MAX, 0);
EXPECT_NE(_POSIX_CHOWN_RESTRICTED, -1);
EXPECT_EQ(_POSIX_VERSION, _POSIX_CLOCK_SELECTION);
+#if !defined(__GLIBC__) // glibc supports ancient kernels.
EXPECT_EQ(_POSIX_VERSION, _POSIX_CPUTIME);
- EXPECT_GT(_POSIX_DELAYTIMER_MAX, 0);
+#endif
EXPECT_EQ(_POSIX_VERSION, _POSIX_FSYNC);
- EXPECT_GT(_POSIX_HOST_NAME_MAX, 0);
EXPECT_EQ(_POSIX_VERSION, _POSIX_IPV6);
EXPECT_GT(_POSIX_JOB_CONTROL, 0);
- EXPECT_GT(_POSIX_LINK_MAX, 0);
- EXPECT_GT(_POSIX_LOGIN_NAME_MAX, 0);
EXPECT_EQ(_POSIX_VERSION, _POSIX_MAPPED_FILES);
- EXPECT_GT(_POSIX_MAX_CANON, 0);
- EXPECT_GT(_POSIX_MAX_INPUT, 0);
EXPECT_EQ(_POSIX_VERSION, _POSIX_MEMLOCK);
EXPECT_EQ(_POSIX_VERSION, _POSIX_MEMLOCK_RANGE);
EXPECT_EQ(_POSIX_VERSION, _POSIX_MEMORY_PROTECTION);
+#if !defined(__GLIBC__) // glibc supports ancient kernels.
EXPECT_EQ(_POSIX_VERSION, _POSIX_MONOTONIC_CLOCK);
- EXPECT_GT(_POSIX_MQ_OPEN_MAX, 0);
- EXPECT_GT(_POSIX_MQ_PRIO_MAX, 0);
- EXPECT_GT(_POSIX_NAME_MAX, 0);
- EXPECT_GT(_POSIX_NGROUPS_MAX, 0);
+#endif
EXPECT_GT(_POSIX_NO_TRUNC, 0);
- EXPECT_GT(_POSIX_OPEN_MAX, 0);
- EXPECT_GT(_POSIX_PATH_MAX, 0);
- EXPECT_GT(_POSIX_PIPE_BUF, 0);
EXPECT_EQ(_POSIX_VERSION, _POSIX_PRIORITY_SCHEDULING);
EXPECT_EQ(_POSIX_VERSION, _POSIX_RAW_SOCKETS);
EXPECT_EQ(_POSIX_VERSION, _POSIX_READER_WRITER_LOCKS);
EXPECT_EQ(_POSIX_VERSION, _POSIX_REALTIME_SIGNALS);
EXPECT_GT(_POSIX_REGEXP, 0);
- EXPECT_GT(_POSIX_RE_DUP_MAX, 0);
EXPECT_GT(_POSIX_SAVED_IDS, 0);
EXPECT_EQ(_POSIX_VERSION, _POSIX_SEMAPHORES);
- EXPECT_GT(_POSIX_SEM_NSEMS_MAX, 0);
- EXPECT_GT(_POSIX_SEM_VALUE_MAX, 0);
EXPECT_GT(_POSIX_SHELL, 0);
- EXPECT_GT(_POSIX_SIGQUEUE_MAX, 0);
EXPECT_EQ(_POSIX_VERSION, _POSIX_SPAWN);
- EXPECT_EQ(_POSIX_VERSION, _POSIX_SPORADIC_SERVER);
- EXPECT_GT(_POSIX_SSIZE_MAX, 0);
- EXPECT_GT(_POSIX_STREAM_MAX, 0);
- EXPECT_GT(_POSIX_SYMLINK_MAX, 0);
- EXPECT_GT(_POSIX_SYMLOOP_MAX, 0);
+ EXPECT_EQ(-1, _POSIX_SPORADIC_SERVER);
EXPECT_EQ(_POSIX_VERSION, _POSIX_SYNCHRONIZED_IO);
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREADS);
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_ATTR_STACKADDR);
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_ATTR_STACKSIZE);
+#if !defined(__GLIBC__) // glibc supports ancient kernels.
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_CPUTIME);
- EXPECT_GT(_POSIX_THREAD_DESTRUCTOR_ITERATIONS, 0);
- EXPECT_EQ(_POSIX_THREAD_KEYS_MAX, 128);
+#endif
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PRIORITY_SCHEDULING);
- EXPECT_EQ(-1, _POSIX_THREAD_PRIO_INHERIT);
- EXPECT_EQ(-1, _POSIX_THREAD_PRIO_PROTECT);
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PROCESS_SHARED);
EXPECT_EQ(-1, _POSIX_THREAD_ROBUST_PRIO_PROTECT);
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_SAFE_FUNCTIONS);
- EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_SPORADIC_SERVER);
- EXPECT_GT(_POSIX_THREAD_THREADS_MAX, 0);
+ EXPECT_EQ(-1, _POSIX_THREAD_SPORADIC_SERVER);
EXPECT_EQ(_POSIX_VERSION, _POSIX_TIMEOUTS);
EXPECT_EQ(_POSIX_VERSION, _POSIX_TIMERS);
- EXPECT_GT(_POSIX_TIMER_MAX, 0);
EXPECT_EQ(-1, _POSIX_TRACE);
EXPECT_EQ(-1, _POSIX_TRACE_EVENT_FILTER);
EXPECT_EQ(-1, _POSIX_TRACE_INHERIT);
EXPECT_EQ(-1, _POSIX_TRACE_LOG);
- EXPECT_GT(_POSIX_TTY_NAME_MAX, 0);
EXPECT_EQ(-1, _POSIX_TYPED_MEMORY_OBJECTS);
- EXPECT_GT(_POSIX_TZNAME_MAX, 0);
EXPECT_NE(-1, _POSIX_VDISABLE);
EXPECT_EQ(_POSIX_VERSION, _POSIX2_VERSION);
- EXPECT_GT(_POSIX2_BC_BASE_MAX, 0);
- EXPECT_GT(_POSIX2_BC_DIM_MAX, 0);
- EXPECT_GT(_POSIX2_BC_SCALE_MAX, 0);
- EXPECT_GT(_POSIX2_BC_STRING_MAX, 0);
- EXPECT_GT(_POSIX2_CHARCLASS_NAME_MAX, 0);
- EXPECT_GT(_POSIX2_COLL_WEIGHTS_MAX, 0);
EXPECT_EQ(_POSIX_VERSION, _POSIX2_C_BIND);
- EXPECT_GT(_POSIX2_EXPR_NEST_MAX, 0);
- EXPECT_GT(_POSIX2_LINE_MAX, 0);
- EXPECT_GT(_POSIX2_RE_DUP_MAX, 0);
+ EXPECT_EQ(_POSIX_VERSION, _POSIX2_CHAR_TERM);
EXPECT_EQ(700, _XOPEN_VERSION);
- EXPECT_GT(_XOPEN_IOV_MAX, 0);
- EXPECT_GT(_XOPEN_UNIX, 0);
+ EXPECT_EQ(1, _XOPEN_ENH_I18N);
+ EXPECT_EQ(1, _XOPEN_REALTIME);
+ EXPECT_EQ(1, _XOPEN_REALTIME_THREADS);
+ EXPECT_EQ(1, _XOPEN_SHM);
+ EXPECT_EQ(1, _XOPEN_UNIX);
#if defined(__BIONIC__)
// These tests only pass on bionic, as bionic and glibc has different support on these macros.
@@ -792,21 +819,20 @@
EXPECT_EQ(-1, _POSIX_MESSAGE_PASSING);
EXPECT_EQ(-1, _POSIX_PRIORITIZED_IO);
EXPECT_EQ(-1, _POSIX_SHARED_MEMORY_OBJECTS);
+ EXPECT_EQ(-1, _POSIX_THREAD_PRIO_INHERIT);
+ EXPECT_EQ(-1, _POSIX_THREAD_PRIO_PROTECT);
EXPECT_EQ(-1, _POSIX_THREAD_ROBUST_PRIO_INHERIT);
- EXPECT_EQ(-1, _POSIX2_CHAR_TERM);
EXPECT_EQ(-1, _POSIX2_C_DEV);
+ EXPECT_EQ(-1, _POSIX2_FORT_DEV);
+ EXPECT_EQ(-1, _POSIX2_FORT_RUN);
EXPECT_EQ(-1, _POSIX2_LOCALEDEF);
EXPECT_EQ(-1, _POSIX2_SW_DEV);
EXPECT_EQ(-1, _POSIX2_UPE);
- EXPECT_EQ(-1, _XOPEN_ENH_I18N);
EXPECT_EQ(-1, _XOPEN_CRYPT);
EXPECT_EQ(-1, _XOPEN_LEGACY);
- EXPECT_EQ(-1, _XOPEN_REALTIME);
- EXPECT_EQ(-1, _XOPEN_REALTIME_THREADS);
- EXPECT_EQ(-1, _XOPEN_SHM);
-
+ EXPECT_EQ(-1, _XOPEN_STREAMS);
#endif // defined(__BIONIC__)
}
@@ -916,11 +942,11 @@
VERIFY_SYSCONF_POSITIVE(_SC_REGEXP);
VERIFY_SYSCONF_POSITIVE(_SC_SHELL);
VERIFY_SYSCONF_POSIX_VERSION(_SC_SPAWN);
- VERIFY_SYSCONF_POSIX_VERSION(_SC_SPORADIC_SERVER);
+ VERIFY_SYSCONF_UNSUPPORTED(_SC_SPORADIC_SERVER);
VERIFY_SYSCONF_POSITIVE(_SC_SYMLOOP_MAX);
VERIFY_SYSCONF_POSIX_VERSION(_SC_THREAD_CPUTIME);
VERIFY_SYSCONF_POSIX_VERSION(_SC_THREAD_PROCESS_SHARED);
- VERIFY_SYSCONF_POSIX_VERSION(_SC_THREAD_SPORADIC_SERVER);
+ VERIFY_SYSCONF_UNSUPPORTED(_SC_THREAD_SPORADIC_SERVER);
VERIFY_SYSCONF_POSIX_VERSION(_SC_TIMEOUTS);
VERIFY_SYSCONF_UNSUPPORTED(_SC_TRACE);
VERIFY_SYSCONF_UNSUPPORTED(_SC_TRACE_EVENT_FILTER);
@@ -1376,6 +1402,41 @@
"<unknown>: usage: run-as");
}
+TEST(UNISTD_TEST, fexecve_failure) {
+ ExecTestHelper eth;
+ errno = 0;
+ int fd = open("/", O_RDONLY);
+ ASSERT_NE(-1, fd);
+ ASSERT_EQ(-1, fexecve(fd, eth.GetArgs(), eth.GetEnv()));
+ ASSERT_EQ(EACCES, errno);
+ close(fd);
+}
+
+TEST(UNISTD_TEST, fexecve_bad_fd) {
+ ExecTestHelper eth;
+ errno = 0;
+ ASSERT_EQ(-1, fexecve(-1, eth.GetArgs(), eth.GetEnv()));
+ ASSERT_EQ(EBADF, errno);
+}
+
+TEST(UNISTD_TEST, fexecve_args) {
+ // Test basic argument passing.
+ int echo_fd = open(BIN_DIR "echo", O_RDONLY | O_CLOEXEC);
+ ASSERT_NE(-1, echo_fd);
+ ExecTestHelper eth;
+ eth.SetArgs({"echo", "hello", "world", nullptr});
+ eth.Run([&]() { fexecve(echo_fd, eth.GetArgs(), eth.GetEnv()); }, 0, "hello world\n");
+ close(echo_fd);
+
+ // Test environment variable setting too.
+ int printenv_fd = open(BIN_DIR "printenv", O_RDONLY | O_CLOEXEC);
+ ASSERT_NE(-1, printenv_fd);
+ eth.SetArgs({"printenv", nullptr});
+ eth.SetEnv({"A=B", nullptr});
+ eth.Run([&]() { fexecve(printenv_fd, eth.GetArgs(), eth.GetEnv()); }, 0, "A=B\n");
+ close(printenv_fd);
+}
+
TEST(UNISTD_TEST, getlogin_r) {
char buf[LOGIN_NAME_MAX] = {};
EXPECT_EQ(ERANGE, getlogin_r(buf, 0));