char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
27e345b57
char/aliceai-t5-moe
1#include "ggml.h" 2#include "gguf.h" 3 4#include <algorithm> 5#include <clocale> 6#include <cstddef> 7#include <cstdio> 8#include <cstdlib> /* abort() */ 9#include <cstring> 10#include <stdexcept> 11#include <string> 12 13#include <sstream> 14#include <fstream> 15 16#ifdef __cplusplus 17extern "C" { 18#endif 19 20#include "hash/xxhash/xxhash.h" 21#include "hash/sha256/sha256.h" 22 23#ifdef __cplusplus 24} 25#endif 26 27// sha1 is compiled as C++ and lives in a namespace, see scripts/sync_vendor.py 28#include "hash/sha1/sha1.h" 29using namespace vendor_hash ; 30 31 32// uuid.uuid5(uuid.NAMESPACE_URL, 'en.wikipedia.org/wiki/Llama.cpp') 33#define UUID_NAMESPACE_LLAMA_CPP "ef001206-dadc-5f6d-a15f-3359e577d4e5" 34#define UUID_NAMESPACE_LLAMA_CPP_HEX 0xef, 0x00, 0x12, 0x06, 0xda, 0xdc, 0x5f, 0x6d, 0xa1, 0x5f, 0x33, 0x59, 0xe5, 0x77, 0xd4, 0xe5 35 36 37#define HASH_TYPE_SHA256_STR "sha256" 38#define HASH_TYPE_SHA1_STR "sha1" 39#define HASH_TYPE_XXH64_STR "xxh64" 40#define HASH_TYPE_UUID_STR "uuid" 41 42 43typedef enum { 44HASH_EXIT_SUCCESS = 0 ,// All hash has been generated or validated 45HASH_EXIT_FAILURE = 1 ,// Generic Failure 46HASH_EXIT_MISMATCH = 2 ,// Hash mismatched during validation 47HASH_EXIT_MANIFEST_MISSING_ENTRY = 3 ,// Hash attempted validation but missing entry in manifest 48HASH_EXIT_MANIFEST_UNKNOWN_HASH = 4 ,// Manifest is present, but we do not know any hash format within it 49HASH_EXIT_MANIFEST_FILE_ERROR = 5 // Manifest is either missing or not a known format 50}hash_exit_code_t ; 51 52 53typedef enum { 54HASH_MANIFEST_NOT_FOUND , 55HASH_MANIFEST_MISMATCH , 56HASH_MANIFEST_OK , 57}hash_manifest_result_t ; 58 59 60struct hash_params { 61 std::string input ; 62bool xxh64 = false; 63bool sha1 = false; 64bool sha256 = false; 65bool uuid = false; 66 67bool no_layer = false; 68 69bool manifest_is_usable = false; 70 std::string manifest_file ; 71}; 72 73struct manifest_check_params { 74bool xxh64 = false; 75bool sha1 = false; 76bool sha256 = false; 77bool uuid = false; 78}; 79 80static char const * hash_manifest_result_to_str (hash_manifest_result_t value ) { 81switch (value ) { 82case HASH_MANIFEST_NOT_FOUND :return "Not Found" ; 83case HASH_MANIFEST_MISMATCH :return "Mismatch" ; 84case HASH_MANIFEST_OK :return "Ok" ; 85 } 86return "?" ; 87} 88 89static char const * hash_exit_code_to_str (hash_exit_code_t value ) { 90switch (value ) { 91case HASH_EXIT_SUCCESS :return "Success" ; 92case HASH_EXIT_FAILURE :return "Failure" ; 93case HASH_EXIT_MISMATCH :return "Mismatch" ; 94case HASH_EXIT_MANIFEST_MISSING_ENTRY :return "Manifest Missing Entry" ; 95case HASH_EXIT_MANIFEST_UNKNOWN_HASH :return "Manifest Unknown Hash" ; 96case HASH_EXIT_MANIFEST_FILE_ERROR :return "Manifest File Error" ; 97 } 98return "?" ; 99} 100 101static void hash_print_usage (const char * executable ) { 102const hash_params default_params ; 103printf ("\n" ); 104printf ("usage: %s [options] GGUF_IN\n" ,executable ); 105printf ("\n" ); 106printf ("Hash a GGUF file" ); 107printf ("\n" ); 108printf ("options:\n" ); 109printf (" -h, --help show this help message and exit\n" ); 110printf (" --xxh64 use xxh64 hash\n" ); 111printf (" --sha1 use sha1 hash\n" ); 112printf (" --sha256 use sha256 hash\n" ); 113printf (" --all use all hash\n" ); 114printf (" --no-layer exclude per layer hash\n" ); 115printf (" --uuid generate UUIDv5 ID\n" ); 116printf (" -c, --check <manifest> verify against a manifest\n" ); 117printf ("\n" ); 118} 119 120static void hash_params_parse_ex (int argc ,const char ** argv ,hash_params & params ) { 121 std::string arg ; 122bool invalid_param = false; 123const std::string arg_prefix = "--" ; 124 125int arg_idx = 1 ; 126for (;arg_idx < argc && strncmp (argv [arg_idx ],"--" ,2 )== 0 ;arg_idx ++ ) { 127arg = argv [arg_idx ]; 128if (arg .compare (0 ,arg_prefix .size (),arg_prefix )== 0 ) { 129 std::replace (arg .begin (),arg .end (),'_' ,'-' ); 130 } 131 132bool arg_found = false; 133if (arg == "-h" || arg == "--help" ) { 134hash_print_usage (argv [0 ]); 135exit (0 ); 136 } 137 138if (arg == "--xxh64" ) { 139arg_found = true; 140params .xxh64 = true; 141 } 142 143if (arg == "--sha1" ) { 144arg_found = true; 145params .sha1 = true; 146 } 147 148if (arg == "--uuid" ) { 149arg_found = true; 150params .uuid = true; 151 } 152 153if (arg == "--sha256" ) { 154arg_found = true; 155params .sha256 = true; 156 } 157 158if (arg == "--all" ) { 159arg_found = true; 160params .sha256 = true; 161params .sha1 = true; 162params .xxh64 = true; 163 } 164 165if (arg == "--no-layer" ) { 166arg_found = true; 167params .no_layer = true; 168 } 169 170if (arg == "-c" || arg == "--check" ) { 171if (++ arg_idx >=argc ) { 172invalid_param = true; 173break ; 174 } 175arg_found = true; 176params .manifest_file = argv [arg_idx ]; 177 } 178 179if (!arg_found ) { 180throw std::invalid_argument ("error: unknown argument: " + arg ); 181 } 182 } 183 184if (invalid_param ) { 185throw std::invalid_argument ("error: invalid parameter for argument:" + arg ); 186 } 187 188if (argc - arg_idx < 1 ) { 189throw std::invalid_argument ("error: bad arguments" ); 190 } 191 192params .input = argv [arg_idx ++ ]; 193} 194 195static bool hash_params_parse (int argc ,const char ** argv ,hash_params & params ) { 196bool result = true; 197try { 198hash_params_parse_ex (argc ,argv ,params ); 199 } 200catch (const std::invalid_argument & ex ) { 201fprintf (stderr ,"%s\n" ,ex .what ()); 202hash_print_usage (argv [0 ]); 203exit (EXIT_FAILURE ); 204 } 205return result ; 206} 207 208static bool manifest_type (const std::string & manifest_file ,manifest_check_params & manifest_check ) { 209if (manifest_file .empty ()) { 210return false; 211 } 212 213 std::ifstream file (manifest_file ); 214if (!file .is_open ()) { 215return false; 216 } 217 218 std::string manifest_entry_line ; 219while (getline (file ,manifest_entry_line )) { 220// hash_type_str hash_str tensor_name 221// e.g. 'xxh64 f66e9cd66a4396a0 test.gguf:tensor_0' 222 std::istringstream line_stream (manifest_entry_line ); 223 std::string file_hash_type ; 224if (line_stream >>file_hash_type ) { 225if (file_hash_type == HASH_TYPE_SHA256_STR ) { 226manifest_check .sha256 = true; 227 }else if (file_hash_type == HASH_TYPE_SHA1_STR ) { 228manifest_check .sha1 = true; 229 }else if (file_hash_type == HASH_TYPE_XXH64_STR ) { 230manifest_check .xxh64 = true; 231 }else if (file_hash_type == HASH_TYPE_UUID_STR ) { 232manifest_check .uuid = true; 233 } 234 } 235 } 236 237return true; 238} 239 240static hash_manifest_result_t manifest_verify (const std::string & manifest_file ,const std::string & hash_type_str ,const std::string & hash_str ,const std::string & tensor_name ) { 241if (manifest_file .empty ()) { 242return HASH_MANIFEST_NOT_FOUND ; 243 } 244 245 std::ifstream file (manifest_file ); 246if (!file .is_open ()) { 247return HASH_MANIFEST_NOT_FOUND ; 248 } 249 250 std::string manifest_entry_line ; 251while (getline (file ,manifest_entry_line )) { 252 std::istringstream line_stream (manifest_entry_line ); 253 std::string file_hash_type ; 254 std::string file_hash ; 255 std::string file_tensor_name ; 256if (line_stream >>file_hash_type >>file_hash >>file_tensor_name ) { 257// Line parsed. Check hash validity 258 259if (file_hash_type != hash_type_str ) { 260continue ; 261 } 262 263if (file_tensor_name != tensor_name ) { 264continue ; 265 } 266 267return (file_hash == hash_str ) ?HASH_MANIFEST_OK :HASH_MANIFEST_MISMATCH ; 268 } 269 } 270 271return HASH_MANIFEST_NOT_FOUND ; 272} 273 274static void generate_uuidv5 (const unsigned char sha1_digest [20 ],unsigned char uuid [16 ]) { 275// Ref: https://www.rfc-editor.org/rfc/rfc9562.html#section-5.5 276// Assumes that digest was processed correctly with the expected namespace 277for (int i = 0 ;i < 16 ;i ++ ) { 278uuid [i ]= sha1_digest [i ]; 279 } 280 281// Set bits corresponding to UUID ver 5 282uuid [6 ] &= ~(0xF <<4 ); 283uuid [6 ] |= (5 <<4 ); 284 285// Set bits corresponding to UUID variant 0b10XX 286uuid [8 ] &= ~(0xc <<4 ); 287uuid [8 ] |= (0x8 <<4 ); 288} 289 290static hash_exit_code_t gguf_hash (const hash_params & hash_params ) { 291const std::string & fname = hash_params .input ; 292struct ggml_context * ctx_data = NULL ; 293 294struct gguf_init_params params = { 295/*.no_alloc = */ false, 296/*.ctx = */ & ctx_data , 297 }; 298 299// xxh64 init 300XXH64_state_t * xxh64_model_hash_state = NULL ; 301if (hash_params .xxh64 ) { 302xxh64_model_hash_state = XXH64_createState (); 303if (xxh64_model_hash_state == NULL ) { 304abort (); 305 } 306 307XXH64_hash_t const seed = 0 ; 308if (XXH64_reset (xxh64_model_hash_state ,seed )== XXH_ERROR ) { 309abort (); 310 } 311 } 312 313// sha1 init 314SHA1_CTX sha1_model_hash_ctx ; 315if (hash_params .sha1 ) { 316SHA1Init (& sha1_model_hash_ctx ); 317 } 318 319// sha256 init 320sha256_t sha256_model_hash_ctx ; 321if (hash_params .sha256 ) { 322sha256_init (& sha256_model_hash_ctx ); 323 } 324 325// sha1 for uuid init 326SHA1_CTX sha1_for_uuid_ctx ; 327if (hash_params .uuid ) { 328unsigned char const uuidv5_namespace []= {UUID_NAMESPACE_LLAMA_CPP_HEX }; 329SHA1Init (& sha1_for_uuid_ctx ); 330SHA1Update (& sha1_for_uuid_ctx , (unsigned char const * )uuidv5_namespace ,sizeof (uuidv5_namespace )); 331 } 332 333struct gguf_context * ctx = gguf_init_from_file (fname .c_str (),params ); 334const int n_tensors = gguf_get_n_tensors (ctx ); 335bool tensor_layer_in_manifest = false; 336bool model_in_manifest = false; 337bool tensor_layer_has_mismatch = false; 338bool model_has_mismatch = false; 339for (int i = 0 ;i < n_tensors ;++ i ) { 340const char * name = gguf_get_tensor_name (ctx ,i ); 341struct ggml_tensor * cur = ggml_get_tensor (ctx_data ,name ); 342auto n_bytes = ggml_nbytes (cur ); 343auto * raw_data = cur -> data ; 344const std::string tensor_layer_name = fname + ":" + name ; 345 346if (hash_params .xxh64 ) { 347 348if (!hash_params .no_layer ) { 349// Per Layer Hash 350XXH64_hash_t hash = XXH64 (raw_data ,n_bytes ,0 ); 351 352char hex_result [17 ]; 353for (int offset = 0 ;offset < 8 ;offset ++ ) { 354unsigned int shift_bits_by = (8 * (8 - offset - 1 )); 355snprintf ( (hex_result + (2 * offset )),sizeof (hex_result )- (2 * offset ),"%02x" , (unsigned char ) (hash >>shift_bits_by )& 0xff ); 356 } 357 358if (hash_params .manifest_is_usable ) { 359hash_manifest_result_t verify_result = manifest_verify (hash_params .manifest_file ,HASH_TYPE_XXH64_STR ,hex_result ,tensor_layer_name ); 360 361switch (verify_result ) { 362case HASH_MANIFEST_NOT_FOUND : 363break ; 364case HASH_MANIFEST_MISMATCH : 365tensor_layer_in_manifest = true; 366tensor_layer_has_mismatch = true; 367break ; 368case HASH_MANIFEST_OK : 369tensor_layer_in_manifest = true; 370break ; 371 } 372 373printf ("%-8s %-s %s - %s\n" ,HASH_TYPE_XXH64_STR ,hex_result ,tensor_layer_name .c_str (),hash_manifest_result_to_str (verify_result )); 374 }else { 375printf ("%-8s %-s %s\n" ,HASH_TYPE_XXH64_STR ,hex_result ,tensor_layer_name .c_str ()); 376 } 377 } 378 379// Overall Model Hash 380if (XXH64_update (xxh64_model_hash_state ,raw_data ,n_bytes )== XXH_ERROR )abort (); 381 } 382 383if (hash_params .sha1 ) { 384 385if (!hash_params .no_layer ) { 386// Per Layer Hash 387char result [21 ];// sha1 outputs 20 bytes 388SHA1 (result , (const char * )raw_data ,n_bytes ); 389 390char hex_result [41 ]= {0 }; 391for (int offset = 0 ;offset < 20 ;offset ++ ) { 392snprintf ( (hex_result + (2 * offset )),sizeof (hex_result )- (2 * offset ),"%02x" ,result [offset ]& 0xff ); 393 } 394 395if (hash_params .manifest_is_usable ) { 396hash_manifest_result_t verify_result = manifest_verify (hash_params .manifest_file ,HASH_TYPE_SHA1_STR ,hex_result ,tensor_layer_name ); 397 398switch (verify_result ) { 399case HASH_MANIFEST_NOT_FOUND : 400break ; 401case HASH_MANIFEST_MISMATCH : 402tensor_layer_in_manifest = true; 403tensor_layer_has_mismatch = true; 404break ; 405case HASH_MANIFEST_OK : 406tensor_layer_in_manifest = true; 407break ; 408 } 409 410printf ("%-8s %-s %s - %s\n" ,HASH_TYPE_SHA1_STR ,hex_result ,tensor_layer_name .c_str (),hash_manifest_result_to_str (verify_result )); 411 }else { 412printf ("%-8s %-s %s\n" ,HASH_TYPE_SHA1_STR ,hex_result ,tensor_layer_name .c_str ()); 413 } 414 } 415 416// Overall Model Hash 417SHA1Update (& sha1_model_hash_ctx , (unsigned char const * )raw_data ,n_bytes ); 418 } 419 420if (hash_params .sha256 ) { 421 422if (!hash_params .no_layer ) { 423// Per Layer Hash 424unsigned char result [SHA256_DIGEST_SIZE ];// sha256 outputs 32 bytes 425sha256_hash ((unsigned char * )result , (const unsigned char * )raw_data ,n_bytes ); 426 427char hex_result [SHA256_DIGEST_SIZE * 2 + 1 ]= {0 }; 428for (int offset = 0 ;offset < SHA256_DIGEST_SIZE ;offset ++ ) { 429snprintf ( (hex_result + (2 * offset )),sizeof (hex_result )- (2 * offset ),"%02x" ,result [offset ]& 0xff ); 430 } 431 432if (hash_params .manifest_is_usable ) { 433hash_manifest_result_t verify_result = manifest_verify (hash_params .manifest_file ,HASH_TYPE_SHA256_STR ,hex_result ,tensor_layer_name ); 434 435switch (verify_result ) { 436case HASH_MANIFEST_NOT_FOUND : 437break ; 438case HASH_MANIFEST_MISMATCH : 439tensor_layer_in_manifest = true; 440tensor_layer_has_mismatch = true; 441break ; 442case HASH_MANIFEST_OK : 443tensor_layer_in_manifest = true; 444break ; 445 } 446 447printf ("%-8s %-s %s - %s\n" ,HASH_TYPE_SHA256_STR ,hex_result ,tensor_layer_name .c_str (),hash_manifest_result_to_str (verify_result )); 448 }else { 449printf ("%-8s %-s %s\n" ,HASH_TYPE_SHA256_STR ,hex_result ,tensor_layer_name .c_str ()); 450 } 451 } 452 453// Overall Model Hash 454sha256_update (& sha256_model_hash_ctx , (unsigned char const * )raw_data ,n_bytes ); 455 } 456 457if (hash_params .uuid ) { 458SHA1Update (& sha1_for_uuid_ctx , (unsigned char const * )raw_data ,n_bytes ); 459 } 460 } 461 462if (hash_params .xxh64 ) { 463XXH64_hash_t const hash = XXH64_digest (xxh64_model_hash_state ); 464 465char hex_result [17 ]; 466for (int offset = 0 ;offset < 8 ;offset ++ ) { 467unsigned int shift_bits_by = (8 * (8 - offset - 1 )); 468snprintf ( (hex_result + (2 * offset )),sizeof (hex_result )- (2 * offset ),"%02x" , (unsigned char ) (hash >>shift_bits_by )& 0xff ); 469 } 470 471if (hash_params .manifest_is_usable ) { 472hash_manifest_result_t verify_result = manifest_verify (hash_params .manifest_file ,HASH_TYPE_XXH64_STR ,hex_result ,fname ); 473 474switch (verify_result ) { 475case HASH_MANIFEST_NOT_FOUND : 476break ; 477case HASH_MANIFEST_MISMATCH : 478model_in_manifest = true; 479model_has_mismatch = true; 480break ; 481case HASH_MANIFEST_OK : 482model_in_manifest = true; 483break ; 484 } 485 486printf ("%-8s %-s %s - %s\n" ,HASH_TYPE_XXH64_STR ,hex_result ,fname .c_str (),hash_manifest_result_to_str (verify_result )); 487 }else { 488printf ("%-8s %-s %s\n" ,HASH_TYPE_XXH64_STR ,hex_result ,fname .c_str ()); 489 } 490 } 491 492if (hash_params .sha1 ) { 493unsigned char result [21 ]; 494SHA1Final (result ,& sha1_model_hash_ctx ); 495 496char hex_result [41 ]; 497for (int offset = 0 ;offset < 20 ;offset ++ ) { 498snprintf ( (hex_result + (2 * offset )),sizeof (hex_result )- (2 * offset ),"%02x" ,result [offset ]& 0xff ); 499 } 500 501if (hash_params .manifest_is_usable ) { 502hash_manifest_result_t verify_result = manifest_verify (hash_params .manifest_file ,HASH_TYPE_SHA1_STR ,hex_result ,fname ); 503 504switch (verify_result ) { 505case HASH_MANIFEST_NOT_FOUND : 506break ; 507case HASH_MANIFEST_MISMATCH : 508model_in_manifest = true; 509model_has_mismatch = true; 510break ; 511case HASH_MANIFEST_OK : 512model_in_manifest = true; 513break ; 514 } 515 516printf ("%-8s %-s %s - %s\n" ,HASH_TYPE_SHA1_STR ,hex_result ,fname .c_str (),hash_manifest_result_to_str (verify_result )); 517 }else { 518printf ("%-8s %-s %s\n" ,HASH_TYPE_SHA1_STR ,hex_result ,fname .c_str ()); 519 } 520 } 521 522if (hash_params .sha256 ) { 523unsigned char result [SHA256_DIGEST_SIZE ];// sha256 outputs 32 bytes 524sha256_final (& sha256_model_hash_ctx ,result ); 525 526char hex_result [SHA256_DIGEST_SIZE * 2 + 1 ]= {0 }; 527for (int offset = 0 ;offset < SHA256_DIGEST_SIZE ;offset ++ ) { 528snprintf ( (hex_result + (2 * offset )),sizeof (hex_result )- (2 * offset ),"%02x" ,result [offset ]& 0xff ); 529 } 530 531if (hash_params .manifest_is_usable ) { 532hash_manifest_result_t verify_result = manifest_verify (hash_params .manifest_file ,HASH_TYPE_SHA256_STR ,hex_result ,fname ); 533 534switch (verify_result ) { 535case HASH_MANIFEST_NOT_FOUND : 536break ; 537case HASH_MANIFEST_MISMATCH : 538model_in_manifest = true; 539model_has_mismatch = true; 540break ; 541case HASH_MANIFEST_OK : 542model_in_manifest = true; 543break ; 544 } 545 546printf ("%-8s %-s %s - %s\n" ,HASH_TYPE_SHA256_STR ,hex_result ,fname .c_str (),hash_manifest_result_to_str (verify_result )); 547 }else { 548printf ("%-8s %-s %s\n" ,HASH_TYPE_SHA256_STR ,hex_result ,fname .c_str ()); 549 } 550 } 551 552if (hash_params .uuid ) { 553unsigned char result [21 ]; 554SHA1Final (result ,& sha1_for_uuid_ctx ); 555 556unsigned char uuid [16 ]; 557generate_uuidv5 (result ,uuid ); 558 559char string_buffer [37 ]= {0 }; 560snprintf (string_buffer ,sizeof (string_buffer ),"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" , 561uuid [0 ],uuid [1 ],uuid [2 ],uuid [3 ], 562uuid [4 ],uuid [5 ],uuid [6 ],uuid [7 ], 563uuid [8 ],uuid [9 ],uuid [10 ],uuid [11 ], 564uuid [12 ],uuid [13 ],uuid [14 ],uuid [15 ]); 565 566if (hash_params .manifest_is_usable ) { 567hash_manifest_result_t verify_result = manifest_verify (hash_params .manifest_file ,HASH_TYPE_SHA256_STR ,string_buffer ,fname ); 568 569switch (verify_result ) { 570case HASH_MANIFEST_NOT_FOUND : 571break ; 572case HASH_MANIFEST_MISMATCH : 573model_in_manifest = true; 574model_has_mismatch = true; 575break ; 576case HASH_MANIFEST_OK : 577model_in_manifest = true; 578break ; 579 } 580 581printf ("%-8s %-s %s - %s\n" ,HASH_TYPE_UUID_STR ,string_buffer ,fname .c_str (),hash_manifest_result_to_str (verify_result )); 582 }else { 583printf ("%-8s %-s %s\n" ,HASH_TYPE_UUID_STR ,string_buffer ,fname .c_str ()); 584 } 585 } 586 587 588ggml_free (ctx_data ); 589gguf_free (ctx ); 590 591 592if (hash_params .manifest_is_usable ) { 593// In hash verification mode 594 595if (!model_in_manifest ) { 596// model missing in manifest? 597 598// Check tensor layer... 599if (!tensor_layer_in_manifest ) { 600// Still missing? Maybe we are reading the wrong manifest. 601return HASH_EXIT_MANIFEST_MISSING_ENTRY ; 602 } 603 604if (tensor_layer_has_mismatch ) { 605// Per tensor check found error 606return HASH_EXIT_FAILURE ; 607 } 608 609// All per tensor layer checks passed? Sounds good enough. 610return HASH_EXIT_SUCCESS ; 611 } 612 613// Overall model check passed, but let's check per layer just in case 614// If missing, we don't care too much as the overall model checked 615if (tensor_layer_in_manifest && tensor_layer_has_mismatch ) { 616return HASH_EXIT_FAILURE ; 617 } 618 619if (model_has_mismatch ) { 620// model has failed hash somewhere in the model 621return HASH_EXIT_FAILURE ; 622 } 623 624// All checks appears to be fine 625return HASH_EXIT_SUCCESS ; 626 } 627 628// In hash generation mode 629return HASH_EXIT_SUCCESS ; 630} 631 632int main (int argc ,const char ** argv ) { 633 std::setlocale (LC_NUMERIC ,"C" ); 634 635hash_params params ; 636manifest_check_params manifest_check ; 637hash_params_parse (argc ,argv ,params ); 638 639if (!params .manifest_file .empty ()) { 640if (!manifest_type (params .manifest_file ,manifest_check )) { 641printf ("ERROR cannot open manifest %s" ,params .manifest_file .c_str ()); 642return HASH_EXIT_MANIFEST_FILE_ERROR ; 643 } 644 645if (!manifest_check .sha256 && !manifest_check .sha1 && !manifest_check .xxh64 && !manifest_check .uuid ) { 646printf ("ERROR manifest does not have any known hash format in %s" ,params .manifest_file .c_str ()); 647return HASH_EXIT_MANIFEST_UNKNOWN_HASH ; 648 } 649 650printf ("manifest %s" ,params .manifest_file .c_str ()); 651 652if (manifest_check .sha256 ) { 653printf (" sha256" ); 654 } 655 656if (manifest_check .sha1 ) { 657printf (" sha1" ); 658 } 659 660if (manifest_check .xxh64 ) { 661printf (" xxh64" ); 662 } 663 664if (manifest_check .uuid ) { 665printf (" uuid" ); 666 } 667 668printf ("\n" ); 669 670// Autoselect the highest security hash if manifest is provided but 671// the user has not specifically defined the hash they care about 672if (!params .xxh64 && !params .sha1 && !params .uuid && !params .sha256 ) { 673// User has not selected a specific value, pick most secure hash 674if (manifest_check .sha256 ) { 675params .sha256 = true; 676 }else if (manifest_check .sha1 ) { 677params .sha1 = true; 678 }else if (manifest_check .xxh64 ) { 679params .xxh64 = true; 680 }else if (manifest_check .uuid ) { 681params .uuid = true; 682 } 683 } 684 685params .manifest_is_usable = true; 686 } 687 688// By default if no swich argument provided, assume xxh64 689if (!params .xxh64 && !params .sha1 && !params .uuid && !params .sha256 ) { 690params .xxh64 = true; 691 } 692 693hash_exit_code_t exit_code = gguf_hash (params ); 694 695if (params .manifest_is_usable ) { 696printf ("\nVerification results for %s - %s\n" ,params .manifest_file .c_str (),hash_exit_code_to_str (exit_code )); 697 } 698 699return exit_code ; 700}