security/sandbox/chromium/base/file_util.cc

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

michael@0 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
michael@0 2 // Use of this source code is governed by a BSD-style license that can be
michael@0 3 // found in the LICENSE file.
michael@0 4
michael@0 5 #include "base/file_util.h"
michael@0 6
michael@0 7 #if defined(OS_WIN)
michael@0 8 #include <io.h>
michael@0 9 #endif
michael@0 10 #include <stdio.h>
michael@0 11
michael@0 12 #include <fstream>
michael@0 13
michael@0 14 #include "base/files/file_enumerator.h"
michael@0 15 #include "base/files/file_path.h"
michael@0 16 #include "base/logging.h"
michael@0 17 #include "base/strings/string_piece.h"
michael@0 18 #include "base/strings/string_util.h"
michael@0 19 #include "base/strings/stringprintf.h"
michael@0 20 #include "base/strings/utf_string_conversions.h"
michael@0 21
michael@0 22 namespace base {
michael@0 23
michael@0 24 namespace {
michael@0 25
michael@0 26 const FilePath::CharType kExtensionSeparator = FILE_PATH_LITERAL('.');
michael@0 27
michael@0 28 // The maximum number of 'uniquified' files we will try to create.
michael@0 29 // This is used when the filename we're trying to download is already in use,
michael@0 30 // so we create a new unique filename by appending " (nnn)" before the
michael@0 31 // extension, where 1 <= nnn <= kMaxUniqueFiles.
michael@0 32 // Also used by code that cleans up said files.
michael@0 33 static const int kMaxUniqueFiles = 100;
michael@0 34
michael@0 35 } // namespace
michael@0 36
michael@0 37 bool g_bug108724_debug = false;
michael@0 38
michael@0 39 int64 ComputeDirectorySize(const FilePath& root_path) {
michael@0 40 int64 running_size = 0;
michael@0 41 FileEnumerator file_iter(root_path, true, FileEnumerator::FILES);
michael@0 42 while (!file_iter.Next().empty())
michael@0 43 running_size += file_iter.GetInfo().GetSize();
michael@0 44 return running_size;
michael@0 45 }
michael@0 46
michael@0 47 bool Move(const FilePath& from_path, const FilePath& to_path) {
michael@0 48 if (from_path.ReferencesParent() || to_path.ReferencesParent())
michael@0 49 return false;
michael@0 50 return internal::MoveUnsafe(from_path, to_path);
michael@0 51 }
michael@0 52
michael@0 53 bool CopyFile(const FilePath& from_path, const FilePath& to_path) {
michael@0 54 if (from_path.ReferencesParent() || to_path.ReferencesParent())
michael@0 55 return false;
michael@0 56 return internal::CopyFileUnsafe(from_path, to_path);
michael@0 57 }
michael@0 58
michael@0 59 bool ContentsEqual(const FilePath& filename1, const FilePath& filename2) {
michael@0 60 // We open the file in binary format even if they are text files because
michael@0 61 // we are just comparing that bytes are exactly same in both files and not
michael@0 62 // doing anything smart with text formatting.
michael@0 63 std::ifstream file1(filename1.value().c_str(),
michael@0 64 std::ios::in | std::ios::binary);
michael@0 65 std::ifstream file2(filename2.value().c_str(),
michael@0 66 std::ios::in | std::ios::binary);
michael@0 67
michael@0 68 // Even if both files aren't openable (and thus, in some sense, "equal"),
michael@0 69 // any unusable file yields a result of "false".
michael@0 70 if (!file1.is_open() || !file2.is_open())
michael@0 71 return false;
michael@0 72
michael@0 73 const int BUFFER_SIZE = 2056;
michael@0 74 char buffer1[BUFFER_SIZE], buffer2[BUFFER_SIZE];
michael@0 75 do {
michael@0 76 file1.read(buffer1, BUFFER_SIZE);
michael@0 77 file2.read(buffer2, BUFFER_SIZE);
michael@0 78
michael@0 79 if ((file1.eof() != file2.eof()) ||
michael@0 80 (file1.gcount() != file2.gcount()) ||
michael@0 81 (memcmp(buffer1, buffer2, file1.gcount()))) {
michael@0 82 file1.close();
michael@0 83 file2.close();
michael@0 84 return false;
michael@0 85 }
michael@0 86 } while (!file1.eof() || !file2.eof());
michael@0 87
michael@0 88 file1.close();
michael@0 89 file2.close();
michael@0 90 return true;
michael@0 91 }
michael@0 92
michael@0 93 bool TextContentsEqual(const FilePath& filename1, const FilePath& filename2) {
michael@0 94 std::ifstream file1(filename1.value().c_str(), std::ios::in);
michael@0 95 std::ifstream file2(filename2.value().c_str(), std::ios::in);
michael@0 96
michael@0 97 // Even if both files aren't openable (and thus, in some sense, "equal"),
michael@0 98 // any unusable file yields a result of "false".
michael@0 99 if (!file1.is_open() || !file2.is_open())
michael@0 100 return false;
michael@0 101
michael@0 102 do {
michael@0 103 std::string line1, line2;
michael@0 104 getline(file1, line1);
michael@0 105 getline(file2, line2);
michael@0 106
michael@0 107 // Check for mismatched EOF states, or any error state.
michael@0 108 if ((file1.eof() != file2.eof()) ||
michael@0 109 file1.bad() || file2.bad()) {
michael@0 110 return false;
michael@0 111 }
michael@0 112
michael@0 113 // Trim all '\r' and '\n' characters from the end of the line.
michael@0 114 std::string::size_type end1 = line1.find_last_not_of("\r\n");
michael@0 115 if (end1 == std::string::npos)
michael@0 116 line1.clear();
michael@0 117 else if (end1 + 1 < line1.length())
michael@0 118 line1.erase(end1 + 1);
michael@0 119
michael@0 120 std::string::size_type end2 = line2.find_last_not_of("\r\n");
michael@0 121 if (end2 == std::string::npos)
michael@0 122 line2.clear();
michael@0 123 else if (end2 + 1 < line2.length())
michael@0 124 line2.erase(end2 + 1);
michael@0 125
michael@0 126 if (line1 != line2)
michael@0 127 return false;
michael@0 128 } while (!file1.eof() || !file2.eof());
michael@0 129
michael@0 130 return true;
michael@0 131 }
michael@0 132
michael@0 133 bool ReadFileToString(const FilePath& path, std::string* contents) {
michael@0 134 if (path.ReferencesParent())
michael@0 135 return false;
michael@0 136 FILE* file = file_util::OpenFile(path, "rb");
michael@0 137 if (!file) {
michael@0 138 return false;
michael@0 139 }
michael@0 140
michael@0 141 char buf[1 << 16];
michael@0 142 size_t len;
michael@0 143 while ((len = fread(buf, 1, sizeof(buf), file)) > 0) {
michael@0 144 if (contents)
michael@0 145 contents->append(buf, len);
michael@0 146 }
michael@0 147 file_util::CloseFile(file);
michael@0 148
michael@0 149 return true;
michael@0 150 }
michael@0 151
michael@0 152 } // namespace base
michael@0 153
michael@0 154 // -----------------------------------------------------------------------------
michael@0 155
michael@0 156 namespace file_util {
michael@0 157
michael@0 158 using base::FileEnumerator;
michael@0 159 using base::FilePath;
michael@0 160 using base::kExtensionSeparator;
michael@0 161 using base::kMaxUniqueFiles;
michael@0 162
michael@0 163 bool IsDirectoryEmpty(const FilePath& dir_path) {
michael@0 164 FileEnumerator files(dir_path, false,
michael@0 165 FileEnumerator::FILES | FileEnumerator::DIRECTORIES);
michael@0 166 if (files.Next().empty())
michael@0 167 return true;
michael@0 168 return false;
michael@0 169 }
michael@0 170
michael@0 171 FILE* CreateAndOpenTemporaryFile(FilePath* path) {
michael@0 172 FilePath directory;
michael@0 173 if (!GetTempDir(&directory))
michael@0 174 return NULL;
michael@0 175
michael@0 176 return CreateAndOpenTemporaryFileInDir(directory, path);
michael@0 177 }
michael@0 178
michael@0 179 bool CreateDirectory(const base::FilePath& full_path) {
michael@0 180 return CreateDirectoryAndGetError(full_path, NULL);
michael@0 181 }
michael@0 182
michael@0 183 bool GetFileSize(const FilePath& file_path, int64* file_size) {
michael@0 184 base::PlatformFileInfo info;
michael@0 185 if (!GetFileInfo(file_path, &info))
michael@0 186 return false;
michael@0 187 *file_size = info.size;
michael@0 188 return true;
michael@0 189 }
michael@0 190
michael@0 191 bool TouchFile(const FilePath& path,
michael@0 192 const base::Time& last_accessed,
michael@0 193 const base::Time& last_modified) {
michael@0 194 int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE_ATTRIBUTES;
michael@0 195
michael@0 196 #if defined(OS_WIN)
michael@0 197 // On Windows, FILE_FLAG_BACKUP_SEMANTICS is needed to open a directory.
michael@0 198 if (DirectoryExists(path))
michael@0 199 flags |= base::PLATFORM_FILE_BACKUP_SEMANTICS;
michael@0 200 #endif // OS_WIN
michael@0 201
michael@0 202 const base::PlatformFile file =
michael@0 203 base::CreatePlatformFile(path, flags, NULL, NULL);
michael@0 204 if (file != base::kInvalidPlatformFileValue) {
michael@0 205 bool result = base::TouchPlatformFile(file, last_accessed, last_modified);
michael@0 206 base::ClosePlatformFile(file);
michael@0 207 return result;
michael@0 208 }
michael@0 209
michael@0 210 return false;
michael@0 211 }
michael@0 212
michael@0 213 bool SetLastModifiedTime(const FilePath& path,
michael@0 214 const base::Time& last_modified) {
michael@0 215 return TouchFile(path, last_modified, last_modified);
michael@0 216 }
michael@0 217
michael@0 218 bool CloseFile(FILE* file) {
michael@0 219 if (file == NULL)
michael@0 220 return true;
michael@0 221 return fclose(file) == 0;
michael@0 222 }
michael@0 223
michael@0 224 bool TruncateFile(FILE* file) {
michael@0 225 if (file == NULL)
michael@0 226 return false;
michael@0 227 long current_offset = ftell(file);
michael@0 228 if (current_offset == -1)
michael@0 229 return false;
michael@0 230 #if defined(OS_WIN)
michael@0 231 int fd = _fileno(file);
michael@0 232 if (_chsize(fd, current_offset) != 0)
michael@0 233 return false;
michael@0 234 #else
michael@0 235 int fd = fileno(file);
michael@0 236 if (ftruncate(fd, current_offset) != 0)
michael@0 237 return false;
michael@0 238 #endif
michael@0 239 return true;
michael@0 240 }
michael@0 241
michael@0 242 int GetUniquePathNumber(
michael@0 243 const FilePath& path,
michael@0 244 const FilePath::StringType& suffix) {
michael@0 245 bool have_suffix = !suffix.empty();
michael@0 246 if (!PathExists(path) &&
michael@0 247 (!have_suffix || !PathExists(FilePath(path.value() + suffix)))) {
michael@0 248 return 0;
michael@0 249 }
michael@0 250
michael@0 251 FilePath new_path;
michael@0 252 for (int count = 1; count <= kMaxUniqueFiles; ++count) {
michael@0 253 new_path =
michael@0 254 path.InsertBeforeExtensionASCII(base::StringPrintf(" (%d)", count));
michael@0 255 if (!PathExists(new_path) &&
michael@0 256 (!have_suffix || !PathExists(FilePath(new_path.value() + suffix)))) {
michael@0 257 return count;
michael@0 258 }
michael@0 259 }
michael@0 260
michael@0 261 return -1;
michael@0 262 }
michael@0 263
michael@0 264 } // namespace file_util

mercurial