C++17ification.

C++17ification!

- Filesystem interaction now uses std::filesystem::path.
- Usage of const char*, std::string have been changed to
  std::string_view where appropriate.
- Usage of printf-style functions changed to use fmt.
This commit is contained in:
gibbed
2020-03-02 09:37:11 -06:00
committed by Rick Gibbed
parent 114cea6fb7
commit 5bf0b34445
220 changed files with 4944 additions and 4294 deletions

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -14,7 +14,7 @@
namespace xe {
namespace vfs {
Device::Device(const std::string& mount_path) : mount_path_(mount_path) {}
Device::Device(const std::string_view mount_path) : mount_path_(mount_path) {}
Device::~Device() = default;
} // namespace vfs

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -22,7 +22,7 @@ namespace vfs {
class Device {
public:
explicit Device(const std::string& path);
explicit Device(const std::string_view mount_path);
virtual ~Device();
virtual bool Initialize() = 0;
@@ -31,7 +31,7 @@ class Device {
virtual bool is_read_only() const { return true; }
virtual void Dump(StringBuffer* string_buffer) = 0;
virtual Entry* ResolvePath(const std::string& path) = 0;
virtual Entry* ResolvePath(const std::string_view path) = 0;
virtual uint32_t total_allocation_units() const = 0;
virtual uint32_t available_allocation_units() const = 0;

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -18,14 +18,14 @@ namespace vfs {
const size_t kXESectorSize = 2048;
DiscImageDevice::DiscImageDevice(const std::string& mount_path,
const std::wstring& local_path)
: Device(mount_path), local_path_(local_path) {}
DiscImageDevice::DiscImageDevice(const std::string_view mount_path,
const std::filesystem::path& host_path)
: Device(mount_path), host_path_(host_path) {}
DiscImageDevice::~DiscImageDevice() = default;
bool DiscImageDevice::Initialize() {
mmap_ = MappedMemory::Open(local_path_, MappedMemory::Mode::kRead);
mmap_ = MappedMemory::Open(host_path_, MappedMemory::Mode::kRead);
if (!mmap_) {
XELOGE("Disc image could not be mapped");
return false;
@@ -54,7 +54,7 @@ void DiscImageDevice::Dump(StringBuffer* string_buffer) {
root_entry_->Dump(string_buffer, 0);
}
Entry* DiscImageDevice::ResolvePath(const std::string& path) {
Entry* DiscImageDevice::ResolvePath(const std::string_view path) {
// The filesystem will have stripped our prefix off already, so the path will
// be in the form:
// some\PATH.foo
@@ -63,8 +63,7 @@ Entry* DiscImageDevice::ResolvePath(const std::string& path) {
// Walk the path, one separator at a time.
auto entry = root_entry_.get();
auto path_parts = xe::split_path(path);
for (auto& part : path_parts) {
for (const auto& part : xe::utf8::split_path(path)) {
entry = entry->GetChild(part);
if (!entry) {
// Not found.
@@ -142,14 +141,15 @@ bool DiscImageDevice::ReadEntry(ParseState* state, const uint8_t* buffer,
size_t length = xe::load<uint32_t>(p + 8);
uint8_t attributes = xe::load<uint8_t>(p + 12);
uint8_t name_length = xe::load<uint8_t>(p + 13);
auto name = reinterpret_cast<const char*>(p + 14);
auto name_buffer = reinterpret_cast<const char*>(p + 14);
if (node_l && !ReadEntry(state, buffer, node_l, parent)) {
return false;
}
auto entry = DiscImageEntry::Create(
this, parent, std::string(name, name_length), mmap_.get());
auto name = std::string(name_buffer, name_length);
auto entry = DiscImageEntry::Create(this, parent, name, mmap_.get());
entry->attributes_ = attributes | kFileAttributeReadOnly;
entry->size_ = length;
entry->allocation_size_ = xe::round_up(length, bytes_per_sector());

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -23,13 +23,13 @@ class DiscImageEntry;
class DiscImageDevice : public Device {
public:
DiscImageDevice(const std::string& mount_path,
const std::wstring& local_path);
DiscImageDevice(const std::string_view mount_path,
const std::filesystem::path& host_path);
~DiscImageDevice() override;
bool Initialize() override;
void Dump(StringBuffer* string_buffer) override;
Entry* ResolvePath(const std::string& path) override;
Entry* ResolvePath(const std::string_view path) override;
uint32_t total_allocation_units() const override {
return uint32_t(mmap_->size() / sectors_per_allocation_unit() /
@@ -48,7 +48,7 @@ class DiscImageDevice : public Device {
kErrorDamagedFile = -31,
};
std::wstring local_path_;
std::filesystem::path host_path_;
std::unique_ptr<Entry> root_entry_;
std::unique_ptr<MappedMemory> mmap_;

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -17,8 +17,8 @@
namespace xe {
namespace vfs {
DiscImageEntry::DiscImageEntry(Device* device, Entry* parent, std::string path,
MappedMemory* mmap)
DiscImageEntry::DiscImageEntry(Device* device, Entry* parent,
const std::string_view path, MappedMemory* mmap)
: Entry(device, parent, path),
mmap_(mmap),
data_offset_(0),
@@ -26,13 +26,11 @@ DiscImageEntry::DiscImageEntry(Device* device, Entry* parent, std::string path,
DiscImageEntry::~DiscImageEntry() = default;
std::unique_ptr<DiscImageEntry> DiscImageEntry::Create(Device* device,
Entry* parent,
std::string name,
MappedMemory* mmap) {
auto path = xe::join_paths(parent->path(), name);
std::unique_ptr<DiscImageEntry> DiscImageEntry::Create(
Device* device, Entry* parent, const std::string_view name,
MappedMemory* mmap) {
auto path = xe::utf8::join_guest_paths(parent->path(), name);
auto entry = std::make_unique<DiscImageEntry>(device, parent, path, mmap);
return std::move(entry);
}

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -24,12 +24,12 @@ class DiscImageDevice;
class DiscImageEntry : public Entry {
public:
DiscImageEntry(Device* device, Entry* parent, std::string path,
DiscImageEntry(Device* device, Entry* parent, const std::string_view path,
MappedMemory* mmap);
~DiscImageEntry() override;
static std::unique_ptr<DiscImageEntry> Create(Device* device, Entry* parent,
std::string name,
const std::string_view name,
MappedMemory* mmap);
MappedMemory* mmap() const { return mmap_; }

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -18,24 +18,25 @@
namespace xe {
namespace vfs {
HostPathDevice::HostPathDevice(const std::string& mount_path,
const std::wstring& local_path, bool read_only)
: Device(mount_path), local_path_(local_path), read_only_(read_only) {}
HostPathDevice::HostPathDevice(const std::string_view mount_path,
const std::filesystem::path& host_path,
bool read_only)
: Device(mount_path), host_path_(host_path), read_only_(read_only) {}
HostPathDevice::~HostPathDevice() = default;
bool HostPathDevice::Initialize() {
if (!xe::filesystem::PathExists(local_path_)) {
if (!xe::filesystem::PathExists(host_path_)) {
if (!read_only_) {
// Create the path.
xe::filesystem::CreateFolder(local_path_);
xe::filesystem::CreateFolder(host_path_);
} else {
XELOGE("Host path does not exist");
return false;
}
}
auto root_entry = new HostPathEntry(this, nullptr, "", local_path_);
auto root_entry = new HostPathEntry(this, nullptr, "", host_path_);
root_entry->attributes_ = kFileAttributeDirectory;
root_entry_ = std::unique_ptr<Entry>(root_entry);
PopulateEntry(root_entry);
@@ -48,7 +49,7 @@ void HostPathDevice::Dump(StringBuffer* string_buffer) {
root_entry_->Dump(string_buffer, 0);
}
Entry* HostPathDevice::ResolvePath(const std::string& path) {
Entry* HostPathDevice::ResolvePath(const std::string_view path) {
// The filesystem will have stripped our prefix off already, so the path will
// be in the form:
// some\PATH.foo
@@ -57,7 +58,7 @@ Entry* HostPathDevice::ResolvePath(const std::string& path) {
// Walk the path, one separator at a time.
auto entry = root_entry_.get();
auto path_parts = xe::split_path(path);
auto path_parts = xe::utf8::split_path(path);
for (auto& part : path_parts) {
entry = entry->GetChild(part);
if (!entry) {
@@ -70,11 +71,10 @@ Entry* HostPathDevice::ResolvePath(const std::string& path) {
}
void HostPathDevice::PopulateEntry(HostPathEntry* parent_entry) {
auto child_infos = xe::filesystem::ListFiles(parent_entry->local_path());
auto child_infos = xe::filesystem::ListFiles(parent_entry->host_path());
for (auto& child_info : child_infos) {
auto child = HostPathEntry::Create(
this, parent_entry,
xe::join_paths(parent_entry->local_path(), child_info.name),
this, parent_entry, parent_entry->host_path() / child_info.name,
child_info);
parent_entry->children_.push_back(std::unique_ptr<Entry>(child));

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -21,13 +21,13 @@ class HostPathEntry;
class HostPathDevice : public Device {
public:
HostPathDevice(const std::string& mount_path, const std::wstring& local_path,
bool read_only);
HostPathDevice(const std::string_view mount_path,
const std::filesystem::path& host_path, bool read_only);
~HostPathDevice() override;
bool Initialize() override;
void Dump(StringBuffer* string_buffer) override;
Entry* ResolvePath(const std::string& path) override;
Entry* ResolvePath(const std::string_view path) override;
bool is_read_only() const override { return read_only_; }
@@ -39,7 +39,7 @@ class HostPathDevice : public Device {
private:
void PopulateEntry(HostPathEntry* parent_entry);
std::wstring local_path_;
std::filesystem::path host_path_;
std::unique_ptr<Entry> root_entry_;
bool read_only_;
};

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -20,16 +20,18 @@
namespace xe {
namespace vfs {
HostPathEntry::HostPathEntry(Device* device, Entry* parent, std::string path,
const std::wstring& local_path)
: Entry(device, parent, path), local_path_(local_path) {}
HostPathEntry::HostPathEntry(Device* device, Entry* parent,
const std::string_view path,
const std::filesystem::path& host_path)
: Entry(device, parent, path), host_path_(host_path) {}
HostPathEntry::~HostPathEntry() = default;
HostPathEntry* HostPathEntry::Create(Device* device, Entry* parent,
const std::wstring& full_path,
const std::filesystem::path& full_path,
xe::filesystem::FileInfo file_info) {
auto path = xe::join_paths(parent->path(), xe::to_string(file_info.name));
auto path = xe::utf8::join_guest_paths(parent->path(),
xe::path_to_utf8(file_info.name));
auto entry = new HostPathEntry(device, parent, path, full_path);
entry->create_timestamp_ = file_info.create_timestamp;
@@ -56,7 +58,7 @@ X_STATUS HostPathEntry::Open(uint32_t desired_access, File** out_file) {
return X_STATUS_ACCESS_DENIED;
}
auto file_handle =
xe::filesystem::FileHandle::OpenExisting(local_path_, desired_access);
xe::filesystem::FileHandle::OpenExisting(host_path_, desired_access);
if (!file_handle) {
// TODO(benvanik): pick correct response.
return X_STATUS_NO_SUCH_FILE;
@@ -68,12 +70,12 @@ X_STATUS HostPathEntry::Open(uint32_t desired_access, File** out_file) {
std::unique_ptr<MappedMemory> HostPathEntry::OpenMapped(MappedMemory::Mode mode,
size_t offset,
size_t length) {
return MappedMemory::Open(local_path_, mode, offset, length);
return MappedMemory::Open(host_path_, mode, offset, length);
}
std::unique_ptr<Entry> HostPathEntry::CreateEntryInternal(std::string name,
uint32_t attributes) {
auto full_path = xe::join_paths(local_path_, xe::to_wstring(name));
std::unique_ptr<Entry> HostPathEntry::CreateEntryInternal(
const std::string_view name, uint32_t attributes) {
auto full_path = host_path_ / xe::to_path(name);
if (attributes & kFileAttributeDirectory) {
if (!xe::filesystem::CreateFolder(full_path)) {
return nullptr;
@@ -94,7 +96,7 @@ std::unique_ptr<Entry> HostPathEntry::CreateEntryInternal(std::string name,
}
bool HostPathEntry::DeleteEntryInternal(Entry* entry) {
auto full_path = xe::join_paths(local_path_, xe::to_wstring(entry->name()));
auto full_path = host_path_ / xe::to_path(entry->name());
if (entry->attributes() & kFileAttributeDirectory) {
// Delete entire directory and contents.
return xe::filesystem::DeleteFolder(full_path);
@@ -106,7 +108,7 @@ bool HostPathEntry::DeleteEntryInternal(Entry* entry) {
void HostPathEntry::update() {
xe::filesystem::FileInfo file_info;
if (!xe::filesystem::GetInfo(local_path_, &file_info)) {
if (!xe::filesystem::GetInfo(host_path_, &file_info)) {
return;
}
if (file_info.type == xe::filesystem::FileInfo::Type::kFile) {

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -22,15 +22,15 @@ class HostPathDevice;
class HostPathEntry : public Entry {
public:
HostPathEntry(Device* device, Entry* parent, std::string path,
const std::wstring& local_path);
HostPathEntry(Device* device, Entry* parent, const std::string_view path,
const std::filesystem::path& host_path);
~HostPathEntry() override;
static HostPathEntry* Create(Device* device, Entry* parent,
const std::wstring& full_path,
const std::filesystem::path& full_path,
xe::filesystem::FileInfo file_info);
const std::wstring& local_path() { return local_path_; }
const std::filesystem::path& host_path() { return host_path_; }
X_STATUS Open(uint32_t desired_access, File** out_file) override;
@@ -43,11 +43,11 @@ class HostPathEntry : public Entry {
private:
friend class HostPathDevice;
std::unique_ptr<Entry> CreateEntryInternal(std::string name,
std::unique_ptr<Entry> CreateEntryInternal(const std::string_view name,
uint32_t attributes) override;
bool DeleteEntryInternal(Entry* entry) override;
std::wstring local_path_;
std::filesystem::path host_path_;
};
} // namespace vfs

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -53,22 +53,23 @@ uint64_t decode_fat_timestamp(uint32_t date, uint32_t time) {
return (timet + 11644473600LL) * 10000000;
}
StfsContainerDevice::StfsContainerDevice(const std::string& mount_path,
const std::wstring& local_path)
: Device(mount_path), local_path_(local_path) {}
StfsContainerDevice::StfsContainerDevice(const std::string_view mount_path,
const std::filesystem::path& host_path)
: Device(mount_path), host_path_(host_path) {}
StfsContainerDevice::~StfsContainerDevice() = default;
bool StfsContainerDevice::Initialize() {
// Resolve a valid STFS file if a directory is given.
if (filesystem::IsFolder(local_path_) && !ResolveFromFolder(local_path_)) {
XELOGE("Could not resolve an STFS container given path %ls",
local_path_.c_str());
if (filesystem::IsFolder(host_path_) && !ResolveFromFolder(host_path_)) {
XELOGE("Could not resolve an STFS container given path %s",
xe::path_to_utf8(host_path_).c_str());
return false;
}
if (!filesystem::PathExists(local_path_)) {
XELOGE("Path to STFS container does not exist: %ls", local_path_.c_str());
if (!filesystem::PathExists(host_path_)) {
XELOGE("Path to STFS container does not exist: %s",
xe::path_to_utf8(host_path_).c_str());
return false;
}
@@ -93,8 +94,8 @@ bool StfsContainerDevice::Initialize() {
StfsContainerDevice::Error StfsContainerDevice::MapFiles() {
// Map the file containing the STFS Header and read it.
XELOGI("Mapping STFS Header file: %ls", local_path_.c_str());
auto header_map = MappedMemory::Open(local_path_, MappedMemory::Mode::kRead);
XELOGI("Mapping STFS Header file: %s", xe::path_to_utf8(host_path_).c_str());
auto header_map = MappedMemory::Open(host_path_, MappedMemory::Mode::kRead);
if (!header_map) {
XELOGE("Error mapping STFS Header file.");
return Error::kErrorReadError;
@@ -118,10 +119,10 @@ StfsContainerDevice::Error StfsContainerDevice::MapFiles() {
// If the STFS package is multi-file, it is an SVOD system. We need to map
// the files in the .data folder and can discard the header.
auto data_fragment_path = local_path_ + L".data";
auto data_fragment_path = host_path_ / ".data";
if (!filesystem::PathExists(data_fragment_path)) {
XELOGE("STFS container is multi-file, but path %ls does not exist.",
xe::to_string(data_fragment_path).c_str());
XELOGE("STFS container is multi-file, but path %s does not exist.",
xe::path_to_utf8(data_fragment_path).c_str());
return Error::kErrorFileMismatch;
}
@@ -140,10 +141,10 @@ StfsContainerDevice::Error StfsContainerDevice::MapFiles() {
for (size_t i = 0; i < fragment_files.size(); i++) {
auto file = fragment_files.at(i);
auto path = xe::join_paths(file.path, file.name);
auto path = file.path / file.name;
auto data = MappedMemory::Open(path, MappedMemory::Mode::kRead);
if (!data) {
XELOGI("Failed to map SVOD file %ls.", path.c_str());
XELOGI("Failed to map SVOD file %s.", xe::path_to_utf8(path).c_str());
mmap_.clear();
return Error::kErrorReadError;
}
@@ -158,7 +159,7 @@ void StfsContainerDevice::Dump(StringBuffer* string_buffer) {
root_entry_->Dump(string_buffer, 0);
}
Entry* StfsContainerDevice::ResolvePath(const std::string& path) {
Entry* StfsContainerDevice::ResolvePath(const std::string_view path) {
// The filesystem will have stripped our prefix off already, so the path will
// be in the form:
// some\PATH.foo
@@ -167,7 +168,7 @@ Entry* StfsContainerDevice::ResolvePath(const std::string& path) {
// Walk the path, one separator at a time.
auto entry = root_entry_.get();
auto path_parts = xe::split_path(path);
auto path_parts = xe::utf8::split_path(path);
for (auto& part : path_parts) {
entry = entry->GetChild(part);
if (!entry) {
@@ -339,8 +340,8 @@ StfsContainerDevice::Error StfsContainerDevice::ReadEntrySVOD(
uint32_t length = xe::load<uint32_t>(data + 0x08);
uint8_t attributes = xe::load<uint8_t>(data + 0x0C);
uint8_t name_length = xe::load<uint8_t>(data + 0x0D);
auto name = reinterpret_cast<const char*>(data + 0x0E);
auto name_str = std::string(name, name_length);
auto name_buffer = reinterpret_cast<const char*>(data + 0x0E);
auto name = std::string(name_buffer, name_length);
// Read the left node
if (node_l) {
@@ -358,7 +359,7 @@ StfsContainerDevice::Error StfsContainerDevice::ReadEntrySVOD(
// NOTE: SVOD entries don't have timestamps for individual files, which can
// cause issues when decrypting games. Using the root entry's timestamp
// solves this issues.
auto entry = StfsContainerEntry::Create(this, parent, name_str, &mmap_);
auto entry = StfsContainerEntry::Create(this, parent, name, &mmap_);
if (attributes & kFileAttributeDirectory) {
// Entry is a directory
entry->attributes_ = kFileAttributeDirectory | kFileAttributeReadOnly;
@@ -507,12 +508,12 @@ StfsContainerDevice::Error StfsContainerDevice::ReadSTFS() {
for (size_t n = 0; n < volume_descriptor.file_table_block_count; n++) {
const uint8_t* p = data + BlockToOffsetSTFS(table_block_index);
for (size_t m = 0; m < 0x1000 / 0x40; m++) {
const uint8_t* filename = p; // 0x28b
if (filename[0] == 0) {
const uint8_t* name_buffer = p; // 0x28b
if (name_buffer[0] == 0) {
// Done.
break;
}
uint8_t filename_length_flags = xe::load_and_swap<uint8_t>(p + 0x28);
uint8_t name_length_flags = xe::load_and_swap<uint8_t>(p + 0x28);
// TODO(benvanik): use for allocation_size_?
// uint32_t allocated_block_count = load_uint24_le(p + 0x29);
uint32_t start_block_index = load_uint24_le(p + 0x2F);
@@ -533,13 +534,12 @@ StfsContainerDevice::Error StfsContainerDevice::ReadSTFS() {
parent_entry = all_entries[path_indicator];
}
std::string name_str(reinterpret_cast<const char*>(filename),
filename_length_flags & 0x3F);
auto entry =
StfsContainerEntry::Create(this, parent_entry, name_str, &mmap_);
std::string name(reinterpret_cast<const char*>(name_buffer),
name_length_flags & 0x3F);
auto entry = StfsContainerEntry::Create(this, parent_entry, name, &mmap_);
// bit 0x40 = consecutive blocks (not fragmented?)
if (filename_length_flags & 0x80) {
if (name_length_flags & 0x80) {
entry->attributes_ = kFileAttributeDirectory;
} else {
entry->attributes_ = kFileAttributeNormal | kFileAttributeReadOnly;
@@ -739,12 +739,12 @@ bool StfsHeader::Read(const uint8_t* p) {
return true;
}
bool StfsContainerDevice::ResolveFromFolder(const std::wstring& path) {
bool StfsContainerDevice::ResolveFromFolder(const std::filesystem::path& path) {
// Scan through folders until a file with magic is found
std::queue<filesystem::FileInfo> queue;
filesystem::FileInfo folder;
filesystem::GetInfo(local_path_, &folder);
filesystem::GetInfo(host_path_, &folder);
queue.push(folder);
while (!queue.empty()) {
@@ -752,25 +752,25 @@ bool StfsContainerDevice::ResolveFromFolder(const std::wstring& path) {
queue.pop();
if (current_file.type == filesystem::FileInfo::Type::kDirectory) {
auto path = xe::join_paths(current_file.path, current_file.name);
auto path = current_file.path / current_file.name;
auto child_files = filesystem::ListFiles(path);
for (auto file : child_files) {
queue.push(file);
}
} else {
// Try to read the file's magic
auto path = xe::join_paths(current_file.path, current_file.name);
auto path = current_file.path / current_file.name;
auto map = MappedMemory::Open(path, MappedMemory::Mode::kRead, 0, 4);
if (map && ReadPackageType(map->data(), map->size(), nullptr) ==
Error::kSuccess) {
local_path_ = xe::join_paths(current_file.path, current_file.name);
XELOGI("STFS Package found: %ls", local_path_.c_str());
host_path_ = current_file.path / current_file.name;
XELOGI("STFS Package found: %s", xe::path_to_utf8(host_path_).c_str());
return true;
}
}
}
if (local_path_ == path) {
if (host_path_ == path) {
// Could not find a suitable container file
return false;
}

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -144,10 +144,10 @@ class StfsHeader {
uint64_t data_file_combined_size;
StfsDescriptorType descriptor_type;
uint8_t device_id[0x14];
wchar_t display_names[0x900 / 2];
wchar_t display_descs[0x900 / 2];
wchar_t publisher_name[0x80 / 2];
wchar_t title_name[0x80 / 2];
char16_t display_names[0x900 / 2];
char16_t display_descs[0x900 / 2];
char16_t publisher_name[0x80 / 2];
char16_t title_name[0x80 / 2];
uint8_t transfer_flags;
uint32_t thumbnail_image_size;
uint32_t title_thumbnail_image_size;
@@ -159,19 +159,19 @@ class StfsHeader {
uint8_t season_id[0x10];
int16_t season_number;
int16_t episode_number;
wchar_t additonal_display_names[0x300 / 2];
wchar_t additional_display_descriptions[0x300 / 2];
char16_t additonal_display_names[0x300 / 2];
char16_t additional_display_descriptions[0x300 / 2];
};
class StfsContainerDevice : public Device {
public:
StfsContainerDevice(const std::string& mount_path,
const std::wstring& local_path);
StfsContainerDevice(const std::string_view mount_path,
const std::filesystem::path& host_path);
~StfsContainerDevice() override;
bool Initialize() override;
void Dump(StringBuffer* string_buffer) override;
Entry* ResolvePath(const std::string& path) override;
Entry* ResolvePath(const std::string_view path) override;
uint32_t total_allocation_units() const override {
return uint32_t(mmap_total_size_ / sectors_per_allocation_unit() /
@@ -197,7 +197,7 @@ class StfsContainerDevice : public Device {
const uint32_t kSTFSHashSpacing = 170;
bool ResolveFromFolder(const std::wstring& path);
bool ResolveFromFolder(const std::filesystem::path& path);
Error MapFiles();
static Error ReadPackageType(const uint8_t* map_ptr, size_t map_size,
@@ -215,7 +215,7 @@ class StfsContainerDevice : public Device {
BlockHash GetBlockHash(const uint8_t* map_ptr, uint32_t block_index,
uint32_t table_offset);
std::wstring local_path_;
std::filesystem::path host_path_;
std::map<size_t, std::unique_ptr<MappedMemory>> mmap_;
size_t mmap_total_size_;

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -17,7 +17,7 @@ namespace xe {
namespace vfs {
StfsContainerEntry::StfsContainerEntry(Device* device, Entry* parent,
std::string path,
const std::string_view path,
MultifileMemoryMap* mmap)
: Entry(device, parent, path),
mmap_(mmap),
@@ -27,8 +27,9 @@ StfsContainerEntry::StfsContainerEntry(Device* device, Entry* parent,
StfsContainerEntry::~StfsContainerEntry() = default;
std::unique_ptr<StfsContainerEntry> StfsContainerEntry::Create(
Device* device, Entry* parent, std::string name, MultifileMemoryMap* mmap) {
auto path = xe::join_paths(parent->path(), name);
Device* device, Entry* parent, const std::string_view name,
MultifileMemoryMap* mmap) {
auto path = xe::utf8::join_guest_paths(parent->path(), name);
auto entry = std::make_unique<StfsContainerEntry>(device, parent, path, mmap);
return std::move(entry);

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -27,13 +27,13 @@ class StfsContainerDevice;
class StfsContainerEntry : public Entry {
public:
StfsContainerEntry(Device* device, Entry* parent, std::string path,
StfsContainerEntry(Device* device, Entry* parent, const std::string_view path,
MultifileMemoryMap* mmap);
~StfsContainerEntry() override;
static std::unique_ptr<StfsContainerEntry> Create(Device* device,
Entry* parent,
std::string name,
const std::string_view name,
MultifileMemoryMap* mmap);
MultifileMemoryMap* mmap() const { return mmap_; }

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -16,7 +16,7 @@
namespace xe {
namespace vfs {
Entry::Entry(Device* device, Entry* parent, const std::string& path)
Entry::Entry(Device* device, Entry* parent, const std::string_view path)
: device_(device),
parent_(parent),
path_(path),
@@ -27,8 +27,8 @@ Entry::Entry(Device* device, Entry* parent, const std::string& path)
access_timestamp_(0),
write_timestamp_(0) {
assert_not_null(device);
absolute_path_ = xe::join_paths(device->mount_path(), path);
name_ = xe::find_name_from_path(path);
absolute_path_ = xe::utf8::join_guest_paths(device->mount_path(), path);
name_ = xe::utf8::find_name_from_guest_path(path);
}
Entry::~Entry() = default;
@@ -46,15 +46,16 @@ void Entry::Dump(xe::StringBuffer* string_buffer, int indent) {
bool Entry::is_read_only() const { return device_->is_read_only(); }
Entry* Entry::GetChild(std::string name) {
Entry* Entry::GetChild(const std::string_view name) {
auto global_lock = global_critical_region_.Acquire();
// TODO(benvanik): a faster search
for (auto& child : children_) {
if (strcasecmp(child->name().c_str(), name.c_str()) == 0) {
return child.get();
}
auto it = std::find_if(children_.cbegin(), children_.cend(),
[&](const auto& child) {
return xe::utf8::equal_case(child->name(), name);
});
if (it == children_.cend()) {
return nullptr;
}
return nullptr;
return (*it).get();
}
Entry* Entry::IterateChildren(const xe::filesystem::WildcardEngine& engine,
@@ -70,7 +71,7 @@ Entry* Entry::IterateChildren(const xe::filesystem::WildcardEngine& engine,
return nullptr;
}
Entry* Entry::CreateEntry(std::string name, uint32_t attributes) {
Entry* Entry::CreateEntry(const std::string_view name, uint32_t attributes) {
auto global_lock = global_critical_region_.Acquire();
if (is_read_only()) {
return nullptr;

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -96,7 +96,7 @@ class Entry {
bool is_read_only() const;
Entry* GetChild(std::string name);
Entry* GetChild(const std::string_view name);
const std::vector<std::unique_ptr<Entry>>& children() const {
return children_;
@@ -105,7 +105,7 @@ class Entry {
Entry* IterateChildren(const xe::filesystem::WildcardEngine& engine,
size_t* current_index);
Entry* CreateEntry(std::string name, uint32_t attributes);
Entry* CreateEntry(const std::string_view name, uint32_t attributes);
bool Delete(Entry* entry);
bool Delete();
void Touch();
@@ -123,10 +123,10 @@ class Entry {
virtual void update() { return; }
protected:
Entry(Device* device, Entry* parent, const std::string& path);
Entry(Device* device, Entry* parent, const std::string_view path);
virtual std::unique_ptr<Entry> CreateEntryInternal(std::string name,
uint32_t attributes) {
virtual std::unique_ptr<Entry> CreateEntryInternal(
const std::string_view name, uint32_t attributes) {
return nullptr;
}
virtual bool DeleteEntryInternal(Entry* entry) { return false; }

View File

@@ -19,6 +19,7 @@ project("xenia-vfs-dump")
kind("ConsoleApp")
language("C++")
links({
"fmt",
"xenia-base",
"xenia-vfs",
})

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2018 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -21,23 +21,23 @@
namespace xe {
namespace vfs {
DEFINE_transient_string(source, "", "Specifies the file to dump from.",
"General");
DEFINE_transient_path(source, "", "Specifies the file to dump from.",
"General");
DEFINE_transient_string(dump_path, "",
"Specifies the directory to dump files to.", "General");
DEFINE_transient_path(dump_path, "",
"Specifies the directory to dump files to.", "General");
int vfs_dump_main(const std::vector<std::wstring>& args) {
if (args.size() <= 2) {
XELOGE("Usage: %S [source] [dump_path]", args[0].c_str());
int vfs_dump_main(const std::vector<std::string>& args) {
if (cvars::source.empty() || cvars::dump_path.empty()) {
XELOGE("Usage: %s [source] [dump_path]", xe::path_to_utf8(args[0]).c_str());
return 1;
}
std::wstring base_path = args[2];
std::filesystem::path base_path = cvars::dump_path;
std::unique_ptr<vfs::Device> device;
// TODO: Flags specifying the type of device.
device = std::make_unique<vfs::StfsContainerDevice>("", args[1]);
device = std::make_unique<vfs::StfsContainerDevice>("", cvars::source);
if (!device->Initialize()) {
XELOGE("Failed to initialize device");
return 1;
@@ -60,9 +60,9 @@ int vfs_dump_main(const std::vector<std::wstring>& args) {
}
XELOGI("%s", entry->path().c_str());
auto dest_name = xe::join_paths(base_path, xe::to_wstring(entry->path()));
auto dest_name = base_path / xe::to_path(entry->path());
if (entry->attributes() & kFileAttributeDirectory) {
xe::filesystem::CreateFolder(dest_name + L"\\");
xe::filesystem::CreateFolder(dest_name);
continue;
}
@@ -113,5 +113,5 @@ int vfs_dump_main(const std::vector<std::wstring>& args) {
} // namespace vfs
} // namespace xe
DEFINE_ENTRY_POINT(L"xenia-vfs-dump", xe::vfs::vfs_dump_main,
DEFINE_ENTRY_POINT("xenia-vfs-dump", xe::vfs::vfs_dump_main,
"[source] [dump_path]", "source", "dump_path");

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -32,7 +32,7 @@ bool VirtualFileSystem::RegisterDevice(std::unique_ptr<Device> device) {
return true;
}
bool VirtualFileSystem::UnregisterDevice(const std::string& path) {
bool VirtualFileSystem::UnregisterDevice(const std::string_view path) {
auto global_lock = global_critical_region_.Acquire();
for (auto it = devices_.begin(); it != devices_.end(); ++it) {
if ((*it)->mount_path() == path) {
@@ -44,18 +44,21 @@ bool VirtualFileSystem::UnregisterDevice(const std::string& path) {
return false;
}
bool VirtualFileSystem::RegisterSymbolicLink(const std::string& path,
const std::string& target) {
bool VirtualFileSystem::RegisterSymbolicLink(const std::string_view path,
const std::string_view target) {
auto global_lock = global_critical_region_.Acquire();
symlinks_.insert({path, target});
XELOGD("Registered symbolic link: %s => %s", path.c_str(), target.c_str());
symlinks_.insert({std::string(path), std::string(target)});
XELOGD("Registered symbolic link: %s => %s", std::string(path).c_str(),
std::string(target).c_str());
return true;
}
bool VirtualFileSystem::UnregisterSymbolicLink(const std::string& path) {
bool VirtualFileSystem::UnregisterSymbolicLink(const std::string_view path) {
auto global_lock = global_critical_region_.Acquire();
auto it = symlinks_.find(path);
auto it = std::find_if(
symlinks_.cbegin(), symlinks_.cend(),
[&](const auto& s) { return xe::utf8::equal_case(path, s.first); });
if (it == symlinks_.end()) {
return false;
}
@@ -66,12 +69,11 @@ bool VirtualFileSystem::UnregisterSymbolicLink(const std::string& path) {
return true;
}
bool VirtualFileSystem::FindSymbolicLink(const std::string& path,
bool VirtualFileSystem::FindSymbolicLink(const std::string_view path,
std::string& target) {
auto it =
std::find_if(symlinks_.cbegin(), symlinks_.cend(), [&](const auto& s) {
return xe::find_first_of_case(path, s.first) == 0;
});
auto it = std::find_if(
symlinks_.cbegin(), symlinks_.cend(),
[&](const auto& s) { return xe::utf8::starts_with_case(path, s.first); });
if (it == symlinks_.cend()) {
return false;
}
@@ -79,14 +81,14 @@ bool VirtualFileSystem::FindSymbolicLink(const std::string& path,
return true;
}
bool VirtualFileSystem::ResolveSymbolicLink(const std::string& path,
bool VirtualFileSystem::ResolveSymbolicLink(const std::string_view path,
std::string& result) {
result = path;
bool was_resolved = false;
while (true) {
auto it =
std::find_if(symlinks_.cbegin(), symlinks_.cend(), [&](const auto& s) {
return xe::find_first_of_case(result, s.first) == 0;
return xe::utf8::starts_with_case(result, s.first);
});
if (it == symlinks_.cend()) {
break;
@@ -100,11 +102,11 @@ bool VirtualFileSystem::ResolveSymbolicLink(const std::string& path,
return was_resolved;
}
Entry* VirtualFileSystem::ResolvePath(const std::string& path) {
Entry* VirtualFileSystem::ResolvePath(const std::string_view path) {
auto global_lock = global_critical_region_.Acquire();
// Resolve relative paths
std::string normalized_path(xe::filesystem::CanonicalizePath(path));
auto normalized_path(xe::utf8::canonicalize_guest_path(path));
// Resolve symlinks.
std::string resolved_path;
@@ -115,10 +117,11 @@ Entry* VirtualFileSystem::ResolvePath(const std::string& path) {
// Find the device.
auto it =
std::find_if(devices_.cbegin(), devices_.cend(), [&](const auto& d) {
return xe::find_first_of_case(normalized_path, d->mount_path()) == 0;
return xe::utf8::starts_with(normalized_path, d->mount_path());
});
if (it == devices_.cend()) {
XELOGE("ResolvePath(%s) failed - device not found", path.c_str());
XELOGE("ResolvePath(%s) failed - device not found",
std::string(path).c_str());
return nullptr;
}
@@ -127,26 +130,26 @@ Entry* VirtualFileSystem::ResolvePath(const std::string& path) {
return device->ResolvePath(relative_path);
}
Entry* VirtualFileSystem::ResolveBasePath(const std::string& path) {
auto base_path = xe::find_base_path(path);
Entry* VirtualFileSystem::ResolveBasePath(const std::string_view path) {
auto base_path = xe::utf8::find_base_guest_path(path);
return ResolvePath(base_path);
}
Entry* VirtualFileSystem::CreatePath(const std::string& path,
Entry* VirtualFileSystem::CreatePath(const std::string_view path,
uint32_t attributes) {
// Create all required directories recursively.
auto path_parts = xe::split_path(path);
auto path_parts = xe::utf8::split_path(path);
if (path_parts.empty()) {
return nullptr;
}
auto partial_path = path_parts[0];
auto partial_path = std::string(path_parts[0]);
auto partial_entry = ResolvePath(partial_path);
if (!partial_entry) {
return nullptr;
}
auto parent_entry = partial_entry;
for (size_t i = 1; i < path_parts.size() - 1; ++i) {
partial_path = xe::join_paths(partial_path, path_parts[i]);
partial_path = xe::utf8::join_guest_paths(partial_path, path_parts[i]);
auto child_entry = ResolvePath(partial_path);
if (!child_entry) {
child_entry =
@@ -161,7 +164,7 @@ Entry* VirtualFileSystem::CreatePath(const std::string& path,
attributes);
}
bool VirtualFileSystem::DeletePath(const std::string& path) {
bool VirtualFileSystem::DeletePath(const std::string_view path) {
auto entry = ResolvePath(path);
if (!entry) {
return false;
@@ -174,7 +177,7 @@ bool VirtualFileSystem::DeletePath(const std::string& path) {
return parent->Delete(entry);
}
X_STATUS VirtualFileSystem::OpenFile(const std::string& path,
X_STATUS VirtualFileSystem::OpenFile(const std::string_view path,
FileDisposition creation_disposition,
uint32_t desired_access, bool is_directory,
File** out_file, FileAction* out_action) {
@@ -196,14 +199,14 @@ X_STATUS VirtualFileSystem::OpenFile(const std::string& path,
// If no device or parent, fail.
Entry* parent_entry = nullptr;
Entry* entry = nullptr;
if (!xe::find_base_path(path).empty()) {
if (!xe::utf8::find_base_guest_path(path).empty()) {
parent_entry = ResolveBasePath(path);
if (!parent_entry) {
*out_action = FileAction::kDoesNotExist;
return X_STATUS_NO_SUCH_FILE;
}
auto file_name = xe::find_name_from_path(path);
auto file_name = xe::utf8::find_name_from_guest_path(path);
entry = parent_entry->GetChild(file_name);
} else {
entry = ResolvePath(path);

View File

@@ -29,19 +29,20 @@ class VirtualFileSystem {
~VirtualFileSystem();
bool RegisterDevice(std::unique_ptr<Device> device);
bool UnregisterDevice(const std::string& path);
bool UnregisterDevice(const std::string_view path);
bool RegisterSymbolicLink(const std::string& path, const std::string& target);
bool UnregisterSymbolicLink(const std::string& path);
bool FindSymbolicLink(const std::string& path, std::string& target);
bool RegisterSymbolicLink(const std::string_view path,
const std::string_view target);
bool UnregisterSymbolicLink(const std::string_view path);
bool FindSymbolicLink(const std::string_view path, std::string& target);
Entry* ResolvePath(const std::string& path);
Entry* ResolveBasePath(const std::string& path);
Entry* ResolvePath(const std::string_view path);
Entry* ResolveBasePath(const std::string_view path);
Entry* CreatePath(const std::string& path, uint32_t attributes);
bool DeletePath(const std::string& path);
Entry* CreatePath(const std::string_view path, uint32_t attributes);
bool DeletePath(const std::string_view path);
X_STATUS OpenFile(const std::string& path,
X_STATUS OpenFile(const std::string_view path,
FileDisposition creation_disposition,
uint32_t desired_access, bool is_directory, File** out_file,
FileAction* out_action);
@@ -51,7 +52,7 @@ class VirtualFileSystem {
std::vector<std::unique_ptr<Device>> devices_;
std::unordered_map<std::string, std::string> symlinks_;
bool ResolveSymbolicLink(const std::string& path, std::string& result);
bool ResolveSymbolicLink(const std::string_view path, std::string& result);
};
} // namespace vfs