Open HTML files in Chrome by default.
[chromium-blink-merge.git] / base / file_util.cc
blob5e9790efe46b82437db165845fc71ebaf1deef3d
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/file_util.h"
7 #if defined(OS_WIN)
8 #include <io.h>
9 #endif
10 #include <stdio.h>
12 #include <fstream>
14 #include "base/files/file_enumerator.h"
15 #include "base/files/file_path.h"
16 #include "base/logging.h"
17 #include "base/strings/string_piece.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/strings/utf_string_conversions.h"
22 namespace base {
24 namespace {
26 // The maximum number of 'uniquified' files we will try to create.
27 // This is used when the filename we're trying to download is already in use,
28 // so we create a new unique filename by appending " (nnn)" before the
29 // extension, where 1 <= nnn <= kMaxUniqueFiles.
30 // Also used by code that cleans up said files.
31 static const int kMaxUniqueFiles = 100;
33 } // namespace
35 int64 ComputeDirectorySize(const FilePath& root_path) {
36 int64 running_size = 0;
37 FileEnumerator file_iter(root_path, true, FileEnumerator::FILES);
38 while (!file_iter.Next().empty())
39 running_size += file_iter.GetInfo().GetSize();
40 return running_size;
43 bool Move(const FilePath& from_path, const FilePath& to_path) {
44 if (from_path.ReferencesParent() || to_path.ReferencesParent())
45 return false;
46 return internal::MoveUnsafe(from_path, to_path);
49 bool CopyFile(const FilePath& from_path, const FilePath& to_path) {
50 if (from_path.ReferencesParent() || to_path.ReferencesParent())
51 return false;
52 return internal::CopyFileUnsafe(from_path, to_path);
55 bool ContentsEqual(const FilePath& filename1, const FilePath& filename2) {
56 // We open the file in binary format even if they are text files because
57 // we are just comparing that bytes are exactly same in both files and not
58 // doing anything smart with text formatting.
59 std::ifstream file1(filename1.value().c_str(),
60 std::ios::in | std::ios::binary);
61 std::ifstream file2(filename2.value().c_str(),
62 std::ios::in | std::ios::binary);
64 // Even if both files aren't openable (and thus, in some sense, "equal"),
65 // any unusable file yields a result of "false".
66 if (!file1.is_open() || !file2.is_open())
67 return false;
69 const int BUFFER_SIZE = 2056;
70 char buffer1[BUFFER_SIZE], buffer2[BUFFER_SIZE];
71 do {
72 file1.read(buffer1, BUFFER_SIZE);
73 file2.read(buffer2, BUFFER_SIZE);
75 if ((file1.eof() != file2.eof()) ||
76 (file1.gcount() != file2.gcount()) ||
77 (memcmp(buffer1, buffer2, file1.gcount()))) {
78 file1.close();
79 file2.close();
80 return false;
82 } while (!file1.eof() || !file2.eof());
84 file1.close();
85 file2.close();
86 return true;
89 bool TextContentsEqual(const FilePath& filename1, const FilePath& filename2) {
90 std::ifstream file1(filename1.value().c_str(), std::ios::in);
91 std::ifstream file2(filename2.value().c_str(), std::ios::in);
93 // Even if both files aren't openable (and thus, in some sense, "equal"),
94 // any unusable file yields a result of "false".
95 if (!file1.is_open() || !file2.is_open())
96 return false;
98 do {
99 std::string line1, line2;
100 getline(file1, line1);
101 getline(file2, line2);
103 // Check for mismatched EOF states, or any error state.
104 if ((file1.eof() != file2.eof()) ||
105 file1.bad() || file2.bad()) {
106 return false;
109 // Trim all '\r' and '\n' characters from the end of the line.
110 std::string::size_type end1 = line1.find_last_not_of("\r\n");
111 if (end1 == std::string::npos)
112 line1.clear();
113 else if (end1 + 1 < line1.length())
114 line1.erase(end1 + 1);
116 std::string::size_type end2 = line2.find_last_not_of("\r\n");
117 if (end2 == std::string::npos)
118 line2.clear();
119 else if (end2 + 1 < line2.length())
120 line2.erase(end2 + 1);
122 if (line1 != line2)
123 return false;
124 } while (!file1.eof() || !file2.eof());
126 return true;
129 bool ReadFileToString(const FilePath& path, std::string* contents) {
130 if (path.ReferencesParent())
131 return false;
132 FILE* file = file_util::OpenFile(path, "rb");
133 if (!file) {
134 return false;
137 char buf[1 << 16];
138 size_t len;
139 while ((len = fread(buf, 1, sizeof(buf), file)) > 0) {
140 if (contents)
141 contents->append(buf, len);
143 file_util::CloseFile(file);
145 return true;
148 } // namespace base
150 // -----------------------------------------------------------------------------
152 namespace file_util {
154 using base::FileEnumerator;
155 using base::FilePath;
156 using base::kMaxUniqueFiles;
158 bool IsDirectoryEmpty(const FilePath& dir_path) {
159 FileEnumerator files(dir_path, false,
160 FileEnumerator::FILES | FileEnumerator::DIRECTORIES);
161 if (files.Next().empty())
162 return true;
163 return false;
166 FILE* CreateAndOpenTemporaryFile(FilePath* path) {
167 FilePath directory;
168 if (!GetTempDir(&directory))
169 return NULL;
171 return CreateAndOpenTemporaryFileInDir(directory, path);
174 bool CreateDirectory(const base::FilePath& full_path) {
175 return CreateDirectoryAndGetError(full_path, NULL);
178 bool GetFileSize(const FilePath& file_path, int64* file_size) {
179 base::PlatformFileInfo info;
180 if (!GetFileInfo(file_path, &info))
181 return false;
182 *file_size = info.size;
183 return true;
186 bool TouchFile(const FilePath& path,
187 const base::Time& last_accessed,
188 const base::Time& last_modified) {
189 int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE_ATTRIBUTES;
191 #if defined(OS_WIN)
192 // On Windows, FILE_FLAG_BACKUP_SEMANTICS is needed to open a directory.
193 if (DirectoryExists(path))
194 flags |= base::PLATFORM_FILE_BACKUP_SEMANTICS;
195 #endif // OS_WIN
197 const base::PlatformFile file =
198 base::CreatePlatformFile(path, flags, NULL, NULL);
199 if (file != base::kInvalidPlatformFileValue) {
200 bool result = base::TouchPlatformFile(file, last_accessed, last_modified);
201 base::ClosePlatformFile(file);
202 return result;
205 return false;
208 bool SetLastModifiedTime(const FilePath& path,
209 const base::Time& last_modified) {
210 return TouchFile(path, last_modified, last_modified);
213 bool CloseFile(FILE* file) {
214 if (file == NULL)
215 return true;
216 return fclose(file) == 0;
219 bool TruncateFile(FILE* file) {
220 if (file == NULL)
221 return false;
222 long current_offset = ftell(file);
223 if (current_offset == -1)
224 return false;
225 #if defined(OS_WIN)
226 int fd = _fileno(file);
227 if (_chsize(fd, current_offset) != 0)
228 return false;
229 #else
230 int fd = fileno(file);
231 if (ftruncate(fd, current_offset) != 0)
232 return false;
233 #endif
234 return true;
237 int GetUniquePathNumber(
238 const FilePath& path,
239 const FilePath::StringType& suffix) {
240 bool have_suffix = !suffix.empty();
241 if (!PathExists(path) &&
242 (!have_suffix || !PathExists(FilePath(path.value() + suffix)))) {
243 return 0;
246 FilePath new_path;
247 for (int count = 1; count <= kMaxUniqueFiles; ++count) {
248 new_path =
249 path.InsertBeforeExtensionASCII(base::StringPrintf(" (%d)", count));
250 if (!PathExists(new_path) &&
251 (!have_suffix || !PathExists(FilePath(new_path.value() + suffix)))) {
252 return count;
256 return -1;
259 } // namespace file_util