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/native_file_util.h" |
| 6 |
| 7 #include <vector> |
| 8 |
| 9 #include "base/file_util.h" |
| 10 #include "base/memory/scoped_ptr.h" |
| 11 #include "webkit/fileapi/file_system_operation_context.h" |
| 12 |
| 13 namespace fileapi { |
| 14 |
| 15 PlatformFileError NativeFileUtil::CreateOrOpen( |
| 16 FileSystemOperationContext* unused, |
| 17 const FilePath& file_path, int file_flags, |
| 18 PlatformFile* file_handle, bool* created) { |
| 19 if (!file_util::DirectoryExists(file_path.DirName())) { |
| 20 // If its parent does not exist, should return NOT_FOUND error. |
| 21 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 22 } |
| 23 PlatformFileError error_code = base::PLATFORM_FILE_OK; |
| 24 *file_handle = base::CreatePlatformFile(file_path, file_flags, |
| 25 created, &error_code); |
| 26 return error_code; |
| 27 } |
| 28 |
| 29 PlatformFileError NativeFileUtil::Close( |
| 30 FileSystemOperationContext* unused, |
| 31 PlatformFile file_handle) { |
| 32 if (!base::ClosePlatformFile(file_handle)) |
| 33 return base::PLATFORM_FILE_ERROR_FAILED; |
| 34 return base::PLATFORM_FILE_OK; |
| 35 } |
| 36 |
| 37 PlatformFileError NativeFileUtil::EnsureFileExists( |
| 38 FileSystemOperationContext* unused, |
| 39 const FilePath& file_path, |
| 40 bool* created) { |
| 41 if (!file_util::DirectoryExists(file_path.DirName())) |
| 42 // If its parent does not exist, should return NOT_FOUND error. |
| 43 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 44 PlatformFileError error_code = base::PLATFORM_FILE_OK; |
| 45 // Tries to create the |file_path| exclusively. This should fail |
| 46 // with base::PLATFORM_FILE_ERROR_EXISTS if the path already exists. |
| 47 PlatformFile handle = base::CreatePlatformFile( |
| 48 file_path, |
| 49 base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_READ, |
| 50 created, &error_code); |
| 51 if (error_code == base::PLATFORM_FILE_ERROR_EXISTS) { |
| 52 // Make sure created_ is false. |
| 53 if (created) |
| 54 *created = false; |
| 55 error_code = base::PLATFORM_FILE_OK; |
| 56 } |
| 57 if (handle != base::kInvalidPlatformFileValue) |
| 58 base::ClosePlatformFile(handle); |
| 59 return error_code; |
| 60 } |
| 61 |
| 62 PlatformFileError NativeFileUtil::GetLocalFilePath( |
| 63 FileSystemOperationContext* unused, |
| 64 const FilePath& virtual_path, |
| 65 FilePath* local_path) { |
| 66 *local_path = virtual_path; |
| 67 return base::PLATFORM_FILE_OK; |
| 68 } |
| 69 |
| 70 PlatformFileError NativeFileUtil::GetFileInfo( |
| 71 FileSystemOperationContext* unused, |
| 72 const FilePath& file_path, |
| 73 base::PlatformFileInfo* file_info, |
| 74 FilePath* platform_file_path) { |
| 75 if (!file_util::PathExists(file_path)) |
| 76 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 77 // TODO(rkc): Fix this hack once we have refactored file_util to handle |
| 78 // symlinks correctly. |
| 79 // http://code.google.com/p/chromium-os/issues/detail?id=15948 |
| 80 if (file_util::IsLink(file_path)) |
| 81 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 82 if (!file_util::GetFileInfo(file_path, file_info)) |
| 83 return base::PLATFORM_FILE_ERROR_FAILED; |
| 84 *platform_file_path = file_path; |
| 85 return base::PLATFORM_FILE_OK; |
| 86 } |
| 87 |
| 88 PlatformFileError NativeFileUtil::ReadDirectory( |
| 89 FileSystemOperationContext* unused, |
| 90 const FilePath& file_path, |
| 91 std::vector<base::FileUtilProxy::Entry>* entries) { |
| 92 // TODO(kkanetkar): Implement directory read in multiple chunks. |
| 93 if (!file_util::DirectoryExists(file_path)) |
| 94 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 95 |
| 96 file_util::FileEnumerator file_enum( |
| 97 file_path, false, static_cast<file_util::FileEnumerator::FileType>( |
| 98 file_util::FileEnumerator::FILES | |
| 99 file_util::FileEnumerator::DIRECTORIES)); |
| 100 FilePath current; |
| 101 while (!(current = file_enum.Next()).empty()) { |
| 102 base::FileUtilProxy::Entry entry; |
| 103 file_util::FileEnumerator::FindInfo info; |
| 104 file_enum.GetFindInfo(&info); |
| 105 entry.is_directory = file_enum.IsDirectory(info); |
| 106 // This will just give the entry's name instead of entire path |
| 107 // if we use current.value(). |
| 108 entry.name = file_util::FileEnumerator::GetFilename(info).value(); |
| 109 entry.size = file_util::FileEnumerator::GetFilesize(info); |
| 110 entry.last_modified_time = |
| 111 file_util::FileEnumerator::GetLastModifiedTime(info); |
| 112 // TODO(rkc): Fix this also once we've refactored file_util |
| 113 // http://code.google.com/p/chromium-os/issues/detail?id=15948 |
| 114 // This currently just prevents a file from showing up at all |
| 115 // if it's a link, hence preventing arbitary 'read' exploits. |
| 116 if (!file_util::IsLink(file_path.Append(entry.name))) |
| 117 entries->push_back(entry); |
| 118 } |
| 119 return base::PLATFORM_FILE_OK; |
| 120 } |
| 121 |
| 122 PlatformFileError NativeFileUtil::CreateDirectory( |
| 123 FileSystemOperationContext* context, |
| 124 const FilePath& file_path, |
| 125 bool exclusive, |
| 126 bool recursive) { |
| 127 if (context->do_not_write_actually()) |
| 128 return base::PLATFORM_FILE_OK; |
| 129 |
| 130 // If parent dir of file doesn't exist. |
| 131 if (!recursive && !file_util::PathExists(file_path.DirName())) |
| 132 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 133 |
| 134 bool path_exists = file_util::PathExists(file_path); |
| 135 if (exclusive && path_exists) |
| 136 return base::PLATFORM_FILE_ERROR_EXISTS; |
| 137 |
| 138 // If file exists at the path. |
| 139 if (path_exists && !file_util::DirectoryExists(file_path)) |
| 140 return base::PLATFORM_FILE_ERROR_EXISTS; |
| 141 |
| 142 if (!file_util::CreateDirectory(file_path)) |
| 143 return base::PLATFORM_FILE_ERROR_FAILED; |
| 144 return base::PLATFORM_FILE_OK; |
| 145 } |
| 146 |
| 147 PlatformFileError NativeFileUtil::Touch( |
| 148 FileSystemOperationContext* unused, |
| 149 const FilePath& file_path, |
| 150 const base::Time& last_access_time, |
| 151 const base::Time& last_modified_time) { |
| 152 if (!file_util::TouchFile( |
| 153 file_path, last_access_time, last_modified_time)) |
| 154 return base::PLATFORM_FILE_ERROR_FAILED; |
| 155 return base::PLATFORM_FILE_OK; |
| 156 } |
| 157 |
| 158 PlatformFileError NativeFileUtil::Truncate( |
| 159 FileSystemOperationContext* unused, |
| 160 const FilePath& file_path, |
| 161 int64 length) { |
| 162 PlatformFileError error_code(base::PLATFORM_FILE_ERROR_FAILED); |
| 163 PlatformFile file = |
| 164 base::CreatePlatformFile( |
| 165 file_path, |
| 166 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE, |
| 167 NULL, |
| 168 &error_code); |
| 169 if (error_code != base::PLATFORM_FILE_OK) { |
| 170 return error_code; |
| 171 } |
| 172 DCHECK_NE(base::kInvalidPlatformFileValue, file); |
| 173 if (!base::TruncatePlatformFile(file, length)) |
| 174 error_code = base::PLATFORM_FILE_ERROR_FAILED; |
| 175 base::ClosePlatformFile(file); |
| 176 return error_code; |
| 177 } |
| 178 |
| 179 PlatformFileError NativeFileUtil::CopyOrMoveFile( |
| 180 FileSystemOperationContext* unused, |
| 181 const FilePath& src_file_path, |
| 182 const FilePath& dest_file_path, |
| 183 bool copy) { |
| 184 if (copy) { |
| 185 if (file_util::CopyFile(src_file_path, dest_file_path)) |
| 186 return base::PLATFORM_FILE_OK; |
| 187 } else { |
| 188 DCHECK(!file_util::DirectoryExists(src_file_path)); |
| 189 if (file_util::Move(src_file_path, dest_file_path)) |
| 190 return base::PLATFORM_FILE_OK; |
| 191 } |
| 192 return base::PLATFORM_FILE_ERROR_FAILED; |
| 193 } |
| 194 |
| 195 PlatformFileError NativeFileUtil::CopyInForeignFile( |
| 196 FileSystemOperationContext* context, |
| 197 const FilePath& src_file_path, |
| 198 const FilePath& dest_file_path) { |
| 199 return CopyOrMoveFile(context, src_file_path, dest_file_path, true); |
| 200 } |
| 201 |
| 202 PlatformFileError NativeFileUtil::DeleteFile( |
| 203 FileSystemOperationContext* unused, |
| 204 const FilePath& file_path) { |
| 205 if (!file_util::PathExists(file_path)) |
| 206 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 207 if (file_util::DirectoryExists(file_path)) |
| 208 return base::PLATFORM_FILE_ERROR_NOT_A_FILE; |
| 209 if (!file_util::Delete(file_path, false)) |
| 210 return base::PLATFORM_FILE_ERROR_FAILED; |
| 211 return base::PLATFORM_FILE_OK; |
| 212 } |
| 213 |
| 214 PlatformFileError NativeFileUtil::DeleteSingleDirectory( |
| 215 FileSystemOperationContext* unused, |
| 216 const FilePath& file_path) { |
| 217 if (!file_util::PathExists(file_path)) |
| 218 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 219 if (!file_util::DirectoryExists(file_path)) { |
| 220 // TODO(dmikurube): Check if this error code is appropriate. |
| 221 return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; |
| 222 } |
| 223 if (!file_util::IsDirectoryEmpty(file_path)) { |
| 224 // TODO(dmikurube): Check if this error code is appropriate. |
| 225 return base::PLATFORM_FILE_ERROR_NOT_EMPTY; |
| 226 } |
| 227 if (!file_util::Delete(file_path, false)) |
| 228 return base::PLATFORM_FILE_ERROR_FAILED; |
| 229 return base::PLATFORM_FILE_OK; |
| 230 } |
| 231 |
| 232 bool NativeFileUtil::PathExists( |
| 233 FileSystemOperationContext* unused, |
| 234 const FilePath& file_path) { |
| 235 return file_util::PathExists(file_path); |
| 236 } |
| 237 |
| 238 bool NativeFileUtil::DirectoryExists( |
| 239 FileSystemOperationContext* unused, |
| 240 const FilePath& file_path) { |
| 241 return file_util::DirectoryExists(file_path); |
| 242 } |
| 243 |
| 244 bool NativeFileUtil::IsDirectoryEmpty( |
| 245 FileSystemOperationContext* unused, |
| 246 const FilePath& file_path) { |
| 247 return file_util::IsDirectoryEmpty(file_path); |
| 248 } |
| 249 |
| 250 class FileSystemFileEnumerator |
| 251 : public FileApiFileUtil::AbstractFileEnumerator { |
| 252 public: |
| 253 FileSystemFileEnumerator(const FilePath& root_path, |
| 254 bool recursive, |
| 255 file_util::FileEnumerator::FileType file_type) |
| 256 : file_enum_(root_path, recursive, file_type) { |
| 257 } |
| 258 |
| 259 ~FileSystemFileEnumerator() {} |
| 260 |
| 261 virtual FilePath Next(); |
| 262 virtual bool IsDirectory(); |
| 263 |
| 264 private: |
| 265 file_util::FileEnumerator file_enum_; |
| 266 }; |
| 267 |
| 268 FilePath FileSystemFileEnumerator::Next() { |
| 269 return file_enum_.Next(); |
| 270 } |
| 271 |
| 272 bool FileSystemFileEnumerator::IsDirectory() { |
| 273 file_util::FileEnumerator::FindInfo file_util_info; |
| 274 file_enum_.GetFindInfo(&file_util_info); |
| 275 return file_util::FileEnumerator::IsDirectory(file_util_info); |
| 276 } |
| 277 |
| 278 FileApiFileUtil::AbstractFileEnumerator* NativeFileUtil::CreateFileEnumerator( |
| 279 FileSystemOperationContext* unused, |
| 280 const FilePath& root_path) { |
| 281 return new FileSystemFileEnumerator( |
| 282 root_path, true, static_cast<file_util::FileEnumerator::FileType>( |
| 283 file_util::FileEnumerator::FILES | |
| 284 file_util::FileEnumerator::DIRECTORIES)); |
| 285 } |
| 286 |
| 287 } // namespace fileapi |
OLD | NEW |