diff --git a/native/jni/core/bootstages.cpp b/native/jni/core/bootstages.cpp index 75655d75f..f07817c3b 100644 --- a/native/jni/core/bootstages.cpp +++ b/native/jni/core/bootstages.cpp @@ -222,39 +222,6 @@ void unlock_blocks() { } } -static void collect_logs(bool reset) { - static bool running = false; - static pthread_mutex_t log_lock = PTHREAD_MUTEX_INITIALIZER; - { - mutex_guard lock(log_lock); - if (running) - return; - int test = exec_command_sync("/system/bin/logcat", "-d", "-f", "/dev/null"); - chmod("/dev/null", 0666); - if (test != 0) - return; - running = true; - } - if (reset) - rename(LOGFILE, LOGFILE ".bak"); - // Start a daemon thread and wait indefinitely - new_daemon_thread([]{ - int fd = xopen(LOGFILE, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, 0644); - exec_t exec { - .fd = fd, - .fork = fork_no_zombie - }; - int pid = exec_command(exec, "/system/bin/logcat", "-s", "Magisk"); - close(fd); - if (pid < 0) { - mutex_guard lock(log_lock); - running = false; - } else { - waitpid(pid, nullptr, 0); - } - }); -} - #define test_bit(bit, array) (array[bit / 8] & (1 << (bit % 8))) static bool check_key_combo() { @@ -317,7 +284,7 @@ void post_fs_data(int client) { if (!check_data()) goto unblock_init; - collect_logs(true); + setup_logfile(true); LOGI("** post-fs-data mode running\n"); @@ -369,7 +336,7 @@ void late_start(int client) { write_int(client, 0); close(client); - collect_logs(false); + setup_logfile(false); if (!pfs_done || safe_mode) return; @@ -384,7 +351,7 @@ void boot_complete(int client) { write_int(client, 0); close(client); - collect_logs(false); + setup_logfile(false); if (safe_mode) return; diff --git a/native/jni/core/daemon.cpp b/native/jni/core/daemon.cpp index cfb083811..66e838eb0 100644 --- a/native/jni/core/daemon.cpp +++ b/native/jni/core/daemon.cpp @@ -14,6 +14,7 @@ #include #include #include +#include using namespace std; @@ -122,21 +123,77 @@ static void handle_request(int client) { } // Create new thread to handle complex requests - new_daemon_thread(std::bind(&request_handler, client, req_code, cred)); + new_daemon_thread([=] { return request_handler(client, req_code, cred); }); return; shortcut: close(client); } -#define vlog __android_log_vprint +static FILE *log_file; + +bool in_mem_log = true; +static char *log_buf; +static size_t log_buf_len; + +void setup_logfile(bool reset) { + if (!in_mem_log) + return; + in_mem_log = false; + if (reset) + rename(LOGFILE, LOGFILE ".bak"); + + int fd = xopen(LOGFILE, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, 0644); + + // Dump all logs in memory (if exists) + if (log_buf) { + write(fd, log_buf, log_buf_len); + } + + // Redirect to log file + log_file = fdopen(fd, "a"); + setbuf(log_file, nullptr); + + free(log_buf); +} + +static int magisk_log(int prio, const char *fmt, va_list ap) { + // Log to logcat + __android_log_vprint(prio, "Magisk", fmt, ap); + + char buf[4096]; + timeval tv; + tm tm; + char type; + switch (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; + } + gettimeofday(&tv, nullptr); + localtime_r(&tv.tv_sec, &tm); + size_t len = strftime(buf, sizeof(buf), "%m-%d %T", &tm); + int ms = tv.tv_usec / 1000; + len += sprintf(buf + len, ".%03d %c : ", ms, type); + strcpy(buf + len, fmt); + return vfprintf(log_file, buf, ap); +} static void android_logging() { - static constexpr char TAG[] = "Magisk"; - log_cb.d = [](auto fmt, auto ap){ return vlog(ANDROID_LOG_DEBUG, TAG, fmt, ap); }; - log_cb.i = [](auto fmt, auto ap){ return vlog(ANDROID_LOG_INFO, TAG, fmt, ap); }; - log_cb.w = [](auto fmt, auto ap){ return vlog(ANDROID_LOG_WARN, TAG, fmt, ap); }; - log_cb.e = [](auto fmt, auto ap){ return vlog(ANDROID_LOG_ERROR, TAG, fmt, ap); }; + log_file = make_stream_fp(log_buf, log_buf_len).release(); + log_cb.d = [](auto fmt, auto ap){ return magisk_log(ANDROID_LOG_DEBUG, fmt, ap); }; + log_cb.i = [](auto fmt, auto ap){ return magisk_log(ANDROID_LOG_INFO, fmt, ap); }; + log_cb.w = [](auto fmt, auto ap){ return magisk_log(ANDROID_LOG_WARN, fmt, ap); }; + log_cb.e = [](auto fmt, auto ap){ return magisk_log(ANDROID_LOG_ERROR, fmt, ap); }; log_cb.ex = nop_ex; } diff --git a/native/jni/include/daemon.hpp b/native/jni/include/daemon.hpp index 05959ef8f..be676ed65 100644 --- a/native/jni/include/daemon.hpp +++ b/native/jni/include/daemon.hpp @@ -53,6 +53,7 @@ void su_daemon_handler(int client, ucred *credential); int connect_daemon(bool create = false); void unlock_blocks(); void reboot(); +void setup_logfile(bool reset); // Module stuffs void handle_modules(); diff --git a/native/jni/utils/files.cpp b/native/jni/utils/files.cpp index b4d3696ad..098e487b4 100644 --- a/native/jni/utils/files.cpp +++ b/native/jni/utils/files.cpp @@ -353,7 +353,7 @@ void file_readline(bool trim, const char *file, const function &&fn) { +void parse_prop_file(const char *file, const function &fn) { file_readline(true, file, [&](string_view line_view) -> bool { char *line = (char *) line_view.data(); if (line[0] == '#') @@ -422,3 +422,11 @@ void restore_folder(const char *dir, vector &files) { setattr(path.data(), &file.attr); } } + +sDIR make_dir(DIR *dp) { + return sDIR(dp, [](DIR *dp){ return dp ? closedir(dp) : 1; }); +} + +sFILE make_file(FILE *fp) { + return sFILE(fp, [](FILE *fp){ return fp ? fclose(fp) : 1; }); +} diff --git a/native/jni/utils/files.hpp b/native/jni/utils/files.hpp index 2e490792f..bf6b766ed 100644 --- a/native/jni/utils/files.hpp +++ b/native/jni/utils/files.hpp @@ -67,7 +67,7 @@ static inline void file_readline(const char *file, file_readline(false, file, fn); } void parse_prop_file(const char *file, - const std::function &&fn); + const std::function &fn); void *__mmap(const char *filename, size_t *size, bool rw); void frm_rf(int dirfd); void clone_dir(int src, int dest); @@ -113,27 +113,29 @@ void mmap_rw(const char *filename, B &buf, L &sz) { using sFILE = std::unique_ptr; using sDIR = std::unique_ptr; +sDIR make_dir(DIR *dp); +sFILE make_file(FILE *fp); static inline sDIR open_dir(const char *path) { - return sDIR(opendir(path), closedir); + return make_dir(opendir(path)); } static inline sDIR xopen_dir(const char *path) { - return sDIR(xopendir(path), closedir); + return make_dir(xopendir(path)); } static inline sDIR xopen_dir(int dirfd) { - return sDIR(xfdopendir(dirfd), closedir); + return make_dir(xfdopendir(dirfd)); } static inline sFILE open_file(const char *path, const char *mode) { - return sFILE(fopen(path, mode), fclose); + return make_file(fopen(path, mode)); } static inline sFILE xopen_file(const char *path, const char *mode) { - return sFILE(xfopen(path, mode), fclose); + return make_file(xfopen(path, mode)); } static inline sFILE xopen_file(int fd, const char *mode) { - return sFILE(xfdopen(fd, mode), fclose); + return make_file(xfdopen(fd, mode)); } diff --git a/native/jni/utils/stream.cpp b/native/jni/utils/stream.cpp index 076baf8c0..3e0d4a64c 100644 --- a/native/jni/utils/stream.cpp +++ b/native/jni/utils/stream.cpp @@ -23,7 +23,7 @@ static int strm_close(void *v) { } sFILE make_stream_fp(stream_ptr &&strm) { - sFILE fp(funopen(strm.release(), strm_read, strm_write, strm_seek, strm_close), fclose); + auto fp = make_file(funopen(strm.release(), strm_read, strm_write, strm_seek, strm_close)); setbuf(fp.get(), nullptr); return fp; }