[go: nahoru, domu]

blob: c1bf50abc45f720bca415d1bc56d5fb9bf35abda [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>
kaliamoorthi@chromium.org0710fdd2014-02-18 16:31:5113#include <limits>
initial.commitd7cae122008-07-26 21:49:3814
brettw@chromium.org25a4c1c2013-06-08 04:53:3615#include "base/files/file_enumerator.h"
brettw@chromium.org57999812013-02-24 05:40:5216#include "base/files/file_path.h"
initial.commitd7cae122008-07-26 21:49:3817#include "base/logging.h"
tfarina@chromium.orgeb62f7262013-03-30 14:29:0018#include "base/strings/string_piece.h"
avi@chromium.org251cd6e52013-06-11 13:36:3719#include "base/strings/string_util.h"
20#include "base/strings/stringprintf.h"
avi@chromium.orga4ea1f12013-06-07 18:37:0721#include "base/strings/utf_string_conversions.h"
estade@chromium.orgb9e04f02008-11-27 04:03:5722
brettw@chromium.org0408c752013-06-22 22:15:4623namespace base {
brettw@chromium.org04af979a2013-02-16 04:12:2624
estade@chromium.orgceeb87e2008-12-04 20:46:0625namespace {
26
jam@chromium.orge285afa2012-01-31 23:16:3927// The maximum number of 'uniquified' files we will try to create.
28// This is used when the filename we're trying to download is already in use,
29// so we create a new unique filename by appending " (nnn)" before the
30// extension, where 1 <= nnn <= kMaxUniqueFiles.
31// Also used by code that cleans up said files.
32static const int kMaxUniqueFiles = 100;
estade@chromium.orgceeb87e2008-12-04 20:46:0633
willchan@chromium.orgc145cbdd2009-04-24 17:44:3934} // namespace
estade@chromium.orgceeb87e2008-12-04 20:46:0635
brettw@chromium.org0408c752013-06-22 22:15:4636int64 ComputeDirectorySize(const FilePath& root_path) {
37 int64 running_size = 0;
38 FileEnumerator file_iter(root_path, true, FileEnumerator::FILES);
39 while (!file_iter.Next().empty())
40 running_size += file_iter.GetInfo().GetSize();
41 return running_size;
42}
43
brettw@chromium.org5553d5b2013-07-01 23:07:3644bool Move(const FilePath& from_path, const FilePath& to_path) {
45 if (from_path.ReferencesParent() || to_path.ReferencesParent())
46 return false;
brettw@chromium.orgf0ff2ad2013-07-09 17:42:2647 return internal::MoveUnsafe(from_path, to_path);
48}
49
50bool CopyFile(const FilePath& from_path, const FilePath& to_path) {
51 if (from_path.ReferencesParent() || to_path.ReferencesParent())
52 return false;
53 return internal::CopyFileUnsafe(from_path, to_path);
brettw@chromium.org5553d5b2013-07-01 23:07:3654}
55
evanm@google.com640517f2008-10-30 23:54:0456bool ContentsEqual(const FilePath& filename1, const FilePath& filename2) {
initial.commitd7cae122008-07-26 21:49:3857 // We open the file in binary format even if they are text files because
58 // we are just comparing that bytes are exactly same in both files and not
59 // doing anything smart with text formatting.
evanm@google.com640517f2008-10-30 23:54:0460 std::ifstream file1(filename1.value().c_str(),
erikkay@google.com5af2edb92008-08-08 20:16:0861 std::ios::in | std::ios::binary);
evanm@google.com640517f2008-10-30 23:54:0462 std::ifstream file2(filename2.value().c_str(),
erikkay@google.com5af2edb92008-08-08 20:16:0863 std::ios::in | std::ios::binary);
estade@chromium.orgb9e04f02008-11-27 04:03:5764
initial.commitd7cae122008-07-26 21:49:3865 // Even if both files aren't openable (and thus, in some sense, "equal"),
66 // any unusable file yields a result of "false".
67 if (!file1.is_open() || !file2.is_open())
68 return false;
69
70 const int BUFFER_SIZE = 2056;
71 char buffer1[BUFFER_SIZE], buffer2[BUFFER_SIZE];
72 do {
73 file1.read(buffer1, BUFFER_SIZE);
74 file2.read(buffer2, BUFFER_SIZE);
75
mark@chromium.orgb81637c32009-06-26 21:17:2476 if ((file1.eof() != file2.eof()) ||
initial.commitd7cae122008-07-26 21:49:3877 (file1.gcount() != file2.gcount()) ||
78 (memcmp(buffer1, buffer2, file1.gcount()))) {
79 file1.close();
80 file2.close();
81 return false;
82 }
mark@chromium.orgb81637c32009-06-26 21:17:2483 } while (!file1.eof() || !file2.eof());
initial.commitd7cae122008-07-26 21:49:3884
85 file1.close();
86 file2.close();
87 return true;
88}
89
mark@chromium.orgb81637c32009-06-26 21:17:2490bool TextContentsEqual(const FilePath& filename1, const FilePath& filename2) {
91 std::ifstream file1(filename1.value().c_str(), std::ios::in);
92 std::ifstream file2(filename2.value().c_str(), std::ios::in);
93
94 // Even if both files aren't openable (and thus, in some sense, "equal"),
95 // any unusable file yields a result of "false".
96 if (!file1.is_open() || !file2.is_open())
97 return false;
98
99 do {
100 std::string line1, line2;
101 getline(file1, line1);
102 getline(file2, line2);
103
104 // Check for mismatched EOF states, or any error state.
105 if ((file1.eof() != file2.eof()) ||
106 file1.bad() || file2.bad()) {
107 return false;
108 }
109
110 // Trim all '\r' and '\n' characters from the end of the line.
111 std::string::size_type end1 = line1.find_last_not_of("\r\n");
112 if (end1 == std::string::npos)
113 line1.clear();
114 else if (end1 + 1 < line1.length())
115 line1.erase(end1 + 1);
116
117 std::string::size_type end2 = line2.find_last_not_of("\r\n");
118 if (end2 == std::string::npos)
119 line2.clear();
120 else if (end2 + 1 < line2.length())
121 line2.erase(end2 + 1);
122
123 if (line1 != line2)
124 return false;
125 } while (!file1.eof() || !file2.eof());
126
127 return true;
128}
129
kaliamoorthi@chromium.org0710fdd2014-02-18 16:31:51130bool ReadFileToString(const FilePath& path,
131 std::string* contents,
132 size_t max_size) {
133 if (contents)
134 contents->clear();
cpu@chromium.org9fea5a92013-01-09 00:38:59135 if (path.ReferencesParent())
136 return false;
thakis@chromium.org7600d0b2013-12-08 21:43:30137 FILE* file = OpenFile(path, "rb");
mark@chromium.org836f1342008-10-01 17:40:13138 if (!file) {
initial.commitd7cae122008-07-26 21:49:38139 return false;
mark@chromium.org836f1342008-10-01 17:40:13140 }
initial.commitd7cae122008-07-26 21:49:38141
142 char buf[1 << 16];
143 size_t len;
kaliamoorthi@chromium.org0710fdd2014-02-18 16:31:51144 size_t size = 0;
145 bool read_status = true;
146
147 // Many files supplied in |path| have incorrect size (proc files etc).
148 // Hence, the file is read sequentially as opposed to a one-shot read.
initial.commitd7cae122008-07-26 21:49:38149 while ((len = fread(buf, 1, sizeof(buf), file)) > 0) {
evan@chromium.org4e074bae2010-05-19 11:07:55150 if (contents)
kaliamoorthi@chromium.org0710fdd2014-02-18 16:31:51151 contents->append(buf, std::min(len, max_size - size));
152
153 if ((max_size - size) < len) {
154 read_status = false;
155 break;
156 }
157
158 size += len;
initial.commitd7cae122008-07-26 21:49:38159 }
thakis@chromium.org7600d0b2013-12-08 21:43:30160 CloseFile(file);
initial.commitd7cae122008-07-26 21:49:38161
kaliamoorthi@chromium.org0710fdd2014-02-18 16:31:51162 return read_status;
163}
164
165bool ReadFileToString(const FilePath& path, std::string* contents) {
166 return ReadFileToString(path, contents, std::numeric_limits<size_t>::max());
initial.commitd7cae122008-07-26 21:49:38167}
168
brettw@chromium.orgfb4bcfa32013-12-02 18:55:49169bool IsDirectoryEmpty(const FilePath& dir_path) {
170 FileEnumerator files(dir_path, false,
171 FileEnumerator::FILES | FileEnumerator::DIRECTORIES);
172 if (files.Next().empty())
173 return true;
174 return false;
175}
176
brettw@chromium.org03d9afc02013-12-03 17:55:52177FILE* CreateAndOpenTemporaryFile(FilePath* path) {
178 FilePath directory;
179 if (!GetTempDir(&directory))
180 return NULL;
181
182 return CreateAndOpenTemporaryFileInDir(directory, path);
183}
184
brettw@chromium.org426d1c92013-12-03 20:08:54185bool CreateDirectory(const FilePath& full_path) {
186 return CreateDirectoryAndGetError(full_path, NULL);
187}
188
brettw@chromium.org56285702013-12-04 18:22:49189bool GetFileSize(const FilePath& file_path, int64* file_size) {
rvargas@chromium.org54124ed02014-01-07 10:06:58190 File::Info info;
brettw@chromium.org9eae4e62013-12-04 20:56:49191 if (!GetFileInfo(file_path, &info))
brettw@chromium.org56285702013-12-04 18:22:49192 return false;
193 *file_size = info.size;
194 return true;
195}
196
brettw@chromium.orgc0d508162013-12-04 22:49:00197bool TouchFile(const FilePath& path,
198 const Time& last_accessed,
199 const Time& last_modified) {
rvargas@chromium.org54124ed02014-01-07 10:06:58200 int flags = File::FLAG_OPEN | File::FLAG_WRITE_ATTRIBUTES;
brettw@chromium.orgc0d508162013-12-04 22:49:00201
202#if defined(OS_WIN)
203 // On Windows, FILE_FLAG_BACKUP_SEMANTICS is needed to open a directory.
204 if (DirectoryExists(path))
rvargas@chromium.org54124ed02014-01-07 10:06:58205 flags |= File::FLAG_BACKUP_SEMANTICS;
brettw@chromium.orgc0d508162013-12-04 22:49:00206#endif // OS_WIN
207
rvargas@chromium.org54124ed02014-01-07 10:06:58208 File file(path, flags);
209 if (!file.IsValid())
210 return false;
brettw@chromium.orgc0d508162013-12-04 22:49:00211
rvargas@chromium.org54124ed02014-01-07 10:06:58212 return file.SetTimes(last_accessed, last_modified);
brettw@chromium.orgc0d508162013-12-04 22:49:00213}
214
mark@chromium.org836f1342008-10-01 17:40:13215bool CloseFile(FILE* file) {
sidchat@google.coma1a19502008-10-21 17:14:45216 if (file == NULL)
217 return true;
mark@chromium.org836f1342008-10-01 17:40:13218 return fclose(file) == 0;
jeremy@chromium.org6e01dae2009-01-27 17:13:02219}
220
jeremy@chromium.orgc2c998c2009-01-27 19:08:39221bool 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;
237}
brettw@chromium.org5a6ddb12013-12-07 00:04:53238
brettw@chromium.orga26f4ae2014-03-13 17:26:21239int GetUniquePathNumber(const FilePath& path,
240 const FilePath::StringType& suffix) {
jam@chromium.orge285afa2012-01-31 23:16:39241 bool have_suffix = !suffix.empty();
242 if (!PathExists(path) &&
243 (!have_suffix || !PathExists(FilePath(path.value() + suffix)))) {
244 return 0;
245 }
246
247 FilePath new_path;
248 for (int count = 1; count <= kMaxUniqueFiles; ++count) {
brettw@chromium.orga26f4ae2014-03-13 17:26:21249 new_path = path.InsertBeforeExtensionASCII(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.orga26f4ae2014-03-13 17:26:21259} // namespace base