unistd.cpp 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/ScopeGuard.h>
  7. #include <AK/ScopedValueRollback.h>
  8. #include <AK/String.h>
  9. #include <AK/Vector.h>
  10. #include <LibCore/File.h>
  11. #include <alloca.h>
  12. #include <assert.h>
  13. #include <bits/pthread_cancel.h>
  14. #include <bits/pthread_integration.h>
  15. #include <dirent.h>
  16. #include <errno.h>
  17. #include <fcntl.h>
  18. #include <getopt.h>
  19. #include <grp.h>
  20. #include <pwd.h>
  21. #include <stdarg.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <sys/ioctl.h>
  26. #include <sys/mman.h>
  27. #include <sys/resource.h>
  28. #include <sys/select.h>
  29. #include <sys/stat.h>
  30. #include <sys/sysmacros.h>
  31. #include <sys/types.h>
  32. #include <syscall.h>
  33. #include <termios.h>
  34. #include <time.h>
  35. #include <unistd.h>
  36. extern "C" {
  37. #ifdef NO_TLS
  38. static int s_cached_tid = 0;
  39. #else
  40. static __thread int s_cached_tid = 0;
  41. #endif
  42. static int s_cached_pid = 0;
  43. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/lchown.html
  44. int lchown(char const* pathname, uid_t uid, gid_t gid)
  45. {
  46. if (!pathname) {
  47. errno = EFAULT;
  48. return -1;
  49. }
  50. Syscall::SC_chown_params params { { pathname, strlen(pathname) }, uid, gid, AT_FDCWD, false };
  51. int rc = syscall(SC_chown, &params);
  52. __RETURN_WITH_ERRNO(rc, rc, -1);
  53. }
  54. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/chown.html
  55. int chown(char const* pathname, uid_t uid, gid_t gid)
  56. {
  57. if (!pathname) {
  58. errno = EFAULT;
  59. return -1;
  60. }
  61. Syscall::SC_chown_params params { { pathname, strlen(pathname) }, uid, gid, AT_FDCWD, true };
  62. int rc = syscall(SC_chown, &params);
  63. __RETURN_WITH_ERRNO(rc, rc, -1);
  64. }
  65. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchown.html
  66. int fchown(int fd, uid_t uid, gid_t gid)
  67. {
  68. int rc = syscall(SC_fchown, fd, uid, gid);
  69. __RETURN_WITH_ERRNO(rc, rc, -1);
  70. }
  71. int fchownat(int fd, char const* pathname, uid_t uid, gid_t gid, int flags)
  72. {
  73. if (!pathname) {
  74. errno = EFAULT;
  75. return -1;
  76. }
  77. Syscall::SC_chown_params params { { pathname, strlen(pathname) }, uid, gid, fd, !(flags & AT_SYMLINK_NOFOLLOW) };
  78. int rc = syscall(SC_chown, &params);
  79. __RETURN_WITH_ERRNO(rc, rc, -1);
  80. }
  81. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html
  82. pid_t fork()
  83. {
  84. __pthread_fork_prepare();
  85. int rc = syscall(SC_fork);
  86. if (rc == 0) {
  87. s_cached_tid = 0;
  88. s_cached_pid = 0;
  89. __pthread_fork_child();
  90. } else if (rc != -1) {
  91. __pthread_fork_parent();
  92. }
  93. __RETURN_WITH_ERRNO(rc, rc, -1);
  94. }
  95. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/vfork.html
  96. pid_t vfork()
  97. {
  98. return fork();
  99. }
  100. // Non-POSIX, but present in BSDs and Linux
  101. // https://man.openbsd.org/daemon.3
  102. int daemon(int nochdir, int noclose)
  103. {
  104. pid_t pid = fork();
  105. if (pid < 0)
  106. return -1;
  107. // exit parent, continue execution in child
  108. if (pid > 0)
  109. _exit(0);
  110. pid = setsid();
  111. if (pid < 0)
  112. return -1;
  113. if (nochdir == 0)
  114. (void)chdir("/");
  115. if (noclose == 0) {
  116. // redirect stdout and stderr to /dev/null
  117. int fd = open("/dev/null", O_WRONLY);
  118. if (fd < 0)
  119. return -1;
  120. (void)close(STDOUT_FILENO);
  121. (void)close(STDERR_FILENO);
  122. (void)dup2(fd, STDOUT_FILENO);
  123. (void)dup2(fd, STDERR_FILENO);
  124. (void)close(fd);
  125. }
  126. return 0;
  127. }
  128. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/execv.html
  129. int execv(char const* path, char* const argv[])
  130. {
  131. return execve(path, argv, environ);
  132. }
  133. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/execve.html
  134. int execve(char const* filename, char* const argv[], char* const envp[])
  135. {
  136. size_t arg_count = 0;
  137. for (size_t i = 0; argv[i]; ++i)
  138. ++arg_count;
  139. size_t env_count = 0;
  140. for (size_t i = 0; envp[i]; ++i)
  141. ++env_count;
  142. auto copy_strings = [&](auto& vec, size_t count, auto& output) {
  143. output.length = count;
  144. for (size_t i = 0; vec[i]; ++i) {
  145. output.strings[i].characters = vec[i];
  146. output.strings[i].length = strlen(vec[i]);
  147. }
  148. };
  149. Syscall::SC_execve_params params;
  150. params.arguments.strings = (Syscall::StringArgument*)alloca(arg_count * sizeof(Syscall::StringArgument));
  151. params.environment.strings = (Syscall::StringArgument*)alloca(env_count * sizeof(Syscall::StringArgument));
  152. params.path = { filename, strlen(filename) };
  153. copy_strings(argv, arg_count, params.arguments);
  154. copy_strings(envp, env_count, params.environment);
  155. int rc = syscall(SC_execve, &params);
  156. __RETURN_WITH_ERRNO(rc, rc, -1);
  157. }
  158. int execvpe(char const* filename, char* const argv[], char* const envp[])
  159. {
  160. if (strchr(filename, '/'))
  161. return execve(filename, argv, envp);
  162. ScopedValueRollback errno_rollback(errno);
  163. String path = getenv("PATH");
  164. if (path.is_empty())
  165. path = DEFAULT_PATH;
  166. auto parts = path.split(':');
  167. for (auto& part : parts) {
  168. auto candidate = String::formatted("{}/{}", part, filename);
  169. int rc = execve(candidate.characters(), argv, envp);
  170. if (rc < 0 && errno != ENOENT) {
  171. errno_rollback.set_override_rollback_value(errno);
  172. dbgln("execvpe() failed on attempt ({}) with {}", candidate, strerror(errno));
  173. return rc;
  174. }
  175. }
  176. errno_rollback.set_override_rollback_value(ENOENT);
  177. dbgln("execvpe() leaving :(");
  178. return -1;
  179. }
  180. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/execvp.html
  181. int execvp(char const* filename, char* const argv[])
  182. {
  183. int rc = execvpe(filename, argv, environ);
  184. int saved_errno = errno;
  185. dbgln("execvp({}, ...) about to return {} with errno={}", filename, rc, saved_errno);
  186. errno = saved_errno;
  187. return rc;
  188. }
  189. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/execl.html
  190. int execl(char const* filename, char const* arg0, ...)
  191. {
  192. Vector<char const*, 16> args;
  193. args.append(arg0);
  194. va_list ap;
  195. va_start(ap, arg0);
  196. for (;;) {
  197. char const* arg = va_arg(ap, char const*);
  198. if (!arg)
  199. break;
  200. args.append(arg);
  201. }
  202. va_end(ap);
  203. args.append(nullptr);
  204. return execve(filename, const_cast<char* const*>(args.data()), environ);
  205. }
  206. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/execle.html
  207. int execle(char const* filename, char const* arg0, ...)
  208. {
  209. Vector<char const*> args;
  210. args.append(arg0);
  211. va_list ap;
  212. va_start(ap, arg0);
  213. char const* arg;
  214. do {
  215. arg = va_arg(ap, char const*);
  216. args.append(arg);
  217. } while (arg);
  218. auto argv = const_cast<char* const*>(args.data());
  219. auto envp = const_cast<char* const*>(va_arg(ap, char* const*));
  220. va_end(ap);
  221. return execve(filename, argv, envp);
  222. }
  223. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/execlp.html
  224. int execlp(char const* filename, char const* arg0, ...)
  225. {
  226. Vector<char const*, 16> args;
  227. args.append(arg0);
  228. va_list ap;
  229. va_start(ap, arg0);
  230. for (;;) {
  231. char const* arg = va_arg(ap, char const*);
  232. if (!arg)
  233. break;
  234. args.append(arg);
  235. }
  236. va_end(ap);
  237. args.append(nullptr);
  238. return execvpe(filename, const_cast<char* const*>(args.data()), environ);
  239. }
  240. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/getuid.html
  241. uid_t geteuid()
  242. {
  243. return syscall(SC_geteuid);
  244. }
  245. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/getegid.html
  246. gid_t getegid()
  247. {
  248. return syscall(SC_getegid);
  249. }
  250. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/getuid.html
  251. uid_t getuid()
  252. {
  253. return syscall(SC_getuid);
  254. }
  255. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/getgid.html
  256. gid_t getgid()
  257. {
  258. return syscall(SC_getgid);
  259. }
  260. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpid.html
  261. pid_t getpid()
  262. {
  263. int cached_pid = s_cached_pid;
  264. if (!cached_pid) {
  265. cached_pid = syscall(SC_getpid);
  266. s_cached_pid = cached_pid;
  267. }
  268. return cached_pid;
  269. }
  270. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/getppid.html
  271. pid_t getppid()
  272. {
  273. return syscall(SC_getppid);
  274. }
  275. int getresuid(uid_t* ruid, uid_t* euid, uid_t* suid)
  276. {
  277. return syscall(SC_getresuid, ruid, euid, suid);
  278. }
  279. int getresgid(gid_t* rgid, gid_t* egid, gid_t* sgid)
  280. {
  281. return syscall(SC_getresgid, rgid, egid, sgid);
  282. }
  283. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsid.html
  284. pid_t getsid(pid_t pid)
  285. {
  286. int rc = syscall(SC_getsid, pid);
  287. __RETURN_WITH_ERRNO(rc, rc, -1);
  288. }
  289. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsid.html
  290. pid_t setsid()
  291. {
  292. int rc = syscall(SC_setsid);
  293. __RETURN_WITH_ERRNO(rc, rc, -1);
  294. }
  295. pid_t tcgetpgrp(int fd)
  296. {
  297. pid_t pgrp;
  298. int rc = ioctl(fd, TIOCGPGRP, &pgrp);
  299. if (rc < 0)
  300. return rc;
  301. return pgrp;
  302. }
  303. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetpgrp.html
  304. int tcsetpgrp(int fd, pid_t pgid)
  305. {
  306. return ioctl(fd, TIOCSPGRP, pgid);
  307. }
  308. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/setpgid.html
  309. int setpgid(pid_t pid, pid_t pgid)
  310. {
  311. int rc = syscall(SC_setpgid, pid, pgid);
  312. __RETURN_WITH_ERRNO(rc, rc, -1);
  313. }
  314. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpgid.html
  315. pid_t getpgid(pid_t pid)
  316. {
  317. int rc = syscall(SC_getpgid, pid);
  318. __RETURN_WITH_ERRNO(rc, rc, -1);
  319. }
  320. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpgrp.html
  321. pid_t getpgrp()
  322. {
  323. int rc = syscall(SC_getpgrp);
  324. __RETURN_WITH_ERRNO(rc, rc, -1);
  325. }
  326. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html
  327. ssize_t read(int fd, void* buf, size_t count)
  328. {
  329. __pthread_maybe_cancel();
  330. int rc = syscall(SC_read, fd, buf, count);
  331. __RETURN_WITH_ERRNO(rc, rc, -1);
  332. }
  333. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html
  334. ssize_t pread(int fd, void* buf, size_t count, off_t offset)
  335. {
  336. __pthread_maybe_cancel();
  337. int rc = syscall(SC_pread, fd, buf, count, &offset);
  338. __RETURN_WITH_ERRNO(rc, rc, -1);
  339. }
  340. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html
  341. ssize_t write(int fd, void const* buf, size_t count)
  342. {
  343. __pthread_maybe_cancel();
  344. int rc = syscall(SC_write, fd, buf, count);
  345. __RETURN_WITH_ERRNO(rc, rc, -1);
  346. }
  347. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html
  348. ssize_t pwrite(int fd, void const* buf, size_t count, off_t offset)
  349. {
  350. __pthread_maybe_cancel();
  351. // FIXME: This is not thread safe and should be implemented in the kernel instead.
  352. off_t old_offset = lseek(fd, 0, SEEK_CUR);
  353. lseek(fd, offset, SEEK_SET);
  354. ssize_t nwritten = write(fd, buf, count);
  355. lseek(fd, old_offset, SEEK_SET);
  356. return nwritten;
  357. }
  358. // Note: Be sure to send to directory_name parameter a directory name ended with trailing slash.
  359. static int ttyname_r_for_directory(char const* directory_name, dev_t device_mode, ino_t inode_number, char* buffer, size_t size)
  360. {
  361. DIR* dirstream = opendir(directory_name);
  362. if (!dirstream) {
  363. return -1;
  364. }
  365. auto close_dir_stream_on_exit = ScopeGuard([dirstream] {
  366. closedir(dirstream);
  367. });
  368. struct dirent* entry = nullptr;
  369. char* name_path = nullptr;
  370. // FIXME: Use LibCore DirIterator here instead
  371. while ((entry = readdir(dirstream)) != nullptr) {
  372. if (((ino_t)entry->d_ino == inode_number)
  373. && strcmp(entry->d_name, "stdin")
  374. && strcmp(entry->d_name, "stdout")
  375. && strcmp(entry->d_name, "stderr")) {
  376. size_t name_length = strlen(directory_name) + strlen(entry->d_name) + 1;
  377. if (name_length > size) {
  378. errno = ERANGE;
  379. return -1;
  380. }
  381. name_path = (char*)malloc(name_length);
  382. memset(name_path, 0, name_length);
  383. memcpy(name_path, directory_name, strlen(directory_name));
  384. memcpy(&name_path[strlen(directory_name)], entry->d_name, strlen(entry->d_name));
  385. struct stat st;
  386. if (lstat(name_path, &st) < 0) {
  387. free(name_path);
  388. name_path = nullptr;
  389. continue;
  390. }
  391. if (device_mode == st.st_rdev) {
  392. memset(buffer, 0, name_length);
  393. memcpy(buffer, name_path, name_length);
  394. free(name_path);
  395. return 0;
  396. }
  397. }
  398. }
  399. free(name_path);
  400. return -1;
  401. }
  402. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/ttyname_r.html
  403. int ttyname_r(int fd, char* buffer, size_t size)
  404. {
  405. struct stat stat;
  406. if (fstat(fd, &stat) < 0)
  407. return -1;
  408. dev_t major_minor_numbers = stat.st_rdev;
  409. ino_t inode_number = stat.st_ino;
  410. if (ttyname_r_for_directory("/dev/", major_minor_numbers, inode_number, buffer, size) < 0) {
  411. if (ttyname_r_for_directory("/dev/pts/", major_minor_numbers, inode_number, buffer, size) < 0) {
  412. errno = ENOTTY;
  413. return -1;
  414. }
  415. }
  416. return 0;
  417. }
  418. static char ttyname_buf[32];
  419. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/ttyname.html
  420. char* ttyname(int fd)
  421. {
  422. if (ttyname_r(fd, ttyname_buf, sizeof(ttyname_buf)) < 0)
  423. return nullptr;
  424. return ttyname_buf;
  425. }
  426. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html
  427. int close(int fd)
  428. {
  429. __pthread_maybe_cancel();
  430. int rc = syscall(SC_close, fd);
  431. __RETURN_WITH_ERRNO(rc, rc, -1);
  432. }
  433. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/chdir.html
  434. int chdir(char const* path)
  435. {
  436. if (!path) {
  437. errno = EFAULT;
  438. return -1;
  439. }
  440. int rc = syscall(SC_chdir, path, strlen(path));
  441. __RETURN_WITH_ERRNO(rc, rc, -1);
  442. }
  443. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchdir.html
  444. int fchdir(int fd)
  445. {
  446. int rc = syscall(SC_fchdir, fd);
  447. __RETURN_WITH_ERRNO(rc, rc, -1);
  448. }
  449. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/getcwd.html
  450. char* getcwd(char* buffer, size_t size)
  451. {
  452. if (buffer && size == 0) {
  453. // POSIX requires that we set errno to EINVAL here, but in our syscall it makes sense to
  454. // allow "probing" the Kernel with a zero-sized buffer, and it does not return -EINVAL.
  455. // So we have to inject EINVAL here.
  456. errno = EINVAL;
  457. return nullptr;
  458. }
  459. bool self_allocated = false;
  460. if (!buffer) {
  461. size = size ? size : 64;
  462. buffer = (char*)malloc(size);
  463. self_allocated = true;
  464. }
  465. int rc = syscall(SC_getcwd, buffer, size);
  466. if (rc < 0) {
  467. if (self_allocated)
  468. free(buffer);
  469. errno = -rc;
  470. return nullptr;
  471. }
  472. size_t actual_size = static_cast<size_t>(rc);
  473. if (actual_size <= size) {
  474. return buffer;
  475. }
  476. // If we get here, the current directory path was silently truncated.
  477. if (!self_allocated) {
  478. // In this case, POSIX causes information loss: the caller cannot learn about the ideal
  479. // buffer size. This is the reason we went with silently truncation instead.
  480. errno = ERANGE;
  481. return nullptr;
  482. }
  483. // Try again.
  484. free(buffer);
  485. size = actual_size;
  486. buffer = (char*)malloc(size);
  487. rc = syscall(SC_getcwd, buffer, size);
  488. if (rc < 0) {
  489. // Can only happen if we lose a race. Let's pretend we lost the race in the first place.
  490. free(buffer);
  491. errno = -rc;
  492. return nullptr;
  493. }
  494. actual_size = static_cast<size_t>(rc);
  495. if (actual_size < size) {
  496. // If we're here, then cwd has become longer while we were looking at it. (Race with another thread?)
  497. // There's not much we can do, unless we want to loop endlessly
  498. // in this case. Let's leave it up to the caller whether to loop.
  499. free(buffer);
  500. errno = EAGAIN;
  501. return nullptr;
  502. }
  503. return buffer;
  504. }
  505. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/getwd.html
  506. char* getwd(char* buf)
  507. {
  508. if (buf == nullptr) {
  509. errno = EINVAL;
  510. return nullptr;
  511. }
  512. auto* p = getcwd(buf, PATH_MAX);
  513. if (errno == ERANGE) {
  514. // POSIX quirk
  515. errno = ENAMETOOLONG;
  516. }
  517. return p;
  518. }
  519. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/sleep.html
  520. unsigned int sleep(unsigned int seconds)
  521. {
  522. struct timespec ts = { seconds, 0 };
  523. if (clock_nanosleep(CLOCK_MONOTONIC_COARSE, 0, &ts, nullptr) < 0)
  524. return ts.tv_sec;
  525. return 0;
  526. }
  527. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/usleep.html
  528. int usleep(useconds_t usec)
  529. {
  530. struct timespec ts = { (long)(usec / 1000000), (long)(usec % 1000000) * 1000 };
  531. return clock_nanosleep(CLOCK_MONOTONIC_COARSE, 0, &ts, nullptr);
  532. }
  533. int gethostname(char* buffer, size_t size)
  534. {
  535. int rc = syscall(SC_gethostname, buffer, size);
  536. __RETURN_WITH_ERRNO(rc, rc, -1);
  537. }
  538. int sethostname(char const* hostname, ssize_t size)
  539. {
  540. int rc = syscall(SC_sethostname, hostname, size);
  541. __RETURN_WITH_ERRNO(rc, rc, -1);
  542. }
  543. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html
  544. ssize_t readlink(char const* path, char* buffer, size_t size)
  545. {
  546. Syscall::SC_readlink_params params { { path, strlen(path) }, { buffer, size } };
  547. int rc = syscall(SC_readlink, &params);
  548. // Return the number of bytes placed in the buffer, not the full path size.
  549. __RETURN_WITH_ERRNO(rc, min((size_t)rc, size), -1);
  550. }
  551. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html
  552. off_t lseek(int fd, off_t offset, int whence)
  553. {
  554. int rc = syscall(SC_lseek, fd, &offset, whence);
  555. __RETURN_WITH_ERRNO(rc, offset, -1);
  556. }
  557. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/link.html
  558. int link(char const* old_path, char const* new_path)
  559. {
  560. if (!old_path || !new_path) {
  561. errno = EFAULT;
  562. return -1;
  563. }
  564. Syscall::SC_link_params params { { old_path, strlen(old_path) }, { new_path, strlen(new_path) } };
  565. int rc = syscall(SC_link, &params);
  566. __RETURN_WITH_ERRNO(rc, rc, -1);
  567. }
  568. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html
  569. int unlink(char const* pathname)
  570. {
  571. return unlinkat(AT_FDCWD, pathname, 0);
  572. }
  573. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlinkat.html
  574. int unlinkat(int dirfd, char const* pathname, int flags)
  575. {
  576. int rc = syscall(SC_unlink, dirfd, pathname, strlen(pathname), flags);
  577. __RETURN_WITH_ERRNO(rc, rc, -1);
  578. }
  579. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/symlink.html
  580. int symlink(char const* target, char const* linkpath)
  581. {
  582. if (!target || !linkpath) {
  583. errno = EFAULT;
  584. return -1;
  585. }
  586. Syscall::SC_symlink_params params { { target, strlen(target) }, { linkpath, strlen(linkpath) } };
  587. int rc = syscall(SC_symlink, &params);
  588. __RETURN_WITH_ERRNO(rc, rc, -1);
  589. }
  590. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/rmdir.html
  591. int rmdir(char const* pathname)
  592. {
  593. if (!pathname) {
  594. errno = EFAULT;
  595. return -1;
  596. }
  597. int rc = syscall(SC_rmdir, pathname, strlen(pathname));
  598. __RETURN_WITH_ERRNO(rc, rc, -1);
  599. }
  600. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/isatty.html
  601. int isatty(int fd)
  602. {
  603. return fcntl(fd, F_ISTTY);
  604. }
  605. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html
  606. int dup(int old_fd)
  607. {
  608. return fcntl(old_fd, F_DUPFD, 0);
  609. }
  610. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup2.html
  611. int dup2(int old_fd, int new_fd)
  612. {
  613. int rc = syscall(SC_dup2, old_fd, new_fd);
  614. __RETURN_WITH_ERRNO(rc, rc, -1);
  615. }
  616. int setgroups(size_t size, gid_t const* list)
  617. {
  618. int rc = syscall(SC_setgroups, size, list);
  619. __RETURN_WITH_ERRNO(rc, rc, -1);
  620. }
  621. int getgroups(int size, gid_t list[])
  622. {
  623. int rc = syscall(SC_getgroups, size, list);
  624. __RETURN_WITH_ERRNO(rc, rc, -1);
  625. }
  626. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html
  627. int pipe(int pipefd[2])
  628. {
  629. return pipe2(pipefd, 0);
  630. }
  631. //
  632. int pipe2(int pipefd[2], int flags)
  633. {
  634. int rc = syscall(SC_pipe, pipefd, flags);
  635. __RETURN_WITH_ERRNO(rc, rc, -1);
  636. }
  637. unsigned int alarm(unsigned int seconds)
  638. {
  639. return syscall(SC_alarm, seconds);
  640. }
  641. int seteuid(uid_t euid)
  642. {
  643. int rc = syscall(SC_seteuid, euid);
  644. __RETURN_WITH_ERRNO(rc, rc, -1);
  645. }
  646. int setegid(gid_t egid)
  647. {
  648. int rc = syscall(SC_setegid, egid);
  649. __RETURN_WITH_ERRNO(rc, rc, -1);
  650. }
  651. int setuid(uid_t uid)
  652. {
  653. int rc = syscall(SC_setuid, uid);
  654. __RETURN_WITH_ERRNO(rc, rc, -1);
  655. }
  656. int setgid(gid_t gid)
  657. {
  658. int rc = syscall(SC_setgid, gid);
  659. __RETURN_WITH_ERRNO(rc, rc, -1);
  660. }
  661. int setreuid(uid_t ruid, uid_t euid)
  662. {
  663. int rc = syscall(SC_setreuid, ruid, euid);
  664. __RETURN_WITH_ERRNO(rc, rc, -1);
  665. }
  666. int setresuid(uid_t ruid, uid_t euid, uid_t suid)
  667. {
  668. int rc = syscall(SC_setresuid, ruid, euid, suid);
  669. __RETURN_WITH_ERRNO(rc, rc, -1);
  670. }
  671. int setresgid(gid_t rgid, gid_t egid, gid_t sgid)
  672. {
  673. int rc = syscall(SC_setresgid, rgid, egid, sgid);
  674. __RETURN_WITH_ERRNO(rc, rc, -1);
  675. }
  676. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/access.html
  677. int access(char const* pathname, int mode)
  678. {
  679. if (!pathname) {
  680. errno = EFAULT;
  681. return -1;
  682. }
  683. int rc = syscall(SC_access, pathname, strlen(pathname), mode);
  684. __RETURN_WITH_ERRNO(rc, rc, -1);
  685. }
  686. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/mknod.html
  687. int mknod(char const* pathname, mode_t mode, dev_t dev)
  688. {
  689. if (!pathname) {
  690. errno = EFAULT;
  691. return -1;
  692. }
  693. Syscall::SC_mknod_params params { { pathname, strlen(pathname) }, mode, dev };
  694. int rc = syscall(SC_mknod, &params);
  695. __RETURN_WITH_ERRNO(rc, rc, -1);
  696. }
  697. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fpathconf.html
  698. long fpathconf([[maybe_unused]] int fd, int name)
  699. {
  700. switch (name) {
  701. case _PC_NAME_MAX:
  702. return NAME_MAX;
  703. case _PC_PATH_MAX:
  704. return PATH_MAX;
  705. case _PC_VDISABLE:
  706. return _POSIX_VDISABLE;
  707. case _PC_LINK_MAX:
  708. return LINK_MAX;
  709. }
  710. VERIFY_NOT_REACHED();
  711. }
  712. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html
  713. long pathconf([[maybe_unused]] char const* path, int name)
  714. {
  715. switch (name) {
  716. case _PC_NAME_MAX:
  717. return NAME_MAX;
  718. case _PC_PATH_MAX:
  719. return PATH_MAX;
  720. case _PC_PIPE_BUF:
  721. return PIPE_BUF;
  722. case _PC_LINK_MAX:
  723. return LINK_MAX;
  724. }
  725. VERIFY_NOT_REACHED();
  726. }
  727. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/_exit.html
  728. void _exit(int status)
  729. {
  730. syscall(SC_exit, status);
  731. VERIFY_NOT_REACHED();
  732. }
  733. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/sync.html
  734. void sync()
  735. {
  736. syscall(SC_sync);
  737. }
  738. static String getlogin_buffer;
  739. char* getlogin()
  740. {
  741. if (getlogin_buffer.is_null()) {
  742. if (auto* passwd = getpwuid(getuid())) {
  743. getlogin_buffer = String(passwd->pw_name);
  744. }
  745. endpwent();
  746. }
  747. return const_cast<char*>(getlogin_buffer.characters());
  748. }
  749. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html
  750. int ftruncate(int fd, off_t length)
  751. {
  752. int rc = syscall(SC_ftruncate, fd, &length);
  753. __RETURN_WITH_ERRNO(rc, rc, -1);
  754. }
  755. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html
  756. int truncate(char const* path, off_t length)
  757. {
  758. int fd = open(path, O_RDWR | O_CREAT, 0666);
  759. if (fd < 0)
  760. return fd;
  761. int rc = ftruncate(fd, length);
  762. int saved_errno = errno;
  763. if (int close_rc = close(fd); close_rc < 0)
  764. return close_rc;
  765. errno = saved_errno;
  766. return rc;
  767. }
  768. int gettid()
  769. {
  770. int cached_tid = s_cached_tid;
  771. if (!cached_tid) {
  772. cached_tid = syscall(SC_gettid);
  773. s_cached_tid = cached_tid;
  774. }
  775. return cached_tid;
  776. }
  777. int sysbeep()
  778. {
  779. int rc = syscall(SC_beep);
  780. __RETURN_WITH_ERRNO(rc, rc, -1);
  781. }
  782. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html
  783. int fsync(int fd)
  784. {
  785. __pthread_maybe_cancel();
  786. int rc = syscall(SC_fsync, fd);
  787. __RETURN_WITH_ERRNO(rc, rc, -1);
  788. }
  789. int mount(int source_fd, char const* target, char const* fs_type, int flags)
  790. {
  791. if (!target || !fs_type) {
  792. errno = EFAULT;
  793. return -1;
  794. }
  795. Syscall::SC_mount_params params {
  796. { target, strlen(target) },
  797. { fs_type, strlen(fs_type) },
  798. source_fd,
  799. flags
  800. };
  801. int rc = syscall(SC_mount, &params);
  802. __RETURN_WITH_ERRNO(rc, rc, -1);
  803. }
  804. int umount(char const* mountpoint)
  805. {
  806. int rc = syscall(SC_umount, mountpoint, strlen(mountpoint));
  807. __RETURN_WITH_ERRNO(rc, rc, -1);
  808. }
  809. void dump_backtrace()
  810. {
  811. syscall(SC_dump_backtrace);
  812. }
  813. int get_process_name(char* buffer, int buffer_size)
  814. {
  815. int rc = syscall(SC_get_process_name, buffer, buffer_size);
  816. __RETURN_WITH_ERRNO(rc, rc, -1);
  817. }
  818. int set_process_name(char const* name, size_t name_length)
  819. {
  820. int rc = syscall(SC_set_process_name, name, name_length);
  821. __RETURN_WITH_ERRNO(rc, rc, -1);
  822. }
  823. int pledge(char const* promises, char const* execpromises)
  824. {
  825. Syscall::SC_pledge_params params {
  826. { promises, promises ? strlen(promises) : 0 },
  827. { execpromises, execpromises ? strlen(execpromises) : 0 }
  828. };
  829. int rc = syscall(SC_pledge, &params);
  830. __RETURN_WITH_ERRNO(rc, rc, -1);
  831. }
  832. int unveil(char const* path, char const* permissions)
  833. {
  834. Syscall::SC_unveil_params params {
  835. { path, path ? strlen(path) : 0 },
  836. { permissions, permissions ? strlen(permissions) : 0 }
  837. };
  838. int rc = syscall(SC_unveil, &params);
  839. __RETURN_WITH_ERRNO(rc, rc, -1);
  840. }
  841. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpass.html
  842. char* getpass(char const* prompt)
  843. {
  844. dbgln("FIXME: getpass('{}')", prompt);
  845. TODO();
  846. }
  847. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html
  848. long sysconf(int name)
  849. {
  850. int rc = syscall(SC_sysconf, name);
  851. __RETURN_WITH_ERRNO(rc, rc, -1);
  852. }
  853. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpagesize.html
  854. int getpagesize()
  855. {
  856. return PAGE_SIZE;
  857. }
  858. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pause.html
  859. int pause()
  860. {
  861. return select(0, nullptr, nullptr, nullptr, nullptr);
  862. }
  863. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/chroot.html
  864. int chroot(char const* path)
  865. {
  866. dbgln("FIXME: chroot(\"{}\")", path);
  867. return -1;
  868. }
  869. // https://pubs.opengroup.org/onlinepubs/7908799/xsh/getdtablesize.html
  870. int getdtablesize()
  871. {
  872. rlimit dtablesize;
  873. int rc = getrlimit(RLIMIT_NOFILE, &dtablesize);
  874. __RETURN_WITH_ERRNO(rc, dtablesize.rlim_cur, rc);
  875. }
  876. // https://pubs.opengroup.org/onlinepubs/007904975/functions/nice.html
  877. int nice(int incr)
  878. {
  879. dbgln("FIXME: nice was called with: {}, not implemented", incr);
  880. return incr;
  881. }
  882. int brk(void* addr)
  883. {
  884. dbgln("TODO: brk({:#x})", addr);
  885. errno = ENOMEM;
  886. return -1;
  887. }
  888. void* sbrk(intptr_t incr)
  889. {
  890. dbgln("TODO: sbrk({:#x})", incr);
  891. errno = ENOMEM;
  892. return reinterpret_cast<void*>(-1);
  893. }
  894. }