1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "istream-private.h"
#include "istream-nonuls.h"
struct nonuls_istream {
struct istream_private istream;
char replace_chr;
};
static int i_stream_read_parent(struct istream_private *stream)
{
ssize_t ret;
if (i_stream_get_data_size(stream->parent) > 0)
return 1;
ret = i_stream_read_memarea(stream->parent);
if (ret <= 0) {
stream->istream.stream_errno = stream->parent->stream_errno;
stream->istream.eof = stream->parent->eof;
return ret;
}
i_assert(i_stream_get_data_size(stream->parent) != 0);
return 1;
}
static ssize_t i_stream_nonuls_read(struct istream_private *stream)
{
struct nonuls_istream *nstream = (struct nonuls_istream *)stream;
const unsigned char *data, *p;
size_t i, size, avail_size;
int ret;
if ((ret = i_stream_read_parent(stream)) <= 0)
return ret;
data = i_stream_get_data(stream->parent, &size);
if (!i_stream_try_alloc(stream, size, &avail_size))
return -2;
if (size > avail_size)
size = avail_size;
i_assert(size > 0);
p = memchr(data, '\0', size);
if (p == NULL) {
/* no NULs in this block */
memcpy(stream->w_buffer+stream->pos, data, size);
} else {
i = p-data;
memcpy(stream->w_buffer+stream->pos, data, i);
for (; i < size; i++) {
stream->w_buffer[stream->pos+i] = data[i] == '\0' ?
nstream->replace_chr : data[i];
}
}
stream->pos += size;
i_stream_skip(stream->parent, size);
return size;
}
struct istream *i_stream_create_nonuls(struct istream *input, char replace_chr)
{
struct nonuls_istream *nstream;
nstream = i_new(struct nonuls_istream, 1);
nstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
nstream->istream.stream_size_passthrough = TRUE;
nstream->istream.read = i_stream_nonuls_read;
nstream->istream.istream.readable_fd = FALSE;
nstream->istream.istream.blocking = input->blocking;
nstream->istream.istream.seekable = FALSE;
nstream->replace_chr = replace_chr;
return i_stream_create(&nstream->istream, input,
i_stream_get_fd(input), 0);
}
|