summaryrefslogtreecommitdiffstats
path: root/liblog
diff options
context:
space:
mode:
authorMark Salyzyn <salyzyn@google.com>2016-03-10 09:50:08 -0800
committerDan Willemsen <dwillemsen@google.com>2016-03-22 13:03:36 -0700
commitd4b061bde280fce9b5426b5738a02d42ec263c48 (patch)
tree4be93d57461360452f7d7af3490f1119da581dc3 /liblog
parent018a96d03f0d452bf078084eedcd5693da42308d (diff)
downloadcore-d4b061bde280fce9b5426b5738a02d42ec263c48.tar.gz
core-d4b061bde280fce9b5426b5738a02d42ec263c48.tar.bz2
core-d4b061bde280fce9b5426b5738a02d42ec263c48.zip
liblog: add __android_log_pmsg_file_write
- This is considered an Android Private function, not exported for general use. - goal is to record a file's content into a series of log messages into pmsg, to be retrieved after a reboot for transfer to a persistent location. - filename reference is converted to a tag-unique "<dirbase>:<filebase>". - buffer and length representing the filename contents are recorded, along with a sequence number placed into the nsec time field to ANDROID_LOG_PMSG_FILE_MAX_SEQUENCE. - Add a gTest for this function. Bug: 27176738 Change-Id: If93df3ae8bfc1bb75516d4a1fd8dae0301af644b
Diffstat (limited to 'liblog')
-rw-r--r--liblog/pmsg_writer.c111
-rw-r--r--liblog/tests/liblog_test.cpp15
2 files changed, 125 insertions, 1 deletions
diff --git a/liblog/pmsg_writer.c b/liblog/pmsg_writer.c
index 7a89e5d54..7034cebaa 100644
--- a/liblog/pmsg_writer.c
+++ b/liblog/pmsg_writer.c
@@ -157,3 +157,114 @@ static int pmsgWrite(log_id_t logId, struct timespec *ts,
return ret;
}
+
+/*
+ * Virtual pmsg filesystem
+ *
+ * Payload will comprise the string "<basedir>:<basefile>\0<content>" to a
+ * maximum of LOGGER_ENTRY_MAX_PAYLOAD, but scaled to the last newline in the
+ * file.
+ *
+ * Will hijack the header.realtime.tv_nsec field for a sequence number in usec.
+ */
+
+static inline const char *strnrchr(const char *buf, size_t len, char c) {
+ const char *cp = buf + len;
+ while ((--cp > buf) && (*cp != c));
+ if (cp <= buf) {
+ return buf + len;
+ }
+ return cp;
+}
+
+/* Write a buffer as filename references (tag = <basedir>:<basename>) */
+LIBLOG_ABI_PRIVATE ssize_t __android_log_pmsg_file_write(
+ log_id_t logId,
+ char prio,
+ const char *filename,
+ const char *buf, size_t len) {
+ int fd;
+ size_t length, packet_len;
+ const char *tag;
+ char *cp, *slash;
+ struct timespec ts;
+ struct iovec vec[3];
+
+ /* Make sure the logId value is not a bad idea */
+ if ((logId == LOG_ID_KERNEL) || /* Verbotten */
+ (logId == LOG_ID_EVENTS) || /* Do not support binary content */
+ (logId == LOG_ID_SECURITY) || /* Bad idea to allow */
+ ((unsigned)logId >= 32)) { /* fit within logMask on arch32 */
+ return -EINVAL;
+ }
+
+ clock_gettime(android_log_clockid(), &ts);
+
+ cp = strdup(filename);
+ if (!cp) {
+ return -ENOMEM;
+ }
+
+ fd = pmsgLoggerWrite.context.fd;
+ if (fd < 0) {
+ __android_log_lock();
+ fd = pmsgOpen();
+ __android_log_unlock();
+ if (fd < 0) {
+ return -EBADF;
+ }
+ }
+
+ tag = cp;
+ slash = strrchr(cp, '/');
+ if (slash) {
+ *slash = ':';
+ slash = strrchr(cp, '/');
+ if (slash) {
+ tag = slash + 1;
+ }
+ }
+
+ length = strlen(tag) + 1;
+ packet_len = LOGGER_ENTRY_MAX_PAYLOAD - sizeof(char) - length;
+
+ vec[0].iov_base = &prio;
+ vec[0].iov_len = sizeof(char);
+ vec[1].iov_base = (unsigned char *)tag;
+ vec[1].iov_len = length;
+
+ for (ts.tv_nsec = 0, length = len;
+ length;
+ ts.tv_nsec += ANDROID_LOG_PMSG_FILE_SEQUENCE) {
+ ssize_t ret;
+ size_t transfer;
+
+ if ((ts.tv_nsec / ANDROID_LOG_PMSG_FILE_SEQUENCE) >=
+ ANDROID_LOG_PMSG_FILE_MAX_SEQUENCE) {
+ len -= length;
+ break;
+ }
+
+ transfer = length;
+ if (transfer > packet_len) {
+ transfer = strnrchr(buf, packet_len - 1, '\n') - buf;
+ if ((transfer < length) && (buf[transfer] == '\n')) {
+ ++transfer;
+ }
+ }
+
+ vec[2].iov_base = (unsigned char *)buf;
+ vec[2].iov_len = transfer;
+
+ ret = pmsgWrite(logId, &ts, vec, sizeof(vec) / sizeof(vec[0]));
+
+ if (ret <= 0) {
+ free(cp);
+ return ret;
+ }
+ length -= transfer;
+ buf += transfer;
+ }
+ free(cp);
+ return len;
+}
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 2767f73b0..f3157913e 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -957,7 +957,10 @@ Good Signior Leonato, you are come to meet your\n\
trouble: the fashion of the world is to avoid\n\
cost, and you encounter it\n\
LEONATO\n\
-Never came trouble to my house in the likeness of your grace";
+Never came trouble to my house in the likeness of your grace,\n\
+for trouble being gone, comfort should remain, but\n\
+when you depart from me, sorrow abides and happiness\n\
+takes his leave.";
TEST(liblog, max_payload) {
pid_t pid = getpid();
@@ -2520,3 +2523,13 @@ TEST(liblog, create_android_logger_overflow) {
EXPECT_LE(0, android_log_destroy(&ctx));
ASSERT_TRUE(NULL == ctx);
}
+
+static const char __pmsg_file[] =
+ "/data/william-shakespeare/MuchAdoAboutNothing.txt";
+
+TEST(liblog, __android_log_pmsg_file_write) {
+ EXPECT_LT(0, __android_log_pmsg_file_write(
+ LOG_ID_CRASH, ANDROID_LOG_VERBOSE,
+ __pmsg_file, max_payload_buf, sizeof(max_payload_buf)));
+ fprintf(stderr, "Reboot, ensure file %s matches\n", __pmsg_file);
+}