#include <Kerberos/KerberosDebug.h>
#include "UNIXReadWrite.h"
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
static int __UNIXReadWriteError (int err, const char *function, const char *file, int line);
#define URWError_(err) __UNIXReadWriteError(err, __FUNCTION__, __FILE__, __LINE__)
static int __UNIXReadWriteError (int err, const char *function, const char *file, int line)
{
if (err && (ddebuglevel () > 0)) {
dprintf ("%s() error %d ('%s') at %s: %d", function, err, strerror (err), file, line);
}
return err;
}
int ReadBuffer (int inDescriptor, size_t inBufferLength, char *ioBuffer)
{
int err = 0;
size_t bytesRead = 0;
if (ioBuffer == NULL) { err = EINVAL; }
if (!err) {
char *ptr = ioBuffer;
do {
ssize_t count = read (inDescriptor, ptr, inBufferLength - bytesRead);
if (count < 0) {
if (errno != EINTR) { err = errno; }
} else if (count == 0) {
err = ECONNRESET; } else {
ptr += count;
bytesRead += count;
}
} while (!err && (bytesRead < inBufferLength));
}
return URWError_ (err);
}
int WriteBuffer (int inDescriptor, const char *inBuffer, size_t inBufferLength)
{
int err = 0;
size_t bytesWritten = 0;
if (inBuffer == NULL) { err = EINVAL; }
if (!err) {
const char *ptr = inBuffer;
do {
ssize_t count = write (inDescriptor, ptr, inBufferLength - bytesWritten);
if (count < 0) {
if (errno != EINTR) { err = errno; }
} else {
ptr += count;
bytesWritten += count;
}
} while (!err && (bytesWritten < inBufferLength));
}
return URWError_ (err);
}
int ReadDynamicLengthBuffer (int inDescriptor, char **outData, size_t *outLength)
{
int err = 0;
char *data = NULL;
u_int32_t length = 0;
if (outData == NULL) { err = EINVAL; }
if (outLength == NULL) { err = EINVAL; }
if (!err) {
err = ReadBuffer (inDescriptor, 4, (char *) &length);
}
if (!err) {
length = ntohl (length);
}
if (!err) {
data = malloc (length);
if (data == NULL) { err = ENOMEM; }
}
if (!err) {
memset (data, 0, length);
err = ReadBuffer (inDescriptor, length, data);
}
if (!err) {
*outLength = length;
*outData = data;
data = NULL; }
if (data != NULL) { free (data); }
return URWError_ (err);
}
int WriteDynamicLengthBuffer (int inDescriptor, const char *inData, size_t inLength)
{
int err = 0;
u_int32_t length = htonl (inLength);
if (inData == NULL) { err = EINVAL; }
if (!err) {
err = WriteBuffer (inDescriptor, (char *) &length, 4);
}
if (!err) {
err = WriteBuffer (inDescriptor, inData, inLength);
}
return URWError_ (err);
}