// Copyright (c) 2007, Monju System Architects
//
// Released under the Monju-Public copyright license:
//
// Permission is hereby granted, free of charge, to any person or entity
// obtaining a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies and modifications
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of published, sold, or
// ownership-transferred versions of the Software. The notices are not
// required for binary-only releases or binary-only derivatives of the
// Software, or documentation provided with binary-only releases and
// binary-only derivatives.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// NOTE: YOU MUST run the following or your exe will exit when the other
// side of a socket is closed and you are still reading from or writing
// to it:
//
// signal(SIGPIPE, SIG_IGN); // ignore SIGPIPE.
//
// Another option is to use MSG_NOSIGNAL or SO_NOSIGPIPE, but these are
// system dependant and outside the scope of this code.
// NOTE: Unix only.
// INCLUDES.
#include <errno.h>
#ifdef _WIN32
#include <Windows.h>
#else
#include <fcntl.h>
#include <unistd.h>
#endif
#include "public/file.h"
// isNonBlockingFile()
bool isNonBlockingFile(FILE_TYPE theFile) {
#ifdef _WIN32
return true;
#else
return O_NONBLOCK & fcntl(theFile, F_GETFL, 0);
#endif
}
// readNonBlockingFile()
//
// This assumes setNonBlocking() was already called on the passed in file descriptor.
void readNonBlockingFile(FILE_TYPE file, char* pBuffer, int* pInOutAmount) {
#ifdef _WIN32
throw("TODO: implement readNonBlocking() for windows.");
#else
// DO THE READ.
ssize_t amount = read(fileHandle, pBuffer, *pInOutAmount);
// HANDLE SUCCESSFUL READ.
if (amount >= 0) {
*pInOutAmount = amount;
return;
}
// HANDLE WOULD BLOCK AND TRY AGAIN.
if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
*pInOutAmount = 0;
return;
}
// HANDLE FAILURE.
throw("readNonBlocking(): read() failed.");
#endif
}
// setBlockingFile()
void setBlockingFile(FILE_TYPE fileHandle) {
#ifdef _WIN32
fileHandle.m_isBlocking = true;
#else
int flags;
#if defined(O_NONBLOCK)
if (-1 == (flags = fcntl(fileHandle, F_GETFL, 0))) {
flags = 0;
}
if(0 != fcntl(fileHandle, F_SETFL, flags & ~O_NONBLOCK)) {
throw("fcntl() failed.");
}
#else
flags = 0;
if (0 != ioctl(fileHandle, FIOBIO, &flags)) {
throw("ioctl() failed.");
}
#endif
#endif
}
// setNonBlockingFile()
void setNonBlockingFile(FILE_TYPE fileHandle) {
#ifdef _WIN32
fileHandle.m_isBlocking = false;
#else
int flags;
#if defined(O_NONBLOCK)
if (-1 == (flags = fcntl(fileHandle, F_GETFL, 0))) {
flags = 0;
}
if(0 != fcntl(fileHandle, F_SETFL, flags | O_NONBLOCK)) {
throw("fcntl() failed.");
}
#else
flags = 1;
if (0 != ioctl(fileHandle, FIOBIO, &flags)) {
throw("ioctl() failed.");
}
#endif
#endif
}
// writeNonBlockingFile()
//
// This assumes setNonBlocking() was already called on the passed in file descriptor.
void writeNonBlockingFile(FILE_TYPE fileHandle, const char* pBuffer, int* pInOutAmount) {
#ifdef _WIN32
throw("TODO: implement writeNonBlocking() for windows.");
#else
// DO THE READ.
ssize_t amount = write(fileHandle, pBuffer, *pInOutAmount);
// HANDLE SUCCESSFUL READ.
if (amount >= 0) {
*pInOutAmount = amount;
return;
}
// HANDLE WOULD BLOCK AND TRY AGAIN.
if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
*pInOutAmount = 0;
return;
}
// HANDLE FAILURE.
throw("writeNonBlocking(): write() failed.");
#endif
}
|