Rotate logs only when there are actual operations

Currently it rotates the log files every time it boots into the recovery
mode. We lose useful logs after ten times. This CL changes the rotation
condition so that it will rotate only if it performs some actual
operations that modify the flash (installs, wipes, sideloads and etc).

Bug: 19695622
Change-Id: Ie708ad955ef31aa500b6590c65faa72391705940
diff --git a/adb_install.cpp b/adb_install.cpp
index 6d6dbb1..ed15938 100644
--- a/adb_install.cpp
+++ b/adb_install.cpp
@@ -74,6 +74,8 @@
 
 int
 apply_from_adb(RecoveryUI* ui_, bool* wipe_cache, const char* install_file) {
+    modified_flash = true;
+
     ui = ui_;
 
     stop_adbd();
diff --git a/common.h b/common.h
index 4f1c099..b818ceb 100644
--- a/common.h
+++ b/common.h
@@ -40,6 +40,7 @@
 #define STRINGIFY(x) #x
 #define EXPAND(x) STRINGIFY(x)
 
+extern bool modified_flash;
 typedef struct fstab_rec Volume;
 
 // fopen a file, mounting volumes and making parent dirs as necessary.
diff --git a/install.cpp b/install.cpp
index 63b1d38..662f81c 100644
--- a/install.cpp
+++ b/install.cpp
@@ -256,6 +256,8 @@
 install_package(const char* path, bool* wipe_cache, const char* install_file,
                 bool needs_mount)
 {
+    modified_flash = true;
+
     FILE* install_log = fopen_path(install_file, "w");
     if (install_log) {
         fputs(path, install_log);
diff --git a/recovery.cpp b/recovery.cpp
index 0ba4d1e..2f8654a 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -92,6 +92,7 @@
 char recovery_version[PROPERTY_VALUE_MAX+1];
 char* stage = NULL;
 char* reason = NULL;
+bool modified_flash = false;
 
 /*
  * The recovery tool communicates with the main system through /cache files.
@@ -337,13 +338,18 @@
 
 // Rename last_log -> last_log.1 -> last_log.2 -> ... -> last_log.$max
 // Overwrites any existing last_log.$max.
-static void
-rotate_last_logs(int max) {
+static void rotate_last_logs(int max) {
+    // Logs should only be rotated once.
+    static bool rotated = false;
+    if (rotated) {
+        return;
+    }
+    rotated = true;
+    ensure_path_mounted(LAST_LOG_FILE);
+
     char oldfn[256];
     char newfn[256];
-
-    int i;
-    for (i = max-1; i >= 0; --i) {
+    for (int i = max-1; i >= 0; --i) {
         snprintf(oldfn, sizeof(oldfn), (i==0) ? LAST_LOG_FILE : (LAST_LOG_FILE ".%d"), i);
         snprintf(newfn, sizeof(newfn), LAST_LOG_FILE ".%d", i+1);
         // ignore errors
@@ -351,8 +357,17 @@
     }
 }
 
-static void
-copy_logs() {
+static void copy_logs() {
+    // We only rotate and record the log of the current session if there are
+    // actual attempts to modify the flash, such as wipes, installs from BCB
+    // or menu selections. This is to avoid unnecessary rotation (and
+    // possible deletion) of log files, if it does not do anything loggable.
+    if (!modified_flash) {
+        return;
+    }
+
+    rotate_last_logs(KEEP_LOG_COUNT);
+
     // Copy logs to cache so the system can find out what happened.
     copy_log_file(TEMPORARY_LOG_FILE, LOG_FILE, true);
     copy_log_file(TEMPORARY_LOG_FILE, LAST_LOG_FILE, false);
@@ -692,6 +707,8 @@
         return false;
     }
 
+    modified_flash = true;
+
     ui->Print("\n-- Wiping data...\n");
     if (device->WipeData() == 0 && erase_volume("/data") == 0 && erase_volume("/cache") == 0) {
         ui->Print("Data wipe complete.\n");
@@ -708,6 +725,8 @@
         return false;
     }
 
+    modified_flash = true;
+
     ui->Print("\n-- Wiping cache...\n");
     if (erase_volume("/cache") == 0) {
         ui->Print("Cache wipe complete.\n");
@@ -816,6 +835,8 @@
 }
 
 static int apply_from_sdcard(Device* device, bool* wipe_cache) {
+    modified_flash = true;
+
     if (ensure_path_mounted(SDCARD_ROOT) != 0) {
         ui->Print("\n-- Couldn't mount %s.\n", SDCARD_ROOT);
         return INSTALL_ERROR;
@@ -990,8 +1011,6 @@
     printf("Starting recovery (pid %d) on %s", getpid(), ctime(&start));
 
     load_volume_table();
-    ensure_path_mounted(LAST_LOG_FILE);
-    rotate_last_logs(KEEP_LOG_COUNT);
     get_args(&argc, &argv);
 
     const char *send_intent = NULL;