/*---------------------------------------------------------------------------* Project: Horizon File: FileTransfer.cpp Copyright 2009 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Rev$ *---------------------------------------------------------------------------*/ #include "FileTransfer.h" #include namespace common { namespace { u64 s_TotalFileSize; u64 s_FinishedFileSize = 0; u64 s_Progress = 0; } nn::Result CalculateFileNum(std::wstring currentDirectory, u32& fileNum, u32& fileSize) { nn::fs::FileInputStream fis; nn::fs::Directory dir; nn::Result result; std::vector entryList; //カレントディレクトリのエントリ一覧を格納 std::vector::iterator entryIndex; result = dir.TryInitialize(currentDirectory.c_str()); if(result.IsSuccess()) { nn::fs::DirectoryEntry entry; s32 numEntry; for(;;) { result = dir.TryRead(&numEntry, &entry, 1); if(result.IsFailure()) { dir.Finalize(); return result; } if(numEntry == 0) { // カレントディレクトリを閉じる dir.Finalize(); // カレントディレクトリの子を開く for(entryIndex = entryList.begin(); entryIndex != entryList.end(); entryIndex++) { if(entryIndex->attributes.isDirectory) { CalculateFileNum(currentDirectory + std::wstring(entryIndex->entryName) + std::wstring(L"/"), fileNum, fileSize); } } return nn::ResultSuccess(); } entryList.push_back(entry); fileNum++; fileSize+= entry.entrySize; } } else { NN_LOG("failed initialize directory\n"); dir.Finalize(); return result; } } // ディレクトリ間のコピー // アーカイブ越しのコピーが可能 // アーカイブにマウントした状態で呼び出す必要あり // 書き込み先のディレクトリはあらかじめ消去しておくこと。 // 引数はスラッシュ付き bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf, const size_t bufSize) { nn::fs::Directory from_dir; nn::fs::DirectoryEntry entry; s32 numread = 0; std::wostringstream target_from; std::wostringstream target_to; bool ret_value = true; nn::Result result = from_dir.TryInitialize(from_path); if (result.IsFailure()) { nn::dbg::PrintResult(result); return false; } while (1) { result = from_dir.TryRead(&numread, &entry, 1); if (result.IsFailure() || numread != 1) { break; } if (std::wcscmp(entry.entryName, L".") == 0 || std::wcscmp(entry.entryName, L"..") == 0) { continue; } target_from.str(L""); target_from.clear(std::stringstream::goodbit); target_from << from_path << entry.entryName; target_to.str(L""); target_to.clear(std::stringstream::goodbit); target_to << to_path << entry.entryName; // ディレクトリの場合 if (entry.attributes.isDirectory) { // ディレクトリ作成 NN_LOG("Create Directory %ls\n", target_to.str().c_str()); result = nn::fs::TryCreateDirectory(target_to.str().c_str()); if (result.IsFailure()) { nn::dbg::PrintResult(result); ret_value = false; } else { target_from << L"/"; target_to << L"/"; // 再帰処理 if (!CopyDirectory(target_from.str().c_str(), target_to.str().c_str(), buf, bufSize)) { ret_value = false; } } } // ファイルの場合 else { // ファイル作成 nn::fs::FileInputStream from_file; nn::fs::FileOutputStream to_file; s64 filesize; s32 readsize; s32 writesize; NN_LOG("Copy File %ls\n", target_from.str().c_str()); // 読み込み対象ファイル開く result = from_file.TryInitialize(target_from.str().c_str()); if (result.IsFailure()) { nn::dbg::PrintResult(result); ret_value = false; } else { // 読み込み対象ファイルのサイズ取得 result = from_file.TryGetSize(&filesize); if (result.IsFailure()) { nn::dbg::PrintResult(result); ret_value = false; } else { // 書き込み対象ファイル作成 result = nn::fs::TryCreateFile(target_to.str().c_str(), filesize); result = to_file.TryInitialize(target_to.str().c_str(), false); if (result.IsFailure()) { nn::dbg::PrintResult(result); ret_value = false; } else { while (1) { result = from_file.TryRead(&readsize, buf, bufSize); if (result.IsFailure()) { nn::dbg::PrintResult(result); ret_value = false; break; } else { if (readsize == 0) { result = to_file.TryFlush(); if (result.IsFailure()) { nn::dbg::PrintResult(result); ret_value = false; } break; } else { result = to_file.TryWrite(&writesize, buf, readsize, false); s_FinishedFileSize += readsize; s_Progress = s_FinishedFileSize * 100/ s_TotalFileSize; NN_LOG("finish = %lld, total = %lld, progress = %lld\n", s_FinishedFileSize, s_TotalFileSize, s_Progress); if (result.IsFailure()) { nn::dbg::PrintResult(result); ret_value = false; } } } } } to_file.Finalize(); } } from_file.Finalize(); } } from_dir.Finalize(); return ret_value; } u32 GetProgress() { return s_Progress; } void InitializeTransferProgress(u64 totalSize) { s_TotalFileSize = totalSize; s_FinishedFileSize = 0; } }