Home | History | Annotate | Download | only in recovery
      1 /*
      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 
     31 static const std::string LAST_KMSG_FILTER = "recovery/last_kmsg";
     32 static const std::string LAST_LOG_FILTER = "recovery/last_log";
     33 
     34 ssize_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;
     42 }
     43 
     44 ssize_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   }
     50 
     51   std::string name(filename);
     52   size_t dot = name.find_last_of('.');
     53   std::string sub = name.substr(0, dot);
     54 
     55   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   }
     59 
     60   // 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";
     67     } else {
     68       size_t i;
     69       if (!android::base::ParseUint(number, &i)) {
     70         LOG(ERROR) << "failed to parse uint in " << number;
     71         return -1;
     72       }
     73       name = sub + "." + std::to_string(i + 1);
     74     }
     75   }
     76 
     77   return __android_log_pmsg_file_write(id, prio, name.c_str(), buf, len);
     78 }
     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.
     83 void rotate_logs(const char* last_log_file, const char* last_kmsg_file) {
     84   // Logs should only be rotated once.
     85   static bool rotated = false;
     86   if (rotated) {
     87     return;
     88   }
     89   rotated = true;
     90 
     91   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);
     95     }
     96     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   }
    107 }
    108