OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/filesystem/file_impl.h" | 5 #include "components/filesystem/file_impl.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 #include <limits> | 9 #include <limits> |
10 #include <utility> | 10 #include <utility> |
(...skipping 30 matching lines...) Expand all Loading... |
41 FileImpl::~FileImpl() { | 41 FileImpl::~FileImpl() { |
42 } | 42 } |
43 | 43 |
44 void FileImpl::Close(const CloseCallback& callback) { | 44 void FileImpl::Close(const CloseCallback& callback) { |
45 if (!file_.IsValid()) { | 45 if (!file_.IsValid()) { |
46 callback.Run(GetError(file_)); | 46 callback.Run(GetError(file_)); |
47 return; | 47 return; |
48 } | 48 } |
49 | 49 |
50 file_.Close(); | 50 file_.Close(); |
51 callback.Run(FILE_ERROR_OK); | 51 callback.Run(FileError::OK); |
52 } | 52 } |
53 | 53 |
54 // TODO(vtl): Move the implementation to a thread pool. | 54 // TODO(vtl): Move the implementation to a thread pool. |
55 void FileImpl::Read(uint32_t num_bytes_to_read, | 55 void FileImpl::Read(uint32_t num_bytes_to_read, |
56 int64_t offset, | 56 int64_t offset, |
57 Whence whence, | 57 Whence whence, |
58 const ReadCallback& callback) { | 58 const ReadCallback& callback) { |
59 if (!file_.IsValid()) { | 59 if (!file_.IsValid()) { |
60 callback.Run(GetError(file_), mojo::Array<uint8_t>()); | 60 callback.Run(GetError(file_), mojo::Array<uint8_t>()); |
61 return; | 61 return; |
62 } | 62 } |
63 if (num_bytes_to_read > kMaxReadSize) { | 63 if (num_bytes_to_read > kMaxReadSize) { |
64 callback.Run(FILE_ERROR_INVALID_OPERATION, mojo::Array<uint8_t>()); | 64 callback.Run(FileError::INVALID_OPERATION, mojo::Array<uint8_t>()); |
65 return; | 65 return; |
66 } | 66 } |
67 if (FileError error = IsOffsetValid(offset)) { | 67 FileError error = IsOffsetValid(offset); |
| 68 if (error != FileError::OK) { |
68 callback.Run(error, mojo::Array<uint8_t>()); | 69 callback.Run(error, mojo::Array<uint8_t>()); |
69 return; | 70 return; |
70 } | 71 } |
71 if (FileError error = IsWhenceValid(whence)) { | 72 error = IsWhenceValid(whence); |
| 73 if (error != FileError::OK) { |
72 callback.Run(error, mojo::Array<uint8_t>()); | 74 callback.Run(error, mojo::Array<uint8_t>()); |
73 return; | 75 return; |
74 } | 76 } |
75 | 77 |
76 if (file_.Seek(static_cast<base::File::Whence>(whence), offset) == -1) { | 78 if (file_.Seek(static_cast<base::File::Whence>(whence), offset) == -1) { |
77 callback.Run(FILE_ERROR_FAILED, mojo::Array<uint8_t>()); | 79 callback.Run(FileError::FAILED, mojo::Array<uint8_t>()); |
78 return; | 80 return; |
79 } | 81 } |
80 | 82 |
81 mojo::Array<uint8_t> bytes_read(num_bytes_to_read); | 83 mojo::Array<uint8_t> bytes_read(num_bytes_to_read); |
82 int num_bytes_read = file_.ReadAtCurrentPos( | 84 int num_bytes_read = file_.ReadAtCurrentPos( |
83 reinterpret_cast<char*>(&bytes_read.front()), num_bytes_to_read); | 85 reinterpret_cast<char*>(&bytes_read.front()), num_bytes_to_read); |
84 if (num_bytes_read < 0) { | 86 if (num_bytes_read < 0) { |
85 callback.Run(FILE_ERROR_FAILED, mojo::Array<uint8_t>()); | 87 callback.Run(FileError::FAILED, mojo::Array<uint8_t>()); |
86 return; | 88 return; |
87 } | 89 } |
88 | 90 |
89 DCHECK_LE(static_cast<size_t>(num_bytes_read), num_bytes_to_read); | 91 DCHECK_LE(static_cast<size_t>(num_bytes_read), num_bytes_to_read); |
90 bytes_read.resize(static_cast<size_t>(num_bytes_read)); | 92 bytes_read.resize(static_cast<size_t>(num_bytes_read)); |
91 callback.Run(FILE_ERROR_OK, std::move(bytes_read)); | 93 callback.Run(FileError::OK, std::move(bytes_read)); |
92 } | 94 } |
93 | 95 |
94 // TODO(vtl): Move the implementation to a thread pool. | 96 // TODO(vtl): Move the implementation to a thread pool. |
95 void FileImpl::Write(mojo::Array<uint8_t> bytes_to_write, | 97 void FileImpl::Write(mojo::Array<uint8_t> bytes_to_write, |
96 int64_t offset, | 98 int64_t offset, |
97 Whence whence, | 99 Whence whence, |
98 const WriteCallback& callback) { | 100 const WriteCallback& callback) { |
99 DCHECK(!bytes_to_write.is_null()); | 101 DCHECK(!bytes_to_write.is_null()); |
100 if (!file_.IsValid()) { | 102 if (!file_.IsValid()) { |
101 callback.Run(GetError(file_), 0); | 103 callback.Run(GetError(file_), 0); |
102 return; | 104 return; |
103 } | 105 } |
104 // Who knows what |write()| would return if the size is that big (and it | 106 // Who knows what |write()| would return if the size is that big (and it |
105 // actually wrote that much). | 107 // actually wrote that much). |
106 if (bytes_to_write.size() > | 108 if (bytes_to_write.size() > |
107 #if defined(OS_WIN) | 109 #if defined(OS_WIN) |
108 static_cast<size_t>(std::numeric_limits<int>::max())) { | 110 static_cast<size_t>(std::numeric_limits<int>::max())) { |
109 #else | 111 #else |
110 static_cast<size_t>(std::numeric_limits<ssize_t>::max())) { | 112 static_cast<size_t>(std::numeric_limits<ssize_t>::max())) { |
111 #endif | 113 #endif |
112 callback.Run(FILE_ERROR_INVALID_OPERATION, 0); | 114 callback.Run(FileError::INVALID_OPERATION, 0); |
113 return; | 115 return; |
114 } | 116 } |
115 if (FileError error = IsOffsetValid(offset)) { | 117 FileError error = IsOffsetValid(offset); |
| 118 if (error != FileError::OK) { |
116 callback.Run(error, 0); | 119 callback.Run(error, 0); |
117 return; | 120 return; |
118 } | 121 } |
119 if (FileError error = IsWhenceValid(whence)) { | 122 error = IsWhenceValid(whence); |
| 123 if (error != FileError::OK) { |
120 callback.Run(error, 0); | 124 callback.Run(error, 0); |
121 return; | 125 return; |
122 } | 126 } |
123 | 127 |
124 if (file_.Seek(static_cast<base::File::Whence>(whence), offset) == -1) { | 128 if (file_.Seek(static_cast<base::File::Whence>(whence), offset) == -1) { |
125 callback.Run(FILE_ERROR_FAILED, 0); | 129 callback.Run(FileError::FAILED, 0); |
126 return; | 130 return; |
127 } | 131 } |
128 | 132 |
129 const char* buf = (bytes_to_write.size() > 0) | 133 const char* buf = (bytes_to_write.size() > 0) |
130 ? reinterpret_cast<char*>(&bytes_to_write.front()) | 134 ? reinterpret_cast<char*>(&bytes_to_write.front()) |
131 : nullptr; | 135 : nullptr; |
132 int num_bytes_written = file_.WriteAtCurrentPos( | 136 int num_bytes_written = file_.WriteAtCurrentPos( |
133 buf, static_cast<int>(bytes_to_write.size())); | 137 buf, static_cast<int>(bytes_to_write.size())); |
134 if (num_bytes_written < 0) { | 138 if (num_bytes_written < 0) { |
135 callback.Run(FILE_ERROR_FAILED, 0); | 139 callback.Run(FileError::FAILED, 0); |
136 return; | 140 return; |
137 } | 141 } |
138 | 142 |
139 DCHECK_LE(static_cast<size_t>(num_bytes_written), | 143 DCHECK_LE(static_cast<size_t>(num_bytes_written), |
140 std::numeric_limits<uint32_t>::max()); | 144 std::numeric_limits<uint32_t>::max()); |
141 callback.Run(FILE_ERROR_OK, static_cast<uint32_t>(num_bytes_written)); | 145 callback.Run(FileError::OK, static_cast<uint32_t>(num_bytes_written)); |
142 } | 146 } |
143 | 147 |
144 void FileImpl::Tell(const TellCallback& callback) { | 148 void FileImpl::Tell(const TellCallback& callback) { |
145 Seek(0, WHENCE_FROM_CURRENT, callback); | 149 Seek(0, Whence::FROM_CURRENT, callback); |
146 } | 150 } |
147 | 151 |
148 void FileImpl::Seek(int64_t offset, | 152 void FileImpl::Seek(int64_t offset, |
149 Whence whence, | 153 Whence whence, |
150 const SeekCallback& callback) { | 154 const SeekCallback& callback) { |
151 if (!file_.IsValid()) { | 155 if (!file_.IsValid()) { |
152 callback.Run(GetError(file_), 0); | 156 callback.Run(GetError(file_), 0); |
153 return; | 157 return; |
154 } | 158 } |
155 if (FileError error = IsOffsetValid(offset)) { | 159 FileError error = IsOffsetValid(offset); |
| 160 if (error != FileError::OK) { |
156 callback.Run(error, 0); | 161 callback.Run(error, 0); |
157 return; | 162 return; |
158 } | 163 } |
159 if (FileError error = IsWhenceValid(whence)) { | 164 error = IsWhenceValid(whence); |
| 165 if (error != FileError::OK) { |
160 callback.Run(error, 0); | 166 callback.Run(error, 0); |
161 return; | 167 return; |
162 } | 168 } |
163 | 169 |
164 int64_t position = | 170 int64_t position = |
165 file_.Seek(static_cast<base::File::Whence>(whence), offset); | 171 file_.Seek(static_cast<base::File::Whence>(whence), offset); |
166 if (position < 0) { | 172 if (position < 0) { |
167 callback.Run(FILE_ERROR_FAILED, 0); | 173 callback.Run(FileError::FAILED, 0); |
168 return; | 174 return; |
169 } | 175 } |
170 | 176 |
171 callback.Run(FILE_ERROR_OK, static_cast<int64_t>(position)); | 177 callback.Run(FileError::OK, static_cast<int64_t>(position)); |
172 } | 178 } |
173 | 179 |
174 void FileImpl::Stat(const StatCallback& callback) { | 180 void FileImpl::Stat(const StatCallback& callback) { |
175 if (!file_.IsValid()) { | 181 if (!file_.IsValid()) { |
176 callback.Run(GetError(file_), nullptr); | 182 callback.Run(GetError(file_), nullptr); |
177 return; | 183 return; |
178 } | 184 } |
179 | 185 |
180 base::File::Info info; | 186 base::File::Info info; |
181 if (!file_.GetInfo(&info)) { | 187 if (!file_.GetInfo(&info)) { |
182 callback.Run(FILE_ERROR_FAILED, nullptr); | 188 callback.Run(FileError::FAILED, nullptr); |
183 return; | 189 return; |
184 } | 190 } |
185 | 191 |
186 callback.Run(FILE_ERROR_OK, MakeFileInformation(info)); | 192 callback.Run(FileError::OK, MakeFileInformation(info)); |
187 } | 193 } |
188 | 194 |
189 void FileImpl::Truncate(int64_t size, const TruncateCallback& callback) { | 195 void FileImpl::Truncate(int64_t size, const TruncateCallback& callback) { |
190 if (!file_.IsValid()) { | 196 if (!file_.IsValid()) { |
191 callback.Run(GetError(file_)); | 197 callback.Run(GetError(file_)); |
192 return; | 198 return; |
193 } | 199 } |
194 if (size < 0) { | 200 if (size < 0) { |
195 callback.Run(FILE_ERROR_INVALID_OPERATION); | 201 callback.Run(FileError::INVALID_OPERATION); |
196 return; | 202 return; |
197 } | 203 } |
198 if (FileError error = IsOffsetValid(size)) { | 204 FileError error = IsOffsetValid(size); |
| 205 if (error != FileError::OK) { |
199 callback.Run(error); | 206 callback.Run(error); |
200 return; | 207 return; |
201 } | 208 } |
202 | 209 |
203 if (!file_.SetLength(size)) { | 210 if (!file_.SetLength(size)) { |
204 callback.Run(FILE_ERROR_NOT_FOUND); | 211 callback.Run(FileError::NOT_FOUND); |
205 return; | 212 return; |
206 } | 213 } |
207 | 214 |
208 callback.Run(FILE_ERROR_OK); | 215 callback.Run(FileError::OK); |
209 } | 216 } |
210 | 217 |
211 void FileImpl::Touch(TimespecOrNowPtr atime, | 218 void FileImpl::Touch(TimespecOrNowPtr atime, |
212 TimespecOrNowPtr mtime, | 219 TimespecOrNowPtr mtime, |
213 const TouchCallback& callback) { | 220 const TouchCallback& callback) { |
214 if (!file_.IsValid()) { | 221 if (!file_.IsValid()) { |
215 callback.Run(GetError(file_)); | 222 callback.Run(GetError(file_)); |
216 return; | 223 return; |
217 } | 224 } |
218 | 225 |
219 base::Time base_atime = Time::Now(); | 226 base::Time base_atime = Time::Now(); |
220 if (!atime) { | 227 if (!atime) { |
221 base::File::Info info; | 228 base::File::Info info; |
222 if (!file_.GetInfo(&info)) { | 229 if (!file_.GetInfo(&info)) { |
223 callback.Run(FILE_ERROR_FAILED); | 230 callback.Run(FileError::FAILED); |
224 return; | 231 return; |
225 } | 232 } |
226 | 233 |
227 base_atime = info.last_accessed; | 234 base_atime = info.last_accessed; |
228 } else if (!atime->now) { | 235 } else if (!atime->now) { |
229 base_atime = Time::FromDoubleT(atime->seconds); | 236 base_atime = Time::FromDoubleT(atime->seconds); |
230 } | 237 } |
231 | 238 |
232 base::Time base_mtime = Time::Now(); | 239 base::Time base_mtime = Time::Now(); |
233 if (!mtime) { | 240 if (!mtime) { |
234 base::File::Info info; | 241 base::File::Info info; |
235 if (!file_.GetInfo(&info)) { | 242 if (!file_.GetInfo(&info)) { |
236 callback.Run(FILE_ERROR_FAILED); | 243 callback.Run(FileError::FAILED); |
237 return; | 244 return; |
238 } | 245 } |
239 | 246 |
240 base_mtime = info.last_modified; | 247 base_mtime = info.last_modified; |
241 } else if (!mtime->now) { | 248 } else if (!mtime->now) { |
242 base_mtime = Time::FromDoubleT(mtime->seconds); | 249 base_mtime = Time::FromDoubleT(mtime->seconds); |
243 } | 250 } |
244 | 251 |
245 file_.SetTimes(base_atime, base_mtime); | 252 file_.SetTimes(base_atime, base_mtime); |
246 callback.Run(FILE_ERROR_OK); | 253 callback.Run(FileError::OK); |
247 } | 254 } |
248 | 255 |
249 void FileImpl::Dup(mojo::InterfaceRequest<File> file, | 256 void FileImpl::Dup(mojo::InterfaceRequest<File> file, |
250 const DupCallback& callback) { | 257 const DupCallback& callback) { |
251 if (!file_.IsValid()) { | 258 if (!file_.IsValid()) { |
252 callback.Run(GetError(file_)); | 259 callback.Run(GetError(file_)); |
253 return; | 260 return; |
254 } | 261 } |
255 | 262 |
256 base::File new_file = file_.Duplicate(); | 263 base::File new_file = file_.Duplicate(); |
257 if (!new_file.IsValid()) { | 264 if (!new_file.IsValid()) { |
258 callback.Run(GetError(new_file)); | 265 callback.Run(GetError(new_file)); |
259 return; | 266 return; |
260 } | 267 } |
261 | 268 |
262 if (file.is_pending()) | 269 if (file.is_pending()) |
263 new FileImpl(std::move(file), std::move(new_file)); | 270 new FileImpl(std::move(file), std::move(new_file)); |
264 callback.Run(FILE_ERROR_OK); | 271 callback.Run(FileError::OK); |
265 } | 272 } |
266 | 273 |
267 void FileImpl::Flush(const FlushCallback& callback) { | 274 void FileImpl::Flush(const FlushCallback& callback) { |
268 if (!file_.IsValid()) { | 275 if (!file_.IsValid()) { |
269 callback.Run(GetError(file_)); | 276 callback.Run(GetError(file_)); |
270 return; | 277 return; |
271 } | 278 } |
272 | 279 |
273 bool ret = file_.Flush(); | 280 bool ret = file_.Flush(); |
274 callback.Run(ret ? FILE_ERROR_OK : FILE_ERROR_FAILED); | 281 callback.Run(ret ? FileError::OK : FileError::FAILED); |
275 } | 282 } |
276 | 283 |
277 void FileImpl::AsHandle(const AsHandleCallback& callback) { | 284 void FileImpl::AsHandle(const AsHandleCallback& callback) { |
278 if (!file_.IsValid()) { | 285 if (!file_.IsValid()) { |
279 callback.Run(GetError(file_), ScopedHandle()); | 286 callback.Run(GetError(file_), ScopedHandle()); |
280 return; | 287 return; |
281 } | 288 } |
282 | 289 |
283 base::File new_file = file_.Duplicate(); | 290 base::File new_file = file_.Duplicate(); |
284 if (!new_file.IsValid()) { | 291 if (!new_file.IsValid()) { |
285 callback.Run(GetError(new_file), ScopedHandle()); | 292 callback.Run(GetError(new_file), ScopedHandle()); |
286 return; | 293 return; |
287 } | 294 } |
288 | 295 |
289 base::File::Info info; | 296 base::File::Info info; |
290 if (!new_file.GetInfo(&info)) { | 297 if (!new_file.GetInfo(&info)) { |
291 callback.Run(FILE_ERROR_FAILED, ScopedHandle()); | 298 callback.Run(FileError::FAILED, ScopedHandle()); |
292 return; | 299 return; |
293 } | 300 } |
294 | 301 |
295 // Perform one additional check right before we send the file's file | 302 // Perform one additional check right before we send the file's file |
296 // descriptor over mojo. This is theoretically redundant, but given that | 303 // descriptor over mojo. This is theoretically redundant, but given that |
297 // passing a file descriptor to a directory is a sandbox escape on Windows, | 304 // passing a file descriptor to a directory is a sandbox escape on Windows, |
298 // we should be absolutely paranoid. | 305 // we should be absolutely paranoid. |
299 if (info.is_directory) { | 306 if (info.is_directory) { |
300 callback.Run(FILE_ERROR_NOT_A_FILE, ScopedHandle()); | 307 callback.Run(FileError::NOT_A_FILE, ScopedHandle()); |
301 return; | 308 return; |
302 } | 309 } |
303 | 310 |
304 MojoHandle mojo_handle; | 311 MojoHandle mojo_handle; |
305 MojoResult create_result = MojoCreatePlatformHandleWrapper( | 312 MojoResult create_result = MojoCreatePlatformHandleWrapper( |
306 new_file.TakePlatformFile(), &mojo_handle); | 313 new_file.TakePlatformFile(), &mojo_handle); |
307 if (create_result != MOJO_RESULT_OK) { | 314 if (create_result != MOJO_RESULT_OK) { |
308 callback.Run(FILE_ERROR_FAILED, ScopedHandle()); | 315 callback.Run(FileError::FAILED, ScopedHandle()); |
309 return; | 316 return; |
310 } | 317 } |
311 | 318 |
312 callback.Run(FILE_ERROR_OK, ScopedHandle(mojo::Handle(mojo_handle))); | 319 callback.Run(FileError::OK, ScopedHandle(mojo::Handle(mojo_handle))); |
313 } | 320 } |
314 | 321 |
315 } // namespace filesystem | 322 } // namespace filesystem |
OLD | NEW |