summaryrefslogtreecommitdiffstats
path: root/libcutils
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:29:04 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:29:04 -0800
commite54eebbf1a908d65ee8cf80bab62821c05666d70 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /libcutils
parenta1e1c1b106423de09bc918502e7a51d4ffe5a4ae (diff)
downloadsystem_core-e54eebbf1a908d65ee8cf80bab62821c05666d70.tar.gz
system_core-e54eebbf1a908d65ee8cf80bab62821c05666d70.tar.bz2
system_core-e54eebbf1a908d65ee8cf80bab62821c05666d70.zip
auto import from //depot/cupcake/@135843
Diffstat (limited to 'libcutils')
-rw-r--r--libcutils/Android.mk113
-rw-r--r--libcutils/MODULE_LICENSE_APACHE20
-rw-r--r--libcutils/NOTICE190
-rw-r--r--libcutils/adb_networking.c172
-rw-r--r--libcutils/array.c155
-rw-r--r--libcutils/ashmem-dev.c85
-rw-r--r--libcutils/ashmem-host.c94
-rw-r--r--libcutils/atomic-android-arm.S274
-rw-r--r--libcutils/atomic-android-armv6.S169
-rw-r--r--libcutils/atomic.c335
-rw-r--r--libcutils/buffer.c116
-rw-r--r--libcutils/buffer.h112
-rw-r--r--libcutils/config_utils.c317
-rw-r--r--libcutils/cpu_info.c83
-rw-r--r--libcutils/dir_hash.c334
-rw-r--r--libcutils/dlmalloc_stubs.c29
-rw-r--r--libcutils/fdevent.c506
-rw-r--r--libcutils/hashmap.c350
-rw-r--r--libcutils/load_file.c51
-rw-r--r--libcutils/loghack.h38
-rw-r--r--libcutils/memory.c87
-rw-r--r--libcutils/memset32.S93
-rw-r--r--libcutils/mq.c1357
-rw-r--r--libcutils/mspace.c246
-rw-r--r--libcutils/private.h368
-rw-r--r--libcutils/process_name.c75
-rw-r--r--libcutils/properties.c368
-rw-r--r--libcutils/record_stream.c186
-rw-r--r--libcutils/selector.c263
-rw-r--r--libcutils/socket_inaddr_any_server.c70
-rw-r--r--libcutils/socket_local.h39
-rw-r--r--libcutils/socket_local_client.c167
-rw-r--r--libcutils/socket_local_server.c124
-rw-r--r--libcutils/socket_loopback_client.c59
-rw-r--r--libcutils/socket_loopback_server.c71
-rw-r--r--libcutils/socket_network_client.c65
-rw-r--r--libcutils/strdup16to8.c104
-rw-r--r--libcutils/strdup8to16.c209
-rw-r--r--libcutils/threads.c84
-rw-r--r--libcutils/tzfile.h180
-rw-r--r--libcutils/tzstrftime.c834
-rw-r--r--libcutils/tztime.c1915
-rw-r--r--libcutils/uio.c76
-rw-r--r--libcutils/zygote.c267
44 files changed, 0 insertions, 10830 deletions
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
deleted file mode 100644
index a43f7e3e4..000000000
--- a/libcutils/Android.mk
+++ /dev/null
@@ -1,113 +0,0 @@
-#
-# Copyright (C) 2008 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.
-#
-LOCAL_PATH := $(my-dir)
-include $(CLEAR_VARS)
-
-commonSources := \
- array.c \
- hashmap.c \
- atomic.c \
- buffer.c \
- socket_inaddr_any_server.c \
- socket_local_client.c \
- socket_local_server.c \
- socket_loopback_client.c \
- socket_loopback_server.c \
- socket_network_client.c \
- config_utils.c \
- cpu_info.c \
- load_file.c \
- strdup16to8.c \
- strdup8to16.c \
- record_stream.c \
- process_name.c \
- properties.c \
- threads.c
-
-# some files must not be compiled when building against Mingw
-# they correspond to features not used by our host development tools
-# which are also hard or even impossible to port to native Win32
-WITH_MINGW :=
-ifeq ($(HOST_OS),windows)
- ifeq ($(strip $(USE_CYGWIN)),)
- WITH_MINGW := 1
- endif
-endif
-# USE_MINGW is defined when we build against Mingw on Linux
-ifneq ($(strip $(USE_MINGW)),)
- WITH_MINGW := 1
-endif
-
-ifeq ($(WITH_MINGW),1)
- commonSources += \
- uio.c
-else
- commonSources += \
- mspace.c \
- selector.c \
- fdevent.c \
- tztime.c \
- tzstrftime.c \
- adb_networking.c \
- zygote.c
-endif
-
-
-# Static library for host
-# ========================================================
-LOCAL_MODULE := libcutils
-LOCAL_SRC_FILES := $(commonSources) ashmem-host.c
-LOCAL_LDLIBS := -lpthread
-LOCAL_STATIC_LIBRARIES := liblog
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-
-ifeq ($(TARGET_SIMULATOR),true)
-
-# Shared library for simulator
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := libcutils
-LOCAL_SRC_FILES := $(commonSources) memory.c dlmalloc_stubs.c ashmem-host.c
-LOCAL_LDLIBS := -lpthread
-LOCAL_SHARED_LIBRARIES := liblog
-include $(BUILD_SHARED_LIBRARY)
-
-else #!sim
-
-# Shared and static library for target
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := libcutils
-LOCAL_SRC_FILES := $(commonSources) ashmem-dev.c mq.c
-
-ifeq ($(TARGET_ARCH),arm)
-LOCAL_SRC_FILES += memset32.S atomic-android-arm.S
-else # !arm
-LOCAL_SRC_FILES += memory.c
-endif # !arm
-
-LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
-LOCAL_STATIC_LIBRARIES := liblog
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libcutils
-LOCAL_WHOLE_STATIC_LIBRARIES := libcutils
-LOCAL_SHARED_LIBRARIES := liblog
-include $(BUILD_SHARED_LIBRARY)
-
-endif #!sim
diff --git a/libcutils/MODULE_LICENSE_APACHE2 b/libcutils/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29bb..000000000
--- a/libcutils/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/libcutils/NOTICE b/libcutils/NOTICE
deleted file mode 100644
index c5b1efa7a..000000000
--- a/libcutils/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
- Copyright (c) 2005-2008, 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.
-
- 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.
-
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
diff --git a/libcutils/adb_networking.c b/libcutils/adb_networking.c
deleted file mode 100644
index d819d44c8..000000000
--- a/libcutils/adb_networking.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/* libs/utils/adb_networking.c
-**
-** Copyright 2006, 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.
-*/
-
-#define ADB_PORT 5037
-
-#define _GNU_SOURCE /* for asprintf */
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <string.h>
-
-#include <cutils/adb_networking.h>
-#include <cutils/sockets.h>
-#include <cutils/properties.h>
-
-#define ADB_RESPONSE_SIZE 4
-
-/**
- * Unfortunately, java.net.Socket wants to create it's filedescriptor early
- * So, this function takes an fd that must be an unconnected
- * PF_LOCAL SOCK_STREAM
- */
-int adb_networking_connect_fd(int fd, struct sockaddr_in *p_address)
-{
- struct sockaddr_in local_addr;
- socklen_t alen;
- char *cmd;
- char buf[ADB_RESPONSE_SIZE + 1];
- ssize_t count_read;
- int ret;
- int err;
- /* for impl of inet_ntoa below*/
- union {
- uint8_t b[4];
- uint32_t l;
- } a;
-
- /* First, connect to adb */
-
- memset(&local_addr, 0, sizeof(local_addr));
- local_addr.sin_family = AF_INET;
- local_addr.sin_port = htons(ADB_PORT);
- local_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
- do {
- err = connect(fd, (struct sockaddr *) &local_addr, sizeof(local_addr));
- } while (err < 0 && errno == EINTR);
-
- if (err < 0) {
- return -1;
- }
-
- a.l = p_address->sin_addr.s_addr;
-
- // compose the command
- asprintf(&cmd, "tcp:%u:%u.%u.%u.%u",
- (unsigned int)ntohs(p_address->sin_port),
- a.b[0],a.b[1],a.b[2],a.b[3]);
-
- // buf is now the ascii hex length of cmd
- snprintf(buf, sizeof(buf), "%04X", strlen(cmd));
-
- // write the 4-byte length
- do {
- err = write(fd, buf, 4);
- } while (err < 0 && errno == EINTR);
-
- // write the command
- do {
- err = write(fd, cmd, strlen(cmd));
- } while (err < 0 && errno == EINTR);
-
- // read the result
- do {
- count_read = read(fd, buf, sizeof(buf) - 1);
- } while (count_read < 0 && errno != EINTR);
-
- if (count_read == ADB_RESPONSE_SIZE
- && 0 == strncmp(buf, "OKAY", ADB_RESPONSE_SIZE)) {
- ret = 0;
- } else {
- /* what errno here? <shrug? */
- errno = ENETUNREACH;
- ret = -1;
- }
-
- free(cmd);
-
- return ret;
-}
-
-/**
- * Fills in *p_out_addr and returns 0 on success
- * Memset's *p_out_addr and returns -1 on fail
- */
-
-int adb_networking_gethostbyname(const char *name, struct in_addr *p_out_addr)
-{
- int fd;
- char *cmd = NULL;
- char buf[ADB_RESPONSE_SIZE + 1];
- int err;
- ssize_t count_read;
-
- fd = socket_loopback_client(ADB_PORT, SOCK_STREAM);
-
- if (fd < 0) {
- return -1;
- }
-
- // compose the command
- asprintf(&cmd, "dns:%s", name);
-
- // buf is now the ascii hex length of cmd
- snprintf(buf, sizeof(buf), "%04X", strlen(cmd));
-
- // write the 4-byte length
- do {
- err = write(fd, buf, 4);
- } while (err < 0 && errno == EINTR);
-
- // write the command
- do {
- err = write(fd, cmd, strlen(cmd));
- } while (err < 0 && errno == EINTR);
-
- // read the result
- do {
- count_read = read(fd, buf, ADB_RESPONSE_SIZE);
- } while (count_read < 0 && errno != EINTR);
-
- if (count_read != ADB_RESPONSE_SIZE
- || 0 != strncmp(buf, "OKAY", ADB_RESPONSE_SIZE)) {
- goto error;
- }
-
- // read the actual IP address
- do {
- count_read = read(fd, &(p_out_addr->s_addr), sizeof(p_out_addr->s_addr));
- } while (count_read < 0 && errno != EINTR);
-
- if (count_read != 4) {
- goto error;
- }
-
- free(cmd);
- close(fd);
- return 0;
-error:
- free(cmd);
- close(fd);
- memset(p_out_addr, 0, sizeof(struct in_addr));
- return -1;
-}
-
diff --git a/libcutils/array.c b/libcutils/array.c
deleted file mode 100644
index ff2c8ff12..000000000
--- a/libcutils/array.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2007 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 <cutils/array.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define INITIAL_CAPACITY (4)
-
-struct Array {
- void** contents;
- int size;
- int capacity;
-};
-
-Array* arrayCreate() {
- return calloc(1, sizeof(struct Array));
-}
-
-void arrayFree(Array* array) {
- assert(array != NULL);
-
- // Free internal array.
- free(array->contents);
-
- // Free the Array itself.
- free(array);
-}
-
-/** Returns 0 if successful, < 0 otherwise.. */
-static int ensureCapacity(Array* array, int capacity) {
- int oldCapacity = array->capacity;
- if (capacity > oldCapacity) {
- int newCapacity = (oldCapacity == 0) ? INITIAL_CAPACITY : oldCapacity * 2;
-
- // Keep doubling capacity until we surpass necessary capacity.
- while (newCapacity < capacity) {
- newCapacity *= 2;
- }
-
- void** newContents;
- if (array->contents == NULL) {
- // Allocate new array.
- newContents = malloc(newCapacity * sizeof(void*));
- if (newContents == NULL) {
- return -1;
- }
- } else {
- // Expand existing array.
- newContents = realloc(array->contents, sizeof(void*) * newCapacity);
- if (newContents == NULL) {
- return -1;
- }
- }
-
- array->capacity = newCapacity;
- array->contents = newContents;
- }
-
- return 0;
-}
-
-int arrayAdd(Array* array, void* pointer) {
- assert(array != NULL);
- int size = array->size;
- int result = ensureCapacity(array, size + 1);
- if (result < 0) {
- return result;
- }
- array->contents[size] = pointer;
- array->size++;
- return 0;
-}
-
-static inline void checkBounds(Array* array, int index) {
- assert(array != NULL);
- assert(index < array->size);
- assert(index >= 0);
-}
-
-void* arrayGet(Array* array, int index) {
- checkBounds(array, index);
- return array->contents[index];
-}
-
-void* arrayRemove(Array* array, int index) {
- checkBounds(array, index);
-
- void* pointer = array->contents[index];
-
- int newSize = array->size - 1;
-
- // Shift entries left.
- if (index != newSize) {
- memmove(array->contents + index, array->contents + index + 1,
- (sizeof(void*)) * (newSize - index));
- }
-
- array->size = newSize;
-
- return pointer;
-}
-
-void* arraySet(Array* array, int index, void* pointer) {
- checkBounds(array, index);
- void* old = array->contents[index];
- array->contents[index] = pointer;
- return old;
-}
-
-int arraySetSize(Array* array, int newSize) {
- assert(array != NULL);
- assert(newSize >= 0);
-
- int oldSize = array->size;
-
- if (newSize > oldSize) {
- // Expand.
- int result = ensureCapacity(array, newSize);
- if (result < 0) {
- return result;
- }
-
- // Zero out new entries.
- memset(array->contents + sizeof(void*) * oldSize, 0,
- sizeof(void*) * (newSize - oldSize));
- }
-
- array->size = newSize;
-
- return 0;
-}
-
-int arraySize(Array* array) {
- assert(array != NULL);
- return array->size;
-}
-
-const void** arrayUnwrap(Array* array) {
- return array->contents;
-}
diff --git a/libcutils/ashmem-dev.c b/libcutils/ashmem-dev.c
deleted file mode 100644
index 5e158af71..000000000
--- a/libcutils/ashmem-dev.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-
-/*
- * Implementation of the user-space ashmem API for devices, which have our
- * ashmem-enabled kernel. See ashmem-sim.c for the "fake" tmp-based version,
- * used by the simulator.
- */
-
-#include <unistd.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-
-#include <linux/ashmem.h>
-#include <cutils/ashmem.h>
-
-#define ASHMEM_DEVICE "/dev/ashmem"
-
-/*
- * ashmem_create_region - creates a new ashmem region and returns the file
- * descriptor, or <0 on error
- *
- * `name' is an optional label to give the region (visible in /proc/pid/maps)
- * `size' is the size of the region, in page-aligned bytes
- */
-int ashmem_create_region(const char *name, size_t size)
-{
- int fd, ret;
-
- fd = open(ASHMEM_DEVICE, O_RDWR);
- if (fd < 0)
- return fd;
-
- if (name) {
- char buf[ASHMEM_NAME_LEN];
-
- strlcpy(buf, name, sizeof(buf));
- ret = ioctl(fd, ASHMEM_SET_NAME, buf);
- if (ret < 0)
- goto error;
- }
-
- ret = ioctl(fd, ASHMEM_SET_SIZE, size);
- if (ret < 0)
- goto error;
-
- return fd;
-
-error:
- close(fd);
- return ret;
-}
-
-int ashmem_set_prot_region(int fd, int prot)
-{
- return ioctl(fd, ASHMEM_SET_PROT_MASK, prot);
-}
-
-int ashmem_pin_region(int fd, size_t offset, size_t len)
-{
- struct ashmem_pin pin = { offset, len };
- return ioctl(fd, ASHMEM_PIN, &pin);
-}
-
-int ashmem_unpin_region(int fd, size_t offset, size_t len)
-{
- struct ashmem_pin pin = { offset, len };
- return ioctl(fd, ASHMEM_UNPIN, &pin);
-}
diff --git a/libcutils/ashmem-host.c b/libcutils/ashmem-host.c
deleted file mode 100644
index dbb52bc47..000000000
--- a/libcutils/ashmem-host.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-
-/*
- * Implementation of the user-space ashmem API for the simulator, which lacks
- * an ashmem-enabled kernel. See ashmem-dev.c for the real ashmem-based version.
- */
-
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <errno.h>
-#include <time.h>
-#include <limits.h>
-
-#include <cutils/ashmem.h>
-
-int ashmem_create_region(const char *ignored, size_t size)
-{
- static const char txt[] = "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- char name[64];
- unsigned int retries = 0;
- pid_t pid = getpid();
- int fd;
-
- srand(time(NULL) + pid);
-
-retry:
- /* not beautiful, its just wolf-like loop unrolling */
- snprintf(name, sizeof(name), "/tmp/android-ashmem-%d-%c%c%c%c%c%c%c%c",
- pid,
- txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))],
- txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))],
- txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))],
- txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))],
- txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))],
- txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))],
- txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))],
- txt[(int) ((sizeof(txt) - 1) * (rand() / (RAND_MAX + 1.0)))]);
-
- /* open O_EXCL & O_CREAT: we are either the sole owner or we fail */
- fd = open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
- if (fd == -1) {
- /* unlikely, but if we failed because `name' exists, retry */
- if (errno == EEXIST && ++retries < 6)
- goto retry;
- return -1;
- }
-
- /* truncate the file to `len' bytes */
- if (ftruncate(fd, size) == -1)
- goto error;
-
- if (unlink(name) == -1)
- goto error;
-
- return fd;
-error:
- close(fd);
- return -1;
-}
-
-int ashmem_set_prot_region(int fd, int prot)
-{
- return 0;
-}
-
-int ashmem_pin_region(int fd, size_t offset, size_t len)
-{
- return ASHMEM_NOT_PURGED;
-}
-
-int ashmem_unpin_region(int fd, size_t offset, size_t len)
-{
- return ASHMEM_IS_UNPINNED;
-}
diff --git a/libcutils/atomic-android-arm.S b/libcutils/atomic-android-arm.S
deleted file mode 100644
index c56ec5d0e..000000000
--- a/libcutils/atomic-android-arm.S
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Copyright (C) 2005 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 <machine/cpu-features.h>
-
-/*
- * NOTE: these atomic operations are SMP safe on all architectures,
- * except swap(), see below.
- */
-
- .text
- .align
-
- .global android_atomic_write
-
- .global android_atomic_inc
- .global android_atomic_dec
-
- .global android_atomic_add
- .global android_atomic_and
- .global android_atomic_or
-
- .global android_atomic_swap
-
- .global android_atomic_cmpxchg
-
-/*
- * ----------------------------------------------------------------------------
- * int __kernel_cmpxchg(int oldval, int newval, int *ptr)
- * clobbered: r3, ip, flags
- * return 0 if a swap was made, non-zero otherwise.
- */
-
- .equ kernel_cmpxchg, 0xFFFF0FC0
- .equ kernel_atomic_base, 0xFFFF0FFF
-
-/*
- * ----------------------------------------------------------------------------
- * android_atomic_write
- * input: r0=value, r1=address
- * output: void
- */
-
-android_atomic_write:
- stmdb sp!, {r4, lr}
- mov r2, r1
- mov r1, r0
-1: @ android_atomic_write
- ldr r0, [r2]
- mov r3, #kernel_atomic_base
-#ifdef __ARM_HAVE_PC_INTERWORK
- add lr, pc, #4
- add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
-#else
- add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
- mov lr, pc
- bx r3
-#endif
- bcc 1b
- ldmia sp!, {r4, lr}
- bx lr
-
-/*
- * ----------------------------------------------------------------------------
- * android_atomic_inc
- * input: r0 = address
- * output: r0 = old value
- */
-
-android_atomic_inc:
- stmdb sp!, {r4, lr}
- mov r2, r0
-1: @ android_atomic_inc
- ldr r0, [r2]
- mov r3, #kernel_atomic_base
-#ifdef __ARM_HAVE_PC_INTERWORK
- add lr, pc, #4
- add r1, r0, #1
- add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
-#else
- add r1, r0, #1
- add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
- mov lr, pc
- bx r3
-#endif
- bcc 1b
- sub r0, r1, #1
- ldmia sp!, {r4, lr}
- bx lr
-
-/*
- * ----------------------------------------------------------------------------
- * android_atomic_dec
- * input: r0=address
- * output: r0 = old value
- */
-
-android_atomic_dec:
- stmdb sp!, {r4, lr}
- mov r2, r0
-1: @ android_atomic_dec
- ldr r0, [r2]
- mov r3, #kernel_atomic_base
-#ifdef __ARM_HAVE_PC_INTERWORK
- add lr, pc, #4
- sub r1, r0, #1
- add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
-#else
- sub r1, r0, #1
- add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
- mov lr, pc
- bx r3
-#endif
- bcc 1b
- add r0, r1, #1
- ldmia sp!, {r4, lr}
- bx lr
-
-/*
- * ----------------------------------------------------------------------------
- * android_atomic_add
- * input: r0=value, r1=address
- * output: r0 = old value
- */
-
-android_atomic_add:
- stmdb sp!, {r4, lr}
- mov r2, r1
- mov r4, r0
-1: @ android_atomic_add
- ldr r0, [r2]
- mov r3, #kernel_atomic_base
-#ifdef __ARM_HAVE_PC_INTERWORK
- add lr, pc, #4
- add r1, r0, r4
- add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
-#else
- add r1, r0, r4
- add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
- mov lr, pc
- bx r3
-#endif
- bcc 1b
- sub r0, r1, r4
- ldmia sp!, {r4, lr}
- bx lr
-
-
-/*
- * ----------------------------------------------------------------------------
- * android_atomic_and
- * input: r0=value, r1=address
- * output: r0 = old value
- */
-
-android_atomic_and:
- stmdb sp!, {r4, r5, lr}
- mov r2, r1 /* r2 = address */
- mov r4, r0 /* r4 = the value */
-1: @ android_atomic_and
- ldr r0, [r2] /* r0 = address[0] */
- mov r3, #kernel_atomic_base
-#ifdef __ARM_HAVE_PC_INTERWORK
- add lr, pc, #8
- mov r5, r0 /* r5 = save address[0] */
- and r1, r0, r4 /* r1 = new value */
- add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
-#else
- mov r5, r0 /* r5 = save address[0] */
- and r1, r0, r4 /* r1 = new value */
- add r3, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
- mov lr, pc
- bx r3
-#endif
- bcc 1b
- mov r0, r5
- ldmia sp!, {r4, r5, lr}
- bx lr
-
-/*
- * ----------------------------------------------------------------------------
- * android_atomic_or
- * input: r0=value, r1=address
- * output: r0 = old value
- */
-
-android_atomic_or:
- stmdb sp!, {r4, r5, lr}
- mov r2, r1 /* r2 = address */
- mov r4, r0 /* r4 = the value */
-1: @ android_atomic_or
- ldr r0, [r2] /* r0 = address[0] */
- mov r3, #kernel_atomic_base
-#ifdef __ARM_HAVE_PC_INTERWORK
- add lr, pc, #8
- mov r5, r0 /* r5 = save address[0] */
- orr r1, r0, r4 /* r1 = new value */
- add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
-#else
- mov r5, r0 /* r5 = save address[0] */
- orr r1, r0, r4 /* r1 = new value */
- add r3, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
- mov lr, pc
- bx r3
-#endif
- bcc 1b
- mov r0, r5
- ldmia sp!, {r4, r5, lr}
- bx lr
-
-/*
- * ----------------------------------------------------------------------------
- * android_atomic_swap
- * input: r0=value, r1=address
- * output: r0 = old value
- */
-
-/* FIXME: this is not safe on SMP systems
- * a general way to do it is to use kernel_cmpxchg */
-
-android_atomic_swap:
- swp r0, r0, [r1]
- bx lr
-
-/*
- * ----------------------------------------------------------------------------
- * android_atomic_cmpxchg
- * input: r0=oldvalue, r1=newvalue, r2=address
- * output: r0 = 0 (xchg done) or non-zero (xchg not done)
- */
-
-android_atomic_cmpxchg:
- stmdb sp!, {r4, lr}
- mov r4, r0 /* r4 = save oldvalue */
-1: @ android_atomic_cmpxchg
- mov r3, #kernel_atomic_base
-#ifdef __ARM_HAVE_PC_INTERWORK
- add lr, pc, #4
- mov r0, r4 /* r0 = oldvalue */
- add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
-#else
- mov r0, r4 /* r0 = oldvalue */
- add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
- mov lr, pc
- bx r3
-#endif
- bcs 2f /* swap was made. we're good, return. */
- ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */
- cmp r3, r4
- beq 1b
-2: @ android_atomic_cmpxchg
- ldmia sp!, {r4, lr}
- bx lr
-
-/*
- * ----------------------------------------------------------------------------
- * android_atomic_cmpxchg_64
- * input: r0-r1=oldvalue, r2-r3=newvalue, arg4 (on stack)=address
- * output: r0 = 0 (xchg done) or non-zero (xchg not done)
- */
-/* TODO: NEED IMPLEMENTATION FOR THIS ARCHITECTURE */
diff --git a/libcutils/atomic-android-armv6.S b/libcutils/atomic-android-armv6.S
deleted file mode 100644
index 64146c177..000000000
--- a/libcutils/atomic-android-armv6.S
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-
-
- .text
- .align
-
- .global android_atomic_write
-
- .global android_atomic_inc
- .global android_atomic_dec
-
- .global android_atomic_add
- .global android_atomic_and
- .global android_atomic_or
-
- .global android_atomic_swap
-
- .global android_atomic_cmpxchg
-
-
-
-/* FIXME: On SMP systems memory barriers may be needed */
-#warning "this file is not safe with SMP systems"
-
-
-/*
- * ----------------------------------------------------------------------------
- * android_atomic_write
- * input: r0=value, r1=address
- * output: void
- */
-
-android_atomic_write:
-1: ldrex r12, [r1]
- strex r12, r0, [r1]
- cmp r12, #0
- bne 1b
- bx lr
-
-/*
- * ----------------------------------------------------------------------------
- * android_atomic_inc
- * input: r0 = address
- * output: r0 = old value
- */
-
-android_atomic_inc:
- mov r12, r0
-1: ldrex r0, [r12]
- add r2, r0, #1
- strex r1, r2, [r12]
- cmp r1, #0
- bxeq lr
- b 1b
-
-/*
- * ----------------------------------------------------------------------------
- * android_atomic_dec
- * input: r0=address
- * output: r0 = old value
- */
-
-android_atomic_dec:
- mov r12, r0
-1: ldrex r0, [r12]
- sub r2, r0, #1
- strex r1, r2, [r12]
- cmp r1, #0
- bxeq lr
- b 1b
-
-
-/*
- * ----------------------------------------------------------------------------
- * android_atomic_add
- * input: r0=value, r1=address
- * output: r0 = old value
- */
-
-android_atomic_add:
- mov r12, r0
-1: ldrex r0, [r1]
- add r2, r0, r12
- strex r3, r2, [r1]
- cmp r3, #0
- bxeq lr
- b 1b
-
-/*
- * ----------------------------------------------------------------------------
- * android_atomic_and
- * input: r0=value, r1=address
- * output: r0 = old value
- */
-
-android_atomic_and:
- mov r12, r0
-1: ldrex r0, [r1]
- and r2, r0, r12
- strex r3, r2, [r1]
- cmp r3, #0
- bxeq lr
- b 1b
-
-
-/*
- * ----------------------------------------------------------------------------
- * android_atomic_or
- * input: r0=value, r1=address
- * output: r0 = old value
- */
-
-android_atomic_or:
- mov r12, r0
-1: ldrex r0, [r1]
- orr r2, r0, r12
- strex r3, r2, [r1]
- cmp r3, #0
- bxeq lr
- b 1b
-
-/*
- * ----------------------------------------------------------------------------
- * android_atomic_swap
- * input: r0=value, r1=address
- * output: r0 = old value
- */
-
-android_atomic_swap:
- swp r0, r0, [r1]
- bx lr
-
-/*
- * ----------------------------------------------------------------------------
- * android_atomic_cmpxchg
- * input: r0=oldvalue, r1=newvalue, r2=address
- * output: r0 = 0 (xchg done) or non-zero (xchg not done)
- */
-
-android_atomic_cmpxchg:
- mov r12, r1
- ldrex r3, [r2]
- eors r0, r0, r3
- strexeq r0, r12, [r2]
- bx lr
-
-
-
-/*
- * ----------------------------------------------------------------------------
- * android_atomic_cmpxchg_64
- * input: r0-r1=oldvalue, r2-r3=newvalue, arg4 (on stack)=address
- * output: r0 = 0 (xchg done) or non-zero (xchg not done)
- */
-/* TODO: NEED IMPLEMENTATION FOR THIS ARCHITECTURE */
diff --git a/libcutils/atomic.c b/libcutils/atomic.c
deleted file mode 100644
index 65d7af0af..000000000
--- a/libcutils/atomic.c
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright (C) 2007 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 <cutils/atomic.h>
-#ifdef HAVE_WIN32_THREADS
-#include <windows.h>
-#else
-#include <sched.h>
-#endif
-
-/*****************************************************************************/
-#if defined(HAVE_MACOSX_IPC)
-
-#include <libkern/OSAtomic.h>
-
-void android_atomic_write(int32_t value, volatile int32_t* addr) {
- int32_t oldValue;
- do {
- oldValue = *addr;
- } while (OSAtomicCompareAndSwap32Barrier(oldValue, value, (int32_t*)addr) == 0);
-}
-
-int32_t android_atomic_inc(volatile int32_t* addr) {
- return OSAtomicIncrement32Barrier((int32_t*)addr)-1;
-}
-
-int32_t android_atomic_dec(volatile int32_t* addr) {
- return OSAtomicDecrement32Barrier((int32_t*)addr)+1;
-}
-
-int32_t android_atomic_add(int32_t value, volatile int32_t* addr) {
- return OSAtomicAdd32Barrier(value, (int32_t*)addr)-value;
-}
-
-int32_t android_atomic_and(int32_t value, volatile int32_t* addr) {
- int32_t oldValue;
- do {
- oldValue = *addr;
- } while (OSAtomicCompareAndSwap32Barrier(oldValue, oldValue&value, (int32_t*)addr) == 0);
- return oldValue;
-}
-
-int32_t android_atomic_or(int32_t value, volatile int32_t* addr) {
- int32_t oldValue;
- do {
- oldValue = *addr;
- } while (OSAtomicCompareAndSwap32Barrier(oldValue, oldValue|value, (int32_t*)addr) == 0);
- return oldValue;
-}
-
-int32_t android_atomic_swap(int32_t value, volatile int32_t* addr) {
- int32_t oldValue;
- do {
- oldValue = *addr;
- } while (android_atomic_cmpxchg(oldValue, value, addr));
- return oldValue;
-}
-
-int android_atomic_cmpxchg(int32_t oldvalue, int32_t newvalue, volatile int32_t* addr) {
- return OSAtomicCompareAndSwap32Barrier(oldvalue, newvalue, (int32_t*)addr) == 0;
-}
-
-#if defined(__ppc__) \
- || defined(__PPC__) \
- || defined(__powerpc__) \
- || defined(__powerpc) \
- || defined(__POWERPC__) \
- || defined(_M_PPC) \
- || defined(__PPC)
-#define NEED_QUASIATOMICS 1
-#else
-
-int android_quasiatomic_cmpxchg_64(int64_t oldvalue, int64_t newvalue,
- volatile int64_t* addr) {
- return OSAtomicCompareAndSwap64Barrier(oldvalue, newvalue,
- (int64_t*)addr) == 0;
-}
-
-int64_t android_quasiatomic_swap_64(int64_t value, volatile int64_t* addr) {
- int64_t oldValue;
- do {
- oldValue = *addr;
- } while (android_quasiatomic_cmpxchg_64(oldValue, value, addr));
- return oldValue;
-}
-
-int64_t android_quasiatomic_read_64(volatile int64_t* addr) {
- return OSAtomicAdd64Barrier(0, addr);
-}
-
-#endif
-
-
-/*****************************************************************************/
-#elif defined(__i386__) || defined(__x86_64__)
-
-void android_atomic_write(int32_t value, volatile int32_t* addr) {
- int32_t oldValue;
- do {
- oldValue = *addr;
- } while (android_atomic_cmpxchg(oldValue, value, addr));
-}
-
-int32_t android_atomic_inc(volatile int32_t* addr) {
- int32_t oldValue;
- do {
- oldValue = *addr;
- } while (android_atomic_cmpxchg(oldValue, oldValue+1, addr));
- return oldValue;
-}
-
-int32_t android_atomic_dec(volatile int32_t* addr) {
- int32_t oldValue;
- do {
- oldValue = *addr;
- } while (android_atomic_cmpxchg(oldValue, oldValue-1, addr));
- return oldValue;
-}
-
-int32_t android_atomic_add(int32_t value, volatile int32_t* addr) {
- int32_t oldValue;
- do {
- oldValue = *addr;
- } while (android_atomic_cmpxchg(oldValue, oldValue+value, addr));
- return oldValue;
-}
-
-int32_t android_atomic_and(int32_t value, volatile int32_t* addr) {
- int32_t oldValue;
- do {
- oldValue = *addr;
- } while (android_atomic_cmpxchg(oldValue, oldValue&value, addr));
- return oldValue;
-}
-
-int32_t android_atomic_or(int32_t value, volatile int32_t* addr) {
- int32_t oldValue;
- do {
- oldValue = *addr;
- } while (android_atomic_cmpxchg(oldValue, oldValue|value, addr));
- return oldValue;
-}
-
-int32_t android_atomic_swap(int32_t value, volatile int32_t* addr) {
- int32_t oldValue;
- do {
- oldValue = *addr;
- } while (android_atomic_cmpxchg(oldValue, value, addr));
- return oldValue;
-}
-
-int android_atomic_cmpxchg(int32_t oldvalue, int32_t newvalue, volatile int32_t* addr) {
- int xchg;
- asm volatile
- (
- " lock; cmpxchg %%ecx, (%%edx);"
- " setne %%al;"
- " andl $1, %%eax"
- : "=a" (xchg)
- : "a" (oldvalue), "c" (newvalue), "d" (addr)
- );
- return xchg;
-}
-
-#define NEED_QUASIATOMICS 1
-
-/*****************************************************************************/
-#elif __arm__
-// Most of the implementation is in atomic-android-arm.s.
-
-// on the device, we implement the 64-bit atomic operations through
-// mutex locking. normally, this is bad because we must initialize
-// a pthread_mutex_t before being able to use it, and this means
-// having to do an initialization check on each function call, and
-// that's where really ugly things begin...
-//
-// BUT, as a special twist, we take advantage of the fact that in our
-// pthread library, a mutex is simply a volatile word whose value is always
-// initialized to 0. In other words, simply declaring a static mutex
-// object initializes it !
-//
-// another twist is that we use a small array of mutexes to dispatch
-// the contention locks from different memory addresses
-//
-
-#include <pthread.h>
-
-#define SWAP_LOCK_COUNT 32U
-static pthread_mutex_t _swap_locks[SWAP_LOCK_COUNT];
-
-#define SWAP_LOCK(addr) \
- &_swap_locks[((unsigned)(void*)(addr) >> 3U) % SWAP_LOCK_COUNT]
-
-
-int64_t android_quasiatomic_swap_64(int64_t value, volatile int64_t* addr) {
- int64_t oldValue;
- pthread_mutex_t* lock = SWAP_LOCK(addr);
-
- pthread_mutex_lock(lock);
-
- oldValue = *addr;
- *addr = value;
-
- pthread_mutex_unlock(lock);
- return oldValue;
-}
-
-int android_quasiatomic_cmpxchg_64(int64_t oldvalue, int64_t newvalue,
- volatile int64_t* addr) {
- int result;
- pthread_mutex_t* lock = SWAP_LOCK(addr);
-
- pthread_mutex_lock(lock);
-
- if (*addr == oldvalue) {
- *addr = newvalue;
- result = 0;
- } else {
- result = 1;
- }
- pthread_mutex_unlock(lock);
- return result;
-}
-
-int64_t android_quasiatomic_read_64(volatile int64_t* addr) {
- int64_t result;
- pthread_mutex_t* lock = SWAP_LOCK(addr);
-
- pthread_mutex_lock(lock);
- result = *addr;
- pthread_mutex_unlock(lock);
- return result;
-}
-
-#else
-
-#error "Unsupported atomic operations for this platform"
-
-#endif
-
-
-
-#if NEED_QUASIATOMICS
-
-/* Note that a spinlock is *not* a good idea in general
- * since they can introduce subtle issues. For example,
- * a real-time thread trying to acquire a spinlock already
- * acquired by another thread will never yeld, making the
- * CPU loop endlessly!
- *
- * However, this code is only used on the Linux simulator
- * so it's probably ok for us.
- *
- * The alternative is to use a pthread mutex, but
- * these must be initialized before being used, and
- * then you have the problem of lazily initializing
- * a mutex without any other synchronization primitive.
- */
-
-/* global spinlock for all 64-bit quasiatomic operations */
-static int32_t quasiatomic_spinlock = 0;
-
-int android_quasiatomic_cmpxchg_64(int64_t oldvalue, int64_t newvalue,
- volatile int64_t* addr) {
- int result;
-
- while (android_atomic_cmpxchg(0, 1, &quasiatomic_spinlock)) {
-#ifdef HAVE_WIN32_THREADS
- Sleep(0);
-#else
- sched_yield();
-#endif
- }
-
- if (*addr == oldvalue) {
- *addr = newvalue;
- result = 0;
- } else {
- result = 1;
- }
-
- android_atomic_swap(0, &quasiatomic_spinlock);
-
- return result;
-}
-
-int64_t android_quasiatomic_read_64(volatile int64_t* addr) {
- int64_t result;
-
- while (android_atomic_cmpxchg(0, 1, &quasiatomic_spinlock)) {
-#ifdef HAVE_WIN32_THREADS
- Sleep(0);
-#else
- sched_yield();
-#endif
- }
-
- result = *addr;
- android_atomic_swap(0, &quasiatomic_spinlock);
-
- return result;
-}
-
-int64_t android_quasiatomic_swap_64(int64_t value, volatile int64_t* addr) {
- int64_t result;
-
- while (android_atomic_cmpxchg(0, 1, &quasiatomic_spinlock)) {
-#ifdef HAVE_WIN32_THREADS
- Sleep(0);
-#else
- sched_yield();
-#endif
- }
-
- result = *addr;
- *addr = value;
- android_atomic_swap(0, &quasiatomic_spinlock);
-
- return result;
-}
-
-#endif
diff --git a/libcutils/buffer.c b/libcutils/buffer.c
deleted file mode 100644
index f34b8f892..000000000
--- a/libcutils/buffer.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-#define LOG_TAG "buffer"
-
-#include <assert.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "buffer.h"
-#include "loghack.h"
-
-Buffer* bufferCreate(size_t capacity) {
- Buffer* buffer = malloc(sizeof(Buffer));
- if (buffer == NULL) {
- return NULL;
- }
- buffer->capacity = capacity;
- buffer->expected = 0;
- buffer->data = malloc(capacity);
- if (buffer->data == NULL) {
- free(buffer);
- return NULL;
- }
- return buffer;
-}
-
-void bufferFree(Buffer* buffer) {
- free(buffer->data);
- free(buffer);
-}
-
-Buffer* bufferWrap(char* data, size_t capacity, size_t size) {
- Buffer* buffer = malloc(sizeof(Buffer));
- if (buffer == NULL) {
- return NULL;
- }
-
- buffer->data = data;
- buffer->capacity = capacity;
- buffer->size = size;
- buffer->expected = 0;
- return buffer;
-}
-
-int bufferPrepareForRead(Buffer* buffer, size_t expected) {
- if (expected > buffer->capacity) {
- // Expand buffer.
- char* expanded = realloc(buffer->data, expected);
- if (expanded == NULL) {
- errno = ENOMEM;
- return -1;
- }
- buffer->capacity = expected;
- buffer->data = expanded;
- }
-
- buffer->size = 0;
- buffer->expected = expected;
- return 0;
-}
-
-ssize_t bufferRead(Buffer* buffer, int fd) {
- assert(buffer->size < buffer->expected);
-
- ssize_t bytesRead = read(fd,
- buffer->data + buffer->size,
- buffer->expected - buffer->size);
-
- if (bytesRead > 0) {
- buffer->size += bytesRead;
- return buffer->size;
- }
-
- return bytesRead;
-}
-
-void bufferPrepareForWrite(Buffer* buffer) {
- buffer->remaining = buffer->size;
-}
-
-ssize_t bufferWrite(Buffer* buffer, int fd) {
- assert(buffer->remaining > 0);
- assert(buffer->remaining <= buffer->size);
-
- ssize_t bytesWritten = write(fd,
- buffer->data + buffer->size - buffer->remaining,
- buffer->remaining);
-
- if (bytesWritten >= 0) {
- buffer->remaining -= bytesWritten;
-
- LOGD("Buffer bytes written: %d", (int) bytesWritten);
- LOGD("Buffer size: %d", (int) buffer->size);
- LOGD("Buffer remaining: %d", (int) buffer->remaining);
-
- return buffer->remaining;
- }
-
- return bytesWritten;
-}
-
diff --git a/libcutils/buffer.h b/libcutils/buffer.h
deleted file mode 100644
index d8bc108ee..000000000
--- a/libcutils/buffer.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-/**
- * Byte buffer utilities.
- */
-
-#ifndef __BUFFER_H
-#define __BUFFER_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdlib.h>
-
-/**
- * Byte buffer of known size. Keeps track of how much data has been read
- * into or written out of the buffer.
- */
-typedef struct {
- /** Buffered data. */
- char* data;
-
- union {
- /** For reading. # of bytes we expect. */
- size_t expected;
-
- /** For writing. # of bytes to write. */
- size_t remaining;
- };
-
- /** Actual # of bytes in the buffer. */
- size_t size;
-
- /** Amount of memory allocated for this buffer. */
- size_t capacity;
-} Buffer;
-
-/**
- * Returns true if all data has been read into the buffer.
- */
-#define bufferReadComplete(buffer) (buffer->expected == buffer->size)
-
-/**
- * Returns true if the buffer has been completely written.
- */
-#define bufferWriteComplete(buffer) (buffer->remaining == 0)
-
-/**
- * Creates a new buffer with the given initial capacity.
- */
-Buffer* bufferCreate(size_t initialCapacity);
-
-/**
- * Wraps an existing byte array.
- */
-Buffer* bufferWrap(char* data, size_t capacity, size_t size);
-
-/**
- * Frees and its data.
- */
-void bufferFree(Buffer* buffer);
-
-/**
- * Prepares buffer to read 'expected' number of bytes. Expands capacity if
- * necessary. Returns 0 if successful or -1 if an error occurs allocating
- * memory.
- */
-int bufferPrepareForRead(Buffer* buffer, size_t expected);
-
-/**
- * Reads some data into a buffer. Returns -1 in case of an error and sets
- * errno (see read()). Returns 0 for EOF. Updates buffer->size and returns
- * the new size after a succesful read.
- *
- * Precondition: buffer->size < buffer->expected
- */
-ssize_t bufferRead(Buffer* buffer, int fd);
-
-/**
- * Prepares a buffer to be written out.
- */
-void bufferPrepareForWrite(Buffer* buffer);
-
-/**
- * Writes data from buffer to the given fd. Returns -1 and sets errno in case
- * of an error. Updates buffer->remaining and returns the number of remaining
- * bytes to be written after a successful write.
- *
- * Precondition: buffer->remaining > 0
- */
-ssize_t bufferWrite(Buffer* buffer, int fd);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __BUFFER_H */
diff --git a/libcutils/config_utils.c b/libcutils/config_utils.c
deleted file mode 100644
index 75fa6c6d4..000000000
--- a/libcutils/config_utils.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright (C) 2007 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 <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <cutils/config_utils.h>
-#include <cutils/misc.h>
-
-cnode* config_node(const char *name, const char *value)
-{
- cnode *node;
-
- node = calloc(sizeof(cnode), 1);
- if(node) {
- node->name = name ? name : "";
- node->value = value ? value : "";
- }
-
- return node;
-}
-
-cnode* config_find(cnode *root, const char *name)
-{
- cnode *node, *match = NULL;
-
- /* we walk the whole list, as we need to return the last (newest) entry */
- for(node = root->first_child; node; node = node->next)
- if(!strcmp(node->name, name))
- match = node;
-
- return match;
-}
-
-static cnode* _config_create(cnode *root, const char *name)
-{
- cnode *node;
-
- node = config_node(name, NULL);
-
- if(root->last_child)
- root->last_child->next = node;
- else
- root->first_child = node;
-
- root->last_child = node;
-
- return node;
-}
-
-int config_bool(cnode *root, const char *name, int _default)
-{
- cnode *node;
-
- node = config_find(root, name);
- if(!node)
- return _default;
-
- switch(node->value[0]) {
- case 'y':
- case 'Y':
- case '1':
- return 1;
- default:
- return 0;
- }
-}
-
-const char* config_str(cnode *root, const char *name, const char *_default)
-{
- cnode *node;
-
- node = config_find(root, name);
- if(!node)
- return _default;
- return node->value;
-}
-
-void config_set(cnode *root, const char *name, const char *value)
-{
- cnode *node;
-
- node = config_find(root, name);
- if(node)
- node->value = value;
- else {
- node = _config_create(root, name);
- node->value = value;
- }
-}
-
-#define T_EOF 0
-#define T_TEXT 1
-#define T_DOT 2
-#define T_OBRACE 3
-#define T_CBRACE 4
-
-typedef struct
-{
- char *data;
- char *text;
- int len;
- char next;
-} cstate;
-
-static int _lex(cstate *cs, int value)
-{
- char c;
- char *s;
- char *data;
-
- data = cs->data;
-
- if(cs->next != 0) {
- c = cs->next;
- cs->next = 0;
- goto got_c;
- }
-
-restart:
- for(;;) {
- c = *data++;
- got_c:
- if(isspace(c))
- continue;
-
- switch(c) {
- case 0:
- return T_EOF;
-
- case '#':
- for(;;) {
- switch(*data) {
- case 0:
- cs->data = data;
- return T_EOF;
- case '\n':
- cs->data = data + 1;
- goto restart;
- default:
- data++;
- }
- }
- break;
-
- case '.':
- cs->data = data;
- return T_DOT;
-
- case '{':
- cs->data = data;
- return T_OBRACE;
-
- case '}':
- cs->data = data;
- return T_CBRACE;
-
- default:
- s = data - 1;
-
- if(value) {
- for(;;) {
- if(*data == 0) {
- cs->data = data;
- break;
- }
- if(*data == '\n') {
- cs->data = data + 1;
- *data-- = 0;
- break;
- }
- data++;
- }
-
- /* strip trailing whitespace */
- while(data > s){
- if(!isspace(*data)) break;
- *data-- = 0;
- }
-
- goto got_text;
- } else {
- for(;;) {
- if(isspace(*data)) {
- *data = 0;
- cs->data = data + 1;
- goto got_text;
- }
- switch(*data) {
- case 0:
- cs->data = data;
- goto got_text;
- case '.':
- case '{':
- case '}':
- cs->next = *data;
- *data = 0;
- cs->data = data + 1;
- goto got_text;
- default:
- data++;
- }
- }
- }
- }
- }
-
-got_text:
- cs->text = s;
- return T_TEXT;
-}
-
-#if 0
-char *TOKENNAMES[] = { "EOF", "TEXT", "DOT", "OBRACE", "CBRACE" };
-
-static int lex(cstate *cs, int value)
-{
- int tok = _lex(cs, value);
- printf("TOKEN(%d) %s %s\n", value, TOKENNAMES[tok],
- tok == T_TEXT ? cs->text : "");
- return tok;
-}
-#else
-#define lex(cs,v) _lex(cs,v)
-#endif
-
-static int parse_expr(cstate *cs, cnode *node);
-
-static int parse_block(cstate *cs, cnode *node)
-{
- for(;;){
- switch(lex(cs, 0)){
- case T_TEXT:
- if(parse_expr(cs, node)) return -1;
- continue;
-
- case T_CBRACE:
- return 0;
-
- default:
- return -1;
- }
- }
-}
-
-static int parse_expr(cstate *cs, cnode *root)
-{
- cnode *node;
-
- /* last token was T_TEXT */
- node = config_find(root, cs->text);
- if(!node || *node->value)
- node = _config_create(root, cs->text);
-
- for(;;) {
- switch(lex(cs, 1)) {
- case T_DOT:
- if(lex(cs, 0) != T_TEXT)
- return -1;
- node = _config_create(node, cs->text);
- continue;
-
- case T_TEXT:
- node->value = cs->text;
- return 0;
-
- case T_OBRACE:
- return parse_block(cs, node);
-
- default:
- return -1;
- }
- }
-}
-
-void config_load(cnode *root, char *data)
-{
- if(data != 0) {
- cstate cs;
- cs.data = data;
- cs.next = 0;
-
- for(;;) {
- switch(lex(&cs, 0)) {
- case T_TEXT:
- if(parse_expr(&cs, root))
- return;
- break;
- default:
- return;
- }
- }
- }
-}
-
-void config_load_file(cnode *root, const char *fn)
-{
- char *data;
- data = load_file(fn, 0);
- config_load(root, data);
-}
diff --git a/libcutils/cpu_info.c b/libcutils/cpu_info.c
deleted file mode 100644
index 23dda8aa1..000000000
--- a/libcutils/cpu_info.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/* libs/cutils/cpu_info.c
-**
-** Copyright 2007, 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 <cutils/cpu_info.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-// we cache the serial number here.
-// this is also used as a fgets() line buffer when we are reading /proc/cpuinfo
-static char serial_number[100] = { 0 };
-
-extern const char* get_cpu_serial_number(void)
-{
- if (serial_number[0] == 0)
- {
- FILE* file;
- char* chp, *end;
- char* whitespace;
- int length;
-
- // read serial number from /proc/cpuinfo
- file = fopen("proc/cpuinfo", "r");
- if (! file)
- return NULL;
-
- while ((chp = fgets(serial_number, sizeof(serial_number), file)) != NULL)
- {
- // look for something like "Serial : 999206122a03591c"
-
- if (strncmp(chp, "Serial", 6) != 0)
- continue;
-
- chp = strchr(chp, ':');
- if (!chp)
- continue;
-
- // skip colon and whitespace
- while ( *(++chp) == ' ') {}
-
- // truncate trailing whitespace
- end = chp;
- while (*end && *end != ' ' && *end != '\t' && *end != '\n' && *end != '\r')
- ++end;
- *end = 0;
-
- whitespace = strchr(chp, ' ');
- if (whitespace)
- *whitespace = 0;
- whitespace = strchr(chp, '\t');
- if (whitespace)
- *whitespace = 0;
- whitespace = strchr(chp, '\r');
- if (whitespace)
- *whitespace = 0;
- whitespace = strchr(chp, '\n');
- if (whitespace)
- *whitespace = 0;
-
- // shift serial number to beginning of the buffer
- memmove(serial_number, chp, strlen(chp) + 1);
- break;
- }
-
- fclose(file);
- }
-
- return (serial_number[0] ? serial_number : NULL);
-}
diff --git a/libcutils/dir_hash.c b/libcutils/dir_hash.c
deleted file mode 100644
index be14af65c..000000000
--- a/libcutils/dir_hash.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright (C) 2007 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 <dirent.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sha1.h>
-#include <unistd.h>
-#include <limits.h>
-
-#include <sys/stat.h>
-
-#include <netinet/in.h>
-#include <resolv.h>
-
-#include <cutils/dir_hash.h>
-
-/**
- * Copies, if it fits within max_output_string bytes, into output_string
- * a hash of the contents, size, permissions, uid, and gid of the file
- * specified by path, using the specified algorithm. Returns the length
- * of the output string, or a negative number if the buffer is too short.
- */
-int get_file_hash(HashAlgorithm algorithm, const char *path,
- char *output_string, size_t max_output_string) {
- SHA1_CTX context;
- struct stat sb;
- unsigned char md[SHA1_DIGEST_LENGTH];
- int used;
- size_t n;
-
- if (algorithm != SHA_1) {
- errno = EINVAL;
- return -1;
- }
-
- if (stat(path, &sb) != 0) {
- return -1;
- }
-
- if (S_ISLNK(sb.st_mode)) {
- char buf[PATH_MAX];
- int len;
-
- len = readlink(path, buf, sizeof(buf));
- if (len < 0) {
- return -1;
- }
-
- SHA1Init(&context);
- SHA1Update(&context, (unsigned char *) buf, len);
- SHA1Final(md, &context);
- } else if (S_ISREG(sb.st_mode)) {
- char buf[10000];
- FILE *f = fopen(path, "rb");
- int len;
-
- if (f == NULL) {
- return -1;
- }
-
- SHA1Init(&context);
-
- while ((len = fread(buf, 1, sizeof(buf), f)) > 0) {
- SHA1Update(&context, (unsigned char *) buf, len);
- }
-
- if (ferror(f)) {
- fclose(f);
- return -1;
- }
-
- fclose(f);
- SHA1Final(md, &context);
- }
-
- if (S_ISLNK(sb.st_mode) || S_ISREG(sb.st_mode)) {
- used = b64_ntop(md, SHA1_DIGEST_LENGTH,
- output_string, max_output_string);
- if (used < 0) {
- errno = ENOSPC;
- return -1;
- }
-
- n = snprintf(output_string + used, max_output_string - used,
- " %d 0%o %d %d", (int) sb.st_size, sb.st_mode,
- (int) sb.st_uid, (int) sb.st_gid);
- } else {
- n = snprintf(output_string, max_output_string,
- "- - 0%o %d %d", sb.st_mode,
- (int) sb.st_uid, (int) sb.st_gid);
- }
-
- if (n >= max_output_string - used) {
- errno = ENOSPC;
- return -(used + n);
- }
-
- return used + n;
-}
-
-struct list {
- char *name;
- struct list *next;
-};
-
-static int cmp(const void *a, const void *b) {
- struct list *const *ra = a;
- struct list *const *rb = b;
-
- return strcmp((*ra)->name, (*rb)->name);
-}
-
-static int recurse(HashAlgorithm algorithm, const char *directory_path,
- struct list **out) {
- struct list *list = NULL;
- struct list *f;
-
- struct dirent *de;
- DIR *d = opendir(directory_path);
-
- if (d == NULL) {
- return -1;
- }
-
- while ((de = readdir(d)) != NULL) {
- if (strcmp(de->d_name, ".") == 0) {
- continue;
- }
- if (strcmp(de->d_name, "..") == 0) {
- continue;
- }
-
- char *name = malloc(strlen(de->d_name) + 1);
- struct list *node = malloc(sizeof(struct list));
-
- if (name == NULL || node == NULL) {
- struct list *next;
- for (f = list; f != NULL; f = next) {
- next = f->next;
- free(f->name);
- free(f);
- }
-
- free(name);
- free(node);
- return -1;
- }
-
- strcpy(name, de->d_name);
-
- node->name = name;
- node->next = list;
- list = node;
- }
-
- closedir(d);
-
- for (f = list; f != NULL; f = f->next) {
- struct stat sb;
- char *name;
- char outstr[NAME_MAX + 100];
- char *keep;
- struct list *res;
-
- name = malloc(strlen(f->name) + strlen(directory_path) + 2);
- if (name == NULL) {
- struct list *next;
- for (f = list; f != NULL; f = f->next) {
- next = f->next;
- free(f->name);
- free(f);
- }
- for (f = *out; f != NULL; f = f->next) {
- next = f->next;
- free(f->name);
- free(f);
- }
- *out = NULL;
- return -1;
- }
-
- sprintf(name, "%s/%s", directory_path, f->name);
-
- int len = get_file_hash(algorithm, name,
- outstr, sizeof(outstr));
- if (len < 0) {
- // should not happen
- return -1;
- }
-
- keep = malloc(len + strlen(name) + 3);
- res = malloc(sizeof(struct list));
-
- if (keep == NULL || res == NULL) {
- struct list *next;
- for (f = list; f != NULL; f = f->next) {
- next = f->next;
- free(f->name);
- free(f);
- }
- for (f = *out; f != NULL; f = f->next) {
- next = f->next;
- free(f->name);
- free(f);
- }
- *out = NULL;
-
- free(keep);
- free(res);
- return -1;
- }
-
- sprintf(keep, "%s %s\n", name, outstr);
-
- res->name = keep;
- res->next = *out;
- *out = res;
-
- if ((stat(name, &sb) == 0) && S_ISDIR(sb.st_mode)) {
- if (recurse(algorithm, name, out) < 0) {
- struct list *next;
- for (f = list; f != NULL; f = next) {
- next = f->next;
- free(f->name);
- free(f);
- }
-
- return -1;
- }
- }
- }
-
- struct list *next;
- for (f = list; f != NULL; f = next) {
- next = f->next;
-
- free(f->name);
- free(f);
- }
-}
-
-/**
- * Allocates a string containing the names and hashes of all files recursively
- * reached under the specified directory_path, using the specified algorithm.
- * The string is returned as *output_string; the return value is the length
- * of the string, or a negative number if there was a failure.
- */
-int get_recursive_hash_manifest(HashAlgorithm algorithm,
- const char *directory_path,
- char **output_string) {
- struct list *out = NULL;
- struct list *r;
- struct list **list;
- int count = 0;
- int len = 0;
- int retlen = 0;
- int i;
- char *buf;
-
- if (recurse(algorithm, directory_path, &out) < 0) {
- return -1;
- }
-
- for (r = out; r != NULL; r = r->next) {
- count++;
- len += strlen(r->name);
- }
-
- list = malloc(count * sizeof(struct list *));
- if (list == NULL) {
- struct list *next;
- for (r = out; r != NULL; r = next) {
- next = r->next;
- free(r->name);
- free(r);
- }
- return -1;
- }
-
- count = 0;
- for (r = out; r != NULL; r = r->next) {
- list[count++] = r;
- }
-
- qsort(list, count, sizeof(struct list *), cmp);
-
- buf = malloc(len + 1);
- if (buf == NULL) {
- struct list *next;
- for (r = out; r != NULL; r = next) {
- next = r->next;
- free(r->name);
- free(r);
- }
- free(list);
- return -1;
- }
-
- for (i = 0; i < count; i++) {
- int n = strlen(list[i]->name);
-
- strcpy(buf + retlen, list[i]->name);
- retlen += n;
- }
-
- free(list);
-
- struct list *next;
- for (r = out; r != NULL; r = next) {
- next = r->next;
-
- free(r->name);
- free(r);
- }
-
- *output_string = buf;
- return retlen;
-}
diff --git a/libcutils/dlmalloc_stubs.c b/libcutils/dlmalloc_stubs.c
deleted file mode 100644
index 1ced147b8..000000000
--- a/libcutils/dlmalloc_stubs.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-/* No-op stubs for functions defined in system/bionic/bionic/dlmalloc.c.
- */
-void dlmalloc_walk_free_pages()
-{
-}
-
-void dlmalloc_walk_heap()
-{
-}
-
-void dlmalloc_trim()
-{
-}
diff --git a/libcutils/fdevent.c b/libcutils/fdevent.c
deleted file mode 100644
index 4cf46faf7..000000000
--- a/libcutils/fdevent.c
+++ /dev/null
@@ -1,506 +0,0 @@
-/* http://frotznet.googlecode.com/svn/trunk/utils/fdevent.c
-**
-** Copyright 2006, Brian Swetland <swetland@frotz.net>
-**
-** 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 <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <fcntl.h>
-
-#include <stdarg.h>
-#include <stddef.h>
-
-#include <cutils/fdevent.h>
-
-#define TRACE(x...) fprintf(stderr,x)
-
-#define DEBUG 0
-
-static void fatal(const char *fn, const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- fprintf(stderr, "%s:", fn);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- abort();
-}
-
-#define FATAL(x...) fatal(__FUNCTION__, x)
-
-#if DEBUG
-static void dump_fde(fdevent *fde, const char *info)
-{
- fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd,
- fde->state & FDE_READ ? 'R' : ' ',
- fde->state & FDE_WRITE ? 'W' : ' ',
- fde->state & FDE_ERROR ? 'E' : ' ',
- info);
-}
-#else
-#define dump_fde(fde, info) do { } while(0)
-#endif
-
-#define FDE_EVENTMASK 0x00ff
-#define FDE_STATEMASK 0xff00
-
-#define FDE_ACTIVE 0x0100
-#define FDE_PENDING 0x0200
-#define FDE_CREATED 0x0400
-
-static void fdevent_plist_enqueue(fdevent *node);
-static void fdevent_plist_remove(fdevent *node);
-static fdevent *fdevent_plist_dequeue(void);
-
-static fdevent list_pending = {
- .next = &list_pending,
- .prev = &list_pending,
-};
-
-static fdevent **fd_table = 0;
-static int fd_table_max = 0;
-
-#ifdef CRAPTASTIC
-//HAVE_EPOLL
-
-#include <sys/epoll.h>
-
-static int epoll_fd = -1;
-
-static void fdevent_init()
-{
- /* XXX: what's a good size for the passed in hint? */
- epoll_fd = epoll_create(256);
-
- if(epoll_fd < 0) {
- perror("epoll_create() failed");
- exit(1);
- }
-
- /* mark for close-on-exec */
- fcntl(epoll_fd, F_SETFD, FD_CLOEXEC);
-}
-
-static void fdevent_connect(fdevent *fde)
-{
- struct epoll_event ev;
-
- memset(&ev, 0, sizeof(ev));
- ev.events = 0;
- ev.data.ptr = fde;
-
-#if 0
- if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
- perror("epoll_ctl() failed\n");
- exit(1);
- }
-#endif
-}
-
-static void fdevent_disconnect(fdevent *fde)
-{
- struct epoll_event ev;
-
- memset(&ev, 0, sizeof(ev));
- ev.events = 0;
- ev.data.ptr = fde;
-
- /* technically we only need to delete if we
- ** were actively monitoring events, but let's
- ** be aggressive and do it anyway, just in case
- ** something's out of sync
- */
- epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev);
-}
-
-static void fdevent_update(fdevent *fde, unsigned events)
-{
- struct epoll_event ev;
- int active;
-
- active = (fde->state & FDE_EVENTMASK) != 0;
-
- memset(&ev, 0, sizeof(ev));
- ev.events = 0;
- ev.data.ptr = fde;
-
- if(events & FDE_READ) ev.events |= EPOLLIN;
- if(events & FDE_WRITE) ev.events |= EPOLLOUT;
- if(events & FDE_ERROR) ev.events |= (EPOLLERR | EPOLLHUP);
-
- fde->state = (fde->state & FDE_STATEMASK) | events;
-
- if(active) {
- /* we're already active. if we're changing to *no*
- ** events being monitored, we need to delete, otherwise
- ** we need to just modify
- */
- if(ev.events) {
- if(epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fde->fd, &ev)) {
- perror("epoll_ctl() failed\n");
- exit(1);
- }
- } else {
- if(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev)) {
- perror("epoll_ctl() failed\n");
- exit(1);
- }
- }
- } else {
- /* we're not active. if we're watching events, we need
- ** to add, otherwise we can just do nothing
- */
- if(ev.events) {
- if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
- perror("epoll_ctl() failed\n");
- exit(1);
- }
- }
- }
-}
-
-static void fdevent_process()
-{
- struct epoll_event events[256];
- fdevent *fde;
- int i, n;
-
- n = epoll_wait(epoll_fd, events, 256, -1);
-
- if(n < 0) {
- if(errno == EINTR) return;
- perror("epoll_wait");
- exit(1);
- }
-
- for(i = 0; i < n; i++) {
- struct epoll_event *ev = events + i;
- fde = ev->data.ptr;
-
- if(ev->events & EPOLLIN) {
- fde->events |= FDE_READ;
- }
- if(ev->events & EPOLLOUT) {
- fde->events |= FDE_WRITE;
- }
- if(ev->events & (EPOLLERR | EPOLLHUP)) {
- fde->events |= FDE_ERROR;
- }
- if(fde->events) {
- if(fde->state & FDE_PENDING) continue;
- fde->state |= FDE_PENDING;
- fdevent_plist_enqueue(fde);
- }
- }
-}
-
-#else /* USE_SELECT */
-
-#ifdef HAVE_WINSOCK
-#include <winsock2.h>
-#else
-#include <sys/select.h>
-#endif
-
-static fd_set read_fds;
-static fd_set write_fds;
-static fd_set error_fds;
-
-static int select_n = 0;
-
-static void fdevent_init(void)
-{
- FD_ZERO(&read_fds);
- FD_ZERO(&write_fds);
- FD_ZERO(&error_fds);
-}
-
-static void fdevent_connect(fdevent *fde)
-{
- if(fde->fd >= select_n) {
- select_n = fde->fd + 1;
- }
-}
-
-static void fdevent_disconnect(fdevent *fde)
-{
- int i, n;
-
- FD_CLR(fde->fd, &read_fds);
- FD_CLR(fde->fd, &write_fds);
- FD_CLR(fde->fd, &error_fds);
-
- for(n = 0, i = 0; i < select_n; i++) {
- if(fd_table[i] != 0) n = i;
- }
- select_n = n + 1;
-}
-
-static void fdevent_update(fdevent *fde, unsigned events)
-{
- if(events & FDE_READ) {
- FD_SET(fde->fd, &read_fds);
- } else {
- FD_CLR(fde->fd, &read_fds);
- }
- if(events & FDE_WRITE) {
- FD_SET(fde->fd, &write_fds);
- } else {
- FD_CLR(fde->fd, &write_fds);
- }
- if(events & FDE_ERROR) {
- FD_SET(fde->fd, &error_fds);
- } else {
- FD_CLR(fde->fd, &error_fds);
- }
-
- fde->state = (fde->state & FDE_STATEMASK) | events;
-}
-
-static void fdevent_process()
-{
- int i, n;
- fdevent *fde;
- unsigned events;
- fd_set rfd, wfd, efd;
-
- memcpy(&rfd, &read_fds, sizeof(fd_set));
- memcpy(&wfd, &write_fds, sizeof(fd_set));
- memcpy(&efd, &error_fds, sizeof(fd_set));
-
- n = select(select_n, &rfd, &wfd, &efd, 0);
-
- if(n < 0) {
- if(errno == EINTR) return;
- perror("select");
- return;
- }
-
- for(i = 0; (i < select_n) && (n > 0); i++) {
- events = 0;
- if(FD_ISSET(i, &rfd)) events |= FDE_READ;
- if(FD_ISSET(i, &wfd)) events |= FDE_WRITE;
- if(FD_ISSET(i, &efd)) events |= FDE_ERROR;
-
- if(events) {
- n--;
-
- fde = fd_table[i];
- if(fde == 0) FATAL("missing fde for fd %d\n", i);
-
- fde->events |= events;
-
- if(fde->state & FDE_PENDING) continue;
- fde->state |= FDE_PENDING;
- fdevent_plist_enqueue(fde);
- }
- }
-}
-
-#endif
-
-static void fdevent_register(fdevent *fde)
-{
- if(fde->fd < 0) {
- FATAL("bogus negative fd (%d)\n", fde->fd);
- }
-
- if(fde->fd >= fd_table_max) {
- int oldmax = fd_table_max;
- if(fde->fd > 32000) {
- FATAL("bogus huuuuge fd (%d)\n", fde->fd);
- }
- if(fd_table_max == 0) {
- fdevent_init();
- fd_table_max = 256;
- }
- while(fd_table_max <= fde->fd) {
- fd_table_max *= 2;
- }
- fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);
- if(fd_table == 0) {
- FATAL("could not expand fd_table to %d entries\n", fd_table_max);
- }
- memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));
- }
-
- fd_table[fde->fd] = fde;
-}
-
-static void fdevent_unregister(fdevent *fde)
-{
- if((fde->fd < 0) || (fde->fd >= fd_table_max)) {
- FATAL("fd out of range (%d)\n", fde->fd);
- }
-
- if(fd_table[fde->fd] != fde) {
- FATAL("fd_table out of sync");
- }
-
- fd_table[fde->fd] = 0;
-
- if(!(fde->state & FDE_DONT_CLOSE)) {
- dump_fde(fde, "close");
- close(fde->fd);
- }
-}
-
-static void fdevent_plist_enqueue(fdevent *node)
-{
- fdevent *list = &list_pending;
-
- node->next = list;
- node->prev = list->prev;
- node->prev->next = node;
- list->prev = node;
-}
-
-static void fdevent_plist_remove(fdevent *node)
-{
- node->prev->next = node->next;
- node->next->prev = node->prev;
- node->next = 0;
- node->prev = 0;
-}
-
-static fdevent *fdevent_plist_dequeue(void)
-{
- fdevent *list = &list_pending;
- fdevent *node = list->next;
-
- if(node == list) return 0;
-
- list->next = node->next;
- list->next->prev = list;
- node->next = 0;
- node->prev = 0;
-
- return node;
-}
-
-fdevent *fdevent_create(int fd, fd_func func, void *arg)
-{
- fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
- if(fde == 0) return 0;
- fdevent_install(fde, fd, func, arg);
- fde->state |= FDE_CREATED;
- return fde;
-}
-
-void fdevent_destroy(fdevent *fde)
-{
- if(fde == 0) return;
- if(!(fde->state & FDE_CREATED)) {
- FATAL("fde %p not created by fdevent_create()\n", fde);
- }
- fdevent_remove(fde);
-}
-
-void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
-{
- memset(fde, 0, sizeof(fdevent));
- fde->state = FDE_ACTIVE;
- fde->fd = fd;
- fde->func = func;
- fde->arg = arg;
-
-#ifndef HAVE_WINSOCK
- fcntl(fd, F_SETFL, O_NONBLOCK);
-#endif
- fdevent_register(fde);
- dump_fde(fde, "connect");
- fdevent_connect(fde);
- fde->state |= FDE_ACTIVE;
-}
-
-void fdevent_remove(fdevent *fde)
-{
- if(fde->state & FDE_PENDING) {
- fdevent_plist_remove(fde);
- }
-
- if(fde->state & FDE_ACTIVE) {
- fdevent_disconnect(fde);
- dump_fde(fde, "disconnect");
- fdevent_unregister(fde);
- }
-
- fde->state = 0;
- fde->events = 0;
-}
-
-
-void fdevent_set(fdevent *fde, unsigned events)
-{
- events &= FDE_EVENTMASK;
-
- if((fde->state & FDE_EVENTMASK) == events) return;
-
- if(fde->state & FDE_ACTIVE) {
- fdevent_update(fde, events);
- dump_fde(fde, "update");
- }
-
- fde->state = (fde->state & FDE_STATEMASK) | events;
-
- if(fde->state & FDE_PENDING) {
- /* if we're pending, make sure
- ** we don't signal an event that
- ** is no longer wanted.
- */
- fde->events &= (~events);
- if(fde->events == 0) {
- fdevent_plist_remove(fde);
- fde->state &= (~FDE_PENDING);
- }
- }
-}
-
-void fdevent_add(fdevent *fde, unsigned events)
-{
- fdevent_set(
- fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
-}
-
-void fdevent_del(fdevent *fde, unsigned events)
-{
- fdevent_set(
- fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
-}
-
-void fdevent_loop()
-{
- fdevent *fde;
-
- for(;;) {
-#if DEBUG
- fprintf(stderr,"--- ---- waiting for events\n");
-#endif
- fdevent_process();
-
- while((fde = fdevent_plist_dequeue())) {
- unsigned events = fde->events;
- fde->events = 0;
- fde->state &= (~FDE_PENDING);
- dump_fde(fde, "callback");
- fde->func(fde->fd, events, fde->arg);
- }
- }
-}
-
diff --git a/libcutils/hashmap.c b/libcutils/hashmap.c
deleted file mode 100644
index e29bc2461..000000000
--- a/libcutils/hashmap.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Copyright (C) 2007 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 <cutils/hashmap.h>
-#include <assert.h>
-#include <errno.h>
-#include <cutils/threads.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdbool.h>
-#include <sys/types.h>
-
-typedef struct Entry Entry;
-struct Entry {
- void* key;
- int hash;
- void* value;
- Entry* next;
-};
-
-struct Hashmap {
- Entry** buckets;
- size_t bucketCount;
- int (*hash)(void* key);
- bool (*equals)(void* keyA, void* keyB);
- mutex_t lock;
- size_t size;
-};
-
-Hashmap* hashmapCreate(size_t initialCapacity,
- int (*hash)(void* key), bool (*equals)(void* keyA, void* keyB)) {
- assert(hash != NULL);
- assert(equals != NULL);
-
- Hashmap* map = malloc(sizeof(Hashmap));
- if (map == NULL) {
- return NULL;
- }
-
- // 0.75 load factor.
- size_t minimumBucketCount = initialCapacity * 4 / 3;
- map->bucketCount = 1;
- while (map->bucketCount <= minimumBucketCount) {
- // Bucket count must be power of 2.
- map->bucketCount <<= 1;
- }
-
- map->buckets = calloc(map->bucketCount, sizeof(Entry*));
- if (map->buckets == NULL) {
- free(map);
- return NULL;
- }
-
- map->size = 0;
-
- map->hash = hash;
- map->equals = equals;
-
- mutex_init(&map->lock);
-
- return map;
-}
-
-/**
- * Hashes the given key.
- */
-static inline int hashKey(Hashmap* map, void* key) {
- int h = map->hash(key);
-
- // We apply this secondary hashing discovered by Doug Lea to defend
- // against bad hashes.
- h += ~(h << 9);
- h ^= (((unsigned int) h) >> 14);
- h += (h << 4);
- h ^= (((unsigned int) h) >> 10);
-
- return h;
-}
-
-size_t hashmapSize(Hashmap* map) {
- return map->size;
-}
-
-static inline size_t calculateIndex(size_t bucketCount, int hash) {
- return ((size_t) hash) & (bucketCount - 1);
-}
-
-static void expandIfNecessary(Hashmap* map) {
- // If the load factor exceeds 0.75...
- if (map->size > (map->bucketCount * 3 / 4)) {
- // Start off with a 0.33 load factor.
- size_t newBucketCount = map->bucketCount << 1;
- Entry** newBuckets = calloc(newBucketCount, sizeof(Entry*));
- if (newBuckets == NULL) {
- // Abort expansion.
- return;
- }
-
- // Move over existing entries.
- size_t i;
- for (i = 0; i < map->bucketCount; i++) {
- Entry* entry = map->buckets[i];
- while (entry != NULL) {
- Entry* next = entry->next;
- size_t index = calculateIndex(newBucketCount, entry->hash);
- entry->next = newBuckets[index];
- newBuckets[index] = entry;
- entry = next;
- }
- }
-
- // Copy over internals.
- free(map->buckets);
- map->buckets = newBuckets;
- map->bucketCount = newBucketCount;
- }
-}
-
-void hashmapLock(Hashmap* map) {
- mutex_lock(&map->lock);
-}
-
-void hashmapUnlock(Hashmap* map) {
- mutex_unlock(&map->lock);
-}
-
-void hashmapFree(Hashmap* map) {
- size_t i;
- for (i = 0; i < map->bucketCount; i++) {
- Entry* entry = map->buckets[i];
- while (entry != NULL) {
- Entry* next = entry->next;
- free(entry);
- entry = next;
- }
- }
- free(map->buckets);
- mutex_destroy(&map->lock);
- free(map);
-}
-
-int hashmapHash(void* key, size_t keySize) {
- int h = keySize;
- char* data = (char*) key;
- size_t i;
- for (i = 0; i < keySize; i++) {
- h = h * 31 + *data;
- data++;
- }
- return h;
-}
-
-static Entry* createEntry(void* key, int hash, void* value) {
- Entry* entry = malloc(sizeof(Entry));
- if (entry == NULL) {
- return NULL;
- }
- entry->key = key;
- entry->hash = hash;
- entry->value = value;
- entry->next = NULL;
- return entry;
-}
-
-static inline bool equalKeys(void* keyA, int hashA, void* keyB, int hashB,
- bool (*equals)(void*, void*)) {
- if (keyA == keyB) {
- return true;
- }
- if (hashA != hashB) {
- return false;
- }
- return equals(keyA, keyB);
-}
-
-void* hashmapPut(Hashmap* map, void* key, void* value) {
- int hash = hashKey(map, key);
- size_t index = calculateIndex(map->bucketCount, hash);
-
- Entry** p = &(map->buckets[index]);
- while (true) {
- Entry* current = *p;
-
- // Add a new entry.
- if (current == NULL) {
- *p = createEntry(key, hash, value);
- if (*p == NULL) {
- errno = ENOMEM;
- return NULL;
- }
- map->size++;
- expandIfNecessary(map);
- return NULL;
- }
-
- // Replace existing entry.
- if (equalKeys(current->key, current->hash, key, hash, map->equals)) {
- void* oldValue = current->value;
- current->value = value;
- return oldValue;
- }
-
- // Move to next entry.
- p = &current->next;
- }
-}
-
-void* hashmapGet(Hashmap* map, void* key) {
- int hash = hashKey(map, key);
- size_t index = calculateIndex(map->bucketCount, hash);
-
- Entry* entry = map->buckets[index];
- while (entry != NULL) {
- if (equalKeys(entry->key, entry->hash, key, hash, map->equals)) {
- return entry->value;
- }
- entry = entry->next;
- }
-
- return NULL;
-}
-
-bool hashmapContainsKey(Hashmap* map, void* key) {
- int hash = hashKey(map, key);
- size_t index = calculateIndex(map->bucketCount, hash);
-
- Entry* entry = map->buckets[index];
- while (entry != NULL) {
- if (equalKeys(entry->key, entry->hash, key, hash, map->equals)) {
- return true;
- }
- entry = entry->next;
- }
-
- return false;
-}
-
-void* hashmapMemoize(Hashmap* map, void* key,
- void* (*initialValue)(void* key, void* context), void* context) {
- int hash = hashKey(map, key);
- size_t index = calculateIndex(map->bucketCount, hash);
-
- Entry** p = &(map->buckets[index]);
- while (true) {
- Entry* current = *p;
-
- // Add a new entry.
- if (current == NULL) {
- *p = createEntry(key, hash, NULL);
- if (*p == NULL) {
- errno = ENOMEM;
- return NULL;
- }
- void* value = initialValue(key, context);
- (*p)->value = value;
- map->size++;
- expandIfNecessary(map);
- return value;
- }
-
- // Return existing value.
- if (equalKeys(current->key, current->hash, key, hash, map->equals)) {
- return current->value;
- }
-
- // Move to next entry.
- p = &current->next;
- }
-}
-
-void* hashmapRemove(Hashmap* map, void* key) {
- int hash = hashKey(map, key);
- size_t index = calculateIndex(map->bucketCount, hash);
-
- // Pointer to the current entry.
- Entry** p = &(map->buckets[index]);
- Entry* current;
- while ((current = *p) != NULL) {
- if (equalKeys(current->key, current->hash, key, hash, map->equals)) {
- void* value = current->value;
- *p = current->next;
- free(current);
- map->size--;
- return value;
- }
-
- p = &current->next;
- }
-
- return NULL;
-}
-
-void hashmapForEach(Hashmap* map,
- bool (*callback)(void* key, void* value, void* context),
- void* context) {
- size_t i;
- for (i = 0; i < map->bucketCount; i++) {
- Entry* entry = map->buckets[i];
- while (entry != NULL) {
- if (!callback(entry->key, entry->value, context)) {
- return;
- }
- entry = entry->next;
- }
- }
-}
-
-size_t hashmapCurrentCapacity(Hashmap* map) {
- size_t bucketCount = map->bucketCount;
- return bucketCount * 3 / 4;
-}
-
-size_t hashmapCountCollisions(Hashmap* map) {
- size_t collisions = 0;
- size_t i;
- for (i = 0; i < map->bucketCount; i++) {
- Entry* entry = map->buckets[i];
- while (entry != NULL) {
- if (entry->next != NULL) {
- collisions++;
- }
- entry = entry->next;
- }
- }
- return collisions;
-}
-
-int hashmapIntHash(void* key) {
- // Return the key value itself.
- return *((int*) key);
-}
-
-bool hashmapIntEquals(void* keyA, void* keyB) {
- int a = *((int*) keyA);
- int b = *((int*) keyB);
- return a == b;
-}
diff --git a/libcutils/load_file.c b/libcutils/load_file.c
deleted file mode 100644
index 99f2965ae..000000000
--- a/libcutils/load_file.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/* libs/cutils/load_file.c
-**
-** Copyright 2006, 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 <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-void *load_file(const char *fn, unsigned *_sz)
-{
- char *data;
- int sz;
- int fd;
-
- data = 0;
- fd = open(fn, O_RDONLY);
- if(fd < 0) return 0;
-
- sz = lseek(fd, 0, SEEK_END);
- if(sz < 0) goto oops;
-
- if(lseek(fd, 0, SEEK_SET) != 0) goto oops;
-
- data = (char*) malloc(sz + 1);
- if(data == 0) goto oops;
-
- if(read(fd, data, sz) != sz) goto oops;
- close(fd);
- data[sz] = 0;
-
- if(_sz) *_sz = sz;
- return data;
-
-oops:
- close(fd);
- if(data != 0) free(data);
- return 0;
-}
diff --git a/libcutils/loghack.h b/libcutils/loghack.h
deleted file mode 100644
index 2bfffe4ec..000000000
--- a/libcutils/loghack.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-/**
- * This is a temporary hack to enable logging from cutils.
- */
-
-#ifndef _CUTILS_LOGHACK_H
-#define _CUTILS_LOGHACK_H
-
-#ifdef HAVE_ANDROID_OS
-#include <cutils/log.h>
-#else
-#include <stdio.h>
-#define LOG(level, ...) \
- ((void)printf("cutils:" level "/" LOG_TAG ": " __VA_ARGS__))
-#define LOGV(...) LOG("V", __VA_ARGS__)
-#define LOGD(...) LOG("D", __VA_ARGS__)
-#define LOGI(...) LOG("I", __VA_ARGS__)
-#define LOGW(...) LOG("W", __VA_ARGS__)
-#define LOGE(...) LOG("E", __VA_ARGS__)
-#define LOG_ALWAYS_FATAL(...) do { LOGE(__VA_ARGS__); exit(1); } while (0)
-#endif
-
-#endif // _CUTILS_LOGHACK_H
diff --git a/libcutils/memory.c b/libcutils/memory.c
deleted file mode 100644
index ef6c7e663..000000000
--- a/libcutils/memory.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2007 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 <cutils/memory.h>
-
-void android_memset16(uint16_t* dst, uint16_t value, size_t size)
-{
- size >>= 1;
- while (size--) {
- *dst++ = value;
- }
-}
-
-void android_memset32(uint32_t* dst, uint32_t value, size_t size)
-{
- size >>= 2;
- while (size--) {
- *dst++ = value;
- }
-}
-
-#if !HAVE_STRLCPY
-/*
- * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <string.h>
-
-/* Implementation of strlcpy() for platforms that don't already have it. */
-
-/*
- * Copy src to string dst of size siz. At most siz-1 characters
- * will be copied. Always NUL terminates (unless siz == 0).
- * Returns strlen(src); if retval >= siz, truncation occurred.
- */
-size_t
-strlcpy(char *dst, const char *src, size_t siz)
-{
- char *d = dst;
- const char *s = src;
- size_t n = siz;
-
- /* Copy as many bytes as will fit */
- if (n != 0) {
- while (--n != 0) {
- if ((*d++ = *s++) == '\0')
- break;
- }
- }
-
- /* Not enough room in dst, add NUL and traverse rest of src */
- if (n == 0) {
- if (siz != 0)
- *d = '\0'; /* NUL-terminate dst */
- while (*s++)
- ;
- }
-
- return(s - src - 1); /* count does not include NUL */
-}
-#endif
diff --git a/libcutils/memset32.S b/libcutils/memset32.S
deleted file mode 100644
index 469726563..000000000
--- a/libcutils/memset32.S
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2006 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.
- */
-/*
- * memset32.S
- *
- */
-
- .text
- .align
-
- .global android_memset32
- .type android_memset32, %function
- .global android_memset16
- .type android_memset16, %function
-
- /*
- * Optimized memset32 and memset16 for ARM.
- *
- * void android_memset16(uint16_t* dst, uint16_t value, size_t size);
- * void android_memset32(uint32_t* dst, uint32_t value, size_t size);
- *
- */
-
-android_memset16:
- .fnstart
- cmp r2, #1
- bxle lr
-
- /* expand the data to 32 bits */
- mov r1, r1, lsl #16
- orr r1, r1, r1, lsr #16
-
- /* align to 32 bits */
- tst r0, #2
- strneh r1, [r0], #2
- subne r2, r2, #2
- .fnend
-
-android_memset32:
- .fnstart
- .save {lr}
- str lr, [sp, #-4]!
-
- /* align the destination to a cache-line */
- mov r12, r1
- mov lr, r1
- rsb r3, r0, #0
- ands r3, r3, #0x1C
- beq .Laligned32
- cmp r3, r2
- andhi r3, r2, #0x1C
- sub r2, r2, r3
-
- /* conditionally writes 0 to 7 words (length in r3) */
- movs r3, r3, lsl #28
- stmcsia r0!, {r1, lr}
- stmcsia r0!, {r1, lr}
- stmmiia r0!, {r1, lr}
- movs r3, r3, lsl #2
- strcs r1, [r0], #4
-
-.Laligned32:
- mov r3, r1
-1: subs r2, r2, #32
- stmhsia r0!, {r1,r3,r12,lr}
- stmhsia r0!, {r1,r3,r12,lr}
- bhs 1b
- add r2, r2, #32
-
- /* conditionally stores 0 to 30 bytes */
- movs r2, r2, lsl #28
- stmcsia r0!, {r1,r3,r12,lr}
- stmmiia r0!, {r1,lr}
- movs r2, r2, lsl #2
- strcs r1, [r0], #4
- strmih lr, [r0], #2
-
- ldr lr, [sp], #4
- bx lr
- .fnend
diff --git a/libcutils/mq.c b/libcutils/mq.c
deleted file mode 100644
index 3b65f1f16..000000000
--- a/libcutils/mq.c
+++ /dev/null
@@ -1,1357 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-#define LOG_TAG "mq"
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <sys/uio.h>
-
-#include <cutils/array.h>
-#include <cutils/hashmap.h>
-#include <cutils/selector.h>
-
-#include "loghack.h"
-#include "buffer.h"
-
-/** Number of dead peers to remember. */
-#define PEER_HISTORY (16)
-
-typedef struct sockaddr SocketAddress;
-typedef struct sockaddr_un UnixAddress;
-
-/**
- * Process/user/group ID. We don't use ucred directly because it's only
- * available on Linux.
- */
-typedef struct {
- pid_t pid;
- uid_t uid;
- gid_t gid;
-} Credentials;
-
-/** Listens for bytes coming from remote peers. */
-typedef void BytesListener(Credentials credentials, char* bytes, size_t size);
-
-/** Listens for the deaths of remote peers. */
-typedef void DeathListener(pid_t pid);
-
-/** Types of packets. */
-typedef enum {
- /** Request for a connection to another peer. */
- CONNECTION_REQUEST,
-
- /** A connection to another peer. */
- CONNECTION,
-
- /** Reports a failed connection attempt. */
- CONNECTION_ERROR,
-
- /** A generic packet of bytes. */
- BYTES,
-} PacketType;
-
-typedef enum {
- /** Reading a packet header. */
- READING_HEADER,
-
- /** Waiting for a connection from the master. */
- ACCEPTING_CONNECTION,
-
- /** Reading bytes. */
- READING_BYTES,
-} InputState;
-
-/** A packet header. */
-// TODO: Use custom headers for master->peer, peer->master, peer->peer.
-typedef struct {
- PacketType type;
- union {
- /** Packet size. Used for BYTES. */
- size_t size;
-
- /** Credentials. Used for CONNECTION and CONNECTION_REQUEST. */
- Credentials credentials;
- };
-} Header;
-
-/** A packet which will be sent to a peer. */
-typedef struct OutgoingPacket OutgoingPacket;
-struct OutgoingPacket {
- /** Packet header. */
- Header header;
-
- union {
- /** Connection to peer. Used with CONNECTION. */
- int socket;
-
- /** Buffer of bytes. Used with BYTES. */
- Buffer* bytes;
- };
-
- /** Frees all resources associated with this packet. */
- void (*free)(OutgoingPacket* packet);
-
- /** Optional context. */
- void* context;
-
- /** Next packet in the queue. */
- OutgoingPacket* nextPacket;
-};
-
-/** Represents a remote peer. */
-typedef struct PeerProxy PeerProxy;
-
-/** Local peer state. You typically have one peer per process. */
-typedef struct {
- /** This peer's PID. */
- pid_t pid;
-
- /**
- * Map from pid to peer proxy. The peer has a peer proxy for each remote
- * peer it's connected to.
- *
- * Acquire mutex before use.
- */
- Hashmap* peerProxies;
-
- /** Manages I/O. */
- Selector* selector;
-
- /** Used to synchronize operations with the selector thread. */
- pthread_mutex_t mutex;
-
- /** Is this peer the master? */
- bool master;
-
- /** Peer proxy for the master. */
- PeerProxy* masterProxy;
-
- /** Listens for packets from remote peers. */
- BytesListener* onBytes;
-
- /** Listens for deaths of remote peers. */
- DeathListener* onDeath;
-
- /** Keeps track of recently dead peers. Requires mutex. */
- pid_t deadPeers[PEER_HISTORY];
- size_t deadPeerCursor;
-} Peer;
-
-struct PeerProxy {
- /** Credentials of the remote process. */
- Credentials credentials;
-
- /** Keeps track of data coming in from the remote peer. */
- InputState inputState;
- Buffer* inputBuffer;
- PeerProxy* connecting;
-
- /** File descriptor for this peer. */
- SelectableFd* fd;
-
- /**
- * Queue of packets to be written out to the remote peer.
- *
- * Requires mutex.
- */
- // TODO: Limit queue length.
- OutgoingPacket* currentPacket;
- OutgoingPacket* lastPacket;
-
- /** Used to write outgoing header. */
- Buffer outgoingHeader;
-
- /** True if this is the master's proxy. */
- bool master;
-
- /** Reference back to the local peer. */
- Peer* peer;
-
- /**
- * Used in master only. Maps this peer proxy to other peer proxies to
- * which the peer has been connected to. Maps pid to PeerProxy. Helps
- * keep track of which connections we've sent to whom.
- */
- Hashmap* connections;
-};
-
-/** Server socket path. */
-static const char* MASTER_PATH = "/master.peer";
-
-/** Credentials of the master peer. */
-static const Credentials MASTER_CREDENTIALS = {0, 0, 0};
-
-/** Creates a peer proxy and adds it to the peer proxy map. */
-static PeerProxy* peerProxyCreate(Peer* peer, Credentials credentials);
-
-/** Sets the non-blocking flag on a descriptor. */
-static void setNonBlocking(int fd) {
- int flags;
- if ((flags = fcntl(fd, F_GETFL, 0)) < 0) {
- LOG_ALWAYS_FATAL("fcntl() error: %s", strerror(errno));
- }
- if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
- LOG_ALWAYS_FATAL("fcntl() error: %s", strerror(errno));
- }
-}
-
-/** Closes a fd and logs a warning if the close fails. */
-static void closeWithWarning(int fd) {
- int result = close(fd);
- if (result == -1) {
- LOGW("close() error: %s", strerror(errno));
- }
-}
-
-/** Hashes pid_t keys. */
-static int pidHash(void* key) {
- pid_t* pid = (pid_t*) key;
- return (int) (*pid);
-}
-
-/** Compares pid_t keys. */
-static bool pidEquals(void* keyA, void* keyB) {
- pid_t* a = (pid_t*) keyA;
- pid_t* b = (pid_t*) keyB;
- return *a == *b;
-}
-
-/** Gets the master address. Not thread safe. */
-static UnixAddress* getMasterAddress() {
- static UnixAddress masterAddress;
- static bool initialized = false;
- if (initialized == false) {
- masterAddress.sun_family = AF_LOCAL;
- strcpy(masterAddress.sun_path, MASTER_PATH);
- initialized = true;
- }
- return &masterAddress;
-}
-
-/** Gets exclusive access to the peer for this thread. */
-static void peerLock(Peer* peer) {
- pthread_mutex_lock(&peer->mutex);
-}
-
-/** Releases exclusive access to the peer. */
-static void peerUnlock(Peer* peer) {
- pthread_mutex_unlock(&peer->mutex);
-}
-
-/** Frees a simple, i.e. header-only, outgoing packet. */
-static void outgoingPacketFree(OutgoingPacket* packet) {
- LOGD("Freeing outgoing packet.");
- free(packet);
-}
-
-/**
- * Prepare to read a new packet from the peer.
- */
-static void peerProxyExpectHeader(PeerProxy* peerProxy) {
- peerProxy->inputState = READING_HEADER;
- bufferPrepareForRead(peerProxy->inputBuffer, sizeof(Header));
-}
-
-/** Sets up the buffer for the outgoing header. */
-static void peerProxyPrepareOutgoingHeader(PeerProxy* peerProxy) {
- peerProxy->outgoingHeader.data
- = (char*) &(peerProxy->currentPacket->header);
- peerProxy->outgoingHeader.size = sizeof(Header);
- bufferPrepareForWrite(&peerProxy->outgoingHeader);
-}
-
-/** Adds a packet to the end of the queue. Callers must have the mutex. */
-static void peerProxyEnqueueOutgoingPacket(PeerProxy* peerProxy,
- OutgoingPacket* newPacket) {
- newPacket->nextPacket = NULL; // Just in case.
- if (peerProxy->currentPacket == NULL) {
- // The queue is empty.
- peerProxy->currentPacket = newPacket;
- peerProxy->lastPacket = newPacket;
-
- peerProxyPrepareOutgoingHeader(peerProxy);
- } else {
- peerProxy->lastPacket->nextPacket = newPacket;
- }
-}
-
-/** Takes the peer lock and enqueues the given packet. */
-static void peerProxyLockAndEnqueueOutgoingPacket(PeerProxy* peerProxy,
- OutgoingPacket* newPacket) {
- Peer* peer = peerProxy->peer;
- peerLock(peer);
- peerProxyEnqueueOutgoingPacket(peerProxy, newPacket);
- peerUnlock(peer);
-}
-
-/**
- * Frees current packet and moves to the next one. Returns true if there is
- * a next packet or false if the queue is empty.
- */
-static bool peerProxyNextPacket(PeerProxy* peerProxy) {
- Peer* peer = peerProxy->peer;
- peerLock(peer);
-
- OutgoingPacket* current = peerProxy->currentPacket;
-
- if (current == NULL) {
- // The queue is already empty.
- peerUnlock(peer);
- return false;
- }
-
- OutgoingPacket* next = current->nextPacket;
- peerProxy->currentPacket = next;
- current->nextPacket = NULL;
- current->free(current);
- if (next == NULL) {
- // The queue is empty.
- peerProxy->lastPacket = NULL;
- peerUnlock(peer);
- return false;
- } else {
- peerUnlock(peer);
- peerProxyPrepareOutgoingHeader(peerProxy);
-
- // TODO: Start writing next packet? It would reduce the number of
- // system calls, but we could also starve other peers.
- return true;
- }
-}
-
-/**
- * Checks whether a peer died recently.
- */
-static bool peerIsDead(Peer* peer, pid_t pid) {
- size_t i;
- for (i = 0; i < PEER_HISTORY; i++) {
- pid_t deadPeer = peer->deadPeers[i];
- if (deadPeer == 0) {
- return false;
- }
- if (deadPeer == pid) {
- return true;
- }
- }
- return false;
-}
-
-/**
- * Cleans up connection information.
- */
-static bool peerProxyRemoveConnection(void* key, void* value, void* context) {
- PeerProxy* deadPeer = (PeerProxy*) context;
- PeerProxy* otherPeer = (PeerProxy*) value;
- hashmapRemove(otherPeer->connections, &(deadPeer->credentials.pid));
- return true;
-}
-
-/**
- * Called when the peer dies.
- */
-static void peerProxyKill(PeerProxy* peerProxy, bool errnoIsSet) {
- if (errnoIsSet) {
- LOGI("Peer %d died. errno: %s", peerProxy->credentials.pid,
- strerror(errno));
- } else {
- LOGI("Peer %d died.", peerProxy->credentials.pid);
- }
-
- // If we lost the master, we're up a creek. We can't let this happen.
- if (peerProxy->master) {
- LOG_ALWAYS_FATAL("Lost connection to master.");
- }
-
- Peer* localPeer = peerProxy->peer;
- pid_t pid = peerProxy->credentials.pid;
-
- peerLock(localPeer);
-
- // Remember for awhile that the peer died.
- localPeer->deadPeers[localPeer->deadPeerCursor]
- = peerProxy->credentials.pid;
- localPeer->deadPeerCursor++;
- if (localPeer->deadPeerCursor == PEER_HISTORY) {
- localPeer->deadPeerCursor = 0;
- }
-
- // Remove from peer map.
- hashmapRemove(localPeer->peerProxies, &pid);
-
- // External threads can no longer get to this peer proxy, so we don't
- // need the lock anymore.
- peerUnlock(localPeer);
-
- // Remove the fd from the selector.
- if (peerProxy->fd != NULL) {
- peerProxy->fd->remove = true;
- }
-
- // Clear outgoing packet queue.
- while (peerProxyNextPacket(peerProxy)) {}
-
- bufferFree(peerProxy->inputBuffer);
-
- // This only applies to the master.
- if (peerProxy->connections != NULL) {
- // We can't leave these other maps pointing to freed memory.
- hashmapForEach(peerProxy->connections, &peerProxyRemoveConnection,
- peerProxy);
- hashmapFree(peerProxy->connections);
- }
-
- // Invoke death listener.
- localPeer->onDeath(pid);
-
- // Free the peer proxy itself.
- free(peerProxy);
-}
-
-static void peerProxyHandleError(PeerProxy* peerProxy, char* functionName) {
- if (errno == EINTR) {
- // Log interruptions but otherwise ignore them.
- LOGW("%s() interrupted.", functionName);
- } else if (errno == EAGAIN) {
- LOGD("EWOULDBLOCK");
- // Ignore.
- } else {
- LOGW("Error returned by %s().", functionName);
- peerProxyKill(peerProxy, true);
- }
-}
-
-/**
- * Buffers output sent to a peer. May be called multiple times until the entire
- * buffer is filled. Returns true when the buffer is empty.
- */
-static bool peerProxyWriteFromBuffer(PeerProxy* peerProxy, Buffer* outgoing) {
- ssize_t size = bufferWrite(outgoing, peerProxy->fd->fd);
- if (size < 0) {
- peerProxyHandleError(peerProxy, "write");
- return false;
- } else {
- return bufferWriteComplete(outgoing);
- }
-}
-
-/** Writes packet bytes to peer. */
-static void peerProxyWriteBytes(PeerProxy* peerProxy) {
- Buffer* buffer = peerProxy->currentPacket->bytes;
- if (peerProxyWriteFromBuffer(peerProxy, buffer)) {
- LOGD("Bytes written.");
- peerProxyNextPacket(peerProxy);
- }
-}
-
-/** Sends a socket to the peer. */
-static void peerProxyWriteConnection(PeerProxy* peerProxy) {
- int socket = peerProxy->currentPacket->socket;
-
- // Why does sending and receiving fds have to be such a PITA?
- struct msghdr msg;
- struct iovec iov[1];
-
- union {
- struct cmsghdr cm;
- char control[CMSG_SPACE(sizeof(int))];
- } control_un;
-
- struct cmsghdr *cmptr;
-
- msg.msg_control = control_un.control;
- msg.msg_controllen = sizeof(control_un.control);
- cmptr = CMSG_FIRSTHDR(&msg);
- cmptr->cmsg_len = CMSG_LEN(sizeof(int));
- cmptr->cmsg_level = SOL_SOCKET;
- cmptr->cmsg_type = SCM_RIGHTS;
-
- // Store the socket in the message.
- *((int *) CMSG_DATA(cmptr)) = peerProxy->currentPacket->socket;
-
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- iov[0].iov_base = "";
- iov[0].iov_len = 1;
- msg.msg_iov = iov;
- msg.msg_iovlen = 1;
-
- ssize_t result = sendmsg(peerProxy->fd->fd, &msg, 0);
-
- if (result < 0) {
- peerProxyHandleError(peerProxy, "sendmsg");
- } else {
- // Success. Queue up the next packet.
- peerProxyNextPacket(peerProxy);
-
- }
-}
-
-/**
- * Writes some outgoing data.
- */
-static void peerProxyWrite(SelectableFd* fd) {
- // TODO: Try to write header and body with one system call.
-
- PeerProxy* peerProxy = (PeerProxy*) fd->data;
- OutgoingPacket* current = peerProxy->currentPacket;
-
- if (current == NULL) {
- // We have nothing left to write.
- return;
- }
-
- // Write the header.
- Buffer* outgoingHeader = &peerProxy->outgoingHeader;
- bool headerWritten = bufferWriteComplete(outgoingHeader);
- if (!headerWritten) {
- LOGD("Writing header...");
- headerWritten = peerProxyWriteFromBuffer(peerProxy, outgoingHeader);
- if (headerWritten) {
- LOGD("Header written.");
- }
- }
-
- // Write body.
- if (headerWritten) {
- PacketType type = current->header.type;
- switch (type) {
- case CONNECTION:
- peerProxyWriteConnection(peerProxy);
- break;
- case BYTES:
- peerProxyWriteBytes(peerProxy);
- break;
- case CONNECTION_REQUEST:
- case CONNECTION_ERROR:
- // These packets consist solely of a header.
- peerProxyNextPacket(peerProxy);
- break;
- default:
- LOG_ALWAYS_FATAL("Unknown packet type: %d", type);
- }
- }
-}
-
-/**
- * Sets up a peer proxy's fd before we try to select() it.
- */
-static void peerProxyBeforeSelect(SelectableFd* fd) {
- LOGD("Before select...");
-
- PeerProxy* peerProxy = (PeerProxy*) fd->data;
-
- peerLock(peerProxy->peer);
- bool hasPackets = peerProxy->currentPacket != NULL;
- peerUnlock(peerProxy->peer);
-
- if (hasPackets) {
- LOGD("Packets found. Setting onWritable().");
-
- fd->onWritable = &peerProxyWrite;
- } else {
- // We have nothing to write.
- fd->onWritable = NULL;
- }
-}
-
-/** Prepare to read bytes from the peer. */
-static void peerProxyExpectBytes(PeerProxy* peerProxy, Header* header) {
- LOGD("Expecting %d bytes.", header->size);
-
- peerProxy->inputState = READING_BYTES;
- if (bufferPrepareForRead(peerProxy->inputBuffer, header->size) == -1) {
- LOGW("Couldn't allocate memory for incoming data. Size: %u",
- (unsigned int) header->size);
-
- // TODO: Ignore the packet and log a warning?
- peerProxyKill(peerProxy, false);
- }
-}
-
-/**
- * Gets a peer proxy for the given ID. Creates a peer proxy if necessary.
- * Sends a connection request to the master if desired.
- *
- * Returns NULL if an error occurs. Sets errno to EHOSTDOWN if the peer died
- * or ENOMEM if memory couldn't be allocated.
- */
-static PeerProxy* peerProxyGetOrCreate(Peer* peer, pid_t pid,
- bool requestConnection) {
- if (pid == peer->pid) {
- errno = EINVAL;
- return NULL;
- }
-
- if (peerIsDead(peer, pid)) {
- errno = EHOSTDOWN;
- return NULL;
- }
-
- PeerProxy* peerProxy = hashmapGet(peer->peerProxies, &pid);
- if (peerProxy != NULL) {
- return peerProxy;
- }
-
- // If this is the master peer, we already know about all peers.
- if (peer->master) {
- errno = EHOSTDOWN;
- return NULL;
- }
-
- // Try to create a peer proxy.
- Credentials credentials;
- credentials.pid = pid;
-
- // Fake gid and uid until we have the real thing. The real creds are
- // filled in by masterProxyExpectConnection(). These fake creds will
- // never be exposed to the user.
- credentials.uid = 0;
- credentials.gid = 0;
-
- // Make sure we can allocate the connection request packet.
- OutgoingPacket* packet = NULL;
- if (requestConnection) {
- packet = calloc(1, sizeof(OutgoingPacket));
- if (packet == NULL) {
- errno = ENOMEM;
- return NULL;
- }
-
- packet->header.type = CONNECTION_REQUEST;
- packet->header.credentials = credentials;
- packet->free = &outgoingPacketFree;
- }
-
- peerProxy = peerProxyCreate(peer, credentials);
- if (peerProxy == NULL) {
- free(packet);
- errno = ENOMEM;
- return NULL;
- } else {
- // Send a connection request to the master.
- if (requestConnection) {
- PeerProxy* masterProxy = peer->masterProxy;
- peerProxyEnqueueOutgoingPacket(masterProxy, packet);
- }
-
- return peerProxy;
- }
-}
-
-/**
- * Switches the master peer proxy into a state where it's waiting for a
- * connection from the master.
- */
-static void masterProxyExpectConnection(PeerProxy* masterProxy,
- Header* header) {
- // TODO: Restructure things so we don't need this check.
- // Verify that this really is the master.
- if (!masterProxy->master) {
- LOGW("Non-master process %d tried to send us a connection.",
- masterProxy->credentials.pid);
- // Kill off the evil peer.
- peerProxyKill(masterProxy, false);
- return;
- }
-
- masterProxy->inputState = ACCEPTING_CONNECTION;
- Peer* localPeer = masterProxy->peer;
-
- // Create a peer proxy so we have somewhere to stash the creds.
- // See if we already have a proxy set up.
- pid_t pid = header->credentials.pid;
- peerLock(localPeer);
- PeerProxy* peerProxy = peerProxyGetOrCreate(localPeer, pid, false);
- if (peerProxy == NULL) {
- LOGW("Peer proxy creation failed: %s", strerror(errno));
- } else {
- // Fill in full credentials.
- peerProxy->credentials = header->credentials;
- }
- peerUnlock(localPeer);
-
- // Keep track of which peer proxy we're accepting a connection for.
- masterProxy->connecting = peerProxy;
-}
-
-/**
- * Reads input from a peer process.
- */
-static void peerProxyRead(SelectableFd* fd);
-
-/** Sets up fd callbacks. */
-static void peerProxySetFd(PeerProxy* peerProxy, SelectableFd* fd) {
- peerProxy->fd = fd;
- fd->data = peerProxy;
- fd->onReadable = &peerProxyRead;
- fd->beforeSelect = &peerProxyBeforeSelect;
-
- // Make the socket non-blocking.
- setNonBlocking(fd->fd);
-}
-
-/**
- * Accepts a connection sent by the master proxy.
- */
-static void masterProxyAcceptConnection(PeerProxy* masterProxy) {
- struct msghdr msg;
- struct iovec iov[1];
- ssize_t size;
- char ignored;
- int incomingFd;
-
- // TODO: Reuse code which writes the connection. Who the heck designed
- // this API anyway?
- union {
- struct cmsghdr cm;
- char control[CMSG_SPACE(sizeof(int))];
- } control_un;
- struct cmsghdr *cmptr;
- msg.msg_control = control_un.control;
- msg.msg_controllen = sizeof(control_un.control);
-
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
-
- // We sent 1 byte of data so we can detect EOF.
- iov[0].iov_base = &ignored;
- iov[0].iov_len = 1;
- msg.msg_iov = iov;
- msg.msg_iovlen = 1;
-
- size = recvmsg(masterProxy->fd->fd, &msg, 0);
- if (size < 0) {
- if (errno == EINTR) {
- // Log interruptions but otherwise ignore them.
- LOGW("recvmsg() interrupted.");
- return;
- } else if (errno == EAGAIN) {
- // Keep waiting for the connection.
- return;
- } else {
- LOG_ALWAYS_FATAL("Error reading connection from master: %s",
- strerror(errno));
- }
- } else if (size == 0) {
- // EOF.
- LOG_ALWAYS_FATAL("Received EOF from master.");
- }
-
- // Extract fd from message.
- if ((cmptr = CMSG_FIRSTHDR(&msg)) != NULL
- && cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {
- if (cmptr->cmsg_level != SOL_SOCKET) {
- LOG_ALWAYS_FATAL("Expected SOL_SOCKET.");
- }
- if (cmptr->cmsg_type != SCM_RIGHTS) {
- LOG_ALWAYS_FATAL("Expected SCM_RIGHTS.");
- }
- incomingFd = *((int*) CMSG_DATA(cmptr));
- } else {
- LOG_ALWAYS_FATAL("Expected fd.");
- }
-
- // The peer proxy this connection is for.
- PeerProxy* peerProxy = masterProxy->connecting;
- if (peerProxy == NULL) {
- LOGW("Received connection for unknown peer.");
- closeWithWarning(incomingFd);
- } else {
- Peer* peer = masterProxy->peer;
-
- SelectableFd* selectableFd = selectorAdd(peer->selector, incomingFd);
- if (selectableFd == NULL) {
- LOGW("Error adding fd to selector for %d.",
- peerProxy->credentials.pid);
- closeWithWarning(incomingFd);
- peerProxyKill(peerProxy, false);
- }
-
- peerProxySetFd(peerProxy, selectableFd);
- }
-
- peerProxyExpectHeader(masterProxy);
-}
-
-/**
- * Frees an outgoing packet containing a connection.
- */
-static void outgoingPacketFreeSocket(OutgoingPacket* packet) {
- closeWithWarning(packet->socket);
- outgoingPacketFree(packet);
-}
-
-/**
- * Connects two known peers.
- */
-static void masterConnectPeers(PeerProxy* peerA, PeerProxy* peerB) {
- int sockets[2];
- int result = socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets);
- if (result == -1) {
- LOGW("socketpair() error: %s", strerror(errno));
- // TODO: Send CONNECTION_FAILED packets to peers.
- return;
- }
-
- OutgoingPacket* packetA = calloc(1, sizeof(OutgoingPacket));
- OutgoingPacket* packetB = calloc(1, sizeof(OutgoingPacket));
- if (packetA == NULL || packetB == NULL) {
- free(packetA);
- free(packetB);
- LOGW("malloc() error. Failed to tell process %d that process %d is"
- " dead.", peerA->credentials.pid, peerB->credentials.pid);
- return;
- }
-
- packetA->header.type = CONNECTION;
- packetB->header.type = CONNECTION;
-
- packetA->header.credentials = peerB->credentials;
- packetB->header.credentials = peerA->credentials;
-
- packetA->socket = sockets[0];
- packetB->socket = sockets[1];
-
- packetA->free = &outgoingPacketFreeSocket;
- packetB->free = &outgoingPacketFreeSocket;
-
- peerLock(peerA->peer);
- peerProxyEnqueueOutgoingPacket(peerA, packetA);
- peerProxyEnqueueOutgoingPacket(peerB, packetB);
- peerUnlock(peerA->peer);
-}
-
-/**
- * Informs a peer that the peer they're trying to connect to couldn't be
- * found.
- */
-static void masterReportConnectionError(PeerProxy* peerProxy,
- Credentials credentials) {
- OutgoingPacket* packet = calloc(1, sizeof(OutgoingPacket));
- if (packet == NULL) {
- LOGW("malloc() error. Failed to tell process %d that process %d is"
- " dead.", peerProxy->credentials.pid, credentials.pid);
- return;
- }
-
- packet->header.type = CONNECTION_ERROR;
- packet->header.credentials = credentials;
- packet->free = &outgoingPacketFree;
-
- peerProxyLockAndEnqueueOutgoingPacket(peerProxy, packet);
-}
-
-/**
- * Handles a request to be connected to another peer.
- */
-static void masterHandleConnectionRequest(PeerProxy* peerProxy,
- Header* header) {
- Peer* master = peerProxy->peer;
- pid_t targetPid = header->credentials.pid;
- if (!hashmapContainsKey(peerProxy->connections, &targetPid)) {
- // We haven't connected these peers yet.
- PeerProxy* targetPeer
- = (PeerProxy*) hashmapGet(master->peerProxies, &targetPid);
- if (targetPeer == NULL) {
- // Unknown process.
- masterReportConnectionError(peerProxy, header->credentials);
- } else {
- masterConnectPeers(peerProxy, targetPeer);
- }
- }
-
- // This packet is complete. Get ready for the next one.
- peerProxyExpectHeader(peerProxy);
-}
-
-/**
- * The master told us this peer is dead.
- */
-static void masterProxyHandleConnectionError(PeerProxy* masterProxy,
- Header* header) {
- Peer* peer = masterProxy->peer;
-
- // Look up the peer proxy.
- pid_t pid = header->credentials.pid;
- PeerProxy* peerProxy = NULL;
- peerLock(peer);
- peerProxy = hashmapGet(peer->peerProxies, &pid);
- peerUnlock(peer);
-
- if (peerProxy != NULL) {
- LOGI("Couldn't connect to %d.", pid);
- peerProxyKill(peerProxy, false);
- } else {
- LOGW("Peer proxy for %d not found. This shouldn't happen.", pid);
- }
-
- peerProxyExpectHeader(masterProxy);
-}
-
-/**
- * Handles a packet header.
- */
-static void peerProxyHandleHeader(PeerProxy* peerProxy, Header* header) {
- switch (header->type) {
- case CONNECTION_REQUEST:
- masterHandleConnectionRequest(peerProxy, header);
- break;
- case CONNECTION:
- masterProxyExpectConnection(peerProxy, header);
- break;
- case CONNECTION_ERROR:
- masterProxyHandleConnectionError(peerProxy, header);
- break;
- case BYTES:
- peerProxyExpectBytes(peerProxy, header);
- break;
- default:
- LOGW("Invalid packet type from %d: %d", peerProxy->credentials.pid,
- header->type);
- peerProxyKill(peerProxy, false);
- }
-}
-
-/**
- * Buffers input sent by peer. May be called multiple times until the entire
- * buffer is filled. Returns true when the buffer is full.
- */
-static bool peerProxyBufferInput(PeerProxy* peerProxy) {
- Buffer* in = peerProxy->inputBuffer;
- ssize_t size = bufferRead(in, peerProxy->fd->fd);
- if (size < 0) {
- peerProxyHandleError(peerProxy, "read");
- return false;
- } else if (size == 0) {
- // EOF.
- LOGI("EOF");
- peerProxyKill(peerProxy, false);
- return false;
- } else if (bufferReadComplete(in)) {
- // We're done!
- return true;
- } else {
- // Continue reading.
- return false;
- }
-}
-
-/**
- * Reads input from a peer process.
- */
-static void peerProxyRead(SelectableFd* fd) {
- LOGD("Reading...");
- PeerProxy* peerProxy = (PeerProxy*) fd->data;
- int state = peerProxy->inputState;
- Buffer* in = peerProxy->inputBuffer;
- switch (state) {
- case READING_HEADER:
- if (peerProxyBufferInput(peerProxy)) {
- LOGD("Header read.");
- // We've read the complete header.
- Header* header = (Header*) in->data;
- peerProxyHandleHeader(peerProxy, header);
- }
- break;
- case READING_BYTES:
- LOGD("Reading bytes...");
- if (peerProxyBufferInput(peerProxy)) {
- LOGD("Bytes read.");
- // We have the complete packet. Notify bytes listener.
- peerProxy->peer->onBytes(peerProxy->credentials,
- in->data, in->size);
-
- // Get ready for the next packet.
- peerProxyExpectHeader(peerProxy);
- }
- break;
- case ACCEPTING_CONNECTION:
- masterProxyAcceptConnection(peerProxy);
- break;
- default:
- LOG_ALWAYS_FATAL("Unknown state: %d", state);
- }
-}
-
-static PeerProxy* peerProxyCreate(Peer* peer, Credentials credentials) {
- PeerProxy* peerProxy = calloc(1, sizeof(PeerProxy));
- if (peerProxy == NULL) {
- return NULL;
- }
-
- peerProxy->inputBuffer = bufferCreate(sizeof(Header));
- if (peerProxy->inputBuffer == NULL) {
- free(peerProxy);
- return NULL;
- }
-
- peerProxy->peer = peer;
- peerProxy->credentials = credentials;
-
- // Initial state == expecting a header.
- peerProxyExpectHeader(peerProxy);
-
- // Add this proxy to the map. Make sure the key points to the stable memory
- // inside of the peer proxy itself.
- pid_t* pid = &(peerProxy->credentials.pid);
- hashmapPut(peer->peerProxies, pid, peerProxy);
- return peerProxy;
-}
-
-/** Accepts a connection to the master peer. */
-static void masterAcceptConnection(SelectableFd* listenerFd) {
- // Accept connection.
- int socket = accept(listenerFd->fd, NULL, NULL);
- if (socket == -1) {
- LOGW("accept() error: %s", strerror(errno));
- return;
- }
-
- LOGD("Accepted connection as fd %d.", socket);
-
- // Get credentials.
- Credentials credentials;
- struct ucred ucredentials;
- socklen_t credentialsSize = sizeof(struct ucred);
- int result = getsockopt(socket, SOL_SOCKET, SO_PEERCRED,
- &ucredentials, &credentialsSize);
- // We might want to verify credentialsSize.
- if (result == -1) {
- LOGW("getsockopt() error: %s", strerror(errno));
- closeWithWarning(socket);
- return;
- }
-
- // Copy values into our own structure so we know we have the types right.
- credentials.pid = ucredentials.pid;
- credentials.uid = ucredentials.uid;
- credentials.gid = ucredentials.gid;
-
- LOGI("Accepted connection from process %d.", credentials.pid);
-
- Peer* masterPeer = (Peer*) listenerFd->data;
-
- peerLock(masterPeer);
-
- // Make sure we don't already have a connection from that process.
- PeerProxy* peerProxy
- = hashmapGet(masterPeer->peerProxies, &credentials.pid);
- if (peerProxy != NULL) {
- peerUnlock(masterPeer);
- LOGW("Alread connected to process %d.", credentials.pid);
- closeWithWarning(socket);
- return;
- }
-
- // Add connection to the selector.
- SelectableFd* socketFd = selectorAdd(masterPeer->selector, socket);
- if (socketFd == NULL) {
- peerUnlock(masterPeer);
- LOGW("malloc() failed.");
- closeWithWarning(socket);
- return;
- }
-
- // Create a peer proxy.
- peerProxy = peerProxyCreate(masterPeer, credentials);
- peerUnlock(masterPeer);
- if (peerProxy == NULL) {
- LOGW("malloc() failed.");
- socketFd->remove = true;
- closeWithWarning(socket);
- }
- peerProxy->connections = hashmapCreate(10, &pidHash, &pidEquals);
- peerProxySetFd(peerProxy, socketFd);
-}
-
-/**
- * Creates the local peer.
- */
-static Peer* peerCreate() {
- Peer* peer = calloc(1, sizeof(Peer));
- if (peer == NULL) {
- LOG_ALWAYS_FATAL("malloc() error.");
- }
- peer->peerProxies = hashmapCreate(10, &pidHash, &pidEquals);
- peer->selector = selectorCreate();
-
- pthread_mutexattr_t attributes;
- if (pthread_mutexattr_init(&attributes) != 0) {
- LOG_ALWAYS_FATAL("pthread_mutexattr_init() error.");
- }
- if (pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE) != 0) {
- LOG_ALWAYS_FATAL("pthread_mutexattr_settype() error.");
- }
- if (pthread_mutex_init(&peer->mutex, &attributes) != 0) {
- LOG_ALWAYS_FATAL("pthread_mutex_init() error.");
- }
-
- peer->pid = getpid();
- return peer;
-}
-
-/** The local peer. */
-static Peer* localPeer;
-
-/** Frees a packet of bytes. */
-static void outgoingPacketFreeBytes(OutgoingPacket* packet) {
- LOGD("Freeing outgoing packet.");
- bufferFree(packet->bytes);
- free(packet);
-}
-
-/**
- * Sends a packet of bytes to a remote peer. Returns 0 on success.
- *
- * Returns -1 if an error occurs. Sets errno to ENOMEM if memory couldn't be
- * allocated. Sets errno to EHOSTDOWN if the peer died recently. Sets errno
- * to EINVAL if pid is the same as the local pid.
- */
-int peerSendBytes(pid_t pid, const char* bytes, size_t size) {
- Peer* peer = localPeer;
- assert(peer != NULL);
-
- OutgoingPacket* packet = calloc(1, sizeof(OutgoingPacket));
- if (packet == NULL) {
- errno = ENOMEM;
- return -1;
- }
-
- Buffer* copy = bufferCreate(size);
- if (copy == NULL) {
- free(packet);
- errno = ENOMEM;
- return -1;
- }
-
- // Copy data.
- memcpy(copy->data, bytes, size);
- copy->size = size;
-
- packet->bytes = copy;
- packet->header.type = BYTES;
- packet->header.size = size;
- packet->free = outgoingPacketFreeBytes;
- bufferPrepareForWrite(packet->bytes);
-
- peerLock(peer);
-
- PeerProxy* peerProxy = peerProxyGetOrCreate(peer, pid, true);
- if (peerProxy == NULL) {
- // The peer is already dead or we couldn't alloc memory. Either way,
- // errno is set.
- peerUnlock(peer);
- packet->free(packet);
- return -1;
- } else {
- peerProxyEnqueueOutgoingPacket(peerProxy, packet);
- peerUnlock(peer);
- selectorWakeUp(peer->selector);
- return 0;
- }
-}
-
-/** Keeps track of how to free shared bytes. */
-typedef struct {
- void (*free)(void* context);
- void* context;
-} SharedBytesFreer;
-
-/** Frees shared bytes. */
-static void outgoingPacketFreeSharedBytes(OutgoingPacket* packet) {
- SharedBytesFreer* sharedBytesFreer
- = (SharedBytesFreer*) packet->context;
- sharedBytesFreer->free(sharedBytesFreer->context);
- free(sharedBytesFreer);
- free(packet);
-}
-
-/**
- * Sends a packet of bytes to a remote peer without copying the bytes. Calls
- * free() with context after the bytes have been sent.
- *
- * Returns -1 if an error occurs. Sets errno to ENOMEM if memory couldn't be
- * allocated. Sets errno to EHOSTDOWN if the peer died recently. Sets errno
- * to EINVAL if pid is the same as the local pid.
- */
-int peerSendSharedBytes(pid_t pid, char* bytes, size_t size,
- void (*free)(void* context), void* context) {
- Peer* peer = localPeer;
- assert(peer != NULL);
-
- OutgoingPacket* packet = calloc(1, sizeof(OutgoingPacket));
- if (packet == NULL) {
- errno = ENOMEM;
- return -1;
- }
-
- Buffer* wrapper = bufferWrap(bytes, size, size);
- if (wrapper == NULL) {
- free(packet);
- errno = ENOMEM;
- return -1;
- }
-
- SharedBytesFreer* sharedBytesFreer = malloc(sizeof(SharedBytesFreer));
- if (sharedBytesFreer == NULL) {
- free(packet);
- free(wrapper);
- errno = ENOMEM;
- return -1;
- }
- sharedBytesFreer->free = free;
- sharedBytesFreer->context = context;
-
- packet->bytes = wrapper;
- packet->context = sharedBytesFreer;
- packet->header.type = BYTES;
- packet->header.size = size;
- packet->free = &outgoingPacketFreeSharedBytes;
- bufferPrepareForWrite(packet->bytes);
-
- peerLock(peer);
-
- PeerProxy* peerProxy = peerProxyGetOrCreate(peer, pid, true);
- if (peerProxy == NULL) {
- // The peer is already dead or we couldn't alloc memory. Either way,
- // errno is set.
- peerUnlock(peer);
- packet->free(packet);
- return -1;
- } else {
- peerProxyEnqueueOutgoingPacket(peerProxy, packet);
- peerUnlock(peer);
- selectorWakeUp(peer->selector);
- return 0;
- }
-}
-
-/**
- * Starts the master peer. The master peer differs from other peers in that
- * it is responsible for connecting the other peers. You can only have one
- * master peer.
- *
- * Goes into an I/O loop and does not return.
- */
-void masterPeerInitialize(BytesListener* bytesListener,
- DeathListener* deathListener) {
- // Create and bind socket.
- int listenerSocket = socket(AF_LOCAL, SOCK_STREAM, 0);
- if (listenerSocket == -1) {
- LOG_ALWAYS_FATAL("socket() error: %s", strerror(errno));
- }
- unlink(MASTER_PATH);
- int result = bind(listenerSocket, (SocketAddress*) getMasterAddress(),
- sizeof(UnixAddress));
- if (result == -1) {
- LOG_ALWAYS_FATAL("bind() error: %s", strerror(errno));
- }
-
- LOGD("Listener socket: %d", listenerSocket);
-
- // Queue up to 16 connections.
- result = listen(listenerSocket, 16);
- if (result != 0) {
- LOG_ALWAYS_FATAL("listen() error: %s", strerror(errno));
- }
-
- // Make socket non-blocking.
- setNonBlocking(listenerSocket);
-
- // Create the peer for this process. Fail if we already have one.
- if (localPeer != NULL) {
- LOG_ALWAYS_FATAL("Peer is already initialized.");
- }
- localPeer = peerCreate();
- if (localPeer == NULL) {
- LOG_ALWAYS_FATAL("malloc() failed.");
- }
- localPeer->master = true;
- localPeer->onBytes = bytesListener;
- localPeer->onDeath = deathListener;
-
- // Make listener socket selectable.
- SelectableFd* listenerFd = selectorAdd(localPeer->selector, listenerSocket);
- if (listenerFd == NULL) {
- LOG_ALWAYS_FATAL("malloc() error.");
- }
- listenerFd->data = localPeer;
- listenerFd->onReadable = &masterAcceptConnection;
-}
-
-/**
- * Starts a local peer.
- *
- * Goes into an I/O loop and does not return.
- */
-void peerInitialize(BytesListener* bytesListener,
- DeathListener* deathListener) {
- // Connect to master peer.
- int masterSocket = socket(AF_LOCAL, SOCK_STREAM, 0);
- if (masterSocket == -1) {
- LOG_ALWAYS_FATAL("socket() error: %s", strerror(errno));
- }
- int result = connect(masterSocket, (SocketAddress*) getMasterAddress(),
- sizeof(UnixAddress));
- if (result != 0) {
- LOG_ALWAYS_FATAL("connect() error: %s", strerror(errno));
- }
-
- // Create the peer for this process. Fail if we already have one.
- if (localPeer != NULL) {
- LOG_ALWAYS_FATAL("Peer is already initialized.");
- }
- localPeer = peerCreate();
- if (localPeer == NULL) {
- LOG_ALWAYS_FATAL("malloc() failed.");
- }
- localPeer->onBytes = bytesListener;
- localPeer->onDeath = deathListener;
-
- // Make connection selectable.
- SelectableFd* masterFd = selectorAdd(localPeer->selector, masterSocket);
- if (masterFd == NULL) {
- LOG_ALWAYS_FATAL("malloc() error.");
- }
-
- // Create a peer proxy for the master peer.
- PeerProxy* masterProxy = peerProxyCreate(localPeer, MASTER_CREDENTIALS);
- if (masterProxy == NULL) {
- LOG_ALWAYS_FATAL("malloc() error.");
- }
- peerProxySetFd(masterProxy, masterFd);
- masterProxy->master = true;
- localPeer->masterProxy = masterProxy;
-}
-
-/** Starts the master peer I/O loop. Doesn't return. */
-void peerLoop() {
- assert(localPeer != NULL);
-
- // Start selector.
- selectorLoop(localPeer->selector);
-}
-
diff --git a/libcutils/mspace.c b/libcutils/mspace.c
deleted file mode 100644
index 8fd5de77d..000000000
--- a/libcutils/mspace.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/* Copyright 2006 The Android Open Source Project */
-
-/* A wrapper file for dlmalloc.c that compiles in the
- * mspace_*() functions, which provide an interface for
- * creating multiple heaps.
- */
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <sys/ioctl.h>
-
-#include <cutils/ashmem.h>
-
-/* It's a pain getting the mallinfo stuff to work
- * with Linux, OSX, and klibc, so just turn it off
- * for now.
- * TODO: make mallinfo work
- */
-#define NO_MALLINFO 1
-
-/* Allow setting the maximum heap footprint.
- */
-#define USE_MAX_ALLOWED_FOOTPRINT 1
-
-/* Don't try to trim memory.
- * TODO: support this.
- */
-#define MORECORE_CANNOT_TRIM 1
-
-/* Use mmap()d anonymous memory to guarantee
- * that an mspace is contiguous.
- *
- * create_mspace() won't work right if this is
- * defined, so hide the definition of it and
- * break any users at build time.
- */
-#define USE_CONTIGUOUS_MSPACES 1
-#if USE_CONTIGUOUS_MSPACES
-/* This combination of settings forces sys_alloc()
- * to always use MORECORE(). It won't expect the
- * results to be contiguous, but we'll guarantee
- * that they are.
- */
-#define HAVE_MMAP 0
-#define HAVE_MORECORE 1
-#define MORECORE_CONTIGUOUS 0
-/* m is always the appropriate local when MORECORE() is called. */
-#define MORECORE(S) contiguous_mspace_morecore(m, S)
-#define create_mspace HIDDEN_create_mspace_HIDDEN
-#define destroy_mspace HIDDEN_destroy_mspace_HIDDEN
-typedef struct malloc_state *mstate0;
-static void *contiguous_mspace_morecore(mstate0 m, ssize_t nb);
-#endif
-
-#define MSPACES 1
-#define ONLY_MSPACES 1
-#include "../../../bionic/libc/bionic/dlmalloc.c"
-
-#ifndef PAGESIZE
-#define PAGESIZE mparams.page_size
-#endif
-
-#define ALIGN_UP(p, alignment) \
- (((uintptr_t)(p) + (alignment)-1) & ~((alignment)-1))
-
-/* A direct copy of dlmalloc_usable_size(),
- * which isn't compiled in when ONLY_MSPACES is set.
- * The mspace parameter isn't actually necessary,
- * but we include it to be consistent with the
- * rest of the mspace_*() functions.
- */
-size_t mspace_usable_size(mspace _unused, const void* mem) {
- if (mem != 0) {
- const mchunkptr p = mem2chunk(mem);
- if (cinuse(p))
- return chunksize(p) - overhead_for(p);
- }
- return 0;
-}
-
-#if USE_CONTIGUOUS_MSPACES
-#include <sys/mman.h>
-#include <limits.h>
-
-#define CONTIG_STATE_MAGIC 0xf00dd00d
-struct mspace_contig_state {
- unsigned int magic;
- char *brk;
- char *top;
- mspace m;
-};
-
-static void *contiguous_mspace_morecore(mstate m, ssize_t nb) {
- struct mspace_contig_state *cs;
- char *oldbrk;
- const unsigned int pagesize = PAGESIZE;
-
- cs = (struct mspace_contig_state *)((uintptr_t)m & ~(pagesize-1));
- assert(cs->magic == CONTIG_STATE_MAGIC);
- assert(cs->m == m);
-assert(nb >= 0); //xxx deal with the trim case
-
- oldbrk = cs->brk;
- if (nb > 0) {
- /* Break to the first page boundary that satisfies the request.
- */
- char *newbrk = (char *)ALIGN_UP(oldbrk + nb, pagesize);
- if (newbrk > cs->top)
- return CMFAIL;
-
- /* Update the protection on the underlying memory.
- * Pages we've given to dlmalloc are read/write, and
- * pages we haven't are not accessable (read or write
- * will cause a seg fault).
- */
- if (mprotect(cs, newbrk - (char *)cs, PROT_READ | PROT_WRITE) < 0)
- return CMFAIL;
- if (newbrk != cs->top) {
- if (mprotect(newbrk, cs->top - newbrk, PROT_NONE) < 0)
- return CMFAIL;
- }
-
- cs->brk = newbrk;
-
- /* Make sure that dlmalloc will merge this block with the
- * initial block that was passed to create_mspace_with_base().
- * We don't care about extern vs. non-extern, so just clear it.
- */
- m->seg.sflags &= ~EXTERN_BIT;
- }
-
- return oldbrk;
-}
-
-mspace create_contiguous_mspace_with_name(size_t starting_capacity,
- size_t max_capacity, int locked, char const * name) {
- int fd, ret;
- struct mspace_contig_state *cs;
- char buf[ASHMEM_NAME_LEN] = "mspace";
- void *base;
- unsigned int pagesize;
- mstate m;
-
- if (starting_capacity > max_capacity)
- return (mspace)0;
-
- init_mparams();
- pagesize = PAGESIZE;
-
- /* Create the anonymous memory that will back the mspace.
- * This reserves all of the virtual address space we could
- * ever need. Physical pages will be mapped as the memory
- * is touched.
- *
- * Align max_capacity to a whole page.
- */
- max_capacity = (size_t)ALIGN_UP(max_capacity, pagesize);
-
- if (name)
- snprintf(buf, sizeof(buf), "mspace/%s", name);
- fd = ashmem_create_region(buf, max_capacity);
- if (fd < 0)
- return (mspace)0;
-
- base = mmap(NULL, max_capacity, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
- close(fd);
- if (base == MAP_FAILED)
- return (mspace)0;
-
- /* Make sure that base is at the beginning of a page.
- */
- assert(((uintptr_t)base & (pagesize-1)) == 0);
-
- /* Reserve some space for the information that our MORECORE needs.
- */
- cs = base;
-
- /* Create the mspace, pointing to the memory we just reserved.
- */
- m = create_mspace_with_base(base + sizeof(*cs), starting_capacity, locked);
- if (m == (mspace)0)
- goto error;
-
- /* Make sure that m is in the same page as cs.
- */
- assert(((uintptr_t)m & (uintptr_t)~(pagesize-1)) == (uintptr_t)base);
-
- /* Find out exactly how much of the memory the mspace
- * is using.
- */
- cs->brk = m->seg.base + m->seg.size;
- cs->top = (char *)base + max_capacity;
- assert((char *)base <= cs->brk);
- assert(cs->brk <= cs->top);
-
- /* Prevent access to the memory we haven't handed out yet.
- */
- if (cs->brk != cs->top) {
- /* mprotect() requires page-aligned arguments, but it's possible
- * for cs->brk not to be page-aligned at this point.
- */
- char *prot_brk = (char *)ALIGN_UP(cs->brk, pagesize);
- if (mprotect(prot_brk, cs->top - prot_brk, PROT_NONE) < 0)
- goto error;
- }
-
- cs->m = m;
- cs->magic = CONTIG_STATE_MAGIC;
-
- return (mspace)m;
-
-error:
- munmap(base, max_capacity);
- return (mspace)0;
-}
-
-mspace create_contiguous_mspace(size_t starting_capacity,
- size_t max_capacity, int locked) {
- return create_contiguous_mspace_with_name(starting_capacity,
- max_capacity, locked, NULL);
-}
-
-size_t destroy_contiguous_mspace(mspace msp) {
- mstate ms = (mstate)msp;
-
- if (ok_magic(ms)) {
- struct mspace_contig_state *cs;
- size_t length;
- const unsigned int pagesize = PAGESIZE;
-
- cs = (struct mspace_contig_state *)((uintptr_t)ms & ~(pagesize-1));
- assert(cs->magic == CONTIG_STATE_MAGIC);
- assert(cs->m == ms);
-
- length = cs->top - (char *)cs;
- if (munmap((char *)cs, length) != 0)
- return length;
- }
- else {
- USAGE_ERROR_ACTION(ms, ms);
- }
- return 0;
-}
-#endif
diff --git a/libcutils/private.h b/libcutils/private.h
deleted file mode 100644
index 2837b70c1..000000000
--- a/libcutils/private.h
+++ /dev/null
@@ -1,368 +0,0 @@
-#ifndef PRIVATE_H
-
-#define PRIVATE_H
-
-/*
-** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson.
-*/
-
-/*
-** This header is for use ONLY with the time conversion code.
-** There is no guarantee that it will remain unchanged,
-** or that it will remain at all.
-** Do NOT copy it to any system include directory.
-** Thank you!
-*/
-
-/*
-** ID
-*/
-
-#ifndef lint
-#ifndef NOID
-static char privatehid[] = "@(#)private.h 8.2";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-#define GRANDPARENTED "Local time zone must be set--see zic manual page"
-
-/*
-** Defaults for preprocessor symbols.
-** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
-*/
-
-#ifndef HAVE_ADJTIME
-#define HAVE_ADJTIME 1
-#endif /* !defined HAVE_ADJTIME */
-
-#ifndef HAVE_GETTEXT
-#define HAVE_GETTEXT 0
-#endif /* !defined HAVE_GETTEXT */
-
-#ifndef HAVE_INCOMPATIBLE_CTIME_R
-#define HAVE_INCOMPATIBLE_CTIME_R 0
-#endif /* !defined INCOMPATIBLE_CTIME_R */
-
-#ifndef HAVE_SETTIMEOFDAY
-#define HAVE_SETTIMEOFDAY 3
-#endif /* !defined HAVE_SETTIMEOFDAY */
-
-#ifndef HAVE_STRERROR
-#define HAVE_STRERROR 1
-#endif /* !defined HAVE_STRERROR */
-
-#ifndef HAVE_SYMLINK
-#define HAVE_SYMLINK 1
-#endif /* !defined HAVE_SYMLINK */
-
-#ifndef HAVE_SYS_STAT_H
-#define HAVE_SYS_STAT_H 1
-#endif /* !defined HAVE_SYS_STAT_H */
-
-#ifndef HAVE_SYS_WAIT_H
-#define HAVE_SYS_WAIT_H 1
-#endif /* !defined HAVE_SYS_WAIT_H */
-
-#ifndef HAVE_UNISTD_H
-#define HAVE_UNISTD_H 1
-#endif /* !defined HAVE_UNISTD_H */
-
-#ifndef HAVE_UTMPX_H
-#define HAVE_UTMPX_H 0
-#endif /* !defined HAVE_UTMPX_H */
-
-#ifndef LOCALE_HOME
-#define LOCALE_HOME "/usr/lib/locale"
-#endif /* !defined LOCALE_HOME */
-
-#if HAVE_INCOMPATIBLE_CTIME_R
-#define asctime_r _incompatible_asctime_r
-#define ctime_r _incompatible_ctime_r
-#endif /* HAVE_INCOMPATIBLE_CTIME_R */
-
-/*
-** Nested includes
-*/
-
-#include "sys/types.h" /* for time_t */
-#include "stdio.h"
-#include "errno.h"
-#include "string.h"
-#include "limits.h" /* for CHAR_BIT et al. */
-#include "time.h"
-#include "stdlib.h"
-
-#if HAVE_GETTEXT
-#include "libintl.h"
-#endif /* HAVE_GETTEXT */
-
-#if HAVE_SYS_WAIT_H
-#include <sys/wait.h> /* for WIFEXITED and WEXITSTATUS */
-#endif /* HAVE_SYS_WAIT_H */
-
-#ifndef WIFEXITED
-#define WIFEXITED(status) (((status) & 0xff) == 0)
-#endif /* !defined WIFEXITED */
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(status) (((status) >> 8) & 0xff)
-#endif /* !defined WEXITSTATUS */
-
-#if HAVE_UNISTD_H
-#include "unistd.h" /* for F_OK and R_OK */
-#endif /* HAVE_UNISTD_H */
-
-#if !HAVE_UNISTD_H
-#ifndef F_OK
-#define F_OK 0
-#endif /* !defined F_OK */
-#ifndef R_OK
-#define R_OK 4
-#endif /* !defined R_OK */
-#endif /* !HAVE_UNISTD_H */
-
-/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
-#define is_digit(c) ((unsigned)(c) - '0' <= 9)
-
-/*
-** Define HAVE_STDINT_H's default value here, rather than at the
-** start, since __GLIBC__'s value depends on previously-included
-** files.
-** (glibc 2.1 and later have stdint.h, even with pre-C99 compilers.)
-*/
-#ifndef HAVE_STDINT_H
-#define HAVE_STDINT_H \
- (199901 <= __STDC_VERSION__ || \
- 2 < (__GLIBC__ + (0 < __GLIBC_MINOR__)))
-#endif /* !defined HAVE_STDINT_H */
-
-#if HAVE_STDINT_H
-#include "stdint.h"
-#endif /* !HAVE_STDINT_H */
-
-#ifndef INT_FAST64_MAX
-/* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */
-#if defined LLONG_MAX || defined __LONG_LONG_MAX__
-typedef long long int_fast64_t;
-#else /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
-#if (LONG_MAX >> 31) < 0xffffffff
-Please use a compiler that supports a 64-bit integer type (or wider);
-you may need to compile with "-DHAVE_STDINT_H".
-#endif /* (LONG_MAX >> 31) < 0xffffffff */
-typedef long int_fast64_t;
-#endif /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
-#endif /* !defined INT_FAST64_MAX */
-
-#ifndef INT32_MAX
-#define INT32_MAX 0x7fffffff
-#endif /* !defined INT32_MAX */
-#ifndef INT32_MIN
-#define INT32_MIN (-1 - INT32_MAX)
-#endif /* !defined INT32_MIN */
-
-/*
-** Workarounds for compilers/systems.
-*/
-
-/*
-** If your compiler lacks prototypes, "#define P(x) ()".
-*/
-
-#ifndef P
-#define P(x) x
-#endif /* !defined P */
-
-/*
-** SunOS 4.1.1 headers lack EXIT_SUCCESS.
-*/
-
-#ifndef EXIT_SUCCESS
-#define EXIT_SUCCESS 0
-#endif /* !defined EXIT_SUCCESS */
-
-/*
-** SunOS 4.1.1 headers lack EXIT_FAILURE.
-*/
-
-#ifndef EXIT_FAILURE
-#define EXIT_FAILURE 1
-#endif /* !defined EXIT_FAILURE */
-
-/*
-** SunOS 4.1.1 headers lack FILENAME_MAX.
-*/
-
-#ifndef FILENAME_MAX
-
-#ifndef MAXPATHLEN
-#ifdef unix
-#include "sys/param.h"
-#endif /* defined unix */
-#endif /* !defined MAXPATHLEN */
-
-#ifdef MAXPATHLEN
-#define FILENAME_MAX MAXPATHLEN
-#endif /* defined MAXPATHLEN */
-#ifndef MAXPATHLEN
-#define FILENAME_MAX 1024 /* Pure guesswork */
-#endif /* !defined MAXPATHLEN */
-
-#endif /* !defined FILENAME_MAX */
-
-/*
-** SunOS 4.1.1 libraries lack remove.
-*/
-
-#ifndef remove
-extern int unlink P((const char * filename));
-#define remove unlink
-#endif /* !defined remove */
-
-/*
-** Some ancient errno.h implementations don't declare errno.
-** But some newer errno.h implementations define it as a macro.
-** Fix the former without affecting the latter.
-*/
-
-#ifndef errno
-extern int errno;
-#endif /* !defined errno */
-
-/*
-** Some time.h implementations don't declare asctime_r.
-** Others might define it as a macro.
-** Fix the former without affecting the latter.
-*/
-
-#ifndef asctime_r
-extern char * asctime_r();
-#endif
-
-/*
-** Private function declarations.
-*/
-
-char * icalloc P((int nelem, int elsize));
-char * icatalloc P((char * old, const char * new));
-char * icpyalloc P((const char * string));
-char * imalloc P((int n));
-void * irealloc P((void * pointer, int size));
-void icfree P((char * pointer));
-void ifree P((char * pointer));
-const char * scheck P((const char * string, const char * format));
-
-/*
-** Finally, some convenience items.
-*/
-
-#ifndef TRUE
-#define TRUE 1
-#endif /* !defined TRUE */
-
-#ifndef FALSE
-#define FALSE 0
-#endif /* !defined FALSE */
-
-#ifndef TYPE_BIT
-#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
-#endif /* !defined TYPE_BIT */
-
-#ifndef TYPE_SIGNED
-#define TYPE_SIGNED(type) (((type) -1) < 0)
-#endif /* !defined TYPE_SIGNED */
-
-/*
-** Since the definition of TYPE_INTEGRAL contains floating point numbers,
-** it cannot be used in preprocessor directives.
-*/
-
-#ifndef TYPE_INTEGRAL
-#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5)
-#endif /* !defined TYPE_INTEGRAL */
-
-#ifndef INT_STRLEN_MAXIMUM
-/*
-** 302 / 1000 is log10(2.0) rounded up.
-** Subtract one for the sign bit if the type is signed;
-** add one for integer division truncation;
-** add one more for a minus sign if the type is signed.
-*/
-#define INT_STRLEN_MAXIMUM(type) \
- ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
- 1 + TYPE_SIGNED(type))
-#endif /* !defined INT_STRLEN_MAXIMUM */
-
-/*
-** INITIALIZE(x)
-*/
-
-#ifndef GNUC_or_lint
-#ifdef lint
-#define GNUC_or_lint
-#endif /* defined lint */
-#ifndef lint
-#ifdef __GNUC__
-#define GNUC_or_lint
-#endif /* defined __GNUC__ */
-#endif /* !defined lint */
-#endif /* !defined GNUC_or_lint */
-
-#ifndef INITIALIZE
-#ifdef GNUC_or_lint
-#define INITIALIZE(x) ((x) = 0)
-#endif /* defined GNUC_or_lint */
-#ifndef GNUC_or_lint
-#define INITIALIZE(x)
-#endif /* !defined GNUC_or_lint */
-#endif /* !defined INITIALIZE */
-
-/*
-** For the benefit of GNU folk...
-** `_(MSGID)' uses the current locale's message library string for MSGID.
-** The default is to use gettext if available, and use MSGID otherwise.
-*/
-
-#ifndef _
-#if HAVE_GETTEXT
-#define _(msgid) gettext(msgid)
-#else /* !HAVE_GETTEXT */
-#define _(msgid) msgid
-#endif /* !HAVE_GETTEXT */
-#endif /* !defined _ */
-
-#ifndef TZ_DOMAIN
-#define TZ_DOMAIN "tz"
-#endif /* !defined TZ_DOMAIN */
-
-#if HAVE_INCOMPATIBLE_CTIME_R
-#undef asctime_r
-#undef ctime_r
-char *asctime_r P((struct tm const *, char *));
-char *ctime_r P((time_t const *, char *));
-#endif /* HAVE_INCOMPATIBLE_CTIME_R */
-
-#ifndef YEARSPERREPEAT
-#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */
-#endif /* !defined YEARSPERREPEAT */
-
-/*
-** The Gregorian year averages 365.2425 days, which is 31556952 seconds.
-*/
-
-#ifndef AVGSECSPERYEAR
-#define AVGSECSPERYEAR 31556952L
-#endif /* !defined AVGSECSPERYEAR */
-
-#ifndef SECSPERREPEAT
-#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
-#endif /* !defined SECSPERREPEAT */
-
-#ifndef SECSPERREPEAT_BITS
-#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
-#endif /* !defined SECSPERREPEAT_BITS */
-
-/*
-** UNIX was a registered trademark of The Open Group in 2003.
-*/
-
-#endif /* !defined PRIVATE_H */
diff --git a/libcutils/process_name.c b/libcutils/process_name.c
deleted file mode 100644
index 17f52e269..000000000
--- a/libcutils/process_name.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2008 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 <string.h>
-#include <cutils/process_name.h>
-#include <cutils/properties.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#define PROCESS_NAME_DEVICE "/sys/qemu_trace/process_name"
-
-static const char* process_name = "unknown";
-static int running_in_emulator = -1;
-
-void set_process_name(const char* new_name) {
- char propBuf[PROPERTY_VALUE_MAX];
-
- if (new_name == NULL) {
- return;
- }
-
- // We never free the old name. Someone else could be using it.
- char* copy = (char*) malloc(strlen(new_name) + 1);
- strcpy(copy, new_name);
- process_name = (const char*) copy;
-
- // If we know we are not running in the emulator, then return.
- if (running_in_emulator == 0) {
- return;
- }
-
- // If the "running_in_emulator" variable has not been initialized,
- // then do it now.
- if (running_in_emulator == -1) {
- property_get("ro.kernel.qemu", propBuf, "");
- if (propBuf[0] == '1') {
- running_in_emulator = 1;
- } else {
- running_in_emulator = 0;
- return;
- }
- }
-
- // If the emulator was started with the "-trace file" command line option
- // then we want to record the process name in the trace even if we are
- // not currently tracing instructions (so that we will know the process
- // name when we do start tracing instructions). We do not need to execute
- // this code if we are just running in the emulator without the "-trace"
- // command line option, but we don't know that here and this function
- // isn't called frequently enough to bother optimizing that case.
- int fd = open(PROCESS_NAME_DEVICE, O_RDWR);
- if (fd < 0)
- return;
- write(fd, process_name, strlen(process_name) + 1);
- close(fd);
-}
-
-const char* get_process_name(void) {
- return process_name;
-}
diff --git a/libcutils/properties.c b/libcutils/properties.c
deleted file mode 100644
index 547cc6dc5..000000000
--- a/libcutils/properties.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright (C) 2006 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.
- */
-
-#define LOG_TAG "properties"
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <cutils/sockets.h>
-#include <errno.h>
-#include <assert.h>
-
-#include <cutils/properties.h>
-#include "loghack.h"
-
-#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
-
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#include <sys/_system_properties.h>
-
-static int send_prop_msg(prop_msg *msg)
-{
- int s;
- int r;
-
- s = socket_local_client(PROP_SERVICE_NAME,
- ANDROID_SOCKET_NAMESPACE_RESERVED,
- SOCK_STREAM);
- if(s < 0) return -1;
-
- while((r = send(s, msg, sizeof(prop_msg), 0)) < 0) {
- if((errno == EINTR) || (errno == EAGAIN)) continue;
- break;
- }
-
- if(r == sizeof(prop_msg)) {
- r = 0;
- } else {
- r = -1;
- }
-
- close(s);
- return r;
-}
-
-int property_set(const char *key, const char *value)
-{
- prop_msg msg;
- unsigned resp;
-
- if(key == 0) return -1;
- if(value == 0) value = "";
-
- if(strlen(key) >= PROP_NAME_MAX) return -1;
- if(strlen(value) >= PROP_VALUE_MAX) return -1;
-
- msg.cmd = PROP_MSG_SETPROP;
- strcpy((char*) msg.name, key);
- strcpy((char*) msg.value, value);
-
- return send_prop_msg(&msg);
-}
-
-int property_get(const char *key, char *value, const char *default_value)
-{
- int len;
-
- len = __system_property_get(key, value);
- if(len > 0) {
- return len;
- }
-
- if(default_value) {
- len = strlen(default_value);
- memcpy(value, default_value, len + 1);
- }
- return len;
-}
-
-int property_list(void (*propfn)(const char *key, const char *value, void *cookie),
- void *cookie)
-{
- char name[PROP_NAME_MAX];
- char value[PROP_VALUE_MAX];
- const prop_info *pi;
- unsigned n;
-
- for(n = 0; (pi = __system_property_find_nth(n)); n++) {
- __system_property_read(pi, name, value);
- propfn(name, value, cookie);
- }
- return 0;
-}
-
-#elif defined(HAVE_SYSTEM_PROPERTY_SERVER)
-
-/*
- * The Linux simulator provides a "system property server" that uses IPC
- * to set/get/list properties. The file descriptor is shared by all
- * threads in the process, so we use a mutex to ensure that requests
- * from multiple threads don't get interleaved.
- */
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <pthread.h>
-
-static pthread_once_t gInitOnce = PTHREAD_ONCE_INIT;
-static pthread_mutex_t gPropertyFdLock = PTHREAD_MUTEX_INITIALIZER;
-static int gPropFd = -1;
-
-/*
- * Connect to the properties server.
- *
- * Returns the socket descriptor on success.
- */
-static int connectToServer(const char* fileName)
-{
- int sock = -1;
- int cc;
-
- struct sockaddr_un addr;
-
- sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (sock < 0) {
- LOGW("UNIX domain socket create failed (errno=%d)\n", errno);
- return -1;
- }
-
- /* connect to socket; fails if file doesn't exist */
- strcpy(addr.sun_path, fileName); // max 108 bytes
- addr.sun_family = AF_UNIX;
- cc = connect(sock, (struct sockaddr*) &addr, SUN_LEN(&addr));
- if (cc < 0) {
- // ENOENT means socket file doesn't exist
- // ECONNREFUSED means socket exists but nobody is listening
- //LOGW("AF_UNIX connect failed for '%s': %s\n",
- // fileName, strerror(errno));
- close(sock);
- return -1;
- }
-
- return sock;
-}
-
-/*
- * Perform one-time initialization.
- */
-static void init(void)
-{
- assert(gPropFd == -1);
-
- gPropFd = connectToServer(SYSTEM_PROPERTY_PIPE_NAME);
- if (gPropFd < 0) {
- //LOGW("not connected to system property server\n");
- } else {
- //LOGV("Connected to system property server\n");
- }
-}
-
-int property_get(const char *key, char *value, const char *default_value)
-{
- char sendBuf[1+PROPERTY_KEY_MAX];
- char recvBuf[1+PROPERTY_VALUE_MAX];
- int len = -1;
-
- //LOGV("PROPERTY GET [%s]\n", key);
-
- pthread_once(&gInitOnce, init);
- if (gPropFd < 0) {
- /* this mimics the behavior of the device implementation */
- if (default_value != NULL) {
- strcpy(value, default_value);
- len = strlen(value);
- }
- return len;
- }
-
- if (strlen(key) >= PROPERTY_KEY_MAX) return -1;
-
- memset(sendBuf, 0xdd, sizeof(sendBuf)); // placate valgrind
-
- sendBuf[0] = (char) kSystemPropertyGet;
- strcpy(sendBuf+1, key);
-
- pthread_mutex_lock(&gPropertyFdLock);
- if (write(gPropFd, sendBuf, sizeof(sendBuf)) != sizeof(sendBuf)) {
- pthread_mutex_unlock(&gPropertyFdLock);
- return -1;
- }
- if (read(gPropFd, recvBuf, sizeof(recvBuf)) != sizeof(recvBuf)) {
- pthread_mutex_unlock(&gPropertyFdLock);
- return -1;
- }
- pthread_mutex_unlock(&gPropertyFdLock);
-
- /* first byte is 0 if value not defined, 1 if found */
- if (recvBuf[0] == 0) {
- if (default_value != NULL) {
- strcpy(value, default_value);
- len = strlen(value);
- } else {
- /*
- * If the value isn't defined, hand back an empty string and
- * a zero length, rather than a failure. This seems wrong,
- * since you can't tell the difference between "undefined" and
- * "defined but empty", but it's what the device does.
- */
- value[0] = '\0';
- len = 0;
- }
- } else if (recvBuf[0] == 1) {
- strcpy(value, recvBuf+1);
- len = strlen(value);
- } else {
- LOGE("Got strange response to property_get request (%d)\n",
- recvBuf[0]);
- assert(0);
- return -1;
- }
- //LOGV("PROP [found=%d def='%s'] (%d) [%s]: [%s]\n",
- // recvBuf[0], default_value, len, key, value);
-
- return len;
-}
-
-
-int property_set(const char *key, const char *value)
-{
- char sendBuf[1+PROPERTY_KEY_MAX+PROPERTY_VALUE_MAX];
- char recvBuf[1];
- int result = -1;
-
- //LOGV("PROPERTY SET [%s]: [%s]\n", key, value);
-
- pthread_once(&gInitOnce, init);
- if (gPropFd < 0)
- return -1;
-
- if (strlen(key) >= PROPERTY_KEY_MAX) return -1;
- if (strlen(value) >= PROPERTY_VALUE_MAX) return -1;
-
- memset(sendBuf, 0xdd, sizeof(sendBuf)); // placate valgrind
-
- sendBuf[0] = (char) kSystemPropertySet;
- strcpy(sendBuf+1, key);
- strcpy(sendBuf+1+PROPERTY_KEY_MAX, value);
-
- pthread_mutex_lock(&gPropertyFdLock);
- if (write(gPropFd, sendBuf, sizeof(sendBuf)) != sizeof(sendBuf)) {
- pthread_mutex_unlock(&gPropertyFdLock);
- return -1;
- }
- if (read(gPropFd, recvBuf, sizeof(recvBuf)) != sizeof(recvBuf)) {
- pthread_mutex_unlock(&gPropertyFdLock);
- return -1;
- }
- pthread_mutex_unlock(&gPropertyFdLock);
-
- if (recvBuf[0] != 1)
- return -1;
- return 0;
-}
-
-int property_list(void (*propfn)(const char *key, const char *value, void *cookie),
- void *cookie)
-{
- //LOGV("PROPERTY LIST\n");
- pthread_once(&gInitOnce, init);
- if (gPropFd < 0)
- return -1;
-
- return 0;
-}
-
-#else
-
-/* SUPER-cheesy place-holder implementation for Win32 */
-
-#include <cutils/threads.h>
-
-static mutex_t env_lock = MUTEX_INITIALIZER;
-
-int property_get(const char *key, char *value, const char *default_value)
-{
- char ename[PROPERTY_KEY_MAX + 6];
- char *p;
- int len;
-
- len = strlen(key);
- if(len >= PROPERTY_KEY_MAX) return -1;
- memcpy(ename, "PROP_", 5);
- memcpy(ename + 5, key, len + 1);
-
- mutex_lock(&env_lock);
-
- p = getenv(ename);
- if(p == 0) p = "";
- len = strlen(p);
- if(len >= PROPERTY_VALUE_MAX) {
- len = PROPERTY_VALUE_MAX - 1;
- }
-
- if((len == 0) && default_value) {
- len = strlen(default_value);
- memcpy(value, default_value, len + 1);
- } else {
- memcpy(value, p, len);
- value[len] = 0;
- }
-
- mutex_unlock(&env_lock);
-
- return len;
-}
-
-
-int property_set(const char *key, const char *value)
-{
- char ename[PROPERTY_KEY_MAX + 6];
- char *p;
- int len;
- int r;
-
- if(strlen(value) >= PROPERTY_VALUE_MAX) return -1;
-
- len = strlen(key);
- if(len >= PROPERTY_KEY_MAX) return -1;
- memcpy(ename, "PROP_", 5);
- memcpy(ename + 5, key, len + 1);
-
- mutex_lock(&env_lock);
-#ifdef HAVE_MS_C_RUNTIME
- {
- char temp[256];
- snprintf( temp, sizeof(temp), "%s=%s", ename, value);
- putenv(temp);
- r = 0;
- }
-#else
- r = setenv(ename, value, 1);
-#endif
- mutex_unlock(&env_lock);
-
- return r;
-}
-
-int property_list(void (*propfn)(const char *key, const char *value, void *cookie),
- void *cookie)
-{
- return 0;
-}
-
-#endif
diff --git a/libcutils/record_stream.c b/libcutils/record_stream.c
deleted file mode 100644
index 274423b74..000000000
--- a/libcutils/record_stream.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/* libs/cutils/record_stream.c
-**
-** Copyright 2006, 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 <stdlib.h>
-#include <unistd.h>
-#include <assert.h>
-#include <errno.h>
-#include <cutils/record_stream.h>
-#include <string.h>
-#include <stdint.h>
-#ifdef HAVE_WINSOCK
-#include <winsock2.h> /* for ntohl */
-#else
-#include <netinet/in.h>
-#endif
-
-#define HEADER_SIZE 4
-
-struct RecordStream {
- int fd;
- size_t maxRecordLen;
-
- unsigned char *buffer;
-
- unsigned char *unconsumed;
- unsigned char *read_end;
- unsigned char *buffer_end;
-};
-
-
-extern RecordStream *record_stream_new(int fd, size_t maxRecordLen)
-{
- RecordStream *ret;
-
- assert (maxRecordLen <= 0xffff);
-
- ret = (RecordStream *)calloc(1, sizeof(RecordStream));
-
- ret->fd = fd;
- ret->maxRecordLen = maxRecordLen;
- ret->buffer = (unsigned char *)malloc (maxRecordLen + HEADER_SIZE);
-
- ret->unconsumed = ret->buffer;
- ret->read_end = ret->buffer;
- ret->buffer_end = ret->buffer + maxRecordLen + HEADER_SIZE;
-
- return ret;
-}
-
-
-extern void record_stream_free(RecordStream *rs)
-{
- free(rs->buffer);
- free(rs);
-}
-
-
-/* returns NULL; if there isn't a full record in the buffer */
-static unsigned char * getEndOfRecord (unsigned char *p_begin,
- unsigned char *p_end)
-{
- size_t len;
- unsigned char * p_ret;
-
- if (p_end < p_begin + HEADER_SIZE) {
- return NULL;
- }
-
- //First four bytes are length
- len = ntohl(*((uint32_t *)p_begin));
-
- p_ret = p_begin + HEADER_SIZE + len;
-
- if (p_end < p_ret) {
- return NULL;
- }
-
- return p_ret;
-}
-
-static void *getNextRecord (RecordStream *p_rs, size_t *p_outRecordLen)
-{
- unsigned char *record_start, *record_end;
-
- record_end = getEndOfRecord (p_rs->unconsumed, p_rs->read_end);
-
- if (record_end != NULL) {
- /* one full line in the buffer */
- record_start = p_rs->unconsumed + HEADER_SIZE;
- p_rs->unconsumed = record_end;
-
- *p_outRecordLen = record_end - record_start;
-
- return record_start;
- }
-
- return NULL;
-}
-
-/**
- * Reads the next record from stream fd
- * Records are prefixed by a 16-bit big endian length value
- * Records may not be larger than maxRecordLen
- *
- * Doesn't guard against EINTR
- *
- * p_outRecord and p_outRecordLen may not be NULL
- *
- * Return 0 on success, -1 on fail
- * Returns 0 with *p_outRecord set to NULL on end of stream
- * Returns -1 / errno = EAGAIN if it needs to read again
- */
-int record_stream_get_next (RecordStream *p_rs, void ** p_outRecord,
- size_t *p_outRecordLen)
-{
- void *ret;
-
- ssize_t countRead;
-
- /* is there one record already in the buffer? */
- ret = getNextRecord (p_rs, p_outRecordLen);
-
- if (ret != NULL) {
- *p_outRecord = ret;
- return 0;
- }
-
- // if the buffer is full and we don't have a full record
- if (p_rs->unconsumed == p_rs->buffer
- && p_rs->read_end == p_rs->buffer_end
- ) {
- // this should never happen
- //LOGE("max record length exceeded\n");
- assert (0);
- errno = EFBIG;
- return -1;
- }
-
- if (p_rs->unconsumed != p_rs->buffer) {
- // move remainder to the beginning of the buffer
- size_t toMove;
-
- toMove = p_rs->read_end - p_rs->unconsumed;
- if (toMove) {
- memmove(p_rs->buffer, p_rs->unconsumed, toMove);
- }
-
- p_rs->read_end = p_rs->buffer + toMove;
- p_rs->unconsumed = p_rs->buffer;
- }
-
- countRead = read (p_rs->fd, p_rs->read_end, p_rs->buffer_end - p_rs->read_end);
-
- if (countRead <= 0) {
- /* note: end-of-stream drops through here too */
- *p_outRecord = NULL;
- return countRead;
- }
-
- p_rs->read_end += countRead;
-
- ret = getNextRecord (p_rs, p_outRecordLen);
-
- if (ret == NULL) {
- /* not enough of a buffer to for a whole command */
- errno = EAGAIN;
- return -1;
- }
-
- *p_outRecord = ret;
- return 0;
-}
diff --git a/libcutils/selector.c b/libcutils/selector.c
deleted file mode 100644
index 943639370..000000000
--- a/libcutils/selector.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-#define LOG_TAG "selector"
-
-#include <assert.h>
-#include <errno.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <cutils/array.h>
-#include <cutils/selector.h>
-
-#include "loghack.h"
-
-struct Selector {
- Array* selectableFds;
- bool looping;
- fd_set readFds;
- fd_set writeFds;
- fd_set exceptFds;
- int maxFd;
- int wakeupPipe[2];
- SelectableFd* wakeupFd;
-
- bool inSelect;
- pthread_mutex_t inSelectLock;
-};
-
-/** Reads and ignores wake up data. */
-static void eatWakeupData(SelectableFd* wakeupFd) {
- static char garbage[64];
- if (read(wakeupFd->fd, garbage, sizeof(garbage)) < 0) {
- if (errno == EINTR) {
- LOGI("read() interrupted.");
- } else {
- LOG_ALWAYS_FATAL("This should never happen: %s", strerror(errno));
- }
- }
-}
-
-static void setInSelect(Selector* selector, bool inSelect) {
- pthread_mutex_lock(&selector->inSelectLock);
- selector->inSelect = inSelect;
- pthread_mutex_unlock(&selector->inSelectLock);
-}
-
-static bool isInSelect(Selector* selector) {
- pthread_mutex_lock(&selector->inSelectLock);
- bool inSelect = selector->inSelect;
- pthread_mutex_unlock(&selector->inSelectLock);
- return inSelect;
-}
-
-void selectorWakeUp(Selector* selector) {
- if (!isInSelect(selector)) {
- // We only need to write wake-up data if we're blocked in select().
- return;
- }
-
- static char garbage[1];
- if (write(selector->wakeupPipe[1], garbage, sizeof(garbage)) < 0) {
- if (errno == EINTR) {
- LOGI("read() interrupted.");
- } else {
- LOG_ALWAYS_FATAL("This should never happen: %s", strerror(errno));
- }
- }
-}
-
-Selector* selectorCreate(void) {
- Selector* selector = calloc(1, sizeof(Selector));
- if (selector == NULL) {
- LOG_ALWAYS_FATAL("malloc() error.");
- }
- selector->selectableFds = arrayCreate();
-
- // Set up wake-up pipe.
- if (pipe(selector->wakeupPipe) < 0) {
- LOG_ALWAYS_FATAL("pipe() error: %s", strerror(errno));
- }
-
- LOGD("Wakeup fd: %d", selector->wakeupPipe[0]);
-
- SelectableFd* wakeupFd = selectorAdd(selector, selector->wakeupPipe[0]);
- if (wakeupFd == NULL) {
- LOG_ALWAYS_FATAL("malloc() error.");
- }
- wakeupFd->onReadable = &eatWakeupData;
-
- pthread_mutex_init(&selector->inSelectLock, NULL);
-
- return selector;
-}
-
-SelectableFd* selectorAdd(Selector* selector, int fd) {
- assert(selector != NULL);
-
- SelectableFd* selectableFd = calloc(1, sizeof(SelectableFd));
- if (selectableFd != NULL) {
- selectableFd->selector = selector;
- selectableFd->fd = fd;
-
- arrayAdd(selector->selectableFds, selectableFd);
- }
-
- return selectableFd;
-}
-
-/**
- * Adds an fd to the given set if the callback is non-null. Returns true
- * if the fd was added.
- */
-static inline bool maybeAdd(SelectableFd* selectableFd,
- void (*callback)(SelectableFd*), fd_set* fdSet) {
- if (callback != NULL) {
- FD_SET(selectableFd->fd, fdSet);
- return true;
- }
- return false;
-}
-
-/**
- * Removes stale file descriptors and initializes file descriptor sets.
- */
-static void prepareForSelect(Selector* selector) {
- fd_set* exceptFds = &selector->exceptFds;
- fd_set* readFds = &selector->readFds;
- fd_set* writeFds = &selector->writeFds;
-
- FD_ZERO(exceptFds);
- FD_ZERO(readFds);
- FD_ZERO(writeFds);
-
- Array* selectableFds = selector->selectableFds;
- int i = 0;
- selector->maxFd = 0;
- int size = arraySize(selectableFds);
- while (i < size) {
- SelectableFd* selectableFd = arrayGet(selectableFds, i);
- if (selectableFd->remove) {
- // This descriptor should be removed.
- arrayRemove(selectableFds, i);
- size--;
- if (selectableFd->onRemove != NULL) {
- selectableFd->onRemove(selectableFd);
- }
- free(selectableFd);
- } else {
- if (selectableFd->beforeSelect != NULL) {
- selectableFd->beforeSelect(selectableFd);
- }
-
- bool inSet = false;
- if (maybeAdd(selectableFd, selectableFd->onExcept, exceptFds)) {
- LOGD("Selecting fd %d for writing...", selectableFd->fd);
- inSet = true;
- }
- if (maybeAdd(selectableFd, selectableFd->onReadable, readFds)) {
- LOGD("Selecting fd %d for reading...", selectableFd->fd);
- inSet = true;
- }
- if (maybeAdd(selectableFd, selectableFd->onWritable, writeFds)) {
- inSet = true;
- }
-
- if (inSet) {
- // If the fd is in a set, check it against max.
- int fd = selectableFd->fd;
- if (fd > selector->maxFd) {
- selector->maxFd = fd;
- }
- }
-
- // Move to next descriptor.
- i++;
- }
- }
-}
-
-/**
- * Invokes a callback if the callback is non-null and the fd is in the given
- * set.
- */
-static inline void maybeInvoke(SelectableFd* selectableFd,
- void (*callback)(SelectableFd*), fd_set* fdSet) {
- if (callback != NULL && !selectableFd->remove &&
- FD_ISSET(selectableFd->fd, fdSet)) {
- LOGD("Selected fd %d.", selectableFd->fd);
- callback(selectableFd);
- }
-}
-
-/**
- * Notifies user if file descriptors are readable or writable, or if
- * out-of-band data is present.
- */
-static void fireEvents(Selector* selector) {
- Array* selectableFds = selector->selectableFds;
- int size = arraySize(selectableFds);
- int i;
- for (i = 0; i < size; i++) {
- SelectableFd* selectableFd = arrayGet(selectableFds, i);
- maybeInvoke(selectableFd, selectableFd->onExcept,
- &selector->exceptFds);
- maybeInvoke(selectableFd, selectableFd->onReadable,
- &selector->readFds);
- maybeInvoke(selectableFd, selectableFd->onWritable,
- &selector->writeFds);
- }
-}
-
-void selectorLoop(Selector* selector) {
- // Make sure we're not already looping.
- if (selector->looping) {
- LOG_ALWAYS_FATAL("Already looping.");
- }
- selector->looping = true;
-
- while (true) {
- setInSelect(selector, true);
-
- prepareForSelect(selector);
-
- LOGD("Entering select().");
-
- // Select file descriptors.
- int result = select(selector->maxFd + 1, &selector->readFds,
- &selector->writeFds, &selector->exceptFds, NULL);
-
- LOGD("Exiting select().");
-
- setInSelect(selector, false);
-
- if (result == -1) {
- // Abort on everything except EINTR.
- if (errno == EINTR) {
- LOGI("select() interrupted.");
- } else {
- LOG_ALWAYS_FATAL("select() error: %s",
- strerror(errno));
- }
- } else if (result > 0) {
- fireEvents(selector);
- }
- }
-}
diff --git a/libcutils/socket_inaddr_any_server.c b/libcutils/socket_inaddr_any_server.c
deleted file mode 100644
index 7d5dab4c8..000000000
--- a/libcutils/socket_inaddr_any_server.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* libs/cutils/socket_inaddr_any_server.c
-**
-** Copyright 2006, 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 <cutils/sockets.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stddef.h>
-
-#ifndef HAVE_WINSOCK
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#endif
-
-#define LISTEN_BACKLOG 4
-
-/* open listen() port on any interface */
-int socket_inaddr_any_server(int port, int type)
-{
- struct sockaddr_in addr;
- size_t alen;
- int s, n;
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
-
- s = socket(AF_INET, type, 0);
- if(s < 0) return -1;
-
- n = 1;
- setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n));
-
- if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- close(s);
- return -1;
- }
-
- if (type == SOCK_STREAM) {
- int ret;
-
- ret = listen(s, LISTEN_BACKLOG);
-
- if (ret < 0) {
- close(s);
- return -1;
- }
- }
-
- return s;
-}
diff --git a/libcutils/socket_local.h b/libcutils/socket_local.h
deleted file mode 100644
index 45b9856b6..000000000
--- a/libcutils/socket_local.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2006 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 __SOCKET_LOCAL_H
-#define __SOCKET_LOCAL_H
-
-#define FILESYSTEM_SOCKET_PREFIX "/tmp/"
-#define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/"
-
-/*
- * Set up a given sockaddr_un, to have it refer to the given
- * name in the given namespace. The namespace must be one
- * of <code>ANDROID_SOCKET_NAMESPACE_ABSTRACT</code>,
- * <code>ANDROID_SOCKET_NAMESPACE_RESERVED</code>, or
- * <code>ANDROID_SOCKET_NAMESPACE_FILESYSTEM</code>. Upon success,
- * the pointed at sockaddr_un is filled in and the pointed at
- * socklen_t is set to indicate the final length. This function
- * will fail if the namespace is invalid (not one of the indicated
- * constants) or if the name is too long.
- *
- * @return 0 on success or -1 on failure
- */
-int socket_make_sockaddr_un(const char *name, int namespaceId,
- struct sockaddr_un *p_addr, socklen_t *alen);
-
-#endif
diff --git a/libcutils/socket_local_client.c b/libcutils/socket_local_client.c
deleted file mode 100644
index 036ce2ef1..000000000
--- a/libcutils/socket_local_client.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2006 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 <cutils/sockets.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stddef.h>
-
-#ifdef HAVE_WINSOCK
-
-int socket_local_client(const char *name, int namespaceId, int type)
-{
- errno = ENOSYS;
- return -1;
-}
-
-#else /* !HAVE_WINSOCK */
-
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/select.h>
-#include <sys/types.h>
-
-#include "socket_local.h"
-
-#define LISTEN_BACKLOG 4
-
-/* Documented in header file. */
-int socket_make_sockaddr_un(const char *name, int namespaceId,
- struct sockaddr_un *p_addr, socklen_t *alen)
-{
- memset (p_addr, 0, sizeof (*p_addr));
- size_t namelen;
-
- switch (namespaceId) {
- case ANDROID_SOCKET_NAMESPACE_ABSTRACT:
-#ifdef HAVE_LINUX_LOCAL_SOCKET_NAMESPACE
- namelen = strlen(name);
-
- // Test with length +1 for the *initial* '\0'.
- if ((namelen + 1) > sizeof(p_addr->sun_path)) {
- goto error;
- }
-
- /*
- * Note: The path in this case is *not* supposed to be
- * '\0'-terminated. ("man 7 unix" for the gory details.)
- */
-
- p_addr->sun_path[0] = 0;
- memcpy(p_addr->sun_path + 1, name, namelen);
-#else /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/
- /* this OS doesn't have the Linux abstract namespace */
-
- namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
- /* unix_path_max appears to be missing on linux */
- if (namelen > sizeof(*p_addr)
- - offsetof(struct sockaddr_un, sun_path) - 1) {
- goto error;
- }
-
- strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX);
- strcat(p_addr->sun_path, name);
-#endif /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/
- break;
-
- case ANDROID_SOCKET_NAMESPACE_RESERVED:
- namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
- /* unix_path_max appears to be missing on linux */
- if (namelen > sizeof(*p_addr)
- - offsetof(struct sockaddr_un, sun_path) - 1) {
- goto error;
- }
-
- strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX);
- strcat(p_addr->sun_path, name);
- break;
-
- case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
- namelen = strlen(name);
- /* unix_path_max appears to be missing on linux */
- if (namelen > sizeof(*p_addr)
- - offsetof(struct sockaddr_un, sun_path) - 1) {
- goto error;
- }
-
- strcpy(p_addr->sun_path, name);
- break;
- default:
- // invalid namespace id
- return -1;
- }
-
- p_addr->sun_family = AF_LOCAL;
- *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
- return 0;
-error:
- return -1;
-}
-
-/**
- * connect to peer named "name" on fd
- * returns same fd or -1 on error.
- * fd is not closed on error. that's your job.
- *
- * Used by AndroidSocketImpl
- */
-int socket_local_client_connect(int fd, const char *name, int namespaceId,
- int type)
-{
- struct sockaddr_un addr;
- socklen_t alen;
- size_t namelen;
- int err;
-
- err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
-
- if (err < 0) {
- goto error;
- }
-
- if(connect(fd, (struct sockaddr *) &addr, alen) < 0) {
- goto error;
- }
-
- return fd;
-
-error:
- return -1;
-}
-
-/**
- * connect to peer named "name"
- * returns fd or -1 on error
- */
-int socket_local_client(const char *name, int namespaceId, int type)
-{
- int s;
-
- s = socket(AF_LOCAL, type, 0);
- if(s < 0) return -1;
-
- if ( 0 > socket_local_client_connect(s, name, namespaceId, type)) {
- close(s);
- return -1;
- }
-
- return s;
-}
-
-#endif /* !HAVE_WINSOCK */
diff --git a/libcutils/socket_local_server.c b/libcutils/socket_local_server.c
deleted file mode 100644
index 4971b1b1c..000000000
--- a/libcutils/socket_local_server.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/* libs/cutils/socket_local_server.c
-**
-** Copyright 2006, 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 <cutils/sockets.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stddef.h>
-
-#ifdef HAVE_WINSOCK
-
-int socket_local_server(const char *name, int namespaceId, int type)
-{
- errno = ENOSYS;
- return -1;
-}
-
-#else /* !HAVE_WINSOCK */
-
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/select.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-
-#include "socket_local.h"
-
-#define LISTEN_BACKLOG 4
-
-
-/**
- * Binds a pre-created socket(AF_LOCAL) 's' to 'name'
- * returns 's' on success, -1 on fail
- *
- * Does not call listen()
- */
-int socket_local_server_bind(int s, const char *name, int namespaceId)
-{
- struct sockaddr_un addr;
- socklen_t alen;
- int n;
- int err;
-
- err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
-
- if (err < 0) {
- return -1;
- }
-
- /* basically: if this is a filesystem path, unlink first */
-#ifndef HAVE_LINUX_LOCAL_SOCKET_NAMESPACE
- if (1) {
-#else
- if (namespaceId == ANDROID_SOCKET_NAMESPACE_RESERVED
- || namespaceId == ANDROID_SOCKET_NAMESPACE_FILESYSTEM) {
-#endif
- /*ignore ENOENT*/
- unlink(addr.sun_path);
- }
-
- n = 1;
- setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n));
-
- if(bind(s, (struct sockaddr *) &addr, alen) < 0) {
- return -1;
- }
-
- return s;
-
-}
-
-
-/** Open a server-side UNIX domain datagram socket in the Linux non-filesystem
- * namespace
- *
- * Returns fd on success, -1 on fail
- */
-
-int socket_local_server(const char *name, int namespace, int type)
-{
- int err;
- int s;
-
- s = socket(AF_LOCAL, type, 0);
- if (s < 0) return -1;
-
- err = socket_local_server_bind(s, name, namespace);
-
- if (err < 0) {
- close(s);
- return -1;
- }
-
- if (type == SOCK_STREAM) {
- int ret;
-
- ret = listen(s, LISTEN_BACKLOG);
-
- if (ret < 0) {
- close(s);
- return -1;
- }
- }
-
- return s;
-}
-
-#endif /* !HAVE_WINSOCK */
diff --git a/libcutils/socket_loopback_client.c b/libcutils/socket_loopback_client.c
deleted file mode 100644
index cb82c5ede..000000000
--- a/libcutils/socket_loopback_client.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* libs/cutils/socket_loopback_client.c
-**
-** Copyright 2006, 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 <cutils/sockets.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stddef.h>
-
-#ifndef HAVE_WINSOCK
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#endif
-
-/* Connect to port on the loopback IP interface. type is
- * SOCK_STREAM or SOCK_DGRAM.
- * return is a file descriptor or -1 on error
- */
-int socket_loopback_client(int port, int type)
-{
- struct sockaddr_in addr;
- socklen_t alen;
- int s;
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
- s = socket(AF_INET, type, 0);
- if(s < 0) return -1;
-
- if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- close(s);
- return -1;
- }
-
- return s;
-
-}
-
diff --git a/libcutils/socket_loopback_server.c b/libcutils/socket_loopback_server.c
deleted file mode 100644
index 3208488ad..000000000
--- a/libcutils/socket_loopback_server.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/* libs/cutils/socket_loopback_server.c
-**
-** Copyright 2006, 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 <cutils/sockets.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stddef.h>
-
-#define LISTEN_BACKLOG 4
-
-#ifndef HAVE_WINSOCK
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#endif
-
-/* open listen() port on loopback interface */
-int socket_loopback_server(int port, int type)
-{
- struct sockaddr_in addr;
- size_t alen;
- int s, n;
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
- s = socket(AF_INET, type, 0);
- if(s < 0) return -1;
-
- n = 1;
- setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n));
-
- if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- close(s);
- return -1;
- }
-
- if (type == SOCK_STREAM) {
- int ret;
-
- ret = listen(s, LISTEN_BACKLOG);
-
- if (ret < 0) {
- close(s);
- return -1;
- }
- }
-
- return s;
-}
-
diff --git a/libcutils/socket_network_client.c b/libcutils/socket_network_client.c
deleted file mode 100644
index a64006cdf..000000000
--- a/libcutils/socket_network_client.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/* libs/cutils/socket_network_client.c
-**
-** Copyright 2006, 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 <cutils/sockets.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stddef.h>
-
-#ifndef HAVE_WINSOCK
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#endif
-
-
-/* Connect to port on the IP interface. type is
- * SOCK_STREAM or SOCK_DGRAM.
- * return is a file descriptor or -1 on error
- */
-int socket_network_client(const char *host, int port, int type)
-{
- struct hostent *hp;
- struct sockaddr_in addr;
- socklen_t alen;
- int s;
-
- hp = gethostbyname(host);
- if(hp == 0) return -1;
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = hp->h_addrtype;
- addr.sin_port = htons(port);
- memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
-
- s = socket(hp->h_addrtype, type, 0);
- if(s < 0) return -1;
-
- if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- close(s);
- return -1;
- }
-
- return s;
-
-}
-
diff --git a/libcutils/strdup16to8.c b/libcutils/strdup16to8.c
deleted file mode 100644
index fadaabed8..000000000
--- a/libcutils/strdup16to8.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/* libs/cutils/strdup16to8.c
-**
-** Copyright 2006, 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 <cutils/jstring.h>
-#include <assert.h>
-#include <stdlib.h>
-
-
-/**
- * Given a UTF-16 string, compute the length of the corresponding UTF-8
- * string in bytes.
- */
-extern size_t strnlen16to8(const char16_t* utf16Str, size_t len)
-{
- size_t utf8Len = 0;
-
- while (len--) {
- unsigned int uic = *utf16Str++;
-
- if (uic > 0x07ff)
- utf8Len += 3;
- else if (uic > 0x7f || uic == 0)
- utf8Len += 2;
- else
- utf8Len++;
- }
- return utf8Len;
-}
-
-
-/**
- * Convert a Java-Style UTF-16 string + length to a JNI-Style UTF-8 string.
- *
- * This basically means: embedded \0's in the UTF-16 string are encoded
- * as "0xc0 0x80"
- *
- * Make sure you allocate "utf8Str" with the result of strlen16to8() + 1,
- * not just "len".
- *
- * Please note, a terminated \0 is always added, so your result will always
- * be "strlen16to8() + 1" bytes long.
- */
-extern char* strncpy16to8(char* utf8Str, const char16_t* utf16Str, size_t len)
-{
- char* utf8cur = utf8Str;
-
- while (len--) {
- unsigned int uic = *utf16Str++;
-
- if (uic > 0x07ff) {
- *utf8cur++ = (uic >> 12) | 0xe0;
- *utf8cur++ = ((uic >> 6) & 0x3f) | 0x80;
- *utf8cur++ = (uic & 0x3f) | 0x80;
- } else if (uic > 0x7f || uic == 0) {
- *utf8cur++ = (uic >> 6) | 0xc0;
- *utf8cur++ = (uic & 0x3f) | 0x80;
- } else {
- *utf8cur++ = uic;
-
- if (uic == 0) {
- break;
- }
- }
- }
-
- *utf8cur = '\0';
-
- return utf8Str;
-}
-
-/**
- * Convert a UTF-16 string to UTF-8.
- *
- * Make sure you allocate "dest" with the result of strblen16to8(),
- * not just "strlen16()".
- */
-char * strndup16to8 (const char16_t* s, size_t n)
-{
- char *ret;
-
- if (s == NULL) {
- return NULL;
- }
-
- ret = malloc(strnlen16to8(s, n) + 1);
-
- strncpy16to8 (ret, s, n);
-
- return ret;
-}
diff --git a/libcutils/strdup8to16.c b/libcutils/strdup8to16.c
deleted file mode 100644
index 8654b0455..000000000
--- a/libcutils/strdup8to16.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/* libs/cutils/strdup8to16.c
-**
-** Copyright 2006, 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 <cutils/jstring.h>
-#include <assert.h>
-#include <stdlib.h>
-
-/* See http://www.unicode.org/reports/tr22/ for discussion
- * on invalid sequences
- */
-
-#define UTF16_REPLACEMENT_CHAR 0xfffd
-
-/* Clever trick from Dianne that returns 1-4 depending on leading bit sequence*/
-#define UTF8_SEQ_LENGTH(ch) (((0xe5000000 >> ((ch >> 3) & 0x1e)) & 3) + 1)
-
-/* note: macro expands to multiple lines */
-#define UTF8_SHIFT_AND_MASK(unicode, byte) \
- (unicode)<<=6; (unicode) |= (0x3f & (byte));
-
-#define UNICODE_UPPER_LIMIT 0x10fffd
-
-/**
- * out_len is an out parameter (which may not be null) containing the
- * length of the UTF-16 string (which may contain embedded \0's)
- */
-
-extern char16_t * strdup8to16 (const char* s, size_t *out_len)
-{
- char16_t *ret;
- size_t len;
-
- if (s == NULL) return NULL;
-
- len = strlen8to16(s);
-
- // no plus-one here. UTF-16 strings are not null terminated
- ret = (char16_t *) malloc (sizeof(char16_t) * len);
-
- return strcpy8to16 (ret, s, out_len);
-}
-
-/**
- * Like "strlen", but for strings encoded with Java's modified UTF-8.
- *
- * The value returned is the number of UTF-16 characters required
- * to represent this string.
- */
-extern size_t strlen8to16 (const char* utf8Str)
-{
- size_t len = 0;
- int ic;
- int expected = 0;
-
- while ((ic = *utf8Str++) != '\0') {
- /* bytes that start 0? or 11 are lead bytes and count as characters.*/
- /* bytes that start 10 are extention bytes and are not counted */
-
- if ((ic & 0xc0) == 0x80) {
- /* count the 0x80 extention bytes. if we have more than
- * expected, then start counting them because strcpy8to16
- * will insert UTF16_REPLACEMENT_CHAR's
- */
- expected--;
- if (expected < 0) {
- len++;
- }
- } else {
- len++;
- expected = UTF8_SEQ_LENGTH(ic) - 1;
-
- /* this will result in a surrogate pair */
- if (expected == 3) {
- len++;
- }
- }
- }
-
- return len;
-}
-
-
-
-/*
- * Retrieve the next UTF-32 character from a UTF-8 string.
- *
- * Stops at inner \0's
- *
- * Returns UTF16_REPLACEMENT_CHAR if an invalid sequence is encountered
- *
- * Advances "*pUtf8Ptr" to the start of the next character.
- */
-static inline uint32_t getUtf32FromUtf8(const char** pUtf8Ptr)
-{
- uint32_t ret;
- int seq_len;
- int i;
-
- /* Mask for leader byte for lengths 1, 2, 3, and 4 respectively*/
- static const char leaderMask[4] = {0xff, 0x1f, 0x0f, 0x07};
-
- /* Bytes that start with bits "10" are not leading characters. */
- if (((**pUtf8Ptr) & 0xc0) == 0x80) {
- (*pUtf8Ptr)++;
- return UTF16_REPLACEMENT_CHAR;
- }
-
- /* note we tolerate invalid leader 11111xxx here */
- seq_len = UTF8_SEQ_LENGTH(**pUtf8Ptr);
-
- ret = (**pUtf8Ptr) & leaderMask [seq_len - 1];
-
- if (**pUtf8Ptr == '\0') return ret;
-
- (*pUtf8Ptr)++;
- for (i = 1; i < seq_len ; i++, (*pUtf8Ptr)++) {
- if ((**pUtf8Ptr) == '\0') return UTF16_REPLACEMENT_CHAR;
- if (((**pUtf8Ptr) & 0xc0) != 0x80) return UTF16_REPLACEMENT_CHAR;
-
- UTF8_SHIFT_AND_MASK(ret, **pUtf8Ptr);
- }
-
- return ret;
-}
-
-
-/**
- * out_len is an out parameter (which may not be null) containing the
- * length of the UTF-16 string (which may contain embedded \0's)
- */
-
-extern char16_t * strcpy8to16 (char16_t *utf16Str, const char*utf8Str,
- size_t *out_len)
-{
- char16_t *dest = utf16Str;
-
- while (*utf8Str != '\0') {
- uint32_t ret;
-
- ret = getUtf32FromUtf8(&utf8Str);
-
- if (ret <= 0xffff) {
- *dest++ = (char16_t) ret;
- } else if (ret <= UNICODE_UPPER_LIMIT) {
- /* Create surrogate pairs */
- /* See http://en.wikipedia.org/wiki/UTF-16/UCS-2#Method_for_code_points_in_Plane_1.2C_Plane_2 */
-
- *dest++ = 0xd800 | ((ret - 0x10000) >> 10);
- *dest++ = 0xdc00 | ((ret - 0x10000) & 0x3ff);
- } else {
- *dest++ = UTF16_REPLACEMENT_CHAR;
- }
- }
-
- *out_len = dest - utf16Str;
-
- return utf16Str;
-}
-
-/**
- * length is the number of characters in the UTF-8 string.
- * out_len is an out parameter (which may not be null) containing the
- * length of the UTF-16 string (which may contain embedded \0's)
- */
-
-extern char16_t * strcpylen8to16 (char16_t *utf16Str, const char*utf8Str,
- int length, size_t *out_len)
-{
- /* TODO: Share more of this code with the method above. Only 2 lines changed. */
-
- char16_t *dest = utf16Str;
-
- const char *end = utf8Str + length; /* This line */
- while (utf8Str < end) { /* and this line changed. */
- uint32_t ret;
-
- ret = getUtf32FromUtf8(&utf8Str);
-
- if (ret <= 0xffff) {
- *dest++ = (char16_t) ret;
- } else if (ret <= UNICODE_UPPER_LIMIT) {
- /* Create surrogate pairs */
- /* See http://en.wikipedia.org/wiki/UTF-16/UCS-2#Method_for_code_points_in_Plane_1.2C_Plane_2 */
-
- *dest++ = 0xd800 | ((ret - 0x10000) >> 10);
- *dest++ = 0xdc00 | ((ret - 0x10000) & 0x3ff);
- } else {
- *dest++ = UTF16_REPLACEMENT_CHAR;
- }
- }
-
- *out_len = dest - utf16Str;
-
- return utf16Str;
-}
diff --git a/libcutils/threads.c b/libcutils/threads.c
deleted file mode 100644
index 42cc92871..000000000
--- a/libcutils/threads.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* libs/cutils/threads.c
-**
-** Copyright (C) 2007, 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 <cutils/threads.h>
-
-#ifdef HAVE_PTHREADS
-void* thread_store_get( thread_store_t* store )
-{
- const pthread_key_t k = store->tls;
-
- if (!store->has_tls)
- return NULL;
-
- return pthread_getspecific( store->tls );
-}
-
-extern void thread_store_set( thread_store_t* store,
- void* value,
- thread_store_destruct_t destroy)
-{
- pthread_mutex_lock( &store->lock );
- if (!store->has_tls) {
- if (pthread_key_create( &store->tls, destroy) != 0) {
- pthread_mutex_unlock(&store->lock);
- return;
- }
- store->has_tls = 1;
- }
- pthread_mutex_unlock( &store->lock );
-
- pthread_setspecific( store->tls, value );
-}
-
-#endif
-
-#ifdef HAVE_WIN32_THREADS
-void* thread_store_get( thread_store_t* store )
-{
- if (!store->has_tls)
- return NULL;
-
- return (void*) TlsGetValue( store->tls );
-}
-
-void thread_store_set( thread_store_t* store,
- void* value,
- thread_store_destruct_t destroy )
-{
- /* XXX: can't use destructor on thread exit */
- if (!store->lock_init) {
- store->lock_init = -1;
- InitializeCriticalSection( &store->lock );
- store->lock_init = -2;
- } else while (store->lock_init != -2) {
- Sleep(10); /* 10ms */
- }
-
- EnterCriticalSection( &store->lock );
- if (!store->has_tls) {
- store->tls = TlsAlloc();
- if (store->tls == TLS_OUT_OF_INDEXES) {
- LeaveCriticalSection( &store->lock );
- return;
- }
- store->has_tls = 1;
- }
- LeaveCriticalSection( &store->lock );
-
- TlsSetValue( store->tls, value );
-}
-#endif
diff --git a/libcutils/tzfile.h b/libcutils/tzfile.h
deleted file mode 100644
index 8c7037558..000000000
--- a/libcutils/tzfile.h
+++ /dev/null
@@ -1,180 +0,0 @@
-#ifndef TZFILE_H
-
-#define TZFILE_H
-
-/*
-** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson.
-*/
-
-/*
-** This header is for use ONLY with the time conversion code.
-** There is no guarantee that it will remain unchanged,
-** or that it will remain at all.
-** Do NOT copy it to any system include directory.
-** Thank you!
-*/
-
-/*
-** ID
-*/
-
-#ifndef lint
-#ifndef NOID
-static char tzfilehid[] = "@(#)tzfile.h 8.1";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-/*
-** Information about time zone files.
-*/
-
-#ifndef TZDIR
-#define TZDIR "/usr/share/zoneinfo" /* "/android/usr/share/zoneinfo" */ /* Time zone object file directory */
-#endif /* !defined TZDIR */
-
-#ifndef TZDEFAULT
-#define TZDEFAULT "localtime"
-#endif /* !defined TZDEFAULT */
-
-#ifndef TZDEFRULES
-#define TZDEFRULES "posixrules"
-#endif /* !defined TZDEFRULES */
-
-/*
-** Each file begins with. . .
-*/
-
-#define TZ_MAGIC "TZif"
-
-struct tzhead {
- char tzh_magic[4]; /* TZ_MAGIC */
- char tzh_version[1]; /* '\0' or '2' as of 2005 */
- char tzh_reserved[15]; /* reserved--must be zero */
- char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
- char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
- char tzh_leapcnt[4]; /* coded number of leap seconds */
- char tzh_timecnt[4]; /* coded number of transition times */
- char tzh_typecnt[4]; /* coded number of local time types */
- char tzh_charcnt[4]; /* coded number of abbr. chars */
-};
-
-/*
-** . . .followed by. . .
-**
-** tzh_timecnt (char [4])s coded transition times a la time(2)
-** tzh_timecnt (unsigned char)s types of local time starting at above
-** tzh_typecnt repetitions of
-** one (char [4]) coded UTC offset in seconds
-** one (unsigned char) used to set tm_isdst
-** one (unsigned char) that's an abbreviation list index
-** tzh_charcnt (char)s '\0'-terminated zone abbreviations
-** tzh_leapcnt repetitions of
-** one (char [4]) coded leap second transition times
-** one (char [4]) total correction after above
-** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition
-** time is standard time, if FALSE,
-** transition time is wall clock time
-** if absent, transition times are
-** assumed to be wall clock time
-** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition
-** time is UTC, if FALSE,
-** transition time is local time
-** if absent, transition times are
-** assumed to be local time
-*/
-
-/*
-** If tzh_version is '2' or greater, the above is followed by a second instance
-** of tzhead and a second instance of the data in which each coded transition
-** time uses 8 rather than 4 chars,
-** then a POSIX-TZ-environment-variable-style string for use in handling
-** instants after the last transition time stored in the file
-** (with nothing between the newlines if there is no POSIX representation for
-** such instants).
-*/
-
-/*
-** In the current implementation, "tzset()" refuses to deal with files that
-** exceed any of the limits below.
-*/
-
-#ifndef TZ_MAX_TIMES
-#define TZ_MAX_TIMES 1200
-#endif /* !defined TZ_MAX_TIMES */
-
-#ifndef TZ_MAX_TYPES
-#ifndef NOSOLAR
-#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
-#endif /* !defined NOSOLAR */
-#ifdef NOSOLAR
-/*
-** Must be at least 14 for Europe/Riga as of Jan 12 1995,
-** as noted by Earl Chew.
-*/
-#define TZ_MAX_TYPES 20 /* Maximum number of local time types */
-#endif /* !defined NOSOLAR */
-#endif /* !defined TZ_MAX_TYPES */
-
-#ifndef TZ_MAX_CHARS
-#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
- /* (limited by what unsigned chars can hold) */
-#endif /* !defined TZ_MAX_CHARS */
-
-#ifndef TZ_MAX_LEAPS
-#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
-#endif /* !defined TZ_MAX_LEAPS */
-
-#define SECSPERMIN 60
-#define MINSPERHOUR 60
-#define HOURSPERDAY 24
-#define DAYSPERWEEK 7
-#define DAYSPERNYEAR 365
-#define DAYSPERLYEAR 366
-#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
-#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
-#define MONSPERYEAR 12
-
-#define TM_SUNDAY 0
-#define TM_MONDAY 1
-#define TM_TUESDAY 2
-#define TM_WEDNESDAY 3
-#define TM_THURSDAY 4
-#define TM_FRIDAY 5
-#define TM_SATURDAY 6
-
-#define TM_JANUARY 0
-#define TM_FEBRUARY 1
-#define TM_MARCH 2
-#define TM_APRIL 3
-#define TM_MAY 4
-#define TM_JUNE 5
-#define TM_JULY 6
-#define TM_AUGUST 7
-#define TM_SEPTEMBER 8
-#define TM_OCTOBER 9
-#define TM_NOVEMBER 10
-#define TM_DECEMBER 11
-
-#define TM_YEAR_BASE 1900
-
-#define EPOCH_YEAR 1970
-#define EPOCH_WDAY TM_THURSDAY
-
-#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
-
-/*
-** Since everything in isleap is modulo 400 (or a factor of 400), we know that
-** isleap(y) == isleap(y % 400)
-** and so
-** isleap(a + b) == isleap((a + b) % 400)
-** or
-** isleap(a + b) == isleap(a % 400 + b % 400)
-** This is true even if % means modulo rather than Fortran remainder
-** (which is allowed by C89 but not C99).
-** We use this to avoid addition overflow problems.
-*/
-
-#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
-
-#endif /* !defined TZFILE_H */
diff --git a/libcutils/tzstrftime.c b/libcutils/tzstrftime.c
deleted file mode 100644
index 29c50154a..000000000
--- a/libcutils/tzstrftime.c
+++ /dev/null
@@ -1,834 +0,0 @@
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)strftime.c 8.1";
-/*
-** Based on the UCB version with the ID appearing below.
-** This is ANSIish only when "multibyte character == plain character".
-*/
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-#include <time.h>
-#include <tzfile.h>
-#include <limits.h>
-#include <cutils/tztime.h>
-
-/*
-** Copyright (c) 1989 The Regents of the University of California.
-** All rights reserved.
-**
-** Redistribution and use in source and binary forms are permitted
-** provided that the above copyright notice and this paragraph are
-** duplicated in all such forms and that any documentation,
-** advertising materials, and other materials related to such
-** distribution and use acknowledge that the software was developed
-** by the University of California, Berkeley. The name of the
-** University may not be used to endorse or promote products derived
-** from this software without specific prior written permission.
-** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
-** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
-** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-*/
-
-#ifndef LIBC_SCCS
-#ifndef lint
-static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89";
-#endif /* !defined lint */
-#endif /* !defined LIBC_SCCS */
-
-#include <ctype.h>
-
-#define P(x) x
-
-static char * _add P((const char *, char *, const char *, int));
-static char * _conv P((int, const char *, char *, const char *));
-static char * _fmt P((const char *, const struct tm *, char *, const char *,
- int *, const struct strftime_locale *Locale));
-static char * _yconv P((int, int, int, int, char *, const char *, int));
-static char * getformat P((int, char *, char *, char *, char *));
-
-extern char * tzname[];
-
-
-
-
-
-/* from private.h */
-
-#ifndef TYPE_BIT
-#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
-#endif /* !defined TYPE_BIT */
-
-#ifndef TYPE_SIGNED
-#define TYPE_SIGNED(type) (((type) -1) < 0)
-#endif /* !defined TYPE_SIGNED */
-
-#ifndef INT_STRLEN_MAXIMUM
-/*
- * ** 302 / 1000 is log10(2.0) rounded up.
- * ** Subtract one for the sign bit if the type is signed;
- * ** add one for integer division truncation;
- * ** add one more for a minus sign if the type is signed.
- * */
-#define INT_STRLEN_MAXIMUM(type) \
- ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
- 1 + TYPE_SIGNED(type))
-#endif /* !defined INT_STRLEN_MAXIMUM */
-
-/* end of part from private.h */
-
-
-
-
-#ifndef YEAR_2000_NAME
-#define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"
-#endif /* !defined YEAR_2000_NAME */
-
-#define IN_NONE 0
-#define IN_SOME 1
-#define IN_THIS 2
-#define IN_ALL 3
-
-#define FORCE_LOWER_CASE 0x100
-
-size_t
-strftime_tz(s, maxsize, format, t, Locale)
-char * const s;
-const size_t maxsize;
-const char * const format;
-const struct tm * const t;
-const struct strftime_locale *Locale;
-{
- char * p;
- int warn;
-
- warn = IN_NONE;
- p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn, Locale);
-#if 0
- if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
- (void) fprintf(stderr, "\n");
- if (format == NULL)
- (void) fprintf(stderr, "NULL strftime format ");
- else (void) fprintf(stderr, "strftime format \"%s\" ",
- format);
- (void) fprintf(stderr, "yields only two digits of years in ");
- if (warn == IN_SOME)
- (void) fprintf(stderr, "some locales");
- else if (warn == IN_THIS)
- (void) fprintf(stderr, "the current locale");
- else (void) fprintf(stderr, "all locales");
- (void) fprintf(stderr, "\n");
- }
-#endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */
- if (p == s + maxsize)
- return 0;
- *p = '\0';
- return p - s;
-}
-
-static char *getformat(int modifier, char *normal, char *underscore,
- char *dash, char *zero) {
- switch (modifier) {
- case '_':
- return underscore;
-
- case '-':
- return dash;
-
- case '0':
- return zero;
- }
-
- return normal;
-}
-
-static char *
-_fmt(format, t, pt, ptlim, warnp, Locale)
-const char * format;
-const struct tm * const t;
-char * pt;
-const char * const ptlim;
-int * warnp;
-const struct strftime_locale *Locale;
-{
- for ( ; *format; ++format) {
- if (*format == '%') {
- int modifier = 0;
-label:
- switch (*++format) {
- case '\0':
- --format;
- break;
- case 'A':
- pt = _add((t->tm_wday < 0 ||
- t->tm_wday >= DAYSPERWEEK) ?
- "?" : Locale->weekday[t->tm_wday],
- pt, ptlim, modifier);
- continue;
- case 'a':
- pt = _add((t->tm_wday < 0 ||
- t->tm_wday >= DAYSPERWEEK) ?
- "?" : Locale->wday[t->tm_wday],
- pt, ptlim, modifier);
- continue;
- case 'B':
- pt = _add((t->tm_mon < 0 ||
- t->tm_mon >= MONSPERYEAR) ?
- "?" : Locale->month[t->tm_mon],
- pt, ptlim, modifier);
- continue;
- case 'b':
- case 'h':
- pt = _add((t->tm_mon < 0 ||
- t->tm_mon >= MONSPERYEAR) ?
- "?" : Locale->mon[t->tm_mon],
- pt, ptlim, modifier);
- continue;
- case 'C':
- /*
- ** %C used to do a...
- ** _fmt("%a %b %e %X %Y", t);
- ** ...whereas now POSIX 1003.2 calls for
- ** something completely different.
- ** (ado, 1993-05-24)
- */
- pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0,
- pt, ptlim, modifier);
- continue;
- case 'c':
- {
- int warn2 = IN_SOME;
-
- pt = _fmt(Locale->c_fmt, t, pt, ptlim, warnp, Locale);
- if (warn2 == IN_ALL)
- warn2 = IN_THIS;
- if (warn2 > *warnp)
- *warnp = warn2;
- }
- continue;
- case 'D':
- pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp, Locale);
- continue;
- case 'd':
- pt = _conv(t->tm_mday,
- getformat(modifier, "%02d",
- "%2d", "%d", "%02d"),
- pt, ptlim);
- continue;
- case 'E':
- case 'O':
- /*
- ** C99 locale modifiers.
- ** The sequences
- ** %Ec %EC %Ex %EX %Ey %EY
- ** %Od %oe %OH %OI %Om %OM
- ** %OS %Ou %OU %OV %Ow %OW %Oy
- ** are supposed to provide alternate
- ** representations.
- */
- goto label;
- case '_':
- case '-':
- case '0':
- case '^':
- case '#':
- modifier = *format;
- goto label;
- case 'e':
- pt = _conv(t->tm_mday,
- getformat(modifier, "%2d",
- "%2d", "%d", "%02d"),
- pt, ptlim);
- continue;
- case 'F':
- pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp, Locale);
- continue;
- case 'H':
- pt = _conv(t->tm_hour,
- getformat(modifier, "%02d",
- "%2d", "%d", "%02d"),
- pt, ptlim);
- continue;
- case 'I':
- pt = _conv((t->tm_hour % 12) ?
- (t->tm_hour % 12) : 12,
- getformat(modifier, "%02d",
- "%2d", "%d", "%02d"),
- pt, ptlim);
- continue;
- case 'j':
- pt = _conv(t->tm_yday + 1,
- getformat(modifier, "%03d", "%3d", "%d", "%03d"),
- pt, ptlim);
- continue;
- case 'k':
- /*
- ** This used to be...
- ** _conv(t->tm_hour % 12 ?
- ** t->tm_hour % 12 : 12, 2, ' ');
- ** ...and has been changed to the below to
- ** match SunOS 4.1.1 and Arnold Robbins'
- ** strftime version 3.0. That is, "%k" and
- ** "%l" have been swapped.
- ** (ado, 1993-05-24)
- */
- pt = _conv(t->tm_hour,
- getformat(modifier, "%2d",
- "%2d", "%d", "%02d"),
- pt, ptlim);
- continue;
-#ifdef KITCHEN_SINK
- case 'K':
- /*
- ** After all this time, still unclaimed!
- */
- pt = _add("kitchen sink", pt, ptlim, modifier);
- continue;
-#endif /* defined KITCHEN_SINK */
- case 'l':
- /*
- ** This used to be...
- ** _conv(t->tm_hour, 2, ' ');
- ** ...and has been changed to the below to
- ** match SunOS 4.1.1 and Arnold Robbin's
- ** strftime version 3.0. That is, "%k" and
- ** "%l" have been swapped.
- ** (ado, 1993-05-24)
- */
- pt = _conv((t->tm_hour % 12) ?
- (t->tm_hour % 12) : 12,
- getformat(modifier, "%2d",
- "%2d", "%d", "%02d"),
- pt, ptlim);
- continue;
- case 'M':
- pt = _conv(t->tm_min,
- getformat(modifier, "%02d",
- "%2d", "%d", "%02d"),
- pt, ptlim);
- continue;
- case 'm':
- pt = _conv(t->tm_mon + 1,
- getformat(modifier, "%02d",
- "%2d", "%d", "%02d"),
- pt, ptlim);
- continue;
- case 'n':
- pt = _add("\n", pt, ptlim, modifier);
- continue;
- case 'p':
- pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
- Locale->pm :
- Locale->am,
- pt, ptlim, modifier);
- continue;
- case 'P':
- pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
- Locale->pm :
- Locale->am,
- pt, ptlim, FORCE_LOWER_CASE);
- continue;
- case 'R':
- pt = _fmt("%H:%M", t, pt, ptlim, warnp, Locale);
- continue;
- case 'r':
- pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp, Locale);
- continue;
- case 'S':
- pt = _conv(t->tm_sec,
- getformat(modifier, "%02d",
- "%2d", "%d", "%02d"),
- pt, ptlim);
- continue;
- case 's':
- {
- struct tm tm;
- char buf[INT_STRLEN_MAXIMUM(
- time_t) + 1];
- time_t mkt;
-
- tm = *t;
- mkt = mktime(&tm);
- if (TYPE_SIGNED(time_t))
- (void) sprintf(buf, "%ld",
- (long) mkt);
- else (void) sprintf(buf, "%lu",
- (unsigned long) mkt);
- pt = _add(buf, pt, ptlim, modifier);
- }
- continue;
- case 'T':
- pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp, Locale);
- continue;
- case 't':
- pt = _add("\t", pt, ptlim, modifier);
- continue;
- case 'U':
- pt = _conv((t->tm_yday + DAYSPERWEEK -
- t->tm_wday) / DAYSPERWEEK,
- getformat(modifier, "%02d",
- "%2d", "%d", "%02d"),
- pt, ptlim);
- continue;
- case 'u':
- /*
- ** From Arnold Robbins' strftime version 3.0:
- ** "ISO 8601: Weekday as a decimal number
- ** [1 (Monday) - 7]"
- ** (ado, 1993-05-24)
- */
- pt = _conv((t->tm_wday == 0) ?
- DAYSPERWEEK : t->tm_wday, "%d", pt, ptlim);
- continue;
- case 'V': /* ISO 8601 week number */
- case 'G': /* ISO 8601 year (four digits) */
- case 'g': /* ISO 8601 year (two digits) */
-/*
-** From Arnold Robbins' strftime version 3.0: "the week number of the
-** year (the first Monday as the first day of week 1) as a decimal number
-** (01-53)."
-** (ado, 1993-05-24)
-**
-** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn:
-** "Week 01 of a year is per definition the first week which has the
-** Thursday in this year, which is equivalent to the week which contains
-** the fourth day of January. In other words, the first week of a new year
-** is the week which has the majority of its days in the new year. Week 01
-** might also contain days from the previous year and the week before week
-** 01 of a year is the last week (52 or 53) of the previous year even if
-** it contains days from the new year. A week starts with Monday (day 1)
-** and ends with Sunday (day 7). For example, the first week of the year
-** 1997 lasts from 1996-12-30 to 1997-01-05..."
-** (ado, 1996-01-02)
-*/
- {
- int year;
- int base;
- int yday;
- int wday;
- int w;
-
- year = t->tm_year;
- base = TM_YEAR_BASE;
- yday = t->tm_yday;
- wday = t->tm_wday;
- for ( ; ; ) {
- int len;
- int bot;
- int top;
-
- len = isleap_sum(year, base) ?
- DAYSPERLYEAR :
- DAYSPERNYEAR;
- /*
- ** What yday (-3 ... 3) does
- ** the ISO year begin on?
- */
- bot = ((yday + 11 - wday) %
- DAYSPERWEEK) - 3;
- /*
- ** What yday does the NEXT
- ** ISO year begin on?
- */
- top = bot -
- (len % DAYSPERWEEK);
- if (top < -3)
- top += DAYSPERWEEK;
- top += len;
- if (yday >= top) {
- ++base;
- w = 1;
- break;
- }
- if (yday >= bot) {
- w = 1 + ((yday - bot) /
- DAYSPERWEEK);
- break;
- }
- --base;
- yday += isleap_sum(year, base) ?
- DAYSPERLYEAR :
- DAYSPERNYEAR;
- }
-#ifdef XPG4_1994_04_09
- if ((w == 52 &&
- t->tm_mon == TM_JANUARY) ||
- (w == 1 &&
- t->tm_mon == TM_DECEMBER))
- w = 53;
-#endif /* defined XPG4_1994_04_09 */
- if (*format == 'V')
- pt = _conv(w,
- getformat(modifier,
- "%02d",
- "%2d",
- "%d",
- "%02d"),
- pt, ptlim);
- else if (*format == 'g') {
- *warnp = IN_ALL;
- pt = _yconv(year, base, 0, 1,
- pt, ptlim, modifier);
- } else pt = _yconv(year, base, 1, 1,
- pt, ptlim, modifier);
- }
- continue;
- case 'v':
- /*
- ** From Arnold Robbins' strftime version 3.0:
- ** "date as dd-bbb-YYYY"
- ** (ado, 1993-05-24)
- */
- pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp, Locale);
- continue;
- case 'W':
- pt = _conv((t->tm_yday + DAYSPERWEEK -
- (t->tm_wday ?
- (t->tm_wday - 1) :
- (DAYSPERWEEK - 1))) / DAYSPERWEEK,
- getformat(modifier, "%02d",
- "%2d", "%d", "%02d"),
- pt, ptlim);
- continue;
- case 'w':
- pt = _conv(t->tm_wday, "%d", pt, ptlim);
- continue;
- case 'X':
- pt = _fmt(Locale->X_fmt, t, pt, ptlim, warnp, Locale);
- continue;
- case 'x':
- {
- int warn2 = IN_SOME;
-
- pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2, Locale);
- if (warn2 == IN_ALL)
- warn2 = IN_THIS;
- if (warn2 > *warnp)
- *warnp = warn2;
- }
- continue;
- case 'y':
- *warnp = IN_ALL;
- pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1,
- pt, ptlim, modifier);
- continue;
- case 'Y':
- pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1,
- pt, ptlim, modifier);
- continue;
- case 'Z':
-#ifdef TM_ZONE
- if (t->TM_ZONE != NULL)
- pt = _add(t->TM_ZONE, pt, ptlim,
- modifier);
- else
-#endif /* defined TM_ZONE */
- if (t->tm_isdst >= 0)
- pt = _add(tzname[t->tm_isdst != 0],
- pt, ptlim, modifier);
- /*
- ** C99 says that %Z must be replaced by the
- ** empty string if the time zone is not
- ** determinable.
- */
- continue;
- case 'z':
- {
- int diff;
- char const * sign;
-
- if (t->tm_isdst < 0)
- continue;
-#ifdef TM_GMTOFF
- diff = t->TM_GMTOFF;
-#else /* !defined TM_GMTOFF */
- /*
- ** C99 says that the UTC offset must
- ** be computed by looking only at
- ** tm_isdst. This requirement is
- ** incorrect, since it means the code
- ** must rely on magic (in this case
- ** altzone and timezone), and the
- ** magic might not have the correct
- ** offset. Doing things correctly is
- ** tricky and requires disobeying C99;
- ** see GNU C strftime for details.
- ** For now, punt and conform to the
- ** standard, even though it's incorrect.
- **
- ** C99 says that %z must be replaced by the
- ** empty string if the time zone is not
- ** determinable, so output nothing if the
- ** appropriate variables are not available.
- */
- if (t->tm_isdst == 0)
-#ifdef USG_COMPAT
- diff = -timezone;
-#else /* !defined USG_COMPAT */
- continue;
-#endif /* !defined USG_COMPAT */
- else
-#ifdef ALTZONE
- diff = -altzone;
-#else /* !defined ALTZONE */
- continue;
-#endif /* !defined ALTZONE */
-#endif /* !defined TM_GMTOFF */
- if (diff < 0) {
- sign = "-";
- diff = -diff;
- } else sign = "+";
- pt = _add(sign, pt, ptlim, modifier);
- diff /= SECSPERMIN;
- diff = (diff / MINSPERHOUR) * 100 +
- (diff % MINSPERHOUR);
- pt = _conv(diff,
- getformat(modifier, "%04d",
- "%4d", "%d", "%04d"),
- pt, ptlim);
- }
- continue;
- case '+':
- pt = _fmt(Locale->date_fmt, t, pt, ptlim,
- warnp, Locale);
- continue;
- case '%':
- /*
- ** X311J/88-090 (4.12.3.5): if conversion char is
- ** undefined, behavior is undefined. Print out the
- ** character itself as printf(3) also does.
- */
- default:
- break;
- }
- }
- if (pt == ptlim)
- break;
- *pt++ = *format;
- }
- return pt;
-}
-
-static char *
-_conv(n, format, pt, ptlim)
-const int n;
-const char * const format;
-char * const pt;
-const char * const ptlim;
-{
- char buf[INT_STRLEN_MAXIMUM(int) + 1];
-
- (void) sprintf(buf, format, n);
- return _add(buf, pt, ptlim, 0);
-}
-
-static char *
-_add(str, pt, ptlim, modifier)
-const char * str;
-char * pt;
-const char * const ptlim;
-int modifier;
-{
- int c;
-
- switch (modifier) {
- case FORCE_LOWER_CASE:
- while (pt < ptlim && (*pt = tolower(*str++)) != '\0') {
- ++pt;
- }
- break;
-
- case '^':
- while (pt < ptlim && (*pt = toupper(*str++)) != '\0') {
- ++pt;
- }
- break;
-
- case '#':
- while (pt < ptlim && (c = *str++) != '\0') {
- if (isupper(c)) {
- c = tolower(c);
- } else if (islower(c)) {
- c = toupper(c);
- }
- *pt = c;
- ++pt;
- }
-
- break;
-
- default:
- while (pt < ptlim && (*pt = *str++) != '\0') {
- ++pt;
- }
- }
-
- return pt;
-}
-
-/*
-** POSIX and the C Standard are unclear or inconsistent about
-** what %C and %y do if the year is negative or exceeds 9999.
-** Use the convention that %C concatenated with %y yields the
-** same output as %Y, and that %Y contains at least 4 bytes,
-** with more only if necessary.
-*/
-
-static char *
-_yconv(a, b, convert_top, convert_yy, pt, ptlim, modifier)
-const int a;
-const int b;
-const int convert_top;
-const int convert_yy;
-char * pt;
-const char * const ptlim;
-int modifier;
-{
- register int lead;
- register int trail;
-
-#define DIVISOR 100
- trail = a % DIVISOR + b % DIVISOR;
- lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR;
- trail %= DIVISOR;
- if (trail < 0 && lead > 0) {
- trail += DIVISOR;
- --lead;
- } else if (lead < 0 && trail > 0) {
- trail -= DIVISOR;
- ++lead;
- }
- if (convert_top) {
- if (lead == 0 && trail < 0)
- pt = _add("-0", pt, ptlim, modifier);
- else pt = _conv(lead, getformat(modifier, "%02d",
- "%2d", "%d", "%02d"),
- pt, ptlim);
- }
- if (convert_yy)
- pt = _conv(((trail < 0) ? -trail : trail),
- getformat(modifier, "%02d", "%2d", "%d", "%02d"),
- pt, ptlim);
- return pt;
-}
-
-#ifdef LOCALE_HOME
-static struct lc_time_T *
-_loc P((void))
-{
- static const char locale_home[] = LOCALE_HOME;
- static const char lc_time[] = "LC_TIME";
- static char * locale_buf;
-
- int fd;
- int oldsun; /* "...ain't got nothin' to do..." */
- char * lbuf;
- char * name;
- char * p;
- const char ** ap;
- const char * plim;
- char filename[FILENAME_MAX];
- struct stat st;
- size_t namesize;
- size_t bufsize;
-
- /*
- ** Use localebuf.mon[0] to signal whether locale is already set up.
- */
- if (localebuf.mon[0])
- return &localebuf;
- name = setlocale(LC_TIME, (char *) NULL);
- if (name == NULL || *name == '\0')
- goto no_locale;
- /*
- ** If the locale name is the same as our cache, use the cache.
- */
- lbuf = locale_buf;
- if (lbuf != NULL && strcmp(name, lbuf) == 0) {
- p = lbuf;
- for (ap = (const char **) &localebuf;
- ap < (const char **) (&localebuf + 1);
- ++ap)
- *ap = p += strlen(p) + 1;
- return &localebuf;
- }
- /*
- ** Slurp the locale file into the cache.
- */
- namesize = strlen(name) + 1;
- if (sizeof filename <
- ((sizeof locale_home) + namesize + (sizeof lc_time)))
- goto no_locale;
- oldsun = 0;
- (void) sprintf(filename, "%s/%s/%s", locale_home, name, lc_time);
- fd = open(filename, O_RDONLY);
- if (fd < 0) {
- /*
- ** Old Sun systems have a different naming and data convention.
- */
- oldsun = 1;
- (void) sprintf(filename, "%s/%s/%s", locale_home,
- lc_time, name);
- fd = open(filename, O_RDONLY);
- if (fd < 0)
- goto no_locale;
- }
- if (fstat(fd, &st) != 0)
- goto bad_locale;
- if (st.st_size <= 0)
- goto bad_locale;
- bufsize = namesize + st.st_size;
- locale_buf = NULL;
- lbuf = (lbuf == NULL) ? malloc(bufsize) : realloc(lbuf, bufsize);
- if (lbuf == NULL)
- goto bad_locale;
- (void) strcpy(lbuf, name);
- p = lbuf + namesize;
- plim = p + st.st_size;
- if (read(fd, p, (size_t) st.st_size) != st.st_size)
- goto bad_lbuf;
- if (close(fd) != 0)
- goto bad_lbuf;
- /*
- ** Parse the locale file into localebuf.
- */
- if (plim[-1] != '\n')
- goto bad_lbuf;
- for (ap = (const char **) &localebuf;
- ap < (const char **) (&localebuf + 1);
- ++ap) {
- if (p == plim)
- goto bad_lbuf;
- *ap = p;
- while (*p != '\n')
- ++p;
- *p++ = '\0';
- }
- if (oldsun) {
- /*
- ** SunOS 4 used an obsolescent format; see localdtconv(3).
- ** c_fmt had the ``short format for dates and times together''
- ** (SunOS 4 date, "%a %b %e %T %Z %Y" in the C locale);
- ** date_fmt had the ``long format for dates''
- ** (SunOS 4 strftime %C, "%A, %B %e, %Y" in the C locale).
- ** Discard the latter in favor of the former.
- */
- localebuf.date_fmt = localebuf.c_fmt;
- }
- /*
- ** Record the successful parse in the cache.
- */
- locale_buf = lbuf;
-
- return &localebuf;
-
-bad_lbuf:
- free(lbuf);
-bad_locale:
- (void) close(fd);
-no_locale:
- localebuf = C_time_locale;
- locale_buf = NULL;
- return &localebuf;
-}
-#endif /* defined LOCALE_HOME */
diff --git a/libcutils/tztime.c b/libcutils/tztime.c
deleted file mode 100644
index 93bbb29da..000000000
--- a/libcutils/tztime.c
+++ /dev/null
@@ -1,1915 +0,0 @@
-/*
-** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson.
-*/
-
-#include <stdio.h>
-
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)localtime.c 8.3";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-/*
-** Leap second handling from Bradley White.
-** POSIX-style TZ environment variable handling from Guy Harris.
-*/
-
-/*LINTLIBRARY*/
-
-#include "private.h"
-#include "tzfile.h"
-#include "fcntl.h"
-#include "float.h" /* for FLT_MAX and DBL_MAX */
-
-#ifndef TZ_ABBR_MAX_LEN
-#define TZ_ABBR_MAX_LEN 16
-#endif /* !defined TZ_ABBR_MAX_LEN */
-
-#ifndef TZ_ABBR_CHAR_SET
-#define TZ_ABBR_CHAR_SET \
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
-#endif /* !defined TZ_ABBR_CHAR_SET */
-
-#ifndef TZ_ABBR_ERR_CHAR
-#define TZ_ABBR_ERR_CHAR '_'
-#endif /* !defined TZ_ABBR_ERR_CHAR */
-
-#define INDEXFILE "/system/usr/share/zoneinfo/zoneinfo.idx"
-#define DATAFILE "/system/usr/share/zoneinfo/zoneinfo.dat"
-#define NAMELEN 40
-#define INTLEN 4
-#define READLEN (NAMELEN + 3 * INTLEN)
-
-/*
-** SunOS 4.1.1 headers lack O_BINARY.
-*/
-
-#ifdef O_BINARY
-#define OPEN_MODE (O_RDONLY | O_BINARY)
-#endif /* defined O_BINARY */
-#ifndef O_BINARY
-#define OPEN_MODE O_RDONLY
-#endif /* !defined O_BINARY */
-
-#ifndef WILDABBR
-/*
-** Someone might make incorrect use of a time zone abbreviation:
-** 1. They might reference tzname[0] before calling tzset (explicitly
-** or implicitly).
-** 2. They might reference tzname[1] before calling tzset (explicitly
-** or implicitly).
-** 3. They might reference tzname[1] after setting to a time zone
-** in which Daylight Saving Time is never observed.
-** 4. They might reference tzname[0] after setting to a time zone
-** in which Standard Time is never observed.
-** 5. They might reference tm.TM_ZONE after calling offtime.
-** What's best to do in the above cases is open to debate;
-** for now, we just set things up so that in any of the five cases
-** WILDABBR is used. Another possibility: initialize tzname[0] to the
-** string "tzname[0] used before set", and similarly for the other cases.
-** And another: initialize tzname[0] to "ERA", with an explanation in the
-** manual page of what this "time zone abbreviation" means (doing this so
-** that tzname[0] has the "normal" length of three characters).
-*/
-#define WILDABBR " "
-#endif /* !defined WILDABBR */
-
-static char wildabbr[] = WILDABBR;
-
-static const char gmt[] = "GMT";
-
-/*
-** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
-** We default to US rules as of 1999-08-17.
-** POSIX 1003.1 section 8.1.1 says that the default DST rules are
-** implementation dependent; for historical reasons, US rules are a
-** common default.
-*/
-#ifndef TZDEFRULESTRING
-#define TZDEFRULESTRING ",M4.1.0,M10.5.0"
-#endif /* !defined TZDEFDST */
-
-struct ttinfo { /* time type information */
- long tt_gmtoff; /* UTC offset in seconds */
- int tt_isdst; /* used to set tm_isdst */
- int tt_abbrind; /* abbreviation list index */
- int tt_ttisstd; /* TRUE if transition is std time */
- int tt_ttisgmt; /* TRUE if transition is UTC */
-};
-
-struct lsinfo { /* leap second information */
- time_t ls_trans; /* transition time */
- long ls_corr; /* correction to apply */
-};
-
-#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
-
-#ifdef TZNAME_MAX
-#define MY_TZNAME_MAX TZNAME_MAX
-#endif /* defined TZNAME_MAX */
-#ifndef TZNAME_MAX
-#define MY_TZNAME_MAX 255
-#endif /* !defined TZNAME_MAX */
-
-struct state {
- int leapcnt;
- int timecnt;
- int typecnt;
- int charcnt;
- int goback;
- int goahead;
- time_t ats[TZ_MAX_TIMES];
- unsigned char types[TZ_MAX_TIMES];
- struct ttinfo ttis[TZ_MAX_TYPES];
- char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
- (2 * (MY_TZNAME_MAX + 1)))];
- struct lsinfo lsis[TZ_MAX_LEAPS];
-};
-
-struct rule {
- int r_type; /* type of rule--see below */
- int r_day; /* day number of rule */
- int r_week; /* week number of rule */
- int r_mon; /* month number of rule */
- long r_time; /* transition time of rule */
-};
-
-#define JULIAN_DAY 0 /* Jn - Julian day */
-#define DAY_OF_YEAR 1 /* n - day of year */
-#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
-
-/*
-** Prototypes for static functions.
-*/
-
-static long detzcode P((const char * codep));
-static time_t detzcode64 P((const char * codep));
-static int differ_by_repeat P((time_t t1, time_t t0));
-static const char * getzname P((const char * strp));
-static const char * getqzname P((const char * strp, const int delim));
-static const char * getnum P((const char * strp, int * nump, int min,
- int max));
-static const char * getsecs P((const char * strp, long * secsp));
-static const char * getoffset P((const char * strp, long * offsetp));
-static const char * getrule P((const char * strp, struct rule * rulep));
-static void gmtload P((struct state * sp));
-static struct tm * gmtsub P((const time_t * timep, long offset,
- struct tm * tmp));
-static struct tm * localsub P((const time_t * timep, long offset,
- struct tm * tmp, struct state *sp));
-static int increment_overflow P((int * number, int delta));
-static int leaps_thru_end_of P((int y));
-static int long_increment_overflow P((long * number, int delta));
-static int long_normalize_overflow P((long * tensptr,
- int * unitsptr, int base));
-static int normalize_overflow P((int * tensptr, int * unitsptr,
- int base));
-static void settzname P((void));
-static time_t time1 P((struct tm * tmp,
- struct tm * (*funcp) P((const time_t *,
- long, struct tm *, const struct state* sp)),
- long offset, const struct state * sp));
-static time_t time2 P((struct tm *tmp,
- struct tm * (*funcp) P((const time_t *,
- long, struct tm*, const struct state* sp)),
- long offset, int * okayp, const struct state * sp));
-static time_t time2sub P((struct tm *tmp,
- struct tm * (*funcp) P((const time_t*, long, struct tm*,const struct state *sp)),
- long offset, int * okayp, int do_norm_secs,
- const struct state *sp));
-static struct tm * timesub P((const time_t * timep, long offset,
- const struct state * sp, struct tm * tmp));
-static int tmcomp P((const struct tm * atmp,
- const struct tm * btmp));
-static time_t transtime P((time_t janfirst, int year,
- const struct rule * rulep, long offset));
-static int tzload P((const char * name, struct state * sp,
- int doextend));
-static int tzload_uncached P((const char * name, struct state * sp,
- int doextend));
-static int tzparse P((const char * name, struct state * sp,
- int lastditch));
-
-#ifdef ALL_STATE
-static struct state * gmtptr;
-#endif /* defined ALL_STATE */
-
-#ifndef ALL_STATE
-static struct state gmtmem;
-#define gmtptr (&gmtmem)
-#endif /* State Farm */
-
-#define CACHE_COUNT 4
-static char * g_cacheNames[CACHE_COUNT] = {0,0};
-static struct state g_cacheStates[CACHE_COUNT];
-static int g_lastCache = 0;
-static struct state g_utc;
-unsigned char g_utcSet = 0;
-
-
-#ifndef TZ_STRLEN_MAX
-#define TZ_STRLEN_MAX 255
-#endif /* !defined TZ_STRLEN_MAX */
-
-static char lcl_TZname[TZ_STRLEN_MAX + 1];
-static int lcl_is_set;
-static int gmt_is_set;
-
-char * tzname[2] = {
- wildabbr,
- wildabbr
-};
-
-/*
-** Section 4.12.3 of X3.159-1989 requires that
-** Except for the strftime function, these functions [asctime,
-** ctime, gmtime, localtime] return values in one of two static
-** objects: a broken-down time structure and an array of char.
-** Thanks to Paul Eggert for noting this.
-*/
-
-static struct tm tm;
-
-#ifdef USG_COMPAT
-time_t timezone = 0;
-int daylight = 0;
-#endif /* defined USG_COMPAT */
-
-#ifdef ALTZONE
-time_t altzone = 0;
-#endif /* defined ALTZONE */
-
-static long
-detzcode(codep)
-const char * const codep;
-{
- register long result;
- register int i;
-
- result = (codep[0] & 0x80) ? ~0L : 0;
- for (i = 0; i < 4; ++i)
- result = (result << 8) | (codep[i] & 0xff);
- return result;
-}
-
-static time_t
-detzcode64(codep)
-const char * const codep;
-{
- register time_t result;
- register int i;
-
- result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0;
- for (i = 0; i < 8; ++i)
- result = result * 256 + (codep[i] & 0xff);
- return result;
-}
-
-static int
-differ_by_repeat(t1, t0)
-const time_t t1;
-const time_t t0;
-{
- if (TYPE_INTEGRAL(time_t) &&
- TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
- return 0;
- return t1 - t0 == SECSPERREPEAT;
-}
-
-static int toint(unsigned char *s) {
- return (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
-}
-
-static int
-tzload(const char *name, struct state * const sp, const int doextend)
-{
- if (name) {
- int i, err;
- if (0 == strcmp(name, "UTC")) {
- if (!g_utcSet) {
- tzload_uncached(name, &g_utc, 1);
- g_utcSet = 1;
- }
- //printf("tzload: utc\n");
- *sp = g_utc;
- return 0;
- }
- for (i=0; i<CACHE_COUNT; i++) {
- if (g_cacheNames[i] && 0 == strcmp(name, g_cacheNames[i])) {
- *sp = g_cacheStates[i];
- //printf("tzload: hit: %s\n", name);
- return 0;
- }
- }
- //printf("tzload: miss: %s\n", name);
- g_lastCache++;
- if (g_lastCache >= CACHE_COUNT) {
- g_lastCache = 0;
- }
- i = g_lastCache;
- if (g_cacheNames[i]) {
- free(g_cacheNames[i]);
- }
- err = tzload_uncached(name, &(g_cacheStates[i]), 1);
- if (err == 0) {
- g_cacheNames[i] = strdup(name);
- *sp = g_cacheStates[i];
- return 0;
- } else {
- g_cacheNames[i] = NULL;
- return err;
- }
- }
- return tzload_uncached(name, sp, doextend);
-}
-
-static int
-tzload_uncached(name, sp, doextend)
-register const char * name;
-register struct state * const sp;
-register const int doextend;
-{
- register const char * p;
- register int i;
- register int fid;
- register int stored;
- register int nread;
- union {
- struct tzhead tzhead;
- char buf[2 * sizeof(struct tzhead) +
- 2 * sizeof *sp +
- 4 * TZ_MAX_TIMES];
- } u;
- int toread = sizeof u.buf;
-
- if (name == NULL && (name = TZDEFAULT) == NULL)
- return -1;
- {
- register int doaccess;
- /*
- ** Section 4.9.1 of the C standard says that
- ** "FILENAME_MAX expands to an integral constant expression
- ** that is the size needed for an array of char large enough
- ** to hold the longest file name string that the implementation
- ** guarantees can be opened."
- */
- char fullname[FILENAME_MAX + 1];
- const char *origname = name;
-
- if (name[0] == ':')
- ++name;
- doaccess = name[0] == '/';
- if (!doaccess) {
- if ((p = TZDIR) == NULL)
- return -1;
- if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
- return -1;
- (void) strcpy(fullname, p);
- (void) strcat(fullname, "/");
- (void) strcat(fullname, name);
- /*
- ** Set doaccess if '.' (as in "../") shows up in name.
- */
- if (strchr(name, '.') != NULL)
- doaccess = TRUE;
- name = fullname;
- }
- if (doaccess && access(name, R_OK) != 0)
- return -1;
- if ((fid = open(name, OPEN_MODE)) == -1) {
- char buf[READLEN];
- char name[NAMELEN + 1];
- int fidix = open(INDEXFILE, OPEN_MODE);
- int off = -1;
-
- if (fidix < 0) {
- return -1;
- }
-
- while (read(fidix, buf, sizeof(buf)) == sizeof(buf)) {
- memcpy(name, buf, NAMELEN);
- name[NAMELEN] = '\0';
-
- if (strcmp(name, origname) == 0) {
- off = toint((unsigned char *) buf + NAMELEN);
- toread = toint((unsigned char *) buf + NAMELEN + INTLEN);
- break;
- }
- }
-
- close(fidix);
-
- if (off < 0)
- return -1;
-
- fid = open(DATAFILE, OPEN_MODE);
-
- if (fid < 0) {
- return -1;
- }
-
- if (lseek(fid, off, SEEK_SET) < 0) {
- return -1;
- }
- }
- }
- nread = read(fid, u.buf, toread);
- if (close(fid) < 0 || nread <= 0)
- return -1;
- for (stored = 4; stored <= 8; stored *= 2) {
- int ttisstdcnt;
- int ttisgmtcnt;
-
- ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
- ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
- sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
- sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
- sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
- sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
- p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
- if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
- sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
- sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
- sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
- (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
- (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
- return -1;
- if (nread - (p - u.buf) <
- sp->timecnt * stored + /* ats */
- sp->timecnt + /* types */
- sp->typecnt * 6 + /* ttinfos */
- sp->charcnt + /* chars */
- sp->leapcnt * (stored + 4) + /* lsinfos */
- ttisstdcnt + /* ttisstds */
- ttisgmtcnt) /* ttisgmts */
- return -1;
- for (i = 0; i < sp->timecnt; ++i) {
- sp->ats[i] = (stored == 4) ?
- detzcode(p) : detzcode64(p);
- p += stored;
- }
- for (i = 0; i < sp->timecnt; ++i) {
- sp->types[i] = (unsigned char) *p++;
- if (sp->types[i] >= sp->typecnt)
- return -1;
- }
- for (i = 0; i < sp->typecnt; ++i) {
- register struct ttinfo * ttisp;
-
- ttisp = &sp->ttis[i];
- ttisp->tt_gmtoff = detzcode(p);
- p += 4;
- ttisp->tt_isdst = (unsigned char) *p++;
- if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
- return -1;
- ttisp->tt_abbrind = (unsigned char) *p++;
- if (ttisp->tt_abbrind < 0 ||
- ttisp->tt_abbrind > sp->charcnt)
- return -1;
- }
- for (i = 0; i < sp->charcnt; ++i)
- sp->chars[i] = *p++;
- sp->chars[i] = '\0'; /* ensure '\0' at end */
- for (i = 0; i < sp->leapcnt; ++i) {
- register struct lsinfo * lsisp;
-
- lsisp = &sp->lsis[i];
- lsisp->ls_trans = (stored == 4) ?
- detzcode(p) : detzcode64(p);
- p += stored;
- lsisp->ls_corr = detzcode(p);
- p += 4;
- }
- for (i = 0; i < sp->typecnt; ++i) {
- register struct ttinfo * ttisp;
-
- ttisp = &sp->ttis[i];
- if (ttisstdcnt == 0)
- ttisp->tt_ttisstd = FALSE;
- else {
- ttisp->tt_ttisstd = *p++;
- if (ttisp->tt_ttisstd != TRUE &&
- ttisp->tt_ttisstd != FALSE)
- return -1;
- }
- }
- for (i = 0; i < sp->typecnt; ++i) {
- register struct ttinfo * ttisp;
-
- ttisp = &sp->ttis[i];
- if (ttisgmtcnt == 0)
- ttisp->tt_ttisgmt = FALSE;
- else {
- ttisp->tt_ttisgmt = *p++;
- if (ttisp->tt_ttisgmt != TRUE &&
- ttisp->tt_ttisgmt != FALSE)
- return -1;
- }
- }
- /*
- ** Out-of-sort ats should mean we're running on a
- ** signed time_t system but using a data file with
- ** unsigned values (or vice versa).
- */
- for (i = 0; i < sp->timecnt - 2; ++i)
- if (sp->ats[i] > sp->ats[i + 1]) {
- ++i;
- if (TYPE_SIGNED(time_t)) {
- /*
- ** Ignore the end (easy).
- */
- sp->timecnt = i;
- } else {
- /*
- ** Ignore the beginning (harder).
- */
- register int j;
-
- for (j = 0; j + i < sp->timecnt; ++j) {
- sp->ats[j] = sp->ats[j + i];
- sp->types[j] = sp->types[j + i];
- }
- sp->timecnt = j;
- }
- break;
- }
- /*
- ** If this is an old file, we're done.
- */
- if (u.tzhead.tzh_version[0] == '\0')
- break;
- nread -= p - u.buf;
- for (i = 0; i < nread; ++i)
- u.buf[i] = p[i];
- /*
- ** If this is a narrow integer time_t system, we're done.
- */
- if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
- break;
- }
- if (doextend && nread > 2 &&
- u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
- sp->typecnt + 2 <= TZ_MAX_TYPES) {
- struct state ts;
- register int result;
-
- u.buf[nread - 1] = '\0';
- result = tzparse(&u.buf[1], &ts, FALSE);
- if (result == 0 && ts.typecnt == 2 &&
- sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
- for (i = 0; i < 2; ++i)
- ts.ttis[i].tt_abbrind +=
- sp->charcnt;
- for (i = 0; i < ts.charcnt; ++i)
- sp->chars[sp->charcnt++] =
- ts.chars[i];
- i = 0;
- while (i < ts.timecnt &&
- ts.ats[i] <=
- sp->ats[sp->timecnt - 1])
- ++i;
- while (i < ts.timecnt &&
- sp->timecnt < TZ_MAX_TIMES) {
- sp->ats[sp->timecnt] =
- ts.ats[i];
- sp->types[sp->timecnt] =
- sp->typecnt +
- ts.types[i];
- ++sp->timecnt;
- ++i;
- }
- sp->ttis[sp->typecnt++] = ts.ttis[0];
- sp->ttis[sp->typecnt++] = ts.ttis[1];
- }
- }
- i = 2 * YEARSPERREPEAT;
- sp->goback = sp->goahead = sp->timecnt > i;
- sp->goback &= sp->types[i] == sp->types[0] &&
- differ_by_repeat(sp->ats[i], sp->ats[0]);
- sp->goahead &=
- sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] &&
- differ_by_repeat(sp->ats[sp->timecnt - 1],
- sp->ats[sp->timecnt - 1 - i]);
- return 0;
-}
-
-static const int mon_lengths[2][MONSPERYEAR] = {
- { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
- { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
-};
-
-static const int year_lengths[2] = {
- DAYSPERNYEAR, DAYSPERLYEAR
-};
-
-/*
-** Given a pointer into a time zone string, scan until a character that is not
-** a valid character in a zone name is found. Return a pointer to that
-** character.
-*/
-
-static const char *
-getzname(strp)
-register const char * strp;
-{
- register char c;
-
- while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
- c != '+')
- ++strp;
- return strp;
-}
-
-/*
-** Given a pointer into an extended time zone string, scan until the ending
-** delimiter of the zone name is located. Return a pointer to the delimiter.
-**
-** As with getzname above, the legal character set is actually quite
-** restricted, with other characters producing undefined results.
-** We don't do any checking here; checking is done later in common-case code.
-*/
-
-static const char *
-getqzname(register const char *strp, const int delim)
-{
- register int c;
-
- while ((c = *strp) != '\0' && c != delim)
- ++strp;
- return strp;
-}
-
-/*
-** Given a pointer into a time zone string, extract a number from that string.
-** Check that the number is within a specified range; if it is not, return
-** NULL.
-** Otherwise, return a pointer to the first character not part of the number.
-*/
-
-static const char *
-getnum(strp, nump, min, max)
-register const char * strp;
-int * const nump;
-const int min;
-const int max;
-{
- register char c;
- register int num;
-
- if (strp == NULL || !is_digit(c = *strp))
- return NULL;
- num = 0;
- do {
- num = num * 10 + (c - '0');
- if (num > max)
- return NULL; /* illegal value */
- c = *++strp;
- } while (is_digit(c));
- if (num < min)
- return NULL; /* illegal value */
- *nump = num;
- return strp;
-}
-
-/*
-** Given a pointer into a time zone string, extract a number of seconds,
-** in hh[:mm[:ss]] form, from the string.
-** If any error occurs, return NULL.
-** Otherwise, return a pointer to the first character not part of the number
-** of seconds.
-*/
-
-static const char *
-getsecs(strp, secsp)
-register const char * strp;
-long * const secsp;
-{
- int num;
-
- /*
- ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
- ** "M10.4.6/26", which does not conform to Posix,
- ** but which specifies the equivalent of
- ** ``02:00 on the first Sunday on or after 23 Oct''.
- */
- strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
- if (strp == NULL)
- return NULL;
- *secsp = num * (long) SECSPERHOUR;
- if (*strp == ':') {
- ++strp;
- strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
- if (strp == NULL)
- return NULL;
- *secsp += num * SECSPERMIN;
- if (*strp == ':') {
- ++strp;
- /* `SECSPERMIN' allows for leap seconds. */
- strp = getnum(strp, &num, 0, SECSPERMIN);
- if (strp == NULL)
- return NULL;
- *secsp += num;
- }
- }
- return strp;
-}
-
-/*
-** Given a pointer into a time zone string, extract an offset, in
-** [+-]hh[:mm[:ss]] form, from the string.
-** If any error occurs, return NULL.
-** Otherwise, return a pointer to the first character not part of the time.
-*/
-
-static const char *
-getoffset(strp, offsetp)
-register const char * strp;
-long * const offsetp;
-{
- register int neg = 0;
-
- if (*strp == '-') {
- neg = 1;
- ++strp;
- } else if (*strp == '+')
- ++strp;
- strp = getsecs(strp, offsetp);
- if (strp == NULL)
- return NULL; /* illegal time */
- if (neg)
- *offsetp = -*offsetp;
- return strp;
-}
-
-/*
-** Given a pointer into a time zone string, extract a rule in the form
-** date[/time]. See POSIX section 8 for the format of "date" and "time".
-** If a valid rule is not found, return NULL.
-** Otherwise, return a pointer to the first character not part of the rule.
-*/
-
-static const char *
-getrule(strp, rulep)
-const char * strp;
-register struct rule * const rulep;
-{
- if (*strp == 'J') {
- /*
- ** Julian day.
- */
- rulep->r_type = JULIAN_DAY;
- ++strp;
- strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
- } else if (*strp == 'M') {
- /*
- ** Month, week, day.
- */
- rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
- ++strp;
- strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
- if (strp == NULL)
- return NULL;
- if (*strp++ != '.')
- return NULL;
- strp = getnum(strp, &rulep->r_week, 1, 5);
- if (strp == NULL)
- return NULL;
- if (*strp++ != '.')
- return NULL;
- strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
- } else if (is_digit(*strp)) {
- /*
- ** Day of year.
- */
- rulep->r_type = DAY_OF_YEAR;
- strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
- } else return NULL; /* invalid format */
- if (strp == NULL)
- return NULL;
- if (*strp == '/') {
- /*
- ** Time specified.
- */
- ++strp;
- strp = getsecs(strp, &rulep->r_time);
- } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
- return strp;
-}
-
-/*
-** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
-** year, a rule, and the offset from UTC at the time that rule takes effect,
-** calculate the Epoch-relative time that rule takes effect.
-*/
-
-static time_t
-transtime(janfirst, year, rulep, offset)
-const time_t janfirst;
-const int year;
-register const struct rule * const rulep;
-const long offset;
-{
- register int leapyear;
- register time_t value;
- register int i;
- int d, m1, yy0, yy1, yy2, dow;
-
- INITIALIZE(value);
- leapyear = isleap(year);
- switch (rulep->r_type) {
-
- case JULIAN_DAY:
- /*
- ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
- ** years.
- ** In non-leap years, or if the day number is 59 or less, just
- ** add SECSPERDAY times the day number-1 to the time of
- ** January 1, midnight, to get the day.
- */
- value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
- if (leapyear && rulep->r_day >= 60)
- value += SECSPERDAY;
- break;
-
- case DAY_OF_YEAR:
- /*
- ** n - day of year.
- ** Just add SECSPERDAY times the day number to the time of
- ** January 1, midnight, to get the day.
- */
- value = janfirst + rulep->r_day * SECSPERDAY;
- break;
-
- case MONTH_NTH_DAY_OF_WEEK:
- /*
- ** Mm.n.d - nth "dth day" of month m.
- */
- value = janfirst;
- for (i = 0; i < rulep->r_mon - 1; ++i)
- value += mon_lengths[leapyear][i] * SECSPERDAY;
-
- /*
- ** Use Zeller's Congruence to get day-of-week of first day of
- ** month.
- */
- m1 = (rulep->r_mon + 9) % 12 + 1;
- yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
- yy1 = yy0 / 100;
- yy2 = yy0 % 100;
- dow = ((26 * m1 - 2) / 10 +
- 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
- if (dow < 0)
- dow += DAYSPERWEEK;
-
- /*
- ** "dow" is the day-of-week of the first day of the month. Get
- ** the day-of-month (zero-origin) of the first "dow" day of the
- ** month.
- */
- d = rulep->r_day - dow;
- if (d < 0)
- d += DAYSPERWEEK;
- for (i = 1; i < rulep->r_week; ++i) {
- if (d + DAYSPERWEEK >=
- mon_lengths[leapyear][rulep->r_mon - 1])
- break;
- d += DAYSPERWEEK;
- }
-
- /*
- ** "d" is the day-of-month (zero-origin) of the day we want.
- */
- value += d * SECSPERDAY;
- break;
- }
-
- /*
- ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
- ** question. To get the Epoch-relative time of the specified local
- ** time on that day, add the transition time and the current offset
- ** from UTC.
- */
- return value + rulep->r_time + offset;
-}
-
-/*
-** Given a POSIX section 8-style TZ string, fill in the rule tables as
-** appropriate.
-*/
-
-static int
-tzparse(name, sp, lastditch)
-const char * name;
-register struct state * const sp;
-const int lastditch;
-{
- const char * stdname;
- const char * dstname;
- size_t stdlen;
- size_t dstlen;
- long stdoffset;
- long dstoffset;
- register time_t * atp;
- register unsigned char * typep;
- register char * cp;
- register int load_result;
-
- INITIALIZE(dstname);
- stdname = name;
- if (lastditch) {
- stdlen = strlen(name); /* length of standard zone name */
- name += stdlen;
- if (stdlen >= sizeof sp->chars)
- stdlen = (sizeof sp->chars) - 1;
- stdoffset = 0;
- } else {
- if (*name == '<') {
- name++;
- stdname = name;
- name = getqzname(name, '>');
- if (*name != '>')
- return (-1);
- stdlen = name - stdname;
- name++;
- } else {
- name = getzname(name);
- stdlen = name - stdname;
- }
- if (*name == '\0')
- return -1;
- name = getoffset(name, &stdoffset);
- if (name == NULL)
- return -1;
- }
- load_result = tzload(TZDEFRULES, sp, FALSE);
- if (load_result != 0)
- sp->leapcnt = 0; /* so, we're off a little */
- sp->timecnt = 0;
- if (*name != '\0') {
- if (*name == '<') {
- dstname = ++name;
- name = getqzname(name, '>');
- if (*name != '>')
- return -1;
- dstlen = name - dstname;
- name++;
- } else {
- dstname = name;
- name = getzname(name);
- dstlen = name - dstname; /* length of DST zone name */
- }
- if (*name != '\0' && *name != ',' && *name != ';') {
- name = getoffset(name, &dstoffset);
- if (name == NULL)
- return -1;
- } else dstoffset = stdoffset - SECSPERHOUR;
- if (*name == '\0' && load_result != 0)
- name = TZDEFRULESTRING;
- if (*name == ',' || *name == ';') {
- struct rule start;
- struct rule end;
- register int year;
- register time_t janfirst;
- time_t starttime;
- time_t endtime;
-
- ++name;
- if ((name = getrule(name, &start)) == NULL)
- return -1;
- if (*name++ != ',')
- return -1;
- if ((name = getrule(name, &end)) == NULL)
- return -1;
- if (*name != '\0')
- return -1;
- sp->typecnt = 2; /* standard time and DST */
- /*
- ** Two transitions per year, from EPOCH_YEAR forward.
- */
- sp->ttis[0].tt_gmtoff = -dstoffset;
- sp->ttis[0].tt_isdst = 1;
- sp->ttis[0].tt_abbrind = stdlen + 1;
- sp->ttis[1].tt_gmtoff = -stdoffset;
- sp->ttis[1].tt_isdst = 0;
- sp->ttis[1].tt_abbrind = 0;
- atp = sp->ats;
- typep = sp->types;
- janfirst = 0;
- for (year = EPOCH_YEAR;
- sp->timecnt + 2 <= TZ_MAX_TIMES;
- ++year) {
- time_t newfirst;
-
- starttime = transtime(janfirst, year, &start,
- stdoffset);
- endtime = transtime(janfirst, year, &end,
- dstoffset);
- if (starttime > endtime) {
- *atp++ = endtime;
- *typep++ = 1; /* DST ends */
- *atp++ = starttime;
- *typep++ = 0; /* DST begins */
- } else {
- *atp++ = starttime;
- *typep++ = 0; /* DST begins */
- *atp++ = endtime;
- *typep++ = 1; /* DST ends */
- }
- sp->timecnt += 2;
- newfirst = janfirst;
- newfirst += year_lengths[isleap(year)] *
- SECSPERDAY;
- if (newfirst <= janfirst)
- break;
- janfirst = newfirst;
- }
- } else {
- register long theirstdoffset;
- register long theirdstoffset;
- register long theiroffset;
- register int isdst;
- register int i;
- register int j;
-
- if (*name != '\0')
- return -1;
- /*
- ** Initial values of theirstdoffset and theirdstoffset.
- */
- theirstdoffset = 0;
- for (i = 0; i < sp->timecnt; ++i) {
- j = sp->types[i];
- if (!sp->ttis[j].tt_isdst) {
- theirstdoffset =
- -sp->ttis[j].tt_gmtoff;
- break;
- }
- }
- theirdstoffset = 0;
- for (i = 0; i < sp->timecnt; ++i) {
- j = sp->types[i];
- if (sp->ttis[j].tt_isdst) {
- theirdstoffset =
- -sp->ttis[j].tt_gmtoff;
- break;
- }
- }
- /*
- ** Initially we're assumed to be in standard time.
- */
- isdst = FALSE;
- theiroffset = theirstdoffset;
- /*
- ** Now juggle transition times and types
- ** tracking offsets as you do.
- */
- for (i = 0; i < sp->timecnt; ++i) {
- j = sp->types[i];
- sp->types[i] = sp->ttis[j].tt_isdst;
- if (sp->ttis[j].tt_ttisgmt) {
- /* No adjustment to transition time */
- } else {
- /*
- ** If summer time is in effect, and the
- ** transition time was not specified as
- ** standard time, add the summer time
- ** offset to the transition time;
- ** otherwise, add the standard time
- ** offset to the transition time.
- */
- /*
- ** Transitions from DST to DDST
- ** will effectively disappear since
- ** POSIX provides for only one DST
- ** offset.
- */
- if (isdst && !sp->ttis[j].tt_ttisstd) {
- sp->ats[i] += dstoffset -
- theirdstoffset;
- } else {
- sp->ats[i] += stdoffset -
- theirstdoffset;
- }
- }
- theiroffset = -sp->ttis[j].tt_gmtoff;
- if (sp->ttis[j].tt_isdst)
- theirdstoffset = theiroffset;
- else theirstdoffset = theiroffset;
- }
- /*
- ** Finally, fill in ttis.
- ** ttisstd and ttisgmt need not be handled.
- */
- sp->ttis[0].tt_gmtoff = -stdoffset;
- sp->ttis[0].tt_isdst = FALSE;
- sp->ttis[0].tt_abbrind = 0;
- sp->ttis[1].tt_gmtoff = -dstoffset;
- sp->ttis[1].tt_isdst = TRUE;
- sp->ttis[1].tt_abbrind = stdlen + 1;
- sp->typecnt = 2;
- }
- } else {
- dstlen = 0;
- sp->typecnt = 1; /* only standard time */
- sp->timecnt = 0;
- sp->ttis[0].tt_gmtoff = -stdoffset;
- sp->ttis[0].tt_isdst = 0;
- sp->ttis[0].tt_abbrind = 0;
- }
- sp->charcnt = stdlen + 1;
- if (dstlen != 0)
- sp->charcnt += dstlen + 1;
- if ((size_t) sp->charcnt > sizeof sp->chars)
- return -1;
- cp = sp->chars;
- (void) strncpy(cp, stdname, stdlen);
- cp += stdlen;
- *cp++ = '\0';
- if (dstlen != 0) {
- (void) strncpy(cp, dstname, dstlen);
- *(cp + dstlen) = '\0';
- }
- return 0;
-}
-
-static void
-gmtload(sp)
-struct state * const sp;
-{
- if (tzload(gmt, sp, TRUE) != 0)
- (void) tzparse(gmt, sp, TRUE);
-}
-
-/*
-** The easy way to behave "as if no library function calls" localtime
-** is to not call it--so we drop its guts into "localsub", which can be
-** freely called. (And no, the PANS doesn't require the above behavior--
-** but it *is* desirable.)
-**
-** The unused offset argument is for the benefit of mktime variants.
-*/
-
-/*ARGSUSED*/
-static struct tm *
-localsub(timep, offset, tmp, sp)
-const time_t * const timep;
-const long offset;
-struct tm * const tmp;
-struct state * sp;
-{
- register const struct ttinfo * ttisp;
- register int i;
- register struct tm * result;
- const time_t t = *timep;
-
-#ifdef ALL_STATE
- if (sp == NULL)
- return gmtsub(timep, offset, tmp);
-#endif /* defined ALL_STATE */
- if ((sp->goback && t < sp->ats[0]) ||
- (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
- time_t newt = t;
- register time_t seconds;
- register time_t tcycles;
- register int_fast64_t icycles;
-
- if (t < sp->ats[0])
- seconds = sp->ats[0] - t;
- else seconds = t - sp->ats[sp->timecnt - 1];
- --seconds;
- tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
- ++tcycles;
- icycles = tcycles;
- if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
- return NULL;
- seconds = icycles;
- seconds *= YEARSPERREPEAT;
- seconds *= AVGSECSPERYEAR;
- if (t < sp->ats[0])
- newt += seconds;
- else newt -= seconds;
- if (newt < sp->ats[0] ||
- newt > sp->ats[sp->timecnt - 1])
- return NULL; /* "cannot happen" */
- result = localsub(&newt, offset, tmp, sp);
- if (result == tmp) {
- register time_t newy;
-
- newy = tmp->tm_year;
- if (t < sp->ats[0])
- newy -= icycles * YEARSPERREPEAT;
- else newy += icycles * YEARSPERREPEAT;
- tmp->tm_year = newy;
- if (tmp->tm_year != newy)
- return NULL;
- }
- return result;
- }
- if (sp->timecnt == 0 || t < sp->ats[0]) {
- i = 0;
- while (sp->ttis[i].tt_isdst)
- if (++i >= sp->typecnt) {
- i = 0;
- break;
- }
- } else {
- register int lo = 1;
- register int hi = sp->timecnt;
-
- while (lo < hi) {
- register int mid = (lo + hi) >> 1;
-
- if (t < sp->ats[mid])
- hi = mid;
- else lo = mid + 1;
- }
- i = (int) sp->types[lo - 1];
- }
- ttisp = &sp->ttis[i];
- /*
- ** To get (wrong) behavior that's compatible with System V Release 2.0
- ** you'd replace the statement below with
- ** t += ttisp->tt_gmtoff;
- ** timesub(&t, 0L, sp, tmp);
- */
- result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
- tmp->tm_isdst = ttisp->tt_isdst;
-#ifdef HAVE_TM_GMTOFF
- tmp->tm_gmtoff = ttisp->tt_gmtoff;
-#endif
- tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
-#ifdef TM_ZONE
- tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
-#endif /* defined TM_ZONE */
- return result;
-}
-
-
-// ============================================================================
-#if 0
-struct tm *
-localtime(timep)
-const time_t * const timep;
-{
- tzset();
- return localsub(timep, 0L, &tm);
-}
-#endif
-
-/*
-** Re-entrant version of localtime.
-*/
-
-// ============================================================================
-void
-localtime_tz(const time_t * const timep, struct tm * tmp, const char* tz)
-{
- struct state st;
- if (tzload(tz, &st, TRUE) != 0) {
- // not sure what's best here, but for now, we fall back to gmt
- gmtload(&st);
- }
-
- localsub(timep, 0L, tmp, &st);
-}
-
-/*
-** gmtsub is to gmtime as localsub is to localtime.
-*/
-
-static struct tm *
-gmtsub(timep, offset, tmp)
-const time_t * const timep;
-const long offset;
-struct tm * const tmp;
-{
- register struct tm * result;
-
- if (!gmt_is_set) {
- gmt_is_set = TRUE;
-#ifdef ALL_STATE
- gmtptr = (struct state *) malloc(sizeof *gmtptr);
- if (gmtptr != NULL)
-#endif /* defined ALL_STATE */
- gmtload(gmtptr);
- }
- result = timesub(timep, offset, gmtptr, tmp);
-#ifdef TM_ZONE
- /*
- ** Could get fancy here and deliver something such as
- ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
- ** but this is no time for a treasure hunt.
- */
- if (offset != 0)
- tmp->TM_ZONE = wildabbr;
- else {
-#ifdef ALL_STATE
- if (gmtptr == NULL)
- tmp->TM_ZONE = gmt;
- else tmp->TM_ZONE = gmtptr->chars;
-#endif /* defined ALL_STATE */
-#ifndef ALL_STATE
- tmp->TM_ZONE = gmtptr->chars;
-#endif /* State Farm */
- }
-#endif /* defined TM_ZONE */
- return result;
-}
-
-// ============================================================================
-#if 0
-struct tm *
-gmtime(timep)
-const time_t * const timep;
-{
- return gmtsub(timep, 0L, &tm);
-}
-#endif
-
-/*
-* Re-entrant version of gmtime.
-*/
-
-// ============================================================================
-#if 0
-struct tm *
-gmtime_r(timep, tmp)
-const time_t * const timep;
-struct tm * tmp;
-{
- return gmtsub(timep, 0L, tmp);
-}
-#endif
-
-#ifdef STD_INSPIRED
-
-// ============================================================================
-#if 0
-struct tm *
-offtime(timep, offset)
-const time_t * const timep;
-const long offset;
-{
- return gmtsub(timep, offset, &tm);
-}
-#endif
-
-#endif /* defined STD_INSPIRED */
-
-/*
-** Return the number of leap years through the end of the given year
-** where, to make the math easy, the answer for year zero is defined as zero.
-*/
-
-static int
-leaps_thru_end_of(y)
-register const int y;
-{
- return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
- -(leaps_thru_end_of(-(y + 1)) + 1);
-}
-
-static struct tm *
-timesub(timep, offset, sp, tmp)
-const time_t * const timep;
-const long offset;
-register const struct state * const sp;
-register struct tm * const tmp;
-{
- register const struct lsinfo * lp;
- register time_t tdays;
- register int idays; /* unsigned would be so 2003 */
- register long rem;
- int y;
- register const int * ip;
- register long corr;
- register int hit;
- register int i;
-
- corr = 0;
- hit = 0;
-#ifdef ALL_STATE
- i = (sp == NULL) ? 0 : sp->leapcnt;
-#endif /* defined ALL_STATE */
-#ifndef ALL_STATE
- i = sp->leapcnt;
-#endif /* State Farm */
- while (--i >= 0) {
- lp = &sp->lsis[i];
- if (*timep >= lp->ls_trans) {
- if (*timep == lp->ls_trans) {
- hit = ((i == 0 && lp->ls_corr > 0) ||
- lp->ls_corr > sp->lsis[i - 1].ls_corr);
- if (hit)
- while (i > 0 &&
- sp->lsis[i].ls_trans ==
- sp->lsis[i - 1].ls_trans + 1 &&
- sp->lsis[i].ls_corr ==
- sp->lsis[i - 1].ls_corr + 1) {
- ++hit;
- --i;
- }
- }
- corr = lp->ls_corr;
- break;
- }
- }
- y = EPOCH_YEAR;
- tdays = *timep / SECSPERDAY;
- rem = *timep - tdays * SECSPERDAY;
- while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
- int newy;
- register time_t tdelta;
- register int idelta;
- register int leapdays;
-
- tdelta = tdays / DAYSPERLYEAR;
- idelta = tdelta;
- if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
- return NULL;
- if (idelta == 0)
- idelta = (tdays < 0) ? -1 : 1;
- newy = y;
- if (increment_overflow(&newy, idelta))
- return NULL;
- leapdays = leaps_thru_end_of(newy - 1) -
- leaps_thru_end_of(y - 1);
- tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
- tdays -= leapdays;
- y = newy;
- }
- {
- register long seconds;
-
- seconds = tdays * SECSPERDAY + 0.5;
- tdays = seconds / SECSPERDAY;
- rem += seconds - tdays * SECSPERDAY;
- }
- /*
- ** Given the range, we can now fearlessly cast...
- */
- idays = tdays;
- rem += offset - corr;
- while (rem < 0) {
- rem += SECSPERDAY;
- --idays;
- }
- while (rem >= SECSPERDAY) {
- rem -= SECSPERDAY;
- ++idays;
- }
- while (idays < 0) {
- if (increment_overflow(&y, -1))
- return NULL;
- idays += year_lengths[isleap(y)];
- }
- while (idays >= year_lengths[isleap(y)]) {
- idays -= year_lengths[isleap(y)];
- if (increment_overflow(&y, 1))
- return NULL;
- }
- tmp->tm_year = y;
- if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
- return NULL;
- tmp->tm_yday = idays;
- /*
- ** The "extra" mods below avoid overflow problems.
- */
- tmp->tm_wday = EPOCH_WDAY +
- ((y - EPOCH_YEAR) % DAYSPERWEEK) *
- (DAYSPERNYEAR % DAYSPERWEEK) +
- leaps_thru_end_of(y - 1) -
- leaps_thru_end_of(EPOCH_YEAR - 1) +
- idays;
- tmp->tm_wday %= DAYSPERWEEK;
- if (tmp->tm_wday < 0)
- tmp->tm_wday += DAYSPERWEEK;
- tmp->tm_hour = (int) (rem / SECSPERHOUR);
- rem %= SECSPERHOUR;
- tmp->tm_min = (int) (rem / SECSPERMIN);
- /*
- ** A positive leap second requires a special
- ** representation. This uses "... ??:59:60" et seq.
- */
- tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
- ip = mon_lengths[isleap(y)];
- for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
- idays -= ip[tmp->tm_mon];
- tmp->tm_mday = (int) (idays + 1);
- tmp->tm_isdst = 0;
-#ifdef TM_GMTOFF
- tmp->TM_GMTOFF = offset;
-#endif /* defined TM_GMTOFF */
- return tmp;
-}
-
-// ============================================================================
-#if 0
-char *
-ctime(timep)
-const time_t * const timep;
-{
-/*
-** Section 4.12.3.2 of X3.159-1989 requires that
-** The ctime function converts the calendar time pointed to by timer
-** to local time in the form of a string. It is equivalent to
-** asctime(localtime(timer))
-*/
- return asctime(localtime(timep));
-}
-#endif
-
-// ============================================================================
-#if 0
-char *
-ctime_r(timep, buf)
-const time_t * const timep;
-char * buf;
-{
- struct tm mytm;
-
- return asctime_r(localtime_r(timep, &mytm), buf);
-}
-#endif
-
-/*
-** Adapted from code provided by Robert Elz, who writes:
-** The "best" way to do mktime I think is based on an idea of Bob
-** Kridle's (so its said...) from a long time ago.
-** It does a binary search of the time_t space. Since time_t's are
-** just 32 bits, its a max of 32 iterations (even at 64 bits it
-** would still be very reasonable).
-*/
-
-#ifndef WRONG
-#define WRONG (-1)
-#endif /* !defined WRONG */
-
-/*
-** Simplified normalize logic courtesy Paul Eggert.
-*/
-
-static int
-increment_overflow(number, delta)
-int * number;
-int delta;
-{
- int number0;
-
- number0 = *number;
- *number += delta;
- return (*number < number0) != (delta < 0);
-}
-
-static int
-long_increment_overflow(number, delta)
-long * number;
-int delta;
-{
- long number0;
-
- number0 = *number;
- *number += delta;
- return (*number < number0) != (delta < 0);
-}
-
-static int
-normalize_overflow(tensptr, unitsptr, base)
-int * const tensptr;
-int * const unitsptr;
-const int base;
-{
- register int tensdelta;
-
- tensdelta = (*unitsptr >= 0) ?
- (*unitsptr / base) :
- (-1 - (-1 - *unitsptr) / base);
- *unitsptr -= tensdelta * base;
- return increment_overflow(tensptr, tensdelta);
-}
-
-static int
-long_normalize_overflow(tensptr, unitsptr, base)
-long * const tensptr;
-int * const unitsptr;
-const int base;
-{
- register int tensdelta;
-
- tensdelta = (*unitsptr >= 0) ?
- (*unitsptr / base) :
- (-1 - (-1 - *unitsptr) / base);
- *unitsptr -= tensdelta * base;
- return long_increment_overflow(tensptr, tensdelta);
-}
-
-static int
-tmcomp(atmp, btmp)
-register const struct tm * const atmp;
-register const struct tm * const btmp;
-{
- register int result;
-
- if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
- (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
- (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
- (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
- (result = (atmp->tm_min - btmp->tm_min)) == 0)
- result = atmp->tm_sec - btmp->tm_sec;
- return result;
-}
-
-static time_t
-time2sub(tmp, funcp, offset, okayp, do_norm_secs, sp)
-struct tm * const tmp;
-struct tm * (* const funcp) P((const time_t*, long, struct tm*,const struct state *sp));
-const long offset;
-int * const okayp;
-const int do_norm_secs;
-const struct state * sp;
-{
- register int dir;
- register int i, j;
- register int saved_seconds;
- register long li;
- register time_t lo;
- register time_t hi;
- long y;
- time_t newt;
- time_t t;
- struct tm yourtm, mytm;
-
- *okayp = FALSE;
- yourtm = *tmp;
- if (do_norm_secs) {
- if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
- SECSPERMIN))
- return WRONG;
- }
- if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
- return WRONG;
- if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
- return WRONG;
- y = yourtm.tm_year;
- if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
- return WRONG;
- /*
- ** Turn y into an actual year number for now.
- ** It is converted back to an offset from TM_YEAR_BASE later.
- */
- if (long_increment_overflow(&y, TM_YEAR_BASE))
- return WRONG;
- while (yourtm.tm_mday <= 0) {
- if (long_increment_overflow(&y, -1))
- return WRONG;
- li = y + (1 < yourtm.tm_mon);
- yourtm.tm_mday += year_lengths[isleap(li)];
- }
- while (yourtm.tm_mday > DAYSPERLYEAR) {
- li = y + (1 < yourtm.tm_mon);
- yourtm.tm_mday -= year_lengths[isleap(li)];
- if (long_increment_overflow(&y, 1))
- return WRONG;
- }
- for ( ; ; ) {
- i = mon_lengths[isleap(y)][yourtm.tm_mon];
- if (yourtm.tm_mday <= i)
- break;
- yourtm.tm_mday -= i;
- if (++yourtm.tm_mon >= MONSPERYEAR) {
- yourtm.tm_mon = 0;
- if (long_increment_overflow(&y, 1))
- return WRONG;
- }
- }
- if (long_increment_overflow(&y, -TM_YEAR_BASE))
- return WRONG;
- yourtm.tm_year = y;
- if (yourtm.tm_year != y)
- return WRONG;
- if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
- saved_seconds = 0;
- else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
- /*
- ** We can't set tm_sec to 0, because that might push the
- ** time below the minimum representable time.
- ** Set tm_sec to 59 instead.
- ** This assumes that the minimum representable time is
- ** not in the same minute that a leap second was deleted from,
- ** which is a safer assumption than using 58 would be.
- */
- if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
- return WRONG;
- saved_seconds = yourtm.tm_sec;
- yourtm.tm_sec = SECSPERMIN - 1;
- } else {
- saved_seconds = yourtm.tm_sec;
- yourtm.tm_sec = 0;
- }
- /*
- ** Do a binary search (this works whatever time_t's type is).
- */
- if (!TYPE_SIGNED(time_t)) {
- lo = 0;
- hi = lo - 1;
- } else if (!TYPE_INTEGRAL(time_t)) {
- if (sizeof(time_t) > sizeof(float))
- hi = (time_t) DBL_MAX;
- else hi = (time_t) FLT_MAX;
- lo = -hi;
- } else {
- lo = 1;
- for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
- lo *= 2;
- hi = -(lo + 1);
- }
- for ( ; ; ) {
- t = lo / 2 + hi / 2;
- if (t < lo)
- t = lo;
- else if (t > hi)
- t = hi;
- if ((*funcp)(&t, offset, &mytm, sp) == NULL) {
- /*
- ** Assume that t is too extreme to be represented in
- ** a struct tm; arrange things so that it is less
- ** extreme on the next pass.
- */
- dir = (t > 0) ? 1 : -1;
- } else dir = tmcomp(&mytm, &yourtm);
- if (dir != 0) {
- if (t == lo) {
- ++t;
- if (t <= lo)
- return WRONG;
- ++lo;
- } else if (t == hi) {
- --t;
- if (t >= hi)
- return WRONG;
- --hi;
- }
- if (lo > hi)
- return WRONG;
- if (dir > 0)
- hi = t;
- else lo = t;
- continue;
- }
- if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
- break;
- /*
- ** Right time, wrong type.
- ** Hunt for right time, right type.
- ** It's okay to guess wrong since the guess
- ** gets checked.
- */
- /*
- ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
- */
-#ifdef ALL_STATE
- if (sp == NULL)
- return WRONG;
-#endif /* defined ALL_STATE */
- for (i = sp->typecnt - 1; i >= 0; --i) {
- if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
- continue;
- for (j = sp->typecnt - 1; j >= 0; --j) {
- if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
- continue;
- newt = t + sp->ttis[j].tt_gmtoff -
- sp->ttis[i].tt_gmtoff;
- if ((*funcp)(&newt, offset, &mytm, sp) == NULL)
- continue;
- if (tmcomp(&mytm, &yourtm) != 0)
- continue;
- if (mytm.tm_isdst != yourtm.tm_isdst)
- continue;
- /*
- ** We have a match.
- */
- t = newt;
- goto label;
- }
- }
- return WRONG;
- }
-label:
- newt = t + saved_seconds;
- if ((newt < t) != (saved_seconds < 0))
- return WRONG;
- t = newt;
- if ((*funcp)(&t, offset, tmp, sp))
- *okayp = TRUE;
- return t;
-}
-
-static time_t
-time2(tmp, funcp, offset, okayp, sp)
-struct tm * const tmp;
-struct tm * (* const funcp) P((const time_t*, long, struct tm*,
- const struct state* sp));
-const long offset;
-int * const okayp;
-const struct state * sp;
-{
- time_t t;
-
- /*
- ** First try without normalization of seconds
- ** (in case tm_sec contains a value associated with a leap second).
- ** If that fails, try with normalization of seconds.
- */
- t = time2sub(tmp, funcp, offset, okayp, FALSE, sp);
- return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp);
-}
-
-static time_t
-time1(tmp, funcp, offset, sp)
-struct tm * const tmp;
-struct tm * (* const funcp) P((const time_t *, long, struct tm *, const struct state* sp));
-const long offset;
-const struct state * sp;
-{
- register time_t t;
- register int samei, otheri;
- register int sameind, otherind;
- register int i;
- register int nseen;
- int seen[TZ_MAX_TYPES];
- int types[TZ_MAX_TYPES];
- int okay;
-
- if (tmp->tm_isdst > 1)
- tmp->tm_isdst = 1;
- t = time2(tmp, funcp, offset, &okay, sp);
-#define PCTS 1
-#ifdef PCTS
- /*
- ** PCTS code courtesy Grant Sullivan.
- */
- if (okay)
- return t;
- if (tmp->tm_isdst < 0)
- tmp->tm_isdst = 0; /* reset to std and try again */
-#endif /* defined PCTS */
-#ifndef PCTS
- if (okay || tmp->tm_isdst < 0)
- return t;
-#endif /* !defined PCTS */
- /*
- ** We're supposed to assume that somebody took a time of one type
- ** and did some math on it that yielded a "struct tm" that's bad.
- ** We try to divine the type they started from and adjust to the
- ** type they need.
- */
- /*
- ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
- */
-#ifdef ALL_STATE
- if (sp == NULL)
- return WRONG;
-#endif /* defined ALL_STATE */
- for (i = 0; i < sp->typecnt; ++i)
- seen[i] = FALSE;
- nseen = 0;
- for (i = sp->timecnt - 1; i >= 0; --i)
- if (!seen[sp->types[i]]) {
- seen[sp->types[i]] = TRUE;
- types[nseen++] = sp->types[i];
- }
- for (sameind = 0; sameind < nseen; ++sameind) {
- samei = types[sameind];
- if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
- continue;
- for (otherind = 0; otherind < nseen; ++otherind) {
- otheri = types[otherind];
- if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
- continue;
- tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
- sp->ttis[samei].tt_gmtoff;
- tmp->tm_isdst = !tmp->tm_isdst;
- t = time2(tmp, funcp, offset, &okay, sp);
- if (okay)
- return t;
- tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
- sp->ttis[samei].tt_gmtoff;
- tmp->tm_isdst = !tmp->tm_isdst;
- }
- }
- return WRONG;
-}
-
-// ============================================================================
-time_t
-mktime_tz(struct tm * const tmp, char const * tz)
-{
- struct state st;
- if (tzload(tz, &st, TRUE) != 0) {
- // not sure what's best here, but for now, we fall back to gmt
- gmtload(&st);
- }
- return time1(tmp, localsub, 0L, &st);
-}
diff --git a/libcutils/uio.c b/libcutils/uio.c
deleted file mode 100644
index baa8051bc..000000000
--- a/libcutils/uio.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2007 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 HAVE_SYS_UIO_H
-
-#include <cutils/uio.h>
-#include <unistd.h>
-
-int readv( int fd, struct iovec* vecs, int count )
-{
- int total = 0;
-
- for ( ; count > 0; count--, vecs++ ) {
- const char* buf = vecs->iov_base;
- int len = vecs->iov_len;
-
- while (len > 0) {
- int ret = read( fd, buf, len );
- if (ret < 0) {
- if (total == 0)
- total = -1;
- goto Exit;
- }
- if (ret == 0)
- goto Exit;
-
- total += ret;
- buf += ret;
- len -= ret;
- }
- }
-Exit:
- return total;
-}
-
-int writev( int fd, const struct iovec* vecs, int count )
-{
- int total = 0;
-
- for ( ; count > 0; count--, vecs++ ) {
- const char* buf = (const char*)vecs->iov_base;
- int len = (int)vecs->iov_len;
-
- while (len > 0) {
- int ret = write( fd, buf, len );
- if (ret < 0) {
- if (total == 0)
- total = -1;
- goto Exit;
- }
- if (ret == 0)
- goto Exit;
-
- total += ret;
- buf += ret;
- len -= ret;
- }
- }
-Exit:
- return total;
-}
-
-#endif /* !HAVE_SYS_UIO_H */
diff --git a/libcutils/zygote.c b/libcutils/zygote.c
deleted file mode 100644
index aa060c05a..000000000
--- a/libcutils/zygote.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-#define LOG_TAG "Zygote"
-
-#include <cutils/sockets.h>
-#include <cutils/zygote.h>
-#include <cutils/log.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <time.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <arpa/inet.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#define ZYGOTE_SOCKET "zygote"
-
-#define ZYGOTE_RETRY_COUNT 1000
-#define ZYGOTE_RETRY_MILLIS 500
-
-static void replace_nl(char *str);
-
-/*
- * If sendStdio is non-zero, the current process's stdio file descriptors
- * will be sent and inherited by the spawned process.
- */
-static int send_request(int fd, int sendStdio, int argc, const char **argv)
-{
-#ifndef HAVE_ANDROID_OS
- // not supported on simulator targets
- //LOGE("zygote_* not supported on simulator targets");
- return -1;
-#else /* HAVE_ANDROID_OS */
- uint32_t pid;
- int i;
- struct iovec ivs[2];
- struct msghdr msg;
- char argc_buffer[12];
- const char *newline_string = "\n";
- struct cmsghdr *cmsg;
- char msgbuf[CMSG_SPACE(sizeof(int) * 3)];
- int *cmsg_payload;
- ssize_t ret;
-
- memset(&msg, 0, sizeof(msg));
- memset(&ivs, 0, sizeof(ivs));
-
- // First line is arg count
- snprintf(argc_buffer, sizeof(argc_buffer), "%d\n", argc);
-
- ivs[0].iov_base = argc_buffer;
- ivs[0].iov_len = strlen(argc_buffer);
-
- msg.msg_iov = ivs;
- msg.msg_iovlen = 1;
-
- if (sendStdio != 0) {
- // Pass the file descriptors with the first write
- msg.msg_control = msgbuf;
- msg.msg_controllen = sizeof msgbuf;
-
- cmsg = CMSG_FIRSTHDR(&msg);
-
- cmsg->cmsg_len = CMSG_LEN(3 * sizeof(int));
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
-
- cmsg_payload = (int *)CMSG_DATA(cmsg);
- cmsg_payload[0] = STDIN_FILENO;
- cmsg_payload[1] = STDOUT_FILENO;
- cmsg_payload[2] = STDERR_FILENO;
- }
-
- do {
- ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
- } while (ret < 0 && errno == EINTR);
-
- if (ret < 0) {
- return -1;
- }
-
- // Only send the fd's once
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
-
- // replace any newlines with spaces and send the args
- for (i = 0; i < argc; i++) {
- char *tofree = NULL;
- const char *toprint;
-
- toprint = argv[i];
-
- if (strchr(toprint, '\n') != NULL) {
- tofree = strdup(toprint);
- toprint = tofree;
- replace_nl(tofree);
- }
-
- ivs[0].iov_base = (char *)toprint;
- ivs[0].iov_len = strlen(toprint);
- ivs[1].iov_base = (char *)newline_string;
- ivs[1].iov_len = 1;
-
- msg.msg_iovlen = 2;
-
- do {
- ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
- } while (ret < 0 && errno == EINTR);
-
- if (tofree != NULL) {
- free(tofree);
- }
-
- if (ret < 0) {
- return -1;
- }
- }
-
- // Read the pid, as a 4-byte network-order integer
-
- ivs[0].iov_base = &pid;
- ivs[0].iov_len = sizeof(pid);
- msg.msg_iovlen = 1;
-
- do {
- do {
- ret = recvmsg(fd, &msg, MSG_NOSIGNAL | MSG_WAITALL);
- } while (ret < 0 && errno == EINTR);
-
- if (ret < 0) {
- return -1;
- }
-
- ivs[0].iov_len -= ret;
- ivs[0].iov_base += ret;
- } while (ivs[0].iov_len > 0);
-
- pid = ntohl(pid);
-
- return pid;
-#endif /* HAVE_ANDROID_OS */
-}
-
-int zygote_run_wait(int argc, const char **argv, void (*post_run_func)(int))
-{
- int fd;
- int pid;
- int err;
- const char *newargv[argc + 1];
-
- fd = socket_local_client(ZYGOTE_SOCKET,
- ANDROID_SOCKET_NAMESPACE_RESERVED, AF_LOCAL);
-
- if (fd < 0) {
- return -1;
- }
-
- // The command socket is passed to the peer as close-on-exec
- // and will close when the peer dies
- newargv[0] = "--peer-wait";
- memcpy(newargv + 1, argv, argc * sizeof(*argv));
-
- pid = send_request(fd, 1, argc + 1, newargv);
-
- if (pid > 0 && post_run_func != NULL) {
- post_run_func(pid);
- }
-
- // Wait for socket to close
- do {
- int dummy;
- err = read(fd, &dummy, sizeof(dummy));
- } while ((err < 0 && errno == EINTR) || err != 0);
-
- do {
- err = close(fd);
- } while (err < 0 && errno == EINTR);
-
- return 0;
-}
-
-/**
- * Spawns a new dalvik instance via the Zygote process. The non-zygote
- * arguments are passed to com.android.internal.os.RuntimeInit(). The
- * first non-option argument should be a class name in the system class path.
- *
- * The arg list may start with zygote params such as --set-uid.
- *
- * If sendStdio is non-zero, the current process's stdio file descriptors
- * will be sent and inherited by the spawned process.
- *
- * The pid of the child process is returned, or -1 if an error was
- * encountered.
- *
- * zygote_run_oneshot waits up to ZYGOTE_RETRY_COUNT *
- * ZYGOTE_RETRY_MILLIS for the zygote socket to be available.
- */
-int zygote_run_oneshot(int sendStdio, int argc, const char **argv)
-{
- int fd = -1;
- int err;
- int i;
- int retries;
- int pid;
- const char **newargv = argv;
- const int newargc = argc;
-
- for (retries = 0; (fd < 0) && (retries < ZYGOTE_RETRY_COUNT); retries++) {
- if (retries > 0) {
- struct timespec ts;
-
- memset(&ts, 0, sizeof(ts));
- ts.tv_nsec = ZYGOTE_RETRY_MILLIS * 1000 * 1000;
-
- do {
- err = nanosleep (&ts, &ts);
- } while (err < 0 && errno == EINTR);
- }
- fd = socket_local_client(ZYGOTE_SOCKET, AF_LOCAL,
- ANDROID_SOCKET_NAMESPACE_RESERVED);
- }
-
- if (fd < 0) {
- return -1;
- }
-
- pid = send_request(fd, 0, newargc, newargv);
-
- do {
- err = close(fd);
- } while (err < 0 && errno == EINTR);
-
- return pid;
-}
-
-/**
- * Replaces all occurrances of newline with space.
- */
-static void replace_nl(char *str)
-{
- for(; *str; str++) {
- if (*str == '\n') {
- *str = ' ';
- }
- }
-}
-
-
-