blob: 4c54818d9187d332e69f665c9996f7c07c793c06 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/installer/util/lzma_file_allocator.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include <windows.h>
extern "C" {
#include "third_party/lzma_sdk/7zAlloc.h"
}
LzmaFileAllocator::LzmaFileAllocator(const base::FilePath& temp_directory) {
DCHECK(base::DirectoryExists(temp_directory));
// Direct the ISzAlloc functions to the LZMA SDK's default allocator.
Alloc = SzAlloc;
Free = SzFree;
if (!base::CreateTemporaryFileInDir(temp_directory, &mapped_file_path_))
return;
mapped_file_.Initialize(mapped_file_path_,
base::File::FLAG_CREATE_ALWAYS |
base::File::FLAG_READ | base::File::FLAG_WRITE |
base::File::FLAG_TEMPORARY |
base::File::FLAG_DELETE_ON_CLOSE);
if (!mapped_file_.IsValid()) {
DPLOG(ERROR) << "Failed to initialize mapped file";
return;
}
// Direct the ISzAlloc functions to this class's allocator.
Alloc = SzFileAlloc;
Free = SzFileFree;
}
LzmaFileAllocator::~LzmaFileAllocator() {
DCHECK(!file_mapping_handle_.IsValid());
Alloc = nullptr;
Free = nullptr;
}
bool LzmaFileAllocator::IsAddressMapped(uintptr_t address) const {
return (address >= mapped_start_address_) &&
(address < mapped_start_address_ + mapped_size_);
}
void* LzmaFileAllocator::DoAllocate(size_t size) {
DCHECK(!file_mapping_handle_.IsValid());
if (size == 0)
return nullptr;
if (!mapped_file_.IsValid())
return SzAlloc(this, size);
if (!mapped_file_.SetLength(size)) {
DPLOG(ERROR) << "Failed to set length of mapped file";
return SzAlloc(this, size);
}
file_mapping_handle_.Set(::CreateFileMapping(
mapped_file_.GetPlatformFile(), nullptr, PAGE_READWRITE, 0, 0, nullptr));
if (!file_mapping_handle_.IsValid()) {
DPLOG(ERROR) << "Failed to create file mapping handle";
return SzAlloc(this, size);
}
void* ret =
::MapViewOfFile(file_mapping_handle_.Get(), FILE_MAP_WRITE, 0, 0, 0);
if (!ret) {
DPLOG(ERROR) << "Failed to map view of file";
file_mapping_handle_.Close();
return SzAlloc(this, size);
}
mapped_start_address_ = reinterpret_cast<uintptr_t>(ret);
mapped_size_ = size;
return ret;
}
void LzmaFileAllocator::DoFree(void* address) {
if (address == nullptr)
return;
if (!file_mapping_handle_.IsValid()) {
SzFree(this, address);
return;
}
int ret = ::UnmapViewOfFile(address);
DPCHECK(ret != 0) << "Failed to unmap view of file";
mapped_start_address_ = 0;
mapped_size_ = 0;
file_mapping_handle_.Close();
}
void* LzmaFileAllocator::SzFileAlloc(void* p, size_t size) {
return static_cast<LzmaFileAllocator*>(p)->DoAllocate(size);
}
void LzmaFileAllocator::SzFileFree(void* p, void* address) {
static_cast<LzmaFileAllocator*>(p)->DoFree(address);
}