1 /* 2 * Copyright (c) 2000-2001 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 #pragma ident "%Z%%M% %I% %E% SMI" 16 17 #include <sm/gen.h> 18 SM_RCSID("@(#)$Id: fflush.c,v 1.44 2005/06/14 23:07:20 ca Exp $") 19 #include <unistd.h> 20 #include <errno.h> 21 #include <sm/time.h> 22 #include <signal.h> 23 #include <fcntl.h> 24 #include <string.h> 25 #include <sm/io.h> 26 #include <sm/assert.h> 27 #include <sm/setjmp.h> 28 #include "local.h" 29 #include <sm/conf.h> 30 31 /* 32 ** SM_IO_FLUSH -- flush the buffer for a 'fp' to the "file" 33 ** 34 ** Flush a single file. We don't allow this function to flush 35 ** all open files when fp==NULL any longer. 36 ** 37 ** Parameters: 38 ** fp -- the file pointer buffer to flush 39 ** timeout -- time to complete the flush 40 ** 41 ** Results: 42 ** Failure: SM_IO_EOF and sets errno 43 ** Success: 0 (zero) 44 */ 45 46 int 47 sm_io_flush(fp, timeout) 48 register SM_FILE_T *fp; 49 int SM_NONVOLATILE timeout; 50 { 51 int fd; 52 struct timeval to; 53 54 SM_REQUIRE_ISA(fp, SmFileMagic); 55 56 if ((fp->f_flags & (SMWR | SMRW)) == 0) 57 { 58 /* 59 ** The file is not opened for writing, so it cannot be flushed 60 ** (writable means SMWR [write] or SMRW [read/write]. 61 */ 62 63 errno = EBADF; 64 return SM_IO_EOF; 65 } 66 67 SM_CONVERT_TIME(fp, fd, timeout, &to); 68 69 /* Now do the flush */ 70 return sm_flush(fp, (int *) &timeout); 71 } 72 73 /* 74 ** SM_FLUSH -- perform the actual flush 75 ** 76 ** Assumes that 'fp' has been validated before this function called. 77 ** 78 ** Parameters: 79 ** fp -- file pointer to be flushed 80 ** timeout -- max time allowed for flush (milliseconds) 81 ** 82 ** Results: 83 ** Success: 0 (zero) 84 ** Failure: SM_IO_EOF and errno set 85 ** 86 ** Side Effects: 87 ** timeout will get updated with the time remaining (if any) 88 */ 89 90 int 91 sm_flush(fp, timeout) 92 register SM_FILE_T *fp; 93 int *timeout; 94 { 95 register unsigned char *p; 96 register int n, t; 97 int fd; 98 99 SM_REQUIRE_ISA(fp, SmFileMagic); 100 101 t = fp->f_flags; 102 if ((t & SMWR) == 0) 103 return 0; 104 105 if (t & SMSTR) 106 { 107 *fp->f_p = '\0'; 108 return 0; 109 } 110 111 if ((p = fp->f_bf.smb_base) == NULL) 112 return 0; 113 114 n = fp->f_p - p; /* write this much */ 115 116 if ((fd = sm_io_getinfo(fp, SM_IO_WHAT_FD, NULL)) == -1) 117 { 118 /* can't get an fd, likely internal 'fake' fp */ 119 errno = 0; 120 fd = -1; 121 } 122 123 /* 124 ** Set these immediately to avoid problems with longjmp and to allow 125 ** exchange buffering (via setvbuf) in user write function. 126 */ 127 128 fp->f_p = p; 129 fp->f_w = t & (SMLBF|SMNBF) ? 0 : fp->f_bf.smb_size; /* implies SMFBF */ 130 131 for (; n > 0; n -= t, p += t) 132 { 133 errno = 0; /* needed to ensure EOF correctly found */ 134 135 /* Call the file type's write function */ 136 t = (*fp->f_write)(fp, (char *)p, n); 137 if (t <= 0) 138 { 139 if (t == 0 && errno == 0) 140 break; /* EOF found */ 141 142 if (IS_IO_ERROR(fd, t, *timeout)) 143 { 144 fp->f_flags |= SMERR; 145 146 /* errno set by fp->f_write */ 147 return SM_IO_EOF; 148 } 149 SM_IO_WR_TIMEOUT(fp, fd, *timeout); 150 } 151 } 152 return 0; 153 } 154