1 // 2 // Copyright (C) 2012 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include "update_engine/common/utils.h" 18 19 #include <stdint.h> 20 21 #include <dirent.h> 22 #include <elf.h> 23 #include <endian.h> 24 #include <errno.h> 25 #include <fcntl.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <sys/mount.h> 30 #include <sys/resource.h> 31 #include <sys/stat.h> 32 #include <sys/types.h> 33 #include <unistd.h> 34 35 #include <algorithm> 36 #include <utility> 37 #include <vector> 38 39 #include <base/callback.h> 40 #include <base/files/file_path.h> 41 #include <base/files/file_util.h> 42 #include <base/files/scoped_file.h> 43 #include <base/format_macros.h> 44 #include <base/location.h> 45 #include <base/logging.h> 46 #include <base/posix/eintr_wrapper.h> 47 #include <base/rand_util.h> 48 #include <base/strings/string_number_conversions.h> 49 #include <base/strings/string_split.h> 50 #include <base/strings/string_util.h> 51 #include <base/strings/stringprintf.h> 52 #include <brillo/data_encoding.h> 53 54 #include "update_engine/common/clock_interface.h" 55 #include "update_engine/common/constants.h" 56 #include "update_engine/common/platform_constants.h" 57 #include "update_engine/common/prefs_interface.h" 58 #include "update_engine/common/subprocess.h" 59 #include "update_engine/payload_consumer/file_descriptor.h" 60 61 using base::Time; 62 using base::TimeDelta; 63 using std::min; 64 using std::pair; 65 using std::string; 66 using std::vector; 67 68 namespace chromeos_update_engine { 69 70 namespace { 71 72 // The following constants control how UnmountFilesystem should retry if 73 // umount() fails with an errno EBUSY, i.e. retry 5 times over the course of 74 // one second. 75 const int kUnmountMaxNumOfRetries = 5; 76 const int kUnmountRetryIntervalInMicroseconds = 200 * 1000; // 200 ms 77 78 // Number of bytes to read from a file to attempt to detect its contents. Used 79 // in GetFileFormat. 80 const int kGetFileFormatMaxHeaderSize = 32; 81 82 // The path to the kernel's boot_id. 83 const char kBootIdPath[] = "/proc/sys/kernel/random/boot_id"; 84 85 // A pointer to a null-terminated string containing the root directory where all 86 // the temporary files should be created. If null, the system default is used 87 // instead. 88 const char* root_temp_dir = nullptr; 89 90 // Return true if |disk_name| is an MTD or a UBI device. Note that this test is 91 // simply based on the name of the device. 92 bool IsMtdDeviceName(const string& disk_name) { 93 return base::StartsWith(disk_name, "/dev/ubi", 94 base::CompareCase::SENSITIVE) || 95 base::StartsWith(disk_name, "/dev/mtd", base::CompareCase::SENSITIVE); 96 } 97 98 // Return the device name for the corresponding partition on a NAND device. 99 // WARNING: This function returns device names that are not mountable. 100 string MakeNandPartitionName(int partition_num) { 101 switch (partition_num) { 102 case 2: 103 case 4: 104 case 6: { 105 return base::StringPrintf("/dev/mtd%d", partition_num); 106 } 107 default: { 108 return base::StringPrintf("/dev/ubi%d_0", partition_num); 109 } 110 } 111 } 112 113 // Return the device name for the corresponding partition on a NAND device that 114 // may be mountable (but may not be writable). 115 string MakeNandPartitionNameForMount(int partition_num) { 116 switch (partition_num) { 117 case 2: 118 case 4: 119 case 6: { 120 return base::StringPrintf("/dev/mtd%d", partition_num); 121 } 122 case 3: 123 case 5: 124 case 7: { 125 return base::StringPrintf("/dev/ubiblock%d_0", partition_num); 126 } 127 default: { 128 return base::StringPrintf("/dev/ubi%d_0", partition_num); 129 } 130 } 131 } 132 133 // If |path| is absolute, or explicit relative to the current working directory, 134 // leaves it as is. Otherwise, uses the system's temp directory, as defined by 135 // base::GetTempDir() and prepends it to |path|. On success stores the full 136 // temporary path in |template_path| and returns true. 137 bool GetTempName(const string& path, base::FilePath* template_path) { 138 if (path[0] == '/' || 139 base::StartsWith(path, "./", base::CompareCase::SENSITIVE) || 140 base::StartsWith(path, "../", base::CompareCase::SENSITIVE)) { 141 *template_path = base::FilePath(path); 142 return true; 143 } 144 145 base::FilePath temp_dir; 146 if (root_temp_dir) { 147 temp_dir = base::FilePath(root_temp_dir); 148 } else { 149 #ifdef __ANDROID__ 150 temp_dir = base::FilePath(constants::kNonVolatileDirectory).Append("tmp"); 151 #else 152 TEST_AND_RETURN_FALSE(base::GetTempDir(&temp_dir)); 153 #endif // __ANDROID__ 154 } 155 if (!base::PathExists(temp_dir)) 156 TEST_AND_RETURN_FALSE(base::CreateDirectory(temp_dir)); 157 *template_path = temp_dir.Append(path); 158 return true; 159 } 160 161 } // namespace 162 163 namespace utils { 164 165 void SetRootTempDir(const char* new_root_temp_dir) { 166 root_temp_dir = new_root_temp_dir; 167 } 168 169 string ParseECVersion(string input_line) { 170 base::TrimWhitespaceASCII(input_line, base::TRIM_ALL, &input_line); 171 172 // At this point we want to convert the format key=value pair from mosys to 173 // a vector of key value pairs. 174 vector<pair<string, string>> kv_pairs; 175 if (base::SplitStringIntoKeyValuePairs(input_line, '=', ' ', &kv_pairs)) { 176 for (const pair<string, string>& kv_pair : kv_pairs) { 177 // Finally match against the fw_verion which may have quotes. 178 if (kv_pair.first == "fw_version") { 179 string output; 180 // Trim any quotes. 181 base::TrimString(kv_pair.second, "\"", &output); 182 return output; 183 } 184 } 185 } 186 LOG(ERROR) << "Unable to parse fwid from ec info."; 187 return ""; 188 } 189 190 bool WriteFile(const char* path, const void* data, size_t data_len) { 191 int fd = HANDLE_EINTR(open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600)); 192 TEST_AND_RETURN_FALSE_ERRNO(fd >= 0); 193 ScopedFdCloser fd_closer(&fd); 194 return WriteAll(fd, data, data_len); 195 } 196 197 bool ReadAll( 198 int fd, void* buf, size_t count, size_t* out_bytes_read, bool* eof) { 199 char* c_buf = static_cast<char*>(buf); 200 size_t bytes_read = 0; 201 *eof = false; 202 while (bytes_read < count) { 203 ssize_t rc = HANDLE_EINTR(read(fd, c_buf + bytes_read, count - bytes_read)); 204 if (rc < 0) { 205 // EAGAIN and EWOULDBLOCK are normal return values when there's no more 206 // input and we are in non-blocking mode. 207 if (errno != EWOULDBLOCK && errno != EAGAIN) { 208 PLOG(ERROR) << "Error reading fd " << fd; 209 *out_bytes_read = bytes_read; 210 return false; 211 } 212 break; 213 } else if (rc == 0) { 214 // A value of 0 means that we reached EOF and there is nothing else to 215 // read from this fd. 216 *eof = true; 217 break; 218 } else { 219 bytes_read += rc; 220 } 221 } 222 *out_bytes_read = bytes_read; 223 return true; 224 } 225 226 bool WriteAll(int fd, const void* buf, size_t count) { 227 const char* c_buf = static_cast<const char*>(buf); 228 ssize_t bytes_written = 0; 229 while (bytes_written < static_cast<ssize_t>(count)) { 230 ssize_t rc = write(fd, c_buf + bytes_written, count - bytes_written); 231 TEST_AND_RETURN_FALSE_ERRNO(rc >= 0); 232 bytes_written += rc; 233 } 234 return true; 235 } 236 237 bool PWriteAll(int fd, const void* buf, size_t count, off_t offset) { 238 const char* c_buf = static_cast<const char*>(buf); 239 size_t bytes_written = 0; 240 int num_attempts = 0; 241 while (bytes_written < count) { 242 num_attempts++; 243 ssize_t rc = pwrite(fd, c_buf + bytes_written, count - bytes_written, 244 offset + bytes_written); 245 // TODO(garnold) for debugging failure in chromium-os:31077; to be removed. 246 if (rc < 0) { 247 PLOG(ERROR) << "pwrite error; num_attempts=" << num_attempts 248 << " bytes_written=" << bytes_written 249 << " count=" << count << " offset=" << offset; 250 } 251 TEST_AND_RETURN_FALSE_ERRNO(rc >= 0); 252 bytes_written += rc; 253 } 254 return true; 255 } 256 257 bool WriteAll(const FileDescriptorPtr& fd, const void* buf, size_t count) { 258 const char* c_buf = static_cast<const char*>(buf); 259 ssize_t bytes_written = 0; 260 while (bytes_written < static_cast<ssize_t>(count)) { 261 ssize_t rc = fd->Write(c_buf + bytes_written, count - bytes_written); 262 TEST_AND_RETURN_FALSE_ERRNO(rc >= 0); 263 bytes_written += rc; 264 } 265 return true; 266 } 267 268 bool PWriteAll(const FileDescriptorPtr& fd, 269 const void* buf, 270 size_t count, 271 off_t offset) { 272 TEST_AND_RETURN_FALSE_ERRNO(fd->Seek(offset, SEEK_SET) != 273 static_cast<off_t>(-1)); 274 return WriteAll(fd, buf, count); 275 } 276 277 bool PReadAll(int fd, void* buf, size_t count, off_t offset, 278 ssize_t* out_bytes_read) { 279 char* c_buf = static_cast<char*>(buf); 280 ssize_t bytes_read = 0; 281 while (bytes_read < static_cast<ssize_t>(count)) { 282 ssize_t rc = pread(fd, c_buf + bytes_read, count - bytes_read, 283 offset + bytes_read); 284 TEST_AND_RETURN_FALSE_ERRNO(rc >= 0); 285 if (rc == 0) { 286 break; 287 } 288 bytes_read += rc; 289 } 290 *out_bytes_read = bytes_read; 291 return true; 292 } 293 294 bool PReadAll(const FileDescriptorPtr& fd, void* buf, size_t count, off_t offset, 295 ssize_t* out_bytes_read) { 296 TEST_AND_RETURN_FALSE_ERRNO(fd->Seek(offset, SEEK_SET) != 297 static_cast<off_t>(-1)); 298 char* c_buf = static_cast<char*>(buf); 299 ssize_t bytes_read = 0; 300 while (bytes_read < static_cast<ssize_t>(count)) { 301 ssize_t rc = fd->Read(c_buf + bytes_read, count - bytes_read); 302 TEST_AND_RETURN_FALSE_ERRNO(rc >= 0); 303 if (rc == 0) { 304 break; 305 } 306 bytes_read += rc; 307 } 308 *out_bytes_read = bytes_read; 309 return true; 310 } 311 312 // Append |nbytes| of content from |buf| to the vector pointed to by either 313 // |vec_p| or |str_p|. 314 static void AppendBytes(const uint8_t* buf, size_t nbytes, 315 brillo::Blob* vec_p) { 316 CHECK(buf); 317 CHECK(vec_p); 318 vec_p->insert(vec_p->end(), buf, buf + nbytes); 319 } 320 static void AppendBytes(const uint8_t* buf, size_t nbytes, 321 string* str_p) { 322 CHECK(buf); 323 CHECK(str_p); 324 str_p->append(buf, buf + nbytes); 325 } 326 327 // Reads from an open file |fp|, appending the read content to the container 328 // pointer to by |out_p|. Returns true upon successful reading all of the 329 // file's content, false otherwise. If |size| is not -1, reads up to |size| 330 // bytes. 331 template <class T> 332 static bool Read(FILE* fp, off_t size, T* out_p) { 333 CHECK(fp); 334 CHECK(size == -1 || size >= 0); 335 uint8_t buf[1024]; 336 while (size == -1 || size > 0) { 337 off_t bytes_to_read = sizeof(buf); 338 if (size > 0 && bytes_to_read > size) { 339 bytes_to_read = size; 340 } 341 size_t nbytes = fread(buf, 1, bytes_to_read, fp); 342 if (!nbytes) { 343 break; 344 } 345 AppendBytes(buf, nbytes, out_p); 346 if (size != -1) { 347 CHECK(size >= static_cast<off_t>(nbytes)); 348 size -= nbytes; 349 } 350 } 351 if (ferror(fp)) { 352 return false; 353 } 354 return size == 0 || feof(fp); 355 } 356 357 // Opens a file |path| for reading and appends its the contents to a container 358 // |out_p|. Starts reading the file from |offset|. If |offset| is beyond the end 359 // of the file, returns success. If |size| is not -1, reads up to |size| bytes. 360 template <class T> 361 static bool ReadFileChunkAndAppend(const string& path, 362 off_t offset, 363 off_t size, 364 T* out_p) { 365 CHECK_GE(offset, 0); 366 CHECK(size == -1 || size >= 0); 367 base::ScopedFILE fp(fopen(path.c_str(), "r")); 368 if (!fp.get()) 369 return false; 370 if (offset) { 371 // Return success without appending any data if a chunk beyond the end of 372 // the file is requested. 373 if (offset >= FileSize(path)) { 374 return true; 375 } 376 TEST_AND_RETURN_FALSE_ERRNO(fseek(fp.get(), offset, SEEK_SET) == 0); 377 } 378 return Read(fp.get(), size, out_p); 379 } 380 381 // TODO(deymo): This is only used in unittest, but requires the private 382 // Read<string>() defined here. Expose Read<string>() or move to base/ version. 383 bool ReadPipe(const string& cmd, string* out_p) { 384 FILE* fp = popen(cmd.c_str(), "r"); 385 if (!fp) 386 return false; 387 bool success = Read(fp, -1, out_p); 388 return (success && pclose(fp) >= 0); 389 } 390 391 bool ReadFile(const string& path, brillo::Blob* out_p) { 392 return ReadFileChunkAndAppend(path, 0, -1, out_p); 393 } 394 395 bool ReadFile(const string& path, string* out_p) { 396 return ReadFileChunkAndAppend(path, 0, -1, out_p); 397 } 398 399 bool ReadFileChunk(const string& path, off_t offset, off_t size, 400 brillo::Blob* out_p) { 401 return ReadFileChunkAndAppend(path, offset, size, out_p); 402 } 403 404 off_t BlockDevSize(int fd) { 405 uint64_t dev_size; 406 int rc = ioctl(fd, BLKGETSIZE64, &dev_size); 407 if (rc == -1) { 408 dev_size = -1; 409 PLOG(ERROR) << "Error running ioctl(BLKGETSIZE64) on " << fd; 410 } 411 return dev_size; 412 } 413 414 off_t FileSize(int fd) { 415 struct stat stbuf; 416 int rc = fstat(fd, &stbuf); 417 CHECK_EQ(rc, 0); 418 if (rc < 0) { 419 PLOG(ERROR) << "Error stat-ing " << fd; 420 return rc; 421 } 422 if (S_ISREG(stbuf.st_mode)) 423 return stbuf.st_size; 424 if (S_ISBLK(stbuf.st_mode)) 425 return BlockDevSize(fd); 426 LOG(ERROR) << "Couldn't determine the type of " << fd; 427 return -1; 428 } 429 430 off_t FileSize(const string& path) { 431 int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC); 432 if (fd == -1) { 433 PLOG(ERROR) << "Error opening " << path; 434 return fd; 435 } 436 off_t size = FileSize(fd); 437 if (size == -1) 438 PLOG(ERROR) << "Error getting file size of " << path; 439 close(fd); 440 return size; 441 } 442 443 void HexDumpArray(const uint8_t* const arr, const size_t length) { 444 LOG(INFO) << "Logging array of length: " << length; 445 const unsigned int bytes_per_line = 16; 446 for (uint32_t i = 0; i < length; i += bytes_per_line) { 447 const unsigned int bytes_remaining = length - i; 448 const unsigned int bytes_per_this_line = min(bytes_per_line, 449 bytes_remaining); 450 char header[100]; 451 int r = snprintf(header, sizeof(header), "0x%08x : ", i); 452 TEST_AND_RETURN(r == 13); 453 string line = header; 454 for (unsigned int j = 0; j < bytes_per_this_line; j++) { 455 char buf[20]; 456 uint8_t c = arr[i + j]; 457 r = snprintf(buf, sizeof(buf), "%02x ", static_cast<unsigned int>(c)); 458 TEST_AND_RETURN(r == 3); 459 line += buf; 460 } 461 LOG(INFO) << line; 462 } 463 } 464 465 bool SplitPartitionName(const string& partition_name, 466 string* out_disk_name, 467 int* out_partition_num) { 468 if (!base::StartsWith(partition_name, "/dev/", 469 base::CompareCase::SENSITIVE)) { 470 LOG(ERROR) << "Invalid partition device name: " << partition_name; 471 return false; 472 } 473 474 size_t last_nondigit_pos = partition_name.find_last_not_of("0123456789"); 475 if (last_nondigit_pos == string::npos || 476 (last_nondigit_pos + 1) == partition_name.size()) { 477 LOG(ERROR) << "Unable to parse partition device name: " << partition_name; 478 return false; 479 } 480 481 size_t partition_name_len = string::npos; 482 if (partition_name[last_nondigit_pos] == '_') { 483 // NAND block devices have weird naming which could be something 484 // like "/dev/ubiblock2_0". We discard "_0" in such a case. 485 size_t prev_nondigit_pos = 486 partition_name.find_last_not_of("0123456789", last_nondigit_pos - 1); 487 if (prev_nondigit_pos == string::npos || 488 (prev_nondigit_pos + 1) == last_nondigit_pos) { 489 LOG(ERROR) << "Unable to parse partition device name: " << partition_name; 490 return false; 491 } 492 493 partition_name_len = last_nondigit_pos - prev_nondigit_pos; 494 last_nondigit_pos = prev_nondigit_pos; 495 } 496 497 if (out_disk_name) { 498 // Special case for MMC devices which have the following naming scheme: 499 // mmcblk0p2 500 size_t disk_name_len = last_nondigit_pos; 501 if (partition_name[last_nondigit_pos] != 'p' || 502 last_nondigit_pos == 0 || 503 !isdigit(partition_name[last_nondigit_pos - 1])) { 504 disk_name_len++; 505 } 506 *out_disk_name = partition_name.substr(0, disk_name_len); 507 } 508 509 if (out_partition_num) { 510 string partition_str = partition_name.substr(last_nondigit_pos + 1, 511 partition_name_len); 512 *out_partition_num = atoi(partition_str.c_str()); 513 } 514 return true; 515 } 516 517 string MakePartitionName(const string& disk_name, int partition_num) { 518 if (partition_num < 1) { 519 LOG(ERROR) << "Invalid partition number: " << partition_num; 520 return string(); 521 } 522 523 if (!base::StartsWith(disk_name, "/dev/", base::CompareCase::SENSITIVE)) { 524 LOG(ERROR) << "Invalid disk name: " << disk_name; 525 return string(); 526 } 527 528 if (IsMtdDeviceName(disk_name)) { 529 // Special case for UBI block devices. 530 // 1. ubiblock is not writable, we need to use plain "ubi". 531 // 2. There is a "_0" suffix. 532 return MakeNandPartitionName(partition_num); 533 } 534 535 string partition_name = disk_name; 536 if (isdigit(partition_name.back())) { 537 // Special case for devices with names ending with a digit. 538 // Add "p" to separate the disk name from partition number, 539 // e.g. "/dev/loop0p2" 540 partition_name += 'p'; 541 } 542 543 partition_name += std::to_string(partition_num); 544 545 return partition_name; 546 } 547 548 string MakePartitionNameForMount(const string& part_name) { 549 if (IsMtdDeviceName(part_name)) { 550 int partition_num; 551 if (!SplitPartitionName(part_name, nullptr, &partition_num)) { 552 return ""; 553 } 554 return MakeNandPartitionNameForMount(partition_num); 555 } 556 return part_name; 557 } 558 559 string ErrnoNumberAsString(int err) { 560 char buf[100]; 561 buf[0] = '\0'; 562 return strerror_r(err, buf, sizeof(buf)); 563 } 564 565 bool FileExists(const char* path) { 566 struct stat stbuf; 567 return 0 == lstat(path, &stbuf); 568 } 569 570 bool IsSymlink(const char* path) { 571 struct stat stbuf; 572 return lstat(path, &stbuf) == 0 && S_ISLNK(stbuf.st_mode) != 0; 573 } 574 575 bool TryAttachingUbiVolume(int volume_num, int timeout) { 576 const string volume_path = base::StringPrintf("/dev/ubi%d_0", volume_num); 577 if (FileExists(volume_path.c_str())) { 578 return true; 579 } 580 581 int exit_code; 582 vector<string> cmd = { 583 "ubiattach", 584 "-m", 585 base::StringPrintf("%d", volume_num), 586 "-d", 587 base::StringPrintf("%d", volume_num) 588 }; 589 TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &exit_code, nullptr)); 590 TEST_AND_RETURN_FALSE(exit_code == 0); 591 592 cmd = { 593 "ubiblock", 594 "--create", 595 volume_path 596 }; 597 TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &exit_code, nullptr)); 598 TEST_AND_RETURN_FALSE(exit_code == 0); 599 600 while (timeout > 0 && !FileExists(volume_path.c_str())) { 601 sleep(1); 602 timeout--; 603 } 604 605 return FileExists(volume_path.c_str()); 606 } 607 608 bool MakeTempFile(const string& base_filename_template, 609 string* filename, 610 int* fd) { 611 base::FilePath filename_template; 612 TEST_AND_RETURN_FALSE( 613 GetTempName(base_filename_template, &filename_template)); 614 DCHECK(filename || fd); 615 vector<char> buf(filename_template.value().size() + 1); 616 memcpy(buf.data(), filename_template.value().data(), 617 filename_template.value().size()); 618 buf[filename_template.value().size()] = '\0'; 619 620 int mkstemp_fd = mkstemp(buf.data()); 621 TEST_AND_RETURN_FALSE_ERRNO(mkstemp_fd >= 0); 622 if (filename) { 623 *filename = buf.data(); 624 } 625 if (fd) { 626 *fd = mkstemp_fd; 627 } else { 628 close(mkstemp_fd); 629 } 630 return true; 631 } 632 633 bool SetBlockDeviceReadOnly(const string& device, bool read_only) { 634 int fd = HANDLE_EINTR(open(device.c_str(), O_RDONLY | O_CLOEXEC)); 635 if (fd < 0) { 636 PLOG(ERROR) << "Opening block device " << device; 637 return false; 638 } 639 ScopedFdCloser fd_closer(&fd); 640 // We take no action if not needed. 641 int read_only_flag; 642 int expected_flag = read_only ? 1 : 0; 643 int rc = ioctl(fd, BLKROGET, &read_only_flag); 644 // In case of failure reading the setting we will try to set it anyway. 645 if (rc == 0 && read_only_flag == expected_flag) 646 return true; 647 648 rc = ioctl(fd, BLKROSET, &expected_flag); 649 if (rc != 0) { 650 PLOG(ERROR) << "Marking block device " << device << " as read_only=" 651 << expected_flag; 652 return false; 653 } 654 return true; 655 } 656 657 bool MountFilesystem(const string& device, 658 const string& mountpoint, 659 unsigned long mountflags, // NOLINT(runtime/int) 660 const string& type, 661 const string& fs_mount_options) { 662 vector<const char*> fstypes; 663 if (type.empty()) { 664 fstypes = {"ext2", "ext3", "ext4", "squashfs"}; 665 } else { 666 fstypes = {type.c_str()}; 667 } 668 for (const char* fstype : fstypes) { 669 int rc = mount(device.c_str(), mountpoint.c_str(), fstype, mountflags, 670 fs_mount_options.c_str()); 671 if (rc == 0) 672 return true; 673 674 PLOG(WARNING) << "Unable to mount destination device " << device 675 << " on " << mountpoint << " as " << fstype; 676 } 677 if (!type.empty()) { 678 LOG(ERROR) << "Unable to mount " << device << " with any supported type"; 679 } 680 return false; 681 } 682 683 bool UnmountFilesystem(const string& mountpoint) { 684 int num_retries = 1; 685 for (;; ++num_retries) { 686 if (umount(mountpoint.c_str()) == 0) 687 return true; 688 if (errno != EBUSY || num_retries >= kUnmountMaxNumOfRetries) 689 break; 690 usleep(kUnmountRetryIntervalInMicroseconds); 691 } 692 if (errno == EINVAL) { 693 LOG(INFO) << "Not a mountpoint: " << mountpoint; 694 return false; 695 } 696 PLOG(WARNING) << "Error unmounting " << mountpoint << " after " << num_retries 697 << " attempts. Lazy unmounting instead, error was"; 698 if (umount2(mountpoint.c_str(), MNT_DETACH) != 0) { 699 PLOG(ERROR) << "Lazy unmount failed"; 700 return false; 701 } 702 return true; 703 } 704 705 bool IsMountpoint(const std::string& mountpoint) { 706 struct stat stdir, stparent; 707 708 // Check whether the passed mountpoint is a directory and the /.. is in the 709 // same device or not. If mountpoint/.. is in a different device it means that 710 // there is a filesystem mounted there. If it is not, but they both point to 711 // the same inode it basically is the special case of /.. pointing to /. This 712 // test doesn't play well with bind mount but that's out of the scope of what 713 // we want to detect here. 714 if (lstat(mountpoint.c_str(), &stdir) != 0) { 715 PLOG(ERROR) << "Error stat'ing " << mountpoint; 716 return false; 717 } 718 if (!S_ISDIR(stdir.st_mode)) 719 return false; 720 721 base::FilePath parent(mountpoint); 722 parent = parent.Append(".."); 723 if (lstat(parent.value().c_str(), &stparent) != 0) { 724 PLOG(ERROR) << "Error stat'ing " << parent.value(); 725 return false; 726 } 727 return S_ISDIR(stparent.st_mode) && 728 (stparent.st_dev != stdir.st_dev || stparent.st_ino == stdir.st_ino); 729 } 730 731 // Tries to parse the header of an ELF file to obtain a human-readable 732 // description of it on the |output| string. 733 static bool GetFileFormatELF(const uint8_t* buffer, size_t size, 734 string* output) { 735 // 0x00: EI_MAG - ELF magic header, 4 bytes. 736 if (size < SELFMAG || memcmp(buffer, ELFMAG, SELFMAG) != 0) 737 return false; 738 *output = "ELF"; 739 740 // 0x04: EI_CLASS, 1 byte. 741 if (size < EI_CLASS + 1) 742 return true; 743 switch (buffer[EI_CLASS]) { 744 case ELFCLASS32: 745 *output += " 32-bit"; 746 break; 747 case ELFCLASS64: 748 *output += " 64-bit"; 749 break; 750 default: 751 *output += " ?-bit"; 752 } 753 754 // 0x05: EI_DATA, endianness, 1 byte. 755 if (size < EI_DATA + 1) 756 return true; 757 uint8_t ei_data = buffer[EI_DATA]; 758 switch (ei_data) { 759 case ELFDATA2LSB: 760 *output += " little-endian"; 761 break; 762 case ELFDATA2MSB: 763 *output += " big-endian"; 764 break; 765 default: 766 *output += " ?-endian"; 767 // Don't parse anything after the 0x10 offset if endianness is unknown. 768 return true; 769 } 770 771 const Elf32_Ehdr* hdr = reinterpret_cast<const Elf32_Ehdr*>(buffer); 772 // 0x12: e_machine, 2 byte endianness based on ei_data. The position (0x12) 773 // and size is the same for both 32 and 64 bits. 774 if (size < offsetof(Elf32_Ehdr, e_machine) + sizeof(hdr->e_machine)) 775 return true; 776 uint16_t e_machine; 777 // Fix endianess regardless of the host endianess. 778 if (ei_data == ELFDATA2LSB) 779 e_machine = le16toh(hdr->e_machine); 780 else 781 e_machine = be16toh(hdr->e_machine); 782 783 switch (e_machine) { 784 case EM_386: 785 *output += " x86"; 786 break; 787 case EM_MIPS: 788 *output += " mips"; 789 break; 790 case EM_ARM: 791 *output += " arm"; 792 break; 793 case EM_X86_64: 794 *output += " x86-64"; 795 break; 796 default: 797 *output += " unknown-arch"; 798 } 799 return true; 800 } 801 802 string GetFileFormat(const string& path) { 803 brillo::Blob buffer; 804 if (!ReadFileChunkAndAppend(path, 0, kGetFileFormatMaxHeaderSize, &buffer)) 805 return "File not found."; 806 807 string result; 808 if (GetFileFormatELF(buffer.data(), buffer.size(), &result)) 809 return result; 810 811 return "data"; 812 } 813 814 int FuzzInt(int value, unsigned int range) { 815 int min = value - range / 2; 816 int max = value + range - range / 2; 817 return base::RandInt(min, max); 818 } 819 820 string FormatSecs(unsigned secs) { 821 return FormatTimeDelta(TimeDelta::FromSeconds(secs)); 822 } 823 824 string FormatTimeDelta(TimeDelta delta) { 825 string str; 826 827 // Handle negative durations by prefixing with a minus. 828 if (delta.ToInternalValue() < 0) { 829 delta *= -1; 830 str = "-"; 831 } 832 833 // Canonicalize into days, hours, minutes, seconds and microseconds. 834 unsigned days = delta.InDays(); 835 delta -= TimeDelta::FromDays(days); 836 unsigned hours = delta.InHours(); 837 delta -= TimeDelta::FromHours(hours); 838 unsigned mins = delta.InMinutes(); 839 delta -= TimeDelta::FromMinutes(mins); 840 unsigned secs = delta.InSeconds(); 841 delta -= TimeDelta::FromSeconds(secs); 842 unsigned usecs = delta.InMicroseconds(); 843 844 if (days) 845 base::StringAppendF(&str, "%ud", days); 846 if (days || hours) 847 base::StringAppendF(&str, "%uh", hours); 848 if (days || hours || mins) 849 base::StringAppendF(&str, "%um", mins); 850 base::StringAppendF(&str, "%u", secs); 851 if (usecs) { 852 int width = 6; 853 while ((usecs / 10) * 10 == usecs) { 854 usecs /= 10; 855 width--; 856 } 857 base::StringAppendF(&str, ".%0*u", width, usecs); 858 } 859 base::StringAppendF(&str, "s"); 860 return str; 861 } 862 863 string ToString(const Time utc_time) { 864 Time::Exploded exp_time; 865 utc_time.UTCExplode(&exp_time); 866 return base::StringPrintf("%d/%d/%d %d:%02d:%02d GMT", 867 exp_time.month, 868 exp_time.day_of_month, 869 exp_time.year, 870 exp_time.hour, 871 exp_time.minute, 872 exp_time.second); 873 } 874 875 string ToString(bool b) { 876 return (b ? "true" : "false"); 877 } 878 879 string ToString(DownloadSource source) { 880 switch (source) { 881 case kDownloadSourceHttpsServer: return "HttpsServer"; 882 case kDownloadSourceHttpServer: return "HttpServer"; 883 case kDownloadSourceHttpPeer: return "HttpPeer"; 884 case kNumDownloadSources: return "Unknown"; 885 // Don't add a default case to let the compiler warn about newly added 886 // download sources which should be added here. 887 } 888 889 return "Unknown"; 890 } 891 892 string ToString(PayloadType payload_type) { 893 switch (payload_type) { 894 case kPayloadTypeDelta: return "Delta"; 895 case kPayloadTypeFull: return "Full"; 896 case kPayloadTypeForcedFull: return "ForcedFull"; 897 case kNumPayloadTypes: return "Unknown"; 898 // Don't add a default case to let the compiler warn about newly added 899 // payload types which should be added here. 900 } 901 902 return "Unknown"; 903 } 904 905 ErrorCode GetBaseErrorCode(ErrorCode code) { 906 // Ignore the higher order bits in the code by applying the mask as 907 // we want the enumerations to be in the small contiguous range 908 // with values less than ErrorCode::kUmaReportedMax. 909 ErrorCode base_code = static_cast<ErrorCode>( 910 static_cast<int>(code) & ~static_cast<int>(ErrorCode::kSpecialFlags)); 911 912 // Make additional adjustments required for UMA and error classification. 913 // TODO(jaysri): Move this logic to UeErrorCode.cc when we fix 914 // chromium-os:34369. 915 if (base_code >= ErrorCode::kOmahaRequestHTTPResponseBase) { 916 // Since we want to keep the enums to a small value, aggregate all HTTP 917 // errors into this one bucket for UMA and error classification purposes. 918 LOG(INFO) << "Converting error code " << base_code 919 << " to ErrorCode::kOmahaErrorInHTTPResponse"; 920 base_code = ErrorCode::kOmahaErrorInHTTPResponse; 921 } 922 923 return base_code; 924 } 925 926 Time TimeFromStructTimespec(struct timespec *ts) { 927 int64_t us = static_cast<int64_t>(ts->tv_sec) * Time::kMicrosecondsPerSecond + 928 static_cast<int64_t>(ts->tv_nsec) / Time::kNanosecondsPerMicrosecond; 929 return Time::UnixEpoch() + TimeDelta::FromMicroseconds(us); 930 } 931 932 string StringVectorToString(const vector<string> &vec_str) { 933 string str = "["; 934 for (vector<string>::const_iterator i = vec_str.begin(); 935 i != vec_str.end(); ++i) { 936 if (i != vec_str.begin()) 937 str += ", "; 938 str += '"'; 939 str += *i; 940 str += '"'; 941 } 942 str += "]"; 943 return str; 944 } 945 946 // The P2P file id should be the same for devices running new version and old 947 // version so that they can share it with each other. The hash in the response 948 // was base64 encoded, but now that we switched to use "hash_sha256" field which 949 // is hex encoded, we have to convert them back to base64 for P2P. However, the 950 // base64 encoded hash was base64 encoded here again historically for some 951 // reason, so we keep the same behavior here. 952 string CalculateP2PFileId(const brillo::Blob& payload_hash, 953 size_t payload_size) { 954 string encoded_hash = brillo::data_encoding::Base64Encode( 955 brillo::data_encoding::Base64Encode(payload_hash)); 956 return base::StringPrintf("cros_update_size_%" PRIuS "_hash_%s", 957 payload_size, 958 encoded_hash.c_str()); 959 } 960 961 bool DecodeAndStoreBase64String(const string& base64_encoded, 962 base::FilePath *out_path) { 963 brillo::Blob contents; 964 965 out_path->clear(); 966 967 if (base64_encoded.size() == 0) { 968 LOG(ERROR) << "Can't decode empty string."; 969 return false; 970 } 971 972 if (!brillo::data_encoding::Base64Decode(base64_encoded, &contents) || 973 contents.size() == 0) { 974 LOG(ERROR) << "Error decoding base64."; 975 return false; 976 } 977 978 FILE *file = base::CreateAndOpenTemporaryFile(out_path); 979 if (file == nullptr) { 980 LOG(ERROR) << "Error creating temporary file."; 981 return false; 982 } 983 984 if (fwrite(contents.data(), 1, contents.size(), file) != contents.size()) { 985 PLOG(ERROR) << "Error writing to temporary file."; 986 if (fclose(file) != 0) 987 PLOG(ERROR) << "Error closing temporary file."; 988 if (unlink(out_path->value().c_str()) != 0) 989 PLOG(ERROR) << "Error unlinking temporary file."; 990 out_path->clear(); 991 return false; 992 } 993 994 if (fclose(file) != 0) { 995 PLOG(ERROR) << "Error closing temporary file."; 996 out_path->clear(); 997 return false; 998 } 999 1000 return true; 1001 } 1002 1003 bool ConvertToOmahaInstallDate(Time time, int *out_num_days) { 1004 time_t unix_time = time.ToTimeT(); 1005 // Output of: date +"%s" --date="Jan 1, 2007 0:00 PST". 1006 const time_t kOmahaEpoch = 1167638400; 1007 const int64_t kNumSecondsPerWeek = 7*24*3600; 1008 const int64_t kNumDaysPerWeek = 7; 1009 1010 time_t omaha_time = unix_time - kOmahaEpoch; 1011 1012 if (omaha_time < 0) 1013 return false; 1014 1015 // Note, as per the comment in utils.h we are deliberately not 1016 // handling DST correctly. 1017 1018 int64_t num_weeks_since_omaha_epoch = omaha_time / kNumSecondsPerWeek; 1019 *out_num_days = num_weeks_since_omaha_epoch * kNumDaysPerWeek; 1020 1021 return true; 1022 } 1023 1024 bool GetMinorVersion(const brillo::KeyValueStore& store, 1025 uint32_t* minor_version) { 1026 string result; 1027 if (store.GetString("PAYLOAD_MINOR_VERSION", &result)) { 1028 if (!base::StringToUint(result, minor_version)) { 1029 LOG(ERROR) << "StringToUint failed when parsing delta minor version."; 1030 return false; 1031 } 1032 return true; 1033 } 1034 return false; 1035 } 1036 1037 bool ReadExtents(const string& path, const vector<Extent>& extents, 1038 brillo::Blob* out_data, ssize_t out_data_size, 1039 size_t block_size) { 1040 brillo::Blob data(out_data_size); 1041 ssize_t bytes_read = 0; 1042 int fd = open(path.c_str(), O_RDONLY); 1043 TEST_AND_RETURN_FALSE_ERRNO(fd >= 0); 1044 ScopedFdCloser fd_closer(&fd); 1045 1046 for (const Extent& extent : extents) { 1047 ssize_t bytes_read_this_iteration = 0; 1048 ssize_t bytes = extent.num_blocks() * block_size; 1049 TEST_AND_RETURN_FALSE(bytes_read + bytes <= out_data_size); 1050 TEST_AND_RETURN_FALSE(utils::PReadAll(fd, 1051 &data[bytes_read], 1052 bytes, 1053 extent.start_block() * block_size, 1054 &bytes_read_this_iteration)); 1055 TEST_AND_RETURN_FALSE(bytes_read_this_iteration == bytes); 1056 bytes_read += bytes_read_this_iteration; 1057 } 1058 TEST_AND_RETURN_FALSE(out_data_size == bytes_read); 1059 *out_data = data; 1060 return true; 1061 } 1062 1063 bool GetBootId(string* boot_id) { 1064 TEST_AND_RETURN_FALSE( 1065 base::ReadFileToString(base::FilePath(kBootIdPath), boot_id)); 1066 base::TrimWhitespaceASCII(*boot_id, base::TRIM_TRAILING, boot_id); 1067 return true; 1068 } 1069 1070 } // namespace utils 1071 1072 } // namespace chromeos_update_engine 1073