blob: bd69d03905c0bc5c99e1159b63a5f7e7f76a193b [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
Tianjie Xu173e6192019-12-10 10:56:01 -080040#ifdef __ANDROID__
41#include <libdm/loop_control.h>
42#endif
43
Alex Deymo64d98782016-02-05 18:03:48 -080044#include "update_engine/common/error_code_utils.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080045#include "update_engine/common/utils.h"
46#include "update_engine/payload_consumer/file_writer.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000047
adlr@google.comc98a7ed2009-12-04 18:54:03 +000048using std::set;
rspangler@google.com49fdf182009-10-10 00:57:34 +000049using std::string;
50using std::vector;
Tianjie Xu173e6192019-12-10 10:56:01 -080051using namespace std::chrono_literals;
Sen Jiangc01f41a2018-11-16 17:19:40 -080052
rspangler@google.com49fdf182009-10-10 00:57:34 +000053namespace chromeos_update_engine {
54
Alex Deymo52490e72015-06-04 14:53:44 +020055void PrintTo(const Extent& extent, ::std::ostream* os) {
56 *os << "(" << extent.start_block() << ", " << extent.num_blocks() << ")";
57}
58
Alex Deymo64d98782016-02-05 18:03:48 -080059void PrintTo(const ErrorCode& error_code, ::std::ostream* os) {
60 *os << utils::ErrorCodeToString(error_code);
61}
62
Alex Deymo10875d92014-11-10 21:52:57 -080063namespace test_utils {
64
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080065const uint8_t kRandomString[] = {
Amin Hassanib2689592019-01-13 17:04:28 -080066 0xf2, 0xb7, 0x55, 0x92, 0xea, 0xa6, 0xc9, 0x57, 0xe0, 0xf8, 0xeb, 0x34,
67 0x93, 0xd9, 0xc4, 0x8f, 0xcb, 0x20, 0xfa, 0x37, 0x4b, 0x40, 0xcf, 0xdc,
68 0xa5, 0x08, 0x70, 0x89, 0x79, 0x35, 0xe2, 0x3d, 0x56, 0xa4, 0x75, 0x73,
69 0xa3, 0x6d, 0xd1, 0xd5, 0x26, 0xbb, 0x9c, 0x60, 0xbd, 0x2f, 0x5a, 0xfa,
70 0xb7, 0xd4, 0x3a, 0x50, 0xa7, 0x6b, 0x3e, 0xfd, 0x61, 0x2b, 0x3a, 0x31,
71 0x30, 0x13, 0x33, 0x53, 0xdb, 0xd0, 0x32, 0x71, 0x5c, 0x39, 0xed, 0xda,
72 0xb4, 0x84, 0xca, 0xbc, 0xbd, 0x78, 0x1c, 0x0c, 0xd8, 0x0b, 0x41, 0xe8,
73 0xe1, 0xe0, 0x41, 0xad, 0x03, 0x12, 0xd3, 0x3d, 0xb8, 0x75, 0x9b, 0xe6,
74 0xd9, 0x01, 0xd0, 0x87, 0xf4, 0x36, 0xfa, 0xa7, 0x0a, 0xfa, 0xc5, 0x87,
75 0x65, 0xab, 0x9a, 0x7b, 0xeb, 0x58, 0x23, 0xf0, 0xa8, 0x0a, 0xf2, 0x33,
76 0x3a, 0xe2, 0xe3, 0x35, 0x74, 0x95, 0xdd, 0x3c, 0x59, 0x5a, 0xd9, 0x52,
77 0x3a, 0x3c, 0xac, 0xe5, 0x15, 0x87, 0x6d, 0x82, 0xbc, 0xf8, 0x7d, 0xbe,
78 0xca, 0xd3, 0x2c, 0xd6, 0xec, 0x38, 0xeb, 0xe4, 0x53, 0xb0, 0x4c, 0x3f,
79 0x39, 0x29, 0xf7, 0xa4, 0x73, 0xa8, 0xcb, 0x32, 0x50, 0x05, 0x8c, 0x1c,
80 0x1c, 0xca, 0xc9, 0x76, 0x0b, 0x8f, 0x6b, 0x57, 0x1f, 0x24, 0x2b, 0xba,
81 0x82, 0xba, 0xed, 0x58, 0xd8, 0xbf, 0xec, 0x06, 0x64, 0x52, 0x6a, 0x3f,
82 0xe4, 0xad, 0xce, 0x84, 0xb4, 0x27, 0x55, 0x14, 0xe3, 0x75, 0x59, 0x73,
83 0x71, 0x51, 0xea, 0xe8, 0xcc, 0xda, 0x4f, 0x09, 0xaf, 0xa4, 0xbc, 0x0e,
84 0xa6, 0x1f, 0xe2, 0x3a, 0xf8, 0x96, 0x7d, 0x30, 0x23, 0xc5, 0x12, 0xb5,
85 0xd8, 0x73, 0x6b, 0x71, 0xab, 0xf1, 0xd7, 0x43, 0x58, 0xa7, 0xc9, 0xf0,
86 0xe4, 0x85, 0x1c, 0xd6, 0x92, 0x50, 0x2c, 0x98, 0x36, 0xfe, 0x87, 0xaf,
87 0x43, 0x8f, 0x8f, 0xf5, 0x88, 0x48, 0x18, 0x42, 0xcf, 0x42, 0xc1, 0xa8,
88 0xe8, 0x05, 0x08, 0xa1, 0x45, 0x70, 0x5b, 0x8c, 0x39, 0x28, 0xab, 0xe9,
89 0x6b, 0x51, 0xd2, 0xcb, 0x30, 0x04, 0xea, 0x7d, 0x2f, 0x6e, 0x6c, 0x3b,
90 0x5f, 0x82, 0xd9, 0x5b, 0x89, 0x37, 0x65, 0x65, 0xbe, 0x9f, 0xa3, 0x5d,
Alex Deymo10875d92014-11-10 21:52:57 -080091};
92
Alex Deymod15c5462016-03-09 18:11:12 -080093string Readlink(const string& path) {
94 vector<char> buf(PATH_MAX + 1);
95 ssize_t r = readlink(path.c_str(), buf.data(), buf.size());
96 if (r < 0)
97 return "";
98 CHECK_LT(r, static_cast<ssize_t>(buf.size()));
99 return string(buf.begin(), buf.begin() + r);
100}
101
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700102bool WriteFileVector(const string& path, const brillo::Blob& data) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800103 return utils::WriteFile(path.c_str(), data.data(), data.size());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000104}
105
Alex Deymof329b932014-10-30 01:37:48 -0700106bool WriteFileString(const string& path, const string& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -0800107 return utils::WriteFile(path.c_str(), data.data(), data.size());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000108}
109
Tianjie Xu173e6192019-12-10 10:56:01 -0800110bool SetLoopDeviceStatus(int loop_device_fd,
111 const std::string& filename,
112 int loop_number,
113 bool writable) {
114 struct loop_info64 device_info {};
115 device_info.lo_offset = 0;
116 device_info.lo_sizelimit = 0; // 0 means whole file.
117 device_info.lo_flags = (writable ? 0 : LO_FLAGS_READ_ONLY);
118 device_info.lo_number = loop_number;
119 strncpy(reinterpret_cast<char*>(device_info.lo_file_name),
120 base::FilePath(filename).BaseName().value().c_str(),
121 LO_NAME_SIZE - 1);
122 device_info.lo_file_name[LO_NAME_SIZE - 1] = '\0';
123 TEST_AND_RETURN_FALSE_ERRNO(
124 ioctl(loop_device_fd, LOOP_SET_STATUS64, &device_info) == 0);
125 if (writable) {
126 // Make sure loop device isn't read only.
127 int ro = 0;
128 if (ioctl(loop_device_fd, BLKROSET, &ro) != 0) {
129 PLOG(WARNING) << "Failed to mark loop device writable.";
130 }
131 }
132
133 return true;
134}
135
136bool BindToUnusedLoopDeviceLegacy(int data_fd,
137 const string& filename,
138 bool writable,
139 string* out_lo_dev_name) {
Alex Deymocbc22742016-03-04 17:53:02 -0800140 // Get the next available loop-device.
141 int control_fd =
142 HANDLE_EINTR(open("/dev/loop-control", O_RDWR | O_LARGEFILE));
143 TEST_AND_RETURN_FALSE_ERRNO(control_fd >= 0);
144 int loop_number = ioctl(control_fd, LOOP_CTL_GET_FREE);
145 IGNORE_EINTR(close(control_fd));
Tianjie Xu173e6192019-12-10 10:56:01 -0800146 *out_lo_dev_name = "/dev/loop" + std::to_string(loop_number);
Don Garrett58e8b1f2012-01-31 16:38:16 -0800147
Alex Deymocbc22742016-03-04 17:53:02 -0800148 // Double check that the loop exists and is free.
149 int loop_device_fd =
150 HANDLE_EINTR(open(out_lo_dev_name->c_str(), O_RDWR | O_LARGEFILE));
151 if (loop_device_fd == -1 && errno == ENOENT) {
152 // Workaround the case when the loop device doesn't exist.
153 TEST_AND_RETURN_FALSE_ERRNO(mknod(out_lo_dev_name->c_str(),
154 S_IFBLK | 0660,
155 makedev(LOOP_MAJOR, loop_number)) == 0);
156 loop_device_fd =
157 HANDLE_EINTR(open(out_lo_dev_name->c_str(), O_RDWR | O_LARGEFILE));
158 }
159 TEST_AND_RETURN_FALSE_ERRNO(loop_device_fd != -1);
160 ScopedFdCloser loop_device_fd_closer(&loop_device_fd);
161
162 struct loop_info64 device_info;
163 if (ioctl(loop_device_fd, LOOP_GET_STATUS64, &device_info) != -1 ||
164 errno != ENXIO) {
165 PLOG(ERROR) << "Loop device " << out_lo_dev_name->c_str()
166 << " already in use";
Gilad Arnold19a45f02012-07-19 12:36:10 -0700167 return false;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000168 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000169
Tianjie Xu173e6192019-12-10 10:56:01 -0800170 // Assign the data fd to the loop device.
171 TEST_AND_RETURN_FALSE_ERRNO(ioctl(loop_device_fd, LOOP_SET_FD, data_fd) == 0);
172 return SetLoopDeviceStatus(loop_device_fd, filename, loop_number, writable);
173}
174
175bool BindToUnusedLoopDevice(const string& filename,
176 bool writable,
177 string* out_lo_dev_name) {
178 CHECK(out_lo_dev_name);
Alex Deymocbc22742016-03-04 17:53:02 -0800179 int data_fd = open(filename.c_str(),
180 (writable ? O_RDWR : O_RDONLY) | O_LARGEFILE | O_CLOEXEC);
181 TEST_AND_RETURN_FALSE_ERRNO(data_fd >= 0);
182 ScopedFdCloser data_fd_closer(&data_fd);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000183
Tianjie Xu173e6192019-12-10 10:56:01 -0800184#ifdef __ANDROID__
185 // Use libdm to bind a free loop device. The library internally handles the
186 // race condition.
187 android::dm::LoopControl loop_control;
188 TEST_AND_RETURN_FALSE(loop_control.Attach(data_fd, 5s, out_lo_dev_name));
189 int loop_device_fd = open(out_lo_dev_name->c_str(), O_RDWR | O_CLOEXEC);
190 ScopedFdCloser loop_fd_closer(&loop_device_fd);
191 int loop_number;
192 TEST_AND_RETURN_FALSE(
193 sscanf(out_lo_dev_name->c_str(), "/dev/block/loop%d", &loop_number) == 1);
194 return SetLoopDeviceStatus(loop_device_fd, filename, loop_number, writable);
195#else
196 return BindToUnusedLoopDeviceLegacy(
197 data_fd, filename, writable, out_lo_dev_name);
198#endif
Alex Deymocbc22742016-03-04 17:53:02 -0800199}
200
201bool UnbindLoopDevice(const string& lo_dev_name) {
202 int loop_device_fd =
203 HANDLE_EINTR(open(lo_dev_name.c_str(), O_RDWR | O_LARGEFILE));
204 if (loop_device_fd == -1 && errno == ENOENT)
205 return true;
206 TEST_AND_RETURN_FALSE_ERRNO(loop_device_fd != -1);
207 ScopedFdCloser loop_device_fd_closer(&loop_device_fd);
208
209 struct loop_info64 device_info;
210 // Check if the device is bound before trying to unbind it.
211 int get_stat_err = ioctl(loop_device_fd, LOOP_GET_STATUS64, &device_info);
212 if (get_stat_err == -1 && errno == ENXIO)
213 return true;
214
215 TEST_AND_RETURN_FALSE_ERRNO(ioctl(loop_device_fd, LOOP_CLR_FD) == 0);
Gilad Arnold19a45f02012-07-19 12:36:10 -0700216 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000217}
218
Amin Hassanib2689592019-01-13 17:04:28 -0800219bool ExpectVectorsEq(const brillo::Blob& expected, const brillo::Blob& actual) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800220 EXPECT_EQ(expected.size(), actual.size());
221 if (expected.size() != actual.size())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000222 return false;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700223 bool is_all_eq = true;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800224 for (unsigned int i = 0; i < expected.size(); i++) {
225 EXPECT_EQ(expected[i], actual[i]) << "offset: " << i;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700226 is_all_eq = is_all_eq && (expected[i] == actual[i]);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000227 }
Gilad Arnold617bbc22012-05-15 08:48:13 -0700228 return is_all_eq;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000229}
230
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700231void FillWithData(brillo::Blob* buffer) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800232 size_t input_counter = 0;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800233 for (uint8_t& b : *buffer) {
234 b = kRandomString[input_counter];
Andrew de los Reyes80061062010-02-04 14:25:00 -0800235 input_counter++;
236 input_counter %= sizeof(kRandomString);
237 }
238}
239
Don Garrett58e8b1f2012-01-31 16:38:16 -0800240ScopedLoopMounter::ScopedLoopMounter(const string& file_path,
241 string* mnt_path,
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700242 unsigned long flags) { // NOLINT - long
Sen Jiang371615b2016-04-13 15:54:29 -0700243 EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
Hidehiko Abe2b9d2412017-12-13 18:56:18 +0900244 *mnt_path = temp_dir_.GetPath().value();
Thieu Le5c7d9752010-12-15 16:09:28 -0800245
Don Garrett58e8b1f2012-01-31 16:38:16 -0800246 string loop_dev;
Alex Deymocbc22742016-03-04 17:53:02 -0800247 loop_binder_.reset(
248 new ScopedLoopbackDeviceBinder(file_path, true, &loop_dev));
Thieu Le5c7d9752010-12-15 16:09:28 -0800249
Sen Jiang2c413572016-03-07 12:55:09 -0800250 EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags, "", ""));
Thieu Le5c7d9752010-12-15 16:09:28 -0800251 unmounter_.reset(new ScopedFilesystemUnmounter(*mnt_path));
252}
253
Alex Deymo2b19cfb2015-03-26 00:35:07 -0700254base::FilePath GetBuildArtifactsPath() {
255 base::FilePath exe_path;
256 base::ReadSymbolicLink(base::FilePath("/proc/self/exe"), &exe_path);
257 return exe_path.DirName();
258}
259
Sen Jiang260f03b2016-03-21 15:34:58 -0700260string GetBuildArtifactsPath(const string& relative_path) {
261 return GetBuildArtifactsPath().Append(relative_path).value();
262}
263
Alex Deymo10875d92014-11-10 21:52:57 -0800264} // namespace test_utils
rspangler@google.com49fdf182009-10-10 00:57:34 +0000265} // namespace chromeos_update_engine