[go: nahoru, domu]

Move file_util to base/files/ directory.

This updates the includes in base but leaves a forwarding header for the rest of the project for now.

R=yzshen@chromium.org

Review URL: https://codereview.chromium.org/468253002

Cr-Commit-Position: refs/heads/master@{#289360}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@289360 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/base/files/file_util.cc b/base/files/file_util.cc
new file mode 100644
index 0000000..96a7164
--- /dev/null
+++ b/base/files/file_util.cc
@@ -0,0 +1,260 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/files/file_util.h"
+
+#if defined(OS_WIN)
+#include <io.h>
+#endif
+#include <stdio.h>
+
+#include <fstream>
+#include <limits>
+
+#include "base/files/file_enumerator.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+
+namespace base {
+
+namespace {
+
+// The maximum number of 'uniquified' files we will try to create.
+// This is used when the filename we're trying to download is already in use,
+// so we create a new unique filename by appending " (nnn)" before the
+// extension, where 1 <= nnn <= kMaxUniqueFiles.
+// Also used by code that cleans up said files.
+static const int kMaxUniqueFiles = 100;
+
+}  // namespace
+
+int64 ComputeDirectorySize(const FilePath& root_path) {
+  int64 running_size = 0;
+  FileEnumerator file_iter(root_path, true, FileEnumerator::FILES);
+  while (!file_iter.Next().empty())
+    running_size += file_iter.GetInfo().GetSize();
+  return running_size;
+}
+
+bool Move(const FilePath& from_path, const FilePath& to_path) {
+  if (from_path.ReferencesParent() || to_path.ReferencesParent())
+    return false;
+  return internal::MoveUnsafe(from_path, to_path);
+}
+
+bool CopyFile(const FilePath& from_path, const FilePath& to_path) {
+  if (from_path.ReferencesParent() || to_path.ReferencesParent())
+    return false;
+  return internal::CopyFileUnsafe(from_path, to_path);
+}
+
+bool ContentsEqual(const FilePath& filename1, const FilePath& filename2) {
+  // We open the file in binary format even if they are text files because
+  // we are just comparing that bytes are exactly same in both files and not
+  // doing anything smart with text formatting.
+  std::ifstream file1(filename1.value().c_str(),
+                      std::ios::in | std::ios::binary);
+  std::ifstream file2(filename2.value().c_str(),
+                      std::ios::in | std::ios::binary);
+
+  // Even if both files aren't openable (and thus, in some sense, "equal"),
+  // any unusable file yields a result of "false".
+  if (!file1.is_open() || !file2.is_open())
+    return false;
+
+  const int BUFFER_SIZE = 2056;
+  char buffer1[BUFFER_SIZE], buffer2[BUFFER_SIZE];
+  do {
+    file1.read(buffer1, BUFFER_SIZE);
+    file2.read(buffer2, BUFFER_SIZE);
+
+    if ((file1.eof() != file2.eof()) ||
+        (file1.gcount() != file2.gcount()) ||
+        (memcmp(buffer1, buffer2, file1.gcount()))) {
+      file1.close();
+      file2.close();
+      return false;
+    }
+  } while (!file1.eof() || !file2.eof());
+
+  file1.close();
+  file2.close();
+  return true;
+}
+
+bool TextContentsEqual(const FilePath& filename1, const FilePath& filename2) {
+  std::ifstream file1(filename1.value().c_str(), std::ios::in);
+  std::ifstream file2(filename2.value().c_str(), std::ios::in);
+
+  // Even if both files aren't openable (and thus, in some sense, "equal"),
+  // any unusable file yields a result of "false".
+  if (!file1.is_open() || !file2.is_open())
+    return false;
+
+  do {
+    std::string line1, line2;
+    getline(file1, line1);
+    getline(file2, line2);
+
+    // Check for mismatched EOF states, or any error state.
+    if ((file1.eof() != file2.eof()) ||
+        file1.bad() || file2.bad()) {
+      return false;
+    }
+
+    // Trim all '\r' and '\n' characters from the end of the line.
+    std::string::size_type end1 = line1.find_last_not_of("\r\n");
+    if (end1 == std::string::npos)
+      line1.clear();
+    else if (end1 + 1 < line1.length())
+      line1.erase(end1 + 1);
+
+    std::string::size_type end2 = line2.find_last_not_of("\r\n");
+    if (end2 == std::string::npos)
+      line2.clear();
+    else if (end2 + 1 < line2.length())
+      line2.erase(end2 + 1);
+
+    if (line1 != line2)
+      return false;
+  } while (!file1.eof() || !file2.eof());
+
+  return true;
+}
+
+bool ReadFileToString(const FilePath& path,
+                      std::string* contents,
+                      size_t max_size) {
+  if (contents)
+    contents->clear();
+  if (path.ReferencesParent())
+    return false;
+  FILE* file = OpenFile(path, "rb");
+  if (!file) {
+    return false;
+  }
+
+  char buf[1 << 16];
+  size_t len;
+  size_t size = 0;
+  bool read_status = true;
+
+  // Many files supplied in |path| have incorrect size (proc files etc).
+  // Hence, the file is read sequentially as opposed to a one-shot read.
+  while ((len = fread(buf, 1, sizeof(buf), file)) > 0) {
+    if (contents)
+      contents->append(buf, std::min(len, max_size - size));
+
+    if ((max_size - size) < len) {
+      read_status = false;
+      break;
+    }
+
+    size += len;
+  }
+  read_status = read_status && !ferror(file);
+  CloseFile(file);
+
+  return read_status;
+}
+
+bool ReadFileToString(const FilePath& path, std::string* contents) {
+  return ReadFileToString(path, contents, std::numeric_limits<size_t>::max());
+}
+
+bool IsDirectoryEmpty(const FilePath& dir_path) {
+  FileEnumerator files(dir_path, false,
+      FileEnumerator::FILES | FileEnumerator::DIRECTORIES);
+  if (files.Next().empty())
+    return true;
+  return false;
+}
+
+FILE* CreateAndOpenTemporaryFile(FilePath* path) {
+  FilePath directory;
+  if (!GetTempDir(&directory))
+    return NULL;
+
+  return CreateAndOpenTemporaryFileInDir(directory, path);
+}
+
+bool CreateDirectory(const FilePath& full_path) {
+  return CreateDirectoryAndGetError(full_path, NULL);
+}
+
+bool GetFileSize(const FilePath& file_path, int64* file_size) {
+  File::Info info;
+  if (!GetFileInfo(file_path, &info))
+    return false;
+  *file_size = info.size;
+  return true;
+}
+
+bool TouchFile(const FilePath& path,
+               const Time& last_accessed,
+               const Time& last_modified) {
+  int flags = File::FLAG_OPEN | File::FLAG_WRITE_ATTRIBUTES;
+
+#if defined(OS_WIN)
+  // On Windows, FILE_FLAG_BACKUP_SEMANTICS is needed to open a directory.
+  if (DirectoryExists(path))
+    flags |= File::FLAG_BACKUP_SEMANTICS;
+#endif  // OS_WIN
+
+  File file(path, flags);
+  if (!file.IsValid())
+    return false;
+
+  return file.SetTimes(last_accessed, last_modified);
+}
+
+bool CloseFile(FILE* file) {
+  if (file == NULL)
+    return true;
+  return fclose(file) == 0;
+}
+
+bool TruncateFile(FILE* file) {
+  if (file == NULL)
+    return false;
+  long current_offset = ftell(file);
+  if (current_offset == -1)
+    return false;
+#if defined(OS_WIN)
+  int fd = _fileno(file);
+  if (_chsize(fd, current_offset) != 0)
+    return false;
+#else
+  int fd = fileno(file);
+  if (ftruncate(fd, current_offset) != 0)
+    return false;
+#endif
+  return true;
+}
+
+int GetUniquePathNumber(const FilePath& path,
+                        const FilePath::StringType& suffix) {
+  bool have_suffix = !suffix.empty();
+  if (!PathExists(path) &&
+      (!have_suffix || !PathExists(FilePath(path.value() + suffix)))) {
+    return 0;
+  }
+
+  FilePath new_path;
+  for (int count = 1; count <= kMaxUniqueFiles; ++count) {
+    new_path = path.InsertBeforeExtensionASCII(StringPrintf(" (%d)", count));
+    if (!PathExists(new_path) &&
+        (!have_suffix || !PathExists(FilePath(new_path.value() + suffix)))) {
+      return count;
+    }
+  }
+
+  return -1;
+}
+
+}  // namespace base