Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <Kernel/FileSystem/FIFO.h>
8#include <Kernel/Process.h>
9
10namespace Kernel {
11
12ErrorOr<FlatPtr> Process::sys$pipe(Userspace<int*> pipefd, int flags)
13{
14 VERIFY_NO_PROCESS_BIG_LOCK(this);
15 TRY(require_promise(Pledge::stdio));
16
17 // Reject flags other than O_CLOEXEC, O_NONBLOCK
18 if ((flags & (O_CLOEXEC | O_NONBLOCK)) != flags)
19 return EINVAL;
20
21 u32 fd_flags = (flags & O_CLOEXEC) ? FD_CLOEXEC : 0;
22 auto credentials = this->credentials();
23 auto fifo = TRY(FIFO::try_create(credentials->uid()));
24
25 auto reader_description = TRY(fifo->open_direction(FIFO::Direction::Reader));
26 auto writer_description = TRY(fifo->open_direction(FIFO::Direction::Writer));
27
28 reader_description->set_readable(true);
29 writer_description->set_writable(true);
30 if (flags & O_NONBLOCK) {
31 reader_description->set_blocking(false);
32 writer_description->set_blocking(false);
33 }
34
35 TRY(m_fds.with_exclusive([&](auto& fds) -> ErrorOr<void> {
36 auto reader_fd_allocation = TRY(fds.allocate());
37 auto writer_fd_allocation = TRY(fds.allocate());
38
39 fds[reader_fd_allocation.fd].set(move(reader_description), fd_flags);
40 fds[writer_fd_allocation.fd].set(move(writer_description), fd_flags);
41
42 int fds_for_userspace[2] = {
43 reader_fd_allocation.fd,
44 writer_fd_allocation.fd,
45 };
46 if (copy_to_user(pipefd, fds_for_userspace, sizeof(fds_for_userspace)).is_error()) {
47 fds[reader_fd_allocation.fd] = {};
48 fds[writer_fd_allocation.fd] = {};
49 return EFAULT;
50 }
51 return {};
52 }));
53 return 0;
54}
55
56}