fs: update + consolidate path normalization logic

This commit is contained in:
Michael Scire
2020-12-06 19:56:45 -08:00
parent 5ef93778f6
commit 32803d9920
22 changed files with 1007 additions and 463 deletions

View File

@@ -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();

View File

@@ -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();
}

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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();
},