/* * Copyright (c) 2000-2002, 2004, 2005 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * 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: fflush.c,v 1.19 2006/07/14 14:42:25 ca Exp $") #include "sm/error.h" #include "sm/time.h" #include "sm/fcntl.h" #include "sm/string.h" #include "sm/io.h" #include "sm/assert.h" #include "io-int.h" /* ** SM_IO_FLUSH -- flush the buffer for a 'fp' to the "file" ** ** Flush a single file. We don't allow this function to flush ** all open files when fp==NULL any longer. ** ** Parameters: ** fp -- the file pointer buffer to flush ** ** Results: ** usual sm_error code */ sm_ret_T sm_io_flush(sm_file_T *fp) { SM_IS_FP(fp); if ((f_flags(*fp) & (SMWR | SMRW)) == 0) { /* ** The file is not opened for writing, so it cannot be flushed ** (writable means SMWR [write] or SMRW [read/write]. */ return sm_error_perm(SM_EM_IO, EBADF); } /* Now do the flush */ return sm_flush(fp); } /* ** SM_FLUSH -- perform the actual flush ** ** Assumes that 'fp' has been validated before this function called. ** ** Parameters: ** fp -- file pointer to be flushed ** ** Results: ** usual sm_error code */ sm_ret_T sm_flush(sm_file_T *fp) { uchar *p; ssize_t t; int n; sm_f_flags_T fl; sm_ret_T res; SM_IS_FP(fp); fl = f_flags(*fp); if ((fl & SMWR) == 0) return SM_SUCCESS; if (fl & (SMSTR|SMSTRSTR)) { *f_p(*fp) = '\0'; return SM_SUCCESS; } p = f_bfbase(*fp); if (p == NULL) return SM_SUCCESS; n = f_p(*fp) - p; /* write this much */ /* ** Set these immediately to avoid problems with longjmp and to allow ** exchange buffering (via setvbuf) in user write function. */ f_p(*fp) = p; f_w(*fp) = fl & SMNBF ? 0 : f_bfsize(*fp); for (; n > 0; n -= t, p += t) { res = (*f_write(*fp))(fp, p, n, &t); if (sm_is_err(res)) { /* ** Notice: f_p/f_w are not correct now! ** Hence this I/O error is not correctible. ** Should we try to fix f_p/f_w? That would require ** shifting the buffer content since we may have ** written a part. */ f_flags(*fp) |= SMERR; #if SM_IO_ERR_VAL f_error(*fp) = res; #endif return res; } } return SM_SUCCESS; }