fflush.c revision 261363
1266987Smarkj/* 2266987Smarkj * Copyright (c) 2000-2001, 2005, 2006 Proofpoint, Inc. and its suppliers. 3266987Smarkj * All rights reserved. 4266987Smarkj * Copyright (c) 1990, 1993 5266987Smarkj * The Regents of the University of California. All rights reserved. 6266987Smarkj * 7266987Smarkj * This code is derived from software contributed to Berkeley by 8266987Smarkj * Chris Torek. 9266987Smarkj * 10266987Smarkj * By using this file, you agree to the terms and conditions set 11266987Smarkj * forth in the LICENSE file which can be found at the top level of 12266987Smarkj * the sendmail distribution. 13266987Smarkj */ 14266987Smarkj 15266987Smarkj#include <sm/gen.h> 16266987SmarkjSM_RCSID("@(#)$Id: fflush.c,v 1.46 2013/11/22 20:51:42 ca Exp $") 17266987Smarkj#include <unistd.h> 18266987Smarkj#include <errno.h> 19266987Smarkj#include <sm/time.h> 20266987Smarkj#include <signal.h> 21266987Smarkj#include <fcntl.h> 22266987Smarkj#include <string.h> 23266987Smarkj#include <sm/io.h> 24266987Smarkj#include <sm/assert.h> 25266987Smarkj#include <sm/setjmp.h> 26266987Smarkj#include "local.h" 27266987Smarkj#include <sm/conf.h> 28266987Smarkj 29266987Smarkj/* 30266987Smarkj** SM_IO_FLUSH -- flush the buffer for a 'fp' to the "file" 31266987Smarkj** 32266987Smarkj** Flush a single file. We don't allow this function to flush 33266987Smarkj** all open files when fp==NULL any longer. 34266987Smarkj** 35266987Smarkj** Parameters: 36266987Smarkj** fp -- the file pointer buffer to flush 37266987Smarkj** timeout -- time to complete the flush 38266987Smarkj** 39266987Smarkj** Results: 40266987Smarkj** Failure: SM_IO_EOF and sets errno 41266987Smarkj** Success: 0 (zero) 42266987Smarkj*/ 43266987Smarkj 44266987Smarkjint 45266987Smarkjsm_io_flush(fp, timeout) 46266987Smarkj register SM_FILE_T *fp; 47266987Smarkj int SM_NONVOLATILE timeout; 48266987Smarkj{ 49266987Smarkj int fd; 50266987Smarkj struct timeval to; 51266987Smarkj 52266987Smarkj SM_REQUIRE_ISA(fp, SmFileMagic); 53266987Smarkj 54266987Smarkj if ((fp->f_flags & (SMWR | SMRW)) == 0) 55266987Smarkj { 56266987Smarkj /* 57266987Smarkj ** The file is not opened for writing, so it cannot be flushed 58266987Smarkj ** (writable means SMWR [write] or SMRW [read/write]. 59266987Smarkj */ 60266987Smarkj 61266987Smarkj errno = EBADF; 62266987Smarkj return SM_IO_EOF; 63266987Smarkj } 64266987Smarkj 65266987Smarkj SM_CONVERT_TIME(fp, fd, timeout, &to); 66 67 /* Now do the flush */ 68 return sm_flush(fp, (int *) &timeout); 69} 70 71/* 72** SM_FLUSH -- perform the actual flush 73** 74** Assumes that 'fp' has been validated before this function called. 75** 76** Parameters: 77** fp -- file pointer to be flushed 78** timeout -- max time allowed for flush (milliseconds) 79** 80** Results: 81** Success: 0 (zero) 82** Failure: SM_IO_EOF and errno set 83** 84** Side Effects: 85** timeout will get updated with the time remaining (if any) 86*/ 87 88int 89sm_flush(fp, timeout) 90 register SM_FILE_T *fp; 91 int *timeout; 92{ 93 register unsigned char *p; 94 register int n, t; 95 int fd; 96 97 SM_REQUIRE_ISA(fp, SmFileMagic); 98 99 t = fp->f_flags; 100 if ((t & SMWR) == 0) 101 return 0; 102 103 if (t & SMSTR) 104 { 105 *fp->f_p = '\0'; 106 return 0; 107 } 108 109 if ((p = fp->f_bf.smb_base) == NULL) 110 return 0; 111 112 n = fp->f_p - p; /* write this much */ 113 114 if ((fd = sm_io_getinfo(fp, SM_IO_WHAT_FD, NULL)) == -1) 115 { 116 /* can't get an fd, likely internal 'fake' fp */ 117 errno = 0; 118 fd = -1; 119 } 120 121 /* 122 ** Set these immediately to avoid problems with longjmp and to allow 123 ** exchange buffering (via setvbuf) in user write function. 124 */ 125 126 fp->f_p = p; 127 fp->f_w = t & (SMLBF|SMNBF) ? 0 : fp->f_bf.smb_size; /* implies SMFBF */ 128 129 for (; n > 0; n -= t, p += t) 130 { 131 errno = 0; /* needed to ensure EOF correctly found */ 132 133 /* Call the file type's write function */ 134 t = (*fp->f_write)(fp, (char *)p, n); 135 if (t <= 0) 136 { 137 if (t == 0 && errno == 0) 138 break; /* EOF found */ 139 140 if (IS_IO_ERROR(fd, t, *timeout)) 141 { 142 fp->f_flags |= SMERR; 143 144 /* errno set by fp->f_write */ 145 return SM_IO_EOF; 146 } 147 SM_IO_WR_TIMEOUT(fp, fd, *timeout); 148 t = 0; 149 } 150 } 151 return 0; 152} 153