1 //
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 //
16
17 #include "update_engine/common/test_utils.h"
18
19 #include <dirent.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <linux/loop.h>
23 #include <linux/major.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <sys/ioctl.h>
27 #include <sys/mount.h>
28 #include <sys/stat.h>
29 #include <sys/sysmacros.h>
30 #include <sys/types.h>
31 #include <sys/xattr.h>
32 #include <unistd.h>
33
34 #include <set>
35 #include <string>
36 #include <vector>
37
38 #include <base/files/file_util.h>
39 #include <base/format_macros.h>
40 #include <base/logging.h>
41 #include <base/strings/string_util.h>
42 #include <base/strings/stringprintf.h>
43
44 #include "update_engine/common/error_code_utils.h"
45 #include "update_engine/common/utils.h"
46 #include "update_engine/payload_consumer/file_writer.h"
47
48 using base::StringPrintf;
49 using std::set;
50 using std::string;
51 using std::vector;
52
53 namespace chromeos_update_engine {
54
PrintTo(const Extent & extent,::std::ostream * os)55 void PrintTo(const Extent& extent, ::std::ostream* os) {
56 *os << "(" << extent.start_block() << ", " << extent.num_blocks() << ")";
57 }
58
PrintTo(const ErrorCode & error_code,::std::ostream * os)59 void PrintTo(const ErrorCode& error_code, ::std::ostream* os) {
60 *os << utils::ErrorCodeToString(error_code);
61 }
62
63 namespace test_utils {
64
65 const uint8_t kRandomString[] = {
66 0xf2, 0xb7, 0x55, 0x92, 0xea, 0xa6, 0xc9, 0x57,
67 0xe0, 0xf8, 0xeb, 0x34, 0x93, 0xd9, 0xc4, 0x8f,
68 0xcb, 0x20, 0xfa, 0x37, 0x4b, 0x40, 0xcf, 0xdc,
69 0xa5, 0x08, 0x70, 0x89, 0x79, 0x35, 0xe2, 0x3d,
70 0x56, 0xa4, 0x75, 0x73, 0xa3, 0x6d, 0xd1, 0xd5,
71 0x26, 0xbb, 0x9c, 0x60, 0xbd, 0x2f, 0x5a, 0xfa,
72 0xb7, 0xd4, 0x3a, 0x50, 0xa7, 0x6b, 0x3e, 0xfd,
73 0x61, 0x2b, 0x3a, 0x31, 0x30, 0x13, 0x33, 0x53,
74 0xdb, 0xd0, 0x32, 0x71, 0x5c, 0x39, 0xed, 0xda,
75 0xb4, 0x84, 0xca, 0xbc, 0xbd, 0x78, 0x1c, 0x0c,
76 0xd8, 0x0b, 0x41, 0xe8, 0xe1, 0xe0, 0x41, 0xad,
77 0x03, 0x12, 0xd3, 0x3d, 0xb8, 0x75, 0x9b, 0xe6,
78 0xd9, 0x01, 0xd0, 0x87, 0xf4, 0x36, 0xfa, 0xa7,
79 0x0a, 0xfa, 0xc5, 0x87, 0x65, 0xab, 0x9a, 0x7b,
80 0xeb, 0x58, 0x23, 0xf0, 0xa8, 0x0a, 0xf2, 0x33,
81 0x3a, 0xe2, 0xe3, 0x35, 0x74, 0x95, 0xdd, 0x3c,
82 0x59, 0x5a, 0xd9, 0x52, 0x3a, 0x3c, 0xac, 0xe5,
83 0x15, 0x87, 0x6d, 0x82, 0xbc, 0xf8, 0x7d, 0xbe,
84 0xca, 0xd3, 0x2c, 0xd6, 0xec, 0x38, 0xeb, 0xe4,
85 0x53, 0xb0, 0x4c, 0x3f, 0x39, 0x29, 0xf7, 0xa4,
86 0x73, 0xa8, 0xcb, 0x32, 0x50, 0x05, 0x8c, 0x1c,
87 0x1c, 0xca, 0xc9, 0x76, 0x0b, 0x8f, 0x6b, 0x57,
88 0x1f, 0x24, 0x2b, 0xba, 0x82, 0xba, 0xed, 0x58,
89 0xd8, 0xbf, 0xec, 0x06, 0x64, 0x52, 0x6a, 0x3f,
90 0xe4, 0xad, 0xce, 0x84, 0xb4, 0x27, 0x55, 0x14,
91 0xe3, 0x75, 0x59, 0x73, 0x71, 0x51, 0xea, 0xe8,
92 0xcc, 0xda, 0x4f, 0x09, 0xaf, 0xa4, 0xbc, 0x0e,
93 0xa6, 0x1f, 0xe2, 0x3a, 0xf8, 0x96, 0x7d, 0x30,
94 0x23, 0xc5, 0x12, 0xb5, 0xd8, 0x73, 0x6b, 0x71,
95 0xab, 0xf1, 0xd7, 0x43, 0x58, 0xa7, 0xc9, 0xf0,
96 0xe4, 0x85, 0x1c, 0xd6, 0x92, 0x50, 0x2c, 0x98,
97 0x36, 0xfe, 0x87, 0xaf, 0x43, 0x8f, 0x8f, 0xf5,
98 0x88, 0x48, 0x18, 0x42, 0xcf, 0x42, 0xc1, 0xa8,
99 0xe8, 0x05, 0x08, 0xa1, 0x45, 0x70, 0x5b, 0x8c,
100 0x39, 0x28, 0xab, 0xe9, 0x6b, 0x51, 0xd2, 0xcb,
101 0x30, 0x04, 0xea, 0x7d, 0x2f, 0x6e, 0x6c, 0x3b,
102 0x5f, 0x82, 0xd9, 0x5b, 0x89, 0x37, 0x65, 0x65,
103 0xbe, 0x9f, 0xa3, 0x5d,
104 };
105
Readlink(const string & path)106 string Readlink(const string& path) {
107 vector<char> buf(PATH_MAX + 1);
108 ssize_t r = readlink(path.c_str(), buf.data(), buf.size());
109 if (r < 0)
110 return "";
111 CHECK_LT(r, static_cast<ssize_t>(buf.size()));
112 return string(buf.begin(), buf.begin() + r);
113 }
114
IsXAttrSupported(const base::FilePath & dir_path)115 bool IsXAttrSupported(const base::FilePath& dir_path) {
116 char *path = strdup(dir_path.Append("xattr_test_XXXXXX").value().c_str());
117
118 int fd = mkstemp(path);
119 if (fd == -1) {
120 PLOG(ERROR) << "Error creating temporary file in " << dir_path.value();
121 free(path);
122 return false;
123 }
124
125 if (unlink(path) != 0) {
126 PLOG(ERROR) << "Error unlinking temporary file " << path;
127 close(fd);
128 free(path);
129 return false;
130 }
131
132 int xattr_res = fsetxattr(fd, "user.xattr-test", "value", strlen("value"), 0);
133 if (xattr_res != 0) {
134 if (errno == ENOTSUP) {
135 // Leave it to call-sites to warn about non-support.
136 } else {
137 PLOG(ERROR) << "Error setting xattr on " << path;
138 }
139 }
140 close(fd);
141 free(path);
142 return xattr_res == 0;
143 }
144
WriteFileVector(const string & path,const brillo::Blob & data)145 bool WriteFileVector(const string& path, const brillo::Blob& data) {
146 return utils::WriteFile(path.c_str(), data.data(), data.size());
147 }
148
WriteFileString(const string & path,const string & data)149 bool WriteFileString(const string& path, const string& data) {
150 return utils::WriteFile(path.c_str(), data.data(), data.size());
151 }
152
BindToUnusedLoopDevice(const string & filename,bool writable,string * out_lo_dev_name)153 bool BindToUnusedLoopDevice(const string& filename,
154 bool writable,
155 string* out_lo_dev_name) {
156 CHECK(out_lo_dev_name);
157 // Get the next available loop-device.
158 int control_fd =
159 HANDLE_EINTR(open("/dev/loop-control", O_RDWR | O_LARGEFILE));
160 TEST_AND_RETURN_FALSE_ERRNO(control_fd >= 0);
161 int loop_number = ioctl(control_fd, LOOP_CTL_GET_FREE);
162 IGNORE_EINTR(close(control_fd));
163 *out_lo_dev_name = StringPrintf("/dev/loop%d", loop_number);
164
165 // Double check that the loop exists and is free.
166 int loop_device_fd =
167 HANDLE_EINTR(open(out_lo_dev_name->c_str(), O_RDWR | O_LARGEFILE));
168 if (loop_device_fd == -1 && errno == ENOENT) {
169 // Workaround the case when the loop device doesn't exist.
170 TEST_AND_RETURN_FALSE_ERRNO(mknod(out_lo_dev_name->c_str(),
171 S_IFBLK | 0660,
172 makedev(LOOP_MAJOR, loop_number)) == 0);
173 loop_device_fd =
174 HANDLE_EINTR(open(out_lo_dev_name->c_str(), O_RDWR | O_LARGEFILE));
175 }
176 TEST_AND_RETURN_FALSE_ERRNO(loop_device_fd != -1);
177 ScopedFdCloser loop_device_fd_closer(&loop_device_fd);
178
179 struct loop_info64 device_info;
180 if (ioctl(loop_device_fd, LOOP_GET_STATUS64, &device_info) != -1 ||
181 errno != ENXIO) {
182 PLOG(ERROR) << "Loop device " << out_lo_dev_name->c_str()
183 << " already in use";
184 return false;
185 }
186
187 // Open our data file and assign it to the loop device.
188 int data_fd = open(filename.c_str(),
189 (writable ? O_RDWR : O_RDONLY) | O_LARGEFILE | O_CLOEXEC);
190 TEST_AND_RETURN_FALSE_ERRNO(data_fd >= 0);
191 ScopedFdCloser data_fd_closer(&data_fd);
192 TEST_AND_RETURN_FALSE_ERRNO(ioctl(loop_device_fd, LOOP_SET_FD, data_fd) == 0);
193
194 memset(&device_info, 0, sizeof(device_info));
195 device_info.lo_offset = 0;
196 device_info.lo_sizelimit = 0; // 0 means whole file.
197 device_info.lo_flags = (writable ? 0 : LO_FLAGS_READ_ONLY);
198 device_info.lo_number = loop_number;
199 strncpy(reinterpret_cast<char*>(device_info.lo_file_name),
200 base::FilePath(filename).BaseName().value().c_str(),
201 LO_NAME_SIZE - 1);
202 device_info.lo_file_name[LO_NAME_SIZE - 1] = '\0';
203 TEST_AND_RETURN_FALSE_ERRNO(
204 ioctl(loop_device_fd, LOOP_SET_STATUS64, &device_info) == 0);
205 if (writable) {
206 // Make sure loop device isn't read only.
207 int ro = 0;
208 if (ioctl(loop_device_fd, BLKROSET, &ro) != 0) {
209 PLOG(WARNING) << "Failed to mark loop device writable.";
210 }
211 }
212 return true;
213 }
214
UnbindLoopDevice(const string & lo_dev_name)215 bool UnbindLoopDevice(const string& lo_dev_name) {
216 int loop_device_fd =
217 HANDLE_EINTR(open(lo_dev_name.c_str(), O_RDWR | O_LARGEFILE));
218 if (loop_device_fd == -1 && errno == ENOENT)
219 return true;
220 TEST_AND_RETURN_FALSE_ERRNO(loop_device_fd != -1);
221 ScopedFdCloser loop_device_fd_closer(&loop_device_fd);
222
223 struct loop_info64 device_info;
224 // Check if the device is bound before trying to unbind it.
225 int get_stat_err = ioctl(loop_device_fd, LOOP_GET_STATUS64, &device_info);
226 if (get_stat_err == -1 && errno == ENXIO)
227 return true;
228
229 TEST_AND_RETURN_FALSE_ERRNO(ioctl(loop_device_fd, LOOP_CLR_FD) == 0);
230 return true;
231 }
232
ExpectVectorsEq(const brillo::Blob & expected,const brillo::Blob & actual)233 bool ExpectVectorsEq(const brillo::Blob& expected,
234 const brillo::Blob& actual) {
235 EXPECT_EQ(expected.size(), actual.size());
236 if (expected.size() != actual.size())
237 return false;
238 bool is_all_eq = true;
239 for (unsigned int i = 0; i < expected.size(); i++) {
240 EXPECT_EQ(expected[i], actual[i]) << "offset: " << i;
241 is_all_eq = is_all_eq && (expected[i] == actual[i]);
242 }
243 return is_all_eq;
244 }
245
FillWithData(brillo::Blob * buffer)246 void FillWithData(brillo::Blob* buffer) {
247 size_t input_counter = 0;
248 for (uint8_t& b : *buffer) {
249 b = kRandomString[input_counter];
250 input_counter++;
251 input_counter %= sizeof(kRandomString);
252 }
253 }
254
ScopedLoopMounter(const string & file_path,string * mnt_path,unsigned long flags)255 ScopedLoopMounter::ScopedLoopMounter(const string& file_path,
256 string* mnt_path,
257 unsigned long flags) { // NOLINT - long
258 EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
259 *mnt_path = temp_dir_.GetPath().value();
260
261 string loop_dev;
262 loop_binder_.reset(
263 new ScopedLoopbackDeviceBinder(file_path, true, &loop_dev));
264
265 EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags, "", ""));
266 unmounter_.reset(new ScopedFilesystemUnmounter(*mnt_path));
267 }
268
GetBuildArtifactsPath()269 base::FilePath GetBuildArtifactsPath() {
270 base::FilePath exe_path;
271 base::ReadSymbolicLink(base::FilePath("/proc/self/exe"), &exe_path);
272 return exe_path.DirName();
273 }
274
GetBuildArtifactsPath(const string & relative_path)275 string GetBuildArtifactsPath(const string& relative_path) {
276 return GetBuildArtifactsPath().Append(relative_path).value();
277 }
278
279 } // namespace test_utils
280 } // namespace chromeos_update_engine
281