~ubuntu-branches/ubuntu/utopic/dovecot/utopic-proposed

« back to all changes in this revision

Viewing changes to src/lib/istream.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-01-08 09:35:49 UTC
  • mfrom: (4.1.35 sid)
  • Revision ID: package-import@ubuntu.com-20140108093549-i72o93pux8p0dlaf
Tags: 1:2.2.9-1ubuntu1
* Merge from Debian unstable, remaining changes:
  + Add mail-stack-delivery package:
    - Update d/rules
    - d/control: convert existing dovecot-postfix package to a dummy
      package and add new mail-stack-delivery package.
    - Update maintainer scripts.
    - Rename d/dovecot-postfix.* to debian/mail-stack-delivery.*
    - d/mail-stack-delivery.preinst: Move previously installed backups and
      config files to a new package namespace.
    - d/mail-stack-delivery.prerm: Added to handle downgrades.
  + Use Snakeoil SSL certificates by default:
    - d/control: Depend on ssl-cert.
    - d/dovecot-core.postinst: Relax grep for SSL_* a bit.
  + Add autopkgtest to debian/tests/*.
  + Add ufw integration:
    - d/dovecot-core.ufw.profile: new ufw profile.
    - d/rules: install profile in dovecot-core.
    - d/control: dovecot-core - suggest ufw.
  + d/dovecot-core.dirs: Added usr/share/doc/dovecot-core
  + Add apport hook:
    - d/rules, d/source_dovecot.py
  + Add upstart job:
    - d/rules, d/dovecot-core.dovecot.upstart, d/control,
      d/dovecot-core.dirs, dovecot-imapd.{postrm, postinst, prerm},
      d/dovecot-pop3d.{postinst, postrm, prerm}.
      d/mail-stack-deliver.postinst: Convert init script to upstart.
  + Use the autotools-dev dh addon to update config.guess/config.sub for
    arm64.
* Dropped changes, included in Debian:
  - Update Dovecot name to reflect distribution in login greeting.
  - Update Drac plugin for >= 2.0.0 support.
* d/control: Drop dovecot-postfix package as its no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2002-2013 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "lib.h"
4
4
#include "ioloop.h"
 
5
#include "array.h"
5
6
#include "str.h"
6
7
#include "istream-private.h"
7
8
 
21
22
        return stream->real_stream->iostream.name;
22
23
}
23
24
 
 
25
static void i_stream_close_full(struct istream *stream, bool close_parents)
 
26
{
 
27
        io_stream_close(&stream->real_stream->iostream, close_parents);
 
28
        stream->closed = TRUE;
 
29
 
 
30
        if (stream->stream_errno == 0)
 
31
                stream->stream_errno = EPIPE;
 
32
}
 
33
 
24
34
void i_stream_destroy(struct istream **stream)
25
35
{
26
 
        i_stream_close(*stream);
 
36
        i_stream_close_full(*stream, FALSE);
27
37
        i_stream_unref(stream);
28
38
}
29
39
 
44
54
        *stream = NULL;
45
55
}
46
56
 
47
 
#undef i_stream_set_destroy_callback
48
 
void i_stream_set_destroy_callback(struct istream *stream,
 
57
#undef i_stream_add_destroy_callback
 
58
void i_stream_add_destroy_callback(struct istream *stream,
49
59
                                   istream_callback_t *callback, void *context)
50
60
{
51
61
        struct iostream_private *iostream = &stream->real_stream->iostream;
 
62
        struct iostream_destroy_callback *dc;
52
63
 
53
 
        iostream->destroy_callback = callback;
54
 
        iostream->destroy_context = context;
 
64
        if (!array_is_created(&iostream->destroy_callbacks))
 
65
                i_array_init(&iostream->destroy_callbacks, 2);
 
66
        dc = array_append_space(&iostream->destroy_callbacks);
 
67
        dc->callback = callback;
 
68
        dc->context = context;
55
69
}
56
70
 
57
 
void i_stream_unset_destroy_callback(struct istream *stream)
 
71
void i_stream_remove_destroy_callback(struct istream *stream,
 
72
                                      void (*callback)())
58
73
{
59
74
        struct iostream_private *iostream = &stream->real_stream->iostream;
 
75
        const struct iostream_destroy_callback *dcs;
 
76
        unsigned int i, count;
60
77
 
61
 
        iostream->destroy_callback = NULL;
62
 
        iostream->destroy_context = NULL;
 
78
        dcs = array_get(&iostream->destroy_callbacks, &count);
 
79
        for (i = 0; i < count; i++) {
 
80
                if (dcs[i].callback == callback) {
 
81
                        array_delete(&iostream->destroy_callbacks, i, 1);
 
82
                        return;
 
83
                }
 
84
        }
 
85
        i_unreached();
63
86
}
64
87
 
65
88
int i_stream_get_fd(struct istream *stream)
69
92
        return _stream->fd;
70
93
}
71
94
 
 
95
const char *i_stream_get_error(struct istream *stream)
 
96
{
 
97
        struct istream *s;
 
98
 
 
99
        /* we'll only return errors for streams that have stream_errno set.
 
100
           we might be returning unintended error otherwise. */
 
101
        if (stream->stream_errno == 0)
 
102
                return "<no error>";
 
103
 
 
104
        for (s = stream; s != NULL; s = s->real_stream->parent) {
 
105
                if (s->stream_errno == 0)
 
106
                        break;
 
107
                if (s->real_stream->iostream.error != NULL)
 
108
                        return s->real_stream->iostream.error;
 
109
        }
 
110
        return strerror(stream->stream_errno);
 
111
}
 
112
 
72
113
void i_stream_close(struct istream *stream)
73
114
{
74
 
        io_stream_close(&stream->real_stream->iostream);
75
 
        stream->closed = TRUE;
76
 
 
77
 
        if (stream->stream_errno == 0)
78
 
                stream->stream_errno = ENOENT;
 
115
        i_stream_close_full(stream, TRUE);
79
116
}
80
117
 
81
118
void i_stream_set_init_buffer_size(struct istream *stream, size_t size)
128
165
 
129
166
        old_size = _stream->pos - _stream->skip;
130
167
        ret = _stream->read(_stream);
 
168
        i_assert(old_size <= _stream->pos - _stream->skip);
131
169
        switch (ret) {
132
170
        case -2:
133
171
                i_assert(_stream->skip != _stream->pos);
140
178
                        errno = stream->stream_errno;
141
179
                } else {
142
180
                        i_assert(stream->eof);
 
181
                        i_assert(old_size == _stream->pos - _stream->skip);
143
182
                }
144
183
                break;
145
184
        case 0:
268
307
        }
269
308
}
270
309
 
271
 
const struct stat *i_stream_stat(struct istream *stream, bool exact)
 
310
int i_stream_stat(struct istream *stream, bool exact, const struct stat **st_r)
272
311
{
273
312
        struct istream_private *_stream = stream->real_stream;
274
313
 
275
314
        if (unlikely(stream->closed))
276
 
                return NULL;
 
315
                return -1;
277
316
 
278
 
        return _stream->stat(_stream, exact);
 
317
        if (_stream->stat(_stream, exact) < 0)
 
318
                return -1;
 
319
        *st_r = &_stream->statbuf;
 
320
        return 0;
279
321
}
280
322
 
281
323
int i_stream_get_size(struct istream *stream, bool exact, uoff_t *size_r)
314
356
        char *ret;
315
357
        size_t end;
316
358
 
317
 
        if (i > 0 && stream->buffer[i-1] == '\r')
 
359
        if (i > 0 && stream->buffer[i-1] == '\r') {
318
360
                end = i - 1;
319
 
        else
 
361
                stream->line_crlf = TRUE;
 
362
        } else {
320
363
                end = i;
 
364
                stream->line_crlf = FALSE;
 
365
        }
321
366
 
322
367
        if (stream->w_buffer != NULL) {
323
368
                /* modify the buffer directly */
356
401
        const unsigned char *pos;
357
402
 
358
403
        if (_stream->skip >= _stream->pos) {
359
 
                stream->stream_errno = 0;
 
404
                if (!unlikely(stream->closed))
 
405
                        stream->stream_errno = 0;
360
406
                return NULL;
361
407
        }
362
408
 
379
425
                if (line != NULL)
380
426
                        break;
381
427
 
382
 
                if (i_stream_read(stream) <= 0)
 
428
                switch (i_stream_read(stream)) {
 
429
                case -2:
 
430
                        stream->stream_errno = ENOBUFS;
 
431
                        stream->eof = TRUE;
 
432
                        return NULL;
 
433
                case -1:
383
434
                        return i_stream_last_line(stream->real_stream);
 
435
                case 0:
 
436
                        return NULL;
 
437
                }
384
438
        }
385
439
        return line;
386
440
}
387
441
 
 
442
bool i_stream_last_line_crlf(struct istream *stream)
 
443
{
 
444
        return stream->real_stream->line_crlf;
 
445
}
 
446
 
388
447
const unsigned char *
389
448
i_stream_get_data(const struct istream *stream, size_t *size_r)
390
449
{
399
458
        return _stream->buffer + _stream->skip;
400
459
}
401
460
 
 
461
size_t i_stream_get_data_size(const struct istream *stream)
 
462
{
 
463
        const struct istream_private *_stream = stream->real_stream;
 
464
 
 
465
        if (_stream->skip >= _stream->pos)
 
466
                return 0;
 
467
        else
 
468
                return _stream->pos - _stream->skip;
 
469
}
 
470
 
402
471
unsigned char *i_stream_get_modifiable_data(const struct istream *stream,
403
472
                                            size_t *size_r)
404
473
{
485
554
        }
486
555
}
487
556
 
488
 
bool i_stream_get_buffer_space(struct istream_private *stream,
489
 
                               size_t wanted_size, size_t *size_r)
 
557
bool i_stream_try_alloc(struct istream_private *stream,
 
558
                        size_t wanted_size, size_t *size_r)
490
559
{
491
560
        i_assert(wanted_size > 0);
492
561
 
501
570
                }
502
571
        }
503
572
 
504
 
        if (size_r != NULL)
505
 
                *size_r = stream->buffer_size - stream->pos;
506
 
        return stream->pos != stream->buffer_size;
 
573
        *size_r = stream->buffer_size - stream->pos;
 
574
        if (stream->try_alloc_limit > 0 &&
 
575
            *size_r > stream->try_alloc_limit)
 
576
                *size_r = stream->try_alloc_limit;
 
577
        return *size_r > 0;
 
578
}
 
579
 
 
580
void *i_stream_alloc(struct istream_private *stream, size_t size)
 
581
{
 
582
        size_t old_size, avail_size;
 
583
 
 
584
        i_stream_try_alloc(stream, size, &avail_size);
 
585
        if (avail_size < size) {
 
586
                old_size = stream->buffer_size;
 
587
                stream->buffer_size = nearest_power(stream->pos + size);
 
588
                stream->w_buffer = i_realloc(stream->w_buffer, old_size,
 
589
                                             stream->buffer_size);
 
590
                stream->buffer = stream->w_buffer;
 
591
                i_stream_try_alloc(stream, size, &avail_size);
 
592
                i_assert(avail_size >= size);
 
593
        }
 
594
        return stream->w_buffer + stream->pos;
507
595
}
508
596
 
509
597
bool i_stream_add_data(struct istream *_stream, const unsigned char *data,
512
600
        struct istream_private *stream = _stream->real_stream;
513
601
        size_t size2;
514
602
 
515
 
        (void)i_stream_get_buffer_space(stream, size, &size2);
 
603
        i_stream_try_alloc(stream, size, &size2);
516
604
        if (size > size2)
517
605
                return FALSE;
518
606
 
532
620
                i_stream_set_max_buffer_size(_stream->parent, max_size);
533
621
}
534
622
 
 
623
static void i_stream_default_close(struct iostream_private *stream,
 
624
                                   bool close_parent)
 
625
{
 
626
        struct istream_private *_stream = (struct istream_private *)stream;
 
627
 
 
628
        if (close_parent && _stream->parent != NULL)
 
629
                i_stream_close(_stream->parent);
 
630
}
 
631
 
535
632
static void i_stream_default_destroy(struct iostream_private *stream)
536
633
{
537
634
        struct istream_private *_stream = (struct istream_private *)stream;
541
638
                i_stream_unref(&_stream->parent);
542
639
}
543
640
 
544
 
void i_stream_default_seek(struct istream_private *stream,
545
 
                           uoff_t v_offset, bool mark ATTR_UNUSED)
 
641
static void
 
642
i_stream_default_seek_seekable(struct istream_private *stream,
 
643
                               uoff_t v_offset, bool mark ATTR_UNUSED)
 
644
{
 
645
        stream->istream.v_offset = v_offset;
 
646
        stream->skip = stream->pos = 0;
 
647
}
 
648
 
 
649
void i_stream_default_seek_nonseekable(struct istream_private *stream,
 
650
                                       uoff_t v_offset, bool mark ATTR_UNUSED)
546
651
{
547
652
        size_t available;
548
653
 
549
654
        if (stream->istream.v_offset > v_offset)
550
 
                i_panic("stream doesn't support seeking backwards");
 
655
                i_panic("stream %s doesn't support seeking backwards",
 
656
                        i_stream_get_name(&stream->istream));
551
657
 
552
658
        while (stream->istream.v_offset < v_offset) {
553
659
                (void)i_stream_read(&stream->istream);
566
672
        }
567
673
}
568
674
 
569
 
static const struct stat *
570
 
i_stream_default_stat(struct istream_private *stream, bool exact ATTR_UNUSED)
 
675
static int
 
676
i_stream_default_stat(struct istream_private *stream, bool exact)
571
677
{
572
 
        return &stream->statbuf;
 
678
        const struct stat *st;
 
679
 
 
680
        if (stream->parent == NULL)
 
681
                return stream->istream.stream_errno == 0 ? 0 : -1;
 
682
 
 
683
        if (i_stream_stat(stream->parent, exact, &st) < 0)
 
684
                return -1;
 
685
        stream->statbuf = *st;
 
686
        if (exact && !stream->stream_size_passthrough) {
 
687
                /* exact size is not known, even if parent returned something */
 
688
                stream->statbuf.st_size = -1;
 
689
        }
 
690
        return 0;
573
691
}
574
692
 
575
693
static int
576
694
i_stream_default_get_size(struct istream_private *stream,
577
695
                          bool exact, uoff_t *size_r)
578
696
{
579
 
        const struct stat *st;
580
 
 
581
 
        st = stream->stat(stream, exact);
582
 
        if (st == NULL)
 
697
        if (stream->stat(stream, exact) < 0)
583
698
                return -1;
584
 
        if (st->st_size == -1)
 
699
        if (stream->statbuf.st_size == -1)
585
700
                return 0;
586
701
 
587
 
        *size_r = st->st_size;
 
702
        *size_r = stream->statbuf.st_size;
588
703
        return 1;
589
704
}
590
705
 
 
706
void i_stream_init_parent(struct istream_private *_stream,
 
707
                          struct istream *parent)
 
708
{
 
709
        _stream->access_counter = parent->real_stream->access_counter;
 
710
        _stream->parent = parent;
 
711
        _stream->parent_start_offset = parent->v_offset;
 
712
        _stream->parent_expected_offset = parent->v_offset;
 
713
        _stream->abs_start_offset = parent->v_offset +
 
714
                parent->real_stream->abs_start_offset;
 
715
        /* if parent stream is an istream-error, copy the error */
 
716
        _stream->istream.stream_errno = parent->stream_errno;
 
717
        _stream->istream.eof = parent->eof;
 
718
        i_stream_ref(parent);
 
719
}
 
720
 
591
721
struct istream *
592
722
i_stream_create(struct istream_private *_stream, struct istream *parent, int fd)
593
723
{
594
724
        _stream->fd = fd;
595
 
        if (parent != NULL) {
596
 
                _stream->access_counter = parent->real_stream->access_counter;
597
 
                _stream->parent = parent;
598
 
                _stream->parent_start_offset = parent->v_offset;
599
 
                _stream->parent_expected_offset = parent->v_offset;
600
 
                _stream->abs_start_offset = parent->v_offset +
601
 
                        parent->real_stream->abs_start_offset;
602
 
                i_stream_ref(parent);
603
 
        }
 
725
        if (parent != NULL)
 
726
                i_stream_init_parent(_stream, parent);
604
727
        _stream->istream.real_stream = _stream;
605
728
 
 
729
        if (_stream->iostream.close == NULL)
 
730
                _stream->iostream.close = i_stream_default_close;
606
731
        if (_stream->iostream.destroy == NULL)
607
732
                _stream->iostream.destroy = i_stream_default_destroy;
608
733
        if (_stream->seek == NULL) {
609
 
                i_assert(!_stream->istream.seekable);
610
 
                _stream->seek = i_stream_default_seek;
 
734
                _stream->seek = _stream->istream.seekable ?
 
735
                        i_stream_default_seek_seekable :
 
736
                        i_stream_default_seek_nonseekable;
611
737
        }
612
738
        if (_stream->stat == NULL)
613
739
                _stream->stat = i_stream_default_stat;
629
755
        io_stream_init(&_stream->iostream);
630
756
        return &_stream->istream;
631
757
}
 
758
 
 
759
struct istream *i_stream_create_error(int stream_errno)
 
760
{
 
761
        struct istream_private *stream;
 
762
 
 
763
        stream = i_new(struct istream_private, 1);
 
764
        stream->istream.closed = TRUE;
 
765
        stream->istream.readable_fd = FALSE;
 
766
        stream->istream.blocking = TRUE;
 
767
        stream->istream.seekable = TRUE;
 
768
        stream->istream.eof = TRUE;
 
769
        stream->istream.stream_errno = stream_errno;
 
770
        i_stream_create(stream, NULL, -1);
 
771
        i_stream_set_name(&stream->istream, "(error)");
 
772
        return &stream->istream;
 
773
}
 
774
 
 
775
struct istream *
 
776
i_stream_create_error_str(int stream_errno, const char *fmt, ...)
 
777
{
 
778
        struct istream *input;
 
779
        va_list args;
 
780
 
 
781
        va_start(args, fmt);
 
782
        input = i_stream_create_error(stream_errno);
 
783
        io_stream_set_verror(&input->real_stream->iostream, fmt, args);
 
784
        va_end(args);
 
785
        return input;
 
786
}