Serenity Operating System
at master 1236 lines 35 kB view raw
1/* 2 * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/Assertions.h> 8#include <AK/CharacterTypes.h> 9#include <AK/FloatingPointStringConversions.h> 10#include <AK/HashMap.h> 11#include <AK/Noncopyable.h> 12#include <AK/Random.h> 13#include <AK/StdLibExtras.h> 14#include <AK/Types.h> 15#include <AK/Utf8View.h> 16#include <alloca.h> 17#include <assert.h> 18#include <bits/pthread_cancel.h> 19#include <ctype.h> 20#include <errno.h> 21#include <fcntl.h> 22#include <pthread.h> 23#include <signal.h> 24#include <spawn.h> 25#include <stdio.h> 26#include <stdlib.h> 27#include <string.h> 28#include <sys/auxv.h> 29#include <sys/internals.h> 30#include <sys/ioctl.h> 31#include <sys/mman.h> 32#include <sys/stat.h> 33#include <sys/sysmacros.h> 34#include <sys/wait.h> 35#include <syscall.h> 36#include <unistd.h> 37#include <wchar.h> 38 39static void strtons(char const* str, char** endptr) 40{ 41 assert(endptr); 42 char* ptr = const_cast<char*>(str); 43 while (isspace(*ptr)) { 44 ptr += 1; 45 } 46 *endptr = ptr; 47} 48 49enum Sign { 50 Negative, 51 Positive, 52}; 53 54static Sign strtosign(char const* str, char** endptr) 55{ 56 assert(endptr); 57 if (*str == '+') { 58 *endptr = const_cast<char*>(str + 1); 59 return Sign::Positive; 60 } else if (*str == '-') { 61 *endptr = const_cast<char*>(str + 1); 62 return Sign::Negative; 63 } else { 64 *endptr = const_cast<char*>(str); 65 return Sign::Positive; 66 } 67} 68 69enum DigitConsumeDecision { 70 Consumed, 71 PosOverflow, 72 NegOverflow, 73 Invalid, 74}; 75 76template<typename T, T min_value, T max_value> 77class NumParser { 78 AK_MAKE_NONMOVABLE(NumParser); 79 80public: 81 NumParser(Sign sign, int base) 82 : m_base(base) 83 , m_num(0) 84 , m_sign(sign) 85 { 86 m_cutoff = positive() ? (max_value / base) : (min_value / base); 87 m_max_digit_after_cutoff = positive() ? (max_value % base) : (min_value % base); 88 } 89 90 int parse_digit(char ch) 91 { 92 int digit; 93 if (isdigit(ch)) 94 digit = ch - '0'; 95 else if (islower(ch)) 96 digit = ch - ('a' - 10); 97 else if (isupper(ch)) 98 digit = ch - ('A' - 10); 99 else 100 return -1; 101 102 if (static_cast<T>(digit) >= m_base) 103 return -1; 104 105 return digit; 106 } 107 108 DigitConsumeDecision consume(char ch) 109 { 110 int digit = parse_digit(ch); 111 if (digit == -1) 112 return DigitConsumeDecision::Invalid; 113 114 if (!can_append_digit(digit)) { 115 if (m_sign != Sign::Negative) { 116 return DigitConsumeDecision::PosOverflow; 117 } else { 118 return DigitConsumeDecision::NegOverflow; 119 } 120 } 121 122 m_num *= m_base; 123 m_num += positive() ? digit : -digit; 124 125 return DigitConsumeDecision::Consumed; 126 } 127 128 T number() const { return m_num; }; 129 130private: 131 bool can_append_digit(int digit) 132 { 133 bool const is_below_cutoff = positive() ? (m_num < m_cutoff) : (m_num > m_cutoff); 134 135 if (is_below_cutoff) { 136 return true; 137 } else { 138 return m_num == m_cutoff && digit <= m_max_digit_after_cutoff; 139 } 140 } 141 142 bool positive() const 143 { 144 return m_sign != Sign::Negative; 145 } 146 147 const T m_base; 148 T m_num; 149 T m_cutoff; 150 int m_max_digit_after_cutoff; 151 Sign m_sign; 152}; 153 154typedef NumParser<int, INT_MIN, INT_MAX> IntParser; 155typedef NumParser<long long, LONG_LONG_MIN, LONG_LONG_MAX> LongLongParser; 156typedef NumParser<unsigned long long, 0ULL, ULONG_LONG_MAX> ULongLongParser; 157 158static bool is_either(char* str, int offset, char lower, char upper) 159{ 160 char ch = *(str + offset); 161 return ch == lower || ch == upper; 162} 163 164template<typename Callback> 165inline int generate_unique_filename(char* pattern, size_t suffix_length, Callback callback) 166{ 167 size_t length = strlen(pattern); 168 169 if (length < 6 + suffix_length || memcmp(pattern + length - 6 - suffix_length, "XXXXXX", 6)) 170 return EINVAL; 171 172 size_t start = length - 6 - suffix_length; 173 174 constexpr char random_characters[] = "abcdefghijklmnopqrstuvwxyz0123456789"; 175 176 for (int attempt = 0; attempt < 100; ++attempt) { 177 for (int i = 0; i < 6; ++i) 178 pattern[start + i] = random_characters[(arc4random() % (sizeof(random_characters) - 1))]; 179 if (callback() == IterationDecision::Break) 180 return 0; 181 } 182 183 return EEXIST; 184} 185 186static bool is_infinity_string(char* parse_ptr, char** endptr) 187{ 188 if (is_either(parse_ptr, 0, 'i', 'I')) { 189 if (is_either(parse_ptr, 1, 'n', 'N')) { 190 if (is_either(parse_ptr, 2, 'f', 'F')) { 191 parse_ptr += 3; 192 if (is_either(parse_ptr, 0, 'i', 'I')) { 193 if (is_either(parse_ptr, 1, 'n', 'N')) { 194 if (is_either(parse_ptr, 2, 'i', 'I')) { 195 if (is_either(parse_ptr, 3, 't', 'T')) { 196 if (is_either(parse_ptr, 4, 'y', 'Y')) { 197 parse_ptr += 5; 198 } 199 } 200 } 201 } 202 } 203 if (endptr) 204 *endptr = parse_ptr; 205 206 return true; 207 } 208 } 209 } 210 211 return false; 212} 213 214static bool is_nan_string(char* parse_ptr, char** endptr) 215{ 216 // FIXME: Actually parse (or at least skip) the (n-char-sequenceopt) part 217 if (is_either(parse_ptr, 0, 'n', 'N')) { 218 if (is_either(parse_ptr, 1, 'a', 'A')) { 219 if (is_either(parse_ptr, 2, 'n', 'N')) { 220 if (endptr) 221 *endptr = parse_ptr + 3; 222 return true; 223 } 224 } 225 } 226 227 return false; 228} 229 230template<FloatingPoint T> 231static T c_str_to_floating_point(char const* str, char** endptr) 232{ 233 // First, they decompose the input string into three parts: 234 char* parse_ptr = const_cast<char*>(str); 235 236 // An initial, possibly empty, sequence of white-space characters (as specified by isspace()) 237 strtons(parse_ptr, &parse_ptr); 238 239 // A subject sequence interpreted as a floating-point constant or representing infinity or NaN 240 241 if (*parse_ptr == '\0') { 242 if (endptr) 243 *endptr = const_cast<char*>(str); 244 return 0.; 245 } 246 247 bool is_hex = [&] { 248 // A hexfloat must start with either 0x, 0X, -0x or -0X and have something after it 249 char const* parse_head = parse_ptr; 250 if (*parse_head == '-') 251 ++parse_head; 252 253 if (*parse_head != '0') 254 return false; 255 256 ++parse_head; 257 258 if (*parse_head != 'x') 259 return false; 260 261 ++parse_head; 262 263 // We must have at least one digit but it can come after the "decimal" point. 264 265 if (is_ascii_hex_digit(*parse_head)) 266 return true; 267 268 if (*parse_head != '.') 269 return false; 270 271 ++parse_head; 272 273 return is_ascii_hex_digit(*parse_head); 274 }(); 275 276 AK::FloatingPointParseResults<T> double_parse_result; 277 if (is_hex) { 278 // A 0x or 0X, then a non-empty sequence of hexadecimal digits optionally containing a radix character; 279 // then an optional binary exponent part consisting of the character 'p' or the character 'P', 280 // optionally followed by a '+' or '-' character, and then followed by one or more decimal digits 281 282 double_parse_result = AK::parse_first_hexfloat_until_zero_character<T>(parse_ptr); 283 } else { 284 // A non-empty sequence of decimal digits optionally containing a radix character; 285 // then an optional exponent part consisting of the character 'e' or the character 'E', 286 // optionally followed by a '+' or '-' character, and then followed by one or more decimal digits 287 double_parse_result = AK::parse_first_floating_point_until_zero_character<T>(parse_ptr); 288 } 289 290 if (double_parse_result.error == AK::FloatingPointError::None) { 291 // The only way to get NaN (which we shouldn't) or infinities is rounding up to them so we 292 // have to set ERANGE in that case. 293 if (!__builtin_isfinite(double_parse_result.value)) 294 errno = ERANGE; 295 296 if (endptr) 297 *endptr = const_cast<char*>(double_parse_result.end_ptr); 298 return double_parse_result.value; 299 } 300 301 if (double_parse_result.error == AK::FloatingPointError::RoundedDownToZero || double_parse_result.error == AK::FloatingPointError::OutOfRange) { 302 // This is a special case for strtod, where we have a double so close to zero we had to round 303 // it to zero, in which case we have to set ERANGE 304 errno = ERANGE; 305 306 if (endptr) 307 *endptr = const_cast<char*>(double_parse_result.end_ptr); 308 return double_parse_result.value; 309 } 310 311 // The only way we are here is if the input was not valid for parse_first_floating_point or not a valid hex float 312 // So the only cases left are: 313 // - One of INF or INFINITY, ignoring case 314 // - One of NAN or NAN(n-char-sequenceopt), ignoring case in the NAN part 315 316 const Sign sign = strtosign(parse_ptr, &parse_ptr); 317 318 if (is_infinity_string(parse_ptr, endptr)) { 319 // Don't set errno to ERANGE here: 320 // The caller may want to distinguish between "input is 321 // literal infinity" and "input is not literal infinity 322 // but did not fit into double". 323 if (sign != Sign::Negative) 324 return static_cast<T>(__builtin_huge_val()); 325 else 326 return static_cast<T>(-__builtin_huge_val()); 327 } 328 329 if (is_nan_string(parse_ptr, endptr)) { 330 errno = ERANGE; 331 // FIXME: Do we actually want to return "different" NaN bit values? 332 if (sign != Sign::Negative) 333 return static_cast<T>(__builtin_nan("")); 334 else 335 return static_cast<T>(-__builtin_nan("")); 336 } 337 338 // If no conversion could be performed, 0 shall be returned, and errno may be set to [EINVAL]. 339 // FIXME: This is in the posix standard linked from strtod but not in implementations of strtod 340 // and not in the man pages for linux strtod. 341 if (endptr) 342 *endptr = const_cast<char*>(str); 343 return 0; 344} 345 346extern "C" { 347 348void exit(int status) 349{ 350 __cxa_finalize(nullptr); 351 352 if (secure_getenv("LIBC_DUMP_MALLOC_STATS")) 353 serenity_dump_malloc_stats(); 354 355 extern void _fini(); 356 _fini(); 357 fflush(nullptr); 358 359#ifndef _DYNAMIC_LOADER 360 __pthread_key_destroy_for_current_thread(); 361#endif 362 363 _exit(status); 364} 365 366static void __atexit_to_cxa_atexit(void* handler) 367{ 368 reinterpret_cast<void (*)()>(handler)(); 369} 370 371int atexit(void (*handler)()) 372{ 373 return __cxa_atexit(__atexit_to_cxa_atexit, (void*)handler, nullptr); 374} 375 376void _abort() 377{ 378 // According to the GCC manual __builtin_trap() can call abort() so using it here might not seem safe at first. However, 379 // on all the platforms we support GCC emits an undefined instruction instead of a call. 380 __builtin_trap(); 381} 382 383void abort() 384{ 385 // For starters, send ourselves a SIGABRT. 386 raise(SIGABRT); 387 // If that didn't kill us, try harder. 388 sigset_t set; 389 sigemptyset(&set); 390 sigaddset(&set, SIGABRT); 391 sigprocmask(SIG_UNBLOCK, &set, nullptr); 392 raise(SIGABRT); 393 _abort(); 394} 395 396static HashTable<FlatPtr> s_malloced_environment_variables; 397 398static void free_environment_variable_if_needed(char const* var) 399{ 400 if (!s_malloced_environment_variables.contains((FlatPtr)var)) 401 return; 402 free(const_cast<char*>(var)); 403 s_malloced_environment_variables.remove((FlatPtr)var); 404} 405 406char* getenv(char const* name) 407{ 408 size_t vl = strlen(name); 409 for (size_t i = 0; environ[i]; ++i) { 410 char const* decl = environ[i]; 411 char* eq = strchr(decl, '='); 412 if (!eq) 413 continue; 414 size_t varLength = eq - decl; 415 if (vl != varLength) 416 continue; 417 if (strncmp(decl, name, varLength) == 0) { 418 return eq + 1; 419 } 420 } 421 return nullptr; 422} 423 424char* secure_getenv(char const* name) 425{ 426 if (getauxval(AT_SECURE)) 427 return nullptr; 428 return getenv(name); 429} 430 431// https://pubs.opengroup.org/onlinepubs/9699919799/functions/unsetenv.html 432int unsetenv(char const* name) 433{ 434 auto new_var_len = strlen(name); 435 size_t environ_size = 0; 436 int skip = -1; 437 438 for (; environ[environ_size]; ++environ_size) { 439 char* old_var = environ[environ_size]; 440 char* old_eq = strchr(old_var, '='); 441 VERIFY(old_eq); 442 size_t old_var_len = old_eq - old_var; 443 444 if (new_var_len != old_var_len) 445 continue; // can't match 446 447 if (strncmp(name, old_var, new_var_len) == 0) 448 skip = environ_size; 449 } 450 451 if (skip == -1) 452 return 0; // not found: no failure. 453 454 // Shuffle the existing array down by one. 455 memmove(&environ[skip], &environ[skip + 1], ((environ_size - 1) - skip) * sizeof(environ[0])); 456 environ[environ_size - 1] = nullptr; 457 458 free_environment_variable_if_needed(name); 459 return 0; 460} 461 462int clearenv() 463{ 464 size_t environ_size = 0; 465 for (; environ[environ_size]; ++environ_size) { 466 environ[environ_size] = NULL; 467 } 468 *environ = NULL; 469 return 0; 470} 471 472// https://pubs.opengroup.org/onlinepubs/9699919799/functions/setenv.html 473int setenv(char const* name, char const* value, int overwrite) 474{ 475 if (!overwrite && getenv(name)) 476 return 0; 477 auto const total_length = strlen(name) + strlen(value) + 2; 478 auto* var = (char*)malloc(total_length); 479 snprintf(var, total_length, "%s=%s", name, value); 480 s_malloced_environment_variables.set((FlatPtr)var); 481 return putenv(var); 482} 483 484// A non-evil version of putenv that will strdup the env (and free it later) 485int serenity_putenv(char const* new_var, size_t length) 486{ 487 auto* var = strndup(new_var, length); 488 s_malloced_environment_variables.set((FlatPtr)var); 489 return putenv(var); 490} 491 492// https://pubs.opengroup.org/onlinepubs/9699919799/functions/putenv.html 493int putenv(char* new_var) 494{ 495 char* new_eq = strchr(new_var, '='); 496 497 if (!new_eq) 498 return unsetenv(new_var); 499 500 auto new_var_len = new_eq - new_var; 501 int environ_size = 0; 502 for (; environ[environ_size]; ++environ_size) { 503 char* old_var = environ[environ_size]; 504 char* old_eq = strchr(old_var, '='); 505 VERIFY(old_eq); 506 auto old_var_len = old_eq - old_var; 507 508 if (new_var_len != old_var_len) 509 continue; // can't match 510 511 if (strncmp(new_var, old_var, new_var_len) == 0) { 512 free_environment_variable_if_needed(old_var); 513 environ[environ_size] = new_var; 514 return 0; 515 } 516 } 517 518 // At this point, we need to append the new var. 519 // 2 here: one for the new var, one for the sentinel value. 520 auto** new_environ = static_cast<char**>(kmalloc_array(environ_size + 2, sizeof(char*))); 521 if (new_environ == nullptr) { 522 errno = ENOMEM; 523 return -1; 524 } 525 526 for (int i = 0; environ[i]; ++i) { 527 new_environ[i] = environ[i]; 528 } 529 530 new_environ[environ_size] = new_var; 531 new_environ[environ_size + 1] = nullptr; 532 533 // swap new and old 534 // note that the initial environ is not heap allocated! 535 extern bool __environ_is_malloced; 536 if (__environ_is_malloced) 537 free(environ); 538 __environ_is_malloced = true; 539 environ = new_environ; 540 return 0; 541} 542 543static char const* __progname = NULL; 544 545char const* getprogname() 546{ 547 return __progname; 548} 549 550void setprogname(char const* progname) 551{ 552 for (int i = strlen(progname) - 1; i >= 0; i--) { 553 if (progname[i] == '/') { 554 __progname = progname + i + 1; 555 return; 556 } 557 } 558 559 __progname = progname; 560} 561 562// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtod.html 563double strtod(char const* str, char** endptr) 564{ 565 return c_str_to_floating_point<double>(str, endptr); 566} 567 568// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtold.html 569long double strtold(char const* str, char** endptr) 570{ 571 assert(sizeof(double) == sizeof(long double)); 572 return strtod(str, endptr); 573} 574 575// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtof.html 576float strtof(char const* str, char** endptr) 577{ 578 return c_str_to_floating_point<float>(str, endptr); 579} 580 581// https://pubs.opengroup.org/onlinepubs/9699919799/functions/atof.html 582double atof(char const* str) 583{ 584 return strtod(str, nullptr); 585} 586 587// https://pubs.opengroup.org/onlinepubs/9699919799/functions/atoi.html 588int atoi(char const* str) 589{ 590 long value = strtol(str, nullptr, 10); 591 if (value > INT_MAX) { 592 return INT_MAX; 593 } 594 return value; 595} 596 597// https://pubs.opengroup.org/onlinepubs/9699919799/functions/atol.html 598long atol(char const* str) 599{ 600 return strtol(str, nullptr, 10); 601} 602 603// https://pubs.opengroup.org/onlinepubs/9699919799/functions/atoll.html 604long long atoll(char const* str) 605{ 606 return strtoll(str, nullptr, 10); 607} 608 609static char ptsname_buf[32]; 610// https://pubs.opengroup.org/onlinepubs/9699919799/functions/ptsname.html 611char* ptsname(int fd) 612{ 613 if (ptsname_r(fd, ptsname_buf, sizeof(ptsname_buf)) < 0) 614 return nullptr; 615 return ptsname_buf; 616} 617 618int ptsname_r(int fd, char* buffer, size_t size) 619{ 620 struct stat stat; 621 if (fstat(fd, &stat) < 0) 622 return -1; 623 624 StringBuilder devpts_path_builder; 625 devpts_path_builder.append("/dev/pts/"sv); 626 627 int master_pty_index = 0; 628 // Note: When the user opens a PTY from /dev/ptmx with posix_openpt(), the open file descriptor 629 // points to /dev/ptmx, (major number is 5 and minor number is 2), but internally 630 // in the kernel, it points to a new MasterPTY device. When we do ioctl with TIOCGPTN option 631 // on the open file descriptor, it actually asks the MasterPTY what is the assigned index 632 // of it when the PTYMultiplexer created it. 633 if (ioctl(fd, TIOCGPTN, &master_pty_index) < 0) 634 return -1; 635 636 if (master_pty_index < 0) { 637 errno = EINVAL; 638 return -1; 639 } 640 641 devpts_path_builder.appendff("{:d}", master_pty_index); 642 if (devpts_path_builder.length() > size) { 643 errno = ERANGE; 644 return -1; 645 } 646 memset(buffer, 0, devpts_path_builder.length() + 1); 647 auto full_devpts_path_string = devpts_path_builder.to_deprecated_string(); 648 if (!full_devpts_path_string.copy_characters_to_buffer(buffer, size)) { 649 errno = ERANGE; 650 return -1; 651 } 652 return 0; 653} 654 655static unsigned long s_next_rand = 1; 656 657// https://pubs.opengroup.org/onlinepubs/9699919799/functions/rand.html 658int rand() 659{ 660 s_next_rand = s_next_rand * 1103515245 + 12345; 661 return ((unsigned)(s_next_rand / ((RAND_MAX + 1) * 2)) % (RAND_MAX + 1)); 662} 663 664// https://pubs.opengroup.org/onlinepubs/9699919799/functions/srand.html 665void srand(unsigned seed) 666{ 667 s_next_rand = seed; 668} 669 670// https://pubs.opengroup.org/onlinepubs/9699919799/functions/abs.html 671int abs(int i) 672{ 673 return i < 0 ? -i : i; 674} 675 676// https://pubs.opengroup.org/onlinepubs/9699919799/functions/labs.html 677long int labs(long int i) 678{ 679 return i < 0 ? -i : i; 680} 681 682// https://pubs.opengroup.org/onlinepubs/9699919799/functions/llabs.html 683long long int llabs(long long int i) 684{ 685 return i < 0 ? -i : i; 686} 687 688// https://pubs.opengroup.org/onlinepubs/9699919799/functions/random.html 689long int random() 690{ 691 return rand(); 692} 693 694// https://pubs.opengroup.org/onlinepubs/9699919799/functions/srandom.html 695void srandom(unsigned seed) 696{ 697 srand(seed); 698} 699 700// https://pubs.opengroup.org/onlinepubs/9699919799/functions/system.html 701int system(char const* command) 702{ 703 __pthread_maybe_cancel(); 704 705 if (!command) 706 return 1; 707 708 pid_t child; 709 char const* argv[] = { "sh", "-c", command, nullptr }; 710 if ((errno = posix_spawn(&child, "/bin/sh", nullptr, nullptr, const_cast<char**>(argv), environ))) 711 return -1; 712 int wstatus; 713 waitpid(child, &wstatus, 0); 714 return WEXITSTATUS(wstatus); 715} 716 717// https://pubs.opengroup.org/onlinepubs/9699919799/functions/mktemp.html 718char* mktemp(char* pattern) 719{ 720 auto error = generate_unique_filename(pattern, 0, [&] { 721 struct stat st; 722 int rc = lstat(pattern, &st); 723 if (rc < 0 && errno == ENOENT) 724 return IterationDecision::Break; 725 return IterationDecision::Continue; 726 }); 727 if (error) { 728 pattern[0] = '\0'; 729 errno = error; 730 } 731 return pattern; 732} 733 734// https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkstemp.html 735int mkstemp(char* pattern) 736{ 737 return mkstemps(pattern, 0); 738} 739 740// https://man7.org/linux/man-pages/man3/mkstemps.3.html 741int mkstemps(char* pattern, int suffix_length) 742{ 743 VERIFY(suffix_length >= 0); 744 int fd = -1; 745 auto error = generate_unique_filename(pattern, static_cast<size_t>(suffix_length), [&] { 746 fd = open(pattern, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); // I'm using the flags I saw glibc using. 747 if (fd >= 0) 748 return IterationDecision::Break; 749 return IterationDecision::Continue; 750 }); 751 if (error) { 752 errno = error; 753 return -1; 754 } 755 return fd; 756} 757 758// https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdtemp.html 759char* mkdtemp(char* pattern) 760{ 761 auto error = generate_unique_filename(pattern, 0, [&] { 762 if (mkdir(pattern, 0700) == 0) 763 return IterationDecision::Break; 764 return IterationDecision::Continue; 765 }); 766 if (error) { 767 errno = error; 768 return nullptr; 769 } 770 return pattern; 771} 772 773// https://pubs.opengroup.org/onlinepubs/9699919799/functions/bsearch.html 774void* bsearch(void const* key, void const* base, size_t nmemb, size_t size, int (*compar)(void const*, void const*)) 775{ 776 char* start = static_cast<char*>(const_cast<void*>(base)); 777 while (nmemb > 0) { 778 char* middle_memb = start + (nmemb / 2) * size; 779 int comparison = compar(key, middle_memb); 780 if (comparison == 0) 781 return middle_memb; 782 else if (comparison > 0) { 783 start = middle_memb + size; 784 --nmemb; 785 } 786 nmemb /= 2; 787 } 788 789 return nullptr; 790} 791 792// https://pubs.opengroup.org/onlinepubs/9699919799/functions/div.html 793div_t div(int numerator, int denominator) 794{ 795 div_t result; 796 result.quot = numerator / denominator; 797 result.rem = numerator % denominator; 798 799 if (numerator >= 0 && result.rem < 0) { 800 result.quot++; 801 result.rem -= denominator; 802 } 803 return result; 804} 805 806// https://pubs.opengroup.org/onlinepubs/9699919799/functions/ldiv.html 807ldiv_t ldiv(long numerator, long denominator) 808{ 809 ldiv_t result; 810 result.quot = numerator / denominator; 811 result.rem = numerator % denominator; 812 813 if (numerator >= 0 && result.rem < 0) { 814 result.quot++; 815 result.rem -= denominator; 816 } 817 return result; 818} 819 820// https://pubs.opengroup.org/onlinepubs/9699919799/functions/lldiv.html 821lldiv_t lldiv(long long numerator, long long denominator) 822{ 823 lldiv_t result; 824 result.quot = numerator / denominator; 825 result.rem = numerator % denominator; 826 827 if (numerator >= 0 && result.rem < 0) { 828 result.quot++; 829 result.rem -= denominator; 830 } 831 return result; 832} 833 834// https://pubs.opengroup.org/onlinepubs/9699919799/functions/mblen.html 835int mblen(char const* s, size_t n) 836{ 837 // POSIX: Equivalent to mbtowc(NULL, s, n), but we mustn't change the state of mbtowc. 838 static mbstate_t internal_state = {}; 839 840 // Reset the internal state and ask whether we have shift states. 841 if (s == nullptr) { 842 internal_state = {}; 843 return 0; 844 } 845 846 size_t ret = mbrtowc(nullptr, s, n, &internal_state); 847 848 // Incomplete characters get returned as illegal sequence. 849 if (ret == -2ul) { 850 errno = EILSEQ; 851 return -1; 852 } 853 854 return ret; 855} 856 857// https://pubs.opengroup.org/onlinepubs/9699919799/functions/mbstowcs.html 858size_t mbstowcs(wchar_t* pwcs, char const* s, size_t n) 859{ 860 static mbstate_t state = {}; 861 return mbsrtowcs(pwcs, &s, n, &state); 862} 863 864// https://pubs.opengroup.org/onlinepubs/9699919799/functions/mbtowc.html 865int mbtowc(wchar_t* pwc, char const* s, size_t n) 866{ 867 static mbstate_t internal_state = {}; 868 869 // Reset the internal state and ask whether we have shift states. 870 if (s == nullptr) { 871 internal_state = {}; 872 return 0; 873 } 874 875 size_t ret = mbrtowc(pwc, s, n, &internal_state); 876 877 // Incomplete characters get returned as illegal sequence. 878 // Internal state is undefined, so don't bother with resetting. 879 if (ret == -2ul) { 880 errno = EILSEQ; 881 return -1; 882 } 883 884 return ret; 885} 886 887// https://pubs.opengroup.org/onlinepubs/9699919799/functions/wctomb.html 888int wctomb(char* s, wchar_t wc) 889{ 890 static mbstate_t _internal_state = {}; 891 892 // nullptr asks whether we have state-dependent encodings, but we don't have any. 893 if (s == nullptr) 894 return 0; 895 896 return static_cast<int>(wcrtomb(s, wc, &_internal_state)); 897} 898 899// https://pubs.opengroup.org/onlinepubs/9699919799/functions/wcstombs.html 900size_t wcstombs(char* dest, wchar_t const* src, size_t max) 901{ 902 char* original_dest = dest; 903 while ((size_t)(dest - original_dest) < max) { 904 StringView v { (char const*)src, sizeof(wchar_t) }; 905 906 // FIXME: dependent on locale, for now utf-8 is supported. 907 Utf8View utf8 { v }; 908 if (*utf8.begin() == '\0') { 909 *dest = '\0'; 910 return (size_t)(dest - original_dest); // Exclude null character in returned size 911 } 912 913 for (auto byte : utf8) { 914 if (byte != '\0') 915 *dest++ = byte; 916 } 917 ++src; 918 } 919 return max; 920} 921 922// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtol.html 923long strtol(char const* str, char** endptr, int base) 924{ 925 long long value = strtoll(str, endptr, base); 926 if (value < LONG_MIN) { 927 errno = ERANGE; 928 return LONG_MIN; 929 } else if (value > LONG_MAX) { 930 errno = ERANGE; 931 return LONG_MAX; 932 } 933 return value; 934} 935 936// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtoul.html 937unsigned long strtoul(char const* str, char** endptr, int base) 938{ 939 unsigned long long value = strtoull(str, endptr, base); 940 if (value > ULONG_MAX) { 941 errno = ERANGE; 942 return ULONG_MAX; 943 } 944 return value; 945} 946 947// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtoll.html 948long long strtoll(char const* str, char** endptr, int base) 949{ 950 // Parse spaces and sign 951 char* parse_ptr = const_cast<char*>(str); 952 strtons(parse_ptr, &parse_ptr); 953 const Sign sign = strtosign(parse_ptr, &parse_ptr); 954 955 // Parse base 956 if (base == 0) { 957 if (*parse_ptr == '0') { 958 if (tolower(*(parse_ptr + 1)) == 'x') { 959 base = 16; 960 parse_ptr += 2; 961 } else { 962 base = 8; 963 } 964 } else { 965 base = 10; 966 } 967 } 968 969 // Parse actual digits. 970 LongLongParser digits { sign, base }; 971 bool digits_usable = false; 972 bool should_continue = true; 973 bool overflow = false; 974 do { 975 bool is_a_digit; 976 if (overflow) { 977 is_a_digit = digits.parse_digit(*parse_ptr) >= 0; 978 } else { 979 DigitConsumeDecision decision = digits.consume(*parse_ptr); 980 switch (decision) { 981 case DigitConsumeDecision::Consumed: 982 is_a_digit = true; 983 // The very first actual digit must pass here: 984 digits_usable = true; 985 break; 986 case DigitConsumeDecision::PosOverflow: 987 case DigitConsumeDecision::NegOverflow: 988 is_a_digit = true; 989 overflow = true; 990 break; 991 case DigitConsumeDecision::Invalid: 992 is_a_digit = false; 993 break; 994 default: 995 VERIFY_NOT_REACHED(); 996 } 997 } 998 999 should_continue = is_a_digit; 1000 parse_ptr += should_continue; 1001 } while (should_continue); 1002 1003 if (!digits_usable) { 1004 // No actual number value available. 1005 if (endptr) 1006 *endptr = const_cast<char*>(str); 1007 return 0; 1008 } 1009 1010 if (endptr) 1011 *endptr = parse_ptr; 1012 1013 if (overflow) { 1014 errno = ERANGE; 1015 if (sign != Sign::Negative) { 1016 return LONG_LONG_MAX; 1017 } else { 1018 return LONG_LONG_MIN; 1019 } 1020 } 1021 1022 return digits.number(); 1023} 1024 1025// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtoull.html 1026unsigned long long strtoull(char const* str, char** endptr, int base) 1027{ 1028 // Parse spaces and sign 1029 char* parse_ptr = const_cast<char*>(str); 1030 strtons(parse_ptr, &parse_ptr); 1031 1032 if (base == 16) { 1033 // Dr. POSIX: "If the value of base is 16, the characters 0x or 0X may optionally precede 1034 // the sequence of letters and digits, following the sign if present." 1035 if (*parse_ptr == '0') { 1036 if (tolower(*(parse_ptr + 1)) == 'x') 1037 parse_ptr += 2; 1038 } 1039 } 1040 // Parse base 1041 if (base == 0) { 1042 if (*parse_ptr == '0') { 1043 if (tolower(*(parse_ptr + 1)) == 'x') { 1044 base = 16; 1045 parse_ptr += 2; 1046 } else { 1047 base = 8; 1048 } 1049 } else { 1050 base = 10; 1051 } 1052 } 1053 1054 // Parse actual digits. 1055 ULongLongParser digits { Sign::Positive, base }; 1056 bool digits_usable = false; 1057 bool should_continue = true; 1058 bool overflow = false; 1059 do { 1060 bool is_a_digit; 1061 if (overflow) { 1062 is_a_digit = digits.parse_digit(*parse_ptr) >= 0; 1063 } else { 1064 DigitConsumeDecision decision = digits.consume(*parse_ptr); 1065 switch (decision) { 1066 case DigitConsumeDecision::Consumed: 1067 is_a_digit = true; 1068 // The very first actual digit must pass here: 1069 digits_usable = true; 1070 break; 1071 case DigitConsumeDecision::PosOverflow: 1072 case DigitConsumeDecision::NegOverflow: 1073 is_a_digit = true; 1074 overflow = true; 1075 break; 1076 case DigitConsumeDecision::Invalid: 1077 is_a_digit = false; 1078 break; 1079 default: 1080 VERIFY_NOT_REACHED(); 1081 } 1082 } 1083 1084 should_continue = is_a_digit; 1085 parse_ptr += should_continue; 1086 } while (should_continue); 1087 1088 if (!digits_usable) { 1089 // No actual number value available. 1090 if (endptr) 1091 *endptr = const_cast<char*>(str); 1092 return 0; 1093 } 1094 1095 if (endptr) 1096 *endptr = parse_ptr; 1097 1098 if (overflow) { 1099 errno = ERANGE; 1100 return LONG_LONG_MAX; 1101 } 1102 1103 return digits.number(); 1104} 1105 1106uint32_t arc4random(void) 1107{ 1108 uint32_t buf; 1109 arc4random_buf(&buf, sizeof(buf)); 1110 return buf; 1111} 1112 1113static pthread_mutex_t s_randomness_mutex = PTHREAD_MUTEX_INITIALIZER; 1114static u8* s_randomness_buffer; 1115static size_t s_randomness_index; 1116 1117void arc4random_buf(void* buffer, size_t buffer_size) 1118{ 1119 pthread_mutex_lock(&s_randomness_mutex); 1120 1121 size_t bytes_needed = buffer_size; 1122 auto* ptr = static_cast<u8*>(buffer); 1123 1124 while (bytes_needed > 0) { 1125 if (!s_randomness_buffer || s_randomness_index >= PAGE_SIZE) { 1126 if (!s_randomness_buffer) { 1127 s_randomness_buffer = static_cast<u8*>(mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_RANDOMIZED, 0, 0)); 1128 VERIFY(s_randomness_buffer != MAP_FAILED); 1129 __pthread_fork_atfork_register_child( 1130 [] { 1131 munmap(s_randomness_buffer, PAGE_SIZE); 1132 s_randomness_buffer = nullptr; 1133 s_randomness_index = 0; 1134 }); 1135 } 1136 syscall(SC_getrandom, s_randomness_buffer, PAGE_SIZE); 1137 s_randomness_index = 0; 1138 } 1139 1140 size_t available_bytes = PAGE_SIZE - s_randomness_index; 1141 size_t bytes_to_copy = min(bytes_needed, available_bytes); 1142 1143 memcpy(ptr, s_randomness_buffer + s_randomness_index, bytes_to_copy); 1144 1145 s_randomness_index += bytes_to_copy; 1146 bytes_needed -= bytes_to_copy; 1147 ptr += bytes_to_copy; 1148 } 1149 1150 pthread_mutex_unlock(&s_randomness_mutex); 1151} 1152 1153uint32_t arc4random_uniform(uint32_t max_bounds) 1154{ 1155 return AK::get_random_uniform(max_bounds); 1156} 1157 1158// https://pubs.opengroup.org/onlinepubs/9699919799/functions/realpath.html 1159char* realpath(char const* pathname, char* buffer) 1160{ 1161 if (!pathname) { 1162 errno = EFAULT; 1163 return nullptr; 1164 } 1165 size_t size = PATH_MAX; 1166 bool self_allocated = false; 1167 if (buffer == nullptr) { 1168 // Since we self-allocate, try to sneakily use a smaller buffer instead, in an attempt to use less memory. 1169 size = 64; 1170 buffer = (char*)malloc(size); 1171 self_allocated = true; 1172 } 1173 Syscall::SC_realpath_params params { { pathname, strlen(pathname) }, { buffer, size } }; 1174 int rc = syscall(SC_realpath, &params); 1175 if (rc < 0) { 1176 if (self_allocated) 1177 free(buffer); 1178 errno = -rc; 1179 return nullptr; 1180 } 1181 if (self_allocated && static_cast<size_t>(rc) > size) { 1182 // There was silent truncation, *and* we can simply retry without the caller noticing. 1183 free(buffer); 1184 size = static_cast<size_t>(rc); 1185 buffer = (char*)malloc(size); 1186 params.buffer = { buffer, size }; 1187 rc = syscall(SC_realpath, &params); 1188 if (rc < 0) { 1189 // Can only happen if we lose a race. Let's pretend we lost the race in the first place. 1190 free(buffer); 1191 errno = -rc; 1192 return nullptr; 1193 } 1194 size_t new_size = static_cast<size_t>(rc); 1195 if (new_size < size) { 1196 // If we're here, the symlink has become longer while we were looking at it. 1197 // There's not much we can do, unless we want to loop endlessly 1198 // in this case. Let's leave it up to the caller whether to loop. 1199 free(buffer); 1200 errno = EAGAIN; 1201 return nullptr; 1202 } 1203 } 1204 errno = 0; 1205 return buffer; 1206} 1207 1208// https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_openpt.html 1209int posix_openpt(int flags) 1210{ 1211 if (flags & ~(O_RDWR | O_NOCTTY | O_CLOEXEC)) { 1212 errno = EINVAL; 1213 return -1; 1214 } 1215 1216 return open("/dev/ptmx", flags); 1217} 1218 1219// https://pubs.opengroup.org/onlinepubs/9699919799/functions/grantpt.html 1220int grantpt([[maybe_unused]] int fd) 1221{ 1222 return 0; 1223} 1224 1225// https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlockpt.html 1226int unlockpt([[maybe_unused]] int fd) 1227{ 1228 return 0; 1229} 1230} 1231 1232// https://pubs.opengroup.org/onlinepubs/9699919799/functions/_Exit.html 1233void _Exit(int status) 1234{ 1235 _exit(status); 1236}