Magisk/native/jni/core/logging.cpp

160 lines
3.6 KiB
C++
Raw Normal View History

2021-08-12 10:26:54 +00:00
#include <sys/uio.h>
#include <android/log.h>
#include <magisk.hpp>
2022-05-12 09:03:42 +00:00
#include <base.hpp>
2021-08-12 10:26:54 +00:00
#include <daemon.hpp>
#include <stream.hpp>
#include "core.hpp"
using namespace std;
struct log_meta {
int prio;
int len;
int pid;
int tid;
};
2021-08-21 10:52:59 +00:00
atomic<int> logd_fd = -1;
2021-08-12 10:26:54 +00:00
void setup_logfile(bool reset) {
if (logd_fd < 0)
return;
iovec iov{};
log_meta meta = {
.prio = -1,
.len = reset
};
iov.iov_base = &meta;
iov.iov_len = sizeof(meta);
writev(logd_fd, &iov, 1);
}
// Maximum message length for pipes to transfer atomically
2022-07-06 04:13:09 +00:00
#define MAX_MSG_LEN (int) (PIPE_BUF - sizeof(log_meta))
2021-08-12 10:26:54 +00:00
2021-10-09 18:36:01 +00:00
static void *logfile_writer(void *arg) {
int pipefd = (long) arg;
2021-09-19 20:41:45 +00:00
run_finally close_pipes([=] {
2021-08-12 10:26:54 +00:00
// Close up all logging pipes when thread dies
close(pipefd);
close(logd_fd.exchange(-1));
});
struct {
void *data;
size_t len;
2021-09-19 20:41:45 +00:00
} tmp{};
stream_ptr strm = make_unique<byte_stream>(tmp.data, tmp.len);
bool switched = false;
2021-08-12 10:26:54 +00:00
log_meta meta{};
2021-08-13 09:08:56 +00:00
char buf[MAX_MSG_LEN];
char aux[64];
iovec iov[2];
iov[0].iov_base = aux;
iov[1].iov_base = buf;
2021-08-12 10:26:54 +00:00
for (;;) {
// Read meta data
2021-09-19 20:41:45 +00:00
if (read(pipefd, &meta, sizeof(meta)) != sizeof(meta))
2021-10-09 18:36:01 +00:00
return nullptr;
2021-08-12 10:26:54 +00:00
2021-09-19 20:41:45 +00:00
if (meta.prio < 0) {
if (!switched) {
run_finally free_tmp([&] {
free(tmp.data);
tmp.data = nullptr;
tmp.len = 0;
});
2021-08-12 10:26:54 +00:00
rename(LOGFILE, LOGFILE ".bak");
2021-09-19 20:41:45 +00:00
int fd = open(LOGFILE, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, 0644);
if (fd < 0)
2021-10-09 18:36:01 +00:00
return nullptr;
2021-09-19 20:41:45 +00:00
if (tmp.data)
write(fd, tmp.data, tmp.len);
strm = make_unique<fd_stream>(fd);
switched = true;
}
2021-08-12 10:26:54 +00:00
continue;
}
2021-08-13 09:08:56 +00:00
// Read message
2021-09-19 20:41:45 +00:00
if (read(pipefd, buf, meta.len) != meta.len)
2021-10-09 18:36:01 +00:00
return nullptr;
2021-08-13 09:08:56 +00:00
2021-08-12 10:26:54 +00:00
timeval tv;
tm tm;
gettimeofday(&tv, nullptr);
localtime_r(&tv.tv_sec, &tm);
// Format detailed info
char type;
switch (meta.prio) {
case ANDROID_LOG_DEBUG:
type = 'D';
break;
case ANDROID_LOG_INFO:
type = 'I';
break;
case ANDROID_LOG_WARN:
type = 'W';
break;
default:
type = 'E';
break;
}
2021-09-19 20:41:45 +00:00
long ms = tv.tv_usec / 1000;
2021-08-13 09:08:56 +00:00
size_t off = strftime(aux, sizeof(aux), "%m-%d %T", &tm);
off += snprintf(aux + off, sizeof(aux) - off,
2021-09-19 20:41:45 +00:00
".%03ld %5d %5d %c : ", ms, meta.pid, meta.tid, type);
2021-08-12 10:26:54 +00:00
2021-08-13 09:08:56 +00:00
iov[0].iov_len = off;
iov[1].iov_len = meta.len;
2021-08-13 07:13:44 +00:00
2021-08-13 09:08:56 +00:00
strm->writev(iov, 2);
2021-08-12 10:26:54 +00:00
}
}
2022-07-06 04:13:09 +00:00
void magisk_log_write(int prio, const char *msg, int len) {
2021-08-12 10:26:54 +00:00
if (logd_fd >= 0) {
2022-07-06 04:13:09 +00:00
// Truncate
len = std::min(MAX_MSG_LEN, len);
2021-08-12 10:26:54 +00:00
log_meta meta = {
.prio = prio,
.len = len,
.pid = getpid(),
.tid = gettid()
};
iovec iov[2];
iov[0].iov_base = &meta;
iov[0].iov_len = sizeof(meta);
2022-07-06 04:13:09 +00:00
iov[1].iov_base = (void *) msg;
2021-08-12 10:26:54 +00:00
iov[1].iov_len = len;
if (writev(logd_fd, iov, 2) < 0) {
// Stop trying to write to file
close(logd_fd.exchange(-1));
}
}
2021-08-21 07:58:51 +00:00
}
2021-08-12 10:26:54 +00:00
void start_log_daemon() {
int fds[2];
if (pipe2(fds, O_CLOEXEC) == 0) {
logd_fd = fds[1];
2021-10-09 18:36:01 +00:00
long fd = fds[0];
new_daemon_thread(logfile_writer, (void *) fd);
2021-08-12 10:26:54 +00:00
}
}