[go: nahoru, domu]

blob: 31693704d6761e414ecc34b33809a15e03b21b1c [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
brettw@chromium.orge3177dd52014-08-13 20:22:145#include "base/files/file_util.h"
initial.commitd7cae122008-07-26 21:49:386
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"
avi543540e2015-12-24 05:15:3222#include "build/build_config.h"
estade@chromium.orgb9e04f02008-11-27 04:03:5723
brettw@chromium.org0408c752013-06-22 22:15:4624namespace base {
brettw@chromium.org04af979a2013-02-16 04:12:2625
hidehiko8fc7c822015-06-09 02:50:5726#if !defined(OS_NACL_NONSFI)
estade@chromium.orgceeb87e2008-12-04 20:46:0627namespace {
28
jam@chromium.orge285afa2012-01-31 23:16:3929// The maximum number of 'uniquified' files we will try to create.
30// This is used when the filename we're trying to download is already in use,
31// so we create a new unique filename by appending " (nnn)" before the
32// extension, where 1 <= nnn <= kMaxUniqueFiles.
33// Also used by code that cleans up said files.
34static const int kMaxUniqueFiles = 100;
estade@chromium.orgceeb87e2008-12-04 20:46:0635
willchan@chromium.orgc145cbdd2009-04-24 17:44:3936} // namespace
estade@chromium.orgceeb87e2008-12-04 20:46:0637
avi543540e2015-12-24 05:15:3238int64_t ComputeDirectorySize(const FilePath& root_path) {
39 int64_t running_size = 0;
brettw@chromium.org0408c752013-06-22 22:15:4640 FileEnumerator file_iter(root_path, true, FileEnumerator::FILES);
41 while (!file_iter.Next().empty())
42 running_size += file_iter.GetInfo().GetSize();
43 return running_size;
44}
45
brettw@chromium.org5553d5b2013-07-01 23:07:3646bool Move(const FilePath& from_path, const FilePath& to_path) {
47 if (from_path.ReferencesParent() || to_path.ReferencesParent())
48 return false;
brettw@chromium.orgf0ff2ad2013-07-09 17:42:2649 return internal::MoveUnsafe(from_path, to_path);
50}
51
evanm@google.com640517f2008-10-30 23:54:0452bool ContentsEqual(const FilePath& filename1, const FilePath& filename2) {
initial.commitd7cae122008-07-26 21:49:3853 // We open the file in binary format even if they are text files because
54 // we are just comparing that bytes are exactly same in both files and not
55 // doing anything smart with text formatting.
evanm@google.com640517f2008-10-30 23:54:0456 std::ifstream file1(filename1.value().c_str(),
erikkay@google.com5af2edb92008-08-08 20:16:0857 std::ios::in | std::ios::binary);
evanm@google.com640517f2008-10-30 23:54:0458 std::ifstream file2(filename2.value().c_str(),
erikkay@google.com5af2edb92008-08-08 20:16:0859 std::ios::in | std::ios::binary);
estade@chromium.orgb9e04f02008-11-27 04:03:5760
initial.commitd7cae122008-07-26 21:49:3861 // Even if both files aren't openable (and thus, in some sense, "equal"),
62 // any unusable file yields a result of "false".
63 if (!file1.is_open() || !file2.is_open())
64 return false;
65
66 const int BUFFER_SIZE = 2056;
67 char buffer1[BUFFER_SIZE], buffer2[BUFFER_SIZE];
68 do {
69 file1.read(buffer1, BUFFER_SIZE);
70 file2.read(buffer2, BUFFER_SIZE);
71
mark@chromium.orgb81637c32009-06-26 21:17:2472 if ((file1.eof() != file2.eof()) ||
initial.commitd7cae122008-07-26 21:49:3873 (file1.gcount() != file2.gcount()) ||
pkasting9cf9b942014-10-01 22:18:4374 (memcmp(buffer1, buffer2, static_cast<size_t>(file1.gcount())))) {
initial.commitd7cae122008-07-26 21:49:3875 file1.close();
76 file2.close();
77 return false;
78 }
mark@chromium.orgb81637c32009-06-26 21:17:2479 } while (!file1.eof() || !file2.eof());
initial.commitd7cae122008-07-26 21:49:3880
81 file1.close();
82 file2.close();
83 return true;
84}
85
mark@chromium.orgb81637c32009-06-26 21:17:2486bool TextContentsEqual(const FilePath& filename1, const FilePath& filename2) {
87 std::ifstream file1(filename1.value().c_str(), std::ios::in);
88 std::ifstream file2(filename2.value().c_str(), std::ios::in);
89
90 // Even if both files aren't openable (and thus, in some sense, "equal"),
91 // any unusable file yields a result of "false".
92 if (!file1.is_open() || !file2.is_open())
93 return false;
94
95 do {
96 std::string line1, line2;
97 getline(file1, line1);
98 getline(file2, line2);
99
100 // Check for mismatched EOF states, or any error state.
101 if ((file1.eof() != file2.eof()) ||
102 file1.bad() || file2.bad()) {
103 return false;
104 }
105
106 // Trim all '\r' and '\n' characters from the end of the line.
107 std::string::size_type end1 = line1.find_last_not_of("\r\n");
108 if (end1 == std::string::npos)
109 line1.clear();
110 else if (end1 + 1 < line1.length())
111 line1.erase(end1 + 1);
112
113 std::string::size_type end2 = line2.find_last_not_of("\r\n");
114 if (end2 == std::string::npos)
115 line2.clear();
116 else if (end2 + 1 < line2.length())
117 line2.erase(end2 + 1);
118
119 if (line1 != line2)
120 return false;
121 } while (!file1.eof() || !file2.eof());
122
123 return true;
124}
hidehiko8fc7c822015-06-09 02:50:57125#endif // !defined(OS_NACL_NONSFI)
mark@chromium.orgb81637c32009-06-26 21:17:24126
hashimoto6da2fef2016-02-24 03:39:58127bool ReadFileToStringWithMaxSize(const FilePath& path,
128 std::string* contents,
129 size_t max_size) {
kaliamoorthi@chromium.org0710fdd2014-02-18 16:31:51130 if (contents)
131 contents->clear();
cpu@chromium.org9fea5a92013-01-09 00:38:59132 if (path.ReferencesParent())
133 return false;
thakis@chromium.org7600d0b2013-12-08 21:43:30134 FILE* file = OpenFile(path, "rb");
mark@chromium.org836f1342008-10-01 17:40:13135 if (!file) {
initial.commitd7cae122008-07-26 21:49:38136 return false;
mark@chromium.org836f1342008-10-01 17:40:13137 }
initial.commitd7cae122008-07-26 21:49:38138
cpu9deb5752014-10-21 01:20:40139 const size_t kBufferSize = 1 << 16;
140 scoped_ptr<char[]> buf(new char[kBufferSize]);
initial.commitd7cae122008-07-26 21:49:38141 size_t len;
kaliamoorthi@chromium.org0710fdd2014-02-18 16:31:51142 size_t size = 0;
143 bool read_status = true;
144
145 // Many files supplied in |path| have incorrect size (proc files etc).
146 // Hence, the file is read sequentially as opposed to a one-shot read.
cpu9deb5752014-10-21 01:20:40147 while ((len = fread(buf.get(), 1, kBufferSize, file)) > 0) {
evan@chromium.org4e074bae2010-05-19 11:07:55148 if (contents)
cpu9deb5752014-10-21 01:20:40149 contents->append(buf.get(), std::min(len, max_size - size));
kaliamoorthi@chromium.org0710fdd2014-02-18 16:31:51150
151 if ((max_size - size) < len) {
152 read_status = false;
153 break;
154 }
155
156 size += len;
initial.commitd7cae122008-07-26 21:49:38157 }
tnagel@chromium.org731daa12014-05-01 10:40:51158 read_status = read_status && !ferror(file);
thakis@chromium.org7600d0b2013-12-08 21:43:30159 CloseFile(file);
initial.commitd7cae122008-07-26 21:49:38160
kaliamoorthi@chromium.org0710fdd2014-02-18 16:31:51161 return read_status;
162}
163
164bool ReadFileToString(const FilePath& path, std::string* contents) {
hashimoto6da2fef2016-02-24 03:39:58165 return ReadFileToStringWithMaxSize(path, contents,
166 std::numeric_limits<size_t>::max());
initial.commitd7cae122008-07-26 21:49:38167}
168
hidehiko8fc7c822015-06-09 02:50:57169#if !defined(OS_NACL_NONSFI)
brettw@chromium.orgfb4bcfa32013-12-02 18:55:49170bool IsDirectoryEmpty(const FilePath& dir_path) {
171 FileEnumerator files(dir_path, false,
172 FileEnumerator::FILES | FileEnumerator::DIRECTORIES);
173 if (files.Next().empty())
174 return true;
175 return false;
176}
177
brettw@chromium.org03d9afc02013-12-03 17:55:52178FILE* CreateAndOpenTemporaryFile(FilePath* path) {
179 FilePath directory;
180 if (!GetTempDir(&directory))
181 return NULL;
182
183 return CreateAndOpenTemporaryFileInDir(directory, path);
184}
185
brettw@chromium.org426d1c92013-12-03 20:08:54186bool CreateDirectory(const FilePath& full_path) {
187 return CreateDirectoryAndGetError(full_path, NULL);
188}
189
avi543540e2015-12-24 05:15:32190bool GetFileSize(const FilePath& file_path, int64_t* file_size) {
rvargas@chromium.org54124ed02014-01-07 10:06:58191 File::Info info;
brettw@chromium.org9eae4e62013-12-04 20:56:49192 if (!GetFileInfo(file_path, &info))
brettw@chromium.org56285702013-12-04 18:22:49193 return false;
194 *file_size = info.size;
195 return true;
196}
197
brettw@chromium.orgc0d508162013-12-04 22:49:00198bool TouchFile(const FilePath& path,
199 const Time& last_accessed,
200 const Time& last_modified) {
rvargas@chromium.org54124ed02014-01-07 10:06:58201 int flags = File::FLAG_OPEN | File::FLAG_WRITE_ATTRIBUTES;
brettw@chromium.orgc0d508162013-12-04 22:49:00202
203#if defined(OS_WIN)
204 // On Windows, FILE_FLAG_BACKUP_SEMANTICS is needed to open a directory.
205 if (DirectoryExists(path))
rvargas@chromium.org54124ed02014-01-07 10:06:58206 flags |= File::FLAG_BACKUP_SEMANTICS;
brettw@chromium.orgc0d508162013-12-04 22:49:00207#endif // OS_WIN
208
rvargas@chromium.org54124ed02014-01-07 10:06:58209 File file(path, flags);
210 if (!file.IsValid())
211 return false;
brettw@chromium.orgc0d508162013-12-04 22:49:00212
rvargas@chromium.org54124ed02014-01-07 10:06:58213 return file.SetTimes(last_accessed, last_modified);
brettw@chromium.orgc0d508162013-12-04 22:49:00214}
hidehiko8fc7c822015-06-09 02:50:57215#endif // !defined(OS_NACL_NONSFI)
brettw@chromium.orgc0d508162013-12-04 22:49:00216
mark@chromium.org836f1342008-10-01 17:40:13217bool CloseFile(FILE* file) {
sidchat@google.coma1a19502008-10-21 17:14:45218 if (file == NULL)
219 return true;
mark@chromium.org836f1342008-10-01 17:40:13220 return fclose(file) == 0;
jeremy@chromium.org6e01dae2009-01-27 17:13:02221}
222
hidehiko8fc7c822015-06-09 02:50:57223#if !defined(OS_NACL_NONSFI)
jeremy@chromium.orgc2c998c2009-01-27 19:08:39224bool TruncateFile(FILE* file) {
225 if (file == NULL)
226 return false;
227 long current_offset = ftell(file);
228 if (current_offset == -1)
229 return false;
230#if defined(OS_WIN)
231 int fd = _fileno(file);
232 if (_chsize(fd, current_offset) != 0)
233 return false;
234#else
235 int fd = fileno(file);
236 if (ftruncate(fd, current_offset) != 0)
237 return false;
238#endif
239 return true;
240}
brettw@chromium.org5a6ddb12013-12-07 00:04:53241
brettw@chromium.orga26f4ae2014-03-13 17:26:21242int GetUniquePathNumber(const FilePath& path,
243 const FilePath::StringType& suffix) {
jam@chromium.orge285afa2012-01-31 23:16:39244 bool have_suffix = !suffix.empty();
245 if (!PathExists(path) &&
246 (!have_suffix || !PathExists(FilePath(path.value() + suffix)))) {
247 return 0;
248 }
249
250 FilePath new_path;
251 for (int count = 1; count <= kMaxUniqueFiles; ++count) {
brettw@chromium.orga26f4ae2014-03-13 17:26:21252 new_path = path.InsertBeforeExtensionASCII(StringPrintf(" (%d)", count));
jam@chromium.orge285afa2012-01-31 23:16:39253 if (!PathExists(new_path) &&
254 (!have_suffix || !PathExists(FilePath(new_path.value() + suffix)))) {
255 return count;
256 }
257 }
258
259 return -1;
aa@chromium.orgee5c29da2009-01-09 22:14:27260}
hidehiko8fc7c822015-06-09 02:50:57261#endif // !defined(OS_NACL_NONSFI)
aa@chromium.orgee5c29da2009-01-09 22:14:27262
brettw@chromium.orga26f4ae2014-03-13 17:26:21263} // namespace base