/*
* Copyright (c) 2003, 2005 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*/
#include "sm/generic.h"
SM_RCSID("@(#)$Id: rcbgetaint.c,v 1.2 2007/01/31 05:25:16 ca Exp $")
#include "sm/assert.h"
#include "sm/magic.h"
#include "sm/error.h"
#include "sm/memops.h"
#include "sm/rpool.h"
#include "sm/limits.h"
#include "sm/rcb.h"
#include "sm/reccom.h"
#if MTA_USE_RCBV_INTN
/*
** SM_RCB_GETAUINT32 -- Read n ints from the current position in a sm_rcb_P.
** In contrast to other sm_rcb_getXuint32 functions, this one
** "knows" about the structure of entries:
** length, rt, value, value, ...
**
** Parameters:
** rcb -- sm_rcb_P object to read int from.
** nmax -- maximum number of entries to read (#entries in pv)
** pn -- (pointer to) number of values (output)
** if NULL then nmax is the number of entries to read
** prt -- (pointer to) record type (output)
** pv -- (pointer to) array of values (output)
**
** Returns:
** usual sm_error code; SM_E_OVFLW_NS
**
** Last code review:
** Last code change:
*/
sm_ret_T
sm_rcb_getauint32(sm_rcb_P rcb, uint nmax, uint *pn, uint32_t *prt, uint32_t *pv)
{
uint u, n;
uint32_t v;
SM_IS_RCB(rcb);
# if SM_RCB_CHECK
SM_REQUIRE(rcb->sm_rcb_state == SM_RCB_DEC);
# endif
SM_REQUIRE(nmax > 0);
SM_REQUIRE(pv != NULL);
if (pn != NULL) {
SM_REQUIRE(prt != NULL);
/* at least 2 entries: number of bytes and rt */
if (rcb->sm_rcb_len < rcb->sm_rcb_rw + sizeof(uint32_t) * 2)
return sm_error_perm(SM_EM_RECCOM, SM_E_OVFLW_NS);
/* number of bytes */
sm_buf2uint32(rcb->sm_rcb_base + rcb->sm_rcb_rw, &v);
rcb->sm_rcb_rw += sizeof(uint32_t);
if (v >= UINT_MAX)
return sm_error_perm(SM_EM_RECCOM, SM_E_OVFLW_NS);
if (v % sizeof(uint32_t) != 0)
return sm_error_perm(SM_EM_RECCOM, EINVAL);
*pn = n = (uint) v / sizeof(uint32_t);
if (n >= nmax)
return sm_error_perm(SM_EM_RECCOM, SM_E_OVFLW_NS);
if (rcb->sm_rcb_len < rcb->sm_rcb_rw + v)
return sm_error_perm(SM_EM_RECCOM, SM_E_OVFLW_NS);
/* record type */
sm_buf2uint32(rcb->sm_rcb_base + rcb->sm_rcb_rw, &v);
rcb->sm_rcb_rw += sizeof(uint32_t);
*prt = v;
}
else {
n = nmax;
}
/* are there n entries? */
if (rcb->sm_rcb_len < rcb->sm_rcb_rw + sizeof(uint32_t) * n)
return sm_error_perm(SM_EM_RECCOM, SM_E_OVFLW_NS);
for (u = 0; u < n; u++) {
sm_buf2uint32(rcb->sm_rcb_base + rcb->sm_rcb_rw, &v);
rcb->sm_rcb_rw += sizeof(uint32_t);
*pv++ = v;
}
return SM_SUCCESS;
}
#endif /* MTA_USE_RCBV_INTN */
syntax highlighted by Code2HTML, v. 0.9.1