1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/sandbox/chromium/base/file_util.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,264 @@ 1.4 +// Copyright (c) 2012 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#include "base/file_util.h" 1.9 + 1.10 +#if defined(OS_WIN) 1.11 +#include <io.h> 1.12 +#endif 1.13 +#include <stdio.h> 1.14 + 1.15 +#include <fstream> 1.16 + 1.17 +#include "base/files/file_enumerator.h" 1.18 +#include "base/files/file_path.h" 1.19 +#include "base/logging.h" 1.20 +#include "base/strings/string_piece.h" 1.21 +#include "base/strings/string_util.h" 1.22 +#include "base/strings/stringprintf.h" 1.23 +#include "base/strings/utf_string_conversions.h" 1.24 + 1.25 +namespace base { 1.26 + 1.27 +namespace { 1.28 + 1.29 +const FilePath::CharType kExtensionSeparator = FILE_PATH_LITERAL('.'); 1.30 + 1.31 +// The maximum number of 'uniquified' files we will try to create. 1.32 +// This is used when the filename we're trying to download is already in use, 1.33 +// so we create a new unique filename by appending " (nnn)" before the 1.34 +// extension, where 1 <= nnn <= kMaxUniqueFiles. 1.35 +// Also used by code that cleans up said files. 1.36 +static const int kMaxUniqueFiles = 100; 1.37 + 1.38 +} // namespace 1.39 + 1.40 +bool g_bug108724_debug = false; 1.41 + 1.42 +int64 ComputeDirectorySize(const FilePath& root_path) { 1.43 + int64 running_size = 0; 1.44 + FileEnumerator file_iter(root_path, true, FileEnumerator::FILES); 1.45 + while (!file_iter.Next().empty()) 1.46 + running_size += file_iter.GetInfo().GetSize(); 1.47 + return running_size; 1.48 +} 1.49 + 1.50 +bool Move(const FilePath& from_path, const FilePath& to_path) { 1.51 + if (from_path.ReferencesParent() || to_path.ReferencesParent()) 1.52 + return false; 1.53 + return internal::MoveUnsafe(from_path, to_path); 1.54 +} 1.55 + 1.56 +bool CopyFile(const FilePath& from_path, const FilePath& to_path) { 1.57 + if (from_path.ReferencesParent() || to_path.ReferencesParent()) 1.58 + return false; 1.59 + return internal::CopyFileUnsafe(from_path, to_path); 1.60 +} 1.61 + 1.62 +bool ContentsEqual(const FilePath& filename1, const FilePath& filename2) { 1.63 + // We open the file in binary format even if they are text files because 1.64 + // we are just comparing that bytes are exactly same in both files and not 1.65 + // doing anything smart with text formatting. 1.66 + std::ifstream file1(filename1.value().c_str(), 1.67 + std::ios::in | std::ios::binary); 1.68 + std::ifstream file2(filename2.value().c_str(), 1.69 + std::ios::in | std::ios::binary); 1.70 + 1.71 + // Even if both files aren't openable (and thus, in some sense, "equal"), 1.72 + // any unusable file yields a result of "false". 1.73 + if (!file1.is_open() || !file2.is_open()) 1.74 + return false; 1.75 + 1.76 + const int BUFFER_SIZE = 2056; 1.77 + char buffer1[BUFFER_SIZE], buffer2[BUFFER_SIZE]; 1.78 + do { 1.79 + file1.read(buffer1, BUFFER_SIZE); 1.80 + file2.read(buffer2, BUFFER_SIZE); 1.81 + 1.82 + if ((file1.eof() != file2.eof()) || 1.83 + (file1.gcount() != file2.gcount()) || 1.84 + (memcmp(buffer1, buffer2, file1.gcount()))) { 1.85 + file1.close(); 1.86 + file2.close(); 1.87 + return false; 1.88 + } 1.89 + } while (!file1.eof() || !file2.eof()); 1.90 + 1.91 + file1.close(); 1.92 + file2.close(); 1.93 + return true; 1.94 +} 1.95 + 1.96 +bool TextContentsEqual(const FilePath& filename1, const FilePath& filename2) { 1.97 + std::ifstream file1(filename1.value().c_str(), std::ios::in); 1.98 + std::ifstream file2(filename2.value().c_str(), std::ios::in); 1.99 + 1.100 + // Even if both files aren't openable (and thus, in some sense, "equal"), 1.101 + // any unusable file yields a result of "false". 1.102 + if (!file1.is_open() || !file2.is_open()) 1.103 + return false; 1.104 + 1.105 + do { 1.106 + std::string line1, line2; 1.107 + getline(file1, line1); 1.108 + getline(file2, line2); 1.109 + 1.110 + // Check for mismatched EOF states, or any error state. 1.111 + if ((file1.eof() != file2.eof()) || 1.112 + file1.bad() || file2.bad()) { 1.113 + return false; 1.114 + } 1.115 + 1.116 + // Trim all '\r' and '\n' characters from the end of the line. 1.117 + std::string::size_type end1 = line1.find_last_not_of("\r\n"); 1.118 + if (end1 == std::string::npos) 1.119 + line1.clear(); 1.120 + else if (end1 + 1 < line1.length()) 1.121 + line1.erase(end1 + 1); 1.122 + 1.123 + std::string::size_type end2 = line2.find_last_not_of("\r\n"); 1.124 + if (end2 == std::string::npos) 1.125 + line2.clear(); 1.126 + else if (end2 + 1 < line2.length()) 1.127 + line2.erase(end2 + 1); 1.128 + 1.129 + if (line1 != line2) 1.130 + return false; 1.131 + } while (!file1.eof() || !file2.eof()); 1.132 + 1.133 + return true; 1.134 +} 1.135 + 1.136 +bool ReadFileToString(const FilePath& path, std::string* contents) { 1.137 + if (path.ReferencesParent()) 1.138 + return false; 1.139 + FILE* file = file_util::OpenFile(path, "rb"); 1.140 + if (!file) { 1.141 + return false; 1.142 + } 1.143 + 1.144 + char buf[1 << 16]; 1.145 + size_t len; 1.146 + while ((len = fread(buf, 1, sizeof(buf), file)) > 0) { 1.147 + if (contents) 1.148 + contents->append(buf, len); 1.149 + } 1.150 + file_util::CloseFile(file); 1.151 + 1.152 + return true; 1.153 +} 1.154 + 1.155 +} // namespace base 1.156 + 1.157 +// ----------------------------------------------------------------------------- 1.158 + 1.159 +namespace file_util { 1.160 + 1.161 +using base::FileEnumerator; 1.162 +using base::FilePath; 1.163 +using base::kExtensionSeparator; 1.164 +using base::kMaxUniqueFiles; 1.165 + 1.166 +bool IsDirectoryEmpty(const FilePath& dir_path) { 1.167 + FileEnumerator files(dir_path, false, 1.168 + FileEnumerator::FILES | FileEnumerator::DIRECTORIES); 1.169 + if (files.Next().empty()) 1.170 + return true; 1.171 + return false; 1.172 +} 1.173 + 1.174 +FILE* CreateAndOpenTemporaryFile(FilePath* path) { 1.175 + FilePath directory; 1.176 + if (!GetTempDir(&directory)) 1.177 + return NULL; 1.178 + 1.179 + return CreateAndOpenTemporaryFileInDir(directory, path); 1.180 +} 1.181 + 1.182 +bool CreateDirectory(const base::FilePath& full_path) { 1.183 + return CreateDirectoryAndGetError(full_path, NULL); 1.184 +} 1.185 + 1.186 +bool GetFileSize(const FilePath& file_path, int64* file_size) { 1.187 + base::PlatformFileInfo info; 1.188 + if (!GetFileInfo(file_path, &info)) 1.189 + return false; 1.190 + *file_size = info.size; 1.191 + return true; 1.192 +} 1.193 + 1.194 +bool TouchFile(const FilePath& path, 1.195 + const base::Time& last_accessed, 1.196 + const base::Time& last_modified) { 1.197 + int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE_ATTRIBUTES; 1.198 + 1.199 +#if defined(OS_WIN) 1.200 + // On Windows, FILE_FLAG_BACKUP_SEMANTICS is needed to open a directory. 1.201 + if (DirectoryExists(path)) 1.202 + flags |= base::PLATFORM_FILE_BACKUP_SEMANTICS; 1.203 +#endif // OS_WIN 1.204 + 1.205 + const base::PlatformFile file = 1.206 + base::CreatePlatformFile(path, flags, NULL, NULL); 1.207 + if (file != base::kInvalidPlatformFileValue) { 1.208 + bool result = base::TouchPlatformFile(file, last_accessed, last_modified); 1.209 + base::ClosePlatformFile(file); 1.210 + return result; 1.211 + } 1.212 + 1.213 + return false; 1.214 +} 1.215 + 1.216 +bool SetLastModifiedTime(const FilePath& path, 1.217 + const base::Time& last_modified) { 1.218 + return TouchFile(path, last_modified, last_modified); 1.219 +} 1.220 + 1.221 +bool CloseFile(FILE* file) { 1.222 + if (file == NULL) 1.223 + return true; 1.224 + return fclose(file) == 0; 1.225 +} 1.226 + 1.227 +bool TruncateFile(FILE* file) { 1.228 + if (file == NULL) 1.229 + return false; 1.230 + long current_offset = ftell(file); 1.231 + if (current_offset == -1) 1.232 + return false; 1.233 +#if defined(OS_WIN) 1.234 + int fd = _fileno(file); 1.235 + if (_chsize(fd, current_offset) != 0) 1.236 + return false; 1.237 +#else 1.238 + int fd = fileno(file); 1.239 + if (ftruncate(fd, current_offset) != 0) 1.240 + return false; 1.241 +#endif 1.242 + return true; 1.243 +} 1.244 + 1.245 +int GetUniquePathNumber( 1.246 + const FilePath& path, 1.247 + const FilePath::StringType& suffix) { 1.248 + bool have_suffix = !suffix.empty(); 1.249 + if (!PathExists(path) && 1.250 + (!have_suffix || !PathExists(FilePath(path.value() + suffix)))) { 1.251 + return 0; 1.252 + } 1.253 + 1.254 + FilePath new_path; 1.255 + for (int count = 1; count <= kMaxUniqueFiles; ++count) { 1.256 + new_path = 1.257 + path.InsertBeforeExtensionASCII(base::StringPrintf(" (%d)", count)); 1.258 + if (!PathExists(new_path) && 1.259 + (!have_suffix || !PathExists(FilePath(new_path.value() + suffix)))) { 1.260 + return count; 1.261 + } 1.262 + } 1.263 + 1.264 + return -1; 1.265 +} 1.266 + 1.267 +} // namespace file_util