summaryrefslogtreecommitdiffstats
path: root/otautil
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--otautil/include/otautil/logging.h14
-rw-r--r--otautil/logging.cpp100
2 files changed, 104 insertions, 10 deletions
diff --git a/otautil/include/otautil/logging.h b/otautil/include/otautil/logging.h
index c4f13292b..608349785 100644
--- a/otautil/include/otautil/logging.h
+++ b/otautil/include/otautil/logging.h
@@ -18,9 +18,11 @@
#define _LOGGING_H
#include <stddef.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <string>
+#include <vector>
#include <log/log_id.h>
@@ -28,6 +30,14 @@ static constexpr int KEEP_LOG_COUNT = 10;
struct selabel_handle;
+struct saved_log_file {
+ std::string name;
+ struct stat sb;
+ std::string data;
+};
+
+void SetLoggingSehandle(selabel_handle* handle);
+
ssize_t logbasename(log_id_t id, char prio, const char* filename, const char* buf, size_t len,
void* arg);
@@ -48,4 +58,8 @@ void reset_tmplog_offset();
void save_kernel_log(const char* destination);
+std::vector<saved_log_file> ReadLogFilesToMemory();
+
+bool RestoreLogFilesAfterFormat(const std::vector<saved_log_file>& log_files);
+
#endif //_LOGGING_H
diff --git a/otautil/logging.cpp b/otautil/logging.cpp
index 7c330ac61..484f1150f 100644
--- a/otautil/logging.cpp
+++ b/otautil/logging.cpp
@@ -16,17 +16,22 @@
#include "otautil/logging.h"
+#include <dirent.h>
+#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/klog.h>
#include <sys/types.h>
+#include <algorithm>
+#include <memory>
#include <string>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
#include <private/android_filesystem_config.h> /* for AID_SYSTEM */
#include <private/android_logger.h> /* private pmsg functions */
#include <selinux/label.h>
@@ -35,13 +40,21 @@
#include "otautil/paths.h"
#include "otautil/roots.h"
-static constexpr const char* LOG_FILE = "/cache/recovery/log";
-static constexpr const char* LAST_INSTALL_FILE = "/cache/recovery/last_install";
-static constexpr const char* LAST_KMSG_FILE = "/cache/recovery/last_kmsg";
-static constexpr const char* LAST_LOG_FILE = "/cache/recovery/last_log";
+constexpr const char* LOG_FILE = "/cache/recovery/log";
+constexpr const char* LAST_INSTALL_FILE = "/cache/recovery/last_install";
+constexpr const char* LAST_KMSG_FILE = "/cache/recovery/last_kmsg";
+constexpr const char* LAST_LOG_FILE = "/cache/recovery/last_log";
-static const std::string LAST_KMSG_FILTER = "recovery/last_kmsg";
-static const std::string LAST_LOG_FILTER = "recovery/last_log";
+constexpr const char* LAST_KMSG_FILTER = "recovery/last_kmsg";
+constexpr const char* LAST_LOG_FILTER = "recovery/last_log";
+
+constexpr const char* CACHE_LOG_DIR = "/cache/recovery";
+
+static struct selabel_handle* logging_sehandle;
+
+void SetLoggingSehandle(selabel_handle* handle) {
+ logging_sehandle = handle;
+}
// fopen(3)'s the given file, by mounting volumes and making parent dirs as necessary. Returns the
// file pointer, or nullptr on error.
@@ -74,8 +87,8 @@ void check_and_fclose(FILE* fp, const std::string& name) {
ssize_t logbasename(log_id_t /* id */, char /* prio */, const char* filename, const char* /* buf */,
size_t len, void* arg) {
bool* do_rotate = static_cast<bool*>(arg);
- if (LAST_KMSG_FILTER.find(filename) != std::string::npos ||
- LAST_LOG_FILTER.find(filename) != std::string::npos) {
+ if (std::string(LAST_KMSG_FILTER).find(filename) != std::string::npos ||
+ std::string(LAST_LOG_FILTER).find(filename) != std::string::npos) {
*do_rotate = true;
}
return len;
@@ -92,8 +105,8 @@ ssize_t logrotate(log_id_t id, char prio, const char* filename, const char* buf,
size_t dot = name.find_last_of('.');
std::string sub = name.substr(0, dot);
- if (LAST_KMSG_FILTER.find(sub) == std::string::npos &&
- LAST_LOG_FILTER.find(sub) == std::string::npos) {
+ if (std::string(LAST_KMSG_FILTER).find(sub) == std::string::npos &&
+ std::string(LAST_LOG_FILTER).find(sub) == std::string::npos) {
return __android_log_pmsg_file_write(id, prio, filename, buf, len);
}
@@ -243,3 +256,70 @@ void save_kernel_log(const char* destination) {
buffer.resize(n);
android::base::WriteStringToFile(buffer, destination);
}
+
+std::vector<saved_log_file> ReadLogFilesToMemory() {
+ ensure_path_mounted("/cache");
+
+ struct dirent* de;
+ std::unique_ptr<DIR, decltype(&closedir)> d(opendir(CACHE_LOG_DIR), closedir);
+ if (!d) {
+ if (errno != ENOENT) {
+ PLOG(ERROR) << "Failed to opendir " << CACHE_LOG_DIR;
+ }
+ return {};
+ }
+
+ std::vector<saved_log_file> log_files;
+ while ((de = readdir(d.get())) != nullptr) {
+ if (strncmp(de->d_name, "last_", 5) == 0 || strcmp(de->d_name, "log") == 0) {
+ std::string path = android::base::StringPrintf("%s/%s", CACHE_LOG_DIR, de->d_name);
+
+ struct stat sb;
+ if (stat(path.c_str(), &sb) != 0) {
+ PLOG(ERROR) << "Failed to stat " << path;
+ continue;
+ }
+ // Truncate files to 512kb
+ size_t read_size = std::min<size_t>(sb.st_size, 1 << 19);
+ std::string data(read_size, '\0');
+
+ android::base::unique_fd log_fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY)));
+ if (log_fd == -1 || !android::base::ReadFully(log_fd, data.data(), read_size)) {
+ PLOG(ERROR) << "Failed to read log file " << path;
+ continue;
+ }
+
+ log_files.emplace_back(saved_log_file{ path, sb, data });
+ }
+ }
+
+ return log_files;
+}
+
+bool RestoreLogFilesAfterFormat(const std::vector<saved_log_file>& log_files) {
+ // Re-create the log dir and write back the log entries.
+ if (ensure_path_mounted(CACHE_LOG_DIR) != 0) {
+ PLOG(ERROR) << "Failed to mount " << CACHE_LOG_DIR;
+ return false;
+ }
+
+ if (mkdir_recursively(CACHE_LOG_DIR, 0777, false, logging_sehandle) != 0) {
+ PLOG(ERROR) << "Failed to create " << CACHE_LOG_DIR;
+ return false;
+ }
+
+ for (const auto& log : log_files) {
+ if (!android::base::WriteStringToFile(log.data, log.name, log.sb.st_mode, log.sb.st_uid,
+ log.sb.st_gid)) {
+ PLOG(ERROR) << "Failed to write to " << log.name;
+ }
+ }
+
+ // Any part of the log we'd copied to cache is now gone.
+ // Reset the pointer so we copy from the beginning of the temp
+ // log.
+ reset_tmplog_offset();
+ copy_logs(true /* save_current_log */, true /* has_cache */, logging_sehandle);
+
+ return true;
+}