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.

     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/file_util.h"
     7 #if defined(OS_WIN)
     8 #include <io.h>
     9 #endif
    10 #include <stdio.h>
    12 #include <fstream>
    14 #include "base/files/file_enumerator.h"
    15 #include "base/files/file_path.h"
    16 #include "base/logging.h"
    17 #include "base/strings/string_piece.h"
    18 #include "base/strings/string_util.h"
    19 #include "base/strings/stringprintf.h"
    20 #include "base/strings/utf_string_conversions.h"
    22 namespace base {
    24 namespace {
    26 const FilePath::CharType kExtensionSeparator = FILE_PATH_LITERAL('.');
    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;
    35 }  // namespace
    37 bool g_bug108724_debug = false;
    39 int64 ComputeDirectorySize(const FilePath& root_path) {
    40   int64 running_size = 0;
    41   FileEnumerator file_iter(root_path, true, FileEnumerator::FILES);
    42   while (!file_iter.Next().empty())
    43     running_size += file_iter.GetInfo().GetSize();
    44   return running_size;
    45 }
    47 bool Move(const FilePath& from_path, const FilePath& to_path) {
    48   if (from_path.ReferencesParent() || to_path.ReferencesParent())
    49     return false;
    50   return internal::MoveUnsafe(from_path, to_path);
    51 }
    53 bool CopyFile(const FilePath& from_path, const FilePath& to_path) {
    54   if (from_path.ReferencesParent() || to_path.ReferencesParent())
    55     return false;
    56   return internal::CopyFileUnsafe(from_path, to_path);
    57 }
    59 bool ContentsEqual(const FilePath& filename1, const FilePath& filename2) {
    60   // We open the file in binary format even if they are text files because
    61   // we are just comparing that bytes are exactly same in both files and not
    62   // doing anything smart with text formatting.
    63   std::ifstream file1(filename1.value().c_str(),
    64                       std::ios::in | std::ios::binary);
    65   std::ifstream file2(filename2.value().c_str(),
    66                       std::ios::in | std::ios::binary);
    68   // Even if both files aren't openable (and thus, in some sense, "equal"),
    69   // any unusable file yields a result of "false".
    70   if (!file1.is_open() || !file2.is_open())
    71     return false;
    73   const int BUFFER_SIZE = 2056;
    74   char buffer1[BUFFER_SIZE], buffer2[BUFFER_SIZE];
    75   do {
    76     file1.read(buffer1, BUFFER_SIZE);
    77     file2.read(buffer2, BUFFER_SIZE);
    79     if ((file1.eof() != file2.eof()) ||
    80         (file1.gcount() != file2.gcount()) ||
    81         (memcmp(buffer1, buffer2, file1.gcount()))) {
    82       file1.close();
    83       file2.close();
    84       return false;
    85     }
    86   } while (!file1.eof() || !file2.eof());
    88   file1.close();
    89   file2.close();
    90   return true;
    91 }
    93 bool TextContentsEqual(const FilePath& filename1, const FilePath& filename2) {
    94   std::ifstream file1(filename1.value().c_str(), std::ios::in);
    95   std::ifstream file2(filename2.value().c_str(), std::ios::in);
    97   // Even if both files aren't openable (and thus, in some sense, "equal"),
    98   // any unusable file yields a result of "false".
    99   if (!file1.is_open() || !file2.is_open())
   100     return false;
   102   do {
   103     std::string line1, line2;
   104     getline(file1, line1);
   105     getline(file2, line2);
   107     // Check for mismatched EOF states, or any error state.
   108     if ((file1.eof() != file2.eof()) ||
   109         file1.bad() || file2.bad()) {
   110       return false;
   111     }
   113     // Trim all '\r' and '\n' characters from the end of the line.
   114     std::string::size_type end1 = line1.find_last_not_of("\r\n");
   115     if (end1 == std::string::npos)
   116       line1.clear();
   117     else if (end1 + 1 < line1.length())
   118       line1.erase(end1 + 1);
   120     std::string::size_type end2 = line2.find_last_not_of("\r\n");
   121     if (end2 == std::string::npos)
   122       line2.clear();
   123     else if (end2 + 1 < line2.length())
   124       line2.erase(end2 + 1);
   126     if (line1 != line2)
   127       return false;
   128   } while (!file1.eof() || !file2.eof());
   130   return true;
   131 }
   133 bool ReadFileToString(const FilePath& path, std::string* contents) {
   134   if (path.ReferencesParent())
   135     return false;
   136   FILE* file = file_util::OpenFile(path, "rb");
   137   if (!file) {
   138     return false;
   139   }
   141   char buf[1 << 16];
   142   size_t len;
   143   while ((len = fread(buf, 1, sizeof(buf), file)) > 0) {
   144     if (contents)
   145       contents->append(buf, len);
   146   }
   147   file_util::CloseFile(file);
   149   return true;
   150 }
   152 }  // namespace base
   154 // -----------------------------------------------------------------------------
   156 namespace file_util {
   158 using base::FileEnumerator;
   159 using base::FilePath;
   160 using base::kExtensionSeparator;
   161 using base::kMaxUniqueFiles;
   163 bool IsDirectoryEmpty(const FilePath& dir_path) {
   164   FileEnumerator files(dir_path, false,
   165       FileEnumerator::FILES | FileEnumerator::DIRECTORIES);
   166   if (files.Next().empty())
   167     return true;
   168   return false;
   169 }
   171 FILE* CreateAndOpenTemporaryFile(FilePath* path) {
   172   FilePath directory;
   173   if (!GetTempDir(&directory))
   174     return NULL;
   176   return CreateAndOpenTemporaryFileInDir(directory, path);
   177 }
   179 bool CreateDirectory(const base::FilePath& full_path) {
   180   return CreateDirectoryAndGetError(full_path, NULL);
   181 }
   183 bool GetFileSize(const FilePath& file_path, int64* file_size) {
   184   base::PlatformFileInfo info;
   185   if (!GetFileInfo(file_path, &info))
   186     return false;
   187   *file_size = info.size;
   188   return true;
   189 }
   191 bool TouchFile(const FilePath& path,
   192                const base::Time& last_accessed,
   193                const base::Time& last_modified) {
   194   int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE_ATTRIBUTES;
   196 #if defined(OS_WIN)
   197   // On Windows, FILE_FLAG_BACKUP_SEMANTICS is needed to open a directory.
   198   if (DirectoryExists(path))
   199     flags |= base::PLATFORM_FILE_BACKUP_SEMANTICS;
   200 #endif  // OS_WIN
   202   const base::PlatformFile file =
   203       base::CreatePlatformFile(path, flags, NULL, NULL);
   204   if (file != base::kInvalidPlatformFileValue) {
   205     bool result = base::TouchPlatformFile(file, last_accessed, last_modified);
   206     base::ClosePlatformFile(file);
   207     return result;
   208   }
   210   return false;
   211 }
   213 bool SetLastModifiedTime(const FilePath& path,
   214                          const base::Time& last_modified) {
   215   return TouchFile(path, last_modified, last_modified);
   216 }
   218 bool CloseFile(FILE* file) {
   219   if (file == NULL)
   220     return true;
   221   return fclose(file) == 0;
   222 }
   224 bool 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 }
   242 int GetUniquePathNumber(
   243     const FilePath& path,
   244     const FilePath::StringType& suffix) {
   245   bool have_suffix = !suffix.empty();
   246   if (!PathExists(path) &&
   247       (!have_suffix || !PathExists(FilePath(path.value() + suffix)))) {
   248     return 0;
   249   }
   251   FilePath new_path;
   252   for (int count = 1; count <= kMaxUniqueFiles; ++count) {
   253     new_path =
   254         path.InsertBeforeExtensionASCII(base::StringPrintf(" (%d)", count));
   255     if (!PathExists(new_path) &&
   256         (!have_suffix || !PathExists(FilePath(new_path.value() + suffix)))) {
   257       return count;
   258     }
   259   }
   261   return -1;
   262 }
   264 }  // namespace file_util

mercurial