/* Common format string for overflow reporting */ staticconstchar *
not_enough_output_msg = "Not enough space in output buffer for '%c'"; /* Common format string for bad value reporting */ staticconstchar *
bad_value_msg = "Type '%c' has unsupported value '%d'";
/**************************************************************************//**
* Add a bool to the output stream
*
* @param c Type letter which triggered the call
* @param trans libipm transport
* @param argptr Pointer to value in argument stack (promoted to int)
* @return != 0for error
*
* The boolean value must be a 0or a 1.
*/ staticenum libipm_status
append_bool_type(char c, struct trans *trans, va_list *argptr)
{ enum libipm_status rv = E_LI_SUCCESS; struct stream *s = trans->out_s; if (!s_check_rem_out(s, 1 + 1))
{
log_append_error(trans, not_enough_output_msg, c);
rv = E_LI_BUFFER_OVERFLOW;
} else
{ int tmp = va_arg(*argptr, int); if (tmp < 0 || tmp > 1)
{
log_append_error(trans, bad_value_msg, c, tmp);
rv = E_LI_BAD_VALUE;
} else
{
out_uint8(s, c);
out_uint8(s, tmp);
}
} return rv;
}
/**************************************************************************//**
* Add an octet to the output stream
*
* @param c Type letter which triggered the call
* @param trans libipm transport
* @param argptr Pointer to value in argument stack (promoted to int)
* @return != 0for error
*/ staticenum libipm_status
append_int8_type(char c, struct trans *trans, va_list *argptr)
{ enum libipm_status rv = E_LI_SUCCESS; struct stream *s = trans->out_s; if (!s_check_rem_out(s, 1 + 1))
{
log_append_error(trans, not_enough_output_msg, c);
rv = E_LI_BUFFER_OVERFLOW;
} else
{ int tmp = va_arg(*argptr, int); if (tmp < 0 || tmp > 255)
{
log_append_error(trans, bad_value_msg, c, tmp);
rv = E_LI_BAD_VALUE;
} else
{
out_uint8(s, c);
out_uint8(s, tmp);
}
} return rv;
}
/**************************************************************************//**
* Add an 16-bit integer to the output stream
*
* @param c Type letter which triggered the call
* @param trans libipm transport
* @param argptr Pointer to value in argument stack (promoted to int)
* @return != 0for error
*/ staticenum libipm_status
append_int16_type(char c, struct trans *trans, va_list *argptr)
{ enum libipm_status rv = E_LI_SUCCESS; struct stream *s = trans->out_s; if (!s_check_rem_out(s, 1 + 2))
{
log_append_error(trans, not_enough_output_msg, c);
rv = E_LI_BUFFER_OVERFLOW;
} else
{ int tmp = va_arg(*argptr, int); if ((c == 'n' && (tmp < -0x8000 || tmp > 0x7fff)) ||
(c == 'q' && (tmp < 0 || tmp > 0xffff)))
{
log_append_error(trans, bad_value_msg, c, tmp);
rv = E_LI_BAD_VALUE;
} else
{
out_uint8(s, c);
out_uint16_le(s, tmp);
}
} return rv;
}
/**************************************************************************//**
* Add a 32-bit integer to the output stream
*
* @param c Type letter which triggered the call
* @param trans libipm transport
* @param argptr Pointer to value in argument stack
* @return != 0for error
*/ staticenum libipm_status
append_int32_type(char c, struct trans *trans, va_list *argptr)
{ enum libipm_status rv = E_LI_SUCCESS; struct stream *s = trans->out_s; if (!s_check_rem_out(s, 1 + 4))
{
log_append_error(trans, not_enough_output_msg, c);
rv = E_LI_BUFFER_OVERFLOW;
} else
{ /* If int is bigger than 4 bytes, the argument will be *promotedto'int'ratherthan'int32_t'/'uint32_t', *andwewillneedtocheckthespecifiedvalueisinrange.
*/ #if SIZEOF_INT > 4 int tmp = va_arg(*argptr, int); if ((c == 'i' && (tmp < -0x80000000 || tmp > 0x7fffffff)) ||
(c == 'u' && (tmp < 0 || tmp > 0xffffffff)))
{
log_append_error(trans, bad_value_msg, c, tmp);
rv = E_LI_BAD_VALUE;
} else
{
out_uint8(s, c);
out_uint32_le(s, tmp);
} #else
uint32_t tmp = va_arg(*argptr, uint32_t);
out_uint8(s, c);
out_uint32_le(s, tmp); #endif
} return rv;
}
/**************************************************************************//**
* Add a 64-bit integer to the output stream
*
* @param c Type letter which triggered the call
* @param trans libipm transport
* @param argptr Pointer to value in argument stack
* @return != 0for error
*/ staticenum libipm_status
append_int64_type(char c, struct trans *trans, va_list *argptr)
{ enum libipm_status rv = E_LI_SUCCESS; struct stream *s = trans->out_s; if (!s_check_rem_out(s, 1 + 8))
{
log_append_error(trans, not_enough_output_msg, c);
rv = E_LI_BUFFER_OVERFLOW;
} else
{
uint64_t tmp = va_arg(*argptr, uint64_t);
out_uint8(s, c);
out_uint64_le(s, tmp);
} return rv;
}
/**************************************************************************//**
* Add a terminated string to the output stream
*
* @param c Type letter which triggered the call
* @param trans libipm transport
* @param argptr Pointer to value in argument stack (promoted to int)
* @return != 0for error
*
* NULL pointers are not allowed for the string.
*/ staticenum libipm_status
append_char_ptr_type(char c, struct trans *trans, va_list *argptr)
{ enum libipm_status rv = E_LI_SUCCESS; struct stream *s = trans->out_s; constchar *str = va_arg(*argptr, constchar *); if (str == NULL)
{
log_append_error(trans, "String cannot be NULL");
rv = E_LI_PROGRAM_ERROR;
} else
{ unsignedint len = g_strlen(str);
if ((len > (LIBIPM_MAX_MSG_SIZE - HEADER_SIZE - 1)) ||
(!s_check_rem_out(s, 1 + 1 + len)))
{
log_append_error(trans, "Not enough space in output buffer for " "'%c'[len=%u]", c, len);
rv = E_LI_BUFFER_OVERFLOW;
} else
{
out_uint8(s, c);
out_uint8p(s, str, len + 1);
}
} return rv;
}
/**************************************************************************//**
* Add a file descriptor to the output stream
*
* @param c Type letter which triggered the call
* @param trans libipm transport
* @param argptr Pointer to value in argument stack (promoted to int)
* @return != 0for error
*/ staticenum libipm_status
append_fd_type(char c, va_list *argptr, struct trans *trans)
{ enum libipm_status rv = E_LI_SUCCESS; struct stream *s = trans->out_s; struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data; int fd = va_arg(*argptr, int); if (fd < 0)
{
log_append_error(trans, "File descriptor cannot be < 0");
rv = E_LI_PROGRAM_ERROR;
} elseif (!s_check_rem_out(s, 1))
{
log_append_error(trans, "Not enough space in output buffer for '%c'", c);
rv = E_LI_BUFFER_OVERFLOW;
} elseif (priv->out_fd_count >= MAX_FD_PER_MSG)
{
log_append_error(trans, "Too many file descriptors for '%c'", c);
rv = E_LI_TOO_MANY_FDS;
} else
{
out_uint8(s, c);
priv->out_fds[priv->out_fd_count++] = fd;
}
return rv;
}
/**************************************************************************//**
* Append a fixed size block to the output stream
*
* @param c Type letter which triggered the call
* @param trans libipm transport
* @param argptr argptr to pointer to block descriptor
* @return != 0for error
*/ staticenum libipm_status
append_fsb_type(char c, struct trans *trans, va_list *argptr)
{ enum libipm_status rv = E_LI_SUCCESS; struct stream *s = trans->out_s; conststruct libipm_fsb *fsb = va_arg(*argptr, conststruct libipm_fsb *); if (fsb == NULL || fsb->data == NULL)
{
log_append_error(trans, "Malformed descriptor for '%c'", c);
rv = E_LI_PROGRAM_ERROR;
} else
{ unsignedint len = fsb->datalen;
/**************************************************************************//**
* Local function to append data to the output stream
*
* @param trans libipm transport
* @param format type-system compatible string
* @param argptr Variables containing data to append
* @pre - trans->priv has been checked to be non-NULL
* @return != 0for error
*/ staticenum libipm_status
libipm_msg_out_appendv(struct trans *trans, constchar *format, va_list *argptr)
{ enum libipm_status rv = E_LI_SUCCESS; struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data; constchar *cp;
if (format != NULL)
{ for (cp = format; rv == 0 && *cp != '\0' ; ++cp)
{ char c = *cp;
++priv->out_param_count; /* Count the parameter */ if (g_strchr(libipm_valid_type_chars, c) == NULL)
{
log_append_error(trans, "Type code '%c' is not supported", c);
rv = E_LI_UNSUPPORTED_TYPE; break;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.