blob: 2e44ff866015e4630f7731f584d52e92061d7b1a [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
2// Copyright (C) 2012 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//
rspangler@google.com49fdf182009-10-10 00:57:34 +000016
Alex Deymo39910dc2015-11-09 17:04:30 -080017#include "update_engine/common/test_utils.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070018
Alex Deymo6b9e38e2015-06-05 00:26:37 +020019#include <dirent.h>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000020#include <errno.h>
Alex Deymocbc22742016-03-04 17:53:02 -080021#include <fcntl.h>
22#include <linux/loop.h>
23#include <linux/major.h>
rspangler@google.com49fdf182009-10-10 00:57:34 +000024#include <stdio.h>
25#include <stdlib.h>
Alex Deymocbc22742016-03-04 17:53:02 -080026#include <sys/ioctl.h>
Sen Jiangd37c81f2017-11-02 18:35:56 -070027#include <sys/mount.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070028#include <sys/stat.h>
Elliott Hughesce7b5692017-05-18 16:44:49 -070029#include <sys/sysmacros.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070030#include <sys/types.h>
rspangler@google.com49fdf182009-10-10 00:57:34 +000031#include <unistd.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070032
adlr@google.comc98a7ed2009-12-04 18:54:03 +000033#include <set>
rspangler@google.com49fdf182009-10-10 00:57:34 +000034#include <string>
35#include <vector>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070036
Alex Deymo2b19cfb2015-03-26 00:35:07 -070037#include <base/files/file_util.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070038#include <base/logging.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070039
Alex Deymo64d98782016-02-05 18:03:48 -080040#include "update_engine/common/error_code_utils.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080041#include "update_engine/common/utils.h"
42#include "update_engine/payload_consumer/file_writer.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000043
adlr@google.comc98a7ed2009-12-04 18:54:03 +000044using std::set;
rspangler@google.com49fdf182009-10-10 00:57:34 +000045using std::string;
46using std::vector;
47
Sen Jiangc01f41a2018-11-16 17:19:40 -080048namespace {
49
50#ifdef __ANDROID__
51#define kLoopDevicePrefix "/dev/block/loop"
52#else
53#define kLoopDevicePrefix "/dev/loop"
54#endif // __ANDROID__
55
56} // namespace
57
rspangler@google.com49fdf182009-10-10 00:57:34 +000058namespace chromeos_update_engine {
59
Alex Deymo52490e72015-06-04 14:53:44 +020060void PrintTo(const Extent& extent, ::std::ostream* os) {
61 *os << "(" << extent.start_block() << ", " << extent.num_blocks() << ")";
62}
63
Alex Deymo64d98782016-02-05 18:03:48 -080064void PrintTo(const ErrorCode& error_code, ::std::ostream* os) {
65 *os << utils::ErrorCodeToString(error_code);
66}
67
Alex Deymo10875d92014-11-10 21:52:57 -080068namespace test_utils {
69
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080070const uint8_t kRandomString[] = {
Alex Deymo10875d92014-11-10 21:52:57 -080071 0xf2, 0xb7, 0x55, 0x92, 0xea, 0xa6, 0xc9, 0x57,
72 0xe0, 0xf8, 0xeb, 0x34, 0x93, 0xd9, 0xc4, 0x8f,
73 0xcb, 0x20, 0xfa, 0x37, 0x4b, 0x40, 0xcf, 0xdc,
74 0xa5, 0x08, 0x70, 0x89, 0x79, 0x35, 0xe2, 0x3d,
75 0x56, 0xa4, 0x75, 0x73, 0xa3, 0x6d, 0xd1, 0xd5,
76 0x26, 0xbb, 0x9c, 0x60, 0xbd, 0x2f, 0x5a, 0xfa,
77 0xb7, 0xd4, 0x3a, 0x50, 0xa7, 0x6b, 0x3e, 0xfd,
78 0x61, 0x2b, 0x3a, 0x31, 0x30, 0x13, 0x33, 0x53,
79 0xdb, 0xd0, 0x32, 0x71, 0x5c, 0x39, 0xed, 0xda,
80 0xb4, 0x84, 0xca, 0xbc, 0xbd, 0x78, 0x1c, 0x0c,
81 0xd8, 0x0b, 0x41, 0xe8, 0xe1, 0xe0, 0x41, 0xad,
82 0x03, 0x12, 0xd3, 0x3d, 0xb8, 0x75, 0x9b, 0xe6,
83 0xd9, 0x01, 0xd0, 0x87, 0xf4, 0x36, 0xfa, 0xa7,
84 0x0a, 0xfa, 0xc5, 0x87, 0x65, 0xab, 0x9a, 0x7b,
85 0xeb, 0x58, 0x23, 0xf0, 0xa8, 0x0a, 0xf2, 0x33,
86 0x3a, 0xe2, 0xe3, 0x35, 0x74, 0x95, 0xdd, 0x3c,
87 0x59, 0x5a, 0xd9, 0x52, 0x3a, 0x3c, 0xac, 0xe5,
88 0x15, 0x87, 0x6d, 0x82, 0xbc, 0xf8, 0x7d, 0xbe,
89 0xca, 0xd3, 0x2c, 0xd6, 0xec, 0x38, 0xeb, 0xe4,
90 0x53, 0xb0, 0x4c, 0x3f, 0x39, 0x29, 0xf7, 0xa4,
91 0x73, 0xa8, 0xcb, 0x32, 0x50, 0x05, 0x8c, 0x1c,
92 0x1c, 0xca, 0xc9, 0x76, 0x0b, 0x8f, 0x6b, 0x57,
93 0x1f, 0x24, 0x2b, 0xba, 0x82, 0xba, 0xed, 0x58,
94 0xd8, 0xbf, 0xec, 0x06, 0x64, 0x52, 0x6a, 0x3f,
95 0xe4, 0xad, 0xce, 0x84, 0xb4, 0x27, 0x55, 0x14,
96 0xe3, 0x75, 0x59, 0x73, 0x71, 0x51, 0xea, 0xe8,
97 0xcc, 0xda, 0x4f, 0x09, 0xaf, 0xa4, 0xbc, 0x0e,
98 0xa6, 0x1f, 0xe2, 0x3a, 0xf8, 0x96, 0x7d, 0x30,
99 0x23, 0xc5, 0x12, 0xb5, 0xd8, 0x73, 0x6b, 0x71,
100 0xab, 0xf1, 0xd7, 0x43, 0x58, 0xa7, 0xc9, 0xf0,
101 0xe4, 0x85, 0x1c, 0xd6, 0x92, 0x50, 0x2c, 0x98,
102 0x36, 0xfe, 0x87, 0xaf, 0x43, 0x8f, 0x8f, 0xf5,
103 0x88, 0x48, 0x18, 0x42, 0xcf, 0x42, 0xc1, 0xa8,
104 0xe8, 0x05, 0x08, 0xa1, 0x45, 0x70, 0x5b, 0x8c,
105 0x39, 0x28, 0xab, 0xe9, 0x6b, 0x51, 0xd2, 0xcb,
106 0x30, 0x04, 0xea, 0x7d, 0x2f, 0x6e, 0x6c, 0x3b,
107 0x5f, 0x82, 0xd9, 0x5b, 0x89, 0x37, 0x65, 0x65,
108 0xbe, 0x9f, 0xa3, 0x5d,
109};
110
Alex Deymod15c5462016-03-09 18:11:12 -0800111string Readlink(const string& path) {
112 vector<char> buf(PATH_MAX + 1);
113 ssize_t r = readlink(path.c_str(), buf.data(), buf.size());
114 if (r < 0)
115 return "";
116 CHECK_LT(r, static_cast<ssize_t>(buf.size()));
117 return string(buf.begin(), buf.begin() + r);
118}
119
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700120bool WriteFileVector(const string& path, const brillo::Blob& data) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800121 return utils::WriteFile(path.c_str(), data.data(), data.size());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000122}
123
Alex Deymof329b932014-10-30 01:37:48 -0700124bool WriteFileString(const string& path, const string& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -0800125 return utils::WriteFile(path.c_str(), data.data(), data.size());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000126}
127
Alex Deymocbc22742016-03-04 17:53:02 -0800128bool BindToUnusedLoopDevice(const string& filename,
129 bool writable,
130 string* out_lo_dev_name) {
131 CHECK(out_lo_dev_name);
132 // Get the next available loop-device.
133 int control_fd =
134 HANDLE_EINTR(open("/dev/loop-control", O_RDWR | O_LARGEFILE));
135 TEST_AND_RETURN_FALSE_ERRNO(control_fd >= 0);
136 int loop_number = ioctl(control_fd, LOOP_CTL_GET_FREE);
137 IGNORE_EINTR(close(control_fd));
Sen Jiangc01f41a2018-11-16 17:19:40 -0800138 *out_lo_dev_name = kLoopDevicePrefix + std::to_string(loop_number);
Don Garrett58e8b1f2012-01-31 16:38:16 -0800139
Alex Deymocbc22742016-03-04 17:53:02 -0800140 // Double check that the loop exists and is free.
141 int loop_device_fd =
142 HANDLE_EINTR(open(out_lo_dev_name->c_str(), O_RDWR | O_LARGEFILE));
143 if (loop_device_fd == -1 && errno == ENOENT) {
144 // Workaround the case when the loop device doesn't exist.
145 TEST_AND_RETURN_FALSE_ERRNO(mknod(out_lo_dev_name->c_str(),
146 S_IFBLK | 0660,
147 makedev(LOOP_MAJOR, loop_number)) == 0);
148 loop_device_fd =
149 HANDLE_EINTR(open(out_lo_dev_name->c_str(), O_RDWR | O_LARGEFILE));
150 }
151 TEST_AND_RETURN_FALSE_ERRNO(loop_device_fd != -1);
152 ScopedFdCloser loop_device_fd_closer(&loop_device_fd);
153
154 struct loop_info64 device_info;
155 if (ioctl(loop_device_fd, LOOP_GET_STATUS64, &device_info) != -1 ||
156 errno != ENXIO) {
157 PLOG(ERROR) << "Loop device " << out_lo_dev_name->c_str()
158 << " already in use";
Gilad Arnold19a45f02012-07-19 12:36:10 -0700159 return false;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000160 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000161
Alex Deymocbc22742016-03-04 17:53:02 -0800162 // Open our data file and assign it to the loop device.
163 int data_fd = open(filename.c_str(),
164 (writable ? O_RDWR : O_RDONLY) | O_LARGEFILE | O_CLOEXEC);
165 TEST_AND_RETURN_FALSE_ERRNO(data_fd >= 0);
166 ScopedFdCloser data_fd_closer(&data_fd);
167 TEST_AND_RETURN_FALSE_ERRNO(ioctl(loop_device_fd, LOOP_SET_FD, data_fd) == 0);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000168
Alex Deymocbc22742016-03-04 17:53:02 -0800169 memset(&device_info, 0, sizeof(device_info));
170 device_info.lo_offset = 0;
171 device_info.lo_sizelimit = 0; // 0 means whole file.
172 device_info.lo_flags = (writable ? 0 : LO_FLAGS_READ_ONLY);
173 device_info.lo_number = loop_number;
174 strncpy(reinterpret_cast<char*>(device_info.lo_file_name),
175 base::FilePath(filename).BaseName().value().c_str(),
176 LO_NAME_SIZE - 1);
177 device_info.lo_file_name[LO_NAME_SIZE - 1] = '\0';
178 TEST_AND_RETURN_FALSE_ERRNO(
179 ioctl(loop_device_fd, LOOP_SET_STATUS64, &device_info) == 0);
Sen Jiangd37c81f2017-11-02 18:35:56 -0700180 if (writable) {
181 // Make sure loop device isn't read only.
182 int ro = 0;
183 if (ioctl(loop_device_fd, BLKROSET, &ro) != 0) {
184 PLOG(WARNING) << "Failed to mark loop device writable.";
185 }
186 }
Alex Deymocbc22742016-03-04 17:53:02 -0800187 return true;
188}
189
190bool UnbindLoopDevice(const string& lo_dev_name) {
191 int loop_device_fd =
192 HANDLE_EINTR(open(lo_dev_name.c_str(), O_RDWR | O_LARGEFILE));
193 if (loop_device_fd == -1 && errno == ENOENT)
194 return true;
195 TEST_AND_RETURN_FALSE_ERRNO(loop_device_fd != -1);
196 ScopedFdCloser loop_device_fd_closer(&loop_device_fd);
197
198 struct loop_info64 device_info;
199 // Check if the device is bound before trying to unbind it.
200 int get_stat_err = ioctl(loop_device_fd, LOOP_GET_STATUS64, &device_info);
201 if (get_stat_err == -1 && errno == ENXIO)
202 return true;
203
204 TEST_AND_RETURN_FALSE_ERRNO(ioctl(loop_device_fd, LOOP_CLR_FD) == 0);
Gilad Arnold19a45f02012-07-19 12:36:10 -0700205 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000206}
207
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700208bool ExpectVectorsEq(const brillo::Blob& expected,
209 const brillo::Blob& actual) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800210 EXPECT_EQ(expected.size(), actual.size());
211 if (expected.size() != actual.size())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000212 return false;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700213 bool is_all_eq = true;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800214 for (unsigned int i = 0; i < expected.size(); i++) {
215 EXPECT_EQ(expected[i], actual[i]) << "offset: " << i;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700216 is_all_eq = is_all_eq && (expected[i] == actual[i]);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000217 }
Gilad Arnold617bbc22012-05-15 08:48:13 -0700218 return is_all_eq;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000219}
220
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700221void FillWithData(brillo::Blob* buffer) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800222 size_t input_counter = 0;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800223 for (uint8_t& b : *buffer) {
224 b = kRandomString[input_counter];
Andrew de los Reyes80061062010-02-04 14:25:00 -0800225 input_counter++;
226 input_counter %= sizeof(kRandomString);
227 }
228}
229
Don Garrett58e8b1f2012-01-31 16:38:16 -0800230ScopedLoopMounter::ScopedLoopMounter(const string& file_path,
231 string* mnt_path,
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700232 unsigned long flags) { // NOLINT - long
Sen Jiang371615b2016-04-13 15:54:29 -0700233 EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
Hidehiko Abe2b9d2412017-12-13 18:56:18 +0900234 *mnt_path = temp_dir_.GetPath().value();
Thieu Le5c7d9752010-12-15 16:09:28 -0800235
Don Garrett58e8b1f2012-01-31 16:38:16 -0800236 string loop_dev;
Alex Deymocbc22742016-03-04 17:53:02 -0800237 loop_binder_.reset(
238 new ScopedLoopbackDeviceBinder(file_path, true, &loop_dev));
Thieu Le5c7d9752010-12-15 16:09:28 -0800239
Sen Jiang2c413572016-03-07 12:55:09 -0800240 EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags, "", ""));
Thieu Le5c7d9752010-12-15 16:09:28 -0800241 unmounter_.reset(new ScopedFilesystemUnmounter(*mnt_path));
242}
243
Alex Deymo2b19cfb2015-03-26 00:35:07 -0700244base::FilePath GetBuildArtifactsPath() {
245 base::FilePath exe_path;
246 base::ReadSymbolicLink(base::FilePath("/proc/self/exe"), &exe_path);
247 return exe_path.DirName();
248}
249
Sen Jiang260f03b2016-03-21 15:34:58 -0700250string GetBuildArtifactsPath(const string& relative_path) {
251 return GetBuildArtifactsPath().Append(relative_path).value();
252}
253
Alex Deymo10875d92014-11-10 21:52:57 -0800254} // namespace test_utils
rspangler@google.com49fdf182009-10-10 00:57:34 +0000255} // namespace chromeos_update_engine