| OLD | NEW |
| (Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 // Useful functions: FilePath::CompareIgnoreCase, FilePath::value [returns a |
| 6 // StringType]. |
| 7 |
| 8 #include "webkit/fileapi/obfuscated_file_util.h" |
| 9 |
| 10 #include "base/file_util.h" |
| 11 #include "base/logging.h" |
| 12 #include "webkit/fileapi/file_system_context.h" |
| 13 #include "webkit/fileapi/file_system_operation_context.h" |
| 14 #include "webkit/fileapi/file_system_path_manager.h" |
| 15 #include "webkit/fileapi/path_obfuscator.h" |
| 16 |
| 17 namespace fileapi { |
| 18 |
| 19 ObfuscatedFileUtil* ObfuscatedFileUtil::GetInstance() { |
| 20 return Singleton<ObfuscatedFileUtil>::get(); |
| 21 } |
| 22 |
| 23 PlatformFileError ObfuscatedFileUtil::CreateOrOpen( |
| 24 FileSystemOperationContext* context, |
| 25 const FilePath& file_path, |
| 26 int file_flags, |
| 27 PlatformFile* file_handle, |
| 28 bool *created) { |
| 29 FilePath root_path; |
| 30 FilePath virtual_path; |
| 31 |
| 32 CHECK(context->file_system_context()->path_manager()->CrackFileSystemPath( |
| 33 file_path, NULL, NULL, &root_path, &virtual_path)); |
| 34 |
| 35 fileapi::PathObfuscator obfuscator(root_path); |
| 36 FilePath obfuscated_path = |
| 37 obfuscator.ObfuscatedPathFromClearPath(virtual_path); |
| 38 FilePath full_path = root_path.Append(obfuscated_path); |
| 39 |
| 40 if (!file_util::DirectoryExists(full_path.DirName())) { |
| 41 // If its parent does not exist, should return NOT_FOUND error. |
| 42 *file_handle = base::kInvalidPlatformFileValue; |
| 43 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 44 } |
| 45 FilePath temp; |
| 46 bool need_commit = false; |
| 47 |
| 48 // Check whether we have a dictionary entry for the file first, so that we can |
| 49 // record that we're going to try to create it if we don't. |
| 50 PlatformFileError error = |
| 51 obfuscator.ClearPathFromObfuscatedPath(obfuscated_path, &temp); |
| 52 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) { |
| 53 error = obfuscator.PrepareAdd(virtual_path, obfuscated_path); |
| 54 need_commit = true; |
| 55 } |
| 56 if (error != base::PLATFORM_FILE_OK) { |
| 57 *file_handle = base::kInvalidPlatformFileValue; |
| 58 return error; |
| 59 } |
| 60 *file_handle = |
| 61 base::CreatePlatformFile(full_path, file_flags, NULL, &error); |
| 62 const int CREATE_EXCLUSIVE = |
| 63 base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_EXCLUSIVE_WRITE; |
| 64 if (error == base::PLATFORM_FILE_ERROR_EXISTS && need_commit && |
| 65 ((file_flags & CREATE_EXCLUSIVE) == CREATE_EXCLUSIVE)) { |
| 66 // The file existed, but wasn't in the dictionary. The user tried an |
| 67 // exclusive create, and it failed by collision. We should add the file to |
| 68 // the dictionary [recovering from some corruption], but report the |
| 69 // collision. |
| 70 obfuscator.Commit(); |
| 71 *file_handle = base::kInvalidPlatformFileValue; |
| 72 return error; |
| 73 } else if (error != base::PLATFORM_FILE_OK) { |
| 74 if (need_commit) |
| 75 obfuscator.Rollback(); |
| 76 *file_handle = base::kInvalidPlatformFileValue; |
| 77 return error; |
| 78 } |
| 79 if (need_commit) |
| 80 obfuscator.Commit(); |
| 81 return base::PLATFORM_FILE_OK; |
| 82 } |
| 83 |
| 84 |
| 85 PlatformFileError ObfuscatedFileUtil::CreateDirectory( |
| 86 FileSystemOperationContext* context, |
| 87 const FilePath& file_path, |
| 88 bool exclusive) { |
| 89 FilePath root_path; |
| 90 FilePath virtual_path; |
| 91 |
| 92 CHECK(context->file_system_context()->path_manager()->CrackFileSystemPath( |
| 93 file_path, NULL, NULL, &root_path, &virtual_path)); |
| 94 |
| 95 fileapi::PathObfuscator obfuscator(root_path); |
| 96 FilePath obfuscated_path = |
| 97 obfuscator.ObfuscatedPathFromClearPath(virtual_path); |
| 98 FilePath full_path = root_path.Append(obfuscated_path); |
| 99 if (!file_util::PathExists(full_path.DirName())) { |
| 100 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 101 } |
| 102 bool path_exists = file_util::PathExists(full_path); |
| 103 if (exclusive && path_exists) { |
| 104 // TODO(ericu): What if it's not in the dictionary? |
| 105 return base::PLATFORM_FILE_ERROR_EXISTS; |
| 106 } |
| 107 if (path_exists && !file_util::DirectoryExists(full_path)) { |
| 108 return base::PLATFORM_FILE_ERROR_EXISTS; |
| 109 } |
| 110 bool inhibit_commit = false; |
| 111 PlatformFileError error = |
| 112 obfuscator.PrepareAdd(virtual_path, obfuscated_path); |
| 113 if (error != base::PLATFORM_FILE_OK) { |
| 114 if (path_exists && !exclusive && |
| 115 error == base::PLATFORM_FILE_ERROR_EXISTS) { |
| 116 return base::PLATFORM_FILE_OK; |
| 117 } |
| 118 if (path_exists || error != base::PLATFORM_FILE_ERROR_EXISTS) { |
| 119 return error; |
| 120 } |
| 121 // Else it's in the dictionary, but not on the disk. We recover from this |
| 122 // corruption by just creating the directory and leaving the dictionary |
| 123 // alone. |
| 124 inhibit_commit = true; |
| 125 } |
| 126 |
| 127 // TODO: Replace this call with a call to |
| 128 // QuotaFileUtil::GetInstance()->CreateDirectory(). |
| 129 if (!file_util::CreateDirectory(full_path)) { |
| 130 obfuscator.Rollback(); |
| 131 return base::PLATFORM_FILE_ERROR_FAILED; |
| 132 } |
| 133 if (!inhibit_commit) |
| 134 obfuscator.Commit(); |
| 135 return base::PLATFORM_FILE_OK; |
| 136 } |
| 137 |
| 138 } // namespace fileapi |
| OLD | NEW |