diff options
Diffstat (limited to 'chromium/webkit/browser/fileapi/native_file_util.cc')
-rw-r--r-- | chromium/webkit/browser/fileapi/native_file_util.cc | 95 |
1 files changed, 80 insertions, 15 deletions
diff --git a/chromium/webkit/browser/fileapi/native_file_util.cc b/chromium/webkit/browser/fileapi/native_file_util.cc index 32e9467091c..9754d6c64a8 100644 --- a/chromium/webkit/browser/fileapi/native_file_util.cc +++ b/chromium/webkit/browser/fileapi/native_file_util.cc @@ -7,7 +7,9 @@ #include "base/file_util.h" #include "base/files/file_enumerator.h" #include "base/memory/scoped_ptr.h" +#include "net/base/file_stream.h" #include "webkit/browser/fileapi/file_system_operation_context.h" +#include "webkit/browser/fileapi/file_system_url.h" namespace fileapi { @@ -32,6 +34,42 @@ bool SetPlatformSpecificDirectoryPermissions(const base::FilePath& dir_path) { return true; } +// Copies a file |from| to |to|, and ensure the written content is synced to +// the disk. This is essentially base::CopyFile followed by fsync(). +bool CopyFileAndSync(const base::FilePath& from, const base::FilePath& to) { + net::FileStream infile(NULL); + if (infile.OpenSync(from, + base::PLATFORM_FILE_OPEN | base:: PLATFORM_FILE_READ) < 0) { + return false; + } + + net::FileStream outfile(NULL); + if (outfile.OpenSync(to, + base::PLATFORM_FILE_CREATE_ALWAYS | base:: PLATFORM_FILE_WRITE) < 0) { + return false; + } + + const int kBufferSize = 32768; + std::vector<char> buffer(kBufferSize); + + for (;;) { + int bytes_read = infile.ReadSync(&buffer[0], kBufferSize); + if (bytes_read < 0) + return false; + if (bytes_read == 0) + break; + for (int bytes_written = 0; bytes_written < bytes_read; ) { + int bytes_written_partial = outfile.WriteSync(&buffer[bytes_written], + bytes_read - bytes_written); + if (bytes_written_partial < 0) + return false; + bytes_written += bytes_written_partial; + } + } + + return outfile.FlushSync() >= 0; +} + } // namespace using base::PlatformFile; @@ -76,6 +114,15 @@ bool NativeFileEnumerator::IsDirectory() { return file_util_info_.IsDirectory(); } +NativeFileUtil::CopyOrMoveMode NativeFileUtil::CopyOrMoveModeForDestination( + const FileSystemURL& dest_url, bool copy) { + if (copy) { + return dest_url.mount_option().copy_sync_option() == COPY_SYNC_OPTION_SYNC ? + COPY_SYNC : COPY_NOSYNC; + } + return MOVE; +} + PlatformFileError NativeFileUtil::CreateOrOpen( const base::FilePath& path, int file_flags, PlatformFile* file_handle, bool* created) { @@ -137,11 +184,15 @@ PlatformFileError NativeFileUtil::CreateDirectory( if (path_exists && !base::DirectoryExists(path)) return base::PLATFORM_FILE_ERROR_EXISTS; - if (!file_util::CreateDirectory(path)) + if (!base::CreateDirectory(path)) return base::PLATFORM_FILE_ERROR_FAILED; - if (!SetPlatformSpecificDirectoryPermissions(path)) - return base::PLATFORM_FILE_ERROR_FAILED; + if (!SetPlatformSpecificDirectoryPermissions(path)) { + // Since some file systems don't support permission setting, we do not treat + // an error from the function as the failure of copying. Just log it. + LOG(WARNING) << "Setting directory permission failed: " + << path.AsUTF8Unsafe(); + } return base::PLATFORM_FILE_OK; } @@ -151,7 +202,7 @@ PlatformFileError NativeFileUtil::GetFileInfo( base::PlatformFileInfo* file_info) { if (!base::PathExists(path)) return base::PLATFORM_FILE_ERROR_NOT_FOUND; - if (!file_util::GetFileInfo(path, file_info)) + if (!base::GetFileInfo(path, file_info)) return base::PLATFORM_FILE_ERROR_FAILED; return base::PLATFORM_FILE_OK; } @@ -169,8 +220,7 @@ PlatformFileError NativeFileUtil::Touch( const base::FilePath& path, const base::Time& last_access_time, const base::Time& last_modified_time) { - if (!file_util::TouchFile( - path, last_access_time, last_modified_time)) + if (!base::TouchFile(path, last_access_time, last_modified_time)) return base::PLATFORM_FILE_ERROR_FAILED; return base::PLATFORM_FILE_OK; } @@ -205,13 +255,15 @@ bool NativeFileUtil::DirectoryExists(const base::FilePath& path) { PlatformFileError NativeFileUtil::CopyOrMoveFile( const base::FilePath& src_path, const base::FilePath& dest_path, - bool copy) { + FileSystemOperation::CopyOrMoveOption option, + CopyOrMoveMode mode) { base::PlatformFileInfo info; base::PlatformFileError error = NativeFileUtil::GetFileInfo(src_path, &info); if (error != base::PLATFORM_FILE_OK) return error; if (info.is_directory) return base::PLATFORM_FILE_ERROR_NOT_A_FILE; + base::Time last_modified = info.last_modified; error = NativeFileUtil::GetFileInfo(dest_path, &info); if (error != base::PLATFORM_FILE_OK && @@ -227,14 +279,27 @@ PlatformFileError NativeFileUtil::CopyOrMoveFile( return base::PLATFORM_FILE_ERROR_NOT_FOUND; } - if (copy) { - if (base::CopyFile(src_path, dest_path)) - return base::PLATFORM_FILE_OK; - } else { - if (base::Move(src_path, dest_path)) - return base::PLATFORM_FILE_OK; + switch (mode) { + case COPY_NOSYNC: + if (!base::CopyFile(src_path, dest_path)) + return base::PLATFORM_FILE_ERROR_FAILED; + break; + case COPY_SYNC: + if (!CopyFileAndSync(src_path, dest_path)) + return base::PLATFORM_FILE_ERROR_FAILED; + break; + case MOVE: + if (!base::Move(src_path, dest_path)) + return base::PLATFORM_FILE_ERROR_FAILED; + break; } - return base::PLATFORM_FILE_ERROR_FAILED; + + // Preserve the last modified time. Do not return error here even if + // the setting is failed, because the copy itself is successfully done. + if (option == FileSystemOperation::OPTION_PRESERVE_LAST_MODIFIED) + base::TouchFile(dest_path, last_modified, last_modified); + + return base::PLATFORM_FILE_OK; } PlatformFileError NativeFileUtil::DeleteFile(const base::FilePath& path) { @@ -252,7 +317,7 @@ PlatformFileError NativeFileUtil::DeleteDirectory(const base::FilePath& path) { return base::PLATFORM_FILE_ERROR_NOT_FOUND; if (!base::DirectoryExists(path)) return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; - if (!file_util::IsDirectoryEmpty(path)) + if (!base::IsDirectoryEmpty(path)) return base::PLATFORM_FILE_ERROR_NOT_EMPTY; if (!base::DeleteFile(path, false)) return base::PLATFORM_FILE_ERROR_FAILED; |