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
//以文件流方式打开包中的一个文件
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.º 4
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;
}
Ejemplo n.º 5
0
//加入/更新一个磁盘文件到包中
bool PackFile::insertContents(const char* szContents, unsigned int nContentsLen, 
					const char* szFileInPak, AXP_CONTENTS sourceType, bool bSaveAtOnce)
{
	assert(szContents && szFileInPak);
	if(!szFileInPak || szFileInPak[0]==0 || !m_hPakFile)
	{
		setLastError(AXP_ERR_PARAM);
		return false;
	}

	if(sourceType==AC_DISKFILE && (!szContents || szContents[0]==0))
	{
		setLastError(AXP_ERR_PARAM);
		return false;
	}

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

	//察看文件是否存在
	if(sourceType==AC_DISKFILE && !PathFileExists(szContents))
	{
		setLastError(AXP_ERR_FILE_NOTFOUND, "%s", szContents);
		return false;
	}

	//在Hash表中分配位置
	int nHashPos = allocStringPosInHashTable(normaliseName(szFileInPak, true, true).c_str());
	if(nHashPos < 0)
	{
		setLastError(AXP_ERR_HASHFULL);
		return false;
	}

	FILE_HASHNODE& hashNode = m_hashTable[nHashPos];

	//获得文件大小
	unsigned int nFileSize = sourceType==AC_DISKFILE ? getDiskFileSize(szContents) : nContentsLen;

	//如果同名文件已经存在
	if(getHashNodeExists(hashNode))
	{
		//Block
		unsigned int nBlockIndex = getHashNodeBlockIndex(hashNode);
		FILE_BLOCKNODE& blockNode = m_blockTable[nBlockIndex];

		//如果尺寸接近
		if(upBoundBlockSize(blockNode.nBlockSize) == upBoundBlockSize(nFileSize))
		{
			//直接替换文件内容

			//###################################
			//!! 磁盘操作开始 保存文件
			//###################################
			if(sourceType==AC_DISKFILE)
			{
				if(!writeDiskFile(blockNode.nDataOffset, 
					upBoundBlockSize(blockNode.nBlockSize), szContents)) return false;
			}
			else
			{
				if(!writeMemory(blockNode.nDataOffset, 
					upBoundBlockSize(blockNode.nBlockSize), szContents, nContentsLen)) return false;
			}

			if(blockNode.nBlockSize != nFileSize)
			{
				//文件尺寸有差异,保存BlockNode数据
				blockNode.nBlockSize = nFileSize;
				if(!writeBlockNode(nBlockIndex)) return false;
			}
			// 确认写入磁盘
			if(bSaveAtOnce)
			{
				FlushFileBuffers(m_hPakFile);
			}
			//###################################
			//!!磁盘操作结束
			//###################################
		}
		//尺寸发生变化,需要删除旧空间,分配新空间
		else 
		{
			//旧块内容设置为不再使用
			setBlockNodeUsed(blockNode, false);

			//将旧块加入空闲块列表
			m_mapFreeBlock.insert(std::make_pair(upBoundBlockSize(blockNode.nBlockSize), nBlockIndex));
			m_fileHead.nData_HoleSize += upBoundBlockSize(blockNode.nBlockSize);

			//重新尝试分配空间
			std::pair< int, int > nNewBlockPair = allocFreeBlock(nFileSize);
			int nNewBlockIndex = nNewBlockPair.first;
			if(nNewBlockIndex < 0) 
			{
				setLastError(AXP_ERR_BLOCKFULL);	//Block表满了
				return false;
			}

			//设置Hash表数据
			setHashNodeExists(hashNode, true);
			setHashNodeBlockIndex(hashNode, nNewBlockIndex);

			//###################################
			//!! 磁盘操作开始 保存文件
			//###################################
			if(nNewBlockPair.second> 0)
			{
				//分割大空间时产生的副空间
				if(!writeBlockNode((unsigned int)(nNewBlockPair.second))) return false;
			}

			//保存文件内容
			if(sourceType==AC_DISKFILE)
			{
				if(!writeDiskFile(m_blockTable[nNewBlockIndex].nDataOffset, 
					upBoundBlockSize(m_blockTable[nNewBlockIndex].nBlockSize), szContents)) return false;
			}
			else
			{
				if(!writeMemory(m_blockTable[nNewBlockIndex].nDataOffset, 
					upBoundBlockSize(m_blockTable[nNewBlockIndex].nBlockSize), 
					szContents, nContentsLen)) return false;
			}

			//文件所在的新的BlockNode
			if(!writeBlockNode((unsigned int)nNewBlockIndex)) return false;
			//原文件所在的BlockNode
			if(nBlockIndex != nNewBlockIndex)
			{
				if(!writeBlockNode((unsigned int)nBlockIndex)) return false;
			}
			//文件的HashNode
			if(!writeHashNode((unsigned int)nHashPos)) return false;
			//文件头
			if(!writeFileHead()) return false;

			// 确认写入磁盘
			if(bSaveAtOnce)
			{
				FlushFileBuffers(m_hPakFile);
			}
			//###################################
			//!!磁盘操作结束
			//###################################
		}
	}
	else
	{
		//获取一块合适空间
		std::pair< int, int > nNewBlockPair = allocFreeBlock(nFileSize);
		int nBlockIndex = nNewBlockPair.first;
		if(nBlockIndex < 0) 
		{
			setLastError(AXP_ERR_BLOCKFULL);	//Block表满了
			return false;
		}

		//设置Hash表数据
		setHashNodeBlockIndex(hashNode, nBlockIndex);
		setHashNodeExists(hashNode, true);
		
		//###################################
		//!! 磁盘操作开始 保存文件
		//###################################
		if(nNewBlockPair.second> 0)
		{
			//分割大空间时产生的副空间
			if(!writeBlockNode((unsigned int)(nNewBlockPair.second))) return false;
		}

		if(sourceType==AC_DISKFILE)
		{
			if(!writeDiskFile(m_blockTable[nBlockIndex].nDataOffset, 
				upBoundBlockSize(m_blockTable[nBlockIndex].nBlockSize), szContents)) return false;
		}
		else
		{
			if(!writeMemory(m_blockTable[nBlockIndex].nDataOffset, 
					upBoundBlockSize(m_blockTable[nBlockIndex].nBlockSize), 
					szContents, nContentsLen)) return false;
		}

		if(!writeBlockNode((unsigned int)nBlockIndex)) return false;
		if(!writeHashNode((unsigned int)nHashPos)) return false;
		if(!writeFileHead()) return false;

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

	return true;
}