Bug Summary

File:Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp
Location:line 315, column 7
Description:Value stored to 'GroupPerm' during its initialization is never read

Annotated Source Code

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
22static Common::replace_v replacements;
23
24
25CWII_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
31CWII_IPC_HLE_Device_fs::~CWII_IPC_HLE_Device_fs()
32{}
33
34bool 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
48bool 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?
59static 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
74bool 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
236bool 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
258s32 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;
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;
Value stored to 'GroupPerm' during its initialization is never read
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 = 0;
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
481 default:
482 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"
, 482, "CWII_IPC_HLE_Device_fs::IOCtl: ni 0x%x", _Parameter)
; } } while (0)
;
483 PanicAlert("CWII_IPC_HLE_Device_fs::IOCtl: ni 0x%x", _Parameter)MsgAlert(false, WARNING, "CWII_IPC_HLE_Device_fs::IOCtl: ni 0x%x"
, _Parameter)
;
484 break;
485 }
486
487 return FS_RESULT_FATAL;
488}
489
490int CWII_IPC_HLE_Device_fs::GetCmdDelay(u32)
491{
492 // ~1/1000th of a second is too short and causes hangs in Wii Party
493 // Play it safe at 1/500th
494 return SystemTimers::GetTicksPerSecond() / 500;
495}
496
497void CWII_IPC_HLE_Device_fs::DoState(PointerWrap& p)
498{
499 DoStateShared(p);
500
501 // handle /tmp
502
503 std::string Path = File::GetUserPath(D_WIIUSER_IDX) + "tmp";
504 if (p.GetMode() == PointerWrap::MODE_READ)
505 {
506 File::DeleteDirRecursively(Path);
507 File::CreateDir(Path.c_str());
508
509 //now restore from the stream
510 while(1) {
511 char type = 0;
512 p.Do(type);
513 if (!type)
514 break;
515 std::string filename;
516 p.Do(filename);
517 std::string name = Path + DIR_SEP"/" + filename;
518 switch(type)
519 {
520 case 'd':
521 {
522 File::CreateDir(name.c_str());
523 break;
524 }
525 case 'f':
526 {
527 u32 size = 0;
528 p.Do(size);
529
530 File::IOFile handle(name, "wb");
531 char buf[65536];
532 u32 count = size;
533 while(count > 65536) {
534 p.DoArray(&buf[0], 65536);
535 handle.WriteArray(&buf[0], 65536);
536 count -= 65536;
537 }
538 p.DoArray(&buf[0], count);
539 handle.WriteArray(&buf[0], count);
540 break;
541 }
542 }
543 }
544 }
545 else
546 {
547 //recurse through tmp and save dirs and files
548
549 File::FSTEntry parentEntry;
550 File::ScanDirectoryTree(Path, parentEntry);
551 std::deque<File::FSTEntry> todo;
552 todo.insert(todo.end(), parentEntry.children.begin(),
553 parentEntry.children.end());
554
555 while(!todo.empty())
556 {
557 File::FSTEntry &entry = todo.front();
558 std::string name = entry.physicalName;
559 name.erase(0,Path.length()+1);
560 char type = entry.isDirectory?'d':'f';
561 p.Do(type);
562 p.Do(name);
563 if (entry.isDirectory)
564 {
565 todo.insert(todo.end(), entry.children.begin(),
566 entry.children.end());
567 }
568 else
569 {
570 u32 size = entry.size;
571 p.Do(size);
572
573 File::IOFile handle(entry.physicalName, "rb");
574 char buf[65536];
575 u32 count = size;
576 while(count > 65536) {
577 handle.ReadArray(&buf[0], 65536);
578 p.DoArray(&buf[0], 65536);
579 count -= 65536;
580 }
581 handle.ReadArray(&buf[0], count);
582 p.DoArray(&buf[0], count);
583 }
584 todo.pop_front();
585 }
586
587 char type = 0;
588 p.Do(type);
589 }
590}