mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-04-22 04:24:48 +00:00
fs: Add wrappers needed for ncm
This commit is contained in:
parent
797815b838
commit
0fe4e2950e
17 changed files with 798 additions and 22 deletions
|
@ -29,4 +29,9 @@
|
|||
#include "fs/fs_mount.hpp"
|
||||
#include "fs/fs_path_tool.hpp"
|
||||
#include "fs/fs_path_utils.hpp"
|
||||
#include "fs/fs_content_storage.hpp"
|
||||
#include "fs/fs_game_card.hpp"
|
||||
#include "fs/fs_sd_card.hpp"
|
||||
#include "fs/fs_save_data_types.hpp"
|
||||
#include "fs/fs_save_data_management.hpp"
|
||||
#include "fs/fs_system_save_data.hpp"
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "fs_common.hpp"
|
||||
|
||||
namespace ams::fs {
|
||||
|
||||
enum class ContentStorageId : u32 {
|
||||
System = 0,
|
||||
User = 1,
|
||||
SdCard = 2,
|
||||
};
|
||||
|
||||
constexpr inline const char * const ContentStorageDirectoryName = "Contents";
|
||||
|
||||
const char *GetContentStorageMountName(ContentStorageId id);
|
||||
|
||||
Result MountContentStorage(ContentStorageId id);
|
||||
Result MountContentStorage(const char *name, ContentStorageId id);
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "fs_common.hpp"
|
||||
|
||||
namespace ams::fs {
|
||||
|
||||
enum class GameCardPartition {
|
||||
Update = 0,
|
||||
Normal = 1,
|
||||
Secure = 2,
|
||||
Logo = 3,
|
||||
};
|
||||
|
||||
enum class GameCardPartitionRaw {
|
||||
NormalReadable,
|
||||
SecureReadable,
|
||||
RootWriteable,
|
||||
};
|
||||
|
||||
enum class GameCardAttribute : u8 {
|
||||
AutoBootFlag = (1 << 0),
|
||||
HistoryEraseFlag = (1 << 1),
|
||||
RepairToolFlag = (1 << 2),
|
||||
DifferentRegionCupToTerraDeviceFlag = (1 << 3),
|
||||
DifferentRegionCupToGlobalDeviceFlag = (1 << 4),
|
||||
};
|
||||
|
||||
using GameCardHandle = u32;
|
||||
|
||||
Result GetGameCardHandle(GameCardHandle *out);
|
||||
Result MountGameCardPartition(const char *name, GameCardHandle handle, GameCardPartition partition);
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "fs_common.hpp"
|
||||
#include "fs_save_data_types.hpp"
|
||||
|
||||
namespace ams::fs {
|
||||
|
||||
Result GetSaveDataFlags(u32 *out, SaveDataId id);
|
||||
Result GetSaveDataFlags(u32 *out, SaveDataSpaceId space_id, SaveDataId id);
|
||||
Result SetSaveDataFlags(SaveDataId id, SaveDataSpaceId space_id, u32 flags);
|
||||
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "fs_common.hpp"
|
||||
|
||||
namespace ams::fs {
|
||||
|
||||
using SaveDataId = u64;
|
||||
using SystemSaveDataId = u64;
|
||||
using SystemBcatSaveDataId = SystemSaveDataId;
|
||||
|
||||
enum class SaveDataSpaceId : u8 {
|
||||
System = 0,
|
||||
User = 1,
|
||||
SdSystem = 2,
|
||||
Temporary = 3,
|
||||
SdUser = 4,
|
||||
|
||||
ProperSystem = 100,
|
||||
SafeMode = 101,
|
||||
};
|
||||
|
||||
enum class SaveDataType : u8 {
|
||||
System = 0,
|
||||
Account = 1,
|
||||
Bcat = 2,
|
||||
Device = 3,
|
||||
Temporary = 4,
|
||||
Cache = 5,
|
||||
SystemBcat = 6,
|
||||
};
|
||||
|
||||
enum class SaveDataRank : u8 {
|
||||
Primary = 0,
|
||||
Secondary = 1,
|
||||
};
|
||||
|
||||
struct UserId {
|
||||
u64 data[2];
|
||||
};
|
||||
static_assert(std::is_pod<UserId>::value);
|
||||
|
||||
constexpr inline bool operator<(const UserId &lhs, const UserId &rhs) {
|
||||
if (lhs.data[0] < rhs.data[0]) {
|
||||
return true;
|
||||
} else if (lhs.data[0] == rhs.data[0] && lhs.data[1] < rhs.data[1]) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline bool operator==(const UserId &lhs, const UserId &rhs) {
|
||||
return lhs.data[0] == rhs.data[0] && lhs.data[1] == rhs.data[1];
|
||||
}
|
||||
|
||||
constexpr inline bool operator!=(const UserId &lhs, const UserId &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
constexpr inline SystemSaveDataId InvalidSystemSaveDataId = 0;
|
||||
constexpr inline UserId InvalidUserId = {};
|
||||
|
||||
struct SaveDataCreationInfo {
|
||||
s64 size;
|
||||
s64 journal_size;
|
||||
s64 block_size;
|
||||
u64 owner_id;
|
||||
u32 flags;
|
||||
SaveDataSpaceId space_id;
|
||||
bool pseudo;
|
||||
u8 reserved[0x1A];
|
||||
};
|
||||
static_assert(std::is_pod<SaveDataCreationInfo>::value);
|
||||
static_assert(sizeof(SaveDataCreationInfo) == 0x40);
|
||||
|
||||
struct SaveDataAttribute {
|
||||
ncm::ProgramId program_id;
|
||||
UserId user_id;
|
||||
SystemSaveDataId system_save_data_id;
|
||||
SaveDataType type;
|
||||
SaveDataRank rank;
|
||||
u16 index;
|
||||
u8 reserved[0x1C];
|
||||
|
||||
static constexpr SaveDataAttribute Make(ncm::ProgramId program_id, SaveDataType type, UserId user_id, SystemSaveDataId system_save_data_id, u16 index, SaveDataRank rank) {
|
||||
return {
|
||||
.program_id = program_id,
|
||||
.user_id = user_id,
|
||||
.system_save_data_id = system_save_data_id,
|
||||
.type = type,
|
||||
.rank = rank,
|
||||
.index = index,
|
||||
};
|
||||
}
|
||||
|
||||
static constexpr SaveDataAttribute Make(ncm::ProgramId program_id, SaveDataType type, UserId user_id, SystemSaveDataId system_save_data_id, u16 index) {
|
||||
return Make(program_id, type, user_id, system_save_data_id, index, SaveDataRank::Primary);
|
||||
}
|
||||
|
||||
static constexpr SaveDataAttribute Make(ncm::ProgramId program_id, SaveDataType type, UserId user_id, SystemSaveDataId system_save_data_id) {
|
||||
return Make(program_id, type, user_id, system_save_data_id, 0, SaveDataRank::Primary);
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(SaveDataAttribute) == 0x40);
|
||||
static_assert(std::is_trivially_destructible<SaveDataAttribute>::value);
|
||||
|
||||
constexpr inline bool operator<(const SaveDataAttribute &lhs, const SaveDataAttribute &rhs) {
|
||||
#define FS_SDA_CHECK_FIELD(FIELD) \
|
||||
if (lhs.FIELD < rhs.FIELD) { \
|
||||
return true; \
|
||||
} else if (lhs.FIELD != rhs.FIELD) { \
|
||||
return false; \
|
||||
}
|
||||
|
||||
FS_SDA_CHECK_FIELD(program_id);
|
||||
FS_SDA_CHECK_FIELD(user_id);
|
||||
FS_SDA_CHECK_FIELD(system_save_data_id);
|
||||
FS_SDA_CHECK_FIELD(index);
|
||||
FS_SDA_CHECK_FIELD(rank);
|
||||
return false;
|
||||
|
||||
#undef FS_SDA_CHECK_FIELD
|
||||
}
|
||||
|
||||
constexpr inline bool operator==(const SaveDataAttribute &lhs, const SaveDataAttribute &rhs) {
|
||||
return lhs.program_id == rhs.program_id &&
|
||||
lhs.user_id == rhs.user_id &&
|
||||
lhs.system_save_data_id == rhs.system_save_data_id &&
|
||||
lhs.type == rhs.type &&
|
||||
lhs.rank == rhs.rank &&
|
||||
lhs.index == rhs.index;
|
||||
}
|
||||
|
||||
constexpr inline bool operator!=(const SaveDataAttribute &lhs, const SaveDataAttribute &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
constexpr inline size_t DefaultSaveDataBlockSize = 16_KB;
|
||||
|
||||
struct SaveDataExtraData {
|
||||
SaveDataAttribute attr;
|
||||
u64 owner_id;
|
||||
s64 timestamp;
|
||||
u32 flags;
|
||||
u8 pad[4];
|
||||
s64 available_size;
|
||||
s64 journal_size;
|
||||
s64 commit_id;
|
||||
u8 unused[0x190];
|
||||
};
|
||||
static_assert(sizeof(SaveDataExtraData) == 0x200);
|
||||
static_assert(std::is_pod<SaveDataExtraData>::value);
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "fs_common.hpp"
|
||||
#include "fs_save_data_types.hpp"
|
||||
|
||||
namespace ams::fs {
|
||||
|
||||
void DisableAutoSaveDataCreation();
|
||||
|
||||
Result CreateSystemSaveData(SystemSaveDataId save_id, s64 size, s64 journal_size, u32 flags);
|
||||
Result CreateSystemSaveData(SystemSaveDataId save_id, u64 owner_id, s64 size, s64 journal_size, u32 flags);
|
||||
Result CreateSystemSaveData(SaveDataSpaceId space_id, SystemSaveDataId save_id, u64 owner_id, s64 size, s64 journal_size, u32 flags);
|
||||
|
||||
Result CreateSystemSaveData(SystemSaveDataId save_id, UserId user_id, s64 size, s64 journal_size, u32 flags);
|
||||
Result CreateSystemSaveData(SystemSaveDataId save_id, UserId user_id, u64 owner_id, s64 size, s64 journal_size, u32 flags);
|
||||
Result CreateSystemSaveData(SaveDataSpaceId space_id, SystemSaveDataId save_id, UserId user_id, u64 owner_id, s64 size, s64 journal_size, u32 flags);
|
||||
|
||||
Result MountSystemSaveData(const char *name, SystemSaveDataId id);
|
||||
Result MountSystemSaveData(const char *name, SaveDataSpaceId space_id, SystemSaveDataId id);
|
||||
|
||||
Result MountSystemSaveData(const char *name, SystemSaveDataId id, UserId user_id);
|
||||
Result MountSystemSaveData(const char *name, SaveDataSpaceId space_id, SystemSaveDataId id, UserId user_id);
|
||||
|
||||
Result DeleteSystemSaveData(SaveDataSpaceId space_id, SystemSaveDataId id, UserId user_id);
|
||||
|
||||
}
|
|
@ -18,26 +18,33 @@
|
|||
namespace ams::fs::impl {
|
||||
|
||||
/* Delimiting of mount names. */
|
||||
constexpr inline const char ReservedMountNamePrefixCharacter = '@';
|
||||
constexpr inline const char *MountNameDelimiter = ":/";
|
||||
constexpr inline const char ReservedMountNamePrefixCharacter = '@';
|
||||
constexpr inline const char * const MountNameDelimiter = ":/";
|
||||
|
||||
/* Filesystem names. */
|
||||
constexpr inline const char *HostRootFileSystemMountName = "@Host";
|
||||
constexpr inline const char *SdCardFileSystemMountName = "@Sdcard";
|
||||
constexpr inline const char *GameCardFileSystemMountName = "@Gc";
|
||||
constexpr inline const char * const HostRootFileSystemMountName = "@Host";
|
||||
constexpr inline const char * const SdCardFileSystemMountName = "@Sdcard";
|
||||
constexpr inline const char * const GameCardFileSystemMountName = "@Gc";
|
||||
|
||||
constexpr inline size_t GameCardFileSystemMountNameSuffixLength = 1;
|
||||
constexpr inline const char *GameCardFileSystemMountNameUpdateSuffix = "U";
|
||||
constexpr inline const char *GameCardFileSystemMountNameNormalSuffix = "N";
|
||||
constexpr inline const char *GameCardFileSystemMountNameSecureSuffix = "S";
|
||||
constexpr inline size_t GameCardFileSystemMountNameSuffixLength = 1;
|
||||
|
||||
constexpr inline const char * const GameCardFileSystemMountNameUpdateSuffix = "U";
|
||||
constexpr inline const char * const GameCardFileSystemMountNameNormalSuffix = "N";
|
||||
constexpr inline const char * const GameCardFileSystemMountNameSecureSuffix = "S";
|
||||
|
||||
/* Built-in storage names. */
|
||||
constexpr inline const char *BisCalibrationFilePartitionMountName = "@CalibFile";
|
||||
constexpr inline const char *BisSafeModePartitionMountName = "@Safe";
|
||||
constexpr inline const char *BisUserPartitionMountName = "@User";
|
||||
constexpr inline const char *BisSystemPartitionMountName = "@System";
|
||||
constexpr inline const char * const BisCalibrationFilePartitionMountName = "@CalibFile";
|
||||
constexpr inline const char * const BisSafeModePartitionMountName = "@Safe";
|
||||
constexpr inline const char * const BisUserPartitionMountName = "@User";
|
||||
constexpr inline const char * const BisSystemPartitionMountName = "@System";
|
||||
|
||||
/* Content storage names. */
|
||||
constexpr inline const char * const ContentStorageSystemMountName = "@SystemContent";
|
||||
constexpr inline const char * const ContentStorageUserMountName = "@UserContent";
|
||||
constexpr inline const char * const ContentStorageSdCardMountName = "@SdCardContent";
|
||||
|
||||
|
||||
/* Registered update partition. */
|
||||
constexpr inline const char *RegisteredUpdatePartitionMountName = "@RegUpdate";
|
||||
constexpr inline const char * const RegisteredUpdatePartitionMountName = "@RegUpdate";
|
||||
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace ams::kvdb {
|
|||
}
|
||||
|
||||
AutoBuffer& operator=(AutoBuffer &&rhs) {
|
||||
rhs.Swap(*this);
|
||||
AutoBuffer(std::move(rhs)).Swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -70,9 +70,8 @@ namespace ams::kvdb {
|
|||
|
||||
/* Allocate a buffer. */
|
||||
this->buffer = static_cast<u8 *>(std::malloc(size));
|
||||
if (this->buffer == nullptr) {
|
||||
return ResultAllocationFailed();
|
||||
}
|
||||
R_UNLESS(this->buffer != nullptr, ResultAllocationFailed());
|
||||
|
||||
this->size = size;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "ncm/ncm_types.hpp"
|
||||
#include "ncm/ncm_auto_buffer.hpp"
|
||||
#include "ncm/ncm_content_meta.hpp"
|
||||
#include "ncm/ncm_content_meta_database.hpp"
|
||||
#include "ncm/ncm_content_storage.hpp"
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
class AutoBuffer {
|
||||
NON_COPYABLE(AutoBuffer);
|
||||
private:
|
||||
u8 *buffer;
|
||||
size_t size;
|
||||
public:
|
||||
AutoBuffer() : buffer(nullptr), size(0) { /* ... */ }
|
||||
|
||||
~AutoBuffer() {
|
||||
this->Reset();
|
||||
}
|
||||
|
||||
AutoBuffer(AutoBuffer &&rhs) {
|
||||
this->buffer = rhs.buffer;
|
||||
this->size = rhs.size;
|
||||
rhs.buffer = nullptr;
|
||||
rhs.size = 0;
|
||||
}
|
||||
|
||||
AutoBuffer& operator=(AutoBuffer &&rhs) {
|
||||
AutoBuffer(std::move(rhs)).Swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Swap(AutoBuffer &rhs) {
|
||||
std::swap(this->buffer, rhs.buffer);
|
||||
std::swap(this->size, rhs.size);
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
if (this->buffer != nullptr) {
|
||||
std::free(this->buffer);
|
||||
this->buffer = nullptr;
|
||||
this->size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
u8 *Get() const {
|
||||
return this->buffer;
|
||||
}
|
||||
|
||||
size_t GetSize() const {
|
||||
return this->size;
|
||||
}
|
||||
|
||||
Result Initialize(size_t size) {
|
||||
/* Check that we're not already initialized. */
|
||||
AMS_ABORT_UNLESS(this->buffer == nullptr);
|
||||
|
||||
/* Allocate a buffer. */
|
||||
this->buffer = static_cast<u8 *>(std::malloc(size));
|
||||
R_UNLESS(this->buffer != nullptr, ResultAllocationFailed());
|
||||
|
||||
this->size = size;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result Initialize(const void *buf, size_t size) {
|
||||
/* Create a new buffer of the right size. */
|
||||
R_TRY(this->Initialize(size));
|
||||
|
||||
/* Copy the input data in. */
|
||||
std::memcpy(this->buffer, buf, size);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
};
|
||||
}
|
|
@ -55,10 +55,6 @@ namespace ams::ncm {
|
|||
Unknown = 7,
|
||||
};
|
||||
|
||||
struct MountName {
|
||||
char name[0x10];
|
||||
};
|
||||
|
||||
struct alignas(8) PlaceHolderId {
|
||||
util::Uuid uuid;
|
||||
|
||||
|
|
93
libraries/libstratosphere/source/fs/fs_content_storage.cpp
Normal file
93
libraries/libstratosphere/source/fs/fs_content_storage.cpp
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "fsa/fs_mount_utils.hpp"
|
||||
|
||||
namespace ams::fs {
|
||||
|
||||
namespace {
|
||||
|
||||
class ContentStorageCommonMountNameGenerator : public fsa::ICommonMountNameGenerator, public impl::Newable {
|
||||
private:
|
||||
const ContentStorageId id;
|
||||
public:
|
||||
explicit ContentStorageCommonMountNameGenerator(ContentStorageId i) : id(i) { /* ... */ }
|
||||
|
||||
virtual Result GenerateCommonMountName(char *dst, size_t dst_size) override {
|
||||
/* Determine how much space we need. */
|
||||
const size_t needed_size = strnlen(GetContentStorageMountName(id), MountNameLengthMax) + 2;
|
||||
AMS_ABORT_UNLESS(dst_size >= needed_size);
|
||||
|
||||
/* Generate the name. */
|
||||
auto size = std::snprintf(dst, dst_size, "%s:", GetContentStorageMountName(id));
|
||||
AMS_ASSERT(static_cast<size_t>(size) == needed_size - 1);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
const char *GetContentStorageMountName(ContentStorageId id) {
|
||||
switch (id) {
|
||||
case ContentStorageId::System: return impl::ContentStorageSystemMountName;
|
||||
case ContentStorageId::User: return impl::ContentStorageUserMountName;
|
||||
case ContentStorageId::SdCard: return impl::ContentStorageSdCardMountName;
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
Result MountContentStorage(ContentStorageId id) {
|
||||
return MountContentStorage(GetContentStorageMountName(id), id);
|
||||
}
|
||||
|
||||
Result MountContentStorage(const char *name, ContentStorageId id) {
|
||||
/* Validate the mount name. */
|
||||
R_TRY(impl::CheckMountNameAllowingReserved(name));
|
||||
|
||||
/* It can take some time for the system partition to be ready (if it's on the SD card). */
|
||||
/* Thus, we will retry up to 10 times, waiting one second each time. */
|
||||
constexpr size_t MaxRetries = 10;
|
||||
constexpr u64 RetryInterval = 1'000'000'000ul;
|
||||
|
||||
/* Mount the content storage, use libnx bindings. */
|
||||
::FsFileSystem fs;
|
||||
for (size_t i = 0; i < MaxRetries; i++) {
|
||||
R_TRY_CATCH(fsOpenContentStorageFileSystem(std::addressof(fs), static_cast<::FsContentStorageId>(id))) {
|
||||
R_CATCH(fs::ResultSystemPartitionNotReady) {
|
||||
if (i < MaxRetries - 1) {
|
||||
/* TODO: os::SleepThread */
|
||||
svcSleepThread(RetryInterval);
|
||||
} else {
|
||||
return fs::ResultSystemPartitionNotReady();
|
||||
}
|
||||
}
|
||||
} R_END_TRY_CATCH;
|
||||
}
|
||||
|
||||
/* Allocate a new filesystem wrapper. */
|
||||
std::unique_ptr<fsa::IFileSystem> fsa(new RemoteFileSystem(fs));
|
||||
R_UNLESS(fsa != nullptr, fs::ResultAllocationFailureInContentStorageA());
|
||||
|
||||
/* Allocate a new mountname generator. */
|
||||
std::unique_ptr<ContentStorageCommonMountNameGenerator> generator(new ContentStorageCommonMountNameGenerator(id));
|
||||
R_UNLESS(generator != nullptr, fs::ResultAllocationFailureInContentStorageB());
|
||||
|
||||
/* Register. */
|
||||
return fsa::Register(name, std::move(fsa), std::move(generator));
|
||||
}
|
||||
|
||||
}
|
87
libraries/libstratosphere/source/fs/fs_game_card.cpp
Normal file
87
libraries/libstratosphere/source/fs/fs_game_card.cpp
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "fsa/fs_mount_utils.hpp"
|
||||
|
||||
namespace ams::fs {
|
||||
|
||||
namespace {
|
||||
|
||||
const char *GetGameCardMountNameSuffix(GameCardPartition which) {
|
||||
switch (which) {
|
||||
case GameCardPartition::Update: return impl::GameCardFileSystemMountNameUpdateSuffix;
|
||||
case GameCardPartition::Normal: return impl::GameCardFileSystemMountNameNormalSuffix;
|
||||
case GameCardPartition::Secure: return impl::GameCardFileSystemMountNameSecureSuffix;
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
class GameCardCommonMountNameGenerator : public fsa::ICommonMountNameGenerator, public impl::Newable {
|
||||
private:
|
||||
const GameCardHandle handle;
|
||||
const GameCardPartition partition;
|
||||
public:
|
||||
explicit GameCardCommonMountNameGenerator(GameCardHandle h, GameCardPartition p) : handle(h), partition(p) { /* ... */ }
|
||||
|
||||
virtual Result GenerateCommonMountName(char *dst, size_t dst_size) override {
|
||||
/* Determine how much space we need. */
|
||||
const size_t needed_size = strnlen(impl::GameCardFileSystemMountName, MountNameLengthMax) + strnlen(GetGameCardMountNameSuffix(this->partition), MountNameLengthMax) + sizeof(GameCardHandle) * 2 + 2;
|
||||
AMS_ABORT_UNLESS(dst_size >= needed_size);
|
||||
|
||||
/* Generate the name. */
|
||||
auto size = std::snprintf(dst, dst_size, "%s%s%08x:", impl::GameCardFileSystemMountName, GetGameCardMountNameSuffix(this->partition), this->handle);
|
||||
AMS_ASSERT(static_cast<size_t>(size) == needed_size - 1);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Result GetGameCardHandle(GameCardHandle *out) {
|
||||
/* TODO: fs::DeviceOperator */
|
||||
/* Open a DeviceOperator. */
|
||||
::FsDeviceOperator d;
|
||||
R_TRY(fsOpenDeviceOperator(std::addressof(d)));
|
||||
ON_SCOPE_EXIT { fsDeviceOperatorClose(std::addressof(d)); };
|
||||
|
||||
/* Get the handle. */
|
||||
static_assert(sizeof(GameCardHandle) == sizeof(::FsGameCardHandle));
|
||||
return fsDeviceOperatorGetGameCardHandle(std::addressof(d), reinterpret_cast<::FsGameCardHandle *>(out));
|
||||
}
|
||||
|
||||
Result MountGameCardPartition(const char *name, GameCardHandle handle, GameCardPartition partition) {
|
||||
/* Validate the mount name. */
|
||||
R_TRY(impl::CheckMountNameAllowingReserved(name));
|
||||
|
||||
/* Open gamecard filesystem. This uses libnx bindings. */
|
||||
::FsFileSystem fs;
|
||||
const ::FsGameCardHandle _hnd = {handle};
|
||||
R_TRY(fsOpenGameCardFileSystem(std::addressof(fs), std::addressof(_hnd), static_cast<::FsGameCardPartition>(partition)));
|
||||
|
||||
/* Allocate a new filesystem wrapper. */
|
||||
std::unique_ptr<fsa::IFileSystem> fsa(new RemoteFileSystem(fs));
|
||||
R_UNLESS(fsa != nullptr, fs::ResultAllocationFailureInGameCardC());
|
||||
|
||||
/* Allocate a new mountname generator. */
|
||||
std::unique_ptr<GameCardCommonMountNameGenerator> generator(new GameCardCommonMountNameGenerator(handle, partition));
|
||||
R_UNLESS(generator != nullptr, fs::ResultAllocationFailureInGameCardD());
|
||||
|
||||
/* Register. */
|
||||
return fsa::Register(name, std::move(fsa), std::move(generator));
|
||||
}
|
||||
|
||||
}
|
110
libraries/libstratosphere/source/fs/fs_save_data_management.cpp
Normal file
110
libraries/libstratosphere/source/fs/fs_save_data_management.cpp
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "fsa/fs_mount_utils.hpp"
|
||||
|
||||
namespace ams::fs {
|
||||
|
||||
namespace impl {
|
||||
|
||||
Result ReadSaveDataFileSystemExtraData(SaveDataExtraData *out, SaveDataId id) {
|
||||
return fsReadSaveDataFileSystemExtraData(out, sizeof(*out), id);
|
||||
}
|
||||
|
||||
Result ReadSaveDataFileSystemExtraData(SaveDataExtraData *out, SaveDataSpaceId space_id, SaveDataId id) {
|
||||
return fsReadSaveDataFileSystemExtraDataBySaveDataSpaceId(out, sizeof(*out), static_cast<::FsSaveDataSpaceId>(space_id), id);
|
||||
}
|
||||
|
||||
Result WriteSaveDataFileSystemExtraData(SaveDataSpaceId space_id, SaveDataId id, const SaveDataExtraData &extra_data) {
|
||||
return fsWriteSaveDataFileSystemExtraData(std::addressof(extra_data), sizeof(extra_data), static_cast<::FsSaveDataSpaceId>(space_id), id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DisableAutoSaveDataCreation() {
|
||||
/* Use libnx binding. */
|
||||
R_ABORT_UNLESS(fsDisableAutoSaveDataCreation());
|
||||
}
|
||||
|
||||
Result CreateSystemSaveData(SaveDataSpaceId space_id, SystemSaveDataId save_id, UserId user_id, u64 owner_id, s64 size, s64 journal_size, u32 flags) {
|
||||
const auto attribute = SaveDataAttribute::Make(ncm::InvalidProgramId, SaveDataType::System, user_id, save_id);
|
||||
const SaveDataCreationInfo info = {
|
||||
.size = size,
|
||||
.journal_size = journal_size,
|
||||
.block_size = DefaultSaveDataBlockSize,
|
||||
.owner_id = owner_id,
|
||||
.flags = flags,
|
||||
.space_id = space_id,
|
||||
.pseudo = false,
|
||||
};
|
||||
|
||||
static_assert(sizeof(SaveDataAttribute) == sizeof(::FsSaveDataAttribute));
|
||||
static_assert(sizeof(SaveDataCreationInfo) == sizeof(::FsSaveDataCreationInfo));
|
||||
return fsCreateSaveDataFileSystemBySystemSaveDataId(reinterpret_cast<const ::FsSaveDataAttribute *>(std::addressof(attribute)), reinterpret_cast<const ::FsSaveDataCreationInfo *>(std::addressof(info)));
|
||||
}
|
||||
|
||||
Result CreateSystemSaveData(SystemSaveDataId save_id, s64 size, s64 journal_size, u32 flags) {
|
||||
return CreateSystemSaveData(SaveDataSpaceId::System, save_id, InvalidUserId, 0, size, journal_size, flags);
|
||||
}
|
||||
|
||||
Result CreateSystemSaveData(SystemSaveDataId save_id, u64 owner_id, s64 size, s64 journal_size, u32 flags) {
|
||||
return CreateSystemSaveData(SaveDataSpaceId::System, save_id, InvalidUserId, owner_id, size, journal_size, flags);
|
||||
}
|
||||
|
||||
Result CreateSystemSaveData(SaveDataSpaceId space_id, SystemSaveDataId save_id, u64 owner_id, s64 size, s64 journal_size, u32 flags) {
|
||||
return CreateSystemSaveData(space_id, save_id, InvalidUserId, owner_id, size, journal_size, flags);
|
||||
}
|
||||
|
||||
Result CreateSystemSaveData(SystemSaveDataId save_id, UserId user_id, s64 size, s64 journal_size, u32 flags) {
|
||||
return CreateSystemSaveData(SaveDataSpaceId::System, save_id, user_id, 0, size, journal_size, flags);
|
||||
}
|
||||
|
||||
Result CreateSystemSaveData(SystemSaveDataId save_id, UserId user_id, u64 owner_id, s64 size, s64 journal_size, u32 flags) {
|
||||
return CreateSystemSaveData(SaveDataSpaceId::System, save_id, user_id, owner_id, size, journal_size, flags);
|
||||
}
|
||||
|
||||
Result DeleteSystemSaveData(SaveDataSpaceId space_id, SystemSaveDataId id, UserId user_id) {
|
||||
const auto attribute = SaveDataAttribute::Make(ncm::InvalidProgramId, SaveDataType::System, user_id, id);
|
||||
|
||||
/* TODO: Libnx binding for DeleteSaveDataFileSystemBySaveDataAttribute */
|
||||
AMS_UNUSED(attribute);
|
||||
AMS_ABORT();
|
||||
}
|
||||
|
||||
Result GetSaveDataFlags(u32 *out, SaveDataId id) {
|
||||
SaveDataExtraData extra_data;
|
||||
R_TRY(impl::ReadSaveDataFileSystemExtraData(std::addressof(extra_data), id));
|
||||
|
||||
*out = extra_data.flags;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result GetSaveDataFlags(u32 *out, SaveDataSpaceId space_id, SaveDataId id) {
|
||||
SaveDataExtraData extra_data;
|
||||
R_TRY(impl::ReadSaveDataFileSystemExtraData(std::addressof(extra_data), space_id, id));
|
||||
|
||||
*out = extra_data.flags;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result SetSaveDataFlags(SaveDataId id, SaveDataSpaceId space_id, u32 flags) {
|
||||
SaveDataExtraData extra_data;
|
||||
R_TRY(impl::ReadSaveDataFileSystemExtraData(std::addressof(extra_data), space_id, id));
|
||||
extra_data.flags = flags;
|
||||
return impl::WriteSaveDataFileSystemExtraData(space_id, id, extra_data);
|
||||
}
|
||||
|
||||
}
|
|
@ -14,10 +14,14 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "fsa/fs_mount_utils.hpp"
|
||||
|
||||
namespace ams::fs {
|
||||
|
||||
Result MountSdCard(const char *name) {
|
||||
/* Validate the mount name. */
|
||||
R_TRY(impl::CheckMountName(name));
|
||||
|
||||
/* Open the SD card. This uses libnx bindings. */
|
||||
FsFileSystem fs;
|
||||
R_TRY(fsOpenSdCardFileSystem(std::addressof(fs)));
|
||||
|
|
61
libraries/libstratosphere/source/fs/fs_system_save_data.cpp
Normal file
61
libraries/libstratosphere/source/fs/fs_system_save_data.cpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "fsa/fs_mount_utils.hpp"
|
||||
|
||||
namespace ams::fs {
|
||||
|
||||
namespace {
|
||||
|
||||
Result MountSystemSaveDataImpl(const char *name, SaveDataSpaceId space_id, SystemSaveDataId id, UserId user_id, SaveDataType type) {
|
||||
/* Validate the mount name. */
|
||||
R_TRY(impl::CheckMountName(name));
|
||||
|
||||
/* Create the attribute. */
|
||||
const auto attribute = SaveDataAttribute::Make(ncm::InvalidProgramId, type, user_id, id);
|
||||
static_assert(sizeof(attribute) == sizeof(::FsSaveDataAttribute));
|
||||
|
||||
/* Open the filesystem, use libnx bindings. */
|
||||
::FsFileSystem fs;
|
||||
R_TRY(fsOpenSaveDataFileSystemBySystemSaveDataId(std::addressof(fs), static_cast<::FsSaveDataSpaceId>(space_id), reinterpret_cast<const ::FsSaveDataAttribute *>(std::addressof(attribute))));
|
||||
|
||||
/* Allocate a new filesystem wrapper. */
|
||||
std::unique_ptr<fsa::IFileSystem> fsa(new RemoteFileSystem(fs));
|
||||
R_UNLESS(fsa != nullptr, fs::ResultAllocationFailureInSystemSaveDataA());
|
||||
|
||||
/* Register. */
|
||||
return fsa::Register(name, std::move(fsa));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Result MountSystemSaveData(const char *name, SystemSaveDataId id) {
|
||||
return MountSystemSaveData(name, id, InvalidUserId);
|
||||
}
|
||||
|
||||
Result MountSystemSaveData(const char *name, SaveDataSpaceId space_id, SystemSaveDataId id) {
|
||||
return MountSystemSaveData(name, space_id, id, InvalidUserId);
|
||||
}
|
||||
|
||||
Result MountSystemSaveData(const char *name, SystemSaveDataId id, UserId user_id) {
|
||||
return MountSystemSaveData(name, SaveDataSpaceId::System, id, user_id);
|
||||
}
|
||||
|
||||
Result MountSystemSaveData(const char *name, SaveDataSpaceId space_id, SystemSaveDataId id, UserId user_id) {
|
||||
return MountSystemSaveDataImpl(name, space_id, id, user_id, SaveDataType::System);
|
||||
}
|
||||
|
||||
}
|
|
@ -47,11 +47,20 @@ namespace ams::fs {
|
|||
R_DEFINE_ERROR_RESULT(NotImplemented, 3001);
|
||||
R_DEFINE_ERROR_RESULT(OutOfRange, 3005);
|
||||
|
||||
R_DEFINE_ERROR_RESULT(SystemPartitionNotReady, 3100);
|
||||
|
||||
R_DEFINE_ERROR_RANGE(AllocationFailure, 3200, 3499);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemAccessorA, 3211);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemAccessorB, 3212);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInContentStorageA, 3220);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInContentStorageB, 3221);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardA, 3225);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardB, 3226);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardC, 3227);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardD, 3228);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInSdCardA, 3244);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInSdCardB, 3245);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInSystemSaveDataA, 3246);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInDirectorySaveDataFileSystem, 3321);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInSubDirectoryFileSystem, 3355);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInRegisterA, 3365);
|
||||
|
|
Loading…
Add table
Reference in a new issue