예제 #1
0
/* <2a494> ../engine/hashpak.c:322 */
void HPAK_AddLump(qboolean bUseQueue, char *pakname, struct resource_s *pResource, void *pData, FileHandle_t fpSource)
{
	FileHandle_t iRead;
	FileHandle_t iWrite;
	char name[MAX_PATH];
	char szTempName[MAX_PATH];
	char szOriginalName[MAX_PATH];
	hash_pack_directory_t olddirectory;
	hash_pack_directory_t newdirectory;
	hash_pack_entry_t *pNewEntry;

	byte md5[16];
	MD5Context_t ctx;
	byte *pDiskData;

	if (pakname == NULL)
	{
		Con_Printf("HPAK_AddLump called with invalid arguments:  no .pak filename\n");
		return;
	}
	if (!pResource)
	{
		Con_Printf("HPAK_AddLump called with invalid arguments:  no lump to add\n");
		return;
	}
	if (!pData && !fpSource)
	{
		Con_Printf("HPAK_AddLump called with invalid arguments:  no file handle\n");
		return;
	}
	if (pResource->nDownloadSize < 1024 || (unsigned int)pResource->nDownloadSize > MAX_FILE_SIZE)
	{
		Con_Printf("HPAK_AddLump called with bogus lump, size:  %i\n", pResource->nDownloadSize);
		return;
	}
	Q_memset(&ctx, 0, sizeof(MD5Context_t));
	MD5Init(&ctx);
	if (pData)
		MD5Update(&ctx, (byte *)pData, pResource->nDownloadSize);
	else
	{
		pDiskData = (byte *)Mem_Malloc(pResource->nDownloadSize + 1);
		Q_memset(pDiskData, 0, pResource->nDownloadSize);

		FS_Read(pDiskData, pResource->nDownloadSize, 1, fpSource);
		FS_Seek(fpSource, FS_Tell(fpSource), FILESYSTEM_SEEK_HEAD);

		MD5Update(&ctx, pDiskData, pResource->nDownloadSize);
		Mem_Free(pDiskData);
	}
	MD5Final(md5, &ctx);
	if (Q_memcmp(pResource->rgucMD5_hash, md5, sizeof(md5)) != 0)
	{
		Con_Printf("HPAK_AddLump called with bogus lump, md5 mismatch\n");
		Con_Printf("Purported:  %s\n", MD5_Print(pResource->rgucMD5_hash));
		Con_Printf("Actual   :  %s\n", MD5_Print(md5));
		Con_Printf("Ignoring lump addition\n");
		return;
	}
	if (bUseQueue)
	{
		HPAK_AddToQueue(pakname, pResource, pData, fpSource);
		return;
	}

	Q_snprintf(name, ARRAYSIZE(name), "%s", pakname);
#ifdef REHLDS_FIXES
	name[ARRAYSIZE(name) - 1] = 0;
#endif // REHLDS_FIXES

	COM_DefaultExtension(name, HASHPAK_EXTENSION);
	COM_FixSlashes(name);

	Q_strncpy(szOriginalName, name, ARRAYSIZE(szOriginalName) - 1);
	szOriginalName[ARRAYSIZE(szOriginalName) - 1] = 0;


	iRead = FS_Open(name, "rb");

	if (!iRead)
	{
		HPAK_CreatePak(pakname, pResource, pData, fpSource);
		return;
	}

	COM_StripExtension(name, szTempName);
	COM_DefaultExtension(szTempName, ".hp2");

	iWrite = FS_Open(szTempName, "w+b");
	if (!iWrite)
	{
		FS_Close(iRead);
		Con_Printf("ERROR: couldn't open %s.\n", szTempName);
		return;
	}
	FS_Read(&hash_pack_header, sizeof(hash_pack_header_t), 1, iRead);
	if (hash_pack_header.version != HASHPAK_VERSION)
	{
		FS_Close(iRead);
		FS_Close(iWrite);
		FS_Unlink(szTempName);
		Con_Printf("Invalid .hpk version in HPAK_AddLump\n");
		return;
	}

	FS_Seek(iRead, 0, FILESYSTEM_SEEK_HEAD);
	COM_CopyFileChunk(iWrite, iRead, FS_Size(iRead));
	FS_Seek(iRead, hash_pack_header.nDirectoryOffset, FILESYSTEM_SEEK_HEAD);
	FS_Read(&olddirectory.nEntries, 4, 1, iRead);

	if (olddirectory.nEntries < 1 || (unsigned int)olddirectory.nEntries > MAX_FILE_ENTRIES)
	{
		FS_Close(iRead);
		FS_Close(iWrite);
		FS_Unlink(szTempName);
		Con_Printf("ERROR: .hpk had bogus # of directory entries:  %i\n", olddirectory.nEntries);
		return;
	}

	olddirectory.p_rgEntries = (hash_pack_entry_t *)Mem_Malloc(sizeof(hash_pack_entry_t) * olddirectory.nEntries);

	FS_Read(olddirectory.p_rgEntries, sizeof(hash_pack_entry_t) * olddirectory.nEntries, 1, iRead);
	FS_Close(iRead);

	if (HPAK_FindResource(&olddirectory, pResource->rgucMD5_hash, NULL) != FALSE)
	{
		FS_Close(iWrite);
		FS_Unlink(szTempName);
		Mem_Free(olddirectory.p_rgEntries);
		return;
	}

	newdirectory.nEntries = olddirectory.nEntries + 1;
	newdirectory.p_rgEntries = (hash_pack_entry_t *)Mem_Malloc(sizeof(hash_pack_entry_t) * newdirectory.nEntries);

	Q_memset(newdirectory.p_rgEntries, 0, sizeof(hash_pack_entry_t) * newdirectory.nEntries);
	Q_memcpy(newdirectory.p_rgEntries, olddirectory.p_rgEntries, sizeof(hash_pack_entry_t) * olddirectory.nEntries);

	pNewEntry = NULL;

	for (int i = 0; i < olddirectory.nEntries; i++)
	{
		if (Q_memcmp(pResource->rgucMD5_hash, olddirectory.p_rgEntries[i].resource.rgucMD5_hash, 16) >= 0)
		{
			pNewEntry = &newdirectory.p_rgEntries[i];
#ifndef REHLDS_FIXES
			while (i < olddirectory.nEntries)
			{
				Q_memcpy(&newdirectory.p_rgEntries[i + 1], &olddirectory.p_rgEntries[i], sizeof(hash_pack_entry_t));
				i++;
			}
#else
			Q_memcpy(&newdirectory.p_rgEntries[i + 1], &olddirectory.p_rgEntries[i], (olddirectory.nEntries - i) * sizeof(hash_pack_entry_t));
#endif
			break;
		}
	}

	if (pNewEntry == NULL)
	{
		pNewEntry = &newdirectory.p_rgEntries[newdirectory.nEntries - 1];
	}

	Q_memset(pNewEntry, 0, sizeof(hash_pack_entry_t));
	FS_Seek(iWrite, hash_pack_header.nDirectoryOffset, FILESYSTEM_SEEK_HEAD);

	Q_memcpy(&pNewEntry->resource, pResource, sizeof(resource_t));

	pNewEntry->nOffset = FS_Tell(iWrite);
	pNewEntry->nFileLength = pResource->nDownloadSize;

	if (pData)
		FS_Write(pData, pResource->nDownloadSize, 1, iWrite);

	else COM_CopyFileChunk(iWrite, fpSource, pResource->nDownloadSize);

	hash_pack_header.nDirectoryOffset = FS_Tell(iWrite);

	FS_Write(&newdirectory.nEntries, 4, 1, iWrite);

	for (int j = 0; j < newdirectory.nEntries; j++)
		FS_Write(&newdirectory.p_rgEntries[j], sizeof(hash_pack_entry_t), 1, iWrite);

	if (newdirectory.p_rgEntries)
		Mem_Free(newdirectory.p_rgEntries);

	if (olddirectory.p_rgEntries)
		Mem_Free(olddirectory.p_rgEntries);

	FS_Seek(iWrite, 0, FILESYSTEM_SEEK_HEAD);
	FS_Write(&hash_pack_header, sizeof(hash_pack_header_t), 1, iWrite);
	FS_Close(iWrite);
	FS_Unlink(szOriginalName);
	FS_Rename(szTempName, szOriginalName);
}
예제 #2
0
/* <2a974> ../engine/hashpak.c:598 */
void HPAK_RemoveLump(char *pakname, resource_t *pResource)
{
	FileHandle_t fp;
	FileHandle_t tmp;
	char szTempName[MAX_PATH];
	char szOriginalName[MAX_PATH];
	hash_pack_directory_t olddir;
	hash_pack_directory_t newdir;
	hash_pack_entry_t *oldentry;
	hash_pack_entry_t *newentry;
	int n;
	int i;

	if (pakname == NULL || *pakname == '\0' || pResource == NULL)
	{
		Con_Printf(__FUNCTION__ ":  Invalid arguments\n");
		return;
	}
	HPAK_FlushHostQueue();

#ifdef REHLDS_FIXES
	Q_strncpy(szOriginalName, pakname, ARRAYSIZE(szOriginalName) - 1);
	szOriginalName[ARRAYSIZE(szOriginalName) - 1] = 0;
	COM_DefaultExtension(szOriginalName, HASHPAK_EXTENSION);
#else

	//TODO: Not sure why Cmd_Argv(1) is used since function receives pakname parameter
	char name[MAX_PATH];
	Q_snprintf(name, ARRAYSIZE(name), "%s", Cmd_Argv(1));
	COM_DefaultExtension(name, HASHPAK_EXTENSION);
	Q_strncpy(szOriginalName, name, ARRAYSIZE(szOriginalName) - 1);
	szOriginalName[ARRAYSIZE(szOriginalName) - 1] = 0;

#endif // REHLDS_FIXES

	fp = FS_Open(szOriginalName, "rb");
	if (!fp)
	{
		Con_Printf("Error:  couldn't open HPAK file %s for removal.\n", szOriginalName);
		return;
	}
	COM_StripExtension(szOriginalName, szTempName);
	COM_DefaultExtension(szTempName, ".hp2");

	tmp = FS_Open(szTempName, "w+b");
	if (!tmp)
	{
		FS_Close(fp);
		Con_Printf("ERROR: couldn't create %s.\n", szTempName);
		return;
	}	
	FS_Seek(fp, 0, FILESYSTEM_SEEK_HEAD);
	FS_Seek(tmp, 0, FILESYSTEM_SEEK_HEAD);
	FS_Read(&hash_pack_header, sizeof(hash_pack_header_t), 1, fp);
	FS_Write(&hash_pack_header, sizeof(hash_pack_header_t), 1, tmp);
	if (Q_strncmp(hash_pack_header.szFileStamp, "HPAK", sizeof(hash_pack_header.szFileStamp)))
	{
		FS_Close(fp);
		FS_Close(tmp);
		FS_Unlink(szTempName);
		Con_Printf("%s is not an HPAK file\n", szOriginalName);
		return;
	}
	if (hash_pack_header.version != HASHPAK_VERSION)
	{
		FS_Close(fp);
		FS_Close(tmp);
		FS_Unlink(szTempName);
		Con_Printf("ERROR: HPAK version outdated\n");
		return;
	}
	FS_Seek(fp, hash_pack_header.nDirectoryOffset, FILESYSTEM_SEEK_HEAD);
	FS_Read(&olddir.nEntries, 4, 1, fp);
	if (olddir.nEntries < 1 || (unsigned int)olddir.nEntries > MAX_FILE_ENTRIES)
	{
		FS_Close(fp);
		FS_Close(tmp);
		FS_Unlink(szTempName);
		Con_Printf("ERROR: HPAK had bogus # of directory entries:  %i\n", olddir.nEntries);
		return;
	}
	if (olddir.nEntries == 1)
	{
		FS_Close(fp);
		FS_Close(tmp);
		FS_Unlink(szOriginalName);
		FS_Unlink(szTempName);
		Con_Printf("Removing final lump from HPAK, deleting HPAK:\n  %s\n", szOriginalName);
		return;
	}
	olddir.p_rgEntries = (hash_pack_entry_t *)Mem_Malloc(sizeof(hash_pack_entry_t) * olddir.nEntries);
	FS_Read(olddir.p_rgEntries, sizeof(hash_pack_entry_t) * olddir.nEntries, 1, fp);

	newdir.nEntries = olddir.nEntries - 1;
	newdir.p_rgEntries = (hash_pack_entry_t *)Mem_Malloc(sizeof(hash_pack_entry_t) * newdir.nEntries);
	if (!HPAK_FindResource(&olddir, pResource->rgucMD5_hash, NULL))
	{
		FS_Close(fp);
		FS_Close(tmp);
		FS_Unlink(szTempName);
		Mem_Free(olddir.p_rgEntries);
		Mem_Free(newdir.p_rgEntries);

		Con_Printf("ERROR: HPAK doesn't contain specified lump:  %s\n", pResource->szFileName);
		return;
	}
	Con_Printf("Removing %s from HPAK %s.\n", pResource->szFileName, szOriginalName);
	for (i = 0, n = 0; i < olddir.nEntries; i++)
	{
		oldentry = &olddir.p_rgEntries[i];

		if (Q_memcmp(olddir.p_rgEntries[i].resource.rgucMD5_hash, pResource->rgucMD5_hash, 16))
		{
			newentry = &newdir.p_rgEntries[n++];
			Q_memcpy(newentry, oldentry, sizeof(hash_pack_entry_t));
			newentry->nOffset = FS_Tell(tmp);

			FS_Seek(fp, oldentry->nOffset, FILESYSTEM_SEEK_HEAD);
			COM_CopyFileChunk(tmp, fp, newentry->nFileLength);
		}
	}
	hash_pack_header.nDirectoryOffset = FS_Tell(tmp);
	FS_Write(&newdir.nEntries, 4, 1, tmp);
	for (i = 0; i < newdir.nEntries; i++)
		FS_Write(&newdir.p_rgEntries[i], sizeof(hash_pack_entry_t), 1, tmp);

	FS_Seek(tmp, 0, FILESYSTEM_SEEK_HEAD);
	FS_Write(&hash_pack_header, sizeof(hash_pack_header_t), 1, tmp);
	FS_Close(fp);
	FS_Close(tmp);
	FS_Unlink(szOriginalName);
	FS_Rename(szTempName, szOriginalName);
	Mem_Free(olddir.p_rgEntries);
	Mem_Free(newdir.p_rgEntries);
}
예제 #3
0
파일: FsWrap_.c 프로젝트: beartan/q-sys
FS_i32 FS_FileCpy(const TCHAR*path1, const TCHAR*path2)		//path1: souce file    path2: destination file
{
	FS_FILE *src;
	FS_FILE * dst;
	FS_i32 read_size,write_size;
	FS_i32 src_size, dst_size;
	struct stat buf;
	_DISK_INFO info;
	FS_i8 *buffer;

	if( !strcmp((const char *)path1, (const char *)path2) )
	{
		FS_Debug("FSW_ERROR:can not copy a file to itself\r\n");
		return 0;
	}
	
	if( -1 == FS_Stat( path1, &buf ) ) return 0;

	src_size = buf.st_size;

	if(GetDiskInfo(path2,&info)==-1)
	{
		FS_Debug("FSW_ERROR:getdiskinfo err\r\n");
		return 0;
	}
		
	if(src_size > info.free_size)
	{
		FS_Debug("there is no enough space on the flash!\n\r");
		return 0;
	}

	src = FS_FOpen(path1, FA_READ|FA_OPEN_EXISTING);
	if(0 == src)
	{
		FS_Debug("FSW_ERROR:cannot open the source file\r\n");
		return 0;
	}

	dst = FS_FOpen(path2, FA_CREATE_ALWAYS|FA_WRITE);
	if(0 == dst)
	{
		FS_Debug("FSW_ERROR:cannot create the distance file\r\n");
		FS_FClose(src);
		return 0;
	}

	buffer=Q_Mallco(COPY_FILE_BUFFER);

	do{		
		read_size = FS_FRead(buffer, COPY_FILE_BUFFER,1,src);
		write_size = FS_FWrite(buffer, read_size,1,dst);

		if(write_size < read_size)
		{
			FS_Debug("FSW_ERROR:file write error\r\n");
			Q_Free(buffer);
			goto CP_FILE_ERROR;
		}
	}while(read_size == COPY_FILE_BUFFER);

	Q_Free(buffer);
	FS_FClose(src);
	FS_FClose(dst);

	if( -1 == FS_Stat( path2, &buf ) ) return 0;

	dst_size = buf.st_size;

	if(dst_size < src_size)
	{
		FS_Debug("there is an unkown flash operation during the copyfile!\n\r");
		FS_Unlink(path2);
		return 0;
	}

	return 1;

CP_FILE_ERROR:
	FS_FClose(src);
	FS_FClose(dst);
	return 0;

}