1 | // SPDX-License-Identifier: GPL-3.0-or-later |
2 | |
3 | #include "mos/device/timer.h" |
4 | #include "mos/ipc/ipc_io.h" |
5 | #include "mos/ipc/memfd.h" |
6 | #include "mos/ipc/pipe.h" |
7 | #include "mos/misc/power.h" |
8 | #include "mos/mm/dma.h" |
9 | #include "mos/tasks/signal.h" |
10 | |
11 | #include <bits/posix/iovec.h> |
12 | #include <errno.h> |
13 | #include <fcntl.h> |
14 | #include <mos/filesystem/fs_types.h> |
15 | #include <mos/filesystem/vfs.h> |
16 | #include <mos/io/io.h> |
17 | #include <mos/locks/futex.h> |
18 | #include <mos/mm/mmap.h> |
19 | #include <mos/mm/paging/paging.h> |
20 | #include <mos/platform/platform.h> |
21 | #include <mos/syscall/decl.h> |
22 | #include <mos/syscall/number.h> |
23 | #include <mos/syslog/printk.h> |
24 | #include <mos/tasks/elf.h> |
25 | #include <mos/tasks/process.h> |
26 | #include <mos/tasks/schedule.h> |
27 | #include <mos/tasks/task_types.h> |
28 | #include <mos/tasks/thread.h> |
29 | #include <mos/types.h> |
30 | #include <mos_stdlib.h> |
31 | #include <mos_string.h> |
32 | #include <sys/poll.h> |
33 | |
34 | #define DEFINE_SYSCALL(ret, name) \ |
35 | MOS_STATIC_ASSERT(SYSCALL_DEFINED(name)); \ |
36 | ret define_syscall(name) |
37 | |
38 | DEFINE_SYSCALL(void, poweroff)(bool reboot, u32 magic) |
39 | { |
40 | #define POWEROFF_MAGIC MOS_FOURCC('G', 'B', 'y', 'e') |
41 | if (magic != POWEROFF_MAGIC) |
42 | { |
43 | mos_warn("poweroff syscall called with wrong magic number (0x%x)" , magic); |
44 | return; |
45 | } |
46 | |
47 | if (!reboot) |
48 | { |
49 | pr_info("Meow, see ya~ :3" ); |
50 | power_shutdown(); |
51 | } |
52 | else |
53 | { |
54 | mos_warn("reboot is not implemented yet" ); |
55 | } |
56 | } |
57 | |
58 | DEFINE_SYSCALL(fd_t, vfs_openat)(fd_t dirfd, const char *path, open_flags flags) |
59 | { |
60 | if (path == NULL) |
61 | return -1; |
62 | |
63 | file_t *f = vfs_openat(fd: dirfd, path, flags); |
64 | if (IS_ERR(ptr: f)) |
65 | return PTR_ERR(ptr: f); |
66 | return process_attach_ref_fd(current_process, file: &f->io, flags: FD_FLAGS_NONE); |
67 | } |
68 | |
69 | DEFINE_SYSCALL(long, vfs_fstatat)(fd_t fd, const char *path, file_stat_t *stat_buf, fstatat_flags flags) |
70 | { |
71 | return vfs_fstatat(fd, path, stat: stat_buf, flags); |
72 | } |
73 | |
74 | DEFINE_SYSCALL(size_t, io_read)(fd_t fd, void *buf, size_t count) |
75 | { |
76 | if (buf == NULL) |
77 | return -EFAULT; |
78 | |
79 | io_t *io = process_get_fd(current_process, fd); |
80 | if (!io) |
81 | return -EBADF; |
82 | |
83 | return io_read(io, buf, count); |
84 | } |
85 | |
86 | DEFINE_SYSCALL(size_t, io_write)(fd_t fd, const void *buf, size_t count) |
87 | { |
88 | if (buf == NULL) |
89 | { |
90 | pr_warn("io_write called with invalid arguments (fd=%d, buf=%p, count=%zd)" , fd, buf, count); |
91 | return -EFAULT; |
92 | } |
93 | |
94 | io_t *io = process_get_fd(current_process, fd); |
95 | if (!io) |
96 | { |
97 | pr_warn("io_write called with invalid fd %d" , fd); |
98 | return -EBADF; |
99 | } |
100 | |
101 | return io_write(io, buf, count); |
102 | } |
103 | |
104 | DEFINE_SYSCALL(bool, io_close)(fd_t fd) |
105 | { |
106 | process_detach_fd(current_process, fd); |
107 | return true; |
108 | } |
109 | |
110 | DEFINE_SYSCALL([[noreturn]] void, exit)(u32 exit_code) |
111 | { |
112 | // only use the lower 8 bits |
113 | exit_code &= 0xff; |
114 | process_exit(current_process, exit_code, signal: 0); |
115 | } |
116 | |
117 | DEFINE_SYSCALL(void, yield_cpu)(void) |
118 | { |
119 | spinlock_acquire(¤t_thread->state_lock); |
120 | reschedule(); |
121 | } |
122 | |
123 | DEFINE_SYSCALL(pid_t, fork)(void) |
124 | { |
125 | process_t *parent = current_process; |
126 | process_t *child = process_do_fork(process: parent); |
127 | if (unlikely(child == NULL)) |
128 | return -1; |
129 | return child->pid; // return 0 for child, pid for parent |
130 | } |
131 | |
132 | DEFINE_SYSCALL(pid_t, get_pid)(void) |
133 | { |
134 | return current_process->pid; |
135 | } |
136 | |
137 | DEFINE_SYSCALL(pid_t, get_parent_pid)(void) |
138 | { |
139 | return current_process->parent->pid; |
140 | } |
141 | |
142 | DEFINE_SYSCALL(pid_t, spawn)(const char *path, const char *const argv[], const char *const envp[]) |
143 | { |
144 | const stdio_t stdio = current_stdio(); |
145 | process_t *process = elf_create_process(path, current_process, argv, envp, ios: &stdio); |
146 | |
147 | if (process == NULL) |
148 | return -1; |
149 | |
150 | return process->pid; |
151 | } |
152 | |
153 | DEFINE_SYSCALL(tid_t, create_thread)(const char *name, thread_entry_t entry, void *arg, size_t stack_size, void *stack) |
154 | { |
155 | thread_t *thread = thread_new(current_process, mode: THREAD_MODE_USER, name, stack_size, stack); |
156 | if (thread == NULL) |
157 | return -1; |
158 | |
159 | platform_context_setup_child_thread(thread, entry, arg); |
160 | thread_complete_init(thread); |
161 | scheduler_add_thread(thread); |
162 | return thread->tid; |
163 | } |
164 | |
165 | DEFINE_SYSCALL(tid_t, get_tid)(void) |
166 | { |
167 | return current_thread->tid; |
168 | } |
169 | |
170 | DEFINE_SYSCALL([[noreturn]] void, thread_exit)(void) |
171 | { |
172 | thread_exit(current_thread); |
173 | } |
174 | |
175 | DEFINE_SYSCALL(bool, wait_for_thread)(tid_t tid) |
176 | { |
177 | return thread_wait_for_tid(tid); |
178 | } |
179 | |
180 | DEFINE_SYSCALL(bool, futex_wait)(futex_word_t *futex, u32 val) |
181 | { |
182 | return futex_wait(futex, expected: val); |
183 | } |
184 | |
185 | DEFINE_SYSCALL(bool, futex_wake)(futex_word_t *futex, size_t count) |
186 | { |
187 | return futex_wake(lock: futex, num_to_wake: count); |
188 | } |
189 | |
190 | DEFINE_SYSCALL(fd_t, ipc_create)(const char *name, size_t max_pending_connections) |
191 | { |
192 | io_t *io = ipc_create(name, max_pending_connections); |
193 | if (IS_ERR(ptr: io)) |
194 | return PTR_ERR(ptr: io); |
195 | return process_attach_ref_fd(current_process, file: io, flags: FD_FLAGS_NONE); |
196 | } |
197 | |
198 | DEFINE_SYSCALL(fd_t, ipc_accept)(fd_t listen_fd) |
199 | { |
200 | io_t *server = process_get_fd(current_process, fd: listen_fd); |
201 | if (server == NULL) |
202 | return -1; |
203 | |
204 | io_t *client_io = ipc_accept(server); |
205 | if (IS_ERR(ptr: client_io)) |
206 | return PTR_ERR(ptr: client_io); |
207 | |
208 | return process_attach_ref_fd(current_process, file: client_io, flags: FD_FLAGS_NONE); |
209 | } |
210 | |
211 | DEFINE_SYSCALL(fd_t, ipc_connect)(const char *server, size_t buffer_size) |
212 | { |
213 | io_t *io = ipc_connect(name: server, buffer_size); |
214 | if (IS_ERR(ptr: io)) |
215 | return PTR_ERR(ptr: io); |
216 | return process_attach_ref_fd(current_process, file: io, flags: FD_FLAGS_NONE); |
217 | } |
218 | |
219 | DEFINE_SYSCALL(u64, arch_syscall)(u64 syscall, u64 arg1, u64 arg2, u64 arg3, u64 arg4) |
220 | { |
221 | return platform_arch_syscall(syscall, arg1, arg2, arg3, arg4); |
222 | } |
223 | |
224 | DEFINE_SYSCALL(long, vfs_mount)(const char *device, const char *mountpoint, const char *fs_type, const char *options) |
225 | { |
226 | return vfs_mount(device, path: mountpoint, fs: fs_type, options); |
227 | } |
228 | |
229 | DEFINE_SYSCALL(ssize_t, vfs_readlinkat)(fd_t dirfd, const char *path, char *buf, size_t buflen) |
230 | { |
231 | return vfs_readlinkat(dirfd, path, buf, size: buflen); |
232 | } |
233 | |
234 | DEFINE_SYSCALL(long, vfs_unlinkat)(fd_t dirfd, const char *path) |
235 | { |
236 | return vfs_unlinkat(dirfd, path); |
237 | } |
238 | |
239 | DEFINE_SYSCALL(long, vfs_symlink)(const char *target, const char *linkpath) |
240 | { |
241 | return vfs_symlink(path: target, target: linkpath); |
242 | } |
243 | |
244 | DEFINE_SYSCALL(long, vfs_mkdir)(const char *path) |
245 | { |
246 | return vfs_mkdir(path); |
247 | } |
248 | |
249 | DEFINE_SYSCALL(size_t, vfs_list_dir)(fd_t fd, char *buffer, size_t buffer_size) |
250 | { |
251 | io_t *io = process_get_fd(current_process, fd); |
252 | if (io == NULL) |
253 | return false; |
254 | return vfs_list_dir(io, buf: buffer, size: buffer_size); |
255 | } |
256 | |
257 | DEFINE_SYSCALL(long, fd_manipulate)(fd_t fd, u64 op, void *arg) |
258 | { |
259 | fd_type *fdt = ¤t_process->files[fd]; |
260 | if (fdt->io == NULL) |
261 | return -EBADF; |
262 | |
263 | switch (op) |
264 | { |
265 | case F_DUPFD: |
266 | { |
267 | fd_t fd2 = process_attach_ref_fd(current_process, file: fdt->io, flags: fdt->flags); |
268 | return fd2; |
269 | } |
270 | case F_DUPFD_CLOEXEC: |
271 | { |
272 | fd_t fd2 = process_attach_ref_fd(current_process, file: fdt->io, flags: fdt->flags | FD_FLAGS_CLOEXEC); |
273 | return fd2; |
274 | } |
275 | case F_GETFD: |
276 | { |
277 | return fdt->flags; |
278 | } |
279 | case F_SETFD: |
280 | { |
281 | // test if arg is a valid flag |
282 | u64 flags = (u64) arg; |
283 | if (flags & ~FD_FLAGS_CLOEXEC) |
284 | return -EINVAL; |
285 | fdt->flags = flags; |
286 | return 0; |
287 | } |
288 | case F_GETFL: |
289 | case F_SETFL: |
290 | { |
291 | return -ENOSYS; // not implemented |
292 | } |
293 | case F_GETLK: |
294 | case F_SETLK: |
295 | case F_SETLKW: |
296 | { |
297 | return -ENOSYS; // not implemented |
298 | } |
299 | case F_GETOWN: |
300 | case F_SETOWN: |
301 | case F_GETOWN_EX: |
302 | case F_SETOWN_EX: |
303 | case F_GETSIG: |
304 | case F_SETSIG: |
305 | case F_GETOWNER_UIDS: |
306 | case F_ADD_SEALS: |
307 | case F_GET_SEALS: |
308 | { |
309 | return -ENOSYS; // not implemented |
310 | } |
311 | } |
312 | |
313 | return -EINVAL; |
314 | } |
315 | |
316 | DEFINE_SYSCALL(void *, mmap_anonymous)(ptr_t hint_addr, size_t size, mem_perm_t perm, mmap_flags_t flags) |
317 | { |
318 | const vm_flags vmflags = VM_USER | (vm_flags) perm; // vm_flags shares the same values as mem_perm_t |
319 | const size_t n_pages = ALIGN_UP_TO_PAGE(size) / MOS_PAGE_SIZE; |
320 | |
321 | ptr_t result = mmap_anonymous(current_mm, hint_addr, flags, vm_flags: vmflags, n_pages); |
322 | return (void *) result; |
323 | } |
324 | |
325 | DEFINE_SYSCALL(void *, mmap_file)(ptr_t hint_addr, size_t size, mem_perm_t perm, mmap_flags_t mmap_flags, fd_t fd, off_t offset) |
326 | { |
327 | const vm_flags vmflags = VM_USER | (vm_flags) perm; // vm_flags shares the same values as mem_perm_t |
328 | const size_t n_pages = ALIGN_UP_TO_PAGE(size) / MOS_PAGE_SIZE; |
329 | |
330 | io_t *io = process_get_fd(current_process, fd); |
331 | if (io == NULL) |
332 | return NULL; |
333 | |
334 | ptr_t result = mmap_file(current_mm, hint_addr, flags: mmap_flags, vm_flags: vmflags, n_pages, io, offset); |
335 | return (void *) result; |
336 | } |
337 | |
338 | DEFINE_SYSCALL(pid_t, wait_for_process)(pid_t pid, u32 *exit_code, u32 flags) |
339 | { |
340 | return process_wait_for_pid(pid, exit_code, flags); |
341 | } |
342 | |
343 | DEFINE_SYSCALL(bool, munmap)(void *addr, size_t size) |
344 | { |
345 | return munmap(addr: (ptr_t) addr, size); |
346 | } |
347 | |
348 | DEFINE_SYSCALL(long, vfs_chdirat)(fd_t dirfd, const char *path) |
349 | { |
350 | return vfs_chdirat(dirfd, path); |
351 | } |
352 | |
353 | DEFINE_SYSCALL(ssize_t, vfs_getcwd)(char *buf, size_t size) |
354 | { |
355 | return vfs_getcwd(buf, size); |
356 | } |
357 | |
358 | DEFINE_SYSCALL(off_t, io_seek)(fd_t fd, off_t offset, io_seek_whence_t whence) |
359 | { |
360 | io_t *io = process_get_fd(current_process, fd); |
361 | if (io == NULL) |
362 | return -1; |
363 | return io_seek(io, offset, whence); |
364 | } |
365 | |
366 | DEFINE_SYSCALL(off_t, io_tell)(fd_t fd) |
367 | { |
368 | io_t *io = process_get_fd(current_process, fd); |
369 | if (io == NULL) |
370 | return -1; |
371 | return io_tell(io); |
372 | } |
373 | |
374 | DEFINE_SYSCALL(bool, signal_register)(signal_t sig, const sigaction_t *action) |
375 | { |
376 | return process_register_signal_handler(current_process, sig, sigaction: action); |
377 | } |
378 | |
379 | DEFINE_SYSCALL(long, signal_process)(pid_t pid, signal_t sig) |
380 | { |
381 | process_t *process = process_get(pid); |
382 | if (!process) |
383 | return -ESRCH; |
384 | return signal_send_to_process(target: process, signal: sig); |
385 | } |
386 | |
387 | DEFINE_SYSCALL(long, signal_thread)(tid_t tid, signal_t sig) |
388 | { |
389 | thread_t *thread = thread_get(id: tid); |
390 | if (thread == NULL) |
391 | return -ESRCH; |
392 | return signal_send_to_thread(target: thread, signal: sig); |
393 | } |
394 | |
395 | DEFINE_SYSCALL([[noreturn]] void, signal_return)(void *sp) |
396 | { |
397 | platform_restore_from_signal_handler(sp); |
398 | } |
399 | |
400 | DEFINE_SYSCALL(bool, vm_protect)(void *addr, size_t size, mem_perm_t perm) |
401 | { |
402 | return vm_protect(current_mm, addr: (ptr_t) addr, size, perm: (vm_flags) perm); |
403 | } |
404 | |
405 | DEFINE_SYSCALL(int, io_poll)(struct pollfd *fds, nfds_t nfds, int timeout) |
406 | { |
407 | if (timeout == 0) // poll with timeout 0 is just a check |
408 | return 0; |
409 | |
410 | if (!fds || nfds == 0) |
411 | return -1; |
412 | |
413 | for (nfds_t i = 0; i < nfds; i++) |
414 | { |
415 | if (fds[i].fd < 0) |
416 | fds[i].revents = 0; |
417 | pr_info2("io_poll: fd=%d, events=%d" , fds[i].fd, fds[i].events); |
418 | } |
419 | |
420 | pr_emerg("io_poll is not implemented yet\n" ); |
421 | signal_send_to_thread(current_thread, SIGKILL); // unimplemented |
422 | return 0; |
423 | } |
424 | |
425 | #ifndef FD_CLR |
426 | #define FD_CLR(__fd, __set) (__set->fds_bits[__fd / 8] &= ~(1 << (__fd % 8))) |
427 | #endif |
428 | |
429 | #ifndef FD_ISSET |
430 | #define FD_ISSET(__fd, __set) (__set->fds_bits[__fd / 8] & (1 << (__fd % 8))) |
431 | #endif |
432 | |
433 | #ifndef FD_SET |
434 | #define FD_SET(__fd, __set) (__set->fds_bits[__fd / 8] |= 1 << (__fd % 8)) |
435 | #endif |
436 | |
437 | #ifndef FD_ZERO |
438 | #define FD_ZERO(__set) memset(__set->fds_bits, 0, sizeof(fd_set)) |
439 | #endif |
440 | |
441 | DEFINE_SYSCALL(int, io_pselect)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask) |
442 | { |
443 | MOS_UNUSED(timeout); |
444 | MOS_UNUSED(sigmask); |
445 | |
446 | for (int i = 0; i < nfds; i++) |
447 | { |
448 | if (readfds && FD_ISSET(i, readfds)) |
449 | { |
450 | // pr_info2("io_pselect: fd=%d, read", i); |
451 | } |
452 | if (writefds && FD_ISSET(i, writefds)) |
453 | { |
454 | // pr_info2("io_pselect: fd=%d, write", i); |
455 | } |
456 | if (exceptfds && FD_ISSET(i, exceptfds)) |
457 | { |
458 | // pr_info2("io_pselect: fd=%d, except", i); |
459 | } |
460 | } |
461 | |
462 | return 1; // stub |
463 | } |
464 | |
465 | DEFINE_SYSCALL(long, execveat)(fd_t dirfd, const char *path, const char *const argv[], const char *const envp[], u32 flags) |
466 | { |
467 | return process_do_execveat(current_process, dirfd, path, argv, envp, flags); |
468 | } |
469 | |
470 | DEFINE_SYSCALL(long, clock_msleep)(u64 ms) |
471 | { |
472 | timer_msleep(ms); |
473 | return 0; |
474 | } |
475 | |
476 | DEFINE_SYSCALL(fd_t, io_dup)(fd_t fd) |
477 | { |
478 | io_t *io = process_get_fd(current_process, fd); |
479 | if (io == NULL) |
480 | return -EBADF; // fd is not a valid file descriptor |
481 | return process_attach_ref_fd(current_process, file: io_ref(io), current_process->files[fd].flags); |
482 | } |
483 | |
484 | DEFINE_SYSCALL(fd_t, io_dup2)(fd_t oldfd, fd_t newfd) |
485 | { |
486 | fd_type *old = ¤t_process->files[oldfd]; |
487 | if (old->io == NULL) |
488 | return -EBADF; // oldfd is not a valid file descriptor |
489 | |
490 | if (oldfd == newfd) |
491 | return newfd; |
492 | |
493 | process_detach_fd(current_process, fd: newfd); |
494 | |
495 | current_process->files[newfd].io = io_ref(io: old->io); |
496 | current_process->files[newfd].flags = old->flags; |
497 | return newfd; |
498 | } |
499 | |
500 | DEFINE_SYSCALL(bool, dmabuf_alloc)(size_t n_pages, ptr_t *phys, ptr_t *virt) |
501 | { |
502 | pfn_t pfn = dmabuf_allocate(n_pages, pages: virt); |
503 | *phys = pfn * MOS_PAGE_SIZE; |
504 | return !IS_ERR_VALUE(pfn); |
505 | } |
506 | |
507 | DEFINE_SYSCALL(bool, dmabuf_free)(ptr_t vaddr, ptr_t paddr) |
508 | { |
509 | return dmabuf_free(vaddr, paddr); |
510 | } |
511 | |
512 | DEFINE_SYSCALL(bool, dmabuf_share)(void *buffer, size_t size, ptr_t *phyaddr) |
513 | { |
514 | pfn_t pfn = dmabuf_share(buffer, size); |
515 | |
516 | if (IS_ERR_VALUE(pfn)) |
517 | return false; |
518 | |
519 | *phyaddr = pfn * MOS_PAGE_SIZE; |
520 | return true; |
521 | } |
522 | |
523 | DEFINE_SYSCALL(bool, dmabuf_unshare)(ptr_t phys, size_t size, void *buf) |
524 | { |
525 | return dmabuf_unshare(phys, size, virt: buf); |
526 | } |
527 | |
528 | DEFINE_SYSCALL(long, pipe)(fd_t *reader, fd_t *writer, fd_flags_t flags) |
529 | { |
530 | pipe_t *pipe = pipe_create(MOS_PAGE_SIZE * 4); |
531 | if (IS_ERR(ptr: pipe)) |
532 | return PTR_ERR(ptr: pipe); |
533 | |
534 | pipeio_t *pipeio = pipeio_create(pipe); |
535 | *reader = process_attach_ref_fd(current_process, file: &pipeio->io_r, flags); |
536 | *writer = process_attach_ref_fd(current_process, file: &pipeio->io_w, flags); |
537 | return 0; |
538 | } |
539 | |
540 | DEFINE_SYSCALL(ssize_t, io_readv)(fd_t fd, const struct iovec *iov, int iovcnt) |
541 | { |
542 | if (fd < 0) |
543 | return -EBADF; |
544 | |
545 | if (iov == NULL) |
546 | return -EFAULT; |
547 | |
548 | io_t *io = process_get_fd(current_process, fd); |
549 | if (!io) |
550 | return -EBADF; |
551 | |
552 | for (int i = 0; i < iovcnt; i++) |
553 | { |
554 | if (iov[i].iov_base == NULL) |
555 | return -EFAULT; |
556 | } |
557 | |
558 | ssize_t bytes_read = 0; |
559 | |
560 | for (int i = 0; i < iovcnt; i++) |
561 | { |
562 | size_t ret = io_read(io, buf: iov[i].iov_base, count: iov[i].iov_len); |
563 | if (IS_ERR_VALUE(ret)) |
564 | return ret; |
565 | |
566 | bytes_read += ret; |
567 | |
568 | if (ret != iov[i].iov_len) |
569 | break; // short read, leave |
570 | } |
571 | |
572 | return bytes_read; |
573 | } |
574 | |
575 | DEFINE_SYSCALL(long, vfs_unmount)(const char *path) |
576 | { |
577 | return vfs_unmount(path); |
578 | } |
579 | |
580 | DEFINE_SYSCALL(long, clock_gettimeofday)(struct timespec *ts) |
581 | { |
582 | timeval_t tv; |
583 | platform_get_time(val: &tv); |
584 | ts->tv_sec = tv.hour * 3600 + tv.minute * 60 + tv.second; |
585 | ts->tv_nsec = 0; |
586 | return 0; |
587 | } |
588 | |
589 | DEFINE_SYSCALL(long, thread_setname)(tid_t tid, const char *name) |
590 | { |
591 | thread_t *thread = thread_get(id: tid); |
592 | if (thread == NULL) |
593 | return -ESRCH; |
594 | |
595 | if (thread->name) |
596 | kfree(ptr: thread->name); |
597 | |
598 | thread->name = strdup(src: name); |
599 | return true; |
600 | } |
601 | |
602 | DEFINE_SYSCALL(ssize_t, thread_getname)(tid_t tid, char *buf, size_t buflen) |
603 | { |
604 | thread_t *thread = thread_get(id: tid); |
605 | |
606 | if (thread == NULL) |
607 | return -ESRCH; |
608 | |
609 | char *end = strncpy(dest: buf, src: thread->name, n: buflen); |
610 | return end - buf; |
611 | } |
612 | |
613 | DEFINE_SYSCALL(long, vfs_fchmodat)(fd_t dirfd, const char *path, int mode, int flags) |
614 | { |
615 | return vfs_fchmodat(fd: dirfd, path, perm: mode, flags); |
616 | } |
617 | |
618 | DEFINE_SYSCALL(long, io_pread)(fd_t fd, void *buf, size_t count, off_t offset) |
619 | { |
620 | if (fd < 0) |
621 | return -EBADF; |
622 | |
623 | if (buf == NULL) |
624 | return -EFAULT; |
625 | |
626 | io_t *io = process_get_fd(current_process, fd); |
627 | if (!io) |
628 | return -EBADF; |
629 | |
630 | return io_pread(io, buf, count, offset); |
631 | } |
632 | |
633 | DEFINE_SYSCALL(fd_t, memfd_create)(const char *name, u32 flags) |
634 | { |
635 | io_t *io = memfd_create(name); |
636 | if (IS_ERR(ptr: io)) |
637 | return PTR_ERR(ptr: io); |
638 | |
639 | return process_attach_ref_fd(current_process, file: io, flags); |
640 | } |
641 | |
642 | DEFINE_SYSCALL(long, signal_mask_op)(int how, const sigset_t *set, sigset_t *oldset) |
643 | { |
644 | if (oldset) |
645 | *oldset = current_thread->signal_info.mask; |
646 | |
647 | if (set) |
648 | { |
649 | switch (how) |
650 | { |
651 | case SIG_SETMASK: current_thread->signal_info.mask = *set; break; |
652 | case SIG_BLOCK: |
653 | { |
654 | char *ptr = (char *) set; |
655 | char *mask = (char *) ¤t_thread->signal_info.mask; |
656 | for (size_t i = 0; i < sizeof(sigset_t); i++) |
657 | mask[i] |= ptr[i]; |
658 | break; |
659 | } |
660 | case SIG_UNBLOCK: |
661 | { |
662 | char *ptr = (char *) set; |
663 | char *mask = (char *) ¤t_thread->signal_info.mask; |
664 | for (size_t i = 0; i < sizeof(sigset_t); i++) |
665 | mask[i] &= ~ptr[i]; |
666 | break; |
667 | } |
668 | default: return -EINVAL; |
669 | } |
670 | } |
671 | |
672 | return 0; |
673 | } |
674 | |
675 | DEFINE_SYSCALL(long, vfs_fsync)(fd_t fd, bool data_only) |
676 | { |
677 | io_t *io = process_get_fd(current_process, fd); |
678 | if (!io) |
679 | return -EBADF; |
680 | |
681 | if (io->type != IO_FILE) |
682 | return -EBADF; |
683 | |
684 | return vfs_fsync(io, sync_metadata: data_only, start: 0, end: (off_t) -1); |
685 | } |
686 | |