/* <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); }
/* <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); }
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; }