fs: update + consolidate path normalization logic
This commit is contained in:
@@ -35,10 +35,10 @@ namespace ams::fssystem {
|
||||
|
||||
DirectoryRedirectionFileSystem::~DirectoryRedirectionFileSystem() {
|
||||
if (this->before_dir != nullptr) {
|
||||
std::free(this->before_dir);
|
||||
fs::impl::Deallocate(this->before_dir, this->before_dir_len);
|
||||
}
|
||||
if (this->after_dir != nullptr) {
|
||||
std::free(this->after_dir);
|
||||
fs::impl::Deallocate(this->after_dir, this->after_dir_len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,26 +53,26 @@ namespace ams::fssystem {
|
||||
/* Normalize the path. */
|
||||
char normalized_path[fs::EntryNameLengthMax + 2];
|
||||
size_t normalized_path_len;
|
||||
R_TRY(PathTool::Normalize(normalized_path, &normalized_path_len, dir, sizeof(normalized_path), this->IsUncPreserved()));
|
||||
R_TRY(fs::PathNormalizer::Normalize(normalized_path, &normalized_path_len, dir, sizeof(normalized_path), this->IsUncPreserved(), false));
|
||||
|
||||
/* Ensure terminating '/' */
|
||||
if (!PathTool::IsSeparator(normalized_path[normalized_path_len - 1])) {
|
||||
AMS_ABORT_UNLESS(normalized_path_len + 2 <= sizeof(normalized_path));
|
||||
normalized_path[normalized_path_len] = StringTraits::DirectorySeparator;
|
||||
normalized_path[normalized_path_len + 1] = StringTraits::NullTerminator;
|
||||
if (!fs::PathNormalizer::IsSeparator(normalized_path[normalized_path_len - 1])) {
|
||||
AMS_ASSERT(normalized_path_len + 2 < sizeof(normalized_path));
|
||||
normalized_path[normalized_path_len] = fs::StringTraits::DirectorySeparator;
|
||||
normalized_path[normalized_path_len + 1] = fs::StringTraits::NullTerminator;
|
||||
|
||||
normalized_path_len++;
|
||||
++normalized_path_len;
|
||||
}
|
||||
|
||||
/* Allocate new path. */
|
||||
const size_t size = normalized_path_len + 1;
|
||||
char *new_dir = static_cast<char *>(std::malloc(size));
|
||||
char *new_dir = static_cast<char *>(fs::impl::Allocate(size));
|
||||
AMS_ABORT_UNLESS(new_dir != nullptr);
|
||||
/* TODO: custom ResultAllocationFailure? */
|
||||
|
||||
/* Copy path in. */
|
||||
std::memcpy(new_dir, normalized_path, normalized_path_len);
|
||||
new_dir[normalized_path_len] = StringTraits::NullTerminator;
|
||||
new_dir[normalized_path_len] = fs::StringTraits::NullTerminator;
|
||||
|
||||
/* Set output. */
|
||||
*out = new_dir;
|
||||
@@ -82,20 +82,30 @@ namespace ams::fssystem {
|
||||
|
||||
Result DirectoryRedirectionFileSystem::Initialize(const char *before, const char *after) {
|
||||
/* Normalize both directories. */
|
||||
this->GetNormalizedDirectoryPath(&this->before_dir, &this->before_dir_len, before);
|
||||
this->GetNormalizedDirectoryPath(&this->after_dir, &this->after_dir_len, after);
|
||||
this->GetNormalizedDirectoryPath(std::addressof(this->before_dir), std::addressof(this->before_dir_len), before);
|
||||
this->GetNormalizedDirectoryPath(std::addressof(this->after_dir), std::addressof(this->after_dir_len), after);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result DirectoryRedirectionFileSystem::ResolveFullPath(char *out, size_t out_size, const char *relative_path) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(relative_path[0] == '/');
|
||||
AMS_ASSERT(this->before_dir_len >= 2);
|
||||
AMS_ASSERT(this->after_dir_len >= 2);
|
||||
AMS_ASSERT(this->after_dir_len <= out_size);
|
||||
AMS_ASSERT(fs::PathNormalizer::IsNullTerminator(this->before_dir[this->before_dir_len - 1]));
|
||||
AMS_ASSERT(fs::PathNormalizer::IsSeparator(this->before_dir[this->before_dir_len - 2]));
|
||||
AMS_ASSERT(fs::PathNormalizer::IsNullTerminator(this->after_dir[this->after_dir_len - 1]));
|
||||
AMS_ASSERT(fs::PathNormalizer::IsSeparator(this->after_dir[this->after_dir_len - 2]));
|
||||
|
||||
/* Normalize the relative path. */
|
||||
char normalized_rel_path[fs::EntryNameLengthMax + 1];
|
||||
size_t normalized_rel_path_len;
|
||||
R_TRY(PathTool::Normalize(normalized_rel_path, &normalized_rel_path_len, relative_path, sizeof(normalized_rel_path), this->IsUncPreserved()));
|
||||
R_TRY(fs::PathNormalizer::Normalize(normalized_rel_path, std::addressof(normalized_rel_path_len), relative_path, sizeof(normalized_rel_path), this->IsUncPreserved(), false));
|
||||
|
||||
const bool is_prefixed = std::memcmp(normalized_rel_path, this->before_dir, this->before_dir_len - 2) == 0 &&
|
||||
(PathTool::IsSeparator(normalized_rel_path[this->before_dir_len - 2]) || PathTool::IsNullTerminator(normalized_rel_path[this->before_dir_len - 2]));
|
||||
(fs::PathNormalizer::IsSeparator(normalized_rel_path[this->before_dir_len - 2]) || fs::PathNormalizer::IsNullTerminator(normalized_rel_path[this->before_dir_len - 2]));
|
||||
if (is_prefixed) {
|
||||
const size_t before_prefix_len = this->before_dir_len - 2;
|
||||
const size_t after_prefix_len = this->after_dir_len - 2;
|
||||
@@ -105,12 +115,12 @@ namespace ams::fssystem {
|
||||
/* Copy normalized path. */
|
||||
std::memcpy(out, this->after_dir, after_prefix_len);
|
||||
std::memcpy(out + after_prefix_len, normalized_rel_path + before_prefix_len, normalized_rel_path_len - before_prefix_len);
|
||||
out[final_str_len] = StringTraits::NullTerminator;
|
||||
out[final_str_len] = fs::StringTraits::NullTerminator;
|
||||
} else {
|
||||
/* Path is not prefixed. */
|
||||
R_UNLESS(normalized_rel_path_len + 1 <= out_size, fs::ResultTooLongPath());
|
||||
std::memcpy(out, normalized_rel_path, normalized_rel_path_len);
|
||||
out[normalized_rel_path_len] = StringTraits::NullTerminator;
|
||||
out[normalized_rel_path_len] = fs::StringTraits::NullTerminator;
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
|
||||
@@ -156,16 +156,16 @@ namespace ams::fssystem {
|
||||
|
||||
Result DirectorySaveDataFileSystem::ResolveFullPath(char *out, size_t out_size, const char *relative_path) {
|
||||
R_UNLESS(strnlen(relative_path, fs::EntryNameLengthMax + 1) < fs::EntryNameLengthMax + 1, fs::ResultTooLongPath());
|
||||
R_UNLESS(PathTool::IsSeparator(relative_path[0]), fs::ResultInvalidPath());
|
||||
R_UNLESS(fs::PathNormalizer::IsSeparator(relative_path[0]), fs::ResultInvalidPath());
|
||||
|
||||
/* Copy working directory path. */
|
||||
std::strncpy(out, WorkingDirectoryPath, out_size);
|
||||
out[out_size - 1] = StringTraits::NullTerminator;
|
||||
out[out_size - 1] = fs::StringTraits::NullTerminator;
|
||||
|
||||
/* Normalize it. */
|
||||
constexpr size_t WorkingDirectoryPathLength = sizeof(WorkingDirectoryPath) - 1;
|
||||
size_t normalized_length;
|
||||
return PathTool::Normalize(out + WorkingDirectoryPathLength - 1, &normalized_length, relative_path, out_size - (WorkingDirectoryPathLength - 1));
|
||||
return fs::PathNormalizer::Normalize(out + WorkingDirectoryPathLength - 1, &normalized_length, relative_path, out_size - (WorkingDirectoryPathLength - 1));
|
||||
}
|
||||
|
||||
void DirectorySaveDataFileSystem::OnWritableFileClose() {
|
||||
@@ -186,7 +186,7 @@ namespace ams::fssystem {
|
||||
R_TRY(this->AllocateWorkBuffer(&work_buf, &work_buf_size, IdealWorkBufferSize));
|
||||
|
||||
/* Copy the directory recursively. */
|
||||
R_TRY(fssystem::CopyDirectoryRecursively(this->base_fs, save_fs, PathTool::RootPath, PathTool::RootPath, work_buf.get(), work_buf_size));
|
||||
R_TRY(fssystem::CopyDirectoryRecursively(this->base_fs, save_fs, fs::PathNormalizer::RootPath, fs::PathNormalizer::RootPath, work_buf.get(), work_buf_size));
|
||||
|
||||
return this->Commit();
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ namespace ams::fssystem {
|
||||
dir_entry.type = fs::DirectoryEntryType_File;
|
||||
dir_entry.file_size = this->parent->meta_data->GetEntry(this->cur_index)->size;
|
||||
std::strncpy(dir_entry.name, this->parent->meta_data->GetEntryName(this->cur_index), sizeof(dir_entry.name) - 1);
|
||||
dir_entry.name[sizeof(dir_entry.name) - 1] = StringTraits::NullTerminator;
|
||||
dir_entry.name[sizeof(dir_entry.name) - 1] = fs::StringTraits::NullTerminator;
|
||||
}
|
||||
|
||||
*out_count = entry_count;
|
||||
@@ -349,11 +349,11 @@ namespace ams::fssystem {
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::DoGetEntryType(fs::DirectoryEntryType *out, const char *path) {
|
||||
/* Validate preconditions. */
|
||||
R_UNLESS(this->initialized, fs::ResultPreconditionViolation());
|
||||
R_UNLESS(PathTool::IsSeparator(path[0]), fs::ResultInvalidPathFormat());
|
||||
R_UNLESS(this->initialized, fs::ResultPreconditionViolation());
|
||||
R_UNLESS(fs::PathNormalizer::IsSeparator(path[0]), fs::ResultInvalidPathFormat());
|
||||
|
||||
/* Check if the path is for a directory. */
|
||||
if (std::strncmp(path, PathTool::RootPath, sizeof(PathTool::RootPath)) == 0) {
|
||||
if (std::strncmp(path, fs::PathNormalizer::RootPath, sizeof(fs::PathNormalizer::RootPath)) == 0) {
|
||||
*out = fs::DirectoryEntryType_Directory;
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -384,8 +384,8 @@ namespace ams::fssystem {
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const char *path, fs::OpenDirectoryMode mode) {
|
||||
/* Validate preconditions. */
|
||||
R_UNLESS(this->initialized, fs::ResultPreconditionViolation());
|
||||
R_UNLESS(std::strncmp(path, PathTool::RootPath, sizeof(PathTool::RootPath)) == 0, fs::ResultPathNotFound());
|
||||
R_UNLESS(this->initialized, fs::ResultPreconditionViolation());
|
||||
R_UNLESS(std::strncmp(path, fs::PathNormalizer::RootPath, sizeof(fs::PathNormalizer::RootPath)) == 0, fs::ResultPathNotFound());
|
||||
|
||||
/* Create and output the partition directory. */
|
||||
std::unique_ptr directory = std::make_unique<PartitionDirectory>(this, mode);
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace ams::fssystem {
|
||||
|
||||
SubDirectoryFileSystem::~SubDirectoryFileSystem() {
|
||||
if (this->base_path != nullptr) {
|
||||
std::free(this->base_path);
|
||||
fs::impl::Deallocate(this->base_path, this->base_path_len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,25 +44,25 @@ namespace ams::fssystem {
|
||||
/* Normalize the path. */
|
||||
char normalized_path[fs::EntryNameLengthMax + 2];
|
||||
size_t normalized_path_len;
|
||||
R_TRY(PathTool::Normalize(normalized_path, &normalized_path_len, bp, sizeof(normalized_path), this->IsUncPreserved()));
|
||||
R_TRY(fs::PathNormalizer::Normalize(normalized_path, std::addressof(normalized_path_len), bp, sizeof(normalized_path), this->IsUncPreserved()));
|
||||
|
||||
/* Ensure terminating '/' */
|
||||
if (!PathTool::IsSeparator(normalized_path[normalized_path_len - 1])) {
|
||||
AMS_ABORT_UNLESS(normalized_path_len + 2 <= sizeof(normalized_path));
|
||||
normalized_path[normalized_path_len] = StringTraits::DirectorySeparator;
|
||||
normalized_path[normalized_path_len + 1] = StringTraits::NullTerminator;
|
||||
if (!fs::PathNormalizer::IsSeparator(normalized_path[normalized_path_len - 1])) {
|
||||
AMS_ASSERT(normalized_path_len + 2 < sizeof(normalized_path));
|
||||
normalized_path[normalized_path_len] = fs::StringTraits::DirectorySeparator;
|
||||
normalized_path[normalized_path_len + 1] = fs::StringTraits::NullTerminator;
|
||||
|
||||
normalized_path_len++;
|
||||
++normalized_path_len;
|
||||
}
|
||||
|
||||
/* Allocate new path. */
|
||||
this->base_path_len = normalized_path_len + 1;
|
||||
this->base_path = static_cast<char *>(std::malloc(this->base_path_len));
|
||||
this->base_path = static_cast<char *>(fs::impl::Allocate(this->base_path_len));
|
||||
R_UNLESS(this->base_path != nullptr, fs::ResultAllocationFailureInSubDirectoryFileSystem());
|
||||
|
||||
/* Copy path in. */
|
||||
std::memcpy(this->base_path, normalized_path, normalized_path_len);
|
||||
this->base_path[normalized_path_len] = StringTraits::NullTerminator;
|
||||
this->base_path[normalized_path_len] = fs::StringTraits::NullTerminator;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace ams::fssystem {
|
||||
/* Normalize it. */
|
||||
const size_t prefix_size = this->base_path_len - 2;
|
||||
size_t normalized_len;
|
||||
return PathTool::Normalize(out + prefix_size, &normalized_len, relative_path, out_size - prefix_size, this->IsUncPreserved());
|
||||
return fs::PathNormalizer::Normalize(out + prefix_size, std::addressof(normalized_len), relative_path, out_size - prefix_size, this->IsUncPreserved(), false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,15 +31,15 @@ namespace ams::fssystem {
|
||||
/* Normalize the path. */
|
||||
char normalized_path[fs::EntryNameLengthMax + 1];
|
||||
size_t normalized_path_len;
|
||||
R_TRY(PathTool::Normalize(normalized_path, &normalized_path_len, path, sizeof(normalized_path)));
|
||||
R_TRY(fs::PathNormalizer::Normalize(normalized_path, std::addressof(normalized_path_len), path, sizeof(normalized_path)));
|
||||
|
||||
/* Repeatedly call CreateDirectory on each directory leading to the target. */
|
||||
for (size_t i = 1; i < normalized_path_len; i++) {
|
||||
/* If we detect a separator, create the directory. */
|
||||
if (PathTool::IsSeparator(normalized_path[i])) {
|
||||
normalized_path[i] = StringTraits::NullTerminator;
|
||||
if (fs::PathNormalizer::IsSeparator(normalized_path[i])) {
|
||||
normalized_path[i] = fs::StringTraits::NullTerminator;
|
||||
R_TRY(EnsureDirectory(fs, normalized_path));
|
||||
normalized_path[i] = StringTraits::DirectorySeparator;
|
||||
normalized_path[i] = fs::StringTraits::DirectorySeparator;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,10 +120,10 @@ namespace ams::fssystem {
|
||||
|
||||
/* Find previous separator, add null terminator */
|
||||
char *cur = &dst_path_buf[len - 2];
|
||||
while (!PathTool::IsSeparator(*cur) && cur > dst_path_buf) {
|
||||
while (!fs::PathNormalizer::IsSeparator(*cur) && cur > dst_path_buf) {
|
||||
cur--;
|
||||
}
|
||||
cur[1] = StringTraits::NullTerminator;
|
||||
cur[1] = fs::StringTraits::NullTerminator;
|
||||
|
||||
return ResultSuccess();
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user