Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import libsparse library from AOSP #475

Merged
merged 2 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions base/cvd/android-base/mapped_file.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "android-base/mapped_file.h"

#include <utility>

#include <errno.h>

namespace android {
namespace base {

static constexpr char kEmptyBuffer[] = {'0'};

static off64_t InitPageSize() {
#if defined(_WIN32)
SYSTEM_INFO si;
GetSystemInfo(&si);
return si.dwAllocationGranularity;
#else
return sysconf(_SC_PAGE_SIZE);
#endif
}

std::unique_ptr<MappedFile> MappedFile::FromFd(borrowed_fd fd, off64_t offset, size_t length,
int prot) {
#if defined(_WIN32)
return FromOsHandle(reinterpret_cast<HANDLE>(_get_osfhandle(fd.get())), offset, length, prot);
#else
return FromOsHandle(fd.get(), offset, length, prot);
#endif
}

std::unique_ptr<MappedFile> MappedFile::FromOsHandle(os_handle h, off64_t offset, size_t length,
int prot) {
static const off64_t page_size = InitPageSize();
size_t slop = offset % page_size;
off64_t file_offset = offset - slop;
off64_t file_length = length + slop;

#if defined(_WIN32)
HANDLE handle = CreateFileMappingW(
h, nullptr, (prot & PROT_WRITE) ? PAGE_READWRITE : PAGE_READONLY, 0, 0, nullptr);
if (handle == nullptr) {
// http://b/119818070 "app crashes when reading asset of zero length".
// Return a MappedFile that's only valid for reading the size.
if (length == 0 && ::GetLastError() == ERROR_FILE_INVALID) {
return std::unique_ptr<MappedFile>(
new MappedFile(const_cast<char*>(kEmptyBuffer), 0, 0, nullptr));
}
return nullptr;
}
void* base = MapViewOfFile(handle, (prot & PROT_WRITE) ? FILE_MAP_ALL_ACCESS : FILE_MAP_READ,
(file_offset >> 32), file_offset, file_length);
if (base == nullptr) {
CloseHandle(handle);
return nullptr;
}
return std::unique_ptr<MappedFile>(
new MappedFile(static_cast<char*>(base), length, slop, handle));
#else
void* base = mmap(nullptr, file_length, prot, MAP_SHARED, h, file_offset);
if (base == MAP_FAILED) {
// http://b/119818070 "app crashes when reading asset of zero length".
// mmap fails with EINVAL for a zero length region.
if (errno == EINVAL && length == 0) {
return std::unique_ptr<MappedFile>(new MappedFile(const_cast<char*>(kEmptyBuffer), 0, 0));
}
return nullptr;
}
return std::unique_ptr<MappedFile>(new MappedFile(static_cast<char*>(base), length, slop));
#endif
}

MappedFile::MappedFile(MappedFile&& other)
: base_(std::exchange(other.base_, nullptr)),
size_(std::exchange(other.size_, 0)),
offset_(std::exchange(other.offset_, 0))
#ifdef _WIN32
,
handle_(std::exchange(other.handle_, nullptr))
#endif
{
}

MappedFile& MappedFile::operator=(MappedFile&& other) {
Close();
base_ = std::exchange(other.base_, nullptr);
size_ = std::exchange(other.size_, 0);
offset_ = std::exchange(other.offset_, 0);
#ifdef _WIN32
handle_ = std::exchange(other.handle_, nullptr);
#endif
return *this;
}

MappedFile::~MappedFile() {
Close();
}

void MappedFile::Close() {
#if defined(_WIN32)
if (base_ != nullptr && size_ != 0) UnmapViewOfFile(base_);
if (handle_ != nullptr) CloseHandle(handle_);
handle_ = nullptr;
#else
if (base_ != nullptr && size_ != 0) munmap(base_, size_ + offset_);
#endif

base_ = nullptr;
offset_ = size_ = 0;
}

} // namespace base
} // namespace android
93 changes: 93 additions & 0 deletions base/cvd/android-base/mapped_file.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <sys/types.h>

#include <memory>

#include "android-base/macros.h"
#include "android-base/off64_t.h"
#include "android-base/unique_fd.h"

#if defined(_WIN32)
#include <windows.h>
#define PROT_READ 1
#define PROT_WRITE 2
using os_handle = HANDLE;
#else
#include <sys/mman.h>
using os_handle = int;
#endif

namespace android {
namespace base {

/**
* A region of a file mapped into memory (for grepping: also known as MmapFile or file mapping).
*/
class MappedFile {
public:
/**
* Creates a new mapping of the file pointed to by `fd`. Unlike the underlying OS primitives,
* `offset` does not need to be page-aligned. If `PROT_WRITE` is set in `prot`, the mapping
* will be writable, otherwise it will be read-only. Mappings are always `MAP_SHARED`.
*/
static std::unique_ptr<MappedFile> FromFd(borrowed_fd fd, off64_t offset, size_t length,
int prot);

/**
* Same thing, but using the raw OS file handle instead of a CRT wrapper.
*/
static std::unique_ptr<MappedFile> FromOsHandle(os_handle h, off64_t offset, size_t length,
int prot);

/**
* Removes the mapping.
*/
~MappedFile();

/**
* Not copyable but movable.
*/
MappedFile(MappedFile&& other);
MappedFile& operator=(MappedFile&& other);

char* data() const { return base_ + offset_; }
size_t size() const { return size_; }

private:
DISALLOW_IMPLICIT_CONSTRUCTORS(MappedFile);

void Close();

char* base_;
size_t size_;

size_t offset_;

#if defined(_WIN32)
MappedFile(char* base, size_t size, size_t offset, HANDLE handle)
: base_(base), size_(size), offset_(offset), handle_(handle) {}
HANDLE handle_;
#else
MappedFile(char* base, size_t size, size_t offset) : base_(base), size_(size), offset_(offset) {}
#endif
};

} // namespace base
} // namespace android
Loading
Loading