1*11be35a1SLionel Sambuc // Copyright 2012 Google Inc.
2*11be35a1SLionel Sambuc // All rights reserved.
3*11be35a1SLionel Sambuc //
4*11be35a1SLionel Sambuc // Redistribution and use in source and binary forms, with or without
5*11be35a1SLionel Sambuc // modification, are permitted provided that the following conditions are
6*11be35a1SLionel Sambuc // met:
7*11be35a1SLionel Sambuc //
8*11be35a1SLionel Sambuc // * Redistributions of source code must retain the above copyright
9*11be35a1SLionel Sambuc // notice, this list of conditions and the following disclaimer.
10*11be35a1SLionel Sambuc // * Redistributions in binary form must reproduce the above copyright
11*11be35a1SLionel Sambuc // notice, this list of conditions and the following disclaimer in the
12*11be35a1SLionel Sambuc // documentation and/or other materials provided with the distribution.
13*11be35a1SLionel Sambuc // * Neither the name of Google Inc. nor the names of its contributors
14*11be35a1SLionel Sambuc // may be used to endorse or promote products derived from this software
15*11be35a1SLionel Sambuc // without specific prior written permission.
16*11be35a1SLionel Sambuc //
17*11be35a1SLionel Sambuc // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*11be35a1SLionel Sambuc // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*11be35a1SLionel Sambuc // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*11be35a1SLionel Sambuc // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*11be35a1SLionel Sambuc // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*11be35a1SLionel Sambuc // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*11be35a1SLionel Sambuc // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*11be35a1SLionel Sambuc // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*11be35a1SLionel Sambuc // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*11be35a1SLionel Sambuc // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*11be35a1SLionel Sambuc // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*11be35a1SLionel Sambuc
29*11be35a1SLionel Sambuc #include "fs.h"
30*11be35a1SLionel Sambuc
31*11be35a1SLionel Sambuc #include <sys/stat.h>
32*11be35a1SLionel Sambuc #include <sys/wait.h>
33*11be35a1SLionel Sambuc
34*11be35a1SLionel Sambuc #include <assert.h>
35*11be35a1SLionel Sambuc #include <dirent.h>
36*11be35a1SLionel Sambuc #include <err.h>
37*11be35a1SLionel Sambuc #include <errno.h>
38*11be35a1SLionel Sambuc #include <signal.h>
39*11be35a1SLionel Sambuc #include <stdbool.h>
40*11be35a1SLionel Sambuc #include <stdio.h>
41*11be35a1SLionel Sambuc #include <stdlib.h>
42*11be35a1SLionel Sambuc #include <string.h>
43*11be35a1SLionel Sambuc #include <unistd.h>
44*11be35a1SLionel Sambuc
45*11be35a1SLionel Sambuc #include <atf-c.h>
46*11be35a1SLionel Sambuc
47*11be35a1SLionel Sambuc #include "error.h"
48*11be35a1SLionel Sambuc
49*11be35a1SLionel Sambuc
50*11be35a1SLionel Sambuc static void run_mount_tmpfs(const char*) KYUA_DEFS_NORETURN;
51*11be35a1SLionel Sambuc
52*11be35a1SLionel Sambuc
53*11be35a1SLionel Sambuc /// Operating systems recognized by the code below.
54*11be35a1SLionel Sambuc enum os_type {
55*11be35a1SLionel Sambuc os_unsupported = 0,
56*11be35a1SLionel Sambuc os_freebsd,
57*11be35a1SLionel Sambuc os_linux,
58*11be35a1SLionel Sambuc os_netbsd,
59*11be35a1SLionel Sambuc os_sunos,
60*11be35a1SLionel Sambuc };
61*11be35a1SLionel Sambuc
62*11be35a1SLionel Sambuc
63*11be35a1SLionel Sambuc /// The current operating system.
64*11be35a1SLionel Sambuc static enum os_type current_os =
65*11be35a1SLionel Sambuc #if defined(__FreeBSD__)
66*11be35a1SLionel Sambuc os_freebsd
67*11be35a1SLionel Sambuc #elif defined(__linux__)
68*11be35a1SLionel Sambuc os_linux
69*11be35a1SLionel Sambuc #elif defined(__NetBSD__)
70*11be35a1SLionel Sambuc os_netbsd
71*11be35a1SLionel Sambuc #elif defined(__SunOS__)
72*11be35a1SLionel Sambuc os_sunos
73*11be35a1SLionel Sambuc #else
74*11be35a1SLionel Sambuc os_unsupported
75*11be35a1SLionel Sambuc #endif
76*11be35a1SLionel Sambuc ;
77*11be35a1SLionel Sambuc
78*11be35a1SLionel Sambuc
79*11be35a1SLionel Sambuc /// Checks if a directory entry exists and matches a specific type.
80*11be35a1SLionel Sambuc ///
81*11be35a1SLionel Sambuc /// \param dir The directory in which to look for the entry.
82*11be35a1SLionel Sambuc /// \param name The name of the entry to look up.
83*11be35a1SLionel Sambuc /// \param expected_type The expected type of the file as given by dir(5).
84*11be35a1SLionel Sambuc ///
85*11be35a1SLionel Sambuc /// \return True if the entry exists and matches the given type; false
86*11be35a1SLionel Sambuc /// otherwise.
87*11be35a1SLionel Sambuc static bool
lookup(const char * dir,const char * name,const int expected_type)88*11be35a1SLionel Sambuc lookup(const char* dir, const char* name, const int expected_type)
89*11be35a1SLionel Sambuc {
90*11be35a1SLionel Sambuc DIR* dirp = opendir(dir);
91*11be35a1SLionel Sambuc ATF_REQUIRE(dirp != NULL);
92*11be35a1SLionel Sambuc
93*11be35a1SLionel Sambuc bool found = false;
94*11be35a1SLionel Sambuc struct dirent* dp;
95*11be35a1SLionel Sambuc while (!found && (dp = readdir(dirp)) != NULL) {
96*11be35a1SLionel Sambuc if (strcmp(dp->d_name, name) == 0 &&
97*11be35a1SLionel Sambuc dp->d_type == expected_type) {
98*11be35a1SLionel Sambuc found = true;
99*11be35a1SLionel Sambuc }
100*11be35a1SLionel Sambuc }
101*11be35a1SLionel Sambuc closedir(dirp);
102*11be35a1SLionel Sambuc return found;
103*11be35a1SLionel Sambuc }
104*11be35a1SLionel Sambuc
105*11be35a1SLionel Sambuc
106*11be35a1SLionel Sambuc /// Executes 'mount -t tmpfs' (or a similar variant).
107*11be35a1SLionel Sambuc ///
108*11be35a1SLionel Sambuc /// This function must be called from a subprocess, as it never returns.
109*11be35a1SLionel Sambuc ///
110*11be35a1SLionel Sambuc /// \param mount_point Location on which to mount a tmpfs.
111*11be35a1SLionel Sambuc static void
run_mount_tmpfs(const char * mount_point)112*11be35a1SLionel Sambuc run_mount_tmpfs(const char* mount_point)
113*11be35a1SLionel Sambuc {
114*11be35a1SLionel Sambuc const char* mount_args[16];
115*11be35a1SLionel Sambuc
116*11be35a1SLionel Sambuc size_t last = 0;
117*11be35a1SLionel Sambuc switch (current_os) {
118*11be35a1SLionel Sambuc case os_freebsd:
119*11be35a1SLionel Sambuc mount_args[last++] = "mdmfs";
120*11be35a1SLionel Sambuc mount_args[last++] = "-s16m";
121*11be35a1SLionel Sambuc mount_args[last++] = "md";
122*11be35a1SLionel Sambuc mount_args[last++] = mount_point;
123*11be35a1SLionel Sambuc break;
124*11be35a1SLionel Sambuc
125*11be35a1SLionel Sambuc case os_linux:
126*11be35a1SLionel Sambuc mount_args[last++] = "mount";
127*11be35a1SLionel Sambuc mount_args[last++] = "-ttmpfs";
128*11be35a1SLionel Sambuc mount_args[last++] = "tmpfs";
129*11be35a1SLionel Sambuc mount_args[last++] = mount_point;
130*11be35a1SLionel Sambuc break;
131*11be35a1SLionel Sambuc
132*11be35a1SLionel Sambuc case os_netbsd:
133*11be35a1SLionel Sambuc mount_args[last++] = "mount";
134*11be35a1SLionel Sambuc mount_args[last++] = "-ttmpfs";
135*11be35a1SLionel Sambuc mount_args[last++] = "tmpfs";
136*11be35a1SLionel Sambuc mount_args[last++] = mount_point;
137*11be35a1SLionel Sambuc break;
138*11be35a1SLionel Sambuc
139*11be35a1SLionel Sambuc case os_sunos:
140*11be35a1SLionel Sambuc mount_args[last++] = "mount";
141*11be35a1SLionel Sambuc mount_args[last++] = "-Ftmpfs";
142*11be35a1SLionel Sambuc mount_args[last++] = "tmpfs";
143*11be35a1SLionel Sambuc mount_args[last++] = mount_point;
144*11be35a1SLionel Sambuc break;
145*11be35a1SLionel Sambuc
146*11be35a1SLionel Sambuc default:
147*11be35a1SLionel Sambuc err(123, "Don't know how to mount a file system for testing "
148*11be35a1SLionel Sambuc "purposes");
149*11be35a1SLionel Sambuc }
150*11be35a1SLionel Sambuc mount_args[last] = NULL;
151*11be35a1SLionel Sambuc
152*11be35a1SLionel Sambuc const char** arg;
153*11be35a1SLionel Sambuc printf("Mounting tmpfs onto %s with:", mount_point);
154*11be35a1SLionel Sambuc for (arg = &mount_args[0]; *arg != NULL; arg++)
155*11be35a1SLionel Sambuc printf(" %s", *arg);
156*11be35a1SLionel Sambuc printf("\n");
157*11be35a1SLionel Sambuc
158*11be35a1SLionel Sambuc const int ret = execvp(mount_args[0], KYUA_DEFS_UNCONST(mount_args));
159*11be35a1SLionel Sambuc assert(ret == -1);
160*11be35a1SLionel Sambuc err(EXIT_FAILURE, "Failed to exec %s", mount_args[0]);
161*11be35a1SLionel Sambuc };
162*11be35a1SLionel Sambuc
163*11be35a1SLionel Sambuc
164*11be35a1SLionel Sambuc /// Mounts a temporary file system.
165*11be35a1SLionel Sambuc ///
166*11be35a1SLionel Sambuc /// This is only provided for testing purposes. The mounted file system
167*11be35a1SLionel Sambuc /// contains no valuable data.
168*11be35a1SLionel Sambuc ///
169*11be35a1SLionel Sambuc /// Note that the calling test case is skipped if the current operating system
170*11be35a1SLionel Sambuc /// is not supported.
171*11be35a1SLionel Sambuc ///
172*11be35a1SLionel Sambuc /// \param mount_point The path on which the file system will be mounted.
173*11be35a1SLionel Sambuc static void
mount_tmpfs(const char * mount_point)174*11be35a1SLionel Sambuc mount_tmpfs(const char* mount_point)
175*11be35a1SLionel Sambuc {
176*11be35a1SLionel Sambuc // SunOS's mount(8) requires paths to be absolute. To err on the side of
177*11be35a1SLionel Sambuc // caution, let's make it absolute in all cases.
178*11be35a1SLionel Sambuc //const fspath abs_mount_point = mount_point.is_absolute() ?
179*11be35a1SLionel Sambuc // mount_point : mount_point.to_absolute();
180*11be35a1SLionel Sambuc
181*11be35a1SLionel Sambuc pid_t pid = fork();
182*11be35a1SLionel Sambuc ATF_REQUIRE(pid != -1);
183*11be35a1SLionel Sambuc if (pid == 0)
184*11be35a1SLionel Sambuc run_mount_tmpfs(mount_point);
185*11be35a1SLionel Sambuc int status;
186*11be35a1SLionel Sambuc ATF_REQUIRE(waitpid(pid, &status, 0) != -1);
187*11be35a1SLionel Sambuc ATF_REQUIRE(WIFEXITED(status));
188*11be35a1SLionel Sambuc if (WEXITSTATUS(status) == 123)
189*11be35a1SLionel Sambuc atf_tc_skip("Don't know how to mount a file system for testing "
190*11be35a1SLionel Sambuc "purposes");
191*11be35a1SLionel Sambuc else
192*11be35a1SLionel Sambuc ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
193*11be35a1SLionel Sambuc }
194*11be35a1SLionel Sambuc
195*11be35a1SLionel Sambuc
196*11be35a1SLionel Sambuc static bool
lchmod_fails(void)197*11be35a1SLionel Sambuc lchmod_fails(void)
198*11be35a1SLionel Sambuc {
199*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("test", 0755) != -1);
200*11be35a1SLionel Sambuc return lchmod("test", 0700) == -1 && chmod("test", 0700) != -1;
201*11be35a1SLionel Sambuc }
202*11be35a1SLionel Sambuc
203*11be35a1SLionel Sambuc
204*11be35a1SLionel Sambuc ATF_TC_WITHOUT_HEAD(cleanup__file);
ATF_TC_BODY(cleanup__file,tc)205*11be35a1SLionel Sambuc ATF_TC_BODY(cleanup__file, tc)
206*11be35a1SLionel Sambuc {
207*11be35a1SLionel Sambuc atf_utils_create_file("root", "%s", "");
208*11be35a1SLionel Sambuc ATF_REQUIRE(lookup(".", "root", DT_REG));
209*11be35a1SLionel Sambuc ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root")));
210*11be35a1SLionel Sambuc ATF_REQUIRE(!lookup(".", "root", DT_REG));
211*11be35a1SLionel Sambuc }
212*11be35a1SLionel Sambuc
213*11be35a1SLionel Sambuc
214*11be35a1SLionel Sambuc ATF_TC_WITHOUT_HEAD(cleanup__subdir__empty);
ATF_TC_BODY(cleanup__subdir__empty,tc)215*11be35a1SLionel Sambuc ATF_TC_BODY(cleanup__subdir__empty, tc)
216*11be35a1SLionel Sambuc {
217*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root", 0755) != -1);
218*11be35a1SLionel Sambuc ATF_REQUIRE(lookup(".", "root", DT_DIR));
219*11be35a1SLionel Sambuc ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root")));
220*11be35a1SLionel Sambuc ATF_REQUIRE(!lookup(".", "root", DT_DIR));
221*11be35a1SLionel Sambuc }
222*11be35a1SLionel Sambuc
223*11be35a1SLionel Sambuc
224*11be35a1SLionel Sambuc ATF_TC_WITHOUT_HEAD(cleanup__subdir__files_and_directories);
ATF_TC_BODY(cleanup__subdir__files_and_directories,tc)225*11be35a1SLionel Sambuc ATF_TC_BODY(cleanup__subdir__files_and_directories, tc)
226*11be35a1SLionel Sambuc {
227*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root", 0755) != -1);
228*11be35a1SLionel Sambuc atf_utils_create_file("root/.hidden_file", "%s", "");
229*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root/.hidden_dir", 0755) != -1);
230*11be35a1SLionel Sambuc atf_utils_create_file("root/.hidden_dir/a", "%s", "");
231*11be35a1SLionel Sambuc atf_utils_create_file("root/file", "%s", "");
232*11be35a1SLionel Sambuc atf_utils_create_file("root/with spaces", "%s", "");
233*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root/dir1", 0755) != -1);
234*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root/dir1/dir2", 0755) != -1);
235*11be35a1SLionel Sambuc atf_utils_create_file("root/dir1/dir2/file", "%s", "");
236*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root/dir1/dir3", 0755) != -1);
237*11be35a1SLionel Sambuc ATF_REQUIRE(lookup(".", "root", DT_DIR));
238*11be35a1SLionel Sambuc ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root")));
239*11be35a1SLionel Sambuc ATF_REQUIRE(!lookup(".", "root", DT_DIR));
240*11be35a1SLionel Sambuc }
241*11be35a1SLionel Sambuc
242*11be35a1SLionel Sambuc
243*11be35a1SLionel Sambuc ATF_TC_WITHOUT_HEAD(cleanup__subdir__unprotect_regular);
ATF_TC_BODY(cleanup__subdir__unprotect_regular,tc)244*11be35a1SLionel Sambuc ATF_TC_BODY(cleanup__subdir__unprotect_regular, tc)
245*11be35a1SLionel Sambuc {
246*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root", 0755) != -1);
247*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root/dir1", 0755) != -1);
248*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root/dir1/dir2", 0755) != -1);
249*11be35a1SLionel Sambuc atf_utils_create_file("root/dir1/dir2/file", "%s", "");
250*11be35a1SLionel Sambuc ATF_REQUIRE(chmod("root/dir1/dir2/file", 0000) != -1);
251*11be35a1SLionel Sambuc ATF_REQUIRE(chmod("root/dir1/dir2", 0000) != -1);
252*11be35a1SLionel Sambuc ATF_REQUIRE(chmod("root/dir1", 0000) != -1);
253*11be35a1SLionel Sambuc ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root")));
254*11be35a1SLionel Sambuc ATF_REQUIRE(!lookup(".", "root", DT_DIR));
255*11be35a1SLionel Sambuc }
256*11be35a1SLionel Sambuc
257*11be35a1SLionel Sambuc
258*11be35a1SLionel Sambuc ATF_TC(cleanup__subdir__unprotect_symlink);
ATF_TC_HEAD(cleanup__subdir__unprotect_symlink,tc)259*11be35a1SLionel Sambuc ATF_TC_HEAD(cleanup__subdir__unprotect_symlink, tc)
260*11be35a1SLionel Sambuc {
261*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "require.progs", "/bin/ls");
262*11be35a1SLionel Sambuc // We are ensuring that chmod is not run on the target of a symlink, so
263*11be35a1SLionel Sambuc // we cannot be root (nor we don't want to, to prevent unprotecting a
264*11be35a1SLionel Sambuc // system file!).
265*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "require.user", "unprivileged");
266*11be35a1SLionel Sambuc }
ATF_TC_BODY(cleanup__subdir__unprotect_symlink,tc)267*11be35a1SLionel Sambuc ATF_TC_BODY(cleanup__subdir__unprotect_symlink, tc)
268*11be35a1SLionel Sambuc {
269*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root", 0755) != -1);
270*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root/dir1", 0755) != -1);
271*11be35a1SLionel Sambuc ATF_REQUIRE(symlink("/bin/ls", "root/dir1/ls") != -1);
272*11be35a1SLionel Sambuc ATF_REQUIRE(chmod("root/dir1", 0555) != -1);
273*11be35a1SLionel Sambuc ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root")));
274*11be35a1SLionel Sambuc ATF_REQUIRE(!lookup(".", "root", DT_DIR));
275*11be35a1SLionel Sambuc }
276*11be35a1SLionel Sambuc
277*11be35a1SLionel Sambuc
278*11be35a1SLionel Sambuc ATF_TC_WITHOUT_HEAD(cleanup__subdir__links);
ATF_TC_BODY(cleanup__subdir__links,tc)279*11be35a1SLionel Sambuc ATF_TC_BODY(cleanup__subdir__links, tc)
280*11be35a1SLionel Sambuc {
281*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root", 0755) != -1);
282*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root/dir1", 0755) != -1);
283*11be35a1SLionel Sambuc ATF_REQUIRE(symlink("../../root", "root/dir1/loop") != -1);
284*11be35a1SLionel Sambuc ATF_REQUIRE(symlink("non-existent", "root/missing") != -1);
285*11be35a1SLionel Sambuc ATF_REQUIRE(lookup(".", "root", DT_DIR));
286*11be35a1SLionel Sambuc kyua_error_t error = kyua_fs_cleanup("root");
287*11be35a1SLionel Sambuc if (kyua_error_is_set(error)) {
288*11be35a1SLionel Sambuc if (lchmod_fails())
289*11be35a1SLionel Sambuc atf_tc_expect_fail("lchmod(2) is not implemented in your system");
290*11be35a1SLionel Sambuc kyua_error_free(error);
291*11be35a1SLionel Sambuc atf_tc_fail("kyua_fs_cleanup returned an error");
292*11be35a1SLionel Sambuc }
293*11be35a1SLionel Sambuc ATF_REQUIRE(!lookup(".", "root", DT_DIR));
294*11be35a1SLionel Sambuc }
295*11be35a1SLionel Sambuc
296*11be35a1SLionel Sambuc
297*11be35a1SLionel Sambuc ATF_TC(cleanup__mount_point__simple);
ATF_TC_HEAD(cleanup__mount_point__simple,tc)298*11be35a1SLionel Sambuc ATF_TC_HEAD(cleanup__mount_point__simple, tc)
299*11be35a1SLionel Sambuc {
300*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "require.user", "root");
301*11be35a1SLionel Sambuc }
ATF_TC_BODY(cleanup__mount_point__simple,tc)302*11be35a1SLionel Sambuc ATF_TC_BODY(cleanup__mount_point__simple, tc)
303*11be35a1SLionel Sambuc {
304*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root", 0755) != -1);
305*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root/dir1", 0755) != -1);
306*11be35a1SLionel Sambuc atf_utils_create_file("root/zz", "%s", "");
307*11be35a1SLionel Sambuc mount_tmpfs("root/dir1");
308*11be35a1SLionel Sambuc ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root")));
309*11be35a1SLionel Sambuc ATF_REQUIRE(!lookup(".", "root", DT_DIR));
310*11be35a1SLionel Sambuc }
311*11be35a1SLionel Sambuc
312*11be35a1SLionel Sambuc
313*11be35a1SLionel Sambuc ATF_TC(cleanup__mount_point__overlayed);
ATF_TC_HEAD(cleanup__mount_point__overlayed,tc)314*11be35a1SLionel Sambuc ATF_TC_HEAD(cleanup__mount_point__overlayed, tc)
315*11be35a1SLionel Sambuc {
316*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "require.user", "root");
317*11be35a1SLionel Sambuc }
ATF_TC_BODY(cleanup__mount_point__overlayed,tc)318*11be35a1SLionel Sambuc ATF_TC_BODY(cleanup__mount_point__overlayed, tc)
319*11be35a1SLionel Sambuc {
320*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root", 0755) != -1);
321*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root/dir1", 0755) != -1);
322*11be35a1SLionel Sambuc atf_utils_create_file("root/zz", "%s", "");
323*11be35a1SLionel Sambuc mount_tmpfs("root/dir1");
324*11be35a1SLionel Sambuc mount_tmpfs("root/dir1");
325*11be35a1SLionel Sambuc ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root")));
326*11be35a1SLionel Sambuc ATF_REQUIRE(!lookup(".", "root", DT_DIR));
327*11be35a1SLionel Sambuc }
328*11be35a1SLionel Sambuc
329*11be35a1SLionel Sambuc
330*11be35a1SLionel Sambuc ATF_TC(cleanup__mount_point__nested);
ATF_TC_HEAD(cleanup__mount_point__nested,tc)331*11be35a1SLionel Sambuc ATF_TC_HEAD(cleanup__mount_point__nested, tc)
332*11be35a1SLionel Sambuc {
333*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "require.user", "root");
334*11be35a1SLionel Sambuc }
ATF_TC_BODY(cleanup__mount_point__nested,tc)335*11be35a1SLionel Sambuc ATF_TC_BODY(cleanup__mount_point__nested, tc)
336*11be35a1SLionel Sambuc {
337*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root", 0755) != -1);
338*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root/dir1", 0755) != -1);
339*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root/dir1/dir2", 0755) != -1);
340*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root/dir3", 0755) != -1);
341*11be35a1SLionel Sambuc mount_tmpfs("root/dir1/dir2");
342*11be35a1SLionel Sambuc mount_tmpfs("root/dir3");
343*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root/dir1/dir2/dir4", 0755) != -1);
344*11be35a1SLionel Sambuc mount_tmpfs("root/dir1/dir2/dir4");
345*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root/dir1/dir2/not-mount-point", 0755) != -1);
346*11be35a1SLionel Sambuc ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root")));
347*11be35a1SLionel Sambuc ATF_REQUIRE(!lookup(".", "root", DT_DIR));
348*11be35a1SLionel Sambuc }
349*11be35a1SLionel Sambuc
350*11be35a1SLionel Sambuc
351*11be35a1SLionel Sambuc ATF_TC(cleanup__mount_point__links);
ATF_TC_HEAD(cleanup__mount_point__links,tc)352*11be35a1SLionel Sambuc ATF_TC_HEAD(cleanup__mount_point__links, tc)
353*11be35a1SLionel Sambuc {
354*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "require.user", "root");
355*11be35a1SLionel Sambuc }
ATF_TC_BODY(cleanup__mount_point__links,tc)356*11be35a1SLionel Sambuc ATF_TC_BODY(cleanup__mount_point__links, tc)
357*11be35a1SLionel Sambuc {
358*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root", 0755) != -1);
359*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root/dir1", 0755) != -1);
360*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root/dir3", 0755) != -1);
361*11be35a1SLionel Sambuc mount_tmpfs("root/dir1");
362*11be35a1SLionel Sambuc ATF_REQUIRE(symlink("../dir3", "root/dir1/link") != -1);
363*11be35a1SLionel Sambuc ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root")));
364*11be35a1SLionel Sambuc ATF_REQUIRE(!lookup(".", "root", DT_DIR));
365*11be35a1SLionel Sambuc }
366*11be35a1SLionel Sambuc
367*11be35a1SLionel Sambuc
368*11be35a1SLionel Sambuc ATF_TC(cleanup__mount_point__busy);
ATF_TC_HEAD(cleanup__mount_point__busy,tc)369*11be35a1SLionel Sambuc ATF_TC_HEAD(cleanup__mount_point__busy, tc)
370*11be35a1SLionel Sambuc {
371*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "require.user", "root");
372*11be35a1SLionel Sambuc }
ATF_TC_BODY(cleanup__mount_point__busy,tc)373*11be35a1SLionel Sambuc ATF_TC_BODY(cleanup__mount_point__busy, tc)
374*11be35a1SLionel Sambuc {
375*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root", 0755) != -1);
376*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root/dir1", 0755) != -1);
377*11be35a1SLionel Sambuc mount_tmpfs("root/dir1");
378*11be35a1SLionel Sambuc
379*11be35a1SLionel Sambuc pid_t pid = fork();
380*11be35a1SLionel Sambuc ATF_REQUIRE(pid != -1);
381*11be35a1SLionel Sambuc if (pid == 0) {
382*11be35a1SLionel Sambuc if (chdir("root/dir1") == -1)
383*11be35a1SLionel Sambuc abort();
384*11be35a1SLionel Sambuc
385*11be35a1SLionel Sambuc atf_utils_create_file("dont-delete-me", "%s", "");
386*11be35a1SLionel Sambuc atf_utils_create_file("../../done", "%s", "");
387*11be35a1SLionel Sambuc
388*11be35a1SLionel Sambuc pause();
389*11be35a1SLionel Sambuc exit(EXIT_SUCCESS);
390*11be35a1SLionel Sambuc } else {
391*11be35a1SLionel Sambuc fprintf(stderr, "Waiting for child to finish preparations\n");
392*11be35a1SLionel Sambuc while (!atf_utils_file_exists("done")) {}
393*11be35a1SLionel Sambuc fprintf(stderr, "Child done; cleaning up\n");
394*11be35a1SLionel Sambuc
395*11be35a1SLionel Sambuc ATF_REQUIRE(kyua_error_is_set(kyua_fs_cleanup("root")));
396*11be35a1SLionel Sambuc ATF_REQUIRE(atf_utils_file_exists("root/dir1/dont-delete-me"));
397*11be35a1SLionel Sambuc
398*11be35a1SLionel Sambuc fprintf(stderr, "Killing child\n");
399*11be35a1SLionel Sambuc ATF_REQUIRE(kill(pid, SIGKILL) != -1);
400*11be35a1SLionel Sambuc int status;
401*11be35a1SLionel Sambuc ATF_REQUIRE(waitpid(pid, &status, 0) != -1);
402*11be35a1SLionel Sambuc
403*11be35a1SLionel Sambuc ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root")));
404*11be35a1SLionel Sambuc ATF_REQUIRE(!lookup(".", "root", DT_DIR));
405*11be35a1SLionel Sambuc }
406*11be35a1SLionel Sambuc }
407*11be35a1SLionel Sambuc
408*11be35a1SLionel Sambuc
409*11be35a1SLionel Sambuc ATF_TC_WITHOUT_HEAD(concat__one);
ATF_TC_BODY(concat__one,tc)410*11be35a1SLionel Sambuc ATF_TC_BODY(concat__one, tc)
411*11be35a1SLionel Sambuc {
412*11be35a1SLionel Sambuc char* path;
413*11be35a1SLionel Sambuc ATF_REQUIRE(!kyua_error_is_set(kyua_fs_concat(&path, "foo", NULL)));
414*11be35a1SLionel Sambuc ATF_REQUIRE_STREQ("foo", path);
415*11be35a1SLionel Sambuc free(path);
416*11be35a1SLionel Sambuc }
417*11be35a1SLionel Sambuc
418*11be35a1SLionel Sambuc
419*11be35a1SLionel Sambuc ATF_TC_WITHOUT_HEAD(concat__two);
ATF_TC_BODY(concat__two,tc)420*11be35a1SLionel Sambuc ATF_TC_BODY(concat__two, tc)
421*11be35a1SLionel Sambuc {
422*11be35a1SLionel Sambuc char* path;
423*11be35a1SLionel Sambuc ATF_REQUIRE(!kyua_error_is_set(kyua_fs_concat(&path, "foo", "bar", NULL)));
424*11be35a1SLionel Sambuc ATF_REQUIRE_STREQ("foo/bar", path);
425*11be35a1SLionel Sambuc free(path);
426*11be35a1SLionel Sambuc }
427*11be35a1SLionel Sambuc
428*11be35a1SLionel Sambuc
429*11be35a1SLionel Sambuc ATF_TC_WITHOUT_HEAD(concat__several);
ATF_TC_BODY(concat__several,tc)430*11be35a1SLionel Sambuc ATF_TC_BODY(concat__several, tc)
431*11be35a1SLionel Sambuc {
432*11be35a1SLionel Sambuc char* path;
433*11be35a1SLionel Sambuc ATF_REQUIRE(!kyua_error_is_set(kyua_fs_concat(&path, "/usr", ".", "bin",
434*11be35a1SLionel Sambuc "ls", NULL)));
435*11be35a1SLionel Sambuc ATF_REQUIRE_STREQ("/usr/./bin/ls", path);
436*11be35a1SLionel Sambuc free(path);
437*11be35a1SLionel Sambuc }
438*11be35a1SLionel Sambuc
439*11be35a1SLionel Sambuc
440*11be35a1SLionel Sambuc ATF_TC_WITHOUT_HEAD(current_path__ok);
ATF_TC_BODY(current_path__ok,tc)441*11be35a1SLionel Sambuc ATF_TC_BODY(current_path__ok, tc)
442*11be35a1SLionel Sambuc {
443*11be35a1SLionel Sambuc char* previous;
444*11be35a1SLionel Sambuc ATF_REQUIRE(!kyua_error_is_set(kyua_fs_current_path(&previous)));
445*11be35a1SLionel Sambuc
446*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root", 0755) != -1);
447*11be35a1SLionel Sambuc ATF_REQUIRE(chdir("root") != -1);
448*11be35a1SLionel Sambuc char* cwd;
449*11be35a1SLionel Sambuc ATF_REQUIRE(!kyua_error_is_set(kyua_fs_current_path(&cwd)));
450*11be35a1SLionel Sambuc
451*11be35a1SLionel Sambuc char* exp_cwd;
452*11be35a1SLionel Sambuc ATF_REQUIRE(!kyua_error_is_set(kyua_fs_concat(&exp_cwd, previous, "root",
453*11be35a1SLionel Sambuc NULL)));
454*11be35a1SLionel Sambuc ATF_REQUIRE_STREQ(exp_cwd, cwd);
455*11be35a1SLionel Sambuc
456*11be35a1SLionel Sambuc free(exp_cwd);
457*11be35a1SLionel Sambuc free(cwd);
458*11be35a1SLionel Sambuc free(previous);
459*11be35a1SLionel Sambuc }
460*11be35a1SLionel Sambuc
461*11be35a1SLionel Sambuc
462*11be35a1SLionel Sambuc ATF_TC_WITHOUT_HEAD(current_path__enoent);
ATF_TC_BODY(current_path__enoent,tc)463*11be35a1SLionel Sambuc ATF_TC_BODY(current_path__enoent, tc)
464*11be35a1SLionel Sambuc {
465*11be35a1SLionel Sambuc char* previous;
466*11be35a1SLionel Sambuc ATF_REQUIRE(!kyua_error_is_set(kyua_fs_current_path(&previous)));
467*11be35a1SLionel Sambuc
468*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("root", 0755) != -1);
469*11be35a1SLionel Sambuc ATF_REQUIRE(chdir("root") != -1);
470*11be35a1SLionel Sambuc ATF_REQUIRE(rmdir("../root") != -1);
471*11be35a1SLionel Sambuc char* cwd = (char*)0xdeadbeef;
472*11be35a1SLionel Sambuc kyua_error_t error = kyua_fs_current_path(&cwd);
473*11be35a1SLionel Sambuc ATF_REQUIRE(kyua_error_is_set(error));
474*11be35a1SLionel Sambuc ATF_REQUIRE(kyua_error_is_type(error, "libc"));
475*11be35a1SLionel Sambuc ATF_REQUIRE_EQ(ENOENT, kyua_libc_error_errno(error));
476*11be35a1SLionel Sambuc ATF_REQUIRE_EQ((char*)0xdeadbeef, cwd);
477*11be35a1SLionel Sambuc kyua_error_free(error);
478*11be35a1SLionel Sambuc
479*11be35a1SLionel Sambuc free(previous);
480*11be35a1SLionel Sambuc }
481*11be35a1SLionel Sambuc
482*11be35a1SLionel Sambuc
483*11be35a1SLionel Sambuc ATF_TC_WITHOUT_HEAD(make_absolute__absolute);
ATF_TC_BODY(make_absolute__absolute,tc)484*11be35a1SLionel Sambuc ATF_TC_BODY(make_absolute__absolute, tc)
485*11be35a1SLionel Sambuc {
486*11be35a1SLionel Sambuc char* absolute;
487*11be35a1SLionel Sambuc ATF_REQUIRE(!kyua_error_is_set(kyua_fs_make_absolute(
488*11be35a1SLionel Sambuc "/this/is/absolute", &absolute)));
489*11be35a1SLionel Sambuc ATF_REQUIRE_STREQ("/this/is/absolute", absolute);
490*11be35a1SLionel Sambuc free(absolute);
491*11be35a1SLionel Sambuc }
492*11be35a1SLionel Sambuc
493*11be35a1SLionel Sambuc
494*11be35a1SLionel Sambuc ATF_TC_WITHOUT_HEAD(make_absolute__relative);
ATF_TC_BODY(make_absolute__relative,tc)495*11be35a1SLionel Sambuc ATF_TC_BODY(make_absolute__relative, tc)
496*11be35a1SLionel Sambuc {
497*11be35a1SLionel Sambuc kyua_error_t error;
498*11be35a1SLionel Sambuc char* absolute;
499*11be35a1SLionel Sambuc
500*11be35a1SLionel Sambuc DIR* previous = opendir(".");
501*11be35a1SLionel Sambuc ATF_REQUIRE(previous != NULL);
502*11be35a1SLionel Sambuc ATF_REQUIRE(chdir("/usr") != -1);
503*11be35a1SLionel Sambuc error = kyua_fs_make_absolute("bin/foobar", &absolute);
504*11be35a1SLionel Sambuc const int previous_fd = dirfd(previous);
505*11be35a1SLionel Sambuc ATF_REQUIRE(fchdir(previous_fd) != -1);
506*11be35a1SLionel Sambuc close(previous_fd);
507*11be35a1SLionel Sambuc
508*11be35a1SLionel Sambuc ATF_REQUIRE(!kyua_error_is_set(error));
509*11be35a1SLionel Sambuc ATF_REQUIRE_STREQ("/usr/bin/foobar", absolute);
510*11be35a1SLionel Sambuc free(absolute);
511*11be35a1SLionel Sambuc }
512*11be35a1SLionel Sambuc
513*11be35a1SLionel Sambuc
514*11be35a1SLionel Sambuc ATF_TC(unmount__ok);
ATF_TC_HEAD(unmount__ok,tc)515*11be35a1SLionel Sambuc ATF_TC_HEAD(unmount__ok, tc)
516*11be35a1SLionel Sambuc {
517*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "require.user", "root");
518*11be35a1SLionel Sambuc }
ATF_TC_BODY(unmount__ok,tc)519*11be35a1SLionel Sambuc ATF_TC_BODY(unmount__ok, tc)
520*11be35a1SLionel Sambuc {
521*11be35a1SLionel Sambuc ATF_REQUIRE(mkdir("mount_point", 0755) != -1);
522*11be35a1SLionel Sambuc
523*11be35a1SLionel Sambuc atf_utils_create_file("mount_point/test1", "%s", "");
524*11be35a1SLionel Sambuc mount_tmpfs("mount_point");
525*11be35a1SLionel Sambuc atf_utils_create_file("mount_point/test2", "%s", "");
526*11be35a1SLionel Sambuc
527*11be35a1SLionel Sambuc ATF_REQUIRE(!atf_utils_file_exists("mount_point/test1"));
528*11be35a1SLionel Sambuc ATF_REQUIRE( atf_utils_file_exists("mount_point/test2"));
529*11be35a1SLionel Sambuc kyua_fs_unmount("mount_point");
530*11be35a1SLionel Sambuc ATF_REQUIRE( atf_utils_file_exists("mount_point/test1"));
531*11be35a1SLionel Sambuc ATF_REQUIRE(!atf_utils_file_exists("mount_point/test2"));
532*11be35a1SLionel Sambuc }
533*11be35a1SLionel Sambuc
534*11be35a1SLionel Sambuc
535*11be35a1SLionel Sambuc ATF_TC(unmount__fail);
ATF_TC_HEAD(unmount__fail,tc)536*11be35a1SLionel Sambuc ATF_TC_HEAD(unmount__fail, tc)
537*11be35a1SLionel Sambuc {
538*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "require.user", "root");
539*11be35a1SLionel Sambuc }
ATF_TC_BODY(unmount__fail,tc)540*11be35a1SLionel Sambuc ATF_TC_BODY(unmount__fail, tc)
541*11be35a1SLionel Sambuc {
542*11be35a1SLionel Sambuc kyua_error_t error = kyua_fs_unmount("mount_point");
543*11be35a1SLionel Sambuc ATF_REQUIRE(kyua_error_is_set(error));
544*11be35a1SLionel Sambuc kyua_error_free(error);
545*11be35a1SLionel Sambuc }
546*11be35a1SLionel Sambuc
547*11be35a1SLionel Sambuc
ATF_TP_ADD_TCS(tp)548*11be35a1SLionel Sambuc ATF_TP_ADD_TCS(tp)
549*11be35a1SLionel Sambuc {
550*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, cleanup__file);
551*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, cleanup__subdir__empty);
552*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, cleanup__subdir__files_and_directories);
553*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, cleanup__subdir__unprotect_regular);
554*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, cleanup__subdir__unprotect_symlink);
555*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, cleanup__subdir__links);
556*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, cleanup__mount_point__simple);
557*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, cleanup__mount_point__overlayed);
558*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, cleanup__mount_point__nested);
559*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, cleanup__mount_point__links);
560*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, cleanup__mount_point__busy);
561*11be35a1SLionel Sambuc
562*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, concat__one);
563*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, concat__two);
564*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, concat__several);
565*11be35a1SLionel Sambuc
566*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, current_path__ok);
567*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, current_path__enoent);
568*11be35a1SLionel Sambuc
569*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, make_absolute__absolute);
570*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, make_absolute__relative);
571*11be35a1SLionel Sambuc
572*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, unmount__ok);
573*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, unmount__fail);
574*11be35a1SLionel Sambuc
575*11be35a1SLionel Sambuc return atf_no_error();
576*11be35a1SLionel Sambuc }
577