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