Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / base / fileutils.cc
1 /*
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 #include <assert.h>
12
13 #if defined(WEBRTC_WIN)
14 // TODO(grunell): Remove io.h includes when Chromium has started
15 // to use AEC in each source. http://crbug.com/264611.
16 #include <io.h>
17 #include "webrtc/base/win32.h"
18 #endif
19
20 #include "webrtc/base/pathutils.h"
21 #include "webrtc/base/fileutils.h"
22 #include "webrtc/base/stringutils.h"
23 #include "webrtc/base/stream.h"
24
25 #if defined(WEBRTC_WIN)
26 #include "webrtc/base/win32filesystem.h"
27 #else
28 #include "webrtc/base/unixfilesystem.h"
29 #endif
30
31 #if !defined(WEBRTC_WIN)
32 #define MAX_PATH 260
33 #endif
34
35 namespace rtc {
36
37 //////////////////////////
38 // Directory Iterator   //
39 //////////////////////////
40
41 // A DirectoryIterator is created with a given directory. It originally points
42 // to the first file in the directory, and can be advanecd with Next(). This
43 // allows you to get information about each file.
44
45   // Constructor
46 DirectoryIterator::DirectoryIterator()
47 #ifdef WEBRTC_WIN
48     : handle_(INVALID_HANDLE_VALUE) {
49 #else
50     : dir_(NULL), dirent_(NULL) {
51 #endif
52 }
53
54   // Destructor
55 DirectoryIterator::~DirectoryIterator() {
56 #if defined(WEBRTC_WIN)
57   if (handle_ != INVALID_HANDLE_VALUE)
58     ::FindClose(handle_);
59 #else
60   if (dir_)
61     closedir(dir_);
62 #endif
63 }
64
65   // Starts traversing a directory.
66   // dir is the directory to traverse
67   // returns true if the directory exists and is valid
68 bool DirectoryIterator::Iterate(const Pathname &dir) {
69   directory_ = dir.pathname();
70 #if defined(WEBRTC_WIN)
71   if (handle_ != INVALID_HANDLE_VALUE)
72     ::FindClose(handle_);
73   std::string d = dir.pathname() + '*';
74   handle_ = ::FindFirstFile(ToUtf16(d).c_str(), &data_);
75   if (handle_ == INVALID_HANDLE_VALUE)
76     return false;
77 #else
78   if (dir_ != NULL)
79     closedir(dir_);
80   dir_ = ::opendir(directory_.c_str());
81   if (dir_ == NULL)
82     return false;
83   dirent_ = readdir(dir_);
84   if (dirent_ == NULL)
85     return false;
86
87   if (::stat(std::string(directory_ + Name()).c_str(), &stat_) != 0)
88     return false;
89 #endif
90   return true;
91 }
92
93   // Advances to the next file
94   // returns true if there were more files in the directory.
95 bool DirectoryIterator::Next() {
96 #if defined(WEBRTC_WIN)
97   return ::FindNextFile(handle_, &data_) == TRUE;
98 #else
99   dirent_ = ::readdir(dir_);
100   if (dirent_ == NULL)
101     return false;
102
103   return ::stat(std::string(directory_ + Name()).c_str(), &stat_) == 0;
104 #endif
105 }
106
107   // returns true if the file currently pointed to is a directory
108 bool DirectoryIterator::IsDirectory() const {
109 #if defined(WEBRTC_WIN)
110   return (data_.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FALSE;
111 #else
112   return S_ISDIR(stat_.st_mode);
113 #endif
114 }
115
116   // returns the name of the file currently pointed to
117 std::string DirectoryIterator::Name() const {
118 #if defined(WEBRTC_WIN)
119   return ToUtf8(data_.cFileName);
120 #else
121   assert(dirent_ != NULL);
122   return dirent_->d_name;
123 #endif
124 }
125
126   // returns the size of the file currently pointed to
127 size_t DirectoryIterator::FileSize() const {
128 #if !defined(WEBRTC_WIN)
129   return stat_.st_size;
130 #else
131   return data_.nFileSizeLow;
132 #endif
133 }
134
135 bool DirectoryIterator::OlderThan(int seconds) const {
136   time_t file_modify_time;
137 #if defined(WEBRTC_WIN)
138   FileTimeToUnixTime(data_.ftLastWriteTime, &file_modify_time);
139 #else
140   file_modify_time = stat_.st_mtime;
141 #endif
142   return TimeDiff(time(NULL), file_modify_time) >= seconds;
143 }
144
145 FilesystemInterface* Filesystem::default_filesystem_ = NULL;
146
147 FilesystemInterface *Filesystem::EnsureDefaultFilesystem() {
148   if (!default_filesystem_) {
149 #if defined(WEBRTC_WIN)
150     default_filesystem_ = new Win32Filesystem();
151 #else
152     default_filesystem_ = new UnixFilesystem();
153 #endif
154   }
155   return default_filesystem_;
156 }
157
158 bool FilesystemInterface::CopyFolder(const Pathname &old_path,
159                                      const Pathname &new_path) {
160   bool success = true;
161   VERIFY(IsFolder(old_path));
162   Pathname new_dir;
163   new_dir.SetFolder(new_path.pathname());
164   Pathname old_dir;
165   old_dir.SetFolder(old_path.pathname());
166   if (!CreateFolder(new_dir))
167     return false;
168   DirectoryIterator *di = IterateDirectory();
169   if (!di)
170     return false;
171   if (di->Iterate(old_dir.pathname())) {
172     do {
173       if (di->Name() == "." || di->Name() == "..")
174         continue;
175       Pathname source;
176       Pathname dest;
177       source.SetFolder(old_dir.pathname());
178       dest.SetFolder(new_path.pathname());
179       source.SetFilename(di->Name());
180       dest.SetFilename(di->Name());
181       if (!CopyFileOrFolder(source, dest))
182         success = false;
183     } while (di->Next());
184   }
185   delete di;
186   return success;
187 }
188
189 bool FilesystemInterface::DeleteFolderContents(const Pathname &folder) {
190   bool success = true;
191   VERIFY(IsFolder(folder));
192   DirectoryIterator *di = IterateDirectory();
193   if (!di)
194     return false;
195   if (di->Iterate(folder)) {
196     do {
197       if (di->Name() == "." || di->Name() == "..")
198         continue;
199       Pathname subdir;
200       subdir.SetFolder(folder.pathname());
201       if (di->IsDirectory()) {
202         subdir.AppendFolder(di->Name());
203         if (!DeleteFolderAndContents(subdir)) {
204           success = false;
205         }
206       } else {
207         subdir.SetFilename(di->Name());
208         if (!DeleteFile(subdir)) {
209           success = false;
210         }
211       }
212     } while (di->Next());
213   }
214   delete di;
215   return success;
216 }
217
218 bool FilesystemInterface::CleanAppTempFolder() {
219   Pathname path;
220   if (!GetAppTempFolder(&path))
221     return false;
222   if (IsAbsent(path))
223     return true;
224   if (!IsTemporaryPath(path)) {
225     ASSERT(false);
226     return false;
227   }
228   return DeleteFolderContents(path);
229 }
230
231 Pathname Filesystem::GetCurrentDirectory() {
232   return EnsureDefaultFilesystem()->GetCurrentDirectory();
233 }
234
235 bool CreateUniqueFile(Pathname& path, bool create_empty) {
236   LOG(LS_INFO) << "Path " << path.pathname() << std::endl;
237   // If no folder is supplied, use the temporary folder
238   if (path.folder().empty()) {
239     Pathname temporary_path;
240     if (!Filesystem::GetTemporaryFolder(temporary_path, true, NULL)) {
241       printf("Get temp failed\n");
242       return false;
243     }
244     path.SetFolder(temporary_path.pathname());
245   }
246
247   // If no filename is supplied, use a temporary name
248   if (path.filename().empty()) {
249     std::string folder(path.folder());
250     std::string filename = Filesystem::TempFilename(folder, "gt");
251     path.SetPathname(filename);
252     if (!create_empty) {
253       Filesystem::DeleteFile(path.pathname());
254     }
255     return true;
256   }
257
258   // Otherwise, create a unique name based on the given filename
259   // foo.txt -> foo-N.txt
260   const std::string basename = path.basename();
261   const size_t MAX_VERSION = 100;
262   size_t version = 0;
263   while (version < MAX_VERSION) {
264     std::string pathname = path.pathname();
265
266     if (!Filesystem::IsFile(pathname)) {
267       if (create_empty) {
268         FileStream* fs = Filesystem::OpenFile(pathname, "w");
269         delete fs;
270       }
271       return true;
272     }
273     version += 1;
274     char version_base[MAX_PATH];
275     sprintfn(version_base, ARRAY_SIZE(version_base), "%s-%u",
276              basename.c_str(), version);
277     path.SetBasename(version_base);
278   }
279   return true;
280 }
281
282 // Taken from Chromium's base/platform_file_*.cc.
283 // TODO(grunell): Remove when Chromium has started to use AEC in each source.
284 // http://crbug.com/264611.
285 FILE* FdopenPlatformFileForWriting(PlatformFile file) {
286 #if defined(WEBRTC_WIN)
287   if (file == kInvalidPlatformFileValue)
288     return NULL;
289   int fd = _open_osfhandle(reinterpret_cast<intptr_t>(file), 0);
290   if (fd < 0)
291     return NULL;
292   return _fdopen(fd, "w");
293 #else
294   return fdopen(file, "w");
295 #endif
296 }
297
298 bool ClosePlatformFile(PlatformFile file) {
299 #if defined(WEBRTC_WIN)
300   return CloseHandle(file) != 0;
301 #else
302   return close(file);
303 #endif
304 }
305
306 }  // namespace rtc