Home | History | Annotate | Download | only in common
      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 
     55 void PrintTo(const Extent& extent, ::std::ostream* os) {
     56   *os << "(" << extent.start_block() << ", " << extent.num_blocks() << ")";
     57 }
     58 
     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 
    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 
    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 
    145 bool WriteFileVector(const string& path, const brillo::Blob& data) {
    146   return utils::WriteFile(path.c_str(), data.data(), data.size());
    147 }
    148 
    149 bool WriteFileString(const string& path, const string& data) {
    150   return utils::WriteFile(path.c_str(), data.data(), data.size());
    151 }
    152 
    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 
    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 
    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 
    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 
    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 
    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 
    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