diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:29:04 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:29:04 -0800 |
commit | e54eebbf1a908d65ee8cf80bab62821c05666d70 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /libcutils | |
parent | a1e1c1b106423de09bc918502e7a51d4ffe5a4ae (diff) | |
download | system_core-e54eebbf1a908d65ee8cf80bab62821c05666d70.tar.gz system_core-e54eebbf1a908d65ee8cf80bab62821c05666d70.tar.bz2 system_core-e54eebbf1a908d65ee8cf80bab62821c05666d70.zip |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'libcutils')
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 = ¤t->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 = ¤t->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 = ¤t->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 = ' '; - } - } -} - - - |