blob: 91129524fff4647257ce8817b5a480313025985c [file] [log] [blame]
henrike@webrtc.org47be73b2014-05-13 18:00:261/*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#ifndef WEBRTC_BASE_FILEUTILS_H_
12#define WEBRTC_BASE_FILEUTILS_H_
13
14#include <string>
15
xians@webrtc.orgfd0ab512014-10-10 08:36:5616#if !defined(WEBRTC_WIN)
henrike@webrtc.org47be73b2014-05-13 18:00:2617#include <dirent.h>
18#include <stdio.h>
19#include <sys/stat.h>
20#include <sys/types.h>
21#include <unistd.h>
22#endif
23
24#include "webrtc/base/basictypes.h"
25#include "webrtc/base/common.h"
xians@webrtc.orgfd0ab512014-10-10 08:36:5626#include "webrtc/base/platform_file.h"
henrike@webrtc.org47be73b2014-05-13 18:00:2627#include "webrtc/base/scoped_ptr.h"
28
29namespace rtc {
30
31class FileStream;
32class Pathname;
33
34//////////////////////////
35// Directory Iterator //
36//////////////////////////
37
38// A DirectoryIterator is created with a given directory. It originally points
39// to the first file in the directory, and can be advanecd with Next(). This
40// allows you to get information about each file.
41
42class DirectoryIterator {
43 friend class Filesystem;
44 public:
45 // Constructor
46 DirectoryIterator();
47 // Destructor
48 virtual ~DirectoryIterator();
49
50 // Starts traversing a directory
51 // dir is the directory to traverse
52 // returns true if the directory exists and is valid
53 // The iterator will point to the first entry in the directory
54 virtual bool Iterate(const Pathname &path);
55
56 // Advances to the next file
57 // returns true if there were more files in the directory.
58 virtual bool Next();
59
60 // returns true if the file currently pointed to is a directory
61 virtual bool IsDirectory() const;
62
63 // returns the name of the file currently pointed to
64 virtual std::string Name() const;
65
66 // returns the size of the file currently pointed to
67 virtual size_t FileSize() const;
68
henrike@webrtc.org3ff42222014-07-25 21:58:5069 // returns true if the file is older than seconds
70 virtual bool OlderThan(int seconds) const;
henrike@webrtc.org47be73b2014-05-13 18:00:2671
72 // checks whether current file is a special directory file "." or ".."
73 bool IsDots() const {
74 std::string filename(Name());
75 return (filename.compare(".") == 0) || (filename.compare("..") == 0);
76 }
77
78 private:
79 std::string directory_;
80#if defined(WEBRTC_WIN)
81 WIN32_FIND_DATA data_;
82 HANDLE handle_;
83#else
84 DIR *dir_;
85 struct dirent *dirent_;
86 struct stat stat_;
87#endif
88};
89
90enum FileTimeType { FTT_CREATED, FTT_MODIFIED, FTT_ACCESSED };
91
92class FilesystemInterface {
93 public:
94 virtual ~FilesystemInterface() {}
95
96 // Returns a DirectoryIterator for a given pathname.
97 // TODO: Do fancy abstracted stuff
98 virtual DirectoryIterator *IterateDirectory() {
99 return new DirectoryIterator();
100 }
101
102 // Opens a file. Returns an open StreamInterface if function succeeds.
103 // Otherwise, returns NULL.
104 // TODO: Add an error param to indicate failure reason, similar to
105 // FileStream::Open
106 virtual FileStream *OpenFile(const Pathname &filename,
107 const std::string &mode) = 0;
108
109 // Atomically creates an empty file accessible only to the current user if one
110 // does not already exist at the given path, otherwise fails. This is the only
111 // secure way to create a file in a shared temp directory (e.g., C:\Temp on
112 // Windows or /tmp on Linux).
113 // Note that if it is essential that a file be successfully created then the
114 // app must generate random names and retry on failure, or else it will be
115 // vulnerable to a trivial DoS.
116 virtual bool CreatePrivateFile(const Pathname &filename) = 0;
117
118 // This will attempt to delete the path located at filename.
119 // It ASSERTS and returns false if the path points to a folder or a
120 // non-existent file.
121 virtual bool DeleteFile(const Pathname &filename) = 0;
122
123 // This will attempt to delete the empty folder located at 'folder'
124 // It ASSERTS and returns false if the path points to a file or a non-existent
125 // folder. It fails normally if the folder is not empty or can otherwise
126 // not be deleted.
127 virtual bool DeleteEmptyFolder(const Pathname &folder) = 0;
128
129 // This will call IterateDirectory, to get a directory iterator, and then
130 // call DeleteFolderAndContents and DeleteFile on every path contained in this
131 // folder. If the folder is empty, this returns true.
132 virtual bool DeleteFolderContents(const Pathname &folder);
133
134 // This deletes the contents of a folder, recursively, and then deletes
135 // the folder itself.
136 virtual bool DeleteFolderAndContents(const Pathname &folder) {
137 return DeleteFolderContents(folder) && DeleteEmptyFolder(folder);
138 }
139
140 // This will delete whatever is located at path, be it a file or a folder.
141 // If it is a folder, it will delete it recursively by calling
142 // DeleteFolderAndContents
143 bool DeleteFileOrFolder(const Pathname &path) {
144 if (IsFolder(path))
145 return DeleteFolderAndContents(path);
146 else
147 return DeleteFile(path);
148 }
149
150 // Creates a directory. This will call itself recursively to create /foo/bar
151 // even if /foo does not exist. Returns true if the function succeeds.
152 virtual bool CreateFolder(const Pathname &pathname) = 0;
153
154 // This moves a file from old_path to new_path, where "old_path" is a
155 // plain file. This ASSERTs and returns false if old_path points to a
156 // directory, and returns true if the function succeeds.
157 // If the new path is on a different volume than the old path, this function
158 // will attempt to copy and, if that succeeds, delete the old path.
159 virtual bool MoveFolder(const Pathname &old_path,
160 const Pathname &new_path) = 0;
161
162 // This moves a directory from old_path to new_path, where "old_path" is a
163 // directory. This ASSERTs and returns false if old_path points to a plain
164 // file, and returns true if the function succeeds.
165 // If the new path is on a different volume, this function will attempt to
166 // copy and if that succeeds, delete the old path.
167 virtual bool MoveFile(const Pathname &old_path, const Pathname &new_path) = 0;
168
169 // This attempts to move whatever is located at old_path to new_path,
170 // be it a file or folder.
171 bool MoveFileOrFolder(const Pathname &old_path, const Pathname &new_path) {
172 if (IsFile(old_path)) {
173 return MoveFile(old_path, new_path);
174 } else {
175 return MoveFolder(old_path, new_path);
176 }
177 }
178
179 // This copies a file from old_path to new_path. This method ASSERTs and
180 // returns false if old_path is a folder, and returns true if the copy
181 // succeeds.
182 virtual bool CopyFile(const Pathname &old_path, const Pathname &new_path) = 0;
183
184 // This copies a folder from old_path to new_path.
185 bool CopyFolder(const Pathname &old_path, const Pathname &new_path);
186
187 bool CopyFileOrFolder(const Pathname &old_path, const Pathname &new_path) {
188 if (IsFile(old_path))
189 return CopyFile(old_path, new_path);
190 else
191 return CopyFolder(old_path, new_path);
192 }
193
194 // Returns true if pathname refers to a directory
195 virtual bool IsFolder(const Pathname& pathname) = 0;
196
197 // Returns true if pathname refers to a file
198 virtual bool IsFile(const Pathname& pathname) = 0;
199
200 // Returns true if pathname refers to no filesystem object, every parent
201 // directory either exists, or is also absent.
202 virtual bool IsAbsent(const Pathname& pathname) = 0;
203
204 // Returns true if pathname represents a temporary location on the system.
205 virtual bool IsTemporaryPath(const Pathname& pathname) = 0;
206
207 // A folder appropriate for storing temporary files (Contents are
208 // automatically deleted when the program exits)
209 virtual bool GetTemporaryFolder(Pathname &path, bool create,
210 const std::string *append) = 0;
211
212 virtual std::string TempFilename(const Pathname &dir,
213 const std::string &prefix) = 0;
214
215 // Determines the size of the file indicated by path.
216 virtual bool GetFileSize(const Pathname& path, size_t* size) = 0;
217
218 // Determines a timestamp associated with the file indicated by path.
219 virtual bool GetFileTime(const Pathname& path, FileTimeType which,
220 time_t* time) = 0;
221
222 // Returns the path to the running application.
223 // Note: This is not guaranteed to work on all platforms. Be aware of the
224 // limitations before using it, and robustly handle failure.
225 virtual bool GetAppPathname(Pathname* path) = 0;
226
227 // Get a folder that is unique to the current application, which is suitable
228 // for sharing data between executions of the app. If the per_user arg is
229 // true, the folder is also specific to the current user.
230 virtual bool GetAppDataFolder(Pathname* path, bool per_user) = 0;
231
232 // Get a temporary folder that is unique to the current user and application.
233 // TODO: Re-evaluate the goals of this function. We probably just need any
234 // directory that won't collide with another existing directory, and which
235 // will be cleaned up when the program exits.
236 virtual bool GetAppTempFolder(Pathname* path) = 0;
237
238 // Delete the contents of the folder returned by GetAppTempFolder
239 bool CleanAppTempFolder();
240
241 virtual bool GetDiskFreeSpace(const Pathname& path, int64 *freebytes) = 0;
242
243 // Returns the absolute path of the current directory.
244 virtual Pathname GetCurrentDirectory() = 0;
245
246 // Note: These might go into some shared config section later, but they're
247 // used by some methods in this interface, so we're leaving them here for now.
248 void SetOrganizationName(const std::string& organization) {
249 organization_name_ = organization;
250 }
251 void GetOrganizationName(std::string* organization) {
252 ASSERT(NULL != organization);
253 *organization = organization_name_;
254 }
255 void SetApplicationName(const std::string& application) {
256 application_name_ = application;
257 }
258 void GetApplicationName(std::string* application) {
259 ASSERT(NULL != application);
260 *application = application_name_;
261 }
262
263 protected:
264 std::string organization_name_;
265 std::string application_name_;
266};
267
268class Filesystem {
269 public:
270 static FilesystemInterface *default_filesystem() {
271 ASSERT(default_filesystem_ != NULL);
272 return default_filesystem_;
273 }
274
275 static void set_default_filesystem(FilesystemInterface *filesystem) {
276 default_filesystem_ = filesystem;
277 }
278
279 static FilesystemInterface *swap_default_filesystem(
280 FilesystemInterface *filesystem) {
281 FilesystemInterface *cur = default_filesystem_;
282 default_filesystem_ = filesystem;
283 return cur;
284 }
285
286 static DirectoryIterator *IterateDirectory() {
287 return EnsureDefaultFilesystem()->IterateDirectory();
288 }
289
290 static bool CreateFolder(const Pathname &pathname) {
291 return EnsureDefaultFilesystem()->CreateFolder(pathname);
292 }
293
294 static FileStream *OpenFile(const Pathname &filename,
295 const std::string &mode) {
296 return EnsureDefaultFilesystem()->OpenFile(filename, mode);
297 }
298
299 static bool CreatePrivateFile(const Pathname &filename) {
300 return EnsureDefaultFilesystem()->CreatePrivateFile(filename);
301 }
302
303 static bool DeleteFile(const Pathname &filename) {
304 return EnsureDefaultFilesystem()->DeleteFile(filename);
305 }
306
307 static bool DeleteEmptyFolder(const Pathname &folder) {
308 return EnsureDefaultFilesystem()->DeleteEmptyFolder(folder);
309 }
310
311 static bool DeleteFolderContents(const Pathname &folder) {
312 return EnsureDefaultFilesystem()->DeleteFolderContents(folder);
313 }
314
315 static bool DeleteFolderAndContents(const Pathname &folder) {
316 return EnsureDefaultFilesystem()->DeleteFolderAndContents(folder);
317 }
318
319 static bool MoveFolder(const Pathname &old_path, const Pathname &new_path) {
320 return EnsureDefaultFilesystem()->MoveFolder(old_path, new_path);
321 }
322
323 static bool MoveFile(const Pathname &old_path, const Pathname &new_path) {
324 return EnsureDefaultFilesystem()->MoveFile(old_path, new_path);
325 }
326
327 static bool CopyFolder(const Pathname &old_path, const Pathname &new_path) {
328 return EnsureDefaultFilesystem()->CopyFolder(old_path, new_path);
329 }
330
331 static bool CopyFile(const Pathname &old_path, const Pathname &new_path) {
332 return EnsureDefaultFilesystem()->CopyFile(old_path, new_path);
333 }
334
335 static bool IsFolder(const Pathname& pathname) {
336 return EnsureDefaultFilesystem()->IsFolder(pathname);
337 }
338
339 static bool IsFile(const Pathname &pathname) {
340 return EnsureDefaultFilesystem()->IsFile(pathname);
341 }
342
343 static bool IsAbsent(const Pathname &pathname) {
344 return EnsureDefaultFilesystem()->IsAbsent(pathname);
345 }
346
347 static bool IsTemporaryPath(const Pathname& pathname) {
348 return EnsureDefaultFilesystem()->IsTemporaryPath(pathname);
349 }
350
351 static bool GetTemporaryFolder(Pathname &path, bool create,
352 const std::string *append) {
353 return EnsureDefaultFilesystem()->GetTemporaryFolder(path, create, append);
354 }
355
356 static std::string TempFilename(const Pathname &dir,
357 const std::string &prefix) {
358 return EnsureDefaultFilesystem()->TempFilename(dir, prefix);
359 }
360
361 static bool GetFileSize(const Pathname& path, size_t* size) {
362 return EnsureDefaultFilesystem()->GetFileSize(path, size);
363 }
364
365 static bool GetFileTime(const Pathname& path, FileTimeType which,
366 time_t* time) {
367 return EnsureDefaultFilesystem()->GetFileTime(path, which, time);
368 }
369
370 static bool GetAppPathname(Pathname* path) {
371 return EnsureDefaultFilesystem()->GetAppPathname(path);
372 }
373
374 static bool GetAppDataFolder(Pathname* path, bool per_user) {
375 return EnsureDefaultFilesystem()->GetAppDataFolder(path, per_user);
376 }
377
378 static bool GetAppTempFolder(Pathname* path) {
379 return EnsureDefaultFilesystem()->GetAppTempFolder(path);
380 }
381
382 static bool CleanAppTempFolder() {
383 return EnsureDefaultFilesystem()->CleanAppTempFolder();
384 }
385
386 static bool GetDiskFreeSpace(const Pathname& path, int64 *freebytes) {
387 return EnsureDefaultFilesystem()->GetDiskFreeSpace(path, freebytes);
388 }
389
390 // Definition has to be in the .cc file due to returning forward-declared
391 // Pathname by value.
392 static Pathname GetCurrentDirectory();
393
394 static void SetOrganizationName(const std::string& organization) {
395 EnsureDefaultFilesystem()->SetOrganizationName(organization);
396 }
397
398 static void GetOrganizationName(std::string* organization) {
399 EnsureDefaultFilesystem()->GetOrganizationName(organization);
400 }
401
402 static void SetApplicationName(const std::string& application) {
403 EnsureDefaultFilesystem()->SetApplicationName(application);
404 }
405
406 static void GetApplicationName(std::string* application) {
407 EnsureDefaultFilesystem()->GetApplicationName(application);
408 }
409
410 private:
411 static FilesystemInterface* default_filesystem_;
412
413 static FilesystemInterface *EnsureDefaultFilesystem();
414 DISALLOW_IMPLICIT_CONSTRUCTORS(Filesystem);
415};
416
417class FilesystemScope{
418 public:
419 explicit FilesystemScope(FilesystemInterface *new_fs) {
420 old_fs_ = Filesystem::swap_default_filesystem(new_fs);
421 }
422 ~FilesystemScope() {
423 Filesystem::set_default_filesystem(old_fs_);
424 }
425 private:
426 FilesystemInterface* old_fs_;
427 DISALLOW_IMPLICIT_CONSTRUCTORS(FilesystemScope);
428};
429
430// Generates a unique filename based on the input path. If no path component
431// is specified, it uses the temporary directory. If a filename is provided,
432// up to 100 variations of form basename-N.extension are tried. When
433// create_empty is true, an empty file of this name is created (which
434// decreases the chance of a temporary filename collision with another
435// process).
436bool CreateUniqueFile(Pathname& path, bool create_empty);
437
henrike@webrtc.org47be73b2014-05-13 18:00:26438} // namespace rtc
439
440#endif // WEBRTC_BASE_FILEUTILS_H_