Include all dupe types (event when value is zero) in scan stats.
[chromium-blink-merge.git] / storage / browser / fileapi / local_file_util.cc
blob27a130817c388140953e7d273c77a0231329411d
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"
17 #include "url/gurl.h"
19 namespace storage {
21 AsyncFileUtil* AsyncFileUtil::CreateForLocalFileSystem() {
22 return new AsyncFileUtilAdapter(new LocalFileUtil());
25 class LocalFileEnumerator : public FileSystemFileUtil::AbstractFileEnumerator {
26 public:
27 LocalFileEnumerator(const base::FilePath& platform_root_path,
28 const base::FilePath& virtual_root_path,
29 int file_type)
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;
42 private:
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();
54 if (next.empty())
55 return next;
56 file_util_info_ = file_enum_.GetInfo();
58 base::FilePath path;
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,
96 bool* created) {
97 base::FilePath file_path;
98 base::File::Error error = GetLocalFilePath(context, url, &file_path);
99 if (error != base::File::FILE_OK)
100 return error;
101 return NativeFileUtil::EnsureFileExists(file_path, created);
104 base::File::Error LocalFileUtil::CreateDirectory(
105 FileSystemOperationContext* context,
106 const FileSystemURL& url,
107 bool exclusive,
108 bool recursive) {
109 base::FilePath file_path;
110 base::File::Error error = GetLocalFilePath(context, url, &file_path);
111 if (error != base::File::FILE_OK)
112 return error;
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)
124 return error;
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;
132 return error;
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(
145 file_path,
146 root_url.path(),
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)
172 return error;
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,
179 int64 length) {
180 base::FilePath file_path;
181 base::File::Error error = GetLocalFilePath(context, url, &file_path);
182 if (error != base::File::FILE_OK)
183 return error;
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,
192 bool copy) {
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)
196 return error;
198 base::FilePath dest_file_path;
199 error = GetLocalFilePath(context, dest_url, &dest_file_path);
200 if (error != base::File::FILE_OK)
201 return error;
203 return NativeFileUtil::CopyOrMoveFile(
204 src_file_path,
205 dest_file_path,
206 option,
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)
221 return error;
222 return NativeFileUtil::CopyOrMoveFile(
223 src_file_path,
224 dest_file_path,
225 FileSystemOperation::OPTION_NONE,
226 storage::NativeFileUtil::CopyOrMoveModeForDestination(dest_url,
227 true /* copy */));
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)
236 return error;
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)
246 return error;
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) {
256 DCHECK(file_info);
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