3 * Copyright 2004--2006, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #ifndef TALK_BASE_FILEUTILS_H_
29 #define TALK_BASE_FILEUTILS_H_
34 #include "talk/base/win32.h"
39 #include <sys/types.h>
43 #include "talk/base/basictypes.h"
44 #include "talk/base/common.h"
45 #include "talk/base/scoped_ptr.h"
52 //////////////////////////
53 // Directory Iterator //
54 //////////////////////////
56 // A DirectoryIterator is created with a given directory. It originally points
57 // to the first file in the directory, and can be advanecd with Next(). This
58 // allows you to get information about each file.
60 class DirectoryIterator {
61 friend class Filesystem;
66 virtual ~DirectoryIterator();
68 // Starts traversing a directory
69 // dir is the directory to traverse
70 // returns true if the directory exists and is valid
71 // The iterator will point to the first entry in the directory
72 virtual bool Iterate(const Pathname &path);
74 // Advances to the next file
75 // returns true if there were more files in the directory.
78 // returns true if the file currently pointed to is a directory
79 virtual bool IsDirectory() const;
81 // returns the name of the file currently pointed to
82 virtual std::string Name() const;
84 // returns the size of the file currently pointed to
85 virtual size_t FileSize() const;
87 // returns the last modified time of the file currently pointed to
88 virtual time_t FileModifyTime() const;
90 // checks whether current file is a special directory file "." or ".."
92 std::string filename(Name());
93 return (filename.compare(".") == 0) || (filename.compare("..") == 0);
97 std::string directory_;
99 WIN32_FIND_DATA data_;
103 struct dirent *dirent_;
108 enum FileTimeType { FTT_CREATED, FTT_MODIFIED, FTT_ACCESSED };
110 class FilesystemInterface {
112 virtual ~FilesystemInterface() {}
114 // Returns a DirectoryIterator for a given pathname.
115 // TODO: Do fancy abstracted stuff
116 virtual DirectoryIterator *IterateDirectory() {
117 return new DirectoryIterator();
120 // Opens a file. Returns an open StreamInterface if function succeeds.
121 // Otherwise, returns NULL.
122 // TODO: Add an error param to indicate failure reason, similar to
124 virtual FileStream *OpenFile(const Pathname &filename,
125 const std::string &mode) = 0;
127 // Atomically creates an empty file accessible only to the current user if one
128 // does not already exist at the given path, otherwise fails. This is the only
129 // secure way to create a file in a shared temp directory (e.g., C:\Temp on
130 // Windows or /tmp on Linux).
131 // Note that if it is essential that a file be successfully created then the
132 // app must generate random names and retry on failure, or else it will be
133 // vulnerable to a trivial DoS.
134 virtual bool CreatePrivateFile(const Pathname &filename) = 0;
136 // This will attempt to delete the path located at filename.
137 // It ASSERTS and returns false if the path points to a folder or a
138 // non-existent file.
139 virtual bool DeleteFile(const Pathname &filename) = 0;
141 // This will attempt to delete the empty folder located at 'folder'
142 // It ASSERTS and returns false if the path points to a file or a non-existent
143 // folder. It fails normally if the folder is not empty or can otherwise
145 virtual bool DeleteEmptyFolder(const Pathname &folder) = 0;
147 // This will call IterateDirectory, to get a directory iterator, and then
148 // call DeleteFolderAndContents and DeleteFile on every path contained in this
149 // folder. If the folder is empty, this returns true.
150 virtual bool DeleteFolderContents(const Pathname &folder);
152 // This deletes the contents of a folder, recursively, and then deletes
153 // the folder itself.
154 virtual bool DeleteFolderAndContents(const Pathname &folder) {
155 return DeleteFolderContents(folder) && DeleteEmptyFolder(folder);
158 // This will delete whatever is located at path, be it a file or a folder.
159 // If it is a folder, it will delete it recursively by calling
160 // DeleteFolderAndContents
161 bool DeleteFileOrFolder(const Pathname &path) {
163 return DeleteFolderAndContents(path);
165 return DeleteFile(path);
168 // Creates a directory. This will call itself recursively to create /foo/bar
169 // even if /foo does not exist. Returns true if the function succeeds.
170 virtual bool CreateFolder(const Pathname &pathname) = 0;
172 // This moves a file from old_path to new_path, where "old_path" is a
173 // plain file. This ASSERTs and returns false if old_path points to a
174 // directory, and returns true if the function succeeds.
175 // If the new path is on a different volume than the old path, this function
176 // will attempt to copy and, if that succeeds, delete the old path.
177 virtual bool MoveFolder(const Pathname &old_path,
178 const Pathname &new_path) = 0;
180 // This moves a directory from old_path to new_path, where "old_path" is a
181 // directory. This ASSERTs and returns false if old_path points to a plain
182 // file, and returns true if the function succeeds.
183 // If the new path is on a different volume, this function will attempt to
184 // copy and if that succeeds, delete the old path.
185 virtual bool MoveFile(const Pathname &old_path, const Pathname &new_path) = 0;
187 // This attempts to move whatever is located at old_path to new_path,
188 // be it a file or folder.
189 bool MoveFileOrFolder(const Pathname &old_path, const Pathname &new_path) {
190 if (IsFile(old_path)) {
191 return MoveFile(old_path, new_path);
193 return MoveFolder(old_path, new_path);
197 // This copies a file from old_path to new_path. This method ASSERTs and
198 // returns false if old_path is a folder, and returns true if the copy
200 virtual bool CopyFile(const Pathname &old_path, const Pathname &new_path) = 0;
202 // This copies a folder from old_path to new_path.
203 bool CopyFolder(const Pathname &old_path, const Pathname &new_path);
205 bool CopyFileOrFolder(const Pathname &old_path, const Pathname &new_path) {
206 if (IsFile(old_path))
207 return CopyFile(old_path, new_path);
209 return CopyFolder(old_path, new_path);
212 // Returns true if pathname refers to a directory
213 virtual bool IsFolder(const Pathname& pathname) = 0;
215 // Returns true if pathname refers to a file
216 virtual bool IsFile(const Pathname& pathname) = 0;
218 // Returns true if pathname refers to no filesystem object, every parent
219 // directory either exists, or is also absent.
220 virtual bool IsAbsent(const Pathname& pathname) = 0;
222 // Returns true if pathname represents a temporary location on the system.
223 virtual bool IsTemporaryPath(const Pathname& pathname) = 0;
225 // A folder appropriate for storing temporary files (Contents are
226 // automatically deleted when the program exits)
227 virtual bool GetTemporaryFolder(Pathname &path, bool create,
228 const std::string *append) = 0;
230 virtual std::string TempFilename(const Pathname &dir,
231 const std::string &prefix) = 0;
233 // Determines the size of the file indicated by path.
234 virtual bool GetFileSize(const Pathname& path, size_t* size) = 0;
236 // Determines a timestamp associated with the file indicated by path.
237 virtual bool GetFileTime(const Pathname& path, FileTimeType which,
240 // Returns the path to the running application.
241 // Note: This is not guaranteed to work on all platforms. Be aware of the
242 // limitations before using it, and robustly handle failure.
243 virtual bool GetAppPathname(Pathname* path) = 0;
245 // Get a folder that is unique to the current application, which is suitable
246 // for sharing data between executions of the app. If the per_user arg is
247 // true, the folder is also specific to the current user.
248 virtual bool GetAppDataFolder(Pathname* path, bool per_user) = 0;
250 // Get a temporary folder that is unique to the current user and application.
251 // TODO: Re-evaluate the goals of this function. We probably just need any
252 // directory that won't collide with another existing directory, and which
253 // will be cleaned up when the program exits.
254 virtual bool GetAppTempFolder(Pathname* path) = 0;
256 // Delete the contents of the folder returned by GetAppTempFolder
257 bool CleanAppTempFolder();
259 virtual bool GetDiskFreeSpace(const Pathname& path, int64 *freebytes) = 0;
261 // Returns the absolute path of the current directory.
262 virtual Pathname GetCurrentDirectory() = 0;
264 // Note: These might go into some shared config section later, but they're
265 // used by some methods in this interface, so we're leaving them here for now.
266 void SetOrganizationName(const std::string& organization) {
267 organization_name_ = organization;
269 void GetOrganizationName(std::string* organization) {
270 ASSERT(NULL != organization);
271 *organization = organization_name_;
273 void SetApplicationName(const std::string& application) {
274 application_name_ = application;
276 void GetApplicationName(std::string* application) {
277 ASSERT(NULL != application);
278 *application = application_name_;
282 std::string organization_name_;
283 std::string application_name_;
288 static FilesystemInterface *default_filesystem() {
289 ASSERT(default_filesystem_ != NULL);
290 return default_filesystem_;
293 static void set_default_filesystem(FilesystemInterface *filesystem) {
294 default_filesystem_ = filesystem;
297 static FilesystemInterface *swap_default_filesystem(
298 FilesystemInterface *filesystem) {
299 FilesystemInterface *cur = default_filesystem_;
300 default_filesystem_ = filesystem;
304 static DirectoryIterator *IterateDirectory() {
305 return EnsureDefaultFilesystem()->IterateDirectory();
308 static bool CreateFolder(const Pathname &pathname) {
309 return EnsureDefaultFilesystem()->CreateFolder(pathname);
312 static FileStream *OpenFile(const Pathname &filename,
313 const std::string &mode) {
314 return EnsureDefaultFilesystem()->OpenFile(filename, mode);
317 static bool CreatePrivateFile(const Pathname &filename) {
318 return EnsureDefaultFilesystem()->CreatePrivateFile(filename);
321 static bool DeleteFile(const Pathname &filename) {
322 return EnsureDefaultFilesystem()->DeleteFile(filename);
325 static bool DeleteEmptyFolder(const Pathname &folder) {
326 return EnsureDefaultFilesystem()->DeleteEmptyFolder(folder);
329 static bool DeleteFolderContents(const Pathname &folder) {
330 return EnsureDefaultFilesystem()->DeleteFolderContents(folder);
333 static bool DeleteFolderAndContents(const Pathname &folder) {
334 return EnsureDefaultFilesystem()->DeleteFolderAndContents(folder);
337 static bool MoveFolder(const Pathname &old_path, const Pathname &new_path) {
338 return EnsureDefaultFilesystem()->MoveFolder(old_path, new_path);
341 static bool MoveFile(const Pathname &old_path, const Pathname &new_path) {
342 return EnsureDefaultFilesystem()->MoveFile(old_path, new_path);
345 static bool CopyFolder(const Pathname &old_path, const Pathname &new_path) {
346 return EnsureDefaultFilesystem()->CopyFolder(old_path, new_path);
349 static bool CopyFile(const Pathname &old_path, const Pathname &new_path) {
350 return EnsureDefaultFilesystem()->CopyFile(old_path, new_path);
353 static bool IsFolder(const Pathname& pathname) {
354 return EnsureDefaultFilesystem()->IsFolder(pathname);
357 static bool IsFile(const Pathname &pathname) {
358 return EnsureDefaultFilesystem()->IsFile(pathname);
361 static bool IsAbsent(const Pathname &pathname) {
362 return EnsureDefaultFilesystem()->IsAbsent(pathname);
365 static bool IsTemporaryPath(const Pathname& pathname) {
366 return EnsureDefaultFilesystem()->IsTemporaryPath(pathname);
369 static bool GetTemporaryFolder(Pathname &path, bool create,
370 const std::string *append) {
371 return EnsureDefaultFilesystem()->GetTemporaryFolder(path, create, append);
374 static std::string TempFilename(const Pathname &dir,
375 const std::string &prefix) {
376 return EnsureDefaultFilesystem()->TempFilename(dir, prefix);
379 static bool GetFileSize(const Pathname& path, size_t* size) {
380 return EnsureDefaultFilesystem()->GetFileSize(path, size);
383 static bool GetFileTime(const Pathname& path, FileTimeType which,
385 return EnsureDefaultFilesystem()->GetFileTime(path, which, time);
388 static bool GetAppPathname(Pathname* path) {
389 return EnsureDefaultFilesystem()->GetAppPathname(path);
392 static bool GetAppDataFolder(Pathname* path, bool per_user) {
393 return EnsureDefaultFilesystem()->GetAppDataFolder(path, per_user);
396 static bool GetAppTempFolder(Pathname* path) {
397 return EnsureDefaultFilesystem()->GetAppTempFolder(path);
400 static bool CleanAppTempFolder() {
401 return EnsureDefaultFilesystem()->CleanAppTempFolder();
404 static bool GetDiskFreeSpace(const Pathname& path, int64 *freebytes) {
405 return EnsureDefaultFilesystem()->GetDiskFreeSpace(path, freebytes);
408 // Definition has to be in the .cc file due to returning forward-declared
409 // Pathname by value.
410 static Pathname GetCurrentDirectory();
412 static void SetOrganizationName(const std::string& organization) {
413 EnsureDefaultFilesystem()->SetOrganizationName(organization);
416 static void GetOrganizationName(std::string* organization) {
417 EnsureDefaultFilesystem()->GetOrganizationName(organization);
420 static void SetApplicationName(const std::string& application) {
421 EnsureDefaultFilesystem()->SetApplicationName(application);
424 static void GetApplicationName(std::string* application) {
425 EnsureDefaultFilesystem()->GetApplicationName(application);
429 static FilesystemInterface* default_filesystem_;
431 static FilesystemInterface *EnsureDefaultFilesystem();
432 DISALLOW_IMPLICIT_CONSTRUCTORS(Filesystem);
435 class FilesystemScope{
437 explicit FilesystemScope(FilesystemInterface *new_fs) {
438 old_fs_ = Filesystem::swap_default_filesystem(new_fs);
441 Filesystem::set_default_filesystem(old_fs_);
444 FilesystemInterface* old_fs_;
445 DISALLOW_IMPLICIT_CONSTRUCTORS(FilesystemScope);
448 // Generates a unique filename based on the input path. If no path component
449 // is specified, it uses the temporary directory. If a filename is provided,
450 // up to 100 variations of form basename-N.extension are tried. When
451 // create_empty is true, an empty file of this name is created (which
452 // decreases the chance of a temporary filename collision with another
454 bool CreateUniqueFile(Pathname& path, bool create_empty);
456 // Taken from Chromium's base/platform_file.h.
457 // Don't use ClosePlatformFile to close a file opened with FdopenPlatformFile.
458 // Use fclose instead.
459 // TODO(grunell): Remove when Chromium has started to use AEC in each source.
460 // http://crbug.com/264611.
462 typedef HANDLE PlatformFile;
463 const PlatformFile kInvalidPlatformFileValue = INVALID_HANDLE_VALUE;
465 typedef int PlatformFile;
466 const PlatformFile kInvalidPlatformFileValue = -1;
468 #error Unsupported platform
471 FILE* FdopenPlatformFileForWriting(PlatformFile file);
472 bool ClosePlatformFile(PlatformFile file);
474 } // namespace talk_base
476 #endif // TALK_BASE_FILEUTILS_H_