Merge "metricsd: Don't cache the metrics status in the daemon."
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index 63cb3c3..984910d 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -195,14 +195,15 @@
adb_sleep_ms(3000);
// fall through to _adb_connect
} else {
- // if server was running, check its version to make sure it is not out of date
+ // If a server is already running, check its version matches.
int version = ADB_SERVER_VERSION - 1;
- // if we have a file descriptor, then parse version result
+ // If we have a file descriptor, then parse version result.
if (fd >= 0) {
std::string version_string;
if (!ReadProtocolString(fd, &version_string, error)) {
- goto error;
+ adb_close(fd);
+ return -1;
}
adb_close(fd);
@@ -214,8 +215,8 @@
return -1;
}
} else {
- // if fd is -1, then check for "unknown host service",
- // which would indicate a version of adb that does not support the
+ // If fd is -1 check for "unknown host service" which would
+ // indicate a version of adb that does not support the
// version command, in which case we should fall-through to kill it.
if (*error != "unknown host service") {
return fd;
@@ -223,7 +224,8 @@
}
if (version != ADB_SERVER_VERSION) {
- printf("adb server is out of date. killing...\n");
+ printf("adb server version (%d) doesn't match this client (%d); killing...\n",
+ version, ADB_SERVER_VERSION);
fd = _adb_connect("host:kill", error);
if (fd >= 0) {
adb_close(fd);
@@ -253,9 +255,6 @@
D("adb_connect: return fd %d", fd);
return fd;
-error:
- adb_close(fd);
- return -1;
}
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index 9bc634c..5513e8f 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -25,6 +25,7 @@
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
+#include <unistd.h>
#include <utime.h>
#include <memory>
@@ -37,6 +38,7 @@
#include "adb_utils.h"
#include "file_sync_service.h"
+#include <base/file.h>
#include <base/strings.h>
#include <base/stringprintf.h>
@@ -46,8 +48,6 @@
char data[SYNC_DATA_MAX];
};
-static syncsendbuf send_buffer;
-
static long long NOW() {
struct timeval tv;
gettimeofday(&tv, 0);
@@ -69,26 +69,6 @@
fflush(stderr);
}
-static bool SendRequest(int fd, int id, const char* path) {
- size_t path_length = strlen(path);
- if (path_length > 1024) {
- fprintf(stderr, "SendRequest failed: path too long: %zu", 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] __attribute__((aligned(8)));
- SyncRequest* req = reinterpret_cast<SyncRequest*>(buf);
- req->id = id;
- req->path_length = path_length;
- char* data = reinterpret_cast<char*>(req + 1);
- memcpy(data, path, path_length);
-
- return WriteFdExactly(fd, buf, sizeof(buf));
-}
-
class SyncConnection {
public:
SyncConnection() : total_bytes(0), start_time_(NOW()) {
@@ -111,6 +91,93 @@
bool IsValid() { return fd >= 0; }
+ 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);
+ 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);
+ 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));
+ }
+
+ // Sending header, payload, and footer in a single write makes a huge
+ // difference to "adb sync" performance.
+ bool SendSmallFile(const char* path_and_mode,
+ const char* data, size_t data_length,
+ unsigned mtime) {
+ size_t path_length = strlen(path_and_mode);
+ if (path_length > 1024) {
+ fprintf(stderr, "SendSmallFile failed: path too long: %zu", path_length);
+ errno = ENAMETOOLONG;
+ return false;
+ }
+
+ char buf[sizeof(SyncRequest) + path_length +
+ sizeof(SyncRequest) + data_length +
+ sizeof(SyncRequest)];
+ char* p = buf;
+
+ SyncRequest* req_send = reinterpret_cast<SyncRequest*>(p);
+ req_send->id = ID_SEND;
+ req_send->path_length = path_length;
+ p += sizeof(SyncRequest);
+ memcpy(p, path_and_mode, path_length);
+ p += path_length;
+
+ SyncRequest* req_data = reinterpret_cast<SyncRequest*>(p);
+ req_data->id = ID_DATA;
+ req_data->path_length = data_length;
+ p += sizeof(SyncRequest);
+ memcpy(p, data, data_length);
+ p += data_length;
+
+ SyncRequest* req_done = reinterpret_cast<SyncRequest*>(p);
+ req_done->id = ID_DONE;
+ req_done->path_length = mtime;
+ p += sizeof(SyncRequest);
+
+ if (!WriteFdExactly(fd, buf, (p-buf))) return false;
+
+ total_bytes += data_length;
+ return true;
+ }
+
+ 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",
+ from, to, strerror(errno));
+ return false;
+ }
+ if (msg.status.id == ID_OKAY) {
+ return true;
+ }
+ if (msg.status.id != ID_FAIL) {
+ fprintf(stderr, "failed to copy '%s' to '%s': unknown reason\n", from, to);
+ 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",
+ from, to, strerror(errno));
+ return false;
+ }
+ buffer[msg.status.msglen] = 0;
+ fprintf(stderr, "failed to copy '%s' to '%s': %s\n", from, to, buffer);
+ return false;
+ }
+
uint64_t total_bytes;
// TODO: add a char[max] buffer here, to replace syncsendbuf...
@@ -121,7 +188,7 @@
uint64_t start_time_;
void SendQuit() {
- SendRequest(fd, ID_QUIT, ""); // TODO: add a SendResponse?
+ SendRequest(ID_QUIT, ""); // TODO: add a SendResponse?
}
void ShowTransferRate() {
@@ -136,12 +203,12 @@
typedef void (*sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char* name, void* cookie);
-static bool sync_ls(int fd, const char* path, sync_ls_cb func, void* cookie) {
- if (!SendRequest(fd, ID_LIST, path)) return false;
+static bool sync_ls(SyncConnection& sc, const char* path, sync_ls_cb func, void* cookie) {
+ if (!sc.SendRequest(ID_LIST, path)) return false;
while (true) {
syncmsg msg;
- if (!ReadFdExactly(fd, &msg.dent, sizeof(msg.dent))) return false;
+ if (!ReadFdExactly(sc.fd, &msg.dent, sizeof(msg.dent))) return false;
if (msg.dent.id == ID_DONE) return true;
if (msg.dent.id != ID_DENT) return false;
@@ -150,17 +217,13 @@
if (len > 256) return false; // TODO: resize buffer? continue?
char buf[257];
- if (!ReadFdExactly(fd, buf, len)) return false;
+ if (!ReadFdExactly(sc.fd, buf, len)) return false;
buf[len] = 0;
func(msg.dent.mode, msg.dent.size, msg.dent.time, buf, cookie);
}
}
-static bool sync_start_stat(SyncConnection& sc, const char* path) {
- return SendRequest(sc.fd, ID_STAT, path);
-}
-
static bool sync_finish_stat(SyncConnection& sc, unsigned int* timestamp,
unsigned int* mode, unsigned int* size) {
syncmsg msg;
@@ -177,10 +240,17 @@
static bool sync_stat(SyncConnection& sc, const char* path,
unsigned int* timestamp, unsigned int* mode, unsigned int* size) {
- return sync_start_stat(sc, path) && sync_finish_stat(sc, timestamp, mode, size);
+ return sc.SendRequest(ID_STAT, path) && sync_finish_stat(sc, timestamp, mode, size);
}
-static bool write_data_file(SyncConnection& sc, const char* path, syncsendbuf* sbuf, bool show_progress) {
+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",
+ path_and_mode, strerror(errno));
+ return false;
+ }
+
unsigned long long size = 0;
if (show_progress) {
// Determine local file size.
@@ -199,9 +269,10 @@
return false;
}
- sbuf->id = ID_DATA;
+ syncsendbuf sbuf;
+ sbuf.id = ID_DATA;
while (true) {
- int ret = adb_read(lfd, sbuf->data, sc.max);
+ 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));
@@ -211,8 +282,8 @@
break;
}
- sbuf->size = ret;
- if (!WriteFdExactly(sc.fd, sbuf, sizeof(unsigned) * 2 + ret)) {
+ sbuf.size = ret;
+ if (!WriteFdExactly(sc.fd, &sbuf, sizeof(unsigned) * 2 + ret)) {
adb_close(lfd);
return false;
}
@@ -224,103 +295,77 @@
}
adb_close(lfd);
- return true;
-}
-
-#if defined(_WIN32)
-extern bool write_data_link(SyncConnection& sc, const char* path, syncsendbuf* sbuf) __attribute__((error("no symlinks on Windows")));
-#else
-static bool write_data_link(SyncConnection& sc, const char* path, syncsendbuf* sbuf) {
- ssize_t len = readlink(path, sbuf->data, sc.max - 1);
- if (len < 0) {
- fprintf(stderr, "error reading link '%s': %s\n", path, strerror(errno));
- return false;
- }
- sbuf->data[len] = '\0';
-
- sbuf->size = len + 1;
- sbuf->id = ID_DATA;
-
- if (!WriteFdExactly(sc.fd, sbuf, sizeof(unsigned) * 2 + len + 1)) {
- return false;
- }
-
- sc.total_bytes += len + 1;
-
- return true;
-}
-#endif
-
-static bool sync_send(SyncConnection& sc, const char *lpath, const char *rpath,
- unsigned mtime, mode_t mode, bool show_progress)
-{
- syncsendbuf* sbuf = &send_buffer;
-
- std::string path_and_mode = android::base::StringPrintf("%s,%d", rpath, mode);
- if (!SendRequest(sc.fd, ID_SEND, path_and_mode.c_str())) {
- fprintf(stderr, "failed to send ID_SEND message '%s': %s\n",
- path_and_mode.c_str(), strerror(errno));
- return false;
- }
-
- if (S_ISREG(mode)) {
- if (!write_data_file(sc, lpath, sbuf, show_progress)) return false;
- } else if (S_ISLNK(mode)) {
- if (!write_data_link(sc, lpath, sbuf)) return false;
- } else {
- fprintf(stderr, "local file '%s' has unsupported mode: 0o%o\n", lpath, mode);
- return false;
- }
syncmsg msg;
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", lpath, strerror(errno));
- return false;
- }
-
- if (!ReadFdExactly(sc.fd, &msg.status, sizeof(msg.status))) {
- fprintf(stderr, "failed to read ID_DONE response for '%s': %s\n", lpath, strerror(errno));
- return false;
- }
- if (msg.status.id != ID_OKAY) {
- if (msg.status.id == ID_FAIL) {
- size_t len = msg.status.msglen;
- if (len > 256) len = 256;
- if (!ReadFdExactly(sc.fd, sbuf->data, len)) {
- fprintf(stderr, "failed to read failure reason (!): %s\n", strerror(errno));
- return false;
- }
- sbuf->data[len] = 0;
- } else {
- strcpy(sbuf->data, "unknown reason");
- }
- fprintf(stderr, "failed to copy '%s' to '%s': %s\n", lpath, rpath, sbuf->data);
+ fprintf(stderr, "failed to send ID_DONE message for '%s': %s\n", path, strerror(errno));
return false;
}
return true;
}
-static int sync_recv(SyncConnection& sc, const char* rpath, const char* lpath, bool show_progress) {
+static bool sync_send(SyncConnection& sc, const char* lpath, const char* rpath,
+ unsigned mtime, mode_t mode, bool show_progress)
+{
+ std::string path_and_mode = android::base::StringPrintf("%s,%d", rpath, mode);
+
+ if (S_ISLNK(mode)) {
+#if !defined(_WIN32)
+ 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));
+ return false;
+ }
+ buf[data_length++] = '\0';
+
+ if (!sc.SendSmallFile(path_and_mode.c_str(), buf, data_length, mtime)) return false;
+ return sc.CopyDone(lpath, rpath);
+#endif
+ }
+
+ if (!S_ISREG(mode)) {
+ fprintf(stderr, "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));
+ 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));
+ return false;
+ }
+ if (!sc.SendSmallFile(path_and_mode.c_str(), data.data(), data.size(), mtime)) return false;
+ } else {
+ if (!SendLargeFile(sc, path_and_mode.c_str(), lpath, mtime, show_progress)) return false;
+ }
+ return sc.CopyDone(lpath, rpath);
+}
+
+static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath, bool show_progress) {
syncmsg msg;
int lfd = -1;
- char *buffer = send_buffer.data;
- unsigned id;
size_t len = strlen(rpath);
- if (len > 1024) return -1;
+ if (len > 1024) return false;
unsigned size = 0;
if (show_progress) {
- if (!sync_stat(sc, rpath, nullptr, nullptr, &size)) return -1;
+ if (!sync_stat(sc, rpath, nullptr, nullptr, &size)) return false;
}
- if (!SendRequest(sc.fd, ID_RECV, rpath)) return -1;
- if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) return -1;
+ if (!sc.SendRequest(ID_RECV, rpath)) return false;
+ if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) return false;
- id = msg.data.id;
+ unsigned id = msg.data.id;
if (id == ID_DATA || id == ID_DONE) {
adb_unlink(lpath);
@@ -328,7 +373,7 @@
lfd = adb_creat(lpath, 0644);
if(lfd < 0) {
fprintf(stderr, "cannot create '%s': %s\n", lpath, strerror(errno));
- return -1;
+ return false;
}
goto handle_data;
} else {
@@ -336,9 +381,11 @@
}
while (true) {
- if(!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
+ char buffer[SYNC_DATA_MAX];
+
+ if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
adb_close(lfd);
- return -1;
+ return false;
}
id = msg.data.id;
@@ -349,18 +396,18 @@
if (len > sc.max) {
fprintf(stderr, "msg.data.size too large: %zu (max %zu)\n", len, sc.max);
adb_close(lfd);
- return -1;
+ return false;
}
- if(!ReadFdExactly(sc.fd, buffer, len)) {
+ if (!ReadFdExactly(sc.fd, buffer, len)) {
adb_close(lfd);
- return -1;
+ return false;
}
- if(!WriteFdExactly(lfd, buffer, len)) {
+ if (!WriteFdExactly(lfd, buffer, len)) {
fprintf(stderr, "cannot write '%s': %s\n", rpath, strerror(errno));
adb_close(lfd);
- return -1;
+ return false;
}
sc.total_bytes += len;
@@ -371,25 +418,13 @@
}
adb_close(lfd);
- return 0;
+ return true;
remote_error:
adb_close(lfd);
adb_unlink(lpath);
-
- if(id == ID_FAIL) {
- len = msg.data.size;
- if(len > 256) len = 256;
- if(!ReadFdExactly(sc.fd, buffer, len)) {
- return -1;
- }
- buffer[len] = 0;
- } else {
- memcpy(buffer, &id, 4);
- buffer[4] = 0;
- }
- fprintf(stderr, "failed to copy '%s' to '%s': %s\n", rpath, lpath, buffer);
- return 0;
+ sc.CopyDone(rpath, lpath);
+ return false;
}
static void do_sync_ls_cb(unsigned mode, unsigned size, unsigned time,
@@ -401,7 +436,7 @@
SyncConnection sc;
if (!sc.IsValid()) return false;
- return sync_ls(sc.fd, path, do_sync_ls_cb, 0);
+ return sync_ls(sc, path, do_sync_ls_cb, 0);
}
struct copyinfo
@@ -411,7 +446,7 @@
const char *dst;
unsigned int time;
unsigned int mode;
- unsigned int size;
+ uint64_t size;
int flag;
};
@@ -531,7 +566,7 @@
if (check_timestamps) {
for (ci = filelist; ci != 0; ci = ci->next) {
- if (!sync_start_stat(sc, ci->dst)) return false;
+ if (!sc.SendRequest(ID_STAT, ci->dst)) return false;
}
for(ci = filelist; ci != 0; ci = ci->next) {
unsigned int timestamp, mode, size;
@@ -629,7 +664,7 @@
}
}
-static bool remote_build_list(int syncfd, copyinfo **filelist,
+static bool remote_build_list(SyncConnection& sc, copyinfo **filelist,
const char *rpath, const char *lpath) {
copyinfo *dirlist = NULL;
sync_ls_build_list_cb_args args;
@@ -640,14 +675,14 @@
args.lpath = lpath;
// Put the files/dirs in rpath on the lists.
- if (!sync_ls(syncfd, rpath, sync_ls_build_list_cb, (void *)&args)) {
+ if (!sync_ls(sc, rpath, sync_ls_build_list_cb, (void *)&args)) {
return false;
}
// Recurse into each directory we found.
while (dirlist != NULL) {
copyinfo *next = dirlist->next;
- if (!remote_build_list(syncfd, filelist, dirlist->src, dirlist->dst)) {
+ if (!remote_build_list(sc, filelist, dirlist->src, dirlist->dst)) {
return false;
}
free(dirlist);
@@ -682,7 +717,7 @@
// Recursively build the list of files to copy.
fprintf(stderr, "pull: building file list...\n");
copyinfo* filelist = nullptr;
- if (!remote_build_list(sc.fd, &filelist, rpath_clean.c_str(), lpath_clean.c_str())) return false;
+ if (!remote_build_list(sc, &filelist, rpath_clean.c_str(), lpath_clean.c_str())) return false;
int pulled = 0;
int skipped = 0;
@@ -691,7 +726,7 @@
copyinfo* next = ci->next;
if (ci->flag == 0) {
fprintf(stderr, "pull: %s -> %s\n", ci->src, ci->dst);
- if (sync_recv(sc, ci->src, ci->dst, false)) {
+ if (!sync_recv(sc, ci->src, ci->dst, false)) {
return false;
}
@@ -734,7 +769,7 @@
lpath = path_holder.c_str();
}
}
- if (sync_recv(sc, rpath, lpath, show_progress)) {
+ if (!sync_recv(sc, rpath, lpath, show_progress)) {
return false;
} else {
if (copy_attrs && set_time_and_mode(lpath, time, mode)) {
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index 2b1ec48..42f6d9b 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -659,6 +659,12 @@
SystemErrorCodeToString(err).c_str());
_socket_set_errno(err);
result = -1;
+ } else {
+ // According to https://code.google.com/p/chromium/issues/detail?id=27870
+ // Winsock Layered Service Providers may cause this.
+ CHECK_LE(result, len) << "Tried to write " << len << " bytes to "
+ << f->name << ", but " << result
+ << " bytes reportedly written";
}
return result;
}
@@ -705,6 +711,23 @@
}
}
+// Map a socket type to an explicit socket protocol instead of using the socket
+// protocol of 0. Explicit socket protocols are used by most apps and we should
+// do the same to reduce the chance of exercising uncommon code-paths that might
+// have problems or that might load different Winsock service providers that
+// have problems.
+static int GetSocketProtocolFromSocketType(int type) {
+ switch (type) {
+ case SOCK_STREAM:
+ return IPPROTO_TCP;
+ case SOCK_DGRAM:
+ return IPPROTO_UDP;
+ default:
+ LOG(FATAL) << "Unknown socket type: " << type;
+ return 0;
+ }
+}
+
int network_loopback_client(int port, int type, std::string* error) {
struct sockaddr_in addr;
SOCKET s;
@@ -723,7 +746,7 @@
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- s = socket(AF_INET, type, 0);
+ s = socket(AF_INET, type, GetSocketProtocolFromSocketType(type));
if(s == INVALID_SOCKET) {
*error = android::base::StringPrintf("cannot create socket: %s",
SystemErrorCodeToString(WSAGetLastError()).c_str());
@@ -777,7 +800,7 @@
// TODO: Consider using dual-stack socket that can simultaneously listen on
// IPv4 and IPv6.
- s = socket(AF_INET, type, 0);
+ s = socket(AF_INET, type, GetSocketProtocolFromSocketType(type));
if (s == INVALID_SOCKET) {
*error = android::base::StringPrintf("cannot create socket: %s",
SystemErrorCodeToString(WSAGetLastError()).c_str());
@@ -849,6 +872,7 @@
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = type;
+ hints.ai_protocol = GetSocketProtocolFromSocketType(type);
char port_str[16];
snprintf(port_str, sizeof(port_str), "%d", port);
@@ -952,6 +976,11 @@
errno = EBADF;
return -1;
}
+
+ // TODO: Once we can assume Windows Vista or later, if the caller is trying
+ // to set SOL_SOCKET, SO_SNDBUF/SO_RCVBUF, ignore it since the OS has
+ // auto-tuning.
+
int result = setsockopt( fh->fh_socket, level, optname,
reinterpret_cast<const char*>(optval), optlen );
if ( result == SOCKET_ERROR ) {
diff --git a/liblog/log_is_loggable.c b/liblog/log_is_loggable.c
index 7a8e33f..cd85ff6 100644
--- a/liblog/log_is_loggable.c
+++ b/liblog/log_is_loggable.c
@@ -93,7 +93,7 @@
if (taglen) {
uint32_t current_local_serial = current_global_serial;
- if (!last_tag || strcmp(last_tag, tag)) {
+ if (!last_tag || (last_tag[0] != tag[0]) || strcmp(last_tag + 1, tag + 1)) {
/* invalidate log.tag.<tag> cache */
for(i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
tag_cache[i].pinfo = NULL;
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index 7db17d1..808d17a 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -24,6 +24,7 @@
#include <sys/uio.h>
#include <syslog.h>
+#include <log/logger.h>
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
@@ -153,15 +154,16 @@
// log to events
- size_t l = strlen(str);
+ size_t l = strnlen(str, LOGGER_ENTRY_MAX_PAYLOAD);
size_t n = l + sizeof(android_log_event_string_t);
bool notify = false;
- android_log_event_string_t *event = static_cast<android_log_event_string_t *>(malloc(n));
- if (!event) {
- rc = -ENOMEM;
- } else {
+ { // begin scope for event buffer
+ uint32_t buffer[(n + sizeof(uint32_t) - 1) / sizeof(uint32_t)];
+
+ android_log_event_string_t *event
+ = reinterpret_cast<android_log_event_string_t *>(buffer);
event->header.tag = htole32(AUDITD_LOG_TAG);
event->type = EVENT_TYPE_STRING;
event->length = htole32(l);
@@ -170,11 +172,10 @@
rc = logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid,
reinterpret_cast<char *>(event),
(n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
- free(event);
-
if (rc >= 0) {
notify = true;
}
+ // end scope for event buffer
}
// log to main
@@ -206,24 +207,28 @@
l = strlen(comm) + 1;
ecomm = "";
}
- n = (estr - str) + strlen(ecomm) + l + 2;
+ size_t b = estr - str;
+ if (b > LOGGER_ENTRY_MAX_PAYLOAD) {
+ b = LOGGER_ENTRY_MAX_PAYLOAD;
+ }
+ size_t e = strnlen(ecomm, LOGGER_ENTRY_MAX_PAYLOAD - b);
+ n = b + e + l + 2;
- char *newstr = static_cast<char *>(malloc(n));
- if (!newstr) {
- rc = -ENOMEM;
- } else {
+ { // begin scope for main buffer
+ char newstr[n];
+
*newstr = info ? ANDROID_LOG_INFO : ANDROID_LOG_WARN;
strlcpy(newstr + 1, comm, l);
- strncpy(newstr + 1 + l, str, estr - str);
- strcpy(newstr + 1 + l + (estr - str), ecomm);
+ strncpy(newstr + 1 + l, str, b);
+ strncpy(newstr + 1 + l + b, ecomm, e);
rc = logbuf->log(LOG_ID_MAIN, now, uid, pid, tid, newstr,
(n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
- free(newstr);
if (rc >= 0) {
notify = true;
}
+ // end scope for main buffer
}
free(commfree);
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index 9fb1439..150ce22 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -91,7 +91,8 @@
size_t retval_len = strlen(retval);
size_t name_len = strlen(name);
// KISS: ToDo: Only checks prefix truncated, not suffix, or both
- if ((retval_len < name_len) && !strcmp(retval, name + name_len - retval_len)) {
+ if ((retval_len < name_len)
+ && !fast<strcmp>(retval, name + name_len - retval_len)) {
free(retval);
retval = name;
} else {
@@ -123,14 +124,16 @@
commName = parent->pidToName(mPid);
parent->unlock();
}
- size_t len = name ? strlen(name) : 0;
- if (len && commName && !strncmp(name, commName, len)) {
- if (commName[len] == '\0') {
- free(commName);
- commName = NULL;
- } else {
- free(name);
- name = NULL;
+ if (name && name[0] && commName && (name[0] == commName[0])) {
+ size_t len = strlen(name + 1);
+ if (!strncmp(name + 1, commName + 1, len)) {
+ if (commName[len + 1] == '\0') {
+ free(commName);
+ commName = NULL;
+ } else {
+ free(name);
+ name = NULL;
+ }
}
}
if (name) {
@@ -150,9 +153,9 @@
}
}
// identical to below to calculate the buffer size required
- len = snprintf(NULL, 0, format_uid, mUid, name ? name : "",
- commName ? commName : "",
- mDropped, (mDropped > 1) ? "s" : "");
+ size_t len = snprintf(NULL, 0, format_uid, mUid, name ? name : "",
+ commName ? commName : "",
+ mDropped, (mDropped > 1) ? "s" : "");
size_t hdrLen;
if (mLogId == LOG_ID_EVENTS) {
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index ca2c3a6..30e43c6 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -25,27 +25,6 @@
#include <log/log.h>
#include <log/log_read.h>
-// Hijack this header as a common include file used by most all sources
-// to report some utilities defined here and there.
-
-namespace android {
-
-// Furnished in main.cpp. Caller must own and free returned value
-char *uidToName(uid_t uid);
-
-// Furnished in LogStatistics.cpp. Caller must own and free returned value
-char *pidToName(pid_t pid);
-char *tidToName(pid_t tid);
-
-// Furnished in main.cpp. Thread safe.
-const char *tagToName(uint32_t tag);
-
-}
-
-static inline bool worstUidEnabledForLogid(log_id_t id) {
- return (id != LOG_ID_CRASH) && (id != LOG_ID_KERNEL) && (id != LOG_ID_EVENTS);
-}
-
class LogBuffer;
#define EXPIRE_HOUR_THRESHOLD 24 // Only expire chatty UID logs to preserve
@@ -85,7 +64,7 @@
unsigned short getDropped(void) const { return mMsg ? 0 : mDropped; }
unsigned short setDropped(unsigned short value) {
if (mMsg) {
- free(mMsg);
+ delete [] mMsg;
mMsg = NULL;
}
return mDropped = value;
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index 242d7a0..d28161e 100644
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -306,7 +306,7 @@
}
--len;
} while (*s++ != c);
- } while (memcmp(s, needle, needleLen) != 0);
+ } while (fast<memcmp>(s, needle, needleLen));
s--;
}
return s;
@@ -588,7 +588,7 @@
const char *bt, *et, *cp;
bt = p;
- if (!strncmp(p, "[INFO]", 6)) {
+ if (!fast<strncmp>(p, "[INFO]", 6)) {
// <PRI>[<TIME>] "[INFO]"<tag> ":" message
bt = p + 6;
taglen -= 6;
@@ -612,10 +612,10 @@
p = cp + 1;
} else if (taglen) {
size = et - bt;
- if (strncmp(bt, cp, size)) {
+ if ((*bt == *cp) && fast<strncmp>(bt + 1, cp + 1, size - 1)) {
// <PRI>[<TIME>] <tag>_host '<tag>.<num>' : message
- if (!strncmp(bt + size - 5, "_host", 5)
- && !strncmp(bt, cp, size - 5)) {
+ if (!fast<strncmp>(bt + size - 5, "_host", 5)
+ && !fast<strncmp>(bt + 1, cp + 1, size - 6)) {
const char *b = cp;
cp += size - 5;
taglen -= size - 5;
@@ -694,10 +694,10 @@
// register names like x18 but not driver names like en0
|| ((size == 3) && (isdigit(tag[1]) && isdigit(tag[2])))
// blacklist
- || ((size == 3) && !strncmp(tag, "CPU", 3))
- || ((size == 7) && !strncasecmp(tag, "WARNING", 7))
- || ((size == 5) && !strncasecmp(tag, "ERROR", 5))
- || ((size == 4) && !strncasecmp(tag, "INFO", 4))) {
+ || ((size == 3) && !fast<strncmp>(tag, "CPU", 3))
+ || ((size == 7) && !fast<strncasecmp>(tag, "WARNING", 7))
+ || ((size == 5) && !fast<strncasecmp>(tag, "ERROR", 5))
+ || ((size == 4) && !fast<strncasecmp>(tag, "INFO", 4))) {
p = start;
etag = tag = "";
}
@@ -709,7 +709,7 @@
const char *mp = strnrchr(tag, ']', taglen);
if (mp && (++mp < etag)) {
size_t s = etag - mp;
- if (((s + s) < taglen) && !memcmp(mp, mp - 1 - s, s)) {
+ if (((s + s) < taglen) && !fast<memcmp>(mp, mp - 1 - s, s)) {
taglen = mp - tag;
}
}
@@ -727,6 +727,9 @@
p = " ";
b = 1;
}
+ if (b > LOGGER_ENTRY_MAX_PAYLOAD) {
+ b = LOGGER_ENTRY_MAX_PAYLOAD;
+ }
size_t n = 1 + taglen + 1 + b + 1;
int rc = n;
if ((taglen > n) || (b > n)) { // Can not happen ...
@@ -734,12 +737,7 @@
return rc;
}
- // Allocate a buffer to hold the interpreted log message
- char *newstr = reinterpret_cast<char *>(malloc(n));
- if (!newstr) {
- rc = -ENOMEM;
- return rc;
- }
+ char newstr[n];
char *np = newstr;
// Convert priority into single-byte Android logger priority
@@ -759,7 +757,6 @@
// Log message
rc = logbuf->log(LOG_ID_KERNEL, now, uid, pid, tid, newstr,
(n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
- free(newstr);
// notify readers
if (!rc) {
diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp
index c7deec0..3833843 100644
--- a/logd/LogReader.cpp
+++ b/logd/LogReader.cpp
@@ -95,7 +95,7 @@
}
bool nonBlock = false;
- if (strncmp(buffer, "dumpAndClose", 12) == 0) {
+ if (!fast<strncmp>(buffer, "dumpAndClose", 12)) {
// Allow writer to get some cycles, and wait for pending notifications
sched_yield();
LogTimeEntry::lock();
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index 61fd559..a9c3086 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -51,7 +51,7 @@
if (ret > 0) {
buffer[sizeof(buffer)-1] = '\0';
// frameworks intermediate state
- if (strcmp(buffer, "<pre-initialized>")) {
+ if (fast<strcmp>(buffer, "<pre-initialized>")) {
retval = strdup(buffer);
}
}
@@ -170,7 +170,7 @@
if (n) {
if (!name) {
name = strdup(n);
- } else if (strcmp(name, n)) {
+ } else if (fast<strcmp>(name, n)) {
free(name);
name = NULL;
break;
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 61000d2..5a44d59 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -26,6 +26,7 @@
#include <log/log.h>
#include "LogBufferElement.h"
+#include "LogUtils.h"
#define log_id_for_each(i) \
for (log_id_t i = LOG_ID_MIN; i < LOG_ID_MAX; i = (log_id_t) (i + 1))
@@ -188,7 +189,7 @@
const char*getName() const { return name; }
inline void add(pid_t p) {
- if (name && !strncmp(name, "zygote", 6)) {
+ if (name && !fast<strncmp>(name, "zygote", 6)) {
free(name);
name = NULL;
}
@@ -240,7 +241,7 @@
const char*getName() const { return name; }
inline void add(pid_t t) {
- if (name && !strncmp(name, "zygote", 6)) {
+ if (name && !fast<strncmp>(name, "zygote", 6)) {
free(name);
name = NULL;
}
diff --git a/logd/LogUtils.h b/logd/LogUtils.h
new file mode 100644
index 0000000..533eb1c
--- /dev/null
+++ b/logd/LogUtils.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012-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 _LOGD_LOG_UTILS_H__
+#define _LOGD_LOG_UTILS_H__
+
+#include <sys/types.h>
+
+#include <log/log.h>
+
+// Hijack this header as a common include file used by most all sources
+// to report some utilities defined here and there.
+
+namespace android {
+
+// Furnished in main.cpp. Caller must own and free returned value
+char *uidToName(uid_t uid);
+
+// Furnished in LogStatistics.cpp. Caller must own and free returned value
+char *pidToName(pid_t pid);
+char *tidToName(pid_t tid);
+
+// Furnished in main.cpp. Thread safe.
+const char *tagToName(uint32_t tag);
+
+}
+
+static inline bool worstUidEnabledForLogid(log_id_t id) {
+ return (id != LOG_ID_CRASH) && (id != LOG_ID_KERNEL) && (id != LOG_ID_EVENTS);
+}
+
+template <int (*cmp)(const char *l, const char *r, const size_t s)>
+static inline int fast(const char *l, const char *r, const size_t s) {
+ return (*l != *r) || cmp(l + 1, r + 1, s - 1);
+}
+
+template <int (*cmp)(const void *l, const void *r, const size_t s)>
+static inline int fast(const void *lv, const void *rv, const size_t s) {
+ const char *l = static_cast<const char *>(lv);
+ const char *r = static_cast<const char *>(rv);
+ return (*l != *r) || cmp(l + 1, r + 1, s - 1);
+}
+
+template <int (*cmp)(const char *l, const char *r)>
+static inline int fast(const char *l, const char *r) {
+ return (*l != *r) || cmp(l + 1, r + 1);
+}
+
+#endif // _LOGD_LOG_UTILS_H__
diff --git a/logd/LogWhiteBlackList.h b/logd/LogWhiteBlackList.h
index 00e1cad..6f17402 100644
--- a/logd/LogWhiteBlackList.h
+++ b/logd/LogWhiteBlackList.h
@@ -22,7 +22,7 @@
#include <list>
#include <string.h>
-#include <LogBufferElement.h>
+#include "LogBufferElement.h"
// White and Blacklist
diff --git a/logd/main.cpp b/logd/main.cpp
index cbdf0b6..f0a39b4 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -47,6 +47,7 @@
#include "LogListener.h"
#include "LogAudit.h"
#include "LogKlog.h"
+#include "LogUtils.h"
#define KMSG_PRIORITY(PRI) \
'<', \