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 | |
47 | size_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 | |
127 | size_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 | |