Serenity Operating System
at master 1553 lines 47 kB view raw
1/* 2 * Copyright (c) 2021-2022, Andreas Kling <kling@serenityos.org> 3 * Copyright (c) 2021-2022, Kenneth Myhra <kennethmyhra@serenityos.org> 4 * Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org> 5 * Copyright (c) 2022, Matthias Zimmerman <matthias291999@gmail.com> 6 * 7 * SPDX-License-Identifier: BSD-2-Clause 8 */ 9 10#include <AK/DeprecatedString.h> 11#include <AK/FixedArray.h> 12#include <AK/ScopedValueRollback.h> 13#include <AK/StdLibExtras.h> 14#include <AK/Vector.h> 15#include <LibCore/DeprecatedFile.h> 16#include <LibCore/SessionManagement.h> 17#include <LibCore/System.h> 18#include <limits.h> 19#include <stdarg.h> 20#include <stdlib.h> 21#include <sys/ioctl.h> 22#include <sys/mman.h> 23#include <sys/time.h> 24#include <termios.h> 25#include <unistd.h> 26 27#ifdef AK_OS_SERENITY 28# include <Kernel/API/Unveil.h> 29# include <LibCore/Account.h> 30# include <LibSystem/syscall.h> 31# include <serenity.h> 32# include <sys/ptrace.h> 33#endif 34 35#if defined(AK_OS_LINUX) && !defined(MFD_CLOEXEC) 36# include <linux/memfd.h> 37# include <sys/syscall.h> 38 39static int memfd_create(char const* name, unsigned int flags) 40{ 41 return syscall(SYS_memfd_create, name, flags); 42} 43#endif 44 45#if defined(AK_OS_MACOS) 46# include <sys/mman.h> 47#endif 48 49#define HANDLE_SYSCALL_RETURN_VALUE(syscall_name, rc, success_value) \ 50 if ((rc) < 0) { \ 51 return Error::from_syscall(syscall_name##sv, rc); \ 52 } \ 53 return success_value; 54 55// clang-format off 56template<typename T> 57concept SupportsReentrantGetpwent = requires(T passwd, T* ptr) 58{ 59 getpwent_r(&passwd, nullptr, 0, &ptr); 60}; 61// clang-format on 62 63// Note: This has to be in the global namespace for the extern declaration to trick the compiler 64// into finding a declaration of getpwent_r when it doesn't actually exist. 65static ErrorOr<Optional<struct passwd>> getpwent_impl(Span<char> buffer) 66{ 67 if constexpr (SupportsReentrantGetpwent<struct passwd>) { 68 struct passwd passwd; 69 struct passwd* ptr = nullptr; 70 71 extern int getpwent_r(struct passwd*, char*, size_t, struct passwd**); 72 auto result = getpwent_r(&passwd, buffer.data(), buffer.size(), &ptr); 73 74 if (result == 0 && ptr) 75 return passwd; 76 if (result != 0 && result != ENOENT) 77 return Error::from_errno(result); 78 } else { 79 errno = 0; 80 if (auto const* passwd = ::getpwent()) 81 return *passwd; 82 if (errno) 83 return Error::from_errno(errno); 84 } 85 86 return Optional<struct passwd> {}; 87} 88 89// clang-format off 90template<typename T> 91concept SupportsReentrantGetgrent = requires(T group, T* ptr) 92{ 93 getgrent_r(&group, nullptr, 0, &ptr); 94}; 95// clang-format on 96 97// Note: This has to be in the global namespace for the extern declaration to trick the compiler 98// into finding a declaration of getgrent_r when it doesn't actually exist. 99static ErrorOr<Optional<struct group>> getgrent_impl(Span<char> buffer) 100{ 101 if constexpr (SupportsReentrantGetgrent<struct group>) { 102 struct group group; 103 struct group* ptr = nullptr; 104 105 extern int getgrent_r(struct group*, char*, size_t, struct group**); 106 auto result = getgrent_r(&group, buffer.data(), buffer.size(), &ptr); 107 108 if (result == 0 && ptr) 109 return group; 110 if (result != 0 && result != ENOENT) 111 return Error::from_errno(result); 112 } else { 113 errno = 0; 114 if (auto const* group = ::getgrent()) 115 return *group; 116 if (errno) 117 return Error::from_errno(errno); 118 } 119 120 return Optional<struct group> {}; 121} 122 123namespace Core::System { 124 125#ifndef HOST_NAME_MAX 126# ifdef AK_OS_MACOS 127# define HOST_NAME_MAX 255 128# else 129# define HOST_NAME_MAX 64 130# endif 131#endif 132 133#ifdef AK_OS_SERENITY 134 135ErrorOr<void> beep(Optional<size_t> tone) 136{ 137 auto rc = ::sysbeep(tone.value_or(440)); 138 if (rc < 0) 139 return Error::from_syscall("beep"sv, -errno); 140 return {}; 141} 142 143ErrorOr<void> pledge(StringView promises, StringView execpromises) 144{ 145 Syscall::SC_pledge_params params { 146 { promises.characters_without_null_termination(), promises.length() }, 147 { execpromises.characters_without_null_termination(), execpromises.length() }, 148 }; 149 int rc = syscall(SC_pledge, &params); 150 HANDLE_SYSCALL_RETURN_VALUE("pledge", rc, {}); 151} 152 153static ErrorOr<void> unveil_dynamic_loader() 154{ 155 static bool dynamic_loader_unveiled { false }; 156 if (dynamic_loader_unveiled) 157 return {}; 158 // FIXME: Try to find a way to not hardcode the dynamic loader path. 159 constexpr auto dynamic_loader_path = "/usr/lib/Loader.so"sv; 160 constexpr auto dynamic_loader_permissions = "x"sv; 161 162 Syscall::SC_unveil_params params { 163 static_cast<int>(UnveilFlags::CurrentProgram), 164 { dynamic_loader_path.characters_without_null_termination(), dynamic_loader_path.length() }, 165 { dynamic_loader_permissions.characters_without_null_termination(), dynamic_loader_permissions.length() }, 166 }; 167 int rc = syscall(SC_unveil, &params); 168 if (rc < 0) { 169 return Error::from_syscall("unveil (DynamicLoader @ /usr/lib/Loader.so)"sv, rc); 170 } 171 dynamic_loader_unveiled = true; 172 return {}; 173} 174 175ErrorOr<void> unveil(StringView path, StringView permissions) 176{ 177 auto const parsed_path = TRY(Core::SessionManagement::parse_path_with_sid(path)); 178 179 if (permissions.contains('x')) 180 TRY(unveil_dynamic_loader()); 181 182 Syscall::SC_unveil_params params { 183 static_cast<int>(UnveilFlags::CurrentProgram), 184 { parsed_path.characters(), parsed_path.length() }, 185 { permissions.characters_without_null_termination(), permissions.length() }, 186 }; 187 int rc = syscall(SC_unveil, &params); 188 HANDLE_SYSCALL_RETURN_VALUE("unveil", rc, {}); 189} 190 191ErrorOr<void> unveil_after_exec(StringView path, StringView permissions) 192{ 193 auto const parsed_path = TRY(Core::SessionManagement::parse_path_with_sid(path)); 194 195 Syscall::SC_unveil_params params { 196 static_cast<int>(UnveilFlags::AfterExec), 197 { parsed_path.characters(), parsed_path.length() }, 198 { permissions.characters_without_null_termination(), permissions.length() }, 199 }; 200 int rc = syscall(SC_unveil, &params); 201 HANDLE_SYSCALL_RETURN_VALUE("unveil", rc, {}); 202} 203 204ErrorOr<void> sendfd(int sockfd, int fd) 205{ 206 if (::sendfd(sockfd, fd) < 0) 207 return Error::from_syscall("sendfd"sv, -errno); 208 return {}; 209} 210 211ErrorOr<int> recvfd(int sockfd, int options) 212{ 213 auto fd = ::recvfd(sockfd, options); 214 if (fd < 0) 215 return Error::from_syscall("recvfd"sv, -errno); 216 return fd; 217} 218 219ErrorOr<void> ptrace_peekbuf(pid_t tid, void const* tracee_addr, Bytes destination_buf) 220{ 221 Syscall::SC_ptrace_buf_params buf_params { 222 { destination_buf.data(), destination_buf.size() } 223 }; 224 Syscall::SC_ptrace_params params { 225 PT_PEEKBUF, 226 tid, 227 const_cast<void*>(tracee_addr), 228 (FlatPtr)&buf_params, 229 }; 230 int rc = syscall(SC_ptrace, &params); 231 HANDLE_SYSCALL_RETURN_VALUE("ptrace_peekbuf", rc, {}); 232} 233 234ErrorOr<void> mount(int source_fd, StringView target, StringView fs_type, int flags) 235{ 236 if (target.is_null() || fs_type.is_null()) 237 return Error::from_errno(EFAULT); 238 239 Syscall::SC_mount_params params { 240 { target.characters_without_null_termination(), target.length() }, 241 { fs_type.characters_without_null_termination(), fs_type.length() }, 242 source_fd, 243 flags 244 }; 245 int rc = syscall(SC_mount, &params); 246 HANDLE_SYSCALL_RETURN_VALUE("mount", rc, {}); 247} 248 249ErrorOr<void> umount(StringView mount_point) 250{ 251 if (mount_point.is_null()) 252 return Error::from_errno(EFAULT); 253 254 int rc = syscall(SC_umount, mount_point.characters_without_null_termination(), mount_point.length()); 255 HANDLE_SYSCALL_RETURN_VALUE("umount", rc, {}); 256} 257 258ErrorOr<long> ptrace(int request, pid_t tid, void* address, void* data) 259{ 260 auto rc = ::ptrace(request, tid, address, data); 261 if (rc < 0) 262 return Error::from_syscall("ptrace"sv, -errno); 263 return rc; 264} 265 266ErrorOr<void> disown(pid_t pid) 267{ 268 int rc = ::disown(pid); 269 HANDLE_SYSCALL_RETURN_VALUE("disown", rc, {}); 270} 271 272ErrorOr<void> profiling_enable(pid_t pid, u64 event_mask) 273{ 274 int rc = ::profiling_enable(pid, event_mask); 275 HANDLE_SYSCALL_RETURN_VALUE("profiling_enable", rc, {}); 276} 277 278ErrorOr<void> profiling_disable(pid_t pid) 279{ 280 int rc = ::profiling_disable(pid); 281 HANDLE_SYSCALL_RETURN_VALUE("profiling_disable", rc, {}); 282} 283 284ErrorOr<void> profiling_free_buffer(pid_t pid) 285{ 286 int rc = ::profiling_free_buffer(pid); 287 HANDLE_SYSCALL_RETURN_VALUE("profiling_free_buffer", rc, {}); 288} 289#endif 290 291#if !defined(AK_OS_BSD_GENERIC) && !defined(AK_OS_ANDROID) 292ErrorOr<Optional<struct spwd>> getspent() 293{ 294 errno = 0; 295 if (auto* spwd = ::getspent()) 296 return *spwd; 297 if (errno) 298 return Error::from_syscall("getspent"sv, -errno); 299 return Optional<struct spwd> {}; 300} 301 302ErrorOr<Optional<struct spwd>> getspnam(StringView name) 303{ 304 errno = 0; 305 ::setspent(); 306 while (auto* spwd = ::getspent()) { 307 if (spwd->sp_namp == name) 308 return *spwd; 309 } 310 if (errno) 311 return Error::from_syscall("getspnam"sv, -errno); 312 return Optional<struct spwd> {}; 313} 314#endif 315 316#ifndef AK_OS_MACOS 317ErrorOr<int> accept4(int sockfd, sockaddr* address, socklen_t* address_length, int flags) 318{ 319 auto fd = ::accept4(sockfd, address, address_length, flags); 320 if (fd < 0) 321 return Error::from_syscall("accept4"sv, -errno); 322 return fd; 323} 324#endif 325 326ErrorOr<void> sigaction(int signal, struct sigaction const* action, struct sigaction* old_action) 327{ 328 if (::sigaction(signal, action, old_action) < 0) 329 return Error::from_syscall("sigaction"sv, -errno); 330 return {}; 331} 332 333#if defined(AK_OS_SOLARIS) 334ErrorOr<SIG_TYP> signal(int signal, SIG_TYP handler) 335#elif defined(AK_OS_BSD_GENERIC) 336ErrorOr<sig_t> signal(int signal, sig_t handler) 337#else 338ErrorOr<sighandler_t> signal(int signal, sighandler_t handler) 339#endif 340{ 341 auto old_handler = ::signal(signal, handler); 342 if (old_handler == SIG_ERR) 343 return Error::from_syscall("signal"sv, -errno); 344 return old_handler; 345} 346 347ErrorOr<struct stat> fstat(int fd) 348{ 349 struct stat st = {}; 350 if (::fstat(fd, &st) < 0) 351 return Error::from_syscall("fstat"sv, -errno); 352 return st; 353} 354 355ErrorOr<int> fcntl(int fd, int command, ...) 356{ 357 va_list ap; 358 va_start(ap, command); 359 uintptr_t extra_arg = va_arg(ap, uintptr_t); 360 int rc = ::fcntl(fd, command, extra_arg); 361 va_end(ap); 362 if (rc < 0) 363 return Error::from_syscall("fcntl"sv, -errno); 364 return rc; 365} 366 367ErrorOr<void*> mmap(void* address, size_t size, int protection, int flags, int fd, off_t offset, [[maybe_unused]] size_t alignment, [[maybe_unused]] StringView name) 368{ 369#ifdef AK_OS_SERENITY 370 Syscall::SC_mmap_params params { address, size, alignment, protection, flags, fd, offset, { name.characters_without_null_termination(), name.length() } }; 371 ptrdiff_t rc = syscall(SC_mmap, &params); 372 if (rc < 0 && rc > -EMAXERRNO) 373 return Error::from_syscall("mmap"sv, rc); 374 return reinterpret_cast<void*>(rc); 375#else 376 // NOTE: Regular POSIX mmap() doesn't support custom alignment requests. 377 VERIFY(!alignment); 378 auto* ptr = ::mmap(address, size, protection, flags, fd, offset); 379 if (ptr == MAP_FAILED) 380 return Error::from_syscall("mmap"sv, -errno); 381 return ptr; 382#endif 383} 384 385ErrorOr<void> munmap(void* address, size_t size) 386{ 387 if (::munmap(address, size) < 0) 388 return Error::from_syscall("munmap"sv, -errno); 389 return {}; 390} 391 392ErrorOr<int> anon_create([[maybe_unused]] size_t size, [[maybe_unused]] int options) 393{ 394 int fd = -1; 395#if defined(AK_OS_SERENITY) 396 fd = ::anon_create(round_up_to_power_of_two(size, PAGE_SIZE), options); 397#elif defined(AK_OS_LINUX) || defined(AK_OS_FREEBSD) 398 // FIXME: Support more options on Linux. 399 auto linux_options = ((options & O_CLOEXEC) > 0) ? MFD_CLOEXEC : 0; 400 fd = memfd_create("", linux_options); 401 if (fd < 0) 402 return Error::from_errno(errno); 403 if (::ftruncate(fd, size) < 0) { 404 auto saved_errno = errno; 405 TRY(close(fd)); 406 return Error::from_errno(saved_errno); 407 } 408#elif defined(AK_OS_BSD_GENERIC) || defined(AK_OS_EMSCRIPTEN) 409 struct timespec time; 410 clock_gettime(CLOCK_REALTIME, &time); 411 auto name = DeprecatedString::formatted("/shm-{}{}", (unsigned long)time.tv_sec, (unsigned long)time.tv_nsec); 412 fd = shm_open(name.characters(), O_RDWR | O_CREAT | options, 0600); 413 414 if (shm_unlink(name.characters()) == -1) { 415 auto saved_errno = errno; 416 TRY(close(fd)); 417 return Error::from_errno(saved_errno); 418 } 419 420 if (fd < 0) 421 return Error::from_errno(errno); 422 423 if (::ftruncate(fd, size) < 0) { 424 auto saved_errno = errno; 425 TRY(close(fd)); 426 return Error::from_errno(saved_errno); 427 } 428 429 void* addr = ::mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, 0); 430 if (addr == MAP_FAILED) { 431 auto saved_errno = errno; 432 TRY(close(fd)); 433 return Error::from_errno(saved_errno); 434 } 435#endif 436 if (fd < 0) 437 return Error::from_errno(errno); 438 return fd; 439} 440 441ErrorOr<int> open(StringView path, int options, mode_t mode) 442{ 443 return openat(AT_FDCWD, path, options, mode); 444} 445 446ErrorOr<int> openat(int fd, StringView path, int options, mode_t mode) 447{ 448 if (!path.characters_without_null_termination()) 449 return Error::from_syscall("open"sv, -EFAULT); 450#ifdef AK_OS_SERENITY 451 Syscall::SC_open_params params { fd, { path.characters_without_null_termination(), path.length() }, options, mode }; 452 int rc = syscall(SC_open, &params); 453 HANDLE_SYSCALL_RETURN_VALUE("open", rc, rc); 454#else 455 // NOTE: We have to ensure that the path is null-terminated. 456 DeprecatedString path_string = path; 457 int rc = ::openat(fd, path_string.characters(), options, mode); 458 if (rc < 0) 459 return Error::from_syscall("open"sv, -errno); 460 return rc; 461#endif 462} 463 464ErrorOr<void> close(int fd) 465{ 466 if (::close(fd) < 0) 467 return Error::from_syscall("close"sv, -errno); 468 return {}; 469} 470 471ErrorOr<void> ftruncate(int fd, off_t length) 472{ 473 if (::ftruncate(fd, length) < 0) 474 return Error::from_syscall("ftruncate"sv, -errno); 475 return {}; 476} 477 478ErrorOr<struct stat> stat(StringView path) 479{ 480 if (!path.characters_without_null_termination()) 481 return Error::from_syscall("stat"sv, -EFAULT); 482 483 struct stat st = {}; 484#ifdef AK_OS_SERENITY 485 Syscall::SC_stat_params params { { path.characters_without_null_termination(), path.length() }, &st, AT_FDCWD, true }; 486 int rc = syscall(SC_stat, &params); 487 HANDLE_SYSCALL_RETURN_VALUE("stat", rc, st); 488#else 489 DeprecatedString path_string = path; 490 if (::stat(path_string.characters(), &st) < 0) 491 return Error::from_syscall("stat"sv, -errno); 492 return st; 493#endif 494} 495 496ErrorOr<struct stat> lstat(StringView path) 497{ 498 if (!path.characters_without_null_termination()) 499 return Error::from_syscall("lstat"sv, -EFAULT); 500 501 struct stat st = {}; 502#ifdef AK_OS_SERENITY 503 Syscall::SC_stat_params params { { path.characters_without_null_termination(), path.length() }, &st, AT_FDCWD, false }; 504 int rc = syscall(SC_stat, &params); 505 HANDLE_SYSCALL_RETURN_VALUE("lstat", rc, st); 506#else 507 DeprecatedString path_string = path; 508 if (::lstat(path_string.characters(), &st) < 0) 509 return Error::from_syscall("lstat"sv, -errno); 510 return st; 511#endif 512} 513 514ErrorOr<ssize_t> read(int fd, Bytes buffer) 515{ 516 ssize_t rc = ::read(fd, buffer.data(), buffer.size()); 517 if (rc < 0) 518 return Error::from_syscall("read"sv, -errno); 519 return rc; 520} 521 522ErrorOr<ssize_t> write(int fd, ReadonlyBytes buffer) 523{ 524 ssize_t rc = ::write(fd, buffer.data(), buffer.size()); 525 if (rc < 0) 526 return Error::from_syscall("write"sv, -errno); 527 return rc; 528} 529 530ErrorOr<void> kill(pid_t pid, int signal) 531{ 532 if (::kill(pid, signal) < 0) 533 return Error::from_syscall("kill"sv, -errno); 534 return {}; 535} 536 537ErrorOr<void> killpg(int pgrp, int signal) 538{ 539 if (::killpg(pgrp, signal) < 0) 540 return Error::from_syscall("killpg"sv, -errno); 541 return {}; 542} 543 544ErrorOr<int> dup(int source_fd) 545{ 546 int fd = ::dup(source_fd); 547 if (fd < 0) 548 return Error::from_syscall("dup"sv, -errno); 549 return fd; 550} 551 552ErrorOr<int> dup2(int source_fd, int destination_fd) 553{ 554 int fd = ::dup2(source_fd, destination_fd); 555 if (fd < 0) 556 return Error::from_syscall("dup2"sv, -errno); 557 return fd; 558} 559 560ErrorOr<DeprecatedString> ptsname(int fd) 561{ 562 auto* name = ::ptsname(fd); 563 if (!name) 564 return Error::from_syscall("ptsname"sv, -errno); 565 return DeprecatedString(name); 566} 567 568ErrorOr<DeprecatedString> gethostname() 569{ 570 char hostname[HOST_NAME_MAX]; 571 int rc = ::gethostname(hostname, sizeof(hostname)); 572 if (rc < 0) 573 return Error::from_syscall("gethostname"sv, -errno); 574 return DeprecatedString(&hostname[0]); 575} 576 577ErrorOr<void> sethostname(StringView hostname) 578{ 579#if defined(AK_OS_SOLARIS) 580 int rc = ::sethostname(const_cast<char*>(hostname.characters_without_null_termination()), hostname.length()); 581#else 582 int rc = ::sethostname(hostname.characters_without_null_termination(), hostname.length()); 583#endif 584 if (rc < 0) 585 return Error::from_syscall("sethostname"sv, -errno); 586 return {}; 587} 588 589ErrorOr<DeprecatedString> getcwd() 590{ 591 auto* cwd = ::getcwd(nullptr, 0); 592 if (!cwd) 593 return Error::from_syscall("getcwd"sv, -errno); 594 595 DeprecatedString string_cwd(cwd); 596 free(cwd); 597 return string_cwd; 598} 599 600ErrorOr<void> ioctl(int fd, unsigned request, ...) 601{ 602 va_list ap; 603 va_start(ap, request); 604 FlatPtr arg = va_arg(ap, FlatPtr); 605 va_end(ap); 606 if (::ioctl(fd, request, arg) < 0) 607 return Error::from_syscall("ioctl"sv, -errno); 608 return {}; 609} 610 611ErrorOr<struct termios> tcgetattr(int fd) 612{ 613 struct termios ios = {}; 614 if (::tcgetattr(fd, &ios) < 0) 615 return Error::from_syscall("tcgetattr"sv, -errno); 616 return ios; 617} 618 619ErrorOr<void> tcsetattr(int fd, int optional_actions, struct termios const& ios) 620{ 621 if (::tcsetattr(fd, optional_actions, &ios) < 0) 622 return Error::from_syscall("tcsetattr"sv, -errno); 623 return {}; 624} 625 626ErrorOr<int> tcsetpgrp(int fd, pid_t pgrp) 627{ 628 int rc = ::tcsetpgrp(fd, pgrp); 629 if (rc < 0) 630 return Error::from_syscall("tcsetpgrp"sv, -errno); 631 return { rc }; 632} 633 634ErrorOr<void> chmod(StringView pathname, mode_t mode) 635{ 636 if (!pathname.characters_without_null_termination()) 637 return Error::from_syscall("chmod"sv, -EFAULT); 638 639#ifdef AK_OS_SERENITY 640 Syscall::SC_chmod_params params { 641 AT_FDCWD, 642 { pathname.characters_without_null_termination(), pathname.length() }, 643 mode, 644 true 645 }; 646 int rc = syscall(SC_chmod, &params); 647 HANDLE_SYSCALL_RETURN_VALUE("chmod", rc, {}); 648#else 649 DeprecatedString path = pathname; 650 if (::chmod(path.characters(), mode) < 0) 651 return Error::from_syscall("chmod"sv, -errno); 652 return {}; 653#endif 654} 655 656ErrorOr<void> fchmod(int fd, mode_t mode) 657{ 658 if (::fchmod(fd, mode) < 0) 659 return Error::from_syscall("fchmod"sv, -errno); 660 return {}; 661} 662 663ErrorOr<void> fchown(int fd, uid_t uid, gid_t gid) 664{ 665 if (::fchown(fd, uid, gid) < 0) 666 return Error::from_syscall("fchown"sv, -errno); 667 return {}; 668} 669 670ErrorOr<void> lchown(StringView pathname, uid_t uid, gid_t gid) 671{ 672 if (!pathname.characters_without_null_termination()) 673 return Error::from_syscall("chown"sv, -EFAULT); 674 675#ifdef AK_OS_SERENITY 676 Syscall::SC_chown_params params = { { pathname.characters_without_null_termination(), pathname.length() }, uid, gid, AT_FDCWD, false }; 677 int rc = syscall(SC_chown, &params); 678 HANDLE_SYSCALL_RETURN_VALUE("chown", rc, {}); 679#else 680 DeprecatedString path = pathname; 681 if (::chown(path.characters(), uid, gid) < 0) 682 return Error::from_syscall("chown"sv, -errno); 683 return {}; 684#endif 685} 686 687ErrorOr<void> chown(StringView pathname, uid_t uid, gid_t gid) 688{ 689 if (!pathname.characters_without_null_termination()) 690 return Error::from_syscall("chown"sv, -EFAULT); 691 692#ifdef AK_OS_SERENITY 693 Syscall::SC_chown_params params = { { pathname.characters_without_null_termination(), pathname.length() }, uid, gid, AT_FDCWD, true }; 694 int rc = syscall(SC_chown, &params); 695 HANDLE_SYSCALL_RETURN_VALUE("chown", rc, {}); 696#else 697 DeprecatedString path = pathname; 698 if (::lchown(path.characters(), uid, gid) < 0) 699 return Error::from_syscall("lchown"sv, -errno); 700 return {}; 701#endif 702} 703 704ErrorOr<Optional<struct passwd>> getpwent(Span<char> buffer) 705{ 706 return getpwent_impl(buffer); 707} 708 709ErrorOr<Optional<struct passwd>> getpwuid(uid_t uid) 710{ 711 errno = 0; 712 if (auto* pwd = ::getpwuid(uid)) 713 return *pwd; 714 if (errno) 715 return Error::from_syscall("getpwuid"sv, -errno); 716 return Optional<struct passwd> {}; 717} 718 719ErrorOr<Optional<struct group>> getgrent(Span<char> buffer) 720{ 721 return getgrent_impl(buffer); 722} 723 724ErrorOr<Optional<struct group>> getgrgid(gid_t gid) 725{ 726 errno = 0; 727 if (auto* grp = ::getgrgid(gid)) 728 return *grp; 729 if (errno) 730 return Error::from_syscall("getgrgid"sv, -errno); 731 return Optional<struct group> {}; 732} 733 734ErrorOr<Optional<struct passwd>> getpwnam(StringView name) 735{ 736 errno = 0; 737 738 ::setpwent(); 739 if (errno) 740 return Error::from_syscall("getpwnam"sv, -errno); 741 742 while (auto* pw = ::getpwent()) { 743 if (errno) 744 return Error::from_syscall("getpwnam"sv, -errno); 745 if (pw->pw_name == name) 746 return *pw; 747 } 748 if (errno) 749 return Error::from_syscall("getpwnam"sv, -errno); 750 else 751 return Optional<struct passwd> {}; 752} 753 754ErrorOr<Optional<struct group>> getgrnam(StringView name) 755{ 756 errno = 0; 757 758 ::setgrent(); 759 if (errno) 760 return Error::from_syscall("getgrnam"sv, -errno); 761 762 while (auto* gr = ::getgrent()) { 763 if (errno) 764 return Error::from_syscall("getgrnam"sv, -errno); 765 if (gr->gr_name == name) 766 return *gr; 767 } 768 if (errno) 769 return Error::from_syscall("getgrnam"sv, -errno); 770 else 771 return Optional<struct group> {}; 772} 773 774ErrorOr<void> clock_settime(clockid_t clock_id, struct timespec* ts) 775{ 776#ifdef AK_OS_SERENITY 777 int rc = syscall(SC_clock_settime, clock_id, ts); 778 HANDLE_SYSCALL_RETURN_VALUE("clocksettime", rc, {}); 779#else 780 if (::clock_settime(clock_id, ts) < 0) 781 return Error::from_syscall("clocksettime"sv, -errno); 782 return {}; 783#endif 784} 785 786static ALWAYS_INLINE ErrorOr<pid_t> posix_spawn_wrapper(StringView path, posix_spawn_file_actions_t const* file_actions, posix_spawnattr_t const* attr, char* const arguments[], char* const envp[], StringView function_name, decltype(::posix_spawn) spawn_function) 787{ 788 pid_t child_pid; 789 if ((errno = spawn_function(&child_pid, path.to_deprecated_string().characters(), file_actions, attr, arguments, envp))) 790 return Error::from_syscall(function_name, -errno); 791 return child_pid; 792} 793 794ErrorOr<pid_t> posix_spawn(StringView path, posix_spawn_file_actions_t const* file_actions, posix_spawnattr_t const* attr, char* const arguments[], char* const envp[]) 795{ 796 return posix_spawn_wrapper(path, file_actions, attr, arguments, envp, "posix_spawn"sv, ::posix_spawn); 797} 798 799ErrorOr<pid_t> posix_spawnp(StringView path, posix_spawn_file_actions_t* const file_actions, posix_spawnattr_t* const attr, char* const arguments[], char* const envp[]) 800{ 801 return posix_spawn_wrapper(path, file_actions, attr, arguments, envp, "posix_spawnp"sv, ::posix_spawnp); 802} 803 804ErrorOr<off_t> lseek(int fd, off_t offset, int whence) 805{ 806 off_t rc = ::lseek(fd, offset, whence); 807 if (rc < 0) 808 return Error::from_syscall("lseek"sv, -errno); 809 return rc; 810} 811 812ErrorOr<void> endgrent() 813{ 814 int old_errno = 0; 815 swap(old_errno, errno); 816 ::endgrent(); 817 if (errno != 0) 818 return Error::from_syscall("endgrent"sv, -errno); 819 errno = old_errno; 820 return {}; 821} 822 823ErrorOr<WaitPidResult> waitpid(pid_t waitee, int options) 824{ 825 int wstatus; 826 pid_t pid = ::waitpid(waitee, &wstatus, options); 827 if (pid < 0) 828 return Error::from_syscall("waitpid"sv, -errno); 829 return WaitPidResult { pid, wstatus }; 830} 831 832ErrorOr<void> setuid(uid_t uid) 833{ 834 if (::setuid(uid) < 0) 835 return Error::from_syscall("setuid"sv, -errno); 836 return {}; 837} 838 839ErrorOr<void> seteuid(uid_t uid) 840{ 841 if (::seteuid(uid) < 0) 842 return Error::from_syscall("seteuid"sv, -errno); 843 return {}; 844} 845 846ErrorOr<void> setgid(gid_t gid) 847{ 848 if (::setgid(gid) < 0) 849 return Error::from_syscall("setgid"sv, -errno); 850 return {}; 851} 852 853ErrorOr<void> setegid(gid_t gid) 854{ 855 if (::setegid(gid) < 0) 856 return Error::from_syscall("setegid"sv, -errno); 857 return {}; 858} 859 860ErrorOr<void> setpgid(pid_t pid, pid_t pgid) 861{ 862 if (::setpgid(pid, pgid) < 0) 863 return Error::from_syscall("setpgid"sv, -errno); 864 return {}; 865} 866 867ErrorOr<pid_t> setsid() 868{ 869 int rc = ::setsid(); 870 if (rc < 0) 871 return Error::from_syscall("setsid"sv, -errno); 872 return rc; 873} 874 875ErrorOr<pid_t> getsid(pid_t pid) 876{ 877 int rc = ::getsid(pid); 878 if (rc < 0) 879 return Error::from_syscall("getsid"sv, -errno); 880 return rc; 881} 882 883ErrorOr<void> drop_privileges() 884{ 885 auto gid_result = setgid(getgid()); 886 auto uid_result = setuid(getuid()); 887 888 if (gid_result.is_error() || uid_result.is_error()) 889 return Error::from_string_literal("Failed to drop privileges"); 890 891 return {}; 892} 893 894ErrorOr<bool> isatty(int fd) 895{ 896 int rc = ::isatty(fd); 897 if (rc < 0) 898 return Error::from_syscall("isatty"sv, -errno); 899 return rc == 1; 900} 901 902ErrorOr<void> link(StringView old_path, StringView new_path) 903{ 904#ifdef AK_OS_SERENITY 905 Syscall::SC_link_params params { 906 .old_path = { old_path.characters_without_null_termination(), old_path.length() }, 907 .new_path = { new_path.characters_without_null_termination(), new_path.length() }, 908 }; 909 int rc = syscall(SC_link, &params); 910 HANDLE_SYSCALL_RETURN_VALUE("link", rc, {}); 911#else 912 DeprecatedString old_path_string = old_path; 913 DeprecatedString new_path_string = new_path; 914 if (::link(old_path_string.characters(), new_path_string.characters()) < 0) 915 return Error::from_syscall("link"sv, -errno); 916 return {}; 917#endif 918} 919 920ErrorOr<void> symlink(StringView target, StringView link_path) 921{ 922#ifdef AK_OS_SERENITY 923 Syscall::SC_symlink_params params { 924 .target = { target.characters_without_null_termination(), target.length() }, 925 .linkpath = { link_path.characters_without_null_termination(), link_path.length() }, 926 .dirfd = AT_FDCWD, 927 }; 928 int rc = syscall(SC_symlink, &params); 929 HANDLE_SYSCALL_RETURN_VALUE("symlink", rc, {}); 930#else 931 DeprecatedString target_string = target; 932 DeprecatedString link_path_string = link_path; 933 if (::symlink(target_string.characters(), link_path_string.characters()) < 0) 934 return Error::from_syscall("symlink"sv, -errno); 935 return {}; 936#endif 937} 938 939ErrorOr<void> mkdir(StringView path, mode_t mode) 940{ 941 if (path.is_null()) 942 return Error::from_errno(EFAULT); 943#ifdef AK_OS_SERENITY 944 int rc = syscall(SC_mkdir, AT_FDCWD, path.characters_without_null_termination(), path.length(), mode); 945 HANDLE_SYSCALL_RETURN_VALUE("mkdir", rc, {}); 946#else 947 DeprecatedString path_string = path; 948 if (::mkdir(path_string.characters(), mode) < 0) 949 return Error::from_syscall("mkdir"sv, -errno); 950 return {}; 951#endif 952} 953 954ErrorOr<void> chdir(StringView path) 955{ 956 if (path.is_null()) 957 return Error::from_errno(EFAULT); 958#ifdef AK_OS_SERENITY 959 int rc = syscall(SC_chdir, path.characters_without_null_termination(), path.length()); 960 HANDLE_SYSCALL_RETURN_VALUE("chdir", rc, {}); 961#else 962 DeprecatedString path_string = path; 963 if (::chdir(path_string.characters()) < 0) 964 return Error::from_syscall("chdir"sv, -errno); 965 return {}; 966#endif 967} 968 969ErrorOr<void> rmdir(StringView path) 970{ 971 if (path.is_null()) 972 return Error::from_errno(EFAULT); 973#ifdef AK_OS_SERENITY 974 int rc = syscall(SC_rmdir, path.characters_without_null_termination(), path.length()); 975 HANDLE_SYSCALL_RETURN_VALUE("rmdir", rc, {}); 976#else 977 DeprecatedString path_string = path; 978 if (::rmdir(path_string.characters()) < 0) 979 return Error::from_syscall("rmdir"sv, -errno); 980 return {}; 981#endif 982} 983 984ErrorOr<pid_t> fork() 985{ 986 pid_t pid = ::fork(); 987 if (pid < 0) 988 return Error::from_syscall("fork"sv, -errno); 989 return pid; 990} 991 992ErrorOr<int> mkstemp(Span<char> pattern) 993{ 994 int fd = ::mkstemp(pattern.data()); 995 if (fd < 0) 996 return Error::from_syscall("mkstemp"sv, -errno); 997 return fd; 998} 999 1000ErrorOr<void> rename(StringView old_path, StringView new_path) 1001{ 1002 if (old_path.is_null() || new_path.is_null()) 1003 return Error::from_errno(EFAULT); 1004 1005#ifdef AK_OS_SERENITY 1006 Syscall::SC_rename_params params { 1007 .olddirfd = AT_FDCWD, 1008 .old_path = { old_path.characters_without_null_termination(), old_path.length() }, 1009 .newdirfd = AT_FDCWD, 1010 .new_path = { new_path.characters_without_null_termination(), new_path.length() }, 1011 }; 1012 int rc = syscall(SC_rename, &params); 1013 HANDLE_SYSCALL_RETURN_VALUE("rename", rc, {}); 1014#else 1015 DeprecatedString old_path_string = old_path; 1016 DeprecatedString new_path_string = new_path; 1017 if (::rename(old_path_string.characters(), new_path_string.characters()) < 0) 1018 return Error::from_syscall("rename"sv, -errno); 1019 return {}; 1020#endif 1021} 1022 1023ErrorOr<void> unlink(StringView path) 1024{ 1025 if (path.is_null()) 1026 return Error::from_errno(EFAULT); 1027 1028#ifdef AK_OS_SERENITY 1029 int rc = syscall(SC_unlink, AT_FDCWD, path.characters_without_null_termination(), path.length(), 0); 1030 HANDLE_SYSCALL_RETURN_VALUE("unlink", rc, {}); 1031#else 1032 DeprecatedString path_string = path; 1033 if (::unlink(path_string.characters()) < 0) 1034 return Error::from_syscall("unlink"sv, -errno); 1035 return {}; 1036#endif 1037} 1038 1039ErrorOr<void> utime(StringView path, Optional<struct utimbuf> maybe_buf) 1040{ 1041 if (path.is_null()) 1042 return Error::from_errno(EFAULT); 1043 1044 struct utimbuf* buf = nullptr; 1045 if (maybe_buf.has_value()) 1046 buf = &maybe_buf.value(); 1047#ifdef AK_OS_SERENITY 1048 int rc = syscall(SC_utime, path.characters_without_null_termination(), path.length(), buf); 1049 HANDLE_SYSCALL_RETURN_VALUE("utime", rc, {}); 1050#else 1051 DeprecatedString path_string = path; 1052 if (::utime(path_string.characters(), buf) < 0) 1053 return Error::from_syscall("utime"sv, -errno); 1054 return {}; 1055#endif 1056} 1057 1058ErrorOr<struct utsname> uname() 1059{ 1060 struct utsname uts; 1061#ifdef AK_OS_SERENITY 1062 int rc = syscall(SC_uname, &uts); 1063 HANDLE_SYSCALL_RETURN_VALUE("uname", rc, uts); 1064#else 1065 if (::uname(&uts) < 0) 1066 return Error::from_syscall("uname"sv, -errno); 1067#endif 1068 return uts; 1069} 1070 1071#ifndef AK_OS_ANDROID 1072ErrorOr<void> adjtime(const struct timeval* delta, struct timeval* old_delta) 1073{ 1074# ifdef AK_OS_SERENITY 1075 int rc = syscall(SC_adjtime, delta, old_delta); 1076 HANDLE_SYSCALL_RETURN_VALUE("adjtime", rc, {}); 1077# else 1078 if (::adjtime(delta, old_delta) < 0) 1079 return Error::from_syscall("adjtime"sv, -errno); 1080 return {}; 1081# endif 1082} 1083#endif 1084 1085#ifdef AK_OS_SERENITY 1086ErrorOr<void> exec_command(Vector<StringView>& command, bool preserve_env) 1087{ 1088 Vector<StringView> exec_environment; 1089 for (size_t i = 0; environ[i]; ++i) { 1090 StringView env_view { environ[i], strlen(environ[i]) }; 1091 auto maybe_needle = env_view.find('='); 1092 1093 if (!maybe_needle.has_value()) 1094 continue; 1095 1096 // FIXME: Allow a custom selection of variables once ArgsParser supports options with optional parameters. 1097 if (!preserve_env && env_view.substring_view(0, maybe_needle.value()) != "TERM"sv) 1098 continue; 1099 1100 exec_environment.append(env_view); 1101 } 1102 1103 TRY(Core::System::exec(command.at(0), command, Core::System::SearchInPath::Yes, exec_environment)); 1104 return {}; 1105} 1106 1107ErrorOr<void> join_jail(u64 jail_index) 1108{ 1109 Syscall::SC_jail_attach_params params { jail_index }; 1110 int rc = syscall(SC_jail_attach, &params); 1111 HANDLE_SYSCALL_RETURN_VALUE("jail_attach", rc, {}); 1112} 1113 1114ErrorOr<u64> create_jail(StringView jail_name) 1115{ 1116 Syscall::SC_jail_create_params params { 0, { jail_name.characters_without_null_termination(), jail_name.length() } }; 1117 int rc = syscall(SC_jail_create, &params); 1118 HANDLE_SYSCALL_RETURN_VALUE("jail_create", rc, static_cast<u64>(params.index)); 1119} 1120#endif 1121 1122ErrorOr<void> exec(StringView filename, ReadonlySpan<StringView> arguments, SearchInPath search_in_path, Optional<ReadonlySpan<StringView>> environment) 1123{ 1124#ifdef AK_OS_SERENITY 1125 Syscall::SC_execve_params params; 1126 1127 auto argument_strings = TRY(FixedArray<Syscall::StringArgument>::create(arguments.size())); 1128 for (size_t i = 0; i < arguments.size(); ++i) { 1129 argument_strings[i] = { arguments[i].characters_without_null_termination(), arguments[i].length() }; 1130 } 1131 params.arguments.strings = argument_strings.data(); 1132 params.arguments.length = argument_strings.size(); 1133 1134 size_t env_count = 0; 1135 if (environment.has_value()) { 1136 env_count = environment->size(); 1137 } else { 1138 for (size_t i = 0; environ[i]; ++i) 1139 ++env_count; 1140 } 1141 1142 auto environment_strings = TRY(FixedArray<Syscall::StringArgument>::create(env_count)); 1143 if (environment.has_value()) { 1144 for (size_t i = 0; i < env_count; ++i) { 1145 environment_strings[i] = { environment->at(i).characters_without_null_termination(), environment->at(i).length() }; 1146 } 1147 } else { 1148 for (size_t i = 0; i < env_count; ++i) { 1149 environment_strings[i] = { environ[i], strlen(environ[i]) }; 1150 } 1151 } 1152 params.environment.strings = environment_strings.data(); 1153 params.environment.length = environment_strings.size(); 1154 1155 auto run_exec = [](Syscall::SC_execve_params& params) -> ErrorOr<void> { 1156 int rc = syscall(Syscall::SC_execve, &params); 1157 if (rc < 0) 1158 return Error::from_syscall("exec"sv, rc); 1159 return {}; 1160 }; 1161 1162 DeprecatedString exec_filename; 1163 1164 if (search_in_path == SearchInPath::Yes) { 1165 auto maybe_executable = Core::DeprecatedFile::resolve_executable_from_environment(filename); 1166 1167 if (!maybe_executable.has_value()) 1168 return ENOENT; 1169 1170 exec_filename = maybe_executable.release_value(); 1171 } else { 1172 exec_filename = filename.to_deprecated_string(); 1173 } 1174 1175 params.path = { exec_filename.characters(), exec_filename.length() }; 1176 TRY(run_exec(params)); 1177 VERIFY_NOT_REACHED(); 1178#else 1179 DeprecatedString filename_string { filename }; 1180 1181 auto argument_strings = TRY(FixedArray<DeprecatedString>::create(arguments.size())); 1182 auto argv = TRY(FixedArray<char*>::create(arguments.size() + 1)); 1183 for (size_t i = 0; i < arguments.size(); ++i) { 1184 argument_strings[i] = arguments[i].to_deprecated_string(); 1185 argv[i] = const_cast<char*>(argument_strings[i].characters()); 1186 } 1187 argv[arguments.size()] = nullptr; 1188 1189 int rc = 0; 1190 if (environment.has_value()) { 1191 auto environment_strings = TRY(FixedArray<DeprecatedString>::create(environment->size())); 1192 auto envp = TRY(FixedArray<char*>::create(environment->size() + 1)); 1193 for (size_t i = 0; i < environment->size(); ++i) { 1194 environment_strings[i] = environment->at(i).to_deprecated_string(); 1195 envp[i] = const_cast<char*>(environment_strings[i].characters()); 1196 } 1197 envp[environment->size()] = nullptr; 1198 1199 if (search_in_path == SearchInPath::Yes && !filename.contains('/')) { 1200# if defined(AK_OS_MACOS) || defined(AK_OS_FREEBSD) || defined(AK_OS_SOLARIS) 1201 // These BSDs don't support execvpe(), so we'll have to manually search the PATH. 1202 ScopedValueRollback errno_rollback(errno); 1203 1204 auto maybe_executable = Core::DeprecatedFile::resolve_executable_from_environment(filename_string); 1205 1206 if (!maybe_executable.has_value()) { 1207 errno_rollback.set_override_rollback_value(ENOENT); 1208 return Error::from_errno(ENOENT); 1209 } 1210 1211 rc = ::execve(maybe_executable.release_value().characters(), argv.data(), envp.data()); 1212# else 1213 rc = ::execvpe(filename_string.characters(), argv.data(), envp.data()); 1214# endif 1215 } else { 1216 rc = ::execve(filename_string.characters(), argv.data(), envp.data()); 1217 } 1218 1219 } else { 1220 if (search_in_path == SearchInPath::Yes) 1221 rc = ::execvp(filename_string.characters(), argv.data()); 1222 else 1223 rc = ::execv(filename_string.characters(), argv.data()); 1224 } 1225 1226 if (rc < 0) 1227 return Error::from_syscall("exec"sv, rc); 1228 VERIFY_NOT_REACHED(); 1229#endif 1230} 1231 1232ErrorOr<int> socket(int domain, int type, int protocol) 1233{ 1234 auto fd = ::socket(domain, type, protocol); 1235 if (fd < 0) 1236 return Error::from_syscall("socket"sv, -errno); 1237 return fd; 1238} 1239 1240ErrorOr<void> bind(int sockfd, struct sockaddr const* address, socklen_t address_length) 1241{ 1242 if (::bind(sockfd, address, address_length) < 0) 1243 return Error::from_syscall("bind"sv, -errno); 1244 return {}; 1245} 1246 1247ErrorOr<void> listen(int sockfd, int backlog) 1248{ 1249 if (::listen(sockfd, backlog) < 0) 1250 return Error::from_syscall("listen"sv, -errno); 1251 return {}; 1252} 1253 1254ErrorOr<int> accept(int sockfd, struct sockaddr* address, socklen_t* address_length) 1255{ 1256 auto fd = ::accept(sockfd, address, address_length); 1257 if (fd < 0) 1258 return Error::from_syscall("accept"sv, -errno); 1259 return fd; 1260} 1261 1262ErrorOr<void> connect(int sockfd, struct sockaddr const* address, socklen_t address_length) 1263{ 1264 if (::connect(sockfd, address, address_length) < 0) 1265 return Error::from_syscall("connect"sv, -errno); 1266 return {}; 1267} 1268 1269ErrorOr<void> shutdown(int sockfd, int how) 1270{ 1271 if (::shutdown(sockfd, how) < 0) 1272 return Error::from_syscall("shutdown"sv, -errno); 1273 return {}; 1274} 1275 1276ErrorOr<ssize_t> send(int sockfd, void const* buffer, size_t buffer_length, int flags) 1277{ 1278 auto sent = ::send(sockfd, buffer, buffer_length, flags); 1279 if (sent < 0) 1280 return Error::from_syscall("send"sv, -errno); 1281 return sent; 1282} 1283 1284ErrorOr<ssize_t> sendmsg(int sockfd, const struct msghdr* message, int flags) 1285{ 1286 auto sent = ::sendmsg(sockfd, message, flags); 1287 if (sent < 0) 1288 return Error::from_syscall("sendmsg"sv, -errno); 1289 return sent; 1290} 1291 1292ErrorOr<ssize_t> sendto(int sockfd, void const* source, size_t source_length, int flags, struct sockaddr const* destination, socklen_t destination_length) 1293{ 1294 auto sent = ::sendto(sockfd, source, source_length, flags, destination, destination_length); 1295 if (sent < 0) 1296 return Error::from_syscall("sendto"sv, -errno); 1297 return sent; 1298} 1299 1300ErrorOr<ssize_t> recv(int sockfd, void* buffer, size_t length, int flags) 1301{ 1302 auto received = ::recv(sockfd, buffer, length, flags); 1303 if (received < 0) 1304 return Error::from_syscall("recv"sv, -errno); 1305 return received; 1306} 1307 1308ErrorOr<ssize_t> recvmsg(int sockfd, struct msghdr* message, int flags) 1309{ 1310 auto received = ::recvmsg(sockfd, message, flags); 1311 if (received < 0) 1312 return Error::from_syscall("recvmsg"sv, -errno); 1313 return received; 1314} 1315 1316ErrorOr<ssize_t> recvfrom(int sockfd, void* buffer, size_t buffer_length, int flags, struct sockaddr* address, socklen_t* address_length) 1317{ 1318 auto received = ::recvfrom(sockfd, buffer, buffer_length, flags, address, address_length); 1319 if (received < 0) 1320 return Error::from_syscall("recvfrom"sv, -errno); 1321 return received; 1322} 1323 1324ErrorOr<AddressInfoVector> getaddrinfo(char const* nodename, char const* servname, struct addrinfo const& hints) 1325{ 1326 struct addrinfo* results = nullptr; 1327 1328 int const rc = ::getaddrinfo(nodename, servname, &hints, &results); 1329 if (rc != 0) { 1330 if (rc == EAI_SYSTEM) { 1331 return Error::from_syscall("getaddrinfo"sv, -errno); 1332 } 1333 1334 auto const* error_string = gai_strerror(rc); 1335 return Error::from_string_view({ error_string, strlen(error_string) }); 1336 } 1337 1338 Vector<struct addrinfo> addresses; 1339 1340 for (auto* result = results; result != nullptr; result = result->ai_next) 1341 TRY(addresses.try_append(*result)); 1342 1343 return AddressInfoVector { move(addresses), results }; 1344} 1345 1346ErrorOr<void> getsockopt(int sockfd, int level, int option, void* value, socklen_t* value_size) 1347{ 1348 if (::getsockopt(sockfd, level, option, value, value_size) < 0) 1349 return Error::from_syscall("getsockopt"sv, -errno); 1350 return {}; 1351} 1352 1353ErrorOr<void> setsockopt(int sockfd, int level, int option, void const* value, socklen_t value_size) 1354{ 1355 if (::setsockopt(sockfd, level, option, value, value_size) < 0) 1356 return Error::from_syscall("setsockopt"sv, -errno); 1357 return {}; 1358} 1359 1360ErrorOr<void> getsockname(int sockfd, struct sockaddr* address, socklen_t* address_length) 1361{ 1362 if (::getsockname(sockfd, address, address_length) < 0) 1363 return Error::from_syscall("getsockname"sv, -errno); 1364 return {}; 1365} 1366 1367ErrorOr<void> getpeername(int sockfd, struct sockaddr* address, socklen_t* address_length) 1368{ 1369 if (::getpeername(sockfd, address, address_length) < 0) 1370 return Error::from_syscall("getpeername"sv, -errno); 1371 return {}; 1372} 1373 1374ErrorOr<void> socketpair(int domain, int type, int protocol, int sv[2]) 1375{ 1376 if (::socketpair(domain, type, protocol, sv) < 0) 1377 return Error::from_syscall("socketpair"sv, -errno); 1378 return {}; 1379} 1380 1381ErrorOr<Array<int, 2>> pipe2([[maybe_unused]] int flags) 1382{ 1383 Array<int, 2> fds; 1384#if defined(__unix__) 1385 if (::pipe2(fds.data(), flags) < 0) 1386 return Error::from_syscall("pipe2"sv, -errno); 1387#else 1388 if (::pipe(fds.data()) < 0) 1389 return Error::from_syscall("pipe2"sv, -errno); 1390#endif 1391 return fds; 1392} 1393 1394ErrorOr<Vector<gid_t>> getgroups() 1395{ 1396 int count = ::getgroups(0, nullptr); 1397 if (count < 0) 1398 return Error::from_syscall("getgroups"sv, -errno); 1399 if (count == 0) 1400 return Vector<gid_t> {}; 1401 Vector<gid_t> groups; 1402 TRY(groups.try_resize(count)); 1403 if (::getgroups(count, groups.data()) < 0) 1404 return Error::from_syscall("getgroups"sv, -errno); 1405 return groups; 1406} 1407 1408ErrorOr<void> setgroups(ReadonlySpan<gid_t> gids) 1409{ 1410 if (::setgroups(gids.size(), gids.data()) < 0) 1411 return Error::from_syscall("setgroups"sv, -errno); 1412 return {}; 1413} 1414 1415ErrorOr<void> mknod(StringView pathname, mode_t mode, dev_t dev) 1416{ 1417 if (pathname.is_null()) 1418 return Error::from_syscall("mknod"sv, -EFAULT); 1419 1420#ifdef AK_OS_SERENITY 1421 Syscall::SC_mknod_params params { { pathname.characters_without_null_termination(), pathname.length() }, mode, dev }; 1422 int rc = syscall(SC_mknod, &params); 1423 HANDLE_SYSCALL_RETURN_VALUE("mknod", rc, {}); 1424#else 1425 DeprecatedString path_string = pathname; 1426 if (::mknod(path_string.characters(), mode, dev) < 0) 1427 return Error::from_syscall("mknod"sv, -errno); 1428 return {}; 1429#endif 1430} 1431 1432ErrorOr<void> mkfifo(StringView pathname, mode_t mode) 1433{ 1434 return mknod(pathname, mode | S_IFIFO, 0); 1435} 1436 1437ErrorOr<void> setenv(StringView name, StringView value, bool overwrite) 1438{ 1439 auto builder = TRY(StringBuilder::create()); 1440 TRY(builder.try_append(name)); 1441 TRY(builder.try_append('\0')); 1442 TRY(builder.try_append(value)); 1443 TRY(builder.try_append('\0')); 1444 // Note the explicit null terminators above. 1445 auto c_name = builder.string_view().characters_without_null_termination(); 1446 auto c_value = c_name + name.length() + 1; 1447 auto rc = ::setenv(c_name, c_value, overwrite); 1448 if (rc < 0) 1449 return Error::from_errno(errno); 1450 return {}; 1451} 1452 1453ErrorOr<void> putenv(StringView env) 1454{ 1455#ifdef AK_OS_SERENITY 1456 auto rc = serenity_putenv(env.characters_without_null_termination(), env.length()); 1457#else 1458 // Leak somewhat unavoidable here due to the putenv API. 1459 auto leaked_new_env = strndup(env.characters_without_null_termination(), env.length()); 1460 auto rc = ::putenv(leaked_new_env); 1461#endif 1462 if (rc < 0) 1463 return Error::from_errno(errno); 1464 return {}; 1465} 1466 1467ErrorOr<int> posix_openpt(int flags) 1468{ 1469 int const rc = ::posix_openpt(flags); 1470 if (rc < 0) 1471 return Error::from_syscall("posix_openpt"sv, -errno); 1472 return rc; 1473} 1474 1475ErrorOr<void> grantpt(int fildes) 1476{ 1477 auto const rc = ::grantpt(fildes); 1478 if (rc < 0) 1479 return Error::from_syscall("grantpt"sv, -errno); 1480 return {}; 1481} 1482 1483ErrorOr<void> unlockpt(int fildes) 1484{ 1485 auto const rc = ::unlockpt(fildes); 1486 if (rc < 0) 1487 return Error::from_syscall("unlockpt"sv, -errno); 1488 return {}; 1489} 1490 1491ErrorOr<void> access(StringView pathname, int mode) 1492{ 1493 if (pathname.is_null()) 1494 return Error::from_syscall("access"sv, -EFAULT); 1495 1496#ifdef AK_OS_SERENITY 1497 Syscall::SC_faccessat_params params { 1498 .dirfd = AT_FDCWD, 1499 .pathname = { pathname.characters_without_null_termination(), pathname.length() }, 1500 .mode = mode, 1501 .flags = 0, 1502 }; 1503 int rc = ::syscall(Syscall::SC_faccessat, &params); 1504 HANDLE_SYSCALL_RETURN_VALUE("access", rc, {}); 1505#else 1506 DeprecatedString path_string = pathname; 1507 if (::access(path_string.characters(), mode) < 0) 1508 return Error::from_syscall("access"sv, -errno); 1509 return {}; 1510#endif 1511} 1512 1513ErrorOr<DeprecatedString> readlink(StringView pathname) 1514{ 1515 // FIXME: Try again with a larger buffer. 1516 char data[PATH_MAX]; 1517#ifdef AK_OS_SERENITY 1518 Syscall::SC_readlink_params small_params { 1519 .path = { pathname.characters_without_null_termination(), pathname.length() }, 1520 .buffer = { data, sizeof(data) }, 1521 .dirfd = AT_FDCWD, 1522 }; 1523 int rc = syscall(SC_readlink, &small_params); 1524 HANDLE_SYSCALL_RETURN_VALUE("readlink", rc, DeprecatedString(data, rc)); 1525#else 1526 DeprecatedString path_string = pathname; 1527 int rc = ::readlink(path_string.characters(), data, sizeof(data)); 1528 if (rc == -1) 1529 return Error::from_syscall("readlink"sv, -errno); 1530 1531 return DeprecatedString(data, rc); 1532#endif 1533} 1534 1535ErrorOr<int> poll(Span<struct pollfd> poll_fds, int timeout) 1536{ 1537 auto const rc = ::poll(poll_fds.data(), poll_fds.size(), timeout); 1538 if (rc < 0) 1539 return Error::from_syscall("poll"sv, -errno); 1540 return { rc }; 1541} 1542 1543#ifdef AK_OS_SERENITY 1544ErrorOr<void> posix_fallocate(int fd, off_t offset, off_t length) 1545{ 1546 int rc = ::posix_fallocate(fd, offset, length); 1547 if (rc != 0) 1548 return Error::from_syscall("posix_fallocate"sv, -rc); 1549 return {}; 1550} 1551#endif 1552 1553}