Update .DEPS.git
[chromium-blink-merge.git] / base / file_util.cc
blob308b150a1d6d8d2aeba7f08caa76abfba49af6e3
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 bool g_bug108724_debug = false;
37 int64 ComputeDirectorySize(const FilePath& root_path) {
38 int64 running_size = 0;
39 FileEnumerator file_iter(root_path, true, FileEnumerator::FILES);
40 while (!file_iter.Next().empty())
41 running_size += file_iter.GetInfo().GetSize();
42 return running_size;
45 bool Move(const FilePath& from_path, const FilePath& to_path) {
46 if (from_path.ReferencesParent() || to_path.ReferencesParent())
47 return false;
48 return internal::MoveUnsafe(from_path, to_path);
51 bool CopyFile(const FilePath& from_path, const FilePath& to_path) {
52 if (from_path.ReferencesParent() || to_path.ReferencesParent())
53 return false;
54 return internal::CopyFileUnsafe(from_path, to_path);
57 bool ContentsEqual(const FilePath& filename1, const FilePath& filename2) {
58 // We open the file in binary format even if they are text files because
59 // we are just comparing that bytes are exactly same in both files and not
60 // doing anything smart with text formatting.
61 std::ifstream file1(filename1.value().c_str(),
62 std::ios::in | std::ios::binary);
63 std::ifstream file2(filename2.value().c_str(),
64 std::ios::in | std::ios::binary);
66 // Even if both files aren't openable (and thus, in some sense, "equal"),
67 // any unusable file yields a result of "false".
68 if (!file1.is_open() || !file2.is_open())
69 return false;
71 const int BUFFER_SIZE = 2056;
72 char buffer1[BUFFER_SIZE], buffer2[BUFFER_SIZE];
73 do {
74 file1.read(buffer1, BUFFER_SIZE);
75 file2.read(buffer2, BUFFER_SIZE);
77 if ((file1.eof() != file2.eof()) ||
78 (file1.gcount() != file2.gcount()) ||
79 (memcmp(buffer1, buffer2, file1.gcount()))) {
80 file1.close();
81 file2.close();
82 return false;
84 } while (!file1.eof() || !file2.eof());
86 file1.close();
87 file2.close();
88 return true;
91 bool TextContentsEqual(const FilePath& filename1, const FilePath& filename2) {
92 std::ifstream file1(filename1.value().c_str(), std::ios::in);
93 std::ifstream file2(filename2.value().c_str(), std::ios::in);
95 // Even if both files aren't openable (and thus, in some sense, "equal"),
96 // any unusable file yields a result of "false".
97 if (!file1.is_open() || !file2.is_open())
98 return false;
100 do {
101 std::string line1, line2;
102 getline(file1, line1);
103 getline(file2, line2);
105 // Check for mismatched EOF states, or any error state.
106 if ((file1.eof() != file2.eof()) ||
107 file1.bad() || file2.bad()) {
108 return false;
111 // Trim all '\r' and '\n' characters from the end of the line.
112 std::string::size_type end1 = line1.find_last_not_of("\r\n");
113 if (end1 == std::string::npos)
114 line1.clear();
115 else if (end1 + 1 < line1.length())
116 line1.erase(end1 + 1);
118 std::string::size_type end2 = line2.find_last_not_of("\r\n");
119 if (end2 == std::string::npos)
120 line2.clear();
121 else if (end2 + 1 < line2.length())
122 line2.erase(end2 + 1);
124 if (line1 != line2)
125 return false;
126 } while (!file1.eof() || !file2.eof());
128 return true;
131 bool ReadFileToString(const FilePath& path, std::string* contents) {
132 if (path.ReferencesParent())
133 return false;
134 FILE* file = file_util::OpenFile(path, "rb");
135 if (!file) {
136 return false;
139 char buf[1 << 16];
140 size_t len;
141 while ((len = fread(buf, 1, sizeof(buf), file)) > 0) {
142 if (contents)
143 contents->append(buf, len);
145 file_util::CloseFile(file);
147 return true;
150 } // namespace base
152 // -----------------------------------------------------------------------------
154 namespace file_util {
156 using base::FileEnumerator;
157 using base::FilePath;
158 using base::kMaxUniqueFiles;
160 bool IsDirectoryEmpty(const FilePath& dir_path) {
161 FileEnumerator files(dir_path, false,
162 FileEnumerator::FILES | FileEnumerator::DIRECTORIES);
163 if (files.Next().empty())
164 return true;
165 return false;
168 FILE* CreateAndOpenTemporaryFile(FilePath* path) {
169 FilePath directory;
170 if (!GetTempDir(&directory))
171 return NULL;
173 return CreateAndOpenTemporaryFileInDir(directory, path);
176 bool CreateDirectory(const base::FilePath& full_path) {
177 return CreateDirectoryAndGetError(full_path, NULL);
180 bool GetFileSize(const FilePath& file_path, int64* file_size) {
181 base::PlatformFileInfo info;
182 if (!GetFileInfo(file_path, &info))
183 return false;
184 *file_size = info.size;
185 return true;
188 bool TouchFile(const FilePath& path,
189 const base::Time& last_accessed,
190 const base::Time& last_modified) {
191 int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE_ATTRIBUTES;
193 #if defined(OS_WIN)
194 // On Windows, FILE_FLAG_BACKUP_SEMANTICS is needed to open a directory.
195 if (DirectoryExists(path))
196 flags |= base::PLATFORM_FILE_BACKUP_SEMANTICS;
197 #endif // OS_WIN
199 const base::PlatformFile file =
200 base::CreatePlatformFile(path, flags, NULL, NULL);
201 if (file != base::kInvalidPlatformFileValue) {
202 bool result = base::TouchPlatformFile(file, last_accessed, last_modified);
203 base::ClosePlatformFile(file);
204 return result;
207 return false;
210 bool SetLastModifiedTime(const FilePath& path,
211 const base::Time& last_modified) {
212 return TouchFile(path, last_modified, last_modified);
215 bool CloseFile(FILE* file) {
216 if (file == NULL)
217 return true;
218 return fclose(file) == 0;
221 bool TruncateFile(FILE* file) {
222 if (file == NULL)
223 return false;
224 long current_offset = ftell(file);
225 if (current_offset == -1)
226 return false;
227 #if defined(OS_WIN)
228 int fd = _fileno(file);
229 if (_chsize(fd, current_offset) != 0)
230 return false;
231 #else
232 int fd = fileno(file);
233 if (ftruncate(fd, current_offset) != 0)
234 return false;
235 #endif
236 return true;
239 int GetUniquePathNumber(
240 const FilePath& path,
241 const FilePath::StringType& suffix) {
242 bool have_suffix = !suffix.empty();
243 if (!PathExists(path) &&
244 (!have_suffix || !PathExists(FilePath(path.value() + suffix)))) {
245 return 0;
248 FilePath new_path;
249 for (int count = 1; count <= kMaxUniqueFiles; ++count) {
250 new_path =
251 path.InsertBeforeExtensionASCII(base::StringPrintf(" (%d)", count));
252 if (!PathExists(new_path) &&
253 (!have_suffix || !PathExists(FilePath(new_path.value() + suffix)))) {
254 return count;
258 return -1;
261 } // namespace file_util