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//
163defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
1739910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/utils.h"
18f74eb6543268b58231649465aee135a85920919fDarin Petkov
199abb763fa3840d69cc1098c0233162557a7f99eaBen Chan#include <stdint.h>
209abb763fa3840d69cc1098c0233162557a7f99eaBen Chan
213defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com#include <dirent.h>
22c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo#include <elf.h>
236f20dd4fc8861d93d188cd27323d2f9746464aafAlex Deymo#include <endian.h>
243defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com#include <errno.h>
25192393ba515e917d06248b6459b20b6547ef496dAlex Deymo#include <ext2fs/ext2fs.h>
26970bb28905b44bf9f2cb986bb412ecda1095b0b1Andrew de los Reyes#include <fcntl.h>
273defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com#include <stdio.h>
283defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com#include <stdlib.h>
293defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com#include <string.h>
30c4acdf40033fc7bedba3ec6449b7a750b1fe5f24Alex Deymo#include <sys/mount.h>
31c4acdf40033fc7bedba3ec6449b7a750b1fe5f24Alex Deymo#include <sys/resource.h>
32c4acdf40033fc7bedba3ec6449b7a750b1fe5f24Alex Deymo#include <sys/stat.h>
33c4acdf40033fc7bedba3ec6449b7a750b1fe5f24Alex Deymo#include <sys/types.h>
34c4acdf40033fc7bedba3ec6449b7a750b1fe5f24Alex Deymo#include <sys/wait.h>
353defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com#include <unistd.h>
36f74eb6543268b58231649465aee135a85920919fDarin Petkov
373defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com#include <algorithm>
38d2779df63aaad8b65fc5d4badee7dbc9bed7f2b6Alex Vakulenko#include <utility>
39c1972483fa3446852b42ce97d1ea43b9caaaf56fChris Sosa#include <vector>
40f74eb6543268b58231649465aee135a85920919fDarin Petkov
414906c1c6dac2ef7916bfa7193cc9324e99b4d223Alex Vakulenko#include <base/callback.h>
42736fcb57ca2dcf09710a797e4c23a64f6cd64e16Ben Chan#include <base/files/file_path.h>
43192393ba515e917d06248b6459b20b6547ef496dAlex Deymo#include <base/files/file_util.h>
44736fcb57ca2dcf09710a797e4c23a64f6cd64e16Ben Chan#include <base/files/scoped_file.h>
45c00c98a1dad941e5cc04ce0b0e766d40b3b384e1Alex Deymo#include <base/format_macros.h>
4660ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo#include <base/location.h>
478155d081dc729d407f8ff9e95b4ef91ae14281ceMike Frysinger#include <base/logging.h>
48fc661a18c07822f1700b870d8435189d5d809f3bChris Sosa#include <base/posix/eintr_wrapper.h>
498f71da83a3ecb7568769705486ea26be06a9d108Will Drewry#include <base/rand_util.h>
5075039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko#include <base/strings/string_number_conversions.h>
5175039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko#include <base/strings/string_split.h>
5275039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko#include <base/strings/string_util.h>
5375039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko#include <base/strings/stringprintf.h>
543f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/data_encoding.h>
553f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/message_loops/message_loop.h>
568f71da83a3ecb7568769705486ea26be06a9d108Will Drewry
5739910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/clock_interface.h"
5839910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/constants.h"
599c12346d5dc18288153fce61e7ffd0bd8e507afcSen Jiang#include "update_engine/common/platform_constants.h"
6039910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/prefs_interface.h"
6139910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/subprocess.h"
6239910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/payload_consumer/file_descriptor.h"
6339910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/payload_consumer/file_writer.h"
643a92aa2fe6aafd1007b6427795dfe8711b6cb094Sen Jiang#include "update_engine/payload_consumer/payload_constants.h"
653defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
66480ddfa079ebd01ed87e495332dec121d9ae781fJay Srinivasanusing base::Time;
678e3f1263218c5046d2281c1d1d3c886acda85b47Gilad Arnoldusing base::TimeDelta;
683defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.comusing std::min;
69c1972483fa3446852b42ce97d1ea43b9caaaf56fChris Sosausing std::pair;
703defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.comusing std::string;
713defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.comusing std::vector;
723defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
733defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.comnamespace chromeos_update_engine {
743defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
7577a1eba102c0d10a0b58f5bffe5c83909773e90bBen Channamespace {
7677a1eba102c0d10a0b58f5bffe5c83909773e90bBen Chan
7777a1eba102c0d10a0b58f5bffe5c83909773e90bBen Chan// The following constants control how UnmountFilesystem should retry if
7877a1eba102c0d10a0b58f5bffe5c83909773e90bBen Chan// umount() fails with an errno EBUSY, i.e. retry 5 times over the course of
7977a1eba102c0d10a0b58f5bffe5c83909773e90bBen Chan// one second.
8077a1eba102c0d10a0b58f5bffe5c83909773e90bBen Chanconst int kUnmountMaxNumOfRetries = 5;
8177a1eba102c0d10a0b58f5bffe5c83909773e90bBen Chanconst int kUnmountRetryIntervalInMicroseconds = 200 * 1000;  // 200 ms
82032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo
83032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo// Number of bytes to read from a file to attempt to detect its contents. Used
84032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo// in GetFileFormat.
85032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymoconst int kGetFileFormatMaxHeaderSize = 32;
86032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo
87dd132f39cced9028c01e98895a4f6c5fb9553de1Alex Deymo// The path to the kernel's boot_id.
88dd132f39cced9028c01e98895a4f6c5fb9553de1Alex Deymoconst char kBootIdPath[] = "/proc/sys/kernel/random/boot_id";
89dd132f39cced9028c01e98895a4f6c5fb9553de1Alex Deymo
90a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen// Return true if |disk_name| is an MTD or a UBI device. Note that this test is
91a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen// simply based on the name of the device.
92a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyenbool IsMtdDeviceName(const string& disk_name) {
930103c36caa2e38e034e0d22185736b9ccfb35c58Alex Vakulenko  return base::StartsWith(disk_name, "/dev/ubi",
940103c36caa2e38e034e0d22185736b9ccfb35c58Alex Vakulenko                          base::CompareCase::SENSITIVE) ||
950103c36caa2e38e034e0d22185736b9ccfb35c58Alex Vakulenko         base::StartsWith(disk_name, "/dev/mtd", base::CompareCase::SENSITIVE);
96a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen}
97a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen
98a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen// Return the device name for the corresponding partition on a NAND device.
99a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen// WARNING: This function returns device names that are not mountable.
100a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyenstring MakeNandPartitionName(int partition_num) {
101a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  switch (partition_num) {
102a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    case 2:
103a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    case 4:
104a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    case 6: {
105a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen      return base::StringPrintf("/dev/mtd%d", partition_num);
106a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    }
107a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    default: {
108a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen      return base::StringPrintf("/dev/ubi%d_0", partition_num);
109a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    }
110a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  }
111a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen}
112a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen
113a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen// Return the device name for the corresponding partition on a NAND device that
114a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen// may be mountable (but may not be writable).
115a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyenstring MakeNandPartitionNameForMount(int partition_num) {
116a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  switch (partition_num) {
117a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    case 2:
118a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    case 4:
119a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    case 6: {
120a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen      return base::StringPrintf("/dev/mtd%d", partition_num);
121a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    }
122a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    case 3:
123a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    case 5:
124a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    case 7: {
125a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen      return base::StringPrintf("/dev/ubiblock%d_0", partition_num);
126a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    }
127a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    default: {
128a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen      return base::StringPrintf("/dev/ubi%d_0", partition_num);
129a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    }
130a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  }
131a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen}
132a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen
1335aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo// If |path| is absolute, or explicit relative to the current working directory,
1345aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo// leaves it as is. Otherwise, uses the system's temp directory, as defined by
1355aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo// base::GetTempDir() and prepends it to |path|. On success stores the full
1365aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo// temporary path in |template_path| and returns true.
1375aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymobool GetTempName(const string& path, base::FilePath* template_path) {
1380103c36caa2e38e034e0d22185736b9ccfb35c58Alex Vakulenko  if (path[0] == '/' ||
1390103c36caa2e38e034e0d22185736b9ccfb35c58Alex Vakulenko      base::StartsWith(path, "./", base::CompareCase::SENSITIVE) ||
1400103c36caa2e38e034e0d22185736b9ccfb35c58Alex Vakulenko      base::StartsWith(path, "../", base::CompareCase::SENSITIVE)) {
1415aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo    *template_path = base::FilePath(path);
1425aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo    return true;
1435aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo  }
1445aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo
1455aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo  base::FilePath temp_dir;
1469c12346d5dc18288153fce61e7ffd0bd8e507afcSen Jiang#ifdef __ANDROID__
1479c12346d5dc18288153fce61e7ffd0bd8e507afcSen Jiang  temp_dir = base::FilePath(constants::kNonVolatileDirectory).Append("tmp");
1489c12346d5dc18288153fce61e7ffd0bd8e507afcSen Jiang  if (!base::PathExists(temp_dir))
1499c12346d5dc18288153fce61e7ffd0bd8e507afcSen Jiang    TEST_AND_RETURN_FALSE(base::CreateDirectory(temp_dir));
1509c12346d5dc18288153fce61e7ffd0bd8e507afcSen Jiang#else
1515aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo  TEST_AND_RETURN_FALSE(base::GetTempDir(&temp_dir));
1529c12346d5dc18288153fce61e7ffd0bd8e507afcSen Jiang#endif  // __ANDROID__
1535aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo  *template_path = temp_dir.Append(path);
1545aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo  return true;
1555aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo}
1565aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo
15777a1eba102c0d10a0b58f5bffe5c83909773e90bBen Chan}  // namespace
15877a1eba102c0d10a0b58f5bffe5c83909773e90bBen Chan
1593defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.comnamespace utils {
1603defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
16163137e5ded659c02eb70d59ef38f99aecac4d076J. Richard Barnettestring ParseECVersion(string input_line) {
162736fcb57ca2dcf09710a797e4c23a64f6cd64e16Ben Chan  base::TrimWhitespaceASCII(input_line, base::TRIM_ALL, &input_line);
163c1972483fa3446852b42ce97d1ea43b9caaaf56fChris Sosa
16475039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko  // At this point we want to convert the format key=value pair from mosys to
165c1972483fa3446852b42ce97d1ea43b9caaaf56fChris Sosa  // a vector of key value pairs.
166f9cb98c0cacccca803db48502c7bd461d04cb6b0Ben Chan  vector<pair<string, string>> kv_pairs;
16763137e5ded659c02eb70d59ef38f99aecac4d076J. Richard Barnette  if (base::SplitStringIntoKeyValuePairs(input_line, '=', ' ', &kv_pairs)) {
168020600db42428e7e96bb0d2e05da225e68650955Alex Deymo    for (const pair<string, string>& kv_pair : kv_pairs) {
169c1972483fa3446852b42ce97d1ea43b9caaaf56fChris Sosa      // Finally match against the fw_verion which may have quotes.
170020600db42428e7e96bb0d2e05da225e68650955Alex Deymo      if (kv_pair.first == "fw_version") {
171c1972483fa3446852b42ce97d1ea43b9caaaf56fChris Sosa        string output;
172c1972483fa3446852b42ce97d1ea43b9caaaf56fChris Sosa        // Trim any quotes.
173020600db42428e7e96bb0d2e05da225e68650955Alex Deymo        base::TrimString(kv_pair.second, "\"", &output);
174c1972483fa3446852b42ce97d1ea43b9caaaf56fChris Sosa        return output;
175c1972483fa3446852b42ce97d1ea43b9caaaf56fChris Sosa      }
176c1972483fa3446852b42ce97d1ea43b9caaaf56fChris Sosa    }
177c1972483fa3446852b42ce97d1ea43b9caaaf56fChris Sosa  }
178c1972483fa3446852b42ce97d1ea43b9caaaf56fChris Sosa  LOG(ERROR) << "Unable to parse fwid from ec info.";
179c1972483fa3446852b42ce97d1ea43b9caaaf56fChris Sosa  return "";
180c1972483fa3446852b42ce97d1ea43b9caaaf56fChris Sosa}
181c1972483fa3446852b42ce97d1ea43b9caaaf56fChris Sosa
182f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenkobool WriteFile(const char* path, const void* data, int data_len) {
183970bb28905b44bf9f2cb986bb412ecda1095b0b1Andrew de los Reyes  DirectFileWriter writer;
184970bb28905b44bf9f2cb986bb412ecda1095b0b1Andrew de los Reyes  TEST_AND_RETURN_FALSE_ERRNO(0 == writer.Open(path,
185970bb28905b44bf9f2cb986bb412ecda1095b0b1Andrew de los Reyes                                               O_WRONLY | O_CREAT | O_TRUNC,
1864dc2ada660d3f7cd50d624b6bf102d806cf8997fChris Masone                                               0600));
187970bb28905b44bf9f2cb986bb412ecda1095b0b1Andrew de los Reyes  ScopedFileWriterCloser closer(&writer);
188e410e0ff57c820e7d5f5bf6abcea56fe6951111bDon Garrett  TEST_AND_RETURN_FALSE_ERRNO(writer.Write(data, data_len));
189970bb28905b44bf9f2cb986bb412ecda1095b0b1Andrew de los Reyes  return true;
190970bb28905b44bf9f2cb986bb412ecda1095b0b1Andrew de los Reyes}
191970bb28905b44bf9f2cb986bb412ecda1095b0b1Andrew de los Reyes
19272ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymobool ReadAll(
19372ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo    int fd, void* buf, size_t count, size_t* out_bytes_read, bool* eof) {
19472ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo  char* c_buf = static_cast<char*>(buf);
19572ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo  size_t bytes_read = 0;
19672ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo  *eof = false;
19772ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo  while (bytes_read < count) {
19872ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo    ssize_t rc = HANDLE_EINTR(read(fd, c_buf + bytes_read, count - bytes_read));
19972ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo    if (rc < 0) {
20072ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo      // EAGAIN and EWOULDBLOCK are normal return values when there's no more
20172ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo      // input and we are in non-blocking mode.
20272ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo      if (errno != EWOULDBLOCK && errno != EAGAIN) {
20372ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo        PLOG(ERROR) << "Error reading fd " << fd;
20472ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo        *out_bytes_read = bytes_read;
20572ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo        return false;
20672ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo      }
20772ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo      break;
20872ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo    } else if (rc == 0) {
20972ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo      // A value of 0 means that we reached EOF and there is nothing else to
21072ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo      // read from this fd.
21172ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo      *eof = true;
21272ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo      break;
21372ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo    } else {
21472ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo      bytes_read += rc;
21572ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo    }
21672ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo  }
21772ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo  *out_bytes_read = bytes_read;
21872ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo  return true;
21972ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo}
22072ea95ab7705448b044cafc6b8cf2a2f4d929bd9Alex Deymo
22109e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyesbool WriteAll(int fd, const void* buf, size_t count) {
222b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes  const char* c_buf = static_cast<const char*>(buf);
223b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes  ssize_t bytes_written = 0;
224b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes  while (bytes_written < static_cast<ssize_t>(count)) {
225b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes    ssize_t rc = write(fd, c_buf + bytes_written, count - bytes_written);
226b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes    TEST_AND_RETURN_FALSE_ERRNO(rc >= 0);
227b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes    bytes_written += rc;
228b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes  }
229b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes  return true;
230b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes}
231b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes
23209e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyesbool PWriteAll(int fd, const void* buf, size_t count, off_t offset) {
23309e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes  const char* c_buf = static_cast<const char*>(buf);
234780db2144f19d696d84b1602858b25d82d70da1fGilad Arnold  size_t bytes_written = 0;
235780db2144f19d696d84b1602858b25d82d70da1fGilad Arnold  int num_attempts = 0;
236780db2144f19d696d84b1602858b25d82d70da1fGilad Arnold  while (bytes_written < count) {
237780db2144f19d696d84b1602858b25d82d70da1fGilad Arnold    num_attempts++;
23809e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes    ssize_t rc = pwrite(fd, c_buf + bytes_written, count - bytes_written,
23909e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes                        offset + bytes_written);
240780db2144f19d696d84b1602858b25d82d70da1fGilad Arnold    // TODO(garnold) for debugging failure in chromium-os:31077; to be removed.
241780db2144f19d696d84b1602858b25d82d70da1fGilad Arnold    if (rc < 0) {
242780db2144f19d696d84b1602858b25d82d70da1fGilad Arnold      PLOG(ERROR) << "pwrite error; num_attempts=" << num_attempts
243780db2144f19d696d84b1602858b25d82d70da1fGilad Arnold                  << " bytes_written=" << bytes_written
244780db2144f19d696d84b1602858b25d82d70da1fGilad Arnold                  << " count=" << count << " offset=" << offset;
245780db2144f19d696d84b1602858b25d82d70da1fGilad Arnold    }
24609e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes    TEST_AND_RETURN_FALSE_ERRNO(rc >= 0);
24709e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes    bytes_written += rc;
24809e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes  }
24909e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes  return true;
25009e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes}
25109e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes
252f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyenbool WriteAll(FileDescriptorPtr fd, const void* buf, size_t count) {
253f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen  const char* c_buf = static_cast<const char*>(buf);
254f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen  ssize_t bytes_written = 0;
255f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen  while (bytes_written < static_cast<ssize_t>(count)) {
256f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen    ssize_t rc = fd->Write(c_buf + bytes_written, count - bytes_written);
257f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen    TEST_AND_RETURN_FALSE_ERRNO(rc >= 0);
258f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen    bytes_written += rc;
259f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen  }
260f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen  return true;
261f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen}
262f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen
263f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyenbool PWriteAll(FileDescriptorPtr fd,
264f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen               const void* buf,
265f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen               size_t count,
266f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen               off_t offset) {
2670c8cf7e5012547feace705d8ef98e6d6a5dd4a74Allie Wood  TEST_AND_RETURN_FALSE_ERRNO(fd->Seek(offset, SEEK_SET) !=
2680c8cf7e5012547feace705d8ef98e6d6a5dd4a74Allie Wood                              static_cast<off_t>(-1));
269f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen  return WriteAll(fd, buf, count);
270f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen}
271f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen
27209e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyesbool PReadAll(int fd, void* buf, size_t count, off_t offset,
27309e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes              ssize_t* out_bytes_read) {
27409e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes  char* c_buf = static_cast<char*>(buf);
27509e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes  ssize_t bytes_read = 0;
27609e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes  while (bytes_read < static_cast<ssize_t>(count)) {
27709e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes    ssize_t rc = pread(fd, c_buf + bytes_read, count - bytes_read,
27809e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes                       offset + bytes_read);
27909e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes    TEST_AND_RETURN_FALSE_ERRNO(rc >= 0);
28009e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes    if (rc == 0) {
28109e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes      break;
28209e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes    }
28309e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes    bytes_read += rc;
28409e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes  }
28509e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes  *out_bytes_read = bytes_read;
28609e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes  return true;
28709e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes}
28809e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes
289f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyenbool PReadAll(FileDescriptorPtr fd, void* buf, size_t count, off_t offset,
290f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen              ssize_t* out_bytes_read) {
2910c8cf7e5012547feace705d8ef98e6d6a5dd4a74Allie Wood  TEST_AND_RETURN_FALSE_ERRNO(fd->Seek(offset, SEEK_SET) !=
2920c8cf7e5012547feace705d8ef98e6d6a5dd4a74Allie Wood                              static_cast<off_t>(-1));
293f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen  char* c_buf = static_cast<char*>(buf);
294f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen  ssize_t bytes_read = 0;
295f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen  while (bytes_read < static_cast<ssize_t>(count)) {
296f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen    ssize_t rc = fd->Read(c_buf + bytes_read, count - bytes_read);
297f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen    TEST_AND_RETURN_FALSE_ERRNO(rc >= 0);
298f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen    if (rc == 0) {
299f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen      break;
300f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen    }
301f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen    bytes_read += rc;
302f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen  }
303f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen  *out_bytes_read = bytes_read;
304f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen  return true;
305f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen}
306f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyen
30719a45f0eda0917b7788b925b501e774208474fdeGilad Arnold// Append |nbytes| of content from |buf| to the vector pointed to by either
30819a45f0eda0917b7788b925b501e774208474fdeGilad Arnold// |vec_p| or |str_p|.
309f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenkostatic void AppendBytes(const uint8_t* buf, size_t nbytes,
3103f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko                        brillo::Blob* vec_p) {
31119a45f0eda0917b7788b925b501e774208474fdeGilad Arnold  CHECK(buf);
31219a45f0eda0917b7788b925b501e774208474fdeGilad Arnold  CHECK(vec_p);
31319a45f0eda0917b7788b925b501e774208474fdeGilad Arnold  vec_p->insert(vec_p->end(), buf, buf + nbytes);
31419a45f0eda0917b7788b925b501e774208474fdeGilad Arnold}
315f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenkostatic void AppendBytes(const uint8_t* buf, size_t nbytes,
316f329b933db41d26644a97afef928eb1b319d6d99Alex Deymo                        string* str_p) {
31719a45f0eda0917b7788b925b501e774208474fdeGilad Arnold  CHECK(buf);
31819a45f0eda0917b7788b925b501e774208474fdeGilad Arnold  CHECK(str_p);
319f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko  str_p->append(buf, buf + nbytes);
32019a45f0eda0917b7788b925b501e774208474fdeGilad Arnold}
32119a45f0eda0917b7788b925b501e774208474fdeGilad Arnold
32219a45f0eda0917b7788b925b501e774208474fdeGilad Arnold// Reads from an open file |fp|, appending the read content to the container
32319a45f0eda0917b7788b925b501e774208474fdeGilad Arnold// pointer to by |out_p|.  Returns true upon successful reading all of the
3248e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov// file's content, false otherwise. If |size| is not -1, reads up to |size|
3258e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov// bytes.
32619a45f0eda0917b7788b925b501e774208474fdeGilad Arnoldtemplate <class T>
3278e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkovstatic bool Read(FILE* fp, off_t size, T* out_p) {
32819a45f0eda0917b7788b925b501e774208474fdeGilad Arnold  CHECK(fp);
3298e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov  CHECK(size == -1 || size >= 0);
330f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko  uint8_t buf[1024];
3318e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov  while (size == -1 || size > 0) {
3328e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov    off_t bytes_to_read = sizeof(buf);
3338e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov    if (size > 0 && bytes_to_read > size) {
3348e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov      bytes_to_read = size;
3358e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov    }
3368e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov    size_t nbytes = fread(buf, 1, bytes_to_read, fp);
3378e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov    if (!nbytes) {
3388e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov      break;
3398e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov    }
34019a45f0eda0917b7788b925b501e774208474fdeGilad Arnold    AppendBytes(buf, nbytes, out_p);
3418e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov    if (size != -1) {
3428e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov      CHECK(size >= static_cast<off_t>(nbytes));
3438e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov      size -= nbytes;
3448e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov    }
3458e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov  }
3468e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov  if (ferror(fp)) {
3478e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov    return false;
3488e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov  }
3498e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov  return size == 0 || feof(fp);
35019a45f0eda0917b7788b925b501e774208474fdeGilad Arnold}
35119a45f0eda0917b7788b925b501e774208474fdeGilad Arnold
3528e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov// Opens a file |path| for reading and appends its the contents to a container
3538e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov// |out_p|. Starts reading the file from |offset|. If |offset| is beyond the end
3548e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov// of the file, returns success. If |size| is not -1, reads up to |size| bytes.
35519a45f0eda0917b7788b925b501e774208474fdeGilad Arnoldtemplate <class T>
356f329b933db41d26644a97afef928eb1b319d6d99Alex Deymostatic bool ReadFileChunkAndAppend(const string& path,
3578e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov                                   off_t offset,
3588e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov                                   off_t size,
3598e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov                                   T* out_p) {
3608e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov  CHECK_GE(offset, 0);
3618e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov  CHECK(size == -1 || size >= 0);
362736fcb57ca2dcf09710a797e4c23a64f6cd64e16Ben Chan  base::ScopedFILE fp(fopen(path.c_str(), "r"));
3638e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov  if (!fp.get())
3643defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com    return false;
3658e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov  if (offset) {
3668e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov    // Return success without appending any data if a chunk beyond the end of
3678e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov    // the file is requested.
3688e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov    if (offset >= FileSize(path)) {
3698e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov      return true;
3708e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov    }
3718e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov    TEST_AND_RETURN_FALSE_ERRNO(fseek(fp.get(), offset, SEEK_SET) == 0);
3728e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov  }
3738e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov  return Read(fp.get(), size, out_p);
3743defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com}
3753defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
37610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo// TODO(deymo): This is only used in unittest, but requires the private
37710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo// Read<string>() defined here. Expose Read<string>() or move to base/ version.
37810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymobool ReadPipe(const string& cmd, string* out_p) {
37919a45f0eda0917b7788b925b501e774208474fdeGilad Arnold  FILE* fp = popen(cmd.c_str(), "r");
38019a45f0eda0917b7788b925b501e774208474fdeGilad Arnold  if (!fp)
3813defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com    return false;
3828e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov  bool success = Read(fp, -1, out_p);
38319a45f0eda0917b7788b925b501e774208474fdeGilad Arnold  return (success && pclose(fp) >= 0);
38419a45f0eda0917b7788b925b501e774208474fdeGilad Arnold}
38519a45f0eda0917b7788b925b501e774208474fdeGilad Arnold
3863f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenkobool ReadFile(const string& path, brillo::Blob* out_p) {
3878e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov  return ReadFileChunkAndAppend(path, 0, -1, out_p);
3888e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov}
3898e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov
3908e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkovbool ReadFile(const string& path, string* out_p) {
3918e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov  return ReadFileChunkAndAppend(path, 0, -1, out_p);
39219a45f0eda0917b7788b925b501e774208474fdeGilad Arnold}
39319a45f0eda0917b7788b925b501e774208474fdeGilad Arnold
3948e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkovbool ReadFileChunk(const string& path, off_t offset, off_t size,
3953f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko                   brillo::Blob* out_p) {
3968e447e02eb60955bc1f982f0d20b7f0d2689e0dbDarin Petkov  return ReadFileChunkAndAppend(path, offset, size, out_p);
39719a45f0eda0917b7788b925b501e774208474fdeGilad Arnold}
39819a45f0eda0917b7788b925b501e774208474fdeGilad Arnold
399b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Blackoff_t BlockDevSize(int fd) {
400b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black  uint64_t dev_size;
401b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black  int rc = ioctl(fd, BLKGETSIZE64, &dev_size);
402b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black  if (rc == -1) {
403b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black    dev_size = -1;
404b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black    PLOG(ERROR) << "Error running ioctl(BLKGETSIZE64) on " << fd;
405b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black  }
406b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black  return dev_size;
407b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black}
408b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black
409b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Blackoff_t FileSize(int fd) {
410f4c7ef1bc239890d8bee30e6823f88814fef8ce5Andrew de los Reyes  struct stat stbuf;
411b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black  int rc = fstat(fd, &stbuf);
412f4c7ef1bc239890d8bee30e6823f88814fef8ce5Andrew de los Reyes  CHECK_EQ(rc, 0);
413b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black  if (rc < 0) {
414b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black    PLOG(ERROR) << "Error stat-ing " << fd;
415f4c7ef1bc239890d8bee30e6823f88814fef8ce5Andrew de los Reyes    return rc;
416b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black  }
417b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black  if (S_ISREG(stbuf.st_mode))
418b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black    return stbuf.st_size;
419b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black  if (S_ISBLK(stbuf.st_mode))
420b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black    return BlockDevSize(fd);
421b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black  LOG(ERROR) << "Couldn't determine the type of " << fd;
422b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black  return -1;
423b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black}
424b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black
425b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Blackoff_t FileSize(const string& path) {
426b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black  int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
427b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black  if (fd == -1) {
428b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black    PLOG(ERROR) << "Error opening " << path;
429b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black    return fd;
430b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black  }
431b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black  off_t size = FileSize(fd);
432b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black  if (size == -1)
433b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black    PLOG(ERROR) << "Error getting file size of " << path;
434b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black  close(fd);
435b92cd2e0c4eb241eecffa6ad63efdd021a387f8bGabe Black  return size;
436f4c7ef1bc239890d8bee30e6823f88814fef8ce5Andrew de los Reyes}
437f4c7ef1bc239890d8bee30e6823f88814fef8ce5Andrew de los Reyes
438f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenkovoid HexDumpArray(const uint8_t* const arr, const size_t length) {
4393defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com  LOG(INFO) << "Logging array of length: " << length;
4403defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com  const unsigned int bytes_per_line = 16;
44108c4e27baaa7b40732b99642e1f21bf889d022efAndrew de los Reyes  for (uint32_t i = 0; i < length; i += bytes_per_line) {
4423defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com    const unsigned int bytes_remaining = length - i;
4433defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com    const unsigned int bytes_per_this_line = min(bytes_per_line,
4443defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com                                                 bytes_remaining);
4453defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com    char header[100];
4463defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com    int r = snprintf(header, sizeof(header), "0x%08x : ", i);
4473defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com    TEST_AND_RETURN(r == 13);
4483defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com    string line = header;
4493defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com    for (unsigned int j = 0; j < bytes_per_this_line; j++) {
4503defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com      char buf[20];
451f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko      uint8_t c = arr[i + j];
4523defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com      r = snprintf(buf, sizeof(buf), "%02x ", static_cast<unsigned int>(c));
4533defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com      TEST_AND_RETURN(r == 3);
4543defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com      line += buf;
4553defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com    }
4563defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com    LOG(INFO) << line;
4573defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com  }
4583defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com}
4593defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
460f329b933db41d26644a97afef928eb1b319d6d99Alex Deymobool SplitPartitionName(const string& partition_name,
461f329b933db41d26644a97afef928eb1b319d6d99Alex Deymo                        string* out_disk_name,
4624f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko                        int* out_partition_num) {
4630103c36caa2e38e034e0d22185736b9ccfb35c58Alex Vakulenko  if (!base::StartsWith(partition_name, "/dev/",
4640103c36caa2e38e034e0d22185736b9ccfb35c58Alex Vakulenko                        base::CompareCase::SENSITIVE)) {
4654f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko    LOG(ERROR) << "Invalid partition device name: " << partition_name;
4664f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko    return false;
467f74eb6543268b58231649465aee135a85920919fDarin Petkov  }
4684f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko
469f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko  size_t last_nondigit_pos = partition_name.find_last_not_of("0123456789");
470f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko  if (last_nondigit_pos == string::npos ||
471f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko      (last_nondigit_pos + 1) == partition_name.size()) {
472f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko    LOG(ERROR) << "Unable to parse partition device name: " << partition_name;
4734f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko    return false;
4744f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko  }
4754f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko
476f329b933db41d26644a97afef928eb1b319d6d99Alex Deymo  size_t partition_name_len = string::npos;
477f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko  if (partition_name[last_nondigit_pos] == '_') {
478f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko    // NAND block devices have weird naming which could be something
479f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko    // like "/dev/ubiblock2_0". We discard "_0" in such a case.
480f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko    size_t prev_nondigit_pos =
481f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko        partition_name.find_last_not_of("0123456789", last_nondigit_pos - 1);
482f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko    if (prev_nondigit_pos == string::npos ||
483f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko        (prev_nondigit_pos + 1) == last_nondigit_pos) {
484f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko      LOG(ERROR) << "Unable to parse partition device name: " << partition_name;
485f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko      return false;
486f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko    }
487f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko
488f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko    partition_name_len = last_nondigit_pos - prev_nondigit_pos;
489f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko    last_nondigit_pos = prev_nondigit_pos;
4904f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko  }
4914f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko
4924f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko  if (out_disk_name) {
4934f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko    // Special case for MMC devices which have the following naming scheme:
4944f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko    // mmcblk0p2
495f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko    size_t disk_name_len = last_nondigit_pos;
496f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko    if (partition_name[last_nondigit_pos] != 'p' ||
497f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko        last_nondigit_pos == 0 ||
498f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko        !isdigit(partition_name[last_nondigit_pos - 1])) {
499f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko      disk_name_len++;
500f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko    }
501f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko    *out_disk_name = partition_name.substr(0, disk_name_len);
502f97144334e945a5ec88970b4b28f4e98ce0bbb80Andrew de los Reyes  }
5034f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko
5044f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko  if (out_partition_num) {
505f329b933db41d26644a97afef928eb1b319d6d99Alex Deymo    string partition_str = partition_name.substr(last_nondigit_pos + 1,
506f329b933db41d26644a97afef928eb1b319d6d99Alex Deymo                                                 partition_name_len);
5074f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko    *out_partition_num = atoi(partition_str.c_str());
5084f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko  }
5094f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko  return true;
510f97144334e945a5ec88970b4b28f4e98ce0bbb80Andrew de los Reyes}
511f97144334e945a5ec88970b4b28f4e98ce0bbb80Andrew de los Reyes
512f329b933db41d26644a97afef928eb1b319d6d99Alex Deymostring MakePartitionName(const string& disk_name, int partition_num) {
513a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  if (partition_num < 1) {
514a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    LOG(ERROR) << "Invalid partition number: " << partition_num;
515a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    return string();
516a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  }
517a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen
5180103c36caa2e38e034e0d22185736b9ccfb35c58Alex Vakulenko  if (!base::StartsWith(disk_name, "/dev/", base::CompareCase::SENSITIVE)) {
5194f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko    LOG(ERROR) << "Invalid disk name: " << disk_name;
520f329b933db41d26644a97afef928eb1b319d6d99Alex Deymo    return string();
5214f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko  }
5224f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko
523a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  if (IsMtdDeviceName(disk_name)) {
524a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    // Special case for UBI block devices.
525a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    //   1. ubiblock is not writable, we need to use plain "ubi".
526a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    //   2. There is a "_0" suffix.
527a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    return MakeNandPartitionName(partition_num);
528f97144334e945a5ec88970b4b28f4e98ce0bbb80Andrew de los Reyes  }
5294f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko
530f329b933db41d26644a97afef928eb1b319d6d99Alex Deymo  string partition_name = disk_name;
531f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko  if (isdigit(partition_name.back())) {
532f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko    // Special case for devices with names ending with a digit.
533f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko    // Add "p" to separate the disk name from partition number,
534f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko    // e.g. "/dev/loop0p2"
5354f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko    partition_name += 'p';
5364f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko  }
5374f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko
538f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko  partition_name += std::to_string(partition_num);
539f3f85bb699e3893e08886f8935385f8c9f517ebcAlex Vakulenko
5404f5b144e3e003663fbc9a89c3a43d214ecc61238Alex Vakulenko  return partition_name;
541f97144334e945a5ec88970b4b28f4e98ce0bbb80Andrew de los Reyes}
542f97144334e945a5ec88970b4b28f4e98ce0bbb80Andrew de los Reyes
543a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyenstring MakePartitionNameForMount(const string& part_name) {
544a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  if (IsMtdDeviceName(part_name)) {
545a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    int partition_num;
546a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    if (!SplitPartitionName(part_name, nullptr, &partition_num)) {
547a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen      return "";
548a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    }
549a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    return MakeNandPartitionNameForMount(partition_num);
550a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  }
551a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  return part_name;
552a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen}
553a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen
554f329b933db41d26644a97afef928eb1b319d6d99Alex Deymostring ErrnoNumberAsString(int err) {
5553defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com  char buf[100];
5563defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com  buf[0] = '\0';
5573defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com  return strerror_r(err, buf, sizeof(buf));
5583defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com}
5593defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
5603defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.combool FileExists(const char* path) {
5613defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com  struct stat stbuf;
5623defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com  return 0 == lstat(path, &stbuf);
5633defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com}
5643defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
56530291edee8e2f7646b540b00672c81b442386ed6Darin Petkovbool IsSymlink(const char* path) {
56630291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  struct stat stbuf;
56730291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  return lstat(path, &stbuf) == 0 && S_ISLNK(stbuf.st_mode) != 0;
56830291edee8e2f7646b540b00672c81b442386ed6Darin Petkov}
56930291edee8e2f7646b540b00672c81b442386ed6Darin Petkov
570a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyenbool TryAttachingUbiVolume(int volume_num, int timeout) {
571a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  const string volume_path = base::StringPrintf("/dev/ubi%d_0", volume_num);
572a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  if (FileExists(volume_path.c_str())) {
573a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    return true;
574a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  }
575a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen
576a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  int exit_code;
577a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  vector<string> cmd = {
578a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen      "ubiattach",
579a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen      "-m",
580a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen      base::StringPrintf("%d", volume_num),
581a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen      "-d",
582a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen      base::StringPrintf("%d", volume_num)
583a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  };
584a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &exit_code, nullptr));
585a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  TEST_AND_RETURN_FALSE(exit_code == 0);
586a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen
587a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  cmd = {
588a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen      "ubiblock",
589a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen      "--create",
590a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen      volume_path
591a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  };
592a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &exit_code, nullptr));
593a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  TEST_AND_RETURN_FALSE(exit_code == 0);
594a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen
595a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  while (timeout > 0 && !FileExists(volume_path.c_str())) {
596a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    sleep(1);
597a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen    timeout--;
598a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  }
599a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen
600a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen  return FileExists(volume_path.c_str());
601a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen}
602a78b28c6f202b801fe7cb85246b33afe01aeaa7aNam T. Nguyen
603f329b933db41d26644a97afef928eb1b319d6d99Alex Deymobool MakeTempFile(const string& base_filename_template,
604f329b933db41d26644a97afef928eb1b319d6d99Alex Deymo                  string* filename,
605b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes                  int* fd) {
6065aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo  base::FilePath filename_template;
6075aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo  TEST_AND_RETURN_FALSE(
6085aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo      GetTempName(base_filename_template, &filename_template));
609b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes  DCHECK(filename || fd);
6105aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo  vector<char> buf(filename_template.value().size() + 1);
6115aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo  memcpy(buf.data(), filename_template.value().data(),
6125aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo         filename_template.value().size());
6135aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo  buf[filename_template.value().size()] = '\0';
614296889c68c92b04d307035c5803681f8d2c8f9d3Darin Petkov
615f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko  int mkstemp_fd = mkstemp(buf.data());
616b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes  TEST_AND_RETURN_FALSE_ERRNO(mkstemp_fd >= 0);
617b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes  if (filename) {
618f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko    *filename = buf.data();
619b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes  }
620b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes  if (fd) {
621b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes    *fd = mkstemp_fd;
622b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes  } else {
623b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes    close(mkstemp_fd);
624b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes  }
625b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes  return true;
626b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes}
627b10320d4f76a2d263566f6eed471921382fae800Andrew de los Reyes
628f329b933db41d26644a97afef928eb1b319d6d99Alex Deymobool MakeTempDirectory(const string& base_dirname_template,
629f329b933db41d26644a97afef928eb1b319d6d99Alex Deymo                       string* dirname) {
6305aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo  base::FilePath dirname_template;
6315aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo  TEST_AND_RETURN_FALSE(GetTempName(base_dirname_template, &dirname_template));
63209e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes  DCHECK(dirname);
6335aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo  vector<char> buf(dirname_template.value().size() + 1);
6345aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo  memcpy(buf.data(), dirname_template.value().data(),
6355aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo         dirname_template.value().size());
6365aa1c54312fdaf541c70932900fb3c80145592e1Alex Deymo  buf[dirname_template.value().size()] = '\0';
637296889c68c92b04d307035c5803681f8d2c8f9d3Darin Petkov
638f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko  char* return_code = mkdtemp(buf.data());
63988b591f24cb3f94f982d7024c2e8ed25c2cc26a2Alex Vakulenko  TEST_AND_RETURN_FALSE_ERRNO(return_code != nullptr);
640f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko  *dirname = buf.data();
64109e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes  return true;
64209e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes}
64309e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes
6442e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymobool SetBlockDeviceReadOnly(const string& device, bool read_only) {
6452e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo  int fd = HANDLE_EINTR(open(device.c_str(), O_RDONLY | O_CLOEXEC));
6462e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo  if (fd < 0) {
6472e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo    PLOG(ERROR) << "Opening block device " << device;
6482e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo    return false;
6492e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo  }
6502e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo  ScopedFdCloser fd_closer(&fd);
6512e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo  // We take no action if not needed.
6522e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo  int read_only_flag;
6532e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo  int expected_flag = read_only ? 1 : 0;
6542e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo  int rc = ioctl(fd, BLKROGET, &read_only_flag);
6552e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo  // In case of failure reading the setting we will try to set it anyway.
6562e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo  if (rc == 0 && read_only_flag == expected_flag)
6572e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo    return true;
6582e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo
6592e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo  rc = ioctl(fd, BLKROSET, &expected_flag);
6602e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo  if (rc != 0) {
6612e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo    PLOG(ERROR) << "Marking block device " << device << " as read_only="
6622e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo                << expected_flag;
6632e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo    return false;
6642e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo  }
6652e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo  return true;
6662e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo}
6672e1de4f9f0457cd6117ddb22ffef72c8e2fbd4f3Alex Deymo
6683defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.combool MountFilesystem(const string& device,
66909e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes                     const string& mountpoint,
670390efedcb7e17587da765b6d682077cb7fa46ee1Alex Deymo                     unsigned long mountflags,  // NOLINT(runtime/int)
67114dbd333439f34c648b9f783ffa656ef565de0ccAlex Deymo                     const string& type,
67214dbd333439f34c648b9f783ffa656ef565de0ccAlex Deymo                     const string& fs_mount_options) {
673390efedcb7e17587da765b6d682077cb7fa46ee1Alex Deymo  vector<const char*> fstypes;
674390efedcb7e17587da765b6d682077cb7fa46ee1Alex Deymo  if (type.empty()) {
675390efedcb7e17587da765b6d682077cb7fa46ee1Alex Deymo    fstypes = {"ext2", "ext3", "ext4", "squashfs"};
676390efedcb7e17587da765b6d682077cb7fa46ee1Alex Deymo  } else {
677390efedcb7e17587da765b6d682077cb7fa46ee1Alex Deymo    fstypes = {type.c_str()};
678390efedcb7e17587da765b6d682077cb7fa46ee1Alex Deymo  }
6794c82df357f29cba23393732bcd6f411f856eb2e6Alex Deymo  for (const char* fstype : fstypes) {
6804c82df357f29cba23393732bcd6f411f856eb2e6Alex Deymo    int rc = mount(device.c_str(), mountpoint.c_str(), fstype, mountflags,
68114dbd333439f34c648b9f783ffa656ef565de0ccAlex Deymo                   fs_mount_options.c_str());
6824c82df357f29cba23393732bcd6f411f856eb2e6Alex Deymo    if (rc == 0)
6834c82df357f29cba23393732bcd6f411f856eb2e6Alex Deymo      return true;
6844c82df357f29cba23393732bcd6f411f856eb2e6Alex Deymo
6854c82df357f29cba23393732bcd6f411f856eb2e6Alex Deymo    PLOG(WARNING) << "Unable to mount destination device " << device
6864c82df357f29cba23393732bcd6f411f856eb2e6Alex Deymo                  << " on " << mountpoint << " as " << fstype;
6873defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com  }
688390efedcb7e17587da765b6d682077cb7fa46ee1Alex Deymo  if (!type.empty()) {
689390efedcb7e17587da765b6d682077cb7fa46ee1Alex Deymo    LOG(ERROR) << "Unable to mount " << device << " with any supported type";
690390efedcb7e17587da765b6d682077cb7fa46ee1Alex Deymo  }
6914c82df357f29cba23393732bcd6f411f856eb2e6Alex Deymo  return false;
6923defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com}
6933defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
6943defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.combool UnmountFilesystem(const string& mountpoint) {
69577a1eba102c0d10a0b58f5bffe5c83909773e90bBen Chan  for (int num_retries = 0; ; ++num_retries) {
69677a1eba102c0d10a0b58f5bffe5c83909773e90bBen Chan    if (umount(mountpoint.c_str()) == 0)
69777a1eba102c0d10a0b58f5bffe5c83909773e90bBen Chan      break;
69877a1eba102c0d10a0b58f5bffe5c83909773e90bBen Chan
69977a1eba102c0d10a0b58f5bffe5c83909773e90bBen Chan    TEST_AND_RETURN_FALSE_ERRNO(errno == EBUSY &&
70077a1eba102c0d10a0b58f5bffe5c83909773e90bBen Chan                                num_retries < kUnmountMaxNumOfRetries);
7018d2bbe38da10c8461437fb14454ec20886bc212cAlex Deymo    usleep(kUnmountRetryIntervalInMicroseconds);
70277a1eba102c0d10a0b58f5bffe5c83909773e90bBen Chan  }
7033defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com  return true;
7043defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com}
7053defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
706f329b933db41d26644a97afef928eb1b319d6d99Alex Deymobool GetFilesystemSize(const string& device,
707d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov                       int* out_block_count,
708d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov                       int* out_block_size) {
709d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov  int fd = HANDLE_EINTR(open(device.c_str(), O_RDONLY));
710e7141c64d1d3afadff05331d1e4cc95f6ce40a54Alex Deymo  TEST_AND_RETURN_FALSE_ERRNO(fd >= 0);
711d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov  ScopedFdCloser fd_closer(&fd);
712d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov  return GetFilesystemSizeFromFD(fd, out_block_count, out_block_size);
713d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov}
714d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov
715d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkovbool GetFilesystemSizeFromFD(int fd,
716d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov                             int* out_block_count,
717d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov                             int* out_block_size) {
718d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov  TEST_AND_RETURN_FALSE(fd >= 0);
719d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov
720192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // Determine the filesystem size by directly reading the block count and
721192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // block size information from the superblock. Supported FS are ext3 and
722192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // squashfs.
723192393ba515e917d06248b6459b20b6547ef496dAlex Deymo
724192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // Read from the fd only once and detect in memory. The first 2 KiB is enough
725192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // to read the ext2 superblock (located at offset 1024) and the squashfs
726192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // superblock (located at offset 0).
727192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  const ssize_t kBufferSize = 2048;
728192393ba515e917d06248b6459b20b6547ef496dAlex Deymo
729192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  uint8_t buffer[kBufferSize];
730192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  if (HANDLE_EINTR(pread(fd, buffer, kBufferSize, 0)) != kBufferSize) {
731192393ba515e917d06248b6459b20b6547ef496dAlex Deymo    PLOG(ERROR) << "Unable to read the file system header:";
732d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov    return false;
733d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov  }
734192393ba515e917d06248b6459b20b6547ef496dAlex Deymo
735192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  if (GetSquashfs4Size(buffer, kBufferSize, out_block_count, out_block_size))
736192393ba515e917d06248b6459b20b6547ef496dAlex Deymo    return true;
737192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  if (GetExt3Size(buffer, kBufferSize, out_block_count, out_block_size))
738192393ba515e917d06248b6459b20b6547ef496dAlex Deymo    return true;
739192393ba515e917d06248b6459b20b6547ef496dAlex Deymo
740192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  LOG(ERROR) << "Unable to determine file system type.";
741192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  return false;
742192393ba515e917d06248b6459b20b6547ef496dAlex Deymo}
743192393ba515e917d06248b6459b20b6547ef496dAlex Deymo
744192393ba515e917d06248b6459b20b6547ef496dAlex Deymobool GetExt3Size(const uint8_t* buffer, size_t buffer_size,
745192393ba515e917d06248b6459b20b6547ef496dAlex Deymo                 int* out_block_count,
746192393ba515e917d06248b6459b20b6547ef496dAlex Deymo                 int* out_block_size) {
747192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // See include/linux/ext2_fs.h for more details on the structure. We obtain
748192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // ext2 constants from ext2fs/ext2fs.h header but we don't link with the
749192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // library.
750192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  if (buffer_size < SUPERBLOCK_OFFSET + SUPERBLOCK_SIZE)
751192393ba515e917d06248b6459b20b6547ef496dAlex Deymo    return false;
752192393ba515e917d06248b6459b20b6547ef496dAlex Deymo
753192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  const uint8_t* superblock = buffer + SUPERBLOCK_OFFSET;
754192393ba515e917d06248b6459b20b6547ef496dAlex Deymo
755192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // ext3_fs.h: ext3_super_block.s_blocks_count
756192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  uint32_t block_count =
757192393ba515e917d06248b6459b20b6547ef496dAlex Deymo      *reinterpret_cast<const uint32_t*>(superblock + 1 * sizeof(int32_t));
758192393ba515e917d06248b6459b20b6547ef496dAlex Deymo
759192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // ext3_fs.h: ext3_super_block.s_log_block_size
760192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  uint32_t log_block_size =
761192393ba515e917d06248b6459b20b6547ef496dAlex Deymo      *reinterpret_cast<const uint32_t*>(superblock + 6 * sizeof(int32_t));
762192393ba515e917d06248b6459b20b6547ef496dAlex Deymo
763192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // ext3_fs.h: ext3_super_block.s_magic
764192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  uint16_t magic =
765192393ba515e917d06248b6459b20b6547ef496dAlex Deymo      *reinterpret_cast<const uint16_t*>(superblock + 14 * sizeof(int32_t));
766192393ba515e917d06248b6459b20b6547ef496dAlex Deymo
767d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov  block_count = le32toh(block_count);
768192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  log_block_size = le32toh(log_block_size) + EXT2_MIN_BLOCK_LOG_SIZE;
769d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov  magic = le16toh(magic);
770d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov
771d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov  // Sanity check the parameters.
772192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  TEST_AND_RETURN_FALSE(magic == EXT2_SUPER_MAGIC);
773192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  TEST_AND_RETURN_FALSE(log_block_size >= EXT2_MIN_BLOCK_LOG_SIZE &&
774192393ba515e917d06248b6459b20b6547ef496dAlex Deymo                        log_block_size <= EXT2_MAX_BLOCK_LOG_SIZE);
775d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov  TEST_AND_RETURN_FALSE(block_count > 0);
776d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov
777192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  if (out_block_count)
778d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov    *out_block_count = block_count;
779192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  if (out_block_size)
780192393ba515e917d06248b6459b20b6547ef496dAlex Deymo    *out_block_size = 1 << log_block_size;
781192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  return true;
782192393ba515e917d06248b6459b20b6547ef496dAlex Deymo}
783192393ba515e917d06248b6459b20b6547ef496dAlex Deymo
784f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenkobool GetSquashfs4Size(const uint8_t* buffer, size_t buffer_size,
785192393ba515e917d06248b6459b20b6547ef496dAlex Deymo                      int* out_block_count,
786192393ba515e917d06248b6459b20b6547ef496dAlex Deymo                      int* out_block_size) {
787192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // See fs/squashfs/squashfs_fs.h for format details. We only support
788192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // Squashfs 4.x little endian.
789192393ba515e917d06248b6459b20b6547ef496dAlex Deymo
790192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // sizeof(struct squashfs_super_block)
791192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  const size_t kSquashfsSuperBlockSize = 96;
792192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  if (buffer_size < kSquashfsSuperBlockSize)
793192393ba515e917d06248b6459b20b6547ef496dAlex Deymo    return false;
794192393ba515e917d06248b6459b20b6547ef496dAlex Deymo
795192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // Check magic, squashfs_fs.h: SQUASHFS_MAGIC
796192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  if (memcmp(buffer, "hsqs", 4) != 0)
797192393ba515e917d06248b6459b20b6547ef496dAlex Deymo    return false;  // Only little endian is supported.
798192393ba515e917d06248b6459b20b6547ef496dAlex Deymo
799192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // squashfs_fs.h: struct squashfs_super_block.s_major
800192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  uint16_t s_major = *reinterpret_cast<const uint16_t*>(
801192393ba515e917d06248b6459b20b6547ef496dAlex Deymo      buffer + 5 * sizeof(uint32_t) + 4 * sizeof(uint16_t));
802192393ba515e917d06248b6459b20b6547ef496dAlex Deymo
803192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  if (s_major != 4) {
804192393ba515e917d06248b6459b20b6547ef496dAlex Deymo    LOG(ERROR) << "Found unsupported squashfs major version " << s_major;
805192393ba515e917d06248b6459b20b6547ef496dAlex Deymo    return false;
806d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov  }
807192393ba515e917d06248b6459b20b6547ef496dAlex Deymo
808192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // squashfs_fs.h: struct squashfs_super_block.bytes_used
809192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  uint64_t bytes_used = *reinterpret_cast<const int64_t*>(
810192393ba515e917d06248b6459b20b6547ef496dAlex Deymo      buffer + 5 * sizeof(uint32_t) + 6 * sizeof(uint16_t) + sizeof(uint64_t));
811192393ba515e917d06248b6459b20b6547ef496dAlex Deymo
812192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  const int block_size = 4096;
813192393ba515e917d06248b6459b20b6547ef496dAlex Deymo
814192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // The squashfs' bytes_used doesn't need to be aligned with the block boundary
815192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  // so we round up to the nearest blocksize.
816192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  if (out_block_count)
817192393ba515e917d06248b6459b20b6547ef496dAlex Deymo    *out_block_count = (bytes_used + block_size - 1) / block_size;
818192393ba515e917d06248b6459b20b6547ef496dAlex Deymo  if (out_block_size)
819d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov    *out_block_size = block_size;
820d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov  return true;
821d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov}
822d3f8c89b7ed8f7ea58fe08ad98949101569e9869Darin Petkov
82360ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymobool IsExtFilesystem(const string& device) {
8243f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::Blob header;
825de942f30cf986cf6bfc55fb5f9af6d7fea4ae51bAlex Deymo  // The first 2 KiB is enough to read the ext2 superblock (located at offset
826de942f30cf986cf6bfc55fb5f9af6d7fea4ae51bAlex Deymo  // 1024).
827de942f30cf986cf6bfc55fb5f9af6d7fea4ae51bAlex Deymo  if (!ReadFileChunk(device, 0, 2048, &header))
828de942f30cf986cf6bfc55fb5f9af6d7fea4ae51bAlex Deymo    return false;
829de942f30cf986cf6bfc55fb5f9af6d7fea4ae51bAlex Deymo  return GetExt3Size(header.data(), header.size(), nullptr, nullptr);
830de942f30cf986cf6bfc55fb5f9af6d7fea4ae51bAlex Deymo}
831de942f30cf986cf6bfc55fb5f9af6d7fea4ae51bAlex Deymo
83260ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymobool IsSquashfsFilesystem(const string& device) {
8333f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::Blob header;
834de942f30cf986cf6bfc55fb5f9af6d7fea4ae51bAlex Deymo  // The first 96 is enough to read the squashfs superblock.
835de942f30cf986cf6bfc55fb5f9af6d7fea4ae51bAlex Deymo  const ssize_t kSquashfsSuperBlockSize = 96;
836de942f30cf986cf6bfc55fb5f9af6d7fea4ae51bAlex Deymo  if (!ReadFileChunk(device, 0, kSquashfsSuperBlockSize, &header))
837de942f30cf986cf6bfc55fb5f9af6d7fea4ae51bAlex Deymo    return false;
838de942f30cf986cf6bfc55fb5f9af6d7fea4ae51bAlex Deymo  return GetSquashfs4Size(header.data(), header.size(), nullptr, nullptr);
839de942f30cf986cf6bfc55fb5f9af6d7fea4ae51bAlex Deymo}
840de942f30cf986cf6bfc55fb5f9af6d7fea4ae51bAlex Deymo
841032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo// Tries to parse the header of an ELF file to obtain a human-readable
842032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo// description of it on the |output| string.
843f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenkostatic bool GetFileFormatELF(const uint8_t* buffer, size_t size,
844f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko                             string* output) {
845032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo  // 0x00: EI_MAG - ELF magic header, 4 bytes.
846c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo  if (size < SELFMAG || memcmp(buffer, ELFMAG, SELFMAG) != 0)
847032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo    return false;
848032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo  *output = "ELF";
849032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo
850032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo  // 0x04: EI_CLASS, 1 byte.
851c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo  if (size < EI_CLASS + 1)
852032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo    return true;
853c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo  switch (buffer[EI_CLASS]) {
854c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo    case ELFCLASS32:
855032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo      *output += " 32-bit";
856032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo      break;
857c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo    case ELFCLASS64:
858032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo      *output += " 64-bit";
859032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo      break;
860032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo    default:
861032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo      *output += " ?-bit";
862032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo  }
863032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo
864032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo  // 0x05: EI_DATA, endianness, 1 byte.
865c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo  if (size < EI_DATA + 1)
866032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo    return true;
867f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko  uint8_t ei_data = buffer[EI_DATA];
868032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo  switch (ei_data) {
869c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo    case ELFDATA2LSB:
870032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo      *output += " little-endian";
871032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo      break;
872c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo    case ELFDATA2MSB:
873032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo      *output += " big-endian";
874032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo      break;
875032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo    default:
876032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo      *output += " ?-endian";
877032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo      // Don't parse anything after the 0x10 offset if endianness is unknown.
878032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo      return true;
879032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo  }
880032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo
881c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo  const Elf32_Ehdr* hdr = reinterpret_cast<const Elf32_Ehdr*>(buffer);
882c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo  // 0x12: e_machine, 2 byte endianness based on ei_data. The position (0x12)
883c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo  // and size is the same for both 32 and 64 bits.
884c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo  if (size < offsetof(Elf32_Ehdr, e_machine) + sizeof(hdr->e_machine))
885032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo    return true;
886c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo  uint16_t e_machine;
887032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo  // Fix endianess regardless of the host endianess.
888c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo  if (ei_data == ELFDATA2LSB)
889c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo    e_machine = le16toh(hdr->e_machine);
890032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo  else
891c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo    e_machine = be16toh(hdr->e_machine);
892032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo
893032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo  switch (e_machine) {
894c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo    case EM_386:
895032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo      *output += " x86";
896032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo      break;
897c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo    case EM_MIPS:
898c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo      *output += " mips";
899c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo      break;
900c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo    case EM_ARM:
901032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo      *output += " arm";
902032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo      break;
903c1711e203f14111a5384860ad1a3ddf07c9d01edAlex Deymo    case EM_X86_64:
904032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo      *output += " x86-64";
905032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo      break;
906032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo    default:
907032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo      *output += " unknown-arch";
908032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo  }
909032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo  return true;
910032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo}
911032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo
912032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymostring GetFileFormat(const string& path) {
9133f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::Blob buffer;
914032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo  if (!ReadFileChunkAndAppend(path, 0, kGetFileFormatMaxHeaderSize, &buffer))
915032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo    return "File not found.";
916032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo
917032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo  string result;
918032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo  if (GetFileFormatELF(buffer.data(), buffer.size(), &result))
919032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo    return result;
920032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo
921032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo  return "data";
922032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo}
923032e772f76a6cd0b4caf1af7bd02dd81af2dc7ddAlex Deymo
924712b3ace08181a22659e7dd87ca225e307d453f2Andrew de los Reyesnamespace {
925712b3ace08181a22659e7dd87ca225e307d453f2Andrew de los Reyes// Do the actual trigger. We do it as a main-loop callback to (try to) get a
926712b3ace08181a22659e7dd87ca225e307d453f2Andrew de los Reyes// consistent stack trace.
92760ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymovoid TriggerCrashReporterUpload() {
928712b3ace08181a22659e7dd87ca225e307d453f2Andrew de los Reyes  pid_t pid = fork();
929d2779df63aaad8b65fc5d4badee7dbc9bed7f2b6Alex Vakulenko  CHECK_GE(pid, 0) << "fork failed";  // fork() failed. Something is very wrong.
930712b3ace08181a22659e7dd87ca225e307d453f2Andrew de los Reyes  if (pid == 0) {
931712b3ace08181a22659e7dd87ca225e307d453f2Andrew de los Reyes    // We are the child. Crash.
932712b3ace08181a22659e7dd87ca225e307d453f2Andrew de los Reyes    abort();  // never returns
933712b3ace08181a22659e7dd87ca225e307d453f2Andrew de los Reyes  }
934712b3ace08181a22659e7dd87ca225e307d453f2Andrew de los Reyes  // We are the parent. Wait for child to terminate.
93588b591f24cb3f94f982d7024c2e8ed25c2cc26a2Alex Vakulenko  pid_t result = waitpid(pid, nullptr, 0);
936712b3ace08181a22659e7dd87ca225e307d453f2Andrew de los Reyes  LOG_IF(ERROR, result < 0) << "waitpid() failed";
937712b3ace08181a22659e7dd87ca225e307d453f2Andrew de los Reyes}
938d2779df63aaad8b65fc5d4badee7dbc9bed7f2b6Alex Vakulenko}  // namespace
939712b3ace08181a22659e7dd87ca225e307d453f2Andrew de los Reyes
940712b3ace08181a22659e7dd87ca225e307d453f2Andrew de los Reyesvoid ScheduleCrashReporterUpload() {
9413f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::MessageLoop::current()->PostTask(
94260ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo      FROM_HERE,
94360ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo      base::Bind(&TriggerCrashReporterUpload));
944712b3ace08181a22659e7dd87ca225e307d453f2Andrew de los Reyes}
945712b3ace08181a22659e7dd87ca225e307d453f2Andrew de los Reyes
9465c0a8afa879886800d82b195e3164e5a580a2cc7Darin Petkovint FuzzInt(int value, unsigned int range) {
9475c0a8afa879886800d82b195e3164e5a580a2cc7Darin Petkov  int min = value - range / 2;
9485c0a8afa879886800d82b195e3164e5a580a2cc7Darin Petkov  int max = value + range - range / 2;
9495c0a8afa879886800d82b195e3164e5a580a2cc7Darin Petkov  return base::RandInt(min, max);
9505c0a8afa879886800d82b195e3164e5a580a2cc7Darin Petkov}
9515c0a8afa879886800d82b195e3164e5a580a2cc7Darin Petkov
952d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnoldstring FormatSecs(unsigned secs) {
9538e3f1263218c5046d2281c1d1d3c886acda85b47Gilad Arnold  return FormatTimeDelta(TimeDelta::FromSeconds(secs));
954d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold}
955d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold
9568e3f1263218c5046d2281c1d1d3c886acda85b47Gilad Arnoldstring FormatTimeDelta(TimeDelta delta) {
957973449e82eaf611adb911ac1b977baad2e2071e9David Zeuthen  string str;
958973449e82eaf611adb911ac1b977baad2e2071e9David Zeuthen
959973449e82eaf611adb911ac1b977baad2e2071e9David Zeuthen  // Handle negative durations by prefixing with a minus.
960973449e82eaf611adb911ac1b977baad2e2071e9David Zeuthen  if (delta.ToInternalValue() < 0) {
961973449e82eaf611adb911ac1b977baad2e2071e9David Zeuthen    delta *= -1;
962973449e82eaf611adb911ac1b977baad2e2071e9David Zeuthen    str = "-";
963973449e82eaf611adb911ac1b977baad2e2071e9David Zeuthen  }
964973449e82eaf611adb911ac1b977baad2e2071e9David Zeuthen
965d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold  // Canonicalize into days, hours, minutes, seconds and microseconds.
966d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold  unsigned days = delta.InDays();
9678e3f1263218c5046d2281c1d1d3c886acda85b47Gilad Arnold  delta -= TimeDelta::FromDays(days);
968d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold  unsigned hours = delta.InHours();
9698e3f1263218c5046d2281c1d1d3c886acda85b47Gilad Arnold  delta -= TimeDelta::FromHours(hours);
970d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold  unsigned mins = delta.InMinutes();
9718e3f1263218c5046d2281c1d1d3c886acda85b47Gilad Arnold  delta -= TimeDelta::FromMinutes(mins);
972d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold  unsigned secs = delta.InSeconds();
9738e3f1263218c5046d2281c1d1d3c886acda85b47Gilad Arnold  delta -= TimeDelta::FromSeconds(secs);
974d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold  unsigned usecs = delta.InMicroseconds();
9751ebd813ad19214d0b59ade04005c3b84ae765e42Gilad Arnold
976d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold  if (days)
977d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold    base::StringAppendF(&str, "%ud", days);
978d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold  if (days || hours)
9791ebd813ad19214d0b59ade04005c3b84ae765e42Gilad Arnold    base::StringAppendF(&str, "%uh", hours);
980d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold  if (days || hours || mins)
9811ebd813ad19214d0b59ade04005c3b84ae765e42Gilad Arnold    base::StringAppendF(&str, "%um", mins);
982d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold  base::StringAppendF(&str, "%u", secs);
983d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold  if (usecs) {
984d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold    int width = 6;
985d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold    while ((usecs / 10) * 10 == usecs) {
986d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold      usecs /= 10;
987d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold      width--;
988d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold    }
989d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold    base::StringAppendF(&str, ".%0*u", width, usecs);
990d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold  }
991d7b513d83954a28f3f71652b807aae4cc0c52f95Gilad Arnold  base::StringAppendF(&str, "s");
9921ebd813ad19214d0b59ade04005c3b84ae765e42Gilad Arnold  return str;
9931ebd813ad19214d0b59ade04005c3b84ae765e42Gilad Arnold}
9941ebd813ad19214d0b59ade04005c3b84ae765e42Gilad Arnold
995480ddfa079ebd01ed87e495332dec121d9ae781fJay Srinivasanstring ToString(const Time utc_time) {
996480ddfa079ebd01ed87e495332dec121d9ae781fJay Srinivasan  Time::Exploded exp_time;
997480ddfa079ebd01ed87e495332dec121d9ae781fJay Srinivasan  utc_time.UTCExplode(&exp_time);
99875039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko  return base::StringPrintf("%d/%d/%d %d:%02d:%02d GMT",
999480ddfa079ebd01ed87e495332dec121d9ae781fJay Srinivasan                      exp_time.month,
1000480ddfa079ebd01ed87e495332dec121d9ae781fJay Srinivasan                      exp_time.day_of_month,
1001480ddfa079ebd01ed87e495332dec121d9ae781fJay Srinivasan                      exp_time.year,
1002480ddfa079ebd01ed87e495332dec121d9ae781fJay Srinivasan                      exp_time.hour,
1003480ddfa079ebd01ed87e495332dec121d9ae781fJay Srinivasan                      exp_time.minute,
1004480ddfa079ebd01ed87e495332dec121d9ae781fJay Srinivasan                      exp_time.second);
1005480ddfa079ebd01ed87e495332dec121d9ae781fJay Srinivasan}
10063defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
1007ae4697c073b84b260990a141acd53c6806da0708Jay Srinivasanstring ToString(bool b) {
1008ae4697c073b84b260990a141acd53c6806da0708Jay Srinivasan  return (b ? "true" : "false");
1009ae4697c073b84b260990a141acd53c6806da0708Jay Srinivasan}
1010ae4697c073b84b260990a141acd53c6806da0708Jay Srinivasan
10111c656c48886cf5054b526ed7e95b05903d7644dbAlex Deymostring ToString(DownloadSource source) {
101219409b74019d787100b768306e75ab3e5882898dJay Srinivasan  switch (source) {
101319409b74019d787100b768306e75ab3e5882898dJay Srinivasan    case kDownloadSourceHttpsServer: return "HttpsServer";
101419409b74019d787100b768306e75ab3e5882898dJay Srinivasan    case kDownloadSourceHttpServer:  return "HttpServer";
1015bb8bdc7dd7e54afe181045cc17d5a0dbde99739bDavid Zeuthen    case kDownloadSourceHttpPeer:    return "HttpPeer";
101619409b74019d787100b768306e75ab3e5882898dJay Srinivasan    case kNumDownloadSources:        return "Unknown";
101719409b74019d787100b768306e75ab3e5882898dJay Srinivasan    // Don't add a default case to let the compiler warn about newly added
101819409b74019d787100b768306e75ab3e5882898dJay Srinivasan    // download sources which should be added here.
101919409b74019d787100b768306e75ab3e5882898dJay Srinivasan  }
102019409b74019d787100b768306e75ab3e5882898dJay Srinivasan
102119409b74019d787100b768306e75ab3e5882898dJay Srinivasan  return "Unknown";
102219409b74019d787100b768306e75ab3e5882898dJay Srinivasan}
102319409b74019d787100b768306e75ab3e5882898dJay Srinivasan
10241c656c48886cf5054b526ed7e95b05903d7644dbAlex Deymostring ToString(PayloadType payload_type) {
10251c656c48886cf5054b526ed7e95b05903d7644dbAlex Deymo  switch (payload_type) {
10261c656c48886cf5054b526ed7e95b05903d7644dbAlex Deymo    case kPayloadTypeDelta:      return "Delta";
10271c656c48886cf5054b526ed7e95b05903d7644dbAlex Deymo    case kPayloadTypeFull:       return "Full";
10281c656c48886cf5054b526ed7e95b05903d7644dbAlex Deymo    case kPayloadTypeForcedFull: return "ForcedFull";
10291c656c48886cf5054b526ed7e95b05903d7644dbAlex Deymo    case kNumPayloadTypes:       return "Unknown";
10301c656c48886cf5054b526ed7e95b05903d7644dbAlex Deymo    // Don't add a default case to let the compiler warn about newly added
10311c656c48886cf5054b526ed7e95b05903d7644dbAlex Deymo    // payload types which should be added here.
10321c656c48886cf5054b526ed7e95b05903d7644dbAlex Deymo  }
10331c656c48886cf5054b526ed7e95b05903d7644dbAlex Deymo
10341c656c48886cf5054b526ed7e95b05903d7644dbAlex Deymo  return "Unknown";
10351c656c48886cf5054b526ed7e95b05903d7644dbAlex Deymo}
10361c656c48886cf5054b526ed7e95b05903d7644dbAlex Deymo
1037a99981fda75fe0b17e96c700e3ddc93eca1cebe5David ZeuthenErrorCode GetBaseErrorCode(ErrorCode code) {
1038f057205065339c54d3403263f049e2ea69417665Jay Srinivasan  // Ignore the higher order bits in the code by applying the mask as
1039f057205065339c54d3403263f049e2ea69417665Jay Srinivasan  // we want the enumerations to be in the small contiguous range
1040d1c4d2dd3daed1d507038046c0355fbafb85260cGilad Arnold  // with values less than ErrorCode::kUmaReportedMax.
1041d1c4d2dd3daed1d507038046c0355fbafb85260cGilad Arnold  ErrorCode base_code = static_cast<ErrorCode>(
1042d1c4d2dd3daed1d507038046c0355fbafb85260cGilad Arnold      static_cast<int>(code) & ~static_cast<int>(ErrorCode::kSpecialFlags));
1043f057205065339c54d3403263f049e2ea69417665Jay Srinivasan
10442b5a0f065187fd19179e3809148dbfc376ada7a0Jay Srinivasan  // Make additional adjustments required for UMA and error classification.
10452b5a0f065187fd19179e3809148dbfc376ada7a0Jay Srinivasan  // TODO(jaysri): Move this logic to UeErrorCode.cc when we fix
10462b5a0f065187fd19179e3809148dbfc376ada7a0Jay Srinivasan  // chromium-os:34369.
1047d1c4d2dd3daed1d507038046c0355fbafb85260cGilad Arnold  if (base_code >= ErrorCode::kOmahaRequestHTTPResponseBase) {
1048f057205065339c54d3403263f049e2ea69417665Jay Srinivasan    // Since we want to keep the enums to a small value, aggregate all HTTP
10492b5a0f065187fd19179e3809148dbfc376ada7a0Jay Srinivasan    // errors into this one bucket for UMA and error classification purposes.
105055f50c24c2624487b803ba2f93588494cc69e523Jay Srinivasan    LOG(INFO) << "Converting error code " << base_code
1051d1c4d2dd3daed1d507038046c0355fbafb85260cGilad Arnold              << " to ErrorCode::kOmahaErrorInHTTPResponse";
1052d1c4d2dd3daed1d507038046c0355fbafb85260cGilad Arnold    base_code = ErrorCode::kOmahaErrorInHTTPResponse;
1053f057205065339c54d3403263f049e2ea69417665Jay Srinivasan  }
1054f057205065339c54d3403263f049e2ea69417665Jay Srinivasan
10552b5a0f065187fd19179e3809148dbfc376ada7a0Jay Srinivasan  return base_code;
10562b5a0f065187fd19179e3809148dbfc376ada7a0Jay Srinivasan}
10572b5a0f065187fd19179e3809148dbfc376ada7a0Jay Srinivasan
105830dedd82be72ffa9bbe570e9c95166ec6bcc7792Gilad Arnoldbool CreatePowerwashMarkerFile(const char* file_path) {
105930dedd82be72ffa9bbe570e9c95166ec6bcc7792Gilad Arnold  const char* marker_file = file_path ? file_path : kPowerwashMarkerFile;
106030dedd82be72ffa9bbe570e9c95166ec6bcc7792Gilad Arnold  bool result = utils::WriteFile(marker_file,
10611c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan                                 kPowerwashCommand,
10621c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan                                 strlen(kPowerwashCommand));
106330dedd82be72ffa9bbe570e9c95166ec6bcc7792Gilad Arnold  if (result) {
106430dedd82be72ffa9bbe570e9c95166ec6bcc7792Gilad Arnold    LOG(INFO) << "Created " << marker_file << " to powerwash on next reboot";
106530dedd82be72ffa9bbe570e9c95166ec6bcc7792Gilad Arnold  } else {
106630dedd82be72ffa9bbe570e9c95166ec6bcc7792Gilad Arnold    PLOG(ERROR) << "Error in creating powerwash marker file: " << marker_file;
106730dedd82be72ffa9bbe570e9c95166ec6bcc7792Gilad Arnold  }
10681c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan
10691c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan  return result;
10701c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan}
10711c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan
107230dedd82be72ffa9bbe570e9c95166ec6bcc7792Gilad Arnoldbool DeletePowerwashMarkerFile(const char* file_path) {
107330dedd82be72ffa9bbe570e9c95166ec6bcc7792Gilad Arnold  const char* marker_file = file_path ? file_path : kPowerwashMarkerFile;
107475039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko  const base::FilePath kPowerwashMarkerPath(marker_file);
107575039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko  bool result = base::DeleteFile(kPowerwashMarkerPath, false);
10761c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan
10771c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan  if (result)
10781c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan    LOG(INFO) << "Successfully deleted the powerwash marker file : "
107930dedd82be72ffa9bbe570e9c95166ec6bcc7792Gilad Arnold              << marker_file;
10801c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan  else
10811c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan    PLOG(ERROR) << "Could not delete the powerwash marker file : "
108230dedd82be72ffa9bbe570e9c95166ec6bcc7792Gilad Arnold                << marker_file;
10831c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan
10841c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan  return result;
10851c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan}
10861c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan
108727a48bc3f2531166370c214f7a21e17fb1fc7af1David ZeuthenTime TimeFromStructTimespec(struct timespec *ts) {
10889abb763fa3840d69cc1098c0233162557a7f99eaBen Chan  int64_t us = static_cast<int64_t>(ts->tv_sec) * Time::kMicrosecondsPerSecond +
10899abb763fa3840d69cc1098c0233162557a7f99eaBen Chan      static_cast<int64_t>(ts->tv_nsec) / Time::kNanosecondsPerMicrosecond;
109027a48bc3f2531166370c214f7a21e17fb1fc7af1David Zeuthen  return Time::UnixEpoch() + TimeDelta::FromMicroseconds(us);
109127a48bc3f2531166370c214f7a21e17fb1fc7af1David Zeuthen}
109227a48bc3f2531166370c214f7a21e17fb1fc7af1David Zeuthen
1093f329b933db41d26644a97afef928eb1b319d6d99Alex Deymostring StringVectorToString(const vector<string> &vec_str) {
109427a48bc3f2531166370c214f7a21e17fb1fc7af1David Zeuthen  string str = "[";
1095f329b933db41d26644a97afef928eb1b319d6d99Alex Deymo  for (vector<string>::const_iterator i = vec_str.begin();
1096f329b933db41d26644a97afef928eb1b319d6d99Alex Deymo       i != vec_str.end(); ++i) {
1097f329b933db41d26644a97afef928eb1b319d6d99Alex Deymo    if (i != vec_str.begin())
109827a48bc3f2531166370c214f7a21e17fb1fc7af1David Zeuthen      str += ", ";
109927a48bc3f2531166370c214f7a21e17fb1fc7af1David Zeuthen    str += '"';
110027a48bc3f2531166370c214f7a21e17fb1fc7af1David Zeuthen    str += *i;
110127a48bc3f2531166370c214f7a21e17fb1fc7af1David Zeuthen    str += '"';
110227a48bc3f2531166370c214f7a21e17fb1fc7af1David Zeuthen  }
110327a48bc3f2531166370c214f7a21e17fb1fc7af1David Zeuthen  str += "]";
110427a48bc3f2531166370c214f7a21e17fb1fc7af1David Zeuthen  return str;
110527a48bc3f2531166370c214f7a21e17fb1fc7af1David Zeuthen}
110627a48bc3f2531166370c214f7a21e17fb1fc7af1David Zeuthen
11078f191b22a1a1ab2b803d65ee488729206e648695David Zeuthenstring CalculateP2PFileId(const string& payload_hash, size_t payload_size) {
11083f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  string encoded_hash = brillo::data_encoding::Base64Encode(payload_hash);
1109c00c98a1dad941e5cc04ce0b0e766d40b3b384e1Alex Deymo  return base::StringPrintf("cros_update_size_%" PRIuS "_hash_%s",
1110981a9fb68ec5fe56f57b3ecb117a0dc681bf5e83Alex Vakulenko                            payload_size,
1111981a9fb68ec5fe56f57b3ecb117a0dc681bf5e83Alex Vakulenko                            encoded_hash.c_str());
11128f191b22a1a1ab2b803d65ee488729206e648695David Zeuthen}
11138f191b22a1a1ab2b803d65ee488729206e648695David Zeuthen
1114f329b933db41d26644a97afef928eb1b319d6d99Alex Deymobool DecodeAndStoreBase64String(const string& base64_encoded,
1115e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen                                base::FilePath *out_path) {
11163f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::Blob contents;
1117e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen
1118e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen  out_path->clear();
1119e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen
1120e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen  if (base64_encoded.size() == 0) {
1121e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen    LOG(ERROR) << "Can't decode empty string.";
1122e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen    return false;
1123e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen  }
1124e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen
11253f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  if (!brillo::data_encoding::Base64Decode(base64_encoded, &contents) ||
1126e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen      contents.size() == 0) {
1127e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen    LOG(ERROR) << "Error decoding base64.";
1128e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen    return false;
1129e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen  }
1130e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen
113175039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko  FILE *file = base::CreateAndOpenTemporaryFile(out_path);
113288b591f24cb3f94f982d7024c2e8ed25c2cc26a2Alex Vakulenko  if (file == nullptr) {
1133e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen    LOG(ERROR) << "Error creating temporary file.";
1134e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen    return false;
1135e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen  }
1136e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen
1137981a9fb68ec5fe56f57b3ecb117a0dc681bf5e83Alex Vakulenko  if (fwrite(contents.data(), 1, contents.size(), file) != contents.size()) {
1138e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen    PLOG(ERROR) << "Error writing to temporary file.";
1139e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen    if (fclose(file) != 0)
1140e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen      PLOG(ERROR) << "Error closing temporary file.";
1141e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen    if (unlink(out_path->value().c_str()) != 0)
1142e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen      PLOG(ERROR) << "Error unlinking temporary file.";
1143e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen    out_path->clear();
1144e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen    return false;
1145e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen  }
1146e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen
1147e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen  if (fclose(file) != 0) {
1148e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen    PLOG(ERROR) << "Error closing temporary file.";
1149e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen    out_path->clear();
1150e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen    return false;
1151e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen  }
1152e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen
1153e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen  return true;
1154e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen}
1155e7f8917f378773fbfee0b2d21f1cb6b3ba8bdcabDavid Zeuthen
1156f329b933db41d26644a97afef928eb1b319d6d99Alex Deymobool ConvertToOmahaInstallDate(Time time, int *out_num_days) {
1157639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen  time_t unix_time = time.ToTimeT();
1158639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen  // Output of: date +"%s" --date="Jan 1, 2007 0:00 PST".
1159639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen  const time_t kOmahaEpoch = 1167638400;
1160639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen  const int64_t kNumSecondsPerWeek = 7*24*3600;
1161639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen  const int64_t kNumDaysPerWeek = 7;
1162639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen
1163639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen  time_t omaha_time = unix_time - kOmahaEpoch;
1164639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen
1165639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen  if (omaha_time < 0)
1166639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen    return false;
1167639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen
1168639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen  // Note, as per the comment in utils.h we are deliberately not
1169639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen  // handling DST correctly.
1170639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen
1171639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen  int64_t num_weeks_since_omaha_epoch = omaha_time / kNumSecondsPerWeek;
1172639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen  *out_num_days = num_weeks_since_omaha_epoch * kNumDaysPerWeek;
1173639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen
1174639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen  return true;
1175639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen}
1176639aa36fc7e27ba400402cd7a32b091f555783a6David Zeuthen
11773f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenkobool GetMinorVersion(const brillo::KeyValueStore& store,
1178b42b98db059a12c44110588fc0b3d5f82d32a2f8Alex Deymo                     uint32_t* minor_version) {
117960ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo  string result;
1180b42b98db059a12c44110588fc0b3d5f82d32a2f8Alex Deymo  if (store.GetString("PAYLOAD_MINOR_VERSION", &result)) {
1181425aa9764d6eac48cf06f726a30422d4e184c3d1Allie Wood    if (!base::StringToUint(result, minor_version)) {
1182425aa9764d6eac48cf06f726a30422d4e184c3d1Allie Wood      LOG(ERROR) << "StringToUint failed when parsing delta minor version.";
1183425aa9764d6eac48cf06f726a30422d4e184c3d1Allie Wood      return false;
1184425aa9764d6eac48cf06f726a30422d4e184c3d1Allie Wood    }
118578750a450ce84b2d335134402d041aa8773ab8efAllie Wood    return true;
118678750a450ce84b2d335134402d041aa8773ab8efAllie Wood  }
118778750a450ce84b2d335134402d041aa8773ab8efAllie Wood  return false;
118878750a450ce84b2d335134402d041aa8773ab8efAllie Wood}
118978750a450ce84b2d335134402d041aa8773ab8efAllie Wood
11903a92aa2fe6aafd1007b6427795dfe8711b6cb094Sen Jiangbool IsZlibCompatible(const string& fingerprint) {
11913a92aa2fe6aafd1007b6427795dfe8711b6cb094Sen Jiang  if (fingerprint.size() != sizeof(kCompatibleZlibFingerprint[0]) - 1) {
11923a92aa2fe6aafd1007b6427795dfe8711b6cb094Sen Jiang    LOG(ERROR) << "Invalid fingerprint: " << fingerprint;
11933a92aa2fe6aafd1007b6427795dfe8711b6cb094Sen Jiang    return false;
11943a92aa2fe6aafd1007b6427795dfe8711b6cb094Sen Jiang  }
11953a92aa2fe6aafd1007b6427795dfe8711b6cb094Sen Jiang  for (auto& f : kCompatibleZlibFingerprint) {
11963a92aa2fe6aafd1007b6427795dfe8711b6cb094Sen Jiang    if (base::CompareCaseInsensitiveASCII(fingerprint, f) == 0) {
11973a92aa2fe6aafd1007b6427795dfe8711b6cb094Sen Jiang      return true;
11983a92aa2fe6aafd1007b6427795dfe8711b6cb094Sen Jiang    }
11993a92aa2fe6aafd1007b6427795dfe8711b6cb094Sen Jiang  }
12003a92aa2fe6aafd1007b6427795dfe8711b6cb094Sen Jiang  return false;
12013a92aa2fe6aafd1007b6427795dfe8711b6cb094Sen Jiang}
12023a92aa2fe6aafd1007b6427795dfe8711b6cb094Sen Jiang
120360ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymobool ReadExtents(const string& path, const vector<Extent>& extents,
12043f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko                 brillo::Blob* out_data, ssize_t out_data_size,
1205568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood                 size_t block_size) {
12063f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::Blob data(out_data_size);
1207568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood  ssize_t bytes_read = 0;
1208568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood  int fd = open(path.c_str(), O_RDONLY);
1209568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood  TEST_AND_RETURN_FALSE_ERRNO(fd >= 0);
1210568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood  ScopedFdCloser fd_closer(&fd);
1211568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood
121241e3474eebe3748a45aba4b297a7a313a1006c6cGilad Arnold  for (const Extent& extent : extents) {
1213568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood    ssize_t bytes_read_this_iteration = 0;
1214568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood    ssize_t bytes = extent.num_blocks() * block_size;
1215568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood    TEST_AND_RETURN_FALSE(bytes_read + bytes <= out_data_size);
1216568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood    TEST_AND_RETURN_FALSE(utils::PReadAll(fd,
1217568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood                                          &data[bytes_read],
1218568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood                                          bytes,
1219568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood                                          extent.start_block() * block_size,
1220568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood                                          &bytes_read_this_iteration));
1221568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood    TEST_AND_RETURN_FALSE(bytes_read_this_iteration == bytes);
1222568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood    bytes_read += bytes_read_this_iteration;
1223568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood  }
1224568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood  TEST_AND_RETURN_FALSE(out_data_size == bytes_read);
1225568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood  *out_data = data;
1226568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood  return true;
1227568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood}
1228568734533c25a5783ea004aeb0da38244dcd3e5bAllie Wood
1229dd132f39cced9028c01e98895a4f6c5fb9553de1Alex Deymobool GetBootId(string* boot_id) {
1230dd132f39cced9028c01e98895a4f6c5fb9553de1Alex Deymo  TEST_AND_RETURN_FALSE(
1231dd132f39cced9028c01e98895a4f6c5fb9553de1Alex Deymo      base::ReadFileToString(base::FilePath(kBootIdPath), boot_id));
1232dd132f39cced9028c01e98895a4f6c5fb9553de1Alex Deymo  base::TrimWhitespaceASCII(*boot_id, base::TRIM_TRAILING, boot_id);
1233dd132f39cced9028c01e98895a4f6c5fb9553de1Alex Deymo  return true;
1234dd132f39cced9028c01e98895a4f6c5fb9553de1Alex Deymo}
1235dd132f39cced9028c01e98895a4f6c5fb9553de1Alex Deymo
12363defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com}  // namespace utils
12373defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
12383defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com}  // namespace chromeos_update_engine
1239