simplify stdio/native file paths by sharing the same code.
This commit is contained in:
@@ -91,7 +91,6 @@ add_executable(sphaira
|
|||||||
source/yati/container/nsp.cpp
|
source/yati/container/nsp.cpp
|
||||||
source/yati/container/xci.cpp
|
source/yati/container/xci.cpp
|
||||||
source/yati/source/file.cpp
|
source/yati/source/file.cpp
|
||||||
source/yati/source/stdio.cpp
|
|
||||||
source/yati/source/usb.cpp
|
source/yati/source/usb.cpp
|
||||||
source/yati/source/stream.cpp
|
source/yati/source/stream.cpp
|
||||||
source/yati/source/stream_file.cpp
|
source/yati/source/stream_file.cpp
|
||||||
|
|||||||
@@ -3,17 +3,20 @@
|
|||||||
#include "base.hpp"
|
#include "base.hpp"
|
||||||
#include "fs.hpp"
|
#include "fs.hpp"
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace sphaira::yati::source {
|
namespace sphaira::yati::source {
|
||||||
|
|
||||||
struct File final : Base {
|
struct File final : Base {
|
||||||
File(FsFileSystem* fs, const fs::FsPath& path);
|
File(FsFileSystem* fs, const fs::FsPath& path);
|
||||||
|
File(const fs::FsPath& path);
|
||||||
~File();
|
~File();
|
||||||
|
|
||||||
Result Read(void* buf, s64 off, s64 size, u64* bytes_read) override;
|
Result Read(void* buf, s64 off, s64 size, u64* bytes_read) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FsFile m_file{};
|
std::unique_ptr<fs::Fs> m_fs{};
|
||||||
|
fs::File m_file{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sphaira::yati::source
|
} // namespace sphaira::yati::source
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "base.hpp"
|
|
||||||
#include "fs.hpp"
|
|
||||||
#include <cstdio>
|
|
||||||
#include <switch.h>
|
|
||||||
|
|
||||||
namespace sphaira::yati::source {
|
|
||||||
|
|
||||||
struct Stdio final : Base {
|
|
||||||
Stdio(const fs::FsPath& path);
|
|
||||||
~Stdio();
|
|
||||||
|
|
||||||
Result Read(void* buf, s64 off, s64 size, u64* bytes_read) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::FILE* m_file{};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace sphaira::yati::source
|
|
||||||
@@ -5,17 +5,20 @@
|
|||||||
#include "stream.hpp"
|
#include "stream.hpp"
|
||||||
#include "fs.hpp"
|
#include "fs.hpp"
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace sphaira::yati::source {
|
namespace sphaira::yati::source {
|
||||||
|
|
||||||
struct StreamFile final : Stream {
|
struct StreamFile final : Stream {
|
||||||
StreamFile(FsFileSystem* fs, const fs::FsPath& path);
|
StreamFile(FsFileSystem* fs, const fs::FsPath& path);
|
||||||
|
StreamFile(const fs::FsPath& path);
|
||||||
~StreamFile();
|
~StreamFile();
|
||||||
|
|
||||||
Result ReadChunk(void* buf, s64 size, u64* bytes_read) override;
|
Result ReadChunk(void* buf, s64 size, u64* bytes_read) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FsFile m_file{};
|
std::unique_ptr<fs::Fs> m_fs{};
|
||||||
|
fs::File m_file{};
|
||||||
s64 m_offset{};
|
s64 m_offset{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ struct ConfigOverride {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Result InstallFromFile(ui::ProgressBox* pbox, FsFileSystem* fs, const fs::FsPath& path, const ConfigOverride& override = {});
|
Result InstallFromFile(ui::ProgressBox* pbox, FsFileSystem* fs, const fs::FsPath& path, const ConfigOverride& override = {});
|
||||||
Result InstallFromStdioFile(ui::ProgressBox* pbox, const fs::FsPath& path, const ConfigOverride& override = {});
|
Result InstallFromFile(ui::ProgressBox* pbox, const fs::FsPath& path, const ConfigOverride& override = {});
|
||||||
Result InstallFromSource(ui::ProgressBox* pbox, std::shared_ptr<source::Base> source, const fs::FsPath& path, const ConfigOverride& override = {});
|
Result InstallFromSource(ui::ProgressBox* pbox, std::shared_ptr<source::Base> source, const fs::FsPath& path, const ConfigOverride& override = {});
|
||||||
Result InstallFromContainer(ui::ProgressBox* pbox, std::shared_ptr<container::Base> container, const ConfigOverride& override = {});
|
Result InstallFromContainer(ui::ProgressBox* pbox, std::shared_ptr<container::Base> container, const ConfigOverride& override = {});
|
||||||
Result InstallFromCollections(ui::ProgressBox* pbox, std::shared_ptr<source::Base> source, const container::Collections& collections, const ConfigOverride& override = {});
|
Result InstallFromCollections(ui::ProgressBox* pbox, std::shared_ptr<source::Base> source, const container::Collections& collections, const ConfigOverride& override = {});
|
||||||
|
|||||||
@@ -102,89 +102,54 @@ private:
|
|||||||
s64 m_pull_offset{};
|
s64 m_pull_offset{};
|
||||||
};
|
};
|
||||||
|
|
||||||
Result DumpToFile(ui::ProgressBox* pbox, BaseSource* source, std::span<const fs::FsPath> paths) {
|
Result DumpToFile(ui::ProgressBox* pbox, fs::Fs* fs, const fs::FsPath& root, BaseSource* source, std::span<const fs::FsPath> paths) {
|
||||||
static constexpr fs::FsPath DUMP_PATH{"/dumps/NSP"};
|
const auto DUMP_PATH = fs::AppendPath(root, "/dumps/NSP");
|
||||||
constexpr s64 BIG_FILE_SIZE = 1024ULL*1024ULL*1024ULL*4ULL;
|
constexpr s64 BIG_FILE_SIZE = 1024ULL*1024ULL*1024ULL*4ULL;
|
||||||
|
|
||||||
fs::FsNativeSd fs{};
|
|
||||||
R_TRY(fs.GetFsOpenResult());
|
|
||||||
|
|
||||||
for (auto path : paths) {
|
for (auto path : paths) {
|
||||||
const auto file_size = source->GetSize(path);
|
const auto file_size = source->GetSize(path);
|
||||||
pbox->SetTitle(source->GetName(path));
|
pbox->SetTitle(source->GetName(path));
|
||||||
pbox->NewTransfer(path);
|
pbox->NewTransfer(path);
|
||||||
|
|
||||||
const auto temp_path = fs::AppendPath(DUMP_PATH, path + ".temp");
|
const auto temp_path = fs::AppendPath(DUMP_PATH, path + ".temp");
|
||||||
fs.CreateDirectoryRecursivelyWithPath(temp_path);
|
fs->CreateDirectoryRecursivelyWithPath(temp_path);
|
||||||
fs.DeleteFile(temp_path);
|
fs->DeleteFile(temp_path);
|
||||||
|
|
||||||
const auto flags = file_size >= BIG_FILE_SIZE ? FsCreateOption_BigFile : 0;
|
const auto flags = file_size >= BIG_FILE_SIZE ? FsCreateOption_BigFile : 0;
|
||||||
R_TRY(fs.CreateFile(temp_path, file_size, flags));
|
R_TRY(fs->CreateFile(temp_path, file_size, flags));
|
||||||
ON_SCOPE_EXIT(fs.DeleteFile(temp_path));
|
ON_SCOPE_EXIT(fs->DeleteFile(temp_path));
|
||||||
|
|
||||||
{
|
{
|
||||||
FsFile file;
|
fs::File file;
|
||||||
R_TRY(fs.OpenFile(temp_path, FsOpenMode_Write, &file));
|
R_TRY(fs->OpenFile(temp_path, FsOpenMode_Write, &file));
|
||||||
ON_SCOPE_EXIT(fsFileClose(&file));
|
ON_SCOPE_EXIT(fs->FileClose(&file));
|
||||||
|
|
||||||
R_TRY(thread::Transfer(pbox, file_size,
|
R_TRY(thread::Transfer(pbox, file_size,
|
||||||
[&](void* data, s64 off, s64 size, u64* bytes_read) -> Result {
|
[&](void* data, s64 off, s64 size, u64* bytes_read) -> Result {
|
||||||
return source->Read(path, data, off, size, bytes_read);
|
return source->Read(path, data, off, size, bytes_read);
|
||||||
},
|
},
|
||||||
[&](const void* data, s64 off, s64 size) -> Result {
|
[&](const void* data, s64 off, s64 size) -> Result {
|
||||||
return fsFileWrite(&file, off, data, size, FsWriteOption_None);
|
return fs->FileWrite(&file, off, data, size, FsWriteOption_None);
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
path = fs::AppendPath(DUMP_PATH, path);
|
path = fs::AppendPath(DUMP_PATH, path);
|
||||||
fs.DeleteFile(path);
|
fs->DeleteFile(path);
|
||||||
R_TRY(fs.RenameFile(temp_path, path));
|
R_TRY(fs->RenameFile(temp_path, path));
|
||||||
}
|
}
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result DumpToFileNative(ui::ProgressBox* pbox, BaseSource* source, std::span<const fs::FsPath> paths) {
|
||||||
|
fs::FsNative fs{};
|
||||||
|
return DumpToFile(pbox, &fs, "/", source, paths);
|
||||||
|
}
|
||||||
|
|
||||||
Result DumpToStdio(ui::ProgressBox* pbox, const location::StdioEntry& loc, BaseSource* source, std::span<const fs::FsPath> paths) {
|
Result DumpToStdio(ui::ProgressBox* pbox, const location::StdioEntry& loc, BaseSource* source, std::span<const fs::FsPath> paths) {
|
||||||
const fs::FsPath DUMP_PATH = loc.mount + "/dumps/NSP";
|
|
||||||
|
|
||||||
fs::FsStdio fs{};
|
fs::FsStdio fs{};
|
||||||
|
return DumpToFile(pbox, &fs, loc.mount, source, paths);
|
||||||
for (auto path : paths) {
|
|
||||||
const auto file_size = source->GetSize(path);
|
|
||||||
pbox->SetTitle(source->GetName(path));
|
|
||||||
pbox->NewTransfer(path);
|
|
||||||
|
|
||||||
const auto temp_path = fs::AppendPath(DUMP_PATH, path + ".temp");
|
|
||||||
fs.CreateDirectoryRecursivelyWithPath(temp_path);
|
|
||||||
fs.DeleteFile(temp_path);
|
|
||||||
|
|
||||||
R_TRY(fs.CreateFile(temp_path, file_size));
|
|
||||||
ON_SCOPE_EXIT(fs.DeleteFile(temp_path));
|
|
||||||
|
|
||||||
{
|
|
||||||
auto file = std::fopen(temp_path, "wb");
|
|
||||||
R_UNLESS(file, 0x1);
|
|
||||||
ON_SCOPE_EXIT(std::fclose(file));
|
|
||||||
|
|
||||||
R_TRY(thread::Transfer(pbox, file_size,
|
|
||||||
[&](void* data, s64 off, s64 size, u64* bytes_read) -> Result {
|
|
||||||
return source->Read(path, data, off, size, bytes_read);
|
|
||||||
},
|
|
||||||
[&](const void* data, s64 off, s64 size) -> Result {
|
|
||||||
const auto written = std::fwrite(data, 1, size, file);
|
|
||||||
R_UNLESS(written >= 1, 0x1);
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
path = fs::AppendPath(DUMP_PATH, path);
|
|
||||||
fs.DeleteFile(path);
|
|
||||||
R_TRY(fs.RenameFile(temp_path, path));
|
|
||||||
}
|
|
||||||
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DumpToUsbS2SStream(ui::ProgressBox* pbox, UsbTest* usb, std::span<const fs::FsPath> paths) {
|
Result DumpToUsbS2SStream(ui::ProgressBox* pbox, UsbTest* usb, std::span<const fs::FsPath> paths) {
|
||||||
@@ -389,7 +354,7 @@ void Dump(std::shared_ptr<BaseSource> source, const std::vector<fs::FsPath>& pat
|
|||||||
} else if (dump_entry.type == DumpLocationType_Stdio) {
|
} else if (dump_entry.type == DumpLocationType_Stdio) {
|
||||||
R_TRY(DumpToStdio(pbox, stdio_locations[dump_entry.index], source.get(), paths));
|
R_TRY(DumpToStdio(pbox, stdio_locations[dump_entry.index], source.get(), paths));
|
||||||
} else if (dump_entry.type == DumpLocationType_SdCard) {
|
} else if (dump_entry.type == DumpLocationType_SdCard) {
|
||||||
R_TRY(DumpToFile(pbox, source.get(), paths));
|
R_TRY(DumpToFileNative(pbox, source.get(), paths));
|
||||||
} else if (dump_entry.type == DumpLocationType_UsbS2S) {
|
} else if (dump_entry.type == DumpLocationType_UsbS2S) {
|
||||||
R_TRY(DumpToUsbS2S(pbox, source.get(), paths));
|
R_TRY(DumpToUsbS2S(pbox, source.get(), paths));
|
||||||
} else if (dump_entry.type == DumpLocationType_DevNull) {
|
} else if (dump_entry.type == DumpLocationType_DevNull) {
|
||||||
|
|||||||
@@ -465,9 +465,9 @@ Result OpenFile(fs::Fs* fs, const fs::FsPath& path, u32 mode, File* f) {
|
|||||||
// todo:
|
// todo:
|
||||||
R_THROW(0x1);
|
R_THROW(0x1);
|
||||||
} else if (mode & FsOpenMode_Read) {
|
} else if (mode & FsOpenMode_Read) {
|
||||||
f->m_stdio = fopen(path, "rb");
|
f->m_stdio = std::fopen(path, "rb");
|
||||||
} else if (mode & FsOpenMode_Write) {
|
} else if (mode & FsOpenMode_Write) {
|
||||||
f->m_stdio = fopen(path, "wb");
|
f->m_stdio = std::fopen(path, "wb");
|
||||||
}
|
}
|
||||||
|
|
||||||
R_UNLESS(f->m_stdio, 0x1);
|
R_UNLESS(f->m_stdio, 0x1);
|
||||||
|
|||||||
@@ -931,7 +931,7 @@ void Menu::InstallFiles() {
|
|||||||
if (m_fs->IsNative()) {
|
if (m_fs->IsNative()) {
|
||||||
R_TRY(yati::InstallFromFile(pbox, &GetNative()->m_fs, GetNewPath(e)));
|
R_TRY(yati::InstallFromFile(pbox, &GetNative()->m_fs, GetNewPath(e)));
|
||||||
} else {
|
} else {
|
||||||
R_TRY(yati::InstallFromStdioFile(pbox, GetNewPath(e)));
|
R_TRY(yati::InstallFromFile(pbox, GetNewPath(e)));
|
||||||
}
|
}
|
||||||
App::Notify("Installed " + e.GetName());
|
App::Notify("Installed " + e.GetName());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,18 +3,28 @@
|
|||||||
namespace sphaira::yati::source {
|
namespace sphaira::yati::source {
|
||||||
|
|
||||||
File::File(FsFileSystem* fs, const fs::FsPath& path) {
|
File::File(FsFileSystem* fs, const fs::FsPath& path) {
|
||||||
m_open_result = fsFsOpenFile(fs, path, FsOpenMode_Read, std::addressof(m_file));
|
if (fs) {
|
||||||
|
m_fs = std::make_unique<fs::FsNative>(fs, false);
|
||||||
|
} else {
|
||||||
|
m_fs = std::make_unique<fs::FsStdio>();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_open_result = m_fs->OpenFile(path, FsOpenMode_Read, std::addressof(m_file));
|
||||||
|
}
|
||||||
|
|
||||||
|
File::File(const fs::FsPath& path) : File{nullptr, path} {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
File::~File() {
|
File::~File() {
|
||||||
if (R_SUCCEEDED(GetOpenResult())) {
|
if (R_SUCCEEDED(GetOpenResult())) {
|
||||||
fsFileClose(std::addressof(m_file));
|
m_fs->FileClose(std::addressof(m_file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result File::Read(void* buf, s64 off, s64 size, u64* bytes_read) {
|
Result File::Read(void* buf, s64 off, s64 size, u64* bytes_read) {
|
||||||
R_TRY(GetOpenResult());
|
R_TRY(GetOpenResult());
|
||||||
return fsFileRead(std::addressof(m_file), off, buf, size, 0, bytes_read);
|
return m_fs->FileRead(std::addressof(m_file), off, buf, size, 0, bytes_read);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sphaira::yati::source
|
} // namespace sphaira::yati::source
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
#include "yati/source/stdio.hpp"
|
|
||||||
|
|
||||||
namespace sphaira::yati::source {
|
|
||||||
|
|
||||||
Stdio::Stdio(const fs::FsPath& path) {
|
|
||||||
m_file = std::fopen(path, "rb");
|
|
||||||
if (!m_file) {
|
|
||||||
m_open_result = fsdevGetLastResult();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Stdio::~Stdio() {
|
|
||||||
if (R_SUCCEEDED(GetOpenResult())) {
|
|
||||||
std::fclose(m_file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Result Stdio::Read(void* buf, s64 off, s64 size, u64* bytes_read) {
|
|
||||||
R_TRY(GetOpenResult());
|
|
||||||
|
|
||||||
std::fseek(m_file, off, SEEK_SET);
|
|
||||||
R_TRY(fsdevGetLastResult());
|
|
||||||
|
|
||||||
*bytes_read = std::fread(buf, 1, size, m_file);
|
|
||||||
return fsdevGetLastResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace sphaira::yati::source
|
|
||||||
@@ -4,18 +4,28 @@
|
|||||||
namespace sphaira::yati::source {
|
namespace sphaira::yati::source {
|
||||||
|
|
||||||
StreamFile::StreamFile(FsFileSystem* fs, const fs::FsPath& path) {
|
StreamFile::StreamFile(FsFileSystem* fs, const fs::FsPath& path) {
|
||||||
m_open_result = fsFsOpenFile(fs, path, FsOpenMode_Read, std::addressof(m_file));
|
if (fs) {
|
||||||
|
m_fs = std::make_unique<fs::FsNative>(fs, false);
|
||||||
|
} else {
|
||||||
|
m_fs = std::make_unique<fs::FsStdio>();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_open_result = m_fs->OpenFile(path, FsOpenMode_Read, std::addressof(m_file));
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamFile::StreamFile(const fs::FsPath& path) : StreamFile{nullptr, path} {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamFile::~StreamFile() {
|
StreamFile::~StreamFile() {
|
||||||
if (R_SUCCEEDED(GetOpenResult())) {
|
if (R_SUCCEEDED(GetOpenResult())) {
|
||||||
fsFileClose(std::addressof(m_file));
|
m_fs->FileClose(std::addressof(m_file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result StreamFile::ReadChunk(void* buf, s64 size, u64* bytes_read) {
|
Result StreamFile::ReadChunk(void* buf, s64 size, u64* bytes_read) {
|
||||||
R_TRY(GetOpenResult());
|
R_TRY(GetOpenResult());
|
||||||
const auto rc = fsFileRead(std::addressof(m_file), m_offset, buf, size, 0, bytes_read);
|
const auto rc = m_fs->FileRead(std::addressof(m_file), m_offset, buf, size, 0, bytes_read);
|
||||||
m_offset += *bytes_read;
|
m_offset += *bytes_read;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "yati/yati.hpp"
|
#include "yati/yati.hpp"
|
||||||
#include "yati/source/file.hpp"
|
#include "yati/source/file.hpp"
|
||||||
#include "yati/source/stream_file.hpp"
|
#include "yati/source/stream_file.hpp"
|
||||||
#include "yati/source/stdio.hpp"
|
|
||||||
#include "yati/container/nsp.hpp"
|
#include "yati/container/nsp.hpp"
|
||||||
#include "yati/container/xci.hpp"
|
#include "yati/container/xci.hpp"
|
||||||
|
|
||||||
@@ -1393,8 +1392,8 @@ Result InstallFromFile(ui::ProgressBox* pbox, FsFileSystem* fs, const fs::FsPath
|
|||||||
// return InstallFromSource(pbox, std::make_shared<source::StreamFile>(fs, path), path, override);
|
// return InstallFromSource(pbox, std::make_shared<source::StreamFile>(fs, path), path, override);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result InstallFromStdioFile(ui::ProgressBox* pbox, const fs::FsPath& path, const ConfigOverride& override) {
|
Result InstallFromFile(ui::ProgressBox* pbox, const fs::FsPath& path, const ConfigOverride& override) {
|
||||||
return InstallFromSource(pbox, std::make_shared<source::Stdio>(path), path, override);
|
return InstallFromFile(pbox, nullptr, path, override);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result InstallFromSource(ui::ProgressBox* pbox, std::shared_ptr<source::Base> source, const fs::FsPath& path, const ConfigOverride& override) {
|
Result InstallFromSource(ui::ProgressBox* pbox, std::shared_ptr<source::Base> source, const fs::FsPath& path, const ConfigOverride& override) {
|
||||||
|
|||||||
Reference in New Issue
Block a user