1*ec63e07aSXin Li // Copyright 2019 Google LLC
2*ec63e07aSXin Li //
3*ec63e07aSXin Li // Licensed under the Apache License, Version 2.0 (the "License");
4*ec63e07aSXin Li // you may not use this file except in compliance with the License.
5*ec63e07aSXin Li // You may obtain a copy of the License at
6*ec63e07aSXin Li //
7*ec63e07aSXin Li // https://www.apache.org/licenses/LICENSE-2.0
8*ec63e07aSXin Li //
9*ec63e07aSXin Li // Unless required by applicable law or agreed to in writing, software
10*ec63e07aSXin Li // distributed under the License is distributed on an "AS IS" BASIS,
11*ec63e07aSXin Li // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*ec63e07aSXin Li // See the License for the specific language governing permissions and
13*ec63e07aSXin Li // limitations under the License.
14*ec63e07aSXin Li
15*ec63e07aSXin Li #include "sandboxed_api/util/fileops.h"
16*ec63e07aSXin Li
17*ec63e07aSXin Li #include <sys/stat.h>
18*ec63e07aSXin Li #include <unistd.h>
19*ec63e07aSXin Li
20*ec63e07aSXin Li #include <algorithm>
21*ec63e07aSXin Li #include <cerrno>
22*ec63e07aSXin Li #include <climits>
23*ec63e07aSXin Li #include <string>
24*ec63e07aSXin Li #include <vector>
25*ec63e07aSXin Li
26*ec63e07aSXin Li #include "gmock/gmock.h"
27*ec63e07aSXin Li #include "gtest/gtest.h"
28*ec63e07aSXin Li #include "absl/strings/str_cat.h"
29*ec63e07aSXin Li #include "sandboxed_api/testing.h"
30*ec63e07aSXin Li #include "sandboxed_api/util/file_helpers.h"
31*ec63e07aSXin Li #include "sandboxed_api/util/status_matchers.h"
32*ec63e07aSXin Li
33*ec63e07aSXin Li namespace sapi::file_util {
34*ec63e07aSXin Li
35*ec63e07aSXin Li // Forward declare functions that are only used in fileops.cc.
36*ec63e07aSXin Li namespace fileops {
37*ec63e07aSXin Li bool GetCWD(std::string* result);
38*ec63e07aSXin Li bool RemoveLastPathComponent(const std::string& file, std::string* output);
39*ec63e07aSXin Li } // namespace fileops
40*ec63e07aSXin Li
41*ec63e07aSXin Li namespace {
42*ec63e07aSXin Li
43*ec63e07aSXin Li using ::sapi::IsOk;
44*ec63e07aSXin Li using ::testing::Eq;
45*ec63e07aSXin Li using ::testing::IsEmpty;
46*ec63e07aSXin Li using ::testing::IsFalse;
47*ec63e07aSXin Li using ::testing::IsTrue;
48*ec63e07aSXin Li using ::testing::Ne;
49*ec63e07aSXin Li using ::testing::SizeIs;
50*ec63e07aSXin Li using ::testing::StrEq;
51*ec63e07aSXin Li
52*ec63e07aSXin Li class FileOpsTest : public testing::Test {
53*ec63e07aSXin Li protected:
SetUpTestSuite()54*ec63e07aSXin Li static void SetUpTestSuite() {
55*ec63e07aSXin Li ASSERT_THAT(chdir(GetTestTempPath().c_str()), Eq(0));
56*ec63e07aSXin Li }
57*ec63e07aSXin Li };
58*ec63e07aSXin Li
TEST_F(FileOpsTest,GetCWDTest)59*ec63e07aSXin Li TEST_F(FileOpsTest, GetCWDTest) {
60*ec63e07aSXin Li std::string result;
61*ec63e07aSXin Li ASSERT_THAT(fileops::GetCWD(&result), IsTrue());
62*ec63e07aSXin Li EXPECT_THAT(result, StrEq(GetTestTempPath()));
63*ec63e07aSXin Li }
64*ec63e07aSXin Li
TEST_F(FileOpsTest,MakeAbsoluteTest)65*ec63e07aSXin Li TEST_F(FileOpsTest, MakeAbsoluteTest) {
66*ec63e07aSXin Li const auto tmp_dir = GetTestTempPath();
67*ec63e07aSXin Li ASSERT_THAT(chdir(tmp_dir.c_str()), Eq(0));
68*ec63e07aSXin Li EXPECT_THAT(fileops::MakeAbsolute("", ""), StrEq(""));
69*ec63e07aSXin Li EXPECT_THAT(fileops::MakeAbsolute(".", ""), StrEq(tmp_dir));
70*ec63e07aSXin Li EXPECT_THAT(fileops::MakeAbsolute(".", tmp_dir), StrEq(tmp_dir));
71*ec63e07aSXin Li EXPECT_THAT(fileops::MakeAbsolute(".", "/"), StrEq("/"));
72*ec63e07aSXin Li EXPECT_THAT(fileops::MakeAbsolute("/", tmp_dir), StrEq("/"));
73*ec63e07aSXin Li EXPECT_THAT(fileops::MakeAbsolute("/", "/"), StrEq("/"));
74*ec63e07aSXin Li EXPECT_THAT(fileops::MakeAbsolute("/", ""), StrEq("/"));
75*ec63e07aSXin Li EXPECT_THAT(fileops::MakeAbsolute("/foo/bar", ""), StrEq("/foo/bar"));
76*ec63e07aSXin Li EXPECT_THAT(fileops::MakeAbsolute("foo/bar", ""),
77*ec63e07aSXin Li StrEq(absl::StrCat(tmp_dir, "/foo/bar")));
78*ec63e07aSXin Li EXPECT_THAT(fileops::MakeAbsolute("foo/bar", tmp_dir),
79*ec63e07aSXin Li StrEq(absl::StrCat(tmp_dir, "/foo/bar")));
80*ec63e07aSXin Li EXPECT_THAT(fileops::MakeAbsolute("foo/bar", tmp_dir + "/"),
81*ec63e07aSXin Li StrEq(absl::StrCat(tmp_dir, "/foo/bar")));
82*ec63e07aSXin Li }
83*ec63e07aSXin Li
TEST_F(FileOpsTest,ExistsTest)84*ec63e07aSXin Li TEST_F(FileOpsTest, ExistsTest) {
85*ec63e07aSXin Li ASSERT_THAT(file::SetContents("exists_test", "", file::Defaults()), IsOk());
86*ec63e07aSXin Li EXPECT_THAT(fileops::Exists("exists_test", false), IsTrue());
87*ec63e07aSXin Li EXPECT_THAT(fileops::Exists("exists_test", true), IsTrue());
88*ec63e07aSXin Li
89*ec63e07aSXin Li ASSERT_THAT(symlink("exists_test", "exists_test_link"), Eq(0));
90*ec63e07aSXin Li EXPECT_THAT(fileops::Exists("exists_test_link", false), IsTrue());
91*ec63e07aSXin Li EXPECT_THAT(fileops::Exists("exists_test_link", true), IsTrue());
92*ec63e07aSXin Li
93*ec63e07aSXin Li ASSERT_THAT(unlink("exists_test"), Eq(0));
94*ec63e07aSXin Li EXPECT_THAT(fileops::Exists("exists_test_link", false), IsTrue());
95*ec63e07aSXin Li EXPECT_THAT(fileops::Exists("exists_test_link", true), IsFalse());
96*ec63e07aSXin Li
97*ec63e07aSXin Li ASSERT_THAT(unlink("exists_test_link"), Eq(0));
98*ec63e07aSXin Li EXPECT_THAT(fileops::Exists("exists_test_link", false), IsFalse());
99*ec63e07aSXin Li EXPECT_THAT(fileops::Exists("exists_test_link", true), IsFalse());
100*ec63e07aSXin Li }
101*ec63e07aSXin Li
TEST_F(FileOpsTest,ReadLinkTest)102*ec63e07aSXin Li TEST_F(FileOpsTest, ReadLinkTest) {
103*ec63e07aSXin Li EXPECT_THAT(fileops::ReadLink("readlink_not_there"), StrEq(""));
104*ec63e07aSXin Li EXPECT_THAT(errno, Eq(ENOENT));
105*ec63e07aSXin Li
106*ec63e07aSXin Li ASSERT_THAT(file::SetContents("readlink_file", "", file::Defaults()), IsOk());
107*ec63e07aSXin Li EXPECT_THAT(fileops::ReadLink("readlink_file"), StrEq(""));
108*ec63e07aSXin Li unlink("readlink_file");
109*ec63e07aSXin Li
110*ec63e07aSXin Li ASSERT_THAT(symlink("..", "readlink_dotdot"), Eq(0));
111*ec63e07aSXin Li EXPECT_THAT(fileops::ReadLink("readlink_dotdot"), StrEq(".."));
112*ec63e07aSXin Li unlink("readlink_dotdot");
113*ec63e07aSXin Li
114*ec63e07aSXin Li ASSERT_THAT(symlink("../", "readlink_dotdotslash"), 0);
115*ec63e07aSXin Li EXPECT_THAT(fileops::ReadLink("readlink_dotdotslash"), "../");
116*ec63e07aSXin Li unlink("readlink_dotdotslash");
117*ec63e07aSXin Li
118*ec63e07aSXin Li ASSERT_THAT(symlink("/", "readlink_slash"), 0);
119*ec63e07aSXin Li EXPECT_THAT(fileops::ReadLink("readlink_slash"), "/");
120*ec63e07aSXin Li unlink("readlink_slash");
121*ec63e07aSXin Li
122*ec63e07aSXin Li const std::string very_long_name(PATH_MAX - 1, 'f');
123*ec63e07aSXin Li ASSERT_THAT(symlink(very_long_name.c_str(), "readlink_long"), Eq(0));
124*ec63e07aSXin Li EXPECT_THAT(fileops::ReadLink("readlink_long"), StrEq(very_long_name));
125*ec63e07aSXin Li unlink("readlink_long");
126*ec63e07aSXin Li }
127*ec63e07aSXin Li
TEST_F(FileOpsTest,ListDirectoryEntriesFailTest)128*ec63e07aSXin Li TEST_F(FileOpsTest, ListDirectoryEntriesFailTest) {
129*ec63e07aSXin Li std::vector<std::string> files;
130*ec63e07aSXin Li std::string error;
131*ec63e07aSXin Li
132*ec63e07aSXin Li EXPECT_THAT(fileops::ListDirectoryEntries("new_dir", &files, &error),
133*ec63e07aSXin Li IsFalse());
134*ec63e07aSXin Li EXPECT_THAT(files, IsEmpty());
135*ec63e07aSXin Li EXPECT_THAT(error, StrEq("opendir(new_dir): No such file or directory"));
136*ec63e07aSXin Li }
137*ec63e07aSXin Li
TEST_F(FileOpsTest,ListDirectoryEntriesEmptyTest)138*ec63e07aSXin Li TEST_F(FileOpsTest, ListDirectoryEntriesEmptyTest) {
139*ec63e07aSXin Li std::vector<std::string> files;
140*ec63e07aSXin Li std::string error;
141*ec63e07aSXin Li
142*ec63e07aSXin Li ASSERT_THAT(mkdir("new_dir", 0700), Eq(0));
143*ec63e07aSXin Li
144*ec63e07aSXin Li EXPECT_THAT(fileops::ListDirectoryEntries("new_dir", &files, &error),
145*ec63e07aSXin Li IsTrue());
146*ec63e07aSXin Li EXPECT_THAT(files, IsEmpty());
147*ec63e07aSXin Li
148*ec63e07aSXin Li rmdir("new_dir");
149*ec63e07aSXin Li }
150*ec63e07aSXin Li
TEST_F(FileOpsTest,ListDirectoryEntriesOneFileTest)151*ec63e07aSXin Li TEST_F(FileOpsTest, ListDirectoryEntriesOneFileTest) {
152*ec63e07aSXin Li ASSERT_THAT(mkdir("new_dir", 0700), Eq(0));
153*ec63e07aSXin Li ASSERT_THAT(file::SetContents("new_dir/first", "", file::Defaults()), IsOk());
154*ec63e07aSXin Li
155*ec63e07aSXin Li std::vector<std::string> files;
156*ec63e07aSXin Li std::string error;
157*ec63e07aSXin Li EXPECT_THAT(fileops::ListDirectoryEntries("new_dir", &files, &error),
158*ec63e07aSXin Li IsTrue());
159*ec63e07aSXin Li
160*ec63e07aSXin Li unlink("new_dir/first");
161*ec63e07aSXin Li rmdir("new_dir");
162*ec63e07aSXin Li
163*ec63e07aSXin Li ASSERT_THAT(files, SizeIs(1));
164*ec63e07aSXin Li EXPECT_THAT(files[0], "first");
165*ec63e07aSXin Li }
166*ec63e07aSXin Li
TEST_F(FileOpsTest,ListDirectoryEntriesTest)167*ec63e07aSXin Li TEST_F(FileOpsTest, ListDirectoryEntriesTest) {
168*ec63e07aSXin Li ASSERT_THAT(mkdir("new_dir", 0700), Eq(0));
169*ec63e07aSXin Li constexpr int kNumFiles = 10;
170*ec63e07aSXin Li for (int i = 0; i < kNumFiles; ++i) {
171*ec63e07aSXin Li ASSERT_THAT(file::SetContents(absl::StrCat("new_dir/file", i), "",
172*ec63e07aSXin Li file::Defaults()),
173*ec63e07aSXin Li IsOk());
174*ec63e07aSXin Li }
175*ec63e07aSXin Li
176*ec63e07aSXin Li std::vector<std::string> files;
177*ec63e07aSXin Li std::string error;
178*ec63e07aSXin Li EXPECT_THAT(fileops::ListDirectoryEntries("new_dir", &files, &error),
179*ec63e07aSXin Li IsTrue());
180*ec63e07aSXin Li
181*ec63e07aSXin Li fileops::DeleteRecursively("new_dir");
182*ec63e07aSXin Li
183*ec63e07aSXin Li ASSERT_THAT(files, SizeIs(kNumFiles));
184*ec63e07aSXin Li std::sort(files.begin(), files.end());
185*ec63e07aSXin Li for (int i = 0; i < kNumFiles; ++i) {
186*ec63e07aSXin Li EXPECT_THAT(files[i], StrEq(absl::StrCat("file", i)));
187*ec63e07aSXin Li }
188*ec63e07aSXin Li }
189*ec63e07aSXin Li
TEST_F(FileOpsTest,RemoveLastPathComponentTest)190*ec63e07aSXin Li TEST_F(FileOpsTest, RemoveLastPathComponentTest) {
191*ec63e07aSXin Li std::string result;
192*ec63e07aSXin Li
193*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("/", &result), IsFalse());
194*ec63e07aSXin Li EXPECT_THAT(result, StrEq("/"));
195*ec63e07aSXin Li
196*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("///", &result), IsFalse());
197*ec63e07aSXin Li EXPECT_THAT(result, StrEq("/"));
198*ec63e07aSXin Li
199*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("/home", &result), IsTrue());
200*ec63e07aSXin Li EXPECT_THAT(result, StrEq("/"));
201*ec63e07aSXin Li
202*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("/home/", &result), IsTrue());
203*ec63e07aSXin Li EXPECT_THAT(result, StrEq("/"));
204*ec63e07aSXin Li
205*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("/home///", &result), IsTrue());
206*ec63e07aSXin Li EXPECT_THAT(result, StrEq("/"));
207*ec63e07aSXin Li
208*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("/home///", &result), IsTrue());
209*ec63e07aSXin Li EXPECT_THAT(result, StrEq("/"));
210*ec63e07aSXin Li
211*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("///home///", &result),
212*ec63e07aSXin Li IsTrue());
213*ec63e07aSXin Li EXPECT_THAT(result, StrEq("/"));
214*ec63e07aSXin Li
215*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("/home/someone", &result),
216*ec63e07aSXin Li IsTrue());
217*ec63e07aSXin Li EXPECT_THAT(result, StrEq("/home"));
218*ec63e07aSXin Li
219*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("/home///someone", &result),
220*ec63e07aSXin Li IsTrue());
221*ec63e07aSXin Li EXPECT_THAT(result, StrEq("/home"));
222*ec63e07aSXin Li
223*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("/home///someone/", &result),
224*ec63e07aSXin Li IsTrue());
225*ec63e07aSXin Li EXPECT_THAT(result, StrEq("/home"));
226*ec63e07aSXin Li
227*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("/home///someone//", &result),
228*ec63e07aSXin Li IsTrue());
229*ec63e07aSXin Li EXPECT_THAT(result, StrEq("/home"));
230*ec63e07aSXin Li
231*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("/home/someone/file", &result),
232*ec63e07aSXin Li IsTrue());
233*ec63e07aSXin Li EXPECT_THAT(result, StrEq("/home/someone"));
234*ec63e07aSXin Li
235*ec63e07aSXin Li EXPECT_THAT(
236*ec63e07aSXin Li fileops::RemoveLastPathComponent("/home/someone////file", &result),
237*ec63e07aSXin Li IsTrue());
238*ec63e07aSXin Li EXPECT_THAT(result, StrEq("/home/someone"));
239*ec63e07aSXin Li
240*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("/home///someone/file", &result),
241*ec63e07aSXin Li IsTrue());
242*ec63e07aSXin Li EXPECT_THAT(result, StrEq("/home///someone"));
243*ec63e07aSXin Li
244*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("/home/someone/file", &result),
245*ec63e07aSXin Li IsTrue());
246*ec63e07aSXin Li EXPECT_THAT(result, StrEq("/home/someone"));
247*ec63e07aSXin Li
248*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("no_root", &result), IsTrue());
249*ec63e07aSXin Li EXPECT_THAT(result, StrEq(""));
250*ec63e07aSXin Li
251*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("no_root/", &result), IsTrue());
252*ec63e07aSXin Li EXPECT_THAT(result, StrEq(""));
253*ec63e07aSXin Li
254*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("no_root///", &result),
255*ec63e07aSXin Li IsTrue());
256*ec63e07aSXin Li EXPECT_THAT(result, StrEq(""));
257*ec63e07aSXin Li
258*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("/file", &result), IsTrue());
259*ec63e07aSXin Li EXPECT_THAT(result, "/");
260*ec63e07aSXin Li
261*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("no_root/file", &result),
262*ec63e07aSXin Li IsTrue());
263*ec63e07aSXin Li EXPECT_THAT(result, StrEq("no_root"));
264*ec63e07aSXin Li
265*ec63e07aSXin Li result = "no_root";
266*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent(result, &result), IsTrue());
267*ec63e07aSXin Li EXPECT_THAT(result, StrEq(""));
268*ec63e07aSXin Li
269*ec63e07aSXin Li result = "no_root/";
270*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent(result, &result), IsTrue());
271*ec63e07aSXin Li EXPECT_THAT(result, StrEq(""));
272*ec63e07aSXin Li
273*ec63e07aSXin Li result = "no_root///";
274*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent(result, &result), IsTrue());
275*ec63e07aSXin Li EXPECT_THAT(result, StrEq(""));
276*ec63e07aSXin Li
277*ec63e07aSXin Li result = "/file";
278*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent(result, &result), IsTrue());
279*ec63e07aSXin Li EXPECT_THAT(result, StrEq("/"));
280*ec63e07aSXin Li
281*ec63e07aSXin Li result = "no_root/file";
282*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent(result, &result), IsTrue());
283*ec63e07aSXin Li EXPECT_THAT(result, StrEq("no_root"));
284*ec63e07aSXin Li
285*ec63e07aSXin Li EXPECT_THAT(fileops::RemoveLastPathComponent("", &result), IsFalse());
286*ec63e07aSXin Li EXPECT_THAT(result, StrEq(""));
287*ec63e07aSXin Li }
288*ec63e07aSXin Li
TEST_F(FileOpsTest,TestBasename)289*ec63e07aSXin Li TEST_F(FileOpsTest, TestBasename) {
290*ec63e07aSXin Li EXPECT_THAT(fileops::Basename(""), StrEq(""));
291*ec63e07aSXin Li EXPECT_THAT(fileops::Basename("/"), StrEq(""));
292*ec63e07aSXin Li EXPECT_THAT(fileops::Basename("//"), StrEq(""));
293*ec63e07aSXin Li EXPECT_THAT(fileops::Basename("/hello/"), StrEq(""));
294*ec63e07aSXin Li EXPECT_THAT(fileops::Basename("//hello"), StrEq("hello"));
295*ec63e07aSXin Li EXPECT_THAT(fileops::Basename("/hello/world"), StrEq("world"));
296*ec63e07aSXin Li EXPECT_THAT(fileops::Basename("/hello, world"), StrEq("hello, world"));
297*ec63e07aSXin Li }
298*ec63e07aSXin Li
TEST_F(FileOpsTest,TestStripBasename)299*ec63e07aSXin Li TEST_F(FileOpsTest, TestStripBasename) {
300*ec63e07aSXin Li EXPECT_THAT(fileops::StripBasename(""), StrEq(""));
301*ec63e07aSXin Li EXPECT_THAT(fileops::StripBasename("/"), StrEq("/"));
302*ec63e07aSXin Li EXPECT_THAT(fileops::StripBasename("//"), StrEq("/"));
303*ec63e07aSXin Li EXPECT_THAT(fileops::StripBasename("/hello"), StrEq("/"));
304*ec63e07aSXin Li EXPECT_THAT(fileops::StripBasename("//hello"), StrEq("/"));
305*ec63e07aSXin Li EXPECT_THAT(fileops::StripBasename("/hello/"), StrEq("/hello"));
306*ec63e07aSXin Li EXPECT_THAT(fileops::StripBasename("/hello//"), StrEq("/hello/"));
307*ec63e07aSXin Li EXPECT_THAT(fileops::StripBasename("/hello/world"), StrEq("/hello"));
308*ec63e07aSXin Li EXPECT_THAT(fileops::StripBasename("/hello, world"), StrEq("/"));
309*ec63e07aSXin Li }
310*ec63e07aSXin Li
SetupDirectory()311*ec63e07aSXin Li void SetupDirectory() {
312*ec63e07aSXin Li ASSERT_THAT(mkdir("foo", 0755), Eq(0));
313*ec63e07aSXin Li ASSERT_THAT(mkdir("foo/bar", 0755), Eq(0));
314*ec63e07aSXin Li ASSERT_THAT(mkdir("foo/baz", 0755), Eq(0));
315*ec63e07aSXin Li ASSERT_THAT(file::SetContents("foo/quux", "", file::Defaults()), IsOk());
316*ec63e07aSXin Li ASSERT_THAT(chmod("foo/quux", 0644), Eq(0));
317*ec63e07aSXin Li
318*ec63e07aSXin Li ASSERT_THAT(file::SetContents("foo/bar/foo", "", file::Defaults()), IsOk());
319*ec63e07aSXin Li ASSERT_THAT(chmod("foo/bar/foo", 0644), Eq(0));
320*ec63e07aSXin Li ASSERT_THAT(file::SetContents("foo/bar/bar", "", file::Defaults()), IsOk());
321*ec63e07aSXin Li ASSERT_THAT(chmod("foo/bar/bar", 0644), Eq(0));
322*ec63e07aSXin Li
323*ec63e07aSXin Li ASSERT_THAT(mkdir("foo/bar/baz", 0755), Eq(0));
324*ec63e07aSXin Li ASSERT_THAT(file::SetContents("foo/bar/baz/foo", "", file::Defaults()),
325*ec63e07aSXin Li IsOk());
326*ec63e07aSXin Li ASSERT_THAT(chmod("foo/bar/baz/foo", 0644), Eq(0));
327*ec63e07aSXin Li }
328*ec63e07aSXin Li
TEST_F(FileOpsTest,CreateDirectoryRecursivelyTest)329*ec63e07aSXin Li TEST_F(FileOpsTest, CreateDirectoryRecursivelyTest) {
330*ec63e07aSXin Li constexpr char kTestDir[] = "a/b/c";
331*ec63e07aSXin Li EXPECT_THAT(fileops::CreateDirectoryRecursively(kTestDir, 0700), IsTrue());
332*ec63e07aSXin Li EXPECT_THAT(fileops::CreateDirectoryRecursively(kTestDir, 0700), IsTrue());
333*ec63e07aSXin Li }
334*ec63e07aSXin Li
TEST_F(FileOpsTest,DeleteRecursivelyTest)335*ec63e07aSXin Li TEST_F(FileOpsTest, DeleteRecursivelyTest) {
336*ec63e07aSXin Li EXPECT_THAT(fileops::DeleteRecursively("foo"), IsTrue());
337*ec63e07aSXin Li EXPECT_THAT(fileops::DeleteRecursively("/not_there"), IsTrue());
338*ec63e07aSXin Li
339*ec63e07aSXin Li // Can't stat file
340*ec63e07aSXin Li SetupDirectory();
341*ec63e07aSXin Li ASSERT_THAT(chmod("foo/bar/baz", 0000), Eq(0));
342*ec63e07aSXin Li EXPECT_THAT(fileops::DeleteRecursively("foo/bar/baz/quux"), IsFalse());
343*ec63e07aSXin Li EXPECT_THAT(errno, Eq(EACCES));
344*ec63e07aSXin Li ASSERT_THAT(chmod("foo/bar/baz", 0755), Eq(0));
345*ec63e07aSXin Li
346*ec63e07aSXin Li EXPECT_THAT(fileops::DeleteRecursively("foo"), IsTrue());
347*ec63e07aSXin Li struct stat64 st;
348*ec63e07aSXin Li EXPECT_THAT(lstat64("foo", &st), Ne(0));
349*ec63e07aSXin Li
350*ec63e07aSXin Li // Can't list subdirectory
351*ec63e07aSXin Li SetupDirectory();
352*ec63e07aSXin Li ASSERT_THAT(chmod("foo/bar/baz", 0000), Eq(0));
353*ec63e07aSXin Li EXPECT_THAT(fileops::DeleteRecursively("foo"), IsFalse());
354*ec63e07aSXin Li EXPECT_THAT(errno, Eq(EACCES));
355*ec63e07aSXin Li ASSERT_THAT(chmod("foo/bar/baz", 0755), Eq(0));
356*ec63e07aSXin Li
357*ec63e07aSXin Li EXPECT_THAT(fileops::DeleteRecursively("foo"), IsTrue());
358*ec63e07aSXin Li
359*ec63e07aSXin Li // Can't delete file
360*ec63e07aSXin Li SetupDirectory();
361*ec63e07aSXin Li ASSERT_THAT(chmod("foo/bar/baz", 0500), Eq(0));
362*ec63e07aSXin Li EXPECT_THAT(fileops::DeleteRecursively("foo"), IsFalse());
363*ec63e07aSXin Li EXPECT_THAT(errno, Eq(EACCES));
364*ec63e07aSXin Li ASSERT_THAT(chmod("foo/bar/baz", 0755), Eq(0));
365*ec63e07aSXin Li
366*ec63e07aSXin Li EXPECT_THAT(fileops::DeleteRecursively("foo"), IsTrue());
367*ec63e07aSXin Li
368*ec63e07aSXin Li // Can't delete directory
369*ec63e07aSXin Li SetupDirectory();
370*ec63e07aSXin Li ASSERT_THAT(fileops::DeleteRecursively("foo/bar/baz/foo"), IsTrue());
371*ec63e07aSXin Li ASSERT_THAT(chmod("foo/bar", 0500), Eq(0));
372*ec63e07aSXin Li EXPECT_THAT(fileops::DeleteRecursively("foo/bar/baz"), IsFalse());
373*ec63e07aSXin Li EXPECT_THAT(errno, Eq(EACCES));
374*ec63e07aSXin Li ASSERT_THAT(chmod("foo/bar", 0755), Eq(0));
375*ec63e07aSXin Li
376*ec63e07aSXin Li EXPECT_THAT(fileops::DeleteRecursively("foo"), IsTrue());
377*ec63e07aSXin Li }
378*ec63e07aSXin Li
TEST_F(FileOpsTest,ReadLinkAbsoluteTest)379*ec63e07aSXin Li TEST_F(FileOpsTest, ReadLinkAbsoluteTest) {
380*ec63e07aSXin Li const auto tmp_dir = GetTestTempPath();
381*ec63e07aSXin Li ASSERT_THAT(chdir(tmp_dir.c_str()), Eq(0));
382*ec63e07aSXin Li
383*ec63e07aSXin Li EXPECT_THAT(fileops::DeleteRecursively("foo"), IsTrue());
384*ec63e07aSXin Li ASSERT_THAT(symlink("rel/path", "foo"), Eq(0));
385*ec63e07aSXin Li
386*ec63e07aSXin Li const std::string expected_path = absl::StrCat(tmp_dir, "/rel/path");
387*ec63e07aSXin Li const std::string expected_path2 = absl::StrCat(tmp_dir, "/./rel/path");
388*ec63e07aSXin Li std::string result;
389*ec63e07aSXin Li EXPECT_THAT(fileops::ReadLinkAbsolute("foo", &result), IsTrue());
390*ec63e07aSXin Li EXPECT_THAT(result, StrEq(expected_path));
391*ec63e07aSXin Li EXPECT_THAT(fileops::ReadLinkAbsolute("./foo", &result), IsTrue());
392*ec63e07aSXin Li EXPECT_THAT(result, StrEq(expected_path2));
393*ec63e07aSXin Li EXPECT_THAT(fileops::ReadLinkAbsolute(absl::StrCat(tmp_dir, "/foo"), &result),
394*ec63e07aSXin Li IsTrue());
395*ec63e07aSXin Li EXPECT_THAT(result, StrEq(expected_path));
396*ec63e07aSXin Li
397*ec63e07aSXin Li result.clear();
398*ec63e07aSXin Li EXPECT_THAT(fileops::ReadLinkAbsolute("/not_there", &result), IsFalse());
399*ec63e07aSXin Li EXPECT_THAT(result, IsEmpty());
400*ec63e07aSXin Li }
401*ec63e07aSXin Li
TEST_F(FileOpsTest,CopyFileTest)402*ec63e07aSXin Li TEST_F(FileOpsTest, CopyFileTest) {
403*ec63e07aSXin Li const auto tmp_dir = GetTestTempPath();
404*ec63e07aSXin Li // Non-existent source
405*ec63e07aSXin Li EXPECT_THAT(
406*ec63e07aSXin Li fileops::CopyFile("/not/there", absl::StrCat(tmp_dir, "/out"), 0777),
407*ec63e07aSXin Li IsFalse());
408*ec63e07aSXin Li
409*ec63e07aSXin Li // Unwritable target
410*ec63e07aSXin Li EXPECT_THAT(fileops::CopyFile("/proc/self/exe", tmp_dir, 0777), IsFalse());
411*ec63e07aSXin Li
412*ec63e07aSXin Li EXPECT_THAT(file::SetContents(absl::StrCat(tmp_dir, "/test"), "test\n",
413*ec63e07aSXin Li file::Defaults()),
414*ec63e07aSXin Li IsOk());
415*ec63e07aSXin Li EXPECT_THAT(fileops::CopyFile(absl::StrCat(tmp_dir, "/test"),
416*ec63e07aSXin Li absl::StrCat(tmp_dir, "/test2"), 0666),
417*ec63e07aSXin Li IsTrue());
418*ec63e07aSXin Li
419*ec63e07aSXin Li std::string text;
420*ec63e07aSXin Li EXPECT_THAT(file::GetContents(absl::StrCat(tmp_dir, "/test2"), &text,
421*ec63e07aSXin Li file::Defaults()),
422*ec63e07aSXin Li IsOk());
423*ec63e07aSXin Li
424*ec63e07aSXin Li EXPECT_THAT(text, StrEq("test\n"));
425*ec63e07aSXin Li
426*ec63e07aSXin Li unlink((absl::StrCat(tmp_dir, "/test")).c_str());
427*ec63e07aSXin Li unlink((absl::StrCat(tmp_dir, "/test2")).c_str());
428*ec63e07aSXin Li }
429*ec63e07aSXin Li
430*ec63e07aSXin Li } // namespace
431*ec63e07aSXin Li } // namespace sapi::file_util
432