QUIC - cleanup changes to sync chromium tree with internal source.
[chromium-blink-merge.git] / base / files / file_util.cc
blob4b6b8886d8ad5d8bc0fd4855b10c97db52420d2e
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/files/file_util.h"
7 #if defined(OS_WIN)
8 #include <io.h>
9 #endif
10 #include <stdio.h>
12 #include <fstream>
13 #include <limits>
15 #include "base/files/file_enumerator.h"
16 #include "base/files/file_path.h"
17 #include "base/logging.h"
18 #include "base/strings/string_piece.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/stringprintf.h"
21 #include "base/strings/utf_string_conversions.h"
23 namespace base {
25 #if !defined(OS_NACL_NONSFI)
26 namespace {
28 // The maximum number of 'uniquified' files we will try to create.
29 // This is used when the filename we're trying to download is already in use,
30 // so we create a new unique filename by appending " (nnn)" before the
31 // extension, where 1 <= nnn <= kMaxUniqueFiles.
32 // Also used by code that cleans up said files.
33 static const int kMaxUniqueFiles = 100;
35 } // namespace
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 ContentsEqual(const FilePath& filename1, const FilePath& filename2) {
52 // We open the file in binary format even if they are text files because
53 // we are just comparing that bytes are exactly same in both files and not
54 // doing anything smart with text formatting.
55 std::ifstream file1(filename1.value().c_str(),
56 std::ios::in | std::ios::binary);
57 std::ifstream file2(filename2.value().c_str(),
58 std::ios::in | std::ios::binary);
60 // Even if both files aren't openable (and thus, in some sense, "equal"),
61 // any unusable file yields a result of "false".
62 if (!file1.is_open() || !file2.is_open())
63 return false;
65 const int BUFFER_SIZE = 2056;
66 char buffer1[BUFFER_SIZE], buffer2[BUFFER_SIZE];
67 do {
68 file1.read(buffer1, BUFFER_SIZE);
69 file2.read(buffer2, BUFFER_SIZE);
71 if ((file1.eof() != file2.eof()) ||
72 (file1.gcount() != file2.gcount()) ||
73 (memcmp(buffer1, buffer2, static_cast<size_t>(file1.gcount())))) {
74 file1.close();
75 file2.close();
76 return false;
78 } while (!file1.eof() || !file2.eof());
80 file1.close();
81 file2.close();
82 return true;
85 bool TextContentsEqual(const FilePath& filename1, const FilePath& filename2) {
86 std::ifstream file1(filename1.value().c_str(), std::ios::in);
87 std::ifstream file2(filename2.value().c_str(), std::ios::in);
89 // Even if both files aren't openable (and thus, in some sense, "equal"),
90 // any unusable file yields a result of "false".
91 if (!file1.is_open() || !file2.is_open())
92 return false;
94 do {
95 std::string line1, line2;
96 getline(file1, line1);
97 getline(file2, line2);
99 // Check for mismatched EOF states, or any error state.
100 if ((file1.eof() != file2.eof()) ||
101 file1.bad() || file2.bad()) {
102 return false;
105 // Trim all '\r' and '\n' characters from the end of the line.
106 std::string::size_type end1 = line1.find_last_not_of("\r\n");
107 if (end1 == std::string::npos)
108 line1.clear();
109 else if (end1 + 1 < line1.length())
110 line1.erase(end1 + 1);
112 std::string::size_type end2 = line2.find_last_not_of("\r\n");
113 if (end2 == std::string::npos)
114 line2.clear();
115 else if (end2 + 1 < line2.length())
116 line2.erase(end2 + 1);
118 if (line1 != line2)
119 return false;
120 } while (!file1.eof() || !file2.eof());
122 return true;
124 #endif // !defined(OS_NACL_NONSFI)
126 bool ReadFileToString(const FilePath& path,
127 std::string* contents,
128 size_t max_size) {
129 if (contents)
130 contents->clear();
131 if (path.ReferencesParent())
132 return false;
133 FILE* file = OpenFile(path, "rb");
134 if (!file) {
135 return false;
138 const size_t kBufferSize = 1 << 16;
139 scoped_ptr<char[]> buf(new char[kBufferSize]);
140 size_t len;
141 size_t size = 0;
142 bool read_status = true;
144 // Many files supplied in |path| have incorrect size (proc files etc).
145 // Hence, the file is read sequentially as opposed to a one-shot read.
146 while ((len = fread(buf.get(), 1, kBufferSize, file)) > 0) {
147 if (contents)
148 contents->append(buf.get(), std::min(len, max_size - size));
150 if ((max_size - size) < len) {
151 read_status = false;
152 break;
155 size += len;
157 read_status = read_status && !ferror(file);
158 CloseFile(file);
160 return read_status;
163 bool ReadFileToString(const FilePath& path, std::string* contents) {
164 return ReadFileToString(path, contents, std::numeric_limits<size_t>::max());
167 #if !defined(OS_NACL_NONSFI)
168 bool IsDirectoryEmpty(const FilePath& dir_path) {
169 FileEnumerator files(dir_path, false,
170 FileEnumerator::FILES | FileEnumerator::DIRECTORIES);
171 if (files.Next().empty())
172 return true;
173 return false;
176 FILE* CreateAndOpenTemporaryFile(FilePath* path) {
177 FilePath directory;
178 if (!GetTempDir(&directory))
179 return NULL;
181 return CreateAndOpenTemporaryFileInDir(directory, path);
184 bool CreateDirectory(const FilePath& full_path) {
185 return CreateDirectoryAndGetError(full_path, NULL);
188 bool GetFileSize(const FilePath& file_path, int64* file_size) {
189 File::Info info;
190 if (!GetFileInfo(file_path, &info))
191 return false;
192 *file_size = info.size;
193 return true;
196 bool TouchFile(const FilePath& path,
197 const Time& last_accessed,
198 const Time& last_modified) {
199 int flags = File::FLAG_OPEN | File::FLAG_WRITE_ATTRIBUTES;
201 #if defined(OS_WIN)
202 // On Windows, FILE_FLAG_BACKUP_SEMANTICS is needed to open a directory.
203 if (DirectoryExists(path))
204 flags |= File::FLAG_BACKUP_SEMANTICS;
205 #endif // OS_WIN
207 File file(path, flags);
208 if (!file.IsValid())
209 return false;
211 return file.SetTimes(last_accessed, last_modified);
213 #endif // !defined(OS_NACL_NONSFI)
215 bool CloseFile(FILE* file) {
216 if (file == NULL)
217 return true;
218 return fclose(file) == 0;
221 #if !defined(OS_NACL_NONSFI)
222 bool TruncateFile(FILE* file) {
223 if (file == NULL)
224 return false;
225 long current_offset = ftell(file);
226 if (current_offset == -1)
227 return false;
228 #if defined(OS_WIN)
229 int fd = _fileno(file);
230 if (_chsize(fd, current_offset) != 0)
231 return false;
232 #else
233 int fd = fileno(file);
234 if (ftruncate(fd, current_offset) != 0)
235 return false;
236 #endif
237 return true;
240 int GetUniquePathNumber(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 = path.InsertBeforeExtensionASCII(StringPrintf(" (%d)", count));
251 if (!PathExists(new_path) &&
252 (!have_suffix || !PathExists(FilePath(new_path.value() + suffix)))) {
253 return count;
257 return -1;
259 #endif // !defined(OS_NACL_NONSFI)
261 } // namespace base