Fix sysconf(_SC_ARG_MAX).
ARG_MAX hasn't been a constant since Linux 2.6.23.
Bug: http://lists.landley.net/pipermail/toybox-landley.net/2016-August/008592.html
Change-Id: I1eddb562751604c75b89fa610d79be0655c53693
Test: ran the bionic tests on device and against glibc
diff --git a/libc/bionic/sysconf.cpp b/libc/bionic/sysconf.cpp
index 7be0ab7..4a23fec 100644
--- a/libc/bionic/sysconf.cpp
+++ b/libc/bionic/sysconf.cpp
@@ -29,10 +29,10 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
-#include <linux/uio.h> // For UIO_MAXIOV.
#include <pthread.h>
#include <stdio.h> // For FOPEN_MAX.
#include <sys/auxv.h>
+#include <sys/param.h>
#include <sys/resource.h>
#include <sys/sysinfo.h>
#include <time.h>
@@ -48,18 +48,39 @@
long sysconf(int name) {
switch (name) {
- case _SC_ARG_MAX: return ARG_MAX;
+ //
+ // Things we actually have to calculate...
+ //
+ case _SC_ARG_MAX:
+ // Not a constant since Linux 2.6.23; see fs/exec.c for details.
+ // At least 32 pages, otherwise a quarter of the stack limit.
+ return MAX(__sysconf_rlimit(RLIMIT_STACK) / 4, _KERNEL_ARG_MAX);
+
+ case _SC_AVPHYS_PAGES: return get_avphys_pages();
+ case _SC_CHILD_MAX: return __sysconf_rlimit(RLIMIT_NPROC);
+ case _SC_CLK_TCK: return static_cast<long>(getauxval(AT_CLKTCK));
+ case _SC_NPROCESSORS_CONF: return get_nprocs_conf();
+ case _SC_NPROCESSORS_ONLN: return get_nprocs();
+ case _SC_OPEN_MAX: return __sysconf_rlimit(RLIMIT_NOFILE);
+
+ case _SC_PAGESIZE:
+ case _SC_PAGE_SIZE:
+ // _SC_PAGESIZE and _SC_PAGE_SIZE are distinct, but return the same value.
+ return static_cast<long>(getauxval(AT_PAGESZ));
+
+ case _SC_PHYS_PAGES: return get_phys_pages();
+
+ //
+ // Constants...
+ //
case _SC_BC_BASE_MAX: return _POSIX2_BC_BASE_MAX; // Minimum requirement.
case _SC_BC_DIM_MAX: return _POSIX2_BC_DIM_MAX; // Minimum requirement.
case _SC_BC_SCALE_MAX: return _POSIX2_BC_SCALE_MAX; // Minimum requirement.
case _SC_BC_STRING_MAX: return _POSIX2_BC_STRING_MAX; // Minimum requirement.
- case _SC_CHILD_MAX: return __sysconf_rlimit(RLIMIT_NPROC);
- case _SC_CLK_TCK: return static_cast<long>(getauxval(AT_CLKTCK));
case _SC_COLL_WEIGHTS_MAX: return _POSIX2_COLL_WEIGHTS_MAX; // Minimum requirement.
case _SC_EXPR_NEST_MAX: return _POSIX2_EXPR_NEST_MAX; // Minimum requirement.
case _SC_LINE_MAX: return _POSIX2_LINE_MAX; // Minimum requirement.
case _SC_NGROUPS_MAX: return NGROUPS_MAX;
- case _SC_OPEN_MAX: return __sysconf_rlimit(RLIMIT_NOFILE);
case _SC_PASS_MAX: return PASS_MAX;
case _SC_2_C_BIND: return _POSIX2_C_BIND;
case _SC_2_C_DEV: return _POSIX2_C_DEV;
@@ -84,12 +105,7 @@
case _SC_XOPEN_REALTIME_THREADS: return _XOPEN_REALTIME_THREADS;
case _SC_XOPEN_LEGACY: return _XOPEN_LEGACY;
case _SC_ATEXIT_MAX: return LONG_MAX; // Unlimited.
- case _SC_IOV_MAX: return UIO_MAXIOV;
-
- // _SC_PAGESIZE and _SC_PAGE_SIZE are distinct, but return the same value.
- case _SC_PAGESIZE:
- case _SC_PAGE_SIZE:
- return static_cast<long>(getauxval(AT_PAGESZ));
+ case _SC_IOV_MAX: return IOV_MAX;
case _SC_XOPEN_UNIX: return _XOPEN_UNIX;
case _SC_AIO_LISTIO_MAX: return _POSIX_AIO_LISTIO_MAX; // Minimum requirement.
@@ -132,10 +148,6 @@
case _SC_THREAD_PRIO_INHERIT: return _POSIX_THREAD_PRIO_INHERIT;
case _SC_THREAD_PRIO_PROTECT: return _POSIX_THREAD_PRIO_PROTECT;
case _SC_THREAD_SAFE_FUNCTIONS: return _POSIX_THREAD_SAFE_FUNCTIONS;
- case _SC_NPROCESSORS_CONF: return get_nprocs_conf();
- case _SC_NPROCESSORS_ONLN: return get_nprocs();
- case _SC_PHYS_PAGES: return get_phys_pages();
- case _SC_AVPHYS_PAGES: return get_avphys_pages();
case _SC_MONOTONIC_CLOCK: return _POSIX_VERSION;
case _SC_2_PBS: return -1; // Obsolescent in POSIX.1-2008.