Adds a modified copy of talk/base to webrtc/base. It is the first step in
migrating talk/base to webrtc/base.

BUG=N/A
R=niklas.enbom@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/17479005

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6129 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/base/fileutils.cc b/webrtc/base/fileutils.cc
new file mode 100644
index 0000000..60bd0f8
--- /dev/null
+++ b/webrtc/base/fileutils.cc
@@ -0,0 +1,307 @@
+/*
+ *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <assert.h>
+
+#if defined(WEBRTC_WIN)
+// TODO(grunell): Remove io.h includes when Chromium has started
+// to use AEC in each source. http://crbug.com/264611.
+#include <io.h>
+#include "webrtc/base/win32.h"
+#endif
+
+#include "webrtc/base/pathutils.h"
+#include "webrtc/base/fileutils.h"
+#include "webrtc/base/stringutils.h"
+#include "webrtc/base/stream.h"
+
+#if defined(WEBRTC_WIN)
+#include "webrtc/base/win32filesystem.h"
+#else
+#include "webrtc/base/unixfilesystem.h"
+#endif
+
+#if !defined(WEBRTC_WIN)
+#define MAX_PATH 260
+#endif
+
+namespace rtc {
+
+//////////////////////////
+// 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.
+
+  // Constructor
+DirectoryIterator::DirectoryIterator()
+#ifdef WEBRTC_WIN
+    : handle_(INVALID_HANDLE_VALUE) {
+#else
+    : dir_(NULL), dirent_(NULL) {
+#endif
+}
+
+  // Destructor
+DirectoryIterator::~DirectoryIterator() {
+#if defined(WEBRTC_WIN)
+  if (handle_ != INVALID_HANDLE_VALUE)
+    ::FindClose(handle_);
+#else
+  if (dir_)
+    closedir(dir_);
+#endif
+}
+
+  // Starts traversing a directory.
+  // dir is the directory to traverse
+  // returns true if the directory exists and is valid
+bool DirectoryIterator::Iterate(const Pathname &dir) {
+  directory_ = dir.pathname();
+#if defined(WEBRTC_WIN)
+  if (handle_ != INVALID_HANDLE_VALUE)
+    ::FindClose(handle_);
+  std::string d = dir.pathname() + '*';
+  handle_ = ::FindFirstFile(ToUtf16(d).c_str(), &data_);
+  if (handle_ == INVALID_HANDLE_VALUE)
+    return false;
+#else
+  if (dir_ != NULL)
+    closedir(dir_);
+  dir_ = ::opendir(directory_.c_str());
+  if (dir_ == NULL)
+    return false;
+  dirent_ = readdir(dir_);
+  if (dirent_ == NULL)
+    return false;
+
+  if (::stat(std::string(directory_ + Name()).c_str(), &stat_) != 0)
+    return false;
+#endif
+  return true;
+}
+
+  // Advances to the next file
+  // returns true if there were more files in the directory.
+bool DirectoryIterator::Next() {
+#if defined(WEBRTC_WIN)
+  return ::FindNextFile(handle_, &data_) == TRUE;
+#else
+  dirent_ = ::readdir(dir_);
+  if (dirent_ == NULL)
+    return false;
+
+  return ::stat(std::string(directory_ + Name()).c_str(), &stat_) == 0;
+#endif
+}
+
+  // returns true if the file currently pointed to is a directory
+bool DirectoryIterator::IsDirectory() const {
+#if defined(WEBRTC_WIN)
+  return (data_.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FALSE;
+#else
+  return S_ISDIR(stat_.st_mode);
+#endif
+}
+
+  // returns the name of the file currently pointed to
+std::string DirectoryIterator::Name() const {
+#if defined(WEBRTC_WIN)
+  return ToUtf8(data_.cFileName);
+#else
+  assert(dirent_ != NULL);
+  return dirent_->d_name;
+#endif
+}
+
+  // returns the size of the file currently pointed to
+size_t DirectoryIterator::FileSize() const {
+#if !defined(WEBRTC_WIN)
+  return stat_.st_size;
+#else
+  return data_.nFileSizeLow;
+#endif
+}
+
+  // returns the last modified time of this file
+time_t DirectoryIterator::FileModifyTime() const {
+#if defined(WEBRTC_WIN)
+  time_t val;
+  FileTimeToUnixTime(data_.ftLastWriteTime, &val);
+  return val;
+#else
+  return stat_.st_mtime;
+#endif
+}
+
+FilesystemInterface* Filesystem::default_filesystem_ = NULL;
+
+FilesystemInterface *Filesystem::EnsureDefaultFilesystem() {
+  if (!default_filesystem_) {
+#if defined(WEBRTC_WIN)
+    default_filesystem_ = new Win32Filesystem();
+#else
+    default_filesystem_ = new UnixFilesystem();
+#endif
+  }
+  return default_filesystem_;
+}
+
+bool FilesystemInterface::CopyFolder(const Pathname &old_path,
+                                     const Pathname &new_path) {
+  bool success = true;
+  VERIFY(IsFolder(old_path));
+  Pathname new_dir;
+  new_dir.SetFolder(new_path.pathname());
+  Pathname old_dir;
+  old_dir.SetFolder(old_path.pathname());
+  if (!CreateFolder(new_dir))
+    return false;
+  DirectoryIterator *di = IterateDirectory();
+  if (!di)
+    return false;
+  if (di->Iterate(old_dir.pathname())) {
+    do {
+      if (di->Name() == "." || di->Name() == "..")
+        continue;
+      Pathname source;
+      Pathname dest;
+      source.SetFolder(old_dir.pathname());
+      dest.SetFolder(new_path.pathname());
+      source.SetFilename(di->Name());
+      dest.SetFilename(di->Name());
+      if (!CopyFileOrFolder(source, dest))
+        success = false;
+    } while (di->Next());
+  }
+  delete di;
+  return success;
+}
+
+bool FilesystemInterface::DeleteFolderContents(const Pathname &folder) {
+  bool success = true;
+  VERIFY(IsFolder(folder));
+  DirectoryIterator *di = IterateDirectory();
+  if (!di)
+    return false;
+  if (di->Iterate(folder)) {
+    do {
+      if (di->Name() == "." || di->Name() == "..")
+        continue;
+      Pathname subdir;
+      subdir.SetFolder(folder.pathname());
+      if (di->IsDirectory()) {
+        subdir.AppendFolder(di->Name());
+        if (!DeleteFolderAndContents(subdir)) {
+          success = false;
+        }
+      } else {
+        subdir.SetFilename(di->Name());
+        if (!DeleteFile(subdir)) {
+          success = false;
+        }
+      }
+    } while (di->Next());
+  }
+  delete di;
+  return success;
+}
+
+bool FilesystemInterface::CleanAppTempFolder() {
+  Pathname path;
+  if (!GetAppTempFolder(&path))
+    return false;
+  if (IsAbsent(path))
+    return true;
+  if (!IsTemporaryPath(path)) {
+    ASSERT(false);
+    return false;
+  }
+  return DeleteFolderContents(path);
+}
+
+Pathname Filesystem::GetCurrentDirectory() {
+  return EnsureDefaultFilesystem()->GetCurrentDirectory();
+}
+
+bool CreateUniqueFile(Pathname& path, bool create_empty) {
+  LOG(LS_INFO) << "Path " << path.pathname() << std::endl;
+  // If no folder is supplied, use the temporary folder
+  if (path.folder().empty()) {
+    Pathname temporary_path;
+    if (!Filesystem::GetTemporaryFolder(temporary_path, true, NULL)) {
+      printf("Get temp failed\n");
+      return false;
+    }
+    path.SetFolder(temporary_path.pathname());
+  }
+
+  // If no filename is supplied, use a temporary name
+  if (path.filename().empty()) {
+    std::string folder(path.folder());
+    std::string filename = Filesystem::TempFilename(folder, "gt");
+    path.SetPathname(filename);
+    if (!create_empty) {
+      Filesystem::DeleteFile(path.pathname());
+    }
+    return true;
+  }
+
+  // Otherwise, create a unique name based on the given filename
+  // foo.txt -> foo-N.txt
+  const std::string basename = path.basename();
+  const size_t MAX_VERSION = 100;
+  size_t version = 0;
+  while (version < MAX_VERSION) {
+    std::string pathname = path.pathname();
+
+    if (!Filesystem::IsFile(pathname)) {
+      if (create_empty) {
+        FileStream* fs = Filesystem::OpenFile(pathname, "w");
+        delete fs;
+      }
+      return true;
+    }
+    version += 1;
+    char version_base[MAX_PATH];
+    sprintfn(version_base, ARRAY_SIZE(version_base), "%s-%u",
+             basename.c_str(), version);
+    path.SetBasename(version_base);
+  }
+  return true;
+}
+
+// Taken from Chromium's base/platform_file_*.cc.
+// TODO(grunell): Remove when Chromium has started to use AEC in each source.
+// http://crbug.com/264611.
+FILE* FdopenPlatformFileForWriting(PlatformFile file) {
+#if defined(WEBRTC_WIN)
+  if (file == kInvalidPlatformFileValue)
+    return NULL;
+  int fd = _open_osfhandle(reinterpret_cast<intptr_t>(file), 0);
+  if (fd < 0)
+    return NULL;
+  return _fdopen(fd, "w");
+#else
+  return fdopen(file, "w");
+#endif
+}
+
+bool ClosePlatformFile(PlatformFile file) {
+#if defined(WEBRTC_WIN)
+  return CloseHandle(file) != 0;
+#else
+  return close(file);
+#endif
+}
+
+}  // namespace rtc