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:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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_;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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_; }
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_; }
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -19,6 +19,7 @@ project("xenia-vfs-dump")
|
||||
kind("ConsoleApp")
|
||||
language("C++")
|
||||
links({
|
||||
"fmt",
|
||||
"xenia-base",
|
||||
"xenia-vfs",
|
||||
})
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user