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 "storage/browser/fileapi/local_file_util.h"
7 #include "base/files/file_enumerator.h"
8 #include "base/files/file_util.h"
9 #include "base/files/file_util_proxy.h"
10 #include "storage/browser/fileapi/async_file_util_adapter.h"
11 #include "storage/browser/fileapi/file_system_context.h"
12 #include "storage/browser/fileapi/file_system_operation_context.h"
13 #include "storage/browser/fileapi/file_system_url.h"
14 #include "storage/browser/fileapi/native_file_util.h"
15 #include "storage/common/fileapi/file_system_types.h"
16 #include "storage/common/fileapi/file_system_util.h"
21 AsyncFileUtil
* AsyncFileUtil::CreateForLocalFileSystem() {
22 return new AsyncFileUtilAdapter(new LocalFileUtil());
25 class LocalFileEnumerator
: public FileSystemFileUtil::AbstractFileEnumerator
{
27 LocalFileEnumerator(const base::FilePath
& platform_root_path
,
28 const base::FilePath
& virtual_root_path
,
30 : file_enum_(platform_root_path
, false /* recursive */, file_type
),
31 platform_root_path_(platform_root_path
),
32 virtual_root_path_(virtual_root_path
) {
35 ~LocalFileEnumerator() override
{}
37 base::FilePath
Next() override
;
38 int64
Size() override
;
39 base::Time
LastModifiedTime() override
;
40 bool IsDirectory() override
;
43 base::FileEnumerator file_enum_
;
44 base::FileEnumerator::FileInfo file_util_info_
;
45 base::FilePath platform_root_path_
;
46 base::FilePath virtual_root_path_
;
49 base::FilePath
LocalFileEnumerator::Next() {
50 base::FilePath next
= file_enum_
.Next();
51 // Don't return symlinks.
52 while (!next
.empty() && base::IsLink(next
))
53 next
= file_enum_
.Next();
56 file_util_info_
= file_enum_
.GetInfo();
59 platform_root_path_
.AppendRelativePath(next
, &path
);
60 return virtual_root_path_
.Append(path
);
63 int64
LocalFileEnumerator::Size() {
64 return file_util_info_
.GetSize();
67 base::Time
LocalFileEnumerator::LastModifiedTime() {
68 return file_util_info_
.GetLastModifiedTime();
71 bool LocalFileEnumerator::IsDirectory() {
72 return file_util_info_
.IsDirectory();
75 LocalFileUtil::LocalFileUtil() {}
77 LocalFileUtil::~LocalFileUtil() {}
79 base::File
LocalFileUtil::CreateOrOpen(
80 FileSystemOperationContext
* context
,
81 const FileSystemURL
& url
, int file_flags
) {
82 base::FilePath file_path
;
83 base::File::Error error
= GetLocalFilePath(context
, url
, &file_path
);
84 if (error
!= base::File::FILE_OK
)
85 return base::File(error
);
86 // Disallow opening files in symlinked paths.
87 if (base::IsLink(file_path
))
88 return base::File(base::File::FILE_ERROR_NOT_FOUND
);
90 return NativeFileUtil::CreateOrOpen(file_path
, file_flags
);
93 base::File::Error
LocalFileUtil::EnsureFileExists(
94 FileSystemOperationContext
* context
,
95 const FileSystemURL
& url
,
97 base::FilePath file_path
;
98 base::File::Error error
= GetLocalFilePath(context
, url
, &file_path
);
99 if (error
!= base::File::FILE_OK
)
101 return NativeFileUtil::EnsureFileExists(file_path
, created
);
104 base::File::Error
LocalFileUtil::CreateDirectory(
105 FileSystemOperationContext
* context
,
106 const FileSystemURL
& url
,
109 base::FilePath file_path
;
110 base::File::Error error
= GetLocalFilePath(context
, url
, &file_path
);
111 if (error
!= base::File::FILE_OK
)
113 return NativeFileUtil::CreateDirectory(file_path
, exclusive
, recursive
);
116 base::File::Error
LocalFileUtil::GetFileInfo(
117 FileSystemOperationContext
* context
,
118 const FileSystemURL
& url
,
119 base::File::Info
* file_info
,
120 base::FilePath
* platform_file_path
) {
121 base::FilePath file_path
;
122 base::File::Error error
= GetLocalFilePath(context
, url
, &file_path
);
123 if (error
!= base::File::FILE_OK
)
125 // We should not follow symbolic links in sandboxed file system.
126 if (base::IsLink(file_path
))
127 return base::File::FILE_ERROR_NOT_FOUND
;
129 error
= NativeFileUtil::GetFileInfo(file_path
, file_info
);
130 if (error
== base::File::FILE_OK
)
131 *platform_file_path
= file_path
;
135 scoped_ptr
<FileSystemFileUtil::AbstractFileEnumerator
> LocalFileUtil::
136 CreateFileEnumerator(
137 FileSystemOperationContext
* context
,
138 const FileSystemURL
& root_url
) {
139 base::FilePath file_path
;
140 if (GetLocalFilePath(context
, root_url
, &file_path
) !=
141 base::File::FILE_OK
) {
142 return make_scoped_ptr(new EmptyFileEnumerator
);
144 return make_scoped_ptr(new LocalFileEnumerator(
147 base::FileEnumerator::FILES
| base::FileEnumerator::DIRECTORIES
));
150 base::File::Error
LocalFileUtil::GetLocalFilePath(
151 FileSystemOperationContext
* context
,
152 const FileSystemURL
& url
,
153 base::FilePath
* local_file_path
) {
154 DCHECK(local_file_path
);
155 DCHECK(url
.is_valid());
156 if (url
.path().empty()) {
157 // Root direcory case, which should not be accessed.
158 return base::File::FILE_ERROR_ACCESS_DENIED
;
160 *local_file_path
= url
.path();
161 return base::File::FILE_OK
;
164 base::File::Error
LocalFileUtil::Touch(
165 FileSystemOperationContext
* context
,
166 const FileSystemURL
& url
,
167 const base::Time
& last_access_time
,
168 const base::Time
& last_modified_time
) {
169 base::FilePath file_path
;
170 base::File::Error error
= GetLocalFilePath(context
, url
, &file_path
);
171 if (error
!= base::File::FILE_OK
)
173 return NativeFileUtil::Touch(file_path
, last_access_time
, last_modified_time
);
176 base::File::Error
LocalFileUtil::Truncate(
177 FileSystemOperationContext
* context
,
178 const FileSystemURL
& url
,
180 base::FilePath file_path
;
181 base::File::Error error
= GetLocalFilePath(context
, url
, &file_path
);
182 if (error
!= base::File::FILE_OK
)
184 return NativeFileUtil::Truncate(file_path
, length
);
187 base::File::Error
LocalFileUtil::CopyOrMoveFile(
188 FileSystemOperationContext
* context
,
189 const FileSystemURL
& src_url
,
190 const FileSystemURL
& dest_url
,
191 CopyOrMoveOption option
,
193 base::FilePath src_file_path
;
194 base::File::Error error
= GetLocalFilePath(context
, src_url
, &src_file_path
);
195 if (error
!= base::File::FILE_OK
)
198 base::FilePath dest_file_path
;
199 error
= GetLocalFilePath(context
, dest_url
, &dest_file_path
);
200 if (error
!= base::File::FILE_OK
)
203 return NativeFileUtil::CopyOrMoveFile(
207 storage::NativeFileUtil::CopyOrMoveModeForDestination(dest_url
, copy
));
210 base::File::Error
LocalFileUtil::CopyInForeignFile(
211 FileSystemOperationContext
* context
,
212 const base::FilePath
& src_file_path
,
213 const FileSystemURL
& dest_url
) {
214 if (src_file_path
.empty())
215 return base::File::FILE_ERROR_INVALID_OPERATION
;
217 base::FilePath dest_file_path
;
218 base::File::Error error
=
219 GetLocalFilePath(context
, dest_url
, &dest_file_path
);
220 if (error
!= base::File::FILE_OK
)
222 return NativeFileUtil::CopyOrMoveFile(
225 FileSystemOperation::OPTION_NONE
,
226 storage::NativeFileUtil::CopyOrMoveModeForDestination(dest_url
,
230 base::File::Error
LocalFileUtil::DeleteFile(
231 FileSystemOperationContext
* context
,
232 const FileSystemURL
& url
) {
233 base::FilePath file_path
;
234 base::File::Error error
= GetLocalFilePath(context
, url
, &file_path
);
235 if (error
!= base::File::FILE_OK
)
237 return NativeFileUtil::DeleteFile(file_path
);
240 base::File::Error
LocalFileUtil::DeleteDirectory(
241 FileSystemOperationContext
* context
,
242 const FileSystemURL
& url
) {
243 base::FilePath file_path
;
244 base::File::Error error
= GetLocalFilePath(context
, url
, &file_path
);
245 if (error
!= base::File::FILE_OK
)
247 return NativeFileUtil::DeleteDirectory(file_path
);
250 storage::ScopedFile
LocalFileUtil::CreateSnapshotFile(
251 FileSystemOperationContext
* context
,
252 const FileSystemURL
& url
,
253 base::File::Error
* error
,
254 base::File::Info
* file_info
,
255 base::FilePath
* platform_path
) {
257 // We're just returning the local file information.
258 *error
= GetFileInfo(context
, url
, file_info
, platform_path
);
259 if (*error
== base::File::FILE_OK
&& file_info
->is_directory
)
260 *error
= base::File::FILE_ERROR_NOT_A_FILE
;
261 return storage::ScopedFile();
264 } // namespace storage