• 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 "webkit/browser/fileapi/local_file_util.h"
6 
7 #include "base/file_util.h"
8 #include "base/files/file_enumerator.h"
9 #include "base/files/file_util_proxy.h"
10 #include "url/gurl.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"
18 
19 namespace fileapi {
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, dest_file_path, option,
206       fileapi::NativeFileUtil::CopyOrMoveModeForDestination(dest_url, copy));
207 }
208 
CopyInForeignFile(FileSystemOperationContext * context,const base::FilePath & src_file_path,const FileSystemURL & dest_url)209 base::File::Error LocalFileUtil::CopyInForeignFile(
210     FileSystemOperationContext* context,
211     const base::FilePath& src_file_path,
212     const FileSystemURL& dest_url) {
213   if (src_file_path.empty())
214     return base::File::FILE_ERROR_INVALID_OPERATION;
215 
216   base::FilePath dest_file_path;
217   base::File::Error error =
218       GetLocalFilePath(context, dest_url, &dest_file_path);
219   if (error != base::File::FILE_OK)
220     return error;
221   return NativeFileUtil::CopyOrMoveFile(
222       src_file_path, dest_file_path, FileSystemOperation::OPTION_NONE,
223       fileapi::NativeFileUtil::CopyOrMoveModeForDestination(dest_url,
224                                                             true /* copy */));
225 }
226 
DeleteFile(FileSystemOperationContext * context,const FileSystemURL & url)227 base::File::Error LocalFileUtil::DeleteFile(
228     FileSystemOperationContext* context,
229     const FileSystemURL& url) {
230   base::FilePath file_path;
231   base::File::Error error = GetLocalFilePath(context, url, &file_path);
232   if (error != base::File::FILE_OK)
233     return error;
234   return NativeFileUtil::DeleteFile(file_path);
235 }
236 
DeleteDirectory(FileSystemOperationContext * context,const FileSystemURL & url)237 base::File::Error LocalFileUtil::DeleteDirectory(
238     FileSystemOperationContext* context,
239     const FileSystemURL& url) {
240   base::FilePath file_path;
241   base::File::Error error = GetLocalFilePath(context, url, &file_path);
242   if (error != base::File::FILE_OK)
243     return error;
244   return NativeFileUtil::DeleteDirectory(file_path);
245 }
246 
CreateSnapshotFile(FileSystemOperationContext * context,const FileSystemURL & url,base::File::Error * error,base::File::Info * file_info,base::FilePath * platform_path)247 webkit_blob::ScopedFile LocalFileUtil::CreateSnapshotFile(
248     FileSystemOperationContext* context,
249     const FileSystemURL& url,
250     base::File::Error* error,
251     base::File::Info* file_info,
252     base::FilePath* platform_path) {
253   DCHECK(file_info);
254   // We're just returning the local file information.
255   *error = GetFileInfo(context, url, file_info, platform_path);
256   if (*error == base::File::FILE_OK && file_info->is_directory)
257     *error = base::File::FILE_ERROR_NOT_A_FILE;
258   return webkit_blob::ScopedFile();
259 }
260 
261 }  // namespace fileapi
262