blob: 76b7f4b06459d834357eedc1cd6eda347b8e1d80 [file] [log] [blame]
Tianjie Xue113e4d2016-10-21 17:46:13 -07001/*
2 * Copyright (C) 2016 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 "rotate_logs.h"
18
19#include <stdio.h>
20#include <string.h>
21#include <sys/types.h>
22
23#include <string>
24
25#include <android-base/file.h>
26#include <android-base/logging.h>
27#include <android-base/parseint.h>
28#include <android-base/stringprintf.h>
29#include <private/android_logger.h> /* private pmsg functions */
30
31static const std::string LAST_KMSG_FILTER = "recovery/last_kmsg";
32static const std::string LAST_LOG_FILTER = "recovery/last_log";
33
Tao Bao245c5222017-10-18 11:06:36 -070034ssize_t logbasename(log_id_t /* id */, char /* prio */, const char* filename, const char* /* buf */,
35 size_t len, void* arg) {
36 bool* do_rotate = static_cast<bool*>(arg);
37 if (LAST_KMSG_FILTER.find(filename) != std::string::npos ||
38 LAST_LOG_FILTER.find(filename) != std::string::npos) {
39 *do_rotate = true;
40 }
41 return len;
Tianjie Xue113e4d2016-10-21 17:46:13 -070042}
43
Tao Bao245c5222017-10-18 11:06:36 -070044ssize_t logrotate(log_id_t id, char prio, const char* filename, const char* buf, size_t len,
45 void* arg) {
46 bool* do_rotate = static_cast<bool*>(arg);
47 if (!*do_rotate) {
48 return __android_log_pmsg_file_write(id, prio, filename, buf, len);
49 }
Tianjie Xue113e4d2016-10-21 17:46:13 -070050
Tao Bao245c5222017-10-18 11:06:36 -070051 std::string name(filename);
52 size_t dot = name.find_last_of('.');
53 std::string sub = name.substr(0, dot);
Tianjie Xue113e4d2016-10-21 17:46:13 -070054
Tao Bao245c5222017-10-18 11:06:36 -070055 if (LAST_KMSG_FILTER.find(sub) == std::string::npos &&
56 LAST_LOG_FILTER.find(sub) == std::string::npos) {
57 return __android_log_pmsg_file_write(id, prio, filename, buf, len);
58 }
Tianjie Xue113e4d2016-10-21 17:46:13 -070059
Tao Bao245c5222017-10-18 11:06:36 -070060 // filename rotation
61 if (dot == std::string::npos) {
62 name += ".1";
63 } else {
64 std::string number = name.substr(dot + 1);
65 if (!isdigit(number[0])) {
66 name += ".1";
Tianjie Xue113e4d2016-10-21 17:46:13 -070067 } else {
Tao Bao245c5222017-10-18 11:06:36 -070068 size_t i;
Ethan Yonker58f21322018-08-24 11:17:36 -050069 if (!android::base::ParseUint(number.c_str(), &i)) {
Tao Bao245c5222017-10-18 11:06:36 -070070 LOG(ERROR) << "failed to parse uint in " << number;
71 return -1;
72 }
73 name = sub + "." + std::to_string(i + 1);
Tianjie Xue113e4d2016-10-21 17:46:13 -070074 }
Tao Bao245c5222017-10-18 11:06:36 -070075 }
Tianjie Xue113e4d2016-10-21 17:46:13 -070076
Tao Bao245c5222017-10-18 11:06:36 -070077 return __android_log_pmsg_file_write(id, prio, name.c_str(), buf, len);
Tianjie Xue113e4d2016-10-21 17:46:13 -070078}
79
80// Rename last_log -> last_log.1 -> last_log.2 -> ... -> last_log.$max.
81// Similarly rename last_kmsg -> last_kmsg.1 -> ... -> last_kmsg.$max.
82// Overwrite any existing last_log.$max and last_kmsg.$max.
83void rotate_logs(const char* last_log_file, const char* last_kmsg_file) {
Tao Bao245c5222017-10-18 11:06:36 -070084 // Logs should only be rotated once.
85 static bool rotated = false;
86 if (rotated) {
87 return;
88 }
89 rotated = true;
Tianjie Xue113e4d2016-10-21 17:46:13 -070090
Tao Bao245c5222017-10-18 11:06:36 -070091 for (int i = KEEP_LOG_COUNT - 1; i >= 0; --i) {
92 std::string old_log = android::base::StringPrintf("%s", last_log_file);
93 if (i > 0) {
94 old_log += "." + std::to_string(i);
Tianjie Xue113e4d2016-10-21 17:46:13 -070095 }
Tao Bao245c5222017-10-18 11:06:36 -070096 std::string new_log = android::base::StringPrintf("%s.%d", last_log_file, i + 1);
97 // Ignore errors if old_log doesn't exist.
98 rename(old_log.c_str(), new_log.c_str());
99
100 std::string old_kmsg = android::base::StringPrintf("%s", last_kmsg_file);
101 if (i > 0) {
102 old_kmsg += "." + std::to_string(i);
103 }
104 std::string new_kmsg = android::base::StringPrintf("%s.%d", last_kmsg_file, i + 1);
105 rename(old_kmsg.c_str(), new_kmsg.c_str());
106 }
Tianjie Xue113e4d2016-10-21 17:46:13 -0700107}