overhaul mbsrtowcs
[musl] / src / fcntl / fcntl.c
1 #define _GNU_SOURCE
2 #include <fcntl.h>
3 #include <unistd.h>
4 #include <stdarg.h>
5 #include <errno.h>
6 #include "syscall.h"
7 #include "libc.h"
8
9 int fcntl(int fd, int cmd, ...)
10 {
11         long arg;
12         va_list ap;
13         va_start(ap, cmd);
14         arg = va_arg(ap, long);
15         va_end(ap);
16         if (cmd == F_SETFL) arg |= O_LARGEFILE;
17         if (cmd == F_SETLKW) return syscall_cp(SYS_fcntl, fd, cmd, arg);
18         if (cmd == F_GETOWN) {
19                 struct f_owner_ex ex;
20                 int ret = __syscall(SYS_fcntl, fd, F_GETOWN_EX, &ex);
21                 if (ret == -EINVAL) return __syscall(SYS_fcntl, fd, cmd, arg);
22                 if (ret) return __syscall_ret(ret);
23                 return ex.type == F_OWNER_PGRP ? -ex.pid : ex.pid;
24         }
25         if (cmd == F_DUPFD_CLOEXEC) {
26                 int ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, arg);
27                 if (ret != -EINVAL) {
28                         if (ret >= 0)
29                                 __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC);
30                         return __syscall_ret(ret);
31                 }
32                 ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, 0);
33                 if (ret != -EINVAL) {
34                         if (ret >= 0) __syscall(SYS_close, ret);
35                         return __syscall_ret(-EINVAL);
36                 }
37                 ret = __syscall(SYS_fcntl, fd, F_DUPFD, arg);
38                 if (ret >= 0) __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC);
39                 return __syscall_ret(ret);
40         }
41         return syscall(SYS_fcntl, fd, cmd, arg);
42 }