Merge "Improving the time to wait for assigning IP address"
diff --git a/adb/Android.mk b/adb/Android.mk
index adad69f..8d38077 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -17,14 +17,14 @@
# small by moving common files into a static library. Hopefully some day we can
# get enough of adb in here that we no longer need minadb. https://b/17626262
LIBADB_SRC_FILES := \
- adb.c \
- adb_auth.c \
+ adb.cpp \
+ adb_auth.cpp \
adb_io.cpp \
- adb_listeners.c \
- sockets.c \
- transport.c \
- transport_local.c \
- transport_usb.c \
+ adb_listeners.cpp \
+ sockets.cpp \
+ transport.cpp \
+ transport_local.cpp \
+ transport_usb.cpp \
LIBADB_CFLAGS := \
-Wall -Werror \
@@ -32,9 +32,20 @@
-Wno-missing-field-initializers \
-fvisibility=hidden \
-LIBADB_darwin_SRC_FILES := fdevent.cpp get_my_path_darwin.c usb_osx.c
-LIBADB_linux_SRC_FILES := fdevent.cpp get_my_path_linux.c usb_linux.c
-LIBADB_windows_SRC_FILES := get_my_path_windows.c sysdeps_win32.c usb_windows.c
+LIBADB_darwin_SRC_FILES := \
+ fdevent.cpp \
+ get_my_path_darwin.c \
+ usb_osx.c \
+
+LIBADB_linux_SRC_FILES := \
+ fdevent.cpp \
+ get_my_path_linux.cpp \
+ usb_linux.cpp \
+
+LIBADB_windows_SRC_FILES := \
+ get_my_path_windows.cpp \
+ sysdeps_win32.c \
+ usb_windows.cpp \
include $(CLEAR_VARS)
LOCAL_CLANG := $(ADB_CLANG)
@@ -42,10 +53,10 @@
LOCAL_CFLAGS := $(LIBADB_CFLAGS) -DADB_HOST=0
LOCAL_SRC_FILES := \
$(LIBADB_SRC_FILES) \
- adb_auth_client.c \
+ adb_auth_client.cpp \
fdevent.cpp \
- jdwp_service.c \
- qemu_tracing.c \
+ jdwp_service.cpp \
+ qemu_tracing.cpp \
usb_linux_client.c \
include $(BUILD_STATIC_LIBRARY)
@@ -57,7 +68,7 @@
LOCAL_SRC_FILES := \
$(LIBADB_SRC_FILES) \
$(LIBADB_$(HOST_OS)_SRC_FILES) \
- adb_auth_host.c \
+ adb_auth_host.cpp \
# 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.
@@ -79,20 +90,19 @@
LOCAL_CFLAGS := -DADB_HOST=0 $(LIBADB_CFLAGS)
LOCAL_SRC_FILES := $(LIBADB_TEST_SRCS)
LOCAL_STATIC_LIBRARIES := libadbd
-LOCAL_SHARED_LIBRARIES := liblog libcutils libutils
+LOCAL_SHARED_LIBRARIES := liblog libbase libcutils
include $(BUILD_NATIVE_TEST)
include $(CLEAR_VARS)
LOCAL_CLANG := $(ADB_CLANG)
LOCAL_MODULE := adb_test
LOCAL_CFLAGS := -DADB_HOST=1 $(LIBADB_CFLAGS)
-LOCAL_SRC_FILES := $(LIBADB_TEST_SRCS) services.c
-LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SRC_FILES := $(LIBADB_TEST_SRCS) services.cpp
+LOCAL_SHARED_LIBRARIES := liblog libbase
LOCAL_STATIC_LIBRARIES := \
libadb \
libcrypto_static \
libcutils \
- libutils \
ifeq ($(HOST_OS),linux)
LOCAL_LDLIBS += -lrt -ldl -lpthread
@@ -126,16 +136,12 @@
LOCAL_CLANG := $(ADB_CLANG)
LOCAL_SRC_FILES := \
- adb_main.c \
- console.c \
- commandline.c \
- adb_client.c \
- services.c \
- file_sync_client.c \
-
-ifneq ($(USE_SYSDEPS_WIN32),)
- LOCAL_SRC_FILES += sysdeps_win32.c
-endif
+ adb_main.cpp \
+ console.cpp \
+ commandline.cpp \
+ adb_client.cpp \
+ services.cpp \
+ file_sync_client.cpp \
LOCAL_CFLAGS += \
-Wall -Werror \
@@ -148,12 +154,11 @@
LOCAL_STATIC_LIBRARIES := \
libadb \
- libzipfile \
libcrypto_static \
$(EXTRA_STATIC_LIBS) \
ifeq ($(USE_SYSDEPS_WIN32),)
- LOCAL_STATIC_LIBRARIES += libcutils
+ LOCAL_STATIC_LIBRARIES += libcutils
endif
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
@@ -176,25 +181,25 @@
LOCAL_CLANG := $(ADB_CLANG)
LOCAL_SRC_FILES := \
- adb_main.c \
- services.c \
- file_sync_service.c \
- framebuffer_service.c \
- remount_service.c \
- set_verity_enable_state_service.c \
+ adb_main.cpp \
+ services.cpp \
+ file_sync_service.cpp \
+ framebuffer_service.cpp \
+ remount_service.cpp \
+ set_verity_enable_state_service.cpp \
LOCAL_CFLAGS := \
- -O2 \
- -g \
- -DADB_HOST=0 \
- -D_GNU_SOURCE \
- -Wall -Wno-unused-parameter -Werror -Wno-deprecated-declarations \
+ -DADB_HOST=0 \
+ -D_GNU_SOURCE \
+ -Wall -Werror \
+ -Wno-unused-parameter \
+ -Wno-deprecated-declarations \
ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
LOCAL_CFLAGS += -DALLOW_ADBD_ROOT=1
endif
-ifneq (,$(filter userdebug,$(TARGET_BUILD_VARIANT)))
+ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=1
endif
diff --git a/adb/adb.c b/adb/adb.cpp
similarity index 97%
rename from adb/adb.c
rename to adb/adb.cpp
index 5f244a5..ffa93f4 100644
--- a/adb/adb.c
+++ b/adb/adb.cpp
@@ -140,10 +140,13 @@
}
}
-apacket *get_apacket(void)
+apacket* get_apacket(void)
{
- apacket *p = malloc(sizeof(apacket));
- if(p == 0) fatal("failed to allocate an apacket");
+ apacket* p = reinterpret_cast<apacket*>(malloc(sizeof(apacket)));
+ if (p == nullptr) {
+ fatal("failed to allocate an apacket");
+ }
+
memset(p, 0, sizeof(apacket) - MAX_PAYLOAD);
return p;
}
@@ -293,7 +296,7 @@
}
#if ADB_HOST
-static char *connection_state_name(atransport *t)
+static const char* connection_state_name(atransport *t)
{
if (t == NULL) {
return "unknown";
@@ -713,8 +716,8 @@
// Create the list of forward redirections.
int buffer_size = format_listeners(NULL, 0);
// Add one byte for the trailing zero.
- char* buffer = malloc(buffer_size + 1);
- if (buffer == NULL) {
+ char* buffer = reinterpret_cast<char*>(malloc(buffer_size + 1));
+ if (buffer == nullptr) {
sendfailmsg(reply_fd, "not enough memory");
return 1;
}
@@ -740,7 +743,7 @@
if (!strncmp(service, "forward:",8) ||
!strncmp(service, "killforward:",12)) {
- char *local, *remote, *err;
+ char *local, *remote;
int r;
atransport *transport;
@@ -777,6 +780,7 @@
}
}
+ const char* err;
transport = acquire_one_transport(CS_ANY, ttype, serial, &err);
if (!transport) {
sendfailmsg(reply_fd, err);
@@ -835,7 +839,6 @@
// "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"))) {
- char* error_string = "unknown failure";
transport_type type = kTransportAny;
if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
@@ -849,6 +852,7 @@
serial = service;
}
+ const char* error_string = "unknown failure";
transport = acquire_one_transport(CS_ANY, type, serial, &error_string);
if (transport) {
@@ -911,8 +915,8 @@
}
if(!strncmp(service,"get-serialno",strlen("get-serialno"))) {
- char *out = "unknown";
- transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
+ const char *out = "unknown";
+ transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
if (transport && transport->serial) {
out = transport->serial;
}
@@ -920,8 +924,8 @@
return 0;
}
if(!strncmp(service,"get-devpath",strlen("get-devpath"))) {
- char *out = "unknown";
- transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
+ const char *out = "unknown";
+ transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
if (transport && transport->devpath) {
out = transport->devpath;
}
@@ -938,7 +942,7 @@
if(!strncmp(service,"get-state",strlen("get-state"))) {
transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
- char *state = connection_state_name(transport);
+ const char *state = connection_state_name(transport);
send_msg_with_okay(reply_fd, state, strlen(state));
return 0;
}
diff --git a/adb/adb.h b/adb/adb.h
index 9a68871..749515c 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -239,8 +239,8 @@
fdevent fde;
int fd;
- const char *local_name;
- const char *connect_to;
+ char *local_name;
+ char *connect_to;
atransport *transport;
adisconnect disconnect;
};
@@ -298,9 +298,6 @@
#if !ADB_HOST
void framebuffer_service(int fd, void *cookie);
-// Allow enable-verity to write to system and vendor block devices
-int make_block_device_writable(const char* dev);
-void remount_service(int fd, void *cookie);
void set_verity_enabled_state_service(int fd, void* cookie);
#endif
@@ -348,7 +345,7 @@
int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol);
#endif
-int adb_commandline(int argc, char **argv);
+int adb_commandline(int argc, const char **argv);
int connection_state(atransport *t);
diff --git a/adb/adb_auth.c b/adb/adb_auth.cpp
similarity index 100%
rename from adb/adb_auth.c
rename to adb/adb_auth.cpp
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index cece5e3..e0425ad 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -23,7 +23,6 @@
extern int auth_enabled;
-void adb_auth_init(void);
int adb_auth_keygen(const char* filename);
void adb_auth_verified(atransport *t);
@@ -40,7 +39,9 @@
#if ADB_HOST
-int adb_auth_sign(void *key, void *token, size_t token_size, void *sig);
+void adb_auth_init(void);
+int adb_auth_sign(void *key, const unsigned char* token, size_t token_size,
+ unsigned char* sig);
void *adb_auth_nextkey(void *current);
int adb_auth_get_userkey(unsigned char *data, size_t len);
@@ -50,12 +51,17 @@
#else // !ADB_HOST
-static inline int adb_auth_sign(void* key, void *token, size_t token_size, void *sig) { return 0; }
+static inline int adb_auth_sign(void* key, const unsigned char* token,
+ size_t token_size, unsigned char* sig) {
+ return 0;
+}
static inline void *adb_auth_nextkey(void *current) { return NULL; }
static inline int adb_auth_get_userkey(unsigned char *data, size_t len) { return 0; }
+void adbd_auth_init(void);
+void adbd_cloexec_auth_socket();
int adb_auth_generate_token(void *token, size_t token_size);
-int adb_auth_verify(void *token, void *sig, int siglen);
+int adb_auth_verify(uint8_t* token, uint8_t* sig, int siglen);
void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t);
#endif // ADB_HOST
diff --git a/adb/adb_auth_client.c b/adb/adb_auth_client.cpp
similarity index 89%
rename from adb/adb_auth_client.c
rename to adb/adb_auth_client.cpp
index 7be883c..5dadcd9 100644
--- a/adb/adb_auth_client.c
+++ b/adb/adb_auth_client.cpp
@@ -37,7 +37,7 @@
RSAPublicKey key;
};
-static char *key_paths[] = {
+static const char *key_paths[] = {
"/adb_keys",
"/data/misc/adb/adb_keys",
NULL
@@ -53,7 +53,6 @@
static void read_keys(const char *file, struct listnode *list)
{
- struct adb_public_key *key;
FILE *f;
char buf[MAX_PAYLOAD];
char *sep;
@@ -67,8 +66,9 @@
while (fgets(buf, sizeof(buf), f)) {
/* Allocate 4 extra bytes to decode the base64 data in-place */
- key = calloc(1, sizeof(*key) + 4);
- if (!key) {
+ auto key = reinterpret_cast<adb_public_key*>(
+ calloc(1, sizeof(adb_public_key) + 4));
+ if (key == nullptr) {
D("Can't malloc key\n");
break;
}
@@ -109,8 +109,8 @@
static void load_keys(struct listnode *list)
{
- char *path;
- char **paths = key_paths;
+ const char* path;
+ const char** paths = key_paths;
struct stat buf;
list_init(list);
@@ -138,10 +138,9 @@
return ret * token_size;
}
-int adb_auth_verify(void *token, void *sig, int siglen)
+int adb_auth_verify(uint8_t* token, uint8_t* sig, int siglen)
{
struct listnode *item;
- struct adb_public_key *key;
struct listnode key_list;
int ret = 0;
@@ -151,7 +150,7 @@
load_keys(&key_list);
list_for_each(item, &key_list) {
- key = node_to_item(item, struct adb_public_key, node);
+ adb_public_key* key = node_to_item(item, struct adb_public_key, node);
ret = RSA_verify(&key->key, sig, siglen, token, SHA_DIGEST_SIZE);
if (ret)
break;
@@ -250,19 +249,23 @@
}
}
-void adb_auth_init(void)
-{
- int fd, ret;
-
- fd = android_get_control_socket("adbd");
- if (fd < 0) {
+void adbd_cloexec_auth_socket() {
+ int fd = android_get_control_socket("adbd");
+ if (fd == -1) {
D("Failed to get adbd socket\n");
return;
}
fcntl(fd, F_SETFD, FD_CLOEXEC);
+}
- ret = listen(fd, 4);
- if (ret < 0) {
+void adbd_auth_init(void) {
+ int fd = android_get_control_socket("adbd");
+ if (fd == -1) {
+ D("Failed to get adbd socket\n");
+ return;
+ }
+
+ if (listen(fd, 4) == -1) {
D("Failed to listen on '%d'\n", fd);
return;
}
diff --git a/adb/adb_auth_host.c b/adb/adb_auth_host.cpp
similarity index 91%
rename from adb/adb_auth_host.c
rename to adb/adb_auth_host.cpp
index 1d48667..aba23d4 100644
--- a/adb/adb_auth_host.c
+++ b/adb/adb_auth_host.cpp
@@ -157,7 +157,7 @@
RSAPublicKey pkey;
FILE *outfile = NULL;
char path[PATH_MAX], info[MAX_PAYLOAD];
- uint8_t *encoded = NULL;
+ uint8_t* encoded = nullptr;
size_t encoded_length;
int ret = 0;
@@ -191,8 +191,8 @@
encoded_length = 1 + ((sizeof(pkey) + 2) / 3 * 4);
#endif
- encoded = malloc(encoded_length);
- if (encoded == NULL) {
+ encoded = reinterpret_cast<uint8_t*>(malloc(encoded_length));
+ if (encoded == nullptr) {
D("Allocation failure");
goto out;
}
@@ -272,18 +272,16 @@
static int read_key(const char *file, struct listnode *list)
{
- struct adb_private_key *key;
- FILE *f;
-
D("read_key '%s'\n", file);
- f = fopen(file, "r");
+ FILE* f = fopen(file, "r");
if (!f) {
D("Failed to open '%s'\n", file);
return 0;
}
- key = malloc(sizeof(*key));
+ adb_private_key* key = reinterpret_cast<adb_private_key*>(
+ malloc(sizeof(adb_private_key)));
if (!key) {
D("Failed to alloc key\n");
fclose(f);
@@ -390,7 +388,8 @@
}
}
-int adb_auth_sign(void *node, void *token, size_t token_size, void *sig)
+int adb_auth_sign(void *node, const unsigned char* token, size_t token_size,
+ unsigned char* sig)
{
unsigned int len;
struct adb_private_key *key = node_to_item(node, struct adb_private_key, node);
@@ -433,31 +432,33 @@
int adb_auth_get_userkey(unsigned char *data, size_t len)
{
char path[PATH_MAX];
- char *file;
- int ret;
-
- ret = get_user_keyfilepath(path, sizeof(path) - 4);
+ int ret = get_user_keyfilepath(path, sizeof(path) - 4);
if (ret < 0 || ret >= (signed)(sizeof(path) - 4)) {
D("Error getting user key filename");
return 0;
}
strcat(path, ".pub");
- file = load_file(path, (unsigned*)&ret);
- if (!file) {
+ // TODO(danalbert): ReadFileToString
+ unsigned size;
+ char* file_data = reinterpret_cast<char*>(load_file(path, &size));
+ if (file_data == nullptr) {
D("Can't load '%s'\n", path);
return 0;
}
- if (len < (size_t)(ret + 1)) {
- D("%s: Content too large ret=%d\n", path, ret);
+ if (len < (size_t)(size + 1)) {
+ D("%s: Content too large ret=%d\n", path, size);
+ free(file_data);
return 0;
}
- memcpy(data, file, ret);
- data[ret] = '\0';
+ memcpy(data, file_data, size);
+ free(file_data);
+ file_data = nullptr;
+ data[size] = '\0';
- return ret + 1;
+ return size + 1;
}
int adb_auth_keygen(const char* filename) {
diff --git a/adb/adb_client.c b/adb/adb_client.cpp
similarity index 98%
rename from adb/adb_client.c
rename to adb/adb_client.cpp
index 5d2bbd7..a485aa2 100644
--- a/adb/adb_client.c
+++ b/adb/adb_client.cpp
@@ -28,7 +28,6 @@
#define TRACE_TAG TRACE_ADB
#include "adb_client.h"
#include "adb_io.h"
-#include "zipfile/zipfile.h"
static transport_type __adb_transport = kTransportAny;
static const char* __adb_serial = NULL;
@@ -115,7 +114,7 @@
if (__adb_serial)
snprintf(service, sizeof service, "host:transport:%s", __adb_serial);
else {
- char* transport_type = "???";
+ const char* transport_type = "???";
switch (__adb_transport) {
case kTransportUsb:
@@ -328,8 +327,8 @@
char *adb_query(const char *service)
{
char buf[5];
- unsigned n;
- char *tmp;
+ unsigned long n;
+ char* tmp;
D("adb_query: %s\n", service);
int fd = adb_connect(service);
@@ -347,7 +346,7 @@
goto oops;
}
- tmp = malloc(n + 1);
+ tmp = reinterpret_cast<char*>(malloc(n + 1));
if(tmp == 0) goto oops;
if(!ReadFdExactly(fd, tmp, n) == 0) {
diff --git a/adb/adb_client.h b/adb/adb_client.h
index 6ba3b38..9af176f 100644
--- a/adb/adb_client.h
+++ b/adb/adb_client.h
@@ -47,7 +47,7 @@
* 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, char** argv);
+int adb_send_emulator_command(int argc, const char** argv);
/* return verbose error string from last operation */
const char *adb_error(void);
diff --git a/adb/adb_io.cpp b/adb/adb_io.cpp
index ca208ad..4dd9f4d 100644
--- a/adb/adb_io.cpp
+++ b/adb/adb_io.cpp
@@ -33,7 +33,7 @@
D("readx: fd=%d wanted=%zu\n", fd, len);
while (len > 0) {
- int r = TEMP_FAILURE_RETRY(adb_read(fd, p, len));
+ int r = adb_read(fd, p, len);
if (r > 0) {
len -= r;
p += r;
@@ -69,7 +69,7 @@
#endif
while (len > 0) {
- r = TEMP_FAILURE_RETRY(adb_write(fd, p, len));
+ r = adb_write(fd, p, len);
if (r == -1) {
D("writex: fd=%d error %d: %s\n", fd, errno, strerror(errno));
if (errno == EAGAIN) {
diff --git a/adb/adb_io_test.cpp b/adb/adb_io_test.cpp
index 330d9ce..0c69bc9 100644
--- a/adb/adb_io_test.cpp
+++ b/adb/adb_io_test.cpp
@@ -24,7 +24,7 @@
#include <string>
-#include "utils/file.h"
+#include "base/file.h"
class TemporaryFile {
public:
@@ -55,7 +55,7 @@
TemporaryFile tf;
ASSERT_NE(-1, tf.fd);
- ASSERT_TRUE(android::WriteStringToFd(expected, tf.fd)) << strerror(errno);
+ ASSERT_TRUE(android::base::WriteStringToFd(expected, tf.fd)) << strerror(errno);
ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
// Test reading the whole file.
@@ -69,7 +69,7 @@
TemporaryFile tf;
ASSERT_NE(-1, tf.fd);
- ASSERT_TRUE(android::WriteStringToFd(expected, tf.fd)) << strerror(errno);
+ ASSERT_TRUE(android::base::WriteStringToFd(expected, tf.fd)) << strerror(errno);
ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
// Test that not having enough data will fail.
@@ -83,7 +83,7 @@
TemporaryFile tf;
ASSERT_NE(-1, tf.fd);
- ASSERT_TRUE(android::WriteStringToFd(input, tf.fd)) << strerror(errno);
+ ASSERT_TRUE(android::base::WriteStringToFd(input, tf.fd)) << strerror(errno);
ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
// Test reading a partial file.
@@ -106,7 +106,7 @@
ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
std::string s;
- ASSERT_TRUE(android::ReadFdToString(tf.fd, &s));
+ ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s));
EXPECT_STREQ(expected, s.c_str());
}
@@ -123,7 +123,7 @@
expected.pop_back();
std::string s;
- ASSERT_TRUE(android::ReadFdToString(tf.fd, &s));
+ ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s));
EXPECT_EQ(expected, s);
}
@@ -137,6 +137,6 @@
ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
std::string s;
- ASSERT_TRUE(android::ReadFdToString(tf.fd, &s));
+ ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s));
EXPECT_STREQ(str, s.c_str());
}
diff --git a/adb/adb_listeners.c b/adb/adb_listeners.cpp
similarity index 76%
rename from adb/adb_listeners.c
rename to adb/adb_listeners.cpp
index f68b876..84b9c64 100644
--- a/adb/adb_listeners.c
+++ b/adb/adb_listeners.cpp
@@ -54,24 +54,26 @@
}
}
-void listener_event_func(int _fd, unsigned ev, void *_l)
+void listener_event_func(int _fd, unsigned ev, void* _l)
{
- alistener *l = _l;
+ alistener* listener = reinterpret_cast<alistener*>(_l);
asocket *s;
- if(ev & FDE_READ) {
+ if (ev & FDE_READ) {
struct sockaddr addr;
socklen_t alen;
int fd;
alen = sizeof(addr);
fd = adb_socket_accept(_fd, &addr, &alen);
- if(fd < 0) return;
+ if (fd < 0) {
+ return;
+ }
s = create_local_socket(fd);
- if(s) {
- s->transport = l->transport;
- connect_to_remote(s, l->connect_to);
+ if (s) {
+ s->transport = listener->transport;
+ connect_to_remote(s, listener->connect_to);
return;
}
@@ -102,11 +104,9 @@
free(l);
}
-void listener_disconnect(void* _l, atransport* t)
+void listener_disconnect(void* listener, atransport* t)
{
- alistener* l = _l;
-
- free_listener(l);
+ free_listener(reinterpret_cast<alistener*>(listener));
}
int local_name_to_fd(const char *name)
@@ -220,20 +220,16 @@
atransport* transport,
int no_rebind)
{
- alistener *l;
+ for (alistener* l = listener_list.next; l != &listener_list; l = l->next) {
+ if (strcmp(local_name, l->local_name) == 0) {
+ char* cto;
- //printf("install_listener('%s','%s')\n", local_name, connect_to);
-
- for(l = listener_list.next; l != &listener_list; l = l->next){
- if(strcmp(local_name, l->local_name) == 0) {
- char *cto;
-
- /* can't repurpose a smartsocket */
+ /* can't repurpose a smartsocket */
if(l->connect_to[0] == '*') {
return INSTALL_STATUS_INTERNAL_ERROR;
}
- /* can't repurpose a listener if 'no_rebind' is true */
+ /* can't repurpose a listener if 'no_rebind' is true */
if (no_rebind) {
return INSTALL_STATUS_CANNOT_REBIND;
}
@@ -243,7 +239,6 @@
return INSTALL_STATUS_INTERNAL_ERROR;
}
- //printf("rebinding '%s' to '%s'\n", local_name, connect_to);
free((void*) l->connect_to);
l->connect_to = cto;
if (l->transport != transport) {
@@ -255,38 +250,51 @@
}
}
- if((l = calloc(1, sizeof(alistener))) == 0) goto nomem;
- if((l->local_name = strdup(local_name)) == 0) goto nomem;
- if((l->connect_to = strdup(connect_to)) == 0) goto nomem;
+ alistener* listener = reinterpret_cast<alistener*>(
+ calloc(1, sizeof(alistener)));
+ if (listener == nullptr) {
+ goto nomem;
+ }
+ listener->local_name = strdup(local_name);
+ if (listener->local_name == nullptr) {
+ goto nomem;
+ }
- l->fd = local_name_to_fd(local_name);
- if(l->fd < 0) {
- free((void*) l->local_name);
- free((void*) l->connect_to);
- free(l);
+ listener->connect_to = strdup(connect_to);
+ if (listener->connect_to == nullptr) {
+ goto nomem;
+ }
+
+ listener->fd = local_name_to_fd(local_name);
+ if (listener->fd < 0) {
+ free(listener->local_name);
+ free(listener->connect_to);
+ free(listener);
printf("cannot bind '%s'\n", local_name);
- return -2;
+ return INSTALL_STATUS_CANNOT_BIND;
}
- close_on_exec(l->fd);
- if(!strcmp(l->connect_to, "*smartsocket*")) {
- fdevent_install(&l->fde, l->fd, ss_listener_event_func, l);
+ close_on_exec(listener->fd);
+ if (!strcmp(listener->connect_to, "*smartsocket*")) {
+ fdevent_install(&listener->fde, listener->fd, ss_listener_event_func,
+ listener);
} else {
- fdevent_install(&l->fde, l->fd, listener_event_func, l);
+ fdevent_install(&listener->fde, listener->fd, listener_event_func,
+ listener);
}
- fdevent_set(&l->fde, FDE_READ);
+ fdevent_set(&listener->fde, FDE_READ);
- l->next = &listener_list;
- l->prev = listener_list.prev;
- l->next->prev = l;
- l->prev->next = l;
- l->transport = transport;
+ listener->next = &listener_list;
+ listener->prev = listener_list.prev;
+ listener->next->prev = listener;
+ listener->prev->next = listener;
+ listener->transport = transport;
if (transport) {
- l->disconnect.opaque = l;
- l->disconnect.func = listener_disconnect;
- add_transport_disconnect(transport, &l->disconnect);
+ listener->disconnect.opaque = listener;
+ listener->disconnect.func = listener_disconnect;
+ add_transport_disconnect(transport, &listener->disconnect);
}
return INSTALL_STATUS_OK;
diff --git a/adb/adb_main.c b/adb/adb_main.cpp
similarity index 97%
rename from adb/adb_main.c
rename to adb/adb_main.cpp
index f8475c7..1d9cc3b 100644
--- a/adb/adb_main.c
+++ b/adb/adb_main.cpp
@@ -273,10 +273,14 @@
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)
- adb_auth_init();
+ adbd_auth_init();
// Our external storage path may be different than apps, since
// we aren't able to bind mount after dropping root.
@@ -387,7 +391,7 @@
adb_sysdeps_init();
adb_trace_init();
D("Handling commandline()\n");
- return adb_commandline(argc - 1, argv + 1);
+ return adb_commandline(argc - 1, const_cast<const char**>(argv + 1));
#else
/* If adbd runs inside the emulator this will enable adb tracing via
* adb-debug qemud service in the emulator. */
diff --git a/adb/commandline.c b/adb/commandline.cpp
similarity index 92%
rename from adb/commandline.c
rename to adb/commandline.cpp
index a8ad7bd..4538b04 100644
--- a/adb/commandline.c
+++ b/adb/commandline.cpp
@@ -40,31 +40,31 @@
#include "adb_io.h"
#include "file_sync_service.h"
-static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
+static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...);
-void get_my_path(char *s, size_t maxLen);
int find_sync_dirs(const char *srcarg,
- char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out);
-int install_app(transport_type transport, char* serial, int argc, char** argv);
-int install_multiple_app(transport_type transport, char* serial, int argc, char** argv);
-int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
+ char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
+ char **oem_srcdir_out);
+int install_app(transport_type transport, const char* serial, int argc,
+ const char** argv);
+int install_multiple_app(transport_type transport, const char* serial, int argc,
+ const char** argv);
+int uninstall_app(transport_type transport, const char* serial, int argc,
+ const char** argv);
static const char *gProductOutPath = NULL;
extern int gListenAll;
static char *product_file(const char *extra)
{
- int n;
- char *x;
-
if (gProductOutPath == NULL) {
fprintf(stderr, "adb: Product directory not specified; "
"use -p or define ANDROID_PRODUCT_OUT\n");
exit(1);
}
- n = strlen(gProductOutPath) + strlen(extra) + 2;
- x = malloc(n);
+ int n = strlen(gProductOutPath) + strlen(extra) + 2;
+ char* x = reinterpret_cast<char*>(malloc(n));
if (x == 0) {
fprintf(stderr, "adb: Out of memory (product_file())\n");
exit(1);
@@ -207,7 +207,7 @@
" adb get-serialno - prints: <serial-number>\n"
" adb get-devpath - prints: <device-path>\n"
" adb status-window - continuously print device status for a specified device\n"
- " adb remount - remounts the /system and /vendor (if present) partitions on the device read-write\n"
+ " adb remount - remounts the /system, /vendor (if present) and /oem (if present) partitions on the device read-write\n"
" adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
" adb reboot-bootloader - reboots the device into the bootloader\n"
" adb root - restarts the adbd daemon with root permissions\n"
@@ -223,9 +223,9 @@
"adb sync notes: adb sync [ <directory> ]\n"
" <localdir> can be interpreted in several ways:\n"
"\n"
- " - If <directory> is not specified, /system, /vendor (if present), and /data partitions will be updated.\n"
+ " - If <directory> is not specified, /system, /vendor (if present), /oem (if present) and /data partitions will be updated.\n"
"\n"
- " - If it is \"system\", \"vendor\" or \"data\", only the corresponding partition\n"
+ " - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
" is updated.\n"
"\n"
"environmental variables:\n"
@@ -422,7 +422,6 @@
{
adb_thread_t thr;
int fdi, fd;
- int *fds;
fd = adb_connect("shell:");
if(fd < 0) {
@@ -431,7 +430,7 @@
}
fdi = 0; //dup(0);
- fds = malloc(sizeof(int) * 2);
+ int* fds = reinterpret_cast<int*>(malloc(sizeof(int) * 2));
fds[0] = fd;
fds[1] = fdi;
@@ -464,7 +463,6 @@
char buf[4096];
unsigned total;
int fd;
- const unsigned char *ptr;
sprintf(buf,"%s:%d", service, sz);
fd = adb_connect(buf);
@@ -477,7 +475,7 @@
opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
total = sz;
- ptr = data;
+ const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
if(progress) {
char *x = strrchr(service, ':');
@@ -557,14 +555,15 @@
* we hang up.
*/
int adb_sideload_host(const char* fn) {
- uint8_t* data;
unsigned sz;
size_t xfer = 0;
int status;
+ int last_percent = -1;
+ int opt = SIDELOAD_HOST_BLOCK_SIZE;
printf("loading: '%s'", fn);
fflush(stdout);
- data = load_file(fn, &sz);
+ uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
if (data == 0) {
printf("\n");
fprintf(stderr, "* cannot read '%s' *\n", fn);
@@ -582,10 +581,8 @@
goto done;
}
- int opt = SIDELOAD_HOST_BLOCK_SIZE;
opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
- int last_percent = -1;
for (;;) {
if (!ReadFdExactly(fd, buf, 8)) {
fprintf(stderr, "* failed to read command: %s\n", adb_error());
@@ -739,13 +736,12 @@
* ppp dev:/dev/omap_csmi_tty0 <ppp options>
*
*/
-int ppp(int argc, char **argv)
+int ppp(int argc, const char **argv)
{
#if defined(_WIN32)
fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
return -1;
#else
- char *adb_service_name;
pid_t pid;
int fd;
@@ -756,8 +752,7 @@
return 1;
}
- adb_service_name = argv[1];
-
+ const char* adb_service_name = argv[1];
fd = adb_connect(adb_service_name);
if(fd < 0) {
@@ -807,7 +802,8 @@
#endif /* !defined(_WIN32) */
}
-static int send_shellcommand(transport_type transport, char* serial, char* buf)
+static int send_shellcommand(transport_type transport, const char* serial,
+ char* buf)
{
int fd, ret;
@@ -828,7 +824,8 @@
return ret;
}
-static int logcat(transport_type transport, char* serial, int argc, char **argv)
+static int logcat(transport_type transport, const char* serial, int argc,
+ const char** argv)
{
char buf[4096];
@@ -877,7 +874,7 @@
return 0;
}
-static int backup(int argc, char** argv) {
+static int backup(int argc, const char** argv) {
char buf[4096];
char default_name[32];
const char* filename = strcpy(default_name, "./backup.ab");
@@ -933,7 +930,7 @@
return 0;
}
-static int restore(int argc, char** argv) {
+static int restore(int argc, const char** argv) {
const char* filename;
int fd, tarFd;
@@ -1102,8 +1099,9 @@
return path_buf;
}
-static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
- int *show_progress, int *copy_attrs) {
+static void parse_push_pull_args(const char **arg, int narg, char const **path1,
+ char const **path2, int *show_progress,
+ int *copy_attrs) {
*show_progress = 0;
*copy_attrs = 0;
@@ -1130,7 +1128,7 @@
}
}
-int adb_commandline(int argc, char **argv)
+int adb_commandline(int argc, const char **argv)
{
char buf[4096];
int no_daemon = 0;
@@ -1139,8 +1137,8 @@
int persist = 0;
int r;
transport_type ttype = kTransportAny;
- char* serial = NULL;
- char* server_port_str = NULL;
+ const char* serial = NULL;
+ const char* server_port_str = NULL;
/* If defined, this should be an absolute path to
* the directory containing all of the various system images
@@ -1274,7 +1272,7 @@
/* handle wait-for-* prefix */
if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
- char* service = argv[0];
+ const char* service = argv[0];
if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
if (ttype == kTransportUsb) {
service = "wait-for-usb";
@@ -1308,7 +1306,7 @@
/* adb_connect() commands */
if (!strcmp(argv[0], "devices")) {
char *tmp;
- char *listopt;
+ const char *listopt;
if (argc < 2)
listopt = "";
else if (argc == 2 && !strcmp(argv[1], "-l"))
@@ -1635,7 +1633,9 @@
return uninstall_app(ttype, serial, argc, argv);
}
else if (!strcmp(argv[0], "sync")) {
- char *srcarg, *android_srcpath, *data_srcpath, *vendor_srcpath;
+ const char* srcarg;
+ char *system_srcpath, *data_srcpath, *vendor_srcpath, *oem_srcpath;
+
int listonly = 0;
int ret;
@@ -1655,18 +1655,22 @@
} else {
return usage();
}
- ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath, &vendor_srcpath);
+ ret = find_sync_dirs(srcarg, &system_srcpath, &data_srcpath, &vendor_srcpath,
+ &oem_srcpath);
if (ret != 0) return usage();
- if (android_srcpath != NULL)
- ret = do_sync_sync(android_srcpath, "/system", listonly);
+ if (system_srcpath != NULL)
+ ret = do_sync_sync(system_srcpath, "/system", listonly);
if (ret == 0 && vendor_srcpath != NULL)
ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
+ if(ret == 0 && oem_srcpath != NULL)
+ ret = do_sync_sync(oem_srcpath, "/oem", listonly);
if (ret == 0 && data_srcpath != NULL)
ret = do_sync_sync(data_srcpath, "/data", listonly);
- free(android_srcpath);
+ free(system_srcpath);
free(vendor_srcpath);
+ free(oem_srcpath);
free(data_srcpath);
return ret;
}
@@ -1736,9 +1740,9 @@
}
#define MAX_ARGV_LENGTH 16
-static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
+static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...)
{
- char *argv[MAX_ARGV_LENGTH];
+ const char *argv[MAX_ARGV_LENGTH];
int argc;
va_list ap;
@@ -1772,54 +1776,65 @@
}
int find_sync_dirs(const char *srcarg,
- char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out)
+ char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
+ char **oem_srcdir_out)
{
- char *android_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL;
+ char *system_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL, *oem_srcdir = NULL;
struct stat st;
if(srcarg == NULL) {
- android_srcdir = product_file("system");
+ system_srcdir = product_file("system");
data_srcdir = product_file("data");
vendor_srcdir = product_file("vendor");
- /* Check if vendor partition exists */
+ oem_srcdir = product_file("oem");
+ // Check if vendor partition exists.
if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
vendor_srcdir = NULL;
+ // Check if oem partition exists.
+ if (lstat(oem_srcdir, &st) || !S_ISDIR(st.st_mode))
+ oem_srcdir = NULL;
} else {
- /* srcarg may be "data", "system" or NULL.
- * if srcarg is NULL, then both data and system are synced
- */
+ // srcarg may be "data", "system", "vendor", "oem" or NULL.
+ // If srcarg is NULL, then all partitions are synced.
if(strcmp(srcarg, "system") == 0) {
- android_srcdir = product_file("system");
+ system_srcdir = product_file("system");
} else if(strcmp(srcarg, "data") == 0) {
data_srcdir = product_file("data");
} else if(strcmp(srcarg, "vendor") == 0) {
vendor_srcdir = product_file("vendor");
+ } else if(strcmp(srcarg, "oem") == 0) {
+ oem_srcdir = product_file("oem");
} else {
- /* It's not "system", "vendor", or "data".
- */
+ // It's not "system", "data", "vendor", or "oem".
return 1;
}
}
- if(android_srcdir_out != NULL)
- *android_srcdir_out = android_srcdir;
+ if(system_srcdir_out != NULL)
+ *system_srcdir_out = system_srcdir;
else
- free(android_srcdir);
+ free(system_srcdir);
if(vendor_srcdir_out != NULL)
*vendor_srcdir_out = vendor_srcdir;
else
free(vendor_srcdir);
+ if(oem_srcdir_out != NULL)
+ *oem_srcdir_out = oem_srcdir;
+ else
+ free(oem_srcdir);
+
if(data_srcdir_out != NULL)
- *data_srcdir_out = data_srcdir;
- else
- free(data_srcdir);
+ *data_srcdir_out = data_srcdir;
+ else
+ free(data_srcdir);
+
return 0;
}
-static int pm_command(transport_type transport, char* serial,
- int argc, char** argv)
+static int pm_command(transport_type transport, const char* serial,
+ int argc, const char** argv)
{
char buf[4096];
@@ -1836,7 +1851,8 @@
return 0;
}
-int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
+int uninstall_app(transport_type 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) */
@@ -1854,7 +1870,7 @@
return pm_command(transport, serial, argc, argv);
}
-static int delete_file(transport_type transport, char* serial, char* filename)
+static int delete_file(transport_type transport, const char* serial, char* filename)
{
char buf[4096];
char* quoted;
@@ -1879,7 +1895,8 @@
}
}
-int install_app(transport_type transport, char* serial, int argc, char** argv)
+int install_app(transport_type 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";
@@ -1897,7 +1914,7 @@
// All other arguments passed through verbatim.
int last_apk = -1;
for (i = argc - 1; i >= 0; i--) {
- char* file = argv[i];
+ const char* file = argv[i];
char* dot = strrchr(file, '.');
if (dot && !strcasecmp(dot, ".apk")) {
if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
@@ -1915,7 +1932,7 @@
return -1;
}
- char* apk_file = argv[last_apk];
+ const char* apk_file = argv[last_apk];
char apk_dest[PATH_MAX];
snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
@@ -1932,7 +1949,8 @@
return err;
}
-int install_multiple_app(transport_type transport, char* serial, int argc, char** argv)
+int install_multiple_app(transport_type transport, const char* serial, int argc,
+ const char** argv)
{
char buf[1024];
int i;
@@ -1943,7 +1961,7 @@
// All other arguments passed through verbatim.
int first_apk = -1;
for (i = argc - 1; i >= 0; i--) {
- char* file = argv[i];
+ const char* file = argv[i];
char* dot = strrchr(file, '.');
if (dot && !strcasecmp(dot, ".apk")) {
if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
@@ -1998,7 +2016,7 @@
// Valid session, now stream the APKs
int success = 1;
for (i = first_apk; i < argc; i++) {
- char* file = argv[i];
+ const char* file = argv[i];
if (stat(file, &sb) == -1) {
fprintf(stderr, "Failed to stat %s\n", file);
success = 0;
diff --git a/adb/console.c b/adb/console.cpp
similarity index 93%
rename from adb/console.c
rename to adb/console.cpp
index b813d33..452ee41 100644
--- a/adb/console.c
+++ b/adb/console.cpp
@@ -24,7 +24,7 @@
}
-int adb_send_emulator_command(int argc, char** argv)
+int adb_send_emulator_command(int argc, const char** argv)
{
int fd, nn;
diff --git a/adb/file_sync_client.c b/adb/file_sync_client.cpp
similarity index 97%
rename from adb/file_sync_client.c
rename to adb/file_sync_client.cpp
index 3a0c666..4ba730b 100644
--- a/adb/file_sync_client.c
+++ b/adb/file_sync_client.cpp
@@ -32,7 +32,6 @@
#include "adb_client.h"
#include "adb_io.h"
#include "file_sync_service.h"
-#include "zipfile/zipfile.h"
static unsigned long long total_bytes;
static long long start_time;
@@ -580,7 +579,8 @@
int ssize = slen + nlen + 2;
int dsize = dlen + nlen + 2;
- copyinfo *ci = 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();
@@ -684,14 +684,14 @@
if((lpath[0] == 0) || (rpath[0] == 0)) return -1;
if(lpath[strlen(lpath) - 1] != '/') {
int tmplen = strlen(lpath)+2;
- char *tmp = malloc(tmplen);
+ char *tmp = reinterpret_cast<char*>(malloc(tmplen));
if(tmp == 0) return -1;
snprintf(tmp, tmplen, "%s/",lpath);
lpath = tmp;
}
if(rpath[strlen(rpath) - 1] != '/') {
int tmplen = strlen(rpath)+2;
- char *tmp = malloc(tmplen);
+ char *tmp = reinterpret_cast<char*>(malloc(tmplen));
if(tmp == 0) return -1;
snprintf(tmp, tmplen, "%s/",rpath);
rpath = tmp;
@@ -784,7 +784,8 @@
name++;
}
int tmplen = strlen(name) + strlen(rpath) + 2;
- char *tmp = malloc(strlen(name) + strlen(rpath) + 2);
+ char *tmp = reinterpret_cast<char*>(
+ malloc(strlen(name) + strlen(rpath) + 2));
if(tmp == 0) return 1;
snprintf(tmp, tmplen, "%s/%s", rpath, name);
rpath = tmp;
@@ -872,7 +873,7 @@
return 0;
}
-static int set_time_and_mode(const char *lpath, unsigned int time, unsigned int mode)
+static int set_time_and_mode(const char *lpath, time_t time, unsigned int mode)
{
struct utimbuf times = { time, time };
int r1 = utime(lpath, ×);
@@ -890,7 +891,7 @@
{
if (path[strlen(path) - 1] != '/') {
size_t len = strlen(path) + 2;
- char *path_with_slash = malloc(len);
+ char *path_with_slash = reinterpret_cast<char*>(malloc(len));
if (path_with_slash == NULL)
return NULL;
snprintf(path_with_slash, len, "%s/", path);
@@ -999,7 +1000,7 @@
name++;
}
int tmplen = strlen(name) + strlen(lpath) + 2;
- char *tmp = malloc(tmplen);
+ char *tmp = reinterpret_cast<char*>(malloc(tmplen));
if(tmp == 0) return 1;
snprintf(tmp, tmplen, "%s/%s", lpath, name);
lpath = tmp;
diff --git a/adb/file_sync_service.c b/adb/file_sync_service.cpp
similarity index 94%
rename from adb/file_sync_service.c
rename to adb/file_sync_service.cpp
index 0b289e8..ac01678 100644
--- a/adb/file_sync_service.c
+++ b/adb/file_sync_service.cpp
@@ -33,15 +33,11 @@
#include "file_sync_service.h"
#include "private/android_filesystem_config.h"
-/* TODO: use fs_config to configure permissions on /data */
-static bool is_on_system(const char *name) {
- const char *SYSTEM = "/system/";
- return (strncmp(SYSTEM, name, strlen(SYSTEM)) == 0);
-}
-
-static bool is_on_vendor(const char *name) {
- const char *VENDOR = "/vendor/";
- return (strncmp(VENDOR, name, strlen(VENDOR)) == 0);
+static bool should_use_fs_config(const char* path) {
+ // TODO: use fs_config to configure permissions on /data.
+ return strncmp("/system/", path, strlen("/system/")) == 0 ||
+ strncmp("/vendor/", path, strlen("/vendor/")) == 0 ||
+ strncmp("/oem/", path, strlen("/oem/")) == 0;
}
static int mkdirs(char *name)
@@ -59,7 +55,7 @@
x = adb_dirstart(x);
if(x == 0) return 0;
*x = 0;
- if (is_on_system(name) || is_on_vendor(name)) {
+ if (should_use_fs_config(name)) {
fs_config(name, 1, &uid, &gid, &mode, &cap);
}
ret = adb_mkdir(name, mode);
@@ -151,7 +147,7 @@
msg.dent.size = 0;
msg.dent.time = 0;
msg.dent.namelen = 0;
- return !WriteFdExactly(s, &msg.dent, sizeof(msg.dent)) ? 0 : -1;
+ return WriteFdExactly(s, &msg.dent, sizeof(msg.dent)) ? 0 : -1;
}
static int fail_message(int s, const char *reason)
@@ -368,7 +364,7 @@
if(*tmp == '/') {
tmp++;
}
- if (is_on_system(path) || is_on_vendor(path)) {
+ if (should_use_fs_config(path)) {
fs_config(tmp, 0, &uid, &gid, &mode, &cap);
}
return handle_send_file(s, path, uid, gid, mode, buffer, do_unlink);
@@ -420,7 +416,7 @@
char name[1025];
unsigned namelen;
- char *buffer = malloc(SYNC_DATA_MAX);
+ char *buffer = reinterpret_cast<char*>(malloc(SYNC_DATA_MAX));
if(buffer == 0) goto fail;
for(;;) {
diff --git a/adb/framebuffer_service.c b/adb/framebuffer_service.cpp
similarity index 98%
rename from adb/framebuffer_service.c
rename to adb/framebuffer_service.cpp
index 9d17d2c..7baad8b 100644
--- a/adb/framebuffer_service.c
+++ b/adb/framebuffer_service.cpp
@@ -62,10 +62,11 @@
int fd_screencap;
int w, h, f;
int fds[2];
+ pid_t pid;
if (pipe2(fds, O_CLOEXEC) < 0) goto pipefail;
- pid_t pid = fork();
+ pid = fork();
if (pid < 0) goto done;
if (pid == 0) {
diff --git a/adb/get_my_path_darwin.c b/adb/get_my_path_darwin.c
index ff1396c..b0c962e 100644
--- a/adb/get_my_path_darwin.c
+++ b/adb/get_my_path_darwin.c
@@ -17,6 +17,8 @@
#import <Carbon/Carbon.h>
#include <unistd.h>
+#include "adb.h"
+
void get_my_path(char *s, size_t maxLen)
{
CFBundleRef mainBundle = CFBundleGetMainBundle();
diff --git a/adb/get_my_path_linux.c b/adb/get_my_path_linux.cpp
similarity index 97%
rename from adb/get_my_path_linux.c
rename to adb/get_my_path_linux.cpp
index 179c3dd..11c0b21 100644
--- a/adb/get_my_path_linux.c
+++ b/adb/get_my_path_linux.cpp
@@ -14,10 +14,12 @@
* limitations under the License.
*/
-#include <sys/types.h>
-#include <unistd.h>
#include <limits.h>
#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "adb.h"
void get_my_path(char *exe, size_t maxLen)
{
diff --git a/adb/get_my_path_windows.c b/adb/get_my_path_windows.cpp
similarity index 97%
rename from adb/get_my_path_windows.c
rename to adb/get_my_path_windows.cpp
index ddf2816..9d23e1c 100644
--- a/adb/get_my_path_windows.c
+++ b/adb/get_my_path_windows.cpp
@@ -14,10 +14,12 @@
* limitations under the License.
*/
-#include <limits.h>
#include <assert.h>
+#include <limits.h>
#include <windows.h>
+#include "adb.h"
+
void get_my_path(char *exe, size_t maxLen)
{
char *r;
diff --git a/adb/jdwp_service.c b/adb/jdwp_service.cpp
similarity index 98%
rename from adb/jdwp_service.c
rename to adb/jdwp_service.cpp
index 3074e42..f0b4ba7 100644
--- a/adb/jdwp_service.c
+++ b/adb/jdwp_service.cpp
@@ -194,7 +194,8 @@
static JdwpProcess*
jdwp_process_alloc( int socket )
{
- JdwpProcess* proc = calloc(1,sizeof(*proc));
+ JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(
+ calloc(1, sizeof(*proc)));
if (proc == NULL) {
D("not enough memory to create new JDWP process\n");
@@ -234,7 +235,7 @@
static void
jdwp_process_event( int socket, unsigned events, void* _proc )
{
- JdwpProcess* proc = _proc;
+ JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc);
if (events & FDE_READ) {
if (proc->pid < 0) {
@@ -601,7 +602,7 @@
asocket*
create_jdwp_service_socket( void )
{
- JdwpSocket* s = calloc(sizeof(*s),1);
+ JdwpSocket* s = reinterpret_cast<JdwpSocket*>(calloc(sizeof(*s), 1));
if (s == NULL)
return NULL;
@@ -696,7 +697,7 @@
asocket*
create_jdwp_tracker_service_socket( void )
{
- JdwpTracker* t = calloc(sizeof(*t),1);
+ JdwpTracker* t = reinterpret_cast<JdwpTracker*>(calloc(sizeof(*t), 1));
if (t == NULL)
return NULL;
diff --git a/adb/qemu_tracing.c b/adb/qemu_tracing.cpp
similarity index 100%
rename from adb/qemu_tracing.c
rename to adb/qemu_tracing.cpp
diff --git a/adb/remount_service.c b/adb/remount_service.cpp
similarity index 63%
rename from adb/remount_service.c
rename to adb/remount_service.cpp
index 414b316..a83d5b1 100644
--- a/adb/remount_service.c
+++ b/adb/remount_service.cpp
@@ -23,6 +23,8 @@
#include <sys/mount.h>
#include <unistd.h>
+#include <string>
+
#include "sysdeps.h"
#define TRACE_TAG TRACE_ADB
@@ -32,10 +34,10 @@
static int system_ro = 1;
static int vendor_ro = 1;
+static int oem_ro = 1;
/* Returns the device used to mount a directory in /proc/mounts */
-static char *find_mount(const char *dir)
-{
+static std::string find_mount(const char *dir) {
FILE* fp;
struct mntent* mentry;
char* device = NULL;
@@ -45,7 +47,7 @@
}
while ((mentry = getmntent(fp)) != NULL) {
if (strcmp(dir, mentry->mnt_dir) == 0) {
- device = strdup(mentry->mnt_fsname);
+ device = mentry->mnt_fsname;
break;
}
}
@@ -53,64 +55,53 @@
return device;
}
-static int hasVendorPartition()
-{
- struct stat info;
- if (!lstat("/vendor", &info))
- if ((info.st_mode & S_IFMT) == S_IFDIR)
- return true;
- return false;
+static bool has_partition(const char* path) {
+ struct stat sb;
+ return (lstat(path, &sb) == 0 && S_ISDIR(sb.st_mode));
}
-int make_block_device_writable(const char* dev)
-{
- int fd = -1;
+int make_block_device_writable(const std::string& dev) {
+ int fd = unix_open(dev.c_str(), O_RDONLY | O_CLOEXEC);
+ if (fd == -1) {
+ return -1;
+ }
+
+ int result = -1;
int OFF = 0;
- int rc = -1;
-
- if (!dev)
- goto errout;
-
- fd = unix_open(dev, O_RDONLY | O_CLOEXEC);
- if (fd < 0)
- goto errout;
-
- if (ioctl(fd, BLKROSET, &OFF)) {
- goto errout;
+ if (!ioctl(fd, BLKROSET, &OFF)) {
+ result = 0;
}
+ adb_close(fd);
- rc = 0;
-
-errout:
- if (fd >= 0) {
- adb_close(fd);
- }
- return rc;
+ return result;
}
-/* Init mounts /system as read only, remount to enable writes. */
-static int remount(const char* dir, int* dir_ro)
-{
- char *dev = 0;
- int rc = -1;
-
- dev = find_mount(dir);
-
- if (!dev || make_block_device_writable(dev)) {
- goto errout;
+// Init mounts /system as read only, remount to enable writes.
+static int remount(const char* dir, int* dir_ro) {
+ std::string dev(find_mount(dir));
+ if (dev.empty() || make_block_device_writable(dev)) {
+ return -1;
}
- rc = mount(dev, dir, "none", MS_REMOUNT, NULL);
+ int rc = mount(dev.c_str(), dir, "none", MS_REMOUNT, NULL);
*dir_ro = rc;
-
-errout:
- free(dev);
return rc;
}
-void remount_service(int fd, void *cookie)
-{
- char buffer[200];
+static bool remount_partition(int fd, const char* partition, int* ro) {
+ if (!has_partition(partition)) {
+ return true;
+ }
+ if (remount(partition, ro)) {
+ char buf[200];
+ snprintf(buf, sizeof(buf), "remount of %s failed: %s\n", partition, strerror(errno));
+ WriteStringFully(fd, buf);
+ return false;
+ }
+ return true;
+}
+
+void remount_service(int fd, void* cookie) {
char prop_buf[PROPERTY_VALUE_MAX];
if (getuid() != 0) {
@@ -133,6 +124,7 @@
if (system_verified || vendor_verified) {
// Allow remount but warn of likely bad effects
bool both = system_verified && vendor_verified;
+ char buffer[200];
snprintf(buffer, sizeof(buffer),
"dm_verity is enabled on the %s%s%s partition%s.\n",
system_verified ? "system" : "",
@@ -147,23 +139,12 @@
WriteStringFully(fd, buffer);
}
- if (remount("/system", &system_ro)) {
- snprintf(buffer, sizeof(buffer), "remount of system failed: %s\n",strerror(errno));
- WriteStringFully(fd, buffer);
- }
+ bool success = true;
+ success &= remount_partition(fd, "/system", &system_ro);
+ success &= remount_partition(fd, "/vendor", &vendor_ro);
+ success &= remount_partition(fd, "/oem", &oem_ro);
- if (hasVendorPartition()) {
- if (remount("/vendor", &vendor_ro)) {
- snprintf(buffer, sizeof(buffer), "remount of vendor failed: %s\n",strerror(errno));
- WriteStringFully(fd, buffer);
- }
- }
-
- if (!system_ro && (!vendor_ro || !hasVendorPartition()))
- WriteStringFully(fd, "remount succeeded\n");
- else {
- WriteStringFully(fd, "remount failed\n");
- }
+ WriteStringFully(fd, success ? "remount succeeded\n" : "remount failed\n");
adb_close(fd);
}
diff --git a/adb/remount_service.h b/adb/remount_service.h
new file mode 100644
index 0000000..e1763cf
--- /dev/null
+++ b/adb/remount_service.h
@@ -0,0 +1,25 @@
+/*
+ * 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 _REMOUNT_SERVICE_H_
+#define _REMOUNT_SERVICE_H_
+
+#include <string>
+
+int make_block_device_writable(const std::string&);
+void remount_service(int, void*);
+
+#endif
diff --git a/adb/services.c b/adb/services.cpp
similarity index 96%
rename from adb/services.c
rename to adb/services.cpp
index 84f2137..e7bf6b0 100644
--- a/adb/services.c
+++ b/adb/services.cpp
@@ -38,6 +38,7 @@
#include "adb.h"
#include "adb_io.h"
#include "file_sync_service.h"
+#include "remount_service.h"
#include "transport.h"
typedef struct stinfo stinfo;
@@ -51,7 +52,7 @@
void *service_bootstrap_func(void *x)
{
- stinfo *sti = x;
+ stinfo* sti = reinterpret_cast<stinfo*>(x);
sti->func(sti->fd, sti->cookie);
free(sti);
return 0;
@@ -161,7 +162,7 @@
void reverse_service(int fd, void* arg)
{
- const char* command = arg;
+ const char* command = reinterpret_cast<const char*>(arg);
if (handle_forward_request(command, kTransportAny, NULL, fd) < 0) {
sendfailmsg(fd, "not a reverse forwarding command");
@@ -174,23 +175,23 @@
static int create_service_thread(void (*func)(int, void *), void *cookie)
{
- stinfo *sti;
- adb_thread_t t;
int s[2];
-
- if(adb_socketpair(s)) {
+ if (adb_socketpair(s)) {
printf("cannot create service socket pair\n");
return -1;
}
D("socketpair: (%d,%d)", s[0], s[1]);
- sti = malloc(sizeof(stinfo));
- if(sti == 0) fatal("cannot allocate stinfo");
+ stinfo* sti = reinterpret_cast<stinfo*>(malloc(sizeof(stinfo)));
+ if (sti == nullptr) {
+ fatal("cannot allocate stinfo");
+ }
sti->func = func;
sti->cookie = cookie;
sti->fd = s[1];
- if(adb_thread_create( &t, service_bootstrap_func, sti)){
+ adb_thread_t t;
+ if (adb_thread_create(&t, service_bootstrap_func, sti)) {
free(sti);
adb_close(s[0]);
adb_close(s[1]);
@@ -359,7 +360,6 @@
static int create_subproc_thread(const char *name, const subproc_mode mode)
{
- stinfo *sti;
adb_thread_t t;
int ret_fd;
pid_t pid = -1;
@@ -384,7 +384,7 @@
}
D("create_subproc ret_fd=%d pid=%d\n", ret_fd, pid);
- sti = malloc(sizeof(stinfo));
+ stinfo* sti = reinterpret_cast<stinfo*>(malloc(sizeof(stinfo)));
if(sti == 0) fatal("cannot allocate stinfo");
sti->func = subproc_waiter_service;
sti->cookie = (void*) (uintptr_t) pid;
@@ -512,11 +512,11 @@
static void wait_for_state(int fd, void* cookie)
{
- struct state_info* sinfo = cookie;
- char* err = "unknown error";
+ state_info* sinfo = reinterpret_cast<state_info*>(cookie);
D("wait_for_state %d\n", sinfo->state);
+ const char* err = "unknown error";
atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err);
if(t != 0) {
WriteFdExactly(fd, "OKAY", 4);
@@ -635,7 +635,7 @@
{
char buf[4096];
char resp[4096];
- char *host = cookie;
+ char *host = reinterpret_cast<char*>(cookie);
if (!strncmp(host, "emu:", 4)) {
connect_emulator(host + 4, buf, sizeof(buf));
@@ -656,7 +656,7 @@
if (!strcmp(name,"track-devices")) {
return create_device_tracker();
} else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) {
- struct state_info* sinfo = malloc(sizeof(struct state_info));
+ auto sinfo = reinterpret_cast<state_info*>(malloc(sizeof(state_info)));
if (serial)
sinfo->serial = strdup(serial);
diff --git a/adb/set_verity_enable_state_service.c b/adb/set_verity_enable_state_service.cpp
similarity index 98%
rename from adb/set_verity_enable_state_service.c
rename to adb/set_verity_enable_state_service.cpp
index 184674d..139b074 100644
--- a/adb/set_verity_enable_state_service.c
+++ b/adb/set_verity_enable_state_service.cpp
@@ -26,6 +26,7 @@
#include "cutils/properties.h"
#include "ext4_sb.h"
#include "fs_mgr.h"
+#include "remount_service.h"
#include "sysdeps.h"
#define FSTAB_PREFIX "/fstab."
@@ -90,7 +91,7 @@
uint32_t magic_number;
const uint32_t new_magic = enable ? VERITY_METADATA_MAGIC_NUMBER
: VERITY_METADATA_MAGIC_DISABLE;
- uint64_t device_length;
+ uint64_t device_length = 0;
int device = -1;
int retval = -1;
@@ -140,7 +141,7 @@
if (magic_number != VERITY_METADATA_MAGIC_NUMBER
&& magic_number != VERITY_METADATA_MAGIC_DISABLE) {
write_console(fd,
- "Couldn't find verity metadata at offset %"PRIu64"!\n",
+ "Couldn't find verity metadata at offset %" PRIu64 "!\n",
device_length);
goto errout;
}
diff --git a/adb/sockets.c b/adb/sockets.cpp
similarity index 92%
rename from adb/sockets.c
rename to adb/sockets.cpp
index d34f8c6..12bc8d8 100644
--- a/adb/sockets.c
+++ b/adb/sockets.cpp
@@ -284,98 +284,101 @@
insert_local_socket(s, &local_socket_closing_list);
}
-static void local_socket_event_func(int fd, unsigned ev, void *_s)
+static void local_socket_event_func(int fd, unsigned ev, void* _s)
{
- asocket *s = _s;
-
+ asocket* s = reinterpret_cast<asocket*>(_s);
D("LS(%d): event_func(fd=%d(==%d), ev=%04x)\n", s->id, s->fd, fd, ev);
/* put the FDE_WRITE processing before the FDE_READ
** in order to simplify the code.
*/
- if(ev & FDE_WRITE){
- apacket *p;
-
- while((p = s->pkt_first) != 0) {
- while(p->len > 0) {
+ if (ev & FDE_WRITE) {
+ apacket* p;
+ while ((p = s->pkt_first) != nullptr) {
+ while (p->len > 0) {
int r = adb_write(fd, p->ptr, p->len);
- if(r > 0) {
+ if (r == -1) {
+ /* returning here is ok because FDE_READ will
+ ** be processed in the next iteration loop
+ */
+ if (errno == EAGAIN) {
+ return;
+ }
+ } else if (r > 0) {
p->ptr += r;
p->len -= r;
continue;
}
- if(r < 0) {
- /* returning here is ok because FDE_READ will
- ** be processed in the next iteration loop
- */
- if(errno == EAGAIN) return;
- if(errno == EINTR) continue;
- }
+
D(" closing after write because r=%d and errno is %d\n", r, errno);
s->close(s);
return;
}
- if(p->len == 0) {
+ if (p->len == 0) {
s->pkt_first = p->next;
- if(s->pkt_first == 0) s->pkt_last = 0;
+ if (s->pkt_first == 0) {
+ s->pkt_last = 0;
+ }
put_apacket(p);
}
}
- /* if we sent the last packet of a closing socket,
- ** we can now destroy it.
- */
+ /* if we sent the last packet of a closing socket,
+ ** we can now destroy it.
+ */
if (s->closing) {
D(" closing because 'closing' is set after write\n");
s->close(s);
return;
}
- /* no more packets queued, so we can ignore
- ** writable events again and tell our peer
- ** to resume writing
- */
+ /* no more packets queued, so we can ignore
+ ** writable events again and tell our peer
+ ** to resume writing
+ */
fdevent_del(&s->fde, FDE_WRITE);
s->peer->ready(s->peer);
}
- if(ev & FDE_READ){
+ if (ev & FDE_READ) {
apacket *p = get_apacket();
unsigned char *x = p->data;
size_t avail = MAX_PAYLOAD;
int r;
int is_eof = 0;
- while(avail > 0) {
+ while (avail > 0) {
r = adb_read(fd, x, avail);
- D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu\n", s->id, s->fd, r, r<0?errno:0, avail);
- if(r > 0) {
+ D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu\n",
+ s->id, s->fd, r, r < 0 ? errno : 0, avail);
+ if (r == -1) {
+ if (errno == EAGAIN) {
+ break;
+ }
+ } else if (r > 0) {
avail -= r;
x += r;
continue;
}
- if(r < 0) {
- if(errno == EAGAIN) break;
- if(errno == EINTR) continue;
- }
- /* r = 0 or unhandled error */
+ /* r = 0 or unhandled error */
is_eof = 1;
break;
}
D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d\n",
s->id, s->fd, r, is_eof, s->fde.force_eof);
- if((avail == MAX_PAYLOAD) || (s->peer == 0)) {
+ if ((avail == MAX_PAYLOAD) || (s->peer == 0)) {
put_apacket(p);
} else {
p->len = MAX_PAYLOAD - avail;
r = s->peer->enqueue(s->peer, p);
- D("LS(%d): fd=%d post peer->enqueue(). r=%d\n", s->id, s->fd, r);
+ D("LS(%d): fd=%d post peer->enqueue(). r=%d\n", s->id, s->fd,
+ r);
- if(r < 0) {
+ if (r < 0) {
/* error return means they closed us as a side-effect
** and we must return immediately.
**
@@ -387,7 +390,7 @@
return;
}
- if(r > 0) {
+ if (r > 0) {
/* if the remote cannot accept further events,
** we disable notification of READs. They'll
** be enabled again when we get a call to ready()
@@ -396,13 +399,14 @@
}
}
/* Don't allow a forced eof if data is still there */
- if((s->fde.force_eof && !r) || is_eof) {
- D(" closing because is_eof=%d r=%d s->fde.force_eof=%d\n", is_eof, r, s->fde.force_eof);
+ if ((s->fde.force_eof && !r) || is_eof) {
+ D(" closing because is_eof=%d r=%d s->fde.force_eof=%d\n",
+ is_eof, r, s->fde.force_eof);
s->close(s);
}
}
- if(ev & FDE_ERROR){
+ if (ev & FDE_ERROR){
/* this should be caught be the next read or write
** catching it here means we may skip the last few
** bytes of readable data.
@@ -415,7 +419,7 @@
asocket *create_local_socket(int fd)
{
- asocket *s = calloc(1, sizeof(asocket));
+ asocket *s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));
if (s == NULL) fatal("cannot allocate socket");
s->fd = fd;
s->enqueue = local_socket_enqueue;
@@ -539,8 +543,8 @@
static void remote_socket_disconnect(void* _s, atransport* t)
{
- asocket* s = _s;
- asocket* peer = s->peer;
+ asocket* s = reinterpret_cast<asocket*>(_s);
+ asocket* peer = s->peer;
D("remote_socket_disconnect RS(%d)\n", s->id);
if (peer) {
@@ -557,12 +561,9 @@
Returns a new non-NULL asocket handle. */
asocket *create_remote_socket(unsigned id, atransport *t)
{
- asocket* s;
- adisconnect* dis;
-
if (id == 0) fatal("invalid remote socket id (0)");
- s = calloc(1, sizeof(aremotesocket));
- dis = &((aremotesocket*)s)->disconnect;
+ asocket* s = reinterpret_cast<asocket*>(calloc(1, sizeof(aremotesocket)));
+ adisconnect* dis = &reinterpret_cast<aremotesocket*>(s)->disconnect;
if (s == NULL) fatal("cannot allocate socket");
s->id = id;
@@ -824,7 +825,7 @@
}
#else /* !ADB_HOST */
if (s->transport == NULL) {
- char* error_string = "unknown failure";
+ const char* error_string = "unknown failure";
s->transport = acquire_one_transport (CS_ANY,
kTransportAny, NULL, &error_string);
@@ -892,7 +893,7 @@
static asocket *create_smart_socket(void)
{
D("Creating smart socket \n");
- asocket *s = calloc(1, sizeof(asocket));
+ asocket *s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));
if (s == NULL) fatal("cannot allocate socket");
s->enqueue = smart_socket_enqueue;
s->ready = smart_socket_ready;
diff --git a/adb/test_track_devices.c b/adb/test_track_devices.cpp
similarity index 100%
rename from adb/test_track_devices.c
rename to adb/test_track_devices.cpp
diff --git a/adb/test_track_jdwp.c b/adb/test_track_jdwp.cpp
similarity index 100%
rename from adb/test_track_jdwp.c
rename to adb/test_track_jdwp.cpp
diff --git a/adb/tests/test_adb.py b/adb/tests/test_adb.py
index 49ead73..f111b043 100755
--- a/adb/tests/test_adb.py
+++ b/adb/tests/test_adb.py
@@ -237,16 +237,36 @@
version_num = True
self.assertTrue(version_num)
- def test_root_unroot(self):
- """Make sure that adb root and adb unroot work, using id(1)."""
+ def _test_root(self):
adb = AdbWrapper()
adb.root()
adb.wait()
self.assertEqual("root", adb.shell("id -un").strip())
+
+ def _test_unroot(self):
+ adb = AdbWrapper()
adb.unroot()
adb.wait()
self.assertEqual("shell", adb.shell("id -un").strip())
+ def test_root_unroot(self):
+ """Make sure that adb root and adb unroot work, using id(1)."""
+ adb = AdbWrapper()
+ original_user = adb.shell("id -un").strip()
+ try:
+ if original_user == "root":
+ self._test_unroot()
+ self._test_root()
+ elif original_user == "shell":
+ self._test_root()
+ self._test_unroot()
+ finally:
+ if original_user == "root":
+ adb.root()
+ else:
+ adb.unroot()
+ adb.wait()
+
class AdbFile(unittest.TestCase):
SCRATCH_DIR = "/data/local/tmp"
diff --git a/adb/transport.c b/adb/transport.cpp
similarity index 97%
rename from adb/transport.c
rename to adb/transport.cpp
index e2c204e..1f8ac03 100644
--- a/adb/transport.c
+++ b/adb/transport.cpp
@@ -221,7 +221,7 @@
static void transport_socket_events(int fd, unsigned events, void *_t)
{
- atransport *t = _t;
+ atransport *t = reinterpret_cast<atransport*>(_t);
D("transport_socket_events(fd=%d, events=%04x,...)\n", fd, events);
if(events & FDE_READ){
apacket *p = 0;
@@ -278,7 +278,7 @@
static void *output_thread(void *_t)
{
- atransport *t = _t;
+ atransport *t = reinterpret_cast<atransport*>(_t);
apacket *p;
D("%s: starting transport output thread on fd %d, SYNC online (%d)\n",
@@ -333,7 +333,7 @@
static void *input_thread(void *_t)
{
- atransport *t = _t;
+ atransport *t = reinterpret_cast<atransport*>(_t);
apacket *p;
int active = 0;
@@ -494,7 +494,8 @@
asocket*
create_device_tracker(void)
{
- device_tracker* tracker = calloc(1,sizeof(*tracker));
+ device_tracker* tracker = reinterpret_cast<device_tracker*>(
+ calloc(1, sizeof(*tracker)));
if(tracker == 0) fatal("cannot allocate device tracker");
@@ -799,7 +800,8 @@
return !*to_test;
}
-atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char** error_out)
+atransport *acquire_one_transport(int state, transport_type ttype,
+ const char* serial, const char** error_out)
{
atransport *t;
atransport *result = NULL;
@@ -1007,7 +1009,8 @@
int register_socket_transport(int s, const char *serial, int port, int local)
{
- atransport *t = calloc(1, sizeof(atransport));
+ atransport *t = reinterpret_cast<atransport*>(
+ calloc(1, sizeof(atransport)));
atransport *n;
char buff[32];
@@ -1106,7 +1109,8 @@
void register_usb_transport(usb_handle *usb, const char *serial, const char *devpath, unsigned writeable)
{
- atransport *t = calloc(1, sizeof(atransport));
+ atransport *t = reinterpret_cast<atransport*>(
+ calloc(1, sizeof(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));
diff --git a/adb/transport.h b/adb/transport.h
index 352bbe4..36a0e40 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -37,7 +37,7 @@
* If no suitable transport is found, error is set.
*/
atransport* acquire_one_transport(int state, transport_type ttype,
- const char* serial, char** error_out);
+ const char* serial, const char** error_out);
void add_transport_disconnect(atransport* t, adisconnect* dis);
void remove_transport_disconnect(atransport* t, adisconnect* dis);
void kick_transport(atransport* t);
diff --git a/adb/transport_local.c b/adb/transport_local.cpp
similarity index 100%
rename from adb/transport_local.c
rename to adb/transport_local.cpp
diff --git a/adb/transport_usb.c b/adb/transport_usb.cpp
similarity index 100%
rename from adb/transport_usb.c
rename to adb/transport_usb.cpp
diff --git a/adb/usb_linux.c b/adb/usb_linux.cpp
similarity index 98%
rename from adb/usb_linux.c
rename to adb/usb_linux.cpp
index d03f8be..c01ec8c 100644
--- a/adb/usb_linux.c
+++ b/adb/usb_linux.cpp
@@ -574,7 +574,6 @@
unsigned char ep_in, unsigned char ep_out,
int interface, int serial_index, unsigned zero_mask)
{
- usb_handle* usb = 0;
int n = 0;
char serial[256];
@@ -587,8 +586,9 @@
** name, we have no further work to do.
*/
adb_mutex_lock(&usb_lock);
- for(usb = handle_list.next; usb != &handle_list; usb = usb->next){
- if(!strcmp(usb->fname, dev_name)) {
+ for (usb_handle* usb = handle_list.next; usb != &handle_list;
+ usb = usb->next) {
+ if (!strcmp(usb->fname, dev_name)) {
adb_mutex_unlock(&usb_lock);
return;
}
@@ -597,7 +597,8 @@
D("[ usb located new device %s (%d/%d/%d) ]\n",
dev_name, ep_in, ep_out, interface);
- usb = calloc(1, sizeof(usb_handle));
+ usb_handle* usb = reinterpret_cast<usb_handle*>(
+ calloc(1, sizeof(usb_handle)));
strcpy(usb->fname, dev_name);
usb->ep_in = ep_in;
usb->ep_out = ep_out;
diff --git a/adb/usb_windows.c b/adb/usb_windows.cpp
similarity index 100%
rename from adb/usb_windows.c
rename to adb/usb_windows.cpp
diff --git a/adf/libadf/Android.mk b/adf/libadf/Android.mk
index 908aa6c..7df354b 100644
--- a/adf/libadf/Android.mk
+++ b/adf/libadf/Android.mk
@@ -18,6 +18,7 @@
LOCAL_SRC_FILES := adf.c
LOCAL_MODULE := libadf
LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS += -Werror
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_C_INCLUDES += $(LOCAL_EXPORT_C_INCLUDE_DIRS)
include $(BUILD_STATIC_LIBRARY)
diff --git a/adf/libadf/tests/Android.mk b/adf/libadf/tests/Android.mk
index 93efafa..68e5817 100644
--- a/adf/libadf/tests/Android.mk
+++ b/adf/libadf/tests/Android.mk
@@ -19,4 +19,5 @@
LOCAL_SRC_FILES := adf_test.cpp
LOCAL_MODULE := adf-unit-tests
LOCAL_STATIC_LIBRARIES := libadf
+LOCAL_CFLAGS += -Werror
include $(BUILD_NATIVE_TEST)
diff --git a/adf/libadf/tests/adf_test.cpp b/adf/libadf/tests/adf_test.cpp
index d95330d..01b2785 100644
--- a/adf/libadf/tests/adf_test.cpp
+++ b/adf/libadf/tests/adf_test.cpp
@@ -182,9 +182,9 @@
ASSERT_GE(err, 0) << "getting ADF device data failed: " << strerror(-err);
EXPECT_LT(data.n_attachments, ADF_MAX_ATTACHMENTS);
- EXPECT_GT(data.n_allowed_attachments, 0);
+ EXPECT_GT(data.n_allowed_attachments, 0U);
EXPECT_LT(data.n_allowed_attachments, ADF_MAX_ATTACHMENTS);
- EXPECT_LT(data.custom_data_size, ADF_MAX_CUSTOM_DATA_SIZE);
+ EXPECT_LT(data.custom_data_size, (size_t)ADF_MAX_CUSTOM_DATA_SIZE);
adf_free_device_data(&data);
}
@@ -195,8 +195,8 @@
EXPECT_LT(data.type, ADF_INTF_TYPE_MAX);
EXPECT_LE(data.dpms_state, DRM_MODE_DPMS_OFF);
EXPECT_EQ(1, data.hotplug_detect);
- EXPECT_GT(data.n_available_modes, 0);
- EXPECT_LT(data.custom_data_size, ADF_MAX_CUSTOM_DATA_SIZE);
+ EXPECT_GT(data.n_available_modes, 0U);
+ EXPECT_LT(data.custom_data_size, (size_t)ADF_MAX_CUSTOM_DATA_SIZE);
adf_free_interface_data(&data);
}
@@ -206,9 +206,9 @@
ASSERT_GE(err, 0) << "getting ADF overlay engine failed: " <<
strerror(-err);
- EXPECT_GT(data.n_supported_formats, 0);
+ EXPECT_GT(data.n_supported_formats, 0U);
EXPECT_LT(data.n_supported_formats, ADF_MAX_SUPPORTED_FORMATS);
- EXPECT_LT(data.custom_data_size, ADF_MAX_CUSTOM_DATA_SIZE);
+ EXPECT_LT(data.custom_data_size, (size_t)ADF_MAX_CUSTOM_DATA_SIZE);
adf_free_overlay_engine_data(&data);
}
diff --git a/adf/libadfhwc/Android.mk b/adf/libadfhwc/Android.mk
index acea322..898f9c9 100644
--- a/adf/libadfhwc/Android.mk
+++ b/adf/libadfhwc/Android.mk
@@ -19,7 +19,7 @@
LOCAL_MODULE := libadfhwc
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libadf liblog libutils
-LOCAL_CFLAGS += -DLOG_TAG=\"adfhwc\"
+LOCAL_CFLAGS += -DLOG_TAG=\"adfhwc\" -Werror
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_C_INCLUDES += $(LOCAL_EXPORT_C_INCLUDE_DIRS)
include $(BUILD_STATIC_LIBRARY)
diff --git a/base/.clang-format b/base/.clang-format
new file mode 100644
index 0000000..2b83a1f
--- /dev/null
+++ b/base/.clang-format
@@ -0,0 +1,11 @@
+BasedOnStyle: Google
+AllowShortBlocksOnASingleLine: false
+AllowShortFunctionsOnASingleLine: false
+
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IndentWidth: 2
+PointerAlignment: Left
+TabWidth: 2
+UseTab: Never
+PenaltyExcessCharacter: 32
diff --git a/base/Android.mk b/base/Android.mk
new file mode 100644
index 0000000..0e1a9b6
--- /dev/null
+++ b/base/Android.mk
@@ -0,0 +1,98 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+libbase_src_files := \
+ file.cpp \
+ stringprintf.cpp \
+ strings.cpp \
+
+libbase_test_src_files := \
+ file_test.cpp \
+ stringprintf_test.cpp \
+ strings_test.cpp \
+
+libbase_cppflags := \
+ -Wall \
+ -Wextra \
+ -Werror \
+
+# Device
+# ------------------------------------------------------------------------------
+include $(CLEAR_VARS)
+LOCAL_MODULE := libbase
+LOCAL_CLANG := true
+LOCAL_SRC_FILES := $(libbase_src_files)
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_CPPFLAGS := $(libbase_cppflags)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_MULTILIB := both
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libbase
+LOCAL_CLANG := true
+LOCAL_WHOLE_STATIC_LIBRARIES := libbase
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_MULTILIB := both
+include $(BUILD_SHARED_LIBRARY)
+
+# Host
+# ------------------------------------------------------------------------------
+include $(CLEAR_VARS)
+LOCAL_MODULE := libbase
+LOCAL_CLANG := true
+LOCAL_SRC_FILES := $(libbase_src_files)
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_CPPFLAGS := $(libbase_cppflags)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_MULTILIB := both
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libbase
+LOCAL_CLANG := true
+LOCAL_WHOLE_STATIC_LIBRARIES := libbase
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_MULTILIB := both
+include $(BUILD_HOST_SHARED_LIBRARY)
+
+# Tests
+# ------------------------------------------------------------------------------
+include $(CLEAR_VARS)
+LOCAL_MODULE := libbase_test
+LOCAL_CLANG := true
+LOCAL_SRC_FILES := $(libbase_test_src_files)
+LOCAL_CPPFLAGS := $(libbase_cppflags)
+LOCAL_SHARED_LIBRARIES := libbase
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+include $(BUILD_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libbase_test
+LOCAL_CLANG := true
+LOCAL_SRC_FILES := $(libbase_test_src_files)
+LOCAL_CPPFLAGS := $(libbase_cppflags)
+LOCAL_SHARED_LIBRARIES := libbase
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+include $(BUILD_HOST_NATIVE_TEST)
diff --git a/base/CPPLINT.cfg b/base/CPPLINT.cfg
new file mode 100644
index 0000000..5ee068e
--- /dev/null
+++ b/base/CPPLINT.cfg
@@ -0,0 +1,2 @@
+set noparent
+filter=-build/header_guard
diff --git a/libutils/file.cpp b/base/file.cpp
similarity index 68%
rename from libutils/file.cpp
rename to base/file.cpp
index 0690bc2..118071e 100644
--- a/libutils/file.cpp
+++ b/base/file.cpp
@@ -14,19 +14,23 @@
* limitations under the License.
*/
-#define LOG_TAG "utils.file"
-#include <cutils/log.h>
-
-#include "utils/file.h"
+#include "base/file.h"
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <utils/Compat.h> // For TEMP_FAILURE_RETRY on Darwin.
+#include <string>
-bool android::ReadFdToString(int fd, std::string* content) {
+#include "base/macros.h" // For TEMP_FAILURE_RETRY on Darwin.
+#define LOG_TAG "base.file"
+#include "cutils/log.h"
+
+namespace android {
+namespace base {
+
+bool ReadFdToString(int fd, std::string* content) {
content->clear();
char buf[BUFSIZ];
@@ -37,10 +41,11 @@
return (n == 0) ? true : false;
}
-bool android::ReadFileToString(const std::string& path, std::string* content) {
+bool ReadFileToString(const std::string& path, std::string* content) {
content->clear();
- int fd = TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
+ int fd =
+ TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
if (fd == -1) {
return false;
}
@@ -49,7 +54,7 @@
return result;
}
-bool android::WriteStringToFd(const std::string& content, int fd) {
+bool WriteStringToFd(const std::string& content, int fd) {
const char* p = content.data();
size_t left = content.size();
while (left > 0) {
@@ -72,18 +77,18 @@
}
#if !defined(_WIN32)
-bool android::WriteStringToFile(const std::string& content, const std::string& path,
- mode_t mode, uid_t owner, gid_t group) {
- int fd = TEMP_FAILURE_RETRY(open(path.c_str(),
- O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
- mode));
+bool WriteStringToFile(const std::string& content, const std::string& path,
+ mode_t mode, uid_t owner, gid_t group) {
+ int fd = TEMP_FAILURE_RETRY(
+ open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
+ mode));
if (fd == -1) {
ALOGE("android::WriteStringToFile open failed: %s", strerror(errno));
return false;
}
- // We do an explicit fchmod here because we assume that the caller really meant what they
- // said and doesn't want the umask-influenced mode.
+ // We do an explicit fchmod here because we assume that the caller really
+ // meant what they said and doesn't want the umask-influenced mode.
if (fchmod(fd, mode) == -1) {
ALOGE("android::WriteStringToFile fchmod failed: %s", strerror(errno));
return CleanUpAfterFailedWrite(path);
@@ -101,10 +106,10 @@
}
#endif
-bool android::WriteStringToFile(const std::string& content, const std::string& path) {
- int fd = TEMP_FAILURE_RETRY(open(path.c_str(),
- O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
- DEFFILEMODE));
+bool WriteStringToFile(const std::string& content, const std::string& path) {
+ int fd = TEMP_FAILURE_RETRY(
+ open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
+ DEFFILEMODE));
if (fd == -1) {
return false;
}
@@ -113,3 +118,6 @@
TEMP_FAILURE_RETRY(close(fd));
return result || CleanUpAfterFailedWrite(path);
}
+
+} // namespace base
+} // namespace android
diff --git a/libutils/tests/file_test.cpp b/base/file_test.cpp
similarity index 72%
rename from libutils/tests/file_test.cpp
rename to base/file_test.cpp
index cea18b6..34b8755 100644
--- a/libutils/tests/file_test.cpp
+++ b/base/file_test.cpp
@@ -14,12 +14,15 @@
* limitations under the License.
*/
-#include "utils/file.h"
+#include "base/file.h"
+
+#include <gtest/gtest.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
-#include <gtest/gtest.h>
+
+#include <string>
class TemporaryFile {
public:
@@ -48,14 +51,14 @@
TEST(file, ReadFileToString_ENOENT) {
std::string s("hello");
errno = 0;
- ASSERT_FALSE(android::ReadFileToString("/proc/does-not-exist", &s));
+ ASSERT_FALSE(android::base::ReadFileToString("/proc/does-not-exist", &s));
EXPECT_EQ(ENOENT, errno);
- EXPECT_EQ("", s); // s was cleared.
+ EXPECT_EQ("", s); // s was cleared.
}
TEST(file, ReadFileToString_success) {
std::string s("hello");
- ASSERT_TRUE(android::ReadFileToString("/proc/version", &s)) << errno;
+ ASSERT_TRUE(android::base::ReadFileToString("/proc/version", &s)) << errno;
EXPECT_GT(s.length(), 6U);
EXPECT_EQ('\n', s[s.length() - 1]);
s[5] = 0;
@@ -65,34 +68,36 @@
TEST(file, WriteStringToFile) {
TemporaryFile tf;
ASSERT_TRUE(tf.fd != -1);
- ASSERT_TRUE(android::WriteStringToFile("abc", tf.filename)) << errno;
+ ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.filename)) << errno;
std::string s;
- ASSERT_TRUE(android::ReadFileToString(tf.filename, &s)) << errno;
+ ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s)) << errno;
EXPECT_EQ("abc", s);
}
TEST(file, WriteStringToFile2) {
TemporaryFile tf;
ASSERT_TRUE(tf.fd != -1);
- ASSERT_TRUE(android::WriteStringToFile("abc", tf.filename, 0660, getuid(), getgid())) << errno;
+ ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.filename, 0660,
+ getuid(), getgid()))
+ << errno;
struct stat sb;
ASSERT_EQ(0, stat(tf.filename, &sb));
ASSERT_EQ(0660U, (sb.st_mode & ~S_IFMT));
ASSERT_EQ(getuid(), sb.st_uid);
ASSERT_EQ(getgid(), sb.st_gid);
std::string s;
- ASSERT_TRUE(android::ReadFileToString(tf.filename, &s)) << errno;
+ ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s)) << errno;
EXPECT_EQ("abc", s);
}
TEST(file, WriteStringToFd) {
TemporaryFile tf;
ASSERT_TRUE(tf.fd != -1);
- ASSERT_TRUE(android::WriteStringToFd("abc", tf.fd));
+ ASSERT_TRUE(android::base::WriteStringToFd("abc", tf.fd));
ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)) << errno;
std::string s;
- ASSERT_TRUE(android::ReadFdToString(tf.fd, &s)) << errno;
+ ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s)) << errno;
EXPECT_EQ("abc", s);
}
diff --git a/include/utils/file.h b/base/include/base/file.h
similarity index 89%
rename from include/utils/file.h
rename to base/include/base/file.h
index a80afb1..ef97742 100644
--- a/include/utils/file.h
+++ b/base/include/base/file.h
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-#ifndef UTILS_FILE_H
-#define UTILS_FILE_H
+#ifndef BASE_FILE_H
+#define BASE_FILE_H
-#include <string>
#include <sys/stat.h>
+#include <string>
namespace android {
+namespace base {
bool ReadFdToString(int fd, std::string* content);
bool ReadFileToString(const std::string& path, std::string* content);
@@ -33,6 +34,7 @@
mode_t mode, uid_t owner, gid_t group);
#endif
-} // namespace android
+} // namespace base
+} // namespace android
-#endif
+#endif // BASE_FILE_H
diff --git a/base/include/base/macros.h b/base/include/base/macros.h
new file mode 100644
index 0000000..b1ce7c6
--- /dev/null
+++ b/base/include/base/macros.h
@@ -0,0 +1,188 @@
+/*
+ * 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 UTILS_MACROS_H
+#define UTILS_MACROS_H
+
+#include <stddef.h> // for size_t
+#include <unistd.h> // for TEMP_FAILURE_RETRY
+
+// bionic and glibc both have TEMP_FAILURE_RETRY, but eg Mac OS' libc doesn't.
+#ifndef TEMP_FAILURE_RETRY
+#define TEMP_FAILURE_RETRY(exp) \
+ ({ \
+ decltype(exp) _rc; \
+ do { \
+ _rc = (exp); \
+ } while (_rc == -1 && errno == EINTR); \
+ _rc; \
+ })
+#endif
+
+// A macro to disallow the copy constructor and operator= functions
+// This must be placed in the private: declarations for a class.
+//
+// For disallowing only assign or copy, delete the relevant operator or
+// constructor, for example:
+// void operator=(const TypeName&) = delete;
+// Note, that most uses of DISALLOW_ASSIGN and DISALLOW_COPY are broken
+// semantically, one should either use disallow both or neither. Try to
+// avoid these in new code.
+//
+// When building with C++11 toolchains, just use the language support
+// for explicitly deleted methods.
+#if __cplusplus >= 201103L
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&) = delete; \
+ void operator=(const TypeName&) = delete
+#else
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&); \
+ void operator=(const TypeName&)
+#endif
+
+// A macro to disallow all the implicit constructors, namely the
+// default constructor, copy constructor and operator= functions.
+//
+// This should be used in the private: declarations for a class
+// that wants to prevent anyone from instantiating it. This is
+// especially useful for classes containing only static methods.
+#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
+ TypeName(); \
+ DISALLOW_COPY_AND_ASSIGN(TypeName)
+
+// The arraysize(arr) macro returns the # of elements in an array arr.
+// The expression is a compile-time constant, and therefore can be
+// used in defining new arrays, for example. If you use arraysize on
+// a pointer by mistake, you will get a compile-time error.
+//
+// One caveat is that arraysize() doesn't accept any array of an
+// anonymous type or a type defined inside a function. In these rare
+// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below. This is
+// due to a limitation in C++'s template system. The limitation might
+// eventually be removed, but it hasn't happened yet.
+
+// This template function declaration is used in defining arraysize.
+// Note that the function doesn't need an implementation, as we only
+// use its type.
+template <typename T, size_t N>
+char(&ArraySizeHelper(T(&array)[N]))[N]; // NOLINT(readability/casting)
+
+#define arraysize(array) (sizeof(ArraySizeHelper(array)))
+
+// ARRAYSIZE_UNSAFE performs essentially the same calculation as arraysize,
+// but can be used on anonymous types or types defined inside
+// functions. It's less safe than arraysize as it accepts some
+// (although not all) pointers. Therefore, you should use arraysize
+// whenever possible.
+//
+// The expression ARRAYSIZE_UNSAFE(a) is a compile-time constant of type
+// size_t.
+//
+// ARRAYSIZE_UNSAFE catches a few type errors. If you see a compiler error
+//
+// "warning: division by zero in ..."
+//
+// when using ARRAYSIZE_UNSAFE, you are (wrongfully) giving it a pointer.
+// You should only use ARRAYSIZE_UNSAFE on statically allocated arrays.
+//
+// The following comments are on the implementation details, and can
+// be ignored by the users.
+//
+// ARRAYSIZE_UNSAFE(arr) works by inspecting sizeof(arr) (the # of bytes in
+// the array) and sizeof(*(arr)) (the # of bytes in one array
+// element). If the former is divisible by the latter, perhaps arr is
+// indeed an array, in which case the division result is the # of
+// elements in the array. Otherwise, arr cannot possibly be an array,
+// and we generate a compiler error to prevent the code from
+// compiling.
+//
+// Since the size of bool is implementation-defined, we need to cast
+// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
+// result has type size_t.
+//
+// This macro is not perfect as it wrongfully accepts certain
+// pointers, namely where the pointer size is divisible by the pointee
+// size. Since all our code has to go through a 32-bit compiler,
+// where a pointer is 4 bytes, this means all pointers to a type whose
+// size is 3 or greater than 4 will be (righteously) rejected.
+#define ARRAYSIZE_UNSAFE(a) \
+ ((sizeof(a) / sizeof(*(a))) / \
+ static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
+
+#define LIKELY(x) __builtin_expect((x), true)
+#define UNLIKELY(x) __builtin_expect((x), false)
+
+#define WARN_UNUSED __attribute__((warn_unused_result))
+
+// A deprecated function to call to create a false use of the parameter, for
+// example:
+// int foo(int x) { UNUSED(x); return 10; }
+// to avoid compiler warnings. Going forward we prefer ATTRIBUTE_UNUSED.
+template <typename... T>
+void UNUSED(const T&...) {
+}
+
+// An attribute to place on a parameter to a function, for example:
+// int foo(int x ATTRIBUTE_UNUSED) { return 10; }
+// to avoid compiler warnings.
+#define ATTRIBUTE_UNUSED __attribute__((__unused__))
+
+// The FALLTHROUGH_INTENDED macro can be used to annotate implicit fall-through
+// between switch labels:
+// switch (x) {
+// case 40:
+// case 41:
+// if (truth_is_out_there) {
+// ++x;
+// FALLTHROUGH_INTENDED; // Use instead of/along with annotations in
+// // comments.
+// } else {
+// return x;
+// }
+// case 42:
+// ...
+//
+// As shown in the example above, the FALLTHROUGH_INTENDED macro should be
+// followed by a semicolon. It is designed to mimic control-flow statements
+// like 'break;', so it can be placed in most places where 'break;' can, but
+// only if there are no statements on the execution path between it and the
+// next switch label.
+//
+// When compiled with clang in C++11 mode, the FALLTHROUGH_INTENDED macro is
+// expanded to [[clang::fallthrough]] attribute, which is analysed when
+// performing switch labels fall-through diagnostic ('-Wimplicit-fallthrough').
+// See clang documentation on language extensions for details:
+// http://clang.llvm.org/docs/LanguageExtensions.html#clang__fallthrough
+//
+// When used with unsupported compilers, the FALLTHROUGH_INTENDED macro has no
+// effect on diagnostics.
+//
+// In either case this macro has no effect on runtime behavior and performance
+// of code.
+#if defined(__clang__) && __cplusplus >= 201103L && defined(__has_warning)
+#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
+#define FALLTHROUGH_INTENDED [[clang::fallthrough]] // NOLINT
+#endif
+#endif
+
+#ifndef FALLTHROUGH_INTENDED
+#define FALLTHROUGH_INTENDED \
+ do { \
+ } while (0)
+#endif
+
+#endif // UTILS_MACROS_H
diff --git a/include/utils/stringprintf.h b/base/include/base/stringprintf.h
similarity index 82%
rename from include/utils/stringprintf.h
rename to base/include/base/stringprintf.h
index e7dbac7..195c1de 100644
--- a/include/utils/stringprintf.h
+++ b/base/include/base/stringprintf.h
@@ -14,25 +14,27 @@
* limitations under the License.
*/
-#ifndef UTILS_STRINGPRINTF_H_
-#define UTILS_STRINGPRINTF_H_
+#ifndef BASE_STRINGPRINTF_H
+#define BASE_STRINGPRINTF_H
#include <stdarg.h>
#include <string>
namespace android {
+namespace base {
// Returns a string corresponding to printf-like formatting of the arguments.
std::string StringPrintf(const char* fmt, ...)
- __attribute__((__format__(__printf__, 1, 2)));
+ __attribute__((__format__(__printf__, 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__(__printf__, 2, 3)));
// Appends a printf-like formatting of the arguments to 'dst'.
void StringAppendV(std::string* dst, const char* format, va_list ap);
+} // namespace base
} // namespace android
-#endif
+#endif // BASE_STRINGPRINTF_H
diff --git a/base/include/base/strings.h b/base/include/base/strings.h
new file mode 100644
index 0000000..5ddfbbd
--- /dev/null
+++ b/base/include/base/strings.h
@@ -0,0 +1,47 @@
+/*
+ * 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 BASE_STRINGS_H
+#define BASE_STRINGS_H
+
+#include <string>
+#include <vector>
+
+namespace android {
+namespace base {
+
+// Splits a string using the given separator character into a vector of strings.
+// Empty strings will be omitted.
+void Split(const std::string& s, char separator,
+ std::vector<std::string>* result);
+
+// 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);
+
+// Tests whether 's' starts with 'prefix'.
+bool StartsWith(const std::string& s, const char* prefix);
+
+// Tests whether 's' ends with 'suffix'.
+bool EndsWith(const std::string& s, const char* suffix);
+
+} // namespace base
+} // namespace android
+
+#endif // BASE_STRINGS_H
diff --git a/libutils/stringprintf.cpp b/base/stringprintf.cpp
similarity index 84%
rename from libutils/stringprintf.cpp
rename to base/stringprintf.cpp
index 5eaa293..d55ff52 100644
--- a/libutils/stringprintf.cpp
+++ b/base/stringprintf.cpp
@@ -14,11 +14,16 @@
* limitations under the License.
*/
-#include <utils/stringprintf.h>
+#include "base/stringprintf.h"
#include <stdio.h>
-void android::StringAppendV(std::string* dst, const char* format, va_list ap) {
+#include <string>
+
+namespace android {
+namespace base {
+
+void StringAppendV(std::string* dst, const char* format, va_list ap) {
// First try with a small fixed size buffer
char space[1024];
@@ -45,7 +50,7 @@
// Increase the buffer size to the size requested by vsnprintf,
// plus one for the closing \0.
- int length = result+1;
+ int length = result + 1;
char* buf = new char[length];
// Restore the va_list before we use it again
@@ -60,7 +65,7 @@
delete[] buf;
}
-std::string android::StringPrintf(const char* fmt, ...) {
+std::string StringPrintf(const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
std::string result;
@@ -69,9 +74,12 @@
return result;
}
-void android::StringAppendF(std::string* dst, const char* format, ...) {
+void StringAppendF(std::string* dst, const char* format, ...) {
va_list ap;
va_start(ap, format);
StringAppendV(dst, format, ap);
va_end(ap);
}
+
+} // namespace base
+} // namespace android
diff --git a/libutils/tests/stringprintf_test.cpp b/base/stringprintf_test.cpp
similarity index 76%
rename from libutils/tests/stringprintf_test.cpp
rename to base/stringprintf_test.cpp
index f995452..5cc2086 100644
--- a/libutils/tests/stringprintf_test.cpp
+++ b/base/stringprintf_test.cpp
@@ -14,25 +14,27 @@
* limitations under the License.
*/
-#include <utils/stringprintf.h>
+#include "base/stringprintf.h"
#include <gtest/gtest.h>
+#include <string>
+
TEST(StringPrintfTest, HexSizeT) {
size_t size = 0x00107e59;
- EXPECT_EQ("00107e59", android::StringPrintf("%08zx", size));
- EXPECT_EQ("0x00107e59", android::StringPrintf("0x%08zx", size));
+ EXPECT_EQ("00107e59", android::base::StringPrintf("%08zx", size));
+ EXPECT_EQ("0x00107e59", android::base::StringPrintf("0x%08zx", size));
}
TEST(StringPrintfTest, StringAppendF) {
std::string s("a");
- android::StringAppendF(&s, "b");
+ android::base::StringAppendF(&s, "b");
EXPECT_EQ("ab", s);
}
TEST(StringPrintfTest, Errno) {
errno = 123;
- android::StringPrintf("hello %s", "world");
+ android::base::StringPrintf("hello %s", "world");
EXPECT_EQ(123, errno);
}
@@ -40,7 +42,7 @@
char* buf = new char[n + 1];
memset(buf, 'x', n);
buf[n] = '\0';
- std::string s(android::StringPrintf("%s", buf));
+ std::string s(android::base::StringPrintf("%s", buf));
EXPECT_EQ(buf, s);
delete[] buf;
}
diff --git a/base/strings.cpp b/base/strings.cpp
new file mode 100644
index 0000000..224a46f
--- /dev/null
+++ b/base/strings.cpp
@@ -0,0 +1,111 @@
+/*
+ * 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 "base/strings.h"
+
+#include <string>
+#include <vector>
+
+namespace android {
+namespace base {
+
+void Split(const std::string& s, char separator,
+ std::vector<std::string>* result) {
+ const char* p = s.data();
+ const char* end = p + s.size();
+ while (p != end) {
+ if (*p == separator) {
+ ++p;
+ } else {
+ const char* start = p;
+ while (++p != end && *p != separator) {
+ // Skip to the next occurrence of the separator.
+ }
+ result->push_back(std::string(start, p - start));
+ }
+ }
+}
+
+std::string Trim(const std::string& s) {
+ std::string result;
+
+ if (s.size() == 0) {
+ return result;
+ }
+
+ size_t start_index = 0;
+ size_t end_index = s.size() - 1;
+
+ // Skip initial whitespace.
+ while (start_index < s.size()) {
+ if (!isspace(s[start_index])) {
+ break;
+ }
+ start_index++;
+ }
+
+ // Skip terminating whitespace.
+ while (end_index >= start_index) {
+ if (!isspace(s[end_index])) {
+ break;
+ }
+ end_index--;
+ }
+
+ // All spaces, no beef.
+ if (end_index < start_index) {
+ return "";
+ }
+ // Start_index is the first non-space, end_index is the last one.
+ 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);
+
+bool StartsWith(const std::string& s, const char* prefix) {
+ return s.compare(0, strlen(prefix), prefix) == 0;
+}
+
+bool EndsWith(const std::string& s, const char* suffix) {
+ size_t suffix_length = strlen(suffix);
+ size_t string_length = s.size();
+ if (suffix_length > string_length) {
+ return false;
+ }
+ size_t offset = string_length - suffix_length;
+ return s.compare(offset, suffix_length, suffix) == 0;
+}
+
+} // namespace base
+} // namespace android
diff --git a/base/strings_test.cpp b/base/strings_test.cpp
new file mode 100644
index 0000000..824598d
--- /dev/null
+++ b/base/strings_test.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "base/strings.h"
+
+#include <gtest/gtest.h>
+
+#include <string>
+#include <vector>
+
+TEST(strings, split_empty) {
+ std::vector<std::string> parts;
+ android::base::Split("", '\0', &parts);
+ ASSERT_EQ(0U, parts.size());
+}
+
+TEST(strings, split_single) {
+ std::vector<std::string> parts;
+ android::base::Split("foo", ',', &parts);
+ ASSERT_EQ(1U, parts.size());
+ ASSERT_EQ("foo", parts[0]);
+}
+
+TEST(strings, split_simple) {
+ std::vector<std::string> parts;
+ android::base::Split("foo,bar,baz", ',', &parts);
+ ASSERT_EQ(3U, parts.size());
+ ASSERT_EQ("foo", parts[0]);
+ ASSERT_EQ("bar", parts[1]);
+ ASSERT_EQ("baz", parts[2]);
+}
+
+TEST(strings, split_with_empty_part) {
+ std::vector<std::string> parts;
+ android::base::Split("foo,,bar", ',', &parts);
+ ASSERT_EQ(2U, parts.size());
+ ASSERT_EQ("foo", parts[0]);
+ ASSERT_EQ("bar", parts[1]);
+}
+
+TEST(strings, trim_empty) {
+ ASSERT_EQ("", android::base::Trim(""));
+}
+
+TEST(strings, trim_already_trimmed) {
+ ASSERT_EQ("foo", android::base::Trim("foo"));
+}
+
+TEST(strings, trim_left) {
+ ASSERT_EQ("foo", android::base::Trim(" foo"));
+}
+
+TEST(strings, trim_right) {
+ ASSERT_EQ("foo", android::base::Trim("foo "));
+}
+
+TEST(strings, trim_both) {
+ ASSERT_EQ("foo", android::base::Trim(" foo "));
+}
+
+TEST(strings, trim_no_trim_middle) {
+ ASSERT_EQ("foo bar", android::base::Trim("foo bar"));
+}
+
+TEST(strings, trim_other_whitespace) {
+ ASSERT_EQ("foo", android::base::Trim("\v\tfoo\n\f"));
+}
+
+TEST(strings, join_nothing) {
+ std::vector<std::string> list = {};
+ ASSERT_EQ("", android::base::Join(list, ','));
+}
+
+TEST(strings, join_single) {
+ std::vector<std::string> list = {"foo"};
+ ASSERT_EQ("foo", android::base::Join(list, ','));
+}
+
+TEST(strings, join_simple) {
+ std::vector<std::string> list = {"foo", "bar", "baz"};
+ ASSERT_EQ("foo,bar,baz", android::base::Join(list, ','));
+}
+
+TEST(strings, join_separator_in_vector) {
+ std::vector<std::string> list = {",", ","};
+ ASSERT_EQ(",,,", android::base::Join(list, ','));
+}
+
+TEST(strings, startswith_empty) {
+ ASSERT_FALSE(android::base::StartsWith("", "foo"));
+ ASSERT_TRUE(android::base::StartsWith("", ""));
+}
+
+TEST(strings, startswith_simple) {
+ ASSERT_TRUE(android::base::StartsWith("foo", ""));
+ ASSERT_TRUE(android::base::StartsWith("foo", "f"));
+ ASSERT_TRUE(android::base::StartsWith("foo", "fo"));
+ ASSERT_TRUE(android::base::StartsWith("foo", "foo"));
+}
+
+TEST(strings, startswith_prefix_too_long) {
+ ASSERT_FALSE(android::base::StartsWith("foo", "foobar"));
+}
+
+TEST(strings, startswith_contains_prefix) {
+ ASSERT_FALSE(android::base::StartsWith("foobar", "oba"));
+ ASSERT_FALSE(android::base::StartsWith("foobar", "bar"));
+}
+
+TEST(strings, endswith_empty) {
+ ASSERT_FALSE(android::base::EndsWith("", "foo"));
+ ASSERT_TRUE(android::base::EndsWith("", ""));
+}
+
+TEST(strings, endswith_simple) {
+ ASSERT_TRUE(android::base::EndsWith("foo", ""));
+ ASSERT_TRUE(android::base::EndsWith("foo", "o"));
+ ASSERT_TRUE(android::base::EndsWith("foo", "oo"));
+ ASSERT_TRUE(android::base::EndsWith("foo", "foo"));
+}
+
+TEST(strings, endswith_prefix_too_long) {
+ ASSERT_FALSE(android::base::EndsWith("foo", "foobar"));
+}
+
+TEST(strings, endswith_contains_prefix) {
+ ASSERT_FALSE(android::base::EndsWith("foobar", "oba"));
+ ASSERT_FALSE(android::base::EndsWith("foobar", "foo"));
+}
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index fbaac39..dd53296 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -5,6 +5,7 @@
LOCAL_SRC_FILES:= \
backtrace.cpp \
debuggerd.cpp \
+ elf_utils.cpp \
getevent.cpp \
tombstone.cpp \
utility.cpp \
@@ -12,7 +13,7 @@
LOCAL_SRC_FILES_arm := arm/machine.cpp
LOCAL_SRC_FILES_arm64 := arm64/machine.cpp
LOCAL_SRC_FILES_mips := mips/machine.cpp
-LOCAL_SRC_FILES_mips64 := mips/machine.cpp
+LOCAL_SRC_FILES_mips64 := mips64/machine.cpp
LOCAL_SRC_FILES_x86 := x86/machine.cpp
LOCAL_SRC_FILES_x86_64 := x86_64/machine.cpp
@@ -28,6 +29,7 @@
LOCAL_SHARED_LIBRARIES := \
libbacktrace \
+ libbase \
libcutils \
liblog \
libselinux \
@@ -38,7 +40,6 @@
LOCAL_MODULE_STEM_32 := debuggerd
LOCAL_MODULE_STEM_64 := debuggerd64
LOCAL_MULTILIB := both
-LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
include $(BUILD_EXECUTABLE)
@@ -49,7 +50,7 @@
LOCAL_SRC_FILES_arm := arm/crashglue.S
LOCAL_SRC_FILES_arm64 := arm64/crashglue.S
LOCAL_SRC_FILES_mips := mips/crashglue.S
-LOCAL_SRC_FILES_mips64 := mips/crashglue.S
+LOCAL_SRC_FILES_mips64 := mips64/crashglue.S
LOCAL_SRC_FILES_x86 := x86/crashglue.S
LOCAL_SRC_FILES_x86_64 := x86_64/crashglue.S
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
diff --git a/debuggerd/elf_utils.cpp b/debuggerd/elf_utils.cpp
new file mode 100644
index 0000000..764b9db
--- /dev/null
+++ b/debuggerd/elf_utils.cpp
@@ -0,0 +1,119 @@
+/*
+ * 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 LOG_TAG "DEBUG"
+
+#include <elf.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <string>
+
+#include <backtrace/Backtrace.h>
+#include <base/stringprintf.h>
+#include <log/log.h>
+
+#include "elf_utils.h"
+
+template <typename HdrType, typename PhdrType, typename NhdrType>
+static bool get_build_id(
+ Backtrace* backtrace, uintptr_t base_addr, uint8_t* e_ident, std::string* build_id) {
+ HdrType hdr;
+
+ memcpy(&hdr.e_ident[0], e_ident, EI_NIDENT);
+
+ // First read the rest of the header.
+ if (backtrace->Read(base_addr + EI_NIDENT, reinterpret_cast<uint8_t*>(&hdr) + EI_NIDENT,
+ sizeof(HdrType) - EI_NIDENT) != sizeof(HdrType) - EI_NIDENT) {
+ return false;
+ }
+
+ for (size_t i = 0; i < hdr.e_phnum; i++) {
+ PhdrType phdr;
+ if (backtrace->Read(base_addr + hdr.e_phoff + i * hdr.e_phentsize,
+ reinterpret_cast<uint8_t*>(&phdr), sizeof(phdr)) != sizeof(phdr)) {
+ return false;
+ }
+ // Looking for the .note.gnu.build-id note.
+ if (phdr.p_type == PT_NOTE) {
+ size_t hdr_size = phdr.p_filesz;
+ uintptr_t addr = base_addr + phdr.p_offset;
+ while (hdr_size >= sizeof(NhdrType)) {
+ NhdrType nhdr;
+ if (backtrace->Read(addr, reinterpret_cast<uint8_t*>(&nhdr), sizeof(nhdr)) != sizeof(nhdr)) {
+ return false;
+ }
+ addr += sizeof(nhdr);
+ if (nhdr.n_type == NT_GNU_BUILD_ID) {
+ // Skip the name (which is the owner and should be "GNU").
+ addr += nhdr.n_namesz;
+ uint8_t build_id_data[128];
+ if (nhdr.n_namesz > sizeof(build_id_data)) {
+ ALOGE("Possible corrupted note, name size value is too large: %u",
+ nhdr.n_namesz);
+ return false;
+ }
+ if (backtrace->Read(addr, build_id_data, nhdr.n_descsz) != nhdr.n_descsz) {
+ return false;
+ }
+
+ build_id->clear();
+ for (size_t bytes = 0; bytes < nhdr.n_descsz; bytes++) {
+ *build_id += android::base::StringPrintf("%02x", build_id_data[bytes]);
+ }
+
+ return true;
+ } else {
+ // Move past the extra note data.
+ hdr_size -= sizeof(nhdr);
+ size_t skip_bytes = nhdr.n_namesz + nhdr.n_descsz;
+ addr += skip_bytes;
+ if (hdr_size < skip_bytes) {
+ break;
+ }
+ hdr_size -= skip_bytes;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool elf_get_build_id(Backtrace* backtrace, uintptr_t addr, std::string* build_id) {
+ // Read and verify the elf magic number first.
+ uint8_t e_ident[EI_NIDENT];
+ if (backtrace->Read(addr, e_ident, SELFMAG) != SELFMAG) {
+ return false;
+ }
+
+ if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) {
+ return false;
+ }
+
+ // Read the rest of EI_NIDENT.
+ if (backtrace->Read(addr + SELFMAG, e_ident + SELFMAG, EI_NIDENT - SELFMAG) != EI_NIDENT - SELFMAG) {
+ return false;
+ }
+
+ if (e_ident[EI_CLASS] == ELFCLASS32) {
+ return get_build_id<Elf32_Ehdr, Elf32_Phdr, Elf32_Nhdr>(backtrace, addr, e_ident, build_id);
+ } else if (e_ident[EI_CLASS] == ELFCLASS64) {
+ return get_build_id<Elf64_Ehdr, Elf64_Phdr, Elf64_Nhdr>(backtrace, addr, e_ident, build_id);
+ }
+
+ return false;
+}
diff --git a/debuggerd/elf_utils.h b/debuggerd/elf_utils.h
new file mode 100644
index 0000000..11d0a43
--- /dev/null
+++ b/debuggerd/elf_utils.h
@@ -0,0 +1,27 @@
+/*
+ * 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 _DEBUGGERD_ELF_UTILS_H
+#define _DEBUGGERD_ELF_UTILS_H
+
+#include <stdint.h>
+#include <string>
+
+class Backtrace;
+
+bool elf_get_build_id(Backtrace*, uintptr_t, std::string*);
+
+#endif // _DEBUGGERD_ELF_UTILS_H
diff --git a/debuggerd/mips64/crashglue.S b/debuggerd/mips64/crashglue.S
new file mode 100644
index 0000000..70a6641
--- /dev/null
+++ b/debuggerd/mips64/crashglue.S
@@ -0,0 +1,48 @@
+ .set noat
+
+ .globl crash1
+ .globl crashnostack
+
+crash1:
+ li $0,0xdead0000+0
+ li $1,0xdead0000+1
+ li $2,0xdead0000+2
+ li $3,0xdead0000+3
+ li $4,0xdead0000+4
+ li $5,0xdead0000+5
+ li $6,0xdead0000+6
+ li $7,0xdead0000+7
+ li $8,0xdead0000+8
+ li $9,0xdead0000+9
+ li $10,0xdead0000+10
+ li $11,0xdead0000+11
+ li $12,0xdead0000+12
+ li $13,0xdead0000+13
+ li $14,0xdead0000+14
+ li $15,0xdead0000+15
+ li $16,0xdead0000+16
+ li $17,0xdead0000+17
+ li $18,0xdead0000+18
+ li $19,0xdead0000+19
+ li $20,0xdead0000+20
+ li $21,0xdead0000+21
+ li $22,0xdead0000+22
+ li $23,0xdead0000+23
+ li $24,0xdead0000+24
+ li $25,0xdead0000+25
+ li $26,0xdead0000+26
+ li $27,0xdead0000+27
+ li $28,0xdead0000+28
+ # don't trash the stack otherwise the signal handler won't run
+ #li $29,0xdead0000+29
+ li $30,0xdead0000+30
+ li $31,0xdead0000+31
+
+ lw $zero,($0)
+ b .
+
+
+crashnostack:
+ li $sp, 0
+ lw $zero,($0)
+ b .
diff --git a/debuggerd/mips64/machine.cpp b/debuggerd/mips64/machine.cpp
new file mode 100644
index 0000000..ef9092f
--- /dev/null
+++ b/debuggerd/mips64/machine.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/ptrace.h>
+
+#include <sys/user.h>
+
+#include "../utility.h"
+#include "../machine.h"
+
+#define R(x) (static_cast<unsigned long>(x))
+
+// If configured to do so, dump memory around *all* registers
+// for the crashing thread.
+void dump_memory_and_code(log_t* log, pid_t tid) {
+ pt_regs r;
+ if (ptrace(PTRACE_GETREGS, tid, 0, &r)) {
+ return;
+ }
+
+ static const char REG_NAMES[] = "$0atv0v1a0a1a2a3a4a5a6a7t0t1t2t3s0s1s2s3s4s5s6s7t8t9k0k1gpsps8ra";
+
+ for (int reg = 0; reg < 32; reg++) {
+ // skip uninteresting registers
+ if (reg == 0 // $0
+ || reg == 26 // $k0
+ || reg == 27 // $k1
+ || reg == 31 // $ra (done below)
+ )
+ continue;
+
+ uintptr_t addr = R(r.regs[reg]);
+
+ // Don't bother if it looks like a small int or ~= null, or if
+ // it's in the kernel area.
+ if (addr < 4096 || addr >= 0x4000000000000000) {
+ continue;
+ }
+
+ _LOG(log, logtype::MEMORY, "\nmemory near %.2s:\n", ®_NAMES[reg * 2]);
+ dump_memory(log, tid, addr);
+ }
+
+ unsigned long pc = R(r.cp0_epc);
+ unsigned long ra = R(r.regs[31]);
+
+ _LOG(log, logtype::MEMORY, "\ncode around pc:\n");
+ dump_memory(log, tid, (uintptr_t)pc);
+
+ if (pc != ra) {
+ _LOG(log, logtype::MEMORY, "\ncode around ra:\n");
+ dump_memory(log, tid, (uintptr_t)ra);
+ }
+}
+
+void dump_registers(log_t* log, pid_t tid) {
+ pt_regs r;
+ if(ptrace(PTRACE_GETREGS, tid, 0, &r)) {
+ _LOG(log, logtype::ERROR, "cannot get registers: %s\n", strerror(errno));
+ return;
+ }
+
+ _LOG(log, logtype::REGISTERS, " zr %016lx at %016lx v0 %016lx v1 %016lx\n",
+ R(r.regs[0]), R(r.regs[1]), R(r.regs[2]), R(r.regs[3]));
+ _LOG(log, logtype::REGISTERS, " a0 %016lx a1 %016lx a2 %016lx a3 %016lx\n",
+ R(r.regs[4]), R(r.regs[5]), R(r.regs[6]), R(r.regs[7]));
+ _LOG(log, logtype::REGISTERS, " a4 %016lx a5 %016lx a6 %016lx a7 %016lx\n",
+ R(r.regs[8]), R(r.regs[9]), R(r.regs[10]), R(r.regs[11]));
+ _LOG(log, logtype::REGISTERS, " t0 %016lx t1 %016lx t2 %016lx t3 %016lx\n",
+ R(r.regs[12]), R(r.regs[13]), R(r.regs[14]), R(r.regs[15]));
+ _LOG(log, logtype::REGISTERS, " s0 %016lx s1 %016lx s2 %016lx s3 %016lx\n",
+ R(r.regs[16]), R(r.regs[17]), R(r.regs[18]), R(r.regs[19]));
+ _LOG(log, logtype::REGISTERS, " s4 %016lx s5 %016lx s6 %016lx s7 %016lx\n",
+ R(r.regs[20]), R(r.regs[21]), R(r.regs[22]), R(r.regs[23]));
+ _LOG(log, logtype::REGISTERS, " t8 %016lx t9 %016lx k0 %016lx k1 %016lx\n",
+ R(r.regs[24]), R(r.regs[25]), R(r.regs[26]), R(r.regs[27]));
+ _LOG(log, logtype::REGISTERS, " gp %016lx sp %016lx s8 %016lx ra %016lx\n",
+ R(r.regs[28]), R(r.regs[29]), R(r.regs[30]), R(r.regs[31]));
+ _LOG(log, logtype::REGISTERS, " hi %016lx lo %016lx bva %016lx epc %016lx\n",
+ R(r.hi), R(r.lo), R(r.cp0_badvaddr), R(r.cp0_epc));
+}
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index e927ea3..094ab48 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -34,6 +34,7 @@
#include <private/android_filesystem_config.h>
+#include <base/stringprintf.h>
#include <cutils/properties.h>
#include <log/log.h>
#include <log/logger.h>
@@ -46,9 +47,12 @@
#include <UniquePtr.h>
+#include <string>
+
+#include "backtrace.h"
+#include "elf_utils.h"
#include "machine.h"
#include "tombstone.h"
-#include "backtrace.h"
#define STACK_WORDS 16
@@ -234,47 +238,36 @@
static void dump_stack_segment(
Backtrace* backtrace, log_t* log, uintptr_t* sp, size_t words, int label) {
+ // Read the data all at once.
+ word_t stack_data[words];
+ size_t bytes_read = backtrace->Read(*sp, reinterpret_cast<uint8_t*>(&stack_data[0]), sizeof(word_t) * words);
+ words = bytes_read / sizeof(word_t);
+ std::string line;
for (size_t i = 0; i < words; i++) {
- word_t stack_content;
- if (!backtrace->ReadWord(*sp, &stack_content)) {
- break;
+ line = " ";
+ if (i == 0 && label >= 0) {
+ // Print the label once.
+ line += android::base::StringPrintf("#%02d ", label);
+ } else {
+ line += " ";
}
+ line += android::base::StringPrintf("%" PRIPTR " %" PRIPTR, *sp, stack_data[i]);
backtrace_map_t map;
- backtrace->FillInMap(stack_content, &map);
- std::string map_name;
- if (BacktraceMap::IsValid(map) && map.name.length() > 0) {
- map_name = " " + map.name;
- }
- uintptr_t offset = 0;
- std::string func_name(backtrace->GetFunctionName(stack_content, &offset));
- if (!func_name.empty()) {
- if (!i && label >= 0) {
+ backtrace->FillInMap(stack_data[i], &map);
+ if (BacktraceMap::IsValid(map) && !map.name.empty()) {
+ line += " " + map.name;
+ uintptr_t offset = 0;
+ std::string func_name(backtrace->GetFunctionName(stack_data[i], &offset));
+ if (!func_name.empty()) {
+ line += " (" + func_name;
if (offset) {
- _LOG(log, logtype::STACK, " #%02d %" PRIPTR " %" PRIPTR "%s (%s+%" PRIuPTR ")\n",
- label, *sp, stack_content, map_name.c_str(), func_name.c_str(), offset);
- } else {
- _LOG(log, logtype::STACK, " #%02d %" PRIPTR " %" PRIPTR "%s (%s)\n",
- label, *sp, stack_content, map_name.c_str(), func_name.c_str());
+ line += android::base::StringPrintf("+%" PRIuPTR, offset);
}
- } else {
- if (offset) {
- _LOG(log, logtype::STACK, " %" PRIPTR " %" PRIPTR "%s (%s+%" PRIuPTR ")\n",
- *sp, stack_content, map_name.c_str(), func_name.c_str(), offset);
- } else {
- _LOG(log, logtype::STACK, " %" PRIPTR " %" PRIPTR "%s (%s)\n",
- *sp, stack_content, map_name.c_str(), func_name.c_str());
- }
- }
- } else {
- if (!i && label >= 0) {
- _LOG(log, logtype::STACK, " #%02d %" PRIPTR " %" PRIPTR "%s\n",
- label, *sp, stack_content, map_name.c_str());
- } else {
- _LOG(log, logtype::STACK, " %" PRIPTR " %" PRIPTR "%s\n",
- *sp, stack_content, map_name.c_str());
+ line += ')';
}
}
+ _LOG(log, logtype::STACK, "%s\n", line.c_str());
*sp += sizeof(word_t);
}
@@ -325,44 +318,72 @@
}
}
-static void dump_map(log_t* log, const backtrace_map_t* map, bool fault_addr) {
- _LOG(log, logtype::MAPS, "%s%" PRIPTR "-%" PRIPTR " %c%c%c %7" PRIdPTR "%s\n",
- (fault_addr? "--->" : " "), map->start, map->end - 1,
- (map->flags & PROT_READ) ? 'r' : '-', (map->flags & PROT_WRITE) ? 'w' : '-',
- (map->flags & PROT_EXEC) ? 'x' : '-',
- (map->end - map->start),
- (map->name.length() > 0) ? (" " + map->name).c_str() : "");
-}
-
-static void dump_all_maps(BacktraceMap* map, log_t* log, pid_t tid) {
- bool has_fault_address = false;
+static void dump_all_maps(Backtrace* backtrace, BacktraceMap* map, log_t* log, pid_t tid) {
+ bool print_fault_address_marker = false;
uintptr_t addr = 0;
siginfo_t si;
memset(&si, 0, sizeof(si));
if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) {
- _LOG(log, logtype::MAPS, "cannot get siginfo for %d: %s\n", tid, strerror(errno));
+ _LOG(log, logtype::ERROR, "cannot get siginfo for %d: %s\n", tid, strerror(errno));
} else {
- has_fault_address = signal_has_si_addr(si.si_signo);
+ print_fault_address_marker = signal_has_si_addr(si.si_signo);
addr = reinterpret_cast<uintptr_t>(si.si_addr);
}
- _LOG(log, logtype::MAPS, "\nmemory map:%s\n", has_fault_address ? " (fault address prefixed with --->)" : "");
-
- if (has_fault_address && (addr < map->begin()->start)) {
- _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " before any mapped regions\n", addr);
- }
-
- BacktraceMap::const_iterator prev = map->begin();
- for (BacktraceMap::const_iterator it = map->begin(); it != map->end(); ++it) {
- if (addr >= (*prev).end && addr < (*it).start) {
- _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " between mapped regions\n", addr);
+ _LOG(log, logtype::MAPS, "\n");
+ if (!print_fault_address_marker) {
+ _LOG(log, logtype::MAPS, "memory map:\n");
+ } else {
+ _LOG(log, logtype::MAPS, "memory map: (fault address prefixed with --->)\n");
+ if (map->begin() != map->end() && addr < map->begin()->start) {
+ _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " before any mapped regions\n",
+ addr);
+ print_fault_address_marker = false;
}
- prev = it;
- bool in_map = has_fault_address && (addr >= (*it).start) && (addr < (*it).end);
- dump_map(log, &*it, in_map);
}
- if (has_fault_address && (addr >= (*prev).end)) {
- _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " after any mapped regions\n", addr);
+
+ std::string line;
+ for (BacktraceMap::const_iterator it = map->begin(); it != map->end(); ++it) {
+ line = " ";
+ if (print_fault_address_marker) {
+ if (addr < it->start) {
+ _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " between mapped regions\n",
+ addr);
+ print_fault_address_marker = false;
+ } else if (addr >= it->start && addr < it->end) {
+ line = "--->";
+ print_fault_address_marker = false;
+ }
+ }
+ line += android::base::StringPrintf("%" PRIPTR "-%" PRIPTR " ", it->start, it->end - 1);
+ if (it->flags & PROT_READ) {
+ line += 'r';
+ } else {
+ line += '-';
+ }
+ if (it->flags & PROT_WRITE) {
+ line += 'w';
+ } else {
+ line += '-';
+ }
+ if (it->flags & PROT_EXEC) {
+ line += 'x';
+ } else {
+ line += '-';
+ }
+ line += android::base::StringPrintf(" %8" PRIxPTR, it->end - it->start);
+ if (it->name.length() > 0) {
+ line += " " + it->name;
+ std::string build_id;
+ if ((it->flags & PROT_READ) && elf_get_build_id(backtrace, it->start, &build_id)) {
+ line += " (BuildId: " + build_id + ")";
+ }
+ }
+ _LOG(log, logtype::MAPS, "%s\n", line.c_str());
+ }
+ if (print_fault_address_marker) {
+ _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " after any mapped regions\n",
+ addr);
}
}
@@ -627,7 +648,7 @@
dump_backtrace_and_stack(backtrace.get(), log);
}
dump_memory_and_code(log, tid);
- dump_all_maps(map.get(), log, tid);
+ dump_all_maps(backtrace.get(), map.get(), log, tid);
if (want_logs) {
dump_logs(log, pid, 5);
diff --git a/debuggerd/utility.h b/debuggerd/utility.h
index 58a882c..49b46e8 100644
--- a/debuggerd/utility.h
+++ b/debuggerd/utility.h
@@ -26,8 +26,10 @@
#define ABI_STRING "arm"
#elif defined(__aarch64__)
#define ABI_STRING "arm64"
-#elif defined(__mips__)
+#elif defined(__mips__) && !defined(__LP64__)
#define ABI_STRING "mips"
+#elif defined(__mips__) && defined(__LP64__)
+#define ABI_STRING "mips64"
#elif defined(__i386__)
#define ABI_STRING "x86"
#elif defined(__x86_64__)
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index a1391e0..d4daed6 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -154,9 +154,10 @@
} else if (!strcmp(fs_type, "f2fs")) {
char *f2fs_fsck_argv[] = {
F2FS_FSCK_BIN,
+ "-f",
blk_device
};
- INFO("Running %s on %s\n", F2FS_FSCK_BIN, blk_device);
+ INFO("Running %s -f %s\n", F2FS_FSCK_BIN, blk_device);
ret = android_fork_execvp_ext(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv,
&status, true, LOG_KLOG | LOG_FILE,
@@ -185,19 +186,22 @@
* Mark the given block device as read-only, using the BLKROSET ioctl.
* Return 0 on success, and -1 on error.
*/
-static void fs_set_blk_ro(const char *blockdev)
+int fs_mgr_set_blk_ro(const char *blockdev)
{
int fd;
+ int rc = -1;
int ON = 1;
- fd = open(blockdev, O_RDONLY);
+ fd = TEMP_FAILURE_RETRY(open(blockdev, O_RDONLY | O_CLOEXEC));
if (fd < 0) {
// should never happen
- return;
+ return rc;
}
- ioctl(fd, BLKROSET, &ON);
- close(fd);
+ rc = ioctl(fd, BLKROSET, &ON);
+ TEMP_FAILURE_RETRY(close(fd));
+
+ return rc;
}
/*
@@ -223,7 +227,7 @@
save_errno = errno;
INFO("%s(source=%s,target=%s,type=%s)=%d\n", __func__, source, target, rec->fs_type, ret);
if ((ret == 0) && (mountflags & MS_RDONLY) != 0) {
- fs_set_blk_ro(source);
+ fs_mgr_set_blk_ro(source);
}
errno = save_errno;
return ret;
@@ -487,7 +491,9 @@
/* Deal with encryptability. */
if (!mret) {
/* If this is encryptable, need to trigger encryption */
- if (fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) {
+ if ( (fstab->recs[attempted_idx].fs_mgr_flags & MF_FORCECRYPT)
+ || (device_is_force_encrypted()
+ && fs_mgr_is_encryptable(&fstab->recs[attempted_idx]))) {
if (umount(fstab->recs[attempted_idx].mount_point) == 0) {
if (encryptable == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
ERROR("Will try to encrypt %s %s\n", fstab->recs[attempted_idx].mount_point,
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index 9d536bd..ab8f128 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -428,11 +428,6 @@
return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT);
}
-int fs_mgr_is_force_encrypted(struct fstab_rec *fstab)
-{
- return fstab->fs_mgr_flags & MF_FORCECRYPT;
-}
-
int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab)
{
return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 4ba6f92..88a1040 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -79,5 +79,7 @@
#define DM_BUF_SIZE 4096
+int fs_mgr_set_blk_ro(const char *blockdev);
+
#endif /* __CORE_FS_MGR_PRIV_H */
diff --git a/fs_mgr/fs_mgr_verity.c b/fs_mgr/fs_mgr_verity.c
index 4683acb..feb3c19 100644
--- a/fs_mgr/fs_mgr_verity.c
+++ b/fs_mgr/fs_mgr_verity.c
@@ -42,9 +42,24 @@
#include "fs_mgr_priv.h"
#include "fs_mgr_priv_verity.h"
+#define FSTAB_PREFIX "/fstab."
+
#define VERITY_METADATA_SIZE 32768
#define VERITY_TABLE_RSA_KEY "/verity_key"
+#define VERITY_STATE_HEADER 0x83c0ae9d
+#define VERITY_STATE_VERSION 1
+
+#define VERITY_KMSG_RESTART "dm-verity device corrupted"
+#define VERITY_KMSG_BUFSIZE 1024
+
+struct verity_state {
+ uint32_t header;
+ uint32_t version;
+ uint32_t size;
+ int32_t mode;
+};
+
extern struct fs_info info;
static RSAPublicKey *load_key(char *path)
@@ -86,11 +101,11 @@
static int verify_table(char *signature, char *table, int table_length)
{
RSAPublicKey *key;
- uint8_t hash_buf[SHA_DIGEST_SIZE];
+ uint8_t hash_buf[SHA256_DIGEST_SIZE];
int retval = -1;
// Hash the table
- SHA_hash((uint8_t*)table, table_length, hash_buf);
+ SHA256_hash((uint8_t*)table, table_length, hash_buf);
// Now get the public key from the keyfile
key = load_key(VERITY_TABLE_RSA_KEY);
@@ -104,7 +119,7 @@
(uint8_t*) signature,
RSANUMBYTES,
(uint8_t*) hash_buf,
- SHA_DIGEST_SIZE)) {
+ SHA256_DIGEST_SIZE)) {
ERROR("Couldn't verify table.");
goto out;
}
@@ -294,10 +309,12 @@
return 0;
}
-static int load_verity_table(struct dm_ioctl *io, char *name, char *blockdev, int fd, char *table)
+static int load_verity_table(struct dm_ioctl *io, char *name, char *blockdev, int fd, char *table,
+ int mode)
{
char *verity_params;
char *buffer = (char*) io;
+ size_t bufsize;
uint64_t device_size = 0;
if (get_target_device_size(blockdev, &device_size) < 0) {
@@ -317,7 +334,17 @@
// build the verity params here
verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
- strcpy(verity_params, table);
+ bufsize = DM_BUF_SIZE - (verity_params - buffer);
+
+ if (mode == VERITY_MODE_EIO) {
+ // allow operation with older dm-verity drivers that are unaware
+ // of the mode parameter by omitting it; this also means that we
+ // cannot use logging mode with these drivers, they always cause
+ // an I/O error for corrupted blocks
+ strcpy(verity_params, table);
+ } else if (snprintf(verity_params, bufsize, "%s %d", table, mode) < 0) {
+ return -1;
+ }
// set next target boundary
verity_params += strlen(verity_params) + 1;
@@ -354,36 +381,300 @@
return -1;
}
-static int set_verified_property(char *name) {
- int ret;
- char *key;
- ret = asprintf(&key, "partition.%s.verified", name);
- if (ret < 0) {
- ERROR("Error formatting verified property");
- return ret;
+static int check_verity_restart(const char *fname)
+{
+ char buffer[VERITY_KMSG_BUFSIZE + 1];
+ int fd;
+ int rc = 0;
+ ssize_t size;
+ struct stat s;
+
+ fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC));
+
+ if (fd == -1) {
+ if (errno != ENOENT) {
+ ERROR("Failed to open %s (%s)\n", fname, strerror(errno));
+ }
+ goto out;
}
- ret = PROP_NAME_MAX - strlen(key);
- if (ret < 0) {
- ERROR("Verified property name is too long");
+
+ if (fstat(fd, &s) == -1) {
+ ERROR("Failed to fstat %s (%s)\n", fname, strerror(errno));
+ goto out;
+ }
+
+ size = VERITY_KMSG_BUFSIZE;
+
+ if (size > s.st_size) {
+ size = s.st_size;
+ }
+
+ if (lseek(fd, s.st_size - size, SEEK_SET) == -1) {
+ ERROR("Failed to lseek %jd %s (%s)\n", (intmax_t)(s.st_size - size), fname,
+ strerror(errno));
+ goto out;
+ }
+
+ if (TEMP_FAILURE_RETRY(read(fd, buffer, size)) != size) {
+ ERROR("Failed to read %zd bytes from %s (%s)\n", size, fname,
+ strerror(errno));
+ goto out;
+ }
+
+ buffer[size] = '\0';
+
+ if (strstr(buffer, VERITY_KMSG_RESTART) != NULL) {
+ rc = 1;
+ }
+
+out:
+ if (fd != -1) {
+ TEMP_FAILURE_RETRY(close(fd));
+ }
+
+ return rc;
+}
+
+static int was_verity_restart()
+{
+ static const char *files[] = {
+ "/sys/fs/pstore/console-ramoops",
+ "/proc/last_kmsg",
+ NULL
+ };
+ int i;
+
+ for (i = 0; files[i]; ++i) {
+ if (check_verity_restart(files[i])) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int write_verity_state(const char *fname, off64_t offset, int32_t mode)
+{
+ int fd;
+ int rc = -1;
+
+ struct verity_state s = {
+ VERITY_STATE_HEADER,
+ VERITY_STATE_VERSION,
+ sizeof(struct verity_state),
+ mode
+ };
+
+ fd = TEMP_FAILURE_RETRY(open(fname, O_WRONLY | O_SYNC | O_CLOEXEC));
+
+ if (fd == -1) {
+ ERROR("Failed to open %s (%s)\n", fname, strerror(errno));
+ goto out;
+ }
+
+ if (TEMP_FAILURE_RETRY(lseek64(fd, offset, SEEK_SET)) < 0) {
+ ERROR("Failed to seek %s to %" PRIu64 " (%s)\n", fname, offset, strerror(errno));
+ goto out;
+ }
+
+ if (TEMP_FAILURE_RETRY(write(fd, &s, sizeof(s))) != sizeof(s)) {
+ ERROR("Failed to write %zu bytes to %s (%s)\n", sizeof(s), fname, strerror(errno));
+ goto out;
+ }
+
+ rc = 0;
+
+out:
+ if (fd != -1) {
+ TEMP_FAILURE_RETRY(close(fd));
+ }
+
+ return rc;
+}
+
+static int get_verity_state_location(char *location, off64_t *offset)
+{
+ char state_off[PROPERTY_VALUE_MAX];
+
+ if (property_get("ro.verity.state.location", location, NULL) <= 0) {
return -1;
}
- ret = property_set(key, "1");
- if (ret < 0)
- ERROR("Error setting verified property %s: %d", key, ret);
- free(key);
- return ret;
+
+ if (*location != '/' || access(location, R_OK | W_OK) == -1) {
+ ERROR("Failed to access verity state %s (%s)\n", location, strerror(errno));
+ return -1;
+ }
+
+ *offset = 0;
+
+ if (property_get("ro.verity.state.offset", state_off, NULL) > 0) {
+ *offset = strtoll(state_off, NULL, 0);
+
+ if (errno == ERANGE || errno == EINVAL) {
+ ERROR("Invalid value in ro.verity.state.offset (%s)\n", state_off);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int fs_mgr_load_verity_state(int *mode)
+{
+ char fname[PROPERTY_VALUE_MAX];
+ int fd = -1;
+ int rc = -1;
+ off64_t offset = 0;
+ struct verity_state s;
+
+ if (get_verity_state_location(fname, &offset) < 0) {
+ /* location for dm-verity state is not specified, fall back to
+ * default behavior: return -EIO for corrupted blocks */
+ *mode = VERITY_MODE_EIO;
+ rc = 0;
+ goto out;
+ }
+
+ if (was_verity_restart()) {
+ /* device was restarted after dm-verity detected a corrupted
+ * block, so switch to logging mode */
+ *mode = VERITY_MODE_LOGGING;
+ rc = write_verity_state(fname, offset, *mode);
+ goto out;
+ }
+
+ fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC));
+
+ if (fd == -1) {
+ ERROR("Failed to open %s (%s)\n", fname, strerror(errno));
+ goto out;
+ }
+
+ if (TEMP_FAILURE_RETRY(lseek64(fd, offset, SEEK_SET)) < 0) {
+ ERROR("Failed to seek %s to %" PRIu64 " (%s)\n", fname, offset, strerror(errno));
+ goto out;
+ }
+
+ if (TEMP_FAILURE_RETRY(read(fd, &s, sizeof(s))) != sizeof(s)) {
+ ERROR("Failed to read %zu bytes from %s (%s)\n", sizeof(s), fname, strerror(errno));
+ goto out;
+ }
+
+ if (s.header != VERITY_STATE_HEADER) {
+ goto out;
+ }
+
+ if (s.version != VERITY_STATE_VERSION) {
+ ERROR("Unsupported verity state version (%u)\n", s.version);
+ goto out;
+ }
+
+ if (s.size != sizeof(s)) {
+ ERROR("Unexpected verity state size (%u)\n", s.size);
+ goto out;
+ }
+
+ if (s.mode < VERITY_MODE_EIO ||
+ s.mode > VERITY_MODE_LAST) {
+ ERROR("Unsupported verity mode (%u)\n", s.mode);
+ goto out;
+ }
+
+ *mode = s.mode;
+ rc = 0;
+
+out:
+ if (fd != -1) {
+ TEMP_FAILURE_RETRY(close(fd));
+ }
+
+ return rc;
+}
+
+int fs_mgr_update_verity_state()
+{
+ _Alignas(struct dm_ioctl) char buffer[DM_BUF_SIZE];
+ char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
+ char *mount_point;
+ char propbuf[PROPERTY_VALUE_MAX];
+ char state_loc[PROPERTY_VALUE_MAX];
+ char *status;
+ int fd = -1;
+ int i;
+ int rc = -1;
+ off64_t offset = 0;
+ struct dm_ioctl *io = (struct dm_ioctl *) buffer;
+ struct fstab *fstab = NULL;
+
+ if (get_verity_state_location(state_loc, &offset) < 0) {
+ goto out;
+ }
+
+ fd = TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC));
+
+ if (fd == -1) {
+ ERROR("Error opening device mapper (%s)\n", strerror(errno));
+ goto out;
+ }
+
+ property_get("ro.hardware", propbuf, "");
+ snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf);
+
+ fstab = fs_mgr_read_fstab(fstab_filename);
+
+ if (!fstab) {
+ ERROR("Failed to read %s\n", fstab_filename);
+ goto out;
+ }
+
+ for (i = 0; i < fstab->num_entries; i++) {
+ if (!fs_mgr_is_verified(&fstab->recs[i])) {
+ continue;
+ }
+
+ mount_point = basename(fstab->recs[i].mount_point);
+ verity_ioctl_init(io, mount_point, 0);
+
+ if (ioctl(fd, DM_TABLE_STATUS, io)) {
+ ERROR("Failed to query DM_TABLE_STATUS for %s (%s)\n", mount_point,
+ strerror(errno));
+ goto out;
+ }
+
+ status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
+
+ if (*status == 'C') {
+ rc = write_verity_state(state_loc, offset, VERITY_MODE_LOGGING);
+ goto out;
+ }
+ }
+
+ /* Don't overwrite possible previous state if there's no corruption. */
+ rc = 0;
+
+out:
+ if (fstab) {
+ fs_mgr_free_fstab(fstab);
+ }
+
+ if (fd) {
+ TEMP_FAILURE_RETRY(close(fd));
+ }
+
+ return rc;
}
int fs_mgr_setup_verity(struct fstab_rec *fstab) {
- int retval = -1;
+ int retval = FS_MGR_SETUP_VERITY_FAIL;
int fd = -1;
+ int mode;
char *verity_blk_name = 0;
char *verity_table = 0;
char *verity_table_signature = 0;
- char buffer[DM_BUF_SIZE];
+ _Alignas(struct dm_ioctl) char buffer[DM_BUF_SIZE];
struct dm_ioctl *io = (struct dm_ioctl *) buffer;
char *mount_point = basename(fstab->mount_point);
@@ -407,6 +698,8 @@
goto out;
}
+ retval = FS_MGR_SETUP_VERITY_FAIL;
+
// get the device mapper fd
if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
ERROR("Error opening device mapper (%s)", strerror(errno));
@@ -432,8 +725,13 @@
goto out;
}
+ if (fs_mgr_load_verity_state(&mode) < 0) {
+ mode = VERITY_MODE_RESTART; /* default dm-verity mode */
+ }
+
// load the verity mapping table
- if (load_verity_table(io, mount_point, fstab->blk_device, fd, verity_table) < 0) {
+ if (load_verity_table(io, mount_point, fstab->blk_device, fd, verity_table,
+ mode) < 0) {
goto out;
}
@@ -442,6 +740,9 @@
goto out;
}
+ // mark the underlying block device as read-only
+ fs_mgr_set_blk_ro(fstab->blk_device);
+
// assign the new verity block device as the block device
free(fstab->blk_device);
fstab->blk_device = verity_blk_name;
@@ -452,8 +753,7 @@
goto out;
}
- // set the property indicating that the partition is verified
- retval = set_verified_property(mount_point);
+ retval = FS_MGR_SETUP_VERITY_SUCCESS;
out:
if (fd != -1) {
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 5ec3b99..0437d45 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -27,6 +27,14 @@
// turn verity off in userdebug builds.
#define VERITY_METADATA_MAGIC_DISABLE 0x46464f56 // "VOFF"
+// Verity modes
+enum verity_mode {
+ VERITY_MODE_EIO = 0,
+ VERITY_MODE_LOGGING = 1,
+ VERITY_MODE_RESTART = 2,
+ VERITY_MODE_LAST = VERITY_MODE_RESTART
+};
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -75,6 +83,8 @@
int fs_mgr_unmount_all(struct fstab *fstab);
int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc,
char *real_blk_device, int size);
+int fs_mgr_load_verity_state(int *mode);
+int fs_mgr_update_verity_state();
int fs_mgr_add_entry(struct fstab *fstab,
const char *mount_point, const char *fs_type,
const char *blk_device);
@@ -83,7 +93,6 @@
int fs_mgr_is_nonremovable(struct fstab_rec *fstab);
int fs_mgr_is_verified(struct fstab_rec *fstab);
int fs_mgr_is_encryptable(struct fstab_rec *fstab);
-int fs_mgr_is_force_encrypted(struct fstab_rec *fstab);
int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab);
int fs_mgr_swapon_all(struct fstab *fstab);
#ifdef __cplusplus
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 06497c2..7ea8250 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -265,10 +265,10 @@
"battery none");
}
- KLOG_INFO(LOG_TAG, "%s chg=%s%s%s\n", dmesgline,
- props.chargerAcOnline ? "a" : "",
- props.chargerUsbOnline ? "u" : "",
- props.chargerWirelessOnline ? "w" : "");
+ KLOG_WARNING(LOG_TAG, "%s chg=%s%s%s\n", dmesgline,
+ props.chargerAcOnline ? "a" : "",
+ props.chargerUsbOnline ? "u" : "",
+ props.chargerWirelessOnline ? "w" : "");
}
healthd_mode_ops->battery_update(&props);
@@ -511,7 +511,7 @@
if (!mChargerNames.size())
KLOG_ERROR(LOG_TAG, "No charger supplies found\n");
if (!mBatteryDevicePresent) {
- KLOG_INFO(LOG_TAG, "No battery devices found\n");
+ KLOG_WARNING(LOG_TAG, "No battery devices found\n");
hc->periodic_chores_interval_fast = -1;
hc->periodic_chores_interval_slow = -1;
} else {
diff --git a/healthd/healthd.cpp b/healthd/healthd.cpp
index b34583d..1fee855 100644
--- a/healthd/healthd.cpp
+++ b/healthd/healthd.cpp
@@ -53,6 +53,7 @@
.batteryCurrentAvgPath = String8(String8::kEmptyString),
.batteryChargeCounterPath = String8(String8::kEmptyString),
.energyCounter = NULL,
+ .screen_on = NULL,
};
static int eventct;
@@ -313,8 +314,8 @@
return -1;
}
- healthd_mode_ops->init(&healthd_config);
healthd_board_init(&healthd_config);
+ healthd_mode_ops->init(&healthd_config);
wakealarm_init();
uevent_init();
gBatteryMonitor = new BatteryMonitor();
diff --git a/healthd/healthd.h b/healthd/healthd.h
index 972e728..4704f0b 100644
--- a/healthd/healthd.h
+++ b/healthd/healthd.h
@@ -67,6 +67,7 @@
android::String8 batteryChargeCounterPath;
int (*energyCounter)(int64_t *);
+ bool (*screen_on)(android::BatteryProperties *props);
};
// Global helper functions
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 291cb6c..9ed5944 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -68,14 +68,13 @@
#define UNPLUGGED_SHUTDOWN_TIME (10 * MSEC_PER_SEC)
#define BATTERY_FULL_THRESH 95
-#define SCREEN_ON_BATTERY_THRESH 0
#define LAST_KMSG_PATH "/proc/last_kmsg"
#define LAST_KMSG_PSTORE_PATH "/sys/fs/pstore/console-ramoops"
#define LAST_KMSG_MAX_SZ (32 * 1024)
#define LOGE(x...) do { KLOG_ERROR("charger", x); } while (0)
-#define LOGI(x...) do { KLOG_INFO("charger", x); } while (0)
+#define LOGW(x...) do { KLOG_WARNING("charger", x); } while (0)
#define LOGV(x...) do { KLOG_DEBUG("charger", x); } while (0)
struct key_state {
@@ -109,7 +108,6 @@
struct charger {
bool have_battery_state;
bool charger_connected;
- int capacity;
int64_t next_screen_transition;
int64_t next_key_check;
int64_t next_pwr_check;
@@ -170,7 +168,8 @@
};
static struct charger charger_state;
-
+static struct healthd_config *healthd_config;
+static struct android::BatteryProperties *batt_prop;
static int char_width;
static int char_height;
static bool minui_inited;
@@ -198,15 +197,15 @@
unsigned sz = 0;
int len;
- LOGI("\n");
- LOGI("*************** LAST KMSG ***************\n");
- LOGI("\n");
+ LOGW("\n");
+ LOGW("*************** LAST KMSG ***************\n");
+ LOGW("\n");
buf = (char *)load_file(LAST_KMSG_PSTORE_PATH, &sz);
if (!buf || !sz) {
buf = (char *)load_file(LAST_KMSG_PATH, &sz);
if (!buf || !sz) {
- LOGI("last_kmsg not found. Cold reset?\n");
+ LOGW("last_kmsg not found. Cold reset?\n");
goto out;
}
}
@@ -225,7 +224,7 @@
yoink = ptr[cnt];
ptr[cnt] = '\0';
- klog_write(6, "<6>%s", ptr);
+ klog_write(6, "<4>%s", ptr);
ptr[cnt] = yoink;
len -= cnt;
@@ -235,14 +234,9 @@
free(buf);
out:
- LOGI("\n");
- LOGI("************* END LAST KMSG *************\n");
- LOGI("\n");
-}
-
-static int get_battery_capacity()
-{
- return charger_state.capacity;
+ LOGW("\n");
+ LOGW("************* END LAST KMSG *************\n");
+ LOGW("\n");
}
#ifdef CHARGER_ENABLE_SUSPEND
@@ -356,15 +350,16 @@
return;
if (!minui_inited) {
- int batt_cap = get_battery_capacity();
- if (batt_cap < SCREEN_ON_BATTERY_THRESH) {
- LOGV("[%" PRId64 "] level %d, leave screen off\n", now, batt_cap);
- batt_anim->run = false;
- charger->next_screen_transition = -1;
- if (charger->charger_connected)
- request_suspend(true);
- return;
+ if (healthd_config && healthd_config->screen_on) {
+ if (!healthd_config->screen_on(batt_prop)) {
+ LOGV("[%" PRId64 "] leave screen off\n", now);
+ batt_anim->run = false;
+ charger->next_screen_transition = -1;
+ if (charger->charger_connected)
+ request_suspend(true);
+ return;
+ }
}
gr_init();
@@ -391,16 +386,14 @@
/* animation starting, set up the animation */
if (batt_anim->cur_frame == 0) {
- int batt_cap;
LOGV("[%" PRId64 "] animation starting\n", now);
- batt_cap = get_battery_capacity();
- if (batt_cap >= 0 && batt_anim->num_frames != 0) {
+ if (batt_prop && batt_prop->batteryLevel >= 0 && batt_anim->num_frames != 0) {
int i;
/* find first frame given current capacity */
for (i = 1; i < batt_anim->num_frames; i++) {
- if (batt_cap < batt_anim->frames[i].min_capacity)
+ if (batt_prop->batteryLevel < batt_anim->frames[i].min_capacity)
break;
}
batt_anim->cur_frame = i - 1;
@@ -408,8 +401,8 @@
/* show the first frame for twice as long */
disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time * 2;
}
-
- batt_anim->capacity = batt_cap;
+ if (batt_prop)
+ batt_anim->capacity = batt_prop->batteryLevel;
}
/* unblank the screen on first cycle */
@@ -524,10 +517,10 @@
all devices. Check the property and continue booting or reboot
accordingly. */
if (property_get_bool("ro.enable_boot_charger_mode", false)) {
- LOGI("[%" PRId64 "] booting from charger mode\n", now);
+ LOGW("[%" PRId64 "] booting from charger mode\n", now);
property_set("sys.boot_from_charger_mode", "1");
} else {
- LOGI("[%" PRId64 "] rebooting\n", now);
+ LOGW("[%" PRId64 "] rebooting\n", now);
android_reboot(ANDROID_RB_RESTART, 0, 0);
}
} else {
@@ -565,10 +558,10 @@
request_suspend(false);
if (charger->next_pwr_check == -1) {
charger->next_pwr_check = now + UNPLUGGED_SHUTDOWN_TIME;
- LOGI("[%" PRId64 "] device unplugged: shutting down in %" PRId64 " (@ %" PRId64 ")\n",
+ LOGW("[%" PRId64 "] device unplugged: shutting down in %" PRId64 " (@ %" PRId64 ")\n",
now, (int64_t)UNPLUGGED_SHUTDOWN_TIME, charger->next_pwr_check);
} else if (now >= charger->next_pwr_check) {
- LOGI("[%" PRId64 "] shutting down\n", now);
+ LOGW("[%" PRId64 "] shutting down\n", now);
android_reboot(ANDROID_RB_POWEROFF, 0, 0);
} else {
/* otherwise we already have a shutdown timer scheduled */
@@ -576,7 +569,7 @@
} else {
/* online supply present, reset shutdown timer if set */
if (charger->next_pwr_check != -1) {
- LOGI("[%" PRId64 "] device plugged in: shutdown cancelled\n", now);
+ LOGW("[%" PRId64 "] device plugged in: shutdown cancelled\n", now);
kick_animation(charger->batt_anim);
}
charger->next_pwr_check = -1;
@@ -605,7 +598,6 @@
charger->charger_connected =
props->chargerAcOnline || props->chargerUsbOnline ||
props->chargerWirelessOnline;
- charger->capacity = props->batteryLevel;
if (!charger->have_battery_state) {
charger->have_battery_state = true;
@@ -613,6 +605,7 @@
reset_animation(charger->batt_anim);
kick_animation(charger->batt_anim);
}
+ batt_prop = props;
}
int healthd_mode_charger_preparetowait(void)
@@ -663,7 +656,7 @@
ev_dispatch();
}
-void healthd_mode_charger_init(struct healthd_config* /*config*/)
+void healthd_mode_charger_init(struct healthd_config* config)
{
int ret;
struct charger *charger = &charger_state;
@@ -672,7 +665,7 @@
dump_last_kmsg();
- LOGI("--------------- STARTING CHARGER MODE ---------------\n");
+ LOGW("--------------- STARTING CHARGER MODE ---------------\n");
ret = ev_init(input_callback, charger);
if (!ret) {
@@ -711,4 +704,5 @@
charger->next_screen_transition = -1;
charger->next_key_check = -1;
charger->next_pwr_check = -1;
+ healthd_config = config;
}
diff --git a/include/backtrace/Backtrace.h b/include/backtrace/Backtrace.h
index e2d718b..8c39acb 100644
--- a/include/backtrace/Backtrace.h
+++ b/include/backtrace/Backtrace.h
@@ -84,6 +84,12 @@
// Read the data at a specific address.
virtual bool ReadWord(uintptr_t ptr, word_t* out_value) = 0;
+ // Read arbitrary data from a specific address. If a read request would
+ // span from one map to another, this call only reads up until the end
+ // of the current map.
+ // Returns the total number of bytes actually read.
+ virtual size_t Read(uintptr_t addr, uint8_t* buffer, size_t bytes) = 0;
+
// Create a string representing the formatted line of backtrace information
// for a single frame.
virtual std::string FormatFrameData(size_t frame_num);
diff --git a/include/ctest/ctest.h b/include/ctest/ctest.h
deleted file mode 100644
index 1a83b20..0000000
--- a/include/ctest/ctest.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Very simple unit testing framework.
- */
-
-#ifndef __CUTILS_TEST_H
-#define __CUTILS_TEST_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Adds a test to the test suite.
- */
-#define addTest(test) addNamedTest(#test, &test)
-
-/**
- * Asserts that a condition is true. The test fails if it isn't.
- */
-#define assertTrue(value, message) assertTrueWithSource(value, __FILE__, __LINE__, message);
-
-/**
- * Asserts that a condition is false. The test fails if the value is true.
- */
-#define assertFalse(value, message) assertTrueWithSource(!value, __FILE__, __LINE__, message);
-
-/** Fails a test with the given message. */
-#define fail(message) assertTrueWithSource(0, __FILE__, __LINE__, message);
-
-/**
- * Asserts that two values are ==.
- */
-#define assertSame(a, b) assertTrueWithSource(a == b, __FILE__, __LINE__, "Expected same value.");
-
-/**
- * Asserts that two values are !=.
- */
-#define assertNotSame(a, b) assertTrueWithSource(a != b, __FILE__, __LINE__,\
- "Expected different values");
-
-/**
- * Runs a test suite.
- */
-void runTests(void);
-
-// Do not call these functions directly. Use macros above instead.
-void addNamedTest(const char* name, void (*test)(void));
-void assertTrueWithSource(int value, const char* file, int line, char* message);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __CUTILS_TEST_H */
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 5efe2e1..a3d11a7 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -230,21 +230,14 @@
static const struct fs_path_config android_files[] = {
{ 00440, AID_ROOT, AID_SHELL, 0, "system/etc/init.goldfish.rc" },
{ 00550, AID_ROOT, AID_SHELL, 0, "system/etc/init.goldfish.sh" },
- { 00440, AID_ROOT, AID_SHELL, 0, "system/etc/init.trout.rc" },
{ 00550, AID_ROOT, AID_SHELL, 0, "system/etc/init.ril" },
{ 00550, AID_DHCP, AID_SHELL, 0, "system/etc/dhcpcd/dhcpcd-run-hooks" },
- { 00444, AID_RADIO, AID_AUDIO, 0, "system/etc/AudioPara4.csv" },
{ 00555, AID_ROOT, AID_ROOT, 0, "system/etc/ppp/*" },
{ 00555, AID_ROOT, AID_ROOT, 0, "system/etc/rc.*" },
{ 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app/*" },
{ 00644, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/*" },
{ 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private/*" },
{ 00644, AID_APP, AID_APP, 0, "data/data/*" },
- { 00755, AID_ROOT, AID_ROOT, 0, "system/bin/ping" },
-
- /* the following file is INTENTIONALLY set-gid and not set-uid.
- * Do not change. */
- { 02750, AID_ROOT, AID_INET, 0, "system/bin/netcfg" },
/* the following five files are INTENTIONALLY set-uid, but they
* are NOT included on user builds. */
@@ -252,7 +245,6 @@
{ 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/librank" },
{ 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/procrank" },
{ 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/procmem" },
- { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/tcpdump" },
{ 04770, AID_ROOT, AID_RADIO, 0, "system/bin/pppd-ril" },
/* the following files have enhanced capabilities and ARE included in user builds. */
diff --git a/include/private/android_logger.h b/include/private/android_logger.h
index cc7ba30..724ca51 100644
--- a/include/private/android_logger.h
+++ b/include/private/android_logger.h
@@ -41,4 +41,46 @@
log_time realtime;
} android_log_header_t;
+/* Event Header Structure to logd */
+typedef struct __attribute__((__packed__)) {
+ int32_t tag; // Little Endian Order
+} android_event_header_t;
+
+/* Event payload EVENT_TYPE_INT */
+typedef struct __attribute__((__packed__)) {
+ int8_t type; // EVENT_TYPE_INT
+ int32_t data; // Little Endian Order
+} android_event_int_t;
+
+/* Event with single EVENT_TYPE_INT */
+typedef struct __attribute__((__packed__)) {
+ android_event_header_t header;
+ android_event_int_t payload;
+} android_log_event_int_t;
+
+/* Event payload EVENT_TYPE_LONG */
+typedef struct __attribute__((__packed__)) {
+ int8_t type; // EVENT_TYPE_LONG
+ int64_t data; // Little Endian Order
+} android_event_long_t;
+
+/* Event with single EVENT_TYPE_LONG */
+typedef struct __attribute__((__packed__)) {
+ android_event_header_t header;
+ android_event_long_t payload;
+} android_log_event_long_t;
+
+/* Event payload EVENT_TYPE_STRING */
+typedef struct __attribute__((__packed__)) {
+ int8_t type; // EVENT_TYPE_STRING;
+ int32_t length; // Little Endian Order
+ char data[];
+} android_event_string_t;
+
+/* Event with single EVENT_TYPE_STRING */
+typedef struct __attribute__((__packed__)) {
+ android_event_header_t header;
+ android_event_string_t payload;
+} android_log_event_string_t;
+
#endif
diff --git a/include/system/audio.h b/include/system/audio.h
index 9a25cfb..181a171 100644
--- a/include/system/audio.h
+++ b/include/system/audio.h
@@ -57,10 +57,14 @@
* and must be routed to speaker
*/
AUDIO_STREAM_DTMF = 8,
- AUDIO_STREAM_TTS = 9,
-
- AUDIO_STREAM_CNT,
- AUDIO_STREAM_MAX = AUDIO_STREAM_CNT - 1,
+ AUDIO_STREAM_TTS = 9, /* Transmitted Through Speaker.
+ * Plays over speaker only, silent on other devices.
+ */
+ AUDIO_STREAM_ACCESSIBILITY = 10, /* For accessibility talk back prompts */
+ AUDIO_STREAM_REROUTING = 11, /* For dynamic policy output mixes */
+ AUDIO_STREAM_PATCH = 12, /* For internal audio flinger tracks. Fixed volume */
+ AUDIO_STREAM_PUBLIC_CNT = AUDIO_STREAM_TTS + 1,
+ AUDIO_STREAM_CNT = AUDIO_STREAM_PATCH + 1,
} audio_stream_type_t;
/* Do not change these values without updating their counterparts
@@ -96,6 +100,7 @@
AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12,
AUDIO_USAGE_ASSISTANCE_SONIFICATION = 13,
AUDIO_USAGE_GAME = 14,
+ AUDIO_USAGE_VIRTUAL_SOURCE = 15,
AUDIO_USAGE_CNT,
AUDIO_USAGE_MAX = AUDIO_USAGE_CNT - 1,
@@ -135,6 +140,7 @@
/* play the mix captured by this audio source. */
AUDIO_SOURCE_CNT,
AUDIO_SOURCE_MAX = AUDIO_SOURCE_CNT - 1,
+ AUDIO_SOURCE_FM_TUNER = 1998,
AUDIO_SOURCE_HOTWORD = 1999, /* A low-priority, preemptible audio source for
for background software hotword detection.
Same tuning as AUDIO_SOURCE_VOICE_RECOGNITION.
diff --git a/init/Android.mk b/init/Android.mk
index a3b01e1..5b8094f 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -27,6 +27,7 @@
parser.cpp \
util.cpp \
+LOCAL_STATIC_LIBRARIES := libbase
LOCAL_MODULE := libinit
include $(BUILD_STATIC_LIBRARY)
@@ -55,7 +56,7 @@
libfs_mgr \
liblogwrap \
libcutils \
- libutils \
+ libbase \
liblog \
libc \
libselinux \
@@ -75,11 +76,12 @@
include $(CLEAR_VARS)
LOCAL_MODULE := init_tests
LOCAL_SRC_FILES := \
+ init_parser_test.cpp \
util_test.cpp \
LOCAL_SHARED_LIBRARIES += \
libcutils \
- libutils \
+ libbase \
LOCAL_STATIC_LIBRARIES := libinit
include $(BUILD_NATIVE_TEST)
diff --git a/init/bootchart.cpp b/init/bootchart.cpp
index cc31920..530eba8 100644
--- a/init/bootchart.cpp
+++ b/init/bootchart.cpp
@@ -32,7 +32,7 @@
#include <string>
-#include <utils/file.h>
+#include <base/file.h>
#define LOG_ROOT "/data/bootchart"
#define LOG_STAT LOG_ROOT"/proc_stat.log"
@@ -59,7 +59,7 @@
static long long get_uptime_jiffies() {
std::string uptime;
- if (!android::ReadFileToString("/proc/uptime", &uptime)) {
+ if (!android::base::ReadFileToString("/proc/uptime", &uptime)) {
return 0;
}
return 100LL * strtod(uptime.c_str(), NULL);
@@ -82,7 +82,7 @@
}
std::string kernel_cmdline;
- android::ReadFileToString("/proc/cmdline", &kernel_cmdline);
+ android::base::ReadFileToString("/proc/cmdline", &kernel_cmdline);
FILE* out = fopen(LOG_HEADER, "we");
if (out == NULL) {
@@ -106,7 +106,7 @@
do_log_uptime(log);
std::string content;
- if (android::ReadFileToString(procfile, &content)) {
+ if (android::base::ReadFileToString(procfile, &content)) {
fprintf(log, "%s\n", content.c_str());
}
}
@@ -127,13 +127,13 @@
// name from /proc/<pid>/cmdline.
snprintf(filename, sizeof(filename), "/proc/%d/cmdline", pid);
std::string cmdline;
- android::ReadFileToString(filename, &cmdline);
+ android::base::ReadFileToString(filename, &cmdline);
const char* full_name = cmdline.c_str(); // So we stop at the first NUL.
// Read process stat line.
snprintf(filename, sizeof(filename), "/proc/%d/stat", pid);
std::string stat;
- if (android::ReadFileToString(filename, &stat)) {
+ if (android::base::ReadFileToString(filename, &stat)) {
if (!cmdline.empty()) {
// Substitute the process name with its real name.
size_t open = stat.find('(');
@@ -155,7 +155,7 @@
int timeout = 0;
std::string start;
- android::ReadFileToString(LOG_STARTFILE, &start);
+ android::base::ReadFileToString(LOG_STARTFILE, &start);
if (!start.empty()) {
timeout = atoi(start.c_str());
} else {
@@ -164,7 +164,7 @@
// timeout. this is useful when using -wipe-data since the /data
// partition is fresh.
std::string cmdline;
- android::ReadFileToString("/proc/cmdline", &cmdline);
+ android::base::ReadFileToString("/proc/cmdline", &cmdline);
#define KERNEL_OPTION "androidboot.bootchart="
if (strstr(cmdline.c_str(), KERNEL_OPTION) != NULL) {
timeout = atoi(cmdline.c_str() + sizeof(KERNEL_OPTION) - 1);
@@ -226,7 +226,7 @@
// Stop if /data/bootchart/stop contains 1.
std::string stop;
- if (android::ReadFileToString(LOG_STOPFILE, &stop) && stop == "1") {
+ if (android::base::ReadFileToString(LOG_STOPFILE, &stop) && stop == "1") {
return -1;
}
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 9f3dcc1..fb1aa7c 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -67,20 +67,6 @@
return init_module(&module[0], module.size(), options);
}
-static int setkey(struct kbentry *kbe)
-{
- int fd, ret;
-
- fd = open("/dev/tty0", O_RDWR | O_SYNC | O_CLOEXEC);
- if (fd < 0)
- return -1;
-
- ret = ioctl(fd, KDSKBENT, kbe);
-
- close(fd);
- return ret;
-}
-
static int __ifupdown(const char *interface, int up)
{
struct ifreq ifr;
@@ -118,18 +104,6 @@
}
}
-int do_chdir(int nargs, char **args)
-{
- chdir(args[1]);
- return 0;
-}
-
-int do_chroot(int nargs, char **args)
-{
- chroot(args[1]);
- return 0;
-}
-
int do_class_start(int nargs, char **args)
{
/* Starting a class does not start services
@@ -172,11 +146,16 @@
return 0;
}
-int do_exec(int nargs, char **args)
-{
- return -1;
+int do_exec(int nargs, char** args) {
+ service* svc = make_exec_oneshot_service(nargs, args);
+ if (svc == NULL) {
+ return -1;
+ }
+ service_start(svc, NULL);
+ return 0;
}
+// TODO: remove execonce when exec is available.
int do_execonce(int nargs, char **args)
{
pid_t child;
@@ -566,24 +545,6 @@
return 0;
}
-int do_setenforce(int nargs, char **args) {
- if (is_selinux_enabled() <= 0)
- return 0;
- if (security_setenforce(atoi(args[1])) < 0) {
- return -errno;
- }
- return 0;
-}
-
-int do_setkey(int nargs, char **args)
-{
- struct kbentry kbe;
- kbe.kb_table = strtoul(args[1], 0, 0);
- kbe.kb_index = strtoul(args[2], 0, 0);
- kbe.kb_value = strtoul(args[3], 0, 0);
- return setkey(&kbe);
-}
-
int do_setprop(int nargs, char **args)
{
const char *name = args[1];
@@ -712,6 +673,20 @@
return 0;
}
+int do_verity_load_state(int nargs, char **args) {
+ if (nargs == 1) {
+ int mode = -1;
+ int rc = fs_mgr_load_verity_state(&mode);
+
+ if (rc == 0 && mode == VERITY_MODE_LOGGING) {
+ action_for_each_trigger("verity-logging", action_add_queue_tail);
+ }
+
+ return rc;
+ }
+ return -1;
+}
+
int do_write(int nargs, char **args)
{
const char *path = args[1];
@@ -844,34 +819,6 @@
return ret;
}
-int do_setsebool(int nargs, char **args) {
- const char *name = args[1];
- const char *value = args[2];
- SELboolean b;
- int ret;
-
- if (is_selinux_enabled() <= 0)
- return 0;
-
- b.name = name;
- if (!strcmp(value, "1") || !strcasecmp(value, "true") || !strcasecmp(value, "on"))
- b.value = 1;
- else if (!strcmp(value, "0") || !strcasecmp(value, "false") || !strcasecmp(value, "off"))
- b.value = 0;
- else {
- ERROR("setsebool: invalid value %s\n", value);
- return -EINVAL;
- }
-
- if (security_set_boolean_list(1, &b, 0) < 0) {
- ret = -errno;
- ERROR("setsebool: could not set %s to %s\n", name, value);
- return ret;
- }
-
- return 0;
-}
-
int do_loglevel(int nargs, char **args) {
int log_level;
char log_level_str[PROP_VALUE_MAX] = "";
diff --git a/init/grab-bootchart.sh b/init/grab-bootchart.sh
index 5715862..d6082aa 100755
--- a/init/grab-bootchart.sh
+++ b/init/grab-bootchart.sh
@@ -1,12 +1,9 @@
#!/bin/sh
#
-# this script is used to retrieve the bootchart log generated
-# by init when compiled with INIT_BOOTCHART=true.
-#
+# This script is used to retrieve a bootchart log generated by init.
# All options are passed to adb, for better or for worse.
-#
-# for all details, see //device/system/init/README.BOOTCHART
-#
+# See the readme in this directory for more on bootcharting.
+
TMPDIR=/tmp/android-bootchart
rm -rf $TMPDIR
mkdir -p $TMPDIR
@@ -22,4 +19,4 @@
(cd $TMPDIR && tar -czf $TARBALL $FILES)
bootchart ${TMPDIR}/${TARBALL}
gnome-open ${TARBALL%.tgz}.png
-echo "Clean up ${TMPDIR}/ & ./${TARBALL%.tgz}.png when done"
+echo "Clean up ${TMPDIR}/ and ./${TARBALL%.tgz}.png when done"
diff --git a/init/init.cpp b/init/init.cpp
index 41ceb0a..3c6e8a4 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -14,37 +14,38 @@
* limitations under the License.
*/
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <signal.h>
-#include <sys/wait.h>
#include <sys/mount.h>
-#include <sys/stat.h>
#include <sys/poll.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <mtd/mtd-user.h>
-#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <sys/un.h>
+#include <sys/wait.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include <mtd/mtd-user.h>
#include <selinux/selinux.h>
#include <selinux/label.h>
#include <selinux/android.h>
-#include <libgen.h>
-
-#include <cutils/list.h>
#include <cutils/android_reboot.h>
-#include <cutils/sockets.h>
-#include <cutils/iosched_policy.h>
#include <cutils/fs.h>
+#include <cutils/iosched_policy.h>
+#include <cutils/list.h>
+#include <cutils/sockets.h>
#include <private/android_filesystem_config.h>
-#include <termios.h>
#include "devices.h"
#include "init.h"
@@ -72,22 +73,35 @@
static struct action *cur_action = NULL;
static struct command *cur_command = NULL;
-void notify_service_state(const char *name, const char *state)
-{
- char pname[PROP_NAME_MAX];
- int len = strlen(name);
- if ((len + 10) > PROP_NAME_MAX)
- return;
- snprintf(pname, sizeof(pname), "init.svc.%s", name);
- property_set(pname, state);
-}
-
static int have_console;
static char console_name[PROP_VALUE_MAX] = "/dev/console";
static time_t process_needs_restart;
static const char *ENV[32];
+bool waiting_for_exec = false;
+
+void service::NotifyStateChange(const char* new_state) {
+ if (!properties_inited()) {
+ // If properties aren't available yet, we can't set them.
+ return;
+ }
+
+ if ((flags & SVC_EXEC) != 0) {
+ // 'exec' commands don't have properties tracking their state.
+ return;
+ }
+
+ char prop_name[PROP_NAME_MAX];
+ if (snprintf(prop_name, sizeof(prop_name), "init.svc.%s", name) >= PROP_NAME_MAX) {
+ // If the property name would be too long, we can't set it.
+ ERROR("Property name \"init.svc.%s\" too long; not setting to %s\n", name, new_state);
+ return;
+ }
+
+ property_set(prop_name, new_state);
+}
+
/* add_environment - add "key=value" to the current environment */
int add_environment(const char *key, const char *val)
{
@@ -160,35 +174,26 @@
void service_start(struct service *svc, const char *dynamic_args)
{
- struct stat s;
- pid_t pid;
- int needs_console;
- char *scon = NULL;
- int rc;
-
- /* starting a service removes it from the disabled or reset
- * state and immediately takes it out of the restarting
- * state if it was in there
- */
+ // Starting a service removes it from the disabled or reset state and
+ // immediately takes it out of the restarting state if it was in there.
svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));
svc->time_started = 0;
- /* running processes require no additional work -- if
- * they're in the process of exiting, we've ensured
- * that they will immediately restart on exit, unless
- * they are ONESHOT
- */
+ // Running processes require no additional work --- if they're in the
+ // process of exiting, we've ensured that they will immediately restart
+ // on exit, unless they are ONESHOT.
if (svc->flags & SVC_RUNNING) {
return;
}
- needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0;
- if (needs_console && (!have_console)) {
+ bool needs_console = (svc->flags & SVC_CONSOLE);
+ if (needs_console && !have_console) {
ERROR("service '%s' requires console\n", svc->name);
svc->flags |= SVC_DISABLED;
return;
}
+ struct stat s;
if (stat(svc->args[0], &s) != 0) {
ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name);
svc->flags |= SVC_DISABLED;
@@ -202,6 +207,7 @@
return;
}
+ char* scon = NULL;
if (is_selinux_enabled() > 0) {
if (svc->seclabel) {
scon = strdup(svc->seclabel);
@@ -213,7 +219,7 @@
char *mycon = NULL, *fcon = NULL;
INFO("computing context for service '%s'\n", svc->args[0]);
- rc = getcon(&mycon);
+ int rc = getcon(&mycon);
if (rc < 0) {
ERROR("could not get context while starting '%s'\n", svc->name);
return;
@@ -241,8 +247,7 @@
NOTICE("starting '%s'\n", svc->name);
- pid = fork();
-
+ pid_t pid = fork();
if (pid == 0) {
struct socketinfo *si;
struct svcenvinfo *ei;
@@ -298,7 +303,7 @@
setpgid(0, getpid());
- /* as requested, set our gid, supplemental gids, and uid */
+ // As requested, set our gid, supplemental gids, and uid.
if (svc->gid) {
if (setgid(svc->gid) != 0) {
ERROR("setgid failed: %s\n", strerror(errno));
@@ -361,8 +366,13 @@
svc->pid = pid;
svc->flags |= SVC_RUNNING;
- if (properties_inited())
- notify_service_state(svc->name, "running");
+ if ((svc->flags & SVC_EXEC) != 0) {
+ INFO("SVC_EXEC pid %d (uid %d gid %d+%zu context %s) started; waiting...\n",
+ svc->pid, svc->uid, svc->gid, svc->nr_supp_gids, svc->seclabel);
+ waiting_for_exec = true;
+ }
+
+ svc->NotifyStateChange("running");
}
/* The how field should be either SVC_DISABLED, SVC_RESET, or SVC_RESTART */
@@ -388,9 +398,9 @@
if (svc->pid) {
NOTICE("service '%s' is being killed\n", svc->name);
kill(-svc->pid, SIGKILL);
- notify_service_state(svc->name, "stopping");
+ svc->NotifyStateChange("stopping");
} else {
- notify_service_state(svc->name, "stopped");
+ svc->NotifyStateChange("stopped");
}
}
@@ -969,28 +979,20 @@
security_setenforce(is_enforcing);
}
-int main(int argc, char **argv)
-{
- size_t fd_count = 0;
- struct pollfd ufds[4];
- int property_set_fd_init = 0;
- int signal_fd_init = 0;
- int keychord_fd_init = 0;
- bool is_charger = false;
-
+int main(int argc, char** argv) {
if (!strcmp(basename(argv[0]), "ueventd"))
return ueventd_main(argc, argv);
if (!strcmp(basename(argv[0]), "watchdogd"))
return watchdogd_main(argc, argv);
- /* clear the umask */
+ // Clear the umask.
umask(0);
- /* Get the basic filesystem setup we need put
- * together in the initramdisk on / and then we'll
- * let the rc file figure out the rest.
- */
+ add_environment("PATH", _PATH_DEFPATH);
+
+ // Get the basic filesystem setup we need put together in the initramdisk
+ // on / and then we'll let the rc file figure out the rest.
mkdir("/dev", 0755);
mkdir("/proc", 0755);
mkdir("/sys", 0755);
@@ -1002,15 +1004,13 @@
mount("proc", "/proc", "proc", 0, NULL);
mount("sysfs", "/sys", "sysfs", 0, NULL);
- /* indicate that booting is in progress to background fw loaders, etc */
+ // Indicate that booting is in progress to background fw loaders, etc.
close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
- /* We must have some place other than / to create the
- * device nodes for kmsg and null, otherwise we won't
- * be able to remount / read-only later on.
- * Now that tmpfs is mounted on /dev, we can actually
- * talk to the outside world.
- */
+ // We must have some place other than / to create the device nodes for
+ // kmsg and null, otherwise we won't be able to remount / read-only
+ // later on. Now that tmpfs is mounted on /dev, we can actually talk
+ // to the outside world.
open_devnull_stdio();
klog_init();
property_init();
@@ -1019,25 +1019,22 @@
process_kernel_cmdline();
- union selinux_callback cb;
+ selinux_callback cb;
cb.func_log = log_callback;
selinux_set_callback(SELINUX_CB_LOG, cb);
-
cb.func_audit = audit_callback;
selinux_set_callback(SELINUX_CB_AUDIT, cb);
selinux_initialize();
- /* 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.
- */
+
+ // 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.
restorecon("/dev");
restorecon("/dev/socket");
restorecon("/dev/__properties__");
restorecon_recursive("/sys");
- is_charger = !strcmp(bootmode, "charger");
-
INFO("property init\n");
property_load_boot_defaults();
@@ -1050,50 +1047,58 @@
queue_builtin_action(keychord_init_action, "keychord_init");
queue_builtin_action(console_init_action, "console_init");
- /* execute all the boot actions to get us started */
+ // Execute all the boot actions to get us started.
action_for_each_trigger("init", action_add_queue_tail);
- /* Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
- * wasn't ready immediately after wait_for_coldboot_done
- */
+ // Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
+ // wasn't ready immediately after wait_for_coldboot_done
queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
queue_builtin_action(property_service_init_action, "property_service_init");
queue_builtin_action(signal_init_action, "signal_init");
- /* Don't mount filesystems or start core system services if in charger mode. */
- if (is_charger) {
+ // Don't mount filesystems or start core system services in charger mode.
+ if (strcmp(bootmode, "charger") == 0) {
action_for_each_trigger("charger", action_add_queue_tail);
} else {
action_for_each_trigger("late-init", action_add_queue_tail);
}
- /* run all property triggers based on current state of the properties */
+ // Run all property triggers based on current state of the properties.
queue_builtin_action(queue_property_triggers_action, "queue_property_triggers");
+ // TODO: why do we only initialize ufds after execute_one_command and restart_processes?
+ size_t fd_count = 0;
+ struct pollfd ufds[3];
+ bool property_set_fd_init = false;
+ bool signal_fd_init = false;
+ bool keychord_fd_init = false;
+
for (;;) {
- execute_one_command();
- restart_processes();
+ if (!waiting_for_exec) {
+ execute_one_command();
+ restart_processes();
+ }
if (!property_set_fd_init && get_property_set_fd() > 0) {
ufds[fd_count].fd = get_property_set_fd();
ufds[fd_count].events = POLLIN;
ufds[fd_count].revents = 0;
fd_count++;
- property_set_fd_init = 1;
+ property_set_fd_init = true;
}
if (!signal_fd_init && get_signal_fd() > 0) {
ufds[fd_count].fd = get_signal_fd();
ufds[fd_count].events = POLLIN;
ufds[fd_count].revents = 0;
fd_count++;
- signal_fd_init = 1;
+ signal_fd_init = true;
}
if (!keychord_fd_init && get_keychord_fd() > 0) {
ufds[fd_count].fd = get_keychord_fd();
ufds[fd_count].events = POLLIN;
ufds[fd_count].revents = 0;
fd_count++;
- keychord_fd_init = 1;
+ keychord_fd_init = true;
}
int timeout = -1;
diff --git a/init/init.h b/init/init.h
index eedec27..a104af6 100644
--- a/init/init.h
+++ b/init/init.h
@@ -17,13 +17,11 @@
#ifndef _INIT_INIT_H
#define _INIT_INIT_H
+#include <sys/types.h>
+
#include <cutils/list.h>
#include <cutils/iosched_policy.h>
-#include <sys/stat.h>
-
-void handle_control_message(const char *msg, const char *arg);
-
struct command
{
/* list of commands in an action */
@@ -59,8 +57,6 @@
struct command *current;
};
-void build_triggers_string(char *name_str, int length, struct action *cur_action);
-
struct socketinfo {
struct socketinfo *next;
const char *name;
@@ -77,27 +73,29 @@
const char *value;
};
-#define SVC_DISABLED 0x01 /* do not autostart with class */
-#define SVC_ONESHOT 0x02 /* do not restart on exit */
-#define SVC_RUNNING 0x04 /* currently active */
-#define SVC_RESTARTING 0x08 /* waiting to restart */
-#define SVC_CONSOLE 0x10 /* requires console */
-#define SVC_CRITICAL 0x20 /* will reboot into recovery if keeps crashing */
-#define SVC_RESET 0x40 /* Use when stopping a process, but not disabling
- so it can be restarted with its class */
-#define SVC_RC_DISABLED 0x80 /* Remember if the disabled flag was set in the rc script */
-#define SVC_RESTART 0x100 /* Use to safely restart (stop, wait, start) a service */
-#define SVC_DISABLED_START 0x200 /* a start was requested but it was disabled at the time */
+#define SVC_DISABLED 0x001 // do not autostart with class
+#define SVC_ONESHOT 0x002 // do not restart on exit
+#define SVC_RUNNING 0x004 // currently active
+#define SVC_RESTARTING 0x008 // waiting to restart
+#define SVC_CONSOLE 0x010 // requires console
+#define SVC_CRITICAL 0x020 // will reboot into recovery if keeps crashing
+#define SVC_RESET 0x040 // Use when stopping a process, but not disabling so it can be restarted with its class.
+#define SVC_RC_DISABLED 0x080 // Remember if the disabled flag was set in the rc script.
+#define SVC_RESTART 0x100 // Use to safely restart (stop, wait, start) a service.
+#define SVC_DISABLED_START 0x200 // A start was requested but it was disabled at the time.
+#define SVC_EXEC 0x400 // This synthetic service corresponds to an 'exec'.
#define NR_SVC_SUPP_GIDS 12 /* twelve supplementary groups */
#define COMMAND_RETRY_TIMEOUT 5
struct service {
+ void NotifyStateChange(const char* new_state);
+
/* list of all services */
struct listnode slist;
- const char *name;
+ char *name;
const char *classname;
unsigned flags;
@@ -105,19 +103,19 @@
time_t time_started; /* time of last start */
time_t time_crashed; /* first crash within inspection window */
int nr_crashed; /* number of times crashed within window */
-
+
uid_t uid;
gid_t gid;
gid_t supp_gids[NR_SVC_SUPP_GIDS];
size_t nr_supp_gids;
- char *seclabel;
+ const char* seclabel;
struct socketinfo *sockets;
struct svcenvinfo *envvars;
struct action onrestart; /* Actions to execute on restart. */
-
+
/* keycodes for triggering this service via /dev/keychord */
int *keycodes;
int nkeycodes;
@@ -131,7 +129,13 @@
char *args[1];
}; /* ^-------'args' MUST be at the end of this struct! */
-void notify_service_state(const char *name, const char *state);
+extern bool waiting_for_exec;
+extern struct selabel_handle *sehandle;
+extern struct selabel_handle *sehandle_prop;
+
+void build_triggers_string(char *name_str, int length, struct action *cur_action);
+
+void handle_control_message(const char *msg, const char *arg);
struct service *service_find_by_name(const char *name);
struct service *service_find_by_pid(pid_t pid);
@@ -147,9 +151,8 @@
void service_start(struct service *svc, const char *dynamic_args);
void property_changed(const char *name, const char *value);
-extern struct selabel_handle *sehandle;
-extern struct selabel_handle *sehandle_prop;
-extern int selinux_reload_policy(void);
+int selinux_reload_policy(void);
+
void zap_stdio(void);
#endif /* _INIT_INIT_H */
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index 61a5e0a..f3d34b2 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -120,8 +121,6 @@
case 'c':
if (!strcmp(s, "opy")) return K_copy;
if (!strcmp(s, "apability")) return K_capability;
- if (!strcmp(s, "hdir")) return K_chdir;
- if (!strcmp(s, "hroot")) return K_chroot;
if (!strcmp(s, "lass")) return K_class;
if (!strcmp(s, "lass_start")) return K_class_start;
if (!strcmp(s, "lass_stop")) return K_class_stop;
@@ -185,12 +184,9 @@
if (!strcmp(s, "eclabel")) return K_seclabel;
if (!strcmp(s, "ervice")) return K_service;
if (!strcmp(s, "etcon")) return K_setcon;
- if (!strcmp(s, "etenforce")) return K_setenforce;
if (!strcmp(s, "etenv")) return K_setenv;
- if (!strcmp(s, "etkey")) return K_setkey;
if (!strcmp(s, "etprop")) return K_setprop;
if (!strcmp(s, "etrlimit")) return K_setrlimit;
- if (!strcmp(s, "etsebool")) return K_setsebool;
if (!strcmp(s, "ocket")) return K_socket;
if (!strcmp(s, "tart")) return K_start;
if (!strcmp(s, "top")) return K_stop;
@@ -204,6 +200,9 @@
case 'u':
if (!strcmp(s, "ser")) return K_user;
break;
+ case 'v':
+ if (!strcmp(s, "erity_load_state")) return K_verity_load_state;
+ break;
case 'w':
if (!strcmp(s, "rite")) return K_write;
if (!strcmp(s, "ait")) return K_wait;
@@ -437,7 +436,7 @@
}
int init_parse_config_file(const char* path) {
- INFO("Parsing %s...", path);
+ INFO("Parsing %s...\n", path);
std::string data;
if (!read_file(path, &data)) {
return -1;
@@ -660,6 +659,65 @@
return list_empty(&action_queue);
}
+service* make_exec_oneshot_service(int nargs, char** args) {
+ // Parse the arguments: exec [SECLABEL [UID [GID]*] --] COMMAND ARGS...
+ int command_arg = 1;
+ for (int i = 1; i < nargs; ++i) {
+ if (strcmp(args[i], "--") == 0) {
+ command_arg = i + 1;
+ break;
+ }
+ }
+ if (command_arg > 4 + NR_SVC_SUPP_GIDS) {
+ ERROR("exec called with too many supplementary group ids\n");
+ return NULL;
+ }
+
+ int argc = nargs - command_arg;
+ char** argv = (args + command_arg);
+ if (argc < 1) {
+ ERROR("exec called without command\n");
+ return NULL;
+ }
+
+ service* svc = (service*) calloc(1, sizeof(*svc) + sizeof(char*) * argc);
+ if (svc == NULL) {
+ ERROR("Couldn't allocate service for exec of '%s': %s", argv[0], strerror(errno));
+ return NULL;
+ }
+
+ if (command_arg > 2) {
+ svc->seclabel = args[1];
+ }
+ if (command_arg > 3) {
+ svc->uid = decode_uid(args[2]);
+ }
+ if (command_arg > 4) {
+ svc->gid = decode_uid(args[3]);
+ svc->nr_supp_gids = command_arg - 1 /* -- */ - 4 /* exec SECLABEL UID GID */;
+ for (size_t i = 0; i < svc->nr_supp_gids; ++i) {
+ svc->supp_gids[i] = decode_uid(args[4 + i]);
+ }
+ }
+
+ static int exec_count; // Every service needs a unique name.
+ char* name = NULL;
+ asprintf(&name, "exec %d (%s)", exec_count++, argv[0]);
+ if (name == NULL) {
+ ERROR("Couldn't allocate name for exec service '%s'\n", argv[0]);
+ free(svc);
+ return NULL;
+ }
+ svc->name = name;
+ svc->classname = "default";
+ svc->flags = SVC_EXEC | SVC_ONESHOT;
+ svc->nargs = argc;
+ memcpy(svc->args, argv, sizeof(char*) * svc->nargs);
+ svc->args[argc] = NULL;
+ list_add_tail(&service_list, &svc->slist);
+ return svc;
+}
+
static void *parse_service(struct parse_state *state, int nargs, char **args)
{
if (nargs < 3) {
@@ -683,7 +741,7 @@
parse_error(state, "out of memory\n");
return 0;
}
- svc->name = args[1];
+ svc->name = strdup(args[1]);
svc->classname = "default";
memcpy(svc->args, args + 2, sizeof(char*) * nargs);
trigger* cur_trigger = (trigger*) calloc(1, sizeof(*cur_trigger));
diff --git a/init/init_parser.h b/init/init_parser.h
index 0047da7..6348607 100644
--- a/init/init_parser.h
+++ b/init/init_parser.h
@@ -20,6 +20,7 @@
#define INIT_PARSER_MAXARGS 64
struct action;
+struct service;
struct action *action_remove_queue_head(void);
void action_add_queue_tail(struct action *act);
@@ -33,4 +34,6 @@
int init_parse_config_file(const char *fn);
int expand_props(char *dst, const char *src, int len);
+service* make_exec_oneshot_service(int argc, char** argv);
+
#endif
diff --git a/init/init_parser_test.cpp b/init/init_parser_test.cpp
new file mode 100644
index 0000000..170a73a
--- /dev/null
+++ b/init/init_parser_test.cpp
@@ -0,0 +1,134 @@
+/*
+ * 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 "init_parser.h"
+
+#include "init.h"
+#include "util.h"
+
+#include <errno.h>
+#include <gtest/gtest.h>
+
+TEST(init_parser, make_exec_oneshot_service_invalid_syntax) {
+ char* argv[10];
+ memset(argv, 0, sizeof(argv));
+
+ // Nothing.
+ ASSERT_EQ(nullptr, make_exec_oneshot_service(0, argv));
+
+ // No arguments to 'exec'.
+ argv[0] = const_cast<char*>("exec");
+ ASSERT_EQ(nullptr, make_exec_oneshot_service(1, argv));
+
+ // No command in "exec --".
+ argv[1] = const_cast<char*>("--");
+ ASSERT_EQ(nullptr, make_exec_oneshot_service(2, argv));
+}
+
+TEST(init_parser, make_exec_oneshot_service_too_many_supplementary_gids) {
+ int argc = 0;
+ char* argv[4 + NR_SVC_SUPP_GIDS + 3];
+ argv[argc++] = const_cast<char*>("exec");
+ argv[argc++] = const_cast<char*>("seclabel");
+ argv[argc++] = const_cast<char*>("root"); // uid.
+ argv[argc++] = const_cast<char*>("root"); // gid.
+ for (int i = 0; i < NR_SVC_SUPP_GIDS; ++i) {
+ argv[argc++] = const_cast<char*>("root"); // Supplementary gid.
+ }
+ argv[argc++] = const_cast<char*>("--");
+ argv[argc++] = const_cast<char*>("/system/bin/id");
+ argv[argc] = nullptr;
+ ASSERT_EQ(nullptr, make_exec_oneshot_service(argc, argv));
+}
+
+static void Test_make_exec_oneshot_service(bool dash_dash, bool seclabel, bool uid, bool gid, bool supplementary_gids) {
+ int argc = 0;
+ char* argv[10];
+ argv[argc++] = const_cast<char*>("exec");
+ if (seclabel) {
+ argv[argc++] = const_cast<char*>("u:r:su:s0"); // seclabel
+ if (uid) {
+ argv[argc++] = const_cast<char*>("log"); // uid
+ if (gid) {
+ argv[argc++] = const_cast<char*>("shell"); // gid
+ if (supplementary_gids) {
+ argv[argc++] = const_cast<char*>("system"); // supplementary gid 0
+ argv[argc++] = const_cast<char*>("adb"); // supplementary gid 1
+ }
+ }
+ }
+ }
+ if (dash_dash) {
+ argv[argc++] = const_cast<char*>("--");
+ }
+ argv[argc++] = const_cast<char*>("/system/bin/toybox");
+ argv[argc++] = const_cast<char*>("id");
+ argv[argc] = nullptr;
+ service* svc = make_exec_oneshot_service(argc, argv);
+ ASSERT_NE(nullptr, svc);
+
+ if (seclabel) {
+ ASSERT_STREQ("u:r:su:s0", svc->seclabel);
+ } else {
+ ASSERT_EQ(nullptr, svc->seclabel);
+ }
+ if (uid) {
+ ASSERT_EQ(decode_uid("log"), svc->uid);
+ } else {
+ ASSERT_EQ(0U, svc->uid);
+ }
+ if (gid) {
+ ASSERT_EQ(decode_uid("shell"), svc->gid);
+ } else {
+ ASSERT_EQ(0U, svc->gid);
+ }
+ if (supplementary_gids) {
+ ASSERT_EQ(2U, svc->nr_supp_gids);
+ ASSERT_EQ(decode_uid("system"), svc->supp_gids[0]);
+ ASSERT_EQ(decode_uid("adb"), svc->supp_gids[1]);
+ } else {
+ ASSERT_EQ(0U, svc->nr_supp_gids);
+ }
+
+ ASSERT_EQ(2, svc->nargs);
+ ASSERT_EQ("/system/bin/toybox", svc->args[0]);
+ ASSERT_EQ("id", svc->args[1]);
+ ASSERT_EQ(nullptr, svc->args[2]);
+}
+
+TEST(init_parser, make_exec_oneshot_service_with_everything) {
+ Test_make_exec_oneshot_service(true, true, true, true, true);
+}
+
+TEST(init_parser, make_exec_oneshot_service_with_seclabel_uid_gid) {
+ Test_make_exec_oneshot_service(true, true, true, true, false);
+}
+
+TEST(init_parser, make_exec_oneshot_service_with_seclabel_uid) {
+ Test_make_exec_oneshot_service(true, true, true, false, false);
+}
+
+TEST(init_parser, make_exec_oneshot_service_with_seclabel) {
+ Test_make_exec_oneshot_service(true, true, false, false, false);
+}
+
+TEST(init_parser, make_exec_oneshot_service_with_just_command) {
+ Test_make_exec_oneshot_service(true, false, false, false, false);
+}
+
+TEST(init_parser, make_exec_oneshot_service_with_just_command_no_dash) {
+ Test_make_exec_oneshot_service(false, false, false, false, false);
+}
diff --git a/init/keywords.h b/init/keywords.h
index a8f29d1..c8327c3 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -1,7 +1,5 @@
#ifndef KEYWORD
int do_bootchart_init(int nargs, char **args);
-int do_chroot(int nargs, char **args);
-int do_chdir(int nargs, char **args);
int do_class_start(int nargs, char **args);
int do_class_stop(int nargs, char **args);
int do_class_reset(int nargs, char **args);
@@ -23,11 +21,8 @@
int do_rm(int nargs, char **args);
int do_rmdir(int nargs, char **args);
int do_setcon(int nargs, char **args);
-int do_setenforce(int nargs, char **args);
-int do_setkey(int nargs, char **args);
int do_setprop(int nargs, char **args);
int do_setrlimit(int nargs, char **args);
-int do_setsebool(int nargs, char **args);
int do_start(int nargs, char **args);
int do_stop(int nargs, char **args);
int do_swapon_all(int nargs, char **args);
@@ -41,6 +36,7 @@
int do_loglevel(int nargs, char **args);
int do_load_persist_props(int nargs, char **args);
int do_load_all_props(int nargs, char **args);
+int do_verity_load_state(int nargs, char **args);
int do_wait(int nargs, char **args);
#define __MAKE_KEYWORD_ENUM__
#define KEYWORD(symbol, flags, nargs, func) K_##symbol,
@@ -48,8 +44,6 @@
K_UNKNOWN,
#endif
KEYWORD(capability, OPTION, 0, 0)
- KEYWORD(chdir, COMMAND, 1, do_chdir)
- KEYWORD(chroot, COMMAND, 1, do_chroot)
KEYWORD(class, OPTION, 0, 0)
KEYWORD(class_start, COMMAND, 1, do_class_start)
KEYWORD(class_stop, COMMAND, 1, do_class_stop)
@@ -83,12 +77,9 @@
KEYWORD(seclabel, OPTION, 0, 0)
KEYWORD(service, SECTION, 0, 0)
KEYWORD(setcon, COMMAND, 1, do_setcon)
- KEYWORD(setenforce, COMMAND, 1, do_setenforce)
KEYWORD(setenv, OPTION, 2, 0)
- KEYWORD(setkey, COMMAND, 0, do_setkey)
KEYWORD(setprop, COMMAND, 2, do_setprop)
KEYWORD(setrlimit, COMMAND, 3, do_setrlimit)
- KEYWORD(setsebool, COMMAND, 2, do_setsebool)
KEYWORD(socket, OPTION, 0, 0)
KEYWORD(start, COMMAND, 1, do_start)
KEYWORD(stop, COMMAND, 1, do_stop)
@@ -97,6 +88,7 @@
KEYWORD(symlink, COMMAND, 1, do_symlink)
KEYWORD(sysclktz, COMMAND, 1, do_sysclktz)
KEYWORD(user, OPTION, 0, 0)
+ KEYWORD(verity_load_state, COMMAND, 0, do_verity_load_state)
KEYWORD(wait, COMMAND, 1, do_wait)
KEYWORD(write, COMMAND, 2, do_write)
KEYWORD(copy, COMMAND, 2, do_copy)
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 05c03d6..ddb8050 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -30,8 +30,6 @@
#include <cutils/sockets.h>
#include <cutils/multiuser.h>
-#include <utils/file.h>
-
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include <sys/_system_properties.h>
diff --git a/init/readme.txt b/init/readme.txt
index 9c24220..7443330 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -70,11 +70,11 @@
setenv <name> <value>
Set the environment variable <name> to <value> in the launched process.
-socket <name> <type> <perm> [ <user> [ <group> [ <context> ] ] ]
+socket <name> <type> <perm> [ <user> [ <group> [ <seclabel> ] ] ]
Create a unix domain socket named /dev/socket/<name> and pass
its fd to the launched process. <type> must be "dgram", "stream" or "seqpacket".
User and group default to 0.
- Context is the SELinux security context for the socket.
+ 'seclabel' is the SELinux security context for the socket.
It defaults to the service security context, as specified by seclabel or
computed based on the service executable file security context.
@@ -91,8 +91,8 @@
supplemental groups of the process (via setgroups()).
Currently defaults to root. (??? probably should default to nobody)
-seclabel <securitycontext>
- Change to securitycontext before exec'ing this service.
+seclabel <seclabel>
+ Change to 'seclabel' before exec'ing this service.
Primarily for use by services run from the rootfs, e.g. ueventd, adbd.
Services on the system partition can instead use policy-defined transitions
based on their file security context.
@@ -137,14 +137,17 @@
Commands
--------
-exec <path> [ <argument> ]*
- This command is not implemented.
+exec [ <seclabel> [ <user> [ <group> ]* ] ] -- <command> [ <argument> ]*
+ Fork and execute command with the given arguments. The command starts
+ after "--" so that an optional security context, user, and supplementary
+ groups can be provided. No other commands will be run until this one
+ finishes.
execonce <path> [ <argument> ]*
Fork and execute a program (<path>). This will block until
the program completes execution. This command can be run at most
once during init's lifetime. Subsequent invocations are ignored.
- It is best to avoid exec as unlike the builtin commands, it runs
+ It is best to avoid execonce as unlike the builtin commands, it runs
the risk of getting init "stuck".
export <name> <value>
@@ -161,18 +164,12 @@
hostname <name>
Set the host name.
-chdir <directory>
- Change working directory.
-
chmod <octal-mode> <path>
Change file access permissions.
chown <owner> <group> <path>
Change file owner and group.
-chroot <directory>
- Change process root directory.
-
class_start <serviceclass>
Start all services of the specified class if they are
not already running.
@@ -202,13 +199,16 @@
mkdir <path> [mode] [owner] [group]
Create a directory at <path>, optionally with the given mode, owner, and
group. If not provided, the directory is created with permissions 755 and
- owned by the root user and root group.
+ owned by the root user and root group. If provided, the mode, owner and group
+ will be updated if the directory exists already.
-mount <type> <device> <dir> [ <mountoption> ]*
+mount <type> <device> <dir> [ <flag> ]* [<options>]
Attempt to mount the named device at the directory <dir>
<device> may be of the form mtd@name to specify a mtd block
device by name.
- <mountoption>s include "ro", "rw", "remount", "noatime", ...
+ <flag>s include "ro", "rw", "remount", "noatime", ...
+ <options> include "barrier=1", "noauto_da_alloc", "discard", ... as
+ a comma separated string, eg: barrier=1,noauto_da_alloc
restorecon <path> [ <path> ]*
Restore the file named by <path> to the security context specified
@@ -220,18 +220,11 @@
Recursively restore the directory tree named by <path> to the
security contexts specified in the file_contexts configuration.
-setcon <securitycontext>
+setcon <seclabel>
Set the current process security context to the specified string.
This is typically only used from early-init to set the init context
before any other process is started.
-setenforce 0|1
- Set the SELinux system-wide enforcing status.
- 0 is permissive (i.e. log but do not deny), 1 is enforcing.
-
-setkey
- TBD
-
setprop <name> <value>
Set system property <name> to <value>. Properties are expanded
within <value>.
@@ -239,10 +232,6 @@
setrlimit <resource> <cur> <max>
Set the rlimit for a resource.
-setsebool <name> <value>
- Set SELinux boolean <name> to <value>.
- <value> may be 1|true|on or 0|false|off
-
start <service>
Start a service running if it is not already running.
@@ -275,7 +264,7 @@
Init updates some system properties to provide some insight into
what it's doing:
-init.action
+init.action
Equal to the name of the action currently being executed or "" if none
init.command
diff --git a/init/signal_handler.cpp b/init/signal_handler.cpp
index c0898fb..c428b96 100644
--- a/init/signal_handler.cpp
+++ b/init/signal_handler.cpp
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-#include <stdio.h>
#include <errno.h>
-#include <signal.h>
-#include <unistd.h>
#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
@@ -27,34 +27,28 @@
#include <cutils/list.h>
#include "init.h"
-#include "util.h"
#include "log.h"
+#include "util.h"
static int signal_fd = -1;
static int signal_recv_fd = -1;
-static void sigchld_handler(int s)
-{
+static void sigchld_handler(int s) {
write(signal_fd, &s, 1);
}
#define CRITICAL_CRASH_THRESHOLD 4 /* if we crash >4 times ... */
-#define CRITICAL_CRASH_WINDOW (4*60) /* ... in 4 minutes, goto recovery*/
+#define CRITICAL_CRASH_WINDOW (4*60) /* ... in 4 minutes, goto recovery */
-static int wait_for_one_process(int block)
-{
+static int wait_for_one_process() {
int status;
- struct service *svc;
- struct socketinfo *si;
- time_t now;
- struct listnode *node;
- struct command *cmd;
-
- pid_t pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, block ? 0 : WNOHANG));
- if (pid <= 0) return -1;
+ pid_t pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG));
+ if (pid <= 0) {
+ return -1;
+ }
INFO("waitpid returned pid %d, status = %08x\n", pid, status);
- svc = service_find_by_pid(pid);
+ service* svc = service_find_by_pid(pid);
if (!svc) {
if (WIFEXITED(status)) {
ERROR("untracked pid %d exited with status %d\n", pid, WEXITSTATUS(status));
@@ -68,36 +62,47 @@
return 0;
}
+ // TODO: all the code from here down should be a member function on service.
+
NOTICE("process '%s', pid %d exited\n", svc->name, pid);
if (!(svc->flags & SVC_ONESHOT) || (svc->flags & SVC_RESTART)) {
- kill(-pid, SIGKILL);
NOTICE("process '%s' killing any children in process group\n", svc->name);
+ kill(-pid, SIGKILL);
}
- /* remove any sockets we may have created */
- for (si = svc->sockets; si; si = si->next) {
+ // Remove any sockets we may have created.
+ for (socketinfo* si = svc->sockets; si; si = si->next) {
char tmp[128];
snprintf(tmp, sizeof(tmp), ANDROID_SOCKET_DIR"/%s", si->name);
unlink(tmp);
}
+ if (svc->flags & SVC_EXEC) {
+ INFO("SVC_EXEC pid %d finished...\n", svc->pid);
+ waiting_for_exec = false;
+ list_remove(&svc->slist);
+ free(svc->name);
+ free(svc);
+ return 0;
+ }
+
svc->pid = 0;
svc->flags &= (~SVC_RUNNING);
- /* oneshot processes go into the disabled state on exit,
- * except when manually restarted. */
+ // Oneshot processes go into the disabled state on exit,
+ // except when manually restarted.
if ((svc->flags & SVC_ONESHOT) && !(svc->flags & SVC_RESTART)) {
svc->flags |= SVC_DISABLED;
}
- /* disabled and reset processes do not get restarted automatically */
- if (svc->flags & (SVC_DISABLED | SVC_RESET) ) {
- notify_service_state(svc->name, "stopped");
+ // Disabled and reset processes do not get restarted automatically.
+ if (svc->flags & (SVC_DISABLED | SVC_RESET)) {
+ svc->NotifyStateChange("stopped");
return 0;
}
- now = gettime();
+ time_t now = gettime();
if ((svc->flags & SVC_CRITICAL) && !(svc->flags & SVC_RESTART)) {
if (svc->time_crashed + CRITICAL_CRASH_WINDOW >= now) {
if (++svc->nr_crashed > CRITICAL_CRASH_THRESHOLD) {
@@ -116,36 +121,33 @@
svc->flags &= (~SVC_RESTART);
svc->flags |= SVC_RESTARTING;
- /* Execute all onrestart commands for this service. */
+ // Execute all onrestart commands for this service.
+ struct listnode* node;
list_for_each(node, &svc->onrestart.commands) {
- cmd = node_to_item(node, struct command, clist);
+ command* cmd = node_to_item(node, struct command, clist);
cmd->func(cmd->nargs, cmd->args);
}
- notify_service_state(svc->name, "restarting");
+ svc->NotifyStateChange("restarting");
return 0;
}
-void handle_signal(void)
-{
+void handle_signal() {
+ // We got a SIGCHLD - reap and restart as needed.
char tmp[32];
-
- /* we got a SIGCHLD - reap and restart as needed */
read(signal_recv_fd, tmp, sizeof(tmp));
- while (!wait_for_one_process(0))
- ;
+ while (!wait_for_one_process()) {
+ }
}
-void signal_init(void)
-{
- int s[2];
-
+void signal_init() {
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = sigchld_handler;
act.sa_flags = SA_NOCLDSTOP;
sigaction(SIGCHLD, &act, 0);
- /* create a signalling mechanism for the sigchld handler */
+ // Create a signalling mechanism for the sigchld handler.
+ int s[2];
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, s) == 0) {
signal_fd = s[0];
signal_recv_fd = s[1];
@@ -154,7 +156,6 @@
handle_signal();
}
-int get_signal_fd()
-{
+int get_signal_fd() {
return signal_recv_fd;
}
diff --git a/init/util.cpp b/init/util.cpp
index 3dddb15..c805083 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -32,11 +32,11 @@
#include <sys/socket.h>
#include <sys/un.h>
+#include <base/file.h>
+
/* for ANDROID_SOCKET_* */
#include <cutils/sockets.h>
-#include <utils/file.h>
-
#include <private/android_filesystem_config.h>
#include "init.h"
@@ -168,7 +168,7 @@
return false;
}
- bool okay = android::ReadFdToString(fd, content);
+ bool okay = android::base::ReadFdToString(fd, content);
TEMP_FAILURE_RETRY(close(fd));
if (okay) {
content->append("\n", 1);
@@ -181,7 +181,7 @@
if (fd == -1) {
return -errno;
}
- int result = android::WriteStringToFd(content, fd) ? 0 : -errno;
+ int result = android::base::WriteStringToFd(content, fd) ? 0 : -errno;
TEMP_FAILURE_RETRY(close(fd));
return result;
}
diff --git a/init/util_test.cpp b/init/util_test.cpp
index e9a1581..5b3ab50 100644
--- a/init/util_test.cpp
+++ b/init/util_test.cpp
@@ -35,3 +35,9 @@
s[5] = 0;
EXPECT_STREQ("Linux", s.c_str());
}
+
+TEST(util, decode_uid) {
+ EXPECT_EQ(0U, decode_uid("root"));
+ EXPECT_EQ(-1U, decode_uid("toot"));
+ EXPECT_EQ(123U, decode_uid("123"));
+}
diff --git a/libbacktrace/BacktraceImpl.cpp b/libbacktrace/BacktraceImpl.cpp
index fb8a725..4650b6a 100644
--- a/libbacktrace/BacktraceImpl.cpp
+++ b/libbacktrace/BacktraceImpl.cpp
@@ -17,6 +17,7 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/param.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <ucontext.h>
@@ -159,6 +160,17 @@
}
}
+size_t BacktraceCurrent::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) {
+ backtrace_map_t map;
+ FillInMap(addr, &map);
+ if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) {
+ return 0;
+ }
+ bytes = MIN(map.end - addr, bytes);
+ memcpy(buffer, reinterpret_cast<uint8_t*>(addr), bytes);
+ return bytes;
+}
+
//-------------------------------------------------------------------------
// BacktracePtrace functions.
//-------------------------------------------------------------------------
@@ -171,25 +183,88 @@
BacktracePtrace::~BacktracePtrace() {
}
-bool BacktracePtrace::ReadWord(uintptr_t ptr, word_t* out_value) {
- if (!VerifyReadWordArgs(ptr, out_value)) {
+#if !defined(__APPLE__)
+static bool PtraceRead(pid_t tid, uintptr_t addr, word_t* out_value) {
+ // ptrace() returns -1 and sets errno when the operation fails.
+ // To disambiguate -1 from a valid result, we clear errno beforehand.
+ errno = 0;
+ *out_value = ptrace(PTRACE_PEEKTEXT, tid, reinterpret_cast<void*>(addr), NULL);
+ if (*out_value == static_cast<word_t>(-1) && errno) {
+ BACK_LOGW("invalid pointer %p reading from tid %d, ptrace() strerror(errno)=%s",
+ reinterpret_cast<void*>(addr), tid, strerror(errno));
return false;
}
+ return true;
+}
+#endif
+bool BacktracePtrace::ReadWord(uintptr_t ptr, word_t* out_value) {
#if defined(__APPLE__)
BACK_LOGW("MacOS does not support reading from another pid.");
return false;
#else
- // ptrace() returns -1 and sets errno when the operation fails.
- // To disambiguate -1 from a valid result, we clear errno beforehand.
- errno = 0;
- *out_value = ptrace(PTRACE_PEEKTEXT, Tid(), reinterpret_cast<void*>(ptr), NULL);
- if (*out_value == static_cast<word_t>(-1) && errno) {
- BACK_LOGW("invalid pointer %p reading from tid %d, ptrace() strerror(errno)=%s",
- reinterpret_cast<void*>(ptr), Tid(), strerror(errno));
+ if (!VerifyReadWordArgs(ptr, out_value)) {
return false;
}
- return true;
+
+ backtrace_map_t map;
+ FillInMap(ptr, &map);
+ if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) {
+ return false;
+ }
+
+ return PtraceRead(Tid(), ptr, out_value);
+#endif
+}
+
+size_t BacktracePtrace::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) {
+#if defined(__APPLE__)
+ BACK_LOGW("MacOS does not support reading from another pid.");
+ return 0;
+#else
+ backtrace_map_t map;
+ FillInMap(addr, &map);
+ if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) {
+ return 0;
+ }
+
+ bytes = MIN(map.end - addr, bytes);
+ size_t bytes_read = 0;
+ word_t data_word;
+ size_t align_bytes = addr & (sizeof(word_t) - 1);
+ if (align_bytes != 0) {
+ if (!PtraceRead(Tid(), addr & ~(sizeof(word_t) - 1), &data_word)) {
+ return 0;
+ }
+ align_bytes = sizeof(word_t) - align_bytes;
+ memcpy(buffer, reinterpret_cast<uint8_t*>(&data_word) + sizeof(word_t) - align_bytes,
+ align_bytes);
+ addr += align_bytes;
+ buffer += align_bytes;
+ bytes -= align_bytes;
+ bytes_read += align_bytes;
+ }
+
+ size_t num_words = bytes / sizeof(word_t);
+ for (size_t i = 0; i < num_words; i++) {
+ if (!PtraceRead(Tid(), addr, &data_word)) {
+ return bytes_read;
+ }
+ memcpy(buffer, &data_word, sizeof(word_t));
+ buffer += sizeof(word_t);
+ addr += sizeof(word_t);
+ bytes_read += sizeof(word_t);
+ }
+
+ size_t left_over = bytes & (sizeof(word_t) - 1);
+ if (left_over) {
+ if (!PtraceRead(Tid(), addr, &data_word)) {
+ return bytes_read;
+ }
+ memcpy(buffer, &data_word, left_over);
+ bytes_read += left_over;
+ }
+ return bytes_read;
#endif
}
diff --git a/libbacktrace/BacktraceImpl.h b/libbacktrace/BacktraceImpl.h
index cd61bdf..18c3cb5 100755
--- a/libbacktrace/BacktraceImpl.h
+++ b/libbacktrace/BacktraceImpl.h
@@ -56,6 +56,8 @@
BacktraceCurrent(BacktraceImpl* impl, BacktraceMap* map);
virtual ~BacktraceCurrent();
+ size_t Read(uintptr_t addr, uint8_t* buffer, size_t bytes);
+
bool ReadWord(uintptr_t ptr, word_t* out_value);
};
@@ -64,6 +66,8 @@
BacktracePtrace(BacktraceImpl* impl, pid_t pid, pid_t tid, BacktraceMap* map);
virtual ~BacktracePtrace();
+ size_t Read(uintptr_t addr, uint8_t* buffer, size_t bytes);
+
bool ReadWord(uintptr_t ptr, word_t* out_value);
};
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index 76aabd1..b1e34bd 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -31,7 +31,6 @@
#include <backtrace/Backtrace.h>
#include <backtrace/BacktraceMap.h>
-#include <UniquePtr.h>
// For the THREAD_SIGNAL definition.
#include "BacktraceThread.h"
@@ -40,6 +39,7 @@
#include <gtest/gtest.h>
#include <algorithm>
+#include <memory>
#include <vector>
#include "thread_utils.h"
@@ -60,6 +60,7 @@
pid_t tid;
int32_t state;
pthread_t threadId;
+ void* data;
};
struct dump_thread_t {
@@ -142,9 +143,9 @@
}
void VerifyLevelBacktrace(void*) {
- UniquePtr<Backtrace> backtrace(
+ std::unique_ptr<Backtrace> backtrace(
Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(backtrace.get() != NULL);
+ ASSERT_TRUE(backtrace.get() != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
VerifyLevelDump(backtrace.get());
@@ -162,9 +163,9 @@
}
void VerifyMaxBacktrace(void*) {
- UniquePtr<Backtrace> backtrace(
+ std::unique_ptr<Backtrace> backtrace(
Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(backtrace.get() != NULL);
+ ASSERT_TRUE(backtrace.get() != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
VerifyMaxDump(backtrace.get());
@@ -180,8 +181,8 @@
}
void VerifyThreadTest(pid_t tid, void (*VerifyFunc)(Backtrace*)) {
- UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), tid));
- ASSERT_TRUE(backtrace.get() != NULL);
+ std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), tid));
+ ASSERT_TRUE(backtrace.get() != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
VerifyFunc(backtrace.get());
@@ -198,7 +199,7 @@
}
TEST(libbacktrace, local_trace) {
- ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelBacktrace, NULL), 0);
+ ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelBacktrace, nullptr), 0);
}
void VerifyIgnoreFrames(
@@ -208,7 +209,7 @@
EXPECT_EQ(bt_all->NumFrames(), bt_ign2->NumFrames() + 2);
// Check all of the frames are the same > the current frame.
- bool check = (cur_proc == NULL);
+ bool check = (cur_proc == nullptr);
for (size_t i = 0; i < bt_ign2->NumFrames(); i++) {
if (check) {
EXPECT_EQ(bt_ign2->GetFrame(i)->pc, bt_ign1->GetFrame(i+1)->pc);
@@ -226,30 +227,30 @@
}
void VerifyLevelIgnoreFrames(void*) {
- UniquePtr<Backtrace> all(
+ std::unique_ptr<Backtrace> all(
Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(all.get() != NULL);
+ ASSERT_TRUE(all.get() != nullptr);
ASSERT_TRUE(all->Unwind(0));
- UniquePtr<Backtrace> ign1(
+ std::unique_ptr<Backtrace> ign1(
Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(ign1.get() != NULL);
+ ASSERT_TRUE(ign1.get() != nullptr);
ASSERT_TRUE(ign1->Unwind(1));
- UniquePtr<Backtrace> ign2(
+ std::unique_ptr<Backtrace> ign2(
Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(ign2.get() != NULL);
+ ASSERT_TRUE(ign2.get() != nullptr);
ASSERT_TRUE(ign2->Unwind(2));
VerifyIgnoreFrames(all.get(), ign1.get(), ign2.get(), "VerifyLevelIgnoreFrames");
}
TEST(libbacktrace, local_trace_ignore_frames) {
- ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelIgnoreFrames, NULL), 0);
+ ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelIgnoreFrames, nullptr), 0);
}
TEST(libbacktrace, local_max_trace) {
- ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxBacktrace, NULL), 0);
+ ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxBacktrace, nullptr), 0);
}
void VerifyProcTest(pid_t pid, pid_t tid, bool share_map,
@@ -269,13 +270,13 @@
// Wait for the process to get to a stopping point.
WaitForStop(ptrace_tid);
- UniquePtr<BacktraceMap> map;
+ std::unique_ptr<BacktraceMap> map;
if (share_map) {
map.reset(BacktraceMap::Create(pid));
}
- UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get()));
+ std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get()));
ASSERT_TRUE(backtrace->Unwind(0));
- ASSERT_TRUE(backtrace.get() != NULL);
+ ASSERT_TRUE(backtrace.get() != nullptr);
if (ReadyFunc(backtrace.get())) {
VerifyFunc(backtrace.get());
verified = true;
@@ -291,7 +292,7 @@
TEST(libbacktrace, ptrace_trace) {
pid_t pid;
if ((pid = fork()) == 0) {
- ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0);
+ ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
_exit(1);
}
VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, false, ReadyLevelBacktrace, VerifyLevelDump);
@@ -304,7 +305,7 @@
TEST(libbacktrace, ptrace_trace_shared_map) {
pid_t pid;
if ((pid = fork()) == 0) {
- ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0);
+ ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
_exit(1);
}
@@ -318,7 +319,7 @@
TEST(libbacktrace, ptrace_max_trace) {
pid_t pid;
if ((pid = fork()) == 0) {
- ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, NULL, NULL), 0);
+ ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, nullptr, nullptr), 0);
_exit(1);
}
VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, false, ReadyMaxBacktrace, VerifyMaxDump);
@@ -329,21 +330,21 @@
}
void VerifyProcessIgnoreFrames(Backtrace* bt_all) {
- UniquePtr<Backtrace> ign1(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(ign1.get() != NULL);
+ std::unique_ptr<Backtrace> ign1(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD));
+ ASSERT_TRUE(ign1.get() != nullptr);
ASSERT_TRUE(ign1->Unwind(1));
- UniquePtr<Backtrace> ign2(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(ign2.get() != NULL);
+ std::unique_ptr<Backtrace> ign2(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD));
+ ASSERT_TRUE(ign2.get() != nullptr);
ASSERT_TRUE(ign2->Unwind(2));
- VerifyIgnoreFrames(bt_all, ign1.get(), ign2.get(), NULL);
+ VerifyIgnoreFrames(bt_all, ign1.get(), ign2.get(), nullptr);
}
TEST(libbacktrace, ptrace_ignore_frames) {
pid_t pid;
if ((pid = fork()) == 0) {
- ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0);
+ ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
_exit(1);
}
VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, false, ReadyLevelBacktrace, VerifyProcessIgnoreFrames);
@@ -355,8 +356,8 @@
// Create a process with multiple threads and dump all of the threads.
void* PtraceThreadLevelRun(void*) {
- EXPECT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0);
- return NULL;
+ EXPECT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
+ return nullptr;
}
void GetThreads(pid_t pid, std::vector<pid_t>* threads) {
@@ -365,9 +366,9 @@
snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid);
DIR* tasks_dir = opendir(task_path);
- ASSERT_TRUE(tasks_dir != NULL);
+ ASSERT_TRUE(tasks_dir != nullptr);
struct dirent* entry;
- while ((entry = readdir(tasks_dir)) != NULL) {
+ while ((entry = readdir(tasks_dir)) != nullptr) {
char* end;
pid_t tid = strtoul(entry->d_name, &end, 10);
if (*end == '\0') {
@@ -386,9 +387,9 @@
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_t thread;
- ASSERT_TRUE(pthread_create(&thread, &attr, PtraceThreadLevelRun, NULL) == 0);
+ ASSERT_TRUE(pthread_create(&thread, &attr, PtraceThreadLevelRun, nullptr) == 0);
}
- ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0);
+ ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
_exit(1);
}
@@ -420,27 +421,27 @@
}
void VerifyLevelThread(void*) {
- UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), gettid()));
- ASSERT_TRUE(backtrace.get() != NULL);
+ std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), gettid()));
+ ASSERT_TRUE(backtrace.get() != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
VerifyLevelDump(backtrace.get());
}
TEST(libbacktrace, thread_current_level) {
- ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelThread, NULL), 0);
+ ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelThread, nullptr), 0);
}
void VerifyMaxThread(void*) {
- UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), gettid()));
- ASSERT_TRUE(backtrace.get() != NULL);
+ std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), gettid()));
+ ASSERT_TRUE(backtrace.get() != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
VerifyMaxDump(backtrace.get());
}
TEST(libbacktrace, thread_current_max) {
- ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxThread, NULL), 0);
+ ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxThread, nullptr), 0);
}
void* ThreadLevelRun(void* data) {
@@ -448,7 +449,7 @@
thread->tid = gettid();
EXPECT_NE(test_level_one(1, 2, 3, 4, ThreadSetState, data), 0);
- return NULL;
+ return nullptr;
}
TEST(libbacktrace, thread_level_trace) {
@@ -456,7 +457,7 @@
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- thread_t thread_data = { 0, 0, 0 };
+ thread_t thread_data = { 0, 0, 0, nullptr };
pthread_t thread;
ASSERT_TRUE(pthread_create(&thread, &attr, ThreadLevelRun, &thread_data) == 0);
@@ -471,10 +472,10 @@
// Save the current signal action and make sure it is restored afterwards.
struct sigaction cur_action;
- ASSERT_TRUE(sigaction(THREAD_SIGNAL, NULL, &cur_action) == 0);
+ ASSERT_TRUE(sigaction(THREAD_SIGNAL, nullptr, &cur_action) == 0);
- UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid));
- ASSERT_TRUE(backtrace.get() != NULL);
+ std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid));
+ ASSERT_TRUE(backtrace.get() != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
VerifyLevelDump(backtrace.get());
@@ -484,7 +485,7 @@
// Verify that the old action was restored.
struct sigaction new_action;
- ASSERT_TRUE(sigaction(THREAD_SIGNAL, NULL, &new_action) == 0);
+ ASSERT_TRUE(sigaction(THREAD_SIGNAL, nullptr, &new_action) == 0);
EXPECT_EQ(cur_action.sa_sigaction, new_action.sa_sigaction);
// The SA_RESTORER flag gets set behind our back, so a direct comparison
// doesn't work unless we mask the value off. Mips doesn't have this
@@ -501,26 +502,26 @@
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- thread_t thread_data = { 0, 0, 0 };
+ thread_t thread_data = { 0, 0, 0, nullptr };
pthread_t thread;
ASSERT_TRUE(pthread_create(&thread, &attr, ThreadLevelRun, &thread_data) == 0);
// Wait up to 2 seconds for the tid to be set.
ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2));
- UniquePtr<Backtrace> all(Backtrace::Create(getpid(), thread_data.tid));
- ASSERT_TRUE(all.get() != NULL);
+ std::unique_ptr<Backtrace> all(Backtrace::Create(getpid(), thread_data.tid));
+ ASSERT_TRUE(all.get() != nullptr);
ASSERT_TRUE(all->Unwind(0));
- UniquePtr<Backtrace> ign1(Backtrace::Create(getpid(), thread_data.tid));
- ASSERT_TRUE(ign1.get() != NULL);
+ std::unique_ptr<Backtrace> ign1(Backtrace::Create(getpid(), thread_data.tid));
+ ASSERT_TRUE(ign1.get() != nullptr);
ASSERT_TRUE(ign1->Unwind(1));
- UniquePtr<Backtrace> ign2(Backtrace::Create(getpid(), thread_data.tid));
- ASSERT_TRUE(ign2.get() != NULL);
+ std::unique_ptr<Backtrace> ign2(Backtrace::Create(getpid(), thread_data.tid));
+ ASSERT_TRUE(ign2.get() != nullptr);
ASSERT_TRUE(ign2->Unwind(2));
- VerifyIgnoreFrames(all.get(), ign1.get(), ign2.get(), NULL);
+ VerifyIgnoreFrames(all.get(), ign1.get(), ign2.get(), nullptr);
// Tell the thread to exit its infinite loop.
android_atomic_acquire_store(0, &thread_data.state);
@@ -531,7 +532,7 @@
thread->tid = gettid();
EXPECT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, ThreadSetState, data), 0);
- return NULL;
+ return nullptr;
}
TEST(libbacktrace, thread_max_trace) {
@@ -539,15 +540,15 @@
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- thread_t thread_data = { 0, 0, 0 };
+ thread_t thread_data = { 0, 0, 0, nullptr };
pthread_t thread;
ASSERT_TRUE(pthread_create(&thread, &attr, ThreadMaxRun, &thread_data) == 0);
// Wait for the tid to be set.
ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2));
- UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid));
- ASSERT_TRUE(backtrace.get() != NULL);
+ std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid));
+ ASSERT_TRUE(backtrace.get() != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
VerifyMaxDump(backtrace.get());
@@ -570,7 +571,7 @@
android_atomic_acquire_store(1, &dump->done);
- return NULL;
+ return nullptr;
}
TEST(libbacktrace, thread_multiple_dump) {
@@ -614,11 +615,11 @@
// Tell the runner thread to exit its infinite loop.
android_atomic_acquire_store(0, &runners[i].state);
- ASSERT_TRUE(dumpers[i].backtrace != NULL);
+ ASSERT_TRUE(dumpers[i].backtrace != nullptr);
VerifyMaxDump(dumpers[i].backtrace);
delete dumpers[i].backtrace;
- dumpers[i].backtrace = NULL;
+ dumpers[i].backtrace = nullptr;
}
}
@@ -654,11 +655,11 @@
for (size_t i = 0; i < NUM_THREADS; i++) {
ASSERT_TRUE(WaitForNonZero(&dumpers[i].done, 30));
- ASSERT_TRUE(dumpers[i].backtrace != NULL);
+ ASSERT_TRUE(dumpers[i].backtrace != nullptr);
VerifyMaxDump(dumpers[i].backtrace);
delete dumpers[i].backtrace;
- dumpers[i].backtrace = NULL;
+ dumpers[i].backtrace = nullptr;
}
// Tell the runner thread to exit its infinite loop.
@@ -708,8 +709,8 @@
}
TEST(libbacktrace, format_test) {
- UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD));
- ASSERT_TRUE(backtrace.get() != NULL);
+ std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD));
+ ASSERT_TRUE(backtrace.get() != nullptr);
backtrace_frame_data_t frame;
frame.num = 1;
@@ -778,12 +779,12 @@
return i.start < j.start;
}
-static void VerifyMap(pid_t pid) {
+void VerifyMap(pid_t pid) {
char buffer[4096];
snprintf(buffer, sizeof(buffer), "/proc/%d/maps", pid);
FILE* map_file = fopen(buffer, "r");
- ASSERT_TRUE(map_file != NULL);
+ ASSERT_TRUE(map_file != nullptr);
std::vector<map_test_t> test_maps;
while (fgets(buffer, sizeof(buffer), map_file)) {
map_test_t map;
@@ -793,7 +794,7 @@
fclose(map_file);
std::sort(test_maps.begin(), test_maps.end(), map_sort);
- UniquePtr<BacktraceMap> map(BacktraceMap::Create(pid));
+ std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(pid));
// Basic test that verifies that the map is in the expected order.
std::vector<map_test_t>::const_iterator test_it = test_maps.begin();
@@ -827,7 +828,167 @@
ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
kill(pid, SIGKILL);
- ASSERT_EQ(waitpid(pid, NULL, 0), pid);
+ ASSERT_EQ(waitpid(pid, nullptr, 0), pid);
+}
+
+void* ThreadReadTest(void* data) {
+ thread_t* thread_data = reinterpret_cast<thread_t*>(data);
+
+ thread_data->tid = gettid();
+
+ // Create two map pages.
+ // Mark the second page as not-readable.
+ size_t pagesize = static_cast<size_t>(sysconf(_SC_PAGE_SIZE));
+ uint8_t* memory;
+ if (posix_memalign(reinterpret_cast<void**>(&memory), pagesize, 2 * pagesize) != 0) {
+ return reinterpret_cast<void*>(-1);
+ }
+
+ if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) {
+ return reinterpret_cast<void*>(-1);
+ }
+
+ // Set up a simple pattern in memory.
+ for (size_t i = 0; i < pagesize; i++) {
+ memory[i] = i;
+ }
+
+ thread_data->data = memory;
+
+ // Tell the caller it's okay to start reading memory.
+ android_atomic_acquire_store(1, &thread_data->state);
+
+ // Loop waiting for everything
+ while (thread_data->state) {
+ }
+
+ free(memory);
+
+ android_atomic_acquire_store(1, &thread_data->state);
+
+ return nullptr;
+}
+
+void RunReadTest(Backtrace* backtrace, uintptr_t read_addr) {
+ size_t pagesize = static_cast<size_t>(sysconf(_SC_PAGE_SIZE));
+
+ // Create a page of data to use to do quick compares.
+ uint8_t* expected = new uint8_t[pagesize];
+ for (size_t i = 0; i < pagesize; i++) {
+ expected[i] = i;
+ }
+ uint8_t* data = new uint8_t[2*pagesize];
+ // Verify that we can only read one page worth of data.
+ size_t bytes_read = backtrace->Read(read_addr, data, 2 * pagesize);
+ ASSERT_EQ(pagesize, bytes_read);
+ ASSERT_TRUE(memcmp(data, expected, pagesize) == 0);
+
+ // Verify unaligned reads.
+ for (size_t i = 1; i < sizeof(word_t); i++) {
+ bytes_read = backtrace->Read(read_addr + i, data, 2 * sizeof(word_t));
+ ASSERT_EQ(2 * sizeof(word_t), bytes_read);
+ ASSERT_TRUE(memcmp(data, &expected[i], 2 * sizeof(word_t)) == 0)
+ << "Offset at " << i << " failed";
+ }
+ delete data;
+ delete expected;
+}
+
+TEST(libbacktrace, thread_read) {
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ pthread_t thread;
+ thread_t thread_data = { 0, 0, 0, nullptr };
+ ASSERT_TRUE(pthread_create(&thread, &attr, ThreadReadTest, &thread_data) == 0);
+
+ ASSERT_TRUE(WaitForNonZero(&thread_data.state, 10));
+
+ std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid));
+ ASSERT_TRUE(backtrace.get() != nullptr);
+
+ RunReadTest(backtrace.get(), reinterpret_cast<uintptr_t>(thread_data.data));
+
+ android_atomic_acquire_store(0, &thread_data.state);
+
+ ASSERT_TRUE(WaitForNonZero(&thread_data.state, 10));
+}
+
+volatile uintptr_t g_ready = 0;
+volatile uintptr_t g_addr = 0;
+
+void ForkedReadTest() {
+ // Create two map pages.
+ size_t pagesize = static_cast<size_t>(sysconf(_SC_PAGE_SIZE));
+ uint8_t* memory;
+ if (posix_memalign(reinterpret_cast<void**>(&memory), pagesize, 2 * pagesize) != 0) {
+ perror("Failed to allocate memory\n");
+ exit(1);
+ }
+
+ // Mark the second page as not-readable.
+ if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) {
+ perror("Failed to mprotect memory\n");
+ exit(1);
+ }
+
+ // Set up a simple pattern in memory.
+ for (size_t i = 0; i < pagesize; i++) {
+ memory[i] = i;
+ }
+
+ g_addr = reinterpret_cast<uintptr_t>(memory);
+ g_ready = 1;
+
+ while (1) {
+ usleep(US_PER_MSEC);
+ }
+}
+
+TEST(libbacktrace, process_read) {
+ pid_t pid;
+ if ((pid = fork()) == 0) {
+ ForkedReadTest();
+ exit(0);
+ }
+ ASSERT_NE(-1, pid);
+
+ bool test_executed = false;
+ uint64_t start = NanoTime();
+ while (1) {
+ if (ptrace(PTRACE_ATTACH, pid, 0, 0) == 0) {
+ WaitForStop(pid);
+
+ std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, pid));
+
+ uintptr_t read_addr;
+ size_t bytes_read = backtrace->Read(reinterpret_cast<uintptr_t>(&g_ready),
+ reinterpret_cast<uint8_t*>(&read_addr),
+ sizeof(uintptr_t));
+ ASSERT_EQ(sizeof(uintptr_t), bytes_read);
+ if (read_addr) {
+ // The forked process is ready to be read.
+ bytes_read = backtrace->Read(reinterpret_cast<uintptr_t>(&g_addr),
+ reinterpret_cast<uint8_t*>(&read_addr),
+ sizeof(uintptr_t));
+ ASSERT_EQ(sizeof(uintptr_t), bytes_read);
+
+ RunReadTest(backtrace.get(), read_addr);
+
+ test_executed = true;
+ break;
+ }
+ ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
+ }
+ if ((NanoTime() - start) > 5 * NS_PER_SEC) {
+ break;
+ }
+ usleep(US_PER_MSEC);
+ }
+ kill(pid, SIGKILL);
+ ASSERT_EQ(waitpid(pid, nullptr, 0), pid);
+
+ ASSERT_TRUE(test_executed);
}
#if defined(ENABLE_PSS_TESTS)
@@ -835,11 +996,11 @@
#define MAX_LEAK_BYTES 32*1024UL
-static void CheckForLeak(pid_t pid, pid_t tid) {
+void CheckForLeak(pid_t pid, pid_t tid) {
// Do a few runs to get the PSS stable.
for (size_t i = 0; i < 100; i++) {
Backtrace* backtrace = Backtrace::Create(pid, tid);
- ASSERT_TRUE(backtrace != NULL);
+ ASSERT_TRUE(backtrace != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
delete backtrace;
}
@@ -848,7 +1009,7 @@
// Loop enough that even a small leak should be detectable.
for (size_t i = 0; i < 4096; i++) {
Backtrace* backtrace = Backtrace::Create(pid, tid);
- ASSERT_TRUE(backtrace != NULL);
+ ASSERT_TRUE(backtrace != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
delete backtrace;
}
@@ -863,9 +1024,9 @@
}
TEST(libbacktrace, check_for_leak_local_thread) {
- thread_t thread_data = { 0, 0, 0 };
+ thread_t thread_data = { 0, 0, 0, nullptr };
pthread_t thread;
- ASSERT_TRUE(pthread_create(&thread, NULL, ThreadLevelRun, &thread_data) == 0);
+ ASSERT_TRUE(pthread_create(&thread, nullptr, ThreadLevelRun, &thread_data) == 0);
// Wait up to 2 seconds for the tid to be set.
ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2));
@@ -875,7 +1036,7 @@
// Tell the thread to exit its infinite loop.
android_atomic_acquire_store(0, &thread_data.state);
- ASSERT_TRUE(pthread_join(thread, NULL) == 0);
+ ASSERT_TRUE(pthread_join(thread, nullptr) == 0);
}
TEST(libbacktrace, check_for_leak_remote) {
@@ -898,6 +1059,6 @@
ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
kill(pid, SIGKILL);
- ASSERT_EQ(waitpid(pid, NULL, 0), pid);
+ ASSERT_EQ(waitpid(pid, nullptr, 0), pid);
}
#endif
diff --git a/libcutils/native_handle.c b/libcutils/native_handle.c
index 4089968..9a4a5bb 100644
--- a/libcutils/native_handle.c
+++ b/libcutils/native_handle.c
@@ -30,9 +30,11 @@
native_handle_t* h = malloc(
sizeof(native_handle_t) + sizeof(int)*(numFds+numInts));
- h->version = sizeof(native_handle_t);
- h->numFds = numFds;
- h->numInts = numInts;
+ if (h) {
+ h->version = sizeof(native_handle_t);
+ h->numFds = numFds;
+ h->numInts = numInts;
+ }
return h;
}
diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c
index 2a9d96b..dfc8777 100644
--- a/libcutils/sched_policy.c
+++ b/libcutils/sched_policy.c
@@ -45,8 +45,6 @@
#define POLICY_DEBUG 0
-#define CAN_SET_SP_SYSTEM 0 // non-zero means to implement set_sched_policy(tid, SP_SYSTEM)
-
// This prctl is only available in Android kernels.
#define PR_SET_TIMERSLACK_PID 41
@@ -60,9 +58,6 @@
// File descriptors open to /dev/cpuctl/../tasks, setup by initialize, or -1 on error.
static int bg_cgroup_fd = -1;
static int fg_cgroup_fd = -1;
-#if CAN_SET_SP_SYSTEM
-static int system_cgroup_fd = -1;
-#endif
/* Add tid to the scheduling group defined by the policy */
static int add_tid_to_cgroup(int tid, SchedPolicy policy)
@@ -78,11 +73,6 @@
case SP_AUDIO_SYS:
fd = fg_cgroup_fd;
break;
-#if CAN_SET_SP_SYSTEM
- case SP_SYSTEM:
- fd = system_cgroup_fd;
- break;
-#endif
default:
fd = -1;
break;
@@ -123,21 +113,13 @@
if (!access("/dev/cpuctl/tasks", F_OK)) {
__sys_supports_schedgroups = 1;
-#if CAN_SET_SP_SYSTEM
filename = "/dev/cpuctl/tasks";
- system_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC);
- if (system_cgroup_fd < 0) {
- SLOGV("open of %s failed: %s\n", filename, strerror(errno));
- }
-#endif
-
- filename = "/dev/cpuctl/apps/tasks";
fg_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC);
if (fg_cgroup_fd < 0) {
SLOGE("open of %s failed: %s\n", filename, strerror(errno));
}
- filename = "/dev/cpuctl/apps/bg_non_interactive/tasks";
+ filename = "/dev/cpuctl/bg_non_interactive/tasks";
bg_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC);
if (bg_cgroup_fd < 0) {
SLOGE("open of %s failed: %s\n", filename, strerror(errno));
@@ -231,11 +213,9 @@
if (getSchedulerGroup(tid, grpBuf, sizeof(grpBuf)) < 0)
return -1;
if (grpBuf[0] == '\0') {
- *policy = SP_SYSTEM;
- } else if (!strcmp(grpBuf, "apps/bg_non_interactive")) {
- *policy = SP_BACKGROUND;
- } else if (!strcmp(grpBuf, "apps")) {
*policy = SP_FOREGROUND;
+ } else if (!strcmp(grpBuf, "bg_non_interactive")) {
+ *policy = SP_BACKGROUND;
} else {
errno = ERANGE;
return -1;
diff --git a/libcutils/uevent.c b/libcutils/uevent.c
index 827170a..de5d227 100644
--- a/libcutils/uevent.c
+++ b/libcutils/uevent.c
@@ -112,7 +112,7 @@
addr.nl_pid = getpid();
addr.nl_groups = 0xffffffff;
- s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
+ s = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
if(s < 0)
return -1;
diff --git a/liblog/Android.mk b/liblog/Android.mk
index 5756c54..70aff83 100644
--- a/liblog/Android.mk
+++ b/liblog/Android.mk
@@ -16,6 +16,14 @@
LOCAL_PATH := $(my-dir)
include $(CLEAR_VARS)
+# This is what we want to do:
+# liblog_cflags := $(shell \
+# sed -n \
+# 's/^\([0-9]*\)[ \t]*liblog[ \t].*/-DLIBLOG_LOG_TAG=\1/p' \
+# $(LOCAL_PATH)/event.logtags)
+# so make sure we do not regret hard-coding it as follows:
+liblog_cflags := -DLIBLOG_LOG_TAG=1005
+
ifneq ($(TARGET_USES_LOGD),false)
liblog_sources := logd_write.c
else
@@ -25,28 +33,20 @@
# some files must not be compiled when building against Mingw
# they correspond to features not used by our host development tools
# which are also hard or even impossible to port to native Win32
-WITH_MINGW :=
-ifeq ($(HOST_OS),windows)
- ifeq ($(strip $(USE_CYGWIN)),)
- WITH_MINGW := true
- endif
-endif
-# USE_MINGW is defined when we build against Mingw on Linux
-ifneq ($(strip $(USE_MINGW)),)
- WITH_MINGW := true
-endif
-ifndef WITH_MINGW
+ifeq ($(strip $(USE_MINGW)),)
liblog_sources += \
- logprint.c \
event_tag_map.c
else
liblog_sources += \
uio.c
endif
-liblog_host_sources := $(liblog_sources) fake_log_device.c
+liblog_host_sources := $(liblog_sources) fake_log_device.c event.logtags
liblog_target_sources := $(liblog_sources) log_time.cpp log_is_loggable.c
+ifeq ($(strip $(USE_MINGW)),)
+liblog_target_sources += logprint.c
+endif
ifneq ($(TARGET_USES_LOGD),false)
liblog_target_sources += log_read.c
else
@@ -57,7 +57,7 @@
# ========================================================
LOCAL_MODULE := liblog
LOCAL_SRC_FILES := $(liblog_host_sources)
-LOCAL_CFLAGS := -DFAKE_LOG_DEVICE=1 -Werror
+LOCAL_CFLAGS := -DFAKE_LOG_DEVICE=1 -Werror $(liblog_cflags)
LOCAL_MULTILIB := both
include $(BUILD_HOST_STATIC_LIBRARY)
@@ -76,13 +76,17 @@
include $(CLEAR_VARS)
LOCAL_MODULE := liblog
LOCAL_SRC_FILES := $(liblog_target_sources)
-LOCAL_CFLAGS := -Werror
+LOCAL_CFLAGS := -Werror $(liblog_cflags)
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := liblog
LOCAL_WHOLE_STATIC_LIBRARIES := liblog
-LOCAL_CFLAGS := -Werror
+LOCAL_CFLAGS := -Werror $(liblog_cflags)
+
+# TODO: This is to work around b/19059885. Remove after root cause is fixed
+LOCAL_LDFLAGS_arm := -Wl,--hash-style=sysv
+
include $(BUILD_SHARED_LIBRARY)
include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/liblog/README b/liblog/README
index 461dfbe..f29ac04 100644
--- a/liblog/README
+++ b/liblog/README
@@ -131,6 +131,33 @@
when opening the sub-log. It is recommended to open the log
ANDROID_LOG_RDONLY in these cases.
+ERRORS
+ If messages fail, a negative error code will be returned to the caller.
+
+ The -ENOTCONN return code indicates that the logger daemon is stopped.
+
+ The -EBADF return code indicates that the log access point can not be
+ opened, or the log buffer id is out of range.
+
+ For the -EAGAIN return code, this means that the logging message was
+ temporarily backed-up either because of Denial Of Service (DOS) logging
+ pressure from some chatty application or service in the Android system,
+ or if too small of a value is set in /proc/sys/net/unix/max_dgram_qlen.
+ To aid in diagnosing the occurence of this, a binary event from liblog
+ will be sent to the log daemon once a new message can get through
+ indicating how many messages were dropped as a result. Please take
+ action to resolve the structural problems at the source.
+
+ It is generally not advised for the caller to retry the -EAGAIN return
+ code as this will only make the problem(s) worse and cause your
+ application to temporarily drop to the logger daemon priority, BATCH
+ scheduling policy and background task cgroup. If you require a group of
+ messages to be passed atomically, merge them into one message with
+ embedded newlines to the maximum length LOGGER_ENTRY_MAX_PAYLOAD.
+
+ Other return codes from writing operation can be returned. Since the
+ library retries on EINTR, -EINTR should never be returned.
+
SEE ALSO
syslogd(8)
diff --git a/liblog/event.logtags b/liblog/event.logtags
new file mode 100644
index 0000000..72ecab1
--- /dev/null
+++ b/liblog/event.logtags
@@ -0,0 +1,36 @@
+# The entries in this file map a sparse set of log tag numbers to tag names.
+# This is installed on the device, in /system/etc, and parsed by logcat.
+#
+# Tag numbers are decimal integers, from 0 to 2^31. (Let's leave the
+# negative values alone for now.)
+#
+# Tag names are one or more ASCII letters and numbers or underscores, i.e.
+# "[A-Z][a-z][0-9]_". Do not include spaces or punctuation (the former
+# impacts log readability, the latter makes regex searches more annoying).
+#
+# Tag numbers and names are separated by whitespace. Blank lines and lines
+# starting with '#' are ignored.
+#
+# Optionally, after the tag names can be put a description for the value(s)
+# of the tag. Description are in the format
+# (<name>|data type[|data unit])
+# Multiple values are separated by commas.
+#
+# The data type is a number from the following values:
+# 1: int
+# 2: long
+# 3: string
+# 4: list
+#
+# The data unit is a number taken from the following list:
+# 1: Number of objects
+# 2: Number of bytes
+# 3: Number of milliseconds
+# 4: Number of allocations
+# 5: Id
+# 6: Percent
+# Default value for data of type int/long is 2 (bytes).
+#
+# TODO: generate ".java" and ".h" files with integer constants from this file.
+
+1005 liblog (dropped|1)
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index 0208c73..8f8cc3f 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -13,12 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#if (FAKE_LOG_DEVICE == 0)
+#include <endian.h>
+#endif
#include <errno.h>
#include <fcntl.h>
#if !defined(_WIN32)
#include <pthread.h>
#endif
#include <stdarg.h>
+#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -172,6 +176,11 @@
size_t i, payload_size;
static uid_t last_uid = AID_ROOT; /* logd *always* starts up as AID_ROOT */
static pid_t last_pid = (pid_t) -1;
+ static atomic_int_fast32_t dropped;
+
+ if (!nr) {
+ return -EINVAL;
+ }
if (last_uid == AID_ROOT) { /* have we called to get the UID yet? */
last_uid = getuid();
@@ -206,7 +215,6 @@
pmsg_header.uid = last_uid;
pmsg_header.pid = last_pid;
- header.id = log_id;
header.tid = gettid();
header.realtime.tv_sec = ts.tv_sec;
header.realtime.tv_nsec = ts.tv_nsec;
@@ -216,6 +224,28 @@
newVec[1].iov_base = (unsigned char *) &header;
newVec[1].iov_len = sizeof(header);
+ if (logd_fd > 0) {
+ int32_t snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
+ if (snapshot) {
+ android_log_event_int_t buffer;
+
+ header.id = LOG_ID_EVENTS;
+ buffer.header.tag = htole32(LIBLOG_LOG_TAG);
+ buffer.payload.type = EVENT_TYPE_INT;
+ buffer.payload.data = htole32(snapshot);
+
+ newVec[2].iov_base = &buffer;
+ newVec[2].iov_len = sizeof(buffer);
+
+ ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, 2));
+ if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
+ atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed);
+ }
+ }
+ }
+
+ header.id = log_id;
+
for (payload_size = 0, i = header_length; i < nr + header_length; i++) {
newVec[i].iov_base = vec[i - header_length].iov_base;
payload_size += newVec[i].iov_len = vec[i - header_length].iov_len;
@@ -281,6 +311,8 @@
if (ret > (ssize_t)sizeof(header)) {
ret -= sizeof(header);
+ } else if (ret == -EAGAIN) {
+ atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed);
}
#endif
@@ -463,7 +495,7 @@
}
__android_log_write(ANDROID_LOG_FATAL, tag, buf);
- __builtin_trap(); /* trap so we have a chance to debug the situation */
+ abort(); /* abort so we have a chance to debug the situation */
/* NOTREACHED */
}
diff --git a/liblog/logd_write_kern.c b/liblog/logd_write_kern.c
index 2ca3c94..ca63067 100644
--- a/liblog/logd_write_kern.c
+++ b/liblog/logd_write_kern.c
@@ -266,7 +266,7 @@
}
__android_log_write(ANDROID_LOG_FATAL, tag, buf);
- __builtin_trap(); /* trap so we have a chance to debug the situation */
+ abort(); /* abort so we have a chance to debug the situation */
/* NOTREACHED */
}
diff --git a/libnativebridge/tests/CompleteFlow_test.cpp b/libnativebridge/tests/CompleteFlow_test.cpp
index cf06d2c..b033792 100644
--- a/libnativebridge/tests/CompleteFlow_test.cpp
+++ b/libnativebridge/tests/CompleteFlow_test.cpp
@@ -36,6 +36,7 @@
// Unload
UnloadNativeBridge();
+
ASSERT_FALSE(NativeBridgeAvailable());
ASSERT_FALSE(NativeBridgeError());
diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c
index bfe7121..7d2a5fb 100644
--- a/libnetutils/ifc_utils.c
+++ b/libnetutils/ifc_utils.c
@@ -123,7 +123,7 @@
{
int ret;
if (ifc_ctl_sock == -1) {
- ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0);
+ ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (ifc_ctl_sock < 0) {
printerr("socket() failed: %s\n", strerror(errno));
}
@@ -137,7 +137,7 @@
int ifc_init6(void)
{
if (ifc_ctl_sock6 == -1) {
- ifc_ctl_sock6 = socket(AF_INET6, SOCK_DGRAM, 0);
+ ifc_ctl_sock6 = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (ifc_ctl_sock6 < 0) {
printerr("socket() failed: %s\n", strerror(errno));
}
@@ -316,7 +316,7 @@
req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len) + RTA_LENGTH(addrlen);
memcpy(RTA_DATA(rta), addr, addrlen);
- s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ s = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
if (send(s, &req, req.n.nlmsg_len, 0) < 0) {
close(s);
return -errno;
diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk
index acd18b0..aa614bc 100644
--- a/libpixelflinger/Android.mk
+++ b/libpixelflinger/Android.mk
@@ -74,22 +74,4 @@
LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as
include $(BUILD_SHARED_LIBRARY)
-#
-# Static library version
-#
-
-include $(CLEAR_VARS)
-LOCAL_MODULE:= libpixelflinger_static
-LOCAL_SRC_FILES := $(PIXELFLINGER_SRC_FILES)
-LOCAL_SRC_FILES_arm := $(PIXELFLINGER_SRC_FILES_arm)
-LOCAL_SRC_FILES_arm64 := $(PIXELFLINGER_SRC_FILES_arm64)
-LOCAL_SRC_FILES_mips := $(PIXELFLINGER_SRC_FILES_mips)
-LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS)
-# t32cb16blend.S does not compile with Clang.
-LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
-# arch-arm64/col32cb16blend.S does not compile with Clang.
-LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as
-include $(BUILD_STATIC_LIBRARY)
-
-
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libutils/Android.mk b/libutils/Android.mk
index 7bff14e..e9c5f89 100644
--- a/libutils/Android.mk
+++ b/libutils/Android.mk
@@ -39,9 +39,7 @@
Tokenizer.cpp \
Unicode.cpp \
VectorImpl.cpp \
- file.cpp \
misc.cpp \
- stringprintf.cpp \
host_commonCflags := -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS) -Werror
diff --git a/libutils/tests/Android.mk b/libutils/tests/Android.mk
index ce288ca..634f44f 100644
--- a/libutils/tests/Android.mk
+++ b/libutils/tests/Android.mk
@@ -26,11 +26,9 @@
BasicHashtable_test.cpp \
BlobCache_test.cpp \
BitSet_test.cpp \
- file_test.cpp \
Looper_test.cpp \
LruCache_test.cpp \
String8_test.cpp \
- stringprintf_test.cpp \
Unicode_test.cpp \
Vector_test.cpp \
diff --git a/libziparchive/Android.mk b/libziparchive/Android.mk
index ba7b74d..3937449 100644
--- a/libziparchive/Android.mk
+++ b/libziparchive/Android.mk
@@ -24,7 +24,8 @@
LOCAL_STATIC_LIBRARIES := libz
LOCAL_SHARED_LIBRARIES := libutils
LOCAL_MODULE:= libziparchive
-LOCAL_CFLAGS := -Werror
+LOCAL_CFLAGS := -Werror -Wall
+LOCAL_CPPFLAGS := -Wold-style-cast
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index ebbab9f..e820f2a 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -18,6 +18,9 @@
* Read-only access to Zip archives, with minimal heap allocation.
*/
+#include <memory>
+#include <vector>
+
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
@@ -293,7 +296,7 @@
/* mapped central directory area */
off64_t directory_offset;
- android::FileMap* directory_map;
+ android::FileMap directory_map;
/* number of entries in the Zip archive */
uint16_t num_entries;
@@ -311,7 +314,6 @@
fd(fd),
close_file(assume_ownership),
directory_offset(0),
- directory_map(NULL),
num_entries(0),
hash_table_size(0),
hash_table(NULL) {}
@@ -321,25 +323,10 @@
close(fd);
}
- delete directory_map;
free(hash_table);
}
};
-// Returns 0 on success and negative values on failure.
-static android::FileMap* MapFileSegment(const int fd, const off64_t start,
- const size_t length, const bool read_only,
- const char* debug_file_name) {
- android::FileMap* file_map = new android::FileMap;
- const bool success = file_map->create(debug_file_name, fd, start, length, read_only);
- if (!success) {
- delete file_map;
- return NULL;
- }
-
- return file_map;
-}
-
static int32_t CopyFileToFile(int fd, uint8_t* begin, const uint32_t length, uint64_t *crc_out) {
static const uint32_t kBufSize = 32768;
uint8_t buf[kBufSize];
@@ -521,16 +508,12 @@
* It all looks good. Create a mapping for the CD, and set the fields
* in archive.
*/
- android::FileMap* map = MapFileSegment(fd,
- static_cast<off64_t>(eocd->cd_start_offset),
- static_cast<size_t>(eocd->cd_size),
- true /* read only */, debug_file_name);
- if (map == NULL) {
- archive->directory_map = NULL;
+ if (!archive->directory_map.create(debug_file_name, fd,
+ static_cast<off64_t>(eocd->cd_start_offset),
+ static_cast<size_t>(eocd->cd_size), true /* read only */) ) {
return kMmapFailed;
}
- archive->directory_map = map;
archive->num_entries = eocd->num_records;
archive->directory_offset = eocd->cd_start_offset;
@@ -557,7 +540,7 @@
return kInvalidFile;
}
- if (file_length > (off64_t) 0xffffffff) {
+ if (file_length > static_cast<off64_t>(0xffffffff)) {
ALOGV("Zip: zip file too long %" PRId64, static_cast<int64_t>(file_length));
return kInvalidFile;
}
@@ -599,9 +582,9 @@
* Returns 0 on success.
*/
static int32_t ParseZipArchive(ZipArchive* archive) {
- int32_t result = -1;
- const uint8_t* const cd_ptr = (const uint8_t*) archive->directory_map->getDataPtr();
- const size_t cd_length = archive->directory_map->getDataLength();
+ const uint8_t* const cd_ptr =
+ reinterpret_cast<const uint8_t*>(archive->directory_map.getDataPtr());
+ const size_t cd_length = archive->directory_map.getDataLength();
const uint16_t num_entries = archive->num_entries;
/*
@@ -610,8 +593,8 @@
* least one unused entry to avoid an infinite loop during creation.
*/
archive->hash_table_size = RoundUpPower2(1 + (num_entries * 4) / 3);
- archive->hash_table = (ZipEntryName*) calloc(archive->hash_table_size,
- sizeof(ZipEntryName));
+ archive->hash_table = reinterpret_cast<ZipEntryName*>(calloc(archive->hash_table_size,
+ sizeof(ZipEntryName)));
/*
* Walk through the central directory, adding entries to the hash
@@ -624,18 +607,19 @@
reinterpret_cast<const CentralDirectoryRecord*>(ptr);
if (cdr->record_signature != CentralDirectoryRecord::kSignature) {
ALOGW("Zip: missed a central dir sig (at %" PRIu16 ")", i);
- goto bail;
+ return -1;
}
if (ptr + sizeof(CentralDirectoryRecord) > cd_end) {
ALOGW("Zip: ran off the end (at %" PRIu16 ")", i);
- goto bail;
+ return -1;
}
const off64_t local_header_offset = cdr->local_file_header_offset;
if (local_header_offset >= archive->directory_offset) {
- ALOGW("Zip: bad LFH offset %" PRId64 " at entry %" PRIu16, (int64_t)local_header_offset, i);
- goto bail;
+ ALOGW("Zip: bad LFH offset %" PRId64 " at entry %" PRIu16,
+ static_cast<int64_t>(local_header_offset), i);
+ return -1;
}
const uint16_t file_name_length = cdr->file_name_length;
@@ -645,7 +629,7 @@
/* check that file name is valid UTF-8 and doesn't contain NUL (U+0000) characters */
if (!IsValidEntryName(file_name, file_name_length)) {
- goto bail;
+ return -1;
}
/* add the CDE filename to the hash table */
@@ -654,25 +638,21 @@
entry_name.name_length = file_name_length;
const int add_result = AddToHash(archive->hash_table,
archive->hash_table_size, entry_name);
- if (add_result) {
+ if (add_result != 0) {
ALOGW("Zip: Error adding entry to hash table %d", add_result);
- result = add_result;
- goto bail;
+ return add_result;
}
ptr += sizeof(CentralDirectoryRecord) + file_name_length + extra_length + comment_length;
if ((ptr - cd_ptr) > static_cast<int64_t>(cd_length)) {
ALOGW("Zip: bad CD advance (%tu vs %zu) at entry %" PRIu16,
ptr - cd_ptr, cd_length, i);
- goto bail;
+ return -1;
}
}
ALOGV("+++ zip good scan %" PRIu16 " entries", num_entries);
- result = 0;
-
-bail:
- return result;
+ return 0;
}
static int32_t OpenArchiveInternal(ZipArchive* archive,
@@ -713,7 +693,7 @@
* Close a ZipArchive, closing the file and freeing the contents.
*/
void CloseArchive(ZipArchiveHandle handle) {
- ZipArchive* archive = (ZipArchive*) handle;
+ ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle);
ALOGV("Closing archive %p", archive);
delete archive;
}
@@ -774,8 +754,8 @@
// the name that's in the hash table is a pointer to a location within
// this mapped region.
const uint8_t* base_ptr = reinterpret_cast<const uint8_t*>(
- archive->directory_map->getDataPtr());
- if (ptr < base_ptr || ptr > base_ptr + archive->directory_map->getDataLength()) {
+ archive->directory_map.getDataPtr());
+ if (ptr < base_ptr || ptr > base_ptr + archive->directory_map.getDataLength()) {
ALOGW("Zip: Invalid entry pointer");
return kInvalidOffset;
}
@@ -810,7 +790,8 @@
ssize_t actual = ReadAtOffset(archive->fd, lfh_buf, sizeof(lfh_buf),
local_header_offset);
if (actual != sizeof(lfh_buf)) {
- ALOGW("Zip: failed reading lfh name from offset %" PRId64, (int64_t)local_header_offset);
+ ALOGW("Zip: failed reading lfh name from offset %" PRId64,
+ static_cast<int64_t>(local_header_offset));
return kIoError;
}
@@ -848,12 +829,12 @@
return kInvalidOffset;
}
- uint8_t* name_buf = (uint8_t*) malloc(nameLen);
+ uint8_t* name_buf = reinterpret_cast<uint8_t*>(malloc(nameLen));
ssize_t actual = ReadAtOffset(archive->fd, name_buf, nameLen,
name_offset);
if (actual != nameLen) {
- ALOGW("Zip: failed reading lfh name from offset %" PRId64, (int64_t)name_offset);
+ ALOGW("Zip: failed reading lfh name from offset %" PRId64, static_cast<int64_t>(name_offset));
free(name_buf);
return kIoError;
}
@@ -872,20 +853,21 @@
const off64_t data_offset = local_header_offset + sizeof(LocalFileHeader)
+ lfh->file_name_length + lfh->extra_field_length;
if (data_offset > cd_offset) {
- ALOGW("Zip: bad data offset %" PRId64 " in zip", (int64_t)data_offset);
+ ALOGW("Zip: bad data offset %" PRId64 " in zip", static_cast<int64_t>(data_offset));
return kInvalidOffset;
}
- if ((off64_t)(data_offset + data->compressed_length) > cd_offset) {
+ if (static_cast<off64_t>(data_offset + data->compressed_length) > cd_offset) {
ALOGW("Zip: bad compressed length in zip (%" PRId64 " + %" PRIu32 " > %" PRId64 ")",
- (int64_t)data_offset, data->compressed_length, (int64_t)cd_offset);
+ static_cast<int64_t>(data_offset), data->compressed_length, static_cast<int64_t>(cd_offset));
return kInvalidOffset;
}
if (data->method == kCompressStored &&
- (off64_t)(data_offset + data->uncompressed_length) > cd_offset) {
+ static_cast<off64_t>(data_offset + data->uncompressed_length) > cd_offset) {
ALOGW("Zip: bad uncompressed length in zip (%" PRId64 " + %" PRIu32 " > %" PRId64 ")",
- (int64_t)data_offset, data->uncompressed_length, (int64_t)cd_offset);
+ static_cast<int64_t>(data_offset), data->uncompressed_length,
+ static_cast<int64_t>(cd_offset));
return kInvalidOffset;
}
@@ -917,7 +899,7 @@
int32_t StartIteration(ZipArchiveHandle handle, void** cookie_ptr,
const ZipEntryName* optional_prefix) {
- ZipArchive* archive = (ZipArchive *) handle;
+ ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle);
if (archive == NULL || archive->hash_table == NULL) {
ALOGW("Zip: Invalid ZipArchiveHandle");
@@ -939,7 +921,7 @@
int32_t FindEntry(const ZipArchiveHandle handle, const ZipEntryName& entryName,
ZipEntry* data) {
- const ZipArchive* archive = (ZipArchive*) handle;
+ const ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle);
if (entryName.name_length == 0) {
ALOGW("Zip: Invalid filename %.*s", entryName.name_length, entryName.name);
return kInvalidEntryName;
@@ -957,7 +939,7 @@
}
int32_t Next(void* cookie, ZipEntry* data, ZipEntryName* name) {
- IterationHandle* handle = (IterationHandle *) cookie;
+ IterationHandle* handle = reinterpret_cast<IterationHandle*>(cookie);
if (handle == NULL) {
return kInvalidHandle;
}
@@ -991,13 +973,20 @@
return kIterationEnd;
}
+// This method is using libz macros with old-style-casts
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+static inline int zlib_inflateInit2(z_stream* stream, int window_bits) {
+ return inflateInit2(stream, window_bits);
+}
+#pragma GCC diagnostic pop
+
static int32_t InflateToFile(int fd, const ZipEntry* entry,
uint8_t* begin, uint32_t length,
uint64_t* crc_out) {
- int32_t result = -1;
- const uint32_t kBufSize = 32768;
- uint8_t read_buf[kBufSize];
- uint8_t write_buf[kBufSize];
+ const size_t kBufSize = 32768;
+ std::vector<uint8_t> read_buf(kBufSize);
+ std::vector<uint8_t> write_buf(kBufSize);
z_stream zstream;
int zerr;
@@ -1010,7 +999,7 @@
zstream.opaque = Z_NULL;
zstream.next_in = NULL;
zstream.avail_in = 0;
- zstream.next_out = (Bytef*) write_buf;
+ zstream.next_out = &write_buf[0];
zstream.avail_out = kBufSize;
zstream.data_type = Z_UNKNOWN;
@@ -1018,7 +1007,7 @@
* Use the undocumented "negative window bits" feature to tell zlib
* that there's no zlib header waiting for it.
*/
- zerr = inflateInit2(&zstream, -MAX_WBITS);
+ zerr = zlib_inflateInit2(&zstream, -MAX_WBITS);
if (zerr != Z_OK) {
if (zerr == Z_VERSION_ERROR) {
ALOGE("Installed zlib is not compatible with linked version (%s)",
@@ -1030,6 +1019,12 @@
return kZlibError;
}
+ auto zstream_deleter = [](z_stream* stream) {
+ inflateEnd(stream); /* free up any allocated structures */
+ };
+
+ std::unique_ptr<z_stream, decltype(zstream_deleter)> zstream_guard(&zstream, zstream_deleter);
+
const uint32_t uncompressed_length = entry->uncompressed_length;
uint32_t compressed_length = entry->compressed_length;
@@ -1038,16 +1033,15 @@
/* read as much as we can */
if (zstream.avail_in == 0) {
const ZD_TYPE getSize = (compressed_length > kBufSize) ? kBufSize : compressed_length;
- const ZD_TYPE actual = TEMP_FAILURE_RETRY(read(fd, read_buf, getSize));
+ const ZD_TYPE actual = TEMP_FAILURE_RETRY(read(fd, &read_buf[0], getSize));
if (actual != getSize) {
ALOGW("Zip: inflate read failed (" ZD " vs " ZD ")", actual, getSize);
- result = kIoError;
- goto z_bail;
+ return kIoError;
}
compressed_length -= getSize;
- zstream.next_in = read_buf;
+ zstream.next_in = &read_buf[0];
zstream.avail_in = getSize;
}
@@ -1057,22 +1051,21 @@
ALOGW("Zip: inflate zerr=%d (nIn=%p aIn=%u nOut=%p aOut=%u)",
zerr, zstream.next_in, zstream.avail_in,
zstream.next_out, zstream.avail_out);
- result = kZlibError;
- goto z_bail;
+ return kZlibError;
}
/* write when we're full or when we're done */
if (zstream.avail_out == 0 ||
(zerr == Z_STREAM_END && zstream.avail_out != kBufSize)) {
- const size_t write_size = zstream.next_out - write_buf;
+ const size_t write_size = zstream.next_out - &write_buf[0];
// The file might have declared a bogus length.
if (write_size + write_count > length) {
- goto z_bail;
+ return -1;
}
- memcpy(begin + write_count, write_buf, write_size);
+ memcpy(begin + write_count, &write_buf[0], write_size);
write_count += write_size;
- zstream.next_out = write_buf;
+ zstream.next_out = &write_buf[0];
zstream.avail_out = kBufSize;
}
} while (zerr == Z_OK);
@@ -1085,26 +1078,20 @@
if (zstream.total_out != uncompressed_length || compressed_length != 0) {
ALOGW("Zip: size mismatch on inflated file (%lu vs %" PRIu32 ")",
zstream.total_out, uncompressed_length);
- result = kInconsistentInformation;
- goto z_bail;
+ return kInconsistentInformation;
}
- result = 0;
-
-z_bail:
- inflateEnd(&zstream); /* free up any allocated structures */
-
- return result;
+ return 0;
}
int32_t ExtractToMemory(ZipArchiveHandle handle,
ZipEntry* entry, uint8_t* begin, uint32_t size) {
- ZipArchive* archive = (ZipArchive*) handle;
+ ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle);
const uint16_t method = entry->method;
off64_t data_offset = entry->offset;
if (lseek64(archive->fd, data_offset, SEEK_SET) != data_offset) {
- ALOGW("Zip: lseek to data at %" PRId64 " failed", (int64_t)data_offset);
+ ALOGW("Zip: lseek to data at %" PRId64 " failed", static_cast<int64_t>(data_offset));
return kIoError;
}
@@ -1148,7 +1135,7 @@
int result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
if (result == -1) {
ALOGW("Zip: unable to truncate file to %" PRId64 ": %s",
- (int64_t)(declared_length + current_offset), strerror(errno));
+ static_cast<int64_t>(declared_length + current_offset), strerror(errno));
return kIoError;
}
@@ -1159,16 +1146,14 @@
return 0;
}
- android::FileMap* map = MapFileSegment(fd, current_offset, declared_length,
- false, kTempMappingFileName);
- if (map == NULL) {
+ android::FileMap map;
+ if (!map.create(kTempMappingFileName, fd, current_offset, declared_length, false)) {
return kMmapFailed;
}
const int32_t error = ExtractToMemory(handle, entry,
- reinterpret_cast<uint8_t*>(map->getDataPtr()),
- map->getDataLength());
- delete map;
+ reinterpret_cast<uint8_t*>(map.getDataPtr()),
+ map.getDataLength());
return error;
}
@@ -1181,6 +1166,6 @@
}
int GetFileDescriptor(const ZipArchiveHandle handle) {
- return ((ZipArchive*) handle)->fd;
+ return reinterpret_cast<ZipArchive*>(handle)->fd;
}
diff --git a/libzipfile/zipfile.c b/libzipfile/zipfile.c
index b903fcf..1032ecc 100644
--- a/libzipfile/zipfile.c
+++ b/libzipfile/zipfile.c
@@ -76,7 +76,7 @@
};
static int
-uninflate(unsigned char* out, int unlen, const unsigned char* in, int clen)
+inflate_wrapper(unsigned char* out, int unlen, const unsigned char* in, int clen)
{
z_stream zstream;
int err = 0;
@@ -121,7 +121,7 @@
memcpy(buf, entry->data, entry->uncompressedSize);
return 0;
case DEFLATED:
- return uninflate(buf, bufsize, entry->data, entry->compressedSize);
+ return inflate_wrapper(buf, bufsize, entry->data, entry->compressedSize);
default:
return -1;
}
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index cd5003e..be96fc4 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -38,14 +38,12 @@
struct logger *logger;
struct logger_list *logger_list;
bool printed;
- char label;
log_device_t* next;
- log_device_t(const char* d, bool b, char l) {
+ log_device_t(const char* d, bool b) {
device = d;
binary = b;
- label = l;
next = NULL;
printed = false;
}
@@ -61,9 +59,7 @@
static int g_outFD = -1;
static off_t g_outByteCount = 0;
static int g_printBinary = 0;
-static int g_devCount = 0;
-
-static EventTagMap* g_eventTagMap = NULL;
+static int g_devCount = 0; // >1 means multiple
static int openLogFile (const char *pathname)
{
@@ -133,8 +129,15 @@
char binaryMsgBuf[1024];
if (dev->binary) {
+ static bool hasOpenedEventTagMap = false;
+ static EventTagMap *eventTagMap = NULL;
+
+ if (!eventTagMap && !hasOpenedEventTagMap) {
+ eventTagMap = android_openEventTagMap(EVENT_TAG_MAP_FILE);
+ hasOpenedEventTagMap = true;
+ }
err = android_log_processBinaryLogBuffer(&buf->entry_v1, &entry,
- g_eventTagMap,
+ eventTagMap,
binaryMsgBuf,
sizeof(binaryMsgBuf));
//printf(">>> pri=%d len=%d msg='%s'\n",
@@ -147,16 +150,6 @@
}
if (android_log_shouldPrintLine(g_logformat, entry.tag, entry.priority)) {
- if (false && g_devCount > 1) {
- binaryMsgBuf[0] = dev->label;
- binaryMsgBuf[1] = ' ';
- bytesWritten = write(g_outFD, binaryMsgBuf, 2);
- if (bytesWritten < 0) {
- perror("output error");
- exit(-1);
- }
- }
-
bytesWritten = android_log_printLogLine(g_logformat, g_outFD, &entry);
if (bytesWritten < 0) {
@@ -222,7 +215,7 @@
fprintf(stderr, "options include:\n"
" -s Set default filter to silent.\n"
- " Like specifying filterspec '*:s'\n"
+ " Like specifying filterspec '*:S'\n"
" -f <filename> Log to file. Default to stdout\n"
" -r [<kbytes>] Rotate log every kbytes. (16 if unspecified). Requires -f\n"
" -n <count> Sets max number of rotated logs to <count>, default 4\n"
@@ -257,21 +250,19 @@
fprintf(stderr,"\nfilterspecs are a series of \n"
" <tag>[:priority]\n\n"
"where <tag> is a log component tag (or * for all) and priority is:\n"
- " V Verbose\n"
- " D Debug\n"
+ " V Verbose (default for <tag>)\n"
+ " D Debug (default for '*')\n"
" I Info\n"
" W Warn\n"
" E Error\n"
" F Fatal\n"
- " S Silent (supress all output)\n"
- "\n'*' means '*:d' and <tag> by itself means <tag>:v\n"
- "\nIf not specified on the commandline, filterspec is set from ANDROID_LOG_TAGS.\n"
- "If no filterspec is found, filter defaults to '*:I'\n"
- "\nIf not specified with -v, format is set from ANDROID_PRINTF_LOG\n"
+ " S Silent (suppress all output)\n"
+ "\n'*' by itself means '*:D' and <tag> by itself means <tag>:V.\n"
+ "If no '*' filterspec or -s on command line, all filter defaults to '*:V'.\n"
+ "eg: '*:S <tag>' prints only <tag>, '<tag>:S' suppresses all <tag> log messages.\n"
+ "\nIf not specified on the command line, filterspec is set from ANDROID_LOG_TAGS.\n"
+ "\nIf not specified with -v on command line, format is set from ANDROID_PRINTF_LOG\n"
"or defaults to \"threadtime\"\n\n");
-
-
-
}
@@ -331,7 +322,6 @@
const char *forceFilters = NULL;
log_device_t* devices = NULL;
log_device_t* dev;
- bool needBinary = false;
bool printDividers = false;
struct logger_list *logger_list;
unsigned int tail_lines = 0;
@@ -469,7 +459,6 @@
devices = dev = NULL;
android::g_devCount = 0;
- needBinary = false;
for(int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
const char *name = android_log_id_to_name((log_id_t)i);
log_id_t log_id = android_name_to_log_id(name);
@@ -479,7 +468,7 @@
}
bool binary = strcmp(name, "events") == 0;
- log_device_t* d = new log_device_t(name, binary, *name);
+ log_device_t* d = new log_device_t(name, binary);
if (dev) {
dev->next = d;
@@ -488,26 +477,20 @@
devices = dev = d;
}
android::g_devCount++;
- if (binary) {
- needBinary = true;
- }
}
break;
}
bool binary = strcmp(optarg, "events") == 0;
- if (binary) {
- needBinary = true;
- }
if (devices) {
dev = devices;
while (dev->next) {
dev = dev->next;
}
- dev->next = new log_device_t(optarg, binary, optarg[0]);
+ dev->next = new log_device_t(optarg, binary);
} else {
- devices = new log_device_t(optarg, binary, optarg[0]);
+ devices = new log_device_t(optarg, binary);
}
android::g_devCount++;
}
@@ -641,14 +624,14 @@
}
if (!devices) {
- dev = devices = new log_device_t("main", false, 'm');
+ dev = devices = new log_device_t("main", false);
android::g_devCount = 1;
if (android_name_to_log_id("system") == LOG_ID_SYSTEM) {
- dev = dev->next = new log_device_t("system", false, 's');
+ dev = dev->next = new log_device_t("system", false);
android::g_devCount++;
}
if (android_name_to_log_id("crash") == LOG_ID_CRASH) {
- dev = dev->next = new log_device_t("crash", false, 'c');
+ dev = dev->next = new log_device_t("crash", false);
android::g_devCount++;
}
}
@@ -848,17 +831,15 @@
//LOG_EVENT_LONG(11, 0x1122334455667788LL);
//LOG_EVENT_STRING(0, "whassup, doc?");
- if (needBinary)
- android::g_eventTagMap = android_openEventTagMap(EVENT_TAG_MAP_FILE);
-
dev = NULL;
+ log_device_t unexpected("unexpected", false);
while (1) {
struct log_msg log_msg;
log_device_t* d;
int ret = android_logger_list_read(logger_list, &log_msg);
if (ret == 0) {
- fprintf(stderr, "read: Unexpected EOF!\n");
+ fprintf(stderr, "read: unexpected EOF!\n");
exit(EXIT_FAILURE);
}
@@ -868,7 +849,7 @@
}
if (ret == -EIO) {
- fprintf(stderr, "read: Unexpected EOF!\n");
+ fprintf(stderr, "read: unexpected EOF!\n");
exit(EXIT_FAILURE);
}
if (ret == -EINVAL) {
@@ -885,8 +866,9 @@
}
}
if (!d) {
- fprintf(stderr, "read: Unexpected log ID!\n");
- exit(EXIT_FAILURE);
+ android::g_devCount = 2; // set to Multiple
+ d = &unexpected;
+ d->binary = log_msg.id() == LOG_ID_EVENTS;
}
if (dev != d) {
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index b358485..de2db67 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -505,12 +505,14 @@
while (fgets(buffer, sizeof(buffer), fp)) {
static const char match_1[] = "4 log.txt";
static const char match_2[] = "8 log.txt";
- static const char match_3[] = "16 log.txt";
+ static const char match_3[] = "12 log.txt";
+ static const char match_4[] = "16 log.txt";
static const char total[] = "total ";
if (!strncmp(buffer, match_1, sizeof(match_1) - 1)
|| !strncmp(buffer, match_2, sizeof(match_2) - 1)
- || !strncmp(buffer, match_3, sizeof(match_3) - 1)) {
+ || !strncmp(buffer, match_3, sizeof(match_3) - 1)
+ || !strncmp(buffer, match_4, sizeof(match_4) - 1)) {
++count;
} else if (strncmp(buffer, total, sizeof(total) - 1)) {
fprintf(stderr, "WARNING: Parse error: %s", buffer);
diff --git a/logd/Android.mk b/logd/Android.mk
index 188511f..127a66b 100644
--- a/logd/Android.mk
+++ b/logd/Android.mk
@@ -26,7 +26,16 @@
libcutils \
libutils
-LOCAL_CFLAGS := -Werror $(shell sed -n 's/^\([0-9]*\)[ \t]*auditd[ \t].*/-DAUDITD_LOG_TAG=\1/p' $(LOCAL_PATH)/event.logtags)
+# This is what we want to do:
+# event_logtags = $(shell \
+# sed -n \
+# "s/^\([0-9]*\)[ \t]*$1[ \t].*/-D`echo $1 | tr a-z A-Z`_LOG_TAG=\1/p" \
+# $(LOCAL_PATH)/$2/event.logtags)
+# event_flag := $(call event_logtags,auditd)
+# so make sure we do not regret hard-coding it as follows:
+event_flag := -DAUDITD_LOG_TAG=1003
+
+LOCAL_CFLAGS := -Werror $(event_flag)
include $(BUILD_EXECUTABLE)
diff --git a/logd/CommandListener.cpp b/logd/CommandListener.cpp
index d7088b4..561ea3e 100644
--- a/logd/CommandListener.cpp
+++ b/logd/CommandListener.cpp
@@ -44,6 +44,7 @@
registerCmd(new GetStatisticsCmd(buf));
registerCmd(new SetPruneListCmd(buf));
registerCmd(new GetPruneListCmd(buf));
+ registerCmd(new ReinitCmd());
}
CommandListener::ShutdownCmd::ShutdownCmd(LogBuffer *buf, LogReader *reader,
@@ -296,6 +297,21 @@
return 0;
}
+CommandListener::ReinitCmd::ReinitCmd()
+ : LogCommand("reinit")
+{ }
+
+int CommandListener::ReinitCmd::runCommand(SocketClient *cli,
+ int /*argc*/, char ** /*argv*/) {
+ setname();
+
+ reinit_signal_handler(SIGHUP);
+
+ cli->sendMsg("success");
+
+ return 0;
+}
+
int CommandListener::getLogSocket() {
static const char socketName[] = "logd";
int sock = android_get_control_socket(socketName);
diff --git a/logd/CommandListener.h b/logd/CommandListener.h
index cd1c306..83e06b4 100644
--- a/logd/CommandListener.h
+++ b/logd/CommandListener.h
@@ -23,6 +23,9 @@
#include "LogReader.h"
#include "LogListener.h"
+// See main.cpp for implementation
+void reinit_signal_handler(int /*signal*/);
+
class CommandListener : public FrameworkListener {
LogBuffer &mBuf;
@@ -60,6 +63,14 @@
LogBufferCmd(GetStatistics)
LogBufferCmd(GetPruneList)
LogBufferCmd(SetPruneList)
+
+ class ReinitCmd : public LogCommand {
+ public:
+ ReinitCmd();
+ virtual ~ReinitCmd() {}
+ int runCommand(SocketClient *c, int argc, char ** argv);
+ };
+
};
#endif
diff --git a/logd/FlushCommand.cpp b/logd/FlushCommand.cpp
index 3be07c0..26a1861 100644
--- a/logd/FlushCommand.cpp
+++ b/logd/FlushCommand.cpp
@@ -27,7 +27,7 @@
unsigned long tail,
unsigned int logMask,
pid_t pid,
- log_time start)
+ uint64_t start)
: mReader(reader)
, mNonBlock(nonBlock)
, mTail(tail)
diff --git a/logd/FlushCommand.h b/logd/FlushCommand.h
index f34c06a..61c6858 100644
--- a/logd/FlushCommand.h
+++ b/logd/FlushCommand.h
@@ -31,7 +31,7 @@
unsigned long mTail;
unsigned int mLogMask;
pid_t mPid;
- log_time mStart;
+ uint64_t mStart;
public:
FlushCommand(LogReader &mReader,
@@ -39,7 +39,7 @@
unsigned long tail = -1,
unsigned int logMask = -1,
pid_t pid = 0,
- log_time start = LogTimeEntry::EPOCH);
+ uint64_t start = 1);
virtual void runSocketCommand(SocketClient *client);
static bool hasReadLogs(SocketClient *client);
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index c7c0249..6b3e637 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -15,6 +15,7 @@
*/
#include <ctype.h>
+#include <endian.h>
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
@@ -23,13 +24,15 @@
#include <sys/uio.h>
#include <syslog.h>
+#include <private/android_logger.h>
+
#include "libaudit.h"
#include "LogAudit.h"
-#define KMSG_PRIORITY(PRI) \
- '<', \
- '0' + (LOG_AUTH | (PRI)) / 10, \
- '0' + (LOG_AUTH | (PRI)) % 10, \
+#define KMSG_PRIORITY(PRI) \
+ '<', \
+ '0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) / 10, \
+ '0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) % 10, \
'>'
LogAudit::LogAudit(LogBuffer *buf, LogReader *reader, int fdDmesg)
@@ -138,29 +141,23 @@
// log to events
size_t l = strlen(str);
- size_t n = l + sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint32_t);
+ size_t n = l + sizeof(android_log_event_string_t);
bool notify = false;
- char *newstr = reinterpret_cast<char *>(malloc(n));
- if (!newstr) {
+ android_log_event_string_t *event = static_cast<android_log_event_string_t *>(malloc(n));
+ if (!event) {
rc = -ENOMEM;
} else {
- cp = newstr;
- *cp++ = AUDITD_LOG_TAG & 0xFF;
- *cp++ = (AUDITD_LOG_TAG >> 8) & 0xFF;
- *cp++ = (AUDITD_LOG_TAG >> 16) & 0xFF;
- *cp++ = (AUDITD_LOG_TAG >> 24) & 0xFF;
- *cp++ = EVENT_TYPE_STRING;
- *cp++ = l & 0xFF;
- *cp++ = (l >> 8) & 0xFF;
- *cp++ = (l >> 16) & 0xFF;
- *cp++ = (l >> 24) & 0xFF;
- memcpy(cp, str, l);
+ event->header.tag = htole32(AUDITD_LOG_TAG);
+ event->payload.type = EVENT_TYPE_STRING;
+ event->payload.length = htole32(l);
+ memcpy(event->payload.data, str, l);
- logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid, newstr,
+ logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid,
+ reinterpret_cast<char *>(event),
(n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
- free(newstr);
+ free(event);
notify = true;
}
@@ -190,7 +187,7 @@
}
n = (estr - str) + strlen(ecomm) + l + 2;
- newstr = reinterpret_cast<char *>(malloc(n));
+ char *newstr = static_cast<char *>(malloc(n));
if (!newstr) {
rc = -ENOMEM;
} else {
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 3d0b38f..2693583 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -92,11 +92,7 @@
return value;
}
-LogBuffer::LogBuffer(LastLogTimes *times)
- : dgramQlenStatistics(false)
- , mTimes(*times) {
- pthread_mutex_init(&mLogElementsLock, NULL);
-
+void LogBuffer::init() {
static const char global_tuneable[] = "persist.logd.size"; // Settings App
static const char global_default[] = "ro.logd.size"; // BoardConfig.mk
@@ -132,6 +128,13 @@
}
}
+LogBuffer::LogBuffer(LastLogTimes *times)
+ : mTimes(*times) {
+ pthread_mutex_init(&mLogElementsLock, NULL);
+
+ init();
+}
+
void LogBuffer::log(log_id_t log_id, log_time realtime,
uid_t uid, pid_t pid, pid_t tid,
const char *msg, unsigned short len) {
@@ -150,23 +153,6 @@
while (last != mLogElements.begin()) {
--it;
if ((*it)->getRealTime() <= realtime) {
- // halves the peak performance, use with caution
- if (dgramQlenStatistics) {
- LogBufferElementCollection::iterator ib = it;
- unsigned short buckets, num = 1;
- for (unsigned short i = 0; (buckets = stats.dgramQlen(i)); ++i) {
- buckets -= num;
- num += buckets;
- while (buckets && (--ib != mLogElements.begin())) {
- --buckets;
- }
- if (buckets) {
- break;
- }
- stats.recordDiff(
- elem->getRealTime() - (*ib)->getRealTime(), i);
- }
- }
break;
}
last = it;
@@ -175,7 +161,7 @@
if (last == mLogElements.end()) {
mLogElements.push_back(elem);
} else {
- log_time end = log_time::EPOCH;
+ uint64_t end = 1;
bool end_set = false;
bool end_always = false;
@@ -198,7 +184,7 @@
}
if (end_always
- || (end_set && (end >= (*last)->getMonotonicTime()))) {
+ || (end_set && (end >= (*last)->getSequence()))) {
mLogElements.push_back(elem);
} else {
mLogElements.insert(last,elem);
@@ -255,7 +241,7 @@
for(it = mLogElements.begin(); it != mLogElements.end();) {
LogBufferElement *e = *it;
- if (oldest && (oldest->mStart <= e->getMonotonicTime())) {
+ if (oldest && (oldest->mStart <= e->getSequence())) {
break;
}
@@ -307,7 +293,7 @@
for(it = mLogElements.begin(); it != mLogElements.end();) {
LogBufferElement *e = *it;
- if (oldest && (oldest->mStart <= e->getMonotonicTime())) {
+ if (oldest && (oldest->mStart <= e->getSequence())) {
break;
}
@@ -348,7 +334,7 @@
while((pruneRows > 0) && (it != mLogElements.end())) {
LogBufferElement *e = *it;
if (e->getLogId() == id) {
- if (oldest && (oldest->mStart <= e->getMonotonicTime())) {
+ if (oldest && (oldest->mStart <= e->getSequence())) {
if (!whitelist) {
if (stats.sizes(id) > (2 * log_buffer_size(id))) {
// kick a misbehaving log reader client off the island
@@ -380,7 +366,7 @@
while((it != mLogElements.end()) && (pruneRows > 0)) {
LogBufferElement *e = *it;
if (e->getLogId() == id) {
- if (oldest && (oldest->mStart <= e->getMonotonicTime())) {
+ if (oldest && (oldest->mStart <= e->getSequence())) {
if (stats.sizes(id) > (2 * log_buffer_size(id))) {
// kick a misbehaving log reader client off the island
oldest->release_Locked();
@@ -437,16 +423,16 @@
return retval;
}
-log_time LogBuffer::flushTo(
- SocketClient *reader, const log_time start, bool privileged,
- bool (*filter)(const LogBufferElement *element, void *arg), void *arg) {
+uint64_t LogBuffer::flushTo(
+ SocketClient *reader, const uint64_t start, bool privileged,
+ int (*filter)(const LogBufferElement *element, void *arg), void *arg) {
LogBufferElementCollection::iterator it;
- log_time max = start;
+ uint64_t max = start;
uid_t uid = reader->getUid();
pthread_mutex_lock(&mLogElementsLock);
- if (start == LogTimeEntry::EPOCH) {
+ if (start <= 1) {
// client wants to start from the beginning
it = mLogElements.begin();
} else {
@@ -455,7 +441,7 @@
for (it = mLogElements.end(); it != mLogElements.begin(); /* do nothing */) {
--it;
LogBufferElement *element = *it;
- if (element->getMonotonicTime() <= start) {
+ if (element->getSequence() <= start) {
it++;
break;
}
@@ -469,13 +455,19 @@
continue;
}
- if (element->getMonotonicTime() <= start) {
+ if (element->getSequence() <= start) {
continue;
}
// NB: calling out to another object with mLogElementsLock held (safe)
- if (filter && !(*filter)(element, arg)) {
- continue;
+ if (filter) {
+ int ret = (*filter)(element, arg);
+ if (ret == false) {
+ continue;
+ }
+ if (ret != true) {
+ break;
+ }
}
pthread_mutex_unlock(&mLogElementsLock);
@@ -495,7 +487,7 @@
}
void LogBuffer::formatStatistics(char **strp, uid_t uid, unsigned int logMask) {
- log_time oldest(CLOCK_MONOTONIC);
+ uint64_t oldest = UINT64_MAX;
pthread_mutex_lock(&mLogElementsLock);
@@ -505,7 +497,7 @@
LogBufferElement *element = *it;
if ((logMask & (1 << element->getLogId()))) {
- oldest = element->getMonotonicTime();
+ oldest = element->getSequence();
break;
}
}
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index 879baea..13e6aa8 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -37,7 +37,6 @@
pthread_mutex_t mLogElementsLock;
LogStatistics stats;
- bool dgramQlenStatistics;
PruneList mPrune;
@@ -47,13 +46,14 @@
LastLogTimes &mTimes;
LogBuffer(LastLogTimes *times);
+ void init();
void log(log_id_t log_id, log_time realtime,
uid_t uid, pid_t pid, pid_t tid,
const char *msg, unsigned short len);
- log_time flushTo(SocketClient *writer, const log_time start,
+ uint64_t flushTo(SocketClient *writer, const uint64_t start,
bool privileged,
- bool (*filter)(const LogBufferElement *element, void *arg) = NULL,
+ int (*filter)(const LogBufferElement *element, void *arg) = NULL,
void *arg = NULL);
void clear(log_id_t id, uid_t uid = AID_ROOT);
@@ -63,11 +63,6 @@
// *strp uses malloc, use free to release.
void formatStatistics(char **strp, uid_t uid, unsigned int logMask);
- void enableDgramQlenStatistics() {
- stats.enableDgramQlenStatistics();
- dgramQlenStatistics = true;
- }
-
void enableStatistics() {
stats.enableStatistics();
}
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index d959ceb..5e780b5 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -24,7 +24,8 @@
#include "LogBufferElement.h"
#include "LogReader.h"
-const log_time LogBufferElement::FLUSH_ERROR((uint32_t)0, (uint32_t)0);
+const uint64_t LogBufferElement::FLUSH_ERROR(0);
+atomic_int_fast64_t LogBufferElement::sequence;
LogBufferElement::LogBufferElement(log_id_t log_id, log_time realtime,
uid_t uid, pid_t pid, pid_t tid,
@@ -34,7 +35,7 @@
, mPid(pid)
, mTid(tid)
, mMsgLen(len)
- , mMonotonicTime(CLOCK_MONOTONIC)
+ , mSequence(sequence.fetch_add(1, memory_order_relaxed))
, mRealTime(realtime) {
mMsg = new char[len];
memcpy(mMsg, msg, len);
@@ -44,7 +45,7 @@
delete [] mMsg;
}
-log_time LogBufferElement::flushTo(SocketClient *reader) {
+uint64_t LogBufferElement::flushTo(SocketClient *reader) {
struct logger_entry_v3 entry;
memset(&entry, 0, sizeof(struct logger_entry_v3));
entry.hdr_size = sizeof(struct logger_entry_v3);
@@ -64,5 +65,5 @@
return FLUSH_ERROR;
}
- return mMonotonicTime;
+ return mSequence;
}
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index fdca973..25f1450 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -18,6 +18,7 @@
#define _LOGD_LOG_BUFFER_ELEMENT_H__
#include <sys/types.h>
+#include <stdatomic.h>
#include <sysutils/SocketClient.h>
#include <log/log.h>
#include <log/log_read.h>
@@ -29,8 +30,9 @@
const pid_t mTid;
char *mMsg;
const unsigned short mMsgLen;
- const log_time mMonotonicTime;
+ const uint64_t mSequence;
const log_time mRealTime;
+ static atomic_int_fast64_t sequence;
public:
LogBufferElement(log_id_t log_id, log_time realtime,
@@ -43,11 +45,12 @@
pid_t getPid(void) const { return mPid; }
pid_t getTid(void) const { return mTid; }
unsigned short getMsgLen() const { return mMsgLen; }
- log_time getMonotonicTime(void) const { return mMonotonicTime; }
+ uint64_t getSequence(void) const { return mSequence; }
+ static uint64_t getCurrentSequence(void) { return sequence.load(memory_order_relaxed); }
log_time getRealTime(void) const { return mRealTime; }
- static const log_time FLUSH_ERROR;
- log_time flushTo(SocketClient *writer);
+ static const uint64_t FLUSH_ERROR;
+ uint64_t flushTo(SocketClient *writer);
};
#endif
diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp
index 26df087..f7df275 100644
--- a/logd/LogReader.cpp
+++ b/logd/LogReader.cpp
@@ -100,50 +100,51 @@
nonBlock = true;
}
- // Convert realtime to monotonic time
- if (start == log_time::EPOCH) {
- start = LogTimeEntry::EPOCH;
- } else {
+ uint64_t sequence = 1;
+ // Convert realtime to sequence number
+ if (start != log_time::EPOCH) {
class LogFindStart {
const pid_t mPid;
const unsigned mLogMask;
bool startTimeSet;
log_time &start;
- log_time last;
+ uint64_t &sequence;
+ uint64_t last;
public:
- LogFindStart(unsigned logMask, pid_t pid, log_time &start)
+ LogFindStart(unsigned logMask, pid_t pid, log_time &start, uint64_t &sequence)
: mPid(pid)
, mLogMask(logMask)
, startTimeSet(false)
, start(start)
- , last(LogTimeEntry::EPOCH)
+ , sequence(sequence)
+ , last(sequence)
{ }
- static bool callback(const LogBufferElement *element, void *obj) {
+ static int callback(const LogBufferElement *element, void *obj) {
LogFindStart *me = reinterpret_cast<LogFindStart *>(obj);
- if (!me->startTimeSet
- && (!me->mPid || (me->mPid == element->getPid()))
+ if ((!me->mPid || (me->mPid == element->getPid()))
&& (me->mLogMask & (1 << element->getLogId()))) {
if (me->start == element->getRealTime()) {
- me->start = element->getMonotonicTime();
+ me->sequence = element->getSequence();
me->startTimeSet = true;
+ return -1;
} else {
if (me->start < element->getRealTime()) {
- me->start = me->last;
+ me->sequence = me->last;
me->startTimeSet = true;
+ return -1;
}
- me->last = element->getMonotonicTime();
+ me->last = element->getSequence();
}
}
return false;
}
bool found() { return startTimeSet; }
- } logFindStart(logMask, pid, start);
+ } logFindStart(logMask, pid, start, sequence);
- logbuf().flushTo(cli, LogTimeEntry::EPOCH,
- FlushCommand::hasReadLogs(cli),
+ logbuf().flushTo(cli, sequence, FlushCommand::hasReadLogs(cli),
logFindStart.callback, &logFindStart);
if (!logFindStart.found()) {
@@ -151,12 +152,11 @@
doSocketDelete(cli);
return false;
}
- log_time now(CLOCK_MONOTONIC);
- start = now;
+ sequence = LogBufferElement::getCurrentSequence();
}
}
- FlushCommand command(*this, nonBlock, tail, logMask, pid, start);
+ FlushCommand command(*this, nonBlock, tail, logMask, pid, sequence);
command.runSocketCommand(cli);
return true;
}
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index 53036e6..5a70689 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -395,71 +395,11 @@
LogStatistics::LogStatistics()
: mStatistics(false)
- , dgramQlenStatistics(false)
, start(CLOCK_MONOTONIC) {
log_id_for_each(i) {
mSizes[i] = 0;
mElements[i] = 0;
}
-
- for(unsigned short bucket = 0; dgramQlen(bucket); ++bucket) {
- mMinimum[bucket].tv_sec = mMinimum[bucket].tv_sec_max;
- mMinimum[bucket].tv_nsec = mMinimum[bucket].tv_nsec_max;
- }
-}
-
-// Each bucket below represents a dgramQlen of log messages. By
-// finding the minimum period of time from start to finish
-// of each dgramQlen, we can get a performance expectation for
-// the user space logger. The net result is that the period
-// of time divided by the dgramQlen will give us the average time
-// between log messages; at the point where the average time
-// is greater than the throughput capability of the logger
-// we will not longer require the benefits of the FIFO formed
-// by max_dgram_qlen. We will also expect to see a very visible
-// knee in the average time between log messages at this point,
-// so we do not necessarily have to compare the rate against the
-// measured performance (BM_log_maximum_retry) of the logger.
-//
-// for example (reformatted):
-//
-// Minimum time between log events per dgramQlen:
-// 1 2 3 5 10 20 30 50 100 200 300 400 500 600
-// 5u2 12u 13u 15u 16u 27u 30u 36u 407u 3m1 3m3 3m9 3m9 5m5
-//
-// demonstrates a clear knee rising at 100, so this means that for this
-// case max_dgram_qlen = 100 would be more than sufficient to handle the
-// worst that the system could stuff into the logger. The
-// BM_log_maximum_retry performance (derated by the log collection) on the
-// same system was 33.2us so we would almost be fine with max_dgram_qlen = 50.
-// BM_log_maxumum_retry with statistics off is roughly 20us, so
-// max_dgram_qlen = 20 would work. We will be more than willing to have
-// a large engineering margin so the rule of thumb that lead us to 100 is
-// fine.
-//
-// bucket dgramQlen are tuned for /proc/sys/net/unix/max_dgram_qlen = 300
-const unsigned short LogStatistics::mBuckets[] = {
- 1, 2, 3, 5, 10, 20, 30, 50, 100, 200, 300, 400, 500, 600
-};
-
-unsigned short LogStatistics::dgramQlen(unsigned short bucket) {
- if (bucket >= sizeof(mBuckets) / sizeof(mBuckets[0])) {
- return 0;
- }
- return mBuckets[bucket];
-}
-
-unsigned long long LogStatistics::minimum(unsigned short bucket) {
- if (mMinimum[bucket].tv_sec == mMinimum[bucket].tv_sec_max) {
- return 0;
- }
- return mMinimum[bucket].nsec();
-}
-
-void LogStatistics::recordDiff(log_time diff, unsigned short bucket) {
- if ((diff.tv_sec || diff.tv_nsec) && (mMinimum[bucket] > diff)) {
- mMinimum[bucket] = diff;
- }
}
void LogStatistics::add(unsigned short size,
@@ -709,55 +649,6 @@
pids.clear();
}
- if (dgramQlenStatistics) {
- const unsigned short spaces_time = 6;
- const unsigned long long max_seconds = 100000;
- spaces = 0;
- string.append("\n\nMinimum time between log events per max_dgram_qlen:\n");
- for(unsigned short i = 0; dgramQlen(i); ++i) {
- oldLength = string.length();
- if (spaces < 0) {
- spaces = 0;
- }
- string.appendFormat("%*s%u", spaces, "", dgramQlen(i));
- spaces += spaces_time + oldLength - string.length();
- }
- string.append("\n");
- spaces = 0;
- unsigned short n;
- for(unsigned short i = 0; (n = dgramQlen(i)); ++i) {
- unsigned long long duration = minimum(i);
- if (duration) {
- duration /= n;
- if (duration >= (NS_PER_SEC * max_seconds)) {
- duration = NS_PER_SEC * (max_seconds - 1);
- }
- oldLength = string.length();
- if (spaces < 0) {
- spaces = 0;
- }
- string.appendFormat("%*s", spaces, "");
- if (duration >= (NS_PER_SEC * 10)) {
- string.appendFormat("%llu",
- (duration + (NS_PER_SEC / 2))
- / NS_PER_SEC);
- } else if (duration >= (NS_PER_SEC / (1000 / 10))) {
- string.appendFormat("%llum",
- (duration + (NS_PER_SEC / 2 / 1000))
- / (NS_PER_SEC / 1000));
- } else if (duration >= (NS_PER_SEC / (1000000 / 10))) {
- string.appendFormat("%lluu",
- (duration + (NS_PER_SEC / 2 / 1000000))
- / (NS_PER_SEC / 1000000));
- } else {
- string.appendFormat("%llun", duration);
- }
- spaces -= string.length() - oldLength;
- }
- spaces += spaces_time;
- }
- }
-
log_id_for_each(i) {
if (!(logMask & (1 << i))) {
continue;
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index f6c4329..f892cd0 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -145,7 +145,6 @@
size_t mElements[LOG_ID_MAX];
bool mStatistics;
- bool dgramQlenStatistics;
static const unsigned short mBuckets[14];
log_time mMinimum[sizeof(mBuckets) / sizeof(mBuckets[0])];
@@ -157,11 +156,7 @@
LidStatistics &id(log_id_t log_id) { return LogIds[log_id]; }
- void enableDgramQlenStatistics() { dgramQlenStatistics = true; }
void enableStatistics() { mStatistics = true; }
- static unsigned short dgramQlen(unsigned short bucket);
- unsigned long long minimum(unsigned short bucket);
- void recordDiff(log_time diff, unsigned short bucket);
void add(unsigned short size, log_id_t log_id, uid_t uid, pid_t pid);
void subtract(unsigned short size, log_id_t log_id, uid_t uid, pid_t pid);
diff --git a/logd/LogTimes.cpp b/logd/LogTimes.cpp
index 5f9db8d..1b60b7e 100644
--- a/logd/LogTimes.cpp
+++ b/logd/LogTimes.cpp
@@ -23,12 +23,10 @@
pthread_mutex_t LogTimeEntry::timesLock = PTHREAD_MUTEX_INITIALIZER;
-const struct timespec LogTimeEntry::EPOCH = { 0, 1 };
-
LogTimeEntry::LogTimeEntry(LogReader &reader, SocketClient *client,
bool nonBlock, unsigned long tail,
unsigned int logMask, pid_t pid,
- log_time start)
+ uint64_t start)
: mRefCount(1)
, mRelease(false)
, mError(false)
@@ -42,7 +40,7 @@
, mClient(client)
, mStart(start)
, mNonBlock(nonBlock)
- , mEnd(CLOCK_MONOTONIC)
+ , mEnd(LogBufferElement::getCurrentSequence())
{
pthread_cond_init(&threadTriggeredCondition, NULL);
cleanSkip_Locked();
@@ -129,7 +127,7 @@
lock();
while (me->threadRunning && !me->isError_Locked()) {
- log_time start = me->mStart;
+ uint64_t start = me->mStart;
unlock();
@@ -161,13 +159,13 @@
}
// A first pass to count the number of elements
-bool LogTimeEntry::FilterFirstPass(const LogBufferElement *element, void *obj) {
+int LogTimeEntry::FilterFirstPass(const LogBufferElement *element, void *obj) {
LogTimeEntry *me = reinterpret_cast<LogTimeEntry *>(obj);
LogTimeEntry::lock();
if (me->mCount == 0) {
- me->mStart = element->getMonotonicTime();
+ me->mStart = element->getSequence();
}
if ((!me->mPid || (me->mPid == element->getPid()))
@@ -181,12 +179,12 @@
}
// A second pass to send the selected elements
-bool LogTimeEntry::FilterSecondPass(const LogBufferElement *element, void *obj) {
+int LogTimeEntry::FilterSecondPass(const LogBufferElement *element, void *obj) {
LogTimeEntry *me = reinterpret_cast<LogTimeEntry *>(obj);
LogTimeEntry::lock();
- me->mStart = element->getMonotonicTime();
+ me->mStart = element->getSequence();
if (me->skipAhead[element->getLogId()]) {
me->skipAhead[element->getLogId()]--;
@@ -195,7 +193,7 @@
// Truncate to close race between first and second pass
if (me->mNonBlock && me->mTail && (me->mIndex >= me->mCount)) {
- goto skip;
+ goto stop;
}
if (!me->isWatching(element->getLogId())) {
@@ -207,7 +205,7 @@
}
if (me->isError_Locked()) {
- goto skip;
+ goto stop;
}
if (!me->mTail) {
@@ -234,6 +232,10 @@
skip:
LogTimeEntry::unlock();
return false;
+
+stop:
+ LogTimeEntry::unlock();
+ return -1;
}
void LogTimeEntry::cleanSkip_Locked(void) {
diff --git a/logd/LogTimes.h b/logd/LogTimes.h
index 81aedfb..ae2f92b 100644
--- a/logd/LogTimes.h
+++ b/logd/LogTimes.h
@@ -47,13 +47,12 @@
public:
LogTimeEntry(LogReader &reader, SocketClient *client, bool nonBlock,
unsigned long tail, unsigned int logMask, pid_t pid,
- log_time start);
+ uint64_t start);
SocketClient *mClient;
- static const struct timespec EPOCH;
- log_time mStart;
+ uint64_t mStart;
const bool mNonBlock;
- const log_time mEnd; // only relevant if mNonBlock
+ const uint64_t mEnd; // only relevant if mNonBlock
// Protect List manipulations
static void lock(void) { pthread_mutex_lock(×Lock); }
@@ -103,8 +102,8 @@
}
bool isWatching(log_id_t id) { return (mLogMask & (1<<id)) != 0; }
// flushTo filter callbacks
- static bool FilterFirstPass(const LogBufferElement *element, void *me);
- static bool FilterSecondPass(const LogBufferElement *element, void *me);
+ static int FilterFirstPass(const LogBufferElement *element, void *me);
+ static int FilterSecondPass(const LogBufferElement *element, void *me);
};
typedef android::List<LogTimeEntry *> LastLogTimes;
diff --git a/logd/README.property b/logd/README.property
index b7fcece..60542b2 100644
--- a/logd/README.property
+++ b/logd/README.property
@@ -7,12 +7,6 @@
logd.statistics bool depends Enable logcat -S statistics.
ro.config.low_ram bool false if true, logd.statistics default false
ro.build.type string if user, logd.statistics default false
-logd.statistics.dgram_qlen bool false Record dgram_qlen statistics. This
- represents a performance impact and
- is used to determine the platform's
- minimum domain socket network FIFO
- size (see source for details) based
- on typical load (logcat -S to view)
persist.logd.size number 256K default size of the buffer for all
log ids at initial startup, at runtime
use: logcat -b all -G <value>
diff --git a/logd/main.cpp b/logd/main.cpp
index 7a1ae54..a61beff 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -17,7 +17,10 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <poll.h>
#include <sched.h>
+#include <semaphore.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -26,10 +29,12 @@
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <syslog.h>
#include <unistd.h>
#include <cutils/properties.h>
#include <cutils/sched_policy.h>
+#include <cutils/sockets.h>
#include "private/android_filesystem_config.h"
#include "CommandListener.h"
@@ -37,6 +42,12 @@
#include "LogListener.h"
#include "LogAudit.h"
+#define KMSG_PRIORITY(PRI) \
+ '<', \
+ '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) / 10, \
+ '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) % 10, \
+ '>'
+
//
// The service is designed to be run by init, it does not respond well
// to starting up manually. When starting up manually the sockets will
@@ -127,17 +138,107 @@
return def;
}
-// Foreground waits for exit of the three main persistent threads that
-// are started here. The three threads are created to manage UNIX
-// domain client sockets for writing, reading and controlling the user
-// space logger. Additional transitory per-client threads are created
-// for each reader once they register.
-int main() {
- bool auditd = property_get_bool("logd.auditd", true);
+// Remove the static, and use this variable
+// globally for debugging if necessary. eg:
+// write(fdDmesg, "I am here\n", 10);
+static int fdDmesg = -1;
- int fdDmesg = -1;
- if (auditd && property_get_bool("logd.auditd.dmesg", true)) {
- fdDmesg = open("/dev/kmsg", O_WRONLY);
+static sem_t reinit;
+static bool reinit_running = false;
+static LogBuffer *logBuf = NULL;
+
+static void *reinit_thread_start(void * /*obj*/) {
+ prctl(PR_SET_NAME, "logd.daemon");
+ set_sched_policy(0, SP_BACKGROUND);
+
+ setgid(AID_LOGD);
+ setuid(AID_LOGD);
+
+ while (reinit_running && !sem_wait(&reinit) && reinit_running) {
+ if (fdDmesg >= 0) {
+ static const char reinit_message[] = { KMSG_PRIORITY(LOG_INFO),
+ 'l', 'o', 'g', 'd', '.', 'd', 'a', 'e', 'm', 'o', 'n', ':',
+ ' ', 'r', 'e', 'i', 'n', 'i', 't', '\n' };
+ write(fdDmesg, reinit_message, sizeof(reinit_message));
+ }
+
+ // Anything that reads persist.<property>
+ if (logBuf) {
+ logBuf->init();
+ }
+ }
+
+ return NULL;
+}
+
+// Serves as a global method to trigger reinitialization
+// and as a function that can be provided to signal().
+void reinit_signal_handler(int /*signal*/) {
+ sem_post(&reinit);
+}
+
+// Foreground waits for exit of the main persistent threads
+// that are started here. The threads are created to manage
+// UNIX domain client sockets for writing, reading and
+// controlling the user space logger, and for any additional
+// logging plugins like auditd and restart control. Additional
+// transitory per-client threads are created for each reader.
+int main(int argc, char *argv[]) {
+ fdDmesg = open("/dev/kmsg", O_WRONLY);
+
+ // issue reinit command. KISS argument parsing.
+ if ((argc > 1) && argv[1] && !strcmp(argv[1], "--reinit")) {
+ int sock = TEMP_FAILURE_RETRY(
+ socket_local_client("logd",
+ ANDROID_SOCKET_NAMESPACE_RESERVED,
+ SOCK_STREAM));
+ if (sock < 0) {
+ return -errno;
+ }
+ static const char reinit[] = "reinit";
+ ssize_t ret = TEMP_FAILURE_RETRY(write(sock, reinit, sizeof(reinit)));
+ if (ret < 0) {
+ return -errno;
+ }
+ struct pollfd p;
+ memset(&p, 0, sizeof(p));
+ p.fd = sock;
+ p.events = POLLIN;
+ ret = TEMP_FAILURE_RETRY(poll(&p, 1, 100));
+ if (ret < 0) {
+ return -errno;
+ }
+ if ((ret == 0) || !(p.revents & POLLIN)) {
+ return -ETIME;
+ }
+ static const char success[] = "success";
+ char buffer[sizeof(success) - 1];
+ memset(buffer, 0, sizeof(buffer));
+ ret = TEMP_FAILURE_RETRY(read(sock, buffer, sizeof(buffer)));
+ if (ret < 0) {
+ return -errno;
+ }
+ return strncmp(buffer, success, sizeof(success) - 1) != 0;
+ }
+
+ // Reinit Thread
+ sem_init(&reinit, 0, 0);
+ pthread_attr_t attr;
+ if (!pthread_attr_init(&attr)) {
+ struct sched_param param;
+
+ memset(¶m, 0, sizeof(param));
+ pthread_attr_setschedparam(&attr, ¶m);
+ pthread_attr_setschedpolicy(&attr, SCHED_BATCH);
+ if (!pthread_attr_setdetachstate(&attr,
+ PTHREAD_CREATE_DETACHED)) {
+ pthread_t thread;
+ reinit_running = true;
+ if (pthread_create(&thread, &attr, reinit_thread_start, NULL)) {
+ reinit_running = false;
+ }
+ }
+ pthread_attr_destroy(&attr);
}
if (drop_privs() != 0) {
@@ -153,11 +254,10 @@
// LogBuffer is the object which is responsible for holding all
// log entries.
- LogBuffer *logBuf = new LogBuffer(times);
+ logBuf = new LogBuffer(times);
- if (property_get_bool("logd.statistics.dgram_qlen", false)) {
- logBuf->enableDgramQlenStatistics();
- }
+ signal(SIGHUP, reinit_signal_handler);
+
{
char property[PROPERTY_VALUE_MAX];
property_get("ro.build.type", property, "");
@@ -198,9 +298,13 @@
// initiated log messages. New log entries are added to LogBuffer
// and LogReader is notified to send updates to connected clients.
+ bool auditd = property_get_bool("logd.auditd", true);
+
if (auditd) {
+ bool dmesg = property_get_bool("logd.auditd.dmesg", true);
+
// failure is an option ... messages are in dmesg (required by standard)
- LogAudit *al = new LogAudit(logBuf, reader, fdDmesg);
+ LogAudit *al = new LogAudit(logBuf, reader, dmesg ? fdDmesg : -1);
int len = klogctl(KLOG_SIZE_BUFFER, NULL, 0);
if (len > 0) {
@@ -220,11 +324,10 @@
if (al->startListener()) {
delete al;
- close(fdDmesg);
}
}
- pause();
+ TEMP_FAILURE_RETRY(pause());
+
exit(0);
}
-
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 96877a9..46bd9c0 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -192,164 +192,6 @@
EXPECT_TRUE(NULL != events_logs);
#endif
- // Parse timing stats
-
- cp = strstr(cp, "Minimum time between log events per dgram_qlen:");
-
- if (cp) {
- while (*cp && (*cp != '\n')) {
- ++cp;
- }
- if (*cp == '\n') {
- ++cp;
- }
-
- char *list_of_spans = cp;
- EXPECT_NE('\0', *list_of_spans);
-
- unsigned short number_of_buckets = 0;
- unsigned short *dgram_qlen = NULL;
- unsigned short bucket = 0;
- while (*cp && (*cp != '\n')) {
- bucket = 0;
- while (isdigit(*cp)) {
- bucket = bucket * 10 + *cp - '0';
- ++cp;
- }
- while (*cp == ' ') {
- ++cp;
- }
- if (!bucket) {
- break;
- }
- unsigned short *new_dgram_qlen = new unsigned short[number_of_buckets + 1];
- EXPECT_TRUE(new_dgram_qlen != NULL);
- if (dgram_qlen) {
- memcpy(new_dgram_qlen, dgram_qlen, sizeof(*dgram_qlen) * number_of_buckets);
- delete [] dgram_qlen;
- }
-
- dgram_qlen = new_dgram_qlen;
- dgram_qlen[number_of_buckets++] = bucket;
- }
-
- char *end_of_spans = cp;
- EXPECT_NE('\0', *end_of_spans);
-
- EXPECT_LT(5, number_of_buckets);
-
- unsigned long long *times = new unsigned long long [number_of_buckets];
- ASSERT_TRUE(times != NULL);
-
- memset(times, 0, sizeof(*times) * number_of_buckets);
-
- while (*cp == '\n') {
- ++cp;
- }
-
- unsigned short number_of_values = 0;
- unsigned long long value;
- while (*cp && (*cp != '\n')) {
- EXPECT_GE(number_of_buckets, number_of_values);
-
- value = 0;
- while (isdigit(*cp)) {
- value = value * 10ULL + *cp - '0';
- ++cp;
- }
-
- switch(*cp) {
- case ' ':
- case '\n':
- value *= 1000ULL;
- /* FALLTHRU */
- case 'm':
- value *= 1000ULL;
- /* FALLTHRU */
- case 'u':
- value *= 1000ULL;
- /* FALLTHRU */
- case 'n':
- default:
- break;
- }
- while (*++cp == ' ');
-
- if (!value) {
- break;
- }
-
- times[number_of_values] = value;
- ++number_of_values;
- }
-
-#ifdef TARGET_USES_LOGD
- EXPECT_EQ(number_of_values, number_of_buckets);
-#endif
-
- FILE *fp;
- ASSERT_TRUE(NULL != (fp = fopen("/proc/sys/net/unix/max_dgram_qlen", "r")));
-
- unsigned max_dgram_qlen = 0;
- fscanf(fp, "%u", &max_dgram_qlen);
-
- fclose(fp);
-
- // Find launch point
- unsigned short launch = 0;
- unsigned long long total = 0;
- do {
- total += times[launch];
- } while (((++launch < number_of_buckets)
- && ((total / launch) >= (times[launch] / 8ULL)))
- || (launch == 1)); // too soon
-
- bool failure = number_of_buckets <= launch;
- if (!failure) {
- unsigned short l = launch;
- if (l >= number_of_buckets) {
- l = number_of_buckets - 1;
- }
- failure = max_dgram_qlen < dgram_qlen[l];
- }
-
- // We can get failure if at any time liblog_benchmarks has been run
- // because designed to overload /proc/sys/net/unix/max_dgram_qlen even
- // at excessive values like 20000. It does so to measure the raw processing
- // performance of logd.
- if (failure) {
- cp = find_benchmark_spam(cp);
- }
-
- if (cp) {
- // Fake a failure, but without the failure code
- if (number_of_buckets <= launch) {
- printf ("Expected: number_of_buckets > launch, actual: %u vs %u\n",
- number_of_buckets, launch);
- }
- if (launch >= number_of_buckets) {
- launch = number_of_buckets - 1;
- }
- if (max_dgram_qlen < dgram_qlen[launch]) {
- printf ("Expected: max_dgram_qlen >= dgram_qlen[%d],"
- " actual: %u vs %u\n",
- launch, max_dgram_qlen, dgram_qlen[launch]);
- }
- } else
-#ifndef TARGET_USES_LOGD
- if (total)
-#endif
- {
- EXPECT_GT(number_of_buckets, launch);
- if (launch >= number_of_buckets) {
- launch = number_of_buckets - 1;
- }
- EXPECT_GE(max_dgram_qlen, dgram_qlen[launch]);
- }
-
- delete [] dgram_qlen;
- delete [] times;
- }
delete [] buf;
}
diff --git a/netcfg/Android.mk b/netcfg/Android.mk
deleted file mode 100644
index 4796c11..0000000
--- a/netcfg/Android.mk
+++ /dev/null
@@ -1,8 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= netcfg.c
-LOCAL_MODULE:= netcfg
-LOCAL_SHARED_LIBRARIES := libnetutils
-LOCAL_CFLAGS := -Werror
-include $(BUILD_EXECUTABLE)
diff --git a/netcfg/MODULE_LICENSE_APACHE2 b/netcfg/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/netcfg/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/netcfg/NOTICE b/netcfg/NOTICE
deleted file mode 100644
index c5b1efa..0000000
--- a/netcfg/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
- Copyright (c) 2005-2008, The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
-
- 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.
-
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
diff --git a/netcfg/netcfg.c b/netcfg/netcfg.c
deleted file mode 100644
index eec1b2f..0000000
--- a/netcfg/netcfg.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include <errno.h>
-#include <dirent.h>
-#include <netinet/ether.h>
-#include <netinet/if_ether.h>
-#include <netutils/dhcp.h>
-#include <netutils/ifc.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-static const char *ipaddr(in_addr_t addr)
-{
- struct in_addr in_addr;
-
- in_addr.s_addr = addr;
- return inet_ntoa(in_addr);
-}
-
-static void usage(void)
-{
- fprintf(stderr,"usage: netcfg [<interface> dhcp]\n");
- exit(1);
-}
-
-static int dump_interface(const char *name)
-{
- unsigned addr, flags;
- unsigned char hwbuf[ETH_ALEN];
- int prefixLength;
-
- if(ifc_get_info(name, &addr, &prefixLength, &flags)) {
- return 0;
- }
-
- printf("%-8s %s ", name, flags & 1 ? "UP " : "DOWN");
- printf("%40s", ipaddr(addr));
- printf("/%-4d", prefixLength);
- printf("0x%08x ", flags);
- if (!ifc_get_hwaddr(name, hwbuf)) {
- int i;
- for(i=0; i < (ETH_ALEN-1); i++)
- printf("%02x:", hwbuf[i]);
- printf("%02x\n", hwbuf[i]);
- } else {
- printf("\n");
- }
- return 0;
-}
-
-static int dump_interfaces(void)
-{
- DIR *d;
- struct dirent *de;
-
- d = opendir("/sys/class/net");
- if(d == 0) return -1;
-
- while((de = readdir(d))) {
- if(de->d_name[0] == '.') continue;
- dump_interface(de->d_name);
- }
- closedir(d);
- return 0;
-}
-
-int main(int argc, char **argv)
-{
- if(ifc_init()) {
- perror("Cannot perform requested operation");
- exit(1);
- }
-
- if(argc == 1) {
- int result = dump_interfaces();
- ifc_close();
- return result;
- }
-
- if(argc != 3) usage();
-
- char* iname = argv[1];
- char* action = argv[2];
- if(strlen(iname) > 16) usage();
-
- if (!strcmp(action, "dhcp")) {
- if (do_dhcp(iname)) {
- fprintf(stderr, "dhcp failed: %s\n", strerror(errno));
- ifc_close();
- exit(1);
- }
- } else {
- fprintf(stderr,"no such action '%s'\n", action);
- usage();
- }
-
- ifc_close();
- return 0;
-}
diff --git a/rootdir/init.environ.rc.in b/rootdir/init.environ.rc.in
index 30bef46..0064790 100644
--- a/rootdir/init.environ.rc.in
+++ b/rootdir/init.environ.rc.in
@@ -1,6 +1,5 @@
# set up the global environment
on init
- export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin
export ANDROID_BOOTLOGO 1
export ANDROID_ROOT /system
export ANDROID_ASSETS /system/app
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 0452f75..bc36c3e 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -118,25 +118,18 @@
mount cgroup none /dev/cpuctl cpu
chown system system /dev/cpuctl
chown system system /dev/cpuctl/tasks
- chmod 0660 /dev/cpuctl/tasks
+ chmod 0666 /dev/cpuctl/tasks
write /dev/cpuctl/cpu.shares 1024
- write /dev/cpuctl/cpu.rt_runtime_us 950000
+ write /dev/cpuctl/cpu.rt_runtime_us 800000
write /dev/cpuctl/cpu.rt_period_us 1000000
- mkdir /dev/cpuctl/apps
- chown system system /dev/cpuctl/apps/tasks
- chmod 0666 /dev/cpuctl/apps/tasks
- write /dev/cpuctl/apps/cpu.shares 1024
- write /dev/cpuctl/apps/cpu.rt_runtime_us 800000
- write /dev/cpuctl/apps/cpu.rt_period_us 1000000
-
- mkdir /dev/cpuctl/apps/bg_non_interactive
- chown system system /dev/cpuctl/apps/bg_non_interactive/tasks
- chmod 0666 /dev/cpuctl/apps/bg_non_interactive/tasks
+ mkdir /dev/cpuctl/bg_non_interactive
+ chown system system /dev/cpuctl/bg_non_interactive/tasks
+ chmod 0666 /dev/cpuctl/bg_non_interactive/tasks
# 5.0 %
- write /dev/cpuctl/apps/bg_non_interactive/cpu.shares 52
- write /dev/cpuctl/apps/bg_non_interactive/cpu.rt_runtime_us 700000
- write /dev/cpuctl/apps/bg_non_interactive/cpu.rt_period_us 1000000
+ write /dev/cpuctl/bg_non_interactive/cpu.shares 52
+ write /dev/cpuctl/bg_non_interactive/cpu.rt_runtime_us 700000
+ write /dev/cpuctl/bg_non_interactive/cpu.rt_period_us 1000000
# qtaguid will limit access to specific data based on group memberships.
# net_bw_acct grants impersonation of socket owners.
@@ -171,6 +164,7 @@
# Load properties from /system/ + /factory after fs mount.
on load_all_props_action
load_all_props
+ start logd-reinit
# Indicate to fw loaders that the relevant mounts are up.
on firmware_mounts_complete
@@ -247,22 +241,6 @@
# Avoid predictable entropy pool. Carry over entropy from previous boot.
copy /data/system/entropy.dat /dev/urandom
- # Create dump dir and collect dumps.
- # Do this before we mount cache so eventually we can use cache for
- # storing dumps on platforms which do not have a dedicated dump partition.
- mkdir /data/dontpanic 0750 root log
-
- # Collect apanic data, free resources and re-arm trigger
- copy /proc/apanic_console /data/dontpanic/apanic_console
- chown root log /data/dontpanic/apanic_console
- chmod 0640 /data/dontpanic/apanic_console
-
- copy /proc/apanic_threads /data/dontpanic/apanic_threads
- chown root log /data/dontpanic/apanic_threads
- chmod 0640 /data/dontpanic/apanic_threads
-
- write /proc/apanic_console 1
-
# create basic filesystem structure
mkdir /data/misc 01771 system misc
mkdir /data/misc/adb 02750 system shell
@@ -453,6 +431,7 @@
on property:vold.decrypt=trigger_load_persist_props
load_persist_props
+ start logd-reinit
on property:vold.decrypt=trigger_post_fs_data
trigger post-fs-data
@@ -495,6 +474,10 @@
socket logdr seqpacket 0666 logd logd
socket logdw dgram 0222 logd logd
+service logd-reinit /system/bin/logd --reinit
+ oneshot
+ disabled
+
service healthd /sbin/healthd
class core
critical
@@ -588,7 +571,7 @@
# encryption) or trigger_restart_min_framework (other encryption)
# One shot invocation to encrypt unencrypted volumes
-service encrypt /system/bin/vdc --wait cryptfs maybeenabledefaultcrypto
+service encrypt /system/bin/vdc --wait cryptfs enablecrypto inplace default
disabled
oneshot
# vold will set vold.decrypt to trigger_restart_framework (default
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index 43d7bc9..9cf9ed9 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -89,6 +89,7 @@
/dev/ppp 0660 radio vpn
# sysfs properties
+/sys/devices/platform/trusty.* trusty_version 0440 root log
/sys/devices/virtual/input/input* enable 0660 root input
/sys/devices/virtual/input/input* poll_delay 0660 root input
/sys/devices/virtual/usb_composite/* enable 0664 root system
diff --git a/sdcard/Android.mk b/sdcard/Android.mk
index 63b0f41..cb3a8fb 100644
--- a/sdcard/Android.mk
+++ b/sdcard/Android.mk
@@ -6,6 +6,6 @@
LOCAL_MODULE := sdcard
LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror
-LOCAL_SHARED_LIBRARIES := libc libcutils
+LOCAL_SHARED_LIBRARIES := libcutils
include $(BUILD_EXECUTABLE)
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 05b83a2..b822ea0 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -44,7 +44,6 @@
df \
getevent \
getprop \
- getsebool \
iftop \
ioctl \
ionice \
@@ -56,6 +55,7 @@
nandread \
newfs_msdos \
ps \
+ prlimit \
renice \
restorecon \
route \
@@ -63,15 +63,12 @@
schedtop \
sendevent \
setprop \
- setsebool \
- smd \
start \
stop \
top \
umount \
uptime \
watchprops \
- wipe \
ALL_TOOLS = $(BSD_TOOLS) $(OUR_TOOLS)
diff --git a/toolbox/getsebool.c b/toolbox/getsebool.c
deleted file mode 100644
index aab5200..0000000
--- a/toolbox/getsebool.c
+++ /dev/null
@@ -1,104 +0,0 @@
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <getopt.h>
-#include <errno.h>
-#include <string.h>
-#include <selinux/selinux.h>
-
-static void usage(const char *progname)
-{
- fprintf(stderr, "usage: %s -a or %s boolean...\n", progname, progname);
- exit(1);
-}
-
-int getsebool_main(int argc, char **argv)
-{
- int i, get_all = 0, rc = 0, active, pending, len = 0, opt;
- char **names;
-
- while ((opt = getopt(argc, argv, "a")) > 0) {
- switch (opt) {
- case 'a':
- if (argc > 2)
- usage(argv[0]);
- if (is_selinux_enabled() <= 0) {
- fprintf(stderr, "%s: SELinux is disabled\n",
- argv[0]);
- return 1;
- }
- errno = 0;
- rc = security_get_boolean_names(&names, &len);
- if (rc) {
- fprintf(stderr,
- "%s: Unable to get boolean names: %s\n",
- argv[0], strerror(errno));
- return 1;
- }
- if (!len) {
- printf("No booleans\n");
- return 0;
- }
- get_all = 1;
- break;
- default:
- usage(argv[0]);
- }
- }
-
- if (is_selinux_enabled() <= 0) {
- fprintf(stderr, "%s: SELinux is disabled\n", argv[0]);
- return 1;
- }
- if (!len) {
- if (argc < 2)
- usage(argv[0]);
- len = argc - 1;
- names = malloc(sizeof(char *) * len);
- if (!names) {
- fprintf(stderr, "%s: out of memory\n", argv[0]);
- return 2;
- }
- for (i = 0; i < len; i++) {
- names[i] = strdup(argv[i + 1]);
- if (!names[i]) {
- fprintf(stderr, "%s: out of memory\n",
- argv[0]);
- return 2;
- }
- }
- }
-
- for (i = 0; i < len; i++) {
- active = security_get_boolean_active(names[i]);
- if (active < 0) {
- if (get_all && errno == EACCES)
- continue;
- fprintf(stderr, "Error getting active value for %s\n",
- names[i]);
- rc = -1;
- goto out;
- }
- pending = security_get_boolean_pending(names[i]);
- if (pending < 0) {
- fprintf(stderr, "Error getting pending value for %s\n",
- names[i]);
- rc = -1;
- goto out;
- }
- if (pending != active) {
- printf("%s --> %s pending: %s\n", names[i],
- (active ? "on" : "off"),
- (pending ? "on" : "off"));
- } else {
- printf("%s --> %s\n", names[i],
- (active ? "on" : "off"));
- }
- }
-
-out:
- for (i = 0; i < len; i++)
- free(names[i]);
- free(names);
- return rc;
-}
diff --git a/toolbox/prlimit.c b/toolbox/prlimit.c
new file mode 100644
index 0000000..8cf202a
--- /dev/null
+++ b/toolbox/prlimit.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2014, The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google, Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+static void
+usage(const char *s)
+{
+ fprintf(stderr, "usage: %s pid resource cur max\n", s);
+ exit(EXIT_FAILURE);
+}
+
+int prlimit_main(int argc, char *argv[])
+{
+ pid_t pid;
+ struct rlimit64 rl;
+ int resource;
+ int rc;
+
+ if (argc != 5)
+ usage(*argv);
+
+ if (sscanf(argv[1], "%d", &pid) != 1)
+ usage(*argv);
+
+ if (sscanf(argv[2], "%d", &resource) != 1)
+ usage(*argv);
+
+ if (sscanf(argv[3], "%llu", &rl.rlim_cur) != 1)
+ usage(*argv);
+
+ if (sscanf(argv[4], "%llu", &rl.rlim_max) != 1)
+ usage(*argv);
+
+ printf("setting resource %d of pid %d to [%llu,%llu]\n", resource, pid,
+ rl.rlim_cur, rl.rlim_max);
+ rc = prlimit64(pid, resource, &rl, NULL);
+ if (rc < 0) {
+ perror("prlimit");
+ exit(EXIT_FAILURE);
+ }
+
+ return 0;
+}
diff --git a/toolbox/ps.c b/toolbox/ps.c
index d0a8db3..cf3f05a 100644
--- a/toolbox/ps.c
+++ b/toolbox/ps.c
@@ -1,6 +1,7 @@
#include <ctype.h>
#include <dirent.h>
#include <fcntl.h>
+#include <inttypes.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
@@ -29,6 +30,12 @@
#define SHOW_NUMERIC_UID 32
#define SHOW_ABI 64
+#if __LP64__
+#define PC_WIDTH 10 /* Realistically, the top bits will be 0, so don't waste space. */
+#else
+#define PC_WIDTH (2*sizeof(uintptr_t))
+#endif
+
static int display_flags = 0;
static int ppid_filter = 0;
@@ -44,7 +51,8 @@
int fd, r;
char *ptr, *name, *state;
int ppid;
- unsigned wchan, rss, vss, eip;
+ unsigned rss, vss;
+ uintptr_t eip;
unsigned utime, stime;
int prio, nice, rtprio, sched, psr;
struct passwd *pw;
@@ -124,7 +132,7 @@
nexttok(&ptr); // blocked
nexttok(&ptr); // sigignore
nexttok(&ptr); // sigcatch
- wchan = strtoul(nexttok(&ptr), 0, 10); // wchan
+ nexttok(&ptr); // wchan
nexttok(&ptr); // nswap
nexttok(&ptr); // cnswap
nexttok(&ptr); // exit signal
@@ -176,7 +184,16 @@
else
printf(" %.2s ", get_sched_policy_name(p));
}
- printf(" %08x %08x %s ", wchan, eip, state);
+ char path[PATH_MAX];
+ snprintf(path, sizeof(path), "/proc/%d/wchan", pid);
+ char wchan[10];
+ int fd = open(path, O_RDONLY);
+ ssize_t wchan_len = read(fd, wchan, sizeof(wchan));
+ if (wchan_len == -1) {
+ wchan[wchan_len = 0] = '\0';
+ }
+ close(fd);
+ printf(" %10.*s %0*" PRIxPTR " %s ", (int) wchan_len, wchan, (int) PC_WIDTH, eip, state);
if (display_flags & SHOW_ABI) {
print_exe_abi(pid);
}
@@ -285,12 +302,13 @@
}
if (display_flags & SHOW_MACLABEL) {
- printf("LABEL USER PID PPID NAME\n");
+ printf("LABEL USER PID PPID NAME\n");
} else {
- printf("USER PID PPID VSIZE RSS %s%s %s WCHAN PC %sNAME\n",
+ printf("USER PID PPID VSIZE RSS %s%s %sWCHAN %*s %sNAME\n",
(display_flags&SHOW_CPU)?"CPU ":"",
(display_flags&SHOW_PRIO)?"PRIO NICE RTPRI SCHED ":"",
(display_flags&SHOW_POLICY)?"PCY " : "",
+ (int) PC_WIDTH, "PC",
(display_flags&SHOW_ABI)?"ABI " : "");
}
while((de = readdir(d)) != 0){
diff --git a/toolbox/setsebool.c b/toolbox/setsebool.c
deleted file mode 100644
index f79a612..0000000
--- a/toolbox/setsebool.c
+++ /dev/null
@@ -1,46 +0,0 @@
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <selinux/selinux.h>
-#include <errno.h>
-
-static int do_setsebool(int nargs, char **args) {
- const char *name = args[1];
- const char *value = args[2];
- SELboolean b;
-
- if (is_selinux_enabled() <= 0)
- return 0;
-
- b.name = name;
- if (!strcmp(value, "1") || !strcasecmp(value, "true") || !strcasecmp(value, "on"))
- b.value = 1;
- else if (!strcmp(value, "0") || !strcasecmp(value, "false") || !strcasecmp(value, "off"))
- b.value = 0;
- else {
- fprintf(stderr, "setsebool: invalid value %s\n", value);
- return -1;
- }
-
- if (security_set_boolean_list(1, &b, 0) < 0)
- {
- fprintf(stderr, "setsebool: could not set %s to %s: %s", name, value, strerror(errno));
- return -1;
- }
-
- return 0;
-}
-
-int setsebool_main(int argc, char **argv)
-{
- if (argc != 3) {
- fprintf(stderr, "Usage: %s name value\n", argv[0]);
- exit(1);
- }
-
- return do_setsebool(argc, argv);
-}
diff --git a/toolbox/smd.c b/toolbox/smd.c
deleted file mode 100644
index 343dea7..0000000
--- a/toolbox/smd.c
+++ /dev/null
@@ -1,42 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-
-int smd_main(int argc, char **argv)
-{
- int fd, len, r, port = 0;
- char devname[32];
- argc--;
- argv++;
-
- if((argc > 0) && (argv[0][0] == '-')) {
- port = atoi(argv[0] + 1);
- argc--;
- argv++;
- }
-
- sprintf(devname,"/dev/smd%d",port);
- fd = open(devname, O_WRONLY);
- if(fd < 0) {
- fprintf(stderr,"failed to open smd0 - %s\n",
- strerror(errno));
- return -1;
- }
- while(argc > 0) {
- len = strlen(argv[0]);
- r = write(fd, argv[0], len);
- if(r != len) {
- fprintf(stderr,"failed to write smd0 (%d) %s\n",
- r, strerror(errno));
- return -1;
- }
- argc--;
- argv++;
- write(fd, argc ? " " : "\r", 1);
- }
- close(fd);
- return 0;
-}
diff --git a/toolbox/wipe.c b/toolbox/wipe.c
deleted file mode 100644
index 650a0d6..0000000
--- a/toolbox/wipe.c
+++ /dev/null
@@ -1,176 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <cutils/android_reboot.h>
-#include <sys/stat.h>
-
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
-
-
-/* Directories created by init defined in system/rootdir/init.rc */
-static char *INIT_DIRS[] = {
- "/system/etc/ppp",
- "/data/misc",
- "/data/local",
- "/data/local/tmp",
- "/data/data",
- "/data/app_private",
- "/data/app",
- NULL
-};
-
-static void wipe (const char *path);
-
-static int usage()
-{
- fprintf(stderr, "wipe <system|data|all>\n\n"
- "system means '/system'\n"
- "data means '/data'\n");
-
- return -1;
-}
-
-int wipe_main (int argc, char *argv[])
-{
- char *whatToWipe;
-
- if (argc != 2) return usage();
-
- whatToWipe = argv[1];
-
- if (0 == strcmp (whatToWipe, "system")) {
- fprintf(stdout, "Wiping /system\n");
- wipe ("/system");
- fprintf(stdout, "Done wiping /android\n");
- } else if (0 == strcmp (whatToWipe, "data")) {
- fprintf(stdout, "Wiping /data\n");
- wipe ("/data");
- fprintf(stdout, "Done wiping /data\n");
- } else if (0 == strcmp (whatToWipe, "all")) {
- fprintf(stdout, "Wiping /system and /data\n");
- wipe ("/system");
- wipe ("/data");
- fprintf(stdout, "Done wiping /system and /data\n");
- } else if (0 == strcmp(whatToWipe, "nuke")) {
- int ret;
- fprintf(stdout, "Nuking the device...\n");
- wipe ("/system");
- wipe ("/data");
- fprintf(stdout, "Device nuked! Rebooting...\n");
- ret = android_reboot(ANDROID_RB_RESTART, 0, 0);
- if (ret < 0) {
- fprintf(stderr, "Reboot failed, %s\n", strerror(errno));
- return 1;
- }
- } else {
- return usage();
- }
-
- return 0;
-}
-
-static char nameBuffer[PATH_MAX];
-static struct stat statBuffer;
-
-static void wipe (const char *path)
-{
- DIR *dir;
- struct dirent *de;
- int ret;
-
- dir = opendir(path);
-
- if (dir == NULL) {
- fprintf (stderr, "Error opendir'ing %s '%s'\n",
- path, strerror(errno));
- return;
- }
-
- char *filenameOffset;
-
- strcpy(nameBuffer, path);
- strcat(nameBuffer, "/");
-
- filenameOffset = nameBuffer + strlen(nameBuffer);
-
- for (;;) {
- de = readdir(dir);
-
- if (de == NULL) {
- break;
- }
-
- if (0 == strcmp(de->d_name, ".")
- || 0 == strcmp(de->d_name, "..")
- || 0 == strcmp(de->d_name, "lost+found")
- ) {
- continue;
- }
-
- strcpy(filenameOffset, de->d_name);
-
- ret = lstat (nameBuffer, &statBuffer);
-
- if (ret != 0) {
- fprintf(stderr, "stat() error on '%s' '%s'\n",
- nameBuffer, strerror(errno));
- }
-
- if(S_ISDIR(statBuffer.st_mode)) {
- int i;
- char *newpath;
-
-#if 0
- closedir(dir);
-#endif
-
- newpath = strdup(nameBuffer);
- wipe(newpath);
-
- /* Leave directories created by init, they have special permissions. */
- for (i = 0; INIT_DIRS[i]; i++) {
- if (strcmp(INIT_DIRS[i], newpath) == 0) {
- break;
- }
- }
- if (INIT_DIRS[i] == NULL) {
- ret = rmdir(newpath);
- if (ret != 0) {
- fprintf(stderr, "rmdir() error on '%s' '%s'\n",
- newpath, strerror(errno));
- }
- }
-
- free(newpath);
-
-#if 0
- dir = opendir(path);
- if (dir == NULL) {
- fprintf (stderr, "Error opendir'ing %s '%s'\n",
- path, strerror(errno));
- return;
- }
-#endif
-
- strcpy(nameBuffer, path);
- strcat(nameBuffer, "/");
-
- } else {
- ret = unlink(nameBuffer);
-
- if (ret != 0) {
- fprintf(stderr, "unlink() error on '%s' '%s'\n",
- nameBuffer, strerror(errno));
- }
- }
- }
-
- closedir(dir);
-
-}