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 14 matching lines...) Expand all Loading... |
25 using base::Time; | 25 using base::Time; |
26 using mojo::ScopedHandle; | 26 using mojo::ScopedHandle; |
27 | 27 |
28 namespace filesystem { | 28 namespace filesystem { |
29 namespace { | 29 namespace { |
30 | 30 |
31 const size_t kMaxReadSize = 1 * 1024 * 1024; // 1 MB. | 31 const size_t kMaxReadSize = 1 * 1024 * 1024; // 1 MB. |
32 | 32 |
33 } // namespace | 33 } // namespace |
34 | 34 |
35 FileImpl::FileImpl(mojo::InterfaceRequest<File> request, | 35 FileImpl::FileImpl(mojo::InterfaceRequest<mojom::File> request, |
36 const base::FilePath& path, | 36 const base::FilePath& path, |
37 uint32_t flags, | 37 uint32_t flags, |
38 scoped_refptr<SharedTempDir> temp_dir, | 38 scoped_refptr<SharedTempDir> temp_dir, |
39 scoped_refptr<LockTable> lock_table) | 39 scoped_refptr<LockTable> lock_table) |
40 : binding_(this, std::move(request)), | 40 : binding_(this, std::move(request)), |
41 file_(path, flags), | 41 file_(path, flags), |
42 path_(path), | 42 path_(path), |
43 temp_dir_(std::move(temp_dir)), | 43 temp_dir_(std::move(temp_dir)), |
44 lock_table_(std::move(lock_table)) { | 44 lock_table_(std::move(lock_table)) { |
45 DCHECK(file_.IsValid()); | 45 DCHECK(file_.IsValid()); |
46 } | 46 } |
47 | 47 |
48 FileImpl::FileImpl(mojo::InterfaceRequest<File> request, | 48 FileImpl::FileImpl(mojo::InterfaceRequest<mojom::File> request, |
49 const base::FilePath& path, | 49 const base::FilePath& path, |
50 base::File file, | 50 base::File file, |
51 scoped_refptr<SharedTempDir> temp_dir, | 51 scoped_refptr<SharedTempDir> temp_dir, |
52 scoped_refptr<LockTable> lock_table) | 52 scoped_refptr<LockTable> lock_table) |
53 : binding_(this, std::move(request)), | 53 : binding_(this, std::move(request)), |
54 file_(std::move(file)), | 54 file_(std::move(file)), |
55 path_(path), | 55 path_(path), |
56 temp_dir_(std::move(temp_dir)), | 56 temp_dir_(std::move(temp_dir)), |
57 lock_table_(std::move(lock_table)) { | 57 lock_table_(std::move(lock_table)) { |
58 DCHECK(file_.IsValid()); | 58 DCHECK(file_.IsValid()); |
(...skipping 17 matching lines...) Expand all Loading... |
76 } | 76 } |
77 | 77 |
78 void FileImpl::Close(const CloseCallback& callback) { | 78 void FileImpl::Close(const CloseCallback& callback) { |
79 if (!file_.IsValid()) { | 79 if (!file_.IsValid()) { |
80 callback.Run(GetError(file_)); | 80 callback.Run(GetError(file_)); |
81 return; | 81 return; |
82 } | 82 } |
83 | 83 |
84 lock_table_->RemoveFromLockTable(path_); | 84 lock_table_->RemoveFromLockTable(path_); |
85 file_.Close(); | 85 file_.Close(); |
86 callback.Run(FileError::OK); | 86 callback.Run(mojom::FileError::OK); |
87 } | 87 } |
88 | 88 |
89 // TODO(vtl): Move the implementation to a thread pool. | 89 // TODO(vtl): Move the implementation to a thread pool. |
90 void FileImpl::Read(uint32_t num_bytes_to_read, | 90 void FileImpl::Read(uint32_t num_bytes_to_read, |
91 int64_t offset, | 91 int64_t offset, |
92 Whence whence, | 92 mojom::Whence whence, |
93 const ReadCallback& callback) { | 93 const ReadCallback& callback) { |
94 if (!file_.IsValid()) { | 94 if (!file_.IsValid()) { |
95 callback.Run(GetError(file_), mojo::Array<uint8_t>()); | 95 callback.Run(GetError(file_), mojo::Array<uint8_t>()); |
96 return; | 96 return; |
97 } | 97 } |
98 if (num_bytes_to_read > kMaxReadSize) { | 98 if (num_bytes_to_read > kMaxReadSize) { |
99 callback.Run(FileError::INVALID_OPERATION, mojo::Array<uint8_t>()); | 99 callback.Run(mojom::FileError::INVALID_OPERATION, mojo::Array<uint8_t>()); |
100 return; | 100 return; |
101 } | 101 } |
102 FileError error = IsOffsetValid(offset); | 102 mojom::FileError error = IsOffsetValid(offset); |
103 if (error != FileError::OK) { | 103 if (error != mojom::FileError::OK) { |
104 callback.Run(error, mojo::Array<uint8_t>()); | 104 callback.Run(error, mojo::Array<uint8_t>()); |
105 return; | 105 return; |
106 } | 106 } |
107 error = IsWhenceValid(whence); | 107 error = IsWhenceValid(whence); |
108 if (error != FileError::OK) { | 108 if (error != mojom::FileError::OK) { |
109 callback.Run(error, mojo::Array<uint8_t>()); | 109 callback.Run(error, mojo::Array<uint8_t>()); |
110 return; | 110 return; |
111 } | 111 } |
112 | 112 |
113 if (file_.Seek(static_cast<base::File::Whence>(whence), offset) == -1) { | 113 if (file_.Seek(static_cast<base::File::Whence>(whence), offset) == -1) { |
114 callback.Run(FileError::FAILED, mojo::Array<uint8_t>()); | 114 callback.Run(mojom::FileError::FAILED, mojo::Array<uint8_t>()); |
115 return; | 115 return; |
116 } | 116 } |
117 | 117 |
118 mojo::Array<uint8_t> bytes_read(num_bytes_to_read); | 118 mojo::Array<uint8_t> bytes_read(num_bytes_to_read); |
119 int num_bytes_read = file_.ReadAtCurrentPos( | 119 int num_bytes_read = file_.ReadAtCurrentPos( |
120 reinterpret_cast<char*>(&bytes_read.front()), num_bytes_to_read); | 120 reinterpret_cast<char*>(&bytes_read.front()), num_bytes_to_read); |
121 if (num_bytes_read < 0) { | 121 if (num_bytes_read < 0) { |
122 callback.Run(FileError::FAILED, mojo::Array<uint8_t>()); | 122 callback.Run(mojom::FileError::FAILED, mojo::Array<uint8_t>()); |
123 return; | 123 return; |
124 } | 124 } |
125 | 125 |
126 DCHECK_LE(static_cast<size_t>(num_bytes_read), num_bytes_to_read); | 126 DCHECK_LE(static_cast<size_t>(num_bytes_read), num_bytes_to_read); |
127 bytes_read.resize(static_cast<size_t>(num_bytes_read)); | 127 bytes_read.resize(static_cast<size_t>(num_bytes_read)); |
128 callback.Run(FileError::OK, std::move(bytes_read)); | 128 callback.Run(mojom::FileError::OK, std::move(bytes_read)); |
129 } | 129 } |
130 | 130 |
131 // TODO(vtl): Move the implementation to a thread pool. | 131 // TODO(vtl): Move the implementation to a thread pool. |
132 void FileImpl::Write(mojo::Array<uint8_t> bytes_to_write, | 132 void FileImpl::Write(mojo::Array<uint8_t> bytes_to_write, |
133 int64_t offset, | 133 int64_t offset, |
134 Whence whence, | 134 mojom::Whence whence, |
135 const WriteCallback& callback) { | 135 const WriteCallback& callback) { |
136 DCHECK(!bytes_to_write.is_null()); | 136 DCHECK(!bytes_to_write.is_null()); |
137 if (!file_.IsValid()) { | 137 if (!file_.IsValid()) { |
138 callback.Run(GetError(file_), 0); | 138 callback.Run(GetError(file_), 0); |
139 return; | 139 return; |
140 } | 140 } |
141 // Who knows what |write()| would return if the size is that big (and it | 141 // Who knows what |write()| would return if the size is that big (and it |
142 // actually wrote that much). | 142 // actually wrote that much). |
143 if (bytes_to_write.size() > | 143 if (bytes_to_write.size() > |
144 #if defined(OS_WIN) | 144 #if defined(OS_WIN) |
145 static_cast<size_t>(std::numeric_limits<int>::max())) { | 145 static_cast<size_t>(std::numeric_limits<int>::max())) { |
146 #else | 146 #else |
147 static_cast<size_t>(std::numeric_limits<ssize_t>::max())) { | 147 static_cast<size_t>(std::numeric_limits<ssize_t>::max())) { |
148 #endif | 148 #endif |
149 callback.Run(FileError::INVALID_OPERATION, 0); | 149 callback.Run(mojom::FileError::INVALID_OPERATION, 0); |
150 return; | 150 return; |
151 } | 151 } |
152 FileError error = IsOffsetValid(offset); | 152 mojom::FileError error = IsOffsetValid(offset); |
153 if (error != FileError::OK) { | 153 if (error != mojom::FileError::OK) { |
154 callback.Run(error, 0); | 154 callback.Run(error, 0); |
155 return; | 155 return; |
156 } | 156 } |
157 error = IsWhenceValid(whence); | 157 error = IsWhenceValid(whence); |
158 if (error != FileError::OK) { | 158 if (error != mojom::FileError::OK) { |
159 callback.Run(error, 0); | 159 callback.Run(error, 0); |
160 return; | 160 return; |
161 } | 161 } |
162 | 162 |
163 if (file_.Seek(static_cast<base::File::Whence>(whence), offset) == -1) { | 163 if (file_.Seek(static_cast<base::File::Whence>(whence), offset) == -1) { |
164 callback.Run(FileError::FAILED, 0); | 164 callback.Run(mojom::FileError::FAILED, 0); |
165 return; | 165 return; |
166 } | 166 } |
167 | 167 |
168 const char* buf = (bytes_to_write.size() > 0) | 168 const char* buf = (bytes_to_write.size() > 0) |
169 ? reinterpret_cast<char*>(&bytes_to_write.front()) | 169 ? reinterpret_cast<char*>(&bytes_to_write.front()) |
170 : nullptr; | 170 : nullptr; |
171 int num_bytes_written = file_.WriteAtCurrentPos( | 171 int num_bytes_written = file_.WriteAtCurrentPos( |
172 buf, static_cast<int>(bytes_to_write.size())); | 172 buf, static_cast<int>(bytes_to_write.size())); |
173 if (num_bytes_written < 0) { | 173 if (num_bytes_written < 0) { |
174 callback.Run(FileError::FAILED, 0); | 174 callback.Run(mojom::FileError::FAILED, 0); |
175 return; | 175 return; |
176 } | 176 } |
177 | 177 |
178 DCHECK_LE(static_cast<size_t>(num_bytes_written), | 178 DCHECK_LE(static_cast<size_t>(num_bytes_written), |
179 std::numeric_limits<uint32_t>::max()); | 179 std::numeric_limits<uint32_t>::max()); |
180 callback.Run(FileError::OK, static_cast<uint32_t>(num_bytes_written)); | 180 callback.Run(mojom::FileError::OK, static_cast<uint32_t>(num_bytes_written)); |
181 } | 181 } |
182 | 182 |
183 void FileImpl::Tell(const TellCallback& callback) { | 183 void FileImpl::Tell(const TellCallback& callback) { |
184 Seek(0, Whence::FROM_CURRENT, callback); | 184 Seek(0, mojom::Whence::FROM_CURRENT, callback); |
185 } | 185 } |
186 | 186 |
187 void FileImpl::Seek(int64_t offset, | 187 void FileImpl::Seek(int64_t offset, |
188 Whence whence, | 188 mojom::Whence whence, |
189 const SeekCallback& callback) { | 189 const SeekCallback& callback) { |
190 if (!file_.IsValid()) { | 190 if (!file_.IsValid()) { |
191 callback.Run(GetError(file_), 0); | 191 callback.Run(GetError(file_), 0); |
192 return; | 192 return; |
193 } | 193 } |
194 FileError error = IsOffsetValid(offset); | 194 mojom::FileError error = IsOffsetValid(offset); |
195 if (error != FileError::OK) { | 195 if (error != mojom::FileError::OK) { |
196 callback.Run(error, 0); | 196 callback.Run(error, 0); |
197 return; | 197 return; |
198 } | 198 } |
199 error = IsWhenceValid(whence); | 199 error = IsWhenceValid(whence); |
200 if (error != FileError::OK) { | 200 if (error != mojom::FileError::OK) { |
201 callback.Run(error, 0); | 201 callback.Run(error, 0); |
202 return; | 202 return; |
203 } | 203 } |
204 | 204 |
205 int64_t position = | 205 int64_t position = |
206 file_.Seek(static_cast<base::File::Whence>(whence), offset); | 206 file_.Seek(static_cast<base::File::Whence>(whence), offset); |
207 if (position < 0) { | 207 if (position < 0) { |
208 callback.Run(FileError::FAILED, 0); | 208 callback.Run(mojom::FileError::FAILED, 0); |
209 return; | 209 return; |
210 } | 210 } |
211 | 211 |
212 callback.Run(FileError::OK, static_cast<int64_t>(position)); | 212 callback.Run(mojom::FileError::OK, static_cast<int64_t>(position)); |
213 } | 213 } |
214 | 214 |
215 void FileImpl::Stat(const StatCallback& callback) { | 215 void FileImpl::Stat(const StatCallback& callback) { |
216 if (!file_.IsValid()) { | 216 if (!file_.IsValid()) { |
217 callback.Run(GetError(file_), nullptr); | 217 callback.Run(GetError(file_), nullptr); |
218 return; | 218 return; |
219 } | 219 } |
220 | 220 |
221 base::File::Info info; | 221 base::File::Info info; |
222 if (!file_.GetInfo(&info)) { | 222 if (!file_.GetInfo(&info)) { |
223 callback.Run(FileError::FAILED, nullptr); | 223 callback.Run(mojom::FileError::FAILED, nullptr); |
224 return; | 224 return; |
225 } | 225 } |
226 | 226 |
227 callback.Run(FileError::OK, MakeFileInformation(info)); | 227 callback.Run(mojom::FileError::OK, MakeFileInformation(info)); |
228 } | 228 } |
229 | 229 |
230 void FileImpl::Truncate(int64_t size, const TruncateCallback& callback) { | 230 void FileImpl::Truncate(int64_t size, const TruncateCallback& callback) { |
231 if (!file_.IsValid()) { | 231 if (!file_.IsValid()) { |
232 callback.Run(GetError(file_)); | 232 callback.Run(GetError(file_)); |
233 return; | 233 return; |
234 } | 234 } |
235 if (size < 0) { | 235 if (size < 0) { |
236 callback.Run(FileError::INVALID_OPERATION); | 236 callback.Run(mojom::FileError::INVALID_OPERATION); |
237 return; | 237 return; |
238 } | 238 } |
239 FileError error = IsOffsetValid(size); | 239 mojom::FileError error = IsOffsetValid(size); |
240 if (error != FileError::OK) { | 240 if (error != mojom::FileError::OK) { |
241 callback.Run(error); | 241 callback.Run(error); |
242 return; | 242 return; |
243 } | 243 } |
244 | 244 |
245 if (!file_.SetLength(size)) { | 245 if (!file_.SetLength(size)) { |
246 callback.Run(FileError::NOT_FOUND); | 246 callback.Run(mojom::FileError::NOT_FOUND); |
247 return; | 247 return; |
248 } | 248 } |
249 | 249 |
250 callback.Run(FileError::OK); | 250 callback.Run(mojom::FileError::OK); |
251 } | 251 } |
252 | 252 |
253 void FileImpl::Touch(TimespecOrNowPtr atime, | 253 void FileImpl::Touch(mojom::TimespecOrNowPtr atime, |
254 TimespecOrNowPtr mtime, | 254 mojom::TimespecOrNowPtr mtime, |
255 const TouchCallback& callback) { | 255 const TouchCallback& callback) { |
256 if (!file_.IsValid()) { | 256 if (!file_.IsValid()) { |
257 callback.Run(GetError(file_)); | 257 callback.Run(GetError(file_)); |
258 return; | 258 return; |
259 } | 259 } |
260 | 260 |
261 base::Time base_atime = Time::Now(); | 261 base::Time base_atime = Time::Now(); |
262 if (!atime) { | 262 if (!atime) { |
263 base::File::Info info; | 263 base::File::Info info; |
264 if (!file_.GetInfo(&info)) { | 264 if (!file_.GetInfo(&info)) { |
265 callback.Run(FileError::FAILED); | 265 callback.Run(mojom::FileError::FAILED); |
266 return; | 266 return; |
267 } | 267 } |
268 | 268 |
269 base_atime = info.last_accessed; | 269 base_atime = info.last_accessed; |
270 } else if (!atime->now) { | 270 } else if (!atime->now) { |
271 base_atime = Time::FromDoubleT(atime->seconds); | 271 base_atime = Time::FromDoubleT(atime->seconds); |
272 } | 272 } |
273 | 273 |
274 base::Time base_mtime = Time::Now(); | 274 base::Time base_mtime = Time::Now(); |
275 if (!mtime) { | 275 if (!mtime) { |
276 base::File::Info info; | 276 base::File::Info info; |
277 if (!file_.GetInfo(&info)) { | 277 if (!file_.GetInfo(&info)) { |
278 callback.Run(FileError::FAILED); | 278 callback.Run(mojom::FileError::FAILED); |
279 return; | 279 return; |
280 } | 280 } |
281 | 281 |
282 base_mtime = info.last_modified; | 282 base_mtime = info.last_modified; |
283 } else if (!mtime->now) { | 283 } else if (!mtime->now) { |
284 base_mtime = Time::FromDoubleT(mtime->seconds); | 284 base_mtime = Time::FromDoubleT(mtime->seconds); |
285 } | 285 } |
286 | 286 |
287 file_.SetTimes(base_atime, base_mtime); | 287 file_.SetTimes(base_atime, base_mtime); |
288 callback.Run(FileError::OK); | 288 callback.Run(mojom::FileError::OK); |
289 } | 289 } |
290 | 290 |
291 void FileImpl::Dup(mojo::InterfaceRequest<File> file, | 291 void FileImpl::Dup(mojo::InterfaceRequest<mojom::File> file, |
292 const DupCallback& callback) { | 292 const DupCallback& callback) { |
293 if (!file_.IsValid()) { | 293 if (!file_.IsValid()) { |
294 callback.Run(GetError(file_)); | 294 callback.Run(GetError(file_)); |
295 return; | 295 return; |
296 } | 296 } |
297 | 297 |
298 base::File new_file = file_.Duplicate(); | 298 base::File new_file = file_.Duplicate(); |
299 if (!new_file.IsValid()) { | 299 if (!new_file.IsValid()) { |
300 callback.Run(GetError(new_file)); | 300 callback.Run(GetError(new_file)); |
301 return; | 301 return; |
302 } | 302 } |
303 | 303 |
304 if (file.is_pending()) | 304 if (file.is_pending()) |
305 new FileImpl(std::move(file), path_, std::move(new_file), temp_dir_, | 305 new FileImpl(std::move(file), path_, std::move(new_file), temp_dir_, |
306 lock_table_); | 306 lock_table_); |
307 callback.Run(FileError::OK); | 307 callback.Run(mojom::FileError::OK); |
308 } | 308 } |
309 | 309 |
310 void FileImpl::Flush(const FlushCallback& callback) { | 310 void FileImpl::Flush(const FlushCallback& callback) { |
311 if (!file_.IsValid()) { | 311 if (!file_.IsValid()) { |
312 callback.Run(GetError(file_)); | 312 callback.Run(GetError(file_)); |
313 return; | 313 return; |
314 } | 314 } |
315 | 315 |
316 bool ret = file_.Flush(); | 316 bool ret = file_.Flush(); |
317 callback.Run(ret ? FileError::OK : FileError::FAILED); | 317 callback.Run(ret ? mojom::FileError::OK : mojom::FileError::FAILED); |
318 } | 318 } |
319 | 319 |
320 void FileImpl::Lock(const LockCallback& callback) { | 320 void FileImpl::Lock(const LockCallback& callback) { |
321 callback.Run(static_cast<filesystem::FileError>(lock_table_->LockFile(this))); | 321 callback.Run( |
| 322 static_cast<filesystem::mojom::FileError>(lock_table_->LockFile(this))); |
322 } | 323 } |
323 | 324 |
324 void FileImpl::Unlock(const UnlockCallback& callback) { | 325 void FileImpl::Unlock(const UnlockCallback& callback) { |
325 callback.Run( | 326 callback.Run( |
326 static_cast<filesystem::FileError>(lock_table_->UnlockFile(this))); | 327 static_cast<filesystem::mojom::FileError>(lock_table_->UnlockFile(this))); |
327 } | 328 } |
328 | 329 |
329 void FileImpl::AsHandle(const AsHandleCallback& callback) { | 330 void FileImpl::AsHandle(const AsHandleCallback& callback) { |
330 if (!file_.IsValid()) { | 331 if (!file_.IsValid()) { |
331 callback.Run(GetError(file_), ScopedHandle()); | 332 callback.Run(GetError(file_), ScopedHandle()); |
332 return; | 333 return; |
333 } | 334 } |
334 | 335 |
335 base::File new_file = file_.Duplicate(); | 336 base::File new_file = file_.Duplicate(); |
336 if (!new_file.IsValid()) { | 337 if (!new_file.IsValid()) { |
337 callback.Run(GetError(new_file), ScopedHandle()); | 338 callback.Run(GetError(new_file), ScopedHandle()); |
338 return; | 339 return; |
339 } | 340 } |
340 | 341 |
341 base::File::Info info; | 342 base::File::Info info; |
342 if (!new_file.GetInfo(&info)) { | 343 if (!new_file.GetInfo(&info)) { |
343 callback.Run(FileError::FAILED, ScopedHandle()); | 344 callback.Run(mojom::FileError::FAILED, ScopedHandle()); |
344 return; | 345 return; |
345 } | 346 } |
346 | 347 |
347 // Perform one additional check right before we send the file's file | 348 // Perform one additional check right before we send the file's file |
348 // descriptor over mojo. This is theoretically redundant, but given that | 349 // descriptor over mojo. This is theoretically redundant, but given that |
349 // passing a file descriptor to a directory is a sandbox escape on Windows, | 350 // passing a file descriptor to a directory is a sandbox escape on Windows, |
350 // we should be absolutely paranoid. | 351 // we should be absolutely paranoid. |
351 if (info.is_directory) { | 352 if (info.is_directory) { |
352 callback.Run(FileError::NOT_A_FILE, ScopedHandle()); | 353 callback.Run(mojom::FileError::NOT_A_FILE, ScopedHandle()); |
353 return; | 354 return; |
354 } | 355 } |
355 | 356 |
356 MojoHandle mojo_handle; | 357 MojoHandle mojo_handle; |
357 MojoResult create_result = MojoCreatePlatformHandleWrapper( | 358 MojoResult create_result = MojoCreatePlatformHandleWrapper( |
358 new_file.TakePlatformFile(), &mojo_handle); | 359 new_file.TakePlatformFile(), &mojo_handle); |
359 if (create_result != MOJO_RESULT_OK) { | 360 if (create_result != MOJO_RESULT_OK) { |
360 callback.Run(FileError::FAILED, ScopedHandle()); | 361 callback.Run(mojom::FileError::FAILED, ScopedHandle()); |
361 return; | 362 return; |
362 } | 363 } |
363 | 364 |
364 callback.Run(FileError::OK, ScopedHandle(mojo::Handle(mojo_handle))); | 365 callback.Run(mojom::FileError::OK, ScopedHandle(mojo::Handle(mojo_handle))); |
365 } | 366 } |
366 | 367 |
367 } // namespace filesystem | 368 } // namespace filesystem |
OLD | NEW |