Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / base / files / file_util.cc
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.
4
5 #include "base/files/file_util.h"
6
7 #if defined(OS_WIN)
8 #include <io.h>
9 #endif
10 #include <stdio.h>
11
12 #include <fstream>
13 #include <limits>
14
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"
22
23 namespace base {
24
25 namespace {
26
27 // 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.
32 static const int kMaxUniqueFiles = 100;
33
34 }  // namespace
35
36 int64 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
44 bool Move(const FilePath& from_path, const FilePath& to_path) {
45   if (from_path.ReferencesParent() || to_path.ReferencesParent())
46     return false;
47   return internal::MoveUnsafe(from_path, to_path);
48 }
49
50 bool 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);
54 }
55
56 bool ContentsEqual(const FilePath& filename1, const FilePath& filename2) {
57   // 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.
60   std::ifstream file1(filename1.value().c_str(),
61                       std::ios::in | std::ios::binary);
62   std::ifstream file2(filename2.value().c_str(),
63                       std::ios::in | std::ios::binary);
64
65   // 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
76     if ((file1.eof() != file2.eof()) ||
77         (file1.gcount() != file2.gcount()) ||
78         (memcmp(buffer1, buffer2, static_cast<size_t>(file1.gcount())))) {
79       file1.close();
80       file2.close();
81       return false;
82     }
83   } while (!file1.eof() || !file2.eof());
84
85   file1.close();
86   file2.close();
87   return true;
88 }
89
90 bool 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
130 bool ReadFileToString(const FilePath& path,
131                       std::string* contents,
132                       size_t max_size) {
133   if (contents)
134     contents->clear();
135   if (path.ReferencesParent())
136     return false;
137   FILE* file = OpenFile(path, "rb");
138   if (!file) {
139     return false;
140   }
141
142   const size_t kBufferSize = 1 << 16;
143   scoped_ptr<char[]> buf(new char[kBufferSize]);
144   size_t len;
145   size_t size = 0;
146   bool read_status = true;
147
148   // Many files supplied in |path| have incorrect size (proc files etc).
149   // Hence, the file is read sequentially as opposed to a one-shot read.
150   while ((len = fread(buf.get(), 1, kBufferSize, file)) > 0) {
151     if (contents)
152       contents->append(buf.get(), std::min(len, max_size - size));
153
154     if ((max_size - size) < len) {
155       read_status = false;
156       break;
157     }
158
159     size += len;
160   }
161   read_status = read_status && !ferror(file);
162   CloseFile(file);
163
164   return read_status;
165 }
166
167 bool ReadFileToString(const FilePath& path, std::string* contents) {
168   return ReadFileToString(path, contents, std::numeric_limits<size_t>::max());
169 }
170
171 bool IsDirectoryEmpty(const FilePath& dir_path) {
172   FileEnumerator files(dir_path, false,
173       FileEnumerator::FILES | FileEnumerator::DIRECTORIES);
174   if (files.Next().empty())
175     return true;
176   return false;
177 }
178
179 FILE* CreateAndOpenTemporaryFile(FilePath* path) {
180   FilePath directory;
181   if (!GetTempDir(&directory))
182     return NULL;
183
184   return CreateAndOpenTemporaryFileInDir(directory, path);
185 }
186
187 bool CreateDirectory(const FilePath& full_path) {
188   return CreateDirectoryAndGetError(full_path, NULL);
189 }
190
191 bool GetFileSize(const FilePath& file_path, int64* file_size) {
192   File::Info info;
193   if (!GetFileInfo(file_path, &info))
194     return false;
195   *file_size = info.size;
196   return true;
197 }
198
199 bool TouchFile(const FilePath& path,
200                const Time& last_accessed,
201                const Time& last_modified) {
202   int flags = File::FLAG_OPEN | File::FLAG_WRITE_ATTRIBUTES;
203
204 #if defined(OS_WIN)
205   // On Windows, FILE_FLAG_BACKUP_SEMANTICS is needed to open a directory.
206   if (DirectoryExists(path))
207     flags |= File::FLAG_BACKUP_SEMANTICS;
208 #endif  // OS_WIN
209
210   File file(path, flags);
211   if (!file.IsValid())
212     return false;
213
214   return file.SetTimes(last_accessed, last_modified);
215 }
216
217 bool CloseFile(FILE* file) {
218   if (file == NULL)
219     return true;
220   return fclose(file) == 0;
221 }
222
223 bool TruncateFile(FILE* file) {
224   if (file == NULL)
225     return false;
226   long current_offset = ftell(file);
227   if (current_offset == -1)
228     return false;
229 #if defined(OS_WIN)
230   int fd = _fileno(file);
231   if (_chsize(fd, current_offset) != 0)
232     return false;
233 #else
234   int fd = fileno(file);
235   if (ftruncate(fd, current_offset) != 0)
236     return false;
237 #endif
238   return true;
239 }
240
241 int GetUniquePathNumber(const FilePath& path,
242                         const FilePath::StringType& suffix) {
243   bool have_suffix = !suffix.empty();
244   if (!PathExists(path) &&
245       (!have_suffix || !PathExists(FilePath(path.value() + suffix)))) {
246     return 0;
247   }
248
249   FilePath new_path;
250   for (int count = 1; count <= kMaxUniqueFiles; ++count) {
251     new_path = path.InsertBeforeExtensionASCII(StringPrintf(" (%d)", count));
252     if (!PathExists(new_path) &&
253         (!have_suffix || !PathExists(FilePath(new_path.value() + suffix)))) {
254       return count;
255     }
256   }
257
258   return -1;
259 }
260
261 }  // namespace base