• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "storage/browser/fileapi/local_file_util.h"
6 
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"
18 
19 namespace storage {
20 
CreateForLocalFileSystem()21 AsyncFileUtil* AsyncFileUtil::CreateForLocalFileSystem() {
22   return new AsyncFileUtilAdapter(new LocalFileUtil());
23 }
24 
25 class LocalFileEnumerator : public FileSystemFileUtil::AbstractFileEnumerator {
26  public:
LocalFileEnumerator(const base::FilePath & platform_root_path,const base::FilePath & virtual_root_path,int file_type)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) {
33   }
34 
~LocalFileEnumerator()35   virtual ~LocalFileEnumerator() {}
36 
37   virtual base::FilePath Next() OVERRIDE;
38   virtual int64 Size() OVERRIDE;
39   virtual base::Time LastModifiedTime() OVERRIDE;
40   virtual bool IsDirectory() OVERRIDE;
41 
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_;
47 };
48 
Next()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();
57 
58   base::FilePath path;
59   platform_root_path_.AppendRelativePath(next, &path);
60   return virtual_root_path_.Append(path);
61 }
62 
Size()63 int64 LocalFileEnumerator::Size() {
64   return file_util_info_.GetSize();
65 }
66 
LastModifiedTime()67 base::Time LocalFileEnumerator::LastModifiedTime() {
68   return file_util_info_.GetLastModifiedTime();
69 }
70 
IsDirectory()71 bool LocalFileEnumerator::IsDirectory() {
72   return file_util_info_.IsDirectory();
73 }
74 
LocalFileUtil()75 LocalFileUtil::LocalFileUtil() {}
76 
~LocalFileUtil()77 LocalFileUtil::~LocalFileUtil() {}
78 
CreateOrOpen(FileSystemOperationContext * context,const FileSystemURL & url,int file_flags)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);
89 
90   return NativeFileUtil::CreateOrOpen(file_path, file_flags);
91 }
92 
EnsureFileExists(FileSystemOperationContext * context,const FileSystemURL & url,bool * created)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);
102 }
103 
CreateDirectory(FileSystemOperationContext * context,const FileSystemURL & url,bool exclusive,bool recursive)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);
114 }
115 
GetFileInfo(FileSystemOperationContext * context,const FileSystemURL & url,base::File::Info * file_info,base::FilePath * platform_file_path)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;
128 
129   error = NativeFileUtil::GetFileInfo(file_path, file_info);
130   if (error == base::File::FILE_OK)
131     *platform_file_path = file_path;
132   return error;
133 }
134 
135 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> LocalFileUtil::
CreateFileEnumerator(FileSystemOperationContext * context,const FileSystemURL & root_url)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)
143         .PassAs<FileSystemFileUtil::AbstractFileEnumerator>();
144   }
145   return make_scoped_ptr(new LocalFileEnumerator(
146       file_path, root_url.path(),
147       base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES))
148       .PassAs<FileSystemFileUtil::AbstractFileEnumerator>();
149 }
150 
GetLocalFilePath(FileSystemOperationContext * context,const FileSystemURL & url,base::FilePath * local_file_path)151 base::File::Error LocalFileUtil::GetLocalFilePath(
152     FileSystemOperationContext* context,
153     const FileSystemURL& url,
154     base::FilePath* local_file_path) {
155   DCHECK(local_file_path);
156   DCHECK(url.is_valid());
157   if (url.path().empty()) {
158     // Root direcory case, which should not be accessed.
159     return base::File::FILE_ERROR_ACCESS_DENIED;
160   }
161   *local_file_path = url.path();
162   return base::File::FILE_OK;
163 }
164 
Touch(FileSystemOperationContext * context,const FileSystemURL & url,const base::Time & last_access_time,const base::Time & last_modified_time)165 base::File::Error LocalFileUtil::Touch(
166     FileSystemOperationContext* context,
167     const FileSystemURL& url,
168     const base::Time& last_access_time,
169     const base::Time& last_modified_time) {
170   base::FilePath file_path;
171   base::File::Error error = GetLocalFilePath(context, url, &file_path);
172   if (error != base::File::FILE_OK)
173     return error;
174   return NativeFileUtil::Touch(file_path, last_access_time, last_modified_time);
175 }
176 
Truncate(FileSystemOperationContext * context,const FileSystemURL & url,int64 length)177 base::File::Error LocalFileUtil::Truncate(
178     FileSystemOperationContext* context,
179     const FileSystemURL& url,
180     int64 length) {
181   base::FilePath file_path;
182   base::File::Error error = GetLocalFilePath(context, url, &file_path);
183   if (error != base::File::FILE_OK)
184     return error;
185   return NativeFileUtil::Truncate(file_path, length);
186 }
187 
CopyOrMoveFile(FileSystemOperationContext * context,const FileSystemURL & src_url,const FileSystemURL & dest_url,CopyOrMoveOption option,bool copy)188 base::File::Error LocalFileUtil::CopyOrMoveFile(
189     FileSystemOperationContext* context,
190     const FileSystemURL& src_url,
191     const FileSystemURL& dest_url,
192     CopyOrMoveOption option,
193     bool copy) {
194   base::FilePath src_file_path;
195   base::File::Error error = GetLocalFilePath(context, src_url, &src_file_path);
196   if (error != base::File::FILE_OK)
197     return error;
198 
199   base::FilePath dest_file_path;
200   error = GetLocalFilePath(context, dest_url, &dest_file_path);
201   if (error != base::File::FILE_OK)
202     return error;
203 
204   return NativeFileUtil::CopyOrMoveFile(
205       src_file_path,
206       dest_file_path,
207       option,
208       storage::NativeFileUtil::CopyOrMoveModeForDestination(dest_url, copy));
209 }
210 
CopyInForeignFile(FileSystemOperationContext * context,const base::FilePath & src_file_path,const FileSystemURL & dest_url)211 base::File::Error LocalFileUtil::CopyInForeignFile(
212     FileSystemOperationContext* context,
213     const base::FilePath& src_file_path,
214     const FileSystemURL& dest_url) {
215   if (src_file_path.empty())
216     return base::File::FILE_ERROR_INVALID_OPERATION;
217 
218   base::FilePath dest_file_path;
219   base::File::Error error =
220       GetLocalFilePath(context, dest_url, &dest_file_path);
221   if (error != base::File::FILE_OK)
222     return error;
223   return NativeFileUtil::CopyOrMoveFile(
224       src_file_path,
225       dest_file_path,
226       FileSystemOperation::OPTION_NONE,
227       storage::NativeFileUtil::CopyOrMoveModeForDestination(dest_url,
228                                                             true /* copy */));
229 }
230 
DeleteFile(FileSystemOperationContext * context,const FileSystemURL & url)231 base::File::Error LocalFileUtil::DeleteFile(
232     FileSystemOperationContext* context,
233     const FileSystemURL& url) {
234   base::FilePath file_path;
235   base::File::Error error = GetLocalFilePath(context, url, &file_path);
236   if (error != base::File::FILE_OK)
237     return error;
238   return NativeFileUtil::DeleteFile(file_path);
239 }
240 
DeleteDirectory(FileSystemOperationContext * context,const FileSystemURL & url)241 base::File::Error LocalFileUtil::DeleteDirectory(
242     FileSystemOperationContext* context,
243     const FileSystemURL& url) {
244   base::FilePath file_path;
245   base::File::Error error = GetLocalFilePath(context, url, &file_path);
246   if (error != base::File::FILE_OK)
247     return error;
248   return NativeFileUtil::DeleteDirectory(file_path);
249 }
250 
CreateSnapshotFile(FileSystemOperationContext * context,const FileSystemURL & url,base::File::Error * error,base::File::Info * file_info,base::FilePath * platform_path)251 storage::ScopedFile LocalFileUtil::CreateSnapshotFile(
252     FileSystemOperationContext* context,
253     const FileSystemURL& url,
254     base::File::Error* error,
255     base::File::Info* file_info,
256     base::FilePath* platform_path) {
257   DCHECK(file_info);
258   // We're just returning the local file information.
259   *error = GetFileInfo(context, url, file_info, platform_path);
260   if (*error == base::File::FILE_OK && file_info->is_directory)
261     *error = base::File::FILE_ERROR_NOT_A_FILE;
262   return storage::ScopedFile();
263 }
264 
265 }  // namespace storage
266