www.pudn.com > potemkin_sourceforPSP.rar > CISOFileSystem.cpp
#include "stdafx.h"
#include "CISOFileSystem.h"
const int sectorSize = 2048;
#pragma pack(push)
#pragma pack(1)
struct DirectoryEntry
{
u8 size;
u8 sectorsInExtendedRecord;
u32 firstDataSectorLE;
u32 firstDataSectorBE;
u32 dataLengthLE;
u32 dataLengthBE;
u8 years;
u8 month;
u8 day;
u8 hour;
u8 minute;
u8 second;
u8 offsetFromGMT;
u8 flags; // 2 = directory
u8 fileUnitSize;
u8 interleaveGap;
u16 volSeqNumberLE;
u16 volSeqNumberBE;
u8 identifierLength; //identifier comes right after
u8 firstIdChar;
};
struct DirectorySector
{
DirectoryEntry entry;
char space[2048-sizeof(DirectoryEntry)];
};
struct VolDescriptor
{
char type;
char cd001[6];
char version;
char sysid[32];
char volid[32];
char zeros[8];
u32 numSectorsLE;
u32 numSectoreBE;
char morezeros[32];
u16 volSetSizeLE;
u16 volSetSizeBE;
u16 volSeqNumLE;
u16 volSeqNumBE;
u16 sectorSizeLE;
u16 sectorSizeBE;
u32 pathTableLengthLE;
u32 pathTableLengthBE;
u16 firstLETableSectorLE;
u16 firstLETableSectorBE;
u16 secondLETableSectorLE;
u16 secondLETableSectorBE;
u16 firstBETableSectorLE;
u16 firstBETableSectorBE;
u16 secondBETableSectorLE;
u16 secondBETableSectorBE;
DirectoryEntry root;
char volumeSetIdentifier[128];
char publisherIdentifier[128];
char dataPreparerIdentifier[128];
char applicationIdentifier[128];
char copyrightFileIdentifier[37];
char abstractFileIdentifier[37];
char bibliographicalFileIdentifier[37];
char volCreationDateTime[17];
char mreModDateTime[17];
char volExpireDateTime[17];
char volEffectiveDateTime[17];
char one;
char zero;
char reserved[512];
char zeroos[653];
};
#pragma pack(pop)
void CISOFileSystem::ReadDirectory(u32 startsector, u32 dirsize, TreeEntry *root)
{
u8 buffer[2048];
int offset=0;
u32 secnum=0;
bool cont=true;
int num = 0;
while (secnum < dirsize/2048)
{
DirectoryEntry &dir = *((DirectoryEntry *)buffer);
fseek(iso, (startsector+secnum) * 2048 + offset, SEEK_SET);
u8 sz;
fread(&sz,1,1,iso);
if (sz==0)
break; //done
fseek(iso, (startsector+secnum) * 2048 + offset, SEEK_SET);
fread(&dir,1,sz,iso);
buffer[2047]=0;
offset += dir.size;
if (offset >= 2048)
{
offset=0;
secnum++;
}
bool isFile = (dir.flags & 2) ? false : true;
char *name = (char *)buffer + 33;
TreeEntry *e = new TreeEntry;
e->name = name;
e->size = dir.dataLengthLE;
e->startingPosition = dir.firstDataSectorLE * 2048;
e->isDirectory = !isFile;
if (isFile)
{
//_dbg_log1_(FILESYS,"File %s.", (char*)buffer + 33);
}
else
{
//_dbg_log1_(FILESYS,"Directory %s.", (char*)buffer + 33);
if (num>1)
ReadDirectory(dir.firstDataSectorLE,dir.dataLengthLE,e);
}
if (num>1) root->children.push_back(e);
num++;
}
}
CISOFileSystem::CISOFileSystem(IHandleAllocator *_hAlloc, std::string _isoFile) : isoFile(_isoFile)
{
hAlloc = _hAlloc;
iso = fopen(_isoFile.c_str(), "rb");
fseek(iso, 2048*16, SEEK_SET);
VolDescriptor desc;
fread(&desc,1,sizeof(VolDescriptor), iso);
int x = sizeof (DirectoryEntry);
if (!memcmp(desc.cd001, "CD001", 5))
{
_dbg_log_(FILESYS, "Looks like a valid ISO!");
}
treeroot = new TreeEntry;
u32 rootSector = desc.root.firstDataSectorLE;
u32 rootSize = desc.root.dataLengthLE;
ReadDirectory(rootSector, rootSize, treeroot);
}
CISOFileSystem::~CISOFileSystem()
{
fclose(iso);
}
CISOFileSystem::TreeEntry *CISOFileSystem::GetFromPath(std::string path)
{
if (path[0] == '/')
path.erase(0,1);
TreeEntry *e = treeroot;
if (path.length() == 0)
return e;
while (true)
{
TreeEntry *ne = 0;
std::string name;
for (size_t i=0; ichildren.size(); i++)
{
std::string n = e->children[i]->name;
if (path.compare(0,n.length(),n) == 0)
{
//yay we got it
ne = e->children[i];
name = n;
}
}
if (ne)
{
e = ne;
int l = name.length();
path.erase(0, l);
if (path.length() == 0)
return e;
path.erase(0, 1);
}
else
{
_dbg_log1_(FILESYS,"File %s not found", path.c_str());
return 0;
}
}
}
u32 CISOFileSystem::OpenFile(std::string filename, FileAccess access)
{
OpenFileEntry entry;
if (access & FILEACCESS_WRITE)
{
_dbg_log1_(FILESYS, "Can't open file %s with write access on an ISO partition", filename.c_str());
return 0;
}
entry.file = GetFromPath(filename);
if (!entry.file)
return 0;
entry.seekPos=0;
u32 newHandle = hAlloc->GetNewHandle();
entries[newHandle] = entry;
return newHandle;
}
void CISOFileSystem::CloseFile(u32 handle)
{
EntryMap::iterator iter = entries.find(handle);
if (iter != entries.end())
{
//CloseHandle((*iter).second.hFile);
hAlloc->FreeHandle(handle);
entries.erase(iter);
}
else
{
//This shouldn't happen...
_dbg_log_(HLE,"Hey, what are you doing? Closing non-open files?");
}
}
bool CISOFileSystem::OwnsHandle(u32 handle)
{
EntryMap::iterator iter = entries.find(handle);
return (iter != entries.end());
}
size_t CISOFileSystem::ReadFile(u32 handle, u8 *pointer, size_t size)
{
EntryMap::iterator iter = entries.find(handle);
if (iter != entries.end())
{
OpenFileEntry &e = iter->second;
fseek(iso, e.file->startingPosition + e.seekPos, SEEK_SET);
if (e.seekPos > e.file->size - size)
{
size = e.file->size - e.seekPos;
}
if (size)
fread(pointer,1,size,iso);
e.seekPos += size;
return size;
}
else
{
//This shouldn't happen...
_dbg_log_(HLE,"Hey, what are you doing? Reading non-open files?");
return 0;
}
}
size_t CISOFileSystem::WriteFile(u32 handle, const u8 *pointer, size_t size)
{
_dbg_log_(HLE,"Hey, what are you doing? You can't write to an ISO!");
return 0;
}
size_t CISOFileSystem::SeekFile(u32 handle, s32 position, FileMove type)
{
EntryMap::iterator iter = entries.find(handle);
if (iter != entries.end())
{
OpenFileEntry &e = iter->second;
switch (type)
{
case FILEMOVE_BEGIN:
e.seekPos = position;
break;
case FILEMOVE_CURRENT:
e.seekPos += position;
break;
case FILEMOVE_END:
e.seekPos = e.file->size + position;
break;
}
return (size_t)e.seekPos;
}
else
{
//This shouldn't happen...
_dbg_log_(HLE,"Hey, what are you doing? Seeking in non-open files?");
return 0;
}
}
FileInfo CISOFileSystem::GetFileInfo(std::string filename)
{
TreeEntry *entry = GetFromPath(filename);
FileInfo x;
if (!entry)
{
x.size=0;
}
else
{
x.name = entry->name;
x.access = FILEACCESS_READ;
x.size = entry->size;
x.type = entry->isDirectory ? FILETYPE_DIRECTORY : FILETYPE_NORMAL;
}
return x;
}
std::vector CISOFileSystem::GetDirListing(std::string path)
{
std::vector myVector;
TreeEntry *entry = GetFromPath(path);
if (!entry)
{
return myVector;
}
// fake the . and ..
FileInfo x;
x.type = FILETYPE_DIRECTORY;
x.name = ".";
myVector.push_back(x);
x.name = "..";
myVector.push_back(x);
for (size_t i=0; ichildren.size(); i++)
{
TreeEntry *e = entry->children[i];
FileInfo x;
x.name = entry->name;
x.access = FILEACCESS_READ;
x.size = entry->size;
x.type = entry->isDirectory ? FILETYPE_DIRECTORY : FILETYPE_NORMAL;
myVector.push_back(x);
}
return myVector;
}