OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "base/file_util_proxy.h" | 5 #include "base/file_util_proxy.h" |
6 | 6 |
7 #include "base/message_loop_proxy.h" | 7 #include "base/message_loop_proxy.h" |
8 | 8 |
9 // TODO(jianli): Move the code from anonymous namespace to base namespace so | 9 // TODO(jianli): Move the code from anonymous namespace to base namespace so |
10 // that all of the base:: prefixes would be unnecessary. | 10 // that all of the base:: prefixes would be unnecessary. |
11 namespace { | 11 namespace { |
12 | 12 |
| 13 namespace { |
| 14 |
| 15 // Performs common checks for move and copy. |
| 16 // This also removes the destination directory if it's non-empty and all other |
| 17 // checks are passed (so that the copy/move correctly overwrites the destination
). |
| 18 static base::PlatformFileError PerformCommonCheckAndPreparationForMoveAndCopy( |
| 19 const FilePath& src_file_path, |
| 20 const FilePath& dest_file_path) { |
| 21 // Exits earlier if the source path does not exist. |
| 22 if (!file_util::PathExists(src_file_path)) |
| 23 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 24 |
| 25 // The parent of the |dest_file_path| does not exist. |
| 26 if (!file_util::DirectoryExists(dest_file_path.DirName())) |
| 27 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 28 |
| 29 // It is an error to try to copy/move an entry into its child. |
| 30 if (file_util::ContainsPath(src_file_path, dest_file_path)) |
| 31 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; |
| 32 |
| 33 // Now it is ok to return if the |dest_file_path| does not exist. |
| 34 if (!file_util::PathExists(dest_file_path)) |
| 35 return base::PLATFORM_FILE_OK; |
| 36 |
| 37 // |src_file_path| exists and is a directory. |
| 38 // |dest_file_path| exists and is a file. |
| 39 bool src_is_directory = file_util::DirectoryExists(src_file_path); |
| 40 bool dest_is_directory = file_util::DirectoryExists(dest_file_path); |
| 41 if (src_is_directory && !dest_is_directory) |
| 42 return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; |
| 43 |
| 44 // |src_file_path| exists and is a file. |
| 45 // |dest_file_path| exists and is a directory. |
| 46 if (!src_is_directory && dest_is_directory) |
| 47 return base::PLATFORM_FILE_ERROR_NOT_A_FILE; |
| 48 |
| 49 // It is an error to copy/move an entry into the same path. |
| 50 if (src_file_path.value() == dest_file_path.value()) |
| 51 return base::PLATFORM_FILE_ERROR_EXISTS; |
| 52 |
| 53 if (dest_is_directory) { |
| 54 // It is an error to copy/move an entry to a non-empty directory. |
| 55 // Otherwise the copy/move attempt must overwrite the destination, but |
| 56 // the file_util's Copy or Move method doesn't perform overwrite |
| 57 // on all platforms, so we delete the destination directory here. |
| 58 // TODO(kinuko): may be better to change the file_util::{Copy,Move}. |
| 59 if (!file_util::Delete(dest_file_path, false /* recursive */)) { |
| 60 if (!file_util::IsDirectoryEmpty(dest_file_path)) |
| 61 return base::PLATFORM_FILE_ERROR_NOT_EMPTY; |
| 62 return base::PLATFORM_FILE_ERROR_FAILED; |
| 63 } |
| 64 } |
| 65 return base::PLATFORM_FILE_OK; |
| 66 } |
| 67 |
| 68 } // anonymous namespace |
| 69 |
13 class MessageLoopRelay | 70 class MessageLoopRelay |
14 : public base::RefCountedThreadSafe<MessageLoopRelay> { | 71 : public base::RefCountedThreadSafe<MessageLoopRelay> { |
15 public: | 72 public: |
16 MessageLoopRelay() | 73 MessageLoopRelay() |
17 : origin_message_loop_proxy_( | 74 : origin_message_loop_proxy_( |
18 base::MessageLoopProxy::CreateForCurrentThread()), | 75 base::MessageLoopProxy::CreateForCurrentThread()), |
19 error_code_(base::PLATFORM_FILE_OK) { | 76 error_code_(base::PLATFORM_FILE_OK) { |
20 } | 77 } |
21 | 78 |
22 bool Start(scoped_refptr<base::MessageLoopProxy> message_loop_proxy, | 79 bool Start(scoped_refptr<base::MessageLoopProxy> message_loop_proxy, |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 } | 255 } |
199 | 256 |
200 protected: | 257 protected: |
201 virtual void RunWork() { | 258 virtual void RunWork() { |
202 if (!file_util::PathExists(file_path_)) { | 259 if (!file_util::PathExists(file_path_)) { |
203 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND); | 260 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND); |
204 return; | 261 return; |
205 } | 262 } |
206 if (!file_util::Delete(file_path_, recursive_)) { | 263 if (!file_util::Delete(file_path_, recursive_)) { |
207 if (!recursive_ && !file_util::IsDirectoryEmpty(file_path_)) { | 264 if (!recursive_ && !file_util::IsDirectoryEmpty(file_path_)) { |
208 set_error_code(base::PLATFORM_FILE_ERROR_INVALID_OPERATION); | 265 set_error_code(base::PLATFORM_FILE_ERROR_NOT_EMPTY); |
209 return; | 266 return; |
210 } | 267 } |
211 set_error_code(base::PLATFORM_FILE_ERROR_FAILED); | 268 set_error_code(base::PLATFORM_FILE_ERROR_FAILED); |
212 } | 269 } |
213 } | 270 } |
214 | 271 |
215 private: | 272 private: |
216 FilePath file_path_; | 273 FilePath file_path_; |
217 bool recursive_; | 274 bool recursive_; |
218 }; | 275 }; |
219 | 276 |
220 class RelayCopy : public RelayWithStatusCallback { | 277 class RelayCopy : public RelayWithStatusCallback { |
221 public: | 278 public: |
222 RelayCopy(const FilePath& src_file_path, | 279 RelayCopy(const FilePath& src_file_path, |
223 const FilePath& dest_file_path, | 280 const FilePath& dest_file_path, |
224 base::FileUtilProxy::StatusCallback* callback) | 281 base::FileUtilProxy::StatusCallback* callback) |
225 : RelayWithStatusCallback(callback), | 282 : RelayWithStatusCallback(callback), |
226 src_file_path_(src_file_path), | 283 src_file_path_(src_file_path), |
227 dest_file_path_(dest_file_path) { | 284 dest_file_path_(dest_file_path) { |
228 } | 285 } |
229 | 286 |
230 protected: | 287 protected: |
231 virtual void RunWork() { | 288 virtual void RunWork() { |
232 bool dest_path_exists = file_util::PathExists(dest_file_path_); | 289 set_error_code(PerformCommonCheckAndPreparationForMoveAndCopy( |
233 if (!dest_path_exists && | 290 src_file_path_, dest_file_path_)); |
234 !file_util::DirectoryExists(dest_file_path_.DirName())) { | 291 if (error_code() != base::PLATFORM_FILE_OK) |
235 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND); | |
236 return; | 292 return; |
237 } | 293 if (!file_util::CopyDirectory(src_file_path_, dest_file_path_, |
238 // |src_file_path| exists and is a directory. | 294 true /* recursive */)) |
239 // |dest_file_path| exists and is a file. | |
240 if (file_util::DirectoryExists(src_file_path_) && | |
241 dest_path_exists && !file_util::DirectoryExists(dest_file_path_)) { | |
242 set_error_code(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY); | |
243 return; | |
244 } | |
245 if (file_util::ContainsPath(src_file_path_, dest_file_path_)) { | |
246 set_error_code(base::PLATFORM_FILE_ERROR_FAILED); | 295 set_error_code(base::PLATFORM_FILE_ERROR_FAILED); |
247 return; | |
248 } | |
249 if (!file_util::CopyDirectory(src_file_path_, dest_file_path_, | |
250 true /* recursive */)) { | |
251 if (!file_util::PathExists(src_file_path_)) { | |
252 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND); | |
253 return; | |
254 } | |
255 if (src_file_path_.value() == dest_file_path_.value()) { | |
256 set_error_code(base::PLATFORM_FILE_ERROR_EXISTS); | |
257 return; | |
258 } | |
259 // Something else went wrong. | |
260 set_error_code(base::PLATFORM_FILE_ERROR_FAILED); | |
261 } | |
262 } | 296 } |
263 | 297 |
264 private: | 298 private: |
265 FilePath src_file_path_; | 299 FilePath src_file_path_; |
266 FilePath dest_file_path_; | 300 FilePath dest_file_path_; |
267 }; | 301 }; |
268 | 302 |
269 class RelayMove : public RelayWithStatusCallback { | 303 class RelayMove : public RelayWithStatusCallback { |
270 public: | 304 public: |
271 RelayMove(const FilePath& src_file_path, | 305 RelayMove(const FilePath& src_file_path, |
272 const FilePath& dest_file_path, | 306 const FilePath& dest_file_path, |
273 base::FileUtilProxy::StatusCallback* callback) | 307 base::FileUtilProxy::StatusCallback* callback) |
274 : RelayWithStatusCallback(callback), | 308 : RelayWithStatusCallback(callback), |
275 src_file_path_(src_file_path), | 309 src_file_path_(src_file_path), |
276 dest_file_path_(dest_file_path) { | 310 dest_file_path_(dest_file_path) { |
277 } | 311 } |
278 | 312 |
279 protected: | 313 protected: |
280 virtual void RunWork() { | 314 virtual void RunWork() { |
281 bool dest_path_exists = file_util::PathExists(dest_file_path_); | 315 set_error_code(PerformCommonCheckAndPreparationForMoveAndCopy( |
282 if (!dest_path_exists && | 316 src_file_path_, dest_file_path_)); |
283 !file_util::DirectoryExists(dest_file_path_.DirName())) { | 317 if (error_code() != base::PLATFORM_FILE_OK) |
284 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND); | |
285 return; | 318 return; |
286 } | 319 if (!file_util::Move(src_file_path_, dest_file_path_)) |
287 // |src_file_path| exists and is a directory. | |
288 // |dest_file_path| exists and is a file. | |
289 if (file_util::DirectoryExists(src_file_path_) && | |
290 dest_path_exists && | |
291 !file_util::DirectoryExists(dest_file_path_)) { | |
292 set_error_code(base::PLATFORM_FILE_ERROR_EXISTS); | |
293 return; | |
294 } | |
295 if (file_util::ContainsPath(src_file_path_, dest_file_path_)) { | |
296 set_error_code(base::PLATFORM_FILE_ERROR_INVALID_OPERATION); | |
297 return; | |
298 } | |
299 if (!file_util::Move(src_file_path_, dest_file_path_)) { | |
300 if (!file_util::PathExists(src_file_path_)) { | |
301 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND); | |
302 return; | |
303 } | |
304 if (src_file_path_.value() == dest_file_path_.value()) { | |
305 set_error_code(base::PLATFORM_FILE_ERROR_EXISTS); | |
306 return; | |
307 } | |
308 // Something else went wrong. | |
309 set_error_code(base::PLATFORM_FILE_ERROR_FAILED); | 320 set_error_code(base::PLATFORM_FILE_ERROR_FAILED); |
310 } | |
311 } | 321 } |
312 | 322 |
313 private: | 323 private: |
314 FilePath src_file_path_; | 324 FilePath src_file_path_; |
315 FilePath dest_file_path_; | 325 FilePath dest_file_path_; |
316 }; | 326 }; |
317 | 327 |
318 class RelayCreateDirectory : public RelayWithStatusCallback { | 328 class RelayCreateDirectory : public RelayWithStatusCallback { |
319 public: | 329 public: |
320 RelayCreateDirectory( | 330 RelayCreateDirectory( |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 bool FileUtilProxy::Close(scoped_refptr<MessageLoopProxy> message_loop_proxy, | 673 bool FileUtilProxy::Close(scoped_refptr<MessageLoopProxy> message_loop_proxy, |
664 base::PlatformFile file_handle, | 674 base::PlatformFile file_handle, |
665 StatusCallback* callback) { | 675 StatusCallback* callback) { |
666 return Start(FROM_HERE, message_loop_proxy, | 676 return Start(FROM_HERE, message_loop_proxy, |
667 new RelayClose(file_handle, callback)); | 677 new RelayClose(file_handle, callback)); |
668 } | 678 } |
669 | 679 |
670 // static | 680 // static |
671 bool FileUtilProxy::Delete(scoped_refptr<MessageLoopProxy> message_loop_proxy, | 681 bool FileUtilProxy::Delete(scoped_refptr<MessageLoopProxy> message_loop_proxy, |
672 const FilePath& file_path, | 682 const FilePath& file_path, |
| 683 bool recursive, |
673 StatusCallback* callback) { | 684 StatusCallback* callback) { |
674 return Start(FROM_HERE, message_loop_proxy, | 685 return Start(FROM_HERE, message_loop_proxy, |
675 new RelayDelete(file_path, false, callback)); | 686 new RelayDelete(file_path, recursive, callback)); |
676 } | 687 } |
677 | 688 |
678 // static | 689 // static |
679 bool FileUtilProxy::Copy(scoped_refptr<MessageLoopProxy> message_loop_proxy, | 690 bool FileUtilProxy::Copy(scoped_refptr<MessageLoopProxy> message_loop_proxy, |
680 const FilePath& src_file_path, | 691 const FilePath& src_file_path, |
681 const FilePath& dest_file_path, | 692 const FilePath& dest_file_path, |
682 StatusCallback* callback) { | 693 StatusCallback* callback) { |
683 return Start(FROM_HERE, message_loop_proxy, | 694 return Start(FROM_HERE, message_loop_proxy, |
684 new RelayCopy(src_file_path, dest_file_path, callback)); | 695 new RelayCopy(src_file_path, dest_file_path, callback)); |
685 } | 696 } |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
790 | 801 |
791 // static | 802 // static |
792 bool FileUtilProxy::Flush( | 803 bool FileUtilProxy::Flush( |
793 scoped_refptr<MessageLoopProxy> message_loop_proxy, | 804 scoped_refptr<MessageLoopProxy> message_loop_proxy, |
794 PlatformFile file, | 805 PlatformFile file, |
795 StatusCallback* callback) { | 806 StatusCallback* callback) { |
796 return Start(FROM_HERE, message_loop_proxy, new RelayFlush(file, callback)); | 807 return Start(FROM_HERE, message_loop_proxy, new RelayFlush(file, callback)); |
797 } | 808 } |
798 | 809 |
799 } // namespace base | 810 } // namespace base |
OLD | NEW |