1*1a96fba6SXin Li // Copyright 2014 The Chromium OS Authors. All rights reserved.
2*1a96fba6SXin Li // Use of this source code is governed by a BSD-style license that can be
3*1a96fba6SXin Li // found in the LICENSE file.
4*1a96fba6SXin Li
5*1a96fba6SXin Li #include "brillo/file_utils.h"
6*1a96fba6SXin Li
7*1a96fba6SXin Li #include <fcntl.h>
8*1a96fba6SXin Li #include <sys/stat.h>
9*1a96fba6SXin Li #include <unistd.h>
10*1a96fba6SXin Li
11*1a96fba6SXin Li #include <string>
12*1a96fba6SXin Li
13*1a96fba6SXin Li #include <base/files/file_util.h>
14*1a96fba6SXin Li #include <base/files/scoped_temp_dir.h>
15*1a96fba6SXin Li #include <base/rand_util.h>
16*1a96fba6SXin Li #include <base/stl_util.h>
17*1a96fba6SXin Li #include <base/strings/string_number_conversions.h>
18*1a96fba6SXin Li #include <gtest/gtest.h>
19*1a96fba6SXin Li
20*1a96fba6SXin Li namespace brillo {
21*1a96fba6SXin Li
22*1a96fba6SXin Li namespace {
23*1a96fba6SXin Li
24*1a96fba6SXin Li constexpr int kPermissions600 =
25*1a96fba6SXin Li base::FILE_PERMISSION_READ_BY_USER | base::FILE_PERMISSION_WRITE_BY_USER;
26*1a96fba6SXin Li constexpr int kPermissions700 = base::FILE_PERMISSION_USER_MASK;
27*1a96fba6SXin Li constexpr int kPermissions777 = base::FILE_PERMISSION_MASK;
28*1a96fba6SXin Li constexpr int kPermissions755 = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
29*1a96fba6SXin Li
GetRandomSuffix()30*1a96fba6SXin Li std::string GetRandomSuffix() {
31*1a96fba6SXin Li const int kBufferSize = 6;
32*1a96fba6SXin Li unsigned char buffer[kBufferSize];
33*1a96fba6SXin Li base::RandBytes(buffer, base::size(buffer));
34*1a96fba6SXin Li return base::HexEncode(buffer, base::size(buffer));
35*1a96fba6SXin Li }
36*1a96fba6SXin Li
IsNonBlockingFD(int fd)37*1a96fba6SXin Li bool IsNonBlockingFD(int fd) {
38*1a96fba6SXin Li return fcntl(fd, F_GETFL) & O_NONBLOCK;
39*1a96fba6SXin Li }
40*1a96fba6SXin Li
41*1a96fba6SXin Li } // namespace
42*1a96fba6SXin Li
43*1a96fba6SXin Li class FileUtilsTest : public testing::Test {
44*1a96fba6SXin Li public:
FileUtilsTest()45*1a96fba6SXin Li FileUtilsTest() {
46*1a96fba6SXin Li CHECK(temp_dir_.CreateUniqueTempDir());
47*1a96fba6SXin Li file_path_ = temp_dir_.GetPath().Append("test.temp");
48*1a96fba6SXin Li }
49*1a96fba6SXin Li
50*1a96fba6SXin Li protected:
51*1a96fba6SXin Li base::FilePath file_path_;
52*1a96fba6SXin Li base::ScopedTempDir temp_dir_;
53*1a96fba6SXin Li
54*1a96fba6SXin Li // Writes |contents| to |file_path_|. Pulled into a separate function just
55*1a96fba6SXin Li // to improve readability of tests.
WriteFile(const std::string & contents)56*1a96fba6SXin Li void WriteFile(const std::string& contents) {
57*1a96fba6SXin Li EXPECT_EQ(contents.length(),
58*1a96fba6SXin Li base::WriteFile(file_path_, contents.c_str(), contents.length()));
59*1a96fba6SXin Li }
60*1a96fba6SXin Li
61*1a96fba6SXin Li // Verifies that the file at |file_path_| exists and contains |contents|.
ExpectFileContains(const std::string & contents)62*1a96fba6SXin Li void ExpectFileContains(const std::string& contents) {
63*1a96fba6SXin Li EXPECT_TRUE(base::PathExists(file_path_));
64*1a96fba6SXin Li std::string new_contents;
65*1a96fba6SXin Li EXPECT_TRUE(base::ReadFileToString(file_path_, &new_contents));
66*1a96fba6SXin Li EXPECT_EQ(contents, new_contents);
67*1a96fba6SXin Li }
68*1a96fba6SXin Li
69*1a96fba6SXin Li // Verifies that the file at |file_path_| has |permissions|.
ExpectFilePermissions(int permissions)70*1a96fba6SXin Li void ExpectFilePermissions(int permissions) {
71*1a96fba6SXin Li int actual_permissions;
72*1a96fba6SXin Li EXPECT_TRUE(base::GetPosixFilePermissions(file_path_, &actual_permissions));
73*1a96fba6SXin Li EXPECT_EQ(permissions, actual_permissions);
74*1a96fba6SXin Li }
75*1a96fba6SXin Li
76*1a96fba6SXin Li // Creates a file with a random name in the temporary directory.
GetTempName()77*1a96fba6SXin Li base::FilePath GetTempName() {
78*1a96fba6SXin Li return temp_dir_.GetPath().Append(GetRandomSuffix());
79*1a96fba6SXin Li }
80*1a96fba6SXin Li };
81*1a96fba6SXin Li
TEST_F(FileUtilsTest,TouchFileCreate)82*1a96fba6SXin Li TEST_F(FileUtilsTest, TouchFileCreate) {
83*1a96fba6SXin Li EXPECT_TRUE(TouchFile(file_path_));
84*1a96fba6SXin Li ExpectFileContains("");
85*1a96fba6SXin Li ExpectFilePermissions(kPermissions600);
86*1a96fba6SXin Li }
87*1a96fba6SXin Li
TEST_F(FileUtilsTest,TouchFileCreateThroughUmask)88*1a96fba6SXin Li TEST_F(FileUtilsTest, TouchFileCreateThroughUmask) {
89*1a96fba6SXin Li mode_t old_umask = umask(kPermissions777);
90*1a96fba6SXin Li EXPECT_TRUE(TouchFile(file_path_));
91*1a96fba6SXin Li umask(old_umask);
92*1a96fba6SXin Li ExpectFileContains("");
93*1a96fba6SXin Li ExpectFilePermissions(kPermissions600);
94*1a96fba6SXin Li }
95*1a96fba6SXin Li
TEST_F(FileUtilsTest,TouchFileCreateDirectoryStructure)96*1a96fba6SXin Li TEST_F(FileUtilsTest, TouchFileCreateDirectoryStructure) {
97*1a96fba6SXin Li file_path_ = temp_dir_.GetPath().Append("foo/bar/baz/test.temp");
98*1a96fba6SXin Li EXPECT_TRUE(TouchFile(file_path_));
99*1a96fba6SXin Li ExpectFileContains("");
100*1a96fba6SXin Li }
101*1a96fba6SXin Li
TEST_F(FileUtilsTest,TouchFileExisting)102*1a96fba6SXin Li TEST_F(FileUtilsTest, TouchFileExisting) {
103*1a96fba6SXin Li WriteFile("abcd");
104*1a96fba6SXin Li EXPECT_TRUE(TouchFile(file_path_));
105*1a96fba6SXin Li ExpectFileContains("abcd");
106*1a96fba6SXin Li }
107*1a96fba6SXin Li
TEST_F(FileUtilsTest,TouchFileReplaceDirectory)108*1a96fba6SXin Li TEST_F(FileUtilsTest, TouchFileReplaceDirectory) {
109*1a96fba6SXin Li EXPECT_TRUE(base::CreateDirectory(file_path_));
110*1a96fba6SXin Li EXPECT_TRUE(TouchFile(file_path_));
111*1a96fba6SXin Li EXPECT_FALSE(base::DirectoryExists(file_path_));
112*1a96fba6SXin Li ExpectFileContains("");
113*1a96fba6SXin Li }
114*1a96fba6SXin Li
TEST_F(FileUtilsTest,TouchFileReplaceSymlink)115*1a96fba6SXin Li TEST_F(FileUtilsTest, TouchFileReplaceSymlink) {
116*1a96fba6SXin Li base::FilePath symlink_target = temp_dir_.GetPath().Append("target.temp");
117*1a96fba6SXin Li EXPECT_TRUE(base::CreateSymbolicLink(symlink_target, file_path_));
118*1a96fba6SXin Li EXPECT_TRUE(TouchFile(file_path_));
119*1a96fba6SXin Li EXPECT_FALSE(base::IsLink(file_path_));
120*1a96fba6SXin Li ExpectFileContains("");
121*1a96fba6SXin Li }
122*1a96fba6SXin Li
TEST_F(FileUtilsTest,TouchFileReplaceOtherUser)123*1a96fba6SXin Li TEST_F(FileUtilsTest, TouchFileReplaceOtherUser) {
124*1a96fba6SXin Li WriteFile("abcd");
125*1a96fba6SXin Li EXPECT_TRUE(TouchFile(file_path_, kPermissions777, geteuid() + 1, getegid()));
126*1a96fba6SXin Li ExpectFileContains("");
127*1a96fba6SXin Li }
128*1a96fba6SXin Li
TEST_F(FileUtilsTest,TouchFileReplaceOtherGroup)129*1a96fba6SXin Li TEST_F(FileUtilsTest, TouchFileReplaceOtherGroup) {
130*1a96fba6SXin Li WriteFile("abcd");
131*1a96fba6SXin Li EXPECT_TRUE(TouchFile(file_path_, kPermissions777, geteuid(), getegid() + 1));
132*1a96fba6SXin Li ExpectFileContains("");
133*1a96fba6SXin Li }
134*1a96fba6SXin Li
TEST_F(FileUtilsTest,TouchFileCreateWithAllPermissions)135*1a96fba6SXin Li TEST_F(FileUtilsTest, TouchFileCreateWithAllPermissions) {
136*1a96fba6SXin Li EXPECT_TRUE(TouchFile(file_path_, kPermissions777, geteuid(), getegid()));
137*1a96fba6SXin Li ExpectFileContains("");
138*1a96fba6SXin Li ExpectFilePermissions(kPermissions777);
139*1a96fba6SXin Li }
140*1a96fba6SXin Li
TEST_F(FileUtilsTest,TouchFileCreateWithOwnerPermissions)141*1a96fba6SXin Li TEST_F(FileUtilsTest, TouchFileCreateWithOwnerPermissions) {
142*1a96fba6SXin Li EXPECT_TRUE(TouchFile(file_path_, kPermissions700, geteuid(), getegid()));
143*1a96fba6SXin Li ExpectFileContains("");
144*1a96fba6SXin Li ExpectFilePermissions(kPermissions700);
145*1a96fba6SXin Li }
146*1a96fba6SXin Li
TEST_F(FileUtilsTest,TouchFileExistingPermissionsUnchanged)147*1a96fba6SXin Li TEST_F(FileUtilsTest, TouchFileExistingPermissionsUnchanged) {
148*1a96fba6SXin Li EXPECT_TRUE(TouchFile(file_path_, kPermissions777, geteuid(), getegid()));
149*1a96fba6SXin Li EXPECT_TRUE(TouchFile(file_path_, kPermissions700, geteuid(), getegid()));
150*1a96fba6SXin Li ExpectFileContains("");
151*1a96fba6SXin Li ExpectFilePermissions(kPermissions777);
152*1a96fba6SXin Li }
153*1a96fba6SXin Li
154*1a96fba6SXin Li // Other parts of OpenSafely are tested in Arcsetup.TestInstallDirectory*.
TEST_F(FileUtilsTest,TestOpenSafelyWithoutNonblocking)155*1a96fba6SXin Li TEST_F(FileUtilsTest, TestOpenSafelyWithoutNonblocking) {
156*1a96fba6SXin Li ASSERT_TRUE(TouchFile(file_path_, kPermissions700, geteuid(), getegid()));
157*1a96fba6SXin Li base::ScopedFD fd(OpenSafely(file_path_, O_RDONLY, 0));
158*1a96fba6SXin Li EXPECT_TRUE(fd.is_valid());
159*1a96fba6SXin Li EXPECT_FALSE(IsNonBlockingFD(fd.get()));
160*1a96fba6SXin Li }
161*1a96fba6SXin Li
TEST_F(FileUtilsTest,TestOpenSafelyWithNonblocking)162*1a96fba6SXin Li TEST_F(FileUtilsTest, TestOpenSafelyWithNonblocking) {
163*1a96fba6SXin Li ASSERT_TRUE(TouchFile(file_path_, kPermissions700, geteuid(), getegid()));
164*1a96fba6SXin Li base::ScopedFD fd = OpenSafely(file_path_, O_RDONLY | O_NONBLOCK, 0);
165*1a96fba6SXin Li EXPECT_TRUE(fd.is_valid());
166*1a96fba6SXin Li EXPECT_TRUE(IsNonBlockingFD(fd.get()));
167*1a96fba6SXin Li }
168*1a96fba6SXin Li
TEST_F(FileUtilsTest,TestOpenFifoSafelySuccess)169*1a96fba6SXin Li TEST_F(FileUtilsTest, TestOpenFifoSafelySuccess) {
170*1a96fba6SXin Li ASSERT_EQ(0, mkfifo(file_path_.value().c_str(), kPermissions700));
171*1a96fba6SXin Li base::ScopedFD fd(OpenFifoSafely(file_path_, O_RDONLY, 0));
172*1a96fba6SXin Li EXPECT_TRUE(fd.is_valid());
173*1a96fba6SXin Li EXPECT_FALSE(IsNonBlockingFD(fd.get()));
174*1a96fba6SXin Li }
175*1a96fba6SXin Li
TEST_F(FileUtilsTest,TestOpenFifoSafelyRegularFile)176*1a96fba6SXin Li TEST_F(FileUtilsTest, TestOpenFifoSafelyRegularFile) {
177*1a96fba6SXin Li ASSERT_TRUE(TouchFile(file_path_, kPermissions700, geteuid(), getegid()));
178*1a96fba6SXin Li base::ScopedFD fd = OpenFifoSafely(file_path_, O_RDONLY, 0);
179*1a96fba6SXin Li EXPECT_FALSE(fd.is_valid());
180*1a96fba6SXin Li }
181*1a96fba6SXin Li
TEST_F(FileUtilsTest,TestMkdirRecursivelyRoot)182*1a96fba6SXin Li TEST_F(FileUtilsTest, TestMkdirRecursivelyRoot) {
183*1a96fba6SXin Li // Try to create an existing directory ("/") should still succeed.
184*1a96fba6SXin Li EXPECT_TRUE(
185*1a96fba6SXin Li MkdirRecursively(base::FilePath("/"), kPermissions755).is_valid());
186*1a96fba6SXin Li }
187*1a96fba6SXin Li
TEST_F(FileUtilsTest,TestMkdirRecursivelySuccess)188*1a96fba6SXin Li TEST_F(FileUtilsTest, TestMkdirRecursivelySuccess) {
189*1a96fba6SXin Li // Set |temp_directory| to 0707.
190*1a96fba6SXin Li EXPECT_TRUE(base::SetPosixFilePermissions(temp_dir_.GetPath(), 0707));
191*1a96fba6SXin Li
192*1a96fba6SXin Li EXPECT_TRUE(
193*1a96fba6SXin Li MkdirRecursively(temp_dir_.GetPath().Append("a/b/c"), kPermissions755)
194*1a96fba6SXin Li .is_valid());
195*1a96fba6SXin Li // Confirm the 3 directories are there.
196*1a96fba6SXin Li EXPECT_TRUE(base::DirectoryExists(temp_dir_.GetPath().Append("a")));
197*1a96fba6SXin Li EXPECT_TRUE(base::DirectoryExists(temp_dir_.GetPath().Append("a/b")));
198*1a96fba6SXin Li EXPECT_TRUE(base::DirectoryExists(temp_dir_.GetPath().Append("a/b/c")));
199*1a96fba6SXin Li
200*1a96fba6SXin Li // Confirm that the newly created directories have 0755 mode.
201*1a96fba6SXin Li int mode = 0;
202*1a96fba6SXin Li EXPECT_TRUE(
203*1a96fba6SXin Li base::GetPosixFilePermissions(temp_dir_.GetPath().Append("a"), &mode));
204*1a96fba6SXin Li EXPECT_EQ(kPermissions755, mode);
205*1a96fba6SXin Li mode = 0;
206*1a96fba6SXin Li EXPECT_TRUE(
207*1a96fba6SXin Li base::GetPosixFilePermissions(temp_dir_.GetPath().Append("a/b"), &mode));
208*1a96fba6SXin Li EXPECT_EQ(kPermissions755, mode);
209*1a96fba6SXin Li mode = 0;
210*1a96fba6SXin Li EXPECT_TRUE(base::GetPosixFilePermissions(temp_dir_.GetPath().Append("a/b/c"),
211*1a96fba6SXin Li &mode));
212*1a96fba6SXin Li EXPECT_EQ(kPermissions755, mode);
213*1a96fba6SXin Li
214*1a96fba6SXin Li // Confirm that the existing directory |temp_directory| still has 0707 mode.
215*1a96fba6SXin Li mode = 0;
216*1a96fba6SXin Li EXPECT_TRUE(base::GetPosixFilePermissions(temp_dir_.GetPath(), &mode));
217*1a96fba6SXin Li EXPECT_EQ(0707, mode);
218*1a96fba6SXin Li
219*1a96fba6SXin Li // Call the API again which should still succeed.
220*1a96fba6SXin Li EXPECT_TRUE(
221*1a96fba6SXin Li MkdirRecursively(temp_dir_.GetPath().Append("a/b/c"), kPermissions755)
222*1a96fba6SXin Li .is_valid());
223*1a96fba6SXin Li EXPECT_TRUE(
224*1a96fba6SXin Li MkdirRecursively(temp_dir_.GetPath().Append("a/b/c/d"), kPermissions755)
225*1a96fba6SXin Li .is_valid());
226*1a96fba6SXin Li EXPECT_TRUE(base::DirectoryExists(temp_dir_.GetPath().Append("a/b/c/d")));
227*1a96fba6SXin Li mode = 0;
228*1a96fba6SXin Li EXPECT_TRUE(base::GetPosixFilePermissions(
229*1a96fba6SXin Li temp_dir_.GetPath().Append("a/b/c/d"), &mode));
230*1a96fba6SXin Li EXPECT_EQ(kPermissions755, mode);
231*1a96fba6SXin Li
232*1a96fba6SXin Li // Call the API again which should still succeed.
233*1a96fba6SXin Li EXPECT_TRUE(
234*1a96fba6SXin Li MkdirRecursively(temp_dir_.GetPath().Append("a/b"), kPermissions755)
235*1a96fba6SXin Li .is_valid());
236*1a96fba6SXin Li EXPECT_TRUE(MkdirRecursively(temp_dir_.GetPath().Append("a"), kPermissions755)
237*1a96fba6SXin Li .is_valid());
238*1a96fba6SXin Li }
239*1a96fba6SXin Li
TEST_F(FileUtilsTest,TestMkdirRecursivelyRelativePath)240*1a96fba6SXin Li TEST_F(FileUtilsTest, TestMkdirRecursivelyRelativePath) {
241*1a96fba6SXin Li // Try to pass a relative or empty directory. They should all fail.
242*1a96fba6SXin Li EXPECT_FALSE(
243*1a96fba6SXin Li MkdirRecursively(base::FilePath("foo"), kPermissions755).is_valid());
244*1a96fba6SXin Li EXPECT_FALSE(
245*1a96fba6SXin Li MkdirRecursively(base::FilePath("bar/"), kPermissions755).is_valid());
246*1a96fba6SXin Li EXPECT_FALSE(MkdirRecursively(base::FilePath(), kPermissions755).is_valid());
247*1a96fba6SXin Li }
248*1a96fba6SXin Li
TEST_F(FileUtilsTest,WriteFileCanBeReadBack)249*1a96fba6SXin Li TEST_F(FileUtilsTest, WriteFileCanBeReadBack) {
250*1a96fba6SXin Li const base::FilePath filename(GetTempName());
251*1a96fba6SXin Li const std::string content("blablabla");
252*1a96fba6SXin Li EXPECT_TRUE(WriteStringToFile(filename, content));
253*1a96fba6SXin Li std::string output;
254*1a96fba6SXin Li EXPECT_TRUE(ReadFileToString(filename, &output));
255*1a96fba6SXin Li EXPECT_EQ(content, output);
256*1a96fba6SXin Li }
257*1a96fba6SXin Li
TEST_F(FileUtilsTest,WriteFileSets0666)258*1a96fba6SXin Li TEST_F(FileUtilsTest, WriteFileSets0666) {
259*1a96fba6SXin Li const mode_t mask = 0000;
260*1a96fba6SXin Li const mode_t mode = 0666;
261*1a96fba6SXin Li const base::FilePath filename(GetTempName());
262*1a96fba6SXin Li const std::string content("blablabla");
263*1a96fba6SXin Li const mode_t old_mask = umask(mask);
264*1a96fba6SXin Li EXPECT_TRUE(WriteStringToFile(filename, content));
265*1a96fba6SXin Li int file_mode = 0;
266*1a96fba6SXin Li EXPECT_TRUE(base::GetPosixFilePermissions(filename, &file_mode));
267*1a96fba6SXin Li EXPECT_EQ(mode & ~mask, file_mode & 0777);
268*1a96fba6SXin Li umask(old_mask);
269*1a96fba6SXin Li }
270*1a96fba6SXin Li
TEST_F(FileUtilsTest,WriteFileCreatesMissingParentDirectoriesWith0700)271*1a96fba6SXin Li TEST_F(FileUtilsTest, WriteFileCreatesMissingParentDirectoriesWith0700) {
272*1a96fba6SXin Li const mode_t mask = 0000;
273*1a96fba6SXin Li const mode_t mode = 0700;
274*1a96fba6SXin Li const base::FilePath dirname(GetTempName());
275*1a96fba6SXin Li const base::FilePath subdirname(dirname.Append(GetRandomSuffix()));
276*1a96fba6SXin Li const base::FilePath filename(subdirname.Append(GetRandomSuffix()));
277*1a96fba6SXin Li const std::string content("blablabla");
278*1a96fba6SXin Li EXPECT_TRUE(WriteStringToFile(filename, content));
279*1a96fba6SXin Li int dir_mode = 0;
280*1a96fba6SXin Li int subdir_mode = 0;
281*1a96fba6SXin Li EXPECT_TRUE(base::GetPosixFilePermissions(dirname, &dir_mode));
282*1a96fba6SXin Li EXPECT_TRUE(base::GetPosixFilePermissions(subdirname, &subdir_mode));
283*1a96fba6SXin Li EXPECT_EQ(mode & ~mask, dir_mode & 0777);
284*1a96fba6SXin Li EXPECT_EQ(mode & ~mask, subdir_mode & 0777);
285*1a96fba6SXin Li const mode_t old_mask = umask(mask);
286*1a96fba6SXin Li umask(old_mask);
287*1a96fba6SXin Li }
288*1a96fba6SXin Li
TEST_F(FileUtilsTest,WriteToFileAtomicCanBeReadBack)289*1a96fba6SXin Li TEST_F(FileUtilsTest, WriteToFileAtomicCanBeReadBack) {
290*1a96fba6SXin Li const base::FilePath filename(GetTempName());
291*1a96fba6SXin Li const std::string content("blablabla");
292*1a96fba6SXin Li EXPECT_TRUE(
293*1a96fba6SXin Li WriteToFileAtomic(filename, content.data(), content.size(), 0644));
294*1a96fba6SXin Li std::string output;
295*1a96fba6SXin Li EXPECT_TRUE(ReadFileToString(filename, &output));
296*1a96fba6SXin Li EXPECT_EQ(content, output);
297*1a96fba6SXin Li }
298*1a96fba6SXin Li
TEST_F(FileUtilsTest,WriteToFileAtomicHonorsMode)299*1a96fba6SXin Li TEST_F(FileUtilsTest, WriteToFileAtomicHonorsMode) {
300*1a96fba6SXin Li const mode_t mask = 0000;
301*1a96fba6SXin Li const mode_t mode = 0616;
302*1a96fba6SXin Li const base::FilePath filename(GetTempName());
303*1a96fba6SXin Li const std::string content("blablabla");
304*1a96fba6SXin Li const mode_t old_mask = umask(mask);
305*1a96fba6SXin Li EXPECT_TRUE(
306*1a96fba6SXin Li WriteToFileAtomic(filename, content.data(), content.size(), mode));
307*1a96fba6SXin Li int file_mode = 0;
308*1a96fba6SXin Li EXPECT_TRUE(base::GetPosixFilePermissions(filename, &file_mode));
309*1a96fba6SXin Li EXPECT_EQ(mode & ~mask, file_mode & 0777);
310*1a96fba6SXin Li umask(old_mask);
311*1a96fba6SXin Li }
312*1a96fba6SXin Li
TEST_F(FileUtilsTest,WriteToFileAtomicHonorsUmask)313*1a96fba6SXin Li TEST_F(FileUtilsTest, WriteToFileAtomicHonorsUmask) {
314*1a96fba6SXin Li const mode_t mask = 0073;
315*1a96fba6SXin Li const mode_t mode = 0777;
316*1a96fba6SXin Li const base::FilePath filename(GetTempName());
317*1a96fba6SXin Li const std::string content("blablabla");
318*1a96fba6SXin Li const mode_t old_mask = umask(mask);
319*1a96fba6SXin Li EXPECT_TRUE(
320*1a96fba6SXin Li WriteToFileAtomic(filename, content.data(), content.size(), mode));
321*1a96fba6SXin Li int file_mode = 0;
322*1a96fba6SXin Li EXPECT_TRUE(base::GetPosixFilePermissions(filename, &file_mode));
323*1a96fba6SXin Li EXPECT_EQ(mode & ~mask, file_mode & 0777);
324*1a96fba6SXin Li umask(old_mask);
325*1a96fba6SXin Li }
326*1a96fba6SXin Li
TEST_F(FileUtilsTest,WriteToFileAtomicCreatesMissingParentDirectoriesWith0700)327*1a96fba6SXin Li TEST_F(FileUtilsTest,
328*1a96fba6SXin Li WriteToFileAtomicCreatesMissingParentDirectoriesWith0700) {
329*1a96fba6SXin Li const mode_t mask = 0000;
330*1a96fba6SXin Li const mode_t mode = 0700;
331*1a96fba6SXin Li const base::FilePath dirname(GetTempName());
332*1a96fba6SXin Li const base::FilePath subdirname(dirname.Append(GetRandomSuffix()));
333*1a96fba6SXin Li const base::FilePath filename(subdirname.Append(GetRandomSuffix()));
334*1a96fba6SXin Li const std::string content("blablabla");
335*1a96fba6SXin Li EXPECT_TRUE(
336*1a96fba6SXin Li WriteToFileAtomic(filename, content.data(), content.size(), 0777));
337*1a96fba6SXin Li int dir_mode = 0;
338*1a96fba6SXin Li int subdir_mode = 0;
339*1a96fba6SXin Li EXPECT_TRUE(base::GetPosixFilePermissions(dirname, &dir_mode));
340*1a96fba6SXin Li EXPECT_TRUE(base::GetPosixFilePermissions(subdirname, &subdir_mode));
341*1a96fba6SXin Li EXPECT_EQ(mode & ~mask, dir_mode & 0777);
342*1a96fba6SXin Li EXPECT_EQ(mode & ~mask, subdir_mode & 0777);
343*1a96fba6SXin Li const mode_t old_mask = umask(mask);
344*1a96fba6SXin Li umask(old_mask);
345*1a96fba6SXin Li }
346*1a96fba6SXin Li
TEST_F(FileUtilsTest,ComputeDirectoryDiskUsageNormalRandomFile)347*1a96fba6SXin Li TEST_F(FileUtilsTest, ComputeDirectoryDiskUsageNormalRandomFile) {
348*1a96fba6SXin Li // 2MB test file.
349*1a96fba6SXin Li constexpr size_t kFileSize = 2 * 1024 * 1024;
350*1a96fba6SXin Li
351*1a96fba6SXin Li const base::FilePath dirname(GetTempName());
352*1a96fba6SXin Li EXPECT_TRUE(base::CreateDirectory(dirname));
353*1a96fba6SXin Li const base::FilePath filename = dirname.Append("test.temp");
354*1a96fba6SXin Li
355*1a96fba6SXin Li std::string file_content = base::RandBytesAsString(kFileSize);
356*1a96fba6SXin Li EXPECT_TRUE(WriteStringToFile(filename, file_content));
357*1a96fba6SXin Li
358*1a96fba6SXin Li int64_t result_usage = ComputeDirectoryDiskUsage(dirname);
359*1a96fba6SXin Li int64_t result_size = base::ComputeDirectorySize(dirname);
360*1a96fba6SXin Li
361*1a96fba6SXin Li // result_usage (what we are testing here) should be within +/-10% of ground
362*1a96fba6SXin Li // truth. The variation is to account for filesystem overhead variations.
363*1a96fba6SXin Li EXPECT_GT(result_usage, kFileSize / 10 * 9);
364*1a96fba6SXin Li EXPECT_LT(result_usage, kFileSize / 10 * 11);
365*1a96fba6SXin Li
366*1a96fba6SXin Li // result_usage should be close to result_size, because the test file is
367*1a96fba6SXin Li // random so it's disk usage should be similar to apparent size.
368*1a96fba6SXin Li EXPECT_GT(result_usage, result_size / 10 * 9);
369*1a96fba6SXin Li EXPECT_LT(result_usage, result_size / 10 * 11);
370*1a96fba6SXin Li }
371*1a96fba6SXin Li
TEST_F(FileUtilsTest,ComputeDirectoryDiskUsageDeepRandomFile)372*1a96fba6SXin Li TEST_F(FileUtilsTest, ComputeDirectoryDiskUsageDeepRandomFile) {
373*1a96fba6SXin Li // 2MB test file.
374*1a96fba6SXin Li constexpr size_t kFileSize = 2 * 1024 * 1024;
375*1a96fba6SXin Li
376*1a96fba6SXin Li const base::FilePath dirname(GetTempName());
377*1a96fba6SXin Li EXPECT_TRUE(base::CreateDirectory(dirname));
378*1a96fba6SXin Li base::FilePath currentlevel = dirname;
379*1a96fba6SXin Li for (int i = 0; i < 10; i++) {
380*1a96fba6SXin Li base::FilePath nextlevel = currentlevel.Append("test.dir");
381*1a96fba6SXin Li EXPECT_TRUE(base::CreateDirectory(nextlevel));
382*1a96fba6SXin Li currentlevel = nextlevel;
383*1a96fba6SXin Li }
384*1a96fba6SXin Li const base::FilePath filename = currentlevel.Append("test.temp");
385*1a96fba6SXin Li
386*1a96fba6SXin Li std::string file_content = base::RandBytesAsString(kFileSize);
387*1a96fba6SXin Li EXPECT_TRUE(WriteStringToFile(filename, file_content));
388*1a96fba6SXin Li
389*1a96fba6SXin Li int64_t result_usage = ComputeDirectoryDiskUsage(dirname);
390*1a96fba6SXin Li int64_t result_size = base::ComputeDirectorySize(dirname);
391*1a96fba6SXin Li
392*1a96fba6SXin Li // result_usage (what we are testing here) should be within +/-10% of ground
393*1a96fba6SXin Li // truth. The variation is to account for filesystem overhead variations.
394*1a96fba6SXin Li EXPECT_GT(result_usage, kFileSize / 10 * 9);
395*1a96fba6SXin Li EXPECT_LT(result_usage, kFileSize / 10 * 11);
396*1a96fba6SXin Li
397*1a96fba6SXin Li // result_usage should be close to result_size, because the test file is
398*1a96fba6SXin Li // random so it's disk usage should be similar to apparent size.
399*1a96fba6SXin Li EXPECT_GT(result_usage, result_size / 10 * 9);
400*1a96fba6SXin Li EXPECT_LT(result_usage, result_size / 10 * 11);
401*1a96fba6SXin Li }
402*1a96fba6SXin Li
TEST_F(FileUtilsTest,ComputeDirectoryDiskUsageHiddenRandomFile)403*1a96fba6SXin Li TEST_F(FileUtilsTest, ComputeDirectoryDiskUsageHiddenRandomFile) {
404*1a96fba6SXin Li // 2MB test file.
405*1a96fba6SXin Li constexpr size_t kFileSize = 2 * 1024 * 1024;
406*1a96fba6SXin Li
407*1a96fba6SXin Li const base::FilePath dirname(GetTempName());
408*1a96fba6SXin Li EXPECT_TRUE(base::CreateDirectory(dirname));
409*1a96fba6SXin Li // File name starts with a dot, so it's a hidden file.
410*1a96fba6SXin Li const base::FilePath filename = dirname.Append(".test.temp");
411*1a96fba6SXin Li
412*1a96fba6SXin Li std::string file_content = base::RandBytesAsString(kFileSize);
413*1a96fba6SXin Li EXPECT_TRUE(WriteStringToFile(filename, file_content));
414*1a96fba6SXin Li
415*1a96fba6SXin Li int64_t result_usage = ComputeDirectoryDiskUsage(dirname);
416*1a96fba6SXin Li int64_t result_size = base::ComputeDirectorySize(dirname);
417*1a96fba6SXin Li
418*1a96fba6SXin Li // result_usage (what we are testing here) should be within +/-10% of ground
419*1a96fba6SXin Li // truth. The variation is to account for filesystem overhead variations.
420*1a96fba6SXin Li EXPECT_GT(result_usage, kFileSize / 10 * 9);
421*1a96fba6SXin Li EXPECT_LT(result_usage, kFileSize / 10 * 11);
422*1a96fba6SXin Li
423*1a96fba6SXin Li // result_usage should be close to result_size, because the test file is
424*1a96fba6SXin Li // random so it's disk usage should be similar to apparent size.
425*1a96fba6SXin Li EXPECT_GT(result_usage, result_size / 10 * 9);
426*1a96fba6SXin Li EXPECT_LT(result_usage, result_size / 10 * 11);
427*1a96fba6SXin Li }
428*1a96fba6SXin Li
TEST_F(FileUtilsTest,ComputeDirectoryDiskUsageSparseFile)429*1a96fba6SXin Li TEST_F(FileUtilsTest, ComputeDirectoryDiskUsageSparseFile) {
430*1a96fba6SXin Li // 128MB sparse test file.
431*1a96fba6SXin Li constexpr size_t kFileSize = 128 * 1024 * 1024;
432*1a96fba6SXin Li constexpr size_t kFileSizeThreshold = 64 * 1024;
433*1a96fba6SXin Li
434*1a96fba6SXin Li const base::FilePath dirname(GetTempName());
435*1a96fba6SXin Li EXPECT_TRUE(base::CreateDirectory(dirname));
436*1a96fba6SXin Li const base::FilePath filename = dirname.Append("test.temp");
437*1a96fba6SXin Li
438*1a96fba6SXin Li int fd =
439*1a96fba6SXin Li open(filename.value().c_str(), O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
440*1a96fba6SXin Li EXPECT_NE(fd, -1);
441*1a96fba6SXin Li // Calling ftruncate on an empty file will create a sparse file.
442*1a96fba6SXin Li EXPECT_EQ(0, ftruncate(fd, kFileSize));
443*1a96fba6SXin Li
444*1a96fba6SXin Li int64_t result_usage = ComputeDirectoryDiskUsage(dirname);
445*1a96fba6SXin Li int64_t result_size = base::ComputeDirectorySize(dirname);
446*1a96fba6SXin Li
447*1a96fba6SXin Li // result_usage (what we are testing here) should be less than
448*1a96fba6SXin Li // kFileSizeThreshold, the threshold is to account for filesystem overhead
449*1a96fba6SXin Li // variations.
450*1a96fba6SXin Li EXPECT_LT(result_usage, kFileSizeThreshold);
451*1a96fba6SXin Li
452*1a96fba6SXin Li // Since we are dealing with sparse files here, the apparent size should be
453*1a96fba6SXin Li // much much larger than the actual disk usage.
454*1a96fba6SXin Li EXPECT_LT(result_usage, result_size / 1000);
455*1a96fba6SXin Li }
456*1a96fba6SXin Li
TEST_F(FileUtilsTest,ComputeDirectoryDiskUsageSymlinkFile)457*1a96fba6SXin Li TEST_F(FileUtilsTest, ComputeDirectoryDiskUsageSymlinkFile) {
458*1a96fba6SXin Li // 2MB test file.
459*1a96fba6SXin Li constexpr size_t kFileSize = 2 * 1024 * 1024;
460*1a96fba6SXin Li
461*1a96fba6SXin Li const base::FilePath dirname(GetTempName());
462*1a96fba6SXin Li EXPECT_TRUE(base::CreateDirectory(dirname));
463*1a96fba6SXin Li const base::FilePath filename = dirname.Append("test.temp");
464*1a96fba6SXin Li const base::FilePath linkname = dirname.Append("test.link");
465*1a96fba6SXin Li
466*1a96fba6SXin Li std::string file_content = base::RandBytesAsString(kFileSize);
467*1a96fba6SXin Li EXPECT_TRUE(WriteStringToFile(filename, file_content));
468*1a96fba6SXin Li
469*1a96fba6SXin Li // Create a symlink.
470*1a96fba6SXin Li EXPECT_TRUE(base::CreateSymbolicLink(filename, linkname));
471*1a96fba6SXin Li
472*1a96fba6SXin Li int64_t result_usage = ComputeDirectoryDiskUsage(dirname);
473*1a96fba6SXin Li
474*1a96fba6SXin Li // result_usage (what we are testing here) should be within +/-10% of ground
475*1a96fba6SXin Li // truth. The variation is to account for filesystem overhead variations.
476*1a96fba6SXin Li // Note that it's not 2x kFileSize because symblink is not counted twice.
477*1a96fba6SXin Li EXPECT_GT(result_usage, kFileSize / 10 * 9);
478*1a96fba6SXin Li EXPECT_LT(result_usage, kFileSize / 10 * 11);
479*1a96fba6SXin Li }
480*1a96fba6SXin Li
TEST_F(FileUtilsTest,ComputeDirectoryDiskUsageSymlinkDir)481*1a96fba6SXin Li TEST_F(FileUtilsTest, ComputeDirectoryDiskUsageSymlinkDir) {
482*1a96fba6SXin Li // 2MB test file.
483*1a96fba6SXin Li constexpr size_t kFileSize = 2 * 1024 * 1024;
484*1a96fba6SXin Li
485*1a96fba6SXin Li const base::FilePath parentname(GetTempName());
486*1a96fba6SXin Li EXPECT_TRUE(base::CreateDirectory(parentname));
487*1a96fba6SXin Li const base::FilePath dirname = parentname.Append("target.dir");
488*1a96fba6SXin Li EXPECT_TRUE(base::CreateDirectory(dirname));
489*1a96fba6SXin Li const base::FilePath linkname = parentname.Append("link.dir");
490*1a96fba6SXin Li
491*1a96fba6SXin Li const base::FilePath filename = dirname.Append("test.temp");
492*1a96fba6SXin Li
493*1a96fba6SXin Li std::string file_content = base::RandBytesAsString(kFileSize);
494*1a96fba6SXin Li EXPECT_TRUE(WriteStringToFile(filename, file_content));
495*1a96fba6SXin Li
496*1a96fba6SXin Li // Create a symlink.
497*1a96fba6SXin Li EXPECT_TRUE(base::CreateSymbolicLink(dirname, linkname));
498*1a96fba6SXin Li
499*1a96fba6SXin Li int64_t result_usage = ComputeDirectoryDiskUsage(dirname);
500*1a96fba6SXin Li
501*1a96fba6SXin Li // result_usage (what we are testing here) should be within +/-10% of ground
502*1a96fba6SXin Li // truth. The variation is to account for filesystem overhead variations.
503*1a96fba6SXin Li // Note that it's not 2x kFileSize because symblink is not counted twice.
504*1a96fba6SXin Li EXPECT_GT(result_usage, kFileSize / 10 * 9);
505*1a96fba6SXin Li EXPECT_LT(result_usage, kFileSize / 10 * 11);
506*1a96fba6SXin Li }
507*1a96fba6SXin Li
508*1a96fba6SXin Li } // namespace brillo
509