190792Sgshapiro/* 2261194Sgshapiro * Copyright (c) 2000-2001, 2005, 2006 Proofpoint, Inc. and its suppliers. 390792Sgshapiro * All rights reserved. 490792Sgshapiro * Copyright (c) 1990, 1993 590792Sgshapiro * The Regents of the University of California. All rights reserved. 690792Sgshapiro * 790792Sgshapiro * This code is derived from software contributed to Berkeley by 890792Sgshapiro * Chris Torek. 990792Sgshapiro * 1090792Sgshapiro * By using this file, you agree to the terms and conditions set 1190792Sgshapiro * forth in the LICENSE file which can be found at the top level of 1290792Sgshapiro * the sendmail distribution. 1390792Sgshapiro */ 1490792Sgshapiro 1590792Sgshapiro#include <sm/gen.h> 16266527SgshapiroSM_RCSID("@(#)$Id: fflush.c,v 1.46 2013-11-22 20:51:42 ca Exp $") 1790792Sgshapiro#include <unistd.h> 1890792Sgshapiro#include <errno.h> 19157001Sgshapiro#include <sm/time.h> 2090792Sgshapiro#include <signal.h> 2190792Sgshapiro#include <fcntl.h> 2290792Sgshapiro#include <string.h> 2390792Sgshapiro#include <sm/io.h> 2490792Sgshapiro#include <sm/assert.h> 2590792Sgshapiro#include <sm/setjmp.h> 2690792Sgshapiro#include "local.h" 2790792Sgshapiro#include <sm/conf.h> 2890792Sgshapiro 2990792Sgshapiro/* 3090792Sgshapiro** SM_IO_FLUSH -- flush the buffer for a 'fp' to the "file" 3190792Sgshapiro** 3290792Sgshapiro** Flush a single file. We don't allow this function to flush 3390792Sgshapiro** all open files when fp==NULL any longer. 3490792Sgshapiro** 3590792Sgshapiro** Parameters: 3690792Sgshapiro** fp -- the file pointer buffer to flush 3790792Sgshapiro** timeout -- time to complete the flush 3890792Sgshapiro** 3990792Sgshapiro** Results: 4090792Sgshapiro** Failure: SM_IO_EOF and sets errno 4190792Sgshapiro** Success: 0 (zero) 4290792Sgshapiro*/ 4390792Sgshapiro 4490792Sgshapiroint 4590792Sgshapirosm_io_flush(fp, timeout) 4690792Sgshapiro register SM_FILE_T *fp; 4790792Sgshapiro int SM_NONVOLATILE timeout; 4890792Sgshapiro{ 4990792Sgshapiro int fd; 5090792Sgshapiro struct timeval to; 5190792Sgshapiro 5290792Sgshapiro SM_REQUIRE_ISA(fp, SmFileMagic); 5390792Sgshapiro 5490792Sgshapiro if ((fp->f_flags & (SMWR | SMRW)) == 0) 5590792Sgshapiro { 5690792Sgshapiro /* 5790792Sgshapiro ** The file is not opened for writing, so it cannot be flushed 5890792Sgshapiro ** (writable means SMWR [write] or SMRW [read/write]. 5990792Sgshapiro */ 6090792Sgshapiro 6190792Sgshapiro errno = EBADF; 6290792Sgshapiro return SM_IO_EOF; 6390792Sgshapiro } 6490792Sgshapiro 6590792Sgshapiro SM_CONVERT_TIME(fp, fd, timeout, &to); 6690792Sgshapiro 6790792Sgshapiro /* Now do the flush */ 6890792Sgshapiro return sm_flush(fp, (int *) &timeout); 6990792Sgshapiro} 7090792Sgshapiro 7190792Sgshapiro/* 7290792Sgshapiro** SM_FLUSH -- perform the actual flush 7390792Sgshapiro** 7490792Sgshapiro** Assumes that 'fp' has been validated before this function called. 7590792Sgshapiro** 7690792Sgshapiro** Parameters: 7790792Sgshapiro** fp -- file pointer to be flushed 7890792Sgshapiro** timeout -- max time allowed for flush (milliseconds) 7990792Sgshapiro** 8090792Sgshapiro** Results: 8190792Sgshapiro** Success: 0 (zero) 8290792Sgshapiro** Failure: SM_IO_EOF and errno set 8390792Sgshapiro** 8490792Sgshapiro** Side Effects: 8590792Sgshapiro** timeout will get updated with the time remaining (if any) 8690792Sgshapiro*/ 8790792Sgshapiro 8890792Sgshapiroint 8990792Sgshapirosm_flush(fp, timeout) 9090792Sgshapiro register SM_FILE_T *fp; 9190792Sgshapiro int *timeout; 9290792Sgshapiro{ 9390792Sgshapiro register unsigned char *p; 9490792Sgshapiro register int n, t; 9590792Sgshapiro int fd; 9690792Sgshapiro 9790792Sgshapiro SM_REQUIRE_ISA(fp, SmFileMagic); 9890792Sgshapiro 9990792Sgshapiro t = fp->f_flags; 10090792Sgshapiro if ((t & SMWR) == 0) 10190792Sgshapiro return 0; 10290792Sgshapiro 10390792Sgshapiro if (t & SMSTR) 10490792Sgshapiro { 10590792Sgshapiro *fp->f_p = '\0'; 10690792Sgshapiro return 0; 10790792Sgshapiro } 10890792Sgshapiro 10990792Sgshapiro if ((p = fp->f_bf.smb_base) == NULL) 11090792Sgshapiro return 0; 11190792Sgshapiro 11290792Sgshapiro n = fp->f_p - p; /* write this much */ 11390792Sgshapiro 11490792Sgshapiro if ((fd = sm_io_getinfo(fp, SM_IO_WHAT_FD, NULL)) == -1) 11590792Sgshapiro { 11690792Sgshapiro /* can't get an fd, likely internal 'fake' fp */ 11790792Sgshapiro errno = 0; 11890792Sgshapiro fd = -1; 11990792Sgshapiro } 12090792Sgshapiro 12190792Sgshapiro /* 12290792Sgshapiro ** Set these immediately to avoid problems with longjmp and to allow 12390792Sgshapiro ** exchange buffering (via setvbuf) in user write function. 12490792Sgshapiro */ 12590792Sgshapiro 12690792Sgshapiro fp->f_p = p; 12790792Sgshapiro fp->f_w = t & (SMLBF|SMNBF) ? 0 : fp->f_bf.smb_size; /* implies SMFBF */ 12890792Sgshapiro 12990792Sgshapiro for (; n > 0; n -= t, p += t) 13090792Sgshapiro { 13190792Sgshapiro errno = 0; /* needed to ensure EOF correctly found */ 13290792Sgshapiro 13390792Sgshapiro /* Call the file type's write function */ 13490792Sgshapiro t = (*fp->f_write)(fp, (char *)p, n); 13590792Sgshapiro if (t <= 0) 13690792Sgshapiro { 13790792Sgshapiro if (t == 0 && errno == 0) 13890792Sgshapiro break; /* EOF found */ 13990792Sgshapiro 14090792Sgshapiro if (IS_IO_ERROR(fd, t, *timeout)) 14190792Sgshapiro { 14290792Sgshapiro fp->f_flags |= SMERR; 14390792Sgshapiro 14490792Sgshapiro /* errno set by fp->f_write */ 14590792Sgshapiro return SM_IO_EOF; 14690792Sgshapiro } 14790792Sgshapiro SM_IO_WR_TIMEOUT(fp, fd, *timeout); 148157001Sgshapiro t = 0; 14990792Sgshapiro } 15090792Sgshapiro } 15190792Sgshapiro return 0; 15290792Sgshapiro} 153