Example #1
0
File_SDMC::File_SDMC(const Archive_SDMC* archive, const Path& path, const Mode mode) {
    // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass
    // the root directory we set while opening the archive.
    // For example, opening /../../etc/passwd can give the emulated program your users list.
    this->path = archive->GetMountPoint() + path.AsString();
    this->mode.hex = mode.hex;
}
Example #2
0
PathParser::PathParser(const Path& path) {
    if (path.GetType() != LowPathType::Char && path.GetType() != LowPathType::Wchar) {
        is_valid = false;
        return;
    }

    auto path_string = path.AsString();
    if (path_string.size() == 0 || path_string[0] != '/') {
        is_valid = false;
        return;
    }

    // Filter out invalid characters for the host system.
    // Although some of these characters are valid on 3DS, they are unlikely to be used by games.
    if (std::find_if(path_string.begin(), path_string.end(), [](char c) {
            static const std::set<char> invalid_chars{'<', '>', '\\', '|', ':', '\"', '*', '?'};
            return invalid_chars.find(c) != invalid_chars.end();
        }) != path_string.end()) {
        is_valid = false;
        return;
    }

    Common::SplitString(path_string, '/', path_sequence);

    auto begin = path_sequence.begin();
    auto end = path_sequence.end();
    end = std::remove_if(begin, end, [](std::string& str) { return str == "" || str == "."; });
    path_sequence = std::vector<std::string>(begin, end);

    // checks if the path is out of bounds.
    int level = 0;
    for (auto& node : path_sequence) {
        if (node == "..") {
            --level;
            if (level < 0) {
                is_valid = false;
                return;
            }
        } else {
            ++level;
        }
    }

    is_valid = true;
    is_root = level == 0;
}
Example #3
0
ResultCode SaveDataArchive::CreateDirectory(const Path& path) const {
    const PathParser path_parser(path);

    if (!path_parser.IsValid()) {
        LOG_ERROR(Service_FS, "Invalid path {}", path.DebugStr());
        return ERROR_INVALID_PATH;
    }

    const auto full_path = path_parser.BuildHostPath(mount_point);

    switch (path_parser.GetHostStatus(mount_point)) {
    case PathParser::InvalidMountPoint:
        LOG_CRITICAL(Service_FS, "(unreachable) Invalid mount point {}", mount_point);
        return ERROR_FILE_NOT_FOUND;
    case PathParser::PathNotFound:
        LOG_ERROR(Service_FS, "Path not found {}", full_path);
        return ERROR_PATH_NOT_FOUND;
    case PathParser::FileInPath:
        LOG_ERROR(Service_FS, "Unexpected file in path {}", full_path);
        return ERROR_UNEXPECTED_FILE_OR_DIRECTORY;
    case PathParser::DirectoryFound:
    case PathParser::FileFound:
        LOG_ERROR(Service_FS, "{} already exists", full_path);
        return ERROR_DIRECTORY_ALREADY_EXISTS;
    case PathParser::NotFound:
        break; // Expected 'success' case
    }

    if (FileUtil::CreateDir(mount_point + path.AsString())) {
        return RESULT_SUCCESS;
    }

    LOG_CRITICAL(Service_FS, "(unreachable) Unknown error creating {}", mount_point);
    return ResultCode(ErrorDescription::NoData, ErrorModule::FS, ErrorSummary::Canceled,
                      ErrorLevel::Status);
}
Example #4
0
/**
 * Create a directory specified by its path
 * @param path Path relative to the archive
 * @return Whether the directory could be created
 */
bool Archive_SDMC::CreateDirectory(const Path& path) const {
    return FileUtil::CreateDir(GetMountPoint() + path.AsString());
}
Example #5
0
bool DiskArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const {
    return FileUtil::Rename(mount_point + src_path.AsString(), mount_point + dest_path.AsString());
}
Example #6
0
bool DiskArchive::CreateDirectory(const Path& path) const {
    return FileUtil::CreateDir(mount_point + path.AsString());
}
Example #7
0
bool DiskArchive::DeleteFile(const Path& path) const {
    return FileUtil::Delete(mount_point + path.AsString());
}
Example #8
0
DiskDirectory::DiskDirectory(const DiskArchive& archive, const Path& path) : directory() {
    // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass
    // the root directory we set while opening the archive.
    // For example, opening /../../usr/bin can give the emulated program your installed programs.
    this->path = archive.mount_point + path.AsString();
}