| File: | /home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp |
| Location: | line 311, column 8 |
| Description: | Value stored to 'OwnerID' during its initialization is never read |
| 1 | // Copyright 2013 Dolphin Emulator Project |
| 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. |
| 4 | |
| 5 | #include "Common.h" |
| 6 | #include "CommonPaths.h" |
| 7 | |
| 8 | #include "WII_IPC_HLE_Device_fs.h" |
| 9 | #include "WII_IPC_HLE_Device_FileIO.h" |
| 10 | |
| 11 | #include "StringUtil.h" |
| 12 | #include "FileSearch.h" |
| 13 | #include "FileUtil.h" |
| 14 | #include "NandPaths.h" |
| 15 | #include "ChunkFile.h" |
| 16 | #include "../HW/SystemTimers.h" |
| 17 | |
| 18 | #include "../VolumeHandler.h" |
| 19 | |
| 20 | #define MAX_NAME(12) (12) |
| 21 | |
| 22 | static Common::replace_v replacements; |
| 23 | |
| 24 | |
| 25 | CWII_IPC_HLE_Device_fs::CWII_IPC_HLE_Device_fs(u32 _DeviceID, const std::string& _rDeviceName) |
| 26 | : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) |
| 27 | { |
| 28 | Common::ReadReplacements(replacements); |
| 29 | } |
| 30 | |
| 31 | CWII_IPC_HLE_Device_fs::~CWII_IPC_HLE_Device_fs() |
| 32 | {} |
| 33 | |
| 34 | bool CWII_IPC_HLE_Device_fs::Open(u32 _CommandAddress, u32 _Mode) |
| 35 | { |
| 36 | // clear tmp folder |
| 37 | { |
| 38 | std::string Path = File::GetUserPath(D_WIIUSER_IDX) + "tmp"; |
| 39 | File::DeleteDirRecursively(Path); |
| 40 | File::CreateDir(Path.c_str()); |
| 41 | } |
| 42 | |
| 43 | Memory::Write_U32(GetDeviceID(), _CommandAddress+4); |
| 44 | m_Active = true; |
| 45 | return true; |
| 46 | } |
| 47 | |
| 48 | bool CWII_IPC_HLE_Device_fs::Close(u32 _CommandAddress, bool _bForce) |
| 49 | { |
| 50 | INFO_LOG(WII_IPC_FILEIO, "Close")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 50, "Close"); } } while (0); |
| 51 | if (!_bForce) |
| 52 | Memory::Write_U32(0, _CommandAddress + 4); |
| 53 | m_Active = false; |
| 54 | return true; |
| 55 | } |
| 56 | |
| 57 | // Get total filesize of contents of a directory (recursive) |
| 58 | // Only used for ES_GetUsage atm, could be useful elsewhere? |
| 59 | static u64 ComputeTotalFileSize(const File::FSTEntry& parentEntry) |
| 60 | { |
| 61 | u64 sizeOfFiles = 0; |
| 62 | const std::vector<File::FSTEntry>& children = parentEntry.children; |
| 63 | for (std::vector<File::FSTEntry>::const_iterator it = children.begin(); it != children.end(); ++it) |
| 64 | { |
| 65 | const File::FSTEntry& entry = *it; |
| 66 | if (entry.isDirectory) |
| 67 | sizeOfFiles += ComputeTotalFileSize(entry); |
| 68 | else |
| 69 | sizeOfFiles += entry.size; |
| 70 | } |
| 71 | return sizeOfFiles; |
| 72 | } |
| 73 | |
| 74 | bool CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress) |
| 75 | { |
| 76 | u32 ReturnValue = FS_RESULT_OK; |
| 77 | SIOCtlVBuffer CommandBuffer(_CommandAddress); |
| 78 | |
| 79 | // Prepare the out buffer(s) with zeros as a safety precaution |
| 80 | // to avoid returning bad values |
| 81 | for(u32 i = 0; i < CommandBuffer.NumberPayloadBuffer; i++) |
| 82 | { |
| 83 | Memory::Memset(CommandBuffer.PayloadBuffer[i].m_Address, 0, |
| 84 | CommandBuffer.PayloadBuffer[i].m_Size); |
| 85 | } |
| 86 | |
| 87 | switch(CommandBuffer.Parameter) |
| 88 | { |
| 89 | case IOCTLV_READ_DIR: |
| 90 | { |
| 91 | // the wii uses this function to define the type (dir or file) |
| 92 | std::string DirName(HLE_IPC_BuildFilename((const char*)Memory::GetPointer( |
| 93 | CommandBuffer.InBuffer[0].m_Address), CommandBuffer.InBuffer[0].m_Size)); |
| 94 | |
| 95 | INFO_LOG(WII_IPC_FILEIO, "FS: IOCTL_READ_DIR %s", DirName.c_str())do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 95, "FS: IOCTL_READ_DIR %s", DirName.c_str()); } } while (0 ); |
| 96 | |
| 97 | if (!File::Exists(DirName)) |
| 98 | { |
| 99 | WARN_LOG(WII_IPC_FILEIO, "FS: Search not found: %s", DirName.c_str())do { { if (LogTypes::LWARNING <= 3) GenericLog(LogTypes::LWARNING , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 99, "FS: Search not found: %s", DirName.c_str()); } } while (0); |
| 100 | ReturnValue = FS_FILE_NOT_EXIST; |
| 101 | break; |
| 102 | } |
| 103 | else if (!File::IsDirectory(DirName)) |
| 104 | { |
| 105 | // It's not a directory, so error. |
| 106 | // Games don't usually seem to care WHICH error they get, as long as it's < |
| 107 | // Well the system menu CARES! |
| 108 | WARN_LOG(WII_IPC_FILEIO, "\tNot a directory - return FS_RESULT_FATAL")do { { if (LogTypes::LWARNING <= 3) GenericLog(LogTypes::LWARNING , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 108, "\tNot a directory - return FS_RESULT_FATAL"); } } while (0); |
| 109 | ReturnValue = FS_RESULT_FATAL; |
| 110 | break; |
| 111 | } |
| 112 | |
| 113 | // make a file search |
| 114 | CFileSearch::XStringVector Directories; |
| 115 | Directories.push_back(DirName); |
| 116 | |
| 117 | CFileSearch::XStringVector Extensions; |
| 118 | Extensions.push_back("*.*"); |
| 119 | |
| 120 | CFileSearch FileSearch(Extensions, Directories); |
| 121 | |
| 122 | // it is one |
| 123 | if ((CommandBuffer.InBuffer.size() == 1) && (CommandBuffer.PayloadBuffer.size() == 1)) |
| 124 | { |
| 125 | size_t numFile = FileSearch.GetFileNames().size(); |
| 126 | INFO_LOG(WII_IPC_FILEIO, "\t%lu files found", (unsigned long)numFile)do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 126, "\t%lu files found", (unsigned long)numFile); } } while (0); |
| 127 | |
| 128 | Memory::Write_U32((u32)numFile, CommandBuffer.PayloadBuffer[0].m_Address); |
| 129 | } |
| 130 | else |
| 131 | { |
| 132 | u32 MaxEntries = Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address); |
| 133 | |
| 134 | memset(Memory::GetPointer(CommandBuffer.PayloadBuffer[0].m_Address), 0, CommandBuffer.PayloadBuffer[0].m_Size); |
| 135 | |
| 136 | size_t numFiles = 0; |
| 137 | char* pFilename = (char*)Memory::GetPointer((u32)(CommandBuffer.PayloadBuffer[0].m_Address)); |
| 138 | |
| 139 | for (size_t i=0; i<FileSearch.GetFileNames().size(); i++) |
| 140 | { |
| 141 | if (i >= MaxEntries) |
| 142 | break; |
| 143 | |
| 144 | std::string name, ext; |
| 145 | SplitPath(FileSearch.GetFileNames()[i], NULL__null, &name, &ext); |
| 146 | std::string FileName = name + ext; |
| 147 | |
| 148 | // Decode entities of invalid file system characters so that |
| 149 | // games (such as HP:HBP) will be able to find what they expect. |
| 150 | for (Common::replace_v::const_iterator it = replacements.begin(); it != replacements.end(); ++it) |
| 151 | { |
| 152 | for (size_t j = 0; (j = FileName.find(it->second, j)) != FileName.npos; ++j) |
| 153 | FileName.replace(j, it->second.length(), 1, it->first); |
| 154 | } |
| 155 | |
| 156 | strcpy(pFilename, FileName.c_str()); |
| 157 | pFilename += FileName.length(); |
| 158 | *pFilename++ = 0x00; // termination |
| 159 | numFiles++; |
| 160 | |
| 161 | INFO_LOG(WII_IPC_FILEIO, "\tFound: %s", FileName.c_str())do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 161, "\tFound: %s", FileName.c_str()); } } while (0); |
| 162 | } |
| 163 | |
| 164 | Memory::Write_U32((u32)numFiles, CommandBuffer.PayloadBuffer[1].m_Address); |
| 165 | } |
| 166 | |
| 167 | ReturnValue = FS_RESULT_OK; |
| 168 | } |
| 169 | break; |
| 170 | |
| 171 | case IOCTLV_GETUSAGE: |
| 172 | { |
| 173 | _dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer.size() == 2){}; |
| 174 | _dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer[0].m_Size == 4){}; |
| 175 | _dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer[1].m_Size == 4){}; |
| 176 | |
| 177 | // this command sucks because it asks of the number of used |
| 178 | // fsBlocks and inodes |
| 179 | // It should be correct, but don't count on it... |
| 180 | const char *relativepath = (const char*)Memory::GetPointer(CommandBuffer.InBuffer[0].m_Address); |
| 181 | std::string path(HLE_IPC_BuildFilename(relativepath, CommandBuffer.InBuffer[0].m_Size)); |
| 182 | u32 fsBlocks = 0; |
| 183 | u32 iNodes = 0; |
| 184 | |
| 185 | INFO_LOG(WII_IPC_FILEIO, "IOCTL_GETUSAGE %s", path.c_str())do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 185, "IOCTL_GETUSAGE %s", path.c_str()); } } while (0); |
| 186 | if (File::IsDirectory(path)) |
| 187 | { |
| 188 | // LPFaint99: After I found that setting the number of inodes to the number of children + 1 for the directory itself |
| 189 | // I decided to compare with sneek which has the following 2 special cases which are |
| 190 | // Copyright (C) 2009-2011 crediar http://code.google.com/p/sneek/ |
| 191 | if ((memcmp(relativepath, "/title/00010001", 16 ) == 0 ) || |
| 192 | (memcmp(relativepath, "/title/00010005", 16) == 0 )) |
| 193 | { |
| 194 | fsBlocks = 23; // size is size/0x4000 |
| 195 | iNodes = 42; // empty folders return a FileCount of 1 |
| 196 | } |
| 197 | else |
| 198 | { |
| 199 | File::FSTEntry parentDir; |
| 200 | // add one for the folder itself, allows some games to create their save files |
| 201 | // R8XE52 (Jurassic: The Hunted), STEETR (Tetris Party Deluxe) now create their saves with this change |
| 202 | iNodes = 1 + File::ScanDirectoryTree(path, parentDir); |
| 203 | |
| 204 | u64 totalSize = ComputeTotalFileSize(parentDir); // "Real" size, to be converted to nand blocks |
| 205 | |
| 206 | fsBlocks = (u32)(totalSize / (16 * 1024)); // one bock is 16kb |
| 207 | } |
| 208 | ReturnValue = FS_RESULT_OK; |
| 209 | |
| 210 | INFO_LOG(WII_IPC_FILEIO, "FS: fsBlock: %i, iNodes: %i", fsBlocks, iNodes)do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 210, "FS: fsBlock: %i, iNodes: %i", fsBlocks, iNodes); } } while (0); |
| 211 | } |
| 212 | else |
| 213 | { |
| 214 | fsBlocks = 0; |
| 215 | iNodes = 0; |
| 216 | ReturnValue = FS_RESULT_OK; |
| 217 | WARN_LOG(WII_IPC_FILEIO, "FS: fsBlock failed, cannot find directory: %s", path.c_str())do { { if (LogTypes::LWARNING <= 3) GenericLog(LogTypes::LWARNING , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 217, "FS: fsBlock failed, cannot find directory: %s", path. c_str()); } } while (0); |
| 218 | } |
| 219 | |
| 220 | Memory::Write_U32(fsBlocks, CommandBuffer.PayloadBuffer[0].m_Address); |
| 221 | Memory::Write_U32(iNodes, CommandBuffer.PayloadBuffer[1].m_Address); |
| 222 | } |
| 223 | break; |
| 224 | |
| 225 | |
| 226 | default: |
| 227 | PanicAlert("CWII_IPC_HLE_Device_fs::IOCtlV: %i", CommandBuffer.Parameter)MsgAlert(false, WARNING, "CWII_IPC_HLE_Device_fs::IOCtlV: %i" , CommandBuffer.Parameter); |
| 228 | break; |
| 229 | } |
| 230 | |
| 231 | Memory::Write_U32(ReturnValue, _CommandAddress+4); |
| 232 | |
| 233 | return true; |
| 234 | } |
| 235 | |
| 236 | bool CWII_IPC_HLE_Device_fs::IOCtl(u32 _CommandAddress) |
| 237 | { |
| 238 | //u32 DeviceID = Memory::Read_U32(_CommandAddress + 8); |
| 239 | //LOG(WII_IPC_FILEIO, "FS: IOCtl (Device=%s, DeviceID=%08x)", GetDeviceName().c_str(), DeviceID); |
| 240 | |
| 241 | u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC); |
| 242 | u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10); |
| 243 | u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14); |
| 244 | u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18); |
| 245 | u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C); |
| 246 | |
| 247 | /* Prepare the out buffer(s) with zeroes as a safety precaution |
| 248 | to avoid returning bad values. */ |
| 249 | //LOG(WII_IPC_FILEIO, "Cleared %u bytes of the out buffer", _BufferOutSize); |
| 250 | Memory::Memset(BufferOut, 0, BufferOutSize); |
| 251 | |
| 252 | u32 ReturnValue = ExecuteCommand(Parameter, BufferIn, BufferInSize, BufferOut, BufferOutSize); |
| 253 | Memory::Write_U32(ReturnValue, _CommandAddress + 4); |
| 254 | |
| 255 | return true; |
| 256 | } |
| 257 | |
| 258 | s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _BufferInSize, u32 _BufferOut, u32 _BufferOutSize) |
| 259 | { |
| 260 | switch(_Parameter) |
| 261 | { |
| 262 | case IOCTL_GET_STATS: |
| 263 | { |
| 264 | if (_BufferOutSize < 0x1c) |
| 265 | return -1017; |
| 266 | |
| 267 | WARN_LOG(WII_IPC_FILEIO, "FS: GET STATS - returning static values for now")do { { if (LogTypes::LWARNING <= 3) GenericLog(LogTypes::LWARNING , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 267, "FS: GET STATS - returning static values for now"); } } while (0); |
| 268 | |
| 269 | NANDStat fs; |
| 270 | |
| 271 | //TODO: scrape the real amounts from somewhere... |
| 272 | fs.BlockSize = 0x4000; |
| 273 | fs.FreeUserBlocks = 0x5DEC; |
| 274 | fs.UsedUserBlocks = 0x1DD4; |
| 275 | fs.FreeSysBlocks = 0x10; |
| 276 | fs.UsedSysBlocks = 0x02F0; |
| 277 | fs.Free_INodes = 0x146B; |
| 278 | fs.Used_Inodes = 0x0394; |
| 279 | |
| 280 | *(NANDStat*)Memory::GetPointer(_BufferOut) = fs; |
| 281 | |
| 282 | return FS_RESULT_OK; |
| 283 | } |
| 284 | break; |
| 285 | |
| 286 | case IOCTL_CREATE_DIR: |
| 287 | { |
| 288 | _dbg_assert_(WII_IPC_FILEIO, _BufferOutSize == 0){}; |
| 289 | u32 Addr = _BufferIn; |
| 290 | |
| 291 | u32 OwnerID = Memory::Read_U32(Addr); Addr += 4; |
| 292 | u16 GroupID = Memory::Read_U16(Addr); Addr += 2; |
| 293 | std::string DirName(HLE_IPC_BuildFilename((const char*)Memory::GetPointer(Addr), 64)); Addr += 64; |
| 294 | Addr += 9; // owner attribs, permission |
| 295 | u8 Attribs = Memory::Read_U8(Addr); |
| 296 | |
| 297 | INFO_LOG(WII_IPC_FILEIO, "FS: CREATE_DIR %s, OwnerID %#x, GroupID %#x, Attributes %#x", DirName.c_str(), OwnerID, GroupID, Attribs)do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 297, "FS: CREATE_DIR %s, OwnerID %#x, GroupID %#x, Attributes %#x" , DirName.c_str(), OwnerID, GroupID, Attribs); } } while (0); |
| 298 | |
| 299 | DirName += DIR_SEP"/"; |
| 300 | File::CreateFullPath(DirName); |
| 301 | _dbg_assert_msg_(WII_IPC_FILEIO, File::IsDirectory(DirName), "FS: CREATE_DIR %s failed", DirName.c_str()){}; |
| 302 | |
| 303 | return FS_RESULT_OK; |
| 304 | } |
| 305 | break; |
| 306 | |
| 307 | case IOCTL_SET_ATTR: |
| 308 | { |
| 309 | u32 Addr = _BufferIn; |
| 310 | |
| 311 | u32 OwnerID = Memory::Read_U32(Addr); Addr += 4; |
Value stored to 'OwnerID' during its initialization is never read | |
| 312 | u16 GroupID = Memory::Read_U16(Addr); Addr += 2; |
| 313 | std::string Filename = HLE_IPC_BuildFilename((const char*)Memory::GetPointer(_BufferIn), 64); Addr += 64; |
| 314 | u8 OwnerPerm = Memory::Read_U8(Addr); Addr += 1; |
| 315 | u8 GroupPerm = Memory::Read_U8(Addr); Addr += 1; |
| 316 | u8 OtherPerm = Memory::Read_U8(Addr); Addr += 1; |
| 317 | u8 Attributes = Memory::Read_U8(Addr); Addr += 1; |
| 318 | |
| 319 | INFO_LOG(WII_IPC_FILEIO, "FS: SetAttrib %s", Filename.c_str())do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 319, "FS: SetAttrib %s", Filename.c_str()); } } while (0); |
| 320 | DEBUG_LOG(WII_IPC_FILEIO, " OwnerID: 0x%08x", OwnerID)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 320, " OwnerID: 0x%08x", OwnerID); } } while (0); |
| 321 | DEBUG_LOG(WII_IPC_FILEIO, " GroupID: 0x%04x", GroupID)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 321, " GroupID: 0x%04x", GroupID); } } while (0); |
| 322 | DEBUG_LOG(WII_IPC_FILEIO, " OwnerPerm: 0x%02x", OwnerPerm)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 322, " OwnerPerm: 0x%02x", OwnerPerm); } } while (0); |
| 323 | DEBUG_LOG(WII_IPC_FILEIO, " GroupPerm: 0x%02x", GroupPerm)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 323, " GroupPerm: 0x%02x", GroupPerm); } } while (0); |
| 324 | DEBUG_LOG(WII_IPC_FILEIO, " OtherPerm: 0x%02x", OtherPerm)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 324, " OtherPerm: 0x%02x", OtherPerm); } } while (0); |
| 325 | DEBUG_LOG(WII_IPC_FILEIO, " Attributes: 0x%02x", Attributes)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 325, " Attributes: 0x%02x", Attributes); } } while (0); |
| 326 | |
| 327 | return FS_RESULT_OK; |
| 328 | } |
| 329 | break; |
| 330 | |
| 331 | case IOCTL_GET_ATTR: |
| 332 | { |
| 333 | _dbg_assert_msg_(WII_IPC_FILEIO, _BufferOutSize == 76,{} |
| 334 | " GET_ATTR needs an 76 bytes large output buffer but it is %i bytes large",{} |
| 335 | _BufferOutSize){}; |
| 336 | |
| 337 | u32 OwnerID = 0; |
| 338 | u16 GroupID = 0x3031; // this is also known as makercd, 01 (0x3031) for nintendo and 08 (0x3038) for MH3 etc |
| 339 | std::string Filename = HLE_IPC_BuildFilename((const char*)Memory::GetPointer(_BufferIn), 64); |
| 340 | u8 OwnerPerm = 0x3; // read/write |
| 341 | u8 GroupPerm = 0x3; // read/write |
| 342 | u8 OtherPerm = 0x3; // read/write |
| 343 | u8 Attributes = 0x00; // no attributes |
| 344 | if (File::IsDirectory(Filename)) |
| 345 | { |
| 346 | INFO_LOG(WII_IPC_FILEIO, "FS: GET_ATTR Directory %s - all permission flags are set", Filename.c_str())do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 346, "FS: GET_ATTR Directory %s - all permission flags are set" , Filename.c_str()); } } while (0); |
| 347 | } |
| 348 | else |
| 349 | { |
| 350 | if (File::Exists(Filename)) |
| 351 | { |
| 352 | INFO_LOG(WII_IPC_FILEIO, "FS: GET_ATTR %s - all permission flags are set", Filename.c_str())do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 352, "FS: GET_ATTR %s - all permission flags are set", Filename .c_str()); } } while (0); |
| 353 | } |
| 354 | else |
| 355 | { |
| 356 | INFO_LOG(WII_IPC_FILEIO, "FS: GET_ATTR unknown %s", Filename.c_str())do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 356, "FS: GET_ATTR unknown %s", Filename.c_str()); } } while (0); |
| 357 | return FS_FILE_NOT_EXIST; |
| 358 | } |
| 359 | } |
| 360 | |
| 361 | // write answer to buffer |
| 362 | if (_BufferOutSize == 76) |
| 363 | { |
| 364 | u32 Addr = _BufferOut; |
| 365 | Memory::Write_U32(OwnerID, Addr); Addr += 4; |
| 366 | Memory::Write_U16(GroupID, Addr); Addr += 2; |
| 367 | memcpy(Memory::GetPointer(Addr), Memory::GetPointer(_BufferIn), 64); Addr += 64; |
| 368 | Memory::Write_U8(OwnerPerm, Addr); Addr += 1; |
| 369 | Memory::Write_U8(GroupPerm, Addr); Addr += 1; |
| 370 | Memory::Write_U8(OtherPerm, Addr); Addr += 1; |
| 371 | Memory::Write_U8(Attributes, Addr); Addr += 1; |
| 372 | } |
| 373 | |
| 374 | return FS_RESULT_OK; |
| 375 | } |
| 376 | break; |
| 377 | |
| 378 | |
| 379 | case IOCTL_DELETE_FILE: |
| 380 | { |
| 381 | _dbg_assert_(WII_IPC_FILEIO, _BufferOutSize == 0){}; |
| 382 | int Offset = 0; |
| 383 | |
| 384 | std::string Filename = HLE_IPC_BuildFilename((const char*)Memory::GetPointer(_BufferIn+Offset), 64); |
| 385 | Offset += 64; |
| 386 | if (File::Delete(Filename)) |
| 387 | { |
| 388 | INFO_LOG(WII_IPC_FILEIO, "FS: DeleteFile %s", Filename.c_str())do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 388, "FS: DeleteFile %s", Filename.c_str()); } } while (0); |
| 389 | } |
| 390 | else if (File::DeleteDir(Filename)) |
| 391 | { |
| 392 | INFO_LOG(WII_IPC_FILEIO, "FS: DeleteDir %s", Filename.c_str())do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 392, "FS: DeleteDir %s", Filename.c_str()); } } while (0); |
| 393 | } |
| 394 | else |
| 395 | { |
| 396 | WARN_LOG(WII_IPC_FILEIO, "FS: DeleteFile %s - failed!!!", Filename.c_str())do { { if (LogTypes::LWARNING <= 3) GenericLog(LogTypes::LWARNING , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 396, "FS: DeleteFile %s - failed!!!", Filename.c_str()); } } while (0); |
| 397 | } |
| 398 | |
| 399 | return FS_RESULT_OK; |
| 400 | } |
| 401 | break; |
| 402 | |
| 403 | case IOCTL_RENAME_FILE: |
| 404 | { |
| 405 | _dbg_assert_(WII_IPC_FILEIO, _BufferOutSize == 0){}; |
| 406 | int Offset = 0; |
| 407 | |
| 408 | std::string Filename = HLE_IPC_BuildFilename((const char*)Memory::GetPointer(_BufferIn+Offset), 64); |
| 409 | Offset += 64; |
| 410 | |
| 411 | std::string FilenameRename = HLE_IPC_BuildFilename((const char*)Memory::GetPointer(_BufferIn+Offset), 64); |
| 412 | Offset += 64; |
| 413 | |
| 414 | // try to make the basis directory |
| 415 | File::CreateFullPath(FilenameRename); |
| 416 | |
| 417 | // if there is already a file, delete it |
| 418 | if (File::Exists(Filename) && File::Exists(FilenameRename)) |
| 419 | { |
| 420 | File::Delete(FilenameRename); |
| 421 | } |
| 422 | |
| 423 | // finally try to rename the file |
| 424 | if (File::Rename(Filename, FilenameRename)) |
| 425 | { |
| 426 | INFO_LOG(WII_IPC_FILEIO, "FS: Rename %s to %s", Filename.c_str(), FilenameRename.c_str())do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 426, "FS: Rename %s to %s", Filename.c_str(), FilenameRename .c_str()); } } while (0); |
| 427 | } |
| 428 | else |
| 429 | { |
| 430 | ERROR_LOG(WII_IPC_FILEIO, "FS: Rename %s to %s - failed", Filename.c_str(), FilenameRename.c_str())do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 430, "FS: Rename %s to %s - failed", Filename.c_str(), FilenameRename .c_str()); } } while (0); |
| 431 | return FS_FILE_NOT_EXIST; |
| 432 | } |
| 433 | |
| 434 | return FS_RESULT_OK; |
| 435 | } |
| 436 | break; |
| 437 | |
| 438 | case IOCTL_CREATE_FILE: |
| 439 | { |
| 440 | _dbg_assert_(WII_IPC_FILEIO, _BufferOutSize == 0){}; |
| 441 | |
| 442 | u32 Addr = _BufferIn; |
| 443 | u32 OwnerID = Memory::Read_U32(Addr); Addr += 4; |
| 444 | u16 GroupID = Memory::Read_U16(Addr); Addr += 2; |
| 445 | std::string Filename(HLE_IPC_BuildFilename((const char*)Memory::GetPointer(Addr), 64)); Addr += 64; |
| 446 | u8 OwnerPerm = Memory::Read_U8(Addr); Addr++; |
| 447 | u8 GroupPerm = Memory::Read_U8(Addr); Addr++; |
| 448 | u8 OtherPerm = Memory::Read_U8(Addr); Addr++; |
| 449 | u8 Attributes = Memory::Read_U8(Addr); Addr++; |
| 450 | |
| 451 | INFO_LOG(WII_IPC_FILEIO, "FS: CreateFile %s", Filename.c_str())do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 451, "FS: CreateFile %s", Filename.c_str()); } } while (0); |
| 452 | DEBUG_LOG(WII_IPC_FILEIO, " OwnerID: 0x%08x", OwnerID)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 452, " OwnerID: 0x%08x", OwnerID); } } while (0); |
| 453 | DEBUG_LOG(WII_IPC_FILEIO, " GroupID: 0x%04x", GroupID)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 453, " GroupID: 0x%04x", GroupID); } } while (0); |
| 454 | DEBUG_LOG(WII_IPC_FILEIO, " OwnerPerm: 0x%02x", OwnerPerm)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 454, " OwnerPerm: 0x%02x", OwnerPerm); } } while (0); |
| 455 | DEBUG_LOG(WII_IPC_FILEIO, " GroupPerm: 0x%02x", GroupPerm)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 455, " GroupPerm: 0x%02x", GroupPerm); } } while (0); |
| 456 | DEBUG_LOG(WII_IPC_FILEIO, " OtherPerm: 0x%02x", OtherPerm)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 456, " OtherPerm: 0x%02x", OtherPerm); } } while (0); |
| 457 | DEBUG_LOG(WII_IPC_FILEIO, " Attributes: 0x%02x", Attributes)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 457, " Attributes: 0x%02x", Attributes); } } while (0); |
| 458 | |
| 459 | // check if the file already exist |
| 460 | if (File::Exists(Filename)) |
| 461 | { |
| 462 | WARN_LOG(WII_IPC_FILEIO, "\tresult = FS_RESULT_EXISTS")do { { if (LogTypes::LWARNING <= 3) GenericLog(LogTypes::LWARNING , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 462, "\tresult = FS_RESULT_EXISTS"); } } while (0); |
| 463 | return FS_FILE_EXIST; |
| 464 | } |
| 465 | |
| 466 | // create the file |
| 467 | File::CreateFullPath(Filename); // just to be sure |
| 468 | bool Result = File::CreateEmptyFile(Filename); |
| 469 | if (!Result) |
| 470 | { |
| 471 | ERROR_LOG(WII_IPC_FILEIO, "CWII_IPC_HLE_Device_fs: couldn't create new file")do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 471, "CWII_IPC_HLE_Device_fs: couldn't create new file"); } } while (0); |
| 472 | PanicAlert("CWII_IPC_HLE_Device_fs: couldn't create new file")MsgAlert(false, WARNING, "CWII_IPC_HLE_Device_fs: couldn't create new file" ); |
| 473 | return FS_RESULT_FATAL; |
| 474 | } |
| 475 | |
| 476 | INFO_LOG(WII_IPC_FILEIO, "\tresult = FS_RESULT_OK")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 476, "\tresult = FS_RESULT_OK"); } } while (0); |
| 477 | return FS_RESULT_OK; |
| 478 | } |
| 479 | break; |
| 480 | case IOCTL_SHUTDOWN: |
| 481 | { |
| 482 | INFO_LOG(WII_IPC_FILEIO, "Wii called Shutdown()")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 482, "Wii called Shutdown()"); } } while (0); |
| 483 | // TODO: stop emulation |
| 484 | } |
| 485 | break; |
| 486 | default: |
| 487 | ERROR_LOG(WII_IPC_FILEIO, "CWII_IPC_HLE_Device_fs::IOCtl: ni 0x%x", _Parameter)do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR , LogTypes::WII_IPC_FILEIO, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp" , 487, "CWII_IPC_HLE_Device_fs::IOCtl: ni 0x%x", _Parameter) ; } } while (0); |
| 488 | PanicAlert("CWII_IPC_HLE_Device_fs::IOCtl: ni 0x%x", _Parameter)MsgAlert(false, WARNING, "CWII_IPC_HLE_Device_fs::IOCtl: ni 0x%x" , _Parameter); |
| 489 | break; |
| 490 | } |
| 491 | |
| 492 | return FS_RESULT_FATAL; |
| 493 | } |
| 494 | |
| 495 | int CWII_IPC_HLE_Device_fs::GetCmdDelay(u32) |
| 496 | { |
| 497 | // ~1/1000th of a second is too short and causes hangs in Wii Party |
| 498 | // Play it safe at 1/500th |
| 499 | return SystemTimers::GetTicksPerSecond() / 500; |
| 500 | } |
| 501 | |
| 502 | void CWII_IPC_HLE_Device_fs::DoState(PointerWrap& p) |
| 503 | { |
| 504 | DoStateShared(p); |
| 505 | |
| 506 | // handle /tmp |
| 507 | |
| 508 | std::string Path = File::GetUserPath(D_WIIUSER_IDX) + "tmp"; |
| 509 | if (p.GetMode() == PointerWrap::MODE_READ) |
| 510 | { |
| 511 | File::DeleteDirRecursively(Path); |
| 512 | File::CreateDir(Path.c_str()); |
| 513 | |
| 514 | //now restore from the stream |
| 515 | while(1) { |
| 516 | char type = 0; |
| 517 | p.Do(type); |
| 518 | if (!type) |
| 519 | break; |
| 520 | std::string filename; |
| 521 | p.Do(filename); |
| 522 | std::string name = Path + DIR_SEP"/" + filename; |
| 523 | switch(type) |
| 524 | { |
| 525 | case 'd': |
| 526 | { |
| 527 | File::CreateDir(name.c_str()); |
| 528 | break; |
| 529 | } |
| 530 | case 'f': |
| 531 | { |
| 532 | u32 size = 0; |
| 533 | p.Do(size); |
| 534 | |
| 535 | File::IOFile handle(name, "wb"); |
| 536 | char buf[65536]; |
| 537 | u32 count = size; |
| 538 | while(count > 65536) { |
| 539 | p.DoArray(&buf[0], 65536); |
| 540 | handle.WriteArray(&buf[0], 65536); |
| 541 | count -= 65536; |
| 542 | } |
| 543 | p.DoArray(&buf[0], count); |
| 544 | handle.WriteArray(&buf[0], count); |
| 545 | break; |
| 546 | } |
| 547 | } |
| 548 | } |
| 549 | } |
| 550 | else |
| 551 | { |
| 552 | //recurse through tmp and save dirs and files |
| 553 | |
| 554 | File::FSTEntry parentEntry; |
| 555 | File::ScanDirectoryTree(Path, parentEntry); |
| 556 | std::deque<File::FSTEntry> todo; |
| 557 | todo.insert(todo.end(), parentEntry.children.begin(), |
| 558 | parentEntry.children.end()); |
| 559 | |
| 560 | while(!todo.empty()) |
| 561 | { |
| 562 | File::FSTEntry &entry = todo.front(); |
| 563 | std::string name = entry.physicalName; |
| 564 | name.erase(0,Path.length()+1); |
| 565 | char type = entry.isDirectory?'d':'f'; |
| 566 | p.Do(type); |
| 567 | p.Do(name); |
| 568 | if (entry.isDirectory) |
| 569 | { |
| 570 | todo.insert(todo.end(), entry.children.begin(), |
| 571 | entry.children.end()); |
| 572 | } |
| 573 | else |
| 574 | { |
| 575 | u32 size = entry.size; |
| 576 | p.Do(size); |
| 577 | |
| 578 | File::IOFile handle(entry.physicalName, "rb"); |
| 579 | char buf[65536]; |
| 580 | u32 count = size; |
| 581 | while(count > 65536) { |
| 582 | handle.ReadArray(&buf[0], 65536); |
| 583 | p.DoArray(&buf[0], 65536); |
| 584 | count -= 65536; |
| 585 | } |
| 586 | handle.ReadArray(&buf[0], count); |
| 587 | p.DoArray(&buf[0], count); |
| 588 | } |
| 589 | todo.pop_front(); |
| 590 | } |
| 591 | |
| 592 | char type = 0; |
| 593 | p.Do(type); |
| 594 | } |
| 595 | } |