Merge pull request 'Use xxhash for file hashing instead of md5' (#48) from xxhash into blankart-dev

Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/48
This commit is contained in:
NepDisk 2025-04-26 21:54:15 +00:00
commit e5386110d3
25 changed files with 7594 additions and 330 deletions

View file

@ -55,6 +55,35 @@ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
2-Clause BSD License
applies to:
- xxHash Library
Copyright (c) 2012-2021 Yann Collet
All rights reserved.
--------------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
0-Clause BSD License

View file

@ -91,6 +91,8 @@ target_link_libraries(SRB2SDL2 PRIVATE tcbrindle::span)
target_link_libraries(SRB2SDL2 PRIVATE fmt::fmt-header-only)
target_link_libraries(SRB2SDL2 PRIVATE Tracy::TracyClient)
target_link_libraries(SRB2SDL2 PRIVATE xxHash::xxhash)
target_compile_definitions(SRB2SDL2 PRIVATE -DUSE_STUN)
if(SRB2_CONFIG_ENABLE_DISCORDRPC)
target_link_libraries(SRB2SDL2 PRIVATE DiscordRPC::DiscordRPC)

View file

@ -36,6 +36,7 @@ extern "C" {
#define WRITEUINT16(p,b) do { UINT16 *p_tmp = ( UINT16 *)p; const UINT16 tv = ( UINT16)(b); memcpy(p, &tv, sizeof( UINT16)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEINT32(p,b) do { INT32 *p_tmp = ( INT32 *)p; const INT32 tv = ( INT32)(b); memcpy(p, &tv, sizeof( INT32)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEUINT32(p,b) do { UINT32 *p_tmp = ( UINT32 *)p; const UINT32 tv = ( UINT32)(b); memcpy(p, &tv, sizeof( UINT32)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEUINT64(p,b) do { UINT64 *p_tmp = ( UINT64 *)p; const UINT64 tv = ( UINT64)(b); memcpy(p, &tv, sizeof( UINT64)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITECHAR(p,b) do { char *p_tmp = ( char *)p; const char tv = ( char)(b); memcpy(p, &tv, sizeof( char)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEFIXED(p,b) do { fixed_t *p_tmp = (fixed_t *)p; const fixed_t tv = (fixed_t)(b); memcpy(p, &tv, sizeof(fixed_t)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEANGLE(p,b) do { angle_t *p_tmp = (angle_t *)p; const angle_t tv = (angle_t)(b); memcpy(p, &tv, sizeof(angle_t)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
@ -46,6 +47,7 @@ extern "C" {
#define WRITEUINT16(p,b) do { UINT16 *p_tmp = ( UINT16 *)p; *p_tmp = ( UINT16)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEINT32(p,b) do { INT32 *p_tmp = ( INT32 *)p; *p_tmp = ( INT32)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEUINT32(p,b) do { UINT32 *p_tmp = ( UINT32 *)p; *p_tmp = ( UINT32)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEUINT64(p,b) do { UINT64 *p_tmp = ( UINT64 *)p; *p_tmp = ( UINT64)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITECHAR(p,b) do { char *p_tmp = ( char *)p; *p_tmp = ( char)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEFIXED(p,b) do { fixed_t *p_tmp = (fixed_t *)p; *p_tmp = (fixed_t)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEANGLE(p,b) do { angle_t *p_tmp = (angle_t *)p; *p_tmp = (angle_t)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
@ -59,6 +61,7 @@ extern "C" {
#define READUINT16(p) ({ const UINT16 *p_tmp = (const UINT16 *)p; UINT16 b; memcpy(&b, p, sizeof( UINT16)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; })
#define READINT32(p) ({ const INT32 *p_tmp = (const INT32 *)p; INT32 b; memcpy(&b, p, sizeof( INT32)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; })
#define READUINT32(p) ({ const UINT32 *p_tmp = (const UINT32 *)p; UINT32 b; memcpy(&b, p, sizeof( UINT32)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; })
#define READUINT64(p) ({ const UINT64 *p_tmp = (const UINT64 *)p; UINT64 b; memcpy(&b, p, sizeof( UINT64)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; })
#define READCHAR(p) ({ const char *p_tmp = (const char *)p; char b; memcpy(&b, p, sizeof( char)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; })
#define READFIXED(p) ({ const fixed_t *p_tmp = (const fixed_t *)p; fixed_t b; memcpy(&b, p, sizeof(fixed_t)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; })
#define READANGLE(p) ({ const angle_t *p_tmp = (const angle_t *)p; angle_t b; memcpy(&b, p, sizeof(angle_t)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; })
@ -69,6 +72,7 @@ extern "C" {
#define READUINT16(p) ((const UINT16*)(*(const void**)(&(p)) = (const void*)&((const UINT16*)(p))[1]))[-1]
#define READINT32(p) ((const INT32*)(*(const void**)(&(p)) = (const void*)&((const INT32*)(p))[1]))[-1]
#define READUINT32(p) ((const UINT32*)(*(const void**)(&(p)) = (const void*)&((const UINT32*)(p))[1]))[-1]
#define READUINT64(p) ((const UINT64*)(*(const void**)(&(p)) = (const void*)&((const UINT64*)(p))[1]))[-1]
#define READCHAR(p) ((const char*)(*(const void**)(&(p)) = (const void*)&((const char*)(p))[1]))[-1]
#define READFIXED(p) ((const fixed_t*)(*(const void**)(&(p)) = (const void*)&((const fixed_t*)(p))[1]))[-1]
#define READANGLE(p) ((const angle_t*)(*(const void**)(&(p)) = (const void*)&((const angle_t*)(p))[1]))[-1]
@ -96,12 +100,26 @@ FUNCINLINE static ATTRINLINE void writelong(void *ptr, INT32 val)
cp[3] = val;
}
FUNCINLINE static ATTRINLINE void writelonglong(void *ptr, INT64 val)
{
SINT8 *cp = ptr;
cp[0] = val; val >>= 8;
cp[1] = val; val >>= 8;
cp[2] = val; val >>= 8;
cp[3] = val; val >>= 8;
cp[4] = val; val >>= 8;
cp[5] = val; val >>= 8;
cp[6] = val; val >>= 8;
cp[7] = val;
}
#define WRITEUINT8(p,b) do { UINT8 *p_tmp = ( UINT8 *)p; *p_tmp = ( UINT8)(b) ; p_tmp++; p = (void *)p_tmp;} while (0)
#define WRITESINT8(p,b) do { SINT8 *p_tmp = ( SINT8 *)p; *p_tmp = ( SINT8)(b) ; p_tmp++; p = (void *)p_tmp;} while (0)
#define WRITEINT16(p,b) do { INT16 *p_tmp = ( INT16 *)p; writeshort (p, ( INT16)(b)); p_tmp++; p = (void *)p_tmp;} while (0)
#define WRITEUINT16(p,b) do { UINT16 *p_tmp = ( UINT16 *)p; writeshort (p, ( UINT16)(b)); p_tmp++; p = (void *)p_tmp;} while (0)
#define WRITEINT32(p,b) do { INT32 *p_tmp = ( INT32 *)p; writelong (p, ( INT32)(b)); p_tmp++; p = (void *)p_tmp;} while (0)
#define WRITEUINT32(p,b) do { UINT32 *p_tmp = ( UINT32 *)p; writelong (p, ( UINT32)(b)); p_tmp++; p = (void *)p_tmp;} while (0)
#define WRITEUINT64(p,b) do { UINT64 *p_tmp = ( UINT64 *)p; writelonglong(p,(UINT64)(b)); p_tmp++; p = (void *)p_tmp;} while (0)
#define WRITECHAR(p,b) do { char *p_tmp = ( char *)p; *p_tmp = ( char)(b) ; p_tmp++; p = (void *)p_tmp;} while (0)
#define WRITEFIXED(p,b) do {fixed_t *p_tmp = (fixed_t *)p; writelong (p, (fixed_t)(b)); p_tmp++; p = (void *)p_tmp;} while (0)
#define WRITEANGLE(p,b) do {angle_t *p_tmp = (angle_t *)p; writelong (p, (angle_t)(b)); p_tmp++; p = (void *)p_tmp;} while (0)
@ -134,12 +152,19 @@ FUNCINLINE static ATTRINLINE UINT32 readulong(void *ptr)
return (ucp[3] << 24) | (ucp[2] << 16) | (ucp[1] << 8) | ucp[0];
}
FUNCINLINE static ATTRINLINE UINT64 readulonglong(void *ptr)
{
UINT8 *ucp = ptr;
return (ucp[7] << 56) | (ucp[6] << 48) | (ucp[5] << 40) | (ucp[4] << 32) | (ucp[3] << 24) | (ucp[2] << 16) | (ucp[1] << 8) | ucp[0];
}
#define READUINT8(p) ((const UINT8*)(p = (const void*)&((const UINT8*)p)[1]))[-1]
#define READSINT8(p) ((const SINT8*)(p = (const void*)&((const SINT8*)p)[1]))[-1]
#define READINT16(p) readshort(&((const INT16*)(p = (const void*)&((const INT16*)p)[1]))[-1])
#define READUINT16(p) readushort(&((const UINT16*)(p = (const void*)&((const UINT16*)p)[1]))[-1])
#define READINT32(p) readlong(&((const INT32*)(p = (const void*)&((const INT32*)p)[1]))[-1])
#define READUINT32(p) readulong(&((const UINT32*)(p = (const void*)&((const UINT32*)p)[1]))
#define READUINT64(p) readulonglong(&((const UINT64*)(p = (const void*)&((const UINT64*)p)[1]))
#define READCHAR(p) ((const char*)(p = (const void*)&((const char*)p)[1]))[-1]
#define READFIXED(p) readlong(&((const fixed_t*)(p = (const void*)&((const fixed_t*)p)[1]))[-1])
#define READANGLE(p) readulong(&((const angle_t*)(p = (const void*)&((const angle_t*)p)[1]))[-1])

View file

@ -846,7 +846,7 @@ static void COM_Exec_f(void)
// Now try by searching the file path
// filename is modified with the full found path
strcpy(filename, COM_Argv(1));
if (findfile(filename, NULL, true) != FS_NOTFOUND)
if (findfile(filename, 0, true) != FS_NOTFOUND)
FIL_ReadFile(filename, &buf);
if (!buf)

View file

@ -951,7 +951,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
CopyCaretColors(netbuffer->u.serverinfo.servername, cv_servername.string,
MAXSERVERNAME);
M_Memcpy(netbuffer->u.serverinfo.mapmd5, mapmd5, 16);
netbuffer->u.serverinfo.maphash = maphash;
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) && !(mapheaderinfo[prevmap]->zonttl[0]))
netbuffer->u.serverinfo.iszone = 1;
@ -1637,7 +1637,7 @@ static boolean CL_FinishedFileList(void)
totalfilesrequestedsize = 0;
for (i = 0; i < fileneedednum; i++)
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_BADHASH)
{
totalfilesrequestednum++;
totalfilesrequestedsize += fileneeded[i].totalsize;
@ -1802,7 +1802,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
if (http_source[0])
{
for (i = 0; i < fileneedednum; i++)
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_BADHASH)
{
curl_transfers++;
}
@ -1814,7 +1814,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
case CL_DOWNLOADHTTPFILES:
waitmore = false;
for (i = 0; i < fileneedednum; i++)
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_BADHASH)
{
if (!curl_running)
CURLPrepareFile(http_source, i);

View file

@ -284,7 +284,7 @@ struct serverinfo_pak
tic_t leveltime;
char servername[MAXSERVERNAME];
char maptitle[33];
unsigned char mapmd5[16];
UINT64 maphash;
UINT8 actnum;
UINT8 iszone;
char httpsource[MAX_MIRROR_LENGTH]; // HTTP URL to download from, always defined for compatibility

View file

@ -81,14 +81,14 @@
#include <tracy/tracy/Tracy.hpp>
// Put hashes here to get them out of header hell.
#define ASSET_HASH_MAIN_PK3 "6e6de1491bdd5410adedbe6e446a8990"
#define ASSET_HASH_SRB2_SRB "c1b9577687f8a795104aef4600720ea7"
#define ASSET_HASH_GFX_KART "06f86ee16136eb8a7043b15001797034"
#define ASSET_HASH_TEXTURES_KART "abb53d56aba47c3a8cb0f764da1c8b80"
#define ASSET_HASH_CHARS_KART "e2c428347dde52858a3dacd29fc5b964"
#define ASSET_HASH_MAPS_KART "d051e55141ba736582228c456953cd98"
#define ASSET_HASH_MAIN_PK3 0x52f03a1c98030bb0
#define ASSET_HASH_SRB2_SRB 0xf3ec1ea4d0eca4a9
#define ASSET_HASH_GFX_KART 0xc91b0d43f5ba131f
#define ASSET_HASH_TEXTURES_KART 0xb4211b2f32b6a291
#define ASSET_HASH_CHARS_KART 0x1e68a3e01aa5c68b
#define ASSET_HASH_MAPS_KART 0x38558ed00da41ce9
#ifdef USE_PATCH_FILE
#define ASSET_HASH_PATCH_PK3 "00000000000000000000000000000000"
#define ASSET_HASH_PATCH_PK3 0x0000000000000000
#endif
#ifdef CMAKECONFIG
@ -1193,7 +1193,7 @@ static void IdentifyVersion(void)
snprintf(configfile, sizeof configfile, "%s" PATHSEP CONFIGFILENAME, srb2waddir);
configfile[sizeof configfile - 1] = '\0';
// if you change the ordering of this or add/remove a file, be sure to update the md5
// if you change the ordering of this or add/remove a file, be sure to update the hash
// checking in D_SRB2Main
D_AddFile(startupiwads, va(pandf,srb2waddir,GRAPHICSNAME));
@ -1483,16 +1483,16 @@ void D_SRB2Main(void)
D_CleanFile(startupiwads);
#ifndef DEVELOP
// Check MD5s of autoloaded files
// Note: Do not add any files that ignore MD5!
W_VerifyFileMD5(MAINWAD_SRB2, ASSET_HASH_SRB2_SRB);
W_VerifyFileMD5(MAINWAD_GFX, ASSET_HASH_GFX_KART);
W_VerifyFileMD5(MAINWAD_TEXTURES, ASSET_HASH_TEXTURES_KART);
W_VerifyFileMD5(MAINWAD_CHARS, ASSET_HASH_CHARS_KART);
W_VerifyFileMD5(MAINWAD_MAPS, ASSET_HASH_MAPS_KART);
W_VerifyFileMD5(MAINWAD_MAIN, ASSET_HASH_MAIN_PK3);
// Check hashes of autoloaded files
// Note: Do not add any files that ignore hashing!
W_VerifyFileHash(MAINWAD_SRB2, ASSET_HASH_SRB2_SRB);
W_VerifyFileHash(MAINWAD_GFX, ASSET_HASH_GFX_KART);
W_VerifyFileHash(MAINWAD_TEXTURES, ASSET_HASH_TEXTURES_KART);
W_VerifyFileHash(MAINWAD_CHARS, ASSET_HASH_CHARS_KART);
W_VerifyFileHash(MAINWAD_MAPS, ASSET_HASH_MAPS_KART);
W_VerifyFileHash(MAINWAD_MAIN, ASSET_HASH_MAIN_PK3);
#ifdef USE_PATCH_FILE
W_VerifyFileMD5(MAINWAD_PATCH, ASSET_HASH_PATCH_PK3);
W_VerifyFileHash(MAINWAD_PATCH, ASSET_HASH_PATCH_PK3);
#endif
#endif //ifndef DEVELOP

View file

@ -50,7 +50,6 @@
#include "lua_hook.h"
#include "m_cond.h"
#include "m_anigif.h"
#include "md5.h"
// SRB2kart
#include "k_kart.h"
@ -201,7 +200,7 @@ static void Command_Displayplayer_f(void);
static void Command_ExitLevel_f(void);
static void Command_Showmap_f(void);
static void Command_Mapmd5_f(void);
static void Command_Maphash_f(void);
static void Command_Teamchange_f(void);
static void Command_Teamchange2_f(void);
@ -788,7 +787,7 @@ void D_RegisterServerCommands(void)
COM_AddCommand("retry", Command_Retry_f);
COM_AddCommand("exitlevel", Command_ExitLevel_f);
COM_AddCommand("showmap", Command_Showmap_f);
COM_AddCommand("mapmd5", Command_Mapmd5_f);
COM_AddCommand("maphash", Command_Maphash_f);
COM_AddCommand("addfile", Command_Addfile);
COM_AddCommand("listwad", Command_ListWADS_f);
@ -4487,10 +4486,10 @@ static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum)
READSTRINGN(*cp, filename, 255);
// Maybe add md5 support?
// Maybe add hashing support?
if (strstr(filename, ".soc") != NULL)
{
ncs = findfile(filename,NULL,true);
ncs = findfile(filename, 0, true);
if (ncs != FS_FOUND)
{
@ -4627,29 +4626,19 @@ static void Command_Addfile(void)
WRITESTRINGN(buf_p,p,240);
// calculate and check md5
// calculate and check the hash
{
UINT8 md5sum[16];
#ifdef NOMD5
memset(md5sum,0,16);
UINT64 filehash;
#ifdef NOFILEHASH
filehash = 0;
#else
FILE *fhandle;
boolean valid = true;
if ((fhandle = W_OpenWadFile(&fn, true)) != NULL)
{
tic_t t = I_GetTime();
CONS_Debug(DBG_SETUP, "Making MD5 for %s\n",fn);
md5_stream(fhandle, md5sum);
CONS_Debug(DBG_SETUP, "MD5 calc for %s took %f second\n", fn, (float)(I_GetTime() - t)/TICRATE);
fclose(fhandle);
}
else // file not found
continue;
if (!W_MakeFileHash(fn, true, &filehash))
continue; // file not found
for (i = 0; i < numwadfiles; i++)
{
if (!memcmp(wadfiles[i]->md5sum, md5sum, 16))
if (wadfiles[i]->hash == filehash)
{
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn);
valid = false;
@ -4662,7 +4651,7 @@ static void Command_Addfile(void)
continue;
}
#endif
WRITEMEM(buf_p, md5sum, 16);
WRITEUINT64(buf_p, filehash);
}
WRITEUINT8(buf_p, compat);
@ -4680,13 +4669,13 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
{
char filename[241];
filestatus_t ncs = FS_NOTCHECKED;
UINT8 md5sum[16];
UINT64 filehash;
boolean kick = false;
boolean toomany = false;
INT32 i,j;
READSTRINGN(*cp, filename, 240);
READMEM(*cp, md5sum, 16);
filehash = READUINT64(cp);
wadcompat_t compat = READUINT8(*cp);
// Only the server processes this message.
@ -4709,7 +4698,7 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
if (numwadfiles >= MAX_WADFILES)
toomany = true;
else
ncs = findfile(filename,md5sum,true);
ncs = findfile(filename, filehash, true);
if (ncs != FS_FOUND || toomany)
{
@ -4719,7 +4708,7 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
sprintf(message, M_GetText("Too many files loaded to add %s\n"), filename);
else if (ncs == FS_NOTFOUND)
sprintf(message, M_GetText("The server doesn't have %s\n"), filename);
else if (ncs == FS_MD5SUMBAD)
else if (ncs == FS_BADHASH)
sprintf(message, M_GetText("Checksum mismatch on %s\n"), filename);
else
sprintf(message, M_GetText("Unknown error finding wad file (%s)\n"), filename);
@ -4740,10 +4729,10 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
{
char filename[241];
filestatus_t ncs = FS_NOTCHECKED;
UINT8 md5sum[16];
UINT64 filehash;
READSTRINGN(*cp, filename, 240);
READMEM(*cp, md5sum, 16);
filehash = READUINT64(*cp);
wadcompat_t compat = READUINT8(*cp);
if (playernum != serverplayer)
@ -4754,7 +4743,7 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
return;
}
ncs = findfile(filename,md5sum,true);
ncs = findfile(filename, filehash, true);
if (ncs != FS_FOUND || !P_AddWadFile(filename, compat))
{
@ -4769,7 +4758,7 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
CONS_Printf(M_GetText("The server tried to add %s,\nbut you don't have this file.\nYou need to find it in order\nto play on this server."), filename);
M_StartMessage(va("The server added a file \n(%s)\nthat you do not have.\n\nPress ESC\n",filename), NULL, MM_NOTHING);
}
else if (ncs == FS_MD5SUMBAD)
else if (ncs == FS_BADHASH)
{
CONS_Printf(M_GetText("Checksum mismatch while loading %s.\nMake sure you have the copy of\nthis file that the server has.\n"), filename);
M_StartMessage(va("Checksum mismatch while loading \n%s.\nThe server seems to have a\ndifferent version of this file.\n\nPress ESC\n",filename), NULL, MM_NOTHING);
@ -5434,16 +5423,10 @@ static void Command_Showmap_f(void)
CONS_Printf(M_GetText("You must be in a level to use this.\n"));
}
static void Command_Mapmd5_f(void)
static void Command_Maphash_f(void)
{
if (gamestate == GS_LEVEL)
{
INT32 i;
char md5tmp[33];
for (i = 0; i < 16; ++i)
sprintf(&md5tmp[i*2], "%02x", mapmd5[i]);
CONS_Printf("%s: %s\n", G_BuildMapName(gamemap), md5tmp);
}
CONS_Printf("%s: " HASHFMT "\n", G_BuildMapName(gamemap), maphash);
else
CONS_Printf(M_GetText("You must be in a level to use this.\n"));
}

View file

@ -51,7 +51,6 @@
#include "p_setup.h"
#include "m_misc.h"
#include "m_menu.h"
#include "md5.h"
#include "filesrch.h"
#include <errno.h>
@ -104,7 +103,7 @@ static tic_t lasttimeackpacketsent = 0;
typedef struct
{
char filename[MAX_WADPATH];
UINT8 md5sum[16];
UINT64 hash;
boolean *receivedfragments;
UINT32 fragmentsize;
UINT32 currentsize;
@ -207,7 +206,7 @@ UINT8 *PutFileNeeded(UINT16 firstfile)
count++;
WRITEUINT32(p, wadfiles[i]->filesize);
WRITESTRINGN(p, wadfilename, MAX_WADPATH);
WRITEMEM(p, wadfiles[i]->md5sum, 16);
WRITEUINT64(p, wadfiles[i]->hash);
WRITEUINT8(p, wadfiles[i]->compatmode);
}
if (netbuffer->packettype == PT_MOREFILESNEEDED)
@ -241,7 +240,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 fi
fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size
fileneeded[i].file = NULL; // The file isn't open yet
READSTRINGN(p, fileneeded[i].filename, MAX_WADPATH); // The next bytes are the file name
READMEM(p, fileneeded[i].md5sum, 16); // The last 16 bytes are the file checksum
fileneeded[i].hash = READUINT64(p); // The last 8 bytes are the file checksum
fileneeded[i].compatmode = READUINT8(p);
}
}
@ -255,7 +254,7 @@ void CL_PrepareDownloadSaveGame(const char *tmpsave)
fileneeded[0].justdownloaded = false;
fileneeded[0].totalsize = UINT32_MAX;
fileneeded[0].file = NULL;
memset(fileneeded[0].md5sum, 0, 16);
fileneeded[0].hash = 0;
strcpy(fileneeded[0].filename, tmpsave);
}
@ -295,19 +294,12 @@ boolean CL_CheckDownloadable(void)
{
CONS_Printf(" * \"%s\" (%dK)", fileneeded[i].filename, fileneeded[i].totalsize >> 10);
if (fileneeded[i].status == FS_MD5SUMBAD)
CONS_Printf(M_GetText(" wrong version, md5: "));
if (fileneeded[i].status == FS_BADHASH)
CONS_Printf(M_GetText(" wrong version, hash: "));
else
CONS_Printf(M_GetText(" not found, md5: "));
CONS_Printf(M_GetText(" not found, hash: "));
{
INT32 j;
char md5tmp[33];
for (j = 0; j < 16; j++)
sprintf(&md5tmp[j*2], "%02x", fileneeded[i].md5sum[j]);
CONS_Printf("%s", md5tmp);
}
CONS_Printf("\n");
CONS_Printf(HASHFMT "\n", fileneeded[i].hash);
}
switch (dlstatus)
@ -335,7 +327,7 @@ static boolean CL_CanResumeDownload(fileneeded_t *file)
{
return pauseddownload
&& !strcmp(pauseddownload->filename, file->filename) // Same name
&& !memcmp(pauseddownload->md5sum, file->md5sum, 16) // Same checksum
&& pauseddownload->hash == file->hash // Same checksum
&& pauseddownload->fragmentsize == file->fragmentsize; // Same fragment size
}
@ -388,7 +380,7 @@ boolean CL_SendFileRequest(void)
return false;
}
#endif
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD || fileneeded[i].status == FS_FALLBACK))
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_BADHASH || fileneeded[i].status == FS_FALLBACK))
{
// Error check for the first time around.
totalfreespaceneeded += fileneeded[i].totalsize;
@ -419,7 +411,7 @@ tryagain:
for (i = 0; i < fileneedednum; i++)
{
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD || fileneeded[i].status == FS_FALLBACK))
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_BADHASH || fileneeded[i].status == FS_FALLBACK))
{
// Pre-prepare.
size_t checklen;
@ -457,7 +449,7 @@ tryagain:
CONS_Printf("Direct download - missing files are as follows:\n");
for (i = 0; i < fileneedednum; i++)
{
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD || fileneeded[i].status == FS_FALLBACK || fileneeded[i].status == FS_REQUESTED)) // FS_REQUESTED added
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_BADHASH || fileneeded[i].status == FS_FALLBACK || fileneeded[i].status == FS_REQUESTED)) // FS_REQUESTED added
CONS_Printf(" %s\n", fileneeded[i].filename);
}
return false;
@ -571,8 +563,8 @@ INT32 CL_CheckFiles(void)
if (i >= fileneedednum || j >= numwadfiles)
return 2;
// For the sake of speed, only bother with a md5 check
if (memcmp(wadfiles[j]->md5sum, fileneeded[i].md5sum, 16))
// For the sake of speed, only bother with a hash check
if (wadfiles[j]->hash != fileneeded[i].hash)
return 2;
// compatmode has to match too!
@ -590,7 +582,7 @@ INT32 CL_CheckFiles(void)
for (i = 0; i < fileneedednum; i++)
{
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD || fileneeded[i].status == FS_FALLBACK)
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_BADHASH || fileneeded[i].status == FS_FALLBACK)
downloadrequired = true;
if (fileneeded[i].status != FS_OPEN)
@ -611,7 +603,7 @@ INT32 CL_CheckFiles(void)
{
nameonly(strcpy(wadfilename, wadfiles[j]->filename));
if (!stricmp(wadfilename, fileneeded[i].filename) &&
!memcmp(wadfiles[j]->md5sum, fileneeded[i].md5sum, 16))
wadfiles[j]->hash == fileneeded[i].hash)
{
CONS_Debug(DBG_NETPLAY, "already loaded\n");
fileneeded[i].status = FS_OPEN;
@ -621,7 +613,7 @@ INT32 CL_CheckFiles(void)
packetsize += nameonlylength(fileneeded[i].filename) + 22;
fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].md5sum, true);
fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].hash, true);
CONS_Debug(DBG_NETPLAY, "found %d\n", fileneeded[i].status);
return 4;
}
@ -655,7 +647,7 @@ boolean CL_LoadServerFiles(void)
fileneeded[i].status = FS_OPEN;
return false;
}
else if (fileneeded[i].status == FS_MD5SUMBAD)
else if (fileneeded[i].status == FS_BADHASH)
I_Error("Wrong version of file %s", fileneeded[i].filename);
else
{
@ -866,7 +858,7 @@ void CL_PrepareDownloadLuaFile(void)
fileneeded[0].justdownloaded = false;
fileneeded[0].totalsize = UINT32_MAX;
fileneeded[0].file = NULL;
memset(fileneeded[0].md5sum, 0, 16);
fileneeded[0].hash = 0;
strcpy(fileneeded[0].filename, luafiletransfers->realfilename);
// Make sure all directories in the file path exist
@ -1551,8 +1543,8 @@ void PT_FileFragment(void)
case FS_OPEN:
s = "FS_OPEN";
break;
case FS_MD5SUMBAD:
s = "FS_MD5SUMBAD";
case FS_BADHASH:
s = "FS_BADHASH";
break;
default:
s = "unknown";
@ -1609,7 +1601,7 @@ void CloseNetFile(void)
I_Error("CloseNetFile: No more memory\n");
strcpy(pauseddownload->filename, fileneeded[i].filename);
memcpy(pauseddownload->md5sum, fileneeded[i].md5sum, 16);
pauseddownload->hash = fileneeded[i].hash;
pauseddownload->currentsize = fileneeded[i].currentsize;
pauseddownload->receivedfragments = fileneeded[i].receivedfragments;
pauseddownload->fragmentsize = fileneeded[i].fragmentsize;
@ -1694,66 +1686,57 @@ size_t nameonlylength(const char *s)
#define O_BINARY 0
#endif
filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum)
filestatus_t checkfilehash(const char *filename, UINT64 wantedhash)
{
#if defined (NOMD5)
(void)wantedmd5sum;
#ifdef NOFILEHASH
(void)wantedhash;
(void)filename;
return FS_FOUND;
#else
FILE *fhandle;
UINT8 md5sum[16];
if (!wantedmd5sum)
if (!wantedhash)
return FS_FOUND;
fhandle = fopen(filename, "rb");
if (fhandle)
{
md5_stream(fhandle,md5sum);
fclose(fhandle);
if (!memcmp(wantedmd5sum, md5sum, 16))
return FS_FOUND;
return FS_MD5SUMBAD;
}
I_Error("Couldn't open %s for md5 check", filename);
UINT64 filehash;
if (W_MakeFileHash(filename, false, &filehash) && wantedhash == filehash)
return FS_FOUND;
else
return FS_BADHASH;
#endif
return FS_FOUND; // will never happen, but makes the compiler shut up
}
// Rewritten by Monster Iestyn to be less stupid
// Note: if completepath is true, "filename" is modified, but only if FS_FOUND is going to be returned
// (Don't worry about WinCE's version of filesearch, nobody cares about that OS anymore)
filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean completepath)
filestatus_t findfile(char *filename, UINT64 wantedhash, boolean completepath)
{
filestatus_t homecheck; // store result of last file search
boolean badmd5 = false; // store whether md5 was bad from either of the first two searches (if nothing was found in the third)
boolean badhash = false; // store whether hash was bad from either of the first two searches (if nothing was found in the third)
// first, check SRB2's "home" directory
homecheck = filesearch(filename, srb2home, wantedmd5sum, completepath, 10);
homecheck = filesearch(filename, srb2home, wantedhash, completepath, 10);
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
return FS_FOUND;
else if (homecheck == FS_MD5SUMBAD) // file has a bad md5; move on and look for a file with the right md5
badmd5 = true;
else if (homecheck == FS_BADHASH) // file has a bad hash; move on and look for a file with the right hash
badhash = true;
// if not found at all, just move on without doing anything
// next, check SRB2's "path" directory
homecheck = filesearch(filename, srb2path, wantedmd5sum, completepath, 10);
homecheck = filesearch(filename, srb2path, wantedhash, completepath, 10);
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
return FS_FOUND;
else if (homecheck == FS_MD5SUMBAD) // file has a bad md5; move on and look for a file with the right md5
badmd5 = true;
else if (homecheck == FS_BADHASH) // file has a bad hash; move on and look for a file with the right hash
badhash = true;
// if not found at all, just move on without doing anything
// finally check "." directory
homecheck = filesearch(filename, ".", wantedmd5sum, completepath, 10);
homecheck = filesearch(filename, ".", wantedhash, completepath, 10);
if (homecheck != FS_NOTFOUND) // if not found this time, fall back on the below return statement
return homecheck; // otherwise return the result we got
return (badmd5 ? FS_MD5SUMBAD : FS_NOTFOUND); // md5 sum bad or file not found
return (badhash ? FS_BADHASH : FS_NOTFOUND); // hash is bad or file not found
}
#ifdef HAVE_CURL
@ -1911,7 +1894,7 @@ void CURLGetFile(void)
{
fclose(curl_curfile->file);
if (checkfilemd5(curl_curfile->filename, curl_curfile->md5sum) == FS_MD5SUMBAD)
if (checkfilehash(curl_curfile->filename, curl_curfile->hash) == FS_BADHASH)
{
CONS_Alert(CONS_ERROR, M_GetText("HTTP Download of %s finished but is corrupt or has been modified\n"), filename);
curl_curfile->status = FS_FALLBACK;

View file

@ -37,7 +37,7 @@ typedef enum
FS_REQUESTED,
FS_DOWNLOADING,
FS_OPEN, // Is opened and used in w_wad
FS_MD5SUMBAD,
FS_BADHASH,
FS_FALLBACK, // HTTP failed
} filestatus_t;
@ -45,7 +45,7 @@ struct fileneeded_t
{
UINT8 willsend; // Is the server willing to send it?
char filename[MAX_WADPATH];
UINT8 md5sum[16];
UINT64 hash;
filestatus_t status; // The value returned by recsearch
boolean justdownloaded; // To prevent late fragments from causing an I_Error
boolean compatmode;
@ -155,9 +155,9 @@ void Command_Downloads_f(void);
boolean fileexist(char *filename, time_t ptime);
// Search a file in the wadpath, return FS_FOUND when found
filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum,
filestatus_t findfile(char *filename, UINT64 wantedhash,
boolean completepath);
filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum);
filestatus_t checkfilehash(const char *filename, UINT64 wantedhash);
void nameonly(char *s);
size_t nameonlylength(const char *s);

View file

@ -121,7 +121,7 @@ extern char logfilename[1024];
/* A mod name to further distinguish versions. */
#define SRB2APPLICATION "SRB2Kart"
//#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable MD5 checking and stuff, all in one go. :3
//#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable hash checking and stuff, all in one go. :3
#ifdef DEVELOP
#define VERSIONSTRING "Development EXE"
#define VERSIONSTRING_RC "Development EXE" "\0"
@ -431,6 +431,13 @@ UINT32 quickncasehash (const char *p, size_t n)
return x;
}
// Standard Hashing Functions (tm)
// see W_MakeFileHash for hashing files
#include "xxhash.h"
#define HASH64(p, n) ((UINT64)XXH3_64bits(p, n))
#define HASH32(p, n) ((UINT32)(XXH3_64bits(p, n) & UINT32_MAX))
#define HASHFMT "%jx"
#ifndef __cplusplus
#ifndef min // Double-Check with WATTCP-32's cdefs.h
#define min(x, y) (((x) < (y)) ? (x) : (y))

View file

@ -5,11 +5,11 @@
/// filesearch:
///
/// ATTENTION : make sure there is enouth space in filename to put a full path (255 or 512)
/// if needmd5check == 0 there is no md5 check
/// if wantedhash == 0 there is no hash check
/// if completepath then filename will be change with the full path and name
/// maxsearchdepth == 0 only search given directory, no subdirs
/// return FS_NOTFOUND
/// FS_MD5SUMBAD;
/// FS_BADHASH;
/// FS_FOUND
#include <stdio.h>
@ -337,12 +337,12 @@ char *refreshdirname = NULL;
#if defined (_XBOX) && defined (_MSC_VER)
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
filestatus_t filesearch(char *filename, const char *startpath, UINT64 wantedhash,
boolean completepath, int maxsearchdepth)
{
//NONE?
startpath = filename = NULL;
wantedmd5sum = NULL;
wantedhash = 0;
maxsearchdepth = 0;
completepath = false;
return FS_NOTFOUND;
@ -369,7 +369,7 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut)
#else
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth)
filestatus_t filesearch(char *filename, const char *startpath, UINT64 wantedhash, boolean completepath, int maxsearchdepth)
{
filestatus_t retval = FS_NOTFOUND;
DIR **dirhandle;
@ -446,7 +446,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
}
else if (!strcasecmp(searchname, dent->d_name))
{
switch (checkfilemd5(searchpath, wantedmd5sum))
switch (checkfilehash(searchpath, wantedhash))
{
case FS_FOUND:
if (completepath)
@ -456,8 +456,8 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
retval = FS_FOUND;
found = 1;
break;
case FS_MD5SUMBAD:
retval = FS_MD5SUMBAD;
case FS_BADHASH:
retval = FS_BADHASH;
break;
default: // prevent some compiler warnings
break;
@ -788,7 +788,7 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut)
if (strcmp(dent->d_name, filenamebuf[i]))
continue;
if (cv_addons_md5.value && !checkfilemd5(menupath, wadfiles[i]->md5sum))
if (cv_addons_md5.value && !checkfilehash(menupath, wadfiles[i]->hash))
continue;
ext |= EXT_LOADED;

View file

@ -20,7 +20,7 @@ extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_sh
\param filename the file to look for
\param startpath where to start look from
\param wantedmd5sum want to check with MD5
\param wantedhash want to check with a hash
\param completepath want to return the complete path of the file?
\param maxsearchdepth the max depth to search for the file
@ -29,7 +29,7 @@ extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_sh
*/
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
filestatus_t filesearch(char *filename, const char *startpath, UINT64 wantedhash,
boolean completepath, int maxsearchdepth);
#define menudepth 20

View file

@ -38,7 +38,6 @@
#include "y_inter.h"
#include "v_video.h"
#include "lua_hook.h"
#include "md5.h" // demo checksums
#include "p_saveg.h" // savebuffer_t
#include "g_party.h"
@ -110,7 +109,7 @@ demoghost *ghosts = NULL;
// DEMO RECORDING
//
#define DEMOVERSION 0x0007
#define DEMOVERSION 0x0008
#define DEMOHEADER "\xF0" "KartReplay" "\x0F"
#define DF_GHOST 0x01 // This demo contains ghost data too!
@ -2133,12 +2132,12 @@ void G_BeginRecording(void)
snprintf(demo.titlename, 64, "%s - %s", G_BuildMapTitle(gamemap), modeattacking ? "Record Attack" : connectedservername);
// demo checksum
demobuf.p += 16;
demobuf.p += sizeof(UINT64);
// game data
M_Memcpy(demobuf.p, "PLAY", 4); demobuf.p += 4;
WRITESTRINGN(demobuf.p, mapheaderinfo[gamemap-1]->lumpname, MAXMAPLUMPNAME);
M_Memcpy(demobuf.p, mapmd5, 16); demobuf.p += 16;
WRITEUINT64(demobuf.p, maphash);
WRITEUINT8(demobuf.p, demoflags);
WRITEUINT8(demobuf.p, gametype & 0xFF);
@ -2154,8 +2153,8 @@ void G_BeginRecording(void)
{
nameonly(( filename = va("%s", wadfiles[i]->filename) ));
WRITESTRINGL(demobuf.p, filename, MAX_WADPATH);
WRITEMEM(demobuf.p, wadfiles[i]->md5sum, 16);
WRITEUINT8(demobuf.p, wadfiles[i]->compatmode);
WRITEUINT64(demobuf.p, wadfiles[i]->hash);
WRITEUINT8(demobuf.p, !!wadfiles[i]->compatmode);
totalfiles++;
}
@ -2327,7 +2326,7 @@ void G_BeginMetal(void)
WRITEUINT16(demobuf.p,DEMOVERSION);
// demo checksum
demobuf.p += 16;
demobuf.p += sizeof(UINT64);
M_Memcpy(demobuf.p, "METL", 4); demobuf.p += 4;
@ -2399,7 +2398,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp)
{
UINT8 totalfiles;
char filename[MAX_WADPATH];
UINT8 md5sum[16];
UINT64 filehash;
filestatus_t ncs;
boolean toomany = false;
boolean alreadyloaded;
@ -2416,7 +2415,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp)
strlcpy(filename, (char *)(*pp), sizeof filename);
SKIPSTRING((*pp));
}
READMEM((*pp), md5sum, 16);
filehash = READUINT64((*pp));
compatmode = READUINT8((*pp));
if (!toomany)
@ -2425,7 +2424,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp)
for (j = 0; j < numwadfiles; ++j)
{
if (memcmp(md5sum, wadfiles[j]->md5sum, 16) == 0)
if (filehash == wadfiles[j]->hash)
{
alreadyloaded = true;
break;
@ -2438,7 +2437,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp)
if (numwadfiles >= MAX_WADFILES)
toomany = true;
else
ncs = findfile(filename, md5sum, false);
ncs = findfile(filename, filehash, false);
if (toomany)
{
@ -2450,7 +2449,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp)
{
if (ncs == FS_NOTFOUND)
CONS_Alert(CONS_NOTICE, M_GetText("You do not have a copy of %s\n"), filename);
else if (ncs == FS_MD5SUMBAD)
else if (ncs == FS_BADHASH)
CONS_Alert(CONS_NOTICE, M_GetText("Checksum mismatch on %s\n"), filename);
else
CONS_Alert(CONS_NOTICE, M_GetText("Unknown error finding file %s\n"), filename);
@ -2478,7 +2477,7 @@ static void G_SkipDemoExtraFiles(UINT8 **pp)
for (i = 0; i < totalfiles; ++i)
{
SKIPSTRING((*pp));// file name
(*pp) += 16;// md5
(*pp) += sizeof(UINT64); // hash
(*pp) += 1; // compatmode
}
}
@ -2489,7 +2488,7 @@ static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick)
{
UINT8 totalfiles, filesloaded, nmusfilecount;
char filename[MAX_WADPATH];
UINT8 md5sum[16];
UINT64 filehash;
boolean toomany = false;
boolean alreadyloaded;
UINT8 i, j;
@ -2506,7 +2505,7 @@ static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick)
strlcpy(filename, (char *)(*pp), sizeof filename);
SKIPSTRING((*pp));
}
READMEM((*pp), md5sum, 16);
filehash = READUINT64((*pp));
(void)READUINT8((*pp)); // compatmode
if (!toomany)
@ -2521,7 +2520,7 @@ static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick)
else
continue;
if (memcmp(md5sum, wadfiles[j]->md5sum, 16) == 0)
if (filehash == wadfiles[j]->hash)
{
alreadyloaded = true;
@ -2540,7 +2539,7 @@ static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick)
if (numwadfiles >= MAX_WADFILES)
error = DFILE_ERROR_CANNOTLOAD;
else if (!quick && findfile(filename, md5sum, false) != FS_FOUND)
else if (!quick && findfile(filename, filehash, false) != FS_FOUND)
error = DFILE_ERROR_CANNOTLOAD;
else if (error < DFILE_ERROR_INCOMPLETEOUTOFORDER)
error |= DFILE_ERROR_NOTLOADED;
@ -2593,11 +2592,11 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
s = READUINT16(p);
I_Assert(s == DEMOVERSION);
p += 64; // full demo title
p += 16; // demo checksum
p += sizeof(UINT64); // demo checksum
I_Assert(!memcmp(p, "PLAY", 4));
p += 4; // PLAY
SKIPSTRING(p); // gamemap
p += 16; // map md5
p += sizeof(UINT64); // map hash
flags = READUINT8(p); // demoflags
p++; // gametype
p++; // numlaps
@ -2647,7 +2646,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
return UINT8_MAX;
}
p += 64; // full demo title
p += 16; // demo checksum
p += sizeof(UINT64); // demo checksum
if (memcmp(p, "PLAY", 4))
{
CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname);
@ -2655,7 +2654,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
return UINT8_MAX;
} p += 4; // "PLAY"
SKIPSTRING(p); // gamemap
p += 16; // mapmd5
p += sizeof(UINT64); // maphash
flags = READUINT8(p);
p++; // gametype
p++; // numlaps
@ -2750,7 +2749,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
if (version != VERSION || subversion != SUBVERSION)
pdemo->type = MD_OUTDATED;
info_p += 16; // demo checksum
info_p += sizeof(UINT64); // demo checksum
if (memcmp(info_p, "PLAY", 4))
{
CONS_Alert(CONS_ERROR, M_GetText("%s is the wrong type of recording and cannot be played.\n"), pdemo->filepath);
@ -2762,7 +2761,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
info_p += 4; // "PLAY"
READSTRINGN(info_p, mapname, sizeof(mapname));
pdemo->map = G_MapNumber(mapname);
info_p += 16; // mapmd5
info_p += sizeof(UINT64); // maphash
pdemoflags = READUINT8(info_p);
@ -3033,7 +3032,7 @@ void G_DoPlayDemo(char *defdemoname)
M_Memcpy(demo.titlename, demobuf.p, 64);
demobuf.p += 64;
demobuf.p += 16; // demo checksum
demobuf.p += sizeof(UINT64); // demo checksum
if (memcmp(demobuf.p, "PLAY", 4))
{
@ -3050,7 +3049,7 @@ void G_DoPlayDemo(char *defdemoname)
demobuf.p += 4; // "PLAY"
READSTRINGN(demobuf.p, mapname, sizeof(mapname)); // gamemap
gamemap = G_MapNumber(mapname)+1;
demobuf.p += 16; // mapmd5
demobuf.p += sizeof(UINT64); // maphash
demoflags = READUINT8(demobuf.p);
gametype = READUINT8(demobuf.p);
@ -3388,7 +3387,8 @@ void G_AddGhost(char *defdemoname)
{
INT32 i;
lumpnum_t l;
char name[17],skin[17],color[MAXCOLORNAME+1],*n,*pdemoname,md5[16];
char name[17],skin[17],color[MAXCOLORNAME+1],*n,*pdemoname;
UINT64 demohash;
demoghost *gh;
UINT8 flags;
UINT8 *buffer,*p;
@ -3457,12 +3457,12 @@ void G_AddGhost(char *defdemoname)
}
p += 64; // title
M_Memcpy(md5, p, 16); p += 16; // demo checksum
demohash = READUINT64(p); // demo checksum
for (gh = ghosts; gh; gh = gh->next)
if (!memcmp(md5, gh->checksum, 16)) // another ghost in the game already has this checksum?
if (demohash == gh->checksum) // another ghost in the game already has this checksum?
{ // Don't add another one, then!
CONS_Debug(DBG_SETUP, "Rejecting duplicate ghost %s (MD5 was matched)\n", pdemoname);
CONS_Debug(DBG_SETUP, "Rejecting duplicate ghost %s (hash was matched)\n", pdemoname);
Z_Free(pdemoname);
Z_Free(buffer);
return;
@ -3478,7 +3478,7 @@ void G_AddGhost(char *defdemoname)
SKIPSTRING(p); // gamemap
p += 16; // mapmd5 (possibly check for consistency?)
p += sizeof(UINT64); // maphash (possibly check for consistency?)
flags = READUINT8(p);
if (!(flags & DF_GHOST))
@ -3605,7 +3605,7 @@ void G_AddGhost(char *defdemoname)
gh = Z_Calloc(sizeof(demoghost), PU_LEVEL, NULL);
gh->next = ghosts;
gh->buffer = buffer;
M_Memcpy(gh->checksum, md5, 16);
gh->checksum = demohash;
gh->p = p;
ghosts = gh;
@ -3707,7 +3707,7 @@ void G_UpdateStaffGhostName(lumpnum_t l)
}
p += 64; // full demo title
p += 16; // demo checksum
p += sizeof(UINT64); // demo checksum
if (memcmp(p, "PLAY", 4))
{
@ -3716,7 +3716,7 @@ void G_UpdateStaffGhostName(lumpnum_t l)
p += 4; // "PLAY"
SKIPSTRING(p); // gamemap
p += 16; // mapmd5 (possibly check for consistency?)
p += sizeof(UINT64); // maphash (possibly check for consistency?)
flags = READUINT8(p);
if (!(flags & DF_GHOST))
@ -3843,7 +3843,7 @@ void G_DoPlayMetal(void)
Z_Free(metalbuffer);
return;
}
metal_p += 16; // demo checksum
metal_p += sizeof(UINT64); // demo checksum
if (memcmp(metal_p, "METL", 4))
{
CONS_Alert(CONS_WARNING, M_GetText("Failed to load bot recording for this map, wasn't recorded in Metal format.\n"));
@ -3876,17 +3876,11 @@ void G_DoneLevelLoad(void)
===================
*/
// Writes the demo's checksum, or just random garbage if you can't do that for some reason.
// Writes the demo's checksum.
static void WriteDemoChecksum(void)
{
UINT8 *p = demobuf.buffer+16; // checksum position
#ifdef NOMD5
UINT8 i;
for (i = 0; i < 16; i++, p++)
*p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
#else
md5_buffer((char *)p+16, demobuf.p - (p+16), p); // make a checksum of everything after the checksum in the file.
#endif
WRITEUINT64(p, HASH64(p+16, demobuf.p - (p+16)));
}
// Stops metal sonic's demo. Separate from other functions because metal + replays can coexist
@ -4113,13 +4107,9 @@ void G_SaveDemo(void)
WRITEUINT32(demoinfo_p, length);
// Doesn't seem like I can use WriteDemoChecksum here, correct me if I'm wrong -Sal
#ifdef NOMD5
for (UINT8 i = 0; i < 16; i++, p++)
*p = M_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
#else
// Make a checksum of everything after the checksum in the file up to the end of the standard data. Extrainfo is freely modifiable.
md5_buffer((char *)p+16, (demobuf.buffer + length) - (p+16), p);
#endif
WRITEUINT64(p, HASH64(p+16, (demobuf.buffer + length) - (p+16)));
if (FIL_WriteFile(demoname, demobuf.buffer, demobuf.p - demobuf.buffer)) // finally output the file.
demo.savemode = DSM_SAVED;

View file

@ -160,7 +160,7 @@ void G_LoadMetal(UINT8 **buffer);
// Your naming conventions are stupid and useless.
// There is no conflict here.
struct demoghost {
UINT8 checksum[16];
UINT64 checksum;
UINT8 *buffer, *p, color;
UINT8 fadein;
UINT16 version;

View file

@ -68,8 +68,6 @@
#include "f_finale.h" // wipes
#include "md5.h" // map MD5
#include "deh_tables.h"
// for MapLoad hook
@ -116,10 +114,10 @@
#endif
//
// Map MD5, calculated on level load.
// Map hash, calculated on level load.
// Sent to clients in PT_SERVERINFO.
//
unsigned char mapmd5[16];
UINT64 maphash;
//
// MAP related Lookup tables.
@ -7634,49 +7632,15 @@ static void P_ConvertBinaryMap(void)
P_WriteTextmap();
}
/** Compute MD5 message digest for bytes read from memory source
*
* The resulting message digest number will be written into the 16 bytes
* beginning at RESBLOCK.
*
* \param filename path of file
* \param resblock resulting MD5 checksum
* \return 0 if MD5 checksum was made, and is at resblock, 1 if error was found
*/
static INT32 P_MakeBufferMD5(const char *buffer, size_t len, void *resblock)
static void P_MakeMapHash(virtres_t *virt, UINT64 *dest)
{
#ifdef NOMD5
(void)buffer;
(void)len;
memset(resblock, 0x00, 16);
return 1;
#else
tic_t t = I_GetTime();
CONS_Debug(DBG_SETUP, "Making MD5\n");
if (md5_buffer(buffer, len, resblock) == NULL)
return 1;
CONS_Debug(DBG_SETUP, "MD5 calc took %f seconds\n", (float)(I_GetTime() - t)/NEWTICRATE);
return 0;
#endif
}
static void P_MakeMapMD5(virtres_t *virt, void *dest)
{
unsigned char resmd5[16];
if (udmf)
{
virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
P_MakeBufferMD5((char*)textmap->data, textmap->size, resmd5);
*dest = HASH64((char*)textmap->data, textmap->size);
}
else
{
unsigned char linemd5[16];
unsigned char sectormd5[16];
unsigned char thingmd5[16];
unsigned char sidedefmd5[16];
UINT8 i;
// Create a hash for the current map
// get the actual lumps!
virtlump_t* virtlines = vres_Find(virt, "LINEDEFS");
@ -7684,16 +7648,12 @@ static void P_MakeMapMD5(virtres_t *virt, void *dest)
virtlump_t* virtmthings = vres_Find(virt, "THINGS");
virtlump_t* virtsides = vres_Find(virt, "SIDEDEFS");
P_MakeBufferMD5((char*)virtlines->data, virtlines->size, linemd5);
P_MakeBufferMD5((char*)virtsectors->data, virtsectors->size, sectormd5);
P_MakeBufferMD5((char*)virtmthings->data, virtmthings->size, thingmd5);
P_MakeBufferMD5((char*)virtsides->data, virtsides->size, sidedefmd5);
for (i = 0; i < 16; i++)
resmd5[i] = (linemd5[i] + sectormd5[i] + thingmd5[i] + sidedefmd5[i]) & 0xFF;
*dest = 0;
*dest += HASH64((char*)virtlines->data, virtlines->size);
*dest += HASH64((char*)virtsectors->data, virtsectors->size);
*dest += HASH64((char*)virtmthings->data, virtmthings->size);
*dest += HASH64((char*)virtsides->data, virtsides->size);
}
M_Memcpy(dest, &resmd5, 16);
}
static boolean P_SetMapNamespace(void)
@ -7801,7 +7761,7 @@ static boolean P_LoadMapFromFile(void)
if (sectors[i].tags.count)
spawnsectors[i].tags.tags = memcpy(Z_Malloc(sectors[i].tags.count*sizeof(mtag_t), PU_LEVEL, NULL), sectors[i].tags.tags, sectors[i].tags.count*sizeof(mtag_t));
P_MakeMapMD5(curmapvirt, &mapmd5);
P_MakeMapHash(curmapvirt, &maphash);
TracyCZoneEnd(__zone);
return true;
}

View file

@ -24,8 +24,8 @@
extern "C" {
#endif
// map md5, sent to players via PT_SERVERINFO
extern unsigned char mapmd5[16];
// map hash, sent to players via PT_SERVERINFO
extern UINT64 maphash;
// Player spawn spots for deathmatch.
#define MAX_DM_STARTS 64

View file

@ -2382,7 +2382,7 @@ static const char *searchWad(const char *searchDir)
filestatus_t fstemp;
strcpy(tempsw, WADKEYWORD);
fstemp = filesearch(tempsw,searchDir,NULL,true,20);
fstemp = filesearch(tempsw,searchDir,0,true,20);
if (fstemp == FS_FOUND)
{
pathonly(tempsw);

View file

@ -62,7 +62,6 @@
#include "r_picformats.h"
#include "i_time.h"
#include "i_system.h"
#include "md5.h"
#include "lua_script.h"
#include "g_game.h" // G_MapNumber
@ -211,7 +210,7 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors)
// If findfile finds the file, the full path will be returned
// in filenamebuf == *filename.
if (findfile(filenamebuf, NULL, true))
if (findfile(filenamebuf, 0, true))
{
if ((handle = fopen_utf8(*filename, "rb")) == NULL)
{
@ -378,39 +377,52 @@ static inline boolean CheckCompatWad(UINT16 wadnum)
return false;
}
/** Compute MD5 message digest for bytes read from STREAM of this filname.
*
* The resulting message digest number will be written into the 16 bytes
* beginning at RESBLOCK.
// adapted from the example in xxhash.h
static UINT64 hashfile(FILE *f)
{
static XXH3_state_t *state;
char buffer[4096];
size_t count;
if (!state)
state = XXH3_createState();
XXH3_64bits_reset(state);
while ((count = fread(buffer, 1, sizeof(buffer), f)) != 0)
XXH3_64bits_update(state, buffer, count);
return XXH3_64bits_digest(state);
}
/** Computes and returns the hash for a file.
*
* \param filename path of file
* \param resblock resulting MD5 checksum
* \return 0 if MD5 checksum was made, and is at resblock, 1 if error was found
* \param openwad true if W_OpenWadFile should be used instead of fopen
* \param ret pointer to UINT64 to store hash
* \return true on success, false on error
*/
static inline INT32 W_MakeFileMD5(const char *filename, void *resblock)
boolean W_MakeFileHash(const char *filename, boolean openwad, UINT64 *ret)
{
#ifdef NOMD5
#ifdef NOFILEHASH
(void)filename;
memset(resblock, 0x00, 16);
(void)openwad;
*ret = 0;
return true;
#else
FILE *fhandle;
FILE *fhandle = openwad ? W_OpenWadFile(&filename, true) : fopen(filename, "rb");
if ((fhandle = fopen(filename, "rb")) != NULL)
if (fhandle == NULL)
{
tic_t t = I_GetTime();
CONS_Debug(DBG_SETUP, "Making MD5 for %s\n",filename);
if (md5_stream(fhandle, resblock) == 1)
{
fclose(fhandle);
return 1;
}
CONS_Debug(DBG_SETUP, "MD5 calc for %s took %f seconds\n",
filename, (float)(I_GetTime() - t)/NEWTICRATE);
fclose(fhandle);
return 0;
CONS_Alert(CONS_WARNING, "Could not open %s for hashing\n", filename);
return false;
}
CONS_Debug(DBG_SETUP, "Hashing file %s\n", filename);
*ret = hashfile(fhandle);
fclose(fhandle);
return true;
#endif
return 1;
}
// Invalidates the cache of lump numbers. Call this whenever a wad is added.
@ -863,10 +875,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup, wadco
wadfile_t *wadfile;
restype_t type;
UINT16 numlumps = 0;
#ifndef NOMD5
size_t i;
#endif
UINT8 md5sum[16];
UINT64 filehash = 0;
int important;
if (!(refreshdirmenu & REFRESHDIR_ADDFILE))
@ -907,17 +916,18 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup, wadco
important = !important;
#ifndef NOMD5
#ifndef NOFILEHASH
//
// w-waiiiit!
// Let's not add a wad file if the MD5 matches
// an MD5 of an already added WAD file!
// Let's not add a wad file if the hash matches
// the hash of an already added WAD file!
//
W_MakeFileMD5(filename, md5sum);
if (!W_MakeFileHash(filename, false, &filehash))
filehash = 0;
for (i = 0; i < numwadfiles; i++)
for (size_t i = 0; i < numwadfiles; i++)
{
if (!memcmp(wadfiles[i]->md5sum, md5sum, 16))
if (wadfiles[i]->hash == filehash)
{
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename);
if (handle)
@ -972,7 +982,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup, wadco
wadfile->type = type;
// already generated, just copy it over
M_Memcpy(&wadfile->md5sum, &md5sum, 16);
wadfile->hash = filehash;
//
// set up caching
@ -2143,74 +2153,32 @@ void *W_CachePatchLongName(const char *name, INT32 tag)
return W_CachePatchNum(num, tag);
}
#ifndef NOMD5
/**
* Prints an MD5 string into a human-readable textual format.
*
* \param md5 The md5 in binary form -- MD5_LEN (16) bytes.
* \param buf Where to print the textual form. Needs 2*MD5_LEN+1 (33) bytes.
* \author Graue <graue@oceanbase.org>
*/
#define MD5_FORMAT \
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
static void PrintMD5String(const UINT8 *md5, char *buf)
{
snprintf(buf, 2*MD5_LEN+1, MD5_FORMAT,
md5[0], md5[1], md5[2], md5[3],
md5[4], md5[5], md5[6], md5[7],
md5[8], md5[9], md5[10], md5[11],
md5[12], md5[13], md5[14], md5[15]);
}
#endif
/** Verifies a file's MD5 is as it should be.
* For releases, used as cheat prevention -- if the MD5 doesn't match, a
* fatal error is thrown. In debug mode, an MD5 mismatch only triggers a
/** Verifies a file's hash is as it should be.
* For releases, used as cheat prevention -- if the hash doesn't match, a
* fatal error is thrown. In debug mode, a hash mismatch only triggers a
* warning.
*
* \param wadfilenum Number of the loaded wad file to check.
* \param matchmd5 The MD5 sum this wad should have, expressed as a
* textual string.
* \param matchhash The hash value this wad should have.
* \author Graue <graue@oceanbase.org>
*/
void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5)
void W_VerifyFileHash(UINT16 wadfilenum, UINT64 matchhash)
{
#ifdef NOMD5
#ifdef NOFILEHASH
(void)wadfilenum;
(void)matchmd5;
(void)matchhash;
#else
UINT8 realmd5[MD5_LEN];
INT32 ix;
I_Assert(strlen(matchmd5) == 2*MD5_LEN);
I_Assert(wadfilenum < numwadfiles);
// Convert an md5 string like "7d355827fa8f981482246d6c95f9bd48"
// into a real md5.
for (ix = 0; ix < 2*MD5_LEN; ix++)
{
INT32 n, c = matchmd5[ix];
if (isdigit(c))
n = c - '0';
else
{
I_Assert(isxdigit(c));
if (isupper(c)) n = c - 'A' + 10;
else n = c - 'a' + 10;
}
if (ix & 1) realmd5[ix>>1] = (UINT8)(realmd5[ix>>1]+n);
else realmd5[ix>>1] = (UINT8)(n<<4);
}
if (memcmp(realmd5, wadfiles[wadfilenum]->md5sum, 16))
if (matchhash != wadfiles[wadfilenum]->hash)
{
char actualmd5text[2*MD5_LEN+1];
PrintMD5String(wadfiles[wadfilenum]->md5sum, actualmd5text);
#ifdef _DEBUG
CONS_Printf
#else
I_Error
#endif
(M_GetText("File is old, is corrupt or has been modified: %s (found md5: %s, wanted: %s)\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5);
(M_GetText("File is old, is corrupt or has been modified: %s (found hash: " HASHFMT ", wanted: " HASHFMT ")\n"),
wadfiles[wadfilenum]->filename, wadfiles[wadfilenum]->hash, matchhash);
}
#endif
}

View file

@ -126,7 +126,7 @@ struct wadfile_t
UINT16 numlumps; // this wad's number of resources
FILE *handle;
UINT32 filesize; // for network
UINT8 md5sum[16];
UINT64 hash;
boolean important; // also network - !W_VerifyNMUSlumps
boolean compatmode;
@ -154,6 +154,8 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors);
// Load and add a wadfile to the active wad files, returns numbers of lumps, INT16_MAX on error
UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup, wadcompat_t compat);
boolean W_MakeFileHash(const char *filename, boolean openwad, UINT64 *ret);
// W_InitMultipleFiles returns 1 if all is okay, 0 otherwise,
// so that it stops with a message if a file was not found, but not if all is okay.
// W_InitMultipleFiles exits if a file was not found, but not if all is okay.
@ -224,7 +226,7 @@ void *W_CacheSoftwarePatchNum(lumpnum_t lumpnum, INT32 tag);
void W_UnlockCachedPatch(void *patch);
void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5);
void W_VerifyFileHash(UINT16 wadfilenum, UINT64 matchhash);
int W_VerifyNMUSlumps(const char *filename, boolean exit_on_error);

View file

@ -535,3 +535,4 @@ endif()
add_subdirectory(tracy)
add_subdirectory(tcbrindle_span)
add_subdirectory(fmt)
add_subdirectory(xxhash)

8
thirdparty/xxhash/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,8 @@
# Update from https://github.com/Cyan4973/xxHash/releases/
# xxHash version 0.8.3
# License: BSD 2-clause
add_library(xxhash STATIC "${CMAKE_CURRENT_SOURCE_DIR}/include/xxhash.c")
target_compile_options(xxhash PRIVATE -O3) # do some optimization will ya
target_include_directories(xxhash PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
add_library(xxHash::xxhash ALIAS xxhash)

26
thirdparty/xxhash/LICENSE vendored Normal file
View file

@ -0,0 +1,26 @@
xxHash Library
Copyright (c) 2012-2021 Yann Collet
All rights reserved.
BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

42
thirdparty/xxhash/include/xxhash.c vendored Normal file
View file

@ -0,0 +1,42 @@
/*
* xxHash - Extremely Fast Hash algorithm
* Copyright (C) 2012-2023 Yann Collet
*
* BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You can contact the author at:
* - xxHash homepage: https://www.xxhash.com
* - xxHash source repository: https://github.com/Cyan4973/xxHash
*/
/*
* xxhash.c instantiates functions defined in xxhash.h
*/
#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */
#define XXH_IMPLEMENTATION /* access definitions */
#include "xxhash.h"

7238
thirdparty/xxhash/include/xxhash.h vendored Normal file

File diff suppressed because it is too large Load diff