fcntl.c 1.3 KB

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