/* * 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 */