finish refactor, add docs and CI
CI / Build NRO (push) Failing after 3s
CI / Format check (push) Successful in 14s
CI / Layering check (push) Successful in 1s

This commit is contained in:
2026-04-27 01:49:41 +03:00
parent dc65a4c8a9
commit 31b7a4401e
47 changed files with 1964 additions and 1470 deletions
+10 -17
View File
@@ -26,9 +26,8 @@
#include <nxst/infra/fs/directory.hpp>
Directory::Directory(const std::string& root)
{
mGood = false;
Directory::Directory(const std::string& root) {
mGood = false;
mError = 0;
mList.clear();
@@ -37,11 +36,10 @@ Directory::Directory(const std::string& root)
if (dir == NULL) {
mError = (Result)errno;
}
else {
} else {
while ((ent = readdir(dir))) {
std::string name = std::string(ent->d_name);
bool directory = ent->d_type == DT_DIR;
std::string name = std::string(ent->d_name);
bool directory = ent->d_type == DT_DIR;
struct DirectoryEntry de = {name, directory};
mList.push_back(de);
}
@@ -50,27 +48,22 @@ Directory::Directory(const std::string& root)
}
}
Result Directory::error(void)
{
Result Directory::error(void) {
return mError;
}
bool Directory::good(void)
{
bool Directory::good(void) {
return mGood;
}
std::string Directory::entry(size_t index)
{
std::string Directory::entry(size_t index) {
return index < mList.size() ? mList.at(index).name : "";
}
bool Directory::folder(size_t index)
{
bool Directory::folder(size_t index) {
return index < mList.size() ? mList.at(index).directory : false;
}
size_t Directory::size(void)
{
size_t Directory::size(void) {
return mList.size();
}
+3 -6
View File
@@ -26,17 +26,14 @@
#include <nxst/infra/fs/filesystem.hpp>
Result FileSystem::mount(FsFileSystem* fileSystem, u64 titleID, AccountUid userID)
{
Result FileSystem::mount(FsFileSystem* fileSystem, u64 titleID, AccountUid userID) {
return fsOpen_SaveData(fileSystem, titleID, userID);
}
int FileSystem::mount(FsFileSystem fs)
{
int FileSystem::mount(FsFileSystem fs) {
return fsdevMountDevice("save", fs);
}
void FileSystem::unmount(void)
{
void FileSystem::unmount(void) {
fsdevUnmountDevice("save");
}
+34 -47
View File
@@ -24,20 +24,19 @@
* reasonable ways as different from the original version.
*/
#include <nxst/infra/fs/io.hpp>
#include <nxst/infra/fs/handles.hpp>
#include <nxst/app/main.hpp>
#include <nxst/infra/sys/logger.hpp>
#include <vector>
bool io::fileExists(const std::string& path)
{
#include <nxst/app/main.hpp>
#include <nxst/infra/fs/handles.hpp>
#include <nxst/infra/fs/io.hpp>
#include <nxst/infra/sys/logger.hpp>
bool io::fileExists(const std::string& path) {
struct stat buffer;
return (stat(path.c_str(), &buffer) == 0);
}
void io::copyFile(const std::string& srcPath, const std::string& dstPath)
{
void io::copyFile(const std::string& srcPath, const std::string& dstPath) {
g_isTransferringFile = true;
nxst::FileHandle src(fopen(srcPath.c_str(), "rb"));
@@ -63,14 +62,13 @@ void io::copyFile(const std::string& srcPath, const std::string& dstPath)
u64 offset = 0;
size_t slashpos = srcPath.rfind('/');
g_currentFile = srcPath.substr(slashpos + 1, srcPath.length() - slashpos - 1);
g_currentFile = srcPath.substr(slashpos + 1, srcPath.length() - slashpos - 1);
while (offset < sz) {
u32 count = (u32)fread(buf.data(), 1, BUFFER_SIZE, src.get());
if (count == 0) {
nxst::log::error("fread returned 0 for %s at offset %llu/%llu (errno %d). Aborting.",
srcPath.c_str(), (unsigned long long)offset,
(unsigned long long)sz, errno);
srcPath.c_str(), (unsigned long long)offset, (unsigned long long)sz, errno);
break;
}
fwrite(buf.data(), 1, count, dst.get());
@@ -84,10 +82,9 @@ void io::copyFile(const std::string& srcPath, const std::string& dstPath)
g_isTransferringFile = false;
}
Result io::copyDirectory(const std::string& srcPath, const std::string& dstPath)
{
Result io::copyDirectory(const std::string& srcPath, const std::string& dstPath) {
Result res = 0;
bool quit = false;
bool quit = false;
Directory items(srcPath);
if (!items.good()) {
@@ -104,12 +101,10 @@ Result io::copyDirectory(const std::string& srcPath, const std::string& dstPath)
newsrc += "/";
newdst += "/";
res = io::copyDirectory(newsrc, newdst);
}
else {
} else {
quit = true;
}
}
else {
} else {
io::copyFile(newsrc, newdst);
}
}
@@ -117,20 +112,17 @@ Result io::copyDirectory(const std::string& srcPath, const std::string& dstPath)
return 0;
}
Result io::createDirectory(const std::string& path)
{
Result io::createDirectory(const std::string& path) {
mkdir(path.c_str(), 0777);
return 0;
}
bool io::directoryExists(const std::string& path)
{
bool io::directoryExists(const std::string& path) {
struct stat sb;
return (stat(path.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode));
}
Result io::deleteFolderRecursively(const std::string& path)
{
Result io::deleteFolderRecursively(const std::string& path) {
Directory dir(path);
if (!dir.good()) {
return dir.error();
@@ -142,8 +134,7 @@ Result io::deleteFolderRecursively(const std::string& path)
deleteFolderRecursively(newpath);
newpath = path + dir.entry(i);
rmdir(newpath.c_str());
}
else {
} else {
std::string newpath = path + dir.entry(i);
std::remove(newpath.c_str());
}
@@ -153,14 +144,12 @@ Result io::deleteFolderRecursively(const std::string& path)
return 0;
}
nxst::Result<std::string> io::backup(size_t index, AccountUid uid)
{
nxst::Result<std::string> io::backup(size_t index, AccountUid uid) {
Title title;
getTitle(title, uid, index);
nxst::log::info("Started backup of %s. Title id: 0x%016lX; User id: 0x%lX%lX.",
title.name().c_str(), title.id(),
title.userId().uid[1], title.userId().uid[0]);
nxst::log::info("Started backup of %s. Title id: 0x%016lX; User id: 0x%lX%lX.", title.name().c_str(),
title.id(), title.userId().uid[1], title.userId().uid[0]);
nxst::FsFileSystemHandle fsHandle;
Result res = FileSystem::mount(fsHandle.get(), title.id(), title.userId());
@@ -180,7 +169,8 @@ nxst::Result<std::string> io::backup(size_t index, AccountUid uid)
}
fsHandle.release(); // devfs now owns the kernel handle
std::string suggestion = StringUtils::removeNotAscii(StringUtils::removeAccents(Account::username(title.userId())));
std::string suggestion =
StringUtils::removeNotAscii(StringUtils::removeAccents(Account::username(title.userId())));
io::createDirectory(title.path());
std::string dst_path = title.path() + "/" + suggestion;
@@ -215,15 +205,13 @@ nxst::Result<std::string> io::backup(size_t index, AccountUid uid)
}
// Creates the save data filesystem for a title if it doesn't exist yet.
static void createSaveIfNeeded(u64 title_id, AccountUid uid)
{
static void createSaveIfNeeded(u64 title_id, AccountUid uid) {
std::vector<u8> nsacd_buf(sizeof(NsApplicationControlData), 0);
auto* nsacd = reinterpret_cast<NsApplicationControlData*>(nsacd_buf.data());
size_t outsize = 0;
if (!R_SUCCEEDED(nsGetApplicationControlData(NsApplicationControlSource_Storage,
title_id, nsacd,
sizeof(NsApplicationControlData), &outsize))) {
if (!R_SUCCEEDED(nsGetApplicationControlData(NsApplicationControlSource_Storage, title_id, nsacd,
sizeof(NsApplicationControlData), &outsize))) {
return;
}
@@ -231,30 +219,29 @@ static void createSaveIfNeeded(u64 title_id, AccountUid uid)
FsSaveDataAttribute attr = {};
attr.application_id = title_id;
attr.uid = uid;
attr.uid = uid;
attr.save_data_type = FsSaveDataType_Account;
attr.save_data_rank = FsSaveDataRank_Primary;
FsSaveDataCreationInfo create_info = {};
create_info.save_data_size = (s64)nsacd->nacp.user_account_save_data_size;
create_info.journal_size = (s64)nsacd->nacp.user_account_save_data_journal_size;
create_info.available_size = 0x4000;
create_info.owner_id = nsacd->nacp.save_data_owner_id;
create_info.save_data_size = (s64)nsacd->nacp.user_account_save_data_size;
create_info.journal_size = (s64)nsacd->nacp.user_account_save_data_journal_size;
create_info.available_size = 0x4000;
create_info.owner_id = nsacd->nacp.save_data_owner_id;
create_info.save_data_space_id = FsSaveDataSpaceId_User;
fsCreateSaveDataFileSystem(&attr, &create_info, &meta);
}
nxst::Result<std::string> io::restore(size_t index, AccountUid uid, size_t cellIndex, const std::string& nameFromCell)
{
nxst::Result<std::string> io::restore(size_t index, AccountUid uid, size_t cellIndex,
const std::string& nameFromCell) {
(void)cellIndex;
Title title;
getTitle(title, uid, index);
nxst::log::info("Started restore of %s. Title id: 0x%016lX; User id: 0x%lX%lX.",
title.name().c_str(), title.id(),
title.userId().uid[1], title.userId().uid[0]);
nxst::log::info("Started restore of %s. Title id: 0x%016lX; User id: 0x%lX%lX.", title.name().c_str(),
title.id(), title.userId().uid[1], title.userId().uid[0]);
createSaveIfNeeded(title.id(), uid);
+42 -16
View File
@@ -1,10 +1,10 @@
#include <nxst/infra/sys/logger.hpp>
#include <cstdarg>
#include <cstdio>
#include <ctime>
#include <mutex>
#include <nxst/infra/sys/logger.hpp>
namespace {
std::mutex g_log_mutex;
@@ -15,8 +15,7 @@ constexpr const char* kLogPath = "/switch/NXST/log.log";
constexpr const char* kLogPath = "nxst.log";
#endif
void writeEntry(const char* tag, const char* fmt, va_list args)
{
void writeEntry(const char* tag, const char* fmt, va_list args) {
char msg[2048];
vsnprintf(msg, sizeof(msg), fmt, args);
@@ -37,18 +36,25 @@ void writeEntry(const char* tag, const char* fmt, va_list args)
}
}
} // namespace
} // namespace
namespace nxst::log {
void write(Level level, const char* fmt, ...)
{
void write(Level level, const char* fmt, ...) {
const char* tag = "[INFO] ";
switch (level) {
case Level::Debug: tag = "[DEBUG]"; break;
case Level::Info: tag = "[INFO] "; break;
case Level::Warn: tag = "[WARN] "; break;
case Level::Error: tag = "[ERROR]"; break;
case Level::Debug:
tag = "[DEBUG]";
break;
case Level::Info:
tag = "[INFO] ";
break;
case Level::Warn:
tag = "[WARN] ";
break;
case Level::Error:
tag = "[ERROR]";
break;
}
va_list args;
va_start(args, fmt);
@@ -56,9 +62,29 @@ void write(Level level, const char* fmt, ...)
va_end(args);
}
void debug(const char* fmt, ...) { va_list args; va_start(args, fmt); writeEntry("[DEBUG]", fmt, args); va_end(args); }
void info (const char* fmt, ...) { va_list args; va_start(args, fmt); writeEntry("[INFO] ", fmt, args); va_end(args); }
void warn (const char* fmt, ...) { va_list args; va_start(args, fmt); writeEntry("[WARN] ", fmt, args); va_end(args); }
void error(const char* fmt, ...) { va_list args; va_start(args, fmt); writeEntry("[ERROR]", fmt, args); va_end(args); }
void debug(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
writeEntry("[DEBUG]", fmt, args);
va_end(args);
}
void info(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
writeEntry("[INFO] ", fmt, args);
va_end(args);
}
void warn(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
writeEntry("[WARN] ", fmt, args);
va_end(args);
}
void error(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
writeEntry("[ERROR]", fmt, args);
va_end(args);
}
} // namespace nxst::log
} // namespace nxst::log