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