blob: f83ddf98d1ba33cad0ff6697012cac67df92b0ee [file] [log] [blame]
rspangler@google.com49fdf182009-10-10 00:57:34 +00001// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
adlr@google.comc98a7ed2009-12-04 18:54:03 +00005#include "update_engine/test_utils.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +00006#include <sys/stat.h>
7#include <sys/types.h>
adlr@google.comc98a7ed2009-12-04 18:54:03 +00008#include <errno.h>
rspangler@google.com49fdf182009-10-10 00:57:34 +00009#include <stdio.h>
10#include <stdlib.h>
11#include <unistd.h>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000012#include <set>
rspangler@google.com49fdf182009-10-10 00:57:34 +000013#include <string>
14#include <vector>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000015#include "base/string_util.h"
16#include "chromeos/obsolete_logging.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000017
18#include "update_engine/file_writer.h"
adlr@google.comc98a7ed2009-12-04 18:54:03 +000019#include "update_engine/filesystem_iterator.h"
20#include "update_engine/utils.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000021
adlr@google.comc98a7ed2009-12-04 18:54:03 +000022using std::set;
rspangler@google.com49fdf182009-10-10 00:57:34 +000023using std::string;
24using std::vector;
25
26namespace chromeos_update_engine {
27
adlr@google.comc98a7ed2009-12-04 18:54:03 +000028bool WriteFileVector(const std::string& path, const std::vector<char>& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -080029 return utils::WriteFile(path.c_str(), &data[0], data.size());
adlr@google.comc98a7ed2009-12-04 18:54:03 +000030}
31
32bool WriteFileString(const std::string& path, const std::string& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -080033 return utils::WriteFile(path.c_str(), data.data(), data.size());
rspangler@google.com49fdf182009-10-10 00:57:34 +000034}
35
36off_t FileSize(const string& path) {
37 struct stat stbuf;
38 int rc = stat(path.c_str(), &stbuf);
adlr@google.comc98a7ed2009-12-04 18:54:03 +000039 CHECK_EQ(rc, 0);
rspangler@google.com49fdf182009-10-10 00:57:34 +000040 if (rc < 0)
41 return rc;
42 return stbuf.st_size;
43}
44
adlr@google.comc98a7ed2009-12-04 18:54:03 +000045std::string Readlink(const std::string& path) {
46 vector<char> buf(PATH_MAX + 1);
47 ssize_t r = readlink(path.c_str(), &buf[0], buf.size());
48 if (r < 0)
49 return "";
50 CHECK_LT(r, static_cast<ssize_t>(buf.size()));
51 buf.resize(r);
52 string ret;
53 ret.insert(ret.begin(), buf.begin(), buf.end());
54 return ret;
55}
56
rspangler@google.com49fdf182009-10-10 00:57:34 +000057std::vector<char> GzipCompressData(const std::vector<char>& data) {
58 const char fname[] = "/tmp/GzipCompressDataTemp";
adlr@google.comc98a7ed2009-12-04 18:54:03 +000059 if (!WriteFileVector(fname, data)) {
rspangler@google.com49fdf182009-10-10 00:57:34 +000060 system((string("rm ") + fname).c_str());
61 return vector<char>();
62 }
63 system((string("cat ") + fname + "|gzip>" + fname + ".gz").c_str());
64 system((string("rm ") + fname).c_str());
adlr@google.comc98a7ed2009-12-04 18:54:03 +000065 vector<char> ret;
66 EXPECT_TRUE(utils::ReadFile(string(fname) + ".gz", &ret));
rspangler@google.com49fdf182009-10-10 00:57:34 +000067 system((string("rm ") + fname + ".gz").c_str());
68 return ret;
69}
70
adlr@google.comc98a7ed2009-12-04 18:54:03 +000071vector<char> GenerateSampleMbr() {
72 // This is the actual MBR from my dev machine. Partition 1 (the first)
73 // is currently marked bootable
74 char mbr[512] = {
75 0xeb, 0x48, 0x90, 0x10, 0x8e, 0xd0, 0xbc, 0x00,
76 0xb0, 0xb8, 0x00, 0x00, 0x8e, 0xd8, 0x8e, 0xc0,
77 0xfb, 0xbe, 0x00, 0x7c, 0xbf, 0x00, 0x06, 0xb9,
78 0x00, 0x02, 0xf3, 0xa4, 0xea, 0x21, 0x06, 0x00,
79 0x00, 0xbe, 0xbe, 0x07, 0x38, 0x04, 0x75, 0x0b,
80 0x83, 0xc6, 0x10, 0x81, 0xfe, 0xfe, 0x07, 0x75,
81 0xf3, 0xeb, 0x16, 0xb4, 0x02, 0xb0, 0x01, 0xbb,
82 0x00, 0x7c, 0xb2, 0x80, 0x8a, 0x74, 0x03, 0x02,
83 0xff, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00,
84 0x00, 0x02, 0xfa, 0x90, 0x90, 0xf6, 0xc2, 0x80,
85 0x75, 0x02, 0xb2, 0x80, 0xea, 0x59, 0x7c, 0x00,
86 0x00, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xd0, 0xbc,
87 0x00, 0x20, 0xfb, 0xa0, 0x40, 0x7c, 0x3c, 0xff,
88 0x74, 0x02, 0x88, 0xc2, 0x52, 0xbe, 0x7f, 0x7d,
89 0xe8, 0x34, 0x01, 0xf6, 0xc2, 0x80, 0x74, 0x54,
90 0xb4, 0x41, 0xbb, 0xaa, 0x55, 0xcd, 0x13, 0x5a,
91 0x52, 0x72, 0x49, 0x81, 0xfb, 0x55, 0xaa, 0x75,
92 0x43, 0xa0, 0x41, 0x7c, 0x84, 0xc0, 0x75, 0x05,
93 0x83, 0xe1, 0x01, 0x74, 0x37, 0x66, 0x8b, 0x4c,
94 0x10, 0xbe, 0x05, 0x7c, 0xc6, 0x44, 0xff, 0x01,
95 0x66, 0x8b, 0x1e, 0x44, 0x7c, 0xc7, 0x04, 0x10,
96 0x00, 0xc7, 0x44, 0x02, 0x01, 0x00, 0x66, 0x89,
97 0x5c, 0x08, 0xc7, 0x44, 0x06, 0x00, 0x70, 0x66,
98 0x31, 0xc0, 0x89, 0x44, 0x04, 0x66, 0x89, 0x44,
99 0x0c, 0xb4, 0x42, 0xcd, 0x13, 0x72, 0x05, 0xbb,
100 0x00, 0x70, 0xeb, 0x7d, 0xb4, 0x08, 0xcd, 0x13,
101 0x73, 0x0a, 0xf6, 0xc2, 0x80, 0x0f, 0x84, 0xea,
102 0x00, 0xe9, 0x8d, 0x00, 0xbe, 0x05, 0x7c, 0xc6,
103 0x44, 0xff, 0x00, 0x66, 0x31, 0xc0, 0x88, 0xf0,
104 0x40, 0x66, 0x89, 0x44, 0x04, 0x31, 0xd2, 0x88,
105 0xca, 0xc1, 0xe2, 0x02, 0x88, 0xe8, 0x88, 0xf4,
106 0x40, 0x89, 0x44, 0x08, 0x31, 0xc0, 0x88, 0xd0,
107 0xc0, 0xe8, 0x02, 0x66, 0x89, 0x04, 0x66, 0xa1,
108 0x44, 0x7c, 0x66, 0x31, 0xd2, 0x66, 0xf7, 0x34,
109 0x88, 0x54, 0x0a, 0x66, 0x31, 0xd2, 0x66, 0xf7,
110 0x74, 0x04, 0x88, 0x54, 0x0b, 0x89, 0x44, 0x0c,
111 0x3b, 0x44, 0x08, 0x7d, 0x3c, 0x8a, 0x54, 0x0d,
112 0xc0, 0xe2, 0x06, 0x8a, 0x4c, 0x0a, 0xfe, 0xc1,
113 0x08, 0xd1, 0x8a, 0x6c, 0x0c, 0x5a, 0x8a, 0x74,
114 0x0b, 0xbb, 0x00, 0x70, 0x8e, 0xc3, 0x31, 0xdb,
115 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x72, 0x2a, 0x8c,
116 0xc3, 0x8e, 0x06, 0x48, 0x7c, 0x60, 0x1e, 0xb9,
117 0x00, 0x01, 0x8e, 0xdb, 0x31, 0xf6, 0x31, 0xff,
118 0xfc, 0xf3, 0xa5, 0x1f, 0x61, 0xff, 0x26, 0x42,
119 0x7c, 0xbe, 0x85, 0x7d, 0xe8, 0x40, 0x00, 0xeb,
120 0x0e, 0xbe, 0x8a, 0x7d, 0xe8, 0x38, 0x00, 0xeb,
121 0x06, 0xbe, 0x94, 0x7d, 0xe8, 0x30, 0x00, 0xbe,
122 0x99, 0x7d, 0xe8, 0x2a, 0x00, 0xeb, 0xfe, 0x47,
123 0x52, 0x55, 0x42, 0x20, 0x00, 0x47, 0x65, 0x6f,
124 0x6d, 0x00, 0x48, 0x61, 0x72, 0x64, 0x20, 0x44,
125 0x69, 0x73, 0x6b, 0x00, 0x52, 0x65, 0x61, 0x64,
126 0x00, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x00,
127 0xbb, 0x01, 0x00, 0xb4, 0x0e, 0xcd, 0x10, 0xac,
128 0x3c, 0x00, 0x75, 0xf4, 0xc3, 0x00, 0x00, 0x00,
129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
130 0x50, 0xc1, 0x04, 0x00, 0x00, 0x00, 0x80, 0x01,
131 0x01, 0x00, 0x83, 0xfe, 0xff, 0xff, 0x3f, 0x00,
132 0x00, 0x00, 0x09, 0x7f, 0x32, 0x06, 0x00, 0xfe,
133 0xff, 0xff, 0x05, 0xfe, 0xff, 0xff, 0x48, 0x7f,
134 0x32, 0x06, 0x79, 0x59, 0x2d, 0x00, 0x00, 0x00,
135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
139 };
140 vector<char> ret;
141 ret.insert(ret.begin(), mbr, mbr + sizeof(mbr));
142 return ret;
143}
144
145std::string GetUnusedLoopDevice() {
146 // get a loop device we can use for the install device
147 FILE* find_dev_cmd = popen("losetup -f", "r");
148 CHECK(find_dev_cmd);
149
150 string ret;
151 char dev[100] = {0};
152 size_t r;
153 while ((r = fread(dev, 1, sizeof(dev - 1), find_dev_cmd)) > 0) {
154 EXPECT_LT(r, sizeof(dev));
155 ret.insert(ret.end(), dev, dev + r);
156 }
157 EXPECT_EQ(r, 0);
158 EXPECT_TRUE(feof(find_dev_cmd));
159 fclose(find_dev_cmd);
160
161 // strip trailing \n on dev
162 if (*ret.rbegin() == '\n')
163 ret.resize(ret.size() - 1);
164
165 return ret;
166}
167
168bool ExpectVectorsEq(const vector<char>& a, const vector<char>& b) {
169 EXPECT_EQ(a.size(), b.size());
170 if (a.size() != b.size())
171 return false;
172 for (unsigned int i = 0; i < a.size(); i++) {
173 EXPECT_EQ(a[i], b[i]) << "offset: " << i;
174 }
175 return true;
176}
177
178void CreateExtImageAtPath(const string& path, vector<string>* out_paths) {
179 // create 10MiB sparse file
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000180 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
181 " seek=10485759 bs=1 count=1",
182 path.c_str())));
183 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -F %s", path.c_str())));
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -0800184 EXPECT_EQ(0, System(StringPrintf("mkdir -p %s", kMountPath)));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000185 EXPECT_EQ(0, System(StringPrintf("mount -o loop %s %s", path.c_str(),
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -0800186 kMountPath)));
187 EXPECT_EQ(0, System(StringPrintf("echo hi > %s/hi", kMountPath)));
188 EXPECT_EQ(0, System(StringPrintf("echo hello > %s/hello", kMountPath)));
189 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir", kMountPath)));
190 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/empty_dir", kMountPath)));
191 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/mnt", kMountPath)));
192 EXPECT_EQ(0, System(StringPrintf("echo T > %s/some_dir/test", kMountPath)));
193 EXPECT_EQ(0, System(StringPrintf("mkfifo %s/some_dir/fifo", kMountPath)));
194 EXPECT_EQ(0, System(StringPrintf("mknod %s/cdev c 2 3", kMountPath)));
195 EXPECT_EQ(0, System(StringPrintf("ln -s /some/target %s/sym", kMountPath)));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000196 EXPECT_EQ(0, System(StringPrintf("ln %s/some_dir/test %s/testlink",
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -0800197 kMountPath, kMountPath)));
198 EXPECT_EQ(0, System(StringPrintf("umount %s", kMountPath)));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000199
200 if (out_paths) {
201 out_paths->clear();
202 out_paths->push_back("");
203 out_paths->push_back("/hi");
204 out_paths->push_back("/hello");
205 out_paths->push_back("/some_dir");
206 out_paths->push_back("/some_dir/empty_dir");
207 out_paths->push_back("/some_dir/mnt");
208 out_paths->push_back("/some_dir/test");
209 out_paths->push_back("/some_dir/fifo");
210 out_paths->push_back("/cdev");
211 out_paths->push_back("/testlink");
212 out_paths->push_back("/sym");
213 out_paths->push_back("/lost+found");
214 }
215}
216
217void VerifyAllPaths(const string& parent, set<string> expected_paths) {
218 FilesystemIterator iter(parent, set<string>());
219 ino_t test_ino = 0;
220 ino_t testlink_ino = 0;
221 while (!iter.IsEnd()) {
222 string path = iter.GetFullPath();
223 EXPECT_TRUE(expected_paths.find(path) != expected_paths.end()) << path;
224 EXPECT_EQ(1, expected_paths.erase(path));
225 if (utils::StringHasSuffix(path, "/hi") ||
226 utils::StringHasSuffix(path, "/hello") ||
227 utils::StringHasSuffix(path, "/test") ||
228 utils::StringHasSuffix(path, "/testlink")) {
229 EXPECT_TRUE(S_ISREG(iter.GetStat().st_mode));
230 if (utils::StringHasSuffix(path, "/test"))
231 test_ino = iter.GetStat().st_ino;
232 else if (utils::StringHasSuffix(path, "/testlink"))
233 testlink_ino = iter.GetStat().st_ino;
234 } else if (utils::StringHasSuffix(path, "/some_dir") ||
235 utils::StringHasSuffix(path, "/empty_dir") ||
236 utils::StringHasSuffix(path, "/mnt") ||
237 utils::StringHasSuffix(path, "/lost+found") ||
238 parent == path) {
239 EXPECT_TRUE(S_ISDIR(iter.GetStat().st_mode));
240 } else if (utils::StringHasSuffix(path, "/fifo")) {
241 EXPECT_TRUE(S_ISFIFO(iter.GetStat().st_mode));
242 } else if (utils::StringHasSuffix(path, "/cdev")) {
243 EXPECT_TRUE(S_ISCHR(iter.GetStat().st_mode));
244 } else if (utils::StringHasSuffix(path, "/sym")) {
245 EXPECT_TRUE(S_ISLNK(iter.GetStat().st_mode));
246 } else {
247 LOG(INFO) << "got non hardcoded path: " << path;
248 }
249 iter.Increment();
250 }
251 EXPECT_EQ(testlink_ino, test_ino);
252 EXPECT_NE(0, test_ino);
253 EXPECT_FALSE(iter.IsErr());
254 EXPECT_TRUE(expected_paths.empty());
255 if (!expected_paths.empty()) {
256 for (set<string>::const_iterator it = expected_paths.begin();
257 it != expected_paths.end(); ++it) {
258 LOG(INFO) << "extra path: " << *it;
259 }
260 }
261}
262
rspangler@google.com49fdf182009-10-10 00:57:34 +0000263} // namespace chromeos_update_engine