Chromium Code Reviews| Index: webkit/fileapi/native_file_util.cc |
| diff --git a/webkit/fileapi/native_file_util.cc b/webkit/fileapi/native_file_util.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..e2aca25af3cc45b6cb2820ac902ea98e8c5b902a |
| --- /dev/null |
| +++ b/webkit/fileapi/native_file_util.cc |
| @@ -0,0 +1,302 @@ |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
|
ericu
2011/08/03 22:59:26
This file seems to be based on file_system_file_ut
Dai Mikurube (NOT FULLTIME)
2011/08/04 03:54:48
Actually I used git mv for this class, but Rietvel
|
| + |
| +#include "webkit/fileapi/native_file_util.h" |
| + |
| +#include <vector> |
| + |
| +#include "base/file_util.h" |
| +#include "base/memory/scoped_ptr.h" |
| +#include "webkit/fileapi/file_system_operation_context.h" |
| + |
| +namespace fileapi { |
| + |
| +namespace { |
| + |
| +// This assumes that the root exists. |
| +bool ParentExists(FileSystemOperationContext* context, |
|
ericu
2011/08/03 22:59:26
This function isn't used.
Dai Mikurube (NOT FULLTIME)
2011/08/04 03:54:48
Exactly. Removed.
|
| + FileUtil* file_util, const FilePath& file_path) { |
| + // If file_path is in the root, file_path.DirName() will be ".", |
| + // since we use paths with no leading '/'. |
| + FilePath parent = file_path.DirName(); |
| + if (parent == FilePath(FILE_PATH_LITERAL("."))) |
| + return true; |
| + return file_util->DirectoryExists(context, parent); |
| +} |
| + |
| +} // namespace |
| + |
| +PlatformFileError NativeFileUtil::CreateOrOpen( |
| + FileSystemOperationContext* unused, |
| + const FilePath& file_path, int file_flags, |
| + PlatformFile* file_handle, bool* created) { |
| + if (!file_util::DirectoryExists(file_path.DirName())) { |
| + // If its parent does not exist, should return NOT_FOUND error. |
| + return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| + } |
| + PlatformFileError error_code = base::PLATFORM_FILE_OK; |
| + *file_handle = base::CreatePlatformFile(file_path, file_flags, |
| + created, &error_code); |
| + return error_code; |
| +} |
| + |
| +PlatformFileError NativeFileUtil::Close( |
| + FileSystemOperationContext* unused, |
| + PlatformFile file_handle) { |
| + if (!base::ClosePlatformFile(file_handle)) |
| + return base::PLATFORM_FILE_ERROR_FAILED; |
| + return base::PLATFORM_FILE_OK; |
| +} |
| + |
| +PlatformFileError NativeFileUtil::EnsureFileExists( |
| + FileSystemOperationContext* unused, |
| + const FilePath& file_path, |
| + bool* created) { |
| + if (!file_util::DirectoryExists(file_path.DirName())) |
| + // If its parent does not exist, should return NOT_FOUND error. |
| + return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| + PlatformFileError error_code = base::PLATFORM_FILE_OK; |
| + // Tries to create the |file_path| exclusively. This should fail |
| + // with base::PLATFORM_FILE_ERROR_EXISTS if the path already exists. |
| + PlatformFile handle = base::CreatePlatformFile( |
| + file_path, |
| + base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_READ, |
| + created, &error_code); |
| + if (error_code == base::PLATFORM_FILE_ERROR_EXISTS) { |
| + // Make sure created_ is false. |
| + if (created) |
| + *created = false; |
| + error_code = base::PLATFORM_FILE_OK; |
| + } |
| + if (handle != base::kInvalidPlatformFileValue) |
| + base::ClosePlatformFile(handle); |
| + return error_code; |
| +} |
| + |
| +PlatformFileError NativeFileUtil::GetLocalFilePath( |
| + FileSystemOperationContext* unused, |
| + const FilePath& virtual_path, |
| + FilePath* local_path) { |
| + *local_path = virtual_path; |
| + return base::PLATFORM_FILE_OK; |
| +} |
| + |
| +PlatformFileError NativeFileUtil::GetFileInfo( |
| + FileSystemOperationContext* unused, |
| + const FilePath& file_path, |
| + base::PlatformFileInfo* file_info, |
| + FilePath* platform_file_path) { |
| + if (!file_util::PathExists(file_path)) |
| + return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| + // TODO(rkc): Fix this hack once we have refactored file_util to handle |
| + // symlinks correctly. |
| + // http://code.google.com/p/chromium-os/issues/detail?id=15948 |
| + if (file_util::IsLink(file_path)) |
| + return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| + if (!file_util::GetFileInfo(file_path, file_info)) |
| + return base::PLATFORM_FILE_ERROR_FAILED; |
| + *platform_file_path = file_path; |
| + return base::PLATFORM_FILE_OK; |
| +} |
| + |
| +PlatformFileError NativeFileUtil::ReadDirectory( |
| + FileSystemOperationContext* unused, |
| + const FilePath& file_path, |
| + std::vector<base::FileUtilProxy::Entry>* entries) { |
| + // TODO(kkanetkar): Implement directory read in multiple chunks. |
| + if (!file_util::DirectoryExists(file_path)) |
| + return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| + |
| + file_util::FileEnumerator file_enum( |
| + file_path, false, static_cast<file_util::FileEnumerator::FILE_TYPE>( |
| + file_util::FileEnumerator::FILES | |
| + file_util::FileEnumerator::DIRECTORIES)); |
| + FilePath current; |
| + while (!(current = file_enum.Next()).empty()) { |
| + base::FileUtilProxy::Entry entry; |
| + file_util::FileEnumerator::FindInfo info; |
| + file_enum.GetFindInfo(&info); |
| + entry.is_directory = file_enum.IsDirectory(info); |
| + // This will just give the entry's name instead of entire path |
| + // if we use current.value(). |
| + entry.name = file_util::FileEnumerator::GetFilename(info).value(); |
| + entry.size = file_util::FileEnumerator::GetFilesize(info); |
| + entry.last_modified_time = |
| + file_util::FileEnumerator::GetLastModifiedTime(info); |
| + // TODO(rkc): Fix this also once we've refactored file_util |
| + // http://code.google.com/p/chromium-os/issues/detail?id=15948 |
| + // This currently just prevents a file from showing up at all |
| + // if it's a link, hence preventing arbitary 'read' exploits. |
| + if (!file_util::IsLink(file_path.Append(entry.name))) |
| + entries->push_back(entry); |
| + } |
| + return base::PLATFORM_FILE_OK; |
| +} |
| + |
| +PlatformFileError NativeFileUtil::CreateDirectory( |
| + FileSystemOperationContext* context, |
| + const FilePath& file_path, |
| + bool exclusive, |
| + bool recursive) { |
| + if (context->do_not_write_actually()) |
| + return base::PLATFORM_FILE_OK; |
| + |
| + // If parent dir of file doesn't exist. |
| + if (!recursive && !file_util::PathExists(file_path.DirName())) |
| + return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| + |
| + bool path_exists = file_util::PathExists(file_path); |
| + if (exclusive && path_exists) |
| + return base::PLATFORM_FILE_ERROR_EXISTS; |
| + |
| + // If file exists at the path. |
| + if (path_exists && !file_util::DirectoryExists(file_path)) |
| + return base::PLATFORM_FILE_ERROR_EXISTS; |
| + |
| + if (!file_util::CreateDirectory(file_path)) |
| + return base::PLATFORM_FILE_ERROR_FAILED; |
| + return base::PLATFORM_FILE_OK; |
| +} |
| + |
| +PlatformFileError NativeFileUtil::Touch( |
| + FileSystemOperationContext* unused, |
| + const FilePath& file_path, |
| + const base::Time& last_access_time, |
| + const base::Time& last_modified_time) { |
| + if (!file_util::TouchFile( |
| + file_path, last_access_time, last_modified_time)) |
| + return base::PLATFORM_FILE_ERROR_FAILED; |
| + return base::PLATFORM_FILE_OK; |
| +} |
| + |
| +PlatformFileError NativeFileUtil::Truncate( |
| + FileSystemOperationContext* unused, |
| + const FilePath& file_path, |
| + int64 length) { |
| + PlatformFileError error_code(base::PLATFORM_FILE_ERROR_FAILED); |
| + PlatformFile file = |
| + base::CreatePlatformFile( |
| + file_path, |
| + base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE, |
| + NULL, |
| + &error_code); |
| + if (error_code != base::PLATFORM_FILE_OK) { |
| + return error_code; |
| + } |
| + DCHECK_NE(base::kInvalidPlatformFileValue, file); |
| + if (!base::TruncatePlatformFile(file, length)) |
| + error_code = base::PLATFORM_FILE_ERROR_FAILED; |
| + base::ClosePlatformFile(file); |
| + return error_code; |
| +} |
| + |
| +PlatformFileError NativeFileUtil::CopyOrMoveFile( |
| + FileSystemOperationContext* unused, |
| + const FilePath& src_file_path, |
| + const FilePath& dest_file_path, |
| + bool copy) { |
| + if (copy) { |
| + if (file_util::CopyFile(src_file_path, dest_file_path)) |
| + return base::PLATFORM_FILE_OK; |
| + } else { |
| + DCHECK(!file_util::DirectoryExists(src_file_path)); |
| + if (file_util::Move(src_file_path, dest_file_path)) |
| + return base::PLATFORM_FILE_OK; |
| + } |
| + return base::PLATFORM_FILE_ERROR_FAILED; |
| +} |
| + |
| +PlatformFileError NativeFileUtil::CopyInForeignFile( |
| + FileSystemOperationContext* context, |
| + const FilePath& src_file_path, |
| + const FilePath& dest_file_path) { |
| + return CopyOrMoveFile(context, src_file_path, dest_file_path, true); |
| +} |
| + |
| +PlatformFileError NativeFileUtil::DeleteFile( |
| + FileSystemOperationContext* unused, |
| + const FilePath& file_path) { |
| + if (!file_util::PathExists(file_path)) |
| + return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| + if (file_util::DirectoryExists(file_path)) |
| + return base::PLATFORM_FILE_ERROR_NOT_A_FILE; |
| + if (!file_util::Delete(file_path, false)) |
| + return base::PLATFORM_FILE_ERROR_FAILED; |
| + return base::PLATFORM_FILE_OK; |
| +} |
| + |
| +PlatformFileError NativeFileUtil::DeleteSingleDirectory( |
| + FileSystemOperationContext* unused, |
| + const FilePath& file_path) { |
| + if (!file_util::PathExists(file_path)) |
| + return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| + if (!file_util::DirectoryExists(file_path)) { |
| + // TODO(dmikurube): Check if this error code is appropriate. |
| + return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; |
| + } |
| + if (!file_util::IsDirectoryEmpty(file_path)) { |
| + // TODO(dmikurube): Check if this error code is appropriate. |
| + return base::PLATFORM_FILE_ERROR_NOT_EMPTY; |
| + } |
| + if (!file_util::Delete(file_path, false)) |
| + return base::PLATFORM_FILE_ERROR_FAILED; |
| + return base::PLATFORM_FILE_OK; |
| +} |
| + |
| +bool NativeFileUtil::PathExists( |
| + FileSystemOperationContext* unused, |
| + const FilePath& file_path) { |
| + return file_util::PathExists(file_path); |
| +} |
| + |
| +bool NativeFileUtil::DirectoryExists( |
| + FileSystemOperationContext* unused, |
| + const FilePath& file_path) { |
| + return file_util::DirectoryExists(file_path); |
| +} |
| + |
| +bool NativeFileUtil::IsDirectoryEmpty( |
| + FileSystemOperationContext* unused, |
| + const FilePath& file_path) { |
| + return file_util::IsDirectoryEmpty(file_path); |
| +} |
| + |
| +class FileSystemFileEnumerator |
| + : public FileUtil::AbstractFileEnumerator { |
| + public: |
| + FileSystemFileEnumerator(const FilePath& root_path, |
| + bool recursive, |
| + file_util::FileEnumerator::FILE_TYPE file_type) |
| + : file_enum_(root_path, recursive, file_type) { |
| + } |
| + |
| + ~FileSystemFileEnumerator() {} |
| + |
| + virtual FilePath Next(); |
| + virtual bool IsDirectory(); |
| + |
| + private: |
| + file_util::FileEnumerator file_enum_; |
| +}; |
| + |
| +FilePath FileSystemFileEnumerator::Next() { |
| + return file_enum_.Next(); |
| +} |
| + |
| +bool FileSystemFileEnumerator::IsDirectory() { |
| + file_util::FileEnumerator::FindInfo file_util_info; |
| + file_enum_.GetFindInfo(&file_util_info); |
| + return file_util::FileEnumerator::IsDirectory(file_util_info); |
| +} |
| + |
| +FileUtil::AbstractFileEnumerator* NativeFileUtil::CreateFileEnumerator( |
| + FileSystemOperationContext* unused, |
| + const FilePath& root_path) { |
| + return new FileSystemFileEnumerator( |
| + root_path, true, static_cast<file_util::FileEnumerator::FILE_TYPE>( |
| + file_util::FileEnumerator::FILES | |
| + file_util::FileEnumerator::DIRECTORIES)); |
| +} |
| + |
| +} // namespace fileapi |