Cross Reference: /dovecot/src/lib/istream-limit.c
istream-limit.c revision 5f5870385cff47efd2f58e7892f251cf13761528
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2003-2012 Dovecot authors, see the included COPYING file */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen#include "lib.h"
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include "istream-private.h"
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenstruct limit_istream {
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private istream;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
9511a40d933181045343110c8101b75887062aaeTimo Sirainen uoff_t v_size;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen};
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
4aa7fe81503a20bc972ae625da4dd9e6996fbdbfTimo Sirainenstatic void i_stream_limit_destroy(struct iostream_private *stream)
4aa7fe81503a20bc972ae625da4dd9e6996fbdbfTimo Sirainen{
4aa7fe81503a20bc972ae625da4dd9e6996fbdbfTimo Sirainen struct limit_istream *lstream = (struct limit_istream *) stream;
4aa7fe81503a20bc972ae625da4dd9e6996fbdbfTimo Sirainen uoff_t v_offset;
4aa7fe81503a20bc972ae625da4dd9e6996fbdbfTimo Sirainen
4aa7fe81503a20bc972ae625da4dd9e6996fbdbfTimo Sirainen v_offset = lstream->istream.parent_start_offset +
4aa7fe81503a20bc972ae625da4dd9e6996fbdbfTimo Sirainen lstream->istream.istream.v_offset;
4aa7fe81503a20bc972ae625da4dd9e6996fbdbfTimo Sirainen if (lstream->istream.parent->seekable ||
4aa7fe81503a20bc972ae625da4dd9e6996fbdbfTimo Sirainen v_offset > lstream->istream.parent->v_offset) {
4aa7fe81503a20bc972ae625da4dd9e6996fbdbfTimo Sirainen /* get to same position in parent stream */
4aa7fe81503a20bc972ae625da4dd9e6996fbdbfTimo Sirainen i_stream_seek(lstream->istream.parent, v_offset);
4aa7fe81503a20bc972ae625da4dd9e6996fbdbfTimo Sirainen }
4aa7fe81503a20bc972ae625da4dd9e6996fbdbfTimo Sirainen i_stream_unref(&lstream->istream.parent);
4aa7fe81503a20bc972ae625da4dd9e6996fbdbfTimo Sirainen}
4aa7fe81503a20bc972ae625da4dd9e6996fbdbfTimo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic ssize_t i_stream_limit_read(struct istream_private *stream)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen{
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct limit_istream *lstream = (struct limit_istream *) stream;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen uoff_t left;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen ssize_t ret;
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen size_t pos;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen if (stream->istream.v_offset +
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen (stream->pos - stream->skip) >= lstream->v_size) {
859cc94211b759825db5e15b0c88754da902ca14Timo Sirainen stream->istream.eof = TRUE;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen return -1;
859cc94211b759825db5e15b0c88754da902ca14Timo Sirainen }
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen i_stream_seek(stream->parent, lstream->istream.parent_start_offset +
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen stream->istream.v_offset);
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen stream->pos -= stream->skip;
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen stream->skip = 0;
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen stream->buffer = i_stream_get_data(stream->parent, &pos);
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen if (pos > stream->pos)
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen ret = 0;
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen else do {
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen if ((ret = i_stream_read(stream->parent)) == -2)
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen return -2;
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen stream->istream.stream_errno = stream->parent->stream_errno;
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen stream->istream.eof = stream->parent->eof;
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen stream->buffer = i_stream_get_data(stream->parent, &pos);
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen } while (pos <= stream->pos && ret > 0);
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen if (lstream->v_size != (uoff_t)-1) {
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen left = lstream->v_size - stream->istream.v_offset;
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen if (pos >= left) {
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen pos = left;
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen stream->istream.eof = TRUE;
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen }
1117aa7adc2909c750031fd7551a58a486d100d8Timo Sirainen }
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen ret = pos > stream->pos ? (ssize_t)(pos - stream->pos) :
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen (ret == 0 ? 0 : -1);
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen stream->pos = pos;
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen i_assert(ret != -1 || stream->istream.eof ||
8887a9bb6d2e3f664cf741b763643a0e5610fa4dTimo Sirainen stream->istream.stream_errno != 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen return ret;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen}
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic void i_stream_limit_seek(struct istream_private *stream, uoff_t v_offset,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen bool mark ATTR_UNUSED)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen{
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen stream->istream.v_offset = v_offset;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen stream->skip = stream->pos = 0;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen}
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic const struct stat *
a94936bafd127680184da114c6a177b37ff656e5Timo Siraineni_stream_limit_stat(struct istream_private *stream, bool exact)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen{
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct limit_istream *lstream = (struct limit_istream *) stream;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen const struct stat *st;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
1de2b5a16a455e018d8cbf72ee114d4b5d557a48Timo Sirainen st = i_stream_stat(stream->parent, exact);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (st == NULL)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen return NULL;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen stream->statbuf = *st;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (lstream->v_size != (uoff_t)-1)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen stream->statbuf.st_size = lstream->v_size;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen return &stream->statbuf;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen}
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainenstatic int i_stream_limit_get_size(struct istream_private *stream,
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen bool exact, uoff_t *size_r)
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen{
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen struct limit_istream *lstream = (struct limit_istream *) stream;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen const struct stat *st;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen if (lstream->v_size != (uoff_t)-1) {
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen *size_r = lstream->v_size;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen return 1;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen }
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen st = i_stream_stat(&stream->istream, exact);
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen if (st == NULL)
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen return -1;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen if (st->st_size == -1)
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen return 0;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen *size_r = st->st_size;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen return 1;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen}
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen
10c96a244935de4add8213ba0b894178dfb889a5Timo Sirainenstruct istream *i_stream_create_limit(struct istream *input, uoff_t v_size)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen{
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct limit_istream *lstream;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen lstream = i_new(struct limit_istream, 1);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen lstream->v_size = v_size;
597dba3488c648ffb375ee4a552bd52ac4346979Timo Sirainen lstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
4aa7fe81503a20bc972ae625da4dd9e6996fbdbfTimo Sirainen lstream->istream.iostream.destroy = i_stream_limit_destroy;
1de2b5a16a455e018d8cbf72ee114d4b5d557a48Timo Sirainen lstream->istream.parent = input;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen lstream->istream.read = i_stream_limit_read;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen lstream->istream.seek = i_stream_limit_seek;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen lstream->istream.stat = i_stream_limit_stat;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen lstream->istream.get_size = i_stream_limit_get_size;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
da2aa032ccfa8e7e4a4380ef738014549f4d2c2dTimo Sirainen lstream->istream.istream.readable_fd = input->readable_fd;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen lstream->istream.istream.blocking = input->blocking;
411d6baa37f31d90730e90c4a28c43e1974bbe58Timo Sirainen lstream->istream.istream.seekable = input->seekable;
9511a40d933181045343110c8101b75887062aaeTimo Sirainen return i_stream_create(&lstream->istream, input,
9511a40d933181045343110c8101b75887062aaeTimo Sirainen i_stream_get_fd(input));
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen}