Revert "hoc-clk: add live vdd2, live boost clock and basic pwm dimming"

This reverts commit 15b7df8ef1.
This commit is contained in:
souldbminersmwc
2025-11-09 16:14:52 -05:00
parent 22ec140738
commit 21a3f953d7
3804 changed files with 435 additions and 570162 deletions

View File

@@ -1,191 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/common/fs_dbm_rom_types.hpp>
#include <stratosphere/fs/common/fs_dbm_rom_path_tool.hpp>
#include <stratosphere/fs/common/fs_dbm_rom_key_value_storage.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: 14.3.0.0 */
class HierarchicalRomFileTable {
public:
using Position = u32;
using StorageSizeType = u32;
struct FindPosition {
Position next_dir;
Position next_file;
};
static_assert(util::is_pod<FindPosition>::value);
using FileInfo = RomFileInfo;
static constexpr RomFileId PositionToFileId(Position pos) {
return static_cast<RomFileId>(pos);
}
static constexpr Position FileIdToPosition(RomFileId id) {
return static_cast<Position>(id);
}
private:
static constexpr inline Position InvalidPosition = ~Position();
static constexpr inline Position RootPosition = 0;
static constexpr inline size_t ReservedDirectoryCount = 1;
static constexpr RomDirectoryId PositionToDirectoryId(Position pos) {
return static_cast<RomDirectoryId>(pos);
}
static constexpr Position DirectoryIdToPosition(RomDirectoryId id) {
return static_cast<Position>(id);
}
static_assert(std::is_same<RomDirectoryId, RomFileId>::value);
struct RomDirectoryEntry {
Position next;
Position dir;
Position file;
};
static_assert(util::is_pod<RomDirectoryEntry>::value);
struct RomFileEntry {
Position next;
FileInfo info;
};
static_assert(util::is_pod<RomFileEntry>::value);
static constexpr inline u32 MaxKeyLength = RomPathTool::MaxPathLength;
template<typename ImplKeyType, typename ClientKeyType, typename ValueType>
class EntryMapTable : public KeyValueRomStorageTemplate<ImplKeyType, ValueType, MaxKeyLength> {
public:
using ImplKey = ImplKeyType;
using ClientKey = ClientKeyType;
using Value = ValueType;
using Position = HierarchicalRomFileTable::Position;
using Base = KeyValueRomStorageTemplate<ImplKeyType, ValueType, MaxKeyLength>;
public:
Result Add(Position *out, const ClientKeyType &key, const Value &value) {
R_RETURN(Base::AddInternal(out, key.key, key.Hash(), key.name.begin(), key.name.length(), value));
}
Result Get(Position *out_pos, Value *out_val, const ClientKeyType &key) {
R_RETURN(Base::GetInternal(out_pos, out_val, key.key, key.Hash(), key.name.begin(), key.name.length()));
}
Result GetByPosition(ImplKey *out_key, Value *out_val, Position pos) {
R_RETURN(Base::GetByPosition(out_key, out_val, pos));
}
Result GetByPosition(ImplKey *out_key, Value *out_val, void *out_aux, size_t *out_aux_size, Position pos) {
R_RETURN(Base::GetByPosition(out_key, out_val, out_aux, out_aux_size, pos));
}
Result SetByPosition(Position pos, const Value &value) {
R_RETURN(Base::SetByPosition(pos, value));
}
};
struct RomEntryKey {
Position parent;
bool IsEqual(const RomEntryKey &rhs, const void *aux_lhs, size_t aux_lhs_size, const void *aux_rhs, size_t aux_rhs_size) const {
if (this->parent != rhs.parent) {
return false;
}
if (aux_lhs_size != aux_rhs_size) {
return false;
}
return RomPathTool::IsEqualPath(reinterpret_cast<const RomPathChar *>(aux_lhs), reinterpret_cast<const RomPathChar *>(aux_rhs), aux_lhs_size / sizeof(RomPathChar));
}
};
static_assert(util::is_pod<RomEntryKey>::value);
struct EntryKey {
RomEntryKey key;
RomPathTool::RomEntryName name;
constexpr u32 Hash() const {
u32 hash = this->key.parent ^ 123456789;
const RomPathChar * cur = this->name.begin();
const RomPathChar * const end = this->name.end();
while (cur < end) {
const u32 c = static_cast<u32>(static_cast<std::make_unsigned<RomPathChar>::type>(*(cur++)));
hash = ((hash >> 5) | (hash << 27)) ^ c;
}
return hash;
}
};
using DirectoryEntryMapTable = EntryMapTable<RomEntryKey, EntryKey, RomDirectoryEntry>;
using FileEntryMapTable = EntryMapTable<RomEntryKey, EntryKey, RomFileEntry>;
private:
DirectoryEntryMapTable m_dir_table;
FileEntryMapTable m_file_table;
public:
static s64 QueryDirectoryEntryBucketStorageSize(StorageSizeType count);
static s64 QueryDirectoryEntrySize(StorageSizeType aux_size);
static s64 QueryFileEntryBucketStorageSize(StorageSizeType count);
static s64 QueryFileEntrySize(StorageSizeType aux_size);
static Result Format(SubStorage dir_bucket, SubStorage file_bucket);
public:
HierarchicalRomFileTable();
Result Initialize(SubStorage dir_bucket, SubStorage dir_entry, SubStorage file_bucket, SubStorage file_entry);
void Finalize();
Result CreateRootDirectory();
Result CreateDirectory(RomDirectoryId *out, const RomPathChar *path);
Result CreateFile(RomFileId *out, const RomPathChar *path, const FileInfo &info);
Result ConvertPathToDirectoryId(RomDirectoryId *out, const RomPathChar *path);
Result ConvertPathToFileId(RomFileId *out, const RomPathChar *path);
Result OpenFile(FileInfo *out, const RomPathChar *path);
Result OpenFile(FileInfo *out, RomFileId id);
Result FindOpen(FindPosition *out, const RomPathChar *path);
Result FindOpen(FindPosition *out, RomDirectoryId id);
Result FindNextDirectory(RomPathChar *out, FindPosition *find, size_t length);
Result FindNextFile(RomPathChar *out, FindPosition *find, size_t length);
Result QueryRomFileSystemSize(s64 *out_dir_entry_size, s64 *out_file_entry_size);
private:
Result GetParent(Position *out_pos, EntryKey *out_dir_key, RomDirectoryEntry *out_dir_entry, Position pos, RomPathTool::RomEntryName name, const RomPathChar *path);
Result FindParentDirectoryRecursive(Position *out_pos, EntryKey *out_dir_key, RomDirectoryEntry *out_dir_entry, RomPathTool::PathParser *parser, const RomPathChar *path);
Result FindPathRecursive(EntryKey *out_key, RomDirectoryEntry *out_dir_entry, bool is_dir, const RomPathChar *path);
Result FindDirectoryRecursive(EntryKey *out_key, RomDirectoryEntry *out_dir_entry, const RomPathChar *path);
Result FindFileRecursive(EntryKey *out_key, RomDirectoryEntry *out_dir_entry, const RomPathChar *path);
Result CheckSameEntryExists(const EntryKey &key, Result if_exists);
Result GetDirectoryEntry(Position *out_pos, RomDirectoryEntry *out_entry, const EntryKey &key);
Result GetDirectoryEntry(RomDirectoryEntry *out_entry, RomDirectoryId id);
Result GetFileEntry(Position *out_pos, RomFileEntry *out_entry, const EntryKey &key);
Result GetFileEntry(RomFileEntry *out_entry, RomFileId id);
Result OpenFile(FileInfo *out, const EntryKey &key);
Result FindOpen(FindPosition *out, const EntryKey &key);
};
}

View File

@@ -1,304 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/common/fs_dbm_rom_types.hpp>
#include <stratosphere/fs/fs_substorage.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: 14.3.0.0 */
template<typename KeyType, typename ValueType, size_t MaxAuxiliarySize>
class KeyValueRomStorageTemplate {
public:
using Key = KeyType;
using Value = ValueType;
using Position = u32;
using BucketIndex = s64;
using StorageSizeType = u32;
struct FindIndex {
BucketIndex ind;
Position pos;
};
static_assert(util::is_pod<FindIndex>::value);
private:
static constexpr inline Position InvalidPosition = ~Position();
struct Element {
Key key;
Value value;
Position next;
StorageSizeType size;
};
static_assert(util::is_pod<Element>::value);
private:
s64 m_bucket_count;
SubStorage m_bucket_storage;
SubStorage m_kv_storage;
s64 m_total_entry_size;
u32 m_entry_count;
public:
static constexpr s64 QueryBucketStorageSize(s64 num) {
return num * sizeof(Position);
}
static constexpr s64 QueryBucketCount(StorageSizeType size) {
return size / sizeof(Position);
}
static constexpr size_t QueryEntrySize(StorageSizeType aux_size) {
return util::AlignUp<size_t>(sizeof(Element) + aux_size, alignof(Element));
}
static Result Format(SubStorage bucket, StorageSizeType count) {
const Position pos = InvalidPosition;
for (auto i = 0u; i < count; i++) {
R_TRY(bucket.Write(i * sizeof(pos), std::addressof(pos), sizeof(pos)));
}
R_SUCCEED();
}
public:
constexpr KeyValueRomStorageTemplate() : m_bucket_count(), m_bucket_storage(), m_kv_storage(), m_total_entry_size(), m_entry_count() { /* ... */ }
Result Initialize(const SubStorage &bucket, s64 count, const SubStorage &kv) {
AMS_ASSERT(count > 0);
m_bucket_storage = bucket;
m_bucket_count = count;
m_kv_storage = kv;
R_SUCCEED();
}
void Finalize() {
m_bucket_storage = SubStorage();
m_bucket_count = 0;
m_kv_storage = SubStorage();
}
s64 GetTotalEntrySize() const {
return m_total_entry_size;
}
protected:
Result AddInternal(Position *out, const Key &key, u32 hash_key, const void *aux, size_t aux_size, const Value &value) {
AMS_ASSERT(out != nullptr);
AMS_ASSERT(aux != nullptr || aux_size == 0);
AMS_ASSERT(m_bucket_count > 0);
{
Position pos, prev_pos;
Element elem;
const Result find_res = this->FindInternal(std::addressof(pos), std::addressof(prev_pos), std::addressof(elem), key, hash_key, aux, aux_size);
R_UNLESS(R_FAILED(find_res), fs::ResultDbmAlreadyExists());
R_UNLESS(fs::ResultDbmKeyNotFound::Includes(find_res), find_res);
}
Position pos;
R_TRY(this->AllocateEntry(std::addressof(pos), static_cast<StorageSizeType>(aux_size)));
Position next_pos;
R_TRY(this->LinkEntry(std::addressof(next_pos), pos, hash_key));
const Element elem = { key, value, next_pos, static_cast<StorageSizeType>(aux_size) };
R_TRY(this->WriteKeyValue(std::addressof(elem), pos, aux, aux_size));
*out = pos;
m_entry_count++;
R_SUCCEED();
}
Result GetInternal(Position *out_pos, Value *out_val, const Key &key, u32 hash_key, const void *aux, size_t aux_size) {
AMS_ASSERT(out_pos != nullptr);
AMS_ASSERT(out_val != nullptr);
AMS_ASSERT(aux != nullptr);
Position pos, prev_pos;
Element elem;
R_TRY(this->FindInternal(std::addressof(pos), std::addressof(prev_pos), std::addressof(elem), key, hash_key, aux, aux_size));
*out_pos = pos;
*out_val = elem.value;
R_SUCCEED();
}
Result GetByPosition(Key *out_key, Value *out_val, Position pos) {
AMS_ASSERT(out_key != nullptr);
AMS_ASSERT(out_val != nullptr);
Element elem;
R_TRY(this->ReadKeyValue(std::addressof(elem), pos));
*out_key = elem.key;
*out_val = elem.value;
R_SUCCEED();
}
Result GetByPosition(Key *out_key, Value *out_val, void *out_aux, size_t *out_aux_size, Position pos) {
AMS_ASSERT(out_key != nullptr);
AMS_ASSERT(out_val != nullptr);
AMS_ASSERT(out_aux != nullptr);
AMS_ASSERT(out_aux_size != nullptr);
Element elem;
R_TRY(this->ReadKeyValue(std::addressof(elem), out_aux, out_aux_size, pos));
*out_key = elem.key;
*out_val = elem.value;
R_SUCCEED();
}
Result SetByPosition(Position pos, const Value &value) {
Element elem;
R_TRY(this->ReadKeyValue(std::addressof(elem), pos));
elem.value = value;
R_RETURN(this->WriteKeyValue(std::addressof(elem), pos, nullptr, 0));
}
private:
BucketIndex HashToBucket(u32 hash_key) const {
return hash_key % m_bucket_count;
}
Result FindInternal(Position *out_pos, Position *out_prev, Element *out_elem, const Key &key, u32 hash_key, const void *aux, size_t aux_size) {
AMS_ASSERT(out_pos != nullptr);
AMS_ASSERT(out_prev != nullptr);
AMS_ASSERT(out_elem != nullptr);
AMS_ASSERT(aux != nullptr || aux_size == 0);
AMS_ASSERT(m_bucket_count > 0);
*out_pos = 0;
*out_prev = 0;
const BucketIndex ind = HashToBucket(hash_key);
Position cur;
R_TRY(this->ReadBucket(std::addressof(cur), ind));
s64 kv_size;
R_TRY(m_kv_storage.GetSize(std::addressof(kv_size)));
AMS_ASSERT(cur == InvalidPosition || cur < kv_size);
R_UNLESS(cur != InvalidPosition, fs::ResultDbmKeyNotFound());
auto buf = ::ams::fs::impl::MakeUnique<u8[]>(MaxAuxiliarySize);
R_UNLESS(buf != nullptr, fs::ResultAllocationMemoryFailedMakeUnique());
while (true) {
size_t cur_aux_size;
R_TRY(this->ReadKeyValue(out_elem, buf.get(), std::addressof(cur_aux_size), cur));
if (key.IsEqual(out_elem->key, aux, aux_size, buf.get(), cur_aux_size)) {
*out_pos = cur;
R_SUCCEED();
}
*out_prev = cur;
cur = out_elem->next;
R_UNLESS(cur != InvalidPosition, fs::ResultDbmKeyNotFound());
}
}
Result AllocateEntry(Position *out, StorageSizeType aux_size) {
AMS_ASSERT(out != nullptr);
s64 kv_size;
R_TRY(m_kv_storage.GetSize(std::addressof(kv_size)));
const size_t end_pos = m_total_entry_size + sizeof(Element) + static_cast<size_t>(aux_size);
R_UNLESS(end_pos <= static_cast<size_t>(kv_size), fs::ResultDbmKeyFull());
*out = static_cast<Position>(m_total_entry_size);
m_total_entry_size = util::AlignUp<s64>(static_cast<s64>(end_pos), alignof(Position));
R_SUCCEED();
}
Result LinkEntry(Position *out, Position pos, u32 hash_key) {
AMS_ASSERT(out != nullptr);
const BucketIndex ind = HashToBucket(hash_key);
Position next;
R_TRY(this->ReadBucket(std::addressof(next), ind));
s64 kv_size;
R_TRY(m_kv_storage.GetSize(std::addressof(kv_size)));
AMS_ASSERT(next == InvalidPosition || next < kv_size);
R_TRY(this->WriteBucket(pos, ind));
*out = next;
R_SUCCEED();
}
Result ReadBucket(Position *out, BucketIndex ind) {
AMS_ASSERT(out != nullptr);
AMS_ASSERT(ind < m_bucket_count);
const s64 offset = ind * sizeof(Position);
R_RETURN(m_bucket_storage.Read(offset, out, sizeof(*out)));
}
Result WriteBucket(Position pos, BucketIndex ind) {
AMS_ASSERT(ind < m_bucket_count);
const s64 offset = ind * sizeof(Position);
R_RETURN(m_bucket_storage.Write(offset, std::addressof(pos), sizeof(pos)));
}
Result ReadKeyValue(Element *out, Position pos) {
AMS_ASSERT(out != nullptr);
s64 kv_size;
R_TRY(m_kv_storage.GetSize(std::addressof(kv_size)));
AMS_ASSERT(pos < kv_size);
R_RETURN(m_kv_storage.Read(pos, out, sizeof(*out)));
}
Result ReadKeyValue(Element *out, void *out_aux, size_t *out_aux_size, Position pos) {
AMS_ASSERT(out != nullptr);
AMS_ASSERT(out_aux != nullptr);
AMS_ASSERT(out_aux_size != nullptr);
R_TRY(this->ReadKeyValue(out, pos));
*out_aux_size = out->size;
if (out->size > 0) {
R_TRY(m_kv_storage.Read(pos + sizeof(*out), out_aux, out->size));
}
R_SUCCEED();
}
Result WriteKeyValue(const Element *elem, Position pos, const void *aux, size_t aux_size) {
AMS_ASSERT(elem != nullptr);
AMS_ASSERT(aux != nullptr);
s64 kv_size;
R_TRY(m_kv_storage.GetSize(std::addressof(kv_size)));
AMS_ASSERT(pos < kv_size);
R_TRY(m_kv_storage.Write(pos, elem, sizeof(*elem)));
if (aux != nullptr && aux_size > 0) {
R_TRY(m_kv_storage.Write(pos + sizeof(*elem), aux, aux_size));
}
R_SUCCEED();
}
};
}

View File

@@ -1,125 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/common/fs_dbm_rom_types.hpp>
namespace ams::fs::RomPathTool {
/* ACCURATE_TO_VERSION: 14.3.0.0 */
constexpr inline u32 MaxPathLength = 0x300;
constexpr ALWAYS_INLINE bool IsSeparator(RomPathChar c) {
return c == RomStringTraits::DirectorySeparator;
}
constexpr ALWAYS_INLINE bool IsNullTerminator(RomPathChar c) {
return c == RomStringTraits::NullTerminator;
}
constexpr ALWAYS_INLINE bool IsDot(RomPathChar c) {
return c == RomStringTraits::Dot;
}
class RomEntryName {
private:
const RomPathChar *m_path;
size_t m_length;
public:
constexpr RomEntryName() : m_path(nullptr), m_length(0) {
/* ... */
}
constexpr void Initialize(const RomPathChar *p, size_t len) {
m_path = p;
m_length = len;
}
constexpr bool IsCurrentDirectory() const {
return m_length == 1 && IsDot(m_path[0]);
}
constexpr bool IsParentDirectory() const {
return m_length == 2 && IsDot(m_path[0]) && IsDot(m_path[1]);
}
constexpr bool IsRootDirectory() const {
return m_length == 0;
}
constexpr const RomPathChar *begin() const {
return m_path;
}
constexpr const RomPathChar *end() const {
return m_path + m_length;
}
constexpr size_t length() const {
return m_length;
}
};
constexpr inline bool IsCurrentDirectory(const RomPathChar *p, size_t length) {
AMS_ASSERT(p != nullptr);
return length == 1 && IsDot(p[0]);
}
constexpr inline bool IsCurrentDirectory(const RomPathChar *p) {
AMS_ASSERT(p != nullptr);
return IsDot(p[0]) && IsNullTerminator(p[1]);
}
constexpr inline bool IsParentDirectory(const RomPathChar *p) {
AMS_ASSERT(p != nullptr);
return IsDot(p[0]) && IsDot(p[1]) && IsNullTerminator(p[2]);
}
constexpr inline bool IsParentDirectory(const RomPathChar *p, size_t length) {
AMS_ASSERT(p != nullptr);
return length == 2 && IsDot(p[0]) && IsDot(p[1]);
}
constexpr inline bool IsEqualPath(const RomPathChar *lhs, const RomPathChar *rhs, size_t length) {
AMS_ASSERT(lhs != nullptr);
AMS_ASSERT(rhs != nullptr);
return std::strncmp(lhs, rhs, length) == 0;
}
Result GetParentDirectoryName(RomEntryName *out, const RomEntryName &cur, const RomPathChar *p);
class PathParser {
private:
const RomPathChar *m_prev_path_start;
const RomPathChar *m_prev_path_end;
const RomPathChar *m_next_path;
bool m_finished;
public:
constexpr PathParser() : m_prev_path_start(), m_prev_path_end(), m_next_path(), m_finished() { /* ... */ }
Result Initialize(const RomPathChar *path);
void Finalize();
bool IsParseFinished() const;
bool IsDirectoryPath() const;
Result GetAsDirectoryName(RomEntryName *out) const;
Result GetAsFileName(RomEntryName *out) const;
Result GetNextDirectoryName(RomEntryName *out);
};
}

View File

@@ -1,55 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: 14.3.0.0 */
using RomPathChar = char;
using RomFileId = u32;
using RomDirectoryId = u32;
struct RomFileSystemInformation {
s64 size;
s64 directory_bucket_offset;
s64 directory_bucket_size;
s64 directory_entry_offset;
s64 directory_entry_size;
s64 file_bucket_offset;
s64 file_bucket_size;
s64 file_entry_offset;
s64 file_entry_size;
s64 body_offset;
};
static_assert(util::is_pod<RomFileSystemInformation>::value);
static_assert(sizeof(RomFileSystemInformation) == 0x50);
struct RomFileInfo {
Int64 offset;
Int64 size;
};
static_assert(util::is_pod<RomFileInfo>::value);
namespace RomStringTraits {
constexpr inline char DirectorySeparator = '/';
constexpr inline char NullTerminator = '\x00';
constexpr inline char Dot = '.';
}
}

View File

@@ -1,124 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_path.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: 13.4.0.0 */
class DirectoryPathParser {
NON_COPYABLE(DirectoryPathParser);
NON_MOVEABLE(DirectoryPathParser);
private:
char *m_buffer;
char m_replaced_char;
s32 m_position;
fs::Path m_current_path;
public:
DirectoryPathParser() : m_buffer(nullptr), m_replaced_char(StringTraits::NullTerminator), m_position(0), m_current_path() { /* ... */ }
const fs::Path &GetCurrentPath() const {
return m_current_path;
}
Result Initialize(fs::Path *path) {
/* Declare a default buffer, in case the path has no write buffer. */
static constinit char EmptyBuffer[1] = "";
/* Get a usable buffer. */
char *buf = path->GetWriteBufferLength() > 0 ? path->GetWriteBuffer() : EmptyBuffer;
/* Get the windows skip length. */
const auto windows_skip_len = fs::GetWindowsSkipLength(buf);
/* Set our buffer. */
m_buffer = buf + windows_skip_len;
/* Set up our initial state. */
if (windows_skip_len) {
R_TRY(m_current_path.InitializeWithNormalization(buf, windows_skip_len + 1));
} else {
if (char * const first = this->ReadNextImpl(); first != nullptr) {
R_TRY(m_current_path.InitializeWithNormalization(first));
}
}
R_SUCCEED();
}
Result ReadNext(bool *out_finished) {
/* Default to not finished. */
*out_finished = false;
/* Get the next child component. */
if (auto * const child = this->ReadNextImpl(); child != nullptr) {
/* Append the child component to our current path. */
R_TRY(m_current_path.AppendChild(child));
} else {
/* We have no child component, so we're finished. */
*out_finished = true;
}
R_SUCCEED();
}
private:
char *ReadNextImpl() {
/* Check that we have characters to read. */
if (m_position < 0 || m_buffer[0] == StringTraits::NullTerminator) {
return nullptr;
}
/* If we have a replaced character, restore it. */
if (m_replaced_char != StringTraits::NullTerminator) {
m_buffer[m_position] = m_replaced_char;
if (m_replaced_char == StringTraits::DirectorySeparator) {
++m_position;
}
}
/* If we're at the start of a root-relative path, begin by returning the root. */
if (m_position == 0 && m_buffer[0] == StringTraits::DirectorySeparator) {
m_replaced_char = m_buffer[1];
m_buffer[1] = StringTraits::NullTerminator;
m_position = 1;
return m_buffer;
}
/* Otherwise, find the end of the next path component. */
s32 i;
for (i = m_position; m_buffer[i] != StringTraits::DirectorySeparator; ++i) {
if (m_buffer[i] == StringTraits::NullTerminator) {
char * const ret = (i != m_position) ? m_buffer + m_position : nullptr;
m_position = -1;
return ret;
}
}
/* Sanity check that we're not ending on a separator. */
AMS_ASSERT(m_buffer[i + 1] != StringTraits::NullTerminator);
char * const ret = m_buffer + m_position;
m_replaced_char = StringTraits::DirectorySeparator;
m_buffer[i] = 0;
m_position = i;
return ret;
}
};
}

View File

@@ -1,118 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_istorage.hpp>
#include <stratosphere/fs/fsa/fs_ifile.hpp>
#include <stratosphere/fs/fsa/fs_ifilesystem.hpp>
#include <stratosphere/fs/impl/fs_newable.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
class FileStorage : public IStorage, public impl::Newable {
NON_COPYABLE(FileStorage);
NON_MOVEABLE(FileStorage);
private:
static constexpr s64 InvalidSize = -1;
private:
std::unique_ptr<fsa::IFile> m_unique_file;
std::shared_ptr<fsa::IFile> m_shared_file;
fsa::IFile *m_base_file;
s64 m_size;
public:
FileStorage(fsa::IFile *f) : m_unique_file(f), m_size(InvalidSize) {
m_base_file = m_unique_file.get();
}
FileStorage(std::unique_ptr<fsa::IFile> f) : m_unique_file(std::move(f)), m_size(InvalidSize) {
m_base_file = m_unique_file.get();
}
FileStorage(std::shared_ptr<fsa::IFile> f) : m_shared_file(f), m_size(InvalidSize) {
m_base_file = m_shared_file.get();
}
virtual ~FileStorage() { /* ... */ }
private:
Result UpdateSize();
protected:
constexpr FileStorage() : m_unique_file(), m_shared_file(), m_base_file(nullptr), m_size(InvalidSize) { /* ... */ }
void SetFile(fs::fsa::IFile *file) {
AMS_ASSERT(file != nullptr);
AMS_ASSERT(m_base_file == nullptr);
m_base_file = file;
}
void SetFile(std::unique_ptr<fs::fsa::IFile> &&file) {
AMS_ASSERT(file != nullptr);
AMS_ASSERT(m_base_file == nullptr);
AMS_ASSERT(m_unique_file == nullptr);
m_unique_file = std::move(file);
m_base_file = m_unique_file.get();
}
public:
virtual Result Read(s64 offset, void *buffer, size_t size) override;
virtual Result Write(s64 offset, const void *buffer, size_t size) override;
virtual Result Flush() override;
virtual Result GetSize(s64 *out_size) override;
virtual Result SetSize(s64 size) override;
virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override;
};
/* ACCURATE_TO_VERSION: Unknown */
class FileStorageBasedFileSystem : public FileStorage {
NON_COPYABLE(FileStorageBasedFileSystem);
NON_MOVEABLE(FileStorageBasedFileSystem);
private:
std::shared_ptr<fs::fsa::IFileSystem> m_base_file_system;
public:
constexpr FileStorageBasedFileSystem() : FileStorage(), m_base_file_system(nullptr) { /* ... */ }
Result Initialize(std::shared_ptr<fs::fsa::IFileSystem> base_file_system, const fs::Path &path, fs::OpenMode mode);
};
class FileHandleStorage : public IStorage, public impl::Newable {
private:
static constexpr s64 InvalidSize = -1;
private:
FileHandle m_handle;
bool m_close_file;
s64 m_size;
os::SdkMutex m_mutex;
public:
constexpr explicit FileHandleStorage(FileHandle handle, bool close_file) : m_handle(handle), m_close_file(close_file), m_size(InvalidSize), m_mutex() { /* ... */ }
constexpr explicit FileHandleStorage(FileHandle handle) : FileHandleStorage(handle, false) { /* ... */ }
virtual ~FileHandleStorage() override {
if (m_close_file) {
CloseFile(m_handle);
}
}
protected:
Result UpdateSize();
public:
virtual Result Read(s64 offset, void *buffer, size_t size) override;
virtual Result Write(s64 offset, const void *buffer, size_t size) override;
virtual Result Flush() override;
virtual Result GetSize(s64 *out_size) override;
virtual Result SetSize(s64 size) override;
virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override;
};
}

View File

@@ -1,35 +0,0 @@
/*
* Copyright (c) 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::fs {
/* ACCURATE_TO_VERSION: Unknown */
enum AccessLogMode : u32 {
AccessLogMode_None = 0,
AccessLogMode_Log = 1,
AccessLogMode_SdCard = 2,
};
Result GetGlobalAccessLogMode(u32 *out);
Result SetGlobalAccessLogMode(u32 mode);
void SetLocalAccessLog(bool enabled);
void SetLocalSystemAccessLogForDebug(bool enabled);
}

View File

@@ -1,26 +0,0 @@
/*
* Copyright (c) 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::fs {
/* ACCURATE_TO_VERSION: Unknown */
void InitializeForSystem();
void InitializeWithMultiSessionForSystem();
}

View File

@@ -1,25 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
Result MountApplicationPackage(const char *name, const char *common_path);
}

View File

@@ -1,62 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_istorage.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
enum class BisPartitionId {
/* Boot0 */
BootPartition1Root = 0,
/* Boot1 */
BootPartition2Root = 10,
/* Non-Boot */
UserDataRoot = 20,
BootConfigAndPackage2Part1 = 21,
BootConfigAndPackage2Part2 = 22,
BootConfigAndPackage2Part3 = 23,
BootConfigAndPackage2Part4 = 24,
BootConfigAndPackage2Part5 = 25,
BootConfigAndPackage2Part6 = 26,
CalibrationBinary = 27,
CalibrationFile = 28,
SafeMode = 29,
User = 30,
System = 31,
SystemProperEncryption = 32,
SystemProperPartition = 33,
SignedSystemPartitionOnSafeMode = 34,
DeviceTreeBlob = 35,
System0 = 36,
};
const char *GetBisMountName(BisPartitionId id);
Result MountBis(BisPartitionId id, const char *root_path);
Result MountBis(const char *name, BisPartitionId id);
void SetBisRootForHost(BisPartitionId id, const char *root_path);
Result OpenBisPartition(std::unique_ptr<fs::IStorage> *out, BisPartitionId id);
Result InvalidateBisCache();
}

View File

@@ -1,29 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/ncm/ncm_ids.hpp>
#include <stratosphere/fs/fs_code_verification_data.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: 16.2.0.0 */
Result MountCode(CodeVerificationData *out, const char *name, const char *path, fs::ContentAttributes attr, ncm::ProgramId program_id, ncm::StorageId storage_id);
Result MountCodeForAtmosphereWithRedirection(CodeVerificationData *out, const char *name, const char *path, fs::ContentAttributes attr, ncm::ProgramId program_id, ncm::StorageId storage_id, bool is_hbl, bool is_specific);
Result MountCodeForAtmosphere(CodeVerificationData *out, const char *name, const char *path, fs::ContentAttributes attr, ncm::ProgramId program_id, ncm::StorageId storage_id);
}

View File

@@ -1,31 +0,0 @@
/*
* Copyright (c) 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>
#include <stratosphere/sf/sf_buffer_tags.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: 13.4.0.0 */
struct CodeVerificationData : public ams::sf::LargeData {
u8 signature[crypto::Rsa2048PssSha256Verifier::SignatureSize];
u8 target_hash[crypto::Rsa2048PssSha256Verifier::HashSize];
bool has_data;
u8 reserved[3];
};
static_assert(sizeof(CodeVerificationData) == crypto::Rsa2048PssSha256Verifier::SignatureSize + crypto::Rsa2048PssSha256Verifier::HashSize + 4);
}

View File

@@ -1,49 +0,0 @@
/*
* Copyright (c) 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>
#include <stratosphere/os.hpp>
#include <stratosphere/ncm/ncm_ids.hpp>
#include <stratosphere/sf.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
struct Int64 {
u32 low;
u32 high;
constexpr ALWAYS_INLINE void Set(s64 v) {
this->low = static_cast<u32>((v & static_cast<u64>(0x00000000FFFFFFFFul)) >> 0);
this->high = static_cast<u32>((v & static_cast<u64>(0xFFFFFFFF00000000ul)) >> 32);
}
constexpr ALWAYS_INLINE s64 Get() const {
return (static_cast<s64>(this->high) << 32) | (static_cast<s64>(this->low));
}
constexpr ALWAYS_INLINE Int64 &operator=(s64 v) {
this->Set(v);
return *this;
}
constexpr ALWAYS_INLINE operator s64() const {
return this->Get();
}
};
static_assert(util::is_pod<Int64>::value);
}

View File

@@ -1,35 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/ncm/ncm_ids.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
enum ContentType {
ContentType_Meta = 0,
ContentType_Control = 1,
ContentType_Manual = 2,
ContentType_Logo = 3,
ContentType_Data = 4,
};
Result MountContent(const char *name, const char *path, fs::ContentAttributes attr, ContentType content_type);
Result MountContent(const char *name, const char *path, fs::ContentAttributes attr, ncm::ProgramId id, ContentType content_type);
Result MountContent(const char *name, const char *path, fs::ContentAttributes attr, ncm::DataId id, ContentType content_type);
}

View File

@@ -1,28 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/ncm/ncm_ids.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
enum ContentAttributes : u8 {
ContentAttributes_None = 0x0,
ContentAttributes_All = 0xF,
};
}

View File

@@ -1,29 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_content_storage_id.hpp>
namespace ams::fs {
constexpr inline const char * const ContentStorageDirectoryName = "Contents";
const char *GetContentStorageMountName(ContentStorageId id);
Result MountContentStorage(ContentStorageId id);
Result MountContentStorage(const char *name, ContentStorageId id);
}

View File

@@ -1,29 +0,0 @@
/*
* Copyright (c) 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::fs {
/* ACCURATE_TO_VERSION: 16.2.0.0 */
enum class ContentStorageId : u32 {
System = 0,
User = 1,
SdCard = 2,
System0 = 3,
};
}

View File

@@ -1,68 +0,0 @@
/*
* Copyright (c) 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::fs {
enum class AbortSpecifier {
Default,
Abort,
Return,
};
using ResultHandler = AbortSpecifier (*)(Result);
class FsContext {
private:
ResultHandler m_handler;
public:
constexpr explicit FsContext(ResultHandler h) : m_handler(h) { /* ... */ }
constexpr void SetHandler(ResultHandler h) { m_handler = h; }
constexpr AbortSpecifier HandleResult(Result result) const { return m_handler(result); }
};
void SetDefaultFsContextResultHandler(const ResultHandler handler);
const FsContext *GetCurrentThreadFsContext();
void SetCurrentThreadFsContext(const FsContext *context);
class ScopedFsContext {
private:
const FsContext * const m_prev_context;
public:
ALWAYS_INLINE ScopedFsContext(const FsContext &ctx) : m_prev_context(GetCurrentThreadFsContext()) {
SetCurrentThreadFsContext(std::addressof(ctx));
}
ALWAYS_INLINE ~ScopedFsContext() {
SetCurrentThreadFsContext(m_prev_context);
}
};
class ScopedAutoAbortDisabler {
private:
const FsContext * const m_prev_context;
public:
ScopedAutoAbortDisabler();
ALWAYS_INLINE ~ScopedAutoAbortDisabler() {
SetCurrentThreadFsContext(m_prev_context);
}
};
}

View File

@@ -1,26 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_save_data_types.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
Result MountDeviceSaveData(const char *name);
Result MountDeviceSaveData(const char *name, const ncm::ApplicationId application_id);
}

View File

@@ -1,40 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
constexpr inline size_t EntryNameLengthMax = 0x300;
struct DirectoryEntry {
char name[EntryNameLengthMax + 1];
char pad[3];
s8 type;
u8 pad2[3];
s64 file_size;
};
struct DirectoryHandle {
void *handle;
};
Result ReadDirectory(s64 *out_count, DirectoryEntry *out_entries, DirectoryHandle handle, s64 max_entries);
Result GetDirectoryEntryCount(s64 *out, DirectoryHandle handle);
void CloseDirectory(DirectoryHandle handle);
}

View File

@@ -1,58 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fat/fat_file_system.hpp>
namespace ams::fs {
struct StorageErrorInfo {
u32 num_activation_failures;
u32 num_activation_error_corrections;
u32 num_read_write_failures;
u32 num_read_write_error_corrections;
};
static_assert(sizeof(StorageErrorInfo) == 0x10);
static_assert(util::is_pod<StorageErrorInfo>::value);
struct FileSystemProxyErrorInfo {
u32 rom_fs_remount_for_data_corruption_count;
u32 rom_fs_unrecoverable_data_corruption_by_remount_count;
fat::FatError fat_fs_error;
u32 rom_fs_recovered_by_invalidate_cache_count;
u32 save_data_index_count;
fat::FatReportInfo1 bis_system_fat_report_info_1;
fat::FatReportInfo1 bis_user_fat_report_info_1;
fat::FatReportInfo1 sd_card_fat_report_info_1;
fat::FatReportInfo2 bis_system_fat_report_info_2;
fat::FatReportInfo2 bis_user_fat_report_info_2;
fat::FatReportInfo2 sd_card_fat_report_info_2;
u32 rom_fs_deep_retry_start_count;
u32 rom_fs_unrecoverable_by_game_card_access_failed_count;
fat::FatSafeInfo bis_system_fat_safe_info;
fat::FatSafeInfo bis_user_fat_safe_info;
u8 reserved[0x18];
};
static_assert(sizeof(FileSystemProxyErrorInfo) == 0x80);
static_assert(util::is_pod<FileSystemProxyErrorInfo>::value);
Result GetAndClearMmcErrorInfo(StorageErrorInfo *out_sei, size_t *out_log_size, char *out_log_buffer, size_t log_buffer_size);
Result GetAndClearSdCardErrorInfo(StorageErrorInfo *out_sei, size_t *out_log_size, char *out_log_buffer, size_t log_buffer_size);
Result GetAndClearFileSystemProxyErrorInfo(FileSystemProxyErrorInfo *out);
}

View File

@@ -1,87 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs {
struct ReadOption {
u32 _value;
static const ReadOption None;
};
enum ReadOptionFlag : u32 {
ReadOptionFlag_None = (0 << 0),
};
inline constexpr const ReadOption ReadOption::None = {ReadOptionFlag_None};
inline constexpr bool operator==(const ReadOption &lhs, const ReadOption &rhs) {
return lhs._value == rhs._value;
}
inline constexpr bool operator!=(const ReadOption &lhs, const ReadOption &rhs) {
return !(lhs == rhs);
}
static_assert(util::is_pod<ReadOption>::value && sizeof(ReadOption) == sizeof(u32));
enum WriteOptionFlag : u32 {
WriteOptionFlag_None = (0 << 0),
WriteOptionFlag_Flush = (1 << 0),
};
struct WriteOption {
u32 _value;
constexpr inline bool HasFlushFlag() const {
return _value & WriteOptionFlag_Flush;
}
static const WriteOption None;
static const WriteOption Flush;
};
inline constexpr const WriteOption WriteOption::None = {WriteOptionFlag_None};
inline constexpr const WriteOption WriteOption::Flush = {WriteOptionFlag_Flush};
inline constexpr bool operator==(const WriteOption &lhs, const WriteOption &rhs) {
return lhs._value == rhs._value;
}
inline constexpr bool operator!=(const WriteOption &lhs, const WriteOption &rhs) {
return !(lhs == rhs);
}
static_assert(util::is_pod<WriteOption>::value && sizeof(WriteOption) == sizeof(u32));
struct FileHandle {
void *handle;
};
Result ReadFile(FileHandle handle, s64 offset, void *buffer, size_t size, const fs::ReadOption &option);
Result ReadFile(FileHandle handle, s64 offset, void *buffer, size_t size);
Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size, const fs::ReadOption &option);
Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size);
Result GetFileSize(s64 *out, FileHandle handle);
Result FlushFile(FileHandle handle);
Result WriteFile(FileHandle handle, s64 offset, const void *buffer, size_t size, const fs::WriteOption &option);
Result SetFileSize(FileHandle handle, s64 size);
int GetFileOpenMode(FileHandle handle);
void CloseFile(FileHandle handle);
}

View File

@@ -1,78 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs {
namespace fsa {
class IFileSystem;
}
enum OpenMode {
OpenMode_Read = (1 << 0),
OpenMode_Write = (1 << 1),
OpenMode_AllowAppend = (1 << 2),
OpenMode_ReadWrite = (OpenMode_Read | OpenMode_Write),
OpenMode_All = (OpenMode_ReadWrite | OpenMode_AllowAppend),
};
enum OpenDirectoryMode {
OpenDirectoryMode_Directory = (1 << 0),
OpenDirectoryMode_File = (1 << 1),
OpenDirectoryMode_All = (OpenDirectoryMode_Directory | OpenDirectoryMode_File),
/* TODO: Separate enum, like N? */
OpenDirectoryMode_NotRequireFileSize = (1 << 31),
};
enum DirectoryEntryType {
DirectoryEntryType_Directory = 0,
DirectoryEntryType_File = 1,
};
enum CreateOption {
CreateOption_None = (0 << 0),
CreateOption_BigFile = (1 << 0),
};
struct FileHandle;
struct DirectoryHandle;
Result CreateFile(const char *path, s64 size);
Result CreateFile(const char* path, s64 size, int option);
Result DeleteFile(const char *path);
Result CreateDirectory(const char *path);
Result DeleteDirectory(const char *path);
Result DeleteDirectoryRecursively(const char *path);
Result RenameFile(const char *old_path, const char *new_path);
Result RenameDirectory(const char *old_path, const char *new_path);
Result GetEntryType(DirectoryEntryType *out, const char *path);
Result OpenFile(FileHandle *out_file, const char *path, int mode);
Result OpenDirectory(DirectoryHandle *out_dir, const char *path, int mode);
Result CleanDirectoryRecursively(const char *path);
Result GetFreeSpaceSize(s64 *out, const char *path);
Result GetTotalSpaceSize(s64 *out, const char *path);
Result SetConcatenationFileAttribute(const char *path);
Result OpenFile(FileHandle *out, std::unique_ptr<fsa::IFile> &&file, int mode);
}

View File

@@ -1,60 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_filesystem.hpp>
#include <stratosphere/time/time_posix_time.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
struct FileTimeStamp {
time::PosixTime create;
time::PosixTime modify;
time::PosixTime access;
bool is_local_time;
char pad[7];
};
static_assert(util::is_pod<FileTimeStamp>::value && sizeof(FileTimeStamp) == 0x20);
struct FileTimeStampRaw {
s64 create;
s64 modify;
s64 access;
bool is_local_time;
char pad[7];
};
static_assert(util::is_pod<FileTimeStampRaw>::value && sizeof(FileTimeStampRaw) == 0x20);
static_assert(__builtin_offsetof(FileTimeStampRaw, create) == __builtin_offsetof(FileTimeStampRaw, create));
static_assert(__builtin_offsetof(FileTimeStampRaw, modify) == __builtin_offsetof(FileTimeStampRaw, modify));
static_assert(__builtin_offsetof(FileTimeStampRaw, access) == __builtin_offsetof(FileTimeStampRaw, access));
static_assert(__builtin_offsetof(FileTimeStampRaw, is_local_time) == __builtin_offsetof(FileTimeStampRaw, is_local_time));
static_assert(__builtin_offsetof(FileTimeStampRaw, pad) == __builtin_offsetof(FileTimeStampRaw, pad));
#if defined(ATMOSPHERE_OS_HORIZON)
static_assert(sizeof(FileTimeStampRaw) == sizeof(::FsTimeStampRaw));
#endif
namespace impl {
Result GetFileTimeStampRawForDebug(FileTimeStampRaw *out, const char *path);
}
Result GetFileTimeStamp(FileTimeStamp *out, const char *path);
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_filesystem.hpp>
#include <stratosphere/fs/fs_filesystem_for_debug.hpp>
namespace ams::fs {
/* Common utilities. */
Result EnsureDirectory(const char *path);
Result EnsureParentDirectory(const char *path);
Result HasFile(bool *out, const char *path);
Result HasDirectory(bool *out, const char *path);
}

View File

@@ -1,93 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
constexpr inline size_t GameCardCidSize = 0x10;
constexpr inline size_t GameCardDeviceIdSize = 0x10;
enum class GameCardPartition {
Update = 0,
Normal = 1,
Secure = 2,
Logo = 3,
};
enum class GameCardPartitionRaw {
NormalReadable,
SecureReadable,
RootWriteable,
};
enum GameCardAttribute : u8 {
GameCardAttribute_AutoBootFlag = (1 << 0),
GameCardAttribute_HistoryEraseFlag = (1 << 1),
GameCardAttribute_RepairToolFlag = (1 << 2),
GameCardAttribute_DifferentRegionCupToTerraDeviceFlag = (1 << 3),
GameCardAttribute_DifferentRegionCupToGlobalDeviceFlag = (1 << 4),
GameCardAttribute_HasCa10CertificateFlag = (1 << 7),
};
enum class GameCardCompatibilityType : u8 {
Normal = 0,
Terra = 1,
};
struct GameCardErrorReportInfo {
u16 game_card_crc_error_num;
u16 reserved1;
u16 asic_crc_error_num;
u16 reserved2;
u16 refresh_num;
u16 reserved3;
u16 retry_limit_out_num;
u16 timeout_retry_num;
u16 asic_reinitialize_failure_detail;
u16 insertion_count;
u16 removal_count;
u16 asic_reinitialize_num;
u32 initialize_count;
u16 asic_reinitialize_failure_num;
u16 awaken_failure_num;
u16 reserved4;
u16 refresh_succeeded_count;
u32 last_read_error_page_address;
u32 last_read_error_page_count;
u32 awaken_count;
u32 read_count_from_insert;
u32 read_count_from_awaken;
u8 reserved5[8];
};
static_assert(util::is_pod<GameCardErrorReportInfo>::value);
static_assert(sizeof(GameCardErrorReportInfo) == 0x40);
using GameCardHandle = u32;
Result GetGameCardHandle(GameCardHandle *out);
Result MountGameCardPartition(const char *name, GameCardHandle handle, GameCardPartition partition);
Result GetGameCardCid(void *dst, size_t size);
Result GetGameCardDeviceId(void *dst, size_t size);
Result GetGameCardErrorReportInfo(GameCardErrorReportInfo *out);
bool IsGameCardInserted();
}

View File

@@ -1,59 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/ncm/ncm_ids.hpp>
#include <stratosphere/fs/fs_code_verification_data.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
enum MountHostOptionFlag : u32 {
MountHostOptionFlag_None = (0 << 0),
MountHostOptionFlag_PseudoCaseSensitive = (1 << 0),
};
struct MountHostOption {
u32 _value;
constexpr inline bool HasPseudoCaseSensitiveFlag() const {
return _value & MountHostOptionFlag_PseudoCaseSensitive;
}
static const MountHostOption None;
static const MountHostOption PseudoCaseSensitive;
};
inline constexpr const MountHostOption MountHostOption::None = {MountHostOptionFlag_None};
inline constexpr const MountHostOption MountHostOption::PseudoCaseSensitive = {MountHostOptionFlag_PseudoCaseSensitive};
inline constexpr bool operator==(const MountHostOption &lhs, const MountHostOption &rhs) {
return lhs._value == rhs._value;
}
inline constexpr bool operator!=(const MountHostOption &lhs, const MountHostOption &rhs) {
return !(lhs == rhs);
}
Result MountHost(const char *name, const char *root_path);
Result MountHost(const char *name, const char *root_path, const MountHostOption &option);
Result MountHostRoot();
Result MountHostRoot(const MountHostOption &option);
void UnmountHostRoot();
}

View File

@@ -1,122 +0,0 @@
/*
* Copyright (c) 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::fs {
class IBufferManager {
public:
class BufferAttribute {
private:
s32 m_level;
public:
constexpr BufferAttribute() : m_level(0) { /* ... */ }
constexpr explicit BufferAttribute(s32 l) : m_level(l) { /* ... */ }
constexpr s32 GetLevel() const { return m_level; }
};
using CacheHandle = u64;
static constexpr s32 BufferLevelMin = 0;
using MemoryRange = std::pair<uintptr_t, size_t>;
static constexpr ALWAYS_INLINE MemoryRange MakeMemoryRange(uintptr_t address, size_t size) { return MemoryRange(address, size); }
public:
virtual ~IBufferManager() { /* ... */ }
ALWAYS_INLINE const MemoryRange AllocateBuffer(size_t size, const BufferAttribute &attr) {
return this->DoAllocateBuffer(size, attr);
}
ALWAYS_INLINE const MemoryRange AllocateBuffer(size_t size) {
return this->DoAllocateBuffer(size, BufferAttribute());
}
ALWAYS_INLINE void DeallocateBuffer(uintptr_t address, size_t size) {
return this->DoDeallocateBuffer(address, size);
}
ALWAYS_INLINE void DeallocateBuffer(const MemoryRange &memory_range) {
return this->DoDeallocateBuffer(memory_range.first, memory_range.second);
}
ALWAYS_INLINE CacheHandle RegisterCache(uintptr_t address, size_t size, const BufferAttribute &attr) {
return this->DoRegisterCache(address, size, attr);
}
ALWAYS_INLINE CacheHandle RegisterCache(const MemoryRange &memory_range, const BufferAttribute &attr) {
return this->DoRegisterCache(memory_range.first, memory_range.second, attr);
}
ALWAYS_INLINE const std::pair<uintptr_t, size_t> AcquireCache(CacheHandle handle) {
return this->DoAcquireCache(handle);
}
ALWAYS_INLINE size_t GetTotalSize() const {
return this->DoGetTotalSize();
}
ALWAYS_INLINE size_t GetFreeSize() const {
return this->DoGetFreeSize();
}
ALWAYS_INLINE size_t GetTotalAllocatableSize() const {
return this->DoGetTotalAllocatableSize();
}
ALWAYS_INLINE size_t GetFreeSizePeak() const {
return this->DoGetFreeSizePeak();
}
ALWAYS_INLINE size_t GetTotalAllocatableSizePeak() const {
return this->DoGetTotalAllocatableSizePeak();
}
ALWAYS_INLINE size_t GetRetriedCount() const {
return this->DoGetRetriedCount();
}
ALWAYS_INLINE void ClearPeak() {
return this->DoClearPeak();
}
protected:
virtual const MemoryRange DoAllocateBuffer(size_t size, const BufferAttribute &attr) = 0;
virtual void DoDeallocateBuffer(uintptr_t address, size_t size) = 0;
virtual CacheHandle DoRegisterCache(uintptr_t address, size_t size, const BufferAttribute &attr) = 0;
virtual const MemoryRange DoAcquireCache(CacheHandle handle) = 0;
virtual size_t DoGetTotalSize() const = 0;
virtual size_t DoGetFreeSize() const = 0;
virtual size_t DoGetTotalAllocatableSize() const = 0;
virtual size_t DoGetFreeSizePeak() const = 0;
virtual size_t DoGetTotalAllocatableSizePeak() const = 0;
virtual size_t DoGetRetriedCount() const = 0;
virtual void DoClearPeak() = 0;
};
}

View File

@@ -1,34 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
class IEventNotifier {
public:
virtual ~IEventNotifier() { /* ... */ }
Result BindEvent(os::SystemEventType *out, os::EventClearMode clear_mode) {
AMS_ASSERT(out != nullptr);
R_RETURN(this->DoBindEvent(out, clear_mode));
}
private:
virtual Result DoBindEvent(os::SystemEventType *out, os::EventClearMode clear_mode) = 0;
};
}

View File

@@ -1,29 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
enum class ImageDirectoryId {
Nand = 0,
SdCard = 1,
};
Result MountImageDirectory(const char *name, ImageDirectoryId id);
}

View File

@@ -1,129 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_file.hpp>
#include <stratosphere/fs/fs_operate_range.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: 14.3.0.0 */
class IStorage {
public:
virtual ~IStorage() { /* ... */ }
virtual Result Read(s64 offset, void *buffer, size_t size) = 0;
virtual Result Write(s64 offset, const void *buffer, size_t size) = 0;
virtual Result Flush() = 0;
virtual Result SetSize(s64 size) = 0;
virtual Result GetSize(s64 *out) = 0;
virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) = 0;
virtual Result OperateRange(OperationId op_id, s64 offset, s64 size) {
R_RETURN(this->OperateRange(nullptr, 0, op_id, offset, size, nullptr, 0));
}
public:
static inline Result CheckAccessRange(s64 offset, s64 size, s64 total_size) {
R_UNLESS(offset >= 0, fs::ResultInvalidOffset());
R_UNLESS(size >= 0, fs::ResultInvalidSize());
R_UNLESS(util::CanAddWithoutOverflow<s64>(offset, size), fs::ResultOutOfRange());
R_UNLESS(offset + size <= total_size, fs::ResultOutOfRange());
R_SUCCEED();
}
static ALWAYS_INLINE Result CheckAccessRange(s64 offset, size_t size, s64 total_size) {
R_RETURN(CheckAccessRange(offset, static_cast<s64>(size), total_size));
}
static inline Result CheckOffsetAndSize(s64 offset, s64 size) {
R_UNLESS(offset >= 0, fs::ResultInvalidOffset());
R_UNLESS(size >= 0, fs::ResultInvalidSize());
R_UNLESS(util::CanAddWithoutOverflow<s64>(offset, size), fs::ResultOutOfRange());
R_SUCCEED();
}
static ALWAYS_INLINE Result CheckOffsetAndSize(s64 offset, size_t size) {
R_RETURN(CheckOffsetAndSize(offset, static_cast<s64>(size)));
}
static inline Result CheckOffsetAndSizeWithResult(s64 offset, s64 size, Result fail_result) {
R_TRY_CATCH(CheckOffsetAndSize(offset, size)) {
R_CONVERT_ALL(fail_result);
} R_END_TRY_CATCH;
R_SUCCEED();
}
static ALWAYS_INLINE Result CheckOffsetAndSizeWithResult(s64 offset, size_t size, Result fail_result) {
R_RETURN(CheckOffsetAndSizeWithResult(offset, static_cast<s64>(size), fail_result));
}
};
class ReadOnlyStorageAdapter : public IStorage {
private:
std::shared_ptr<IStorage> m_shared_storage;
std::unique_ptr<IStorage> m_unique_storage;
IStorage *m_storage;
public:
explicit ReadOnlyStorageAdapter(IStorage *s) : m_unique_storage(s) {
m_storage = m_unique_storage.get();
}
explicit ReadOnlyStorageAdapter(std::shared_ptr<IStorage> s) : m_shared_storage(s) {
m_storage = m_shared_storage.get();
}
explicit ReadOnlyStorageAdapter(std::unique_ptr<IStorage> s) : m_unique_storage(std::move(s)) {
m_storage = m_unique_storage.get();
}
virtual ~ReadOnlyStorageAdapter() { /* ... */ }
public:
virtual Result Read(s64 offset, void *buffer, size_t size) override {
R_RETURN(m_storage->Read(offset, buffer, size));
}
virtual Result Flush() override {
R_RETURN(m_storage->Flush());
}
virtual Result GetSize(s64 *out) override {
R_RETURN(m_storage->GetSize(out));
}
virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override {
R_RETURN(m_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
}
virtual Result Write(s64 offset, const void *buffer, size_t size) override {
/* TODO: Better result? Is it possible to get a more specific one? */
AMS_UNUSED(offset, buffer, size);
R_THROW(fs::ResultUnsupportedOperation());
}
virtual Result SetSize(s64 size) override {
/* TODO: Better result? Is it possible to get a more specific one? */
AMS_UNUSED(size);
R_THROW(fs::ResultUnsupportedOperation());
}
};
template<typename T>
concept PointerToStorage = ::ams::util::RawOrSmartPointerTo<T, ::ams::fs::IStorage>;
}

View File

@@ -1,165 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
using AllocateFunction = void *(*)(size_t);
using DeallocateFunction = void (*)(void *, size_t);
void SetAllocator(AllocateFunction allocator, DeallocateFunction deallocator);
namespace impl {
class Newable;
void *Allocate(size_t size);
void Deallocate(void *ptr, size_t size);
void LockAllocatorMutex();
void UnlockAllocatorMutex();
void *AllocateUnsafe(size_t size);
void DeallocateUnsafe(void *ptr, size_t size);
class AllocatorImpl {
public:
static ALWAYS_INLINE void *Allocate(size_t size) { return ::ams::fs::impl::Allocate(size); }
static ALWAYS_INLINE void *AllocateUnsafe(size_t size) { return ::ams::fs::impl::AllocateUnsafe(size); }
static ALWAYS_INLINE void Deallocate(void *ptr, size_t size) { return ::ams::fs::impl::Deallocate(ptr, size); }
static ALWAYS_INLINE void DeallocateUnsafe(void *ptr, size_t size) { return ::ams::fs::impl::DeallocateUnsafe(ptr, size); }
static ALWAYS_INLINE void LockAllocatorMutex() { return ::ams::fs::impl::LockAllocatorMutex(); }
static ALWAYS_INLINE void UnlockAllocatorMutex() { return ::ams::fs::impl::UnlockAllocatorMutex(); }
};
template<typename T, typename Impl, bool AllocateWhileLocked>
class AllocatorTemplate : public std::allocator<T> {
public:
template<typename U>
struct rebind {
using other = AllocatorTemplate<U, Impl, AllocateWhileLocked>;
};
private:
bool m_allocation_failed;
private:
static ALWAYS_INLINE T *AllocateImpl(::std::size_t n) {
if constexpr (AllocateWhileLocked) {
auto * const p = Impl::AllocateUnsafe(sizeof(T) * n);
Impl::UnlockAllocatorMutex();
return static_cast<T *>(p);
} else {
return static_cast<T *>(Impl::Allocate(sizeof(T) * n));
}
}
public:
AllocatorTemplate() : m_allocation_failed(false) { /* ... */ }
template<typename U>
AllocatorTemplate(const AllocatorTemplate<U, Impl, AllocateWhileLocked> &rhs) : m_allocation_failed(rhs.IsAllocationFailed()) { /* ... */ }
bool IsAllocationFailed() const { return m_allocation_failed; }
[[nodiscard]] T *allocate(::std::size_t n) {
auto * const p = AllocateImpl(n);
if (AMS_UNLIKELY(p == nullptr) && n) {
m_allocation_failed = true;
}
return p;
}
void deallocate(T *p, ::std::size_t n) {
Impl::Deallocate(p, sizeof(T) * n);
}
};
template<typename T, typename Impl>
using AllocatorTemplateForAllocateShared = AllocatorTemplate<T, Impl, true>;
template<typename T, template<typename, typename> class AllocatorTemplateT, typename Impl, typename... Args>
std::shared_ptr<T> AllocateSharedImpl(Args &&... args) {
/* Try to allocate. */
{
/* Acquire exclusive access to the allocator. */
Impl::LockAllocatorMutex();
/* Check that we can allocate memory (using overestimate of 0x80 + sizeof(T)). */
if (auto * const p = Impl::AllocateUnsafe(0x80 + sizeof(T)); AMS_LIKELY(p != nullptr)) {
/* Free the memory we allocated. */
Impl::DeallocateUnsafe(p, 0x80 + sizeof(T));
/* Get allocator type. */
using AllocatorType = AllocatorTemplateT<T, Impl>;
/* Allocate the shared pointer. */
return std::allocate_shared<T>(AllocatorType{}, std::forward<Args>(args)...);
} else {
/* We can't allocate. */
Impl::UnlockAllocatorMutex();
}
}
/* We failed. */
return nullptr;
}
class Deleter {
private:
size_t m_size;
public:
Deleter() : m_size() { /* ... */ }
explicit Deleter(size_t sz) : m_size(sz) { /* ... */ }
void operator()(void *ptr) const {
::ams::fs::impl::Deallocate(ptr, m_size);
}
};
template<typename T>
auto MakeUnique() {
/* Check that we're not using MakeUnique unnecessarily. */
static_assert(!std::derived_from<T, ::ams::fs::impl::Newable>);
return std::unique_ptr<T, Deleter>(static_cast<T *>(::ams::fs::impl::Allocate(sizeof(T))), Deleter(sizeof(T)));
}
template<typename ArrayT>
auto MakeUnique(size_t size) {
using T = typename std::remove_extent<ArrayT>::type;
static_assert(util::is_pod<ArrayT>::value);
static_assert(std::is_array<ArrayT>::value);
/* Check that we're not using MakeUnique unnecessarily. */
static_assert(!std::derived_from<T, ::ams::fs::impl::Newable>);
using ReturnType = std::unique_ptr<ArrayT, Deleter>;
const size_t alloc_size = sizeof(T) * size;
return ReturnType(static_cast<T *>(::ams::fs::impl::Allocate(alloc_size)), Deleter(alloc_size));
}
}
template<typename T, typename... Args>
std::shared_ptr<T> AllocateShared(Args &&... args) {
return ::ams::fs::impl::AllocateSharedImpl<T, ::ams::fs::impl::AllocatorTemplateForAllocateShared, ::ams::fs::impl::AllocatorImpl>(std::forward<Args>(args)...);
}
}

View File

@@ -1,42 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs {
struct MemoryReportInfo {
u64 pooled_buffer_peak_free_size;
u64 pooled_buffer_retried_count;
u64 pooled_buffer_reduce_allocation_count;
u64 buffer_manager_peak_free_size;
u64 buffer_manager_retried_count;
u64 exp_heap_peak_free_size;
u64 buffer_pool_peak_free_size;
u64 patrol_read_allocate_buffer_success_count;
u64 patrol_read_allocate_buffer_failure_count;
u64 buffer_manager_peak_total_allocatable_size;
u64 buffer_pool_max_allocate_size;
u64 pooled_buffer_failed_ideal_allocation_count_on_async_access;
u8 reserved[0x20];
};
static_assert(sizeof(MemoryReportInfo) == 0x80);
static_assert(util::is_pod<MemoryReportInfo>::value);
Result GetAndClearMemoryReportInfo(MemoryReportInfo *out);
}

View File

@@ -1,88 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/impl/fs_newable.hpp>
#include <stratosphere/fs/fs_istorage.hpp>
#include <stratosphere/fs/fs_query_range.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
class MemoryStorage : public ::ams::fs::IStorage, public ::ams::fs::impl::Newable {
private:
u8 * const m_buf;
const s64 m_size;
public:
MemoryStorage(void *b, s64 sz) : m_buf(static_cast<u8 *>(b)), m_size(sz) { /* .. */ }
public:
virtual Result Read(s64 offset, void *buffer, size_t size) override {
/* Succeed immediately on zero-sized read. */
R_SUCCEED_IF(size == 0);
/* Validate arguments. */
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
R_TRY(IStorage::CheckAccessRange(offset, size, m_size));
/* Copy from memory. */
std::memcpy(buffer, m_buf + offset, size);
R_SUCCEED();
}
virtual Result Write(s64 offset, const void *buffer, size_t size) override {
/* Succeed immediately on zero-sized write. */
R_SUCCEED_IF(size == 0);
/* Validate arguments. */
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
R_TRY(IStorage::CheckAccessRange(offset, size, m_size));
/* Copy to memory. */
std::memcpy(m_buf + offset, buffer, size);
R_SUCCEED();
}
virtual Result Flush() override {
R_SUCCEED();
}
virtual Result GetSize(s64 *out) override {
*out = m_size;
R_SUCCEED();
}
virtual Result SetSize(s64 size) override {
AMS_UNUSED(size);
R_THROW(fs::ResultUnsupportedSetSizeForMemoryStorage());
}
virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override {
AMS_UNUSED(offset, size, src, src_size);
switch (op_id) {
case OperationId::Invalidate:
R_SUCCEED();
case OperationId::QueryRange:
R_UNLESS(dst != nullptr, fs::ResultNullptrArgument());
R_UNLESS(dst_size == sizeof(QueryRangeInfo), fs::ResultInvalidSize());
reinterpret_cast<QueryRangeInfo *>(dst)->Clear();
R_SUCCEED();
default:
R_THROW(fs::ResultUnsupportedOperateRangeForMemoryStorage());
}
}
};
}

View File

@@ -1,57 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs {
constexpr inline size_t MmcCidSize = 0x10;
constexpr inline size_t MmcExtendedCsdSize = 0x200;
constexpr inline int MmcExtendedCsdOffsetReEolInfo = 267;
constexpr inline int MmcExtendedCsdOffsetDeviceLifeTimeEstTypA = 268;
constexpr inline int MmcExtendedCsdOffsetDeviceLifeTimeEstTypB = 269;
enum MmcSpeedMode {
MmcSpeedMode_Identification = 0,
MmcSpeedMode_LegacySpeed = 1,
MmcSpeedMode_HighSpeed = 2,
MmcSpeedMode_Hs200 = 3,
MmcSpeedMode_Hs400 = 4,
MmcSpeedMode_Unknown = 5,
};
enum class MmcPartition {
UserData = 0,
BootPartition1 = 1,
BootPartition2 = 2,
};
Result GetMmcCid(void *dst, size_t size);
inline void ClearMmcCidSerialNumber(u8 *cid) {
/* Clear the serial number from the cid. */
std::memset(cid + 1, 0, 4);
}
Result GetMmcSpeedMode(MmcSpeedMode *out);
Result GetMmcPatrolCount(u32 *out);
Result GetMmcExtendedCsd(void *dst, size_t size);
}

View File

@@ -1,28 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
constexpr inline size_t MountNameLengthMax = 15;
Result ConvertToFsCommonPath(char *dst, size_t dst_size, const char *src);
void Unmount(const char *mount_name);
}

View File

@@ -1,34 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
enum class OperationId : s64 {
FillZero = 0,
DestroySignature = 1,
Invalidate = 2,
QueryRange = 3,
QueryUnpreparedRange = 4,
QueryLazyLoadCompletionRate = 5,
SetLazyLoadPriority = 6,
ReadLazyLoadFileForciblyForDebug = 10001,
};
}

View File

@@ -1,675 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_memory_management.hpp>
#include <stratosphere/fs/impl/fs_common_mount_name.hpp>
#include <stratosphere/fs/fs_path_utility.hpp>
namespace ams::fs {
class DirectoryPathParser;
/* ACCURATE_TO_VERSION: 13.4.0.0 */
/* NOTE: Intentional inaccuracy in custom WriteBuffer class, to save 0x10 bytes (0x28 -> 0x18) over Nintendo's implementation. */
class Path {
NON_COPYABLE(Path);
NON_MOVEABLE(Path);
private:
static constexpr const char *EmptyPath = "";
static constexpr size_t WriteBufferAlignmentLength = 8;
private:
friend class DirectoryPathParser;
public:
class WriteBuffer {
NON_COPYABLE(WriteBuffer);
private:
char *m_buffer;
size_t m_length_and_is_normalized;
public:
constexpr WriteBuffer() : m_buffer(nullptr), m_length_and_is_normalized(0) { /* ... */ }
constexpr ~WriteBuffer() {
if (m_buffer != nullptr) {
::ams::fs::impl::Deallocate(m_buffer, this->GetLength());
this->ResetBuffer();
}
}
constexpr WriteBuffer(WriteBuffer &&rhs) : m_buffer(rhs.m_buffer), m_length_and_is_normalized(rhs.m_length_and_is_normalized) {
rhs.ResetBuffer();
}
constexpr WriteBuffer &operator=(WriteBuffer &&rhs) {
if (m_buffer != nullptr) {
::ams::fs::impl::Deallocate(m_buffer, this->GetLength());
}
m_buffer = rhs.m_buffer;
m_length_and_is_normalized = rhs.m_length_and_is_normalized;
rhs.ResetBuffer();
return *this;
}
std::unique_ptr<char[], ::ams::fs::impl::Deleter> ReleaseBuffer() {
auto released = std::unique_ptr<char[], ::ams::fs::impl::Deleter>(m_buffer, ::ams::fs::impl::Deleter(this->GetLength()));
this->ResetBuffer();
return released;
}
constexpr ALWAYS_INLINE void ResetBuffer() {
m_buffer = nullptr;
this->SetLength(0);
}
constexpr ALWAYS_INLINE char *Get() const {
return m_buffer;
}
constexpr ALWAYS_INLINE size_t GetLength() const {
return m_length_and_is_normalized >> 1;
}
constexpr ALWAYS_INLINE bool IsNormalized() const {
return static_cast<bool>(m_length_and_is_normalized & 1);
}
constexpr ALWAYS_INLINE void SetNormalized() {
m_length_and_is_normalized |= static_cast<size_t>(1);
}
constexpr ALWAYS_INLINE void SetNotNormalized() {
m_length_and_is_normalized &= ~static_cast<size_t>(1);
}
private:
constexpr ALWAYS_INLINE WriteBuffer(char *buffer, size_t length) : m_buffer(buffer), m_length_and_is_normalized(0) {
this->SetLength(length);
}
public:
static WriteBuffer Make(size_t length) {
if (void *alloc = ::ams::fs::impl::Allocate(length); alloc != nullptr) {
return WriteBuffer(static_cast<char *>(alloc), length);
} else {
return WriteBuffer();
}
}
private:
constexpr ALWAYS_INLINE void SetLength(size_t size) {
m_length_and_is_normalized = (m_length_and_is_normalized & 1) | (size << 1);
}
};
private:
const char *m_str;
WriteBuffer m_write_buffer;
public:
constexpr Path() : m_str(EmptyPath), m_write_buffer() {
/* ... */
}
constexpr Path(const char *s, util::ConstantInitializeTag) : m_str(s), m_write_buffer() {
m_write_buffer.SetNormalized();
}
constexpr ~Path() { /* ... */ }
std::unique_ptr<char[], ::ams::fs::impl::Deleter> ReleaseBuffer() {
/* Check pre-conditions. */
AMS_ASSERT(m_write_buffer.Get() != nullptr);
/* Reset. */
m_str = EmptyPath;
/* Release our write buffer. */
return m_write_buffer.ReleaseBuffer();
}
constexpr Result SetShallowBuffer(const char *buffer) {
/* Check pre-conditions. */
AMS_ASSERT(m_write_buffer.GetLength() == 0);
/* Check the buffer is valid. */
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
/* Set buffer. */
this->SetReadOnlyBuffer(buffer);
/* Note that we're normalized. */
this->SetNormalized();
R_SUCCEED();
}
constexpr const char *GetString() const {
/* Check pre-conditions. */
AMS_ASSERT(this->IsNormalized());
return m_str;
}
constexpr size_t GetLength() const {
if (std::is_constant_evaluated()) {
return util::Strlen(this->GetString());
} else {
return std::strlen(this->GetString());
}
}
constexpr bool IsEmpty() const {
return *m_str == '\x00';
}
constexpr bool IsMatchHead(const char *p, size_t len) const {
return util::Strncmp(this->GetString(), p, len) == 0;
}
Result Initialize(const Path &rhs) {
/* Check the other path is normalized. */
const bool normalized = rhs.IsNormalized();
R_UNLESS(normalized, fs::ResultNotNormalized());
/* Allocate buffer for our path. */
const auto len = rhs.GetLength();
R_TRY(this->Preallocate(len + 1));
/* Copy the path. */
const size_t copied = util::Strlcpy<char>(m_write_buffer.Get(), rhs.GetString(), len + 1);
R_UNLESS(copied == len, fs::ResultUnexpectedInPathA());
/* Set normalized. */
this->SetNormalized();
R_SUCCEED();
}
Result Initialize(const char *path, size_t len) {
/* Check the path is valid. */
R_UNLESS(path != nullptr, fs::ResultNullptrArgument());
/* Initialize. */
R_TRY(this->InitializeImpl(path, len));
/* Set not normalized. */
this->SetNotNormalized();
R_SUCCEED();
}
Result Initialize(const char *path) {
/* Check the path is valid. */
R_UNLESS(path != nullptr, fs::ResultNullptrArgument());
R_RETURN(this->Initialize(path, std::strlen(path)));
}
Result InitializeWithFormat(const char *fmt, ...) __attribute__((format (printf, 2, 3))) {
/* Check the format string is valid. */
R_UNLESS(fmt != nullptr, fs::ResultNullptrArgument());
/* Create the va_list for formatting. */
std::va_list vl;
va_start(vl, fmt);
/* Determine how big the string will be. */
char dummy;
const auto len = util::VSNPrintf(std::addressof(dummy), 0, fmt, vl);
/* Allocate buffer for our path. */
R_TRY(this->Preallocate(len + 1));
/* Format our path into our new buffer. */
const auto real_len = util::VSNPrintf(m_write_buffer.Get(), m_write_buffer.GetLength(), fmt, vl);
AMS_ASSERT(real_len == len);
AMS_UNUSED(real_len);
/* Finish the va_list. */
va_end(vl);
/* Set not normalized. */
this->SetNotNormalized();
R_SUCCEED();
}
Result InitializeWithReplaceBackslash(const char *path) {
/* Check the path is valid. */
R_UNLESS(path != nullptr, fs::ResultNullptrArgument());
/* Initialize. */
R_TRY(this->InitializeImpl(path, std::strlen(path)));
/* Replace slashes as desired. */
if (const auto write_buffer_length = m_write_buffer.GetLength(); write_buffer_length > 1) {
fs::Replace(m_write_buffer.Get(), write_buffer_length - 1, '\\', '/');
}
/* Set not normalized. */
this->SetNotNormalized();
R_SUCCEED();
}
Result InitializeWithReplaceForwardSlashes(const char *path) {
/* Check the path is valid. */
R_UNLESS(path != nullptr, fs::ResultNullptrArgument());
/* Initialize. */
R_TRY(this->InitializeImpl(path, std::strlen(path)));
/* Replace slashes as desired. */
if (m_write_buffer.GetLength() > 1) {
if (auto *p = m_write_buffer.Get(); p[0] == '/' && p[1] == '/') {
p[0] = '\\';
p[1] = '\\';
}
}
/* Set not normalized. */
this->SetNotNormalized();
R_SUCCEED();
}
Result InitializeWithReplaceUnc(const char *path) {
/* Check the path is valid. */
R_UNLESS(path != nullptr, fs::ResultNullptrArgument());
/* Initialize. */
R_TRY(this->InitializeImpl(path, std::strlen(path)));
/* Set not normalized. */
this->SetNotNormalized();
/* Replace unc as desired. */
if (m_str[0]) {
auto *p = m_write_buffer.Get();
/* Replace :/// -> \\ as needed. */
if (auto *sep = std::strstr(p, ":///"); sep != nullptr) {
sep[0] = '\\';
sep[1] = '\\';
}
/* Edit path prefix. */
if (!util::Strncmp(p, AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME AMS_FS_IMPL_MOUNT_NAME_DELIMITER "/", AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME_LEN + AMS_FS_IMPL_MOUNT_NAME_DELIMITER_LEN + 1)) {
static_assert((AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME AMS_FS_IMPL_MOUNT_NAME_DELIMITER)[AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME_LEN + AMS_FS_IMPL_MOUNT_NAME_DELIMITER_LEN - 1] == '/');
p[AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME_LEN + AMS_FS_IMPL_MOUNT_NAME_DELIMITER_LEN - 1] = '\\';
p[AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME_LEN + AMS_FS_IMPL_MOUNT_NAME_DELIMITER_LEN - 0] = '\\';
}
if (p[0] == '/' && p[1] == '/') {
p[0] = '\\';
p[1] = '\\';
}
}
R_SUCCEED();
}
Result InitializeWithNormalization(const char *path, size_t size) {
/* Check the path is valid. */
R_UNLESS(path != nullptr, fs::ResultNullptrArgument());
/* Initialize. */
R_TRY(this->InitializeImpl(path, size));
/* Set not normalized. */
this->SetNotNormalized();
/* Perform normalization. */
fs::PathFlags path_flags;
if (fs::IsPathRelative(m_str)) {
path_flags.AllowRelativePath();
} else if (fs::IsWindowsPath(m_str, true)) {
path_flags.AllowWindowsPath();
} else {
/* NOTE: In this case, Nintendo checks is normalized, then sets is normalized, then returns success. */
/* This seems like a bug. */
size_t dummy;
bool normalized;
R_TRY(PathFormatter::IsNormalized(std::addressof(normalized), std::addressof(dummy), m_str));
this->SetNormalized();
R_SUCCEED();
}
/* Normalize. */
R_TRY(this->Normalize(path_flags));
this->SetNormalized();
R_SUCCEED();
}
Result InitializeWithNormalization(const char *path) {
/* Check the path is valid. */
R_UNLESS(path != nullptr, fs::ResultNullptrArgument());
R_RETURN(this->InitializeWithNormalization(path, std::strlen(path)));
}
Result InitializeAsEmpty() {
/* Clear our buffer. */
this->ClearBuffer();
/* Set normalized. */
this->SetNormalized();
R_SUCCEED();
}
Result AppendChild(const char *child) {
/* Check the path is valid. */
R_UNLESS(child != nullptr, fs::ResultNullptrArgument());
/* Basic checks. If we hvea a path and the child is empty, we have nothing to do. */
const char *c = child;
if (m_str[0]) {
/* Skip an early separator. */
if (*c == '/') {
++c;
}
R_SUCCEED_IF(*c == '\x00');
}
/* If we don't have a string, we can just initialize. */
auto cur_len = std::strlen(m_str);
if (cur_len == 0) {
R_RETURN(this->Initialize(child));
}
/* Remove a trailing separator. */
if (m_str[cur_len - 1] == '/' || m_str[cur_len - 1] == '\\') {
--cur_len;
}
/* Get the child path's length. */
auto child_len = std::strlen(c);
/* Reset our write buffer. */
WriteBuffer old_write_buffer;
if (m_write_buffer.Get() != nullptr) {
old_write_buffer = std::move(m_write_buffer);
this->ClearBuffer();
}
/* Pre-allocate the new buffer. */
R_TRY(this->Preallocate(cur_len + 1 + child_len + 1));
/* Get our write buffer. */
auto *dst = m_write_buffer.Get();
if (old_write_buffer.Get() != nullptr && cur_len > 0) {
util::Strlcpy<char>(dst, old_write_buffer.Get(), cur_len + 1);
}
/* Add separator. */
dst[cur_len] = '/';
/* Copy the child path. */
const size_t copied = util::Strlcpy<char>(dst + cur_len + 1, c, child_len + 1);
R_UNLESS(copied == child_len, fs::ResultUnexpectedInPathA());
R_SUCCEED();
}
Result AppendChild(const Path &rhs) {
R_RETURN(this->AppendChild(rhs.GetString()));
}
Result Combine(const Path &parent, const Path &child) {
/* Get the lengths. */
const auto p_len = parent.GetLength();
const auto c_len = child.GetLength();
/* Allocate our buffer. */
R_TRY(this->Preallocate(p_len + c_len + 1));
/* Initialize as parent. */
R_TRY(this->Initialize(parent));
/* If we're empty, we can just initialize as child. */
if (this->IsEmpty()) {
R_TRY(this->Initialize(child));
} else {
/* Otherwise, we should append the child. */
R_TRY(this->AppendChild(child));
}
R_SUCCEED();
}
Result RemoveChild() {
/* If we don't have a write-buffer, ensure that we have one. */
if (m_write_buffer.Get() == nullptr) {
if (const auto len = std::strlen(m_str); len > 0) {
R_TRY(this->Preallocate(len));
util::Strlcpy<char>(m_write_buffer.Get(), m_str, len + 1);
}
}
/* Check that it's possible for us to remove a child. */
auto *p = m_write_buffer.Get();
s32 len = std::strlen(p);
R_UNLESS(len != 1 || (p[0] != '/' && p[0] != '.'), fs::ResultNotImplemented());
/* Handle a trailing separator. */
if (len > 0 && (p[len - 1] == '\\' || p[len - 1] == '/')) {
--len;
}
/* Remove the child path segment. */
while ((--len) >= 0 && p[len]) {
if (p[len] == '/' || p[len] == '\\') {
if (len > 0) {
p[len] = 0;
} else {
p[1] = 0;
len = 1;
}
break;
}
}
/* Check that length remains > 0. */
R_UNLESS(len > 0, fs::ResultNotImplemented());
R_SUCCEED();
}
Result Normalize(const PathFlags &flags) {
/* If we're already normalized, nothing to do. */
R_SUCCEED_IF(this->IsNormalized());
/* Check if we're normalized. */
bool normalized;
size_t dummy;
R_TRY(PathFormatter::IsNormalized(std::addressof(normalized), std::addressof(dummy), m_str, flags));
/* If we're not normalized, normalize. */
if (!normalized) {
/* Determine necessary buffer length. */
auto len = m_write_buffer.GetLength();
if (flags.IsRelativePathAllowed() && fs::IsPathRelative(m_str)) {
len += 2;
}
if (flags.IsWindowsPathAllowed() && fs::IsWindowsPath(m_str, true)) {
len += 1;
}
/* Allocate a new buffer. */
const size_t size = util::AlignUp(len, WriteBufferAlignmentLength);
auto buf = WriteBuffer::Make(size);
R_UNLESS(buf.Get() != nullptr, fs::ResultAllocationMemoryFailedMakeUnique());
/* Normalize into it. */
R_TRY(PathFormatter::Normalize(buf.Get(), size, m_write_buffer.Get(), m_write_buffer.GetLength(), flags));
/* Set the normalized buffer as our buffer. */
this->SetModifiableBuffer(std::move(buf));
}
/* Set normalized. */
this->SetNormalized();
R_SUCCEED();
}
private:
void ClearBuffer() {
m_write_buffer.ResetBuffer();
m_str = EmptyPath;
}
void SetModifiableBuffer(WriteBuffer &&buffer) {
/* Check pre-conditions. */
AMS_ASSERT(buffer.Get() != nullptr);
AMS_ASSERT(buffer.GetLength() > 0);
AMS_ASSERT(util::IsAligned(buffer.GetLength(), WriteBufferAlignmentLength));
/* Get whether we're normalized. */
if (m_write_buffer.IsNormalized()) {
buffer.SetNormalized();
} else {
buffer.SetNotNormalized();
}
/* Set write buffer. */
m_write_buffer = std::move(buffer);
m_str = m_write_buffer.Get();
}
constexpr void SetReadOnlyBuffer(const char *buffer) {
m_str = buffer;
m_write_buffer.ResetBuffer();
}
Result Preallocate(size_t length) {
/* Allocate additional space, if needed. */
if (length > m_write_buffer.GetLength()) {
/* Allocate buffer. */
const size_t size = util::AlignUp(length, WriteBufferAlignmentLength);
auto buf = WriteBuffer::Make(size);
R_UNLESS(buf.Get() != nullptr, fs::ResultAllocationMemoryFailedMakeUnique());
/* Set write buffer. */
this->SetModifiableBuffer(std::move(buf));
}
R_SUCCEED();
}
Result InitializeImpl(const char *path, size_t size) {
if (size > 0 && path[0]) {
/* Pre allocate a buffer for the path. */
R_TRY(this->Preallocate(size + 1));
/* Copy the path. */
const size_t copied = util::Strlcpy<char>(m_write_buffer.Get(), path, size + 1);
R_UNLESS(copied >= size, fs::ResultUnexpectedInPathA());
} else {
/* We can just clear the buffer. */
this->ClearBuffer();
}
R_SUCCEED();
}
constexpr char *GetWriteBuffer() {
AMS_ASSERT(m_write_buffer.Get() != nullptr);
return m_write_buffer.Get();
}
constexpr ALWAYS_INLINE size_t GetWriteBufferLength() const {
return m_write_buffer.GetLength();
}
constexpr ALWAYS_INLINE bool IsNormalized() const { return m_write_buffer.IsNormalized(); }
constexpr ALWAYS_INLINE void SetNormalized() { m_write_buffer.SetNormalized(); }
constexpr ALWAYS_INLINE void SetNotNormalized() { m_write_buffer.SetNotNormalized(); }
public:
ALWAYS_INLINE bool operator==(const fs::Path &rhs) const { return std::strcmp(this->GetString(), rhs.GetString()) == 0; }
ALWAYS_INLINE bool operator!=(const fs::Path &rhs) const { return !(*this == rhs); }
ALWAYS_INLINE bool operator==(const char *p) const { return std::strcmp(this->GetString(), p) == 0; }
ALWAYS_INLINE bool operator!=(const char *p) const { return !(*this == p); }
};
consteval fs::Path MakeConstantPath(const char *s) { return fs::Path(s, util::ConstantInitializeTag{}); }
inline Result SetUpFixedPath(fs::Path *out, const char *s) {
/* Verify the path is normalized. */
bool normalized;
size_t dummy;
R_TRY(PathNormalizer::IsNormalized(std::addressof(normalized), std::addressof(dummy), s));
R_UNLESS(normalized, fs::ResultInvalidPathFormat());
/* Set the fixed path. */
R_RETURN(out->SetShallowBuffer(s));
}
inline Result SetUpFixedPathSingleEntry(fs::Path *out, char *buf, size_t buf_size, const char *e) {
/* Print the path into the buffer. */
const size_t len = util::TSNPrintf(buf, buf_size, "/%s", e);
R_UNLESS(len < buf_size, fs::ResultInvalidArgument());
/* Set up the path. */
R_RETURN(SetUpFixedPath(out, buf));
}
inline Result SetUpFixedPathDoubleEntry(fs::Path *out, char *buf, size_t buf_size, const char *e, const char *e2) {
/* Print the path into the buffer. */
const size_t len = util::TSNPrintf(buf, buf_size, "/%s/%s", e, e2);
R_UNLESS(len < buf_size, fs::ResultInvalidArgument());
/* Set up the path. */
R_RETURN(SetUpFixedPath(out, buf));
}
inline Result SetUpFixedPathSaveId(fs::Path *out, char *buf, size_t buf_size, u64 id) {
/* Print the path into the buffer. */
const size_t len = util::TSNPrintf(buf, buf_size, "/%016" PRIx64 "", id);
R_UNLESS(len < buf_size, fs::ResultInvalidArgument());
/* Set up the path. */
R_RETURN(SetUpFixedPath(out, buf));
}
inline Result SetUpFixedPathSaveMetaName(fs::Path *out, char *buf, size_t buf_size, u32 type) {
/* Print the path into the buffer. */
const size_t len = util::TSNPrintf(buf, buf_size, "/%08" PRIx32 ".meta", type);
R_UNLESS(len < buf_size, fs::ResultInvalidArgument());
/* Set up the path. */
R_RETURN(SetUpFixedPath(out, buf));
}
inline Result SetUpFixedPathSaveMetaDir(fs::Path *out, char *buf, size_t buf_size, u64 id) {
/* Print the path into the buffer. */
const size_t len = util::TSNPrintf(buf, buf_size, "/saveMeta/%016" PRIx64 "", id);
R_UNLESS(len < buf_size, fs::ResultInvalidArgument());
/* Set up the path. */
R_RETURN(SetUpFixedPath(out, buf));
}
constexpr inline bool IsWindowsDriveRootPath(const fs::Path &path) {
const char * const str = path.GetString();
return fs::IsWindowsDrive(str) && (str[2] == StringTraits::DirectorySeparator || str[2] == StringTraits::AlternateDirectorySeparator) && str[3] == StringTraits::NullTerminator;
}
}

View File

@@ -1,45 +0,0 @@
/*
* Copyright (c) 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::fs {
/* ACCURATE_TO_VERSION: Unknown */
enum Priority {
Priority_Realtime = 0,
Priority_Normal = 1,
Priority_Low = 2,
};
enum PriorityRaw {
PriorityRaw_Realtime = 0,
PriorityRaw_Normal = 1,
PriorityRaw_Low = 2,
PriorityRaw_Background = 3,
};
Priority GetPriorityOnCurrentThread();
Priority GetPriority(os::ThreadType *thread);
PriorityRaw GetPriorityRawOnCurrentThread();
PriorityRaw GetPriorityRaw(os::ThreadType *thread);
void SetPriorityOnCurrentThread(Priority prio);
void SetPriority(os::ThreadType *thread, Priority prio);
void SetPriorityRawOnCurrentThread(PriorityRaw prio);
void SetPriorityRaw(os::ThreadType *thread, PriorityRaw prio);
}

View File

@@ -1,26 +0,0 @@
/*
* Copyright (c) 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>
#include <stratosphere/fs/fs_content_attributes.hpp>
#include <stratosphere/ncm/ncm_ids.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: 17.5.0.0 */
Result GetProgramId(ncm::ProgramId *out, const char *path, fs::ContentAttributes attr);
}

View File

@@ -1,32 +0,0 @@
/*
* Copyright (c) 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>
#include <stratosphere/ncm/ncm_ids.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
struct ProgramIndexMapInfo {
ncm::ProgramId program_id;
ncm::ProgramId base_program_id;
u8 program_index;
u8 pad[0xF];
};
static_assert(util::is_pod<ProgramIndexMapInfo>::value);
static_assert(sizeof(ProgramIndexMapInfo) == 0x20);
}

View File

@@ -1,58 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_file.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
struct QueryRangeInfo {
s32 aes_ctr_key_type;
s32 speed_emulation_type;
u8 reserved[0x38];
void Clear() {
this->aes_ctr_key_type = 0;
this->speed_emulation_type = 0;
std::memset(this->reserved, 0, sizeof(this->reserved));
}
void Merge(const QueryRangeInfo &rhs) {
this->aes_ctr_key_type |= rhs.aes_ctr_key_type;
this->speed_emulation_type |= rhs.speed_emulation_type;
}
};
static_assert(util::is_pod<QueryRangeInfo>::value);
static_assert(sizeof(QueryRangeInfo) == 0x40);
#if defined(ATMOSPHERE_OS_HORIZON)
static_assert(sizeof(QueryRangeInfo) == sizeof(::FsRangeInfo));
#endif
using FileQueryRangeInfo = QueryRangeInfo;
using StorageQueryRangeInfo = QueryRangeInfo;
Result QueryRange(QueryRangeInfo *out, FileHandle handle, s64 offset, s64 size);
enum class AesCtrKeyTypeFlag : s32 {
InternalKeyForSoftwareAes = (1 << 0),
InternalKeyForHardwareAes = (1 << 1),
ExternalKeyForHardwareAes = (1 << 2),
};
}

View File

@@ -1,176 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/impl/fs_newable.hpp>
#include <stratosphere/fs/fsa/fs_ifile.hpp>
#include <stratosphere/fs/fsa/fs_idirectory.hpp>
#include <stratosphere/fs/fsa/fs_ifilesystem.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
namespace {
class ReadOnlyFile : public fsa::IFile, public impl::Newable {
NON_COPYABLE(ReadOnlyFile);
NON_MOVEABLE(ReadOnlyFile);
private:
std::unique_ptr<fsa::IFile> m_base_file;
public:
explicit ReadOnlyFile(std::unique_ptr<fsa::IFile> &&f) : m_base_file(std::move(f)) { AMS_ASSERT(m_base_file != nullptr); }
virtual ~ReadOnlyFile() { /* ... */ }
private:
virtual Result DoRead(size_t *out, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) override final {
R_RETURN(m_base_file->Read(out, offset, buffer, size, option));
}
virtual Result DoGetSize(s64 *out) override final {
R_RETURN(m_base_file->GetSize(out));
}
virtual Result DoFlush() override final {
R_SUCCEED();
}
virtual Result DoWrite(s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) override final {
bool need_append;
R_TRY(this->DryWrite(std::addressof(need_append), offset, size, option, fs::OpenMode_Read));
AMS_ASSERT(!need_append);
AMS_UNUSED(buffer);
R_THROW(fs::ResultUnsupportedWriteForReadOnlyFile());
}
virtual Result DoSetSize(s64 size) override final {
R_TRY(this->DrySetSize(size, fs::OpenMode_Read));
R_THROW(fs::ResultUnsupportedWriteForReadOnlyFile());
}
virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override final {
switch (op_id) {
case OperationId::Invalidate:
case OperationId::QueryRange:
R_RETURN(m_base_file->OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
default:
R_THROW(fs::ResultUnsupportedOperateRangeForReadOnlyFile());
}
}
public:
virtual sf::cmif::DomainObjectId GetDomainObjectId() const override {
return m_base_file->GetDomainObjectId();
}
};
}
template<typename T>
class ReadOnlyFileSystemTemplate : public fsa::IFileSystem, public impl::Newable {
NON_COPYABLE(ReadOnlyFileSystemTemplate);
NON_MOVEABLE(ReadOnlyFileSystemTemplate);
private:
T m_base_fs;
public:
explicit ReadOnlyFileSystemTemplate(T &&fs) : m_base_fs(std::move(fs)) { /* ... */ }
virtual ~ReadOnlyFileSystemTemplate() { /* ... */ }
private:
virtual Result DoOpenFile(std::unique_ptr<fsa::IFile> *out_file, const fs::Path &path, OpenMode mode) override final {
/* Only allow opening files with mode = read. */
R_UNLESS((mode & fs::OpenMode_All) == fs::OpenMode_Read, fs::ResultInvalidOpenMode());
std::unique_ptr<fsa::IFile> base_file;
R_TRY(m_base_fs->OpenFile(std::addressof(base_file), path, mode));
auto read_only_file = std::make_unique<ReadOnlyFile>(std::move(base_file));
R_UNLESS(read_only_file != nullptr, fs::ResultAllocationMemoryFailedInReadOnlyFileSystemA());
*out_file = std::move(read_only_file);
R_SUCCEED();
}
virtual Result DoOpenDirectory(std::unique_ptr<fsa::IDirectory> *out_dir, const fs::Path &path, OpenDirectoryMode mode) override final {
R_RETURN(m_base_fs->OpenDirectory(out_dir, path, mode));
}
virtual Result DoGetEntryType(DirectoryEntryType *out, const fs::Path &path) override final {
R_RETURN(m_base_fs->GetEntryType(out, path));
}
virtual Result DoCommit() override final {
R_SUCCEED();
}
virtual Result DoCreateFile(const fs::Path &path, s64 size, int flags) override final {
AMS_UNUSED(path, size, flags);
R_THROW(fs::ResultUnsupportedWriteForReadOnlyFileSystem());
}
virtual Result DoDeleteFile(const fs::Path &path) override final {
AMS_UNUSED(path);
R_THROW(fs::ResultUnsupportedWriteForReadOnlyFileSystem());
}
virtual Result DoCreateDirectory(const fs::Path &path) override final {
AMS_UNUSED(path);
R_THROW(fs::ResultUnsupportedWriteForReadOnlyFileSystem());
}
virtual Result DoDeleteDirectory(const fs::Path &path) override final {
AMS_UNUSED(path);
R_THROW(fs::ResultUnsupportedWriteForReadOnlyFileSystem());
}
virtual Result DoDeleteDirectoryRecursively(const fs::Path &path) override final {
AMS_UNUSED(path);
R_THROW(fs::ResultUnsupportedWriteForReadOnlyFileSystem());
}
virtual Result DoRenameFile(const fs::Path &old_path, const fs::Path &new_path) override final {
AMS_UNUSED(old_path, new_path);
R_THROW(fs::ResultUnsupportedWriteForReadOnlyFileSystem());
}
virtual Result DoRenameDirectory(const fs::Path &old_path, const fs::Path &new_path) override final {
AMS_UNUSED(old_path, new_path);
R_THROW(fs::ResultUnsupportedWriteForReadOnlyFileSystem());
}
virtual Result DoCleanDirectoryRecursively(const fs::Path &path) override final {
AMS_UNUSED(path);
R_THROW(fs::ResultUnsupportedWriteForReadOnlyFileSystem());
}
virtual Result DoGetFreeSpaceSize(s64 *out, const fs::Path &path) override final {
R_RETURN(m_base_fs->GetFreeSpaceSize(out, path));
}
virtual Result DoGetTotalSpaceSize(s64 *out, const fs::Path &path) override final {
AMS_UNUSED(out, path);
R_THROW(fs::ResultUnsupportedGetTotalSpaceSizeForReadOnlyFileSystem());
}
virtual Result DoCommitProvisionally(s64 counter) override final {
AMS_UNUSED(counter);
R_THROW(fs::ResultUnsupportedCommitProvisionallyForReadOnlyFileSystem());
}
};
using ReadOnlyFileSystem = ReadOnlyFileSystemTemplate<std::unique_ptr<::ams::fs::fsa::IFileSystem>>;
using ReadOnlyFileSystemShared = ReadOnlyFileSystemTemplate<std::shared_ptr<::ams::fs::fsa::IFileSystem>>;
}

View File

@@ -1,238 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/impl/fs_newable.hpp>
#include <stratosphere/fs/fsa/fs_ifile.hpp>
#include <stratosphere/fs/fsa/fs_idirectory.hpp>
#include <stratosphere/fs/fsa/fs_ifilesystem.hpp>
#include <stratosphere/fs/fs_query_range.hpp>
namespace ams::fs {
#if defined(ATMOSPHERE_OS_HORIZON)
class RemoteFile : public fsa::IFile, public impl::Newable {
NON_COPYABLE(RemoteFile);
NON_MOVEABLE(RemoteFile);
private:
::FsFile m_base_file;
public:
RemoteFile(const ::FsFile &f) : m_base_file(f) { /* ... */ }
virtual ~RemoteFile() { fsFileClose(std::addressof(m_base_file)); }
public:
virtual Result DoRead(size_t *out, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) override final {
R_RETURN(fsFileRead(std::addressof(m_base_file), offset, buffer, size, option._value, out));
}
virtual Result DoGetSize(s64 *out) override final {
R_RETURN(fsFileGetSize(std::addressof(m_base_file), out));
}
virtual Result DoFlush() override final {
R_RETURN(fsFileFlush(std::addressof(m_base_file)));
}
virtual Result DoWrite(s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) override final {
R_RETURN(fsFileWrite(std::addressof(m_base_file), offset, buffer, size, option._value));
}
virtual Result DoSetSize(s64 size) override final {
R_RETURN(fsFileSetSize(std::addressof(m_base_file), size));
}
virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override final {
AMS_UNUSED(src, src_size);
R_UNLESS(op_id == OperationId::QueryRange, fs::ResultUnsupportedOperateRangeForFileServiceObjectAdapter());
R_UNLESS(dst_size == sizeof(FileQueryRangeInfo), fs::ResultInvalidSize());
R_RETURN(fsFileOperateRange(std::addressof(m_base_file), static_cast<::FsOperationId>(op_id), offset, size, reinterpret_cast<::FsRangeInfo *>(dst)));
}
public:
virtual sf::cmif::DomainObjectId GetDomainObjectId() const override final {
return sf::cmif::DomainObjectId{serviceGetObjectId(const_cast<::Service *>(std::addressof(m_base_file.s)))};
}
};
class RemoteDirectory : public fsa::IDirectory, public impl::Newable {
NON_COPYABLE(RemoteDirectory);
NON_MOVEABLE(RemoteDirectory);
private:
::FsDir m_base_dir;
public:
RemoteDirectory(const ::FsDir &d) : m_base_dir(d) { /* ... */ }
virtual ~RemoteDirectory() { fsDirClose(std::addressof(m_base_dir)); }
public:
virtual Result DoRead(s64 *out_count, DirectoryEntry *out_entries, s64 max_entries) override final {
static_assert(sizeof(*out_entries) == sizeof(::FsDirectoryEntry));
R_RETURN(fsDirRead(std::addressof(m_base_dir), out_count, max_entries, reinterpret_cast<::FsDirectoryEntry *>(out_entries)));
}
virtual Result DoGetEntryCount(s64 *out) override final {
R_RETURN(fsDirGetEntryCount(std::addressof(m_base_dir), out));
}
public:
virtual sf::cmif::DomainObjectId GetDomainObjectId() const override final {
return sf::cmif::DomainObjectId{serviceGetObjectId(const_cast<::Service *>(std::addressof(m_base_dir.s)))};
}
};
class RemoteFileSystem : public fsa::IFileSystem, public impl::Newable {
NON_COPYABLE(RemoteFileSystem);
NON_MOVEABLE(RemoteFileSystem);
private:
::FsFileSystem m_base_fs;
public:
RemoteFileSystem(const ::FsFileSystem &fs) : m_base_fs(fs) { /* ... */ }
virtual ~RemoteFileSystem() { fsFsClose(std::addressof(m_base_fs)); }
private:
Result GetPathForServiceObject(fssrv::sf::Path *out_path, const fs::Path &path) {
/* Copy, ensuring length is in bounds. */
const size_t len = util::Strlcpy<char>(out_path->str, path.GetString(), sizeof(out_path->str));
R_UNLESS(len < sizeof(out_path->str), fs::ResultTooLongPath());
/* Replace directory separators. */
/* TODO: Is this still necessary? We originally had it to not break things on low firmware. */
#if defined(ATMOSPHERE_BOARD_NINTENDO_NX)
fs::Replace(out_path->str, sizeof(out_path->str) - 1, '\\', '/');
#endif
R_SUCCEED();
}
public:
virtual Result DoCreateFile(const fs::Path &path, s64 size, int flags) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
R_RETURN(fsFsCreateFile(std::addressof(m_base_fs), sf_path.str, size, flags));
}
virtual Result DoDeleteFile(const fs::Path &path) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
R_RETURN(fsFsDeleteFile(std::addressof(m_base_fs), sf_path.str));
}
virtual Result DoCreateDirectory(const fs::Path &path) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
R_RETURN(fsFsCreateDirectory(std::addressof(m_base_fs), sf_path.str));
}
virtual Result DoDeleteDirectory(const fs::Path &path) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
R_RETURN(fsFsDeleteDirectory(std::addressof(m_base_fs), sf_path.str));
}
virtual Result DoDeleteDirectoryRecursively(const fs::Path &path) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
R_RETURN(fsFsDeleteDirectoryRecursively(std::addressof(m_base_fs), sf_path.str));
}
virtual Result DoRenameFile(const fs::Path &old_path, const fs::Path &new_path) override final {
fssrv::sf::Path old_sf_path;
fssrv::sf::Path new_sf_path;
R_TRY(GetPathForServiceObject(std::addressof(old_sf_path), old_path));
R_TRY(GetPathForServiceObject(std::addressof(new_sf_path), new_path));
R_RETURN(fsFsRenameFile(std::addressof(m_base_fs), old_sf_path.str, new_sf_path.str));
}
virtual Result DoRenameDirectory(const fs::Path &old_path, const fs::Path &new_path) override final {
fssrv::sf::Path old_sf_path;
fssrv::sf::Path new_sf_path;
R_TRY(GetPathForServiceObject(std::addressof(old_sf_path), old_path));
R_TRY(GetPathForServiceObject(std::addressof(new_sf_path), new_path));
R_RETURN(fsFsRenameDirectory(std::addressof(m_base_fs), old_sf_path.str, new_sf_path.str));
}
virtual Result DoGetEntryType(DirectoryEntryType *out, const fs::Path &path) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
static_assert(sizeof(::FsDirEntryType) == sizeof(DirectoryEntryType));
R_RETURN(fsFsGetEntryType(std::addressof(m_base_fs), sf_path.str, reinterpret_cast<::FsDirEntryType *>(out)));
}
virtual Result DoOpenFile(std::unique_ptr<fsa::IFile> *out_file, const fs::Path &path, OpenMode mode) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
FsFile f;
R_TRY(fsFsOpenFile(std::addressof(m_base_fs), sf_path.str, mode, std::addressof(f)));
auto file = std::make_unique<RemoteFile>(f);
R_UNLESS(file != nullptr, fs::ResultAllocationMemoryFailedNew());
*out_file = std::move(file);
R_SUCCEED();
}
virtual Result DoOpenDirectory(std::unique_ptr<fsa::IDirectory> *out_dir, const fs::Path &path, OpenDirectoryMode mode) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
FsDir d;
R_TRY(fsFsOpenDirectory(std::addressof(m_base_fs), sf_path.str, mode, std::addressof(d)));
auto dir = std::make_unique<RemoteDirectory>(d);
R_UNLESS(dir != nullptr, fs::ResultAllocationMemoryFailedNew());
*out_dir = std::move(dir);
R_SUCCEED();
}
virtual Result DoCommit() override final {
R_RETURN(fsFsCommit(std::addressof(m_base_fs)));
}
virtual Result DoGetFreeSpaceSize(s64 *out, const fs::Path &path) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
R_RETURN(fsFsGetFreeSpace(std::addressof(m_base_fs), sf_path.str, out));
}
virtual Result DoGetTotalSpaceSize(s64 *out, const fs::Path &path) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
R_RETURN(fsFsGetTotalSpace(std::addressof(m_base_fs), sf_path.str, out));
}
virtual Result DoCleanDirectoryRecursively(const fs::Path &path) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
R_RETURN(fsFsCleanDirectoryRecursively(std::addressof(m_base_fs), sf_path.str));
}
virtual Result DoGetFileTimeStampRaw(FileTimeStampRaw *out, const fs::Path &path) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
static_assert(sizeof(FileTimeStampRaw) == sizeof(::FsTimeStampRaw));
R_RETURN(fsFsGetFileTimeStampRaw(std::addressof(m_base_fs), sf_path.str, reinterpret_cast<::FsTimeStampRaw *>(out)));
}
virtual Result DoQueryEntry(char *dst, size_t dst_size, const char *src, size_t src_size, fsa::QueryId query, const fs::Path &path) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
R_RETURN(fsFsQueryEntry(std::addressof(m_base_fs), dst, dst_size, src, src_size, sf_path.str, static_cast<FsFileSystemQueryId>(query)));
}
};
#endif
}

View File

@@ -1,62 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_istorage.hpp>
#include <stratosphere/fs/impl/fs_newable.hpp>
namespace ams::fs {
#if defined(ATMOSPHERE_OS_HORIZON)
class RemoteStorage : public IStorage, public impl::Newable {
NON_COPYABLE(RemoteStorage);
NON_MOVEABLE(RemoteStorage);
private:
::FsStorage m_base_storage;
public:
RemoteStorage(::FsStorage &s) : m_base_storage(s) { /* ... */}
virtual ~RemoteStorage() { fsStorageClose(std::addressof(m_base_storage)); }
public:
virtual Result Read(s64 offset, void *buffer, size_t size) override {
R_RETURN(fsStorageRead(std::addressof(m_base_storage), offset, buffer, size));
};
virtual Result Write(s64 offset, const void *buffer, size_t size) override {
R_RETURN(fsStorageWrite(std::addressof(m_base_storage), offset, buffer, size));
};
virtual Result Flush() override {
R_RETURN(fsStorageFlush(std::addressof(m_base_storage)));
};
virtual Result GetSize(s64 *out_size) override {
R_RETURN(fsStorageGetSize(std::addressof(m_base_storage), out_size));
};
virtual Result SetSize(s64 size) override {
R_RETURN(fsStorageSetSize(std::addressof(m_base_storage), size));
};
virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override {
/* TODO: How to deal with this? */
AMS_UNUSED(dst, dst_size, op_id, offset, size, src, src_size);
R_THROW(fs::ResultUnsupportedOperation());
};
};
#endif
}

View File

@@ -1,25 +0,0 @@
/*
* Copyright (c) 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::fs {
/* ACCURATE_TO_VERSION: Unknown */
void SetEnabledAutoAbort(bool enabled);
void SetResultHandledByApplication(bool application);
}

View File

@@ -1,48 +0,0 @@
/*
* Copyright (c) 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>
#include <stratosphere/fs/fs_content_attributes.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
union RightsId {
u8 data[0x10];
u64 data64[2];
};
static_assert(sizeof(RightsId) == 0x10);
static_assert(util::is_pod<RightsId>::value);
inline bool operator==(const RightsId &lhs, const RightsId &rhs) {
return std::memcmp(std::addressof(lhs), std::addressof(rhs), sizeof(RightsId)) == 0;
}
inline bool operator!=(const RightsId &lhs, const RightsId &rhs) {
return !(lhs == rhs);
}
inline bool operator<(const RightsId &lhs, const RightsId &rhs) {
return std::memcmp(std::addressof(lhs), std::addressof(rhs), sizeof(RightsId)) < 0;
}
constexpr inline RightsId InvalidRightsId = {};
/* Rights ID API */
Result GetRightsId(RightsId *out, const char *path, fs::ContentAttributes attr);
Result GetRightsId(RightsId *out, u8 *out_key_generation, const char *path, fs::ContentAttributes attr);
}

View File

@@ -1,75 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/impl/fs_newable.hpp>
#include <stratosphere/fs/fsa/fs_ifile.hpp>
#include <stratosphere/fs/fsa/fs_idirectory.hpp>
#include <stratosphere/fs/fsa/fs_ifilesystem.hpp>
#include <stratosphere/fs/common/fs_dbm_hierarchical_rom_file_table.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
class RomFsFileSystem : public fsa::IFileSystem, public impl::Newable {
NON_COPYABLE(RomFsFileSystem);
public:
using RomFileTable = HierarchicalRomFileTable;
private:
RomFileTable m_rom_file_table;
IStorage *m_base_storage;
std::unique_ptr<IStorage> m_unique_storage;
std::unique_ptr<IStorage> m_dir_bucket_storage;
std::unique_ptr<IStorage> m_dir_entry_storage;
std::unique_ptr<IStorage> m_file_bucket_storage;
std::unique_ptr<IStorage> m_file_entry_storage;
s64 m_entry_size;
private:
Result GetFileInfo(RomFileTable::FileInfo *out, const char *path);
public:
static Result GetRequiredWorkingMemorySize(size_t *out, IStorage *storage);
public:
RomFsFileSystem();
virtual ~RomFsFileSystem() override;
Result Initialize(IStorage *base, void *work, size_t work_size, bool use_cache);
Result Initialize(std::unique_ptr<IStorage>&& base, void *work, size_t work_size, bool use_cache);
IStorage *GetBaseStorage();
RomFileTable *GetRomFileTable();
Result GetFileBaseOffset(s64 *out, const char *path);
public:
virtual Result DoCreateFile(const fs::Path &path, s64 size, int flags) override;
virtual Result DoDeleteFile(const fs::Path &path) override;
virtual Result DoCreateDirectory(const fs::Path &path) override;
virtual Result DoDeleteDirectory(const fs::Path &path) override;
virtual Result DoDeleteDirectoryRecursively(const fs::Path &path) override;
virtual Result DoRenameFile(const fs::Path &old_path, const fs::Path &new_path) override;
virtual Result DoRenameDirectory(const fs::Path &old_path, const fs::Path &new_path) override;
virtual Result DoGetEntryType(fs::DirectoryEntryType *out, const fs::Path &path) override;
virtual Result DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const fs::Path &path, fs::OpenMode mode) override;
virtual Result DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const fs::Path &path, fs::OpenDirectoryMode mode) override;
virtual Result DoCommit() override;
virtual Result DoGetFreeSpaceSize(s64 *out, const fs::Path &path) override;
virtual Result DoGetTotalSpaceSize(s64 *out, const fs::Path &path) override;
virtual Result DoCleanDirectoryRecursively(const fs::Path &path) override;
/* These aren't accessible as commands. */
virtual Result DoCommitProvisionally(s64 counter) override;
virtual Result DoRollback() override;
};
}

View File

@@ -1,35 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_save_data_types.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
Result DeleteSaveData(SaveDataId id);
Result DeleteSaveData(SaveDataSpaceId space_id, SaveDataId id);
Result GetSaveDataFlags(u32 *out, SaveDataId id);
Result GetSaveDataFlags(u32 *out, SaveDataSpaceId space_id, SaveDataId id);
Result SetSaveDataFlags(SaveDataId id, SaveDataSpaceId space_id, u32 flags);
Result GetSaveDataAvailableSize(s64 *out, SaveDataId id);
Result GetSaveDataJournalSize(s64 *out, SaveDataId id);
Result ExtendSaveData(SaveDataSpaceId space_id, SaveDataId id, s64 available_size, s64 journal_size);
}

View File

@@ -1,25 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_save_data_types.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
Result CommitSaveData(const char *path);
}

View File

@@ -1,184 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
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(util::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 = {};
enum SaveDataFlags : u32 {
SaveDataFlags_None = (0 << 0),
SaveDataFlags_KeepAfterResettingSystemSaveData = (1 << 0),
SaveDataFlags_KeepAfterRefurbishment = (1 << 1),
SaveDataFlags_KeepAfterResettingSystemSaveDataWithoutUserSaveData = (1 << 2),
SaveDataFlags_NeedsSecureDelete = (1 << 3),
};
enum class SaveDataMetaType : u8 {
None = 0,
Thumbnail = 1,
ExtensionContext = 2,
};
struct SaveDataMetaInfo {
u32 size;
SaveDataMetaType type;
u8 reserved[0xB];
};
static_assert(util::is_pod<SaveDataMetaInfo>::value);
static_assert(sizeof(SaveDataMetaInfo) == 0x10);
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(util::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) {
return std::tie(lhs.program_id, lhs.user_id, lhs.system_save_data_id, lhs.index, lhs.rank) <
std::tie(rhs.program_id, rhs.user_id, rhs.system_save_data_id, rhs.index, rhs.rank);
}
constexpr inline bool operator==(const SaveDataAttribute &lhs, const SaveDataAttribute &rhs) {
return std::tie(lhs.program_id, lhs.user_id, lhs.system_save_data_id, lhs.type, lhs.rank, lhs.index) ==
std::tie(rhs.program_id, rhs.user_id, rhs.system_save_data_id, rhs.type, rhs.rank, 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(util::is_pod<SaveDataExtraData>::value);
struct HashSalt {
static constexpr size_t Size = 32;
u8 value[Size];
};
static_assert(util::is_pod<HashSalt>::value);
static_assert(sizeof(HashSalt) == HashSalt::Size);
using SaveDataHashSalt = util::optional<HashSalt>;
}

View File

@@ -1,64 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
class IEventNotifier;
constexpr inline size_t SdCardCidSize = 0x10;
enum SdCardSpeedMode {
SdCardSpeedMode_Identification = 0,
SdCardSpeedMode_DefaultSpeed = 1,
SdCardSpeedMode_HighSpeed = 2,
SdCardSpeedMode_Sdr12 = 3,
SdCardSpeedMode_Sdr25 = 4,
SdCardSpeedMode_Sdr50 = 5,
SdCardSpeedMode_Sdr104 = 6,
SdCardSpeedMode_Ddr50 = 7,
SdCardSpeedMode_Unknown = 8,
};
struct EncryptionSeed {
char value[0x10];
};
static_assert(util::is_pod<EncryptionSeed>::value);
static_assert(sizeof(EncryptionSeed) == 0x10);
Result GetSdCardCid(void *dst, size_t size);
inline void ClearSdCardCidSerialNumber(u8 *cid) {
/* Clear the serial number from the cid. */
std::memset(cid + 2, 0, 4);
}
Result GetSdCardUserAreaSize(s64 *out);
Result GetSdCardProtectedAreaSize(s64 *out);
Result GetSdCardSpeedMode(SdCardSpeedMode *out);
Result MountSdCard(const char *name);
Result MountSdCardErrorReportDirectoryForAtmosphere(const char *name);
Result OpenSdCardDetectionEventNotifier(std::unique_ptr<IEventNotifier> *out);
bool IsSdCardInserted();
}

View File

@@ -1,25 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
bool IsSignedSystemPartitionOnSdCardValid(const char *system_root_path);
bool IsSignedSystemPartitionOnSdCardValidDeprecated();
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
enum class SpeedEmulationMode {
None = 0,
Faster = 1,
Slower = 2,
Random = 3,
};
/* TODO */
/* Result SetSpeedEmulationMode(SpeedEmulationMode mode); */
/* Result GetSpeedEmulationMode(SpeedEmulationMode *out); */
}

View File

@@ -1,28 +0,0 @@
/*
* Copyright (c) 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::fs {
/* ACCURATE_TO_VERSION: Unknown */
enum StorageType : s32 {
StorageType_SaveData = 0,
StorageType_RomFs = 1,
StorageType_Authoring = 2,
};
}

View File

@@ -1,155 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/impl/fs_newable.hpp>
#include <stratosphere/fs/fs_istorage.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
class SubStorage : public ::ams::fs::IStorage, public ::ams::fs::impl::Newable {
private:
std::shared_ptr<IStorage> m_shared_base_storage;
fs::IStorage *m_base_storage;
s64 m_offset;
s64 m_size;
bool m_resizable;
private:
constexpr bool IsValid() const {
return m_base_storage != nullptr;
}
public:
SubStorage() : m_shared_base_storage(), m_base_storage(nullptr), m_offset(0), m_size(0), m_resizable(false) { /* ... */ }
SubStorage(const SubStorage &rhs) : m_shared_base_storage(rhs.m_shared_base_storage), m_base_storage(rhs.m_base_storage), m_offset(rhs.m_offset), m_size(rhs.m_size), m_resizable(rhs.m_resizable) { /* ... */}
SubStorage &operator=(const SubStorage &rhs) {
if (this != std::addressof(rhs)) {
m_shared_base_storage = rhs.m_shared_base_storage;
m_base_storage = rhs.m_base_storage;
m_offset = rhs.m_offset;
m_size = rhs.m_size;
m_resizable = rhs.m_resizable;
}
return *this;
}
SubStorage(IStorage *storage, s64 o, s64 sz) : m_shared_base_storage(), m_base_storage(storage), m_offset(o), m_size(sz), m_resizable(false) {
AMS_ABORT_UNLESS(this->IsValid());
AMS_ABORT_UNLESS(m_offset >= 0);
AMS_ABORT_UNLESS(m_size >= 0);
}
SubStorage(std::shared_ptr<IStorage> storage, s64 o, s64 sz) : m_shared_base_storage(storage), m_base_storage(storage.get()), m_offset(o), m_size(sz), m_resizable(false) {
AMS_ABORT_UNLESS(this->IsValid());
AMS_ABORT_UNLESS(m_offset >= 0);
AMS_ABORT_UNLESS(m_size >= 0);
}
SubStorage(SubStorage *sub, s64 o, s64 sz) : m_shared_base_storage(sub->m_shared_base_storage), m_base_storage(sub->m_base_storage), m_offset(o + sub->m_offset), m_size(sz), m_resizable(false) {
AMS_ABORT_UNLESS(this->IsValid());
AMS_ABORT_UNLESS(m_offset >= 0);
AMS_ABORT_UNLESS(m_size >= 0);
AMS_ABORT_UNLESS(sub->m_size >= o + sz);
}
ALWAYS_INLINE ::ams::fs::IStorage *operator->() {
return this;
}
public:
void SetResizable(bool rsz) {
m_resizable = rsz;
}
public:
virtual Result Read(s64 offset, void *buffer, size_t size) override {
/* Ensure we're initialized. */
R_UNLESS(this->IsValid(), fs::ResultNotInitialized());
/* Succeed immediately on zero-sized operation. */
R_SUCCEED_IF(size == 0);
/* Validate arguments and read. */
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
R_TRY(IStorage::CheckAccessRange(offset, size, m_size));
R_RETURN(m_base_storage->Read(m_offset + offset, buffer, size));
}
virtual Result Write(s64 offset, const void *buffer, size_t size) override{
/* Ensure we're initialized. */
R_UNLESS(this->IsValid(), fs::ResultNotInitialized());
/* Succeed immediately on zero-sized operation. */
R_SUCCEED_IF(size == 0);
/* Validate arguments and write. */
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
R_TRY(IStorage::CheckAccessRange(offset, size, m_size));
R_RETURN(m_base_storage->Write(m_offset + offset, buffer, size));
}
virtual Result Flush() override {
R_UNLESS(this->IsValid(), fs::ResultNotInitialized());
R_RETURN(m_base_storage->Flush());
}
virtual Result SetSize(s64 size) override {
/* Ensure we're initialized and validate arguments. */
R_UNLESS(this->IsValid(), fs::ResultNotInitialized());
R_UNLESS(m_resizable, fs::ResultUnsupportedSetSizeForNotResizableSubStorage());
R_TRY(IStorage::CheckOffsetAndSize(m_offset, size));
/* Ensure that we're allowed to set size. */
s64 cur_size;
R_TRY(m_base_storage->GetSize(std::addressof(cur_size)));
R_UNLESS(cur_size == m_offset + m_size, fs::ResultUnsupportedSetSizeForResizableSubStorage());
/* Set the size. */
R_TRY(m_base_storage->SetSize(m_offset + size));
m_size = size;
R_SUCCEED();
}
virtual Result GetSize(s64 *out) override {
/* Ensure we're initialized. */
R_UNLESS(this->IsValid(), fs::ResultNotInitialized());
*out = m_size;
R_SUCCEED();
}
virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override {
/* Ensure we're initialized. */
R_UNLESS(this->IsValid(), fs::ResultNotInitialized());
/* If we're not invalidating, sanity check arguments. */
if (op_id != fs::OperationId::Invalidate) {
/* Succeed immediately on zero-sized operation other than invalidate. */
R_SUCCEED_IF(size == 0);
/* Check access extents. */
R_TRY(IStorage::CheckOffsetAndSize(offset, size));
}
/* Perform the operation. */
R_RETURN(m_base_storage->OperateRange(dst, dst_size, op_id, m_offset + offset, size, src, src_size));
}
using IStorage::OperateRange;
};
}

View File

@@ -1,27 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
Result QueryMountSystemDataCacheSize(size_t *out, ncm::SystemDataId data_id);
Result MountSystemData(const char *name, ncm::SystemDataId data_id);
Result MountSystemData(const char *name, ncm::SystemDataId data_id, void *cache_buffer, size_t cache_size);
}

View File

@@ -1,41 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_save_data_types.hpp>
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
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);
}

View File

@@ -1,53 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_directory.hpp>
namespace ams::fs::fsa {
/* ACCURATE_TO_VERSION: Unknown */
class IDirectory {
public:
virtual ~IDirectory() { /* ... */ }
Result Read(s64 *out_count, DirectoryEntry *out_entries, s64 max_entries) {
R_UNLESS(out_count != nullptr, fs::ResultNullptrArgument());
if (max_entries == 0) {
*out_count = 0;
R_SUCCEED();
}
R_UNLESS(out_entries != nullptr, fs::ResultNullptrArgument());
R_UNLESS(max_entries > 0, fs::ResultInvalidArgument());
R_RETURN(this->DoRead(out_count, out_entries, max_entries));
}
Result GetEntryCount(s64 *out) {
R_UNLESS(out != nullptr, fs::ResultNullptrArgument());
R_RETURN(this->DoGetEntryCount(out));
}
public:
/* TODO: This is a hack to allow the mitm API to work. Find a better way? */
virtual sf::cmif::DomainObjectId GetDomainObjectId() const = 0;
protected:
/* ...? */
private:
virtual Result DoRead(s64 *out_count, DirectoryEntry *out_entries, s64 max_entries) = 0;
virtual Result DoGetEntryCount(s64 *out) = 0;
};
}

View File

@@ -1,144 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_file.hpp>
#include <stratosphere/fs/fs_filesystem.hpp>
#include <stratosphere/fs/fs_operate_range.hpp>
namespace ams::fs::fsa {
class IFile {
public:
virtual ~IFile() { /* ... */ }
Result Read(size_t *out, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) {
/* Check that we have an output pointer. */
R_UNLESS(out != nullptr, fs::ResultNullptrArgument());
/* If we have nothing to read, just succeed. */
if (size == 0) {
*out = 0;
R_SUCCEED();
}
/* Check that the read is valid. */
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
R_UNLESS(offset >= 0, fs::ResultOutOfRange());
R_UNLESS(util::IsIntValueRepresentable<s64>(size), fs::ResultOutOfRange());
R_UNLESS(util::CanAddWithoutOverflow<s64>(offset, size), fs::ResultOutOfRange());
/* Do the read. */
R_RETURN(this->DoRead(out, offset, buffer, size, option));
}
ALWAYS_INLINE Result Read(size_t *out, s64 offset, void *buffer, size_t size) { R_RETURN(this->Read(out, offset, buffer, size, ReadOption::None)); }
Result GetSize(s64 *out) {
R_UNLESS(out != nullptr, fs::ResultNullptrArgument());
R_RETURN(this->DoGetSize(out));
}
Result Flush() {
R_RETURN(this->DoFlush());
}
Result Write(s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) {
/* Handle the zero-size case. */
if (size == 0) {
if (option.HasFlushFlag()) {
R_TRY(this->Flush());
}
R_SUCCEED();
}
/* Check the write is valid. */
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
R_UNLESS(offset >= 0, fs::ResultOutOfRange());
R_UNLESS(util::IsIntValueRepresentable<s64>(size), fs::ResultOutOfRange());
R_UNLESS(util::CanAddWithoutOverflow<s64>(offset, size), fs::ResultOutOfRange());
R_RETURN(this->DoWrite(offset, buffer, size, option));
}
Result SetSize(s64 size) {
R_UNLESS(size >= 0, fs::ResultOutOfRange());
R_RETURN(this->DoSetSize(size));
}
Result OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) {
R_RETURN(this->DoOperateRange(dst, dst_size, op_id, offset, size, src, src_size));
}
Result OperateRange(fs::OperationId op_id, s64 offset, s64 size) {
R_RETURN(this->DoOperateRange(nullptr, 0, op_id, offset, size, nullptr, 0));
}
public:
/* TODO: This is a hack to allow the mitm API to work. Find a better way? */
virtual sf::cmif::DomainObjectId GetDomainObjectId() const = 0;
protected:
Result DryRead(size_t *out, s64 offset, size_t size, const fs::ReadOption &option, OpenMode open_mode) {
AMS_UNUSED(option);
/* Check that we can read. */
R_UNLESS((open_mode & OpenMode_Read) != 0, fs::ResultReadNotPermitted());
/* Get the file size, and validate our offset. */
s64 file_size = 0;
R_TRY(this->DoGetSize(std::addressof(file_size)));
R_UNLESS(offset <= file_size, fs::ResultOutOfRange());
*out = static_cast<size_t>(std::min(file_size - offset, static_cast<s64>(size)));
R_SUCCEED();
}
Result DrySetSize(s64 size, fs::OpenMode open_mode) {
AMS_UNUSED(size);
/* Check that we can write. */
R_UNLESS((open_mode & OpenMode_Write) != 0, fs::ResultWriteNotPermitted());
R_SUCCEED();
}
Result DryWrite(bool *out_append, s64 offset, size_t size, const fs::WriteOption &option, fs::OpenMode open_mode) {
AMS_UNUSED(option);
/* Check that we can write. */
R_UNLESS((open_mode & OpenMode_Write) != 0, fs::ResultWriteNotPermitted());
/* Get the file size. */
s64 file_size = 0;
R_TRY(this->DoGetSize(&file_size));
/* Determine if we need to append. */
*out_append = false;
if (file_size < offset + static_cast<s64>(size)) {
R_UNLESS((open_mode & OpenMode_AllowAppend) != 0, fs::ResultFileExtensionWithoutOpenModeAllowAppend());
*out_append = true;
}
R_SUCCEED();
}
private:
virtual Result DoRead(size_t *out, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) = 0;
virtual Result DoGetSize(s64 *out) = 0;
virtual Result DoFlush() = 0;
virtual Result DoWrite(s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) = 0;
virtual Result DoSetSize(s64 size) = 0;
virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) = 0;
};
}

View File

@@ -1,187 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_filesystem.hpp>
#include <stratosphere/fs/fs_filesystem_for_debug.hpp>
#include <stratosphere/fs/fs_path.hpp>
namespace ams::fs::fsa {
/* ACCURATE_TO_VERSION: Unknown */
class IFile;
class IDirectory;
enum class QueryId {
SetConcatenationFileAttribute = 0,
UpdateMac = 1,
IsSignedSystemPartitionOnSdCardValid = 2,
QueryUnpreparedFileInformation = 3,
};
class IFileSystem {
public:
virtual ~IFileSystem() { /* ... */ }
Result CreateFile(const fs::Path &path, s64 size, int option) {
R_UNLESS(size >= 0, fs::ResultOutOfRange());
R_RETURN(this->DoCreateFile(path, size, option));
}
Result CreateFile(const fs::Path &path, s64 size) {
R_RETURN(this->CreateFile(path, size, fs::CreateOption_None));
}
Result DeleteFile(const fs::Path &path) {
R_RETURN(this->DoDeleteFile(path));
}
Result CreateDirectory(const fs::Path &path) {
R_RETURN(this->DoCreateDirectory(path));
}
Result DeleteDirectory(const fs::Path &path) {
R_RETURN(this->DoDeleteDirectory(path));
}
Result DeleteDirectoryRecursively(const fs::Path &path) {
R_RETURN(this->DoDeleteDirectoryRecursively(path));
}
Result RenameFile(const fs::Path &old_path, const fs::Path &new_path) {
R_RETURN(this->DoRenameFile(old_path, new_path));
}
Result RenameDirectory(const fs::Path &old_path, const fs::Path &new_path) {
R_RETURN(this->DoRenameDirectory(old_path, new_path));
}
Result GetEntryType(DirectoryEntryType *out, const fs::Path &path) {
R_RETURN(this->DoGetEntryType(out, path));
}
Result OpenFile(std::unique_ptr<IFile> *out_file, const fs::Path &path, OpenMode mode) {
R_UNLESS(out_file != nullptr, fs::ResultNullptrArgument());
R_UNLESS((mode & OpenMode_ReadWrite) != 0, fs::ResultInvalidOpenMode());
R_UNLESS((mode & ~OpenMode_All) == 0, fs::ResultInvalidOpenMode());
R_RETURN(this->DoOpenFile(out_file, path, mode));
}
Result OpenDirectory(std::unique_ptr<IDirectory> *out_dir, const fs::Path &path, OpenDirectoryMode mode) {
R_UNLESS(out_dir != nullptr, fs::ResultNullptrArgument());
R_UNLESS((mode & OpenDirectoryMode_All) != 0, fs::ResultInvalidOpenMode());
R_UNLESS((mode & ~(OpenDirectoryMode_All | OpenDirectoryMode_NotRequireFileSize)) == 0, fs::ResultInvalidOpenMode());
R_RETURN(this->DoOpenDirectory(out_dir, path, mode));
}
Result Commit() {
R_RETURN(this->DoCommit());
}
Result GetFreeSpaceSize(s64 *out, const fs::Path &path) {
R_UNLESS(out != nullptr, fs::ResultNullptrArgument());
R_RETURN(this->DoGetFreeSpaceSize(out, path));
}
Result GetTotalSpaceSize(s64 *out, const fs::Path &path) {
R_UNLESS(out != nullptr, fs::ResultNullptrArgument());
R_RETURN(this->DoGetTotalSpaceSize(out, path));
}
Result CleanDirectoryRecursively(const fs::Path &path) {
R_RETURN(this->DoCleanDirectoryRecursively(path));
}
Result GetFileTimeStampRaw(FileTimeStampRaw *out, const fs::Path &path) {
R_UNLESS(out != nullptr, fs::ResultNullptrArgument());
R_RETURN(this->DoGetFileTimeStampRaw(out, path));
}
Result QueryEntry(char *dst, size_t dst_size, const char *src, size_t src_size, QueryId query, const fs::Path &path) {
R_RETURN(this->DoQueryEntry(dst, dst_size, src, src_size, query, path));
}
/* These aren't accessible as commands. */
Result CommitProvisionally(s64 counter) {
R_RETURN(this->DoCommitProvisionally(counter));
}
Result Rollback() {
R_RETURN(this->DoRollback());
}
Result Flush() {
R_RETURN(this->DoFlush());
}
protected:
/* ...? */
private:
virtual Result DoCreateFile(const fs::Path &path, s64 size, int flags) = 0;
virtual Result DoDeleteFile(const fs::Path &path) = 0;
virtual Result DoCreateDirectory(const fs::Path &path) = 0;
virtual Result DoDeleteDirectory(const fs::Path &path) = 0;
virtual Result DoDeleteDirectoryRecursively(const fs::Path &path) = 0;
virtual Result DoRenameFile(const fs::Path &old_path, const fs::Path &new_path) = 0;
virtual Result DoRenameDirectory(const fs::Path &old_path, const fs::Path &new_path) = 0;
virtual Result DoGetEntryType(fs::DirectoryEntryType *out, const fs::Path &path) = 0;
virtual Result DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const fs::Path &path, fs::OpenMode mode) = 0;
virtual Result DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const fs::Path &path, fs::OpenDirectoryMode mode) = 0;
virtual Result DoCommit() = 0;
virtual Result DoGetFreeSpaceSize(s64 *out, const fs::Path &path) {
AMS_UNUSED(out, path);
R_THROW(fs::ResultNotImplemented());
}
virtual Result DoGetTotalSpaceSize(s64 *out, const fs::Path &path) {
AMS_UNUSED(out, path);
R_THROW(fs::ResultNotImplemented());
}
virtual Result DoCleanDirectoryRecursively(const fs::Path &path) = 0;
virtual Result DoGetFileTimeStampRaw(fs::FileTimeStampRaw *out, const fs::Path &path) {
AMS_UNUSED(out, path);
R_THROW(fs::ResultNotImplemented());
}
virtual Result DoQueryEntry(char *dst, size_t dst_size, const char *src, size_t src_size, fs::fsa::QueryId query, const fs::Path &path) {
AMS_UNUSED(dst, dst_size, src, src_size, query, path);
R_THROW(fs::ResultNotImplemented());
}
/* These aren't accessible as commands. */
virtual Result DoCommitProvisionally(s64 counter) {
AMS_UNUSED(counter);
R_THROW(fs::ResultNotImplemented());
}
virtual Result DoRollback() {
R_THROW(fs::ResultNotImplemented());
}
virtual Result DoFlush() {
R_THROW(fs::ResultNotImplemented());
}
};
template<typename T>
concept PointerToFileSystem = ::ams::util::RawOrSmartPointerTo<T, ::ams::fs::fsa::IFileSystem>;
}

View File

@@ -1,36 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs::fsa {
/* ACCURATE_TO_VERSION: Unknown */
class ICommonMountNameGenerator {
public:
virtual ~ICommonMountNameGenerator() { /* ... */ }
virtual Result GenerateCommonMountName(char *name, size_t name_size) = 0;
};
class IFileSystem;
Result Register(const char *name, std::unique_ptr<IFileSystem> &&fs);
Result Register(const char *name, std::unique_ptr<IFileSystem> &&fs, std::unique_ptr<ICommonMountNameGenerator> &&generator);
Result Register(const char *name, std::unique_ptr<IFileSystem> &&fs, std::unique_ptr<ICommonMountNameGenerator> &&generator, bool use_data_cache, bool use_path_cache, bool multi_commit_supported);
void Unregister(const char *name);
}

View File

@@ -1,341 +0,0 @@
/*
* Copyright (c) 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>
#include <stratosphere/fs/fs_access_log.hpp>
#include <stratosphere/fs/fs_directory.hpp>
#include <stratosphere/fs/fs_file.hpp>
#include <stratosphere/fs/fs_priority.hpp>
#include <stratosphere/os/os_tick.hpp>
namespace ams::fs::impl {
/* ACCURATE_TO_VERSION: Unknown */
enum AccessLogTarget : u32 {
AccessLogTarget_None = (0 << 0),
AccessLogTarget_Application = (1 << 0),
AccessLogTarget_System = (1 << 1),
};
struct IdentifyAccessLogHandle {
void *handle;
public:
static constexpr IdentifyAccessLogHandle MakeHandle(void *h) {
return IdentifyAccessLogHandle{h};
}
};
bool IsEnabledAccessLog(u32 target);
bool IsEnabledAccessLog();
bool IsEnabledHandleAccessLog(fs::FileHandle handle);
bool IsEnabledHandleAccessLog(fs::DirectoryHandle handle);
bool IsEnabledHandleAccessLog(fs::impl::IdentifyAccessLogHandle handle);
bool IsEnabledHandleAccessLog(const void *handle);
bool IsEnabledFileSystemAccessorAccessLog(const char *mount_name);
void EnableFileSystemAccessorAccessLog(const char *mount_name);
using AccessLogPrinterCallback = int (*)(char *buffer, size_t buffer_size);
void RegisterStartAccessLogPrinterCallback(AccessLogPrinterCallback callback);
void OutputAccessLog(Result result, os::Tick start, os::Tick end, const char *name, fs::FileHandle handle, const char *fmt, ...) __attribute__((format (printf, 6, 7)));
void OutputAccessLog(Result result, os::Tick start, os::Tick end, const char *name, fs::DirectoryHandle handle, const char *fmt, ...) __attribute__((format (printf, 6, 7)));
void OutputAccessLog(Result result, os::Tick start, os::Tick end, const char *name, fs::impl::IdentifyAccessLogHandle handle, const char *fmt, ...) __attribute__((format (printf, 6, 7)));
void OutputAccessLog(Result result, os::Tick start, os::Tick end, const char *name, const void *handle, const char *fmt, ...) __attribute__((format (printf, 6, 7)));
void OutputAccessLog(Result result, fs::Priority priority, os::Tick start, os::Tick end, const char *name, const void *handle, const char *fmt, ...) __attribute__((format (printf, 7, 8)));
void OutputAccessLog(Result result, fs::PriorityRaw priority_raw, os::Tick start, os::Tick end, const char *name, const void *handle, const char *fmt, ...) __attribute__((format (printf, 7, 8)));
void OutputAccessLogToOnlySdCard(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
void OutputAccessLogUnlessResultSuccess(Result result, os::Tick start, os::Tick end, const char *name, fs::FileHandle handle, const char *fmt, ...) __attribute__((format (printf, 6, 7)));
void OutputAccessLogUnlessResultSuccess(Result result, os::Tick start, os::Tick end, const char *name, fs::DirectoryHandle handle, const char *fmt, ...) __attribute__((format (printf, 6, 7)));
void OutputAccessLogUnlessResultSuccess(Result result, os::Tick start, os::Tick end, const char *name, const void *handle, const char *fmt, ...) __attribute__((format (printf, 6, 7)));
class IdString {
private:
char m_buffer[0x20];
private:
const char *ToValueString(int id);
public:
template<typename T>
const char *ToString(T id);
};
template<typename T> requires (requires { T{}; })
inline T DereferenceOutValue(T *out_value, Result result) {
if (R_SUCCEEDED(result) && out_value != nullptr) {
return *out_value;
} else {
return T{};
}
}
static_assert(sizeof(size_t) == sizeof(u64));
}
/* Access log result name. */
#define AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME __tmp_ams_fs_access_log_result
/* Access log utils. */
#define AMS_FS_IMPL_ACCESS_LOG_DEREFERENCE_OUT_VALUE(__VALUE__) ::ams::fs::impl::DereferenceOutValue(__VALUE__, AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME)
/* Access log components. */
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_SIZE ", size: %" PRId64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_READ_SIZE ", read_size: %" PRIuZ ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_QUERY_SIZE ", read_size: %" PRIuZ ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_OFFSET_AND_SIZE ", offset: %" PRId64 ", size: %" PRIuZ ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_THREAD_ID ", thread_id: %" PRIu64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT ", name: \"%s\""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_ENTRY_COUNT ", entry_count: %" PRId64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_ENTRY_BUFFER_COUNT ", entry_buffer_count: %" PRId64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_OPEN_MODE ", open_mode: 0x%" PRIX32 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH ", path: \"%s\""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH_AND_SIZE ", path: \"%s\", size: %" PRId64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH_AND_OPEN_MODE ", path: \"%s\", open_mode: 0x%" PRIX32 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_RENAME ", path: \"%s\", new_path: \"%s\""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_DIRECTORY_ENTRY_TYPE ", entry_type: %s"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_CONTENT_TYPE ", content_type: %s"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_HOST_OPTION ", mount_host_option: %s"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_ROOT_PATH ", root_path: %s"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_APPLICATION_ID ", applicationid: 0x%" PRIx64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_BIS_PARTITION_ID ", bispartitionid: %s"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_CONTENT_STORAGE_ID ", contentstorageid: %s"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_SYSTEM_DATA_ID ", systemdataid: 0x%" PRIx64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_DATA_ID ", dataid: 0x%" PRIx64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_GAME_CARD_HANDLE ", gamecard_handle: 0x%" PRIX32 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_GAME_CARD_PARTITION ", gamecard_partition: %s"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_IMAGE_DIRECTORY_ID ", imagedirectoryid: %s"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_PROGRAM_ID ", programid: 0x%" PRIx64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_ID ", savedataid: 0x%" PRIx64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_SPACE_ID ", savedataspaceid: %s"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_OWNER_ID ", save_data_owner_id: 0x%" PRIx64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_USER_ID ", userid: 0x%016" PRIx64 "%016" PRIx64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_FLAGS ", save_data_flags: 0x%08" PRIX32 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_JOURNAL_SIZE ", save_data_journal_size: %" PRId64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_SIZE ", save_data_size: %" PRId64 ""
/* Access log formats. */
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_NONE ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_READ_FILE(__OUT_READ_SIZE__, __OFFSET__, __SIZE__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_OFFSET_AND_SIZE AMS_FS_IMPL_ACCESS_LOG_FORMAT_READ_SIZE, __OFFSET__, __SIZE__, AMS_FS_IMPL_ACCESS_LOG_DEREFERENCE_OUT_VALUE(__OUT_READ_SIZE__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_WRITE_FILE_WITH_NO_OPTION AMS_FS_IMPL_ACCESS_LOG_FORMAT_OFFSET_AND_SIZE
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_WRITE_FILE_WITH_FLUSH_OPTION AMS_FS_IMPL_ACCESS_LOG_FORMAT_WRITE_FILE_WITH_NO_OPTION ", write_option: Flush"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_WRITE_FILE(__OPTION__) ((__OPTION__).HasFlushFlag() ? AMS_FS_IMPL_ACCESS_LOG_FORMAT_WRITE_FILE_WITH_FLUSH_OPTION : AMS_FS_IMPL_ACCESS_LOG_FORMAT_WRITE_FILE_WITH_NO_OPTION)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_GET_FILE_SIZE(__OUT_SIZE__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_SIZE, AMS_FS_IMPL_ACCESS_LOG_DEREFERENCE_OUT_VALUE(__OUT_SIZE__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_READ_DIRECTORY(__OUT_ENTRY_COUNT__, __ENTRY_BUFFER_COUNT__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_ENTRY_BUFFER_COUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_ENTRY_COUNT, __ENTRY_BUFFER_COUNT__, AMS_FS_IMPL_ACCESS_LOG_DEREFERENCE_OUT_VALUE(__OUT_ENTRY_COUNT__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_GET_DIRECTORY_ENTRY_COUNT(__OUT_ENTRY_COUNT__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_ENTRY_COUNT, AMS_FS_IMPL_ACCESS_LOG_DEREFERENCE_OUT_VALUE(__OUT_ENTRY_COUNT__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_GET_ENTRY_TYPE(__OUT_ENTRY_TYPE__, __PATH__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH AMS_FS_IMPL_ACCESS_LOG_FORMAT_DIRECTORY_ENTRY_TYPE, __PATH__, ::ams::fs::impl::IdString().ToString(AMS_FS_IMPL_ACCESS_LOG_DEREFERENCE_OUT_VALUE(__OUT_ENTRY_TYPE__))
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_GET_SPACE_SIZE(__OUT_SIZE__, __NAME__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_SIZE, __NAME__, AMS_FS_IMPL_ACCESS_LOG_DEREFERENCE_OUT_VALUE(__OUT_SIZE__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_APPLICATION_PACKAGE(__NAME__, __PATH__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH, (__NAME__), (__PATH__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_BIS(__NAME__, __ID__, __PATH__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_BIS_PARTITION_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH, (__NAME__), ::ams::fs::impl::IdString().ToString(__ID__), (__PATH__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_CODE(__NAME__, __PATH__, __ID__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH AMS_FS_IMPL_ACCESS_LOG_FORMAT_PROGRAM_ID, (__NAME__), (__PATH__), (__ID__).value
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_CONTENT_PATH(__NAME__, __PATH__, __TYPE__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH AMS_FS_IMPL_ACCESS_LOG_FORMAT_CONTENT_TYPE, (__NAME__), (__PATH__), ::ams::fs::impl::IdString().ToString(__TYPE__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_CONTENT_PROGRAM_ID(__NAME__, __ID__, __TYPE__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_PROGRAM_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_CONTENT_TYPE, (__NAME__), (__ID__), ::ams::fs::impl::IdString().ToString(__TYPE__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_CONTENT_PATH_AND_PROGRAM_ID(__NAME__, __PATH__, __ID__, __TYPE__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH AMS_FS_IMPL_ACCESS_LOG_FORMAT_PROGRAM_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_CONTENT_TYPE, (__NAME__), (__PATH__), (__ID__).value, ::ams::fs::impl::IdString().ToString(__TYPE__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_CONTENT_PATH_AND_DATA_ID(__NAME__, __PATH__, __ID__, __TYPE__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH AMS_FS_IMPL_ACCESS_LOG_FORMAT_DATA_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_CONTENT_TYPE, (__NAME__), (__PATH__), (__ID__).value, ::ams::fs::impl::IdString().ToString(__TYPE__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_CONTENT_STORAGE(__NAME__, __ID__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_CONTENT_STORAGE_ID, (__NAME__), ::ams::fs::impl::IdString().ToString(__ID__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_DEVICE_SAVE_DATA_APPLICATION_ID(__NAME__, __ID__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_APPLICATION_ID, (__NAME__), (__ID__).value
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_GAME_CARD_PARTITION(__NAME__, __GCHANDLE__, __PARTITION__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_GAME_CARD_HANDLE AMS_FS_IMPL_ACCESS_LOG_FORMAT_GAME_CARD_PARTITION, (__NAME__), __GCHANDLE__, ::ams::fs::impl::IdString().ToString(__PARTITION__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_HOST_ROOT() \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT, (AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_HOST_ROOT_WITH_OPTION(__OPTION__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_HOST_OPTION, (AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME), ::ams::fs::impl::IdString().ToString(__OPTION__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_HOST(__NAME__, __ROOT_PATH__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_ROOT_PATH, (__NAME__), (__ROOT_PATH__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_HOST_WITH_OPTION(__NAME__, __ROOT_PATH__, __OPTION__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_ROOT_PATH AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_HOST_OPTION, (__NAME__), (__ROOT_PATH__), ::ams::fs::impl::IdString().ToString(__OPTION__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_IMAGE_DIRECTORY(__NAME__, __ID__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_IMAGE_DIRECTORY_ID, (__NAME__), ::ams::fs::impl::IdString().ToString(__ID__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_SYSTEM_DATA(__NAME__, __ID__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_SYSTEM_DATA_ID, (__NAME__), (__ID__).value
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_SYSTEM_SAVE_DATA(__NAME__, __SPACE__, __SAVE__, __USER__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_SPACE_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_USER_ID, \
(__NAME__), ::ams::fs::impl::IdString().ToString(__SPACE__), (__SAVE__), (__USER__).data[0], (__USER__).data[1]
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_CREATE_SYSTEM_SAVE_DATA(__SPACE__, __SAVE__, __USER__, __OWNER__, __SIZE__, __JOURNAL_SIZE__, __FLAGS__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_SPACE_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_USER_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_OWNER_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_SIZE AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_JOURNAL_SIZE AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_FLAGS, \
::ams::fs::impl::IdString().ToString(__SPACE__), (__SAVE__), (__USER__).data[0], (__USER__).data[1], (__OWNER__), (__SIZE__), (__JOURNAL_SIZE__), (__FLAGS__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_DELETE_SAVE_DATA(__SPACE__, __SAVE__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_SPACE_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_ID, \
::ams::fs::impl::IdString().ToString(__SPACE__), (__SAVE__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_DELETE_SYSTEM_SAVE_DATA(__SPACE__, __SAVE__, __USER__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_SPACE_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_USER_ID, \
::ams::fs::impl::IdString().ToString(__SPACE__), (__SAVE__), (__USER__).data[0], (__USER__).data[1]
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_EXTEND_SAVE_DATA(__SPACE__, __SAVE__, __SIZE__, __JOURNAL_SIZE__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_SPACE_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_SIZE AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_JOURNAL_SIZE, \
::ams::fs::impl::IdString().ToString(__SPACE__), (__SAVE__), (__SIZE__), (__JOURNAL_SIZE__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_QUERY_MOUNT_SYSTEM_DATA_CACHE_SIZE(__ID__, __SIZE__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_SYSTEM_DATA_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_QUERY_SIZE, (__ID__).value, AMS_FS_IMPL_ACCESS_LOG_DEREFERENCE_OUT_VALUE(__SIZE__)
/* Access log invocation lambdas. */
#define AMS_FS_IMPL_ACCESS_LOG_IMPL(__EXPR__, __HANDLE__, __ENABLED__, __NAME__, ...) \
[&](const char *__fs_func_name_) -> Result { \
if (!(__ENABLED__)) { \
R_RETURN(__EXPR__); \
} else { \
const ::ams::os::Tick __fs_start_tick = ::ams::os::GetSystemTick(); \
const auto AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME = (__EXPR__); \
const ::ams::os::Tick __fs_end_tick = ::ams::os::GetSystemTick(); \
::ams::fs::impl::OutputAccessLog(AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME, __fs_start_tick, __fs_end_tick, __fs_func_name_, __HANDLE__, __VA_ARGS__); \
R_RETURN( AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME ); \
} \
}(__NAME__)
#define AMS_FS_IMPL_ACCESS_LOG_WITH_PRIORITY_IMPL(__EXPR__, __PRIORITY__, __HANDLE__, __ENABLED__, __NAME__, ...) \
[&](const char *__fs_func_name_) -> Result { \
if (!(__ENABLED__)) { \
R_RETURN(__EXPR__); \
} else { \
const ::ams::os::Tick __fs_start_tick = ::ams::os::GetSystemTick(); \
const auto AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME = (__EXPR__); \
const ::ams::os::Tick __fs_end_tick = ::ams::os::GetSystemTick(); \
::ams::fs::impl::OutputAccessLog(AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME, __PRIORITY__, __fs_start_tick, __fs_end_tick, __fs_func_name_, __HANDLE__, __VA_ARGS__); \
R_RETURN( AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME ); \
} \
}(__NAME__)
#define AMS_FS_IMPL_ACCESS_LOG_EXPLICIT_IMPL(__RESULT__, __START__, __END__, __HANDLE__, __ENABLED__, __NAME__, ...) \
[&](const char *__fs_func_name_) -> Result { \
if (!(__ENABLED__)) { \
R_RETURN(__RESULT__); \
} else { \
const auto AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME = (__RESULT__); \
::ams::fs::impl::OutputAccessLog(AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME, __START__, __END__, __fs_func_name_, __HANDLE__, __VA_ARGS__); \
R_RETURN( AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME ); \
} \
}(__NAME__)
#define AMS_FS_IMPL_ACCESS_LOG_UNLESS_R_SUCCEEDED_IMPL(__EXPR__, __ENABLED__, __NAME__, ...) \
[&](const char *__fs_func_name_) -> Result { \
if (!(__ENABLED__)) { \
R_RETURN(__EXPR__); \
} else { \
const ::ams::os::Tick __fs_start_tick = ::ams::os::GetSystemTick(); \
const auto AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME = (__EXPR__); \
const ::ams::os::Tick __fs_end_tick = ::ams::os::GetSystemTick(); \
::ams::fs::impl::OutputAccessLogUnlessResultSuccess(AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME, __fs_start_tick, __fs_end_tick, __fs_func_name_, nullptr, __VA_ARGS__); \
R_RETURN( AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME ); \
} \
}(__NAME__)
/* Access log api. */
#define AMS_FS_IMPL_ACCESS_LOG(__EXPR__, __HANDLE__, ...) \
AMS_FS_IMPL_ACCESS_LOG_IMPL((__EXPR__), __HANDLE__, ::ams::fs::impl::IsEnabledAccessLog() && ::ams::fs::impl::IsEnabledHandleAccessLog(__HANDLE__), AMS_CURRENT_FUNCTION_NAME, __VA_ARGS__)
#define AMS_FS_IMPL_ACCESS_LOG_SYSTEM(__EXPR__, __HANDLE__, ...) \
AMS_FS_IMPL_ACCESS_LOG_IMPL((__EXPR__), __HANDLE__, ::ams::fs::impl::IsEnabledAccessLog(::ams::fs::impl::AccessLogTarget_System) && ::ams::fs::impl::IsEnabledHandleAccessLog(__HANDLE__), AMS_CURRENT_FUNCTION_NAME, __VA_ARGS__)
#define AMS_FS_IMPL_ACCESS_LOG_WITH_NAME(__EXPR__, __HANDLE__, __NAME__, ...) \
AMS_FS_IMPL_ACCESS_LOG_IMPL((__EXPR__), __HANDLE__, ::ams::fs::impl::IsEnabledAccessLog() && ::ams::fs::impl::IsEnabledHandleAccessLog(__HANDLE__), __NAME__, __VA_ARGS__)
#define AMS_FS_IMPL_ACCESS_LOG_EXPLICIT(__RESULT__, __START__, __END__, __HANDLE__, __NAME__, ...) \
AMS_FS_IMPL_ACCESS_LOG_EXPLICIT_IMPL((__RESULT__), __START__, __END__, __HANDLE__, ::ams::fs::impl::IsEnabledAccessLog() && ::ams::fs::impl::IsEnabledHandleAccessLog(__HANDLE__), __NAME__, __VA_ARGS__)
#define AMS_FS_IMPL_ACCESS_LOG_UNLESS_R_SUCCEEDED(__EXPR__, ...) \
AMS_FS_IMPL_ACCESS_LOG_UNLESS_R_SUCCEEDED_IMPL((__EXPR__), ::ams::fs::impl::IsEnabledAccessLog(), AMS_CURRENT_FUNCTION_NAME, __VA_ARGS__)
/* FS Accessor logging. */
#define AMS_FS_IMPL_ACCESS_LOG_FS_ACCESSOR_ENABLE_IMPL(__NAME__, __ENABLED__) \
do { \
if (static_cast<bool>(__ENABLED__)) { \
::ams::fs::impl::EnableFileSystemAccessorAccessLog((__NAME__)); \
} \
} while (false)
#define AMS_FS_IMPL_ACCESS_LOG_FS_ACCESSOR_ENABLE(__NAME__) \
AMS_FS_IMPL_ACCESS_LOG_FS_ACCESSOR_ENABLE_IMPL((__NAME__), ::ams::fs::impl::IsEnabledAccessLog(::ams::fs::impl::AccessLogTarget_Application))
// DEBUG
#define AMS_FS_FORCE_ENABLE_SYSTEM_MOUNT_ACCESS_LOG
/* System access log api. */
#if defined(AMS_BUILD_FOR_DEBUGGING) || defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_FS_FORCE_ENABLE_SYSTEM_MOUNT_ACCESS_LOG)
#define AMS_FS_IMPL_ACCESS_LOG_SYSTEM_MOUNT(__EXPR__, __NAME__, ...) \
AMS_FS_IMPL_ACCESS_LOG_IMPL((__EXPR__), nullptr, ::ams::fs::impl::IsEnabledAccessLog(::ams::fs::impl::AccessLogTarget_System), AMS_CURRENT_FUNCTION_NAME, __VA_ARGS__)
#define AMS_FS_IMPL_ACCESS_LOG_SYSTEM_FS_ACCESSOR_ENABLE(__NAME__) \
AMS_FS_IMPL_ACCESS_LOG_FS_ACCESSOR_ENABLE_IMPL((__NAME__), ::ams::fs::impl::IsEnabledAccessLog(::ams::fs::impl::AccessLogTarget_System))
#else
#define AMS_FS_IMPL_ACCESS_LOG_SYSTEM_MOUNT(__EXPR__, __NAME__, ...) (__EXPR__)
#define AMS_FS_IMPL_ACCESS_LOG_SYSTEM_FS_ACCESSOR_ENABLE(__NAME__) static_cast<void>(0)
#endif
/* Specific utilities. */
#define AMS_FS_IMPL_ACCESS_LOG_FILESYSTEM(__EXPR__, __HANDLE__, __FILESYSTEM__, ...) \
AMS_FS_IMPL_ACCESS_LOG_IMPL((__EXPR__), __HANDLE__, ::ams::fs::impl::IsEnabledAccessLog() && (__FILESYSTEM__)->IsEnabledAccessLog(), AMS_CURRENT_FUNCTION_NAME, __VA_ARGS__)
#define AMS_FS_IMPL_ACCESS_LOG_FILESYSTEM_WITH_NAME(__EXPR__, __HANDLE__, __FILESYSTEM__, __NAME__, ...) \
AMS_FS_IMPL_ACCESS_LOG_IMPL((__EXPR__), __HANDLE__, ::ams::fs::impl::IsEnabledAccessLog() && (__FILESYSTEM__)->IsEnabledAccessLog(), __NAME__, __VA_ARGS__)
#define AMS_FS_IMPL_ACCESS_LOG_MOUNT(__EXPR__, __NAME__, ...) \
AMS_FS_IMPL_ACCESS_LOG_IMPL((__EXPR__), nullptr, ::ams::fs::impl::IsEnabledAccessLog(::ams::fs::impl::AccessLogTarget_Application), AMS_CURRENT_FUNCTION_NAME, __VA_ARGS__)
#define AMS_FS_IMPL_ACCESS_LOG_MOUNT_UNLESS_R_SUCCEEDED(__EXPR__, __NAME__, ...) \
AMS_FS_IMPL_ACCESS_LOG_UNLESS_R_SUCCEEDED_IMPL((__EXPR__), ::ams::fs::impl::IsEnabledAccessLog(::ams::fs::impl::AccessLogTarget_Application), AMS_CURRENT_FUNCTION_NAME, __VA_ARGS__)
#define AMS_FS_IMPL_ACCESS_LOG_UNMOUNT(__EXPR__, __MOUNT_NAME__, ...) \
AMS_FS_IMPL_ACCESS_LOG_IMPL((__EXPR__), nullptr, ::ams::fs::impl::IsEnabledAccessLog() && ::ams::fs::impl::IsEnabledFileSystemAccessorAccessLog(__MOUNT_NAME__), AMS_CURRENT_FUNCTION_NAME, __VA_ARGS__)

View File

@@ -1,59 +0,0 @@
/*
* Copyright (c) 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
namespace ams::fs::impl {
/* ACCURATE_TO_VERSION: Unknown */
/* Delimiting of mount names. */
constexpr inline const char ReservedMountNamePrefixCharacter = '@';
#define AMS_FS_IMPL_MOUNT_NAME_DELIMITER ":/"
#define AMS_FS_IMPL_MOUNT_NAME_DELIMITER_LEN 2
constexpr inline const char * const MountNameDelimiter = AMS_FS_IMPL_MOUNT_NAME_DELIMITER;
/* Filesystem names. */
#define AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME "@Host"
#define AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME_LEN 5
constexpr inline const char * const HostRootFileSystemMountName = AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME;
constexpr inline const char * const SdCardFileSystemMountName = "@Sdcard";
constexpr inline const char * const GameCardFileSystemMountName = "@Gc";
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 * 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 * const RegisteredUpdatePartitionMountName = "@RegUpdate";
}

View File

@@ -1,28 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
namespace ams::fs::impl {
/* ACCURATE_TO_VERSION: Unknown */
Result QueryMountDataCacheSize(size_t *out, ncm::DataId data_id, ncm::StorageId storage_id);
Result MountData(const char *name, ncm::DataId data_id, ncm::StorageId storage_id);
Result MountData(const char *name, ncm::DataId data_id, ncm::StorageId storage_id, void *cache_buffer, size_t cache_size);
Result MountData(const char *name, ncm::DataId data_id, ncm::StorageId storage_id, void *cache_buffer, size_t cache_size, bool use_data_cache, bool use_path_cache);
}

View File

@@ -1,34 +0,0 @@
/*
* Copyright (c) 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::fs::impl {
/* ACCURATE_TO_VERSION: Unknown */
enum FileSystemProxyType {
FileSystemProxyType_Code = 0,
FileSystemProxyType_Rom = 1,
FileSystemProxyType_Logo = 2,
FileSystemProxyType_Control = 3,
FileSystemProxyType_Manual = 4,
FileSystemProxyType_Meta = 5,
FileSystemProxyType_Data = 6,
FileSystemProxyType_Package = 7,
FileSystemProxyType_UpdatePartition = 8,
};
}

View File

@@ -1,47 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/sf/sf_fs_inline_context.hpp>
namespace ams::fs::impl {
/* ACCURATE_TO_VERSION: Unknown */
constexpr inline u8 TlsIoPriorityMask = 0x7;
constexpr inline u8 TlsIoRecursiveCallMask = 0x8;
struct TlsIoValueForInheritance {
u8 _tls_value;
};
inline void SetCurrentRequestRecursive() {
os::ThreadType * const cur_thread = os::GetCurrentThread();
sf::SetFsInlineContext(cur_thread, TlsIoRecursiveCallMask | sf::GetFsInlineContext(cur_thread));
}
inline bool IsCurrentRequestRecursive() {
return (sf::GetFsInlineContext(os::GetCurrentThread()) & TlsIoRecursiveCallMask) != 0;
}
inline TlsIoValueForInheritance GetTlsIoValueForInheritance() {
return TlsIoValueForInheritance { sf::GetFsInlineContext(os::GetCurrentThread()) };
}
inline void SetTlsIoValueForInheritance(TlsIoValueForInheritance tls_io) {
sf::SetFsInlineContext(os::GetCurrentThread(), tls_io._tls_value);
}
}

View File

@@ -1,25 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fssystem/fssystem_i_hash_256_generator.hpp>
namespace ams::fs::impl {
/* ACCURATE_TO_VERSION: Unknown */
fssystem::IHash256GeneratorFactorySelector *GetNcaHashGeneratorFactorySelector();
fssystem::IHash256GeneratorFactorySelector *GetSaveDataHashGeneratorFactorySelector();
}

View File

@@ -1,46 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_memory_management.hpp>
namespace ams::fs::impl {
/* ACCURATE_TO_VERSION: Unknown */
class Newable {
public:
static ALWAYS_INLINE void *operator new(size_t size) noexcept {
return ::ams::fs::impl::Allocate(size);
}
static ALWAYS_INLINE void *operator new(size_t size, Newable *placement) noexcept {
AMS_UNUSED(size);
return placement;
}
static ALWAYS_INLINE void *operator new[](size_t size) noexcept {
return ::ams::fs::impl::Allocate(size);
}
static ALWAYS_INLINE void operator delete(void *ptr, size_t size) noexcept {
return ::ams::fs::impl::Deallocate(ptr, size);
}
static ALWAYS_INLINE void operator delete[](void *ptr, size_t size) noexcept {
return ::ams::fs::impl::Deallocate(ptr, size);
}
};
}

View File

@@ -1,71 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_priority.hpp>
#include <stratosphere/fs/impl/fs_fs_inline_context_utils.hpp>
namespace ams::fs::impl {
/* ACCURATE_TO_VERSION: Unknown */
enum TlsIoPriority : u8 {
TlsIoPriority_Normal = 0,
TlsIoPriority_Realtime = 1,
TlsIoPriority_Low = 2,
TlsIoPriority_Background = 3,
};
#if defined(ATMOSPHERE_OS_HORIZON)
/* Ensure that TlsIo priority matches libnx priority. */
static_assert(TlsIoPriority_Normal == static_cast<TlsIoPriority>(::FsPriority_Normal));
static_assert(TlsIoPriority_Realtime == static_cast<TlsIoPriority>(::FsPriority_Realtime));
static_assert(TlsIoPriority_Low == static_cast<TlsIoPriority>(::FsPriority_Low));
static_assert(TlsIoPriority_Background == static_cast<TlsIoPriority>(::FsPriority_Background));
#endif
constexpr inline Result ConvertFsPriorityToTlsIoPriority(u8 *out, PriorityRaw priority) {
AMS_ASSERT(out != nullptr);
switch (priority) {
case PriorityRaw_Normal: *out = TlsIoPriority_Normal; break;
case PriorityRaw_Realtime: *out = TlsIoPriority_Realtime; break;
case PriorityRaw_Low: *out = TlsIoPriority_Low; break;
case PriorityRaw_Background: *out = TlsIoPriority_Background; break;
default: R_THROW(fs::ResultInvalidArgument());
}
R_SUCCEED();
}
constexpr inline Result ConvertTlsIoPriorityToFsPriority(PriorityRaw *out, u8 tls_io) {
AMS_ASSERT(out != nullptr);
switch (static_cast<TlsIoPriority>(tls_io)) {
case TlsIoPriority_Normal: *out = PriorityRaw_Normal; break;
case TlsIoPriority_Realtime: *out = PriorityRaw_Realtime; break;
case TlsIoPriority_Low: *out = PriorityRaw_Low; break;
case TlsIoPriority_Background: *out = PriorityRaw_Background; break;
default: R_THROW(fs::ResultInvalidArgument());
}
R_SUCCEED();
}
inline u8 GetTlsIoPriority(os::ThreadType *thread) {
return sf::GetFsInlineContext(thread) & TlsIoPriorityMask;
}
}

View File

@@ -1,85 +0,0 @@
/*
* Copyright (c) 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::fs::impl {
/* ACCURATE_TO_VERSION: Unknown */
bool IsAbortNeeded(Result result);
void LogErrorMessage(Result result, const char *function);
}
#define AMS_FS_R_CHECK_ABORT_IMPL(__RESULT__, __FORCE__) \
({ \
if (::ams::fs::impl::IsAbortNeeded(__RESULT__) || (__FORCE__)) { \
::ams::fs::impl::LogErrorMessage(__RESULT__, AMS_CURRENT_FUNCTION_NAME); \
R_ABORT_UNLESS(__RESULT__); \
} \
})
#define AMS_FS_R_TRY(__RESULT__) \
({ \
const ::ams::Result __tmp_fs_result = (__RESULT__); \
AMS_FS_R_CHECK_ABORT_IMPL(__tmp_fs_result, false); \
R_TRY(__tmp_fs_result); \
})
#define AMS_FS_R_ABORT_UNLESS(__RESULT__) \
({ \
const ::ams::Result __tmp_fs_result = (__RESULT__); \
AMS_FS_R_CHECK_ABORT_IMPL(__tmp_fs_result, true); \
})
#define AMS_FS_ABORT_UNLESS_WITH_RESULT(__EXPR__, __RESULT__) \
({ \
if (!(__EXPR__)) { \
AMS_FS_R_ABORT_UNLESS((__RESULT__)); \
} \
})
#define AMS_FS_R_THROW(__RESULT__) \
({ \
const ::ams::Result __tmp_fs_result = (__RESULT__); \
AMS_FS_R_CHECK_ABORT_IMPL(__tmp_fs_result, false); \
R_THROW(__tmp_fs_result); \
})
#define AMS_FS_R_UNLESS(__EXPR__, __RESULT__) \
({ \
if (!(__EXPR__)) { \
AMS_FS_R_THROW((__RESULT__)); \
} \
})
#define AMS_FS_R_TRY_CATCH(__EXPR__) R_TRY_CATCH(__EXPR__)
#define AMS_FS_R_CATCH(...) R_CATCH(__VA_ARGS__)
#define AMS_FS_R_END_TRY_CATCH \
else if (R_FAILED(R_CURRENT_RESULT)) { \
AMS_FS_R_THROW(R_CURRENT_RESULT); \
} \
} \
})
#define AMS_FS_R_END_TRY_CATCH_WITH_ABORT_UNLESS \
else { \
AMS_FS_R_ABORT_UNLESS(R_CURRENT_RESULT); \
} \
} \
})

View File

@@ -1,26 +0,0 @@
/*
* Copyright (c) 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>
#include <stratosphere/sm/sm_types.hpp>
namespace ams::fs::impl {
constexpr inline const sm::ServiceName FileSystemProxyServiceName = sm::ServiceName::Encode("fsp-srv");
constexpr inline const sm::ServiceName ProgramRegistryServiceName = sm::ServiceName::Encode("fsp-pr");
constexpr inline const sm::ServiceName FileSystemProxyForLoaderServiceName = sm::ServiceName::Encode("fsp-ldr");
}

View File

@@ -1,76 +0,0 @@
/*
* Copyright (c) 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 <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_istorage.hpp>
#include <stratosphere/fs/impl/fs_newable.hpp>
namespace ams::fs::impl {
template<typename StorageInterface>
class StorageServiceObjectAdapter : public ::ams::fs::impl::Newable, public ::ams::fs::IStorage {
NON_COPYABLE(StorageServiceObjectAdapter);
NON_MOVEABLE(StorageServiceObjectAdapter);
private:
sf::SharedPointer<StorageInterface> m_x;
public:
explicit StorageServiceObjectAdapter(sf::SharedPointer<StorageInterface> &&o) : m_x(o) { /* ... */}
virtual ~StorageServiceObjectAdapter() { /* ... */ }
public:
virtual Result Read(s64 offset, void *buffer, size_t size) override final {
R_RETURN(m_x->Read(offset, sf::OutNonSecureBuffer(buffer, size), static_cast<s64>(size)));
}
virtual Result GetSize(s64 *out) override final {
R_RETURN(m_x->GetSize(out));
}
virtual Result Flush() override final {
R_RETURN(m_x->Flush());
}
virtual Result Write(s64 offset, const void *buffer, size_t size) override final {
R_RETURN(m_x->Write(offset, sf::InNonSecureBuffer(buffer, size), static_cast<s64>(size)));
}
virtual Result SetSize(s64 size) override final {
R_RETURN(m_x->SetSize(size));
}
virtual Result OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override final {
AMS_UNUSED(src, src_size);
switch (op_id) {
case OperationId::Invalidate:
{
fs::QueryRangeInfo dummy_range_info;
R_RETURN(m_x->OperateRange(std::addressof(dummy_range_info), static_cast<s32>(op_id), offset, size));
}
case OperationId::QueryRange:
{
R_UNLESS(dst != nullptr, fs::ResultNullptrArgument());
R_UNLESS(dst_size == sizeof(fs::QueryRangeInfo), fs::ResultInvalidSize());
R_RETURN(m_x->OperateRange(reinterpret_cast<fs::QueryRangeInfo *>(dst), static_cast<s32>(op_id), offset, size));
}
default:
{
R_THROW(fs::ResultUnsupportedOperateRangeForStorageServiceObjectAdapter());
}
}
}
};
}