mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-28 12:40:12 +00:00
VFS::TruncateFile() implemented
This commit is contained in:
parent
b1f7543436
commit
f2276bb70c
@ -21,7 +21,7 @@ std::unique_ptr<wchar_t> ConvertUTF8ToWChar(const std::string& source)
|
||||
|
||||
if (!MultiByteToWideChar(CP_UTF8, 0, source.c_str(), size, buffer.get(), size))
|
||||
{
|
||||
LOG_ERROR(GENERAL, "ConvertUTF8ToWChar(source='%s') failed: 0x%llx", source.c_str(), GET_API_ERROR);
|
||||
LOG_ERROR(GENERAL, "ConvertUTF8ToWChar(source='%s') failed: 0x%llx", source, GET_API_ERROR);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
@ -36,6 +36,33 @@ time_t to_time_t(const FILETIME& ft)
|
||||
return v.QuadPart / 10000000ULL - 11644473600ULL;
|
||||
}
|
||||
|
||||
bool truncate_file(const std::string& file, uint64_t length)
|
||||
{
|
||||
const auto handle = CreateFileW(ConvertUTF8ToWChar(file).get(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
LARGE_INTEGER distance;
|
||||
distance.QuadPart = length;
|
||||
|
||||
if (!SetFilePointerEx(handle, distance, NULL, FILE_BEGIN))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SetEndOfFile(handle))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
return false;
|
||||
}
|
||||
|
||||
return CloseHandle(handle);
|
||||
}
|
||||
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
@ -119,10 +146,16 @@ bool rIsDir(const std::string& dir)
|
||||
bool rMkdir(const std::string& dir)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return !_mkdir(dir.c_str());
|
||||
if (!CreateDirectoryW(ConvertUTF8ToWChar(dir).get(), NULL))
|
||||
#else
|
||||
return !mkdir(dir.c_str(), 0777);
|
||||
if (mkdir(dir.c_str(), 0777))
|
||||
#endif
|
||||
{
|
||||
LOG_ERROR(GENERAL, "Error creating directory '%s': 0x%llx", dir, GET_API_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool rMkpath(const std::string& path)
|
||||
@ -160,7 +193,7 @@ bool rRmdir(const std::string& dir)
|
||||
if (rmdir(dir.c_str()))
|
||||
#endif
|
||||
{
|
||||
LOG_ERROR(GENERAL, "Error deleting directory %s: 0x%llx", dir.c_str(), GET_API_ERROR);
|
||||
LOG_ERROR(GENERAL, "Error deleting directory '%s': 0x%llx", dir, GET_API_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -176,7 +209,7 @@ bool rRename(const std::string& from, const std::string& to)
|
||||
if (rename(from.c_str(), to.c_str()))
|
||||
#endif
|
||||
{
|
||||
LOG_ERROR(GENERAL, "Error renaming '%s' to '%s': 0x%llx", from.c_str(), to.c_str(), GET_API_ERROR);
|
||||
LOG_ERROR(GENERAL, "Error renaming '%s' to '%s': 0x%llx", from, to, GET_API_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -227,7 +260,7 @@ bool rCopy(const std::string& from, const std::string& to, bool overwrite)
|
||||
if (OSCopyFile(from.c_str(), to.c_str(), overwrite))
|
||||
#endif
|
||||
{
|
||||
LOG_ERROR(GENERAL, "Error copying '%s' to '%s': 0x%llx", from.c_str(), to.c_str(), GET_API_ERROR);
|
||||
LOG_ERROR(GENERAL, "Error copying '%s' to '%s': 0x%llx", from, to, GET_API_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -252,9 +285,25 @@ bool rRemoveFile(const std::string& file)
|
||||
if (unlink(file.c_str()))
|
||||
#endif
|
||||
{
|
||||
LOG_ERROR(GENERAL, "Error deleting file %s: 0x%llx", file.c_str(), GET_API_ERROR);
|
||||
LOG_ERROR(GENERAL, "Error deleting file '%s': 0x%llx", file, GET_API_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool rTruncate(const std::string& file, uint64_t length)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (!truncate_file(file, length))
|
||||
#else
|
||||
if (truncate64(file.c_str()), length)
|
||||
#endif
|
||||
{
|
||||
LOG_ERROR(GENERAL, "Error resizing file '%s' to 0x%llx: 0x%llx", file, length, GET_API_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -350,7 +399,6 @@ rFile::rFile()
|
||||
|
||||
rFile::rFile(const std::string& filename, rFile::OpenMode open)
|
||||
{
|
||||
|
||||
handle = reinterpret_cast<void*>(new wxFile(fmt::FromUTF8(filename), convertOpenMode(open)));
|
||||
}
|
||||
|
||||
|
@ -20,8 +20,9 @@ bool rMkdir(const std::string& dir);
|
||||
bool rMkpath(const std::string& path);
|
||||
bool rRename(const std::string& from, const std::string& to);
|
||||
bool rCopy(const std::string& from, const std::string& to, bool overwrite);
|
||||
bool rExists(const std::string& path);
|
||||
bool rRemoveFile(const std::string& path);
|
||||
bool rExists(const std::string& file);
|
||||
bool rRemoveFile(const std::string& file);
|
||||
bool rTruncate(const std::string& file, uint64_t length);
|
||||
|
||||
enum rSeekMode
|
||||
{
|
||||
|
@ -315,6 +315,18 @@ bool VFS::CopyFile(const std::string& ps3_path_from, const std::string& ps3_path
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VFS::TruncateFile(const std::string& ps3_path, u64 length) const
|
||||
{
|
||||
std::string path;
|
||||
|
||||
if (vfsDevice* dev = GetDevice(ps3_path, path))
|
||||
{
|
||||
return rTruncate(path, length);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
vfsDevice* VFS::GetDevice(const std::string& ps3_path, std::string& path) const
|
||||
{
|
||||
auto try_get_device = [this, &path](const std::string& ps3_path) -> vfsDevice*
|
||||
|
@ -90,6 +90,7 @@ struct VFS
|
||||
bool RenameFile(const std::string& ps3_path_from, const std::string& ps3_path_to) const;
|
||||
bool RenameDir(const std::string& ps3_path_from, const std::string& ps3_path_to) const;
|
||||
bool CopyFile(const std::string& ps3_path_from, const std::string& ps3_path_to, bool overwrite = true) const;
|
||||
bool TruncateFile(const std::string& ps3_path, u64 length) const;
|
||||
|
||||
vfsDevice* GetDevice(const std::string& ps3_path, std::string& path) const;
|
||||
vfsDevice* GetDeviceLocal(const std::string& local_path, std::string& path) const;
|
||||
|
@ -346,18 +346,22 @@ __noinline s32 savedata_op(
|
||||
save_entry.dirName = dirName.get_ptr();
|
||||
}
|
||||
|
||||
// get save stats
|
||||
std::string dir_path = base_dir + save_entry.dirName + "/";
|
||||
std::string sfo_path = dir_path + "PARAM.SFO";
|
||||
|
||||
PSFLoader psf;
|
||||
|
||||
// Load PARAM.SFO
|
||||
{
|
||||
vfsFile f(sfo_path);
|
||||
psf.Load(f);
|
||||
}
|
||||
|
||||
// Get save stats
|
||||
{
|
||||
vm::stackvar<CellSaveDataStatGet> statGet(CPU);
|
||||
vm::stackvar<CellSaveDataStatSet> statSet(CPU);
|
||||
|
||||
vfsFile f(sfo_path);
|
||||
PSFLoader psf(f);
|
||||
f.Close();
|
||||
|
||||
std::string dir_local_path;
|
||||
|
||||
Emu.GetVFS().GetDevice(dir_path, dir_local_path);
|
||||
@ -416,9 +420,13 @@ __noinline s32 savedata_op(
|
||||
{
|
||||
file.fileType = CELL_SAVEDATA_FILETYPE_CONTENT_SND0;
|
||||
}
|
||||
else if (psf.GetInteger("*" + entry->name)) // let's put the list of protected files in PARAM.SFO (int param = 1 if protected)
|
||||
{
|
||||
file.fileType = CELL_SAVEDATA_FILETYPE_SECUREFILE;
|
||||
}
|
||||
else
|
||||
{
|
||||
file.fileType = CELL_SAVEDATA_FILETYPE_NORMALFILE; // protected files are not supported
|
||||
file.fileType = CELL_SAVEDATA_FILETYPE_NORMALFILE;
|
||||
}
|
||||
|
||||
file.size = entry->size;
|
||||
@ -481,22 +489,12 @@ __noinline s32 savedata_op(
|
||||
return CELL_SAVEDATA_ERROR_PARAM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create save directory if necessary
|
||||
if (save_entry.isNew && !Emu.GetVFS().CreateDir(dir_path))
|
||||
{
|
||||
// error
|
||||
}
|
||||
|
||||
// Write PARAM.SFO
|
||||
if (psf)
|
||||
{
|
||||
Emu.GetVFS().CreateFile(sfo_path, true);
|
||||
|
||||
f.Open(sfo_path, vfsWrite);
|
||||
psf.Save(f);
|
||||
f.Close();
|
||||
}
|
||||
// Create save directory if necessary
|
||||
if (save_entry.isNew && !Emu.GetVFS().CreateDir(dir_path))
|
||||
{
|
||||
// Let's ignore this error for now
|
||||
}
|
||||
|
||||
// Enter the loop where the save files are read/created/deleted
|
||||
@ -520,38 +518,38 @@ __noinline s32 savedata_op(
|
||||
break;
|
||||
}
|
||||
|
||||
std::string filepath = dir_path;
|
||||
std::string filepath;
|
||||
|
||||
switch (const u32 type = fileSet->fileType)
|
||||
{
|
||||
case CELL_SAVEDATA_FILETYPE_SECUREFILE:
|
||||
case CELL_SAVEDATA_FILETYPE_NORMALFILE:
|
||||
{
|
||||
filepath += fileSet->fileName.get_ptr();
|
||||
filepath = fileSet->fileName.get_ptr();
|
||||
break;
|
||||
}
|
||||
|
||||
case CELL_SAVEDATA_FILETYPE_CONTENT_ICON0:
|
||||
{
|
||||
filepath += "ICON0.PNG";
|
||||
filepath = "ICON0.PNG";
|
||||
break;
|
||||
}
|
||||
|
||||
case CELL_SAVEDATA_FILETYPE_CONTENT_ICON1:
|
||||
{
|
||||
filepath += "ICON1.PAM";
|
||||
filepath = "ICON1.PAM";
|
||||
break;
|
||||
}
|
||||
|
||||
case CELL_SAVEDATA_FILETYPE_CONTENT_PIC1:
|
||||
{
|
||||
filepath += "PIC1.PNG";
|
||||
filepath = "PIC1.PNG";
|
||||
break;
|
||||
}
|
||||
|
||||
case CELL_SAVEDATA_FILETYPE_CONTENT_SND0:
|
||||
{
|
||||
filepath += "SND0.AT3";
|
||||
filepath = "SND0.AT3";
|
||||
break;
|
||||
}
|
||||
|
||||
@ -562,6 +560,10 @@ __noinline s32 savedata_op(
|
||||
}
|
||||
}
|
||||
|
||||
psf.SetInteger("*" + filepath, fileSet->fileType.data() == se32(CELL_SAVEDATA_FILETYPE_SECUREFILE));
|
||||
|
||||
filepath = dir_path + filepath;
|
||||
|
||||
std::unique_ptr<vfsStream> file;
|
||||
|
||||
switch (const u32 op = fileSet->fileOperation)
|
||||
@ -608,6 +610,15 @@ __noinline s32 savedata_op(
|
||||
}
|
||||
}
|
||||
|
||||
// Write PARAM.SFO
|
||||
if (psf)
|
||||
{
|
||||
Emu.GetVFS().CreateFile(sfo_path, true);
|
||||
|
||||
vfsFile f(sfo_path, vfsWrite);
|
||||
psf.Save(f);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -527,28 +527,16 @@ s32 sys_fs_truncate(vm::ptr<const char> path, u64 size)
|
||||
sys_fs.Warning("sys_fs_truncate(path=*0x%x, size=0x%llx)", path, size);
|
||||
sys_fs.Warning("*** path = '%s'", path.get_ptr());
|
||||
|
||||
vfsFile f(path.get_ptr(), vfsReadWrite);
|
||||
if (!f.IsOpened())
|
||||
const std::string filename = path.get_ptr();
|
||||
|
||||
if (!Emu.GetVFS().ExistsFile(filename))
|
||||
{
|
||||
sys_fs.Warning("sys_fs_truncate(): '%s' not found", path.get_ptr());
|
||||
return CELL_FS_ENOENT;
|
||||
}
|
||||
|
||||
u64 initialSize = f.GetSize();
|
||||
|
||||
if (initialSize < size)
|
||||
if (!Emu.GetVFS().TruncateFile(filename, size))
|
||||
{
|
||||
u64 last_pos = f.Tell();
|
||||
f.Seek(0, vfsSeekEnd);
|
||||
static const char nullbyte = 0;
|
||||
f.Seek(size - initialSize - 1, vfsSeekCur);
|
||||
f.Write(&nullbyte, sizeof(char));
|
||||
f.Seek(last_pos, vfsSeekSet);
|
||||
}
|
||||
|
||||
if (initialSize > size)
|
||||
{
|
||||
// (TODO)
|
||||
return CELL_FS_EIO; // ???
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
|
@ -41,6 +41,8 @@ class PSFLoader
|
||||
std::vector<PSFEntry> m_entries;
|
||||
|
||||
public:
|
||||
PSFLoader() = default;
|
||||
|
||||
PSFLoader(vfsStream& stream)
|
||||
{
|
||||
Load(stream);
|
||||
|
Loading…
x
Reference in New Issue
Block a user