123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- #include "toolkit.h"
- #include "dbgutil.h"
- #include "core.h"
- #include <errno.h>
- #include <fcntl.h> /* O_CLOEXEC */
- #include <unistd.h>
- #include <assert.h>
- #include <sys/ioctl.h>
- #include <sys/syscall.h>
- #include <sys/eventfd.h>
- int make_fd_cloexec(int fd, int set)
- {
- int flags;
- int r;
- do {
- r = fcntl(fd, F_GETFD);
- }while (r == -1 && errno == EINTR);
- if (r == -1)
- return -1;
- /* Bail out now if already set/clear. */
- if (!!(r & FD_CLOEXEC) == !!set)
- return 0;
- if (set)
- flags = r | FD_CLOEXEC;
- else
- flags = r & ~FD_CLOEXEC;
- do {
- r = fcntl(fd, F_SETFD, flags);
- }while (r == -1 && errno == EINTR);
- if (r == -1)
- return -1;
- return 0;
- }
- int make_fd_nonblock(int fd, int set)
- {
- int flags;
- int r;
- do
- r = fcntl(fd, F_GETFL);
- while (r == -1 && errno == EINTR);
- if (r == -1)
- return TOOLKIT__ERR(errno);
- /* Bail out now if already set/clear. */
- if (!!(r & O_NONBLOCK) == !!set)
- return 0;
- if (set)
- flags = r | O_NONBLOCK;
- else
- flags = r & ~O_NONBLOCK;
- do
- r = fcntl(fd, F_SETFL, flags);
- while (r == -1 && errno == EINTR);
- if (r)
- return TOOLKIT__ERR(errno);
- return 0;
- }
- int async_fd_create()
- {
- int fd;
- fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
- if (fd == -1) {
- return -1;
- }
- return fd;
- }
- void async_fd_close(int fd)
- {
- close(fd);
- }
- int toolkit__open_cloexec(const char* path, int flags)
- {
- #if defined(O_CLOEXEC)
- int fd;
- fd = open(path, flags | O_CLOEXEC);
- if (fd == -1)
- return TOOLKIT__ERR(errno);
- return fd;
- #else /* O_CLOEXEC */
- int err;
- int fd;
- fd = open(path, flags);
- if (fd == -1)
- return TOOLKIT__ERR(errno);
- err = make_fd_cloexec(fd, 1);
- if (err) {
- toolkit__close(fd);
- return err;
- }
- return fd;
- #endif /* O_CLOEXEC */
- }
- /* get a file pointer to a file in read-only and close-on-exec mode */
- FILE* toolkit__open_file(const char* path)
- {
- int fd;
- FILE* fp;
- fd = toolkit__open_cloexec(path, O_RDONLY);
- if (fd < 0)
- return NULL;
- fp = fdopen(fd, "r");
- if (fp == NULL)
- toolkit__close(fd);
- return fp;
- }
- int toolkit__close_nocancel(int fd)
- {
- #if defined(__APPLE__)
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension"
- #if defined(__LP64__)
- extern int close$NOCANCEL(int);
- return close$NOCANCEL(fd);
- #else
- extern int close$NOCANCEL$UNIX2003(int);
- return close$NOCANCEL$UNIX2003(fd);
- #endif
- #pragma GCC diagnostic pop
- #elif defined(__linux__)
- return syscall(SYS_close, fd);
- #else
- return close(fd);
- #endif
- }
- int toolkit__close_nocheckstdio(int fd)
- {
- int saved_errno;
- int rc;
- TOOLKIT_ASSERT(fd > -1); /* Catch uninitialized io_watcher.fd bugs. */
- saved_errno = errno;
- rc = toolkit__close_nocancel(fd);
- if (rc == -1) {
- rc = TOOLKIT__ERR(errno);
- if (rc == TOOLKIT_EINTR || rc == TOOLKIT__ERR(EINPROGRESS))
- rc = 0; /* The close is in progress, not an error. */
- errno = saved_errno;
- }
- return rc;
- }
- int toolkit__close(int fd)
- {
- TOOLKIT_ASSERT(fd > STDERR_FILENO); /* Catch stdio close bugs. */
- #if defined(__MVS__)
- SAVE_ERRNO(epoll_file_close(fd));
- #endif
- return toolkit__close_nocheckstdio(fd);
- }
|