1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2012 The Android Open Source Project
3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License");
5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License.
6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at
7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//      http://www.apache.org/licenses/LICENSE-2.0
9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software
11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS,
12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and
14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License.
15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
1649fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
1739910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/test_utils.h"
1809e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes
196b9e38ef1180efe55e4a82bb18536d1b53fe493dAlex Deymo#include <dirent.h>
20c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com#include <errno.h>
21c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo#include <fcntl.h>
22c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo#include <linux/loop.h>
23c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo#include <linux/major.h>
2449fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com#include <stdio.h>
2549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com#include <stdlib.h>
26c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo#include <sys/ioctl.h>
27161c4a132743f15fc4757112b673085c2a7a7f29Alex Deymo#include <sys/stat.h>
28161c4a132743f15fc4757112b673085c2a7a7f29Alex Deymo#include <sys/types.h>
296f20dd4fc8861d93d188cd27323d2f9746464aafAlex Deymo#include <sys/xattr.h>
3049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com#include <unistd.h>
3109e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes
32c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com#include <set>
3349fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com#include <string>
3449fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com#include <vector>
3509e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes
362b19cfbcdb1aa8c5d1f338d19312fe14b6734bd5Alex Deymo#include <base/files/file_util.h>
37c00c98a1dad941e5cc04ce0b0e766d40b3b384e1Alex Deymo#include <base/format_macros.h>
38161c4a132743f15fc4757112b673085c2a7a7f29Alex Deymo#include <base/logging.h>
392b19cfbcdb1aa8c5d1f338d19312fe14b6734bd5Alex Deymo#include <base/strings/string_util.h>
40305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo#include <base/strings/stringprintf.h>
41161c4a132743f15fc4757112b673085c2a7a7f29Alex Deymo
4264d9878470aa7b388e971862181daf6260851602Alex Deymo#include "update_engine/common/error_code_utils.h"
4339910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/utils.h"
4439910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/payload_consumer/file_writer.h"
4549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
46161c4a132743f15fc4757112b673085c2a7a7f29Alex Deymousing base::StringPrintf;
47c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.comusing std::set;
4849fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comusing std::string;
4949fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comusing std::vector;
5049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
5149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comnamespace chromeos_update_engine {
5249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
5352490e776a9d34a94fb18ab1fe7d416425e94ddaAlex Deymovoid PrintTo(const Extent& extent, ::std::ostream* os) {
5452490e776a9d34a94fb18ab1fe7d416425e94ddaAlex Deymo  *os << "(" << extent.start_block() << ", " << extent.num_blocks() << ")";
5552490e776a9d34a94fb18ab1fe7d416425e94ddaAlex Deymo}
5652490e776a9d34a94fb18ab1fe7d416425e94ddaAlex Deymo
5764d9878470aa7b388e971862181daf6260851602Alex Deymovoid PrintTo(const ErrorCode& error_code, ::std::ostream* os) {
5864d9878470aa7b388e971862181daf6260851602Alex Deymo  *os << utils::ErrorCodeToString(error_code);
5964d9878470aa7b388e971862181daf6260851602Alex Deymo}
6064d9878470aa7b388e971862181daf6260851602Alex Deymo
6110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymonamespace test_utils {
6210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo
63a6742b35938b6f58e24e3f1c550fe92d4d33eb74Gilad Arnoldconst char* const kMountPathTemplate = "UpdateEngineTests_mnt-XXXXXX";
6461d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold
65f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenkoconst uint8_t kRandomString[] = {
6610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xf2, 0xb7, 0x55, 0x92, 0xea, 0xa6, 0xc9, 0x57,
6710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xe0, 0xf8, 0xeb, 0x34, 0x93, 0xd9, 0xc4, 0x8f,
6810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xcb, 0x20, 0xfa, 0x37, 0x4b, 0x40, 0xcf, 0xdc,
6910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xa5, 0x08, 0x70, 0x89, 0x79, 0x35, 0xe2, 0x3d,
7010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x56, 0xa4, 0x75, 0x73, 0xa3, 0x6d, 0xd1, 0xd5,
7110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x26, 0xbb, 0x9c, 0x60, 0xbd, 0x2f, 0x5a, 0xfa,
7210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xb7, 0xd4, 0x3a, 0x50, 0xa7, 0x6b, 0x3e, 0xfd,
7310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x61, 0x2b, 0x3a, 0x31, 0x30, 0x13, 0x33, 0x53,
7410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xdb, 0xd0, 0x32, 0x71, 0x5c, 0x39, 0xed, 0xda,
7510875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xb4, 0x84, 0xca, 0xbc, 0xbd, 0x78, 0x1c, 0x0c,
7610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xd8, 0x0b, 0x41, 0xe8, 0xe1, 0xe0, 0x41, 0xad,
7710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x03, 0x12, 0xd3, 0x3d, 0xb8, 0x75, 0x9b, 0xe6,
7810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xd9, 0x01, 0xd0, 0x87, 0xf4, 0x36, 0xfa, 0xa7,
7910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x0a, 0xfa, 0xc5, 0x87, 0x65, 0xab, 0x9a, 0x7b,
8010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xeb, 0x58, 0x23, 0xf0, 0xa8, 0x0a, 0xf2, 0x33,
8110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x3a, 0xe2, 0xe3, 0x35, 0x74, 0x95, 0xdd, 0x3c,
8210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x59, 0x5a, 0xd9, 0x52, 0x3a, 0x3c, 0xac, 0xe5,
8310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x15, 0x87, 0x6d, 0x82, 0xbc, 0xf8, 0x7d, 0xbe,
8410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xca, 0xd3, 0x2c, 0xd6, 0xec, 0x38, 0xeb, 0xe4,
8510875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x53, 0xb0, 0x4c, 0x3f, 0x39, 0x29, 0xf7, 0xa4,
8610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x73, 0xa8, 0xcb, 0x32, 0x50, 0x05, 0x8c, 0x1c,
8710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x1c, 0xca, 0xc9, 0x76, 0x0b, 0x8f, 0x6b, 0x57,
8810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x1f, 0x24, 0x2b, 0xba, 0x82, 0xba, 0xed, 0x58,
8910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xd8, 0xbf, 0xec, 0x06, 0x64, 0x52, 0x6a, 0x3f,
9010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xe4, 0xad, 0xce, 0x84, 0xb4, 0x27, 0x55, 0x14,
9110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xe3, 0x75, 0x59, 0x73, 0x71, 0x51, 0xea, 0xe8,
9210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xcc, 0xda, 0x4f, 0x09, 0xaf, 0xa4, 0xbc, 0x0e,
9310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xa6, 0x1f, 0xe2, 0x3a, 0xf8, 0x96, 0x7d, 0x30,
9410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x23, 0xc5, 0x12, 0xb5, 0xd8, 0x73, 0x6b, 0x71,
9510875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xab, 0xf1, 0xd7, 0x43, 0x58, 0xa7, 0xc9, 0xf0,
9610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xe4, 0x85, 0x1c, 0xd6, 0x92, 0x50, 0x2c, 0x98,
9710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x36, 0xfe, 0x87, 0xaf, 0x43, 0x8f, 0x8f, 0xf5,
9810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x88, 0x48, 0x18, 0x42, 0xcf, 0x42, 0xc1, 0xa8,
9910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xe8, 0x05, 0x08, 0xa1, 0x45, 0x70, 0x5b, 0x8c,
10010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x39, 0x28, 0xab, 0xe9, 0x6b, 0x51, 0xd2, 0xcb,
10110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x30, 0x04, 0xea, 0x7d, 0x2f, 0x6e, 0x6c, 0x3b,
10210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x5f, 0x82, 0xd9, 0x5b, 0x89, 0x37, 0x65, 0x65,
10310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xbe, 0x9f, 0xa3, 0x5d,
10410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo};
10510875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo
106bb0c067bf37c98cc55b6c79c1174084b1e0c9b0bAlex Deymostring Readlink(const string& path) {
107bb0c067bf37c98cc55b6c79c1174084b1e0c9b0bAlex Deymo  vector<char> buf(PATH_MAX + 1);
108bb0c067bf37c98cc55b6c79c1174084b1e0c9b0bAlex Deymo  ssize_t r = readlink(path.c_str(), buf.data(), buf.size());
109bb0c067bf37c98cc55b6c79c1174084b1e0c9b0bAlex Deymo  if (r < 0)
110bb0c067bf37c98cc55b6c79c1174084b1e0c9b0bAlex Deymo    return "";
111bb0c067bf37c98cc55b6c79c1174084b1e0c9b0bAlex Deymo  CHECK_LT(r, static_cast<ssize_t>(buf.size()));
112bb0c067bf37c98cc55b6c79c1174084b1e0c9b0bAlex Deymo  return string(buf.begin(), buf.begin() + r);
113bb0c067bf37c98cc55b6c79c1174084b1e0c9b0bAlex Deymo}
114bb0c067bf37c98cc55b6c79c1174084b1e0c9b0bAlex Deymo
11510875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymobool IsXAttrSupported(const base::FilePath& dir_path) {
11610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  char *path = strdup(dir_path.Append("xattr_test_XXXXXX").value().c_str());
11710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo
11810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  int fd = mkstemp(path);
11910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  if (fd == -1) {
12010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    PLOG(ERROR) << "Error creating temporary file in " << dir_path.value();
12110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    free(path);
12210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    return false;
12310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  }
12410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo
12510875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  if (unlink(path) != 0) {
12610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    PLOG(ERROR) << "Error unlinking temporary file " << path;
12710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    close(fd);
12810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    free(path);
12910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    return false;
13010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  }
13110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo
13210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  int xattr_res = fsetxattr(fd, "user.xattr-test", "value", strlen("value"), 0);
13310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  if (xattr_res != 0) {
13410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    if (errno == ENOTSUP) {
13510875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo      // Leave it to call-sites to warn about non-support.
13610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    } else {
13710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo      PLOG(ERROR) << "Error setting xattr on " << path;
13810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    }
13910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  }
14010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  close(fd);
14110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  free(path);
14210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  return xattr_res == 0;
14310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo}
14410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo
1453f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenkobool WriteFileVector(const string& path, const brillo::Blob& data) {
146f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko  return utils::WriteFile(path.c_str(), data.data(), data.size());
147c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com}
148c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com
149f329b933db41d26644a97afef928eb1b319d6d99Alex Deymobool WriteFileString(const string& path, const string& data) {
150970bb28905b44bf9f2cb986bb412ecda1095b0b1Andrew de los Reyes  return utils::WriteFile(path.c_str(), data.data(), data.size());
151c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com}
152c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com
153c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymobool BindToUnusedLoopDevice(const string& filename,
154c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo                            bool writable,
155c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo                            string* out_lo_dev_name) {
156c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  CHECK(out_lo_dev_name);
157c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  // Get the next available loop-device.
158c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  int control_fd =
159c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo      HANDLE_EINTR(open("/dev/loop-control", O_RDWR | O_LARGEFILE));
160c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  TEST_AND_RETURN_FALSE_ERRNO(control_fd >= 0);
161c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  int loop_number = ioctl(control_fd, LOOP_CTL_GET_FREE);
162c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  IGNORE_EINTR(close(control_fd));
163c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  *out_lo_dev_name = StringPrintf("/dev/loop%d", loop_number);
164c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo
165c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  // Double check that the loop exists and is free.
166c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  int loop_device_fd =
167c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo      HANDLE_EINTR(open(out_lo_dev_name->c_str(), O_RDWR | O_LARGEFILE));
168c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  if (loop_device_fd == -1 && errno == ENOENT) {
169c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo    // Workaround the case when the loop device doesn't exist.
170c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo    TEST_AND_RETURN_FALSE_ERRNO(mknod(out_lo_dev_name->c_str(),
171c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo                                      S_IFBLK | 0660,
172c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo                                      makedev(LOOP_MAJOR, loop_number)) == 0);
173c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo    loop_device_fd =
174c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo        HANDLE_EINTR(open(out_lo_dev_name->c_str(), O_RDWR | O_LARGEFILE));
175c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  }
176c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  TEST_AND_RETURN_FALSE_ERRNO(loop_device_fd != -1);
177c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  ScopedFdCloser loop_device_fd_closer(&loop_device_fd);
178c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo
179c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  struct loop_info64 device_info;
180c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  if (ioctl(loop_device_fd, LOOP_GET_STATUS64, &device_info) != -1 ||
181c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo      errno != ENXIO) {
182c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo    PLOG(ERROR) << "Loop device " << out_lo_dev_name->c_str()
183c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo                << " already in use";
18419a45f0eda0917b7788b925b501e774208474fdeGilad Arnold    return false;
185c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com  }
186c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com
187c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  // Open our data file and assign it to the loop device.
188c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  int data_fd = open(filename.c_str(),
189c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo                     (writable ? O_RDWR : O_RDONLY) | O_LARGEFILE | O_CLOEXEC);
190c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  TEST_AND_RETURN_FALSE_ERRNO(data_fd >= 0);
191c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  ScopedFdCloser data_fd_closer(&data_fd);
192c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  TEST_AND_RETURN_FALSE_ERRNO(ioctl(loop_device_fd, LOOP_SET_FD, data_fd) == 0);
193c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo
194c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  memset(&device_info, 0, sizeof(device_info));
195c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  device_info.lo_offset = 0;
196c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  device_info.lo_sizelimit = 0;  // 0 means whole file.
197c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  device_info.lo_flags = (writable ? 0 : LO_FLAGS_READ_ONLY);
198c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  device_info.lo_number = loop_number;
199c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  strncpy(reinterpret_cast<char*>(device_info.lo_file_name),
200c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo          base::FilePath(filename).BaseName().value().c_str(),
201c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo          LO_NAME_SIZE - 1);
202c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  device_info.lo_file_name[LO_NAME_SIZE - 1] = '\0';
203c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  TEST_AND_RETURN_FALSE_ERRNO(
204c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo      ioctl(loop_device_fd, LOOP_SET_STATUS64, &device_info) == 0);
205c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  return true;
206c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo}
207c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com
208c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymobool UnbindLoopDevice(const string& lo_dev_name) {
209c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  int loop_device_fd =
210c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo      HANDLE_EINTR(open(lo_dev_name.c_str(), O_RDWR | O_LARGEFILE));
211c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  if (loop_device_fd == -1 && errno == ENOENT)
212c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo    return true;
213c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  TEST_AND_RETURN_FALSE_ERRNO(loop_device_fd != -1);
214c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  ScopedFdCloser loop_device_fd_closer(&loop_device_fd);
215c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo
216c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  struct loop_info64 device_info;
217c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  // Check if the device is bound before trying to unbind it.
218c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  int get_stat_err = ioctl(loop_device_fd, LOOP_GET_STATUS64, &device_info);
219c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  if (get_stat_err == -1 && errno == ENXIO)
220c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo    return true;
221c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo
222c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  TEST_AND_RETURN_FALSE_ERRNO(ioctl(loop_device_fd, LOOP_CLR_FD) == 0);
22319a45f0eda0917b7788b925b501e774208474fdeGilad Arnold  return true;
224c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com}
225c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com
2263f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenkobool ExpectVectorsEq(const brillo::Blob& expected,
2273f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko                     const brillo::Blob& actual) {
2288006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  EXPECT_EQ(expected.size(), actual.size());
2298006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  if (expected.size() != actual.size())
230c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    return false;
231617bbc23d2cf4cba5881ec54607926393f7245c7Gilad Arnold  bool is_all_eq = true;
2328006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  for (unsigned int i = 0; i < expected.size(); i++) {
2338006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes    EXPECT_EQ(expected[i], actual[i]) << "offset: " << i;
234617bbc23d2cf4cba5881ec54607926393f7245c7Gilad Arnold    is_all_eq = is_all_eq && (expected[i] == actual[i]);
235c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com  }
236617bbc23d2cf4cba5881ec54607926393f7245c7Gilad Arnold  return is_all_eq;
237c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com}
238c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com
2393f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenkovoid FillWithData(brillo::Blob* buffer) {
2408006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  size_t input_counter = 0;
241f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko  for (uint8_t& b : *buffer) {
242f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko    b = kRandomString[input_counter];
2438006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes    input_counter++;
2448006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes    input_counter %= sizeof(kRandomString);
2458006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  }
2468006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes}
2478006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes
2485c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Levoid CreateEmptyExtImageAtPath(const string& path,
2495c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le                               size_t size,
2505c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le                               int block_size) {
2515c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le  EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
252c00c98a1dad941e5cc04ce0b0e766d40b3b384e1Alex Deymo                                   " seek=%" PRIuS " bs=1 count=1 status=none",
2535c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le                                   path.c_str(), size)));
2546ded6548c4d3606923d606981dd29f224bcfc723Alex Deymo  EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -q -b %d -F %s",
2555c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le                                   block_size, path.c_str())));
2565c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le}
2575c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le
258c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.comvoid CreateExtImageAtPath(const string& path, vector<string>* out_paths) {
25961d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  // create 10MiB sparse file, mounted at a unique location.
26061d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  string mount_path;
26161d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  CHECK(utils::MakeTempDirectory(kMountPathTemplate, &mount_path));
262a58b62a57eb2fe4070ed7efbf869b37037fbeaa7Alex Deymo  ScopedDirRemover mount_path_unlinker(mount_path);
26361d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold
264c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com  EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
2651f93d031baa4c0c4f390fcf5784b5179d15f289dAlex Deymo                                   " seek=10485759 bs=1 count=1 status=none",
266c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com                                   path.c_str())));
2676ded6548c4d3606923d606981dd29f224bcfc723Alex Deymo  EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -q -b 4096 -F %s",
2686ded6548c4d3606923d606981dd29f224bcfc723Alex Deymo                                   path.c_str())));
269c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com  EXPECT_EQ(0, System(StringPrintf("mount -o loop %s %s", path.c_str(),
27061d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str())));
27161d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("echo hi > %s/hi", mount_path.c_str())));
27261d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("echo hello > %s/hello",
27361d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str())));
27461d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir", mount_path.c_str())));
27561d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/empty_dir",
27661d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str())));
27761d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/mnt",
27861d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str())));
27961d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("echo T > %s/some_dir/test",
28061d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str())));
28161d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("mkfifo %s/some_dir/fifo",
28261d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str())));
28361d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("mknod %s/cdev c 2 3", mount_path.c_str())));
28461d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("ln -s /some/target %s/sym",
28561d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str())));
286c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com  EXPECT_EQ(0, System(StringPrintf("ln %s/some_dir/test %s/testlink",
28761d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str(), mount_path.c_str())));
28861d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("echo T > %s/srchardlink0",
28961d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str())));
29029da8aafd5da32ebfb57c7f3cf1b89ce3e5d60cbAndrew de los Reyes  EXPECT_EQ(0, System(StringPrintf("ln %s/srchardlink0 %s/srchardlink1",
29161d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str(), mount_path.c_str())));
29248a0a4826c47fe097d7ff31ad830911c1f288dbfAndrew de los Reyes  EXPECT_EQ(0, System(StringPrintf("ln -s bogus %s/boguslink",
29361d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str())));
29461d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_TRUE(utils::UnmountFilesystem(mount_path.c_str()));
2955c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le
296c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com  if (out_paths) {
297c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->clear();
298c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("");
299c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/hi");
30048a0a4826c47fe097d7ff31ad830911c1f288dbfAndrew de los Reyes    out_paths->push_back("/boguslink");
301c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/hello");
302c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/some_dir");
303c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/some_dir/empty_dir");
304c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/some_dir/mnt");
305c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/some_dir/test");
306c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/some_dir/fifo");
307c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/cdev");
308c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/testlink");
309c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/sym");
31029da8aafd5da32ebfb57c7f3cf1b89ce3e5d60cbAndrew de los Reyes    out_paths->push_back("/srchardlink0");
31129da8aafd5da32ebfb57c7f3cf1b89ce3e5d60cbAndrew de los Reyes    out_paths->push_back("/srchardlink1");
312c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/lost+found");
313c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com  }
314c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com}
315c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com
31658e8b1f8b32b355d879008572648fd621873711dDon GarrettScopedLoopMounter::ScopedLoopMounter(const string& file_path,
31758e8b1f8b32b355d879008572648fd621873711dDon Garrett                                     string* mnt_path,
318d2779df63aaad8b65fc5d4badee7dbc9bed7f2b6Alex Vakulenko                                     unsigned long flags) {  // NOLINT - long
319a6742b35938b6f58e24e3f1c550fe92d4d33eb74Gilad Arnold  EXPECT_TRUE(utils::MakeTempDirectory("mnt.XXXXXX", mnt_path));
3205c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le  dir_remover_.reset(new ScopedDirRemover(*mnt_path));
3215c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le
32258e8b1f8b32b355d879008572648fd621873711dDon Garrett  string loop_dev;
323c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo  loop_binder_.reset(
324c975d7bc6767711c4802e104c4a9d4731910c9beAlex Deymo      new ScopedLoopbackDeviceBinder(file_path, true, &loop_dev));
3255c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le
32614dbd333439f34c648b9f783ffa656ef565de0ccAlex Deymo  EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags, "", nullptr));
3275c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le  unmounter_.reset(new ScopedFilesystemUnmounter(*mnt_path));
3285c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le}
3295c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le
3302b19cfbcdb1aa8c5d1f338d19312fe14b6734bd5Alex Deymobase::FilePath GetBuildArtifactsPath() {
3312b19cfbcdb1aa8c5d1f338d19312fe14b6734bd5Alex Deymo  base::FilePath exe_path;
3322b19cfbcdb1aa8c5d1f338d19312fe14b6734bd5Alex Deymo  base::ReadSymbolicLink(base::FilePath("/proc/self/exe"), &exe_path);
3332b19cfbcdb1aa8c5d1f338d19312fe14b6734bd5Alex Deymo  return exe_path.DirName();
3342b19cfbcdb1aa8c5d1f338d19312fe14b6734bd5Alex Deymo}
3352b19cfbcdb1aa8c5d1f338d19312fe14b6734bd5Alex Deymo
33610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo}  // namespace test_utils
33749fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com}  // namespace chromeos_update_engine
338