diff options
Diffstat (limited to 'chromium/base/files')
-rw-r--r-- | chromium/base/files/file_descriptor_watcher_posix.h | 2 | ||||
-rw-r--r-- | chromium/base/files/file_enumerator.h | 6 | ||||
-rw-r--r-- | chromium/base/files/file_path.cc | 41 | ||||
-rw-r--r-- | chromium/base/files/file_path.h | 2 | ||||
-rw-r--r-- | chromium/base/files/file_path_watcher_linux.cc | 2 | ||||
-rw-r--r-- | chromium/base/files/file_path_watcher_unittest.cc | 1 | ||||
-rw-r--r-- | chromium/base/files/file_util.cc | 16 | ||||
-rw-r--r-- | chromium/base/files/file_util.h | 54 | ||||
-rw-r--r-- | chromium/base/files/file_util_posix.cc | 39 | ||||
-rw-r--r-- | chromium/base/files/file_util_unittest.cc | 88 | ||||
-rw-r--r-- | chromium/base/files/file_util_win.cc | 8 | ||||
-rw-r--r-- | chromium/base/files/important_file_writer.cc | 23 | ||||
-rw-r--r-- | chromium/base/files/important_file_writer_cleaner_unittest.cc | 2 | ||||
-rw-r--r-- | chromium/base/files/memory_mapped_file.cc | 1 | ||||
-rw-r--r-- | chromium/base/files/memory_mapped_file_win.cc | 1 | ||||
-rw-r--r-- | chromium/base/files/scoped_file.h | 1 |
16 files changed, 202 insertions, 85 deletions
diff --git a/chromium/base/files/file_descriptor_watcher_posix.h b/chromium/base/files/file_descriptor_watcher_posix.h index 3230350efb6..51958d19ccb 100644 --- a/chromium/base/files/file_descriptor_watcher_posix.h +++ b/chromium/base/files/file_descriptor_watcher_posix.h @@ -9,7 +9,7 @@ #include "base/base_export.h" #include "base/callback.h" -#include "base/logging.h" +#include "base/check_op.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" diff --git a/chromium/base/files/file_enumerator.h b/chromium/base/files/file_enumerator.h index de702e1ca6c..b2bd5ab8dd9 100644 --- a/chromium/base/files/file_enumerator.h +++ b/chromium/base/files/file_enumerator.h @@ -37,9 +37,9 @@ namespace base { // // Example: // -// base::FileEnumerator enum(my_dir, false, base::FileEnumerator::FILES, -// FILE_PATH_LITERAL("*.txt")); -// for (base::FilePath name = enum.Next(); !name.empty(); name = enum.Next()) +// base::FileEnumerator e(my_dir, false, base::FileEnumerator::FILES, +// FILE_PATH_LITERAL("*.txt")); +// for (base::FilePath name = e.Next(); !name.empty(); name = e.Next()) // ... class BASE_EXPORT FileEnumerator { public: diff --git a/chromium/base/files/file_path.cc b/chromium/base/files/file_path.cc index f1a4b0a9bf6..56c02d2bfc7 100644 --- a/chromium/base/files/file_path.cc +++ b/chromium/base/files/file_path.cc @@ -40,20 +40,6 @@ const char* const kCommonDoubleExtensionSuffixes[] = {"gz", "xz", "bz2", "z", "bz"}; const char* const kCommonDoubleExtensions[] = { "user.js" }; -// Compatibility shim for cross-platform code that passes a StringPieceType to a -// string utility function. Most of these functions are only implemented for -// base::StringPiece and base::StringPiece16, which is why base::WStringPieces -// need to be converted. -#if defined(OS_WIN) -StringPiece16 AsCommonStringPiece(WStringPiece str) { - return AsStringPiece16(str); -} -#else -StringPiece AsCommonStringPiece(StringPiece str) { - return str; -} -#endif - const FilePath::CharType kStringTerminator = FILE_PATH_LITERAL('\0'); // If this FilePath contains a drive letter specification, returns the @@ -84,8 +70,7 @@ bool EqualDriveLetterCaseInsensitive(StringPieceType a, StringPieceType b) { StringPieceType a_letter(a.substr(0, a_letter_pos + 1)); StringPieceType b_letter(b.substr(0, b_letter_pos + 1)); - if (!StartsWith(AsCommonStringPiece(a_letter), AsCommonStringPiece(b_letter), - CompareCase::INSENSITIVE_ASCII)) + if (!StartsWith(a_letter, b_letter, CompareCase::INSENSITIVE_ASCII)) return false; StringPieceType a_rest(a.substr(a_letter_pos + 1)); @@ -156,13 +141,13 @@ StringType::size_type ExtensionSeparatorPosition(const StringType& path) { for (auto* i : kCommonDoubleExtensions) { StringType extension(path, penultimate_dot + 1); - if (LowerCaseEqualsASCII(AsCommonStringPiece(extension), i)) + if (LowerCaseEqualsASCII(extension, i)) return penultimate_dot; } StringType extension(path, last_dot + 1); for (auto* i : kCommonDoubleExtensionSuffixes) { - if (LowerCaseEqualsASCII(AsCommonStringPiece(extension), i)) { + if (LowerCaseEqualsASCII(extension, i)) { if ((last_dot - penultimate_dot) <= 5U && (last_dot - penultimate_dot) > 1U) { return penultimate_dot; @@ -201,7 +186,7 @@ FilePath::~FilePath() = default; FilePath& FilePath::operator=(const FilePath& that) = default; -FilePath& FilePath::operator=(FilePath&& that) = default; +FilePath& FilePath::operator=(FilePath&& that) noexcept = default; bool FilePath::operator==(const FilePath& that) const { #if defined(FILE_PATH_USES_DRIVE_LETTERS) @@ -295,9 +280,7 @@ bool FilePath::AppendRelativePath(const FilePath& child, // never case sensitive. if ((FindDriveLetter(*parent_comp) != StringType::npos) && (FindDriveLetter(*child_comp) != StringType::npos)) { - if (!StartsWith(AsCommonStringPiece(*parent_comp), - AsCommonStringPiece(*child_comp), - CompareCase::INSENSITIVE_ASCII)) + if (!StartsWith(*parent_comp, *child_comp, CompareCase::INSENSITIVE_ASCII)) return false; ++parent_comp; ++child_comp; @@ -613,21 +596,19 @@ bool FilePath::ReferencesParent() const { #if defined(OS_WIN) string16 FilePath::LossyDisplayName() const { - return string16(as_u16cstr(path_.data()), path_.size()); + return AsString16(path_); } std::string FilePath::MaybeAsASCII() const { - if (base::IsStringASCII(AsCommonStringPiece(path_))) - return UTF16ToASCII(AsCommonStringPiece(path_)); - return std::string(); + return base::IsStringASCII(path_) ? WideToASCII(path_) : std::string(); } std::string FilePath::AsUTF8Unsafe() const { - return UTF16ToUTF8(AsCommonStringPiece(value())); + return WideToUTF8(value()); } string16 FilePath::AsUTF16Unsafe() const { - return string16(AsCommonStringPiece(value())); + return WideToUTF16(value()); } // static @@ -637,7 +618,7 @@ FilePath FilePath::FromUTF8Unsafe(StringPiece utf8) { // static FilePath FilePath::FromUTF16Unsafe(StringPiece16 utf16) { - return FilePath(WStringPiece(as_wcstr(utf16.data()), utf16.size())); + return FilePath(AsWStringPiece(utf16)); } #elif defined(OS_POSIX) || defined(OS_FUCHSIA) @@ -693,7 +674,7 @@ FilePath FilePath::FromUTF16Unsafe(StringPiece16 utf16) { void FilePath::WriteToPickle(Pickle* pickle) const { #if defined(OS_WIN) - pickle->WriteString16(AsCommonStringPiece(path_)); + pickle->WriteString16(AsStringPiece16(path_)); #elif defined(OS_POSIX) || defined(OS_FUCHSIA) pickle->WriteString(path_); #else diff --git a/chromium/base/files/file_path.h b/chromium/base/files/file_path.h index 4e23f71a92a..2160fdaca31 100644 --- a/chromium/base/files/file_path.h +++ b/chromium/base/files/file_path.h @@ -193,7 +193,7 @@ class BASE_EXPORT FilePath { FilePath(FilePath&& that) noexcept; // Replaces the contents with those of |that|, which is left in valid but // unspecified state. - FilePath& operator=(FilePath&& that); + FilePath& operator=(FilePath&& that) noexcept; bool operator==(const FilePath& that) const; diff --git a/chromium/base/files/file_path_watcher_linux.cc b/chromium/base/files/file_path_watcher_linux.cc index 563e0806758..7a04ac7dfef 100644 --- a/chromium/base/files/file_path_watcher_linux.cc +++ b/chromium/base/files/file_path_watcher_linux.cc @@ -38,7 +38,7 @@ #include "base/threading/platform_thread.h" #include "base/threading/scoped_blocking_call.h" #include "base/threading/sequenced_task_runner_handle.h" -#include "base/trace_event/trace_event.h" +#include "base/trace_event/base_tracing.h" namespace base { diff --git a/chromium/base/files/file_path_watcher_unittest.cc b/chromium/base/files/file_path_watcher_unittest.cc index ccefc27666b..055e0af45d9 100644 --- a/chromium/base/files/file_path_watcher_unittest.cc +++ b/chromium/base/files/file_path_watcher_unittest.cc @@ -20,6 +20,7 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/location.h" +#include "base/logging.h" #include "base/macros.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" diff --git a/chromium/base/files/file_util.cc b/chromium/base/files/file_util.cc index 546934b7084..27a2e428d54 100644 --- a/chromium/base/files/file_util.cc +++ b/chromium/base/files/file_util.cc @@ -27,6 +27,22 @@ namespace base { #if !defined(OS_NACL_NONSFI) +namespace { + +void DeleteFileHelper(const FilePath& path) { + DeleteFile(path, /*recursive=*/false); +} + +} // namespace + +OnceCallback<void(const FilePath&)> GetDeleteFileCallback() { + return BindOnce(&DeleteFileHelper); +} + +OnceCallback<void(const FilePath&)> GetDeletePathRecursivelyCallback() { + return BindOnce(IgnoreResult(&DeleteFileRecursively)); +} + int64_t ComputeDirectorySize(const FilePath& root_path) { int64_t running_size = 0; FileEnumerator file_iter(root_path, true, FileEnumerator::FILES); diff --git a/chromium/base/files/file_util.h b/chromium/base/files/file_util.h index 76bd98767f5..c9c2470942f 100644 --- a/chromium/base/files/file_util.h +++ b/chromium/base/files/file_util.h @@ -23,6 +23,7 @@ #endif #include "base/base_export.h" +#include "base/callback_forward.h" #include "base/containers/span.h" #include "base/files/file.h" #include "base/files/file_path.h" @@ -34,7 +35,6 @@ #include "base/win/windows_types.h" #elif defined(OS_POSIX) || defined(OS_FUCHSIA) #include "base/file_descriptor_posix.h" -#include "base/logging.h" #include "base/posix/eintr_wrapper.h" #endif @@ -59,33 +59,54 @@ BASE_EXPORT FilePath MakeAbsoluteFilePath(const FilePath& input); BASE_EXPORT int64_t ComputeDirectorySize(const FilePath& root_path); // Deletes the given path, whether it's a file or a directory. +// If it's a directory, it's perfectly happy to delete all of the directory's +// contents, but it will not recursively delete subdirectories and their +// contents. +// Returns true if successful, false otherwise. It is considered successful to +// attempt to delete a file that does not exist. +// +// In POSIX environment and if |path| is a symbolic link, this deletes only +// the symlink. (even if the symlink points to a non-existent file) +BASE_EXPORT bool DeleteFile(const FilePath& path); + +// Deletes the given path, whether it's a file or a directory. // If it's a directory, it's perfectly happy to delete all of the -// directory's contents. Passing true to recursive deletes -// subdirectories and their contents as well. +// directory's contents, including subdirectories and their contents. // Returns true if successful, false otherwise. It is considered successful // to attempt to delete a file that does not exist. // // In POSIX environment and if |path| is a symbolic link, this deletes only // the symlink. (even if the symlink points to a non-existent file) // -// WARNING: USING THIS WITH recursive==true IS EQUIVALENT -// TO "rm -rf", SO USE WITH CAUTION. -// -// Note: The |recursive| parameter is in the process of being removed. Use -// DeleteFileRecursively() instead. See https://crbug.com/1009837 -BASE_EXPORT bool DeleteFile(const FilePath& path, bool recursive); +// WARNING: USING THIS EQUIVALENT TO "rm -rf", SO USE WITH CAUTION. +// TODO(thestig): Rename to DeletePathRecursively(). +BASE_EXPORT bool DeleteFileRecursively(const FilePath& path); +// DEPRECATED. Please use the functions immediately above. +// https://crbug.com/1009837 +// // Deletes the given path, whether it's a file or a directory. // If it's a directory, it's perfectly happy to delete all of the -// directory's contents, including subdirectories and their contents. +// directory's contents. Passing true to recursively delete +// subdirectories and their contents as well. // Returns true if successful, false otherwise. It is considered successful // to attempt to delete a file that does not exist. // // In POSIX environment and if |path| is a symbolic link, this deletes only // the symlink. (even if the symlink points to a non-existent file) // -// WARNING: USING THIS EQUIVALENT TO "rm -rf", SO USE WITH CAUTION. -BASE_EXPORT bool DeleteFileRecursively(const FilePath& path); +// WARNING: USING THIS WITH recursive==true IS EQUIVALENT +// TO "rm -rf", SO USE WITH CAUTION. +BASE_EXPORT bool DeleteFile(const FilePath& path, bool recursive); + +// Simplified way to get a callback to do DeleteFile(path) and ignore the +// DeleteFile() result. +BASE_EXPORT OnceCallback<void(const FilePath&)> GetDeleteFileCallback(); + +// Simplified way to get a callback to do DeleteFileRecursively(path) and ignore +// the DeleteFileRecursively() result. +BASE_EXPORT OnceCallback<void(const FilePath&)> +GetDeletePathRecursivelyCallback(); #if defined(OS_WIN) // Schedules to delete the given path, whether it's a file or a directory, until @@ -223,6 +244,15 @@ BASE_EXPORT ScopedFD CreateAndOpenFdForTemporaryFileInDir(const FilePath& dir, #if defined(OS_POSIX) +// ReadFileToStringNonBlocking is identical to ReadFileToString except it +// guarantees that it will not block. This guarantee is provided on POSIX by +// opening the file as O_NONBLOCK. This variant should only be used on files +// which are guaranteed not to block (such as kernel files). Or in situations +// where a partial read would be acceptable because the backing store returned +// EWOULDBLOCK. +BASE_EXPORT bool ReadFileToStringNonBlocking(const base::FilePath& file, + std::string* ret); + // Creates a symbolic link at |symlink| pointing to |target|. Returns // false on failure. BASE_EXPORT bool CreateSymbolicLink(const FilePath& target, diff --git a/chromium/base/files/file_util_posix.cc b/chromium/base/files/file_util_posix.cc index 91514251d9c..dea1a945826 100644 --- a/chromium/base/files/file_util_posix.cc +++ b/chromium/base/files/file_util_posix.cc @@ -367,14 +367,18 @@ FilePath MakeAbsoluteFilePath(const FilePath& input) { return FilePath(full_path); } -bool DeleteFile(const FilePath& path, bool recursive) { - return DoDeleteFile(path, recursive); +bool DeleteFile(const FilePath& path) { + return DoDeleteFile(path, /*recursive=*/false); } bool DeleteFileRecursively(const FilePath& path) { return DoDeleteFile(path, /*recursive=*/true); } +bool DeleteFile(const FilePath& path, bool recursive) { + return DoDeleteFile(path, recursive); +} + bool ReplaceFile(const FilePath& from_path, const FilePath& to_path, File::Error* error) { @@ -736,6 +740,37 @@ bool CreateDirectoryAndGetError(const FilePath& full_path, return true; } +// ReadFileToStringNonBlockingNonBlocking will read a file to a string. This +// method should only be used on files which are known to be non-blocking such +// as procfs or sysfs nodes. Additionally, the file is opened as O_NONBLOCK so +// it WILL NOT block even if opened on a blocking file. It will return true if +// the file read until EOF and it will return false otherwise, errno will remain +// set on error conditions. |ret| will be populated with the contents of the +// file. +bool ReadFileToStringNonBlocking(const base::FilePath& file, std::string* ret) { + DCHECK(ret); + ret->clear(); + + base::ScopedFD fd(HANDLE_EINTR( + open(file.MaybeAsASCII().c_str(), O_CLOEXEC | O_NONBLOCK | O_RDONLY))); + if (!fd.is_valid()) { + return false; + } + + ssize_t bytes_read = 0; + do { + char buf[4096]; + bytes_read = HANDLE_EINTR(read(fd.get(), buf, sizeof(buf))); + if (bytes_read < 0) { + return false; + } else if (bytes_read > 0) { + ret->append(buf, bytes_read); + } + } while (bytes_read > 0); + + return true; +} + bool NormalizeFilePath(const FilePath& path, FilePath* normalized_path) { FilePath real_path_result = MakeAbsoluteFilePath(path); if (real_path_result.empty()) diff --git a/chromium/base/files/file_util_unittest.cc b/chromium/base/files/file_util_unittest.cc index 2ade5709855..701f8b4b6cd 100644 --- a/chromium/base/files/file_util_unittest.cc +++ b/chromium/base/files/file_util_unittest.cc @@ -28,6 +28,7 @@ #include "base/files/scoped_file.h" #include "base/files/scoped_temp_dir.h" #include "base/guid.h" +#include "base/logging.h" #include "base/path_service.h" #include "base/stl_util.h" #include "base/strings/string_util.h" @@ -738,11 +739,11 @@ TEST_F(FileUtilTest, MakeLongFilePathTest) { EXPECT_EQ(long_test_file, MakeLongFilePath(short_test_file)); // MakeLongFilePath should return empty path if file does not exist. - EXPECT_TRUE(DeleteFile(short_test_file, false)); + EXPECT_TRUE(DeleteFile(short_test_file)); EXPECT_TRUE(MakeLongFilePath(short_test_file).empty()); // MakeLongFilePath should return empty path if directory does not exist. - EXPECT_TRUE(DeleteFile(short_test_dir, false)); + EXPECT_TRUE(DeleteFile(short_test_dir)); EXPECT_TRUE(MakeLongFilePath(short_test_dir).empty()); } @@ -850,7 +851,7 @@ TEST_F(FileUtilTest, DeleteSymlinkToExistentFile) { << "Failed to create symlink."; // Delete the symbolic link. - EXPECT_TRUE(DeleteFile(file_link, false)); + EXPECT_TRUE(DeleteFile(file_link)); // Make sure original file is not deleted. EXPECT_FALSE(PathExists(file_link)); @@ -873,7 +874,7 @@ TEST_F(FileUtilTest, DeleteSymlinkToNonExistentFile) { EXPECT_FALSE(PathExists(file_link)); // Delete the symbolic link. - EXPECT_TRUE(DeleteFile(file_link, false)); + EXPECT_TRUE(DeleteFile(file_link)); // Make sure the symbolic link is deleted. EXPECT_FALSE(IsLink(file_link)); @@ -941,7 +942,7 @@ TEST_F(FileUtilTest, ChangeFilePermissionsAndRead) { EXPECT_EQ(kDataSize, ReadFile(file_name, buffer, kDataSize)); // Delete the file. - EXPECT_TRUE(DeleteFile(file_name, false)); + EXPECT_TRUE(DeleteFile(file_name)); EXPECT_FALSE(PathExists(file_name)); } @@ -981,7 +982,7 @@ TEST_F(FileUtilTest, ChangeFilePermissionsAndWrite) { EXPECT_TRUE(PathIsWritable(file_name)); // Delete the file. - EXPECT_TRUE(DeleteFile(file_name, false)); + EXPECT_TRUE(DeleteFile(file_name)); EXPECT_FALSE(PathExists(file_name)); } @@ -1291,7 +1292,7 @@ TEST_F(FileUtilTest, CopyFileExecutablePermission) { expected_mode = 0600; #endif EXPECT_EQ(expected_mode, mode); - ASSERT_TRUE(DeleteFile(dst, false)); + ASSERT_TRUE(DeleteFile(dst)); ASSERT_TRUE(SetPosixFilePermissions(src, 0777)); ASSERT_TRUE(GetPosixFilePermissions(src, &mode)); @@ -1309,7 +1310,7 @@ TEST_F(FileUtilTest, CopyFileExecutablePermission) { expected_mode = 0600; #endif EXPECT_EQ(expected_mode, mode); - ASSERT_TRUE(DeleteFile(dst, false)); + ASSERT_TRUE(DeleteFile(dst)); ASSERT_TRUE(SetPosixFilePermissions(src, 0400)); ASSERT_TRUE(GetPosixFilePermissions(src, &mode)); @@ -1403,7 +1404,7 @@ TEST_F(FileUtilTest, DeleteNonExistent) { temp_dir_.GetPath().AppendASCII("bogus_file_dne.foobar"); ASSERT_FALSE(PathExists(non_existent)); - EXPECT_TRUE(DeleteFile(non_existent, false)); + EXPECT_TRUE(DeleteFile(non_existent)); ASSERT_FALSE(PathExists(non_existent)); EXPECT_TRUE(DeleteFileRecursively(non_existent)); ASSERT_FALSE(PathExists(non_existent)); @@ -1414,7 +1415,7 @@ TEST_F(FileUtilTest, DeleteNonExistentWithNonExistentParent) { non_existent = non_existent.AppendASCII("bogus_subdir"); ASSERT_FALSE(PathExists(non_existent)); - EXPECT_TRUE(DeleteFile(non_existent, false)); + EXPECT_TRUE(DeleteFile(non_existent)); ASSERT_FALSE(PathExists(non_existent)); EXPECT_TRUE(DeleteFileRecursively(non_existent)); ASSERT_FALSE(PathExists(non_existent)); @@ -1427,7 +1428,7 @@ TEST_F(FileUtilTest, DeleteFile) { ASSERT_TRUE(PathExists(file_name)); // Make sure it's deleted - EXPECT_TRUE(DeleteFile(file_name, false)); + EXPECT_TRUE(DeleteFile(file_name)); EXPECT_FALSE(PathExists(file_name)); // Test recursive case, create a new file @@ -1461,7 +1462,7 @@ TEST_F(FileUtilTest, DeleteContentUri) { ASSERT_TRUE(PathExists(uri_path)); // Try deleting the content URI. - EXPECT_TRUE(DeleteFile(uri_path, false)); + EXPECT_TRUE(DeleteFile(uri_path)); EXPECT_FALSE(PathExists(image_copy)); EXPECT_FALSE(PathExists(uri_path)); } @@ -1487,7 +1488,7 @@ TEST_F(FileUtilTest, DeleteWildCard) { directory_contents = directory_contents.Append(FPL("*")); // Delete non-recursively and check that only the file is deleted - EXPECT_TRUE(DeleteFile(directory_contents, false)); + EXPECT_TRUE(DeleteFile(directory_contents)); EXPECT_FALSE(PathExists(file_name)); EXPECT_TRUE(PathExists(subdir_path)); @@ -1510,7 +1511,7 @@ TEST_F(FileUtilTest, DeleteNonExistantWildCard) { directory_contents = directory_contents.Append(FPL("*")); // Delete non-recursively and check nothing got deleted - EXPECT_TRUE(DeleteFile(directory_contents, false)); + EXPECT_TRUE(DeleteFile(directory_contents)); EXPECT_TRUE(PathExists(subdir_path)); // Delete recursively and check nothing got deleted @@ -1540,11 +1541,11 @@ TEST_F(FileUtilTest, DeleteDirNonRecursive) { ASSERT_TRUE(PathExists(subdir_path2)); // Delete non-recursively and check that the empty dir got deleted - EXPECT_TRUE(DeleteFile(subdir_path2, false)); + EXPECT_TRUE(DeleteFile(subdir_path2)); EXPECT_FALSE(PathExists(subdir_path2)); // Delete non-recursively and check that nothing got deleted - EXPECT_FALSE(DeleteFile(test_subdir, false)); + EXPECT_FALSE(DeleteFile(test_subdir)); EXPECT_TRUE(PathExists(test_subdir)); EXPECT_TRUE(PathExists(file_name)); EXPECT_TRUE(PathExists(subdir_path1)); @@ -1632,6 +1633,41 @@ TEST_F(FileUtilTest, DeleteDirRecursiveWithOpenFile) { #endif } +#if defined(OS_LINUX) +// This test will validate that files which would block when read result in a +// failure on a call to ReadFileToStringNonBlocking. To accomplish this we will +// use a named pipe because it appears as a file on disk and we can control how +// much data is available to read. This allows us to simulate a file which would +// block. +TEST_F(FileUtilTest, TestNonBlockingFileReadLinux) { + FilePath fifo_path = temp_dir_.GetPath().Append(FPL("fifo")); + int res = mkfifo(fifo_path.MaybeAsASCII().c_str(), + S_IWUSR | S_IRUSR | S_IWGRP | S_IWGRP); + ASSERT_NE(res, -1); + + base::ScopedFD fd(open(fifo_path.MaybeAsASCII().c_str(), O_RDWR)); + ASSERT_TRUE(fd.is_valid()); + + std::string result; + // We will try to read when nothing is available on the fifo, the output + // string will be unmodified and it will fail with EWOULDBLOCK. + ASSERT_FALSE(ReadFileToStringNonBlocking(fifo_path, &result)); + EXPECT_EQ(errno, EWOULDBLOCK); + EXPECT_TRUE(result.empty()); + + // Make a single byte available to read on the FIFO. + ASSERT_EQ(write(fd.get(), "a", 1), 1); + + // Now the key part of the test we will call ReadFromFileNonBlocking which + // should fail, errno will be EWOULDBLOCK and the output string will contain + // the single 'a' byte. + ASSERT_FALSE(ReadFileToStringNonBlocking(fifo_path, &result)); + EXPECT_EQ(errno, EWOULDBLOCK); + ASSERT_EQ(result.size(), 1u); + EXPECT_EQ(result[0], 'a'); +} +#endif // defined(OS_LINUX) + TEST_F(FileUtilTest, MoveFileNew) { // Create a file FilePath file_name_from = @@ -2223,7 +2259,7 @@ TEST_F(FileUtilTest, CopyDirectoryExclFileOverDanglingSymlink) { dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt")); ASSERT_TRUE(CreateSymbolicLink(symlink_target, symlink_name_to)); ASSERT_TRUE(PathExists(symlink_name_to)); - ASSERT_TRUE(DeleteFile(symlink_target, false)); + ASSERT_TRUE(DeleteFile(symlink_target)); // Check that copying fails and that no file was created for the symlink's // referent. @@ -2258,7 +2294,7 @@ TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverDanglingSymlink) { dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt")); ASSERT_TRUE(CreateSymbolicLink(symlink_target, symlink_name_to)); ASSERT_TRUE(PathExists(symlink_name_to)); - ASSERT_TRUE(DeleteFile(symlink_target, false)); + ASSERT_TRUE(DeleteFile(symlink_target)); // Check that copying fails and that no directory was created for the // symlink's referent. @@ -2533,7 +2569,7 @@ TEST_F(FileUtilTest, OpenFileNoInheritance) { ASSERT_NO_FATAL_FAILURE(GetIsInheritable(file, &is_inheritable)); EXPECT_FALSE(is_inheritable); } - ASSERT_TRUE(DeleteFile(file_path, false)); + ASSERT_TRUE(DeleteFile(file_path)); } } @@ -2565,7 +2601,7 @@ TEST_F(FileUtilTest, CreateTemporaryFileTest) { for (int i = 0; i < 3; i++) EXPECT_FALSE(temp_files[i] == temp_files[(i+1)%3]); for (const auto& i : temp_files) - EXPECT_TRUE(DeleteFile(i, false)); + EXPECT_TRUE(DeleteFile(i)); } TEST_F(FileUtilTest, CreateAndOpenTemporaryStreamTest) { @@ -2588,7 +2624,7 @@ TEST_F(FileUtilTest, CreateAndOpenTemporaryStreamTest) { // Close and delete. for (i = 0; i < 3; ++i) { fps[i].reset(); - EXPECT_TRUE(DeleteFile(names[i], false)); + EXPECT_TRUE(DeleteFile(names[i])); } } @@ -2666,7 +2702,7 @@ TEST_F(FileUtilTest, CreateNewTempDirectoryTest) { FilePath temp_dir; ASSERT_TRUE(CreateNewTempDirectory(FilePath::StringType(), &temp_dir)); EXPECT_TRUE(PathExists(temp_dir)); - EXPECT_TRUE(DeleteFile(temp_dir, false)); + EXPECT_TRUE(DeleteFile(temp_dir)); } TEST_F(FileUtilTest, CreateNewTemporaryDirInDirTest) { @@ -2676,7 +2712,7 @@ TEST_F(FileUtilTest, CreateNewTemporaryDirInDirTest) { &new_dir)); EXPECT_TRUE(PathExists(new_dir)); EXPECT_TRUE(temp_dir_.GetPath().IsParent(new_dir)); - EXPECT_TRUE(DeleteFile(new_dir, false)); + EXPECT_TRUE(DeleteFile(new_dir)); } #if defined(OS_POSIX) || defined(OS_FUCHSIA) @@ -2836,7 +2872,7 @@ TEST_F(FileUtilTest, DetectDirectoryTest) { CreateTextFile(test_path, L"test file"); EXPECT_TRUE(PathExists(test_path)); EXPECT_FALSE(DirectoryExists(test_path)); - EXPECT_TRUE(DeleteFile(test_path, false)); + EXPECT_TRUE(DeleteFile(test_path)); EXPECT_TRUE(DeleteFileRecursively(test_root)); } @@ -3105,7 +3141,7 @@ TEST_F(FileUtilTest, ReadFileToString) { EXPECT_EQ(0u, data.length()); // Delete test file. - EXPECT_TRUE(DeleteFile(file_path, false)); + EXPECT_TRUE(DeleteFile(file_path)); data = "temp"; EXPECT_FALSE(ReadFileToString(file_path, &data)); @@ -4153,7 +4189,7 @@ TEST(FileUtilMultiThreadedTest, MAYBE_MultiThreadedTempFiles) { EXPECT_EQ(content, output_file_contents); - DeleteFile(output_filename, false); + DeleteFile(output_filename); }); // Post tasks to each thread in a round-robin fashion to ensure as much diff --git a/chromium/base/files/file_util_win.cc b/chromium/base/files/file_util_win.cc index e0ac2598455..4399e1ae3bb 100644 --- a/chromium/base/files/file_util_win.cc +++ b/chromium/base/files/file_util_win.cc @@ -382,14 +382,18 @@ FilePath MakeAbsoluteFilePath(const FilePath& input) { return FilePath(file_path); } -bool DeleteFile(const FilePath& path, bool recursive) { - return DeleteFileAndRecordMetrics(path, recursive); +bool DeleteFile(const FilePath& path) { + return DeleteFileAndRecordMetrics(path, /*recursive=*/false); } bool DeleteFileRecursively(const FilePath& path) { return DeleteFileAndRecordMetrics(path, /*recursive=*/true); } +bool DeleteFile(const FilePath& path, bool recursive) { + return DeleteFileAndRecordMetrics(path, recursive); +} + bool DeleteFileAfterReboot(const FilePath& path) { ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK); diff --git a/chromium/base/files/important_file_writer.cc b/chromium/base/files/important_file_writer.cc index 79921df5c1f..c956fd351a1 100644 --- a/chromium/base/files/important_file_writer.cc +++ b/chromium/base/files/important_file_writer.cc @@ -30,6 +30,7 @@ #include "base/strings/string_util.h" #include "base/task_runner.h" #include "base/task_runner_util.h" +#include "base/threading/platform_thread.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/thread.h" #include "base/time/time.h" @@ -258,20 +259,32 @@ bool ImportantFileWriter::WriteFileAtomicallyImpl(const FilePath& path, // The file must be closed for ReplaceFile to do its job, which opens up a // race with other software that may open the temp file (e.g., an A/V scanner - // doing its job without oplocks). Close as late as possible to improve the - // chances that the other software will lose the race. + // doing its job without oplocks). Boost a background thread's priority on + // Windows and close as late as possible to improve the chances that the other + // software will lose the race. +#if defined(OS_WIN) + const auto previous_priority = PlatformThread::GetCurrentThreadPriority(); + const bool reset_priority = previous_priority <= ThreadPriority::NORMAL; + if (reset_priority) + PlatformThread::SetCurrentThreadPriority(ThreadPriority::DISPLAY); +#endif // defined(OS_WIN) tmp_file.Close(); - if (!ReplaceFile(tmp_file_path, path, &replace_file_error)) { + const bool result = ReplaceFile(tmp_file_path, path, &replace_file_error); +#if defined(OS_WIN) + if (reset_priority) + PlatformThread::SetCurrentThreadPriority(previous_priority); +#endif // defined(OS_WIN) + + if (!result) { UmaHistogramExactLinearWithSuffix("ImportantFile.FileRenameError", histogram_suffix, -replace_file_error, -File::FILE_ERROR_MAX); LogFailure(path, histogram_suffix, FAILED_RENAMING, "could not rename temporary file"); DeleteTmpFileWithRetry(File(), tmp_file_path, histogram_suffix); - return false; } - return true; + return result; } ImportantFileWriter::ImportantFileWriter( diff --git a/chromium/base/files/important_file_writer_cleaner_unittest.cc b/chromium/base/files/important_file_writer_cleaner_unittest.cc index 6b0d6a5e746..d8121f44759 100644 --- a/chromium/base/files/important_file_writer_cleaner_unittest.cc +++ b/chromium/base/files/important_file_writer_cleaner_unittest.cc @@ -4,11 +4,11 @@ #include "base/files/important_file_writer_cleaner.h" +#include "base/check.h" #include "base/files/file.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" -#include "base/logging.h" #include "base/optional.h" #include "base/process/process.h" #include "base/strings/stringprintf.h" diff --git a/chromium/base/files/memory_mapped_file.cc b/chromium/base/files/memory_mapped_file.cc index 6c8a0d9d581..30aefa1e639 100644 --- a/chromium/base/files/memory_mapped_file.cc +++ b/chromium/base/files/memory_mapped_file.cc @@ -8,6 +8,7 @@ #include "base/files/file_path.h" #include "base/logging.h" +#include "base/notreached.h" #include "base/numerics/safe_math.h" #include "base/system/sys_info.h" #include "build/build_config.h" diff --git a/chromium/base/files/memory_mapped_file_win.cc b/chromium/base/files/memory_mapped_file_win.cc index cb43a879769..d5fece0e510 100644 --- a/chromium/base/files/memory_mapped_file_win.cc +++ b/chromium/base/files/memory_mapped_file_win.cc @@ -10,6 +10,7 @@ #include <limits> #include "base/files/file_path.h" +#include "base/logging.h" #include "base/strings/string16.h" #include "base/threading/scoped_blocking_call.h" #include "base/win/pe_image.h" diff --git a/chromium/base/files/scoped_file.h b/chromium/base/files/scoped_file.h index 78fee9b7944..ee49fd7e655 100644 --- a/chromium/base/files/scoped_file.h +++ b/chromium/base/files/scoped_file.h @@ -10,7 +10,6 @@ #include <memory> #include "base/base_export.h" -#include "base/logging.h" #include "base/scoped_generic.h" #include "build/build_config.h" |