diff --git a/trunk/ConsoleDataMigration/sources/ConsoleBackup/SavedataChecker.cpp b/trunk/ConsoleDataMigration/sources/ConsoleBackup/SavedataChecker.cpp index 98e6d4b..d8c8028 100644 --- a/trunk/ConsoleDataMigration/sources/ConsoleBackup/SavedataChecker.cpp +++ b/trunk/ConsoleDataMigration/sources/ConsoleBackup/SavedataChecker.cpp @@ -179,61 +179,7 @@ nn::Result SavedataCheckerBase::CleanUpFilesRecursively(bool* modified, std::str nn::Result SavedataCheckerBase::GetFileSize(std::wstring currentDirectory) { - nn::fs::Directory dir; - nn::fs::DirectoryEntry entry; - nn::Result result; - - NN_LOG("%s\n", common::GetCharStr(currentDirectory.c_str())); - result = dir.TryInitialize(currentDirectory.c_str()); - if(result.IsFailure()) - { - return result; - } - - for (;;) - { - s32 numRead; - result = dir.TryRead(&numRead, &entry, 1); - if(result.IsFailure()) - { - continue; - } - - - if(numRead == 0) - { - break; - } - - if (std::wcscmp(entry.entryName, L".") == 0 || std::wcscmp(entry.entryName, L"..") == 0) - { - continue; - } - - - // ディレクトリの場合 - if (entry.attributes.isDirectory) - { - return GetFileSize(currentDirectory + std::wstring(entry.entryName) + std::wstring(L"/")); - } - // ファイルの場合 - else - { - nn::fs::FileInputStream file; - std::wstring filePath = (currentDirectory + std::wstring(entry.entryName)).c_str(); - const wchar_t* path = filePath.c_str(); - - result = file.TryInitialize(path); - if(result.IsFailure()) - { - continue; - } - - m_CalculatedFileSize += file.GetSize(); - } - } - - return nn::ResultSuccess(); + return common::CalculateFileSizeRecursively(currentDirectory, m_CalculatedFileSize); } s64 SavedataCheckerBase::GetCalculatedSize() diff --git a/trunk/ConsoleDataMigration/sources/common/FileName.h b/trunk/ConsoleDataMigration/sources/common/FileName.h index 310e351..bb66cdf 100644 --- a/trunk/ConsoleDataMigration/sources/common/FileName.h +++ b/trunk/ConsoleDataMigration/sources/common/FileName.h @@ -71,6 +71,7 @@ const wchar_t* const MOVE_CONTEXT_PATHNAME = L"sdmc:/CTR_Console_Repair/MoveCont const wchar_t* const SD_NINTENDO_3DS_ROOT_PATH = L"sdmc:/Nintendo 3DS/"; const wchar_t* const SD_SAEVDATA_SYS_NAME = L"sysdata"; +const wchar_t* const SD_SAEVDATA_EXT_NAME = L"extdata"; enum TWL_PATH_INDEX { diff --git a/trunk/ConsoleDataMigration/sources/common/FileTransfer.cpp b/trunk/ConsoleDataMigration/sources/common/FileTransfer.cpp index 04b6823..daf8d15 100644 --- a/trunk/ConsoleDataMigration/sources/common/FileTransfer.cpp +++ b/trunk/ConsoleDataMigration/sources/common/FileTransfer.cpp @@ -766,4 +766,63 @@ bool AddPathNameAndUpdateContext(nn::fs::FileOutputStream* file, const wchar_t * return true; } +nn::Result CalculateFileSizeRecursively(std::wstring currentDirectory, s64& fileSize) +{ + nn::fs::Directory dir; + nn::fs::DirectoryEntry entry; + nn::Result result; + + NN_LOG("%s\n", common::GetCharStr(currentDirectory.c_str())); + result = dir.TryInitialize(currentDirectory.c_str()); + if(result.IsFailure()) + { + return result; + } + + for (;;) + { + s32 numRead; + result = dir.TryRead(&numRead, &entry, 1); + if(result.IsFailure()) + { + continue; + } + + + if(numRead == 0) + { + break; + } + + if (std::wcscmp(entry.entryName, L".") == 0 || std::wcscmp(entry.entryName, L"..") == 0) + { + continue; + } + + + // ディレクトリの場合 + if (entry.attributes.isDirectory) + { + return CalculateFileSizeRecursively(currentDirectory + std::wstring(entry.entryName) + std::wstring(L"/"), fileSize); + } + // ファイルの場合 + else + { + nn::fs::FileInputStream file; + std::wstring filePath = (currentDirectory + std::wstring(entry.entryName)).c_str(); + const wchar_t* path = filePath.c_str(); + + result = file.TryInitialize(path); + if(result.IsFailure()) + { + continue; + } + + fileSize += file.GetSize(); + } + } + + return nn::ResultSuccess(); +} + } diff --git a/trunk/ConsoleDataMigration/sources/common/FileTransfer.h b/trunk/ConsoleDataMigration/sources/common/FileTransfer.h index 02042c2..d74fa78 100644 --- a/trunk/ConsoleDataMigration/sources/common/FileTransfer.h +++ b/trunk/ConsoleDataMigration/sources/common/FileTransfer.h @@ -59,6 +59,9 @@ const char* GetCharStr(const wchar_t* path); void AddPkcsPadding(u8* paddingSize, void* buf, size_t bufSize, s32* readSize); +// ディレクトリ以下のファイルサイズを計算する +nn::Result CalculateFileSizeRecursively(std::wstring currentDirectory, s64& fileSize); + } #endif /* FILETRANSFER_H_ */ diff --git a/trunk/ConsoleDataMigration/sources/common/SaveDataMover.cpp b/trunk/ConsoleDataMigration/sources/common/SaveDataMover.cpp index 69a1fb0..b163dc5 100644 --- a/trunk/ConsoleDataMigration/sources/common/SaveDataMover.cpp +++ b/trunk/ConsoleDataMigration/sources/common/SaveDataMover.cpp @@ -16,7 +16,9 @@ #include #include +#include #include +#include #include @@ -24,6 +26,7 @@ #include "CommonLogger.h" #include "FileName.h" #include "SdReaderWriter.h" +#include "FileTransfer.h" namespace common @@ -31,9 +34,12 @@ namespace common namespace { + const char* ARC_NAME = "sext:"; + const s32 MAX_SYSTEM_SAVE_DATA_ID_NUM = 256; nn::fs::SystemSaveDataId s_SystemSaveDataIdList[MAX_SYSTEM_SAVE_DATA_ID_NUM * sizeof(bit32)]; - + const s32 MAX_SHARED_EXT_SAVE_DATA_ID_NUM = 10; + nn::fs::SharedExtSaveDataId s_SharedExtSaveDataIdList[MAX_SHARED_EXT_SAVE_DATA_ID_NUM * sizeof(bit32)]; bool IsNotMovedId(bit32 id) { @@ -46,23 +52,21 @@ namespace SaveDataMover::SaveDataMover() : m_Progress(0), m_FinishedSize(0), m_TotalSize(0), m_Result(nn::ResultSuccess()) { - // TODO 自動生成されたコンストラクター・スタブ } SaveDataMover::~SaveDataMover() { - // TODO Auto-generated destructor stub } void SaveDataMover::StartExport(void* buf, size_t bufSize, u64* progress) { SetupExport(); + COMMON_LOGGER_RETURN_VOID_IF_FAILED(GetLastResult()); CalculateFileSize(); - if(GetLastResult().IsFailure()) - { - return; - } + COMMON_LOGGER_RETURN_VOID_IF_FAILED(GetLastResult()); ExportSystemSaveData(buf, bufSize, progress); + COMMON_LOGGER_RETURN_VOID_IF_FAILED(GetLastResult()); + ExportSharedExtSaveData(buf, bufSize, progress); } nn::Result SaveDataMover::GetLastResult() @@ -84,19 +88,33 @@ void SaveDataMover::SetupExport() COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); // 3. 出力用ディレクトリの作成 + // 3.1 システムセーブデータ用ディレクトリ common::SdReaderWriter sdWriter; m_Result = sdWriter.CreateDirectory((::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring( common::SD_SAVEDATA_ROOT_NAME) + std::wstring(common::SD_SAEVDATA_SYS_NAME)).c_str()); COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); + + // 3.2 共有拡張セーブデータ用ディレクトリ + m_Result = sdWriter.CreateDirectory((::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring( + common::SD_SAVEDATA_ROOT_NAME) + std::wstring(common::SD_SAEVDATA_EXT_NAME)).c_str()); + COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); + } void SaveDataMover::CalculateFileSize() +{ + CalculateSystemSaveDataSize(); + CalculateSharedExtSaveDataSize(); +} + +void SaveDataMover::CalculateSystemSaveDataSize() { s32 systemSaveDataIdNum; m_Result = nn::fs::EnumerateSystemSaveData(&systemSaveDataIdNum, s_SystemSaveDataIdList, MAX_SYSTEM_SAVE_DATA_ID_NUM); COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); - for(int i = 0; i < systemSaveDataIdNum; ++i) + // システムセーブデータのサイズを確認する + for(s32 i = 0; i < systemSaveDataIdNum; ++i) { nn::fs::FileInputStream input; @@ -117,6 +135,35 @@ void SaveDataMover::CalculateFileSize() } } +void SaveDataMover::CalculateSharedExtSaveDataSize() +{ + // 共有拡張セーブデータのサイズを確認する + // 0. ID の列挙を行う。 + s32 sharedExtSaveDataIdNum; + m_Result = nn::fs::EnumerateSharedExtSaveData(&sharedExtSaveDataIdNum, s_SharedExtSaveDataIdList, + MAX_SHARED_EXT_SAVE_DATA_ID_NUM); + for(s32 i = 0; i < sharedExtSaveDataIdNum; ++i) + { + bit32 id = s_SharedExtSaveDataIdList[i]; + + // 1. fs::MountSharedExtSaveDataRawStorage を呼び + // ID に対応するアーカイブをマウントする。 + // 既存の共有拡張セーブデータ領域へのアーカイブをマウントします。 + m_Result = nn::fs::MountSharedExtSaveDataRawStorage(ARC_NAME, id); + COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); + + // 2. アーカイブ内を走査して、含まれるファイルと + // ディレクトリを、その構造を保ったまま + // エクスポートする。 + COMMON_LOGGER_RETURN_VOID_IF_FAILED(common::CalculateFileSizeRecursively(L"sext:/", m_TotalSize)); + + // 3. アンマウントする + m_Result = nn::fs::Unmount(ARC_NAME); + COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); + } + NN_LOG("calculatedSize = %lld\n", m_TotalSize); +} + void SaveDataMover::ExportSystemSaveData(void* buf, size_t bufSize, u64* progress) { s64 totalFileSize = 0; @@ -126,7 +173,7 @@ void SaveDataMover::ExportSystemSaveData(void* buf, size_t bufSize, u64* progres m_Result = nn::fs::EnumerateSystemSaveData(&systemSaveDataIdNum, s_SystemSaveDataIdList, MAX_SYSTEM_SAVE_DATA_ID_NUM); COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); - for(int i = 0; i < systemSaveDataIdNum; ++i) + for(s32 i = 0; i < systemSaveDataIdNum; ++i) { nn::fs::FileInputStream input; @@ -178,27 +225,132 @@ void SaveDataMover::ExportSystemSaveData(void* buf, size_t bufSize, u64* progres NN_LOG("totalFileSize = %lld\n", totalFileSize); } +void SaveDataMover::ExportSharedExtSaveData(void* buf, size_t bufSize, u64* progress) +{ + // 0. ID の列挙を行う。 + s32 sharedExtSaveDataIdNum; + m_Result = nn::fs::EnumerateSharedExtSaveData(&sharedExtSaveDataIdNum, s_SharedExtSaveDataIdList, + MAX_SHARED_EXT_SAVE_DATA_ID_NUM); + for(s32 i = 0; i < sharedExtSaveDataIdNum; ++i) + { + bit32 id = s_SharedExtSaveDataIdList[i]; + NN_LOG("Export: %08x\n", id); + + // 1. fs::MountSharedExtSaveDataRawStorage を呼び + // ID に対応するアーカイブをマウントする。 + // 既存の共有拡張セーブデータ領域へのアーカイブをマウントします。 + m_Result = nn::fs::MountSharedExtSaveDataRawStorage(ARC_NAME, id); + COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); + + m_Result = Export(buf, bufSize, id, progress); + COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); + + // 3. アンマウントする + m_Result = nn::fs::Unmount(ARC_NAME); + COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); + } + +} + +nn::Result SaveDataMover::Export(void* buf, size_t bufSize, bit32 id, u64* progress) +{ + const s32 MAX_PATH_LEN = 127; + char destRoot[MAX_PATH_LEN + 1]; + + nn::nstd::TSNPrintf(destRoot, MAX_PATH_LEN, "%s/%08x", SD_SAVEDATA_EXT_ROOT_PATH, id); + NN_LOG("destRoot = %s\n", destRoot);; + + // 出力先ディレクトリを作成 + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(nn::fs::TryCreateDirectory(destRoot)); + + // 2. アーカイブ内を走査して、含まれるファイルと + // ディレクトリを、その構造を保ったまま + // エクスポートする。 + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(CopyRecursivly(buf, bufSize, ARC_NAME, destRoot, progress)); + + return nn::ResultSuccess(); +} + // ファイルの読み書き nn::Result SaveDataMover::CopyFile(nn::fs::FileInputStream& is, nn::fs::FileOutputStream& os, void* pBuffer, const s32 bufferSize, u64* progress) { s64 restSize; - NN_UTIL_RETURN_IF_FAILED(is.TryGetSize(&restSize)); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(is.TryGetSize(&restSize)); while (restSize > 0) { s32 readSize = restSize > bufferSize ? bufferSize : restSize; s32 read = 0; s32 write = 0; - NN_UTIL_RETURN_IF_FAILED(is.TryRead(&read, pBuffer, readSize)); - NN_UTIL_RETURN_IF_FAILED(os.TryWrite(&write, pBuffer, read)); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(is.TryRead(&read, pBuffer, readSize)); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(os.TryWrite(&write, pBuffer, read)); restSize -= read; m_FinishedSize += read; *progress = m_FinishedSize * 100 / m_TotalSize; + NN_LOG("FinishedSize = %lld\n", m_FinishedSize); NN_LOG("progress = %lld\n", *progress); } return nn::ResultSuccess(); } +// ディレクトリ内を再帰的にコピー +// INFO: 本当は再帰を使わないで書く +nn::Result SaveDataMover::CopyRecursivly(void* buf, size_t bufSize, const char* src, const char* dest, u64* progress) +{ + char srcPath[128]; + char destPath[128]; + char entryName[128]; + + nn::nstd::TSNPrintf(srcPath, sizeof(srcPath), "%s/", src); + nn::fs::Directory srcDir; + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(srcDir.TryInitialize(srcPath)); + + while (1) + { + nn::fs::DirectoryEntry entry; + s32 numRead; + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(srcDir.TryRead(&numRead, &entry, 1)); + if (numRead == 0) + { + break; + } + + std::wcstombs(entryName, entry.entryName, sizeof(entryName) - 1); + entryName[sizeof(entryName) - 1] = '\0'; + nn::nstd::TSNPrintf(srcPath, sizeof(srcPath), "%s/%s", src, entryName); + nn::nstd::TSNPrintf(destPath, sizeof(destPath), "%s/%s", dest, entryName); + + if (entry.attributes.isDirectory) + { + nn::Result result = nn::fs::TryCreateDirectory(destPath); + if (result.IsFailure()) + { + if (result.GetDescription() == nn::fs::DESCRIPTION_FAT_ALREADY_EXISTS + && result.GetModule() == nn::Result::MODULE_NN_FS) + { + } + else + { + return result; + } + } + m_Result = CopyRecursivly(buf, bufSize, srcPath, destPath, progress); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(m_Result); + } + else + { + nn::fs::FileInputStream input; + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(input.TryInitialize(srcPath)); + + nn::fs::FileOutputStream output; + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(output.TryInitialize(destPath, true)); + + CopyFile(input, output, buf, bufSize, progress); + } + } + return nn::ResultSuccess(); +} + } /* namespace common */ diff --git a/trunk/ConsoleDataMigration/sources/common/SaveDataMover.h b/trunk/ConsoleDataMigration/sources/common/SaveDataMover.h index cc66b21..20e4b69 100644 --- a/trunk/ConsoleDataMigration/sources/common/SaveDataMover.h +++ b/trunk/ConsoleDataMigration/sources/common/SaveDataMover.h @@ -43,16 +43,27 @@ private: //! @brief 出力するファイルサイズを計算します void CalculateFileSize(); + void CalculateSystemSaveDataSize(); + void CalculateSharedExtSaveDataSize(); + //! @brief システムセーブデータを出力します void ExportSystemSaveData(void* buf, size_t bufSize, u64* progress); + //! @brief 共有拡張セーブデータを出力します + void ExportSharedExtSaveData(void* buf, size_t bufSize, u64* progress); + + //! @breif 共有拡張セーブデータを出力します + nn::Result Export(void* buf, size_t bufSize, bit32 id, u64* progress); + nn::Result CopyFile(nn::fs::FileInputStream& is, nn::fs::FileOutputStream& os, void* pBuffer, const s32 bufferSize, u64* progress); + nn::Result CopyRecursivly(void* buf, size_t bufSize, const char* src, const char* dest, u64* progress); + NN_PADDING4; - u64 m_Progress; - u64 m_FinishedSize; - u64 m_TotalSize; + s64 m_Progress; + s64 m_FinishedSize; + s64 m_TotalSize; nn::Result m_Result; };