1 /* 2 * Copyright (c) 2000-2001, 2005, 2006 Sendmail, Inc. and its suppliers. 3 * All rights reserved. 4 * Copyright (c) 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Chris Torek. 9 * 10 * By using this file, you agree to the terms and conditions set 11 * forth in the LICENSE file which can be found at the top level of 12 * the sendmail distribution. 13 */ 14 15 #include <sm/gen.h> 16 SM_RCSID("@(#)$Id: fflush.c,v 1.45 2006/03/03 22:25:00 ca Exp $") 17 #include <unistd.h> 18 #include <errno.h> 19 #include <sm/time.h> 20 #include <signal.h> 21 #include <fcntl.h> 22 #include <string.h> 23 #include <sm/io.h> 24 #include <sm/assert.h> 25 #include <sm/setjmp.h> 26 #include "local.h" 27 #include <sm/conf.h> 28 29 /* 30 ** SM_IO_FLUSH -- flush the buffer for a 'fp' to the "file" 31 ** 32 ** Flush a single file. We don't allow this function to flush 33 ** all open files when fp==NULL any longer. 34 ** 35 ** Parameters: 36 ** fp -- the file pointer buffer to flush 37 ** timeout -- time to complete the flush 38 ** 39 ** Results: 40 ** Failure: SM_IO_EOF and sets errno 41 ** Success: 0 (zero) 42 */ 43 44 int 45 sm_io_flush(fp, timeout) 46 register SM_FILE_T *fp; 47 int SM_NONVOLATILE timeout; 48 { 49 int fd; 50 struct timeval to; 51 52 SM_REQUIRE_ISA(fp, SmFileMagic); 53 54 if ((fp->f_flags & (SMWR | SMRW)) == 0) 55 { 56 /* 57 ** The file is not opened for writing, so it cannot be flushed 58 ** (writable means SMWR [write] or SMRW [read/write]. 59 */ 60 61 errno = EBADF; 62 return SM_IO_EOF; 63 } 64 65 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 88 int 89 sm_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