mirror of
https://github.com/rvtr/ctr_Repair.git
synced 2025-10-31 13:51:08 -04:00
302 lines
8.4 KiB
C++
302 lines
8.4 KiB
C++
//共通関数
|
||
|
||
#include "savefile.h"
|
||
|
||
//終端から前方検索で見つかった境界("/"=0x2f)位置を返す
|
||
//top :検索範囲の先頭指定
|
||
int GetPosDelmLast(wchar_t *s,int top)
|
||
{
|
||
size_t i = wcslen(s);
|
||
if (i <= top)return 0;
|
||
i--;
|
||
while(i > top-1){
|
||
if (s[i]==L'/')return i;
|
||
i--;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
//パス結合
|
||
void ChainPath(wchar_t *p1,wchar_t *p2)
|
||
{
|
||
int n=wcslen(p1);
|
||
if ((p1[n-1] == L'/') && (p2[0] == L'/')) p1[n-1] = 0;
|
||
if ((p1[wcslen(p1)-1] != L'/') && (p2[0] != L'/')) wcscat(p1,L"/");
|
||
wcscat(p1,p2);
|
||
}
|
||
|
||
|
||
//パス名チェック for SD
|
||
//fs関数で引数エラー(INVALID_ARGUMENT)にならないものをチェック
|
||
bool CheckPath(wchar_t *s)
|
||
{
|
||
int i;
|
||
size_t n = wcslen(s);
|
||
|
||
if ((n > 253) || (n==0))return false;
|
||
if (n>251)
|
||
{//ディレクトリオープン時は251まで
|
||
if ((s[251]==L'/') || (s[252]==L'/'))return false;
|
||
}
|
||
|
||
for (i =0;i< n-1;i++)
|
||
{
|
||
if ((s[i-1] == ' ')||(s[i+1] == ' '))return false;//厳密にはスラッシュ前後と最後尾
|
||
if ((s[i-1] == 0x5c) ||(s[i+1] == 0x5c))return false;//0x5c = 円マーク
|
||
}
|
||
return true;
|
||
|
||
}
|
||
|
||
//-------------- Class SaveFileWrite
|
||
//ディレクトリ作成ありのオープン
|
||
bool SaveFileWrite::OpenC(wchar_t *path,s64 size,bool *mkdir)
|
||
{
|
||
int pos,pos2;
|
||
|
||
wcscpy(pathw_w,root_w);
|
||
ChainPath(pathw_w,path);
|
||
|
||
*mkdir = false;
|
||
LastNnResult = nn::fs::TryCreateFile(pathw_w,size);
|
||
if(LastNnResult.IsSuccess())
|
||
{
|
||
LastNnResult = writer.TryInitialize(pathw_w,false);
|
||
return LastNnResult.IsSuccess();
|
||
}
|
||
//ディレクトリがなければディレクトリを作成
|
||
pos = GetPosDelmLast(pathw_w,RootLength);//ファイルが存在するディレクトリ
|
||
if (pos <= 0)return false;//rootかパスが不正
|
||
wcscpy(pathw_w2,pathw_w);//ワークにコピー
|
||
while (LastNnResult.IsFailure()){//ディレクトリ作成できるまで遡る
|
||
if(nn::fs::ResultNotFound::Includes(LastNnResult)==false)return false;
|
||
pos2 = GetPosDelmLast(pathw_w2,RootLength);//境界位置を探す
|
||
if (pos2 == 0)return false;//root到達
|
||
pathw_w2[pos2] = 0;//境界まで削除 (例) dir1/dir2/file -> dir1/dir2 -> dir1
|
||
LastNnResult = nn::fs::TryCreateDirectory(pathw_w2);
|
||
}
|
||
|
||
//作成ディレクトリ多いと画面止まるので、作成ごとに抜ける
|
||
*mkdir = true; // 帰値:false で mkdir=true ならディレクトリ作成のみ
|
||
return false;
|
||
}
|
||
|
||
//ディレクトリ作成なしオープン、存在する場合は追記
|
||
bool SaveFileWrite::OpenAdd(wchar_t *path)
|
||
{
|
||
wcscpy(pathw_w,root_w);
|
||
ChainPath(pathw_w,path);
|
||
LastNnResult = writer.TryInitialize(pathw_w,false);
|
||
if (LastNnResult.IsSuccess()){
|
||
LastNnResult = writer.TrySeek(0,nn::fs::POSITION_BASE_END);//追記
|
||
}else LastNnResult = writer.TryInitialize(pathw_w,true);//新規
|
||
if (LastNnResult.IsFailure())
|
||
{
|
||
writer.Finalize();
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
|
||
//ディレクトリ作成なしオープン
|
||
bool SaveFileWrite::OpenW(const wchar_t *path)
|
||
{
|
||
wcscpy(pathw_w,root_w);
|
||
ChainPath(pathw_w,(wchar_t*)path);
|
||
LastNnResult = writer.TryInitialize(pathw_w,true);
|
||
return LastNnResult.IsSuccess();
|
||
}
|
||
|
||
|
||
|
||
//クローズ
|
||
void SaveFileWrite::CloseW()
|
||
{
|
||
writer.Finalize();
|
||
}
|
||
|
||
s32 SaveFileWrite::Write(char *buffer,size_t size)
|
||
{
|
||
s32 ct;
|
||
LastNnResult = writer.TryWrite(&ct,(void*)buffer,size);
|
||
if(LastNnResult.IsFailure()){NN_LOG("write fail\n");ct=0;}
|
||
return ct;
|
||
}
|
||
|
||
|
||
//ディレクトリ作成
|
||
bool SaveFileWrite::CreateDir(const wchar_t *dir)
|
||
{
|
||
LastNnResult = nn::fs::TryCreateDirectory(dir);
|
||
if(LastNnResult.IsSuccess())return true;
|
||
return nn::fs::ResultAlreadyExists::Includes(LastNnResult);
|
||
}
|
||
|
||
//削除
|
||
bool SaveFileWrite::DeleteDir(const wchar_t *dir)
|
||
{
|
||
LastNnResult = nn::fs::TryDeleteDirectoryRecursively(dir);
|
||
return LastNnResult.IsSuccess();
|
||
}
|
||
|
||
|
||
//------------------------------------------------------ Class SaveFileRead
|
||
bool SaveFileRead::Open(const wchar_t *path)
|
||
{
|
||
wcscpy(pathw_w,root_w);
|
||
ChainPath(pathw_w,(wchar_t*)path);
|
||
LastNnResult = reader.TryInitialize(pathw_w);
|
||
if (LastNnResult.IsSuccess())
|
||
{
|
||
LastNnResult = reader.TryGetSize(&FileSize);
|
||
if (LastNnResult.IsSuccess())return true;
|
||
else Close();
|
||
}
|
||
return false;
|
||
|
||
}
|
||
|
||
void SaveFileRead::Close()
|
||
{
|
||
reader.Finalize();
|
||
}
|
||
|
||
|
||
//ファイルリード
|
||
s32 SaveFileRead::Read(char *buffer,size_t size)
|
||
{
|
||
s32 ct;
|
||
LastNnResult = reader.TryRead(&ct,(void*)buffer,size);
|
||
if(LastNnResult.IsFailure())ct=0;
|
||
return ct;
|
||
}
|
||
|
||
//存在チェック
|
||
myResult SaveFileRead::IsExist(){
|
||
myResult res;
|
||
res = Mount();
|
||
Unmount();
|
||
return res;
|
||
}
|
||
|
||
|
||
void SaveFileRead::ResetPath()
|
||
{
|
||
s_lv=0;
|
||
s_serch = false;
|
||
wcscpy(path_w,root_w);
|
||
wcscat(path_w,L"/");
|
||
for (int n = 0;n<MAX_LEVEL;n++)dc_readed[n] = 0;
|
||
}
|
||
|
||
myResult SaveFileRead::GetPath(wchar_t *path)
|
||
{
|
||
static nn::fs::DirectoryEntry dcEntryl;
|
||
static nn::fs::Directory dcl;
|
||
|
||
int n,ct;
|
||
while(1){
|
||
LastNnResult = dcl.TryInitialize(path_w);//Open
|
||
if (LastNnResult.IsFailure())return RESULT_FAIL;
|
||
if (dc_readed[s_lv] != 0)for(n=0;n<dc_readed[s_lv];n++)dcl.Read(&dcEntryl,1);
|
||
n = (dcl.Read(&dcEntryl,1));
|
||
dc_readed[s_lv]++;
|
||
dcl.Finalize();
|
||
if ( n==0 )//終端
|
||
{
|
||
if (s_lv == 0){path[0]=0;return RESULT_OK;}// ---- rootなら終了
|
||
dc_readed[s_lv]=0;
|
||
s_lv--;//上の層に戻る
|
||
wcscpy(path_w,pathu_w[s_lv]);//パス戻す
|
||
}else{
|
||
if(dcEntryl.attributes.isDirectory){//ディレクトリ
|
||
wcscpy(pathu_w[s_lv],path_w);//パス保存
|
||
wcscat(path_w,dcEntryl.entryName);//次のディレクトリパス
|
||
wcscat(path_w,L"/");
|
||
if (++s_lv == MAX_LEVEL)return RESULT_DIR_LEVEL_OVER;
|
||
}else{//ファイル
|
||
wcscpy(path,pPathTop);
|
||
ct =wcslen(path) + wcslen(dcEntryl.entryName);
|
||
if (ct>MAX_PATH_LENGTH - 1)return RESULT_PATH_LENGTH_OVER;
|
||
wcscat(path,dcEntryl.entryName);
|
||
return RESULT_OK;
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
//アーカイブ情報の取得
|
||
bool SaveFileRead::GetInfo(tArcInfo *pinfo,size_t clsz)
|
||
{
|
||
static nn::fs::DirectoryEntry dcEntryl;
|
||
static nn::fs::Directory dcl;
|
||
|
||
if(IsMounted==false){NN_LOG("GetInfo: Not Mounted\n");return false;};
|
||
|
||
s_lv=0;
|
||
m_info.DirCount = 0;
|
||
m_info.FileCount = 0;
|
||
m_info.DirEntry = 0;
|
||
m_info.FileEntry = 0;
|
||
m_info.total = 0;
|
||
m_info.Dup = false;
|
||
wcscpy(pathw_w,root_w);
|
||
wcscat(pathw_w,L"/");
|
||
|
||
int n;
|
||
int lv = 0;
|
||
for (n = 0;n<MAX_LEVEL;n++)dc_readed[n] = 0;
|
||
bool cont = true;
|
||
size_t sn;
|
||
while(cont){
|
||
LastNnResult = dcl.TryInitialize(pathw_w);//Open
|
||
if (LastNnResult.IsFailure())return false;
|
||
if (dc_readed[lv] != 0)for(n=0;n<dc_readed[lv];n++)dcl.Read(&dcEntryl,1);
|
||
while(1){
|
||
n = (dcl.Read(&dcEntryl,1));
|
||
dc_readed[lv]++;
|
||
if ( n==0 )//終端
|
||
{
|
||
if (lv == 0){cont=false;break;}// ---- 終了
|
||
dc_readed[lv]=0;
|
||
lv--;//上の層に戻る
|
||
wcscpy(pathw_w,pathu_w[lv]);//パス戻す
|
||
break;
|
||
}else{
|
||
if(dcEntryl.attributes.isDirectory){//ディレクトリ
|
||
m_info.DirCount++;
|
||
if (clsz>0)m_info.total +=clsz;//SD..ディレクトリでクラスタ分取る
|
||
wcscpy(pathu_w[lv],pathw_w);//パス保存
|
||
wcscat(pathw_w,dcEntryl.entryName);//次のディレクトリパス
|
||
wcscat(pathw_w,L"/");
|
||
if (++lv == MAX_LEVEL)return false;
|
||
break;
|
||
}else{//ファイル
|
||
m_info.FileCount++;
|
||
if (clsz==0){
|
||
m_info.total += dcEntryl.entrySize;
|
||
}else{//クラスタサイズで調整 .. SD占有容量
|
||
sn = dcEntryl.entrySize / clsz;
|
||
if ((dcEntryl.entrySize % clsz) > 0 )sn++;
|
||
m_info.total += sn*clsz;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
dcl.Finalize();
|
||
}
|
||
for (n = 0;n<MAX_LEVEL;n++)dc_readed[n] = 0;
|
||
|
||
Unmount();//GetCtrCardSaveDataFormatInfo内でマウントするので一旦アンマウント(SDK2.1~3のみエラー?)
|
||
GetFormatInfoCore(&m_info);
|
||
Mount();
|
||
|
||
*pinfo = m_info;
|
||
return true;
|
||
|
||
}
|
||
|