Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe7eecff authored by Tao Bao's avatar Tao Bao Committed by Gerrit Code Review
Browse files

Merge "Move sysMapFile and sysReleaseMap into MemMapping class."

parents ba365180 b656a154
Loading
Loading
Loading
Loading
+1 −5
Original line number Diff line number Diff line
@@ -569,7 +569,7 @@ static int really_install_package(const std::string& path, bool* wipe_cache, boo
  }

  MemMapping map;
  if (sysMapFile(path.c_str(), &map) != 0) {
  if (!map.MapFile(path)) {
    LOG(ERROR) << "failed to map file";
    return INSTALL_CORRUPT;
  }
@@ -577,7 +577,6 @@ static int really_install_package(const std::string& path, bool* wipe_cache, boo
  // Verify package.
  if (!verify_package(map.addr, map.length)) {
    log_buffer->push_back(android::base::StringPrintf("error: %d", kZipVerificationFailure));
    sysReleaseMap(&map);
    return INSTALL_CORRUPT;
  }

@@ -588,7 +587,6 @@ static int really_install_package(const std::string& path, bool* wipe_cache, boo
    LOG(ERROR) << "Can't open " << path << " : " << ErrorCodeString(err);
    log_buffer->push_back(android::base::StringPrintf("error: %d", kZipOpenFailure));

    sysReleaseMap(&map);
    CloseArchive(zip);
    return INSTALL_CORRUPT;
  }
@@ -596,7 +594,6 @@ static int really_install_package(const std::string& path, bool* wipe_cache, boo
  // Additionally verify the compatibility of the package.
  if (!verify_package_compatibility(zip)) {
    log_buffer->push_back(android::base::StringPrintf("error: %d", kPackageCompatibilityFailure));
    sysReleaseMap(&map);
    CloseArchive(zip);
    return INSTALL_CORRUPT;
  }
@@ -611,7 +608,6 @@ static int really_install_package(const std::string& path, bool* wipe_cache, boo
  ui->SetEnableReboot(true);
  ui->Print("\n");

  sysReleaseMap(&map);
  CloseArchive(zip);
  return result;
}
+58 −68
Original line number Diff line number Diff line
@@ -16,14 +16,12 @@

#include "SysUtil.h"

#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdint.h>  // SIZE_MAX
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <algorithm>
#include <string>
#include <vector>

@@ -32,9 +30,7 @@
#include <android-base/strings.h>
#include <android-base/unique_fd.h>

static bool sysMapFD(int fd, MemMapping* pMap) {
  CHECK(pMap != nullptr);

bool MemMapping::MapFD(int fd) {
  struct stat sb;
  if (fstat(fd, &sb) == -1) {
    PLOG(ERROR) << "fstat(" << fd << ") failed";
@@ -47,9 +43,10 @@ static bool sysMapFD(int fd, MemMapping* pMap) {
    return false;
  }

  pMap->addr = static_cast<unsigned char*>(memPtr);
  pMap->length = sb.st_size;
  pMap->ranges.push_back({ memPtr, static_cast<size_t>(sb.st_size) });
  addr = static_cast<unsigned char*>(memPtr);
  length = sb.st_size;
  ranges_.clear();
  ranges_.emplace_back(MappedRange{ memPtr, static_cast<size_t>(sb.st_size) });

  return true;
}
@@ -63,34 +60,32 @@ static bool sysMapFD(int fd, MemMapping* pMap) {
//   2100 2102                                           # ... block range 1
//   30 33                                               # ... block range 2
//
// Each block range represents a half-open interval; the line "30 33"
// reprents the blocks [30, 31, 32].
static int sysMapBlockFile(const char* filename, MemMapping* pMap) {
  CHECK(pMap != nullptr);

// Each block range represents a half-open interval; the line "30 33" reprents the blocks
// [30, 31, 32].
bool MemMapping::MapBlockFile(const std::string& filename) {
  std::string content;
  if (!android::base::ReadFileToString(filename, &content)) {
    PLOG(ERROR) << "Failed to read " << filename;
    return -1;
    return false;
  }

  std::vector<std::string> lines = android::base::Split(android::base::Trim(content), "\n");
  if (lines.size() < 4) {
    LOG(ERROR) << "Block map file is too short: " << lines.size();
    return -1;
    return false;
  }

  size_t size;
  unsigned int blksize;
  if (sscanf(lines[1].c_str(), "%zu %u", &size, &blksize) != 2) {
  size_t blksize;
  if (sscanf(lines[1].c_str(), "%zu %zu", &size, &blksize) != 2) {
    LOG(ERROR) << "Failed to parse file size and block size: " << lines[1];
    return -1;
    return false;
  }

  size_t range_count;
  if (sscanf(lines[2].c_str(), "%zu", &range_count) != 1) {
    LOG(ERROR) << "Failed to parse block map header: " << lines[2];
    return -1;
    return false;
  }

  size_t blocks;
@@ -101,14 +96,14 @@ static int sysMapBlockFile(const char* filename, MemMapping* pMap) {
      lines.size() != 3 + range_count) {
    LOG(ERROR) << "Invalid data in block map file: size " << size << ", blksize " << blksize
               << ", range_count " << range_count << ", lines " << lines.size();
    return -1;
    return false;
  }

  // Reserve enough contiguous address space for the whole file.
  void* reserve = mmap64(nullptr, blocks * blksize, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
  if (reserve == MAP_FAILED) {
    PLOG(ERROR) << "failed to reserve address space";
    return -1;
    return false;
  }

  const std::string& block_dev = lines[0];
@@ -116,10 +111,10 @@ static int sysMapBlockFile(const char* filename, MemMapping* pMap) {
  if (fd == -1) {
    PLOG(ERROR) << "failed to open block device " << block_dev;
    munmap(reserve, blocks * blksize);
    return -1;
    return false;
  }

  pMap->ranges.resize(range_count);
  ranges_.clear();

  unsigned char* next = static_cast<unsigned char*>(reserve);
  size_t remaining_size = blocks * blksize;
@@ -129,84 +124,79 @@ static int sysMapBlockFile(const char* filename, MemMapping* pMap) {

    size_t start, end;
    if (sscanf(line.c_str(), "%zu %zu\n", &start, &end) != 2) {
      LOG(ERROR) << "failed to parse range " << i << " in block map: " << line;
      LOG(ERROR) << "failed to parse range " << i << ": " << line;
      success = false;
      break;
    }
    size_t length = (end - start) * blksize;
    if (end <= start || (end - start) > SIZE_MAX / blksize || length > remaining_size) {
      LOG(ERROR) << "unexpected range in block map: " << start << " " << end;
    size_t range_size = (end - start) * blksize;
    if (end <= start || (end - start) > SIZE_MAX / blksize || range_size > remaining_size) {
      LOG(ERROR) << "Invalid range: " << start << " " << end;
      success = false;
      break;
    }

    void* addr = mmap64(next, length, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd,
    void* range_start = mmap64(next, range_size, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd,
                               static_cast<off64_t>(start) * blksize);
    if (addr == MAP_FAILED) {
      PLOG(ERROR) << "failed to map block " << i;
    if (range_start == MAP_FAILED) {
      PLOG(ERROR) << "failed to map range " << i << ": " << line;
      success = false;
      break;
    }
    pMap->ranges[i].addr = addr;
    pMap->ranges[i].length = length;
    ranges_.emplace_back(MappedRange{ range_start, range_size });

    next += length;
    remaining_size -= length;
    next += range_size;
    remaining_size -= range_size;
  }
  if (success && remaining_size != 0) {
    LOG(ERROR) << "ranges in block map are invalid: remaining_size = " << remaining_size;
    LOG(ERROR) << "Invalid ranges: remaining_size " << remaining_size;
    success = false;
  }
  if (!success) {
    munmap(reserve, blocks * blksize);
    return -1;
    return false;
  }

  pMap->addr = static_cast<unsigned char*>(reserve);
  pMap->length = size;
  addr = static_cast<unsigned char*>(reserve);
  length = size;

  LOG(INFO) << "mmapped " << range_count << " ranges";

  return 0;
  return true;
}

int sysMapFile(const char* fn, MemMapping* pMap) {
  if (fn == nullptr || pMap == nullptr) {
    LOG(ERROR) << "Invalid argument(s)";
    return -1;
bool MemMapping::MapFile(const std::string& fn) {
  if (fn.empty()) {
    LOG(ERROR) << "Empty filename";
    return false;
  }

  *pMap = {};

  if (fn[0] == '@') {
    if (sysMapBlockFile(fn + 1, pMap) != 0) {
    // Block map file "@/cache/recovery/block.map".
    if (!MapBlockFile(fn.substr(1))) {
      LOG(ERROR) << "Map of '" << fn << "' failed";
      return -1;
      return false;
    }
  } else {
    // This is a regular file.
    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(fn, O_RDONLY)));
    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(fn.c_str(), O_RDONLY)));
    if (fd == -1) {
      PLOG(ERROR) << "Unable to open '" << fn << "'";
      return -1;
      return false;
    }

    if (!sysMapFD(fd, pMap)) {
    if (!MapFD(fd)) {
      LOG(ERROR) << "Map of '" << fn << "' failed";
      return -1;
      return false;
    }
  }
  return 0;
  return true;
}

/*
 * Release a memory mapping.
 */
void sysReleaseMap(MemMapping* pMap) {
  std::for_each(pMap->ranges.cbegin(), pMap->ranges.cend(), [](const MappedRange& range) {
MemMapping::~MemMapping() {
  for (const auto& range : ranges_) {
    if (munmap(range.addr, range.length) == -1) {
      PLOG(ERROR) << "munmap(" << range.addr << ", " << range.length << ") failed";
      PLOG(ERROR) << "Failed to munmap(" << range.addr << ", " << range.length << ")";
    }
  });
  pMap->ranges.clear();
  };
  ranges_.clear();
}
+24 −26
Original line number Diff line number Diff line
@@ -19,37 +19,35 @@

#include <sys/types.h>

#include <string>
#include <vector>

struct MappedRange {
  void* addr;
  size_t length;
};

/*
 * Use this to keep track of mapped segments.
 */
struct MemMapping {
  unsigned char* addr; /* start of data */
  size_t length;       /* length of data */
class MemMapping {
 public:
  ~MemMapping();
  // Map a file into a private, read-only memory segment. If 'filename' begins with an '@'
  // character, it is a map of blocks to be mapped, otherwise it is treated as an ordinary file.
  bool MapFile(const std::string& filename);
  size_t ranges() const {
    return ranges_.size();
  };

  unsigned char* addr;  // start of data
  size_t length;        // length of data

  std::vector<MappedRange> ranges;
 private:
  struct MappedRange {
    void* addr;
    size_t length;
  };

/*
 * Map a file into a private, read-only memory segment.  If 'fn'
 * begins with an '@' character, it is a map of blocks to be mapped,
 * otherwise it is treated as an ordinary file.
 *
 * On success, "pMap" is filled in, and zero is returned.
 */
int sysMapFile(const char* fn, MemMapping* pMap);
  bool MapBlockFile(const std::string& filename);
  bool MapFD(int fd);

/*
 * Release the pages associated with a shared memory segment.
 *
 * This does not free "pMap"; it just releases the memory.
 */
void sysReleaseMap(MemMapping* pMap);
  std::vector<MappedRange> ranges_;
};

#endif  // _OTAUTIL_SYSUTIL
+2 −2
Original line number Diff line number Diff line
@@ -570,7 +570,7 @@ TEST_F(UpdaterTest, block_image_update) {
  ASSERT_EQ(0, fclose(zip_file_ptr));

  MemMapping map;
  ASSERT_EQ(0, sysMapFile(zip_file.path, &map));
  ASSERT_TRUE(map.MapFile(zip_file.path));
  ZipArchiveHandle handle;
  ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle));

@@ -646,7 +646,7 @@ TEST_F(UpdaterTest, new_data_short_write) {
  ASSERT_EQ(0, fclose(zip_file_ptr));

  MemMapping map;
  ASSERT_EQ(0, sysMapFile(zip_file.path, &map));
  ASSERT_TRUE(map.MapFile(zip_file.path));
  ZipArchiveHandle handle;
  ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle));

+1 −1
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ class VerifierTest : public testing::TestWithParam<std::vector<std::string>> {
  void SetUp() override {
    std::vector<std::string> args = GetParam();
    std::string package = from_testdata_base(args[0]);
    if (sysMapFile(package.c_str(), &memmap) != 0) {
    if (!memmap.MapFile(package)) {
      FAIL() << "Failed to mmap " << package << ": " << strerror(errno) << "\n";
    }

Loading