Coverage Report

Created: 2026-03-19 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/bio/fd.cc
Line
Count
Source
1
// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include <openssl/bio.h>
16
17
#if !defined(OPENSSL_NO_POSIX_IO)
18
19
#include <errno.h>
20
#include <string.h>
21
22
#if !defined(OPENSSL_WINDOWS)
23
#include <unistd.h>
24
#else
25
#include <io.h>
26
#endif
27
28
#include <openssl/err.h>
29
#include <openssl/mem.h>
30
31
#include "internal.h"
32
#include "../internal.h"
33
34
35
#if defined(OPENSSL_WINDOWS)
36
  #define BORINGSSL_CLOSE _close
37
  #define BORINGSSL_LSEEK _lseek
38
  #define BORINGSSL_READ _read
39
  #define BORINGSSL_WRITE _write
40
#else
41
0
  #define BORINGSSL_CLOSE close
42
0
  #define BORINGSSL_LSEEK lseek
43
0
  #define BORINGSSL_READ read
44
0
  #define BORINGSSL_WRITE write
45
#endif
46
47
using namespace bssl;
48
49
0
BIO *BIO_new_fd(int fd, int close_flag) {
50
0
  BIO *ret = BIO_new(BIO_s_fd());
51
0
  if (ret == nullptr) {
52
0
    return nullptr;
53
0
  }
54
0
  BIO_set_fd(ret, fd, close_flag);
55
0
  return ret;
56
0
}
57
58
0
static int fd_new(BIO *bio) {
59
  // num is used to store the file descriptor.
60
0
  FromOpaque(bio)->num = -1;
61
0
  return 1;
62
0
}
63
64
0
static int fd_free(BIO *bio) {
65
0
  if (BIO_get_shutdown(bio)) {
66
0
    if (BIO_get_init(bio)) {
67
0
      BORINGSSL_CLOSE(FromOpaque(bio)->num);
68
0
    }
69
0
    BIO_set_init(bio, 0);
70
0
  }
71
0
  return 1;
72
0
}
73
74
0
static int fd_read(BIO *b, char *out, int outl) {
75
0
  int ret = 0;
76
77
0
  ret = (int)BORINGSSL_READ(FromOpaque(b)->num, out, outl);
78
0
  BIO_clear_retry_flags(b);
79
0
  if (ret <= 0) {
80
0
    if (bio_errno_should_retry(ret)) {
81
0
      BIO_set_retry_read(b);
82
0
    }
83
0
  }
84
85
0
  return ret;
86
0
}
87
88
0
static int fd_write(BIO *b, const char *in, int inl) {
89
0
  int ret = (int)BORINGSSL_WRITE(FromOpaque(b)->num, in, inl);
90
0
  BIO_clear_retry_flags(b);
91
0
  if (ret <= 0) {
92
0
    if (bio_errno_should_retry(ret)) {
93
0
      BIO_set_retry_write(b);
94
0
    }
95
0
  }
96
97
0
  return ret;
98
0
}
99
100
0
static long fd_ctrl(BIO *b, int cmd, long num, void *ptr) {
101
0
  switch (cmd) {
102
0
    case BIO_CTRL_RESET:
103
0
      num = 0;
104
0
      [[fallthrough]];
105
0
    case BIO_C_FILE_SEEK:
106
0
      if (BIO_get_init(b)) {
107
0
        return (long)BORINGSSL_LSEEK(FromOpaque(b)->num, num, SEEK_SET);
108
0
      }
109
0
      return 0;
110
0
    case BIO_C_FILE_TELL:
111
0
    case BIO_CTRL_INFO:
112
0
      if (BIO_get_init(b)) {
113
0
        return (long)BORINGSSL_LSEEK(FromOpaque(b)->num, 0, SEEK_CUR);
114
0
      }
115
0
      return 0;
116
0
    case BIO_C_SET_FD:
117
0
      fd_free(b);
118
0
      FromOpaque(b)->num = *static_cast<int *>(ptr);
119
0
      BIO_set_shutdown(b, static_cast<int>(num));
120
0
      BIO_set_init(b, 1);
121
0
      return 1;
122
0
    case BIO_C_GET_FD:
123
0
      if (BIO_get_init(b)) {
124
0
        int *out = static_cast<int *>(ptr);
125
0
        if (out != nullptr) {
126
0
          *out = FromOpaque(b)->num;
127
0
        }
128
0
        return FromOpaque(b)->num;
129
0
      } else {
130
0
        return -1;
131
0
      }
132
0
    case BIO_CTRL_GET_CLOSE:
133
0
      return BIO_get_shutdown(b);
134
0
    case BIO_CTRL_SET_CLOSE:
135
0
      BIO_set_shutdown(b, static_cast<int>(num));
136
0
      return 1;
137
0
    case BIO_CTRL_FLUSH:
138
0
      return 1;
139
0
    default:
140
0
      return 0;
141
0
  }
142
0
}
143
144
0
static int fd_gets(BIO *bp, char *buf, int size) {
145
0
  if (size <= 0) {
146
0
    return 0;
147
0
  }
148
149
0
  char *ptr = buf;
150
0
  char *end = buf + size - 1;
151
0
  while (ptr < end && fd_read(bp, ptr, 1) > 0) {
152
0
    char c = ptr[0];
153
0
    ptr++;
154
0
    if (c == '\n') {
155
0
      break;
156
0
    }
157
0
  }
158
159
0
  ptr[0] = '\0';
160
161
  // The output length is bounded by |size|.
162
0
  return (int)(ptr - buf);
163
0
}
164
165
static const BIO_METHOD methods_fdp = {
166
    BIO_TYPE_FD, "file descriptor", fd_write,
167
    fd_read,     fd_gets,           fd_ctrl,
168
    fd_new,      fd_free,           /*callback_ctrl=*/nullptr,
169
};
170
171
0
const BIO_METHOD *BIO_s_fd() { return &methods_fdp; }
172
173
#endif  // OPENSSL_NO_POSIX_IO
174
175
0
int BIO_set_fd(BIO *bio, int fd, int close_flag) {
176
0
  return (int)BIO_int_ctrl(bio, BIO_C_SET_FD, close_flag, fd);
177
0
}
178
179
0
int BIO_get_fd(BIO *bio, int *out_fd) {
180
0
  return (int)BIO_ctrl(bio, BIO_C_GET_FD, 0, (char *) out_fd);
181
0
}