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 | #include <sm/gen.h> |
---|
16 | SM_RCSID("@(#)$Id: fflush.c,v 1.2 2006-03-23 21:02:44 zacheiss Exp $") |
---|
17 | #include <unistd.h> |
---|
18 | #include <errno.h> |
---|
19 | #include <sys/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 | } |
---|