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; 
}