Coverage Report

Created: 2026-05-16 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mysql-server/mysys/my_read.cc
Line
Count
Source
1
/* Copyright (c) 2000, 2025, Oracle and/or its affiliates.
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License, version 2.0,
5
   as published by the Free Software Foundation.
6
7
   This program is designed to work with certain software (including
8
   but not limited to OpenSSL) that is licensed under separate terms,
9
   as designated in a particular file or component or in included license
10
   documentation.  The authors of MySQL hereby grant you an additional
11
   permission to link the program and your derivative works with the
12
   separately licensed software that they have either included with
13
   the program or referenced in the documentation.
14
15
   Without limiting anything contained in the foregoing, this file,
16
   which is part of C Driver for MySQL (Connector/C), is also subject to the
17
   Universal FOSS Exception, version 1.0, a copy of which can be found at
18
   http://oss.oracle.com/licenses/universal-foss-exception.
19
20
   This program is distributed in the hope that it will be useful,
21
   but WITHOUT ANY WARRANTY; without even the implied warranty of
22
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
   GNU General Public License, version 2.0, for more details.
24
25
   You should have received a copy of the GNU General Public License
26
   along with this program; if not, write to the Free Software
27
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
28
29
/**
30
  @file mysys/my_read.cc
31
*/
32
33
#include "my_config.h"
34
35
#include <sys/types.h>
36
#include <cerrno>
37
#include <cstddef>
38
#include <cstdint>
39
#ifdef HAVE_UNISTD_H
40
#include <unistd.h>
41
#endif
42
43
#include "my_base.h"
44
#include "my_dbug.h"
45
#include "my_inttypes.h"
46
#include "my_sys.h"
47
#include "my_thread_local.h"
48
#include "mysys_err.h"
49
#ifdef _WIN32
50
#include "mysys/mysys_priv.h"
51
#endif
52
53
#ifndef _WIN32
54
// Mock away read() for unit testing.
55
ssize_t (*mock_read)(int fd, void *buf, size_t count) = nullptr;
56
#endif
57
58
/**
59
   Read a chunk of bytes from a file with retry's if needed
60
   If flag MY_FULL_IO is set then keep reading until EOF is found.
61
62
   @param       fd       File descriptor to read from
63
   @param[out]  Buffer   Buffer to hold at least Count bytes
64
   @param       Count    Bytes to read
65
   @param       MyFlags  Flags on what to do on error
66
67
   @return Operation status
68
     @retval  -1  on error
69
     @retval   0  if flag has bits MY_NABP or MY_FNABP set
70
     @retval   N  number of bytes read
71
*/
72
73
0
size_t my_read(File fd, uchar *Buffer, size_t Count, myf MyFlags) {
74
0
  int64_t savedbytes = 0;
75
0
  DBUG_TRACE;
76
77
0
  for (;;) {
78
0
    errno = 0; /* Linux, Windows don't reset this on EOF/success */
79
0
    int64_t readbytes =
80
#ifdef _WIN32
81
        // Using my_win_pread() with offset -1 which will cause
82
        // ReadFile() to be called with nullptr for the OVERLAPPED
83
        // argument. This way we avoid having both my_win_read()
84
        // my_win_pread() which were identical except for the OVERLAPPED
85
        // arg passed to ReadFile().
86
        my_win_pread(fd, Buffer, Count, -1);
87
#else
88
0
        (mock_read ? mock_read(fd, Buffer, Count) : read(fd, Buffer, Count));
89
0
#endif
90
0
    DBUG_EXECUTE_IF("simulate_file_read_error", {
91
0
      errno = ENOSPC;
92
0
      readbytes = -1;
93
0
      DBUG_SET("-d,simulate_file_read_error");
94
0
      DBUG_SET("-d,simulate_my_b_fill_error");
95
0
    });
96
97
0
    if (readbytes != static_cast<int64_t>(Count)) {
98
0
      set_my_errno(errno);
99
0
      if (errno == 0 || (readbytes != -1 && (MyFlags & (MY_NABP | MY_FNABP))))
100
0
        set_my_errno(HA_ERR_FILE_TOO_SHORT);
101
102
0
      if ((readbytes == 0 || readbytes == -1) && errno == EINTR) {
103
0
        continue; /* Interrupted */
104
0
      }
105
106
0
      if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) {
107
0
        if (readbytes == -1)
108
0
          MyOsError(my_errno(), EE_READ, MYF(0), my_filename(fd));
109
0
        else if (MyFlags & (MY_NABP | MY_FNABP))
110
0
          MyOsError(my_errno(), EE_EOFERR, MYF(0), my_filename(fd));
111
0
      }
112
0
      if (readbytes == -1 ||
113
0
          ((MyFlags & (MY_FNABP | MY_NABP)) && !(MyFlags & MY_FULL_IO)))
114
0
        return MY_FILE_ERROR; /* Return with error */
115
      /* readbytes == 0 when EOF. No need to continue in case of EOF */
116
0
      if (readbytes != 0 && (MyFlags & MY_FULL_IO)) {
117
0
        Buffer += readbytes;
118
0
        Count -= readbytes;
119
0
        savedbytes += readbytes;
120
0
        continue;
121
0
      }
122
0
    }
123
124
0
    if (MyFlags & (MY_NABP | MY_FNABP))
125
0
      readbytes = 0; /* Ok on read */
126
0
    else if (MyFlags & MY_FULL_IO)
127
0
      readbytes += savedbytes;
128
129
0
    return readbytes;
130
0
  }  // for (;;)
131
0
}