From 52abb4b1ef5f0a0939f1485433cf817523caf779 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 15 Jul 2012 15:52:50 -0700 Subject: [PATCH 01/89] Added clear command to toolbox Change-Id: Ifb1b7693727997b94614f7da73081f0894ee88ad --- toolbox/Android.mk | 3 ++- toolbox/clear.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 toolbox/clear.c diff --git a/toolbox/Android.mk b/toolbox/Android.mk index 086ba0dc9..b027787ad 100644 --- a/toolbox/Android.mk +++ b/toolbox/Android.mk @@ -57,7 +57,8 @@ TOOLS := \ touch \ lsof \ du \ - md5 + md5 \ + clear ifeq ($(HAVE_SELINUX),true) diff --git a/toolbox/clear.c b/toolbox/clear.c new file mode 100644 index 000000000..df46ad251 --- /dev/null +++ b/toolbox/clear.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012, 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. + * * Neither the name of Google, Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT 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 + +int clear_main(int argc, char **argv) { + /* This prints the clear screen and move cursor to top-left corner control + * characters for VT100 terminals. This means it will not work on + * non-VT100 compliant terminals, namely Windows' cmd.exe, but should + * work on anything unix-y. */ + fputs("\x1b[2J\x1b[H", stdout); + return 0; +} From f286dd75f6e715f900a2b2a230c8e8fb68a418a3 Mon Sep 17 00:00:00 2001 From: Jon Larimer Date: Mon, 13 Aug 2012 13:10:41 -0400 Subject: [PATCH 02/89] Make usage() static in du.c to avoid conflicts Change-Id: Ic6b036d050943fb5f0af8553c081ca75362167e8 --- toolbox/du.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/toolbox/du.c b/toolbox/du.c index 06374a440..fc7c94345 100644 --- a/toolbox/du.c +++ b/toolbox/du.c @@ -62,7 +62,7 @@ __RCSID("$NetBSD: du.c,v 1.33 2008/07/30 22:03:40 dsl Exp $"); int linkchk(dev_t, ino_t); void prstat(const char *, int64_t); -void usage(void); +static void usage(void); long blocksize; @@ -312,7 +312,7 @@ linkchk(dev_t dev, ino_t ino) return 0; } -void +static void usage(void) { From 1cd5bcf591690adfc671731bb2d50308b3f6fe35 Mon Sep 17 00:00:00 2001 From: Joe Onorato Date: Wed, 18 Jul 2012 12:03:33 -0700 Subject: [PATCH 03/89] libext4_utils on host is now called libext4_utils_host so there is no name conflict Change-Id: Ibc7923676925ed6942b3f672ee764cfaa98ee96e --- fastboot/Android.mk | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fastboot/Android.mk b/fastboot/Android.mk index e3261a7f7..b6fbd3fd6 100644 --- a/fastboot/Android.mk +++ b/fastboot/Android.mk @@ -48,7 +48,13 @@ ifeq ($(HOST_OS),windows) LOCAL_C_INCLUDES += development/host/windows/usb/api endif -LOCAL_STATIC_LIBRARIES := $(EXTRA_STATIC_LIBS) libzipfile libunz libext4_utils libsparse libz +LOCAL_STATIC_LIBRARIES := \ + $(EXTRA_STATIC_LIBS) \ + libzipfile \ + libunz \ + libext4_utils_host \ + libsparse \ + libz ifneq ($(HOST_OS),windows) ifeq ($(HAVE_SELINUX), true) From 4d9571145abbf5ca15bf42f90a2f81439bcfbbd4 Mon Sep 17 00:00:00 2001 From: "Mike J. Chen" Date: Fri, 20 Jul 2012 18:35:32 -0700 Subject: [PATCH 04/89] Fix build by removing TAGS from host module Change-Id: I0118cebff021b435baea0b46dd3c43250ef96632 Signed-off-by: Mike J. Chen --- gpttool/Android.mk | 1 - 1 file changed, 1 deletion(-) diff --git a/gpttool/Android.mk b/gpttool/Android.mk index a9fffe901..b8f9844c7 100644 --- a/gpttool/Android.mk +++ b/gpttool/Android.mk @@ -7,7 +7,6 @@ LOCAL_SRC_FILES := gpttool.c LOCAL_STATIC_LIBRARIES := libz LOCAL_MODULE := gpttool -LOCAL_MODULE_TAGS := eng include $(BUILD_HOST_EXECUTABLE) From 20258b501e1d2b15b4587d42c83db848b8fae188 Mon Sep 17 00:00:00 2001 From: Joe Onorato Date: Mon, 23 Jul 2012 19:15:14 -0700 Subject: [PATCH 05/89] Support for multiple modules with the same name is going away. Change-Id: I5006b467978071f9107babe532efa71d05061580 --- fastboot/Android.mk | 5 ++- libsparse/Android.mk | 82 +++++++++++++++++++++----------------------- 2 files changed, 44 insertions(+), 43 deletions(-) diff --git a/fastboot/Android.mk b/fastboot/Android.mk index b6fbd3fd6..905f7598f 100644 --- a/fastboot/Android.mk +++ b/fastboot/Android.mk @@ -53,7 +53,7 @@ LOCAL_STATIC_LIBRARIES := \ libzipfile \ libunz \ libext4_utils_host \ - libsparse \ + libsparse_host \ libz ifneq ($(HOST_OS),windows) @@ -63,8 +63,11 @@ endif # HAVE_SELINUX endif # HOST_OS != windows include $(BUILD_HOST_EXECUTABLE) + + $(call dist-for-goals,dist_files,$(LOCAL_BUILT_MODULE)) + ifeq ($(HOST_OS),linux) include $(CLEAR_VARS) LOCAL_SRC_FILES := usbtest.c usb_linux.c diff --git a/libsparse/Android.mk b/libsparse/Android.mk index 69b52c387..9025cc025 100644 --- a/libsparse/Android.mk +++ b/libsparse/Android.mk @@ -10,92 +10,90 @@ libsparse_src_files := \ sparse_err.c \ sparse_read.c -include $(CLEAR_VARS) +include $(CLEAR_VARS) LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include LOCAL_SRC_FILES := $(libsparse_src_files) -LOCAL_MODULE := libsparse -LOCAL_MODULE_TAGS := optional +LOCAL_MODULE := libsparse_host LOCAL_STATIC_LIBRARIES := libz LOCAL_C_INCLUDES += $(LOCAL_PATH)/include external/zlib - include $(BUILD_HOST_STATIC_LIBRARY) -include $(CLEAR_VARS) +include $(CLEAR_VARS) LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include LOCAL_SRC_FILES := $(libsparse_src_files) LOCAL_MODULE := libsparse -LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES += $(LOCAL_PATH)/include external/zlib -LOCAL_SHARED_LIBRARIES := libz - +LOCAL_SHARED_LIBRARIES := \ + libz include $(BUILD_SHARED_LIBRARY) -include $(CLEAR_VARS) +include $(CLEAR_VARS) LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include LOCAL_SRC_FILES := $(libsparse_src_files) -LOCAL_MODULE := libsparse -LOCAL_MODULE_TAGS := optional +LOCAL_MODULE := libsparse_static LOCAL_C_INCLUDES += $(LOCAL_PATH)/include external/zlib LOCAL_STATIC_LIBRARIES := libz - include $(BUILD_STATIC_LIBRARY) -include $(CLEAR_VARS) +include $(CLEAR_VARS) +LOCAL_SRC_FILES := simg2img.c \ + sparse_crc32.c +LOCAL_MODULE := simg2img_host +# Need a unique module name, but exe should still be called simg2img +LOCAL_MODULE_STEM := simg2img +LOCAL_STATIC_LIBRARIES := \ + libsparse_host \ + libz +include $(BUILD_HOST_EXECUTABLE) + + +include $(CLEAR_VARS) LOCAL_SRC_FILES := simg2img.c \ sparse_crc32.c LOCAL_MODULE := simg2img -LOCAL_MODULE_TAGS := debug -LOCAL_STATIC_LIBRARIES := libsparse libz - -include $(BUILD_HOST_EXECUTABLE) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := simg2img.c \ - sparse_crc32.c -LOCAL_MODULE := simg2img -LOCAL_MODULE_TAGS := optional -LOCAL_STATIC_LIBRARIES := libsparse libz - +LOCAL_STATIC_LIBRARIES := \ + libsparse_static \ + libz include $(BUILD_EXECUTABLE) + include $(CLEAR_VARS) - LOCAL_SRC_FILES := img2simg.c -LOCAL_MODULE := img2simg -LOCAL_MODULE_TAGS := debug -LOCAL_STATIC_LIBRARIES := libsparse libz - +LOCAL_MODULE := img2simg_host +# Need a unique module name, but exe should still be called simg2img +LOCAL_MODULE_STEM := img2simg +LOCAL_STATIC_LIBRARIES := \ + libsparse_host \ + libz include $(BUILD_HOST_EXECUTABLE) -include $(CLEAR_VARS) +include $(CLEAR_VARS) LOCAL_SRC_FILES := img2simg.c LOCAL_MODULE := img2simg -LOCAL_MODULE_TAGS := optional -LOCAL_STATIC_LIBRARIES := libsparse libz - +LOCAL_STATIC_LIBRARIES := \ + libsparse_static \ + libz include $(BUILD_EXECUTABLE) -include $(CLEAR_VARS) +include $(CLEAR_VARS) LOCAL_SRC_FILES := simg2simg.c LOCAL_MODULE := simg2simg -LOCAL_MODULE_TAGS := debug -LOCAL_STATIC_LIBRARIES := libsparse libz - +LOCAL_STATIC_LIBRARIES := \ + libsparse_host \ + libz include $(BUILD_HOST_EXECUTABLE) -include $(CLEAR_VARS) +include $(CLEAR_VARS) LOCAL_MODULE := simg_dump.py -LOCAL_MODULE_TAGS := debug LOCAL_SRC_FILES := simg_dump.py LOCAL_MODULE_CLASS := EXECUTABLES LOCAL_IS_HOST_MODULE := true - include $(BUILD_PREBUILT) + From d832567908a9967d1aa35a24b43e541356728d07 Mon Sep 17 00:00:00 2001 From: Geremy Condra Date: Tue, 11 Sep 2012 21:38:31 -0700 Subject: [PATCH 06/89] Add event log tag for cert pin failures. Change-Id: Ib93f4eeec35b5754498464ada94faeb2bdb0b896 --- logcat/event.logtags | 3 +++ 1 file changed, 3 insertions(+) diff --git a/logcat/event.logtags b/logcat/event.logtags index 09640e122..6040bd9c9 100644 --- a/logcat/event.logtags +++ b/logcat/event.logtags @@ -150,5 +150,8 @@ 80305 bionic_event_resolver_wrong_server (uid|1) 80310 bionic_event_resolver_wrong_query (uid|1) +# libcore failure logging +90100 cert_pin_failure (certs|4) + # NOTE - the range 1000000-2000000 is reserved for partners and others who # want to define their own log tags without conflicting with the core platform. From 295b82bd691d413c07665c7e7607fe0e5d3485f5 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Mon, 27 Aug 2012 19:10:57 +0300 Subject: [PATCH 07/89] Rename getline to fs_getline for fs_mgr fs_mgr defines its own version of getline and uses it internally. This leads to a build error if getline is also defined in bionic, since fs_mgr will see readline as defined internally. Rename getline in fs_mgr to a local name (fs_getline) so that there will no longer be any conflicts. This is needed it we want to add getline in bionic. Change-Id: I3a32be71a645e122629802d98ff8f9ab9c419e86 Signed-off-by: Irina Tirdea --- fs_mgr/fs_mgr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c index 0361ab8bc..e117a0b4b 100644 --- a/fs_mgr/fs_mgr.c +++ b/fs_mgr/fs_mgr.c @@ -167,7 +167,7 @@ out: * then return an empty buffer. This effectively ignores lines that are too long. * On EOF, return null. */ -static char *getline(char *buf, int size, FILE *file) +static char *fs_getline(char *buf, int size, FILE *file) { int cnt = 0; int eof = 0; @@ -241,7 +241,7 @@ static struct fstab_rec *read_fstab(char *fstab_path) } entries = 0; - while (getline(line, sizeof(line), fstab_file)) { + while (fs_getline(line, sizeof(line), fstab_file)) { /* if the last character is a newline, shorten the string by 1 byte */ len = strlen(line); if (line[len - 1] == '\n') { @@ -268,7 +268,7 @@ static struct fstab_rec *read_fstab(char *fstab_path) fseek(fstab_file, 0, SEEK_SET); cnt = 0; - while (getline(line, sizeof(line), fstab_file)) { + while (fs_getline(line, sizeof(line), fstab_file)) { /* if the last character is a newline, shorten the string by 1 byte */ len = strlen(line); if (line[len - 1] == '\n') { From d5d6d97defa8999784a15003ed41449954bc7178 Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Wed, 26 Sep 2012 09:58:07 -0700 Subject: [PATCH 08/89] Host builds: add fastboot and adb Add fastboot and adb host utilities to debug builds for debugging and development purposes. Change-Id: If77699a27497b8641998930f14d4ee418b856080 --- adb/Android.mk | 1 + fastboot/Android.mk | 1 + 2 files changed, 2 insertions(+) diff --git a/adb/Android.mk b/adb/Android.mk index bc8315ed2..d6b01463e 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -77,6 +77,7 @@ endif LOCAL_CFLAGS += -O2 -g -DADB_HOST=1 -Wall -Wno-unused-parameter LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE LOCAL_MODULE := adb +LOCAL_MODULE_TAGS := debug LOCAL_STATIC_LIBRARIES := libzipfile libunz libcrypto_static $(EXTRA_STATIC_LIBS) ifeq ($(USE_SYSDEPS_WIN32),) diff --git a/fastboot/Android.mk b/fastboot/Android.mk index 92e9219db..5e0e172f0 100644 --- a/fastboot/Android.mk +++ b/fastboot/Android.mk @@ -20,6 +20,7 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/../mkbootimg \ $(LOCAL_PATH)/../../extras/ext4_utils LOCAL_SRC_FILES := protocol.c engine.c bootimg.c fastboot.c LOCAL_MODULE := fastboot +LOCAL_MODULE_TAGS := debug ifeq ($(HOST_OS),linux) LOCAL_SRC_FILES += usb_linux.c util_linux.c From 1f90dcd0c022182220c37b300690cf73674d03b8 Mon Sep 17 00:00:00 2001 From: Michal Frynas Date: Thu, 14 Jul 2011 15:20:05 +0200 Subject: [PATCH 09/89] Fixed improper size displaying in 'df' utility 'df' command used to display filesystem usage statistics as integer values, in most cases rounding the actual value down. Because of that 'df' tended to display faulty size values. This fix to 'df' utility calculates the fractional part of the size, then it rounds it when needed to the nearest one-digit integer value and displays after decimal dot. Change-Id: I9bc52635d45d3e55ce61b3b1c6b80d1267516e75 --- toolbox/df.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/toolbox/df.c b/toolbox/df.c index 63940a153..9cd07431a 100644 --- a/toolbox/df.c +++ b/toolbox/df.c @@ -9,16 +9,22 @@ static int ok = EXIT_SUCCESS; static void printsize(long long n) { char unit = 'K'; - n /= 1024; - if (n > 1024) { + long long t; + + n *= 10; + + if (n > 1024*1024*10) { n /= 1024; unit = 'M'; } - if (n > 1024) { + + if (n > 1024*1024*10) { n /= 1024; unit = 'G'; } - printf("%4lld%c", n, unit); + + t = (n + 512) / 1024; + printf("%4lld.%1lld%c", t/10, t%10, unit); } static void df(char *s, int always) { @@ -41,7 +47,7 @@ static void df(char *s, int always) { } int df_main(int argc, char *argv[]) { - printf("Filesystem Size Used Free Blksize\n"); + printf("Filesystem Size Used Free Blksize\n"); if (argc == 1) { char s[2000]; FILE *f = fopen("/proc/mounts", "r"); From 7ecfe6a94baf9f5d883e32a870e282c5b349a954 Mon Sep 17 00:00:00 2001 From: Nick Kralevich Date: Tue, 2 Oct 2012 14:59:59 -0700 Subject: [PATCH 10/89] init: harden property service. Don't create temporary files in a well-known location. Rather, use mkstemp(). Don't read persistent property files from insecure files. Change-Id: I81e2aca674a2a7ca54869f088737fb228d3af6d2 --- init/property_service.c | 70 ++++++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/init/property_service.c b/init/property_service.c index 5017375fc..c6c2e3f49 100644 --- a/init/property_service.c +++ b/init/property_service.c @@ -123,7 +123,7 @@ static int init_workspace(workspace *w, size_t size) /* dev is a tmpfs that we can use to carve a shared workspace * out of, so let's do that... */ - fd = open("/dev/__properties__", O_RDWR | O_CREAT, 0600); + fd = open("/dev/__properties__", O_RDWR | O_CREAT | O_NOFOLLOW, 0600); if (fd < 0) return -1; @@ -136,7 +136,7 @@ static int init_workspace(workspace *w, size_t size) close(fd); - fd = open("/dev/__properties__", O_RDONLY); + fd = open("/dev/__properties__", O_RDONLY | O_NOFOLLOW); if (fd < 0) return -1; @@ -318,13 +318,12 @@ const char* property_get(const char *name) static void write_persistent_property(const char *name, const char *value) { - const char *tempPath = PERSISTENT_PROPERTY_DIR "/.temp"; + char tempPath[PATH_MAX]; char path[PATH_MAX]; - int fd, length; + int fd; - snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, name); - - fd = open(tempPath, O_WRONLY|O_CREAT|O_TRUNC, 0600); + snprintf(tempPath, sizeof(tempPath), "%s/.temp.XXXXXX", PERSISTENT_PROPERTY_DIR); + fd = mkstemp(tempPath); if (fd < 0) { ERROR("Unable to write persistent property to temp file %s errno: %d\n", tempPath, errno); return; @@ -332,6 +331,7 @@ static void write_persistent_property(const char *name, const char *value) write(fd, value, strlen(value)); close(fd); + snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, name); if (rename(tempPath, path)) { unlink(tempPath); ERROR("Unable to rename persistent property file %s to %s\n", tempPath, path); @@ -343,8 +343,8 @@ int property_set(const char *name, const char *value) prop_area *pa; prop_info *pi; - int namelen = strlen(name); - int valuelen = strlen(value); + size_t namelen = strlen(name); + size_t valuelen = strlen(value); if(namelen >= PROP_NAME_MAX) return -1; if(valuelen >= PROP_VALUE_MAX) return -1; @@ -423,13 +423,13 @@ void handle_property_set_fd() /* Check socket options here */ if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) { close(s); - ERROR("Unable to recieve socket options\n"); + ERROR("Unable to receive socket options\n"); return; } r = TEMP_FAILURE_RETRY(recv(s, &msg, sizeof(msg), 0)); if(r != sizeof(prop_msg)) { - ERROR("sys_prop: mis-match msg size recieved: %d expected: %d errno: %d\n", + ERROR("sys_prop: mis-match msg size received: %d expected: %d errno: %d\n", r, sizeof(prop_msg), errno); close(s); return; @@ -528,10 +528,11 @@ static void load_properties_from_file(const char *fn) static void load_persistent_properties() { DIR* dir = opendir(PERSISTENT_PROPERTY_DIR); + int dir_fd = dirfd(dir); struct dirent* entry; - char path[PATH_MAX]; char value[PROP_VALUE_MAX]; int fd, length; + struct stat sb; if (dir) { while ((entry = readdir(dir)) != NULL) { @@ -542,20 +543,39 @@ static void load_persistent_properties() continue; #endif /* open the file and read the property value */ - snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, entry->d_name); - fd = open(path, O_RDONLY); - if (fd >= 0) { - length = read(fd, value, sizeof(value) - 1); - if (length >= 0) { - value[length] = 0; - property_set(entry->d_name, value); - } else { - ERROR("Unable to read persistent property file %s errno: %d\n", path, errno); - } - close(fd); - } else { - ERROR("Unable to open persistent property file %s errno: %d\n", path, errno); + fd = openat(dir_fd, entry->d_name, O_RDONLY | O_NOFOLLOW); + if (fd < 0) { + ERROR("Unable to open persistent property file \"%s\" errno: %d\n", + entry->d_name, errno); + continue; } + if (fstat(fd, &sb) < 0) { + ERROR("fstat on property file \"%s\" failed errno: %d\n", entry->d_name, errno); + close(fd); + continue; + } + + // File must not be accessible to others, be owned by root/root, and + // not be a hard link to any other file. + if (((sb.st_mode & (S_IRWXG | S_IRWXO)) != 0) + || (sb.st_uid != 0) + || (sb.st_gid != 0) + || (sb.st_nlink != 1)) { + ERROR("skipping insecure property file %s (uid=%lu gid=%lu nlink=%d mode=%o)\n", + entry->d_name, sb.st_uid, sb.st_gid, sb.st_nlink, sb.st_mode); + close(fd); + continue; + } + + length = read(fd, value, sizeof(value) - 1); + if (length >= 0) { + value[length] = 0; + property_set(entry->d_name, value); + } else { + ERROR("Unable to read persistent property file %s errno: %d\n", + entry->d_name, errno); + } + close(fd); } closedir(dir); } else { From 87980b5c9fab12737196b8505e948186a210d96e Mon Sep 17 00:00:00 2001 From: Nick Kralevich Date: Fri, 5 Oct 2012 12:44:38 -0700 Subject: [PATCH 11/89] Revert "init: Set ADDR_COMPAT_LAYOUT before spawning processes." This reverts commit 01b1dee0ab7ad649760f9d8a7cead2a3f6d9cf70. Bug: 7188322 Change-Id: Ia159eab36e9e7373f470d20a3796b63868ea5689 --- init/init.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/init/init.c b/init/init.c index 1c80d9cc4..6127fd38e 100755 --- a/init/init.c +++ b/init/init.c @@ -31,7 +31,6 @@ #include #include #include -#include #ifdef HAVE_SELINUX #include @@ -243,21 +242,6 @@ void service_start(struct service *svc, const char *dynamic_args) int fd, sz; umask(077); -#ifdef __arm__ - /* - * b/7188322 - Temporarily revert to the compat memory layout - * to avoid breaking third party apps. - * - * THIS WILL GO AWAY IN A FUTURE ANDROID RELEASE. - * - * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=7dbaa466 - * changes the kernel mapping from bottom up to top-down. - * This breaks some programs which improperly embed - * an out of date copy of Android's linker. - */ - int current = personality(0xffffFFFF); - personality(current | ADDR_COMPAT_LAYOUT); -#endif if (properties_inited()) { get_property_workspace(&fd, &sz); sprintf(tmp, "%d,%d", dup(fd), sz); From ef5d0340e4ff3fe11b7668ebaf2f4f0c4c06134d Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Wed, 10 Oct 2012 11:26:54 -0700 Subject: [PATCH 12/89] toolbox: silence some compiler warnings Comparison of signed and unsigned integers. Use parenthesis around a group of bitwise OR operations. Change-Id: Ia404380593ce2c2a291133c07c0fc7a016a3ad3f --- toolbox/ls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/toolbox/ls.c b/toolbox/ls.c index a4db99ca8..b7ba1b748 100644 --- a/toolbox/ls.c +++ b/toolbox/ls.c @@ -276,12 +276,12 @@ static int listfile_maclabel(const char *path, int flags) switch(s.st_mode & S_IFMT) { case S_IFLNK: { char linkto[256]; - int len; + ssize_t len; len = readlink(path, linkto, sizeof(linkto)); if(len < 0) return -1; - if(len > sizeof(linkto)-1) { + if((size_t)len > sizeof(linkto)-1) { linkto[sizeof(linkto)-4] = '.'; linkto[sizeof(linkto)-3] = '.'; linkto[sizeof(linkto)-2] = '.'; @@ -307,7 +307,7 @@ static int listfile_maclabel(const char *path, int flags) static int listfile(const char *dirname, const char *filename, int flags) { - if ((flags & LIST_LONG | LIST_SIZE | LIST_CLASSIFY | LIST_MACLABEL) == 0) { + if ((flags & (LIST_LONG | LIST_SIZE | LIST_CLASSIFY | LIST_MACLABEL)) == 0) { printf("%s\n", filename); return 0; } From 73167412bc52ee370761e418366ddac504666567 Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Fri, 12 Oct 2012 15:26:45 -0700 Subject: [PATCH 13/89] Make adb robust against EINTR Change-Id: I39a8d9007ce2d5662a33a50e4d7e2e7f8f9fad63 --- adb/services.c | 2 +- adb/sysdeps.h | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/adb/services.c b/adb/services.c index 495a0830f..54d21a8b7 100644 --- a/adb/services.c +++ b/adb/services.c @@ -202,7 +202,7 @@ static void echo_service(int fd, void *cookie) int c; for(;;) { - r = read(fd, buf, 4096); + r = adb_read(fd, buf, 4096); if(r == 0) goto done; if(r < 0) { if(errno == EINTR) continue; diff --git a/adb/sysdeps.h b/adb/sysdeps.h index b51807615..22f01dd82 100644 --- a/adb/sysdeps.h +++ b/adb/sysdeps.h @@ -272,6 +272,7 @@ static __inline__ int adb_is_absolute_host_path( const char* path ) #include #include #include +#include #define OS_PATH_SEPARATOR '/' #define OS_PATH_SEPARATOR_STR "/" @@ -306,7 +307,7 @@ static __inline__ int unix_open(const char* path, int options,...) { if ((options & O_CREAT) == 0) { - return open(path, options); + return TEMP_FAILURE_RETRY( open(path, options) ); } else { @@ -315,19 +316,19 @@ static __inline__ int unix_open(const char* path, int options,...) va_start( args, options ); mode = va_arg( args, int ); va_end( args ); - return open(path, options, mode); + return TEMP_FAILURE_RETRY( open( path, options, mode ) ); } } static __inline__ int adb_open_mode( const char* pathname, int options, int mode ) { - return open( pathname, options, mode ); + return TEMP_FAILURE_RETRY( open( pathname, options, mode ) ); } static __inline__ int adb_open( const char* pathname, int options ) { - int fd = open( pathname, options ); + int fd = TEMP_FAILURE_RETRY( open( pathname, options ) ); if (fd < 0) return -1; close_on_exec( fd ); @@ -353,7 +354,7 @@ static __inline__ int adb_close(int fd) static __inline__ int adb_read(int fd, void* buf, size_t len) { - return read(fd, buf, len); + return TEMP_FAILURE_RETRY( read( fd, buf, len ) ); } #undef read @@ -361,7 +362,7 @@ static __inline__ int adb_read(int fd, void* buf, size_t len) static __inline__ int adb_write(int fd, const void* buf, size_t len) { - return write(fd, buf, len); + return TEMP_FAILURE_RETRY( write( fd, buf, len ) ); } #undef write #define write ___xxx_write @@ -382,7 +383,7 @@ static __inline__ int adb_unlink(const char* path) static __inline__ int adb_creat(const char* path, int mode) { - int fd = creat(path, mode); + int fd = TEMP_FAILURE_RETRY( creat( path, mode ) ); if ( fd < 0 ) return -1; @@ -397,7 +398,7 @@ static __inline__ int adb_socket_accept(int serverfd, struct sockaddr* addr, { int fd; - fd = accept(serverfd, addr, addrlen); + fd = TEMP_FAILURE_RETRY( accept( serverfd, addr, addrlen ) ); if (fd >= 0) close_on_exec(fd); From ec90f1dc11488f0ab8a25a9159965b4ae3c4ca88 Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Sat, 13 Oct 2012 11:59:01 -0700 Subject: [PATCH 14/89] Add TEMP_FAILURE_RETRY macro for darwin Darwin doesn't define the TEMP_FAILURE_RETRY macro in unistd.h so we need to add it everywhere. Joy! Change-Id: Ida554fc65193672cc4616dec79e6282e06cc1b28 --- adb/sysdeps.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/adb/sysdeps.h b/adb/sysdeps.h index ee7cd495e..0252ef3b8 100644 --- a/adb/sysdeps.h +++ b/adb/sysdeps.h @@ -277,6 +277,21 @@ extern char* adb_strtok_r(char *str, const char *delim, char **saveptr); #include #include +/* + * TEMP_FAILURE_RETRY is defined by some, but not all, versions of + * . (Alas, it is not as standard as we'd hoped!) So, if it's + * not already defined, then define it here. + */ +#ifndef TEMP_FAILURE_RETRY +/* Used to retry syscalls that can return EINTR. */ +#define TEMP_FAILURE_RETRY(exp) ({ \ + typeof (exp) _rc; \ + do { \ + _rc = (exp); \ + } while (_rc == -1 && errno == EINTR); \ + _rc; }) +#endif + #define OS_PATH_SEPARATOR '/' #define OS_PATH_SEPARATOR_STR "/" #define ENV_PATH_SEPARATOR_STR ":" From 89c2812bd68ce81fb7a85bb1b946cc2f79f5dbfd Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Sat, 13 Oct 2012 11:59:01 -0700 Subject: [PATCH 15/89] Add TEMP_FAILURE_RETRY macro for darwin Darwin doesn't define the TEMP_FAILURE_RETRY macro in unistd.h so we need to add it everywhere. Joy! (cherry picked from commit ec90f1dc11488f0ab8a25a9159965b4ae3c4ca88) Change-Id: Ida554fc65193672cc4616dec79e6282e06cc1b28 --- adb/sysdeps.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/adb/sysdeps.h b/adb/sysdeps.h index 22f01dd82..e883557f2 100644 --- a/adb/sysdeps.h +++ b/adb/sysdeps.h @@ -274,6 +274,21 @@ static __inline__ int adb_is_absolute_host_path( const char* path ) #include #include +/* + * TEMP_FAILURE_RETRY is defined by some, but not all, versions of + * . (Alas, it is not as standard as we'd hoped!) So, if it's + * not already defined, then define it here. + */ +#ifndef TEMP_FAILURE_RETRY +/* Used to retry syscalls that can return EINTR. */ +#define TEMP_FAILURE_RETRY(exp) ({ \ + typeof (exp) _rc; \ + do { \ + _rc = (exp); \ + } while (_rc == -1 && errno == EINTR); \ + _rc; }) +#endif + #define OS_PATH_SEPARATOR '/' #define OS_PATH_SEPARATOR_STR "/" From 69ce489fc3946b7b89ca837a01d3828f1af2e0a0 Mon Sep 17 00:00:00 2001 From: Nick Kralevich Date: Mon, 15 Oct 2012 15:51:33 -0700 Subject: [PATCH 16/89] fs.c: Fix implicit declaration of function 'mkstemp' system/core/libcutils/fs.c: In function 'fs_write_atomic_int': system/core/libcutils/fs.c:109:5: warning: implicit declaration of function 'mkstemp' [-Wimplicit-function-declaration] Change-Id: I337ecb818f85e20b058f782df45987acf2e9d6c1 --- libcutils/fs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libcutils/fs.c b/libcutils/fs.c index 1226d447e..116526dca 100644 --- a/libcutils/fs.c +++ b/libcutils/fs.c @@ -26,6 +26,7 @@ #include #include #include +#include #define ALL_PERMS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO) #define BUF_SIZE 64 From b49183f122956137b8eb3487a19ae980540842c8 Mon Sep 17 00:00:00 2001 From: Daniel Drown Date: Thu, 16 Feb 2012 10:00:24 -0600 Subject: [PATCH 17/89] Allocate a UID for clatd clatd(464xlat) runs as its own UID after it drops root privs Change-Id: I2392f8127dcd90d16b0f20ff31bcc5aa096db464 Signed-off-by: Daniel Drown --- include/private/android_filesystem_config.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h index 33ecd9a6b..6d1868081 100644 --- a/include/private/android_filesystem_config.h +++ b/include/private/android_filesystem_config.h @@ -62,6 +62,7 @@ #define AID_DRMRPC 1026 /* group for drm rpc */ #define AID_NFC 1027 /* nfc subsystem */ #define AID_SDCARD_R 1028 /* external storage read access */ +#define AID_CLAT 1029 /* clat part of nat464 */ #define AID_SHELL 2000 /* adb and debug shell user */ #define AID_CACHE 2001 /* cache access */ @@ -137,6 +138,7 @@ static const struct android_id_info android_ids[] = { { "net_bw_acct", AID_NET_BW_ACCT, }, { "misc", AID_MISC, }, { "nobody", AID_NOBODY, }, + { "clat", AID_CLAT, }, }; #define android_id_count \ From b83c09812f30d36285cacdf5cf824c56c267f8e5 Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Wed, 10 Oct 2012 11:26:33 -0700 Subject: [PATCH 18/89] Remove HAVE_SELINUX guards Change-Id: Idef0a784a1d237257ff4135bb1df62ff8a67ded3 --- fastboot/Android.mk | 2 -- toolbox/Android.mk | 23 ++++++----------------- toolbox/id.c | 7 ------- toolbox/ls.c | 6 ------ 4 files changed, 6 insertions(+), 32 deletions(-) diff --git a/fastboot/Android.mk b/fastboot/Android.mk index 905f7598f..3d582b248 100644 --- a/fastboot/Android.mk +++ b/fastboot/Android.mk @@ -57,9 +57,7 @@ LOCAL_STATIC_LIBRARIES := \ libz ifneq ($(HOST_OS),windows) -ifeq ($(HAVE_SELINUX), true) LOCAL_STATIC_LIBRARIES += libselinux -endif # HAVE_SELINUX endif # HOST_OS != windows include $(BUILD_HOST_EXECUTABLE) diff --git a/toolbox/Android.mk b/toolbox/Android.mk index be95e7cdf..2c1ba42b6 100644 --- a/toolbox/Android.mk +++ b/toolbox/Android.mk @@ -56,11 +56,7 @@ TOOLS := \ ionice \ touch \ lsof \ - md5 - -ifeq ($(HAVE_SELINUX),true) - -TOOLS += \ + md5 \ getenforce \ setenforce \ chcon \ @@ -70,9 +66,6 @@ TOOLS += \ setsebool \ load_policy -endif - - ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT))) TOOLS += r endif @@ -82,17 +75,13 @@ LOCAL_SRC_FILES:= \ toolbox.c \ $(patsubst %,%.c,$(TOOLS)) -LOCAL_SHARED_LIBRARIES := libcutils libc libusbhost - LOCAL_C_INCLUDES := bionic/libc/bionic -ifeq ($(HAVE_SELINUX),true) - -LOCAL_CFLAGS += -DHAVE_SELINUX -LOCAL_SHARED_LIBRARIES += libselinux -LOCAL_C_INCLUDES += external/libselinux/include - -endif +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libc \ + libusbhost \ + libselinux LOCAL_MODULE:= toolbox diff --git a/toolbox/id.c b/toolbox/id.c index bc792887c..8ec79c148 100644 --- a/toolbox/id.c +++ b/toolbox/id.c @@ -4,10 +4,7 @@ #include #include #include - -#ifdef HAVE_SELINUX #include -#endif static void print_uid(uid_t uid) { @@ -34,9 +31,7 @@ int id_main(int argc, char **argv) { gid_t list[64]; int n, max; -#ifdef HAVE_SELINUX char *secctx; -#endif max = getgroups(64, list); if (max < 0) max = 0; @@ -53,12 +48,10 @@ int id_main(int argc, char **argv) print_gid(list[n]); } } -#ifdef HAVE_SELINUX if (getcon(&secctx) == 0) { printf(" context=%s", secctx); free(secctx); } -#endif printf("\n"); return 0; } diff --git a/toolbox/ls.c b/toolbox/ls.c index b7ba1b748..e5305212b 100644 --- a/toolbox/ls.c +++ b/toolbox/ls.c @@ -5,9 +5,7 @@ #include #include -#ifdef HAVE_SELINUX #include -#endif #include #include @@ -260,11 +258,7 @@ static int listfile_maclabel(const char *path, int flags) return -1; } -#ifdef HAVE_SELINUX lgetfilecon(path, &maclabel); -#else - maclabel = strdup("-"); -#endif if (!maclabel) { return -1; } From b5982bf7c65b30be981ecfe1847437b05e32b2bb Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Tue, 16 Oct 2012 23:07:05 -0700 Subject: [PATCH 19/89] Remove HAVE_SELINUX guards Change-Id: I8272c573b3c5dc663203bafab68fad5e94d89364 --- debuggerd/Android.mk | 12 +++++------- debuggerd/tombstone.c | 4 ---- init/Android.mk | 12 +++++------- init/builtins.c | 9 +-------- init/devices.c | 17 +++++------------ init/init.c | 27 +-------------------------- init/init.h | 4 ---- init/init_parser.c | 2 -- init/property_service.c | 18 ------------------ init/util.c | 15 +-------------- 10 files changed, 18 insertions(+), 102 deletions(-) diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk index 15083f400..e48b9af51 100644 --- a/debuggerd/Android.mk +++ b/debuggerd/Android.mk @@ -23,13 +23,11 @@ ifeq ($(ARCH_ARM_HAVE_VFP_D32),true) LOCAL_CFLAGS += -DWITH_VFP_D32 endif # ARCH_ARM_HAVE_VFP_D32 -LOCAL_SHARED_LIBRARIES := libcutils libc libcorkscrew - -ifeq ($(HAVE_SELINUX),true) -LOCAL_SHARED_LIBRARIES += libselinux -LOCAL_C_INCLUDES += external/libselinux/include -LOCAL_CFLAGS += -DHAVE_SELINUX -endif +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libc \ + libcorkscrew \ + libselinux include $(BUILD_EXECUTABLE) diff --git a/debuggerd/tombstone.c b/debuggerd/tombstone.c index 012337bcb..52223da73 100644 --- a/debuggerd/tombstone.c +++ b/debuggerd/tombstone.c @@ -35,9 +35,7 @@ #include #include -#ifdef HAVE_SELINUX #include -#endif #include "machine.h" #include "tombstone.h" @@ -686,12 +684,10 @@ char* engrave_tombstone(pid_t pid, pid_t tid, int signal, mkdir(TOMBSTONE_DIR, 0755); chown(TOMBSTONE_DIR, AID_SYSTEM, AID_SYSTEM); -#ifdef HAVE_SELINUX if (selinux_android_restorecon(TOMBSTONE_DIR) == -1) { *detach_failed = false; return NULL; } -#endif int fd; char* path = find_and_open_tombstone(&fd); diff --git a/init/Android.mk b/init/Android.mk index 7dae9df89..f3287a8ca 100644 --- a/init/Android.mk +++ b/init/Android.mk @@ -32,13 +32,11 @@ LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED) -LOCAL_STATIC_LIBRARIES := libfs_mgr libcutils libc - -ifeq ($(HAVE_SELINUX),true) -LOCAL_STATIC_LIBRARIES += libselinux -LOCAL_C_INCLUDES += external/libselinux/include -LOCAL_CFLAGS += -DHAVE_SELINUX -endif +LOCAL_STATIC_LIBRARIES := \ + libfs_mgr \ + libcutils \ + libc \ + libselinux include $(BUILD_EXECUTABLE) diff --git a/init/builtins.c b/init/builtins.c index 882ceb59e..550be6885 100644 --- a/init/builtins.c +++ b/init/builtins.c @@ -35,10 +35,8 @@ #include #include -#ifdef HAVE_SELINUX #include #include -#endif #include "init.h" #include "keywords.h" @@ -501,24 +499,20 @@ int do_mount_all(int nargs, char **args) } int do_setcon(int nargs, char **args) { -#ifdef HAVE_SELINUX if (is_selinux_enabled() <= 0) return 0; if (setcon(args[1]) < 0) { return -errno; } -#endif return 0; } int do_setenforce(int nargs, char **args) { -#ifdef HAVE_SELINUX if (is_selinux_enabled() <= 0) return 0; if (security_setenforce(atoi(args[1])) < 0) { return -errno; } -#endif return 0; } @@ -746,7 +740,6 @@ int do_restorecon(int nargs, char **args) { } int do_setsebool(int nargs, char **args) { -#ifdef HAVE_SELINUX SELboolean *b = alloca(nargs * sizeof(SELboolean)); char *v; int i; @@ -775,7 +768,7 @@ int do_setsebool(int nargs, char **args) { if (security_set_boolean_list(nargs - 1, b, 0) < 0) return -errno; -#endif + return 0; } diff --git a/init/devices.c b/init/devices.c index e43dbaf86..2644623b8 100644 --- a/init/devices.c +++ b/init/devices.c @@ -30,11 +30,9 @@ #include #include -#ifdef HAVE_SELINUX #include #include #include -#endif #include #include @@ -52,9 +50,7 @@ #define FIRMWARE_DIR1 "/etc/firmware" #define FIRMWARE_DIR2 "/vendor/firmware" -#ifdef HAVE_SELINUX extern struct selabel_handle *sehandle; -#endif static int device_fd = -1; @@ -192,17 +188,15 @@ static void make_device(const char *path, unsigned gid; mode_t mode; dev_t dev; -#ifdef HAVE_SELINUX char *secontext = NULL; -#endif mode = get_device_perm(path, &uid, &gid) | (block ? S_IFBLK : S_IFCHR); -#ifdef HAVE_SELINUX + if (sehandle) { selabel_lookup(sehandle, &secontext, path, mode); setfscreatecon(secontext); } -#endif + dev = makedev(major, minor); /* Temporarily change egid to avoid race condition setting the gid of the * device node. Unforunately changing the euid would prevent creation of @@ -213,12 +207,11 @@ static void make_device(const char *path, mknod(path, mode, dev); chown(path, uid, -1); setegid(AID_ROOT); -#ifdef HAVE_SELINUX + if (secontext) { freecon(secontext); setfscreatecon(NULL); } -#endif } static void add_platform_device(const char *name) @@ -874,12 +867,12 @@ void device_init(void) suseconds_t t0, t1; struct stat info; int fd; -#ifdef HAVE_SELINUX + sehandle = NULL; if (is_selinux_enabled() > 0) { sehandle = selinux_android_file_context_handle(); } -#endif + /* is 64K enough? udev uses 16MB! */ device_fd = uevent_open_socket(64*1024, true); if(device_fd < 0) diff --git a/init/init.c b/init/init.c index b2e39bdaf..1d639dd21 100755 --- a/init/init.c +++ b/init/init.c @@ -32,11 +32,9 @@ #include #include -#ifdef HAVE_SELINUX #include #include #include -#endif #include @@ -59,10 +57,8 @@ #include "util.h" #include "ueventd.h" -#ifdef HAVE_SELINUX struct selabel_handle *sehandle; struct selabel_handle *sehandle_prop; -#endif static int property_triggers_enabled = 0; @@ -76,9 +72,7 @@ static char hardware[32]; static unsigned revision = 0; static char qemu[32]; -#ifdef HAVE_SELINUX static int selinux_enabled = 1; -#endif static struct action *cur_action = NULL; static struct command *cur_command = NULL; @@ -162,10 +156,9 @@ void service_start(struct service *svc, const char *dynamic_args) pid_t pid; int needs_console; int n; -#ifdef HAVE_SELINUX char *scon = NULL; int rc; -#endif + /* starting a service removes it from the disabled or reset * state and immediately takes it out of the restarting * state if it was in there @@ -202,7 +195,6 @@ void service_start(struct service *svc, const char *dynamic_args) return; } -#ifdef HAVE_SELINUX if (is_selinux_enabled() > 0) { char *mycon = NULL, *fcon = NULL; @@ -228,7 +220,6 @@ void service_start(struct service *svc, const char *dynamic_args) return; } } -#endif NOTICE("starting '%s'\n", svc->name); @@ -250,9 +241,7 @@ void service_start(struct service *svc, const char *dynamic_args) for (ei = svc->envvars; ei; ei = ei->next) add_environment(ei->name, ei->value); -#ifdef HAVE_SELINUX setsockcreatecon(scon); -#endif for (si = svc->sockets; si; si = si->next) { int socket_type = ( @@ -265,11 +254,9 @@ void service_start(struct service *svc, const char *dynamic_args) } } -#ifdef HAVE_SELINUX freecon(scon); scon = NULL; setsockcreatecon(NULL); -#endif if (svc->ioprio_class != IoSchedClass_NONE) { if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) { @@ -315,15 +302,12 @@ void service_start(struct service *svc, const char *dynamic_args) _exit(127); } } - -#ifdef HAVE_SELINUX if (svc->seclabel) { if (is_selinux_enabled() > 0 && setexeccon(svc->seclabel) < 0) { ERROR("cannot setexeccon('%s'): %s\n", svc->seclabel, strerror(errno)); _exit(127); } } -#endif if (!dynamic_args) { if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) { @@ -350,9 +334,7 @@ void service_start(struct service *svc, const char *dynamic_args) _exit(127); } -#ifdef HAVE_SELINUX freecon(scon); -#endif if (pid < 0) { ERROR("failed to start '%s'\n", svc->name); @@ -603,11 +585,9 @@ static void import_kernel_nv(char *name, int for_emulator) *value++ = 0; if (name_len == 0) return; -#ifdef HAVE_SELINUX if (!strcmp(name,"selinux")) { selinux_enabled = atoi(value); } -#endif if (for_emulator) { /* in the emulator, export any kernel option with the @@ -755,7 +735,6 @@ static int bootchart_init_action(int nargs, char **args) } #endif -#ifdef HAVE_SELINUX static const struct selinux_opt seopts_prop[] = { { SELABEL_OPT_PATH, "/data/system/property_contexts" }, { SELABEL_OPT_PATH, "/property_contexts" }, @@ -814,8 +793,6 @@ int audit_callback(void *data, security_class_t cls, char *buf, size_t len) return 0; } -#endif - int main(int argc, char **argv) { int fd_count = 0; @@ -866,7 +843,6 @@ int main(int argc, char **argv) process_kernel_cmdline(); -#ifdef HAVE_SELINUX union selinux_callback cb; cb.func_log = klog_write; selinux_set_callback(SELINUX_CB_LOG, cb); @@ -891,7 +867,6 @@ int main(int argc, char **argv) */ restorecon("/dev"); restorecon("/dev/socket"); -#endif is_charger = !strcmp(bootmode, "charger"); diff --git a/init/init.h b/init/init.h index b7e06c93e..955e1f046 100644 --- a/init/init.h +++ b/init/init.h @@ -95,9 +95,7 @@ struct service { gid_t supp_gids[NR_SVC_SUPP_GIDS]; size_t nr_supp_gids; -#ifdef HAVE_SELINUX char *seclabel; -#endif struct socketinfo *sockets; struct svcenvinfo *envvars; @@ -136,10 +134,8 @@ void property_changed(const char *name, const char *value); int load_565rle_image( char *file_name ); -#ifdef HAVE_SELINUX extern struct selabel_handle *sehandle; extern struct selabel_handle *sehandle_prop; extern int selinux_reload_policy(void); -#endif #endif /* _INIT_INIT_H */ diff --git a/init/init_parser.c b/init/init_parser.c index 5393e526c..beb9188fc 100644 --- a/init/init_parser.c +++ b/init/init_parser.c @@ -799,13 +799,11 @@ static void parse_line_service(struct parse_state *state, int nargs, char **args } break; case K_seclabel: -#ifdef HAVE_SELINUX if (nargs != 2) { parse_error(state, "seclabel option requires a label string\n"); } else { svc->seclabel = args[1]; } -#endif break; default: diff --git a/init/property_service.c b/init/property_service.c index c6c2e3f49..2c1b4a1fc 100644 --- a/init/property_service.c +++ b/init/property_service.c @@ -40,10 +40,8 @@ #include #include -#ifdef HAVE_SELINUX #include #include -#endif #include "property_service.h" #include "init.h" @@ -199,7 +197,6 @@ static void update_prop_info(prop_info *pi, const char *value, unsigned len) static int check_mac_perms(const char *name, char *sctx) { -#ifdef HAVE_SELINUX if (is_selinux_enabled() <= 0) return 1; @@ -223,15 +220,10 @@ static int check_mac_perms(const char *name, char *sctx) freecon(tctx); err: return result; - -#endif - return 1; } static int check_control_mac_perms(const char *name, char *sctx) { -#ifdef HAVE_SELINUX - /* * Create a name prefix out of ctl. * The new prefix allows the use of the existing @@ -245,9 +237,6 @@ static int check_control_mac_perms(const char *name, char *sctx) return 0; return check_mac_perms(ctl_name, sctx); - -#endif - return 1; } /* @@ -394,11 +383,9 @@ int property_set(const char *name, const char *value) * to prevent them from being overwritten by default values. */ write_persistent_property(name, value); -#ifdef HAVE_SELINUX } else if (strcmp("selinux.reload_policy", name) == 0 && strcmp("1", value) == 0) { selinux_reload_policy(); -#endif } property_changed(name, value); return 0; @@ -440,9 +427,7 @@ void handle_property_set_fd() msg.name[PROP_NAME_MAX-1] = 0; msg.value[PROP_VALUE_MAX-1] = 0; -#ifdef HAVE_SELINUX getpeercon(s, &source_ctx); -#endif if(memcmp(msg.name,"ctl.",4) == 0) { // Keep the old close-socket-early behavior when handling @@ -467,10 +452,7 @@ void handle_property_set_fd() // the property is written to memory. close(s); } -#ifdef HAVE_SELINUX freecon(source_ctx); -#endif - break; default: diff --git a/init/util.c b/init/util.c index 743748b3f..918bc057e 100755 --- a/init/util.c +++ b/init/util.c @@ -23,9 +23,7 @@ #include #include -#ifdef HAVE_SELINUX #include -#endif #include #include @@ -89,9 +87,7 @@ int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid) { struct sockaddr_un addr; int fd, ret; -#ifdef HAVE_SELINUX char *secon; -#endif fd = socket(PF_UNIX, type, 0); if (fd < 0) { @@ -110,14 +106,12 @@ int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid) goto out_close; } -#ifdef HAVE_SELINUX secon = NULL; if (sehandle) { ret = selabel_lookup(sehandle, &secon, addr.sun_path, S_IFSOCK); if (ret == 0) setfscreatecon(secon); } -#endif ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr)); if (ret) { @@ -125,10 +119,8 @@ int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid) goto out_unlink; } -#ifdef HAVE_SELINUX setfscreatecon(NULL); freecon(secon); -#endif chown(addr.sun_path, uid, gid); chmod(addr.sun_path, perm); @@ -468,31 +460,27 @@ int make_dir(const char *path, mode_t mode) { int rc; -#ifdef HAVE_SELINUX char *secontext = NULL; if (sehandle) { selabel_lookup(sehandle, &secontext, path, mode); setfscreatecon(secontext); } -#endif rc = mkdir(path, mode); -#ifdef HAVE_SELINUX if (secontext) { int save_errno = errno; freecon(secontext); setfscreatecon(NULL); errno = save_errno; } -#endif + return rc; } int restorecon(const char *pathname) { -#ifdef HAVE_SELINUX char *secontext = NULL; struct stat sb; int i; @@ -509,6 +497,5 @@ int restorecon(const char *pathname) return -errno; } freecon(secontext); -#endif return 0; } From 663005248dd5d62198feb2188bc9e841739b673e Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 11 Sep 2012 11:18:38 -0700 Subject: [PATCH 20/89] The localtime_tz and mktime_tz extensions are now in bionic. Bug: 7012465 (cherry-pick of d03072ffde3279fbb60591a0d07c820d8e792762.) Conflicts: libcutils/Android.mk Change-Id: I5e34edd4c8f59cc0a4d5dcc4740707ae063608a0 --- include/cutils/tztime.h | 39 +- libcutils/Android.mk | 4 - libcutils/private.h | 368 -------- libcutils/tzfile.h | 180 ---- libcutils/tzstrftime.c | 842 ----------------- libcutils/tztime.c | 1950 --------------------------------------- 6 files changed, 1 insertion(+), 3382 deletions(-) delete mode 100644 libcutils/private.h delete mode 100644 libcutils/tzfile.h delete mode 100644 libcutils/tzstrftime.c delete mode 100644 libcutils/tztime.c diff --git a/include/cutils/tztime.h b/include/cutils/tztime.h index 36ac25d89..dbdbd60bc 100644 --- a/include/cutils/tztime.h +++ b/include/cutils/tztime.h @@ -17,45 +17,8 @@ #ifndef _CUTILS_TZTIME_H #define _CUTILS_TZTIME_H -#include - -#ifdef __cplusplus -extern "C" { -#endif - -time_t mktime_tz(struct tm * const tmp, char const * tz); -void localtime_tz(const time_t * const timep, struct tm * tmp, const char* tz); - -#ifdef HAVE_ANDROID_OS - -/* the following is defined in the Bionic C library on Android, but the - * declarations are only available through a platform-private header - */ +// TODO: fix both callers to just include themselves. #include -#else /* !HAVE_ANDROID_OS */ - -struct strftime_locale { - const char *mon[12]; /* short names */ - const char *month[12]; /* long names */ - const char *standalone_month[12]; /* long standalone names */ - const char *wday[7]; /* short names */ - const char *weekday[7]; /* long names */ - const char *X_fmt; - const char *x_fmt; - const char *c_fmt; - const char *am; - const char *pm; - const char *date_fmt; -}; - -size_t strftime_tz(char *s, size_t max, const char *format, const struct tm *tm, const struct strftime_locale *locale); - -#endif /* !HAVE_ANDROID_OS */ - -#ifdef __cplusplus -} -#endif - #endif /* __CUTILS_TZTIME_H */ diff --git a/libcutils/Android.mk b/libcutils/Android.mk index d9bd8d83f..fc6d08de3 100644 --- a/libcutils/Android.mk +++ b/libcutils/Android.mk @@ -77,12 +77,8 @@ else abort_socket.c \ fs.c \ selector.c \ - tztime.c \ multiuser.c \ zygote.c - - commonHostSources += \ - tzstrftime.c endif diff --git a/libcutils/private.h b/libcutils/private.h deleted file mode 100644 index 2837b70c1..000000000 --- a/libcutils/private.h +++ /dev/null @@ -1,368 +0,0 @@ -#ifndef PRIVATE_H - -#define PRIVATE_H - -/* -** This file is in the public domain, so clarified as of -** 1996-06-05 by Arthur David Olson. -*/ - -/* -** This header is for use ONLY with the time conversion code. -** There is no guarantee that it will remain unchanged, -** or that it will remain at all. -** Do NOT copy it to any system include directory. -** Thank you! -*/ - -/* -** ID -*/ - -#ifndef lint -#ifndef NOID -static char privatehid[] = "@(#)private.h 8.2"; -#endif /* !defined NOID */ -#endif /* !defined lint */ - -#define GRANDPARENTED "Local time zone must be set--see zic manual page" - -/* -** Defaults for preprocessor symbols. -** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'. -*/ - -#ifndef HAVE_ADJTIME -#define HAVE_ADJTIME 1 -#endif /* !defined HAVE_ADJTIME */ - -#ifndef HAVE_GETTEXT -#define HAVE_GETTEXT 0 -#endif /* !defined HAVE_GETTEXT */ - -#ifndef HAVE_INCOMPATIBLE_CTIME_R -#define HAVE_INCOMPATIBLE_CTIME_R 0 -#endif /* !defined INCOMPATIBLE_CTIME_R */ - -#ifndef HAVE_SETTIMEOFDAY -#define HAVE_SETTIMEOFDAY 3 -#endif /* !defined HAVE_SETTIMEOFDAY */ - -#ifndef HAVE_STRERROR -#define HAVE_STRERROR 1 -#endif /* !defined HAVE_STRERROR */ - -#ifndef HAVE_SYMLINK -#define HAVE_SYMLINK 1 -#endif /* !defined HAVE_SYMLINK */ - -#ifndef HAVE_SYS_STAT_H -#define HAVE_SYS_STAT_H 1 -#endif /* !defined HAVE_SYS_STAT_H */ - -#ifndef HAVE_SYS_WAIT_H -#define HAVE_SYS_WAIT_H 1 -#endif /* !defined HAVE_SYS_WAIT_H */ - -#ifndef HAVE_UNISTD_H -#define HAVE_UNISTD_H 1 -#endif /* !defined HAVE_UNISTD_H */ - -#ifndef HAVE_UTMPX_H -#define HAVE_UTMPX_H 0 -#endif /* !defined HAVE_UTMPX_H */ - -#ifndef LOCALE_HOME -#define LOCALE_HOME "/usr/lib/locale" -#endif /* !defined LOCALE_HOME */ - -#if HAVE_INCOMPATIBLE_CTIME_R -#define asctime_r _incompatible_asctime_r -#define ctime_r _incompatible_ctime_r -#endif /* HAVE_INCOMPATIBLE_CTIME_R */ - -/* -** Nested includes -*/ - -#include "sys/types.h" /* for time_t */ -#include "stdio.h" -#include "errno.h" -#include "string.h" -#include "limits.h" /* for CHAR_BIT et al. */ -#include "time.h" -#include "stdlib.h" - -#if HAVE_GETTEXT -#include "libintl.h" -#endif /* HAVE_GETTEXT */ - -#if HAVE_SYS_WAIT_H -#include /* for WIFEXITED and WEXITSTATUS */ -#endif /* HAVE_SYS_WAIT_H */ - -#ifndef WIFEXITED -#define WIFEXITED(status) (((status) & 0xff) == 0) -#endif /* !defined WIFEXITED */ -#ifndef WEXITSTATUS -#define WEXITSTATUS(status) (((status) >> 8) & 0xff) -#endif /* !defined WEXITSTATUS */ - -#if HAVE_UNISTD_H -#include "unistd.h" /* for F_OK and R_OK */ -#endif /* HAVE_UNISTD_H */ - -#if !HAVE_UNISTD_H -#ifndef F_OK -#define F_OK 0 -#endif /* !defined F_OK */ -#ifndef R_OK -#define R_OK 4 -#endif /* !defined R_OK */ -#endif /* !HAVE_UNISTD_H */ - -/* Unlike 's isdigit, this also works if c < 0 | c > UCHAR_MAX. */ -#define is_digit(c) ((unsigned)(c) - '0' <= 9) - -/* -** Define HAVE_STDINT_H's default value here, rather than at the -** start, since __GLIBC__'s value depends on previously-included -** files. -** (glibc 2.1 and later have stdint.h, even with pre-C99 compilers.) -*/ -#ifndef HAVE_STDINT_H -#define HAVE_STDINT_H \ - (199901 <= __STDC_VERSION__ || \ - 2 < (__GLIBC__ + (0 < __GLIBC_MINOR__))) -#endif /* !defined HAVE_STDINT_H */ - -#if HAVE_STDINT_H -#include "stdint.h" -#endif /* !HAVE_STDINT_H */ - -#ifndef INT_FAST64_MAX -/* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */ -#if defined LLONG_MAX || defined __LONG_LONG_MAX__ -typedef long long int_fast64_t; -#else /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */ -#if (LONG_MAX >> 31) < 0xffffffff -Please use a compiler that supports a 64-bit integer type (or wider); -you may need to compile with "-DHAVE_STDINT_H". -#endif /* (LONG_MAX >> 31) < 0xffffffff */ -typedef long int_fast64_t; -#endif /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */ -#endif /* !defined INT_FAST64_MAX */ - -#ifndef INT32_MAX -#define INT32_MAX 0x7fffffff -#endif /* !defined INT32_MAX */ -#ifndef INT32_MIN -#define INT32_MIN (-1 - INT32_MAX) -#endif /* !defined INT32_MIN */ - -/* -** Workarounds for compilers/systems. -*/ - -/* -** If your compiler lacks prototypes, "#define P(x) ()". -*/ - -#ifndef P -#define P(x) x -#endif /* !defined P */ - -/* -** SunOS 4.1.1 headers lack EXIT_SUCCESS. -*/ - -#ifndef EXIT_SUCCESS -#define EXIT_SUCCESS 0 -#endif /* !defined EXIT_SUCCESS */ - -/* -** SunOS 4.1.1 headers lack EXIT_FAILURE. -*/ - -#ifndef EXIT_FAILURE -#define EXIT_FAILURE 1 -#endif /* !defined EXIT_FAILURE */ - -/* -** SunOS 4.1.1 headers lack FILENAME_MAX. -*/ - -#ifndef FILENAME_MAX - -#ifndef MAXPATHLEN -#ifdef unix -#include "sys/param.h" -#endif /* defined unix */ -#endif /* !defined MAXPATHLEN */ - -#ifdef MAXPATHLEN -#define FILENAME_MAX MAXPATHLEN -#endif /* defined MAXPATHLEN */ -#ifndef MAXPATHLEN -#define FILENAME_MAX 1024 /* Pure guesswork */ -#endif /* !defined MAXPATHLEN */ - -#endif /* !defined FILENAME_MAX */ - -/* -** SunOS 4.1.1 libraries lack remove. -*/ - -#ifndef remove -extern int unlink P((const char * filename)); -#define remove unlink -#endif /* !defined remove */ - -/* -** Some ancient errno.h implementations don't declare errno. -** But some newer errno.h implementations define it as a macro. -** Fix the former without affecting the latter. -*/ - -#ifndef errno -extern int errno; -#endif /* !defined errno */ - -/* -** Some time.h implementations don't declare asctime_r. -** Others might define it as a macro. -** Fix the former without affecting the latter. -*/ - -#ifndef asctime_r -extern char * asctime_r(); -#endif - -/* -** Private function declarations. -*/ - -char * icalloc P((int nelem, int elsize)); -char * icatalloc P((char * old, const char * new)); -char * icpyalloc P((const char * string)); -char * imalloc P((int n)); -void * irealloc P((void * pointer, int size)); -void icfree P((char * pointer)); -void ifree P((char * pointer)); -const char * scheck P((const char * string, const char * format)); - -/* -** Finally, some convenience items. -*/ - -#ifndef TRUE -#define TRUE 1 -#endif /* !defined TRUE */ - -#ifndef FALSE -#define FALSE 0 -#endif /* !defined FALSE */ - -#ifndef TYPE_BIT -#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT) -#endif /* !defined TYPE_BIT */ - -#ifndef TYPE_SIGNED -#define TYPE_SIGNED(type) (((type) -1) < 0) -#endif /* !defined TYPE_SIGNED */ - -/* -** Since the definition of TYPE_INTEGRAL contains floating point numbers, -** it cannot be used in preprocessor directives. -*/ - -#ifndef TYPE_INTEGRAL -#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5) -#endif /* !defined TYPE_INTEGRAL */ - -#ifndef INT_STRLEN_MAXIMUM -/* -** 302 / 1000 is log10(2.0) rounded up. -** Subtract one for the sign bit if the type is signed; -** add one for integer division truncation; -** add one more for a minus sign if the type is signed. -*/ -#define INT_STRLEN_MAXIMUM(type) \ - ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \ - 1 + TYPE_SIGNED(type)) -#endif /* !defined INT_STRLEN_MAXIMUM */ - -/* -** INITIALIZE(x) -*/ - -#ifndef GNUC_or_lint -#ifdef lint -#define GNUC_or_lint -#endif /* defined lint */ -#ifndef lint -#ifdef __GNUC__ -#define GNUC_or_lint -#endif /* defined __GNUC__ */ -#endif /* !defined lint */ -#endif /* !defined GNUC_or_lint */ - -#ifndef INITIALIZE -#ifdef GNUC_or_lint -#define INITIALIZE(x) ((x) = 0) -#endif /* defined GNUC_or_lint */ -#ifndef GNUC_or_lint -#define INITIALIZE(x) -#endif /* !defined GNUC_or_lint */ -#endif /* !defined INITIALIZE */ - -/* -** For the benefit of GNU folk... -** `_(MSGID)' uses the current locale's message library string for MSGID. -** The default is to use gettext if available, and use MSGID otherwise. -*/ - -#ifndef _ -#if HAVE_GETTEXT -#define _(msgid) gettext(msgid) -#else /* !HAVE_GETTEXT */ -#define _(msgid) msgid -#endif /* !HAVE_GETTEXT */ -#endif /* !defined _ */ - -#ifndef TZ_DOMAIN -#define TZ_DOMAIN "tz" -#endif /* !defined TZ_DOMAIN */ - -#if HAVE_INCOMPATIBLE_CTIME_R -#undef asctime_r -#undef ctime_r -char *asctime_r P((struct tm const *, char *)); -char *ctime_r P((time_t const *, char *)); -#endif /* HAVE_INCOMPATIBLE_CTIME_R */ - -#ifndef YEARSPERREPEAT -#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */ -#endif /* !defined YEARSPERREPEAT */ - -/* -** The Gregorian year averages 365.2425 days, which is 31556952 seconds. -*/ - -#ifndef AVGSECSPERYEAR -#define AVGSECSPERYEAR 31556952L -#endif /* !defined AVGSECSPERYEAR */ - -#ifndef SECSPERREPEAT -#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR) -#endif /* !defined SECSPERREPEAT */ - -#ifndef SECSPERREPEAT_BITS -#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */ -#endif /* !defined SECSPERREPEAT_BITS */ - -/* -** UNIX was a registered trademark of The Open Group in 2003. -*/ - -#endif /* !defined PRIVATE_H */ diff --git a/libcutils/tzfile.h b/libcutils/tzfile.h deleted file mode 100644 index 8c7037558..000000000 --- a/libcutils/tzfile.h +++ /dev/null @@ -1,180 +0,0 @@ -#ifndef TZFILE_H - -#define TZFILE_H - -/* -** This file is in the public domain, so clarified as of -** 1996-06-05 by Arthur David Olson. -*/ - -/* -** This header is for use ONLY with the time conversion code. -** There is no guarantee that it will remain unchanged, -** or that it will remain at all. -** Do NOT copy it to any system include directory. -** Thank you! -*/ - -/* -** ID -*/ - -#ifndef lint -#ifndef NOID -static char tzfilehid[] = "@(#)tzfile.h 8.1"; -#endif /* !defined NOID */ -#endif /* !defined lint */ - -/* -** Information about time zone files. -*/ - -#ifndef TZDIR -#define TZDIR "/usr/share/zoneinfo" /* "/android/usr/share/zoneinfo" */ /* Time zone object file directory */ -#endif /* !defined TZDIR */ - -#ifndef TZDEFAULT -#define TZDEFAULT "localtime" -#endif /* !defined TZDEFAULT */ - -#ifndef TZDEFRULES -#define TZDEFRULES "posixrules" -#endif /* !defined TZDEFRULES */ - -/* -** Each file begins with. . . -*/ - -#define TZ_MAGIC "TZif" - -struct tzhead { - char tzh_magic[4]; /* TZ_MAGIC */ - char tzh_version[1]; /* '\0' or '2' as of 2005 */ - char tzh_reserved[15]; /* reserved--must be zero */ - char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */ - char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ - char tzh_leapcnt[4]; /* coded number of leap seconds */ - char tzh_timecnt[4]; /* coded number of transition times */ - char tzh_typecnt[4]; /* coded number of local time types */ - char tzh_charcnt[4]; /* coded number of abbr. chars */ -}; - -/* -** . . .followed by. . . -** -** tzh_timecnt (char [4])s coded transition times a la time(2) -** tzh_timecnt (unsigned char)s types of local time starting at above -** tzh_typecnt repetitions of -** one (char [4]) coded UTC offset in seconds -** one (unsigned char) used to set tm_isdst -** one (unsigned char) that's an abbreviation list index -** tzh_charcnt (char)s '\0'-terminated zone abbreviations -** tzh_leapcnt repetitions of -** one (char [4]) coded leap second transition times -** one (char [4]) total correction after above -** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition -** time is standard time, if FALSE, -** transition time is wall clock time -** if absent, transition times are -** assumed to be wall clock time -** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition -** time is UTC, if FALSE, -** transition time is local time -** if absent, transition times are -** assumed to be local time -*/ - -/* -** If tzh_version is '2' or greater, the above is followed by a second instance -** of tzhead and a second instance of the data in which each coded transition -** time uses 8 rather than 4 chars, -** then a POSIX-TZ-environment-variable-style string for use in handling -** instants after the last transition time stored in the file -** (with nothing between the newlines if there is no POSIX representation for -** such instants). -*/ - -/* -** In the current implementation, "tzset()" refuses to deal with files that -** exceed any of the limits below. -*/ - -#ifndef TZ_MAX_TIMES -#define TZ_MAX_TIMES 1200 -#endif /* !defined TZ_MAX_TIMES */ - -#ifndef TZ_MAX_TYPES -#ifndef NOSOLAR -#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ -#endif /* !defined NOSOLAR */ -#ifdef NOSOLAR -/* -** Must be at least 14 for Europe/Riga as of Jan 12 1995, -** as noted by Earl Chew. -*/ -#define TZ_MAX_TYPES 20 /* Maximum number of local time types */ -#endif /* !defined NOSOLAR */ -#endif /* !defined TZ_MAX_TYPES */ - -#ifndef TZ_MAX_CHARS -#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ - /* (limited by what unsigned chars can hold) */ -#endif /* !defined TZ_MAX_CHARS */ - -#ifndef TZ_MAX_LEAPS -#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ -#endif /* !defined TZ_MAX_LEAPS */ - -#define SECSPERMIN 60 -#define MINSPERHOUR 60 -#define HOURSPERDAY 24 -#define DAYSPERWEEK 7 -#define DAYSPERNYEAR 365 -#define DAYSPERLYEAR 366 -#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) -#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY) -#define MONSPERYEAR 12 - -#define TM_SUNDAY 0 -#define TM_MONDAY 1 -#define TM_TUESDAY 2 -#define TM_WEDNESDAY 3 -#define TM_THURSDAY 4 -#define TM_FRIDAY 5 -#define TM_SATURDAY 6 - -#define TM_JANUARY 0 -#define TM_FEBRUARY 1 -#define TM_MARCH 2 -#define TM_APRIL 3 -#define TM_MAY 4 -#define TM_JUNE 5 -#define TM_JULY 6 -#define TM_AUGUST 7 -#define TM_SEPTEMBER 8 -#define TM_OCTOBER 9 -#define TM_NOVEMBER 10 -#define TM_DECEMBER 11 - -#define TM_YEAR_BASE 1900 - -#define EPOCH_YEAR 1970 -#define EPOCH_WDAY TM_THURSDAY - -#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) - -/* -** Since everything in isleap is modulo 400 (or a factor of 400), we know that -** isleap(y) == isleap(y % 400) -** and so -** isleap(a + b) == isleap((a + b) % 400) -** or -** isleap(a + b) == isleap(a % 400 + b % 400) -** This is true even if % means modulo rather than Fortran remainder -** (which is allowed by C89 but not C99). -** We use this to avoid addition overflow problems. -*/ - -#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400) - -#endif /* !defined TZFILE_H */ diff --git a/libcutils/tzstrftime.c b/libcutils/tzstrftime.c deleted file mode 100644 index e4f54df5b..000000000 --- a/libcutils/tzstrftime.c +++ /dev/null @@ -1,842 +0,0 @@ -#ifndef lint -#ifndef NOID -static char elsieid[] = "@(#)strftime.c 8.1"; -/* -** Based on the UCB version with the ID appearing below. -** This is ANSIish only when "multibyte character == plain character". -*/ -#endif /* !defined NOID */ -#endif /* !defined lint */ - -#include -#include -#include -#include -#include - -/* -** Copyright (c) 1989 The Regents of the University of California. -** All rights reserved. -** -** Redistribution and use in source and binary forms are permitted -** provided that the above copyright notice and this paragraph are -** duplicated in all such forms and that any documentation, -** advertising materials, and other materials related to such -** distribution and use acknowledge that the software was developed -** by the University of California, Berkeley. The name of the -** University may not be used to endorse or promote products derived -** from this software without specific prior written permission. -** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED -** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -*/ - -#ifndef LIBC_SCCS -#ifndef lint -static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89"; -#endif /* !defined lint */ -#endif /* !defined LIBC_SCCS */ - -#include - -#define P(x) x - -static char * _add P((const char *, char *, const char *, int)); -static char * _conv P((int, const char *, char *, const char *)); -static char * _fmt P((const char *, const struct tm *, char *, const char *, - int *, const struct strftime_locale *Locale)); -static char * _yconv P((int, int, int, int, char *, const char *, int)); -static char * getformat P((int, char *, char *, char *, char *)); - -extern char * tzname[]; - - - - - -/* from private.h */ - -#ifndef TYPE_BIT -#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT) -#endif /* !defined TYPE_BIT */ - -#ifndef TYPE_SIGNED -#define TYPE_SIGNED(type) (((type) -1) < 0) -#endif /* !defined TYPE_SIGNED */ - -#ifndef INT_STRLEN_MAXIMUM -/* - * ** 302 / 1000 is log10(2.0) rounded up. - * ** Subtract one for the sign bit if the type is signed; - * ** add one for integer division truncation; - * ** add one more for a minus sign if the type is signed. - * */ -#define INT_STRLEN_MAXIMUM(type) \ - ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \ - 1 + TYPE_SIGNED(type)) -#endif /* !defined INT_STRLEN_MAXIMUM */ - -/* end of part from private.h */ - - - - -#ifndef YEAR_2000_NAME -#define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS" -#endif /* !defined YEAR_2000_NAME */ - -#define IN_NONE 0 -#define IN_SOME 1 -#define IN_THIS 2 -#define IN_ALL 3 - -#define FORCE_LOWER_CASE 0x100 - -size_t -strftime_tz(s, maxsize, format, t, Locale) -char * const s; -const size_t maxsize; -const char * const format; -const struct tm * const t; -const struct strftime_locale *Locale; -{ - char * p; - int warn; - - warn = IN_NONE; - p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn, Locale); -#if 0 - if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) { - (void) fprintf(stderr, "\n"); - if (format == NULL) - (void) fprintf(stderr, "NULL strftime format "); - else (void) fprintf(stderr, "strftime format \"%s\" ", - format); - (void) fprintf(stderr, "yields only two digits of years in "); - if (warn == IN_SOME) - (void) fprintf(stderr, "some locales"); - else if (warn == IN_THIS) - (void) fprintf(stderr, "the current locale"); - else (void) fprintf(stderr, "all locales"); - (void) fprintf(stderr, "\n"); - } -#endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */ - if (p == s + maxsize) - return 0; - *p = '\0'; - return p - s; -} - -static char *getformat(int modifier, char *normal, char *underscore, - char *dash, char *zero) { - switch (modifier) { - case '_': - return underscore; - - case '-': - return dash; - - case '0': - return zero; - } - - return normal; -} - -static char * -_fmt(format, t, pt, ptlim, warnp, Locale) -const char * format; -const struct tm * const t; -char * pt; -const char * const ptlim; -int * warnp; -const struct strftime_locale *Locale; -{ - for ( ; *format; ++format) { - if (*format == '%') { - int modifier = 0; -label: - switch (*++format) { - case '\0': - --format; - break; - case 'A': - pt = _add((t->tm_wday < 0 || - t->tm_wday >= DAYSPERWEEK) ? - "?" : Locale->weekday[t->tm_wday], - pt, ptlim, modifier); - continue; - case 'a': - pt = _add((t->tm_wday < 0 || - t->tm_wday >= DAYSPERWEEK) ? - "?" : Locale->wday[t->tm_wday], - pt, ptlim, modifier); - continue; - case 'B': - if (modifier == '-') { - pt = _add((t->tm_mon < 0 || - t->tm_mon >= MONSPERYEAR) ? - "?" : Locale->standalone_month[t->tm_mon], - pt, ptlim, modifier); - } else { - pt = _add((t->tm_mon < 0 || - t->tm_mon >= MONSPERYEAR) ? - "?" : Locale->month[t->tm_mon], - pt, ptlim, modifier); - } - continue; - case 'b': - case 'h': - pt = _add((t->tm_mon < 0 || - t->tm_mon >= MONSPERYEAR) ? - "?" : Locale->mon[t->tm_mon], - pt, ptlim, modifier); - continue; - case 'C': - /* - ** %C used to do a... - ** _fmt("%a %b %e %X %Y", t); - ** ...whereas now POSIX 1003.2 calls for - ** something completely different. - ** (ado, 1993-05-24) - */ - pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0, - pt, ptlim, modifier); - continue; - case 'c': - { - int warn2 = IN_SOME; - - pt = _fmt(Locale->c_fmt, t, pt, ptlim, warnp, Locale); - if (warn2 == IN_ALL) - warn2 = IN_THIS; - if (warn2 > *warnp) - *warnp = warn2; - } - continue; - case 'D': - pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp, Locale); - continue; - case 'd': - pt = _conv(t->tm_mday, - getformat(modifier, "%02d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 'E': - case 'O': - /* - ** C99 locale modifiers. - ** The sequences - ** %Ec %EC %Ex %EX %Ey %EY - ** %Od %oe %OH %OI %Om %OM - ** %OS %Ou %OU %OV %Ow %OW %Oy - ** are supposed to provide alternate - ** representations. - */ - goto label; - case '_': - case '-': - case '0': - case '^': - case '#': - modifier = *format; - goto label; - case 'e': - pt = _conv(t->tm_mday, - getformat(modifier, "%2d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 'F': - pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp, Locale); - continue; - case 'H': - pt = _conv(t->tm_hour, - getformat(modifier, "%02d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 'I': - pt = _conv((t->tm_hour % 12) ? - (t->tm_hour % 12) : 12, - getformat(modifier, "%02d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 'j': - pt = _conv(t->tm_yday + 1, - getformat(modifier, "%03d", "%3d", "%d", "%03d"), - pt, ptlim); - continue; - case 'k': - /* - ** This used to be... - ** _conv(t->tm_hour % 12 ? - ** t->tm_hour % 12 : 12, 2, ' '); - ** ...and has been changed to the below to - ** match SunOS 4.1.1 and Arnold Robbins' - ** strftime version 3.0. That is, "%k" and - ** "%l" have been swapped. - ** (ado, 1993-05-24) - */ - pt = _conv(t->tm_hour, - getformat(modifier, "%2d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; -#ifdef KITCHEN_SINK - case 'K': - /* - ** After all this time, still unclaimed! - */ - pt = _add("kitchen sink", pt, ptlim, modifier); - continue; -#endif /* defined KITCHEN_SINK */ - case 'l': - /* - ** This used to be... - ** _conv(t->tm_hour, 2, ' '); - ** ...and has been changed to the below to - ** match SunOS 4.1.1 and Arnold Robbin's - ** strftime version 3.0. That is, "%k" and - ** "%l" have been swapped. - ** (ado, 1993-05-24) - */ - pt = _conv((t->tm_hour % 12) ? - (t->tm_hour % 12) : 12, - getformat(modifier, "%2d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 'M': - pt = _conv(t->tm_min, - getformat(modifier, "%02d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 'm': - pt = _conv(t->tm_mon + 1, - getformat(modifier, "%02d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 'n': - pt = _add("\n", pt, ptlim, modifier); - continue; - case 'p': - pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ? - Locale->pm : - Locale->am, - pt, ptlim, modifier); - continue; - case 'P': - pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ? - Locale->pm : - Locale->am, - pt, ptlim, FORCE_LOWER_CASE); - continue; - case 'R': - pt = _fmt("%H:%M", t, pt, ptlim, warnp, Locale); - continue; - case 'r': - pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp, Locale); - continue; - case 'S': - pt = _conv(t->tm_sec, - getformat(modifier, "%02d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 's': - { - struct tm tm; - char buf[INT_STRLEN_MAXIMUM( - time_t) + 1]; - time_t mkt; - - tm = *t; - mkt = mktime(&tm); - if (TYPE_SIGNED(time_t)) - (void) sprintf(buf, "%ld", - (long) mkt); - else (void) sprintf(buf, "%lu", - (unsigned long) mkt); - pt = _add(buf, pt, ptlim, modifier); - } - continue; - case 'T': - pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp, Locale); - continue; - case 't': - pt = _add("\t", pt, ptlim, modifier); - continue; - case 'U': - pt = _conv((t->tm_yday + DAYSPERWEEK - - t->tm_wday) / DAYSPERWEEK, - getformat(modifier, "%02d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 'u': - /* - ** From Arnold Robbins' strftime version 3.0: - ** "ISO 8601: Weekday as a decimal number - ** [1 (Monday) - 7]" - ** (ado, 1993-05-24) - */ - pt = _conv((t->tm_wday == 0) ? - DAYSPERWEEK : t->tm_wday, "%d", pt, ptlim); - continue; - case 'V': /* ISO 8601 week number */ - case 'G': /* ISO 8601 year (four digits) */ - case 'g': /* ISO 8601 year (two digits) */ -/* -** From Arnold Robbins' strftime version 3.0: "the week number of the -** year (the first Monday as the first day of week 1) as a decimal number -** (01-53)." -** (ado, 1993-05-24) -** -** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn: -** "Week 01 of a year is per definition the first week which has the -** Thursday in this year, which is equivalent to the week which contains -** the fourth day of January. In other words, the first week of a new year -** is the week which has the majority of its days in the new year. Week 01 -** might also contain days from the previous year and the week before week -** 01 of a year is the last week (52 or 53) of the previous year even if -** it contains days from the new year. A week starts with Monday (day 1) -** and ends with Sunday (day 7). For example, the first week of the year -** 1997 lasts from 1996-12-30 to 1997-01-05..." -** (ado, 1996-01-02) -*/ - { - int year; - int base; - int yday; - int wday; - int w; - - year = t->tm_year; - base = TM_YEAR_BASE; - yday = t->tm_yday; - wday = t->tm_wday; - for ( ; ; ) { - int len; - int bot; - int top; - - len = isleap_sum(year, base) ? - DAYSPERLYEAR : - DAYSPERNYEAR; - /* - ** What yday (-3 ... 3) does - ** the ISO year begin on? - */ - bot = ((yday + 11 - wday) % - DAYSPERWEEK) - 3; - /* - ** What yday does the NEXT - ** ISO year begin on? - */ - top = bot - - (len % DAYSPERWEEK); - if (top < -3) - top += DAYSPERWEEK; - top += len; - if (yday >= top) { - ++base; - w = 1; - break; - } - if (yday >= bot) { - w = 1 + ((yday - bot) / - DAYSPERWEEK); - break; - } - --base; - yday += isleap_sum(year, base) ? - DAYSPERLYEAR : - DAYSPERNYEAR; - } -#ifdef XPG4_1994_04_09 - if ((w == 52 && - t->tm_mon == TM_JANUARY) || - (w == 1 && - t->tm_mon == TM_DECEMBER)) - w = 53; -#endif /* defined XPG4_1994_04_09 */ - if (*format == 'V') - pt = _conv(w, - getformat(modifier, - "%02d", - "%2d", - "%d", - "%02d"), - pt, ptlim); - else if (*format == 'g') { - *warnp = IN_ALL; - pt = _yconv(year, base, 0, 1, - pt, ptlim, modifier); - } else pt = _yconv(year, base, 1, 1, - pt, ptlim, modifier); - } - continue; - case 'v': - /* - ** From Arnold Robbins' strftime version 3.0: - ** "date as dd-bbb-YYYY" - ** (ado, 1993-05-24) - */ - pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp, Locale); - continue; - case 'W': - pt = _conv((t->tm_yday + DAYSPERWEEK - - (t->tm_wday ? - (t->tm_wday - 1) : - (DAYSPERWEEK - 1))) / DAYSPERWEEK, - getformat(modifier, "%02d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 'w': - pt = _conv(t->tm_wday, "%d", pt, ptlim); - continue; - case 'X': - pt = _fmt(Locale->X_fmt, t, pt, ptlim, warnp, Locale); - continue; - case 'x': - { - int warn2 = IN_SOME; - - pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2, Locale); - if (warn2 == IN_ALL) - warn2 = IN_THIS; - if (warn2 > *warnp) - *warnp = warn2; - } - continue; - case 'y': - *warnp = IN_ALL; - pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1, - pt, ptlim, modifier); - continue; - case 'Y': - pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1, - pt, ptlim, modifier); - continue; - case 'Z': -#ifdef TM_ZONE - if (t->TM_ZONE != NULL) - pt = _add(t->TM_ZONE, pt, ptlim, - modifier); - else -#endif /* defined TM_ZONE */ - if (t->tm_isdst >= 0) - pt = _add(tzname[t->tm_isdst != 0], - pt, ptlim, modifier); - /* - ** C99 says that %Z must be replaced by the - ** empty string if the time zone is not - ** determinable. - */ - continue; - case 'z': - { - int diff; - char const * sign; - - if (t->tm_isdst < 0) - continue; -#ifdef TM_GMTOFF - diff = t->TM_GMTOFF; -#else /* !defined TM_GMTOFF */ - /* - ** C99 says that the UTC offset must - ** be computed by looking only at - ** tm_isdst. This requirement is - ** incorrect, since it means the code - ** must rely on magic (in this case - ** altzone and timezone), and the - ** magic might not have the correct - ** offset. Doing things correctly is - ** tricky and requires disobeying C99; - ** see GNU C strftime for details. - ** For now, punt and conform to the - ** standard, even though it's incorrect. - ** - ** C99 says that %z must be replaced by the - ** empty string if the time zone is not - ** determinable, so output nothing if the - ** appropriate variables are not available. - */ - if (t->tm_isdst == 0) -#ifdef USG_COMPAT - diff = -timezone; -#else /* !defined USG_COMPAT */ - continue; -#endif /* !defined USG_COMPAT */ - else -#ifdef ALTZONE - diff = -altzone; -#else /* !defined ALTZONE */ - continue; -#endif /* !defined ALTZONE */ -#endif /* !defined TM_GMTOFF */ - if (diff < 0) { - sign = "-"; - diff = -diff; - } else sign = "+"; - pt = _add(sign, pt, ptlim, modifier); - diff /= SECSPERMIN; - diff = (diff / MINSPERHOUR) * 100 + - (diff % MINSPERHOUR); - pt = _conv(diff, - getformat(modifier, "%04d", - "%4d", "%d", "%04d"), - pt, ptlim); - } - continue; - case '+': - pt = _fmt(Locale->date_fmt, t, pt, ptlim, - warnp, Locale); - continue; - case '%': - /* - ** X311J/88-090 (4.12.3.5): if conversion char is - ** undefined, behavior is undefined. Print out the - ** character itself as printf(3) also does. - */ - default: - break; - } - } - if (pt == ptlim) - break; - *pt++ = *format; - } - return pt; -} - -static char * -_conv(n, format, pt, ptlim) -const int n; -const char * const format; -char * const pt; -const char * const ptlim; -{ - char buf[INT_STRLEN_MAXIMUM(int) + 1]; - - (void) sprintf(buf, format, n); - return _add(buf, pt, ptlim, 0); -} - -static char * -_add(str, pt, ptlim, modifier) -const char * str; -char * pt; -const char * const ptlim; -int modifier; -{ - int c; - - switch (modifier) { - case FORCE_LOWER_CASE: - while (pt < ptlim && (*pt = tolower(*str++)) != '\0') { - ++pt; - } - break; - - case '^': - while (pt < ptlim && (*pt = toupper(*str++)) != '\0') { - ++pt; - } - break; - - case '#': - while (pt < ptlim && (c = *str++) != '\0') { - if (isupper(c)) { - c = tolower(c); - } else if (islower(c)) { - c = toupper(c); - } - *pt = c; - ++pt; - } - - break; - - default: - while (pt < ptlim && (*pt = *str++) != '\0') { - ++pt; - } - } - - return pt; -} - -/* -** POSIX and the C Standard are unclear or inconsistent about -** what %C and %y do if the year is negative or exceeds 9999. -** Use the convention that %C concatenated with %y yields the -** same output as %Y, and that %Y contains at least 4 bytes, -** with more only if necessary. -*/ - -static char * -_yconv(a, b, convert_top, convert_yy, pt, ptlim, modifier) -const int a; -const int b; -const int convert_top; -const int convert_yy; -char * pt; -const char * const ptlim; -int modifier; -{ - register int lead; - register int trail; - -#define DIVISOR 100 - trail = a % DIVISOR + b % DIVISOR; - lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR; - trail %= DIVISOR; - if (trail < 0 && lead > 0) { - trail += DIVISOR; - --lead; - } else if (lead < 0 && trail > 0) { - trail -= DIVISOR; - ++lead; - } - if (convert_top) { - if (lead == 0 && trail < 0) - pt = _add("-0", pt, ptlim, modifier); - else pt = _conv(lead, getformat(modifier, "%02d", - "%2d", "%d", "%02d"), - pt, ptlim); - } - if (convert_yy) - pt = _conv(((trail < 0) ? -trail : trail), - getformat(modifier, "%02d", "%2d", "%d", "%02d"), - pt, ptlim); - return pt; -} - -#ifdef LOCALE_HOME -static struct lc_time_T * -_loc P((void)) -{ - static const char locale_home[] = LOCALE_HOME; - static const char lc_time[] = "LC_TIME"; - static char * locale_buf; - - int fd; - int oldsun; /* "...ain't got nothin' to do..." */ - char * lbuf; - char * name; - char * p; - const char ** ap; - const char * plim; - char filename[FILENAME_MAX]; - struct stat st; - size_t namesize; - size_t bufsize; - - /* - ** Use localebuf.mon[0] to signal whether locale is already set up. - */ - if (localebuf.mon[0]) - return &localebuf; - name = setlocale(LC_TIME, (char *) NULL); - if (name == NULL || *name == '\0') - goto no_locale; - /* - ** If the locale name is the same as our cache, use the cache. - */ - lbuf = locale_buf; - if (lbuf != NULL && strcmp(name, lbuf) == 0) { - p = lbuf; - for (ap = (const char **) &localebuf; - ap < (const char **) (&localebuf + 1); - ++ap) - *ap = p += strlen(p) + 1; - return &localebuf; - } - /* - ** Slurp the locale file into the cache. - */ - namesize = strlen(name) + 1; - if (sizeof filename < - ((sizeof locale_home) + namesize + (sizeof lc_time))) - goto no_locale; - oldsun = 0; - (void) sprintf(filename, "%s/%s/%s", locale_home, name, lc_time); - fd = open(filename, O_RDONLY); - if (fd < 0) { - /* - ** Old Sun systems have a different naming and data convention. - */ - oldsun = 1; - (void) sprintf(filename, "%s/%s/%s", locale_home, - lc_time, name); - fd = open(filename, O_RDONLY); - if (fd < 0) - goto no_locale; - } - if (fstat(fd, &st) != 0) - goto bad_locale; - if (st.st_size <= 0) - goto bad_locale; - bufsize = namesize + st.st_size; - locale_buf = NULL; - lbuf = (lbuf == NULL) ? malloc(bufsize) : realloc(lbuf, bufsize); - if (lbuf == NULL) - goto bad_locale; - (void) strcpy(lbuf, name); - p = lbuf + namesize; - plim = p + st.st_size; - if (read(fd, p, (size_t) st.st_size) != st.st_size) - goto bad_lbuf; - if (close(fd) != 0) - goto bad_lbuf; - /* - ** Parse the locale file into localebuf. - */ - if (plim[-1] != '\n') - goto bad_lbuf; - for (ap = (const char **) &localebuf; - ap < (const char **) (&localebuf + 1); - ++ap) { - if (p == plim) - goto bad_lbuf; - *ap = p; - while (*p != '\n') - ++p; - *p++ = '\0'; - } - if (oldsun) { - /* - ** SunOS 4 used an obsolescent format; see localdtconv(3). - ** c_fmt had the ``short format for dates and times together'' - ** (SunOS 4 date, "%a %b %e %T %Z %Y" in the C locale); - ** date_fmt had the ``long format for dates'' - ** (SunOS 4 strftime %C, "%A, %B %e, %Y" in the C locale). - ** Discard the latter in favor of the former. - */ - localebuf.date_fmt = localebuf.c_fmt; - } - /* - ** Record the successful parse in the cache. - */ - locale_buf = lbuf; - - return &localebuf; - -bad_lbuf: - free(lbuf); -bad_locale: - (void) close(fd); -no_locale: - localebuf = C_time_locale; - locale_buf = NULL; - return &localebuf; -} -#endif /* defined LOCALE_HOME */ diff --git a/libcutils/tztime.c b/libcutils/tztime.c deleted file mode 100644 index d6448a1da..000000000 --- a/libcutils/tztime.c +++ /dev/null @@ -1,1950 +0,0 @@ -/* -** This file is in the public domain, so clarified as of -** 1996-06-05 by Arthur David Olson. -*/ - -#include - -#ifndef lint -#ifndef NOID -static char elsieid[] = "@(#)localtime.c 8.3"; -#endif /* !defined NOID */ -#endif /* !defined lint */ - -/* -** Leap second handling from Bradley White. -** POSIX-style TZ environment variable handling from Guy Harris. -*/ - -/*LINTLIBRARY*/ - -#include "private.h" -#include "tzfile.h" -#include "fcntl.h" -#include "float.h" /* for FLT_MAX and DBL_MAX */ - -#ifndef TZ_ABBR_MAX_LEN -#define TZ_ABBR_MAX_LEN 16 -#endif /* !defined TZ_ABBR_MAX_LEN */ - -#ifndef TZ_ABBR_CHAR_SET -#define TZ_ABBR_CHAR_SET \ - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._" -#endif /* !defined TZ_ABBR_CHAR_SET */ - -#ifndef TZ_ABBR_ERR_CHAR -#define TZ_ABBR_ERR_CHAR '_' -#endif /* !defined TZ_ABBR_ERR_CHAR */ - -#define INDEXFILE "/system/usr/share/zoneinfo/zoneinfo.idx" -#define DATAFILE "/system/usr/share/zoneinfo/zoneinfo.dat" -#define NAMELEN 40 -#define INTLEN 4 -#define READLEN (NAMELEN + 3 * INTLEN) - -/* -** SunOS 4.1.1 headers lack O_BINARY. -*/ - -#ifdef O_BINARY -#define OPEN_MODE (O_RDONLY | O_BINARY) -#endif /* defined O_BINARY */ -#ifndef O_BINARY -#define OPEN_MODE O_RDONLY -#endif /* !defined O_BINARY */ - -/* Complex computations to determine the min/max of time_t depending - * on TYPE_BIT / TYPE_SIGNED / TYPE_INTEGRAL. - * These macros cannot be used in pre-processor directives, so we - * let the C compiler do the work, which makes things a bit funky. - */ -static const time_t TIME_T_MAX = - TYPE_INTEGRAL(time_t) ? - ( TYPE_SIGNED(time_t) ? - ~((time_t)1 << (TYPE_BIT(time_t)-1)) - : - ~(time_t)0 - ) - : /* if time_t is a floating point number */ - ( sizeof(time_t) > sizeof(float) ? (time_t)DBL_MAX : (time_t)FLT_MAX ); - -static const time_t TIME_T_MIN = - TYPE_INTEGRAL(time_t) ? - ( TYPE_SIGNED(time_t) ? - ((time_t)1 << (TYPE_BIT(time_t)-1)) - : - 0 - ) - : - ( sizeof(time_t) > sizeof(float) ? (time_t)DBL_MIN : (time_t)FLT_MIN ); - -#ifndef WILDABBR -/* -** Someone might make incorrect use of a time zone abbreviation: -** 1. They might reference tzname[0] before calling tzset (explicitly -** or implicitly). -** 2. They might reference tzname[1] before calling tzset (explicitly -** or implicitly). -** 3. They might reference tzname[1] after setting to a time zone -** in which Daylight Saving Time is never observed. -** 4. They might reference tzname[0] after setting to a time zone -** in which Standard Time is never observed. -** 5. They might reference tm.TM_ZONE after calling offtime. -** What's best to do in the above cases is open to debate; -** for now, we just set things up so that in any of the five cases -** WILDABBR is used. Another possibility: initialize tzname[0] to the -** string "tzname[0] used before set", and similarly for the other cases. -** And another: initialize tzname[0] to "ERA", with an explanation in the -** manual page of what this "time zone abbreviation" means (doing this so -** that tzname[0] has the "normal" length of three characters). -*/ -#define WILDABBR " " -#endif /* !defined WILDABBR */ - -static char wildabbr[] = WILDABBR; - -static const char gmt[] = "GMT"; - -/* -** The DST rules to use if TZ has no rules and we can't load TZDEFRULES. -** We default to US rules as of 1999-08-17. -** POSIX 1003.1 section 8.1.1 says that the default DST rules are -** implementation dependent; for historical reasons, US rules are a -** common default. -*/ -#ifndef TZDEFRULESTRING -#define TZDEFRULESTRING ",M4.1.0,M10.5.0" -#endif /* !defined TZDEFDST */ - -struct ttinfo { /* time type information */ - long tt_gmtoff; /* UTC offset in seconds */ - int tt_isdst; /* used to set tm_isdst */ - int tt_abbrind; /* abbreviation list index */ - int tt_ttisstd; /* TRUE if transition is std time */ - int tt_ttisgmt; /* TRUE if transition is UTC */ -}; - -struct lsinfo { /* leap second information */ - time_t ls_trans; /* transition time */ - long ls_corr; /* correction to apply */ -}; - -#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b)) - -#ifdef TZNAME_MAX -#define MY_TZNAME_MAX TZNAME_MAX -#endif /* defined TZNAME_MAX */ -#ifndef TZNAME_MAX -#define MY_TZNAME_MAX 255 -#endif /* !defined TZNAME_MAX */ - -struct state { - int leapcnt; - int timecnt; - int typecnt; - int charcnt; - int goback; - int goahead; - time_t ats[TZ_MAX_TIMES]; - unsigned char types[TZ_MAX_TIMES]; - struct ttinfo ttis[TZ_MAX_TYPES]; - char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt), - (2 * (MY_TZNAME_MAX + 1)))]; - struct lsinfo lsis[TZ_MAX_LEAPS]; -}; - -struct rule { - int r_type; /* type of rule--see below */ - int r_day; /* day number of rule */ - int r_week; /* week number of rule */ - int r_mon; /* month number of rule */ - long r_time; /* transition time of rule */ -}; - -#define JULIAN_DAY 0 /* Jn - Julian day */ -#define DAY_OF_YEAR 1 /* n - day of year */ -#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */ - -/* -** Prototypes for static functions. -*/ - -static long detzcode P((const char * codep)); -static time_t detzcode64 P((const char * codep)); -static int differ_by_repeat P((time_t t1, time_t t0)); -static const char * getzname P((const char * strp)); -static const char * getqzname P((const char * strp, const int delim)); -static const char * getnum P((const char * strp, int * nump, int min, - int max)); -static const char * getsecs P((const char * strp, long * secsp)); -static const char * getoffset P((const char * strp, long * offsetp)); -static const char * getrule P((const char * strp, struct rule * rulep)); -static void gmtload P((struct state * sp)); -static struct tm * gmtsub P((const time_t * timep, long offset, - struct tm * tmp)); -static struct tm * localsub P((const time_t * timep, long offset, - struct tm * tmp, const struct state *sp)); -static int increment_overflow P((int * number, int delta)); -static int leaps_thru_end_of P((int y)); -static int long_increment_overflow P((long * number, int delta)); -static int long_normalize_overflow P((long * tensptr, - int * unitsptr, int base)); -static int normalize_overflow P((int * tensptr, int * unitsptr, - int base)); -static void settzname P((void)); -static time_t time1 P((struct tm * tmp, - struct tm * (*funcp) P((const time_t *, - long, struct tm *, const struct state* sp)), - long offset, const struct state * sp)); -static time_t time2 P((struct tm *tmp, - struct tm * (*funcp) P((const time_t *, - long, struct tm*, const struct state* sp)), - long offset, int * okayp, const struct state * sp)); -static time_t time2sub P((struct tm *tmp, - struct tm * (*funcp) P((const time_t*, long, struct tm*,const struct state *sp)), - long offset, int * okayp, int do_norm_secs, - const struct state *sp)); -static struct tm * timesub P((const time_t * timep, long offset, - const struct state * sp, struct tm * tmp)); -static int tmcomp P((const struct tm * atmp, - const struct tm * btmp)); -static time_t transtime P((time_t janfirst, int year, - const struct rule * rulep, long offset)); -static int tzload P((const char * name, struct state * sp, - int doextend)); -static int tzload_uncached P((const char * name, struct state * sp, - int doextend)); -static int tzparse P((const char * name, struct state * sp, - int lastditch)); - -#ifdef ALL_STATE -static struct state * gmtptr; -#endif /* defined ALL_STATE */ - -#ifndef ALL_STATE -static struct state gmtmem; -#define gmtptr (&gmtmem) -#endif /* State Farm */ - -#define CACHE_COUNT 4 -static char * g_cacheNames[CACHE_COUNT] = {0,0}; -static struct state g_cacheStates[CACHE_COUNT]; -static int g_lastCache = 0; -static struct state g_utc; -unsigned char g_utcSet = 0; - - -#ifndef TZ_STRLEN_MAX -#define TZ_STRLEN_MAX 255 -#endif /* !defined TZ_STRLEN_MAX */ - -static char lcl_TZname[TZ_STRLEN_MAX + 1]; -static int lcl_is_set; -static int gmt_is_set; - -char * tzname[2] = { - wildabbr, - wildabbr -}; - -/* -** Section 4.12.3 of X3.159-1989 requires that -** Except for the strftime function, these functions [asctime, -** ctime, gmtime, localtime] return values in one of two static -** objects: a broken-down time structure and an array of char. -** Thanks to Paul Eggert for noting this. -*/ - -static struct tm tm; - -#ifdef USG_COMPAT -time_t timezone = 0; -int daylight = 0; -#endif /* defined USG_COMPAT */ - -#ifdef ALTZONE -time_t altzone = 0; -#endif /* defined ALTZONE */ - -static long -detzcode(codep) -const char * const codep; -{ - register long result; - register int i; - - result = (codep[0] & 0x80) ? ~0L : 0; - for (i = 0; i < 4; ++i) - result = (result << 8) | (codep[i] & 0xff); - return result; -} - -static time_t -detzcode64(codep) -const char * const codep; -{ - register time_t result; - register int i; - - result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0; - for (i = 0; i < 8; ++i) - result = result * 256 + (codep[i] & 0xff); - return result; -} - -static int -differ_by_repeat(t1, t0) -const time_t t1; -const time_t t0; -{ - if (TYPE_INTEGRAL(time_t) && - TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS) - return 0; - return t1 - t0 == SECSPERREPEAT; -} - -static int toint(unsigned char *s) { - return (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; -} - -static int -tzload(const char *name, struct state * const sp, const int doextend) -{ - if (name) { - int i, err; - if (0 == strcmp(name, "UTC")) { - if (!g_utcSet) { - tzload_uncached(name, &g_utc, 1); - g_utcSet = 1; - } - //printf("tzload: utc\n"); - *sp = g_utc; - return 0; - } - for (i=0; i= CACHE_COUNT) { - g_lastCache = 0; - } - i = g_lastCache; - if (g_cacheNames[i]) { - free(g_cacheNames[i]); - } - err = tzload_uncached(name, &(g_cacheStates[i]), 1); - if (err == 0) { - g_cacheNames[i] = strdup(name); - *sp = g_cacheStates[i]; - return 0; - } else { - g_cacheNames[i] = NULL; - return err; - } - } - return tzload_uncached(name, sp, doextend); -} - -static int -tzload_uncached(name, sp, doextend) -register const char * name; -register struct state * const sp; -register const int doextend; -{ - register const char * p; - register int i; - register int fid; - register int stored; - register int nread; - union { - struct tzhead tzhead; - char buf[2 * sizeof(struct tzhead) + - 2 * sizeof *sp + - 4 * TZ_MAX_TIMES]; - } u; - int toread = sizeof u.buf; - - if (name == NULL && (name = TZDEFAULT) == NULL) - return -1; - { - register int doaccess; - /* - ** Section 4.9.1 of the C standard says that - ** "FILENAME_MAX expands to an integral constant expression - ** that is the size needed for an array of char large enough - ** to hold the longest file name string that the implementation - ** guarantees can be opened." - */ - char fullname[FILENAME_MAX + 1]; - const char *origname = name; - - if (name[0] == ':') - ++name; - doaccess = name[0] == '/'; - if (!doaccess) { - if ((p = TZDIR) == NULL) - return -1; - if ((strlen(p) + strlen(name) + 1) >= sizeof fullname) - return -1; - (void) strcpy(fullname, p); - (void) strcat(fullname, "/"); - (void) strcat(fullname, name); - /* - ** Set doaccess if '.' (as in "../") shows up in name. - */ - if (strchr(name, '.') != NULL) - doaccess = TRUE; - name = fullname; - } - if (doaccess && access(name, R_OK) != 0) - return -1; - if ((fid = open(name, OPEN_MODE)) == -1) { - char buf[READLEN]; - char name[NAMELEN + 1]; - int fidix = open(INDEXFILE, OPEN_MODE); - int off = -1; - - if (fidix < 0) { - return -1; - } - - while (read(fidix, buf, sizeof(buf)) == sizeof(buf)) { - memcpy(name, buf, NAMELEN); - name[NAMELEN] = '\0'; - - if (strcmp(name, origname) == 0) { - off = toint((unsigned char *) buf + NAMELEN); - toread = toint((unsigned char *) buf + NAMELEN + INTLEN); - break; - } - } - - close(fidix); - - if (off < 0) - return -1; - - fid = open(DATAFILE, OPEN_MODE); - - if (fid < 0) { - return -1; - } - - if (lseek(fid, off, SEEK_SET) < 0) { - return -1; - } - } - } - nread = read(fid, u.buf, toread); - if (close(fid) < 0 || nread <= 0) - return -1; - for (stored = 4; stored <= 8; stored *= 2) { - int ttisstdcnt; - int ttisgmtcnt; - - ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt); - ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt); - sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt); - sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt); - sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt); - sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt); - p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt; - if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS || - sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES || - sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES || - sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS || - (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) || - (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0)) - return -1; - if (nread - (p - u.buf) < - sp->timecnt * stored + /* ats */ - sp->timecnt + /* types */ - sp->typecnt * 6 + /* ttinfos */ - sp->charcnt + /* chars */ - sp->leapcnt * (stored + 4) + /* lsinfos */ - ttisstdcnt + /* ttisstds */ - ttisgmtcnt) /* ttisgmts */ - return -1; - for (i = 0; i < sp->timecnt; ++i) { - sp->ats[i] = (stored == 4) ? - detzcode(p) : detzcode64(p); - p += stored; - } - for (i = 0; i < sp->timecnt; ++i) { - sp->types[i] = (unsigned char) *p++; - if (sp->types[i] >= sp->typecnt) - return -1; - } - for (i = 0; i < sp->typecnt; ++i) { - register struct ttinfo * ttisp; - - ttisp = &sp->ttis[i]; - ttisp->tt_gmtoff = detzcode(p); - p += 4; - ttisp->tt_isdst = (unsigned char) *p++; - if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1) - return -1; - ttisp->tt_abbrind = (unsigned char) *p++; - if (ttisp->tt_abbrind < 0 || - ttisp->tt_abbrind > sp->charcnt) - return -1; - } - for (i = 0; i < sp->charcnt; ++i) - sp->chars[i] = *p++; - sp->chars[i] = '\0'; /* ensure '\0' at end */ - for (i = 0; i < sp->leapcnt; ++i) { - register struct lsinfo * lsisp; - - lsisp = &sp->lsis[i]; - lsisp->ls_trans = (stored == 4) ? - detzcode(p) : detzcode64(p); - p += stored; - lsisp->ls_corr = detzcode(p); - p += 4; - } - for (i = 0; i < sp->typecnt; ++i) { - register struct ttinfo * ttisp; - - ttisp = &sp->ttis[i]; - if (ttisstdcnt == 0) - ttisp->tt_ttisstd = FALSE; - else { - ttisp->tt_ttisstd = *p++; - if (ttisp->tt_ttisstd != TRUE && - ttisp->tt_ttisstd != FALSE) - return -1; - } - } - for (i = 0; i < sp->typecnt; ++i) { - register struct ttinfo * ttisp; - - ttisp = &sp->ttis[i]; - if (ttisgmtcnt == 0) - ttisp->tt_ttisgmt = FALSE; - else { - ttisp->tt_ttisgmt = *p++; - if (ttisp->tt_ttisgmt != TRUE && - ttisp->tt_ttisgmt != FALSE) - return -1; - } - } - /* - ** Out-of-sort ats should mean we're running on a - ** signed time_t system but using a data file with - ** unsigned values (or vice versa). - */ - for (i = 0; i < sp->timecnt - 2; ++i) - if (sp->ats[i] > sp->ats[i + 1]) { - ++i; - if (TYPE_SIGNED(time_t)) { - /* - ** Ignore the end (easy). - */ - sp->timecnt = i; - } else { - /* - ** Ignore the beginning (harder). - */ - register int j; - - for (j = 0; j + i < sp->timecnt; ++j) { - sp->ats[j] = sp->ats[j + i]; - sp->types[j] = sp->types[j + i]; - } - sp->timecnt = j; - } - break; - } - /* - ** If this is an old file, we're done. - */ - if (u.tzhead.tzh_version[0] == '\0') - break; - nread -= p - u.buf; - for (i = 0; i < nread; ++i) - u.buf[i] = p[i]; - /* - ** If this is a narrow integer time_t system, we're done. - */ - if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t)) - break; - } - if (doextend && nread > 2 && - u.buf[0] == '\n' && u.buf[nread - 1] == '\n' && - sp->typecnt + 2 <= TZ_MAX_TYPES) { - struct state ts; - register int result; - - u.buf[nread - 1] = '\0'; - result = tzparse(&u.buf[1], &ts, FALSE); - if (result == 0 && ts.typecnt == 2 && - sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) { - for (i = 0; i < 2; ++i) - ts.ttis[i].tt_abbrind += - sp->charcnt; - for (i = 0; i < ts.charcnt; ++i) - sp->chars[sp->charcnt++] = - ts.chars[i]; - i = 0; - while (i < ts.timecnt && - ts.ats[i] <= - sp->ats[sp->timecnt - 1]) - ++i; - while (i < ts.timecnt && - sp->timecnt < TZ_MAX_TIMES) { - sp->ats[sp->timecnt] = - ts.ats[i]; - sp->types[sp->timecnt] = - sp->typecnt + - ts.types[i]; - ++sp->timecnt; - ++i; - } - sp->ttis[sp->typecnt++] = ts.ttis[0]; - sp->ttis[sp->typecnt++] = ts.ttis[1]; - } - } - i = 2 * YEARSPERREPEAT; - sp->goback = sp->goahead = sp->timecnt > i; - sp->goback &= sp->types[i] == sp->types[0] && - differ_by_repeat(sp->ats[i], sp->ats[0]); - sp->goahead &= - sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] && - differ_by_repeat(sp->ats[sp->timecnt - 1], - sp->ats[sp->timecnt - 1 - i]); - return 0; -} - -static const int mon_lengths[2][MONSPERYEAR] = { - { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, - { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } -}; - -static const int year_lengths[2] = { - DAYSPERNYEAR, DAYSPERLYEAR -}; - -/* -** Given a pointer into a time zone string, scan until a character that is not -** a valid character in a zone name is found. Return a pointer to that -** character. -*/ - -static const char * -getzname(strp) -register const char * strp; -{ - register char c; - - while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' && - c != '+') - ++strp; - return strp; -} - -/* -** Given a pointer into an extended time zone string, scan until the ending -** delimiter of the zone name is located. Return a pointer to the delimiter. -** -** As with getzname above, the legal character set is actually quite -** restricted, with other characters producing undefined results. -** We don't do any checking here; checking is done later in common-case code. -*/ - -static const char * -getqzname(register const char *strp, const int delim) -{ - register int c; - - while ((c = *strp) != '\0' && c != delim) - ++strp; - return strp; -} - -/* -** Given a pointer into a time zone string, extract a number from that string. -** Check that the number is within a specified range; if it is not, return -** NULL. -** Otherwise, return a pointer to the first character not part of the number. -*/ - -static const char * -getnum(strp, nump, min, max) -register const char * strp; -int * const nump; -const int min; -const int max; -{ - register char c; - register int num; - - if (strp == NULL || !is_digit(c = *strp)) - return NULL; - num = 0; - do { - num = num * 10 + (c - '0'); - if (num > max) - return NULL; /* illegal value */ - c = *++strp; - } while (is_digit(c)); - if (num < min) - return NULL; /* illegal value */ - *nump = num; - return strp; -} - -/* -** Given a pointer into a time zone string, extract a number of seconds, -** in hh[:mm[:ss]] form, from the string. -** If any error occurs, return NULL. -** Otherwise, return a pointer to the first character not part of the number -** of seconds. -*/ - -static const char * -getsecs(strp, secsp) -register const char * strp; -long * const secsp; -{ - int num; - - /* - ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like - ** "M10.4.6/26", which does not conform to Posix, - ** but which specifies the equivalent of - ** ``02:00 on the first Sunday on or after 23 Oct''. - */ - strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1); - if (strp == NULL) - return NULL; - *secsp = num * (long) SECSPERHOUR; - if (*strp == ':') { - ++strp; - strp = getnum(strp, &num, 0, MINSPERHOUR - 1); - if (strp == NULL) - return NULL; - *secsp += num * SECSPERMIN; - if (*strp == ':') { - ++strp; - /* `SECSPERMIN' allows for leap seconds. */ - strp = getnum(strp, &num, 0, SECSPERMIN); - if (strp == NULL) - return NULL; - *secsp += num; - } - } - return strp; -} - -/* -** Given a pointer into a time zone string, extract an offset, in -** [+-]hh[:mm[:ss]] form, from the string. -** If any error occurs, return NULL. -** Otherwise, return a pointer to the first character not part of the time. -*/ - -static const char * -getoffset(strp, offsetp) -register const char * strp; -long * const offsetp; -{ - register int neg = 0; - - if (*strp == '-') { - neg = 1; - ++strp; - } else if (*strp == '+') - ++strp; - strp = getsecs(strp, offsetp); - if (strp == NULL) - return NULL; /* illegal time */ - if (neg) - *offsetp = -*offsetp; - return strp; -} - -/* -** Given a pointer into a time zone string, extract a rule in the form -** date[/time]. See POSIX section 8 for the format of "date" and "time". -** If a valid rule is not found, return NULL. -** Otherwise, return a pointer to the first character not part of the rule. -*/ - -static const char * -getrule(strp, rulep) -const char * strp; -register struct rule * const rulep; -{ - if (*strp == 'J') { - /* - ** Julian day. - */ - rulep->r_type = JULIAN_DAY; - ++strp; - strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR); - } else if (*strp == 'M') { - /* - ** Month, week, day. - */ - rulep->r_type = MONTH_NTH_DAY_OF_WEEK; - ++strp; - strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR); - if (strp == NULL) - return NULL; - if (*strp++ != '.') - return NULL; - strp = getnum(strp, &rulep->r_week, 1, 5); - if (strp == NULL) - return NULL; - if (*strp++ != '.') - return NULL; - strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1); - } else if (is_digit(*strp)) { - /* - ** Day of year. - */ - rulep->r_type = DAY_OF_YEAR; - strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); - } else return NULL; /* invalid format */ - if (strp == NULL) - return NULL; - if (*strp == '/') { - /* - ** Time specified. - */ - ++strp; - strp = getsecs(strp, &rulep->r_time); - } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ - return strp; -} - -/* -** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the -** year, a rule, and the offset from UTC at the time that rule takes effect, -** calculate the Epoch-relative time that rule takes effect. -*/ - -static time_t -transtime(janfirst, year, rulep, offset) -const time_t janfirst; -const int year; -register const struct rule * const rulep; -const long offset; -{ - register int leapyear; - register time_t value; - register int i; - int d, m1, yy0, yy1, yy2, dow; - - INITIALIZE(value); - leapyear = isleap(year); - switch (rulep->r_type) { - - case JULIAN_DAY: - /* - ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap - ** years. - ** In non-leap years, or if the day number is 59 or less, just - ** add SECSPERDAY times the day number-1 to the time of - ** January 1, midnight, to get the day. - */ - value = janfirst + (rulep->r_day - 1) * SECSPERDAY; - if (leapyear && rulep->r_day >= 60) - value += SECSPERDAY; - break; - - case DAY_OF_YEAR: - /* - ** n - day of year. - ** Just add SECSPERDAY times the day number to the time of - ** January 1, midnight, to get the day. - */ - value = janfirst + rulep->r_day * SECSPERDAY; - break; - - case MONTH_NTH_DAY_OF_WEEK: - /* - ** Mm.n.d - nth "dth day" of month m. - */ - value = janfirst; - for (i = 0; i < rulep->r_mon - 1; ++i) - value += mon_lengths[leapyear][i] * SECSPERDAY; - - /* - ** Use Zeller's Congruence to get day-of-week of first day of - ** month. - */ - m1 = (rulep->r_mon + 9) % 12 + 1; - yy0 = (rulep->r_mon <= 2) ? (year - 1) : year; - yy1 = yy0 / 100; - yy2 = yy0 % 100; - dow = ((26 * m1 - 2) / 10 + - 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7; - if (dow < 0) - dow += DAYSPERWEEK; - - /* - ** "dow" is the day-of-week of the first day of the month. Get - ** the day-of-month (zero-origin) of the first "dow" day of the - ** month. - */ - d = rulep->r_day - dow; - if (d < 0) - d += DAYSPERWEEK; - for (i = 1; i < rulep->r_week; ++i) { - if (d + DAYSPERWEEK >= - mon_lengths[leapyear][rulep->r_mon - 1]) - break; - d += DAYSPERWEEK; - } - - /* - ** "d" is the day-of-month (zero-origin) of the day we want. - */ - value += d * SECSPERDAY; - break; - } - - /* - ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in - ** question. To get the Epoch-relative time of the specified local - ** time on that day, add the transition time and the current offset - ** from UTC. - */ - return value + rulep->r_time + offset; -} - -/* -** Given a POSIX section 8-style TZ string, fill in the rule tables as -** appropriate. -*/ - -static int -tzparse(name, sp, lastditch) -const char * name; -register struct state * const sp; -const int lastditch; -{ - const char * stdname; - const char * dstname; - size_t stdlen; - size_t dstlen; - long stdoffset; - long dstoffset; - register time_t * atp; - register unsigned char * typep; - register char * cp; - register int load_result; - - INITIALIZE(dstname); - stdname = name; - if (lastditch) { - stdlen = strlen(name); /* length of standard zone name */ - name += stdlen; - if (stdlen >= sizeof sp->chars) - stdlen = (sizeof sp->chars) - 1; - stdoffset = 0; - } else { - if (*name == '<') { - name++; - stdname = name; - name = getqzname(name, '>'); - if (*name != '>') - return (-1); - stdlen = name - stdname; - name++; - } else { - name = getzname(name); - stdlen = name - stdname; - } - if (*name == '\0') - return -1; - name = getoffset(name, &stdoffset); - if (name == NULL) - return -1; - } - load_result = tzload(TZDEFRULES, sp, FALSE); - if (load_result != 0) - sp->leapcnt = 0; /* so, we're off a little */ - sp->timecnt = 0; - if (*name != '\0') { - if (*name == '<') { - dstname = ++name; - name = getqzname(name, '>'); - if (*name != '>') - return -1; - dstlen = name - dstname; - name++; - } else { - dstname = name; - name = getzname(name); - dstlen = name - dstname; /* length of DST zone name */ - } - if (*name != '\0' && *name != ',' && *name != ';') { - name = getoffset(name, &dstoffset); - if (name == NULL) - return -1; - } else dstoffset = stdoffset - SECSPERHOUR; - if (*name == '\0' && load_result != 0) - name = TZDEFRULESTRING; - if (*name == ',' || *name == ';') { - struct rule start; - struct rule end; - register int year; - register time_t janfirst; - time_t starttime; - time_t endtime; - - ++name; - if ((name = getrule(name, &start)) == NULL) - return -1; - if (*name++ != ',') - return -1; - if ((name = getrule(name, &end)) == NULL) - return -1; - if (*name != '\0') - return -1; - sp->typecnt = 2; /* standard time and DST */ - /* - ** Two transitions per year, from EPOCH_YEAR forward. - */ - sp->ttis[0].tt_gmtoff = -dstoffset; - sp->ttis[0].tt_isdst = 1; - sp->ttis[0].tt_abbrind = stdlen + 1; - sp->ttis[1].tt_gmtoff = -stdoffset; - sp->ttis[1].tt_isdst = 0; - sp->ttis[1].tt_abbrind = 0; - atp = sp->ats; - typep = sp->types; - janfirst = 0; - for (year = EPOCH_YEAR; - sp->timecnt + 2 <= TZ_MAX_TIMES; - ++year) { - time_t newfirst; - - starttime = transtime(janfirst, year, &start, - stdoffset); - endtime = transtime(janfirst, year, &end, - dstoffset); - if (starttime > endtime) { - *atp++ = endtime; - *typep++ = 1; /* DST ends */ - *atp++ = starttime; - *typep++ = 0; /* DST begins */ - } else { - *atp++ = starttime; - *typep++ = 0; /* DST begins */ - *atp++ = endtime; - *typep++ = 1; /* DST ends */ - } - sp->timecnt += 2; - newfirst = janfirst; - newfirst += year_lengths[isleap(year)] * - SECSPERDAY; - if (newfirst <= janfirst) - break; - janfirst = newfirst; - } - } else { - register long theirstdoffset; - register long theirdstoffset; - register long theiroffset; - register int isdst; - register int i; - register int j; - - if (*name != '\0') - return -1; - /* - ** Initial values of theirstdoffset and theirdstoffset. - */ - theirstdoffset = 0; - for (i = 0; i < sp->timecnt; ++i) { - j = sp->types[i]; - if (!sp->ttis[j].tt_isdst) { - theirstdoffset = - -sp->ttis[j].tt_gmtoff; - break; - } - } - theirdstoffset = 0; - for (i = 0; i < sp->timecnt; ++i) { - j = sp->types[i]; - if (sp->ttis[j].tt_isdst) { - theirdstoffset = - -sp->ttis[j].tt_gmtoff; - break; - } - } - /* - ** Initially we're assumed to be in standard time. - */ - isdst = FALSE; - theiroffset = theirstdoffset; - /* - ** Now juggle transition times and types - ** tracking offsets as you do. - */ - for (i = 0; i < sp->timecnt; ++i) { - j = sp->types[i]; - sp->types[i] = sp->ttis[j].tt_isdst; - if (sp->ttis[j].tt_ttisgmt) { - /* No adjustment to transition time */ - } else { - /* - ** If summer time is in effect, and the - ** transition time was not specified as - ** standard time, add the summer time - ** offset to the transition time; - ** otherwise, add the standard time - ** offset to the transition time. - */ - /* - ** Transitions from DST to DDST - ** will effectively disappear since - ** POSIX provides for only one DST - ** offset. - */ - if (isdst && !sp->ttis[j].tt_ttisstd) { - sp->ats[i] += dstoffset - - theirdstoffset; - } else { - sp->ats[i] += stdoffset - - theirstdoffset; - } - } - theiroffset = -sp->ttis[j].tt_gmtoff; - if (sp->ttis[j].tt_isdst) - theirdstoffset = theiroffset; - else theirstdoffset = theiroffset; - } - /* - ** Finally, fill in ttis. - ** ttisstd and ttisgmt need not be handled. - */ - sp->ttis[0].tt_gmtoff = -stdoffset; - sp->ttis[0].tt_isdst = FALSE; - sp->ttis[0].tt_abbrind = 0; - sp->ttis[1].tt_gmtoff = -dstoffset; - sp->ttis[1].tt_isdst = TRUE; - sp->ttis[1].tt_abbrind = stdlen + 1; - sp->typecnt = 2; - } - } else { - dstlen = 0; - sp->typecnt = 1; /* only standard time */ - sp->timecnt = 0; - sp->ttis[0].tt_gmtoff = -stdoffset; - sp->ttis[0].tt_isdst = 0; - sp->ttis[0].tt_abbrind = 0; - } - sp->charcnt = stdlen + 1; - if (dstlen != 0) - sp->charcnt += dstlen + 1; - if ((size_t) sp->charcnt > sizeof sp->chars) - return -1; - cp = sp->chars; - (void) strncpy(cp, stdname, stdlen); - cp += stdlen; - *cp++ = '\0'; - if (dstlen != 0) { - (void) strncpy(cp, dstname, dstlen); - *(cp + dstlen) = '\0'; - } - return 0; -} - -static void -gmtload(sp) -struct state * const sp; -{ - if (tzload(gmt, sp, TRUE) != 0) - (void) tzparse(gmt, sp, TRUE); -} - -/* -** The easy way to behave "as if no library function calls" localtime -** is to not call it--so we drop its guts into "localsub", which can be -** freely called. (And no, the PANS doesn't require the above behavior-- -** but it *is* desirable.) -** -** The unused offset argument is for the benefit of mktime variants. -*/ - -/*ARGSUSED*/ -static struct tm * -localsub(timep, offset, tmp, sp) -const time_t * const timep; -const long offset; -struct tm * const tmp; -const struct state * sp; -{ - register const struct ttinfo * ttisp; - register int i; - register struct tm * result; - const time_t t = *timep; - -#ifdef ALL_STATE - if (sp == NULL) - return gmtsub(timep, offset, tmp); -#endif /* defined ALL_STATE */ - if ((sp->goback && t < sp->ats[0]) || - (sp->goahead && t > sp->ats[sp->timecnt - 1])) { - time_t newt = t; - register time_t seconds; - register time_t tcycles; - register int_fast64_t icycles; - - if (t < sp->ats[0]) - seconds = sp->ats[0] - t; - else seconds = t - sp->ats[sp->timecnt - 1]; - --seconds; - tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR; - ++tcycles; - icycles = tcycles; - if (tcycles - icycles >= 1 || icycles - tcycles >= 1) - return NULL; - seconds = icycles; - seconds *= YEARSPERREPEAT; - seconds *= AVGSECSPERYEAR; - if (t < sp->ats[0]) - newt += seconds; - else newt -= seconds; - if (newt < sp->ats[0] || - newt > sp->ats[sp->timecnt - 1]) - return NULL; /* "cannot happen" */ - result = localsub(&newt, offset, tmp, sp); - if (result == tmp) { - register time_t newy; - - newy = tmp->tm_year; - if (t < sp->ats[0]) - newy -= icycles * YEARSPERREPEAT; - else newy += icycles * YEARSPERREPEAT; - tmp->tm_year = newy; - if (tmp->tm_year != newy) - return NULL; - } - return result; - } - if (sp->timecnt == 0 || t < sp->ats[0]) { - i = 0; - while (sp->ttis[i].tt_isdst) - if (++i >= sp->typecnt) { - i = 0; - break; - } - } else { - register int lo = 1; - register int hi = sp->timecnt; - - while (lo < hi) { - register int mid = (lo + hi) >> 1; - - if (t < sp->ats[mid]) - hi = mid; - else lo = mid + 1; - } - i = (int) sp->types[lo - 1]; - } - ttisp = &sp->ttis[i]; - /* - ** To get (wrong) behavior that's compatible with System V Release 2.0 - ** you'd replace the statement below with - ** t += ttisp->tt_gmtoff; - ** timesub(&t, 0L, sp, tmp); - */ - result = timesub(&t, ttisp->tt_gmtoff, sp, tmp); - tmp->tm_isdst = ttisp->tt_isdst; -#ifdef HAVE_TM_GMTOFF - tmp->tm_gmtoff = ttisp->tt_gmtoff; -#endif - tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind]; -#ifdef TM_ZONE - tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind]; -#endif /* defined TM_ZONE */ - return result; -} - - -// ============================================================================ -#if 0 -struct tm * -localtime(timep) -const time_t * const timep; -{ - tzset(); - return localsub(timep, 0L, &tm); -} -#endif - -/* -** Re-entrant version of localtime. -*/ - -// ============================================================================ -void -localtime_tz(const time_t * const timep, struct tm * tmp, const char* tz) -{ - struct state st; - if (tzload(tz, &st, TRUE) != 0) { - // not sure what's best here, but for now, we fall back to gmt - gmtload(&st); - } - - localsub(timep, 0L, tmp, &st); -} - -/* -** gmtsub is to gmtime as localsub is to localtime. -*/ - -static struct tm * -gmtsub(timep, offset, tmp) -const time_t * const timep; -const long offset; -struct tm * const tmp; -{ - register struct tm * result; - - if (!gmt_is_set) { - gmt_is_set = TRUE; -#ifdef ALL_STATE - gmtptr = (struct state *) malloc(sizeof *gmtptr); - if (gmtptr != NULL) -#endif /* defined ALL_STATE */ - gmtload(gmtptr); - } - result = timesub(timep, offset, gmtptr, tmp); -#ifdef TM_ZONE - /* - ** Could get fancy here and deliver something such as - ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero, - ** but this is no time for a treasure hunt. - */ - if (offset != 0) - tmp->TM_ZONE = wildabbr; - else { -#ifdef ALL_STATE - if (gmtptr == NULL) - tmp->TM_ZONE = gmt; - else tmp->TM_ZONE = gmtptr->chars; -#endif /* defined ALL_STATE */ -#ifndef ALL_STATE - tmp->TM_ZONE = gmtptr->chars; -#endif /* State Farm */ - } -#endif /* defined TM_ZONE */ - return result; -} - -// ============================================================================ -#if 0 -struct tm * -gmtime(timep) -const time_t * const timep; -{ - return gmtsub(timep, 0L, &tm); -} -#endif - -/* -* Re-entrant version of gmtime. -*/ - -// ============================================================================ -#if 0 -struct tm * -gmtime_r(timep, tmp) -const time_t * const timep; -struct tm * tmp; -{ - return gmtsub(timep, 0L, tmp); -} -#endif - -#ifdef STD_INSPIRED - -// ============================================================================ -#if 0 -struct tm * -offtime(timep, offset) -const time_t * const timep; -const long offset; -{ - return gmtsub(timep, offset, &tm); -} -#endif - -#endif /* defined STD_INSPIRED */ - -/* -** Return the number of leap years through the end of the given year -** where, to make the math easy, the answer for year zero is defined as zero. -*/ - -static int -leaps_thru_end_of(y) -register const int y; -{ - return (y >= 0) ? (y / 4 - y / 100 + y / 400) : - -(leaps_thru_end_of(-(y + 1)) + 1); -} - -static struct tm * -timesub(timep, offset, sp, tmp) -const time_t * const timep; -const long offset; -register const struct state * const sp; -register struct tm * const tmp; -{ - register const struct lsinfo * lp; - register time_t tdays; - register int idays; /* unsigned would be so 2003 */ - register long rem; - int y; - register const int * ip; - register long corr; - register int hit; - register int i; - - corr = 0; - hit = 0; -#ifdef ALL_STATE - i = (sp == NULL) ? 0 : sp->leapcnt; -#endif /* defined ALL_STATE */ -#ifndef ALL_STATE - i = sp->leapcnt; -#endif /* State Farm */ - while (--i >= 0) { - lp = &sp->lsis[i]; - if (*timep >= lp->ls_trans) { - if (*timep == lp->ls_trans) { - hit = ((i == 0 && lp->ls_corr > 0) || - lp->ls_corr > sp->lsis[i - 1].ls_corr); - if (hit) - while (i > 0 && - sp->lsis[i].ls_trans == - sp->lsis[i - 1].ls_trans + 1 && - sp->lsis[i].ls_corr == - sp->lsis[i - 1].ls_corr + 1) { - ++hit; - --i; - } - } - corr = lp->ls_corr; - break; - } - } - y = EPOCH_YEAR; - tdays = *timep / SECSPERDAY; - rem = *timep - tdays * SECSPERDAY; - while (tdays < 0 || tdays >= year_lengths[isleap(y)]) { - int newy; - register time_t tdelta; - register int idelta; - register int leapdays; - - tdelta = tdays / DAYSPERLYEAR; - idelta = tdelta; - if (tdelta - idelta >= 1 || idelta - tdelta >= 1) - return NULL; - if (idelta == 0) - idelta = (tdays < 0) ? -1 : 1; - newy = y; - if (increment_overflow(&newy, idelta)) - return NULL; - leapdays = leaps_thru_end_of(newy - 1) - - leaps_thru_end_of(y - 1); - tdays -= ((time_t) newy - y) * DAYSPERNYEAR; - tdays -= leapdays; - y = newy; - } - { - register long seconds; - - seconds = tdays * SECSPERDAY + 0.5; - tdays = seconds / SECSPERDAY; - rem += seconds - tdays * SECSPERDAY; - } - /* - ** Given the range, we can now fearlessly cast... - */ - idays = tdays; - rem += offset - corr; - while (rem < 0) { - rem += SECSPERDAY; - --idays; - } - while (rem >= SECSPERDAY) { - rem -= SECSPERDAY; - ++idays; - } - while (idays < 0) { - if (increment_overflow(&y, -1)) - return NULL; - idays += year_lengths[isleap(y)]; - } - while (idays >= year_lengths[isleap(y)]) { - idays -= year_lengths[isleap(y)]; - if (increment_overflow(&y, 1)) - return NULL; - } - tmp->tm_year = y; - if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE)) - return NULL; - tmp->tm_yday = idays; - /* - ** The "extra" mods below avoid overflow problems. - */ - tmp->tm_wday = EPOCH_WDAY + - ((y - EPOCH_YEAR) % DAYSPERWEEK) * - (DAYSPERNYEAR % DAYSPERWEEK) + - leaps_thru_end_of(y - 1) - - leaps_thru_end_of(EPOCH_YEAR - 1) + - idays; - tmp->tm_wday %= DAYSPERWEEK; - if (tmp->tm_wday < 0) - tmp->tm_wday += DAYSPERWEEK; - tmp->tm_hour = (int) (rem / SECSPERHOUR); - rem %= SECSPERHOUR; - tmp->tm_min = (int) (rem / SECSPERMIN); - /* - ** A positive leap second requires a special - ** representation. This uses "... ??:59:60" et seq. - */ - tmp->tm_sec = (int) (rem % SECSPERMIN) + hit; - ip = mon_lengths[isleap(y)]; - for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon)) - idays -= ip[tmp->tm_mon]; - tmp->tm_mday = (int) (idays + 1); - tmp->tm_isdst = 0; -#ifdef TM_GMTOFF - tmp->TM_GMTOFF = offset; -#endif /* defined TM_GMTOFF */ - return tmp; -} - -// ============================================================================ -#if 0 -char * -ctime(timep) -const time_t * const timep; -{ -/* -** Section 4.12.3.2 of X3.159-1989 requires that -** The ctime function converts the calendar time pointed to by timer -** to local time in the form of a string. It is equivalent to -** asctime(localtime(timer)) -*/ - return asctime(localtime(timep)); -} -#endif - -// ============================================================================ -#if 0 -char * -ctime_r(timep, buf) -const time_t * const timep; -char * buf; -{ - struct tm mytm; - - return asctime_r(localtime_r(timep, &mytm), buf); -} -#endif - -/* -** Adapted from code provided by Robert Elz, who writes: -** The "best" way to do mktime I think is based on an idea of Bob -** Kridle's (so its said...) from a long time ago. -** It does a binary search of the time_t space. Since time_t's are -** just 32 bits, its a max of 32 iterations (even at 64 bits it -** would still be very reasonable). -*/ - -#ifndef WRONG -#define WRONG (-1) -#endif /* !defined WRONG */ - -/* -** Simplified normalize logic courtesy Paul Eggert. -*/ - -static int -increment_overflow(number, delta) -int * number; -int delta; -{ - unsigned number0 = (unsigned)*number; - unsigned number1 = (unsigned)(number0 + delta); - - *number = (int)number1; - - if (delta >= 0) { - return ((int)number1 < (int)number0); - } else { - return ((int)number1 > (int)number0); - } -} - -static int -long_increment_overflow(number, delta) -long * number; -int delta; -{ - unsigned long number0 = (unsigned long)*number; - unsigned long number1 = (unsigned long)(number0 + delta); - - *number = (long)number1; - - if (delta >= 0) { - return ((long)number1 < (long)number0); - } else { - return ((long)number1 > (long)number0); - } -} - -static int -normalize_overflow(tensptr, unitsptr, base) -int * const tensptr; -int * const unitsptr; -const int base; -{ - register int tensdelta; - - tensdelta = (*unitsptr >= 0) ? - (*unitsptr / base) : - (-1 - (-1 - *unitsptr) / base); - *unitsptr -= tensdelta * base; - return increment_overflow(tensptr, tensdelta); -} - -static int -long_normalize_overflow(tensptr, unitsptr, base) -long * const tensptr; -int * const unitsptr; -const int base; -{ - register int tensdelta; - - tensdelta = (*unitsptr >= 0) ? - (*unitsptr / base) : - (-1 - (-1 - *unitsptr) / base); - *unitsptr -= tensdelta * base; - return long_increment_overflow(tensptr, tensdelta); -} - -static int -tmcomp(atmp, btmp) -register const struct tm * const atmp; -register const struct tm * const btmp; -{ - register int result; - - if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && - (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && - (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && - (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && - (result = (atmp->tm_min - btmp->tm_min)) == 0) - result = atmp->tm_sec - btmp->tm_sec; - return result; -} - -static time_t -time2sub(tmp, funcp, offset, okayp, do_norm_secs, sp) -struct tm * const tmp; -struct tm * (* const funcp) P((const time_t*, long, struct tm*,const struct state *sp)); -const long offset; -int * const okayp; -const int do_norm_secs; -const struct state * sp; -{ - register int dir; - register int i, j; - register int saved_seconds; - register long li; - register time_t lo; - register time_t hi; - long y; - time_t newt; - time_t t; - struct tm yourtm, mytm; - - *okayp = FALSE; - yourtm = *tmp; - if (do_norm_secs) { - if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec, - SECSPERMIN)) - return WRONG; - } - if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR)) - return WRONG; - if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY)) - return WRONG; - y = yourtm.tm_year; - if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR)) - return WRONG; - /* - ** Turn y into an actual year number for now. - ** It is converted back to an offset from TM_YEAR_BASE later. - */ - if (long_increment_overflow(&y, TM_YEAR_BASE)) - return WRONG; - while (yourtm.tm_mday <= 0) { - if (long_increment_overflow(&y, -1)) - return WRONG; - li = y + (1 < yourtm.tm_mon); - yourtm.tm_mday += year_lengths[isleap(li)]; - } - while (yourtm.tm_mday > DAYSPERLYEAR) { - li = y + (1 < yourtm.tm_mon); - yourtm.tm_mday -= year_lengths[isleap(li)]; - if (long_increment_overflow(&y, 1)) - return WRONG; - } - for ( ; ; ) { - i = mon_lengths[isleap(y)][yourtm.tm_mon]; - if (yourtm.tm_mday <= i) - break; - yourtm.tm_mday -= i; - if (++yourtm.tm_mon >= MONSPERYEAR) { - yourtm.tm_mon = 0; - if (long_increment_overflow(&y, 1)) - return WRONG; - } - } - if (long_increment_overflow(&y, -TM_YEAR_BASE)) - return WRONG; - yourtm.tm_year = y; - if (yourtm.tm_year != y) - return WRONG; - if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN) - saved_seconds = 0; - else if (y + TM_YEAR_BASE < EPOCH_YEAR) { - /* - ** We can't set tm_sec to 0, because that might push the - ** time below the minimum representable time. - ** Set tm_sec to 59 instead. - ** This assumes that the minimum representable time is - ** not in the same minute that a leap second was deleted from, - ** which is a safer assumption than using 58 would be. - */ - if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN)) - return WRONG; - saved_seconds = yourtm.tm_sec; - yourtm.tm_sec = SECSPERMIN - 1; - } else { - saved_seconds = yourtm.tm_sec; - yourtm.tm_sec = 0; - } - /* - ** Do a binary search (this works whatever time_t's type is). - */ - if (!TYPE_SIGNED(time_t)) { - lo = 0; - hi = lo - 1; - } else if (!TYPE_INTEGRAL(time_t)) { - if (sizeof(time_t) > sizeof(float)) - hi = (time_t) DBL_MAX; - else hi = (time_t) FLT_MAX; - lo = -hi; - } else { - lo = 1; - for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i) - lo *= 2; - hi = -(lo + 1); - } - for ( ; ; ) { - t = lo / 2 + hi / 2; - if (t < lo) - t = lo; - else if (t > hi) - t = hi; - if ((*funcp)(&t, offset, &mytm, sp) == NULL) { - /* - ** Assume that t is too extreme to be represented in - ** a struct tm; arrange things so that it is less - ** extreme on the next pass. - */ - dir = (t > 0) ? 1 : -1; - } else dir = tmcomp(&mytm, &yourtm); - if (dir != 0) { - if (t == lo) { - if (t == TIME_T_MAX) - return WRONG; - ++t; - ++lo; - } else if (t == hi) { - if (t == TIME_T_MIN) - return WRONG; - --t; - --hi; - } - if (lo > hi) - return WRONG; - if (dir > 0) - hi = t; - else lo = t; - continue; - } - if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) - break; - /* - ** Right time, wrong type. - ** Hunt for right time, right type. - ** It's okay to guess wrong since the guess - ** gets checked. - */ - /* - ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's. - */ -#ifdef ALL_STATE - if (sp == NULL) - return WRONG; -#endif /* defined ALL_STATE */ - for (i = sp->typecnt - 1; i >= 0; --i) { - if (sp->ttis[i].tt_isdst != yourtm.tm_isdst) - continue; - for (j = sp->typecnt - 1; j >= 0; --j) { - if (sp->ttis[j].tt_isdst == yourtm.tm_isdst) - continue; - newt = t + sp->ttis[j].tt_gmtoff - - sp->ttis[i].tt_gmtoff; - if ((*funcp)(&newt, offset, &mytm, sp) == NULL) - continue; - if (tmcomp(&mytm, &yourtm) != 0) - continue; - if (mytm.tm_isdst != yourtm.tm_isdst) - continue; - /* - ** We have a match. - */ - t = newt; - goto label; - } - } - return WRONG; - } -label: - newt = t + saved_seconds; - if ((newt < t) != (saved_seconds < 0)) - return WRONG; - t = newt; - if ((*funcp)(&t, offset, tmp, sp)) - *okayp = TRUE; - return t; -} - -static time_t -time2(tmp, funcp, offset, okayp, sp) -struct tm * const tmp; -struct tm * (* const funcp) P((const time_t*, long, struct tm*, - const struct state* sp)); -const long offset; -int * const okayp; -const struct state * sp; -{ - time_t t; - - /* - ** First try without normalization of seconds - ** (in case tm_sec contains a value associated with a leap second). - ** If that fails, try with normalization of seconds. - */ - t = time2sub(tmp, funcp, offset, okayp, FALSE, sp); - return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp); -} - -static time_t -time1(tmp, funcp, offset, sp) -struct tm * const tmp; -struct tm * (* const funcp) P((const time_t *, long, struct tm *, const struct state* sp)); -const long offset; -const struct state * sp; -{ - register time_t t; - register int samei, otheri; - register int sameind, otherind; - register int i; - register int nseen; - int seen[TZ_MAX_TYPES]; - int types[TZ_MAX_TYPES]; - int okay; - - if (tmp->tm_isdst > 1) - tmp->tm_isdst = 1; - t = time2(tmp, funcp, offset, &okay, sp); -#define PCTS 1 -#ifdef PCTS - /* - ** PCTS code courtesy Grant Sullivan. - */ - if (okay) - return t; - if (tmp->tm_isdst < 0) - tmp->tm_isdst = 0; /* reset to std and try again */ -#endif /* defined PCTS */ -#ifndef PCTS - if (okay || tmp->tm_isdst < 0) - return t; -#endif /* !defined PCTS */ - /* - ** We're supposed to assume that somebody took a time of one type - ** and did some math on it that yielded a "struct tm" that's bad. - ** We try to divine the type they started from and adjust to the - ** type they need. - */ - /* - ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's. - */ -#ifdef ALL_STATE - if (sp == NULL) - return WRONG; -#endif /* defined ALL_STATE */ - for (i = 0; i < sp->typecnt; ++i) - seen[i] = FALSE; - nseen = 0; - for (i = sp->timecnt - 1; i >= 0; --i) - if (!seen[sp->types[i]]) { - seen[sp->types[i]] = TRUE; - types[nseen++] = sp->types[i]; - } - for (sameind = 0; sameind < nseen; ++sameind) { - samei = types[sameind]; - if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) - continue; - for (otherind = 0; otherind < nseen; ++otherind) { - otheri = types[otherind]; - if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst) - continue; - tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - - sp->ttis[samei].tt_gmtoff; - tmp->tm_isdst = !tmp->tm_isdst; - t = time2(tmp, funcp, offset, &okay, sp); - if (okay) - return t; - tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff - - sp->ttis[samei].tt_gmtoff; - tmp->tm_isdst = !tmp->tm_isdst; - } - } - return WRONG; -} - -// ============================================================================ -time_t -mktime_tz(struct tm * const tmp, char const * tz) -{ - struct state st; - if (tzload(tz, &st, TRUE) != 0) { - // not sure what's best here, but for now, we fall back to gmt - gmtload(&st); - } - return time1(tmp, localsub, 0L, &st); -} From f820e85164a1863e4384f5e1ca8b6f46902bd74e Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 19 Oct 2012 18:10:05 -0700 Subject: [PATCH 21/89] Add a directory for tzdata updates. Bug: 7012465 Change-Id: I7e2c9965a4bcad125ca4fb788b842bd114b5619c --- rootdir/init.rc | 1 + 1 file changed, 1 insertion(+) diff --git a/rootdir/init.rc b/rootdir/init.rc index 0cd906c85..0d9f779bb 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -183,6 +183,7 @@ on post-fs-data mkdir /data/misc/bluetooth 0770 system system mkdir /data/misc/keystore 0700 keystore keystore mkdir /data/misc/keychain 0771 system system + mkdir /data/misc/zoneinfo 0775 system system mkdir /data/misc/vpn 0770 system vpn mkdir /data/misc/systemkeys 0700 system system # give system access to wpa_supplicant.conf for backup and restore From e41bc3155588c2fdc23b512a959e20e896da5180 Mon Sep 17 00:00:00 2001 From: Yi-wei Zhao Date: Tue, 23 Oct 2012 21:09:56 +0800 Subject: [PATCH 22/89] Fix dirfd crash issue in property service In "init: harden property service" patch, dirfd() is invoked without checking whether opendir() return successfully. It may fail if load_persistent_properties() is invoked before userdata partition is mounted; then dirfd(NULL) will make init crash. This may happen if "is_charger" is true. Change-Id: I216fb743a3c9fa050f92fcb31b62e766346d84bb Signed-off-by: Yi-wei Zhao --- init/property_service.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/init/property_service.c b/init/property_service.c index 2c1b4a1fc..31bc55ad7 100644 --- a/init/property_service.c +++ b/init/property_service.c @@ -510,13 +510,14 @@ static void load_properties_from_file(const char *fn) static void load_persistent_properties() { DIR* dir = opendir(PERSISTENT_PROPERTY_DIR); - int dir_fd = dirfd(dir); + int dir_fd; struct dirent* entry; char value[PROP_VALUE_MAX]; int fd, length; struct stat sb; if (dir) { + dir_fd = dirfd(dir); while ((entry = readdir(dir)) != NULL) { if (strncmp("persist.", entry->d_name, strlen("persist."))) continue; From c463d2cf9c5717dcd37589deb01615b984266c8c Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 26 Oct 2012 16:47:09 -0700 Subject: [PATCH 23/89] Fix debuggerd's use of readdir_r(3). Change-Id: I1b178af054cefebfb774320e4b4699d6dc8bbb01 --- debuggerd/backtrace.c | 7 +++---- debuggerd/tombstone.c | 5 ++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/debuggerd/backtrace.c b/debuggerd/backtrace.c index 62f7f325c..ba76e7dc3 100644 --- a/debuggerd/backtrace.c +++ b/debuggerd/backtrace.c @@ -125,10 +125,9 @@ void dump_backtrace(int fd, pid_t pid, pid_t tid, bool* detach_failed, char task_path[64]; snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid); DIR* d = opendir(task_path); - if (d) { - struct dirent debuf; - struct dirent *de; - while (!readdir_r(d, &debuf, &de) && de) { + if (d != NULL) { + struct dirent* de = NULL; + while ((de = readdir(d)) != NULL) { if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) { continue; } diff --git a/debuggerd/tombstone.c b/debuggerd/tombstone.c index 52223da73..47a1bf5f5 100644 --- a/debuggerd/tombstone.c +++ b/debuggerd/tombstone.c @@ -405,9 +405,8 @@ static bool dump_sibling_thread_report(const ptrace_context_t* context, } bool detach_failed = false; - struct dirent debuf; - struct dirent *de; - while (!readdir_r(d, &debuf, &de) && de) { + struct dirent* de; + while ((de = readdir(d)) != NULL) { /* Ignore "." and ".." */ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) { continue; From 3fb611083061535f8e32da1b7ea2d6c4687d114e Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Fri, 2 Nov 2012 15:22:34 -0400 Subject: [PATCH 24/89] Document the SELinux extensions to the Android init language. Change-Id: I9b066e0789c93e5147c28a60baeed91c44dd9359 Signed-off-by: Stephen Smalley --- init/readme.txt | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/init/readme.txt b/init/readme.txt index fe0d15d09..9cc291c33 100644 --- a/init/readme.txt +++ b/init/readme.txt @@ -88,6 +88,13 @@ group [ ]* supplemental groups of the process (via setgroups()). Currently defaults to root. (??? probably should default to nobody) +seclabel + Change to securitycontext before exec'ing this service. + Primarily for use by services run from the rootfs, e.g. ueventd, adbd. + Services on the system partition can instead use policy-defined transitions + based on their file security context. + If not specified and no transition is defined in policy, defaults to the init context. + oneshot Do not restart the service when it exits. @@ -182,6 +189,21 @@ mount [ ]* device by name. s include "ro", "rw", "remount", "noatime", ... +restorecon + Restore the file named by to the security context specified + in the file_contexts configuration. + Not required for directories created by the init.rc as these are + automatically labeled correctly by init. + +setcon + Set the current process security context to the specified string. + This is typically only used from early-init to set the init context + before any other process is started. + +setenforce 0|1 + Set the SELinux system-wide enforcing status. + 0 is permissive (i.e. log but do not deny), 1 is enforcing. + setkey TBD @@ -191,6 +213,10 @@ setprop setrlimit Set the rlimit for a resource. +setsebool = + Set SELinux boolean to . + may be 1|true|on or 0|false|off + start Start a service running if it is not already running. From 6d358ae44ccfbcd5b89511d142f334b2cc1b67b1 Mon Sep 17 00:00:00 2001 From: Josef Kindberg Date: Wed, 23 Feb 2011 12:40:44 +0100 Subject: [PATCH 25/89] libsysutils: Increase command buffersize and command args Needed to support tethering of multiple remote Bluetooth devices. Change-Id: I9f736affd83226e8b2fa4f0faacd3654175dd8c9 Signed-off-by: Patrik Ryd --- include/sysutils/FrameworkListener.h | 3 ++- libsysutils/src/FrameworkListener.cpp | 10 +++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/sysutils/FrameworkListener.h b/include/sysutils/FrameworkListener.h index 756bacfd0..f1a4b43f8 100644 --- a/include/sysutils/FrameworkListener.h +++ b/include/sysutils/FrameworkListener.h @@ -23,10 +23,11 @@ class SocketClient; class FrameworkListener : public SocketListener { public: - static const int CMD_ARGS_MAX = 16; + static const int CMD_ARGS_MAX = 26; /* 1 out of errorRate will be dropped */ int errorRate; + private: int mCommandCount; bool mWithSeq; diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp index 6731cf1bd..02a401d41 100644 --- a/libsysutils/src/FrameworkListener.cpp +++ b/libsysutils/src/FrameworkListener.cpp @@ -25,6 +25,8 @@ #include #include +static const int CMD_BUF_SIZE = 1024; + FrameworkListener::FrameworkListener(const char *socketName, bool withSeq) : SocketListener(socketName, true, withSeq) { init(socketName, withSeq); @@ -43,7 +45,7 @@ void FrameworkListener::init(const char *socketName, bool withSeq) { } bool FrameworkListener::onDataAvailable(SocketClient *c) { - char buffer[255]; + char buffer[CMD_BUF_SIZE]; int len; len = TEMP_FAILURE_RETRY(read(c->getSocket(), buffer, sizeof(buffer))); @@ -52,6 +54,8 @@ bool FrameworkListener::onDataAvailable(SocketClient *c) { return false; } else if (!len) return false; + if(buffer[len-1] != '\0') + SLOGW("String is not zero-terminated"); int offset = 0; int i; @@ -63,6 +67,7 @@ bool FrameworkListener::onDataAvailable(SocketClient *c) { offset = i + 1; } } + return true; } @@ -74,7 +79,7 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { FrameworkCommandCollection::iterator i; int argc = 0; char *argv[FrameworkListener::CMD_ARGS_MAX]; - char tmp[255]; + char tmp[CMD_BUF_SIZE]; char *p = data; char *q = tmp; char *qlimit = tmp + sizeof(tmp) - 1; @@ -180,7 +185,6 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { goto out; } } - cli->sendMsg(500, "Command not recognized", false); out: int j; From 6ecbdca4c19bc6f8eb371dd2c7a85fac06e1854d Mon Sep 17 00:00:00 2001 From: Robert Greenwalt Date: Tue, 13 Nov 2012 10:56:01 -0800 Subject: [PATCH 26/89] Read domain name from dhcp system prop This property is set by the dhcpcd daemon. bug:6799630 Change-Id: I21002e286819cff420ec72e3857764e5f58ecfe4 --- libnetutils/dhcp_utils.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c index d0ca90acb..541d3fb52 100644 --- a/libnetutils/dhcp_utils.c +++ b/libnetutils/dhcp_utils.c @@ -92,7 +92,8 @@ static int fill_ip_info(const char *interface, char *dns2, char *server, uint32_t *lease, - char *vendorInfo) + char *vendorInfo, + char *domain) { char prop_name[PROPERTY_KEY_MAX]; char prop_value[PROPERTY_VALUE_MAX]; @@ -153,6 +154,10 @@ static int fill_ip_info(const char *interface, p2p_interface); property_get(prop_name, vendorInfo, NULL); + snprintf(prop_name, sizeof(prop_name), "%s.%s.domain", DHCP_PROP_NAME_PREFIX, + p2p_interface); + property_get(prop_name, domain, NULL); + return 0; } @@ -181,7 +186,8 @@ int dhcp_do_request(const char *interface, char *dns2, char *server, uint32_t *lease, - char *vendorInfo) + char *vendorInfo, + char *domain) { char result_prop_name[PROPERTY_KEY_MAX]; char daemon_prop_name[PROPERTY_KEY_MAX]; @@ -233,7 +239,7 @@ int dhcp_do_request(const char *interface, if (strcmp(prop_value, "ok") == 0) { char dns_prop_name[PROPERTY_KEY_MAX]; if (fill_ip_info(interface, ipaddr, gateway, prefixLength, - dns1, dns2, server, lease, vendorInfo) == -1) { + dns1, dns2, server, lease, vendorInfo, domain) == -1) { return -1; } @@ -331,7 +337,8 @@ int dhcp_do_request_renew(const char *interface, char *dns2, char *server, uint32_t *lease, - char *vendorInfo) + char *vendorInfo, + char *domain) { char result_prop_name[PROPERTY_KEY_MAX]; char prop_value[PROPERTY_VALUE_MAX] = {'\0'}; @@ -368,7 +375,7 @@ int dhcp_do_request_renew(const char *interface, } if (strcmp(prop_value, "ok") == 0) { fill_ip_info(interface, ipaddr, gateway, prefixLength, - dns1, dns2, server, lease, vendorInfo); + dns1, dns2, server, lease, vendorInfo, domain); return 0; } else { snprintf(errmsg, sizeof(errmsg), "DHCP Renew result was %s", prop_value); From 92781808bab8f045752aa1824a57956ddd52fcbd Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Mon, 12 Nov 2012 16:36:15 -0800 Subject: [PATCH 27/89] Switch keystore to binder Change-Id: I1607bc1f14af5115cefd6727be3815cdcce670a8 --- rootdir/init.rc | 1 - 1 file changed, 1 deletion(-) diff --git a/rootdir/init.rc b/rootdir/init.rc index af422239d..a76602c4d 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -495,7 +495,6 @@ service keystore /system/bin/keystore /data/misc/keystore class main user keystore group keystore drmrpc - socket keystore stream 666 service dumpstate /system/bin/dumpstate -s class main From 44a9abdd045b50f47c08430a38ddc4e94ce813c1 Mon Sep 17 00:00:00 2001 From: Wink Saville Date: Fri, 16 Nov 2012 12:46:08 -0800 Subject: [PATCH 28/89] Add RLOGx This will eventually allow us to remove the code in logd_write.c#__android_log_write which uses the tag to direct logs to the radio buffer. Change-Id: Ic992c0b8d1cf000b1814dc7786d2a40becf75eaf --- include/cutils/log.h | 83 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/include/cutils/log.h b/include/cutils/log.h index 878952e05..8b045c75d 100644 --- a/include/cutils/log.h +++ b/include/cutils/log.h @@ -279,7 +279,88 @@ extern "C" { : (void)0 ) #endif - +// --------------------------------------------------------------------- + +/* + * Simplified macro to send a verbose radio log message using the current LOG_TAG. + */ +#ifndef RLOGV +#if LOG_NDEBUG +#define RLOGV(...) ((void)0) +#else +#define RLOGV(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) +#endif +#endif + +#define CONDITION(cond) (__builtin_expect((cond)!=0, 0)) + +#ifndef RLOGV_IF +#if LOG_NDEBUG +#define RLOGV_IF(cond, ...) ((void)0) +#else +#define RLOGV_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif +#endif + +/* + * Simplified macro to send a debug radio log message using the current LOG_TAG. + */ +#ifndef RLOGD +#define RLOGD(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef RLOGD_IF +#define RLOGD_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +/* + * Simplified macro to send an info radio log message using the current LOG_TAG. + */ +#ifndef RLOGI +#define RLOGI(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef RLOGI_IF +#define RLOGI_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +/* + * Simplified macro to send a warning radio log message using the current LOG_TAG. + */ +#ifndef RLOGW +#define RLOGW(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef RLOGW_IF +#define RLOGW_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +/* + * Simplified macro to send an error radio log message using the current LOG_TAG. + */ +#ifndef RLOGE +#define RLOGE(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef RLOGE_IF +#define RLOGE_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + // --------------------------------------------------------------------- From a26b4caf4cf5241e5c2145f53ec7170200ab4bb9 Mon Sep 17 00:00:00 2001 From: Kyle Russell Date: Mon, 19 Nov 2012 16:29:58 -0500 Subject: [PATCH 29/89] autosuspend_inited flag set even if initialization fails Prevents possible SIGSEGV on second autosuspend_enable attempt when first intialization attempt fails. autosuspend_inited should only be set once autosuspend_ops has been assigned. Consider the first call to autosuspend_enable(). autosuspend_init() sets its inited flag to true, and attempts to set autosuspend_ops. If all the other autosuspend_*_init() attempts fail, autosuspend_init() returns -1, which autosuspend_enable() will return as a failure. A second call to autosuspend_enable() will check autosuspend_init() and see that autosuspend has already been initialized. It will attempt to access autosuspend_ops, which were not set in the first initialization attempt, causing a SIGSEGV. Change-Id: Ib2d3ee62fee4c3b6d0323e5b7f3709a23c6b923f --- libsuspend/autosuspend.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsuspend/autosuspend.c b/libsuspend/autosuspend.c index 7d1d97333..eb1f66e37 100644 --- a/libsuspend/autosuspend.c +++ b/libsuspend/autosuspend.c @@ -33,8 +33,6 @@ static int autosuspend_init(void) return 0; } - autosuspend_inited = true; - autosuspend_ops = autosuspend_earlysuspend_init(); if (autosuspend_ops) { goto out; @@ -56,6 +54,8 @@ static int autosuspend_init(void) } out: + autosuspend_inited = true; + ALOGV("autosuspend initialized\n"); return 0; } From 0d82fbf04d6db847cf598f370aa6986af794bd72 Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Wed, 14 Nov 2012 15:01:55 +0100 Subject: [PATCH 30/89] adb: Improve ADB's forward redirection management. This adds a few new options/modes to 'adb forward': adb forward --list adb forward --remove adb forward --remove-all adb forward --no-rebind For more context, see http://code.google.com/p/android/issues/detail?id=39631 Note that this only affects the host adb client and server programs, i.e. it's compatible with devices running older adbd versions. Change-Id: I9cda3ba12b5a8560a2061620bc7f948e5c1e70f7 --- adb/SERVICES.TXT | 27 +++++++ adb/adb.c | 177 ++++++++++++++++++++++++++++++++++++++-------- adb/commandline.c | 95 ++++++++++++++++++++++--- 3 files changed, 262 insertions(+), 37 deletions(-) diff --git a/adb/SERVICES.TXT b/adb/SERVICES.TXT index d9aa09c38..b53bc444c 100644 --- a/adb/SERVICES.TXT +++ b/adb/SERVICES.TXT @@ -117,7 +117,34 @@ host: or even any one of the local services described below. +:forward:norebind:; + Same as :forward:; except that it will + fail it there is already a forward connection from . + Used to implement 'adb forward --no-rebind ' + +:killforward: + Remove any existing forward local connection from . + This is used to implement 'adb forward --remove ' + +:killforward-all + Remove all forward network connections. + This is used to implement 'adb forward --remove-all'. + +:list-forward + List all existing forward connections from this server. + This returns something that looks like the following: + + : The length of the payload, as 4 hexadecimal chars. + : A series of lines of the following format: + + " " " " "\n" + + Where is a device serial number. + is the host-specific endpoint (e.g. tcp:9000). + is the device-specific endpoint. + + Used to implement 'adb forward --list'. LOCAL SERVICES: diff --git a/adb/adb.c b/adb/adb.c index 07bfbe5d5..b3283de9a 100644 --- a/adb/adb.c +++ b/adb/adb.c @@ -722,24 +722,90 @@ int local_name_to_fd(const char *name) return -1; } -static int remove_listener(const char *local_name, const char *connect_to, atransport* transport) +// Write a single line describing a listener to a user-provided buffer. +// Appends a trailing zero, even in case of truncation, but the function +// returns the full line length. +// If |buffer| is NULL, does not write but returns required size. +static int format_listener(alistener* l, char* buffer, size_t buffer_len) { + // Format is simply: + // + // " " " " "\n" + // + int local_len = strlen(l->local_name); + int connect_len = strlen(l->connect_to); + int serial_len = strlen(l->transport->serial); + + if (buffer != NULL) { + snprintf(buffer, buffer_len, "%s %s %s\n", + l->transport->serial, l->local_name, l->connect_to); + } + // NOTE: snprintf() on Windows returns -1 in case of truncation, so + // return the computed line length instead. + return local_len + connect_len + serial_len + 3; +} + +// Write the list of current listeners (network redirections) into a +// user-provided buffer. Appends a trailing zero, even in case of +// trunctaion, but return the full size in bytes. +// If |buffer| is NULL, does not write but returns required size. +static int format_listeners(char* buf, size_t buflen) +{ + alistener* l; + int result = 0; + for (l = listener_list.next; l != &listener_list; l = l->next) { + // Ignore special listeners like those for *smartsocket* + if (l->connect_to[0] == '*') + continue; + int len = format_listener(l, buf, buflen); + // Ensure there is space for the trailing zero. + result += len; + if (buf != NULL) { + buf += len; + buflen -= len; + if (buflen <= 0) + break; + } + } + return result; +} + +static int remove_listener(const char *local_name, atransport* transport) { alistener *l; for (l = listener_list.next; l != &listener_list; l = l->next) { - if (!strcmp(local_name, l->local_name) && - !strcmp(connect_to, l->connect_to) && - l->transport && l->transport == transport) { - - listener_disconnect(l, transport); + if (!strcmp(local_name, l->local_name)) { + listener_disconnect(l, l->transport); return 0; } } - return -1; } -static int install_listener(const char *local_name, const char *connect_to, atransport* transport) +static void remove_all_listeners(void) +{ + alistener *l, *l_next; + for (l = listener_list.next; l != &listener_list; l = l_next) { + l_next = l->next; + // Never remove smart sockets. + if (l->connect_to[0] == '*') + continue; + listener_disconnect(l, l->transport); + } +} + +// error/status codes for install_listener. +typedef enum { + INSTALL_STATUS_OK = 0, + INSTALL_STATUS_INTERNAL_ERROR = -1, + INSTALL_STATUS_CANNOT_BIND = -2, + INSTALL_STATUS_CANNOT_REBIND = -3, +} install_status_t; + +static install_status_t install_listener(const char *local_name, + const char *connect_to, + atransport* transport, + int no_rebind) { alistener *l; @@ -751,12 +817,17 @@ static int install_listener(const char *local_name, const char *connect_to, atra /* can't repurpose a smartsocket */ if(l->connect_to[0] == '*') { - return -1; + return INSTALL_STATUS_INTERNAL_ERROR; + } + + /* can't repurpose a listener if 'no_rebind' is true */ + if (no_rebind) { + return INSTALL_STATUS_CANNOT_REBIND; } cto = strdup(connect_to); if(cto == 0) { - return -1; + return INSTALL_STATUS_INTERNAL_ERROR; } //printf("rebinding '%s' to '%s'\n", local_name, connect_to); @@ -767,7 +838,7 @@ static int install_listener(const char *local_name, const char *connect_to, atra l->transport = transport; add_transport_disconnect(l->transport, &l->disconnect); } - return 0; + return INSTALL_STATUS_OK; } } @@ -804,11 +875,11 @@ static int install_listener(const char *local_name, const char *connect_to, atra l->disconnect.func = listener_disconnect; add_transport_disconnect(transport, &l->disconnect); } - return 0; + return INSTALL_STATUS_OK; nomem: fatal("cannot allocate listener"); - return 0; + return INSTALL_STATUS_INTERNAL_ERROR; } #ifdef HAVE_WIN32_PROC @@ -1113,7 +1184,7 @@ int adb_main(int is_daemon, int server_port) char local_name[30]; build_local_name(local_name, sizeof(local_name), server_port); - if(install_listener(local_name, "*smartsocket*", NULL)) { + if(install_listener(local_name, "*smartsocket*", NULL, 0)) { exit(1); } #else @@ -1180,7 +1251,7 @@ int adb_main(int is_daemon, int server_port) } else { char local_name[30]; build_local_name(local_name, sizeof(local_name), server_port); - if(install_listener(local_name, "*smartsocket*", NULL)) { + if(install_listener(local_name, "*smartsocket*", NULL, 0)) { exit(1); } } @@ -1474,24 +1545,63 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r } #endif // ADB_HOST - if(!strncmp(service,"forward:",8) || !strncmp(service,"killforward:",12)) { + if(!strcmp(service,"list-forward")) { + // Create the list of forward redirections. + char header[9]; + int buffer_size = format_listeners(NULL, 0); + // Add one byte for the trailing zero. + char* buffer = malloc(buffer_size+1); + (void) format_listeners(buffer, buffer_size+1); + snprintf(header, sizeof header, "OKAY%04x", buffer_size); + writex(reply_fd, header, 8); + writex(reply_fd, buffer, buffer_size); + free(buffer); + return 0; + } + + if (!strcmp(service,"killforward-all")) { + remove_all_listeners(); + adb_write(reply_fd, "OKAYOKAY", 8); + return 0; + } + + if(!strncmp(service,"forward:",8) || + !strncmp(service,"killforward:",12)) { char *local, *remote, *err; int r; atransport *transport; int createForward = strncmp(service,"kill",4); + int no_rebind = 0; - local = service + (createForward ? 8 : 12); - remote = strchr(local,';'); - if(remote == 0) { - sendfailmsg(reply_fd, "malformed forward spec"); - return 0; + local = strchr(service, ':') + 1; + + // Handle forward:norebind:... here + if (createForward && !strncmp(local, "norebind:", 9)) { + no_rebind = 1; + local = strchr(local, ':') + 1; } - *remote++ = 0; - if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')){ - sendfailmsg(reply_fd, "malformed forward spec"); - return 0; + remote = strchr(local,';'); + + if (createForward) { + // Check forward: parameter format: ';' + if(remote == 0) { + sendfailmsg(reply_fd, "malformed forward spec"); + return 0; + } + + *remote++ = 0; + if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')){ + sendfailmsg(reply_fd, "malformed forward spec"); + return 0; + } + } else { + // Check killforward: parameter format: '' + if (local[0] == 0) { + sendfailmsg(reply_fd, "malformed forward spec"); + return 0; + } } transport = acquire_one_transport(CS_ANY, ttype, serial, &err); @@ -1501,9 +1611,9 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r } if (createForward) { - r = install_listener(local, remote, transport); + r = install_listener(local, remote, transport, no_rebind); } else { - r = remove_listener(local, remote, transport); + r = remove_listener(local, transport); } if(r == 0) { /* 1st OKAY is connect, 2nd OKAY is status */ @@ -1512,7 +1622,18 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r } if (createForward) { - sendfailmsg(reply_fd, (r == -1) ? "cannot rebind smartsocket" : "cannot bind socket"); + const char* message; + switch (r) { + case INSTALL_STATUS_CANNOT_BIND: + message = "cannot bind to socket"; + break; + case INSTALL_STATUS_CANNOT_REBIND: + message = "cannot rebind existing socket"; + break; + default: + message = "internal error"; + } + sendfailmsg(reply_fd, message); } else { sendfailmsg(reply_fd, "cannot remove listener"); } diff --git a/adb/commandline.c b/adb/commandline.c index 24cbb5a6f..a4c2f40ee 100644 --- a/adb/commandline.c +++ b/adb/commandline.c @@ -112,6 +112,9 @@ void help() " adb shell - run remote shell command\n" " adb emu - run emulator console command\n" " adb logcat [ ] - View device log\n" + " adb forward --list - list all forward socket connections.\n" + " the format is a list of lines with the following format:\n" + " \" \" \" \" \"\\n\"\n" " adb forward - forward socket connections\n" " forward specs are one of: \n" " tcp:\n" @@ -120,6 +123,11 @@ void help() " localfilesystem:\n" " dev:\n" " jdwp: (remote only)\n" + " adb forward --no-rebind \n" + " - same as 'adb forward ' but fails\n" + " if is already forwarded\n" + " adb forward --remove - remove a specific forward socket connection\n" + " adb forward --remove-all - remove all forward socket connections\n" " adb jdwp - list PIDs of processes hosting a JDWP transport\n" " adb install [-l] [-r] [-s] [--algo --key --iv ] \n" " - push this package file to the device and install it\n" @@ -1223,16 +1231,85 @@ top: } if(!strcmp(argv[0], "forward")) { - if(argc != 3) return usage(); - if (serial) { - snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]); - } else if (ttype == kTransportUsb) { - snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]); - } else if (ttype == kTransportLocal) { - snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]); - } else { - snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]); + char host_prefix[64]; + char remove = 0; + char remove_all = 0; + char list = 0; + char no_rebind = 0; + + // Parse options here. + while (argc > 1 && argv[1][0] == '-') { + if (!strcmp(argv[1], "--list")) + list = 1; + else if (!strcmp(argv[1], "--remove")) + remove = 1; + else if (!strcmp(argv[1], "--remove-all")) + remove_all = 1; + else if (!strcmp(argv[1], "--no-rebind")) + no_rebind = 1; + else { + return usage(); + } + argc--; + argv++; } + + // Ensure we can only use one option at a time. + if (list + remove + remove_all + no_rebind > 1) { + return usage(); + } + + // Determine the for this command. + if (serial) { + snprintf(host_prefix, sizeof host_prefix, "host-serial:%s", + serial); + } else if (ttype == kTransportUsb) { + snprintf(host_prefix, sizeof host_prefix, "host-usb"); + } else if (ttype == kTransportLocal) { + snprintf(host_prefix, sizeof host_prefix, "host-local"); + } else { + snprintf(host_prefix, sizeof host_prefix, "host"); + } + + // Implement forward --list + if (list) { + if (argc != 1) + return usage(); + snprintf(buf, sizeof buf, "%s:list-forward", host_prefix); + char* forwards = adb_query(buf); + if (forwards == NULL) { + fprintf(stderr, "error: %s\n", adb_error()); + return 1; + } + printf("%s", forwards); + free(forwards); + return 0; + } + + // Implement forward --remove-all + else if (remove_all) { + if (argc != 1) + return usage(); + snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix); + } + + // Implement forward --remove + else if (remove) { + if (argc != 2) + return usage(); + snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]); + } + // Or implement one of: + // forward + // forward --no-rebind + else + { + if (argc != 3) + return usage(); + const char* command = no_rebind ? "forward:norebind:" : "forward"; + snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]); + } + if(adb_command(buf)) { fprintf(stderr,"error: %s\n", adb_error()); return 1; From 91b114669f571c4b00f823d958934d3b5d64e534 Mon Sep 17 00:00:00 2001 From: Wink Saville Date: Wed, 28 Nov 2012 12:20:19 -0800 Subject: [PATCH 31/89] Use Rlog instead of Log Changing __android_log_write so the tag warns users relying on the tag to direct log output to the radio buffer to instead use Rlog or RLOG. Change-Id: I04b7bb5e620c1ab22b9b495382a252b539947e28 --- liblog/logd_write.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/liblog/logd_write.c b/liblog/logd_write.c index b91de523b..d812abce9 100644 --- a/liblog/logd_write.c +++ b/liblog/logd_write.c @@ -134,6 +134,7 @@ int __android_log_write(int prio, const char *tag, const char *msg) { struct iovec vec[3]; log_id_t log_id = LOG_ID_MAIN; + char tmp_tag[32]; if (!tag) tag = ""; @@ -147,8 +148,12 @@ int __android_log_write(int prio, const char *tag, const char *msg) !strcmp(tag, "STK") || !strcmp(tag, "CDMA") || !strcmp(tag, "PHONE") || - !strcmp(tag, "SMS")) + !strcmp(tag, "SMS")) { log_id = LOG_ID_RADIO; + // Inform third party apps/ril/radio.. to use Rlog or RLOG + snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag); + tag = tmp_tag; + } vec[0].iov_base = (unsigned char *) &prio; vec[0].iov_len = 1; @@ -163,12 +168,14 @@ int __android_log_write(int prio, const char *tag, const char *msg) int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg) { struct iovec vec[3]; + char tmp_tag[32]; if (!tag) tag = ""; /* XXX: This needs to go! */ - if (!strcmp(tag, "HTC_RIL") || + if ((bufID != LOG_ID_RADIO) && + (!strcmp(tag, "HTC_RIL") || !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */ !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */ !strcmp(tag, "AT") || @@ -176,8 +183,12 @@ int __android_log_buf_write(int bufID, int prio, const char *tag, const char *ms !strcmp(tag, "STK") || !strcmp(tag, "CDMA") || !strcmp(tag, "PHONE") || - !strcmp(tag, "SMS")) + !strcmp(tag, "SMS"))) { bufID = LOG_ID_RADIO; + // Inform third party apps/ril/radio.. to use Rlog or RLOG + snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag); + tag = tmp_tag; + } vec[0].iov_base = (unsigned char *) &prio; vec[0].iov_len = 1; From 0a34643160890eb50f7d8e016b4ec93d9db2aa27 Mon Sep 17 00:00:00 2001 From: Alex Ray Date: Wed, 14 Nov 2012 17:25:28 -0800 Subject: [PATCH 32/89] cutils: Add tracing support Basic tracing functionality to cutils, which can be turned on at start, or dynamically controlled by the frameworks. The goal is for hardware modules to add tracing that will be controlled by their respective services. Change-Id: I84eeb7d6be0038f734e719074fa4a2fae4ffe9c0 --- include/cutils/trace.h | 192 +++++++++++++++++++++++++++++++++++++++++ libcutils/Android.mk | 1 + libcutils/trace.c | 75 ++++++++++++++++ 3 files changed, 268 insertions(+) create mode 100644 include/cutils/trace.h create mode 100644 libcutils/trace.c diff --git a/include/cutils/trace.h b/include/cutils/trace.h new file mode 100644 index 000000000..7fdb3210c --- /dev/null +++ b/include/cutils/trace.h @@ -0,0 +1,192 @@ +/* + * 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. + */ + +#ifndef _LIBS_CUTILS_TRACE_H +#define _LIBS_CUTILS_TRACE_H + +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +/** + * The ATRACE_TAG macro can be defined before including this header to trace + * using one of the tags defined below. It must be defined to one of the + * following ATRACE_TAG_* macros. The trace tag is used to filter tracing in + * userland to avoid some of the runtime cost of tracing when it is not desired. + * + * Defining ATRACE_TAG to be ATRACE_TAG_ALWAYS will result in the tracing always + * being enabled - this should ONLY be done for debug code, as userland tracing + * has a performance cost even when the trace is not being recorded. Defining + * ATRACE_TAG to be ATRACE_TAG_NEVER or leaving ATRACE_TAG undefined will result + * in the tracing always being disabled. + * + * ATRACE_TAG_HAL should be bitwise ORed with the relevant tags for tracing + * within a hardware module. For example a camera hardware module would set: + * #define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL) + * + * Keep these in sync with frameworks/base/core/java/android/os/Trace.java. + */ +#define ATRACE_TAG_NEVER 0 // This tag is never enabled. +#define ATRACE_TAG_ALWAYS (1<<0) // This tag is always enabled. +#define ATRACE_TAG_GRAPHICS (1<<1) +#define ATRACE_TAG_INPUT (1<<2) +#define ATRACE_TAG_VIEW (1<<3) +#define ATRACE_TAG_WEBVIEW (1<<4) +#define ATRACE_TAG_WINDOW_MANAGER (1<<5) +#define ATRACE_TAG_ACTIVITY_MANAGER (1<<6) +#define ATRACE_TAG_SYNC_MANAGER (1<<7) +#define ATRACE_TAG_AUDIO (1<<8) +#define ATRACE_TAG_VIDEO (1<<9) +#define ATRACE_TAG_CAMERA (1<<10) +#define ATRACE_TAG_HAL (1<<11) +#define ATRACE_TAG_LAST ATRACE_TAG_HAL + +// Reserved for initialization. +#define ATRACE_TAG_NOT_READY (1LL<<63) + +#define ATRACE_TAG_VALID_MASK ((ATRACE_TAG_LAST - 1) | ATRACE_TAG_LAST) + +#ifndef ATRACE_TAG +#define ATRACE_TAG ATRACE_TAG_NEVER +#elif ATRACE_TAG > ATRACE_TAG_VALID_MASK +#error ATRACE_TAG must be defined to be one of the tags defined in cutils/trace.h +#endif + +/** + * Maximum size of a message that can be logged to the trace buffer. + * Note this message includes a tag, the pid, and the string given as the name. + * Names should be kept short to get the most use of the trace buffer. + */ +#define ATRACE_MESSAGE_LENGTH 1024 + +/** + * Opens the trace file for writing and reads the property for initial tags. + * The atrace.tags.enableflags property sets the tags to trace. + * This function should not be explicitly called, the first call to any normal + * trace function will cause it to be run safely. + */ +void atrace_setup(); + +/** + * Flag indicating whether setup has been completed, initialized to 0. + * Nonzero indicates setup has completed. + * Note: This does NOT indicate whether or not setup was successful. + */ +extern int32_t atrace_is_ready; + +/** + * Set of ATRACE_TAG flags to trace for, initialized to ATRACE_TAG_NOT_READY. + * A value of zero indicates setup has failed. + * Any other nonzero value indicates setup has succeeded, and tracing is on. + */ +extern uint64_t atrace_enabled_tags; + +/** + * Handle to the kernel's trace buffer, initialized to -1. + * Any other value indicates setup has succeeded, and is a valid fd for tracing. + */ +extern int atrace_marker_fd; + +/** + * atrace_init readies the process for tracing by opening the trace_marker file. + * Calling any trace function causes this to be run, so calling it is optional. + * This can be explicitly run to avoid setup delay on first trace function. + */ +#define ATRACE_INIT() atrace_init() +static inline void atrace_init() +{ + if (CC_UNLIKELY(!android_atomic_acquire_load(&atrace_is_ready))) { + atrace_setup(); + } +} + +/** + * Get the mask of all tags currently enabled. + * It can be used as a guard condition around more expensive trace calculations. + * Every trace function calls this, which ensures atrace_init is run. + */ +#define ATRACE_GET_ENABLED_TAGS() atrace_get_enabled_tags() +static inline uint64_t atrace_get_enabled_tags() +{ + atrace_init(); + return atrace_enabled_tags; +} + +/** + * Test if a given tag is currently enabled. + * Returns nonzero if the tag is enabled, otherwise zero. + * It can be used as a guard condition around more expensive trace calculations. + */ +#define ATRACE_ENABLED() atrace_is_tag_enabled(ATRACE_TAG) +static inline uint64_t atrace_is_tag_enabled(uint64_t tag) +{ + return atrace_get_enabled_tags() & tag; +} + +/** + * Trace the beginning of a context. name is used to identify the context. + * This is often used to time function execution. + */ +#define ATRACE_BEGIN(name) atrace_begin(ATRACE_TAG, name) +static inline void atrace_begin(uint64_t tag, const char* name) +{ + if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) { + char buf[ATRACE_MESSAGE_LENGTH]; + size_t len; + + len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "B|%d|%s", getpid(), name); + write(atrace_marker_fd, buf, len); + } +} + +/** + * Trace the end of a context. + * This should match up (and occur after) a corresponding ATRACE_BEGIN. + */ +#define ATRACE_END() atrace_end(ATRACE_TAG) +static inline void atrace_end(uint64_t tag) +{ + if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) { + char c = 'E'; + write(atrace_marker_fd, &c, 1); + } +} + +/** + * Traces an integer counter value. name is used to identify the counter. + * This can be used to track how a value changes over time. + */ +#define ATRACE_INT(name, value) atrace_int(ATRACE_TAG, name, value) +static inline void atrace_int(uint64_t tag, const char* name, int32_t value) +{ + if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) { + char buf[ATRACE_MESSAGE_LENGTH]; + size_t len; + + len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "C|%d|%s|%d", + getpid(), name, value); + write(atrace_marker_fd, buf, len); + } +} + +__END_DECLS + +#endif // _LIBS_CUTILS_TRACE_H diff --git a/libcutils/Android.mk b/libcutils/Android.mk index fc6d08de3..23a73d2a1 100644 --- a/libcutils/Android.mk +++ b/libcutils/Android.mk @@ -121,6 +121,7 @@ LOCAL_SRC_FILES := $(commonSources) \ mq.c \ partition_utils.c \ qtaguid.c \ + trace.c \ uevent.c ifeq ($(TARGET_ARCH),arm) diff --git a/libcutils/trace.c b/libcutils/trace.c new file mode 100644 index 000000000..15c8a98a2 --- /dev/null +++ b/libcutils/trace.c @@ -0,0 +1,75 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "cutils-trace" +#include + +int32_t atrace_is_ready = 0; +int atrace_marker_fd = -1; +uint64_t atrace_enabled_tags = ATRACE_TAG_NOT_READY; +static pthread_once_t atrace_once_control = PTHREAD_ONCE_INIT; + +// Read the sysprop and return the value tags should be set to +static uint64_t atrace_get_property() +{ + char value[PROPERTY_VALUE_MAX]; + char *endptr; + uint64_t tags; + + property_get("debug.atrace.tags.enableflags", value, "0"); + errno = 0; + tags = strtoull(value, &endptr, 0); + if (value[0] == '\0' || *endptr != '\0') { + ALOGE("Error parsing trace property: Not a number: %s", value); + return 0; + } else if (errno == ERANGE || tags == ULLONG_MAX) { + ALOGE("Error parsing trace property: Number too large: %s", value); + return 0; + } + return (tags | ATRACE_TAG_ALWAYS) & ATRACE_TAG_VALID_MASK; +} + +static void atrace_init_once() +{ + atrace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_WRONLY); + 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: + android_atomic_release_store(1, &atrace_is_ready); +} + +void atrace_setup() +{ + pthread_once(&atrace_once_control, atrace_init_once); +} From e7bb7bca4f4036c213763673627e1eb6c2c2fdd6 Mon Sep 17 00:00:00 2001 From: Alex Ray Date: Tue, 20 Nov 2012 01:39:09 -0800 Subject: [PATCH 33/89] cutils: trace: add atrace_update_tags() Adds a function to read the current trace system property value, and sets the trace tags to it, do be used as a sysprop change callback. Change-Id: Ia6336652173aa5b07188898736c2c795a69fe79a --- include/cutils/trace.h | 6 ++++++ libcutils/trace.c | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/include/cutils/trace.h b/include/cutils/trace.h index 7fdb3210c..386966250 100644 --- a/include/cutils/trace.h +++ b/include/cutils/trace.h @@ -85,6 +85,12 @@ __BEGIN_DECLS */ void atrace_setup(); +/** + * If tracing is ready, set atrace_enabled_tags to the system property + * debug.atrace.tags.enableflags. Can be used as a sysprop change callback. + */ +void atrace_update_tags(); + /** * Flag indicating whether setup has been completed, initialized to 0. * Nonzero indicates setup has completed. diff --git a/libcutils/trace.c b/libcutils/trace.c index 15c8a98a2..152ea6157 100644 --- a/libcutils/trace.c +++ b/libcutils/trace.c @@ -33,6 +33,7 @@ int32_t atrace_is_ready = 0; int atrace_marker_fd = -1; uint64_t atrace_enabled_tags = ATRACE_TAG_NOT_READY; static pthread_once_t atrace_once_control = PTHREAD_ONCE_INIT; +static pthread_mutex_t atrace_tags_mutex = PTHREAD_MUTEX_INITIALIZER; // Read the sysprop and return the value tags should be set to static uint64_t atrace_get_property() @@ -54,6 +55,18 @@ static uint64_t atrace_get_property() return (tags | ATRACE_TAG_ALWAYS) & ATRACE_TAG_VALID_MASK; } +// Update tags if tracing is ready. Useful as a sysprop change callback. +void atrace_update_tags() +{ + uint64_t tags; + if (CC_UNLIKELY(android_atomic_acquire_load(&atrace_is_ready))) { + tags = atrace_get_property(); + pthread_mutex_lock(&atrace_tags_mutex); + atrace_enabled_tags = tags; + pthread_mutex_unlock(&atrace_tags_mutex); + } +} + static void atrace_init_once() { atrace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_WRONLY); From 448f76a1c4eb78661b5ac68013e8a2348c92df63 Mon Sep 17 00:00:00 2001 From: Alex Ray Date: Fri, 30 Nov 2012 19:37:53 -0800 Subject: [PATCH 34/89] cutils: trace: use ANDROID_SMP to switch atomics With inline atomics, trace functions have no non-inline function calls in the fast (tracing off) path. To enable this, ANDROID_SMP must be defined for the project. Otherwise, normal (non-inline) atomics are used. Change-Id: Id1f75bdf7db2f5d319a389ad411f55073d78c48c --- include/cutils/trace.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/cutils/trace.h b/include/cutils/trace.h index 386966250..1db39038b 100644 --- a/include/cutils/trace.h +++ b/include/cutils/trace.h @@ -21,9 +21,14 @@ #include #include #include -#include #include +#ifdef ANDROID_SMP +#include +#else +#include +#endif + __BEGIN_DECLS /** From 9bfecb0e3444306ec57d7fafe4a99a47d3848c17 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Thu, 6 Dec 2012 09:34:34 -0800 Subject: [PATCH 35/89] Add old fastboot_protocol.txt fastboot_protocol.txt used to live in bootable/bootloader/legacy which was old, obsolete code. However, fastboot_protocol.txt is a useful file and belongs with the fastboot code. Change-Id: Iea50c3219f9ff9dd0c394fc6028c456fa948ffd9 Signed-off-by: Scott Anderson --- fastboot/fastboot_protocol.txt | 173 +++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 fastboot/fastboot_protocol.txt diff --git a/fastboot/fastboot_protocol.txt b/fastboot/fastboot_protocol.txt new file mode 100644 index 000000000..2248992d2 --- /dev/null +++ b/fastboot/fastboot_protocol.txt @@ -0,0 +1,173 @@ + +FastBoot Version 0.4 +---------------------- + +The fastboot protocol is a mechanism for communicating with bootloaders +over USB. It is designed to be very straightforward to implement, to +allow it to be used across a wide range of devices and from hosts running +Linux, Windows, or OSX. + + +Basic Requirements +------------------ + +* Two bulk endpoints (in, out) are required +* Max packet size must be 64 bytes for full-speed and 512 bytes for + high-speed USB +* The protocol is entirely host-driven and synchronous (unlike the + multi-channel, bi-directional, asynchronous ADB protocol) + + +Transport and Framing +--------------------- + +1. Host sends a command, which is an ascii string in a single + packet no greater than 64 bytes. + +2. Client response with a single packet no greater than 64 bytes. + The first four bytes of the response are "OKAY", "FAIL", "DATA", + or "INFO". Additional bytes may contain an (ascii) informative + message. + + a. INFO -> the remaining 60 bytes are an informative message + (providing progress or diagnostic messages). They should + be displayed and then step #2 repeats + + b. FAIL -> the requested command failed. The remaining 60 bytes + of the response (if present) provide a textual failure message + to present to the user. Stop. + + c. OKAY -> the requested command completed successfully. Go to #5 + + d. DATA -> the requested command is ready for the data phase. + A DATA response packet will be 12 bytes long, in the form of + DATA00000000 where the 8 digit hexidecimal number represents + the total data size to transfer. + +3. Data phase. Depending on the command, the host or client will + send the indicated amount of data. Short packets are always + acceptable and zero-length packets are ignored. This phase continues + until the client has sent or received the number of bytes indicated + in the "DATA" response above. + +4. Client responds with a single packet no greater than 64 bytes. + The first four bytes of the response are "OKAY", "FAIL", or "INFO". + Similar to #2: + + a. INFO -> display the remaining 60 bytes and return to #4 + + b. FAIL -> display the remaining 60 bytes (if present) as a failure + reason and consider the command failed. Stop. + + c. OKAY -> success. Go to #5 + +5. Success. Stop. + + +Example Session +--------------- + +Host: "getvar:version" request version variable + +Client: "OKAY0.4" return version "0.4" + +Host: "getvar:nonexistant" request some undefined variable + +Client: "OKAY" return value "" + +Host: "download:00001234" request to send 0x1234 bytes of data + +Client: "DATA00001234" ready to accept data + +Host: < 0x1234 bytes > send data + +Client: "OKAY" success + +Host: "flash:bootloader" request to flash the data to the bootloader + +Client: "INFOerasing flash" indicate status / progress + "INFOwriting flash" + "OKAY" indicate success + +Host: "powerdown" send a command + +Client: "FAILunknown command" indicate failure + + +Command Reference +----------------- + +* Command parameters are indicated by printf-style escape sequences. + +* Commands are ascii strings and sent without the quotes (which are + for illustration only here) and without a trailing 0 byte. + +* Commands that begin with a lowercase letter are reserved for this + specification. OEM-specific commands should not begin with a + lowercase letter, to prevent incompatibilities with future specs. + + "getvar:%s" Read a config/version variable from the bootloader. + The variable contents will be returned after the + OKAY response. + + "download:%08x" Write data to memory which will be later used + by "boot", "ramdisk", "flash", etc. The client + will reply with "DATA%08x" if it has enough + space in RAM or "FAIL" if not. The size of + the download is remembered. + + "verify:%08x" Send a digital signature to verify the downloaded + data. Required if the bootloader is "secure" + otherwise "flash" and "boot" will be ignored. + + "flash:%s" Write the previously downloaded image to the + named partition (if possible). + + "erase:%s" Erase the indicated partition (clear to 0xFFs) + + "boot" The previously downloaded data is a boot.img + and should be booted according to the normal + procedure for a boot.img + + "continue" Continue booting as normal (if possible) + + "reboot" Reboot the device. + + "reboot-bootloader" Reboot back into the bootloader. + Useful for upgrade processes that require upgrading + the bootloader and then upgrading other partitions + using the new bootloader. + + "powerdown" Power off the device. + + + +Client Variables +---------------- + +The "getvar:%s" command is used to read client variables which +represent various information about the device and the software +on it. + +The various currently defined names are: + + version Version of FastBoot protocol supported. + It should be "0.3" for this document. + + version-bootloader Version string for the Bootloader. + + version-baseband Version string of the Baseband Software + + product Name of the product + + serialno Product serial number + + secure If the value is "yes", this is a secure + bootloader requiring a signature before + it will install or boot images. + +Names starting with a lowercase character are reserved by this +specification. OEM-specific names should not start with lowercase +characters. + + From 9d7ad45eff156d99759123b584a878c32ba08bb9 Mon Sep 17 00:00:00 2001 From: Wink Saville Date: Fri, 16 Nov 2012 12:46:08 -0800 Subject: [PATCH 36/89] Add RLOGx This will eventually allow us to remove the code in logd_write.c#__android_log_write which uses the tag to direct logs to the radio buffer. Change-Id: Ic992c0b8d1cf000b1814dc7786d2a40becf75eaf --- include/cutils/log.h | 83 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/include/cutils/log.h b/include/cutils/log.h index 878952e05..8b045c75d 100644 --- a/include/cutils/log.h +++ b/include/cutils/log.h @@ -279,7 +279,88 @@ extern "C" { : (void)0 ) #endif - +// --------------------------------------------------------------------- + +/* + * Simplified macro to send a verbose radio log message using the current LOG_TAG. + */ +#ifndef RLOGV +#if LOG_NDEBUG +#define RLOGV(...) ((void)0) +#else +#define RLOGV(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) +#endif +#endif + +#define CONDITION(cond) (__builtin_expect((cond)!=0, 0)) + +#ifndef RLOGV_IF +#if LOG_NDEBUG +#define RLOGV_IF(cond, ...) ((void)0) +#else +#define RLOGV_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif +#endif + +/* + * Simplified macro to send a debug radio log message using the current LOG_TAG. + */ +#ifndef RLOGD +#define RLOGD(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef RLOGD_IF +#define RLOGD_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +/* + * Simplified macro to send an info radio log message using the current LOG_TAG. + */ +#ifndef RLOGI +#define RLOGI(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef RLOGI_IF +#define RLOGI_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +/* + * Simplified macro to send a warning radio log message using the current LOG_TAG. + */ +#ifndef RLOGW +#define RLOGW(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef RLOGW_IF +#define RLOGW_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +/* + * Simplified macro to send an error radio log message using the current LOG_TAG. + */ +#ifndef RLOGE +#define RLOGE(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef RLOGE_IF +#define RLOGE_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + // --------------------------------------------------------------------- From 3761e963b30cfc0c2dbcbe69906d689c976b9f2e Mon Sep 17 00:00:00 2001 From: Wink Saville Date: Wed, 28 Nov 2012 12:20:19 -0800 Subject: [PATCH 37/89] Use Rlog instead of Log Changing __android_log_write so the tag warns users relying on the tag to direct log output to the radio buffer to instead use Rlog or RLOG. Change-Id: I04b7bb5e620c1ab22b9b495382a252b539947e28 --- liblog/logd_write.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/liblog/logd_write.c b/liblog/logd_write.c index b91de523b..d812abce9 100644 --- a/liblog/logd_write.c +++ b/liblog/logd_write.c @@ -134,6 +134,7 @@ int __android_log_write(int prio, const char *tag, const char *msg) { struct iovec vec[3]; log_id_t log_id = LOG_ID_MAIN; + char tmp_tag[32]; if (!tag) tag = ""; @@ -147,8 +148,12 @@ int __android_log_write(int prio, const char *tag, const char *msg) !strcmp(tag, "STK") || !strcmp(tag, "CDMA") || !strcmp(tag, "PHONE") || - !strcmp(tag, "SMS")) + !strcmp(tag, "SMS")) { log_id = LOG_ID_RADIO; + // Inform third party apps/ril/radio.. to use Rlog or RLOG + snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag); + tag = tmp_tag; + } vec[0].iov_base = (unsigned char *) &prio; vec[0].iov_len = 1; @@ -163,12 +168,14 @@ int __android_log_write(int prio, const char *tag, const char *msg) int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg) { struct iovec vec[3]; + char tmp_tag[32]; if (!tag) tag = ""; /* XXX: This needs to go! */ - if (!strcmp(tag, "HTC_RIL") || + if ((bufID != LOG_ID_RADIO) && + (!strcmp(tag, "HTC_RIL") || !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */ !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */ !strcmp(tag, "AT") || @@ -176,8 +183,12 @@ int __android_log_buf_write(int bufID, int prio, const char *tag, const char *ms !strcmp(tag, "STK") || !strcmp(tag, "CDMA") || !strcmp(tag, "PHONE") || - !strcmp(tag, "SMS")) + !strcmp(tag, "SMS"))) { bufID = LOG_ID_RADIO; + // Inform third party apps/ril/radio.. to use Rlog or RLOG + snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag); + tag = tmp_tag; + } vec[0].iov_base = (unsigned char *) &prio; vec[0].iov_len = 1; From 35c625194bd1d2efb1a8230fd63c7febfbd98f31 Mon Sep 17 00:00:00 2001 From: Irfan Sheriff Date: Thu, 6 Dec 2012 12:08:05 -0800 Subject: [PATCH 38/89] Remove dead code Remove unnecessary DHCP properties Change-Id: I27b5d0a2d8fd67c911d04bb2d18dc1b3f10e7c2a --- libnetutils/dhcp_utils.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c index 541d3fb52..a22096781 100644 --- a/libnetutils/dhcp_utils.c +++ b/libnetutils/dhcp_utils.c @@ -242,13 +242,6 @@ int dhcp_do_request(const char *interface, dns1, dns2, server, lease, vendorInfo, domain) == -1) { return -1; } - - /* copy dns data to system properties - TODO - remove this after we have async - * notification of renewal's */ - snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns1", interface); - property_set(dns_prop_name, *dns1 ? ipaddr_to_string(*dns1) : ""); - snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", interface); - property_set(dns_prop_name, *dns2 ? ipaddr_to_string(*dns2) : ""); return 0; } else { snprintf(errmsg, sizeof(errmsg), "DHCP result was %s", prop_value); From 94cecfc4a00237cfd08e4327a836c67104ff2e20 Mon Sep 17 00:00:00 2001 From: Irfan Sheriff Date: Fri, 7 Dec 2012 10:36:29 -0800 Subject: [PATCH 39/89] Handle empty gateways Change-Id: Icbc1859125bae0bc222685bfbc18af38273d6827 --- libnetutils/dhcp_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c index a22096781..a59de0d5a 100644 --- a/libnetutils/dhcp_utils.c +++ b/libnetutils/dhcp_utils.c @@ -112,7 +112,7 @@ static int fill_ip_info(const char *interface, property_get(prop_name, server, NULL); //TODO: Handle IPv6 when we change system property usage - if (strcmp(gateway, "0.0.0.0") == 0) { + if (gateway[0] == '\0' || strncmp(gateway, "0.0.0.0", 7) == 0) { //DHCP server is our best bet as gateway strncpy(gateway, server, PROPERTY_VALUE_MAX); } From 5206d5971208fab8208669dabc98bbb9f7e4a45a Mon Sep 17 00:00:00 2001 From: Ben Cheng Date: Fri, 7 Dec 2012 10:54:09 -0800 Subject: [PATCH 40/89] Fail-proof the inline directives for SMP atomic operations. The various atomic operations are declared as inline in the header files to cut the function call overhead. However, the plain inline keyword is just a suggestion to the compiler which makes its own decision on whether to inline them or not. Worst, if they are not inlined, the -fvisibility-inlines-hidden compiler flag will render them as hidden symbols in the object file. If they are picked up by the linker over the ones supplied in libcutils.so the following warning will be reported: warning: hidden symbol 'android_atomic_inc' in foo.o is referenced by DSO bar.so One way is to add __attribute__((visibility("default"))) to those inline functions to suppress the linker warnings. A better way is to force inlining as with this patch. Change-Id: Ie4fcfdfaaf06f42d351619a0d89671a9df15ca2f --- include/cutils/atomic-arm.h | 82 +++++++++++++++++++++--------------- include/cutils/atomic-mips.h | 66 +++++++++++++++++------------ include/cutils/atomic-x86.h | 63 +++++++++++++++------------ libcutils/atomic.c | 2 +- 4 files changed, 124 insertions(+), 89 deletions(-) diff --git a/include/cutils/atomic-arm.h b/include/cutils/atomic-arm.h index 16fe51242..795afd39a 100644 --- a/include/cutils/atomic-arm.h +++ b/include/cutils/atomic-arm.h @@ -20,72 +20,78 @@ #include #include -extern inline void android_compiler_barrier(void) +#ifndef ANDROID_ATOMIC_INLINE +#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline)) +#endif + +extern ANDROID_ATOMIC_INLINE void android_compiler_barrier(void) { __asm__ __volatile__ ("" : : : "memory"); } #if ANDROID_SMP == 0 -extern inline void android_memory_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void) { android_compiler_barrier(); } -extern inline void android_memory_store_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void) { android_compiler_barrier(); } #elif defined(__ARM_HAVE_DMB) -extern inline void android_memory_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void) { __asm__ __volatile__ ("dmb" : : : "memory"); } -extern inline void android_memory_store_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void) { __asm__ __volatile__ ("dmb st" : : : "memory"); } #elif defined(__ARM_HAVE_LDREX_STREX) -extern inline void android_memory_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void) { __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r" (0) : "memory"); } -extern inline void android_memory_store_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void) { android_memory_barrier(); } #else -extern inline void android_memory_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void) { typedef void (kuser_memory_barrier)(void); (*(kuser_memory_barrier *)0xffff0fa0)(); } -extern inline void android_memory_store_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void) { android_memory_barrier(); } #endif -extern inline int32_t android_atomic_acquire_load(volatile const int32_t *ptr) +extern ANDROID_ATOMIC_INLINE +int32_t android_atomic_acquire_load(volatile const int32_t *ptr) { int32_t value = *ptr; android_memory_barrier(); return value; } -extern inline int32_t android_atomic_release_load(volatile const int32_t *ptr) +extern ANDROID_ATOMIC_INLINE +int32_t android_atomic_release_load(volatile const int32_t *ptr) { android_memory_barrier(); return *ptr; } -extern inline void android_atomic_acquire_store(int32_t value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE void +android_atomic_acquire_store(int32_t value, volatile int32_t *ptr) { *ptr = value; android_memory_barrier(); } -extern inline void android_atomic_release_store(int32_t value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE void +android_atomic_release_store(int32_t value, volatile int32_t *ptr) { android_memory_barrier(); *ptr = value; @@ -95,8 +101,8 @@ extern inline void android_atomic_release_store(int32_t value, extern int android_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr); #elif defined(__ARM_HAVE_LDREX_STREX) -extern inline int android_atomic_cas(int32_t old_value, int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr) { int32_t prev, status; do { @@ -111,8 +117,8 @@ extern inline int android_atomic_cas(int32_t old_value, int32_t new_value, return prev != old_value; } #else -extern inline int android_atomic_cas(int32_t old_value, int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr) { typedef int (kuser_cmpxchg)(int32_t, int32_t, volatile int32_t *); int32_t prev, status; @@ -127,18 +133,20 @@ extern inline int android_atomic_cas(int32_t old_value, int32_t new_value, } #endif -extern inline int android_atomic_acquire_cas(int32_t old_value, - int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_acquire_cas(int32_t old_value, + int32_t new_value, + volatile int32_t *ptr) { int status = android_atomic_cas(old_value, new_value, ptr); android_memory_barrier(); return status; } -extern inline int android_atomic_release_cas(int32_t old_value, - int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_release_cas(int32_t old_value, + int32_t new_value, + volatile int32_t *ptr) { android_memory_barrier(); return android_atomic_cas(old_value, new_value, ptr); @@ -149,8 +157,8 @@ extern inline int android_atomic_release_cas(int32_t old_value, extern int32_t android_atomic_add(int32_t increment, volatile int32_t *ptr); #elif defined(__ARM_HAVE_LDREX_STREX) -extern inline int32_t android_atomic_add(int32_t increment, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_add(int32_t increment, volatile int32_t *ptr) { int32_t prev, tmp, status; android_memory_barrier(); @@ -166,8 +174,8 @@ extern inline int32_t android_atomic_add(int32_t increment, return prev; } #else -extern inline int32_t android_atomic_add(int32_t increment, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_add(int32_t increment, volatile int32_t *ptr) { int32_t prev, status; android_memory_barrier(); @@ -179,12 +187,12 @@ extern inline int32_t android_atomic_add(int32_t increment, } #endif -extern inline int32_t android_atomic_inc(volatile int32_t *addr) +extern ANDROID_ATOMIC_INLINE int32_t android_atomic_inc(volatile int32_t *addr) { return android_atomic_add(1, addr); } -extern inline int32_t android_atomic_dec(volatile int32_t *addr) +extern ANDROID_ATOMIC_INLINE int32_t android_atomic_dec(volatile int32_t *addr) { return android_atomic_add(-1, addr); } @@ -192,7 +200,8 @@ extern inline int32_t android_atomic_dec(volatile int32_t *addr) #if defined(__thumb__) extern int32_t android_atomic_and(int32_t value, volatile int32_t *ptr); #elif defined(__ARM_HAVE_LDREX_STREX) -extern inline int32_t android_atomic_and(int32_t value, volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_and(int32_t value, volatile int32_t *ptr) { int32_t prev, tmp, status; android_memory_barrier(); @@ -208,7 +217,8 @@ extern inline int32_t android_atomic_and(int32_t value, volatile int32_t *ptr) return prev; } #else -extern inline int32_t android_atomic_and(int32_t value, volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_and(int32_t value, volatile int32_t *ptr) { int32_t prev, status; android_memory_barrier(); @@ -223,7 +233,8 @@ extern inline int32_t android_atomic_and(int32_t value, volatile int32_t *ptr) #if defined(__thumb__) extern int32_t android_atomic_or(int32_t value, volatile int32_t *ptr); #elif defined(__ARM_HAVE_LDREX_STREX) -extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_or(int32_t value, volatile int32_t *ptr) { int32_t prev, tmp, status; android_memory_barrier(); @@ -239,7 +250,8 @@ extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr) return prev; } #else -extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_or(int32_t value, volatile int32_t *ptr) { int32_t prev, status; android_memory_barrier(); diff --git a/include/cutils/atomic-mips.h b/include/cutils/atomic-mips.h index 49144a374..f9d3e253e 100644 --- a/include/cutils/atomic-mips.h +++ b/include/cutils/atomic-mips.h @@ -19,60 +19,66 @@ #include -extern inline void android_compiler_barrier(void) +#ifndef ANDROID_ATOMIC_INLINE +#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline)) +#endif + +extern ANDROID_ATOMIC_INLINE void android_compiler_barrier(void) { __asm__ __volatile__ ("" : : : "memory"); } #if ANDROID_SMP == 0 -extern inline void android_memory_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void) { android_compiler_barrier(); } -extern inline void android_memory_store_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void) { android_compiler_barrier(); } #else -extern inline void android_memory_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void) { __asm__ __volatile__ ("sync" : : : "memory"); } -extern inline void android_memory_store_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void) { __asm__ __volatile__ ("sync" : : : "memory"); } #endif -extern inline int32_t android_atomic_acquire_load(volatile const int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_acquire_load(volatile const int32_t *ptr) { int32_t value = *ptr; android_memory_barrier(); return value; } -extern inline int32_t android_atomic_release_load(volatile const int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_release_load(volatile const int32_t *ptr) { android_memory_barrier(); return *ptr; } -extern inline void android_atomic_acquire_store(int32_t value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE void +android_atomic_acquire_store(int32_t value, volatile int32_t *ptr) { *ptr = value; android_memory_barrier(); } -extern inline void android_atomic_release_store(int32_t value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE void +android_atomic_release_store(int32_t value, volatile int32_t *ptr) { android_memory_barrier(); *ptr = value; } -extern inline int android_atomic_cas(int32_t old_value, int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr) { int32_t prev, status; do { @@ -90,26 +96,28 @@ extern inline int android_atomic_cas(int32_t old_value, int32_t new_value, return prev != old_value; } -extern inline int android_atomic_acquire_cas(int32_t old_value, - int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_acquire_cas(int32_t old_value, + int32_t new_value, + volatile int32_t *ptr) { int status = android_atomic_cas(old_value, new_value, ptr); android_memory_barrier(); return status; } -extern inline int android_atomic_release_cas(int32_t old_value, - int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_release_cas(int32_t old_value, + int32_t new_value, + volatile int32_t *ptr) { android_memory_barrier(); return android_atomic_cas(old_value, new_value, ptr); } -extern inline int32_t android_atomic_swap(int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_swap(int32_t new_value, volatile int32_t *ptr) { int32_t prev, status; do { @@ -125,8 +133,8 @@ extern inline int32_t android_atomic_swap(int32_t new_value, return prev; } -extern inline int32_t android_atomic_add(int32_t increment, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_add(int32_t increment, volatile int32_t *ptr) { int32_t prev, status; android_memory_barrier(); @@ -142,17 +150,20 @@ extern inline int32_t android_atomic_add(int32_t increment, return prev; } -extern inline int32_t android_atomic_inc(volatile int32_t *addr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_inc(volatile int32_t *addr) { return android_atomic_add(1, addr); } -extern inline int32_t android_atomic_dec(volatile int32_t *addr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_dec(volatile int32_t *addr) { return android_atomic_add(-1, addr); } -extern inline int32_t android_atomic_and(int32_t value, volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_and(int32_t value, volatile int32_t *ptr) { int32_t prev, status; android_memory_barrier(); @@ -168,7 +179,8 @@ extern inline int32_t android_atomic_and(int32_t value, volatile int32_t *ptr) return prev; } -extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_or(int32_t value, volatile int32_t *ptr) { int32_t prev, status; android_memory_barrier(); diff --git a/include/cutils/atomic-x86.h b/include/cutils/atomic-x86.h index 438012e50..9480f57fe 100644 --- a/include/cutils/atomic-x86.h +++ b/include/cutils/atomic-x86.h @@ -19,60 +19,66 @@ #include -extern inline void android_compiler_barrier(void) +#ifndef ANDROID_ATOMIC_INLINE +#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline)) +#endif + +extern ANDROID_ATOMIC_INLINE void android_compiler_barrier(void) { __asm__ __volatile__ ("" : : : "memory"); } #if ANDROID_SMP == 0 -extern inline void android_memory_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void) { android_compiler_barrier(); } -extern inline void android_memory_store_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void) { android_compiler_barrier(); } #else -extern inline void android_memory_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void) { __asm__ __volatile__ ("mfence" : : : "memory"); } -extern inline void android_memory_store_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void) { android_compiler_barrier(); } #endif -extern inline int32_t android_atomic_acquire_load(volatile const int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_acquire_load(volatile const int32_t *ptr) { int32_t value = *ptr; android_compiler_barrier(); return value; } -extern inline int32_t android_atomic_release_load(volatile const int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_release_load(volatile const int32_t *ptr) { android_memory_barrier(); return *ptr; } -extern inline void android_atomic_acquire_store(int32_t value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE void +android_atomic_acquire_store(int32_t value, volatile int32_t *ptr) { *ptr = value; android_memory_barrier(); } -extern inline void android_atomic_release_store(int32_t value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE void +android_atomic_release_store(int32_t value, volatile int32_t *ptr) { android_compiler_barrier(); *ptr = value; } -extern inline int android_atomic_cas(int32_t old_value, int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr) { int32_t prev; __asm__ __volatile__ ("lock; cmpxchgl %1, %2" @@ -82,24 +88,26 @@ extern inline int android_atomic_cas(int32_t old_value, int32_t new_value, return prev != old_value; } -extern inline int android_atomic_acquire_cas(int32_t old_value, - int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_acquire_cas(int32_t old_value, + int32_t new_value, + volatile int32_t *ptr) { /* Loads are not reordered with other loads. */ return android_atomic_cas(old_value, new_value, ptr); } -extern inline int android_atomic_release_cas(int32_t old_value, - int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_release_cas(int32_t old_value, + int32_t new_value, + volatile int32_t *ptr) { /* Stores are not reordered with other stores. */ return android_atomic_cas(old_value, new_value, ptr); } -extern inline int32_t android_atomic_add(int32_t increment, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_add(int32_t increment, volatile int32_t *ptr) { __asm__ __volatile__ ("lock; xaddl %0, %1" : "+r" (increment), "+m" (*ptr) @@ -108,18 +116,20 @@ extern inline int32_t android_atomic_add(int32_t increment, return increment; } -extern inline int32_t android_atomic_inc(volatile int32_t *addr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_inc(volatile int32_t *addr) { return android_atomic_add(1, addr); } -extern inline int32_t android_atomic_dec(volatile int32_t *addr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_dec(volatile int32_t *addr) { return android_atomic_add(-1, addr); } -extern inline int32_t android_atomic_and(int32_t value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_and(int32_t value, volatile int32_t *ptr) { int32_t prev, status; do { @@ -129,7 +139,8 @@ extern inline int32_t android_atomic_and(int32_t value, return prev; } -extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_or(int32_t value, volatile int32_t *ptr) { int32_t prev, status; do { diff --git a/libcutils/atomic.c b/libcutils/atomic.c index f6cd8b0e7..1484ef890 100644 --- a/libcutils/atomic.c +++ b/libcutils/atomic.c @@ -14,6 +14,6 @@ * limitations under the License. */ -#define inline +#define ANDROID_ATOMIC_INLINE #include From dea46b6657845a366d13f57c720eab28c9062ab7 Mon Sep 17 00:00:00 2001 From: Guillaume Ranquet Date: Tue, 23 Oct 2012 17:11:44 +0200 Subject: [PATCH 41/89] libusbhost: permits client polling on inotify wd Modify libusbhost to expose the inotify watch descriptor to clients This modification permits clients to add the watch descriptor to their polling loop so that they don't have to use a dedicated thread only for libusbhost. Change-Id: I615bfcd56beab978135034b228d4d93337351eab Signed-off-by: Guillaume Ranquet Signed-off-by: Luc Piguet-Lacroix --- include/usbhost/usbhost.h | 13 +++ libusbhost/usbhost.c | 170 +++++++++++++++++++++++--------------- 2 files changed, 118 insertions(+), 65 deletions(-) diff --git a/include/usbhost/usbhost.h b/include/usbhost/usbhost.h index 9a6b59c5f..1d67c12a9 100644 --- a/include/usbhost/usbhost.h +++ b/include/usbhost/usbhost.h @@ -72,6 +72,19 @@ struct usb_host_context *usb_host_init(void); /* Call this to cleanup the USB host library. */ void usb_host_cleanup(struct usb_host_context *context); +/* Call this to get the inotify file descriptor. */ +int usb_host_get_fd(struct usb_host_context *context); + +/* Call this to initialize the usb host context. */ +int usb_host_load(struct usb_host_context *context, + usb_device_added_cb added_cb, + usb_device_removed_cb removed_cb, + usb_discovery_done_cb discovery_done_cb, + void *client_data); + +/* Call this to read and handle occuring usb event. */ +int usb_host_read_event(struct usb_host_context *context); + /* Call this to monitor the USB bus for new and removed devices. * This is intended to be called from a dedicated thread, * as it will not return until one of the callbacks returns true. diff --git a/libusbhost/usbhost.c b/libusbhost/usbhost.c index c059b898f..167fa6061 100644 --- a/libusbhost/usbhost.c +++ b/libusbhost/usbhost.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -50,16 +51,23 @@ #include "usbhost/usbhost.h" #define DEV_DIR "/dev" -#define USB_FS_DIR "/dev/bus/usb" -#define USB_FS_ID_SCANNER "/dev/bus/usb/%d/%d" -#define USB_FS_ID_FORMAT "/dev/bus/usb/%03d/%03d" +#define USB_FS_DIR DEV_DIR "/bus/usb" +#define USB_FS_ID_SCANNER USB_FS_DIR "/%d/%d" +#define USB_FS_ID_FORMAT USB_FS_DIR "/%03d/%03d" // From drivers/usb/core/devio.c // I don't know why this isn't in a kernel header #define MAX_USBFS_BUFFER_SIZE 16384 +#define MAX_USBFS_WD_COUNT 10 + struct usb_host_context { - int fd; + int fd; + usb_device_added_cb cb_added; + usb_device_removed_cb cb_removed; + void *data; + int wds[MAX_USBFS_WD_COUNT]; + int wdd; }; struct usb_device { @@ -116,10 +124,10 @@ static int find_existing_devices(usb_device_added_cb added_cb, while ((de = readdir(busdir)) != 0 && !done) { if(badname(de->d_name)) continue; - snprintf(busname, sizeof(busname), "%s/%s", USB_FS_DIR, de->d_name); + snprintf(busname, sizeof(busname), USB_FS_DIR "/%s", de->d_name); done = find_existing_devices_bus(busname, added_cb, client_data); - } + } //end of busdir while closedir(busdir); return done; @@ -137,7 +145,7 @@ static void watch_existing_subdirs(struct usb_host_context *context, /* watch existing subdirectories of USB_FS_DIR */ for (i = 1; i < wd_count; i++) { - snprintf(path, sizeof(path), "%s/%03d", USB_FS_DIR, i); + snprintf(path, sizeof(path), USB_FS_DIR "/%03d", i); ret = inotify_add_watch(context->fd, path, IN_CREATE | IN_DELETE); if (ret >= 0) wds[i] = ret; @@ -166,93 +174,126 @@ void usb_host_cleanup(struct usb_host_context *context) free(context); } -void usb_host_run(struct usb_host_context *context, +int usb_host_get_fd(struct usb_host_context *context) +{ + return context->fd; +} /* usb_host_get_fd() */ + +int usb_host_load(struct usb_host_context *context, usb_device_added_cb added_cb, usb_device_removed_cb removed_cb, usb_discovery_done_cb discovery_done_cb, void *client_data) { - struct inotify_event* event; - char event_buf[512]; - char path[100]; - int i, ret, done = 0; - int wd, wdd, wds[10]; - int wd_count = sizeof(wds) / sizeof(wds[0]); + int done = 0; + int i; + + context->cb_added = added_cb; + context->cb_removed = removed_cb; + context->data = client_data; D("Created device discovery thread\n"); /* watch for files added and deleted within USB_FS_DIR */ - for (i = 0; i < wd_count; i++) - wds[i] = -1; + for (i = 0; i < MAX_USBFS_WD_COUNT; i++) + context->wds[i] = -1; /* watch the root for new subdirectories */ - wdd = inotify_add_watch(context->fd, DEV_DIR, IN_CREATE | IN_DELETE); - if (wdd < 0) { + context->wdd = inotify_add_watch(context->fd, DEV_DIR, IN_CREATE | IN_DELETE); + if (context->wdd < 0) { fprintf(stderr, "inotify_add_watch failed\n"); if (discovery_done_cb) discovery_done_cb(client_data); - return; + return done; } - watch_existing_subdirs(context, wds, wd_count); + watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT); /* check for existing devices first, after we have inotify set up */ done = find_existing_devices(added_cb, client_data); if (discovery_done_cb) done |= discovery_done_cb(client_data); - while (!done) { - ret = read(context->fd, event_buf, sizeof(event_buf)); - if (ret >= (int)sizeof(struct inotify_event)) { - event = (struct inotify_event *)event_buf; - wd = event->wd; - if (wd == wdd) { - if ((event->mask & IN_CREATE) && !strcmp(event->name, "bus")) { - watch_existing_subdirs(context, wds, wd_count); - done = find_existing_devices(added_cb, client_data); - } else if ((event->mask & IN_DELETE) && !strcmp(event->name, "bus")) { - for (i = 0; i < wd_count; i++) { - if (wds[i] >= 0) { - inotify_rm_watch(context->fd, wds[i]); - wds[i] = -1; - } + return done; +} /* usb_host_load() */ + +int usb_host_read_event(struct usb_host_context *context) +{ + struct inotify_event* event; + char event_buf[512]; + char path[100]; + int i, ret, done = 0; + int j, event_size; + int wd; + + ret = read(context->fd, event_buf, sizeof(event_buf)); + if (ret >= (int)sizeof(struct inotify_event)) { + event = (struct inotify_event *)event_buf; + wd = event->wd; + if (wd == context->wdd) { + if ((event->mask & IN_CREATE) && !strcmp(event->name, "bus")) { + watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT); + done = find_existing_devices(context->cb_added, context->data); + } else if ((event->mask & IN_DELETE) && !strcmp(event->name, "bus")) { + for (i = 0; i < MAX_USBFS_WD_COUNT; i++) { + if (context->wds[i] >= 0) { + inotify_rm_watch(context->fd, context->wds[i]); + context->wds[i] = -1; } } - } else if (wd == wds[0]) { - i = atoi(event->name); - snprintf(path, sizeof(path), "%s/%s", USB_FS_DIR, event->name); - D("%s subdirectory %s: index: %d\n", (event->mask & IN_CREATE) ? - "new" : "gone", path, i); - if (i > 0 && i < wd_count) { - if (event->mask & IN_CREATE) { - ret = inotify_add_watch(context->fd, path, - IN_CREATE | IN_DELETE); - if (ret >= 0) - wds[i] = ret; - done = find_existing_devices_bus(path, added_cb, - client_data); - } else if (event->mask & IN_DELETE) { - inotify_rm_watch(context->fd, wds[i]); - wds[i] = -1; - } + } + } else if (wd == context->wds[0]) { + i = atoi(event->name); + snprintf(path, sizeof(path), USB_FS_DIR "/%s", event->name); + D("%s subdirectory %s: index: %d\n", (event->mask & IN_CREATE) ? + "new" : "gone", path, i); + if (i > 0 && i < MAX_USBFS_WD_COUNT) { + if (event->mask & IN_CREATE) { + ret = inotify_add_watch(context->fd, path, + IN_CREATE | IN_DELETE); + if (ret >= 0) + context->wds[i] = ret; + done = find_existing_devices_bus(path, context->cb_added, + context->data); + } else if (event->mask & IN_DELETE) { + inotify_rm_watch(context->fd, context->wds[i]); + context->wds[i] = -1; } - } else { - for (i = 1; i < wd_count && !done; i++) { - if (wd == wds[i]) { - snprintf(path, sizeof(path), "%s/%03d/%s", USB_FS_DIR, i, event->name); - if (event->mask == IN_CREATE) { - D("new device %s\n", path); - done = added_cb(path, client_data); - } else if (event->mask == IN_DELETE) { - D("gone device %s\n", path); - done = removed_cb(path, client_data); - } + } + } else { + for (i = 1; (i < MAX_USBFS_WD_COUNT) && !done; i++) { + if (wd == context->wds[i]) { + snprintf(path, sizeof(path), USB_FS_DIR "/%03d/%s", i, event->name); + if (event->mask == IN_CREATE) { + D("new device %s\n", path); + done = context->cb_added(path, context->data); + } else if (event->mask == IN_DELETE) { + D("gone device %s\n", path); + done = context->cb_removed(path, context->data); } } } } } -} + + return done; +} /* usb_host_read_event() */ + +void usb_host_run(struct usb_host_context *context, + usb_device_added_cb added_cb, + usb_device_removed_cb removed_cb, + usb_discovery_done_cb discovery_done_cb, + void *client_data) +{ + int done; + + done = usb_host_load(context, added_cb, removed_cb, discovery_done_cb, client_data); + + while (!done) { + + done = usb_host_read_event(context); + } +} /* usb_host_run() */ struct usb_device *usb_device_open(const char *dev_name) { @@ -606,7 +647,6 @@ struct usb_request *usb_request_wait(struct usb_device *dev) { struct usbdevfs_urb *urb = NULL; struct usb_request *req = NULL; - int res; while (1) { int res = ioctl(dev->fd, USBDEVFS_REAPURB, &urb); From 08c119910aed26011a26eb95b1c4477eb16c22a0 Mon Sep 17 00:00:00 2001 From: Guillaume Ranquet Date: Fri, 7 Dec 2012 13:39:39 +0100 Subject: [PATCH 42/89] libusbhost: generates a static library due to limitations of the droidboot OS used for POS, there's a need for a static libusbhost library. this permits to include libusbhost in droidboot Change-Id: I0f0c07817ad19b773b466b69fd6e997877d41b34 Signed-off-by: Guillaume Ranquet --- libusbhost/Android.mk | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libusbhost/Android.mk b/libusbhost/Android.mk index 52b4eadc9..9565cc57b 100644 --- a/libusbhost/Android.mk +++ b/libusbhost/Android.mk @@ -44,3 +44,13 @@ LOCAL_CFLAGS := -g -DUSE_LIBLOG LOCAL_SHARED_LIBRARIES := libcutils include $(BUILD_SHARED_LIBRARY) + +# Static library for target +# ======================================================== + +include $(CLEAR_VARS) + +LOCAL_MODULE := libusbhost +LOCAL_SRC_FILES := usbhost.c + +include $(BUILD_STATIC_LIBRARY) From 8f7d4430f341c555533ef6effd883a5aae1ce160 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Mon, 10 Dec 2012 10:29:05 -0800 Subject: [PATCH 43/89] Add missing signal codes to get_sigcode. The only common one we were missing is SI_TKILL, but we've had the full set on the dalvik-dev branch for some time now. Change-Id: I7cf52d352b8624e0adb17a2ed440e7a10f490dfd --- debuggerd/tombstone.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/debuggerd/tombstone.c b/debuggerd/tombstone.c index 5f2db43e3..98016c30e 100644 --- a/debuggerd/tombstone.c +++ b/debuggerd/tombstone.c @@ -84,6 +84,7 @@ static const char *get_signame(int sig) static const char *get_sigcode(int signo, int code) { + // Try the signal-specific codes... switch (signo) { case SIGILL: switch (code) { @@ -122,7 +123,31 @@ static const char *get_sigcode(int signo, int code) case SEGV_ACCERR: return "SEGV_ACCERR"; } break; + case SIGTRAP: + switch (code) { + case TRAP_BRKPT: return "TRAP_BRKPT"; + case TRAP_TRACE: return "TRAP_TRACE"; + } + break; } + // Then the other codes... + switch (code) { + case SI_USER: return "SI_USER"; +#if defined(SI_KERNEL) + case SI_KERNEL: return "SI_KERNEL"; +#endif + case SI_QUEUE: return "SI_QUEUE"; + case SI_TIMER: return "SI_TIMER"; + case SI_MESGQ: return "SI_MESGQ"; + case SI_ASYNCIO: return "SI_ASYNCIO"; +#if defined(SI_SIGIO) + case SI_SIGIO: return "SI_SIGIO"; +#endif +#if defined(SI_TKILL) + case SI_TKILL: return "SI_TKILL"; +#endif + } + // Then give up... return "?"; } From b08084850dd1f3e1d0a69cca7095e4a68845f89a Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Mon, 10 Dec 2012 10:40:28 -0800 Subject: [PATCH 44/89] Show pid+uid in certain failures If somebody sends debuggerd bad data, it logs a complaint but doesn't give any indication of the source. Now we show the pid and uid we get from SO_PEERCRED. Bug 7704699 Change-Id: I2738eb972932cc868ad969b60e16dd0b623212a1 --- debuggerd/debuggerd.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/debuggerd/debuggerd.c b/debuggerd/debuggerd.c index 55222c500..65ff0f661 100644 --- a/debuggerd/debuggerd.c +++ b/debuggerd/debuggerd.c @@ -202,18 +202,20 @@ static int read_request(int fd, debugger_request_t* out_request) { pollfds[0].revents = 0; status = TEMP_FAILURE_RETRY(poll(pollfds, 1, 3000)); if (status != 1) { - LOG("timed out reading tid\n"); + LOG("timed out reading tid (from pid=%d uid=%d)\n", cr.pid, cr.uid); return -1; } debugger_msg_t msg; status = TEMP_FAILURE_RETRY(read(fd, &msg, sizeof(msg))); if (status < 0) { - LOG("read failure? %s\n", strerror(errno)); + LOG("read failure? %s (pid=%d uid=%d)\n", + strerror(errno), cr.pid, cr.uid); return -1; } if (status != sizeof(msg)) { - LOG("invalid crash request of size %d\n", status); + LOG("invalid crash request of size %d (from pid=%d uid=%d)\n", + status, cr.pid, cr.uid); return -1; } @@ -245,7 +247,7 @@ static int read_request(int fd, debugger_request_t* out_request) { return -1; } } else { - /* No one else is not allowed to dump arbitrary processes. */ + /* No one else is allowed to dump arbitrary processes. */ return -1; } return 0; From aa4213057ba1723e4f164e54f80bb7621c3cb6b3 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Mon, 10 Dec 2012 14:15:42 -0800 Subject: [PATCH 45/89] Expand crasher with a "thread-" prefix to crash on another thread. So "thread-nostack" runs the "nostack" code on a new thread, and "thread-abort" runs the "abort" code on a new thread, and so on. Bug: http://code.google.com/p/android/issues/detail?id=16672 Change-Id: I026a0e43eea147f1a7a74243846954599bcf4238 --- debuggerd/crasher.c | 45 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/debuggerd/crasher.c b/debuggerd/crasher.c index 00652e975..74eaa4983 100644 --- a/debuggerd/crasher.c +++ b/debuggerd/crasher.c @@ -20,6 +20,7 @@ void crash1(void); void crashnostack(void); void maybeabort(void); +int do_action(const char* arg); static void debuggerd_connect() { @@ -74,24 +75,46 @@ int ctest() return 0; } -int main(int argc, char **argv) +static void* thread_callback(void* raw_arg) { + return (void*) do_action((const char*) raw_arg); +} + +int do_action_on_thread(const char* arg) +{ + pthread_t t; + pthread_create(&t, NULL, thread_callback, (void*) arg); + void* result = NULL; + pthread_join(t, &result); + return (int) result; +} + +int do_action(const char* arg) +{ + if(!strncmp(arg, "thread-", strlen("thread-"))) { + return do_action_on_thread(arg + strlen("thread-")); + } + + if(!strcmp(arg,"nostack")) crashnostack(); + if(!strcmp(arg,"ctest")) return ctest(); + if(!strcmp(arg,"exit")) exit(1); + if(!strcmp(arg,"abort")) maybeabort(); + pthread_t thr; pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&thr, &attr, test_thread, 0); + while(1) sleep(1); +} - fprintf(stderr,"crasher: " __TIME__ "!@\n"); +int main(int argc, char **argv) +{ + fprintf(stderr,"crasher: built at " __TIME__ "!@\n"); fprintf(stderr,"crasher: init pid=%d tid=%d\n", getpid(), gettid()); if(argc > 1) { - if(!strcmp(argv[1],"nostack")) crashnostack(); - if(!strcmp(argv[1],"ctest")) return ctest(); - if(!strcmp(argv[1],"exit")) exit(1); - if(!strcmp(argv[1],"abort")) maybeabort(); - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&thr, &attr, test_thread, 0); - while(1) sleep(1); + return do_action(argv[1]); } else { crash1(); // *((int*) 0) = 42; From 0015a42942d246cc225034b9754bb6d926b16f10 Mon Sep 17 00:00:00 2001 From: Ben Cheng Date: Mon, 10 Dec 2012 14:51:32 -0800 Subject: [PATCH 46/89] Fix ELF header parser bug. Program header size should be 32 instead of 40. Bug: 7696928 Change-Id: I8298a030790e9c28e8e8a0d2ad4e9ef294708eb6 --- libcorkscrew/arch-arm/ptrace-arm.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libcorkscrew/arch-arm/ptrace-arm.c b/libcorkscrew/arch-arm/ptrace-arm.c index 868230ceb..78a9ea9a4 100644 --- a/libcorkscrew/arch-arm/ptrace-arm.c +++ b/libcorkscrew/arch-arm/ptrace-arm.c @@ -29,12 +29,15 @@ static void load_exidx_header(pid_t pid, map_info_t* mi, uintptr_t* out_exidx_start, size_t* out_exidx_size) { uint32_t elf_phoff; - uint32_t elf_phentsize_phnum; + uint32_t elf_phentsize_ehsize; + uint32_t elf_shentsize_phnum; if (try_get_word_ptrace(pid, mi->start + offsetof(Elf32_Ehdr, e_phoff), &elf_phoff) + && try_get_word_ptrace(pid, mi->start + offsetof(Elf32_Ehdr, e_ehsize), + &elf_phentsize_ehsize) && try_get_word_ptrace(pid, mi->start + offsetof(Elf32_Ehdr, e_phnum), - &elf_phentsize_phnum)) { - uint32_t elf_phentsize = elf_phentsize_phnum >> 16; - uint32_t elf_phnum = elf_phentsize_phnum & 0xffff; + &elf_shentsize_phnum)) { + uint32_t elf_phentsize = elf_phentsize_ehsize >> 16; + uint32_t elf_phnum = elf_shentsize_phnum & 0xffff; for (uint32_t i = 0; i < elf_phnum; i++) { uintptr_t elf_phdr = mi->start + elf_phoff + i * elf_phentsize; uint32_t elf_phdr_type; From 0e23fee505fda39de4286d20022a4b2119156e15 Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Wed, 28 Nov 2012 13:52:12 -0500 Subject: [PATCH 47/89] Change setsebool syntax to be consistent with other init built-ins. Change setsebool syntax from name=value to name value. This is to make it consistent with setprop and similar commands. Update both the init built-in command and the toolbox command for consistency. Change-Id: I2c8e016ba26731c4a2ad4a49ae3b89362bf8f8a8 Signed-off-by: Stephen Smalley --- init/builtins.c | 39 +++++++++++++++++---------------------- init/keywords.h | 2 +- init/readme.txt | 2 +- toolbox/setsebool.c | 39 +++++++++++++++------------------------ 4 files changed, 34 insertions(+), 48 deletions(-) diff --git a/init/builtins.c b/init/builtins.c index baa3e7fd5..dc7900e22 100644 --- a/init/builtins.c +++ b/init/builtins.c @@ -754,34 +754,29 @@ int do_restorecon(int nargs, char **args) { } int do_setsebool(int nargs, char **args) { - SELboolean *b = alloca(nargs * sizeof(SELboolean)); - char *v; - int i; + const char *name = args[1]; + const char *value = args[2]; + SELboolean b; + int ret; if (is_selinux_enabled() <= 0) return 0; - for (i = 1; i < nargs; i++) { - char *name = args[i]; - v = strchr(name, '='); - if (!v) { - ERROR("setsebool: argument %s had no =\n", name); - return -EINVAL; - } - *v++ = 0; - b[i-1].name = name; - if (!strcmp(v, "1") || !strcasecmp(v, "true") || !strcasecmp(v, "on")) - b[i-1].value = 1; - else if (!strcmp(v, "0") || !strcasecmp(v, "false") || !strcasecmp(v, "off")) - b[i-1].value = 0; - else { - ERROR("setsebool: invalid value %s\n", v); - return -EINVAL; - } + b.name = name; + if (!strcmp(value, "1") || !strcasecmp(value, "true") || !strcasecmp(value, "on")) + b.value = 1; + else if (!strcmp(value, "0") || !strcasecmp(value, "false") || !strcasecmp(value, "off")) + b.value = 0; + else { + ERROR("setsebool: invalid value %s\n", value); + return -EINVAL; } - if (security_set_boolean_list(nargs - 1, b, 0) < 0) - return -errno; + if (security_set_boolean_list(1, &b, 0) < 0) { + ret = -errno; + ERROR("setsebool: could not set %s to %s\n", name, value); + return ret; + } return 0; } diff --git a/init/keywords.h b/init/keywords.h index 97d4950a8..f188db5d7 100644 --- a/init/keywords.h +++ b/init/keywords.h @@ -78,7 +78,7 @@ enum { KEYWORD(setkey, COMMAND, 0, do_setkey) KEYWORD(setprop, COMMAND, 2, do_setprop) KEYWORD(setrlimit, COMMAND, 3, do_setrlimit) - KEYWORD(setsebool, COMMAND, 1, do_setsebool) + KEYWORD(setsebool, COMMAND, 2, do_setsebool) KEYWORD(socket, OPTION, 0, 0) KEYWORD(start, COMMAND, 1, do_start) KEYWORD(stop, COMMAND, 1, do_stop) diff --git a/init/readme.txt b/init/readme.txt index 9cc291c33..7a5997d26 100644 --- a/init/readme.txt +++ b/init/readme.txt @@ -213,7 +213,7 @@ setprop setrlimit Set the rlimit for a resource. -setsebool = +setsebool Set SELinux boolean to . may be 1|true|on or 0|false|off diff --git a/toolbox/setsebool.c b/toolbox/setsebool.c index 4a3d87d0f..f79a6127c 100644 --- a/toolbox/setsebool.c +++ b/toolbox/setsebool.c @@ -9,35 +9,26 @@ #include static int do_setsebool(int nargs, char **args) { - SELboolean *b = alloca(nargs * sizeof(SELboolean)); - char *v; - int i; + const char *name = args[1]; + const char *value = args[2]; + SELboolean b; if (is_selinux_enabled() <= 0) return 0; - for (i = 1; i < nargs; i++) { - char *name = args[i]; - v = strchr(name, '='); - if (!v) { - fprintf(stderr, "setsebool: argument %s had no =\n", name); - return -1; - } - *v++ = 0; - b[i-1].name = name; - if (!strcmp(v, "1") || !strcasecmp(v, "true") || !strcasecmp(v, "on")) - b[i-1].value = 1; - else if (!strcmp(v, "0") || !strcasecmp(v, "false") || !strcasecmp(v, "off")) - b[i-1].value = 0; - else { - fprintf(stderr, "setsebool: invalid value %s\n", v); - return -1; - } + b.name = name; + if (!strcmp(value, "1") || !strcasecmp(value, "true") || !strcasecmp(value, "on")) + b.value = 1; + else if (!strcmp(value, "0") || !strcasecmp(value, "false") || !strcasecmp(value, "off")) + b.value = 0; + else { + fprintf(stderr, "setsebool: invalid value %s\n", value); + return -1; } - if (security_set_boolean_list(nargs - 1, b, 0) < 0) + if (security_set_boolean_list(1, &b, 0) < 0) { - fprintf(stderr, "setsebool: unable to set booleans: %s", strerror(errno)); + fprintf(stderr, "setsebool: could not set %s to %s: %s", name, value, strerror(errno)); return -1; } @@ -46,8 +37,8 @@ static int do_setsebool(int nargs, char **args) { int setsebool_main(int argc, char **argv) { - if (argc < 2) { - fprintf(stderr, "Usage: %s name=value...\n", argv[0]); + if (argc != 3) { + fprintf(stderr, "Usage: %s name value\n", argv[0]); exit(1); } From 04aaf5a424b1f88a481a17a6bc3518e2116250e2 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 21 Dec 2012 12:50:29 -0800 Subject: [PATCH 48/89] android_filesystem_config: allow absolute paths SELinux policies use absolute paths, allow absolute paths in fs_config as well. Change-Id: Ic97ee0b4eb4df9eac965a8e819fde01df473de7e --- include/private/android_filesystem_config.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h index 3a2500ede..f90af81ca 100644 --- a/include/private/android_filesystem_config.h +++ b/include/private/android_filesystem_config.h @@ -236,6 +236,10 @@ static inline void fs_config(const char *path, int dir, struct fs_path_config *pc; int plen; + if (path[0] == '/') { + path++; + } + pc = dir ? android_dirs : android_files; plen = strlen(path); for(; pc->prefix; pc++){ From 334ad0ed49356db93ef17c173cad19d098923ffe Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 21 Dec 2012 14:45:27 -0800 Subject: [PATCH 49/89] Track the setsebool change in the emulator init.rc. setsebool's syntax changed in November. This is the sole caller in AOSP. Change-Id: I0da608ee974bc3a9060372ef68a71c52726a44a6 --- rootdir/etc/init.goldfish.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rootdir/etc/init.goldfish.rc b/rootdir/etc/init.goldfish.rc index cde9dee2d..a0c1c4f31 100644 --- a/rootdir/etc/init.goldfish.rc +++ b/rootdir/etc/init.goldfish.rc @@ -5,7 +5,7 @@ on early-init symlink /mnt/sdcard /sdcard on boot - setsebool in_qemu=1 + setsebool in_qemu 1 restorecon /sys/qemu_trace/process_name restorecon /sys/qemu_trace/state restorecon /sys/qemu_trace/symbol From 9c607552077321d9b6b2e29dab8a6e276bffb457 Mon Sep 17 00:00:00 2001 From: Chih-Wei Huang Date: Tue, 1 Jan 2013 15:24:33 +0800 Subject: [PATCH 50/89] Correct LOCAL_LDLIBS of adb adb doesn't really use ncurses-libs, remove it. Add -ldl for the symbols dlclose, dlerror, dlopen... introduced from dso_dlfcn.c of libcrypto_static.a. Change-Id: If1cc23987a9b35ec535bbf8f4e7db141b9f10af7 --- adb/Android.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adb/Android.mk b/adb/Android.mk index bc8315ed2..32dd95a46 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -16,7 +16,7 @@ EXTRA_SRCS := ifeq ($(HOST_OS),linux) USB_SRCS := usb_linux.c EXTRA_SRCS := get_my_path_linux.c - LOCAL_LDLIBS += -lrt -lncurses -lpthread + LOCAL_LDLIBS += -lrt -ldl -lpthread endif ifeq ($(HOST_OS),darwin) @@ -139,7 +139,7 @@ include $(BUILD_EXECUTABLE) ifneq ($(SDK_ONLY),true) include $(CLEAR_VARS) -LOCAL_LDLIBS := -lrt -lncurses -lpthread +LOCAL_LDLIBS := -lrt -ldl -lpthread LOCAL_SRC_FILES := \ adb.c \ From 2b5b3bb103f59d9d3bf25c0c1f8035db036917da Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Thu, 20 Dec 2012 18:52:03 -0800 Subject: [PATCH 51/89] rootdir: init.rc: set perms for new interactive governor attrs /sys/devices/system/cpu/cpufreq/interactive/timer_slack /sys/devices/system/cpu/cpufreq/interactive/target_loads Change-Id: Ia5d5c3d615ad64bab3a1317e5de2ac9a6d61679e --- rootdir/init.rc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rootdir/init.rc b/rootdir/init.rc index 1a671f5e0..d4baab421 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -281,10 +281,14 @@ on boot chown system system /sys/devices/system/cpu/cpufreq/interactive/timer_rate chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/timer_rate + chown system system /sys/devices/system/cpu/cpufreq/interactive/timer_slack + chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/timer_slack chown system system /sys/devices/system/cpu/cpufreq/interactive/min_sample_time chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/min_sample_time chown system system /sys/devices/system/cpu/cpufreq/interactive/hispeed_freq chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/hispeed_freq + chown system system /sys/devices/system/cpu/cpufreq/interactive/target_loads + chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/target_loads chown system system /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load chown system system /sys/devices/system/cpu/cpufreq/interactive/above_hispeed_delay From d1420be6133fc5ba71d59315936fb85239ea78b1 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Thu, 3 Jan 2013 13:39:57 -0800 Subject: [PATCH 52/89] Include page protections in the debuggerd map output. Bug: 7941716 Change-Id: I3bf475425c628c06f7799340c8a6132aab741742 --- debuggerd/tombstone.c | 30 +++++++++++++++--------------- include/corkscrew/map_info.h | 6 ++++-- libcorkscrew/map_info.c | 11 +++++++++-- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/debuggerd/tombstone.c b/debuggerd/tombstone.c index 98016c30e..e8b3e24d1 100644 --- a/debuggerd/tombstone.c +++ b/debuggerd/tombstone.c @@ -350,6 +350,18 @@ static void dump_backtrace_and_stack(const ptrace_context_t* context, log_t* log } } +static void dump_map(log_t* log, map_info_t* m, const char* what) { + if (m != NULL) { + _LOG(log, false, " %08x-%08x %c%c%c %s\n", m->start, m->end, + m->is_readable ? 'r' : '-', + m->is_writable ? 'w' : '-', + m->is_executable ? 'x' : '-', + m->name); + } else { + _LOG(log, false, " (no %s)\n", what); + } +} + static void dump_nearby_maps(const ptrace_context_t* context, log_t* log, pid_t tid) { siginfo_t si; memset(&si, 0, sizeof(si)); @@ -396,21 +408,9 @@ static void dump_nearby_maps(const ptrace_context_t* context, log_t* log, pid_t * Show "next" then "match" then "prev" so that the addresses appear in * ascending order (like /proc/pid/maps). */ - if (next != NULL) { - _LOG(log, false, " %08x-%08x %s\n", next->start, next->end, next->name); - } else { - _LOG(log, false, " (no map below)\n"); - } - if (map != NULL) { - _LOG(log, false, " %08x-%08x %s\n", map->start, map->end, map->name); - } else { - _LOG(log, false, " (no map for address)\n"); - } - if (prev != NULL) { - _LOG(log, false, " %08x-%08x %s\n", prev->start, prev->end, prev->name); - } else { - _LOG(log, false, " (no map above)\n"); - } + dump_map(log, next, "map below"); + dump_map(log, map, "map for address"); + dump_map(log, prev, "map above"); } static void dump_thread(const ptrace_context_t* context, log_t* log, pid_t tid, bool at_fault, diff --git a/include/corkscrew/map_info.h b/include/corkscrew/map_info.h index ea1d35ffb..c9b241d3c 100644 --- a/include/corkscrew/map_info.h +++ b/include/corkscrew/map_info.h @@ -32,6 +32,7 @@ typedef struct map_info { uintptr_t start; uintptr_t end; bool is_readable; + bool is_writable; bool is_executable; void* data; // arbitrary data associated with the map by the user, initially NULL char name[]; @@ -46,9 +47,10 @@ void free_map_info_list(map_info_t* milist); /* Finds the memory map that contains the specified address. */ const map_info_t* find_map_info(const map_info_t* milist, uintptr_t addr); -/* Returns true if the addr is in an readable map. */ +/* Returns true if the addr is in a readable map. */ bool is_readable_map(const map_info_t* milist, uintptr_t addr); - +/* Returns true if the addr is in a writable map. */ +bool is_writable_map(const map_info_t* milist, uintptr_t addr); /* Returns true if the addr is in an executable map. */ bool is_executable_map(const map_info_t* milist, uintptr_t addr); diff --git a/libcorkscrew/map_info.c b/libcorkscrew/map_info.c index 3c5285416..6a27664d9 100644 --- a/libcorkscrew/map_info.c +++ b/libcorkscrew/map_info.c @@ -57,13 +57,15 @@ static map_info_t* parse_maps_line(const char* line) mi->start = start; mi->end = end; mi->is_readable = strlen(permissions) == 4 && permissions[0] == 'r'; + mi->is_writable = strlen(permissions) == 4 && permissions[1] == 'w'; mi->is_executable = strlen(permissions) == 4 && permissions[2] == 'x'; mi->data = NULL; memcpy(mi->name, name, name_len); mi->name[name_len] = '\0'; ALOGV("Parsed map: start=0x%08x, end=0x%08x, " - "is_readable=%d, is_executable=%d, name=%s", - mi->start, mi->end, mi->is_readable, mi->is_executable, mi->name); + "is_readable=%d, is_writable=%d, is_executable=%d, name=%s", + mi->start, mi->end, + mi->is_readable, mi->is_writable, mi->is_executable, mi->name); } return mi; } @@ -110,6 +112,11 @@ bool is_readable_map(const map_info_t* milist, uintptr_t addr) { return mi && mi->is_readable; } +bool is_writable_map(const map_info_t* milist, uintptr_t addr) { + const map_info_t* mi = find_map_info(milist, addr); + return mi && mi->is_writable; +} + bool is_executable_map(const map_info_t* milist, uintptr_t addr) { const map_info_t* mi = find_map_info(milist, addr); return mi && mi->is_executable; From 4d74bcf4458c4b2c902a3d4f45afbd51f5a3be1e Mon Sep 17 00:00:00 2001 From: Rom Lemarchand Date: Thu, 3 Jan 2013 14:37:57 -0800 Subject: [PATCH 53/89] Remove -d option from logwrapper Removing the ability of logwrapper to die with a SIGSEGV at address "return code from wait". Change-Id: I563715db2b1e5e789af84190fc2ff78664d63572 --- logwrapper/logwrapper.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/logwrapper/logwrapper.c b/logwrapper/logwrapper.c index dd777c032..3b876d4e6 100644 --- a/logwrapper/logwrapper.c +++ b/logwrapper/logwrapper.c @@ -35,17 +35,14 @@ void fatal(const char *msg) { void usage() { fatal( - "Usage: logwrapper [-d] BINARY [ARGS ...]\n" + "Usage: logwrapper BINARY [ARGS ...]\n" "\n" "Forks and executes BINARY ARGS, redirecting stdout and stderr to\n" "the Android logging system. Tag is set to BINARY, priority is\n" - "always LOG_INFO.\n" - "\n" - "-d: Causes logwrapper to SIGSEGV when BINARY terminates\n" - " fault address is set to the status of wait()\n"); + "always LOG_INFO.\n"); } -void parent(const char *tag, int seg_fault_on_exit, int parent_read) { +void parent(const char *tag, int parent_read) { int status; char buffer[4096]; @@ -105,8 +102,6 @@ void parent(const char *tag, int seg_fault_on_exit, int parent_read) { } else ALOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag, strerror(errno), errno); - if (seg_fault_on_exit) - *(int *)status = 0; // causes SIGSEGV with fault_address = status } void child(int argc, char* argv[]) { @@ -124,7 +119,6 @@ void child(int argc, char* argv[]) { int main(int argc, char* argv[]) { pid_t pid; - int seg_fault_on_exit = 0; int parent_ptty; int child_ptty; @@ -134,16 +128,6 @@ int main(int argc, char* argv[]) { usage(); } - if (strncmp(argv[1], "-d", 2) == 0) { - seg_fault_on_exit = 1; - argc--; - argv++; - } - - if (argc < 2) { - usage(); - } - /* Use ptty instead of socketpair so that STDOUT is not buffered */ parent_ptty = open("/dev/ptmx", O_RDWR); if (parent_ptty < 0) { @@ -179,7 +163,7 @@ int main(int argc, char* argv[]) { setgid(AID_LOG); setuid(AID_LOG); - parent(argv[1], seg_fault_on_exit, parent_ptty); + parent(argv[1], parent_ptty); } return 0; From ba2ba5c011a3fb13cba538296b70888dd0fb129b Mon Sep 17 00:00:00 2001 From: Matt Gumbel Date: Fri, 4 Jan 2013 09:53:42 -0800 Subject: [PATCH 54/89] Fix dhcpcd startup when net.hostname is not set Commit 62d6f74 swapped p2p_interface and DHCP_CONFIG_PATH erroneously. This reverts them to their correct ordering and makes dhcpcd startup work again. Change-Id: Iea033a7e0dad98bb2a63fb39755330675cfbb0ab Signed-off-by: Matt Gumbel --- libnetutils/dhcp_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c index d0ca90acb..b4caaf977 100644 --- a/libnetutils/dhcp_utils.c +++ b/libnetutils/dhcp_utils.c @@ -211,7 +211,7 @@ int dhcp_do_request(const char *interface, p2p_interface, DHCP_CONFIG_PATH, prop_value, interface); else snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s:-f %s %s", DAEMON_NAME, - DHCP_CONFIG_PATH, p2p_interface, interface); + p2p_interface, DHCP_CONFIG_PATH, interface); memset(prop_value, '\0', PROPERTY_VALUE_MAX); property_set(ctrl_prop, daemon_cmd); if (wait_for_property(daemon_prop_name, desired_status, 10) < 0) { From d7b33085117ccbb908a883f624cb1fe5495ee92a Mon Sep 17 00:00:00 2001 From: Matt Gumbel Date: Wed, 14 Nov 2012 10:16:17 -0800 Subject: [PATCH 55/89] Support adb client connect to remote server ADB client: allow user to specify hostname and port number of remote adb server. ADB server: bind server to all network interfaces instead of just localhost when user gives -a flag. Primary use-case for this change is to support remote testing of USB devices. HostA is running some test automation software which invokes adb client. HostB has USB-only device attached and is running adb server. adb client on HostA makes connection to adb server on HostB to talk to the USB device. Change-Id: I845cc8c00350b400317f8c18f813e6fd79bd5470 Signed-off-by: Dean Kwon Signed-off-by: Jim Bride Signed-off-by: Matt Gumbel --- adb/adb.c | 13 +++++++++++-- adb/adb_client.c | 19 ++++++++++++++++--- adb/adb_client.h | 4 ++++ adb/commandline.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 73 insertions(+), 7 deletions(-) diff --git a/adb/adb.c b/adb/adb.c index b3283de9a..4c3364fe5 100644 --- a/adb/adb.c +++ b/adb/adb.c @@ -46,6 +46,7 @@ ADB_MUTEX_DEFINE( D_lock ); #endif int HOST = 0; +int gListenAll = 0; static int auth_enabled = 0; @@ -701,7 +702,13 @@ int local_name_to_fd(const char *name) if(!strncmp("tcp:", name, 4)){ int ret; port = atoi(name + 4); - ret = socket_loopback_server(port, SOCK_STREAM); + + if (gListenAll > 0) { + ret = socket_inaddr_any_server(port, SOCK_STREAM); + } else { + ret = socket_loopback_server(port, SOCK_STREAM); + } + return ret; } #ifndef HAVE_WIN32_IPC /* no Unix-domain sockets on Win32 */ @@ -1079,8 +1086,10 @@ int launch_server(int server_port) dup2(fd[1], STDERR_FILENO); adb_close(fd[1]); + char str_port[30]; + snprintf(str_port, sizeof(str_port), "%d", server_port); // child process - int result = execl(path, "adb", "fork-server", "server", NULL); + int result = execl(path, "adb", "-P", str_port, "fork-server", "server", NULL); // this should not return fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno); } else { diff --git a/adb/adb_client.c b/adb/adb_client.c index 9a812f0cf..8340738c9 100644 --- a/adb/adb_client.c +++ b/adb/adb_client.c @@ -17,6 +17,7 @@ static transport_type __adb_transport = kTransportAny; static const char* __adb_serial = NULL; static int __adb_server_port = DEFAULT_ADB_PORT; +static const char* __adb_server_name = NULL; void adb_set_transport(transport_type type, const char* serial) { @@ -29,6 +30,11 @@ void adb_set_tcp_specifics(int server_port) __adb_server_port = server_port; } +void adb_set_tcp_name(const char* hostname) +{ + __adb_server_name = hostname; +} + int adb_get_emulator_console_port(void) { const char* serial = __adb_serial; @@ -181,7 +187,11 @@ int _adb_connect(const char *service) } snprintf(tmp, sizeof tmp, "%04x", len); - fd = socket_loopback_client(__adb_server_port, SOCK_STREAM); + if (__adb_server_name) + fd = socket_network_client(__adb_server_name, __adb_server_port, SOCK_STREAM); + else + fd = socket_loopback_client(__adb_server_port, SOCK_STREAM); + if(fd < 0) { strcpy(__adb_error, "cannot connect to daemon"); return -2; @@ -212,7 +222,10 @@ int adb_connect(const char *service) int fd = _adb_connect("host:version"); D("adb_connect: service %s\n", service); - if(fd == -2) { + if(fd == -2 && __adb_server_name) { + fprintf(stderr,"** Cannot start server on remote host\n"); + return fd; + } else if(fd == -2) { fprintf(stdout,"* daemon not running. starting it now on port %d *\n", __adb_server_port); start_server: @@ -266,7 +279,7 @@ int adb_connect(const char *service) fd = _adb_connect(service); if(fd == -2) { - fprintf(stderr,"** daemon still not running"); + fprintf(stderr,"** daemon still not running\n"); } D("adb_connect: return fd %d\n", fd); diff --git a/adb/adb_client.h b/adb/adb_client.h index 40ab18970..0ec47ca89 100644 --- a/adb/adb_client.h +++ b/adb/adb_client.h @@ -29,6 +29,10 @@ void adb_set_transport(transport_type type, const char* serial); */ void adb_set_tcp_specifics(int server_port); +/* Set TCP Hostname of the transport to use +*/ +void adb_set_tcp_name(const char* hostname); + /* Return the console port of the currently connected emulator (if any) * of -1 if there is no emulator, and -2 if there is more than one. * assumes adb_set_transport() was alled previously... diff --git a/adb/commandline.c b/adb/commandline.c index a4c2f40ee..cbe46160a 100644 --- a/adb/commandline.c +++ b/adb/commandline.c @@ -46,6 +46,7 @@ int install_app(transport_type transport, char* serial, int argc, char** argv); int uninstall_app(transport_type transport, char* serial, int argc, char** argv); static const char *gProductOutPath = NULL; +extern int gListenAll; static char *product_file(const char *extra) { @@ -80,6 +81,7 @@ void help() fprintf(stderr, "\n" + " -a - directs adb to listen on all interfaces for a connection\n" " -d - directs command to the only connected USB device\n" " returns an error if more than one USB device is present.\n" " -e - directs command to the only running emulator.\n" @@ -93,6 +95,8 @@ void help() " If -p is not specified, the ANDROID_PRODUCT_OUT\n" " environment variable is used, which must\n" " be an absolute path.\n" + " -H - Name of adb server host (default: localhost)\n" + " -P - Port of adb server (default: 5037)\n" " devices [-l] - list all connected devices\n" " ('-l' will also list device qualifiers)\n" " connect [:] - connect to a device via TCP/IP\n" @@ -946,9 +950,9 @@ int adb_commandline(int argc, char **argv) int server_port = DEFAULT_ADB_PORT; if (server_port_str && strlen(server_port_str) > 0) { server_port = (int) strtol(server_port_str, NULL, 0); - if (server_port <= 0) { + if (server_port <= 0 || server_port > 65535) { fprintf(stderr, - "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n", + "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65535. Got \"%s\"\n", server_port_str); return usage(); } @@ -994,6 +998,42 @@ int adb_commandline(int argc, char **argv) ttype = kTransportUsb; } else if (!strcmp(argv[0],"-e")) { ttype = kTransportLocal; + } else if (!strcmp(argv[0],"-a")) { + gListenAll = 1; + } else if(!strncmp(argv[0], "-H", 2)) { + const char *hostname = NULL; + if (argv[0][2] == '\0') { + if (argc < 2) return usage(); + hostname = argv[1]; + argc--; + argv++; + } else { + hostname = argv[0] + 2; + } + adb_set_tcp_name(hostname); + + } else if(!strncmp(argv[0], "-P", 2)) { + if (argv[0][2] == '\0') { + if (argc < 2) return usage(); + server_port_str = argv[1]; + argc--; + argv++; + } else { + server_port_str = argv[0] + 2; + } + if (strlen(server_port_str) > 0) { + server_port = (int) strtol(server_port_str, NULL, 0); + if (server_port <= 0 || server_port > 65535) { + fprintf(stderr, + "adb: port number must be a positive number less than 65536. Got \"%s\"\n", + server_port_str); + return usage(); + } + } else { + fprintf(stderr, + "adb: port number must be a positive number less than 65536. Got empty string.\n"); + return usage(); + } } else { /* out of recognized modifiers and flags */ break; From d562ca78aa713d186e83f05061c0aed88e200bcd Mon Sep 17 00:00:00 2001 From: Andrew Boie Date: Tue, 4 Dec 2012 15:47:20 -0800 Subject: [PATCH 56/89] ueventd: Increase uevent buffer size As it turns out, no, 64K is not enough. A device provisioning tool was generating many uevents as it manipulated the GPT, causing events near the end of the process (including events as a result of the final BLKRRPART ioctl()) to get lost. It's not clear what the best value for this should be, but increasing to 256K fixed the problem in this case. Change-Id: I4883b34e96c89e8a6fa581bc9cd121bb021b5694 Signed-off-by: Andrew Boie --- init/devices.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/init/devices.c b/init/devices.c index dd875d655..b07a1a6a1 100644 --- a/init/devices.c +++ b/init/devices.c @@ -881,8 +881,8 @@ void device_init(void) sehandle = selinux_android_file_context_handle(); } - /* is 64K enough? udev uses 16MB! */ - device_fd = uevent_open_socket(64*1024, true); + /* is 256K enough? udev uses 16MB! */ + device_fd = uevent_open_socket(256*1024, true); if(device_fd < 0) return; From 3e54aabc63535572242477fadbf13ec42b06649e Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Fri, 4 Jan 2013 14:34:58 -0800 Subject: [PATCH 57/89] init.rc: setup qtaguid group ownership of ctrl and stat files This will help get rid of android_aid.h in the kernel. The group of the proc entries will be used in place of the default values picked up by the xt_qtaguid netfilter module (AID_NET_BW_STATS, AID_NET_BW_ACCT). This change has no effect until the matching kernel changes are submitted. Change-Id: I3c177e7b5caf9c59300eba6bd4a976634b333674 --- rootdir/init.rc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rootdir/init.rc b/rootdir/init.rc index a76602c4d..52052003c 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -120,6 +120,12 @@ loglevel 3 write /dev/cpuctl/apps/bg_non_interactive/cpu.rt_runtime_us 700000 write /dev/cpuctl/apps/bg_non_interactive/cpu.rt_period_us 1000000 +# qtaguid will limit access to specific data based on group memberships. +# net_bw_acct grants impersonation of socket owners. +# net_bw_stats grants access to other apps' detailed tagged-socket stats. + chown root net_bw_acct /proc/net/xt_qtaguid/ctrl + chown root net_bw_stats /proc/net/xt_qtaguid/stats + # Allow everybody to read the xt_qtaguid resource tracking misc dev. # This is needed by any process that uses socket tagging. chmod 0644 /dev/xt_qtaguid From b10c7b4e3daadd0e8fccade8d8064f622b509eef Mon Sep 17 00:00:00 2001 From: Rom Lemarchand Date: Fri, 4 Jan 2013 16:20:36 -0800 Subject: [PATCH 58/89] Revert "Remove -d option from logwrapper" This reverts commit 4d74bcf4458c4b2c902a3d4f45afbd51f5a3be1e Change-Id: Ibcd19400cd2589b52df2b3acaba25f02676ba9e0 --- logwrapper/logwrapper.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/logwrapper/logwrapper.c b/logwrapper/logwrapper.c index 3b876d4e6..dd777c032 100644 --- a/logwrapper/logwrapper.c +++ b/logwrapper/logwrapper.c @@ -35,14 +35,17 @@ void fatal(const char *msg) { void usage() { fatal( - "Usage: logwrapper BINARY [ARGS ...]\n" + "Usage: logwrapper [-d] BINARY [ARGS ...]\n" "\n" "Forks and executes BINARY ARGS, redirecting stdout and stderr to\n" "the Android logging system. Tag is set to BINARY, priority is\n" - "always LOG_INFO.\n"); + "always LOG_INFO.\n" + "\n" + "-d: Causes logwrapper to SIGSEGV when BINARY terminates\n" + " fault address is set to the status of wait()\n"); } -void parent(const char *tag, int parent_read) { +void parent(const char *tag, int seg_fault_on_exit, int parent_read) { int status; char buffer[4096]; @@ -102,6 +105,8 @@ void parent(const char *tag, int parent_read) { } else ALOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag, strerror(errno), errno); + if (seg_fault_on_exit) + *(int *)status = 0; // causes SIGSEGV with fault_address = status } void child(int argc, char* argv[]) { @@ -119,6 +124,7 @@ void child(int argc, char* argv[]) { int main(int argc, char* argv[]) { pid_t pid; + int seg_fault_on_exit = 0; int parent_ptty; int child_ptty; @@ -128,6 +134,16 @@ int main(int argc, char* argv[]) { usage(); } + if (strncmp(argv[1], "-d", 2) == 0) { + seg_fault_on_exit = 1; + argc--; + argv++; + } + + if (argc < 2) { + usage(); + } + /* Use ptty instead of socketpair so that STDOUT is not buffered */ parent_ptty = open("/dev/ptmx", O_RDWR); if (parent_ptty < 0) { @@ -163,7 +179,7 @@ int main(int argc, char* argv[]) { setgid(AID_LOG); setuid(AID_LOG); - parent(argv[1], parent_ptty); + parent(argv[1], seg_fault_on_exit, parent_ptty); } return 0; From 2111bc7b28af06757fa8108bab045188d4b337fd Mon Sep 17 00:00:00 2001 From: Alex Ray Date: Thu, 3 Jan 2013 10:57:13 -0800 Subject: [PATCH 59/89] cutils: Add bitmask utilities to bitops Bitmask utils handle resource tracking using a (multi-word) bitmask. Change-Id: I2ae45df1ac8c665c29ea9cae32a757168686b96c --- include/cutils/bitops.h | 68 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/include/cutils/bitops.h b/include/cutils/bitops.h index 1b3b762e6..6893985b8 100644 --- a/include/cutils/bitops.h +++ b/include/cutils/bitops.h @@ -17,10 +17,78 @@ #ifndef __CUTILS_BITOPS_H #define __CUTILS_BITOPS_H +#include +#include #include __BEGIN_DECLS +/* + * Bitmask Operations + * + * Note this doesn't provide any locking/exclusion, and isn't atomic. + * Additionally no bounds checking is done on the bitmask array. + * + * Example: + * + * int num_resources; + * unsigned int resource_bits[BITS_TO_WORDS(num_resources)]; + * bitmask_init(resource_bits, num_resources); + * ... + * int bit = bitmask_ffz(resource_bits, num_resources); + * bitmask_set(resource_bits, bit); + * ... + * if (bitmask_test(resource_bits, bit)) { ... } + * ... + * bitmask_clear(resource_bits, bit); + * + */ + +#define BITS_PER_WORD (sizeof(unsigned int) * 8) +#define BITS_TO_WORDS(x) (((x) + BITS_PER_WORD - 1) / BITS_PER_WORD) +#define BIT_IN_WORD(x) ((x) % BITS_PER_WORD) +#define BIT_WORD(x) ((x) / BITS_PER_WORD) +#define BIT_MASK(x) (1 << BIT_IN_WORD(x)) + +static inline void bitmask_init(unsigned int *bitmask, int num_bits) +{ + memset(bitmask, 0, BITS_TO_WORDS(num_bits)*sizeof(unsigned int)); +} + +static inline int bitmask_ffz(unsigned int *bitmask, int num_bits) +{ + int bit, result; + unsigned int i; + + for (i = 0; i < BITS_TO_WORDS(num_bits); i++) { + bit = ffs(~bitmask[i]); + if (bit) { + // ffs is 1-indexed, return 0-indexed result + bit--; + result = BITS_PER_WORD * i + bit; + if (result >= num_bits) + return -1; + return result; + } + } + return -1; +} + +static inline void bitmask_set(unsigned int *bitmask, int bit) +{ + bitmask[BIT_WORD(bit)] |= BIT_MASK(bit); +} + +static inline void bitmask_clear(unsigned int *bitmask, int bit) +{ + bitmask[BIT_WORD(bit)] &= ~BIT_MASK(bit); +} + +static inline bool bitmask_test(unsigned int *bitmask, int bit) +{ + return bitmask[BIT_WORD(bit)] & BIT_MASK(bit); +} + static inline int popcount(unsigned int x) { return __builtin_popcount(x); From 81ec96df4f83df9781368c6f2b8160ee1b177f75 Mon Sep 17 00:00:00 2001 From: Alex Ray Date: Mon, 7 Jan 2013 16:58:01 -0800 Subject: [PATCH 60/89] cutils: bitops: add include for bool Change-Id: I3eca5a7c1f5ec66ded1229ccb6ca1dbb5d608ffd --- include/cutils/bitops.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/cutils/bitops.h b/include/cutils/bitops.h index 6893985b8..eb44236f5 100644 --- a/include/cutils/bitops.h +++ b/include/cutils/bitops.h @@ -17,6 +17,7 @@ #ifndef __CUTILS_BITOPS_H #define __CUTILS_BITOPS_H +#include #include #include #include From 267aa8b00eadf273321e492026af74b7baad890e Mon Sep 17 00:00:00 2001 From: Ray Donnelly Date: Thu, 29 Nov 2012 01:18:50 +0000 Subject: [PATCH 61/89] Windows adb: Make client stdout and stderr handles uninheritable Change-Id: Ib0519a199c9504aad1d0ecc3757f4d162984bf22 --- adb/adb.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/adb/adb.c b/adb/adb.c index 07bfbe5d5..9871939c3 100644 --- a/adb/adb.c +++ b/adb/adb.c @@ -913,6 +913,7 @@ int launch_server(int server_port) /* message since the pipe handles must be inheritable, we use a */ /* security attribute */ HANDLE pipe_read, pipe_write; + HANDLE stdout_handle, stderr_handle; SECURITY_ATTRIBUTES sa; STARTUPINFO startup; PROCESS_INFORMATION pinfo; @@ -932,6 +933,26 @@ int launch_server(int server_port) SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 ); + /* Some programs want to launch an adb command and collect its output by + * calling CreateProcess with inheritable stdout/stderr handles, then + * using read() to get its output. When this happens, the stdout/stderr + * handles passed to the adb client process will also be inheritable. + * When starting the adb server here, care must be taken to reset them + * to non-inheritable. + * Otherwise, something bad happens: even if the adb command completes, + * the calling process is stuck while read()-ing from the stdout/stderr + * descriptors, because they're connected to corresponding handles in the + * adb server process (even if the latter never uses/writes to them). + */ + stdout_handle = GetStdHandle( STD_OUTPUT_HANDLE ); + stderr_handle = GetStdHandle( STD_ERROR_HANDLE ); + if (stdout_handle != INVALID_HANDLE_VALUE) { + SetHandleInformation( stdout_handle, HANDLE_FLAG_INHERIT, 0 ); + } + if (stderr_handle != INVALID_HANDLE_VALUE) { + SetHandleInformation( stderr_handle, HANDLE_FLAG_INHERIT, 0 ); + } + ZeroMemory( &startup, sizeof(startup) ); startup.cb = sizeof(startup); startup.hStdInput = GetStdHandle( STD_INPUT_HANDLE ); From cbb9891049628a2a89d566cade88c80ba1ba4a7b Mon Sep 17 00:00:00 2001 From: Ray Donnelly Date: Thu, 29 Nov 2012 01:36:08 +0000 Subject: [PATCH 62/89] Windows adb: include stdint.h for uint8_t on MinGW-w64 Change-Id: I84b8284bc034feb0acd313b0aad9e2fa5868854f --- adb/adb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/adb/adb.c b/adb/adb.c index 9871939c3..2f305434a 100644 --- a/adb/adb.c +++ b/adb/adb.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "sysdeps.h" #include "adb.h" From 571c1367682c83cb23481cc9c1028c8588a1fed0 Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Thu, 6 Dec 2012 18:18:12 -0800 Subject: [PATCH 63/89] adb: HACK: (linux only) allow temp mitigation for multithreaded issues There are serious multithreading issues between the fdevent and transport subsystems which both manipulate struct asocket and struct fde concurrently. The prevalent symptom being around multiple socket closures which stomp on each other, typically causing: "glibc detected *** adb: double free or corruption ..." This HACK allows forcing CPU affinity via an env var. E.g.: export ADB_CPU_AFFINITY_BUG6558362=0 which will cause ONLY the adb server and all its threads to be pegged to CPU 0. The result is visible in valgrind's helgrind: no *socket_close() related data races. But tons of other races are still there. Bug: 6558362 Change-Id: I0f112390a6a921c64b2a783297be9e99ce27fd56 --- adb/Android.mk | 1 + adb/adb.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/adb/Android.mk b/adb/Android.mk index d6b01463e..1fca6845d 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -17,6 +17,7 @@ ifeq ($(HOST_OS),linux) USB_SRCS := usb_linux.c EXTRA_SRCS := get_my_path_linux.c LOCAL_LDLIBS += -lrt -lncurses -lpthread + LOCAL_CFLAGS += -DWORKAROUND_BUG6558362 endif ifeq ($(HOST_OS),darwin) diff --git a/adb/adb.c b/adb/adb.c index 4c3364fe5..8be576567 100644 --- a/adb/adb.c +++ b/adb/adb.c @@ -983,6 +983,33 @@ void start_device_log(void) #endif #if ADB_HOST + +#ifdef WORKAROUND_BUG6558362 +#include +#define AFFINITY_ENVVAR "ADB_CPU_AFFINITY_BUG6558362" +void adb_set_affinity(void) +{ + cpu_set_t cpu_set; + const char* cpunum_str = getenv(AFFINITY_ENVVAR); + char* strtol_res; + int cpu_num; + + if (!cpunum_str || !*cpunum_str) + return; + cpu_num = strtol(cpunum_str, &strtol_res, 0); + if (*strtol_res != '\0') + fatal("bad number (%s) in env var %s. Expecting 0..n.\n", cpunum_str, AFFINITY_ENVVAR); + + sched_getaffinity(0, sizeof(cpu_set), &cpu_set); + D("orig cpu_set[0]=0x%08lx\n", cpu_set.__bits[0]); + CPU_ZERO(&cpu_set); + CPU_SET(cpu_num, &cpu_set); + sched_setaffinity(0, sizeof(cpu_set), &cpu_set); + sched_getaffinity(0, sizeof(cpu_set), &cpu_set); + D("new cpu_set[0]=0x%08lx\n", cpu_set.__bits[0]); +} +#endif + int launch_server(int server_port) { #ifdef HAVE_WIN32_PROC @@ -1186,6 +1213,10 @@ int adb_main(int is_daemon, int server_port) #if ADB_HOST HOST = 1; + +#ifdef WORKAROUND_BUG6558362 + if(is_daemon) adb_set_affinity(); +#endif usb_vendors_init(); usb_init(); local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT); From fdd573188d08fbd3739aeda19ef0f2d03752db9f Mon Sep 17 00:00:00 2001 From: Robert Greenwalt Date: Wed, 9 Jan 2013 16:22:12 -0800 Subject: [PATCH 64/89] Support 4 dns servers, up from 2 bug:5958524 Change-Id: I61c25e23d21e92653ec9b874d3d456a330d8fe05 --- include/netutils/dhcp.h | 11 +++++++++-- libnetutils/dhcp_utils.c | 26 ++++++++++++-------------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/include/netutils/dhcp.h b/include/netutils/dhcp.h index d25e58fa6..bd2c9571a 100644 --- a/include/netutils/dhcp.h +++ b/include/netutils/dhcp.h @@ -27,11 +27,18 @@ extern int dhcp_do_request(const char *ifname, char *ipaddr, char *gateway, uint32_t *prefixLength, - char *dns1, - char *dns2, + char *dns[], char *server, uint32_t *lease, char *vendorInfo); +extern int dhcp_do_request_renew(const char *ifname, + char *ipaddr, + char *gateway, + uint32_t *prefixLength, + char *dns[], + char *server, + uint32_t *lease, + char *vendorInfo); extern int dhcp_stop(const char *ifname); extern int dhcp_release_lease(const char *ifname); extern char *dhcp_get_errmsg(); diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c index a59de0d5a..2f5fdd39b 100644 --- a/libnetutils/dhcp_utils.c +++ b/libnetutils/dhcp_utils.c @@ -88,8 +88,7 @@ static int fill_ip_info(const char *interface, char *ipaddr, char *gateway, uint32_t *prefixLength, - char *dns1, - char *dns2, + char *dns[], char *server, uint32_t *lease, char *vendorInfo, @@ -99,6 +98,7 @@ static int fill_ip_info(const char *interface, char prop_value[PROPERTY_VALUE_MAX]; /* Interface name after converting p2p0-p2p0-X to p2p to reuse system properties */ char p2p_interface[MAX_INTERFACE_LENGTH]; + int x; get_p2p_interface_replacement(interface, p2p_interface); @@ -139,11 +139,11 @@ static int fill_ip_info(const char *interface, } *prefixLength = p; } - snprintf(prop_name, sizeof(prop_name), "%s.%s.dns1", DHCP_PROP_NAME_PREFIX, p2p_interface); - property_get(prop_name, dns1, NULL); - snprintf(prop_name, sizeof(prop_name), "%s.%s.dns2", DHCP_PROP_NAME_PREFIX, p2p_interface); - property_get(prop_name, dns2, NULL); + for (x=0; dns[x] != NULL; x++) { + snprintf(prop_name, sizeof(prop_name), "%s.%s.dns%d", DHCP_PROP_NAME_PREFIX, p2p_interface, x+1); + property_get(prop_name, dns[x], NULL); + } snprintf(prop_name, sizeof(prop_name), "%s.%s.leasetime", DHCP_PROP_NAME_PREFIX, p2p_interface); if (property_get(prop_name, prop_value, NULL)) { @@ -182,8 +182,7 @@ int dhcp_do_request(const char *interface, char *ipaddr, char *gateway, uint32_t *prefixLength, - char *dns1, - char *dns2, + char *dns[], char *server, uint32_t *lease, char *vendorInfo, @@ -238,8 +237,8 @@ int dhcp_do_request(const char *interface, } if (strcmp(prop_value, "ok") == 0) { char dns_prop_name[PROPERTY_KEY_MAX]; - if (fill_ip_info(interface, ipaddr, gateway, prefixLength, - dns1, dns2, server, lease, vendorInfo, domain) == -1) { + if (fill_ip_info(interface, ipaddr, gateway, prefixLength, dns, + server, lease, vendorInfo, domain) == -1) { return -1; } return 0; @@ -326,8 +325,7 @@ int dhcp_do_request_renew(const char *interface, char *ipaddr, char *gateway, uint32_t *prefixLength, - char *dns1, - char *dns2, + char *dns[], char *server, uint32_t *lease, char *vendorInfo, @@ -367,8 +365,8 @@ int dhcp_do_request_renew(const char *interface, return -1; } if (strcmp(prop_value, "ok") == 0) { - fill_ip_info(interface, ipaddr, gateway, prefixLength, - dns1, dns2, server, lease, vendorInfo, domain); + fill_ip_info(interface, ipaddr, gateway, prefixLength, dns, + server, lease, vendorInfo, domain); return 0; } else { snprintf(errmsg, sizeof(errmsg), "DHCP Renew result was %s", prop_value); From d874cc8bb9ed0f836495b5eabea44def6cffe9a8 Mon Sep 17 00:00:00 2001 From: Alex Ray Date: Wed, 9 Jan 2013 18:13:28 -0800 Subject: [PATCH 65/89] cutils: add simple reference counter Change-Id: Iefb34abc864cb4ca2da2f1c85c45f89af8c7fe8b --- include/cutils/aref.h | 62 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 include/cutils/aref.h diff --git a/include/cutils/aref.h b/include/cutils/aref.h new file mode 100644 index 000000000..460ac020b --- /dev/null +++ b/include/cutils/aref.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CUTILS_AREF_H_ +#define _CUTILS_AREF_H_ + +#include +#include + +#ifdef ANDROID_SMP +#include +#else +#include +#endif + +__BEGIN_DECLS + +#define AREF_TO_ITEM(aref, container, member) \ + (container *) (((char*) (aref)) - offsetof(container, member)) + +struct aref +{ + volatile int32_t count; +}; + +static inline void aref_init(struct aref *r) +{ + r->count = 1; +} + +static inline int32_t aref_count(struct aref *r) +{ + return r->count; +} + +static inline void aref_get(struct aref *r) +{ + android_atomic_inc(&r->count); +} + +static inline void aref_put(struct aref *r, void (*release)(struct aref *)) +{ + if (android_atomic_dec(&r->count) == 1) + release(r); +} + +__END_DECLS + +#endif // _CUTILS_AREF_H_ From bbe26c1f79bf860dde9cfbe8cd4ad826cd1a8a53 Mon Sep 17 00:00:00 2001 From: Ray Donnelly Date: Fri, 11 Jan 2013 16:36:00 +0000 Subject: [PATCH 66/89] Windows adb: initialize on to 1 in disable_tcp_nagle --- adb/sysdeps_win32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adb/sysdeps_win32.c b/adb/sysdeps_win32.c index d41c42c09..2105b1687 100644 --- a/adb/sysdeps_win32.c +++ b/adb/sysdeps_win32.c @@ -781,7 +781,7 @@ int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrle void disable_tcp_nagle(int fd) { FH fh = _fh_from_int(fd); - int on; + int on = 1; if ( !fh || fh->clazz != &_fh_socket_class ) return; From 113bd47d619fa36eb5017cbf2c1b6fe677715ed0 Mon Sep 17 00:00:00 2001 From: Rom Lemarchand Date: Thu, 10 Jan 2013 15:21:18 -0800 Subject: [PATCH 67/89] logwrapper: split into liblogwrap and the executable itself Abstracting the functionality of logwrapper into a library and making use of it for the logwrapper executable. Change-Id: I2bcf722413f3a8454c6f52137dec86c4477fb8b5 --- logwrapper/Android.mk | 29 ++++- logwrapper/include/logwrap/logwrap.h | 27 +++++ logwrapper/logwrap.c | 161 +++++++++++++++++++++++++++ logwrapper/logwrapper.c | 139 +++-------------------- 4 files changed, 230 insertions(+), 126 deletions(-) create mode 100644 logwrapper/include/logwrap/logwrap.h create mode 100644 logwrapper/logwrap.c diff --git a/logwrapper/Android.mk b/logwrapper/Android.mk index 5fd635676..b4b6b2986 100644 --- a/logwrapper/Android.mk +++ b/logwrapper/Android.mk @@ -1,7 +1,34 @@ LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +# ======================================================== +# Static library +# ======================================================== +include $(CLEAR_VARS) +LOCAL_MODULE := liblogwrap +LOCAL_SRC_FILES := logwrap.c +LOCAL_SHARED_LIBRARIES := libcutils liblog +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include +include $(BUILD_STATIC_LIBRARY) + +# ======================================================== +# Shared library +# ======================================================== +include $(CLEAR_VARS) +LOCAL_MODULE := liblogwrap +LOCAL_SHARED_LIBRARIES := libcutils liblog +LOCAL_WHOLE_STATIC_LIBRARIES := liblogwrap +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include +include $(BUILD_SHARED_LIBRARY) + +# ======================================================== +# Executable +# ======================================================== include $(CLEAR_VARS) LOCAL_SRC_FILES:= logwrapper.c LOCAL_MODULE := logwrapper -LOCAL_STATIC_LIBRARIES := liblog +LOCAL_STATIC_LIBRARIES := liblog liblogwrap include $(BUILD_EXECUTABLE) diff --git a/logwrapper/include/logwrap/logwrap.h b/logwrapper/include/logwrap/logwrap.h new file mode 100644 index 000000000..a58f23820 --- /dev/null +++ b/logwrapper/include/logwrap/logwrap.h @@ -0,0 +1,27 @@ +/* system/core/include/logwrap/logwrap.h + * + * Copyright 2013, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LIBS_LOGWRAP_H +#define __LIBS_LOGWRAP_H + +__BEGIN_DECLS + +int logwrap(int argc, char* argv[], int *chld_sts); + +__END_DECLS + +#endif /* __LIBS_LOGWRAP_H */ diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c new file mode 100644 index 000000000..302a739dd --- /dev/null +++ b/logwrapper/logwrap.c @@ -0,0 +1,161 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "private/android_filesystem_config.h" +#include "cutils/log.h" + +static int fatal(const char *msg) { + fprintf(stderr, "%s", msg); + ALOG(LOG_ERROR, "logwrapper", "%s", msg); + return -1; +} + +void parent(const char *tag, int parent_read, int *chld_sts) { + int status; + char buffer[4096]; + + int a = 0; // start index of unprocessed data + int b = 0; // end index of unprocessed data + int sz; + + char *btag = basename(tag); + if (!btag) btag = (char*) tag; + + while ((sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b)) > 0) { + + sz += b; + // Log one line at a time + for (b = 0; b < sz; b++) { + if (buffer[b] == '\r') { + buffer[b] = '\0'; + } else if (buffer[b] == '\n') { + buffer[b] = '\0'; + ALOG(LOG_INFO, btag, "%s", &buffer[a]); + a = b + 1; + } + } + + if (a == 0 && b == sizeof(buffer) - 1) { + // buffer is full, flush + buffer[b] = '\0'; + ALOG(LOG_INFO, btag, "%s", &buffer[a]); + b = 0; + } else if (a != b) { + // Keep left-overs + b -= a; + memmove(buffer, &buffer[a], b); + a = 0; + } else { + a = 0; + b = 0; + } + + } + // Flush remaining data + if (a != b) { + buffer[b] = '\0'; + ALOG(LOG_INFO, btag, "%s", &buffer[a]); + } + + if (wait(&status) != -1) { // Wait for child + if (WIFEXITED(status) && WEXITSTATUS(status)) + ALOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", tag, + WEXITSTATUS(status)); + else if (WIFSIGNALED(status)) + ALOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag, + WTERMSIG(status)); + else if (WIFSTOPPED(status)) + ALOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag, + WSTOPSIG(status)); + if (chld_sts != NULL) + *chld_sts = status; + } else + ALOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag, + strerror(errno), errno); +} + +void child(int argc, char* argv[]) { + // create null terminated argv_child array + char* argv_child[argc + 1]; + memcpy(argv_child, argv, argc * sizeof(char *)); + argv_child[argc] = NULL; + + if (execvp(argv_child[0], argv_child)) { + ALOG(LOG_ERROR, "logwrapper", + "executing %s failed: %s\n", argv_child[0], strerror(errno)); + exit(-1); + } +} + +int logwrap(int argc, char* argv[], int *chld_sts) { + pid_t pid; + + int parent_ptty; + int child_ptty; + char *child_devname = NULL; + + /* Use ptty instead of socketpair so that STDOUT is not buffered */ + parent_ptty = open("/dev/ptmx", O_RDWR); + if (parent_ptty < 0) { + return fatal("Cannot create parent ptty\n"); + } + + if (grantpt(parent_ptty) || unlockpt(parent_ptty) || + ((child_devname = (char*)ptsname(parent_ptty)) == 0)) { + return fatal("Problem with /dev/ptmx\n"); + } + + pid = fork(); + if (pid < 0) { + close(parent_ptty); + return fatal("Failed to fork\n"); + } else if (pid == 0) { + child_ptty = open(child_devname, O_RDWR); + close(parent_ptty); + if (child_ptty < 0) { + return fatal("Problem with child ptty\n"); + } + + // redirect stdout and stderr + dup2(child_ptty, 1); + dup2(child_ptty, 2); + close(child_ptty); + + child(argc - 1, &argv[1]); + + } else { + // switch user and group to "log" + // this may fail if we are not root, + // but in that case switching user/group is unnecessary + setgid(AID_LOG); + setuid(AID_LOG); + + parent(argv[1], parent_ptty, chld_sts); + } + + return 0; +} diff --git a/logwrapper/logwrapper.c b/logwrapper/logwrapper.c index dd777c032..4f1bff9d4 100644 --- a/logwrapper/logwrapper.c +++ b/logwrapper/logwrapper.c @@ -14,17 +14,12 @@ * limitations under the License. */ -#include -#include -#include #include #include -#include -#include -#include -#include +#include + +#include -#include "private/android_filesystem_config.h" #include "cutils/log.h" void fatal(const char *msg) { @@ -45,90 +40,10 @@ void usage() { " fault address is set to the status of wait()\n"); } -void parent(const char *tag, int seg_fault_on_exit, int parent_read) { - int status; - char buffer[4096]; - - int a = 0; // start index of unprocessed data - int b = 0; // end index of unprocessed data - int sz; - - char *btag = basename(tag); - if (!btag) btag = (char*) tag; - - while ((sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b)) > 0) { - - sz += b; - // Log one line at a time - for (b = 0; b < sz; b++) { - if (buffer[b] == '\r') { - buffer[b] = '\0'; - } else if (buffer[b] == '\n') { - buffer[b] = '\0'; - ALOG(LOG_INFO, btag, "%s", &buffer[a]); - a = b + 1; - } - } - - if (a == 0 && b == sizeof(buffer) - 1) { - // buffer is full, flush - buffer[b] = '\0'; - ALOG(LOG_INFO, btag, "%s", &buffer[a]); - b = 0; - } else if (a != b) { - // Keep left-overs - b -= a; - memmove(buffer, &buffer[a], b); - a = 0; - } else { - a = 0; - b = 0; - } - - } - // Flush remaining data - if (a != b) { - buffer[b] = '\0'; - ALOG(LOG_INFO, btag, "%s", &buffer[a]); - } - status = 0xAAAA; - if (wait(&status) != -1) { // Wait for child - if (WIFEXITED(status) && WEXITSTATUS(status)) - ALOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", tag, - WEXITSTATUS(status)); - else if (WIFSIGNALED(status)) - ALOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag, - WTERMSIG(status)); - else if (WIFSTOPPED(status)) - ALOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag, - WSTOPSIG(status)); - } else - ALOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag, - strerror(errno), errno); - if (seg_fault_on_exit) - *(int *)status = 0; // causes SIGSEGV with fault_address = status -} - -void child(int argc, char* argv[]) { - // create null terminated argv_child array - char* argv_child[argc + 1]; - memcpy(argv_child, argv, argc * sizeof(char *)); - argv_child[argc] = NULL; - - if (execvp(argv_child[0], argv_child)) { - ALOG(LOG_ERROR, "logwrapper", - "executing %s failed: %s\n", argv_child[0], strerror(errno)); - exit(-1); - } -} - int main(int argc, char* argv[]) { - pid_t pid; int seg_fault_on_exit = 0; - - int parent_ptty; - int child_ptty; - char *child_devname = NULL; + int status = 0xAAAA; + int rc; if (argc < 2) { usage(); @@ -144,43 +59,17 @@ int main(int argc, char* argv[]) { usage(); } - /* Use ptty instead of socketpair so that STDOUT is not buffered */ - parent_ptty = open("/dev/ptmx", O_RDWR); - if (parent_ptty < 0) { - fatal("Cannot create parent ptty\n"); + rc = logwrap(argc, argv, &status); + if (!rc) { + if (WIFEXITED(status)) + rc = WEXITSTATUS(status); + else + rc = -ECHILD; } - if (grantpt(parent_ptty) || unlockpt(parent_ptty) || - ((child_devname = (char*)ptsname(parent_ptty)) == 0)) { - fatal("Problem with /dev/ptmx\n"); + if (seg_fault_on_exit) { + *(int *)status = 0; // causes SIGSEGV with fault_address = status } - pid = fork(); - if (pid < 0) { - fatal("Failed to fork\n"); - } else if (pid == 0) { - child_ptty = open(child_devname, O_RDWR); - if (child_ptty < 0) { - fatal("Problem with child ptty\n"); - } - - // redirect stdout and stderr - close(parent_ptty); - dup2(child_ptty, 1); - dup2(child_ptty, 2); - close(child_ptty); - - child(argc - 1, &argv[1]); - - } else { - // switch user and group to "log" - // this may fail if we are not root, - // but in that case switching user/group is unnecessary - setgid(AID_LOG); - setuid(AID_LOG); - - parent(argv[1], seg_fault_on_exit, parent_ptty); - } - - return 0; + return rc; } From b58a82295529e775fbb900ecfb2d9104b2dafdc1 Mon Sep 17 00:00:00 2001 From: Rom Lemarchand Date: Wed, 9 Jan 2013 21:31:25 -0800 Subject: [PATCH 68/89] logwrapper: prevent logwrap from hanging when child dies Sometimes the read on the PTY can wait indefinitely if the child dies. By using a poll statement that monitors both the output of the child and its state we prevent this from happening. Change-Id: I51d5556c66f039bca673145ca72db262977e1689 --- logwrapper/include/logwrap/logwrap.h | 24 ++++- logwrapper/logwrap.c | 152 +++++++++++++++++++-------- 2 files changed, 131 insertions(+), 45 deletions(-) diff --git a/logwrapper/include/logwrap/logwrap.h b/logwrapper/include/logwrap/logwrap.h index a58f23820..722dda2ac 100644 --- a/logwrapper/include/logwrap/logwrap.h +++ b/logwrapper/include/logwrap/logwrap.h @@ -20,7 +20,29 @@ __BEGIN_DECLS -int logwrap(int argc, char* argv[], int *chld_sts); +/* + * Run a command while logging its stdout and stderr + * + * WARNING: while this function is running it will clear all SIGCHLD handlers + * if you rely on SIGCHLD in the caller there is a chance zombies will be + * created if you're not calling waitpid after calling this. This function will + * log a warning when it clears SIGCHLD for processes other than the child it + * created. + * + * Arguments: + * argc: the number of elements in argv + * argv: an array of strings containing the command to be executed and its + * arguments as separate strings. argv does not need to be + * NULL-terminated + * status: the equivalent child status as populated by wait(status). This + * value is only valid when logwrap successfully completes + * + * Return value: + * 0 when logwrap successfully run the child process and captured its status + * -1 when an internal error occurred + * + */ +int logwrap(int argc, char* argv[], int *status); __END_DECLS diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c index 302a739dd..c2b36be29 100644 --- a/logwrapper/logwrap.c +++ b/logwrapper/logwrap.c @@ -16,6 +16,9 @@ #include #include +#include +#include +#include #include #include #include @@ -28,15 +31,28 @@ #include "private/android_filesystem_config.h" #include "cutils/log.h" +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) + static int fatal(const char *msg) { fprintf(stderr, "%s", msg); ALOG(LOG_ERROR, "logwrapper", "%s", msg); return -1; } -void parent(const char *tag, int parent_read, int *chld_sts) { +static int parent(const char *tag, int parent_read, int signal_fd, pid_t pid, + int *chld_sts) { int status; char buffer[4096]; + struct pollfd poll_fds[] = { + [0] = { + .fd = parent_read, + .events = POLLIN, + }, + [1] = { + .fd = signal_fd, + .events = POLLIN, + }, + }; int a = 0; // start index of unprocessed data int b = 0; // end index of unprocessed data @@ -45,60 +61,82 @@ void parent(const char *tag, int parent_read, int *chld_sts) { char *btag = basename(tag); if (!btag) btag = (char*) tag; - while ((sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b)) > 0) { + while (1) { + if (poll(poll_fds, ARRAY_SIZE(poll_fds), -1) <= 0) { + return fatal("poll failed\n"); + } - sz += b; - // Log one line at a time - for (b = 0; b < sz; b++) { - if (buffer[b] == '\r') { - buffer[b] = '\0'; - } else if (buffer[b] == '\n') { + if (poll_fds[0].revents & POLLIN) { + sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b); + + sz += b; + // Log one line at a time + for (b = 0; b < sz; b++) { + if (buffer[b] == '\r') { + buffer[b] = '\0'; + } else if (buffer[b] == '\n') { + buffer[b] = '\0'; + ALOG(LOG_INFO, btag, "%s", &buffer[a]); + a = b + 1; + } + } + + if (a == 0 && b == sizeof(buffer) - 1) { + // buffer is full, flush buffer[b] = '\0'; ALOG(LOG_INFO, btag, "%s", &buffer[a]); - a = b + 1; + b = 0; + } else if (a != b) { + // Keep left-overs + b -= a; + memmove(buffer, &buffer[a], b); + a = 0; + } else { + a = 0; + b = 0; } } - if (a == 0 && b == sizeof(buffer) - 1) { - // buffer is full, flush - buffer[b] = '\0'; - ALOG(LOG_INFO, btag, "%s", &buffer[a]); - b = 0; - } else if (a != b) { - // Keep left-overs - b -= a; - memmove(buffer, &buffer[a], b); - a = 0; - } else { - a = 0; - b = 0; - } + if (poll_fds[1].revents & POLLIN) { + struct signalfd_siginfo sfd_info; + pid_t wpid; + // Clear all pending signals before reading the child's status + while (read(signal_fd, &sfd_info, sizeof(sfd_info)) > 0) { + if ((pid_t)sfd_info.ssi_pid != pid) + ALOG(LOG_WARN, "logwrapper", "cleared SIGCHLD for pid %u\n", + sfd_info.ssi_pid); + } + wpid = waitpid(pid, &status, WNOHANG); + if (wpid > 0) + break; + } } + // Flush remaining data if (a != b) { buffer[b] = '\0'; ALOG(LOG_INFO, btag, "%s", &buffer[a]); } - if (wait(&status) != -1) { // Wait for child - if (WIFEXITED(status) && WEXITSTATUS(status)) + if (WIFEXITED(status)) { + if (WEXITSTATUS(status)) ALOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", tag, WEXITSTATUS(status)); - else if (WIFSIGNALED(status)) - ALOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag, - WTERMSIG(status)); - else if (WIFSTOPPED(status)) - ALOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag, - WSTOPSIG(status)); - if (chld_sts != NULL) - *chld_sts = status; - } else - ALOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag, - strerror(errno), errno); + } else if (WIFSIGNALED(status)) { + ALOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag, + WTERMSIG(status)); + } else if (WIFSTOPPED(status)) { + ALOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag, + WSTOPSIG(status)); + } + if (chld_sts != NULL) + *chld_sts = status; + + return 0; } -void child(int argc, char* argv[]) { +static void child(int argc, char* argv[]) { // create null terminated argv_child array char* argv_child[argc + 1]; memcpy(argv_child, argv, argc * sizeof(char *)); @@ -111,12 +149,13 @@ void child(int argc, char* argv[]) { } } -int logwrap(int argc, char* argv[], int *chld_sts) { +int logwrap(int argc, char* argv[], int *status) { pid_t pid; int parent_ptty; int child_ptty; char *child_devname = NULL; + sigset_t chldset; /* Use ptty instead of socketpair so that STDOUT is not buffered */ parent_ptty = open("/dev/ptmx", O_RDWR); @@ -129,13 +168,19 @@ int logwrap(int argc, char* argv[], int *chld_sts) { return fatal("Problem with /dev/ptmx\n"); } + sigemptyset(&chldset); + sigaddset(&chldset, SIGCHLD); + sigprocmask(SIG_BLOCK, &chldset, NULL); + pid = fork(); if (pid < 0) { close(parent_ptty); + sigprocmask(SIG_UNBLOCK, &chldset, NULL); return fatal("Failed to fork\n"); } else if (pid == 0) { - child_ptty = open(child_devname, O_RDWR); close(parent_ptty); + sigprocmask(SIG_UNBLOCK, &chldset, NULL); + child_ptty = open(child_devname, O_RDWR); if (child_ptty < 0) { return fatal("Problem with child ptty\n"); } @@ -146,16 +191,35 @@ int logwrap(int argc, char* argv[], int *chld_sts) { close(child_ptty); child(argc - 1, &argv[1]); + return fatal("This should never happen\n"); } else { + int rc; + int fd; + + fd = signalfd(-1, &chldset, SFD_NONBLOCK); + if (fd == -1) { + char msg[40]; + + snprintf(msg, sizeof(msg), "signalfd failed: %d\n", errno); + + close(parent_ptty); + sigprocmask(SIG_UNBLOCK, &chldset, NULL); + return fatal(msg); + } + // switch user and group to "log" - // this may fail if we are not root, - // but in that case switching user/group is unnecessary + // this may fail if we are not root, + // but in that case switching user/group is unnecessary setgid(AID_LOG); setuid(AID_LOG); - parent(argv[1], parent_ptty, chld_sts); - } + rc = parent(argv[1], parent_ptty, fd, pid, status); + close(parent_ptty); + close(fd); - return 0; + sigprocmask(SIG_UNBLOCK, &chldset, NULL); + + return rc; + } } From def8d6a706ee173de419000fccb3daf8b24117ec Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 11 Sep 2012 11:18:38 -0700 Subject: [PATCH 69/89] The localtime_tz and mktime_tz extensions are now in bionic. (cherry-pick of d03072ffde3279fbb60591a0d07c820d8e792762. This change was originally committed to AOSP, is in internal master, but was somehow lost from AOSP.) Bug: 7012465 Conflicts: libcutils/Android.mk Change-Id: I08ee8eb9b8ce5d3f9d8f2e67437d653e08697bc1 --- include/cutils/tztime.h | 39 +- libcutils/Android.mk | 4 - libcutils/private.h | 368 -------- libcutils/tzfile.h | 180 ---- libcutils/tzstrftime.c | 842 ----------------- libcutils/tztime.c | 1950 --------------------------------------- 6 files changed, 1 insertion(+), 3382 deletions(-) delete mode 100644 libcutils/private.h delete mode 100644 libcutils/tzfile.h delete mode 100644 libcutils/tzstrftime.c delete mode 100644 libcutils/tztime.c diff --git a/include/cutils/tztime.h b/include/cutils/tztime.h index 36ac25d89..dbdbd60bc 100644 --- a/include/cutils/tztime.h +++ b/include/cutils/tztime.h @@ -17,45 +17,8 @@ #ifndef _CUTILS_TZTIME_H #define _CUTILS_TZTIME_H -#include - -#ifdef __cplusplus -extern "C" { -#endif - -time_t mktime_tz(struct tm * const tmp, char const * tz); -void localtime_tz(const time_t * const timep, struct tm * tmp, const char* tz); - -#ifdef HAVE_ANDROID_OS - -/* the following is defined in the Bionic C library on Android, but the - * declarations are only available through a platform-private header - */ +// TODO: fix both callers to just include themselves. #include -#else /* !HAVE_ANDROID_OS */ - -struct strftime_locale { - const char *mon[12]; /* short names */ - const char *month[12]; /* long names */ - const char *standalone_month[12]; /* long standalone names */ - const char *wday[7]; /* short names */ - const char *weekday[7]; /* long names */ - const char *X_fmt; - const char *x_fmt; - const char *c_fmt; - const char *am; - const char *pm; - const char *date_fmt; -}; - -size_t strftime_tz(char *s, size_t max, const char *format, const struct tm *tm, const struct strftime_locale *locale); - -#endif /* !HAVE_ANDROID_OS */ - -#ifdef __cplusplus -} -#endif - #endif /* __CUTILS_TZTIME_H */ diff --git a/libcutils/Android.mk b/libcutils/Android.mk index d9bd8d83f..fc6d08de3 100644 --- a/libcutils/Android.mk +++ b/libcutils/Android.mk @@ -77,12 +77,8 @@ else abort_socket.c \ fs.c \ selector.c \ - tztime.c \ multiuser.c \ zygote.c - - commonHostSources += \ - tzstrftime.c endif diff --git a/libcutils/private.h b/libcutils/private.h deleted file mode 100644 index 2837b70c1..000000000 --- a/libcutils/private.h +++ /dev/null @@ -1,368 +0,0 @@ -#ifndef PRIVATE_H - -#define PRIVATE_H - -/* -** This file is in the public domain, so clarified as of -** 1996-06-05 by Arthur David Olson. -*/ - -/* -** This header is for use ONLY with the time conversion code. -** There is no guarantee that it will remain unchanged, -** or that it will remain at all. -** Do NOT copy it to any system include directory. -** Thank you! -*/ - -/* -** ID -*/ - -#ifndef lint -#ifndef NOID -static char privatehid[] = "@(#)private.h 8.2"; -#endif /* !defined NOID */ -#endif /* !defined lint */ - -#define GRANDPARENTED "Local time zone must be set--see zic manual page" - -/* -** Defaults for preprocessor symbols. -** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'. -*/ - -#ifndef HAVE_ADJTIME -#define HAVE_ADJTIME 1 -#endif /* !defined HAVE_ADJTIME */ - -#ifndef HAVE_GETTEXT -#define HAVE_GETTEXT 0 -#endif /* !defined HAVE_GETTEXT */ - -#ifndef HAVE_INCOMPATIBLE_CTIME_R -#define HAVE_INCOMPATIBLE_CTIME_R 0 -#endif /* !defined INCOMPATIBLE_CTIME_R */ - -#ifndef HAVE_SETTIMEOFDAY -#define HAVE_SETTIMEOFDAY 3 -#endif /* !defined HAVE_SETTIMEOFDAY */ - -#ifndef HAVE_STRERROR -#define HAVE_STRERROR 1 -#endif /* !defined HAVE_STRERROR */ - -#ifndef HAVE_SYMLINK -#define HAVE_SYMLINK 1 -#endif /* !defined HAVE_SYMLINK */ - -#ifndef HAVE_SYS_STAT_H -#define HAVE_SYS_STAT_H 1 -#endif /* !defined HAVE_SYS_STAT_H */ - -#ifndef HAVE_SYS_WAIT_H -#define HAVE_SYS_WAIT_H 1 -#endif /* !defined HAVE_SYS_WAIT_H */ - -#ifndef HAVE_UNISTD_H -#define HAVE_UNISTD_H 1 -#endif /* !defined HAVE_UNISTD_H */ - -#ifndef HAVE_UTMPX_H -#define HAVE_UTMPX_H 0 -#endif /* !defined HAVE_UTMPX_H */ - -#ifndef LOCALE_HOME -#define LOCALE_HOME "/usr/lib/locale" -#endif /* !defined LOCALE_HOME */ - -#if HAVE_INCOMPATIBLE_CTIME_R -#define asctime_r _incompatible_asctime_r -#define ctime_r _incompatible_ctime_r -#endif /* HAVE_INCOMPATIBLE_CTIME_R */ - -/* -** Nested includes -*/ - -#include "sys/types.h" /* for time_t */ -#include "stdio.h" -#include "errno.h" -#include "string.h" -#include "limits.h" /* for CHAR_BIT et al. */ -#include "time.h" -#include "stdlib.h" - -#if HAVE_GETTEXT -#include "libintl.h" -#endif /* HAVE_GETTEXT */ - -#if HAVE_SYS_WAIT_H -#include /* for WIFEXITED and WEXITSTATUS */ -#endif /* HAVE_SYS_WAIT_H */ - -#ifndef WIFEXITED -#define WIFEXITED(status) (((status) & 0xff) == 0) -#endif /* !defined WIFEXITED */ -#ifndef WEXITSTATUS -#define WEXITSTATUS(status) (((status) >> 8) & 0xff) -#endif /* !defined WEXITSTATUS */ - -#if HAVE_UNISTD_H -#include "unistd.h" /* for F_OK and R_OK */ -#endif /* HAVE_UNISTD_H */ - -#if !HAVE_UNISTD_H -#ifndef F_OK -#define F_OK 0 -#endif /* !defined F_OK */ -#ifndef R_OK -#define R_OK 4 -#endif /* !defined R_OK */ -#endif /* !HAVE_UNISTD_H */ - -/* Unlike 's isdigit, this also works if c < 0 | c > UCHAR_MAX. */ -#define is_digit(c) ((unsigned)(c) - '0' <= 9) - -/* -** Define HAVE_STDINT_H's default value here, rather than at the -** start, since __GLIBC__'s value depends on previously-included -** files. -** (glibc 2.1 and later have stdint.h, even with pre-C99 compilers.) -*/ -#ifndef HAVE_STDINT_H -#define HAVE_STDINT_H \ - (199901 <= __STDC_VERSION__ || \ - 2 < (__GLIBC__ + (0 < __GLIBC_MINOR__))) -#endif /* !defined HAVE_STDINT_H */ - -#if HAVE_STDINT_H -#include "stdint.h" -#endif /* !HAVE_STDINT_H */ - -#ifndef INT_FAST64_MAX -/* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */ -#if defined LLONG_MAX || defined __LONG_LONG_MAX__ -typedef long long int_fast64_t; -#else /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */ -#if (LONG_MAX >> 31) < 0xffffffff -Please use a compiler that supports a 64-bit integer type (or wider); -you may need to compile with "-DHAVE_STDINT_H". -#endif /* (LONG_MAX >> 31) < 0xffffffff */ -typedef long int_fast64_t; -#endif /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */ -#endif /* !defined INT_FAST64_MAX */ - -#ifndef INT32_MAX -#define INT32_MAX 0x7fffffff -#endif /* !defined INT32_MAX */ -#ifndef INT32_MIN -#define INT32_MIN (-1 - INT32_MAX) -#endif /* !defined INT32_MIN */ - -/* -** Workarounds for compilers/systems. -*/ - -/* -** If your compiler lacks prototypes, "#define P(x) ()". -*/ - -#ifndef P -#define P(x) x -#endif /* !defined P */ - -/* -** SunOS 4.1.1 headers lack EXIT_SUCCESS. -*/ - -#ifndef EXIT_SUCCESS -#define EXIT_SUCCESS 0 -#endif /* !defined EXIT_SUCCESS */ - -/* -** SunOS 4.1.1 headers lack EXIT_FAILURE. -*/ - -#ifndef EXIT_FAILURE -#define EXIT_FAILURE 1 -#endif /* !defined EXIT_FAILURE */ - -/* -** SunOS 4.1.1 headers lack FILENAME_MAX. -*/ - -#ifndef FILENAME_MAX - -#ifndef MAXPATHLEN -#ifdef unix -#include "sys/param.h" -#endif /* defined unix */ -#endif /* !defined MAXPATHLEN */ - -#ifdef MAXPATHLEN -#define FILENAME_MAX MAXPATHLEN -#endif /* defined MAXPATHLEN */ -#ifndef MAXPATHLEN -#define FILENAME_MAX 1024 /* Pure guesswork */ -#endif /* !defined MAXPATHLEN */ - -#endif /* !defined FILENAME_MAX */ - -/* -** SunOS 4.1.1 libraries lack remove. -*/ - -#ifndef remove -extern int unlink P((const char * filename)); -#define remove unlink -#endif /* !defined remove */ - -/* -** Some ancient errno.h implementations don't declare errno. -** But some newer errno.h implementations define it as a macro. -** Fix the former without affecting the latter. -*/ - -#ifndef errno -extern int errno; -#endif /* !defined errno */ - -/* -** Some time.h implementations don't declare asctime_r. -** Others might define it as a macro. -** Fix the former without affecting the latter. -*/ - -#ifndef asctime_r -extern char * asctime_r(); -#endif - -/* -** Private function declarations. -*/ - -char * icalloc P((int nelem, int elsize)); -char * icatalloc P((char * old, const char * new)); -char * icpyalloc P((const char * string)); -char * imalloc P((int n)); -void * irealloc P((void * pointer, int size)); -void icfree P((char * pointer)); -void ifree P((char * pointer)); -const char * scheck P((const char * string, const char * format)); - -/* -** Finally, some convenience items. -*/ - -#ifndef TRUE -#define TRUE 1 -#endif /* !defined TRUE */ - -#ifndef FALSE -#define FALSE 0 -#endif /* !defined FALSE */ - -#ifndef TYPE_BIT -#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT) -#endif /* !defined TYPE_BIT */ - -#ifndef TYPE_SIGNED -#define TYPE_SIGNED(type) (((type) -1) < 0) -#endif /* !defined TYPE_SIGNED */ - -/* -** Since the definition of TYPE_INTEGRAL contains floating point numbers, -** it cannot be used in preprocessor directives. -*/ - -#ifndef TYPE_INTEGRAL -#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5) -#endif /* !defined TYPE_INTEGRAL */ - -#ifndef INT_STRLEN_MAXIMUM -/* -** 302 / 1000 is log10(2.0) rounded up. -** Subtract one for the sign bit if the type is signed; -** add one for integer division truncation; -** add one more for a minus sign if the type is signed. -*/ -#define INT_STRLEN_MAXIMUM(type) \ - ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \ - 1 + TYPE_SIGNED(type)) -#endif /* !defined INT_STRLEN_MAXIMUM */ - -/* -** INITIALIZE(x) -*/ - -#ifndef GNUC_or_lint -#ifdef lint -#define GNUC_or_lint -#endif /* defined lint */ -#ifndef lint -#ifdef __GNUC__ -#define GNUC_or_lint -#endif /* defined __GNUC__ */ -#endif /* !defined lint */ -#endif /* !defined GNUC_or_lint */ - -#ifndef INITIALIZE -#ifdef GNUC_or_lint -#define INITIALIZE(x) ((x) = 0) -#endif /* defined GNUC_or_lint */ -#ifndef GNUC_or_lint -#define INITIALIZE(x) -#endif /* !defined GNUC_or_lint */ -#endif /* !defined INITIALIZE */ - -/* -** For the benefit of GNU folk... -** `_(MSGID)' uses the current locale's message library string for MSGID. -** The default is to use gettext if available, and use MSGID otherwise. -*/ - -#ifndef _ -#if HAVE_GETTEXT -#define _(msgid) gettext(msgid) -#else /* !HAVE_GETTEXT */ -#define _(msgid) msgid -#endif /* !HAVE_GETTEXT */ -#endif /* !defined _ */ - -#ifndef TZ_DOMAIN -#define TZ_DOMAIN "tz" -#endif /* !defined TZ_DOMAIN */ - -#if HAVE_INCOMPATIBLE_CTIME_R -#undef asctime_r -#undef ctime_r -char *asctime_r P((struct tm const *, char *)); -char *ctime_r P((time_t const *, char *)); -#endif /* HAVE_INCOMPATIBLE_CTIME_R */ - -#ifndef YEARSPERREPEAT -#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */ -#endif /* !defined YEARSPERREPEAT */ - -/* -** The Gregorian year averages 365.2425 days, which is 31556952 seconds. -*/ - -#ifndef AVGSECSPERYEAR -#define AVGSECSPERYEAR 31556952L -#endif /* !defined AVGSECSPERYEAR */ - -#ifndef SECSPERREPEAT -#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR) -#endif /* !defined SECSPERREPEAT */ - -#ifndef SECSPERREPEAT_BITS -#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */ -#endif /* !defined SECSPERREPEAT_BITS */ - -/* -** UNIX was a registered trademark of The Open Group in 2003. -*/ - -#endif /* !defined PRIVATE_H */ diff --git a/libcutils/tzfile.h b/libcutils/tzfile.h deleted file mode 100644 index 8c7037558..000000000 --- a/libcutils/tzfile.h +++ /dev/null @@ -1,180 +0,0 @@ -#ifndef TZFILE_H - -#define TZFILE_H - -/* -** This file is in the public domain, so clarified as of -** 1996-06-05 by Arthur David Olson. -*/ - -/* -** This header is for use ONLY with the time conversion code. -** There is no guarantee that it will remain unchanged, -** or that it will remain at all. -** Do NOT copy it to any system include directory. -** Thank you! -*/ - -/* -** ID -*/ - -#ifndef lint -#ifndef NOID -static char tzfilehid[] = "@(#)tzfile.h 8.1"; -#endif /* !defined NOID */ -#endif /* !defined lint */ - -/* -** Information about time zone files. -*/ - -#ifndef TZDIR -#define TZDIR "/usr/share/zoneinfo" /* "/android/usr/share/zoneinfo" */ /* Time zone object file directory */ -#endif /* !defined TZDIR */ - -#ifndef TZDEFAULT -#define TZDEFAULT "localtime" -#endif /* !defined TZDEFAULT */ - -#ifndef TZDEFRULES -#define TZDEFRULES "posixrules" -#endif /* !defined TZDEFRULES */ - -/* -** Each file begins with. . . -*/ - -#define TZ_MAGIC "TZif" - -struct tzhead { - char tzh_magic[4]; /* TZ_MAGIC */ - char tzh_version[1]; /* '\0' or '2' as of 2005 */ - char tzh_reserved[15]; /* reserved--must be zero */ - char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */ - char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ - char tzh_leapcnt[4]; /* coded number of leap seconds */ - char tzh_timecnt[4]; /* coded number of transition times */ - char tzh_typecnt[4]; /* coded number of local time types */ - char tzh_charcnt[4]; /* coded number of abbr. chars */ -}; - -/* -** . . .followed by. . . -** -** tzh_timecnt (char [4])s coded transition times a la time(2) -** tzh_timecnt (unsigned char)s types of local time starting at above -** tzh_typecnt repetitions of -** one (char [4]) coded UTC offset in seconds -** one (unsigned char) used to set tm_isdst -** one (unsigned char) that's an abbreviation list index -** tzh_charcnt (char)s '\0'-terminated zone abbreviations -** tzh_leapcnt repetitions of -** one (char [4]) coded leap second transition times -** one (char [4]) total correction after above -** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition -** time is standard time, if FALSE, -** transition time is wall clock time -** if absent, transition times are -** assumed to be wall clock time -** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition -** time is UTC, if FALSE, -** transition time is local time -** if absent, transition times are -** assumed to be local time -*/ - -/* -** If tzh_version is '2' or greater, the above is followed by a second instance -** of tzhead and a second instance of the data in which each coded transition -** time uses 8 rather than 4 chars, -** then a POSIX-TZ-environment-variable-style string for use in handling -** instants after the last transition time stored in the file -** (with nothing between the newlines if there is no POSIX representation for -** such instants). -*/ - -/* -** In the current implementation, "tzset()" refuses to deal with files that -** exceed any of the limits below. -*/ - -#ifndef TZ_MAX_TIMES -#define TZ_MAX_TIMES 1200 -#endif /* !defined TZ_MAX_TIMES */ - -#ifndef TZ_MAX_TYPES -#ifndef NOSOLAR -#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ -#endif /* !defined NOSOLAR */ -#ifdef NOSOLAR -/* -** Must be at least 14 for Europe/Riga as of Jan 12 1995, -** as noted by Earl Chew. -*/ -#define TZ_MAX_TYPES 20 /* Maximum number of local time types */ -#endif /* !defined NOSOLAR */ -#endif /* !defined TZ_MAX_TYPES */ - -#ifndef TZ_MAX_CHARS -#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ - /* (limited by what unsigned chars can hold) */ -#endif /* !defined TZ_MAX_CHARS */ - -#ifndef TZ_MAX_LEAPS -#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ -#endif /* !defined TZ_MAX_LEAPS */ - -#define SECSPERMIN 60 -#define MINSPERHOUR 60 -#define HOURSPERDAY 24 -#define DAYSPERWEEK 7 -#define DAYSPERNYEAR 365 -#define DAYSPERLYEAR 366 -#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) -#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY) -#define MONSPERYEAR 12 - -#define TM_SUNDAY 0 -#define TM_MONDAY 1 -#define TM_TUESDAY 2 -#define TM_WEDNESDAY 3 -#define TM_THURSDAY 4 -#define TM_FRIDAY 5 -#define TM_SATURDAY 6 - -#define TM_JANUARY 0 -#define TM_FEBRUARY 1 -#define TM_MARCH 2 -#define TM_APRIL 3 -#define TM_MAY 4 -#define TM_JUNE 5 -#define TM_JULY 6 -#define TM_AUGUST 7 -#define TM_SEPTEMBER 8 -#define TM_OCTOBER 9 -#define TM_NOVEMBER 10 -#define TM_DECEMBER 11 - -#define TM_YEAR_BASE 1900 - -#define EPOCH_YEAR 1970 -#define EPOCH_WDAY TM_THURSDAY - -#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) - -/* -** Since everything in isleap is modulo 400 (or a factor of 400), we know that -** isleap(y) == isleap(y % 400) -** and so -** isleap(a + b) == isleap((a + b) % 400) -** or -** isleap(a + b) == isleap(a % 400 + b % 400) -** This is true even if % means modulo rather than Fortran remainder -** (which is allowed by C89 but not C99). -** We use this to avoid addition overflow problems. -*/ - -#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400) - -#endif /* !defined TZFILE_H */ diff --git a/libcutils/tzstrftime.c b/libcutils/tzstrftime.c deleted file mode 100644 index e4f54df5b..000000000 --- a/libcutils/tzstrftime.c +++ /dev/null @@ -1,842 +0,0 @@ -#ifndef lint -#ifndef NOID -static char elsieid[] = "@(#)strftime.c 8.1"; -/* -** Based on the UCB version with the ID appearing below. -** This is ANSIish only when "multibyte character == plain character". -*/ -#endif /* !defined NOID */ -#endif /* !defined lint */ - -#include -#include -#include -#include -#include - -/* -** Copyright (c) 1989 The Regents of the University of California. -** All rights reserved. -** -** Redistribution and use in source and binary forms are permitted -** provided that the above copyright notice and this paragraph are -** duplicated in all such forms and that any documentation, -** advertising materials, and other materials related to such -** distribution and use acknowledge that the software was developed -** by the University of California, Berkeley. The name of the -** University may not be used to endorse or promote products derived -** from this software without specific prior written permission. -** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED -** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -*/ - -#ifndef LIBC_SCCS -#ifndef lint -static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89"; -#endif /* !defined lint */ -#endif /* !defined LIBC_SCCS */ - -#include - -#define P(x) x - -static char * _add P((const char *, char *, const char *, int)); -static char * _conv P((int, const char *, char *, const char *)); -static char * _fmt P((const char *, const struct tm *, char *, const char *, - int *, const struct strftime_locale *Locale)); -static char * _yconv P((int, int, int, int, char *, const char *, int)); -static char * getformat P((int, char *, char *, char *, char *)); - -extern char * tzname[]; - - - - - -/* from private.h */ - -#ifndef TYPE_BIT -#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT) -#endif /* !defined TYPE_BIT */ - -#ifndef TYPE_SIGNED -#define TYPE_SIGNED(type) (((type) -1) < 0) -#endif /* !defined TYPE_SIGNED */ - -#ifndef INT_STRLEN_MAXIMUM -/* - * ** 302 / 1000 is log10(2.0) rounded up. - * ** Subtract one for the sign bit if the type is signed; - * ** add one for integer division truncation; - * ** add one more for a minus sign if the type is signed. - * */ -#define INT_STRLEN_MAXIMUM(type) \ - ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \ - 1 + TYPE_SIGNED(type)) -#endif /* !defined INT_STRLEN_MAXIMUM */ - -/* end of part from private.h */ - - - - -#ifndef YEAR_2000_NAME -#define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS" -#endif /* !defined YEAR_2000_NAME */ - -#define IN_NONE 0 -#define IN_SOME 1 -#define IN_THIS 2 -#define IN_ALL 3 - -#define FORCE_LOWER_CASE 0x100 - -size_t -strftime_tz(s, maxsize, format, t, Locale) -char * const s; -const size_t maxsize; -const char * const format; -const struct tm * const t; -const struct strftime_locale *Locale; -{ - char * p; - int warn; - - warn = IN_NONE; - p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn, Locale); -#if 0 - if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) { - (void) fprintf(stderr, "\n"); - if (format == NULL) - (void) fprintf(stderr, "NULL strftime format "); - else (void) fprintf(stderr, "strftime format \"%s\" ", - format); - (void) fprintf(stderr, "yields only two digits of years in "); - if (warn == IN_SOME) - (void) fprintf(stderr, "some locales"); - else if (warn == IN_THIS) - (void) fprintf(stderr, "the current locale"); - else (void) fprintf(stderr, "all locales"); - (void) fprintf(stderr, "\n"); - } -#endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */ - if (p == s + maxsize) - return 0; - *p = '\0'; - return p - s; -} - -static char *getformat(int modifier, char *normal, char *underscore, - char *dash, char *zero) { - switch (modifier) { - case '_': - return underscore; - - case '-': - return dash; - - case '0': - return zero; - } - - return normal; -} - -static char * -_fmt(format, t, pt, ptlim, warnp, Locale) -const char * format; -const struct tm * const t; -char * pt; -const char * const ptlim; -int * warnp; -const struct strftime_locale *Locale; -{ - for ( ; *format; ++format) { - if (*format == '%') { - int modifier = 0; -label: - switch (*++format) { - case '\0': - --format; - break; - case 'A': - pt = _add((t->tm_wday < 0 || - t->tm_wday >= DAYSPERWEEK) ? - "?" : Locale->weekday[t->tm_wday], - pt, ptlim, modifier); - continue; - case 'a': - pt = _add((t->tm_wday < 0 || - t->tm_wday >= DAYSPERWEEK) ? - "?" : Locale->wday[t->tm_wday], - pt, ptlim, modifier); - continue; - case 'B': - if (modifier == '-') { - pt = _add((t->tm_mon < 0 || - t->tm_mon >= MONSPERYEAR) ? - "?" : Locale->standalone_month[t->tm_mon], - pt, ptlim, modifier); - } else { - pt = _add((t->tm_mon < 0 || - t->tm_mon >= MONSPERYEAR) ? - "?" : Locale->month[t->tm_mon], - pt, ptlim, modifier); - } - continue; - case 'b': - case 'h': - pt = _add((t->tm_mon < 0 || - t->tm_mon >= MONSPERYEAR) ? - "?" : Locale->mon[t->tm_mon], - pt, ptlim, modifier); - continue; - case 'C': - /* - ** %C used to do a... - ** _fmt("%a %b %e %X %Y", t); - ** ...whereas now POSIX 1003.2 calls for - ** something completely different. - ** (ado, 1993-05-24) - */ - pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0, - pt, ptlim, modifier); - continue; - case 'c': - { - int warn2 = IN_SOME; - - pt = _fmt(Locale->c_fmt, t, pt, ptlim, warnp, Locale); - if (warn2 == IN_ALL) - warn2 = IN_THIS; - if (warn2 > *warnp) - *warnp = warn2; - } - continue; - case 'D': - pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp, Locale); - continue; - case 'd': - pt = _conv(t->tm_mday, - getformat(modifier, "%02d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 'E': - case 'O': - /* - ** C99 locale modifiers. - ** The sequences - ** %Ec %EC %Ex %EX %Ey %EY - ** %Od %oe %OH %OI %Om %OM - ** %OS %Ou %OU %OV %Ow %OW %Oy - ** are supposed to provide alternate - ** representations. - */ - goto label; - case '_': - case '-': - case '0': - case '^': - case '#': - modifier = *format; - goto label; - case 'e': - pt = _conv(t->tm_mday, - getformat(modifier, "%2d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 'F': - pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp, Locale); - continue; - case 'H': - pt = _conv(t->tm_hour, - getformat(modifier, "%02d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 'I': - pt = _conv((t->tm_hour % 12) ? - (t->tm_hour % 12) : 12, - getformat(modifier, "%02d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 'j': - pt = _conv(t->tm_yday + 1, - getformat(modifier, "%03d", "%3d", "%d", "%03d"), - pt, ptlim); - continue; - case 'k': - /* - ** This used to be... - ** _conv(t->tm_hour % 12 ? - ** t->tm_hour % 12 : 12, 2, ' '); - ** ...and has been changed to the below to - ** match SunOS 4.1.1 and Arnold Robbins' - ** strftime version 3.0. That is, "%k" and - ** "%l" have been swapped. - ** (ado, 1993-05-24) - */ - pt = _conv(t->tm_hour, - getformat(modifier, "%2d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; -#ifdef KITCHEN_SINK - case 'K': - /* - ** After all this time, still unclaimed! - */ - pt = _add("kitchen sink", pt, ptlim, modifier); - continue; -#endif /* defined KITCHEN_SINK */ - case 'l': - /* - ** This used to be... - ** _conv(t->tm_hour, 2, ' '); - ** ...and has been changed to the below to - ** match SunOS 4.1.1 and Arnold Robbin's - ** strftime version 3.0. That is, "%k" and - ** "%l" have been swapped. - ** (ado, 1993-05-24) - */ - pt = _conv((t->tm_hour % 12) ? - (t->tm_hour % 12) : 12, - getformat(modifier, "%2d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 'M': - pt = _conv(t->tm_min, - getformat(modifier, "%02d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 'm': - pt = _conv(t->tm_mon + 1, - getformat(modifier, "%02d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 'n': - pt = _add("\n", pt, ptlim, modifier); - continue; - case 'p': - pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ? - Locale->pm : - Locale->am, - pt, ptlim, modifier); - continue; - case 'P': - pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ? - Locale->pm : - Locale->am, - pt, ptlim, FORCE_LOWER_CASE); - continue; - case 'R': - pt = _fmt("%H:%M", t, pt, ptlim, warnp, Locale); - continue; - case 'r': - pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp, Locale); - continue; - case 'S': - pt = _conv(t->tm_sec, - getformat(modifier, "%02d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 's': - { - struct tm tm; - char buf[INT_STRLEN_MAXIMUM( - time_t) + 1]; - time_t mkt; - - tm = *t; - mkt = mktime(&tm); - if (TYPE_SIGNED(time_t)) - (void) sprintf(buf, "%ld", - (long) mkt); - else (void) sprintf(buf, "%lu", - (unsigned long) mkt); - pt = _add(buf, pt, ptlim, modifier); - } - continue; - case 'T': - pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp, Locale); - continue; - case 't': - pt = _add("\t", pt, ptlim, modifier); - continue; - case 'U': - pt = _conv((t->tm_yday + DAYSPERWEEK - - t->tm_wday) / DAYSPERWEEK, - getformat(modifier, "%02d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 'u': - /* - ** From Arnold Robbins' strftime version 3.0: - ** "ISO 8601: Weekday as a decimal number - ** [1 (Monday) - 7]" - ** (ado, 1993-05-24) - */ - pt = _conv((t->tm_wday == 0) ? - DAYSPERWEEK : t->tm_wday, "%d", pt, ptlim); - continue; - case 'V': /* ISO 8601 week number */ - case 'G': /* ISO 8601 year (four digits) */ - case 'g': /* ISO 8601 year (two digits) */ -/* -** From Arnold Robbins' strftime version 3.0: "the week number of the -** year (the first Monday as the first day of week 1) as a decimal number -** (01-53)." -** (ado, 1993-05-24) -** -** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn: -** "Week 01 of a year is per definition the first week which has the -** Thursday in this year, which is equivalent to the week which contains -** the fourth day of January. In other words, the first week of a new year -** is the week which has the majority of its days in the new year. Week 01 -** might also contain days from the previous year and the week before week -** 01 of a year is the last week (52 or 53) of the previous year even if -** it contains days from the new year. A week starts with Monday (day 1) -** and ends with Sunday (day 7). For example, the first week of the year -** 1997 lasts from 1996-12-30 to 1997-01-05..." -** (ado, 1996-01-02) -*/ - { - int year; - int base; - int yday; - int wday; - int w; - - year = t->tm_year; - base = TM_YEAR_BASE; - yday = t->tm_yday; - wday = t->tm_wday; - for ( ; ; ) { - int len; - int bot; - int top; - - len = isleap_sum(year, base) ? - DAYSPERLYEAR : - DAYSPERNYEAR; - /* - ** What yday (-3 ... 3) does - ** the ISO year begin on? - */ - bot = ((yday + 11 - wday) % - DAYSPERWEEK) - 3; - /* - ** What yday does the NEXT - ** ISO year begin on? - */ - top = bot - - (len % DAYSPERWEEK); - if (top < -3) - top += DAYSPERWEEK; - top += len; - if (yday >= top) { - ++base; - w = 1; - break; - } - if (yday >= bot) { - w = 1 + ((yday - bot) / - DAYSPERWEEK); - break; - } - --base; - yday += isleap_sum(year, base) ? - DAYSPERLYEAR : - DAYSPERNYEAR; - } -#ifdef XPG4_1994_04_09 - if ((w == 52 && - t->tm_mon == TM_JANUARY) || - (w == 1 && - t->tm_mon == TM_DECEMBER)) - w = 53; -#endif /* defined XPG4_1994_04_09 */ - if (*format == 'V') - pt = _conv(w, - getformat(modifier, - "%02d", - "%2d", - "%d", - "%02d"), - pt, ptlim); - else if (*format == 'g') { - *warnp = IN_ALL; - pt = _yconv(year, base, 0, 1, - pt, ptlim, modifier); - } else pt = _yconv(year, base, 1, 1, - pt, ptlim, modifier); - } - continue; - case 'v': - /* - ** From Arnold Robbins' strftime version 3.0: - ** "date as dd-bbb-YYYY" - ** (ado, 1993-05-24) - */ - pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp, Locale); - continue; - case 'W': - pt = _conv((t->tm_yday + DAYSPERWEEK - - (t->tm_wday ? - (t->tm_wday - 1) : - (DAYSPERWEEK - 1))) / DAYSPERWEEK, - getformat(modifier, "%02d", - "%2d", "%d", "%02d"), - pt, ptlim); - continue; - case 'w': - pt = _conv(t->tm_wday, "%d", pt, ptlim); - continue; - case 'X': - pt = _fmt(Locale->X_fmt, t, pt, ptlim, warnp, Locale); - continue; - case 'x': - { - int warn2 = IN_SOME; - - pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2, Locale); - if (warn2 == IN_ALL) - warn2 = IN_THIS; - if (warn2 > *warnp) - *warnp = warn2; - } - continue; - case 'y': - *warnp = IN_ALL; - pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1, - pt, ptlim, modifier); - continue; - case 'Y': - pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1, - pt, ptlim, modifier); - continue; - case 'Z': -#ifdef TM_ZONE - if (t->TM_ZONE != NULL) - pt = _add(t->TM_ZONE, pt, ptlim, - modifier); - else -#endif /* defined TM_ZONE */ - if (t->tm_isdst >= 0) - pt = _add(tzname[t->tm_isdst != 0], - pt, ptlim, modifier); - /* - ** C99 says that %Z must be replaced by the - ** empty string if the time zone is not - ** determinable. - */ - continue; - case 'z': - { - int diff; - char const * sign; - - if (t->tm_isdst < 0) - continue; -#ifdef TM_GMTOFF - diff = t->TM_GMTOFF; -#else /* !defined TM_GMTOFF */ - /* - ** C99 says that the UTC offset must - ** be computed by looking only at - ** tm_isdst. This requirement is - ** incorrect, since it means the code - ** must rely on magic (in this case - ** altzone and timezone), and the - ** magic might not have the correct - ** offset. Doing things correctly is - ** tricky and requires disobeying C99; - ** see GNU C strftime for details. - ** For now, punt and conform to the - ** standard, even though it's incorrect. - ** - ** C99 says that %z must be replaced by the - ** empty string if the time zone is not - ** determinable, so output nothing if the - ** appropriate variables are not available. - */ - if (t->tm_isdst == 0) -#ifdef USG_COMPAT - diff = -timezone; -#else /* !defined USG_COMPAT */ - continue; -#endif /* !defined USG_COMPAT */ - else -#ifdef ALTZONE - diff = -altzone; -#else /* !defined ALTZONE */ - continue; -#endif /* !defined ALTZONE */ -#endif /* !defined TM_GMTOFF */ - if (diff < 0) { - sign = "-"; - diff = -diff; - } else sign = "+"; - pt = _add(sign, pt, ptlim, modifier); - diff /= SECSPERMIN; - diff = (diff / MINSPERHOUR) * 100 + - (diff % MINSPERHOUR); - pt = _conv(diff, - getformat(modifier, "%04d", - "%4d", "%d", "%04d"), - pt, ptlim); - } - continue; - case '+': - pt = _fmt(Locale->date_fmt, t, pt, ptlim, - warnp, Locale); - continue; - case '%': - /* - ** X311J/88-090 (4.12.3.5): if conversion char is - ** undefined, behavior is undefined. Print out the - ** character itself as printf(3) also does. - */ - default: - break; - } - } - if (pt == ptlim) - break; - *pt++ = *format; - } - return pt; -} - -static char * -_conv(n, format, pt, ptlim) -const int n; -const char * const format; -char * const pt; -const char * const ptlim; -{ - char buf[INT_STRLEN_MAXIMUM(int) + 1]; - - (void) sprintf(buf, format, n); - return _add(buf, pt, ptlim, 0); -} - -static char * -_add(str, pt, ptlim, modifier) -const char * str; -char * pt; -const char * const ptlim; -int modifier; -{ - int c; - - switch (modifier) { - case FORCE_LOWER_CASE: - while (pt < ptlim && (*pt = tolower(*str++)) != '\0') { - ++pt; - } - break; - - case '^': - while (pt < ptlim && (*pt = toupper(*str++)) != '\0') { - ++pt; - } - break; - - case '#': - while (pt < ptlim && (c = *str++) != '\0') { - if (isupper(c)) { - c = tolower(c); - } else if (islower(c)) { - c = toupper(c); - } - *pt = c; - ++pt; - } - - break; - - default: - while (pt < ptlim && (*pt = *str++) != '\0') { - ++pt; - } - } - - return pt; -} - -/* -** POSIX and the C Standard are unclear or inconsistent about -** what %C and %y do if the year is negative or exceeds 9999. -** Use the convention that %C concatenated with %y yields the -** same output as %Y, and that %Y contains at least 4 bytes, -** with more only if necessary. -*/ - -static char * -_yconv(a, b, convert_top, convert_yy, pt, ptlim, modifier) -const int a; -const int b; -const int convert_top; -const int convert_yy; -char * pt; -const char * const ptlim; -int modifier; -{ - register int lead; - register int trail; - -#define DIVISOR 100 - trail = a % DIVISOR + b % DIVISOR; - lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR; - trail %= DIVISOR; - if (trail < 0 && lead > 0) { - trail += DIVISOR; - --lead; - } else if (lead < 0 && trail > 0) { - trail -= DIVISOR; - ++lead; - } - if (convert_top) { - if (lead == 0 && trail < 0) - pt = _add("-0", pt, ptlim, modifier); - else pt = _conv(lead, getformat(modifier, "%02d", - "%2d", "%d", "%02d"), - pt, ptlim); - } - if (convert_yy) - pt = _conv(((trail < 0) ? -trail : trail), - getformat(modifier, "%02d", "%2d", "%d", "%02d"), - pt, ptlim); - return pt; -} - -#ifdef LOCALE_HOME -static struct lc_time_T * -_loc P((void)) -{ - static const char locale_home[] = LOCALE_HOME; - static const char lc_time[] = "LC_TIME"; - static char * locale_buf; - - int fd; - int oldsun; /* "...ain't got nothin' to do..." */ - char * lbuf; - char * name; - char * p; - const char ** ap; - const char * plim; - char filename[FILENAME_MAX]; - struct stat st; - size_t namesize; - size_t bufsize; - - /* - ** Use localebuf.mon[0] to signal whether locale is already set up. - */ - if (localebuf.mon[0]) - return &localebuf; - name = setlocale(LC_TIME, (char *) NULL); - if (name == NULL || *name == '\0') - goto no_locale; - /* - ** If the locale name is the same as our cache, use the cache. - */ - lbuf = locale_buf; - if (lbuf != NULL && strcmp(name, lbuf) == 0) { - p = lbuf; - for (ap = (const char **) &localebuf; - ap < (const char **) (&localebuf + 1); - ++ap) - *ap = p += strlen(p) + 1; - return &localebuf; - } - /* - ** Slurp the locale file into the cache. - */ - namesize = strlen(name) + 1; - if (sizeof filename < - ((sizeof locale_home) + namesize + (sizeof lc_time))) - goto no_locale; - oldsun = 0; - (void) sprintf(filename, "%s/%s/%s", locale_home, name, lc_time); - fd = open(filename, O_RDONLY); - if (fd < 0) { - /* - ** Old Sun systems have a different naming and data convention. - */ - oldsun = 1; - (void) sprintf(filename, "%s/%s/%s", locale_home, - lc_time, name); - fd = open(filename, O_RDONLY); - if (fd < 0) - goto no_locale; - } - if (fstat(fd, &st) != 0) - goto bad_locale; - if (st.st_size <= 0) - goto bad_locale; - bufsize = namesize + st.st_size; - locale_buf = NULL; - lbuf = (lbuf == NULL) ? malloc(bufsize) : realloc(lbuf, bufsize); - if (lbuf == NULL) - goto bad_locale; - (void) strcpy(lbuf, name); - p = lbuf + namesize; - plim = p + st.st_size; - if (read(fd, p, (size_t) st.st_size) != st.st_size) - goto bad_lbuf; - if (close(fd) != 0) - goto bad_lbuf; - /* - ** Parse the locale file into localebuf. - */ - if (plim[-1] != '\n') - goto bad_lbuf; - for (ap = (const char **) &localebuf; - ap < (const char **) (&localebuf + 1); - ++ap) { - if (p == plim) - goto bad_lbuf; - *ap = p; - while (*p != '\n') - ++p; - *p++ = '\0'; - } - if (oldsun) { - /* - ** SunOS 4 used an obsolescent format; see localdtconv(3). - ** c_fmt had the ``short format for dates and times together'' - ** (SunOS 4 date, "%a %b %e %T %Z %Y" in the C locale); - ** date_fmt had the ``long format for dates'' - ** (SunOS 4 strftime %C, "%A, %B %e, %Y" in the C locale). - ** Discard the latter in favor of the former. - */ - localebuf.date_fmt = localebuf.c_fmt; - } - /* - ** Record the successful parse in the cache. - */ - locale_buf = lbuf; - - return &localebuf; - -bad_lbuf: - free(lbuf); -bad_locale: - (void) close(fd); -no_locale: - localebuf = C_time_locale; - locale_buf = NULL; - return &localebuf; -} -#endif /* defined LOCALE_HOME */ diff --git a/libcutils/tztime.c b/libcutils/tztime.c deleted file mode 100644 index d6448a1da..000000000 --- a/libcutils/tztime.c +++ /dev/null @@ -1,1950 +0,0 @@ -/* -** This file is in the public domain, so clarified as of -** 1996-06-05 by Arthur David Olson. -*/ - -#include - -#ifndef lint -#ifndef NOID -static char elsieid[] = "@(#)localtime.c 8.3"; -#endif /* !defined NOID */ -#endif /* !defined lint */ - -/* -** Leap second handling from Bradley White. -** POSIX-style TZ environment variable handling from Guy Harris. -*/ - -/*LINTLIBRARY*/ - -#include "private.h" -#include "tzfile.h" -#include "fcntl.h" -#include "float.h" /* for FLT_MAX and DBL_MAX */ - -#ifndef TZ_ABBR_MAX_LEN -#define TZ_ABBR_MAX_LEN 16 -#endif /* !defined TZ_ABBR_MAX_LEN */ - -#ifndef TZ_ABBR_CHAR_SET -#define TZ_ABBR_CHAR_SET \ - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._" -#endif /* !defined TZ_ABBR_CHAR_SET */ - -#ifndef TZ_ABBR_ERR_CHAR -#define TZ_ABBR_ERR_CHAR '_' -#endif /* !defined TZ_ABBR_ERR_CHAR */ - -#define INDEXFILE "/system/usr/share/zoneinfo/zoneinfo.idx" -#define DATAFILE "/system/usr/share/zoneinfo/zoneinfo.dat" -#define NAMELEN 40 -#define INTLEN 4 -#define READLEN (NAMELEN + 3 * INTLEN) - -/* -** SunOS 4.1.1 headers lack O_BINARY. -*/ - -#ifdef O_BINARY -#define OPEN_MODE (O_RDONLY | O_BINARY) -#endif /* defined O_BINARY */ -#ifndef O_BINARY -#define OPEN_MODE O_RDONLY -#endif /* !defined O_BINARY */ - -/* Complex computations to determine the min/max of time_t depending - * on TYPE_BIT / TYPE_SIGNED / TYPE_INTEGRAL. - * These macros cannot be used in pre-processor directives, so we - * let the C compiler do the work, which makes things a bit funky. - */ -static const time_t TIME_T_MAX = - TYPE_INTEGRAL(time_t) ? - ( TYPE_SIGNED(time_t) ? - ~((time_t)1 << (TYPE_BIT(time_t)-1)) - : - ~(time_t)0 - ) - : /* if time_t is a floating point number */ - ( sizeof(time_t) > sizeof(float) ? (time_t)DBL_MAX : (time_t)FLT_MAX ); - -static const time_t TIME_T_MIN = - TYPE_INTEGRAL(time_t) ? - ( TYPE_SIGNED(time_t) ? - ((time_t)1 << (TYPE_BIT(time_t)-1)) - : - 0 - ) - : - ( sizeof(time_t) > sizeof(float) ? (time_t)DBL_MIN : (time_t)FLT_MIN ); - -#ifndef WILDABBR -/* -** Someone might make incorrect use of a time zone abbreviation: -** 1. They might reference tzname[0] before calling tzset (explicitly -** or implicitly). -** 2. They might reference tzname[1] before calling tzset (explicitly -** or implicitly). -** 3. They might reference tzname[1] after setting to a time zone -** in which Daylight Saving Time is never observed. -** 4. They might reference tzname[0] after setting to a time zone -** in which Standard Time is never observed. -** 5. They might reference tm.TM_ZONE after calling offtime. -** What's best to do in the above cases is open to debate; -** for now, we just set things up so that in any of the five cases -** WILDABBR is used. Another possibility: initialize tzname[0] to the -** string "tzname[0] used before set", and similarly for the other cases. -** And another: initialize tzname[0] to "ERA", with an explanation in the -** manual page of what this "time zone abbreviation" means (doing this so -** that tzname[0] has the "normal" length of three characters). -*/ -#define WILDABBR " " -#endif /* !defined WILDABBR */ - -static char wildabbr[] = WILDABBR; - -static const char gmt[] = "GMT"; - -/* -** The DST rules to use if TZ has no rules and we can't load TZDEFRULES. -** We default to US rules as of 1999-08-17. -** POSIX 1003.1 section 8.1.1 says that the default DST rules are -** implementation dependent; for historical reasons, US rules are a -** common default. -*/ -#ifndef TZDEFRULESTRING -#define TZDEFRULESTRING ",M4.1.0,M10.5.0" -#endif /* !defined TZDEFDST */ - -struct ttinfo { /* time type information */ - long tt_gmtoff; /* UTC offset in seconds */ - int tt_isdst; /* used to set tm_isdst */ - int tt_abbrind; /* abbreviation list index */ - int tt_ttisstd; /* TRUE if transition is std time */ - int tt_ttisgmt; /* TRUE if transition is UTC */ -}; - -struct lsinfo { /* leap second information */ - time_t ls_trans; /* transition time */ - long ls_corr; /* correction to apply */ -}; - -#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b)) - -#ifdef TZNAME_MAX -#define MY_TZNAME_MAX TZNAME_MAX -#endif /* defined TZNAME_MAX */ -#ifndef TZNAME_MAX -#define MY_TZNAME_MAX 255 -#endif /* !defined TZNAME_MAX */ - -struct state { - int leapcnt; - int timecnt; - int typecnt; - int charcnt; - int goback; - int goahead; - time_t ats[TZ_MAX_TIMES]; - unsigned char types[TZ_MAX_TIMES]; - struct ttinfo ttis[TZ_MAX_TYPES]; - char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt), - (2 * (MY_TZNAME_MAX + 1)))]; - struct lsinfo lsis[TZ_MAX_LEAPS]; -}; - -struct rule { - int r_type; /* type of rule--see below */ - int r_day; /* day number of rule */ - int r_week; /* week number of rule */ - int r_mon; /* month number of rule */ - long r_time; /* transition time of rule */ -}; - -#define JULIAN_DAY 0 /* Jn - Julian day */ -#define DAY_OF_YEAR 1 /* n - day of year */ -#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */ - -/* -** Prototypes for static functions. -*/ - -static long detzcode P((const char * codep)); -static time_t detzcode64 P((const char * codep)); -static int differ_by_repeat P((time_t t1, time_t t0)); -static const char * getzname P((const char * strp)); -static const char * getqzname P((const char * strp, const int delim)); -static const char * getnum P((const char * strp, int * nump, int min, - int max)); -static const char * getsecs P((const char * strp, long * secsp)); -static const char * getoffset P((const char * strp, long * offsetp)); -static const char * getrule P((const char * strp, struct rule * rulep)); -static void gmtload P((struct state * sp)); -static struct tm * gmtsub P((const time_t * timep, long offset, - struct tm * tmp)); -static struct tm * localsub P((const time_t * timep, long offset, - struct tm * tmp, const struct state *sp)); -static int increment_overflow P((int * number, int delta)); -static int leaps_thru_end_of P((int y)); -static int long_increment_overflow P((long * number, int delta)); -static int long_normalize_overflow P((long * tensptr, - int * unitsptr, int base)); -static int normalize_overflow P((int * tensptr, int * unitsptr, - int base)); -static void settzname P((void)); -static time_t time1 P((struct tm * tmp, - struct tm * (*funcp) P((const time_t *, - long, struct tm *, const struct state* sp)), - long offset, const struct state * sp)); -static time_t time2 P((struct tm *tmp, - struct tm * (*funcp) P((const time_t *, - long, struct tm*, const struct state* sp)), - long offset, int * okayp, const struct state * sp)); -static time_t time2sub P((struct tm *tmp, - struct tm * (*funcp) P((const time_t*, long, struct tm*,const struct state *sp)), - long offset, int * okayp, int do_norm_secs, - const struct state *sp)); -static struct tm * timesub P((const time_t * timep, long offset, - const struct state * sp, struct tm * tmp)); -static int tmcomp P((const struct tm * atmp, - const struct tm * btmp)); -static time_t transtime P((time_t janfirst, int year, - const struct rule * rulep, long offset)); -static int tzload P((const char * name, struct state * sp, - int doextend)); -static int tzload_uncached P((const char * name, struct state * sp, - int doextend)); -static int tzparse P((const char * name, struct state * sp, - int lastditch)); - -#ifdef ALL_STATE -static struct state * gmtptr; -#endif /* defined ALL_STATE */ - -#ifndef ALL_STATE -static struct state gmtmem; -#define gmtptr (&gmtmem) -#endif /* State Farm */ - -#define CACHE_COUNT 4 -static char * g_cacheNames[CACHE_COUNT] = {0,0}; -static struct state g_cacheStates[CACHE_COUNT]; -static int g_lastCache = 0; -static struct state g_utc; -unsigned char g_utcSet = 0; - - -#ifndef TZ_STRLEN_MAX -#define TZ_STRLEN_MAX 255 -#endif /* !defined TZ_STRLEN_MAX */ - -static char lcl_TZname[TZ_STRLEN_MAX + 1]; -static int lcl_is_set; -static int gmt_is_set; - -char * tzname[2] = { - wildabbr, - wildabbr -}; - -/* -** Section 4.12.3 of X3.159-1989 requires that -** Except for the strftime function, these functions [asctime, -** ctime, gmtime, localtime] return values in one of two static -** objects: a broken-down time structure and an array of char. -** Thanks to Paul Eggert for noting this. -*/ - -static struct tm tm; - -#ifdef USG_COMPAT -time_t timezone = 0; -int daylight = 0; -#endif /* defined USG_COMPAT */ - -#ifdef ALTZONE -time_t altzone = 0; -#endif /* defined ALTZONE */ - -static long -detzcode(codep) -const char * const codep; -{ - register long result; - register int i; - - result = (codep[0] & 0x80) ? ~0L : 0; - for (i = 0; i < 4; ++i) - result = (result << 8) | (codep[i] & 0xff); - return result; -} - -static time_t -detzcode64(codep) -const char * const codep; -{ - register time_t result; - register int i; - - result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0; - for (i = 0; i < 8; ++i) - result = result * 256 + (codep[i] & 0xff); - return result; -} - -static int -differ_by_repeat(t1, t0) -const time_t t1; -const time_t t0; -{ - if (TYPE_INTEGRAL(time_t) && - TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS) - return 0; - return t1 - t0 == SECSPERREPEAT; -} - -static int toint(unsigned char *s) { - return (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; -} - -static int -tzload(const char *name, struct state * const sp, const int doextend) -{ - if (name) { - int i, err; - if (0 == strcmp(name, "UTC")) { - if (!g_utcSet) { - tzload_uncached(name, &g_utc, 1); - g_utcSet = 1; - } - //printf("tzload: utc\n"); - *sp = g_utc; - return 0; - } - for (i=0; i= CACHE_COUNT) { - g_lastCache = 0; - } - i = g_lastCache; - if (g_cacheNames[i]) { - free(g_cacheNames[i]); - } - err = tzload_uncached(name, &(g_cacheStates[i]), 1); - if (err == 0) { - g_cacheNames[i] = strdup(name); - *sp = g_cacheStates[i]; - return 0; - } else { - g_cacheNames[i] = NULL; - return err; - } - } - return tzload_uncached(name, sp, doextend); -} - -static int -tzload_uncached(name, sp, doextend) -register const char * name; -register struct state * const sp; -register const int doextend; -{ - register const char * p; - register int i; - register int fid; - register int stored; - register int nread; - union { - struct tzhead tzhead; - char buf[2 * sizeof(struct tzhead) + - 2 * sizeof *sp + - 4 * TZ_MAX_TIMES]; - } u; - int toread = sizeof u.buf; - - if (name == NULL && (name = TZDEFAULT) == NULL) - return -1; - { - register int doaccess; - /* - ** Section 4.9.1 of the C standard says that - ** "FILENAME_MAX expands to an integral constant expression - ** that is the size needed for an array of char large enough - ** to hold the longest file name string that the implementation - ** guarantees can be opened." - */ - char fullname[FILENAME_MAX + 1]; - const char *origname = name; - - if (name[0] == ':') - ++name; - doaccess = name[0] == '/'; - if (!doaccess) { - if ((p = TZDIR) == NULL) - return -1; - if ((strlen(p) + strlen(name) + 1) >= sizeof fullname) - return -1; - (void) strcpy(fullname, p); - (void) strcat(fullname, "/"); - (void) strcat(fullname, name); - /* - ** Set doaccess if '.' (as in "../") shows up in name. - */ - if (strchr(name, '.') != NULL) - doaccess = TRUE; - name = fullname; - } - if (doaccess && access(name, R_OK) != 0) - return -1; - if ((fid = open(name, OPEN_MODE)) == -1) { - char buf[READLEN]; - char name[NAMELEN + 1]; - int fidix = open(INDEXFILE, OPEN_MODE); - int off = -1; - - if (fidix < 0) { - return -1; - } - - while (read(fidix, buf, sizeof(buf)) == sizeof(buf)) { - memcpy(name, buf, NAMELEN); - name[NAMELEN] = '\0'; - - if (strcmp(name, origname) == 0) { - off = toint((unsigned char *) buf + NAMELEN); - toread = toint((unsigned char *) buf + NAMELEN + INTLEN); - break; - } - } - - close(fidix); - - if (off < 0) - return -1; - - fid = open(DATAFILE, OPEN_MODE); - - if (fid < 0) { - return -1; - } - - if (lseek(fid, off, SEEK_SET) < 0) { - return -1; - } - } - } - nread = read(fid, u.buf, toread); - if (close(fid) < 0 || nread <= 0) - return -1; - for (stored = 4; stored <= 8; stored *= 2) { - int ttisstdcnt; - int ttisgmtcnt; - - ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt); - ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt); - sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt); - sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt); - sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt); - sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt); - p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt; - if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS || - sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES || - sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES || - sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS || - (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) || - (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0)) - return -1; - if (nread - (p - u.buf) < - sp->timecnt * stored + /* ats */ - sp->timecnt + /* types */ - sp->typecnt * 6 + /* ttinfos */ - sp->charcnt + /* chars */ - sp->leapcnt * (stored + 4) + /* lsinfos */ - ttisstdcnt + /* ttisstds */ - ttisgmtcnt) /* ttisgmts */ - return -1; - for (i = 0; i < sp->timecnt; ++i) { - sp->ats[i] = (stored == 4) ? - detzcode(p) : detzcode64(p); - p += stored; - } - for (i = 0; i < sp->timecnt; ++i) { - sp->types[i] = (unsigned char) *p++; - if (sp->types[i] >= sp->typecnt) - return -1; - } - for (i = 0; i < sp->typecnt; ++i) { - register struct ttinfo * ttisp; - - ttisp = &sp->ttis[i]; - ttisp->tt_gmtoff = detzcode(p); - p += 4; - ttisp->tt_isdst = (unsigned char) *p++; - if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1) - return -1; - ttisp->tt_abbrind = (unsigned char) *p++; - if (ttisp->tt_abbrind < 0 || - ttisp->tt_abbrind > sp->charcnt) - return -1; - } - for (i = 0; i < sp->charcnt; ++i) - sp->chars[i] = *p++; - sp->chars[i] = '\0'; /* ensure '\0' at end */ - for (i = 0; i < sp->leapcnt; ++i) { - register struct lsinfo * lsisp; - - lsisp = &sp->lsis[i]; - lsisp->ls_trans = (stored == 4) ? - detzcode(p) : detzcode64(p); - p += stored; - lsisp->ls_corr = detzcode(p); - p += 4; - } - for (i = 0; i < sp->typecnt; ++i) { - register struct ttinfo * ttisp; - - ttisp = &sp->ttis[i]; - if (ttisstdcnt == 0) - ttisp->tt_ttisstd = FALSE; - else { - ttisp->tt_ttisstd = *p++; - if (ttisp->tt_ttisstd != TRUE && - ttisp->tt_ttisstd != FALSE) - return -1; - } - } - for (i = 0; i < sp->typecnt; ++i) { - register struct ttinfo * ttisp; - - ttisp = &sp->ttis[i]; - if (ttisgmtcnt == 0) - ttisp->tt_ttisgmt = FALSE; - else { - ttisp->tt_ttisgmt = *p++; - if (ttisp->tt_ttisgmt != TRUE && - ttisp->tt_ttisgmt != FALSE) - return -1; - } - } - /* - ** Out-of-sort ats should mean we're running on a - ** signed time_t system but using a data file with - ** unsigned values (or vice versa). - */ - for (i = 0; i < sp->timecnt - 2; ++i) - if (sp->ats[i] > sp->ats[i + 1]) { - ++i; - if (TYPE_SIGNED(time_t)) { - /* - ** Ignore the end (easy). - */ - sp->timecnt = i; - } else { - /* - ** Ignore the beginning (harder). - */ - register int j; - - for (j = 0; j + i < sp->timecnt; ++j) { - sp->ats[j] = sp->ats[j + i]; - sp->types[j] = sp->types[j + i]; - } - sp->timecnt = j; - } - break; - } - /* - ** If this is an old file, we're done. - */ - if (u.tzhead.tzh_version[0] == '\0') - break; - nread -= p - u.buf; - for (i = 0; i < nread; ++i) - u.buf[i] = p[i]; - /* - ** If this is a narrow integer time_t system, we're done. - */ - if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t)) - break; - } - if (doextend && nread > 2 && - u.buf[0] == '\n' && u.buf[nread - 1] == '\n' && - sp->typecnt + 2 <= TZ_MAX_TYPES) { - struct state ts; - register int result; - - u.buf[nread - 1] = '\0'; - result = tzparse(&u.buf[1], &ts, FALSE); - if (result == 0 && ts.typecnt == 2 && - sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) { - for (i = 0; i < 2; ++i) - ts.ttis[i].tt_abbrind += - sp->charcnt; - for (i = 0; i < ts.charcnt; ++i) - sp->chars[sp->charcnt++] = - ts.chars[i]; - i = 0; - while (i < ts.timecnt && - ts.ats[i] <= - sp->ats[sp->timecnt - 1]) - ++i; - while (i < ts.timecnt && - sp->timecnt < TZ_MAX_TIMES) { - sp->ats[sp->timecnt] = - ts.ats[i]; - sp->types[sp->timecnt] = - sp->typecnt + - ts.types[i]; - ++sp->timecnt; - ++i; - } - sp->ttis[sp->typecnt++] = ts.ttis[0]; - sp->ttis[sp->typecnt++] = ts.ttis[1]; - } - } - i = 2 * YEARSPERREPEAT; - sp->goback = sp->goahead = sp->timecnt > i; - sp->goback &= sp->types[i] == sp->types[0] && - differ_by_repeat(sp->ats[i], sp->ats[0]); - sp->goahead &= - sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] && - differ_by_repeat(sp->ats[sp->timecnt - 1], - sp->ats[sp->timecnt - 1 - i]); - return 0; -} - -static const int mon_lengths[2][MONSPERYEAR] = { - { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, - { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } -}; - -static const int year_lengths[2] = { - DAYSPERNYEAR, DAYSPERLYEAR -}; - -/* -** Given a pointer into a time zone string, scan until a character that is not -** a valid character in a zone name is found. Return a pointer to that -** character. -*/ - -static const char * -getzname(strp) -register const char * strp; -{ - register char c; - - while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' && - c != '+') - ++strp; - return strp; -} - -/* -** Given a pointer into an extended time zone string, scan until the ending -** delimiter of the zone name is located. Return a pointer to the delimiter. -** -** As with getzname above, the legal character set is actually quite -** restricted, with other characters producing undefined results. -** We don't do any checking here; checking is done later in common-case code. -*/ - -static const char * -getqzname(register const char *strp, const int delim) -{ - register int c; - - while ((c = *strp) != '\0' && c != delim) - ++strp; - return strp; -} - -/* -** Given a pointer into a time zone string, extract a number from that string. -** Check that the number is within a specified range; if it is not, return -** NULL. -** Otherwise, return a pointer to the first character not part of the number. -*/ - -static const char * -getnum(strp, nump, min, max) -register const char * strp; -int * const nump; -const int min; -const int max; -{ - register char c; - register int num; - - if (strp == NULL || !is_digit(c = *strp)) - return NULL; - num = 0; - do { - num = num * 10 + (c - '0'); - if (num > max) - return NULL; /* illegal value */ - c = *++strp; - } while (is_digit(c)); - if (num < min) - return NULL; /* illegal value */ - *nump = num; - return strp; -} - -/* -** Given a pointer into a time zone string, extract a number of seconds, -** in hh[:mm[:ss]] form, from the string. -** If any error occurs, return NULL. -** Otherwise, return a pointer to the first character not part of the number -** of seconds. -*/ - -static const char * -getsecs(strp, secsp) -register const char * strp; -long * const secsp; -{ - int num; - - /* - ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like - ** "M10.4.6/26", which does not conform to Posix, - ** but which specifies the equivalent of - ** ``02:00 on the first Sunday on or after 23 Oct''. - */ - strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1); - if (strp == NULL) - return NULL; - *secsp = num * (long) SECSPERHOUR; - if (*strp == ':') { - ++strp; - strp = getnum(strp, &num, 0, MINSPERHOUR - 1); - if (strp == NULL) - return NULL; - *secsp += num * SECSPERMIN; - if (*strp == ':') { - ++strp; - /* `SECSPERMIN' allows for leap seconds. */ - strp = getnum(strp, &num, 0, SECSPERMIN); - if (strp == NULL) - return NULL; - *secsp += num; - } - } - return strp; -} - -/* -** Given a pointer into a time zone string, extract an offset, in -** [+-]hh[:mm[:ss]] form, from the string. -** If any error occurs, return NULL. -** Otherwise, return a pointer to the first character not part of the time. -*/ - -static const char * -getoffset(strp, offsetp) -register const char * strp; -long * const offsetp; -{ - register int neg = 0; - - if (*strp == '-') { - neg = 1; - ++strp; - } else if (*strp == '+') - ++strp; - strp = getsecs(strp, offsetp); - if (strp == NULL) - return NULL; /* illegal time */ - if (neg) - *offsetp = -*offsetp; - return strp; -} - -/* -** Given a pointer into a time zone string, extract a rule in the form -** date[/time]. See POSIX section 8 for the format of "date" and "time". -** If a valid rule is not found, return NULL. -** Otherwise, return a pointer to the first character not part of the rule. -*/ - -static const char * -getrule(strp, rulep) -const char * strp; -register struct rule * const rulep; -{ - if (*strp == 'J') { - /* - ** Julian day. - */ - rulep->r_type = JULIAN_DAY; - ++strp; - strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR); - } else if (*strp == 'M') { - /* - ** Month, week, day. - */ - rulep->r_type = MONTH_NTH_DAY_OF_WEEK; - ++strp; - strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR); - if (strp == NULL) - return NULL; - if (*strp++ != '.') - return NULL; - strp = getnum(strp, &rulep->r_week, 1, 5); - if (strp == NULL) - return NULL; - if (*strp++ != '.') - return NULL; - strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1); - } else if (is_digit(*strp)) { - /* - ** Day of year. - */ - rulep->r_type = DAY_OF_YEAR; - strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); - } else return NULL; /* invalid format */ - if (strp == NULL) - return NULL; - if (*strp == '/') { - /* - ** Time specified. - */ - ++strp; - strp = getsecs(strp, &rulep->r_time); - } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ - return strp; -} - -/* -** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the -** year, a rule, and the offset from UTC at the time that rule takes effect, -** calculate the Epoch-relative time that rule takes effect. -*/ - -static time_t -transtime(janfirst, year, rulep, offset) -const time_t janfirst; -const int year; -register const struct rule * const rulep; -const long offset; -{ - register int leapyear; - register time_t value; - register int i; - int d, m1, yy0, yy1, yy2, dow; - - INITIALIZE(value); - leapyear = isleap(year); - switch (rulep->r_type) { - - case JULIAN_DAY: - /* - ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap - ** years. - ** In non-leap years, or if the day number is 59 or less, just - ** add SECSPERDAY times the day number-1 to the time of - ** January 1, midnight, to get the day. - */ - value = janfirst + (rulep->r_day - 1) * SECSPERDAY; - if (leapyear && rulep->r_day >= 60) - value += SECSPERDAY; - break; - - case DAY_OF_YEAR: - /* - ** n - day of year. - ** Just add SECSPERDAY times the day number to the time of - ** January 1, midnight, to get the day. - */ - value = janfirst + rulep->r_day * SECSPERDAY; - break; - - case MONTH_NTH_DAY_OF_WEEK: - /* - ** Mm.n.d - nth "dth day" of month m. - */ - value = janfirst; - for (i = 0; i < rulep->r_mon - 1; ++i) - value += mon_lengths[leapyear][i] * SECSPERDAY; - - /* - ** Use Zeller's Congruence to get day-of-week of first day of - ** month. - */ - m1 = (rulep->r_mon + 9) % 12 + 1; - yy0 = (rulep->r_mon <= 2) ? (year - 1) : year; - yy1 = yy0 / 100; - yy2 = yy0 % 100; - dow = ((26 * m1 - 2) / 10 + - 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7; - if (dow < 0) - dow += DAYSPERWEEK; - - /* - ** "dow" is the day-of-week of the first day of the month. Get - ** the day-of-month (zero-origin) of the first "dow" day of the - ** month. - */ - d = rulep->r_day - dow; - if (d < 0) - d += DAYSPERWEEK; - for (i = 1; i < rulep->r_week; ++i) { - if (d + DAYSPERWEEK >= - mon_lengths[leapyear][rulep->r_mon - 1]) - break; - d += DAYSPERWEEK; - } - - /* - ** "d" is the day-of-month (zero-origin) of the day we want. - */ - value += d * SECSPERDAY; - break; - } - - /* - ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in - ** question. To get the Epoch-relative time of the specified local - ** time on that day, add the transition time and the current offset - ** from UTC. - */ - return value + rulep->r_time + offset; -} - -/* -** Given a POSIX section 8-style TZ string, fill in the rule tables as -** appropriate. -*/ - -static int -tzparse(name, sp, lastditch) -const char * name; -register struct state * const sp; -const int lastditch; -{ - const char * stdname; - const char * dstname; - size_t stdlen; - size_t dstlen; - long stdoffset; - long dstoffset; - register time_t * atp; - register unsigned char * typep; - register char * cp; - register int load_result; - - INITIALIZE(dstname); - stdname = name; - if (lastditch) { - stdlen = strlen(name); /* length of standard zone name */ - name += stdlen; - if (stdlen >= sizeof sp->chars) - stdlen = (sizeof sp->chars) - 1; - stdoffset = 0; - } else { - if (*name == '<') { - name++; - stdname = name; - name = getqzname(name, '>'); - if (*name != '>') - return (-1); - stdlen = name - stdname; - name++; - } else { - name = getzname(name); - stdlen = name - stdname; - } - if (*name == '\0') - return -1; - name = getoffset(name, &stdoffset); - if (name == NULL) - return -1; - } - load_result = tzload(TZDEFRULES, sp, FALSE); - if (load_result != 0) - sp->leapcnt = 0; /* so, we're off a little */ - sp->timecnt = 0; - if (*name != '\0') { - if (*name == '<') { - dstname = ++name; - name = getqzname(name, '>'); - if (*name != '>') - return -1; - dstlen = name - dstname; - name++; - } else { - dstname = name; - name = getzname(name); - dstlen = name - dstname; /* length of DST zone name */ - } - if (*name != '\0' && *name != ',' && *name != ';') { - name = getoffset(name, &dstoffset); - if (name == NULL) - return -1; - } else dstoffset = stdoffset - SECSPERHOUR; - if (*name == '\0' && load_result != 0) - name = TZDEFRULESTRING; - if (*name == ',' || *name == ';') { - struct rule start; - struct rule end; - register int year; - register time_t janfirst; - time_t starttime; - time_t endtime; - - ++name; - if ((name = getrule(name, &start)) == NULL) - return -1; - if (*name++ != ',') - return -1; - if ((name = getrule(name, &end)) == NULL) - return -1; - if (*name != '\0') - return -1; - sp->typecnt = 2; /* standard time and DST */ - /* - ** Two transitions per year, from EPOCH_YEAR forward. - */ - sp->ttis[0].tt_gmtoff = -dstoffset; - sp->ttis[0].tt_isdst = 1; - sp->ttis[0].tt_abbrind = stdlen + 1; - sp->ttis[1].tt_gmtoff = -stdoffset; - sp->ttis[1].tt_isdst = 0; - sp->ttis[1].tt_abbrind = 0; - atp = sp->ats; - typep = sp->types; - janfirst = 0; - for (year = EPOCH_YEAR; - sp->timecnt + 2 <= TZ_MAX_TIMES; - ++year) { - time_t newfirst; - - starttime = transtime(janfirst, year, &start, - stdoffset); - endtime = transtime(janfirst, year, &end, - dstoffset); - if (starttime > endtime) { - *atp++ = endtime; - *typep++ = 1; /* DST ends */ - *atp++ = starttime; - *typep++ = 0; /* DST begins */ - } else { - *atp++ = starttime; - *typep++ = 0; /* DST begins */ - *atp++ = endtime; - *typep++ = 1; /* DST ends */ - } - sp->timecnt += 2; - newfirst = janfirst; - newfirst += year_lengths[isleap(year)] * - SECSPERDAY; - if (newfirst <= janfirst) - break; - janfirst = newfirst; - } - } else { - register long theirstdoffset; - register long theirdstoffset; - register long theiroffset; - register int isdst; - register int i; - register int j; - - if (*name != '\0') - return -1; - /* - ** Initial values of theirstdoffset and theirdstoffset. - */ - theirstdoffset = 0; - for (i = 0; i < sp->timecnt; ++i) { - j = sp->types[i]; - if (!sp->ttis[j].tt_isdst) { - theirstdoffset = - -sp->ttis[j].tt_gmtoff; - break; - } - } - theirdstoffset = 0; - for (i = 0; i < sp->timecnt; ++i) { - j = sp->types[i]; - if (sp->ttis[j].tt_isdst) { - theirdstoffset = - -sp->ttis[j].tt_gmtoff; - break; - } - } - /* - ** Initially we're assumed to be in standard time. - */ - isdst = FALSE; - theiroffset = theirstdoffset; - /* - ** Now juggle transition times and types - ** tracking offsets as you do. - */ - for (i = 0; i < sp->timecnt; ++i) { - j = sp->types[i]; - sp->types[i] = sp->ttis[j].tt_isdst; - if (sp->ttis[j].tt_ttisgmt) { - /* No adjustment to transition time */ - } else { - /* - ** If summer time is in effect, and the - ** transition time was not specified as - ** standard time, add the summer time - ** offset to the transition time; - ** otherwise, add the standard time - ** offset to the transition time. - */ - /* - ** Transitions from DST to DDST - ** will effectively disappear since - ** POSIX provides for only one DST - ** offset. - */ - if (isdst && !sp->ttis[j].tt_ttisstd) { - sp->ats[i] += dstoffset - - theirdstoffset; - } else { - sp->ats[i] += stdoffset - - theirstdoffset; - } - } - theiroffset = -sp->ttis[j].tt_gmtoff; - if (sp->ttis[j].tt_isdst) - theirdstoffset = theiroffset; - else theirstdoffset = theiroffset; - } - /* - ** Finally, fill in ttis. - ** ttisstd and ttisgmt need not be handled. - */ - sp->ttis[0].tt_gmtoff = -stdoffset; - sp->ttis[0].tt_isdst = FALSE; - sp->ttis[0].tt_abbrind = 0; - sp->ttis[1].tt_gmtoff = -dstoffset; - sp->ttis[1].tt_isdst = TRUE; - sp->ttis[1].tt_abbrind = stdlen + 1; - sp->typecnt = 2; - } - } else { - dstlen = 0; - sp->typecnt = 1; /* only standard time */ - sp->timecnt = 0; - sp->ttis[0].tt_gmtoff = -stdoffset; - sp->ttis[0].tt_isdst = 0; - sp->ttis[0].tt_abbrind = 0; - } - sp->charcnt = stdlen + 1; - if (dstlen != 0) - sp->charcnt += dstlen + 1; - if ((size_t) sp->charcnt > sizeof sp->chars) - return -1; - cp = sp->chars; - (void) strncpy(cp, stdname, stdlen); - cp += stdlen; - *cp++ = '\0'; - if (dstlen != 0) { - (void) strncpy(cp, dstname, dstlen); - *(cp + dstlen) = '\0'; - } - return 0; -} - -static void -gmtload(sp) -struct state * const sp; -{ - if (tzload(gmt, sp, TRUE) != 0) - (void) tzparse(gmt, sp, TRUE); -} - -/* -** The easy way to behave "as if no library function calls" localtime -** is to not call it--so we drop its guts into "localsub", which can be -** freely called. (And no, the PANS doesn't require the above behavior-- -** but it *is* desirable.) -** -** The unused offset argument is for the benefit of mktime variants. -*/ - -/*ARGSUSED*/ -static struct tm * -localsub(timep, offset, tmp, sp) -const time_t * const timep; -const long offset; -struct tm * const tmp; -const struct state * sp; -{ - register const struct ttinfo * ttisp; - register int i; - register struct tm * result; - const time_t t = *timep; - -#ifdef ALL_STATE - if (sp == NULL) - return gmtsub(timep, offset, tmp); -#endif /* defined ALL_STATE */ - if ((sp->goback && t < sp->ats[0]) || - (sp->goahead && t > sp->ats[sp->timecnt - 1])) { - time_t newt = t; - register time_t seconds; - register time_t tcycles; - register int_fast64_t icycles; - - if (t < sp->ats[0]) - seconds = sp->ats[0] - t; - else seconds = t - sp->ats[sp->timecnt - 1]; - --seconds; - tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR; - ++tcycles; - icycles = tcycles; - if (tcycles - icycles >= 1 || icycles - tcycles >= 1) - return NULL; - seconds = icycles; - seconds *= YEARSPERREPEAT; - seconds *= AVGSECSPERYEAR; - if (t < sp->ats[0]) - newt += seconds; - else newt -= seconds; - if (newt < sp->ats[0] || - newt > sp->ats[sp->timecnt - 1]) - return NULL; /* "cannot happen" */ - result = localsub(&newt, offset, tmp, sp); - if (result == tmp) { - register time_t newy; - - newy = tmp->tm_year; - if (t < sp->ats[0]) - newy -= icycles * YEARSPERREPEAT; - else newy += icycles * YEARSPERREPEAT; - tmp->tm_year = newy; - if (tmp->tm_year != newy) - return NULL; - } - return result; - } - if (sp->timecnt == 0 || t < sp->ats[0]) { - i = 0; - while (sp->ttis[i].tt_isdst) - if (++i >= sp->typecnt) { - i = 0; - break; - } - } else { - register int lo = 1; - register int hi = sp->timecnt; - - while (lo < hi) { - register int mid = (lo + hi) >> 1; - - if (t < sp->ats[mid]) - hi = mid; - else lo = mid + 1; - } - i = (int) sp->types[lo - 1]; - } - ttisp = &sp->ttis[i]; - /* - ** To get (wrong) behavior that's compatible with System V Release 2.0 - ** you'd replace the statement below with - ** t += ttisp->tt_gmtoff; - ** timesub(&t, 0L, sp, tmp); - */ - result = timesub(&t, ttisp->tt_gmtoff, sp, tmp); - tmp->tm_isdst = ttisp->tt_isdst; -#ifdef HAVE_TM_GMTOFF - tmp->tm_gmtoff = ttisp->tt_gmtoff; -#endif - tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind]; -#ifdef TM_ZONE - tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind]; -#endif /* defined TM_ZONE */ - return result; -} - - -// ============================================================================ -#if 0 -struct tm * -localtime(timep) -const time_t * const timep; -{ - tzset(); - return localsub(timep, 0L, &tm); -} -#endif - -/* -** Re-entrant version of localtime. -*/ - -// ============================================================================ -void -localtime_tz(const time_t * const timep, struct tm * tmp, const char* tz) -{ - struct state st; - if (tzload(tz, &st, TRUE) != 0) { - // not sure what's best here, but for now, we fall back to gmt - gmtload(&st); - } - - localsub(timep, 0L, tmp, &st); -} - -/* -** gmtsub is to gmtime as localsub is to localtime. -*/ - -static struct tm * -gmtsub(timep, offset, tmp) -const time_t * const timep; -const long offset; -struct tm * const tmp; -{ - register struct tm * result; - - if (!gmt_is_set) { - gmt_is_set = TRUE; -#ifdef ALL_STATE - gmtptr = (struct state *) malloc(sizeof *gmtptr); - if (gmtptr != NULL) -#endif /* defined ALL_STATE */ - gmtload(gmtptr); - } - result = timesub(timep, offset, gmtptr, tmp); -#ifdef TM_ZONE - /* - ** Could get fancy here and deliver something such as - ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero, - ** but this is no time for a treasure hunt. - */ - if (offset != 0) - tmp->TM_ZONE = wildabbr; - else { -#ifdef ALL_STATE - if (gmtptr == NULL) - tmp->TM_ZONE = gmt; - else tmp->TM_ZONE = gmtptr->chars; -#endif /* defined ALL_STATE */ -#ifndef ALL_STATE - tmp->TM_ZONE = gmtptr->chars; -#endif /* State Farm */ - } -#endif /* defined TM_ZONE */ - return result; -} - -// ============================================================================ -#if 0 -struct tm * -gmtime(timep) -const time_t * const timep; -{ - return gmtsub(timep, 0L, &tm); -} -#endif - -/* -* Re-entrant version of gmtime. -*/ - -// ============================================================================ -#if 0 -struct tm * -gmtime_r(timep, tmp) -const time_t * const timep; -struct tm * tmp; -{ - return gmtsub(timep, 0L, tmp); -} -#endif - -#ifdef STD_INSPIRED - -// ============================================================================ -#if 0 -struct tm * -offtime(timep, offset) -const time_t * const timep; -const long offset; -{ - return gmtsub(timep, offset, &tm); -} -#endif - -#endif /* defined STD_INSPIRED */ - -/* -** Return the number of leap years through the end of the given year -** where, to make the math easy, the answer for year zero is defined as zero. -*/ - -static int -leaps_thru_end_of(y) -register const int y; -{ - return (y >= 0) ? (y / 4 - y / 100 + y / 400) : - -(leaps_thru_end_of(-(y + 1)) + 1); -} - -static struct tm * -timesub(timep, offset, sp, tmp) -const time_t * const timep; -const long offset; -register const struct state * const sp; -register struct tm * const tmp; -{ - register const struct lsinfo * lp; - register time_t tdays; - register int idays; /* unsigned would be so 2003 */ - register long rem; - int y; - register const int * ip; - register long corr; - register int hit; - register int i; - - corr = 0; - hit = 0; -#ifdef ALL_STATE - i = (sp == NULL) ? 0 : sp->leapcnt; -#endif /* defined ALL_STATE */ -#ifndef ALL_STATE - i = sp->leapcnt; -#endif /* State Farm */ - while (--i >= 0) { - lp = &sp->lsis[i]; - if (*timep >= lp->ls_trans) { - if (*timep == lp->ls_trans) { - hit = ((i == 0 && lp->ls_corr > 0) || - lp->ls_corr > sp->lsis[i - 1].ls_corr); - if (hit) - while (i > 0 && - sp->lsis[i].ls_trans == - sp->lsis[i - 1].ls_trans + 1 && - sp->lsis[i].ls_corr == - sp->lsis[i - 1].ls_corr + 1) { - ++hit; - --i; - } - } - corr = lp->ls_corr; - break; - } - } - y = EPOCH_YEAR; - tdays = *timep / SECSPERDAY; - rem = *timep - tdays * SECSPERDAY; - while (tdays < 0 || tdays >= year_lengths[isleap(y)]) { - int newy; - register time_t tdelta; - register int idelta; - register int leapdays; - - tdelta = tdays / DAYSPERLYEAR; - idelta = tdelta; - if (tdelta - idelta >= 1 || idelta - tdelta >= 1) - return NULL; - if (idelta == 0) - idelta = (tdays < 0) ? -1 : 1; - newy = y; - if (increment_overflow(&newy, idelta)) - return NULL; - leapdays = leaps_thru_end_of(newy - 1) - - leaps_thru_end_of(y - 1); - tdays -= ((time_t) newy - y) * DAYSPERNYEAR; - tdays -= leapdays; - y = newy; - } - { - register long seconds; - - seconds = tdays * SECSPERDAY + 0.5; - tdays = seconds / SECSPERDAY; - rem += seconds - tdays * SECSPERDAY; - } - /* - ** Given the range, we can now fearlessly cast... - */ - idays = tdays; - rem += offset - corr; - while (rem < 0) { - rem += SECSPERDAY; - --idays; - } - while (rem >= SECSPERDAY) { - rem -= SECSPERDAY; - ++idays; - } - while (idays < 0) { - if (increment_overflow(&y, -1)) - return NULL; - idays += year_lengths[isleap(y)]; - } - while (idays >= year_lengths[isleap(y)]) { - idays -= year_lengths[isleap(y)]; - if (increment_overflow(&y, 1)) - return NULL; - } - tmp->tm_year = y; - if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE)) - return NULL; - tmp->tm_yday = idays; - /* - ** The "extra" mods below avoid overflow problems. - */ - tmp->tm_wday = EPOCH_WDAY + - ((y - EPOCH_YEAR) % DAYSPERWEEK) * - (DAYSPERNYEAR % DAYSPERWEEK) + - leaps_thru_end_of(y - 1) - - leaps_thru_end_of(EPOCH_YEAR - 1) + - idays; - tmp->tm_wday %= DAYSPERWEEK; - if (tmp->tm_wday < 0) - tmp->tm_wday += DAYSPERWEEK; - tmp->tm_hour = (int) (rem / SECSPERHOUR); - rem %= SECSPERHOUR; - tmp->tm_min = (int) (rem / SECSPERMIN); - /* - ** A positive leap second requires a special - ** representation. This uses "... ??:59:60" et seq. - */ - tmp->tm_sec = (int) (rem % SECSPERMIN) + hit; - ip = mon_lengths[isleap(y)]; - for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon)) - idays -= ip[tmp->tm_mon]; - tmp->tm_mday = (int) (idays + 1); - tmp->tm_isdst = 0; -#ifdef TM_GMTOFF - tmp->TM_GMTOFF = offset; -#endif /* defined TM_GMTOFF */ - return tmp; -} - -// ============================================================================ -#if 0 -char * -ctime(timep) -const time_t * const timep; -{ -/* -** Section 4.12.3.2 of X3.159-1989 requires that -** The ctime function converts the calendar time pointed to by timer -** to local time in the form of a string. It is equivalent to -** asctime(localtime(timer)) -*/ - return asctime(localtime(timep)); -} -#endif - -// ============================================================================ -#if 0 -char * -ctime_r(timep, buf) -const time_t * const timep; -char * buf; -{ - struct tm mytm; - - return asctime_r(localtime_r(timep, &mytm), buf); -} -#endif - -/* -** Adapted from code provided by Robert Elz, who writes: -** The "best" way to do mktime I think is based on an idea of Bob -** Kridle's (so its said...) from a long time ago. -** It does a binary search of the time_t space. Since time_t's are -** just 32 bits, its a max of 32 iterations (even at 64 bits it -** would still be very reasonable). -*/ - -#ifndef WRONG -#define WRONG (-1) -#endif /* !defined WRONG */ - -/* -** Simplified normalize logic courtesy Paul Eggert. -*/ - -static int -increment_overflow(number, delta) -int * number; -int delta; -{ - unsigned number0 = (unsigned)*number; - unsigned number1 = (unsigned)(number0 + delta); - - *number = (int)number1; - - if (delta >= 0) { - return ((int)number1 < (int)number0); - } else { - return ((int)number1 > (int)number0); - } -} - -static int -long_increment_overflow(number, delta) -long * number; -int delta; -{ - unsigned long number0 = (unsigned long)*number; - unsigned long number1 = (unsigned long)(number0 + delta); - - *number = (long)number1; - - if (delta >= 0) { - return ((long)number1 < (long)number0); - } else { - return ((long)number1 > (long)number0); - } -} - -static int -normalize_overflow(tensptr, unitsptr, base) -int * const tensptr; -int * const unitsptr; -const int base; -{ - register int tensdelta; - - tensdelta = (*unitsptr >= 0) ? - (*unitsptr / base) : - (-1 - (-1 - *unitsptr) / base); - *unitsptr -= tensdelta * base; - return increment_overflow(tensptr, tensdelta); -} - -static int -long_normalize_overflow(tensptr, unitsptr, base) -long * const tensptr; -int * const unitsptr; -const int base; -{ - register int tensdelta; - - tensdelta = (*unitsptr >= 0) ? - (*unitsptr / base) : - (-1 - (-1 - *unitsptr) / base); - *unitsptr -= tensdelta * base; - return long_increment_overflow(tensptr, tensdelta); -} - -static int -tmcomp(atmp, btmp) -register const struct tm * const atmp; -register const struct tm * const btmp; -{ - register int result; - - if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && - (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && - (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && - (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && - (result = (atmp->tm_min - btmp->tm_min)) == 0) - result = atmp->tm_sec - btmp->tm_sec; - return result; -} - -static time_t -time2sub(tmp, funcp, offset, okayp, do_norm_secs, sp) -struct tm * const tmp; -struct tm * (* const funcp) P((const time_t*, long, struct tm*,const struct state *sp)); -const long offset; -int * const okayp; -const int do_norm_secs; -const struct state * sp; -{ - register int dir; - register int i, j; - register int saved_seconds; - register long li; - register time_t lo; - register time_t hi; - long y; - time_t newt; - time_t t; - struct tm yourtm, mytm; - - *okayp = FALSE; - yourtm = *tmp; - if (do_norm_secs) { - if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec, - SECSPERMIN)) - return WRONG; - } - if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR)) - return WRONG; - if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY)) - return WRONG; - y = yourtm.tm_year; - if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR)) - return WRONG; - /* - ** Turn y into an actual year number for now. - ** It is converted back to an offset from TM_YEAR_BASE later. - */ - if (long_increment_overflow(&y, TM_YEAR_BASE)) - return WRONG; - while (yourtm.tm_mday <= 0) { - if (long_increment_overflow(&y, -1)) - return WRONG; - li = y + (1 < yourtm.tm_mon); - yourtm.tm_mday += year_lengths[isleap(li)]; - } - while (yourtm.tm_mday > DAYSPERLYEAR) { - li = y + (1 < yourtm.tm_mon); - yourtm.tm_mday -= year_lengths[isleap(li)]; - if (long_increment_overflow(&y, 1)) - return WRONG; - } - for ( ; ; ) { - i = mon_lengths[isleap(y)][yourtm.tm_mon]; - if (yourtm.tm_mday <= i) - break; - yourtm.tm_mday -= i; - if (++yourtm.tm_mon >= MONSPERYEAR) { - yourtm.tm_mon = 0; - if (long_increment_overflow(&y, 1)) - return WRONG; - } - } - if (long_increment_overflow(&y, -TM_YEAR_BASE)) - return WRONG; - yourtm.tm_year = y; - if (yourtm.tm_year != y) - return WRONG; - if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN) - saved_seconds = 0; - else if (y + TM_YEAR_BASE < EPOCH_YEAR) { - /* - ** We can't set tm_sec to 0, because that might push the - ** time below the minimum representable time. - ** Set tm_sec to 59 instead. - ** This assumes that the minimum representable time is - ** not in the same minute that a leap second was deleted from, - ** which is a safer assumption than using 58 would be. - */ - if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN)) - return WRONG; - saved_seconds = yourtm.tm_sec; - yourtm.tm_sec = SECSPERMIN - 1; - } else { - saved_seconds = yourtm.tm_sec; - yourtm.tm_sec = 0; - } - /* - ** Do a binary search (this works whatever time_t's type is). - */ - if (!TYPE_SIGNED(time_t)) { - lo = 0; - hi = lo - 1; - } else if (!TYPE_INTEGRAL(time_t)) { - if (sizeof(time_t) > sizeof(float)) - hi = (time_t) DBL_MAX; - else hi = (time_t) FLT_MAX; - lo = -hi; - } else { - lo = 1; - for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i) - lo *= 2; - hi = -(lo + 1); - } - for ( ; ; ) { - t = lo / 2 + hi / 2; - if (t < lo) - t = lo; - else if (t > hi) - t = hi; - if ((*funcp)(&t, offset, &mytm, sp) == NULL) { - /* - ** Assume that t is too extreme to be represented in - ** a struct tm; arrange things so that it is less - ** extreme on the next pass. - */ - dir = (t > 0) ? 1 : -1; - } else dir = tmcomp(&mytm, &yourtm); - if (dir != 0) { - if (t == lo) { - if (t == TIME_T_MAX) - return WRONG; - ++t; - ++lo; - } else if (t == hi) { - if (t == TIME_T_MIN) - return WRONG; - --t; - --hi; - } - if (lo > hi) - return WRONG; - if (dir > 0) - hi = t; - else lo = t; - continue; - } - if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) - break; - /* - ** Right time, wrong type. - ** Hunt for right time, right type. - ** It's okay to guess wrong since the guess - ** gets checked. - */ - /* - ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's. - */ -#ifdef ALL_STATE - if (sp == NULL) - return WRONG; -#endif /* defined ALL_STATE */ - for (i = sp->typecnt - 1; i >= 0; --i) { - if (sp->ttis[i].tt_isdst != yourtm.tm_isdst) - continue; - for (j = sp->typecnt - 1; j >= 0; --j) { - if (sp->ttis[j].tt_isdst == yourtm.tm_isdst) - continue; - newt = t + sp->ttis[j].tt_gmtoff - - sp->ttis[i].tt_gmtoff; - if ((*funcp)(&newt, offset, &mytm, sp) == NULL) - continue; - if (tmcomp(&mytm, &yourtm) != 0) - continue; - if (mytm.tm_isdst != yourtm.tm_isdst) - continue; - /* - ** We have a match. - */ - t = newt; - goto label; - } - } - return WRONG; - } -label: - newt = t + saved_seconds; - if ((newt < t) != (saved_seconds < 0)) - return WRONG; - t = newt; - if ((*funcp)(&t, offset, tmp, sp)) - *okayp = TRUE; - return t; -} - -static time_t -time2(tmp, funcp, offset, okayp, sp) -struct tm * const tmp; -struct tm * (* const funcp) P((const time_t*, long, struct tm*, - const struct state* sp)); -const long offset; -int * const okayp; -const struct state * sp; -{ - time_t t; - - /* - ** First try without normalization of seconds - ** (in case tm_sec contains a value associated with a leap second). - ** If that fails, try with normalization of seconds. - */ - t = time2sub(tmp, funcp, offset, okayp, FALSE, sp); - return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp); -} - -static time_t -time1(tmp, funcp, offset, sp) -struct tm * const tmp; -struct tm * (* const funcp) P((const time_t *, long, struct tm *, const struct state* sp)); -const long offset; -const struct state * sp; -{ - register time_t t; - register int samei, otheri; - register int sameind, otherind; - register int i; - register int nseen; - int seen[TZ_MAX_TYPES]; - int types[TZ_MAX_TYPES]; - int okay; - - if (tmp->tm_isdst > 1) - tmp->tm_isdst = 1; - t = time2(tmp, funcp, offset, &okay, sp); -#define PCTS 1 -#ifdef PCTS - /* - ** PCTS code courtesy Grant Sullivan. - */ - if (okay) - return t; - if (tmp->tm_isdst < 0) - tmp->tm_isdst = 0; /* reset to std and try again */ -#endif /* defined PCTS */ -#ifndef PCTS - if (okay || tmp->tm_isdst < 0) - return t; -#endif /* !defined PCTS */ - /* - ** We're supposed to assume that somebody took a time of one type - ** and did some math on it that yielded a "struct tm" that's bad. - ** We try to divine the type they started from and adjust to the - ** type they need. - */ - /* - ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's. - */ -#ifdef ALL_STATE - if (sp == NULL) - return WRONG; -#endif /* defined ALL_STATE */ - for (i = 0; i < sp->typecnt; ++i) - seen[i] = FALSE; - nseen = 0; - for (i = sp->timecnt - 1; i >= 0; --i) - if (!seen[sp->types[i]]) { - seen[sp->types[i]] = TRUE; - types[nseen++] = sp->types[i]; - } - for (sameind = 0; sameind < nseen; ++sameind) { - samei = types[sameind]; - if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) - continue; - for (otherind = 0; otherind < nseen; ++otherind) { - otheri = types[otherind]; - if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst) - continue; - tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - - sp->ttis[samei].tt_gmtoff; - tmp->tm_isdst = !tmp->tm_isdst; - t = time2(tmp, funcp, offset, &okay, sp); - if (okay) - return t; - tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff - - sp->ttis[samei].tt_gmtoff; - tmp->tm_isdst = !tmp->tm_isdst; - } - } - return WRONG; -} - -// ============================================================================ -time_t -mktime_tz(struct tm * const tmp, char const * tz) -{ - struct state st; - if (tzload(tz, &st, TRUE) != 0) { - // not sure what's best here, but for now, we fall back to gmt - gmtload(&st); - } - return time1(tmp, localsub, 0L, &st); -} From 345cb066d2e0c774c877a85d3035f298df1daf16 Mon Sep 17 00:00:00 2001 From: Benoit Goby Date: Mon, 14 Jan 2013 21:26:30 -0800 Subject: [PATCH 70/89] adb: Read secure adb keys on every auth request The framework can now clear the user key list, so we need to reload the key list on every auth request instead of loading it once when adbd starts. This also fixes issues with encrypted devices, where the user key file is only readable after the user has unlocked the device. Change-Id: I350c5aab986f8ca86b95f316398d03012553e581 --- adb/adb_auth.h | 2 -- adb/adb_auth_client.c | 23 +++++++++++------------ 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/adb/adb_auth.h b/adb/adb_auth.h index 1fffa4976..96f637b9e 100644 --- a/adb/adb_auth.h +++ b/adb/adb_auth.h @@ -36,7 +36,6 @@ int adb_auth_get_userkey(unsigned char *data, size_t len); static inline int adb_auth_generate_token(void *token, size_t token_size) { return 0; } static inline int adb_auth_verify(void *token, void *sig, int siglen) { return 0; } static inline void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t) { } -static inline void adb_auth_reload_keys(void) { } #else // !ADB_HOST @@ -47,7 +46,6 @@ static inline int adb_auth_get_userkey(unsigned char *data, size_t len) { return int adb_auth_generate_token(void *token, size_t token_size); int adb_auth_verify(void *token, void *sig, int siglen); void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t); -void adb_auth_reload_keys(void); #endif // ADB_HOST diff --git a/adb/adb_auth_client.c b/adb/adb_auth_client.c index 0b4913ef4..a4ad18fd9 100644 --- a/adb/adb_auth_client.c +++ b/adb/adb_auth_client.c @@ -34,8 +34,6 @@ struct adb_public_key { RSAPublicKey key; }; -static struct listnode key_list; - static char *key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", @@ -102,18 +100,18 @@ static void free_keys(struct listnode *list) } } -void adb_auth_reload_keys(void) +static void load_keys(struct listnode *list) { char *path; char **paths = key_paths; struct stat buf; - free_keys(&key_list); + list_init(list); while ((path = *paths++)) { if (!stat(path, &buf)) { D("Loading keys from '%s'\n", path); - read_keys(path, &key_list); + read_keys(path, list); } } } @@ -137,19 +135,24 @@ int adb_auth_verify(void *token, void *sig, int siglen) { struct listnode *item; struct adb_public_key *key; - int ret; + struct listnode key_list; + int ret = 0; if (siglen != RSANUMBYTES) return 0; + load_keys(&key_list); + list_for_each(item, &key_list) { key = node_to_item(item, struct adb_public_key, node); ret = RSA_verify(&key->key, sig, siglen, token); if (ret) - return 1; + break; } - return 0; + free_keys(&key_list); + + return ret; } static void adb_auth_event(int fd, unsigned events, void *data) @@ -166,7 +169,6 @@ static void adb_auth_event(int fd, unsigned events, void *data) framework_fd = -1; } else if (ret == 2 && response[0] == 'O' && response[1] == 'K') { - adb_auth_reload_keys(); adb_auth_verified(t); } } @@ -225,9 +227,6 @@ void adb_auth_init(void) { int fd, ret; - list_init(&key_list); - adb_auth_reload_keys(); - fd = android_get_control_socket("adbd"); if (fd < 0) { D("Failed to get adbd socket\n"); From 77e8e5851d3b951b5382663bd50f1f83cb531eb2 Mon Sep 17 00:00:00 2001 From: Benoit Goby Date: Tue, 15 Jan 2013 12:36:47 -0800 Subject: [PATCH 71/89] adb: Add "unauthorized" connection state Add a new connection state, so that devices, that require confirmation to allow adb, appear as "unauthorized" in the adb devices lists. Change-Id: Ib4264bc5736dedecf05bcf8e31896f4d7a91fad8 --- adb/adb.c | 3 +++ adb/adb.h | 1 + adb/transport.c | 7 +++++++ 3 files changed, 11 insertions(+) diff --git a/adb/adb.c b/adb/adb.c index 8be576567..744e847fa 100644 --- a/adb/adb.c +++ b/adb/adb.c @@ -402,6 +402,8 @@ static char *connection_state_name(atransport *t) return "device"; case CS_OFFLINE: return "offline"; + case CS_UNAUTHORIZED: + return "unauthorized"; default: return "unknown"; } @@ -531,6 +533,7 @@ void handle_packet(apacket *p, atransport *t) case A_AUTH: if (p->msg.arg0 == ADB_AUTH_TOKEN) { + t->connection_state = CS_UNAUTHORIZED; t->key = adb_auth_nextkey(t->key); if (t->key) { send_auth_response(p->data, p->msg.data_length, t); diff --git a/adb/adb.h b/adb/adb.h index 9da8af8bf..a01d460e4 100644 --- a/adb/adb.h +++ b/adb/adb.h @@ -468,6 +468,7 @@ int connection_state(atransport *t); #define CS_RECOVERY 4 #define CS_NOPERM 5 /* Insufficient permissions to communicate with the device */ #define CS_SIDELOAD 6 +#define CS_UNAUTHORIZED 7 extern int HOST; extern int SHELL_EXIT_NOTIFY_FD; diff --git a/adb/transport.c b/adb/transport.c index 9fd6cc2e6..b4abb66ec 100644 --- a/adb/transport.c +++ b/adb/transport.c @@ -851,6 +851,12 @@ retry: adb_mutex_unlock(&transport_lock); if (result) { + if (result->connection_state == CS_UNAUTHORIZED) { + if (error_out) + *error_out = "device unauthorized. Please check the confirmation dialog on your device."; + result = NULL; + } + /* offline devices are ignored -- they are either being born or dying */ if (result && result->connection_state == CS_OFFLINE) { if (error_out) @@ -888,6 +894,7 @@ static const char *statename(atransport *t) case CS_RECOVERY: return "recovery"; case CS_SIDELOAD: return "sideload"; case CS_NOPERM: return "no permissions"; + case CS_UNAUTHORIZED: return "unauthorized"; default: return "unknown"; } } From 31c8095cac4cd652c360feb85c47854363233a1c Mon Sep 17 00:00:00 2001 From: Benoit Goby Date: Tue, 15 Jan 2013 15:01:12 -0800 Subject: [PATCH 72/89] Revert "init.usb.rc: set sys.usb.config to none before changing it" This can cause init to be stucked in a loop in very rare cases where persist.sys.usb.config is set to "none" (because the "setprop sys.usb.config none" action is added twice to the action list). The original issue on encrypted devices has been fixed differently by change # I350c5aab986f8ca86b95f316398d03012553e581 This reverts commit 80828af3def1f37eff1d483520df79ebe4238d55. Change-Id: Id0a7af8dd861c8d10b80a13b540c8a339b432007 --- rootdir/init.usb.rc | 1 - 1 file changed, 1 deletion(-) diff --git a/rootdir/init.usb.rc b/rootdir/init.usb.rc index f37b630bc..15467cc21 100644 --- a/rootdir/init.usb.rc +++ b/rootdir/init.usb.rc @@ -88,5 +88,4 @@ on property:sys.usb.config=accessory,audio_source,adb # Used to set USB configuration at boot and to switch the configuration # when changing the default configuration on property:persist.sys.usb.config=* - setprop sys.usb.config none setprop sys.usb.config ${persist.sys.usb.config} From 51e06618dbd87c4374c56d9193a5e567aa3d02ac Mon Sep 17 00:00:00 2001 From: Nick Kralevich Date: Fri, 18 Jan 2013 14:31:19 -0800 Subject: [PATCH 73/89] init: make system properties more secure. Currently, system properties are passed via the environment variable ANDROID_PROPERTY_WORKSPACE and a file descriptor passed from parent to child. This is insecure for setuid executables, as the environment variable can be changed by the caller. Modify system property handling so that we get the properties from a root owned properties file, rather than using an environment variable. Related to bug: 8029617 Change-Id: I18610128e11c4037ed6f4dec6eba20f69fa647eb --- init/init.c | 5 ----- init/property_service.c | 24 ++++-------------------- init/property_service.h | 1 - 3 files changed, 4 insertions(+), 26 deletions(-) diff --git a/init/init.c b/init/init.c index 2fbe00219..bc88ba952 100755 --- a/init/init.c +++ b/init/init.c @@ -233,11 +233,6 @@ void service_start(struct service *svc, const char *dynamic_args) int fd, sz; umask(077); - if (properties_inited()) { - get_property_workspace(&fd, &sz); - sprintf(tmp, "%d,%d", dup(fd), sz); - add_environment("ANDROID_PROPERTY_WORKSPACE", tmp); - } for (ei = svc->envvars; ei; ei = ei->next) add_environment(ei->name, ei->value); diff --git a/init/property_service.c b/init/property_service.c index 61dd86fdc..b608d2f58 100755 --- a/init/property_service.c +++ b/init/property_service.c @@ -112,7 +112,6 @@ struct { typedef struct { void *data; size_t size; - int fd; } workspace; static int init_workspace(workspace *w, size_t size) @@ -120,10 +119,10 @@ static int init_workspace(workspace *w, size_t size) void *data; int fd; - /* dev is a tmpfs that we can use to carve a shared workspace - * out of, so let's do that... - */ - fd = open("/dev/__properties__", O_RDWR | O_CREAT | O_NOFOLLOW, 0600); + /* dev is a tmpfs that we can use to carve a shared workspace + * out of, so let's do that... + */ + fd = open(PROP_FILENAME, O_RDWR | O_CREAT | O_NOFOLLOW, 0644); if (fd < 0) return -1; @@ -136,15 +135,8 @@ static int init_workspace(workspace *w, size_t size) close(fd); - fd = open("/dev/__properties__", O_RDONLY | O_NOFOLLOW); - if (fd < 0) - return -1; - - unlink("/dev/__properties__"); - w->data = data; w->size = size; - w->fd = fd; return 0; out: @@ -174,8 +166,6 @@ static int init_property_area(void) if(init_workspace(&pa_workspace, PA_SIZE)) return -1; - fcntl(pa_workspace.fd, F_SETFD, FD_CLOEXEC); - pa_info_array = (void*) (((char*) pa_workspace.data) + PA_INFO_START); pa = pa_workspace.data; @@ -463,12 +453,6 @@ void handle_property_set_fd() } } -void get_property_workspace(int *fd, int *sz) -{ - *fd = pa_workspace.fd; - *sz = pa_workspace.size; -} - static void load_properties(char *data) { char *key, *value, *eol, *sol, *tmp; diff --git a/init/property_service.h b/init/property_service.h index b9d1bf610..df71f3f95 100644 --- a/init/property_service.h +++ b/init/property_service.h @@ -24,7 +24,6 @@ extern void property_init(void); extern void property_load_boot_defaults(void); extern void load_persist_props(void); extern void start_property_service(void); -void get_property_workspace(int *fd, int *sz); extern const char* property_get(const char *name); extern int property_set(const char *name, const char *value); extern int properties_inited(); From 2840647b15fe91069aee02ce0e203943346bf294 Mon Sep 17 00:00:00 2001 From: Nick Kralevich Date: Tue, 22 Jan 2013 12:46:09 -0800 Subject: [PATCH 74/89] Revert "init: make system properties more secure." This reverts commit 51e06618dbd87c4374c56d9193a5e567aa3d02ac. Bug: 8045561 --- init/init.c | 5 +++++ init/property_service.c | 24 ++++++++++++++++++++---- init/property_service.h | 1 + 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/init/init.c b/init/init.c index bc88ba952..2fbe00219 100755 --- a/init/init.c +++ b/init/init.c @@ -233,6 +233,11 @@ void service_start(struct service *svc, const char *dynamic_args) int fd, sz; umask(077); + if (properties_inited()) { + get_property_workspace(&fd, &sz); + sprintf(tmp, "%d,%d", dup(fd), sz); + add_environment("ANDROID_PROPERTY_WORKSPACE", tmp); + } for (ei = svc->envvars; ei; ei = ei->next) add_environment(ei->name, ei->value); diff --git a/init/property_service.c b/init/property_service.c index b608d2f58..61dd86fdc 100755 --- a/init/property_service.c +++ b/init/property_service.c @@ -112,6 +112,7 @@ struct { typedef struct { void *data; size_t size; + int fd; } workspace; static int init_workspace(workspace *w, size_t size) @@ -119,10 +120,10 @@ static int init_workspace(workspace *w, size_t size) void *data; int fd; - /* dev is a tmpfs that we can use to carve a shared workspace - * out of, so let's do that... - */ - fd = open(PROP_FILENAME, O_RDWR | O_CREAT | O_NOFOLLOW, 0644); + /* dev is a tmpfs that we can use to carve a shared workspace + * out of, so let's do that... + */ + fd = open("/dev/__properties__", O_RDWR | O_CREAT | O_NOFOLLOW, 0600); if (fd < 0) return -1; @@ -135,8 +136,15 @@ static int init_workspace(workspace *w, size_t size) close(fd); + fd = open("/dev/__properties__", O_RDONLY | O_NOFOLLOW); + if (fd < 0) + return -1; + + unlink("/dev/__properties__"); + w->data = data; w->size = size; + w->fd = fd; return 0; out: @@ -166,6 +174,8 @@ static int init_property_area(void) if(init_workspace(&pa_workspace, PA_SIZE)) return -1; + fcntl(pa_workspace.fd, F_SETFD, FD_CLOEXEC); + pa_info_array = (void*) (((char*) pa_workspace.data) + PA_INFO_START); pa = pa_workspace.data; @@ -453,6 +463,12 @@ void handle_property_set_fd() } } +void get_property_workspace(int *fd, int *sz) +{ + *fd = pa_workspace.fd; + *sz = pa_workspace.size; +} + static void load_properties(char *data) { char *key, *value, *eol, *sol, *tmp; diff --git a/init/property_service.h b/init/property_service.h index df71f3f95..b9d1bf610 100644 --- a/init/property_service.h +++ b/init/property_service.h @@ -24,6 +24,7 @@ extern void property_init(void); extern void property_load_boot_defaults(void); extern void load_persist_props(void); extern void start_property_service(void); +void get_property_workspace(int *fd, int *sz); extern const char* property_get(const char *name); extern int property_set(const char *name, const char *value); extern int properties_inited(); From fdf2f337805b0b9c6ebdf57540b2b70bb1eb64dd Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Wed, 5 Dec 2012 15:19:07 -0800 Subject: [PATCH 75/89] libsuspend: compile as a static library Compile libsuspend as a static library as well, currently needed by the charger code in some cases. Related-to-bug: 7429504 Change-Id: I113017c2c855f915b77c76d8934b6e57c0bb532c Signed-off-by: Iliyan Malchev --- libsuspend/Android.mk | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libsuspend/Android.mk b/libsuspend/Android.mk index 45cb70116..a2fa3e0d8 100644 --- a/libsuspend/Android.mk +++ b/libsuspend/Android.mk @@ -12,7 +12,6 @@ libsuspend_libraries := \ liblog libcutils include $(CLEAR_VARS) - LOCAL_SRC_FILES := $(libsuspend_src_files) LOCAL_MODULE := libsuspend LOCAL_MODULE_TAGS := optional @@ -21,3 +20,12 @@ LOCAL_C_INCLUDES += $(LOCAL_PATH)/include LOCAL_SHARED_LIBRARIES := $(libsuspend_libraries) #LOCAL_CFLAGS += -DLOG_NDEBUG=0 include $(BUILD_SHARED_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := $(libsuspend_src_files) +LOCAL_MODULE := libsuspend +LOCAL_MODULE_TAGS := optional +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include +LOCAL_C_INCLUDES += $(LOCAL_PATH)/include +#LOCAL_CFLAGS += -DLOG_NDEBUG=0 +include $(BUILD_STATIC_LIBRARY) From 4db7df71da5641dfa6c89543b9843dca1999d78e Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 22 Jan 2013 15:41:58 -0800 Subject: [PATCH 76/89] toolbox: renice: Add -t TYPE parameter and switch to getopt Change-Id: Idaedabe1505a9c373629ef1fd31aa4b4beb068c2 Signed-off-by: Dmitry Shmidt --- toolbox/renice.c | 64 ++++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/toolbox/renice.c b/toolbox/renice.c index 978b3295c..9dfeb51f9 100644 --- a/toolbox/renice.c +++ b/toolbox/renice.c @@ -35,11 +35,12 @@ #include #include #include +#include static void usage(const char *s) { - fprintf(stderr, "USAGE: %s [[-r] priority pids ...] [-g pid]\n", s); + fprintf(stderr, "USAGE: %s [[-r] [-t TYPE] priority pids ...] [-g pid]\n", s); exit(EXIT_FAILURE); } @@ -74,32 +75,49 @@ void print_prio(pid_t pid) sched_get_priority_min(sched), sched_get_priority_max(sched)); } +int get_sched(char *str) +{ + if (strcasecmp(str, "RR") == 0) + return SCHED_RR; + else if (strcasecmp(str, "FIFO") == 0) + return SCHED_FIFO; + else if (strcasecmp(str, "NORMAL") == 0) + return SCHED_OTHER; + else if (strcasecmp(str, "OTHER") == 0) + return SCHED_OTHER; + return SCHED_RR; +} + int renice_main(int argc, char *argv[]) { int prio; int realtime = 0; + int opt; + int sched = SCHED_RR; char *cmd = argv[0]; - // consume command name - argc--; - argv++; - - if (argc < 1) - usage(cmd); - - if(strcmp("-r", argv[0]) == 0) { - // do realtime priority adjustment - realtime = 1; - argc--; - argv++; - } - - if(strcmp("-g", argv[0]) == 0) { - if (argc < 2) + do { + opt = getopt(argc, argv, "rt:g:"); + if (opt == -1) + break; + switch (opt) { + case 'r': + // do realtime priority adjustment + realtime = 1; + break; + case 't': + sched = get_sched(optarg); + break; + case 'g': + print_prio(atoi(optarg)); + return 0; + default: usage(cmd); - print_prio(atoi(argv[1])); - return 0; - } + } + } while (1); + + argc -= optind; + argv += optind; if (argc < 1) usage(cmd); @@ -122,7 +140,7 @@ int renice_main(int argc, char *argv[]) struct sched_param sp = { .sched_priority = prio }; int ret; - ret = sched_setscheduler(pid, SCHED_RR, &sp); + ret = sched_setscheduler(pid, sched, &sp); if (ret) { perror("sched_set_scheduler"); exit(EXIT_FAILURE); @@ -137,8 +155,6 @@ int renice_main(int argc, char *argv[]) } } } - + return 0; } - - From 7ece0a862cf97e85bbe69458a32a2bd165456874 Mon Sep 17 00:00:00 2001 From: Nick Kralevich Date: Wed, 23 Jan 2013 09:24:33 -0800 Subject: [PATCH 77/89] property_service: make /dev/__properties__ readable Currently, system properties are passed via the environment variable ANDROID_PROPERTY_WORKSPACE and a file descriptor passed from parent to child. This is insecure for setuid executables, as the environment variable can be changed by the caller. Make the /dev/__properties__ file accessible, so an app can get properties directly from the file, rather than relying on environment variables. Preserve the environment variable for compatibility with pre-existing apps. Bug: 8045561 Change-Id: If81e2b705eca43ddd8b491871aceff59c0e00387 --- init/property_service.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/init/property_service.c b/init/property_service.c index 61dd86fdc..578000154 100755 --- a/init/property_service.c +++ b/init/property_service.c @@ -123,7 +123,7 @@ static int init_workspace(workspace *w, size_t size) /* dev is a tmpfs that we can use to carve a shared workspace * out of, so let's do that... */ - fd = open("/dev/__properties__", O_RDWR | O_CREAT | O_NOFOLLOW, 0600); + fd = open(PROP_FILENAME, O_RDWR | O_CREAT | O_NOFOLLOW, 0644); if (fd < 0) return -1; @@ -136,12 +136,10 @@ static int init_workspace(workspace *w, size_t size) close(fd); - fd = open("/dev/__properties__", O_RDONLY | O_NOFOLLOW); + fd = open(PROP_FILENAME, O_RDONLY | O_NOFOLLOW); if (fd < 0) return -1; - unlink("/dev/__properties__"); - w->data = data; w->size = size; w->fd = fd; From 2aaf5e84f004739858f5454e42cc88fd92e4f779 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 23 Jan 2013 15:41:08 -0800 Subject: [PATCH 78/89] fastboot: use better exported api from libext4_utils Switch fastboot to use an exported api from libext4_utils that will change less often, and remove some of the implementation details from fastboot. Change-Id: I85a10c8f58abe8093d0c781e1a0e100c348ef0d9 --- fastboot/engine.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/fastboot/engine.c b/fastboot/engine.c index 7a5526033..6c636cd73 100644 --- a/fastboot/engine.c +++ b/fastboot/engine.c @@ -45,8 +45,6 @@ #include #endif -extern struct fs_info info; - #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) double now() @@ -302,10 +300,7 @@ void generate_ext4_image(struct image_data *image) #else fd = fileno(tmpfile()); #endif - /* reset ext4fs info so we can be called multiple times */ - reset_ext4fs_info(); - info.len = image->partition_size; - make_ext4fs_internal(fd, NULL, NULL, NULL, 0, 1, 0, 0, 0, NULL); + make_ext4fs_sparse_fd(fd, image->partition_size, NULL, NULL); fstat(fd, &st); image->image_size = st.st_size; From 81c632e4dacb14c4afa8a1f166faa1bbacce4d8f Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 23 Jan 2013 19:13:43 -0800 Subject: [PATCH 79/89] fastboot: add errno.h to fix windows build The removal of extra headers from ext4_utils.h removed an indirect include of errno.h that breaks building with USE_MINGW=1. Change-Id: Ic8448db97b5c056a139dc836e1d6f3aaafb917c9 --- fastboot/engine.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fastboot/engine.c b/fastboot/engine.c index 6c636cd73..8d469911a 100644 --- a/fastboot/engine.c +++ b/fastboot/engine.c @@ -29,6 +29,7 @@ #include "fastboot.h" #include "make_ext4fs.h" +#include #include #include #include From 46d079dd8c974cb28d52b052158c2843d4125756 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 25 Jan 2013 15:39:33 -0800 Subject: [PATCH 80/89] libcorkscrew will always HAVE_DLADDR. The only place we don't have dladdr(3) is Windows, and libcorkscrew is for Unix. Change-Id: If7633ee8398bccf9897add728facbe07592c0fcf --- libcorkscrew/backtrace.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libcorkscrew/backtrace.c b/libcorkscrew/backtrace.c index 3697d18de..03dbd53c4 100644 --- a/libcorkscrew/backtrace.c +++ b/libcorkscrew/backtrace.c @@ -35,10 +35,8 @@ #include #include -#if HAVE_DLADDR #define __USE_GNU // For dladdr(3) in glibc. #include -#endif #if defined(__BIONIC__) @@ -256,7 +254,6 @@ void get_backtrace_symbols(const backtrace_frame_t* backtrace, size_t frames, if (mi->name[0]) { symbol->map_name = strdup(mi->name); } -#if HAVE_DLADDR Dl_info info; if (dladdr((const void*)frame->absolute_pc, &info) && info.dli_sname) { symbol->relative_symbol_addr = (uintptr_t)info.dli_saddr @@ -264,7 +261,6 @@ void get_backtrace_symbols(const backtrace_frame_t* backtrace, size_t frames, symbol->symbol_name = strdup(info.dli_sname); symbol->demangled_name = demangle_symbol_name(symbol->symbol_name); } -#endif } } release_my_map_info_list(milist); From 0cc2cab6af2635e3293b3611a4c0982061dbb935 Mon Sep 17 00:00:00 2001 From: Rom Lemarchand Date: Wed, 16 Jan 2013 12:08:04 -0800 Subject: [PATCH 81/89] logwrapper: switch to signal handlers for SIGCHLD Switch to a signal handler to monitor SIGCHLD. Also, clean up the exit path and log a warning when the previous SIGCHLD sigaction is not default or ignore. Change-Id: I7ef7daabee18d80e9e82fba3943cf1d03b504ae3 --- logwrapper/logwrap.c | 213 +++++++++++++++++++++++++++---------------- 1 file changed, 136 insertions(+), 77 deletions(-) diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c index c2b36be29..9cd3fe4cc 100644 --- a/logwrapper/logwrap.c +++ b/logwrapper/logwrap.c @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include #include @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "private/android_filesystem_config.h" @@ -33,83 +34,104 @@ #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) -static int fatal(const char *msg) { +static int signal_fd_write; + +static void fatal(const char *msg) { fprintf(stderr, "%s", msg); ALOG(LOG_ERROR, "logwrapper", "%s", msg); - return -1; } static int parent(const char *tag, int parent_read, int signal_fd, pid_t pid, int *chld_sts) { - int status; + int status = 0; char buffer[4096]; struct pollfd poll_fds[] = { [0] = { - .fd = parent_read, - .events = POLLIN, - }, - [1] = { .fd = signal_fd, .events = POLLIN, }, + [1] = { + .fd = parent_read, + .events = POLLIN, + }, }; + int rc = 0; + sigset_t chldset; int a = 0; // start index of unprocessed data int b = 0; // end index of unprocessed data int sz; + bool remote_hung = false; + bool found_child = false; char *btag = basename(tag); if (!btag) btag = (char*) tag; - while (1) { - if (poll(poll_fds, ARRAY_SIZE(poll_fds), -1) <= 0) { - return fatal("poll failed\n"); + sigemptyset(&chldset); + sigaddset(&chldset, SIGCHLD); + sigprocmask(SIG_UNBLOCK, &chldset, NULL); + + while (!found_child) { + if (poll(poll_fds, remote_hung ? 1 : 2, -1) < 0) { + if (errno == EINTR) + continue; + fatal("poll failed\n"); + rc = -1; + goto err_poll; } - if (poll_fds[0].revents & POLLIN) { - sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b); + if (!remote_hung) { + if (poll_fds[1].revents & POLLIN) { + sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b); - sz += b; - // Log one line at a time - for (b = 0; b < sz; b++) { - if (buffer[b] == '\r') { - buffer[b] = '\0'; - } else if (buffer[b] == '\n') { + sz += b; + // Log one line at a time + for (b = 0; b < sz; b++) { + if (buffer[b] == '\r') { + buffer[b] = '\0'; + } else if (buffer[b] == '\n') { + buffer[b] = '\0'; + ALOG(LOG_INFO, btag, "%s", &buffer[a]); + a = b + 1; + } + } + + if (a == 0 && b == sizeof(buffer) - 1) { + // buffer is full, flush buffer[b] = '\0'; ALOG(LOG_INFO, btag, "%s", &buffer[a]); - a = b + 1; + b = 0; + } else if (a != b) { + // Keep left-overs + b -= a; + memmove(buffer, &buffer[a], b); + a = 0; + } else { + a = 0; + b = 0; } } - if (a == 0 && b == sizeof(buffer) - 1) { - // buffer is full, flush - buffer[b] = '\0'; - ALOG(LOG_INFO, btag, "%s", &buffer[a]); - b = 0; - } else if (a != b) { - // Keep left-overs - b -= a; - memmove(buffer, &buffer[a], b); - a = 0; - } else { - a = 0; - b = 0; + if (poll_fds[1].revents & POLLHUP) { + remote_hung = true; } } - if (poll_fds[1].revents & POLLIN) { - struct signalfd_siginfo sfd_info; - pid_t wpid; + if (poll_fds[0].revents & POLLIN) { + char tmp[32]; + int ret; - // Clear all pending signals before reading the child's status - while (read(signal_fd, &sfd_info, sizeof(sfd_info)) > 0) { - if ((pid_t)sfd_info.ssi_pid != pid) - ALOG(LOG_WARN, "logwrapper", "cleared SIGCHLD for pid %u\n", - sfd_info.ssi_pid); + read(signal_fd, tmp, sizeof(tmp)); + while (!found_child) { + do { + ret = waitpid(-1, &status, WNOHANG); + } while (ret < 0 && errno == EINTR); + + if (ret <= 0) + break; + + found_child = (pid == ret); } - wpid = waitpid(pid, &status, WNOHANG); - if (wpid > 0) - break; } } @@ -121,19 +143,20 @@ static int parent(const char *tag, int parent_read, int signal_fd, pid_t pid, if (WIFEXITED(status)) { if (WEXITSTATUS(status)) - ALOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", tag, + ALOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", btag, WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { - ALOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag, + ALOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", btag, WTERMSIG(status)); } else if (WIFSTOPPED(status)) { - ALOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag, + ALOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", btag, WSTOPSIG(status)); } if (chld_sts != NULL) *chld_sts = status; - return 0; +err_poll: + return rc; } static void child(int argc, char* argv[]) { @@ -149,40 +172,54 @@ static void child(int argc, char* argv[]) { } } +void sigchld_handler(int sig) { + write(signal_fd_write, &sig, 1); +} + int logwrap(int argc, char* argv[], int *status) { pid_t pid; - int parent_ptty; int child_ptty; char *child_devname = NULL; - sigset_t chldset; + struct sigaction chldact; + struct sigaction oldchldact; + sigset_t blockset; + sigset_t oldset; + int sockets[2]; + int rc = 0; /* Use ptty instead of socketpair so that STDOUT is not buffered */ parent_ptty = open("/dev/ptmx", O_RDWR); if (parent_ptty < 0) { - return fatal("Cannot create parent ptty\n"); + fatal("Cannot create parent ptty\n"); + rc = -1; + goto err_open; } if (grantpt(parent_ptty) || unlockpt(parent_ptty) || ((child_devname = (char*)ptsname(parent_ptty)) == 0)) { - return fatal("Problem with /dev/ptmx\n"); + fatal("Problem with /dev/ptmx\n"); + rc = -1; + goto err_ptty; } - sigemptyset(&chldset); - sigaddset(&chldset, SIGCHLD); - sigprocmask(SIG_BLOCK, &chldset, NULL); + sigemptyset(&blockset); + sigaddset(&blockset, SIGCHLD); + sigprocmask(SIG_BLOCK, &blockset, &oldset); pid = fork(); if (pid < 0) { - close(parent_ptty); - sigprocmask(SIG_UNBLOCK, &chldset, NULL); - return fatal("Failed to fork\n"); + fatal("Failed to fork\n"); + rc = -1; + goto err_fork; } else if (pid == 0) { + sigprocmask(SIG_SETMASK, &oldset, NULL); close(parent_ptty); - sigprocmask(SIG_UNBLOCK, &chldset, NULL); + child_ptty = open(child_devname, O_RDWR); if (child_ptty < 0) { - return fatal("Problem with child ptty\n"); + fatal("Problem with child ptty\n"); + return -1; } // redirect stdout and stderr @@ -191,35 +228,57 @@ int logwrap(int argc, char* argv[], int *status) { close(child_ptty); child(argc - 1, &argv[1]); - return fatal("This should never happen\n"); - + fatal("This should never happen\n"); + return -1; } else { - int rc; - int fd; + memset(&chldact, 0, sizeof(chldact)); + chldact.sa_handler = sigchld_handler; + chldact.sa_flags = SA_NOCLDSTOP; - fd = signalfd(-1, &chldset, SFD_NONBLOCK); - if (fd == -1) { + sigaction(SIGCHLD, &chldact, &oldchldact); + if ((!(oldchldact.sa_flags & SA_SIGINFO) && + oldchldact.sa_handler != SIG_DFL && + oldchldact.sa_handler != SIG_IGN) || + ((oldchldact.sa_flags & SA_SIGINFO) && + oldchldact.sa_sigaction != NULL)) { + ALOG(LOG_WARN, "logwrapper", "logwrap replaced the SIGCHLD " + "handler and might cause interaction issues"); + } + + rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); + if (rc == -1) { char msg[40]; - snprintf(msg, sizeof(msg), "signalfd failed: %d\n", errno); + snprintf(msg, sizeof(msg), "socketpair failed: %d\n", errno); - close(parent_ptty); - sigprocmask(SIG_UNBLOCK, &chldset, NULL); - return fatal(msg); + fatal(msg); + goto err_socketpair; } + fcntl(sockets[0], F_SETFD, FD_CLOEXEC); + fcntl(sockets[0], F_SETFL, O_NONBLOCK); + fcntl(sockets[1], F_SETFD, FD_CLOEXEC); + fcntl(sockets[1], F_SETFL, O_NONBLOCK); + + signal_fd_write = sockets[0]; + // switch user and group to "log" // this may fail if we are not root, // but in that case switching user/group is unnecessary setgid(AID_LOG); setuid(AID_LOG); - rc = parent(argv[1], parent_ptty, fd, pid, status); - close(parent_ptty); - close(fd); - - sigprocmask(SIG_UNBLOCK, &chldset, NULL); - - return rc; + rc = parent(argv[1], parent_ptty, sockets[1], pid, status); } + + close(sockets[0]); + close(sockets[1]); +err_socketpair: + sigaction(SIGCHLD, &oldchldact, NULL); +err_fork: + sigprocmask(SIG_SETMASK, &oldset, NULL); +err_ptty: + close(parent_ptty); +err_open: + return rc; } From 611f5b4b938f2ffcf2a2e71a847e4fd12587ca4b Mon Sep 17 00:00:00 2001 From: Rom Lemarchand Date: Mon, 14 Jan 2013 14:11:01 -0800 Subject: [PATCH 82/89] logwrap: fix off by 1 argument error Fix off by 1 argument parsing error in liblogwrap. Change-Id: I79832ae338a71c445f9f616d780c577826874386 --- logwrapper/logwrap.c | 4 ++-- logwrapper/logwrapper.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c index 9cd3fe4cc..09f8b814c 100644 --- a/logwrapper/logwrap.c +++ b/logwrapper/logwrap.c @@ -227,7 +227,7 @@ int logwrap(int argc, char* argv[], int *status) { dup2(child_ptty, 2); close(child_ptty); - child(argc - 1, &argv[1]); + child(argc, argv); fatal("This should never happen\n"); return -1; } else { @@ -268,7 +268,7 @@ int logwrap(int argc, char* argv[], int *status) { setgid(AID_LOG); setuid(AID_LOG); - rc = parent(argv[1], parent_ptty, sockets[1], pid, status); + rc = parent(argv[0], parent_ptty, sockets[1], pid, status); } close(sockets[0]); diff --git a/logwrapper/logwrapper.c b/logwrapper/logwrapper.c index 4f1bff9d4..e647b4d32 100644 --- a/logwrapper/logwrapper.c +++ b/logwrapper/logwrapper.c @@ -59,7 +59,7 @@ int main(int argc, char* argv[]) { usage(); } - rc = logwrap(argc, argv, &status); + rc = logwrap(argc - 1, &argv[1], &status); if (!rc) { if (WIFEXITED(status)) rc = WEXITSTATUS(status); From cfb5ec3c283bb0fd5a99d6ed282a508be309d291 Mon Sep 17 00:00:00 2001 From: Rom Lemarchand Date: Fri, 11 Jan 2013 14:56:44 -0800 Subject: [PATCH 83/89] logwrap: remove unnecessary call to setuid/setgid Android allows all users to write to log. The setuid/setgid call is unneeded and could cause unintended side effects when called from daemons or programs that need to run as root. Change-Id: I3bdb26eaa4363ef037615e45a1a5cb1ceb4088f3 --- logwrapper/logwrap.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c index 09f8b814c..ef457def5 100644 --- a/logwrapper/logwrap.c +++ b/logwrapper/logwrap.c @@ -262,12 +262,6 @@ int logwrap(int argc, char* argv[], int *status) { signal_fd_write = sockets[0]; - // switch user and group to "log" - // this may fail if we are not root, - // but in that case switching user/group is unnecessary - setgid(AID_LOG); - setuid(AID_LOG); - rc = parent(argv[0], parent_ptty, sockets[1], pid, status); } From c0d399df697850712432cb6092d63669ffa0fc23 Mon Sep 17 00:00:00 2001 From: Wink Saville Date: Mon, 28 Jan 2013 15:28:20 -0800 Subject: [PATCH 84/89] Delete frameworks/base/voip use voip-common from frameworks/opt/net/voip Add voip-common to BOOTCLASSPATH Change-Id: Ieaba759a0f69b45c4b8839cbed1fe757cdf190c5 --- rootdir/init.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rootdir/init.rc b/rootdir/init.rc index bee072933..f866ad1d1 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -37,7 +37,7 @@ loglevel 3 export ANDROID_STORAGE /storage export ASEC_MOUNTPOINT /mnt/asec export LOOP_MOUNTPOINT /mnt/obb - export BOOTCLASSPATH /system/framework/core.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/telephony-common.jar:/system/framework/mms-common.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/apache-xml.jar + export BOOTCLASSPATH /system/framework/core.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/telephony-common.jar:/system/framework/voip-common.jar:/system/framework/mms-common.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/apache-xml.jar # Backward compatibility symlink /system/etc /etc From 99e1966400559f9fcc18174e37ccf8a0e5265ffc Mon Sep 17 00:00:00 2001 From: Rom Lemarchand Date: Mon, 7 Jan 2013 15:50:02 -0800 Subject: [PATCH 85/89] logwrap: ensure child exits with _exit Always exit the child process with _exit() rather than exit() to ensure none of the parent's atexit functions get called if the child needs to exit before calling exec. Change-Id: I6a75111ef1bb3468c114c98743565471cf82c9dd --- logwrapper/logwrap.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c index ef457def5..016e12a2d 100644 --- a/logwrapper/logwrap.c +++ b/logwrapper/logwrap.c @@ -36,10 +36,17 @@ static int signal_fd_write; -static void fatal(const char *msg) { - fprintf(stderr, "%s", msg); - ALOG(LOG_ERROR, "logwrapper", "%s", msg); -} +#define ERROR(fmt, args...) \ +do { \ + fprintf(stderr, fmt, ## args); \ + ALOG(LOG_ERROR, "logwrapper", fmt, ## args); \ +} while(0) + +#define FATAL_CHILD(fmt, args...) \ +do { \ + ERROR(fmt, ## args); \ + _exit(-1); \ +} while(0) static int parent(const char *tag, int parent_read, int signal_fd, pid_t pid, int *chld_sts) { @@ -75,7 +82,7 @@ static int parent(const char *tag, int parent_read, int signal_fd, pid_t pid, if (poll(poll_fds, remote_hung ? 1 : 2, -1) < 0) { if (errno == EINTR) continue; - fatal("poll failed\n"); + ERROR("poll failed\n"); rc = -1; goto err_poll; } @@ -166,9 +173,8 @@ static void child(int argc, char* argv[]) { argv_child[argc] = NULL; if (execvp(argv_child[0], argv_child)) { - ALOG(LOG_ERROR, "logwrapper", - "executing %s failed: %s\n", argv_child[0], strerror(errno)); - exit(-1); + FATAL_CHILD("executing %s failed: %s\n", argv_child[0], + strerror(errno)); } } @@ -191,14 +197,14 @@ int logwrap(int argc, char* argv[], int *status) { /* Use ptty instead of socketpair so that STDOUT is not buffered */ parent_ptty = open("/dev/ptmx", O_RDWR); if (parent_ptty < 0) { - fatal("Cannot create parent ptty\n"); + ERROR("Cannot create parent ptty\n"); rc = -1; goto err_open; } if (grantpt(parent_ptty) || unlockpt(parent_ptty) || ((child_devname = (char*)ptsname(parent_ptty)) == 0)) { - fatal("Problem with /dev/ptmx\n"); + ERROR("Problem with /dev/ptmx\n"); rc = -1; goto err_ptty; } @@ -209,7 +215,7 @@ int logwrap(int argc, char* argv[], int *status) { pid = fork(); if (pid < 0) { - fatal("Failed to fork\n"); + ERROR("Failed to fork\n"); rc = -1; goto err_fork; } else if (pid == 0) { @@ -218,8 +224,7 @@ int logwrap(int argc, char* argv[], int *status) { child_ptty = open(child_devname, O_RDWR); if (child_ptty < 0) { - fatal("Problem with child ptty\n"); - return -1; + FATAL_CHILD("Problem with child ptty\n"); } // redirect stdout and stderr @@ -228,8 +233,6 @@ int logwrap(int argc, char* argv[], int *status) { close(child_ptty); child(argc, argv); - fatal("This should never happen\n"); - return -1; } else { memset(&chldact, 0, sizeof(chldact)); chldact.sa_handler = sigchld_handler; @@ -247,11 +250,7 @@ int logwrap(int argc, char* argv[], int *status) { rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); if (rc == -1) { - char msg[40]; - - snprintf(msg, sizeof(msg), "socketpair failed: %d\n", errno); - - fatal(msg); + ERROR("socketpair failed: %s\n", strerror(errno)); goto err_socketpair; } From 75c289aab9b81dc2235680cf141a4b183ee49391 Mon Sep 17 00:00:00 2001 From: Rom Lemarchand Date: Wed, 9 Jan 2013 10:20:25 -0800 Subject: [PATCH 86/89] logwrap: wait for child process when receiving SIGINT or SIGQUIT - Wait for the child to exit before propagating SIGINT and SIGQUIT to the parent - Add ignore_int_quit argument to logwrap() that gives the caller the option to ignore SIGINT and SIGQUIT while logwrap is running Change-Id: If5c96cf23094917211310f00aa6aed515f110f5b --- logwrapper/include/logwrap/logwrap.h | 8 +++++++- logwrapper/logwrap.c | 19 ++++++++++++++++++- logwrapper/logwrapper.c | 2 +- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/logwrapper/include/logwrap/logwrap.h b/logwrapper/include/logwrap/logwrap.h index 722dda2ac..6593f3cb4 100644 --- a/logwrapper/include/logwrap/logwrap.h +++ b/logwrapper/include/logwrap/logwrap.h @@ -18,6 +18,8 @@ #ifndef __LIBS_LOGWRAP_H #define __LIBS_LOGWRAP_H +#include + __BEGIN_DECLS /* @@ -36,13 +38,17 @@ __BEGIN_DECLS * NULL-terminated * status: the equivalent child status as populated by wait(status). This * value is only valid when logwrap successfully completes + * ignore_int_quit: set to true if you want to completely ignore SIGINT and + * SIGQUIT while logwrap is running. This may force the end-user to + * send a signal twice to signal the caller (once for the child, and + * once for the caller) * * Return value: * 0 when logwrap successfully run the child process and captured its status * -1 when an internal error occurred * */ -int logwrap(int argc, char* argv[], int *status); +int logwrap(int argc, char* argv[], int *status, bool ignore_int_quit); __END_DECLS diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c index ef457def5..99a462f63 100644 --- a/logwrapper/logwrap.c +++ b/logwrapper/logwrap.c @@ -176,13 +176,15 @@ void sigchld_handler(int sig) { write(signal_fd_write, &sig, 1); } -int logwrap(int argc, char* argv[], int *status) { +int logwrap(int argc, char* argv[], int *status, bool ignore_int_quit) { pid_t pid; int parent_ptty; int child_ptty; char *child_devname = NULL; struct sigaction chldact; struct sigaction oldchldact; + struct sigaction intact; + struct sigaction quitact; sigset_t blockset; sigset_t oldset; int sockets[2]; @@ -204,6 +206,8 @@ int logwrap(int argc, char* argv[], int *status) { } sigemptyset(&blockset); + sigaddset(&blockset, SIGINT); + sigaddset(&blockset, SIGQUIT); sigaddset(&blockset, SIGCHLD); sigprocmask(SIG_BLOCK, &blockset, &oldset); @@ -231,6 +235,8 @@ int logwrap(int argc, char* argv[], int *status) { fatal("This should never happen\n"); return -1; } else { + struct sigaction ignact; + memset(&chldact, 0, sizeof(chldact)); chldact.sa_handler = sigchld_handler; chldact.sa_flags = SA_NOCLDSTOP; @@ -245,6 +251,13 @@ int logwrap(int argc, char* argv[], int *status) { "handler and might cause interaction issues"); } + if (ignore_int_quit) { + memset(&ignact, 0, sizeof(ignact)); + ignact.sa_handler = SIG_IGN; + sigaction(SIGINT, &ignact, &intact); + sigaction(SIGQUIT, &ignact, &quitact); + } + rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); if (rc == -1) { char msg[40]; @@ -268,6 +281,10 @@ int logwrap(int argc, char* argv[], int *status) { close(sockets[0]); close(sockets[1]); err_socketpair: + if (ignore_int_quit) { + sigaction(SIGINT, &intact, NULL); + sigaction(SIGQUIT, &quitact, NULL); + } sigaction(SIGCHLD, &oldchldact, NULL); err_fork: sigprocmask(SIG_SETMASK, &oldset, NULL); diff --git a/logwrapper/logwrapper.c b/logwrapper/logwrapper.c index e647b4d32..563fcee07 100644 --- a/logwrapper/logwrapper.c +++ b/logwrapper/logwrapper.c @@ -59,7 +59,7 @@ int main(int argc, char* argv[]) { usage(); } - rc = logwrap(argc - 1, &argv[1], &status); + rc = logwrap(argc - 1, &argv[1], &status, true); if (!rc) { if (WIFEXITED(status)) rc = WEXITSTATUS(status); From ed179d2f98c1628a593aec6d8408b621015f4de5 Mon Sep 17 00:00:00 2001 From: Rom Lemarchand Date: Wed, 16 Jan 2013 15:07:30 -0800 Subject: [PATCH 87/89] logwrap: Replace sigprocmask with pthread_sigmask sigprocmask has undefined behavior when called from a thread. Replacing with pthread_sigmask to ensure correct behavior if logwrap() gets called from a thread. Change-Id: I77b6959d345eac8d7b90039ed8144ead8c19a00c --- logwrapper/logwrap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c index 99a462f63..94e022968 100644 --- a/logwrapper/logwrap.c +++ b/logwrapper/logwrap.c @@ -69,7 +69,7 @@ static int parent(const char *tag, int parent_read, int signal_fd, pid_t pid, sigemptyset(&chldset); sigaddset(&chldset, SIGCHLD); - sigprocmask(SIG_UNBLOCK, &chldset, NULL); + pthread_sigmask(SIG_UNBLOCK, &chldset, NULL); while (!found_child) { if (poll(poll_fds, remote_hung ? 1 : 2, -1) < 0) { @@ -209,7 +209,7 @@ int logwrap(int argc, char* argv[], int *status, bool ignore_int_quit) { sigaddset(&blockset, SIGINT); sigaddset(&blockset, SIGQUIT); sigaddset(&blockset, SIGCHLD); - sigprocmask(SIG_BLOCK, &blockset, &oldset); + pthread_sigmask(SIG_BLOCK, &blockset, &oldset); pid = fork(); if (pid < 0) { @@ -217,7 +217,7 @@ int logwrap(int argc, char* argv[], int *status, bool ignore_int_quit) { rc = -1; goto err_fork; } else if (pid == 0) { - sigprocmask(SIG_SETMASK, &oldset, NULL); + pthread_sigmask(SIG_SETMASK, &oldset, NULL); close(parent_ptty); child_ptty = open(child_devname, O_RDWR); @@ -287,7 +287,7 @@ err_socketpair: } sigaction(SIGCHLD, &oldchldact, NULL); err_fork: - sigprocmask(SIG_SETMASK, &oldset, NULL); + pthread_sigmask(SIG_SETMASK, &oldset, NULL); err_ptty: close(parent_ptty); err_open: From f5200c075098a6fb6a69ac4e2baa2fdd3809cbbd Mon Sep 17 00:00:00 2001 From: Rom Lemarchand Date: Thu, 24 Jan 2013 10:57:44 -0800 Subject: [PATCH 88/89] logwrap: add quiet flag to logwrap() Add a quiet flag to the logwrap function that prevents messages from getting logged. Change-Id: Ic56c011fb608babae32b03900b955833a6bdd070 --- logwrapper/include/logwrap/logwrap.h | 4 +- logwrapper/logwrap.c | 69 ++++++++++++++++------------ logwrapper/logwrapper.c | 2 +- 3 files changed, 43 insertions(+), 32 deletions(-) diff --git a/logwrapper/include/logwrap/logwrap.h b/logwrapper/include/logwrap/logwrap.h index 6593f3cb4..6597ef59f 100644 --- a/logwrapper/include/logwrap/logwrap.h +++ b/logwrapper/include/logwrap/logwrap.h @@ -42,13 +42,15 @@ __BEGIN_DECLS * SIGQUIT while logwrap is running. This may force the end-user to * send a signal twice to signal the caller (once for the child, and * once for the caller) + * quiet: when true, don't display log messages * * Return value: * 0 when logwrap successfully run the child process and captured its status * -1 when an internal error occurred * */ -int logwrap(int argc, char* argv[], int *status, bool ignore_int_quit); +int logwrap(int argc, char* argv[], int *status, bool ignore_int_quit, + bool quiet); __END_DECLS diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c index f6a96e088..5af167191 100644 --- a/logwrapper/logwrap.c +++ b/logwrapper/logwrap.c @@ -36,20 +36,22 @@ static int signal_fd_write; -#define ERROR(fmt, args...) \ +#define ERROR(fmt, quiet, args...) \ do { \ - fprintf(stderr, fmt, ## args); \ - ALOG(LOG_ERROR, "logwrapper", fmt, ## args); \ + if (!quiet) { \ + fprintf(stderr, fmt, ## args); \ + ALOG(LOG_ERROR, "logwrapper", fmt, ## args); \ + } \ } while(0) -#define FATAL_CHILD(fmt, args...) \ +#define FATAL_CHILD(fmt, quiet, args...) \ do { \ - ERROR(fmt, ## args); \ + ERROR(fmt, quiet, ## args); \ _exit(-1); \ } while(0) static int parent(const char *tag, int parent_read, int signal_fd, pid_t pid, - int *chld_sts) { + int *chld_sts, bool quiet) { int status = 0; char buffer[4096]; struct pollfd poll_fds[] = { @@ -82,7 +84,7 @@ static int parent(const char *tag, int parent_read, int signal_fd, pid_t pid, if (poll(poll_fds, remote_hung ? 1 : 2, -1) < 0) { if (errno == EINTR) continue; - ERROR("poll failed\n"); + ERROR("poll failed\n", quiet); rc = -1; goto err_poll; } @@ -98,7 +100,8 @@ static int parent(const char *tag, int parent_read, int signal_fd, pid_t pid, buffer[b] = '\0'; } else if (buffer[b] == '\n') { buffer[b] = '\0'; - ALOG(LOG_INFO, btag, "%s", &buffer[a]); + if (!quiet) + ALOG(LOG_INFO, btag, "%s", &buffer[a]); a = b + 1; } } @@ -106,7 +109,8 @@ static int parent(const char *tag, int parent_read, int signal_fd, pid_t pid, if (a == 0 && b == sizeof(buffer) - 1) { // buffer is full, flush buffer[b] = '\0'; - ALOG(LOG_INFO, btag, "%s", &buffer[a]); + if (!quiet) + ALOG(LOG_INFO, btag, "%s", &buffer[a]); b = 0; } else if (a != b) { // Keep left-overs @@ -145,19 +149,22 @@ static int parent(const char *tag, int parent_read, int signal_fd, pid_t pid, // Flush remaining data if (a != b) { buffer[b] = '\0'; - ALOG(LOG_INFO, btag, "%s", &buffer[a]); + if (!quiet) + ALOG(LOG_INFO, btag, "%s", &buffer[a]); } - if (WIFEXITED(status)) { - if (WEXITSTATUS(status)) - ALOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", btag, - WEXITSTATUS(status)); - } else if (WIFSIGNALED(status)) { - ALOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", btag, - WTERMSIG(status)); - } else if (WIFSTOPPED(status)) { - ALOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", btag, - WSTOPSIG(status)); + if (!quiet) { + if (WIFEXITED(status)) { + if (WEXITSTATUS(status)) + ALOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", btag, + WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + ALOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", btag, + WTERMSIG(status)); + } else if (WIFSTOPPED(status)) { + ALOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", btag, + WSTOPSIG(status)); + } } if (chld_sts != NULL) *chld_sts = status; @@ -166,14 +173,14 @@ err_poll: return rc; } -static void child(int argc, char* argv[]) { +static void child(int argc, char* argv[], bool quiet) { // create null terminated argv_child array char* argv_child[argc + 1]; memcpy(argv_child, argv, argc * sizeof(char *)); argv_child[argc] = NULL; if (execvp(argv_child[0], argv_child)) { - FATAL_CHILD("executing %s failed: %s\n", argv_child[0], + FATAL_CHILD("executing %s failed: %s\n", quiet, argv_child[0], strerror(errno)); } } @@ -182,7 +189,8 @@ void sigchld_handler(int sig) { write(signal_fd_write, &sig, 1); } -int logwrap(int argc, char* argv[], int *status, bool ignore_int_quit) { +int logwrap(int argc, char* argv[], int *status, bool ignore_int_quit, + bool quiet) { pid_t pid; int parent_ptty; int child_ptty; @@ -199,14 +207,14 @@ int logwrap(int argc, char* argv[], int *status, bool ignore_int_quit) { /* Use ptty instead of socketpair so that STDOUT is not buffered */ parent_ptty = open("/dev/ptmx", O_RDWR); if (parent_ptty < 0) { - ERROR("Cannot create parent ptty\n"); + ERROR("Cannot create parent ptty\n", quiet); rc = -1; goto err_open; } if (grantpt(parent_ptty) || unlockpt(parent_ptty) || ((child_devname = (char*)ptsname(parent_ptty)) == 0)) { - ERROR("Problem with /dev/ptmx\n"); + ERROR("Problem with /dev/ptmx\n", quiet); rc = -1; goto err_ptty; } @@ -219,7 +227,7 @@ int logwrap(int argc, char* argv[], int *status, bool ignore_int_quit) { pid = fork(); if (pid < 0) { - ERROR("Failed to fork\n"); + ERROR("Failed to fork\n", quiet); rc = -1; goto err_fork; } else if (pid == 0) { @@ -228,7 +236,8 @@ int logwrap(int argc, char* argv[], int *status, bool ignore_int_quit) { child_ptty = open(child_devname, O_RDWR); if (child_ptty < 0) { - FATAL_CHILD("Problem with child ptty\n"); + FATAL_CHILD("Problem with child ptty\n", quiet); + return -1; } // redirect stdout and stderr @@ -236,7 +245,7 @@ int logwrap(int argc, char* argv[], int *status, bool ignore_int_quit) { dup2(child_ptty, 2); close(child_ptty); - child(argc, argv); + child(argc, argv, quiet); } else { struct sigaction ignact; @@ -263,7 +272,7 @@ int logwrap(int argc, char* argv[], int *status, bool ignore_int_quit) { rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); if (rc == -1) { - ERROR("socketpair failed: %s\n", strerror(errno)); + ERROR("socketpair failed: %s\n", quiet, strerror(errno)); goto err_socketpair; } @@ -274,7 +283,7 @@ int logwrap(int argc, char* argv[], int *status, bool ignore_int_quit) { signal_fd_write = sockets[0]; - rc = parent(argv[0], parent_ptty, sockets[1], pid, status); + rc = parent(argv[0], parent_ptty, sockets[1], pid, status, quiet); } close(sockets[0]); diff --git a/logwrapper/logwrapper.c b/logwrapper/logwrapper.c index 563fcee07..cba69d91c 100644 --- a/logwrapper/logwrapper.c +++ b/logwrapper/logwrapper.c @@ -59,7 +59,7 @@ int main(int argc, char* argv[]) { usage(); } - rc = logwrap(argc - 1, &argv[1], &status, true); + rc = logwrap(argc - 1, &argv[1], &status, true, false); if (!rc) { if (WIFEXITED(status)) rc = WEXITSTATUS(status); From b94fd1abcbff1eacb8a2ad79c51de21ecf8f6d65 Mon Sep 17 00:00:00 2001 From: Nick Kralevich Date: Tue, 29 Jan 2013 13:19:20 -0800 Subject: [PATCH 89/89] cutils: remove dead code. The last caller of this code was removed in dalvik commit eb1703442f3fc0577b3395b7eb4d55300b4125db (https://android-review.googlesource.com/50689) Change-Id: I3f4865c02092752a13369a3b2c3289fc9a4f6a62 --- include/cutils/zygote.h | 1 - libcutils/zygote.c | 38 -------------------------------------- 2 files changed, 39 deletions(-) diff --git a/include/cutils/zygote.h b/include/cutils/zygote.h index 22721a6bd..a7480d320 100644 --- a/include/cutils/zygote.h +++ b/include/cutils/zygote.h @@ -23,7 +23,6 @@ extern "C" { int zygote_run_oneshot(int sendStdio, int argc, const char **argv); int zygote_run(int argc, const char **argv); -int zygote_run_wait(int argc, const char **argv, void (*post_run_func)(int)); #ifdef __cplusplus } diff --git a/libcutils/zygote.c b/libcutils/zygote.c index 75ce3ba99..37236e8a6 100644 --- a/libcutils/zygote.c +++ b/libcutils/zygote.c @@ -159,44 +159,6 @@ static int send_request(int fd, int sendStdio, int argc, const char **argv) #endif /* HAVE_ANDROID_OS */ } -int zygote_run_wait(int argc, const char **argv, void (*post_run_func)(int)) -{ - int fd; - int pid; - int err; - const char *newargv[argc + 1]; - - fd = socket_local_client(ZYGOTE_SOCKET, - ANDROID_SOCKET_NAMESPACE_RESERVED, AF_LOCAL); - - if (fd < 0) { - return -1; - } - - // The command socket is passed to the peer as close-on-exec - // and will close when the peer dies - newargv[0] = "--peer-wait"; - memcpy(newargv + 1, argv, argc * sizeof(*argv)); - - pid = send_request(fd, 1, argc + 1, newargv); - - if (pid > 0 && post_run_func != NULL) { - post_run_func(pid); - } - - // Wait for socket to close - do { - int dummy; - err = read(fd, &dummy, sizeof(dummy)); - } while ((err < 0 && errno == EINTR) || err != 0); - - do { - err = close(fd); - } while (err < 0 && errno == EINTR); - - return 0; -} - /** * Spawns a new dalvik instance via the Zygote process. The non-zygote * arguments are passed to com.android.internal.os.RuntimeInit(). The