1 /* $OpenBSD: uthread_closefrom.c,v 1.1 2004/01/15 22:22:11 marc Exp $ */ 2 3 /* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */ 4 5 #include <sys/stat.h> 6 7 #include <errno.h> 8 #include <fcntl.h> 9 #include <pthread.h> 10 #include <unistd.h> 11 12 #include "pthread_private.h" 13 14 /* 15 * Reset the non-blocking flag if necessary. Remove the fd table entry 16 * for the given fd. 17 */ 18 static void _close_flags(int fd)19_close_flags(int fd) 20 { 21 struct stat sb; 22 int flags; 23 24 if (_FD_LOCK(fd, FD_RDWR, NULL) == 0) { 25 if ((_thread_sys_fstat(fd, &sb) == 0) && 26 ((S_ISREG(sb.st_mode) || S_ISCHR(sb.st_mode)) && 27 (_thread_fd_table[fd]->flags & O_NONBLOCK) == 0)) { 28 /* Get the current flags: */ 29 flags = _thread_sys_fcntl(fd, F_GETFL, NULL); 30 /* Clear the nonblocking file descriptor flag: */ 31 _thread_sys_fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); 32 } 33 _thread_fd_table_remove(fd); 34 } 35 } 36 37 int closefrom(int fd)38closefrom(int fd) 39 { 40 int ret; 41 int safe_fd; 42 int lock_fd; 43 44 _thread_enter_cancellation_point(); 45 46 if (fd < 0 || fd >= _thread_dtablesize) { 47 errno = EBADF; 48 ret = -1; 49 } else { 50 safe_fd = _thread_kern_pipe[0] > _thread_kern_pipe[1] ? 51 _thread_kern_pipe[0] : _thread_kern_pipe[1]; 52 53 /* 54 * close individual files until we get past the pipe 55 * fds. Attempting to close a pipe fd is a no-op. 56 */ 57 for (safe_fd++; fd < safe_fd; fd++) 58 close(fd); 59 60 /* Reset flags and clean up the fd table for fds to close */ 61 for (lock_fd = fd; lock_fd < _thread_dtablesize; lock_fd++) 62 if (_thread_fd_table[lock_fd] != NULL) 63 _close_flags(lock_fd); 64 65 /* Now let the system do its thing */ 66 ret = _thread_sys_closefrom(fd); 67 } 68 69 _thread_leave_cancellation_point(); 70 71 return ret; 72 73 } 74