Browse Source

Add a singleton CacheLocation to replace the hard coded locations

This class allows us to set the following locations dynamically:
cache_temp_source, last_command_file, stash_directory_base.

In the updater's main function, we reset the values of these variables
to their default locations in /cache; while we can set them to temp
files in unit tests or host simulation.

Test: unit tests pass
Change-Id: I528652650caa41373617ab055d41b1f1a4ec0f87
Tianjie Xu 3 years ago
parent
commit
3bbb20f557

+ 5
- 6
applypatch/applypatch.cpp View File

@@ -40,10 +40,9 @@
40 40
 
41 41
 #include "edify/expr.h"
42 42
 #include "otafault/ota_io.h"
43
+#include "otautil/cache_location.h"
43 44
 #include "otautil/print_sha1.h"
44 45
 
45
-std::string cache_temp_source = "/cache/saved.file";
46
-
47 46
 static int LoadPartitionContents(const std::string& filename, FileContents* file);
48 47
 static size_t FileSink(const unsigned char* data, size_t len, int fd);
49 48
 static int GenerateTarget(const FileContents& source_file, const std::unique_ptr<Value>& patch,
@@ -404,7 +403,7 @@ int applypatch_check(const char* filename, const std::vector<std::string>& patch
404 403
     // If the source file is missing or corrupted, it might be because we were killed in the middle
405 404
     // of patching it.  A copy of it should have been made in cache_temp_source.  If that file
406 405
     // exists and matches the sha1 we're looking for, the check still passes.
407
-    if (LoadFileContents(cache_temp_source.c_str(), &file) != 0) {
406
+    if (LoadFileContents(CacheLocation::location().cache_temp_source().c_str(), &file) != 0) {
408 407
       printf("failed to load cache file\n");
409 408
       return 1;
410 409
     }
@@ -526,7 +525,7 @@ int applypatch(const char* source_filename, const char* target_filename,
526 525
   printf("source file is bad; trying copy\n");
527 526
 
528 527
   FileContents copy_file;
529
-  if (LoadFileContents(cache_temp_source.c_str(), &copy_file) < 0) {
528
+  if (LoadFileContents(CacheLocation::location().cache_temp_source().c_str(), &copy_file) < 0) {
530 529
     printf("failed to read copy file\n");
531 530
     return 1;
532 531
   }
@@ -621,7 +620,7 @@ static int GenerateTarget(const FileContents& source_file, const std::unique_ptr
621 620
     printf("not enough free space on /cache\n");
622 621
     return 1;
623 622
   }
624
-  if (SaveFileContents(cache_temp_source.c_str(), &source_file) < 0) {
623
+  if (SaveFileContents(CacheLocation::location().cache_temp_source().c_str(), &source_file) < 0) {
625 624
     printf("failed to back up source file\n");
626 625
     return 1;
627 626
   }
@@ -667,7 +666,7 @@ static int GenerateTarget(const FileContents& source_file, const std::unique_ptr
667 666
   }
668 667
 
669 668
   // Delete the backup copy of the source.
670
-  unlink(cache_temp_source.c_str());
669
+  unlink(CacheLocation::location().cache_temp_source().c_str());
671 670
 
672 671
   // Success!
673 672
   return 0;

+ 2
- 1
applypatch/freecache.cpp View File

@@ -33,6 +33,7 @@
33 33
 #include <android-base/stringprintf.h>
34 34
 
35 35
 #include "applypatch/applypatch.h"
36
+#include "otautil/cache_location.h"
36 37
 
37 38
 static int EliminateOpenFiles(std::set<std::string>* files) {
38 39
   std::unique_ptr<DIR, decltype(&closedir)> d(opendir("/proc"), closedir);
@@ -92,7 +93,7 @@ static std::set<std::string> FindExpendableFiles() {
92 93
 
93 94
       // We can't delete cache_temp_source; if it's there we might have restarted during
94 95
       // installation and could be depending on it to be there.
95
-      if (path == cache_temp_source) {
96
+      if (path == CacheLocation::location().cache_temp_source()) {
96 97
         continue;
97 98
       }
98 99
 

+ 0
- 6
applypatch/include/applypatch/applypatch.h View File

@@ -34,12 +34,6 @@ struct FileContents {
34 34
   std::vector<unsigned char> data;
35 35
 };
36 36
 
37
-// When there isn't enough room on the target filesystem to hold the patched version of the file,
38
-// we copy the original here and delete it to free up space.  If the expected source file doesn't
39
-// exist, or is corrupted, we look to see if the cached file contains the bits we want and use it as
40
-// the source instead.  The default location for the cached source is "/cache/saved.file".
41
-extern std::string cache_temp_source;
42
-
43 37
 using SinkFn = std::function<size_t(const unsigned char*, size_t)>;
44 38
 
45 39
 // applypatch.cpp

+ 1
- 0
otautil/Android.bp View File

@@ -21,6 +21,7 @@ cc_library_static {
21 21
         "SysUtil.cpp",
22 22
         "DirUtil.cpp",
23 23
         "ThermalUtil.cpp",
24
+        "cache_location.cpp",
24 25
         "rangeset.cpp",
25 26
     ],
26 27
 

+ 32
- 0
otautil/cache_location.cpp View File

@@ -0,0 +1,32 @@
1
+/*
2
+ * Copyright (C) 2018 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 "otautil/cache_location.h"
18
+
19
+constexpr const char kDefaultCacheTempSource[] = "/cache/saved.file";
20
+constexpr const char kDefaultLastCommandFile[] = "/cache/recovery/last_command";
21
+constexpr const char kDefaultStashDirectoryBase[] = "/cache/recovery";
22
+
23
+CacheLocation& CacheLocation::location() {
24
+  static CacheLocation cache_location;
25
+  return cache_location;
26
+}
27
+
28
+void CacheLocation::ResetLocations() {
29
+  cache_temp_source_ = kDefaultCacheTempSource;
30
+  last_command_file_ = kDefaultLastCommandFile;
31
+  stash_directory_base_ = kDefaultStashDirectoryBase;
32
+}

+ 72
- 0
otautil/include/otautil/cache_location.h View File

@@ -0,0 +1,72 @@
1
+/*
2
+ * Copyright (C) 2018 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
+#ifndef _OTAUTIL_OTAUTIL_CACHE_LOCATION_H_
18
+#define _OTAUTIL_OTAUTIL_CACHE_LOCATION_H_
19
+
20
+#include <string>
21
+
22
+#include "android-base/macros.h"
23
+
24
+// A singleton class to maintain the update related locations. The locations should be only set
25
+// once at the start of the program.
26
+class CacheLocation {
27
+ public:
28
+  static CacheLocation& location();
29
+
30
+  // Reset the locations to their default values.
31
+  void ResetLocations();
32
+
33
+  // getter and setter functions.
34
+  std::string cache_temp_source() const {
35
+    return cache_temp_source_;
36
+  }
37
+  void set_cache_temp_source(const std::string& temp_source) {
38
+    cache_temp_source_ = temp_source;
39
+  }
40
+
41
+  std::string last_command_file() const {
42
+    return last_command_file_;
43
+  }
44
+  void set_last_command_file(const std::string& last_command) {
45
+    last_command_file_ = last_command;
46
+  }
47
+
48
+  std::string stash_directory_base() const {
49
+    return stash_directory_base_;
50
+  }
51
+  void set_stash_directory_base(const std::string& base) {
52
+    stash_directory_base_ = base;
53
+  }
54
+
55
+ private:
56
+  CacheLocation() {}
57
+  DISALLOW_COPY_AND_ASSIGN(CacheLocation);
58
+
59
+  // When there isn't enough room on the target filesystem to hold the patched version of the file,
60
+  // we copy the original here and delete it to free up space.  If the expected source file doesn't
61
+  // exist, or is corrupted, we look to see if the cached file contains the bits we want and use it
62
+  // as the source instead.  The default location for the cached source is "/cache/saved.file".
63
+  std::string cache_temp_source_;
64
+
65
+  // Location to save the last command that stashes blocks.
66
+  std::string last_command_file_;
67
+
68
+  // The base directory to write stashes during update.
69
+  std::string stash_directory_base_;
70
+};
71
+
72
+#endif  // _OTAUTIL_OTAUTIL_CACHE_LOCATION_H_

+ 3
- 2
tests/component/applypatch_test.cpp View File

@@ -35,6 +35,7 @@
35 35
 #include "applypatch/applypatch.h"
36 36
 #include "applypatch/applypatch_modes.h"
37 37
 #include "common/test_constants.h"
38
+#include "otautil/cache_location.h"
38 39
 #include "otautil/print_sha1.h"
39 40
 
40 41
 static void sha1sum(const std::string& fname, std::string* sha1, size_t* fsize = nullptr) {
@@ -93,14 +94,14 @@ class ApplyPatchCacheTest : public ApplyPatchTest {
93 94
  protected:
94 95
   void SetUp() override {
95 96
     ApplyPatchTest::SetUp();
96
-    cache_temp_source = old_file;
97
+    CacheLocation::location().set_cache_temp_source(old_file);
97 98
   }
98 99
 };
99 100
 
100 101
 class ApplyPatchModesTest : public ::testing::Test {
101 102
  protected:
102 103
   void SetUp() override {
103
-    cache_temp_source = cache_source.path;
104
+    CacheLocation::location().set_cache_temp_source(cache_source.path);
104 105
   }
105 106
 
106 107
   TemporaryFile cache_source;

+ 14
- 7
tests/component/updater_test.cpp View File

@@ -41,6 +41,7 @@
41 41
 #include "common/test_constants.h"
42 42
 #include "edify/expr.h"
43 43
 #include "otautil/SysUtil.h"
44
+#include "otautil/cache_location.h"
44 45
 #include "otautil/error_code.h"
45 46
 #include "otautil/print_sha1.h"
46 47
 #include "updater/blockimg.h"
@@ -104,7 +105,16 @@ class UpdaterTest : public ::testing::Test {
104 105
     RegisterBuiltins();
105 106
     RegisterInstallFunctions();
106 107
     RegisterBlockImageFunctions();
108
+
109
+    // Mock the location of last_command_file.
110
+    CacheLocation::location().set_cache_temp_source(temp_saved_source_.path);
111
+    CacheLocation::location().set_last_command_file(temp_last_command_.path);
112
+    CacheLocation::location().set_stash_directory_base(temp_stash_base_.path);
107 113
   }
114
+
115
+  TemporaryFile temp_saved_source_;
116
+  TemporaryFile temp_last_command_;
117
+  TemporaryDir temp_stash_base_;
108 118
 };
109 119
 
110 120
 TEST_F(UpdaterTest, getprop) {
@@ -542,7 +552,7 @@ TEST_F(UpdaterTest, block_image_update_fail) {
542 552
   expect("", script.c_str(), kNoCause, &updater_info);
543 553
   // Updater generates the stash name based on the input file name.
544 554
   std::string name_digest = get_sha1(update_file.path);
545
-  std::string stash_base = "/cache/recovery/" + name_digest;
555
+  std::string stash_base = std::string(temp_stash_base_.path) + "/" + name_digest;
546 556
   ASSERT_EQ(0, access(stash_base.c_str(), F_OK));
547 557
   ASSERT_EQ(-1, access((stash_base + src_hash).c_str(), F_OK));
548 558
   ASSERT_EQ(0, rmdir(stash_base.c_str()));
@@ -709,8 +719,7 @@ TEST_F(UpdaterTest, brotli_new_data) {
709 719
 }
710 720
 
711 721
 TEST_F(UpdaterTest, last_command_update) {
712
-  TemporaryFile temp_file;
713
-  last_command_file = temp_file.path;
722
+  std::string last_command_file = CacheLocation::location().last_command_file();
714 723
 
715 724
   std::string block1 = std::string(4096, '1');
716 725
   std::string block2 = std::string(4096, '2');
@@ -797,8 +806,7 @@ TEST_F(UpdaterTest, last_command_update) {
797 806
 }
798 807
 
799 808
 TEST_F(UpdaterTest, last_command_update_unresumable) {
800
-  TemporaryFile temp_file;
801
-  last_command_file = temp_file.path;
809
+  std::string last_command_file = CacheLocation::location().last_command_file();
802 810
 
803 811
   std::string block1 = std::string(4096, '1');
804 812
   std::string block2 = std::string(4096, '2');
@@ -853,8 +861,7 @@ TEST_F(UpdaterTest, last_command_update_unresumable) {
853 861
 }
854 862
 
855 863
 TEST_F(UpdaterTest, last_command_verify) {
856
-  TemporaryFile temp_file;
857
-  last_command_file = temp_file.path;
864
+  std::string last_command_file = CacheLocation::location().last_command_file();
858 865
 
859 866
   std::string block1 = std::string(4096, '1');
860 867
   std::string block2 = std::string(4096, '2');

+ 5
- 4
updater/blockimg.cpp View File

@@ -53,6 +53,7 @@
53 53
 
54 54
 #include "edify/expr.h"
55 55
 #include "otafault/ota_io.h"
56
+#include "otautil/cache_location.h"
56 57
 #include "otautil/error_code.h"
57 58
 #include "otautil/print_sha1.h"
58 59
 #include "otautil/rangeset.h"
@@ -65,17 +66,15 @@
65 66
 #define DEBUG_ERASE  0
66 67
 
67 68
 static constexpr size_t BLOCKSIZE = 4096;
68
-static constexpr const char* STASH_DIRECTORY_BASE = "/cache/recovery";
69 69
 static constexpr mode_t STASH_DIRECTORY_MODE = 0700;
70 70
 static constexpr mode_t STASH_FILE_MODE = 0600;
71 71
 
72
-std::string last_command_file = "/cache/recovery/last_command";
73
-
74 72
 static CauseCode failure_type = kNoCause;
75 73
 static bool is_retry = false;
76 74
 static std::unordered_map<std::string, RangeSet> stash_map;
77 75
 
78 76
 static void DeleteLastCommandFile() {
77
+  std::string last_command_file = CacheLocation::location().last_command_file();
79 78
   if (unlink(last_command_file.c_str()) == -1 && errno != ENOENT) {
80 79
     PLOG(ERROR) << "Failed to unlink: " << last_command_file;
81 80
   }
@@ -84,6 +83,7 @@ static void DeleteLastCommandFile() {
84 83
 // Parse the last command index of the last update and save the result to |last_command_index|.
85 84
 // Return true if we successfully read the index.
86 85
 static bool ParseLastCommandFile(int* last_command_index) {
86
+  std::string last_command_file = CacheLocation::location().last_command_file();
87 87
   android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(last_command_file.c_str(), O_RDONLY)));
88 88
   if (fd == -1) {
89 89
     if (errno != ENOENT) {
@@ -119,6 +119,7 @@ static bool ParseLastCommandFile(int* last_command_index) {
119 119
 // Update the last command index in the last_command_file if the current command writes to the
120 120
 // stash either explicitly or implicitly.
121 121
 static bool UpdateLastCommandIndex(int command_index, const std::string& command_string) {
122
+  std::string last_command_file = CacheLocation::location().last_command_file();
122 123
   std::string last_command_tmp = last_command_file + ".tmp";
123 124
   std::string content = std::to_string(command_index) + "\n" + command_string;
124 125
   android::base::unique_fd wfd(
@@ -676,7 +677,7 @@ static std::string GetStashFileName(const std::string& base, const std::string&
676 677
         return "";
677 678
     }
678 679
 
679
-    std::string fn(STASH_DIRECTORY_BASE);
680
+    std::string fn(CacheLocation::location().stash_directory_base());
680 681
     fn += "/" + base + "/" + id + postfix;
681 682
 
682 683
     return fn;

+ 0
- 1
updater/include/updater/blockimg.h View File

@@ -19,7 +19,6 @@
19 19
 
20 20
 #include <string>
21 21
 
22
-extern std::string last_command_file;
23 22
 void RegisterBlockImageFunctions();
24 23
 
25 24
 #endif

+ 5
- 0
updater/updater.cpp View File

@@ -34,6 +34,7 @@
34 34
 #include "otafault/config.h"
35 35
 #include "otautil/DirUtil.h"
36 36
 #include "otautil/SysUtil.h"
37
+#include "otautil/cache_location.h"
37 38
 #include "otautil/error_code.h"
38 39
 #include "updater/blockimg.h"
39 40
 #include "updater/install.h"
@@ -168,6 +169,10 @@ int main(int argc, char** argv) {
168 169
   }
169 170
   ota_io_init(za, state.is_retry);
170 171
 
172
+  // Initialize the cache_temp_source, last_command_file and stash_directory_base to their default
173
+  // locations.
174
+  CacheLocation::location().ResetLocations();
175
+
171 176
   std::string result;
172 177
   bool status = Evaluate(&state, root, &result);
173 178