2015-07-31 14:06:45 -04:00
|
|
|
#include <string.h>
|
2007-12-07 00:26:56 +00:00
|
|
|
#include <limits.h>
|
|
|
|
#include "ISO9660.h"
|
|
|
|
#include "StdStream.h"
|
|
|
|
#include "File.h"
|
|
|
|
#include "DirectoryRecord.h"
|
|
|
|
#include "stricmp.h"
|
|
|
|
|
|
|
|
using namespace ISO9660;
|
|
|
|
|
2015-05-17 21:47:31 -04:00
|
|
|
CISO9660::CISO9660(const BlockProviderPtr& blockProvider)
|
2018-04-30 21:01:23 +01:00
|
|
|
: m_blockProvider(blockProvider)
|
|
|
|
, m_volumeDescriptor(blockProvider.get())
|
|
|
|
, m_pathTable(blockProvider.get(), m_volumeDescriptor.GetLPathTableAddress())
|
2007-12-07 00:26:56 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
CISO9660::~CISO9660()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-07-12 21:59:58 -04:00
|
|
|
void CISO9660::ReadBlock(uint32 address, void* data)
|
2007-12-07 00:26:56 +00:00
|
|
|
{
|
2015-07-04 22:34:32 -04:00
|
|
|
//The buffer is needed to make sure exception handlers
|
|
|
|
//are properly called as some system calls (ie.: ReadFile)
|
|
|
|
//won't generate an exception when trying to write to
|
|
|
|
//a write protected area
|
|
|
|
m_blockProvider->ReadBlock(address, m_blockBuffer);
|
|
|
|
memcpy(data, m_blockBuffer, CBlockProvider::BLOCKSIZE);
|
2007-12-07 00:26:56 +00:00
|
|
|
}
|
|
|
|
|
2014-07-12 21:59:58 -04:00
|
|
|
bool CISO9660::GetFileRecord(CDirectoryRecord* record, const char* filename)
|
2007-12-07 00:26:56 +00:00
|
|
|
{
|
|
|
|
//Remove the first '/'
|
2014-07-12 21:59:58 -04:00
|
|
|
if(filename[0] == '/' || filename[0] == '\\') filename++;
|
2007-12-07 00:26:56 +00:00
|
|
|
|
2014-07-12 21:59:58 -04:00
|
|
|
unsigned int recordIndex = m_pathTable.FindRoot();
|
2007-12-07 00:26:56 +00:00
|
|
|
|
|
|
|
while(1)
|
|
|
|
{
|
|
|
|
//Find the next '/'
|
2014-07-12 21:59:58 -04:00
|
|
|
const char* next = strchr(filename, '/');
|
|
|
|
if(next == nullptr) break;
|
2007-12-07 00:26:56 +00:00
|
|
|
|
2014-07-12 21:59:58 -04:00
|
|
|
std::string dir(filename, next);
|
|
|
|
recordIndex = m_pathTable.FindDirectory(dir.c_str(), recordIndex);
|
|
|
|
if(recordIndex == 0)
|
2007-12-07 00:26:56 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-07-12 21:59:58 -04:00
|
|
|
filename = next + 1;
|
2007-12-07 00:26:56 +00:00
|
|
|
}
|
|
|
|
|
2014-07-12 21:59:58 -04:00
|
|
|
unsigned int address = m_pathTable.GetDirectoryAddress(recordIndex);
|
2007-12-07 00:26:56 +00:00
|
|
|
|
2014-07-12 21:59:58 -04:00
|
|
|
return GetFileRecordFromDirectory(record, address, filename);
|
2007-12-07 00:26:56 +00:00
|
|
|
}
|
|
|
|
|
2014-07-12 21:59:58 -04:00
|
|
|
bool CISO9660::GetFileRecordFromDirectory(CDirectoryRecord* record, uint32 address, const char* filename)
|
2007-12-07 00:26:56 +00:00
|
|
|
{
|
2015-05-17 21:47:31 -04:00
|
|
|
CFile directory(m_blockProvider.get(), address * CBlockProvider::BLOCKSIZE);
|
2007-12-07 00:26:56 +00:00
|
|
|
|
|
|
|
while(1)
|
|
|
|
{
|
2014-07-12 21:59:58 -04:00
|
|
|
CDirectoryRecord entry(&directory);
|
2007-12-07 00:26:56 +00:00
|
|
|
|
2014-07-12 21:59:58 -04:00
|
|
|
if(entry.GetLength() == 0) break;
|
|
|
|
if(strnicmp(entry.GetName(), filename, strlen(filename))) continue;
|
2007-12-07 00:26:56 +00:00
|
|
|
|
2014-07-12 21:59:58 -04:00
|
|
|
(*record) = entry;
|
2007-12-07 00:26:56 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-07-12 21:59:58 -04:00
|
|
|
Framework::CStream* CISO9660::Open(const char* filename)
|
2007-12-07 00:26:56 +00:00
|
|
|
{
|
2014-07-12 21:59:58 -04:00
|
|
|
CDirectoryRecord record;
|
2007-12-07 00:26:56 +00:00
|
|
|
|
2014-07-12 21:59:58 -04:00
|
|
|
if(GetFileRecord(&record, filename))
|
2007-12-07 00:26:56 +00:00
|
|
|
{
|
2015-05-17 21:47:31 -04:00
|
|
|
return new CFile(m_blockProvider.get(), static_cast<uint64>(record.GetPosition()) * CBlockProvider::BLOCKSIZE, record.GetDataLength());
|
2007-12-07 00:26:56 +00:00
|
|
|
}
|
|
|
|
|
2014-07-12 21:59:58 -04:00
|
|
|
return nullptr;
|
2007-12-07 00:26:56 +00:00
|
|
|
}
|
2022-02-25 17:32:56 -05:00
|
|
|
|
|
|
|
Framework::CStream* CISO9660::OpenDirectory(const char* path)
|
|
|
|
{
|
|
|
|
CDirectoryRecord record;
|
|
|
|
|
|
|
|
if(GetFileRecord(&record, path) && record.IsDirectory())
|
|
|
|
{
|
|
|
|
return new CFile(m_blockProvider.get(), static_cast<uint64>(record.GetPosition()) * CBlockProvider::BLOCKSIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|