[go: nahoru, domu]

blob: 6140ceae28ab5980395ce2c0db96eeed76388e0f [file] [log] [blame]
thestig@chromium.orgb2f28d22012-03-03 01:54:351// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commitd7cae122008-07-26 21:49:384
5#include "base/file_util.h"
6
jeremy@chromium.orgc2c998c2009-01-27 19:08:397#if defined(OS_WIN)
8#include <io.h>
9#endif
mark@chromium.org836f1342008-10-01 17:40:1310#include <stdio.h>
11
initial.commitd7cae122008-07-26 21:49:3812#include <fstream>
initial.commitd7cae122008-07-26 21:49:3813
brettw@chromium.org25a4c1c2013-06-08 04:53:3614#include "base/files/file_enumerator.h"
brettw@chromium.org57999812013-02-24 05:40:5215#include "base/files/file_path.h"
initial.commitd7cae122008-07-26 21:49:3816#include "base/logging.h"
tfarina@chromium.orgeb62f7262013-03-30 14:29:0017#include "base/strings/string_piece.h"
avi@chromium.org251cd6e52013-06-11 13:36:3718#include "base/strings/string_util.h"
19#include "base/strings/stringprintf.h"
avi@chromium.orga4ea1f12013-06-07 18:37:0720#include "base/strings/utf_string_conversions.h"
estade@chromium.orgb9e04f02008-11-27 04:03:5721
brettw@chromium.org0408c752013-06-22 22:15:4622namespace base {
brettw@chromium.org04af979a2013-02-16 04:12:2623
estade@chromium.orgceeb87e2008-12-04 20:46:0624namespace {
25
jam@chromium.orge285afa2012-01-31 23:16:3926// 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.
31static const int kMaxUniqueFiles = 100;
estade@chromium.orgceeb87e2008-12-04 20:46:0632
willchan@chromium.orgc145cbdd2009-04-24 17:44:3933} // namespace
estade@chromium.orgceeb87e2008-12-04 20:46:0634
brettw@chromium.org0408c752013-06-22 22:15:4635int64 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;
41}
42
brettw@chromium.org5553d5b2013-07-01 23:07:3643bool Move(const FilePath& from_path, const FilePath& to_path) {
44 if (from_path.ReferencesParent() || to_path.ReferencesParent())
45 return false;
brettw@chromium.orgf0ff2ad2013-07-09 17:42:2646 return internal::MoveUnsafe(from_path, to_path);
47}
48
49bool 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);
brettw@chromium.org5553d5b2013-07-01 23:07:3653}
54
evanm@google.com640517f2008-10-30 23:54:0455bool ContentsEqual(const FilePath& filename1, const FilePath& filename2) {
initial.commitd7cae122008-07-26 21:49:3856 // 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.
evanm@google.com640517f2008-10-30 23:54:0459 std::ifstream file1(filename1.value().c_str(),
erikkay@google.com5af2edb92008-08-08 20:16:0860 std::ios::in | std::ios::binary);
evanm@google.com640517f2008-10-30 23:54:0461 std::ifstream file2(filename2.value().c_str(),
erikkay@google.com5af2edb92008-08-08 20:16:0862 std::ios::in | std::ios::binary);
estade@chromium.orgb9e04f02008-11-27 04:03:5763
initial.commitd7cae122008-07-26 21:49:3864 // 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;
68
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);
74
mark@chromium.orgb81637c32009-06-26 21:17:2475 if ((file1.eof() != file2.eof()) ||
initial.commitd7cae122008-07-26 21:49:3876 (file1.gcount() != file2.gcount()) ||
77 (memcmp(buffer1, buffer2, file1.gcount()))) {
78 file1.close();
79 file2.close();
80 return false;
81 }
mark@chromium.orgb81637c32009-06-26 21:17:2482 } while (!file1.eof() || !file2.eof());
initial.commitd7cae122008-07-26 21:49:3883
84 file1.close();
85 file2.close();
86 return true;
87}
88
mark@chromium.orgb81637c32009-06-26 21:17:2489bool 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);
92
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;
97
98 do {
99 std::string line1, line2;
100 getline(file1, line1);
101 getline(file2, line2);
102
103 // Check for mismatched EOF states, or any error state.
104 if ((file1.eof() != file2.eof()) ||
105 file1.bad() || file2.bad()) {
106 return false;
107 }
108
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);
115
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);
121
122 if (line1 != line2)
123 return false;
124 } while (!file1.eof() || !file2.eof());
125
126 return true;
127}
128
erikkay@google.com3c5281022009-01-28 00:22:46129bool ReadFileToString(const FilePath& path, std::string* contents) {
cpu@chromium.org9fea5a92013-01-09 00:38:59130 if (path.ReferencesParent())
131 return false;
brettw@chromium.org82f84b92013-08-30 18:23:50132 FILE* file = file_util::OpenFile(path, "rb");
mark@chromium.org836f1342008-10-01 17:40:13133 if (!file) {
initial.commitd7cae122008-07-26 21:49:38134 return false;
mark@chromium.org836f1342008-10-01 17:40:13135 }
initial.commitd7cae122008-07-26 21:49:38136
137 char buf[1 << 16];
138 size_t len;
139 while ((len = fread(buf, 1, sizeof(buf), file)) > 0) {
evan@chromium.org4e074bae2010-05-19 11:07:55140 if (contents)
141 contents->append(buf, len);
initial.commitd7cae122008-07-26 21:49:38142 }
brettw@chromium.org82f84b92013-08-30 18:23:50143 file_util::CloseFile(file);
initial.commitd7cae122008-07-26 21:49:38144
145 return true;
initial.commitd7cae122008-07-26 21:49:38146}
147
brettw@chromium.orgfb4bcfa32013-12-02 18:55:49148bool IsDirectoryEmpty(const FilePath& dir_path) {
149 FileEnumerator files(dir_path, false,
150 FileEnumerator::FILES | FileEnumerator::DIRECTORIES);
151 if (files.Next().empty())
152 return true;
153 return false;
154}
155
brettw@chromium.org03d9afc02013-12-03 17:55:52156FILE* CreateAndOpenTemporaryFile(FilePath* path) {
157 FilePath directory;
158 if (!GetTempDir(&directory))
159 return NULL;
160
161 return CreateAndOpenTemporaryFileInDir(directory, path);
162}
163
brettw@chromium.org426d1c92013-12-03 20:08:54164bool CreateDirectory(const FilePath& full_path) {
165 return CreateDirectoryAndGetError(full_path, NULL);
166}
167
brettw@chromium.org56285702013-12-04 18:22:49168bool GetFileSize(const FilePath& file_path, int64* file_size) {
169 PlatformFileInfo info;
brettw@chromium.org9eae4e62013-12-04 20:56:49170 if (!GetFileInfo(file_path, &info))
brettw@chromium.org56285702013-12-04 18:22:49171 return false;
172 *file_size = info.size;
173 return true;
174}
175
brettw@chromium.org82f84b92013-08-30 18:23:50176} // namespace base
177
178// -----------------------------------------------------------------------------
179
180namespace file_util {
181
182using base::FileEnumerator;
183using base::FilePath;
brettw@chromium.org82f84b92013-08-30 18:23:50184using base::kMaxUniqueFiles;
darin@google.comf5e3da4d2008-09-26 01:04:08185
dumi@chromium.org507fb9a2010-09-23 23:28:22186bool TouchFile(const FilePath& path,
187 const base::Time& last_accessed,
188 const base::Time& last_modified) {
nhiroki@chromium.org307a825a2012-11-01 11:48:52189 int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE_ATTRIBUTES;
190
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
196
197 const base::PlatformFile file =
198 base::CreatePlatformFile(path, flags, NULL, NULL);
dumi@chromium.org507fb9a2010-09-23 23:28:22199 if (file != base::kInvalidPlatformFileValue) {
200 bool result = base::TouchPlatformFile(file, last_accessed, last_modified);
201 base::ClosePlatformFile(file);
202 return result;
203 }
204
205 return false;
206}
207
208bool SetLastModifiedTime(const FilePath& path,
209 const base::Time& last_modified) {
210 return TouchFile(path, last_modified, last_modified);
211}
212
mark@chromium.org836f1342008-10-01 17:40:13213bool CloseFile(FILE* file) {
sidchat@google.coma1a19502008-10-21 17:14:45214 if (file == NULL)
215 return true;
mark@chromium.org836f1342008-10-01 17:40:13216 return fclose(file) == 0;
jeremy@chromium.org6e01dae2009-01-27 17:13:02217}
218
jeremy@chromium.orgc2c998c2009-01-27 19:08:39219bool 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;
235}
236
jam@chromium.orge285afa2012-01-31 23:16:39237int 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;
244 }
245
246 FilePath new_path;
247 for (int count = 1; count <= kMaxUniqueFiles; ++count) {
groby@chromium.org7d3cbc92013-03-18 22:33:04248 new_path =
249 path.InsertBeforeExtensionASCII(base::StringPrintf(" (%d)", count));
jam@chromium.orge285afa2012-01-31 23:16:39250 if (!PathExists(new_path) &&
251 (!have_suffix || !PathExists(FilePath(new_path.value() + suffix)))) {
252 return count;
253 }
254 }
255
256 return -1;
aa@chromium.orgee5c29da2009-01-09 22:14:27257}
258
brettw@chromium.org0408c752013-06-22 22:15:46259} // namespace file_util