System.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /*
  2. * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021, Kenneth Myhra <kennethmyhra@gmail.com>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/String.h>
  8. #include <LibCore/System.h>
  9. #include <LibSystem/syscall.h>
  10. #include <fcntl.h>
  11. #include <stdarg.h>
  12. #include <sys/mman.h>
  13. #include <unistd.h>
  14. #define HANDLE_SYSCALL_RETURN_VALUE(syscall_name, rc, success_value) \
  15. if ((rc) < 0) { \
  16. return Error::from_syscall(syscall_name, rc); \
  17. } \
  18. return success_value;
  19. namespace Core::System {
  20. #ifdef __serenity__
  21. ErrorOr<void> pledge(StringView promises, StringView execpromises)
  22. {
  23. Syscall::SC_pledge_params params {
  24. { promises.characters_without_null_termination(), promises.length() },
  25. { execpromises.characters_without_null_termination(), execpromises.length() },
  26. };
  27. int rc = syscall(SC_pledge, &params);
  28. HANDLE_SYSCALL_RETURN_VALUE("pledge"sv, rc, {});
  29. }
  30. ErrorOr<void> unveil(StringView path, StringView permissions)
  31. {
  32. Syscall::SC_unveil_params params {
  33. { path.characters_without_null_termination(), path.length() },
  34. { permissions.characters_without_null_termination(), permissions.length() },
  35. };
  36. int rc = syscall(SC_unveil, &params);
  37. HANDLE_SYSCALL_RETURN_VALUE("unveil"sv, rc, {});
  38. }
  39. ErrorOr<Array<int, 2>> pipe2(int flags)
  40. {
  41. Array<int, 2> fds;
  42. if (::pipe2(fds.data(), flags) < 0)
  43. return Error::from_syscall("pipe2"sv, -errno);
  44. return fds;
  45. }
  46. #endif
  47. ErrorOr<void> sigaction(int signal, struct sigaction const* action, struct sigaction* old_action)
  48. {
  49. if (::sigaction(signal, action, old_action) < 0)
  50. return Error::from_syscall("sigaction"sv, -errno);
  51. return {};
  52. }
  53. ErrorOr<struct stat> fstat(int fd)
  54. {
  55. struct stat st = {};
  56. if (::fstat(fd, &st) < 0)
  57. return Error::from_syscall("fstat"sv, -errno);
  58. return st;
  59. }
  60. ErrorOr<int> fcntl(int fd, int command, ...)
  61. {
  62. va_list ap;
  63. va_start(ap, command);
  64. u32 extra_arg = va_arg(ap, u32);
  65. int rc = ::fcntl(fd, command, extra_arg);
  66. va_end(ap);
  67. if (rc < 0)
  68. return Error::from_syscall("fcntl"sv, -errno);
  69. return rc;
  70. }
  71. ErrorOr<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)
  72. {
  73. #ifdef __serenity__
  74. Syscall::SC_mmap_params params { (uintptr_t)address, size, alignment, protection, flags, fd, offset, { name.characters_without_null_termination(), name.length() } };
  75. ptrdiff_t rc = syscall(SC_mmap, &params);
  76. if (rc < 0 && rc > -EMAXERRNO)
  77. return Error::from_syscall("mmap"sv, rc);
  78. return reinterpret_cast<void*>(rc);
  79. #else
  80. // NOTE: Regular POSIX mmap() doesn't support custom alignment requests.
  81. VERIFY(!alignment);
  82. auto* ptr = ::mmap(address, size, protection, flags, fd, offset);
  83. if (ptr == MAP_FAILED)
  84. return Error::from_syscall("mmap"sv, -errno);
  85. return ptr;
  86. #endif
  87. }
  88. ErrorOr<void> munmap(void* address, size_t size)
  89. {
  90. if (::munmap(address, size) < 0)
  91. return Error::from_syscall("munmap"sv, -errno);
  92. return {};
  93. }
  94. ErrorOr<int> open(StringView path, int options, ...)
  95. {
  96. if (!path.characters_without_null_termination())
  97. return Error::from_syscall("open"sv, -EFAULT);
  98. va_list ap;
  99. va_start(ap, options);
  100. auto mode = (mode_t)va_arg(ap, unsigned);
  101. va_end(ap);
  102. #ifdef __serenity__
  103. Syscall::SC_open_params params { AT_FDCWD, { path.characters_without_null_termination(), path.length() }, options, mode };
  104. int rc = syscall(SC_open, &params);
  105. HANDLE_SYSCALL_RETURN_VALUE("open"sv, rc, rc);
  106. #else
  107. // NOTE: We have to ensure that the path is null-terminated.
  108. String path_string = path;
  109. int rc = ::open(path_string.characters(), options, mode);
  110. if (rc < 0)
  111. return Error::from_syscall("open"sv, -errno);
  112. return rc;
  113. #endif
  114. }
  115. ErrorOr<void> close(int fd)
  116. {
  117. if (::close(fd) < 0)
  118. return Error::from_syscall("close"sv, -errno);
  119. return {};
  120. }
  121. ErrorOr<void> ftruncate(int fd, off_t length)
  122. {
  123. if (::ftruncate(fd, length) < 0)
  124. return Error::from_syscall("ftruncate"sv, -errno);
  125. return {};
  126. }
  127. ErrorOr<struct stat> stat(StringView path)
  128. {
  129. if (!path.characters_without_null_termination())
  130. return Error::from_syscall("stat"sv, -EFAULT);
  131. struct stat st = {};
  132. #ifdef __serenity__
  133. Syscall::SC_stat_params params { { path.characters_without_null_termination(), path.length() }, &st, AT_FDCWD, true };
  134. int rc = syscall(SC_stat, &params);
  135. HANDLE_SYSCALL_RETURN_VALUE("stat"sv, rc, st);
  136. #else
  137. String path_string = path;
  138. if (::stat(path_string.characters(), &st) < 0)
  139. return Error::from_syscall("stat"sv, -errno);
  140. return st;
  141. #endif
  142. }
  143. ErrorOr<ssize_t> read(int fd, Bytes buffer)
  144. {
  145. ssize_t rc = ::read(fd, buffer.data(), buffer.size());
  146. if (rc < 0)
  147. return Error::from_syscall("read"sv, -errno);
  148. return rc;
  149. }
  150. ErrorOr<ssize_t> write(int fd, ReadonlyBytes buffer)
  151. {
  152. ssize_t rc = ::write(fd, buffer.data(), buffer.size());
  153. if (rc < 0)
  154. return Error::from_syscall("write"sv, -errno);
  155. return rc;
  156. }
  157. ErrorOr<void> kill(pid_t pid, int signal)
  158. {
  159. if (::kill(pid, signal) < 0)
  160. return Error::from_syscall("kill"sv, -errno);
  161. return {};
  162. }
  163. ErrorOr<int> dup2(int source_fd, int destination_fd)
  164. {
  165. int fd = ::dup2(source_fd, destination_fd);
  166. if (fd < 0)
  167. return Error::from_syscall("dup2"sv, -errno);
  168. return fd;
  169. }
  170. ErrorOr<String> ptsname(int fd)
  171. {
  172. auto* name = ::ptsname(fd);
  173. if (!name)
  174. return Error::from_syscall("ptsname"sv, -errno);
  175. return String(name);
  176. }
  177. ErrorOr<String> gethostname()
  178. {
  179. char hostname[256];
  180. int rc = ::gethostname(hostname, sizeof(hostname));
  181. if (rc < 0)
  182. return Error::from_syscall("gethostname"sv, -errno);
  183. return String(&hostname[0]);
  184. }
  185. }