Merge "logd: print a message when kicking a client or skipping entries"
diff --git a/liblog/event_tag_map.cpp b/liblog/event_tag_map.cpp
index 22cf43b..2886289 100644
--- a/liblog/event_tag_map.cpp
+++ b/liblog/event_tag_map.cpp
@@ -494,7 +494,7 @@
// Cache miss, go to logd to acquire a public reference.
// Because we lack access to a SHARED PUBLIC /dev/event-log-tags file map?
-static const TagFmt* __getEventTag(EventTagMap* map, unsigned int tag) {
+static const TagFmt* __getEventTag([[maybe_unused]] EventTagMap* map, unsigned int tag) {
// call event tag service to arrange for a new tag
char* buf = NULL;
// Can not use android::base::StringPrintf, asprintf + free instead.
@@ -515,8 +515,9 @@
} else {
size = ret;
}
+#ifdef __ANDROID__
// Ask event log tag service for an existing entry
- if (__send_log_msg(buf, size) >= 0) {
+ if (SendLogdControlMessage(buf, size) >= 0) {
buf[size - 1] = '\0';
char* ep;
unsigned long val = strtoul(buf, &ep, 10); // return size
@@ -529,6 +530,7 @@
}
}
}
+#endif
free(buf);
}
return NULL;
@@ -618,8 +620,9 @@
} else {
size = ret;
}
+#ifdef __ANDROID__
// Ask event log tag service for an allocation
- if (__send_log_msg(buf, size) >= 0) {
+ if (SendLogdControlMessage(buf, size) >= 0) {
buf[size - 1] = '\0';
unsigned long val = strtoul(buf, &cp, 10); // return size
if ((buf != cp) && (val > 0) && (*cp == '\n')) { // truncation OK
@@ -635,6 +638,7 @@
}
}
}
+#endif
free(buf);
}
diff --git a/liblog/fake_log_device.cpp b/liblog/fake_log_device.cpp
index 428a482..f61bbdc 100644
--- a/liblog/fake_log_device.cpp
+++ b/liblog/fake_log_device.cpp
@@ -650,10 +650,6 @@
return fd;
}
-ssize_t __send_log_msg(char*, size_t) {
- return -ENODEV;
-}
-
int __android_log_is_loggable(int prio, const char*, int def) {
int logLevel = def;
return logLevel >= 0 && prio >= logLevel;
diff --git a/liblog/fake_log_device.h b/liblog/fake_log_device.h
index ce54db2..bd2256c 100644
--- a/liblog/fake_log_device.h
+++ b/liblog/fake_log_device.h
@@ -29,7 +29,6 @@
int fakeLogClose(int fd);
ssize_t fakeLogWritev(int fd, const struct iovec* vector, int count);
-ssize_t __send_log_msg(char*, size_t);
int __android_log_is_loggable(int prio, const char*, int def);
int __android_log_is_loggable_len(int prio, const char*, size_t, int def);
int __android_log_is_debuggable();
diff --git a/liblog/log_event_list.cpp b/liblog/log_event_list.cpp
index 7882c96..e9f4a32 100644
--- a/liblog/log_event_list.cpp
+++ b/liblog/log_event_list.cpp
@@ -47,9 +47,6 @@
uint8_t storage[LOGGER_ENTRY_MAX_PAYLOAD];
};
-// TODO(tomcherry): real C++ structs.
-typedef struct android_log_context_internal android_log_context_internal;
-
static void init_context(android_log_context_internal* context, uint32_t tag) {
context->tag = tag;
context->read_write_flag = kAndroidLoggerWrite;
@@ -110,11 +107,9 @@
return 0;
}
-int android_log_reset(android_log_context ctx) {
- android_log_context_internal* context;
+int android_log_reset(android_log_context context) {
uint32_t tag;
- context = (android_log_context_internal*)ctx;
if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
return -EBADF;
}
@@ -126,10 +121,7 @@
return 0;
}
-int android_log_parser_reset(android_log_context ctx, const char* msg, size_t len) {
- android_log_context_internal* context;
-
- context = (android_log_context_internal*)ctx;
+int android_log_parser_reset(android_log_context context, const char* msg, size_t len) {
if (!context || (kAndroidLoggerRead != context->read_write_flag)) {
return -EBADF;
}
@@ -140,10 +132,7 @@
return 0;
}
-int android_log_write_list_begin(android_log_context ctx) {
- android_log_context_internal* context;
-
- context = (android_log_context_internal*)ctx;
+int android_log_write_list_begin(android_log_context context) {
if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
return -EBADF;
}
@@ -174,8 +163,7 @@
return 0;
}
-int android_log_write_int32(android_log_context ctx, int32_t value) {
- android_log_context_internal* context = (android_log_context_internal*)ctx;
+int android_log_write_int32(android_log_context context, int32_t value) {
if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
return -EBADF;
}
@@ -195,8 +183,7 @@
return 0;
}
-int android_log_write_int64(android_log_context ctx, int64_t value) {
- android_log_context_internal* context = (android_log_context_internal*)ctx;
+int android_log_write_int64(android_log_context context, int64_t value) {
if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
return -EBADF;
}
@@ -216,8 +203,7 @@
return 0;
}
-int android_log_write_string8_len(android_log_context ctx, const char* value, size_t maxlen) {
- android_log_context_internal* context = (android_log_context_internal*)ctx;
+int android_log_write_string8_len(android_log_context context, const char* value, size_t maxlen) {
if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
return -EBADF;
}
@@ -252,8 +238,7 @@
return android_log_write_string8_len(ctx, value, MAX_EVENT_PAYLOAD);
}
-int android_log_write_float32(android_log_context ctx, float value) {
- android_log_context_internal* context = (android_log_context_internal*)ctx;
+int android_log_write_float32(android_log_context context, float value) {
if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
return -EBADF;
}
@@ -273,10 +258,7 @@
return 0;
}
-int android_log_write_list_end(android_log_context ctx) {
- android_log_context_internal* context;
-
- context = (android_log_context_internal*)ctx;
+int android_log_write_list_end(android_log_context context) {
if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
return -EBADF;
}
@@ -303,8 +285,7 @@
/*
* Logs the list of elements to the event log.
*/
-int android_log_write_list(android_log_context ctx, log_id_t id) {
- android_log_context_internal* context;
+int android_log_write_list(android_log_context context, log_id_t id) {
const char* msg;
ssize_t len;
@@ -312,7 +293,6 @@
return -EINVAL;
}
- context = (android_log_context_internal*)ctx;
if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
return -EBADF;
}
@@ -337,12 +317,10 @@
: __android_log_security_bwrite(context->tag, msg, len));
}
-int android_log_write_list_buffer(android_log_context ctx, const char** buffer) {
- android_log_context_internal* context;
+int android_log_write_list_buffer(android_log_context context, const char** buffer) {
const char* msg;
ssize_t len;
- context = (android_log_context_internal*)ctx;
if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
return -EBADF;
}
@@ -375,12 +353,10 @@
* this and continues to call this function, the behavior is undefined
* (although it won't crash).
*/
-static android_log_list_element android_log_read_next_internal(android_log_context ctx, int peek) {
+static android_log_list_element android_log_read_next_internal(android_log_context context,
+ int peek) {
android_log_list_element elem;
unsigned pos;
- android_log_context_internal* context;
-
- context = (android_log_context_internal*)ctx;
memset(&elem, 0, sizeof(elem));
diff --git a/liblog/logd_reader.cpp b/liblog/logd_reader.cpp
index 619cf8c..96e7a61 100644
--- a/liblog/logd_reader.cpp
+++ b/liblog/logd_reader.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "logd_reader.h"
+
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
@@ -35,66 +37,8 @@
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
-#include "log_portability.h"
-#include "logd_reader.h"
#include "logger.h"
-static int logdAvailable(log_id_t LogId);
-static int logdVersion(struct android_log_logger* logger,
- struct android_log_transport_context* transp);
-static int logdRead(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp, struct log_msg* log_msg);
-static int logdPoll(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp);
-static void logdClose(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp);
-static int logdClear(struct android_log_logger* logger,
- struct android_log_transport_context* transp);
-static ssize_t logdSetSize(struct android_log_logger* logger,
- struct android_log_transport_context* transp, size_t size);
-static ssize_t logdGetSize(struct android_log_logger* logger,
- struct android_log_transport_context* transp);
-static ssize_t logdGetReadableSize(struct android_log_logger* logger,
- struct android_log_transport_context* transp);
-static ssize_t logdGetPrune(struct android_log_logger_list* logger,
- struct android_log_transport_context* transp, char* buf, size_t len);
-static ssize_t logdSetPrune(struct android_log_logger_list* logger,
- struct android_log_transport_context* transp, char* buf, size_t len);
-static ssize_t logdGetStats(struct android_log_logger_list* logger,
- struct android_log_transport_context* transp, char* buf, size_t len);
-
-struct android_log_transport_read logdLoggerRead = {
- .name = "logd",
- .available = logdAvailable,
- .version = logdVersion,
- .close = logdClose,
- .read = logdRead,
- .poll = logdPoll,
- .clear = logdClear,
- .setSize = logdSetSize,
- .getSize = logdGetSize,
- .getReadableSize = logdGetReadableSize,
- .getPrune = logdGetPrune,
- .setPrune = logdSetPrune,
- .getStats = logdGetStats,
-};
-
-static int logdAvailable(log_id_t logId) {
- if (logId >= LOG_ID_MAX) {
- return -EINVAL;
- }
- if (logId == LOG_ID_SECURITY) {
- uid_t uid = __android_log_uid();
- if (uid != AID_SYSTEM) {
- return -EPERM;
- }
- }
- if (access("/dev/socket/logdw", W_OK) == 0) {
- return 0;
- }
- return -EBADF;
-}
-
// Connects to /dev/socket/<name> and returns the associated fd or returns -1 on error.
// O_CLOEXEC is always set.
static int socket_local_client(const std::string& name, int type) {
@@ -120,8 +64,7 @@
}
/* worker for sending the command to the logger */
-static ssize_t send_log_msg(struct android_log_logger* logger, const char* msg, char* buf,
- size_t buf_size) {
+ssize_t SendLogdControlMessage(char* buf, size_t buf_size) {
ssize_t ret;
size_t len;
char* cp;
@@ -131,10 +74,6 @@
return sock;
}
- if (msg) {
- snprintf(buf, buf_size, msg, logger ? logger->logId : (unsigned)-1);
- }
-
len = strlen(buf) + 1;
ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
if (ret <= 0) {
@@ -185,10 +124,6 @@
return ret;
}
-ssize_t __send_log_msg(char* buf, size_t buf_size) {
- return send_log_msg(NULL, NULL, buf, buf_size);
-}
-
static int check_log_success(char* buf, ssize_t ret) {
if (ret < 0) {
return ret;
@@ -202,19 +137,28 @@
return 0;
}
-static int logdClear(struct android_log_logger* logger,
- struct android_log_transport_context* transp __unused) {
+int android_logger_clear(struct logger* logger) {
+ if (!android_logger_is_logd(logger)) {
+ return -EINVAL;
+ }
+ uint32_t log_id = android_logger_get_id(logger);
char buf[512];
+ snprintf(buf, sizeof(buf), "clear %" PRIu32, log_id);
- return check_log_success(buf, send_log_msg(logger, "clear %d", buf, sizeof(buf)));
+ return check_log_success(buf, SendLogdControlMessage(buf, sizeof(buf)));
}
/* returns the total size of the log's ring buffer */
-static ssize_t logdGetSize(struct android_log_logger* logger,
- struct android_log_transport_context* transp __unused) {
- char buf[512];
+long android_logger_get_log_size(struct logger* logger) {
+ if (!android_logger_is_logd(logger)) {
+ return -EINVAL;
+ }
- ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
+ uint32_t log_id = android_logger_get_id(logger);
+ char buf[512];
+ snprintf(buf, sizeof(buf), "getLogSize %" PRIu32, log_id);
+
+ ssize_t ret = SendLogdControlMessage(buf, sizeof(buf));
if (ret < 0) {
return ret;
}
@@ -226,24 +170,32 @@
return atol(buf);
}
-static ssize_t logdSetSize(struct android_log_logger* logger,
- struct android_log_transport_context* transp __unused, size_t size) {
+int android_logger_set_log_size(struct logger* logger, unsigned long size) {
+ if (!android_logger_is_logd(logger)) {
+ return -EINVAL;
+ }
+
+ uint32_t log_id = android_logger_get_id(logger);
char buf[512];
+ snprintf(buf, sizeof(buf), "setLogSize %" PRIu32 " %lu", log_id, size);
- snprintf(buf, sizeof(buf), "setLogSize %d %zu", logger->logId, size);
-
- return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
+ return check_log_success(buf, SendLogdControlMessage(buf, sizeof(buf)));
}
/*
* returns the readable size of the log's ring buffer (that is, amount of the
* log consumed)
*/
-static ssize_t logdGetReadableSize(struct android_log_logger* logger,
- struct android_log_transport_context* transp __unused) {
- char buf[512];
+long android_logger_get_log_readable_size(struct logger* logger) {
+ if (!android_logger_is_logd(logger)) {
+ return -EINVAL;
+ }
- ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
+ uint32_t log_id = android_logger_get_id(logger);
+ char buf[512];
+ snprintf(buf, sizeof(buf), "getLogSizeUsed %" PRIu32, log_id);
+
+ ssize_t ret = SendLogdControlMessage(buf, sizeof(buf));
if (ret < 0) {
return ret;
}
@@ -255,22 +207,15 @@
return atol(buf);
}
-/*
- * returns the logger version
- */
-static int logdVersion(struct android_log_logger* logger __unused,
- struct android_log_transport_context* transp __unused) {
- uid_t uid = __android_log_uid();
- return ((uid != AID_ROOT) && (uid != AID_LOG) && (uid != AID_SYSTEM)) ? 3 : 4;
+int android_logger_get_log_version(struct logger*) {
+ return 4;
}
-/*
- * returns statistics
- */
-static ssize_t logdGetStats(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp __unused, char* buf,
- size_t len) {
- struct android_log_logger* logger;
+ssize_t android_logger_get_statistics(struct logger_list* logger_list, char* buf, size_t len) {
+ if (logger_list->mode & ANDROID_LOG_PSTORE) {
+ return -EINVAL;
+ }
+
char* cp = buf;
size_t remaining = len;
size_t n;
@@ -280,29 +225,35 @@
remaining -= n;
cp += n;
- logger_for_each(logger, logger_list) {
- n = snprintf(cp, remaining, " %d", logger->logId);
- n = MIN(n, remaining);
- remaining -= n;
- cp += n;
+ for (size_t log_id = 0; log_id < LOG_ID_MAX; ++log_id) {
+ if ((1 << log_id) & logger_list->log_mask) {
+ n = snprintf(cp, remaining, " %zu", log_id);
+ n = MIN(n, remaining);
+ remaining -= n;
+ cp += n;
+ }
}
if (logger_list->pid) {
snprintf(cp, remaining, " pid=%u", logger_list->pid);
}
- return send_log_msg(NULL, NULL, buf, len);
+ return SendLogdControlMessage(buf, len);
+}
+ssize_t android_logger_get_prune_list(struct logger_list* logger_list, char* buf, size_t len) {
+ if (logger_list->mode & ANDROID_LOG_PSTORE) {
+ return -EINVAL;
+ }
+
+ snprintf(buf, len, "getPruneList");
+ return SendLogdControlMessage(buf, len);
}
-static ssize_t logdGetPrune(struct android_log_logger_list* logger_list __unused,
- struct android_log_transport_context* transp __unused, char* buf,
- size_t len) {
- return send_log_msg(NULL, "getPruneList", buf, len);
-}
+int android_logger_set_prune_list(struct logger_list* logger_list, char* buf, size_t len) {
+ if (logger_list->mode & ANDROID_LOG_PSTORE) {
+ return -EINVAL;
+ }
-static ssize_t logdSetPrune(struct android_log_logger_list* logger_list __unused,
- struct android_log_transport_context* transp __unused, char* buf,
- size_t len) {
const char cmd[] = "setPruneList ";
const size_t cmdlen = sizeof(cmd) - 1;
@@ -313,20 +264,14 @@
buf[len - 1] = '\0';
memcpy(buf, cmd, cmdlen);
- return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
+ return check_log_success(buf, SendLogdControlMessage(buf, len));
}
-static int logdOpen(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp) {
- struct android_log_logger* logger;
+static int logdOpen(struct logger_list* logger_list) {
char buffer[256], *cp, c;
int ret, remaining, sock;
- if (!logger_list) {
- return -EINVAL;
- }
-
- sock = atomic_load(&transp->context.sock);
+ sock = atomic_load(&logger_list->fd);
if (sock > 0) {
return sock;
}
@@ -346,12 +291,15 @@
cp += 5;
c = '=';
remaining = sizeof(buffer) - (cp - buffer);
- logger_for_each(logger, logger_list) {
- ret = snprintf(cp, remaining, "%c%u", c, logger->logId);
- ret = MIN(ret, remaining);
- remaining -= ret;
- cp += ret;
- c = ',';
+
+ for (size_t log_id = 0; log_id < LOG_ID_MAX; ++log_id) {
+ if ((1 << log_id) & logger_list->log_mask) {
+ ret = snprintf(cp, remaining, "%c%zu", c, log_id);
+ ret = MIN(ret, remaining);
+ remaining -= ret;
+ cp += ret;
+ c = ',';
+ }
}
if (logger_list->tail) {
@@ -396,7 +344,7 @@
return ret;
}
- ret = atomic_exchange(&transp->context.sock, sock);
+ ret = atomic_exchange(&logger_list->fd, sock);
if ((ret > 0) && (ret != sock)) {
close(ret);
}
@@ -404,15 +352,12 @@
}
/* Read from the selected logs */
-static int logdRead(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp, struct log_msg* log_msg) {
- int ret = logdOpen(logger_list, transp);
+int LogdRead(struct logger_list* logger_list, struct log_msg* log_msg) {
+ int ret = logdOpen(logger_list);
if (ret < 0) {
return ret;
}
- memset(log_msg, 0, sizeof(*log_msg));
-
/* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
ret = TEMP_FAILURE_RETRY(recv(ret, log_msg, LOGGER_ENTRY_MAX_LEN, 0));
if ((logger_list->mode & ANDROID_LOG_NONBLOCK) && ret == 0) {
@@ -425,32 +370,9 @@
return ret;
}
-static int logdPoll(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp) {
- struct pollfd p;
-
- int ret = logdOpen(logger_list, transp);
- if (ret < 0) {
- return ret;
- }
-
- memset(&p, 0, sizeof(p));
- p.fd = ret;
- p.events = POLLIN;
- ret = poll(&p, 1, 20);
- if ((ret > 0) && !(p.revents & POLLIN)) {
- ret = 0;
- }
- if ((ret == -1) && errno) {
- return -errno;
- }
- return ret;
-}
-
/* Close all the logs */
-static void logdClose(struct android_log_logger_list* logger_list __unused,
- struct android_log_transport_context* transp) {
- int sock = atomic_exchange(&transp->context.sock, -1);
+void LogdClose(struct logger_list* logger_list) {
+ int sock = atomic_exchange(&logger_list->fd, -1);
if (sock > 0) {
close(sock);
}
diff --git a/liblog/logd_reader.h b/liblog/logd_reader.h
index 7c53cbb..2d032fa 100644
--- a/liblog/logd_reader.h
+++ b/liblog/logd_reader.h
@@ -18,10 +18,14 @@
#include <unistd.h>
+#include "log/log_read.h"
#include "log_portability.h"
__BEGIN_DECLS
-ssize_t __send_log_msg(char* buf, size_t buf_size);
+int LogdRead(struct logger_list* logger_list, struct log_msg* log_msg);
+void LogdClose(struct logger_list* logger_list);
+
+ssize_t SendLogdControlMessage(char* buf, size_t buf_size);
__END_DECLS
diff --git a/liblog/logger.h b/liblog/logger.h
index 02cad22..9d74d29 100644
--- a/liblog/logger.h
+++ b/liblog/logger.h
@@ -46,84 +46,28 @@
size_t nr);
};
-struct android_log_logger_list;
-struct android_log_transport_context;
-struct android_log_logger;
-
-struct android_log_transport_read {
- const char* name; /* human name to describe the transport */
-
- /* Does not cause resources to be taken */
- int (*available)(log_id_t logId);
- int (*version)(struct android_log_logger* logger,
- struct android_log_transport_context* transp);
- /* Release resources taken by the following interfaces */
- void (*close)(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp);
- /*
- * Expect all to instantiate open automagically on any call,
- * so we do not have an explicit open call.
- */
- int (*read)(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp,
- struct log_msg* log_msg);
- /* Must only be called if not ANDROID_LOG_NONBLOCK (blocking) */
- int (*poll)(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp);
-
- int (*clear)(struct android_log_logger* logger,
- struct android_log_transport_context* transp);
- ssize_t (*setSize)(struct android_log_logger* logger,
- struct android_log_transport_context* transp, size_t size);
- ssize_t (*getSize)(struct android_log_logger* logger,
- struct android_log_transport_context* transp);
- ssize_t (*getReadableSize)(struct android_log_logger* logger,
- struct android_log_transport_context* transp);
-
- ssize_t (*getPrune)(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp, char* buf,
- size_t len);
- ssize_t (*setPrune)(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp, char* buf,
- size_t len);
- ssize_t (*getStats)(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp, char* buf,
- size_t len);
-};
-
-struct android_log_transport_context {
- union android_log_context_union context; /* zero init per-transport context */
-
- struct android_log_transport_read* transport;
- unsigned logMask; /* mask of requested log buffers */
-};
-
-struct android_log_logger_list {
- struct listnode logger;
- android_log_transport_context transport_context;
- bool transport_initialized;
+struct logger_list {
+ atomic_int fd;
int mode;
unsigned int tail;
log_time start;
pid_t pid;
+ uint32_t log_mask;
};
-struct android_log_logger {
- struct listnode node;
- struct android_log_logger_list* parent;
+// Format for a 'logger' entry: uintptr_t where only the bottom 32 bits are used.
+// bit 31: Set if this 'logger' is for logd.
+// bit 30: Set if this 'logger' is for pmsg
+// bits 0-2: the decimal value of the log buffer.
+// Other bits are unused.
- log_id_t logId;
-};
+#define LOGGER_LOGD (1U << 31)
+#define LOGGER_PMSG (1U << 30)
+#define LOGGER_LOG_ID_MASK ((1U << 3) - 1)
-/* assumes caller has structures read-locked, single threaded, or fenced */
-#define logger_for_each(logp, logger_list) \
- for ((logp) = node_to_item((logger_list)->logger.next, \
- struct android_log_logger, node); \
- ((logp) != node_to_item(&(logger_list)->logger, \
- struct android_log_logger, node)) && \
- ((logp)->parent == (logger_list)); \
- (logp) = \
- node_to_item((logp)->node.next, struct android_log_logger, node))
+inline bool android_logger_is_logd(struct logger* logger) {
+ return reinterpret_cast<uintptr_t>(logger) & LOGGER_LOGD;
+}
/* OS specific dribs and drabs */
diff --git a/liblog/logger_read.cpp b/liblog/logger_read.cpp
index e8a89eb..c65501c 100644
--- a/liblog/logger_read.cpp
+++ b/liblog/logger_read.cpp
@@ -21,6 +21,7 @@
#include <pthread.h>
#include <sched.h>
#include <stddef.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -30,223 +31,49 @@
#include <private/android_filesystem_config.h>
#include "log_portability.h"
+#include "logd_reader.h"
#include "logger.h"
-
-/* android_logger_alloc unimplemented, no use case */
-/* android_logger_free not exported */
-static void android_logger_free(struct logger* logger) {
- struct android_log_logger* logger_internal = (struct android_log_logger*)logger;
-
- if (!logger_internal) {
- return;
- }
-
- list_remove(&logger_internal->node);
-
- free(logger_internal);
-}
-
-/* android_logger_alloc unimplemented, no use case */
+#include "pmsg_reader.h"
/* method for getting the associated sublog id */
log_id_t android_logger_get_id(struct logger* logger) {
- return ((struct android_log_logger*)logger)->logId;
+ return static_cast<log_id_t>(reinterpret_cast<uintptr_t>(logger) & LOGGER_LOG_ID_MASK);
}
-static int init_transport_context(struct android_log_logger_list* logger_list) {
+static struct logger_list* android_logger_list_alloc_internal(int mode, unsigned int tail,
+ log_time start, pid_t pid) {
+ auto* logger_list = static_cast<struct logger_list*>(calloc(1, sizeof(struct logger_list)));
if (!logger_list) {
- return -EINVAL;
+ return nullptr;
}
- if (list_empty(&logger_list->logger)) {
- return -EINVAL;
- }
-
- if (logger_list->transport_initialized) {
- return 0;
- }
-
-#if (FAKE_LOG_DEVICE == 0)
- extern struct android_log_transport_read logdLoggerRead;
- extern struct android_log_transport_read pmsgLoggerRead;
-
- struct android_log_transport_read* transport;
- transport = (logger_list->mode & ANDROID_LOG_PSTORE) ? &pmsgLoggerRead : &logdLoggerRead;
-
- struct android_log_logger* logger;
- unsigned logMask = 0;
-
- logger_for_each(logger, logger_list) {
- log_id_t logId = logger->logId;
-
- if (logId == LOG_ID_SECURITY && __android_log_uid() != AID_SYSTEM) {
- continue;
- }
- if (transport->read && (!transport->available || transport->available(logId) >= 0)) {
- logMask |= 1 << logId;
- }
- }
- if (!logMask) {
- return -ENODEV;
- }
-
- logger_list->transport_context.transport = transport;
- logger_list->transport_context.logMask = logMask;
-#endif
- return 0;
-}
-
-#define LOGGER_FUNCTION(logger, def, func, args...) \
- ssize_t ret = -EINVAL; \
- android_log_logger* logger_internal = reinterpret_cast<android_log_logger*>(logger); \
- \
- if (!logger_internal) { \
- return ret; \
- } \
- ret = init_transport_context(logger_internal->parent); \
- if (ret < 0) { \
- return ret; \
- } \
- \
- ret = (def); \
- android_log_transport_context* transport_context = &logger_internal->parent->transport_context; \
- if (transport_context->logMask & (1 << logger_internal->logId) && \
- transport_context->transport && transport_context->transport->func) { \
- ssize_t retval = \
- (transport_context->transport->func)(logger_internal, transport_context, ##args); \
- if (ret >= 0 || ret == (def)) { \
- ret = retval; \
- } \
- } \
- return ret
-
-int android_logger_clear(struct logger* logger) {
- LOGGER_FUNCTION(logger, -ENODEV, clear);
-}
-
-/* returns the total size of the log's ring buffer */
-long android_logger_get_log_size(struct logger* logger) {
- LOGGER_FUNCTION(logger, -ENODEV, getSize);
-}
-
-int android_logger_set_log_size(struct logger* logger, unsigned long size) {
- LOGGER_FUNCTION(logger, -ENODEV, setSize, size);
-}
-
-/*
- * returns the readable size of the log's ring buffer (that is, amount of the
- * log consumed)
- */
-long android_logger_get_log_readable_size(struct logger* logger) {
- LOGGER_FUNCTION(logger, -ENODEV, getReadableSize);
-}
-
-/*
- * returns the logger version
- */
-int android_logger_get_log_version(struct logger* logger) {
- LOGGER_FUNCTION(logger, 4, version);
-}
-
-#define LOGGER_LIST_FUNCTION(logger_list, def, func, args...) \
- android_log_logger_list* logger_list_internal = \
- reinterpret_cast<android_log_logger_list*>(logger_list); \
- \
- ssize_t ret = init_transport_context(logger_list_internal); \
- if (ret < 0) { \
- return ret; \
- } \
- \
- ret = (def); \
- android_log_transport_context* transport_context = &logger_list_internal->transport_context; \
- if (transport_context->transport && transport_context->transport->func) { \
- ssize_t retval = \
- (transport_context->transport->func)(logger_list_internal, transport_context, ##args); \
- if (ret >= 0 || ret == (def)) { \
- ret = retval; \
- } \
- } \
- return ret
-
-/*
- * returns statistics
- */
-ssize_t android_logger_get_statistics(struct logger_list* logger_list, char* buf, size_t len) {
- LOGGER_LIST_FUNCTION(logger_list, -ENODEV, getStats, buf, len);
-}
-
-ssize_t android_logger_get_prune_list(struct logger_list* logger_list, char* buf, size_t len) {
- LOGGER_LIST_FUNCTION(logger_list, -ENODEV, getPrune, buf, len);
-}
-
-int android_logger_set_prune_list(struct logger_list* logger_list, char* buf, size_t len) {
- LOGGER_LIST_FUNCTION(logger_list, -ENODEV, setPrune, buf, len);
-}
-
-struct logger_list* android_logger_list_alloc(int mode, unsigned int tail, pid_t pid) {
- struct android_log_logger_list* logger_list;
-
- logger_list = static_cast<android_log_logger_list*>(calloc(1, sizeof(*logger_list)));
- if (!logger_list) {
- return NULL;
- }
-
- list_init(&logger_list->logger);
logger_list->mode = mode;
+ logger_list->start = start;
logger_list->tail = tail;
logger_list->pid = pid;
- return (struct logger_list*)logger_list;
+ return logger_list;
+}
+
+struct logger_list* android_logger_list_alloc(int mode, unsigned int tail, pid_t pid) {
+ return android_logger_list_alloc_internal(mode, tail, log_time(0, 0), pid);
}
struct logger_list* android_logger_list_alloc_time(int mode, log_time start, pid_t pid) {
- struct android_log_logger_list* logger_list;
-
- logger_list = static_cast<android_log_logger_list*>(calloc(1, sizeof(*logger_list)));
- if (!logger_list) {
- return NULL;
- }
-
- list_init(&logger_list->logger);
- logger_list->mode = mode;
- logger_list->start = start;
- logger_list->pid = pid;
-
- return (struct logger_list*)logger_list;
+ return android_logger_list_alloc_internal(mode, 0, start, pid);
}
-/* android_logger_list_register unimplemented, no use case */
-/* android_logger_list_unregister unimplemented, no use case */
-
/* Open the named log and add it to the logger list */
struct logger* android_logger_open(struct logger_list* logger_list, log_id_t logId) {
- struct android_log_logger_list* logger_list_internal =
- (struct android_log_logger_list*)logger_list;
- struct android_log_logger* logger;
-
- if (!logger_list_internal || (logId >= LOG_ID_MAX)) {
+ if (!logger_list || (logId >= LOG_ID_MAX)) {
return nullptr;
}
- logger_for_each(logger, logger_list_internal) {
- if (logger->logId == logId) {
- return reinterpret_cast<struct logger*>(logger);
- }
- }
+ logger_list->log_mask |= 1 << logId;
- logger = static_cast<android_log_logger*>(calloc(1, sizeof(*logger)));
- if (!logger) {
- return nullptr;
- }
-
- logger->logId = logId;
- list_add_tail(&logger_list_internal->logger, &logger->node);
- logger->parent = logger_list_internal;
-
- // Reset known transport to re-evaluate, since we added a new logger.
- logger_list_internal->transport_initialized = false;
-
- return (struct logger*)logger;
+ uintptr_t logger = logId;
+ logger |= (logger_list->mode & ANDROID_LOG_PSTORE) ? LOGGER_PMSG : LOGGER_LOGD;
+ return reinterpret_cast<struct logger*>(logger);
}
/* Open the single named log and make it part of a new logger list */
@@ -266,11 +93,20 @@
return logger_list;
}
-/* Validate log_msg packet, read function has already been null checked */
-static int android_transport_read(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp,
- struct log_msg* log_msg) {
- int ret = (*transp->transport->read)(logger_list, transp, log_msg);
+int android_logger_list_read(struct logger_list* logger_list, struct log_msg* log_msg) {
+ if (logger_list == nullptr || logger_list->log_mask == 0) {
+ return -EINVAL;
+ }
+
+ int ret = 0;
+
+#if (FAKE_LOG_DEVICE == 0)
+ if (logger_list->mode & ANDROID_LOG_PSTORE) {
+ ret = PmsgRead(logger_list, log_msg);
+ } else {
+ ret = LogdRead(logger_list, log_msg);
+ }
+#endif
if (ret <= 0) {
return ret;
@@ -295,40 +131,19 @@
return ret;
}
-/* Read from the selected logs */
-int android_logger_list_read(struct logger_list* logger_list, struct log_msg* log_msg) {
- struct android_log_logger_list* logger_list_internal =
- (struct android_log_logger_list*)logger_list;
-
- int ret = init_transport_context(logger_list_internal);
- if (ret < 0) {
- return ret;
- }
-
- android_log_transport_context* transport_context = &logger_list_internal->transport_context;
- return android_transport_read(logger_list_internal, transport_context, log_msg);
-}
-
/* Close all the logs */
void android_logger_list_free(struct logger_list* logger_list) {
- struct android_log_logger_list* logger_list_internal =
- (struct android_log_logger_list*)logger_list;
-
- if (logger_list_internal == NULL) {
+ if (logger_list == NULL) {
return;
}
- android_log_transport_context* transport_context = &logger_list_internal->transport_context;
-
- if (transport_context->transport && transport_context->transport->close) {
- (*transport_context->transport->close)(logger_list_internal, transport_context);
+#if (FAKE_LOG_DEVICE == 0)
+ if (logger_list->mode & ANDROID_LOG_PSTORE) {
+ PmsgClose(logger_list);
+ } else {
+ LogdClose(logger_list);
}
+#endif
- while (!list_empty(&logger_list_internal->logger)) {
- struct listnode* node = list_head(&logger_list_internal->logger);
- struct android_log_logger* logger = node_to_item(node, struct android_log_logger, node);
- android_logger_free((struct logger*)logger);
- }
-
- free(logger_list_internal);
+ free(logger_list);
}
diff --git a/liblog/pmsg_reader.cpp b/liblog/pmsg_reader.cpp
index f43ce3a..9390fec 100644
--- a/liblog/pmsg_reader.cpp
+++ b/liblog/pmsg_reader.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "pmsg_reader.h"
+
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
@@ -26,57 +28,7 @@
#include "logger.h"
-static int pmsgAvailable(log_id_t logId);
-static int pmsgVersion(struct android_log_logger* logger,
- struct android_log_transport_context* transp);
-static int pmsgRead(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp, struct log_msg* log_msg);
-static void pmsgClose(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp);
-static int pmsgClear(struct android_log_logger* logger,
- struct android_log_transport_context* transp);
-
-struct android_log_transport_read pmsgLoggerRead = {
- .name = "pmsg",
- .available = pmsgAvailable,
- .version = pmsgVersion,
- .close = pmsgClose,
- .read = pmsgRead,
- .poll = NULL,
- .clear = pmsgClear,
- .setSize = NULL,
- .getSize = NULL,
- .getReadableSize = NULL,
- .getPrune = NULL,
- .setPrune = NULL,
- .getStats = NULL,
-};
-
-static int pmsgAvailable(log_id_t logId) {
- if (logId > LOG_ID_SECURITY) {
- return -EINVAL;
- }
- if (access("/dev/pmsg0", W_OK) == 0) {
- return 0;
- }
- return -EBADF;
-}
-
-static int pmsgClear(struct android_log_logger* logger __unused,
- struct android_log_transport_context* transp __unused) {
- return unlink("/sys/fs/pstore/pmsg-ramoops-0");
-}
-
-/*
- * returns the logger version
- */
-static int pmsgVersion(struct android_log_logger* logger __unused,
- struct android_log_transport_context* transp __unused) {
- return 4;
-}
-
-static int pmsgRead(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp, struct log_msg* log_msg) {
+int PmsgRead(struct logger_list* logger_list, struct log_msg* log_msg) {
ssize_t ret;
off_t current, next;
struct __attribute__((__packed__)) {
@@ -88,7 +40,7 @@
memset(log_msg, 0, sizeof(*log_msg));
- if (atomic_load(&transp->context.fd) <= 0) {
+ if (atomic_load(&logger_list->fd) <= 0) {
int i, fd = open("/sys/fs/pstore/pmsg-ramoops-0", O_RDONLY | O_CLOEXEC);
if (fd < 0) {
@@ -101,7 +53,7 @@
return -errno;
}
}
- i = atomic_exchange(&transp->context.fd, fd);
+ i = atomic_exchange(&logger_list->fd, fd);
if ((i > 0) && (i != fd)) {
close(i);
}
@@ -112,7 +64,7 @@
int fd;
if (preread_count < sizeof(buf)) {
- fd = atomic_load(&transp->context.fd);
+ fd = atomic_load(&logger_list->fd);
if (fd <= 0) {
return -EBADF;
}
@@ -138,7 +90,7 @@
}
preread_count = 0;
- if ((transp->logMask & (1 << buf.l.id)) &&
+ if ((logger_list->log_mask & (1 << buf.l.id)) &&
((!logger_list->start.tv_sec && !logger_list->start.tv_nsec) ||
((logger_list->start.tv_sec <= buf.l.realtime.tv_sec) &&
((logger_list->start.tv_sec != buf.l.realtime.tv_sec) ||
@@ -146,7 +98,7 @@
(!logger_list->pid || (logger_list->pid == buf.p.pid))) {
char* msg = log_msg->entry.msg;
*msg = buf.prio;
- fd = atomic_load(&transp->context.fd);
+ fd = atomic_load(&logger_list->fd);
if (fd <= 0) {
return -EBADF;
}
@@ -170,7 +122,7 @@
return ret + sizeof(buf.prio) + log_msg->entry.hdr_size;
}
- fd = atomic_load(&transp->context.fd);
+ fd = atomic_load(&logger_list->fd);
if (fd <= 0) {
return -EBADF;
}
@@ -178,7 +130,7 @@
if (current < 0) {
return -errno;
}
- fd = atomic_load(&transp->context.fd);
+ fd = atomic_load(&logger_list->fd);
if (fd <= 0) {
return -EBADF;
}
@@ -192,9 +144,8 @@
}
}
-static void pmsgClose(struct android_log_logger_list* logger_list __unused,
- struct android_log_transport_context* transp) {
- int fd = atomic_exchange(&transp->context.fd, 0);
+void PmsgClose(struct logger_list* logger_list) {
+ int fd = atomic_exchange(&logger_list->fd, 0);
if (fd > 0) {
close(fd);
}
@@ -211,8 +162,7 @@
ssize_t __android_log_pmsg_file_read(log_id_t logId, char prio, const char* prefix,
__android_log_pmsg_file_read_fn fn, void* arg) {
ssize_t ret;
- struct android_log_logger_list logger_list;
- struct android_log_transport_context transp;
+ struct logger_list logger_list;
struct content {
struct listnode node;
struct logger_entry entry;
@@ -234,15 +184,14 @@
/* Add just enough clues in logger_list and transp to make API function */
memset(&logger_list, 0, sizeof(logger_list));
- memset(&transp, 0, sizeof(transp));
logger_list.mode = ANDROID_LOG_PSTORE | ANDROID_LOG_NONBLOCK | ANDROID_LOG_RDONLY;
- transp.logMask = (unsigned)-1;
+ logger_list.log_mask = (unsigned)-1;
if (logId != LOG_ID_ANY) {
- transp.logMask = (1 << logId);
+ logger_list.log_mask = (1 << logId);
}
- transp.logMask &= ~((1 << LOG_ID_KERNEL) | (1 << LOG_ID_EVENTS) | (1 << LOG_ID_SECURITY));
- if (!transp.logMask) {
+ logger_list.log_mask &= ~((1 << LOG_ID_KERNEL) | (1 << LOG_ID_EVENTS) | (1 << LOG_ID_SECURITY));
+ if (!logger_list.log_mask) {
return -EINVAL;
}
@@ -268,7 +217,7 @@
/* Read the file content */
log_msg log_msg;
- while (pmsgRead(&logger_list, &transp, &log_msg) > 0) {
+ while (PmsgRead(&logger_list, &log_msg) > 0) {
const char* cp;
size_t hdr_size = log_msg.entry.hdr_size;
@@ -426,7 +375,7 @@
}
list_add_head(node, &content->node);
}
- pmsgClose(&logger_list, &transp);
+ PmsgClose(&logger_list);
/* Progress through all the collected files */
list_for_each_safe(node, n, &name_list) {
diff --git a/liblog/pmsg_reader.h b/liblog/pmsg_reader.h
new file mode 100644
index 0000000..53746d8
--- /dev/null
+++ b/liblog/pmsg_reader.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#pragma once
+
+#include <unistd.h>
+
+#include "log/log_read.h"
+#include "log_portability.h"
+
+__BEGIN_DECLS
+
+int PmsgRead(struct logger_list* logger_list, struct log_msg* log_msg);
+void PmsgClose(struct logger_list* logger_list);
+
+__END_DECLS
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index 56892a2..39ac7a5 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -913,7 +913,7 @@
}
BENCHMARK(BM_lookupEventTagNum);
-// Must be functionally identical to liblog internal __send_log_msg.
+// Must be functionally identical to liblog internal SendLogdControlMessage()
static void send_to_control(char* buf, size_t len) {
int sock =
socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM | SOCK_CLOEXEC);
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 70ccb80..2d14bf3 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -969,6 +969,16 @@
}
}
+ if (mode & ANDROID_LOG_PSTORE) {
+ if (clearLog) {
+ unlink("/sys/fs/pstore/pmsg-ramoops-0");
+ return EXIT_SUCCESS;
+ }
+ if (setLogSize || getLogSize || printStatistics || getPruneList || setPruneList) {
+ LogcatPanic(HELP_TRUE, "-L is incompatible with -g/-G, -S, and -p/-P");
+ }
+ }
+
std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
nullptr, &android_logger_list_free};
if (tail_time != log_time::EPOCH) {