Merge "Add deflate compression to ZipWriter"
diff --git a/adb/Android.mk b/adb/Android.mk
index 4ee1ced..c507905 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -14,6 +14,7 @@
-Wall -Wextra -Werror \
-Wno-unused-parameter \
-Wno-missing-field-initializers \
+ -Wvla \
-DADB_REVISION='"$(adb_version)"' \
# Define windows.h and tchar.h Unicode preprocessor symbols so that
@@ -294,11 +295,15 @@
libadbd \
libbase \
libfs_mgr \
+ libfec \
+ libfec_rs \
+ libselinux \
liblog \
libmincrypt \
- libselinux \
libext4_utils_static \
+ libsquashfs_utils \
libcutils \
libbase \
+ libcrypto_static
include $(BUILD_EXECUTABLE)
diff --git a/adb/adb_io_test.cpp b/adb/adb_io_test.cpp
index 84e3db6..6928a90 100644
--- a/adb/adb_io_test.cpp
+++ b/adb/adb_io_test.cpp
@@ -43,7 +43,7 @@
ASSERT_NE(-1, tf.fd);
ASSERT_TRUE(android::base::WriteStringToFd(expected, tf.fd)) << strerror(errno);
- ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+ ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
// Test reading the whole file.
char buf[sizeof(expected)] = {};
@@ -57,7 +57,7 @@
ASSERT_NE(-1, tf.fd);
ASSERT_TRUE(android::base::WriteStringToFd(expected, tf.fd)) << strerror(errno);
- ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+ ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
// Test that not having enough data will fail.
char buf[sizeof(expected) + 1] = {};
@@ -71,7 +71,7 @@
ASSERT_NE(-1, tf.fd);
ASSERT_TRUE(android::base::WriteStringToFd(input, tf.fd)) << strerror(errno);
- ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+ ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
// Test reading a partial file.
char buf[sizeof(input) - 1] = {};
@@ -90,7 +90,7 @@
// Test writing the whole string to the file.
ASSERT_TRUE(WriteFdExactly(tf.fd, expected, sizeof(expected)))
<< strerror(errno);
- ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+ ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
std::string s;
ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s));
@@ -104,7 +104,7 @@
// Test writing a partial string to the file.
ASSERT_TRUE(WriteFdExactly(tf.fd, buf, sizeof(buf) - 2)) << strerror(errno);
- ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+ ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
std::string expected(buf);
expected.pop_back();
@@ -130,7 +130,7 @@
// Test writing a partial string to the file.
ASSERT_TRUE(WriteFdExactly(tf.fd, str)) << strerror(errno);
- ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+ ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
std::string s;
ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s));
@@ -143,7 +143,7 @@
// Test writing a partial string to the file.
ASSERT_TRUE(WriteFdFmt(tf.fd, "Foo%s%d", "bar", 123)) << strerror(errno);
- ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+ ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
std::string s;
ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s));
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index bc5ba38..2632b1f 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -39,6 +39,7 @@
#include <base/strings.h>
#if !defined(_WIN32)
+#include <signal.h>
#include <termios.h>
#include <unistd.h>
#endif
@@ -440,6 +441,14 @@
adb_thread_setname("stdin reader");
+#ifndef __WIN32
+ // Mask SIGTTIN in case we're in a backgrounded process
+ sigset_t sigset;
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGTTIN);
+ pthread_sigmask(SIG_BLOCK, &sigset, nullptr);
+#endif
+
char raw_buffer[1024];
char* buffer_ptr = raw_buffer;
size_t buffer_size = sizeof(raw_buffer);
@@ -478,7 +487,11 @@
state = 1;
break;
case '~':
- if(state == 1) state++;
+ if(state == 1) {
+ state++;
+ } else {
+ state = 0;
+ }
break;
case '.':
if(state == 2) {
@@ -1342,15 +1355,20 @@
// argv[0] is always "shell".
--argc;
++argv;
- std::string shell_type_arg;
+ int t_arg_count = 0;
while (argc) {
if (!strcmp(argv[0], "-T") || !strcmp(argv[0], "-t")) {
if (!CanUseFeature(features, kFeatureShell2)) {
fprintf(stderr, "error: target doesn't support PTY args -Tt\n");
return 1;
}
- shell_type_arg = (argv[0][1] == 'T') ? kShellServiceArgRaw
- : kShellServiceArgPty;
+ // Like ssh, -t arguments are cumulative so that multiple -t's
+ // are needed to force a PTY.
+ if (argv[0][1] == 't') {
+ ++t_arg_count;
+ } else {
+ t_arg_count = -1;
+ }
--argc;
++argv;
} else if (!strcmp(argv[0], "-x")) {
@@ -1362,6 +1380,33 @@
}
}
+ std::string shell_type_arg;
+ if (CanUseFeature(features, kFeatureShell2)) {
+ if (t_arg_count < 0) {
+ shell_type_arg = kShellServiceArgRaw;
+ } else if (t_arg_count == 0) {
+ // If stdin isn't a TTY, default to a raw shell; this lets
+ // things like `adb shell < my_script.sh` work as expected.
+ // Otherwise leave |shell_type_arg| blank which uses PTY for
+ // interactive shells and raw for non-interactive.
+ if (!isatty(STDIN_FILENO)) {
+ shell_type_arg = kShellServiceArgRaw;
+ }
+ } else if (t_arg_count == 1) {
+ // A single -t arg isn't enough to override implicit -T.
+ if (!isatty(STDIN_FILENO)) {
+ fprintf(stderr,
+ "Remote PTY will not be allocated because stdin is not a terminal.\n"
+ "Use multiple -t options to force remote PTY allocation.\n");
+ shell_type_arg = kShellServiceArgRaw;
+ } else {
+ shell_type_arg = kShellServiceArgPty;
+ }
+ } else {
+ shell_type_arg = kShellServiceArgPty;
+ }
+ }
+
std::string command;
if (argc) {
// We don't escape here, just like ssh(1). http://b/20564385.
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index 5513e8f..1d668bc 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -29,6 +29,7 @@
#include <utime.h>
#include <memory>
+#include <vector>
#include "sysdeps.h"
@@ -77,7 +78,7 @@
std::string error;
fd = adb_connect("sync:", &error);
if (fd < 0) {
- fprintf(stderr, "error: %s\n", error.c_str());
+ fprintf(stderr, "adb: error: %s\n", error.c_str());
}
}
@@ -94,21 +95,21 @@
bool SendRequest(int id, const char* path_and_mode) {
size_t path_length = strlen(path_and_mode);
if (path_length > 1024) {
- fprintf(stderr, "SendRequest failed: path too long: %zu", path_length);
+ fprintf(stderr, "adb: SendRequest failed: path too long: %zu\n", path_length);
errno = ENAMETOOLONG;
return false;
}
// Sending header and payload in a single write makes a noticeable
// difference to "adb sync" performance.
- char buf[sizeof(SyncRequest) + path_length];
- SyncRequest* req = reinterpret_cast<SyncRequest*>(buf);
+ std::vector<char> buf(sizeof(SyncRequest) + path_length);
+ SyncRequest* req = reinterpret_cast<SyncRequest*>(&buf[0]);
req->id = id;
req->path_length = path_length;
char* data = reinterpret_cast<char*>(req + 1);
memcpy(data, path_and_mode, path_length);
- return WriteFdExactly(fd, buf, sizeof(buf));
+ return WriteFdExactly(fd, &buf[0], buf.size());
}
// Sending header, payload, and footer in a single write makes a huge
@@ -118,15 +119,15 @@
unsigned mtime) {
size_t path_length = strlen(path_and_mode);
if (path_length > 1024) {
- fprintf(stderr, "SendSmallFile failed: path too long: %zu", path_length);
+ fprintf(stderr, "adb: SendSmallFile failed: path too long: %zu\n", path_length);
errno = ENAMETOOLONG;
return false;
}
- char buf[sizeof(SyncRequest) + path_length +
+ std::vector<char> buf(sizeof(SyncRequest) + path_length +
sizeof(SyncRequest) + data_length +
- sizeof(SyncRequest)];
- char* p = buf;
+ sizeof(SyncRequest));
+ char* p = &buf[0];
SyncRequest* req_send = reinterpret_cast<SyncRequest*>(p);
req_send->id = ID_SEND;
@@ -147,7 +148,7 @@
req_done->path_length = mtime;
p += sizeof(SyncRequest);
- if (!WriteFdExactly(fd, buf, (p-buf))) return false;
+ if (!WriteFdExactly(fd, &buf[0], (p - &buf[0]))) return false;
total_bytes += data_length;
return true;
@@ -156,7 +157,7 @@
bool CopyDone(const char* from, const char* to) {
syncmsg msg;
if (!ReadFdExactly(fd, &msg.status, sizeof(msg.status))) {
- fprintf(stderr, "failed to copy '%s' to '%s': no ID_DONE: %s\n",
+ fprintf(stderr, "adb: failed to copy '%s' to '%s': no ID_DONE: %s\n",
from, to, strerror(errno));
return false;
}
@@ -164,17 +165,22 @@
return true;
}
if (msg.status.id != ID_FAIL) {
- fprintf(stderr, "failed to copy '%s' to '%s': unknown reason\n", from, to);
+ fprintf(stderr, "adb: failed to copy '%s' to '%s': unknown reason %d\n",
+ from, to, msg.status.id);
return false;
}
- char buffer[msg.status.msglen + 1];
- if (!ReadFdExactly(fd, buffer, msg.status.msglen)) {
- fprintf(stderr, "failed to copy '%s' to '%s'; failed to read reason (!): %s\n",
+ return ReportCopyFailure(from, to, msg);
+ }
+
+ bool ReportCopyFailure(const char* from, const char* to, const syncmsg& msg) {
+ std::vector<char> buf(msg.status.msglen + 1);
+ if (!ReadFdExactly(fd, &buf[0], msg.status.msglen)) {
+ fprintf(stderr, "adb: failed to copy '%s' to '%s'; failed to read reason (!): %s\n",
from, to, strerror(errno));
return false;
}
- buffer[msg.status.msglen] = 0;
- fprintf(stderr, "failed to copy '%s' to '%s': %s\n", from, to, buffer);
+ buf[msg.status.msglen] = 0;
+ fprintf(stderr, "adb: failed to copy '%s' to '%s': %s\n", from, to, &buf[0]);
return false;
}
@@ -246,7 +252,7 @@
static bool SendLargeFile(SyncConnection& sc, const char* path_and_mode, const char* path,
unsigned mtime, bool show_progress) {
if (!sc.SendRequest(ID_SEND, path_and_mode)) {
- fprintf(stderr, "failed to send ID_SEND message '%s': %s\n",
+ fprintf(stderr, "adb: failed to send ID_SEND message '%s': %s\n",
path_and_mode, strerror(errno));
return false;
}
@@ -256,7 +262,7 @@
// Determine local file size.
struct stat st;
if (stat(path, &st) == -1) {
- fprintf(stderr, "cannot stat '%s': %s\n", path, strerror(errno));
+ fprintf(stderr, "adb: cannot stat '%s': %s\n", path, strerror(errno));
return false;
}
@@ -265,7 +271,7 @@
int lfd = adb_open(path, O_RDONLY);
if (lfd < 0) {
- fprintf(stderr, "cannot open '%s': %s\n", path, strerror(errno));
+ fprintf(stderr, "adb: cannot open '%s': %s\n", path, strerror(errno));
return false;
}
@@ -275,7 +281,7 @@
int ret = adb_read(lfd, sbuf.data, sc.max);
if (ret <= 0) {
if (ret < 0) {
- fprintf(stderr, "cannot read '%s': %s\n", path, strerror(errno));
+ fprintf(stderr, "adb: cannot read '%s': %s\n", path, strerror(errno));
adb_close(lfd);
return false;
}
@@ -300,7 +306,8 @@
msg.data.id = ID_DONE;
msg.data.size = mtime;
if (!WriteFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
- fprintf(stderr, "failed to send ID_DONE message for '%s': %s\n", path, strerror(errno));
+ fprintf(stderr, "adb: failed to send ID_DONE message for '%s': %s\n",
+ path, strerror(errno));
return false;
}
@@ -317,7 +324,7 @@
char buf[PATH_MAX];
ssize_t data_length = readlink(lpath, buf, PATH_MAX - 1);
if (data_length == -1) {
- fprintf(stderr, "readlink '%s' failed: %s\n", lpath, strerror(errno));
+ fprintf(stderr, "adb: readlink '%s' failed: %s\n", lpath, strerror(errno));
return false;
}
buf[data_length++] = '\0';
@@ -328,19 +335,19 @@
}
if (!S_ISREG(mode)) {
- fprintf(stderr, "local file '%s' has unsupported mode: 0o%o\n", lpath, mode);
+ fprintf(stderr, "adb: local file '%s' has unsupported mode: 0o%o\n", lpath, mode);
return false;
}
struct stat st;
if (stat(lpath, &st) == -1) {
- fprintf(stderr, "stat '%s' failed: %s\n", lpath, strerror(errno));
+ fprintf(stderr, "adb: failed to stat local file '%s': %s\n", lpath, strerror(errno));
return false;
}
if (st.st_size < SYNC_DATA_MAX) {
std::string data;
if (!android::base::ReadFileToString(lpath, &data)) {
- fprintf(stderr, "failed to read all of '%s': %s\n", lpath, strerror(errno));
+ fprintf(stderr, "adb: failed to read all of '%s': %s\n", lpath, strerror(errno));
return false;
}
if (!sc.SendSmallFile(path_and_mode.c_str(), data.data(), data.size(), mtime)) return false;
@@ -351,66 +358,60 @@
}
static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath, bool show_progress) {
- syncmsg msg;
- int lfd = -1;
-
- size_t len = strlen(rpath);
- if (len > 1024) return false;
-
unsigned size = 0;
if (show_progress) {
if (!sync_stat(sc, rpath, nullptr, nullptr, &size)) return false;
}
if (!sc.SendRequest(ID_RECV, rpath)) return false;
- if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) return false;
- unsigned id = msg.data.id;
-
- if (id == ID_DATA || id == ID_DONE) {
- adb_unlink(lpath);
- mkdirs(lpath);
- lfd = adb_creat(lpath, 0644);
- if(lfd < 0) {
- fprintf(stderr, "cannot create '%s': %s\n", lpath, strerror(errno));
- return false;
- }
- goto handle_data;
- } else {
- goto remote_error;
+ adb_unlink(lpath);
+ mkdirs(lpath);
+ int lfd = adb_creat(lpath, 0644);
+ if (lfd < 0) {
+ fprintf(stderr, "adb: cannot create '%s': %s\n", lpath, strerror(errno));
+ return false;
}
while (true) {
- char buffer[SYNC_DATA_MAX];
-
+ syncmsg msg;
if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
adb_close(lfd);
+ adb_unlink(lpath);
return false;
}
- id = msg.data.id;
- handle_data:
- len = msg.data.size;
- if (id == ID_DONE) break;
- if (id != ID_DATA) goto remote_error;
- if (len > sc.max) {
- fprintf(stderr, "msg.data.size too large: %zu (max %zu)\n", len, sc.max);
+ if (msg.data.id == ID_DONE) break;
+
+ if (msg.data.id != ID_DATA) {
adb_close(lfd);
+ adb_unlink(lpath);
+ sc.ReportCopyFailure(rpath, lpath, msg);
return false;
}
- if (!ReadFdExactly(sc.fd, buffer, len)) {
+ if (msg.data.size > sc.max) {
+ fprintf(stderr, "adb: msg.data.size too large: %u (max %zu)\n", msg.data.size, sc.max);
adb_close(lfd);
+ adb_unlink(lpath);
return false;
}
- if (!WriteFdExactly(lfd, buffer, len)) {
- fprintf(stderr, "cannot write '%s': %s\n", rpath, strerror(errno));
+ char buffer[SYNC_DATA_MAX];
+ if (!ReadFdExactly(sc.fd, buffer, msg.data.size)) {
adb_close(lfd);
+ adb_unlink(lpath);
return false;
}
- sc.total_bytes += len;
+ if (!WriteFdExactly(lfd, buffer, msg.data.size)) {
+ fprintf(stderr, "adb: cannot write '%s': %s\n", lpath, strerror(errno));
+ adb_close(lfd);
+ adb_unlink(lpath);
+ return false;
+ }
+
+ sc.total_bytes += msg.data.size;
if (show_progress) {
print_transfer_progress(sc.total_bytes, size);
@@ -419,12 +420,6 @@
adb_close(lfd);
return true;
-
-remote_error:
- adb_close(lfd);
- adb_unlink(lpath);
- sc.CopyDone(rpath, lpath);
- return false;
}
static void do_sync_ls_cb(unsigned mode, unsigned size, unsigned time,
@@ -486,7 +481,7 @@
std::unique_ptr<DIR, int(*)(DIR*)> dir(opendir(lpath), closedir);
if (!dir) {
- fprintf(stderr, "cannot open '%s': %s\n", lpath, strerror(errno));
+ fprintf(stderr, "adb: cannot open '%s': %s\n", lpath, strerror(errno));
return -1;
}
@@ -496,7 +491,7 @@
char stat_path[PATH_MAX];
if (strlen(lpath) + strlen(de->d_name) + 1 > sizeof(stat_path)) {
- fprintf(stderr, "skipping long path '%s%s'\n", lpath, de->d_name);
+ fprintf(stderr, "adb: skipping long path '%s%s'\n", lpath, de->d_name);
continue;
}
strcpy(stat_path, lpath);
@@ -511,7 +506,7 @@
} else {
ci = mkcopyinfo(lpath, rpath, de->d_name, 0);
if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) {
- fprintf(stderr, "skipping special file '%s'\n", ci->src);
+ fprintf(stderr, "adb: skipping special file '%s'\n", ci->src);
free(ci);
} else {
ci->time = st.st_mtime;
@@ -522,7 +517,7 @@
}
}
} else {
- fprintf(stderr, "cannot lstat '%s': %s\n",stat_path , strerror(errno));
+ fprintf(stderr, "adb: cannot lstat '%s': %s\n",stat_path , strerror(errno));
}
}
@@ -607,7 +602,7 @@
struct stat st;
if (stat(lpath, &st)) {
- fprintf(stderr, "cannot stat '%s': %s\n", lpath, strerror(errno));
+ fprintf(stderr, "adb: cannot stat '%s': %s\n", lpath, strerror(errno));
return false;
}
@@ -660,7 +655,7 @@
ci->next = *filelist;
*filelist = ci;
} else {
- fprintf(stderr, "skipping special file '%s'\n", name);
+ fprintf(stderr, "adb: skipping special file '%s'\n", name);
}
}
@@ -754,7 +749,7 @@
unsigned mode, time;
if (!sync_stat(sc, rpath, &time, &mode, nullptr)) return false;
if (mode == 0) {
- fprintf(stderr, "remote object '%s' does not exist\n", rpath);
+ fprintf(stderr, "adb: remote object '%s' does not exist\n", rpath);
return false;
}
@@ -781,7 +776,7 @@
return copy_remote_dir_local(sc, rpath, lpath, copy_attrs);
}
- fprintf(stderr, "remote object '%s' not a file or directory\n", rpath);
+ fprintf(stderr, "adb: remote object '%s' not a file or directory\n", rpath);
return false;
}
diff --git a/adb/set_verity_enable_state_service.cpp b/adb/set_verity_enable_state_service.cpp
index fd1740d..f5188e9 100644
--- a/adb/set_verity_enable_state_service.cpp
+++ b/adb/set_verity_enable_state_service.cpp
@@ -28,10 +28,11 @@
#include "adb.h"
#include "adb_io.h"
-#include "ext4_sb.h"
#include "fs_mgr.h"
#include "remount_service.h"
+#include "fec/io.h"
+
#define FSTAB_PREFIX "/fstab."
struct fstab *fstab;
@@ -41,115 +42,50 @@
static const bool kAllowDisableVerity = false;
#endif
-static int get_target_device_size(int fd, const char *blk_device,
- uint64_t *device_size)
-{
- int data_device;
- struct ext4_super_block sb;
- struct fs_info info;
-
- info.len = 0; /* Only len is set to 0 to ask the device for real size. */
-
- data_device = adb_open(blk_device, O_RDONLY | O_CLOEXEC);
- if (data_device < 0) {
- WriteFdFmt(fd, "Error opening block device (%s)\n", strerror(errno));
- return -1;
- }
-
- if (lseek64(data_device, 1024, SEEK_SET) < 0) {
- WriteFdFmt(fd, "Error seeking to superblock\n");
- adb_close(data_device);
- return -1;
- }
-
- if (adb_read(data_device, &sb, sizeof(sb)) != sizeof(sb)) {
- WriteFdFmt(fd, "Error reading superblock\n");
- adb_close(data_device);
- return -1;
- }
-
- ext4_parse_sb(&sb, &info);
- *device_size = info.len;
-
- adb_close(data_device);
- return 0;
-}
-
/* Turn verity on/off */
static int set_verity_enabled_state(int fd, const char *block_device,
const char* mount_point, bool enable)
{
- uint32_t magic_number;
- const uint32_t new_magic = enable ? VERITY_METADATA_MAGIC_NUMBER
- : VERITY_METADATA_MAGIC_DISABLE;
- uint64_t device_length = 0;
- int device = -1;
- int retval = -1;
-
if (!make_block_device_writable(block_device)) {
WriteFdFmt(fd, "Could not make block device %s writable (%s).\n",
block_device, strerror(errno));
- goto errout;
+ return -1;
}
- device = adb_open(block_device, O_RDWR | O_CLOEXEC);
- if (device == -1) {
+ fec::io fh(block_device, O_RDWR);
+
+ if (!fh) {
WriteFdFmt(fd, "Could not open block device %s (%s).\n", block_device, strerror(errno));
- WriteFdFmt(fd, "Maybe run adb remount?\n");
- goto errout;
+ WriteFdFmt(fd, "Maybe run adb root?\n");
+ return -1;
}
- // find the start of the verity metadata
- if (get_target_device_size(fd, (char*)block_device, &device_length) < 0) {
- WriteFdFmt(fd, "Could not get target device size.\n");
- goto errout;
+ fec_verity_metadata metadata;
+
+ if (!fh.get_verity_metadata(metadata)) {
+ WriteFdFmt(fd, "Couldn't find verity metadata!\n");
+ return -1;
}
- if (lseek64(device, device_length, SEEK_SET) < 0) {
- WriteFdFmt(fd, "Could not seek to start of verity metadata block.\n");
- goto errout;
- }
-
- // check the magic number
- if (adb_read(device, &magic_number, sizeof(magic_number)) != sizeof(magic_number)) {
- WriteFdFmt(fd, "Couldn't read magic number!\n");
- goto errout;
- }
-
- if (!enable && magic_number == VERITY_METADATA_MAGIC_DISABLE) {
+ if (!enable && metadata.disabled) {
WriteFdFmt(fd, "Verity already disabled on %s\n", mount_point);
- goto errout;
+ return -1;
}
- if (enable && magic_number == VERITY_METADATA_MAGIC_NUMBER) {
+ if (enable && !metadata.disabled) {
WriteFdFmt(fd, "Verity already enabled on %s\n", mount_point);
- goto errout;
+ return -1;
}
- if (magic_number != VERITY_METADATA_MAGIC_NUMBER
- && magic_number != VERITY_METADATA_MAGIC_DISABLE) {
- WriteFdFmt(fd, "Couldn't find verity metadata at offset %" PRIu64 "!\n", device_length);
- goto errout;
- }
-
- if (lseek64(device, device_length, SEEK_SET) < 0) {
- WriteFdFmt(fd, "Could not seek to start of verity metadata block.\n");
- goto errout;
- }
-
- if (adb_write(device, &new_magic, sizeof(new_magic)) != sizeof(new_magic)) {
+ if (!fh.set_verity_status(enable)) {
WriteFdFmt(fd, "Could not set verity %s flag on device %s with error %s\n",
enable ? "enabled" : "disabled",
block_device, strerror(errno));
- goto errout;
+ return -1;
}
WriteFdFmt(fd, "Verity %s on %s\n", enable ? "enabled" : "disabled", mount_point);
- retval = 0;
-errout:
- if (device != -1)
- adb_close(device);
- return retval;
+ return 0;
}
void set_verity_enabled_state_service(int fd, void* cookie)
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 501a75a..51d09a6 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -319,6 +319,9 @@
#define getcwd adb_getcwd
+char* adb_strerror(int err);
+#define strerror adb_strerror
+
// Convert from UTF-8 to UTF-16, typically used to convert char strings into
// wchar_t strings that can be passed to wchar_t-based OS and C Runtime APIs
// on Windows.
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index 994b851..14d1375 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -556,6 +556,81 @@
return 0;
}
+// Overrides strerror() to handle error codes not supported by the Windows C
+// Runtime (MSVCRT.DLL).
+char* adb_strerror(int err) {
+ // sysdeps.h defines strerror to adb_strerror, but in this function, we
+ // want to call the real C Runtime strerror().
+#pragma push_macro("strerror")
+#undef strerror
+ const int saved_err = errno; // Save because we overwrite it later.
+
+ // Lookup the string for an unknown error.
+ char* errmsg = strerror(-1);
+ const std::string unknown_error = (errmsg == nullptr) ? "" : errmsg;
+
+ // Lookup the string for this error to see if the C Runtime has it.
+ errmsg = strerror(err);
+ if (errmsg != nullptr && unknown_error != errmsg) {
+ // The CRT returned an error message and it is different than the error
+ // message for an unknown error, so it is probably valid, so use it.
+ } else {
+ // Check if we have a string for this error code.
+ const char* custom_msg = nullptr;
+ switch (err) {
+#pragma push_macro("ERR")
+#undef ERR
+#define ERR(errnum, desc) case errnum: custom_msg = desc; break
+ // These error strings are from AOSP bionic/libc/include/sys/_errdefs.h.
+ // Note that these cannot be longer than 94 characters because we
+ // pass this to _strerror() which has that requirement.
+ ERR(ECONNRESET, "Connection reset by peer");
+ ERR(EHOSTUNREACH, "No route to host");
+ ERR(ENETDOWN, "Network is down");
+ ERR(ENETRESET, "Network dropped connection because of reset");
+ ERR(ENOBUFS, "No buffer space available");
+ ERR(ENOPROTOOPT, "Protocol not available");
+ ERR(ENOTCONN, "Transport endpoint is not connected");
+ ERR(ENOTSOCK, "Socket operation on non-socket");
+ ERR(EOPNOTSUPP, "Operation not supported on transport endpoint");
+#pragma pop_macro("ERR")
+ }
+
+ if (custom_msg != nullptr) {
+ // Use _strerror() to write our string into the writable per-thread
+ // buffer used by strerror()/_strerror(). _strerror() appends the
+ // msg for the current value of errno, so set errno to a consistent
+ // value for every call so that our code-path is always the same.
+ errno = 0;
+ errmsg = _strerror(custom_msg);
+ const size_t custom_msg_len = strlen(custom_msg);
+ // Just in case _strerror() returned a read-only string, check if
+ // the returned string starts with our custom message because that
+ // implies that the string is not read-only.
+ if ((errmsg != nullptr) &&
+ !strncmp(custom_msg, errmsg, custom_msg_len)) {
+ // _strerror() puts other text after our custom message, so
+ // remove that by terminating after our message.
+ errmsg[custom_msg_len] = '\0';
+ } else {
+ // For some reason nullptr was returned or a pointer to a
+ // read-only string was returned, so fallback to whatever
+ // strerror() can muster (probably "Unknown error" or some
+ // generic CRT error string).
+ errmsg = strerror(err);
+ }
+ } else {
+ // We don't have a custom message, so use whatever strerror(err)
+ // returned earlier.
+ }
+ }
+
+ errno = saved_err; // restore
+
+ return errmsg;
+#pragma pop_macro("strerror")
+}
+
/**************************************************************************/
/**************************************************************************/
/***** *****/
@@ -567,18 +642,38 @@
#undef setsockopt
static void _socket_set_errno( const DWORD err ) {
- // The Windows C Runtime (MSVCRT.DLL) strerror() does not support a lot of
- // POSIX and socket error codes, so this can only meaningfully map so much.
+ // Because the Windows C Runtime (MSVCRT.DLL) strerror() does not support a
+ // lot of POSIX and socket error codes, some of the resulting error codes
+ // are mapped to strings by adb_strerror() above.
switch ( err ) {
case 0: errno = 0; break;
+ // Don't map WSAEINTR since that is only for Winsock 1.1 which we don't use.
+ // case WSAEINTR: errno = EINTR; break;
+ case WSAEFAULT: errno = EFAULT; break;
+ case WSAEINVAL: errno = EINVAL; break;
+ case WSAEMFILE: errno = EMFILE; break;
// Mapping WSAEWOULDBLOCK to EAGAIN is absolutely critical because
// non-blocking sockets can cause an error code of WSAEWOULDBLOCK and
// callers check specifically for EAGAIN.
case WSAEWOULDBLOCK: errno = EAGAIN; break;
- case WSAEINTR: errno = EINTR; break;
- case WSAEFAULT: errno = EFAULT; break;
- case WSAEINVAL: errno = EINVAL; break;
- case WSAEMFILE: errno = EMFILE; break;
+ case WSAENOTSOCK: errno = ENOTSOCK; break;
+ case WSAENOPROTOOPT: errno = ENOPROTOOPT; break;
+ case WSAEOPNOTSUPP: errno = EOPNOTSUPP; break;
+ case WSAENETDOWN: errno = ENETDOWN; break;
+ case WSAENETRESET: errno = ENETRESET; break;
+ // Map WSAECONNABORTED to EPIPE instead of ECONNABORTED because POSIX seems
+ // to use EPIPE for these situations and there are some callers that look
+ // for EPIPE.
+ case WSAECONNABORTED: errno = EPIPE; break;
+ case WSAECONNRESET: errno = ECONNRESET; break;
+ case WSAENOBUFS: errno = ENOBUFS; break;
+ case WSAENOTCONN: errno = ENOTCONN; break;
+ // Don't map WSAETIMEDOUT because we don't currently use SO_RCVTIMEO or
+ // SO_SNDTIMEO which would cause WSAETIMEDOUT to be returned. Future
+ // considerations: Reportedly send() can return zero on timeout, and POSIX
+ // code may expect EAGAIN instead of ETIMEDOUT on timeout.
+ // case WSAETIMEDOUT: errno = ETIMEDOUT; break;
+ case WSAEHOSTUNREACH: errno = EHOSTUNREACH; break;
default:
errno = EINVAL;
D( "_socket_set_errno: mapping Windows error code %lu to errno %d",
@@ -655,8 +750,12 @@
int result = send(f->fh_socket, reinterpret_cast<const char*>(buf), len, 0);
if (result == SOCKET_ERROR) {
const DWORD err = WSAGetLastError();
- D("send fd %d failed: %s", _fh_to_int(f),
- SystemErrorCodeToString(err).c_str());
+ // WSAEWOULDBLOCK is normal with a non-blocking socket, so don't trace
+ // that to reduce spam and confusion.
+ if (err != WSAEWOULDBLOCK) {
+ D("send fd %d failed: %s", _fh_to_int(f),
+ SystemErrorCodeToString(err).c_str());
+ }
_socket_set_errno(err);
result = -1;
} else {
diff --git a/adb/sysdeps_win32_test.cpp b/adb/sysdeps_win32_test.cpp
index cc3ac5c..66d1ba8 100755
--- a/adb/sysdeps_win32_test.cpp
+++ b/adb/sysdeps_win32_test.cpp
@@ -67,3 +67,29 @@
EXPECT_GT(strlen(path_val), 0);
}
}
+
+void TestAdbStrError(int err, const char* expected) {
+ errno = 12345;
+ const char* result = adb_strerror(err);
+ // Check that errno is not overwritten.
+ EXPECT_EQ(12345, errno);
+ EXPECT_STREQ(expected, result);
+}
+
+TEST(sysdeps_win32, adb_strerror) {
+ // Test an error code that should not have a mapped string. Use an error
+ // code that is not used by the internal implementation of adb_strerror().
+ TestAdbStrError(-2, "Unknown error");
+ // adb_strerror() uses -1 internally, so test that it can still be passed
+ // as a parameter.
+ TestAdbStrError(-1, "Unknown error");
+ // Test very big, positive unknown error.
+ TestAdbStrError(1000000, "Unknown error");
+ // Test success case.
+ TestAdbStrError(0, "No error");
+ // Test error that regular strerror() should have a string for.
+ TestAdbStrError(EPERM, "Operation not permitted");
+ // Test error that regular strerror() doesn't have a string for, but that
+ // adb_strerror() returns.
+ TestAdbStrError(ECONNRESET, "Connection reset by peer");
+}
diff --git a/base/logging_test.cpp b/base/logging_test.cpp
index 9cf1aad..70f9952 100644
--- a/base/logging_test.cpp
+++ b/base/logging_test.cpp
@@ -139,7 +139,7 @@
{
CapturedStderr cap;
LOG(WARNING) << "foobar";
- ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+ ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
@@ -155,7 +155,7 @@
{
CapturedStderr cap;
LOG(INFO) << "foobar";
- ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+ ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
@@ -171,7 +171,7 @@
{
CapturedStderr cap;
LOG(DEBUG) << "foobar";
- ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+ ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
@@ -182,7 +182,7 @@
android::base::ScopedLogSeverity severity(android::base::DEBUG);
CapturedStderr cap;
LOG(DEBUG) << "foobar";
- ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+ ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
@@ -202,7 +202,7 @@
LOG(INFO) << (errno = 67890);
EXPECT_EQ(12345, errno) << "errno was not restored";
- ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+ ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
@@ -245,7 +245,7 @@
CapturedStderr cap;
errno = ENOENT;
PLOG(INFO) << "foobar";
- ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+ ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
@@ -264,7 +264,7 @@
CapturedStderr cap;
errno = ENOENT;
UNIMPLEMENTED(ERROR);
- ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+ ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
diff --git a/crash_reporter/Android.mk b/crash_reporter/Android.mk
index 11dfcbc..c5ca4e4 100644
--- a/crash_reporter/Android.mk
+++ b/crash_reporter/Android.mk
@@ -43,7 +43,7 @@
LOCAL_C_INCLUDES := $(crash_reporter_includes)
LOCAL_RTTI_FLAG := -frtti
LOCAL_SHARED_LIBRARIES := libchrome \
- libchromeos \
+ libbrillo \
libcutils \
libdbus \
libmetrics \
@@ -65,7 +65,7 @@
LOCAL_INIT_RC := crash_reporter.rc
LOCAL_RTTI_FLAG := -frtti
LOCAL_SHARED_LIBRARIES := libchrome \
- libchromeos \
+ libbrillo \
libcutils \
libdbus \
libmetrics \
@@ -106,6 +106,7 @@
# will log it as a configuration error.
$(LOCAL_BUILT_MODULE): BRILLO_CRASH_SERVER ?= ""
$(LOCAL_BUILT_MODULE):
+ $(hide)mkdir -p $(dir $@)
echo $(BRILLO_CRASH_SERVER) > $@
endif
@@ -133,7 +134,7 @@
LOCAL_MODULE := crash_reporter_tests
LOCAL_CPP_EXTENSION := $(crash_reporter_cpp_extension)
LOCAL_SHARED_LIBRARIES := libchrome \
- libchromeos \
+ libbrillo \
libcutils \
libdbus \
libpcrecpp
diff --git a/crash_reporter/crash_sender b/crash_reporter/crash_sender
index 5b859a8..95204a4 100755
--- a/crash_reporter/crash_sender
+++ b/crash_reporter/crash_sender
@@ -98,6 +98,10 @@
log -t "${TAG}" "$@"
}
+lwarn() {
+ lecho -psyslog.warn "$@"
+}
+
# Returns true if mock is enabled.
is_mock() {
[ -f "${MOCK_CRASH_SENDING}" ] && return 0
@@ -294,6 +298,11 @@
fi
}
+# Return the log string filtered with only JSON-safe white-listed characters.
+filter_log_string() {
+ echo "$1" | tr -cd '[:alnum:]_.\-:;'
+}
+
send_crash() {
local meta_path="$1"
local report_payload="$(get_key_value "${meta_path}" "payload")"
@@ -434,8 +443,7 @@
ret=$?
if [ ${ret} -ne 0 ]; then
proxy=''
- lecho -psyslog.warn \
- "Listing proxies failed with exit code ${ret}"
+ lwarn "Listing proxies failed with exit code ${ret}"
else
proxy=$(echo "${proxy}" | head -1)
fi
@@ -446,7 +454,7 @@
local curl_stderr="${TMP_DIR}/curl_stderr"
set +e
- curl "${url}" -v ${proxy:+--proxy "$proxy"} \
+ curl "${url}" -f -v ${proxy:+--proxy "$proxy"} \
--capath "${RESTRICTED_CERTIFICATES_PATH}" --ciphers HIGH \
-F "prod=${product}" \
-F "ver=${version}" \
@@ -466,22 +474,17 @@
if [ ${curl_result} -eq 0 ]; then
local id="$(cat "${report_id}")"
- local product_name
local timestamp="$(date +%s)"
- case ${product} in
- Chrome_ChromeOS)
- if is_official_image; then
- product_name="Chrome"
- else
- product_name="Chromium"
- fi
- ;;
- *)
- product_name="Brillo"
- ;;
- esac
- printf '%s,%s,%s\n' \
- "${timestamp}" "${id}" "${product_name}" >> "${CRASH_LOG}"
+ local filter_prod="$(filter_log_string "${product}")"
+ local filter_exec="$(filter_log_string "${exec_name}")"
+ if [ "${filter_prod}" != "${product}" ]; then
+ lwarn "Product name filtered to: ${filter_prod}."
+ fi
+ if [ "${filter_exec}" != "${exec_name}" ]; then
+ lwarn "Exec name filtered to: ${filter_exec}."
+ fi
+ printf "{'time':%s,'id':'%s','product':'%s','exec_name':'%s'}\n" \
+ "${timestamp}" "${id}" "${filter_prod}" "${filter_exec}" >> "${CRASH_LOG}"
lecho "Crash report receipt ID ${id}"
else
lecho "Crash sending failed with exit code ${curl_result}: " \
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 713638d..1287fb9 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -528,7 +528,7 @@
return 1;
fcntl(s, F_SETFD, FD_CLOEXEC);
- ALOGI("debuggerd: " __DATE__ " " __TIME__ "\n");
+ ALOGI("debuggerd: starting\n");
for (;;) {
sockaddr addr;
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index c358982..6983b72 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -765,8 +765,9 @@
continue;
}
- if (current == VERITY_MODE_LOGGING) {
+ if (current != VERITY_MODE_DEFAULT) {
*mode = current;
+ break;
}
}
@@ -784,7 +785,6 @@
{
alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
bool use_state = true;
- bool use_state_for_device = true;
char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
char *mount_point;
char propbuf[PROPERTY_VALUE_MAX];
@@ -801,12 +801,13 @@
property_get("ro.boot.veritymode", propbuf, "");
if (*propbuf != '\0') {
- if (fs_mgr_load_verity_state(&mode) == -1) {
- return -1;
- }
use_state = false; /* state is kept by the bootloader */
}
+ if (fs_mgr_load_verity_state(&mode) == -1) {
+ return -1;
+ }
+
fd = TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC));
if (fd == -1) {
@@ -829,15 +830,6 @@
continue;
}
- use_state_for_device = use_state;
-
- if (use_state) {
- if (get_verity_state_offset(&fstab->recs[i], &offset) < 0 ||
- read_verity_state(fstab->recs[i].verity_loc, offset, &mode) < 0) {
- use_state_for_device = false;
- }
- }
-
mount_point = basename(fstab->recs[i].mount_point);
verity_ioctl_init(io, mount_point, 0);
@@ -849,7 +841,7 @@
status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
- if (use_state_for_device && *status == 'C') {
+ if (use_state && *status == 'C') {
if (write_verity_state(fstab->recs[i].verity_loc, offset,
VERITY_MODE_LOGGING) < 0) {
continue;
diff --git a/healthd/Android.mk b/healthd/Android.mk
index 07e1d73..27c985c 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -35,7 +35,7 @@
LOCAL_C_INCLUDES := bootable/recovery
-LOCAL_STATIC_LIBRARIES := libbatteryservice libbinder libminui libpng libz libutils libstdc++ libcutils liblog libm libc
+LOCAL_STATIC_LIBRARIES := libbatteryservice libbinder libminui libpng libz libutils libcutils liblog libm libc
ifeq ($(strip $(BOARD_CHARGER_ENABLE_SUSPEND)),true)
LOCAL_STATIC_LIBRARIES += libsuspend
diff --git a/include/binderwrapper/binder_wrapper.h b/include/binderwrapper/binder_wrapper.h
index e57cf83..921c4ed 100644
--- a/include/binderwrapper/binder_wrapper.h
+++ b/include/binderwrapper/binder_wrapper.h
@@ -17,6 +17,8 @@
#ifndef SYSTEM_CORE_INCLUDE_BINDERWRAPPER_BINDER_WRAPPER_H_
#define SYSTEM_CORE_INCLUDE_BINDERWRAPPER_BINDER_WRAPPER_H_
+#include <sys/types.h>
+
#include <string>
#include <base/callback.h>
@@ -68,6 +70,10 @@
// Unregisters the callback, if any, for |binder|.
virtual bool UnregisterForDeathNotifications(const sp<IBinder>& binder) = 0;
+ // When called while in a transaction, returns the caller's UID or PID.
+ virtual uid_t GetCallingUid() = 0;
+ virtual pid_t GetCallingPid() = 0;
+
private:
static BinderWrapper* instance_;
};
diff --git a/include/binderwrapper/stub_binder_wrapper.h b/include/binderwrapper/stub_binder_wrapper.h
index 6e198ae..01c9648 100644
--- a/include/binderwrapper/stub_binder_wrapper.h
+++ b/include/binderwrapper/stub_binder_wrapper.h
@@ -77,6 +77,9 @@
}
void clear_local_binders() { local_binders_.clear(); }
+ void set_calling_uid(uid_t uid) { calling_uid_ = uid; }
+ void set_calling_pid(pid_t pid) { calling_pid_ = pid; }
+
// Sets the binder to return when |service_name| is passed to GetService() or
// WaitForService().
void SetBinderForService(const std::string& service_name,
@@ -97,6 +100,8 @@
bool RegisterForDeathNotifications(const sp<IBinder>& binder,
const base::Closure& callback) override;
bool UnregisterForDeathNotifications(const sp<IBinder>& binder) override;
+ uid_t GetCallingUid() override;
+ pid_t GetCallingPid() override;
private:
using ServiceMap = std::map<std::string, sp<IBinder>>;
@@ -116,6 +121,10 @@
// death.
std::map<sp<IBinder>, base::Closure> death_callbacks_;
+ // Values to return from GetCallingUid() and GetCallingPid();
+ uid_t calling_uid_;
+ pid_t calling_pid_;
+
DISALLOW_COPY_AND_ASSIGN(StubBinderWrapper);
};
diff --git a/include/log/logger.h b/include/log/logger.h
index f030dab..c795253 100644
--- a/include/log/logger.h
+++ b/include/log/logger.h
@@ -183,6 +183,8 @@
pid_t pid);
#define android_logger_list_close android_logger_list_free
+char android_log_timestamp();
+
/*
* log_id_t helpers
*/
diff --git a/include/log/logprint.h b/include/log/logprint.h
index 26b1ee5..204b3f2 100644
--- a/include/log/logprint.h
+++ b/include/log/logprint.h
@@ -42,6 +42,8 @@
FORMAT_MODIFIER_PRINTABLE, /* converts non-printable to printable escapes */
FORMAT_MODIFIER_YEAR, /* Adds year to date */
FORMAT_MODIFIER_ZONE, /* Adds zone to date */
+ FORMAT_MODIFIER_EPOCH, /* Print time as seconds since Jan 1 1970 */
+ FORMAT_MODIFIER_MONOTONIC, /* Print cpu time as seconds since start */
} AndroidLogPrintFormat;
typedef struct AndroidLogFormat_t AndroidLogFormat;
diff --git a/init/Android.mk b/init/Android.mk
index 8e45a7a..d6cb4e5 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -92,9 +92,9 @@
libbase \
libext4_utils_static \
libutils \
- liblog \
libc \
libselinux \
+ liblog \
libmincrypt \
libcrypto_static \
libc++_static \
diff --git a/init/bootchart.cpp b/init/bootchart.cpp
index a768762..e1e0c48 100644
--- a/init/bootchart.cpp
+++ b/init/bootchart.cpp
@@ -89,7 +89,7 @@
if (out == NULL) {
return;
}
- fprintf(out, "version = Android init 0.8 " __TIME__ "\n");
+ fprintf(out, "version = Android init 0.8\n");
fprintf(out, "title = Boot chart for Android (%s)\n", date);
fprintf(out, "system.uname = %s %s %s %s\n", uts.sysname, uts.release, uts.version, uts.machine);
fprintf(out, "system.release = %s\n", fingerprint.c_str());
diff --git a/libbinderwrapper/real_binder_wrapper.cc b/libbinderwrapper/real_binder_wrapper.cc
index adff19b..1c51822 100644
--- a/libbinderwrapper/real_binder_wrapper.cc
+++ b/libbinderwrapper/real_binder_wrapper.cc
@@ -19,6 +19,7 @@
#include <base/logging.h>
#include <binder/Binder.h>
#include <binder/IBinder.h>
+#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
namespace android {
@@ -111,4 +112,12 @@
return true;
}
+uid_t RealBinderWrapper::GetCallingUid() {
+ return IPCThreadState::self()->getCallingUid();
+}
+
+pid_t RealBinderWrapper::GetCallingPid() {
+ return IPCThreadState::self()->getCallingPid();
+}
+
} // namespace android
diff --git a/libbinderwrapper/real_binder_wrapper.h b/libbinderwrapper/real_binder_wrapper.h
index 8e281f2..ea08371 100644
--- a/libbinderwrapper/real_binder_wrapper.h
+++ b/libbinderwrapper/real_binder_wrapper.h
@@ -38,6 +38,8 @@
bool RegisterForDeathNotifications(const sp<IBinder>& binder,
const base::Closure& callback) override;
bool UnregisterForDeathNotifications(const sp<IBinder>& binder) override;
+ uid_t GetCallingUid() override;
+ pid_t GetCallingPid() override;
private:
class DeathRecipient;
diff --git a/libbinderwrapper/stub_binder_wrapper.cc b/libbinderwrapper/stub_binder_wrapper.cc
index 1d24681..87c6ab7 100644
--- a/libbinderwrapper/stub_binder_wrapper.cc
+++ b/libbinderwrapper/stub_binder_wrapper.cc
@@ -22,7 +22,9 @@
namespace android {
-StubBinderWrapper::StubBinderWrapper() = default;
+StubBinderWrapper::StubBinderWrapper()
+ : calling_uid_(-1),
+ calling_pid_(-1) {}
StubBinderWrapper::~StubBinderWrapper() = default;
@@ -73,4 +75,12 @@
return true;
}
+uid_t StubBinderWrapper::GetCallingUid() {
+ return calling_uid_;
+}
+
+pid_t StubBinderWrapper::GetCallingPid() {
+ return calling_pid_;
+}
+
} // namespace android
diff --git a/liblog/log_is_loggable.c b/liblog/log_is_loggable.c
index cd85ff6..814d96d 100644
--- a/liblog/log_is_loggable.c
+++ b/liblog/log_is_loggable.c
@@ -176,3 +176,28 @@
int logLevel = __android_log_level(tag, def);
return logLevel >= 0 && prio >= logLevel;
}
+
+char android_log_timestamp()
+{
+ static struct cache r_time_cache = { NULL, -1, 0 };
+ static struct cache p_time_cache = { NULL, -1, 0 };
+ static uint32_t serial;
+ uint32_t current_serial;
+ char retval;
+
+ pthread_mutex_lock(&lock);
+
+ current_serial = __system_property_area_serial();
+ if (current_serial != serial) {
+ refresh_cache(&r_time_cache, "ro.logd.timestamp");
+ refresh_cache(&p_time_cache, "persist.logd.timestamp");
+ serial = current_serial;
+ }
+ if (!(retval = p_time_cache.c)) {
+ retval = r_time_cache.c;
+ }
+
+ pthread_mutex_unlock(&lock);
+
+ return tolower(retval ?: 'r');
+}
diff --git a/liblog/logprint.c b/liblog/logprint.c
index b6dba2e..0ea2269 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -29,9 +29,13 @@
#include <inttypes.h>
#include <sys/param.h>
+#include <cutils/list.h>
#include <log/logd.h>
#include <log/logprint.h>
+#define MS_PER_NSEC 1000000
+#define US_PER_NSEC 1000
+
/* open coded fragment, prevent circular dependencies */
#define WEAK static
@@ -50,6 +54,8 @@
bool printable_output;
bool year_output;
bool zone_output;
+ bool epoch_output;
+ bool monotonic_output;
};
/*
@@ -196,10 +202,14 @@
p_ret->printable_output = false;
p_ret->year_output = false;
p_ret->zone_output = false;
+ p_ret->epoch_output = false;
+ p_ret->monotonic_output = false;
return p_ret;
}
+static list_declare(convertHead);
+
void android_log_format_free(AndroidLogFormat *p_format)
{
FilterInfo *p_info, *p_info_old;
@@ -214,10 +224,15 @@
}
free(p_format);
+
+ /* Free conversion resource, can always be reconstructed */
+ while (!list_empty(&convertHead)) {
+ struct listnode *node = list_head(&convertHead);
+ list_remove(node);
+ free(node);
+ }
}
-
-
int android_log_setPrintFormat(AndroidLogFormat *p_format,
AndroidLogPrintFormat format)
{
@@ -237,6 +252,12 @@
case FORMAT_MODIFIER_ZONE:
p_format->zone_output = !p_format->zone_output;
return 0;
+ case FORMAT_MODIFIER_EPOCH:
+ p_format->epoch_output = true;
+ return 0;
+ case FORMAT_MODIFIER_MONOTONIC:
+ p_format->monotonic_output = true;
+ return 0;
default:
break;
}
@@ -267,6 +288,8 @@
else if (strcmp(formatString, "printable") == 0) format = FORMAT_MODIFIER_PRINTABLE;
else if (strcmp(formatString, "year") == 0) format = FORMAT_MODIFIER_YEAR;
else if (strcmp(formatString, "zone") == 0) format = FORMAT_MODIFIER_ZONE;
+ else if (strcmp(formatString, "epoch") == 0) format = FORMAT_MODIFIER_EPOCH;
+ else if (strcmp(formatString, "monotonic") == 0) format = FORMAT_MODIFIER_MONOTONIC;
else {
extern char *tzname[2];
static const char gmt[] = "GMT";
@@ -913,6 +936,285 @@
return p - begin;
}
+char *readSeconds(char *e, struct timespec *t)
+{
+ unsigned long multiplier;
+ char *p;
+ t->tv_sec = strtoul(e, &p, 10);
+ if (*p != '.') {
+ return NULL;
+ }
+ t->tv_nsec = 0;
+ multiplier = NS_PER_SEC;
+ while (isdigit(*++p) && (multiplier /= 10)) {
+ t->tv_nsec += (*p - '0') * multiplier;
+ }
+ return p;
+}
+
+static struct timespec *sumTimespec(struct timespec *left,
+ struct timespec *right)
+{
+ left->tv_nsec += right->tv_nsec;
+ left->tv_sec += right->tv_sec;
+ if (left->tv_nsec >= (long)NS_PER_SEC) {
+ left->tv_nsec -= NS_PER_SEC;
+ left->tv_sec += 1;
+ }
+ return left;
+}
+
+static struct timespec *subTimespec(struct timespec *result,
+ struct timespec *left,
+ struct timespec *right)
+{
+ result->tv_nsec = left->tv_nsec - right->tv_nsec;
+ result->tv_sec = left->tv_sec - right->tv_sec;
+ if (result->tv_nsec < 0) {
+ result->tv_nsec += NS_PER_SEC;
+ result->tv_sec -= 1;
+ }
+ return result;
+}
+
+static long long nsecTimespec(struct timespec *now)
+{
+ return (long long)now->tv_sec * NS_PER_SEC + now->tv_nsec;
+}
+
+static void convertMonotonic(struct timespec *result,
+ const AndroidLogEntry *entry)
+{
+ struct listnode *node;
+ struct conversionList {
+ struct listnode node; /* first */
+ struct timespec time;
+ struct timespec convert;
+ } *list, *next;
+ struct timespec time, convert;
+
+ /* If we do not have a conversion list, build one up */
+ if (list_empty(&convertHead)) {
+ bool suspended_pending = false;
+ struct timespec suspended_monotonic = { 0, 0 };
+ struct timespec suspended_diff = { 0, 0 };
+
+ /*
+ * Read dmesg for _some_ synchronization markers and insert
+ * Anything in the Android Logger before the dmesg logging span will
+ * be highly suspect regarding the monotonic time calculations.
+ */
+ FILE *p = popen("/system/bin/dmesg", "r");
+ if (p) {
+ char *line = NULL;
+ size_t len = 0;
+ while (getline(&line, &len, p) > 0) {
+ static const char suspend[] = "PM: suspend entry ";
+ static const char resume[] = "PM: suspend exit ";
+ static const char healthd[] = "healthd";
+ static const char battery[] = ": battery ";
+ static const char suspended[] = "Suspended for ";
+ struct timespec monotonic;
+ struct tm tm;
+ char *cp, *e = line;
+ bool add_entry = true;
+
+ if (*e == '<') {
+ while (*e && (*e != '>')) {
+ ++e;
+ }
+ if (*e != '>') {
+ continue;
+ }
+ }
+ if (*e != '[') {
+ continue;
+ }
+ while (*++e == ' ') {
+ ;
+ }
+ e = readSeconds(e, &monotonic);
+ if (!e || (*e != ']')) {
+ continue;
+ }
+
+ if ((e = strstr(e, suspend))) {
+ e += sizeof(suspend) - 1;
+ } else if ((e = strstr(line, resume))) {
+ e += sizeof(resume) - 1;
+ } else if (((e = strstr(line, healthd)))
+ && ((e = strstr(e + sizeof(healthd) - 1, battery)))) {
+ /* NB: healthd is roughly 150us late, worth the price to
+ * deal with ntp-induced or hardware clock drift. */
+ e += sizeof(battery) - 1;
+ } else if ((e = strstr(line, suspended))) {
+ e += sizeof(suspended) - 1;
+ e = readSeconds(e, &time);
+ if (!e) {
+ continue;
+ }
+ add_entry = false;
+ suspended_pending = true;
+ suspended_monotonic = monotonic;
+ suspended_diff = time;
+ } else {
+ continue;
+ }
+ if (add_entry) {
+ /* look for "????-??-?? ??:??:??.????????? UTC" */
+ cp = strstr(e, " UTC");
+ if (!cp || ((cp - e) < 29) || (cp[-10] != '.')) {
+ continue;
+ }
+ e = cp - 29;
+ cp = readSeconds(cp - 10, &time);
+ if (!cp) {
+ continue;
+ }
+ cp = strptime(e, "%Y-%m-%d %H:%M:%S.", &tm);
+ if (!cp) {
+ continue;
+ }
+ cp = getenv(tz);
+ if (cp) {
+ cp = strdup(cp);
+ }
+ setenv(tz, utc, 1);
+ time.tv_sec = mktime(&tm);
+ if (cp) {
+ setenv(tz, cp, 1);
+ free(cp);
+ } else {
+ unsetenv(tz);
+ }
+ list = calloc(1, sizeof(struct conversionList));
+ list_init(&list->node);
+ list->time = time;
+ subTimespec(&list->convert, &time, &monotonic);
+ list_add_tail(&convertHead, &list->node);
+ }
+ if (suspended_pending && !list_empty(&convertHead)) {
+ list = node_to_item(list_tail(&convertHead),
+ struct conversionList, node);
+ if (subTimespec(&time,
+ subTimespec(&time,
+ &list->time,
+ &list->convert),
+ &suspended_monotonic)->tv_sec > 0) {
+ /* resume, what is convert factor before? */
+ subTimespec(&convert, &list->convert, &suspended_diff);
+ } else {
+ /* suspend */
+ convert = list->convert;
+ }
+ time = suspended_monotonic;
+ sumTimespec(&time, &convert);
+ /* breakpoint just before sleep */
+ list = calloc(1, sizeof(struct conversionList));
+ list_init(&list->node);
+ list->time = time;
+ list->convert = convert;
+ list_add_tail(&convertHead, &list->node);
+ /* breakpoint just after sleep */
+ list = calloc(1, sizeof(struct conversionList));
+ list_init(&list->node);
+ list->time = time;
+ sumTimespec(&list->time, &suspended_diff);
+ list->convert = convert;
+ sumTimespec(&list->convert, &suspended_diff);
+ list_add_tail(&convertHead, &list->node);
+ suspended_pending = false;
+ }
+ }
+ pclose(p);
+ }
+ /* last entry is our current time conversion */
+ list = calloc(1, sizeof(struct conversionList));
+ list_init(&list->node);
+ clock_gettime(CLOCK_REALTIME, &list->time);
+ clock_gettime(CLOCK_MONOTONIC, &convert);
+ clock_gettime(CLOCK_MONOTONIC, &time);
+ /* Correct for instant clock_gettime latency (syscall or ~30ns) */
+ subTimespec(&time, &convert, subTimespec(&time, &time, &convert));
+ /* Calculate conversion factor */
+ subTimespec(&list->convert, &list->time, &time);
+ list_add_tail(&convertHead, &list->node);
+ if (suspended_pending) {
+ /* manufacture a suspend @ point before */
+ subTimespec(&convert, &list->convert, &suspended_diff);
+ time = suspended_monotonic;
+ sumTimespec(&time, &convert);
+ /* breakpoint just after sleep */
+ list = calloc(1, sizeof(struct conversionList));
+ list_init(&list->node);
+ list->time = time;
+ sumTimespec(&list->time, &suspended_diff);
+ list->convert = convert;
+ sumTimespec(&list->convert, &suspended_diff);
+ list_add_head(&convertHead, &list->node);
+ /* breakpoint just before sleep */
+ list = calloc(1, sizeof(struct conversionList));
+ list_init(&list->node);
+ list->time = time;
+ list->convert = convert;
+ list_add_head(&convertHead, &list->node);
+ }
+ }
+
+ /* Find the breakpoint in the conversion list */
+ list = node_to_item(list_head(&convertHead), struct conversionList, node);
+ next = NULL;
+ list_for_each(node, &convertHead) {
+ next = node_to_item(node, struct conversionList, node);
+ if (entry->tv_sec < next->time.tv_sec) {
+ break;
+ } else if (entry->tv_sec == next->time.tv_sec) {
+ if (entry->tv_nsec < next->time.tv_nsec) {
+ break;
+ }
+ }
+ list = next;
+ }
+
+ /* blend time from one breakpoint to the next */
+ convert = list->convert;
+ if (next) {
+ unsigned long long total, run;
+
+ total = nsecTimespec(subTimespec(&time, &next->time, &list->time));
+ time.tv_sec = entry->tv_sec;
+ time.tv_nsec = entry->tv_nsec;
+ run = nsecTimespec(subTimespec(&time, &time, &list->time));
+ if (run < total) {
+ long long crun;
+
+ float f = nsecTimespec(subTimespec(&time, &next->convert, &convert));
+ f *= run;
+ f /= total;
+ crun = f;
+ convert.tv_sec += crun / (long long)NS_PER_SEC;
+ if (crun < 0) {
+ convert.tv_nsec -= (-crun) % NS_PER_SEC;
+ if (convert.tv_nsec < 0) {
+ convert.tv_nsec += NS_PER_SEC;
+ convert.tv_sec -= 1;
+ }
+ } else {
+ convert.tv_nsec += crun % NS_PER_SEC;
+ if (convert.tv_nsec >= (long)NS_PER_SEC) {
+ convert.tv_nsec -= NS_PER_SEC;
+ convert.tv_sec += 1;
+ }
+ }
+ }
+ }
+
+ /* Apply the correction factor */
+ result->tv_sec = entry->tv_sec;
+ result->tv_nsec = entry->tv_nsec;
+ subTimespec(result, result, &convert);
+}
+
/**
* Formats a log message into a buffer
*
@@ -936,7 +1238,9 @@
char prefixBuf[128], suffixBuf[128];
char priChar;
int prefixSuffixIsHeaderFooter = 0;
- char * ret = NULL;
+ char *ret = NULL;
+ time_t now;
+ unsigned long nsec;
priChar = filterPriToChar(entry->priority);
size_t prefixLen = 0, suffixLen = 0;
@@ -954,23 +1258,41 @@
* The caller may have affected the timezone environment, this is
* expected to be sensitive to that.
*/
+ now = entry->tv_sec;
+ nsec = entry->tv_nsec;
+ if (p_format->monotonic_output) {
+ struct timespec time;
+ convertMonotonic(&time, entry);
+ now = time.tv_sec;
+ nsec = time.tv_nsec;
+ }
+ if (now < 0) {
+ nsec = NS_PER_SEC - nsec;
+ }
+ if (p_format->epoch_output || p_format->monotonic_output) {
+ ptm = NULL;
+ snprintf(timeBuf, sizeof(timeBuf),
+ p_format->monotonic_output ? "%6lld" : "%19lld",
+ (long long)now);
+ } else {
#if !defined(_WIN32)
- ptm = localtime_r(&(entry->tv_sec), &tmBuf);
+ ptm = localtime_r(&now, &tmBuf);
#else
- ptm = localtime(&(entry->tv_sec));
+ ptm = localtime(&now);
#endif
- strftime(timeBuf, sizeof(timeBuf),
- &"%Y-%m-%d %H:%M:%S"[p_format->year_output ? 0 : 3],
- ptm);
+ strftime(timeBuf, sizeof(timeBuf),
+ &"%Y-%m-%d %H:%M:%S"[p_format->year_output ? 0 : 3],
+ ptm);
+ }
len = strlen(timeBuf);
if (p_format->usec_time_output) {
len += snprintf(timeBuf + len, sizeof(timeBuf) - len,
- ".%06ld", entry->tv_nsec / 1000);
+ ".%06ld", nsec / US_PER_NSEC);
} else {
len += snprintf(timeBuf + len, sizeof(timeBuf) - len,
- ".%03ld", entry->tv_nsec / 1000000);
+ ".%03ld", nsec / MS_PER_NSEC);
}
- if (p_format->zone_output) {
+ if (p_format->zone_output && ptm) {
strftime(timeBuf + len, sizeof(timeBuf) - len, " %z", ptm);
}
diff --git a/libpixelflinger/include/private/pixelflinger/ggl_context.h b/libpixelflinger/include/private/pixelflinger/ggl_context.h
index d43655c..a18b2f7 100644
--- a/libpixelflinger/include/private/pixelflinger/ggl_context.h
+++ b/libpixelflinger/include/private/pixelflinger/ggl_context.h
@@ -234,7 +234,7 @@
// ----------------------------------------------------------------------------
-class needs_filter_t;
+struct needs_filter_t;
struct needs_t {
inline int match(const needs_filter_t& filter);
inline bool operator == (const needs_t& rhs) const {
diff --git a/libpixelflinger/trap.cpp b/libpixelflinger/trap.cpp
index 80efeff..ea53625 100644
--- a/libpixelflinger/trap.cpp
+++ b/libpixelflinger/trap.cpp
@@ -563,10 +563,10 @@
c->init_y(c, miny);
for (int32_t y = miny; y < maxy; y++) {
- register int32_t ex0 = ey0;
- register int32_t ex1 = ey1;
- register int32_t ex2 = ey2;
- register int32_t xl, xr;
+ int32_t ex0 = ey0;
+ int32_t ex1 = ey1;
+ int32_t ex2 = ey2;
+ int32_t xl, xr;
for (xl=minx ; xl<maxx ; xl++) {
if (ex0>0 && ex1>0 && ex2>0)
break; // all strictly positive
diff --git a/libsparse/simg2img.c b/libsparse/simg2img.c
index 95e9b5b..b9b438e 100644
--- a/libsparse/simg2img.c
+++ b/libsparse/simg2img.c
@@ -40,7 +40,6 @@
int in;
int out;
int i;
- int ret;
struct sparse_file *s;
if (argc < 3) {
@@ -71,10 +70,12 @@
exit(-1);
}
- lseek(out, SEEK_SET, 0);
+ if (lseek(out, 0, SEEK_SET) == -1) {
+ perror("lseek failed");
+ exit(EXIT_FAILURE);
+ }
- ret = sparse_file_write(s, out, false, false, false);
- if (ret < 0) {
+ if (sparse_file_write(s, out, false, false, false) < 0) {
fprintf(stderr, "Cannot write output file\n");
exit(-1);
}
diff --git a/libsparse/sparse_read.c b/libsparse/sparse_read.c
index 9b10293..ec63850 100644
--- a/libsparse/sparse_read.c
+++ b/libsparse/sparse_read.c
@@ -18,6 +18,7 @@
#define _FILE_OFFSET_BITS 64
#define _LARGEFILE64_SOURCE 1
+#include <inttypes.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdbool.h>
@@ -233,7 +234,7 @@
ret = process_raw_chunk(s, chunk_data_size, fd, offset,
chunk_header->chunk_sz, cur_block, crc_ptr);
if (ret < 0) {
- verbose_error(s->verbose, ret, "data block at %lld", offset);
+ verbose_error(s->verbose, ret, "data block at %" PRId64, offset);
return ret;
}
return chunk_header->chunk_sz;
@@ -241,7 +242,7 @@
ret = process_fill_chunk(s, chunk_data_size, fd,
chunk_header->chunk_sz, cur_block, crc_ptr);
if (ret < 0) {
- verbose_error(s->verbose, ret, "fill block at %lld", offset);
+ verbose_error(s->verbose, ret, "fill block at %" PRId64, offset);
return ret;
}
return chunk_header->chunk_sz;
@@ -250,7 +251,7 @@
chunk_header->chunk_sz, cur_block, crc_ptr);
if (chunk_data_size != 0) {
if (ret < 0) {
- verbose_error(s->verbose, ret, "skip block at %lld", offset);
+ verbose_error(s->verbose, ret, "skip block at %" PRId64, offset);
return ret;
}
}
@@ -258,13 +259,13 @@
case CHUNK_TYPE_CRC32:
ret = process_crc32_chunk(fd, chunk_data_size, *crc_ptr);
if (ret < 0) {
- verbose_error(s->verbose, -EINVAL, "crc block at %lld",
+ verbose_error(s->verbose, -EINVAL, "crc block at %" PRId64,
offset);
return ret;
}
return 0;
default:
- verbose_error(s->verbose, -EINVAL, "unknown block %04X at %lld",
+ verbose_error(s->verbose, -EINVAL, "unknown block %04X at %" PRId64,
chunk_header->chunk_type, offset);
}
diff --git a/libutils/LinearTransform.cpp b/libutils/LinearTransform.cpp
index b7d28d4..138ce8b 100644
--- a/libutils/LinearTransform.cpp
+++ b/libutils/LinearTransform.cpp
@@ -21,11 +21,24 @@
#include <utils/LinearTransform.h>
+// disable sanitize as these functions may intentionally overflow (see comments below).
+// the ifdef can be removed when host builds use clang.
+#if defined(__clang__)
+#define ATTRIBUTE_NO_SANITIZE_INTEGER __attribute__((no_sanitize("integer")))
+#else
+#define ATTRIBUTE_NO_SANITIZE_INTEGER
+#endif
+
namespace android {
-template<class T> static inline T ABS(T x) { return (x < 0) ? -x : x; }
+// sanitize failure with T = int32_t and x = 0x80000000
+template<class T>
+ATTRIBUTE_NO_SANITIZE_INTEGER
+static inline T ABS(T x) { return (x < 0) ? -x : x; }
// Static math methods involving linear transformations
+// remote sanitize failure on overflow case.
+ATTRIBUTE_NO_SANITIZE_INTEGER
static bool scale_u64_to_u64(
uint64_t val,
uint32_t N,
@@ -109,6 +122,8 @@
return true;
}
+// at least one known sanitize failure (see comment below)
+ATTRIBUTE_NO_SANITIZE_INTEGER
static bool linear_transform_s64_to_s64(
int64_t val,
int64_t basis1,
@@ -172,7 +187,7 @@
// (scaled_signbit XOR res_signbit)
if (is_neg)
- scaled = -scaled;
+ scaled = -scaled; // known sanitize failure
res = scaled + basis2;
if ((scaled ^ basis2 ^ INT64_MIN) & (scaled ^ res) & INT64_MIN)
@@ -250,6 +265,8 @@
template void LinearTransform::reduce<uint64_t>(uint64_t* N, uint64_t* D);
template void LinearTransform::reduce<uint32_t>(uint32_t* N, uint32_t* D);
+// sanitize failure if *N = 0x80000000
+ATTRIBUTE_NO_SANITIZE_INTEGER
void LinearTransform::reduce(int32_t* N, uint32_t* D) {
if (N && D && *D) {
if (*N < 0) {
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index f1e13a7..3d18f7c 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -588,7 +588,7 @@
// and other interesting attributes from the central directory. These
// will later be compared against values from the local file header.
data->method = cdr->compression_method;
- data->mod_time = cdr->last_mod_time;
+ data->mod_time = cdr->last_mod_date << 16 | cdr->last_mod_time;
data->crc32 = cdr->crc32;
data->compressed_length = cdr->compressed_size;
data->uncompressed_length = cdr->uncompressed_size;
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index 9a3cdb4..32b1a38 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -272,6 +272,7 @@
ASSERT_EQ(static_cast<uint32_t>(17), data.uncompressed_length);
ASSERT_EQ(static_cast<uint32_t>(13), data.compressed_length);
ASSERT_EQ(0x950821c5, data.crc32);
+ ASSERT_EQ(static_cast<uint32_t>(0x438a8005), data.mod_time);
// An entry that doesn't exist. Should be a negative return code.
ZipString absent_name;
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index ddbfb3e..cb9a85b 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -259,8 +259,8 @@
" -r <kbytes> Rotate log every kbytes. Requires -f\n"
" -n <count> Sets max number of rotated logs to <count>, default 4\n"
" -v <format> Sets the log print format, where <format> is:\n\n"
- " brief color long printable process raw tag thread\n"
- " threadtime time usec UTC year zone\n\n"
+ " brief color epoch long monotonic printable process raw\n"
+ " tag thread threadtime time usec UTC year zone\n\n"
" -D print dividers between each log buffer\n"
" -c clear (flush) the entire log and exit\n"
" -d dump the log and then exit (don't block)\n"
@@ -269,7 +269,7 @@
" -T <count> print only the most recent <count> lines (does not imply -d)\n"
" -T '<time>' print most recent lines since specified time (not imply -d)\n"
" count is pure numerical, time is 'MM-DD hh:mm:ss.mmm...'\n"
- " or 'YYYY-MM-DD hh:mm:ss.mmm...' format\n"
+ " 'YYYY-MM-DD hh:mm:ss.mmm...' or 'sssss.mmm...' format\n"
" -g get the size of the log's ring buffer and exit\n"
" -L dump logs from prior to last reboot\n"
" -b <buffer> Request alternate ring buffer, 'main', 'system', 'radio',\n"
@@ -384,7 +384,11 @@
if (ep) {
return ep;
}
- return t.strptime(cp, "%Y-%m-%d %H:%M:%S.%q");
+ ep = t.strptime(cp, "%Y-%m-%d %H:%M:%S.%q");
+ if (ep) {
+ return ep;
+ }
+ return t.strptime(cp, "%s.%q");
}
// Find last logged line in gestalt of all matching existing output files
diff --git a/logd/Android.mk b/logd/Android.mk
index c00061b..feca8d5 100644
--- a/logd/Android.mk
+++ b/logd/Android.mk
@@ -27,7 +27,8 @@
libsysutils \
liblog \
libcutils \
- libbase
+ libbase \
+ libpackagelistparser
# This is what we want to do:
# event_logtags = $(shell \
diff --git a/logd/main.cpp b/logd/main.cpp
index 60262e9..13dda78 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -33,12 +33,14 @@
#include <syslog.h>
#include <unistd.h>
+#include <cstdbool>
#include <memory>
#include <cutils/properties.h>
#include <cutils/sched_policy.h>
#include <cutils/sockets.h>
#include <log/event_tag_map.h>
+#include <packagelistparser/packagelistparser.h>
#include <private/android_filesystem_config.h>
#include <utils/threads.h>
@@ -166,6 +168,19 @@
static bool reinit_running = false;
static LogBuffer *logBuf = NULL;
+static bool package_list_parser_cb(pkg_info *info, void * /* userdata */) {
+
+ bool rc = true;
+ if (info->uid == uid) {
+ name = strdup(info->name);
+ // false to stop processing
+ rc = false;
+ }
+
+ packagelist_free(info);
+ return rc;
+}
+
static void *reinit_thread_start(void * /*obj*/) {
prctl(PR_SET_NAME, "logd.daemon");
set_sched_policy(0, SP_BACKGROUND);
@@ -180,31 +195,8 @@
if (uid) {
name = NULL;
- FILE *fp = fopen("/data/system/packages.list", "r");
- if (fp) {
- // This simple parser is sensitive to format changes in
- // frameworks/base/services/core/java/com/android/server/pm/Settings.java
- // A dependency note has been added to that file to correct
- // this parser.
+ packagelist_parse(package_list_parser_cb, NULL);
- char *buffer = NULL;
- size_t len;
- while (getline(&buffer, &len, fp) > 0) {
- char *userId = strchr(buffer, ' ');
- if (!userId) {
- continue;
- }
- *userId = '\0';
- unsigned long value = strtoul(userId + 1, NULL, 10);
- if (value != uid) {
- continue;
- }
- name = strdup(buffer);
- break;
- }
- free(buffer);
- fclose(fp);
- }
uid = 0;
sem_post(&uidName);
continue;
diff --git a/metricsd/Android.mk b/metricsd/Android.mk
index 8dbaad9..b08c153 100644
--- a/metricsd/Android.mk
+++ b/metricsd/Android.mk
@@ -64,11 +64,11 @@
-fvisibility=default
metrics_includes := external/gtest/include \
$(LOCAL_PATH)/include
-libmetrics_shared_libraries := libchrome libchromeos
+libmetrics_shared_libraries := libchrome libbrillo
metrics_daemon_shared_libraries := $(libmetrics_shared_libraries) \
+ libbrillo-http \
+ libbrillo-dbus \
libchrome-dbus \
- libchromeos-http \
- libchromeos-dbus \
libdbus \
libmetrics \
libprotobuf-cpp-lite \
@@ -120,8 +120,7 @@
# ========================================================
include $(CLEAR_VARS)
LOCAL_MODULE := metrics_daemon
-LOCAL_C_INCLUDES := $(metrics_includes) \
- external/libchromeos
+LOCAL_C_INCLUDES := $(metrics_includes)
LOCAL_CFLAGS := $(metrics_CFLAGS)
LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
LOCAL_CPPFLAGS := $(metrics_CPPFLAGS)
diff --git a/metricsd/libmetrics.gypi b/metricsd/libmetrics.gypi
index 5b90a55..3c8fc7c 100644
--- a/metricsd/libmetrics.gypi
+++ b/metricsd/libmetrics.gypi
@@ -2,8 +2,8 @@
'target_defaults': {
'variables': {
'deps': [
+ 'libbrillo-<(libbase_ver)',
'libchrome-<(libbase_ver)',
- 'libchromeos-<(libbase_ver)',
]
},
'cflags_cc': [
diff --git a/metricsd/metrics.gyp b/metricsd/metrics.gyp
index 276ec78..c9c02d7 100644
--- a/metricsd/metrics.gyp
+++ b/metricsd/metrics.gyp
@@ -3,8 +3,8 @@
'variables': {
'deps': [
'dbus-1',
+ 'libbrillo-<(libbase_ver)',
'libchrome-<(libbase_ver)',
- 'libchromeos-<(libbase_ver)',
]
},
'cflags_cc': [
diff --git a/metricsd/uploader/metrics_log_base.cc b/metricsd/uploader/metrics_log_base.cc
index 311e43a..1a60b4f 100644
--- a/metricsd/uploader/metrics_log_base.cc
+++ b/metricsd/uploader/metrics_log_base.cc
@@ -16,6 +16,7 @@
#include "uploader/metrics_log_base.h"
+#include "base/build_time.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_samples.h"
#include "uploader/metrics_hashes.h"
@@ -82,10 +83,7 @@
int64_t MetricsLogBase::GetBuildTime() {
static int64_t integral_build_time = 0;
if (!integral_build_time) {
- Time time;
- const char* kDateTime = __DATE__ " " __TIME__ " GMT";
- bool result = Time::FromString(kDateTime, &time);
- DCHECK(result);
+ Time time = base::GetBuildTime();
integral_build_time = static_cast<int64_t>(time.ToTimeT());
}
return integral_build_time;
diff --git a/metricsd/uploader/sender_http.h b/metricsd/uploader/sender_http.h
index 6249d90..4f1c08f 100644
--- a/metricsd/uploader/sender_http.h
+++ b/metricsd/uploader/sender_http.h
@@ -23,7 +23,7 @@
#include "uploader/sender.h"
-// Sender implemented using http_utils from libchromeos
+// Sender implemented using http_utils from libbrillo
class HttpSender : public Sender {
public:
explicit HttpSender(std::string server_url);
diff --git a/packagelistparser/Android.mk b/packagelistparser/Android.mk
new file mode 100644
index 0000000..802a3cb
--- /dev/null
+++ b/packagelistparser/Android.mk
@@ -0,0 +1,32 @@
+LOCAL_PATH:= $(call my-dir)
+
+#########################
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libpackagelistparser
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := packagelistparser.c
+LOCAL_COPY_HEADERS_TO := packagelistparser
+LOCAL_COPY_HEADERS := packagelistparser.h
+LOCAL_SHARED_LIBRARIES := liblog
+
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
+
+include $(BUILD_SHARED_LIBRARY)
+
+#########################
+include $(CLEAR_VARS)
+
+
+LOCAL_MODULE := libpackagelistparser
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := packagelistparser.c
+LOCAL_COPY_HEADERS_TO := packagelistparser
+LOCAL_COPY_HEADERS := packagelistparser.h
+LOCAL_STATIC_LIBRARIES := liblog
+
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/packagelistparser/packagelistparser.c b/packagelistparser/packagelistparser.c
new file mode 100644
index 0000000..3e2539c
--- /dev/null
+++ b/packagelistparser/packagelistparser.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2015, Intel Corporation
+ * 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.
+ *
+ * Written by William Roberts <william.c.roberts@intel.com>
+ *
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/limits.h>
+
+#define LOG_TAG "packagelistparser"
+#include <utils/Log.h>
+
+#include "packagelistparser.h"
+
+#define CLOGE(fmt, ...) \
+ do {\
+ IF_ALOGE() {\
+ ALOGE(fmt, ##__VA_ARGS__);\
+ }\
+ } while(0)
+
+static size_t get_gid_cnt(const char *gids)
+{
+ size_t cnt;
+
+ if (*gids == '\0') {
+ return 0;
+ }
+
+ if (!strcmp(gids, "none")) {
+ return 0;
+ }
+
+ for (cnt = 1; gids[cnt]; gids[cnt] == ',' ? cnt++ : *gids++)
+ ;
+
+ return cnt;
+}
+
+static bool parse_gids(char *gids, gid_t *gid_list, size_t *cnt)
+{
+ gid_t gid;
+ char* token;
+ char *endptr;
+ size_t cmp = 0;
+
+ while ((token = strsep(&gids, ",\r\n"))) {
+
+ if (cmp > *cnt) {
+ return false;
+ }
+
+ gid = strtoul(token, &endptr, 10);
+ if (*endptr != '\0') {
+ return false;
+ }
+
+ /*
+ * if unsigned long is greater than size of gid_t,
+ * prevent a truncation based roll-over
+ */
+ if (gid > GID_MAX) {
+ CLOGE("A gid in field \"gid list\" greater than GID_MAX");
+ return false;
+ }
+
+ gid_list[cmp++] = gid;
+ }
+ return true;
+}
+
+extern bool packagelist_parse(pfn_on_package callback, void *userdata)
+{
+
+ FILE *fp;
+ char *cur;
+ char *next;
+ char *endptr;
+ unsigned long tmp;
+ ssize_t bytesread;
+
+ bool rc = false;
+ char *buf = NULL;
+ size_t buflen = 0;
+ unsigned long lineno = 1;
+ const char *errmsg = NULL;
+ struct pkg_info *pkg_info = NULL;
+
+ fp = fopen(PACKAGES_LIST_FILE, "re");
+ if (!fp) {
+ CLOGE("Could not open: \"%s\", error: \"%s\"\n", PACKAGES_LIST_FILE,
+ strerror(errno));
+ return false;
+ }
+
+ while ((bytesread = getline(&buf, &buflen, fp)) > 0) {
+
+ pkg_info = calloc(1, sizeof(*pkg_info));
+ if (!pkg_info) {
+ goto err;
+ }
+
+ next = buf;
+
+ cur = strsep(&next, " \t\r\n");
+ if (!cur) {
+ errmsg = "Could not get next token for \"package name\"";
+ goto err;
+ }
+
+ pkg_info->name = strdup(cur);
+ if (!pkg_info->name) {
+ goto err;
+ }
+
+ cur = strsep(&next, " \t\r\n");
+ if (!cur) {
+ errmsg = "Could not get next token for field \"uid\"";
+ goto err;
+ }
+
+ tmp = strtoul(cur, &endptr, 10);
+ if (*endptr != '\0') {
+ errmsg = "Could not convert field \"uid\" to integer value";
+ goto err;
+ }
+
+ /*
+ * if unsigned long is greater than size of uid_t,
+ * prevent a truncation based roll-over
+ */
+ if (tmp > UID_MAX) {
+ errmsg = "Field \"uid\" greater than UID_MAX";
+ goto err;
+ }
+
+ pkg_info->uid = (uid_t) tmp;
+
+ cur = strsep(&next, " \t\r\n");
+ if (!cur) {
+ errmsg = "Could not get next token for field \"debuggable\"";
+ goto err;
+ }
+
+ tmp = strtoul(cur, &endptr, 10);
+ if (*endptr != '\0') {
+ errmsg = "Could not convert field \"debuggable\" to integer value";
+ goto err;
+ }
+
+ /* should be a valid boolean of 1 or 0 */
+ if (!(tmp == 0 || tmp == 1)) {
+ errmsg = "Field \"debuggable\" is not 0 or 1 boolean value";
+ goto err;
+ }
+
+ pkg_info->debuggable = (bool) tmp;
+
+ cur = strsep(&next, " \t\r\n");
+ if (!cur) {
+ errmsg = "Could not get next token for field \"data dir\"";
+ goto err;
+ }
+
+ pkg_info->data_dir = strdup(cur);
+ if (!pkg_info->data_dir) {
+ goto err;
+ }
+
+ cur = strsep(&next, " \t\r\n");
+ if (!cur) {
+ errmsg = "Could not get next token for field \"seinfo\"";
+ goto err;
+ }
+
+ pkg_info->seinfo = strdup(cur);
+ if (!pkg_info->seinfo) {
+ goto err;
+ }
+
+ cur = strsep(&next, " \t\r\n");
+ if (!cur) {
+ errmsg = "Could not get next token for field \"gid(s)\"";
+ goto err;
+ }
+
+ /*
+ * Parse the gid list, could be in the form of none, single gid or list:
+ * none
+ * gid
+ * gid, gid ...
+ */
+ pkg_info->gids.cnt = get_gid_cnt(cur);
+ if (pkg_info->gids.cnt > 0) {
+
+ pkg_info->gids.gids = calloc(pkg_info->gids.cnt, sizeof(gid_t));
+ if (!pkg_info->gids.gids) {
+ goto err;
+ }
+
+ rc = parse_gids(cur, pkg_info->gids.gids, &pkg_info->gids.cnt);
+ if (!rc) {
+ errmsg = "Could not parse field \"gid list\"";
+ goto err;
+ }
+ }
+
+ rc = callback(pkg_info, userdata);
+ if (rc == false) {
+ /*
+ * We do not log this as this can be intentional from
+ * callback to abort processing. We go to out to not
+ * free the pkg_info
+ */
+ rc = true;
+ goto out;
+ }
+ lineno++;
+ }
+
+ rc = true;
+
+out:
+ free(buf);
+ fclose(fp);
+ return rc;
+
+err:
+ if (errmsg) {
+ CLOGE("Error Parsing \"%s\" on line: %lu for reason: %s",
+ PACKAGES_LIST_FILE, lineno, errmsg);
+ }
+ rc = false;
+ packagelist_free(pkg_info);
+ goto out;
+}
+
+void packagelist_free(pkg_info *info)
+{
+ if (info) {
+ free(info->name);
+ free(info->data_dir);
+ free(info->seinfo);
+ free(info->gids.gids);
+ free(info);
+ }
+}
diff --git a/packagelistparser/packagelistparser.h b/packagelistparser/packagelistparser.h
new file mode 100644
index 0000000..d602c26
--- /dev/null
+++ b/packagelistparser/packagelistparser.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2015, Intel Corporation
+ * 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.
+ *
+ * Written by William Roberts <william.c.roberts@intel.com>
+ *
+ * This is a parser library for parsing the packages.list file generated
+ * by PackageManager service.
+ *
+ * This simple parser is sensitive to format changes in
+ * frameworks/base/services/core/java/com/android/server/pm/Settings.java
+ * A dependency note has been added to that file to correct
+ * this parser.
+ */
+
+#ifndef PACKAGELISTPARSER_H_
+#define PACKAGELISTPARSER_H_
+
+#include <stdbool.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+/** The file containing the list of installed packages on the system */
+#define PACKAGES_LIST_FILE "/data/system/packages.list"
+
+typedef struct pkg_info pkg_info;
+typedef struct gid_list gid_list;
+
+struct gid_list {
+ size_t cnt;
+ gid_t *gids;
+};
+
+struct pkg_info {
+ char *name;
+ uid_t uid;
+ bool debuggable;
+ char *data_dir;
+ char *seinfo;
+ gid_list gids;
+ void *private_data;
+};
+
+/**
+ * Callback function to be used by packagelist_parse() routine.
+ * @param info
+ * The parsed package information
+ * @param userdata
+ * The supplied userdata pointer to packagelist_parse()
+ * @return
+ * true to keep processing, false to stop.
+ */
+typedef bool (*pfn_on_package)(pkg_info *info, void *userdata);
+
+/**
+ * Parses the file specified by PACKAGES_LIST_FILE and invokes the callback on
+ * each entry found. Once the callback is invoked, ownership of the pkg_info pointer
+ * is passed to the callback routine, thus they are required to perform any cleanup
+ * desired.
+ * @param callback
+ * The callback function called on each parsed line of the packages list.
+ * @param userdata
+ * An optional userdata supplied pointer to pass to the callback function.
+ * @return
+ * true on success false on failure.
+ */
+extern bool packagelist_parse(pfn_on_package callback, void *userdata);
+
+/**
+ * Frees a pkg_info structure.
+ * @param info
+ * The struct to free
+ */
+extern void packagelist_free(pkg_info *info);
+
+__END_DECLS
+
+#endif /* PACKAGELISTPARSER_H_ */
diff --git a/rootdir/asan.options b/rootdir/asan.options
index 2f12341..43896a1 100644
--- a/rootdir/asan.options
+++ b/rootdir/asan.options
@@ -1 +1,5 @@
-allow_user_segv_handler=1:detect_odr_violation=0:alloc_dealloc_mismatch=0:allocator_may_return_null=1
+allow_user_segv_handler=1
+detect_odr_violation=0
+alloc_dealloc_mismatch=0
+allocator_may_return_null=1
+detect_container_overflow=0
diff --git a/sdcard/Android.mk b/sdcard/Android.mk
index cb3a8fb..c5f3d1d 100644
--- a/sdcard/Android.mk
+++ b/sdcard/Android.mk
@@ -5,7 +5,6 @@
LOCAL_SRC_FILES := sdcard.c
LOCAL_MODULE := sdcard
LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror
-
-LOCAL_SHARED_LIBRARIES := libcutils
+LOCAL_SHARED_LIBRARIES := libcutils libpackagelistparser
include $(BUILD_EXECUTABLE)
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index d2d2315..b6bbe7e 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -24,6 +24,7 @@
#include <limits.h>
#include <linux/fuse.h>
#include <pthread.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -34,6 +35,7 @@
#include <sys/stat.h>
#include <sys/statfs.h>
#include <sys/time.h>
+#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
@@ -41,6 +43,7 @@
#include <cutils/hashmap.h>
#include <cutils/log.h>
#include <cutils/multiuser.h>
+#include <packagelistparser/packagelistparser.h>
#include <private/android_filesystem_config.h>
@@ -103,9 +106,6 @@
* or that a reply has already been written. */
#define NO_STATUS 1
-/* Path to system-provided mapping of package name to appIds */
-static const char* const kPackagesListFile = "/data/system/packages.list";
-
/* Supplementary groups to execute with */
static const gid_t kGroups[1] = { AID_PACKAGE_INFO };
@@ -1636,35 +1636,27 @@
return true;
}
-static int read_package_list(struct fuse_global* global) {
+static bool package_parse_callback(pkg_info *info, void *userdata) {
+ struct fuse_global *global = (struct fuse_global *)userdata;
+
+ char* name = strdup(info->name);
+ hashmapPut(global->package_to_appid, name, (void*) (uintptr_t) info->uid);
+ packagelist_free(info);
+ return true;
+}
+
+static bool read_package_list(struct fuse_global* global) {
pthread_mutex_lock(&global->lock);
hashmapForEach(global->package_to_appid, remove_str_to_int, global->package_to_appid);
- FILE* file = fopen(kPackagesListFile, "r");
- if (!file) {
- ERROR("failed to open package list: %s\n", strerror(errno));
- pthread_mutex_unlock(&global->lock);
- return -1;
- }
-
- char buf[512];
- while (fgets(buf, sizeof(buf), file) != NULL) {
- char package_name[512];
- int appid;
- char gids[512];
-
- if (sscanf(buf, "%s %d %*d %*s %*s %s", package_name, &appid, gids) == 3) {
- char* package_name_dup = strdup(package_name);
- hashmapPut(global->package_to_appid, package_name_dup, (void*) (uintptr_t) appid);
- }
- }
-
+ bool rc = packagelist_parse(package_parse_callback, global);
TRACE("read_package_list: found %zu packages\n",
hashmapSize(global->package_to_appid));
- fclose(file);
+
pthread_mutex_unlock(&global->lock);
- return 0;
+
+ return rc;
}
static void watch_package_list(struct fuse_global* global) {
@@ -1680,11 +1672,11 @@
bool active = false;
while (1) {
if (!active) {
- int res = inotify_add_watch(nfd, kPackagesListFile, IN_DELETE_SELF);
+ int res = inotify_add_watch(nfd, PACKAGES_LIST_FILE, IN_DELETE_SELF);
if (res == -1) {
if (errno == ENOENT || errno == EACCES) {
/* Framework may not have created yet, sleep and retry */
- ERROR("missing packages.list; retrying\n");
+ ERROR("missing \"%s\"; retrying\n", PACKAGES_LIST_FILE);
sleep(3);
continue;
} else {
@@ -1695,8 +1687,8 @@
/* Watch above will tell us about any future changes, so
* read the current state. */
- if (read_package_list(global) == -1) {
- ERROR("read_package_list failed: %s\n", strerror(errno));
+ if (read_package_list(global) == false) {
+ ERROR("read_package_list failed\n");
return;
}
active = true;
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 579d26e..52716e9 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -31,7 +31,6 @@
dd \
OUR_TOOLS := \
- df \
getevent \
iftop \
ioctl \
diff --git a/toolbox/df.c b/toolbox/df.c
deleted file mode 100644
index 9cd0743..0000000
--- a/toolbox/df.c
+++ /dev/null
@@ -1,85 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/statfs.h>
-
-static int ok = EXIT_SUCCESS;
-
-static void printsize(long long n)
-{
- char unit = 'K';
- long long t;
-
- n *= 10;
-
- if (n > 1024*1024*10) {
- n /= 1024;
- unit = 'M';
- }
-
- if (n > 1024*1024*10) {
- n /= 1024;
- unit = 'G';
- }
-
- t = (n + 512) / 1024;
- printf("%4lld.%1lld%c", t/10, t%10, unit);
-}
-
-static void df(char *s, int always) {
- struct statfs st;
-
- if (statfs(s, &st) < 0) {
- fprintf(stderr, "%s: %s\n", s, strerror(errno));
- ok = EXIT_FAILURE;
- } else {
- if (st.f_blocks == 0 && !always)
- return;
- printf("%-20s ", s);
- printsize((long long)st.f_blocks * (long long)st.f_bsize);
- printf(" ");
- printsize((long long)(st.f_blocks - (long long)st.f_bfree) * st.f_bsize);
- printf(" ");
- printsize((long long)st.f_bfree * (long long)st.f_bsize);
- printf(" %d\n", (int) st.f_bsize);
- }
-}
-
-int df_main(int argc, char *argv[]) {
- printf("Filesystem Size Used Free Blksize\n");
- if (argc == 1) {
- char s[2000];
- FILE *f = fopen("/proc/mounts", "r");
-
- while (fgets(s, 2000, f)) {
- char *c, *e = s;
-
- for (c = s; *c; c++) {
- if (*c == ' ') {
- e = c + 1;
- break;
- }
- }
-
- for (c = e; *c; c++) {
- if (*c == ' ') {
- *c = '\0';
- break;
- }
- }
-
- df(e, 0);
- }
-
- fclose(f);
- } else {
- int i;
-
- for (i = 1; i < argc; i++) {
- df(argv[i], 1);
- }
- }
-
- exit(ok);
-}