/*
* Copyright (c) 2002, 2004, 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: fpad.c,v 1.5 2005/03/15 19:56:07 ca Exp $")
#include "sm/error.h"
#include "sm/time.h"
#include "sm/fcntl.h"
#include "sm/io.h"
#include "sm/setjmp.h"
#include "io-int.h"
#include "fvwrite.h"
/*
** SM_IO_FPAD -- fill up file (buffer)
**
** This routine can be used to move the file write pointer for
** fixed size records.
**
** Parameters:
** fp -- the file pointer to write to
** len -- number of bytes for padding, must be less or equal
** remaining space in buffer
**
** Returns:
** usual sm_error code
*/
sm_ret_T
sm_io_fpad(sm_file_T *fp, size_t len)
{
int w;
sm_ret_T ret;
/* make sure we can write */
if (cantwrite(fp))
return sm_error_perm(SM_EM_IO, EBADF);
if (len == 0)
return SM_SUCCESS;
if (f_flags(*fp) & SMNBF)
return sm_error_perm(SM_EM_IO, EINVAL);
/* not enough space? */
if ((size_t) f_w(*fp) < len)
return sm_error_perm(SM_EM_IO, EINVAL);
/* this isn't really useful, but keep it for now */
if ((f_flags(*fp) & (SMALC | SMSTR)) == (SMALC | SMSTR))
{
size_t blen;
int tsize;
uchar *tbase;
/* Allocate space exponentially. */
tsize = f_bfsize(*fp);
blen = f_p(*fp) - f_bfbase(*fp);
do
{
tsize = (tsize << 1) + 1;
} while ((size_t) tsize < blen + len);
tbase = (uchar *) sm_realloc(f_bfbase(*fp),
tsize + 1);
if (tbase == NULL)
{
ret = sm_error_temp(SM_EM_IO, ENOMEM);
goto err;
}
f_w(*fp) += tsize - f_bfsize(*fp);
f_bfbase(*fp) = tbase;
f_bfsize(*fp) = tsize;
f_p(*fp) = tbase + blen;
}
w = f_w(*fp);
if (f_flags(*fp) & SMSTR)
{
if (len < (size_t) w)
w = len;
if (w > 0)
{
sm_memzero((void *)f_p(*fp), (size_t)(w));
f_w(*fp) -= w;
f_p(*fp) += w;
}
w = len; /* but pretend copied all */
}
#ifdef SMSTRSTR
/* str? */
else if (f_flags(*fp) & SMSTRSTR)
{
if (len < (size_t) w)
w = len;
if (w > 0)
{
/*
ret = sm_str_spadn(f_cookie(*fp),
(char *) p, w);
*/
ret = sm_error_perm(SM_EM_IO, EINVAL);
if (sm_is_err(ret))
goto err;
f_w(*fp) -= w;
f_p(*fp) += w;
}
w = len; /* but pretend copied all */
}
#endif /* SMSTRSTR */
else
{
/* fill and done */
w = len;
sm_memzero((void *)f_p(*fp), (size_t)(w));
f_w(*fp) -= w;
f_p(*fp) += w;
}
return SM_SUCCESS;
err:
/* ret set before goto places us here */
f_flags(*fp) |= SMERR;
#if SM_IO_ERR_VAL
f_error(*fp) = res;
#endif
return ret;
}
syntax highlighted by Code2HTML, v. 0.9.1