Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / base / fileutils.h
1 /*
2  * libjingle
3  * Copyright 2004--2006, Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
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.
15  *
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.
26  */
27
28 #ifndef TALK_BASE_FILEUTILS_H_
29 #define TALK_BASE_FILEUTILS_H_
30
31 #include <string>
32
33 #ifdef WIN32
34 #include "talk/base/win32.h"
35 #else
36 #include <dirent.h>
37 #include <stdio.h>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40 #include <unistd.h>
41 #endif
42
43 #include "talk/base/basictypes.h"
44 #include "talk/base/common.h"
45 #include "talk/base/scoped_ptr.h"
46
47 namespace talk_base {
48
49 class FileStream;
50 class Pathname;
51
52 //////////////////////////
53 // Directory Iterator   //
54 //////////////////////////
55
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.
59
60 class DirectoryIterator {
61   friend class Filesystem;
62  public:
63   // Constructor
64   DirectoryIterator();
65   // Destructor
66   virtual ~DirectoryIterator();
67
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);
73
74   // Advances to the next file
75   // returns true if there were more files in the directory.
76   virtual bool Next();
77
78   // returns true if the file currently pointed to is a directory
79   virtual bool IsDirectory() const;
80
81   // returns the name of the file currently pointed to
82   virtual std::string Name() const;
83
84   // returns the size of the file currently pointed to
85   virtual size_t FileSize() const;
86
87   // returns the last modified time of the file currently pointed to
88   virtual time_t FileModifyTime() const;
89
90   // checks whether current file is a special directory file "." or ".."
91   bool IsDots() const {
92     std::string filename(Name());
93     return (filename.compare(".") == 0) || (filename.compare("..") == 0);
94   }
95
96  private:
97   std::string directory_;
98 #ifdef WIN32
99   WIN32_FIND_DATA data_;
100   HANDLE handle_;
101 #else
102   DIR *dir_;
103   struct dirent *dirent_;
104   struct stat stat_;
105 #endif
106 };
107
108 enum FileTimeType { FTT_CREATED, FTT_MODIFIED, FTT_ACCESSED };
109
110 class FilesystemInterface {
111  public:
112   virtual ~FilesystemInterface() {}
113
114   // Returns a DirectoryIterator for a given pathname.
115   // TODO: Do fancy abstracted stuff
116   virtual DirectoryIterator *IterateDirectory() {
117     return new DirectoryIterator();
118   }
119
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
123   // FileStream::Open
124   virtual FileStream *OpenFile(const Pathname &filename,
125                                const std::string &mode) = 0;
126
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;
135
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;
140
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
144   // not be deleted.
145   virtual bool DeleteEmptyFolder(const Pathname &folder) = 0;
146
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);
151
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);
156   }
157
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) {
162     if (IsFolder(path))
163       return DeleteFolderAndContents(path);
164     else
165       return DeleteFile(path);
166   }
167
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;
171
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;
179
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;
186
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);
192     } else {
193       return MoveFolder(old_path, new_path);
194     }
195   }
196
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
199   // succeeds.
200   virtual bool CopyFile(const Pathname &old_path, const Pathname &new_path) = 0;
201
202   // This copies a folder from old_path to new_path.
203   bool CopyFolder(const Pathname &old_path, const Pathname &new_path);
204
205   bool CopyFileOrFolder(const Pathname &old_path, const Pathname &new_path) {
206     if (IsFile(old_path))
207       return CopyFile(old_path, new_path);
208     else
209       return CopyFolder(old_path, new_path);
210   }
211
212   // Returns true if pathname refers to a directory
213   virtual bool IsFolder(const Pathname& pathname) = 0;
214
215   // Returns true if pathname refers to a file
216   virtual bool IsFile(const Pathname& pathname) = 0;
217
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;
221
222   // Returns true if pathname represents a temporary location on the system.
223   virtual bool IsTemporaryPath(const Pathname& pathname) = 0;
224
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;
229
230   virtual std::string TempFilename(const Pathname &dir,
231                                    const std::string &prefix) = 0;
232
233   // Determines the size of the file indicated by path.
234   virtual bool GetFileSize(const Pathname& path, size_t* size) = 0;
235
236   // Determines a timestamp associated with the file indicated by path.
237   virtual bool GetFileTime(const Pathname& path, FileTimeType which,
238                            time_t* time) = 0;
239
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;
244
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;
249
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;
255
256   // Delete the contents of the folder returned by GetAppTempFolder
257   bool CleanAppTempFolder();
258
259   virtual bool GetDiskFreeSpace(const Pathname& path, int64 *freebytes) = 0;
260
261   // Returns the absolute path of the current directory.
262   virtual Pathname GetCurrentDirectory() = 0;
263
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;
268   }
269   void GetOrganizationName(std::string* organization) {
270     ASSERT(NULL != organization);
271     *organization = organization_name_;
272   }
273   void SetApplicationName(const std::string& application) {
274     application_name_ = application;
275   }
276   void GetApplicationName(std::string* application) {
277     ASSERT(NULL != application);
278     *application = application_name_;
279   }
280
281  protected:
282   std::string organization_name_;
283   std::string application_name_;
284 };
285
286 class Filesystem {
287  public:
288   static FilesystemInterface *default_filesystem() {
289     ASSERT(default_filesystem_ != NULL);
290     return default_filesystem_;
291   }
292
293   static void set_default_filesystem(FilesystemInterface *filesystem) {
294     default_filesystem_ = filesystem;
295   }
296
297   static FilesystemInterface *swap_default_filesystem(
298       FilesystemInterface *filesystem) {
299     FilesystemInterface *cur = default_filesystem_;
300     default_filesystem_ = filesystem;
301     return cur;
302   }
303
304   static DirectoryIterator *IterateDirectory() {
305     return EnsureDefaultFilesystem()->IterateDirectory();
306   }
307
308   static bool CreateFolder(const Pathname &pathname) {
309     return EnsureDefaultFilesystem()->CreateFolder(pathname);
310   }
311
312   static FileStream *OpenFile(const Pathname &filename,
313                               const std::string &mode) {
314     return EnsureDefaultFilesystem()->OpenFile(filename, mode);
315   }
316
317   static bool CreatePrivateFile(const Pathname &filename) {
318     return EnsureDefaultFilesystem()->CreatePrivateFile(filename);
319   }
320
321   static bool DeleteFile(const Pathname &filename) {
322     return EnsureDefaultFilesystem()->DeleteFile(filename);
323   }
324
325   static bool DeleteEmptyFolder(const Pathname &folder) {
326     return EnsureDefaultFilesystem()->DeleteEmptyFolder(folder);
327   }
328
329   static bool DeleteFolderContents(const Pathname &folder) {
330     return EnsureDefaultFilesystem()->DeleteFolderContents(folder);
331   }
332
333   static bool DeleteFolderAndContents(const Pathname &folder) {
334     return EnsureDefaultFilesystem()->DeleteFolderAndContents(folder);
335   }
336
337   static bool MoveFolder(const Pathname &old_path, const Pathname &new_path) {
338     return EnsureDefaultFilesystem()->MoveFolder(old_path, new_path);
339   }
340
341   static bool MoveFile(const Pathname &old_path, const Pathname &new_path) {
342     return EnsureDefaultFilesystem()->MoveFile(old_path, new_path);
343   }
344
345   static bool CopyFolder(const Pathname &old_path, const Pathname &new_path) {
346     return EnsureDefaultFilesystem()->CopyFolder(old_path, new_path);
347   }
348
349   static bool CopyFile(const Pathname &old_path, const Pathname &new_path) {
350     return EnsureDefaultFilesystem()->CopyFile(old_path, new_path);
351   }
352
353   static bool IsFolder(const Pathname& pathname) {
354     return EnsureDefaultFilesystem()->IsFolder(pathname);
355   }
356
357   static bool IsFile(const Pathname &pathname) {
358     return EnsureDefaultFilesystem()->IsFile(pathname);
359   }
360
361   static bool IsAbsent(const Pathname &pathname) {
362     return EnsureDefaultFilesystem()->IsAbsent(pathname);
363   }
364
365   static bool IsTemporaryPath(const Pathname& pathname) {
366     return EnsureDefaultFilesystem()->IsTemporaryPath(pathname);
367   }
368
369   static bool GetTemporaryFolder(Pathname &path, bool create,
370                                  const std::string *append) {
371     return EnsureDefaultFilesystem()->GetTemporaryFolder(path, create, append);
372   }
373
374   static std::string TempFilename(const Pathname &dir,
375                                   const std::string &prefix) {
376     return EnsureDefaultFilesystem()->TempFilename(dir, prefix);
377   }
378
379   static bool GetFileSize(const Pathname& path, size_t* size) {
380     return EnsureDefaultFilesystem()->GetFileSize(path, size);
381   }
382
383   static bool GetFileTime(const Pathname& path, FileTimeType which,
384                           time_t* time) {
385     return EnsureDefaultFilesystem()->GetFileTime(path, which, time);
386   }
387
388   static bool GetAppPathname(Pathname* path) {
389     return EnsureDefaultFilesystem()->GetAppPathname(path);
390   }
391
392   static bool GetAppDataFolder(Pathname* path, bool per_user) {
393     return EnsureDefaultFilesystem()->GetAppDataFolder(path, per_user);
394   }
395
396   static bool GetAppTempFolder(Pathname* path) {
397     return EnsureDefaultFilesystem()->GetAppTempFolder(path);
398   }
399
400   static bool CleanAppTempFolder() {
401     return EnsureDefaultFilesystem()->CleanAppTempFolder();
402   }
403
404   static bool GetDiskFreeSpace(const Pathname& path, int64 *freebytes) {
405     return EnsureDefaultFilesystem()->GetDiskFreeSpace(path, freebytes);
406   }
407
408   // Definition has to be in the .cc file due to returning forward-declared
409   // Pathname by value.
410   static Pathname GetCurrentDirectory();
411
412   static void SetOrganizationName(const std::string& organization) {
413     EnsureDefaultFilesystem()->SetOrganizationName(organization);
414   }
415
416   static void GetOrganizationName(std::string* organization) {
417     EnsureDefaultFilesystem()->GetOrganizationName(organization);
418   }
419
420   static void SetApplicationName(const std::string& application) {
421     EnsureDefaultFilesystem()->SetApplicationName(application);
422   }
423
424   static void GetApplicationName(std::string* application) {
425     EnsureDefaultFilesystem()->GetApplicationName(application);
426   }
427
428  private:
429   static FilesystemInterface* default_filesystem_;
430
431   static FilesystemInterface *EnsureDefaultFilesystem();
432   DISALLOW_IMPLICIT_CONSTRUCTORS(Filesystem);
433 };
434
435 class FilesystemScope{
436  public:
437   explicit FilesystemScope(FilesystemInterface *new_fs) {
438     old_fs_ = Filesystem::swap_default_filesystem(new_fs);
439   }
440   ~FilesystemScope() {
441     Filesystem::set_default_filesystem(old_fs_);
442   }
443  private:
444   FilesystemInterface* old_fs_;
445   DISALLOW_IMPLICIT_CONSTRUCTORS(FilesystemScope);
446 };
447
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
453 // process).
454 bool CreateUniqueFile(Pathname& path, bool create_empty);
455
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.
461 #if defined(WIN32)
462 typedef HANDLE PlatformFile;
463 const PlatformFile kInvalidPlatformFileValue = INVALID_HANDLE_VALUE;
464 #elif defined(POSIX)
465 typedef int PlatformFile;
466 const PlatformFile kInvalidPlatformFileValue = -1;
467 #else
468 #error Unsupported platform
469 #endif
470
471 FILE* FdopenPlatformFileForWriting(PlatformFile file);
472 bool ClosePlatformFile(PlatformFile file);
473
474 }  // namespace talk_base
475
476 #endif  // TALK_BASE_FILEUTILS_H_