am 3678a5fb: Merge "Move crypt commands to a different listener in vold" into mnc-dev
* commit '3678a5fb8d1094c4796c1316f3b571cb63cf7246':
Move crypt commands to a different listener in vold
diff --git a/adb/Android.mk b/adb/Android.mk
index 1613a88..f030041 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -6,16 +6,17 @@
LOCAL_PATH:= $(call my-dir)
ifeq ($(HOST_OS),windows)
- adb_host_clang := false # libc++ for mingw not ready yet.
+ adb_host_clang := false # libc++ for mingw not ready yet.
else
- adb_host_clang := true
+ adb_host_clang := true
endif
adb_version := $(shell git -C $(LOCAL_PATH) rev-parse --short=12 HEAD 2>/dev/null)-android
ADB_COMMON_CFLAGS := \
- -Wall -Werror \
+ -Wall -Wextra -Werror \
-Wno-unused-parameter \
+ -Wno-missing-field-initializers \
-DADB_REVISION='"$(adb_version)"' \
# libadb
@@ -45,7 +46,6 @@
LIBADB_CFLAGS := \
$(ADB_COMMON_CFLAGS) \
- -Wno-missing-field-initializers \
-fvisibility=hidden \
LIBADB_darwin_SRC_FILES := \
@@ -77,6 +77,10 @@
LOCAL_SHARED_LIBRARIES := libbase
+# Even though we're building a static library (and thus there's no link step for
+# this to take effect), this adds the includes to our path.
+LOCAL_STATIC_LIBRARIES := libbase
+
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
@@ -91,8 +95,8 @@
LOCAL_SHARED_LIBRARIES := libbase
# 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
+# this to take effect), this adds the includes to our path.
+LOCAL_STATIC_LIBRARIES := libcrypto_static libbase
ifeq ($(HOST_OS),windows)
LOCAL_C_INCLUDES += development/host/windows/usb/api/
@@ -109,6 +113,7 @@
LOCAL_SHARED_LIBRARIES := liblog libbase libcutils
include $(BUILD_NATIVE_TEST)
+ifneq ($(HOST_OS),windows)
include $(CLEAR_VARS)
LOCAL_CLANG := $(adb_host_clang)
LOCAL_MODULE := adb_test
@@ -121,14 +126,15 @@
libcutils \
ifeq ($(HOST_OS),linux)
- LOCAL_LDLIBS += -lrt -ldl -lpthread
+ LOCAL_LDLIBS += -lrt -ldl -lpthread
endif
ifeq ($(HOST_OS),darwin)
- LOCAL_LDLIBS += -framework CoreFoundation -framework IOKit
+ LOCAL_LDLIBS += -framework CoreFoundation -framework IOKit
endif
include $(BUILD_HOST_NATIVE_TEST)
+endif
# adb device tracker (used by ddms) test tool
# =========================================================
@@ -150,24 +156,24 @@
include $(CLEAR_VARS)
ifeq ($(HOST_OS),linux)
- LOCAL_LDLIBS += -lrt -ldl -lpthread
- LOCAL_CFLAGS += -DWORKAROUND_BUG6558362
+ LOCAL_LDLIBS += -lrt -ldl -lpthread
+ LOCAL_CFLAGS += -DWORKAROUND_BUG6558362
endif
ifeq ($(HOST_OS),darwin)
- LOCAL_LDLIBS += -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
- LOCAL_CFLAGS += -Wno-sizeof-pointer-memaccess -Wno-unused-parameter
+ LOCAL_LDLIBS += -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
+ LOCAL_CFLAGS += -Wno-sizeof-pointer-memaccess -Wno-unused-parameter
endif
ifeq ($(HOST_OS),windows)
- LOCAL_LDLIBS += -lws2_32 -lgdi32
- EXTRA_STATIC_LIBS := AdbWinApi
+ LOCAL_LDLIBS += -lws2_32 -lgdi32
+ EXTRA_STATIC_LIBS := AdbWinApi
endif
LOCAL_CLANG := $(adb_host_clang)
LOCAL_SRC_FILES := \
- adb_main.cpp \
+ client/main.cpp \
console.cpp \
commandline.cpp \
adb_client.cpp \
@@ -219,7 +225,7 @@
LOCAL_CLANG := true
LOCAL_SRC_FILES := \
- adb_main.cpp \
+ daemon/main.cpp \
services.cpp \
file_sync_service.cpp \
framebuffer_service.cpp \
@@ -252,10 +258,10 @@
libbase \
libfs_mgr \
liblog \
- libcutils \
- libc \
libmincrypt \
libselinux \
libext4_utils_static \
+ libcutils \
+ libbase \
include $(BUILD_EXECUTABLE)
diff --git a/adb/CPPLINT.cfg b/adb/CPPLINT.cfg
index 9b906e8..f496490 100644
--- a/adb/CPPLINT.cfg
+++ b/adb/CPPLINT.cfg
@@ -1,2 +1,2 @@
set noparent
-filter=-build/header_guard,-build/include,-readability/function
+filter=-build/header_guard,-build/include,-readability/function,-whitespace/indent
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 8a7b9c9..ff6a499 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -31,7 +31,10 @@
#include <time.h>
#include <string>
+#include <vector>
+#include <unordered_map>
+#include <base/logging.h>
#include <base/stringprintf.h>
#include <base/strings.h>
@@ -48,16 +51,25 @@
#include <sys/mount.h>
#endif
-ADB_MUTEX_DEFINE( D_lock );
+ADB_MUTEX_DEFINE(D_lock);
int HOST = 0;
#if !ADB_HOST
-const char *adb_device_banner = "device";
+const char* adb_device_banner = "device";
+static android::base::LogdLogger gLogdLogger;
#endif
-void fatal(const char *fmt, ...)
-{
+void AdbLogger(android::base::LogId id, android::base::LogSeverity severity,
+ const char* tag, const char* file, unsigned int line,
+ const char* message) {
+ android::base::StderrLogger(id, severity, tag, file, line, message);
+#if !ADB_HOST
+ gLogdLogger(id, severity, tag, file, line, message);
+#endif
+}
+
+void fatal(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "error: ");
@@ -67,8 +79,7 @@
exit(-1);
}
-void fatal_errno(const char *fmt, ...)
-{
+void fatal_errno(const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "error: %s: ", strerror(errno));
@@ -79,7 +90,7 @@
}
#if !ADB_HOST
-void start_device_log(void) {
+static std::string get_log_file_name() {
struct tm now;
time_t t;
tzset();
@@ -89,17 +100,22 @@
char timestamp[PATH_MAX];
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d-%H-%M-%S", &now);
- std::string path = android::base::StringPrintf("/data/adb/adb-%s-%d", timestamp, getpid());
- int fd = unix_open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0640);
+ return android::base::StringPrintf("/data/adb/adb-%s-%d", timestamp,
+ getpid());
+}
+
+void start_device_log(void) {
+ int fd = unix_open(get_log_file_name().c_str(),
+ O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0640);
if (fd == -1) {
return;
}
- // redirect stdout and stderr to the log file
+ // Redirect stdout and stderr to the log file.
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
fprintf(stderr, "--- adb starting (pid %d) ---\n", getpid());
- adb_close(fd);
+ unix_close(fd);
}
#endif
@@ -130,71 +146,58 @@
#endif
}
-// Split the comma/space/colum/semi-column separated list of tags from the trace
-// setting and build the trace mask from it. note that '1' and 'all' are special
-// cases to enable all tracing.
+// Split the space separated list of tags from the trace setting and build the
+// trace mask from it. note that '1' and 'all' are special cases to enable all
+// tracing.
//
// adb's trace setting comes from the ADB_TRACE environment variable, whereas
// adbd's comes from the system property persist.adb.trace_mask.
-void adb_trace_init() {
+static void setup_trace_mask() {
const std::string trace_setting = get_trace_setting();
- static const struct {
- const char* tag;
- int flag;
- } tags[] = {
- { "1", 0 },
- { "all", 0 },
- { "adb", TRACE_ADB },
- { "sockets", TRACE_SOCKETS },
- { "packets", TRACE_PACKETS },
- { "rwx", TRACE_RWX },
- { "usb", TRACE_USB },
- { "sync", TRACE_SYNC },
- { "sysdeps", TRACE_SYSDEPS },
- { "transport", TRACE_TRANSPORT },
- { "jdwp", TRACE_JDWP },
- { "services", TRACE_SERVICES },
- { "auth", TRACE_AUTH },
- { NULL, 0 }
- };
+ std::unordered_map<std::string, int> trace_flags = {
+ {"1", 0},
+ {"all", 0},
+ {"adb", TRACE_ADB},
+ {"sockets", TRACE_SOCKETS},
+ {"packets", TRACE_PACKETS},
+ {"rwx", TRACE_RWX},
+ {"usb", TRACE_USB},
+ {"sync", TRACE_SYNC},
+ {"sysdeps", TRACE_SYSDEPS},
+ {"transport", TRACE_TRANSPORT},
+ {"jdwp", TRACE_JDWP},
+ {"services", TRACE_SERVICES},
+ {"auth", TRACE_AUTH}};
- if (trace_setting.empty()) {
- return;
- }
-
- // Use a comma/colon/semi-colon/space separated list
- const char* p = trace_setting.c_str();
- while (*p) {
- int len, tagn;
-
- const char* q = strpbrk(p, " ,:;");
- if (q == NULL) {
- q = p + strlen(p);
+ std::vector<std::string> elements = android::base::Split(trace_setting, " ");
+ for (const auto& elem : elements) {
+ const auto& flag = trace_flags.find(elem);
+ if (flag == trace_flags.end()) {
+ D("Unknown trace flag: %s", flag->first.c_str());
+ continue;
}
- len = q - p;
- for (tagn = 0; tags[tagn].tag != NULL; tagn++) {
- int taglen = strlen(tags[tagn].tag);
-
- if (len == taglen && !memcmp(tags[tagn].tag, p, len)) {
- int flag = tags[tagn].flag;
- if (flag == 0) {
- adb_trace_mask = ~0;
- return;
- }
- adb_trace_mask |= (1 << flag);
- break;
- }
+ if (flag->second == 0) {
+ // 0 is used for the special values "1" and "all" that enable all
+ // tracing.
+ adb_trace_mask = ~0;
+ return;
+ } else {
+ adb_trace_mask |= 1 << flag->second;
}
- p = q;
- if (*p)
- p++;
}
+}
+void adb_trace_init(char** argv) {
#if !ADB_HOST
- start_device_log();
+ if (isatty(STDOUT_FILENO) == 0) {
+ start_device_log();
+ }
#endif
+
+ setup_trace_mask();
+ android::base::InitLogging(argv, AdbLogger);
}
apacket* get_apacket(void)
@@ -369,24 +372,24 @@
const std::string& type = pieces[0];
if (type == "bootloader") {
- D("setting connection_state to CS_BOOTLOADER\n");
- t->connection_state = CS_BOOTLOADER;
+ D("setting connection_state to kCsBootloader\n");
+ t->connection_state = kCsBootloader;
update_transports();
} else if (type == "device") {
- D("setting connection_state to CS_DEVICE\n");
- t->connection_state = CS_DEVICE;
+ D("setting connection_state to kCsDevice\n");
+ t->connection_state = kCsDevice;
update_transports();
} else if (type == "recovery") {
- D("setting connection_state to CS_RECOVERY\n");
- t->connection_state = CS_RECOVERY;
+ D("setting connection_state to kCsRecovery\n");
+ t->connection_state = kCsRecovery;
update_transports();
} else if (type == "sideload") {
- D("setting connection_state to CS_SIDELOAD\n");
- t->connection_state = CS_SIDELOAD;
+ D("setting connection_state to kCsSideload\n");
+ t->connection_state = kCsSideload;
update_transports();
} else {
- D("setting connection_state to CS_HOST\n");
- t->connection_state = CS_HOST;
+ D("setting connection_state to kCsHost\n");
+ t->connection_state = kCsHost;
}
}
@@ -406,7 +409,7 @@
send_packet(p, t);
if(HOST) send_connect(t);
} else {
- t->connection_state = CS_OFFLINE;
+ t->connection_state = kCsOffline;
handle_offline(t);
send_packet(p, t);
}
@@ -414,8 +417,8 @@
case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
/* XXX verify version, etc */
- if(t->connection_state != CS_OFFLINE) {
- t->connection_state = CS_OFFLINE;
+ if(t->connection_state != kCsOffline) {
+ t->connection_state = kCsOffline;
handle_offline(t);
}
@@ -431,7 +434,7 @@
case A_AUTH:
if (p->msg.arg0 == ADB_AUTH_TOKEN) {
- t->connection_state = CS_UNAUTHORIZED;
+ t->connection_state = kCsUnauthorized;
t->key = adb_auth_nextkey(t->key);
if (t->key) {
send_auth_response(p->data, p->msg.data_length, t);
@@ -696,7 +699,7 @@
// 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.
-int handle_forward_request(const char* service, transport_type ttype, char* serial, int reply_fd)
+int handle_forward_request(const char* service, TransportType type, const char* serial, int reply_fd)
{
if (!strcmp(service, "list-forward")) {
// Create the list of forward redirections.
@@ -718,56 +721,50 @@
return 1;
}
- if (!strncmp(service, "forward:",8) ||
- !strncmp(service, "killforward:",12)) {
- char *local, *remote;
- atransport *transport;
-
- int createForward = strncmp(service, "kill", 4);
- int no_rebind = 0;
-
- local = strchr(service, ':') + 1;
-
- // Handle forward:norebind:<local>... here
- if (createForward && !strncmp(local, "norebind:", 9)) {
- no_rebind = 1;
- local = strchr(local, ':') + 1;
+ if (!strncmp(service, "forward:", 8) || !strncmp(service, "killforward:", 12)) {
+ // killforward:local
+ // forward:(norebind:)?local;remote
+ bool kill_forward = false;
+ bool no_rebind = false;
+ if (android::base::StartsWith(service, "killforward:")) {
+ kill_forward = true;
+ service += 12;
+ if (android::base::StartsWith(service, "norebind:")) {
+ no_rebind = true;
+ service += 9;
+ }
+ } else {
+ service += 8;
}
- remote = strchr(local,';');
+ std::vector<std::string> pieces = android::base::Split(service, ";");
- if (createForward) {
- // Check forward: parameter format: '<local>;<remote>'
- if(remote == 0) {
- SendFail(reply_fd, "malformed forward spec");
- return 1;
- }
-
- *remote++ = 0;
- if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')) {
- SendFail(reply_fd, "malformed forward spec");
+ if (kill_forward) {
+ // Check killforward: parameter format: '<local>'
+ if (pieces.size() != 1 || pieces[0].empty()) {
+ SendFail(reply_fd, android::base::StringPrintf("bad killforward: %s", service));
return 1;
}
} else {
- // Check killforward: parameter format: '<local>'
- if (local[0] == 0) {
- SendFail(reply_fd, "malformed forward spec");
+ // Check forward: parameter format: '<local>;<remote>'
+ if (pieces.size() != 2 || pieces[0].empty() || pieces[1].empty() || pieces[1][0] == '*') {
+ SendFail(reply_fd, android::base::StringPrintf("bad forward: %s", service));
return 1;
}
}
std::string error_msg;
- transport = acquire_one_transport(CS_ANY, ttype, serial, &error_msg);
+ atransport* transport = acquire_one_transport(kCsAny, type, serial, &error_msg);
if (!transport) {
SendFail(reply_fd, error_msg);
return 1;
}
- install_status_t r;
- if (createForward) {
- r = install_listener(local, remote, transport, no_rebind);
+ InstallStatus r;
+ if (kill_forward) {
+ r = remove_listener(pieces[0].c_str(), transport);
} else {
- r = remove_listener(local, transport);
+ r = install_listener(pieces[0], pieces[1].c_str(), transport, no_rebind);
}
if (r == INSTALL_STATUS_OK) {
#if ADB_HOST
@@ -780,7 +777,7 @@
std::string message;
switch (r) {
- case INSTALL_STATUS_OK: message = " "; break;
+ case INSTALL_STATUS_OK: message = "success (!)"; break;
case INSTALL_STATUS_INTERNAL_ERROR: message = "internal error"; break;
case INSTALL_STATUS_CANNOT_BIND:
message = android::base::StringPrintf("cannot bind to socket: %s", strerror(errno));
@@ -788,7 +785,9 @@
case INSTALL_STATUS_CANNOT_REBIND:
message = android::base::StringPrintf("cannot rebind existing socket: %s", strerror(errno));
break;
- case INSTALL_STATUS_LISTENER_NOT_FOUND: message = "listener not found"; break;
+ case INSTALL_STATUS_LISTENER_NOT_FOUND:
+ message = android::base::StringPrintf("listener '%s' not found", service);
+ break;
}
SendFail(reply_fd, message);
return 1;
@@ -796,13 +795,12 @@
return 0;
}
-int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
-{
- if(!strcmp(service, "kill")) {
- fprintf(stderr,"adb server killed by remote request\n");
+int handle_host_request(const char* service, TransportType type,
+ const char* serial, int reply_fd, asocket* s) {
+ if (strcmp(service, "kill") == 0) {
+ fprintf(stderr, "adb server killed by remote request\n");
fflush(stdout);
SendOkay(reply_fd);
- usb_cleanup();
exit(0);
}
@@ -813,7 +811,7 @@
// "transport-local:" is used for switching transport to the only local transport
// "transport-any:" is used for switching transport to the only transport
if (!strncmp(service, "transport", strlen("transport"))) {
- transport_type type = kTransportAny;
+ TransportType type = kTransportAny;
if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
type = kTransportUsb;
@@ -827,7 +825,7 @@
}
std::string error_msg = "unknown failure";
- transport = acquire_one_transport(CS_ANY, type, serial, &error_msg);
+ transport = acquire_one_transport(kCsAny, type, serial, &error_msg);
if (transport) {
s->transport = transport;
@@ -856,7 +854,7 @@
if (!strncmp(service, "disconnect:", 11)) {
char buffer[4096];
memset(buffer, 0, sizeof(buffer));
- char* serial = service + 11;
+ const char* serial = service + 11;
if (serial[0] == 0) {
// disconnect from all TCP devices
unregister_all_tcp_transports();
@@ -890,7 +888,7 @@
if(!strncmp(service,"get-serialno",strlen("get-serialno"))) {
const char *out = "unknown";
- transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
+ transport = acquire_one_transport(kCsAny, type, serial, NULL);
if (transport && transport->serial) {
out = transport->serial;
}
@@ -900,7 +898,7 @@
}
if(!strncmp(service,"get-devpath",strlen("get-devpath"))) {
const char *out = "unknown";
- transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
+ transport = acquire_one_transport(kCsAny, type, serial, NULL);
if (transport && transport->devpath) {
out = transport->devpath;
}
@@ -917,14 +915,14 @@
}
if(!strncmp(service,"get-state",strlen("get-state"))) {
- transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
+ transport = acquire_one_transport(kCsAny, type, serial, NULL);
SendOkay(reply_fd);
SendProtocolString(reply_fd, transport->connection_state_name());
return 0;
}
#endif // ADB_HOST
- int ret = handle_forward_request(service, ttype, serial, reply_fd);
+ int ret = handle_forward_request(service, type, serial, reply_fd);
if (ret >= 0)
return ret - 1;
return -1;
diff --git a/adb/adb.h b/adb/adb.h
index fd9d0e6..1be83d7 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -20,6 +20,8 @@
#include <limits.h>
#include <sys/types.h>
+#include <base/macros.h>
+
#include "adb_trace.h"
#include "fdevent.h"
@@ -43,7 +45,7 @@
// Increment this when we want to force users to start a new adb server.
#define ADB_SERVER_VERSION 32
-struct atransport;
+class atransport;
struct usb_handle;
struct amessage {
@@ -152,65 +154,88 @@
};
-/* a transport object models the connection to a remote device or emulator
-** there is one transport per connected device/emulator. a "local transport"
-** connects through TCP (for the emulator), while a "usb transport" through
-** USB (for real devices)
-**
-** note that kTransportHost doesn't really correspond to a real transport
-** object, it's a special value used to indicate that a client wants to
-** connect to a service implemented within the ADB server itself.
-*/
-enum transport_type {
- kTransportUsb,
- kTransportLocal,
- kTransportAny,
- kTransportHost,
+// A transport object models the connection to a remote device or emulator there
+// is one transport per connected device/emulator. A "local transport" connects
+// through TCP (for the emulator), while a "usb transport" through USB (for real
+// devices).
+//
+// Note that kTransportHost doesn't really correspond to a real transport
+// object, it's a special value used to indicate that a client wants to connect
+// to a service implemented within the ADB server itself.
+enum TransportType {
+ kTransportUsb,
+ kTransportLocal,
+ kTransportAny,
+ kTransportHost,
};
#define TOKEN_SIZE 20
-struct atransport
-{
- atransport *next;
- atransport *prev;
+enum ConnectionState {
+ kCsAny = -1,
+ kCsOffline = 0,
+ kCsBootloader,
+ kCsDevice,
+ kCsHost,
+ kCsRecovery,
+ kCsNoPerm, // Insufficient permissions to communicate with the device.
+ kCsSideload,
+ kCsUnauthorized,
+};
- int (*read_from_remote)(apacket *p, atransport *t);
- int (*write_to_remote)(apacket *p, atransport *t);
- void (*close)(atransport *t);
- void (*kick)(atransport *t);
+class atransport {
+public:
+ // TODO(danalbert): We expose waaaaaaay too much stuff because this was
+ // historically just a struct, but making the whole thing a more idiomatic
+ // class in one go is a very large change. Given how bad our testing is,
+ // it's better to do this piece by piece.
- int fd;
- int transport_socket;
+ atransport() {
+ auth_fde = {};
+ transport_fde = {};
+ }
+
+ virtual ~atransport() {}
+
+ int (*read_from_remote)(apacket* p, atransport* t) = nullptr;
+ int (*write_to_remote)(apacket* p, atransport* t) = nullptr;
+ void (*close)(atransport* t) = nullptr;
+ void (*kick)(atransport* t) = nullptr;
+
+ int fd = -1;
+ int transport_socket = -1;
fdevent transport_fde;
- int ref_count;
- unsigned sync_token;
- int connection_state;
- int online;
- transport_type type;
+ int ref_count = 0;
+ uint32_t sync_token = 0;
+ ConnectionState connection_state = kCsOffline;
+ bool online = false;
+ TransportType type = kTransportAny;
- /* usb handle or socket fd as needed */
- usb_handle *usb;
- int sfd;
+ // USB handle or socket fd as needed.
+ usb_handle* usb = nullptr;
+ int sfd = -1;
- /* used to identify transports for clients */
- char *serial;
- char *product;
- char *model;
- char *device;
- char *devpath;
- int adb_port; // Use for emulators (local transport)
+ // Used to identify transports for clients.
+ char* serial = nullptr;
+ char* product = nullptr;
+ char* model = nullptr;
+ char* device = nullptr;
+ char* devpath = nullptr;
+ int adb_port = -1; // Use for emulators (local transport)
+ bool kicked = false;
- /* a list of adisconnect callbacks called when the transport is kicked */
- int kicked;
- adisconnect disconnects;
+ // A list of adisconnect callbacks called when the transport is kicked.
+ adisconnect disconnects = {};
- void *key;
- unsigned char token[TOKEN_SIZE];
+ void* key = nullptr;
+ unsigned char token[TOKEN_SIZE] = {};
fdevent auth_fde;
- unsigned failed_auth_attempts;
+ size_t failed_auth_attempts = 0;
const char* connection_state_name() const;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(atransport);
};
@@ -266,7 +291,7 @@
int get_available_local_transport_index();
#endif
int init_socket_transport(atransport *t, int s, int port, int local);
-void init_usb_transport(atransport *t, usb_handle *usb, int state);
+void init_usb_transport(atransport *t, usb_handle *usb, ConnectionState state);
#if ADB_HOST
atransport* find_emulator_transport_by_adb_port(int adb_port);
@@ -284,7 +309,7 @@
int create_jdwp_connection_fd(int jdwp_pid);
#endif
-int handle_forward_request(const char* service, transport_type ttype, char* serial, int reply_fd);
+int handle_forward_request(const char* service, TransportType type, const char* serial, int reply_fd);
#if !ADB_HOST
void framebuffer_service(int fd, void *cookie);
@@ -324,7 +349,6 @@
/* usb host/client interface */
void usb_init();
-void usb_cleanup();
int usb_write(usb_handle *h, const void *data, int len);
int usb_read(usb_handle *h, void *data, int len);
int usb_close(usb_handle *h);
@@ -337,27 +361,12 @@
int adb_commandline(int argc, const char **argv);
-int connection_state(atransport *t);
-
-#define CS_ANY -1
-#define CS_OFFLINE 0
-#define CS_BOOTLOADER 1
-#define CS_DEVICE 2
-#define CS_HOST 3
-#define CS_RECOVERY 4
-#define CS_NOPERM 5 /* Insufficient permissions to communicate with the device */
-#define CS_SIDELOAD 6
-#define CS_UNAUTHORIZED 7
+ConnectionState connection_state(atransport *t);
extern const char *adb_device_banner;
extern int HOST;
extern int SHELL_EXIT_NOTIFY_FD;
-enum subproc_mode {
- SUBPROC_PTY = 0,
- SUBPROC_RAW = 1,
-} ;
-
#define CHUNK_SIZE (64*1024)
#if !ADB_HOST
@@ -371,7 +380,7 @@
#define USB_FFS_ADB_IN USB_FFS_ADB_EP(ep2)
#endif
-int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s);
+int handle_host_request(const char* service, TransportType type, const char* serial, int reply_fd, asocket *s);
void handle_online(atransport *t);
void handle_offline(atransport *t);
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index 510dcc2..e878f8b 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -173,7 +173,7 @@
return 0;
}
- outfile = fopen(path, "we");
+ outfile = fopen(path, "w");
if (!outfile) {
D("Failed to open '%s'\n", path);
return 0;
@@ -239,7 +239,7 @@
old_mask = umask(077);
- f = fopen(file, "we");
+ f = fopen(file, "w");
if (!f) {
D("Failed to open '%s'\n", file);
umask(old_mask);
@@ -273,7 +273,7 @@
{
D("read_key '%s'\n", file);
- FILE* fp = fopen(file, "re");
+ FILE* fp = fopen(file, "r");
if (!fp) {
D("Failed to open '%s': %s\n", file, strerror(errno));
return 0;
@@ -420,6 +420,9 @@
strcat(path, ".pub");
// TODO(danalbert): ReadFileToString
+ // Note that on Windows, load_file() does not do CR/LF translation, but
+ // ReadFileToString() uses the C Runtime which uses CR/LF translation by
+ // default (by is overridable with _setmode()).
unsigned size;
char* file_data = reinterpret_cast<char*>(load_file(path, &size));
if (file_data == nullptr) {
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index 7bb8e4a..ef9a586 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -36,7 +36,7 @@
#include "adb_io.h"
-static transport_type __adb_transport = kTransportAny;
+static TransportType __adb_transport = kTransportAny;
static const char* __adb_serial = NULL;
static int __adb_server_port = DEFAULT_ADB_PORT;
@@ -64,7 +64,7 @@
return true;
}
-void adb_set_transport(transport_type type, const char* serial)
+void adb_set_transport(TransportType type, const char* serial)
{
__adb_transport = type;
__adb_serial = serial;
@@ -80,36 +80,6 @@
__adb_server_name = hostname;
}
-int adb_get_emulator_console_port() {
- if (__adb_serial) {
- // The user specified a serial number; is it an emulator?
- int port;
- return (sscanf(__adb_serial, "emulator-%d", &port) == 1) ? port : -1;
- }
-
- // No specific device was given, so get the list of connected
- // devices and search for emulators. If there's one, we'll
- // take it. If there are more than one, that's an error.
- std::string devices;
- std::string error;
- if (!adb_query("host:devices", &devices, &error)) {
- printf("no emulator connected: %s\n", error.c_str());
- return -1;
- }
-
- int port;
- size_t emulator_count = 0;
- for (auto& device : android::base::Split(devices, "\n")) {
- if (sscanf(device.c_str(), "emulator-%d", &port) == 1) {
- if (++emulator_count > 1) {
- return -2;
- }
- }
- }
- if (emulator_count == 0) return -1;
- return port;
-}
-
static int switch_socket_transport(int fd, std::string* error) {
std::string service;
if (__adb_serial) {
@@ -175,8 +145,8 @@
int _adb_connect(const std::string& service, std::string* error) {
D("_adb_connect: %s\n", service.c_str());
if (service.empty() || service.size() > 1024) {
- *error = android::base::StringPrintf("bad service name length (%d)",
- static_cast<int>(service.size()));
+ *error = android::base::StringPrintf("bad service name length (%zd)",
+ service.size());
return -1;
}
@@ -286,19 +256,21 @@
}
-int adb_command(const std::string& service, std::string* error) {
- int fd = adb_connect(service, error);
+bool adb_command(const std::string& service) {
+ std::string error;
+ int fd = adb_connect(service, &error);
if (fd < 0) {
- fprintf(stderr, "error: %s\n", error->c_str());
- return -1;
+ fprintf(stderr, "error: %s\n", error.c_str());
+ return false;
}
- if (!adb_status(fd, error)) {
+ if (!adb_status(fd, &error)) {
+ fprintf(stderr, "error: %s\n", error.c_str());
adb_close(fd);
- return -1;
+ return false;
}
- return 0;
+ return true;
}
bool adb_query(const std::string& service, std::string* result, std::string* error) {
diff --git a/adb/adb_client.h b/adb/adb_client.h
index 96416f5..5de0638 100644
--- a/adb/adb_client.h
+++ b/adb/adb_client.h
@@ -1,3 +1,19 @@
+/*
+ * 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_CLIENT_H_
#define _ADB_CLIENT_H_
@@ -5,49 +21,35 @@
#include <string>
-/* connect to adb, connect to the named service, and return
-** a valid fd for interacting with that service upon success
-** or a negative number on failure
-*/
+// Connect to adb, connect to the named service, and return a valid fd for
+// interacting with that service upon success or a negative number on failure.
int adb_connect(const std::string& service, std::string* error);
int _adb_connect(const std::string& service, std::string* error);
-/* connect to adb, connect to the named service, return 0 if
-** the connection succeeded AND the service returned OKAY
-*/
-int adb_command(const std::string& service, std::string* error);
+// Connect to adb, connect to the named service, returns true if the connection
+// succeeded AND the service returned OKAY. Outputs any returned error otherwise.
+bool adb_command(const std::string& service);
// Connects to the named adb service and fills 'result' with the response.
// Returns true on success; returns false and fills 'error' on failure.
bool adb_query(const std::string& service, std::string* result, std::string* error);
-/* Set the preferred transport to connect to.
-*/
-void adb_set_transport(transport_type type, const char* serial);
+// Set the preferred transport to connect to.
+void adb_set_transport(TransportType type, const char* serial);
-/* Set TCP specifics of the transport to use
-*/
+// Set TCP specifics of the transport to use.
void adb_set_tcp_specifics(int server_port);
-/* Set TCP Hostname of the transport to use
-*/
+// Set TCP Hostname of the transport to use.
void adb_set_tcp_name(const char* hostname);
-/* Return the console port of the currently connected emulator (if any)
- * of -1 if there is no emulator, and -2 if there is more than one.
- * assumes adb_set_transport() was alled previously...
- */
-int adb_get_emulator_console_port(void);
+// Send commands to the current emulator instance. Will fail if there is not
+// exactly one emulator connected (or if you use -s <serial> with a <serial>
+// that does not designate an emulator).
+int adb_send_emulator_command(int argc, const char** argv, const char* serial);
-/* send commands to the current emulator instance. will fail if there
- * is zero, or more than one emulator connected (or if you use -s <serial>
- * with a <serial> that does not designate an emulator)
- */
-int adb_send_emulator_command(int argc, const char** argv);
-
-// Reads a standard adb status response (OKAY|FAIL) and
-// returns true in the event of OKAY, false in the event of FAIL
-// or protocol error.
+// Reads a standard adb status response (OKAY|FAIL) and returns true in the
+// event of OKAY, false in the event of FAIL or protocol error.
bool adb_status(int fd, std::string* error);
#endif
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index 3fc4719..a335eec 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -26,13 +26,12 @@
int gListenAll = 0; /* Not static because it is used in commandline.c. */
-alistener listener_list = {
+static alistener listener_list = {
.next = &listener_list,
.prev = &listener_list,
};
-void ss_listener_event_func(int _fd, unsigned ev, void *_l)
-{
+static void ss_listener_event_func(int _fd, unsigned ev, void *_l) {
asocket *s;
if(ev & FDE_READ) {
@@ -56,7 +55,7 @@
}
}
-void listener_event_func(int _fd, unsigned ev, void* _l)
+static void listener_event_func(int _fd, unsigned ev, void* _l)
{
alistener* listener = reinterpret_cast<alistener*>(_l);
asocket *s;
@@ -106,38 +105,27 @@
free(l);
}
-void listener_disconnect(void* listener, atransport* t)
-{
+static void listener_disconnect(void* listener, atransport* t) {
free_listener(reinterpret_cast<alistener*>(listener));
}
-int local_name_to_fd(const char *name)
-{
- int port;
-
- if(!strncmp("tcp:", name, 4)){
- int ret;
- port = atoi(name + 4);
-
+static int local_name_to_fd(const char* name) {
+ if (!strncmp("tcp:", name, 4)) {
+ int port = atoi(name + 4);
if (gListenAll > 0) {
- ret = socket_inaddr_any_server(port, SOCK_STREAM);
+ return socket_inaddr_any_server(port, SOCK_STREAM);
} else {
- ret = socket_loopback_server(port, SOCK_STREAM);
+ return 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);
+ // It's nonsensical 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
@@ -160,8 +148,7 @@
return result;
}
-install_status_t remove_listener(const char *local_name, atransport* transport)
-{
+InstallStatus remove_listener(const char *local_name, atransport* transport) {
alistener *l;
for (l = listener_list.next; l != &listener_list; l = l->next) {
@@ -185,7 +172,7 @@
}
}
-install_status_t install_listener(const std::string& local_name,
+InstallStatus install_listener(const std::string& local_name,
const char *connect_to,
atransport* transport,
int no_rebind)
diff --git a/adb/adb_listeners.h b/adb/adb_listeners.h
index 67168ae..67deb21 100644
--- a/adb/adb_listeners.h
+++ b/adb/adb_listeners.h
@@ -22,7 +22,7 @@
#include <string>
// error/status codes for install_listener.
-enum install_status_t {
+enum InstallStatus {
INSTALL_STATUS_OK = 0,
INSTALL_STATUS_INTERNAL_ERROR = -1,
INSTALL_STATUS_CANNOT_BIND = -2,
@@ -30,20 +30,14 @@
INSTALL_STATUS_LISTENER_NOT_FOUND = -4,
};
-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 std::string& local_name,
- const char* connect_to,
- atransport* transport,
- int no_rebind);
+InstallStatus install_listener(const std::string& local_name,
+ const char* connect_to,
+ atransport* transport,
+ int no_rebind);
std::string format_listeners();
-install_status_t remove_listener(const char* local_name, atransport* transport);
+InstallStatus remove_listener(const char* local_name, atransport* transport);
void remove_all_listeners(void);
#endif /* __ADB_LISTENERS_H */
diff --git a/adb/adb_main.cpp b/adb/adb_main.cpp
deleted file mode 100644
index 3f88d13..0000000
--- a/adb/adb_main.cpp
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * 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 "sysdeps.h"
-
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "adb.h"
-#include "adb_auth.h"
-#include "adb_listeners.h"
-#include "transport.h"
-
-#include <base/stringprintf.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 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;
- }
-
- // 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 */
-}
-#endif /* ADB_HOST */
-
-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();
-
- std::string local_name = android::base::StringPrintf("tcp:%d", server_port);
- if (install_listener(local_name, "*smartsocket*", NULL, 0)) {
- exit(1);
- }
-#else
- // We need to call this even if auth isn't enabled because the file
- // descriptor will always be open.
- adbd_cloexec_auth_socket();
-
- property_get("ro.adb.secure", value, "0");
- auth_enabled = !strcmp(value, "1");
- if (auth_enabled)
- adbd_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 {
- if ((root_seclabel != NULL) && (is_selinux_enabled() > 0)) {
- // b/12587913: fix setcon to allow const pointers
- if (setcon((char *)root_seclabel) < 0) {
- exit(1);
- }
- }
- std::string local_name = android::base::StringPrintf("tcp:%d", 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;
-}
-
-#if !ADB_HOST
-void close_stdin() {
- int fd = unix_open("/dev/null", O_RDONLY);
- if (fd == -1) {
- perror("failed to open /dev/null, stdin will remain open");
- return;
- }
- dup2(fd, 0);
- adb_close(fd);
-}
-#endif
-
-// TODO(danalbert): Split this file up into adb_main.cpp and adbd_main.cpp.
-int main(int argc, char **argv) {
-#if ADB_HOST
- // adb client/server
- adb_sysdeps_init();
- adb_trace_init();
- D("Handling commandline()\n");
- return adb_commandline(argc - 1, const_cast<const char**>(argv + 1));
-#else
- // adbd
- while (true) {
- static struct option opts[] = {
- {"root_seclabel", required_argument, nullptr, 's'},
- {"device_banner", required_argument, nullptr, 'b'},
- {"version", no_argument, nullptr, 'v'},
- };
-
- int option_index = 0;
- int 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;
- case 'v':
- printf("Android Debug Bridge Daemon version %d.%d.%d %s\n",
- ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION,
- ADB_REVISION);
- return 0;
- default:
- break;
- }
- }
-
- close_stdin();
-
- adb_trace_init();
-
- /* If adbd runs inside the emulator this will enable adb tracing via
- * adb-debug qemud service in the emulator. */
- adb_qemu_trace_init();
-
- 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 63d4151..dbc7ec8 100644
--- a/adb/adb_trace.h
+++ b/adb/adb_trace.h
@@ -57,9 +57,9 @@
#define DQ(...) ((void)0)
#endif /* !ADB_HOST */
-extern int adb_trace_mask;
-extern unsigned char adb_trace_output_count;
-void adb_trace_init(void);
+extern int adb_trace_mask;
+extern unsigned char adb_trace_output_count;
+void adb_trace_init(char**);
# define ADB_TRACING ((adb_trace_mask & (1 << TRACE_TAG)) != 0)
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
new file mode 100644
index 0000000..0cd6670
--- /dev/null
+++ b/adb/client/main.cpp
@@ -0,0 +1,182 @@
+/*
+ * 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 "sysdeps.h"
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+// We only build the affinity WAR code for Linux.
+#if defined(__linux__)
+#include <sched.h>
+#endif
+
+#include "base/file.h"
+#include "base/logging.h"
+#include "base/stringprintf.h"
+
+#include "adb.h"
+#include "adb_auth.h"
+#include "adb_listeners.h"
+#include "transport.h"
+
+#if defined(WORKAROUND_BUG6558362) && defined(__linux__)
+static const bool kWorkaroundBug6558362 = true;
+#else
+static const bool kWorkaroundBug6558362 = false;
+#endif
+
+static void adb_workaround_affinity(void) {
+#if defined(__linux__)
+ const char affinity_env[] = "ADB_CPU_AFFINITY_BUG6558362";
+ const char* cpunum_str = getenv(affinity_env);
+ if (cpunum_str == nullptr || *cpunum_str == '\0') {
+ return;
+ }
+
+ char* strtol_res;
+ int 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_env);
+ }
+
+ cpu_set_t cpu_set;
+ 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]);
+#else
+ // No workaround was ever implemented for the other platforms.
+#endif
+}
+
+#if defined(_WIN32)
+static const char kNullFileName[] = "NUL";
+
+static BOOL WINAPI ctrlc_handler(DWORD type) {
+ exit(STATUS_CONTROL_C_EXIT);
+ return TRUE;
+}
+
+static std::string GetLogFilePath() {
+ const char log_name[] = "adb.log";
+ char temp_path[MAX_PATH - sizeof(log_name) + 1];
+
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364992%28v=vs.85%29.aspx
+ DWORD nchars = GetTempPath(sizeof(temp_path), temp_path);
+ CHECK_LE(nchars, sizeof(temp_path));
+ if (nchars == 0) {
+ // TODO(danalbert): Log the error message from FormatError().
+ // Windows unfortunately has two errnos, errno and GetLastError(), so
+ // I'm not sure what to do about PLOG here. Probably better to just
+ // ignore it and add a simplified version of FormatError() for use in
+ // log messages.
+ LOG(ERROR) << "Error creating log file";
+ }
+
+ return std::string(temp_path) + log_name;
+}
+#else
+static const char kNullFileName[] = "/dev/null";
+
+static std::string GetLogFilePath() {
+ return std::string("/tmp/adb.log");
+}
+#endif
+
+static void close_stdin() {
+ int fd = unix_open(kNullFileName, O_RDONLY);
+ CHECK_NE(fd, -1);
+ dup2(fd, STDIN_FILENO);
+ adb_close(fd);
+}
+
+static void setup_daemon_logging(void) {
+ int fd = unix_open(GetLogFilePath().c_str(), O_WRONLY | O_CREAT | O_APPEND,
+ 0640);
+ if (fd == -1) {
+ fd = unix_open(kNullFileName, O_WRONLY);
+ }
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
+ adb_close(fd);
+ fprintf(stderr, "--- adb starting (pid %d) ---\n", getpid());
+}
+
+int adb_main(int is_daemon, int server_port) {
+ HOST = 1;
+
+#if defined(_WIN32)
+ SetConsoleCtrlHandler(ctrlc_handler, TRUE);
+#else
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
+ init_transport_registration();
+
+ if (kWorkaroundBug6558362 && is_daemon) {
+ adb_workaround_affinity();
+ }
+
+ usb_init();
+ local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
+ adb_auth_init();
+
+ std::string local_name = android::base::StringPrintf("tcp:%d", server_port);
+ if (install_listener(local_name, "*smartsocket*", nullptr, 0)) {
+ LOG(FATAL) << "Could not install *smartsocket* listener";
+ }
+
+ if (is_daemon) {
+ // Inform our parent that we are up and running.
+ // TODO(danalbert): Can't use SendOkay because we're sending "OK\n", not
+ // "OKAY".
+ // TODO(danalbert): Why do we use stdout for Windows?
+#if defined(_WIN32)
+ int reply_fd = STDOUT_FILENO;
+ // Change stdout mode to binary so \n => \r\n translation does not
+ // occur. In a moment stdout will be reopened to the daemon log file
+ // anyway.
+ _setmode(reply_fd, _O_BINARY);
+#else
+ int reply_fd = STDERR_FILENO;
+#endif
+ android::base::WriteStringToFd("OK\n", reply_fd);
+ close_stdin();
+ setup_daemon_logging();
+ }
+
+ D("Event loop starting\n");
+ fdevent_loop();
+
+ return 0;
+}
+
+int main(int argc, char** argv) {
+ adb_sysdeps_init();
+ adb_trace_init(argv);
+ D("Handling commandline()\n");
+ return adb_commandline(argc - 1, const_cast<const char**>(argv + 1));
+}
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index fd9953c..17c4432 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -47,9 +47,9 @@
#include "adb_utils.h"
#include "file_sync_service.h"
-static int install_app(transport_type t, const char* serial, int argc, const char** argv);
-static int install_multiple_app(transport_type t, const char* serial, int argc, const char** argv);
-static int uninstall_app(transport_type t, const char* serial, int argc, const char** argv);
+static int install_app(TransportType t, const char* serial, int argc, const char** argv);
+static int install_multiple_app(TransportType t, const char* serial, int argc, const char** argv);
+static int uninstall_app(TransportType t, const char* serial, int argc, const char** argv);
static std::string gProductOutPath;
extern int gListenAll;
@@ -404,7 +404,6 @@
}
static int interactive_shell() {
- adb_thread_t thr;
int fdi;
std::string error;
@@ -425,14 +424,15 @@
fds[1] = fdi;
stdin_raw_init(fdi);
- adb_thread_create(&thr, stdin_read_thread, fds);
+
+ adb_thread_create(stdin_read_thread, fds);
read_and_dump(fd);
stdin_raw_restore(fdi);
return 0;
}
-static std::string format_host_command(const char* command, transport_type type, const char* serial) {
+static std::string format_host_command(const char* command, TransportType type, const char* serial) {
if (serial) {
return android::base::StringPrintf("host-serial:%s:%s", serial, command);
}
@@ -674,7 +674,7 @@
#endif /* !defined(_WIN32) */
}
-static bool wait_for_device(const char* service, transport_type t, const char* serial) {
+static bool wait_for_device(const char* service, TransportType t, const char* serial) {
// Was the caller vague about what they'd like us to wait for?
// If so, check they weren't more specific in their choice of transport type.
if (strcmp(service, "wait-for-device") == 0) {
@@ -688,17 +688,10 @@
}
std::string cmd = format_host_command(service, t, serial);
- std::string error;
- if (adb_command(cmd, &error)) {
- D("failure: %s *\n", error.c_str());
- fprintf(stderr,"error: %s\n", error.c_str());
- return false;
- }
-
- return true;
+ return adb_command(cmd);
}
-static int send_shell_command(transport_type transport_type, const char* serial,
+static int send_shell_command(TransportType transport_type, const char* serial,
const std::string& command) {
int fd;
while (true) {
@@ -720,7 +713,7 @@
return rc;
}
-static int logcat(transport_type transport, const char* serial, int argc, const char** argv) {
+static int logcat(TransportType transport, const char* serial, int argc, const char** argv) {
char* log_tags = getenv("ANDROID_LOG_TAGS");
std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
@@ -953,11 +946,8 @@
int no_daemon = 0;
int is_daemon = 0;
int is_server = 0;
- int persist = 0;
int r;
- transport_type ttype = kTransportAny;
- const char* serial = NULL;
- const char* server_port_str = NULL;
+ TransportType transport_type = kTransportAny;
// If defined, this should be an absolute path to
// the directory containing all of the various system images
@@ -970,10 +960,10 @@
}
// TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
- serial = getenv("ANDROID_SERIAL");
+ const char* serial = getenv("ANDROID_SERIAL");
/* Validate and assign the server port */
- server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
+ const char* server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
int server_port = DEFAULT_ADB_PORT;
if (server_port_str && strlen(server_port_str) > 0) {
server_port = (int) strtol(server_port_str, NULL, 0);
@@ -994,8 +984,6 @@
} else if (!strcmp(argv[0], "fork-server")) {
/* this is a special flag used only when the ADB client launches the ADB Server */
is_daemon = 1;
- } else if (!strcmp(argv[0],"persist")) {
- persist = 1;
} else if (!strncmp(argv[0], "-p", 2)) {
const char *product = NULL;
if (argv[0][2] == '\0') {
@@ -1021,9 +1009,9 @@
argv++;
}
} else if (!strcmp(argv[0],"-d")) {
- ttype = kTransportUsb;
+ transport_type = kTransportUsb;
} else if (!strcmp(argv[0],"-e")) {
- ttype = kTransportLocal;
+ transport_type = kTransportLocal;
} else if (!strcmp(argv[0],"-a")) {
gListenAll = 1;
} else if (!strncmp(argv[0], "-H", 2)) {
@@ -1068,7 +1056,7 @@
argv++;
}
- adb_set_transport(ttype, serial);
+ adb_set_transport(transport_type, serial);
adb_set_tcp_specifics(server_port);
if (is_server) {
@@ -1091,7 +1079,7 @@
if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
const char* service = argv[0];
- if (!wait_for_device(service, ttype, serial)) {
+ if (!wait_for_device(service, transport_type, serial)) {
return 1;
}
@@ -1142,7 +1130,7 @@
return adb_query_command(query);
}
else if (!strcmp(argv[0], "emu")) {
- return adb_send_emulator_command(argc, argv);
+ return adb_send_emulator_command(argc, argv, serial);
}
else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
char h = (argv[0][0] == 'h');
@@ -1187,18 +1175,12 @@
r = -1;
}
- if (persist) {
- fprintf(stderr,"\n- waiting for device -\n");
- adb_sleep_ms(1000);
- wait_for_device("wait-for-device", ttype, serial);
- } else {
- if (h) {
- printf("\x1b[0m");
- fflush(stdout);
- }
- D("interactive shell loop. return r=%d\n", r);
- return r;
+ if (h) {
+ printf("\x1b[0m");
+ fflush(stdout);
}
+ D("interactive shell loop. return r=%d\n", r);
+ return r;
}
}
else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
@@ -1266,92 +1248,52 @@
}
else if (!strcmp(argv[0], "bugreport")) {
if (argc != 1) return usage();
- return send_shell_command(ttype, serial, "shell:bugreport");
+ return send_shell_command(transport_type, serial, "shell:bugreport");
}
- /* adb_command() wrapper commands */
else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
- std::string cmd;
- char host_prefix[64];
- char reverse = (char) !strcmp(argv[0], "reverse");
- char remove = 0;
- char remove_all = 0;
- char list = 0;
- char no_rebind = 0;
-
- // Parse options here.
- while (argc > 1 && argv[1][0] == '-') {
- if (!strcmp(argv[1], "--list"))
- list = 1;
- else if (!strcmp(argv[1], "--remove"))
- remove = 1;
- else if (!strcmp(argv[1], "--remove-all"))
- remove_all = 1;
- else if (!strcmp(argv[1], "--no-rebind"))
- no_rebind = 1;
- else {
- return usage();
- }
- argc--;
- argv++;
- }
-
- // Ensure we can only use one option at a time.
- if (list + remove + remove_all + no_rebind > 1) {
- return usage();
- }
+ bool reverse = !strcmp(argv[0], "reverse");
+ ++argv;
+ --argc;
+ if (argc < 1) return usage();
// Determine the <host-prefix> for this command.
+ std::string host_prefix;
if (reverse) {
- snprintf(host_prefix, sizeof host_prefix, "reverse");
+ host_prefix = "reverse";
} else {
if (serial) {
- snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
- serial);
- } else if (ttype == kTransportUsb) {
- snprintf(host_prefix, sizeof host_prefix, "host-usb");
- } else if (ttype == kTransportLocal) {
- snprintf(host_prefix, sizeof host_prefix, "host-local");
+ host_prefix = android::base::StringPrintf("host-serial:%s", serial);
+ } else if (transport_type == kTransportUsb) {
+ host_prefix = "host-usb";
+ } else if (transport_type == kTransportLocal) {
+ host_prefix = "host-local";
} else {
- snprintf(host_prefix, sizeof host_prefix, "host");
+ host_prefix = "host";
}
}
- // Implement forward --list
- if (list) {
- if (argc != 1) {
- return usage();
- }
-
- std::string query = android::base::StringPrintf("%s:list-forward", host_prefix);
- return adb_query_command(query);
- }
-
- // Implement forward --remove-all
- else if (remove_all) {
+ std::string cmd;
+ if (strcmp(argv[0], "--list") == 0) {
if (argc != 1) return usage();
- cmd = android::base::StringPrintf("%s:killforward-all", host_prefix);
- }
-
- // Implement forward --remove <local>
- else if (remove) {
+ return adb_query_command(host_prefix + ":list-forward");
+ } else if (strcmp(argv[0], "--remove-all") == 0) {
+ if (argc != 1) return usage();
+ cmd = host_prefix + ":killforward-all";
+ } else if (strcmp(argv[0], "--remove") == 0) {
+ // forward --remove <local>
if (argc != 2) return usage();
- cmd = android::base::StringPrintf("%s:killforward:%s", host_prefix, argv[1]);
- }
- // Or implement one of:
- // forward <local> <remote>
- // forward --no-rebind <local> <remote>
- else {
+ cmd = host_prefix + ":killforward:" + argv[1];
+ } else if (strcmp(argv[0], "--no-rebind") == 0) {
+ // forward --no-rebind <local> <remote>
if (argc != 3) return usage();
- const char* command = no_rebind ? "forward:norebind" : "forward";
- cmd = android::base::StringPrintf("%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
+ cmd = host_prefix + ":forward:norebind:" + argv[1] + ";" + argv[2];
+ } else {
+ // forward <local> <remote>
+ if (argc != 2) return usage();
+ cmd = host_prefix + ":forward:" + argv[0] + ";" + argv[1];
}
- std::string error;
- if (adb_command(cmd, &error)) {
- fprintf(stderr, "error: %s\n", error.c_str());
- return 1;
- }
- return 0;
+ return adb_command(cmd) ? 0 : 1;
}
/* do_sync_*() commands */
else if (!strcmp(argv[0], "ls")) {
@@ -1386,15 +1328,15 @@
}
else if (!strcmp(argv[0], "install")) {
if (argc < 2) return usage();
- return install_app(ttype, serial, argc, argv);
+ return install_app(transport_type, serial, argc, argv);
}
else if (!strcmp(argv[0], "install-multiple")) {
if (argc < 2) return usage();
- return install_multiple_app(ttype, serial, argc, argv);
+ return install_multiple_app(transport_type, serial, argc, argv);
}
else if (!strcmp(argv[0], "uninstall")) {
if (argc < 2) return usage();
- return uninstall_app(ttype, serial, argc, argv);
+ return uninstall_app(transport_type, serial, argc, argv);
}
else if (!strcmp(argv[0], "sync")) {
std::string src;
@@ -1446,11 +1388,11 @@
!strcmp(argv[0],"get-serialno") ||
!strcmp(argv[0],"get-devpath"))
{
- return adb_query_command(format_host_command(argv[0], ttype, serial));
+ return adb_query_command(format_host_command(argv[0], transport_type, serial));
}
/* other commands */
else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
- return logcat(ttype, serial, argc, argv);
+ return logcat(transport_type, serial, argc, argv);
}
else if (!strcmp(argv[0],"ppp")) {
return ppp(argc, argv);
@@ -1486,9 +1428,7 @@
return 1;
}
-static int pm_command(transport_type transport, const char* serial,
- int argc, const char** argv)
-{
+static int pm_command(TransportType transport, const char* serial, int argc, const char** argv) {
std::string cmd = "shell:pm";
while (argc-- > 0) {
@@ -1498,9 +1438,7 @@
return send_shell_command(transport, serial, cmd);
}
-static int uninstall_app(transport_type transport, const char* serial, int argc,
- const char** argv)
-{
+static int uninstall_app(TransportType transport, const char* serial, int argc, const char** argv) {
/* if the user choose the -k option, we refuse to do it until devices are
out with the option to uninstall the remaining data somehow (adb/ui) */
if (argc == 3 && strcmp(argv[1], "-k") == 0)
@@ -1517,8 +1455,7 @@
return pm_command(transport, serial, argc, argv);
}
-static int delete_file(transport_type transport, const char* serial, char* filename)
-{
+static int delete_file(TransportType transport, const char* serial, char* filename) {
std::string cmd = "shell:rm -f " + escape_arg(filename);
return send_shell_command(transport, serial, cmd);
}
@@ -1534,9 +1471,7 @@
}
}
-static int install_app(transport_type transport, const char* serial, int argc,
- const char** argv)
-{
+static int install_app(TransportType transport, const char* serial, int argc, const char** argv) {
static const char *const DATA_DEST = "/data/local/tmp/%s";
static const char *const SD_DEST = "/sdcard/tmp/%s";
const char* where = DATA_DEST;
@@ -1588,7 +1523,7 @@
return err;
}
-static int install_multiple_app(transport_type transport, const char* serial, int argc,
+static int install_multiple_app(TransportType transport, const char* serial, int argc,
const char** argv)
{
int i;
@@ -1619,11 +1554,7 @@
return 1;
}
-#if defined(_WIN32) // Remove when we're using clang for Win32.
- std::string cmd = android::base::StringPrintf("exec:pm install-create -S %u", (unsigned) total_size);
-#else
std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size);
-#endif
for (i = 1; i < first_apk; i++) {
cmd += " " + escape_arg(argv[i]);
}
@@ -1664,15 +1595,9 @@
goto finalize_session;
}
-#if defined(_WIN32) // Remove when we're using clang for Win32.
- std::string cmd = android::base::StringPrintf(
- "exec:pm install-write -S %u %d %d_%s -",
- (unsigned) sb.st_size, session_id, i, get_basename(file));
-#else
std::string cmd = android::base::StringPrintf(
"exec:pm install-write -S %" PRIu64 " %d %d_%s -",
static_cast<uint64_t>(sb.st_size), session_id, i, get_basename(file));
-#endif
int localFd = adb_open(file, O_RDONLY);
if (localFd < 0) {
diff --git a/adb/console.cpp b/adb/console.cpp
index 452ee41..0707960 100644
--- a/adb/console.cpp
+++ b/adb/console.cpp
@@ -1,44 +1,115 @@
+/*
+ * 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 "sysdeps.h"
-#include "adb.h"
-#include "adb_client.h"
+
#include <stdio.h>
-static int connect_to_console(void)
-{
- int fd, port;
+#include "base/file.h"
+#include "base/logging.h"
+#include "base/strings.h"
- port = adb_get_emulator_console_port();
- if (port < 0) {
- if (port == -2)
- fprintf(stderr, "error: more than one emulator detected. use -s option\n");
- else
- fprintf(stderr, "error: no emulator detected\n");
+#include "adb.h"
+#include "adb_client.h"
+
+// Return the console port of the currently connected emulator (if any) or -1 if
+// there is no emulator, and -2 if there is more than one.
+static int adb_get_emulator_console_port(const char* serial) {
+ if (serial) {
+ // The user specified a serial number; is it an emulator?
+ int port;
+ return (sscanf(serial, "emulator-%d", &port) == 1) ? port : -1;
+ }
+
+ // No specific device was given, so get the list of connected devices and
+ // search for emulators. If there's one, we'll take it. If there are more
+ // than one, that's an error.
+ std::string devices;
+ std::string error;
+ if (!adb_query("host:devices", &devices, &error)) {
+ fprintf(stderr, "error: no emulator connected: %s\n", error.c_str());
return -1;
}
- fd = socket_loopback_client( port, SOCK_STREAM );
- if (fd < 0) {
+
+ int port;
+ size_t emulator_count = 0;
+ for (const auto& device : android::base::Split(devices, "\n")) {
+ if (sscanf(device.c_str(), "emulator-%d", &port) == 1) {
+ if (++emulator_count > 1) {
+ fprintf(
+ stderr, "error: more than one emulator detected; use -s\n");
+ return -1;
+ }
+ }
+ }
+
+ if (emulator_count == 0) {
+ fprintf(stderr, "error: no emulator detected\n");
+ return -1;
+ }
+
+ return port;
+}
+
+static int connect_to_console(const char* serial) {
+ int port = adb_get_emulator_console_port(serial);
+ if (port == -1) {
+ return -1;
+ }
+
+ int fd = socket_loopback_client(port, SOCK_STREAM);
+ if (fd == -1) {
fprintf(stderr, "error: could not connect to TCP port %d\n", port);
return -1;
}
- return fd;
+ return fd;
}
-
-int adb_send_emulator_command(int argc, const char** argv)
-{
- int fd, nn;
-
- fd = connect_to_console();
- if (fd < 0)
+int adb_send_emulator_command(int argc, const char** argv, const char* serial) {
+ int fd = connect_to_console(serial);
+ if (fd == -1) {
return 1;
-
-#define QUIT "quit\n"
-
- for (nn = 1; nn < argc; nn++) {
- adb_write( fd, argv[nn], strlen(argv[nn]) );
- adb_write( fd, (nn == argc-1) ? "\n" : " ", 1 );
}
- adb_write( fd, QUIT, sizeof(QUIT)-1 );
+
+ for (int i = 1; i < argc; i++) {
+ adb_write(fd, argv[i], strlen(argv[i]));
+ adb_write(fd, i == argc - 1 ? "\n" : " ", 1);
+ }
+
+ const char disconnect_command[] = "quit\n";
+ if (adb_write(fd, disconnect_command, sizeof(disconnect_command) - 1) == -1) {
+ LOG(FATAL) << "Could not finalize emulator command";
+ }
+
+ // Drain output that the emulator console has sent us to prevent a problem
+ // on Windows where if adb closes the socket without reading all the data,
+ // the emulator's next call to recv() will have an ECONNABORTED error,
+ // preventing the emulator from reading the command that adb has sent.
+ // https://code.google.com/p/android/issues/detail?id=21021
+ int result;
+ do {
+ char buf[BUFSIZ];
+ result = adb_read(fd, buf, sizeof(buf));
+ // Keep reading until zero bytes (EOF) or an error. If 'adb emu kill'
+ // is executed, the emulator calls exit() which causes adb to get
+ // ECONNRESET. Any other emu command is followed by the quit command
+ // that we sent above, and that causes the emulator to close the socket
+ // which should cause zero bytes (EOF) to be returned.
+ } while (result > 0);
+
adb_close(fd);
return 0;
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
new file mode 100644
index 0000000..78ab3f6
--- /dev/null
+++ b/adb/daemon/main.cpp
@@ -0,0 +1,274 @@
+/*
+ * 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 "sysdeps.h"
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <sys/prctl.h>
+
+#include "base/logging.h"
+#include "base/stringprintf.h"
+#include "cutils/properties.h"
+#include "private/android_filesystem_config.h"
+#include "selinux/selinux.h"
+
+#include "adb.h"
+#include "adb_auth.h"
+#include "adb_listeners.h"
+#include "transport.h"
+#include "qemu_tracing.h"
+
+static const char* root_seclabel = nullptr;
+
+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
+ for (int 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)) {
+ PLOG(FATAL) << "Could not drop capabilities";
+ }
+ }
+}
+
+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;
+ }
+
+ // 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
+}
+
+int adbd_main(int server_port) {
+ umask(0);
+
+ signal(SIGPIPE, SIG_IGN);
+
+ init_transport_registration();
+
+ // We need to call this even if auth isn't enabled because the file
+ // descriptor will always be open.
+ adbd_cloexec_auth_socket();
+
+ auth_enabled = property_get_bool("ro.adb.secure", 0) != 0;
+ if (auth_enabled) {
+ adbd_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 (adb_external_storage != nullptr) {
+ 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) {
+ PLOG(FATAL) << "Could not set supplental groups";
+ }
+
+ /* 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) {
+ PLOG(FATAL) << "Could not setgid";
+ }
+ if (setuid(AID_SHELL) != 0) {
+ PLOG(FATAL) << "Could not setuid";
+ }
+
+ D("Local port disabled\n");
+ } else {
+ if ((root_seclabel != nullptr) && (is_selinux_enabled() > 0)) {
+ if (setcon(root_seclabel) < 0) {
+ LOG(FATAL) << "Could not set selinux context";
+ }
+ }
+ std::string local_name =
+ android::base::StringPrintf("tcp:%d", server_port);
+ if (install_listener(local_name, "*smartsocket*", nullptr, 0)) {
+ LOG(FATAL) << "Could not install *smartsocket* listener";
+ }
+ }
+
+ bool is_usb = false;
+ if (access(USB_ADB_PATH, F_OK) == 0 || access(USB_FFS_ADB_EP0, F_OK) == 0) {
+ // Listen on USB.
+ usb_init();
+ is_usb = true;
+ }
+
+ // 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.
+ char prop_port[PROPERTY_VALUE_MAX];
+ property_get("service.adb.tcp.port", prop_port, "");
+ if (prop_port[0] == '\0') {
+ property_get("persist.adb.tcp.port", prop_port, "");
+ }
+
+ int port;
+ if (sscanf(prop_port, "%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 (!is_usb) {
+ // Listen on default port.
+ local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
+ }
+
+ D("adbd_main(): pre init_jdwp()\n");
+ init_jdwp();
+ D("adbd_main(): post init_jdwp()\n");
+
+ D("Event loop starting\n");
+ fdevent_loop();
+
+ return 0;
+}
+
+static void close_stdin() {
+ int fd = unix_open("/dev/null", O_RDONLY);
+ if (fd == -1) {
+ perror("failed to open /dev/null, stdin will remain open");
+ return;
+ }
+ dup2(fd, STDIN_FILENO);
+ unix_close(fd);
+}
+
+int main(int argc, char** argv) {
+ while (true) {
+ static struct option opts[] = {
+ {"root_seclabel", required_argument, nullptr, 's'},
+ {"device_banner", required_argument, nullptr, 'b'},
+ {"version", no_argument, nullptr, 'v'},
+ };
+
+ int option_index = 0;
+ int 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;
+ case 'v':
+ printf("Android Debug Bridge Daemon version %d.%d.%d %s\n",
+ ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION,
+ ADB_REVISION);
+ return 0;
+ default:
+ // getopt already prints "adbd: invalid option -- %c" for us.
+ return 1;
+ }
+ }
+
+ close_stdin();
+
+ adb_trace_init(argv);
+
+ /* If adbd runs inside the emulator this will enable adb tracing via
+ * adb-debug qemud service in the emulator. */
+ adb_qemu_trace_init();
+
+ D("Handling main()\n");
+ return adbd_main(DEFAULT_ADB_PORT);
+}
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index aded301..1dc711ae 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -16,6 +16,7 @@
#include <dirent.h>
#include <errno.h>
+#include <inttypes.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
@@ -63,13 +64,12 @@
total_bytes, (t / 1000000LL), (t % 1000000LL) / 1000LL);
}
-static const char* transfer_progress_format = "\rTransferring: %llu/%llu (%d%%)";
-
-static void print_transfer_progress(unsigned long long bytes_current,
- unsigned long long bytes_total) {
+static void print_transfer_progress(uint64_t bytes_current,
+ uint64_t bytes_total) {
if (bytes_total == 0) return;
- fprintf(stderr, transfer_progress_format, bytes_current, bytes_total,
+ fprintf(stderr, "\rTransferring: %" PRIu64 "/%" PRIu64 " (%d%%)",
+ bytes_current, bytes_total,
(int) (bytes_current * 100 / bytes_total));
if (bytes_current == bytes_total) {
@@ -79,8 +79,7 @@
fflush(stderr);
}
-void sync_quit(int fd)
-{
+static void sync_quit(int fd) {
syncmsg msg;
msg.req.id = ID_QUIT;
@@ -91,8 +90,7 @@
typedef void (*sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char *name, void *cookie);
-int sync_ls(int fd, const char *path, sync_ls_cb func, void *cookie)
-{
+static int sync_ls(int fd, const char* path, sync_ls_cb func, void* cookie) {
syncmsg msg;
char buf[257];
int len;
@@ -138,9 +136,7 @@
static syncsendbuf send_buffer;
-int sync_readtime(int fd, const char *path, unsigned int *timestamp,
- unsigned int *mode)
-{
+static int sync_readtime(int fd, const char* path, unsigned int* timestamp, unsigned int* mode) {
syncmsg msg;
int len = strlen(path);
@@ -199,8 +195,7 @@
return 0;
}
-int sync_readmode(int fd, const char *path, unsigned *mode)
-{
+static int sync_readmode(int fd, const char* path, unsigned* mode) {
syncmsg msg;
int len = strlen(path);
@@ -419,8 +414,7 @@
return 0;
}
-int sync_recv(int fd, const char *rpath, const char *lpath, int show_progress)
-{
+static int sync_recv(int fd, const char* rpath, const char* lpath, int show_progress) {
syncmsg msg;
int len;
int lfd = -1;
@@ -566,17 +560,14 @@
int flag;
};
-copyinfo *mkcopyinfo(const char *spath, const char *dpath,
- const char *name, int isdir)
-{
+static copyinfo* mkcopyinfo(const char* spath, const char* dpath, const char* name, int isdir) {
int slen = strlen(spath);
int dlen = strlen(dpath);
int nlen = strlen(name);
int ssize = slen + nlen + 2;
int dsize = dlen + nlen + 2;
- copyinfo *ci = reinterpret_cast<copyinfo*>(
- malloc(sizeof(copyinfo) + ssize + dsize));
+ copyinfo *ci = reinterpret_cast<copyinfo*>(malloc(sizeof(copyinfo) + ssize + dsize));
if(ci == 0) {
fprintf(stderr,"out of memory\n");
abort();
@@ -807,9 +798,8 @@
const char *lpath;
};
-void
-sync_ls_build_list_cb(unsigned mode, unsigned size, unsigned time,
- const char *name, void *cookie)
+static void sync_ls_build_list_cb(unsigned mode, unsigned size, unsigned time,
+ const char* name, void* cookie)
{
sync_ls_build_list_cb_args *args = (sync_ls_build_list_cb_args *)cookie;
copyinfo *ci;
diff --git a/adb/remount_service.cpp b/adb/remount_service.cpp
index 7a3b89a..3a4d2da 100644
--- a/adb/remount_service.cpp
+++ b/adb/remount_service.cpp
@@ -58,7 +58,7 @@
int OFF = 0;
bool result = (ioctl(fd, BLKROSET, &OFF) != -1);
- adb_close(fd);
+ unix_close(fd);
return result;
}
diff --git a/adb/services.cpp b/adb/services.cpp
index 1847447..2fd75ab 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -24,6 +24,11 @@
#include <stdlib.h>
#include <string.h>
+#if !ADB_HOST
+#include <pty.h>
+#include <termios.h>
+#endif
+
#ifndef _WIN32
#include <netdb.h>
#include <netinet/in.h>
@@ -210,8 +215,7 @@
sti->cookie = cookie;
sti->fd = s[1];
- adb_thread_t t;
- if (adb_thread_create(&t, service_bootstrap_func, sti)) {
+ if (!adb_thread_create(service_bootstrap_func, sti)) {
free(sti);
adb_close(s[0]);
adb_close(s[1]);
@@ -239,60 +243,65 @@
}
}
-static int create_subproc_pty(const char *cmd, const char *arg0, const char *arg1, pid_t *pid)
-{
+#if !ADB_HOST
+static int create_subproc_pty(const char* cmd, const char* arg0,
+ const char* arg1, pid_t* pid) {
D("create_subproc_pty(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1);
-#if defined(_WIN32)
- fprintf(stderr, "error: create_subproc_pty not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
- return -1;
-#else
+ char pts_name[PATH_MAX];
int ptm;
-
- ptm = unix_open("/dev/ptmx", O_RDWR | O_CLOEXEC); // | O_NOCTTY);
- if(ptm < 0){
- printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
- return -1;
- }
-
- char devname[64];
- if(grantpt(ptm) || unlockpt(ptm) || ptsname_r(ptm, devname, sizeof(devname)) != 0) {
- printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
- adb_close(ptm);
- return -1;
- }
-
- *pid = fork();
- if(*pid < 0) {
+ *pid = forkpty(&ptm, pts_name, nullptr, nullptr);
+ if (*pid == -1) {
printf("- fork failed: %s -\n", strerror(errno));
- adb_close(ptm);
+ unix_close(ptm);
return -1;
}
if (*pid == 0) {
init_subproc_child();
- int pts = unix_open(devname, O_RDWR | O_CLOEXEC);
- if (pts < 0) {
- fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname);
+ int pts = unix_open(pts_name, O_RDWR | O_CLOEXEC);
+ if (pts == -1) {
+ fprintf(stderr, "child failed to open pseudo-term slave %s: %s\n",
+ pts_name, strerror(errno));
+ unix_close(ptm);
exit(-1);
}
+ // arg0 is "-c" in batch mode and "-" in interactive mode.
+ if (strcmp(arg0, "-c") == 0) {
+ termios tattr;
+ if (tcgetattr(pts, &tattr) == -1) {
+ fprintf(stderr, "tcgetattr failed: %s\n", strerror(errno));
+ unix_close(pts);
+ unix_close(ptm);
+ exit(-1);
+ }
+
+ cfmakeraw(&tattr);
+ if (tcsetattr(pts, TCSADRAIN, &tattr) == -1) {
+ fprintf(stderr, "tcsetattr failed: %s\n", strerror(errno));
+ unix_close(pts);
+ unix_close(ptm);
+ exit(-1);
+ }
+ }
+
dup2(pts, STDIN_FILENO);
dup2(pts, STDOUT_FILENO);
dup2(pts, STDERR_FILENO);
- adb_close(pts);
- adb_close(ptm);
+ unix_close(pts);
+ unix_close(ptm);
- execl(cmd, cmd, arg0, arg1, NULL);
+ execl(cmd, cmd, arg0, arg1, nullptr);
fprintf(stderr, "- exec '%s' failed: %s (%d) -\n",
cmd, strerror(errno), errno);
exit(-1);
} else {
return ptm;
}
-#endif /* !defined(_WIN32) */
}
+#endif // !ADB_HOST
static int create_subproc_raw(const char *cmd, const char *arg0, const char *arg1, pid_t *pid)
{
@@ -378,12 +387,7 @@
}
}
-static int create_subproc_thread(const char *name, const subproc_mode mode)
-{
- adb_thread_t t;
- int ret_fd;
- pid_t pid = -1;
-
+static int create_subproc_thread(const char *name, bool pty = false) {
const char *arg0, *arg1;
if (name == 0 || *name == 0) {
arg0 = "-"; arg1 = 0;
@@ -391,16 +395,12 @@
arg0 = "-c"; arg1 = name;
}
- switch (mode) {
- case SUBPROC_PTY:
+ pid_t pid = -1;
+ int ret_fd;
+ if (pty) {
ret_fd = create_subproc_pty(SHELL_COMMAND, arg0, arg1, &pid);
- break;
- case SUBPROC_RAW:
+ } else {
ret_fd = create_subproc_raw(SHELL_COMMAND, arg0, arg1, &pid);
- break;
- default:
- fprintf(stderr, "invalid subproc_mode %d\n", mode);
- return -1;
}
D("create_subproc ret_fd=%d pid=%d\n", ret_fd, pid);
@@ -410,7 +410,7 @@
sti->cookie = (void*) (uintptr_t) pid;
sti->fd = ret_fd;
- if (adb_thread_create(&t, service_bootstrap_func, sti)) {
+ if (!adb_thread_create(service_bootstrap_func, sti)) {
free(sti);
adb_close(ret_fd);
fprintf(stderr, "cannot create service thread\n");
@@ -462,9 +462,9 @@
} else if (!strncmp(name, "jdwp:", 5)) {
ret = create_jdwp_connection_fd(atoi(name+5));
} else if(!HOST && !strncmp(name, "shell:", 6)) {
- ret = create_subproc_thread(name + 6, SUBPROC_PTY);
+ ret = create_subproc_thread(name + 6, true);
} else if(!HOST && !strncmp(name, "exec:", 5)) {
- ret = create_subproc_thread(name + 5, SUBPROC_RAW);
+ ret = create_subproc_thread(name + 5);
} else if(!strncmp(name, "sync:", 5)) {
ret = create_service_thread(file_sync_service, NULL);
} else if(!strncmp(name, "remount:", 8)) {
@@ -479,9 +479,9 @@
ret = create_service_thread(restart_unroot_service, NULL);
} else if(!strncmp(name, "backup:", 7)) {
ret = create_subproc_thread(android::base::StringPrintf("/system/bin/bu backup %s",
- (name + 7)).c_str(), SUBPROC_RAW);
+ (name + 7)).c_str());
} else if(!strncmp(name, "restore:", 8)) {
- ret = create_subproc_thread("/system/bin/bu restore", SUBPROC_RAW);
+ ret = create_subproc_thread("/system/bin/bu restore");
} else if(!strncmp(name, "tcpip:", 6)) {
int port;
if (sscanf(name + 6, "%d", &port) != 1) {
@@ -514,9 +514,9 @@
#if ADB_HOST
struct state_info {
- transport_type transport;
+ TransportType transport_type;
char* serial;
- int state;
+ ConnectionState state;
};
static void wait_for_state(int fd, void* cookie)
@@ -526,7 +526,8 @@
D("wait_for_state %d\n", sinfo->state);
std::string error_msg = "unknown error";
- atransport* t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &error_msg);
+ atransport* t = acquire_one_transport(sinfo->state, sinfo->transport_type, sinfo->serial,
+ &error_msg);
if (t != 0) {
SendOkay(fd);
} else {
@@ -627,16 +628,15 @@
}
}
-static void connect_service(int fd, void* cookie)
-{
- char *host = reinterpret_cast<char*>(cookie);
-
+static void connect_service(int fd, void* data) {
+ char* host = reinterpret_cast<char*>(data);
std::string response;
if (!strncmp(host, "emu:", 4)) {
connect_emulator(host + 4, &response);
} else {
connect_device(host, &response);
}
+ free(host);
// Send response for emulator and device
SendProtocolString(fd, response);
@@ -664,15 +664,18 @@
name += strlen("wait-for-");
if (!strncmp(name, "local", strlen("local"))) {
- sinfo->transport = kTransportLocal;
- sinfo->state = CS_DEVICE;
+ sinfo->transport_type = kTransportLocal;
+ sinfo->state = kCsDevice;
} else if (!strncmp(name, "usb", strlen("usb"))) {
- sinfo->transport = kTransportUsb;
- sinfo->state = CS_DEVICE;
+ sinfo->transport_type = kTransportUsb;
+ sinfo->state = kCsDevice;
} else if (!strncmp(name, "any", strlen("any"))) {
- sinfo->transport = kTransportAny;
- sinfo->state = CS_DEVICE;
+ sinfo->transport_type = kTransportAny;
+ sinfo->state = kCsDevice;
} else {
+ if (sinfo->serial) {
+ free(sinfo->serial);
+ }
free(sinfo);
return NULL;
}
@@ -680,8 +683,8 @@
int fd = create_service_thread(wait_for_state, sinfo);
return create_local_socket(fd);
} else if (!strncmp(name, "connect:", 8)) {
- const char *host = name + 8;
- int fd = create_service_thread(connect_service, (void *)host);
+ char* host = strdup(name + 8);
+ int fd = create_service_thread(connect_service, host);
return create_local_socket(fd);
}
return NULL;
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index 32ca17d..621944e 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -691,7 +691,7 @@
#if ADB_HOST
char *service = NULL;
char* serial = NULL;
- transport_type ttype = kTransportAny;
+ TransportType type = kTransportAny;
#endif
D("SS(%d): enqueue %d\n", s->id, p->len);
@@ -748,13 +748,13 @@
service = serial_end + 1;
}
} else if (!strncmp(service, "host-usb:", strlen("host-usb:"))) {
- ttype = kTransportUsb;
+ type = kTransportUsb;
service += strlen("host-usb:");
} else if (!strncmp(service, "host-local:", strlen("host-local:"))) {
- ttype = kTransportLocal;
+ type = kTransportLocal;
service += strlen("host-local:");
} else if (!strncmp(service, "host:", strlen("host:"))) {
- ttype = kTransportAny;
+ type = kTransportAny;
service += strlen("host:");
} else {
service = NULL;
@@ -768,7 +768,7 @@
** the OKAY or FAIL message and all we have to do
** is clean up.
*/
- if(handle_host_request(service, ttype, serial, s->peer->fd, s) == 0) {
+ if(handle_host_request(service, type, serial, s->peer->fd, s) == 0) {
/* XXX fail message? */
D( "SS(%d): handled host service '%s'\n", s->id, service );
goto fail;
@@ -815,7 +815,8 @@
#else /* !ADB_HOST */
if (s->transport == NULL) {
std::string error_msg = "unknown failure";
- s->transport = acquire_one_transport(CS_ANY, kTransportAny, NULL, &error_msg);
+ s->transport =
+ acquire_one_transport(kCsAny, kTransportAny, NULL, &error_msg);
if (s->transport == NULL) {
SendFail(s->peer->fd, error_msg);
@@ -824,7 +825,7 @@
}
#endif
- if(!(s->transport) || (s->transport->connection_state == CS_OFFLINE)) {
+ if(!(s->transport) || (s->transport->connection_state == kCsOffline)) {
/* if there's no remote we fail the connection
** right here and terminate it
*/
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 59e5b0b..b7c16d9 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -79,19 +79,13 @@
LeaveCriticalSection( lock );
}
-typedef struct { unsigned tid; } adb_thread_t;
-
typedef void* (*adb_thread_func_t)(void* arg);
typedef void (*win_thread_func_t)(void* arg);
-static __inline__ int adb_thread_create( adb_thread_t *thread, adb_thread_func_t func, void* arg)
-{
- thread->tid = _beginthread( (win_thread_func_t)func, 0, arg );
- if (thread->tid == (unsigned)-1L) {
- return -1;
- }
- return 0;
+static __inline__ bool adb_thread_create(adb_thread_func_t func, void* arg) {
+ uintptr_t tid = _beginthread((win_thread_func_t)func, 0, arg);
+ return (tid != static_cast<uintptr_t>(-1L));
}
static __inline__ unsigned long adb_thread_id()
@@ -131,6 +125,7 @@
#undef mkdir
#define mkdir ___xxx_mkdir
+// See the comments for the !defined(_WIN32) versions of adb_*().
extern int adb_open(const char* path, int options);
extern int adb_creat(const char* path, int mode);
extern int adb_read(int fd, void* buf, int len);
@@ -139,6 +134,7 @@
extern int adb_shutdown(int fd);
extern int adb_close(int fd);
+// See the comments for the !defined(_WIN32) version of unix_close().
static __inline__ int unix_close(int fd)
{
return close(fd);
@@ -146,11 +142,13 @@
#undef close
#define close ____xxx_close
+// See the comments for the !defined(_WIN32) version of unix_read().
extern int unix_read(int fd, void* buf, size_t len);
#undef read
#define read ___xxx_read
+// See the comments for the !defined(_WIN32) version of unix_write().
static __inline__ int unix_write(int fd, const void* buf, size_t len)
{
return write(fd, buf, len);
@@ -158,11 +156,13 @@
#undef write
#define write ___xxx_write
+// See the comments for the !defined(_WIN32) version of adb_open_mode().
static __inline__ int adb_open_mode(const char* path, int options, int mode)
{
return adb_open(path, options);
}
+// See the comments for the !defined(_WIN32) version of unix_open().
static __inline__ int unix_open(const char* path, int options,...)
{
if ((options & O_CREAT) == 0)
@@ -320,6 +320,15 @@
fcntl( fd, F_SETFD, FD_CLOEXEC );
}
+// Open a file and return a file descriptor that may be used with unix_read(),
+// unix_write(), unix_close(), but not adb_read(), adb_write(), adb_close().
+//
+// On Unix, this is based on open(), so the file descriptor is a real OS file
+// descriptor, but the Windows implementation (in sysdeps_win32.cpp) returns a
+// file descriptor that can only be used with C Runtime APIs (which are wrapped
+// by unix_read(), unix_write(), unix_close()). Also, the C Runtime has
+// configurable CR/LF translation which defaults to text mode, but is settable
+// with _setmode().
static __inline__ int unix_open(const char* path, int options,...)
{
if ((options & O_CREAT) == 0)
@@ -337,12 +346,21 @@
}
}
+// Similar to the two-argument adb_open(), but takes a mode parameter for file
+// creation. See adb_open() for more info.
static __inline__ int adb_open_mode( const char* pathname, int options, int mode )
{
return TEMP_FAILURE_RETRY( open( pathname, options, mode ) );
}
+// Open a file and return a file descriptor that may be used with adb_read(),
+// adb_write(), adb_close(), but not unix_read(), unix_write(), unix_close().
+//
+// On Unix, this is based on open(), but the Windows implementation (in
+// sysdeps_win32.cpp) uses Windows native file I/O and bypasses the C Runtime
+// and its CR/LF translation. The returned file descriptor should be used with
+// adb_read(), adb_write(), adb_close(), etc.
static __inline__ int adb_open( const char* pathname, int options )
{
int fd = TEMP_FAILURE_RETRY( open( pathname, options ) );
@@ -361,6 +379,9 @@
#undef shutdown
#define shutdown ____xxx_shutdown
+// Closes a file descriptor that came from adb_open() or adb_open_mode(), but
+// not designed to take a file descriptor from unix_open(). See the comments
+// for adb_open() for more info.
static __inline__ int adb_close(int fd)
{
return close(fd);
@@ -425,22 +446,28 @@
#undef accept
#define accept ___xxx_accept
+// Operate on a file descriptor returned from unix_open() or a well-known file
+// descriptor such as STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO.
+//
+// On Unix, unix_read(), unix_write(), unix_close() map to adb_read(),
+// adb_write(), adb_close() (which all map to Unix system calls), but the
+// Windows implementations (in the ifdef above and in sysdeps_win32.cpp) call
+// into the C Runtime and its configurable CR/LF translation (which is settable
+// via _setmode()).
#define unix_read adb_read
#define unix_write adb_write
#define unix_close adb_close
-typedef pthread_t adb_thread_t;
-
typedef void* (*adb_thread_func_t)( void* arg );
-static __inline__ int adb_thread_create( adb_thread_t *pthread, adb_thread_func_t start, void* arg )
-{
- pthread_attr_t attr;
+static __inline__ bool adb_thread_create(adb_thread_func_t start, void* arg) {
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- pthread_attr_init (&attr);
- pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
-
- return pthread_create( pthread, &attr, start, arg );
+ pthread_t thread;
+ errno = pthread_create(&thread, &attr, start, arg);
+ return (errno == 0);
}
static __inline__ int adb_socket_setbufsize( int fd, int bufsize )
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index a21272f..50c99f1 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -172,14 +172,15 @@
static int _win32_fh_count;
static FH
-_fh_from_int( int fd )
+_fh_from_int( int fd, const char* func )
{
FH f;
fd -= WIN32_FH_BASE;
if (fd < 0 || fd >= _win32_fh_count) {
- D( "_fh_from_int: invalid fd %d\n", fd + WIN32_FH_BASE );
+ D( "_fh_from_int: invalid fd %d passed to %s\n", fd + WIN32_FH_BASE,
+ func );
errno = EBADF;
return NULL;
}
@@ -187,7 +188,8 @@
f = &_win32_fhs[fd];
if (f->used == 0) {
- D( "_fh_from_int: invalid fd %d\n", fd + WIN32_FH_BASE );
+ D( "_fh_from_int: invalid fd %d passed to %s\n", fd + WIN32_FH_BASE,
+ func );
errno = EBADF;
return NULL;
}
@@ -427,7 +429,7 @@
int adb_read(int fd, void* buf, int len)
{
- FH f = _fh_from_int(fd);
+ FH f = _fh_from_int(fd, __func__);
if (f == NULL) {
return -1;
@@ -439,7 +441,7 @@
int adb_write(int fd, const void* buf, int len)
{
- FH f = _fh_from_int(fd);
+ FH f = _fh_from_int(fd, __func__);
if (f == NULL) {
return -1;
@@ -451,7 +453,7 @@
int adb_lseek(int fd, int pos, int where)
{
- FH f = _fh_from_int(fd);
+ FH f = _fh_from_int(fd, __func__);
if (!f) {
return -1;
@@ -463,7 +465,7 @@
int adb_shutdown(int fd)
{
- FH f = _fh_from_int(fd);
+ FH f = _fh_from_int(fd, __func__);
if (!f || f->clazz != &_fh_socket_class) {
D("adb_shutdown: invalid fd %d\n", fd);
@@ -478,7 +480,7 @@
int adb_close(int fd)
{
- FH f = _fh_from_int(fd);
+ FH f = _fh_from_int(fd, __func__);
if (!f) {
return -1;
@@ -763,7 +765,7 @@
#undef accept
int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen)
{
- FH serverfh = _fh_from_int(serverfd);
+ FH serverfh = _fh_from_int(serverfd, __func__);
FH fh;
if ( !serverfh || serverfh->clazz != &_fh_socket_class ) {
@@ -792,7 +794,7 @@
int adb_setsockopt( int fd, int level, int optname, const void* optval, socklen_t optlen )
{
- FH fh = _fh_from_int(fd);
+ FH fh = _fh_from_int(fd, __func__);
if ( !fh || fh->clazz != &_fh_socket_class ) {
D("adb_setsockopt: invalid fd %d\n", fd);
@@ -1386,7 +1388,7 @@
static void
event_looper_hook( EventLooper looper, int fd, int events )
{
- FH f = _fh_from_int(fd);
+ FH f = _fh_from_int(fd, __func__);
EventHook *pnode;
EventHook node;
@@ -1418,7 +1420,7 @@
static void
event_looper_unhook( EventLooper looper, int fd, int events )
{
- FH fh = _fh_from_int(fd);
+ FH fh = _fh_from_int(fd, __func__);
EventHook *pnode = event_looper_find_p( looper, fh );
EventHook node = *pnode;
@@ -3036,7 +3038,7 @@
}
}
-// Called by 'adb shell' command to read from stdin.
+// Called by 'adb shell' and 'adb exec-in' to read from stdin.
int unix_read(int fd, void* buf, size_t len) {
if ((fd == STDIN_FILENO) && (_console_handle != NULL)) {
// If it is a request to read from stdin, and stdin_raw_init() has been
@@ -3046,8 +3048,12 @@
return _console_read(_console_handle, buf, len);
} else {
// Just call into C Runtime which can read from pipes/files and which
- // can do LF/CR translation.
+ // can do LF/CR translation (which is overridable with _setmode()).
+ // Undefine the macro that is set in sysdeps.h which bans calls to
+ // plain read() in favor of unix_read() or adb_read().
+#pragma push_macro("read")
#undef read
return read(fd, buf, len);
+#pragma pop_macro("read")
}
}
diff --git a/adb/test_track_devices.cpp b/adb/test_track_devices.cpp
index 3e823e9..f78daeb 100644
--- a/adb/test_track_devices.cpp
+++ b/adb/test_track_devices.cpp
@@ -62,7 +62,7 @@
if (!android::base::ReadFully(s, buffer, len))
panic("could not read data");
- printf( "received header %.*s (%d bytes):\n%.*s", 4, head, len, len, buffer );
+ printf( "received header %.*s (%d bytes):\n%.*s----\n", 4, head, len, len, buffer );
}
close(s);
}
diff --git a/adb/tests/test_adb.py b/adb/tests/test_adb.py
index 0ff87d2..4eccc8c 100755
--- a/adb/tests/test_adb.py
+++ b/adb/tests/test_adb.py
@@ -164,7 +164,8 @@
return call_combined(self.adb_cmd + "shell " + cmd)
def install(self, filename):
- return call_checked(self.adb_cmd + "install {}".format(pipes.quote(filename)))
+ return call_checked(
+ self.adb_cmd + "install {}".format(pipes.quote(filename)))
def push(self, local, remote):
return call_checked(self.adb_cmd + "push {} {}".format(local, remote))
@@ -283,7 +284,7 @@
result = adb.shell("sh -c 'echo hello; echo world'").splitlines()
self.assertEqual(["", "world"], result)
# If you really wanted "hello" and "world", here's what you'd do:
- result = adb.shell("echo hello\;echo world").splitlines()
+ result = adb.shell(r"echo hello\;echo world").splitlines()
self.assertEqual(["hello", "world"], result)
# http://b/15479704
@@ -292,7 +293,7 @@
# http://b/20564385
self.assertEqual('t', adb.shell("FOO=a BAR=b echo t").strip())
- self.assertEqual('123Linux', adb.shell("echo -n 123\;uname").strip())
+ self.assertEqual('123Linux', adb.shell(r"echo -n 123\;uname").strip())
def test_install_argument_escaping(self):
"""Make sure that install argument escaping works."""
@@ -306,6 +307,13 @@
tf = tempfile.NamedTemporaryFile("w", suffix="-Live Hold'em.apk")
self.assertIn("-Live Hold'em.apk", adb.install(tf.name))
+ def test_line_endings(self):
+ """Ensure that line ending translation is not happening in the pty.
+
+ Bug: http://b/19735063
+ """
+ self.assertFalse(AdbWrapper().shell("uname").endswith("\r\n"))
+
class AdbFile(unittest.TestCase):
SCRATCH_DIR = "/data/local/tmp"
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 2cd6ac2..379c702 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -26,6 +26,8 @@
#include <string.h>
#include <unistd.h>
+#include <list>
+
#include <base/stringprintf.h>
#include "adb.h"
@@ -33,15 +35,8 @@
static void transport_unref(atransport *t);
-static atransport transport_list = {
- .next = &transport_list,
- .prev = &transport_list,
-};
-
-static atransport pending_list = {
- .next = &pending_list,
- .prev = &pending_list,
-};
+static std::list<atransport*> transport_list;
+static std::list<atransport*> pending_list;
ADB_MUTEX_DEFINE( transport_lock );
@@ -530,8 +525,6 @@
static void transport_registration_func(int _fd, unsigned ev, void *data)
{
tmsg m;
- adb_thread_t output_thread_ptr;
- adb_thread_t input_thread_ptr;
int s[2];
atransport *t;
@@ -555,8 +548,7 @@
adb_close(t->fd);
adb_mutex_lock(&transport_lock);
- t->next->prev = t->prev;
- t->prev->next = t->next;
+ transport_list.remove(t);
adb_mutex_unlock(&transport_lock);
run_transport_disconnects(t);
@@ -572,19 +564,18 @@
if (t->devpath)
free(t->devpath);
- memset(t,0xee,sizeof(atransport));
- free(t);
+ delete t;
update_transports();
return;
}
/* don't create transport threads for inaccessible devices */
- if (t->connection_state != CS_NOPERM) {
+ if (t->connection_state != kCsNoPerm) {
/* initial references are the two threads */
t->ref_count = 2;
- if(adb_socketpair(s)) {
+ if (adb_socketpair(s)) {
fatal_errno("cannot open transport socketpair");
}
@@ -600,24 +591,18 @@
fdevent_set(&(t->transport_fde), FDE_READ);
- if(adb_thread_create(&input_thread_ptr, input_thread, t)){
+ if (!adb_thread_create(input_thread, t)) {
fatal_errno("cannot create input thread");
}
- if(adb_thread_create(&output_thread_ptr, output_thread, t)){
+ if (!adb_thread_create(output_thread, t)) {
fatal_errno("cannot create output thread");
}
}
adb_mutex_lock(&transport_lock);
- /* remove from pending list */
- t->next->prev = t->prev;
- t->prev->next = t->next;
- /* put us on the master device list */
- t->next = &transport_list;
- t->prev = transport_list.prev;
- t->next->prev = t;
- t->prev->next = t;
+ pending_list.remove(t);
+ transport_list.push_front(t);
adb_mutex_unlock(&transport_lock);
t->disconnects.next = t->disconnects.prev = &t->disconnects;
@@ -740,10 +725,8 @@
return !*to_test;
}
-atransport* acquire_one_transport(int state, transport_type ttype,
- const char* serial, std::string* error_out)
-{
- atransport *t;
+atransport* acquire_one_transport(ConnectionState state, TransportType type,
+ const char* serial, std::string* error_out) {
atransport *result = NULL;
int ambiguous = 0;
@@ -751,8 +734,8 @@
if (error_out) *error_out = android::base::StringPrintf("device '%s' not found", serial);
adb_mutex_lock(&transport_lock);
- for (t = transport_list.next; t != &transport_list; t = t->next) {
- if (t->connection_state == CS_NOPERM) {
+ for (auto t : transport_list) {
+ if (t->connection_state == kCsNoPerm) {
if (error_out) *error_out = "insufficient permissions for device";
continue;
}
@@ -773,7 +756,7 @@
result = t;
}
} else {
- if (ttype == kTransportUsb && t->type == kTransportUsb) {
+ if (type == kTransportUsb && t->type == kTransportUsb) {
if (result) {
if (error_out) *error_out = "more than one device";
ambiguous = 1;
@@ -781,7 +764,7 @@
break;
}
result = t;
- } else if (ttype == kTransportLocal && t->type == kTransportLocal) {
+ } else if (type == kTransportLocal && t->type == kTransportLocal) {
if (result) {
if (error_out) *error_out = "more than one emulator";
ambiguous = 1;
@@ -789,7 +772,7 @@
break;
}
result = t;
- } else if (ttype == kTransportAny) {
+ } else if (type == kTransportAny) {
if (result) {
if (error_out) *error_out = "more than one device/emulator";
ambiguous = 1;
@@ -803,7 +786,7 @@
adb_mutex_unlock(&transport_lock);
if (result) {
- if (result->connection_state == CS_UNAUTHORIZED) {
+ if (result->connection_state == kCsUnauthorized) {
if (error_out) {
*error_out = "device unauthorized.\n";
char* ADB_VENDOR_KEYS = getenv("ADB_VENDOR_KEYS");
@@ -816,13 +799,13 @@
}
/* offline devices are ignored -- they are either being born or dying */
- if (result && result->connection_state == CS_OFFLINE) {
+ if (result && result->connection_state == kCsOffline) {
if (error_out) *error_out = "device offline";
result = NULL;
}
/* check for required connection state */
- if (result && state != CS_ANY && result->connection_state != state) {
+ if (result && state != kCsAny && result->connection_state != state) {
if (error_out) *error_out = "invalid device state";
result = NULL;
}
@@ -831,7 +814,7 @@
if (result) {
/* found one that we can take */
if (error_out) *error_out = "success";
- } else if (state != CS_ANY && (serial || !ambiguous)) {
+ } else if (state != kCsAny && (serial || !ambiguous)) {
adb_sleep_ms(1000);
goto retry;
}
@@ -841,14 +824,14 @@
const char* atransport::connection_state_name() const {
switch (connection_state) {
- case CS_OFFLINE: return "offline";
- case CS_BOOTLOADER: return "bootloader";
- case CS_DEVICE: return "device";
- case CS_HOST: return "host";
- case CS_RECOVERY: return "recovery";
- case CS_NOPERM: return "no permissions";
- case CS_SIDELOAD: return "sideload";
- case CS_UNAUTHORIZED: return "unauthorized";
+ case kCsOffline: return "offline";
+ case kCsBootloader: return "bootloader";
+ case kCsDevice: return "device";
+ case kCsHost: return "host";
+ case kCsRecovery: return "recovery";
+ case kCsNoPerm: return "no permissions";
+ case kCsSideload: return "sideload";
+ case kCsUnauthorized: return "unauthorized";
default: return "unknown";
}
}
@@ -869,7 +852,8 @@
}
}
-static void append_transport(atransport* t, std::string* result, bool long_listing) {
+static void append_transport(const atransport* t, std::string* result,
+ bool long_listing) {
const char* serial = t->serial;
if (!serial || !serial[0]) {
serial = "(no serial number)";
@@ -893,7 +877,7 @@
std::string list_transports(bool long_listing) {
std::string result;
adb_mutex_lock(&transport_lock);
- for (atransport* t = transport_list.next; t != &transport_list; t = t->next) {
+ for (const auto t : transport_list) {
append_transport(t, &result, long_listing);
}
adb_mutex_unlock(&transport_lock);
@@ -901,11 +885,10 @@
}
/* hack for osx */
-void close_usb_devices()
-{
+void close_usb_devices() {
adb_mutex_lock(&transport_lock);
- for (atransport* t = transport_list.next; t != &transport_list; t = t->next) {
- if ( !t->kicked ) {
+ for (auto t : transport_list) {
+ if (!t->kicked) {
t->kicked = 1;
t->kick(t);
}
@@ -914,47 +897,39 @@
}
#endif // ADB_HOST
-int register_socket_transport(int s, const char *serial, int port, int local)
-{
- atransport *t = reinterpret_cast<atransport*>(calloc(1, sizeof(atransport)));
- if (t == nullptr) {
- return -1;
- }
-
- atransport *n;
- char buff[32];
+int register_socket_transport(int s, const char *serial, int port, int local) {
+ atransport* t = new atransport();
if (!serial) {
- snprintf(buff, sizeof buff, "T-%p", t);
- serial = buff;
+ char buf[32];
+ snprintf(buf, sizeof(buf), "T-%p", t);
+ serial = buf;
}
+
D("transport: %s init'ing for socket %d, on port %d\n", serial, s, port);
if (init_socket_transport(t, s, port, local) < 0) {
- free(t);
+ delete t;
return -1;
}
adb_mutex_lock(&transport_lock);
- for (n = pending_list.next; n != &pending_list; n = n->next) {
- if (n->serial && !strcmp(serial, n->serial)) {
+ for (auto transport : pending_list) {
+ if (transport->serial && strcmp(serial, transport->serial) == 0) {
adb_mutex_unlock(&transport_lock);
- free(t);
+ delete t;
return -1;
}
}
- for (n = transport_list.next; n != &transport_list; n = n->next) {
- if (n->serial && !strcmp(serial, n->serial)) {
+ for (auto transport : transport_list) {
+ if (transport->serial && strcmp(serial, transport->serial) == 0) {
adb_mutex_unlock(&transport_lock);
- free(t);
+ delete t;
return -1;
}
}
- t->next = &pending_list;
- t->prev = pending_list.prev;
- t->next->prev = t;
- t->prev->next = t;
+ pending_list.push_front(t);
t->serial = strdup(serial);
adb_mutex_unlock(&transport_lock);
@@ -963,96 +938,83 @@
}
#if ADB_HOST
-atransport *find_transport(const char *serial)
-{
- atransport *t;
+atransport *find_transport(const char *serial) {
+ atransport* result = nullptr;
adb_mutex_lock(&transport_lock);
- for(t = transport_list.next; t != &transport_list; t = t->next) {
- if (t->serial && !strcmp(serial, t->serial)) {
+ for (auto t : transport_list) {
+ if (t->serial && strcmp(serial, t->serial) == 0) {
+ result = t;
break;
}
- }
+ }
adb_mutex_unlock(&transport_lock);
- if (t != &transport_list)
- return t;
- else
- return 0;
+ return result;
}
void unregister_transport(atransport *t)
{
adb_mutex_lock(&transport_lock);
- t->next->prev = t->prev;
- t->prev->next = t->next;
+ transport_list.remove(t);
adb_mutex_unlock(&transport_lock);
kick_transport(t);
transport_unref(t);
}
-// unregisters all non-emulator TCP transports
-void unregister_all_tcp_transports()
-{
- atransport *t, *next;
+// Unregisters all non-emulator TCP transports.
+void unregister_all_tcp_transports() {
adb_mutex_lock(&transport_lock);
- for (t = transport_list.next; t != &transport_list; t = next) {
- next = t->next;
+ for (auto it = transport_list.begin(); it != transport_list.end(); ) {
+ atransport* t = *it;
if (t->type == kTransportLocal && t->adb_port == 0) {
- t->next->prev = t->prev;
- t->prev->next = next;
- // we cannot call kick_transport when holding transport_lock
- if (!t->kicked)
- {
+ // We cannot call kick_transport when holding transport_lock.
+ if (!t->kicked) {
t->kicked = 1;
t->kick(t);
}
transport_unref_locked(t);
+
+ it = transport_list.erase(it);
+ } else {
+ ++it;
}
- }
+ }
adb_mutex_unlock(&transport_lock);
}
#endif
-void register_usb_transport(usb_handle *usb, const char *serial, const char *devpath, unsigned writeable)
-{
- atransport *t = reinterpret_cast<atransport*>(calloc(1, sizeof(atransport)));
- if (t == nullptr) fatal("cannot allocate USB atransport");
+void register_usb_transport(usb_handle* usb, const char* serial,
+ const char* devpath, unsigned writeable) {
+ atransport* t = new atransport();
+
D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
serial ? serial : "");
- init_usb_transport(t, usb, (writeable ? CS_OFFLINE : CS_NOPERM));
+ init_usb_transport(t, usb, (writeable ? kCsOffline : kCsNoPerm));
if(serial) {
t->serial = strdup(serial);
}
- if(devpath) {
+
+ if (devpath) {
t->devpath = strdup(devpath);
}
adb_mutex_lock(&transport_lock);
- t->next = &pending_list;
- t->prev = pending_list.prev;
- t->next->prev = t;
- t->prev->next = t;
+ pending_list.push_front(t);
adb_mutex_unlock(&transport_lock);
register_transport(t);
}
-/* this should only be used for transports with connection_state == CS_NOPERM */
-void unregister_usb_transport(usb_handle *usb)
-{
- atransport *t;
+// This should only be used for transports with connection_state == kCsNoPerm.
+void unregister_usb_transport(usb_handle *usb) {
adb_mutex_lock(&transport_lock);
- for(t = transport_list.next; t != &transport_list; t = t->next) {
- if (t->usb == usb && t->connection_state == CS_NOPERM) {
- t->next->prev = t->prev;
- t->prev->next = t->next;
- break;
- }
- }
+ transport_list.remove_if([usb](atransport* t) {
+ return t->usb == usb && t->connection_state == kCsNoPerm;
+ });
adb_mutex_unlock(&transport_lock);
}
diff --git a/adb/transport.h b/adb/transport.h
index 5b6fdac..538f63e 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -25,11 +25,11 @@
/*
* Obtain a transport from the available transports.
- * If state is != CS_ANY, only transports in that state are considered.
+ * If state is != kCsAny, 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,
+atransport* acquire_one_transport(ConnectionState state, TransportType type,
const char* serial, std::string* error_out);
void add_transport_disconnect(atransport* t, adisconnect* dis);
void remove_transport_disconnect(atransport* t, adisconnect* dis);
@@ -50,7 +50,7 @@
/* 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 */
+// This should only be used for transports with connection_state == kCsNoPerm.
void unregister_usb_transport(usb_handle* usb);
/* these should only be used for the "adb disconnect" command */
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index b1deffd..d3c4c30 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -234,9 +234,8 @@
if (fd < 0) {
/* This could be an older version of the emulator, that doesn't
* implement adb QEMUD service. Fall back to the old TCP way. */
- adb_thread_t thr;
D("adb service is not available. Falling back to TCP socket.\n");
- adb_thread_create(&thr, server_socket_thread, arg);
+ adb_thread_create(server_socket_thread, arg);
return 0;
}
@@ -279,7 +278,6 @@
void local_init(int port)
{
- adb_thread_t thr;
void* (*func)(void *);
if(HOST) {
@@ -304,9 +302,8 @@
D("transport: local %s init\n", HOST ? "client" : "server");
- if(adb_thread_create(&thr, func, (void *) (uintptr_t) port)) {
- fatal_errno("cannot create local socket %s thread",
- HOST ? "client" : "server");
+ if (!adb_thread_create(func, (void *) (uintptr_t) port)) {
+ fatal_errno("cannot create local socket %s thread", HOST ? "client" : "server");
}
}
@@ -390,7 +387,7 @@
t->write_to_remote = remote_write;
t->sfd = s;
t->sync_token = 1;
- t->connection_state = CS_OFFLINE;
+ t->connection_state = kCsOffline;
t->type = kTransportLocal;
t->adb_port = 0;
diff --git a/adb/transport_test.cpp b/adb/transport_test.cpp
index 2b3fe3c..4b74adf 100644
--- a/adb/transport_test.cpp
+++ b/adb/transport_test.cpp
@@ -20,34 +20,85 @@
#include "adb.h"
+class TestTransport : public atransport {
+public:
+ bool operator==(const atransport& rhs) const {
+ EXPECT_EQ(read_from_remote, rhs.read_from_remote);
+ EXPECT_EQ(write_to_remote, rhs.write_to_remote);
+ EXPECT_EQ(close, rhs.close);
+ EXPECT_EQ(kick, rhs.kick);
+
+ EXPECT_EQ(fd, rhs.fd);
+ EXPECT_EQ(transport_socket, rhs.transport_socket);
+
+ EXPECT_EQ(
+ 0, memcmp(&transport_fde, &rhs.transport_fde, sizeof(fdevent)));
+
+ EXPECT_EQ(ref_count, rhs.ref_count);
+ EXPECT_EQ(sync_token, rhs.sync_token);
+ EXPECT_EQ(connection_state, rhs.connection_state);
+ EXPECT_EQ(online, rhs.online);
+ EXPECT_EQ(type, rhs.type);
+
+ EXPECT_EQ(usb, rhs.usb);
+ EXPECT_EQ(sfd, rhs.sfd);
+
+ EXPECT_EQ(serial, rhs.serial);
+ EXPECT_EQ(product, rhs.product);
+ EXPECT_EQ(model, rhs.model);
+ EXPECT_EQ(device, rhs.device);
+ EXPECT_EQ(devpath, rhs.devpath);
+ EXPECT_EQ(adb_port, rhs.adb_port);
+ EXPECT_EQ(kicked, rhs.kicked);
+
+ EXPECT_EQ(
+ 0, memcmp(&disconnects, &rhs.disconnects, sizeof(adisconnect)));
+
+ EXPECT_EQ(key, rhs.key);
+ EXPECT_EQ(0, memcmp(token, rhs.token, TOKEN_SIZE));
+ EXPECT_EQ(0, memcmp(&auth_fde, &rhs.auth_fde, sizeof(fdevent)));
+ EXPECT_EQ(failed_auth_attempts, rhs.failed_auth_attempts);
+
+ return true;
+ }
+};
+
TEST(transport, kick_transport) {
- atransport t = {};
+ TestTransport t;
+
// Mutate some member so we can test that the function is run.
t.kick = [](atransport* trans) { trans->fd = 42; };
- atransport expected = t;
+
+ TestTransport expected;
+ expected.kick = t.kick;
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)));
+ ASSERT_EQ(expected, t);
}
TEST(transport, kick_transport_already_kicked) {
// Ensure that the transport is not modified if the transport has already been
// kicked.
- atransport t = {};
+ TestTransport t;
t.kicked = 1;
t.kick = [](atransport*) { FAIL() << "Kick should not have been called"; };
- atransport expected = t;
+
+ TestTransport expected;
+ expected.kicked = 1;
+ expected.kick = t.kick;
+
kick_transport(&t);
- ASSERT_EQ(0, memcmp(&expected, &t, sizeof(atransport)));
+ ASSERT_EQ(expected, t);
}
// 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 = {};
+ atransport t;
run_transport_disconnects(&t);
}
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index cdabffe..eb3454d 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -80,7 +80,7 @@
usb_kick(t->usb);
}
-void init_usb_transport(atransport *t, usb_handle *h, int state)
+void init_usb_transport(atransport *t, usb_handle *h, ConnectionState state)
{
D("transport: usb\n");
t->close = remote_close;
diff --git a/adb/usb_linux.cpp b/adb/usb_linux.cpp
index 71baaee..c6f712b 100644
--- a/adb/usb_linux.cpp
+++ b/adb/usb_linux.cpp
@@ -168,13 +168,13 @@
continue;
}
- desclength = adb_read(fd, devdesc, sizeof(devdesc));
+ desclength = unix_read(fd, devdesc, sizeof(devdesc));
bufend = bufptr + desclength;
// should have device and configuration descriptors, and atleast two endpoints
if (desclength < USB_DT_DEVICE_SIZE + USB_DT_CONFIG_SIZE) {
D("desclength %zu is too small\n", desclength);
- adb_close(fd);
+ unix_close(fd);
continue;
}
@@ -182,7 +182,7 @@
bufptr += USB_DT_DEVICE_SIZE;
if((device->bLength != USB_DT_DEVICE_SIZE) || (device->bDescriptorType != USB_DT_DEVICE)) {
- adb_close(fd);
+ unix_close(fd);
continue;
}
@@ -195,7 +195,7 @@
bufptr += USB_DT_CONFIG_SIZE;
if (config->bLength != USB_DT_CONFIG_SIZE || config->bDescriptorType != USB_DT_CONFIG) {
D("usb_config_descriptor not found\n");
- adb_close(fd);
+ unix_close(fd);
continue;
}
@@ -303,17 +303,13 @@
}
} // end of while
- adb_close(fd);
+ unix_close(fd);
} // end of devdir while
closedir(devdir);
} //end of busdir while
closedir(busdir);
}
-void usb_cleanup()
-{
-}
-
static int usb_bulk_write(usb_handle *h, const void *data, int len)
{
struct usbdevfs_urb *urb = &h->urb_out;
@@ -559,7 +555,7 @@
h->prev = 0;
h->next = 0;
- adb_close(h->desc);
+ unix_close(h->desc);
D("-- usb closed %p (fd = %d) --\n", h, h->desc);
adb_mutex_unlock(&usb_lock);
@@ -622,7 +618,7 @@
if (ioctl(usb->desc, USBDEVFS_CLAIMINTERFACE, &interface) != 0) {
D("[ usb ioctl(%d, USBDEVFS_CLAIMINTERFACE) failed: %s]\n",
usb->desc, strerror(errno));
- adb_close(usb->desc);
+ unix_close(usb->desc);
free(usb);
return;
}
@@ -669,7 +665,6 @@
void usb_init()
{
- adb_thread_t tid;
struct sigaction actions;
memset(&actions, 0, sizeof(actions));
@@ -678,7 +673,7 @@
actions.sa_handler = sigalrm_handler;
sigaction(SIGALRM,& actions, NULL);
- if(adb_thread_create(&tid, device_poll_thread, NULL)){
+ if (!adb_thread_create(device_poll_thread, nullptr)) {
fatal_errno("cannot create input thread");
}
}
diff --git a/adb/usb_linux_client.cpp b/adb/usb_linux_client.cpp
index 18289e2..d34c454 100644
--- a/adb/usb_linux_client.cpp
+++ b/adb/usb_linux_client.cpp
@@ -82,7 +82,7 @@
struct func_desc fs_descs, hs_descs;
} __attribute__((packed));
-struct func_desc fs_descriptors = {
+static struct func_desc fs_descriptors = {
.intf = {
.bLength = sizeof(fs_descriptors.intf),
.bDescriptorType = USB_DT_INTERFACE,
@@ -109,7 +109,7 @@
},
};
-struct func_desc hs_descriptors = {
+static struct func_desc hs_descriptors = {
.intf = {
.bLength = sizeof(hs_descriptors.intf),
.bDescriptorType = USB_DT_INTERFACE,
@@ -201,7 +201,7 @@
int n;
D("about to write (fd=%d, len=%d)\n", h->fd, len);
- n = adb_write(h->fd, data, len);
+ n = unix_write(h->fd, data, len);
if(n != len) {
D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
h->fd, n, errno, strerror(errno));
@@ -216,7 +216,7 @@
int n;
D("about to read (fd=%d, len=%d)\n", h->fd, len);
- n = adb_read(h->fd, data, len);
+ n = unix_read(h->fd, data, len);
if(n != len) {
D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
h->fd, n, errno, strerror(errno));
@@ -230,7 +230,7 @@
{
D("usb_kick\n");
adb_mutex_lock(&h->lock);
- adb_close(h->fd);
+ unix_close(h->fd);
h->fd = -1;
// notify usb_adb_open_thread that we are disconnected
@@ -264,8 +264,7 @@
}
D("[ usb_init - starting thread ]\n");
- adb_thread_t tid;
- if(adb_thread_create(&tid, usb_adb_open_thread, h)){
+ if (!adb_thread_create(usb_adb_open_thread, h)) {
fatal_errno("cannot create usb thread");
}
}
@@ -483,8 +482,7 @@
adb_mutex_init(&h->lock, 0);
D("[ usb_init - starting thread ]\n");
- adb_thread_t tid;
- if (adb_thread_create(&tid, usb_ffs_open_thread, h)){
+ if (!adb_thread_create(usb_ffs_open_thread, h)) {
fatal_errno("[ cannot create usb thread ]\n");
}
}
@@ -497,10 +495,6 @@
usb_adb_init();
}
-void usb_cleanup()
-{
-}
-
int usb_write(usb_handle *h, const void *data, int len)
{
return h->write(h, data, len);
diff --git a/adb/usb_osx.cpp b/adb/usb_osx.cpp
index a795ce3..af65130 100644
--- a/adb/usb_osx.cpp
+++ b/adb/usb_osx.cpp
@@ -398,22 +398,27 @@
IONotificationPortDestroy(notificationPort);
DBG("RunLoopThread done\n");
- return NULL;
+ return NULL;
}
+static void usb_cleanup() {
+ DBG("usb_cleanup\n");
+ close_usb_devices();
+ if (currentRunLoop)
+ CFRunLoopStop(currentRunLoop);
+}
-static int initialized = 0;
-void usb_init()
-{
- if (!initialized)
- {
- adb_thread_t tid;
+void usb_init() {
+ static bool initialized = false;
+ if (!initialized) {
+ atexit(usb_cleanup);
adb_mutex_init(&start_lock, NULL);
adb_cond_init(&start_cond, NULL);
- if(adb_thread_create(&tid, RunLoopThread, NULL))
+ if (!adb_thread_create(RunLoopThread, nullptr)) {
fatal_errno("cannot create input thread");
+ }
// Wait for initialization to finish
adb_mutex_lock(&start_lock);
@@ -423,18 +428,10 @@
adb_mutex_destroy(&start_lock);
adb_cond_destroy(&start_cond);
- initialized = 1;
+ initialized = true;
}
}
-void usb_cleanup()
-{
- DBG("usb_cleanup\n");
- close_usb_devices();
- if (currentRunLoop)
- CFRunLoopStop(currentRunLoop);
-}
-
int usb_write(usb_handle *handle, const void *buf, int len)
{
IOReturn result;
diff --git a/adb/usb_windows.cpp b/adb/usb_windows.cpp
index d2bd58c..25deb1b 100644
--- a/adb/usb_windows.cpp
+++ b/adb/usb_windows.cpp
@@ -93,9 +93,6 @@
/// Initializes this module
void usb_init();
-/// Cleans up this module
-void usb_cleanup();
-
/// Opens usb interface (device) by interface (device) name.
usb_handle* do_usb_open(const wchar_t* interface_name);
@@ -181,16 +178,11 @@
}
void usb_init() {
- adb_thread_t tid;
-
- if(adb_thread_create(&tid, device_poll_thread, NULL)) {
+ if (!adb_thread_create(device_poll_thread, nullptr)) {
fatal_errno("cannot create input thread");
}
}
-void usb_cleanup() {
-}
-
usb_handle* do_usb_open(const wchar_t* interface_name) {
// Allocate our handle
usb_handle* ret = (usb_handle*)malloc(sizeof(usb_handle));
diff --git a/base/Android.mk b/base/Android.mk
index ad85c6b..7bd317b 100644
--- a/base/Android.mk
+++ b/base/Android.mk
@@ -18,11 +18,13 @@
libbase_src_files := \
file.cpp \
+ logging.cpp \
stringprintf.cpp \
strings.cpp \
libbase_test_src_files := \
file_test.cpp \
+ logging_test.cpp \
stringprintf_test.cpp \
strings_test.cpp \
test_main.cpp \
@@ -38,7 +40,7 @@
include $(CLEAR_VARS)
LOCAL_MODULE := libbase
LOCAL_CLANG := true
-LOCAL_SRC_FILES := $(libbase_src_files) logging.cpp
+LOCAL_SRC_FILES := $(libbase_src_files)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_CPPFLAGS := $(libbase_cppflags)
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
@@ -61,9 +63,6 @@
include $(CLEAR_VARS)
LOCAL_MODULE := libbase
LOCAL_SRC_FILES := $(libbase_src_files)
-ifneq ($(HOST_OS),windows)
- LOCAL_SRC_FILES += logging.cpp
-endif
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_CPPFLAGS := $(libbase_cppflags)
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
@@ -85,7 +84,7 @@
include $(CLEAR_VARS)
LOCAL_MODULE := libbase_test
LOCAL_CLANG := true
-LOCAL_SRC_FILES := $(libbase_test_src_files) logging_test.cpp
+LOCAL_SRC_FILES := $(libbase_test_src_files)
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_CPPFLAGS := $(libbase_cppflags)
LOCAL_SHARED_LIBRARIES := libbase
@@ -97,9 +96,6 @@
include $(CLEAR_VARS)
LOCAL_MODULE := libbase_test
LOCAL_SRC_FILES := $(libbase_test_src_files)
-ifneq ($(HOST_OS),windows)
- LOCAL_SRC_FILES += logging_test.cpp
-endif
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_CPPFLAGS := $(libbase_cppflags)
LOCAL_SHARED_LIBRARIES := libbase
diff --git a/base/file_test.cpp b/base/file_test.cpp
index e5cf696..b138094 100644
--- a/base/file_test.cpp
+++ b/base/file_test.cpp
@@ -36,7 +36,8 @@
TEST(file, ReadFileToString_success) {
std::string s("hello");
- ASSERT_TRUE(android::base::ReadFileToString("/proc/version", &s)) << errno;
+ ASSERT_TRUE(android::base::ReadFileToString("/proc/version", &s))
+ << strerror(errno);
EXPECT_GT(s.length(), 6U);
EXPECT_EQ('\n', s[s.length() - 1]);
s[5] = 0;
@@ -46,37 +47,44 @@
TEST(file, WriteStringToFile) {
TemporaryFile tf;
ASSERT_TRUE(tf.fd != -1);
- ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.filename)) << errno;
+ ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.filename))
+ << strerror(errno);
std::string s;
- ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s)) << errno;
+ ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s))
+ << strerror(errno);
EXPECT_EQ("abc", s);
}
+// WriteStringToFile2 is explicitly for setting Unix permissions, which make no
+// sense on Windows.
+#if !defined(_WIN32)
TEST(file, WriteStringToFile2) {
TemporaryFile tf;
ASSERT_TRUE(tf.fd != -1);
ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.filename, 0660,
getuid(), getgid()))
- << errno;
+ << strerror(errno);
struct stat sb;
ASSERT_EQ(0, stat(tf.filename, &sb));
- ASSERT_EQ(0660U, (sb.st_mode & ~S_IFMT));
+ ASSERT_EQ(0660U, static_cast<unsigned int>(sb.st_mode & ~S_IFMT));
ASSERT_EQ(getuid(), sb.st_uid);
ASSERT_EQ(getgid(), sb.st_gid);
std::string s;
- ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s)) << errno;
+ ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s))
+ << strerror(errno);
EXPECT_EQ("abc", s);
}
+#endif
TEST(file, WriteStringToFd) {
TemporaryFile tf;
ASSERT_TRUE(tf.fd != -1);
ASSERT_TRUE(android::base::WriteStringToFd("abc", tf.fd));
- ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)) << errno;
+ ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)) << strerror(errno);
std::string s;
- ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s)) << errno;
+ ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s)) << strerror(errno);
EXPECT_EQ("abc", s);
}
@@ -101,6 +109,7 @@
ASSERT_TRUE(tf.fd != -1);
ASSERT_TRUE(android::base::WriteFully(tf.fd, "abc", 3));
std::string s;
- ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s)) << errno;
+ ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s))
+ << strerror(errno);
EXPECT_EQ("abc", s);
}
diff --git a/base/include/base/logging.h b/base/include/base/logging.h
index 230adb8..283a7bc 100644
--- a/base/include/base/logging.h
+++ b/base/include/base/logging.h
@@ -13,10 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#ifndef BASE_LOGGING_H
#define BASE_LOGGING_H
+// NOTE: For Windows, you must include logging.h after windows.h to allow the
+// following code to suppress the evil ERROR macro:
+#ifdef _WIN32
+// windows.h includes wingdi.h which defines an evil macro ERROR.
+#ifdef ERROR
+#undef ERROR
+#endif
+#endif
+
#include <functional>
#include <memory>
#include <ostream>
diff --git a/base/include/base/stringprintf.h b/base/include/base/stringprintf.h
index 195c1de..d68af87 100644
--- a/base/include/base/stringprintf.h
+++ b/base/include/base/stringprintf.h
@@ -23,16 +23,32 @@
namespace android {
namespace base {
+// These printf-like functions are implemented in terms of vsnprintf, so they
+// use the same attribute for compile-time format string checking. On Windows,
+// if the mingw version of vsnprintf is used, use `gnu_printf' which allows z
+// in %zd and PRIu64 (and related) to be recognized by the compile-time
+// checking.
+#define FORMAT_ARCHETYPE __printf__
+#ifdef __USE_MINGW_ANSI_STDIO
+#if __USE_MINGW_ANSI_STDIO
+#undef FORMAT_ARCHETYPE
+#define FORMAT_ARCHETYPE gnu_printf
+#endif
+#endif
+
// Returns a string corresponding to printf-like formatting of the arguments.
std::string StringPrintf(const char* fmt, ...)
- __attribute__((__format__(__printf__, 1, 2)));
+ __attribute__((__format__(FORMAT_ARCHETYPE, 1, 2)));
// Appends a printf-like formatting of the arguments to 'dst'.
void StringAppendF(std::string* dst, const char* fmt, ...)
- __attribute__((__format__(__printf__, 2, 3)));
+ __attribute__((__format__(FORMAT_ARCHETYPE, 2, 3)));
// Appends a printf-like formatting of the arguments to 'dst'.
-void StringAppendV(std::string* dst, const char* format, va_list ap);
+void StringAppendV(std::string* dst, const char* format, va_list ap)
+ __attribute__((__format__(FORMAT_ARCHETYPE, 2, 0)));
+
+#undef FORMAT_ARCHETYPE
} // namespace base
} // namespace android
diff --git a/base/include/base/strings.h b/base/include/base/strings.h
index 5dbc5fb..638f845 100644
--- a/base/include/base/strings.h
+++ b/base/include/base/strings.h
@@ -17,6 +17,7 @@
#ifndef BASE_STRINGS_H
#define BASE_STRINGS_H
+#include <sstream>
#include <string>
#include <vector>
@@ -34,9 +35,24 @@
// Trims whitespace off both ends of the given string.
std::string Trim(const std::string& s);
-// Joins a vector of strings into a single string, using the given separator.
-template <typename StringT>
-std::string Join(const std::vector<StringT>& strings, char separator);
+// Joins a container of things into a single string, using the given separator.
+template <typename ContainerT>
+std::string Join(const ContainerT& things, char separator) {
+ if (things.empty()) {
+ return "";
+ }
+
+ std::ostringstream result;
+ result << *things.begin();
+ for (auto it = std::next(things.begin()); it != things.end(); ++it) {
+ result << separator << *it;
+ }
+ return result.str();
+}
+
+// We instantiate the common cases in strings.cpp.
+extern template std::string Join(const std::vector<std::string>&, char);
+extern template std::string Join(const std::vector<const char*>&, char);
// Tests whether 's' starts with 'prefix'.
bool StartsWith(const std::string& s, const char* prefix);
diff --git a/base/logging.cpp b/base/logging.cpp
index 0142b70..34229a2 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
#include "base/logging.h"
#include <libgen.h>
@@ -27,12 +31,16 @@
#include <iostream>
#include <limits>
-#include <mutex>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
+#ifndef _WIN32
+#include <mutex>
+#endif
+
+#include "base/macros.h"
#include "base/strings.h"
#include "cutils/threads.h"
@@ -45,10 +53,79 @@
#include <unistd.h>
#endif
+namespace {
+#ifndef _WIN32
+using std::mutex;
+using std::lock_guard;
+
+#if defined(__GLIBC__)
+const char* getprogname() {
+ return program_invocation_short_name;
+}
+#endif
+
+#else
+const char* getprogname() {
+ static bool first = true;
+ static char progname[MAX_PATH] = {};
+
+ if (first) {
+ // TODO(danalbert): This is a full path on Windows. Just get the basename.
+ DWORD nchars = GetModuleFileName(nullptr, progname, sizeof(progname));
+ DCHECK_GT(nchars, 0U);
+ first = false;
+ }
+
+ return progname;
+}
+
+class mutex {
+ public:
+ mutex() {
+ semaphore_ = CreateSemaphore(nullptr, 1, 1, nullptr);
+ CHECK(semaphore_ != nullptr) << "Failed to create Mutex";
+ }
+ ~mutex() {
+ CloseHandle(semaphore_);
+ }
+
+ void lock() {
+ DWORD result = WaitForSingleObject(semaphore_, INFINITE);
+ CHECK_EQ(result, WAIT_OBJECT_0) << GetLastError();
+ }
+
+ void unlock() {
+ bool result = ReleaseSemaphore(semaphore_, 1, nullptr);
+ CHECK(result);
+ }
+
+ private:
+ HANDLE semaphore_;
+};
+
+template <typename LockT>
+class lock_guard {
+ public:
+ explicit lock_guard(LockT& lock) : lock_(lock) {
+ lock_.lock();
+ }
+
+ ~lock_guard() {
+ lock_.unlock();
+ }
+
+ private:
+ LockT& lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(lock_guard);
+};
+#endif
+} // namespace
+
namespace android {
namespace base {
-static std::mutex logging_lock;
+static mutex logging_lock;
#ifdef __ANDROID__
static LogFunction gLogger = LogdLogger();
@@ -60,12 +137,6 @@
static LogSeverity gMinimumLogSeverity = INFO;
static std::unique_ptr<std::string> gProgramInvocationName;
-#if defined(__GLIBC__)
-static const char* getprogname() {
- return program_invocation_short_name;
-}
-#endif
-
static const char* ProgramInvocationName() {
if (gProgramInvocationName == nullptr) {
gProgramInvocationName.reset(new std::string(getprogname()));
@@ -182,7 +253,7 @@
}
void SetLogger(LogFunction&& logger) {
- std::lock_guard<std::mutex> lock(logging_lock);
+ lock_guard<mutex> lock(logging_lock);
gLogger = std::move(logger);
}
@@ -287,7 +358,7 @@
void LogMessage::LogLine(const char* file, unsigned int line, LogId id,
LogSeverity severity, const char* message) {
const char* tag = ProgramInvocationName();
- std::lock_guard<std::mutex> lock(logging_lock);
+ lock_guard<mutex> lock(logging_lock);
gLogger(id, severity, tag, file, line, message);
}
diff --git a/base/logging_test.cpp b/base/logging_test.cpp
index d947c1d..c91857a 100644
--- a/base/logging_test.cpp
+++ b/base/logging_test.cpp
@@ -85,6 +85,9 @@
TEST(logging, LOG) {
ASSERT_DEATH(LOG(FATAL) << "foobar", "foobar");
+ // We can't usefully check the output of any of these on Windows because we
+ // don't have std::regex, but we can at least make sure we printed at least as
+ // many characters are in the log message.
{
CapturedStderr cap;
LOG(WARNING) << "foobar";
@@ -92,10 +95,13 @@
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
+ ASSERT_GT(output.length(), strlen("foobar"));
+#if !defined(_WIN32)
std::regex message_regex(
make_log_pattern(android::base::WARNING, "foobar"));
ASSERT_TRUE(std::regex_search(output, message_regex));
+#endif
}
{
@@ -105,10 +111,13 @@
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
+ ASSERT_GT(output.length(), strlen("foobar"));
+#if !defined(_WIN32)
std::regex message_regex(
make_log_pattern(android::base::INFO, "foobar"));
ASSERT_TRUE(std::regex_search(output, message_regex));
+#endif
}
{
@@ -129,10 +138,13 @@
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
+ ASSERT_GT(output.length(), strlen("foobar"));
+#if !defined(_WIN32)
std::regex message_regex(
make_log_pattern(android::base::DEBUG, "foobar"));
ASSERT_TRUE(std::regex_search(output, message_regex));
+#endif
}
}
@@ -145,10 +157,13 @@
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
+ ASSERT_GT(output.length(), strlen("foobar"));
+#if !defined(_WIN32)
std::regex message_regex(make_log_pattern(
android::base::INFO, "foobar: No such file or directory"));
ASSERT_TRUE(std::regex_search(output, message_regex));
+#endif
}
}
@@ -161,11 +176,14 @@
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
+ ASSERT_GT(output.length(), strlen("unimplemented"));
+#if !defined(_WIN32)
std::string expected_message =
android::base::StringPrintf("%s unimplemented ", __PRETTY_FUNCTION__);
std::regex message_regex(
make_log_pattern(android::base::ERROR, expected_message.c_str()));
ASSERT_TRUE(std::regex_search(output, message_regex));
+#endif
}
}
diff --git a/base/stringprintf_test.cpp b/base/stringprintf_test.cpp
index 5cc2086..54b2b6c 100644
--- a/base/stringprintf_test.cpp
+++ b/base/stringprintf_test.cpp
@@ -20,11 +20,14 @@
#include <string>
+// The z size sepcifier isn't supported on Windows, so this test isn't useful.
+#if !defined(_WIN32)
TEST(StringPrintfTest, HexSizeT) {
size_t size = 0x00107e59;
EXPECT_EQ("00107e59", android::base::StringPrintf("%08zx", size));
EXPECT_EQ("0x00107e59", android::base::StringPrintf("0x%08zx", size));
}
+#endif
TEST(StringPrintfTest, StringAppendF) {
std::string s("a");
diff --git a/base/strings.cpp b/base/strings.cpp
index d3375d9..bac983b 100644
--- a/base/strings.cpp
+++ b/base/strings.cpp
@@ -79,25 +79,10 @@
return s.substr(start_index, end_index - start_index + 1);
}
-template <typename StringT>
-std::string Join(const std::vector<StringT>& strings, char separator) {
- if (strings.empty()) {
- return "";
- }
-
- std::string result(strings[0]);
- for (size_t i = 1; i < strings.size(); ++i) {
- result += separator;
- result += strings[i];
- }
- return result;
-}
-
-// Explicit instantiations.
-template std::string Join<std::string>(const std::vector<std::string>& strings,
- char separator);
-template std::string Join<const char*>(const std::vector<const char*>& strings,
- char separator);
+// These cases are probably the norm, so we mark them extern in the header to
+// aid compile time and binary size.
+template std::string Join(const std::vector<std::string>&, char);
+template std::string Join(const std::vector<const char*>&, char);
bool StartsWith(const std::string& s, const char* prefix) {
return s.compare(0, strlen(prefix), prefix) == 0;
diff --git a/base/strings_test.cpp b/base/strings_test.cpp
index 46a1ab5..5f67575 100644
--- a/base/strings_test.cpp
+++ b/base/strings_test.cpp
@@ -20,6 +20,8 @@
#include <string>
#include <vector>
+#include <set>
+#include <unordered_set>
TEST(strings, split_empty) {
std::vector<std::string> parts = android::base::Split("", ",");
@@ -121,6 +123,17 @@
ASSERT_EQ(",,,", android::base::Join(list, ','));
}
+TEST(strings, join_simple_ints) {
+ std::set<int> list = {1, 2, 3};
+ ASSERT_EQ("1,2,3", android::base::Join(list, ','));
+}
+
+TEST(strings, join_unordered_set) {
+ std::unordered_set<int> list = {1, 2};
+ ASSERT_TRUE("1,2" == android::base::Join(list, ',') ||
+ "2,1" == android::base::Join(list, ','));
+}
+
TEST(strings, startswith_empty) {
ASSERT_FALSE(android::base::StartsWith("", "foo"));
ASSERT_TRUE(android::base::StartsWith("", ""));
diff --git a/base/test_utils.cpp b/base/test_utils.cpp
index 1f6d3cf..0517bc7 100644
--- a/base/test_utils.cpp
+++ b/base/test_utils.cpp
@@ -16,15 +16,26 @@
#include "test_utils.h"
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
+#include <sys/stat.h>
#include <unistd.h>
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+
TemporaryFile::TemporaryFile() {
+#if defined(__ANDROID__)
init("/data/local/tmp");
- if (fd == -1) {
- init("/tmp");
- }
+#elif defined(_WIN32)
+ char wd[MAX_PATH] = {};
+ _getcwd(wd, sizeof(wd));
+ init(wd);
+#else
+ init("/tmp");
+#endif
}
TemporaryFile::~TemporaryFile() {
@@ -34,5 +45,15 @@
void TemporaryFile::init(const char* tmp_dir) {
snprintf(filename, sizeof(filename), "%s/TemporaryFile-XXXXXX", tmp_dir);
+#if !defined(_WIN32)
fd = mkstemp(filename);
+#else
+ // Windows doesn't have mkstemp, and tmpfile creates the file in the root
+ // directory, requiring root (?!) permissions. We have to settle for mktemp.
+ if (mktemp(filename) == nullptr) {
+ abort();
+ }
+
+ fd = open(filename, O_RDWR | O_NOINHERIT | O_CREAT, _S_IREAD | _S_IWRITE);
+#endif
}
diff --git a/fastboot/engineering_key.p12 b/fastboot/engineering_key.p12
deleted file mode 100644
index d8183b0..0000000
--- a/fastboot/engineering_key.p12
+++ /dev/null
Binary files differ
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 6724d05..be80cce 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -406,6 +406,35 @@
return data;
}
+#if defined(_WIN32)
+
+// TODO: move this to somewhere it can be shared.
+
+#include <windows.h>
+
+// Windows' tmpfile(3) requires administrator rights because
+// it creates temporary files in the root directory.
+static FILE* win32_tmpfile() {
+ char temp_path[PATH_MAX];
+ DWORD nchars = GetTempPath(sizeof(temp_path), temp_path);
+ if (nchars == 0 || nchars >= sizeof(temp_path)) {
+ fprintf(stderr, "GetTempPath failed, error %ld\n", GetLastError());
+ return nullptr;
+ }
+
+ char filename[PATH_MAX];
+ if (GetTempFileName(temp_path, "fastboot", 0, filename) == 0) {
+ fprintf(stderr, "GetTempFileName failed, error %ld\n", GetLastError());
+ return nullptr;
+ }
+
+ return fopen(filename, "w+bTD");
+}
+
+#define tmpfile win32_tmpfile
+
+#endif
+
static int unzip_to_file(ZipArchiveHandle zip, char* entry_name) {
FILE* fp = tmpfile();
if (fp == NULL) {
diff --git a/fastboot/p12topem.sh b/fastboot/p12topem.sh
deleted file mode 100755
index f081eb5..0000000
--- a/fastboot/p12topem.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-if [ $# -ne 2 ]
-then
- echo "Usage: $0 alias passphrase"
- exit -1
-fi
-
-openssl pkcs12 -passin pass:"$2" -passout pass:"$2" -in $1.p12 -out $1.pem
diff --git a/fastboot/signfile.sh b/fastboot/signfile.sh
deleted file mode 100755
index 3188d2d..0000000
--- a/fastboot/signfile.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-
-if [ $# -ne 3 ]
-then
- echo "Usage: $0 alias filename passpharse"
- exit -1
-fi
-
-openssl dgst -passin pass:"$3" -binary -sha1 -sign $1.pem $2 > $2.sign
-
diff --git a/fs_mgr/fs_mgr_verity.c b/fs_mgr/fs_mgr_verity.c
index cc8c57e..81c7c9a 100644
--- a/fs_mgr/fs_mgr_verity.c
+++ b/fs_mgr/fs_mgr_verity.c
@@ -934,10 +934,6 @@
struct dm_ioctl *io = (struct dm_ioctl *) buffer;
char *mount_point = basename(fstab->mount_point);
- // set the dm_ioctl flags
- io->flags |= 1;
- io->target_count = 1;
-
// get verity filesystem size
if (get_fs_size(fstab->fs_type, fstab->blk_device, &device_size) < 0) {
return retval;
diff --git a/init/Android.mk b/init/Android.mk
index de065dc..f154cc3 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -5,9 +5,9 @@
# --
ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
-init_options += -DALLOW_LOCAL_PROP_OVERRIDE=1 -DALLOW_DISABLE_SELINUX=1
+init_options += -DALLOW_LOCAL_PROP_OVERRIDE=1 -DALLOW_PERMISSIVE_SELINUX=1
else
-init_options += -DALLOW_LOCAL_PROP_OVERRIDE=0 -DALLOW_DISABLE_SELINUX=0
+init_options += -DALLOW_LOCAL_PROP_OVERRIDE=0 -DALLOW_PERMISSIVE_SELINUX=0
endif
init_options += -DLOG_UEVENTS=0
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 9e5f9ff..ca31c50 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -591,7 +591,13 @@
int do_trigger(int nargs, char **args)
{
- action_for_each_trigger(args[1], action_add_queue_tail);
+ char prop_val[PROP_VALUE_MAX];
+ int res = expand_props(prop_val, args[1], sizeof(prop_val));
+ if (res) {
+ ERROR("trigger: cannot expand '%s'\n", args[1]);
+ return -EINVAL;
+ }
+ action_for_each_trigger(prop_val, action_add_queue_tail);
return 0;
}
diff --git a/init/init.cpp b/init/init.cpp
index 85d7909..2500985 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -43,6 +43,7 @@
#include <base/file.h>
#include <base/stringprintf.h>
+#include <base/strings.h>
#include <cutils/android_reboot.h>
#include <cutils/fs.h>
#include <cutils/iosched_policy.h>
@@ -205,16 +206,15 @@
return;
}
- struct stat s;
- if (stat(svc->args[0], &s) != 0) {
- ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name);
+ struct stat sb;
+ if (stat(svc->args[0], &sb) == -1) {
+ ERROR("cannot find '%s' (%s), disabling '%s'\n", svc->args[0], strerror(errno), svc->name);
svc->flags |= SVC_DISABLED;
return;
}
if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) {
- ERROR("service '%s' must be one-shot to use dynamic args, disabling\n",
- svc->args[0]);
+ ERROR("service '%s' must be one-shot to use dynamic args, disabling\n", svc->args[0]);
svc->flags |= SVC_DISABLED;
return;
}
@@ -750,36 +750,20 @@
return 0;
}
-static void import_kernel_nv(char *name, bool for_emulator)
-{
- char *value = strchr(name, '=');
- int name_len = strlen(name);
-
- if (value == 0) return;
- *value++ = 0;
- if (name_len == 0) return;
+static void import_kernel_nv(const std::string& key, const std::string& value, bool for_emulator) {
+ if (key.empty()) return;
if (for_emulator) {
- /* in the emulator, export any kernel option with the
- * ro.kernel. prefix */
- char buff[PROP_NAME_MAX];
- int len = snprintf( buff, sizeof(buff), "ro.kernel.%s", name );
-
- if (len < (int)sizeof(buff))
- property_set( buff, value );
+ // In the emulator, export any kernel option with the "ro.kernel." prefix.
+ property_set(android::base::StringPrintf("ro.kernel.%s", key.c_str()).c_str(), value.c_str());
return;
}
- if (!strcmp(name,"qemu")) {
- strlcpy(qemu, value, sizeof(qemu));
- } else if (!strncmp(name, "androidboot.", 12) && name_len > 12) {
- const char *boot_prop_name = name + 12;
- char prop[PROP_NAME_MAX];
- int cnt;
-
- cnt = snprintf(prop, sizeof(prop), "ro.boot.%s", boot_prop_name);
- if (cnt < PROP_NAME_MAX)
- property_set(prop, value);
+ if (key == "qemu") {
+ strlcpy(qemu, value.c_str(), sizeof(qemu));
+ } else if (android::base::StartsWith(key, "androidboot.")) {
+ property_set(android::base::StringPrintf("ro.boot.%s", key.c_str() + 12).c_str(),
+ value.c_str());
}
}
@@ -803,8 +787,7 @@
}
}
-static void process_kernel_dt(void)
-{
+static void process_kernel_dt() {
static const char android_dir[] = "/proc/device-tree/firmware/android";
std::string file_name = android::base::StringPrintf("%s/compatible", android_dir);
@@ -817,13 +800,13 @@
}
std::unique_ptr<DIR, int(*)(DIR*)>dir(opendir(android_dir), closedir);
- if (!dir)
- return;
+ if (!dir) return;
struct dirent *dp;
while ((dp = readdir(dir.get())) != NULL) {
- if (dp->d_type != DT_REG || !strcmp(dp->d_name, "compatible"))
+ if (dp->d_type != DT_REG || !strcmp(dp->d_name, "compatible")) {
continue;
+ }
file_name = android::base::StringPrintf("%s/%s", android_dir, dp->d_name);
@@ -835,18 +818,15 @@
}
}
-static void process_kernel_cmdline(void)
-{
- /* don't expose the raw commandline to nonpriv processes */
+static void process_kernel_cmdline() {
+ // Don't expose the raw commandline to unprivileged processes.
chmod("/proc/cmdline", 0440);
- /* first pass does the common stuff, and finds if we are in qemu.
- * second pass is only necessary for qemu to export all kernel params
- * as props.
- */
+ // The first pass does the common stuff, and finds if we are in qemu.
+ // The second pass is only necessary for qemu to export all kernel params
+ // as properties.
import_kernel_cmdline(false, import_kernel_nv);
- if (qemu[0])
- import_kernel_cmdline(true, import_kernel_nv);
+ if (qemu[0]) import_kernel_cmdline(true, import_kernel_nv);
}
static int queue_property_triggers_action(int nargs, char **args)
@@ -864,46 +844,23 @@
sehandle_prop = selinux_android_prop_context_handle();
}
-enum selinux_enforcing_status { SELINUX_DISABLED, SELINUX_PERMISSIVE, SELINUX_ENFORCING };
+enum selinux_enforcing_status { SELINUX_PERMISSIVE, SELINUX_ENFORCING };
static selinux_enforcing_status selinux_status_from_cmdline() {
selinux_enforcing_status status = SELINUX_ENFORCING;
- std::function<void(char*,bool)> fn = [&](char* name, bool in_qemu) {
- char *value = strchr(name, '=');
- if (value == nullptr) { return; }
- *value++ = '\0';
- if (strcmp(name, "androidboot.selinux") == 0) {
- if (strcmp(value, "disabled") == 0) {
- status = SELINUX_DISABLED;
- } else if (strcmp(value, "permissive") == 0) {
- status = SELINUX_PERMISSIVE;
- }
+ import_kernel_cmdline(false, [&](const std::string& key, const std::string& value, bool in_qemu) {
+ if (key == "androidboot.selinux" && value == "permissive") {
+ status = SELINUX_PERMISSIVE;
}
- };
- import_kernel_cmdline(false, fn);
+ });
return status;
}
-
-static bool selinux_is_disabled(void)
-{
- if (ALLOW_DISABLE_SELINUX) {
- if (access("/sys/fs/selinux", F_OK) != 0) {
- // SELinux is not compiled into the kernel, or has been disabled
- // via the kernel command line "selinux=0".
- return true;
- }
- return selinux_status_from_cmdline() == SELINUX_DISABLED;
- }
-
- return false;
-}
-
static bool selinux_is_enforcing(void)
{
- if (ALLOW_DISABLE_SELINUX) {
+ if (ALLOW_PERMISSIVE_SELINUX) {
return selinux_status_from_cmdline() == SELINUX_ENFORCING;
}
return true;
@@ -911,10 +868,6 @@
int selinux_reload_policy(void)
{
- if (selinux_is_disabled()) {
- return -1;
- }
-
INFO("SELinux: Attempting to reload policy files\n");
if (selinux_android_reload_policy() == -1) {
@@ -951,10 +904,6 @@
cb.func_audit = audit_callback;
selinux_set_callback(SELINUX_CB_AUDIT, cb);
- if (selinux_is_disabled()) {
- return;
- }
-
if (in_kernel_domain) {
INFO("Loading SELinux policy...\n");
if (selinux_android_load_policy() < 0) {
@@ -962,8 +911,15 @@
security_failure();
}
+ bool kernel_enforcing = (security_getenforce() == 1);
bool is_enforcing = selinux_is_enforcing();
- security_setenforce(is_enforcing);
+ if (kernel_enforcing != is_enforcing) {
+ if (security_setenforce(is_enforcing)) {
+ ERROR("security_setenforce(%s) failed: %s\n",
+ is_enforcing ? "true" : "false", strerror(errno));
+ security_failure();
+ }
+ }
if (write_file("/sys/fs/selinux/checkreqprot", "0") == -1) {
security_failure();
@@ -1011,7 +967,7 @@
klog_init();
klog_set_level(KLOG_NOTICE_LEVEL);
- NOTICE("init%s started!\n", is_first_stage ? "" : " second stage");
+ NOTICE("init %s started!\n", is_first_stage ? "first stage" : "second stage");
if (!is_first_stage) {
// Indicate that booting is in progress to background fw loaders, etc.
@@ -1024,7 +980,7 @@
process_kernel_dt();
process_kernel_cmdline();
- // Propogate the kernel variables to internal variables
+ // Propagate the kernel variables to internal variables
// used by init as well as the current required properties.
export_kernel_boot_props();
}
@@ -1050,7 +1006,7 @@
// These directories were necessarily created before initial policy load
// and therefore need their security context restored to the proper value.
// This must happen before /dev is populated by ueventd.
- INFO("Running restorecon...\n");
+ NOTICE("Running restorecon...\n");
restorecon("/dev");
restorecon("/dev/socket");
restorecon("/dev/__properties__");
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index 385b37b..f975b6c 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -426,22 +426,20 @@
parser_done:
list_for_each(node, &import_list) {
- struct import *import = node_to_item(node, struct import, list);
- int ret;
-
- ret = init_parse_config_file(import->filename);
- if (ret)
- ERROR("could not import file '%s' from '%s'\n",
- import->filename, fn);
+ struct import* import = node_to_item(node, struct import, list);
+ if (!init_parse_config_file(import->filename)) {
+ ERROR("could not import file '%s' from '%s': %s\n",
+ import->filename, fn, strerror(errno));
+ }
}
}
-int init_parse_config_file(const char* path) {
+bool init_parse_config_file(const char* path) {
INFO("Parsing %s...\n", path);
Timer t;
std::string data;
if (!read_file(path, &data)) {
- return -1;
+ return false;
}
data.push_back('\n'); // TODO: fix parse_config.
@@ -449,7 +447,7 @@
dump_parser_state();
NOTICE("(Parsing %s took %.2fs.)\n", path, t.duration());
- return 0;
+ return true;
}
static int valid_name(const char *name)
diff --git a/init/init_parser.h b/init/init_parser.h
index 6348607..90f880f 100644
--- a/init/init_parser.h
+++ b/init/init_parser.h
@@ -31,7 +31,7 @@
void queue_all_property_triggers();
void queue_builtin_action(int (*func)(int nargs, char **args), const char *name);
-int init_parse_config_file(const char *fn);
+bool init_parse_config_file(const char* path);
int expand_props(char *dst, const char *src, int len);
service* make_exec_oneshot_service(int argc, char** argv);
diff --git a/init/log.cpp b/init/log.cpp
index d32f2da..eb5ec42 100644
--- a/init/log.cpp
+++ b/init/log.cpp
@@ -14,30 +14,35 @@
* limitations under the License.
*/
+#include "log.h"
+
#include <stdlib.h>
#include <string.h>
#include <sys/uio.h>
#include <selinux/selinux.h>
-#include "log.h"
+#include <base/stringprintf.h>
static void init_klog_vwrite(int level, const char* fmt, va_list ap) {
static const char* tag = basename(getprogname());
- char prefix[64];
- snprintf(prefix, sizeof(prefix), "<%d>%s: ", level, tag);
+ // The kernel's printk buffer is only 1024 bytes.
+ // TODO: should we automatically break up long lines into multiple lines?
+ // Or we could log but with something like "..." at the end?
+ char buf[1024];
+ size_t prefix_size = snprintf(buf, sizeof(buf), "<%d>%s: ", level, tag);
+ size_t msg_size = vsnprintf(buf + prefix_size, sizeof(buf) - prefix_size, fmt, ap);
+ if (msg_size >= sizeof(buf) - prefix_size) {
+ msg_size = snprintf(buf + prefix_size, sizeof(buf) - prefix_size,
+ "(%zu-byte message too long for printk)\n", msg_size);
+ }
- char msg[512];
- vsnprintf(msg, sizeof(msg), fmt, ap);
+ iovec iov[1];
+ iov[0].iov_base = buf;
+ iov[0].iov_len = prefix_size + msg_size;
- iovec iov[2];
- iov[0].iov_base = prefix;
- iov[0].iov_len = strlen(prefix);
- iov[1].iov_base = msg;
- iov[1].iov_len = strlen(msg);
-
- klog_writev(level, iov, 2);
+ klog_writev(level, iov, 1);
}
void init_klog_write(int level, const char* fmt, ...) {
diff --git a/init/util.cpp b/init/util.cpp
index a5392c6..c647fb3 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -33,6 +33,7 @@
#include <sys/un.h>
#include <base/file.h>
+#include <base/strings.h>
/* for ANDROID_SOCKET_* */
#include <cutils/sockets.h>
@@ -401,32 +402,16 @@
}
}
-void import_kernel_cmdline(bool in_qemu, std::function<void(char*,bool)> import_kernel_nv)
-{
- char cmdline[2048];
- char *ptr;
- int fd;
+void import_kernel_cmdline(bool in_qemu,
+ std::function<void(const std::string&, const std::string&, bool)> fn) {
+ std::string cmdline;
+ android::base::ReadFileToString("/proc/cmdline", &cmdline);
- fd = open("/proc/cmdline", O_RDONLY | O_CLOEXEC);
- if (fd >= 0) {
- int n = read(fd, cmdline, sizeof(cmdline) - 1);
- if (n < 0) n = 0;
-
- /* get rid of trailing newline, it happens */
- if (n > 0 && cmdline[n-1] == '\n') n--;
-
- cmdline[n] = 0;
- close(fd);
- } else {
- cmdline[0] = 0;
- }
-
- ptr = cmdline;
- while (ptr && *ptr) {
- char *x = strchr(ptr, ' ');
- if (x != 0) *x++ = 0;
- import_kernel_nv(ptr, in_qemu);
- ptr = x;
+ for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) {
+ std::vector<std::string> pieces = android::base::Split(entry, "=");
+ if (pieces.size() == 2) {
+ fn(pieces[0], pieces[1], in_qemu);
+ }
}
}
diff --git a/init/util.h b/init/util.h
index 09d64cd..30db2c4 100644
--- a/init/util.h
+++ b/init/util.h
@@ -58,7 +58,8 @@
void remove_link(const char *oldpath, const char *newpath);
int wait_for_file(const char *filename, int timeout);
void open_devnull_stdio(void);
-void import_kernel_cmdline(bool in_qemu, std::function<void(char*,bool)>);
+void import_kernel_cmdline(bool in_qemu,
+ std::function<void(const std::string&, const std::string&, bool)>);
int make_dir(const char *path, mode_t mode);
int restorecon(const char *pathname);
int restorecon_recursive(const char *pathname);
diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk
index 6a689a6..be8b803 100644
--- a/libbacktrace/Android.mk
+++ b/libbacktrace/Android.mk
@@ -51,18 +51,10 @@
UnwindMap.cpp \
UnwindPtrace.cpp \
-libbacktrace_shared_libraries_target := \
- libcutils \
-
libbacktrace_shared_libraries := \
libbase \
- libunwind \
-
-libbacktrace_shared_libraries_host := \
liblog \
-
-libbacktrace_static_libraries_host := \
- libcutils \
+ libunwind \
libbacktrace_ldlibs_host := \
-lpthread \
diff --git a/libbacktrace/BacktraceMap.cpp b/libbacktrace/BacktraceMap.cpp
index b0ada46..ca47f67 100644
--- a/libbacktrace/BacktraceMap.cpp
+++ b/libbacktrace/BacktraceMap.cpp
@@ -135,7 +135,7 @@
#if defined(__APPLE__)
// Corkscrew and libunwind don't compile on the mac, so create a generic
// map object.
-BacktraceMap* BacktraceMap::Create(pid_t pid, bool uncached) {
+BacktraceMap* BacktraceMap::Create(pid_t pid, bool /*uncached*/) {
BacktraceMap* map = new BacktraceMap(pid);
if (!map->Build()) {
delete map;
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index 9dc15d1..d5a9050 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -106,9 +106,6 @@
trace-dev.c \
uevent.c \
-# arch-arm/memset32.S does not compile with Clang.
-LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
-
LOCAL_SRC_FILES_arm += arch-arm/memset32.S
LOCAL_SRC_FILES_arm64 += arch-arm64/android_memset.S
diff --git a/libcutils/arch-arm/memset32.S b/libcutils/arch-arm/memset32.S
index 6efab9f..1e89636 100644
--- a/libcutils/arch-arm/memset32.S
+++ b/libcutils/arch-arm/memset32.S
@@ -18,6 +18,8 @@
*
*/
+ .syntax unified
+
.text
.align
@@ -45,7 +47,7 @@
/* align to 32 bits */
tst r0, #2
- strneh r1, [r0], #2
+ strhne r1, [r0], #2
subne r2, r2, #2
.fnend
@@ -68,27 +70,27 @@
/* conditionally writes 0 to 7 words (length in r3) */
movs r3, r3, lsl #28
- stmcsia r0!, {r1, lr}
- stmcsia r0!, {r1, lr}
- stmmiia r0!, {r1, lr}
+ stmiacs r0!, {r1, lr}
+ stmiacs r0!, {r1, lr}
+ stmiami r0!, {r1, lr}
movs r3, r3, lsl #2
strcs r1, [r0], #4
.Laligned32:
mov r3, r1
1: subs r2, r2, #32
- stmhsia r0!, {r1,r3,r12,lr}
- stmhsia r0!, {r1,r3,r12,lr}
+ stmiahs r0!, {r1,r3,r12,lr}
+ stmiahs r0!, {r1,r3,r12,lr}
bhs 1b
add r2, r2, #32
/* conditionally stores 0 to 30 bytes */
movs r2, r2, lsl #28
- stmcsia r0!, {r1,r3,r12,lr}
- stmmiia r0!, {r1,lr}
+ stmiacs r0!, {r1,r3,r12,lr}
+ stmiami r0!, {r1,lr}
movs r2, r2, lsl #2
strcs r1, [r0], #4
- strmih lr, [r0], #2
+ strhmi lr, [r0], #2
ldr lr, [sp], #4
.cfi_def_cfa_offset 0
diff --git a/libsparse/simg_dump.py b/libsparse/simg_dump.py
index 6ece31d..c70d45f 100755
--- a/libsparse/simg_dump.py
+++ b/libsparse/simg_dump.py
@@ -135,7 +135,7 @@
break;
else:
crc_bin = FH.read(4)
- crc = struct.unpack("<I", crc)
+ crc = struct.unpack("<I", crc_bin)
print("Unverified CRC32 0x%08X" % (crc))
else:
print("Unknown chunk type 0x%04X" % (chunk_type), end="")
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index b2a9f88..d7af34e 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -473,7 +473,7 @@
return kEmptyArchive;
}
- ALOGV("+++ num_entries=%" PRIu32 "dir_size=%" PRIu32 " dir_offset=%" PRIu32,
+ ALOGV("+++ num_entries=%" PRIu32 " dir_size=%" PRIu32 " dir_offset=%" PRIu32,
eocd->num_records, eocd->cd_size, eocd->cd_start_offset);
/*
diff --git a/mkbootimg/Android.mk b/mkbootimg/Android.mk
index 0c9b0c6..8661d7d 100644
--- a/mkbootimg/Android.mk
+++ b/mkbootimg/Android.mk
@@ -2,12 +2,10 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := mkbootimg.c
-LOCAL_STATIC_LIBRARIES := libmincrypt
-LOCAL_CFLAGS := -Werror
+LOCAL_SRC_FILES := mkbootimg
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_IS_HOST_MODULE := true
LOCAL_MODULE := mkbootimg
-include $(BUILD_HOST_EXECUTABLE)
-
-$(call dist-for-goals,dist_files,$(LOCAL_BUILT_MODULE))
+include $(BUILD_PREBUILT)
diff --git a/mkbootimg/mkbootimg b/mkbootimg/mkbootimg
new file mode 100755
index 0000000..aea2585
--- /dev/null
+++ b/mkbootimg/mkbootimg
@@ -0,0 +1,140 @@
+#!/usr/bin/env python
+# Copyright 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.
+
+from __future__ import print_function
+from sys import argv, exit, stderr
+from argparse import ArgumentParser, FileType, Action
+from os import fstat
+from struct import pack
+from hashlib import sha1
+
+def filesize(f):
+ if f is None:
+ return 0
+ try:
+ return fstat(f.fileno()).st_size
+ except OSError:
+ return 0
+
+
+def update_sha(sha, f):
+ if f:
+ sha.update(f.read())
+ f.seek(0)
+ sha.update(pack('I', filesize(f)))
+ else:
+ sha.update(pack('I', 0))
+
+
+def pad_file(f, padding):
+ pad = (padding - (f.tell() & (padding - 1))) & (padding - 1)
+ f.write(pack(str(pad) + 'x'))
+
+
+def write_header(args):
+ BOOT_MAGIC = 'ANDROID!'.encode()
+ args.output.write(pack('8s', BOOT_MAGIC))
+ args.output.write(pack('8I',
+ filesize(args.kernel), # size in bytes
+ args.base + args.kernel_offset, # physical load addr
+ filesize(args.ramdisk), # size in bytes
+ args.base + args.ramdisk_offset, # physical load addr
+ filesize(args.second), # size in bytes
+ args.base + args.second_offset, # physical load addr
+ args.base + args.tags_offset, # physical addr for kernel tags
+ args.pagesize)) # flash page size we assume
+ args.output.write(pack('8x')) # future expansion: should be 0
+ args.output.write(pack('16s', args.board.encode())) # asciiz product name
+ args.output.write(pack('512s', args.cmdline[:512].encode()))
+
+ sha = sha1()
+ update_sha(sha, args.kernel)
+ update_sha(sha, args.ramdisk)
+ update_sha(sha, args.second)
+ img_id = pack('32s', sha.digest())
+
+ args.output.write(img_id)
+ args.output.write(pack('1024s', args.cmdline[512:].encode()))
+ pad_file(args.output, args.pagesize)
+ return img_id
+
+
+class ValidateStrLenAction(Action):
+ def __init__(self, option_strings, dest, nargs=None, **kwargs):
+ if 'maxlen' not in kwargs:
+ raise ValueError('maxlen must be set')
+ self.maxlen = int(kwargs['maxlen'])
+ del kwargs['maxlen']
+ super(ValidateStrLenAction, self).__init__(option_strings, dest, **kwargs)
+
+ def __call__(self, parser, namespace, values, option_string=None):
+ if len(values) > self.maxlen:
+ raise ValueError('String argument too long: max {0:d}, got {1:d}'.
+ format(self.maxlen, len(values)))
+ setattr(namespace, self.dest, values)
+
+
+def write_padded_file(f_out, f_in, padding):
+ if f_in is None:
+ return
+ f_out.write(f_in.read())
+ pad_file(f_out, padding)
+
+
+def parse_int(x):
+ return int(x, 0)
+
+
+def parse_cmdline():
+ parser = ArgumentParser()
+ parser.add_argument('--kernel', help='path to the kernel', type=FileType('rb'),
+ required=True)
+ parser.add_argument('--ramdisk', help='path to the ramdisk', type=FileType('rb'))
+ parser.add_argument('--second', help='path to the 2nd bootloader', type=FileType('rb'))
+ parser.add_argument('--cmdline', help='extra arguments to be passed on the '
+ 'kernel command line', default='', action=ValidateStrLenAction, maxlen=1536)
+ parser.add_argument('--base', help='base address', type=parse_int, default=0x10000000)
+ parser.add_argument('--kernel_offset', help='kernel offset', type=parse_int, default=0x00008000)
+ parser.add_argument('--ramdisk_offset', help='ramdisk offset', type=parse_int, default=0x01000000)
+ parser.add_argument('--second_offset', help='2nd bootloader offset', type=parse_int,
+ default=0x00f00000)
+ parser.add_argument('--tags_offset', help='tags offset', type=parse_int, default=0x00000100)
+ parser.add_argument('--board', help='board name', default='', action=ValidateStrLenAction,
+ maxlen=16)
+ parser.add_argument('--pagesize', help='page size', type=parse_int,
+ choices=[2**i for i in range(11,15)], default=2048)
+ parser.add_argument('--id', help='print the image ID on standard output',
+ action='store_true')
+ parser.add_argument('-o', '--output', help='output file name', type=FileType('wb'),
+ required=True)
+ return parser.parse_args()
+
+
+def write_data(args):
+ write_padded_file(args.output, args.kernel, args.pagesize)
+ write_padded_file(args.output, args.ramdisk, args.pagesize)
+ write_padded_file(args.output, args.second, args.pagesize)
+
+
+def main():
+ args = parse_cmdline()
+ img_id = write_header(args)
+ write_data(args)
+ if args.id:
+ print('0x' + ''.join('{:02x}'.format(ord(c)) for c in img_id))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/mkbootimg/mkbootimg.c b/mkbootimg/mkbootimg.c
deleted file mode 100644
index b6a2801..0000000
--- a/mkbootimg/mkbootimg.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/* tools/mkbootimg/mkbootimg.c
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdbool.h>
-
-#include "mincrypt/sha.h"
-#include "bootimg.h"
-
-static void *load_file(const char *fn, unsigned *_sz)
-{
- char *data;
- int sz;
- int fd;
-
- data = 0;
- fd = open(fn, O_RDONLY);
- if(fd < 0) return 0;
-
- sz = lseek(fd, 0, SEEK_END);
- if(sz < 0) goto oops;
-
- if(lseek(fd, 0, SEEK_SET) != 0) goto oops;
-
- data = (char*) malloc(sz);
- if(data == 0) goto oops;
-
- if(read(fd, data, sz) != sz) goto oops;
- close(fd);
-
- if(_sz) *_sz = sz;
- return data;
-
-oops:
- close(fd);
- if(data != 0) free(data);
- return 0;
-}
-
-int usage(void)
-{
- fprintf(stderr,"usage: mkbootimg\n"
- " --kernel <filename>\n"
- " [ --ramdisk <filename> ]\n"
- " [ --second <2ndbootloader-filename> ]\n"
- " [ --cmdline <kernel-commandline> ]\n"
- " [ --board <boardname> ]\n"
- " [ --base <address> ]\n"
- " [ --pagesize <pagesize> ]\n"
- " [ --id ]\n"
- " -o|--output <filename>\n"
- );
- return 1;
-}
-
-
-
-static unsigned char padding[16384] = { 0, };
-
-static void print_id(const uint8_t *id, size_t id_len) {
- printf("0x");
- for (unsigned i = 0; i < id_len; i++) {
- printf("%02x", id[i]);
- }
- printf("\n");
-}
-
-int write_padding(int fd, unsigned pagesize, unsigned itemsize)
-{
- unsigned pagemask = pagesize - 1;
- ssize_t count;
-
- if((itemsize & pagemask) == 0) {
- return 0;
- }
-
- count = pagesize - (itemsize & pagemask);
-
- if(write(fd, padding, count) != count) {
- return -1;
- } else {
- return 0;
- }
-}
-
-int main(int argc, char **argv)
-{
- boot_img_hdr hdr;
-
- char *kernel_fn = NULL;
- void *kernel_data = NULL;
- char *ramdisk_fn = NULL;
- void *ramdisk_data = NULL;
- char *second_fn = NULL;
- void *second_data = NULL;
- char *cmdline = "";
- char *bootimg = NULL;
- char *board = "";
- uint32_t pagesize = 2048;
- int fd;
- SHA_CTX ctx;
- const uint8_t* sha;
- uint32_t base = 0x10000000U;
- uint32_t kernel_offset = 0x00008000U;
- uint32_t ramdisk_offset = 0x01000000U;
- uint32_t second_offset = 0x00f00000U;
- uint32_t tags_offset = 0x00000100U;
- size_t cmdlen;
-
- argc--;
- argv++;
-
- memset(&hdr, 0, sizeof(hdr));
-
- bool get_id = false;
- while(argc > 0){
- char *arg = argv[0];
- if (!strcmp(arg, "--id")) {
- get_id = true;
- argc -= 1;
- argv += 1;
- } else if(argc >= 2) {
- char *val = argv[1];
- argc -= 2;
- argv += 2;
- if(!strcmp(arg, "--output") || !strcmp(arg, "-o")) {
- bootimg = val;
- } else if(!strcmp(arg, "--kernel")) {
- kernel_fn = val;
- } else if(!strcmp(arg, "--ramdisk")) {
- ramdisk_fn = val;
- } else if(!strcmp(arg, "--second")) {
- second_fn = val;
- } else if(!strcmp(arg, "--cmdline")) {
- cmdline = val;
- } else if(!strcmp(arg, "--base")) {
- base = strtoul(val, 0, 16);
- } else if(!strcmp(arg, "--kernel_offset")) {
- kernel_offset = strtoul(val, 0, 16);
- } else if(!strcmp(arg, "--ramdisk_offset")) {
- ramdisk_offset = strtoul(val, 0, 16);
- } else if(!strcmp(arg, "--second_offset")) {
- second_offset = strtoul(val, 0, 16);
- } else if(!strcmp(arg, "--tags_offset")) {
- tags_offset = strtoul(val, 0, 16);
- } else if(!strcmp(arg, "--board")) {
- board = val;
- } else if(!strcmp(arg,"--pagesize")) {
- pagesize = strtoul(val, 0, 10);
- if ((pagesize != 2048) && (pagesize != 4096)
- && (pagesize != 8192) && (pagesize != 16384)) {
- fprintf(stderr,"error: unsupported page size %d\n", pagesize);
- return -1;
- }
- } else {
- return usage();
- }
- } else {
- return usage();
- }
- }
- hdr.page_size = pagesize;
-
- hdr.kernel_addr = base + kernel_offset;
- hdr.ramdisk_addr = base + ramdisk_offset;
- hdr.second_addr = base + second_offset;
- hdr.tags_addr = base + tags_offset;
-
- if(bootimg == 0) {
- fprintf(stderr,"error: no output filename specified\n");
- return usage();
- }
-
- if(kernel_fn == 0) {
- fprintf(stderr,"error: no kernel image specified\n");
- return usage();
- }
-
- if(strlen(board) >= BOOT_NAME_SIZE) {
- fprintf(stderr,"error: board name too large\n");
- return usage();
- }
-
- strcpy((char *) hdr.name, board);
-
- memcpy(hdr.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
-
- cmdlen = strlen(cmdline);
- if(cmdlen > (BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE - 2)) {
- fprintf(stderr,"error: kernel commandline too large\n");
- return 1;
- }
- /* Even if we need to use the supplemental field, ensure we
- * are still NULL-terminated */
- strncpy((char *)hdr.cmdline, cmdline, BOOT_ARGS_SIZE - 1);
- hdr.cmdline[BOOT_ARGS_SIZE - 1] = '\0';
- if (cmdlen >= (BOOT_ARGS_SIZE - 1)) {
- cmdline += (BOOT_ARGS_SIZE - 1);
- strncpy((char *)hdr.extra_cmdline, cmdline, BOOT_EXTRA_ARGS_SIZE);
- }
-
- kernel_data = load_file(kernel_fn, &hdr.kernel_size);
- if(kernel_data == 0) {
- fprintf(stderr,"error: could not load kernel '%s'\n", kernel_fn);
- return 1;
- }
-
- if(ramdisk_fn == 0) {
- ramdisk_data = 0;
- hdr.ramdisk_size = 0;
- } else {
- ramdisk_data = load_file(ramdisk_fn, &hdr.ramdisk_size);
- if(ramdisk_data == 0) {
- fprintf(stderr,"error: could not load ramdisk '%s'\n", ramdisk_fn);
- return 1;
- }
- }
-
- if(second_fn) {
- second_data = load_file(second_fn, &hdr.second_size);
- if(second_data == 0) {
- fprintf(stderr,"error: could not load secondstage '%s'\n", second_fn);
- return 1;
- }
- }
-
- /* put a hash of the contents in the header so boot images can be
- * differentiated based on their first 2k.
- */
- SHA_init(&ctx);
- SHA_update(&ctx, kernel_data, hdr.kernel_size);
- SHA_update(&ctx, &hdr.kernel_size, sizeof(hdr.kernel_size));
- SHA_update(&ctx, ramdisk_data, hdr.ramdisk_size);
- SHA_update(&ctx, &hdr.ramdisk_size, sizeof(hdr.ramdisk_size));
- SHA_update(&ctx, second_data, hdr.second_size);
- SHA_update(&ctx, &hdr.second_size, sizeof(hdr.second_size));
- sha = SHA_final(&ctx);
- memcpy(hdr.id, sha,
- SHA_DIGEST_SIZE > sizeof(hdr.id) ? sizeof(hdr.id) : SHA_DIGEST_SIZE);
-
- fd = open(bootimg, O_CREAT | O_TRUNC | O_WRONLY, 0644);
- if(fd < 0) {
- fprintf(stderr,"error: could not create '%s'\n", bootimg);
- return 1;
- }
-
- if(write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) goto fail;
- if(write_padding(fd, pagesize, sizeof(hdr))) goto fail;
-
- if(write(fd, kernel_data, hdr.kernel_size) != (ssize_t) hdr.kernel_size) goto fail;
- if(write_padding(fd, pagesize, hdr.kernel_size)) goto fail;
-
- if(write(fd, ramdisk_data, hdr.ramdisk_size) != (ssize_t) hdr.ramdisk_size) goto fail;
- if(write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail;
-
- if(second_data) {
- if(write(fd, second_data, hdr.second_size) != (ssize_t) hdr.second_size) goto fail;
- if(write_padding(fd, pagesize, hdr.second_size)) goto fail;
- }
-
- if (get_id) {
- print_id((uint8_t *) hdr.id, sizeof(hdr.id));
- }
-
- return 0;
-
-fail:
- unlink(bootimg);
- close(fd);
- fprintf(stderr,"error: failed writing '%s': %s\n", bootimg,
- strerror(errno));
- return 1;
-}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 2fbac23..ec30ac8 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -229,14 +229,13 @@
# We restorecon /data in case the userdata partition has been reset.
restorecon /data
- # Emulated internal storage area
- mkdir /data/media 0770 media_rw media_rw
-
# Make sure we have the device encryption key
start logd
start vold
installkey /data
+ # Emulated internal storage area
+ mkdir /data/media 0770 media_rw media_rw
# Start bootcharting as soon as possible after the data partition is
# mounted to collect more data.
mkdir /data/bootchart 0755 shell shell
@@ -271,7 +270,6 @@
chmod 0660 /data/misc/wifi/wpa_supplicant.conf
mkdir /data/local 0751 root root
mkdir /data/misc/media 0700 media media
- mkdir /data/misc/vold 0700 root root
# For security reasons, /data/local/tmp should always be empty.
# Do not place files or directories in /data/local/tmp