am 3dbcb6d6: am 98d07897: Merge "Windows adb: Make client stdout and stderr handles uninheritable"
* commit '3dbcb6d6c6befc406e4ce4e2b7aa9ad2635dfbb8':
Windows adb: Make client stdout and stderr handles uninheritable
diff --git a/adb/Android.mk b/adb/Android.mk
index 32dd95a..a803978 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -17,6 +17,7 @@
USB_SRCS := usb_linux.c
EXTRA_SRCS := get_my_path_linux.c
LOCAL_LDLIBS += -lrt -ldl -lpthread
+ LOCAL_CFLAGS += -DWORKAROUND_BUG6558362
endif
ifeq ($(HOST_OS),darwin)
@@ -77,6 +78,7 @@
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/adb/adb.c b/adb/adb.c
index b5d93f8..1bf4b9e 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -983,6 +983,33 @@
#endif
#if ADB_HOST
+
+#ifdef WORKAROUND_BUG6558362
+#include <sched.h>
+#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
@@ -1207,6 +1234,10 @@
#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);
diff --git a/debuggerd/debuggerd.c b/debuggerd/debuggerd.c
index 55222c5..65ff0f6 100644
--- a/debuggerd/debuggerd.c
+++ b/debuggerd/debuggerd.c
@@ -202,18 +202,20 @@
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 @@
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;
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index 5025dae..1189e1f 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -20,6 +20,7 @@
$(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
diff --git a/fastboot/fastboot_protocol.txt b/fastboot/fastboot_protocol.txt
new file mode 100644
index 0000000..2248992
--- /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.
+
+
diff --git a/include/cutils/aref.h b/include/cutils/aref.h
new file mode 100644
index 0000000..460ac02
--- /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 <stddef.h>
+#include <sys/cdefs.h>
+
+#ifdef ANDROID_SMP
+#include <cutils/atomic-inline.h>
+#else
+#include <cutils/atomic.h>
+#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_
diff --git a/include/cutils/bitops.h b/include/cutils/bitops.h
index 1b3b762..eb44236 100644
--- a/include/cutils/bitops.h
+++ b/include/cutils/bitops.h
@@ -17,10 +17,79 @@
#ifndef __CUTILS_BITOPS_H
#define __CUTILS_BITOPS_H
+#include <stdbool.h>
+#include <string.h>
+#include <strings.h>
#include <sys/cdefs.h>
__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);
diff --git a/include/cutils/trace.h b/include/cutils/trace.h
new file mode 100644
index 0000000..1db3903
--- /dev/null
+++ b/include/cutils/trace.h
@@ -0,0 +1,203 @@
+/*
+ * 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 <sys/cdefs.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <cutils/compiler.h>
+
+#ifdef ANDROID_SMP
+#include <cutils/atomic-inline.h>
+#else
+#include <cutils/atomic.h>
+#endif
+
+__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();
+
+/**
+ * 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.
+ * 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/include/netutils/dhcp.h b/include/netutils/dhcp.h
index d25e58f..bd2c957 100644
--- a/include/netutils/dhcp.h
+++ b/include/netutils/dhcp.h
@@ -27,11 +27,18 @@
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/init/init.c b/init/init.c
index b20b434..bc88ba9 100755
--- a/init/init.c
+++ b/init/init.c
@@ -31,7 +31,6 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
-#include <sys/personality.h>
#include <selinux/selinux.h>
#include <selinux/label.h>
@@ -234,26 +233,6 @@
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);
- 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 61dd86f..b608d2f 100755
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -112,7 +112,6 @@
typedef struct {
void *data;
size_t size;
- int fd;
} workspace;
static int init_workspace(workspace *w, size_t size)
@@ -120,10 +119,10 @@
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 @@
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 @@
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 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 b9d1bf6..df71f3f 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -24,7 +24,6 @@
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();
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index fc6d08d..23a73d2 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -121,6 +121,7 @@
mq.c \
partition_utils.c \
qtaguid.c \
+ trace.c \
uevent.c
ifeq ($(TARGET_ARCH),arm)
diff --git a/libcutils/fs.c b/libcutils/fs.c
index 1226d44..116526d 100644
--- a/libcutils/fs.c
+++ b/libcutils/fs.c
@@ -26,6 +26,7 @@
#include <errno.h>
#include <string.h>
#include <limits.h>
+#include <stdlib.h>
#define ALL_PERMS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
#define BUF_SIZE 64
diff --git a/libcutils/trace.c b/libcutils/trace.c
new file mode 100644
index 0000000..152ea61
--- /dev/null
+++ b/libcutils/trace.c
@@ -0,0 +1,88 @@
+/*
+ * 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 <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <cutils/atomic.h>
+#include <cutils/compiler.h>
+#include <cutils/properties.h>
+#include <cutils/trace.h>
+
+#define LOG_TAG "cutils-trace"
+#include <cutils/log.h>
+
+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()
+{
+ 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;
+}
+
+// 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);
+ 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);
+}
diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c
index b4caaf9..bd48eff 100644
--- a/libnetutils/dhcp_utils.c
+++ b/libnetutils/dhcp_utils.c
@@ -88,16 +88,17 @@
char *ipaddr,
char *gateway,
uint32_t *prefixLength,
- char *dns1,
- char *dns2,
+ char *dns[],
char *server,
uint32_t *lease,
- char *vendorInfo)
+ char *vendorInfo,
+ char *domain)
{
char prop_name[PROPERTY_KEY_MAX];
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);
@@ -111,7 +112,7 @@
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);
}
@@ -138,11 +139,11 @@
}
*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)) {
@@ -153,6 +154,10 @@
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;
}
@@ -177,11 +182,11 @@
char *ipaddr,
char *gateway,
uint32_t *prefixLength,
- char *dns1,
- char *dns2,
+ char *dns[],
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];
@@ -232,17 +237,10 @@
}
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) {
+ if (fill_ip_info(interface, ipaddr, gateway, prefixLength, dns,
+ 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);
@@ -327,11 +325,11 @@
char *ipaddr,
char *gateway,
uint32_t *prefixLength,
- char *dns1,
- char *dns2,
+ char *dns[],
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'};
@@ -367,8 +365,8 @@
return -1;
}
if (strcmp(prop_value, "ok") == 0) {
- fill_ip_info(interface, ipaddr, gateway, prefixLength,
- dns1, dns2, server, lease, vendorInfo);
+ 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);
diff --git a/logwrapper/Android.mk b/logwrapper/Android.mk
index 5fd6356..b4b6b29 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 0000000..722dda2
--- /dev/null
+++ b/logwrapper/include/logwrap/logwrap.h
@@ -0,0 +1,49 @@
+/* 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
+
+/*
+ * 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
+
+#endif /* __LIBS_LOGWRAP_H */
diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c
new file mode 100644
index 0000000..c2b36be
--- /dev/null
+++ b/logwrapper/logwrap.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/signalfd.h>
+#include <signal.h>
+#include <poll.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+
+#include <logwrap/logwrap.h>
+#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;
+}
+
+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
+ int sz;
+
+ 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");
+ }
+
+ 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]);
+ 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 (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;
+
+ return 0;
+}
+
+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 *));
+ 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 *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);
+ 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");
+ }
+
+ 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) {
+ 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");
+ }
+
+ // redirect stdout and stderr
+ dup2(child_ptty, 1);
+ dup2(child_ptty, 2);
+ 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
+ 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;
+ }
+}
diff --git a/logwrapper/logwrapper.c b/logwrapper/logwrapper.c
index dd777c0..4f1bff9 100644
--- a/logwrapper/logwrapper.c
+++ b/logwrapper/logwrapper.c
@@ -14,17 +14,12 @@
* limitations under the License.
*/
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <libgen.h>
+#include <sys/wait.h>
-#include "private/android_filesystem_config.h"
+#include <logwrap/logwrap.h>
+
#include "cutils/log.h"
void fatal(const char *msg) {
@@ -45,90 +40,10 @@
" 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 @@
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;
}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 871a1f7..bee0729 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -287,10 +287,14 @@
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
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index dbbce06..2ecb626 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -58,6 +58,7 @@
lsof \
du \
md5 \
+ clear \
getenforce \
setenforce \
chcon \
diff --git a/toolbox/clear.c b/toolbox/clear.c
new file mode 100644
index 0000000..df46ad2
--- /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 <stdio.h>
+
+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;
+}
diff --git a/toolbox/du.c b/toolbox/du.c
index 06374a4..fc7c943 100644
--- a/toolbox/du.c
+++ b/toolbox/du.c
@@ -62,7 +62,7 @@
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 @@
return 0;
}
-void
+static void
usage(void)
{