/*
* Copyright (c) Likewise Software. All rights Reserved.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the license, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details. You should have received a copy
* of the GNU Lesser General Public License along with this program. If
* not, see .
*
* LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING
* TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT
* WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE
* TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU
* LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU
* HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING
* TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT
* license@likewisesoftware.com
*/
/*
* Module Name:
*
* util-private.h
*
* Abstract:
*
* Utility functions (private header)
*
* Authors: Brian Koropoff (bkoropoff@likewisesoftware.com)
*
*/
#ifndef __LWMSG_UTIL_PRIVATE_H__
#define __LWMSG_UTIL_PRIVATE_H__
#include "status-private.h"
#include "context-private.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LWMSG_ASSERT_SUCCESS(_x_) \
do \
{ \
LWMsgStatus __status__ = (_x_); \
if (__status__) \
{ \
fprintf(stderr, \
"%s:%i: Assertion failed with status %i: %s\n", \
__FILE__, __LINE__, __status__, #_x_); \
abort(); \
} \
} while (0)
#define LWMSG_ASSERT(_x_) \
do \
{ \
if (!(_x_)) \
{ \
fprintf(stderr, \
"%s:%i: Assertion failed: %s\n", \
__FILE__, __LINE__, #_x_); \
abort(); \
} \
} while (0)
#define BAIL_ON_ERROR(_x_) \
do \
{ \
if ((_x_)) \
{ \
goto error; \
} \
} while (0)
#define RAISE_ERROR(_context_, _status_, ...) \
do \
{ \
(void) lwmsg_error_raise( \
&(_context_)->error, \
(_status_), \
__VA_ARGS__); \
goto error; \
} while (0)
#define PROPAGATE_ERROR(_from_, _to_, _status_) \
do { \
if (lwmsg_error_propagate( \
&(_from_)->error, \
&(_to_)->error, \
(_status_))) \
{ \
goto error; \
} \
} while (0)
#define LWMSG_ALLOC_ARRAY(_count_, _obj_) \
((*(_obj_) = calloc((_count_), sizeof **(_obj_))) ? LWMSG_STATUS_SUCCESS : LWMSG_STATUS_MEMORY)
#define LWMSG_ALLOC(_obj_) (LWMSG_ALLOC_ARRAY(1, _obj_))
#define LWMSG_POINTER_AS_ULONG(ptr) ((unsigned long) (size_t) (ptr))
char* lwmsg_formatv(const char* fmt, va_list ap);
char* lwmsg_format(const char* fmt, ...);
static inline LWMsgStatus
lwmsg_buffer_read(
LWMsgBuffer* buffer,
void* out,
size_t count
)
{
LWMsgStatus status = LWMSG_STATUS_SUCCESS;
unsigned char* out_bytes = (unsigned char*) out;
while (count)
{
if (buffer->cursor + count > buffer->end)
{
/* Not enough bytes remain in buffer, so copy what we have and ask for more */
size_t remaining = buffer->end - buffer->cursor;
memcpy(out_bytes, buffer->cursor, remaining);
count -= remaining;
buffer->cursor += remaining;
out_bytes += remaining;
if (buffer->wrap)
{
BAIL_ON_ERROR(status = buffer->wrap(buffer, count));
}
else
{
BAIL_ON_ERROR(status = LWMSG_STATUS_EOF);
}
}
else
{
memcpy(out_bytes, buffer->cursor, count);
buffer->cursor += count;
break;
}
}
error:
return status;
}
static inline LWMsgStatus
lwmsg_buffer_write(LWMsgBuffer* buffer, unsigned char* in_bytes, size_t count)
{
LWMsgStatus status = LWMSG_STATUS_SUCCESS;
size_t remaining;
size_t writable;
while (count)
{
remaining = buffer->end - buffer->cursor;
if (count > remaining)
writable = remaining;
else
writable = count;
memcpy(buffer->cursor, in_bytes, writable);
in_bytes += writable;
count -= writable;
buffer->cursor += writable;
if (count)
{
if (buffer->wrap)
{
BAIL_ON_ERROR(status = buffer->wrap(buffer, count));
}
else
{
BAIL_ON_ERROR(status = LWMSG_STATUS_EOF);
}
}
}
error:
return status;
}
ssize_t
lwmsg_convert_string_alloc(
void* input,
size_t input_len,
void** output,
const char* input_type,
const char* output_type
);
ssize_t
lwmsg_convert_string_buffer(
void* input,
size_t input_len,
void* output,
size_t output_len,
const char* input_type,
const char* output_type
);
LWMsgStatus
lwmsg_add_unsigned(
size_t operand_a,
size_t operand_b,
size_t* result
);
LWMsgStatus
lwmsg_multiply_unsigned(
size_t operand_a,
size_t operand_b,
size_t* result
);
typedef struct LWMsgRing
{
struct LWMsgRing* prev;
struct LWMsgRing* next;
} LWMsgRing;
static inline
void
lwmsg_ring_init(
LWMsgRing* ring
)
{
ring->prev = ring->next = ring;
}
static inline
void
lwmsg_ring_sanity(
LWMsgRing* ring
)
{
LWMSG_ASSERT(ring->prev->next == ring && ring->next->prev == ring);
}
static inline
void
lwmsg_ring_insert_after(
LWMsgRing* anchor,
LWMsgRing* element
)
{
lwmsg_ring_sanity(anchor);
lwmsg_ring_sanity(element);
LWMSG_ASSERT(element->prev == element->next && element->prev == element);
element->next = anchor->next;
element->prev = anchor;
anchor->next->prev = element;
anchor->next = element;
}
static inline
void
lwmsg_ring_insert_before(
LWMsgRing* anchor,
LWMsgRing* element
)
{
lwmsg_ring_sanity(anchor);
lwmsg_ring_sanity(element);
LWMSG_ASSERT(element->prev == element->next && element->prev == element);
element->next = anchor;
element->prev = anchor->prev;
anchor->prev->next = element;
anchor->prev = element;
}
static inline
void
lwmsg_ring_remove(
LWMsgRing* element
)
{
lwmsg_ring_sanity(element);
element->prev->next = element->next;
element->next->prev = element->prev;
lwmsg_ring_init(element);
}
static inline
void
lwmsg_ring_enqueue(
LWMsgRing* anchor,
LWMsgRing* element
)
{
lwmsg_ring_insert_before(anchor, element);
}
static inline
void
lwmsg_ring_dequeue(
LWMsgRing* anchor,
LWMsgRing** element
)
{
*element = anchor->next;
lwmsg_ring_remove(*element);
}
static inline
void
lwmsg_ring_move(
LWMsgRing* from,
LWMsgRing* to
)
{
LWMsgRing* from_first = from->next;
LWMsgRing* from_last = from->prev;
LWMsgRing* to_last = to->prev;
lwmsg_ring_sanity(from);
lwmsg_ring_sanity(to);
if (from->next != from)
{
/* Link from to_last and from_first */
to_last->next = from_first;
from_first->prev = to_last;
/* Link from_last into to */
from_last->next = to;
to->prev = from_last;
from->next = from->prev = from;
}
}
static inline
size_t
lwmsg_ring_count(
LWMsgRing* ring
)
{
LWMsgRing* iter = NULL;
size_t count = 0;
lwmsg_ring_sanity(ring);
for (iter = ring->next; iter != ring; iter = iter->next, count++);
return count;
}
static inline
LWMsgBool
lwmsg_ring_is_empty(
LWMsgRing* ring
)
{
lwmsg_ring_sanity(ring);
return ring->next == ring;
}
LWMsgStatus
lwmsg_strerror(
int err,
char** message
);
LWMsgStatus
lwmsg_set_close_on_exec(
int fd
);
#define LWMSG_OBJECT_FROM_MEMBER(_ptr_, _type_, _field_) \
((_type_ *) ((unsigned char*) (_ptr_) - offsetof(_type_, _field_)))
#define _LWMSG_SWAP16(val) \
((((uint16_t)(val) & 0xFF00) >> 8) | \
(((uint16_t)(val) & 0x00FF) << 8))
#define _LWMSG_SWAP32(val) \
((((uint32_t)(val) & 0xFF000000L) >> 24) | \
(((uint32_t)(val) & 0x00FF0000L) >> 8) | \
(((uint32_t)(val) & 0x0000FF00L) << 8) | \
(((uint32_t)(val) & 0x000000FFL) << 24))
#define _LWMSG_SWAP64(val) \
(((uint64_t)(_SMB_ENDIAN_SWAP32(((uint64_t)(val) & 0xFFFFFFFF00000000LL) >> 32))) | \
(((uint64_t)_SMB_ENDIAN_SWAP32(((uint64_t)(val) & 0x00000000FFFFFFFFLL))) << 32))
#define LWMSG_SWAP16(val, src_order, dst_order) \
((src_order) == (dst_order) ? \
(val) : \
_LWMSG_SWAP16((val)))
#define LWMSG_SWAP32(val, src_order, dst_order) \
((src_order) == (dst_order) ? \
(val) : \
_LWMSG_SWAP32((val)))
#define LWMSG_SWAP64(val, src_order, dst_order) \
((src_order) == (dst_order) ? \
(val) : \
_LWMSG_SWAP64((val)))
#define LWMSG_LOCK(b, l) \
do \
{ \
if (!(b)) \
{ \
pthread_mutex_lock((l)); \
(b) = LWMSG_TRUE; \
} \
} while(0)
#define LWMSG_UNLOCK(b, l) \
do \
{ \
if ((b)) \
{ \
pthread_mutex_unlock((l)); \
(b) = LWMSG_FALSE; \
} \
} while(0)
static inline
const char*
lwmsg_string_without_prefix(
const char* str,
const char* prefix
)
{
if (!strncmp(str, prefix, strlen(prefix)))
{
return str + strlen(prefix);
}
else
{
return str;
}
}
ssize_t
lwmsg_recvmsg_timeout(
int sock,
struct msghdr* msg,
int flags,
LWMsgTime* time
);
ssize_t
lwmsg_sendmsg_timeout(
int sock,
const struct msghdr* msg,
int flags,
LWMsgTime* time
);
#endif