1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/file_util.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <io.h>
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stdio.h>
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <fstream>
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/file_path.h"
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h"
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_piece.h"
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h"
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/utf_string_conversions.h"
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst FilePath::CharType kExtensionSeparator = FILE_PATH_LITERAL('.');
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace file_util {
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EndsWithSeparator(const FilePath& path) {
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath::StringType value = path.value();
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (value.empty())
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return FilePath::IsSeparator(value[value.size() - 1]);
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EnsureEndsWithSeparator(FilePath* path) {
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!DirectoryExists(*path))
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (EndsWithSeparator(*path))
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return true;
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath::StringType& path_str =
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      const_cast<FilePath::StringType&>(path->value());
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  path_str.append(&FilePath::kSeparators[0], 1);
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFilePath::StringType GetFileExtensionFromPath(const FilePath& path) {
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath::StringType file_name = path.BaseName().value();
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const FilePath::StringType::size_type last_dot =
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      file_name.rfind(kExtensionSeparator);
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return FilePath::StringType(last_dot == FilePath::StringType::npos ?
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                              FILE_PATH_LITERAL("") :
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                              file_name, last_dot+1);
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid InsertBeforeExtension(FilePath* path, const FilePath::StringType& suffix) {
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath::StringType& value =
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      const_cast<FilePath::StringType&>(path->value());
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const FilePath::StringType::size_type last_dot =
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      value.rfind(kExtensionSeparator);
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const FilePath::StringType::size_type last_separator =
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      value.find_last_of(FilePath::StringType(FilePath::kSeparators));
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (last_dot == FilePath::StringType::npos ||
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      (last_separator != std::wstring::npos && last_dot < last_separator)) {
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // The path looks something like "C:\pics.old\jojo" or "C:\pics\jojo".
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // We should just append the suffix to the entire path.
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    value.append(suffix);
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  value.insert(last_dot, suffix);
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool ContentsEqual(const FilePath& filename1, const FilePath& filename2) {
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We open the file in binary format even if they are text files because
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // we are just comparing that bytes are exactly same in both files and not
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // doing anything smart with text formatting.
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::ifstream file1(filename1.value().c_str(),
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                      std::ios::in | std::ios::binary);
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::ifstream file2(filename2.value().c_str(),
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                      std::ios::in | std::ios::binary);
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Even if both files aren't openable (and thus, in some sense, "equal"),
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // any unusable file yields a result of "false".
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!file1.is_open() || !file2.is_open())
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const int BUFFER_SIZE = 2056;
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char buffer1[BUFFER_SIZE], buffer2[BUFFER_SIZE];
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  do {
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    file1.read(buffer1, BUFFER_SIZE);
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    file2.read(buffer2, BUFFER_SIZE);
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if ((file1.eof() != file2.eof()) ||
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        (file1.gcount() != file2.gcount()) ||
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        (memcmp(buffer1, buffer2, file1.gcount()))) {
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      file1.close();
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      file2.close();
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } while (!file1.eof() || !file2.eof());
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  file1.close();
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  file2.close();
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool TextContentsEqual(const FilePath& filename1, const FilePath& filename2) {
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::ifstream file1(filename1.value().c_str(), std::ios::in);
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::ifstream file2(filename2.value().c_str(), std::ios::in);
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Even if both files aren't openable (and thus, in some sense, "equal"),
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // any unusable file yields a result of "false".
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!file1.is_open() || !file2.is_open())
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  do {
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    std::string line1, line2;
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    getline(file1, line1);
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    getline(file2, line2);
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Check for mismatched EOF states, or any error state.
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if ((file1.eof() != file2.eof()) ||
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        file1.bad() || file2.bad()) {
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Trim all '\r' and '\n' characters from the end of the line.
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    std::string::size_type end1 = line1.find_last_not_of("\r\n");
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (end1 == std::string::npos)
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      line1.clear();
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    else if (end1 + 1 < line1.length())
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      line1.erase(end1 + 1);
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    std::string::size_type end2 = line2.find_last_not_of("\r\n");
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (end2 == std::string::npos)
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      line2.clear();
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    else if (end2 + 1 < line2.length())
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      line2.erase(end2 + 1);
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (line1 != line2)
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } while (!file1.eof() || !file2.eof());
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool ReadFileToString(const FilePath& path, std::string* contents) {
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FILE* file = OpenFile(path, "rb");
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!file) {
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char buf[1 << 16];
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t len;
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  while ((len = fread(buf, 1, sizeof(buf), file)) > 0) {
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (contents)
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      contents->append(buf, len);
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CloseFile(file);
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool IsDirectoryEmpty(const FilePath& dir_path) {
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FileEnumerator files(dir_path, false,
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      static_cast<FileEnumerator::FILE_TYPE>(
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          FileEnumerator::FILES | FileEnumerator::DIRECTORIES));
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (files.Next().value().empty())
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFILE* CreateAndOpenTemporaryFile(FilePath* path) {
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath directory;
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!GetTempDir(&directory))
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return CreateAndOpenTemporaryFileInDir(directory, path);
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool GetFileSize(const FilePath& file_path, int64* file_size) {
1883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::PlatformFileInfo info;
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!GetFileInfo(file_path, &info))
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *file_size = info.size;
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool IsDot(const FilePath& path) {
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return FILE_PATH_LITERAL(".") == path.BaseName().value();
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool IsDotDot(const FilePath& path) {
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return FILE_PATH_LITERAL("..") == path.BaseName().value();
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool TouchFile(const FilePath& path,
2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick               const base::Time& last_accessed,
2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick               const base::Time& last_modified) {
2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::PlatformFile file =
2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::CreatePlatformFile(path,
2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                               base::PLATFORM_FILE_OPEN |
2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                               base::PLATFORM_FILE_WRITE_ATTRIBUTES,
2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                               NULL, NULL);
2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (file != base::kInvalidPlatformFileValue) {
2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    bool result = base::TouchPlatformFile(file, last_accessed, last_modified);
2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    base::ClosePlatformFile(file);
2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return result;
2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return false;
2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool SetLastModifiedTime(const FilePath& path,
2213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                         const base::Time& last_modified) {
2223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return TouchFile(path, last_modified, last_modified);
2233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool CloseFile(FILE* file) {
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (file == NULL)
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return true;
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return fclose(file) == 0;
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool TruncateFile(FILE* file) {
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (file == NULL)
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  long current_offset = ftell(file);
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (current_offset == -1)
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int fd = _fileno(file);
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (_chsize(fd, current_offset) != 0)
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int fd = fileno(file);
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (ftruncate(fd, current_offset) != 0)
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool ContainsPath(const FilePath &parent, const FilePath& child) {
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath abs_parent = FilePath(parent);
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath abs_child = FilePath(child);
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!file_util::AbsolutePath(&abs_parent) ||
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      !file_util::AbsolutePath(&abs_child))
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // file_util::AbsolutePath() does not flatten case on Windows, so we must do
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // a case-insensitive compare.
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!StartsWith(abs_child.value(), abs_parent.value(), false))
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!StartsWithASCII(abs_child.value(), abs_parent.value(), true))
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // file_util::AbsolutePath() normalizes '/' to '\' on Windows, so we only need
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // to check kSeparators[0].
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (abs_child.value().length() <= abs_parent.value().length() ||
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      abs_child.value()[abs_parent.value().length()] !=
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          FilePath::kSeparators[0])
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint64 ComputeDirectorySize(const FilePath& root_path) {
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int64 running_size = 0;
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FileEnumerator file_iter(root_path, true, FileEnumerator::FILES);
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (FilePath current = file_iter.Next(); !current.empty();
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       current = file_iter.Next()) {
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FileEnumerator::FindInfo info;
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    file_iter.GetFindInfo(&info);
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN)
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LARGE_INTEGER li = { info.nFileSizeLow, info.nFileSizeHigh };
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    running_size += li.QuadPart;
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    running_size += info.stat.st_size;
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return running_size;
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint64 ComputeFilesSize(const FilePath& directory,
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       const FilePath::StringType& pattern) {
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int64 running_size = 0;
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FileEnumerator file_iter(directory, false, FileEnumerator::FILES, pattern);
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (FilePath current = file_iter.Next(); !current.empty();
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       current = file_iter.Next()) {
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FileEnumerator::FindInfo info;
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    file_iter.GetFindInfo(&info);
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN)
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LARGE_INTEGER li = { info.nFileSizeLow, info.nFileSizeHigh };
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    running_size += li.QuadPart;
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    running_size += info.stat.st_size;
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return running_size;
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott///////////////////////////////////////////////
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// MemoryMappedFile
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMemoryMappedFile::~MemoryMappedFile() {
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CloseHandles();
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
31872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool MemoryMappedFile::Initialize(const FilePath& file_name) {
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (IsValid())
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
32272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!MapFileToMemory(file_name)) {
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CloseHandles();
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
33072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool MemoryMappedFile::Initialize(base::PlatformFile file) {
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (IsValid())
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
33472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  file_ = file;
33572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
33672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!MapFileToMemoryInternal()) {
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CloseHandles();
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
344dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool MemoryMappedFile::IsValid() const {
34572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return data_ != NULL;
34672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
34772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool MemoryMappedFile::MapFileToMemory(const FilePath& file_name) {
3493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  file_ = base::CreatePlatformFile(
3503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      file_name, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
3513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NULL, NULL);
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (file_ == base::kInvalidPlatformFileValue) {
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Couldn't open " << file_name.value();
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return MapFileToMemoryInternal();
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Deprecated functions ----------------------------------------------------
362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
363731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#if defined(OS_WIN)
364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid AppendToPath(std::wstring* path, const std::wstring& new_ending) {
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!path) {
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED();
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;  // Don't crash in this function in release builds.
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!EndsWithSeparator(FilePath(*path)))
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    path->push_back(FilePath::kSeparators[0]);
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  path->append(new_ending);
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool CopyDirectory(const std::wstring& from_path, const std::wstring& to_path,
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                   bool recursive) {
377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return CopyDirectory(FilePath::FromWStringHack(from_path),
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                       FilePath::FromWStringHack(to_path),
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                       recursive);
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool Delete(const std::wstring& path, bool recursive) {
382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return Delete(FilePath::FromWStringHack(path), recursive);
383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::wstring GetFileExtensionFromPath(const std::wstring& path) {
385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath::StringType extension =
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      GetFileExtensionFromPath(FilePath::FromWStringHack(path));
387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return extension;
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFILE* OpenFile(const std::wstring& filename, const char* mode) {
390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return OpenFile(FilePath::FromWStringHack(filename), mode);
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint ReadFile(const std::wstring& filename, char* data, int size) {
393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return ReadFile(FilePath::FromWStringHack(filename), data, size);
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint WriteFile(const std::wstring& filename, const char* data, int size) {
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return WriteFile(FilePath::FromWStringHack(filename), data, size);
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
398731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#endif  // OS_WIN
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott///////////////////////////////////////////////
401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// FileEnumerator
402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Note: the main logic is in file_util_<platform>.cc
404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FileEnumerator::ShouldSkip(const FilePath& path) {
406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath::StringType basename = path.BaseName().value();
407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return IsDot(path) || (IsDotDot(path) && !(INCLUDE_DOT_DOT & file_type_));
408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace
411