Coverage Report

Created: 2023-10-10 06:32

/src/dovecot/src/lib/istream-unix.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (c) 2014-2018 Dovecot authors, see the included COPYING file */
2
3
#include "lib.h"
4
#include "fdpass.h"
5
#include "istream-file-private.h"
6
#include "istream-unix.h"
7
8
struct unix_istream {
9
  struct file_istream fstream;
10
  bool next_read_fd;
11
  int read_fd;
12
};
13
14
static void
15
i_stream_unix_close(struct iostream_private *stream, bool close_parent)
16
0
{
17
0
  struct unix_istream *ustream =
18
0
    container_of(stream, struct unix_istream,
19
0
           fstream.istream.iostream);
20
21
0
  i_close_fd(&ustream->read_fd);
22
0
  i_stream_file_close(stream, close_parent);
23
0
}
24
25
static ssize_t i_stream_unix_read(struct istream_private *stream)
26
0
{
27
0
  struct unix_istream *ustream =
28
0
    container_of(stream, struct unix_istream, fstream.istream);
29
0
  size_t size;
30
0
  ssize_t ret;
31
32
0
  if (!ustream->next_read_fd)
33
0
    return i_stream_file_read(stream);
34
35
0
  i_assert(ustream->read_fd == -1);
36
0
  i_assert(ustream->fstream.skip_left == 0); /* not supported here.. */
37
0
  if (!i_stream_try_alloc(stream, 1, &size))
38
0
    return -2;
39
40
0
  ret = fd_read(stream->fd, stream->w_buffer + stream->pos, size,
41
0
          &ustream->read_fd);
42
0
  if (ustream->read_fd != -1)
43
0
    ustream->next_read_fd = FALSE;
44
45
0
  if (ret == 0) {
46
    /* EOF */
47
0
    stream->istream.eof = TRUE;
48
0
    ustream->fstream.seen_eof = TRUE;
49
0
    return -1;
50
0
  }
51
52
0
  if (unlikely(ret < 0)) {
53
0
    if ((errno == EINTR || errno == EAGAIN) &&
54
0
        !stream->istream.blocking) {
55
0
      return 0;
56
0
    } else {
57
0
      i_assert(errno != 0);
58
      /* if we get EBADF for a valid fd, it means something's
59
         really wrong and we'd better just crash. */
60
0
      i_assert(errno != EBADF);
61
0
      stream->istream.stream_errno = errno;
62
0
      return -1;
63
0
    }
64
0
  }
65
0
  stream->pos += ret;
66
0
  return ret;
67
0
}
68
69
struct istream *i_stream_create_unix(int fd, size_t max_buffer_size)
70
0
{
71
0
  struct unix_istream *ustream;
72
0
  struct istream *input;
73
74
0
  i_assert(fd != -1);
75
76
0
  ustream = i_new(struct unix_istream, 1);
77
0
  ustream->read_fd = -1;
78
0
  input = i_stream_create_file_common(&ustream->fstream, fd, NULL,
79
0
              max_buffer_size, FALSE);
80
0
  input->real_stream->iostream.close = i_stream_unix_close;
81
0
  input->real_stream->read = i_stream_unix_read;
82
0
  return input;
83
0
}
84
85
void i_stream_unix_set_read_fd(struct istream *input)
86
0
{
87
0
  struct unix_istream *ustream =
88
0
    container_of(input->real_stream, struct unix_istream,
89
0
           fstream.istream);
90
91
0
  ustream->next_read_fd = TRUE;
92
0
}
93
94
void i_stream_unix_unset_read_fd(struct istream *input)
95
0
{
96
0
  struct unix_istream *ustream =
97
0
    container_of(input->real_stream, struct unix_istream,
98
0
           fstream.istream);
99
100
0
  ustream->next_read_fd = FALSE;
101
0
}
102
103
int i_stream_unix_get_read_fd(struct istream *input)
104
0
{
105
0
  struct unix_istream *ustream =
106
0
    container_of(input->real_stream, struct unix_istream,
107
0
           fstream.istream);
108
0
  int fd;
109
110
0
  fd = ustream->read_fd;
111
0
  ustream->read_fd = -1;
112
0
  return fd;
113
0
}