blob: ae1c8ed81744c6010a8e625b1194e5201a8091ba [file] [log] [blame]
Yifan Hongc80de2d2020-02-25 17:13:53 -08001//
2// Copyright (C) 2020 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include <inttypes.h>
18#include <stdio.h>
19#include <sys/stat.h>
20#include <unistd.h>
21
22#include <algorithm>
23#include <string>
24#include <vector>
25
26#include <base/files/dir_reader_posix.h>
27#include <base/logging.h>
28#include <base/strings/string_util.h>
29#include <base/strings/stringprintf.h>
30
31#include "update_engine/common/utils.h"
32
33using std::string;
34
35namespace chromeos_update_engine {
36namespace {
37
38constexpr char kSystemLogsRoot[] = "/data/misc/update_engine_log";
39constexpr size_t kLogCount = 5;
40
41// Keep the most recent |kLogCount| logs but remove the old ones in
42// "/data/misc/update_engine_log/".
43void DeleteOldLogs(const string& kLogsRoot) {
44 base::DirReaderPosix reader(kLogsRoot.c_str());
45 if (!reader.IsValid()) {
46 LOG(ERROR) << "Failed to read " << kLogsRoot;
47 return;
48 }
49
50 std::vector<string> old_logs;
51 while (reader.Next()) {
52 if (reader.name()[0] == '.')
53 continue;
54
55 // Log files are in format "update_engine.%Y%m%d-%H%M%S",
56 // e.g. update_engine.20090103-231425
57 uint64_t date;
58 uint64_t local_time;
59 if (sscanf(reader.name(),
60 "update_engine.%" PRIu64 "-%" PRIu64 "",
61 &date,
62 &local_time) == 2) {
63 old_logs.push_back(reader.name());
64 } else {
65 LOG(WARNING) << "Unrecognized log file " << reader.name();
66 }
67 }
68
69 std::sort(old_logs.begin(), old_logs.end(), std::greater<string>());
70 for (size_t i = kLogCount; i < old_logs.size(); i++) {
71 string log_path = kLogsRoot + "/" + old_logs[i];
72 if (unlink(log_path.c_str()) == -1) {
73 PLOG(WARNING) << "Failed to unlink " << log_path;
74 }
75 }
76}
77
78string SetupLogFile(const string& kLogsRoot) {
79 DeleteOldLogs(kLogsRoot);
80
81 return base::StringPrintf("%s/update_engine.%s",
82 kLogsRoot.c_str(),
83 utils::GetTimeAsString(::time(nullptr)).c_str());
84}
85
86} // namespace
87
88void SetupLogging(bool log_to_system, bool log_to_file) {
89 logging::LoggingSettings log_settings;
90 log_settings.lock_log = logging::DONT_LOCK_LOG_FILE;
91 log_settings.logging_dest = static_cast<logging::LoggingDestination>(
92 (log_to_system ? logging::LOG_TO_SYSTEM_DEBUG_LOG : 0) |
93 (log_to_file ? logging::LOG_TO_FILE : 0));
94 log_settings.log_file = nullptr;
95
96 string log_file;
97 if (log_to_file) {
98 log_file = SetupLogFile(kSystemLogsRoot);
99 log_settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE;
100 log_settings.log_file = log_file.c_str();
101 }
102 logging::InitLogging(log_settings);
103
104 // The log file will have AID_LOG as group ID; this GID is inherited from the
105 // parent directory "/data/misc/update_engine_log" which sets the SGID bit.
106 chmod(log_file.c_str(), 0640);
107}
108
109} // namespace chromeos_update_engine