Coverage Report

Created: 2025-07-18 06:24

/src/dovecot/src/lib/ostream.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef OSTREAM_H
2
#define OSTREAM_H
3
4
#include "ioloop.h"
5
6
struct iostream_fd;
7
8
enum ostream_send_istream_result {
9
  /* All of the istream was successfully sent to ostream. */
10
  OSTREAM_SEND_ISTREAM_RESULT_FINISHED,
11
  /* Caller needs to wait for more input from non-blocking istream. */
12
  OSTREAM_SEND_ISTREAM_RESULT_WAIT_INPUT,
13
  /* Caller needs to wait for output to non-blocking ostream.
14
     o_stream_set_flush_pending() is automatically called. */
15
  OSTREAM_SEND_ISTREAM_RESULT_WAIT_OUTPUT,
16
  /* Read from istream failed. See istream->stream_errno. */
17
  OSTREAM_SEND_ISTREAM_RESULT_ERROR_INPUT,
18
  /* Write to ostream failed. See ostream->stream_errno. */
19
  OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT
20
};
21
22
enum ostream_create_file_flags {
23
  /* without append, file is truncated */
24
  OSTREAM_CREATE_FILE_FLAG_APPEND = BIT(0),
25
};
26
27
struct ostream {
28
  /* Number of bytes sent via o_stream_send*() and similar functions.
29
     This is counting the input data. For example with a compressed
30
     ostream this is counting the uncompressed bytes. The compressed
31
     bytes could be counted from the parent ostream's offset.
32
33
     Seeking to a specified offset only makes sense if there is no
34
     difference between input and output data sizes (e.g. there are no
35
     wrapper ostreams changing the data). */
36
  uoff_t offset;
37
38
  /* errno for the last operation send/seek operation. cleared before
39
     each call. */
40
  int stream_errno;
41
42
  /* overflow is set when some of the data given to send()
43
     functions was neither sent nor buffered. It's never unset inside
44
     ostream code. */
45
  bool overflow:1;
46
  /* o_stream_send() writes all the data or returns failure */
47
  bool blocking:1;
48
  bool closed:1;
49
50
  struct ostream_private *real_stream;
51
};
52
53
/* Returns 1 if all data is sent (not necessarily flushed), 0 if not.
54
   Pretty much the only real reason to return 0 is if you wish to send more
55
   data to client which isn't buffered, eg. o_stream_send_istream(). */
56
typedef int stream_flush_callback_t(void *context);
57
typedef void ostream_callback_t(void *context);
58
59
/* Create new output stream from given file descriptor.
60
   If max_buffer_size is 0, an "optimal" buffer size is used (max 128kB). */
61
struct ostream *o_stream_create_fd(int fd, size_t max_buffer_size);
62
/* The fd is set to -1 immediately to avoid accidentally closing it twice. */
63
struct ostream *o_stream_create_fd_autoclose(int *fd, size_t max_buffer_size);
64
/* Autoclose the fd once ref's refcount drops to 0. This function increases the
65
   refcount, so the caller is expected to unref it as well. */
66
struct ostream *o_stream_create_fd_ref_autoclose(struct iostream_fd *ref,
67
             size_t max_buffer_size);
68
/* Create an output stream from a regular file which begins at given offset.
69
   If offset==UOFF_T_MAX, the current offset isn't known. */
70
struct ostream *
71
o_stream_create_fd_file(int fd, uoff_t offset, bool autoclose_fd);
72
struct ostream *o_stream_create_fd_file_autoclose(int *fd, uoff_t offset);
73
/* Create ostream for file. If append flag is not set, file will be truncated. */
74
struct ostream *o_stream_create_file(const char *path, uoff_t offset, mode_t mode,
75
             enum ostream_create_file_flags flags);
76
/* Create ostream for a blocking (network) fd. It assumes that all the output
77
   can be written to the fd. If not, the ostream fails. */
78
struct ostream *o_stream_create_fd_blocking(int fd);
79
/* Create an output stream to a buffer. Note that the buffer is treated as the
80
   ostream's internal buffer. This means that o_stream_get_buffer_used_size()
81
   returns buf->used, and _get_buffer_avail_size() returns how many bytes can
82
   be written until the buffer's max size is reached. This behavior may make
83
   ostream-buffer unsuitable for code that assumes that having bytes in the
84
   internal buffer means that ostream isn't finished flushing its internal
85
   buffer. Especially o_stream_flush_parent_if_needed() (used by
86
   lib-compression ostreams) don't work with this. */
87
struct ostream *o_stream_create_buffer(buffer_t *buf);
88
/* Create an output streams that always fails the writes. */
89
struct ostream *o_stream_create_error(int stream_errno);
90
struct ostream *
91
o_stream_create_error_str(int stream_errno, const char *fmt, ...)
92
  ATTR_FORMAT(2, 3);
93
/* Create an output stream that simply passes through data. This is mainly
94
   useful as a wrapper when combined with destroy callbacks. */
95
struct ostream *o_stream_create_passthrough(struct ostream *output);
96
97
/* Set name (e.g. path) for output stream. */
98
void o_stream_set_name(struct ostream *stream, const char *name);
99
/* Get output stream's name. Returns "" if stream has no name. */
100
const char *o_stream_get_name(struct ostream *stream);
101
102
/* Return file descriptor for stream, or -1 if none is available. */
103
int o_stream_get_fd(struct ostream *stream);
104
/* Returns error string for the previous error. */
105
const char *o_stream_get_error(struct ostream *stream);
106
/* Returns human-readable reason for why ostream was disconnected.
107
   The output is either "Connection closed" for clean disconnections or
108
   "Connection closed: <error>" for unclean disconnections. This is an
109
   alternative to o_stream_get_error(), which is preferred to be used when
110
   logging errors about client connections. */
111
const char *o_stream_get_disconnect_reason(struct ostream *stream);
112
113
/* Close this stream (but not its parents) and unreference it. */
114
void o_stream_destroy(struct ostream **stream);
115
/* Reference counting. References start from 1, so calling o_stream_unref()
116
   destroys the stream if o_stream_ref() is never used. */
117
void o_stream_ref(struct ostream *stream);
118
/* Unreferences the stream and sets stream pointer to NULL. */
119
void o_stream_unref(struct ostream **stream);
120
/* Call the given callback function when stream is destroyed. */
121
void o_stream_add_destroy_callback(struct ostream *stream,
122
           ostream_callback_t *callback, void *context)
123
  ATTR_NULL(3);
124
#define o_stream_add_destroy_callback(stream, callback, context) \
125
  o_stream_add_destroy_callback(stream - \
126
    CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
127
    (ostream_callback_t *)callback, context)
128
/* Remove the destroy callback. */
129
void o_stream_remove_destroy_callback(struct ostream *stream,
130
              void (*callback)());
131
132
/* Mark the stream and all of its parent streams closed. Nothing will be
133
   sent after this call. When using ostreams that require writing a trailer,
134
   o_stream_finish() must be used before the stream is closed. When ostream
135
   is destroyed, it's also closed but its parents aren't.
136
137
   Closing the ostream (also via destroy) will first flush the ostream, and
138
   afterwards requires one of: a) stream has failed, b) there is no more
139
   buffered data, c) o_stream_set_no_error_handling() has been called. */
140
void o_stream_close(struct ostream *stream);
141
142
/* Set IO_WRITE callback. Default will just try to flush the output and
143
   finishes when the buffer is empty.  */
144
void o_stream_set_flush_callback(struct ostream *stream,
145
         stream_flush_callback_t *callback,
146
         void *context) ATTR_NULL(3);
147
#define o_stream_set_flush_callback(stream, callback, context) \
148
0
  o_stream_set_flush_callback(stream - \
149
0
    CALLBACK_TYPECHECK(callback, int (*)(typeof(context))), \
150
0
    (stream_flush_callback_t *)callback, context)
151
void o_stream_unset_flush_callback(struct ostream *stream);
152
/* Get the current flush callback, returns NULL if none set. */
153
stream_flush_callback_t *
154
o_stream_get_flush_callback(struct ostream *stream, void **context_r);
155
156
/* Change the maximum size for stream's output buffer to grow. */
157
void o_stream_set_max_buffer_size(struct ostream *stream, size_t max_size);
158
/* Returns the current max. buffer size. */
159
size_t o_stream_get_max_buffer_size(struct ostream *stream);
160
161
/* Delays sending as far as possible, writing only full buffers. Also sets
162
   TCP_CORK on if supported. */
163
void o_stream_cork(struct ostream *stream);
164
/* Try to flush the buffer by calling o_stream_flush() and remove TCP_CORK.
165
   Note that after this o_stream_flush() must be called, unless the stream
166
   ignores errors. */
167
void o_stream_uncork(struct ostream *stream);
168
bool o_stream_is_corked(struct ostream *stream);
169
/* Try to flush the output stream. If o_stream_nsend*() had been used and
170
   the stream had overflown, return error. Returns 1 if all data is sent,
171
   0 there's still buffered data, -1 if error. */
172
int o_stream_flush(struct ostream *stream);
173
/* Wrapper to easily both uncork and flush. */
174
static inline int o_stream_uncork_flush(struct ostream *stream)
175
0
{
176
0
  o_stream_uncork(stream);
177
0
  return o_stream_flush(stream);
178
0
}
Unexecuted instantiation: fuzzer.c:o_stream_uncork_flush
Unexecuted instantiation: iostream-pump.c:o_stream_uncork_flush
Unexecuted instantiation: ostream.c:o_stream_uncork_flush
Unexecuted instantiation: ostream-file.c:o_stream_uncork_flush
Unexecuted instantiation: iostream.c:o_stream_uncork_flush
179
180
/* Set "flush pending" state of stream. If set, the flush callback is called
181
   when more data is allowed to be sent, even if the buffer itself is empty.
182
   Note that if the stream is corked, the flush callback won't be called until
183
   the stream is first uncorked. */
184
void o_stream_set_flush_pending(struct ostream *stream, bool set);
185
/* Returns the number of bytes currently in all the pending write buffers of
186
   this ostream, including its parent streams. This function is commonly used
187
   by callers to determine when they've filled up the ostream so they can stop
188
   writing to it. Because of this, the return value shouldn't include buffers
189
   that are expected to be filled up before they send anything to their parent
190
   stream. Otherwise the callers may stop writing to the stream too early and
191
   hang. Such an example could be a compression ostream that won't send
192
   anything to its parent stream before an internal compression buffer is
193
   full. */
194
size_t o_stream_get_buffer_used_size(const struct ostream *stream) ATTR_PURE;
195
/* Returns the (minimum) number of bytes we can still write without failing.
196
   This is commonly used by callers to find out how many bytes they're
197
   guaranteed to be able to send, and then generate that much data and send
198
   it. */
199
size_t o_stream_get_buffer_avail_size(const struct ostream *stream) ATTR_PURE;
200
201
/* Seek to specified position from beginning of file. This works only for
202
   files. Returns 1 if successful, -1 if error. */
203
int o_stream_seek(struct ostream *stream, uoff_t offset);
204
/* Returns number of bytes sent, -1 = error */
205
ssize_t o_stream_send(struct ostream *stream, const void *data, size_t size)
206
  ATTR_WARN_UNUSED_RESULT;
207
ssize_t o_stream_sendv(struct ostream *stream, const struct const_iovec *iov,
208
           unsigned int iov_count) ATTR_WARN_UNUSED_RESULT;
209
ssize_t o_stream_send_str(struct ostream *stream, const char *str)
210
  ATTR_WARN_UNUSED_RESULT;
211
/* Send with delayed error handling. o_stream_flush() or
212
   o_stream_ignore_last_errors() must be called after these functions before
213
   the stream is destroyed. If any of the data can't be sent due to stream's
214
   buffer getting full, all further nsends are ignores and o_stream_flush()
215
   will fail. */
216
void o_stream_nsend(struct ostream *stream, const void *data, size_t size);
217
void o_stream_nsendv(struct ostream *stream, const struct const_iovec *iov,
218
         unsigned int iov_count);
219
void o_stream_nsend_str(struct ostream *stream, const char *str);
220
/* Mark the ostream as finished and flush it. If the ostream has a footer,
221
   it's written here. Any further write attempts to the ostream will
222
   assert-crash. Returns the same as o_stream_flush(). Afterwards any calls to
223
   this function are identical to o_stream_flush(). */
224
int o_stream_finish(struct ostream *stream);
225
/* Specify whether calling o_stream_finish() will cause the parent stream to
226
   be finished as well. The default is yes. */
227
void o_stream_set_finish_also_parent(struct ostream *stream, bool set);
228
/* Specify whether calling o_stream_finish() on a child stream will cause
229
   this stream to be finished as well. The default is yes. */
230
void o_stream_set_finish_via_child(struct ostream *stream, bool set);
231
/* Marks the stream's error handling as completed to avoid i_panic() on
232
   destroy. */
233
void o_stream_ignore_last_errors(struct ostream *stream);
234
/* Abort writing to the ostream, also marking any previous error handling as
235
   completed. If the stream hasn't already failed, sets the stream_errno=EPIPE.
236
   This is necessary when aborting write to streams that require finishing. */
237
void o_stream_abort(struct ostream *stream);
238
/* If error handling is disabled, the i_panic() on destroy is never called.
239
   This function can be called immediately after the stream is created.
240
   When creating wrapper streams, they copy this behavior from the parent
241
   stream. */
242
void o_stream_set_no_error_handling(struct ostream *stream, bool set);
243
/* Send all of the instream to outstream.
244
245
   On non-failure instream is skips over all data written to outstream.
246
   This means that the number of bytes written to outstream is always equal to
247
   the number of bytes skipped in instream.
248
249
   It's also possible to use this function to copy data within same file
250
   descriptor, even if the source and destination overlaps. If the file must
251
   be grown, you have to do it manually before calling this function. */
252
enum ostream_send_istream_result ATTR_WARN_UNUSED_RESULT
253
o_stream_send_istream(struct ostream *outstream, struct istream *instream);
254
/* Same as o_stream_send_istream(), but assume that reads and writes will
255
   succeed. If not, o_stream_flush() will fail with the correct error
256
   message (even istream's). */
257
void o_stream_nsend_istream(struct ostream *outstream, struct istream *instream);
258
259
/* Write data to specified offset. Returns 0 if successful, -1 if error. */
260
int o_stream_pwrite(struct ostream *stream, const void *data, size_t size,
261
        uoff_t offset);
262
263
/* Return the last timestamp when something was successfully sent to the
264
   ostream's internal buffers (no guarantees that anything was sent further).
265
   The timestamp is 0 if nothing has ever been written. */
266
void o_stream_get_last_write_time(struct ostream *stream, struct timeval *tv_r);
267
268
/* If there are any I/O loop items associated with the stream, move all of
269
   them to provided/current ioloop. */
270
void o_stream_switch_ioloop_to(struct ostream *stream, struct ioloop *ioloop);
271
void o_stream_switch_ioloop(struct ostream *stream);
272
273
#endif