mirror of
https://github.com/stenzek/duckstation.git
synced 2025-06-12 22:37:21 +00:00
ISOReader: Add file extraction helpers
This commit is contained in:
parent
20df4ec14e
commit
e9644c7eeb
@ -5,7 +5,9 @@
|
|||||||
#include "cd_image.h"
|
#include "cd_image.h"
|
||||||
|
|
||||||
#include "common/error.h"
|
#include "common/error.h"
|
||||||
|
#include "common/file_system.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
|
#include "common/progress_callback.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
|
|
||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
@ -385,3 +387,97 @@ bool IsoReader::ReadFile(const ISODirectoryEntry& de, std::vector<u8>* data, Err
|
|||||||
data->resize(de.length_le);
|
data->resize(de.length_le);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsoReader::WriteFileToStream(std::string_view path, std::FILE* fp, Error* error /* = nullptr */,
|
||||||
|
ProgressCallback* progress /* = nullptr */)
|
||||||
|
{
|
||||||
|
auto de = LocateFile(path, error);
|
||||||
|
if (!de)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return WriteFileToStream(de.value(), fp, error, progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsoReader::WriteFileToStream(const ISODirectoryEntry& de, std::FILE* fp, Error* error /* = nullptr */,
|
||||||
|
ProgressCallback* progress /* = nullptr */)
|
||||||
|
{
|
||||||
|
if (de.flags & ISODirectoryEntryFlag_Directory)
|
||||||
|
{
|
||||||
|
Error::SetString(error, "File is a directory");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FileSystem::FSeek64(fp, 0, SEEK_SET, error))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (de.length_le == 0)
|
||||||
|
return FileSystem::FTruncate64(fp, 0, error);
|
||||||
|
|
||||||
|
const u32 num_sectors = (de.length_le + (SECTOR_SIZE - 1)) / SECTOR_SIZE;
|
||||||
|
u32 file_pos = 0;
|
||||||
|
u8 sector_buffer[SECTOR_SIZE];
|
||||||
|
|
||||||
|
if (progress)
|
||||||
|
{
|
||||||
|
progress->SetProgressRange(de.length_le);
|
||||||
|
progress->SetProgressValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0, lsn = de.location_le; i < num_sectors; i++, lsn++)
|
||||||
|
{
|
||||||
|
if (!ReadSector(sector_buffer, lsn, error))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const u32 write_size = std::min<u32>(de.length_le - file_pos, SECTOR_SIZE);
|
||||||
|
if (std::fwrite(sector_buffer, write_size, 1, fp) != 1)
|
||||||
|
{
|
||||||
|
Error::SetErrno(error, "fwrite() failed: ", errno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_pos += write_size;
|
||||||
|
if (progress)
|
||||||
|
{
|
||||||
|
progress->SetProgressValue(file_pos);
|
||||||
|
if (progress->IsCancelled())
|
||||||
|
{
|
||||||
|
Error::SetStringView(error, "Operation was cancelled.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::fflush(fp) != 0)
|
||||||
|
{
|
||||||
|
Error::SetErrno(error, "fflush() failed: ", errno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string IsoReader::ISODirectoryEntryDateTime::GetFormattedTime() const
|
||||||
|
{
|
||||||
|
// need to apply the UTC offset, so first convert to unix time
|
||||||
|
struct tm utime;
|
||||||
|
utime.tm_year = years_since_1900;
|
||||||
|
utime.tm_mon = (month > 0) ? (month - 1) : 0;
|
||||||
|
utime.tm_mday = (day > 0) ? (day - 1) : 0;
|
||||||
|
utime.tm_hour = hour;
|
||||||
|
utime.tm_min = minute;
|
||||||
|
utime.tm_sec = second;
|
||||||
|
|
||||||
|
const s32 uts_offset = static_cast<s32>(gmt_offset) * 3600;
|
||||||
|
const time_t uts = std::mktime(&utime) + uts_offset;
|
||||||
|
|
||||||
|
struct tm ltime;
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
localtime_s(<ime, &uts);
|
||||||
|
#else
|
||||||
|
localtime_r(&uts, <ime);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char buf[128];
|
||||||
|
const size_t len = std::strftime(buf, std::size(buf), "%c", <ime);
|
||||||
|
return std::string(buf, len);
|
||||||
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -13,6 +14,7 @@
|
|||||||
class CDImage;
|
class CDImage;
|
||||||
|
|
||||||
class Error;
|
class Error;
|
||||||
|
class ProgressCallback;
|
||||||
|
|
||||||
class IsoReader
|
class IsoReader
|
||||||
{
|
{
|
||||||
@ -104,6 +106,8 @@ public:
|
|||||||
u8 minute;
|
u8 minute;
|
||||||
u8 second;
|
u8 second;
|
||||||
s8 gmt_offset;
|
s8 gmt_offset;
|
||||||
|
|
||||||
|
std::string GetFormattedTime() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ISODirectoryEntryFlags : u8
|
enum ISODirectoryEntryFlags : u8
|
||||||
@ -161,6 +165,11 @@ public:
|
|||||||
bool ReadFile(std::string_view path, std::vector<u8>* data, Error* error = nullptr);
|
bool ReadFile(std::string_view path, std::vector<u8>* data, Error* error = nullptr);
|
||||||
bool ReadFile(const ISODirectoryEntry& de, std::vector<u8>* data, Error* error = nullptr);
|
bool ReadFile(const ISODirectoryEntry& de, std::vector<u8>* data, Error* error = nullptr);
|
||||||
|
|
||||||
|
bool WriteFileToStream(std::string_view path, std::FILE* fp, Error* error = nullptr,
|
||||||
|
ProgressCallback* progress = nullptr);
|
||||||
|
bool WriteFileToStream(const ISODirectoryEntry& de, std::FILE* fp, Error* error = nullptr,
|
||||||
|
ProgressCallback* progress = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::string_view GetDirectoryEntryFileName(const u8* sector, u32 de_sector_offset);
|
static std::string_view GetDirectoryEntryFileName(const u8* sector, u32 de_sector_offset);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user