Merge "Coverage configs for bionic."
diff --git a/libc/Android.mk b/libc/Android.mk
index d0c51e4..0dc6c3b 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -51,11 +51,9 @@
bionic/ioctl.c \
bionic/isatty.c \
bionic/memmem.c \
- bionic/pathconf.c \
bionic/pututline.c \
bionic/sched_cpualloc.c \
bionic/sched_cpucount.c \
- bionic/semaphore.c \
bionic/sigblock.c \
bionic/siginterrupt.c \
bionic/sigsetmask.c \
@@ -145,6 +143,7 @@
bionic/mntent.cpp \
bionic/NetdClientDispatch.cpp \
bionic/open.cpp \
+ bionic/pathconf.cpp \
bionic/pause.cpp \
bionic/pipe.cpp \
bionic/poll.cpp \
@@ -184,6 +183,7 @@
bionic/scandir.cpp \
bionic/sched_getaffinity.cpp \
bionic/sched_getcpu.cpp \
+ bionic/semaphore.cpp \
bionic/send.cpp \
bionic/setegid.cpp \
bionic/__set_errno.cpp \
@@ -243,7 +243,6 @@
upstream-freebsd/lib/libc/gen/sleep.c \
upstream-freebsd/lib/libc/gen/usleep.c \
upstream-freebsd/lib/libc/stdio/fclose.c \
- upstream-freebsd/lib/libc/stdio/flags.c \
upstream-freebsd/lib/libc/stdio/fopen.c \
upstream-freebsd/lib/libc/stdlib/abs.c \
upstream-freebsd/lib/libc/stdlib/getopt_long.c \
@@ -290,7 +289,6 @@
upstream-netbsd/lib/libc/stdlib/div.c \
upstream-netbsd/lib/libc/stdlib/drand48.c \
upstream-netbsd/lib/libc/stdlib/erand48.c \
- upstream-netbsd/lib/libc/stdlib/insque.c \
upstream-netbsd/lib/libc/stdlib/jrand48.c \
upstream-netbsd/lib/libc/stdlib/ldiv.c \
upstream-netbsd/lib/libc/stdlib/lldiv.c \
@@ -299,14 +297,12 @@
upstream-netbsd/lib/libc/stdlib/nrand48.c \
upstream-netbsd/lib/libc/stdlib/_rand48.c \
upstream-netbsd/lib/libc/stdlib/rand_r.c \
- upstream-netbsd/lib/libc/stdlib/remque.c \
upstream-netbsd/lib/libc/stdlib/seed48.c \
upstream-netbsd/lib/libc/stdlib/srand48.c \
upstream-netbsd/lib/libc/string/memccpy.c \
upstream-netbsd/lib/libc/string/strcasestr.c \
upstream-netbsd/lib/libc/string/strcoll.c \
upstream-netbsd/lib/libc/string/strxfrm.c \
- upstream-netbsd/lib/libc/unistd/killpg.c \
libc_upstream_openbsd_gdtoa_src_files := \
upstream-openbsd/android/gdtoa_support.cpp \
@@ -336,6 +332,7 @@
upstream-openbsd/lib/libc/gdtoa/strtorQ.c \
libc_upstream_openbsd_src_files := \
+ upstream-openbsd/lib/libc/compat-43/killpg.c \
upstream-openbsd/lib/libc/crypt/arc4random.c \
upstream-openbsd/lib/libc/crypt/arc4random_uniform.c \
upstream-openbsd/lib/libc/gen/alarm.c \
@@ -403,6 +400,7 @@
upstream-openbsd/lib/libc/stdio/fgetws.c \
upstream-openbsd/lib/libc/stdio/fileno.c \
upstream-openbsd/lib/libc/stdio/findfp.c \
+ upstream-openbsd/lib/libc/stdio/flags.c \
upstream-openbsd/lib/libc/stdio/fmemopen.c \
upstream-openbsd/lib/libc/stdio/fprintf.c \
upstream-openbsd/lib/libc/stdio/fpurge.c \
@@ -482,7 +480,9 @@
upstream-openbsd/lib/libc/stdlib/atoll.c \
upstream-openbsd/lib/libc/stdlib/exit.c \
upstream-openbsd/lib/libc/stdlib/getenv.c \
+ upstream-openbsd/lib/libc/stdlib/insque.c \
upstream-openbsd/lib/libc/stdlib/lsearch.c \
+ upstream-openbsd/lib/libc/stdlib/remque.c \
upstream-openbsd/lib/libc/stdlib/setenv.c \
upstream-openbsd/lib/libc/stdlib/strtoimax.c \
upstream-openbsd/lib/libc/stdlib/strtol.c \
@@ -1138,10 +1138,7 @@
# ========================================================
include $(CLEAR_VARS)
-LOCAL_CFLAGS := \
- $(libc_common_cflags) \
- -DMALLOC_LEAK_CHECK \
-
+LOCAL_CFLAGS := $(libc_common_cflags)
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
LOCAL_CPPFLAGS := $(libc_common_cppflags)
diff --git a/libc/arch-arm64/arm64.mk b/libc/arch-arm64/arm64.mk
index 0dd3c27..cdb2777 100644
--- a/libc/arch-arm64/arm64.mk
+++ b/libc/arch-arm64/arm64.mk
@@ -59,7 +59,7 @@
endif
cpu_variant_mk := $(LOCAL_PATH)/arch-arm64/$(TARGET_CPU_VARIANT)/$(TARGET_CPU_VARIANT).mk
ifeq ($(wildcard $(cpu_variant_mk)),)
-$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are generic, generic-neon, denver64. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
+$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are generic, denver64. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
endif
include $(cpu_variant_mk)
libc_common_additional_dependencies += $(cpu_variank_mk)
diff --git a/libc/arch-arm64/generic-neon/bionic/memcpy.S b/libc/arch-arm64/generic-neon/bionic/memcpy.S
deleted file mode 100644
index 320f748..0000000
--- a/libc/arch-arm64/generic-neon/bionic/memcpy.S
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Copyright (c) 2012, Linaro Limited
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- * Neither the name of the Linaro nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* Assumptions:
- *
- * ARMv8-a, AArch64
- * Unaligned accesses
- *
- */
-
-#include <private/bionic_asm.h>
-
-#define dstin x0
-#define src x1
-#define count x2
-#define tmp1 x3
-#define tmp1w w3
-#define tmp2 x4
-#define tmp2w w4
-#define tmp3 x5
-#define tmp3w w5
-#define dst x6
-
-#define A_l x7
-#define A_h x8
-#define B_l x9
-#define B_h x10
-#define C_l x11
-#define C_h x12
-#define D_l x13
-#define D_h x14
-
-#define QA_l q0
-#define QA_h q1
-#define QB_l q2
-#define QB_h q3
-
-ENTRY(memcpy)
-
- mov dst, dstin
- cmp count, #64
- b.ge .Lcpy_not_short
- cmp count, #15
- b.le .Ltail15tiny
-
- /* Deal with small copies quickly by dropping straight into the
- * exit block. */
-.Ltail63:
- /* Copy up to 48 bytes of data. At this point we only need the
- * bottom 6 bits of count to be accurate. */
- ands tmp1, count, #0x30
- b.eq .Ltail15
- add dst, dst, tmp1
- add src, src, tmp1
- cmp tmp1w, #0x20
- b.eq 1f
- b.lt 2f
- ldp A_l, A_h, [src, #-48]
- stp A_l, A_h, [dst, #-48]
-1:
- ldp A_l, A_h, [src, #-32]
- stp A_l, A_h, [dst, #-32]
-2:
- ldp A_l, A_h, [src, #-16]
- stp A_l, A_h, [dst, #-16]
-
-.Ltail15:
- ands count, count, #15
- beq 1f
- add src, src, count
- ldp A_l, A_h, [src, #-16]
- add dst, dst, count
- stp A_l, A_h, [dst, #-16]
-1:
- ret
-
-.Ltail15tiny:
- /* Copy up to 15 bytes of data. Does not assume additional data
- being copied. */
- tbz count, #3, 1f
- ldr tmp1, [src], #8
- str tmp1, [dst], #8
-1:
- tbz count, #2, 1f
- ldr tmp1w, [src], #4
- str tmp1w, [dst], #4
-1:
- tbz count, #1, 1f
- ldrh tmp1w, [src], #2
- strh tmp1w, [dst], #2
-1:
- tbz count, #0, 1f
- ldrb tmp1w, [src]
- strb tmp1w, [dst]
-1:
- ret
-
-.Lcpy_not_short:
- /* We don't much care about the alignment of DST, but we want SRC
- * to be 128-bit (16 byte) aligned so that we don't cross cache line
- * boundaries on both loads and stores. */
- neg tmp2, src
- ands tmp2, tmp2, #15 /* Bytes to reach alignment. */
- b.eq 2f
- sub count, count, tmp2
- /* Copy more data than needed; it's faster than jumping
- * around copying sub-Quadword quantities. We know that
- * it can't overrun. */
- ldp A_l, A_h, [src]
- add src, src, tmp2
- stp A_l, A_h, [dst]
- add dst, dst, tmp2
- /* There may be less than 63 bytes to go now. */
- cmp count, #63
- b.le .Ltail63
-2:
- subs count, count, #128
- b.ge .Lcpy_body_large
- /* Less than 128 bytes to copy, so handle 64 here and then jump
- * to the tail. */
- ldp QA_l, QA_h, [src]
- ldp QB_l, QB_h, [src, #32]
- stp QA_l, QA_h, [dst]
- stp QB_l, QB_h, [dst, #32]
- tst count, #0x3f
- add src, src, #64
- add dst, dst, #64
- b.ne .Ltail63
- ret
-
- /* Critical loop. Start at a new cache line boundary. Assuming
- * 64 bytes per line this ensures the entire loop is in one line. */
- .p2align 6
-.Lcpy_body_large:
- /* There are at least 128 bytes to copy. */
- ldp QA_l, QA_h, [src, #0]
- sub dst, dst, #32 /* Pre-bias. */
- ldp QB_l, QB_h, [src, #32]! /* src += 64 - Pre-bias. */
-1:
- stp QA_l, QA_h, [dst, #32]
- ldp QA_l, QA_h, [src, #32]
- stp QB_l, QB_h, [dst, #64]!
- ldp QB_l, QB_h, [src, #64]!
-
- subs count, count, #64
- b.ge 1b
-
- stp QA_l, QA_h, [dst, #32]
- stp QB_l, QB_h, [dst, #64]
- add src, src, #32
- add dst, dst, #64 + 32
- tst count, #0x3f
- b.ne .Ltail63
- ret
-END(memcpy)
diff --git a/libc/arch-arm64/generic-neon/generic-neon.mk b/libc/arch-arm64/generic-neon/generic-neon.mk
deleted file mode 100644
index 77e3861..0000000
--- a/libc/arch-arm64/generic-neon/generic-neon.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-libc_bionic_src_files_arm64 += \
- arch-arm64/generic/bionic/memchr.S \
- arch-arm64/generic/bionic/memcmp.S \
- arch-arm64/generic/bionic/memmove.S \
- arch-arm64/generic/bionic/memset.S \
- arch-arm64/generic/bionic/stpcpy.S \
- arch-arm64/generic/bionic/strchr.S \
- arch-arm64/generic/bionic/strcmp.S \
- arch-arm64/generic/bionic/strcpy.S \
- arch-arm64/generic/bionic/strlen.S \
- arch-arm64/generic/bionic/strncmp.S \
- arch-arm64/generic/bionic/strnlen.S \
- arch-arm64/generic-neon/bionic/memcpy.S \
diff --git a/libc/bionic/bionic_time_conversions.cpp b/libc/bionic/bionic_time_conversions.cpp
index 7f3c026..75e8d49 100644
--- a/libc/bionic/bionic_time_conversions.cpp
+++ b/libc/bionic/bionic_time_conversions.cpp
@@ -28,6 +28,8 @@
#include "private/bionic_time_conversions.h"
+#include "private/bionic_constants.h"
+
bool timespec_from_timeval(timespec& ts, const timeval& tv) {
// Whole seconds can just be copied.
ts.tv_sec = tv.tv_sec;
@@ -49,3 +51,19 @@
tv.tv_sec = ts.tv_sec;
tv.tv_usec = ts.tv_nsec / 1000;
}
+
+// Initializes 'ts' with the difference between 'abs_ts' and the current time
+// according to 'clock'. Returns false if abstime already expired, true otherwise.
+bool timespec_from_absolute_timespec(timespec& ts, const timespec& abs_ts, clockid_t clock) {
+ clock_gettime(clock, &ts);
+ ts.tv_sec = abs_ts.tv_sec - ts.tv_sec;
+ ts.tv_nsec = abs_ts.tv_nsec - ts.tv_nsec;
+ if (ts.tv_nsec < 0) {
+ ts.tv_sec--;
+ ts.tv_nsec += NS_PER_S;
+ }
+ if (ts.tv_nsec < 0 || ts.tv_sec < 0) {
+ return false;
+ }
+ return true;
+}
diff --git a/libc/bionic/lfs64_support.cpp b/libc/bionic/lfs64_support.cpp
index ab795f5..45d4f7f 100644
--- a/libc/bionic/lfs64_support.cpp
+++ b/libc/bionic/lfs64_support.cpp
@@ -17,11 +17,20 @@
#include <ftw.h>
#include <stdlib.h>
-int mkstemp64(char* filename) {
- // Delegation will work in this case because all the transitive dependencies
- // are already 64-bit ready. In particular, we don't have non-O_LARGEFILE
- // open (our open is actually open64) and stat and stat64 are the same.
- return mkstemp(filename);
+// Delegation will work in these cases because all the transitive dependencies
+// are already 64-bit ready. In particular, we don't have non-O_LARGEFILE
+// open (our open is actually open64) and stat and stat64 are the same.
+int mkstemp64(char* path) {
+ return mkstemp(path);
+}
+int mkostemp64(char* path, int flags) {
+ return mkostemp(path, flags);
+}
+int mkstemps64(char* path, int suffix_length) {
+ return mkstemps(path, suffix_length);
+}
+int mkostemps64(char* path, int suffix_length, int flags) {
+ return mkostemps(path, suffix_length, flags);
}
typedef int (*ftw_fn)(const char*, const struct stat*, int);
diff --git a/libc/bionic/malloc_debug_common.cpp b/libc/bionic/malloc_debug_common.cpp
index 0b6a142..38c6583 100644
--- a/libc/bionic/malloc_debug_common.cpp
+++ b/libc/bionic/malloc_debug_common.cpp
@@ -29,14 +29,13 @@
// Contains definition of structures, global variables, and implementation of
// routines that are used by malloc leak detection code and other components in
// the system. The trick is that some components expect these data and
-// routines to be defined / implemented in libc.so library, regardless
-// whether or not MALLOC_LEAK_CHECK macro is defined. To make things even
-// more tricky, malloc leak detection code, implemented in
-// libc_malloc_debug.so also requires access to these variables and routines
-// (to fill allocation entry hash table, for example). So, all relevant
-// variables and routines are defined / implemented here and exported
-// to all, leak detection code and other components via dynamic (libc.so),
-// or static (libc.a) linking.
+// routines to be defined / implemented in libc.so, regardless whether or not
+// malloc leak detection code is going to run. To make things even more tricky,
+// malloc leak detection code, implemented in libc_malloc_debug.so also
+// requires access to these variables and routines (to fill allocation entry
+// hash table, for example). So, all relevant variables and routines are
+// defined / implemented here and exported to all, leak detection code and
+// other components via dynamic (libc.so), or static (libc.a) linking.
#include "malloc_debug_common.h"
diff --git a/libc/bionic/malloc_debug_leak.cpp b/libc/bionic/malloc_debug_leak.cpp
index df0f997..64f2112 100644
--- a/libc/bionic/malloc_debug_leak.cpp
+++ b/libc/bionic/malloc_debug_leak.cpp
@@ -55,13 +55,6 @@
#include "private/libc_logging.h"
#include "private/ScopedPthreadMutexLocker.h"
-// This file should be included into the build only when
-// MALLOC_LEAK_CHECK, or MALLOC_QEMU_INSTRUMENT, or both
-// macros are defined.
-#ifndef MALLOC_LEAK_CHECK
-#error MALLOC_LEAK_CHECK is not defined.
-#endif // !MALLOC_LEAK_CHECK
-
extern int gMallocLeakZygoteChild;
extern HashTable* g_hash_table;
extern const MallocDebug* g_malloc_dispatch;
diff --git a/libc/bionic/pathconf.c b/libc/bionic/pathconf.c
deleted file mode 100644
index cf81272..0000000
--- a/libc/bionic/pathconf.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <pathconf.h>
-#include <sys/vfs.h>
-#include <sys/limits.h>
-#include <errno.h>
-
-/* these may not be defined yet by our headers */
-#ifndef _POSIX_VDISABLE
-#define _POSIX_VDISABLE -1
-#endif
-
-#ifndef _POSIX_SYNC_IO
-#define _POSIX_SYNC_IO -1
-#endif
-
-#ifndef _POSIX_PRIO_IO
-#define _POSIX_PRIO_IO -1
-#endif
-
-#ifndef _POSIX_ASYNC_IO
-#define _POSIX_ASYNC_IO -1
-#endif
-
-
-static long
-__filesizebits( struct statfs* s )
-{
-#define EOL_MAGIC 0x0000U
-
- /* list of known 64-bit aware filesystems */
- static const uint32_t known64[] = {
- EXT2_SUPER_MAGIC,
- UFS_MAGIC,
- REISERFS_SUPER_MAGIC,
- XFS_SUPER_MAGIC,
- SMB_SUPER_MAGIC,
- UDF_SUPER_MAGIC,
- JFS_SUPER_MAGIC,
- NTFS_SB_MAGIC,
- VXFS_SUPER_MAGIC,
- EOL_MAGIC
- };
- int nn = 0;
-
- for (; known64[nn] != EOL_MAGIC; ++nn) {
- if (known64[nn] == s->f_type) {
- return 64;
- }
- }
- return 32;
-}
-
-
-static long
-__link_max( struct statfs* s )
-{
- // These constant values were taken from kernel headers.
- // They're not available in uapi headers.
- static const struct { uint32_t type; int max; } knownMax[] =
- {
- { EXT2_SUPER_MAGIC, 32000 },
- { EXT3_SUPER_MAGIC, 32000 },
- { MINIX_SUPER_MAGIC, 250 },
- { MINIX2_SUPER_MAGIC, 65530 },
- { REISERFS_SUPER_MAGIC, 0xffff - 1000 },
- { UFS_MAGIC, 32000 },
- { EOL_MAGIC, 0 }
- };
- int nn = 0;
-
- for (; knownMax[nn].type != EOL_MAGIC; ++nn) {
- if (knownMax[nn].type == s->f_type) {
- return knownMax[nn].max;
- }
- }
- return LINK_MAX;
-}
-
-static long
-__2_symlinks( struct statfs* s )
-{
- /* list of know filesystems that don't support symlinks */
- static const uint32_t knownNoSymlinks[] = {
- ADFS_SUPER_MAGIC, BFS_MAGIC, CRAMFS_MAGIC,
- EFS_SUPER_MAGIC, MSDOS_SUPER_MAGIC, NTFS_SB_MAGIC,
- QNX4_SUPER_MAGIC,
- EOL_MAGIC
- };
- int nn = 0;
-
- for (; knownNoSymlinks[nn] != EOL_MAGIC; ++nn) {
- if (knownNoSymlinks[nn] == s->f_type) {
- return 0;
- }
- }
- return 1;
-}
-
-static long
-__name_max( struct statfs* s )
-{
- return s->f_namelen;
-}
-
-long
-pathconf(const char *path, int name)
-{
- struct statfs buf;
- int ret = statfs( path, &buf );
-
- if (ret < 0)
- return -1;
-
- switch (name) {
- case _PC_FILESIZEBITS:
- return __filesizebits(&buf);
-
- case _PC_LINK_MAX:
- return __link_max(&buf);
-
- case _PC_MAX_CANON:
- return MAX_CANON;
-
- case _PC_MAX_INPUT:
- return MAX_INPUT;
-
- case _PC_NAME_MAX:
- return __name_max(&buf);
-
- case _PC_PATH_MAX:
- return PATH_MAX;
-
- case _PC_PIPE_BUF:
- return PIPE_BUF;
-
- case _PC_2_SYMLINKS:
- return __2_symlinks(&buf);
-
-#if 0 /* don't know what to do there, the specs are really weird */
- case _PC_ALLOC_SIZE_MIN:
- case _PC_REC_INCR_XFER_SIZE:
- case _PC_REC_MAX_XFER_SIZE:
- case _PC_REC_MIN_XFER_SIZE:
- case _PC_REC_XFER_ALIGN:
-#endif
-
- case _PC_SYMLINK_MAX:
- return -1; /* no limit */
-
- case _PC_CHOWN_RESTRICTED:
- return _POSIX_CHOWN_RESTRICTED;
-
- case _PC_NO_TRUNC:
- return _POSIX_NO_TRUNC;
-
- case _PC_VDISABLE:
- return _POSIX_VDISABLE;
-
- case _PC_ASYNC_IO:
- return _POSIX_ASYNC_IO;
-
- case _PC_PRIO_IO:
- return _POSIX_PRIO_IO;
-
- case _PC_SYNC_IO:
- return _POSIX_SYNC_IO;
-
- default:
- errno = EINVAL;
- return -1;
- }
-}
-
-long fpathconf(int fildes, int name)
-{
- struct statfs buf;
- int ret = fstatfs(fildes, &buf);
-
- if (ret < 0)
- return -1;
-
- switch (name) {
- case _PC_FILESIZEBITS:
- return __filesizebits(&buf);
-
- case _PC_LINK_MAX:
- return __link_max(&buf);
-
- case _PC_MAX_CANON:
- return MAX_CANON;
-
- case _PC_MAX_INPUT:
- return MAX_INPUT;
-
- case _PC_NAME_MAX:
- return __name_max(&buf);
-
- case _PC_PATH_MAX:
- return PATH_MAX;
-
- case _PC_PIPE_BUF:
- return PIPE_BUF;
-
- case _PC_2_SYMLINKS:
- return __2_symlinks(&buf);
-
-#if 0 /* don't know what to do there, the specs are really weird */
- case _PC_ALLOC_SIZE_MIN:
- case _PC_REC_INCR_XFER_SIZE:
- case _PC_REC_MAX_XFER_SIZE:
- case _PC_REC_MIN_XFER_SIZE:
- case _PC_REC_XFER_ALIGN:
-#endif
-
- case _PC_SYMLINK_MAX:
- return -1; /* no limit */
-
- case _PC_CHOWN_RESTRICTED:
- return _POSIX_CHOWN_RESTRICTED;
-
- case _PC_NO_TRUNC:
- return _POSIX_NO_TRUNC;
-
- case _PC_VDISABLE:
- return _POSIX_VDISABLE;
-
- case _PC_ASYNC_IO:
- return _POSIX_ASYNC_IO;
-
- case _PC_PRIO_IO:
- return _POSIX_PRIO_IO;
-
- case _PC_SYNC_IO:
- return _POSIX_SYNC_IO;
-
- default:
- errno = EINVAL;
- return -1;
- }
-}
diff --git a/libc/bionic/pathconf.cpp b/libc/bionic/pathconf.cpp
new file mode 100644
index 0000000..de9e022
--- /dev/null
+++ b/libc/bionic/pathconf.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <unistd.h>
+
+#include <errno.h>
+#include <sys/limits.h>
+#include <sys/vfs.h>
+
+static long __filesizebits(const struct statfs& s) {
+ switch (s.f_type) {
+ case JFFS2_SUPER_MAGIC:
+ case MSDOS_SUPER_MAGIC:
+ case NCP_SUPER_MAGIC:
+ return 32;
+ }
+ // There won't be any new 32-bit file systems.
+ return 64;
+}
+
+static long __link_max(const struct statfs& s) {
+ // These constant values were taken from kernel headers.
+ // They're not available in uapi headers.
+ switch (s.f_type) {
+ case EXT2_SUPER_MAGIC:
+ return 32000;
+ case MINIX_SUPER_MAGIC:
+ return 250;
+ case MINIX2_SUPER_MAGIC:
+ return 65530;
+ case REISERFS_SUPER_MAGIC:
+ return 0xffff - 1000;
+ case UFS_MAGIC:
+ return 32000;
+ }
+ return LINK_MAX;
+}
+
+static long __2_symlinks(const struct statfs& s) {
+ switch (s.f_type) {
+ case ADFS_SUPER_MAGIC:
+ case BFS_MAGIC:
+ case CRAMFS_MAGIC:
+ case EFS_SUPER_MAGIC:
+ case MSDOS_SUPER_MAGIC:
+ case QNX4_SUPER_MAGIC:
+ return 0;
+ }
+ return 1;
+}
+
+static long __pathconf(const struct statfs& s, int name) {
+ switch (name) {
+ case _PC_FILESIZEBITS:
+ return __filesizebits(s);
+
+ case _PC_LINK_MAX:
+ return __link_max(s);
+
+ case _PC_MAX_CANON:
+ return MAX_CANON;
+
+ case _PC_MAX_INPUT:
+ return MAX_INPUT;
+
+ case _PC_NAME_MAX:
+ return s.f_namelen;
+
+ case _PC_PATH_MAX:
+ return PATH_MAX;
+
+ case _PC_PIPE_BUF:
+ return PIPE_BUF;
+
+ case _PC_2_SYMLINKS:
+ return __2_symlinks(s);
+
+#if 0
+ case _PC_ALLOC_SIZE_MIN:
+ case _PC_REC_INCR_XFER_SIZE:
+ case _PC_REC_MAX_XFER_SIZE:
+ case _PC_REC_MIN_XFER_SIZE:
+ case _PC_REC_XFER_ALIGN:
+#endif
+
+ case _PC_SYMLINK_MAX:
+ return -1; /* no limit */
+
+ case _PC_CHOWN_RESTRICTED:
+ return _POSIX_CHOWN_RESTRICTED;
+
+ case _PC_NO_TRUNC:
+ return _POSIX_NO_TRUNC;
+
+ case _PC_VDISABLE:
+ return _POSIX_VDISABLE;
+
+ case _PC_ASYNC_IO:
+ return -1;
+
+ case _PC_PRIO_IO:
+ return -1;
+
+ case _PC_SYNC_IO:
+ return -1;
+
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+}
+
+long pathconf(const char* path, int name) {
+ struct statfs sb;
+ if (statfs(path, &sb) == -1) {
+ return -1;
+ }
+ return __pathconf(sb, name);
+}
+
+long fpathconf(int fd, int name) {
+ struct statfs sb;
+ if (fstatfs(fd, &sb) == -1) {
+ return -1;
+ }
+ return __pathconf(sb, name);
+}
diff --git a/libc/bionic/pthread_cond.cpp b/libc/bionic/pthread_cond.cpp
index e623b62..32ff81a 100644
--- a/libc/bionic/pthread_cond.cpp
+++ b/libc/bionic/pthread_cond.cpp
@@ -163,12 +163,12 @@
}
__LIBC_HIDDEN__
-int __pthread_cond_timedwait(pthread_cond_t* cond, pthread_mutex_t* mutex, const timespec* abstime, clockid_t clock) {
+int __pthread_cond_timedwait(pthread_cond_t* cond, pthread_mutex_t* mutex, const timespec* abs_ts, clockid_t clock) {
timespec ts;
timespec* tsp;
- if (abstime != NULL) {
- if (__timespec_from_absolute(&ts, abstime, clock) < 0) {
+ if (abs_ts != NULL) {
+ if (!timespec_from_absolute_timespec(ts, *abs_ts, clock)) {
return ETIMEDOUT;
}
tsp = &ts;
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index a5b3002..392e781 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -117,8 +117,6 @@
__LIBC_HIDDEN__ extern pthread_internal_t* g_thread_list;
__LIBC_HIDDEN__ extern pthread_mutex_t g_thread_list_lock;
-__LIBC_HIDDEN__ int __timespec_from_absolute(timespec*, const timespec*, clockid_t);
-
/* Needed by fork. */
__LIBC_HIDDEN__ extern void __bionic_atfork_run_prepare();
__LIBC_HIDDEN__ extern void __bionic_atfork_run_child();
diff --git a/libc/bionic/pthread_internals.cpp b/libc/bionic/pthread_internals.cpp
index 4c08ba8..19c00d4 100644
--- a/libc/bionic/pthread_internals.cpp
+++ b/libc/bionic/pthread_internals.cpp
@@ -67,19 +67,3 @@
pthread_internal_t* __get_thread(void) {
return reinterpret_cast<pthread_internal_t*>(__get_tls()[TLS_SLOT_THREAD_ID]);
}
-
-// Initialize 'ts' with the difference between 'abstime' and the current time
-// according to 'clock'. Returns -1 if abstime already expired, or 0 otherwise.
-int __timespec_from_absolute(timespec* ts, const timespec* abstime, clockid_t clock) {
- clock_gettime(clock, ts);
- ts->tv_sec = abstime->tv_sec - ts->tv_sec;
- ts->tv_nsec = abstime->tv_nsec - ts->tv_nsec;
- if (ts->tv_nsec < 0) {
- ts->tv_sec--;
- ts->tv_nsec += 1000000000;
- }
- if ((ts->tv_nsec < 0) || (ts->tv_sec < 0)) {
- return -1;
- }
- return 0;
-}
diff --git a/libc/bionic/pthread_mutex.cpp b/libc/bionic/pthread_mutex.cpp
index e00ffb4..cbb6ef7 100644
--- a/libc/bionic/pthread_mutex.cpp
+++ b/libc/bionic/pthread_mutex.cpp
@@ -36,7 +36,9 @@
#include "pthread_internal.h"
#include "private/bionic_atomic_inline.h"
+#include "private/bionic_constants.h"
#include "private/bionic_futex.h"
+#include "private/bionic_time_conversions.h"
#include "private/bionic_tls.h"
#include "private/bionic_systrace.h"
@@ -615,7 +617,7 @@
return EBUSY;
}
-static int __pthread_mutex_timedlock(pthread_mutex_t* mutex, const timespec* abs_timeout, clockid_t clock) {
+static int __pthread_mutex_timedlock(pthread_mutex_t* mutex, const timespec* abs_ts, clockid_t clock) {
timespec ts;
int mvalue = mutex->value;
@@ -638,7 +640,7 @@
// Loop while needed.
while (__bionic_swap(locked_contended, &mutex->value) != unlocked) {
- if (__timespec_from_absolute(&ts, abs_timeout, clock) < 0) {
+ if (!timespec_from_absolute_timespec(ts, *abs_ts, clock)) {
return ETIMEDOUT;
}
__futex_wait_ex(&mutex->value, shared, locked_contended, &ts);
@@ -681,7 +683,7 @@
}
// The value changed before we could lock it. We need to check
// the time to avoid livelocks, reload the value, then loop again.
- if (__timespec_from_absolute(&ts, abs_timeout, clock) < 0) {
+ if (!timespec_from_absolute_timespec(ts, *abs_ts, clock)) {
return ETIMEDOUT;
}
@@ -703,7 +705,7 @@
}
// Check time and update 'ts'.
- if (__timespec_from_absolute(&ts, abs_timeout, clock) < 0) {
+ if (timespec_from_absolute_timespec(ts, *abs_ts, clock)) {
return ETIMEDOUT;
}
@@ -726,9 +728,9 @@
clock_gettime(CLOCK_MONOTONIC, &abs_timeout);
abs_timeout.tv_sec += ms / 1000;
abs_timeout.tv_nsec += (ms % 1000) * 1000000;
- if (abs_timeout.tv_nsec >= 1000000000) {
+ if (abs_timeout.tv_nsec >= NS_PER_S) {
abs_timeout.tv_sec++;
- abs_timeout.tv_nsec -= 1000000000;
+ abs_timeout.tv_nsec -= NS_PER_S;
}
int error = __pthread_mutex_timedlock(mutex, &abs_timeout, CLOCK_MONOTONIC);
diff --git a/libc/bionic/pthread_rwlock.cpp b/libc/bionic/pthread_rwlock.cpp
index 063137b..0d63457 100644
--- a/libc/bionic/pthread_rwlock.cpp
+++ b/libc/bionic/pthread_rwlock.cpp
@@ -30,6 +30,7 @@
#include "pthread_internal.h"
#include "private/bionic_futex.h"
+#include "private/bionic_time_conversions.h"
/* Technical note:
*
@@ -71,7 +72,7 @@
static bool timespec_from_absolute(timespec* rel_timeout, const timespec* abs_timeout) {
if (abs_timeout != NULL) {
- if (__timespec_from_absolute(rel_timeout, abs_timeout, CLOCK_REALTIME) < 0) {
+ if (!timespec_from_absolute_timespec(*rel_timeout, *abs_timeout, CLOCK_REALTIME)) {
return false;
}
}
diff --git a/libc/bionic/semaphore.c b/libc/bionic/semaphore.c
deleted file mode 100644
index 1fa019e..0000000
--- a/libc/bionic/semaphore.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <semaphore.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <time.h>
-#include <limits.h>
-
-#include "private/bionic_atomic_inline.h"
-#include "private/bionic_futex.h"
-
-/* In this implementation, a semaphore contains a
- * 31-bit signed value and a 1-bit 'shared' flag
- * (for process-sharing purpose).
- *
- * We use the value -1 to indicate contention on the
- * semaphore, 0 or more to indicate uncontended state,
- * any value lower than -2 is invalid at runtime.
- *
- * State diagram:
- *
- * post(1) ==> 2
- * post(0) ==> 1
- * post(-1) ==> 1, then wake all waiters
- *
- * wait(2) ==> 1
- * wait(1) ==> 0
- * wait(0) ==> -1 then wait for a wake up + loop
- * wait(-1) ==> -1 then wait for a wake up + loop
- *
- */
-
-/* Use the upper 31-bits for the counter, and the lower one
- * for the shared flag.
- */
-#define SEMCOUNT_SHARED_MASK 0x00000001
-#define SEMCOUNT_VALUE_MASK 0xfffffffe
-#define SEMCOUNT_VALUE_SHIFT 1
-
-/* Maximum unsigned value that can be stored in the semaphore.
- * One bit is used for the shared flag, another one for the
- * sign bit, leaving us with only 30 bits.
- */
-#define SEM_MAX_VALUE 0x3fffffff
-
-/* convert a value into the corresponding sem->count bit pattern */
-#define SEMCOUNT_FROM_VALUE(val) (((val) << SEMCOUNT_VALUE_SHIFT) & SEMCOUNT_VALUE_MASK)
-
-/* convert a sem->count bit pattern into the corresponding signed value */
-#define SEMCOUNT_TO_VALUE(sval) ((int)(sval) >> SEMCOUNT_VALUE_SHIFT)
-
-/* the value +1 as a sem->count bit-pattern. */
-#define SEMCOUNT_ONE SEMCOUNT_FROM_VALUE(1)
-
-/* the value -1 as a sem->count bit-pattern. */
-#define SEMCOUNT_MINUS_ONE SEMCOUNT_FROM_VALUE(-1)
-
-#define SEMCOUNT_DECREMENT(sval) (((sval) - (1U << SEMCOUNT_VALUE_SHIFT)) & SEMCOUNT_VALUE_MASK)
-#define SEMCOUNT_INCREMENT(sval) (((sval) + (1U << SEMCOUNT_VALUE_SHIFT)) & SEMCOUNT_VALUE_MASK)
-
-/* return the shared bitflag from a semaphore */
-#define SEM_GET_SHARED(sem) ((sem)->count & SEMCOUNT_SHARED_MASK)
-
-
-int sem_init(sem_t *sem, int pshared, unsigned int value)
-{
- if (sem == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- /* ensure that 'value' can be stored in the semaphore */
- if (value > SEM_MAX_VALUE) {
- errno = EINVAL;
- return -1;
- }
-
- sem->count = SEMCOUNT_FROM_VALUE(value);
- if (pshared != 0)
- sem->count |= SEMCOUNT_SHARED_MASK;
-
- return 0;
-}
-
-
-int sem_destroy(sem_t *sem)
-{
- int count;
-
- if (sem == NULL) {
- errno = EINVAL;
- return -1;
- }
- count = SEMCOUNT_TO_VALUE(sem->count);
- if (count < 0) {
- errno = EBUSY;
- return -1;
- }
- sem->count = 0;
- return 0;
-}
-
-
-sem_t *sem_open(const char *name __unused, int oflag __unused, ...)
-{
- errno = ENOSYS;
- return SEM_FAILED;
-}
-
-
-int sem_close(sem_t *sem)
-{
- if (sem == NULL) {
- errno = EINVAL;
- return -1;
- }
- errno = ENOSYS;
- return -1;
-}
-
-
-int sem_unlink(const char* name __unused)
-{
- errno = ENOSYS;
- return -1;
-}
-
-
-/* Decrement a semaphore's value atomically,
- * and return the old one. As a special case,
- * this returns immediately if the value is
- * negative (i.e. -1)
- */
-static int
-__sem_dec(volatile unsigned int *pvalue)
-{
- unsigned int shared = (*pvalue & SEMCOUNT_SHARED_MASK);
- unsigned int old, new;
- int ret;
-
- do {
- old = (*pvalue & SEMCOUNT_VALUE_MASK);
- ret = SEMCOUNT_TO_VALUE(old);
- if (ret < 0)
- break;
-
- new = SEMCOUNT_DECREMENT(old);
- }
- while (__bionic_cmpxchg((int)(old|shared),
- (int)(new|shared),
- (volatile int *)pvalue) != 0);
- return ret;
-}
-
-/* Same as __sem_dec, but will not touch anything if the
- * value is already negative *or* 0. Returns the old value.
- */
-static int
-__sem_trydec(volatile unsigned int *pvalue)
-{
- unsigned int shared = (*pvalue & SEMCOUNT_SHARED_MASK);
- unsigned int old, new;
- int ret;
-
- do {
- old = (*pvalue & SEMCOUNT_VALUE_MASK);
- ret = SEMCOUNT_TO_VALUE(old);
- if (ret <= 0)
- break;
-
- new = SEMCOUNT_DECREMENT(old);
- }
- while (__bionic_cmpxchg((int)(old|shared),
- (int)(new|shared),
- (volatile int *)pvalue) != 0);
-
- return ret;
-}
-
-
-/* "Increment" the value of a semaphore atomically and
- * return its old value. Note that this implements
- * the special case of "incrementing" any negative
- * value to +1 directly.
- *
- * NOTE: The value will _not_ wrap above SEM_VALUE_MAX
- */
-static int
-__sem_inc(volatile unsigned int *pvalue)
-{
- unsigned int shared = (*pvalue & SEMCOUNT_SHARED_MASK);
- unsigned int old, new;
- int ret;
-
- do {
- old = (*pvalue & SEMCOUNT_VALUE_MASK);
- ret = SEMCOUNT_TO_VALUE(old);
-
- /* Can't go higher than SEM_MAX_VALUE */
- if (ret == SEM_MAX_VALUE)
- break;
-
- /* If the counter is negative, go directly to +1,
- * otherwise just increment */
- if (ret < 0)
- new = SEMCOUNT_ONE;
- else
- new = SEMCOUNT_INCREMENT(old);
- }
- while ( __bionic_cmpxchg((int)(old|shared),
- (int)(new|shared),
- (volatile int*)pvalue) != 0);
-
- return ret;
-}
-
-/* lock a semaphore */
-int sem_wait(sem_t *sem)
-{
- unsigned shared;
-
- if (sem == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- shared = SEM_GET_SHARED(sem);
-
- for (;;) {
- if (__sem_dec(&sem->count) > 0)
- break;
-
- __futex_wait_ex(&sem->count, shared, shared|SEMCOUNT_MINUS_ONE, NULL);
- }
- ANDROID_MEMBAR_FULL();
- return 0;
-}
-
-int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout)
-{
- unsigned int shared;
-
- if (sem == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- /* POSIX says we need to try to decrement the semaphore
- * before checking the timeout value. Note that if the
- * value is currently 0, __sem_trydec() does nothing.
- */
- if (__sem_trydec(&sem->count) > 0) {
- ANDROID_MEMBAR_FULL();
- return 0;
- }
-
- /* Check it as per Posix */
- if (abs_timeout == NULL ||
- abs_timeout->tv_sec < 0 ||
- abs_timeout->tv_nsec < 0 ||
- abs_timeout->tv_nsec >= 1000000000)
- {
- errno = EINVAL;
- return -1;
- }
-
- shared = SEM_GET_SHARED(sem);
-
- for (;;) {
- struct timespec ts;
- int ret;
-
- /* Posix mandates CLOCK_REALTIME here */
- clock_gettime( CLOCK_REALTIME, &ts );
- ts.tv_sec = abs_timeout->tv_sec - ts.tv_sec;
- ts.tv_nsec = abs_timeout->tv_nsec - ts.tv_nsec;
- if (ts.tv_nsec < 0) {
- ts.tv_nsec += 1000000000;
- ts.tv_sec -= 1;
- }
-
- if (ts.tv_sec < 0 || ts.tv_nsec < 0) {
- errno = ETIMEDOUT;
- return -1;
- }
-
- /* Try to grab the semaphore. If the value was 0, this
- * will also change it to -1 */
- if (__sem_dec(&sem->count) > 0) {
- ANDROID_MEMBAR_FULL();
- break;
- }
-
- /* Contention detected. wait for a wakeup event */
- ret = __futex_wait_ex(&sem->count, shared, shared|SEMCOUNT_MINUS_ONE, &ts);
-
- /* return in case of timeout or interrupt */
- if (ret == -ETIMEDOUT || ret == -EINTR) {
- errno = -ret;
- return -1;
- }
- }
- return 0;
-}
-
-/* Unlock a semaphore */
-int sem_post(sem_t *sem)
-{
- unsigned int shared;
- int old;
-
- if (sem == NULL)
- return EINVAL;
-
- shared = SEM_GET_SHARED(sem);
-
- ANDROID_MEMBAR_FULL();
- old = __sem_inc(&sem->count);
- if (old < 0) {
- /* contention on the semaphore, wake up all waiters */
- __futex_wake_ex(&sem->count, shared, INT_MAX);
- }
- else if (old == SEM_MAX_VALUE) {
- /* overflow detected */
- errno = EOVERFLOW;
- return -1;
- }
-
- return 0;
-}
-
-int sem_trywait(sem_t *sem)
-{
- if (sem == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- if (__sem_trydec(&sem->count) > 0) {
- ANDROID_MEMBAR_FULL();
- return 0;
- } else {
- errno = EAGAIN;
- return -1;
- }
-}
-
-/* Note that Posix requires that sem_getvalue() returns, in
- * case of contention, the negative of the number of waiting
- * threads.
- *
- * However, code that depends on this negative value to be
- * meaningful is most probably racy. The GLibc sem_getvalue()
- * only returns the semaphore value, which is 0, in case of
- * contention, so we will mimick this behaviour here instead
- * for better compatibility.
- */
-int sem_getvalue(sem_t *sem, int *sval)
-{
- int val;
-
- if (sem == NULL || sval == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- val = SEMCOUNT_TO_VALUE(sem->count);
- if (val < 0)
- val = 0;
-
- *sval = val;
- return 0;
-}
diff --git a/libc/bionic/semaphore.cpp b/libc/bionic/semaphore.cpp
new file mode 100644
index 0000000..c23eb75
--- /dev/null
+++ b/libc/bionic/semaphore.cpp
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <semaphore.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include "private/bionic_atomic_inline.h"
+#include "private/bionic_constants.h"
+#include "private/bionic_futex.h"
+#include "private/bionic_time_conversions.h"
+
+// In this implementation, a semaphore contains a
+// 31-bit signed value and a 1-bit 'shared' flag
+// (for process-sharing purpose).
+//
+// We use the value -1 to indicate contention on the
+// semaphore, 0 or more to indicate uncontended state,
+// any value lower than -2 is invalid at runtime.
+//
+// State diagram:
+//
+// post(1) ==> 2
+// post(0) ==> 1
+// post(-1) ==> 1, then wake all waiters
+//
+// wait(2) ==> 1
+// wait(1) ==> 0
+// wait(0) ==> -1 then wait for a wake up + loop
+// wait(-1) ==> -1 then wait for a wake up + loop
+
+// Use the upper 31-bits for the counter, and the lower one
+// for the shared flag.
+#define SEMCOUNT_SHARED_MASK 0x00000001
+#define SEMCOUNT_VALUE_MASK 0xfffffffe
+#define SEMCOUNT_VALUE_SHIFT 1
+
+// Convert a value into the corresponding sem->count bit pattern.
+#define SEMCOUNT_FROM_VALUE(val) (((val) << SEMCOUNT_VALUE_SHIFT) & SEMCOUNT_VALUE_MASK)
+
+// Convert a sem->count bit pattern into the corresponding signed value.
+static inline int SEMCOUNT_TO_VALUE(uint32_t sval) {
+ return (static_cast<int>(sval) >> SEMCOUNT_VALUE_SHIFT);
+}
+
+// The value +1 as a sem->count bit-pattern.
+#define SEMCOUNT_ONE SEMCOUNT_FROM_VALUE(1)
+
+// The value -1 as a sem->count bit-pattern.
+#define SEMCOUNT_MINUS_ONE SEMCOUNT_FROM_VALUE(-1)
+
+#define SEMCOUNT_DECREMENT(sval) (((sval) - (1U << SEMCOUNT_VALUE_SHIFT)) & SEMCOUNT_VALUE_MASK)
+#define SEMCOUNT_INCREMENT(sval) (((sval) + (1U << SEMCOUNT_VALUE_SHIFT)) & SEMCOUNT_VALUE_MASK)
+
+// Return the shared bitflag from a semaphore.
+static inline uint32_t SEM_GET_SHARED(sem_t* sem) {
+ return (sem->count & SEMCOUNT_SHARED_MASK);
+}
+
+
+int sem_init(sem_t* sem, int pshared, unsigned int value) {
+ if (sem == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ // Ensure that 'value' can be stored in the semaphore.
+ if (value > SEM_VALUE_MAX) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ sem->count = SEMCOUNT_FROM_VALUE(value);
+ if (pshared != 0) {
+ sem->count |= SEMCOUNT_SHARED_MASK;
+ }
+ return 0;
+}
+
+int sem_destroy(sem_t* sem) {
+ if (sem == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ return 0;
+}
+
+sem_t* sem_open(const char*, int, ...) {
+ errno = ENOSYS;
+ return SEM_FAILED;
+}
+
+int sem_close(sem_t*) {
+ errno = ENOSYS;
+ return -1;
+}
+
+int sem_unlink(const char*) {
+ errno = ENOSYS;
+ return -1;
+}
+
+// Decrement a semaphore's value atomically,
+// and return the old one. As a special case,
+// this returns immediately if the value is
+// negative (i.e. -1)
+static int __sem_dec(volatile uint32_t* sem) {
+ volatile int32_t* ptr = reinterpret_cast<volatile int32_t*>(sem);
+ uint32_t shared = (*sem & SEMCOUNT_SHARED_MASK);
+ uint32_t old_value, new_value;
+ int ret;
+
+ do {
+ old_value = (*sem & SEMCOUNT_VALUE_MASK);
+ ret = SEMCOUNT_TO_VALUE(old_value);
+ if (ret < 0) {
+ break;
+ }
+
+ new_value = SEMCOUNT_DECREMENT(old_value);
+ } while (__bionic_cmpxchg((old_value|shared), (new_value|shared), ptr) != 0);
+
+ return ret;
+}
+
+// Same as __sem_dec, but will not touch anything if the
+// value is already negative *or* 0. Returns the old value.
+static int __sem_trydec(volatile uint32_t* sem) {
+ volatile int32_t* ptr = reinterpret_cast<volatile int32_t*>(sem);
+ uint32_t shared = (*sem & SEMCOUNT_SHARED_MASK);
+ uint32_t old_value, new_value;
+ int ret;
+
+ do {
+ old_value = (*sem & SEMCOUNT_VALUE_MASK);
+ ret = SEMCOUNT_TO_VALUE(old_value);
+ if (ret <= 0) {
+ break;
+ }
+
+ new_value = SEMCOUNT_DECREMENT(old_value);
+ } while (__bionic_cmpxchg((old_value|shared), (new_value|shared), ptr) != 0);
+
+ return ret;
+}
+
+
+// "Increment" the value of a semaphore atomically and
+// return its old value. Note that this implements
+// the special case of "incrementing" any negative
+// value to +1 directly.
+//
+// NOTE: The value will _not_ wrap above SEM_VALUE_MAX
+static int __sem_inc(volatile uint32_t* sem) {
+ volatile int32_t* ptr = reinterpret_cast<volatile int32_t*>(sem);
+ uint32_t shared = (*sem & SEMCOUNT_SHARED_MASK);
+ uint32_t old_value, new_value;
+ int ret;
+
+ do {
+ old_value = (*sem & SEMCOUNT_VALUE_MASK);
+ ret = SEMCOUNT_TO_VALUE(old_value);
+
+ // Can't go higher than SEM_VALUE_MAX.
+ if (ret == SEM_VALUE_MAX) {
+ break;
+ }
+
+ // If the counter is negative, go directly to +1, otherwise just increment.
+ if (ret < 0) {
+ new_value = SEMCOUNT_ONE;
+ } else {
+ new_value = SEMCOUNT_INCREMENT(old_value);
+ }
+ } while (__bionic_cmpxchg((old_value|shared), (new_value|shared), ptr) != 0);
+
+ return ret;
+}
+
+int sem_wait(sem_t* sem) {
+ if (sem == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ uint32_t shared = SEM_GET_SHARED(sem);
+
+ while (true) {
+ if (__sem_dec(&sem->count) > 0) {
+ ANDROID_MEMBAR_FULL();
+ return 0;
+ }
+
+ __futex_wait_ex(&sem->count, shared, shared|SEMCOUNT_MINUS_ONE, NULL);
+ }
+}
+
+int sem_timedwait(sem_t* sem, const timespec* abs_timeout) {
+ if (sem == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ // POSIX says we need to try to decrement the semaphore
+ // before checking the timeout value. Note that if the
+ // value is currently 0, __sem_trydec() does nothing.
+ if (__sem_trydec(&sem->count) > 0) {
+ ANDROID_MEMBAR_FULL();
+ return 0;
+ }
+
+ // Check it as per POSIX.
+ if (abs_timeout == NULL || abs_timeout->tv_sec < 0 || abs_timeout->tv_nsec < 0 || abs_timeout->tv_nsec >= NS_PER_S) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ uint32_t shared = SEM_GET_SHARED(sem);
+
+ while (true) {
+ // POSIX mandates CLOCK_REALTIME here.
+ timespec ts;
+ if (!timespec_from_absolute_timespec(ts, *abs_timeout, CLOCK_REALTIME)) {
+ errno = ETIMEDOUT;
+ return -1;
+ }
+
+ // Try to grab the semaphore. If the value was 0, this will also change it to -1.
+ if (__sem_dec(&sem->count) > 0) {
+ ANDROID_MEMBAR_FULL();
+ break;
+ }
+
+ // Contention detected. Wait for a wakeup event.
+ int ret = __futex_wait_ex(&sem->count, shared, shared|SEMCOUNT_MINUS_ONE, &ts);
+
+ // Return in case of timeout or interrupt.
+ if (ret == -ETIMEDOUT || ret == -EINTR) {
+ errno = -ret;
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int sem_post(sem_t* sem) {
+ if (sem == NULL) {
+ return EINVAL;
+ }
+
+ uint32_t shared = SEM_GET_SHARED(sem);
+
+ ANDROID_MEMBAR_FULL();
+ int old_value = __sem_inc(&sem->count);
+ if (old_value < 0) {
+ // Contention on the semaphore. Wake up all waiters.
+ __futex_wake_ex(&sem->count, shared, INT_MAX);
+ } else if (old_value == SEM_VALUE_MAX) {
+ // Overflow detected.
+ errno = EOVERFLOW;
+ return -1;
+ }
+
+ return 0;
+}
+
+int sem_trywait(sem_t* sem) {
+ if (sem == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (__sem_trydec(&sem->count) > 0) {
+ ANDROID_MEMBAR_FULL();
+ return 0;
+ } else {
+ errno = EAGAIN;
+ return -1;
+ }
+}
+
+int sem_getvalue(sem_t* sem, int* sval) {
+ if (sem == NULL || sval == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ int val = SEMCOUNT_TO_VALUE(sem->count);
+ if (val < 0) {
+ val = 0;
+ }
+
+ *sval = val;
+ return 0;
+}
diff --git a/libc/bionic/strtoll_l.cpp b/libc/bionic/strtoll_l.cpp
index 05fb760..47b126e 100644
--- a/libc/bionic/strtoll_l.cpp
+++ b/libc/bionic/strtoll_l.cpp
@@ -28,6 +28,6 @@
#include <stdlib.h>
-long long strtoll_l(const char *nptr, char **endptr, size_t base, locale_t) {
+long long strtoll_l(const char *nptr, char **endptr, int base, locale_t) {
return strtoll(nptr, endptr, base);
}
diff --git a/libc/bionic/strtoull_l.cpp b/libc/bionic/strtoull_l.cpp
index ba0bc6a..398ba0e 100644
--- a/libc/bionic/strtoull_l.cpp
+++ b/libc/bionic/strtoull_l.cpp
@@ -28,7 +28,7 @@
#include <stdlib.h>
-unsigned long long strtoull_l(const char *nptr, char **endptr, size_t base,
+unsigned long long strtoull_l(const char *nptr, char **endptr, int base,
locale_t) {
return strtoull(nptr, endptr, base);
}
diff --git a/libc/bionic/sysconf.cpp b/libc/bionic/sysconf.cpp
index d8aac4f..951860d 100644
--- a/libc/bionic/sysconf.cpp
+++ b/libc/bionic/sysconf.cpp
@@ -49,7 +49,6 @@
#define SYSTEM_MQ_OPEN_MAX 8
#define SYSTEM_MQ_PRIO_MAX 32768
#define SYSTEM_SEM_NSEMS_MAX 256
-#define SYSTEM_SEM_VALUE_MAX 0x3fffffff /* see bionic/semaphore.c */
#define SYSTEM_SIGQUEUE_MAX 32
#define SYSTEM_TIMER_MAX 32
#define SYSTEM_LOGIN_NAME_MAX 256
@@ -151,36 +150,14 @@
}
int sysconf(int name) {
- switch (name) {
-#ifdef _POSIX_ARG_MAX
+ switch (name) {
case _SC_ARG_MAX: return _POSIX_ARG_MAX;
-#endif
-#ifdef _POSIX2_BC_BASE_MAX
- case _SC_BC_BASE_MAX: return _POSIX2_BC_BASE_MAX;
-#endif
-#ifdef _POSIX2_BC_DIM_MAX
- case _SC_BC_DIM_MAX: return _POSIX2_BC_DIM_MAX;
-#endif
-#ifdef _POSIX2_BC_SCALE_MAX
- case _SC_BC_SCALE_MAX: return _POSIX2_BC_SCALE_MAX;
-#endif
-#ifdef _POSIX2_BC_STRING_MAX
- case _SC_BC_STRING_MAX: return _POSIX2_BC_STRING_MAX;
-#endif
case _SC_CHILD_MAX: return CHILD_MAX;
case _SC_CLK_TCK: return SYSTEM_CLK_TCK;
-#ifdef _POSIX2_COLL_WEIGHTS_MASK
- case _SC_COLL_WEIGHTS_MAX: return _POSIX2_COLL_WEIGHTS_MASK;
-#endif
-#ifdef _POSIX2_EXPR_NEST_MAX
- case _SC_EXPR_NEST_MAX: return _POSIX2_EXPR_NEST_MAX;
-#endif
-#ifdef _POSIX2_LINE_MAX
case _SC_LINE_MAX: return _POSIX2_LINE_MAX;
-#endif
case _SC_NGROUPS_MAX: return NGROUPS_MAX;
case _SC_OPEN_MAX: return OPEN_MAX;
- //case _SC_PASS_MAX: return PASS_MAX;
+ case _SC_PASS_MAX: return PASS_MAX;
case _SC_2_C_BIND: return SYSTEM_2_C_BIND;
case _SC_2_C_DEV: return SYSTEM_2_C_DEV;
case _SC_2_C_VERSION: return SYSTEM_2_C_VER;
@@ -191,42 +168,20 @@
case _SC_2_SW_DEV: return SYSTEM_2_SW_DEV;
case _SC_2_UPE: return SYSTEM_2_UPE;
case _SC_2_VERSION: return SYSTEM_2_VERSION;
-#ifdef _POSIX_JOB_CONTROL
case _SC_JOB_CONTROL: return _POSIX_JOB_CONTROL;
-#endif
-#ifdef _POSIX_SAVED_IDS
case _SC_SAVED_IDS: return _POSIX_SAVED_IDS;
-#endif
-#ifdef _POSIX_VERSION
case _SC_VERSION: return _POSIX_VERSION;
-#endif
- //case _SC_RE_DUP_<AX: return ;
+ case _SC_RE_DUP_MAX: return _POSIX_RE_DUP_MAX;
case _SC_STREAM_MAX: return FOPEN_MAX;
- //case _SC_TZNAME_MAX: return ;
-#if _XOPEN_CRYPT
+ case _SC_TZNAME_MAX: return _POSIX_TZNAME_MAX;
case _SC_XOPEN_CRYPT: return _XOPEN_CRYPT;
-#endif
-#ifdef _XOPEN_ENH_I18N
case _SC_XOPEN_ENH_I18N: return _XOPEN_ENH_I18N;
-#endif
-#ifdef _XOPEN_SHM
- case _SC_XOPEN_SHM: return _XOPEN_SHM;
-#endif
-#ifdef _XOPEN_VERSION
+ //case _SC_XOPEN_SHM: return _XOPEN_SHM;
case _SC_XOPEN_VERSION: return _XOPEN_VERSION;
-#endif
-#ifdef _XOPEN_XCU_VERSION
case _SC_XOPEN_XCU_VERSION: return _XOPEN_XCU_VERSION;
-#endif
-#ifdef _XOPEN_REALTIME
case _SC_XOPEN_REALTIME: return _XOPEN_REALTIME;
-#endif
-#ifdef _XOPEN_REALTIME_THREADS
case _SC_XOPEN_REALTIME_THREADS: return _XOPEN_REALTIME_THREADS;
-#endif
-#ifdef _XOPEN_LEGACY
case _SC_XOPEN_LEGACY: return _XOPEN_LEGACY;
-#endif
case _SC_ATEXIT_MAX: return SYSTEM_ATEXIT_MAX;
case _SC_IOV_MAX: return SYSTEM_IOV_MAX;
@@ -234,71 +189,35 @@
case _SC_PAGE_SIZE:
return PAGE_SIZE;
-#ifdef _XOPEN_UNIX
case _SC_XOPEN_UNIX: return _XOPEN_UNIX;
-#endif
// XXX: TODO: XBS5 nonsense
-#ifdef AIO_LISTIO_MAX
- case _SC_AIO_LISTIO_MAX: return AIO_LISTIO_MAX;
-#endif
-#ifdef AIO_MAX
- case _SC_AIO_MAX: return AIO_MAX;
-#endif
-#ifdef AIO_PRIO_DELTA_MAX
- case _SC_AIO_PRIO_DELTA_MAX: return AIO_PRIO_DELTA_MAX;
-#endif
+ //case _SC_AIO_LISTIO_MAX: return AIO_LISTIO_MAX;
+ //case _SC_AIO_MAX: return AIO_MAX;
+ //case _SC_AIO_PRIO_DELTA_MAX: return AIO_PRIO_DELTA_MAX;
case _SC_DELAYTIMER_MAX: return SYSTEM_DELAYTIMER_MAX;
case _SC_MQ_OPEN_MAX: return SYSTEM_MQ_OPEN_MAX;
case _SC_MQ_PRIO_MAX: return SYSTEM_MQ_PRIO_MAX;
case _SC_RTSIG_MAX: return RTSIG_MAX;
case _SC_SEM_NSEMS_MAX: return SYSTEM_SEM_NSEMS_MAX;
- case _SC_SEM_VALUE_MAX: return SYSTEM_SEM_VALUE_MAX;
+ case _SC_SEM_VALUE_MAX: return SEM_VALUE_MAX;
case _SC_SIGQUEUE_MAX: return SYSTEM_SIGQUEUE_MAX;
case _SC_TIMER_MAX: return SYSTEM_TIMER_MAX;
-#ifdef _POSIX_ASYNCHRONOUS_IO
- case _SC_ASYNCHRONOUS_IO: return _POSIX_ASYNCHRONOUS_IO;
-#endif
-#ifdef _POSIX_FSYNC
+ //case _SC_ASYNCHRONOUS_IO: return _POSIX_ASYNCHRONOUS_IO;
case _SC_FSYNC: return _POSIX_FSYNC;
-#endif
-#ifdef _POSIX_MAPPED_FILES
case _SC_MAPPED_FILES: return _POSIX_MAPPED_FILES;
-#endif
-#ifdef _POSIX_MEMLOCK
- case _SC_MEMLOCK: return _POSIX_MEMLOCK;
-#endif
-#ifdef _POSIX_MEMLOCK_RANGE
- case _SC_MEMLOCK_RANGE: return _POSIX_MEMLOCK_RANGE
-#endif
-#ifdef _POSIX_MEMORY_PROTECTION
- case _SC_MEMORY_PROTECTION: return _POSIX_MEMORY_PROTECTION;
-#endif
-#ifdef _POSIX_MESSAGE_PASSING
- case _SC_MESSAGE_PASSING: return _POSIX_MESSAGE_PASSING;
-#endif
-#ifdef _POSIX_PRIORITIZED_IO
- case _SC_PRIORITIZED_IO: return _POSIX_PRIORITIZED_IO;
-#endif
-#ifdef _POSIX_PRIORITY_SCHEDULING
+ //case _SC_MEMLOCK: return _POSIX_MEMLOCK;
+ //case _SC_MEMLOCK_RANGE: return _POSIX_MEMLOCK_RANGE;
+ //case _SC_MEMORY_PROTECTION: return _POSIX_MEMORY_PROTECTION;
+ //case _SC_MESSAGE_PASSING: return _POSIX_MESSAGE_PASSING;
+ //case _SC_PRIORITIZED_IO: return _POSIX_PRIORITIZED_IO;
case _SC_PRIORITY_SCHEDULING: return _POSIX_PRIORITY_SCHEDULING;
-#endif
-#ifdef _POSIX_REALTIME_SIGNALS
case _SC_REALTIME_SIGNALS: return _POSIX_REALTIME_SIGNALS;
-#endif
-#ifdef _POSIX_SEMAPHORES
case _SC_SEMAPHORES: return _POSIX_SEMAPHORES;
-#endif
-#ifdef _POSIX_SHARED_MEMORY_OBJECTS
- case _SC_SHARED_MEMORY_OBJECTS: return _POSIX_SHARED_MEMORY_OBJECTS;
-#endif
-#ifdef _POSIX_SYNCHRONIZED_IO
+ //case _SC_SHARED_MEMORY_OBJECTS: return _POSIX_SHARED_MEMORY_OBJECTS;
case _SC_SYNCHRONIZED_IO: return _POSIX_SYNCHRONIZED_IO;
-#endif
-#ifdef _POSIX_TIMERS
case _SC_TIMERS: return _POSIX_TIMERS;
-#endif
case _SC_GETGR_R_SIZE_MAX: return 1024;
case _SC_GETPW_R_SIZE_MAX: return 1024;
@@ -314,25 +233,15 @@
case _SC_THREAD_STACK_MIN: return PTHREAD_STACK_MIN;
case _SC_THREAD_THREADS_MAX: return SYSTEM_THREAD_THREADS_MAX;
case _SC_TTY_NAME_MAX: return SYSTEM_TTY_NAME_MAX;
-#ifdef _POSIX_THREADS
case _SC_THREADS: return _POSIX_THREADS;
-#endif
case _SC_THREAD_ATTR_STACKADDR: return -1; // Removed in POSIX 2008
case _SC_THREAD_ATTR_STACKSIZE: return -1; // Removed in POSIX 2008
-#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
- case _SC_THREAD_PRIORITY_SCHEDULING: return _POSIX_THREAD_PRIORITY_SCHEDULING;
-#endif
-#ifdef _POSIX_THREAD_PRIO_INHERIT
+ //case _SC_THREAD_PRIORITY_SCHEDULING: return _POSIX_THREAD_PRIORITY_SCHEDULING;
case _SC_THREAD_PRIO_INHERIT: return _POSIX_THREAD_PRIO_INHERIT;
-#endif
-#ifdef _POSIX_THREAD_PRIO_PROTECT
case _SC_THREAD_PRIO_PROTECT: return _POSIX_THREAD_PRIO_PROTECT;
-#endif
-#ifdef _POSIX_THREAD_SAFE_FUNCTIONS
- case _SC_THREAD_SAFE_FUNCTIONS: return _POSIX_THREAD_SAFE_FUNCTIONS
-#endif
+ //case _SC_THREAD_SAFE_FUNCTIONS: return _POSIX_THREAD_SAFE_FUNCTIONS
case _SC_MONOTONIC_CLOCK: return __sysconf_monotonic_clock();
case _SC_NPROCESSORS_CONF: return __sysconf_nprocessors_conf();
@@ -341,9 +250,9 @@
case _SC_AVPHYS_PAGES: return __sysconf_avphys_pages();
default:
- /* Posix says EINVAL is the only error that shall be returned,
- * but GLibc uses ENOSYS */
- errno = ENOSYS;
- return -1;
- }
+ // Posix says EINVAL is the only error that shall be returned,
+ // but glibc uses ENOSYS.
+ errno = ENOSYS;
+ return -1;
+ }
}
diff --git a/libc/bionic/system_properties.cpp b/libc/bionic/system_properties.cpp
index 411d6bf..170e7ac 100644
--- a/libc/bionic/system_properties.cpp
+++ b/libc/bionic/system_properties.cpp
@@ -471,8 +471,8 @@
static int send_prop_msg(const prop_msg *msg)
{
- const int fd = socket(AF_LOCAL, SOCK_STREAM, 0);
- if (fd < 0) {
+ const int fd = socket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ if (fd == -1) {
return -1;
}
diff --git a/libc/bionic/wchar.cpp b/libc/bionic/wchar.cpp
index 524ba07..e0879b9 100644
--- a/libc/bionic/wchar.cpp
+++ b/libc/bionic/wchar.cpp
@@ -230,13 +230,13 @@
return wcsxfrm(dest, src, n);
}
-long long wcstoll_l(const wchar_t *nptr, wchar_t **endptr, size_t base,
+long long wcstoll_l(const wchar_t *nptr, wchar_t **endptr, int base,
locale_t) {
return wcstoll(nptr, endptr, base);
}
unsigned long long wcstoull_l(const wchar_t *nptr, wchar_t **endptr,
- size_t base, locale_t) {
+ int base, locale_t) {
return wcstoull(nptr, endptr, base);
}
diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h
index db56ce3..f57c320 100644
--- a/libc/include/fcntl.h
+++ b/libc/include/fcntl.h
@@ -46,6 +46,7 @@
#endif
#define O_ASYNC FASYNC
+#define O_RSYNC O_SYNC
#define SPLICE_F_MOVE 1
#define SPLICE_F_NONBLOCK 2
diff --git a/libc/include/limits.h b/libc/include/limits.h
index fb09657..69df082 100644
--- a/libc/include/limits.h
+++ b/libc/include/limits.h
@@ -37,39 +37,6 @@
#include <sys/cdefs.h>
-#if __POSIX_VISIBLE
-#define _POSIX_ARG_MAX 4096
-#define _POSIX_CHILD_MAX 25
-#define _POSIX_LINK_MAX 8
-#define _POSIX_MAX_CANON 255
-#define _POSIX_MAX_INPUT 255
-#define _POSIX_NAME_MAX 14
-#define _POSIX_NGROUPS_MAX 0
-#define _POSIX_OPEN_MAX 16
-#define _POSIX_PATH_MAX 256
-#define _POSIX_PIPE_BUF 512
-#define _POSIX_RE_DUP_MAX 255
-#define _POSIX_SSIZE_MAX 32767
-#define _POSIX_STREAM_MAX 8
-#define _POSIX_SYMLINK_MAX 255
-#define _POSIX_SYMLOOP_MAX 8
-#define _POSIX_TZNAME_MAX 3
-
-#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_COLL_WEIGHTS_MAX 2
-#define _POSIX2_EXPR_NEST_MAX 32
-#define _POSIX2_LINE_MAX 2048
-#define _POSIX2_RE_DUP_MAX _POSIX_RE_DUP_MAX
-
-#if __POSIX_VISIBLE >= 200112
-#define _POSIX_TTY_NAME_MAX 9 /* includes trailing NUL */
-#define _POSIX_LOGIN_NAME_MAX 9 /* includes trailing NUL */
-#endif /* __POSIX_VISIBLE >= 200112 */
-#endif /* __POSIX_VISIBLE */
-
#if __XPG_VISIBLE
#define PASS_MAX 128 /* _PASSWORD_LEN from <pwd.h> */
@@ -125,4 +92,9 @@
/* glibc's PAGE_MASK is the bitwise negation of BSD's! TODO: remove? */
#define PAGE_MASK (~(PAGE_SIZE - 1))
+#define SEM_VALUE_MAX 0x3fffffff
+
+/* POSIX says these belong in <unistd.h> but BSD has some in <limits.h>. */
+#include <machine/posix_limits.h>
+
#endif /* !_LIMITS_H_ */
diff --git a/libc/include/machine/posix_limits.h b/libc/include/machine/posix_limits.h
new file mode 100644
index 0000000..f906e3b
--- /dev/null
+++ b/libc/include/machine/posix_limits.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _POSIX_LIMITS_H_
+#define _POSIX_LIMITS_H_
+
+/* TODO: complete and check these. */
+#define _POSIX2_LINE_MAX 2048
+#define _POSIX2_RE_DUP_MAX _POSIX_RE_DUP_MAX
+#define _POSIX_ARG_MAX 4096
+#define _POSIX_CHILD_MAX 25
+#define _POSIX_CHOWN_RESTRICTED 1 /* yes, chown requires appropriate privileges */
+#define _POSIX_FSYNC 1 /* fdatasync() supported */
+#define _POSIX_JOB_CONTROL 1 /* job control is a Linux feature */
+#define _POSIX_LINK_MAX 8
+#define _POSIX_LOGIN_NAME_MAX 9 /* includes trailing NUL */
+#define _POSIX_MAPPED_FILES 1 /* mmap-ed files supported */
+#define _POSIX_MAX_CANON 255
+#define _POSIX_MAX_INPUT 255
+#define _POSIX_MONOTONIC_CLOCK 0 /* the monotonic clock may be available; ask sysconf */
+#define _POSIX_NAME_MAX 14
+#define _POSIX_NGROUPS_MAX 0
+#define _POSIX_NO_TRUNC 1 /* very long pathnames generate an error */
+#define _POSIX_OPEN_MAX 16
+#define _POSIX_PATH_MAX 256
+#define _POSIX_PIPE_BUF 512
+#define _POSIX_PRIORITY_SCHEDULING 1 /* priority scheduling is a Linux feature */
+#define _POSIX_REALTIME_SIGNALS -1 /* for now, this is not supported */
+#define _POSIX_RE_DUP_MAX 255
+#define _POSIX_SAVED_IDS 1 /* saved user ids is a Linux feature */
+#define _POSIX_SEMAPHORES 200809L
+#define _POSIX_SEM_VALUE_MAX 32767
+#define _POSIX_SSIZE_MAX 32767
+#define _POSIX_STREAM_MAX 8
+#define _POSIX_SYMLINK_MAX 255
+#define _POSIX_SYMLOOP_MAX 8
+#define _POSIX_SYNCHRONIZED_IO 1 /* synchronized i/o supported */
+#define _POSIX_THREAD_PRIO_INHERIT 200112L /* linux feature */
+#define _POSIX_THREAD_PRIO_PROTECT 200112L /* linux feature */
+#define _POSIX_THREADS 1 /* we support threads */
+#define _POSIX_THREAD_STACKADDR 1 /* we support thread stack address */
+#define _POSIX_THREAD_STACKSIZE 1 /* we support thread stack size */
+#define _POSIX_TIMERS 1 /* Posix timers are supported */
+#define _POSIX_TTY_NAME_MAX 9 /* includes trailing NUL */
+#define _POSIX_TZNAME_MAX 3
+#define _POSIX_VDISABLE '\0'
+
+#endif /* _POSIX_LIMITS_H_ */
diff --git a/libc/include/pathconf.h b/libc/include/pathconf.h
deleted file mode 100644
index 94f9787..0000000
--- a/libc/include/pathconf.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#ifndef _PATHCONF_H_
-#define _PATHCONF_H_
-
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-
-/* constants to be used for the 'name' paremeter of pathconf/fpathconf */
-
-#define _PC_FILESIZEBITS 0x0000
-#define _PC_LINK_MAX 0x0001
-#define _PC_MAX_CANON 0x0002
-#define _PC_MAX_INPUT 0x0003
-#define _PC_NAME_MAX 0x0004
-#define _PC_PATH_MAX 0x0005
-#define _PC_PIPE_BUF 0x0006
-#define _PC_2_SYMLINKS 0x0007
-#define _PC_ALLOC_SIZE_MIN 0x0008
-#define _PC_REC_INCR_XFER_SIZE 0x0009
-#define _PC_REC_MAX_XFER_SIZE 0x000a
-#define _PC_REC_MIN_XFER_SIZE 0x000b
-#define _PC_REC_XFER_ALIGN 0x000c
-#define _PC_SYMLINK_MAX 0x000d
-#define _PC_CHOWN_RESTRICTED 0x000e
-#define _PC_NO_TRUNC 0x000f
-#define _PC_VDISABLE 0x0010
-#define _PC_ASYNC_IO 0x0011
-#define _PC_PRIO_IO 0x0012
-#define _PC_SYNC_IO 0x0013
-
-extern long fpathconf(int fildes, int name);
-extern long pathconf(const char *path, int name);
-
-__END_DECLS
-
-#endif /* _PATHCONF_H_ */
-
diff --git a/libc/include/semaphore.h b/libc/include/semaphore.h
index 7ae3c3a..5827870 100644
--- a/libc/include/semaphore.h
+++ b/libc/include/semaphore.h
@@ -25,6 +25,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+
#ifndef _SEMAPHORE_H
#define _SEMAPHORE_H
@@ -32,6 +33,8 @@
__BEGIN_DECLS
+struct timespec;
+
typedef struct {
volatile unsigned int count;
#ifdef __LP64__
@@ -41,20 +44,18 @@
#define SEM_FAILED NULL
-extern int sem_init(sem_t *sem, int pshared, unsigned int value);
+int sem_destroy(sem_t*);
+int sem_getvalue(sem_t*, int*);
+int sem_init(sem_t*, int, unsigned int);
+int sem_post(sem_t*);
+int sem_timedwait(sem_t*, const struct timespec*);
+int sem_trywait(sem_t*);
+int sem_wait(sem_t*);
-extern int sem_close(sem_t *);
-extern int sem_destroy(sem_t *);
-extern int sem_getvalue(sem_t *, int *);
-extern int sem_init(sem_t *, int, unsigned int);
-extern sem_t *sem_open(const char *, int, ...);
-extern int sem_post(sem_t *);
-extern int sem_trywait(sem_t *);
-extern int sem_unlink(const char *);
-extern int sem_wait(sem_t *);
-
-struct timespec;
-extern int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
+/* These aren't actually implemented. */
+sem_t* sem_open(const char*, int, ...);
+int sem_close(sem_t*);
+int sem_unlink(const char*);
__END_DECLS
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 52f71dd..fd2bf6c 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -59,8 +59,15 @@
extern char* mkdtemp(char*);
extern char* mktemp(char*) __warnattr("mktemp possibly used unsafely; consider using mkstemp");
-extern int mkstemp(char*);
+
+extern int mkostemp64(char*, int);
+extern int mkostemp(char*, int);
+extern int mkostemps64(char*, int, int);
+extern int mkostemps(char*, int, int);
extern int mkstemp64(char*);
+extern int mkstemp(char*);
+extern int mkstemps64(char*, int);
+extern int mkstemps(char*, int);
extern long strtol(const char *, char **, int);
extern long long strtoll(const char *, char **, int);
@@ -76,8 +83,8 @@
extern long double strtold(const char*, char**) __LIBC_ABI_PUBLIC__;
extern long double strtold_l(const char *, char **, locale_t) __LIBC_ABI_PUBLIC__;
-extern long long strtoll_l(const char *, char **, size_t, locale_t) __LIBC_ABI_PUBLIC__;
-extern unsigned long long strtoull_l(const char *, char **, size_t, locale_t) __LIBC_ABI_PUBLIC__;
+extern long long strtoll_l(const char *, char **, int, locale_t) __LIBC_ABI_PUBLIC__;
+extern unsigned long long strtoull_l(const char *, char **, int, locale_t) __LIBC_ABI_PUBLIC__;
extern int atoi(const char*) __purefunc;
extern long atol(const char*) __purefunc;
diff --git a/libc/include/sys/limits.h b/libc/include/sys/limits.h
index c50eb10..edb8c47 100644
--- a/libc/include/sys/limits.h
+++ b/libc/include/sys/limits.h
@@ -135,31 +135,6 @@
#define _XOPEN_REALTIME -1 /* we don't support all these functions */
#define _XOPEN_REALTIME_THREADS -1 /* same here */
-#define _POSIX_REALTIME_SIGNALS -1 /* for now, this is not supported */
-#define _POSIX_PRIORITY_SCHEDULING 1 /* priority scheduling is a Linux feature */
-#define _POSIX_TIMERS 1 /* Posix timers are supported */
-#undef _POSIX_ASYNCHRONOUS_IO /* aio_ functions are not supported */
-#define _POSIX_SYNCHRONIZED_IO 1 /* synchronized i/o supported */
-#define _POSIX_FSYNC 1 /* fdatasync() supported */
-#define _POSIX_MAPPED_FILES 1 /* mmap-ed files supported */
-
-/* XXX: TODO: complete and check list here */
-
-
-#define _POSIX_THREADS 1 /* we support threads */
-#define _POSIX_THREAD_STACKADDR 1 /* we support thread stack address */
-#define _POSIX_THREAD_STACKSIZE 1 /* we support thread stack size */
-#define _POSIX_THREAD_PRIO_INHERIT 200112L /* linux feature */
-#define _POSIX_THREAD_PRIO_PROTECT 200112L /* linux feature */
-
-#undef _POSIX_PROCESS_SHARED /* we don't support process-shared synchronization */
-#undef _POSIX_THREAD_SAFE_FUNCTIONS /* most functions are, but not everything yet */
-#define _POSIX_CHOWN_RESTRICTED 1 /* yes, chown requires appropriate privileges */
-#define _POSIX_MONOTONIC_CLOCK 0 /* the monotonic clock may be available; ask sysconf */
-#define _POSIX_NO_TRUNC 1 /* very long pathnames generate an error */
-#define _POSIX_SAVED_IDS 1 /* saved user ids is a Linux feature */
-#define _POSIX_JOB_CONTROL 1 /* job control is a Linux feature */
-
#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 /* the minimum mandated by POSIX */
#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS
#define _POSIX_THREAD_KEYS_MAX 128 /* the minimum mandated by POSIX */
@@ -167,5 +142,4 @@
#define _POSIX_THREAD_THREADS_MAX 64 /* the minimum mandated by POSIX */
#define PTHREAD_THREADS_MAX /* bionic has no specific limit */
-
#endif
diff --git a/libc/include/sys/vfs.h b/libc/include/sys/vfs.h
index 5358ffb..1fbc8be 100644
--- a/libc/include/sys/vfs.h
+++ b/libc/include/sys/vfs.h
@@ -25,6 +25,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+
#ifndef _SYS_VFS_H_
#define _SYS_VFS_H_
@@ -114,50 +115,27 @@
#define _STATFS_F_FRSIZE
#define _STATFS_F_FLAGS
-#define ADFS_SUPER_MAGIC 0xadf5
-#define AFFS_SUPER_MAGIC 0xADFF
-#define BEFS_SUPER_MAGIC 0x42465331
-#define BFS_MAGIC 0x1BADFACE
-#define CIFS_MAGIC_NUMBER 0xFF534D42
-#define CODA_SUPER_MAGIC 0x73757245
-#define COH_SUPER_MAGIC 0x012FF7B7
-#define CRAMFS_MAGIC 0x28cd3d45
-#define DEVFS_SUPER_MAGIC 0x1373
-#define EFS_SUPER_MAGIC 0x00414A53
-#define EXT_SUPER_MAGIC 0x137D
-#define EXT2_OLD_SUPER_MAGIC 0xEF51
-#define EXT2_SUPER_MAGIC 0xEF53
-#define EXT3_SUPER_MAGIC 0xEF53
-#define HFS_SUPER_MAGIC 0x4244
-#define HPFS_SUPER_MAGIC 0xF995E849
-#define HUGETLBFS_MAGIC 0x958458f6
-#define ISOFS_SUPER_MAGIC 0x9660
-#define JFFS2_SUPER_MAGIC 0x72b6
-#define JFS_SUPER_MAGIC 0x3153464a
-#define MINIX_SUPER_MAGIC 0x137F /* orig. minix */
-#define MINIX_SUPER_MAGIC2 0x138F /* 30 char minix */
-#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 */
-#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2, 30 char names */
-#define MSDOS_SUPER_MAGIC 0x4d44
-#define NCP_SUPER_MAGIC 0x564c
-#define NFS_SUPER_MAGIC 0x6969
-#define NTFS_SB_MAGIC 0x5346544e
-#define OPENPROM_SUPER_MAGIC 0x9fa1
-#define PROC_SUPER_MAGIC 0x9fa0
-#define QNX4_SUPER_MAGIC 0x002f
-#define REISERFS_SUPER_MAGIC 0x52654973
-#define ROMFS_MAGIC 0x7275
-#define SMB_SUPER_MAGIC 0x517B
-#define SYSV2_SUPER_MAGIC 0x012FF7B6
-#define SYSV4_SUPER_MAGIC 0x012FF7B5
-#define TMPFS_MAGIC 0x01021994
-#define UDF_SUPER_MAGIC 0x15013346
-#define UFS_MAGIC 0x00011954
-#define USBDEVICE_SUPER_MAGIC 0x9fa2
-#define VXFS_SUPER_MAGIC 0xa501FCF5
-#define XENIX_SUPER_MAGIC 0x012FF7B4
-#define XFS_SUPER_MAGIC 0x58465342
-#define _XIAFS_SUPER_MAGIC 0x012FD16D
+/* Pull in the kernel magic numbers. */
+#include <linux/magic.h>
+/* Add in ones that we had historically that aren't in the uapi header. */
+#define BEFS_SUPER_MAGIC 0x42465331
+#define BFS_MAGIC 0x1BADFACE
+#define CIFS_MAGIC_NUMBER 0xFF534D42
+#define COH_SUPER_MAGIC 0x012FF7B7
+#define DEVFS_SUPER_MAGIC 0x1373
+#define EXT_SUPER_MAGIC 0x137D
+#define EXT2_OLD_SUPER_MAGIC 0xEF51
+#define HFS_SUPER_MAGIC 0x4244
+#define JFS_SUPER_MAGIC 0x3153464a
+#define NTFS_SB_MAGIC 0x5346544e
+#define ROMFS_MAGIC 0x7275
+#define SYSV2_SUPER_MAGIC 0x012FF7B6
+#define SYSV4_SUPER_MAGIC 0x012FF7B5
+#define UDF_SUPER_MAGIC 0x15013346
+#define UFS_MAGIC 0x00011954
+#define VXFS_SUPER_MAGIC 0xa501FCF5
+#define XENIX_SUPER_MAGIC 0x012FF7B4
+#define XFS_SUPER_MAGIC 0x58465342
extern int statfs(const char*, struct statfs*) __nonnull((1, 2));
extern int statfs64(const char*, struct statfs64*) __nonnull((1, 2));
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 34ae2bc..475ee1af 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -34,7 +34,6 @@
#include <sys/types.h>
#include <sys/select.h>
#include <sys/sysconf.h>
-#include <pathconf.h>
__BEGIN_DECLS
@@ -48,6 +47,29 @@
#define SEEK_CUR 1
#define SEEK_END 2
+#define _PC_FILESIZEBITS 0
+#define _PC_LINK_MAX 1
+#define _PC_MAX_CANON 2
+#define _PC_MAX_INPUT 3
+#define _PC_NAME_MAX 4
+#define _PC_PATH_MAX 5
+#define _PC_PIPE_BUF 6
+#define _PC_2_SYMLINKS 7
+#define _PC_ALLOC_SIZE_MIN 8
+#define _PC_REC_INCR_XFER_SIZE 9
+#define _PC_REC_MAX_XFER_SIZE 10
+#define _PC_REC_MIN_XFER_SIZE 11
+#define _PC_REC_XFER_ALIGN 12
+#define _PC_SYMLINK_MAX 13
+#define _PC_CHOWN_RESTRICTED 14
+#define _PC_NO_TRUNC 15
+#define _PC_VDISABLE 16
+#define _PC_ASYNC_IO 17
+#define _PC_PRIO_IO 18
+#define _PC_SYNC_IO 19
+
+#include <machine/posix_limits.h>
+
extern char** environ;
extern __noreturn void _exit(int);
@@ -96,6 +118,9 @@
extern void endusershell(void);
+extern long fpathconf(int, int);
+extern long pathconf(const char*, int);
+
/* Macros for access() */
#define R_OK 4 /* Read */
@@ -144,9 +169,7 @@
extern int dup(int);
extern int dup2(int, int);
-#if defined(__USE_GNU)
extern int dup3(int, int, int);
-#endif
extern int fcntl(int, int, ...);
extern int ioctl(int, int, ...);
extern int flock(int, int);
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index ae10d93..10a78b8 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -151,8 +151,8 @@
extern int wprintf(const wchar_t *, ...);
extern int wscanf(const wchar_t *, ...);
-extern long long wcstoll_l(const wchar_t *, wchar_t **, size_t, locale_t);
-extern unsigned long long wcstoull_l(const wchar_t *, wchar_t **, size_t, locale_t);
+extern long long wcstoll_l(const wchar_t *, wchar_t **, int, locale_t);
+extern unsigned long long wcstoull_l(const wchar_t *, wchar_t **, int, locale_t);
extern long double wcstold_l(const wchar_t *, wchar_t **, locale_t );
extern int wcscoll_l(const wchar_t *, const wchar_t *, locale_t);
diff --git a/libc/private/bionic_constants.h b/libc/private/bionic_constants.h
new file mode 100644
index 0000000..9ae1c8d
--- /dev/null
+++ b/libc/private/bionic_constants.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef _BIONIC_CONSTANTS_H_
+#define _BIONIC_CONSTANTS_H_
+
+#define NS_PER_S 1000000000
+
+#endif // _BIONIC_CONSTANTS_H_
diff --git a/libc/private/bionic_time_conversions.h b/libc/private/bionic_time_conversions.h
index 51f543f..cf0046a 100644
--- a/libc/private/bionic_time_conversions.h
+++ b/libc/private/bionic_time_conversions.h
@@ -39,6 +39,8 @@
__LIBC_HIDDEN__ void timeval_from_timespec(timeval& tv, const timespec& ts);
+__LIBC_HIDDEN__ bool timespec_from_absolute_timespec(timespec& ts, const timespec& abs_ts, clockid_t clock);
+
__END_DECLS
#endif
diff --git a/libc/upstream-netbsd/lib/libc/unistd/killpg.c b/libc/upstream-openbsd/lib/libc/compat-43/killpg.c
similarity index 80%
rename from libc/upstream-netbsd/lib/libc/unistd/killpg.c
rename to libc/upstream-openbsd/lib/libc/compat-43/killpg.c
index ceac3f4..75b1ad9 100644
--- a/libc/upstream-netbsd/lib/libc/unistd/killpg.c
+++ b/libc/upstream-openbsd/lib/libc/compat-43/killpg.c
@@ -1,8 +1,6 @@
-/* $NetBSD: killpg.c,v 1.8 2003/08/07 16:42:39 agc Exp $ */
-
/*
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,15 +27,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)killpg.c 8.1 (Berkeley) 6/2/93";
-#else
-__RCSID("$NetBSD: killpg.c,v 1.8 2003/08/07 16:42:39 agc Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
#include <sys/types.h>
#include <signal.h>
#include <errno.h>
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/ldtoa.c b/libc/upstream-openbsd/lib/libc/gdtoa/ldtoa.c
index 793d71c..16f6f9c 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/ldtoa.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/ldtoa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldtoa.c,v 1.1 2008/09/07 20:36:08 martynas Exp $ */
+/* $OpenBSD: ldtoa.c,v 1.2 2014/08/10 02:15:18 guenther Exp $ */
/*-
* Copyright (c) 2003 David Schultz <das@FreeBSD.ORG>
* All rights reserved.
@@ -30,7 +30,7 @@
#include <machine/ieee.h>
#endif /* !__vax__ */
#include <float.h>
-#include <inttypes.h>
+#include <stdint.h>
#include <limits.h>
#include <math.h>
#include <stdlib.h>
diff --git a/libc/upstream-openbsd/lib/libc/net/htonl.c b/libc/upstream-openbsd/lib/libc/net/htonl.c
index 5ab4189..6ee6e7e 100644
--- a/libc/upstream-openbsd/lib/libc/net/htonl.c
+++ b/libc/upstream-openbsd/lib/libc/net/htonl.c
@@ -1,11 +1,11 @@
-/* $OpenBSD: htonl.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
+/* $OpenBSD: htonl.c,v 1.7 2014/07/21 01:51:10 guenther Exp $ */
/*
* Written by J.T. Conklin <jtc@netbsd.org>.
* Public domain.
*/
#include <sys/types.h>
-#include <machine/endian.h>
+#include <endian.h>
#undef htonl
diff --git a/libc/upstream-openbsd/lib/libc/net/htons.c b/libc/upstream-openbsd/lib/libc/net/htons.c
index c8b73fd..f48d91e 100644
--- a/libc/upstream-openbsd/lib/libc/net/htons.c
+++ b/libc/upstream-openbsd/lib/libc/net/htons.c
@@ -1,11 +1,11 @@
-/* $OpenBSD: htons.c,v 1.8 2005/08/06 20:30:03 espie Exp $ */
+/* $OpenBSD: htons.c,v 1.9 2014/07/21 01:51:10 guenther Exp $ */
/*
* Written by J.T. Conklin <jtc@netbsd.org>.
* Public domain.
*/
#include <sys/types.h>
-#include <machine/endian.h>
+#include <endian.h>
#undef htons
diff --git a/libc/upstream-openbsd/lib/libc/net/ntohl.c b/libc/upstream-openbsd/lib/libc/net/ntohl.c
index 36414b7..0d05bac 100644
--- a/libc/upstream-openbsd/lib/libc/net/ntohl.c
+++ b/libc/upstream-openbsd/lib/libc/net/ntohl.c
@@ -1,11 +1,11 @@
-/* $OpenBSD: ntohl.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
+/* $OpenBSD: ntohl.c,v 1.7 2014/07/21 01:51:10 guenther Exp $ */
/*
* Written by J.T. Conklin <jtc@netbsd.org>.
* Public domain.
*/
#include <sys/types.h>
-#include <machine/endian.h>
+#include <endian.h>
#undef ntohl
diff --git a/libc/upstream-openbsd/lib/libc/net/ntohs.c b/libc/upstream-openbsd/lib/libc/net/ntohs.c
index 8f345e8..b5ea361 100644
--- a/libc/upstream-openbsd/lib/libc/net/ntohs.c
+++ b/libc/upstream-openbsd/lib/libc/net/ntohs.c
@@ -1,11 +1,11 @@
-/* $OpenBSD: ntohs.c,v 1.8 2005/08/06 20:30:03 espie Exp $ */
+/* $OpenBSD: ntohs.c,v 1.9 2014/07/21 01:51:10 guenther Exp $ */
/*
* Written by J.T. Conklin <jtc@netbsd.org>.
* Public domain.
*/
#include <sys/types.h>
-#include <machine/endian.h>
+#include <endian.h>
#undef ntohs
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fdopen.c b/libc/upstream-openbsd/lib/libc/stdio/fdopen.c
index 3e47f2c..1c0c813 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fdopen.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fdopen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fdopen.c,v 1.6 2008/04/21 12:28:35 otto Exp $ */
+/* $OpenBSD: fdopen.c,v 1.7 2014/08/31 02:21:18 guenther Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -66,6 +66,7 @@
if ((fp = __sfp()) == NULL)
return (NULL);
fp->_flags = flags;
+
/*
* If opened for appending, but underlying descriptor does not have
* O_APPEND bit set, assert __SAPP so that __swrite() will lseek to
@@ -73,6 +74,13 @@
*/
if ((oflags & O_APPEND) && !(fdflags & O_APPEND))
fp->_flags |= __SAPP;
+
+ /*
+ * If close-on-exec was requested, then turn it on if not already
+ */
+ if ((oflags & O_CLOEXEC) && !((tmp = fcntl(fd, F_GETFD)) & FD_CLOEXEC))
+ fcntl(fd, F_SETFD, tmp | FD_CLOEXEC);
+
fp->_file = fd;
fp->_cookie = fp;
fp->_read = __sread;
diff --git a/libc/upstream-freebsd/lib/libc/stdio/flags.c b/libc/upstream-openbsd/lib/libc/stdio/flags.c
similarity index 77%
rename from libc/upstream-freebsd/lib/libc/stdio/flags.c
rename to libc/upstream-openbsd/lib/libc/stdio/flags.c
index 1878c2f..d6df6da 100644
--- a/libc/upstream-freebsd/lib/libc/stdio/flags.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/flags.c
@@ -1,3 +1,4 @@
+/* $OpenBSD: flags.c,v 1.8 2014/08/31 02:21:18 guenther Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,22 +31,15 @@
* SUCH DAMAGE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)flags.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/file.h>
#include <stdio.h>
#include <errno.h>
-
#include "local.h"
/*
* Return the (stdio) flags for a given mode. Store the flags
- * to be passed to an _open() syscall through *optr.
+ * to be passed to an open() syscall through *optr.
* Return 0 on error.
*/
int
@@ -78,34 +72,33 @@
return (0);
}
- /* 'b' (binary) is ignored */
- if (*mode == 'b')
- mode++;
-
- /* [rwa][b]\+ means read and write */
- if (*mode == '+') {
- mode++;
- ret = __SRW;
- m = O_RDWR;
- }
-
- /* 'b' (binary) can appear here, too -- and is ignored again */
- if (*mode == 'b')
- mode++;
-
- /* 'x' means exclusive (fail if the file exists) */
- if (*mode == 'x') {
- mode++;
- if (m == O_RDONLY) {
+ while (*mode != '\0')
+ switch (*mode++) {
+ case 'b':
+ break;
+ case '+':
+ ret = __SRW;
+ m = O_RDWR;
+ break;
+ case 'e':
+ o |= O_CLOEXEC;
+ break;
+ case 'x':
+ if (o & O_CREAT)
+ o |= O_EXCL;
+ break;
+ default:
+ /*
+ * Lots of software passes other extension mode
+ * letters, like Window's 't'
+ */
+#if 0
errno = EINVAL;
return (0);
+#else
+ break;
+#endif
}
- o |= O_EXCL;
- }
-
- /* set close-on-exec */
- if (*mode == 'e')
- o |= O_CLOEXEC;
*optr = m | o;
return (ret);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/freopen.c b/libc/upstream-openbsd/lib/libc/stdio/freopen.c
index 3158fb1..82717b1 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/freopen.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/freopen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: freopen.c,v 1.13 2009/11/09 00:18:27 kurt Exp $ */
+/* $OpenBSD: freopen.c,v 1.14 2014/08/31 02:21:18 guenther Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -134,7 +134,7 @@
* assume stderr is always fd STDERR_FILENO, even if being freopen'd.
*/
if (wantfd >= 0 && f != wantfd) {
- if (dup2(f, wantfd) >= 0) {
+ if (dup3(f, wantfd, oflags & O_CLOEXEC) >= 0) {
(void) close(f);
f = wantfd;
}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/mktemp.c b/libc/upstream-openbsd/lib/libc/stdio/mktemp.c
index cb154c4..2a17e52 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/mktemp.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/mktemp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mktemp.c,v 1.33 2014/05/06 22:55:27 millert Exp $ */
+/* $OpenBSD: mktemp.c,v 1.34 2014/08/31 02:21:18 guenther Exp $ */
/*
* Copyright (c) 1996-1998, 2008 Theo de Raadt
* Copyright (c) 1997, 2008-2009 Todd C. Miller
@@ -35,12 +35,14 @@
#define NUM_CHARS (sizeof(TEMPCHARS) - 1)
#define MIN_X 6
+#define MKOTEMP_FLAGS (O_APPEND | O_CLOEXEC | O_DSYNC | O_RSYNC | O_SYNC)
+
#ifndef nitems
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
#endif
static int
-mktemp_internal(char *path, int slen, int mode)
+mktemp_internal(char *path, int slen, int mode, int flags)
{
char *start, *cp, *ep;
const char *tempchars = TEMPCHARS;
@@ -63,6 +65,12 @@
return(-1);
}
+ if (flags & ~MKOTEMP_FLAGS) {
+ errno = EINVAL;
+ return(-1);
+ }
+ flags |= O_CREAT | O_EXCL | O_RDWR;
+
tries = INT_MAX;
do {
cp = start;
@@ -85,7 +93,7 @@
return(errno == ENOENT ? 0 : -1);
break;
case MKTEMP_FILE:
- fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
+ fd = open(path, flags, S_IRUSR|S_IWUSR);
if (fd != -1 || errno != EEXIST)
return(fd);
break;
@@ -107,7 +115,7 @@
char *
_mktemp(char *path)
{
- if (mktemp_internal(path, 0, MKTEMP_NAME) == -1)
+ if (mktemp_internal(path, 0, MKTEMP_NAME, 0) == -1)
return(NULL);
return(path);
}
@@ -122,15 +130,27 @@
}
int
+mkostemps(char *path, int slen, int flags)
+{
+ return(mktemp_internal(path, slen, MKTEMP_FILE, flags));
+}
+
+int
mkstemp(char *path)
{
- return(mktemp_internal(path, 0, MKTEMP_FILE));
+ return(mktemp_internal(path, 0, MKTEMP_FILE, 0));
+}
+
+int
+mkostemp(char *path, int flags)
+{
+ return(mktemp_internal(path, 0, MKTEMP_FILE, flags));
}
int
mkstemps(char *path, int slen)
{
- return(mktemp_internal(path, slen, MKTEMP_FILE));
+ return(mktemp_internal(path, slen, MKTEMP_FILE, 0));
}
char *
@@ -138,6 +158,6 @@
{
int error;
- error = mktemp_internal(path, 0, MKTEMP_DIR);
+ error = mktemp_internal(path, 0, MKTEMP_DIR, 0);
return(error ? NULL : path);
}
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/insque.c b/libc/upstream-openbsd/lib/libc/stdlib/insque.c
similarity index 81%
rename from libc/upstream-netbsd/lib/libc/stdlib/insque.c
rename to libc/upstream-openbsd/lib/libc/stdlib/insque.c
index 09020ae..590ff83 100644
--- a/libc/upstream-netbsd/lib/libc/stdlib/insque.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/insque.c
@@ -1,7 +1,9 @@
+/* $OpenBSD: insque.c,v 1.3 2014/08/15 04:14:36 guenther Exp $ */
+
/*
* Copyright (c) 1993 John Brezak
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -12,7 +14,7 @@
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may be used to endorse or promote products
* derived from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -26,12 +28,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: insque.c,v 1.3 2012/06/25 22:32:45 abs Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#include <assert.h>
+#include <stdlib.h>
#include <search.h>
struct qelem {
@@ -42,17 +39,16 @@
void
insque(void *entry, void *pred)
{
- struct qelem *e = (struct qelem *) entry;
- struct qelem *p = (struct qelem *) pred;
+ struct qelem *e = entry;
+ struct qelem *p = pred;
- _DIAGASSERT(e != 0);
-
- e->q_back = p;
- if (p) {
+ if (p == NULL)
+ e->q_forw = e->q_back = NULL;
+ else {
e->q_forw = p->q_forw;
- if (p->q_forw)
+ e->q_back = p;
+ if (p->q_forw != NULL)
p->q_forw->q_back = e;
p->q_forw = e;
- } else
- e->q_forw = 0;
+ }
}
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/remque.c b/libc/upstream-openbsd/lib/libc/stdlib/remque.c
similarity index 84%
rename from libc/upstream-netbsd/lib/libc/stdlib/remque.c
rename to libc/upstream-openbsd/lib/libc/stdlib/remque.c
index 6060ad8..71b74b2 100644
--- a/libc/upstream-netbsd/lib/libc/stdlib/remque.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/remque.c
@@ -1,7 +1,9 @@
+/* $OpenBSD: remque.c,v 1.3 2014/08/15 04:14:36 guenther Exp $ */
+
/*
* Copyright (c) 1993 John Brezak
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -12,7 +14,7 @@
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may be used to endorse or promote products
* derived from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -26,12 +28,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: remque.c,v 1.3 2012/06/25 22:32:45 abs Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#include <assert.h>
+#include <stdlib.h>
#include <search.h>
struct qelem {
@@ -42,12 +39,10 @@
void
remque(void *element)
{
- struct qelem *e = (struct qelem *) element;
+ struct qelem *e = element;
- _DIAGASSERT(e != 0);
-
- if (e->q_forw)
+ if (e->q_forw != NULL)
e->q_forw->q_back = e->q_back;
- if (e->q_back)
+ if (e->q_back != NULL)
e->q_back->q_forw = e->q_forw;
}
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/strtoimax.c b/libc/upstream-openbsd/lib/libc/stdlib/strtoimax.c
index 2c77f41..2fc04e4 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/strtoimax.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/strtoimax.c
@@ -1,6 +1,5 @@
-/* $OpenBSD: strtoimax.c,v 1.1 2006/01/13 17:58:09 millert Exp $ */
-
-/*-
+/* $OpenBSD: strtoimax.c,v 1.2 2014/09/13 20:10:12 schwarze Exp $ */
+/*
* Copyright (c) 1992 The Regents of the University of California.
* All rights reserved.
*
@@ -48,6 +47,17 @@
int neg, any, cutlim;
/*
+ * Ensure that base is between 2 and 36 inclusive, or the special
+ * value of 0.
+ */
+ if (base < 0 || base == 1 || base > 36) {
+ if (endptr != 0)
+ *endptr = (char *)nptr;
+ errno = EINVAL;
+ return 0;
+ }
+
+ /*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
* assume decimal; if base is already 16, allow 0x.
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/strtol.c b/libc/upstream-openbsd/lib/libc/stdlib/strtol.c
index dc2cf88..86cec35 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/strtol.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/strtol.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: strtol.c,v 1.9 2013/04/17 17:40:35 tedu Exp $ */
-/*-
+/* $OpenBSD: strtol.c,v 1.10 2014/09/13 20:10:12 schwarze Exp $ */
+/*
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
@@ -33,7 +33,6 @@
#include <limits.h>
#include <stdlib.h>
-
/*
* Convert a string to a long integer.
*
@@ -52,7 +51,7 @@
* Ensure that base is between 2 and 36 inclusive, or the special
* value of 0.
*/
- if (base != 0 && (base < 2 || base > 36)) {
+ if (base < 0 || base == 1 || base > 36) {
if (endptr != 0)
*endptr = (char *)nptr;
errno = EINVAL;
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/strtoll.c b/libc/upstream-openbsd/lib/libc/stdlib/strtoll.c
index 4bcc556..cf82c8e 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/strtoll.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/strtoll.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: strtoll.c,v 1.7 2013/03/28 18:09:38 martynas Exp $ */
-/*-
+/* $OpenBSD: strtoll.c,v 1.8 2014/09/13 20:10:12 schwarze Exp $ */
+/*
* Copyright (c) 1992 The Regents of the University of California.
* All rights reserved.
*
@@ -50,6 +50,17 @@
int neg, any, cutlim;
/*
+ * Ensure that base is between 2 and 36 inclusive, or the special
+ * value of 0.
+ */
+ if (base < 0 || base == 1 || base > 36) {
+ if (endptr != 0)
+ *endptr = (char *)nptr;
+ errno = EINVAL;
+ return 0;
+ }
+
+ /*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
* assume decimal; if base is already 16, allow 0x.
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/strtoul.c b/libc/upstream-openbsd/lib/libc/stdlib/strtoul.c
index a236365..2aa41b7 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/strtoul.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/strtoul.c
@@ -1,6 +1,6 @@
-/* $OpenBSD: strtoul.c,v 1.8 2013/04/17 17:40:35 tedu Exp $ */
+/* $OpenBSD: strtoul.c,v 1.9 2014/09/13 20:10:12 schwarze Exp $ */
/*
- * Copyright (c) 1990 Regents of the University of California.
+ * Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -50,6 +50,13 @@
/*
* See strtol for comments as to the logic used.
*/
+ if (base < 0 || base == 1 || base > 36) {
+ if (endptr != 0)
+ *endptr = (char *)nptr;
+ errno = EINVAL;
+ return 0;
+ }
+
s = nptr;
do {
c = (unsigned char) *s++;
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/strtoull.c b/libc/upstream-openbsd/lib/libc/stdlib/strtoull.c
index 28f613a..8464176 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/strtoull.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/strtoull.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: strtoull.c,v 1.6 2013/03/28 18:09:38 martynas Exp $ */
-/*-
+/* $OpenBSD: strtoull.c,v 1.7 2014/09/13 20:10:12 schwarze Exp $ */
+/*
* Copyright (c) 1992 The Regents of the University of California.
* All rights reserved.
*
@@ -50,8 +50,15 @@
int neg, any, cutlim;
/*
- * See strtoq for comments as to the logic used.
+ * See strtoll for comments as to the logic used.
*/
+ if (base < 0 || base == 1 || base > 36) {
+ if (endptr != 0)
+ *endptr = (char *)nptr;
+ errno = EINVAL;
+ return 0;
+ }
+
s = nptr;
do {
c = (unsigned char) *s++;
@@ -59,7 +66,7 @@
if (c == '-') {
neg = 1;
c = *s++;
- } else {
+ } else {
neg = 0;
if (c == '+')
c = *s++;
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/strtoumax.c b/libc/upstream-openbsd/lib/libc/stdlib/strtoumax.c
index ce6e2c0..c73f7e5 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/strtoumax.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/strtoumax.c
@@ -1,6 +1,5 @@
-/* $OpenBSD: strtoumax.c,v 1.1 2006/01/13 17:58:09 millert Exp $ */
-
-/*-
+/* $OpenBSD: strtoumax.c,v 1.2 2014/09/13 20:10:12 schwarze Exp $ */
+/*
* Copyright (c) 1992 The Regents of the University of California.
* All rights reserved.
*
@@ -48,8 +47,15 @@
int neg, any, cutlim;
/*
- * See strtoq for comments as to the logic used.
+ * See strtoimax for comments as to the logic used.
*/
+ if (base < 0 || base == 1 || base > 36) {
+ if (endptr != 0)
+ *endptr = (char *)nptr;
+ errno = EINVAL;
+ return 0;
+ }
+
s = nptr;
do {
c = (unsigned char) *s++;
@@ -57,7 +63,7 @@
if (c == '-') {
neg = 1;
c = *s++;
- } else {
+ } else {
neg = 0;
if (c == '+')
c = *s++;
diff --git a/linker/debugger.cpp b/linker/debugger.cpp
index 6565985..ac466a5 100644
--- a/linker/debugger.cpp
+++ b/linker/debugger.cpp
@@ -215,7 +215,7 @@
return;
}
- int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM);
+ int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM | SOCK_CLOEXEC);
if (s == -1) {
__libc_format_log(ANDROID_LOG_FATAL, "libc", "Unable to open connection to debuggerd: %s",
strerror(errno));
diff --git a/tests/Android.mk b/tests/Android.mk
index 890e203..59fe57d 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -86,6 +86,7 @@
regex_test.cpp \
sched_test.cpp \
search_test.cpp \
+ semaphore_test.cpp \
signal_test.cpp \
stack_protector_test.cpp \
stdatomic_test.cpp \
diff --git a/tests/TemporaryFile.h b/tests/TemporaryFile.h
index c4ee2d5..5c2fe4f 100644
--- a/tests/TemporaryFile.h
+++ b/tests/TemporaryFile.h
@@ -17,24 +17,26 @@
#include <fcntl.h>
#include <unistd.h>
-template<int (*mk_fn)(char*)>
+#include "private/bionic_macros.h"
+
+template <typename T = int (*)(char*)>
class GenericTemporaryFile {
public:
- GenericTemporaryFile(const char* dirpath = NULL) {
- if (dirpath != NULL) {
- init(dirpath);
- } else {
- // Since we might be running on the host or the target, and if we're
- // running on the host we might be running under bionic or glibc,
- // let's just try both possible temporary directories and take the
- // first one that works.
- init("/data/local/tmp");
- if (fd == -1) {
- init("/tmp");
- }
+ GenericTemporaryFile(T mk_fn = mkstemp) : mk_fn(mk_fn) {
+ // Since we might be running on the host or the target, and if we're
+ // running on the host we might be running under bionic or glibc,
+ // let's just try both possible temporary directories and take the
+ // first one that works.
+ init("/data/local/tmp");
+ if (fd == -1) {
+ init("/tmp");
}
}
+ GenericTemporaryFile(const char* dirpath, T mk_fn = mkstemp) : mk_fn(mk_fn) {
+ init(dirpath);
+ }
+
~GenericTemporaryFile() {
close(fd);
unlink(filename);
@@ -49,13 +51,17 @@
char filename[1024];
private:
+ T mk_fn;
+
void init(const char* tmp_dir) {
snprintf(filename, sizeof(filename), "%s/TemporaryFile-XXXXXX", tmp_dir);
fd = mk_fn(filename);
}
+
+ DISALLOW_COPY_AND_ASSIGN(GenericTemporaryFile);
};
-typedef GenericTemporaryFile<mkstemp> TemporaryFile;
+typedef GenericTemporaryFile<> TemporaryFile;
class TemporaryDir {
public:
@@ -77,4 +83,5 @@
return (mkdtemp(dirname) != NULL);
}
+ DISALLOW_COPY_AND_ASSIGN(TemporaryDir);
};
diff --git a/tests/ftw_test.cpp b/tests/ftw_test.cpp
index 6d3a308..7ffbfe0 100644
--- a/tests/ftw_test.cpp
+++ b/tests/ftw_test.cpp
@@ -68,7 +68,7 @@
TEST(ftw, ftw64) {
TemporaryDir td;
- GenericTemporaryFile<mkstemp64> tf(td.dirname);
+ TemporaryFile tf(td.dirname, mkstemp64);
ftw64(td.dirname, check_ftw64, 1);
}
@@ -80,6 +80,6 @@
TEST(ftw, nftw64) {
TemporaryDir td;
- GenericTemporaryFile<mkstemp64> tf(td.dirname);
+ TemporaryFile tf(td.dirname, mkstemp64);
nftw64(td.dirname, check_nftw64, 1, 0);
}
diff --git a/tests/inttypes_test.cpp b/tests/inttypes_test.cpp
index e588503..dbbb6d4 100644
--- a/tests/inttypes_test.cpp
+++ b/tests/inttypes_test.cpp
@@ -14,11 +14,12 @@
* limitations under the License.
*/
-#include <gtest/gtest.h>
-
-#include <stdio.h>
#include <inttypes.h>
+#include <errno.h>
+#include <gtest/gtest.h>
+#include <stdio.h>
+
TEST(inttypes, misc) {
char buf[512];
@@ -46,3 +47,51 @@
TEST(inttypes, wcstoumax) {
ASSERT_EQ(123U, wcstoumax(L"123", NULL, 10));
}
+
+TEST(inttypes, strtoimax_EINVAL) {
+ errno = 0;
+ strtoimax("123", NULL, -1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ strtoimax("123", NULL, 1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ strtoimax("123", NULL, 37);
+ ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(inttypes, strtoumax_EINVAL) {
+ errno = 0;
+ strtoumax("123", NULL, -1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ strtoumax("123", NULL, 1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ strtoumax("123", NULL, 37);
+ ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(inttypes, wcstoimax_EINVAL) {
+ errno = 0;
+ wcstoimax(L"123", NULL, -1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ wcstoimax(L"123", NULL, 1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ wcstoimax(L"123", NULL, 37);
+ ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(inttypes, wcstoumax_EINVAL) {
+ errno = 0;
+ wcstoumax(L"123", NULL, -1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ wcstoumax(L"123", NULL, 1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ wcstoumax(L"123", NULL, 37);
+ ASSERT_EQ(EINVAL, errno);
+}
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 43587f4..9dbb4f5 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -168,8 +168,7 @@
static void MakeDeadThread(pthread_t& t) {
ASSERT_EQ(0, pthread_create(&t, NULL, IdFn, NULL));
- void* result;
- ASSERT_EQ(0, pthread_join(t, &result));
+ ASSERT_EQ(0, pthread_join(t, NULL));
}
TEST(pthread, pthread_create) {
@@ -201,8 +200,7 @@
AssertDetached(t1, true);
// ...pthread_join should fail.
- void* result;
- ASSERT_EQ(EINVAL, pthread_join(t1, &result));
+ ASSERT_EQ(EINVAL, pthread_join(t1, NULL));
}
TEST(pthread, pthread_no_op_detach_after_join) {
@@ -230,8 +228,7 @@
}
TEST(pthread, pthread_join_self) {
- void* result;
- ASSERT_EQ(EDEADLK, pthread_join(pthread_self(), &result));
+ ASSERT_EQ(EDEADLK, pthread_join(pthread_self(), NULL));
}
struct TestBug37410 {
@@ -481,8 +478,7 @@
pthread_t dead_thread;
MakeDeadThread(dead_thread);
- void* result;
- ASSERT_EQ(ESRCH, pthread_join(dead_thread, &result));
+ ASSERT_EQ(ESRCH, pthread_join(dead_thread, NULL));
}
TEST(pthread, pthread_kill__no_such_thread) {
@@ -543,8 +539,7 @@
size_t result;
pthread_t t;
pthread_create(&t, &attributes, GetActualGuardSizeFn, &result);
- void* join_result;
- pthread_join(t, &join_result);
+ pthread_join(t, NULL);
return result;
}
@@ -559,8 +554,7 @@
size_t result;
pthread_t t;
pthread_create(&t, &attributes, GetActualStackSizeFn, &result);
- void* join_result;
- pthread_join(t, &join_result);
+ pthread_join(t, NULL);
return result;
}
@@ -927,11 +921,47 @@
pid_t t_pthread_gettid_np_result = pthread_gettid_np(t);
- void* join_result;
- pthread_join(t, &join_result);
+ pthread_join(t, NULL);
ASSERT_EQ(t_gettid_result, t_pthread_gettid_np_result);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
+
+static size_t cleanup_counter = 0;
+
+void AbortCleanupRoutine(void*) {
+ abort();
+}
+
+void CountCleanupRoutine(void*) {
+ ++cleanup_counter;
+}
+
+void PthreadCleanupTester() {
+ pthread_cleanup_push(CountCleanupRoutine, NULL);
+ pthread_cleanup_push(CountCleanupRoutine, NULL);
+ pthread_cleanup_push(AbortCleanupRoutine, NULL);
+
+ pthread_cleanup_pop(0); // Pop the abort without executing it.
+ pthread_cleanup_pop(1); // Pop one count while executing it.
+ ASSERT_EQ(1U, cleanup_counter);
+ // Exit while the other count is still on the cleanup stack.
+ pthread_exit(NULL);
+
+ // Calls to pthread_cleanup_pop/pthread_cleanup_push must always be balanced.
+ pthread_cleanup_pop(0);
+}
+
+void* PthreadCleanupStartRoutine(void*) {
+ PthreadCleanupTester();
+ return NULL;
+}
+
+TEST(pthread, pthread_cleanup_push__pthread_cleanup_pop) {
+ pthread_t t;
+ ASSERT_EQ(0, pthread_create(&t, NULL, PthreadCleanupStartRoutine, NULL));
+ pthread_join(t, NULL);
+ ASSERT_EQ(2U, cleanup_counter);
+}
diff --git a/tests/semaphore_test.cpp b/tests/semaphore_test.cpp
new file mode 100644
index 0000000..e517f81
--- /dev/null
+++ b/tests/semaphore_test.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include <semaphore.h>
+
+#include <errno.h>
+#include <gtest/gtest.h>
+#include <limits.h>
+#include <pthread.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "private/bionic_constants.h"
+
+TEST(semaphore, sem_init) {
+ sem_t s;
+
+ // Perfectly fine initial values.
+ ASSERT_EQ(0, sem_init(&s, 0, 0));
+ ASSERT_EQ(0, sem_init(&s, 0, 1));
+ ASSERT_EQ(0, sem_init(&s, 0, 123));
+
+ // Too small an initial value.
+ errno = 0;
+ ASSERT_EQ(-1, sem_init(&s, 0, -1));
+ ASSERT_EQ(EINVAL, errno);
+
+ ASSERT_EQ(SEM_VALUE_MAX, sysconf(_SC_SEM_VALUE_MAX));
+
+ // The largest initial value.
+ ASSERT_EQ(0, sem_init(&s, 0, SEM_VALUE_MAX));
+
+ // Too large an initial value.
+ errno = 0;
+ ASSERT_EQ(-1, sem_init(&s, 0, SEM_VALUE_MAX + 1));
+ ASSERT_EQ(EINVAL, errno);
+
+ ASSERT_EQ(0, sem_destroy(&s));
+}
+
+TEST(semaphore, sem_trywait) {
+ sem_t s;
+ ASSERT_EQ(0, sem_init(&s, 0, 3));
+ ASSERT_EQ(0, sem_trywait(&s));
+ ASSERT_EQ(0, sem_trywait(&s));
+ ASSERT_EQ(0, sem_trywait(&s));
+ errno = 0;
+ ASSERT_EQ(-1, sem_trywait(&s));
+ ASSERT_EQ(EAGAIN, errno);
+ ASSERT_EQ(0, sem_destroy(&s));
+}
+
+static void SemWaitThreadTestFn(sem_t& sem) {
+ ASSERT_EQ(0, sem_wait(&sem));
+}
+
+static void* SemWaitThreadFn(void* arg) {
+ SemWaitThreadTestFn(*reinterpret_cast<sem_t*>(arg));
+ return nullptr;
+}
+
+TEST(semaphore, sem_wait__sem_post) {
+ sem_t s;
+ ASSERT_EQ(0, sem_init(&s, 0, 0));
+
+ pthread_t t1, t2, t3;
+ ASSERT_EQ(0, pthread_create(&t1, NULL, SemWaitThreadFn, &s));
+ ASSERT_EQ(0, pthread_create(&t2, NULL, SemWaitThreadFn, &s));
+ ASSERT_EQ(0, pthread_create(&t3, NULL, SemWaitThreadFn, &s));
+
+ ASSERT_EQ(0, sem_post(&s));
+ ASSERT_EQ(0, sem_post(&s));
+ ASSERT_EQ(0, sem_post(&s));
+
+ void* result;
+ ASSERT_EQ(0, pthread_join(t1, &result));
+ ASSERT_EQ(0, pthread_join(t2, &result));
+ ASSERT_EQ(0, pthread_join(t3, &result));
+}
+
+static inline void timespec_add_ms(timespec& ts, size_t ms) {
+ ts.tv_sec += ms / 1000;
+ ts.tv_nsec += (ms % 1000) * 1000000;
+ if (ts.tv_nsec >= NS_PER_S) {
+ ts.tv_sec++;
+ ts.tv_nsec -= NS_PER_S;
+ }
+}
+
+TEST(semaphore, sem_timedwait) {
+ sem_t s;
+ ASSERT_EQ(0, sem_init(&s, 0, 0));
+
+ timespec ts;
+ ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &ts));
+ timespec_add_ms(ts, 100);
+
+ errno = 0;
+ ASSERT_EQ(-1, sem_timedwait(&s, &ts));
+ ASSERT_EQ(ETIMEDOUT, errno);
+
+ // A negative timeout is an error.
+ errno = 0;
+ ts.tv_nsec = -1;
+ ASSERT_EQ(-1, sem_timedwait(&s, &ts));
+ ASSERT_EQ(EINVAL, errno);
+
+ ASSERT_EQ(0, sem_destroy(&s));
+}
+
+TEST(semaphore, sem_getvalue) {
+ sem_t s;
+ ASSERT_EQ(0, sem_init(&s, 0, 0));
+
+ int i;
+ ASSERT_EQ(0, sem_getvalue(&s, &i));
+ ASSERT_EQ(0, i);
+
+ ASSERT_EQ(0, sem_post(&s));
+ ASSERT_EQ(0, sem_getvalue(&s, &i));
+ ASSERT_EQ(1, i);
+
+ ASSERT_EQ(0, sem_post(&s));
+ ASSERT_EQ(0, sem_getvalue(&s, &i));
+ ASSERT_EQ(2, i);
+
+ ASSERT_EQ(0, sem_wait(&s));
+ ASSERT_EQ(0, sem_getvalue(&s, &i));
+ ASSERT_EQ(1, i);
+}
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index c01ab68..6a653b4 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -756,3 +756,43 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
+
+TEST(stdio, fdopen_CLOEXEC) {
+ int fd = open("/proc/version", O_RDONLY);
+ ASSERT_TRUE(fd != -1);
+
+ // This fd doesn't have O_CLOEXEC...
+ int flags = fcntl(fd, F_GETFD);
+ ASSERT_TRUE(flags != -1);
+ ASSERT_EQ(0, flags & FD_CLOEXEC);
+
+ FILE* fp = fdopen(fd, "re");
+ ASSERT_TRUE(fp != NULL);
+
+ // ...but the new one does.
+ flags = fcntl(fileno(fp), F_GETFD);
+ ASSERT_TRUE(flags != -1);
+ ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
+
+ fclose(fp);
+ close(fd);
+}
+
+TEST(stdio, freopen_CLOEXEC) {
+ FILE* fp = fopen("/proc/version", "r");
+ ASSERT_TRUE(fp != NULL);
+
+ // This FILE* doesn't have O_CLOEXEC...
+ int flags = fcntl(fileno(fp), F_GETFD);
+ ASSERT_TRUE(flags != -1);
+ ASSERT_EQ(0, flags & FD_CLOEXEC);
+
+ fp = freopen("/proc/version", "re", fp);
+
+ // ...but the new one does.
+ flags = fcntl(fileno(fp), F_GETFD);
+ ASSERT_TRUE(flags != -1);
+ ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
+
+ fclose(fp);
+}
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 553f018..e814ef7 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -162,19 +162,33 @@
ASSERT_EXIT(TestBug57421_main(), ::testing::ExitedWithCode(0), "");
}
+TEST(stdlib, mkostemp64) {
+ TemporaryFile tf([](char* path) { return mkostemp64(path, O_CLOEXEC); });
+ int flags = fcntl(tf.fd, F_GETFD);
+ ASSERT_TRUE(flags != -1);
+ ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
+}
+
+TEST(stdlib, mkostemp) {
+ TemporaryFile tf([](char* path) { return mkostemp(path, O_CLOEXEC); });
+ int flags = fcntl(tf.fd, F_GETFD);
+ ASSERT_TRUE(flags != -1);
+ ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
+}
+
+TEST(stdlib, mkstemp64) {
+ TemporaryFile tf(mkstemp64);
+ struct stat64 sb;
+ ASSERT_EQ(0, fstat64(tf.fd, &sb));
+ ASSERT_EQ(O_LARGEFILE, fcntl(tf.fd, F_GETFL) & O_LARGEFILE);
+}
+
TEST(stdlib, mkstemp) {
TemporaryFile tf;
struct stat sb;
ASSERT_EQ(0, fstat(tf.fd, &sb));
}
-TEST(stdlib, mkstemp64) {
- GenericTemporaryFile<mkstemp64> tf;
- struct stat64 sb;
- ASSERT_EQ(0, fstat64(tf.fd, &sb));
- ASSERT_EQ(O_LARGEFILE, fcntl(tf.fd, F_GETFL) & O_LARGEFILE);
-}
-
TEST(stdlib, system) {
int status;
@@ -361,3 +375,51 @@
ASSERT_EQ(ENOTTY, errno);
close(fd);
}
+
+TEST(stdlib, strtol_EINVAL) {
+ errno = 0;
+ strtol("123", NULL, -1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ strtol("123", NULL, 1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ strtol("123", NULL, 37);
+ ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(stdlib, strtoll_EINVAL) {
+ errno = 0;
+ strtoll("123", NULL, -1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ strtoll("123", NULL, 1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ strtoll("123", NULL, 37);
+ ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(stdlib, strtoul_EINVAL) {
+ errno = 0;
+ strtoul("123", NULL, -1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ strtoul("123", NULL, 1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ strtoul("123", NULL, 37);
+ ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(stdlib, strtoull_EINVAL) {
+ errno = 0;
+ strtoull("123", NULL, -1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ strtoull("123", NULL, 1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ strtoull("123", NULL, 37);
+ ASSERT_EQ(EINVAL, errno);
+}
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index c9ead8d..c631b6a 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -26,6 +26,8 @@
#include "ScopedSignalHandler.h"
+#include "private/bionic_constants.h"
+
TEST(time, gmtime) {
time_t t = 0;
tm* broken_down = gmtime(&t);
@@ -395,7 +397,7 @@
ts2.tv_nsec -= ts1.tv_nsec;
if (ts2.tv_nsec < 0) {
--ts2.tv_sec;
- ts2.tv_nsec += 1000000000;
+ ts2.tv_nsec += NS_PER_S;
}
// Should be less than (a very generous, to try to avoid flakiness) 1000000ns.
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 8195ea8..21c14f4 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -462,3 +462,8 @@
ASSERT_EQ(0, pthread_join(t, &result));
ASSERT_EQ(NULL, result);
}
+
+TEST(unistd_DeathTest, abort) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ ASSERT_EXIT(abort(), testing::KilledBySignal(SIGABRT), "");
+}
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index 760475f..887266c 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -520,3 +520,75 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
+
+TEST(wchar, wcstol_EINVAL) {
+ errno = 0;
+ wcstol(L"123", NULL, -1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ wcstol(L"123", NULL, 1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ wcstol(L"123", NULL, 37);
+ ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(wchar, wcstoll_EINVAL) {
+ errno = 0;
+ wcstoll(L"123", NULL, -1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ wcstoll(L"123", NULL, 1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ wcstoll(L"123", NULL, 37);
+ ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(wchar, wcstoul_EINVAL) {
+ errno = 0;
+ wcstoul(L"123", NULL, -1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ wcstoul(L"123", NULL, 1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ wcstoul(L"123", NULL, 37);
+ ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(wchar, wcstoull_EINVAL) {
+ errno = 0;
+ wcstoull(L"123", NULL, -1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ wcstoull(L"123", NULL, 1);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ wcstoull(L"123", NULL, 37);
+ ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(wchar, wcstoll_l_EINVAL) {
+ errno = 0;
+ wcstoll_l(L"123", NULL, -1, LC_GLOBAL_LOCALE);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ wcstoll_l(L"123", NULL, 1, LC_GLOBAL_LOCALE);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ wcstoll_l(L"123", NULL, 37, LC_GLOBAL_LOCALE);
+ ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(wchar, wcstoull_l_EINVAL) {
+ errno = 0;
+ wcstoull_l(L"123", NULL, -1, LC_GLOBAL_LOCALE);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ wcstoull_l(L"123", NULL, 1, LC_GLOBAL_LOCALE);
+ ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ wcstoull_l(L"123", NULL, 37, LC_GLOBAL_LOCALE);
+ ASSERT_EQ(EINVAL, errno);
+}