1/* Copyright (c) 2000, 2011, Oracle and/or its affiliates.
2 Copyright (c) 2011, Monty Program Ab
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16
17#include "mysys_priv.h"
18#include "mysys_err.h"
19#include "my_base.h"
20#include <m_string.h>
21#include <errno.h>
22#ifndef _WIN32
23#include <unistd.h>
24#endif
25
26/*
27 Read a chunk of bytes from a file from a given position
28
29 SYNOPSIOS
30 my_pread()
31 Filedes File descriptor
32 Buffer Buffer to read data into
33 Count Number of bytes to read
34 offset Position to read from
35 MyFlags Flags
36
37 NOTES
38 This differs from the normal pread() call in that we don't care
39 to set the position in the file back to the original position
40 if the system doesn't support pread().
41
42 RETURN
43 (size_t) -1 Error
44 # Number of bytes read
45*/
46
47size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset,
48 myf MyFlags)
49{
50 size_t readbytes;
51 int error= 0;
52
53 DBUG_ENTER("my_pread");
54
55 DBUG_PRINT("my",("fd: %d Seek: %llu Buffer: %p Count: %lu MyFlags: %lu",
56 Filedes, (ulonglong)offset, Buffer, (ulong)Count, MyFlags));
57
58 if (!(MyFlags & (MY_WME | MY_FAE | MY_FNABP)))
59 MyFlags|= my_global_flags;
60
61 for (;;)
62 {
63 errno= 0; /* Linux, Windows don't reset this on EOF/success */
64#ifdef _WIN32
65 readbytes= my_win_pread(Filedes, Buffer, Count, offset);
66#else
67 readbytes= pread(Filedes, Buffer, Count, offset);
68#endif
69 error = (readbytes != Count);
70
71 if (error)
72 {
73 my_errno= errno ? errno : -1;
74 if (errno == 0 || (readbytes != (size_t) -1 &&
75 (MyFlags & (MY_NABP | MY_FNABP))))
76 my_errno= HA_ERR_FILE_TOO_SHORT;
77 DBUG_PRINT("warning",("Read only %d bytes off %u from %d, errno: %d",
78 (int) readbytes, (uint) Count,Filedes,my_errno));
79 if ((readbytes == 0 || readbytes == (size_t) -1) && errno == EINTR)
80 {
81 DBUG_PRINT("debug", ("my_pread() was interrupted and returned %d",
82 (int) readbytes));
83 continue; /* Interrupted */
84 }
85 if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
86 {
87 if (readbytes == (size_t) -1)
88 my_error(EE_READ,
89 MYF(ME_BELL | ME_WAITTANG | (MyFlags & (ME_JUST_INFO | ME_NOREFRESH))),
90 my_filename(Filedes),my_errno);
91 else if (MyFlags & (MY_NABP | MY_FNABP))
92 my_error(EE_EOFERR,
93 MYF(ME_BELL | ME_WAITTANG | (MyFlags & (ME_JUST_INFO | ME_NOREFRESH))),
94 my_filename(Filedes),my_errno);
95 }
96 if (readbytes == (size_t) -1 || (MyFlags & (MY_FNABP | MY_NABP)))
97 DBUG_RETURN(MY_FILE_ERROR); /* Return with error */
98 }
99 if (MyFlags & (MY_NABP | MY_FNABP))
100 DBUG_RETURN(0); /* Read went ok; Return 0 */
101 DBUG_RETURN(readbytes); /* purecov: inspected */
102 }
103} /* my_pread */
104
105
106/*
107 Write a chunk of bytes to a file at a given position
108
109 SYNOPSIOS
110 my_pwrite()
111 Filedes File descriptor
112 Buffer Buffer to write data from
113 Count Number of bytes to write
114 offset Position to write to
115 MyFlags Flags
116
117 NOTES
118 This differs from the normal pwrite() call in that we don't care
119 to set the position in the file back to the original position
120 if the system doesn't support pwrite()
121
122 RETURN
123 (size_t) -1 Error
124 # Number of bytes read
125*/
126
127size_t my_pwrite(int Filedes, const uchar *Buffer, size_t Count,
128 my_off_t offset, myf MyFlags)
129{
130 size_t writtenbytes, written;
131 uint errors;
132 DBUG_ENTER("my_pwrite");
133 DBUG_PRINT("my",("fd: %d Seek: %llu Buffer: %p Count: %lu MyFlags: %lu",
134 Filedes, (ulonglong)offset, Buffer, (ulong)Count, MyFlags));
135 errors= 0;
136 written= 0;
137 if (!(MyFlags & (MY_WME | MY_FAE | MY_FNABP)))
138 MyFlags|= my_global_flags;
139
140 for (;;)
141 {
142#ifdef _WIN32
143 writtenbytes= my_win_pwrite(Filedes, Buffer, Count,offset);
144#else
145 writtenbytes= pwrite(Filedes, Buffer, Count, offset);
146#endif
147 if (writtenbytes == Count)
148 break;
149 my_errno= errno;
150 if (writtenbytes != (size_t) -1)
151 { /* Safegueard */
152 written+=writtenbytes;
153 Buffer+=writtenbytes;
154 Count-=writtenbytes;
155 offset+=writtenbytes;
156 }
157 DBUG_PRINT("error",("Write only %u bytes", (uint) writtenbytes));
158#ifndef NO_BACKGROUND
159 if (my_thread_var->abort)
160 MyFlags&= ~ MY_WAIT_IF_FULL; /* End if aborted by user */
161 if ((my_errno == ENOSPC || my_errno == EDQUOT) &&
162 (MyFlags & MY_WAIT_IF_FULL))
163 {
164 wait_for_free_space(my_filename(Filedes), errors);
165 errors++;
166 continue;
167 }
168 if ((writtenbytes && writtenbytes != (size_t) -1) || my_errno == EINTR)
169 continue; /* Retry */
170#endif
171
172 /* Don't give a warning if it's ok that we only write part of the data */
173 if (MyFlags & (MY_NABP | MY_FNABP))
174 {
175 if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
176 my_error(EE_WRITE, MYF(ME_BELL | ME_WAITTANG | (MyFlags & (ME_JUST_INFO | ME_NOREFRESH))),
177 my_filename(Filedes),my_errno);
178 DBUG_RETURN(MY_FILE_ERROR); /* Error on write */
179 }
180 break; /* Return bytes written */
181 }
182 DBUG_EXECUTE_IF("check", my_seek(Filedes, -1, SEEK_SET, MYF(0)););
183 if (MyFlags & (MY_NABP | MY_FNABP))
184 DBUG_RETURN(0); /* Want only errors */
185 DBUG_RETURN(writtenbytes+written); /* purecov: inspected */
186} /* my_pwrite */
187