Ejemplo n.º 1
0
//得到包中某个文件的大小
unsigned int PackFile::getFileSize(const char* szFileName) const
{
	assert(szFileName);
	if(!szFileName || szFileName[0]==0)
	{
		setLastError(AXP_ERR_PARAM);
		return 0;
	}

	//在hash表中搜索
	int nHashPos = getStringPosInHashTable(normaliseName(szFileName, true, true).c_str());
	if(nHashPos < 0) 
	{
		setLastError(AXP_ERR_FILE_NOTFOUND, "%s", szFileName);
		return 0;
	}

	const FILE_HASHNODE& hashNode = m_hashTable[nHashPos];
	
	//得到Block数据
	unsigned int nBlockIndex = getHashNodeBlockIndex(hashNode);
	assert(nBlockIndex < (unsigned int)m_blockTable.size());

	const FILE_BLOCKNODE& blockNode = m_blockTable[nBlockIndex];

	return blockNode.nBlockSize;
}
Ejemplo n.º 2
0
bool PackFile::removeFile(const char* szFileInPak, bool bSaveAtOnce)
{
	assert(szFileInPak);
	if(!szFileInPak || szFileInPak[0]==0 || !m_hPakFile)
	{
		setLastError(AXP_ERR_PARAM);
		return false;
	}

	//只读模式不支持
	if(m_bConst)
	{
		setLastError(AXP_ERR_FILE_ACCESS);
		return false;
	}

	//在hash表中搜索
	int nHashPos = getStringPosInHashTable(normaliseName(szFileInPak, true, true).c_str());
	if(nHashPos < 0)
	{
		setLastError(AXP_ERR_FILE_NOTFOUND, "%s", szFileInPak);
		return false;
	}

	FILE_HASHNODE& hashNode = m_hashTable[nHashPos];

	//Block Node
	unsigned int nBlockPos = getHashNodeBlockIndex(hashNode);
	FILE_BLOCKNODE& blockNode = m_blockTable[nBlockPos];
	
	//设定值
	setBlockNodeUsed(blockNode, false);
	setHashNodeExists(hashNode, false);

	//保存空闲快
	m_mapFreeBlock.insert(std::make_pair(upBoundBlockSize(blockNode.nBlockSize), nBlockPos));
	m_fileHead.nData_HoleSize += upBoundBlockSize(blockNode.nBlockSize);

	//###################################
	//!! 磁盘操作开始 保存文件
	//###################################
	if(!writeBlockNode((unsigned int)nBlockPos)) return false;
	if(!writeHashNode((unsigned int)nHashPos)) return false;
	if(!writeFileHead()) return false;

	if(bSaveAtOnce)
	{
		FlushFileBuffers(m_hPakFile);
	}
	//###################################
	//!!磁盘操作结束
	//###################################

	return true;
}
Ejemplo n.º 3
0
//某文件在包中是否存在
bool PackFile::isFileExists(const char* szFileName) const
{
	assert(szFileName);
	if(!szFileName || szFileName[0]==0)
	{
		setLastError(AXP_ERR_PARAM);
		return false;
	}

	//在hash表中搜索
	int nHashPos = getStringPosInHashTable(normaliseName(szFileName, true, true).c_str());

	return nHashPos >= 0;
}
Ejemplo n.º 4
0
/**********************************************
在Hash表中创建一个字符串的位置,
如果已经存在,则会被替换,如果找不到位置,返回-1
***********************************************/
int PackFile::allocStringPosInHashTable(const char* szString)
{
	assert(szString);
	if(!szString || szString[0]==0 ) return -1;

	//查看是否已经存在
	int nOldPos = getStringPosInHashTable(szString);
	if(nOldPos >= 0) return nOldPos;

	unsigned int nHash = _hashString(HT_OFFSET, szString);		// for pos

	unsigned int nHashA = _hashString(HT_A, szString);	// for check
	unsigned int nHashB = _hashString(HT_B, szString);	// for check again

	unsigned int nHashStart = nHash%HASH_TABLE_SIZE;
	register unsigned int nHashPos = nHashStart;

	do
	{
		FILE_HASHNODE& hashNode = m_hashTable[nHashPos];

		//该位置为空
		if(!getHashNodeExists(hashNode)) 
		{
			hashNode.nHashA = nHashA;
			hashNode.nHashB = nHashB;
			return (int)nHashPos;
		}

		//查找下一个
		nHashPos = (nHashPos+1)%HASH_TABLE_SIZE;
		if(nHashPos == nHashStart)break;	//回到了起点,退出,防止死循环

	}while(true);

	//Hash表已经满了
	return -1;
}
Ejemplo n.º 5
0
//以文件流方式打开包中的一个文件
IStream* PackFile::openFile(const char* szFileName)
{
	//进入关键段,考虑多线程访问
	AUTO_LOCK autoLock(&m_secFile);

	assert(szFileName && m_hPakFile);
	if(!szFileName || szFileName[0]==0 || m_hPakFile==0)
	{
		setLastError(AXP_ERR_PARAM);
		return false;
	}

	//在hash表中搜索
	int nHashPos = getStringPosInHashTable(normaliseName(szFileName, true, true).c_str());
	if(nHashPos < 0) 
	{
		setLastError(AXP_ERR_FILE_NOTFOUND, szFileName);
		return 0;
	}

	const FILE_HASHNODE& hashNode = m_hashTable[nHashPos];

	//得到Block数据
	unsigned int nBlockIndex = getHashNodeBlockIndex(hashNode);
	assert(nBlockIndex < (unsigned int)m_blockTable.size());

	const FILE_BLOCKNODE& blockNode = m_blockTable[nBlockIndex];

	//得到当前线程id
	unsigned int uCurrentThread = (unsigned int)::GetCurrentThreadId();
	FileHandleMap::iterator itHandle = m_mapFileHandle.find(uCurrentThread);	//是否已经有句柄
	if(itHandle == m_mapFileHandle.end())
	{
		//分配一个句柄
		HANDLE hFile = ::CreateFile(m_strFileName.c_str(), 
			GENERIC_READ,
			FILE_SHARE_READ|FILE_SHARE_WRITE,
			0,
			OPEN_EXISTING,
			FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_SEQUENTIAL_SCAN,
			0);
		if(hFile == INVALID_HANDLE_VALUE)
		{
			setLastError(AXP_ERR_FILE_ACCESS, "File=%s, WinErr=%d", m_strFileName.c_str(), ::GetLastError());
			return 0;
		}

		//加入map
		m_mapFileHandle.insert(std::make_pair(uCurrentThread, hFile));
		itHandle = m_mapFileHandle.find(uCurrentThread);
		assert(itHandle != m_mapFileHandle.end());
	}

	//Alloc a datastream
	DataStream* pNewStream = new DataStream(this, 
		itHandle->second, blockNode.nDataOffset, blockNode.nBlockSize, 
		blockNode.nBlockSize<=STREAM_PREREAD_SIZE);
	m_listStream.push_back(pNewStream);

	return (IStream*)pNewStream;
}
Ejemplo n.º 6
0
//文件自检功能
bool PackFile::selfCheck(SELFCHECK_CALLBACK callBack)
{
	if(0==m_hPakFile) 
	{
		setLastError(AXP_ERR_PARAM);
		return false;
	}

	//编辑模式错误
	if(m_fileHead.nEditFlag != 0)
	{
		setLastError(AXP_ERR_FILE_EDITMODE);
		return false;
	}

	//打开List文件
	IStream* pListStream = openFile(LIST_FILENAME);
	if(!pListStream) return false;

	//skip first line
	pListStream->skipLine();

	//read second line
	char szTempLine[MAX_PATH*4] = {0};
	int nLineSize = pListStream->readLine(szTempLine, MAX_PATH*4);
	int nFileCount = atoi(szTempLine);

	//记录已经检查过的HashNode索引
	std::set< unsigned int > setHashNode;
	//记录已经检查过的BlockNode索引
	std::set< unsigned int > setBlockNode;

	//逐行读文件
	int nFileListSize = 0;
	while (!pListStream->eof())
	{
		int nLineLength = pListStream->readLine(szTempLine, MAX_PATH*4);
		if(0 == nLineLength) 
		{
			pListStream->close();
			setLastError(AXP_ERR_FILE_FORMAT, "list file second line=0");
			return false;
		}

		//分析文件描述
		std::vector< std::string > vStringVec;
		convertStringToVector(szTempLine, vStringVec, "|", true, false);
		if(vStringVec.size() != 3) 
		{
			pListStream->close();
			setLastError(AXP_ERR_FILE_FORMAT, "list file=%s", szTempLine);
			return false;
		}

		//获得文件信息
		std::string& strFileName = vStringVec[0];
		unsigned int nFileSize, nFileCRC;
		sscanf(vStringVec[1].c_str(), "%08X", &(nFileSize));
		sscanf(vStringVec[2].c_str(), "%08X", &(nFileCRC));

		//读入文件
		IStream* pFileStream = openFile(strFileName.c_str());	//打开文件
		if(!pFileStream)
		{
			pListStream->close();
			return false;
		}

		unsigned int nStreamSize = pFileStream->size();
		if(nStreamSize != nFileSize)
		{
			pFileStream->close();
			pListStream->close();
			setLastError(AXP_ERR_FILE_FORMAT, "file=%s, sizedif(%d!=%d)", 
				strFileName.c_str(), nStreamSize, nFileSize);
			return false;
		}

		char* pTempBuf = new char[nStreamSize];
		if(nStreamSize != pFileStream->read(pTempBuf, nStreamSize))
		{
			pFileStream->close();
			pListStream->close();
			setLastError(AXP_ERR_FILE_READ, "file=%s", strFileName.c_str());
		}
		pFileStream->close(); pFileStream=0;

		//计算文件实际crc
		unsigned int  nStreamCRC;
		crcMemory32(pTempBuf, nStreamSize, nStreamCRC);
		delete[] pTempBuf; pTempBuf=0;

		if(nStreamCRC != nFileCRC)
		{
//			pFileStream->close();
			pListStream->close();
			setLastError(AXP_ERR_FILE_FORMAT, "file=%s, crcdif(%d!=%d)", 
				strFileName.c_str(), nStreamCRC, nFileCRC);
			return false;
		}

		//保存分析过的文件Hash和Block数据

		//得到Hash数据
		int nHashPos = getStringPosInHashTable(normaliseName(strFileName).c_str());
		setHashNode.insert(nHashPos);

		//得到Block数据
		unsigned int nBlockIndex = getHashNodeBlockIndex(m_hashTable[nHashPos]);
		setBlockNode.insert(nBlockIndex);

		nFileListSize++;
	};
	pListStream->close(); pListStream=0;

	//文件个数检查
	if(nFileListSize != nFileCount)
	{
		setLastError(AXP_ERR_FILE_FORMAT, "file countdif(%d!=%d)", nFileListSize, nFileCount);
		return false;
	}

	//得到(list)的Hash数据
	int nListFileHashPos = getStringPosInHashTable(LIST_FILENAME);
	//得到(list)的Block数据
	unsigned int nListFileBlockIndex = getHashNodeBlockIndex(m_hashTable[nListFileHashPos]);

	//检查是否有未引用的Hash数据
	for(int i=0; i<HASH_TABLE_SIZE; i++)
	{
		const FILE_HASHNODE& hashNode = m_hashTable[i];
		if(!getHashNodeExists(hashNode)) continue;

		if(setHashNode.find(i) != setHashNode.end()) continue;
		if(i==nListFileHashPos) continue;

		//未引用的Hash数据
		setLastError(AXP_ERR_FILE_FORMAT, "unref hashnode(%d)", i);
		return false;
	}

	//检查是否有未引用的BlockNode数据
	for(int i=0; i<(int)m_blockTable.size(); i++)
	{
		const FILE_BLOCKNODE& blockNode = m_blockTable[i];
		if(!getBlockNodeUsed(blockNode)) continue;
		if(setBlockNode.find(i) != setBlockNode.end()) continue;
		if(i==nListFileBlockIndex) continue;

		//未引用的Hash数据
		setLastError(AXP_ERR_FILE_FORMAT, "unref blocknode(%d)", i);
		return false;
	}

	return true;
}