Пример #1
0
// Get total filesize of contents of a directory (recursive)
// Only used for ES_GetUsage atm, could be useful elsewhere?
static u64 ComputeTotalFileSize(const File::FSTEntry& parentEntry)
{
	u64 sizeOfFiles = 0;
	for (const File::FSTEntry& entry : parentEntry.children)
	{
		if (entry.isDirectory)
			sizeOfFiles += ComputeTotalFileSize(entry);
		else
			sizeOfFiles += entry.size;
	}
	return sizeOfFiles;
}
// Get total filesize of contents of a directory (recursive)
// Only used for ES_GetUsage atm, could be useful elsewhere?
static u64 ComputeTotalFileSize(const File::FSTEntry& parentEntry)
{
	u64 sizeOfFiles = 0;
	const std::vector<File::FSTEntry>& children = parentEntry.children;
	for (std::vector<File::FSTEntry>::const_iterator it = children.begin(); it != children.end(); ++it)
	{
		const File::FSTEntry& entry = *it;
		if (entry.isDirectory)
			sizeOfFiles += ComputeTotalFileSize(entry);
		else
			sizeOfFiles += entry.size;
	}
	return sizeOfFiles;
}
Пример #3
0
Result<DirectoryStats> HostFileSystem::GetDirectoryStats(const std::string& wii_path)
{
  if (!IsValidWiiPath(wii_path))
    return ResultCode::Invalid;

  DirectoryStats stats{};
  std::string path(BuildFilename(wii_path));
  if (File::IsDirectory(path))
  {
    File::FSTEntry parent_dir = File::ScanDirectoryTree(path, true);
    // add one for the folder itself
    stats.used_inodes = 1 + (u32)parent_dir.size;

    u64 total_size = ComputeTotalFileSize(parent_dir);  // "Real" size to convert to nand blocks

    stats.used_clusters = (u32)(total_size / (16 * 1024));  // one block is 16kb
  }
  else
  {
    WARN_LOG(IOS_FS, "fsBlock failed, cannot find directory: %s", path.c_str());
  }
  return stats;
}
Пример #4
0
bool CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
{
	u32 ReturnValue = FS_RESULT_OK;
	SIOCtlVBuffer CommandBuffer(_CommandAddress);

	// Prepare the out buffer(s) with zeros as a safety precaution
	// to avoid returning bad values
	for(u32 i = 0; i < CommandBuffer.NumberPayloadBuffer; i++)
	{
		Memory::Memset(CommandBuffer.PayloadBuffer[i].m_Address, 0,
			CommandBuffer.PayloadBuffer[i].m_Size);
	}

	switch(CommandBuffer.Parameter)
	{
	case IOCTLV_READ_DIR:
		{
			// the wii uses this function to define the type (dir or file)
			std::string DirName(HLE_IPC_BuildFilename((const char*)Memory::GetPointer(
				CommandBuffer.InBuffer[0].m_Address), CommandBuffer.InBuffer[0].m_Size));

			INFO_LOG(WII_IPC_FILEIO, "FS: IOCTL_READ_DIR %s", DirName.c_str());

			if (!File::Exists(DirName))
			{
				WARN_LOG(WII_IPC_FILEIO, "FS: Search not found: %s", DirName.c_str());
				ReturnValue = FS_FILE_NOT_EXIST;
				break;
			}
			else if (!File::IsDirectory(DirName))
			{
				// It's not a directory, so error.
				// Games don't usually seem to care WHICH error they get, as long as it's <
				// Well the system menu CARES!
				WARN_LOG(WII_IPC_FILEIO, "\tNot a directory - return FS_RESULT_FATAL");
				ReturnValue = FS_RESULT_FATAL;
				break;
			}

			// make a file search
			CFileSearch::XStringVector Directories;
			Directories.push_back(DirName);

			CFileSearch::XStringVector Extensions;
			Extensions.push_back("*.*");

			CFileSearch FileSearch(Extensions, Directories);

			// it is one
			if ((CommandBuffer.InBuffer.size() == 1) && (CommandBuffer.PayloadBuffer.size() == 1))
			{
				size_t numFile = FileSearch.GetFileNames().size();
				INFO_LOG(WII_IPC_FILEIO, "\t%lu files found", (unsigned long)numFile);

				Memory::Write_U32((u32)numFile, CommandBuffer.PayloadBuffer[0].m_Address);
			}
			else
			{
				u32 MaxEntries = Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address);

				memset(Memory::GetPointer(CommandBuffer.PayloadBuffer[0].m_Address), 0, CommandBuffer.PayloadBuffer[0].m_Size);

				size_t numFiles = 0;
				char* pFilename = (char*)Memory::GetPointer((u32)(CommandBuffer.PayloadBuffer[0].m_Address));

				for (size_t i=0; i<FileSearch.GetFileNames().size(); i++)
				{
					if (i >= MaxEntries)
						break;

					std::string name, ext;
					SplitPath(FileSearch.GetFileNames()[i], NULL, &name, &ext);
					std::string FileName = name + ext;

					// Decode entities of invalid file system characters so that
					// games (such as HP:HBP) will be able to find what they expect.
					for (const Common::replace_t& r : replacements)
					{
						for (size_t j = 0; (j = FileName.find(r.second, j)) != FileName.npos; ++j)
							FileName.replace(j, r.second.length(), 1, r.first);
					}

					strcpy(pFilename, FileName.c_str());
					pFilename += FileName.length();
					*pFilename++ = 0x00;  // termination
					numFiles++;

					INFO_LOG(WII_IPC_FILEIO, "\tFound: %s", FileName.c_str());
				}

				Memory::Write_U32((u32)numFiles, CommandBuffer.PayloadBuffer[1].m_Address);
			}

			ReturnValue = FS_RESULT_OK;
		}
		break;

	case IOCTLV_GETUSAGE:
		{
			_dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer.size() == 2);
			_dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer[0].m_Size == 4);
			_dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer[1].m_Size == 4);

			// this command sucks because it asks of the number of used
			// fsBlocks and inodes
			// It should be correct, but don't count on it...
			const char *relativepath = (const char*)Memory::GetPointer(CommandBuffer.InBuffer[0].m_Address);
			std::string path(HLE_IPC_BuildFilename(relativepath, CommandBuffer.InBuffer[0].m_Size));
			u32 fsBlocks = 0;
			u32 iNodes = 0;

			INFO_LOG(WII_IPC_FILEIO, "IOCTL_GETUSAGE %s", path.c_str());
			if (File::IsDirectory(path))
			{
				// LPFaint99: After I found that setting the number of inodes to the number of children + 1 for the directory itself
				// I decided to compare with sneek which has the following 2 special cases which are
				// Copyright (C) 2009-2011  crediar http://code.google.com/p/sneek/
				if ((memcmp(relativepath, "/title/00010001", 16 ) == 0 ) ||
					(memcmp(relativepath, "/title/00010005", 16) == 0 ))
				{
					fsBlocks = 23; // size is size/0x4000
					iNodes = 42; // empty folders return a FileCount of 1
				}
				else
				{
					File::FSTEntry parentDir;
					// add one for the folder itself, allows some games to create their save files
					// R8XE52 (Jurassic: The Hunted), STEETR (Tetris Party Deluxe) now create their saves with this change
					iNodes = 1 + File::ScanDirectoryTree(path, parentDir);

					u64 totalSize = ComputeTotalFileSize(parentDir); // "Real" size, to be converted to nand blocks

					fsBlocks = (u32)(totalSize / (16 * 1024));  // one bock is 16kb
				}
				ReturnValue = FS_RESULT_OK;

				INFO_LOG(WII_IPC_FILEIO, "FS: fsBlock: %i, iNodes: %i", fsBlocks, iNodes);
			}
			else
			{
				fsBlocks = 0;
				iNodes = 0;
				ReturnValue = FS_RESULT_OK;
				WARN_LOG(WII_IPC_FILEIO, "FS: fsBlock failed, cannot find directory: %s", path.c_str());
			}

			Memory::Write_U32(fsBlocks, CommandBuffer.PayloadBuffer[0].m_Address);
			Memory::Write_U32(iNodes, CommandBuffer.PayloadBuffer[1].m_Address);
		}
		break;


	default:
		PanicAlert("CWII_IPC_HLE_Device_fs::IOCtlV: %i", CommandBuffer.Parameter);
		break;
	}

	Memory::Write_U32(ReturnValue, _CommandAddress+4);

	return true;
}
Пример #5
0
IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
{
  u32 ReturnValue = FS_RESULT_OK;
  SIOCtlVBuffer CommandBuffer(_CommandAddress);

  // Prepare the out buffer(s) with zeros as a safety precaution
  // to avoid returning bad values
  for (u32 i = 0; i < CommandBuffer.NumberPayloadBuffer; i++)
  {
    Memory::Memset(CommandBuffer.PayloadBuffer[i].m_Address, 0,
                   CommandBuffer.PayloadBuffer[i].m_Size);
  }

  switch (CommandBuffer.Parameter)
  {
  case IOCTLV_READ_DIR:
  {
    const std::string relative_path =
        Memory::GetString(CommandBuffer.InBuffer[0].m_Address, CommandBuffer.InBuffer[0].m_Size);

    if (!IsValidWiiPath(relative_path))
    {
      WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", relative_path.c_str());
      ReturnValue = FS_RESULT_FATAL;
      break;
    }

    // the Wii uses this function to define the type (dir or file)
    std::string DirName(HLE_IPC_BuildFilename(relative_path));

    INFO_LOG(WII_IPC_FILEIO, "FS: IOCTL_READ_DIR %s", DirName.c_str());

    if (!File::Exists(DirName))
    {
      WARN_LOG(WII_IPC_FILEIO, "FS: Search not found: %s", DirName.c_str());
      ReturnValue = FS_FILE_NOT_EXIST;
      break;
    }
    else if (!File::IsDirectory(DirName))
    {
      // It's not a directory, so error.
      // Games don't usually seem to care WHICH error they get, as long as it's <
      // Well the system menu CARES!
      WARN_LOG(WII_IPC_FILEIO, "\tNot a directory - return FS_RESULT_FATAL");
      ReturnValue = FS_RESULT_FATAL;
      break;
    }

    File::FSTEntry entry = File::ScanDirectoryTree(DirName, false);

    // it is one
    if ((CommandBuffer.InBuffer.size() == 1) && (CommandBuffer.PayloadBuffer.size() == 1))
    {
      size_t numFile = entry.children.size();
      INFO_LOG(WII_IPC_FILEIO, "\t%zu files found", numFile);

      Memory::Write_U32((u32)numFile, CommandBuffer.PayloadBuffer[0].m_Address);
    }
    else
    {
      for (File::FSTEntry& child : entry.children)
      {
        // Decode escaped invalid file system characters so that games (such as
        // Harry Potter and the Half-Blood Prince) can find what they expect.
        child.virtualName = Common::UnescapeFileName(child.virtualName);
      }

      std::sort(entry.children.begin(), entry.children.end(),
                [](const File::FSTEntry& one, const File::FSTEntry& two) {
                  return one.virtualName < two.virtualName;
                });

      u32 MaxEntries = Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address);

      memset(Memory::GetPointer(CommandBuffer.PayloadBuffer[0].m_Address), 0,
             CommandBuffer.PayloadBuffer[0].m_Size);

      size_t numFiles = 0;
      char* pFilename = (char*)Memory::GetPointer((u32)(CommandBuffer.PayloadBuffer[0].m_Address));

      for (size_t i = 0; i < entry.children.size() && i < MaxEntries; i++)
      {
        const std::string& FileName = entry.children[i].virtualName;

        strcpy(pFilename, FileName.c_str());
        pFilename += FileName.length();
        *pFilename++ = 0x00;  // termination
        numFiles++;

        INFO_LOG(WII_IPC_FILEIO, "\tFound: %s", FileName.c_str());
      }

      Memory::Write_U32((u32)numFiles, CommandBuffer.PayloadBuffer[1].m_Address);
    }

    ReturnValue = FS_RESULT_OK;
  }
  break;

  case IOCTLV_GETUSAGE:
  {
    _dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer.size() == 2);
    _dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer[0].m_Size == 4);
    _dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer[1].m_Size == 4);

    // this command sucks because it asks of the number of used
    // fsBlocks and inodes
    // It should be correct, but don't count on it...
    std::string relativepath =
        Memory::GetString(CommandBuffer.InBuffer[0].m_Address, CommandBuffer.InBuffer[0].m_Size);

    if (!IsValidWiiPath(relativepath))
    {
      WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", relativepath.c_str());
      ReturnValue = FS_RESULT_FATAL;
      break;
    }

    std::string path(HLE_IPC_BuildFilename(relativepath));
    u32 fsBlocks = 0;
    u32 iNodes = 0;

    INFO_LOG(WII_IPC_FILEIO, "IOCTL_GETUSAGE %s", path.c_str());
    if (File::IsDirectory(path))
    {
      // LPFaint99: After I found that setting the number of inodes to the number of children + 1
      // for the directory itself
      // I decided to compare with sneek which has the following 2 special cases which are
      // Copyright (C) 2009-2011  crediar http://code.google.com/p/sneek/
      if ((relativepath.compare(0, 16, "/title/00010001") == 0) ||
          (relativepath.compare(0, 16, "/title/00010005") == 0))
      {
        fsBlocks = 23;  // size is size/0x4000
        iNodes = 42;    // empty folders return a FileCount of 1
      }
      else
      {
        File::FSTEntry parentDir = File::ScanDirectoryTree(path, true);
        // add one for the folder itself
        iNodes = 1 + (u32)parentDir.size;

        u64 totalSize =
            ComputeTotalFileSize(parentDir);  // "Real" size, to be converted to nand blocks

        fsBlocks = (u32)(totalSize / (16 * 1024));  // one bock is 16kb
      }
      ReturnValue = FS_RESULT_OK;

      INFO_LOG(WII_IPC_FILEIO, "FS: fsBlock: %i, iNodes: %i", fsBlocks, iNodes);
    }
    else
    {
      fsBlocks = 0;
      iNodes = 0;
      ReturnValue = FS_RESULT_OK;
      WARN_LOG(WII_IPC_FILEIO, "FS: fsBlock failed, cannot find directory: %s", path.c_str());
    }

    Memory::Write_U32(fsBlocks, CommandBuffer.PayloadBuffer[0].m_Address);
    Memory::Write_U32(iNodes, CommandBuffer.PayloadBuffer[1].m_Address);
  }
  break;

  default:
    PanicAlert("CWII_IPC_HLE_Device_fs::IOCtlV: %i", CommandBuffer.Parameter);
    break;
  }

  Memory::Write_U32(ReturnValue, _CommandAddress + 4);

  return GetFSReply();
}