//共通関数 #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 SDMC //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; } //パス名チェック for 拡張セーブ bool CheckPathEx(wchar_t *s) { size_t n = wcslen(s); if ((n > 248) || (n==0))return false; return true; } //ディレクトリ一致チェック //ret= 0:なし、他:最初に一致した階層 //ex) s = "/d1/d2/d3",s2 ="d2" or "/d2" ret=2 // "/"で囲まれた文字列をディレクトリと見なす int CmpDirW(wchar_t *s,wchar_t *s2) { int i=0,j,n = wcslen(s),n2 = wcslen(s2); int lv=1; wchar_t *ss; if (s2[0]==L'/') { ss = &s2[1]; n2--; }else ss = s2; while(i=n)return 0; if ((j-i-1) == n2) {//文字長一致したら比較 if(memcmp((void*)&s[i+1],(void*)ss,n2)==0)return lv; } lv++; i=j;//次 }else i++; } return 0; } //ファイル名の一致確認 //s:パス ex)"/dir/name" //s2:ファイル名 ex) "/name" bool CmpNameW(wchar_t *s,wchar_t *s2) { int n,n2,i; n = wcslen(s); n2 = wcslen(s2); i = GetPosDelmLast(s,1);//"/"の位置 if (n2 != n-i)return false;//文字数一致? return memcmp((void*)&s[i],(void*)s2,n2*2)==0; } bool CmpPathW(wchar_t *s,wchar_t *s2) { int n,n2; n = wcslen(s); n2 = wcslen(s2); if (n2 != n)return false;//文字数一致? return memcmp((void*)s,(void*)s2,n2*2)==0; } //-------------- 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::MakeDir(wchar_t *path,bool *mkdir) { int pos,pos2; *mkdir = false; LastNnResult = nn::fs::TryCreateDirectory(path); if(LastNnResult.IsSuccess())return true; if(nn::fs::ResultAlreadyExists::Includes(LastNnResult))return true; //ディレクトリがなければディレクトリを作成 pos = GetPosDelmLast(path,RootLength);//ファイルが存在するディレクトリ if (pos <= 0)return false;//rootかパスが不正 wcscpy(pathw_w2,path);//ワークにコピー 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(); } bool SaveFileWrite::DeleteFile(const wchar_t *path) { LastNnResult = nn::fs::TryDeleteFile(path); 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(); } //シーク bool SaveFileRead::SetPos(s64 pos) { LastNnResult = reader.TrySetPosition(pos); return LastNnResult.IsSuccess(); } //ファイルリード s32 SaveFileRead::Read(char *buffer,size_t size) { s32 ct; LastNnResult = reader.TryRead(&ct,(void*)buffer,size); if(LastNnResult.IsFailure())ct=0; return ct; } //存在チェック bool SaveFileRead::IsExist(){ myResult res; res = Mount(); Unmount(); return (res != RESULT_FAIL_MOUNT); } void SaveFileRead::ResetPath() { s_lv=0; s_serch = false; wcscpy(path_w,root_w); wcscat(path_w,L"/"); for (int n = 0;nMAX_PATH_LENGTH - 1)return RESULT_PATH_LENGTH_OVER; wcscat(path,dcEntryl.entryName); return RESULT_OK; } } } } //アーカイブ情報の取得 //clsz:SDの場合クラスタサイズ指定で現実に近いサイズに調整 bool SaveFileRead::GetInfo(tArcInfo *pinfo,tDcList *pDcList,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"/"); CheckPathBit = 0; pDcList->num = 0; int n; int lv = 0; for (n = 0;n0)m_info.total +=clsz;//SD..ディレクトリでクラスタ分取る wcscpy(pathu_w[lv],pathw_w);//パス保存 wcscat(pathw_w,dcEntryl.entryName);//次のディレクトリパス if ( m_info.DirCount < MAX_DCLIST) wcscpy(pDcList->name[m_info.DirCount],pathw_w);//リストに格納 m_info.DirCount++; 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; } wcscpy(pathw_w2,pathw_w); wcscat(pathw_w2,dcEntryl.entryName); if(CheckPathEx(pathw_w2)==false)CheckPathBit |= cpb_ex; if(CheckPath(pathw_w2)==false)CheckPathBit |= cpb_sdmc; } } } dcl.Finalize(); } for (n = 0;nnum = m_info.DirCount; *pinfo = m_info; return true; }