fflush.c revision 98121
1113656Sdeischen/* 2113656Sdeischen * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. 3113656Sdeischen * All rights reserved. 4113656Sdeischen * Copyright (c) 1990, 1993 5113656Sdeischen * The Regents of the University of California. All rights reserved. 6113656Sdeischen * 7113656Sdeischen * This code is derived from software contributed to Berkeley by 8113656Sdeischen * Chris Torek. 9113656Sdeischen * 10113656Sdeischen * By using this file, you agree to the terms and conditions set 11113656Sdeischen * forth in the LICENSE file which can be found at the top level of 12113656Sdeischen * the sendmail distribution. 13113656Sdeischen */ 14113656Sdeischen 15113656Sdeischen#include <sm/gen.h> 16113656SdeischenSM_RCSID("@(#)$Id: fflush.c,v 1.43 2001/09/11 04:04:48 gshapiro Exp $") 17113656Sdeischen#include <unistd.h> 18113656Sdeischen#include <errno.h> 19113656Sdeischen#include <sys/time.h> 20113656Sdeischen#include <signal.h> 21113656Sdeischen#include <fcntl.h> 22113656Sdeischen#include <string.h> 23113656Sdeischen#include <sm/io.h> 24113656Sdeischen#include <sm/assert.h> 25113656Sdeischen#include <sm/setjmp.h> 26113656Sdeischen#include "local.h" 27113656Sdeischen#include <sm/conf.h> 28113656Sdeischen 29113656Sdeischen/* 30113656Sdeischen** SM_IO_FLUSH -- flush the buffer for a 'fp' to the "file" 31113656Sdeischen** 32113656Sdeischen** Flush a single file. We don't allow this function to flush 33113656Sdeischen** all open files when fp==NULL any longer. 34133801Sdavidxu** 35118277Sdeischen** Parameters: 36113656Sdeischen** fp -- the file pointer buffer to flush 37113656Sdeischen** timeout -- time to complete the flush 38118277Sdeischen** 39118277Sdeischen** Results: 40113656Sdeischen** Failure: SM_IO_EOF and sets errno 41120263Smarcel** Success: 0 (zero) 42133801Sdavidxu*/ 43120263Smarcel 44118510Sdeischenint 45118510Sdeischensm_io_flush(fp, timeout) 46113656Sdeischen register SM_FILE_T *fp; 47118510Sdeischen int SM_NONVOLATILE timeout; 48118510Sdeischen{ 49116771Smarcel int fd; 50118510Sdeischen struct timeval to; 51118510Sdeischen 52118510Sdeischen SM_REQUIRE_ISA(fp, SmFileMagic); 53116771Smarcel 54118510Sdeischen if ((fp->f_flags & (SMWR | SMRW)) == 0) 55116771Smarcel { 56118510Sdeischen /* 57118510Sdeischen ** The file is not opened for writing, so it cannot be flushed 58118510Sdeischen ** (writable means SMWR [write] or SMRW [read/write]. 59118510Sdeischen */ 60118510Sdeischen 61118510Sdeischen errno = EBADF; 62116771Smarcel return SM_IO_EOF; 63116771Smarcel } 64118510Sdeischen 65133756Sdfr SM_CONVERT_TIME(fp, fd, timeout, &to); 66133756Sdfr 67118510Sdeischen /* Now do the flush */ 68118510Sdeischen return sm_flush(fp, (int *) &timeout); 69118510Sdeischen} 70118510Sdeischen 71118277Sdeischen/* 72118510Sdeischen** SM_FLUSH -- perform the actual flush 73118510Sdeischen** 74118510Sdeischen** Assumes that 'fp' has been validated before this function called. 75118510Sdeischen** 76118510Sdeischen** Parameters: 77118510Sdeischen** fp -- file pointer to be flushed 78118510Sdeischen** timeout -- max time allowed for flush (milliseconds) 79118510Sdeischen** 80118510Sdeischen** Results: 81118510Sdeischen** Success: 0 (zero) 82118510Sdeischen** Failure: SM_IO_EOF and errno set 83118510Sdeischen** 84118510Sdeischen** Side Effects: 85118510Sdeischen** timeout will get updated with the time remaining (if any) 86118510Sdeischen*/ 87118510Sdeischen 88118510Sdeischenint 89118510Sdeischensm_flush(fp, timeout) 90118510Sdeischen register SM_FILE_T *fp; 91118510Sdeischen int *timeout; 92134326Sdavidxu{ 93118510Sdeischen register unsigned char *p; 94118510Sdeischen register int n, t; 95118510Sdeischen int fd; 96118510Sdeischen 97118510Sdeischen SM_REQUIRE_ISA(fp, SmFileMagic); 98118510Sdeischen 99118510Sdeischen t = fp->f_flags; 100118510Sdeischen if ((t & SMWR) == 0) 101118510Sdeischen return 0; 102118510Sdeischen 103118510Sdeischen if (t & SMSTR) 104134319Sdavidxu { 105118510Sdeischen *fp->f_p = '\0'; 106118510Sdeischen return 0; 107118510Sdeischen } 108118510Sdeischen 109118510Sdeischen if ((p = fp->f_bf.smb_base) == NULL) 110118510Sdeischen return 0; 111118510Sdeischen 112118510Sdeischen n = fp->f_p - p; /* write this much */ 113118510Sdeischen 114118510Sdeischen if ((fd = sm_io_getinfo(fp, SM_IO_WHAT_FD, NULL)) == -1) 115118510Sdeischen { 116118510Sdeischen /* can't get an fd, likely internal 'fake' fp */ 117118510Sdeischen errno = 0; 118118510Sdeischen fd = -1; 119118510Sdeischen } 120118510Sdeischen 121118510Sdeischen /* 122118510Sdeischen ** Set these immediately to avoid problems with longjmp and to allow 123118510Sdeischen ** exchange buffering (via setvbuf) in user write function. 124118510Sdeischen */ 125118510Sdeischen 126118510Sdeischen fp->f_p = p; 127118510Sdeischen fp->f_w = t & (SMLBF|SMNBF) ? 0 : fp->f_bf.smb_size; /* implies SMFBF */ 128118510Sdeischen 129118510Sdeischen for (; n > 0; n -= t, p += t) 130118510Sdeischen { 131118510Sdeischen errno = 0; /* needed to ensure EOF correctly found */ 132118510Sdeischen 133118510Sdeischen /* Call the file type's write function */ 134118510Sdeischen t = (*fp->f_write)(fp, (char *)p, n); 135118510Sdeischen if (t <= 0) 136118510Sdeischen { 137118510Sdeischen if (t == 0 && errno == 0) 138118510Sdeischen break; /* EOF found */ 139118510Sdeischen 140118510Sdeischen if (IS_IO_ERROR(fd, t, *timeout)) 141118510Sdeischen { 142118510Sdeischen fp->f_flags |= SMERR; 143118510Sdeischen 144133756Sdfr /* errno set by fp->f_write */ 145118510Sdeischen return SM_IO_EOF; 146118510Sdeischen } 147118510Sdeischen SM_IO_WR_TIMEOUT(fp, fd, *timeout); 148118510Sdeischen } 149118510Sdeischen } 150118510Sdeischen return 0; 151118510Sdeischen} 152118510Sdeischen