| 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> | |
| 9 | 8 |
| 10 #include "base/file_util_proxy.h" | |
| 11 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 12 #include "webkit/fileapi/file_system_operation_context.h" | 10 #include "webkit/fileapi/file_system_operation_context.h" |
| 13 | 11 |
| 14 namespace fileapi { | 12 namespace fileapi { |
| 15 | 13 |
| 16 namespace { | 14 namespace { |
| 17 | 15 |
| 18 // This assumes that the root exists. | 16 // This assumes that the root exists. |
| 19 bool ParentExists(FileSystemOperationContext* context, | 17 bool ParentExists(FileSystemOperationContext* context, |
| 20 FileSystemFileUtil* file_util, const FilePath& file_path) { | 18 FileSystemFileUtil* file_util, const FilePath& file_path) { |
| 21 // If file_path is in the root, file_path.DirName() will be ".", | 19 // If file_path is in the root, file_path.DirName() will be ".", |
| 22 // since we use paths with no leading '/'. | 20 // since we use paths with no leading '/'. |
| 23 FilePath parent = file_path.DirName(); | 21 FilePath parent = file_path.DirName(); |
| 24 if (parent == FilePath(FILE_PATH_LITERAL("."))) | 22 if (parent == FilePath(FILE_PATH_LITERAL("."))) |
| 25 return true; | 23 return true; |
| 26 return file_util->DirectoryExists(context, parent); | 24 return file_util->DirectoryExists(context, parent); |
| 27 } | 25 } |
| 28 | 26 |
| 29 } // namespace | 27 } // namespace |
| 30 | 28 |
| 31 PlatformFileError FileSystemFileUtil::CreateOrOpen( | 29 FileSystemFileUtil::FileSystemFileUtil() { |
| 32 FileSystemOperationContext* unused, | |
| 33 const FilePath& file_path, int file_flags, | |
| 34 PlatformFile* file_handle, bool* created) { | |
| 35 if (!file_util::DirectoryExists(file_path.DirName())) { | |
| 36 // If its parent does not exist, should return NOT_FOUND error. | |
| 37 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 38 } | |
| 39 PlatformFileError error_code = base::PLATFORM_FILE_OK; | |
| 40 *file_handle = base::CreatePlatformFile(file_path, file_flags, | |
| 41 created, &error_code); | |
| 42 return error_code; | |
| 43 } | 30 } |
| 44 | 31 |
| 45 PlatformFileError FileSystemFileUtil::Close( | 32 FileSystemFileUtil::FileSystemFileUtil(FileSystemFileUtil* underlying_file_util) |
| 46 FileSystemOperationContext* unused, | 33 : underlying_file_util_(underlying_file_util) { |
| 47 PlatformFile file_handle) { | |
| 48 if (!base::ClosePlatformFile(file_handle)) | |
| 49 return base::PLATFORM_FILE_ERROR_FAILED; | |
| 50 return base::PLATFORM_FILE_OK; | |
| 51 } | 34 } |
| 52 | 35 |
| 53 PlatformFileError FileSystemFileUtil::EnsureFileExists( | 36 FileSystemFileUtil::~FileSystemFileUtil() { |
| 54 FileSystemOperationContext* unused, | |
| 55 const FilePath& file_path, | |
| 56 bool* created) { | |
| 57 if (!file_util::DirectoryExists(file_path.DirName())) | |
| 58 // If its parent does not exist, should return NOT_FOUND error. | |
| 59 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 60 PlatformFileError error_code = base::PLATFORM_FILE_OK; | |
| 61 // Tries to create the |file_path| exclusively. This should fail | |
| 62 // with base::PLATFORM_FILE_ERROR_EXISTS if the path already exists. | |
| 63 PlatformFile handle = base::CreatePlatformFile( | |
| 64 file_path, | |
| 65 base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_READ, | |
| 66 created, &error_code); | |
| 67 if (error_code == base::PLATFORM_FILE_ERROR_EXISTS) { | |
| 68 // Make sure created_ is false. | |
| 69 if (created) | |
| 70 *created = false; | |
| 71 error_code = base::PLATFORM_FILE_OK; | |
| 72 } | |
| 73 if (handle != base::kInvalidPlatformFileValue) | |
| 74 base::ClosePlatformFile(handle); | |
| 75 return error_code; | |
| 76 } | |
| 77 | |
| 78 PlatformFileError FileSystemFileUtil::GetLocalFilePath( | |
| 79 FileSystemOperationContext* context, | |
| 80 const FilePath& virtual_path, | |
| 81 FilePath* local_path) { | |
| 82 *local_path = virtual_path; | |
| 83 return base::PLATFORM_FILE_OK; | |
| 84 } | |
| 85 | |
| 86 PlatformFileError FileSystemFileUtil::GetFileInfo( | |
| 87 FileSystemOperationContext* unused, | |
| 88 const FilePath& file_path, | |
| 89 base::PlatformFileInfo* file_info, | |
| 90 FilePath* platform_file_path) { | |
| 91 if (!file_util::PathExists(file_path)) | |
| 92 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 93 // TODO(rkc): Fix this hack once we have refactored file_util to handle | |
| 94 // symlinks correctly. | |
| 95 // http://code.google.com/p/chromium-os/issues/detail?id=15948 | |
| 96 if (file_util::IsLink(file_path)) | |
| 97 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 98 if (!file_util::GetFileInfo(file_path, file_info)) | |
| 99 return base::PLATFORM_FILE_ERROR_FAILED; | |
| 100 *platform_file_path = file_path; | |
| 101 return base::PLATFORM_FILE_OK; | |
| 102 } | |
| 103 | |
| 104 PlatformFileError FileSystemFileUtil::ReadDirectory( | |
| 105 FileSystemOperationContext* unused, | |
| 106 const FilePath& file_path, | |
| 107 std::vector<base::FileUtilProxy::Entry>* entries) { | |
| 108 // TODO(kkanetkar): Implement directory read in multiple chunks. | |
| 109 if (!file_util::DirectoryExists(file_path)) | |
| 110 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 111 | |
| 112 file_util::FileEnumerator file_enum( | |
| 113 file_path, false, static_cast<file_util::FileEnumerator::FileType>( | |
| 114 file_util::FileEnumerator::FILES | | |
| 115 file_util::FileEnumerator::DIRECTORIES)); | |
| 116 FilePath current; | |
| 117 while (!(current = file_enum.Next()).empty()) { | |
| 118 base::FileUtilProxy::Entry entry; | |
| 119 file_util::FileEnumerator::FindInfo info; | |
| 120 file_enum.GetFindInfo(&info); | |
| 121 entry.is_directory = file_enum.IsDirectory(info); | |
| 122 // This will just give the entry's name instead of entire path | |
| 123 // if we use current.value(). | |
| 124 entry.name = file_util::FileEnumerator::GetFilename(info).value(); | |
| 125 entry.size = file_util::FileEnumerator::GetFilesize(info); | |
| 126 entry.last_modified_time = | |
| 127 file_util::FileEnumerator::GetLastModifiedTime(info); | |
| 128 // TODO(rkc): Fix this also once we've refactored file_util | |
| 129 // http://code.google.com/p/chromium-os/issues/detail?id=15948 | |
| 130 // This currently just prevents a file from showing up at all | |
| 131 // if it's a link, hence preventing arbitary 'read' exploits. | |
| 132 if (!file_util::IsLink(file_path.Append(entry.name))) | |
| 133 entries->push_back(entry); | |
| 134 } | |
| 135 return base::PLATFORM_FILE_OK; | |
| 136 } | |
| 137 | |
| 138 PlatformFileError FileSystemFileUtil::CreateDirectory( | |
| 139 FileSystemOperationContext* unused, | |
| 140 const FilePath& file_path, | |
| 141 bool exclusive, | |
| 142 bool recursive) { | |
| 143 // If parent dir of file doesn't exist. | |
| 144 if (!recursive && !file_util::PathExists(file_path.DirName())) | |
| 145 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 146 | |
| 147 bool path_exists = file_util::PathExists(file_path); | |
| 148 if (exclusive && path_exists) | |
| 149 return base::PLATFORM_FILE_ERROR_EXISTS; | |
| 150 | |
| 151 // If file exists at the path. | |
| 152 if (path_exists && !file_util::DirectoryExists(file_path)) | |
| 153 return base::PLATFORM_FILE_ERROR_EXISTS; | |
| 154 | |
| 155 if (!file_util::CreateDirectory(file_path)) | |
| 156 return base::PLATFORM_FILE_ERROR_FAILED; | |
| 157 return base::PLATFORM_FILE_OK; | |
| 158 } | 37 } |
| 159 | 38 |
| 160 PlatformFileError FileSystemFileUtil::Copy( | 39 PlatformFileError FileSystemFileUtil::Copy( |
| 161 FileSystemOperationContext* context, | 40 FileSystemOperationContext* context, |
| 162 const FilePath& src_file_path, | 41 const FilePath& src_file_path, |
| 163 const FilePath& dest_file_path) { | 42 const FilePath& dest_file_path) { |
| 164 PlatformFileError error_code; | 43 PlatformFileError error_code; |
| 165 error_code = | 44 error_code = |
| 166 PerformCommonCheckAndPreparationForMoveAndCopy( | 45 PerformCommonCheckAndPreparationForMoveAndCopy( |
| 167 context, src_file_path, dest_file_path); | 46 context, src_file_path, dest_file_path); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 if (DirectoryExists(context, file_path)) { | 80 if (DirectoryExists(context, file_path)) { |
| 202 if (!recursive) | 81 if (!recursive) |
| 203 return DeleteSingleDirectory(context, file_path); | 82 return DeleteSingleDirectory(context, file_path); |
| 204 else | 83 else |
| 205 return DeleteDirectoryRecursive(context, file_path); | 84 return DeleteDirectoryRecursive(context, file_path); |
| 206 } else { | 85 } else { |
| 207 return DeleteFile(context, file_path); | 86 return DeleteFile(context, file_path); |
| 208 } | 87 } |
| 209 } | 88 } |
| 210 | 89 |
| 90 PlatformFileError FileSystemFileUtil::CreateOrOpen( |
| 91 FileSystemOperationContext* context, |
| 92 const FilePath& file_path, int file_flags, |
| 93 PlatformFile* file_handle, bool* created) { |
| 94 if (underlying_file_util_.get()) { |
| 95 return underlying_file_util_->CreateOrOpen( |
| 96 context, file_path, file_flags, file_handle, created); |
| 97 } |
| 98 NOTREACHED() << "Subclasses must provide implementation if they have no" |
| 99 << "underlying_file_util"; |
| 100 return base::PLATFORM_FILE_ERROR_FAILED; |
| 101 } |
| 102 |
| 103 PlatformFileError FileSystemFileUtil::Close( |
| 104 FileSystemOperationContext* context, |
| 105 PlatformFile file_handle) { |
| 106 if (underlying_file_util_.get()) { |
| 107 return underlying_file_util_->Close(context, file_handle); |
| 108 } |
| 109 NOTREACHED() << "Subclasses must provide implementation if they have no" |
| 110 << "underlying_file_util"; |
| 111 return base::PLATFORM_FILE_ERROR_FAILED; |
| 112 } |
| 113 |
| 114 PlatformFileError FileSystemFileUtil::EnsureFileExists( |
| 115 FileSystemOperationContext* context, |
| 116 const FilePath& file_path, |
| 117 bool* created) { |
| 118 if (underlying_file_util_.get()) { |
| 119 return underlying_file_util_->EnsureFileExists(context, file_path, created); |
| 120 } |
| 121 NOTREACHED() << "Subclasses must provide implementation if they have no" |
| 122 << "underlying_file_util"; |
| 123 return base::PLATFORM_FILE_ERROR_FAILED; |
| 124 } |
| 125 |
| 126 PlatformFileError FileSystemFileUtil::CreateDirectory( |
| 127 FileSystemOperationContext* context, |
| 128 const FilePath& file_path, |
| 129 bool exclusive, |
| 130 bool recursive) { |
| 131 if (underlying_file_util_.get()) { |
| 132 return underlying_file_util_->CreateDirectory( |
| 133 context, file_path, exclusive, recursive); |
| 134 } |
| 135 NOTREACHED() << "Subclasses must provide implementation if they have no" |
| 136 << "underlying_file_util"; |
| 137 return base::PLATFORM_FILE_ERROR_FAILED; |
| 138 } |
| 139 |
| 140 PlatformFileError FileSystemFileUtil::GetFileInfo( |
| 141 FileSystemOperationContext* context, |
| 142 const FilePath& file_path, |
| 143 base::PlatformFileInfo* file_info, |
| 144 FilePath* platform_file_path) { |
| 145 if (underlying_file_util_.get()) { |
| 146 return underlying_file_util_->GetFileInfo( |
| 147 context, file_path, file_info, platform_file_path); |
| 148 } |
| 149 NOTREACHED() << "Subclasses must provide implementation if they have no" |
| 150 << "underlying_file_util"; |
| 151 return base::PLATFORM_FILE_ERROR_FAILED; |
| 152 } |
| 153 |
| 154 PlatformFileError FileSystemFileUtil::ReadDirectory( |
| 155 FileSystemOperationContext* context, |
| 156 const FilePath& file_path, |
| 157 std::vector<base::FileUtilProxy::Entry>* entries) { |
| 158 if (underlying_file_util_.get()) { |
| 159 return underlying_file_util_->ReadDirectory(context, file_path, entries); |
| 160 } |
| 161 NOTREACHED() << "Subclasses must provide implementation if they have no" |
| 162 << "underlying_file_util"; |
| 163 return base::PLATFORM_FILE_ERROR_FAILED; |
| 164 } |
| 165 |
| 166 FileSystemFileUtil::AbstractFileEnumerator* |
| 167 FileSystemFileUtil::CreateFileEnumerator( |
| 168 FileSystemOperationContext* context, |
| 169 const FilePath& root_path) { |
| 170 if (underlying_file_util_.get()) { |
| 171 return underlying_file_util_->CreateFileEnumerator(context, root_path); |
| 172 } |
| 173 NOTREACHED() << "Subclasses must provide implementation if they have no" |
| 174 << "underlying_file_util"; |
| 175 return NULL; |
| 176 } |
| 177 |
| 178 PlatformFileError FileSystemFileUtil::GetLocalFilePath( |
| 179 FileSystemOperationContext* context, |
| 180 const FilePath& virtual_path, |
| 181 FilePath* local_path) { |
| 182 if (underlying_file_util_.get()) { |
| 183 return underlying_file_util_->GetLocalFilePath( |
| 184 context, virtual_path, local_path); |
| 185 } |
| 186 NOTREACHED() << "Subclasses must provide implementation if they have no" |
| 187 << "underlying_file_util"; |
| 188 return base::PLATFORM_FILE_ERROR_FAILED; |
| 189 } |
| 190 |
| 211 PlatformFileError FileSystemFileUtil::Touch( | 191 PlatformFileError FileSystemFileUtil::Touch( |
| 212 FileSystemOperationContext* unused, | 192 FileSystemOperationContext* context, |
| 213 const FilePath& file_path, | 193 const FilePath& file_path, |
| 214 const base::Time& last_access_time, | 194 const base::Time& last_access_time, |
| 215 const base::Time& last_modified_time) { | 195 const base::Time& last_modified_time) { |
| 216 if (!file_util::TouchFile( | 196 if (underlying_file_util_.get()) { |
| 217 file_path, last_access_time, last_modified_time)) | 197 return underlying_file_util_->Touch( |
| 218 return base::PLATFORM_FILE_ERROR_FAILED; | 198 context, file_path, last_access_time, last_modified_time); |
| 219 return base::PLATFORM_FILE_OK; | 199 } |
| 200 NOTREACHED() << "Subclasses must provide implementation if they have no" |
| 201 << "underlying_file_util"; |
| 202 return base::PLATFORM_FILE_ERROR_FAILED; |
| 220 } | 203 } |
| 221 | 204 |
| 222 PlatformFileError FileSystemFileUtil::Truncate( | 205 PlatformFileError FileSystemFileUtil::Truncate( |
| 223 FileSystemOperationContext* unused, | 206 FileSystemOperationContext* context, |
| 224 const FilePath& file_path, | 207 const FilePath& file_path, |
| 225 int64 length) { | 208 int64 length) { |
| 226 PlatformFileError error_code(base::PLATFORM_FILE_ERROR_FAILED); | 209 if (underlying_file_util_.get()) { |
| 227 PlatformFile file = | 210 return underlying_file_util_->Truncate(context, file_path, length); |
| 228 base::CreatePlatformFile( | 211 } |
| 229 file_path, | 212 NOTREACHED() << "Subclasses must provide implementation if they have no" |
| 230 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE, | 213 << "underlying_file_util"; |
| 231 NULL, | 214 return base::PLATFORM_FILE_ERROR_FAILED; |
| 232 &error_code); | 215 } |
| 233 if (error_code != base::PLATFORM_FILE_OK) { | 216 |
| 234 return error_code; | 217 |
| 235 } | 218 bool FileSystemFileUtil::PathExists( |
| 236 DCHECK_NE(base::kInvalidPlatformFileValue, file); | 219 FileSystemOperationContext* context, |
| 237 if (!base::TruncatePlatformFile(file, length)) | 220 const FilePath& file_path) { |
| 238 error_code = base::PLATFORM_FILE_ERROR_FAILED; | 221 if (underlying_file_util_.get()) { |
| 239 base::ClosePlatformFile(file); | 222 return underlying_file_util_->PathExists(context, file_path); |
| 240 return error_code; | 223 } |
| 224 NOTREACHED() << "Subclasses must provide implementation if they have no" |
| 225 << "underlying_file_util"; |
| 226 return false; |
| 227 } |
| 228 |
| 229 bool FileSystemFileUtil::DirectoryExists( |
| 230 FileSystemOperationContext* context, |
| 231 const FilePath& file_path) { |
| 232 if (underlying_file_util_.get()) { |
| 233 return underlying_file_util_->DirectoryExists(context, file_path); |
| 234 } |
| 235 NOTREACHED() << "Subclasses must provide implementation if they have no" |
| 236 << "underlying_file_util"; |
| 237 return false; |
| 238 } |
| 239 |
| 240 bool FileSystemFileUtil::IsDirectoryEmpty( |
| 241 FileSystemOperationContext* context, |
| 242 const FilePath& file_path) { |
| 243 if (underlying_file_util_.get()) { |
| 244 return underlying_file_util_->IsDirectoryEmpty(context, file_path); |
| 245 } |
| 246 NOTREACHED() << "Subclasses must provide implementation if they have no" |
| 247 << "underlying_file_util"; |
| 248 return false; |
| 249 } |
| 250 |
| 251 PlatformFileError FileSystemFileUtil::CopyOrMoveFile( |
| 252 FileSystemOperationContext* context, |
| 253 const FilePath& src_file_path, |
| 254 const FilePath& dest_file_path, |
| 255 bool copy) { |
| 256 if (underlying_file_util_.get()) { |
| 257 return underlying_file_util_->CopyOrMoveFile( |
| 258 context, src_file_path, dest_file_path, copy); |
| 259 } |
| 260 NOTREACHED() << "Subclasses must provide implementation if they have no" |
| 261 << "underlying_file_util"; |
| 262 return base::PLATFORM_FILE_ERROR_FAILED; |
| 263 } |
| 264 |
| 265 PlatformFileError FileSystemFileUtil::CopyInForeignFile( |
| 266 FileSystemOperationContext* context, |
| 267 const FilePath& src_file_path, |
| 268 const FilePath& dest_file_path) { |
| 269 if (underlying_file_util_.get()) { |
| 270 return underlying_file_util_->CopyInForeignFile( |
| 271 context, src_file_path, dest_file_path); |
| 272 } |
| 273 NOTREACHED() << "Subclasses must provide implementation if they have no" |
| 274 << "underlying_file_util"; |
| 275 return base::PLATFORM_FILE_ERROR_FAILED; |
| 276 } |
| 277 |
| 278 PlatformFileError FileSystemFileUtil::DeleteFile( |
| 279 FileSystemOperationContext* context, |
| 280 const FilePath& file_path) { |
| 281 if (underlying_file_util_.get()) { |
| 282 return underlying_file_util_->DeleteFile(context, file_path); |
| 283 } |
| 284 NOTREACHED() << "Subclasses must provide implementation if they have no" |
| 285 << "underlying_file_util"; |
| 286 return base::PLATFORM_FILE_ERROR_FAILED; |
| 287 } |
| 288 |
| 289 PlatformFileError FileSystemFileUtil::DeleteSingleDirectory( |
| 290 FileSystemOperationContext* context, |
| 291 const FilePath& file_path) { |
| 292 if (underlying_file_util_.get()) { |
| 293 return underlying_file_util_->DeleteSingleDirectory(context, file_path); |
| 294 } |
| 295 NOTREACHED() << "Subclasses must provide implementation if they have no" |
| 296 << "underlying_file_util"; |
| 297 return base::PLATFORM_FILE_ERROR_FAILED; |
| 241 } | 298 } |
| 242 | 299 |
| 243 PlatformFileError | 300 PlatformFileError |
| 244 FileSystemFileUtil::PerformCommonCheckAndPreparationForMoveAndCopy( | 301 FileSystemFileUtil::PerformCommonCheckAndPreparationForMoveAndCopy( |
| 245 FileSystemOperationContext* context, | 302 FileSystemOperationContext* context, |
| 246 const FilePath& src_file_path, | 303 const FilePath& src_file_path, |
| 247 const FilePath& dest_file_path) { | 304 const FilePath& dest_file_path) { |
| 248 bool same_file_system = | 305 bool same_file_system = |
| 249 (context->src_origin_url() == context->dest_origin_url()) && | 306 (context->src_origin_url() == context->dest_origin_url()) && |
| 250 (context->src_type() == context->dest_type()); | 307 (context->src_type() == context->dest_type()); |
| 251 FileSystemFileUtil* dest_util = context->dest_file_system_file_util(); | 308 FileSystemFileUtil* dest_util = context->dest_file_util(); |
| 252 DCHECK(dest_util); | 309 DCHECK(dest_util); |
| 253 scoped_ptr<FileSystemOperationContext> local_dest_context; | 310 scoped_ptr<FileSystemOperationContext> local_dest_context; |
| 254 FileSystemOperationContext* dest_context = NULL; | 311 FileSystemOperationContext* dest_context = NULL; |
| 255 if (same_file_system) { | 312 if (same_file_system) { |
| 256 dest_context = context; | 313 dest_context = context; |
| 257 DCHECK(context->src_file_system_file_util() == | 314 DCHECK(context->src_file_util() == context->dest_file_util()); |
| 258 context->dest_file_system_file_util()); | |
| 259 } else { | 315 } else { |
| 260 local_dest_context.reset(context->CreateInheritedContextForDest()); | 316 local_dest_context.reset(context->CreateInheritedContextForDest()); |
| 261 // All the single-path virtual FSFU methods expect the context information | 317 // All the single-path virtual FSFU methods expect the context information |
| 262 // to be in the src_* variables, not the dest_* variables, so we have to | 318 // to be in the src_* variables, not the dest_* variables, so we have to |
| 263 // make a new context if we want to call them on the dest_file_path. | 319 // make a new context if we want to call them on the dest_file_path. |
| 264 dest_context = local_dest_context.get(); | 320 dest_context = local_dest_context.get(); |
| 265 } | 321 } |
| 266 | 322 |
| 267 // Exits earlier if the source path does not exist. | 323 // Exits earlier if the source path does not exist. |
| 268 if (!PathExists(context, src_file_path)) | 324 if (!PathExists(context, src_file_path)) |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 return base::PLATFORM_FILE_ERROR_NOT_EMPTY; | 366 return base::PLATFORM_FILE_ERROR_NOT_EMPTY; |
| 311 return base::PLATFORM_FILE_ERROR_FAILED; | 367 return base::PLATFORM_FILE_ERROR_FAILED; |
| 312 } | 368 } |
| 313 // Reflect changes in usage back to the original context. | 369 // Reflect changes in usage back to the original context. |
| 314 if (!same_file_system) | 370 if (!same_file_system) |
| 315 context->set_allowed_bytes_growth(dest_context->allowed_bytes_growth()); | 371 context->set_allowed_bytes_growth(dest_context->allowed_bytes_growth()); |
| 316 } | 372 } |
| 317 return base::PLATFORM_FILE_OK; | 373 return base::PLATFORM_FILE_OK; |
| 318 } | 374 } |
| 319 | 375 |
| 320 PlatformFileError FileSystemFileUtil::CopyOrMoveFile( | |
| 321 FileSystemOperationContext* unused, | |
| 322 const FilePath& src_file_path, | |
| 323 const FilePath& dest_file_path, | |
| 324 bool copy) { | |
| 325 if (copy) { | |
| 326 if (file_util::CopyFile(src_file_path, dest_file_path)) | |
| 327 return base::PLATFORM_FILE_OK; | |
| 328 } else { | |
| 329 DCHECK(!file_util::DirectoryExists(src_file_path)); | |
| 330 if (file_util::Move(src_file_path, dest_file_path)) | |
| 331 return base::PLATFORM_FILE_OK; | |
| 332 } | |
| 333 return base::PLATFORM_FILE_ERROR_FAILED; | |
| 334 } | |
| 335 | |
| 336 PlatformFileError FileSystemFileUtil::CopyInForeignFile( | |
| 337 FileSystemOperationContext* context, | |
| 338 const FilePath& src_file_path, | |
| 339 const FilePath& dest_file_path) { | |
| 340 return CopyOrMoveFile(context, src_file_path, dest_file_path, true); | |
| 341 } | |
| 342 | |
| 343 PlatformFileError FileSystemFileUtil::CopyOrMoveDirectory( | 376 PlatformFileError FileSystemFileUtil::CopyOrMoveDirectory( |
| 344 FileSystemOperationContext* context, | 377 FileSystemOperationContext* context, |
| 345 const FilePath& src_file_path, | 378 const FilePath& src_file_path, |
| 346 const FilePath& dest_file_path, | 379 const FilePath& dest_file_path, |
| 347 bool copy) { | 380 bool copy) { |
| 348 FileSystemFileUtil* dest_util = context->dest_file_system_file_util(); | 381 FileSystemFileUtil* dest_util = context->dest_file_util(); |
| 349 // All the single-path virtual FSFU methods expect the context information to | 382 // All the single-path virtual FSFU methods expect the context information to |
| 350 // be in the src_* variables, not the dest_* variables, so we have to make a | 383 // be in the src_* variables, not the dest_* variables, so we have to make a |
| 351 // new context if we want to call them on the dest_file_path. | 384 // new context if we want to call them on the dest_file_path. |
| 352 scoped_ptr<FileSystemOperationContext> dest_context( | 385 scoped_ptr<FileSystemOperationContext> dest_context( |
| 353 context->CreateInheritedContextForDest()); | 386 context->CreateInheritedContextForDest()); |
| 354 | 387 |
| 355 // Re-check PerformCommonCheckAndPreparationForMoveAndCopy() by DCHECK. | 388 // Re-check PerformCommonCheckAndPreparationForMoveAndCopy() by DCHECK. |
| 356 DCHECK(DirectoryExists(context, src_file_path)); | 389 DCHECK(DirectoryExists(context, src_file_path)); |
| 357 DCHECK(ParentExists(dest_context.get(), dest_util, dest_file_path)); | 390 DCHECK(ParentExists(dest_context.get(), dest_util, dest_file_path)); |
| 358 DCHECK(!dest_util->PathExists(dest_context.get(), dest_file_path)); | 391 DCHECK(!dest_util->PathExists(dest_context.get(), dest_file_path)); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 } | 434 } |
| 402 | 435 |
| 403 PlatformFileError FileSystemFileUtil::CopyOrMoveFileHelper( | 436 PlatformFileError FileSystemFileUtil::CopyOrMoveFileHelper( |
| 404 FileSystemOperationContext* context, | 437 FileSystemOperationContext* context, |
| 405 const FilePath& src_file_path, | 438 const FilePath& src_file_path, |
| 406 const FilePath& dest_file_path, | 439 const FilePath& dest_file_path, |
| 407 bool copy) { | 440 bool copy) { |
| 408 // CopyOrMoveFile here is the virtual overridden member function. | 441 // CopyOrMoveFile here is the virtual overridden member function. |
| 409 if ((context->src_origin_url() == context->dest_origin_url()) && | 442 if ((context->src_origin_url() == context->dest_origin_url()) && |
| 410 (context->src_type() == context->dest_type())) { | 443 (context->src_type() == context->dest_type())) { |
| 411 DCHECK(context->src_file_system_file_util() == | 444 DCHECK(context->src_file_util() == context->dest_file_util()); |
| 412 context->dest_file_system_file_util()); | |
| 413 return CopyOrMoveFile(context, src_file_path, dest_file_path, copy); | 445 return CopyOrMoveFile(context, src_file_path, dest_file_path, copy); |
| 414 } | 446 } |
| 415 base::PlatformFileInfo file_info; | 447 base::PlatformFileInfo file_info; |
| 416 FilePath platform_file_path; | 448 FilePath platform_file_path; |
| 417 PlatformFileError error_code; | 449 PlatformFileError error_code; |
| 418 error_code = | 450 error_code = |
| 419 GetFileInfo(context, src_file_path, &file_info, &platform_file_path); | 451 GetFileInfo(context, src_file_path, &file_info, &platform_file_path); |
| 420 if (error_code != base::PLATFORM_FILE_OK) | 452 if (error_code != base::PLATFORM_FILE_OK) |
| 421 return error_code; | 453 return error_code; |
| 422 | 454 |
| 423 DCHECK(context->dest_file_system_file_util()); | 455 DCHECK(context->dest_file_util()); |
| 424 error_code = context->dest_file_system_file_util()->CopyInForeignFile( | 456 error_code = context->dest_file_util()->CopyInForeignFile( |
| 425 context, platform_file_path, dest_file_path); | 457 context, platform_file_path, dest_file_path); |
| 426 if (copy || error_code != base::PLATFORM_FILE_OK) | 458 if (copy || error_code != base::PLATFORM_FILE_OK) |
| 427 return error_code; | 459 return error_code; |
| 428 return DeleteFile(context, src_file_path); | 460 return DeleteFile(context, src_file_path); |
| 429 } | 461 } |
| 430 | 462 |
| 431 | |
| 432 PlatformFileError FileSystemFileUtil::DeleteFile( | |
| 433 FileSystemOperationContext* unused, | |
| 434 const FilePath& file_path) { | |
| 435 if (!file_util::PathExists(file_path)) | |
| 436 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 437 if (file_util::DirectoryExists(file_path)) | |
| 438 return base::PLATFORM_FILE_ERROR_NOT_A_FILE; | |
| 439 if (!file_util::Delete(file_path, false)) | |
| 440 return base::PLATFORM_FILE_ERROR_FAILED; | |
| 441 return base::PLATFORM_FILE_OK; | |
| 442 } | |
| 443 | |
| 444 PlatformFileError FileSystemFileUtil::DeleteSingleDirectory( | |
| 445 FileSystemOperationContext* unused, | |
| 446 const FilePath& file_path) { | |
| 447 if (!file_util::PathExists(file_path)) | |
| 448 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 449 if (!file_util::DirectoryExists(file_path)) { | |
| 450 // TODO(dmikurube): Check if this error code is appropriate. | |
| 451 return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; | |
| 452 } | |
| 453 if (!file_util::IsDirectoryEmpty(file_path)) { | |
| 454 // TODO(dmikurube): Check if this error code is appropriate. | |
| 455 return base::PLATFORM_FILE_ERROR_NOT_EMPTY; | |
| 456 } | |
| 457 if (!file_util::Delete(file_path, false)) | |
| 458 return base::PLATFORM_FILE_ERROR_FAILED; | |
| 459 return base::PLATFORM_FILE_OK; | |
| 460 } | |
| 461 | |
| 462 PlatformFileError FileSystemFileUtil::DeleteDirectoryRecursive( | 463 PlatformFileError FileSystemFileUtil::DeleteDirectoryRecursive( |
| 463 FileSystemOperationContext* context, | 464 FileSystemOperationContext* context, |
| 464 const FilePath& file_path) { | 465 const FilePath& file_path) { |
| 465 scoped_ptr<AbstractFileEnumerator> file_enum( | 466 scoped_ptr<AbstractFileEnumerator> file_enum( |
| 466 CreateFileEnumerator(context, file_path)); | 467 CreateFileEnumerator(context, file_path)); |
| 467 FilePath file_path_each; | 468 FilePath file_path_each; |
| 468 | 469 |
| 469 std::stack<FilePath> directories; | 470 std::stack<FilePath> directories; |
| 470 while (!(file_path_each = file_enum->Next()).empty()) { | 471 while (!(file_path_each = file_enum->Next()).empty()) { |
| 471 if (file_enum->IsDirectory()) { | 472 if (file_enum->IsDirectory()) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 484 PlatformFileError error = DeleteSingleDirectory(context, directories.top()); | 485 PlatformFileError error = DeleteSingleDirectory(context, directories.top()); |
| 485 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) | 486 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) |
| 486 return base::PLATFORM_FILE_ERROR_FAILED; | 487 return base::PLATFORM_FILE_ERROR_FAILED; |
| 487 else if (error != base::PLATFORM_FILE_OK) | 488 else if (error != base::PLATFORM_FILE_OK) |
| 488 return error; | 489 return error; |
| 489 directories.pop(); | 490 directories.pop(); |
| 490 } | 491 } |
| 491 return DeleteSingleDirectory(context, file_path); | 492 return DeleteSingleDirectory(context, file_path); |
| 492 } | 493 } |
| 493 | 494 |
| 494 bool FileSystemFileUtil::PathExists( | |
| 495 FileSystemOperationContext* unused, | |
| 496 const FilePath& file_path) { | |
| 497 return file_util::PathExists(file_path); | |
| 498 } | |
| 499 | |
| 500 bool FileSystemFileUtil::DirectoryExists( | |
| 501 FileSystemOperationContext* unused, | |
| 502 const FilePath& file_path) { | |
| 503 return file_util::DirectoryExists(file_path); | |
| 504 } | |
| 505 | |
| 506 bool FileSystemFileUtil::IsDirectoryEmpty( | |
| 507 FileSystemOperationContext* unused, | |
| 508 const FilePath& file_path) { | |
| 509 return file_util::IsDirectoryEmpty(file_path); | |
| 510 } | |
| 511 | |
| 512 class FileSystemFileEnumerator | |
| 513 : public FileSystemFileUtil::AbstractFileEnumerator { | |
| 514 public: | |
| 515 FileSystemFileEnumerator(const FilePath& root_path, | |
| 516 bool recursive, | |
| 517 file_util::FileEnumerator::FileType file_type) | |
| 518 : file_enum_(root_path, recursive, file_type) { | |
| 519 } | |
| 520 | |
| 521 ~FileSystemFileEnumerator() {} | |
| 522 | |
| 523 virtual FilePath Next() OVERRIDE; | |
| 524 virtual int64 Size() OVERRIDE; | |
| 525 virtual bool IsDirectory() OVERRIDE; | |
| 526 | |
| 527 private: | |
| 528 file_util::FileEnumerator file_enum_; | |
| 529 file_util::FileEnumerator::FindInfo file_util_info_; | |
| 530 }; | |
| 531 | |
| 532 FilePath FileSystemFileEnumerator::Next() { | |
| 533 FilePath rv = file_enum_.Next(); | |
| 534 if (!rv.empty()) | |
| 535 file_enum_.GetFindInfo(&file_util_info_); | |
| 536 return rv; | |
| 537 } | |
| 538 | |
| 539 int64 FileSystemFileEnumerator::Size() { | |
| 540 return file_util::FileEnumerator::GetFilesize(file_util_info_); | |
| 541 } | |
| 542 | |
| 543 bool FileSystemFileEnumerator::IsDirectory() { | |
| 544 return file_util::FileEnumerator::IsDirectory(file_util_info_); | |
| 545 } | |
| 546 | |
| 547 FileSystemFileUtil::AbstractFileEnumerator* | |
| 548 FileSystemFileUtil::CreateFileEnumerator( | |
| 549 FileSystemOperationContext* unused, | |
| 550 const FilePath& root_path) { | |
| 551 return new FileSystemFileEnumerator( | |
| 552 root_path, true, static_cast<file_util::FileEnumerator::FileType>( | |
| 553 file_util::FileEnumerator::FILES | | |
| 554 file_util::FileEnumerator::DIRECTORIES)); | |
| 555 } | |
| 556 | |
| 557 } // namespace fileapi | 495 } // namespace fileapi |
| OLD | NEW |