1 // Copyright (c) 2012 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.
5 #include "webkit/browser/fileapi/local_file_util.h"
7 #include "base/file_util.h"
8 #include "base/files/file_enumerator.h"
9 #include "base/files/file_util_proxy.h"
11 #include "webkit/browser/fileapi/async_file_util_adapter.h"
12 #include "webkit/browser/fileapi/file_system_context.h"
13 #include "webkit/browser/fileapi/file_system_operation_context.h"
14 #include "webkit/browser/fileapi/file_system_url.h"
15 #include "webkit/browser/fileapi/native_file_util.h"
16 #include "webkit/common/fileapi/file_system_types.h"
17 #include "webkit/common/fileapi/file_system_util.h"
21 AsyncFileUtil
* AsyncFileUtil::CreateForLocalFileSystem() {
22 return new AsyncFileUtilAdapter(new LocalFileUtil());
25 using base::PlatformFileError
;
27 class LocalFileEnumerator
: public FileSystemFileUtil::AbstractFileEnumerator
{
29 LocalFileEnumerator(const base::FilePath
& platform_root_path
,
30 const base::FilePath
& virtual_root_path
,
32 : file_enum_(platform_root_path
, false /* recursive */, file_type
),
33 platform_root_path_(platform_root_path
),
34 virtual_root_path_(virtual_root_path
) {
37 virtual ~LocalFileEnumerator() {}
39 virtual base::FilePath
Next() OVERRIDE
;
40 virtual int64
Size() OVERRIDE
;
41 virtual base::Time
LastModifiedTime() OVERRIDE
;
42 virtual bool IsDirectory() OVERRIDE
;
45 base::FileEnumerator file_enum_
;
46 base::FileEnumerator::FileInfo file_util_info_
;
47 base::FilePath platform_root_path_
;
48 base::FilePath virtual_root_path_
;
51 base::FilePath
LocalFileEnumerator::Next() {
52 base::FilePath next
= file_enum_
.Next();
53 // Don't return symlinks.
54 while (!next
.empty() && file_util::IsLink(next
))
55 next
= file_enum_
.Next();
58 file_util_info_
= file_enum_
.GetInfo();
61 platform_root_path_
.AppendRelativePath(next
, &path
);
62 return virtual_root_path_
.Append(path
);
65 int64
LocalFileEnumerator::Size() {
66 return file_util_info_
.GetSize();
69 base::Time
LocalFileEnumerator::LastModifiedTime() {
70 return file_util_info_
.GetLastModifiedTime();
73 bool LocalFileEnumerator::IsDirectory() {
74 return file_util_info_
.IsDirectory();
77 LocalFileUtil::LocalFileUtil() {}
79 LocalFileUtil::~LocalFileUtil() {}
81 PlatformFileError
LocalFileUtil::CreateOrOpen(
82 FileSystemOperationContext
* context
,
83 const FileSystemURL
& url
, int file_flags
,
84 base::PlatformFile
* file_handle
, bool* created
) {
86 base::FilePath file_path
;
87 PlatformFileError error
= GetLocalFilePath(context
, url
, &file_path
);
88 if (error
!= base::PLATFORM_FILE_OK
)
90 // Disallow opening files in symlinked paths.
91 if (file_util::IsLink(file_path
))
92 return base::PLATFORM_FILE_ERROR_NOT_FOUND
;
93 return NativeFileUtil::CreateOrOpen(
94 file_path
, file_flags
, file_handle
, created
);
97 PlatformFileError
LocalFileUtil::Close(FileSystemOperationContext
* context
,
98 base::PlatformFile file
) {
99 return NativeFileUtil::Close(file
);
102 PlatformFileError
LocalFileUtil::EnsureFileExists(
103 FileSystemOperationContext
* context
,
104 const FileSystemURL
& url
,
106 base::FilePath file_path
;
107 PlatformFileError error
= GetLocalFilePath(context
, url
, &file_path
);
108 if (error
!= base::PLATFORM_FILE_OK
)
110 return NativeFileUtil::EnsureFileExists(file_path
, created
);
113 PlatformFileError
LocalFileUtil::CreateDirectory(
114 FileSystemOperationContext
* context
,
115 const FileSystemURL
& url
,
118 base::FilePath file_path
;
119 PlatformFileError error
= GetLocalFilePath(context
, url
, &file_path
);
120 if (error
!= base::PLATFORM_FILE_OK
)
122 return NativeFileUtil::CreateDirectory(file_path
, exclusive
, recursive
);
125 PlatformFileError
LocalFileUtil::GetFileInfo(
126 FileSystemOperationContext
* context
,
127 const FileSystemURL
& url
,
128 base::PlatformFileInfo
* file_info
,
129 base::FilePath
* platform_file_path
) {
130 base::FilePath file_path
;
131 PlatformFileError error
= GetLocalFilePath(context
, url
, &file_path
);
132 if (error
!= base::PLATFORM_FILE_OK
)
134 // We should not follow symbolic links in sandboxed file system.
135 if (file_util::IsLink(file_path
))
136 return base::PLATFORM_FILE_ERROR_NOT_FOUND
;
137 error
= NativeFileUtil::GetFileInfo(file_path
, file_info
);
138 if (error
== base::PLATFORM_FILE_OK
)
139 *platform_file_path
= file_path
;
143 scoped_ptr
<FileSystemFileUtil::AbstractFileEnumerator
> LocalFileUtil::
144 CreateFileEnumerator(
145 FileSystemOperationContext
* context
,
146 const FileSystemURL
& root_url
) {
147 base::FilePath file_path
;
148 if (GetLocalFilePath(context
, root_url
, &file_path
) !=
149 base::PLATFORM_FILE_OK
) {
150 return make_scoped_ptr(new EmptyFileEnumerator
)
151 .PassAs
<FileSystemFileUtil::AbstractFileEnumerator
>();
153 return make_scoped_ptr(new LocalFileEnumerator(
154 file_path
, root_url
.path(),
155 base::FileEnumerator::FILES
| base::FileEnumerator::DIRECTORIES
))
156 .PassAs
<FileSystemFileUtil::AbstractFileEnumerator
>();
159 PlatformFileError
LocalFileUtil::GetLocalFilePath(
160 FileSystemOperationContext
* context
,
161 const FileSystemURL
& url
,
162 base::FilePath
* local_file_path
) {
163 DCHECK(local_file_path
);
164 DCHECK(url
.is_valid());
165 if (url
.path().empty()) {
166 // Root direcory case, which should not be accessed.
167 return base::PLATFORM_FILE_ERROR_ACCESS_DENIED
;
169 *local_file_path
= url
.path();
170 return base::PLATFORM_FILE_OK
;
173 PlatformFileError
LocalFileUtil::Touch(
174 FileSystemOperationContext
* context
,
175 const FileSystemURL
& url
,
176 const base::Time
& last_access_time
,
177 const base::Time
& last_modified_time
) {
178 base::FilePath file_path
;
179 PlatformFileError error
= GetLocalFilePath(context
, url
, &file_path
);
180 if (error
!= base::PLATFORM_FILE_OK
)
182 return NativeFileUtil::Touch(file_path
, last_access_time
, last_modified_time
);
185 PlatformFileError
LocalFileUtil::Truncate(
186 FileSystemOperationContext
* context
,
187 const FileSystemURL
& url
,
189 base::FilePath file_path
;
190 PlatformFileError error
= GetLocalFilePath(context
, url
, &file_path
);
191 if (error
!= base::PLATFORM_FILE_OK
)
193 return NativeFileUtil::Truncate(file_path
, length
);
196 PlatformFileError
LocalFileUtil::CopyOrMoveFile(
197 FileSystemOperationContext
* context
,
198 const FileSystemURL
& src_url
,
199 const FileSystemURL
& dest_url
,
200 CopyOrMoveOption option
,
202 base::FilePath src_file_path
;
203 PlatformFileError error
= GetLocalFilePath(context
, src_url
, &src_file_path
);
204 if (error
!= base::PLATFORM_FILE_OK
)
207 base::FilePath dest_file_path
;
208 error
= GetLocalFilePath(context
, dest_url
, &dest_file_path
);
209 if (error
!= base::PLATFORM_FILE_OK
)
212 return NativeFileUtil::CopyOrMoveFile(
213 src_file_path
, dest_file_path
, option
, copy
);
216 PlatformFileError
LocalFileUtil::CopyInForeignFile(
217 FileSystemOperationContext
* context
,
218 const base::FilePath
& src_file_path
,
219 const FileSystemURL
& dest_url
) {
220 if (src_file_path
.empty())
221 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION
;
223 base::FilePath dest_file_path
;
224 PlatformFileError error
=
225 GetLocalFilePath(context
, dest_url
, &dest_file_path
);
226 if (error
!= base::PLATFORM_FILE_OK
)
228 return NativeFileUtil::CopyOrMoveFile(
229 src_file_path
, dest_file_path
, FileSystemOperation::OPTION_NONE
, true);
232 PlatformFileError
LocalFileUtil::DeleteFile(
233 FileSystemOperationContext
* context
,
234 const FileSystemURL
& url
) {
235 base::FilePath file_path
;
236 PlatformFileError error
= GetLocalFilePath(context
, url
, &file_path
);
237 if (error
!= base::PLATFORM_FILE_OK
)
239 return NativeFileUtil::DeleteFile(file_path
);
242 PlatformFileError
LocalFileUtil::DeleteDirectory(
243 FileSystemOperationContext
* context
,
244 const FileSystemURL
& url
) {
245 base::FilePath file_path
;
246 PlatformFileError error
= GetLocalFilePath(context
, url
, &file_path
);
247 if (error
!= base::PLATFORM_FILE_OK
)
249 return NativeFileUtil::DeleteDirectory(file_path
);
252 webkit_blob::ScopedFile
LocalFileUtil::CreateSnapshotFile(
253 FileSystemOperationContext
* context
,
254 const FileSystemURL
& url
,
255 base::PlatformFileError
* error
,
256 base::PlatformFileInfo
* file_info
,
257 base::FilePath
* platform_path
) {
259 // We're just returning the local file information.
260 *error
= GetFileInfo(context
, url
, file_info
, platform_path
);
261 if (*error
== base::PLATFORM_FILE_OK
&& file_info
->is_directory
)
262 *error
= base::PLATFORM_FILE_ERROR_NOT_A_FILE
;
263 return webkit_blob::ScopedFile();
266 } // namespace fileapi