System.cpp 6.2 KB

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