summaryrefslogtreecommitdiff
path: root/chromium/base/files
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-20 15:06:40 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-22 11:48:58 +0000
commitdaa093eea7c773db06799a13bd7e4e2e2a9f8f14 (patch)
tree96cc5e7b9194c1b29eab927730bfa419e7111c25 /chromium/base/files
parentbe59a35641616a4cf23c4a13fa0632624b021c1b (diff)
downloadqtwebengine-chromium-daa093eea7c773db06799a13bd7e4e2e2a9f8f14.tar.gz
BASELINE: Update Chromium to 63.0.3239.58
Change-Id: Ia93b322a00ba4dd4004f3bcf1254063ba90e1605 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/base/files')
-rw-r--r--chromium/base/files/file_enumerator.h4
-rw-r--r--chromium/base/files/file_enumerator_unittest.cc6
-rw-r--r--chromium/base/files/file_path.cc8
-rw-r--r--chromium/base/files/file_path.h5
-rw-r--r--chromium/base/files/file_path_unittest.cc2
-rw-r--r--chromium/base/files/file_path_watcher_linux.cc13
-rw-r--r--chromium/base/files/file_posix.cc1
-rw-r--r--chromium/base/files/file_util.h24
-rw-r--r--chromium/base/files/file_util_posix.cc162
-rw-r--r--chromium/base/files/file_util_unittest.cc324
10 files changed, 449 insertions, 100 deletions
diff --git a/chromium/base/files/file_enumerator.h b/chromium/base/files/file_enumerator.h
index 4f3ee57a8c5..190a0612bf7 100644
--- a/chromium/base/files/file_enumerator.h
+++ b/chromium/base/files/file_enumerator.h
@@ -8,10 +8,10 @@
#include <stddef.h>
#include <stdint.h>
-#include <stack>
#include <vector>
#include "base/base_export.h"
+#include "base/containers/stack.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/time/time.h"
@@ -164,7 +164,7 @@ class BASE_EXPORT FileEnumerator {
// A stack that keeps track of which subdirectories we still need to
// enumerate in the breadth-first search.
- std::stack<FilePath> pending_paths_;
+ base::stack<FilePath> pending_paths_;
DISALLOW_COPY_AND_ASSIGN(FileEnumerator);
};
diff --git a/chromium/base/files/file_enumerator_unittest.cc b/chromium/base/files/file_enumerator_unittest.cc
index 5faa80f7611..11df075ecd6 100644
--- a/chromium/base/files/file_enumerator_unittest.cc
+++ b/chromium/base/files/file_enumerator_unittest.cc
@@ -4,10 +4,10 @@
#include "base/files/file_enumerator.h"
-#include <deque>
#include <utility>
#include <vector>
+#include "base/containers/circular_deque.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
@@ -27,13 +27,13 @@ const std::vector<FileEnumerator::FolderSearchPolicy> kFolderSearchPolicies{
FileEnumerator::FolderSearchPolicy::MATCH_ONLY,
FileEnumerator::FolderSearchPolicy::ALL};
-std::deque<FilePath> RunEnumerator(
+circular_deque<FilePath> RunEnumerator(
const FilePath& root_path,
bool recursive,
int file_type,
const FilePath::StringType& pattern,
FileEnumerator::FolderSearchPolicy folder_search_policy) {
- std::deque<FilePath> rv;
+ circular_deque<FilePath> rv;
FileEnumerator enumerator(root_path, recursive, file_type, pattern,
folder_search_policy);
for (auto file = enumerator.Next(); !file.empty(); file = enumerator.Next())
diff --git a/chromium/base/files/file_path.cc b/chromium/base/files/file_path.cc
index c0d6c1210db..cc3c0d12e66 100644
--- a/chromium/base/files/file_path.cc
+++ b/chromium/base/files/file_path.cc
@@ -670,14 +670,6 @@ FilePath FilePath::FromUTF16Unsafe(StringPiece16 utf16) {
}
#endif
-void FilePath::GetSizeForPickle(PickleSizer* sizer) const {
-#if defined(OS_WIN)
- sizer->AddString16(path_);
-#else
- sizer->AddString(path_);
-#endif
-}
-
void FilePath::WriteToPickle(Pickle* pickle) const {
#if defined(OS_WIN)
pickle->WriteString16(path_);
diff --git a/chromium/base/files/file_path.h b/chromium/base/files/file_path.h
index a4ced9481a4..6cb2e7577e8 100644
--- a/chromium/base/files/file_path.h
+++ b/chromium/base/files/file_path.h
@@ -137,7 +137,6 @@ namespace base {
class Pickle;
class PickleIterator;
-class PickleSizer;
// An abstraction to isolate users from the differences between native
// pathnames on different platforms.
@@ -239,7 +238,8 @@ class BASE_EXPORT FilePath {
// named by this object, stripping away the file component. If this object
// only contains one component, returns a FilePath identifying
// kCurrentDirectory. If this object already refers to the root directory,
- // returns a FilePath identifying the root directory.
+ // returns a FilePath identifying the root directory. Please note that this
+ // doesn't resolve directory navigation, e.g. the result for "../a" is "..".
FilePath DirName() const WARN_UNUSED_RESULT;
// Returns a FilePath corresponding to the last path component of this
@@ -384,7 +384,6 @@ class BASE_EXPORT FilePath {
// Similar to FromUTF8Unsafe, but accepts UTF-16 instead.
static FilePath FromUTF16Unsafe(StringPiece16 utf16);
- void GetSizeForPickle(PickleSizer* sizer) const;
void WriteToPickle(Pickle* pickle) const;
bool ReadFromPickle(PickleIterator* iter);
diff --git a/chromium/base/files/file_path_unittest.cc b/chromium/base/files/file_path_unittest.cc
index eba9a96028f..6ca652c5f15 100644
--- a/chromium/base/files/file_path_unittest.cc
+++ b/chromium/base/files/file_path_unittest.cc
@@ -89,6 +89,7 @@ TEST_F(FilePathTest, DirName) {
{ FPL("{:"), FPL(".") },
{ FPL("\xB3:"), FPL(".") },
{ FPL("\xC5:"), FPL(".") },
+ { FPL("/aa/../bb/cc"), FPL("/aa/../bb")},
#if defined(OS_WIN)
{ FPL("\x0143:"), FPL(".") },
#endif // OS_WIN
@@ -128,6 +129,7 @@ TEST_F(FilePathTest, DirName) {
{ FPL("\\\\aa\\bb"), FPL("\\\\aa") },
{ FPL("\\\\aa\\"), FPL("\\\\") },
{ FPL("\\\\aa"), FPL("\\\\") },
+ { FPL("aa\\..\\bb\\c"), FPL("aa\\..\\bb")},
#if defined(FILE_PATH_USES_DRIVE_LETTERS)
{ FPL("c:\\"), FPL("c:\\") },
{ FPL("c:\\\\"), FPL("c:\\\\") },
diff --git a/chromium/base/files/file_path_watcher_linux.cc b/chromium/base/files/file_path_watcher_linux.cc
index 9686624b97f..1c1bb3eb3c7 100644
--- a/chromium/base/files/file_path_watcher_linux.cc
+++ b/chromium/base/files/file_path_watcher_linux.cc
@@ -187,6 +187,12 @@ class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate {
std::unordered_map<InotifyReader::Watch, FilePath> recursive_paths_by_watch_;
std::map<FilePath, InotifyReader::Watch> recursive_watches_by_path_;
+ // Read only while INotifyReader::lock_ is held, and used to post asynchronous
+ // notifications to the Watcher on its home task_runner(). Ideally this should
+ // be const, but since it is initialized from |weak_factory_|, which must
+ // appear after it, that is not possible.
+ WeakPtr<FilePathWatcherImpl> weak_ptr_;
+
WeakPtrFactory<FilePathWatcherImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl);
@@ -313,7 +319,9 @@ void InotifyReader::OnInotifyEvent(const inotify_event* event) {
}
FilePathWatcherImpl::FilePathWatcherImpl()
- : recursive_(false), weak_factory_(this) {}
+ : recursive_(false), weak_factory_(this) {
+ weak_ptr_ = weak_factory_.GetWeakPtr();
+}
FilePathWatcherImpl::~FilePathWatcherImpl() {
DCHECK(!task_runner() || task_runner()->RunsTasksInCurrentSequence());
@@ -332,8 +340,7 @@ void FilePathWatcherImpl::OnFilePathChanged(InotifyReader::Watch fired_watch,
task_runner()->PostTask(
FROM_HERE,
BindOnce(&FilePathWatcherImpl::OnFilePathChangedOnOriginSequence,
- weak_factory_.GetWeakPtr(), fired_watch, child, created, deleted,
- is_dir));
+ weak_ptr_, fired_watch, child, created, deleted, is_dir));
}
void FilePathWatcherImpl::OnFilePathChangedOnOriginSequence(
diff --git a/chromium/base/files/file_posix.cc b/chromium/base/files/file_posix.cc
index 3c2346e48fa..6b5d174525c 100644
--- a/chromium/base/files/file_posix.cc
+++ b/chromium/base/files/file_posix.cc
@@ -410,6 +410,7 @@ File::Error File::OSErrorToFileError(int saved_errno) {
return FILE_ERROR_IO;
case ENOENT:
return FILE_ERROR_NOT_FOUND;
+ case ENFILE: // fallthrough
case EMFILE:
return FILE_ERROR_TOO_MANY_OPENED;
case ENOMEM:
diff --git a/chromium/base/files/file_util.h b/chromium/base/files/file_util.h
index fac14d3d499..950d24ba000 100644
--- a/chromium/base/files/file_util.h
+++ b/chromium/base/files/file_util.h
@@ -95,11 +95,26 @@ BASE_EXPORT bool ReplaceFile(const FilePath& from_path,
const FilePath& to_path,
File::Error* error);
-// Copies a single file. Use CopyDirectory to copy directories.
+// Copies a single file. Use CopyDirectory() to copy directories.
// This function fails if either path contains traversal components ('..').
+// This function also fails if |to_path| is a directory.
//
-// This function keeps the metadata on Windows. The read only bit on Windows is
-// not kept.
+// On POSIX, if |to_path| is a symlink, CopyFile() will follow the symlink. This
+// may have security implications. Use with care.
+//
+// If |to_path| already exists and is a regular file, it will be overwritten,
+// though its permissions will stay the same.
+//
+// If |to_path| does not exist, it will be created. The new file's permissions
+// varies per platform:
+//
+// - This function keeps the metadata on Windows. The read only bit is not kept.
+// - On Mac and iOS, |to_path| retains |from_path|'s permissions, except user
+// read/write permissions are always set.
+// - On Linux and Android, |to_path| has user read/write permissions only. i.e.
+// Always 0600.
+// - On ChromeOS, |to_path| has user read/write permissions and group/others
+// read permissions. i.e. Always 0644.
BASE_EXPORT bool CopyFile(const FilePath& from_path, const FilePath& to_path);
// Copies the given path, and optionally all subdirectories and their contents
@@ -108,8 +123,7 @@ BASE_EXPORT bool CopyFile(const FilePath& from_path, const FilePath& to_path);
// If there are files existing under to_path, always overwrite. Returns true
// if successful, false otherwise. Wildcards on the names are not supported.
//
-// This function calls into CopyFile() so the same behavior w.r.t. metadata
-// applies.
+// This function has the same metadata behavior as CopyFile().
//
// If you only need to copy a file use CopyFile, it's faster.
BASE_EXPORT bool CopyDirectory(const FilePath& from_path,
diff --git a/chromium/base/files/file_util_posix.cc b/chromium/base/files/file_util_posix.cc
index de9da50cd01..98887acf996 100644
--- a/chromium/base/files/file_util_posix.cc
+++ b/chromium/base/files/file_util_posix.cc
@@ -21,6 +21,7 @@
#include <time.h>
#include <unistd.h>
+#include "base/containers/stack.h"
#include "base/environment.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
@@ -176,7 +177,46 @@ bool DetermineDevShmExecutable() {
}
return result;
}
-#endif // defined(OS_LINUX)
+#endif // defined(OS_LINUX) || defined(OS_AIX)
+
+bool AdvanceEnumeratorWithStat(FileEnumerator* traversal,
+ FilePath* out_next_path,
+ struct stat* out_next_stat) {
+ DCHECK(out_next_path);
+ DCHECK(out_next_stat);
+ *out_next_path = traversal->Next();
+ if (out_next_path->empty())
+ return false;
+
+ *out_next_stat = traversal->GetInfo().stat();
+ return true;
+}
+
+bool CopyFileContents(File* infile, File* outfile) {
+ static constexpr size_t kBufferSize = 32768;
+ std::vector<char> buffer(kBufferSize);
+
+ for (;;) {
+ ssize_t bytes_read = infile->ReadAtCurrentPos(buffer.data(), buffer.size());
+ if (bytes_read < 0)
+ return false;
+ if (bytes_read == 0)
+ return true;
+ // Allow for partial writes
+ ssize_t bytes_written_per_read = 0;
+ do {
+ ssize_t bytes_written_partial = outfile->WriteAtCurrentPos(
+ &buffer[bytes_written_per_read], bytes_read - bytes_written_per_read);
+ if (bytes_written_partial < 0)
+ return false;
+
+ bytes_written_per_read += bytes_written_partial;
+ } while (bytes_written_per_read < bytes_read);
+ }
+
+ NOTREACHED();
+ return false;
+}
#endif // !defined(OS_NACL_NONSFI)
#if !defined(OS_MACOSX)
@@ -221,7 +261,7 @@ bool DeleteFile(const FilePath& path, bool recursive) {
return (rmdir(path_str) == 0);
bool success = true;
- std::stack<std::string> directories;
+ base::stack<std::string> directories;
directories.push(path.value());
FileEnumerator traversal(path, true,
FileEnumerator::FILES | FileEnumerator::DIRECTORIES |
@@ -294,8 +334,8 @@ bool CopyDirectory(const FilePath& from_path,
struct stat from_stat;
FilePath current = from_path;
if (stat(from_path.value().c_str(), &from_stat) < 0) {
- DLOG(ERROR) << "CopyDirectory() couldn't stat source directory: "
- << from_path.value() << " errno = " << errno;
+ DPLOG(ERROR) << "CopyDirectory() couldn't stat source directory: "
+ << from_path.value();
return false;
}
FilePath from_path_base = from_path;
@@ -310,44 +350,81 @@ bool CopyDirectory(const FilePath& from_path,
// TODO(maruel): This is not necessary anymore.
DCHECK(recursive || S_ISDIR(from_stat.st_mode));
- bool success = true;
- while (success && !current.empty()) {
+ do {
// current is the source path, including from_path, so append
// the suffix after from_path to to_path to create the target_path.
FilePath target_path(to_path);
- if (from_path_base != current) {
- if (!from_path_base.AppendRelativePath(current, &target_path)) {
- success = false;
- break;
- }
+ if (from_path_base != current &&
+ !from_path_base.AppendRelativePath(current, &target_path)) {
+ return false;
}
if (S_ISDIR(from_stat.st_mode)) {
if (mkdir(target_path.value().c_str(),
- (from_stat.st_mode & 01777) | S_IRUSR | S_IXUSR | S_IWUSR) !=
- 0 &&
- errno != EEXIST) {
- DLOG(ERROR) << "CopyDirectory() couldn't create directory: "
- << target_path.value() << " errno = " << errno;
- success = false;
- }
- } else if (S_ISREG(from_stat.st_mode)) {
- if (!CopyFile(current, target_path)) {
- DLOG(ERROR) << "CopyDirectory() couldn't create file: "
- << target_path.value();
- success = false;
+ (from_stat.st_mode & 01777) | S_IRUSR | S_IXUSR | S_IWUSR) ==
+ 0 ||
+ errno == EEXIST) {
+ continue;
}
- } else {
+
+ DPLOG(ERROR) << "CopyDirectory() couldn't create directory: "
+ << target_path.value();
+ return false;
+ }
+
+ if (!S_ISREG(from_stat.st_mode)) {
DLOG(WARNING) << "CopyDirectory() skipping non-regular file: "
<< current.value();
+ continue;
}
- current = traversal.Next();
- if (!current.empty())
- from_stat = traversal.GetInfo().stat();
- }
+ // Add O_NONBLOCK so we can't block opening a pipe.
+ base::File infile(open(current.value().c_str(), O_RDONLY | O_NONBLOCK));
+ if (!infile.IsValid()) {
+ DPLOG(ERROR) << "CopyDirectory() couldn't open file: " << current.value();
+ return false;
+ }
- return success;
+ struct stat stat_at_use;
+ if (fstat(infile.GetPlatformFile(), &stat_at_use) < 0) {
+ DPLOG(ERROR) << "CopyDirectory() couldn't stat file: " << current.value();
+ return false;
+ }
+
+ if (!S_ISREG(stat_at_use.st_mode)) {
+ DLOG(WARNING) << "CopyDirectory() skipping non-regular file: "
+ << current.value();
+ continue;
+ }
+
+ // Each platform has different default file opening modes for CopyFile which
+ // we want to replicate here. On OS X, we use copyfile(3) which takes the
+ // source file's permissions into account. On the other platforms, we just
+ // use the base::File constructor. On Chrome OS, base::File uses a different
+ // set of permissions than it does on other POSIX platforms.
+#if defined(OS_MACOSX)
+ int mode = 0600 | (stat_at_use.st_mode & 0177);
+#elif defined(OS_CHROMEOS)
+ int mode = 0644;
+#else
+ int mode = 0600;
+#endif
+ base::File outfile(
+ open(target_path.value().c_str(),
+ O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode));
+ if (!outfile.IsValid()) {
+ DPLOG(ERROR) << "CopyDirectory() couldn't create file: "
+ << target_path.value();
+ return false;
+ }
+
+ if (!CopyFileContents(&infile, &outfile)) {
+ DLOG(ERROR) << "CopyDirectory() couldn't copy file: " << current.value();
+ return false;
+ }
+ } while (AdvanceEnumeratorWithStat(&traversal, &current, &from_stat));
+
+ return true;
}
#endif // !defined(OS_NACL_NONSFI)
@@ -943,32 +1020,7 @@ bool CopyFile(const FilePath& from_path, const FilePath& to_path) {
if (!outfile.IsValid())
return false;
- const size_t kBufferSize = 32768;
- std::vector<char> buffer(kBufferSize);
- bool result = true;
-
- while (result) {
- ssize_t bytes_read = infile.ReadAtCurrentPos(&buffer[0], buffer.size());
- if (bytes_read < 0) {
- result = false;
- break;
- }
- if (bytes_read == 0)
- break;
- // Allow for partial writes
- ssize_t bytes_written_per_read = 0;
- do {
- ssize_t bytes_written_partial = outfile.WriteAtCurrentPos(
- &buffer[bytes_written_per_read], bytes_read - bytes_written_per_read);
- if (bytes_written_partial < 0) {
- result = false;
- break;
- }
- bytes_written_per_read += bytes_written_partial;
- } while (bytes_written_per_read < bytes_read);
- }
-
- return result;
+ return CopyFileContents(&infile, &outfile);
}
#endif // !defined(OS_MACOSX)
diff --git a/chromium/base/files/file_util_unittest.cc b/chromium/base/files/file_util_unittest.cc
index 5b98069c8ba..3f2e0f0876b 100644
--- a/chromium/base/files/file_util_unittest.cc
+++ b/chromium/base/files/file_util_unittest.cc
@@ -8,6 +8,7 @@
#include <algorithm>
#include <fstream>
#include <initializer_list>
+#include <memory>
#include <set>
#include <utility>
#include <vector>
@@ -632,8 +633,7 @@ TEST_F(FileUtilTest, CreateAndReadSymlinks) {
// If we created the link properly, we should be able to read the contents
// through it.
- std::wstring contents = ReadTextFile(link_from);
- EXPECT_EQ(bogus_content, contents);
+ EXPECT_EQ(bogus_content, ReadTextFile(link_from));
FilePath result;
ASSERT_TRUE(ReadSymbolicLink(link_from, &result));
@@ -737,20 +737,46 @@ TEST_F(FileUtilTest, DeleteSymlinkToNonExistentFile) {
EXPECT_FALSE(IsLink(file_link));
}
+TEST_F(FileUtilTest, CopyFileFollowsSymlinks) {
+ FilePath link_from = temp_dir_.GetPath().Append(FPL("from_file"));
+ FilePath link_to = temp_dir_.GetPath().Append(FPL("to_file"));
+ CreateTextFile(link_to, bogus_content);
+
+ ASSERT_TRUE(CreateSymbolicLink(link_to, link_from));
+
+ // If we created the link properly, we should be able to read the contents
+ // through it.
+ EXPECT_EQ(bogus_content, ReadTextFile(link_from));
+
+ FilePath result;
+ ASSERT_TRUE(ReadSymbolicLink(link_from, &result));
+ EXPECT_EQ(link_to.value(), result.value());
+
+ // Create another file and copy it to |link_from|.
+ FilePath src_file = temp_dir_.GetPath().Append(FPL("src.txt"));
+ const std::wstring file_contents(L"Gooooooooooooooooooooogle");
+ CreateTextFile(src_file, file_contents);
+ ASSERT_TRUE(CopyFile(src_file, link_from));
+
+ // Make sure |link_from| is still a symlink, and |link_to| has been written to
+ // by CopyFile().
+ EXPECT_TRUE(IsLink(link_from));
+ EXPECT_EQ(file_contents, ReadTextFile(link_from));
+ EXPECT_EQ(file_contents, ReadTextFile(link_to));
+}
+
TEST_F(FileUtilTest, ChangeFilePermissionsAndRead) {
// Create a file path.
FilePath file_name =
temp_dir_.GetPath().Append(FPL("Test Readable File.txt"));
EXPECT_FALSE(PathExists(file_name));
- const std::string kData("hello");
-
- int buffer_size = kData.length();
- char* buffer = new char[buffer_size];
+ static constexpr char kData[] = "hello";
+ static constexpr int kDataSize = sizeof(kData) - 1;
+ char buffer[kDataSize];
// Write file.
- EXPECT_EQ(static_cast<int>(kData.length()),
- WriteFile(file_name, kData.data(), kData.length()));
+ EXPECT_EQ(kDataSize, WriteFile(file_name, kData, kDataSize));
EXPECT_TRUE(PathExists(file_name));
// Make sure the file is readable.
@@ -763,21 +789,18 @@ TEST_F(FileUtilTest, ChangeFilePermissionsAndRead) {
EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
EXPECT_FALSE(mode & FILE_PERMISSION_READ_BY_USER);
// Make sure the file can't be read.
- EXPECT_EQ(-1, ReadFile(file_name, buffer, buffer_size));
+ EXPECT_EQ(-1, ReadFile(file_name, buffer, kDataSize));
// Give the read permission.
EXPECT_TRUE(SetPosixFilePermissions(file_name, FILE_PERMISSION_READ_BY_USER));
EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
EXPECT_TRUE(mode & FILE_PERMISSION_READ_BY_USER);
// Make sure the file can be read.
- EXPECT_EQ(static_cast<int>(kData.length()),
- ReadFile(file_name, buffer, buffer_size));
+ EXPECT_EQ(kDataSize, ReadFile(file_name, buffer, kDataSize));
// Delete the file.
EXPECT_TRUE(DeleteFile(file_name, false));
EXPECT_FALSE(PathExists(file_name));
-
- delete[] buffer;
}
TEST_F(FileUtilTest, ChangeFilePermissionsAndWrite) {
@@ -907,6 +930,193 @@ TEST_F(FileUtilTest, ExecutableExistsInPath) {
EXPECT_FALSE(ExecutableExistsInPath(scoped_env.GetEnv(), kDneFileName));
}
+TEST_F(FileUtilTest, CopyDirectoryPermissions) {
+ // Create a directory.
+ FilePath dir_name_from =
+ temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
+ CreateDirectory(dir_name_from);
+ ASSERT_TRUE(PathExists(dir_name_from));
+
+ // Create some regular files under the directory with various permissions.
+ FilePath file_name_from =
+ dir_name_from.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
+ CreateTextFile(file_name_from, L"Mordecai");
+ ASSERT_TRUE(PathExists(file_name_from));
+ ASSERT_TRUE(SetPosixFilePermissions(file_name_from, 0755));
+
+ FilePath file2_name_from =
+ dir_name_from.Append(FILE_PATH_LITERAL("Reggy-2.txt"));
+ CreateTextFile(file2_name_from, L"Rigby");
+ ASSERT_TRUE(PathExists(file2_name_from));
+ ASSERT_TRUE(SetPosixFilePermissions(file2_name_from, 0777));
+
+ FilePath file3_name_from =
+ dir_name_from.Append(FILE_PATH_LITERAL("Reggy-3.txt"));
+ CreateTextFile(file3_name_from, L"Benson");
+ ASSERT_TRUE(PathExists(file3_name_from));
+ ASSERT_TRUE(SetPosixFilePermissions(file3_name_from, 0400));
+
+ // Copy the directory recursively.
+ FilePath dir_name_to =
+ temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
+ FilePath file_name_to =
+ dir_name_to.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
+ FilePath file2_name_to =
+ dir_name_to.Append(FILE_PATH_LITERAL("Reggy-2.txt"));
+ FilePath file3_name_to =
+ dir_name_to.Append(FILE_PATH_LITERAL("Reggy-3.txt"));
+
+ ASSERT_FALSE(PathExists(dir_name_to));
+
+ EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, true));
+ ASSERT_TRUE(PathExists(file_name_to));
+ ASSERT_TRUE(PathExists(file2_name_to));
+ ASSERT_TRUE(PathExists(file3_name_to));
+
+ int mode = 0;
+ int expected_mode;
+ ASSERT_TRUE(GetPosixFilePermissions(file_name_to, &mode));
+#if defined(OS_MACOSX)
+ expected_mode = 0755;
+#elif defined(OS_CHROMEOS)
+ expected_mode = 0644;
+#else
+ expected_mode = 0600;
+#endif
+ EXPECT_EQ(expected_mode, mode);
+
+ ASSERT_TRUE(GetPosixFilePermissions(file2_name_to, &mode));
+#if defined(OS_MACOSX)
+ expected_mode = 0755;
+#elif defined(OS_CHROMEOS)
+ expected_mode = 0644;
+#else
+ expected_mode = 0600;
+#endif
+ EXPECT_EQ(expected_mode, mode);
+
+ ASSERT_TRUE(GetPosixFilePermissions(file3_name_to, &mode));
+#if defined(OS_MACOSX)
+ expected_mode = 0600;
+#elif defined(OS_CHROMEOS)
+ expected_mode = 0644;
+#else
+ expected_mode = 0600;
+#endif
+ EXPECT_EQ(expected_mode, mode);
+}
+
+TEST_F(FileUtilTest, CopyDirectoryPermissionsOverExistingFile) {
+ // Create a directory.
+ FilePath dir_name_from =
+ temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
+ CreateDirectory(dir_name_from);
+ ASSERT_TRUE(PathExists(dir_name_from));
+
+ // Create a file under the directory.
+ FilePath file_name_from =
+ dir_name_from.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
+ CreateTextFile(file_name_from, L"Mordecai");
+ ASSERT_TRUE(PathExists(file_name_from));
+ ASSERT_TRUE(SetPosixFilePermissions(file_name_from, 0644));
+
+ // Create a directory.
+ FilePath dir_name_to =
+ temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
+ CreateDirectory(dir_name_to);
+ ASSERT_TRUE(PathExists(dir_name_to));
+
+ // Create a file under the directory with wider permissions.
+ FilePath file_name_to =
+ dir_name_to.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
+ CreateTextFile(file_name_to, L"Rigby");
+ ASSERT_TRUE(PathExists(file_name_to));
+ ASSERT_TRUE(SetPosixFilePermissions(file_name_to, 0777));
+
+ // Ensure that when we copy the directory, the file contents are copied
+ // but the permissions on the destination are left alone.
+ EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, false));
+ ASSERT_TRUE(PathExists(file_name_to));
+ ASSERT_EQ(L"Mordecai", ReadTextFile(file_name_to));
+
+ int mode = 0;
+ ASSERT_TRUE(GetPosixFilePermissions(file_name_to, &mode));
+ EXPECT_EQ(0777, mode);
+}
+
+TEST_F(FileUtilTest, CopyFileExecutablePermission) {
+ FilePath src = temp_dir_.GetPath().Append(FPL("src.txt"));
+ const std::wstring file_contents(L"Gooooooooooooooooooooogle");
+ CreateTextFile(src, file_contents);
+
+ ASSERT_TRUE(SetPosixFilePermissions(src, 0755));
+ int mode = 0;
+ ASSERT_TRUE(GetPosixFilePermissions(src, &mode));
+ EXPECT_EQ(0755, mode);
+
+ FilePath dst = temp_dir_.GetPath().Append(FPL("dst.txt"));
+ ASSERT_TRUE(CopyFile(src, dst));
+ EXPECT_EQ(file_contents, ReadTextFile(dst));
+
+ ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
+ int expected_mode;
+#if defined(OS_MACOSX)
+ expected_mode = 0755;
+#elif defined(OS_CHROMEOS)
+ expected_mode = 0644;
+#else
+ expected_mode = 0600;
+#endif
+ EXPECT_EQ(expected_mode, mode);
+ ASSERT_TRUE(DeleteFile(dst, false));
+
+ ASSERT_TRUE(SetPosixFilePermissions(src, 0777));
+ ASSERT_TRUE(GetPosixFilePermissions(src, &mode));
+ EXPECT_EQ(0777, mode);
+
+ ASSERT_TRUE(CopyFile(src, dst));
+ EXPECT_EQ(file_contents, ReadTextFile(dst));
+
+ ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
+#if defined(OS_MACOSX)
+ expected_mode = 0755;
+#elif defined(OS_CHROMEOS)
+ expected_mode = 0644;
+#else
+ expected_mode = 0600;
+#endif
+ EXPECT_EQ(expected_mode, mode);
+ ASSERT_TRUE(DeleteFile(dst, false));
+
+ ASSERT_TRUE(SetPosixFilePermissions(src, 0400));
+ ASSERT_TRUE(GetPosixFilePermissions(src, &mode));
+ EXPECT_EQ(0400, mode);
+
+ ASSERT_TRUE(CopyFile(src, dst));
+ EXPECT_EQ(file_contents, ReadTextFile(dst));
+
+ ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
+#if defined(OS_MACOSX)
+ expected_mode = 0600;
+#elif defined(OS_CHROMEOS)
+ expected_mode = 0644;
+#else
+ expected_mode = 0600;
+#endif
+ EXPECT_EQ(expected_mode, mode);
+
+ // This time, do not delete |dst|. Instead set its permissions to 0777.
+ ASSERT_TRUE(SetPosixFilePermissions(dst, 0777));
+ ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
+ EXPECT_EQ(0777, mode);
+
+ // Overwrite it and check the permissions again.
+ ASSERT_TRUE(CopyFile(src, dst));
+ EXPECT_EQ(file_contents, ReadTextFile(dst));
+ ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
+ EXPECT_EQ(0777, mode);
+}
+
#endif // !defined(OS_FUCHSIA) && defined(OS_POSIX)
#if !defined(OS_FUCHSIA)
@@ -1550,12 +1760,64 @@ TEST_F(FileUtilTest, CopyDirectoryWithTrailingSeparators) {
EXPECT_TRUE(PathExists(file_name_to));
}
+#if !defined(OS_FUCHSIA) && defined(OS_POSIX)
+TEST_F(FileUtilTest, CopyDirectoryWithNonRegularFiles) {
+ // Create a directory.
+ FilePath dir_name_from =
+ temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
+ ASSERT_TRUE(CreateDirectory(dir_name_from));
+ ASSERT_TRUE(PathExists(dir_name_from));
+
+ // Create a file under the directory.
+ FilePath file_name_from =
+ dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
+ CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
+ ASSERT_TRUE(PathExists(file_name_from));
+
+ // Create a symbolic link under the directory pointing to that file.
+ FilePath symlink_name_from =
+ dir_name_from.Append(FILE_PATH_LITERAL("Symlink"));
+ ASSERT_TRUE(CreateSymbolicLink(file_name_from, symlink_name_from));
+ ASSERT_TRUE(PathExists(symlink_name_from));
+
+ // Create a fifo under the directory.
+ FilePath fifo_name_from =
+ dir_name_from.Append(FILE_PATH_LITERAL("Fifo"));
+ ASSERT_EQ(0, mkfifo(fifo_name_from.value().c_str(), 0644));
+ ASSERT_TRUE(PathExists(fifo_name_from));
+
+ // Copy the directory.
+ FilePath dir_name_to =
+ temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
+ FilePath file_name_to =
+ dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
+ FilePath symlink_name_to =
+ dir_name_to.Append(FILE_PATH_LITERAL("Symlink"));
+ FilePath fifo_name_to =
+ dir_name_to.Append(FILE_PATH_LITERAL("Fifo"));
+
+ ASSERT_FALSE(PathExists(dir_name_to));
+
+ EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, false));
+
+ // Check that only directories and regular files are copied.
+ EXPECT_TRUE(PathExists(dir_name_from));
+ EXPECT_TRUE(PathExists(file_name_from));
+ EXPECT_TRUE(PathExists(symlink_name_from));
+ EXPECT_TRUE(PathExists(fifo_name_from));
+ EXPECT_TRUE(PathExists(dir_name_to));
+ EXPECT_TRUE(PathExists(file_name_to));
+ EXPECT_FALSE(PathExists(symlink_name_to));
+ EXPECT_FALSE(PathExists(fifo_name_to));
+}
+#endif // !defined(OS_FUCHSIA) && defined(OS_POSIX)
+
TEST_F(FileUtilTest, CopyFile) {
// Create a directory
FilePath dir_name_from =
temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
- CreateDirectory(dir_name_from);
- ASSERT_TRUE(PathExists(dir_name_from));
+ ASSERT_TRUE(CreateDirectory(dir_name_from));
+ ASSERT_TRUE(DirectoryExists(dir_name_from));
// Create a file under the directory
FilePath file_name_from =
@@ -1581,10 +1843,31 @@ TEST_F(FileUtilTest, CopyFile) {
// Check expected copy results.
EXPECT_TRUE(PathExists(file_name_from));
EXPECT_TRUE(PathExists(dest_file));
- const std::wstring read_contents = ReadTextFile(dest_file);
- EXPECT_EQ(file_contents, read_contents);
+ EXPECT_EQ(file_contents, ReadTextFile(dest_file));
EXPECT_FALSE(PathExists(dest_file2_test));
EXPECT_FALSE(PathExists(dest_file2));
+
+ // Change |file_name_from| contents.
+ const std::wstring new_file_contents(L"Moogle");
+ CreateTextFile(file_name_from, new_file_contents);
+ ASSERT_TRUE(PathExists(file_name_from));
+ EXPECT_EQ(new_file_contents, ReadTextFile(file_name_from));
+
+ // Overwrite |dest_file|.
+ ASSERT_TRUE(CopyFile(file_name_from, dest_file));
+ EXPECT_TRUE(PathExists(dest_file));
+ EXPECT_EQ(new_file_contents, ReadTextFile(dest_file));
+
+ // Create another directory.
+ FilePath dest_dir = temp_dir_.GetPath().Append(FPL("dest_dir"));
+ ASSERT_TRUE(CreateDirectory(dest_dir));
+ EXPECT_TRUE(DirectoryExists(dest_dir));
+ EXPECT_TRUE(IsDirectoryEmpty(dest_dir));
+
+ // Make sure CopyFile() cannot overwrite a directory.
+ ASSERT_FALSE(CopyFile(file_name_from, dest_dir));
+ EXPECT_TRUE(DirectoryExists(dest_dir));
+ EXPECT_TRUE(IsDirectoryEmpty(dest_dir));
}
// file_util winds up using autoreleased objects on the Mac, so this needs
@@ -2584,7 +2867,7 @@ TEST_F(FileUtilTest, ValidContentUriTest) {
FilePath image_file = data_dir.Append(FILE_PATH_LITERAL("red.png"));
int64_t image_size;
GetFileSize(image_file, &image_size);
- EXPECT_LT(0, image_size);
+ ASSERT_GT(image_size, 0);
// Insert the image into MediaStore. MediaStore will do some conversions, and
// return the content URI.
@@ -2598,11 +2881,10 @@ TEST_F(FileUtilTest, ValidContentUriTest) {
EXPECT_EQ(image_size, content_uri_size);
// We should be able to read the file.
- char* buffer = new char[image_size];
File file = OpenContentUriForRead(path);
EXPECT_TRUE(file.IsValid());
- EXPECT_TRUE(file.ReadAtCurrentPos(buffer, image_size));
- delete[] buffer;
+ auto buffer = std::make_unique<char[]>(image_size);
+ EXPECT_TRUE(file.ReadAtCurrentPos(buffer.get(), image_size));
}
TEST_F(FileUtilTest, NonExistentContentUriTest) {