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"
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"
25 #if !defined(OS_NACL_NONSFI)
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;
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();
45 bool Move(const FilePath
& from_path
, const FilePath
& to_path
) {
46 if (from_path
.ReferencesParent() || to_path
.ReferencesParent())
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())
65 const int BUFFER_SIZE
= 2056;
66 char buffer1
[BUFFER_SIZE
], buffer2
[BUFFER_SIZE
];
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())))) {
78 } while (!file1
.eof() || !file2
.eof());
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())
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()) {
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
)
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
)
115 else if (end2
+ 1 < line2
.length())
116 line2
.erase(end2
+ 1);
120 } while (!file1
.eof() || !file2
.eof());
124 #endif // !defined(OS_NACL_NONSFI)
126 bool ReadFileToString(const FilePath
& path
,
127 std::string
* contents
,
131 if (path
.ReferencesParent())
133 FILE* file
= OpenFile(path
, "rb");
138 const size_t kBufferSize
= 1 << 16;
139 scoped_ptr
<char[]> buf(new char[kBufferSize
]);
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) {
148 contents
->append(buf
.get(), std::min(len
, max_size
- size
));
150 if ((max_size
- size
) < len
) {
157 read_status
= read_status
&& !ferror(file
);
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())
176 FILE* CreateAndOpenTemporaryFile(FilePath
* path
) {
178 if (!GetTempDir(&directory
))
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
) {
190 if (!GetFileInfo(file_path
, &info
))
192 *file_size
= info
.size
;
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
;
202 // On Windows, FILE_FLAG_BACKUP_SEMANTICS is needed to open a directory.
203 if (DirectoryExists(path
))
204 flags
|= File::FLAG_BACKUP_SEMANTICS
;
207 File
file(path
, flags
);
211 return file
.SetTimes(last_accessed
, last_modified
);
213 #endif // !defined(OS_NACL_NONSFI)
215 bool CloseFile(FILE* file
) {
218 return fclose(file
) == 0;
221 #if !defined(OS_NACL_NONSFI)
222 bool TruncateFile(FILE* file
) {
225 long current_offset
= ftell(file
);
226 if (current_offset
== -1)
229 int fd
= _fileno(file
);
230 if (_chsize(fd
, current_offset
) != 0)
233 int fd
= fileno(file
);
234 if (ftruncate(fd
, current_offset
) != 0)
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
)))) {
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
)))) {
259 #endif // !defined(OS_NACL_NONSFI)