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