1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
/*
* Set or clear file descriptor flags.
*
* Simple functions (wrappers around fcntl) to set or clear file descriptor
* flags like close-on-exec or nonblocking I/O.
*
* The canonical version of this file is maintained in the rra-c-util package,
* which can be found at <https://www.eyrie.org/~eagle/software/rra-c-util/>.
*
* Written by Russ Allbery <eagle@eyrie.org>
* Copyright 2008, 2011, 2013
* The Board of Trustees of the Leland Stanford Junior University
* Copyright 2004-2006 Internet Systems Consortium, Inc. ("ISC")
* Copyright 1991, 1994-2003 The Internet Software Consortium and Rich Salz
*
* This code is derived from software contributed to the Internet Software
* Consortium by Rich Salz.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* SPDX-License-Identifier: ISC
*/
#include <config.h>
#include <portable/system.h>
#ifdef _WIN32
# include <winsock2.h>
#else
# include <fcntl.h>
# ifndef O_NONBLOCK
# include <sys/ioctl.h>
# if HAVE_SYS_FILIO_H
# include <sys/filio.h>
# endif
# endif
#endif
#include <util/fdflag.h>
#include <util/macros.h>
/*
* Set a file to close-on-exec (or clear that setting if the flag is false),
* returning true on success and false on failure.
*
* One is supposed to retrieve the flags, add FD_CLOEXEC, and then set them,
* although I've never seen a system with any flags other than close-on-exec.
* Do it right anyway; it's not that expensive.
*
* Stub this out on Windows, where it's not supported (at least currently by
* this utility library). Do not use socket_type for the first parameter,
* since it's meaningful to set file descriptors for regular files to
* close-on-exec (even though this is currently irrelevant since the function
* isn't supported on Windows).
*/
#ifdef _WIN32
bool
fdflag_close_exec(int fd UNUSED, bool flag UNUSED)
{
return false;
}
#else
bool
fdflag_close_exec(int fd, bool flag)
{
int oflag, mode;
oflag = fcntl(fd, F_GETFD, 0);
if (oflag < 0)
return false;
mode = flag ? (oflag | FD_CLOEXEC) : (oflag & ~FD_CLOEXEC);
return (fcntl(fd, F_SETFD, mode) == 0);
}
#endif
/*
* Set a file descriptor to nonblocking (or clear the nonblocking flag if flag
* is false), returning true on success and false on failure.
*
* For Windows, be aware that this will only work for sockets. For UNIX, you
* can pass a non-socket in and it will do the right thing, since UNIX doesn't
* distinguish, but Windows will not allow that. Thankfully, there's rarely
* any need to set non-sockets non-blocking.
*
* For UNIX, always use O_NONBLOCK; O_NDELAY is not the same thing
* historically. The semantics of O_NDELAY are that if the read would block,
* it returns 0 instead. This is indistinguishable from an end of file
* condition. POSIX added O_NONBLOCK, which requires read to return -1 and
* set errno to EAGAIN, which is what we want.
*
* FNDELAY (4.3BSD) originally did the correct thing, although it has a
* different incompatibility (affecting all users of a socket rather than just
* a file descriptor and returning EWOULDBLOCK instead of EAGAIN) that we
* probably don't care about. Using it is probably safe, but BSD should also
* have the ioctl, and at least on Solaris FNDELAY does the same thing as
* O_NDELAY, not O_NONBLOCK. So if we don't have O_NONBLOCK, fall back to the
* ioctl instead.
*
* Reference: Stevens, Advanced Unix Programming, pg. 364.
*
* Note that O_NONBLOCK is known not to work on earlier versions of ULTRIX,
* SunOS, and AIX, possibly not setting the socket nonblocking at all, despite
* the fact that they do define it. It works in later SunOS and, current AIX,
* however, and a 1999-10-25 survey of current operating systems failed to
* turn up any that didn't handle it correctly (as required by POSIX), while
* HP-UX 11.00 did use the broken return-zero semantics of O_NDELAY (most
* other operating systems surveyed treated O_NDELAY as synonymous with
* O_NONBLOCK). Accordingly, we currently unconditionally use O_NONBLOCK. If
* this causes too many problems, an autoconf test may be required.
*/
#if defined(_WIN32)
bool
fdflag_nonblocking(socket_type fd, bool flag)
{
u_long mode;
mode = flag ? 1 : 0;
return (ioctlsocket(fd, FIONBIO, &mode) == 0);
}
#elif defined(O_NONBLOCK)
bool
fdflag_nonblocking(socket_type fd, bool flag)
{
int mode;
mode = fcntl(fd, F_GETFL, 0);
if (mode < 0)
return false;
mode = (flag ? (mode | O_NONBLOCK) : (mode & ~O_NONBLOCK));
return (fcntl(fd, F_SETFL, mode) == 0);
}
#else /* !O_NONBLOCK */
bool
fdflag_nonblocking(socket_type fd, bool flag)
{
int state;
state = flag ? 1 : 0;
return (ioctl(fd, FIONBIO, &state) == 0);
}
#endif /* !O_NONBLOCK */
|