core.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #include "toolkit.h"
  2. #include "dbgutil.h"
  3. #include "core.h"
  4. #include <errno.h>
  5. #include <fcntl.h> /* O_CLOEXEC */
  6. #include <unistd.h>
  7. #include <assert.h>
  8. #include <sys/ioctl.h>
  9. #include <sys/syscall.h>
  10. #include <sys/eventfd.h>
  11. int make_fd_cloexec(int fd, int set)
  12. {
  13. int flags;
  14. int r;
  15. do {
  16. r = fcntl(fd, F_GETFD);
  17. }while (r == -1 && errno == EINTR);
  18. if (r == -1)
  19. return -1;
  20. /* Bail out now if already set/clear. */
  21. if (!!(r & FD_CLOEXEC) == !!set)
  22. return 0;
  23. if (set)
  24. flags = r | FD_CLOEXEC;
  25. else
  26. flags = r & ~FD_CLOEXEC;
  27. do {
  28. r = fcntl(fd, F_SETFD, flags);
  29. }while (r == -1 && errno == EINTR);
  30. if (r == -1)
  31. return -1;
  32. return 0;
  33. }
  34. int make_fd_nonblock(int fd, int set)
  35. {
  36. int flags;
  37. int r;
  38. do
  39. r = fcntl(fd, F_GETFL);
  40. while (r == -1 && errno == EINTR);
  41. if (r == -1)
  42. return TOOLKIT__ERR(errno);
  43. /* Bail out now if already set/clear. */
  44. if (!!(r & O_NONBLOCK) == !!set)
  45. return 0;
  46. if (set)
  47. flags = r | O_NONBLOCK;
  48. else
  49. flags = r & ~O_NONBLOCK;
  50. do
  51. r = fcntl(fd, F_SETFL, flags);
  52. while (r == -1 && errno == EINTR);
  53. if (r)
  54. return TOOLKIT__ERR(errno);
  55. return 0;
  56. }
  57. int async_fd_create()
  58. {
  59. int fd;
  60. fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
  61. if (fd == -1) {
  62. return -1;
  63. }
  64. return fd;
  65. }
  66. void async_fd_close(int fd)
  67. {
  68. close(fd);
  69. }
  70. int toolkit__open_cloexec(const char* path, int flags)
  71. {
  72. #if defined(O_CLOEXEC)
  73. int fd;
  74. fd = open(path, flags | O_CLOEXEC);
  75. if (fd == -1)
  76. return TOOLKIT__ERR(errno);
  77. return fd;
  78. #else /* O_CLOEXEC */
  79. int err;
  80. int fd;
  81. fd = open(path, flags);
  82. if (fd == -1)
  83. return TOOLKIT__ERR(errno);
  84. err = make_fd_cloexec(fd, 1);
  85. if (err) {
  86. toolkit__close(fd);
  87. return err;
  88. }
  89. return fd;
  90. #endif /* O_CLOEXEC */
  91. }
  92. /* get a file pointer to a file in read-only and close-on-exec mode */
  93. FILE* toolkit__open_file(const char* path)
  94. {
  95. int fd;
  96. FILE* fp;
  97. fd = toolkit__open_cloexec(path, O_RDONLY);
  98. if (fd < 0)
  99. return NULL;
  100. fp = fdopen(fd, "r");
  101. if (fp == NULL)
  102. toolkit__close(fd);
  103. return fp;
  104. }
  105. int toolkit__close_nocancel(int fd)
  106. {
  107. #if defined(__APPLE__)
  108. #pragma GCC diagnostic push
  109. #pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension"
  110. #if defined(__LP64__)
  111. extern int close$NOCANCEL(int);
  112. return close$NOCANCEL(fd);
  113. #else
  114. extern int close$NOCANCEL$UNIX2003(int);
  115. return close$NOCANCEL$UNIX2003(fd);
  116. #endif
  117. #pragma GCC diagnostic pop
  118. #elif defined(__linux__)
  119. return syscall(SYS_close, fd);
  120. #else
  121. return close(fd);
  122. #endif
  123. }
  124. int toolkit__close_nocheckstdio(int fd)
  125. {
  126. int saved_errno;
  127. int rc;
  128. TOOLKIT_ASSERT(fd > -1); /* Catch uninitialized io_watcher.fd bugs. */
  129. saved_errno = errno;
  130. rc = toolkit__close_nocancel(fd);
  131. if (rc == -1) {
  132. rc = TOOLKIT__ERR(errno);
  133. if (rc == TOOLKIT_EINTR || rc == TOOLKIT__ERR(EINPROGRESS))
  134. rc = 0; /* The close is in progress, not an error. */
  135. errno = saved_errno;
  136. }
  137. return rc;
  138. }
  139. int toolkit__close(int fd)
  140. {
  141. TOOLKIT_ASSERT(fd > STDERR_FILENO); /* Catch stdio close bugs. */
  142. #if defined(__MVS__)
  143. SAVE_ERRNO(epoll_file_close(fd));
  144. #endif
  145. return toolkit__close_nocheckstdio(fd);
  146. }