167d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui/*
267d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui * Copyright (C) 2015 The Android Open Source Project
367d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui *
467d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui * Licensed under the Apache License, Version 2.0 (the "License");
567d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui * you may not use this file except in compliance with the License.
667d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui * You may obtain a copy of the License at
767d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui *
867d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui *      http://www.apache.org/licenses/LICENSE-2.0
967d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui *
1067d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui * Unless required by applicable law or agreed to in writing, software
1167d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui * distributed under the License is distributed on an "AS IS" BASIS,
1267d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1367d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui * See the License for the specific language governing permissions and
1467d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui * limitations under the License.
1567d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui */
1667d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui
1767d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui#include "utils.h"
1867d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui
197d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui#include <dirent.h>
20323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui#include <errno.h>
21b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui#include <fcntl.h>
22b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui#include <inttypes.h>
2367d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui#include <stdarg.h>
2467d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui#include <stdio.h>
256afc7e17d39ab294bdf625076777443a6b4c8e18Yabin Cui#include <sys/stat.h>
26323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui#include <unistd.h>
27323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui
28cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui#include <algorithm>
298f680f60dc800bec880c5c35bfbc1ac36165e1f3Yabin Cui#include <map>
30cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui#include <string>
31cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui
32b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui#include <android-base/file.h>
3366dd09e8e2407082ce93bf0784de641298131912Elliott Hughes#include <android-base/logging.h>
3467d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui
3505400539d15c50a52a388daba2e831b86824cc8eYabin Cui#include <7zCrc.h>
3605400539d15c50a52a388daba2e831b86824cc8eYabin Cui#include <Xz.h>
3705400539d15c50a52a388daba2e831b86824cc8eYabin Cui#include <XzCrc64.h>
3805400539d15c50a52a388daba2e831b86824cc8eYabin Cui
39cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cuivoid OneTimeFreeAllocator::Clear() {
40cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui  for (auto& p : v_) {
41cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui    delete[] p;
42cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui  }
43cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui  v_.clear();
44cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui  cur_ = nullptr;
45cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui  end_ = nullptr;
46cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui}
47cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui
48cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cuiconst char* OneTimeFreeAllocator::AllocateString(const std::string& s) {
49cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui  size_t size = s.size() + 1;
50cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui  if (cur_ + size > end_) {
51cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui    size_t alloc_size = std::max(size, unit_size_);
52cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui    char* p = new char[alloc_size];
53cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui    v_.push_back(p);
54cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui    cur_ = p;
55cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui    end_ = p + alloc_size;
56cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui  }
57cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui  strcpy(cur_, s.c_str());
58cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui  const char* result = cur_;
59cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui  cur_ += size;
60cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui  return result;
61cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui}
62cc2e59e2478d330c89eaceda0dcc1f05ee32fbf8Yabin Cui
63be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui
64be7ec66eaa4f995bd9068637f7c7d5718173922cYabin CuiFileHelper FileHelper::OpenReadOnly(const std::string& filename) {
65be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui    int fd = TEMP_FAILURE_RETRY(open(filename.c_str(), O_RDONLY | O_BINARY));
66be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui    return FileHelper(fd);
67b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui}
68b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui
69be7ec66eaa4f995bd9068637f7c7d5718173922cYabin CuiFileHelper FileHelper::OpenWriteOnly(const std::string& filename) {
70be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui    int fd = TEMP_FAILURE_RETRY(open(filename.c_str(), O_WRONLY | O_BINARY | O_CREAT, 0644));
71be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui    return FileHelper(fd);
72b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui}
73b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui
74b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin CuiFileHelper::~FileHelper() {
75b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  if (fd_ != -1) {
76b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui    close(fd_);
77b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  }
78b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui}
79b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui
80be7ec66eaa4f995bd9068637f7c7d5718173922cYabin CuiArchiveHelper::ArchiveHelper(int fd, const std::string& debug_filename) : valid_(false) {
81be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui  int rc = OpenArchiveFd(fd, "", &handle_, false);
82be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui  if (rc == 0) {
83be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui    valid_ = true;
84be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui  } else {
85be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui    LOG(ERROR) << "Failed to open archive " << debug_filename << ": " << ErrorCodeString(rc);
86be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui  }
87be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui}
88be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui
89be7ec66eaa4f995bd9068637f7c7d5718173922cYabin CuiArchiveHelper::~ArchiveHelper() {
90be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui  if (valid_) {
91be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui    CloseArchive(handle_);
92be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui  }
93be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui}
94be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui
9567d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cuivoid PrintIndented(size_t indent, const char* fmt, ...) {
9667d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui  va_list ap;
9767d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui  va_start(ap, fmt);
989759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  printf("%*s", static_cast<int>(indent * 2), "");
9967d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui  vprintf(fmt, ap);
10067d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui  va_end(ap);
10167d3abd7b26a741347b33402ad32f5c6735ca0bdYabin Cui}
102323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui
103767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cuivoid FprintIndented(FILE* fp, size_t indent, const char* fmt, ...) {
104767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui  va_list ap;
105767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui  va_start(ap, fmt);
106767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui  fprintf(fp, "%*s", static_cast<int>(indent * 2), "");
107767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui  vfprintf(fp, fmt, ap);
108767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui  va_end(ap);
109767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui}
110767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui
1119759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuibool IsPowerOfTwo(uint64_t value) {
1129759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  return (value != 0 && ((value & (value - 1)) == 0));
1139759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui}
1149759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
115078658638c01c035ebcb98a557628101566a1d57Yabin Cuistd::vector<std::string> GetEntriesInDir(const std::string& dirpath) {
116078658638c01c035ebcb98a557628101566a1d57Yabin Cui  std::vector<std::string> result;
1177d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui  DIR* dir = opendir(dirpath.c_str());
1187d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui  if (dir == nullptr) {
1197d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui    PLOG(DEBUG) << "can't open dir " << dirpath;
120078658638c01c035ebcb98a557628101566a1d57Yabin Cui    return result;
1217d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui  }
1227d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui  dirent* entry;
1237d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui  while ((entry = readdir(dir)) != nullptr) {
1247d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui    if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
1257d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui      continue;
1267d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui    }
127078658638c01c035ebcb98a557628101566a1d57Yabin Cui    result.push_back(entry->d_name);
1287d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui  }
1297d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui  closedir(dir);
130078658638c01c035ebcb98a557628101566a1d57Yabin Cui  return result;
131078658638c01c035ebcb98a557628101566a1d57Yabin Cui}
132078658638c01c035ebcb98a557628101566a1d57Yabin Cui
133078658638c01c035ebcb98a557628101566a1d57Yabin Cuistd::vector<std::string> GetSubDirs(const std::string& dirpath) {
134078658638c01c035ebcb98a557628101566a1d57Yabin Cui  std::vector<std::string> entries = GetEntriesInDir(dirpath);
135078658638c01c035ebcb98a557628101566a1d57Yabin Cui  std::vector<std::string> result;
136078658638c01c035ebcb98a557628101566a1d57Yabin Cui  for (size_t i = 0; i < entries.size(); ++i) {
137078658638c01c035ebcb98a557628101566a1d57Yabin Cui    if (IsDir(dirpath + "/" + entries[i])) {
138078658638c01c035ebcb98a557628101566a1d57Yabin Cui      result.push_back(std::move(entries[i]));
139078658638c01c035ebcb98a557628101566a1d57Yabin Cui    }
140078658638c01c035ebcb98a557628101566a1d57Yabin Cui  }
141078658638c01c035ebcb98a557628101566a1d57Yabin Cui  return result;
1427d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui}
1436afc7e17d39ab294bdf625076777443a6b4c8e18Yabin Cui
144b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cuibool IsDir(const std::string& dirpath) {
145b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui  struct stat st;
146b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui  if (stat(dirpath.c_str(), &st) == 0) {
147b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui    if (S_ISDIR(st.st_mode)) {
148b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui      return true;
149b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui    }
150b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui  }
151b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui  return false;
152b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui}
153b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui
154797116bfb9ad10d858086680c7465d65c399ef6eYabin Cuibool IsRegularFile(const std::string& filename) {
155797116bfb9ad10d858086680c7465d65c399ef6eYabin Cui  struct stat st;
156797116bfb9ad10d858086680c7465d65c399ef6eYabin Cui  if (stat(filename.c_str(), &st) == 0) {
157797116bfb9ad10d858086680c7465d65c399ef6eYabin Cui    if (S_ISREG(st.st_mode)) {
158797116bfb9ad10d858086680c7465d65c399ef6eYabin Cui      return true;
159797116bfb9ad10d858086680c7465d65c399ef6eYabin Cui    }
160797116bfb9ad10d858086680c7465d65c399ef6eYabin Cui  }
161797116bfb9ad10d858086680c7465d65c399ef6eYabin Cui  return false;
162797116bfb9ad10d858086680c7465d65c399ef6eYabin Cui}
163b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui
164b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cuiuint64_t GetFileSize(const std::string& filename) {
165b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  struct stat st;
166b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  if (stat(filename.c_str(), &st) == 0) {
167b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui    return static_cast<uint64_t>(st.st_size);
168b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  }
169b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  return 0;
170b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui}
171be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui
172be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cuibool MkdirWithParents(const std::string& path) {
173be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui  size_t prev_end = 0;
174be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui  while (prev_end < path.size()) {
175be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui    size_t next_end = path.find('/', prev_end + 1);
176be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui    if (next_end == std::string::npos) {
177be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui      break;
178be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui    }
179be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui    std::string dir_path = path.substr(0, next_end);
180be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui    if (!IsDir(dir_path)) {
181be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui#if defined(_WIN32)
182be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui      int ret = mkdir(dir_path.c_str());
183be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui#else
184be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui      int ret = mkdir(dir_path.c_str(), 0755);
185be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui#endif
186be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui      if (ret != 0) {
187be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui        PLOG(ERROR) << "failed to create dir " << dir_path;
188be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui        return false;
189be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui      }
190be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui    }
191be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui    prev_end = next_end;
192be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui  }
193be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui  return true;
194be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui}
19505400539d15c50a52a388daba2e831b86824cc8eYabin Cui
19605400539d15c50a52a388daba2e831b86824cc8eYabin Cuistatic void* xz_alloc(void*, size_t size) {
19705400539d15c50a52a388daba2e831b86824cc8eYabin Cui  return malloc(size);
19805400539d15c50a52a388daba2e831b86824cc8eYabin Cui}
19905400539d15c50a52a388daba2e831b86824cc8eYabin Cui
20005400539d15c50a52a388daba2e831b86824cc8eYabin Cuistatic void xz_free(void*, void* address) {
20105400539d15c50a52a388daba2e831b86824cc8eYabin Cui  free(address);
20205400539d15c50a52a388daba2e831b86824cc8eYabin Cui}
20305400539d15c50a52a388daba2e831b86824cc8eYabin Cui
20405400539d15c50a52a388daba2e831b86824cc8eYabin Cuibool XzDecompress(const std::string& compressed_data, std::string* decompressed_data) {
20505400539d15c50a52a388daba2e831b86824cc8eYabin Cui  ISzAlloc alloc;
20605400539d15c50a52a388daba2e831b86824cc8eYabin Cui  CXzUnpacker state;
20705400539d15c50a52a388daba2e831b86824cc8eYabin Cui  alloc.Alloc = xz_alloc;
20805400539d15c50a52a388daba2e831b86824cc8eYabin Cui  alloc.Free = xz_free;
20905400539d15c50a52a388daba2e831b86824cc8eYabin Cui  XzUnpacker_Construct(&state, &alloc);
21005400539d15c50a52a388daba2e831b86824cc8eYabin Cui  CrcGenerateTable();
21105400539d15c50a52a388daba2e831b86824cc8eYabin Cui  Crc64GenerateTable();
21205400539d15c50a52a388daba2e831b86824cc8eYabin Cui  size_t src_offset = 0;
21305400539d15c50a52a388daba2e831b86824cc8eYabin Cui  size_t dst_offset = 0;
21405400539d15c50a52a388daba2e831b86824cc8eYabin Cui  std::string dst(compressed_data.size(), ' ');
21505400539d15c50a52a388daba2e831b86824cc8eYabin Cui
21605400539d15c50a52a388daba2e831b86824cc8eYabin Cui  ECoderStatus status = CODER_STATUS_NOT_FINISHED;
21705400539d15c50a52a388daba2e831b86824cc8eYabin Cui  while (status == CODER_STATUS_NOT_FINISHED) {
21805400539d15c50a52a388daba2e831b86824cc8eYabin Cui    dst.resize(dst.size() * 2);
21905400539d15c50a52a388daba2e831b86824cc8eYabin Cui    size_t src_remaining = compressed_data.size() - src_offset;
22005400539d15c50a52a388daba2e831b86824cc8eYabin Cui    size_t dst_remaining = dst.size() - dst_offset;
22105400539d15c50a52a388daba2e831b86824cc8eYabin Cui    int res = XzUnpacker_Code(&state, reinterpret_cast<Byte*>(&dst[dst_offset]), &dst_remaining,
22205400539d15c50a52a388daba2e831b86824cc8eYabin Cui                              reinterpret_cast<const Byte*>(&compressed_data[src_offset]),
22305400539d15c50a52a388daba2e831b86824cc8eYabin Cui                              &src_remaining, CODER_FINISH_ANY, &status);
22405400539d15c50a52a388daba2e831b86824cc8eYabin Cui    if (res != SZ_OK) {
22505400539d15c50a52a388daba2e831b86824cc8eYabin Cui      LOG(ERROR) << "LZMA decompression failed with error " << res;
22605400539d15c50a52a388daba2e831b86824cc8eYabin Cui      XzUnpacker_Free(&state);
22705400539d15c50a52a388daba2e831b86824cc8eYabin Cui      return false;
22805400539d15c50a52a388daba2e831b86824cc8eYabin Cui    }
22905400539d15c50a52a388daba2e831b86824cc8eYabin Cui    src_offset += src_remaining;
23005400539d15c50a52a388daba2e831b86824cc8eYabin Cui    dst_offset += dst_remaining;
23105400539d15c50a52a388daba2e831b86824cc8eYabin Cui  }
23205400539d15c50a52a388daba2e831b86824cc8eYabin Cui  XzUnpacker_Free(&state);
23305400539d15c50a52a388daba2e831b86824cc8eYabin Cui  if (!XzUnpacker_IsStreamWasFinished(&state)) {
23405400539d15c50a52a388daba2e831b86824cc8eYabin Cui    LOG(ERROR) << "LZMA decompresstion failed due to incomplete stream";
23505400539d15c50a52a388daba2e831b86824cc8eYabin Cui    return false;
23605400539d15c50a52a388daba2e831b86824cc8eYabin Cui  }
23705400539d15c50a52a388daba2e831b86824cc8eYabin Cui  dst.resize(dst_offset);
23805400539d15c50a52a388daba2e831b86824cc8eYabin Cui  *decompressed_data = std::move(dst);
23905400539d15c50a52a388daba2e831b86824cc8eYabin Cui  return true;
24005400539d15c50a52a388daba2e831b86824cc8eYabin Cui}
2418f680f60dc800bec880c5c35bfbc1ac36165e1f3Yabin Cui
2428f680f60dc800bec880c5c35bfbc1ac36165e1f3Yabin Cuibool GetLogSeverity(const std::string& name, android::base::LogSeverity* severity) {
2438f680f60dc800bec880c5c35bfbc1ac36165e1f3Yabin Cui  static std::map<std::string, android::base::LogSeverity> log_severity_map = {
2448f680f60dc800bec880c5c35bfbc1ac36165e1f3Yabin Cui      {"verbose", android::base::VERBOSE},
2458f680f60dc800bec880c5c35bfbc1ac36165e1f3Yabin Cui      {"debug", android::base::DEBUG},
246767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui      {"info", android::base::INFO},
2478f680f60dc800bec880c5c35bfbc1ac36165e1f3Yabin Cui      {"warning", android::base::WARNING},
2488f680f60dc800bec880c5c35bfbc1ac36165e1f3Yabin Cui      {"error", android::base::ERROR},
2498f680f60dc800bec880c5c35bfbc1ac36165e1f3Yabin Cui      {"fatal", android::base::FATAL},
2508f680f60dc800bec880c5c35bfbc1ac36165e1f3Yabin Cui  };
2518f680f60dc800bec880c5c35bfbc1ac36165e1f3Yabin Cui  auto it = log_severity_map.find(name);
2528f680f60dc800bec880c5c35bfbc1ac36165e1f3Yabin Cui  if (it != log_severity_map.end()) {
2538f680f60dc800bec880c5c35bfbc1ac36165e1f3Yabin Cui    *severity = it->second;
2548f680f60dc800bec880c5c35bfbc1ac36165e1f3Yabin Cui    return true;
2558f680f60dc800bec880c5c35bfbc1ac36165e1f3Yabin Cui  }
2568f680f60dc800bec880c5c35bfbc1ac36165e1f3Yabin Cui  return false;
2578f680f60dc800bec880c5c35bfbc1ac36165e1f3Yabin Cui}
2585633586f0efc54dbaecad3deeb8568786317832dYabin Cui
2595633586f0efc54dbaecad3deeb8568786317832dYabin Cuibool IsRoot() {
2605633586f0efc54dbaecad3deeb8568786317832dYabin Cui  static int is_root = -1;
2615633586f0efc54dbaecad3deeb8568786317832dYabin Cui  if (is_root == -1) {
2625633586f0efc54dbaecad3deeb8568786317832dYabin Cui#if defined(__linux__)
2635633586f0efc54dbaecad3deeb8568786317832dYabin Cui    is_root = (getuid() == 0) ? 1 : 0;
2645633586f0efc54dbaecad3deeb8568786317832dYabin Cui#else
2655633586f0efc54dbaecad3deeb8568786317832dYabin Cui    is_root = 0;
2665633586f0efc54dbaecad3deeb8568786317832dYabin Cui#endif
2675633586f0efc54dbaecad3deeb8568786317832dYabin Cui  }
2685633586f0efc54dbaecad3deeb8568786317832dYabin Cui  return is_root == 1;
2695633586f0efc54dbaecad3deeb8568786317832dYabin Cui}
270b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui
271b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cuibool ProcessKernelSymbols(std::string& symbol_data,
2723e4c5950f3aafb0bf66544468d98ee3ec26b705cYabin Cui                          const std::function<bool(const KernelSymbol&)>& callback) {
273b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  char* p = &symbol_data[0];
274b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  char* data_end = p + symbol_data.size();
275b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  while (p < data_end) {
276b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    char* line_end = strchr(p, '\n');
277b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    if (line_end != nullptr) {
278b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      *line_end = '\0';
279b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    }
280b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    size_t line_size = (line_end != nullptr) ? (line_end - p) : (data_end - p);
281b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    // Parse line like: ffffffffa005c4e4 d __warned.41698       [libsas]
282b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    char name[line_size];
283b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    char module[line_size];
284b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    strcpy(module, "");
285b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui
286b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    KernelSymbol symbol;
287b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    int ret = sscanf(p, "%" PRIx64 " %c %s%s", &symbol.addr, &symbol.type, name, module);
288b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    if (line_end != nullptr) {
289b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      *line_end = '\n';
290b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      p = line_end + 1;
291b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    } else {
292b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      p = data_end;
293b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    }
294b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    if (ret >= 3) {
295b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      symbol.name = name;
296b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      size_t module_len = strlen(module);
297b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      if (module_len > 2 && module[0] == '[' && module[module_len - 1] == ']') {
298b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui        module[module_len - 1] = '\0';
299b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui        symbol.module = &module[1];
300b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      } else {
301b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui        symbol.module = nullptr;
302b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      }
303b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui
304b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      if (callback(symbol)) {
305b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui        return true;
306b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      }
307b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    }
308b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  }
309b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  return false;
310b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui}
3114f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui
3124f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cuisize_t GetPageSize() {
3134f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui#if defined(__linux__)
3144f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui  return sysconf(_SC_PAGE_SIZE);
3154f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui#else
3164f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui  return 4096;
3174f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui#endif
3184f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui}
3194f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui
3204f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cuiuint64_t ConvertBytesToValue(const char* bytes, uint32_t size) {
321f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui  if (size > 8) {
322f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui    LOG(FATAL) << "unexpected size " << size << " in ConvertBytesToValue";
3234f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui  }
324f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui  uint64_t result = 0;
325f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui  int shift = 0;
326f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui  for (uint32_t i = 0; i < size; ++i) {
327f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui    uint64_t tmp = static_cast<unsigned char>(bytes[i]);
328f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui    result |= tmp << shift;
329f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui    shift += 8;
330f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui  }
331f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui  return result;
3324f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui}
3333e4c5950f3aafb0bf66544468d98ee3ec26b705cYabin Cui
3343e4c5950f3aafb0bf66544468d98ee3ec26b705cYabin Cuitimeval SecondToTimeval(double time_in_sec) {
3353e4c5950f3aafb0bf66544468d98ee3ec26b705cYabin Cui  timeval tv;
3363e4c5950f3aafb0bf66544468d98ee3ec26b705cYabin Cui  tv.tv_sec = static_cast<time_t>(time_in_sec);
3373e4c5950f3aafb0bf66544468d98ee3ec26b705cYabin Cui  tv.tv_usec = static_cast<int>((time_in_sec - tv.tv_sec) * 1000000);
3383e4c5950f3aafb0bf66544468d98ee3ec26b705cYabin Cui  return tv;
3393e4c5950f3aafb0bf66544468d98ee3ec26b705cYabin Cui}
340