/src/dovecot/src/lib/istream.h
Line | Count | Source (jump to first uncovered line) |
1 | | #ifndef ISTREAM_H |
2 | | #define ISTREAM_H |
3 | | |
4 | | /* Note that some systems (Solaris) may use a macro to redefine struct stat */ |
5 | | #include <sys/stat.h> |
6 | | |
7 | | struct ioloop; |
8 | | struct iostream_fd; |
9 | | |
10 | | struct istream { |
11 | | uoff_t v_offset; |
12 | | |
13 | | /* Commonly used errors: |
14 | | |
15 | | ENOENT - File/object doesn't exist. |
16 | | EPIPE - Stream ended unexpectedly (or i_stream_close() was called). |
17 | | ESPIPE - i_stream_seek() was used on a stream that can't be seeked. |
18 | | ENOBUFS - i_stream_read_next_line() was used for a too long line. |
19 | | EIO - Internal error. Retrying may work, but it may also be |
20 | | because of a misconfiguration. |
21 | | EINVAL - Stream is corrupted. |
22 | | |
23 | | If stream_errno != 0, eof==TRUE as well. |
24 | | */ |
25 | | int stream_errno; |
26 | | |
27 | | bool mmaped:1; /* be careful when copying data */ |
28 | | bool blocking:1; /* read() shouldn't return 0 */ |
29 | | bool closed:1; |
30 | | bool readable_fd:1; /* fd can be read directly if necessary |
31 | | (for sendfile()) */ |
32 | | bool seekable:1; /* we can seek() backwards */ |
33 | | /* read() has reached to end of file (but there may still be data |
34 | | available in buffer) or stream_errno != 0 */ |
35 | | bool eof:1; |
36 | | |
37 | | struct istream_private *real_stream; |
38 | | }; |
39 | | |
40 | | typedef void istream_callback_t(void *context); |
41 | | |
42 | | struct istream *i_stream_create_fd(int fd, size_t max_buffer_size); |
43 | | /* The fd is set to -1 immediately to avoid accidentally closing it twice. */ |
44 | | struct istream *i_stream_create_fd_autoclose(int *fd, size_t max_buffer_size); |
45 | | /* Autoclose the fd once ref's refcount drops to 0. This function increases the |
46 | | refcount, so the caller is expected to unref it as well. */ |
47 | | struct istream *i_stream_create_fd_ref_autoclose(struct iostream_fd *ref, |
48 | | size_t max_buffer_size); |
49 | | /* Open the given path only when something is actually tried to be read from |
50 | | the stream. */ |
51 | | struct istream *i_stream_create_file(const char *path, size_t max_buffer_size); |
52 | | /* Create an input stream using the provided data block. That data block must |
53 | | remain allocated during the full lifetime of the stream. */ |
54 | | struct istream *i_stream_create_from_data(const void *data, size_t size); |
55 | | #define i_stream_create_from_buffer(buf) \ |
56 | | i_stream_create_from_data((buf)->data, (buf)->used) |
57 | | #define i_stream_create_from_string(str) \ |
58 | | i_stream_create_from_data(str_data(str), str_len(str)) |
59 | | /* Create an input stream using a copy of the provided data block. The |
60 | | provided data block may be freed at any time. The copy is freed when the |
61 | | stream is destroyed. */ |
62 | | struct istream * |
63 | | i_stream_create_copy_from_data(const void *data, size_t size); |
64 | | #define i_stream_create_copy_from_buffer(buf) \ |
65 | | i_stream_create_copy_from_data((buf)->data, (buf)->used) |
66 | | #define i_stream_create_copy_from_string(str) \ |
67 | | i_stream_create_copy_from_data(str_data(str), str_len(str)) |
68 | | /* Create a no-operation wrapper to allow input to be used as child stream. */ |
69 | | struct istream *i_stream_create_noop(struct istream *input); |
70 | | struct istream *i_stream_create_limit(struct istream *input, uoff_t v_size); |
71 | | struct istream *i_stream_create_range(struct istream *input, |
72 | | uoff_t v_offset, uoff_t v_size); |
73 | | struct istream *i_stream_create_error(int stream_errno); |
74 | | struct istream * |
75 | | i_stream_create_error_str(int stream_errno, const char *fmt, ...) |
76 | | ATTR_FORMAT(2, 3); |
77 | | |
78 | | /* Set name (e.g. path) for input stream. */ |
79 | | void i_stream_set_name(struct istream *stream, const char *name); |
80 | | /* Get input stream's name. If stream itself doesn't have a name, |
81 | | it looks up further into stream's parents until one of them has a name. |
82 | | Returns "" if stream has no name. */ |
83 | | const char *i_stream_get_name(struct istream *stream); |
84 | | |
85 | | /* Close this stream (but not its parents) and unreference it. */ |
86 | | void i_stream_destroy(struct istream **stream); |
87 | | |
88 | | /* Reference counting. References start from 1, so calling i_stream_unref() |
89 | | destroys the stream if i_stream_ref() is never used. */ |
90 | | void i_stream_ref(struct istream *stream); |
91 | | /* Unreferences the stream and sets stream pointer to NULL. */ |
92 | | void i_stream_unref(struct istream **stream); |
93 | | /* Call the given callback function when stream is destroyed. */ |
94 | | void i_stream_add_destroy_callback(struct istream *stream, |
95 | | istream_callback_t *callback, void *context) |
96 | | ATTR_NULL(3); |
97 | | #define i_stream_add_destroy_callback(stream, callback, context) \ |
98 | 0 | i_stream_add_destroy_callback(stream - \ |
99 | 0 | CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \ |
100 | 0 | (istream_callback_t *)callback, context) |
101 | | /* Remove the destroy callback. */ |
102 | | void i_stream_remove_destroy_callback(struct istream *stream, |
103 | | void (*callback)()); |
104 | | |
105 | | /* Return file descriptor for stream, or -1 if none is available. */ |
106 | | int i_stream_get_fd(struct istream *stream); |
107 | | /* Copy the file descriptor from source istream to destination istream. |
108 | | The readable_fd is preserved. Assert-crashes if source doesn't have a |
109 | | file descriptor. */ |
110 | | void i_stream_copy_fd(struct istream *dest, struct istream *source); |
111 | | /* Set error for istream. */ |
112 | | void i_stream_set_error(struct istream *stream, int stream_errno, |
113 | | const char *fmt, ...) ATTR_FORMAT(3, 4); |
114 | | /* Returns error string for the last error. It also returns "EOF" in case there |
115 | | is no error, but eof is set. Otherwise it returns "<no error>". */ |
116 | | const char *i_stream_get_error(struct istream *stream); |
117 | | /* Returns human-readable reason for why istream was disconnected. |
118 | | The output is either "Connection closed" for clean disconnections or |
119 | | "Connection closed: <error>" for unclean disconnections. This is an |
120 | | alternative to i_stream_get_error(), which is preferred to be used when |
121 | | logging errors about client connections. */ |
122 | | const char *i_stream_get_disconnect_reason(struct istream *stream); |
123 | | |
124 | | /* Mark the stream and all of its parent streams closed. Any reads after this |
125 | | will return -1. The data already read can still be used. */ |
126 | | void i_stream_close(struct istream *stream); |
127 | | /* Sync the stream with the underlying backend, ie. if a file has been |
128 | | modified, flush any cached data. */ |
129 | | void i_stream_sync(struct istream *stream); |
130 | | |
131 | | /* Change the initial size for stream's input buffer. This basically just |
132 | | grows the read buffer size from the default. This function has no effect |
133 | | unless it's called before reading anything. */ |
134 | | void i_stream_set_init_buffer_size(struct istream *stream, size_t size); |
135 | | /* Change the maximum size for stream's input buffer to grow. Useful only |
136 | | for buffered streams (currently only file). This changes also all the |
137 | | parent streams' max buffer size. */ |
138 | | void i_stream_set_max_buffer_size(struct istream *stream, size_t max_size); |
139 | | /* Returns the current max. buffer size for the stream. This function also |
140 | | goes through all of the parent streams and returns the highest seen max |
141 | | buffer size. This is needed because some streams (e.g. istream-chain) change |
142 | | their max buffer size dynamically. */ |
143 | | size_t i_stream_get_max_buffer_size(struct istream *stream); |
144 | | /* Enable/disable i_stream[_read]_next_line() returning the last line if it |
145 | | doesn't end with LF. */ |
146 | | void i_stream_set_return_partial_line(struct istream *stream, bool set); |
147 | | /* Change whether buffers are allocated persistently (default=TRUE). When not, |
148 | | the memory usage is minimized by freeing the stream's buffers whenever they |
149 | | become empty. */ |
150 | | void i_stream_set_persistent_buffers(struct istream *stream, bool set); |
151 | | /* Set the istream blocking or nonblocking, including its parent streams. |
152 | | If any of the istreams have an fd, its O_NONBLOCK flag is changed. */ |
153 | | void i_stream_set_blocking(struct istream *stream, bool blocking); |
154 | | |
155 | | /* Returns number of bytes read if read was ok, 0 if stream is non-blocking and |
156 | | no more data is available, -1 if EOF or error, -2 if the input buffer is |
157 | | full. If <=0 is returned, pointers to existing data returned by the previous |
158 | | i_stream_get_data() will stay valid, although calling it again may return |
159 | | a different pointer. The pointers to old data are invalidated again when |
160 | | return value is >0. */ |
161 | | ssize_t i_stream_read(struct istream *stream); |
162 | | /* Skip forward a number of bytes. Never fails, the next read tells if it |
163 | | was successful. */ |
164 | | void i_stream_skip(struct istream *stream, uoff_t count); |
165 | | /* Seek to specified position from beginning of file. Never fails, the next |
166 | | read tells if it was successful. This works only for files, others will |
167 | | set stream_errno=ESPIPE. */ |
168 | | void i_stream_seek(struct istream *stream, uoff_t v_offset); |
169 | | /* Like i_stream_seek(), but also giving a hint that after reading some data |
170 | | we could be seeking back to this mark or somewhere after it. If input |
171 | | stream's implementation is slow in seeking backwards, it can use this hint |
172 | | to cache some of the data in memory. */ |
173 | | void i_stream_seek_mark(struct istream *stream, uoff_t v_offset); |
174 | | /* Returns 0 if ok, -1 if error. As the underlying stream may not be |
175 | | a file, only some of the fields might be set, others would be zero. |
176 | | st_size is always set, and if it's not known, it's -1. |
177 | | |
178 | | If exact=FALSE, the stream may not return exactly correct values, but the |
179 | | returned values can be compared to see if anything had changed (eg. in |
180 | | compressed stream st_size could be compressed size) */ |
181 | | int i_stream_stat(struct istream *stream, bool exact, const struct stat **st_r); |
182 | | /* Similar to i_stream_stat() call. Returns 1 if size was successfully |
183 | | set, 0 if size is unknown, -1 if error. */ |
184 | | int i_stream_get_size(struct istream *stream, bool exact, uoff_t *size_r); |
185 | | /* Returns TRUE if there are any bytes left to be read or in buffer. */ |
186 | | bool i_stream_have_bytes_left(struct istream *stream); |
187 | | /* Returns TRUE if there are no bytes currently buffered and i_stream_read() |
188 | | returns EOF/error. Usually it's enough to check for stream->eof instead of |
189 | | calling this function. Note that if the stream isn't at EOF, this function |
190 | | has now read data into the stream buffer. */ |
191 | | bool i_stream_read_eof(struct istream *stream); |
192 | | /* Returns the absolute offset of the stream. This is the stream's current |
193 | | v_offset + the parent's absolute offset when the stream was created. */ |
194 | | uoff_t i_stream_get_absolute_offset(struct istream *stream); |
195 | | |
196 | | /* Gets the next line from stream and returns it, or NULL if more data is |
197 | | needed to make a full line. i_stream_set_return_partial_line() specifies |
198 | | if the last line should be returned if it doesn't end with LF. */ |
199 | | char *i_stream_next_line(struct istream *stream); |
200 | | /* Like i_stream_next_line(), but reads for more data if needed. Returns NULL |
201 | | if more data is needed or error occurred. If the input buffer gets full, |
202 | | stream_errno is set to ENOBUFS. */ |
203 | | char *i_stream_read_next_line(struct istream *stream); |
204 | | /* Returns TRUE if the last line read with i_stream_next_line() ended with |
205 | | CRLF (instead of LF). */ |
206 | | bool i_stream_last_line_crlf(struct istream *stream); |
207 | | |
208 | | /* Returns pointer to beginning of read data. */ |
209 | | const unsigned char *i_stream_get_data(struct istream *stream, size_t *size_r); |
210 | | size_t i_stream_get_data_size(struct istream *stream); |
211 | | /* Like i_stream_get_data(), but returns non-const data. This only works with |
212 | | buffered streams (currently only file), others return NULL. */ |
213 | | unsigned char *i_stream_get_modifiable_data(struct istream *stream, |
214 | | size_t *size_r); |
215 | | /* Like i_stream_get_data(), but read more when needed. Returns 1 if more |
216 | | than threshold bytes are available, 0 if as much or less, -1 if error or |
217 | | EOF with no bytes read that weren't already in buffer, or -2 if stream's |
218 | | input buffer is full. */ |
219 | | int i_stream_read_data(struct istream *stream, const unsigned char **data_r, |
220 | | size_t *size_r, size_t threshold); |
221 | | /* Like i_stream_get_data(), but read more when needed. Returns 1 if at least |
222 | | the wanted number of bytes are available, 0 if less, -1 if error or |
223 | | EOF with no bytes read that weren't already in buffer, or -2 if stream's |
224 | | input buffer is full. */ |
225 | | static inline int |
226 | | i_stream_read_bytes(struct istream *stream, const unsigned char **data_r, |
227 | | size_t *size_r, size_t wanted) |
228 | 13.4k | { |
229 | 13.4k | i_assert(wanted > 0); |
230 | 13.4k | return i_stream_read_data(stream, data_r, size_r, wanted - 1); |
231 | 13.4k | } Unexecuted instantiation: fuzz-smtp-server.c:i_stream_read_bytes Unexecuted instantiation: smtp-server-cmd-data.c:i_stream_read_bytes Unexecuted instantiation: smtp-server-reply.c:i_stream_read_bytes Unexecuted instantiation: smtp-server-connection.c:i_stream_read_bytes Unexecuted instantiation: smtp-server.c:i_stream_read_bytes Unexecuted instantiation: smtp-reply-parser.c:i_stream_read_bytes Unexecuted instantiation: smtp-command-parser.c:i_stream_read_bytes Unexecuted instantiation: smtp-server-cmd-starttls.c:i_stream_read_bytes Unexecuted instantiation: smtp-server-cmd-auth.c:i_stream_read_bytes Unexecuted instantiation: smtp-server-cmd-xclient.c:i_stream_read_bytes Unexecuted instantiation: istream-dot.c:i_stream_read_bytes Unexecuted instantiation: fuzzer.c:i_stream_read_bytes Unexecuted instantiation: connection.c:i_stream_read_bytes Unexecuted instantiation: iostream.c:i_stream_read_bytes Unexecuted instantiation: iostream-pump.c:i_stream_read_bytes Unexecuted instantiation: iostream-rawlog.c:i_stream_read_bytes Unexecuted instantiation: istream.c:i_stream_read_bytes Unexecuted instantiation: istream-chain.c:i_stream_read_bytes Unexecuted instantiation: istream-data.c:i_stream_read_bytes Unexecuted instantiation: istream-failure-at.c:i_stream_read_bytes Unexecuted instantiation: istream-file.c:i_stream_read_bytes Unexecuted instantiation: istream-limit.c:i_stream_read_bytes Unexecuted instantiation: istream-rawlog.c:i_stream_read_bytes Unexecuted instantiation: istream-sized.c:i_stream_read_bytes Unexecuted instantiation: istream-unix.c:i_stream_read_bytes Unexecuted instantiation: ioloop.c:i_stream_read_bytes ostream.c:i_stream_read_bytes Line | Count | Source | 228 | 13.4k | { | 229 | 13.4k | i_assert(wanted > 0); | 230 | 13.4k | return i_stream_read_data(stream, data_r, size_r, wanted - 1); | 231 | 13.4k | } |
Unexecuted instantiation: ostream-file.c:i_stream_read_bytes |
232 | | /* Short-hand for just requesting more data (i.e. even one byte) */ |
233 | | static inline int |
234 | | i_stream_read_more(struct istream *stream, const unsigned char **data_r, |
235 | | size_t *size_r) |
236 | 13.4k | { |
237 | 13.4k | int ret = i_stream_read_bytes(stream, data_r, size_r, 1); |
238 | 13.4k | i_assert(ret != -2); /* stream must have space for at least 1 byte */ |
239 | 13.4k | return ret; |
240 | 13.4k | } Unexecuted instantiation: fuzz-smtp-server.c:i_stream_read_more Unexecuted instantiation: smtp-server-cmd-data.c:i_stream_read_more Unexecuted instantiation: smtp-server-reply.c:i_stream_read_more Unexecuted instantiation: smtp-server-connection.c:i_stream_read_more Unexecuted instantiation: smtp-server.c:i_stream_read_more Unexecuted instantiation: smtp-reply-parser.c:i_stream_read_more Unexecuted instantiation: smtp-command-parser.c:i_stream_read_more Unexecuted instantiation: smtp-server-cmd-starttls.c:i_stream_read_more Unexecuted instantiation: smtp-server-cmd-auth.c:i_stream_read_more Unexecuted instantiation: smtp-server-cmd-xclient.c:i_stream_read_more Unexecuted instantiation: istream-dot.c:i_stream_read_more Unexecuted instantiation: fuzzer.c:i_stream_read_more Unexecuted instantiation: connection.c:i_stream_read_more Unexecuted instantiation: iostream.c:i_stream_read_more Unexecuted instantiation: iostream-pump.c:i_stream_read_more Unexecuted instantiation: iostream-rawlog.c:i_stream_read_more Unexecuted instantiation: istream.c:i_stream_read_more Unexecuted instantiation: istream-chain.c:i_stream_read_more Unexecuted instantiation: istream-data.c:i_stream_read_more Unexecuted instantiation: istream-failure-at.c:i_stream_read_more Unexecuted instantiation: istream-file.c:i_stream_read_more Unexecuted instantiation: istream-limit.c:i_stream_read_more Unexecuted instantiation: istream-rawlog.c:i_stream_read_more Unexecuted instantiation: istream-sized.c:i_stream_read_more Unexecuted instantiation: istream-unix.c:i_stream_read_more Unexecuted instantiation: ioloop.c:i_stream_read_more ostream.c:i_stream_read_more Line | Count | Source | 236 | 13.4k | { | 237 | 13.4k | int ret = i_stream_read_bytes(stream, data_r, size_r, 1); | 238 | 13.4k | i_assert(ret != -2); /* stream must have space for at least 1 byte */ | 239 | 13.4k | return ret; | 240 | 13.4k | } |
Unexecuted instantiation: ostream-file.c:i_stream_read_more |
241 | | /* Like i_stream_read_more(), but tries to avoid buffering more than the |
242 | | indicated limit. Use this function to prevent growing the stream buffer |
243 | | beyond what the application is willing to read immediately. Since this |
244 | | function doesn't fully prevent buffering beyond the limit, the amount of data |
245 | | actually buffered can exceed the limit. However, *size_r will always be <= |
246 | | limit to avoid confusion. */ |
247 | | int i_stream_read_limited(struct istream *stream, const unsigned char **data_r, |
248 | | size_t *size_r, size_t limit); |
249 | | /* Return the timestamp when istream last successfully read something. |
250 | | The timestamp is 0 if nothing has ever been read. */ |
251 | | void i_stream_get_last_read_time(struct istream *stream, struct timeval *tv_r); |
252 | | |
253 | | /* Append external data to input stream. Returns TRUE if successful, FALSE if |
254 | | there is not enough space in the stream. */ |
255 | | bool i_stream_add_data(struct istream *stream, const unsigned char *data, |
256 | | size_t size); |
257 | | |
258 | | void i_stream_set_input_pending(struct istream *stream, bool pending); |
259 | | |
260 | | /* If there are any I/O loop items associated with the stream, move all of |
261 | | them to provided/current ioloop. */ |
262 | | void i_stream_switch_ioloop_to(struct istream *stream, struct ioloop *ioloop); |
263 | | void i_stream_switch_ioloop(struct istream *stream); |
264 | | |
265 | | #endif |