1 // #FILENAME sha256sum.c 1 2 /* Copyright (C) 2021 Bastian Bittorf 3 * Copyright (C) 2021 Alain Mosnier 4 * Copyright (C) 2017-2021 Jan Venekamp 5 * Copyright (C) 2021 Jeremiah Orians 6 * This file is part of mescc-tools 7 * 8 * mescc-tools is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * (at your option) any later version. 12 * 13 * mescc-tools is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with mescc-tools. If not, see . 20 */ 21 22 // #FILENAME 1 23 /* Copyright (C) 2016 Jeremiah Orians 24 * This file is part of M2-Planet. 25 * 26 * M2-Planet is free software: you can redistribute it and/or modify 27 * it under the terms of the GNU General Public License as published by 28 * the Free Software Foundation, either version 3 of the License, or 29 * (at your option) any later version. 30 * 31 * M2-Planet is distributed in the hope that it will be useful, 32 * but WITHOUT ANY WARRANTY; without even the implied warranty of 33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 34 * GNU General Public License for more details. 35 * 36 * You should have received a copy of the GNU General Public License 37 * along with M2-Planet. If not, see . 38 */ 39 40 41 42 43 44 // #FILENAME 1 45 /* Copyright (C) 2016 Jeremiah Orians 46 * This file is part of M2-Planet. 47 * 48 * M2-Planet is free software: you can redistribute it and/or modify 49 * it under the terms of the GNU General Public License as published by 50 * the Free Software Foundation, either version 3 of the License, or 51 * (at your option) any later version. 52 * 53 * M2-Planet is distributed in the hope that it will be useful, 54 * but WITHOUT ANY WARRANTY; without even the implied warranty of 55 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 56 * GNU General Public License for more details. 57 * 58 * You should have received a copy of the GNU General Public License 59 * along with M2-Planet. If not, see . 60 */ 61 62 // #FILENAME 1 63 /* Copyright (C) 2016 Jeremiah Orians 64 * This file is part of M2-Planet. 65 * 66 * M2-Planet is free software: you can redistribute it and/or modify 67 * it under the terms of the GNU General Public License as published by 68 * the Free Software Foundation, either version 3 of the License, or 69 * (at your option) any later version. 70 * 71 * M2-Planet is distributed in the hope that it will be useful, 72 * but WITHOUT ANY WARRANTY; without even the implied warranty of 73 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 74 * GNU General Public License for more details. 75 * 76 * You should have received a copy of the GNU General Public License 77 * along with M2-Planet. If not, see . 78 */ 79 80 81 82 // #FILENAME 1 83 /* Copyright (C) 2016 Jeremiah Orians 84 * This file is part of M2-Planet. 85 * 86 * M2-Planet is free software: you can redistribute it and/or modify 87 * it under the terms of the GNU General Public License as published by 88 * the Free Software Foundation, either version 3 of the License, or 89 * (at your option) any later version. 90 * 91 * M2-Planet is distributed in the hope that it will be useful, 92 * but WITHOUT ANY WARRANTY; without even the implied warranty of 93 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 94 * GNU General Public License for more details. 95 * 96 * You should have received a copy of the GNU General Public License 97 * along with M2-Planet. If not, see . 98 */ 99 100 101 102 103 104 105 106 107 108 typedef SCM ulong; 109 typedef long ssize_t; 110 typedef int pid_t; 111 typedef long intptr_t; 112 typedef ulong uintptr_t; 113 typedef long clock_t; 114 typedef int mode_t; 115 typedef long dev_t; 116 117 // #FILENAME 21 118 119 120 121 122 typedef long ptrdiff_t; 123 typedef ulong size_t; 124 125 126 // #FILENAME 19 127 128 129 130 char* strcpy(char* dest, char const* src) 131 { 132 int i = 0; 133 134 while (0 != src[i]) 135 { 136 dest[i] = src[i]; 137 i = i + 1; 138 } 139 dest[i] = 0; 140 141 return dest; 142 } 143 144 145 char* strncpy(char* dest, char const* src, size_t count) 146 { 147 if(0 == count) return dest; 148 size_t i = 0; 149 while(0 != src[i]) 150 { 151 dest[i] = src[i]; 152 i = i + 1; 153 if(count == i) return dest; 154 } 155 156 while(i <= count) 157 { 158 dest[i] = 0; 159 i = i + 1; 160 } 161 162 return dest; 163 } 164 165 166 char* strcat(char* dest, char const* src) 167 { 168 int i = 0; 169 int j = 0; 170 while(0 != dest[i]) i = i + 1; 171 while(0 != src[j]) 172 { 173 dest[i] = src[j]; 174 i = i + 1; 175 j = j + 1; 176 } 177 dest[i] = 0; 178 return dest; 179 } 180 181 182 char* strncat(char* dest, char const* src, size_t count) 183 { 184 size_t i = 0; 185 size_t j = 0; 186 while(0 != dest[i]) i = i + 1; 187 while(0 != src[j]) 188 { 189 if(count == j) 190 { 191 dest[i] = 0; 192 return dest; 193 } 194 dest[i] = src[j]; 195 i = i + 1; 196 j = j + 1; 197 } 198 dest[i] = 0; 199 return dest; 200 } 201 202 203 size_t strlen(char const* str ) 204 { 205 size_t i = 0; 206 while(0 != str[i]) i = i + 1; 207 return i; 208 } 209 210 211 size_t strnlen_s(char const* str, size_t strsz ) 212 { 213 size_t i = 0; 214 while(0 != str[i]) 215 { 216 if(strsz == i) return i; 217 i = i + 1; 218 } 219 return i; 220 } 221 222 223 int strcmp(char const* lhs, char const* rhs ) 224 { 225 int i = 0; 226 while(0 != lhs[i]) 227 { 228 if(lhs[i] != rhs[i]) return lhs[i] - rhs[i]; 229 i = i + 1; 230 } 231 232 return lhs[i] - rhs[i]; 233 } 234 235 236 int strncmp(char const* lhs, char const* rhs, size_t count) 237 { 238 size_t i = 0; 239 while(count > i) 240 { 241 if(0 == lhs[i]) break; 242 if(lhs[i] != rhs[i]) return lhs[i] - rhs[i]; 243 i = i + 1; 244 } 245 246 return 0; 247 } 248 249 250 char* strchr(char const* str, int ch) 251 { 252 char* p = str; 253 while(ch != p[0]) 254 { 255 if(0 == p[0]) return 0; 256 p = p + 1; 257 } 258 if(0 == p[0]) return 0; 259 return p; 260 } 261 262 263 char* strrchr(char const* str, int ch) 264 { 265 char* p = str; 266 int i = 0; 267 while(0 != p[i]) i = i + 1; 268 while(ch != p[i]) 269 { 270 if(0 == i) return 0; 271 i = i - 1; 272 } 273 return (p + i); 274 } 275 276 277 size_t strspn(char const* dest, char const* src) 278 { 279 if(0 == dest[0]) return 0; 280 int i = 0; 281 while(0 != strchr(src, dest[i])) i = i + 1; 282 return i; 283 } 284 285 286 size_t strcspn(char const* dest, char const* src) 287 { 288 int i = 0; 289 while(0 == strchr(src, dest[i])) i = i + 1; 290 return i; 291 } 292 293 294 char* strpbrk(char const* dest, char const* breakset) 295 { 296 char* p = dest; 297 char* s; 298 while(0 != p[0]) 299 { 300 s = strchr(breakset, p[0]); 301 if(0 != s) return strchr(p, s[0]); 302 p = p + 1; 303 } 304 return p; 305 } 306 307 308 void* memset(void* dest, int ch, size_t count) 309 { 310 if(0 == dest) return dest; 311 size_t i = 0; 312 char* s = dest; 313 while(i < count) 314 { 315 s[i] = ch; 316 i = i + 1; 317 } 318 return dest; 319 } 320 321 322 void* memcpy(void* dest, void const* src, size_t count) 323 { 324 if(0 == dest) return dest; 325 if(0 == src) return 0; 326 327 char* s1 = dest; 328 char const* s2 = src; 329 size_t i = 0; 330 while(i < count) 331 { 332 s1[i] = s2[i]; 333 i = i + 1; 334 } 335 return dest; 336 } 337 338 void* memmove(void* dest, void const* src, size_t count) 339 { 340 if (dest < src) return memcpy (dest, src, count); 341 char *p = dest; 342 char const *q = src; 343 count = count - 1; 344 while (count >= 0) 345 { 346 p[count] = q[count]; 347 count = count - 1; 348 } 349 return dest; 350 } 351 352 353 int memcmp(void const* lhs, void const* rhs, size_t count) 354 { 355 if(0 == count) return 0; 356 size_t i = 0; 357 char const* s1 = lhs; 358 char const* s2 = rhs; 359 while(s1[i] == s2[i]) 360 { 361 i = i + 1; 362 if(count == i) return count; 363 } 364 return (s1[i] - s2[i]); 365 } 366 // #FILENAME 23 367 368 369 370 371 372 373 374 375 // #FILENAME sha256sum.c 22 376 377 378 // #FILENAME 1 379 /* Copyright (C) 2016 Jeremiah Orians 380 * This file is part of M2-Planet. 381 * 382 * M2-Planet is free software: you can redistribute it and/or modify 383 * it under the terms of the GNU General Public License as published by 384 * the Free Software Foundation, either version 3 of the License, or 385 * (at your option) any later version. 386 * 387 * M2-Planet is distributed in the hope that it will be useful, 388 * but WITHOUT ANY WARRANTY; without even the implied warranty of 389 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 390 * GNU General Public License for more details. 391 * 392 * You should have received a copy of the GNU General Public License 393 * along with M2-Planet. If not, see . 394 */ 395 396 397 398 399 400 // #FILENAME 1 401 /* Copyright (C) 2016 Jeremiah Orians 402 * This file is part of M2-Planet. 403 * 404 * M2-Planet is free software: you can redistribute it and/or modify 405 * it under the terms of the GNU General Public License as published by 406 * the Free Software Foundation, either version 3 of the License, or 407 * (at your option) any later version. 408 * 409 * M2-Planet is distributed in the hope that it will be useful, 410 * but WITHOUT ANY WARRANTY; without even the implied warranty of 411 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 412 * GNU General Public License for more details. 413 * 414 * You should have received a copy of the GNU General Public License 415 * along with M2-Planet. If not, see . 416 */ 417 418 419 420 421 422 // #FILENAME 1 423 /* Copyright (C) 2020 Jeremiah Orians 424 * This file is part of M2-Planet. 425 * 426 * M2-Planet is free software: you can redistribute it and/or modify 427 * it under the terms of the GNU General Public License as published by 428 * the Free Software Foundation, either version 3 of the License, or 429 * (at your option) any later version. 430 * 431 * M2-Planet is distributed in the hope that it will be useful, 432 * but WITHOUT ANY WARRANTY; without even the implied warranty of 433 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 434 * GNU General Public License for more details. 435 * 436 * You should have received a copy of the GNU General Public License 437 * along with M2-Planet. If not, see . 438 */ 439 440 441 442 443 444 445 446 // #FILENAME 1 447 /* Copyright (C) 2020 Jeremiah Orians 448 * This file is part of M2-Planet. 449 * 450 * M2-Planet is free software: you can redistribute it and/or modify 451 * it under the terms of the GNU General Public License as published by 452 * the Free Software Foundation, either version 3 of the License, or 453 * (at your option) any later version. 454 * 455 * M2-Planet is distributed in the hope that it will be useful, 456 * but WITHOUT ANY WARRANTY; without even the implied warranty of 457 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 458 * GNU General Public License for more details. 459 * 460 * You should have received a copy of the GNU General Public License 461 * along with M2-Planet. If not, see . 462 */ 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 int chmod(char *pathname, int mode) 488 { 489 asm("LOAD_EFFECTIVE_ADDRESS_rdi %16" 490 "LOAD_INTEGER_rdi" 491 "LOAD_EFFECTIVE_ADDRESS_rsi %8" 492 "LOAD_INTEGER_rsi" 493 "LOAD_IMMEDIATE_rax %90" 494 "SYSCALL"); 495 } 496 497 498 int fchmod(int a, mode_t b) 499 { 500 asm("LOAD_EFFECTIVE_ADDRESS_rdi %16" 501 "LOAD_INTEGER_rdi" 502 "LOAD_EFFECTIVE_ADDRESS_rsi %8" 503 "LOAD_INTEGER_rsi" 504 "LOAD_IMMEDIATE_rax %91" 505 "SYSCALL"); 506 } 507 508 509 int mkdir(char const* a, mode_t b) 510 { 511 asm("LOAD_EFFECTIVE_ADDRESS_rdi %16" 512 "LOAD_INTEGER_rdi" 513 "LOAD_EFFECTIVE_ADDRESS_rsi %8" 514 "LOAD_INTEGER_rsi" 515 "LOAD_IMMEDIATE_rax %83" 516 "SYSCALL"); 517 } 518 519 520 int mknod(char const* a, mode_t b, dev_t c) 521 { 522 asm("LOAD_EFFECTIVE_ADDRESS_rdi %24" 523 "LOAD_INTEGER_rdi" 524 "LOAD_EFFECTIVE_ADDRESS_rsi %16" 525 "LOAD_INTEGER_rsi" 526 "LOAD_EFFECTIVE_ADDRESS_rdx %8" 527 "LOAD_INTEGER_rdx" 528 "LOAD_IMMEDIATE_rax %133" 529 "SYSCALL"); 530 } 531 532 533 mode_t umask(mode_t m) 534 { 535 asm("LOAD_EFFECTIVE_ADDRESS_rdi %8" 536 "LOAD_INTEGER_rdi" 537 "LOAD_IMMEDIATE_rax %95" 538 "SYSCALL"); 539 } 540 541 // #FILENAME 27 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 // #FILENAME 21 576 577 578 // #FILENAME 1 579 /* Copyright (C) 2016 Jeremiah Orians 580 * This file is part of M2-Planet. 581 * 582 * M2-Planet is free software: you can redistribute it and/or modify 583 * it under the terms of the GNU General Public License as published by 584 * the Free Software Foundation, either version 3 of the License, or 585 * (at your option) any later version. 586 * 587 * M2-Planet is distributed in the hope that it will be useful, 588 * but WITHOUT ANY WARRANTY; without even the implied warranty of 589 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 590 * GNU General Public License for more details. 591 * 592 * You should have received a copy of the GNU General Public License 593 * along with M2-Planet. If not, see . 594 */ 595 596 597 598 599 600 601 602 // #FILENAME 1 603 /* Copyright (C) 2016 Jeremiah Orians 604 * This file is part of M2-Planet. 605 * 606 * M2-Planet is free software: you can redistribute it and/or modify 607 * it under the terms of the GNU General Public License as published by 608 * the Free Software Foundation, either version 3 of the License, or 609 * (at your option) any later version. 610 * 611 * M2-Planet is distributed in the hope that it will be useful, 612 * but WITHOUT ANY WARRANTY; without even the implied warranty of 613 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 614 * GNU General Public License for more details. 615 * 616 * You should have received a copy of the GNU General Public License 617 * along with M2-Planet. If not, see . 618 */ 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 int open(char* name, int flag, int mode) 638 { 639 asm("LOAD_EFFECTIVE_ADDRESS_rdi %24" 640 "LOAD_INTEGER_rdi" 641 "LOAD_EFFECTIVE_ADDRESS_rsi %16" 642 "LOAD_INTEGER_rsi" 643 "LOAD_EFFECTIVE_ADDRESS_rdx %8" 644 "LOAD_INTEGER_rdx" 645 "LOAD_IMMEDIATE_rax %2" 646 "SYSCALL"); 647 } 648 649 650 651 652 653 // #FILENAME 27 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 // #FILENAME 23 682 683 684 // #FILENAME 1 685 /* Copyright (C) 2020 Jeremiah Orians 686 * This file is part of M2-Planet. 687 * 688 * M2-Planet is free software: you can redistribute it and/or modify 689 * it under the terms of the GNU General Public License as published by 690 * the Free Software Foundation, either version 3 of the License, or 691 * (at your option) any later version. 692 * 693 * M2-Planet is distributed in the hope that it will be useful, 694 * but WITHOUT ANY WARRANTY; without even the implied warranty of 695 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 696 * GNU General Public License for more details. 697 * 698 * You should have received a copy of the GNU General Public License 699 * along with M2-Planet. If not, see . 700 */ 701 702 703 704 705 706 707 708 // #FILENAME 1 709 /* Copyright (C) 2020 Jeremiah Orians 710 * This file is part of M2-Planet. 711 * 712 * M2-Planet is free software: you can redistribute it and/or modify 713 * it under the terms of the GNU General Public License as published by 714 * the Free Software Foundation, either version 3 of the License, or 715 * (at your option) any later version. 716 * 717 * M2-Planet is distributed in the hope that it will be useful, 718 * but WITHOUT ANY WARRANTY; without even the implied warranty of 719 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 720 * GNU General Public License for more details. 721 * 722 * You should have received a copy of the GNU General Public License 723 * along with M2-Planet. If not, see . 724 */ 725 726 727 728 729 730 731 732 733 void* malloc(unsigned size); 734 735 int access(char* pathname, int mode) 736 { 737 asm("LOAD_EFFECTIVE_ADDRESS_rdi %16" 738 "LOAD_INTEGER_rdi" 739 "LOAD_EFFECTIVE_ADDRESS_rsi %8" 740 "LOAD_INTEGER_rsi" 741 "LOAD_IMMEDIATE_rax %21" 742 "SYSCALL"); 743 } 744 745 int chdir(char* path) 746 { 747 asm("LOAD_EFFECTIVE_ADDRESS_rdi %8" 748 "LOAD_INTEGER_rdi" 749 "LOAD_IMMEDIATE_rax %80" 750 "SYSCALL"); 751 } 752 753 int fchdir(int fd) 754 { 755 asm("LOAD_EFFECTIVE_ADDRESS_rdi %8" 756 "LOAD_INTEGER_rdi" 757 "LOAD_IMMEDIATE_rax %81" 758 "SYSCALL"); 759 } 760 761 void _exit(int value); 762 763 int fork() 764 { 765 asm("LOAD_IMMEDIATE_rax %57" 766 "LOAD_IMMEDIATE_rdi %0" 767 "SYSCALL"); 768 } 769 770 771 int waitpid (int pid, int* status_ptr, int options) 772 { 773 /* Uses wait4 with struct rusage *ru set to NULL */ 774 asm("LOAD_EFFECTIVE_ADDRESS_rdi %24" 775 "LOAD_INTEGER_rdi" 776 "LOAD_EFFECTIVE_ADDRESS_rsi %16" 777 "LOAD_INTEGER_rsi" 778 "LOAD_EFFECTIVE_ADDRESS_rdx %8" 779 "LOAD_INTEGER_rdx" 780 "LOAD_IMMEDIATE_r10 %0" 781 "LOAD_IMMEDIATE_rax %61" 782 "SYSCALL"); 783 } 784 785 786 int execve(char* file_name, char** argv, char** envp) 787 { 788 asm("LOAD_EFFECTIVE_ADDRESS_rdi %24" 789 "LOAD_INTEGER_rdi" 790 "LOAD_EFFECTIVE_ADDRESS_rsi %16" 791 "LOAD_INTEGER_rsi" 792 "LOAD_EFFECTIVE_ADDRESS_rdx %8" 793 "LOAD_INTEGER_rdx" 794 "LOAD_IMMEDIATE_rax %59" 795 "SYSCALL"); 796 } 797 798 int read(int fd, char* buf, unsigned count) 799 { /*maybe*/ 800 asm("LOAD_EFFECTIVE_ADDRESS_rdi %24" 801 "LOAD_INTEGER_rdi" 802 "LOAD_EFFECTIVE_ADDRESS_rsi %16" 803 "LOAD_INTEGER_rsi" 804 "LOAD_EFFECTIVE_ADDRESS_rdx %8" 805 "LOAD_INTEGER_rdx" 806 "LOAD_IMMEDIATE_rax %0" 807 "SYSCALL"); 808 } 809 810 int write(int fd, char* buf, unsigned count) 811 {/*maybe*/ 812 asm("LOAD_EFFECTIVE_ADDRESS_rdi %24" 813 "LOAD_INTEGER_rdi" 814 "LOAD_EFFECTIVE_ADDRESS_rsi %16" 815 "LOAD_INTEGER_rsi" 816 "LOAD_EFFECTIVE_ADDRESS_rdx %8" 817 "LOAD_INTEGER_rdx" 818 "LOAD_IMMEDIATE_rax %1" 819 "SYSCALL"); 820 } 821 822 int lseek(int fd, int offset, int whence) 823 { 824 asm("LOAD_EFFECTIVE_ADDRESS_rdi %24" 825 "LOAD_INTEGER_rdi" 826 "LOAD_EFFECTIVE_ADDRESS_rsi %16" 827 "LOAD_INTEGER_rsi" 828 "LOAD_EFFECTIVE_ADDRESS_rdx %8" 829 "LOAD_INTEGER_rdx" 830 "LOAD_IMMEDIATE_rax %8" 831 "SYSCALL"); 832 } 833 834 835 int close(int fd) 836 { 837 asm("LOAD_EFFECTIVE_ADDRESS_rdi %8" 838 "LOAD_INTEGER_rdi" 839 "LOAD_IMMEDIATE_rax %3" 840 "SYSCALL"); 841 } 842 843 844 int unlink (char* filename) 845 { 846 asm("LOAD_EFFECTIVE_ADDRESS_rdi %8" 847 "LOAD_INTEGER_rdi" 848 "LOAD_IMMEDIATE_rax %87" 849 "SYSCALL"); 850 } 851 852 853 int _getcwd(char* buf, int size) 854 { 855 asm("LOAD_EFFECTIVE_ADDRESS_rdi %16" 856 "LOAD_INTEGER_rdi" 857 "LOAD_EFFECTIVE_ADDRESS_rsi %8" 858 "LOAD_INTEGER_rsi" 859 "LOAD_IMMEDIATE_rax %79" 860 "SYSCALL"); 861 } 862 863 864 char* getcwd(char* buf, unsigned size) 865 { 866 int c = _getcwd(buf, size); 867 if(0 == c) return 0; 868 return buf; 869 } 870 871 872 char* getwd(char* buf) 873 { 874 return getcwd(buf, 4096); 875 } 876 877 878 char* get_current_dir_name() 879 { 880 return getcwd(malloc(4096), 4096); 881 } 882 883 884 int brk(void *addr) 885 { 886 asm("LOAD_RSP_IMMEDIATE_into_rax %8" 887 "PUSH_RAX" 888 "LOAD_IMMEDIATE_rax %12" 889 "POP_RBX" 890 "COPY_rbx_to_rdi" 891 "SYSCALL"); 892 } 893 894 struct utsname 895 { 896 char sysname[65]; /* Operating system name (e.g., "Linux") */ 897 char nodename[65]; /* Name within "some implementation-defined network" */ 898 char release[65]; /* Operating system release (e.g., "2.6.28") */ 899 char version[65]; /* Operating system version */ 900 char machine[65]; /* Hardware identifier */ 901 }; 902 903 int uname(struct utsname* unameData) 904 { 905 asm("LOAD_EFFECTIVE_ADDRESS_rdi %8" 906 "LOAD_INTEGER_rdi" 907 "LOAD_IMMEDIATE_rax %63" 908 "SYSCALL"); 909 } 910 911 // #FILENAME 27 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 // #FILENAME 25 929 930 931 // #FILENAME 1 932 /* Copyright (C) 2016 Jeremiah Orians 933 * This file is part of M2-Planet. 934 * 935 * M2-Planet is free software: you can redistribute it and/or modify 936 * it under the terms of the GNU General Public License as published by 937 * the Free Software Foundation, either version 3 of the License, or 938 * (at your option) any later version. 939 * 940 * M2-Planet is distributed in the hope that it will be useful, 941 * but WITHOUT ANY WARRANTY; without even the implied warranty of 942 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 943 * GNU General Public License for more details. 944 * 945 * You should have received a copy of the GNU General Public License 946 * along with M2-Planet. If not, see . 947 */ 948 949 950 951 952 953 954 955 // #FILENAME 1 956 /* Copyright (C) 2016 Jeremiah Orians 957 * This file is part of M2-Planet. 958 * 959 * M2-Planet is free software: you can redistribute it and/or modify 960 * it under the terms of the GNU General Public License as published by 961 * the Free Software Foundation, either version 3 of the License, or 962 * (at your option) any later version. 963 * 964 * M2-Planet is distributed in the hope that it will be useful, 965 * but WITHOUT ANY WARRANTY; without even the implied warranty of 966 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 967 * GNU General Public License for more details. 968 * 969 * You should have received a copy of the GNU General Public License 970 * along with M2-Planet. If not, see . 971 */ 972 973 974 975 976 977 978 979 980 981 982 983 void exit(int value); 984 985 long _malloc_ptr; 986 long _brk_ptr; 987 988 void free(void* l) 989 { 990 return; 991 } 992 993 994 void* malloc(unsigned size) 995 { 996 if(0 == _brk_ptr) 997 { 998 _brk_ptr = brk(0); 999 _malloc_ptr = _brk_ptr; 1000 } 1001 1002 if(_brk_ptr < _malloc_ptr + size) 1003 { 1004 _brk_ptr = brk(_malloc_ptr + size); 1005 if(-1 == _brk_ptr) return 0; 1006 } 1007 1008 long old_malloc = _malloc_ptr; 1009 _malloc_ptr = _malloc_ptr + size; 1010 return old_malloc; 1011 } 1012 1013 1014 void* memset(void* ptr, int value, int num) 1015 { 1016 char* s; 1017 for(s = ptr; 0 < num; num = num - 1) 1018 { 1019 s[0] = value; 1020 s = s + 1; 1021 } 1022 1023 return ptr; 1024 } 1025 1026 1027 void* calloc(int count, int size) 1028 { 1029 void* ret = malloc(count * size); 1030 if(0 == ret) return 0; 1031 memset(ret, 0, (count * size)); 1032 return ret; 1033 } 1034 1035 1036 /* USED EXCLUSIVELY BY MKSTEMP */ 1037 void __set_name(char* s, int i) 1038 { 1039 s[5] = '0' + (i % 10); 1040 i = i / 10; 1041 s[4] = '0' + (i % 10); 1042 i = i / 10; 1043 s[3] = '0' + (i % 10); 1044 i = i / 10; 1045 s[2] = '0' + (i % 10); 1046 i = i / 10; 1047 s[1] = '0' + (i % 10); 1048 i = i / 10; 1049 s[0] = '0' + i; 1050 } 1051 1052 int mkstemp(char *template) 1053 { 1054 int i = 0; 1055 while(0 != template[i]) i = i + 1; 1056 i = i - 1; 1057 1058 /* String MUST be more than 6 characters in length */ 1059 if(i < 6) return -1; 1060 1061 int count = 6; 1062 int c; 1063 while(count > 0) 1064 { 1065 c = template[i]; 1066 /* last 6 chars must be X */ 1067 if('X' != c) return -1; 1068 template[i] = '0'; 1069 i = i - 1; 1070 count = count - 1; 1071 } 1072 1073 int fd = -1; 1074 count = -1; 1075 /* open will return -17 or other values */ 1076 while(0 > fd) 1077 { 1078 /* Just give up after the planet has blown up */ 1079 if(9000 < count) return -1; 1080 1081 /* Try upto 9000 unique filenames before stopping */ 1082 count = count + 1; 1083 __set_name(template+i+1, count); 1084 1085 /* Pray we can */ 1086 fd = open(template, 2 | 00100 | 00200, 00600); 1087 } 1088 1089 /* well that only took count many tries */ 1090 return fd; 1091 } 1092 // #FILENAME 24 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 // #FILENAME 27 1104 1105 1106 1107 /* Required constants */ 1108 /* For file I/O*/ 1109 1110 1111 1112 /* For lseek */ 1113 1114 1115 1116 1117 /* Actual format of FILE */ 1118 struct __IO_FILE 1119 { 1120 int fd; 1121 int bufmode; /* O_RDONLY = 0, O_WRONLY = 1 */ 1122 int bufpos; 1123 int file_pos; 1124 int buflen; 1125 char* buffer; 1126 struct __IO_FILE* next; 1127 struct __IO_FILE* prev; 1128 }; 1129 1130 /* Now give us the FILE we all love */ 1131 typedef struct __IO_FILE FILE; 1132 1133 /* Required variables */ 1134 FILE* stdin; 1135 FILE* stdout; 1136 FILE* stderr; 1137 FILE* __list; 1138 1139 void __init_io() 1140 { 1141 __list = 0; 1142 stdin = calloc(1, sizeof(FILE)); 1143 stdin->fd = 0; 1144 stdin->bufmode = 0; 1145 stdin->buflen = 1; 1146 stdin->buffer = calloc(2, sizeof(char)); 1147 1148 stdout = calloc(1, sizeof(FILE)); 1149 stdout->fd = 1; 1150 stdout->bufmode = 1; 1151 stdout->buflen = 512; 1152 stdout->buffer = calloc(514, sizeof(char)); 1153 1154 stderr = calloc(1, sizeof(FILE)); 1155 stderr->fd = 2; 1156 stderr->bufmode = 1; 1157 stderr->buflen = 512; 1158 stderr->buffer = calloc(514, sizeof(char)); 1159 } 1160 1161 1162 /* Flush all IO on exit */ 1163 int fflush(FILE* stream); 1164 void __kill_io() 1165 { 1166 fflush(stdout); 1167 fflush(stderr); 1168 while(0 != __list) 1169 { 1170 fflush(__list); 1171 __list = __list->next; 1172 } 1173 } 1174 1175 /* Standard C functions */ 1176 /* Getting */ 1177 int fgetc(FILE* f) 1178 { 1179 /* Only read on read buffers */ 1180 if(1 == f->bufmode) return 0xFFFFFFFF; 1181 1182 /* Deal with stdin */ 1183 if(0 == f->fd) 1184 { 1185 f->bufpos = 0; 1186 int r = read(f->fd, f->buffer, 1); 1187 1188 /* Catch special case of STDIN gets nothing (AN EOF) */ 1189 if(0 == r) return 0xFFFFFFFF; 1190 } 1191 1192 /* Catch EOF */ 1193 if(f->buflen <= f->bufpos) return 0xFFFFFFFF; 1194 1195 /* Deal with standard case */ 1196 int ret = f->buffer[f->bufpos]; 1197 f->bufpos = f->bufpos + 1; 1198 1199 /* Ensure 0xFF doesn't return EOF */ 1200 return (ret & 0xFF); 1201 } 1202 1203 size_t fread( void* buffer, size_t size, size_t count, FILE* stream ) 1204 { 1205 if(0 == size) return 0; 1206 if(0 == count) return 0; 1207 1208 long n = size + count - 1; 1209 char* p = buffer; 1210 long i; 1211 unsigned c; 1212 for(i = 0; i < n; i = i + 1) 1213 { 1214 c = fgetc(stream); 1215 if(0xFFFFFFFF == c) return (i/size); 1216 p[i] = c; 1217 } 1218 1219 return (i/size); 1220 } 1221 1222 int getchar() 1223 { 1224 return fgetc(stdin); 1225 } 1226 1227 1228 char* fgets(char* str, int count, FILE* stream) 1229 { 1230 int i = 0; 1231 int ch; 1232 while(i < count) 1233 { 1234 ch = fgetc(stream); 1235 if(0xFFFFFFFF == ch) break; 1236 1237 str[i] = ch; 1238 i = i + 1; 1239 1240 if('\n' == ch) break; 1241 } 1242 1243 return str; 1244 } 1245 1246 /* Putting */ 1247 void fputc(char s, FILE* f) 1248 { 1249 /* Only write on write buffers */ 1250 if(0 == f->bufmode) return; 1251 1252 /* Add to buffer */ 1253 f->buffer[f->bufpos] = s; 1254 f->bufpos = f->bufpos + 1; 1255 1256 /* Flush if full or '\n' */ 1257 if(f->bufpos == f->buflen) fflush(f); 1258 else if(('\n' == s) && (2 >= f->fd)) fflush(f); 1259 } 1260 1261 size_t fwrite(void const* buffer, size_t size, size_t count, FILE* stream ) 1262 { 1263 long n = size * count; 1264 if(0 == n) return 0; 1265 1266 char* p = buffer; 1267 int c; 1268 long i; 1269 for(i=0; i < n; i = i + 1) 1270 { 1271 c = p[i]; 1272 fputc(c, stream); 1273 } 1274 1275 return (i/size); 1276 } 1277 1278 void putchar(char s) 1279 { 1280 fputc(s, stdout); 1281 } 1282 1283 1284 int fputs(char const* str, FILE* stream) 1285 { 1286 while(0 != str[0]) 1287 { 1288 fputc(str[0], stream); 1289 str = str + 1; 1290 } 1291 return 0; 1292 } 1293 1294 1295 int puts(char const* str) 1296 { 1297 fputs(str, stdout); 1298 fputc('\n', stdout); 1299 return 0; 1300 } 1301 1302 1303 /* File management */ 1304 FILE* fopen(char const* filename, char const* mode) 1305 { 1306 int f; 1307 FILE* fi = calloc(1, sizeof(FILE)); 1308 fi->next = __list; 1309 if(0 != __list) __list->prev = fi; 1310 __list = fi; 1311 int size; 1312 1313 if('w' == mode[0]) f = open(filename, 1|00100|001000 , 00600); 1314 else f = open(filename, 0, 0); /* Everything else is a read */ 1315 1316 /* Negative numbers are error codes */ 1317 if(0 > f) 1318 { 1319 return 0; 1320 } 1321 1322 if('w' == mode[0]) 1323 { 1324 /* Buffer as much as possible */ 1325 fi->buffer = malloc(0x1000 * sizeof(char)); 1326 fi->buflen = 0x1000; 1327 fi->bufmode = 1; 1328 } 1329 else 1330 { 1331 /* Get enough buffer to read it all */ 1332 size = lseek(f, 0, 2); 1333 fi->buffer = malloc((size + 1) * sizeof(char)); 1334 fi->buflen = size; 1335 fi->bufmode = 0; 1336 1337 /* Now read it all */ 1338 lseek(f, 0, 0); 1339 read(f, fi->buffer, size); 1340 } 1341 1342 fi->fd = f; 1343 return fi; 1344 } 1345 1346 FILE* fdopen(int fd, char* mode) 1347 { 1348 FILE* fi = calloc(1, sizeof(FILE)); 1349 fi->next = __list; 1350 if(0 != __list) __list->prev = fi; 1351 __list = fi; 1352 int size; 1353 1354 if('w' == mode[0]) 1355 { 1356 /* Buffer as much as possible */ 1357 fi->buffer = malloc(0x1000 * sizeof(char)); 1358 fi->buflen = 0x1000; 1359 fi->bufmode = 1; 1360 } 1361 else 1362 { 1363 /* Get enough buffer to read it all */ 1364 size = lseek(fd, 0, 2); 1365 fi->buffer = malloc((size + 1) * sizeof(char)); 1366 fi->buflen = size; 1367 fi->bufmode = 0; 1368 1369 /* Now read it all */ 1370 lseek(fd, 0, 0); 1371 read(fd, fi->buffer, size); 1372 } 1373 1374 fi->fd = fd; 1375 return fi; 1376 } 1377 1378 1379 int fflush(FILE* stream) 1380 { 1381 /* We only need to flush on writes */ 1382 if(0 == stream->bufmode) return 0; 1383 1384 /* If nothing to flush */ 1385 if(0 ==stream->bufpos) return 0; 1386 1387 /* The actual flushing */ 1388 int error = write(stream->fd, stream->buffer, stream->bufpos); 1389 1390 /* Keep track of position */ 1391 stream->file_pos = stream->file_pos + stream->bufpos; 1392 stream->bufpos = 0; 1393 1394 return error; 1395 } 1396 1397 1398 int fclose(FILE* stream) 1399 { 1400 /* Deal with STDIN, STDOUT and STDERR */ 1401 /* No close for you */ 1402 if(2 >= stream->fd) return 0; 1403 1404 /* We only need to flush on writes */ 1405 if(1 == stream->bufmode) 1406 { 1407 fflush(stream); 1408 } 1409 1410 /* Need to keep the File Descriptor for a moment */ 1411 int fd = stream->fd; 1412 1413 /* Remove from __list */ 1414 if(0 != stream->prev) stream->prev->next = stream->next; 1415 if(0 != stream->next) stream->next->prev = stream->prev; 1416 /* Deal with special case of first node in __list */ 1417 if (__list == stream) __list = __list->next; 1418 1419 /* Free up the buffer and struct used for FILE */ 1420 free(stream->buffer); 1421 free(stream); 1422 1423 /* Do the actual closing */ 1424 return close(fd); 1425 } 1426 1427 1428 /* File Removal */ 1429 int remove(char *pathname) 1430 { 1431 return unlink(pathname); 1432 } 1433 1434 1435 /* File Positioning */ 1436 int ungetc(int ch, FILE* stream) 1437 { 1438 /* Deal with STDIN, STDOUT and STDERR */ 1439 /* No ungetc for you */ 1440 if(2 >= stream->fd) return 0xFFFFFFFF; 1441 1442 /* You can't unget on a write stream! */ 1443 if(1 == stream->bufmode) return 0xFFFFFFFF; 1444 1445 /* Don't underflow */ 1446 if(0 == stream->bufpos) return 0xFFFFFFFF; 1447 1448 /* Don't let crap be shoved into read stream */ 1449 if(stream->buffer[stream->bufpos - 1] != ch) return 0xFFFFFFFF; 1450 1451 stream->bufpos = stream->bufpos - 1; 1452 1453 return ch; 1454 } 1455 1456 1457 long ftell(FILE* stream) 1458 { 1459 /* Deal with STDIN, STDOUT and STDERR */ 1460 /* No ftell for you */ 1461 if(2 >= stream->fd) return 0; 1462 1463 /* Deal with buffered output */ 1464 if(1 == stream->bufmode) return stream->file_pos + stream->bufpos; 1465 1466 /* Deal with read */ 1467 return stream->bufpos; 1468 } 1469 1470 1471 int fseek(FILE* f, long offset, int whence) 1472 { 1473 /* Deal with STDIN, STDOUT and STDERR */ 1474 /* No seek and destroy missions */ 1475 if(2 >= f->fd) return 0; 1476 1477 /* Deal with ugly case */ 1478 if(1 == f->bufmode) 1479 { 1480 fflush(f); 1481 return lseek(f->fd, offset, whence); 1482 } 1483 1484 /* Deal with read mode */ 1485 int pos; 1486 1487 if(0 == whence) 1488 { 1489 pos = offset; 1490 } 1491 else if(1 == whence) 1492 { 1493 pos = f->bufpos + offset; 1494 } 1495 else if(2 == whence) 1496 { 1497 pos = f->buflen + offset; 1498 } 1499 else return -1; 1500 1501 if(pos < 0) return -1; 1502 if(pos > f->buflen) return -1; 1503 1504 f->bufpos = pos; 1505 return pos; 1506 } 1507 1508 1509 void rewind(FILE* f) 1510 { 1511 fseek(f, 0, 0); 1512 } 1513 // #FILENAME 23 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 // #FILENAME sha256sum.c 24 1532 1533 1534 1535 1536 // #FILENAME "M2libc/bootstrappable.h" 1 1537 /* Copyright (C) 2016 Jeremiah Orians 1538 * This file is part of M2-Planet. 1539 * 1540 * M2-Planet is free software: you can redistribute it and/or modify 1541 * it under the terms of the GNU General Public License as published by 1542 * the Free Software Foundation, either version 3 of the License, or 1543 * (at your option) any later version. 1544 * 1545 * M2-Planet is distributed in the hope that it will be useful, 1546 * but WITHOUT ANY WARRANTY; without even the implied warranty of 1547 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1548 * GNU General Public License for more details. 1549 * 1550 * You should have received a copy of the GNU General Public License 1551 * along with M2-Planet. If not, see . 1552 */ 1553 1554 1555 1556 1557 /* Essential common CONSTANTS*/ 1558 1559 1560 1561 1562 // #FILENAME 1 1563 /* Copyright (C) 2016 Jeremiah Orians 1564 * This file is part of M2-Planet. 1565 * 1566 * M2-Planet is free software: you can redistribute it and/or modify 1567 * it under the terms of the GNU General Public License as published by 1568 * the Free Software Foundation, either version 3 of the License, or 1569 * (at your option) any later version. 1570 * 1571 * M2-Planet is distributed in the hope that it will be useful, 1572 * but WITHOUT ANY WARRANTY; without even the implied warranty of 1573 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1574 * GNU General Public License for more details. 1575 * 1576 * You should have received a copy of the GNU General Public License 1577 * along with M2-Planet. If not, see . 1578 */ 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 void require(int bool, char* error) 1591 { 1592 if(!bool) 1593 { 1594 fputs(error, stderr); 1595 exit(1); 1596 } 1597 } 1598 1599 1600 int match(char* a, char* b) 1601 { 1602 if((0 == a) && (0 == b)) return 1; 1603 if(0 == a) return 0; 1604 if(0 == b) return 0; 1605 1606 int i = -1; 1607 do 1608 { 1609 i = i + 1; 1610 if(a[i] != b[i]) 1611 { 1612 return 0; 1613 } 1614 } while((0 != a[i]) && (0 !=b[i])); 1615 return 1; 1616 } 1617 1618 1619 int in_set(int c, char* s) 1620 { 1621 /* NULL set is always false */ 1622 if(0 == s) return 0; 1623 1624 while(0 != s[0]) 1625 { 1626 if(c == s[0]) return 1; 1627 s = s + 1; 1628 } 1629 return 0; 1630 } 1631 1632 /* INTERNAL ONLY */ 1633 int __index_number(char* s, char c) 1634 { 1635 int i = 0; 1636 while(s[i] != c) 1637 { 1638 i = i + 1; 1639 if(0 == s[i]) return -1; 1640 } 1641 return i; 1642 } 1643 1644 /* INTERNAL ONLY */ 1645 int __toupper(int c) 1646 { 1647 if(in_set(c, "abcdefghijklmnopqrstuvwxyz")) return (c & 0xDF); 1648 return c; 1649 } 1650 1651 /* INTERNAL ONLY */ 1652 int __set_reader(char* set, int mult, char* input) 1653 { 1654 int n = 0; 1655 int i = 0; 1656 int hold; 1657 int negative_p = 0; 1658 1659 if(input[0] == '-') 1660 { 1661 negative_p = 1; 1662 i = i + 1; 1663 } 1664 1665 while(in_set(input[i], set)) 1666 { 1667 n = n * mult; 1668 hold = __index_number(set, __toupper(input[i])); 1669 1670 /* Input managed to change between in_set and index_number */ 1671 if(-1 == hold) return 0; 1672 n = n + hold; 1673 i = i + 1; 1674 } 1675 1676 /* loop exited before NULL and thus invalid input */ 1677 if(0 != input[i]) return 0; 1678 1679 if(negative_p) 1680 { 1681 n = 0 - n; 1682 } 1683 1684 return n; 1685 } 1686 1687 int strtoint(char *a) 1688 { 1689 int result = 0; 1690 /* If NULL string */ 1691 if(0 == a[0]) 1692 { 1693 result = 0; 1694 } 1695 /* Deal with binary*/ 1696 else if ('0' == a[0] && 'b' == a[1]) 1697 { 1698 result = __set_reader("01", 2, a+2); 1699 } 1700 /* Deal with hex */ 1701 else if ('0' == a[0] && 'x' == a[1]) 1702 { 1703 result = __set_reader("0123456789ABCDEFabcdef", 16, a+2); 1704 } 1705 /* Deal with octal */ 1706 else if('0' == a[0]) 1707 { 1708 result = __set_reader("01234567", 8, a+1); 1709 } 1710 /* Deal with decimal */ 1711 else 1712 { 1713 result = __set_reader("0123456789", 10, a); 1714 } 1715 1716 /* Deal with sign extension for 64bit hosts */ 1717 if(0 != (0x80000000 & result)) result = (0xFFFFFFFF << 31) | result; 1718 return result; 1719 } 1720 1721 char* int2str(int x, int base, int signed_p) 1722 { 1723 require(1 < base, "int2str doesn't support a base less than 2\n"); 1724 require(37 > base, "int2str doesn't support a base more than 36\n"); 1725 /* Be overly conservative and save space for 32binary digits and padding null */ 1726 char* p = calloc(34, sizeof(char)); 1727 /* if calloc fails return null to let calling code deal with it */ 1728 if(0 == p) return p; 1729 1730 p = p + 32; 1731 unsigned i; 1732 int sign_p = 0; 1733 char* table = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 1734 1735 if(signed_p && (10 == base) && (0 != (x & 0x80000000))) 1736 { 1737 /* Truncate to 31bits */ 1738 i = -x & 0x7FFFFFFF; 1739 if(0 == i) return "-2147483648"; 1740 sign_p = 1; 1741 } /* Truncate to 32bits */ 1742 else i = x & (0x7FFFFFFF | (1 << 31)); 1743 1744 do 1745 { 1746 p[0] = table[i % base]; 1747 p = p - 1; 1748 i = i / base; 1749 } while(0 < i); 1750 1751 if(sign_p) 1752 { 1753 p[0] = '-'; 1754 p = p - 1; 1755 } 1756 1757 return p + 1; 1758 } 1759 // #FILENAME "M2libc/bootstrappable.h" 27 1760 1761 1762 1763 1764 1765 // #FILENAME sha256sum.c 27 1766 1767 1768 1769 1770 1771 1772 int mask; 1773 1774 /* 1775 * Initialize array of round constants: 1776 * (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311): 1777 */ 1778 unsigned* init_k() 1779 { 1780 unsigned* k = calloc(65, sizeof(unsigned)); 1781 k[0] = 0x428a2f98; 1782 k[1] = 0x71374491; 1783 k[2] = 0xb5c0fbcf; 1784 k[3] = 0xe9b5dba5; 1785 k[4] = 0x3956c25b; 1786 k[5] = 0x59f111f1; 1787 k[6] = 0x923f82a4; 1788 k[7] = 0xab1c5ed5; 1789 k[8] = 0xd807aa98; 1790 k[9] = 0x12835b01; 1791 k[10] = 0x243185be; 1792 k[11] = 0x550c7dc3; 1793 k[12] = 0x72be5d74; 1794 k[13] = 0x80deb1fe; 1795 k[14] = 0x9bdc06a7; 1796 k[15] = 0xc19bf174; 1797 k[16] = 0xe49b69c1; 1798 k[17] = 0xefbe4786; 1799 k[18] = 0x0fc19dc6; 1800 k[19] = 0x240ca1cc; 1801 k[20] = 0x2de92c6f; 1802 k[21] = 0x4a7484aa; 1803 k[22] = 0x5cb0a9dc; 1804 k[23] = 0x76f988da; 1805 k[24] = 0x983e5152; 1806 k[25] = 0xa831c66d; 1807 k[26] = 0xb00327c8; 1808 k[27] = 0xbf597fc7; 1809 k[28] = 0xc6e00bf3; 1810 k[29] = 0xd5a79147; 1811 k[30] = 0x06ca6351; 1812 k[31] = 0x14292967; 1813 k[32] = 0x27b70a85; 1814 k[33] = 0x2e1b2138; 1815 k[34] = 0x4d2c6dfc; 1816 k[35] = 0x53380d13; 1817 k[36] = 0x650a7354; 1818 k[37] = 0x766a0abb; 1819 k[38] = 0x81c2c92e; 1820 k[39] = 0x92722c85; 1821 k[40] = 0xa2bfe8a1; 1822 k[41] = 0xa81a664b; 1823 k[42] = 0xc24b8b70; 1824 k[43] = 0xc76c51a3; 1825 k[44] = 0xd192e819; 1826 k[45] = 0xd6990624; 1827 k[46] = 0xf40e3585; 1828 k[47] = 0x106aa070; 1829 k[48] = 0x19a4c116; 1830 k[49] = 0x1e376c08; 1831 k[50] = 0x2748774c; 1832 k[51] = 0x34b0bcb5; 1833 k[52] = 0x391c0cb3; 1834 k[53] = 0x4ed8aa4a; 1835 k[54] = 0x5b9cca4f; 1836 k[55] = 0x682e6ff3; 1837 k[56] = 0x748f82ee; 1838 k[57] = 0x78a5636f; 1839 k[58] = 0x84c87814; 1840 k[59] = 0x8cc70208; 1841 k[60] = 0x90befffa; 1842 k[61] = 0xa4506ceb; 1843 k[62] = 0xbef9a3f7; 1844 k[63] = 0xc67178f2; 1845 return k; 1846 } 1847 1848 unsigned* init_h() 1849 { 1850 unsigned* h = calloc(9, sizeof(unsigned)); 1851 h[0] = 0x6a09e667; 1852 h[1] = 0xbb67ae85; 1853 h[2] = 0x3c6ef372; 1854 h[3] = 0xa54ff53a; 1855 h[4] = 0x510e527f; 1856 h[5] = 0x9b05688c; 1857 h[6] = 0x1f83d9ab; 1858 h[7] = 0x5be0cd19; 1859 return h; 1860 } 1861 1862 struct buffer_state 1863 { 1864 char* p; 1865 size_t len; 1866 size_t total_len; 1867 int single_one_delivered; /* bool */ 1868 int total_len_delivered; /* bool */ 1869 }; 1870 1871 unsigned right_rot(unsigned value, unsigned count) 1872 { 1873 /* 1874 * Defined behaviour in standard C for all count where 0 < count < 32, 1875 * which is what we need here. 1876 */ 1877 1878 value &= mask; 1879 int hold1 = (value >> count) & mask; 1880 int hold2 = (value << (32 - count)) & mask; 1881 int hold = (hold1 | hold2) & mask; 1882 return hold; 1883 } 1884 1885 void init_buf_state(struct buffer_state * state, char* input, size_t len) 1886 { 1887 state->p = input; 1888 state->len = len; 1889 state->total_len = len; 1890 state->single_one_delivered = 0; 1891 state->total_len_delivered = 0; 1892 } 1893 1894 /* Return value: bool */ 1895 int calc_chunk(char* chunk, struct buffer_state * state) 1896 { 1897 size_t space_in_chunk; 1898 1899 if(state->total_len_delivered) 1900 { 1901 return 0; 1902 } 1903 1904 if(state->len >= 64) 1905 { 1906 memcpy(chunk, state->p, 64); 1907 state->p += 64; 1908 state->len -= 64; 1909 return 1; 1910 } 1911 1912 memcpy(chunk, state->p, state->len); 1913 chunk += state->len; 1914 space_in_chunk = 64 - state->len; 1915 state->p += state->len; 1916 state->len = 0; 1917 1918 /* If we are here, space_in_chunk is one at minimum. */ 1919 if(!state->single_one_delivered) 1920 { 1921 chunk[0] = 0x80; 1922 chunk += 1; 1923 space_in_chunk -= 1; 1924 state->single_one_delivered = 1; 1925 } 1926 1927 /* 1928 * Now: 1929 * - either there is enough space left for the total length, and we can conclude, 1930 * - or there is too little space left, and we have to pad the rest of this chunk with zeroes. 1931 * In the latter case, we will conclude at the next invocation of this function. 1932 */ 1933 if(space_in_chunk >= 8) 1934 { 1935 size_t left = space_in_chunk - 8; 1936 size_t len = state->total_len; 1937 int i; 1938 memset(chunk, 0x00, left); 1939 chunk += left; 1940 /* Storing of len * 8 as a big endian 64-bit without overflow. */ 1941 chunk[7] = (len << 3); 1942 len >>= 5; 1943 1944 for(i = 6; i >= 0; i -= 1) 1945 { 1946 chunk[i] = len; 1947 len >>= 8; 1948 } 1949 1950 state->total_len_delivered = 1; 1951 } 1952 else 1953 { 1954 memset(chunk, 0x00, space_in_chunk); 1955 } 1956 1957 return 1; 1958 } 1959 1960 /* 1961 * Limitations: 1962 * - Since input is a pointer in RAM, the data to hash should be in RAM, which could be a problem 1963 * for large data sizes. 1964 * - SHA algorithms theoretically operate on bit strings. However, this implementation has no support 1965 * for bit string lengths that are not multiples of eight, and it really operates on arrays of bytes. 1966 * In particular, the len parameter is a number of bytes. 1967 */ 1968 void calc_sha_256(char* hash, char* input, size_t len) 1969 { 1970 /* 1971 * Note 1: All integers (expect indexes) are 32-bit unsigned integers and addition is calculated modulo 2^32. 1972 * Note 2: For each round, there is one round constant k[i] and one entry in the message schedule array w[i], 0 = i = 63 1973 * Note 3: The compression function uses 8 working variables, a through h 1974 * Note 4: Big-endian convention is used when expressing the constants in this pseudocode, 1975 * and when parsing message block data from bytes to words, for example, 1976 * the first word of the input message "abc" after padding is 0x61626380 1977 */ 1978 /* 1979 * Initialize hash values: 1980 * (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19): 1981 */ 1982 unsigned* k = init_k(); 1983 unsigned* h = init_h(); 1984 unsigned i; 1985 unsigned j; 1986 unsigned hold1; 1987 unsigned hold2; 1988 /* 512-bit chunks is what we will operate on. */ 1989 char* chunk = calloc(65, sizeof(char)); 1990 struct buffer_state* state = calloc(1, sizeof(struct buffer_state)); 1991 init_buf_state(state, input, len); 1992 unsigned* ah = calloc(9, sizeof(unsigned)); 1993 char *p; 1994 unsigned* w = calloc(17, sizeof(unsigned)); 1995 unsigned s0; 1996 unsigned s1; 1997 unsigned ch; 1998 unsigned temp1; 1999 unsigned temp2; 2000 unsigned maj; 2001 2002 while(calc_chunk(chunk, state)) 2003 { 2004 p = chunk; 2005 2006 /* Initialize working variables to current hash value: */ 2007 for(i = 0; i < 8; i += 1) 2008 { 2009 ah[i] = h[i]; 2010 } 2011 2012 /* Compression function main loop: */ 2013 for(i = 0; i < 4; i += 1) 2014 { 2015 /* 2016 * The w-array is really w[64], but since we only need 2017 * 16 of them at a time, we save stack by calculating 2018 * 16 at a time. 2019 * 2020 * This optimization was not there initially and the 2021 * rest of the comments about w[64] are kept in their 2022 * initial state. 2023 */ 2024 /* 2025 * create a 64-entry message schedule array w[0..63] of 32-bit words 2026 * (The initial values in w[0..63] don't matter, so many implementations zero them here) 2027 * copy chunk into first 16 words w[0..15] of the message schedule array 2028 */ 2029 2030 for(j = 0; j < 16; j += 1) 2031 { 2032 if(i == 0) 2033 { 2034 w[j] = ((p[0] & 0xFF) << 24) | ((p[1] & 0xFF) << 16) | ((p[2] & 0xFF) << 8) | (p[3] & 0xFF); 2035 p += 4; 2036 } 2037 else 2038 { 2039 /* Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array: */ 2040 hold1 = (j + 1) & 0xf; 2041 hold2 = w[hold1]; 2042 s0 = right_rot(hold2, 7) ^ right_rot(hold2, 18) ^ ((hold2 & mask) >> 3); 2043 2044 hold1 = (j + 14) & 0xf; 2045 hold2 = w[hold1]; 2046 s1 = right_rot(hold2, 17) ^ right_rot(hold2, 19) ^ ((hold2 & mask) >> 10); 2047 2048 w[j] += s0 + w[(j + 9) & 0xf] + s1; 2049 } 2050 2051 s1 = right_rot(ah[4], 6) ^ right_rot(ah[4], 11) ^ right_rot(ah[4], 25); 2052 ch = (ah[4] & ah[5]) ^ (~ah[4] & ah[6]); 2053 temp1 = ah[7] + s1 + ch + k[i << 4 | j] + w[j]; 2054 s0 = right_rot(ah[0], 2) ^ right_rot(ah[0], 13) ^ right_rot(ah[0], 22); 2055 maj = (ah[0] & ah[1]) ^ (ah[0] & ah[2]) ^ (ah[1] & ah[2]); 2056 temp2 = s0 + maj; 2057 ah[7] = ah[6]; 2058 ah[6] = ah[5]; 2059 ah[5] = ah[4]; 2060 ah[4] = ah[3] + temp1; 2061 ah[3] = ah[2]; 2062 ah[2] = ah[1]; 2063 ah[1] = ah[0]; 2064 ah[0] = temp1 + temp2; 2065 } 2066 } 2067 2068 /* Add the compressed chunk to the current hash value: */ 2069 for(i = 0; i < 8; i += 1) 2070 { 2071 h[i] += ah[i]; 2072 } 2073 } 2074 2075 /* Produce the final hash value (big-endian): */ 2076 i = 0; 2077 for(j = 0; i < 8; i += 1) 2078 { 2079 hash[j] = ((h[i] >> 24) & 0xFF); 2080 j += 1; 2081 hash[j] = ((h[i] >> 16) & 0xFF); 2082 j += 1; 2083 hash[j] = ((h[i] >> 8) & 0xFF); 2084 j += 1; 2085 hash[j] = (h[i] & 0xFF); 2086 j += 1; 2087 } 2088 } 2089 2090 struct list 2091 { 2092 int found; 2093 char* name; 2094 FILE* f; 2095 size_t size; 2096 char* buffer; 2097 char* hash; 2098 struct list* next; 2099 }; 2100 2101 void bad_checkfile(char* filename) 2102 { 2103 fputs(filename, stdout); 2104 puts(": no properly formatted SHA256 checksum lines found"); 2105 } 2106 2107 int hex2int(char c, char* filename) 2108 { 2109 if((c >= '0') && (c <= '9')) return (c - 48); 2110 else if((c >= 'a') && (c <= 'f')) return (c - 87); 2111 else if ((c >= 'F') && (c <= 'F')) return (c - 55); 2112 bad_checkfile(filename); 2113 exit(1); 2114 } 2115 2116 char* hash_to_string(char* a) 2117 { 2118 char* table = "0123456789abcdef"; 2119 char* r = calloc(66, sizeof(char)); 2120 int i; 2121 int j = 0; 2122 int c; 2123 for(i = 0; i < 32; i += 1) 2124 { 2125 c = a[i] & 0xFF; 2126 r[j] = table[(c >> 4)]; 2127 j += 1; 2128 r[j] = table[(c & 0xF)]; 2129 j += 1; 2130 } 2131 return r; 2132 } 2133 2134 int check_file(char* b, char* filename) 2135 { 2136 int r = 1; 2137 size_t i; 2138 int hold1; 2139 int hold2; 2140 FILE* f; 2141 char* name = calloc(4097, sizeof(char)); 2142 char* hash = calloc(33, sizeof(char)); 2143 char* hash2 = calloc(33, sizeof(char)); 2144 size_t size; 2145 char* buffer; 2146 go_again: 2147 for(i = 0; i < 32; i += 1) 2148 { 2149 hold1 = hex2int(b[0], filename); 2150 hold2 = hex2int(b[1], filename); 2151 hash[i] = (hold1 << 4) + hold2; 2152 b += 2; 2153 } 2154 2155 if((' ' != b[0]) || (' ' != b[1])) 2156 { 2157 bad_checkfile(filename); 2158 exit(1); 2159 } 2160 2161 b += 2; 2162 for(i = 0; i < 4096; i += 1) 2163 { 2164 if('\n' == b[0]) 2165 { 2166 name[i] = 0; 2167 b += 1; 2168 break; 2169 } 2170 name[i] = b[0]; 2171 b += 1; 2172 } 2173 2174 f = fopen(name, "r"); 2175 if(0 == f) 2176 { 2177 fputs(name, stdout); 2178 puts(": No such file or directory"); 2179 exit(1); 2180 } 2181 else 2182 { 2183 fseek(f, 0, 2); 2184 size = ftell(f); 2185 rewind(f); 2186 buffer = calloc(size + 1, sizeof(char)); 2187 fread(buffer, sizeof(char), size, f); 2188 calc_sha_256(hash2, buffer, size); 2189 if(match(hash_to_string(hash), hash_to_string(hash2))) 2190 { 2191 fputs(name, stdout); 2192 puts(": OK"); 2193 } 2194 else 2195 { 2196 fputs(name, stdout); 2197 fputs(": FAILED\nWanted: ", stdout); 2198 fputs(hash_to_string(hash), stdout); 2199 fputs("\nReceived: ", stdout); 2200 puts(hash_to_string(hash2)); 2201 r = 0; 2202 } 2203 } 2204 2205 if(0 == b[0]) return r; 2206 goto go_again; 2207 } 2208 2209 /* reverse the linked list */ 2210 void reverse(struct list** head) 2211 { 2212 struct list* prev = 0; 2213 struct list* current = *head; 2214 struct list* next = 0; 2215 while (current != 0) 2216 { 2217 next = current->next; 2218 current->next = prev; 2219 prev = current; 2220 current = next; 2221 } 2222 *head = prev; 2223 } 2224 2225 int main(int argc, char **argv) 2226 { 2227 struct list* l = 0; 2228 struct list* t = 0; 2229 size_t read; 2230 int check = 0; 2231 int r = 1; 2232 char* output_file = ""; 2233 FILE* output = stdout; 2234 mask = (0x7FFFFFFF << 1) | 0x1; 2235 2236 int i = 1; 2237 while(i <= argc) 2238 { 2239 if(0 == argv[i]) 2240 { 2241 i += 1; 2242 } 2243 else if(match(argv[i], "-c") || match(argv[i], "--check")) 2244 { 2245 check = 1; 2246 i += 1; 2247 } 2248 else if (match(argv[i], "-o") || match(argv[i], "--output")) 2249 { 2250 output_file = argv[i + 1]; 2251 i += 2; 2252 if (output != stdout) { 2253 fclose(output); 2254 } 2255 output = fopen(output_file, "w"); 2256 require(output != 0, "Output file cannot be opened!\n"); 2257 } 2258 else if(match(argv[i], "-h") || match(argv[i], "--help")) 2259 { 2260 puts("Usage: sha256sum [--check]"); 2261 exit(0); 2262 } 2263 else 2264 { 2265 t = calloc(1, sizeof(struct list)); 2266 t->hash = calloc(33, sizeof(char)); 2267 t->name = argv[i]; 2268 t->f = fopen(t->name, "r"); 2269 if(0 != t->f) 2270 { 2271 t->found = 1; 2272 fseek(t->f, 0, 2); 2273 t->size = ftell(t->f); 2274 rewind(t->f); 2275 t->buffer = calloc(t->size + 1, sizeof(char)); 2276 read = fread(t->buffer, sizeof(char), t->size, t->f); 2277 } 2278 t->next = l; 2279 l = t; 2280 i += 1; 2281 } 2282 } 2283 reverse(&l); 2284 2285 if(check) 2286 { 2287 while(0 != l) 2288 { 2289 if(l->found) 2290 { 2291 if(!check_file(l->buffer, l->name)) r = 0; 2292 } 2293 else 2294 { 2295 fputs(l->name, stdout); 2296 puts(": No such file or directory"); 2297 exit(1); 2298 } 2299 l = l->next; 2300 } 2301 } 2302 else 2303 { 2304 while(0 != l) 2305 { 2306 if(l->found) 2307 { 2308 calc_sha_256(l->hash, l->buffer, l->size); 2309 fputs(hash_to_string(l->hash), output); 2310 fputs(" ", output); 2311 fputs(l->name, output); 2312 fputc('\n', output); 2313 } 2314 else 2315 { 2316 fputs(l->name, output); 2317 fputs(": No such file or directory\n", output); 2318 exit(1); 2319 } 2320 l = l->next; 2321 } 2322 } 2323 if (output != stdout) { 2324 fclose(output); 2325 } 2326 2327 if(r) return 0; 2328 else return 1; 2329 }