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 #include "webkit/fileapi/file_system_file_util.h" | |
6 | |
7 #include <stack> | |
8 #include <vector> | |
9 | |
10 #include "base/file_util_proxy.h" | |
11 #include "base/memory/scoped_ptr.h" | |
12 #include "webkit/fileapi/file_system_operation_context.h" | |
13 | |
14 namespace fileapi { | |
15 | |
16 namespace { | |
17 | |
18 // This assumes that the root exists. | |
19 bool ParentExists(FileSystemOperationContext* context, | |
20 FileSystemFileUtil* file_util, const FilePath& file_path) { | |
21 // If file_path is in the root, file_path.DirName() will be ".", | |
22 // since we use paths with no leading '/'. | |
23 FilePath parent = file_path.DirName(); | |
24 if (parent == FilePath(FILE_PATH_LITERAL("."))) | |
25 return true; | |
26 return file_util->DirectoryExists(context, parent); | |
27 } | |
28 | |
29 } // namespace | |
30 | |
31 PlatformFileError FileSystemFileUtil::CreateOrOpen( | |
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 } | |
44 | |
45 PlatformFileError FileSystemFileUtil::Close( | |
46 FileSystemOperationContext* unused, | |
47 PlatformFile file_handle) { | |
48 if (!base::ClosePlatformFile(file_handle)) | |
49 return base::PLATFORM_FILE_ERROR_FAILED; | |
50 return base::PLATFORM_FILE_OK; | |
51 } | |
52 | |
53 PlatformFileError FileSystemFileUtil::EnsureFileExists( | |
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::FILE_TYPE>( | |
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* fs_context, | |
140 const FilePath& file_path, | |
141 bool exclusive, | |
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. | |
147 if (!recursive && !file_util::PathExists(file_path.DirName())) | |
148 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
149 | |
150 bool path_exists = file_util::PathExists(file_path); | |
151 if (exclusive && path_exists) | |
152 return base::PLATFORM_FILE_ERROR_EXISTS; | |
153 | |
154 // If file exists at the path. | |
155 if (path_exists && !file_util::DirectoryExists(file_path)) | |
156 return base::PLATFORM_FILE_ERROR_EXISTS; | |
157 | |
158 if (!file_util::CreateDirectory(file_path)) | |
159 return base::PLATFORM_FILE_ERROR_FAILED; | |
160 return base::PLATFORM_FILE_OK; | |
161 } | |
162 | |
163 PlatformFileError FileSystemFileUtil::Copy( | |
164 FileSystemOperationContext* context, | |
165 const FilePath& src_file_path, | |
166 const FilePath& dest_file_path) { | |
167 PlatformFileError error_code; | |
168 error_code = | |
169 PerformCommonCheckAndPreparationForMoveAndCopy( | |
170 context, src_file_path, dest_file_path); | |
171 if (error_code != base::PLATFORM_FILE_OK) | |
172 return error_code; | |
173 | |
174 if (DirectoryExists(context, src_file_path)) | |
175 return CopyOrMoveDirectory(context, src_file_path, dest_file_path, | |
176 true /* copy */); | |
177 return CopyOrMoveFileHelper(context, src_file_path, dest_file_path, | |
178 true /* copy */); | |
179 } | |
180 | |
181 PlatformFileError FileSystemFileUtil::Move( | |
182 FileSystemOperationContext* context, | |
183 const FilePath& src_file_path, | |
184 const FilePath& dest_file_path) { | |
185 PlatformFileError error_code; | |
186 error_code = | |
187 PerformCommonCheckAndPreparationForMoveAndCopy( | |
188 context, src_file_path, dest_file_path); | |
189 if (error_code != base::PLATFORM_FILE_OK) | |
190 return error_code; | |
191 | |
192 // TODO(dmikurube): ReplaceFile if in the same domain and filesystem type. | |
193 if (DirectoryExists(context, src_file_path)) | |
194 return CopyOrMoveDirectory(context, src_file_path, dest_file_path, | |
195 false /* copy */); | |
196 return CopyOrMoveFileHelper(context, src_file_path, dest_file_path, | |
197 false /* copy */); | |
198 } | |
199 | |
200 PlatformFileError FileSystemFileUtil::Delete( | |
201 FileSystemOperationContext* context, | |
202 const FilePath& file_path, | |
203 bool recursive) { | |
204 if (DirectoryExists(context, file_path)) { | |
205 if (!recursive) | |
206 return DeleteSingleDirectory(context, file_path); | |
207 else | |
208 return DeleteDirectoryRecursive(context, file_path); | |
209 } else { | |
210 return DeleteFile(context, file_path); | |
211 } | |
212 } | |
213 | |
214 PlatformFileError FileSystemFileUtil::Touch( | |
215 FileSystemOperationContext* unused, | |
216 const FilePath& file_path, | |
217 const base::Time& last_access_time, | |
218 const base::Time& last_modified_time) { | |
219 if (!file_util::TouchFile( | |
220 file_path, last_access_time, last_modified_time)) | |
221 return base::PLATFORM_FILE_ERROR_FAILED; | |
222 return base::PLATFORM_FILE_OK; | |
223 } | |
224 | |
225 PlatformFileError FileSystemFileUtil::Truncate( | |
226 FileSystemOperationContext* unused, | |
227 const FilePath& file_path, | |
228 int64 length) { | |
229 PlatformFileError error_code(base::PLATFORM_FILE_ERROR_FAILED); | |
230 PlatformFile file = | |
231 base::CreatePlatformFile( | |
232 file_path, | |
233 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE, | |
234 NULL, | |
235 &error_code); | |
236 if (error_code != base::PLATFORM_FILE_OK) { | |
237 return error_code; | |
238 } | |
239 DCHECK_NE(base::kInvalidPlatformFileValue, file); | |
240 if (!base::TruncatePlatformFile(file, length)) | |
241 error_code = base::PLATFORM_FILE_ERROR_FAILED; | |
242 base::ClosePlatformFile(file); | |
243 return error_code; | |
244 } | |
245 | |
246 PlatformFileError | |
247 FileSystemFileUtil::PerformCommonCheckAndPreparationForMoveAndCopy( | |
248 FileSystemOperationContext* context, | |
249 const FilePath& src_file_path, | |
250 const FilePath& dest_file_path) { | |
251 bool same_file_system = | |
252 (context->src_origin_url() == context->dest_origin_url()) && | |
253 (context->src_type() == context->dest_type()); | |
254 FileSystemFileUtil* dest_util = context->dest_file_system_file_util(); | |
255 DCHECK(dest_util); | |
256 if (same_file_system) | |
257 DCHECK(context->src_file_system_file_util() == | |
258 context->dest_file_system_file_util()); | |
259 // All the single-path virtual FSFU methods expect the context information | |
260 // to be in the src_* variables, not the dest_* variables, so we have to | |
261 // make a new context if we want to call them on the dest_file_path. | |
262 scoped_ptr<FileSystemOperationContext> dest_context( | |
263 context->CreateInheritedContextForDest()); | |
264 | |
265 // Exits earlier if the source path does not exist. | |
266 if (!PathExists(context, src_file_path)) | |
267 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
268 | |
269 // The parent of the |dest_file_path| does not exist. | |
270 if (!ParentExists(dest_context.get(), dest_util, dest_file_path)) | |
271 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
272 | |
273 // 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)) | |
275 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | |
276 | |
277 // 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)) | |
279 return base::PLATFORM_FILE_OK; | |
280 | |
281 // |src_file_path| exists and is a directory. | |
282 // |dest_file_path| exists and is a file. | |
283 bool src_is_directory = DirectoryExists(context, src_file_path); | |
284 bool dest_is_directory = | |
285 dest_util->DirectoryExists(dest_context.get(), dest_file_path); | |
286 if (src_is_directory && !dest_is_directory) | |
287 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | |
288 | |
289 // |src_file_path| exists and is a file. | |
290 // |dest_file_path| exists and is a directory. | |
291 if (!src_is_directory && dest_is_directory) | |
292 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | |
293 | |
294 // 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())) | |
296 return base::PLATFORM_FILE_ERROR_EXISTS; | |
297 | |
298 if (dest_is_directory) { | |
299 // 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 | |
301 // the file_util's Copy or Move method doesn't perform overwrite | |
302 // on all platforms, so we delete the destination directory here. | |
303 // TODO(kinuko): may be better to change the file_util::{Copy,Move}. | |
304 PlatformFileError error = dest_util->Delete( | |
305 dest_context.get(), dest_file_path, false /* recursive */); | |
306 context->ImportAllowedBytesGrowth(*dest_context); | |
307 if (base::PLATFORM_FILE_OK != error) { | |
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_FAILED; | |
311 } | |
312 } | |
313 return base::PLATFORM_FILE_OK; | |
314 } | |
315 | |
316 PlatformFileError FileSystemFileUtil::CopyOrMoveFile( | |
317 FileSystemOperationContext* unused, | |
318 const FilePath& src_file_path, | |
319 const FilePath& dest_file_path, | |
320 bool copy) { | |
321 if (copy) { | |
322 if (file_util::CopyFile(src_file_path, dest_file_path)) | |
323 return base::PLATFORM_FILE_OK; | |
324 } else { | |
325 DCHECK(!file_util::DirectoryExists(src_file_path)); | |
326 if (file_util::Move(src_file_path, dest_file_path)) | |
327 return base::PLATFORM_FILE_OK; | |
328 } | |
329 return base::PLATFORM_FILE_ERROR_FAILED; | |
330 } | |
331 | |
332 PlatformFileError FileSystemFileUtil::CopyInForeignFile( | |
333 FileSystemOperationContext* context, | |
334 const FilePath& src_file_path, | |
335 const FilePath& dest_file_path) { | |
336 return CopyOrMoveFile(context, src_file_path, dest_file_path, true); | |
337 } | |
338 | |
339 PlatformFileError FileSystemFileUtil::CopyOrMoveDirectory( | |
340 FileSystemOperationContext* context, | |
341 const FilePath& src_file_path, | |
342 const FilePath& dest_file_path, | |
343 bool copy) { | |
344 FileSystemFileUtil* dest_util = context->dest_file_system_file_util(); | |
345 scoped_ptr<FileSystemOperationContext> dest_context( | |
346 context->CreateInheritedContextForDest()); | |
347 | |
348 // Re-check PerformCommonCheckAndPreparationForMoveAndCopy() by DCHECK. | |
349 DCHECK(DirectoryExists(context, src_file_path)); | |
350 DCHECK(ParentExists(dest_context.get(), dest_util, dest_file_path)); | |
351 DCHECK(!dest_util->PathExists(dest_context.get(), dest_file_path)); | |
352 if ((context->src_origin_url() == context->dest_origin_url()) && | |
353 (context->src_type() == context->dest_type())) | |
354 DCHECK(!src_file_path.IsParent(dest_file_path)); | |
355 | |
356 if (!dest_util->DirectoryExists(dest_context.get(), dest_file_path)) { | |
357 PlatformFileError error = dest_util->CreateDirectory(dest_context.get(), | |
358 dest_file_path, false, false); | |
359 context->ImportAllowedBytesGrowth(*dest_context); | |
360 if (error != base::PLATFORM_FILE_OK) | |
361 return error; | |
362 } | |
363 | |
364 scoped_ptr<AbstractFileEnumerator> file_enum( | |
365 CreateFileEnumerator(context, src_file_path)); | |
366 FilePath src_file_path_each; | |
367 while (!(src_file_path_each = file_enum->Next()).empty()) { | |
368 FilePath dest_file_path_each(dest_file_path); | |
369 src_file_path.AppendRelativePath(src_file_path_each, &dest_file_path_each); | |
370 | |
371 if (file_enum->IsDirectory()) { | |
372 scoped_ptr<FileSystemOperationContext> new_directory_context( | |
373 dest_context->CreateInheritedContextWithNewVirtualPaths( | |
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) | |
379 return error; | |
380 } else { | |
381 scoped_ptr<FileSystemOperationContext> copy_context( | |
382 context->CreateInheritedContextWithNewVirtualPaths( | |
383 src_file_path_each, dest_file_path_each)); | |
384 PlatformFileError error = CopyOrMoveFileHelper( | |
385 copy_context.get(), src_file_path_each, dest_file_path_each, copy); | |
386 context->ImportAllowedBytesGrowth(*copy_context); | |
387 if (error != base::PLATFORM_FILE_OK) | |
388 return error; | |
389 } | |
390 } | |
391 | |
392 if (!copy) { | |
393 PlatformFileError error = Delete(context, src_file_path, true); | |
394 if (error != base::PLATFORM_FILE_OK) | |
395 return error; | |
396 } | |
397 return base::PLATFORM_FILE_OK; | |
398 } | |
399 | |
400 PlatformFileError FileSystemFileUtil::CopyOrMoveFileHelper( | |
401 FileSystemOperationContext* context, | |
402 const FilePath& src_file_path, | |
403 const FilePath& dest_file_path, | |
404 bool copy) { | |
405 // CopyOrMoveFile here is the virtual overridden member function. | |
406 if ((context->src_origin_url() == context->dest_origin_url()) && | |
407 (context->src_type() == context->dest_type())) { | |
408 DCHECK(context->src_file_system_file_util() == | |
409 context->dest_file_system_file_util()); | |
410 return CopyOrMoveFile(context, src_file_path, dest_file_path, copy); | |
411 } | |
412 base::PlatformFileInfo file_info; | |
413 FilePath platform_file_path; | |
414 PlatformFileError error_code; | |
415 error_code = | |
416 GetFileInfo(context, src_file_path, &file_info, &platform_file_path); | |
417 if (error_code != base::PLATFORM_FILE_OK) | |
418 return error_code; | |
419 | |
420 DCHECK(context->dest_file_system_file_util()); | |
421 error_code = context->dest_file_system_file_util()->CopyInForeignFile( | |
422 context, platform_file_path, dest_file_path); | |
423 if (copy || error_code != base::PLATFORM_FILE_OK) | |
424 return error_code; | |
425 return DeleteFile(context, src_file_path); | |
426 } | |
427 | |
428 | |
429 PlatformFileError FileSystemFileUtil::DeleteFile( | |
430 FileSystemOperationContext* unused, | |
431 const FilePath& file_path) { | |
432 if (!file_util::PathExists(file_path)) | |
433 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
434 if (file_util::DirectoryExists(file_path)) | |
435 return base::PLATFORM_FILE_ERROR_NOT_A_FILE; | |
436 if (!file_util::Delete(file_path, false)) | |
437 return base::PLATFORM_FILE_ERROR_FAILED; | |
438 return base::PLATFORM_FILE_OK; | |
439 } | |
440 | |
441 PlatformFileError FileSystemFileUtil::DeleteSingleDirectory( | |
442 FileSystemOperationContext* unused, | |
443 const FilePath& file_path) { | |
444 if (!file_util::PathExists(file_path)) | |
445 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
446 if (!file_util::DirectoryExists(file_path)) { | |
447 // TODO(dmikurube): Check if this error code is appropriate. | |
448 return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; | |
449 } | |
450 if (!file_util::IsDirectoryEmpty(file_path)) { | |
451 // TODO(dmikurube): Check if this error code is appropriate. | |
452 return base::PLATFORM_FILE_ERROR_NOT_EMPTY; | |
453 } | |
454 if (!file_util::Delete(file_path, false)) | |
455 return base::PLATFORM_FILE_ERROR_FAILED; | |
456 return base::PLATFORM_FILE_OK; | |
457 } | |
458 | |
459 PlatformFileError FileSystemFileUtil::DeleteDirectoryRecursive( | |
460 FileSystemOperationContext* context, | |
461 const FilePath& file_path) { | |
462 scoped_ptr<AbstractFileEnumerator> file_enum( | |
463 CreateFileEnumerator(context, file_path)); | |
464 FilePath file_path_each; | |
465 | |
466 std::stack<FilePath> directories; | |
467 while (!(file_path_each = file_enum->Next()).empty()) { | |
468 if (file_enum->IsDirectory()) { | |
469 directories.push(file_path_each); | |
470 } else { | |
471 // DeleteFile here is the virtual overridden member function. | |
472 scoped_ptr<FileSystemOperationContext> inherited_context( | |
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) | |
479 return base::PLATFORM_FILE_ERROR_FAILED; | |
480 else if (error != base::PLATFORM_FILE_OK) | |
481 return error; | |
482 } | |
483 } | |
484 | |
485 while (!directories.empty()) { | |
486 scoped_ptr<FileSystemOperationContext> inherited_context( | |
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) | |
493 return base::PLATFORM_FILE_ERROR_FAILED; | |
494 else if (error != base::PLATFORM_FILE_OK) | |
495 return error; | |
496 directories.pop(); | |
497 } | |
498 return DeleteSingleDirectory(context, file_path); | |
499 } | |
500 | |
501 bool FileSystemFileUtil::PathExists( | |
502 FileSystemOperationContext* unused, | |
503 const FilePath& file_path) { | |
504 return file_util::PathExists(file_path); | |
505 } | |
506 | |
507 bool FileSystemFileUtil::DirectoryExists( | |
508 FileSystemOperationContext* unused, | |
509 const FilePath& file_path) { | |
510 return file_util::DirectoryExists(file_path); | |
511 } | |
512 | |
513 bool FileSystemFileUtil::IsDirectoryEmpty( | |
514 FileSystemOperationContext* unused, | |
515 const FilePath& file_path) { | |
516 return file_util::IsDirectoryEmpty(file_path); | |
517 } | |
518 | |
519 class FileSystemFileEnumerator | |
520 : public FileSystemFileUtil::AbstractFileEnumerator { | |
521 public: | |
522 FileSystemFileEnumerator(const FilePath& root_path, | |
523 bool recursive, | |
524 file_util::FileEnumerator::FILE_TYPE file_type) | |
525 : file_enum_(root_path, recursive, file_type) { | |
526 } | |
527 | |
528 ~FileSystemFileEnumerator() {} | |
529 | |
530 virtual FilePath Next(); | |
531 virtual bool IsDirectory(); | |
532 | |
533 private: | |
534 file_util::FileEnumerator file_enum_; | |
535 }; | |
536 | |
537 FilePath FileSystemFileEnumerator::Next() { | |
538 return file_enum_.Next(); | |
539 } | |
540 | |
541 bool FileSystemFileEnumerator::IsDirectory() { | |
542 file_util::FileEnumerator::FindInfo file_util_info; | |
543 file_enum_.GetFindInfo(&file_util_info); | |
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::FILE_TYPE>( | |
553 file_util::FileEnumerator::FILES | | |
554 file_util::FileEnumerator::DIRECTORIES)); | |
555 } | |
556 | |
557 } // namespace fileapi | |
OLD | NEW |