 67ee6b9a62
			
		
	
	67ee6b9a62
	
	
	
		
			
			Review URL: https://webrtc-codereview.appspot.com/7909004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5475 4adac7df-926f-26a2-2b94-8c16560cd09d
		
			
				
	
	
		
			477 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			477 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * libjingle
 | |
|  * Copyright 2004--2006, Google Inc.
 | |
|  *
 | |
|  * Redistribution and use in source and binary forms, with or without
 | |
|  * modification, are permitted provided that the following conditions are met:
 | |
|  *
 | |
|  *  1. Redistributions of source code must retain the above copyright notice,
 | |
|  *     this list of conditions and the following disclaimer.
 | |
|  *  2. Redistributions in binary form must reproduce the above copyright notice,
 | |
|  *     this list of conditions and the following disclaimer in the documentation
 | |
|  *     and/or other materials provided with the distribution.
 | |
|  *  3. The name of the author may not be used to endorse or promote products
 | |
|  *     derived from this software without specific prior written permission.
 | |
|  *
 | |
|  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 | |
|  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | |
|  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 | |
|  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
|  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 | |
|  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 | |
|  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 | |
|  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 | |
|  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 | |
|  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
|  */
 | |
| 
 | |
| #ifndef TALK_BASE_FILEUTILS_H_
 | |
| #define TALK_BASE_FILEUTILS_H_
 | |
| 
 | |
| #include <string>
 | |
| 
 | |
| #ifdef WIN32
 | |
| #include "talk/base/win32.h"
 | |
| #else
 | |
| #include <dirent.h>
 | |
| #include <stdio.h>
 | |
| #include <sys/stat.h>
 | |
| #include <sys/types.h>
 | |
| #include <unistd.h>
 | |
| #endif
 | |
| 
 | |
| #include "talk/base/basictypes.h"
 | |
| #include "talk/base/common.h"
 | |
| #include "talk/base/scoped_ptr.h"
 | |
| 
 | |
| namespace talk_base {
 | |
| 
 | |
| class FileStream;
 | |
| class Pathname;
 | |
| 
 | |
| //////////////////////////
 | |
| // Directory Iterator   //
 | |
| //////////////////////////
 | |
| 
 | |
| // A DirectoryIterator is created with a given directory. It originally points
 | |
| // to the first file in the directory, and can be advanecd with Next(). This
 | |
| // allows you to get information about each file.
 | |
| 
 | |
| class DirectoryIterator {
 | |
|   friend class Filesystem;
 | |
|  public:
 | |
|   // Constructor
 | |
|   DirectoryIterator();
 | |
|   // Destructor
 | |
|   virtual ~DirectoryIterator();
 | |
| 
 | |
|   // Starts traversing a directory
 | |
|   // dir is the directory to traverse
 | |
|   // returns true if the directory exists and is valid
 | |
|   // The iterator will point to the first entry in the directory
 | |
|   virtual bool Iterate(const Pathname &path);
 | |
| 
 | |
|   // Advances to the next file
 | |
|   // returns true if there were more files in the directory.
 | |
|   virtual bool Next();
 | |
| 
 | |
|   // returns true if the file currently pointed to is a directory
 | |
|   virtual bool IsDirectory() const;
 | |
| 
 | |
|   // returns the name of the file currently pointed to
 | |
|   virtual std::string Name() const;
 | |
| 
 | |
|   // returns the size of the file currently pointed to
 | |
|   virtual size_t FileSize() const;
 | |
| 
 | |
|   // returns the last modified time of the file currently pointed to
 | |
|   virtual time_t FileModifyTime() const;
 | |
| 
 | |
|   // checks whether current file is a special directory file "." or ".."
 | |
|   bool IsDots() const {
 | |
|     std::string filename(Name());
 | |
|     return (filename.compare(".") == 0) || (filename.compare("..") == 0);
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   std::string directory_;
 | |
| #ifdef WIN32
 | |
|   WIN32_FIND_DATA data_;
 | |
|   HANDLE handle_;
 | |
| #else
 | |
|   DIR *dir_;
 | |
|   struct dirent *dirent_;
 | |
|   struct stat stat_;
 | |
| #endif
 | |
| };
 | |
| 
 | |
| enum FileTimeType { FTT_CREATED, FTT_MODIFIED, FTT_ACCESSED };
 | |
| 
 | |
| class FilesystemInterface {
 | |
|  public:
 | |
|   virtual ~FilesystemInterface() {}
 | |
| 
 | |
|   // Returns a DirectoryIterator for a given pathname.
 | |
|   // TODO: Do fancy abstracted stuff
 | |
|   virtual DirectoryIterator *IterateDirectory() {
 | |
|     return new DirectoryIterator();
 | |
|   }
 | |
| 
 | |
|   // Opens a file. Returns an open StreamInterface if function succeeds.
 | |
|   // Otherwise, returns NULL.
 | |
|   // TODO: Add an error param to indicate failure reason, similar to
 | |
|   // FileStream::Open
 | |
|   virtual FileStream *OpenFile(const Pathname &filename,
 | |
|                                const std::string &mode) = 0;
 | |
| 
 | |
|   // Atomically creates an empty file accessible only to the current user if one
 | |
|   // does not already exist at the given path, otherwise fails. This is the only
 | |
|   // secure way to create a file in a shared temp directory (e.g., C:\Temp on
 | |
|   // Windows or /tmp on Linux).
 | |
|   // Note that if it is essential that a file be successfully created then the
 | |
|   // app must generate random names and retry on failure, or else it will be
 | |
|   // vulnerable to a trivial DoS.
 | |
|   virtual bool CreatePrivateFile(const Pathname &filename) = 0;
 | |
| 
 | |
|   // This will attempt to delete the path located at filename.
 | |
|   // It ASSERTS and returns false if the path points to a folder or a
 | |
|   // non-existent file.
 | |
|   virtual bool DeleteFile(const Pathname &filename) = 0;
 | |
| 
 | |
|   // This will attempt to delete the empty folder located at 'folder'
 | |
|   // It ASSERTS and returns false if the path points to a file or a non-existent
 | |
|   // folder. It fails normally if the folder is not empty or can otherwise
 | |
|   // not be deleted.
 | |
|   virtual bool DeleteEmptyFolder(const Pathname &folder) = 0;
 | |
| 
 | |
|   // This will call IterateDirectory, to get a directory iterator, and then
 | |
|   // call DeleteFolderAndContents and DeleteFile on every path contained in this
 | |
|   // folder. If the folder is empty, this returns true.
 | |
|   virtual bool DeleteFolderContents(const Pathname &folder);
 | |
| 
 | |
|   // This deletes the contents of a folder, recursively, and then deletes
 | |
|   // the folder itself.
 | |
|   virtual bool DeleteFolderAndContents(const Pathname &folder) {
 | |
|     return DeleteFolderContents(folder) && DeleteEmptyFolder(folder);
 | |
|   }
 | |
| 
 | |
|   // This will delete whatever is located at path, be it a file or a folder.
 | |
|   // If it is a folder, it will delete it recursively by calling
 | |
|   // DeleteFolderAndContents
 | |
|   bool DeleteFileOrFolder(const Pathname &path) {
 | |
|     if (IsFolder(path))
 | |
|       return DeleteFolderAndContents(path);
 | |
|     else
 | |
|       return DeleteFile(path);
 | |
|   }
 | |
| 
 | |
|   // Creates a directory. This will call itself recursively to create /foo/bar
 | |
|   // even if /foo does not exist. Returns true if the function succeeds.
 | |
|   virtual bool CreateFolder(const Pathname &pathname) = 0;
 | |
| 
 | |
|   // This moves a file from old_path to new_path, where "old_path" is a
 | |
|   // plain file. This ASSERTs and returns false if old_path points to a
 | |
|   // directory, and returns true if the function succeeds.
 | |
|   // If the new path is on a different volume than the old path, this function
 | |
|   // will attempt to copy and, if that succeeds, delete the old path.
 | |
|   virtual bool MoveFolder(const Pathname &old_path,
 | |
|                           const Pathname &new_path) = 0;
 | |
| 
 | |
|   // This moves a directory from old_path to new_path, where "old_path" is a
 | |
|   // directory. This ASSERTs and returns false if old_path points to a plain
 | |
|   // file, and returns true if the function succeeds.
 | |
|   // If the new path is on a different volume, this function will attempt to
 | |
|   // copy and if that succeeds, delete the old path.
 | |
|   virtual bool MoveFile(const Pathname &old_path, const Pathname &new_path) = 0;
 | |
| 
 | |
|   // This attempts to move whatever is located at old_path to new_path,
 | |
|   // be it a file or folder.
 | |
|   bool MoveFileOrFolder(const Pathname &old_path, const Pathname &new_path) {
 | |
|     if (IsFile(old_path)) {
 | |
|       return MoveFile(old_path, new_path);
 | |
|     } else {
 | |
|       return MoveFolder(old_path, new_path);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // This copies a file from old_path to new_path. This method ASSERTs and
 | |
|   // returns false if old_path is a folder, and returns true if the copy
 | |
|   // succeeds.
 | |
|   virtual bool CopyFile(const Pathname &old_path, const Pathname &new_path) = 0;
 | |
| 
 | |
|   // This copies a folder from old_path to new_path.
 | |
|   bool CopyFolder(const Pathname &old_path, const Pathname &new_path);
 | |
| 
 | |
|   bool CopyFileOrFolder(const Pathname &old_path, const Pathname &new_path) {
 | |
|     if (IsFile(old_path))
 | |
|       return CopyFile(old_path, new_path);
 | |
|     else
 | |
|       return CopyFolder(old_path, new_path);
 | |
|   }
 | |
| 
 | |
|   // Returns true if pathname refers to a directory
 | |
|   virtual bool IsFolder(const Pathname& pathname) = 0;
 | |
| 
 | |
|   // Returns true if pathname refers to a file
 | |
|   virtual bool IsFile(const Pathname& pathname) = 0;
 | |
| 
 | |
|   // Returns true if pathname refers to no filesystem object, every parent
 | |
|   // directory either exists, or is also absent.
 | |
|   virtual bool IsAbsent(const Pathname& pathname) = 0;
 | |
| 
 | |
|   // Returns true if pathname represents a temporary location on the system.
 | |
|   virtual bool IsTemporaryPath(const Pathname& pathname) = 0;
 | |
| 
 | |
|   // A folder appropriate for storing temporary files (Contents are
 | |
|   // automatically deleted when the program exits)
 | |
|   virtual bool GetTemporaryFolder(Pathname &path, bool create,
 | |
|                                   const std::string *append) = 0;
 | |
| 
 | |
|   virtual std::string TempFilename(const Pathname &dir,
 | |
|                                    const std::string &prefix) = 0;
 | |
| 
 | |
|   // Determines the size of the file indicated by path.
 | |
|   virtual bool GetFileSize(const Pathname& path, size_t* size) = 0;
 | |
| 
 | |
|   // Determines a timestamp associated with the file indicated by path.
 | |
|   virtual bool GetFileTime(const Pathname& path, FileTimeType which,
 | |
|                            time_t* time) = 0;
 | |
| 
 | |
|   // Returns the path to the running application.
 | |
|   // Note: This is not guaranteed to work on all platforms.  Be aware of the
 | |
|   // limitations before using it, and robustly handle failure.
 | |
|   virtual bool GetAppPathname(Pathname* path) = 0;
 | |
| 
 | |
|   // Get a folder that is unique to the current application, which is suitable
 | |
|   // for sharing data between executions of the app.  If the per_user arg is
 | |
|   // true, the folder is also specific to the current user.
 | |
|   virtual bool GetAppDataFolder(Pathname* path, bool per_user) = 0;
 | |
| 
 | |
|   // Get a temporary folder that is unique to the current user and application.
 | |
|   // TODO: Re-evaluate the goals of this function.  We probably just need any
 | |
|   // directory that won't collide with another existing directory, and which
 | |
|   // will be cleaned up when the program exits.
 | |
|   virtual bool GetAppTempFolder(Pathname* path) = 0;
 | |
| 
 | |
|   // Delete the contents of the folder returned by GetAppTempFolder
 | |
|   bool CleanAppTempFolder();
 | |
| 
 | |
|   virtual bool GetDiskFreeSpace(const Pathname& path, int64 *freebytes) = 0;
 | |
| 
 | |
|   // Returns the absolute path of the current directory.
 | |
|   virtual Pathname GetCurrentDirectory() = 0;
 | |
| 
 | |
|   // Note: These might go into some shared config section later, but they're
 | |
|   // used by some methods in this interface, so we're leaving them here for now.
 | |
|   void SetOrganizationName(const std::string& organization) {
 | |
|     organization_name_ = organization;
 | |
|   }
 | |
|   void GetOrganizationName(std::string* organization) {
 | |
|     ASSERT(NULL != organization);
 | |
|     *organization = organization_name_;
 | |
|   }
 | |
|   void SetApplicationName(const std::string& application) {
 | |
|     application_name_ = application;
 | |
|   }
 | |
|   void GetApplicationName(std::string* application) {
 | |
|     ASSERT(NULL != application);
 | |
|     *application = application_name_;
 | |
|   }
 | |
| 
 | |
|  protected:
 | |
|   std::string organization_name_;
 | |
|   std::string application_name_;
 | |
| };
 | |
| 
 | |
| class Filesystem {
 | |
|  public:
 | |
|   static FilesystemInterface *default_filesystem() {
 | |
|     ASSERT(default_filesystem_ != NULL);
 | |
|     return default_filesystem_;
 | |
|   }
 | |
| 
 | |
|   static void set_default_filesystem(FilesystemInterface *filesystem) {
 | |
|     default_filesystem_ = filesystem;
 | |
|   }
 | |
| 
 | |
|   static FilesystemInterface *swap_default_filesystem(
 | |
|       FilesystemInterface *filesystem) {
 | |
|     FilesystemInterface *cur = default_filesystem_;
 | |
|     default_filesystem_ = filesystem;
 | |
|     return cur;
 | |
|   }
 | |
| 
 | |
|   static DirectoryIterator *IterateDirectory() {
 | |
|     return EnsureDefaultFilesystem()->IterateDirectory();
 | |
|   }
 | |
| 
 | |
|   static bool CreateFolder(const Pathname &pathname) {
 | |
|     return EnsureDefaultFilesystem()->CreateFolder(pathname);
 | |
|   }
 | |
| 
 | |
|   static FileStream *OpenFile(const Pathname &filename,
 | |
|                               const std::string &mode) {
 | |
|     return EnsureDefaultFilesystem()->OpenFile(filename, mode);
 | |
|   }
 | |
| 
 | |
|   static bool CreatePrivateFile(const Pathname &filename) {
 | |
|     return EnsureDefaultFilesystem()->CreatePrivateFile(filename);
 | |
|   }
 | |
| 
 | |
|   static bool DeleteFile(const Pathname &filename) {
 | |
|     return EnsureDefaultFilesystem()->DeleteFile(filename);
 | |
|   }
 | |
| 
 | |
|   static bool DeleteEmptyFolder(const Pathname &folder) {
 | |
|     return EnsureDefaultFilesystem()->DeleteEmptyFolder(folder);
 | |
|   }
 | |
| 
 | |
|   static bool DeleteFolderContents(const Pathname &folder) {
 | |
|     return EnsureDefaultFilesystem()->DeleteFolderContents(folder);
 | |
|   }
 | |
| 
 | |
|   static bool DeleteFolderAndContents(const Pathname &folder) {
 | |
|     return EnsureDefaultFilesystem()->DeleteFolderAndContents(folder);
 | |
|   }
 | |
| 
 | |
|   static bool MoveFolder(const Pathname &old_path, const Pathname &new_path) {
 | |
|     return EnsureDefaultFilesystem()->MoveFolder(old_path, new_path);
 | |
|   }
 | |
| 
 | |
|   static bool MoveFile(const Pathname &old_path, const Pathname &new_path) {
 | |
|     return EnsureDefaultFilesystem()->MoveFile(old_path, new_path);
 | |
|   }
 | |
| 
 | |
|   static bool CopyFolder(const Pathname &old_path, const Pathname &new_path) {
 | |
|     return EnsureDefaultFilesystem()->CopyFolder(old_path, new_path);
 | |
|   }
 | |
| 
 | |
|   static bool CopyFile(const Pathname &old_path, const Pathname &new_path) {
 | |
|     return EnsureDefaultFilesystem()->CopyFile(old_path, new_path);
 | |
|   }
 | |
| 
 | |
|   static bool IsFolder(const Pathname& pathname) {
 | |
|     return EnsureDefaultFilesystem()->IsFolder(pathname);
 | |
|   }
 | |
| 
 | |
|   static bool IsFile(const Pathname &pathname) {
 | |
|     return EnsureDefaultFilesystem()->IsFile(pathname);
 | |
|   }
 | |
| 
 | |
|   static bool IsAbsent(const Pathname &pathname) {
 | |
|     return EnsureDefaultFilesystem()->IsAbsent(pathname);
 | |
|   }
 | |
| 
 | |
|   static bool IsTemporaryPath(const Pathname& pathname) {
 | |
|     return EnsureDefaultFilesystem()->IsTemporaryPath(pathname);
 | |
|   }
 | |
| 
 | |
|   static bool GetTemporaryFolder(Pathname &path, bool create,
 | |
|                                  const std::string *append) {
 | |
|     return EnsureDefaultFilesystem()->GetTemporaryFolder(path, create, append);
 | |
|   }
 | |
| 
 | |
|   static std::string TempFilename(const Pathname &dir,
 | |
|                                   const std::string &prefix) {
 | |
|     return EnsureDefaultFilesystem()->TempFilename(dir, prefix);
 | |
|   }
 | |
| 
 | |
|   static bool GetFileSize(const Pathname& path, size_t* size) {
 | |
|     return EnsureDefaultFilesystem()->GetFileSize(path, size);
 | |
|   }
 | |
| 
 | |
|   static bool GetFileTime(const Pathname& path, FileTimeType which,
 | |
|                           time_t* time) {
 | |
|     return EnsureDefaultFilesystem()->GetFileTime(path, which, time);
 | |
|   }
 | |
| 
 | |
|   static bool GetAppPathname(Pathname* path) {
 | |
|     return EnsureDefaultFilesystem()->GetAppPathname(path);
 | |
|   }
 | |
| 
 | |
|   static bool GetAppDataFolder(Pathname* path, bool per_user) {
 | |
|     return EnsureDefaultFilesystem()->GetAppDataFolder(path, per_user);
 | |
|   }
 | |
| 
 | |
|   static bool GetAppTempFolder(Pathname* path) {
 | |
|     return EnsureDefaultFilesystem()->GetAppTempFolder(path);
 | |
|   }
 | |
| 
 | |
|   static bool CleanAppTempFolder() {
 | |
|     return EnsureDefaultFilesystem()->CleanAppTempFolder();
 | |
|   }
 | |
| 
 | |
|   static bool GetDiskFreeSpace(const Pathname& path, int64 *freebytes) {
 | |
|     return EnsureDefaultFilesystem()->GetDiskFreeSpace(path, freebytes);
 | |
|   }
 | |
| 
 | |
|   // Definition has to be in the .cc file due to returning forward-declared
 | |
|   // Pathname by value.
 | |
|   static Pathname GetCurrentDirectory();
 | |
| 
 | |
|   static void SetOrganizationName(const std::string& organization) {
 | |
|     EnsureDefaultFilesystem()->SetOrganizationName(organization);
 | |
|   }
 | |
| 
 | |
|   static void GetOrganizationName(std::string* organization) {
 | |
|     EnsureDefaultFilesystem()->GetOrganizationName(organization);
 | |
|   }
 | |
| 
 | |
|   static void SetApplicationName(const std::string& application) {
 | |
|     EnsureDefaultFilesystem()->SetApplicationName(application);
 | |
|   }
 | |
| 
 | |
|   static void GetApplicationName(std::string* application) {
 | |
|     EnsureDefaultFilesystem()->GetApplicationName(application);
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   static FilesystemInterface* default_filesystem_;
 | |
| 
 | |
|   static FilesystemInterface *EnsureDefaultFilesystem();
 | |
|   DISALLOW_IMPLICIT_CONSTRUCTORS(Filesystem);
 | |
| };
 | |
| 
 | |
| class FilesystemScope{
 | |
|  public:
 | |
|   explicit FilesystemScope(FilesystemInterface *new_fs) {
 | |
|     old_fs_ = Filesystem::swap_default_filesystem(new_fs);
 | |
|   }
 | |
|   ~FilesystemScope() {
 | |
|     Filesystem::set_default_filesystem(old_fs_);
 | |
|   }
 | |
|  private:
 | |
|   FilesystemInterface* old_fs_;
 | |
|   DISALLOW_IMPLICIT_CONSTRUCTORS(FilesystemScope);
 | |
| };
 | |
| 
 | |
| // Generates a unique filename based on the input path.  If no path component
 | |
| // is specified, it uses the temporary directory.  If a filename is provided,
 | |
| // up to 100 variations of form basename-N.extension are tried.  When
 | |
| // create_empty is true, an empty file of this name is created (which
 | |
| // decreases the chance of a temporary filename collision with another
 | |
| // process).
 | |
| bool CreateUniqueFile(Pathname& path, bool create_empty);
 | |
| 
 | |
| // Taken from Chromium's base/platform_file.h.
 | |
| // Don't use ClosePlatformFile to close a file opened with FdopenPlatformFile.
 | |
| // Use fclose instead.
 | |
| // TODO(grunell): Remove when Chromium has started to use AEC in each source.
 | |
| // http://crbug.com/264611.
 | |
| #if defined(WIN32)
 | |
| typedef HANDLE PlatformFile;
 | |
| const PlatformFile kInvalidPlatformFileValue = INVALID_HANDLE_VALUE;
 | |
| #elif defined(POSIX)
 | |
| typedef int PlatformFile;
 | |
| const PlatformFile kInvalidPlatformFileValue = -1;
 | |
| #else
 | |
| #error Unsupported platform
 | |
| #endif
 | |
| 
 | |
| FILE* FdopenPlatformFileForWriting(PlatformFile file);
 | |
| bool ClosePlatformFile(PlatformFile file);
 | |
| 
 | |
| }  // namespace talk_base
 | |
| 
 | |
| #endif  // TALK_BASE_FILEUTILS_H_
 |