Merge "Add init support for dm-verity logging mode"
diff --git a/adb/.clang-format b/adb/.clang-format
new file mode 100644
index 0000000..2b83a1f
--- /dev/null
+++ b/adb/.clang-format
@@ -0,0 +1,11 @@
+BasedOnStyle: Google
+AllowShortBlocksOnASingleLine: false
+AllowShortFunctionsOnASingleLine: false
+
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IndentWidth: 2
+PointerAlignment: Left
+TabWidth: 2
+UseTab: Never
+PenaltyExcessCharacter: 32
diff --git a/adb/Android.mk b/adb/Android.mk
index 83d168b..adad69f 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -5,6 +5,8 @@
LOCAL_PATH:= $(call my-dir)
+ADB_CLANG :=
+
# libadb
# =========================================================
@@ -14,93 +16,133 @@
# divergence makes this difficult to do all at once. For now, we will start
# small by moving common files into a static library. Hopefully some day we can
# get enough of adb in here that we no longer need minadb. https://b/17626262
-LIBADB_SRC_FILES := transport.c transport_usb.c
-LIBADB_C_FLAGS := -Wall -Werror -D_XOPEN_SOURCE -D_GNU_SOURCE
+LIBADB_SRC_FILES := \
+ adb.c \
+ adb_auth.c \
+ adb_io.cpp \
+ adb_listeners.c \
+ sockets.c \
+ transport.c \
+ transport_local.c \
+ transport_usb.c \
-LIBADB_LINUX_SRC_FILES := fdevent.cpp
-LIBADB_WINDOWS_SRC_FILES := sysdeps_win32.c
+LIBADB_CFLAGS := \
+ -Wall -Werror \
+ -Wno-unused-parameter \
+ -Wno-missing-field-initializers \
+ -fvisibility=hidden \
+
+LIBADB_darwin_SRC_FILES := fdevent.cpp get_my_path_darwin.c usb_osx.c
+LIBADB_linux_SRC_FILES := fdevent.cpp get_my_path_linux.c usb_linux.c
+LIBADB_windows_SRC_FILES := get_my_path_windows.c sysdeps_win32.c usb_windows.c
include $(CLEAR_VARS)
+LOCAL_CLANG := $(ADB_CLANG)
LOCAL_MODULE := libadbd
LOCAL_CFLAGS := $(LIBADB_CFLAGS) -DADB_HOST=0
LOCAL_SRC_FILES := \
$(LIBADB_SRC_FILES) \
- $(LIBADB_LINUX_SRC_FILES) \
+ adb_auth_client.c \
+ fdevent.cpp \
+ jdwp_service.c \
qemu_tracing.c \
usb_linux_client.c \
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
+LOCAL_CLANG := $(ADB_CLANG)
LOCAL_MODULE := libadb
LOCAL_CFLAGS := $(LIBADB_CFLAGS) -DADB_HOST=1
-LOCAL_SRC_FILES := $(LIBADB_SRC_FILES) $(LIBADB_LINUX_SRC_FILES)
-include $(BUILD_STATIC_LIBRARY)
+LOCAL_SRC_FILES := \
+ $(LIBADB_SRC_FILES) \
+ $(LIBADB_$(HOST_OS)_SRC_FILES) \
+ adb_auth_host.c \
+
+# Even though we're building a static library (and thus there's no link step for
+# this to take effect), this adds the SSL includes to our path.
+LOCAL_STATIC_LIBRARIES := libcrypto_static
+
+ifeq ($(HOST_OS),windows)
+ LOCAL_C_INCLUDES += development/host/windows/usb/api/
+endif
+
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+LIBADB_TEST_SRCS := \
+ adb_io_test.cpp \
+ transport_test.cpp \
include $(CLEAR_VARS)
-LOCAL_MODULE := libadb
-LOCAL_CFLAGS := $(LIBADB_CFLAGS) -DADB_HOST=1
-LOCAL_SRC_FILES := $(LIBADB_SRC_FILES)
-ifeq ($(HOST_OS),windows)
- LOCAL_SRC_FILES += $(LIBADB_WINDOWS_SRC_FILES)
-else
- LOCAL_SRC_FILES += $(LIBADB_LINUX_SRC_FILES)
+LOCAL_CLANG := $(ADB_CLANG)
+LOCAL_MODULE := adbd_test
+LOCAL_CFLAGS := -DADB_HOST=0 $(LIBADB_CFLAGS)
+LOCAL_SRC_FILES := $(LIBADB_TEST_SRCS)
+LOCAL_STATIC_LIBRARIES := libadbd
+LOCAL_SHARED_LIBRARIES := liblog libcutils libutils
+include $(BUILD_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+LOCAL_CLANG := $(ADB_CLANG)
+LOCAL_MODULE := adb_test
+LOCAL_CFLAGS := -DADB_HOST=1 $(LIBADB_CFLAGS)
+LOCAL_SRC_FILES := $(LIBADB_TEST_SRCS) services.c
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_STATIC_LIBRARIES := \
+ libadb \
+ libcrypto_static \
+ libcutils \
+ libutils \
+
+ifeq ($(HOST_OS),linux)
+ LOCAL_LDLIBS += -lrt -ldl -lpthread
endif
-include $(BUILD_HOST_STATIC_LIBRARY)
+
+include $(BUILD_HOST_NATIVE_TEST)
# adb host tool
# =========================================================
include $(CLEAR_VARS)
-# Default to a virtual (sockets) usb interface
-USB_SRCS :=
-EXTRA_SRCS :=
-
ifeq ($(HOST_OS),linux)
- 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)
- USB_SRCS := usb_osx.c
- EXTRA_SRCS := get_my_path_darwin.c
LOCAL_LDLIBS += -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
LOCAL_CFLAGS += -Wno-sizeof-pointer-memaccess -Wno-unused-parameter
endif
ifeq ($(HOST_OS),windows)
- USB_SRCS := usb_windows.c
- EXTRA_SRCS := get_my_path_windows.c
EXTRA_STATIC_LIBS := AdbWinApi
ifneq ($(strip $(USE_MINGW)),)
# MinGW under Linux case
LOCAL_LDLIBS += -lws2_32 -lgdi32
USE_SYSDEPS_WIN32 := 1
endif
- LOCAL_C_INCLUDES += development/host/windows/usb/api/
endif
+LOCAL_CLANG := $(ADB_CLANG)
+
LOCAL_SRC_FILES := \
- adb.c \
+ adb_main.c \
console.c \
- transport_local.c \
commandline.c \
adb_client.c \
- adb_auth_host.c \
- sockets.c \
services.c \
file_sync_client.c \
- $(EXTRA_SRCS) \
- $(USB_SRCS) \
ifneq ($(USE_SYSDEPS_WIN32),)
LOCAL_SRC_FILES += sysdeps_win32.c
endif
-LOCAL_CFLAGS += -O2 -g -DADB_HOST=1 -Wall -Wno-unused-parameter -Werror
-LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE
+LOCAL_CFLAGS += \
+ -Wall -Werror \
+ -Wno-unused-parameter \
+ -D_GNU_SOURCE \
+ -DADB_HOST=1 \
+
LOCAL_MODULE := adb
LOCAL_MODULE_TAGS := debug
@@ -131,24 +173,20 @@
include $(CLEAR_VARS)
+LOCAL_CLANG := $(ADB_CLANG)
+
LOCAL_SRC_FILES := \
- adb.c \
- transport_local.c \
- adb_auth_client.c \
- sockets.c \
+ adb_main.c \
services.c \
file_sync_service.c \
- jdwp_service.c \
framebuffer_service.c \
remount_service.c \
set_verity_enable_state_service.c \
- usb_linux_client.c
LOCAL_CFLAGS := \
-O2 \
-g \
-DADB_HOST=0 \
- -D_XOPEN_SOURCE \
-D_GNU_SOURCE \
-Wall -Wno-unused-parameter -Werror -Wno-deprecated-declarations \
diff --git a/adb/CPPLINT.cfg b/adb/CPPLINT.cfg
index b981cd4..9b906e8 100644
--- a/adb/CPPLINT.cfg
+++ b/adb/CPPLINT.cfg
@@ -1,2 +1,2 @@
set noparent
-filter=-build/header_guard,-readability/function
+filter=-build/header_guard,-build/include,-readability/function
diff --git a/adb/adb.c b/adb/adb.c
index e9671e3..5f244a5 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -30,18 +30,16 @@
#include "sysdeps.h"
#include "adb.h"
#include "adb_auth.h"
-#include "qemu_tracing.h"
+#include "adb_io.h"
+#include "adb_listeners.h"
+#include "transport.h"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#if !ADB_HOST
#include <cutils/properties.h>
-#include <private/android_filesystem_config.h>
#include <sys/capability.h>
#include <sys/mount.h>
-#include <sys/prctl.h>
-#include <getopt.h>
-#include <selinux/selinux.h>
#endif
#if ADB_TRACE
@@ -49,13 +47,9 @@
#endif
int HOST = 0;
-int gListenAll = 0;
-
-static int auth_enabled = 0;
#if !ADB_HOST
-static const char *adb_device_banner = "device";
-static const char *root_seclabel = NULL;
+const char *adb_device_banner = "device";
#endif
void fatal(const char *fmt, ...)
@@ -270,8 +264,8 @@
if (msglen > 0xffff)
msglen = 0xffff;
snprintf(header, sizeof(header), "%04x", (unsigned)msglen);
- writex(fd, header, 4);
- writex(fd, msg, msglen);
+ WriteFdExactly(fd, header, 4);
+ WriteFdExactly(fd, msg, msglen);
}
#endif
@@ -281,12 +275,12 @@
if (msglen > 0xffff)
msglen = 0xffff;
snprintf(header, sizeof(header), "OKAY%04x", (unsigned)msglen);
- writex(fd, header, 8);
- writex(fd, msg, msglen);
+ WriteFdExactly(fd, header, 8);
+ WriteFdExactly(fd, msg, msglen);
}
#endif // ADB_HOST
-static void send_connect(atransport *t)
+void send_connect(atransport *t)
{
D("Calling send_connect \n");
apacket *cp = get_apacket();
@@ -298,70 +292,6 @@
send_packet(cp, t);
}
-void send_auth_request(atransport *t)
-{
- D("Calling send_auth_request\n");
- apacket *p;
- int ret;
-
- ret = adb_auth_generate_token(t->token, sizeof(t->token));
- if (ret != sizeof(t->token)) {
- D("Error generating token ret=%d\n", ret);
- return;
- }
-
- p = get_apacket();
- memcpy(p->data, t->token, ret);
- p->msg.command = A_AUTH;
- p->msg.arg0 = ADB_AUTH_TOKEN;
- p->msg.data_length = ret;
- send_packet(p, t);
-}
-
-static void send_auth_response(uint8_t *token, size_t token_size, atransport *t)
-{
- D("Calling send_auth_response\n");
- apacket *p = get_apacket();
- int ret;
-
- ret = adb_auth_sign(t->key, token, token_size, p->data);
- if (!ret) {
- D("Error signing the token\n");
- put_apacket(p);
- return;
- }
-
- p->msg.command = A_AUTH;
- p->msg.arg0 = ADB_AUTH_SIGNATURE;
- p->msg.data_length = ret;
- send_packet(p, t);
-}
-
-static void send_auth_publickey(atransport *t)
-{
- D("Calling send_auth_publickey\n");
- apacket *p = get_apacket();
- int ret;
-
- ret = adb_auth_get_userkey(p->data, sizeof(p->data));
- if (!ret) {
- D("Failed to get user public key\n");
- put_apacket(p);
- return;
- }
-
- p->msg.command = A_AUTH;
- p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY;
- p->msg.data_length = ret;
- send_packet(p, t);
-}
-
-void adb_auth_verified(atransport *t)
-{
- handle_online(t);
- send_connect(t);
-}
-
#if ADB_HOST
static char *connection_state_name(atransport *t)
{
@@ -614,406 +544,8 @@
put_apacket(p);
}
-alistener listener_list = {
- .next = &listener_list,
- .prev = &listener_list,
-};
-
-static void ss_listener_event_func(int _fd, unsigned ev, void *_l)
-{
- asocket *s;
-
- if(ev & FDE_READ) {
- struct sockaddr addr;
- socklen_t alen;
- int fd;
-
- alen = sizeof(addr);
- fd = adb_socket_accept(_fd, &addr, &alen);
- if(fd < 0) return;
-
- adb_socket_setbufsize(fd, CHUNK_SIZE);
-
- s = create_local_socket(fd);
- if(s) {
- connect_to_smartsocket(s);
- return;
- }
-
- adb_close(fd);
- }
-}
-
-static void listener_event_func(int _fd, unsigned ev, void *_l)
-{
- alistener *l = _l;
- asocket *s;
-
- if(ev & FDE_READ) {
- struct sockaddr addr;
- socklen_t alen;
- int fd;
-
- alen = sizeof(addr);
- fd = adb_socket_accept(_fd, &addr, &alen);
- if(fd < 0) return;
-
- s = create_local_socket(fd);
- if(s) {
- s->transport = l->transport;
- connect_to_remote(s, l->connect_to);
- return;
- }
-
- adb_close(fd);
- }
-}
-
-static void free_listener(alistener* l)
-{
- if (l->next) {
- l->next->prev = l->prev;
- l->prev->next = l->next;
- l->next = l->prev = l;
- }
-
- // closes the corresponding fd
- fdevent_remove(&l->fde);
-
- if (l->local_name)
- free((char*)l->local_name);
-
- if (l->connect_to)
- free((char*)l->connect_to);
-
- if (l->transport) {
- remove_transport_disconnect(l->transport, &l->disconnect);
- }
- free(l);
-}
-
-static void listener_disconnect(void* _l, atransport* t)
-{
- alistener* l = _l;
-
- free_listener(l);
-}
-
-int local_name_to_fd(const char *name)
-{
- int port;
-
- if(!strncmp("tcp:", name, 4)){
- int ret;
- port = atoi(name + 4);
-
- 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 */
- // It's non-sensical to support the "reserved" space on the adb host side
- if(!strncmp(name, "local:", 6)) {
- return socket_local_server(name + 6,
- ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
- } else if(!strncmp(name, "localabstract:", 14)) {
- return socket_local_server(name + 14,
- ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
- } else if(!strncmp(name, "localfilesystem:", 16)) {
- return socket_local_server(name + 16,
- ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
- }
-
-#endif
- printf("unknown local portname '%s'\n", name);
- return -1;
-}
-
-// 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:
- //
- // <device-serial> " " <local-name> " " <remote-name> "\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)) {
- listener_disconnect(l, l->transport);
- return 0;
- }
- }
- return -1;
-}
-
-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;
-
- //printf("install_listener('%s','%s')\n", local_name, connect_to);
-
- for(l = listener_list.next; l != &listener_list; l = l->next){
- if(strcmp(local_name, l->local_name) == 0) {
- char *cto;
-
- /* can't repurpose a smartsocket */
- if(l->connect_to[0] == '*') {
- 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 INSTALL_STATUS_INTERNAL_ERROR;
- }
-
- //printf("rebinding '%s' to '%s'\n", local_name, connect_to);
- free((void*) l->connect_to);
- l->connect_to = cto;
- if (l->transport != transport) {
- remove_transport_disconnect(l->transport, &l->disconnect);
- l->transport = transport;
- add_transport_disconnect(l->transport, &l->disconnect);
- }
- return INSTALL_STATUS_OK;
- }
- }
-
- if((l = calloc(1, sizeof(alistener))) == 0) goto nomem;
- if((l->local_name = strdup(local_name)) == 0) goto nomem;
- if((l->connect_to = strdup(connect_to)) == 0) goto nomem;
-
-
- l->fd = local_name_to_fd(local_name);
- if(l->fd < 0) {
- free((void*) l->local_name);
- free((void*) l->connect_to);
- free(l);
- printf("cannot bind '%s'\n", local_name);
- return -2;
- }
-
- close_on_exec(l->fd);
- if(!strcmp(l->connect_to, "*smartsocket*")) {
- fdevent_install(&l->fde, l->fd, ss_listener_event_func, l);
- } else {
- fdevent_install(&l->fde, l->fd, listener_event_func, l);
- }
- fdevent_set(&l->fde, FDE_READ);
-
- l->next = &listener_list;
- l->prev = listener_list.prev;
- l->next->prev = l;
- l->prev->next = l;
- l->transport = transport;
-
- if (transport) {
- l->disconnect.opaque = l;
- l->disconnect.func = listener_disconnect;
- add_transport_disconnect(transport, &l->disconnect);
- }
- return INSTALL_STATUS_OK;
-
-nomem:
- fatal("cannot allocate listener");
- return INSTALL_STATUS_INTERNAL_ERROR;
-}
-
-#if defined(_WIN32)
-static BOOL WINAPI ctrlc_handler(DWORD type)
-{
- exit(STATUS_CONTROL_C_EXIT);
- return TRUE;
-}
-#endif
-
-static void adb_cleanup(void)
-{
- usb_cleanup();
-}
-
-void start_logging(void)
-{
-#if defined(_WIN32)
- char temp[ MAX_PATH ];
- FILE* fnul;
- FILE* flog;
-
- GetTempPath( sizeof(temp) - 8, temp );
- strcat( temp, "adb.log" );
-
- /* Win32 specific redirections */
- fnul = fopen( "NUL", "rt" );
- if (fnul != NULL)
- stdin[0] = fnul[0];
-
- flog = fopen( temp, "at" );
- if (flog == NULL)
- flog = fnul;
-
- setvbuf( flog, NULL, _IONBF, 0 );
-
- stdout[0] = flog[0];
- stderr[0] = flog[0];
- fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
-#else
- int fd;
-
- fd = unix_open("/dev/null", O_RDONLY);
- dup2(fd, 0);
- adb_close(fd);
-
- fd = unix_open("/tmp/adb.log", O_WRONLY | O_CREAT | O_APPEND, 0640);
- if(fd < 0) {
- fd = unix_open("/dev/null", O_WRONLY);
- }
- dup2(fd, 1);
- dup2(fd, 2);
- adb_close(fd);
- fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
-#endif
-}
-
-#if !ADB_HOST
-void start_device_log(void)
-{
- int fd;
- char path[PATH_MAX];
- struct tm now;
- time_t t;
- char value[PROPERTY_VALUE_MAX];
-
- // read the trace mask from persistent property persist.adb.trace_mask
- // give up if the property is not set or cannot be parsed
- property_get("persist.adb.trace_mask", value, "");
- if (sscanf(value, "%x", &adb_trace_mask) != 1)
- return;
-
- adb_mkdir("/data/adb", 0775);
- tzset();
- time(&t);
- localtime_r(&t, &now);
- strftime(path, sizeof(path),
- "/data/adb/adb-%Y-%m-%d-%H-%M-%S.txt",
- &now);
- fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0640);
- if (fd < 0)
- return;
-
- // redirect stdout and stderr to the log file
- dup2(fd, 1);
- dup2(fd, 2);
- fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
- adb_close(fd);
-
- fd = unix_open("/dev/null", O_RDONLY);
- dup2(fd, 0);
- adb_close(fd);
-}
-#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)
{
#if defined(_WIN32)
@@ -1172,226 +704,6 @@
}
#endif /* ADB_HOST */
-/* Constructs a local name of form tcp:port.
- * target_str points to the target string, it's content will be overwritten.
- * target_size is the capacity of the target string.
- * server_port is the port number to use for the local name.
- */
-void build_local_name(char* target_str, size_t target_size, int server_port)
-{
- snprintf(target_str, target_size, "tcp:%d", server_port);
-}
-
-#if !ADB_HOST
-
-static void drop_capabilities_bounding_set_if_needed() {
-#ifdef ALLOW_ADBD_ROOT
- char value[PROPERTY_VALUE_MAX];
- property_get("ro.debuggable", value, "");
- if (strcmp(value, "1") == 0) {
- return;
- }
-#endif
- int i;
- for (i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
- if (i == CAP_SETUID || i == CAP_SETGID) {
- // CAP_SETUID CAP_SETGID needed by /system/bin/run-as
- continue;
- }
- int err = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
-
- // Some kernels don't have file capabilities compiled in, and
- // prctl(PR_CAPBSET_DROP) returns EINVAL. Don't automatically
- // die when we see such misconfigured kernels.
- if ((err < 0) && (errno != EINVAL)) {
- exit(1);
- }
- }
-}
-
-static bool should_drop_privileges() {
-#if defined(ALLOW_ADBD_ROOT)
- char value[PROPERTY_VALUE_MAX];
-
- // The emulator is never secure, so don't drop privileges there.
- // TODO: this seems like a bug --- shouldn't the emulator behave like a device?
- property_get("ro.kernel.qemu", value, "");
- if (strcmp(value, "1") == 0) {
- return false;
- }
-
- property_get("ro.secure", value, "1");
- bool ro_secure = (strcmp(value, "1") == 0);
-
- // Drop privileges if ro.secure is set...
- bool drop = ro_secure;
-
- property_get("ro.debuggable", value, "");
- bool ro_debuggable = (strcmp(value, "1") == 0);
- property_get("service.adb.root", value, "");
- bool adb_root = (strcmp(value, "1") == 0);
- bool adb_unroot = (strcmp(value, "0") == 0);
-
- // ...except "adb root" lets you keep privileges in a debuggable build.
- if (ro_debuggable && adb_root) {
- drop = false;
- }
-
- // ...and "adb unroot" lets you explicitly drop privileges.
- if (adb_unroot) {
- drop = true;
- }
-
- return drop;
-#else
- return true; // "adb root" not allowed, always drop privileges.
-#endif /* ALLOW_ADBD_ROOT */
-}
-#endif /* !ADB_HOST */
-
-int adb_main(int is_daemon, int server_port)
-{
-#if !ADB_HOST
- int port;
- char value[PROPERTY_VALUE_MAX];
-
- umask(000);
-#endif
-
- atexit(adb_cleanup);
-#if defined(_WIN32)
- SetConsoleCtrlHandler( ctrlc_handler, TRUE );
-#else
- // No SIGCHLD. Let the service subproc handle its children.
- signal(SIGPIPE, SIG_IGN);
-#endif
-
- init_transport_registration();
-
-#if ADB_HOST
- HOST = 1;
-
-#ifdef WORKAROUND_BUG6558362
- if(is_daemon) adb_set_affinity();
-#endif
- usb_init();
- local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
- adb_auth_init();
-
- char local_name[30];
- build_local_name(local_name, sizeof(local_name), server_port);
- if(install_listener(local_name, "*smartsocket*", NULL, 0)) {
- exit(1);
- }
-#else
- property_get("ro.adb.secure", value, "0");
- auth_enabled = !strcmp(value, "1");
- if (auth_enabled)
- adb_auth_init();
-
- // Our external storage path may be different than apps, since
- // we aren't able to bind mount after dropping root.
- const char* adb_external_storage = getenv("ADB_EXTERNAL_STORAGE");
- if (NULL != adb_external_storage) {
- setenv("EXTERNAL_STORAGE", adb_external_storage, 1);
- } else {
- D("Warning: ADB_EXTERNAL_STORAGE is not set. Leaving EXTERNAL_STORAGE"
- " unchanged.\n");
- }
-
- /* add extra groups:
- ** AID_ADB to access the USB driver
- ** AID_LOG to read system logs (adb logcat)
- ** AID_INPUT to diagnose input issues (getevent)
- ** AID_INET to diagnose network issues (ping)
- ** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump)
- ** AID_SDCARD_R to allow reading from the SD card
- ** AID_SDCARD_RW to allow writing to the SD card
- ** AID_NET_BW_STATS to read out qtaguid statistics
- */
- gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_NET_BT,
- AID_NET_BT_ADMIN, AID_SDCARD_R, AID_SDCARD_RW,
- AID_NET_BW_STATS };
- if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
- exit(1);
- }
-
- /* don't listen on a port (default 5037) if running in secure mode */
- /* don't run as root if we are running in secure mode */
- if (should_drop_privileges()) {
- drop_capabilities_bounding_set_if_needed();
-
- /* then switch user and group to "shell" */
- if (setgid(AID_SHELL) != 0) {
- exit(1);
- }
- if (setuid(AID_SHELL) != 0) {
- exit(1);
- }
-
- D("Local port disabled\n");
- } else {
- char local_name[30];
- if ((root_seclabel != NULL) && (is_selinux_enabled() > 0)) {
- // b/12587913: fix setcon to allow const pointers
- if (setcon((char *)root_seclabel) < 0) {
- exit(1);
- }
- }
- build_local_name(local_name, sizeof(local_name), server_port);
- if(install_listener(local_name, "*smartsocket*", NULL, 0)) {
- exit(1);
- }
- }
-
- int usb = 0;
- if (access(USB_ADB_PATH, F_OK) == 0 || access(USB_FFS_ADB_EP0, F_OK) == 0) {
- // listen on USB
- usb_init();
- usb = 1;
- }
-
- // If one of these properties is set, also listen on that port
- // If one of the properties isn't set and we couldn't listen on usb,
- // listen on the default port.
- property_get("service.adb.tcp.port", value, "");
- if (!value[0]) {
- property_get("persist.adb.tcp.port", value, "");
- }
- if (sscanf(value, "%d", &port) == 1 && port > 0) {
- printf("using port=%d\n", port);
- // listen on TCP port specified by service.adb.tcp.port property
- local_init(port);
- } else if (!usb) {
- // listen on default port
- local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
- }
-
- D("adb_main(): pre init_jdwp()\n");
- init_jdwp();
- D("adb_main(): post init_jdwp()\n");
-#endif
-
- if (is_daemon)
- {
- // inform our parent that we are up and running.
-#if defined(_WIN32)
- DWORD count;
- WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ), "OK\n", 3, &count, NULL );
-#else
- fprintf(stderr, "OK\n");
-#endif
- start_logging();
- }
- D("Event loop starting\n");
-
- fdevent_loop();
-
- usb_cleanup();
-
- return 0;
-}
-
// Try to handle a network forwarding request.
// This returns 1 on success, 0 on failure, and -1 to indicate this is not
// a forwarding-related request.
@@ -1479,9 +791,9 @@
if(r == 0) {
#if ADB_HOST
/* On the host: 1st OKAY is connect, 2nd OKAY is status */
- writex(reply_fd, "OKAY", 4);
+ WriteFdExactly(reply_fd, "OKAY", 4);
#endif
- writex(reply_fd, "OKAY", 4);
+ WriteFdExactly(reply_fd, "OKAY", 4);
return 1;
}
@@ -1637,42 +949,3 @@
return ret - 1;
return -1;
}
-
-int main(int argc, char **argv)
-{
-#if ADB_HOST
- adb_sysdeps_init();
- adb_trace_init();
- D("Handling commandline()\n");
- return adb_commandline(argc - 1, argv + 1);
-#else
- /* If adbd runs inside the emulator this will enable adb tracing via
- * adb-debug qemud service in the emulator. */
- adb_qemu_trace_init();
- while(1) {
- int c;
- int option_index = 0;
- static struct option opts[] = {
- {"root_seclabel", required_argument, 0, 's' },
- {"device_banner", required_argument, 0, 'b' }
- };
- c = getopt_long(argc, argv, "", opts, &option_index);
- if (c == -1)
- break;
- switch (c) {
- case 's':
- root_seclabel = optarg;
- break;
- case 'b':
- adb_device_banner = optarg;
- break;
- default:
- break;
- }
- }
-
- start_device_log();
- D("Handling main()\n");
- return adb_main(0, DEFAULT_ADB_PORT);
-#endif
-}
diff --git a/adb/adb.h b/adb/adb.h
index 600bdd5..9a68871 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -18,10 +18,10 @@
#define __ADB_H
#include <limits.h>
+#include <sys/types.h>
#include "adb_trace.h"
#include "fdevent.h"
-#include "transport.h" /* readx(), writex() */
#ifdef __cplusplus
extern "C" {
@@ -37,12 +37,15 @@
#define A_WRTE 0x45545257
#define A_AUTH 0x48545541
-#define A_VERSION 0x01000000 // ADB protocol version
+// ADB protocol version.
+#define A_VERSION 0x01000000
-#define ADB_VERSION_MAJOR 1 // Used for help/version information
-#define ADB_VERSION_MINOR 0 // Used for help/version information
+// Used for help/version information.
+#define ADB_VERSION_MAJOR 1
+#define ADB_VERSION_MINOR 0
-#define ADB_SERVER_VERSION 32 // Increment this when we want to force users to start a new adb server
+// Increment this when we want to force users to start a new adb server.
+#define ADB_SERVER_VERSION 32
typedef struct amessage amessage;
typedef struct apacket apacket;
@@ -263,33 +266,11 @@
void fatal_errno(const char *fmt, ...);
void handle_packet(apacket *p, atransport *t);
-void send_packet(apacket *p, atransport *t);
void get_my_path(char *s, size_t maxLen);
int launch_server(int server_port);
int adb_main(int is_daemon, int server_port);
-
-/* transports are ref-counted
-** get_device_transport does an acquire on your behalf before returning
-*/
-void init_transport_registration(void);
-int list_transports(char *buf, size_t bufsize, int long_listing);
-void update_transports(void);
-
-asocket* create_device_tracker(void);
-
-/* Obtain a transport from the available transports.
-** If state is != CS_ANY, only transports in that state are considered.
-** If serial is non-NULL then only the device with that serial will be chosen.
-** If no suitable transport is found, error is set.
-*/
-atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char **error_out);
-void add_transport_disconnect( atransport* t, adisconnect* dis );
-void remove_transport_disconnect( atransport* t, adisconnect* dis );
-void run_transport_disconnects( atransport* t );
-void kick_transport( atransport* t );
-
/* initialize a transport object's func pointers and state */
#if ADB_HOST
int get_available_local_transport_index();
@@ -297,22 +278,6 @@
int init_socket_transport(atransport *t, int s, int port, int local);
void init_usb_transport(atransport *t, usb_handle *usb, int state);
-/* for MacOS X cleanup */
-void close_usb_devices();
-
-/* cause new transports to be init'd and added to the list */
-int register_socket_transport(int s, const char *serial, int port, int local);
-
-/* these should only be used for the "adb disconnect" command */
-void unregister_transport(atransport *t);
-void unregister_all_tcp_transports();
-
-void register_usb_transport(usb_handle *h, const char *serial, const char *devpath, unsigned writeable);
-
-/* this should only be used for transports with connection_state == CS_NOPERM */
-void unregister_usb_transport(usb_handle *usb);
-
-atransport *find_transport(const char *serial);
#if ADB_HOST
atransport* find_emulator_transport_by_adb_port(int adb_port);
#endif
@@ -343,9 +308,6 @@
apacket *get_apacket(void);
void put_apacket(apacket *p);
-int check_header(apacket *p);
-int check_data(apacket *p);
-
// Define it if you want to dump packets.
#define DEBUG_PACKETS 0
@@ -400,6 +362,7 @@
#define CS_SIDELOAD 6
#define CS_UNAUTHORIZED 7
+extern const char *adb_device_banner;
extern int HOST;
extern int SHELL_EXIT_NOTIFY_FD;
@@ -424,6 +387,11 @@
int sendfailmsg(int fd, const char *reason);
int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s);
+void handle_online(atransport *t);
+void handle_offline(atransport *t);
+
+void send_connect(atransport *t);
+
#ifdef __cplusplus
}
#endif
diff --git a/adb/adb_auth.c b/adb/adb_auth.c
new file mode 100644
index 0000000..c236b64
--- /dev/null
+++ b/adb/adb_auth.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define TRACE_TAG TRACE_ADB
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "adb.h"
+#include "adb_auth.h"
+#include "transport.h"
+#include "sysdeps.h"
+
+int auth_enabled = 0;
+
+void send_auth_request(atransport *t)
+{
+ D("Calling send_auth_request\n");
+ apacket *p;
+ int ret;
+
+ ret = adb_auth_generate_token(t->token, sizeof(t->token));
+ if (ret != sizeof(t->token)) {
+ D("Error generating token ret=%d\n", ret);
+ return;
+ }
+
+ p = get_apacket();
+ memcpy(p->data, t->token, ret);
+ p->msg.command = A_AUTH;
+ p->msg.arg0 = ADB_AUTH_TOKEN;
+ p->msg.data_length = ret;
+ send_packet(p, t);
+}
+
+void send_auth_response(uint8_t *token, size_t token_size, atransport *t)
+{
+ D("Calling send_auth_response\n");
+ apacket *p = get_apacket();
+ int ret;
+
+ ret = adb_auth_sign(t->key, token, token_size, p->data);
+ if (!ret) {
+ D("Error signing the token\n");
+ put_apacket(p);
+ return;
+ }
+
+ p->msg.command = A_AUTH;
+ p->msg.arg0 = ADB_AUTH_SIGNATURE;
+ p->msg.data_length = ret;
+ send_packet(p, t);
+}
+
+void send_auth_publickey(atransport *t)
+{
+ D("Calling send_auth_publickey\n");
+ apacket *p = get_apacket();
+ int ret;
+
+ ret = adb_auth_get_userkey(p->data, sizeof(p->data));
+ if (!ret) {
+ D("Failed to get user public key\n");
+ put_apacket(p);
+ return;
+ }
+
+ p->msg.command = A_AUTH;
+ p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY;
+ p->msg.data_length = ret;
+ send_packet(p, t);
+}
+
+void adb_auth_verified(atransport *t)
+{
+ handle_online(t);
+ send_connect(t);
+}
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index b718b42..cece5e3 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -21,11 +21,15 @@
extern "C" {
#endif
+extern int auth_enabled;
+
void adb_auth_init(void);
int adb_auth_keygen(const char* filename);
void adb_auth_verified(atransport *t);
void send_auth_request(atransport *t);
+void send_auth_response(uint8_t *token, size_t token_size, atransport *t);
+void send_auth_publickey(atransport *t);
/* AUTH packets first argument */
/* Request */
diff --git a/adb/adb_auth_client.c b/adb/adb_auth_client.c
index 55e9dca..7be883c 100644
--- a/adb/adb_auth_client.c
+++ b/adb/adb_auth_client.c
@@ -14,18 +14,20 @@
* limitations under the License.
*/
+#include <resolv.h>
#include <stdio.h>
#include <string.h>
-#include <resolv.h>
-#include <cutils/list.h>
-#include <cutils/sockets.h>
#include "sysdeps.h"
+
#include "adb.h"
#include "adb_auth.h"
+#include "cutils/list.h"
+#include "cutils/sockets.h"
#include "fdevent.h"
#include "mincrypt/rsa.h"
#include "mincrypt/sha.h"
+#include "transport.h"
#define TRACE_TAG TRACE_AUTH
diff --git a/adb/adb_client.c b/adb/adb_client.c
index ac5e15a..5d2bbd7 100644
--- a/adb/adb_client.c
+++ b/adb/adb_client.c
@@ -1,17 +1,34 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+/*
+ * Copyright (C) 2015 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 <limits.h>
#include <stdarg.h>
-#include <zipfile/zipfile.h>
-#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/stat.h>
+#include <sys/types.h>
#include "sysdeps.h"
#define TRACE_TAG TRACE_ADB
#include "adb_client.h"
+#include "adb_io.h"
+#include "zipfile/zipfile.h"
static transport_type __adb_transport = kTransportAny;
static const char* __adb_serial = NULL;
@@ -121,7 +138,7 @@
len = strlen(service);
snprintf(tmp, sizeof tmp, "%04x", len);
- if(writex(fd, tmp, 4) || writex(fd, service, len)) {
+ if(!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, service, len)) {
strcpy(__adb_error, "write failure during connection");
adb_close(fd);
return -1;
@@ -142,7 +159,7 @@
unsigned char buf[5];
unsigned len;
- if(readx(fd, buf, 4)) {
+ if(!ReadFdExactly(fd, buf, 4)) {
strcpy(__adb_error, "protocol fault (no status)");
return -1;
}
@@ -158,14 +175,14 @@
return -1;
}
- if(readx(fd, buf, 4)) {
+ if(!ReadFdExactly(fd, buf, 4)) {
strcpy(__adb_error, "protocol fault (status len)");
return -1;
}
buf[4] = 0;
len = strtoul((char*)buf, 0, 16);
if(len > 255) len = 255;
- if(readx(fd, __adb_error, len)) {
+ if(!ReadFdExactly(fd, __adb_error, len)) {
strcpy(__adb_error, "protocol fault (status read)");
return -1;
}
@@ -201,7 +218,7 @@
return -1;
}
- if(writex(fd, tmp, 4) || writex(fd, service, len)) {
+ if(!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, service, len)) {
strcpy(__adb_error, "write failure during connection");
adb_close(fd);
return -1;
@@ -246,12 +263,12 @@
// if we have a file descriptor, then parse version result
if(fd >= 0) {
- if(readx(fd, buf, 4)) goto error;
+ if(!ReadFdExactly(fd, buf, 4)) goto error;
buf[4] = 0;
n = strtoul(buf, 0, 16);
if(n > sizeof(buf)) goto error;
- if(readx(fd, buf, n)) goto error;
+ if(!ReadFdExactly(fd, buf, n)) goto error;
adb_close(fd);
if (sscanf(buf, "%04x", &version) != 1) goto error;
@@ -321,7 +338,7 @@
return 0;
}
- if(readx(fd, buf, 4)) goto oops;
+ if(!ReadFdExactly(fd, buf, 4)) goto oops;
buf[4] = 0;
n = strtoul(buf, 0, 16);
@@ -333,7 +350,7 @@
tmp = malloc(n + 1);
if(tmp == 0) goto oops;
- if(readx(fd, tmp, n) == 0) {
+ if(!ReadFdExactly(fd, tmp, n) == 0) {
tmp[n] = 0;
adb_close(fd);
return tmp;
diff --git a/adb/adb_io.cpp b/adb/adb_io.cpp
new file mode 100644
index 0000000..ca208ad
--- /dev/null
+++ b/adb/adb_io.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define TRACE_TAG TRACE_RWX
+
+#include "sysdeps.h"
+#include "adb_io.h"
+
+#include <unistd.h>
+
+#include "adb_trace.h"
+#include "transport.h"
+
+bool ReadFdExactly(int fd, void* buf, size_t len) {
+ char* p = reinterpret_cast<char*>(buf);
+
+#if ADB_TRACE
+ size_t len0 = len;
+#endif
+
+ D("readx: fd=%d wanted=%zu\n", fd, len);
+ while (len > 0) {
+ int r = TEMP_FAILURE_RETRY(adb_read(fd, p, len));
+ if (r > 0) {
+ len -= r;
+ p += r;
+ } else if (r == -1) {
+ D("readx: fd=%d error %d: %s\n", fd, errno, strerror(errno));
+ return false;
+ } else {
+ D("readx: fd=%d disconnected\n", fd);
+ errno = 0;
+ return false;
+ }
+ }
+
+#if ADB_TRACE
+ D("readx: fd=%d wanted=%zu got=%zu\n", fd, len0, len0 - len);
+ if (ADB_TRACING) {
+ dump_hex(reinterpret_cast<const unsigned char*>(buf), len0);
+ }
+#endif
+
+ return true;
+}
+
+bool WriteFdExactly(int fd, const void* buf, size_t len) {
+ const char* p = reinterpret_cast<const char*>(buf);
+ int r;
+
+#if ADB_TRACE
+ D("writex: fd=%d len=%d: ", fd, (int)len);
+ if (ADB_TRACING) {
+ dump_hex(reinterpret_cast<const unsigned char*>(buf), len);
+ }
+#endif
+
+ while (len > 0) {
+ r = TEMP_FAILURE_RETRY(adb_write(fd, p, len));
+ if (r == -1) {
+ D("writex: fd=%d error %d: %s\n", fd, errno, strerror(errno));
+ if (errno == EAGAIN) {
+ adb_sleep_ms(1); // just yield some cpu time
+ continue;
+ } else if (errno == EPIPE) {
+ D("writex: fd=%d disconnected\n", fd);
+ errno = 0;
+ return false;
+ }
+ } else {
+ len -= r;
+ p += r;
+ }
+ }
+ return true;
+}
+
+bool WriteStringFully(int fd, const char* str) {
+ return WriteFdExactly(fd, str, strlen(str));
+}
diff --git a/adb/adb_io.h b/adb/adb_io.h
new file mode 100644
index 0000000..7d09e7b
--- /dev/null
+++ b/adb/adb_io.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 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 ADB_IO_H
+#define ADB_IO_H
+
+#include <stdbool.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Reads exactly len bytes from fd into buf.
+ *
+ * Returns false if there is an error or if EOF was reached before len bytes
+ * were read. If EOF was found, errno will be set to 0.
+ *
+ * If this function fails, the contents of buf are undefined.
+ */
+bool ReadFdExactly(int fd, void *buf, size_t len);
+
+/*
+ * Writes exactly len bytes from buf to fd.
+ *
+ * Returns false if there is an error or if the fd was closed before the write
+ * completed. If the other end of the fd (such as in a socket, pipe, or fifo),
+ * is closed, errno will be set to 0.
+ */
+bool WriteFdExactly(int fd, const void *buf, size_t len);
+
+/* Same as WriteFdExactly, but with an implicit len = strlen(buf). */
+bool WriteStringFully(int fd, const char* str);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ADB_IO_H */
diff --git a/adb/adb_io_test.cpp b/adb/adb_io_test.cpp
new file mode 100644
index 0000000..330d9ce
--- /dev/null
+++ b/adb/adb_io_test.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2015 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 "adb_io.h"
+
+#include <gtest/gtest.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <string>
+
+#include "utils/file.h"
+
+class TemporaryFile {
+ public:
+ TemporaryFile() {
+ init("/data/local/tmp");
+ if (fd == -1) {
+ init("/tmp");
+ }
+ }
+
+ ~TemporaryFile() {
+ close(fd);
+ unlink(filename);
+ }
+
+ int fd;
+ char filename[1024];
+
+ private:
+ void init(const char* tmp_dir) {
+ snprintf(filename, sizeof(filename), "%s/TemporaryFile-XXXXXX", tmp_dir);
+ fd = mkstemp(filename);
+ }
+};
+
+TEST(io, ReadFdExactly_whole) {
+ const char expected[] = "Foobar";
+ TemporaryFile tf;
+ ASSERT_NE(-1, tf.fd);
+
+ ASSERT_TRUE(android::WriteStringToFd(expected, tf.fd)) << strerror(errno);
+ ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+
+ // Test reading the whole file.
+ char buf[sizeof(expected)] = {};
+ ASSERT_TRUE(ReadFdExactly(tf.fd, buf, sizeof(buf) - 1)) << strerror(errno);
+ EXPECT_STREQ(expected, buf);
+}
+
+TEST(io, ReadFdExactly_eof) {
+ const char expected[] = "Foobar";
+ TemporaryFile tf;
+ ASSERT_NE(-1, tf.fd);
+
+ ASSERT_TRUE(android::WriteStringToFd(expected, tf.fd)) << strerror(errno);
+ ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+
+ // Test that not having enough data will fail.
+ char buf[sizeof(expected) + 1] = {};
+ ASSERT_FALSE(ReadFdExactly(tf.fd, buf, sizeof(buf)));
+ EXPECT_EQ(0, errno) << strerror(errno);
+}
+
+TEST(io, ReadFdExactly_partial) {
+ const char input[] = "Foobar";
+ TemporaryFile tf;
+ ASSERT_NE(-1, tf.fd);
+
+ ASSERT_TRUE(android::WriteStringToFd(input, tf.fd)) << strerror(errno);
+ ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+
+ // Test reading a partial file.
+ char buf[sizeof(input) - 1] = {};
+ ASSERT_TRUE(ReadFdExactly(tf.fd, buf, sizeof(buf) - 1));
+
+ std::string expected(input);
+ expected.pop_back();
+ EXPECT_STREQ(expected.c_str(), buf);
+}
+
+TEST(io, WriteFdExactly_whole) {
+ const char expected[] = "Foobar";
+ TemporaryFile tf;
+ ASSERT_NE(-1, tf.fd);
+
+ // Test writing the whole string to the file.
+ ASSERT_TRUE(WriteFdExactly(tf.fd, expected, sizeof(expected)))
+ << strerror(errno);
+ ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+
+ std::string s;
+ ASSERT_TRUE(android::ReadFdToString(tf.fd, &s));
+ EXPECT_STREQ(expected, s.c_str());
+}
+
+TEST(io, WriteFdExactly_partial) {
+ const char buf[] = "Foobar";
+ TemporaryFile tf;
+ ASSERT_NE(-1, tf.fd);
+
+ // Test writing a partial string to the file.
+ ASSERT_TRUE(WriteFdExactly(tf.fd, buf, sizeof(buf) - 2)) << strerror(errno);
+ ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+
+ std::string expected(buf);
+ expected.pop_back();
+
+ std::string s;
+ ASSERT_TRUE(android::ReadFdToString(tf.fd, &s));
+ EXPECT_EQ(expected, s);
+}
+
+TEST(io, WriteStringFully) {
+ const char str[] = "Foobar";
+ TemporaryFile tf;
+ ASSERT_NE(-1, tf.fd);
+
+ // Test writing a partial string to the file.
+ ASSERT_TRUE(WriteStringFully(tf.fd, str)) << strerror(errno);
+ ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+
+ std::string s;
+ ASSERT_TRUE(android::ReadFdToString(tf.fd, &s));
+ EXPECT_STREQ(str, s.c_str());
+}
diff --git a/adb/adb_listeners.c b/adb/adb_listeners.c
new file mode 100644
index 0000000..f68b876
--- /dev/null
+++ b/adb/adb_listeners.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2015 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 "adb_listeners.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "sysdeps.h"
+#include "transport.h"
+
+int gListenAll = 0; /* Not static because it is used in commandline.c. */
+
+alistener listener_list = {
+ .next = &listener_list,
+ .prev = &listener_list,
+};
+
+void ss_listener_event_func(int _fd, unsigned ev, void *_l)
+{
+ asocket *s;
+
+ if(ev & FDE_READ) {
+ struct sockaddr addr;
+ socklen_t alen;
+ int fd;
+
+ alen = sizeof(addr);
+ fd = adb_socket_accept(_fd, &addr, &alen);
+ if(fd < 0) return;
+
+ adb_socket_setbufsize(fd, CHUNK_SIZE);
+
+ s = create_local_socket(fd);
+ if(s) {
+ connect_to_smartsocket(s);
+ return;
+ }
+
+ adb_close(fd);
+ }
+}
+
+void listener_event_func(int _fd, unsigned ev, void *_l)
+{
+ alistener *l = _l;
+ asocket *s;
+
+ if(ev & FDE_READ) {
+ struct sockaddr addr;
+ socklen_t alen;
+ int fd;
+
+ alen = sizeof(addr);
+ fd = adb_socket_accept(_fd, &addr, &alen);
+ if(fd < 0) return;
+
+ s = create_local_socket(fd);
+ if(s) {
+ s->transport = l->transport;
+ connect_to_remote(s, l->connect_to);
+ return;
+ }
+
+ adb_close(fd);
+ }
+}
+
+static void free_listener(alistener* l)
+{
+ if (l->next) {
+ l->next->prev = l->prev;
+ l->prev->next = l->next;
+ l->next = l->prev = l;
+ }
+
+ // closes the corresponding fd
+ fdevent_remove(&l->fde);
+
+ if (l->local_name)
+ free((char*)l->local_name);
+
+ if (l->connect_to)
+ free((char*)l->connect_to);
+
+ if (l->transport) {
+ remove_transport_disconnect(l->transport, &l->disconnect);
+ }
+ free(l);
+}
+
+void listener_disconnect(void* _l, atransport* t)
+{
+ alistener* l = _l;
+
+ free_listener(l);
+}
+
+int local_name_to_fd(const char *name)
+{
+ int port;
+
+ if(!strncmp("tcp:", name, 4)){
+ int ret;
+ port = atoi(name + 4);
+
+ 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 */
+ // It's non-sensical to support the "reserved" space on the adb host side
+ if(!strncmp(name, "local:", 6)) {
+ return socket_local_server(name + 6,
+ ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+ } else if(!strncmp(name, "localabstract:", 14)) {
+ return socket_local_server(name + 14,
+ ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+ } else if(!strncmp(name, "localfilesystem:", 16)) {
+ return socket_local_server(name + 16,
+ ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
+ }
+
+#endif
+ printf("unknown local portname '%s'\n", name);
+ return -1;
+}
+
+// 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:
+ //
+ // <device-serial> " " <local-name> " " <remote-name> "\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.
+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;
+}
+
+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)) {
+ listener_disconnect(l, l->transport);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+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);
+ }
+}
+
+install_status_t install_listener(const char *local_name,
+ const char *connect_to,
+ atransport* transport,
+ int no_rebind)
+{
+ alistener *l;
+
+ //printf("install_listener('%s','%s')\n", local_name, connect_to);
+
+ for(l = listener_list.next; l != &listener_list; l = l->next){
+ if(strcmp(local_name, l->local_name) == 0) {
+ char *cto;
+
+ /* can't repurpose a smartsocket */
+ if(l->connect_to[0] == '*') {
+ 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 INSTALL_STATUS_INTERNAL_ERROR;
+ }
+
+ //printf("rebinding '%s' to '%s'\n", local_name, connect_to);
+ free((void*) l->connect_to);
+ l->connect_to = cto;
+ if (l->transport != transport) {
+ remove_transport_disconnect(l->transport, &l->disconnect);
+ l->transport = transport;
+ add_transport_disconnect(l->transport, &l->disconnect);
+ }
+ return INSTALL_STATUS_OK;
+ }
+ }
+
+ if((l = calloc(1, sizeof(alistener))) == 0) goto nomem;
+ if((l->local_name = strdup(local_name)) == 0) goto nomem;
+ if((l->connect_to = strdup(connect_to)) == 0) goto nomem;
+
+
+ l->fd = local_name_to_fd(local_name);
+ if(l->fd < 0) {
+ free((void*) l->local_name);
+ free((void*) l->connect_to);
+ free(l);
+ printf("cannot bind '%s'\n", local_name);
+ return -2;
+ }
+
+ close_on_exec(l->fd);
+ if(!strcmp(l->connect_to, "*smartsocket*")) {
+ fdevent_install(&l->fde, l->fd, ss_listener_event_func, l);
+ } else {
+ fdevent_install(&l->fde, l->fd, listener_event_func, l);
+ }
+ fdevent_set(&l->fde, FDE_READ);
+
+ l->next = &listener_list;
+ l->prev = listener_list.prev;
+ l->next->prev = l;
+ l->prev->next = l;
+ l->transport = transport;
+
+ if (transport) {
+ l->disconnect.opaque = l;
+ l->disconnect.func = listener_disconnect;
+ add_transport_disconnect(transport, &l->disconnect);
+ }
+ return INSTALL_STATUS_OK;
+
+nomem:
+ fatal("cannot allocate listener");
+ return INSTALL_STATUS_INTERNAL_ERROR;
+}
diff --git a/adb/adb_listeners.h b/adb/adb_listeners.h
new file mode 100644
index 0000000..14fdcd6
--- /dev/null
+++ b/adb/adb_listeners.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 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 __ADB_LISTENERS_H
+#define __ADB_LISTENERS_H
+
+#include "adb.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// 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;
+
+extern alistener listener_list;
+
+void listener_disconnect(void* _l, atransport* t);
+void listener_event_func(int _fd, unsigned ev, void *_l);
+void ss_listener_event_func(int _fd, unsigned ev, void *_l);
+
+install_status_t install_listener(const char *local_name,
+ const char *connect_to,
+ atransport* transport,
+ int no_rebind);
+
+int format_listeners(char* buf, size_t buflen);
+
+int remove_listener(const char *local_name, atransport* transport);
+void remove_all_listeners(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ADB_LISTENERS_H */
diff --git a/adb/adb_main.c b/adb/adb_main.c
new file mode 100644
index 0000000..f8475c7
--- /dev/null
+++ b/adb/adb_main.c
@@ -0,0 +1,421 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define TRACE_TAG TRACE_ADB
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "sysdeps.h"
+
+#include "adb.h"
+#include "adb_auth.h"
+#include "adb_listeners.h"
+#include "transport.h"
+
+#if !ADB_HOST
+#include <getopt.h>
+#include <sys/prctl.h>
+
+#include "cutils/properties.h"
+#include "private/android_filesystem_config.h"
+#include "selinux/selinux.h"
+
+#include "qemu_tracing.h"
+#endif
+
+static void adb_cleanup(void)
+{
+ usb_cleanup();
+}
+
+#if defined(_WIN32)
+static BOOL WINAPI ctrlc_handler(DWORD type)
+{
+ exit(STATUS_CONTROL_C_EXIT);
+ return TRUE;
+}
+#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
+#else /* ADB_HOST */
+static const char *root_seclabel = NULL;
+
+static void drop_capabilities_bounding_set_if_needed() {
+#ifdef ALLOW_ADBD_ROOT
+ char value[PROPERTY_VALUE_MAX];
+ property_get("ro.debuggable", value, "");
+ if (strcmp(value, "1") == 0) {
+ return;
+ }
+#endif
+ int i;
+ for (i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
+ if (i == CAP_SETUID || i == CAP_SETGID) {
+ // CAP_SETUID CAP_SETGID needed by /system/bin/run-as
+ continue;
+ }
+ int err = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
+
+ // Some kernels don't have file capabilities compiled in, and
+ // prctl(PR_CAPBSET_DROP) returns EINVAL. Don't automatically
+ // die when we see such misconfigured kernels.
+ if ((err < 0) && (errno != EINVAL)) {
+ exit(1);
+ }
+ }
+}
+
+static bool should_drop_privileges() {
+#if defined(ALLOW_ADBD_ROOT)
+ char value[PROPERTY_VALUE_MAX];
+
+ // The properties that affect `adb root` and `adb unroot` are ro.secure and
+ // ro.debuggable. In this context the names don't make the expected behavior
+ // particularly obvious.
+ //
+ // ro.debuggable:
+ // Allowed to become root, but not necessarily the default. Set to 1 on
+ // eng and userdebug builds.
+ //
+ // ro.secure:
+ // Drop privileges by default. Set to 1 on userdebug and user builds.
+ property_get("ro.secure", value, "1");
+ bool ro_secure = (strcmp(value, "1") == 0);
+
+ property_get("ro.debuggable", value, "");
+ bool ro_debuggable = (strcmp(value, "1") == 0);
+
+ // Drop privileges if ro.secure is set...
+ bool drop = ro_secure;
+
+ property_get("service.adb.root", value, "");
+ bool adb_root = (strcmp(value, "1") == 0);
+ bool adb_unroot = (strcmp(value, "0") == 0);
+
+ // ...except "adb root" lets you keep privileges in a debuggable build.
+ if (ro_debuggable && adb_root) {
+ drop = false;
+ }
+
+ // ...and "adb unroot" lets you explicitly drop privileges.
+ if (adb_unroot) {
+ drop = true;
+ }
+
+ return drop;
+#else
+ return true; // "adb root" not allowed, always drop privileges.
+#endif /* ALLOW_ADBD_ROOT */
+}
+
+void start_device_log(void)
+{
+ int fd;
+ char path[PATH_MAX];
+ struct tm now;
+ time_t t;
+ char value[PROPERTY_VALUE_MAX];
+
+ // read the trace mask from persistent property persist.adb.trace_mask
+ // give up if the property is not set or cannot be parsed
+ property_get("persist.adb.trace_mask", value, "");
+ if (sscanf(value, "%x", &adb_trace_mask) != 1)
+ return;
+
+ adb_mkdir("/data/adb", 0775);
+ tzset();
+ time(&t);
+ localtime_r(&t, &now);
+ strftime(path, sizeof(path),
+ "/data/adb/adb-%Y-%m-%d-%H-%M-%S.txt",
+ &now);
+ fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0640);
+ if (fd < 0)
+ return;
+
+ // redirect stdout and stderr to the log file
+ dup2(fd, 1);
+ dup2(fd, 2);
+ fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
+ adb_close(fd);
+
+ fd = unix_open("/dev/null", O_RDONLY);
+ dup2(fd, 0);
+ adb_close(fd);
+}
+#endif /* ADB_HOST */
+
+/* Constructs a local name of form tcp:port.
+ * target_str points to the target string, it's content will be overwritten.
+ * target_size is the capacity of the target string.
+ * server_port is the port number to use for the local name.
+ */
+void build_local_name(char* target_str, size_t target_size, int server_port)
+{
+ snprintf(target_str, target_size, "tcp:%d", server_port);
+}
+
+void start_logging(void)
+{
+#if defined(_WIN32)
+ char temp[ MAX_PATH ];
+ FILE* fnul;
+ FILE* flog;
+
+ GetTempPath( sizeof(temp) - 8, temp );
+ strcat( temp, "adb.log" );
+
+ /* Win32 specific redirections */
+ fnul = fopen( "NUL", "rt" );
+ if (fnul != NULL)
+ stdin[0] = fnul[0];
+
+ flog = fopen( temp, "at" );
+ if (flog == NULL)
+ flog = fnul;
+
+ setvbuf( flog, NULL, _IONBF, 0 );
+
+ stdout[0] = flog[0];
+ stderr[0] = flog[0];
+ fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
+#else
+ int fd;
+
+ fd = unix_open("/dev/null", O_RDONLY);
+ dup2(fd, 0);
+ adb_close(fd);
+
+ fd = unix_open("/tmp/adb.log", O_WRONLY | O_CREAT | O_APPEND, 0640);
+ if(fd < 0) {
+ fd = unix_open("/dev/null", O_WRONLY);
+ }
+ dup2(fd, 1);
+ dup2(fd, 2);
+ adb_close(fd);
+ fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
+#endif
+}
+
+int adb_main(int is_daemon, int server_port)
+{
+#if !ADB_HOST
+ int port;
+ char value[PROPERTY_VALUE_MAX];
+
+ umask(000);
+#endif
+
+ atexit(adb_cleanup);
+#if defined(_WIN32)
+ SetConsoleCtrlHandler( ctrlc_handler, TRUE );
+#else
+ // No SIGCHLD. Let the service subproc handle its children.
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
+ init_transport_registration();
+
+#if ADB_HOST
+ HOST = 1;
+
+#ifdef WORKAROUND_BUG6558362
+ if(is_daemon) adb_set_affinity();
+#endif
+ usb_init();
+ local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
+ adb_auth_init();
+
+ char local_name[30];
+ build_local_name(local_name, sizeof(local_name), server_port);
+ if(install_listener(local_name, "*smartsocket*", NULL, 0)) {
+ exit(1);
+ }
+#else
+ property_get("ro.adb.secure", value, "0");
+ auth_enabled = !strcmp(value, "1");
+ if (auth_enabled)
+ adb_auth_init();
+
+ // Our external storage path may be different than apps, since
+ // we aren't able to bind mount after dropping root.
+ const char* adb_external_storage = getenv("ADB_EXTERNAL_STORAGE");
+ if (NULL != adb_external_storage) {
+ setenv("EXTERNAL_STORAGE", adb_external_storage, 1);
+ } else {
+ D("Warning: ADB_EXTERNAL_STORAGE is not set. Leaving EXTERNAL_STORAGE"
+ " unchanged.\n");
+ }
+
+ /* add extra groups:
+ ** AID_ADB to access the USB driver
+ ** AID_LOG to read system logs (adb logcat)
+ ** AID_INPUT to diagnose input issues (getevent)
+ ** AID_INET to diagnose network issues (ping)
+ ** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump)
+ ** AID_SDCARD_R to allow reading from the SD card
+ ** AID_SDCARD_RW to allow writing to the SD card
+ ** AID_NET_BW_STATS to read out qtaguid statistics
+ */
+ gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_NET_BT,
+ AID_NET_BT_ADMIN, AID_SDCARD_R, AID_SDCARD_RW,
+ AID_NET_BW_STATS };
+ if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
+ exit(1);
+ }
+
+ /* don't listen on a port (default 5037) if running in secure mode */
+ /* don't run as root if we are running in secure mode */
+ if (should_drop_privileges()) {
+ drop_capabilities_bounding_set_if_needed();
+
+ /* then switch user and group to "shell" */
+ if (setgid(AID_SHELL) != 0) {
+ exit(1);
+ }
+ if (setuid(AID_SHELL) != 0) {
+ exit(1);
+ }
+
+ D("Local port disabled\n");
+ } else {
+ char local_name[30];
+ if ((root_seclabel != NULL) && (is_selinux_enabled() > 0)) {
+ // b/12587913: fix setcon to allow const pointers
+ if (setcon((char *)root_seclabel) < 0) {
+ exit(1);
+ }
+ }
+ build_local_name(local_name, sizeof(local_name), server_port);
+ if(install_listener(local_name, "*smartsocket*", NULL, 0)) {
+ exit(1);
+ }
+ }
+
+ int usb = 0;
+ if (access(USB_ADB_PATH, F_OK) == 0 || access(USB_FFS_ADB_EP0, F_OK) == 0) {
+ // listen on USB
+ usb_init();
+ usb = 1;
+ }
+
+ // If one of these properties is set, also listen on that port
+ // If one of the properties isn't set and we couldn't listen on usb,
+ // listen on the default port.
+ property_get("service.adb.tcp.port", value, "");
+ if (!value[0]) {
+ property_get("persist.adb.tcp.port", value, "");
+ }
+ if (sscanf(value, "%d", &port) == 1 && port > 0) {
+ printf("using port=%d\n", port);
+ // listen on TCP port specified by service.adb.tcp.port property
+ local_init(port);
+ } else if (!usb) {
+ // listen on default port
+ local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
+ }
+
+ D("adb_main(): pre init_jdwp()\n");
+ init_jdwp();
+ D("adb_main(): post init_jdwp()\n");
+#endif
+
+ if (is_daemon)
+ {
+ // inform our parent that we are up and running.
+#if defined(_WIN32)
+ DWORD count;
+ WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ), "OK\n", 3, &count, NULL );
+#else
+ fprintf(stderr, "OK\n");
+#endif
+ start_logging();
+ }
+ D("Event loop starting\n");
+
+ fdevent_loop();
+
+ usb_cleanup();
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+#if ADB_HOST
+ adb_sysdeps_init();
+ adb_trace_init();
+ D("Handling commandline()\n");
+ return adb_commandline(argc - 1, argv + 1);
+#else
+ /* If adbd runs inside the emulator this will enable adb tracing via
+ * adb-debug qemud service in the emulator. */
+ adb_qemu_trace_init();
+ while(1) {
+ int c;
+ int option_index = 0;
+ static struct option opts[] = {
+ {"root_seclabel", required_argument, 0, 's' },
+ {"device_banner", required_argument, 0, 'b' }
+ };
+ c = getopt_long(argc, argv, "", opts, &option_index);
+ if (c == -1)
+ break;
+ switch (c) {
+ case 's':
+ root_seclabel = optarg;
+ break;
+ case 'b':
+ adb_device_banner = optarg;
+ break;
+ default:
+ break;
+ }
+ }
+
+ start_device_log();
+ D("Handling main()\n");
+ return adb_main(0, DEFAULT_ADB_PORT);
+#endif
+}
diff --git a/adb/adb_trace.h b/adb/adb_trace.h
index 69b6c69..ef5dc24 100644
--- a/adb/adb_trace.h
+++ b/adb/adb_trace.h
@@ -19,6 +19,8 @@
#if !ADB_HOST
#include <android/log.h>
+#else
+#include <stdio.h>
#endif
#ifdef __cplusplus
diff --git a/adb/commandline.c b/adb/commandline.c
index 830f290..a8ad7bd 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -14,29 +14,30 @@
* limitations under the License.
*/
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
+#include <assert.h>
+#include <ctype.h>
#include <errno.h>
-#include <unistd.h>
#include <limits.h>
#include <stdarg.h>
-#include <sys/types.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/stat.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include "sysdeps.h"
+#include <sys/types.h>
#if !defined(_WIN32)
#include <termios.h>
+#include <unistd.h>
#endif
+#include "sysdeps.h"
+
#define TRACE_TAG TRACE_ADB
#include "adb.h"
-#include "adb_client.h"
#include "adb_auth.h"
+#include "adb_client.h"
+#include "adb_io.h"
#include "file_sync_service.h"
static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
@@ -485,7 +486,7 @@
while(sz > 0) {
unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
- if(writex(fd, ptr, xfer)) {
+ if(!WriteFdExactly(fd, ptr, xfer)) {
adb_status(fd);
fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
return -1;
@@ -501,7 +502,7 @@
printf("\n");
}
- if(readx(fd, buf, 4)){
+ if(!ReadFdExactly(fd, buf, 4)){
fprintf(stderr,"* error reading response *\n");
adb_close(fd);
return -1;
@@ -586,7 +587,7 @@
int last_percent = -1;
for (;;) {
- if (readx(fd, buf, 8)) {
+ if (!ReadFdExactly(fd, buf, 8)) {
fprintf(stderr, "* failed to read command: %s\n", adb_error());
status = -1;
goto done;
@@ -613,7 +614,7 @@
to_write = sz - offset;
}
- if(writex(fd, start, to_write)) {
+ if(!WriteFdExactly(fd, start, to_write)) {
adb_status(fd);
fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
status = -1;
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index bd0f3b2..45d33db 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -28,9 +28,9 @@
#include <stdarg.h>
#include <stddef.h>
+#include "adb_io.h"
#include "adb_trace.h"
#include "fdevent.h"
-#include "transport.h"
#include "sysdeps.h"
#define TRACE_TAG TRACE_FDEVENT
@@ -528,7 +528,7 @@
if(ev & FDE_READ){
int subproc_fd;
- if(readx(fd, &subproc_fd, sizeof(subproc_fd))) {
+ if(!ReadFdExactly(fd, &subproc_fd, sizeof(subproc_fd))) {
FATAL("Failed to read the subproc's fd from fd=%d\n", fd);
}
if((subproc_fd < 0) || (subproc_fd >= fd_table_max)) {
diff --git a/adb/file_sync_client.c b/adb/file_sync_client.c
index f93c876..3a0c666 100644
--- a/adb/file_sync_client.c
+++ b/adb/file_sync_client.c
@@ -14,24 +14,25 @@
* limitations under the License.
*/
+#include <dirent.h>
+#include <errno.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <errno.h>
#include <sys/stat.h>
#include <sys/time.h>
-#include <time.h>
-#include <dirent.h>
-#include <limits.h>
#include <sys/types.h>
-#include <zipfile/zipfile.h>
+#include <time.h>
#include <utime.h>
#include "sysdeps.h"
+
#include "adb.h"
#include "adb_client.h"
+#include "adb_io.h"
#include "file_sync_service.h"
-
+#include "zipfile/zipfile.h"
static unsigned long long total_bytes;
static long long start_time;
@@ -86,7 +87,7 @@
msg.req.id = ID_QUIT;
msg.req.namelen = 0;
- writex(fd, &msg.req, sizeof(msg.req));
+ WriteFdExactly(fd, &msg.req, sizeof(msg.req));
}
typedef void (*sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char *name, void *cookie);
@@ -103,20 +104,20 @@
msg.req.id = ID_LIST;
msg.req.namelen = htoll(len);
- if(writex(fd, &msg.req, sizeof(msg.req)) ||
- writex(fd, path, len)) {
+ if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) ||
+ !WriteFdExactly(fd, path, len)) {
goto fail;
}
for(;;) {
- if(readx(fd, &msg.dent, sizeof(msg.dent))) break;
+ if(!ReadFdExactly(fd, &msg.dent, sizeof(msg.dent))) break;
if(msg.dent.id == ID_DONE) return 0;
if(msg.dent.id != ID_DENT) break;
len = ltohl(msg.dent.namelen);
if(len > 256) break;
- if(readx(fd, buf, len)) break;
+ if(!ReadFdExactly(fd, buf, len)) break;
buf[len] = 0;
func(ltohl(msg.dent.mode),
@@ -149,12 +150,12 @@
msg.req.id = ID_STAT;
msg.req.namelen = htoll(len);
- if(writex(fd, &msg.req, sizeof(msg.req)) ||
- writex(fd, path, len)) {
+ if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) ||
+ !WriteFdExactly(fd, path, len)) {
return -1;
}
- if(readx(fd, &msg.stat, sizeof(msg.stat))) {
+ if(!ReadFdExactly(fd, &msg.stat, sizeof(msg.stat))) {
return -1;
}
@@ -175,8 +176,8 @@
msg.req.id = ID_STAT;
msg.req.namelen = htoll(len);
- if(writex(fd, &msg.req, sizeof(msg.req)) ||
- writex(fd, path, len)) {
+ if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) ||
+ !WriteFdExactly(fd, path, len)) {
return -1;
}
@@ -188,7 +189,7 @@
{
syncmsg msg;
- if(readx(fd, &msg.stat, sizeof(msg.stat)))
+ if(!ReadFdExactly(fd, &msg.stat, sizeof(msg.stat)))
return -1;
if(msg.stat.id != ID_STAT)
@@ -209,12 +210,12 @@
msg.req.id = ID_STAT;
msg.req.namelen = htoll(len);
- if(writex(fd, &msg.req, sizeof(msg.req)) ||
- writex(fd, path, len)) {
+ if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) ||
+ !WriteFdExactly(fd, path, len)) {
return -1;
}
- if(readx(fd, &msg.stat, sizeof(msg.stat))) {
+ if(!ReadFdExactly(fd, &msg.stat, sizeof(msg.stat))) {
return -1;
}
@@ -264,7 +265,7 @@
}
sbuf->size = htoll(ret);
- if(writex(fd, sbuf, sizeof(unsigned) * 2 + ret)){
+ if(!WriteFdExactly(fd, sbuf, sizeof(unsigned) * 2 + ret)){
err = -1;
break;
}
@@ -294,7 +295,7 @@
memcpy(sbuf->data, &file_buffer[total], count);
sbuf->size = htoll(count);
- if(writex(fd, sbuf, sizeof(unsigned) * 2 + count)){
+ if(!WriteFdExactly(fd, sbuf, sizeof(unsigned) * 2 + count)){
err = -1;
break;
}
@@ -326,7 +327,7 @@
sbuf->size = htoll(len + 1);
sbuf->id = ID_DATA;
- ret = writex(fd, sbuf, sizeof(unsigned) * 2 + len + 1);
+ ret = !WriteFdExactly(fd, sbuf, sizeof(unsigned) * 2 + len + 1);
if(ret)
return -1;
@@ -355,8 +356,8 @@
msg.req.id = ID_SEND;
msg.req.namelen = htoll(len + r);
- if(writex(fd, &msg.req, sizeof(msg.req)) ||
- writex(fd, rpath, len) || writex(fd, tmp, r)) {
+ if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) ||
+ !WriteFdExactly(fd, rpath, len) || !WriteFdExactly(fd, tmp, r)) {
free(file_buffer);
goto fail;
}
@@ -373,17 +374,17 @@
msg.data.id = ID_DONE;
msg.data.size = htoll(mtime);
- if(writex(fd, &msg.data, sizeof(msg.data)))
+ if(!WriteFdExactly(fd, &msg.data, sizeof(msg.data)))
goto fail;
- if(readx(fd, &msg.status, sizeof(msg.status)))
+ if(!ReadFdExactly(fd, &msg.status, sizeof(msg.status)))
return -1;
if(msg.status.id != ID_OKAY) {
if(msg.status.id == ID_FAIL) {
len = ltohl(msg.status.msglen);
if(len > 256) len = 256;
- if(readx(fd, sbuf->data, len)) {
+ if(!ReadFdExactly(fd, sbuf->data, len)) {
return -1;
}
sbuf->data[len] = 0;
@@ -439,12 +440,12 @@
stat_msg.req.id = ID_STAT;
stat_msg.req.namelen = htoll(len);
- if (writex(fd, &stat_msg.req, sizeof(stat_msg.req)) ||
- writex(fd, rpath, len)) {
+ if (!WriteFdExactly(fd, &stat_msg.req, sizeof(stat_msg.req)) ||
+ !WriteFdExactly(fd, rpath, len)) {
return -1;
}
- if (readx(fd, &stat_msg.stat, sizeof(stat_msg.stat))) {
+ if (!ReadFdExactly(fd, &stat_msg.stat, sizeof(stat_msg.stat))) {
return -1;
}
@@ -455,12 +456,12 @@
msg.req.id = ID_RECV;
msg.req.namelen = htoll(len);
- if(writex(fd, &msg.req, sizeof(msg.req)) ||
- writex(fd, rpath, len)) {
+ if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) ||
+ !WriteFdExactly(fd, rpath, len)) {
return -1;
}
- if(readx(fd, &msg.data, sizeof(msg.data))) {
+ if(!ReadFdExactly(fd, &msg.data, sizeof(msg.data))) {
return -1;
}
id = msg.data.id;
@@ -479,7 +480,7 @@
}
for(;;) {
- if(readx(fd, &msg.data, sizeof(msg.data))) {
+ if(!ReadFdExactly(fd, &msg.data, sizeof(msg.data))) {
return -1;
}
id = msg.data.id;
@@ -494,12 +495,12 @@
return -1;
}
- if(readx(fd, buffer, len)) {
+ if(!ReadFdExactly(fd, buffer, len)) {
adb_close(lfd);
return -1;
}
- if(writex(lfd, buffer, len)) {
+ if(!WriteFdExactly(lfd, buffer, len)) {
fprintf(stderr,"cannot write '%s': %s\n", rpath, strerror(errno));
adb_close(lfd);
return -1;
@@ -522,24 +523,19 @@
if(id == ID_FAIL) {
len = ltohl(msg.data.size);
if(len > 256) len = 256;
- if(readx(fd, buffer, len)) {
+ if(!ReadFdExactly(fd, buffer, len)) {
return -1;
}
buffer[len] = 0;
} else {
memcpy(buffer, &id, 4);
buffer[4] = 0;
-// strcpy(buffer,"unknown reason");
}
fprintf(stderr,"failed to copy '%s' to '%s': %s\n", rpath, lpath, buffer);
return 0;
}
-
-
/* --- */
-
-
static void do_sync_ls_cb(unsigned mode, unsigned size, unsigned time,
const char *name, void *cookie)
{
@@ -573,7 +569,6 @@
unsigned int mode;
unsigned int size;
int flag;
- //char data[0];
};
copyinfo *mkcopyinfo(const char *spath, const char *dpath,
@@ -601,7 +596,6 @@
snprintf((char*) ci->src, ssize, isdir ? "%s%s/" : "%s%s", spath, name);
snprintf((char*) ci->dst, dsize, isdir ? "%s%s/" : "%s%s", dpath, name);
-// fprintf(stderr,"mkcopyinfo('%s','%s')\n", ci->src, ci->dst);
return ci;
}
@@ -615,8 +609,6 @@
copyinfo *dirlist = 0;
copyinfo *ci, *next;
-// fprintf(stderr,"local_build_list('%s','%s')\n", lpath, rpath);
-
d = opendir(lpath);
if(d == 0) {
fprintf(stderr,"cannot open '%s': %s\n", lpath, strerror(errno));
diff --git a/adb/file_sync_service.c b/adb/file_sync_service.c
index 7de82b7..0b289e8 100644
--- a/adb/file_sync_service.c
+++ b/adb/file_sync_service.c
@@ -14,24 +14,24 @@
* limitations under the License.
*/
-#include <stdlib.h>
+#include <dirent.h>
+#include <errno.h>
+#include <selinux/android.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-
#include <sys/stat.h>
#include <sys/types.h>
-#include <dirent.h>
-#include <utime.h>
#include <unistd.h>
+#include <utime.h>
-#include <errno.h>
-#include <private/android_filesystem_config.h>
-#include <selinux/android.h>
#include "sysdeps.h"
#define TRACE_TAG TRACE_SYNC
#include "adb.h"
+#include "adb_io.h"
#include "file_sync_service.h"
+#include "private/android_filesystem_config.h"
/* TODO: use fs_config to configure permissions on /data */
static bool is_on_system(const char *name) {
@@ -97,7 +97,7 @@
msg.stat.time = htoll(st.st_mtime);
}
- return writex(s, &msg.stat, sizeof(msg.stat));
+ return WriteFdExactly(s, &msg.stat, sizeof(msg.stat)) ? 0 : -1;
}
static int do_list(int s, const char *path)
@@ -135,8 +135,8 @@
msg.dent.time = htoll(st.st_mtime);
msg.dent.namelen = htoll(len);
- if(writex(s, &msg.dent, sizeof(msg.dent)) ||
- writex(s, de->d_name, len)) {
+ if(!WriteFdExactly(s, &msg.dent, sizeof(msg.dent)) ||
+ !WriteFdExactly(s, de->d_name, len)) {
closedir(d);
return -1;
}
@@ -151,7 +151,7 @@
msg.dent.size = 0;
msg.dent.time = 0;
msg.dent.namelen = 0;
- return writex(s, &msg.dent, sizeof(msg.dent));
+ return !WriteFdExactly(s, &msg.dent, sizeof(msg.dent)) ? 0 : -1;
}
static int fail_message(int s, const char *reason)
@@ -163,8 +163,8 @@
msg.data.id = ID_FAIL;
msg.data.size = htoll(len);
- if(writex(s, &msg.data, sizeof(msg.data)) ||
- writex(s, reason, len)) {
+ if(!WriteFdExactly(s, &msg.data, sizeof(msg.data)) ||
+ !WriteFdExactly(s, reason, len)) {
return -1;
} else {
return 0;
@@ -217,7 +217,7 @@
for(;;) {
unsigned int len;
- if(readx(s, &msg.data, sizeof(msg.data)))
+ if(!ReadFdExactly(s, &msg.data, sizeof(msg.data)))
goto fail;
if(msg.data.id != ID_DATA) {
@@ -233,12 +233,12 @@
fail_message(s, "oversize data message");
goto fail;
}
- if(readx(s, buffer, len))
+ if(!ReadFdExactly(s, buffer, len))
goto fail;
if(fd < 0)
continue;
- if(writex(fd, buffer, len)) {
+ if(!WriteFdExactly(fd, buffer, len)) {
int saved_errno = errno;
adb_close(fd);
if (do_unlink) adb_unlink(path);
@@ -258,7 +258,7 @@
msg.status.id = ID_OKAY;
msg.status.msglen = 0;
- if(writex(s, &msg.status, sizeof(msg.status)))
+ if(!WriteFdExactly(s, &msg.status, sizeof(msg.status)))
return -1;
}
return 0;
@@ -279,7 +279,7 @@
unsigned int len;
int ret;
- if(readx(s, &msg.data, sizeof(msg.data)))
+ if(!ReadFdExactly(s, &msg.data, sizeof(msg.data)))
return -1;
if(msg.data.id != ID_DATA) {
@@ -292,7 +292,7 @@
fail_message(s, "oversize data message");
return -1;
}
- if(readx(s, buffer, len))
+ if(!ReadFdExactly(s, buffer, len))
return -1;
ret = symlink(buffer, path);
@@ -308,13 +308,13 @@
return -1;
}
- if(readx(s, &msg.data, sizeof(msg.data)))
+ if(!ReadFdExactly(s, &msg.data, sizeof(msg.data)))
return -1;
if(msg.data.id == ID_DONE) {
msg.status.id = ID_OKAY;
msg.status.msglen = 0;
- if(writex(s, &msg.status, sizeof(msg.status)))
+ if(!WriteFdExactly(s, &msg.status, sizeof(msg.status)))
return -1;
} else {
fail_message(s, "invalid data message: expected ID_DONE");
@@ -396,8 +396,8 @@
return r;
}
msg.data.size = htoll(r);
- if(writex(s, &msg.data, sizeof(msg.data)) ||
- writex(s, buffer, r)) {
+ if(!WriteFdExactly(s, &msg.data, sizeof(msg.data)) ||
+ !WriteFdExactly(s, buffer, r)) {
adb_close(fd);
return -1;
}
@@ -407,7 +407,7 @@
msg.data.id = ID_DONE;
msg.data.size = 0;
- if(writex(s, &msg.data, sizeof(msg.data))) {
+ if(!WriteFdExactly(s, &msg.data, sizeof(msg.data))) {
return -1;
}
@@ -426,7 +426,7 @@
for(;;) {
D("sync: waiting for command\n");
- if(readx(fd, &msg.req, sizeof(msg.req))) {
+ if(!ReadFdExactly(fd, &msg.req, sizeof(msg.req))) {
fail_message(fd, "command read failure");
break;
}
@@ -435,7 +435,7 @@
fail_message(fd, "invalid namelen");
break;
}
- if(readx(fd, name, namelen)) {
+ if(!ReadFdExactly(fd, name, namelen)) {
fail_message(fd, "filename read failure");
break;
}
diff --git a/adb/framebuffer_service.c b/adb/framebuffer_service.c
index 61578aa..9d17d2c 100644
--- a/adb/framebuffer_service.c
+++ b/adb/framebuffer_service.c
@@ -14,21 +14,23 @@
* limitations under the License.
*/
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
#include <errno.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include "fdevent.h"
-#include "adb.h"
-
+#include <fcntl.h>
#include <linux/fb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "sysdeps.h"
+
+#include "adb.h"
+#include "adb_io.h"
+#include "fdevent.h"
/* TODO:
** - sync with vsync to avoid tearing
@@ -68,21 +70,21 @@
if (pid == 0) {
dup2(fds[1], STDOUT_FILENO);
- close(fds[0]);
- close(fds[1]);
+ adb_close(fds[0]);
+ adb_close(fds[1]);
const char* command = "screencap";
const char *args[2] = {command, NULL};
execvp(command, (char**)args);
exit(1);
}
- close(fds[1]);
+ adb_close(fds[1]);
fd_screencap = fds[0];
/* read w, h & format */
- if(readx(fd_screencap, &w, 4)) goto done;
- if(readx(fd_screencap, &h, 4)) goto done;
- if(readx(fd_screencap, &f, 4)) goto done;
+ if(!ReadFdExactly(fd_screencap, &w, 4)) goto done;
+ if(!ReadFdExactly(fd_screencap, &h, 4)) goto done;
+ if(!ReadFdExactly(fd_screencap, &f, 4)) goto done;
fbinfo.version = DDMS_RAWIMAGE_VERSION;
/* see hardware/hardware.h */
@@ -162,21 +164,21 @@
}
/* write header */
- if(writex(fd, &fbinfo, sizeof(fbinfo))) goto done;
+ if(!WriteFdExactly(fd, &fbinfo, sizeof(fbinfo))) goto done;
/* write data */
for(i = 0; i < fbinfo.size; i += bsize) {
bsize = sizeof(buf);
if (i + bsize > fbinfo.size)
bsize = fbinfo.size - i;
- if(readx(fd_screencap, buf, bsize)) goto done;
- if(writex(fd, buf, bsize)) goto done;
+ if(!ReadFdExactly(fd_screencap, buf, bsize)) goto done;
+ if(!WriteFdExactly(fd, buf, bsize)) goto done;
}
done:
- close(fds[0]);
+ adb_close(fds[0]);
TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0));
pipefail:
- close(fd);
+ adb_close(fd);
}
diff --git a/adb/remount_service.c b/adb/remount_service.c
index d7b0dd1..414b316 100644
--- a/adb/remount_service.c
+++ b/adb/remount_service.c
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#include "sysdeps.h"
-
#include <errno.h>
#include <fcntl.h>
#include <mntent.h>
@@ -25,11 +23,12 @@
#include <sys/mount.h>
#include <unistd.h>
-#include "cutils/properties.h"
+#include "sysdeps.h"
#define TRACE_TAG TRACE_ADB
#include "adb.h"
-
+#include "adb_io.h"
+#include "cutils/properties.h"
static int system_ro = 1;
static int vendor_ro = 1;
@@ -109,16 +108,17 @@
return rc;
}
-static void write_string(int fd, const char* str)
-{
- writex(fd, str, strlen(str));
-}
-
void remount_service(int fd, void *cookie)
{
char buffer[200];
char prop_buf[PROPERTY_VALUE_MAX];
+ if (getuid() != 0) {
+ WriteStringFully(fd, "Not running as root. Try \"adb root\" first.\n");
+ adb_close(fd);
+ return;
+ }
+
bool system_verified = false, vendor_verified = false;
property_get("partition.system.verified", prop_buf, "0");
if (!strcmp(prop_buf, "1")) {
@@ -139,30 +139,30 @@
both ? " and " : "",
vendor_verified ? "vendor" : "",
both ? "s" : "");
- write_string(fd, buffer);
+ WriteStringFully(fd, buffer);
snprintf(buffer, sizeof(buffer),
"Use \"adb disable-verity\" to disable verity.\n"
"If you do not, remount may succeed, however, you will still "
"not be able to write to these volumes.\n");
- write_string(fd, buffer);
+ WriteStringFully(fd, buffer);
}
if (remount("/system", &system_ro)) {
snprintf(buffer, sizeof(buffer), "remount of system failed: %s\n",strerror(errno));
- write_string(fd, buffer);
+ WriteStringFully(fd, buffer);
}
if (hasVendorPartition()) {
if (remount("/vendor", &vendor_ro)) {
snprintf(buffer, sizeof(buffer), "remount of vendor failed: %s\n",strerror(errno));
- write_string(fd, buffer);
+ WriteStringFully(fd, buffer);
}
}
if (!system_ro && (!vendor_ro || !hasVendorPartition()))
- write_string(fd, "remount succeeded\n");
+ WriteStringFully(fd, "remount succeeded\n");
else {
- write_string(fd, "remount failed\n");
+ WriteStringFully(fd, "remount failed\n");
}
adb_close(fd);
diff --git a/adb/services.c b/adb/services.c
index bd210a8..84f2137 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -14,29 +14,31 @@
* limitations under the License.
*/
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef _WIN32
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#endif
+
+#if !ADB_HOST
+#include "cutils/android_reboot.h"
+#include "cutils/properties.h"
+#endif
#include "sysdeps.h"
#define TRACE_TAG TRACE_SERVICES
#include "adb.h"
+#include "adb_io.h"
#include "file_sync_service.h"
-
-#if ADB_HOST
-# ifndef HAVE_WINSOCK
-# include <netinet/in.h>
-# include <netdb.h>
-# include <sys/ioctl.h>
-# endif
-#else
-# include <cutils/android_reboot.h>
-# include <cutils/properties.h>
-#endif
+#include "transport.h"
typedef struct stinfo stinfo;
@@ -64,20 +66,20 @@
if (getuid() == 0) {
snprintf(buf, sizeof(buf), "adbd is already running as root\n");
- writex(fd, buf, strlen(buf));
+ WriteFdExactly(fd, buf, strlen(buf));
adb_close(fd);
} else {
property_get("ro.debuggable", value, "");
if (strcmp(value, "1") != 0) {
snprintf(buf, sizeof(buf), "adbd cannot run as root in production builds\n");
- writex(fd, buf, strlen(buf));
+ WriteFdExactly(fd, buf, strlen(buf));
adb_close(fd);
return;
}
property_set("service.adb.root", "1");
snprintf(buf, sizeof(buf), "restarting adbd as root\n");
- writex(fd, buf, strlen(buf));
+ WriteFdExactly(fd, buf, strlen(buf));
adb_close(fd);
}
}
@@ -88,12 +90,12 @@
if (getuid() != 0) {
snprintf(buf, sizeof(buf), "adbd not running as root\n");
- writex(fd, buf, strlen(buf));
+ WriteFdExactly(fd, buf, strlen(buf));
adb_close(fd);
} else {
property_set("service.adb.root", "0");
snprintf(buf, sizeof(buf), "restarting adbd as non root\n");
- writex(fd, buf, strlen(buf));
+ WriteFdExactly(fd, buf, strlen(buf));
adb_close(fd);
}
}
@@ -106,7 +108,7 @@
if (port <= 0) {
snprintf(buf, sizeof(buf), "invalid port\n");
- writex(fd, buf, strlen(buf));
+ WriteFdExactly(fd, buf, strlen(buf));
adb_close(fd);
return;
}
@@ -114,7 +116,7 @@
snprintf(value, sizeof(value), "%d", port);
property_set("service.adb.tcp.port", value);
snprintf(buf, sizeof(buf), "restarting in TCP mode port: %d\n", port);
- writex(fd, buf, strlen(buf));
+ WriteFdExactly(fd, buf, strlen(buf));
adb_close(fd);
}
@@ -124,7 +126,7 @@
property_set("service.adb.tcp.port", "0");
snprintf(buf, sizeof(buf), "restarting in USB mode\n");
- writex(fd, buf, strlen(buf));
+ WriteFdExactly(fd, buf, strlen(buf));
adb_close(fd);
}
@@ -139,14 +141,14 @@
ret = snprintf(property_val, sizeof(property_val), "reboot,%s", (char *) arg);
if (ret >= (int) sizeof(property_val)) {
snprintf(buf, sizeof(buf), "reboot string too long. length=%d\n", ret);
- writex(fd, buf, strlen(buf));
+ WriteFdExactly(fd, buf, strlen(buf));
goto cleanup;
}
ret = property_set(ANDROID_RB_PROPERTY, property_val);
if (ret < 0) {
snprintf(buf, sizeof(buf), "reboot failed: %d\n", ret);
- writex(fd, buf, strlen(buf));
+ WriteFdExactly(fd, buf, strlen(buf));
goto cleanup;
}
// Don't return early. Give the reboot command time to take effect
@@ -349,7 +351,7 @@
D("shell exited fd=%d of pid=%d err=%d\n", fd, pid, errno);
if (SHELL_EXIT_NOTIFY_FD >=0) {
int res;
- res = writex(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd));
+ res = WriteFdExactly(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd)) ? 0 : -1;
D("notified shell exit via fd=%d for pid=%d res=%d errno=%d\n",
SHELL_EXIT_NOTIFY_FD, pid, res, errno);
}
@@ -517,7 +519,7 @@
atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err);
if(t != 0) {
- writex(fd, "OKAY", 4);
+ WriteFdExactly(fd, "OKAY", 4);
} else {
sendfailmsg(fd, err);
}
@@ -643,7 +645,7 @@
// Send response for emulator and device
snprintf(resp, sizeof(resp), "%04x%s",(unsigned)strlen(buf), buf);
- writex(fd, resp, strlen(resp));
+ WriteFdExactly(fd, resp, strlen(resp));
adb_close(fd);
}
#endif
diff --git a/adb/sockets.c b/adb/sockets.c
index 6cdde97..d34f8c6 100644
--- a/adb/sockets.c
+++ b/adb/sockets.c
@@ -14,21 +14,22 @@
* limitations under the License.
*/
+#include <ctype.h>
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
#include <string.h>
-#include <ctype.h>
+#include <unistd.h>
#include "sysdeps.h"
-#if !ADB_HOST
-#include <cutils/properties.h>
-#endif
-
#define TRACE_TAG TRACE_SOCKETS
#include "adb.h"
+#include "adb_io.h"
+#if !ADB_HOST
+#include "cutils/properties.h"
+#endif
+#include "transport.h"
ADB_MUTEX_DEFINE( socket_list_lock );
@@ -39,13 +40,17 @@
char buf[9];
int len;
len = strlen(reason);
- if(len > 0xffff) len = 0xffff;
- snprintf(buf, sizeof buf, "FAIL%04x", len);
- if(writex(fd, buf, 8)) return -1;
- return writex(fd, reason, len);
-}
+ if (len > 0xffff) {
+ len = 0xffff;
+ }
-//extern int online;
+ snprintf(buf, sizeof buf, "FAIL%04x", len);
+ if (!WriteFdExactly(fd, buf, 8)) {
+ return -1;
+ }
+
+ return WriteFdExactly(fd, reason, len) ? 0 : -1;
+}
static unsigned local_socket_next_id = 1;
@@ -196,10 +201,9 @@
static void local_socket_ready(asocket *s)
{
- /* far side is ready for data, pay attention to
- readable events */
+ /* far side is ready for data, pay attention to
+ readable events */
fdevent_add(&s->fde, FDE_READ);
-// D("LS(%d): ready()\n", s->id);
}
static void local_socket_close(asocket *s)
@@ -240,7 +244,7 @@
static void local_socket_close_locked(asocket *s)
{
- D("entered. LS(%d) fd=%d\n", s->id, s->fd);
+ D("entered local_socket_close_locked. LS(%d) fd=%d\n", s->id, s->fd);
if(s->peer) {
D("LS(%d): closing peer. peer->id=%d peer->fd=%d\n",
s->id, s->peer->id, s->peer->fd);
@@ -403,7 +407,6 @@
** catching it here means we may skip the last few
** bytes of readable data.
*/
-// s->close(s);
D("LS(%d): FDE_ERROR (fd=%d)\n", s->id, s->fd);
return;
@@ -422,8 +425,6 @@
install_local_socket(s);
fdevent_install(&s->fde, fd, local_socket_event_func, s);
-/* fdevent_add(&s->fde, FDE_ERROR); */
- //fprintf(stderr, "Created local socket in create_local_socket \n");
D("LS(%d): created (fd=%d)\n", s->id, s->fd);
return s;
}
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index ec847b5..c317e3a 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -24,6 +24,21 @@
# undef _WIN32
#endif
+/*
+ * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
+ * <unistd.h>. (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
+
#ifdef _WIN32
#include <ctype.h>
@@ -264,10 +279,6 @@
extern char* adb_strtok_r(char *str, const char *delim, char **saveptr);
-#ifdef __cplusplus
-}
-#endif
-
#else /* !_WIN32 a.k.a. Unix */
#include "fdevent.h"
@@ -291,21 +302,6 @@
extern "C" {
#endif
-/*
- * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
- * <unistd.h>. (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 ":"
diff --git a/adb/tests/test_adb.py b/adb/tests/test_adb.py
index 4b3baf3..49ead73 100755
--- a/adb/tests/test_adb.py
+++ b/adb/tests/test_adb.py
@@ -215,15 +215,13 @@
class AdbBasic(unittest.TestCase):
- def test_devices(self):
- """Get uptime for each device plugged in from /proc/uptime."""
- dev_list = get_device_list()
- for device in dev_list:
- out = call_checked(
- "adb -s {} shell cat /proc/uptime".format(device))
- self.assertEqual(len(out.split()), 2)
- self.assertGreater(float(out.split()[0]), 0.0)
- self.assertGreater(float(out.split()[1]), 0.0)
+ def test_shell(self):
+ """Check that we can at least cat a file."""
+ adb = AdbWrapper()
+ out = adb.shell("cat /proc/uptime")
+ self.assertEqual(len(out.split()), 2)
+ self.assertGreater(float(out.split()[0]), 0.0)
+ self.assertGreater(float(out.split()[1]), 0.0)
def test_help(self):
"""Make sure we get _something_ out of help."""
@@ -241,14 +239,13 @@
def test_root_unroot(self):
"""Make sure that adb root and adb unroot work, using id(1)."""
- for device in get_device_list():
- adb = AdbWrapper(device)
- adb.root()
- adb.wait()
- self.assertEqual("root", adb.shell("id -un").strip())
- adb.unroot()
- adb.wait()
- self.assertEqual("shell", adb.shell("id -un").strip())
+ adb = AdbWrapper()
+ adb.root()
+ adb.wait()
+ self.assertEqual("root", adb.shell("id -un").strip())
+ adb.unroot()
+ adb.wait()
+ self.assertEqual("shell", adb.shell("id -un").strip())
class AdbFile(unittest.TestCase):
@@ -257,15 +254,9 @@
DEVICE_TEMP_DIR = SCRATCH_DIR + "/adb_test_dir"
def test_push(self):
- """Push a file to all attached devices."""
- dev_list = get_device_list()
- for device in dev_list:
- self.push_with_device(device)
-
- def push_with_device(self, device):
"""Push a randomly generated file to specified device."""
kbytes = 512
- adb = AdbWrapper(device)
+ adb = AdbWrapper()
with tempfile.NamedTemporaryFile(mode="w") as tmp:
rand_str = os.urandom(1024 * kbytes)
tmp.write(rand_str)
@@ -284,15 +275,9 @@
# TODO: write push directory test.
def test_pull(self):
- """Pull a file from all attached devices."""
- dev_list = get_device_list()
- for device in dev_list:
- self.pull_with_device(device)
-
- def pull_with_device(self, device):
"""Pull a randomly generated file from specified device."""
kbytes = 512
- adb = AdbWrapper(device)
+ adb = AdbWrapper()
adb.shell_nocheck("rm -r {}".format(AdbFile.DEVICE_TEMP_FILE))
try:
adb.shell("dd if=/dev/urandom of={} bs=1024 count={}".format(
@@ -310,14 +295,8 @@
adb.shell_nocheck("rm {}".format(AdbFile.DEVICE_TEMP_FILE))
def test_pull_dir(self):
- """Pull a directory from all attached devices."""
- dev_list = get_device_list()
- for device in dev_list:
- self.pull_dir_with_device(device)
-
- def pull_dir_with_device(self, device):
"""Pull a randomly generated directory of files from the device."""
- adb = AdbWrapper(device)
+ adb = AdbWrapper()
temp_files = {}
host_dir = None
try:
@@ -350,15 +329,9 @@
os.removedirs(host_dir)
def test_sync(self):
- """Sync a directory with all attached devices."""
- dev_list = get_device_list()
- for device in dev_list:
- self.sync_dir_with_device(device)
-
- def sync_dir_with_device(self, device):
"""Sync a randomly generated directory of files to specified device."""
try:
- adb = AdbWrapper(device)
+ adb = AdbWrapper()
temp_files = {}
# create temporary host directory
@@ -373,7 +346,7 @@
num_files=32)
# clean up any trash on the device
- adb = AdbWrapper(device, out_dir=base_dir)
+ adb = AdbWrapper(out_dir=base_dir)
adb.shell_nocheck("rm -r {}".format(AdbFile.DEVICE_TEMP_DIR))
# issue the sync
diff --git a/adb/transport.c b/adb/transport.c
index ffe59da..e2c204e 100644
--- a/adb/transport.c
+++ b/adb/transport.c
@@ -14,13 +14,16 @@
* limitations under the License.
*/
+#include "sysdeps.h"
+
+#include "transport.h"
+
+#include <ctype.h>
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
#include <string.h>
-#include <errno.h>
-
-#include "sysdeps.h"
+#include <unistd.h>
#define TRACE_TAG TRACE_TRANSPORT
#include "adb.h"
@@ -41,7 +44,7 @@
#if ADB_TRACE
#define MAX_DUMP_HEX_LEN 16
-static void dump_hex( const unsigned char* ptr, size_t len )
+void dump_hex(const unsigned char* ptr, size_t len)
{
int nn, len2 = len;
// Build a string instead of logging each character.
@@ -67,8 +70,7 @@
}
#endif
-void
-kick_transport(atransport* t)
+void kick_transport(atransport* t)
{
if (t && !t->kicked)
{
@@ -85,8 +87,25 @@
}
}
-void
-run_transport_disconnects(atransport* t)
+// Each atransport contains a list of adisconnects (t->disconnects).
+// An adisconnect contains a link to the next/prev adisconnect, a function
+// pointer to a disconnect callback which takes a void* piece of user data and
+// the atransport, and some user data for the callback (helpfully named
+// "opaque").
+//
+// The list is circular. New items are added to the entry member of the list
+// (t->disconnects) by add_transport_disconnect.
+//
+// run_transport_disconnects invokes each function in the list.
+//
+// Gotchas:
+// * run_transport_disconnects assumes that t->disconnects is non-null, so
+// this can't be run on a zeroed atransport.
+// * The callbacks in this list are not removed when called, and this function
+// is not guarded against running more than once. As such, ensure that this
+// function is not called multiple times on the same atransport.
+// TODO(danalbert): Just fix this so that it is guarded once you have tests.
+void run_transport_disconnects(atransport* t)
{
adisconnect* dis = t->disconnects.next;
@@ -494,8 +513,7 @@
/* call this function each time the transport list has changed */
-void update_transports(void)
-{
+void update_transports(void) {
char buffer[1024];
int len;
device_tracker* tracker;
@@ -752,17 +770,6 @@
dis->next = dis->prev = dis;
}
-static int qual_char_is_invalid(char ch)
-{
- if ('A' <= ch && ch <= 'Z')
- return 0;
- if ('a' <= ch && ch <= 'z')
- return 0;
- if ('0' <= ch && ch <= '9')
- return 0;
- return 1;
-}
-
static int qual_match(const char *to_test,
const char *prefix, const char *qual, int sanitize_qual)
{
@@ -782,7 +789,7 @@
while (*qual) {
char ch = *qual++;
- if (sanitize_qual && qual_char_is_invalid(ch))
+ if (sanitize_qual && isalnum(ch))
ch = '_';
if (ch != *to_test++)
return 0;
@@ -922,7 +929,7 @@
if (sanitize_qual) {
char *cp;
for (cp = *buf + prefix_len; cp < *buf + len; cp++) {
- if (qual_char_is_invalid(*cp))
+ if (isalnum(*cp))
*cp = '_';
}
}
@@ -1138,74 +1145,6 @@
#undef TRACE_TAG
#define TRACE_TAG TRACE_RWX
-int readx(int fd, void *ptr, size_t len)
-{
- char *p = ptr;
- int r;
-#if ADB_TRACE
- size_t len0 = len;
-#endif
- D("readx: fd=%d wanted=%zu\n", fd, len);
- while(len > 0) {
- r = adb_read(fd, p, len);
- if(r > 0) {
- len -= r;
- p += r;
- } else {
- if (r < 0) {
- D("readx: fd=%d error %d: %s\n", fd, errno, strerror(errno));
- if (errno == EINTR)
- continue;
- } else {
- D("readx: fd=%d disconnected\n", fd);
- }
- return -1;
- }
- }
-
-#if ADB_TRACE
- D("readx: fd=%d wanted=%zu got=%zu\n", fd, len0, len0 - len);
- if (ADB_TRACING) {
- dump_hex( ptr, len0 );
- }
-#endif
- return 0;
-}
-
-int writex(int fd, const void *ptr, size_t len)
-{
- char *p = (char*) ptr;
- int r;
-
-#if ADB_TRACE
- D("writex: fd=%d len=%d: ", fd, (int)len);
- if (ADB_TRACING) {
- dump_hex( ptr, len );
- }
-#endif
- while(len > 0) {
- r = adb_write(fd, p, len);
- if(r > 0) {
- len -= r;
- p += r;
- } else {
- if (r < 0) {
- D("writex: fd=%d error %d: %s\n", fd, errno, strerror(errno));
- if (errno == EINTR)
- continue;
- if (errno == EAGAIN) {
- adb_sleep_ms(1); // just yield some cpu time
- continue;
- }
- } else {
- D("writex: fd=%d disconnected\n", fd);
- }
- return -1;
- }
- }
- return 0;
-}
-
int check_header(apacket *p)
{
if(p->msg.magic != (p->msg.command ^ 0xffffffff)) {
diff --git a/adb/transport.h b/adb/transport.h
index c1b8ff3..352bbe4 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -17,16 +17,62 @@
#ifndef __TRANSPORT_H
#define __TRANSPORT_H
+#include <stdbool.h>
+#include <sys/types.h>
+
+#include "adb.h"
+
#ifdef __cplusplus
extern "C" {
#endif
-/* convenience wrappers around read/write that will retry on
-** EINTR and/or short read/write. Returns 0 on success, -1
-** on error or EOF.
+#if ADB_TRACE
+void dump_hex(const unsigned char* ptr, size_t len);
+#endif
+
+/*
+ * Obtain a transport from the available transports.
+ * If state is != CS_ANY, only transports in that state are considered.
+ * If serial is non-NULL then only the device with that serial will be chosen.
+ * If no suitable transport is found, error is set.
+ */
+atransport* acquire_one_transport(int state, transport_type ttype,
+ const char* serial, char** error_out);
+void add_transport_disconnect(atransport* t, adisconnect* dis);
+void remove_transport_disconnect(atransport* t, adisconnect* dis);
+void kick_transport(atransport* t);
+void run_transport_disconnects(atransport* t);
+void update_transports(void);
+
+/* transports are ref-counted
+** get_device_transport does an acquire on your behalf before returning
*/
-int readx(int fd, void *ptr, size_t len);
-int writex(int fd, const void *ptr, size_t len);
+void init_transport_registration(void);
+int list_transports(char* buf, size_t bufsize, int long_listing);
+atransport* find_transport(const char* serial);
+
+void register_usb_transport(usb_handle* h, const char* serial,
+ const char* devpath, unsigned writeable);
+
+/* cause new transports to be init'd and added to the list */
+int register_socket_transport(int s, const char* serial, int port, int local);
+
+/* this should only be used for transports with connection_state == CS_NOPERM */
+void unregister_usb_transport(usb_handle* usb);
+
+/* these should only be used for the "adb disconnect" command */
+void unregister_transport(atransport* t);
+void unregister_all_tcp_transports();
+
+int check_header(apacket* p);
+int check_data(apacket* p);
+
+/* for MacOS X cleanup */
+void close_usb_devices();
+
+void send_packet(apacket* p, atransport* t);
+
+asocket* create_device_tracker(void);
#ifdef __cplusplus
}
diff --git a/adb/transport_local.c b/adb/transport_local.c
index 6c4e220..440d4c5 100644
--- a/adb/transport_local.c
+++ b/adb/transport_local.c
@@ -14,19 +14,21 @@
* limitations under the License.
*/
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <errno.h>
+#include <sys/types.h>
#include "sysdeps.h"
-#include <sys/types.h>
-#if !ADB_HOST
-#include <cutils/properties.h>
-#endif
#define TRACE_TAG TRACE_TRANSPORT
#include "adb.h"
+#include "adb_io.h"
+#if !ADB_HOST
+#include "cutils/properties.h"
+#endif
+#include "transport.h"
#if ADB_HOST
/* we keep a list of opened transports. The atransport struct knows to which
@@ -42,7 +44,7 @@
static int remote_read(apacket *p, atransport *t)
{
- if(readx(t->sfd, &p->msg, sizeof(amessage))){
+ if(!ReadFdExactly(t->sfd, &p->msg, sizeof(amessage))){
D("remote local: read terminated (message)\n");
return -1;
}
@@ -52,7 +54,7 @@
return -1;
}
- if(readx(t->sfd, p->data, p->msg.data_length)){
+ if(!ReadFdExactly(t->sfd, p->data, p->msg.data_length)){
D("remote local: terminated (data)\n");
return -1;
}
@@ -69,7 +71,7 @@
{
int length = p->msg.data_length;
- if(writex(t->sfd, &p->msg, sizeof(amessage) + length)) {
+ if(!WriteFdExactly(t->sfd, &p->msg, sizeof(amessage) + length)) {
D("remote local: write terminated\n");
return -1;
}
diff --git a/adb/transport_test.cpp b/adb/transport_test.cpp
new file mode 100644
index 0000000..2b3fe3c
--- /dev/null
+++ b/adb/transport_test.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 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 "transport.h"
+
+#include <gtest/gtest.h>
+
+#include "adb.h"
+
+TEST(transport, kick_transport) {
+ atransport t = {};
+ // Mutate some member so we can test that the function is run.
+ t.kick = [](atransport* trans) { trans->fd = 42; };
+ atransport expected = t;
+ expected.fd = 42;
+ expected.kicked = 1;
+ kick_transport(&t);
+ ASSERT_EQ(42, t.fd);
+ ASSERT_EQ(1, t.kicked);
+ ASSERT_EQ(0, memcmp(&expected, &t, sizeof(atransport)));
+}
+
+TEST(transport, kick_transport_already_kicked) {
+ // Ensure that the transport is not modified if the transport has already been
+ // kicked.
+ atransport t = {};
+ t.kicked = 1;
+ t.kick = [](atransport*) { FAIL() << "Kick should not have been called"; };
+ atransport expected = t;
+ kick_transport(&t);
+ ASSERT_EQ(0, memcmp(&expected, &t, sizeof(atransport)));
+}
+
+// Disabled because the function currently segfaults for a zeroed atransport. I
+// want to make sure I understand how this is working at all before I try fixing
+// that.
+TEST(transport, DISABLED_run_transport_disconnects_zeroed_atransport) {
+ atransport t = {};
+ run_transport_disconnects(&t);
+}
diff --git a/adb/transport_usb.c b/adb/transport_usb.c
index 1138ddd..37a8219 100644
--- a/adb/transport_usb.c
+++ b/adb/transport_usb.c
@@ -22,6 +22,7 @@
#define TRACE_TAG TRACE_TRANSPORT
#include "adb.h"
+#include "transport.h"
static int remote_read(apacket *p, atransport *t)
{
diff --git a/adb/usb_linux.c b/adb/usb_linux.c
index 7d13a5d..d03f8be 100644
--- a/adb/usb_linux.c
+++ b/adb/usb_linux.c
@@ -14,33 +14,30 @@
* limitations under the License.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <errno.h>
#include <ctype.h>
-
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
#include <linux/usbdevice_fs.h>
#include <linux/version.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20)
#include <linux/usb/ch9.h>
#else
#include <linux/usb_ch9.h>
#endif
-#include <asm/byteorder.h>
#include "sysdeps.h"
#define TRACE_TAG TRACE_USB
#include "adb.h"
-
+#include "transport.h"
/* usb scan debugging is waaaay too verbose */
#define DBGX(x...)
@@ -379,6 +376,7 @@
struct usbdevfs_urb *out = NULL;
int res;
+ D("++ usb_bulk_read ++\n");
memset(urb, 0, sizeof(*urb));
urb->type = USBDEVFS_URB_TYPE_BULK;
urb->endpoint = h->ep_in;
@@ -441,6 +439,7 @@
}
fail:
adb_mutex_unlock(&h->lock);
+ D("-- usb_bulk_read --\n");
return res;
}
@@ -451,6 +450,7 @@
int n;
int need_zero = 0;
+ D("++ usb_write ++\n");
if(h->zero_mask) {
/* if we need 0-markers and our transfer
** is an even multiple of the packet size,
@@ -480,6 +480,7 @@
return n;
}
+ D("-- usb_write --\n");
return 0;
}
@@ -554,7 +555,7 @@
int usb_close(usb_handle *h)
{
- D("[ usb close ... ]\n");
+ D("++ usb close ++\n");
adb_mutex_lock(&usb_lock);
h->next->prev = h->prev;
h->prev->next = h->next;
@@ -562,7 +563,7 @@
h->next = 0;
adb_close(h->desc);
- D("[ usb closed %p (fd = %d) ]\n", h, h->desc);
+ D("-- usb closed %p (fd = %d) --\n", h, h->desc);
adb_mutex_unlock(&usb_lock);
free(h);
diff --git a/adb/usb_linux_client.c b/adb/usb_linux_client.c
index ee6b37c..c88b258 100644
--- a/adb/usb_linux_client.c
+++ b/adb/usb_linux_client.c
@@ -14,22 +14,22 @@
* limitations under the License.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/functionfs.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/functionfs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <unistd.h>
#include "sysdeps.h"
#define TRACE_TAG TRACE_USB
#include "adb.h"
+#include "transport.h"
#define MAX_PACKET_SIZE_FS 64
#define MAX_PACKET_SIZE_HS 512
diff --git a/adb/usb_osx.c b/adb/usb_osx.c
index ba157f1..aa7e1ea 100644
--- a/adb/usb_osx.c
+++ b/adb/usb_osx.c
@@ -22,12 +22,13 @@
#include <IOKit/IOMessage.h>
#include <mach/mach_port.h>
-#include "sysdeps.h"
-
#include <stdio.h>
+#include "sysdeps.h"
+
#define TRACE_TAG TRACE_USB
#include "adb.h"
+#include "transport.h"
#define DBG D
diff --git a/adb/usb_windows.c b/adb/usb_windows.c
index a2d7226..3c5533b 100644
--- a/adb/usb_windows.c
+++ b/adb/usb_windows.c
@@ -14,19 +14,20 @@
* limitations under the License.
*/
-#include <winsock2.h>
-#include <windows.h>
-#include <winerror.h>
-#include <errno.h>
-#include <usb100.h>
+#include <winsock2.h> // winsock.h *must* be included before windows.h.
#include <adb_api.h>
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
+#include <usb100.h>
+#include <windows.h>
+#include <winerror.h>
#include "sysdeps.h"
#define TRACE_TAG TRACE_USB
#include "adb.h"
+#include "transport.h"
/** Structure usb_handle describes our connection to the usb device via
AdbWinApi.dll. This structure is returned from usb_open() routine and
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index 4233d46..e927ea3 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -453,7 +453,7 @@
}
logger_list = android_logger_list_open(
- android_name_to_log_id(filename), O_RDONLY | O_NONBLOCK, tail, pid);
+ android_name_to_log_id(filename), ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, tail, pid);
if (!logger_list) {
ALOGE("Unable to open %s: %s\n", filename, strerror(errno));
diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c
index 959d3ad..fc544a6 100644
--- a/fastboot/fastboot.c
+++ b/fastboot/fastboot.c
@@ -300,7 +300,7 @@
" flash it\n"
" devices list all connected devices\n"
" continue continue with autoboot\n"
- " reboot reboot device normally\n"
+ " reboot [bootloader] reboot device, optionally into bootloader\n"
" reboot-bootloader reboot device into bootloader\n"
" help show this help message\n"
"\n"
@@ -1153,6 +1153,14 @@
} else if(!strcmp(*argv, "reboot")) {
wants_reboot = 1;
skip(1);
+ if (argc > 0) {
+ if (!strcmp(*argv, "bootloader")) {
+ wants_reboot = 0;
+ wants_reboot_bootloader = 1;
+ skip(1);
+ }
+ }
+ require(0);
} else if(!strcmp(*argv, "reboot-bootloader")) {
wants_reboot_bootloader = 1;
skip(1);
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index a1391e0..f9a6ba2 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -185,19 +185,22 @@
* Mark the given block device as read-only, using the BLKROSET ioctl.
* Return 0 on success, and -1 on error.
*/
-static void fs_set_blk_ro(const char *blockdev)
+int fs_mgr_set_blk_ro(const char *blockdev)
{
int fd;
+ int rc = -1;
int ON = 1;
- fd = open(blockdev, O_RDONLY);
+ fd = TEMP_FAILURE_RETRY(open(blockdev, O_RDONLY | O_CLOEXEC));
if (fd < 0) {
// should never happen
- return;
+ return rc;
}
- ioctl(fd, BLKROSET, &ON);
- close(fd);
+ rc = ioctl(fd, BLKROSET, &ON);
+ TEMP_FAILURE_RETRY(close(fd));
+
+ return rc;
}
/*
@@ -223,7 +226,7 @@
save_errno = errno;
INFO("%s(source=%s,target=%s,type=%s)=%d\n", __func__, source, target, rec->fs_type, ret);
if ((ret == 0) && (mountflags & MS_RDONLY) != 0) {
- fs_set_blk_ro(source);
+ fs_mgr_set_blk_ro(source);
}
errno = save_errno;
return ret;
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 4ba6f92..88a1040 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -79,5 +79,7 @@
#define DM_BUF_SIZE 4096
+int fs_mgr_set_blk_ro(const char *blockdev);
+
#endif /* __CORE_FS_MGR_PRIV_H */
diff --git a/fs_mgr/fs_mgr_verity.c b/fs_mgr/fs_mgr_verity.c
index 4e9158e..70f40fe 100644
--- a/fs_mgr/fs_mgr_verity.c
+++ b/fs_mgr/fs_mgr_verity.c
@@ -761,6 +761,9 @@
goto out;
}
+ // mark the underlying block device as read-only
+ fs_mgr_set_blk_ro(fstab->blk_device);
+
// assign the new verity block device as the block device
free(fstab->blk_device);
fstab->blk_device = verity_blk_name;
diff --git a/include/log/logger.h b/include/log/logger.h
index 53be1d3..f030dab 100644
--- a/include/log/logger.h
+++ b/include/log/logger.h
@@ -154,6 +154,13 @@
int android_logger_set_prune_list(struct logger_list *logger_list,
char *buf, size_t len);
+#define ANDROID_LOG_RDONLY O_RDONLY
+#define ANDROID_LOG_WRONLY O_WRONLY
+#define ANDROID_LOG_RDWR O_RDWR
+#define ANDROID_LOG_ACCMODE O_ACCMODE
+#define ANDROID_LOG_NONBLOCK O_NONBLOCK
+#define ANDROID_LOG_PSTORE 0x80000000
+
struct logger_list *android_logger_list_alloc(int mode,
unsigned int tail,
pid_t pid);
diff --git a/include/utils/FileMap.h b/include/utils/FileMap.h
index 6c0aa52..f70fc92 100644
--- a/include/utils/FileMap.h
+++ b/include/utils/FileMap.h
@@ -63,6 +63,8 @@
bool create(const char* origFileName, int fd,
off64_t offset, size_t length, bool readOnly);
+ ~FileMap(void);
+
/*
* Return the name of the file this map came from, if known.
*/
@@ -84,19 +86,6 @@
off64_t getDataOffset(void) const { return mDataOffset; }
/*
- * Get a "copy" of the object.
- */
- FileMap* acquire(void) { mRefCount++; return this; }
-
- /*
- * Call this when mapping is no longer needed.
- */
- void release(void) {
- if (--mRefCount <= 0)
- delete this;
- }
-
- /*
* This maps directly to madvise() values, but allows us to avoid
* including <sys/mman.h> everywhere.
*/
@@ -112,15 +101,12 @@
int advise(MapAdvice advice);
protected:
- // don't delete objects; call release()
- ~FileMap(void);
private:
// these are not implemented
FileMap(const FileMap& src);
const FileMap& operator=(const FileMap& src);
- int mRefCount; // reference count
char* mFileName; // original file name, if known
void* mBasePtr; // base of mmap area; page aligned
size_t mBaseLength; // length, measured from "mBasePtr"
diff --git a/init/grab-bootchart.sh b/init/grab-bootchart.sh
index 7fe8904..5715862 100755
--- a/init/grab-bootchart.sh
+++ b/init/grab-bootchart.sh
@@ -3,6 +3,8 @@
# this script is used to retrieve the bootchart log generated
# by init when compiled with INIT_BOOTCHART=true.
#
+# All options are passed to adb, for better or for worse.
+#
# for all details, see //device/system/init/README.BOOTCHART
#
TMPDIR=/tmp/android-bootchart
@@ -15,8 +17,9 @@
FILES="header proc_stat.log proc_ps.log proc_diskstats.log kernel_pacct"
for f in $FILES; do
- adb pull $LOGROOT/$f $TMPDIR/$f 2>&1 > /dev/null
+ adb "${@}" pull $LOGROOT/$f $TMPDIR/$f 2>&1 > /dev/null
done
(cd $TMPDIR && tar -czf $TARBALL $FILES)
-cp -f $TMPDIR/$TARBALL ./$TARBALL
-echo "look at $TARBALL"
+bootchart ${TMPDIR}/${TARBALL}
+gnome-open ${TARBALL%.tgz}.png
+echo "Clean up ${TMPDIR}/ & ./${TARBALL%.tgz}.png when done"
diff --git a/init/readme.txt b/init/readme.txt
index 32eb4ab..9c24220 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -313,9 +313,8 @@
bootchart command-line utility:
sudo apt-get install pybootchartgui
+ ANDROID_SERIAL=<device serial number>
$ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh
- bootchart ./bootchart.tgz
- gnome-open bootchart.png
Debugging init
diff --git a/libcutils/debugger.c b/libcutils/debugger.c
index 2cd8ec3..4558719 100644
--- a/libcutils/debugger.c
+++ b/libcutils/debugger.c
@@ -43,7 +43,6 @@
}
static int make_dump_request(debugger_action_t action, pid_t tid, int timeout_secs) {
- const char* socket_name;
debugger_msg_t msg;
memset(&msg, 0, sizeof(msg));
msg.tid = tid;
diff --git a/libcutils/loghack.h b/libcutils/loghack.h
deleted file mode 100644
index 750cab0..0000000
--- a/libcutils/loghack.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * This is a temporary hack to enable logging from cutils.
- */
-
-#ifndef _CUTILS_LOGHACK_H
-#define _CUTILS_LOGHACK_H
-
-#ifdef HAVE_ANDROID_OS
-#include <cutils/log.h>
-#else
-#include <stdio.h>
-#define ALOG(level, ...) \
- ((void)printf("cutils:" level "/" LOG_TAG ": " __VA_ARGS__))
-#define ALOGV(...) ALOG("V", __VA_ARGS__)
-#define ALOGD(...) ALOG("D", __VA_ARGS__)
-#define ALOGI(...) ALOG("I", __VA_ARGS__)
-#define ALOGW(...) ALOG("W", __VA_ARGS__)
-#define ALOGE(...) ALOG("E", __VA_ARGS__)
-#define LOG_ALWAYS_FATAL(...) do { ALOGE(__VA_ARGS__); exit(1); } while (0)
-#endif
-
-#endif // _CUTILS_LOGHACK_H
diff --git a/libcutils/properties.c b/libcutils/properties.c
index 1190ab7..4e46e02 100644
--- a/libcutils/properties.c
+++ b/libcutils/properties.c
@@ -28,7 +28,7 @@
#include <cutils/properties.h>
#include <stdbool.h>
#include <inttypes.h>
-#include "loghack.h"
+#include <log/log.h>
int8_t property_get_bool(const char *key, int8_t default_value) {
if (!key) {
@@ -104,8 +104,6 @@
return (int32_t)property_get_imax(key, INT32_MIN, INT32_MAX, default_value);
}
-#ifdef __BIONIC__
-
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include <sys/_system_properties.h>
@@ -156,83 +154,3 @@
struct property_list_callback_data data = { propfn, cookie };
return __system_property_foreach(property_list_callback, &data);
}
-
-#else
-
-/* SUPER-cheesy place-holder implementation for glibc/Mac OS/Windows. */
-
-#include <cutils/threads.h>
-
-static mutex_t env_lock = MUTEX_INITIALIZER;
-
-int property_get(const char *key, char *value, const char *default_value)
-{
- char ename[PROPERTY_KEY_MAX + 6];
- char *p;
- int len;
-
- len = strlen(key);
- if(len >= PROPERTY_KEY_MAX) return -1;
- memcpy(ename, "PROP_", 5);
- memcpy(ename + 5, key, len + 1);
-
- mutex_lock(&env_lock);
-
- p = getenv(ename);
- if(p == 0) p = "";
- len = strlen(p);
- if(len >= PROPERTY_VALUE_MAX) {
- len = PROPERTY_VALUE_MAX - 1;
- }
-
- if((len == 0) && default_value) {
- len = strlen(default_value);
- memcpy(value, default_value, len + 1);
- } else {
- memcpy(value, p, len);
- value[len] = 0;
- }
-
- mutex_unlock(&env_lock);
-
- return len;
-}
-
-
-int property_set(const char *key, const char *value)
-{
- char ename[PROPERTY_KEY_MAX + 6];
- char *p;
- int len;
- int r;
-
- if(strlen(value) >= PROPERTY_VALUE_MAX) return -1;
-
- len = strlen(key);
- if(len >= PROPERTY_KEY_MAX) return -1;
- memcpy(ename, "PROP_", 5);
- memcpy(ename + 5, key, len + 1);
-
- mutex_lock(&env_lock);
-#ifdef HAVE_MS_C_RUNTIME
- {
- char temp[256];
- snprintf( temp, sizeof(temp), "%s=%s", ename, value);
- putenv(temp);
- r = 0;
- }
-#else
- r = setenv(ename, value, 1);
-#endif
- mutex_unlock(&env_lock);
-
- return r;
-}
-
-int property_list(void (*propfn)(const char *key, const char *value, void *cookie),
- void *cookie)
-{
- return 0;
-}
-
-#endif
diff --git a/libcutils/uevent.c b/libcutils/uevent.c
index 827170a..de5d227 100644
--- a/libcutils/uevent.c
+++ b/libcutils/uevent.c
@@ -112,7 +112,7 @@
addr.nl_pid = getpid();
addr.nl_groups = 0xffffffff;
- s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
+ s = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
if(s < 0)
return -1;
diff --git a/liblog/README b/liblog/README
index d7472e4..461dfbe 100644
--- a/liblog/README
+++ b/liblog/README
@@ -111,24 +111,29 @@
ger_list_alloc, calling in turn the android_logger_open for each log
id. Each entry can be retrieved with android_logger_list_read. The
log(s) can be closed with android_logger_list_free. The logs should be
- opened with an O_RDONLY mode. O_NDELAY mode will report when the log
- reading is done with an EAGAIN error return code, otherwise the
- android_logger_list_read call will block for new entries.
+ opened with an ANDROID_LOG_RDONLY mode. ANDROID_LOG_NONBLOCK mode
+ will report when the log reading is done with an EAGAIN error return
+ code, otherwise the android_logger_list_read call will block for new
+ entries.
+
+ The ANDROID_LOG_PSTORE mode flag to the android_logger_open is used to
+ switch from the active logs to the persistent logs from before the last
+ reboot.
The value returned by android_logger_open can be used as a parameter to
the android_logger_clear function to empty the sub-log. It is recom‐
- mended to only open log O_WRONLY.
+ mended to only open log ANDROID_LOG_WRONLY in that case.
The value returned by android_logger_open can be used as a parameter to
the android_logger_get_log_(size|readable_size|version) to retrieve the
sub-log maximum size, readable size and log buffer format protocol ver‐
sion respectively. android_logger_get_id returns the id that was used
- when opening the sub-log. It is recommended to open the log O_RDONLY
- in these cases.
+ when opening the sub-log. It is recommended to open the log
+ ANDROID_LOG_RDONLY in these cases.
SEE ALSO
syslogd(8)
- 17 Dec 2013 LIBLOG(3)
+ 24 Jan 2014 LIBLOG(3)
diff --git a/liblog/log_read.c b/liblog/log_read.c
index dbed886..5364e4f 100644
--- a/liblog/log_read.c
+++ b/liblog/log_read.c
@@ -19,6 +19,7 @@
#include <inttypes.h>
#include <poll.h>
#include <signal.h>
+#include <stdbool.h>
#include <stddef.h>
#define NOMINMAX /* for windows to suppress definition of min in stdlib.h */
#include <stdlib.h>
@@ -30,6 +31,8 @@
#include <cutils/sockets.h>
#include <log/log.h>
#include <log/logger.h>
+#include <private/android_filesystem_config.h>
+#include <private/android_logger.h>
/* branchless on many architectures. */
#define min(x,y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
@@ -357,10 +360,64 @@
return 0;
}
+/* Determine the credentials of the caller */
+static bool uid_has_log_permission(uid_t uid)
+{
+ return (uid == AID_SYSTEM) || (uid == AID_LOG) || (uid == AID_ROOT);
+}
+
+static uid_t get_best_effective_uid()
+{
+ uid_t euid;
+ uid_t uid;
+ gid_t gid;
+ ssize_t i;
+ static uid_t last_uid = (uid_t) -1;
+
+ if (last_uid != (uid_t) -1) {
+ return last_uid;
+ }
+ uid = getuid();
+ if (uid_has_log_permission(uid)) {
+ return last_uid = uid;
+ }
+ euid = geteuid();
+ if (uid_has_log_permission(euid)) {
+ return last_uid = euid;
+ }
+ gid = getgid();
+ if (uid_has_log_permission(gid)) {
+ return last_uid = gid;
+ }
+ gid = getegid();
+ if (uid_has_log_permission(gid)) {
+ return last_uid = gid;
+ }
+ i = getgroups((size_t) 0, NULL);
+ if (i > 0) {
+ gid_t list[i];
+
+ getgroups(i, list);
+ while (--i >= 0) {
+ if (uid_has_log_permission(list[i])) {
+ return last_uid = list[i];
+ }
+ }
+ }
+ return last_uid = uid;
+}
+
int android_logger_clear(struct logger *logger)
{
char buf[512];
+ if (logger->top->mode & ANDROID_LOG_PSTORE) {
+ if (uid_has_log_permission(get_best_effective_uid())) {
+ return unlink("/sys/fs/pstore/pmsg-ramoops-0");
+ }
+ errno = EPERM;
+ return -1;
+ }
return check_log_success(buf,
send_log_msg(logger, "clear %d", buf, sizeof(buf)));
}
@@ -564,6 +621,116 @@
return logger_list;
}
+static int android_logger_list_read_pstore(struct logger_list *logger_list,
+ struct log_msg *log_msg)
+{
+ ssize_t ret;
+ off_t current, next;
+ uid_t uid;
+ struct logger *logger;
+ struct __attribute__((__packed__)) {
+ android_pmsg_log_header_t p;
+ android_log_header_t l;
+ } buf;
+ static uint8_t preread_count;
+
+ memset(log_msg, 0, sizeof(*log_msg));
+
+ if (logger_list->sock < 0) {
+ int fd = open("/sys/fs/pstore/pmsg-ramoops-0", O_RDONLY);
+
+ if (fd < 0) {
+ return -errno;
+ }
+ logger_list->sock = fd;
+ preread_count = 0;
+ }
+
+ ret = 0;
+ while(1) {
+ if (preread_count < sizeof(buf)) {
+ ret = TEMP_FAILURE_RETRY(read(logger_list->sock,
+ &buf.p.magic + preread_count,
+ sizeof(buf) - preread_count));
+ if (ret < 0) {
+ return -errno;
+ }
+ preread_count += ret;
+ }
+ if (preread_count != sizeof(buf)) {
+ return preread_count ? -EIO : -EAGAIN;
+ }
+ if ((buf.p.magic != LOGGER_MAGIC)
+ || (buf.p.len <= sizeof(buf))
+ || (buf.p.len > (sizeof(buf) + LOGGER_ENTRY_MAX_PAYLOAD))
+ || (buf.l.id >= LOG_ID_MAX)
+ || (buf.l.realtime.tv_nsec >= NS_PER_SEC)) {
+ do {
+ memmove(&buf.p.magic, &buf.p.magic + 1, --preread_count);
+ } while (preread_count && (buf.p.magic != LOGGER_MAGIC));
+ continue;
+ }
+ preread_count = 0;
+
+ logger_for_each(logger, logger_list) {
+ if (buf.l.id != logger->id) {
+ continue;
+ }
+
+ if ((logger_list->start.tv_sec || logger_list->start.tv_nsec)
+ && ((logger_list->start.tv_sec > buf.l.realtime.tv_sec)
+ || ((logger_list->start.tv_sec == buf.l.realtime.tv_sec)
+ && (logger_list->start.tv_nsec > buf.l.realtime.tv_nsec)))) {
+ break;
+ }
+
+ if (logger_list->pid && (logger_list->pid != buf.p.pid)) {
+ break;
+ }
+
+ uid = get_best_effective_uid();
+ if (!uid_has_log_permission(uid) && (uid != buf.p.uid)) {
+ break;
+ }
+
+ ret = TEMP_FAILURE_RETRY(read(logger_list->sock,
+ log_msg->entry_v3.msg,
+ buf.p.len - sizeof(buf)));
+ if (ret < 0) {
+ return -errno;
+ }
+ if (ret != (ssize_t)(buf.p.len - sizeof(buf))) {
+ return -EIO;
+ }
+
+ log_msg->entry_v3.len = buf.p.len - sizeof(buf);
+ log_msg->entry_v3.hdr_size = sizeof(log_msg->entry_v3);
+ log_msg->entry_v3.pid = buf.p.pid;
+ log_msg->entry_v3.tid = buf.l.tid;
+ log_msg->entry_v3.sec = buf.l.realtime.tv_sec;
+ log_msg->entry_v3.nsec = buf.l.realtime.tv_nsec;
+ log_msg->entry_v3.lid = buf.l.id;
+
+ return ret;
+ }
+
+ current = TEMP_FAILURE_RETRY(lseek(logger_list->sock,
+ (off_t)0, SEEK_CUR));
+ if (current < 0) {
+ return -errno;
+ }
+ next = TEMP_FAILURE_RETRY(lseek(logger_list->sock,
+ (off_t)(buf.p.len - sizeof(buf)),
+ SEEK_CUR));
+ if (next < 0) {
+ return -errno;
+ }
+ if ((next - current) != (ssize_t)(buf.p.len - sizeof(buf))) {
+ return -EIO;
+ }
+ }
+}
+
static void caught_signal(int signum __unused)
{
}
@@ -582,7 +749,11 @@
return -EINVAL;
}
- if (logger_list->mode & O_NONBLOCK) {
+ if (logger_list->mode & ANDROID_LOG_PSTORE) {
+ return android_logger_list_read_pstore(logger_list, log_msg);
+ }
+
+ if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
memset(&ignore, 0, sizeof(ignore));
ignore.sa_handler = caught_signal;
sigemptyset(&ignore.sa_mask);
@@ -602,7 +773,7 @@
}
strcpy(buffer,
- (logger_list->mode & O_NONBLOCK) ? "dumpAndClose" : "stream");
+ (logger_list->mode & ANDROID_LOG_NONBLOCK) ? "dumpAndClose" : "stream");
cp = buffer + strlen(buffer);
strcpy(cp, " lids");
@@ -640,14 +811,14 @@
cp += ret;
}
- if (logger_list->mode & O_NONBLOCK) {
+ if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
/* Deal with an unresponsive logd */
sigaction(SIGALRM, &ignore, &old_sigaction);
old_alarm = alarm(30);
}
ret = write(sock, buffer, cp - buffer);
e = errno;
- if (logger_list->mode & O_NONBLOCK) {
+ if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
if (e == EINTR) {
e = ETIMEDOUT;
}
@@ -673,7 +844,7 @@
while(1) {
memset(log_msg, 0, sizeof(*log_msg));
- if (logger_list->mode & O_NONBLOCK) {
+ if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
/* particularily useful if tombstone is reporting for logd */
sigaction(SIGALRM, &ignore, &old_sigaction);
old_alarm = alarm(30);
@@ -681,7 +852,7 @@
/* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
ret = recv(logger_list->sock, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
e = errno;
- if (logger_list->mode & O_NONBLOCK) {
+ if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
if ((ret == 0) || (e == EINTR)) {
e = EAGAIN;
ret = -1;
diff --git a/liblog/log_read_kern.c b/liblog/log_read_kern.c
index 41b8a51..bdc7b18 100644
--- a/liblog/log_read_kern.c
+++ b/liblog/log_read_kern.c
@@ -75,10 +75,10 @@
static int accessmode(int mode)
{
- if ((mode & O_ACCMODE) == O_WRONLY) {
+ if ((mode & ANDROID_LOG_ACCMODE) == ANDROID_LOG_WRONLY) {
return W_OK;
}
- if ((mode & O_ACCMODE) == O_RDWR) {
+ if ((mode & ANDROID_LOG_ACCMODE) == ANDROID_LOG_RDWR) {
return R_OK | W_OK;
}
return R_OK;
@@ -117,7 +117,7 @@
++b;
}
- ret = check_allocate_accessible(&n, b, O_RDONLY);
+ ret = check_allocate_accessible(&n, b, ANDROID_LOG_RDONLY);
free(n);
if (ret) {
return ret;
@@ -201,8 +201,8 @@
return -EFAULT;
}
- if (((mode & O_ACCMODE) == O_RDWR)
- || (((mode ^ logger->top->mode) & O_ACCMODE) == 0)) {
+ if (((mode & ANDROID_LOG_ACCMODE) == ANDROID_LOG_RDWR)
+ || (((mode ^ logger->top->mode) & ANDROID_LOG_ACCMODE) == 0)) {
return ioctl(logger->fd, cmd);
}
@@ -227,13 +227,13 @@
int android_logger_clear(struct logger *logger)
{
- return logger_ioctl(logger, LOGGER_FLUSH_LOG, O_WRONLY);
+ return logger_ioctl(logger, LOGGER_FLUSH_LOG, ANDROID_LOG_WRONLY);
}
/* returns the total size of the log's ring buffer */
long android_logger_get_log_size(struct logger *logger)
{
- return logger_ioctl(logger, LOGGER_GET_LOG_BUF_SIZE, O_RDWR);
+ return logger_ioctl(logger, LOGGER_GET_LOG_BUF_SIZE, ANDROID_LOG_RDWR);
}
int android_logger_set_log_size(struct logger *logger __unused,
@@ -248,7 +248,7 @@
*/
long android_logger_get_log_readable_size(struct logger *logger)
{
- return logger_ioctl(logger, LOGGER_GET_LOG_LEN, O_RDONLY);
+ return logger_ioctl(logger, LOGGER_GET_LOG_LEN, ANDROID_LOG_RDONLY);
}
/*
@@ -256,7 +256,7 @@
*/
int android_logger_get_log_version(struct logger *logger)
{
- int ret = logger_ioctl(logger, LOGGER_GET_VERSION, O_RDWR);
+ int ret = logger_ioctl(logger, LOGGER_GET_VERSION, ANDROID_LOG_RDWR);
return (ret < 0) ? 1 : ret;
}
@@ -342,7 +342,7 @@
goto err_name;
}
- logger->fd = open(n, logger_list->mode);
+ logger->fd = open(n, logger_list->mode & (ANDROID_LOG_ACCMODE | ANDROID_LOG_NONBLOCK));
if (logger->fd < 0) {
goto err_name;
}
@@ -565,7 +565,7 @@
if (result <= 0) {
if (result) {
error = errno;
- } else if (logger_list->mode & O_NDELAY) {
+ } else if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
error = EAGAIN;
} else {
logger_list->timeout_ms = LOG_TIMEOUT_NEVER;
diff --git a/liblog/tests/libc_test.cpp b/liblog/tests/libc_test.cpp
index 9839729..29501be 100644
--- a/liblog/tests/libc_test.cpp
+++ b/liblog/tests/libc_test.cpp
@@ -39,7 +39,7 @@
pid_t pid = getpid();
ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
- LOG_ID_EVENTS, O_RDONLY | O_NDELAY, 1000, pid)));
+ LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
@@ -99,7 +99,7 @@
pid_t pid = getpid();
ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
- (log_id_t)LOG_ID_CRASH, O_RDONLY | O_NDELAY, 1000, pid)));
+ (log_id_t)LOG_ID_CRASH, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
char b[80];
struct timespec ts;
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index 549d79e..979aded 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -130,7 +130,7 @@
pid_t pid = getpid();
struct logger_list * logger_list = android_logger_list_open(LOG_ID_EVENTS,
- O_RDONLY, 0, pid);
+ ANDROID_LOG_RDONLY, 0, pid);
if (!logger_list) {
fprintf(stderr, "Unable to open events log: %s\n", strerror(errno));
@@ -208,7 +208,7 @@
pid_t pid = getpid();
struct logger_list * logger_list = android_logger_list_open(LOG_ID_EVENTS,
- O_RDONLY, 0, pid);
+ ANDROID_LOG_RDONLY, 0, pid);
if (!logger_list) {
fprintf(stderr, "Unable to open events log: %s\n", strerror(errno));
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 393e2cd..33f6481 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -122,7 +122,7 @@
pid_t pid = getpid();
ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
- LOG_ID_EVENTS, O_RDONLY | O_NDELAY, 1000, pid)));
+ LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
log_time ts(CLOCK_MONOTONIC);
@@ -223,7 +223,7 @@
v += pid & 0xFFFF;
ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
- LOG_ID_EVENTS, O_RDONLY, 1000, pid)));
+ LOG_ID_EVENTS, ANDROID_LOG_RDONLY, 1000, pid)));
int count = 0;
@@ -443,7 +443,7 @@
struct logger_list *logger_list;
ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
- LOG_ID_SYSTEM, O_RDONLY, 100, 0)));
+ LOG_ID_SYSTEM, ANDROID_LOG_RDONLY, 100, 0)));
bool matches = false;
ssize_t max_len = 0;
@@ -505,7 +505,7 @@
struct logger_list *logger_list;
ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
- LOG_ID_SYSTEM, O_RDONLY | O_NDELAY, 100, 0)));
+ LOG_ID_SYSTEM, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 100, 0)));
ssize_t max_len = 0;
@@ -552,12 +552,12 @@
// >25 messages due to liblog.__android_log_buf_print__concurrentXX above.
ASSERT_TRUE(NULL != (logger_list1 = android_logger_list_open(
- LOG_ID_MAIN, O_RDONLY | O_NDELAY, 25, 0)));
+ LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 25, 0)));
struct logger_list *logger_list2;
if (NULL == (logger_list2 = android_logger_list_open(
- LOG_ID_MAIN, O_RDONLY | O_NDELAY, 15, 0))) {
+ LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 15, 0))) {
android_logger_list_close(logger_list1);
ASSERT_TRUE(NULL != logger_list2);
}
@@ -595,7 +595,7 @@
}
TEST(liblog, android_logger_get_) {
- struct logger_list * logger_list = android_logger_list_alloc(O_WRONLY, 0, 0);
+ struct logger_list * logger_list = android_logger_list_alloc(ANDROID_LOG_WRONLY, 0, 0);
for(int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
log_id_t id = static_cast<log_id_t>(i);
diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c
index bfe7121..7d2a5fb 100644
--- a/libnetutils/ifc_utils.c
+++ b/libnetutils/ifc_utils.c
@@ -123,7 +123,7 @@
{
int ret;
if (ifc_ctl_sock == -1) {
- ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0);
+ ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (ifc_ctl_sock < 0) {
printerr("socket() failed: %s\n", strerror(errno));
}
@@ -137,7 +137,7 @@
int ifc_init6(void)
{
if (ifc_ctl_sock6 == -1) {
- ifc_ctl_sock6 = socket(AF_INET6, SOCK_DGRAM, 0);
+ ifc_ctl_sock6 = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (ifc_ctl_sock6 < 0) {
printerr("socket() failed: %s\n", strerror(errno));
}
@@ -316,7 +316,7 @@
req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len) + RTA_LENGTH(addrlen);
memcpy(RTA_DATA(rta), addr, addrlen);
- s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ s = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
if (send(s, &req, req.n.nlmsg_len, 0) < 0) {
close(s);
return -errno;
diff --git a/libutils/FileMap.cpp b/libutils/FileMap.cpp
index f49b4f9..91e45d8 100644
--- a/libutils/FileMap.cpp
+++ b/libutils/FileMap.cpp
@@ -48,7 +48,7 @@
// Constructor. Create an empty object.
FileMap::FileMap(void)
- : mRefCount(1), mFileName(NULL), mBasePtr(NULL), mBaseLength(0),
+ : mFileName(NULL), mBasePtr(NULL), mBaseLength(0),
mDataPtr(NULL), mDataLength(0)
{
}
@@ -56,11 +56,6 @@
// Destructor.
FileMap::~FileMap(void)
{
- assert(mRefCount == 0);
-
- //printf("+++ removing FileMap %p %zu\n", mDataPtr, mDataLength);
-
- mRefCount = -100; // help catch double-free
if (mFileName != NULL) {
free(mFileName);
}
@@ -134,27 +129,20 @@
void* ptr;
- assert(mRefCount == 1);
assert(fd >= 0);
assert(offset >= 0);
assert(length > 0);
// init on first use
if (mPageSize == -1) {
-#if NOT_USING_KLIBC
mPageSize = sysconf(_SC_PAGESIZE);
if (mPageSize == -1) {
ALOGE("could not get _SC_PAGESIZE\n");
return false;
}
-#else
- // this holds for Linux, Darwin, Cygwin, and doesn't pain the ARM
- mPageSize = 4096;
-#endif
}
- adjust = offset % mPageSize;
-try_again:
+ adjust = offset % mPageSize;
adjOffset = offset - adjust;
adjLength = length + adjust;
@@ -165,13 +153,6 @@
ptr = mmap(NULL, adjLength, prot, flags, fd, adjOffset);
if (ptr == MAP_FAILED) {
- // Cygwin does not seem to like file mapping files from an offset.
- // So if we fail, try again with offset zero
- if (adjOffset > 0) {
- adjust = offset;
- goto try_again;
- }
-
ALOGE("mmap(%lld,%zu) failed: %s\n",
(long long)adjOffset, adjLength, strerror(errno));
return false;
diff --git a/libutils/Tokenizer.cpp b/libutils/Tokenizer.cpp
index 7067533..610002f 100644
--- a/libutils/Tokenizer.cpp
+++ b/libutils/Tokenizer.cpp
@@ -43,9 +43,7 @@
}
Tokenizer::~Tokenizer() {
- if (mFileMap) {
- mFileMap->release();
- }
+ delete mFileMap;
if (mOwnBuffer) {
delete[] mBuffer;
}
@@ -74,7 +72,7 @@
fileMap->advise(FileMap::SEQUENTIAL);
buffer = static_cast<char*>(fileMap->getDataPtr());
} else {
- fileMap->release();
+ delete fileMap;
fileMap = NULL;
// Fall back to reading into a buffer since we can't mmap files in sysfs.
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index afc122d..ebbab9f 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -321,9 +321,7 @@
close(fd);
}
- if (directory_map != NULL) {
- directory_map->release();
- }
+ delete directory_map;
free(hash_table);
}
};
@@ -335,7 +333,7 @@
android::FileMap* file_map = new android::FileMap;
const bool success = file_map->create(debug_file_name, fd, start, length, read_only);
if (!success) {
- file_map->release();
+ delete file_map;
return NULL;
}
@@ -1170,7 +1168,7 @@
const int32_t error = ExtractToMemory(handle, entry,
reinterpret_cast<uint8_t*>(map->getDataPtr()),
map->getDataLength());
- map->release();
+ delete map;
return error;
}
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 79f2ebd..cd5003e 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -1,4 +1,4 @@
-// Copyright 2006-2014 The Android Open Source Project
+// Copyright 2006-2015 The Android Open Source Project
#include <assert.h>
#include <ctype.h>
@@ -178,18 +178,19 @@
return;
}
-static void maybePrintStart(log_device_t* dev) {
- if (!dev->printed) {
- dev->printed = true;
+static void maybePrintStart(log_device_t* dev, bool printDividers) {
+ if (!dev->printed || printDividers) {
if (g_devCount > 1 && !g_printBinary) {
char buf[1024];
- snprintf(buf, sizeof(buf), "--------- beginning of %s\n",
+ snprintf(buf, sizeof(buf), "--------- %s %s\n",
+ dev->printed ? "switch to" : "beginning of",
dev->device);
if (write(g_outFD, buf, strlen(buf)) < 0) {
perror("output error");
exit(-1);
}
}
+ dev->printed = true;
}
}
@@ -227,6 +228,7 @@
" -n <count> Sets max number of rotated logs to <count>, default 4\n"
" -v <format> Sets the log print format, where <format> is:\n\n"
" brief color long process raw tag thread threadtime time\n\n"
+ " -D print dividers between each log buffer\n"
" -c clear (flush) the entire log and exit\n"
" -d dump the log and then exit (don't block)\n"
" -t <count> print only the most recent <count> lines (implies -d)\n"
@@ -235,6 +237,7 @@
" -T '<time>' print most recent lines since specified time (not imply -d)\n"
" count is pure numerical, time is 'MM-DD hh:mm:ss.mmm'\n"
" -g get the size of the log's ring buffer and exit\n"
+ " -L dump logs from prior to last reboot\n"
" -b <buffer> Request alternate ring buffer, 'main', 'system', 'radio',\n"
" 'events', 'crash' or 'all'. Multiple -b parameters are\n"
" allowed and results are interleaved. The default is\n"
@@ -324,11 +327,12 @@
int getPruneList = 0;
char *setPruneList = NULL;
int printStatistics = 0;
- int mode = O_RDONLY;
+ int mode = ANDROID_LOG_RDONLY;
const char *forceFilters = NULL;
log_device_t* devices = NULL;
log_device_t* dev;
bool needBinary = false;
+ bool printDividers = false;
struct logger_list *logger_list;
unsigned int tail_lines = 0;
log_time tail_time(log_time::EPOCH);
@@ -345,7 +349,7 @@
for (;;) {
int ret;
- ret = getopt(argc, argv, "cdt:T:gG:sQf:r:n:v:b:BSpP:");
+ ret = getopt(argc, argv, "cdDLt:T:gG:sQf:r:n:v:b:BSpP:");
if (ret < 0) {
break;
@@ -359,15 +363,19 @@
case 'c':
clearLog = 1;
- mode = O_WRONLY;
+ mode |= ANDROID_LOG_WRONLY;
+ break;
+
+ case 'L':
+ mode |= ANDROID_LOG_PSTORE;
break;
case 'd':
- mode = O_RDONLY | O_NDELAY;
+ mode |= ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK;
break;
case 't':
- mode = O_RDONLY | O_NDELAY;
+ mode |= ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK;
/* FALLTHRU */
case 'T':
if (strspn(optarg, "0123456789") != strlen(optarg)) {
@@ -398,6 +406,10 @@
}
break;
+ case 'D':
+ printDividers = true;
+ break;
+
case 'g':
getLogSize = 1;
break;
@@ -839,8 +851,10 @@
if (needBinary)
android::g_eventTagMap = android_openEventTagMap(EVENT_TAG_MAP_FILE);
+ dev = NULL;
while (1) {
struct log_msg log_msg;
+ log_device_t* d;
int ret = android_logger_list_read(logger_list, &log_msg);
if (ret == 0) {
@@ -865,17 +879,20 @@
exit(EXIT_FAILURE);
}
- for(dev = devices; dev; dev = dev->next) {
- if (android_name_to_log_id(dev->device) == log_msg.id()) {
+ for(d = devices; d; d = d->next) {
+ if (android_name_to_log_id(d->device) == log_msg.id()) {
break;
}
}
- if (!dev) {
+ if (!d) {
fprintf(stderr, "read: Unexpected log ID!\n");
exit(EXIT_FAILURE);
}
- android::maybePrintStart(dev);
+ if (dev != d) {
+ dev = d;
+ android::maybePrintStart(dev, printDividers);
+ }
if (android::g_printBinary) {
android::printBinary(&log_msg);
} else {
diff --git a/rootdir/init.rc b/rootdir/init.rc
index bbb812b..2a599ac 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -247,22 +247,6 @@
# Avoid predictable entropy pool. Carry over entropy from previous boot.
copy /data/system/entropy.dat /dev/urandom
- # Create dump dir and collect dumps.
- # Do this before we mount cache so eventually we can use cache for
- # storing dumps on platforms which do not have a dedicated dump partition.
- mkdir /data/dontpanic 0750 root log
-
- # Collect apanic data, free resources and re-arm trigger
- copy /proc/apanic_console /data/dontpanic/apanic_console
- chown root log /data/dontpanic/apanic_console
- chmod 0640 /data/dontpanic/apanic_console
-
- copy /proc/apanic_threads /data/dontpanic/apanic_threads
- chown root log /data/dontpanic/apanic_threads
- chmod 0640 /data/dontpanic/apanic_threads
-
- write /proc/apanic_console 1
-
# create basic filesystem structure
mkdir /data/misc 01771 system misc
mkdir /data/misc/adb 02750 system shell
@@ -494,7 +478,6 @@
socket logd stream 0666 logd logd
socket logdr seqpacket 0666 logd logd
socket logdw dgram 0222 logd logd
- seclabel u:r:logd:s0
service healthd /sbin/healthd
class core
@@ -608,7 +591,6 @@
service flash_recovery /system/bin/install-recovery.sh
class main
- seclabel u:r:install_recovery:s0
oneshot
service racoon /system/bin/racoon