OLD | NEW |
1 #define _GNU_SOURCE | 1 #define _GNU_SOURCE |
2 #include <fcntl.h> | 2 #include <fcntl.h> |
3 #include <stdarg.h> | 3 #include <stdarg.h> |
4 #include <errno.h> | 4 #include <errno.h> |
5 #include "syscall.h" | 5 #include "syscall.h" |
6 #include "libc.h" | 6 #include "libc.h" |
7 | 7 |
8 int fcntl(int fd, int cmd, ...) | 8 int fcntl(int fd, int cmd, ...) { |
9 { | 9 unsigned long arg; |
10 » unsigned long arg; | 10 va_list ap; |
11 » va_list ap; | 11 va_start(ap, cmd); |
12 » va_start(ap, cmd); | 12 arg = va_arg(ap, unsigned long); |
13 » arg = va_arg(ap, unsigned long); | 13 va_end(ap); |
14 » va_end(ap); | 14 if (cmd == F_SETFL) |
15 » if (cmd == F_SETFL) arg |= O_LARGEFILE; | 15 arg |= O_LARGEFILE; |
16 » if (cmd == F_SETLKW) return syscall_cp(SYS_fcntl, fd, cmd, (void *)arg); | 16 if (cmd == F_SETLKW) |
17 » if (cmd == F_GETOWN) { | 17 return syscall_cp(SYS_fcntl, fd, cmd, (void*)arg); |
18 » » struct f_owner_ex ex; | 18 if (cmd == F_GETOWN) { |
19 » » int ret = __syscall(SYS_fcntl, fd, F_GETOWN_EX, &ex); | 19 struct f_owner_ex ex; |
20 » » if (ret == -EINVAL) return __syscall(SYS_fcntl, fd, cmd, (void *
)arg); | 20 int ret = __syscall(SYS_fcntl, fd, F_GETOWN_EX, &ex); |
21 » » if (ret) return __syscall_ret(ret); | 21 if (ret == -EINVAL) |
22 » » return ex.type == F_OWNER_PGRP ? -ex.pid : ex.pid; | 22 return __syscall(SYS_fcntl, fd, cmd, (void*)arg); |
23 » } | 23 if (ret) |
24 » if (cmd == F_DUPFD_CLOEXEC) { | 24 return __syscall_ret(ret); |
25 » » int ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, arg); | 25 return ex.type == F_OWNER_PGRP ? -ex.pid : ex.pid; |
26 » » if (ret != -EINVAL) { | 26 } |
27 » » » if (ret >= 0) | 27 if (cmd == F_DUPFD_CLOEXEC) { |
28 » » » » __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC); | 28 int ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, arg); |
29 » » » return __syscall_ret(ret); | 29 if (ret != -EINVAL) { |
30 » » } | 30 if (ret >= 0) |
31 » » ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, 0); | 31 __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC); |
32 » » if (ret != -EINVAL) { | 32 return __syscall_ret(ret); |
33 » » » if (ret >= 0) __syscall(SYS_close, ret); | 33 } |
34 » » » return __syscall_ret(-EINVAL); | 34 ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, 0); |
35 » » } | 35 if (ret != -EINVAL) { |
36 » » ret = __syscall(SYS_fcntl, fd, F_DUPFD, arg); | 36 if (ret >= 0) |
37 » » if (ret >= 0) __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC); | 37 __syscall(SYS_close, ret); |
38 » » return __syscall_ret(ret); | 38 return __syscall_ret(-EINVAL); |
39 » } | 39 } |
40 » switch (cmd) { | 40 ret = __syscall(SYS_fcntl, fd, F_DUPFD, arg); |
41 » case F_SETLK: | 41 if (ret >= 0) |
42 » case F_GETLK: | 42 __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC); |
43 » case F_GETOWN_EX: | 43 return __syscall_ret(ret); |
44 » case F_SETOWN_EX: | 44 } |
45 » » return syscall(SYS_fcntl, fd, cmd, (void *)arg); | 45 switch (cmd) { |
46 » default: | 46 case F_SETLK: |
47 » » return syscall(SYS_fcntl, fd, cmd, arg); | 47 case F_GETLK: |
48 » } | 48 case F_GETOWN_EX: |
| 49 case F_SETOWN_EX: |
| 50 return syscall(SYS_fcntl, fd, cmd, (void*)arg); |
| 51 default: |
| 52 return syscall(SYS_fcntl, fd, cmd, arg); |
| 53 } |
49 } | 54 } |
OLD | NEW |