Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "webkit/fileapi/file_system_file_util.h" | 5 #include "webkit/fileapi/file_system_file_util.h" |
| 6 | 6 |
| 7 #include <stack> | 7 #include <stack> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/file_util_proxy.h" | 10 #include "base/file_util_proxy.h" |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 129 // http://code.google.com/p/chromium-os/issues/detail?id=15948 | 129 // http://code.google.com/p/chromium-os/issues/detail?id=15948 |
| 130 // This currently just prevents a file from showing up at all | 130 // This currently just prevents a file from showing up at all |
| 131 // if it's a link, hence preventing arbitary 'read' exploits. | 131 // if it's a link, hence preventing arbitary 'read' exploits. |
| 132 if (!file_util::IsLink(file_path.Append(entry.name))) | 132 if (!file_util::IsLink(file_path.Append(entry.name))) |
| 133 entries->push_back(entry); | 133 entries->push_back(entry); |
| 134 } | 134 } |
| 135 return base::PLATFORM_FILE_OK; | 135 return base::PLATFORM_FILE_OK; |
| 136 } | 136 } |
| 137 | 137 |
| 138 PlatformFileError FileSystemFileUtil::CreateDirectory( | 138 PlatformFileError FileSystemFileUtil::CreateDirectory( |
| 139 FileSystemOperationContext* fs_context, | 139 FileSystemOperationContext* unused, |
| 140 const FilePath& file_path, | 140 const FilePath& file_path, |
| 141 bool exclusive, | 141 bool exclusive, |
| 142 bool recursive) { | 142 bool recursive) { |
| 143 if (fs_context->do_not_write_actually()) | |
| 144 return base::PLATFORM_FILE_OK; | |
| 145 | |
| 146 // If parent dir of file doesn't exist. | 143 // If parent dir of file doesn't exist. |
| 147 if (!recursive && !file_util::PathExists(file_path.DirName())) | 144 if (!recursive && !file_util::PathExists(file_path.DirName())) |
| 148 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | 145 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 149 | 146 |
| 150 bool path_exists = file_util::PathExists(file_path); | 147 bool path_exists = file_util::PathExists(file_path); |
| 151 if (exclusive && path_exists) | 148 if (exclusive && path_exists) |
| 152 return base::PLATFORM_FILE_ERROR_EXISTS; | 149 return base::PLATFORM_FILE_ERROR_EXISTS; |
| 153 | 150 |
| 154 // If file exists at the path. | 151 // If file exists at the path. |
| 155 if (path_exists && !file_util::DirectoryExists(file_path)) | 152 if (path_exists && !file_util::DirectoryExists(file_path)) |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 246 PlatformFileError | 243 PlatformFileError |
| 247 FileSystemFileUtil::PerformCommonCheckAndPreparationForMoveAndCopy( | 244 FileSystemFileUtil::PerformCommonCheckAndPreparationForMoveAndCopy( |
| 248 FileSystemOperationContext* context, | 245 FileSystemOperationContext* context, |
| 249 const FilePath& src_file_path, | 246 const FilePath& src_file_path, |
| 250 const FilePath& dest_file_path) { | 247 const FilePath& dest_file_path) { |
| 251 bool same_file_system = | 248 bool same_file_system = |
| 252 (context->src_origin_url() == context->dest_origin_url()) && | 249 (context->src_origin_url() == context->dest_origin_url()) && |
| 253 (context->src_type() == context->dest_type()); | 250 (context->src_type() == context->dest_type()); |
| 254 FileSystemFileUtil* dest_util = context->dest_file_system_file_util(); | 251 FileSystemFileUtil* dest_util = context->dest_file_system_file_util(); |
| 255 DCHECK(dest_util); | 252 DCHECK(dest_util); |
| 256 if (same_file_system) | 253 scoped_ptr<FileSystemOperationContext> local_dest_context; |
| 254 FileSystemOperationContext* dest_context = NULL; | |
| 255 if (same_file_system) { | |
| 256 dest_context = context; | |
| 257 DCHECK(context->src_file_system_file_util() == | 257 DCHECK(context->src_file_system_file_util() == |
| 258 context->dest_file_system_file_util()); | 258 context->dest_file_system_file_util()); |
| 259 // All the single-path virtual FSFU methods expect the context information | 259 } else { |
| 260 // to be in the src_* variables, not the dest_* variables, so we have to | 260 local_dest_context.reset(context->CreateInheritedContextForDest()); |
| 261 // make a new context if we want to call them on the dest_file_path. | 261 // All the single-path virtual FSFU methods expect the context information |
| 262 scoped_ptr<FileSystemOperationContext> dest_context( | 262 // to be in the src_* variables, not the dest_* variables, so we have to |
| 263 context->CreateInheritedContextForDest()); | 263 // make a new context if we want to call them on the dest_file_path. |
| 264 dest_context = local_dest_context.get(); | |
| 265 } | |
| 264 | 266 |
| 265 // Exits earlier if the source path does not exist. | 267 // Exits earlier if the source path does not exist. |
| 266 if (!PathExists(context, src_file_path)) | 268 if (!PathExists(context, src_file_path)) |
| 267 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | 269 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 268 | 270 |
| 269 // The parent of the |dest_file_path| does not exist. | 271 // The parent of the |dest_file_path| does not exist. |
| 270 if (!ParentExists(dest_context.get(), dest_util, dest_file_path)) | 272 if (!ParentExists(dest_context, dest_util, dest_file_path)) |
| 271 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | 273 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 272 | 274 |
| 273 // It is an error to try to copy/move an entry into its child. | 275 // It is an error to try to copy/move an entry into its child. |
| 274 if (same_file_system && src_file_path.IsParent(dest_file_path)) | 276 if (same_file_system && src_file_path.IsParent(dest_file_path)) |
| 275 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | 277 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; |
| 276 | 278 |
| 277 // Now it is ok to return if the |dest_file_path| does not exist. | 279 // Now it is ok to return if the |dest_file_path| does not exist. |
| 278 if (!dest_util->PathExists(dest_context.get(), dest_file_path)) | 280 if (!dest_util->PathExists(dest_context, dest_file_path)) |
| 279 return base::PLATFORM_FILE_OK; | 281 return base::PLATFORM_FILE_OK; |
| 280 | 282 |
| 281 // |src_file_path| exists and is a directory. | 283 // |src_file_path| exists and is a directory. |
| 282 // |dest_file_path| exists and is a file. | 284 // |dest_file_path| exists and is a file. |
| 283 bool src_is_directory = DirectoryExists(context, src_file_path); | 285 bool src_is_directory = DirectoryExists(context, src_file_path); |
| 284 bool dest_is_directory = | 286 bool dest_is_directory = |
| 285 dest_util->DirectoryExists(dest_context.get(), dest_file_path); | 287 dest_util->DirectoryExists(dest_context, dest_file_path); |
| 286 if (src_is_directory && !dest_is_directory) | 288 if (src_is_directory && !dest_is_directory) |
| 287 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | 289 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; |
| 288 | 290 |
| 289 // |src_file_path| exists and is a file. | 291 // |src_file_path| exists and is a file. |
| 290 // |dest_file_path| exists and is a directory. | 292 // |dest_file_path| exists and is a directory. |
| 291 if (!src_is_directory && dest_is_directory) | 293 if (!src_is_directory && dest_is_directory) |
| 292 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | 294 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; |
| 293 | 295 |
| 294 // It is an error to copy/move an entry into the same path. | 296 // It is an error to copy/move an entry into the same path. |
| 295 if (same_file_system && (src_file_path.value() == dest_file_path.value())) | 297 if (same_file_system && (src_file_path.value() == dest_file_path.value())) |
| 296 return base::PLATFORM_FILE_ERROR_EXISTS; | 298 return base::PLATFORM_FILE_ERROR_EXISTS; |
| 297 | 299 |
| 298 if (dest_is_directory) { | 300 if (dest_is_directory) { |
| 299 // It is an error to copy/move an entry to a non-empty directory. | 301 // It is an error to copy/move an entry to a non-empty directory. |
| 300 // Otherwise the copy/move attempt must overwrite the destination, but | 302 // Otherwise the copy/move attempt must overwrite the destination, but |
| 301 // the file_util's Copy or Move method doesn't perform overwrite | 303 // the file_util's Copy or Move method doesn't perform overwrite |
| 302 // on all platforms, so we delete the destination directory here. | 304 // on all platforms, so we delete the destination directory here. |
| 303 // TODO(kinuko): may be better to change the file_util::{Copy,Move}. | 305 // TODO(kinuko): may be better to change the file_util::{Copy,Move}. |
| 304 PlatformFileError error = dest_util->Delete( | 306 if (base::PLATFORM_FILE_OK != |
| 305 dest_context.get(), dest_file_path, false /* recursive */); | 307 dest_util->Delete(dest_context, dest_file_path, |
| 306 context->ImportAllowedBytesGrowth(*dest_context); | 308 false /* recursive */)) { |
|
Dai Mikurube (NOT FULLTIME)
2011/08/16 05:11:00
dest_context->allowed_bytes_growth changes in Dele
ericu
2011/08/16 21:16:31
Done.
| |
| 307 if (base::PLATFORM_FILE_OK != error) { | 309 if (!dest_util->IsDirectoryEmpty(dest_context, dest_file_path)) |
| 308 if (!dest_util->IsDirectoryEmpty(dest_context.get(), dest_file_path)) | |
| 309 return base::PLATFORM_FILE_ERROR_NOT_EMPTY; | 310 return base::PLATFORM_FILE_ERROR_NOT_EMPTY; |
| 310 return base::PLATFORM_FILE_ERROR_FAILED; | 311 return base::PLATFORM_FILE_ERROR_FAILED; |
| 311 } | 312 } |
| 312 } | 313 } |
| 313 return base::PLATFORM_FILE_OK; | 314 return base::PLATFORM_FILE_OK; |
| 314 } | 315 } |
| 315 | 316 |
| 316 PlatformFileError FileSystemFileUtil::CopyOrMoveFile( | 317 PlatformFileError FileSystemFileUtil::CopyOrMoveFile( |
| 317 FileSystemOperationContext* unused, | 318 FileSystemOperationContext* unused, |
| 318 const FilePath& src_file_path, | 319 const FilePath& src_file_path, |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 335 const FilePath& dest_file_path) { | 336 const FilePath& dest_file_path) { |
| 336 return CopyOrMoveFile(context, src_file_path, dest_file_path, true); | 337 return CopyOrMoveFile(context, src_file_path, dest_file_path, true); |
| 337 } | 338 } |
| 338 | 339 |
| 339 PlatformFileError FileSystemFileUtil::CopyOrMoveDirectory( | 340 PlatformFileError FileSystemFileUtil::CopyOrMoveDirectory( |
| 340 FileSystemOperationContext* context, | 341 FileSystemOperationContext* context, |
| 341 const FilePath& src_file_path, | 342 const FilePath& src_file_path, |
| 342 const FilePath& dest_file_path, | 343 const FilePath& dest_file_path, |
| 343 bool copy) { | 344 bool copy) { |
| 344 FileSystemFileUtil* dest_util = context->dest_file_system_file_util(); | 345 FileSystemFileUtil* dest_util = context->dest_file_system_file_util(); |
| 346 // All the single-path virtual FSFU methods expect the context information to | |
| 347 // be in the src_* variables, not the dest_* variables, so we have to make a | |
| 348 // new context if we want to call them on the dest_file_path. | |
| 345 scoped_ptr<FileSystemOperationContext> dest_context( | 349 scoped_ptr<FileSystemOperationContext> dest_context( |
| 346 context->CreateInheritedContextForDest()); | 350 context->CreateInheritedContextForDest()); |
| 347 | 351 |
| 348 // Re-check PerformCommonCheckAndPreparationForMoveAndCopy() by DCHECK. | 352 // Re-check PerformCommonCheckAndPreparationForMoveAndCopy() by DCHECK. |
| 349 DCHECK(DirectoryExists(context, src_file_path)); | 353 DCHECK(DirectoryExists(context, src_file_path)); |
| 350 DCHECK(ParentExists(dest_context.get(), dest_util, dest_file_path)); | 354 DCHECK(ParentExists(dest_context.get(), dest_util, dest_file_path)); |
| 351 DCHECK(!dest_util->PathExists(dest_context.get(), dest_file_path)); | 355 DCHECK(!dest_util->PathExists(dest_context.get(), dest_file_path)); |
| 352 if ((context->src_origin_url() == context->dest_origin_url()) && | 356 if ((context->src_origin_url() == context->dest_origin_url()) && |
| 353 (context->src_type() == context->dest_type())) | 357 (context->src_type() == context->dest_type())) |
| 354 DCHECK(!src_file_path.IsParent(dest_file_path)); | 358 DCHECK(!src_file_path.IsParent(dest_file_path)); |
| 355 | 359 |
| 356 if (!dest_util->DirectoryExists(dest_context.get(), dest_file_path)) { | 360 if (!dest_util->DirectoryExists(dest_context.get(), dest_file_path)) { |
| 357 PlatformFileError error = dest_util->CreateDirectory(dest_context.get(), | 361 PlatformFileError error = dest_util->CreateDirectory(dest_context.get(), |
| 358 dest_file_path, false, false); | 362 dest_file_path, false, false); |
|
Dai Mikurube (NOT FULLTIME)
2011/08/16 05:11:00
ditto. dest_context->allowed_bytes_growth changes
ericu
2011/08/16 21:16:31
Done [only in the success cases--I don't believe w
| |
| 359 context->ImportAllowedBytesGrowth(*dest_context); | |
| 360 if (error != base::PLATFORM_FILE_OK) | 363 if (error != base::PLATFORM_FILE_OK) |
| 361 return error; | 364 return error; |
| 362 } | 365 } |
| 363 | 366 |
| 364 scoped_ptr<AbstractFileEnumerator> file_enum( | 367 scoped_ptr<AbstractFileEnumerator> file_enum( |
| 365 CreateFileEnumerator(context, src_file_path)); | 368 CreateFileEnumerator(context, src_file_path)); |
| 366 FilePath src_file_path_each; | 369 FilePath src_file_path_each; |
| 367 while (!(src_file_path_each = file_enum->Next()).empty()) { | 370 while (!(src_file_path_each = file_enum->Next()).empty()) { |
| 368 FilePath dest_file_path_each(dest_file_path); | 371 FilePath dest_file_path_each(dest_file_path); |
| 369 src_file_path.AppendRelativePath(src_file_path_each, &dest_file_path_each); | 372 src_file_path.AppendRelativePath(src_file_path_each, &dest_file_path_each); |
| 370 | 373 |
| 371 if (file_enum->IsDirectory()) { | 374 if (file_enum->IsDirectory()) { |
| 372 scoped_ptr<FileSystemOperationContext> new_directory_context( | 375 PlatformFileError error = dest_util->CreateDirectory(dest_context.get(), |
| 373 dest_context->CreateInheritedContextWithNewVirtualPaths( | 376 dest_file_path_each, false, false); |
| 374 dest_file_path_each, FilePath())); | |
| 375 PlatformFileError error = dest_util->CreateDirectory( | |
| 376 new_directory_context.get(), dest_file_path_each, false, false); | |
| 377 context->ImportAllowedBytesGrowth(*new_directory_context); | |
| 378 if (error != base::PLATFORM_FILE_OK) | 377 if (error != base::PLATFORM_FILE_OK) |
| 379 return error; | 378 return error; |
| 380 } else { | 379 } else { |
| 381 scoped_ptr<FileSystemOperationContext> copy_context( | |
| 382 context->CreateInheritedContextWithNewVirtualPaths( | |
| 383 src_file_path_each, dest_file_path_each)); | |
| 384 PlatformFileError error = CopyOrMoveFileHelper( | 380 PlatformFileError error = CopyOrMoveFileHelper( |
| 385 copy_context.get(), src_file_path_each, dest_file_path_each, copy); | 381 context, src_file_path_each, dest_file_path_each, copy); |
| 386 context->ImportAllowedBytesGrowth(*copy_context); | |
| 387 if (error != base::PLATFORM_FILE_OK) | 382 if (error != base::PLATFORM_FILE_OK) |
| 388 return error; | 383 return error; |
| 389 } | 384 } |
| 390 } | 385 } |
| 391 | 386 |
| 392 if (!copy) { | 387 if (!copy) { |
| 393 PlatformFileError error = Delete(context, src_file_path, true); | 388 PlatformFileError error = Delete(context, src_file_path, true); |
| 394 if (error != base::PLATFORM_FILE_OK) | 389 if (error != base::PLATFORM_FILE_OK) |
| 395 return error; | 390 return error; |
| 396 } | 391 } |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 462 scoped_ptr<AbstractFileEnumerator> file_enum( | 457 scoped_ptr<AbstractFileEnumerator> file_enum( |
| 463 CreateFileEnumerator(context, file_path)); | 458 CreateFileEnumerator(context, file_path)); |
| 464 FilePath file_path_each; | 459 FilePath file_path_each; |
| 465 | 460 |
| 466 std::stack<FilePath> directories; | 461 std::stack<FilePath> directories; |
| 467 while (!(file_path_each = file_enum->Next()).empty()) { | 462 while (!(file_path_each = file_enum->Next()).empty()) { |
| 468 if (file_enum->IsDirectory()) { | 463 if (file_enum->IsDirectory()) { |
| 469 directories.push(file_path_each); | 464 directories.push(file_path_each); |
| 470 } else { | 465 } else { |
| 471 // DeleteFile here is the virtual overridden member function. | 466 // DeleteFile here is the virtual overridden member function. |
| 472 scoped_ptr<FileSystemOperationContext> inherited_context( | 467 PlatformFileError error = DeleteFile(context, file_path_each); |
| 473 context->CreateInheritedContextWithNewVirtualPaths( | |
| 474 file_path_each, FilePath())); | |
| 475 PlatformFileError error = | |
| 476 DeleteFile(inherited_context.get(), file_path_each); | |
| 477 context->ImportAllowedBytesGrowth(*inherited_context); | |
| 478 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) | 468 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) |
| 479 return base::PLATFORM_FILE_ERROR_FAILED; | 469 return base::PLATFORM_FILE_ERROR_FAILED; |
| 480 else if (error != base::PLATFORM_FILE_OK) | 470 else if (error != base::PLATFORM_FILE_OK) |
| 481 return error; | 471 return error; |
| 482 } | 472 } |
| 483 } | 473 } |
| 484 | 474 |
| 485 while (!directories.empty()) { | 475 while (!directories.empty()) { |
| 486 scoped_ptr<FileSystemOperationContext> inherited_context( | 476 PlatformFileError error = DeleteSingleDirectory(context, directories.top()); |
| 487 context->CreateInheritedContextWithNewVirtualPaths( | |
| 488 directories.top(), FilePath())); | |
| 489 PlatformFileError error = | |
| 490 DeleteSingleDirectory(inherited_context.get(), directories.top()); | |
| 491 context->ImportAllowedBytesGrowth(*inherited_context); | |
| 492 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) | 477 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) |
| 493 return base::PLATFORM_FILE_ERROR_FAILED; | 478 return base::PLATFORM_FILE_ERROR_FAILED; |
| 494 else if (error != base::PLATFORM_FILE_OK) | 479 else if (error != base::PLATFORM_FILE_OK) |
| 495 return error; | 480 return error; |
| 496 directories.pop(); | 481 directories.pop(); |
| 497 } | 482 } |
| 498 return DeleteSingleDirectory(context, file_path); | 483 return DeleteSingleDirectory(context, file_path); |
| 499 } | 484 } |
| 500 | 485 |
| 501 bool FileSystemFileUtil::PathExists( | 486 bool FileSystemFileUtil::PathExists( |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 548 FileSystemFileUtil::CreateFileEnumerator( | 533 FileSystemFileUtil::CreateFileEnumerator( |
| 549 FileSystemOperationContext* unused, | 534 FileSystemOperationContext* unused, |
| 550 const FilePath& root_path) { | 535 const FilePath& root_path) { |
| 551 return new FileSystemFileEnumerator( | 536 return new FileSystemFileEnumerator( |
| 552 root_path, true, static_cast<file_util::FileEnumerator::FILE_TYPE>( | 537 root_path, true, static_cast<file_util::FileEnumerator::FILE_TYPE>( |
| 553 file_util::FileEnumerator::FILES | | 538 file_util::FileEnumerator::FILES | |
| 554 file_util::FileEnumerator::DIRECTORIES)); | 539 file_util::FileEnumerator::DIRECTORIES)); |
| 555 } | 540 } |
| 556 | 541 |
| 557 } // namespace fileapi | 542 } // namespace fileapi |
| OLD | NEW |