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