Cross Reference: /dovecot/src/lib/istream.c
istream.c revision 4aa7fe81503a20bc972ae625da4dd9e6996fbdbf
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "lib.h"
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen#include "ioloop.h"
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen#include "str.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "istream-internal.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainenvoid i_stream_destroy(struct istream **stream)
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen{
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen i_stream_close(*stream);
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen i_stream_unref(stream);
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen}
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenvoid i_stream_ref(struct istream *stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen io_stream_ref(&stream->real_stream->iostream);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenvoid i_stream_unref(struct istream **stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = (*stream)->real_stream;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (_stream->iostream.refcount == 1) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (_stream->line_str != NULL)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen str_free(&_stream->line_str);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen }
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen io_stream_unref(&(*stream)->real_stream->iostream);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen *stream = NULL;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen#undef i_stream_set_destroy_callback
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainenvoid i_stream_set_destroy_callback(struct istream *stream,
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen istream_callback_t *callback, void *context)
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen{
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen struct iostream_private *iostream = &stream->real_stream->iostream;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen iostream->destroy_callback = callback;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen iostream->destroy_context = context;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen}
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenint i_stream_get_fd(struct istream *stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return _stream->fd;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenvoid i_stream_close(struct istream *stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen io_stream_close(&stream->real_stream->iostream);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen stream->closed = TRUE;
7db932bd4934cd967eeae643300aef5b91caeaeaTimo Sirainen
7db932bd4934cd967eeae643300aef5b91caeaeaTimo Sirainen if (stream->stream_errno == 0)
74066569545099304b20e790df7c261883d1746bTimo Sirainen stream->stream_errno = ENOENT;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenvoid i_stream_set_max_buffer_size(struct istream *stream, size_t max_size)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen io_stream_set_max_buffer_size(&stream->real_stream->iostream, max_size);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainenvoid i_stream_set_return_partial_line(struct istream *stream, bool set)
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen{
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen stream->real_stream->return_nolf_line = set;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen}
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenssize_t i_stream_read(struct istream *stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen size_t old_size;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen ssize_t ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (unlikely(stream->closed))
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return -1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen stream->eof = FALSE;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen stream->stream_errno = 0;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen old_size = _stream->pos - _stream->skip;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen ret = _stream->read(_stream);
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen switch (ret) {
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen case -2:
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen i_assert(_stream->skip != _stream->pos);
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen break;
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen case -1:
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen if (stream->stream_errno != 0) {
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen /* error handling should be easier if we now just
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen assume the stream is now at EOF */
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen stream->eof = TRUE;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen } else {
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen i_assert(stream->eof);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen }
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen break;
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen case 0:
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen i_assert(!stream->blocking);
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen break;
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen default:
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen i_assert(ret > 0);
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen i_assert((size_t)ret+old_size == _stream->pos - _stream->skip);
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen break;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen }
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen return ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenssize_t i_stream_read_copy_from_parent(struct istream *istream)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen{
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen struct istream_private *stream = istream->real_stream;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen size_t pos;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen ssize_t ret;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen stream->pos -= stream->skip;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen stream->skip = 0;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen stream->buffer = i_stream_get_data(stream->parent, &pos);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen if (pos > stream->pos)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen ret = 0;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen else do {
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen if ((ret = i_stream_read(stream->parent)) == -2)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen return -2;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen stream->istream.stream_errno = stream->parent->stream_errno;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen stream->istream.eof = stream->parent->eof;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen stream->buffer = i_stream_get_data(stream->parent, &pos);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen /* check again, in case the parent stream had been seeked
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen backwards and the previous read() didn't get us far
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen enough. */
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen } while (pos <= stream->pos && ret > 0);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen ret = pos > stream->pos ? (ssize_t)(pos - stream->pos) :
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen (ret == 0 ? 0 : -1);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen stream->pos = pos;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen i_assert(ret != -1 || stream->istream.eof ||
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen stream->istream.stream_errno != 0);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen return ret;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen}
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenvoid i_stream_skip(struct istream *stream, uoff_t count)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen size_t data_size;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen data_size = _stream->pos - _stream->skip;
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen if (count <= data_size) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* within buffer */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen stream->v_offset += count;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen _stream->skip += count;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* have to seek forward */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen count -= data_size;
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen _stream->skip = _stream->pos;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen stream->v_offset += data_size;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (unlikely(stream->closed))
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen return;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen stream->stream_errno = 0;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen _stream->seek(_stream, stream->v_offset + count, FALSE);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainenstatic bool i_stream_can_optimize_seek(struct istream *stream)
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen{
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen uoff_t expected_offset;
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen if (stream->real_stream->parent == NULL)
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen return TRUE;
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen /* use the fast route only if the parent stream is at the
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen expected offset */
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen expected_offset = stream->real_stream->parent_start_offset +
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen stream->v_offset - stream->real_stream->skip;
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen if (stream->real_stream->parent->v_offset != expected_offset)
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen return FALSE;
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen return i_stream_can_optimize_seek(stream->real_stream->parent);
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen}
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenvoid i_stream_seek(struct istream *stream, uoff_t v_offset)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen if (v_offset >= stream->v_offset &&
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen i_stream_can_optimize_seek(stream)) {
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen i_stream_skip(stream, v_offset - stream->v_offset);
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen return;
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen }
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (unlikely(stream->closed))
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen stream->eof = FALSE;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen _stream->seek(_stream, v_offset, FALSE);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen}
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainenvoid i_stream_seek_mark(struct istream *stream, uoff_t v_offset)
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (unlikely(stream->closed))
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen return;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen stream->eof = FALSE;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen _stream->seek(_stream, v_offset, TRUE);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainenvoid i_stream_sync(struct istream *stream)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (unlikely(stream->closed))
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen return;
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (_stream->sync != NULL)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen _stream->sync(_stream);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen}
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenconst struct stat *i_stream_stat(struct istream *stream, bool exact)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (unlikely(stream->closed))
548e394330621952db0f03dd667b70184c4a37b6Timo Sirainen return NULL;
548e394330621952db0f03dd667b70184c4a37b6Timo Sirainen
7d207b1e77a7b5e3fda640e353acfc86d261fedfTimo Sirainen return _stream->stat(_stream, exact);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen}
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainenint i_stream_get_size(struct istream *stream, bool exact, uoff_t *size_r)
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen{
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen struct istream_private *_stream = stream->real_stream;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen if (unlikely(stream->closed))
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen return -1;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen return _stream->get_size(_stream, exact, size_r);
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen}
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenbool i_stream_have_bytes_left(const struct istream *stream)
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen{
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen const struct istream_private *_stream = stream->real_stream;
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen return !stream->eof || _stream->skip != _stream->pos;
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen}
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainenbool i_stream_is_eof(struct istream *stream)
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen{
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen const struct istream_private *_stream = stream->real_stream;
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen if (_stream->skip == _stream->pos)
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen (void)i_stream_read(stream);
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen return !i_stream_have_bytes_left(stream);
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen}
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstatic char *i_stream_next_line_finish(struct istream_private *stream, size_t i)
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen{
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen char *ret;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen size_t end;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (i > 0 && stream->buffer[i-1] == '\r')
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen end = i - 1;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen else
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen end = i;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (stream->w_buffer != NULL) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen /* modify the buffer directly */
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen stream->w_buffer[end] = '\0';
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen ret = (char *)stream->w_buffer + stream->skip;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen } else {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen /* use a temporary string to return it */
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (stream->line_str == NULL)
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen stream->line_str = str_new(default_pool, 256);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen str_truncate(stream->line_str, 0);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen str_append_n(stream->line_str, stream->buffer + stream->skip,
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen end - stream->skip);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen ret = str_c_modifiable(stream->line_str);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen }
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen if (i < stream->pos)
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen i++;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen stream->istream.v_offset += i - stream->skip;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen stream->skip = i;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen return ret;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen}
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainenstatic char *i_stream_last_line(struct istream_private *_stream)
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen{
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen if (_stream->istream.eof && _stream->skip != _stream->pos &&
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen _stream->return_nolf_line) {
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen /* the last line is missing LF and we want to return it. */
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen return i_stream_next_line_finish(_stream, _stream->pos);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen }
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen return NULL;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen}
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenchar *i_stream_next_line(struct istream *stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen char *ret_buf;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen size_t i;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
0611067f385a37773800225256dcd5cf6aa34212Timo Sirainen if (_stream->skip >= _stream->pos) {
0611067f385a37773800225256dcd5cf6aa34212Timo Sirainen stream->stream_errno = 0;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return NULL;
0611067f385a37773800225256dcd5cf6aa34212Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (unlikely(_stream->w_buffer == NULL)) {
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen i_error("i_stream_next_line() called for unmodifiable stream");
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return NULL;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
5254d77805cd35b9356d072ba325c356c43b0d51Timo Sirainen /* @UNSAFE */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ret_buf = NULL;
3e25b17126e9536736d5da03697613e4c3af5f76Timo Sirainen for (i = _stream->skip; i < _stream->pos; i++) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (_stream->buffer[i] == 10) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* got it */
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen ret_buf = i_stream_next_line_finish(_stream, i);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen break;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen if (ret_buf == NULL)
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen return i_stream_last_line(_stream);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return ret_buf;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainenchar *i_stream_read_next_line(struct istream *stream)
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen{
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen char *line;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen for (;;) {
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen line = i_stream_next_line(stream);
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen if (line != NULL)
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen break;
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen if (i_stream_read(stream) <= 0)
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen return i_stream_last_line(stream->real_stream);
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen }
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen return line;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen}
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenconst unsigned char *
68a4946b12583b88fa802e52ebee45cd96056772Timo Siraineni_stream_get_data(const struct istream *stream, size_t *size_r)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen const struct istream_private *_stream = stream->real_stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (_stream->skip >= _stream->pos) {
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen *size_r = 0;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return NULL;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen *size_r = _stream->pos - _stream->skip;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return _stream->buffer + _stream->skip;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenunsigned char *i_stream_get_modifiable_data(const struct istream *stream,
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen size_t *size_r)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen const struct istream_private *_stream = stream->real_stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (_stream->skip >= _stream->pos || _stream->w_buffer == NULL) {
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen *size_r = 0;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return NULL;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen *size_r = _stream->pos - _stream->skip;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return _stream->w_buffer + _stream->skip;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainenint i_stream_read_data(struct istream *stream, const unsigned char **data_r,
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen size_t *size_r, size_t threshold)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ssize_t ret = 0;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen bool read_more = FALSE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen do {
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen *data_r = i_stream_get_data(stream, size_r);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen if (*size_r > threshold)
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen return 1;
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* we need more data */
f4bbeadda12fbd7c219063db68f3e78646d83c2cTimo Sirainen ret = i_stream_read(stream);
0b47e9f5e0181053b4d9ca7b426b0e5c185e820eTimo Sirainen if (ret > 0)
0b47e9f5e0181053b4d9ca7b426b0e5c185e820eTimo Sirainen read_more = TRUE;
abe8754852e70763e92f74caabbcc13d0917714cTimo Sirainen } while (ret > 0);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen *data_r = i_stream_get_data(stream, size_r);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen if (ret == -2)
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen return -2;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen
90b8f131849540fa374aede95edd86d47d35c09dTimo Sirainen if (ret == 0) {
90b8f131849540fa374aede95edd86d47d35c09dTimo Sirainen /* need to read more */
90b8f131849540fa374aede95edd86d47d35c09dTimo Sirainen i_assert(!stream->blocking);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen return 0;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen }
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen if (stream->eof) {
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen if (read_more) {
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen /* we read at least some new data */
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen return 0;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen }
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen } else {
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen i_assert(stream->stream_errno != 0);
90b8f131849540fa374aede95edd86d47d35c09dTimo Sirainen }
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen return -1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenvoid i_stream_compress(struct istream_private *stream)
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen{
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen memmove(stream->w_buffer, stream->w_buffer + stream->skip,
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen stream->pos - stream->skip);
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen stream->pos -= stream->skip;
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen stream->skip = 0;
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen}
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenvoid i_stream_grow_buffer(struct istream_private *stream, size_t bytes)
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen{
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen size_t old_size;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen old_size = stream->buffer_size;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen stream->buffer_size = stream->pos + bytes;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen if (stream->buffer_size <= I_STREAM_MIN_SIZE)
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen stream->buffer_size = I_STREAM_MIN_SIZE;
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen else
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen stream->buffer_size = nearest_power(stream->buffer_size);
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen if (stream->max_buffer_size > 0 &&
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen stream->buffer_size > stream->max_buffer_size)
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen stream->buffer_size = stream->max_buffer_size;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen stream->buffer = stream->w_buffer =
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen i_realloc(stream->w_buffer, old_size, stream->buffer_size);
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen}
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen
14175321ddb88619015866978c05a27786ca4814Timo Sirainenbool i_stream_get_buffer_space(struct istream_private *stream,
14175321ddb88619015866978c05a27786ca4814Timo Sirainen size_t wanted_size, size_t *size_r)
14175321ddb88619015866978c05a27786ca4814Timo Sirainen{
14175321ddb88619015866978c05a27786ca4814Timo Sirainen i_assert(wanted_size > 0);
14175321ddb88619015866978c05a27786ca4814Timo Sirainen
14175321ddb88619015866978c05a27786ca4814Timo Sirainen if (wanted_size > stream->buffer_size - stream->pos) {
14175321ddb88619015866978c05a27786ca4814Timo Sirainen if (stream->skip > 0) {
14175321ddb88619015866978c05a27786ca4814Timo Sirainen /* remove the unused bytes from beginning of buffer */
14175321ddb88619015866978c05a27786ca4814Timo Sirainen i_stream_compress(stream);
14175321ddb88619015866978c05a27786ca4814Timo Sirainen } else if (stream->max_buffer_size == 0 ||
14175321ddb88619015866978c05a27786ca4814Timo Sirainen stream->buffer_size < stream->max_buffer_size) {
14175321ddb88619015866978c05a27786ca4814Timo Sirainen /* buffer is full - grow it */
14175321ddb88619015866978c05a27786ca4814Timo Sirainen i_stream_grow_buffer(stream, I_STREAM_MIN_SIZE);
14175321ddb88619015866978c05a27786ca4814Timo Sirainen }
14175321ddb88619015866978c05a27786ca4814Timo Sirainen }
14175321ddb88619015866978c05a27786ca4814Timo Sirainen
14175321ddb88619015866978c05a27786ca4814Timo Sirainen if (size_r != NULL)
14175321ddb88619015866978c05a27786ca4814Timo Sirainen *size_r = stream->buffer_size - stream->pos;
14175321ddb88619015866978c05a27786ca4814Timo Sirainen return stream->pos != stream->buffer_size;
14175321ddb88619015866978c05a27786ca4814Timo Sirainen}
14175321ddb88619015866978c05a27786ca4814Timo Sirainen
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainenbool i_stream_add_data(struct istream *_stream, const unsigned char *data,
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen size_t size)
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen{
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen struct istream_private *stream = _stream->real_stream;
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen size_t size2;
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen (void)i_stream_get_buffer_space(stream, size, &size2);
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen if (size > size2)
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen return FALSE;
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen memcpy(stream->w_buffer + stream->pos, data, size);
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen stream->pos += size;
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen return TRUE;
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen}
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstatic void
a94936bafd127680184da114c6a177b37ff656e5Timo Siraineni_stream_default_set_max_buffer_size(struct iostream_private *stream,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen size_t max_size)
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = (struct istream_private *)stream;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen _stream->max_buffer_size = max_size;
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen if (_stream->parent != NULL)
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen i_stream_set_max_buffer_size(_stream->parent, max_size);
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen}
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainenstatic void i_stream_default_destroy(struct iostream_private *stream)
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen{
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen struct istream_private *_stream = (struct istream_private *)stream;
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen i_free(_stream->w_buffer);
4aa7fe81503a20bc972ae625da4dd9e6996fbdbfTimo Sirainen if (_stream->parent != NULL)
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen i_stream_unref(&_stream->parent);
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen}
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainenstatic void
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Siraineni_stream_default_seek(struct istream_private *stream,
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen uoff_t v_offset, bool mark ATTR_UNUSED)
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen{
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen size_t available;
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen if (stream->istream.v_offset > v_offset)
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen i_panic("stream doesn't support seeking backwards");
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen while (stream->istream.v_offset < v_offset) {
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen (void)i_stream_read(&stream->istream);
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen available = stream->pos - stream->skip;
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen if (available == 0) {
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen stream->istream.stream_errno = ESPIPE;
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen return;
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen }
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen if (available <= v_offset - stream->istream.v_offset)
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen i_stream_skip(&stream->istream, available);
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen else {
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen i_stream_skip(&stream->istream,
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen v_offset - stream->istream.v_offset);
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen }
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen }
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen}
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainenstatic const struct stat *
a94936bafd127680184da114c6a177b37ff656e5Timo Siraineni_stream_default_stat(struct istream_private *stream, bool exact ATTR_UNUSED)
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen{
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen return &stream->statbuf;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen}
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainenstatic int
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Siraineni_stream_default_get_size(struct istream_private *stream,
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen bool exact, uoff_t *size_r)
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen{
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen const struct stat *st;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen st = stream->stat(stream, 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
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainenstruct istream *
9511a40d933181045343110c8101b75887062aaeTimo Siraineni_stream_create(struct istream_private *_stream, struct istream *parent, int fd)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen _stream->fd = fd;
9511a40d933181045343110c8101b75887062aaeTimo Sirainen if (parent != NULL) {
9511a40d933181045343110c8101b75887062aaeTimo Sirainen _stream->parent = parent;
9511a40d933181045343110c8101b75887062aaeTimo Sirainen _stream->parent_start_offset = parent->v_offset;
9511a40d933181045343110c8101b75887062aaeTimo Sirainen _stream->abs_start_offset = parent->v_offset +
9511a40d933181045343110c8101b75887062aaeTimo Sirainen parent->real_stream->abs_start_offset;
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen i_stream_ref(parent);
9511a40d933181045343110c8101b75887062aaeTimo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen _stream->istream.real_stream = _stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen if (_stream->iostream.destroy == NULL)
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen _stream->iostream.destroy = i_stream_default_destroy;
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen if (_stream->seek == NULL) {
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen i_assert(!_stream->istream.seekable);
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen _stream->seek = i_stream_default_seek;
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen }
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen if (_stream->stat == NULL)
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen _stream->stat = i_stream_default_stat;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen if (_stream->get_size == NULL)
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen _stream->get_size = i_stream_default_get_size;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen if (_stream->iostream.set_max_buffer_size == NULL) {
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen _stream->iostream.set_max_buffer_size =
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen i_stream_default_set_max_buffer_size;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen }
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen memset(&_stream->statbuf, 0, sizeof(_stream->statbuf));
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen _stream->statbuf.st_size = -1;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen _stream->statbuf.st_atime =
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen _stream->statbuf.st_mtime =
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen _stream->statbuf.st_ctime = ioloop_time;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen io_stream_init(&_stream->iostream);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return &_stream->istream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen#ifdef STREAM_TEST
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen/* gcc istream.c -o teststream liblib.a -Wall -DHAVE_CONFIG_H -DSTREAM_TEST -g */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen#include <fcntl.h>
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen#include <unistd.h>
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen#include "ostream.h"
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen#define BUF_VALUE(offset) \
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen (((offset) % 256) ^ ((offset) / 256))
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenstatic void check_buffer(const unsigned char *data, size_t size, size_t offset)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen{
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen size_t i;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen for (i = 0; i < size; i++)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(data[i] == BUF_VALUE(i+offset));
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen}
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenint main(void)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen{
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct istream *input, *l_input;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct ostream *output1, *output2;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen int i, fd1, fd2;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen unsigned char buf[1024];
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen const unsigned char *data;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen size_t size;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen lib_init();
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen fd1 = open("teststream.1", O_RDWR | O_CREAT | O_TRUNC, 0600);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (fd1 < 0)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_fatal("open() failed: %m");
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen fd2 = open("teststream.2", O_RDWR | O_CREAT | O_TRUNC, 0600);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (fd2 < 0)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_fatal("open() failed: %m");
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* write initial data */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen for (i = 0; i < sizeof(buf); i++)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen buf[i] = BUF_VALUE(i);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen write(fd1, buf, sizeof(buf));
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* test reading */
2526d52441ef368215ab6bf04fd0356d3b09d235Timo Sirainen input = i_stream_create_fd(fd1, 512, FALSE);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(i_stream_get_size(input) == sizeof(buf));
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(i_stream_read_data(input, &data, &size, 0) > 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(size == 512);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen check_buffer(data, size, 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_stream_seek(input, 256);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(i_stream_read_data(input, &data, &size, 0) > 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(size == 512);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen check_buffer(data, size, 256);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_stream_seek(input, 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(i_stream_read_data(input, &data, &size, 512) == -2);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(size == 512);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen check_buffer(data, size, 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_stream_skip(input, 900);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(i_stream_read_data(input, &data, &size, 0) > 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(size == sizeof(buf) - 900);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen check_buffer(data, size, 900);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* test moving data */
2526d52441ef368215ab6bf04fd0356d3b09d235Timo Sirainen output1 = o_stream_create_fd(fd1, 512, FALSE);
2526d52441ef368215ab6bf04fd0356d3b09d235Timo Sirainen output2 = o_stream_create_fd(fd2, 512, FALSE);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_stream_seek(input, 1); size = sizeof(buf)-1;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(o_stream_send_istream(output2, input) == size);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen o_stream_flush(output2);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen lseek(fd2, 0, SEEK_SET);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(read(fd2, buf, sizeof(buf)) == size);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen check_buffer(buf, size, 1);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_stream_seek(input, 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen o_stream_seek(output1, sizeof(buf));
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(o_stream_send_istream(output1, input) == sizeof(buf));
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* test moving with limits */
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen l_input = i_stream_create_limit(input, sizeof(buf)/2, 512);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_stream_seek(l_input, 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen o_stream_seek(output1, 10);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(o_stream_send_istream(output1, l_input) == 512);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_stream_set_max_buffer_size(input, sizeof(buf));
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_stream_seek(input, 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(i_stream_read_data(input, &data, &size, sizeof(buf)-1) > 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(size == sizeof(buf));
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen check_buffer(data, 10, 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen check_buffer(data + 10, 512, sizeof(buf)/2);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen check_buffer(data + 10 + 512,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen size - (10 + 512), 10 + 512);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* reading within limits */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_stream_seek(l_input, 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(i_stream_read_data(l_input, &data, &size, 511) > 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(size == 512);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(i_stream_read_data(l_input, &data, &size, 512) == -2);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(size == 512);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_stream_skip(l_input, 511);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(i_stream_read_data(l_input, &data, &size, 0) > 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(size == 1);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_stream_skip(l_input, 1);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(i_stream_read_data(l_input, &data, &size, 0) == -1);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(size == 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen unlink("teststream.1");
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen unlink("teststream.2");
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen return 0;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen}
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen#endif