From 8e9aeb9053695a14539653093937158d15385ca6 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 10 Nov 2017 10:22:07 -0800 Subject: Move libcutils source to C++. Just the minimial changes to get this to actually build, because otherwise we always bog down trying to rewrite everything (when the real answer is usually "stop using libcutils, it's awful"). This doesn't move a handful of files: two are basically just BSD libc source, a couple have outstanding code reviews, and one can be deleted (but I'll do that in a separate change). I'm also skipping the presubmit hooks because otherwise clang-format wants to reformat everything. I'll follow up with that... Bug: N/A Test: builds Change-Id: I06403f465b67c8e493bad466dd76b1151eed5993 --- libcutils/Android.bp | 48 ++-- libcutils/android_get_control_file.cpp | 5 +- libcutils/android_reboot.c | 51 ---- libcutils/android_reboot.cpp | 53 ++++ libcutils/ashmem-dev.c | 225 --------------- libcutils/ashmem-dev.cpp | 227 +++++++++++++++ libcutils/ashmem-host.c | 92 ------ libcutils/ashmem-host.cpp | 93 ++++++ libcutils/canned_fs_config.c | 129 --------- libcutils/canned_fs_config.cpp | 129 +++++++++ libcutils/config_utils.c | 329 --------------------- libcutils/config_utils.cpp | 328 +++++++++++++++++++++ libcutils/fs.c | 274 ------------------ libcutils/fs.cpp | 276 ++++++++++++++++++ libcutils/fs_config.cpp | 3 +- libcutils/hashmap.c | 358 ----------------------- libcutils/hashmap.cpp | 359 +++++++++++++++++++++++ libcutils/include/cutils/android_reboot.h | 1 + libcutils/include/cutils/partition_utils.h | 2 + libcutils/include/cutils/record_stream.h | 1 + libcutils/include/private/canned_fs_config.h | 4 + libcutils/include/private/fs_config.h | 1 + libcutils/iosched_policy.c | 59 ---- libcutils/iosched_policy.cpp | 59 ++++ libcutils/klog.cpp | 3 +- libcutils/load_file.c | 51 ---- libcutils/load_file.cpp | 53 ++++ libcutils/native_handle.c | 95 ------ libcutils/native_handle.cpp | 95 ++++++ libcutils/partition_utils.c | 68 ----- libcutils/partition_utils.cpp | 70 +++++ libcutils/properties.cpp | 3 +- libcutils/qtaguid.cpp | 3 +- libcutils/record_stream.c | 186 ------------ libcutils/record_stream.cpp | 187 ++++++++++++ libcutils/sched_policy.cpp | 3 +- libcutils/socket_inaddr_any_server_unix.c | 66 ----- libcutils/socket_inaddr_any_server_unix.cpp | 66 +++++ libcutils/socket_inaddr_any_server_windows.c | 79 ----- libcutils/socket_inaddr_any_server_windows.cpp | 79 +++++ libcutils/socket_local_client_unix.c | 168 ----------- libcutils/socket_local_client_unix.cpp | 168 +++++++++++ libcutils/socket_local_server_unix.c | 126 -------- libcutils/socket_local_server_unix.cpp | 126 ++++++++ libcutils/socket_network_client_unix.c | 125 -------- libcutils/socket_network_client_unix.cpp | 125 ++++++++ libcutils/socket_network_client_windows.c | 69 ----- libcutils/socket_network_client_windows.cpp | 69 +++++ libcutils/sockets_unix.cpp | 3 +- libcutils/sockets_windows.cpp | 2 +- libcutils/str_parms.c | 382 ------------------------- libcutils/str_parms.cpp | 376 ++++++++++++++++++++++++ libcutils/strdup16to8.c | 171 ----------- libcutils/strdup16to8.cpp | 168 +++++++++++ libcutils/strdup8to16.c | 214 -------------- libcutils/strdup8to16.cpp | 215 ++++++++++++++ libcutils/tests/trace-dev_test.cpp | 2 +- libcutils/threads.c | 111 ------- libcutils/threads.cpp | 111 +++++++ libcutils/trace-container.c | 231 --------------- libcutils/trace-container.cpp | 233 +++++++++++++++ libcutils/trace-dev.c | 77 ----- libcutils/trace-dev.cpp | 79 +++++ libcutils/trace-host.c | 36 --- libcutils/trace-host.cpp | 36 +++ 65 files changed, 3830 insertions(+), 3806 deletions(-) delete mode 100644 libcutils/android_reboot.c create mode 100644 libcutils/android_reboot.cpp delete mode 100644 libcutils/ashmem-dev.c create mode 100644 libcutils/ashmem-dev.cpp delete mode 100644 libcutils/ashmem-host.c create mode 100644 libcutils/ashmem-host.cpp delete mode 100644 libcutils/canned_fs_config.c create mode 100644 libcutils/canned_fs_config.cpp delete mode 100644 libcutils/config_utils.c create mode 100644 libcutils/config_utils.cpp delete mode 100644 libcutils/fs.c create mode 100644 libcutils/fs.cpp delete mode 100644 libcutils/hashmap.c create mode 100644 libcutils/hashmap.cpp delete mode 100644 libcutils/iosched_policy.c create mode 100644 libcutils/iosched_policy.cpp delete mode 100644 libcutils/load_file.c create mode 100644 libcutils/load_file.cpp delete mode 100644 libcutils/native_handle.c create mode 100644 libcutils/native_handle.cpp delete mode 100644 libcutils/partition_utils.c create mode 100644 libcutils/partition_utils.cpp delete mode 100644 libcutils/record_stream.c create mode 100644 libcutils/record_stream.cpp delete mode 100644 libcutils/socket_inaddr_any_server_unix.c create mode 100644 libcutils/socket_inaddr_any_server_unix.cpp delete mode 100644 libcutils/socket_inaddr_any_server_windows.c create mode 100644 libcutils/socket_inaddr_any_server_windows.cpp delete mode 100644 libcutils/socket_local_client_unix.c create mode 100644 libcutils/socket_local_client_unix.cpp delete mode 100644 libcutils/socket_local_server_unix.c create mode 100644 libcutils/socket_local_server_unix.cpp delete mode 100644 libcutils/socket_network_client_unix.c create mode 100644 libcutils/socket_network_client_unix.cpp delete mode 100644 libcutils/socket_network_client_windows.c create mode 100644 libcutils/socket_network_client_windows.cpp delete mode 100644 libcutils/str_parms.c create mode 100644 libcutils/str_parms.cpp delete mode 100644 libcutils/strdup16to8.c create mode 100644 libcutils/strdup16to8.cpp delete mode 100644 libcutils/strdup8to16.c create mode 100644 libcutils/strdup8to16.cpp delete mode 100644 libcutils/threads.c create mode 100644 libcutils/threads.cpp delete mode 100644 libcutils/trace-container.c create mode 100644 libcutils/trace-container.cpp delete mode 100644 libcutils/trace-dev.c create mode 100644 libcutils/trace-dev.cpp delete mode 100644 libcutils/trace-host.c create mode 100644 libcutils/trace-host.cpp diff --git a/libcutils/Android.bp b/libcutils/Android.bp index 8fb3a52d7..a21d1caab 100644 --- a/libcutils/Android.bp +++ b/libcutils/Android.bp @@ -19,14 +19,14 @@ // which are also hard or even impossible to port to native Win32 libcutils_nonwindows_sources = [ "android_get_control_file.cpp", - "fs.c", + "fs.cpp", "multiuser.c", - "socket_inaddr_any_server_unix.c", - "socket_local_client_unix.c", - "socket_local_server_unix.c", - "socket_network_client_unix.c", + "socket_inaddr_any_server_unix.cpp", + "socket_local_client_unix.cpp", + "socket_local_server_unix.cpp", + "socket_network_client_unix.cpp", "sockets_unix.cpp", - "str_parms.c", + "str_parms.cpp", ] cc_library_headers { @@ -56,21 +56,21 @@ cc_library { }, host_supported: true, srcs: [ - "config_utils.c", + "config_utils.cpp", "fs_config.cpp", - "canned_fs_config.c", - "hashmap.c", - "iosched_policy.c", - "load_file.c", - "native_handle.c", + "canned_fs_config.cpp", + "hashmap.cpp", + "iosched_policy.cpp", + "load_file.cpp", + "native_handle.cpp", "open_memstream.c", - "record_stream.c", + "record_stream.cpp", "sched_policy.cpp", "sockets.cpp", - "strdup16to8.c", - "strdup8to16.c", + "strdup16to8.cpp", + "strdup8to16.cpp", "strlcpy.c", - "threads.c", + "threads.cpp", ], target: { @@ -83,14 +83,14 @@ cc_library { }, not_windows: { srcs: libcutils_nonwindows_sources + [ - "ashmem-host.c", - "trace-host.c", + "ashmem-host.cpp", + "trace-host.cpp", ], }, windows: { srcs: [ - "socket_inaddr_any_server_windows.c", - "socket_network_client_windows.c", + "socket_inaddr_any_server_windows.cpp", + "socket_network_client_windows.cpp", "sockets_windows.cpp", ], @@ -105,13 +105,13 @@ cc_library { android: { srcs: libcutils_nonwindows_sources + [ - "android_reboot.c", - "ashmem-dev.c", + "android_reboot.cpp", + "ashmem-dev.cpp", "klog.cpp", - "partition_utils.c", + "partition_utils.cpp", "properties.cpp", "qtaguid.cpp", - "trace-dev.c", + "trace-dev.cpp", "uevent.cpp", ], }, diff --git a/libcutils/android_get_control_file.cpp b/libcutils/android_get_control_file.cpp index 780d9f136..d8121f5cd 100644 --- a/libcutils/android_get_control_file.cpp +++ b/libcutils/android_get_control_file.cpp @@ -25,6 +25,9 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ + +#include + #include #include #include @@ -36,8 +39,6 @@ #include #include -#include - #include "android_get_control_env.h" #ifndef TEMP_FAILURE_RETRY diff --git a/libcutils/android_reboot.c b/libcutils/android_reboot.c deleted file mode 100644 index 996d89d9b..000000000 --- a/libcutils/android_reboot.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2011, 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 -#include - -#include -#include - -#define TAG "android_reboot" - -int android_reboot(int cmd, int flags __unused, const char* arg) { - int ret; - const char* restart_cmd = NULL; - char* prop_value; - - switch (cmd) { - case ANDROID_RB_RESTART: // deprecated - case ANDROID_RB_RESTART2: - restart_cmd = "reboot"; - break; - case ANDROID_RB_POWEROFF: - restart_cmd = "shutdown"; - break; - case ANDROID_RB_THERMOFF: - restart_cmd = "shutdown,thermal"; - break; - } - if (!restart_cmd) return -1; - if (arg && arg[0]) { - ret = asprintf(&prop_value, "%s,%s", restart_cmd, arg); - } else { - ret = asprintf(&prop_value, "%s", restart_cmd); - } - if (ret < 0) return -1; - ret = property_set(ANDROID_RB_PROPERTY, prop_value); - free(prop_value); - return ret; -} diff --git a/libcutils/android_reboot.cpp b/libcutils/android_reboot.cpp new file mode 100644 index 000000000..5e864d442 --- /dev/null +++ b/libcutils/android_reboot.cpp @@ -0,0 +1,53 @@ +/* + * Copyright 2011, 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 + +#include +#include + +#include + +#define TAG "android_reboot" + +int android_reboot(int cmd, int flags __unused, const char* arg) { + int ret; + const char* restart_cmd = NULL; + char* prop_value; + + switch (static_cast(cmd)) { + case ANDROID_RB_RESTART: // deprecated + case ANDROID_RB_RESTART2: + restart_cmd = "reboot"; + break; + case ANDROID_RB_POWEROFF: + restart_cmd = "shutdown"; + break; + case ANDROID_RB_THERMOFF: + restart_cmd = "shutdown,thermal"; + break; + } + if (!restart_cmd) return -1; + if (arg && arg[0]) { + ret = asprintf(&prop_value, "%s,%s", restart_cmd, arg); + } else { + ret = asprintf(&prop_value, "%s", restart_cmd); + } + if (ret < 0) return -1; + ret = property_set(ANDROID_RB_PROPERTY, prop_value); + free(prop_value); + return ret; +} diff --git a/libcutils/ashmem-dev.c b/libcutils/ashmem-dev.c deleted file mode 100644 index 95f2259ec..000000000 --- a/libcutils/ashmem-dev.c +++ /dev/null @@ -1,225 +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. - */ -#define LOG_TAG "ashmem" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define ASHMEM_DEVICE "/dev/ashmem" - -/* ashmem identity */ -static dev_t __ashmem_rdev; -/* - * If we trigger a signal handler in the middle of locked activity and the - * signal handler calls ashmem, we could get into a deadlock state. - */ -static pthread_mutex_t __ashmem_lock = PTHREAD_MUTEX_INITIALIZER; - -/* logistics of getting file descriptor for ashmem */ -static int __ashmem_open_locked() -{ - int ret; - struct stat st; - - int fd = TEMP_FAILURE_RETRY(open(ASHMEM_DEVICE, O_RDWR | O_CLOEXEC)); - if (fd < 0) { - return fd; - } - - ret = TEMP_FAILURE_RETRY(fstat(fd, &st)); - if (ret < 0) { - int save_errno = errno; - close(fd); - errno = save_errno; - return ret; - } - if (!S_ISCHR(st.st_mode) || !st.st_rdev) { - close(fd); - errno = ENOTTY; - return -1; - } - - __ashmem_rdev = st.st_rdev; - return fd; -} - -static int __ashmem_open() -{ - int fd; - - pthread_mutex_lock(&__ashmem_lock); - fd = __ashmem_open_locked(); - pthread_mutex_unlock(&__ashmem_lock); - - return fd; -} - -/* Make sure file descriptor references ashmem, negative number means false */ -static int __ashmem_is_ashmem(int fd, int fatal) -{ - dev_t rdev; - struct stat st; - - if (TEMP_FAILURE_RETRY(fstat(fd, &st)) < 0) { - return -1; - } - - rdev = 0; /* Too much complexity to sniff __ashmem_rdev */ - if (S_ISCHR(st.st_mode) && st.st_rdev) { - pthread_mutex_lock(&__ashmem_lock); - rdev = __ashmem_rdev; - if (rdev) { - pthread_mutex_unlock(&__ashmem_lock); - } else { - int fd = __ashmem_open_locked(); - if (fd < 0) { - pthread_mutex_unlock(&__ashmem_lock); - return -1; - } - rdev = __ashmem_rdev; - pthread_mutex_unlock(&__ashmem_lock); - - close(fd); - } - - if (st.st_rdev == rdev) { - return 0; - } - } - - if (fatal) { - if (rdev) { - LOG_ALWAYS_FATAL("illegal fd=%d mode=0%o rdev=%d:%d expected 0%o %d:%d", - fd, st.st_mode, major(st.st_rdev), minor(st.st_rdev), - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IRGRP, - major(rdev), minor(rdev)); - } else { - LOG_ALWAYS_FATAL("illegal fd=%d mode=0%o rdev=%d:%d expected 0%o", - fd, st.st_mode, major(st.st_rdev), minor(st.st_rdev), - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IRGRP); - } - /* NOTREACHED */ - } - - errno = ENOTTY; - return -1; -} - -int ashmem_valid(int fd) -{ - return __ashmem_is_ashmem(fd, 0) >= 0; -} - -/* - * 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 ret, save_errno; - - int fd = __ashmem_open(); - if (fd < 0) { - return fd; - } - - if (name) { - char buf[ASHMEM_NAME_LEN] = {0}; - - strlcpy(buf, name, sizeof(buf)); - ret = TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_SET_NAME, buf)); - if (ret < 0) { - goto error; - } - } - - ret = TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_SET_SIZE, size)); - if (ret < 0) { - goto error; - } - - return fd; - -error: - save_errno = errno; - close(fd); - errno = save_errno; - return ret; -} - -int ashmem_set_prot_region(int fd, int prot) -{ - int ret = __ashmem_is_ashmem(fd, 1); - if (ret < 0) { - return ret; - } - - return TEMP_FAILURE_RETRY(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 }; - - int ret = __ashmem_is_ashmem(fd, 1); - if (ret < 0) { - return ret; - } - - return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_PIN, &pin)); -} - -int ashmem_unpin_region(int fd, size_t offset, size_t len) -{ - struct ashmem_pin pin = { offset, len }; - - int ret = __ashmem_is_ashmem(fd, 1); - if (ret < 0) { - return ret; - } - - return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_UNPIN, &pin)); -} - -int ashmem_get_size_region(int fd) -{ - int ret = __ashmem_is_ashmem(fd, 1); - if (ret < 0) { - return ret; - } - - return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_SIZE, NULL)); -} diff --git a/libcutils/ashmem-dev.cpp b/libcutils/ashmem-dev.cpp new file mode 100644 index 000000000..15ace0e64 --- /dev/null +++ b/libcutils/ashmem-dev.cpp @@ -0,0 +1,227 @@ +/* + * 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 + +/* + * 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. + */ +#define LOG_TAG "ashmem" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ASHMEM_DEVICE "/dev/ashmem" + +/* ashmem identity */ +static dev_t __ashmem_rdev; +/* + * If we trigger a signal handler in the middle of locked activity and the + * signal handler calls ashmem, we could get into a deadlock state. + */ +static pthread_mutex_t __ashmem_lock = PTHREAD_MUTEX_INITIALIZER; + +/* logistics of getting file descriptor for ashmem */ +static int __ashmem_open_locked() +{ + int ret; + struct stat st; + + int fd = TEMP_FAILURE_RETRY(open(ASHMEM_DEVICE, O_RDWR | O_CLOEXEC)); + if (fd < 0) { + return fd; + } + + ret = TEMP_FAILURE_RETRY(fstat(fd, &st)); + if (ret < 0) { + int save_errno = errno; + close(fd); + errno = save_errno; + return ret; + } + if (!S_ISCHR(st.st_mode) || !st.st_rdev) { + close(fd); + errno = ENOTTY; + return -1; + } + + __ashmem_rdev = st.st_rdev; + return fd; +} + +static int __ashmem_open() +{ + int fd; + + pthread_mutex_lock(&__ashmem_lock); + fd = __ashmem_open_locked(); + pthread_mutex_unlock(&__ashmem_lock); + + return fd; +} + +/* Make sure file descriptor references ashmem, negative number means false */ +static int __ashmem_is_ashmem(int fd, int fatal) +{ + dev_t rdev; + struct stat st; + + if (TEMP_FAILURE_RETRY(fstat(fd, &st)) < 0) { + return -1; + } + + rdev = 0; /* Too much complexity to sniff __ashmem_rdev */ + if (S_ISCHR(st.st_mode) && st.st_rdev) { + pthread_mutex_lock(&__ashmem_lock); + rdev = __ashmem_rdev; + if (rdev) { + pthread_mutex_unlock(&__ashmem_lock); + } else { + int fd = __ashmem_open_locked(); + if (fd < 0) { + pthread_mutex_unlock(&__ashmem_lock); + return -1; + } + rdev = __ashmem_rdev; + pthread_mutex_unlock(&__ashmem_lock); + + close(fd); + } + + if (st.st_rdev == rdev) { + return 0; + } + } + + if (fatal) { + if (rdev) { + LOG_ALWAYS_FATAL("illegal fd=%d mode=0%o rdev=%d:%d expected 0%o %d:%d", + fd, st.st_mode, major(st.st_rdev), minor(st.st_rdev), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IRGRP, + major(rdev), minor(rdev)); + } else { + LOG_ALWAYS_FATAL("illegal fd=%d mode=0%o rdev=%d:%d expected 0%o", + fd, st.st_mode, major(st.st_rdev), minor(st.st_rdev), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IRGRP); + } + /* NOTREACHED */ + } + + errno = ENOTTY; + return -1; +} + +int ashmem_valid(int fd) +{ + return __ashmem_is_ashmem(fd, 0) >= 0; +} + +/* + * 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 ret, save_errno; + + int fd = __ashmem_open(); + if (fd < 0) { + return fd; + } + + if (name) { + char buf[ASHMEM_NAME_LEN] = {0}; + + strlcpy(buf, name, sizeof(buf)); + ret = TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_SET_NAME, buf)); + if (ret < 0) { + goto error; + } + } + + ret = TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_SET_SIZE, size)); + if (ret < 0) { + goto error; + } + + return fd; + +error: + save_errno = errno; + close(fd); + errno = save_errno; + return ret; +} + +int ashmem_set_prot_region(int fd, int prot) +{ + int ret = __ashmem_is_ashmem(fd, 1); + if (ret < 0) { + return ret; + } + + return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_SET_PROT_MASK, prot)); +} + +int ashmem_pin_region(int fd, size_t offset, size_t len) +{ + // TODO: should LP64 reject too-large offset/len? + ashmem_pin pin = { static_cast(offset), static_cast(len) }; + + int ret = __ashmem_is_ashmem(fd, 1); + if (ret < 0) { + return ret; + } + + return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_PIN, &pin)); +} + +int ashmem_unpin_region(int fd, size_t offset, size_t len) +{ + // TODO: should LP64 reject too-large offset/len? + ashmem_pin pin = { static_cast(offset), static_cast(len) }; + + int ret = __ashmem_is_ashmem(fd, 1); + if (ret < 0) { + return ret; + } + + return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_UNPIN, &pin)); +} + +int ashmem_get_size_region(int fd) +{ + int ret = __ashmem_is_ashmem(fd, 1); + if (ret < 0) { + return ret; + } + + return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_SIZE, NULL)); +} diff --git a/libcutils/ashmem-host.c b/libcutils/ashmem-host.c deleted file mode 100644 index 1f9f753e4..000000000 --- a/libcutils/ashmem-host.c +++ /dev/null @@ -1,92 +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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifndef __unused -#define __unused __attribute__((__unused__)) -#endif - -int ashmem_create_region(const char *ignored __unused, size_t size) -{ - char template[PATH_MAX]; - snprintf(template, sizeof(template), "/tmp/android-ashmem-%d-XXXXXXXXX", getpid()); - int fd = mkstemp(template); - if (fd == -1) return -1; - - unlink(template); - - if (TEMP_FAILURE_RETRY(ftruncate(fd, size)) == -1) { - close(fd); - return -1; - } - - return fd; -} - -int ashmem_set_prot_region(int fd __unused, int prot __unused) -{ - return 0; -} - -int ashmem_pin_region(int fd __unused, size_t offset __unused, size_t len __unused) -{ - return 0 /*ASHMEM_NOT_PURGED*/; -} - -int ashmem_unpin_region(int fd __unused, size_t offset __unused, size_t len __unused) -{ - return 0 /*ASHMEM_IS_UNPINNED*/; -} - -int ashmem_get_size_region(int fd) -{ - struct stat buf; - int result = fstat(fd, &buf); - if (result == -1) { - return -1; - } - - /* - * Check if this is an "ashmem" region. - * TODO: This is very hacky, and can easily break. - * We need some reliable indicator. - */ - if (!(buf.st_nlink == 0 && S_ISREG(buf.st_mode))) { - errno = ENOTTY; - return -1; - } - - return buf.st_size; -} diff --git a/libcutils/ashmem-host.cpp b/libcutils/ashmem-host.cpp new file mode 100644 index 000000000..d2c28f393 --- /dev/null +++ b/libcutils/ashmem-host.cpp @@ -0,0 +1,93 @@ +/* + * 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 + +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifndef __unused +#define __unused __attribute__((__unused__)) +#endif + +int ashmem_create_region(const char *ignored __unused, size_t size) +{ + char pattern[PATH_MAX]; + snprintf(pattern, sizeof(pattern), "/tmp/android-ashmem-%d-XXXXXXXXX", getpid()); + int fd = mkstemp(pattern); + if (fd == -1) return -1; + + unlink(pattern); + + if (TEMP_FAILURE_RETRY(ftruncate(fd, size)) == -1) { + close(fd); + return -1; + } + + return fd; +} + +int ashmem_set_prot_region(int fd __unused, int prot __unused) +{ + return 0; +} + +int ashmem_pin_region(int fd __unused, size_t offset __unused, size_t len __unused) +{ + return 0 /*ASHMEM_NOT_PURGED*/; +} + +int ashmem_unpin_region(int fd __unused, size_t offset __unused, size_t len __unused) +{ + return 0 /*ASHMEM_IS_UNPINNED*/; +} + +int ashmem_get_size_region(int fd) +{ + struct stat buf; + int result = fstat(fd, &buf); + if (result == -1) { + return -1; + } + + /* + * Check if this is an "ashmem" region. + * TODO: This is very hacky, and can easily break. + * We need some reliable indicator. + */ + if (!(buf.st_nlink == 0 && S_ISREG(buf.st_mode))) { + errno = ENOTTY; + return -1; + } + + return buf.st_size; +} diff --git a/libcutils/canned_fs_config.c b/libcutils/canned_fs_config.c deleted file mode 100644 index 819a846a6..000000000 --- a/libcutils/canned_fs_config.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -typedef struct { - const char* path; - unsigned uid; - unsigned gid; - unsigned mode; - uint64_t capabilities; -} Path; - -static Path* canned_data = NULL; -static int canned_alloc = 0; -static int canned_used = 0; - -static int path_compare(const void* a, const void* b) { - return strcmp(((Path*)a)->path, ((Path*)b)->path); -} - -int load_canned_fs_config(const char* fn) { - char buf[PATH_MAX + 200]; - FILE* f; - - f = fopen(fn, "r"); - if (f == NULL) { - fprintf(stderr, "failed to open %s: %s\n", fn, strerror(errno)); - return -1; - } - - while (fgets(buf, sizeof(buf), f)) { - Path* p; - char* token; - char* line = buf; - bool rootdir; - - while (canned_used >= canned_alloc) { - canned_alloc = (canned_alloc+1) * 2; - canned_data = (Path*) realloc(canned_data, canned_alloc * sizeof(Path)); - } - p = canned_data + canned_used; - if (line[0] == '/') line++; - rootdir = line[0] == ' '; - p->path = strdup(rootdir ? "" : strtok(line, " ")); - p->uid = atoi(strtok(rootdir ? line : NULL, " ")); - p->gid = atoi(strtok(NULL, " ")); - p->mode = strtol(strtok(NULL, " "), NULL, 8); // mode is in octal - p->capabilities = 0; - - do { - token = strtok(NULL, " "); - if (token && strncmp(token, "capabilities=", 13) == 0) { - p->capabilities = strtoll(token+13, NULL, 0); - break; - } - } while (token); - - canned_used++; - } - - fclose(f); - - qsort(canned_data, canned_used, sizeof(Path), path_compare); - printf("loaded %d fs_config entries\n", canned_used); - - return 0; -} - -static const int kDebugCannedFsConfig = 0; - -void canned_fs_config(const char* path, int dir, const char* target_out_path, - unsigned* uid, unsigned* gid, unsigned* mode, uint64_t* capabilities) { - Path key, *p; - - key.path = path; - if (path[0] == '/') key.path++; // canned paths lack the leading '/' - p = (Path*) bsearch(&key, canned_data, canned_used, sizeof(Path), path_compare); - if (p == NULL) { - fprintf(stderr, "failed to find [%s] in canned fs_config\n", path); - exit(1); - } - *uid = p->uid; - *gid = p->gid; - *mode = p->mode; - *capabilities = p->capabilities; - - if (kDebugCannedFsConfig) { - // for debugging, run the built-in fs_config and compare the results. - - unsigned c_uid, c_gid, c_mode; - uint64_t c_capabilities; - - fs_config(path, dir, target_out_path, &c_uid, &c_gid, &c_mode, &c_capabilities); - - if (c_uid != *uid) printf("%s uid %d %d\n", path, *uid, c_uid); - if (c_gid != *gid) printf("%s gid %d %d\n", path, *gid, c_gid); - if (c_mode != *mode) printf("%s mode 0%o 0%o\n", path, *mode, c_mode); - if (c_capabilities != *capabilities) { - printf("%s capabilities %" PRIx64 " %" PRIx64 "\n", - path, - *capabilities, - c_capabilities); - } - } -} diff --git a/libcutils/canned_fs_config.cpp b/libcutils/canned_fs_config.cpp new file mode 100644 index 000000000..6b5763b16 --- /dev/null +++ b/libcutils/canned_fs_config.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + const char* path; + unsigned uid; + unsigned gid; + unsigned mode; + uint64_t capabilities; +} Path; + +static Path* canned_data = NULL; +static int canned_alloc = 0; +static int canned_used = 0; + +static int path_compare(const void* a, const void* b) { + return strcmp(((Path*)a)->path, ((Path*)b)->path); +} + +int load_canned_fs_config(const char* fn) { + char buf[PATH_MAX + 200]; + FILE* f; + + f = fopen(fn, "r"); + if (f == NULL) { + fprintf(stderr, "failed to open %s: %s\n", fn, strerror(errno)); + return -1; + } + + while (fgets(buf, sizeof(buf), f)) { + Path* p; + char* token; + char* line = buf; + bool rootdir; + + while (canned_used >= canned_alloc) { + canned_alloc = (canned_alloc+1) * 2; + canned_data = (Path*) realloc(canned_data, canned_alloc * sizeof(Path)); + } + p = canned_data + canned_used; + if (line[0] == '/') line++; + rootdir = line[0] == ' '; + p->path = strdup(rootdir ? "" : strtok(line, " ")); + p->uid = atoi(strtok(rootdir ? line : NULL, " ")); + p->gid = atoi(strtok(NULL, " ")); + p->mode = strtol(strtok(NULL, " "), NULL, 8); // mode is in octal + p->capabilities = 0; + + do { + token = strtok(NULL, " "); + if (token && strncmp(token, "capabilities=", 13) == 0) { + p->capabilities = strtoll(token+13, NULL, 0); + break; + } + } while (token); + + canned_used++; + } + + fclose(f); + + qsort(canned_data, canned_used, sizeof(Path), path_compare); + printf("loaded %d fs_config entries\n", canned_used); + + return 0; +} + +static const int kDebugCannedFsConfig = 0; + +void canned_fs_config(const char* path, int dir, const char* target_out_path, + unsigned* uid, unsigned* gid, unsigned* mode, uint64_t* capabilities) { + Path key, *p; + + key.path = path; + if (path[0] == '/') key.path++; // canned paths lack the leading '/' + p = (Path*) bsearch(&key, canned_data, canned_used, sizeof(Path), path_compare); + if (p == NULL) { + fprintf(stderr, "failed to find [%s] in canned fs_config\n", path); + exit(1); + } + *uid = p->uid; + *gid = p->gid; + *mode = p->mode; + *capabilities = p->capabilities; + + if (kDebugCannedFsConfig) { + // for debugging, run the built-in fs_config and compare the results. + + unsigned c_uid, c_gid, c_mode; + uint64_t c_capabilities; + + fs_config(path, dir, target_out_path, &c_uid, &c_gid, &c_mode, &c_capabilities); + + if (c_uid != *uid) printf("%s uid %d %d\n", path, *uid, c_uid); + if (c_gid != *gid) printf("%s gid %d %d\n", path, *gid, c_gid); + if (c_mode != *mode) printf("%s mode 0%o 0%o\n", path, *mode, c_mode); + if (c_capabilities != *capabilities) { + printf("%s capabilities %" PRIx64 " %" PRIx64 "\n", + path, + *capabilities, + c_capabilities); + } + } +} diff --git a/libcutils/config_utils.c b/libcutils/config_utils.c deleted file mode 100644 index fc5ca7876..000000000 --- a/libcutils/config_utils.c +++ /dev/null @@ -1,329 +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 -#include -#include -#include -#include - -#include -#include - -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); -} - -void config_free(cnode *root) -{ - cnode *cur = root->first_child; - - while (cur) { - cnode *prev = cur; - config_free(cur); - cur = cur->next; - free(prev); - } -} diff --git a/libcutils/config_utils.cpp b/libcutils/config_utils.cpp new file mode 100644 index 000000000..a3af01a58 --- /dev/null +++ b/libcutils/config_utils.cpp @@ -0,0 +1,328 @@ +/* + * 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 + +#include +#include +#include +#include +#include + +#include + +cnode* config_node(const char *name, const char *value) +{ + cnode* node = static_cast(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 = static_cast(load_file(fn, nullptr)); + config_load(root, data); + // TODO: deliberate leak :-/ +} + +void config_free(cnode *root) +{ + cnode *cur = root->first_child; + + while (cur) { + cnode *prev = cur; + config_free(cur); + cur = cur->next; + free(prev); + } +} diff --git a/libcutils/fs.c b/libcutils/fs.c deleted file mode 100644 index b253b1cd9..000000000 --- a/libcutils/fs.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (C) 2012 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 "cutils" - -/* These defines are only needed because prebuilt headers are out of date */ -#define __USE_XOPEN2K8 1 -#define _ATFILE_SOURCE 1 -#define _GNU_SOURCE 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define ALL_PERMS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO) -#define BUF_SIZE 64 - -static int fs_prepare_path_impl(const char* path, mode_t mode, uid_t uid, gid_t gid, - int allow_fixup, int prepare_as_dir) { - // Check if path needs to be created - struct stat sb; - int create_result = -1; - if (TEMP_FAILURE_RETRY(lstat(path, &sb)) == -1) { - if (errno == ENOENT) { - goto create; - } else { - ALOGE("Failed to lstat(%s): %s", path, strerror(errno)); - return -1; - } - } - - // Exists, verify status - int type_ok = prepare_as_dir ? S_ISDIR(sb.st_mode) : S_ISREG(sb.st_mode); - if (!type_ok) { - ALOGE("Not a %s: %s", (prepare_as_dir ? "directory" : "regular file"), path); - return -1; - } - - int owner_match = ((sb.st_uid == uid) && (sb.st_gid == gid)); - int mode_match = ((sb.st_mode & ALL_PERMS) == mode); - if (owner_match && mode_match) { - return 0; - } else if (allow_fixup) { - goto fixup; - } else { - if (!owner_match) { - ALOGE("Expected path %s with owner %d:%d but found %d:%d", - path, uid, gid, sb.st_uid, sb.st_gid); - return -1; - } else { - ALOGW("Expected path %s with mode %o but found %o", - path, mode, (sb.st_mode & ALL_PERMS)); - return 0; - } - } - -create: - create_result = prepare_as_dir - ? TEMP_FAILURE_RETRY(mkdir(path, mode)) - : TEMP_FAILURE_RETRY(open(path, O_CREAT | O_CLOEXEC | O_NOFOLLOW | O_RDONLY, 0644)); - if (create_result == -1) { - if (errno != EEXIST) { - ALOGE("Failed to %s(%s): %s", - (prepare_as_dir ? "mkdir" : "open"), path, strerror(errno)); - return -1; - } - } else if (!prepare_as_dir) { - // For regular files we need to make sure we close the descriptor - if (close(create_result) == -1) { - ALOGW("Failed to close file after create %s: %s", path, strerror(errno)); - } - } -fixup: - if (TEMP_FAILURE_RETRY(chmod(path, mode)) == -1) { - ALOGE("Failed to chmod(%s, %d): %s", path, mode, strerror(errno)); - return -1; - } - if (TEMP_FAILURE_RETRY(chown(path, uid, gid)) == -1) { - ALOGE("Failed to chown(%s, %d, %d): %s", path, uid, gid, strerror(errno)); - return -1; - } - - return 0; -} - -int fs_prepare_dir(const char* path, mode_t mode, uid_t uid, gid_t gid) { - return fs_prepare_path_impl(path, mode, uid, gid, /*allow_fixup*/ 1, /*prepare_as_dir*/ 1); -} - -int fs_prepare_dir_strict(const char* path, mode_t mode, uid_t uid, gid_t gid) { - return fs_prepare_path_impl(path, mode, uid, gid, /*allow_fixup*/ 0, /*prepare_as_dir*/ 1); -} - -int fs_prepare_file_strict(const char* path, mode_t mode, uid_t uid, gid_t gid) { - return fs_prepare_path_impl(path, mode, uid, gid, /*allow_fixup*/ 0, /*prepare_as_dir*/ 0); -} - -int fs_read_atomic_int(const char* path, int* out_value) { - int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY)); - if (fd == -1) { - ALOGE("Failed to read %s: %s", path, strerror(errno)); - return -1; - } - - char buf[BUF_SIZE]; - if (TEMP_FAILURE_RETRY(read(fd, buf, BUF_SIZE)) == -1) { - ALOGE("Failed to read %s: %s", path, strerror(errno)); - goto fail; - } - if (sscanf(buf, "%d", out_value) != 1) { - ALOGE("Failed to parse %s: %s", path, strerror(errno)); - goto fail; - } - close(fd); - return 0; - -fail: - close(fd); - *out_value = -1; - return -1; -} - -int fs_write_atomic_int(const char* path, int value) { - char temp[PATH_MAX]; - if (snprintf(temp, PATH_MAX, "%s.XXXXXX", path) >= PATH_MAX) { - ALOGE("Path too long"); - return -1; - } - - int fd = TEMP_FAILURE_RETRY(mkstemp(temp)); - if (fd == -1) { - ALOGE("Failed to open %s: %s", temp, strerror(errno)); - return -1; - } - - char buf[BUF_SIZE]; - int len = snprintf(buf, BUF_SIZE, "%d", value) + 1; - if (len > BUF_SIZE) { - ALOGE("Value %d too large: %s", value, strerror(errno)); - goto fail; - } - if (TEMP_FAILURE_RETRY(write(fd, buf, len)) < len) { - ALOGE("Failed to write %s: %s", temp, strerror(errno)); - goto fail; - } - if (close(fd) == -1) { - ALOGE("Failed to close %s: %s", temp, strerror(errno)); - goto fail_closed; - } - - if (rename(temp, path) == -1) { - ALOGE("Failed to rename %s to %s: %s", temp, path, strerror(errno)); - goto fail_closed; - } - - return 0; - -fail: - close(fd); -fail_closed: - unlink(temp); - return -1; -} - -#ifndef __APPLE__ - -int fs_mkdirs(const char* path, mode_t mode) { - int res = 0; - int fd = 0; - struct stat sb; - char* buf = strdup(path); - - if (*buf != '/') { - ALOGE("Relative paths are not allowed: %s", buf); - res = -EINVAL; - goto done; - } - - if ((fd = open("/", 0)) == -1) { - ALOGE("Failed to open(/): %s", strerror(errno)); - res = -errno; - goto done; - } - - char* segment = buf + 1; - char* p = segment; - while (*p != '\0') { - if (*p == '/') { - *p = '\0'; - - if (!strcmp(segment, "..") || !strcmp(segment, ".") || !strcmp(segment, "")) { - ALOGE("Invalid path: %s", buf); - res = -EINVAL; - goto done_close; - } - - if (fstatat(fd, segment, &sb, AT_SYMLINK_NOFOLLOW) != 0) { - if (errno == ENOENT) { - /* Nothing there yet; let's create it! */ - if (mkdirat(fd, segment, mode) != 0) { - if (errno == EEXIST) { - /* We raced with someone; ignore */ - } else { - ALOGE("Failed to mkdirat(%s): %s", buf, strerror(errno)); - res = -errno; - goto done_close; - } - } - } else { - ALOGE("Failed to fstatat(%s): %s", buf, strerror(errno)); - res = -errno; - goto done_close; - } - } else { - if (S_ISLNK(sb.st_mode)) { - ALOGE("Symbolic links are not allowed: %s", buf); - res = -ELOOP; - goto done_close; - } - if (!S_ISDIR(sb.st_mode)) { - ALOGE("Existing segment not a directory: %s", buf); - res = -ENOTDIR; - goto done_close; - } - } - - /* Yay, segment is ready for us to step into */ - int next_fd; - if ((next_fd = openat(fd, segment, O_NOFOLLOW | O_CLOEXEC)) == -1) { - ALOGE("Failed to openat(%s): %s", buf, strerror(errno)); - res = -errno; - goto done_close; - } - - close(fd); - fd = next_fd; - - *p = '/'; - segment = p + 1; - } - p++; - } - -done_close: - close(fd); -done: - free(buf); - return res; -} - -#endif diff --git a/libcutils/fs.cpp b/libcutils/fs.cpp new file mode 100644 index 000000000..ef85accce --- /dev/null +++ b/libcutils/fs.cpp @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2012 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 + +#define LOG_TAG "cutils" + +/* These defines are only needed because prebuilt headers are out of date */ +#define __USE_XOPEN2K8 1 +#define _ATFILE_SOURCE 1 +#define _GNU_SOURCE 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define ALL_PERMS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO) +#define BUF_SIZE 64 + +static int fs_prepare_path_impl(const char* path, mode_t mode, uid_t uid, gid_t gid, + int allow_fixup, int prepare_as_dir) { + // TODO: fix the goto hell below. + int type_ok; + int owner_match; + int mode_match; + + // Check if path needs to be created + struct stat sb; + int create_result = -1; + if (TEMP_FAILURE_RETRY(lstat(path, &sb)) == -1) { + if (errno == ENOENT) { + goto create; + } else { + ALOGE("Failed to lstat(%s): %s", path, strerror(errno)); + return -1; + } + } + + // Exists, verify status + type_ok = prepare_as_dir ? S_ISDIR(sb.st_mode) : S_ISREG(sb.st_mode); + if (!type_ok) { + ALOGE("Not a %s: %s", (prepare_as_dir ? "directory" : "regular file"), path); + return -1; + } + + owner_match = ((sb.st_uid == uid) && (sb.st_gid == gid)); + mode_match = ((sb.st_mode & ALL_PERMS) == mode); + if (owner_match && mode_match) { + return 0; + } else if (allow_fixup) { + goto fixup; + } else { + if (!owner_match) { + ALOGE("Expected path %s with owner %d:%d but found %d:%d", + path, uid, gid, sb.st_uid, sb.st_gid); + return -1; + } else { + ALOGW("Expected path %s with mode %o but found %o", + path, mode, (sb.st_mode & ALL_PERMS)); + return 0; + } + } + +create: + create_result = prepare_as_dir + ? TEMP_FAILURE_RETRY(mkdir(path, mode)) + : TEMP_FAILURE_RETRY(open(path, O_CREAT | O_CLOEXEC | O_NOFOLLOW | O_RDONLY, 0644)); + if (create_result == -1) { + if (errno != EEXIST) { + ALOGE("Failed to %s(%s): %s", + (prepare_as_dir ? "mkdir" : "open"), path, strerror(errno)); + return -1; + } + } else if (!prepare_as_dir) { + // For regular files we need to make sure we close the descriptor + if (close(create_result) == -1) { + ALOGW("Failed to close file after create %s: %s", path, strerror(errno)); + } + } +fixup: + if (TEMP_FAILURE_RETRY(chmod(path, mode)) == -1) { + ALOGE("Failed to chmod(%s, %d): %s", path, mode, strerror(errno)); + return -1; + } + if (TEMP_FAILURE_RETRY(chown(path, uid, gid)) == -1) { + ALOGE("Failed to chown(%s, %d, %d): %s", path, uid, gid, strerror(errno)); + return -1; + } + + return 0; +} + +int fs_prepare_dir(const char* path, mode_t mode, uid_t uid, gid_t gid) { + return fs_prepare_path_impl(path, mode, uid, gid, /*allow_fixup*/ 1, /*prepare_as_dir*/ 1); +} + +int fs_prepare_dir_strict(const char* path, mode_t mode, uid_t uid, gid_t gid) { + return fs_prepare_path_impl(path, mode, uid, gid, /*allow_fixup*/ 0, /*prepare_as_dir*/ 1); +} + +int fs_prepare_file_strict(const char* path, mode_t mode, uid_t uid, gid_t gid) { + return fs_prepare_path_impl(path, mode, uid, gid, /*allow_fixup*/ 0, /*prepare_as_dir*/ 0); +} + +int fs_read_atomic_int(const char* path, int* out_value) { + int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY)); + if (fd == -1) { + ALOGE("Failed to read %s: %s", path, strerror(errno)); + return -1; + } + + char buf[BUF_SIZE]; + if (TEMP_FAILURE_RETRY(read(fd, buf, BUF_SIZE)) == -1) { + ALOGE("Failed to read %s: %s", path, strerror(errno)); + goto fail; + } + if (sscanf(buf, "%d", out_value) != 1) { + ALOGE("Failed to parse %s: %s", path, strerror(errno)); + goto fail; + } + close(fd); + return 0; + +fail: + close(fd); + *out_value = -1; + return -1; +} + +int fs_write_atomic_int(const char* path, int value) { + char temp[PATH_MAX]; + if (snprintf(temp, PATH_MAX, "%s.XXXXXX", path) >= PATH_MAX) { + ALOGE("Path too long"); + return -1; + } + + int fd = TEMP_FAILURE_RETRY(mkstemp(temp)); + if (fd == -1) { + ALOGE("Failed to open %s: %s", temp, strerror(errno)); + return -1; + } + + char buf[BUF_SIZE]; + int len = snprintf(buf, BUF_SIZE, "%d", value) + 1; + if (len > BUF_SIZE) { + ALOGE("Value %d too large: %s", value, strerror(errno)); + goto fail; + } + if (TEMP_FAILURE_RETRY(write(fd, buf, len)) < len) { + ALOGE("Failed to write %s: %s", temp, strerror(errno)); + goto fail; + } + if (close(fd) == -1) { + ALOGE("Failed to close %s: %s", temp, strerror(errno)); + goto fail_closed; + } + + if (rename(temp, path) == -1) { + ALOGE("Failed to rename %s to %s: %s", temp, path, strerror(errno)); + goto fail_closed; + } + + return 0; + +fail: + close(fd); +fail_closed: + unlink(temp); + return -1; +} + +#ifndef __APPLE__ + +int fs_mkdirs(const char* path, mode_t mode) { + if (*path != '/') { + ALOGE("Relative paths are not allowed: %s", path); + return -EINVAL; + } + + int fd = open("/", 0); + if (fd == -1) { + ALOGE("Failed to open(/): %s", strerror(errno)); + return -errno; + } + + struct stat sb; + int res = 0; + char* buf = strdup(path); + char* segment = buf + 1; + char* p = segment; + while (*p != '\0') { + if (*p == '/') { + *p = '\0'; + + if (!strcmp(segment, "..") || !strcmp(segment, ".") || !strcmp(segment, "")) { + ALOGE("Invalid path: %s", buf); + res = -EINVAL; + goto done_close; + } + + if (fstatat(fd, segment, &sb, AT_SYMLINK_NOFOLLOW) != 0) { + if (errno == ENOENT) { + /* Nothing there yet; let's create it! */ + if (mkdirat(fd, segment, mode) != 0) { + if (errno == EEXIST) { + /* We raced with someone; ignore */ + } else { + ALOGE("Failed to mkdirat(%s): %s", buf, strerror(errno)); + res = -errno; + goto done_close; + } + } + } else { + ALOGE("Failed to fstatat(%s): %s", buf, strerror(errno)); + res = -errno; + goto done_close; + } + } else { + if (S_ISLNK(sb.st_mode)) { + ALOGE("Symbolic links are not allowed: %s", buf); + res = -ELOOP; + goto done_close; + } + if (!S_ISDIR(sb.st_mode)) { + ALOGE("Existing segment not a directory: %s", buf); + res = -ENOTDIR; + goto done_close; + } + } + + /* Yay, segment is ready for us to step into */ + int next_fd; + if ((next_fd = openat(fd, segment, O_NOFOLLOW | O_CLOEXEC)) == -1) { + ALOGE("Failed to openat(%s): %s", buf, strerror(errno)); + res = -errno; + goto done_close; + } + + close(fd); + fd = next_fd; + + *p = '/'; + segment = p + 1; + } + p++; + } + +done_close: + close(fd); + free(buf); + return res; +} + +#endif diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp index 7603ffce6..f45472e7e 100644 --- a/libcutils/fs_config.cpp +++ b/libcutils/fs_config.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include + // This file is used to define the properties of the filesystem // images generated by build tools (mkbootfs and mkyaffs2image) and // by the device side of adb. @@ -31,7 +33,6 @@ #include #include -#include #include #ifndef O_BINARY diff --git a/libcutils/hashmap.c b/libcutils/hashmap.c deleted file mode 100644 index ede3b981d..000000000 --- a/libcutils/hashmap.c +++ /dev/null @@ -1,358 +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 -#include -#include -#include -#include -#include -#include -#include - -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. - */ -#ifdef __clang__ -__attribute__((no_sanitize("integer"))) -#endif -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); -} - -#ifdef __clang__ -__attribute__((no_sanitize("integer"))) -#endif -/* FIXME: relies on signed integer overflow, which is undefined behavior */ -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) { - Entry *next = entry->next; - if (!callback(entry->key, entry->value, context)) { - return; - } - 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/hashmap.cpp b/libcutils/hashmap.cpp new file mode 100644 index 000000000..65b6ab185 --- /dev/null +++ b/libcutils/hashmap.cpp @@ -0,0 +1,359 @@ +/* + * 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 + +#include +#include +#include +#include +#include +#include +#include + +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 = static_cast(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 = static_cast(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. + */ +#ifdef __clang__ +__attribute__((no_sanitize("integer"))) +#endif +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 = static_cast(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); +} + +#ifdef __clang__ +__attribute__((no_sanitize("integer"))) +#endif +/* FIXME: relies on signed integer overflow, which is undefined behavior */ +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 = static_cast(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) { + Entry *next = entry->next; + if (!callback(entry->key, entry->value, context)) { + return; + } + 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/include/cutils/android_reboot.h b/libcutils/include/cutils/android_reboot.h index a903adba3..99030eddd 100644 --- a/libcutils/include/cutils/android_reboot.h +++ b/libcutils/include/cutils/android_reboot.h @@ -17,6 +17,7 @@ #ifndef __CUTILS_ANDROID_REBOOT_H__ #define __CUTILS_ANDROID_REBOOT_H__ +#include __BEGIN_DECLS diff --git a/libcutils/include/cutils/partition_utils.h b/libcutils/include/cutils/partition_utils.h index 72ca80d35..7518559a4 100644 --- a/libcutils/include/cutils/partition_utils.h +++ b/libcutils/include/cutils/partition_utils.h @@ -17,6 +17,8 @@ #ifndef __CUTILS_PARTITION_WIPED_H__ #define __CUTILS_PARTITION_WIPED_H__ +#include + __BEGIN_DECLS int partition_wiped(char *source); diff --git a/libcutils/include/cutils/record_stream.h b/libcutils/include/cutils/record_stream.h index bfac87a53..bcfc80d5d 100644 --- a/libcutils/include/cutils/record_stream.h +++ b/libcutils/include/cutils/record_stream.h @@ -25,6 +25,7 @@ extern "C" { #endif +#include typedef struct RecordStream RecordStream; diff --git a/libcutils/include/private/canned_fs_config.h b/libcutils/include/private/canned_fs_config.h index 71e1537b2..135b91c6c 100644 --- a/libcutils/include/private/canned_fs_config.h +++ b/libcutils/include/private/canned_fs_config.h @@ -19,8 +19,12 @@ #include +__BEGIN_DECLS + int load_canned_fs_config(const char* fn); void canned_fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid, unsigned* mode, uint64_t* capabilities); +__END_DECLS + #endif diff --git a/libcutils/include/private/fs_config.h b/libcutils/include/private/fs_config.h index aab504281..892649187 100644 --- a/libcutils/include/private/fs_config.h +++ b/libcutils/include/private/fs_config.h @@ -24,6 +24,7 @@ #include #include +#include #if defined(__BIONIC__) #include diff --git a/libcutils/iosched_policy.c b/libcutils/iosched_policy.c deleted file mode 100644 index 13c2cebbc..000000000 --- a/libcutils/iosched_policy.c +++ /dev/null @@ -1,59 +0,0 @@ -/* -** 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 -#include -#include -#include -#include -#include - -#include - -#if defined(__ANDROID__) -#define IOPRIO_WHO_PROCESS (1) -#define IOPRIO_CLASS_SHIFT (13) -#include -#define __android_unused -#else -#define __android_unused __attribute__((__unused__)) -#endif - -int android_set_ioprio(int pid __android_unused, IoSchedClass clazz __android_unused, int ioprio __android_unused) { -#if defined(__ANDROID__) - if (syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, pid, ioprio | (clazz << IOPRIO_CLASS_SHIFT))) { - return -1; - } -#endif - return 0; -} - -int android_get_ioprio(int pid __android_unused, IoSchedClass *clazz, int *ioprio) { -#if defined(__ANDROID__) - int rc; - - if ((rc = syscall(SYS_ioprio_get, IOPRIO_WHO_PROCESS, pid)) < 0) { - return -1; - } - - *clazz = (rc >> IOPRIO_CLASS_SHIFT); - *ioprio = (rc & 0xff); -#else - *clazz = IoSchedClass_NONE; - *ioprio = 0; -#endif - return 0; -} diff --git a/libcutils/iosched_policy.cpp b/libcutils/iosched_policy.cpp new file mode 100644 index 000000000..012c537ac --- /dev/null +++ b/libcutils/iosched_policy.cpp @@ -0,0 +1,59 @@ +/* +** 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 + +#include +#include +#include +#include +#include +#include + +#if defined(__ANDROID__) +#define IOPRIO_WHO_PROCESS (1) +#define IOPRIO_CLASS_SHIFT (13) +#include +#define __android_unused +#else +#define __android_unused __attribute__((__unused__)) +#endif + +int android_set_ioprio(int pid __android_unused, IoSchedClass clazz __android_unused, int ioprio __android_unused) { +#if defined(__ANDROID__) + if (syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, pid, ioprio | (clazz << IOPRIO_CLASS_SHIFT))) { + return -1; + } +#endif + return 0; +} + +int android_get_ioprio(int pid __android_unused, IoSchedClass *clazz, int *ioprio) { +#if defined(__ANDROID__) + int rc; + + if ((rc = syscall(SYS_ioprio_get, IOPRIO_WHO_PROCESS, pid)) < 0) { + return -1; + } + + *clazz = static_cast(rc >> IOPRIO_CLASS_SHIFT); + *ioprio = (rc & 0xff); +#else + *clazz = IoSchedClass_NONE; + *ioprio = 0; +#endif + return 0; +} diff --git a/libcutils/klog.cpp b/libcutils/klog.cpp index d301276f9..6a9f4df8a 100644 --- a/libcutils/klog.cpp +++ b/libcutils/klog.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include + #include #include #include @@ -25,7 +27,6 @@ #include #include -#include static int klog_level = KLOG_INFO_LEVEL; 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 -#include -#include - -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/load_file.cpp b/libcutils/load_file.cpp new file mode 100644 index 000000000..346105c5c --- /dev/null +++ b/libcutils/load_file.cpp @@ -0,0 +1,53 @@ +/* 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 + +#include +#include +#include + +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/native_handle.c b/libcutils/native_handle.c deleted file mode 100644 index 95bbc41c4..000000000 --- a/libcutils/native_handle.c +++ /dev/null @@ -1,95 +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 - -#include -#include -#include -#include -#include - -static const int kMaxNativeFds = 1024; -static const int kMaxNativeInts = 1024; - -native_handle_t* native_handle_init(char* storage, int numFds, int numInts) { - if ((uintptr_t) storage % alignof(native_handle_t)) { - errno = EINVAL; - return NULL; - } - - native_handle_t* handle = (native_handle_t*) storage; - handle->version = sizeof(native_handle_t); - handle->numFds = numFds; - handle->numInts = numInts; - return handle; -} - -native_handle_t* native_handle_create(int numFds, int numInts) { - if (numFds < 0 || numInts < 0 || numFds > kMaxNativeFds || numInts > kMaxNativeInts) { - errno = EINVAL; - return NULL; - } - - size_t mallocSize = sizeof(native_handle_t) + (sizeof(int) * (numFds + numInts)); - native_handle_t* h = malloc(mallocSize); - if (h) { - h->version = sizeof(native_handle_t); - h->numFds = numFds; - h->numInts = numInts; - } - return h; -} - -native_handle_t* native_handle_clone(const native_handle_t* handle) { - native_handle_t* clone = native_handle_create(handle->numFds, handle->numInts); - if (clone == NULL) return NULL; - - for (int i = 0; i < handle->numFds; i++) { - clone->data[i] = dup(handle->data[i]); - if (clone->data[i] == -1) { - clone->numFds = i; - native_handle_close(clone); - native_handle_delete(clone); - return NULL; - } - } - - memcpy(&clone->data[handle->numFds], &handle->data[handle->numFds], - sizeof(int) * handle->numInts); - - return clone; -} - -int native_handle_delete(native_handle_t* h) { - if (h) { - if (h->version != sizeof(native_handle_t)) return -EINVAL; - free(h); - } - return 0; -} - -int native_handle_close(const native_handle_t* h) { - if (h->version != sizeof(native_handle_t)) return -EINVAL; - - int saved_errno = errno; - const int numFds = h->numFds; - for (int i = 0; i < numFds; ++i) { - close(h->data[i]); - } - errno = saved_errno; - return 0; -} diff --git a/libcutils/native_handle.cpp b/libcutils/native_handle.cpp new file mode 100644 index 000000000..66f7a3d59 --- /dev/null +++ b/libcutils/native_handle.cpp @@ -0,0 +1,95 @@ +/* + * 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 + +#include +#include +#include +#include +#include + +static const int kMaxNativeFds = 1024; +static const int kMaxNativeInts = 1024; + +native_handle_t* native_handle_init(char* storage, int numFds, int numInts) { + if ((uintptr_t) storage % alignof(native_handle_t)) { + errno = EINVAL; + return NULL; + } + + native_handle_t* handle = (native_handle_t*) storage; + handle->version = sizeof(native_handle_t); + handle->numFds = numFds; + handle->numInts = numInts; + return handle; +} + +native_handle_t* native_handle_create(int numFds, int numInts) { + if (numFds < 0 || numInts < 0 || numFds > kMaxNativeFds || numInts > kMaxNativeInts) { + errno = EINVAL; + return NULL; + } + + size_t mallocSize = sizeof(native_handle_t) + (sizeof(int) * (numFds + numInts)); + native_handle_t* h = static_cast(malloc(mallocSize)); + if (h) { + h->version = sizeof(native_handle_t); + h->numFds = numFds; + h->numInts = numInts; + } + return h; +} + +native_handle_t* native_handle_clone(const native_handle_t* handle) { + native_handle_t* clone = native_handle_create(handle->numFds, handle->numInts); + if (clone == NULL) return NULL; + + for (int i = 0; i < handle->numFds; i++) { + clone->data[i] = dup(handle->data[i]); + if (clone->data[i] == -1) { + clone->numFds = i; + native_handle_close(clone); + native_handle_delete(clone); + return NULL; + } + } + + memcpy(&clone->data[handle->numFds], &handle->data[handle->numFds], + sizeof(int) * handle->numInts); + + return clone; +} + +int native_handle_delete(native_handle_t* h) { + if (h) { + if (h->version != sizeof(native_handle_t)) return -EINVAL; + free(h); + } + return 0; +} + +int native_handle_close(const native_handle_t* h) { + if (h->version != sizeof(native_handle_t)) return -EINVAL; + + int saved_errno = errno; + const int numFds = h->numFds; + for (int i = 0; i < numFds; ++i) { + close(h->data[i]); + } + errno = saved_errno; + return 0; +} diff --git a/libcutils/partition_utils.c b/libcutils/partition_utils.c deleted file mode 100644 index 823b16289..000000000 --- a/libcutils/partition_utils.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2011, 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 -#include -#include /* for BLKGETSIZE */ -#include -#include -#include - -#include - -static int only_one_char(char *buf, int len, char c) -{ - int i, ret; - - ret = 1; - for (i=0; i + +#include +#include +#include /* for BLKGETSIZE */ +#include +#include +#include + +#include + +static int only_one_char(char *buf, int len, char c) +{ + int i, ret; + + ret = 1; + for (i=0; i + #define LOG_TAG "properties" // #define LOG_NDEBUG 0 @@ -25,7 +27,6 @@ #include #include -#include #include #include diff --git a/libcutils/qtaguid.cpp b/libcutils/qtaguid.cpp index 86a5dc4b3..b94d134be 100644 --- a/libcutils/qtaguid.cpp +++ b/libcutils/qtaguid.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include + // #define LOG_NDEBUG 0 #define LOG_TAG "qtaguid" @@ -26,7 +28,6 @@ #include #include -#include #include class netdHandler { diff --git a/libcutils/record_stream.c b/libcutils/record_stream.c deleted file mode 100644 index 2bc4226ed..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 -#include -#include -#include -#include -#include -#include -#if defined(_WIN32) -#include /* for ntohl */ -#else -#include -#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 - //ALOGE("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/record_stream.cpp b/libcutils/record_stream.cpp new file mode 100644 index 000000000..5a86b8393 --- /dev/null +++ b/libcutils/record_stream.cpp @@ -0,0 +1,187 @@ +/* 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 + +#include +#include +#include +#include +#include +#include +#if defined(_WIN32) +#include /* for ntohl */ +#else +#include +#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 + //ALOGE("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/sched_policy.cpp b/libcutils/sched_policy.cpp index b00fa8561..0e6d33333 100644 --- a/libcutils/sched_policy.cpp +++ b/libcutils/sched_policy.cpp @@ -14,6 +14,8 @@ ** limitations under the License. */ +#include + #define LOG_TAG "SchedPolicy" #include @@ -24,7 +26,6 @@ #include #include -#include #define UNUSED __attribute__((__unused__)) diff --git a/libcutils/socket_inaddr_any_server_unix.c b/libcutils/socket_inaddr_any_server_unix.c deleted file mode 100644 index 387258fdf..000000000 --- a/libcutils/socket_inaddr_any_server_unix.c +++ /dev/null @@ -1,66 +0,0 @@ -/* -** 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 -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#define LISTEN_BACKLOG 4 - -/* open listen() port on any interface */ -int socket_inaddr_any_server(int port, int type) -{ - struct sockaddr_in6 addr; - int s, n; - - memset(&addr, 0, sizeof(addr)); - addr.sin6_family = AF_INET6; - addr.sin6_port = htons(port); - addr.sin6_addr = in6addr_any; - - s = socket(AF_INET6, type, 0); - if (s < 0) return -1; - - n = 1; - setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &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_inaddr_any_server_unix.cpp b/libcutils/socket_inaddr_any_server_unix.cpp new file mode 100644 index 000000000..27c5333f3 --- /dev/null +++ b/libcutils/socket_inaddr_any_server_unix.cpp @@ -0,0 +1,66 @@ +/* +** 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 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define LISTEN_BACKLOG 4 + +/* open listen() port on any interface */ +int socket_inaddr_any_server(int port, int type) +{ + struct sockaddr_in6 addr; + int s, n; + + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_port = htons(port); + addr.sin6_addr = in6addr_any; + + s = socket(AF_INET6, type, 0); + if (s < 0) return -1; + + n = 1; + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &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_inaddr_any_server_windows.c b/libcutils/socket_inaddr_any_server_windows.c deleted file mode 100644 index c15200ad5..000000000 --- a/libcutils/socket_inaddr_any_server_windows.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include - -#include - -#define LISTEN_BACKLOG 4 - -extern bool initialize_windows_sockets(); - -SOCKET socket_inaddr_any_server(int port, int type) { - if (!initialize_windows_sockets()) { - return INVALID_SOCKET; - } - - SOCKET sock = socket(AF_INET6, type, 0); - if (sock == INVALID_SOCKET) { - return INVALID_SOCKET; - } - - // Enforce exclusive addresses so nobody can steal the port from us (1), - // and enable dual-stack so both IPv4 and IPv6 work (2). - // (1) https://msdn.microsoft.com/en-us/library/windows/desktop/ms740621(v=vs.85).aspx. - // (2) https://msdn.microsoft.com/en-us/library/windows/desktop/bb513665(v=vs.85).aspx. - int exclusive = 1; - DWORD v6_only = 0; - if (setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&exclusive, - sizeof(exclusive)) == SOCKET_ERROR || - setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&v6_only, - sizeof(v6_only)) == SOCKET_ERROR) { - closesocket(sock); - return INVALID_SOCKET; - } - - // Bind the socket to our local port. - struct sockaddr_in6 addr; - memset(&addr, 0, sizeof(addr)); - addr.sin6_family = AF_INET6; - addr.sin6_port = htons(port); - addr.sin6_addr = in6addr_any; - if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) { - closesocket(sock); - return INVALID_SOCKET; - } - - // Start listening for connections if this is a TCP socket. - if (type == SOCK_STREAM && listen(sock, LISTEN_BACKLOG) == SOCKET_ERROR) { - closesocket(sock); - return INVALID_SOCKET; - } - - return sock; -} diff --git a/libcutils/socket_inaddr_any_server_windows.cpp b/libcutils/socket_inaddr_any_server_windows.cpp new file mode 100644 index 000000000..1d7320698 --- /dev/null +++ b/libcutils/socket_inaddr_any_server_windows.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include + +#define LISTEN_BACKLOG 4 + +extern bool initialize_windows_sockets(); + +SOCKET socket_inaddr_any_server(int port, int type) { + if (!initialize_windows_sockets()) { + return INVALID_SOCKET; + } + + SOCKET sock = socket(AF_INET6, type, 0); + if (sock == INVALID_SOCKET) { + return INVALID_SOCKET; + } + + // Enforce exclusive addresses so nobody can steal the port from us (1), + // and enable dual-stack so both IPv4 and IPv6 work (2). + // (1) https://msdn.microsoft.com/en-us/library/windows/desktop/ms740621(v=vs.85).aspx. + // (2) https://msdn.microsoft.com/en-us/library/windows/desktop/bb513665(v=vs.85).aspx. + int exclusive = 1; + DWORD v6_only = 0; + if (setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&exclusive, + sizeof(exclusive)) == SOCKET_ERROR || + setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&v6_only, + sizeof(v6_only)) == SOCKET_ERROR) { + closesocket(sock); + return INVALID_SOCKET; + } + + // Bind the socket to our local port. + struct sockaddr_in6 addr; + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_port = htons(port); + addr.sin6_addr = in6addr_any; + if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) { + closesocket(sock); + return INVALID_SOCKET; + } + + // Start listening for connections if this is a TCP socket. + if (type == SOCK_STREAM && listen(sock, LISTEN_BACKLOG) == SOCKET_ERROR) { + closesocket(sock); + return INVALID_SOCKET; + } + + return sock; +} diff --git a/libcutils/socket_local_client_unix.c b/libcutils/socket_local_client_unix.c deleted file mode 100644 index 92fb9f17d..000000000 --- a/libcutils/socket_local_client_unix.c +++ /dev/null @@ -1,168 +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 -#include -#include -#include -#include - -#include - -#if defined(_WIN32) - -int socket_local_client(const char *name, int namespaceId, int type) -{ - errno = ENOSYS; - return -1; -} - -#else /* !_WIN32 */ - -#include -#include -#include -#include - -#include "socket_local_unix.h" - -#define UNUSED __attribute__((unused)) - -#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: -#if defined(__linux__) - 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 - /* 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 - 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 UNUSED) -{ - struct sockaddr_un addr; - socklen_t alen; - 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 /* !_WIN32 */ diff --git a/libcutils/socket_local_client_unix.cpp b/libcutils/socket_local_client_unix.cpp new file mode 100644 index 000000000..68b2b0ce9 --- /dev/null +++ b/libcutils/socket_local_client_unix.cpp @@ -0,0 +1,168 @@ +/* + * 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 + +#include +#include +#include +#include +#include + +#if defined(_WIN32) + +int socket_local_client(const char *name, int namespaceId, int type) +{ + errno = ENOSYS; + return -1; +} + +#else /* !_WIN32 */ + +#include +#include +#include +#include + +#include "socket_local_unix.h" + +#define UNUSED __attribute__((unused)) + +#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: +#if defined(__linux__) + 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 + /* 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 + 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 UNUSED) +{ + struct sockaddr_un addr; + socklen_t alen; + 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 /* !_WIN32 */ diff --git a/libcutils/socket_local_server_unix.c b/libcutils/socket_local_server_unix.c deleted file mode 100644 index db9e1e04d..000000000 --- a/libcutils/socket_local_server_unix.c +++ /dev/null @@ -1,126 +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 - -#include -#include -#include -#include -#include - -#if defined(_WIN32) - -int socket_local_server(const char *name, int namespaceId, int type) -{ - errno = ENOSYS; - return -1; -} - -#else /* !_WIN32 */ - -#include -#include -#include -#include -#include - -#include "socket_local_unix.h" - -#define LISTEN_BACKLOG 4 - -/* Only the bottom bits are really the socket type; there are flags too. */ -#define SOCK_TYPE_MASK 0xf - -/** - * 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 */ -#if !defined(__linux__) - 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_TYPE_MASK) == SOCK_STREAM) { - int ret; - - ret = listen(s, LISTEN_BACKLOG); - - if (ret < 0) { - close(s); - return -1; - } - } - - return s; -} - -#endif /* !_WIN32 */ diff --git a/libcutils/socket_local_server_unix.cpp b/libcutils/socket_local_server_unix.cpp new file mode 100644 index 000000000..855e5da4e --- /dev/null +++ b/libcutils/socket_local_server_unix.cpp @@ -0,0 +1,126 @@ +/* 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 + +#include +#include +#include +#include +#include + +#if defined(_WIN32) + +int socket_local_server(const char *name, int namespaceId, int type) +{ + errno = ENOSYS; + return -1; +} + +#else /* !_WIN32 */ + +#include +#include +#include +#include +#include + +#include "socket_local_unix.h" + +#define LISTEN_BACKLOG 4 + +/* Only the bottom bits are really the socket type; there are flags too. */ +#define SOCK_TYPE_MASK 0xf + +/** + * 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 */ +#if !defined(__linux__) + 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 namespaceId, int type) +{ + int err; + int s; + + s = socket(AF_LOCAL, type, 0); + if (s < 0) return -1; + + err = socket_local_server_bind(s, name, namespaceId); + + if (err < 0) { + close(s); + return -1; + } + + if ((type & SOCK_TYPE_MASK) == SOCK_STREAM) { + int ret; + + ret = listen(s, LISTEN_BACKLOG); + + if (ret < 0) { + close(s); + return -1; + } + } + + return s; +} + +#endif /* !_WIN32 */ diff --git a/libcutils/socket_network_client_unix.c b/libcutils/socket_network_client_unix.c deleted file mode 100644 index 1b87c49be..000000000 --- a/libcutils/socket_network_client_unix.c +++ /dev/null @@ -1,125 +0,0 @@ -/* -** 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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -static int toggle_O_NONBLOCK(int s) { - int flags = fcntl(s, F_GETFL); - if (flags == -1 || fcntl(s, F_SETFL, flags ^ O_NONBLOCK) == -1) { - close(s); - return -1; - } - return s; -} - -// Connect to the given host and port. -// 'timeout' is in seconds (0 for no timeout). -// Returns a file descriptor or -1 on error. -// On error, check *getaddrinfo_error (for use with gai_strerror) first; -// if that's 0, use errno instead. -int socket_network_client_timeout(const char* host, int port, int type, int timeout, - int* getaddrinfo_error) { - struct addrinfo hints; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = type; - - char port_str[16]; - snprintf(port_str, sizeof(port_str), "%d", port); - - struct addrinfo* addrs; - *getaddrinfo_error = getaddrinfo(host, port_str, &hints, &addrs); - if (*getaddrinfo_error != 0) { - return -1; - } - - int result = -1; - for (struct addrinfo* addr = addrs; addr != NULL; addr = addr->ai_next) { - // The Mac doesn't have SOCK_NONBLOCK. - int s = socket(addr->ai_family, type, addr->ai_protocol); - if (s == -1 || toggle_O_NONBLOCK(s) == -1) break; - - int rc = connect(s, addr->ai_addr, addr->ai_addrlen); - if (rc == 0) { - result = toggle_O_NONBLOCK(s); - break; - } else if (rc == -1 && errno != EINPROGRESS) { - close(s); - continue; - } - - fd_set r_set; - FD_ZERO(&r_set); - FD_SET(s, &r_set); - fd_set w_set = r_set; - - struct timeval ts; - ts.tv_sec = timeout; - ts.tv_usec = 0; - if ((rc = select(s + 1, &r_set, &w_set, NULL, (timeout != 0) ? &ts : NULL)) == -1) { - close(s); - break; - } - if (rc == 0) { // we had a timeout - errno = ETIMEDOUT; - close(s); - break; - } - - int error = 0; - socklen_t len = sizeof(error); - if (FD_ISSET(s, &r_set) || FD_ISSET(s, &w_set)) { - if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { - close(s); - break; - } - } else { - close(s); - break; - } - - if (error) { // check if we had a socket error - // TODO: Update the timeout. - errno = error; - close(s); - continue; - } - - result = toggle_O_NONBLOCK(s); - break; - } - - freeaddrinfo(addrs); - return result; -} - -int socket_network_client(const char* host, int port, int type) { - int getaddrinfo_error; - return socket_network_client_timeout(host, port, type, 0, &getaddrinfo_error); -} diff --git a/libcutils/socket_network_client_unix.cpp b/libcutils/socket_network_client_unix.cpp new file mode 100644 index 000000000..be3c53575 --- /dev/null +++ b/libcutils/socket_network_client_unix.cpp @@ -0,0 +1,125 @@ +/* +** 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +static int toggle_O_NONBLOCK(int s) { + int flags = fcntl(s, F_GETFL); + if (flags == -1 || fcntl(s, F_SETFL, flags ^ O_NONBLOCK) == -1) { + close(s); + return -1; + } + return s; +} + +// Connect to the given host and port. +// 'timeout' is in seconds (0 for no timeout). +// Returns a file descriptor or -1 on error. +// On error, check *getaddrinfo_error (for use with gai_strerror) first; +// if that's 0, use errno instead. +int socket_network_client_timeout(const char* host, int port, int type, int timeout, + int* getaddrinfo_error) { + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = type; + + char port_str[16]; + snprintf(port_str, sizeof(port_str), "%d", port); + + struct addrinfo* addrs; + *getaddrinfo_error = getaddrinfo(host, port_str, &hints, &addrs); + if (*getaddrinfo_error != 0) { + return -1; + } + + int result = -1; + for (struct addrinfo* addr = addrs; addr != NULL; addr = addr->ai_next) { + // The Mac doesn't have SOCK_NONBLOCK. + int s = socket(addr->ai_family, type, addr->ai_protocol); + if (s == -1 || toggle_O_NONBLOCK(s) == -1) break; + + int rc = connect(s, addr->ai_addr, addr->ai_addrlen); + if (rc == 0) { + result = toggle_O_NONBLOCK(s); + break; + } else if (rc == -1 && errno != EINPROGRESS) { + close(s); + continue; + } + + fd_set r_set; + FD_ZERO(&r_set); + FD_SET(s, &r_set); + fd_set w_set = r_set; + + struct timeval ts; + ts.tv_sec = timeout; + ts.tv_usec = 0; + if ((rc = select(s + 1, &r_set, &w_set, NULL, (timeout != 0) ? &ts : NULL)) == -1) { + close(s); + break; + } + if (rc == 0) { // we had a timeout + errno = ETIMEDOUT; + close(s); + break; + } + + int error = 0; + socklen_t len = sizeof(error); + if (FD_ISSET(s, &r_set) || FD_ISSET(s, &w_set)) { + if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { + close(s); + break; + } + } else { + close(s); + break; + } + + if (error) { // check if we had a socket error + // TODO: Update the timeout. + errno = error; + close(s); + continue; + } + + result = toggle_O_NONBLOCK(s); + break; + } + + freeaddrinfo(addrs); + return result; +} + +int socket_network_client(const char* host, int port, int type) { + int getaddrinfo_error; + return socket_network_client_timeout(host, port, type, 0, &getaddrinfo_error); +} diff --git a/libcutils/socket_network_client_windows.c b/libcutils/socket_network_client_windows.c deleted file mode 100644 index ab1a52f74..000000000 --- a/libcutils/socket_network_client_windows.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include - -extern bool initialize_windows_sockets(); - -SOCKET socket_network_client(const char* host, int port, int type) { - if (!initialize_windows_sockets()) { - return INVALID_SOCKET; - } - - // First resolve the host and port parameters into a usable network address. - struct addrinfo hints; - memset(&hints, 0, sizeof(hints)); - hints.ai_socktype = type; - - struct addrinfo* address = NULL; - char port_str[16]; - snprintf(port_str, sizeof(port_str), "%d", port); - if (getaddrinfo(host, port_str, &hints, &address) != 0 || address == NULL) { - if (address != NULL) { - freeaddrinfo(address); - } - return INVALID_SOCKET; - } - - // Now create and connect the socket. - SOCKET sock = socket(address->ai_family, address->ai_socktype, - address->ai_protocol); - if (sock == INVALID_SOCKET) { - freeaddrinfo(address); - return INVALID_SOCKET; - } - - if (connect(sock, address->ai_addr, address->ai_addrlen) == SOCKET_ERROR) { - closesocket(sock); - freeaddrinfo(address); - return INVALID_SOCKET; - } - - freeaddrinfo(address); - return sock; -} diff --git a/libcutils/socket_network_client_windows.cpp b/libcutils/socket_network_client_windows.cpp new file mode 100644 index 000000000..ab1a52f74 --- /dev/null +++ b/libcutils/socket_network_client_windows.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +extern bool initialize_windows_sockets(); + +SOCKET socket_network_client(const char* host, int port, int type) { + if (!initialize_windows_sockets()) { + return INVALID_SOCKET; + } + + // First resolve the host and port parameters into a usable network address. + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = type; + + struct addrinfo* address = NULL; + char port_str[16]; + snprintf(port_str, sizeof(port_str), "%d", port); + if (getaddrinfo(host, port_str, &hints, &address) != 0 || address == NULL) { + if (address != NULL) { + freeaddrinfo(address); + } + return INVALID_SOCKET; + } + + // Now create and connect the socket. + SOCKET sock = socket(address->ai_family, address->ai_socktype, + address->ai_protocol); + if (sock == INVALID_SOCKET) { + freeaddrinfo(address); + return INVALID_SOCKET; + } + + if (connect(sock, address->ai_addr, address->ai_addrlen) == SOCKET_ERROR) { + closesocket(sock); + freeaddrinfo(address); + return INVALID_SOCKET; + } + + freeaddrinfo(address); + return sock; +} diff --git a/libcutils/sockets_unix.cpp b/libcutils/sockets_unix.cpp index e91f35831..2849aa886 100644 --- a/libcutils/sockets_unix.cpp +++ b/libcutils/sockets_unix.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include + #define LOG_TAG "socket-unix" #include @@ -26,7 +28,6 @@ #include #include -#include #include #include "android_get_control_env.h" diff --git a/libcutils/sockets_windows.cpp b/libcutils/sockets_windows.cpp index 3064c70e5..3e49b85b4 100644 --- a/libcutils/sockets_windows.cpp +++ b/libcutils/sockets_windows.cpp @@ -37,7 +37,7 @@ // Both adb (1) and Chrome (2) purposefully avoid WSACleanup() with no issues. // (1) https://android.googlesource.com/platform/system/core.git/+/master/adb/sysdeps_win32.cpp // (2) https://code.google.com/p/chromium/codesearch#chromium/src/net/base/winsock_init.cc -extern "C" bool initialize_windows_sockets() { +bool initialize_windows_sockets() { // There's no harm in calling WSAStartup() multiple times but no benefit // either, we may as well skip it after the first. static bool init_success = false; diff --git a/libcutils/str_parms.c b/libcutils/str_parms.c deleted file mode 100644 index 8dafdedac..000000000 --- a/libcutils/str_parms.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright (C) 2011 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 "str_params" -//#define LOG_NDEBUG 0 - -#define _GNU_SOURCE 1 -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define UNUSED __attribute__((unused)) - -/* When an object is allocated but not freed in a function, - * because its ownership is released to other object like a hashmap, - * call RELEASE_OWNERSHIP to tell the clang analyzer and avoid - * false warnings about potential memory leak. - * For now, a "temporary" assignment to global variables - * is enough to confuse the clang static analyzer. - */ -#ifdef __clang_analyzer__ -static void *released_pointer; -#define RELEASE_OWNERSHIP(x) { released_pointer = x; released_pointer = 0; } -#else -#define RELEASE_OWNERSHIP(x) -#endif - -struct str_parms { - Hashmap *map; -}; - - -static bool str_eq(void *key_a, void *key_b) -{ - return !strcmp((const char *)key_a, (const char *)key_b); -} - -/* use djb hash unless we find it inadequate */ -#ifdef __clang__ -__attribute__((no_sanitize("integer"))) -#endif -static int str_hash_fn(void *str) -{ - uint32_t hash = 5381; - char *p; - - for (p = str; p && *p; p++) - hash = ((hash << 5) + hash) + *p; - return (int)hash; -} - -struct str_parms *str_parms_create(void) -{ - struct str_parms *str_parms; - - str_parms = calloc(1, sizeof(struct str_parms)); - if (!str_parms) - return NULL; - - str_parms->map = hashmapCreate(5, str_hash_fn, str_eq); - if (!str_parms->map) - goto err; - - return str_parms; - -err: - free(str_parms); - return NULL; -} - -struct remove_ctxt { - struct str_parms *str_parms; - const char *key; -}; - -static bool remove_pair(void *key, void *value, void *context) -{ - struct remove_ctxt *ctxt = context; - bool should_continue; - - /* - * - if key is not supplied, then we are removing all entries, - * so remove key and continue (i.e. return true) - * - if key is supplied and matches, then remove it and don't - * continue (return false). Otherwise, return true and keep searching - * for key. - * - */ - if (!ctxt->key) { - should_continue = true; - goto do_remove; - } else if (!strcmp(ctxt->key, key)) { - should_continue = false; - goto do_remove; - } - - return true; - -do_remove: - hashmapRemove(ctxt->str_parms->map, key); - free(key); - free(value); - return should_continue; -} - -void str_parms_del(struct str_parms *str_parms, const char *key) -{ - struct remove_ctxt ctxt = { - .str_parms = str_parms, - .key = key, - }; - hashmapForEach(str_parms->map, remove_pair, &ctxt); -} - -void str_parms_destroy(struct str_parms *str_parms) -{ - struct remove_ctxt ctxt = { - .str_parms = str_parms, - }; - - hashmapForEach(str_parms->map, remove_pair, &ctxt); - hashmapFree(str_parms->map); - free(str_parms); -} - -struct str_parms *str_parms_create_str(const char *_string) -{ - struct str_parms *str_parms; - char *str; - char *kvpair; - char *tmpstr; - int items = 0; - - str_parms = str_parms_create(); - if (!str_parms) - goto err_create_str_parms; - - str = strdup(_string); - if (!str) - goto err_strdup; - - ALOGV("%s: source string == '%s'\n", __func__, _string); - - kvpair = strtok_r(str, ";", &tmpstr); - while (kvpair && *kvpair) { - char *eq = strchr(kvpair, '='); /* would love strchrnul */ - char *value; - char *key; - void *old_val; - - if (eq == kvpair) - goto next_pair; - - if (eq) { - key = strndup(kvpair, eq - kvpair); - if (*(++eq)) - value = strdup(eq); - else - value = strdup(""); - } else { - key = strdup(kvpair); - value = strdup(""); - } - - /* if we replaced a value, free it */ - old_val = hashmapPut(str_parms->map, key, value); - RELEASE_OWNERSHIP(value); - if (old_val) { - free(old_val); - free(key); - } else { - RELEASE_OWNERSHIP(key); - } - - items++; -next_pair: - kvpair = strtok_r(NULL, ";", &tmpstr); - } - - if (!items) - ALOGV("%s: no items found in string\n", __func__); - - free(str); - - return str_parms; - -err_strdup: - str_parms_destroy(str_parms); -err_create_str_parms: - return NULL; -} - -int str_parms_add_str(struct str_parms *str_parms, const char *key, - const char *value) -{ - void *tmp_key = NULL; - void *tmp_val = NULL; - void *old_val = NULL; - - // strdup and hashmapPut both set errno on failure. - // Set errno to 0 so we can recognize whether anything went wrong. - int saved_errno = errno; - errno = 0; - - tmp_key = strdup(key); - if (tmp_key == NULL) { - goto clean_up; - } - - tmp_val = strdup(value); - if (tmp_val == NULL) { - goto clean_up; - } - - old_val = hashmapPut(str_parms->map, tmp_key, tmp_val); - if (old_val == NULL) { - // Did hashmapPut fail? - if (errno == ENOMEM) { - goto clean_up; - } - // For new keys, hashmap takes ownership of tmp_key and tmp_val. - RELEASE_OWNERSHIP(tmp_key); - RELEASE_OWNERSHIP(tmp_val); - tmp_key = tmp_val = NULL; - } else { - // For existing keys, hashmap takes ownership of tmp_val. - // (It also gives up ownership of old_val.) - RELEASE_OWNERSHIP(tmp_val); - tmp_val = NULL; - } - -clean_up: - free(tmp_key); - free(tmp_val); - free(old_val); - int result = -errno; - errno = saved_errno; - return result; -} - -int str_parms_add_int(struct str_parms *str_parms, const char *key, int value) -{ - char val_str[12]; - int ret; - - ret = snprintf(val_str, sizeof(val_str), "%d", value); - if (ret < 0) - return -EINVAL; - - ret = str_parms_add_str(str_parms, key, val_str); - return ret; -} - -int str_parms_add_float(struct str_parms *str_parms, const char *key, - float value) -{ - char val_str[23]; - int ret; - - ret = snprintf(val_str, sizeof(val_str), "%.10f", value); - if (ret < 0) - return -EINVAL; - - ret = str_parms_add_str(str_parms, key, val_str); - return ret; -} - -int str_parms_has_key(struct str_parms *str_parms, const char *key) { - return hashmapGet(str_parms->map, (void *)key) != NULL; -} - -int str_parms_get_str(struct str_parms *str_parms, const char *key, char *val, - int len) -{ - char *value; - - value = hashmapGet(str_parms->map, (void *)key); - if (value) - return strlcpy(val, value, len); - - return -ENOENT; -} - -int str_parms_get_int(struct str_parms *str_parms, const char *key, int *val) -{ - char *value; - char *end; - - value = hashmapGet(str_parms->map, (void *)key); - if (!value) - return -ENOENT; - - *val = (int)strtol(value, &end, 0); - if (*value != '\0' && *end == '\0') - return 0; - - return -EINVAL; -} - -int str_parms_get_float(struct str_parms *str_parms, const char *key, - float *val) -{ - float out; - char *value; - char *end; - - value = hashmapGet(str_parms->map, (void *)key); - if (!value) - return -ENOENT; - - out = strtof(value, &end); - if (*value == '\0' || *end != '\0') - return -EINVAL; - - *val = out; - return 0; -} - -static bool combine_strings(void *key, void *value, void *context) -{ - char **old_str = context; - char *new_str; - int ret; - - ret = asprintf(&new_str, "%s%s%s=%s", - *old_str ? *old_str : "", - *old_str ? ";" : "", - (char *)key, - (char *)value); - if (*old_str) - free(*old_str); - - if (ret >= 0) { - *old_str = new_str; - return true; - } - - *old_str = NULL; - return false; -} - -char *str_parms_to_str(struct str_parms *str_parms) -{ - char *str = NULL; - - if (hashmapSize(str_parms->map) > 0) - hashmapForEach(str_parms->map, combine_strings, &str); - else - str = strdup(""); - return str; -} - -static bool dump_entry(void *key, void *value, void *context UNUSED) -{ - ALOGI("key: '%s' value: '%s'\n", (char *)key, (char *)value); - return true; -} - -void str_parms_dump(struct str_parms *str_parms) -{ - hashmapForEach(str_parms->map, dump_entry, str_parms); -} diff --git a/libcutils/str_parms.cpp b/libcutils/str_parms.cpp new file mode 100644 index 000000000..139d62f6d --- /dev/null +++ b/libcutils/str_parms.cpp @@ -0,0 +1,376 @@ +/* + * Copyright (C) 2011 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 + +#define LOG_TAG "str_params" +//#define LOG_NDEBUG 0 + +#define _GNU_SOURCE 1 +#include +#include +#include +#include +#include + +#include +#include +#include + +#define UNUSED __attribute__((unused)) + +/* When an object is allocated but not freed in a function, + * because its ownership is released to other object like a hashmap, + * call RELEASE_OWNERSHIP to tell the clang analyzer and avoid + * false warnings about potential memory leak. + * For now, a "temporary" assignment to global variables + * is enough to confuse the clang static analyzer. + */ +#ifdef __clang_analyzer__ +static void *released_pointer; +#define RELEASE_OWNERSHIP(x) { released_pointer = x; released_pointer = 0; } +#else +#define RELEASE_OWNERSHIP(x) +#endif + +struct str_parms { + Hashmap *map; +}; + + +static bool str_eq(void *key_a, void *key_b) +{ + return !strcmp((const char *)key_a, (const char *)key_b); +} + +/* use djb hash unless we find it inadequate */ +#ifdef __clang__ +__attribute__((no_sanitize("integer"))) +#endif +static int str_hash_fn(void *str) +{ + uint32_t hash = 5381; + + for (char* p = static_cast(str); p && *p; p++) + hash = ((hash << 5) + hash) + *p; + return (int)hash; +} + +struct str_parms *str_parms_create(void) +{ + str_parms* s = static_cast(calloc(1, sizeof(str_parms))); + if (!s) return NULL; + + s->map = hashmapCreate(5, str_hash_fn, str_eq); + if (!s->map) { + free(s); + return NULL; + } + + return s; +} + +struct remove_ctxt { + struct str_parms *str_parms; + const char *key; +}; + +static bool remove_pair(void *key, void *value, void *context) +{ + remove_ctxt* ctxt = static_cast(context); + bool should_continue; + + /* + * - if key is not supplied, then we are removing all entries, + * so remove key and continue (i.e. return true) + * - if key is supplied and matches, then remove it and don't + * continue (return false). Otherwise, return true and keep searching + * for key. + * + */ + if (!ctxt->key) { + should_continue = true; + goto do_remove; + } else if (!strcmp(ctxt->key, static_cast(key))) { + should_continue = false; + goto do_remove; + } + + return true; + +do_remove: + hashmapRemove(ctxt->str_parms->map, key); + free(key); + free(value); + return should_continue; +} + +void str_parms_del(struct str_parms *str_parms, const char *key) +{ + struct remove_ctxt ctxt = { + .str_parms = str_parms, + .key = key, + }; + hashmapForEach(str_parms->map, remove_pair, &ctxt); +} + +void str_parms_destroy(struct str_parms *str_parms) +{ + struct remove_ctxt ctxt = { + .str_parms = str_parms, + }; + + hashmapForEach(str_parms->map, remove_pair, &ctxt); + hashmapFree(str_parms->map); + free(str_parms); +} + +struct str_parms *str_parms_create_str(const char *_string) +{ + struct str_parms *str_parms; + char *str; + char *kvpair; + char *tmpstr; + int items = 0; + + str_parms = str_parms_create(); + if (!str_parms) + goto err_create_str_parms; + + str = strdup(_string); + if (!str) + goto err_strdup; + + ALOGV("%s: source string == '%s'\n", __func__, _string); + + kvpair = strtok_r(str, ";", &tmpstr); + while (kvpair && *kvpair) { + char *eq = strchr(kvpair, '='); /* would love strchrnul */ + char *value; + char *key; + void *old_val; + + if (eq == kvpair) + goto next_pair; + + if (eq) { + key = strndup(kvpair, eq - kvpair); + if (*(++eq)) + value = strdup(eq); + else + value = strdup(""); + } else { + key = strdup(kvpair); + value = strdup(""); + } + + /* if we replaced a value, free it */ + old_val = hashmapPut(str_parms->map, key, value); + RELEASE_OWNERSHIP(value); + if (old_val) { + free(old_val); + free(key); + } else { + RELEASE_OWNERSHIP(key); + } + + items++; +next_pair: + kvpair = strtok_r(NULL, ";", &tmpstr); + } + + if (!items) + ALOGV("%s: no items found in string\n", __func__); + + free(str); + + return str_parms; + +err_strdup: + str_parms_destroy(str_parms); +err_create_str_parms: + return NULL; +} + +int str_parms_add_str(struct str_parms *str_parms, const char *key, + const char *value) +{ + void *tmp_key = NULL; + void *tmp_val = NULL; + void *old_val = NULL; + + // strdup and hashmapPut both set errno on failure. + // Set errno to 0 so we can recognize whether anything went wrong. + int saved_errno = errno; + errno = 0; + + tmp_key = strdup(key); + if (tmp_key == NULL) { + goto clean_up; + } + + tmp_val = strdup(value); + if (tmp_val == NULL) { + goto clean_up; + } + + old_val = hashmapPut(str_parms->map, tmp_key, tmp_val); + if (old_val == NULL) { + // Did hashmapPut fail? + if (errno == ENOMEM) { + goto clean_up; + } + // For new keys, hashmap takes ownership of tmp_key and tmp_val. + RELEASE_OWNERSHIP(tmp_key); + RELEASE_OWNERSHIP(tmp_val); + tmp_key = tmp_val = NULL; + } else { + // For existing keys, hashmap takes ownership of tmp_val. + // (It also gives up ownership of old_val.) + RELEASE_OWNERSHIP(tmp_val); + tmp_val = NULL; + } + +clean_up: + free(tmp_key); + free(tmp_val); + free(old_val); + int result = -errno; + errno = saved_errno; + return result; +} + +int str_parms_add_int(struct str_parms *str_parms, const char *key, int value) +{ + char val_str[12]; + int ret; + + ret = snprintf(val_str, sizeof(val_str), "%d", value); + if (ret < 0) + return -EINVAL; + + ret = str_parms_add_str(str_parms, key, val_str); + return ret; +} + +int str_parms_add_float(struct str_parms *str_parms, const char *key, + float value) +{ + char val_str[23]; + int ret; + + ret = snprintf(val_str, sizeof(val_str), "%.10f", value); + if (ret < 0) + return -EINVAL; + + ret = str_parms_add_str(str_parms, key, val_str); + return ret; +} + +int str_parms_has_key(struct str_parms *str_parms, const char *key) { + return hashmapGet(str_parms->map, (void *)key) != NULL; +} + +int str_parms_get_str(struct str_parms *str_parms, const char *key, char *val, + int len) +{ + // TODO: hashmapGet should take a const* key. + char* value = static_cast(hashmapGet(str_parms->map, (void*)key)); + if (value) + return strlcpy(val, value, len); + + return -ENOENT; +} + +int str_parms_get_int(struct str_parms *str_parms, const char *key, int *val) +{ + char *end; + + // TODO: hashmapGet should take a const* key. + char* value = static_cast(hashmapGet(str_parms->map, (void*)key)); + if (!value) + return -ENOENT; + + *val = (int)strtol(value, &end, 0); + if (*value != '\0' && *end == '\0') + return 0; + + return -EINVAL; +} + +int str_parms_get_float(struct str_parms *str_parms, const char *key, + float *val) +{ + float out; + char *end; + + // TODO: hashmapGet should take a const* key. + char* value = static_cast(hashmapGet(str_parms->map, (void*)(key))); + if (!value) + return -ENOENT; + + out = strtof(value, &end); + if (*value == '\0' || *end != '\0') + return -EINVAL; + + *val = out; + return 0; +} + +static bool combine_strings(void *key, void *value, void *context) +{ + char** old_str = static_cast(context); + char *new_str; + int ret; + + ret = asprintf(&new_str, "%s%s%s=%s", + *old_str ? *old_str : "", + *old_str ? ";" : "", + (char *)key, + (char *)value); + if (*old_str) + free(*old_str); + + if (ret >= 0) { + *old_str = new_str; + return true; + } + + *old_str = NULL; + return false; +} + +char *str_parms_to_str(struct str_parms *str_parms) +{ + char *str = NULL; + + if (hashmapSize(str_parms->map) > 0) + hashmapForEach(str_parms->map, combine_strings, &str); + else + str = strdup(""); + return str; +} + +static bool dump_entry(void *key, void *value, void *context UNUSED) +{ + ALOGI("key: '%s' value: '%s'\n", (char *)key, (char *)value); + return true; +} + +void str_parms_dump(struct str_parms *str_parms) +{ + hashmapForEach(str_parms->map, dump_entry, str_parms); +} diff --git a/libcutils/strdup16to8.c b/libcutils/strdup16to8.c deleted file mode 100644 index 4dc987e41..000000000 --- a/libcutils/strdup16to8.c +++ /dev/null @@ -1,171 +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 /* for SIZE_MAX */ - -#include -#include -#include - - -/** - * 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; - - /* A small note on integer overflow. The result can - * potentially be as big as 3*len, which will overflow - * for len > SIZE_MAX/3. - * - * Moreover, the result of a strnlen16to8 is typically used - * to allocate a destination buffer to strncpy16to8 which - * requires one more byte to terminate the UTF-8 copy, and - * this is generally done by careless users by incrementing - * the result without checking for integer overflows, e.g.: - * - * dst = malloc(strnlen16to8(utf16,len)+1) - * - * Due to this, the following code will try to detect - * overflows, and never return more than (SIZE_MAX-1) - * when it detects one. A careless user will try to malloc - * SIZE_MAX bytes, which will return NULL which can at least - * be detected appropriately. - * - * As far as I know, this function is only used by strndup16(), - * but better be safe than sorry. - */ - - /* Fast path for the usual case where 3*len is < SIZE_MAX-1. - */ - if (len < (SIZE_MAX-1)/3) { - while (len != 0) { - len--; - unsigned int uic = *utf16Str++; - - if (uic > 0x07ff) - utf8Len += 3; - else if (uic > 0x7f || uic == 0) - utf8Len += 2; - else - utf8Len++; - } - return utf8Len; - } - - /* The slower but paranoid version */ - while (len != 0) { - len--; - unsigned int uic = *utf16Str++; - size_t utf8Cur = utf8Len; - - if (uic > 0x07ff) - utf8Len += 3; - else if (uic > 0x7f || uic == 0) - utf8Len += 2; - else - utf8Len++; - - if (utf8Len < utf8Cur) /* overflow detected */ - return SIZE_MAX-1; - } - - /* don't return SIZE_MAX to avoid common user bug */ - if (utf8Len == SIZE_MAX) - utf8Len = SIZE_MAX-1; - - 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; - - /* Note on overflows: We assume the user did check the result of - * strnlen16to8() properly or at a minimum checked the result of - * its malloc(SIZE_MAX) in case of overflow. - */ - while (len != 0) { - 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. - * - */ -char * strndup16to8 (const char16_t* s, size_t n) -{ - char* ret; - size_t len; - - if (s == NULL) { - return NULL; - } - - len = strnlen16to8(s, n); - - /* We are paranoid, and we check for SIZE_MAX-1 - * too since it is an overflow value for our - * strnlen16to8 implementation. - */ - if (len >= SIZE_MAX-1) - return NULL; - - ret = malloc(len + 1); - if (ret == NULL) - return NULL; - - strncpy16to8 (ret, s, n); - - return ret; -} diff --git a/libcutils/strdup16to8.cpp b/libcutils/strdup16to8.cpp new file mode 100644 index 000000000..d89181e14 --- /dev/null +++ b/libcutils/strdup16to8.cpp @@ -0,0 +1,168 @@ +/* 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 + +#include +#include /* for SIZE_MAX */ +#include + + +/** + * 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; + + /* A small note on integer overflow. The result can + * potentially be as big as 3*len, which will overflow + * for len > SIZE_MAX/3. + * + * Moreover, the result of a strnlen16to8 is typically used + * to allocate a destination buffer to strncpy16to8 which + * requires one more byte to terminate the UTF-8 copy, and + * this is generally done by careless users by incrementing + * the result without checking for integer overflows, e.g.: + * + * dst = malloc(strnlen16to8(utf16,len)+1) + * + * Due to this, the following code will try to detect + * overflows, and never return more than (SIZE_MAX-1) + * when it detects one. A careless user will try to malloc + * SIZE_MAX bytes, which will return NULL which can at least + * be detected appropriately. + * + * As far as I know, this function is only used by strndup16(), + * but better be safe than sorry. + */ + + /* Fast path for the usual case where 3*len is < SIZE_MAX-1. + */ + if (len < (SIZE_MAX-1)/3) { + while (len != 0) { + len--; + unsigned int uic = *utf16Str++; + + if (uic > 0x07ff) + utf8Len += 3; + else if (uic > 0x7f || uic == 0) + utf8Len += 2; + else + utf8Len++; + } + return utf8Len; + } + + /* The slower but paranoid version */ + while (len != 0) { + len--; + unsigned int uic = *utf16Str++; + size_t utf8Cur = utf8Len; + + if (uic > 0x07ff) + utf8Len += 3; + else if (uic > 0x7f || uic == 0) + utf8Len += 2; + else + utf8Len++; + + if (utf8Len < utf8Cur) /* overflow detected */ + return SIZE_MAX-1; + } + + /* don't return SIZE_MAX to avoid common user bug */ + if (utf8Len == SIZE_MAX) + utf8Len = SIZE_MAX-1; + + 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; + + /* Note on overflows: We assume the user did check the result of + * strnlen16to8() properly or at a minimum checked the result of + * its malloc(SIZE_MAX) in case of overflow. + */ + while (len != 0) { + 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. + * + */ +char * strndup16to8 (const char16_t* s, size_t n) +{ + if (s == NULL) { + return NULL; + } + + size_t len = strnlen16to8(s, n); + + /* We are paranoid, and we check for SIZE_MAX-1 + * too since it is an overflow value for our + * strnlen16to8 implementation. + */ + if (len >= SIZE_MAX-1) + return NULL; + + char* ret = static_cast(malloc(len + 1)); + if (ret == NULL) + return NULL; + + strncpy16to8 (ret, s, n); + + return ret; +} diff --git a/libcutils/strdup8to16.c b/libcutils/strdup8to16.c deleted file mode 100644 index c23cf8b9a..000000000 --- a/libcutils/strdup8to16.c +++ /dev/null @@ -1,214 +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 -#include -#include -#include - -/* 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); - - // fail on overflow - if (len && SIZE_MAX/len < sizeof(char16_t)) - return NULL; - - // 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/strdup8to16.cpp b/libcutils/strdup8to16.cpp new file mode 100644 index 000000000..d1e51b9ca --- /dev/null +++ b/libcutils/strdup8to16.cpp @@ -0,0 +1,215 @@ +/* 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 + +#include +#include +#include + +/* 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); + + // fail on overflow + if (len && SIZE_MAX/len < sizeof(char16_t)) + return NULL; + + // 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 unsigned 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/tests/trace-dev_test.cpp b/libcutils/tests/trace-dev_test.cpp index edf981b39..f8d4f0064 100644 --- a/libcutils/tests/trace-dev_test.cpp +++ b/libcutils/tests/trace-dev_test.cpp @@ -25,7 +25,7 @@ #include #include -#include "../trace-dev.c" +#include "../trace-dev.cpp" class TraceDevTest : public ::testing::Test { protected: diff --git a/libcutils/threads.c b/libcutils/threads.c deleted file mode 100644 index 4bae39e0f..000000000 --- a/libcutils/threads.c +++ /dev/null @@ -1,111 +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/threads.h" - -// For gettid. -#if defined(__APPLE__) -#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED -#include -#include -#include -#include -#include -#elif defined(__linux__) && !defined(__ANDROID__) -#include -#include -#elif defined(_WIN32) -#include -#endif - -// No definition needed for Android because we'll just pick up bionic's copy. -#ifndef __ANDROID__ -pid_t gettid() { -#if defined(__APPLE__) - uint64_t tid; - pthread_threadid_np(NULL, &tid); - return tid; -#elif defined(__linux__) - return syscall(__NR_gettid); -#elif defined(_WIN32) - return GetCurrentThreadId(); -#endif -} -#endif // __ANDROID__ - -#if !defined(_WIN32) - -void* thread_store_get( thread_store_t* store ) -{ - 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 ); -} - -#else /* !defined(_WIN32) */ -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 /* !defined(_WIN32) */ diff --git a/libcutils/threads.cpp b/libcutils/threads.cpp new file mode 100644 index 000000000..beea8bdfc --- /dev/null +++ b/libcutils/threads.cpp @@ -0,0 +1,111 @@ +/* +** 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 + +// For gettid. +#if defined(__APPLE__) +#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED +#include +#include +#include +#include +#include +#elif defined(__linux__) && !defined(__ANDROID__) +#include +#include +#elif defined(_WIN32) +#include +#endif + +// No definition needed for Android because we'll just pick up bionic's copy. +#ifndef __ANDROID__ +pid_t gettid() { +#if defined(__APPLE__) + uint64_t tid; + pthread_threadid_np(NULL, &tid); + return tid; +#elif defined(__linux__) + return syscall(__NR_gettid); +#elif defined(_WIN32) + return GetCurrentThreadId(); +#endif +} +#endif // __ANDROID__ + +#if !defined(_WIN32) + +void* thread_store_get( thread_store_t* store ) +{ + 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 ); +} + +#else /* !defined(_WIN32) */ +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 /* !defined(_WIN32) */ diff --git a/libcutils/trace-container.c b/libcutils/trace-container.c deleted file mode 100644 index 03e91b1f2..000000000 --- a/libcutils/trace-container.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "trace-dev.inc" - -#include -#include -#include - -/** - * For tracing in container, tags are written into a socket - * instead of ftrace. Additional data is appended so we need extra space. - */ -#define CONTAINER_ATRACE_MESSAGE_LENGTH (ATRACE_MESSAGE_LENGTH + 512) - -static pthread_once_t atrace_once_control = PTHREAD_ONCE_INIT; - -// Variables used for tracing in container with socket. -// Note that we need to manually close and reopen socket when Zygote is forking. This requires -// writing and closing sockets on multiple threads. A rwlock is used for avoiding concurrent -// operation on the file descriptor. -static bool atrace_use_container_sock = false; -static int atrace_container_sock_fd = -1; -static pthread_mutex_t atrace_enabling_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_rwlock_t atrace_container_sock_rwlock = PTHREAD_RWLOCK_INITIALIZER; - -static bool atrace_init_container_sock() -{ - pthread_rwlock_wrlock(&atrace_container_sock_rwlock); - atrace_container_sock_fd = - socket_local_client("trace", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET); - if (atrace_container_sock_fd < 0) { - ALOGE("Error opening container trace socket: %s (%d)", strerror(errno), errno); - } - pthread_rwlock_unlock(&atrace_container_sock_rwlock); - return atrace_container_sock_fd != -1; -} - -static void atrace_close_container_sock() -{ - pthread_rwlock_wrlock(&atrace_container_sock_rwlock); - if (atrace_container_sock_fd != -1) close(atrace_container_sock_fd); - atrace_container_sock_fd = -1; - pthread_rwlock_unlock(&atrace_container_sock_rwlock); -} - -// Set whether tracing is enabled in this process. This is used to prevent -// the Zygote process from tracing. We need to close the socket in the container when tracing is -// disabled, and reopen it again after Zygote forking. -void atrace_set_tracing_enabled(bool enabled) -{ - pthread_mutex_lock(&atrace_enabling_mutex); - if (atrace_use_container_sock) { - bool already_enabled = atomic_load_explicit(&atrace_is_enabled, memory_order_acquire); - if (enabled && !already_enabled) { - // Trace was disabled previously. Re-initialize container socket. - atrace_init_container_sock(); - } else if (!enabled && already_enabled) { - // Trace was enabled previously. Close container socket. - atrace_close_container_sock(); - } - } - atomic_store_explicit(&atrace_is_enabled, enabled, memory_order_release); - pthread_mutex_unlock(&atrace_enabling_mutex); - atrace_update_tags(); -} - -static void atrace_init_once() -{ - atrace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_WRONLY | O_CLOEXEC); - if (atrace_marker_fd < 0) { - // We're in container, ftrace may be disabled. In such case, we use the - // socket to write trace event. - - // Protect the initialization of container socket from - // atrace_set_tracing_enabled. - pthread_mutex_lock(&atrace_enabling_mutex); - atrace_use_container_sock = true; - bool success = false; - if (atomic_load_explicit(&atrace_is_enabled, memory_order_acquire)) { - success = atrace_init_container_sock(); - } - pthread_mutex_unlock(&atrace_enabling_mutex); - - if (!success) { - atrace_enabled_tags = 0; - goto done; - } - } - atrace_enabled_tags = atrace_get_property(); - -done: - atomic_store_explicit(&atrace_is_ready, true, memory_order_release); -} - -void atrace_setup() -{ - pthread_once(&atrace_once_control, atrace_init_once); -} - -static inline uint64_t gettime(clockid_t clk_id) -{ - struct timespec ts; - clock_gettime(clk_id, &ts); - return ts.tv_sec * 1000000 + ts.tv_nsec / 1000; -} - -// Write trace events to container trace file. Note that we need to amend tid and time information -// here comparing to normal ftrace, where those informations are added by kernel. -#define WRITE_MSG_IN_CONTAINER_LOCKED(ph, sep_before_name, value_format, name, value) { \ - char buf[CONTAINER_ATRACE_MESSAGE_LENGTH]; \ - int pid = getpid(); \ - int tid = gettid(); \ - uint64_t ts = gettime(CLOCK_MONOTONIC); \ - uint64_t tts = gettime(CLOCK_THREAD_CPUTIME_ID); \ - int len = snprintf( \ - buf, sizeof(buf), \ - ph "|%d|%d|%" PRIu64 "|%" PRIu64 sep_before_name "%s" value_format, \ - pid, tid, ts, tts, name, value); \ - if (len >= (int) sizeof(buf)) { \ - int name_len = strlen(name) - (len - sizeof(buf)) - 1; \ - /* Truncate the name to make the message fit. */ \ - if (name_len > 0) { \ - ALOGW("Truncated name in %s: %s\n", __FUNCTION__, name); \ - len = snprintf( \ - buf, sizeof(buf), \ - ph "|%d|%d|%" PRIu64 "|%" PRIu64 sep_before_name "%.*s" value_format, \ - pid, tid, ts, tts, name_len, name, value); \ - } else { \ - /* Data is still too long. Drop it. */ \ - ALOGW("Data is too long in %s: %s\n", __FUNCTION__, name); \ - len = 0; \ - } \ - } \ - if (len > 0) { \ - write(atrace_container_sock_fd, buf, len); \ - } \ -} - -#define WRITE_MSG_IN_CONTAINER(ph, sep_before_name, value_format, name, value) { \ - pthread_rwlock_rdlock(&atrace_container_sock_rwlock); \ - if (atrace_container_sock_fd != -1) { \ - WRITE_MSG_IN_CONTAINER_LOCKED(ph, sep_before_name, value_format, name, value); \ - } \ - pthread_rwlock_unlock(&atrace_container_sock_rwlock); \ -} - -void atrace_begin_body(const char* name) -{ - if (CC_LIKELY(atrace_use_container_sock)) { - WRITE_MSG_IN_CONTAINER("B", "|", "%s", name, ""); - return; - } - - if (atrace_marker_fd < 0) return; - - WRITE_MSG("B|%d|", "%s", name, ""); -} - -void atrace_end_body() -{ - if (CC_LIKELY(atrace_use_container_sock)) { - WRITE_MSG_IN_CONTAINER("E", "", "%s", "", ""); - return; - } - - if (atrace_marker_fd < 0) return; - - WRITE_MSG("E|%d", "%s", "", ""); -} - -void atrace_async_begin_body(const char* name, int32_t cookie) -{ - if (CC_LIKELY(atrace_use_container_sock)) { - WRITE_MSG_IN_CONTAINER("S", "|", "|%d", name, cookie); - return; - } - - if (atrace_marker_fd < 0) return; - - WRITE_MSG("S|%d|", "|%" PRId32, name, cookie); -} - -void atrace_async_end_body(const char* name, int32_t cookie) -{ - if (CC_LIKELY(atrace_use_container_sock)) { - WRITE_MSG_IN_CONTAINER("F", "|", "|%d", name, cookie); - return; - } - - if (atrace_marker_fd < 0) return; - - WRITE_MSG("F|%d|", "|%" PRId32, name, cookie); -} - -void atrace_int_body(const char* name, int32_t value) -{ - if (CC_LIKELY(atrace_use_container_sock)) { - WRITE_MSG_IN_CONTAINER("C", "|", "|%" PRId32, name, value); - return; - } - - if (atrace_marker_fd < 0) return; - - WRITE_MSG("C|%d|", "|%" PRId32, name, value); -} - -void atrace_int64_body(const char* name, int64_t value) -{ - if (CC_LIKELY(atrace_use_container_sock)) { - WRITE_MSG_IN_CONTAINER("C", "|", "|%" PRId64, name, value); - return; - } - - if (atrace_marker_fd < 0) return; - - WRITE_MSG("C|%d|", "|%" PRId64, name, value); -} diff --git a/libcutils/trace-container.cpp b/libcutils/trace-container.cpp new file mode 100644 index 000000000..d981f8fa5 --- /dev/null +++ b/libcutils/trace-container.cpp @@ -0,0 +1,233 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "trace-dev.inc" + +#include +#include +#include + +/** + * For tracing in container, tags are written into a socket + * instead of ftrace. Additional data is appended so we need extra space. + */ +#define CONTAINER_ATRACE_MESSAGE_LENGTH (ATRACE_MESSAGE_LENGTH + 512) + +static pthread_once_t atrace_once_control = PTHREAD_ONCE_INIT; + +// Variables used for tracing in container with socket. +// Note that we need to manually close and reopen socket when Zygote is forking. This requires +// writing and closing sockets on multiple threads. A rwlock is used for avoiding concurrent +// operation on the file descriptor. +static bool atrace_use_container_sock = false; +static int atrace_container_sock_fd = -1; +static pthread_mutex_t atrace_enabling_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_rwlock_t atrace_container_sock_rwlock = PTHREAD_RWLOCK_INITIALIZER; + +static bool atrace_init_container_sock() +{ + pthread_rwlock_wrlock(&atrace_container_sock_rwlock); + atrace_container_sock_fd = + socket_local_client("trace", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET); + if (atrace_container_sock_fd < 0) { + ALOGE("Error opening container trace socket: %s (%d)", strerror(errno), errno); + } + pthread_rwlock_unlock(&atrace_container_sock_rwlock); + return atrace_container_sock_fd != -1; +} + +static void atrace_close_container_sock() +{ + pthread_rwlock_wrlock(&atrace_container_sock_rwlock); + if (atrace_container_sock_fd != -1) close(atrace_container_sock_fd); + atrace_container_sock_fd = -1; + pthread_rwlock_unlock(&atrace_container_sock_rwlock); +} + +// Set whether tracing is enabled in this process. This is used to prevent +// the Zygote process from tracing. We need to close the socket in the container when tracing is +// disabled, and reopen it again after Zygote forking. +void atrace_set_tracing_enabled(bool enabled) +{ + pthread_mutex_lock(&atrace_enabling_mutex); + if (atrace_use_container_sock) { + bool already_enabled = atomic_load_explicit(&atrace_is_enabled, memory_order_acquire); + if (enabled && !already_enabled) { + // Trace was disabled previously. Re-initialize container socket. + atrace_init_container_sock(); + } else if (!enabled && already_enabled) { + // Trace was enabled previously. Close container socket. + atrace_close_container_sock(); + } + } + atomic_store_explicit(&atrace_is_enabled, enabled, memory_order_release); + pthread_mutex_unlock(&atrace_enabling_mutex); + atrace_update_tags(); +} + +static void atrace_init_once() +{ + atrace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_WRONLY | O_CLOEXEC); + if (atrace_marker_fd < 0) { + // We're in container, ftrace may be disabled. In such case, we use the + // socket to write trace event. + + // Protect the initialization of container socket from + // atrace_set_tracing_enabled. + pthread_mutex_lock(&atrace_enabling_mutex); + atrace_use_container_sock = true; + bool success = false; + if (atomic_load_explicit(&atrace_is_enabled, memory_order_acquire)) { + success = atrace_init_container_sock(); + } + pthread_mutex_unlock(&atrace_enabling_mutex); + + if (!success) { + atrace_enabled_tags = 0; + goto done; + } + } + atrace_enabled_tags = atrace_get_property(); + +done: + atomic_store_explicit(&atrace_is_ready, true, memory_order_release); +} + +void atrace_setup() +{ + pthread_once(&atrace_once_control, atrace_init_once); +} + +static inline uint64_t gettime(clockid_t clk_id) +{ + struct timespec ts; + clock_gettime(clk_id, &ts); + return ts.tv_sec * 1000000 + ts.tv_nsec / 1000; +} + +// Write trace events to container trace file. Note that we need to amend tid and time information +// here comparing to normal ftrace, where those informations are added by kernel. +#define WRITE_MSG_IN_CONTAINER_LOCKED(ph, sep_before_name, value_format, name, value) { \ + char buf[CONTAINER_ATRACE_MESSAGE_LENGTH]; \ + int pid = getpid(); \ + int tid = gettid(); \ + uint64_t ts = gettime(CLOCK_MONOTONIC); \ + uint64_t tts = gettime(CLOCK_THREAD_CPUTIME_ID); \ + int len = snprintf( \ + buf, sizeof(buf), \ + ph "|%d|%d|%" PRIu64 "|%" PRIu64 sep_before_name "%s" value_format, \ + pid, tid, ts, tts, name, value); \ + if (len >= (int) sizeof(buf)) { \ + int name_len = strlen(name) - (len - sizeof(buf)) - 1; \ + /* Truncate the name to make the message fit. */ \ + if (name_len > 0) { \ + ALOGW("Truncated name in %s: %s\n", __FUNCTION__, name); \ + len = snprintf( \ + buf, sizeof(buf), \ + ph "|%d|%d|%" PRIu64 "|%" PRIu64 sep_before_name "%.*s" value_format, \ + pid, tid, ts, tts, name_len, name, value); \ + } else { \ + /* Data is still too long. Drop it. */ \ + ALOGW("Data is too long in %s: %s\n", __FUNCTION__, name); \ + len = 0; \ + } \ + } \ + if (len > 0) { \ + write(atrace_container_sock_fd, buf, len); \ + } \ +} + +#define WRITE_MSG_IN_CONTAINER(ph, sep_before_name, value_format, name, value) { \ + pthread_rwlock_rdlock(&atrace_container_sock_rwlock); \ + if (atrace_container_sock_fd != -1) { \ + WRITE_MSG_IN_CONTAINER_LOCKED(ph, sep_before_name, value_format, name, value); \ + } \ + pthread_rwlock_unlock(&atrace_container_sock_rwlock); \ +} + +void atrace_begin_body(const char* name) +{ + if (CC_LIKELY(atrace_use_container_sock)) { + WRITE_MSG_IN_CONTAINER("B", "|", "%s", name, ""); + return; + } + + if (atrace_marker_fd < 0) return; + + WRITE_MSG("B|%d|", "%s", name, ""); +} + +void atrace_end_body() +{ + if (CC_LIKELY(atrace_use_container_sock)) { + WRITE_MSG_IN_CONTAINER("E", "", "%s", "", ""); + return; + } + + if (atrace_marker_fd < 0) return; + + WRITE_MSG("E|%d", "%s", "", ""); +} + +void atrace_async_begin_body(const char* name, int32_t cookie) +{ + if (CC_LIKELY(atrace_use_container_sock)) { + WRITE_MSG_IN_CONTAINER("S", "|", "|%d", name, cookie); + return; + } + + if (atrace_marker_fd < 0) return; + + WRITE_MSG("S|%d|", "|%" PRId32, name, cookie); +} + +void atrace_async_end_body(const char* name, int32_t cookie) +{ + if (CC_LIKELY(atrace_use_container_sock)) { + WRITE_MSG_IN_CONTAINER("F", "|", "|%d", name, cookie); + return; + } + + if (atrace_marker_fd < 0) return; + + WRITE_MSG("F|%d|", "|%" PRId32, name, cookie); +} + +void atrace_int_body(const char* name, int32_t value) +{ + if (CC_LIKELY(atrace_use_container_sock)) { + WRITE_MSG_IN_CONTAINER("C", "|", "|%" PRId32, name, value); + return; + } + + if (atrace_marker_fd < 0) return; + + WRITE_MSG("C|%d|", "|%" PRId32, name, value); +} + +void atrace_int64_body(const char* name, int64_t value) +{ + if (CC_LIKELY(atrace_use_container_sock)) { + WRITE_MSG_IN_CONTAINER("C", "|", "|%" PRId64, name, value); + return; + } + + if (atrace_marker_fd < 0) return; + + WRITE_MSG("C|%d|", "|%" PRId64, name, value); +} diff --git a/libcutils/trace-dev.c b/libcutils/trace-dev.c deleted file mode 100644 index 4468e83f6..000000000 --- a/libcutils/trace-dev.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2012 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 "trace-dev.inc" - -static pthread_once_t atrace_once_control = PTHREAD_ONCE_INIT; - -// Set whether tracing is enabled in this process. This is used to prevent -// the Zygote process from tracing. -void atrace_set_tracing_enabled(bool enabled) -{ - atomic_store_explicit(&atrace_is_enabled, enabled, memory_order_release); - atrace_update_tags(); -} - -static void atrace_init_once() -{ - atrace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_WRONLY | O_CLOEXEC); - if (atrace_marker_fd == -1) { - ALOGE("Error opening trace file: %s (%d)", strerror(errno), errno); - atrace_enabled_tags = 0; - goto done; - } - - atrace_enabled_tags = atrace_get_property(); - -done: - atomic_store_explicit(&atrace_is_ready, true, memory_order_release); -} - -void atrace_setup() -{ - pthread_once(&atrace_once_control, atrace_init_once); -} - -void atrace_begin_body(const char* name) -{ - WRITE_MSG("B|%d|", "%s", name, ""); -} - -void atrace_end_body() -{ - WRITE_MSG("E|%d", "%s", "", ""); -} - -void atrace_async_begin_body(const char* name, int32_t cookie) -{ - WRITE_MSG("S|%d|", "|%" PRId32, name, cookie); -} - -void atrace_async_end_body(const char* name, int32_t cookie) -{ - WRITE_MSG("F|%d|", "|%" PRId32, name, cookie); -} - -void atrace_int_body(const char* name, int32_t value) -{ - WRITE_MSG("C|%d|", "|%" PRId32, name, value); -} - -void atrace_int64_body(const char* name, int64_t value) -{ - WRITE_MSG("C|%d|", "|%" PRId64, name, value); -} diff --git a/libcutils/trace-dev.cpp b/libcutils/trace-dev.cpp new file mode 100644 index 000000000..4da821555 --- /dev/null +++ b/libcutils/trace-dev.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2012 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 + +#include "trace-dev.inc" + +static pthread_once_t atrace_once_control = PTHREAD_ONCE_INIT; + +// Set whether tracing is enabled in this process. This is used to prevent +// the Zygote process from tracing. +void atrace_set_tracing_enabled(bool enabled) +{ + atomic_store_explicit(&atrace_is_enabled, enabled, memory_order_release); + atrace_update_tags(); +} + +static void atrace_init_once() +{ + atrace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_WRONLY | O_CLOEXEC); + if (atrace_marker_fd == -1) { + ALOGE("Error opening trace file: %s (%d)", strerror(errno), errno); + atrace_enabled_tags = 0; + goto done; + } + + atrace_enabled_tags = atrace_get_property(); + +done: + atomic_store_explicit(&atrace_is_ready, true, memory_order_release); +} + +void atrace_setup() +{ + pthread_once(&atrace_once_control, atrace_init_once); +} + +void atrace_begin_body(const char* name) +{ + WRITE_MSG("B|%d|", "%s", name, ""); +} + +void atrace_end_body() +{ + WRITE_MSG("E|%d", "%s", "", ""); +} + +void atrace_async_begin_body(const char* name, int32_t cookie) +{ + WRITE_MSG("S|%d|", "|%" PRId32, name, cookie); +} + +void atrace_async_end_body(const char* name, int32_t cookie) +{ + WRITE_MSG("F|%d|", "|%" PRId32, name, cookie); +} + +void atrace_int_body(const char* name, int32_t value) +{ + WRITE_MSG("C|%d|", "|%" PRId32, name, value); +} + +void atrace_int64_body(const char* name, int64_t value) +{ + WRITE_MSG("C|%d|", "|%" PRId64, name, value); +} diff --git a/libcutils/trace-host.c b/libcutils/trace-host.c deleted file mode 100644 index 05842cd7d..000000000 --- a/libcutils/trace-host.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2012 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 - -#ifndef __unused -#define __unused __attribute__((__unused__)) -#endif - -atomic_bool atrace_is_ready = ATOMIC_VAR_INIT(true); -int atrace_marker_fd = -1; -uint64_t atrace_enabled_tags = 0; - -void atrace_set_debuggable(bool debuggable __unused) { } -void atrace_set_tracing_enabled(bool enabled __unused) { } -void atrace_update_tags() { } -void atrace_setup() { } -void atrace_begin_body(const char* name __unused) { } -void atrace_end_body() { } -void atrace_async_begin_body(const char* name __unused, int32_t cookie __unused) { } -void atrace_async_end_body(const char* name __unused, int32_t cookie __unused) { } -void atrace_int_body(const char* name __unused, int32_t value __unused) { } -void atrace_int64_body(const char* name __unused, int64_t value __unused) { } diff --git a/libcutils/trace-host.cpp b/libcutils/trace-host.cpp new file mode 100644 index 000000000..05842cd7d --- /dev/null +++ b/libcutils/trace-host.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2012 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 + +#ifndef __unused +#define __unused __attribute__((__unused__)) +#endif + +atomic_bool atrace_is_ready = ATOMIC_VAR_INIT(true); +int atrace_marker_fd = -1; +uint64_t atrace_enabled_tags = 0; + +void atrace_set_debuggable(bool debuggable __unused) { } +void atrace_set_tracing_enabled(bool enabled __unused) { } +void atrace_update_tags() { } +void atrace_setup() { } +void atrace_begin_body(const char* name __unused) { } +void atrace_end_body() { } +void atrace_async_begin_body(const char* name __unused, int32_t cookie __unused) { } +void atrace_async_end_body(const char* name __unused, int32_t cookie __unused) { } +void atrace_int_body(const char* name __unused, int32_t value __unused) { } +void atrace_int64_body(const char* name __unused, int64_t value __unused) { } -- cgit v1.2.3-54-g00ecf