#include "base/files/file_util.h"
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <algorithm>
#include <fstream>
#include <initializer_list>
#include <memory>
#include <set>
#include <utility>
#include <vector>
#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/environment.h"
#include "base/features.h"
#include "base/files/file.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/platform_file.h"
#include "base/files/scoped_file.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/rand_util.h"
#include "base/scoped_environment_variable_override.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/test/multiprocess_test.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/test/test_file_util.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "base/uuid.h"
#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/multiprocess_func_list.h"
#include "testing/platform_test.h"
#include "third_party/abseil-cpp/absl/cleanup/cleanup.h"
#if BUILDFLAG(IS_WIN)
#include <tchar.h>
#include <windows.h>
#include <fileapi.h>
#include <shellapi.h>
#include <shlobj.h>
#include "base/scoped_native_library.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/file_path_reparse_point_win.h"
#include "base/test/gtest_util.h"
#include "base/win/scoped_handle.h"
#include "base/win/win_util.h"
#endif
#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <unistd.h>
#endif
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
#include <sys/socket.h>
#endif
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#include <linux/fs.h>
#endif
#if BUILDFLAG(IS_ANDROID)
#include "base/android/content_uri_utils.h"
#endif
#if BUILDFLAG(IS_FUCHSIA)
#include "base/test/scoped_dev_zero_fuchsia.h"
#endif
#define FPL(x) …
namespace base {
namespace {
const size_t kLargeFileSize = …;
#if BUILDFLAG(IS_WIN)
FilePath MakeShortFilePath(const FilePath& input) {
DWORD path_short_len = ::GetShortPathName(input.value().c_str(), nullptr, 0);
if (path_short_len == 0UL) {
return FilePath();
}
std::wstring path_short_str;
path_short_len = ::GetShortPathName(
input.value().c_str(), WriteInto(&path_short_str, path_short_len),
path_short_len);
if (path_short_len == 0UL) {
return FilePath();
}
return FilePath(path_short_str);
}
#endif
#if BUILDFLAG(IS_MAC)
void ChangePosixFilePermissions(const FilePath& path,
int mode_bits_to_set,
int mode_bits_to_clear) {
ASSERT_FALSE(mode_bits_to_set & mode_bits_to_clear)
<< "Can't set and clear the same bits.";
int mode = 0;
ASSERT_TRUE(GetPosixFilePermissions(path, &mode));
mode |= mode_bits_to_set;
mode &= ~mode_bits_to_clear;
ASSERT_TRUE(SetPosixFilePermissions(path, mode));
}
#endif
#if !BUILDFLAG(IS_FUCHSIA)
void SetReadOnly(const FilePath& path, bool read_only) { … }
bool IsReadOnly(const FilePath& path) { … }
#endif
const wchar_t bogus_content[] = …;
const int FILES_AND_DIRECTORIES = …;
class FileUtilTest : public PlatformTest { … };
class FindResultCollector { … };
void CreateTextFile(const FilePath& filename, const std::wstring& contents) { … }
std::wstring ReadTextFile(const FilePath& filename) { … }
void GetIsInheritable(FILE* stream, bool* is_inheritable) { … }
#if BUILDFLAG(IS_POSIX)
class ScopedWorkingDirectory { … };
TEST_F(FileUtilTest, MakeAbsoluteFilePathNoResolveSymbolicLinks) { … }
#endif
TEST_F(FileUtilTest, FileAndDirectorySize) { … }
TEST_F(FileUtilTest, NormalizeFilePathBasic) { … }
#if BUILDFLAG(IS_WIN)
TEST_F(FileUtilTest, NormalizeFileEmptyFile) {
const wchar_t empty_content[] = L"";
FilePath file_a_path = temp_dir_.GetPath().Append(FPL("file_empty_a"));
FilePath dir_path = temp_dir_.GetPath().Append(FPL("dir"));
FilePath file_b_path = dir_path.Append(FPL("file_empty_b"));
ASSERT_TRUE(CreateDirectory(dir_path));
FilePath normalized_file_a_path, normalized_file_b_path;
ASSERT_FALSE(PathExists(file_a_path));
EXPECT_FALSE(NormalizeFilePath(file_a_path, &normalized_file_a_path))
<< "NormalizeFilePath() should fail on nonexistent paths.";
CreateTextFile(file_a_path, empty_content);
ASSERT_TRUE(PathExists(file_a_path));
EXPECT_TRUE(NormalizeFilePath(file_a_path, &normalized_file_a_path));
CreateTextFile(file_b_path, empty_content);
ASSERT_TRUE(PathExists(file_b_path));
EXPECT_TRUE(NormalizeFilePath(file_b_path, &normalized_file_b_path));
EXPECT_TRUE(normalized_file_a_path.DirName().IsParent(
normalized_file_b_path.DirName()));
}
TEST_F(FileUtilTest, NormalizeFilePathReparsePoints) {
FilePath base_a = temp_dir_.GetPath().Append(FPL("base_a"));
std::wstring temp_base_a = base_a.value();
ASSERT_FALSE(temp_base_a.empty());
temp_base_a[0] = ToUpperASCII(char16_t{temp_base_a[0]});
base_a = FilePath(temp_base_a);
ASSERT_TRUE(CreateDirectory(base_a));
base_a = MakeLongFilePath(base_a);
FilePath sub_a = base_a.Append(FPL("sub_a"));
ASSERT_TRUE(CreateDirectory(sub_a));
FilePath file_txt = sub_a.Append(FPL("file.txt"));
CreateTextFile(file_txt, bogus_content);
FilePath sub_long_rel(FPL("sub_long"));
FilePath deep_txt(FPL("deepfile.txt"));
int target_length = MAX_PATH - 1;
target_length -= (sub_a.value().length() + 1);
target_length -= (sub_long_rel.Append(deep_txt).value().length() + 1);
FilePath::StringType long_name_str = FPL("long_name_");
long_name_str.resize(target_length, '_');
FilePath long_name = sub_a.Append(FilePath(long_name_str));
FilePath deep_file = long_name.Append(sub_long_rel).Append(deep_txt);
ASSERT_EQ(static_cast<size_t>(MAX_PATH - 1), deep_file.value().length());
FilePath sub_long = deep_file.DirName();
ASSERT_TRUE(CreateDirectory(sub_long));
CreateTextFile(deep_file, bogus_content);
FilePath base_b = temp_dir_.GetPath().Append(FPL("base_b"));
ASSERT_TRUE(CreateDirectory(base_b));
base_b = MakeLongFilePath(base_b);
FilePath to_sub_a = base_b.Append(FPL("to_sub_a"));
ASSERT_TRUE(CreateDirectory(to_sub_a));
FilePath normalized_path;
{
auto reparse_to_sub_a = test::FilePathReparsePoint::Create(to_sub_a, sub_a);
ASSERT_TRUE(reparse_to_sub_a.has_value());
FilePath to_base_b = base_b.Append(FPL("to_base_b"));
ASSERT_TRUE(CreateDirectory(to_base_b));
auto reparse_to_base_b =
test::FilePathReparsePoint::Create(to_base_b, base_b);
ASSERT_TRUE(reparse_to_base_b.has_value());
FilePath to_sub_long = base_b.Append(FPL("to_sub_long"));
ASSERT_TRUE(CreateDirectory(to_sub_long));
auto reparse_to_sub_long =
test::FilePathReparsePoint::Create(to_sub_long, sub_long);
ASSERT_TRUE(reparse_to_sub_long.has_value());
ASSERT_TRUE(NormalizeFilePath(file_txt, &normalized_path));
ASSERT_EQ(file_txt.value(), normalized_path.value());
ASSERT_TRUE(
NormalizeFilePath(to_sub_a.Append(FPL("file.txt")), &normalized_path));
ASSERT_EQ(file_txt.value(), normalized_path.value());
ASSERT_TRUE(NormalizeFilePath(base_b.Append(FPL("to_base_b"))
.Append(FPL("to_base_b"))
.Append(FPL("to_sub_a"))
.Append(FPL("file.txt")),
&normalized_path));
ASSERT_EQ(file_txt.value(), normalized_path.value());
FilePath long_path = base_b;
const int kLengthLimit = MAX_PATH + 40;
while (long_path.value().length() <= kLengthLimit) {
long_path = long_path.Append(FPL("to_base_b"));
}
long_path = long_path.Append(FPL("to_sub_a")).Append(FPL("file.txt"));
ASSERT_FALSE(NormalizeFilePath(long_path, &normalized_path));
ASSERT_TRUE(
NormalizeFilePath(to_sub_long.Append(deep_txt), &normalized_path));
ASSERT_EQ(normalized_path, deep_file);
}
ASSERT_FALSE(
NormalizeFilePath(to_sub_a.Append(FPL("file.txt")), &normalized_path));
}
TEST_F(FileUtilTest, NormalizeFilePathWithLongPath) {
const FilePath::StringType kPathPrefix(FPL("\\\\?\\"));
constexpr int kLengthLimit = MAX_PATH + 40;
FilePath long_path = temp_dir_.GetPath();
while (long_path.value().length() <= kLengthLimit) {
long_path = long_path.Append(FPL("to_base_b"));
const auto path_with_no_check = kPathPrefix + long_path.value();
ASSERT_TRUE(::CreateDirectoryW(path_with_no_check.c_str(), nullptr));
}
auto path_with_no_check = kPathPrefix + long_path.value();
long_path = FilePath(path_with_no_check);
FilePath normalized_path;
ASSERT_FALSE(NormalizeFilePath(long_path, &normalized_path));
}
TEST_F(FileUtilTest, DevicePathToDriveLetter) {
std::wstring real_drive_letter = AsWString(
ToUpperASCII(AsStringPiece16(temp_dir_.GetPath().value().substr(0, 2))));
if (!IsAsciiAlpha(real_drive_letter[0]) || ':' != real_drive_letter[1]) {
LOG(ERROR) << "Can't get a drive letter to test with.";
return;
}
wchar_t device_path[MAX_PATH] = {'\0'};
ASSERT_TRUE(
::QueryDosDevice(real_drive_letter.c_str(), device_path, MAX_PATH));
FilePath actual_device_path(device_path);
FilePath win32_path;
ASSERT_TRUE(DevicePathToDriveLetterPath(actual_device_path, &win32_path));
ASSERT_EQ(real_drive_letter, win32_path.value());
FilePath kRelativePath(FPL("dir1\\dir2\\file.txt"));
ASSERT_TRUE(DevicePathToDriveLetterPath(
actual_device_path.Append(kRelativePath), &win32_path));
EXPECT_EQ(FilePath(real_drive_letter + FILE_PATH_LITERAL("\\"))
.Append(kRelativePath)
.value(),
win32_path.value());
size_t path_length = actual_device_path.value().length();
size_t new_length = path_length - 4;
ASSERT_GT(new_length, 0u);
FilePath prefix_of_real_device_path(
actual_device_path.value().substr(0, new_length));
ASSERT_FALSE(
DevicePathToDriveLetterPath(prefix_of_real_device_path, &win32_path));
ASSERT_FALSE(DevicePathToDriveLetterPath(
prefix_of_real_device_path.Append(kRelativePath), &win32_path));
const FilePath::StringType kExtraChars = FPL("12345");
FilePath real_device_path_plus_numbers(actual_device_path.value() +
kExtraChars);
ASSERT_FALSE(
DevicePathToDriveLetterPath(real_device_path_plus_numbers, &win32_path));
ASSERT_FALSE(DevicePathToDriveLetterPath(
real_device_path_plus_numbers.Append(kRelativePath), &win32_path));
}
TEST_F(FileUtilTest, AreShortFilePathsEnabled) {
constexpr FilePath::CharType kLongDirName[] = FPL("A long path");
FilePath long_test_dir = temp_dir_.GetPath().Append(kLongDirName);
ASSERT_TRUE(CreateDirectory(long_test_dir));
FilePath short_test_dir = MakeShortFilePath(long_test_dir);
ASSERT_EQ(AreShortFilePathsEnabled(), short_test_dir != long_test_dir);
}
TEST_F(FileUtilTest, CreateTemporaryFileInDirLongPathTest) {
if (!AreShortFilePathsEnabled()) {
GTEST_SKIP() << "Short filepaths are not supported on this system.";
}
constexpr FilePath::CharType kLongDirName[] = FPL("A long path");
constexpr FilePath::CharType kTestSubDirName[] = FPL("test");
FilePath long_test_dir = temp_dir_.GetPath().Append(kLongDirName);
ASSERT_TRUE(CreateDirectory(long_test_dir));
FilePath short_test_dir = MakeShortFilePath(long_test_dir);
ASSERT_FALSE(short_test_dir.empty());
ASSERT_NE(kLongDirName, short_test_dir.BaseName().value());
FilePath temp_file;
ASSERT_TRUE(CreateTemporaryFileInDir(short_test_dir, &temp_file));
EXPECT_EQ(kLongDirName, temp_file.DirName().BaseName().value());
EXPECT_TRUE(PathExists(temp_file));
FilePath access_test_dir = long_test_dir.Append(kTestSubDirName);
ASSERT_TRUE(CreateDirectory(access_test_dir));
FilePermissionRestorer long_test_dir_restorer(long_test_dir);
ASSERT_TRUE(MakeFileUnreadable(long_test_dir));
ASSERT_TRUE(CreateTemporaryFileInDir(short_test_dir.Append(kTestSubDirName),
&temp_file));
EXPECT_TRUE(PathExists(temp_file));
EXPECT_TRUE(short_test_dir.IsParent(temp_file.DirName()));
FilePath temp_file_long = MakeLongFilePath(temp_file);
ASSERT_TRUE(temp_file_long.empty());
}
TEST_F(FileUtilTest, MakeLongFilePathTest) {
if (!AreShortFilePathsEnabled()) {
GTEST_SKIP() << "Short filepaths are not supported on this system.";
}
FilePath temp_dir_long = MakeLongFilePath(temp_dir_.GetPath());
ASSERT_FALSE(temp_dir_long.empty());
FilePath long_test_dir = temp_dir_long.Append(FPL("A long directory name"));
ASSERT_TRUE(CreateDirectory(long_test_dir));
FilePath short_test_dir = MakeShortFilePath(long_test_dir);
ASSERT_FALSE(short_test_dir.empty());
EXPECT_NE(long_test_dir, short_test_dir);
EXPECT_EQ(long_test_dir, MakeLongFilePath(short_test_dir));
FilePath long_test_file = long_test_dir.Append(FPL("A long file name.1234"));
CreateTextFile(long_test_file, bogus_content);
ASSERT_TRUE(PathExists(long_test_file));
FilePath short_test_file = MakeShortFilePath(long_test_file);
ASSERT_FALSE(short_test_file.empty());
EXPECT_NE(long_test_file, short_test_file);
EXPECT_EQ(long_test_file, MakeLongFilePath(short_test_file));
EXPECT_TRUE(DeleteFile(short_test_file));
EXPECT_TRUE(MakeLongFilePath(short_test_file).empty());
EXPECT_TRUE(DeleteFile(short_test_dir));
EXPECT_TRUE(MakeLongFilePath(short_test_dir).empty());
}
TEST_F(FileUtilTest, CreateWinHardlinkTest) {
FilePath test_dir = temp_dir_.GetPath().Append(FPL("test"));
ASSERT_TRUE(CreateDirectory(test_dir));
FilePath temp_file;
ASSERT_TRUE(CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file));
FilePath link_to_file = test_dir.Append(FPL("linked_name"));
EXPECT_TRUE(CreateWinHardLink(link_to_file, temp_file));
EXPECT_TRUE(PathExists(link_to_file));
EXPECT_FALSE(CreateWinHardLink(temp_dir_.GetPath(), test_dir));
}
TEST_F(FileUtilTest, PreventExecuteMappingNewFile) {
base::test::ScopedFeatureList enforcement_feature;
enforcement_feature.InitAndEnableFeature(
features::kEnforceNoExecutableFileHandles);
FilePath file = temp_dir_.GetPath().Append(FPL("afile.txt"));
ASSERT_FALSE(PathExists(file));
{
File new_file(file, File::FLAG_WRITE | File::FLAG_WIN_NO_EXECUTE |
File::FLAG_CREATE_ALWAYS);
ASSERT_TRUE(new_file.IsValid());
}
{
File open_file(file, File::FLAG_READ | File::FLAG_WIN_EXECUTE |
File::FLAG_OPEN_ALWAYS);
EXPECT_FALSE(open_file.IsValid());
}
EXPECT_TRUE(DeleteFile(file));
}
TEST_F(FileUtilTest, PreventExecuteMappingExisting) {
base::test::ScopedFeatureList enforcement_feature;
enforcement_feature.InitAndEnableFeature(
features::kEnforceNoExecutableFileHandles);
FilePath file = temp_dir_.GetPath().Append(FPL("afile.txt"));
CreateTextFile(file, bogus_content);
ASSERT_TRUE(PathExists(file));
{
File open_file(file, File::FLAG_READ | File::FLAG_WIN_EXECUTE |
File::FLAG_OPEN_ALWAYS);
EXPECT_TRUE(open_file.IsValid());
}
EXPECT_TRUE(PreventExecuteMapping(file));
{
File open_file(file, File::FLAG_READ | File::FLAG_WIN_EXECUTE |
File::FLAG_OPEN_ALWAYS);
EXPECT_FALSE(open_file.IsValid());
}
EXPECT_TRUE(DeleteFile(file));
}
TEST_F(FileUtilTest, PreventExecuteMappingOpenFile) {
base::test::ScopedFeatureList enforcement_feature;
enforcement_feature.InitAndEnableFeature(
features::kEnforceNoExecutableFileHandles);
FilePath file = temp_dir_.GetPath().Append(FPL("afile.txt"));
CreateTextFile(file, bogus_content);
ASSERT_TRUE(PathExists(file));
File open_file(file, File::FLAG_READ | File::FLAG_WRITE |
File::FLAG_WIN_EXECUTE | File::FLAG_OPEN_ALWAYS);
EXPECT_TRUE(open_file.IsValid());
EXPECT_TRUE(PreventExecuteMapping(file));
{
File second_open_file(
file, File::FLAG_READ | File::FLAG_WRITE | File::FLAG_OPEN_ALWAYS);
EXPECT_TRUE(second_open_file.IsValid());
}
{
File third_open_file(file, File::FLAG_READ | File::FLAG_WIN_EXECUTE |
File::FLAG_OPEN_ALWAYS);
EXPECT_FALSE(third_open_file.IsValid());
}
open_file.Close();
EXPECT_TRUE(DeleteFile(file));
}
TEST(FileUtilDeathTest, DisallowNoExecuteOnUnsafeFile) {
base::test::ScopedFeatureList enforcement_feature;
enforcement_feature.InitAndEnableFeature(
features::kEnforceNoExecutableFileHandles);
base::FilePath local_app_data;
ASSERT_TRUE(
base::PathService::Get(base::DIR_LOCAL_APP_DATA, &local_app_data));
base::FilePath file_path;
EXPECT_DCHECK_DEATH_WITH(
{
{
base::File temp_file =
base::CreateAndOpenTemporaryFileInDir(local_app_data, &file_path);
}
File reopen_file(file_path, File::FLAG_READ | File::FLAG_WRITE |
File::FLAG_WIN_NO_EXECUTE |
File::FLAG_OPEN_ALWAYS |
File::FLAG_DELETE_ON_CLOSE);
},
"Unsafe to deny execute access to path");
}
MULTIPROCESS_TEST_MAIN(NoExecuteOnSafeFileMain) {
base::FilePath temp_file;
CHECK(base::CreateTemporaryFile(&temp_file));
File reopen_file(temp_file, File::FLAG_READ | File::FLAG_WRITE |
File::FLAG_WIN_NO_EXECUTE |
File::FLAG_OPEN_ALWAYS |
File::FLAG_DELETE_ON_CLOSE);
return 0;
}
TEST_F(FileUtilTest, NoExecuteOnSafeFile) {
FilePath new_dir;
ASSERT_TRUE(CreateTemporaryDirInDir(
temp_dir_.GetPath(), FILE_PATH_LITERAL("NoExecuteOnSafeFileLongPath"),
&new_dir));
FilePath short_dir = base::MakeShortFilePath(new_dir);
LaunchOptions options;
options.environment[L"TMP"] = short_dir.value();
CommandLine child_command_line(GetMultiProcessTestChildBaseCommandLine());
Process child_process = SpawnMultiProcessTestChild(
"NoExecuteOnSafeFileMain", child_command_line, options);
ASSERT_TRUE(child_process.IsValid());
int rv = -1;
ASSERT_TRUE(WaitForMultiprocessTestChildExit(
child_process, TestTimeouts::action_timeout(), &rv));
ASSERT_EQ(0, rv);
}
class FileUtilExecuteEnforcementTest
: public FileUtilTest,
public ::testing::WithParamInterface<bool> {
public:
FileUtilExecuteEnforcementTest() {
if (IsEnforcementEnabled()) {
enforcement_feature_.InitAndEnableFeature(
features::kEnforceNoExecutableFileHandles);
} else {
enforcement_feature_.InitAndDisableFeature(
features::kEnforceNoExecutableFileHandles);
}
}
protected:
bool IsEnforcementEnabled() { return GetParam(); }
private:
base::test::ScopedFeatureList enforcement_feature_;
};
TEST_P(FileUtilExecuteEnforcementTest, Functional) {
FilePath dir_exe;
EXPECT_TRUE(PathService::Get(DIR_EXE, &dir_exe));
FilePath test_dll(dir_exe.Append(FPL("scoped_handle_test_dll.dll")));
EXPECT_TRUE(base::PathExists(test_dll));
FilePath dll_copy_path = temp_dir_.GetPath().Append(FPL("test.dll"));
ASSERT_TRUE(CopyFile(test_dll, dll_copy_path));
ASSERT_TRUE(PreventExecuteMapping(dll_copy_path));
ScopedNativeLibrary module(dll_copy_path);
EXPECT_EQ(IsEnforcementEnabled(), !module.is_valid());
}
INSTANTIATE_TEST_SUITE_P(EnforcementEnabled,
FileUtilExecuteEnforcementTest,
::testing::Values(true));
INSTANTIATE_TEST_SUITE_P(EnforcementDisabled,
FileUtilExecuteEnforcementTest,
::testing::Values(false));
#endif
#if BUILDFLAG(IS_POSIX)
TEST_F(FileUtilTest, CreateAndReadSymlinks) { … }
TEST_F(FileUtilTest, CreateAndReadRelativeSymlinks) { … }
TEST_F(FileUtilTest, NormalizeFilePathSymlinks) { … }
TEST_F(FileUtilTest, DeleteSymlinkToExistentFile) { … }
TEST_F(FileUtilTest, DeleteSymlinkToNonExistentFile) { … }
TEST_F(FileUtilTest, CopyFileFollowsSymlinks) { … }
TEST_F(FileUtilTest, ChangeFilePermissionsAndRead) { … }
TEST_F(FileUtilTest, ChangeFilePermissionsAndWrite) { … }
TEST_F(FileUtilTest, ChangeDirectoryPermissionsAndEnumerate) { … }
TEST_F(FileUtilTest, ExecutableExistsInPath) { … }
TEST_F(FileUtilTest, CopyDirectoryPermissions) { … }
TEST_F(FileUtilTest, CopyDirectoryPermissionsOverExistingFile) { … }
TEST_F(FileUtilTest, CopyDirectoryExclDoesNotOverwrite) { … }
TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverExistingFile) { … }
TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverExistingDirectory) { … }
TEST_F(FileUtilTest, CopyFileExecutablePermission) { … }
#endif
#if !BUILDFLAG(IS_FUCHSIA)
TEST_F(FileUtilTest, CopyFileACL) { … }
TEST_F(FileUtilTest, CopyDirectoryACL) { … }
#endif
TEST_F(FileUtilTest, DeleteNonExistent) { … }
TEST_F(FileUtilTest, DeleteNonExistentWithNonExistentParent) { … }
TEST_F(FileUtilTest, DeleteFile) { … }
#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
TEST_F(FileUtilTest, DeleteDeep) { … }
#endif
#if BUILDFLAG(IS_ANDROID)
TEST_F(FileUtilTest, DeleteContentUri) {
FilePath data_dir;
ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &data_dir));
data_dir = data_dir.Append(FPL("file_util"));
ASSERT_TRUE(PathExists(data_dir));
FilePath image_file = data_dir.Append(FPL("red.png"));
ASSERT_TRUE(PathExists(image_file));
FilePath image_copy = data_dir.Append(FPL("redcopy.png"));
ASSERT_TRUE(CopyFile(image_file, image_copy));
FilePath uri_path = InsertImageIntoMediaStore(image_copy);
ASSERT_TRUE(uri_path.IsContentUri());
ASSERT_TRUE(PathExists(uri_path));
EXPECT_TRUE(DeleteFile(uri_path));
EXPECT_FALSE(PathExists(image_copy));
EXPECT_FALSE(PathExists(uri_path));
}
#endif
#if BUILDFLAG(IS_WIN)
TEST_F(FileUtilTest, DeleteWildCard) {
FilePath file_name =
temp_dir_.GetPath().Append(FPL("Test DeleteWildCard.txt"));
CreateTextFile(file_name, bogus_content);
ASSERT_TRUE(PathExists(file_name));
FilePath subdir_path = temp_dir_.GetPath().Append(FPL("DeleteWildCardDir"));
CreateDirectory(subdir_path);
ASSERT_TRUE(PathExists(subdir_path));
FilePath directory_contents = temp_dir_.GetPath();
directory_contents = directory_contents.Append(FPL("*"));
EXPECT_TRUE(DeleteFile(directory_contents));
EXPECT_FALSE(PathExists(file_name));
EXPECT_TRUE(PathExists(subdir_path));
EXPECT_TRUE(DeletePathRecursively(directory_contents));
EXPECT_FALSE(PathExists(file_name));
EXPECT_FALSE(PathExists(subdir_path));
}
TEST_F(FileUtilTest, DeleteNonExistantWildCard) {
FilePath subdir_path =
temp_dir_.GetPath().Append(FPL("DeleteNonExistantWildCard"));
CreateDirectory(subdir_path);
ASSERT_TRUE(PathExists(subdir_path));
FilePath directory_contents = subdir_path;
directory_contents = directory_contents.Append(FPL("*"));
EXPECT_TRUE(DeleteFile(directory_contents));
EXPECT_TRUE(PathExists(subdir_path));
EXPECT_TRUE(DeletePathRecursively(directory_contents));
EXPECT_TRUE(PathExists(subdir_path));
}
#endif
TEST_F(FileUtilTest, DeleteDirNonRecursive) { … }
TEST_F(FileUtilTest, DeleteDirRecursive) { … }
TEST_F(FileUtilTest, DeleteDirRecursiveWithOpenFile) { … }
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
TEST_F(FileUtilTest, TestNonBlockingFileReadLinux) { … }
#endif
TEST_F(FileUtilTest, MoveFileNew) { … }
TEST_F(FileUtilTest, MoveFileExists) { … }
TEST_F(FileUtilTest, MoveFileDirExists) { … }
TEST_F(FileUtilTest, MoveNew) { … }
TEST_F(FileUtilTest, MoveExist) { … }
TEST_F(FileUtilTest, CopyDirectoryRecursivelyNew) { … }
TEST_F(FileUtilTest, CopyDirectoryRecursivelyExists) { … }
TEST_F(FileUtilTest, CopyDirectoryNew) { … }
TEST_F(FileUtilTest, CopyDirectoryExists) { … }
TEST_F(FileUtilTest, CopyFileWithCopyDirectoryRecursiveToNew) { … }
TEST_F(FileUtilTest, CopyFileWithCopyDirectoryRecursiveToExisting) { … }
TEST_F(FileUtilTest, CopyFileWithCopyDirectoryRecursiveToExistingDirectory) { … }
TEST_F(FileUtilTest, CopyFileFailureWithCopyDirectoryExcl) { … }
TEST_F(FileUtilTest, CopyDirectoryWithTrailingSeparators) { … }
#if BUILDFLAG(IS_POSIX)
TEST_F(FileUtilTest, CopyDirectoryWithNonRegularFiles) { … }
TEST_F(FileUtilTest, CopyDirectoryExclFileOverSymlink) { … }
TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverSymlink) { … }
TEST_F(FileUtilTest, CopyDirectoryExclFileOverDanglingSymlink) { … }
TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverDanglingSymlink) { … }
TEST_F(FileUtilTest, CopyDirectoryExclFileOverFifo) { … }
#endif
TEST_F(FileUtilTest, CopyFile) { … }
ReadOnlyFileUtilTest;
TEST_F(ReadOnlyFileUtilTest, ContentsEqual) { … }
TEST_F(ReadOnlyFileUtilTest, TextContentsEqual) { … }
#if BUILDFLAG(IS_WIN)
TEST_F(FileUtilTest, CopyAndDeleteDirectoryTest) {
FilePath dir_name_from = temp_dir_.GetPath().Append(
FILE_PATH_LITERAL("CopyAndDelete_From_Subdir"));
CreateDirectory(dir_name_from);
ASSERT_TRUE(PathExists(dir_name_from));
FilePath file_name_from =
dir_name_from.Append(FILE_PATH_LITERAL("CopyAndDelete_Test_File.txt"));
CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
ASSERT_TRUE(PathExists(file_name_from));
FilePath dir_name_to =
temp_dir_.GetPath().Append(FILE_PATH_LITERAL("CopyAndDelete_To_Subdir"));
FilePath file_name_to =
dir_name_to.Append(FILE_PATH_LITERAL("CopyAndDelete_Test_File.txt"));
ASSERT_FALSE(PathExists(dir_name_to));
EXPECT_TRUE(internal::CopyAndDeleteDirectory(dir_name_from, dir_name_to));
EXPECT_FALSE(PathExists(dir_name_from));
EXPECT_FALSE(PathExists(file_name_from));
EXPECT_TRUE(PathExists(dir_name_to));
EXPECT_TRUE(PathExists(file_name_to));
}
TEST_F(FileUtilTest, GetTempDirTest) {
const TCHAR* kTmpKey = _T("TMP");
std::array<const TCHAR*, 5> kTmpValues = {_T(""), _T("C:"), _T("C:\\"),
_T("C:\\tmp"), _T("C:\\tmp\\")};
size_t original_tmp_size;
TCHAR* original_tmp;
ASSERT_EQ(0, ::_tdupenv_s(&original_tmp, &original_tmp_size, kTmpKey));
for (const TCHAR* val : kTmpValues) {
FilePath path;
::_tputenv_s(kTmpKey, val);
GetTempDir(&path);
EXPECT_TRUE(path.IsAbsolute())
<< "$TMP=" << val << " result=" << path.value();
}
if (original_tmp) {
::_tputenv_s(kTmpKey, original_tmp);
free(original_tmp);
} else {
::_tputenv_s(kTmpKey, _T(""));
}
}
#endif
TEST_F(FileUtilTest, OpenFileNoInheritance) { … }
TEST_F(FileUtilTest, CreateAndOpenTemporaryFileInDir) { … }
TEST_F(FileUtilTest, CreateTemporaryFileTest) { … }
TEST_F(FileUtilTest, CreateAndOpenTemporaryStreamTest) { … }
TEST_F(FileUtilTest, GetUniquePath) { … }
TEST_F(FileUtilTest, GetUniquePathTooManyFiles) { … }
TEST_F(FileUtilTest, GetUniquePathWithSuffixFormat) { … }
TEST_F(FileUtilTest, FileToFILE) { … }
TEST_F(FileUtilTest, FILEToFile) { … }
TEST_F(FileUtilTest, CreateNewTempDirectoryTest) { … }
#if BUILDFLAG(IS_WIN)
TEST_F(FileUtilTest, TempDirectoryParentTest) {
if (!::IsUserAnAdmin()) {
GTEST_SKIP() << "This test must be run by an admin user";
}
FilePath temp_dir;
ASSERT_TRUE(CreateNewTempDirectory(FilePath::StringType(), &temp_dir));
EXPECT_TRUE(PathExists(temp_dir));
FilePath expected_parent_dir;
if (!::IsUserAnAdmin() ||
!PathService::Get(DIR_SYSTEM_TEMP, &expected_parent_dir)) {
EXPECT_TRUE(PathService::Get(DIR_TEMP, &expected_parent_dir));
}
EXPECT_TRUE(expected_parent_dir.IsParent(temp_dir));
EXPECT_TRUE(DeleteFile(temp_dir));
}
#endif
TEST_F(FileUtilTest, CreateNewTemporaryDirInDirTest) { … }
#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
TEST_F(FileUtilTest, GetShmemTempDirTest) { … }
TEST_F(FileUtilTest, AllocateFileRegionTest_ZeroOffset) { … }
TEST_F(FileUtilTest, AllocateFileRegionTest_NonZeroOffset) { … }
TEST_F(FileUtilTest, AllocateFileRegionTest_DontTruncate) { … }
#endif
TEST_F(FileUtilTest, GetHomeDirTest) { … }
TEST_F(FileUtilTest, CreateDirectoryTest) { … }
TEST_F(FileUtilTest, DetectDirectoryTest) { … }
TEST_F(FileUtilTest, FileEnumeratorTest) { … }
TEST_F(FileUtilTest, AppendToFile) { … }
TEST_F(FileUtilTest, ReadFile) { … }
TEST_F(FileUtilTest, ReadFileToBytes) { … }
TEST_F(FileUtilTest, ReadFileToString) { … }
#if !BUILDFLAG(IS_WIN)
TEST_F(FileUtilTest, ReadFileToStringWithUnknownFileSize) { … }
#endif
#if !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_FUCHSIA) && \
!BUILDFLAG(IS_IOS)
#define ChildMain …
#define ChildMainString …
MULTIPROCESS_TEST_MAIN(ChildMain) { … }
#define MoreThanBufferSizeChildMain …
#define MoreThanBufferSizeChildMainString …
MULTIPROCESS_TEST_MAIN(MoreThanBufferSizeChildMain) { … }
TEST_F(FileUtilTest, ReadFileToStringWithNamedPipe) { … }
#endif
#if BUILDFLAG(IS_WIN)
#define ChildMain …
#define ChildMainString …
MULTIPROCESS_TEST_MAIN(ChildMain) {
const char kTestData[] = "0123";
CommandLine* command_line = CommandLine::ForCurrentProcess();
const FilePath pipe_path = command_line->GetSwitchValuePath("pipe-path");
std::string switch_string = command_line->GetSwitchValueASCII("sync_event");
EXPECT_FALSE(switch_string.empty());
unsigned int switch_uint = 0;
EXPECT_TRUE(StringToUint(switch_string, &switch_uint));
win::ScopedHandle sync_event(win::Uint32ToHandle(switch_uint));
HANDLE ph = CreateNamedPipe(pipe_path.value().c_str(), PIPE_ACCESS_OUTBOUND,
PIPE_WAIT, 1, 0, 0, 0, NULL);
EXPECT_NE(ph, INVALID_HANDLE_VALUE);
EXPECT_TRUE(SetEvent(sync_event.get()));
if (!::ConnectNamedPipe(ph, nullptr)) {
auto error = ::GetLastError();
EXPECT_EQ(error, DWORD{ERROR_PIPE_CONNECTED});
}
DWORD written;
EXPECT_TRUE(::WriteFile(ph, kTestData, strlen(kTestData), &written, NULL));
EXPECT_EQ(strlen(kTestData), written);
CloseHandle(ph);
return 0;
}
#define MoreThanBufferSizeChildMain …
#define MoreThanBufferSizeChildMainString …
MULTIPROCESS_TEST_MAIN(MoreThanBufferSizeChildMain) {
std::string data(kLargeFileSize, 'c');
CommandLine* command_line = CommandLine::ForCurrentProcess();
const FilePath pipe_path = command_line->GetSwitchValuePath("pipe-path");
std::string switch_string = command_line->GetSwitchValueASCII("sync_event");
EXPECT_FALSE(switch_string.empty());
unsigned int switch_uint = 0;
EXPECT_TRUE(StringToUint(switch_string, &switch_uint));
win::ScopedHandle sync_event(win::Uint32ToHandle(switch_uint));
HANDLE ph = CreateNamedPipe(pipe_path.value().c_str(), PIPE_ACCESS_OUTBOUND,
PIPE_WAIT, 1, data.size(), data.size(), 0, NULL);
EXPECT_NE(ph, INVALID_HANDLE_VALUE);
EXPECT_TRUE(SetEvent(sync_event.get()));
if (!::ConnectNamedPipe(ph, nullptr)) {
auto error = ::GetLastError();
EXPECT_EQ(error, DWORD{ERROR_PIPE_CONNECTED});
}
DWORD written;
EXPECT_TRUE(::WriteFile(ph, data.c_str(), data.size(), &written, NULL));
EXPECT_EQ(data.size(), written);
CloseHandle(ph);
return 0;
}
TEST_F(FileUtilTest, ReadFileToStringWithNamedPipe) {
FilePath pipe_path(FILE_PATH_LITERAL("\\\\.\\pipe\\test_pipe"));
win::ScopedHandle sync_event(CreateEvent(0, false, false, nullptr));
CommandLine child_command_line(GetMultiProcessTestChildBaseCommandLine());
child_command_line.AppendSwitchPath("pipe-path", pipe_path);
child_command_line.AppendSwitchASCII(
"sync_event", NumberToString(win::HandleToUint32(sync_event.get())));
LaunchOptions options;
options.handles_to_inherit.push_back(sync_event.get());
{
Process child_process = SpawnMultiProcessTestChild(
ChildMainString, child_command_line, options);
ASSERT_TRUE(child_process.IsValid());
EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.get(), INFINITE));
std::string data = "temp";
EXPECT_FALSE(ReadFileToStringWithMaxSize(pipe_path, &data, 2));
EXPECT_EQ("01", data);
int rv = -1;
ASSERT_TRUE(WaitForMultiprocessTestChildExit(
child_process, TestTimeouts::action_timeout(), &rv));
ASSERT_EQ(0, rv);
}
{
Process child_process = SpawnMultiProcessTestChild(
ChildMainString, child_command_line, options);
ASSERT_TRUE(child_process.IsValid());
EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.get(), INFINITE));
std::string data = "temp";
EXPECT_TRUE(ReadFileToStringWithMaxSize(pipe_path, &data, 6));
EXPECT_EQ("0123", data);
int rv = -1;
ASSERT_TRUE(WaitForMultiprocessTestChildExit(
child_process, TestTimeouts::action_timeout(), &rv));
ASSERT_EQ(0, rv);
}
{
Process child_process = SpawnMultiProcessTestChild(
MoreThanBufferSizeChildMainString, child_command_line, options);
ASSERT_TRUE(child_process.IsValid());
EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.get(), INFINITE));
std::string data = "temp";
EXPECT_FALSE(ReadFileToStringWithMaxSize(pipe_path, &data, 6));
EXPECT_EQ("cccccc", data);
int rv = -1;
ASSERT_TRUE(WaitForMultiprocessTestChildExit(
child_process, TestTimeouts::action_timeout(), &rv));
ASSERT_EQ(0, rv);
}
{
Process child_process = SpawnMultiProcessTestChild(
MoreThanBufferSizeChildMainString, child_command_line, options);
ASSERT_TRUE(child_process.IsValid());
EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.get(), INFINITE));
std::string data = "temp";
EXPECT_FALSE(
ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize - 1));
EXPECT_EQ(std::string(kLargeFileSize - 1, 'c'), data);
int rv = -1;
ASSERT_TRUE(WaitForMultiprocessTestChildExit(
child_process, TestTimeouts::action_timeout(), &rv));
ASSERT_EQ(0, rv);
}
{
Process child_process = SpawnMultiProcessTestChild(
MoreThanBufferSizeChildMainString, child_command_line, options);
ASSERT_TRUE(child_process.IsValid());
EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.get(), INFINITE));
std::string data = "temp";
EXPECT_TRUE(ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize));
EXPECT_EQ(std::string(kLargeFileSize, 'c'), data);
int rv = -1;
ASSERT_TRUE(WaitForMultiprocessTestChildExit(
child_process, TestTimeouts::action_timeout(), &rv));
ASSERT_EQ(0, rv);
}
{
Process child_process = SpawnMultiProcessTestChild(
MoreThanBufferSizeChildMainString, child_command_line, options);
ASSERT_TRUE(child_process.IsValid());
EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.get(), INFINITE));
std::string data = "temp";
EXPECT_TRUE(
ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize * 5));
EXPECT_EQ(std::string(kLargeFileSize, 'c'), data);
int rv = -1;
ASSERT_TRUE(WaitForMultiprocessTestChildExit(
child_process, TestTimeouts::action_timeout(), &rv));
ASSERT_EQ(0, rv);
}
}
#endif
#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE)
TEST_F(FileUtilTest, ReadFileToStringWithProcFileSystem) { … }
#endif
TEST_F(FileUtilTest, ReadFileToStringWithLargeFile) { … }
TEST_F(FileUtilTest, ReadStreamToString) { … }
#if BUILDFLAG(IS_POSIX)
TEST_F(FileUtilTest, ReadStreamToString_ZeroLengthFile) { … }
#endif
TEST_F(FileUtilTest, ReadStreamToStringWithMaxSize) { … }
TEST_F(FileUtilTest, ReadStreamToStringNullStream) { … }
TEST_F(FileUtilTest, TouchFile) { … }
TEST_F(FileUtilTest, WriteFileSpanVariant) { … }
TEST_F(FileUtilTest, WriteFileStringVariant) { … }
TEST_F(FileUtilTest, IsDirectoryEmpty) { … }
#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
TEST_F(FileUtilTest, SetNonBlocking) { … }
TEST_F(FileUtilTest, SetCloseOnExec) { … }
#endif
#if BUILDFLAG(IS_MAC)
class VerifyPathControlledByUserTest : public FileUtilTest {
protected:
void SetUp() override {
FileUtilTest::SetUp();
base_dir_ = temp_dir_.GetPath().AppendASCII("base_dir");
ASSERT_TRUE(CreateDirectory(base_dir_));
sub_dir_ = base_dir_.AppendASCII("sub_dir");
ASSERT_TRUE(CreateDirectory(sub_dir_));
text_file_ = sub_dir_.AppendASCII("file.txt");
CreateTextFile(text_file_, L"This text file has some text in it.");
stat_wrapper_t stat_buf;
ASSERT_EQ(0, File::Stat(base_dir_, &stat_buf));
uid_ = stat_buf.st_uid;
ok_gids_.insert(stat_buf.st_gid);
bad_gids_.insert(stat_buf.st_gid + 1);
ASSERT_EQ(uid_, getuid());
int enabled_permissions =
FILE_PERMISSION_USER_MASK | FILE_PERMISSION_GROUP_MASK;
int disabled_permissions = FILE_PERMISSION_OTHERS_MASK;
ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(
base_dir_, enabled_permissions, disabled_permissions));
ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(
sub_dir_, enabled_permissions, disabled_permissions));
}
FilePath base_dir_;
FilePath sub_dir_;
FilePath text_file_;
uid_t uid_;
std::set<gid_t> ok_gids_;
std::set<gid_t> bad_gids_;
};
TEST_F(VerifyPathControlledByUserTest, BadPaths) {
FilePath does_not_exist =
base_dir_.AppendASCII("does").AppendASCII("not").AppendASCII("exist");
EXPECT_FALSE(
VerifyPathControlledByUser(base_dir_, does_not_exist, uid_, ok_gids_));
EXPECT_FALSE(VerifyPathControlledByUser(sub_dir_, base_dir_, uid_, ok_gids_));
FilePath empty;
EXPECT_FALSE(VerifyPathControlledByUser(empty, base_dir_, uid_, ok_gids_));
EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
}
TEST_F(VerifyPathControlledByUserTest, Symlinks) {
FilePath file_link = base_dir_.AppendASCII("file_link");
ASSERT_TRUE(CreateSymbolicLink(text_file_, file_link))
<< "Failed to create symlink.";
EXPECT_FALSE(
VerifyPathControlledByUser(base_dir_, file_link, uid_, ok_gids_));
EXPECT_FALSE(
VerifyPathControlledByUser(file_link, file_link, uid_, ok_gids_));
FilePath link_to_sub_dir = base_dir_.AppendASCII("link_to_sub_dir");
ASSERT_TRUE(CreateSymbolicLink(sub_dir_, link_to_sub_dir))
<< "Failed to create symlink.";
FilePath file_path_with_link = link_to_sub_dir.AppendASCII("file.txt");
ASSERT_TRUE(PathExists(file_path_with_link));
EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, file_path_with_link, uid_,
ok_gids_));
EXPECT_FALSE(VerifyPathControlledByUser(link_to_sub_dir, file_path_with_link,
uid_, ok_gids_));
EXPECT_TRUE(VerifyPathControlledByUser(file_path_with_link,
file_path_with_link, uid_, ok_gids_));
}
TEST_F(VerifyPathControlledByUserTest, OwnershipChecks) {
uid_t bad_uid = uid_ + 1;
ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH));
ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH));
ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(text_file_, 0u, S_IWOTH));
EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
EXPECT_TRUE(
VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
EXPECT_FALSE(
VerifyPathControlledByUser(base_dir_, sub_dir_, bad_uid, ok_gids_));
EXPECT_FALSE(
VerifyPathControlledByUser(base_dir_, text_file_, bad_uid, ok_gids_));
EXPECT_FALSE(
VerifyPathControlledByUser(sub_dir_, text_file_, bad_uid, ok_gids_));
EXPECT_FALSE(
VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, bad_gids_));
EXPECT_FALSE(
VerifyPathControlledByUser(base_dir_, text_file_, uid_, bad_gids_));
EXPECT_FALSE(
VerifyPathControlledByUser(sub_dir_, text_file_, uid_, bad_gids_));
}
TEST_F(VerifyPathControlledByUserTest, GroupWriteTest) {
ASSERT_NO_FATAL_FAILURE(
ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH | S_IWGRP));
ASSERT_NO_FATAL_FAILURE(
ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH | S_IWGRP));
ASSERT_NO_FATAL_FAILURE(
ChangePosixFilePermissions(text_file_, 0u, S_IWOTH | S_IWGRP));
EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
EXPECT_TRUE(
VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, bad_gids_));
EXPECT_TRUE(
VerifyPathControlledByUser(base_dir_, text_file_, uid_, bad_gids_));
EXPECT_TRUE(
VerifyPathControlledByUser(sub_dir_, text_file_, uid_, bad_gids_));
std::set<gid_t> no_gids;
EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, no_gids));
EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, text_file_, uid_, no_gids));
EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, no_gids));
ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(base_dir_, S_IWGRP, 0u));
ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(sub_dir_, S_IWGRP, 0u));
ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(text_file_, S_IWGRP, 0u));
EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
EXPECT_TRUE(
VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
EXPECT_FALSE(
VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, bad_gids_));
EXPECT_FALSE(
VerifyPathControlledByUser(base_dir_, text_file_, uid_, bad_gids_));
EXPECT_FALSE(
VerifyPathControlledByUser(sub_dir_, text_file_, uid_, bad_gids_));
std::set<gid_t> multiple_gids;
std::set_union(ok_gids_.begin(), ok_gids_.end(), bad_gids_.begin(),
bad_gids_.end(),
std::inserter(multiple_gids, multiple_gids.begin()));
EXPECT_TRUE(
VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, multiple_gids));
EXPECT_TRUE(
VerifyPathControlledByUser(base_dir_, text_file_, uid_, multiple_gids));
EXPECT_TRUE(
VerifyPathControlledByUser(sub_dir_, text_file_, uid_, multiple_gids));
}
TEST_F(VerifyPathControlledByUserTest, WriteBitChecks) {
ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH));
ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH));
ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(text_file_, 0u, S_IWOTH));
EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
EXPECT_TRUE(
VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(base_dir_, S_IWOTH, 0u));
EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
EXPECT_FALSE(
VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(sub_dir_, S_IWOTH, 0u));
EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
EXPECT_FALSE(
VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
EXPECT_FALSE(
VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(text_file_, S_IWOTH, 0u));
EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
EXPECT_FALSE(
VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
EXPECT_FALSE(
VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH));
EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
EXPECT_FALSE(
VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
EXPECT_FALSE(
VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH));
EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
EXPECT_FALSE(
VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
EXPECT_FALSE(
VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(text_file_, 0u, S_IWOTH));
EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
EXPECT_TRUE(
VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
}
#endif
#if BUILDFLAG(IS_ANDROID)
TEST_F(FileUtilTest, DISABLED_ValidContentUriTest) {
FilePath data_dir;
ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &data_dir));
data_dir = data_dir.AppendASCII("file_util");
ASSERT_TRUE(PathExists(data_dir));
FilePath image_file = data_dir.Append(FILE_PATH_LITERAL("red.png"));
int64_t image_size;
GetFileSize(image_file, &image_size);
ASSERT_GT(image_size, 0);
FilePath path = InsertImageIntoMediaStore(image_file);
EXPECT_TRUE(path.IsContentUri());
EXPECT_TRUE(PathExists(path));
int64_t content_uri_size;
GetFileSize(path, &content_uri_size);
EXPECT_EQ(image_size, content_uri_size);
File file = OpenContentUri(path, File::FLAG_OPEN | File::FLAG_READ);
EXPECT_TRUE(file.IsValid());
auto buffer = std::make_unique<char[]>(image_size);
EXPECT_TRUE(UNSAFE_BUFFERS(file.ReadAtCurrentPos(buffer.get(), image_size)));
file = OpenContentUri(path, File::FLAG_CREATE_ALWAYS | File::FLAG_WRITE);
EXPECT_TRUE(file.IsValid());
}
TEST_F(FileUtilTest, NonExistentContentUriTest) {
FilePath path("content://foo.bar");
EXPECT_TRUE(path.IsContentUri());
EXPECT_FALSE(PathExists(path));
int64_t size;
EXPECT_FALSE(GetFileSize(path, &size));
File file = OpenContentUri(path, File::FLAG_OPEN | File::FLAG_READ);
EXPECT_FALSE(file.IsValid());
}
#endif
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING) && \
defined(ARCH_CPU_32_BITS)
#define FLAKY_327582285 …
#endif
#if defined(FLAKY_327582285)
#define MAYBE_PreReadFileExistingFileNoSize …
#else
#define MAYBE_PreReadFileExistingFileNoSize …
#endif
TEST_F(FileUtilTest, MAYBE_PreReadFileExistingFileNoSize) { … }
#if defined(FLAKY_327582285)
#define MAYBE_PreReadFileExistingFileExactSize …
#else
#define MAYBE_PreReadFileExistingFileExactSize …
#endif
TEST_F(FileUtilTest, MAYBE_PreReadFileExistingFileExactSize) { … }
#if defined(FLAKY_327582285)
#define MAYBE_PreReadFileExistingFileOverSized …
#else
#define MAYBE_PreReadFileExistingFileOverSized …
#endif
TEST_F(FileUtilTest, MAYBE_PreReadFileExistingFileOverSized) { … }
#if defined(FLAKY_327582285)
#define MAYBE_PreReadFileExistingFileUnderSized …
#else
#define MAYBE_PreReadFileExistingFileUnderSized …
#endif
TEST_F(FileUtilTest, MAYBE_PreReadFileExistingFileUnderSized) { … }
TEST_F(FileUtilTest, PreReadFileExistingFileZeroSize) { … }
TEST_F(FileUtilTest, PreReadFileExistingEmptyFileNoSize) { … }
TEST_F(FileUtilTest, PreReadFileExistingEmptyFileZeroSize) { … }
TEST_F(FileUtilTest, PreReadFileInexistentFile) { … }
#if defined(FLAKY_327582285)
#define MAYBE_PreReadFileExecutable …
#else
#define MAYBE_PreReadFileExecutable …
#endif
TEST_F(FileUtilTest, MAYBE_PreReadFileExecutable) { … }
#if defined(FLAKY_327582285)
#define MAYBE_PreReadFileWithSequentialAccess …
#else
#define MAYBE_PreReadFileWithSequentialAccess …
#endif
TEST_F(FileUtilTest, MAYBE_PreReadFileWithSequentialAccess) { … }
#undef FLAKY_327582285
TEST(FileUtilMultiThreadedTest, MultiThreadedTempFiles) { … }
#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
TEST(ScopedFD, ScopedFDDoesClose) { … }
#if defined(GTEST_HAS_DEATH_TEST)
void CloseWithScopedFD(int fd) { … }
#endif
TEST(ScopedFD, ScopedFDCrashesOnCloseFailure) { … }
#endif
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
TEST_F(FileUtilTest, CopyFileContentsWithSendfile) { … }
TEST_F(FileUtilTest, CopyFileContentsWithSendfileEmpty) { … }
TEST_F(FileUtilTest, CopyFileContentsWithSendfilePipe) { … }
TEST_F(FileUtilTest, CopyFileContentsWithSendfileSocket) { … }
TEST_F(FileUtilTest, CopyFileContentsWithSendfileSeqFile) { … }
#endif
}
}