1*433d6423SLionel Sambuc /* This tests the behavior of Minix when the current working dir (cwd) doesn't
2*433d6423SLionel Sambuc * actually exist and we either:
3*433d6423SLionel Sambuc * - create a new file
4*433d6423SLionel Sambuc * - make a new directory
5*433d6423SLionel Sambuc * - make a special file (mknod)
6*433d6423SLionel Sambuc * - create a hard link
7*433d6423SLionel Sambuc * - create a symbolic link, or
8*433d6423SLionel Sambuc * - rename a file
9*433d6423SLionel Sambuc * In each case, `a component of the path does not name an existing file', and
10*433d6423SLionel Sambuc * the operation should fail with ENOENT. These tests should actually be
11*433d6423SLionel Sambuc * distributed over the other tests that actually test the specific system
12*433d6423SLionel Sambuc * calls.
13*433d6423SLionel Sambuc */
14*433d6423SLionel Sambuc
15*433d6423SLionel Sambuc #include <stdio.h>
16*433d6423SLionel Sambuc #include <errno.h>
17*433d6423SLionel Sambuc #include <fcntl.h>
18*433d6423SLionel Sambuc #include <unistd.h>
19*433d6423SLionel Sambuc #include <sys/socket.h>
20*433d6423SLionel Sambuc #include <sys/types.h>
21*433d6423SLionel Sambuc #include <sys/wait.h>
22*433d6423SLionel Sambuc #include <sys/stat.h>
23*433d6423SLionel Sambuc #include <sys/syslimits.h>
24*433d6423SLionel Sambuc
25*433d6423SLionel Sambuc int subtest = -1;
26*433d6423SLionel Sambuc int max_error = 999; /* Effectively no limit. This is necessary as this
27*433d6423SLionel Sambuc * test tries to undo errors and should therefore not
28*433d6423SLionel Sambuc * preemptively exit, as that would leave the FS
29*433d6423SLionel Sambuc * in a corrupted state. */
30*433d6423SLionel Sambuc
31*433d6423SLionel Sambuc #include "common.h"
32*433d6423SLionel Sambuc
33*433d6423SLionel Sambuc #define TEST_PATH "a/b/c"
34*433d6423SLionel Sambuc #define INTEGR_MSG "You might want to check fs integrity\n"
35*433d6423SLionel Sambuc
36*433d6423SLionel Sambuc void do_test(void);
37*433d6423SLionel Sambuc
do_test(void)38*433d6423SLionel Sambuc void do_test(void)
39*433d6423SLionel Sambuc {
40*433d6423SLionel Sambuc int r, fd;
41*433d6423SLionel Sambuc int s[2];
42*433d6423SLionel Sambuc char buf[1], testroot[PATH_MAX+1], renamebuf[PATH_MAX+1];
43*433d6423SLionel Sambuc
44*433d6423SLionel Sambuc subtest = 1;
45*433d6423SLionel Sambuc if (socketpair(PF_UNIX, SOCK_STREAM, 0, s) == -1) e(1);
46*433d6423SLionel Sambuc if (system("mkdir -p " TEST_PATH) == -1) e(2);
47*433d6423SLionel Sambuc if (realpath(".", testroot) == NULL) e(3);
48*433d6423SLionel Sambuc
49*433d6423SLionel Sambuc r = fork();
50*433d6423SLionel Sambuc if (r == -1) e(4);
51*433d6423SLionel Sambuc else if (r == 0) { /* Child */
52*433d6423SLionel Sambuc /* Change child's cwd to TEST_PATH */
53*433d6423SLionel Sambuc if (chdir(TEST_PATH) == -1) e(5);
54*433d6423SLionel Sambuc
55*433d6423SLionel Sambuc /* Signal parent we're ready for the test */
56*433d6423SLionel Sambuc buf[0] = 'a';
57*433d6423SLionel Sambuc if (write(s[0], buf, sizeof(buf)) != sizeof(buf)) e(6);
58*433d6423SLionel Sambuc
59*433d6423SLionel Sambuc /* Wait for parent to remove my cwd */
60*433d6423SLionel Sambuc if (read(s[0], buf, sizeof(buf)) != sizeof(buf)) e(7);
61*433d6423SLionel Sambuc
62*433d6423SLionel Sambuc /* Try to create a file */
63*433d6423SLionel Sambuc if ((fd = open("testfile", O_RDWR | O_CREAT)) != -1) {
64*433d6423SLionel Sambuc e(8);
65*433d6423SLionel Sambuc /* Uh oh. We created a file?! Try to remove it. */
66*433d6423SLionel Sambuc (void) close(fd);
67*433d6423SLionel Sambuc if (unlink("testfile") != 0) {
68*433d6423SLionel Sambuc /* This is not good. We created a file, but we can
69*433d6423SLionel Sambuc * never access it; we have a spurious inode.
70*433d6423SLionel Sambuc */
71*433d6423SLionel Sambuc e(9);
72*433d6423SLionel Sambuc printf(INTEGR_MSG);
73*433d6423SLionel Sambuc exit(errct);
74*433d6423SLionel Sambuc }
75*433d6423SLionel Sambuc }
76*433d6423SLionel Sambuc if (errno != ENOENT) e(10);
77*433d6423SLionel Sambuc
78*433d6423SLionel Sambuc /* Try to create a dir */
79*433d6423SLionel Sambuc errno = 0;
80*433d6423SLionel Sambuc if (mkdir("testdir", 0777) == 0) {
81*433d6423SLionel Sambuc e(11);
82*433d6423SLionel Sambuc /* Uh oh. This shouldn't have been possible. Try to undo. */
83*433d6423SLionel Sambuc if (rmdir("testdir") != 0) {
84*433d6423SLionel Sambuc /* Not good. */
85*433d6423SLionel Sambuc e(12);
86*433d6423SLionel Sambuc printf(INTEGR_MSG);
87*433d6423SLionel Sambuc exit(errct);
88*433d6423SLionel Sambuc }
89*433d6423SLionel Sambuc }
90*433d6423SLionel Sambuc if (errno != ENOENT) e(13);
91*433d6423SLionel Sambuc
92*433d6423SLionel Sambuc /* Try to create a special file */
93*433d6423SLionel Sambuc errno = 0;
94*433d6423SLionel Sambuc if (mknod("testnode", 0777 | S_IFIFO, 0) == 0) {
95*433d6423SLionel Sambuc e(14);
96*433d6423SLionel Sambuc /* Impossible. Try to make it unhappen. */
97*433d6423SLionel Sambuc if (unlink("testnode") != 0) {
98*433d6423SLionel Sambuc /* Not good. */
99*433d6423SLionel Sambuc e(15);
100*433d6423SLionel Sambuc printf(INTEGR_MSG);
101*433d6423SLionel Sambuc exit(errct);
102*433d6423SLionel Sambuc }
103*433d6423SLionel Sambuc }
104*433d6423SLionel Sambuc if (errno != ENOENT) e(16);
105*433d6423SLionel Sambuc
106*433d6423SLionel Sambuc /* Try to rename a file */
107*433d6423SLionel Sambuc errno = 0;
108*433d6423SLionel Sambuc /* First create a file in the test dir */
109*433d6423SLionel Sambuc snprintf(renamebuf, PATH_MAX, "%s/oldname", testroot);
110*433d6423SLionel Sambuc if ((fd = open(renamebuf, O_RDWR | O_CREAT)) == -1) e(17);
111*433d6423SLionel Sambuc if (close(fd) != 0) e(18);
112*433d6423SLionel Sambuc
113*433d6423SLionel Sambuc /* Now try to rename that file to an entry in the current, non-existing
114*433d6423SLionel Sambuc * working directory.
115*433d6423SLionel Sambuc */
116*433d6423SLionel Sambuc if (rename(renamebuf, "testrename") == 0) {
117*433d6423SLionel Sambuc e(19);
118*433d6423SLionel Sambuc /* This shouldn't have been possible. Revert the name change.
119*433d6423SLionel Sambuc */
120*433d6423SLionel Sambuc if (rename("testrename", renamebuf) != 0) {
121*433d6423SLionel Sambuc /* Failed */
122*433d6423SLionel Sambuc e(20);
123*433d6423SLionel Sambuc printf(INTEGR_MSG);
124*433d6423SLionel Sambuc exit(errct);
125*433d6423SLionel Sambuc }
126*433d6423SLionel Sambuc }
127*433d6423SLionel Sambuc
128*433d6423SLionel Sambuc /* Try to create a hard link to that file */
129*433d6423SLionel Sambuc errno = 0;
130*433d6423SLionel Sambuc if (link(renamebuf, "testhlink") == 0) {
131*433d6423SLionel Sambuc e(21);
132*433d6423SLionel Sambuc /* Try to undo the hard link to prevent fs corruption. */
133*433d6423SLionel Sambuc if (unlink("testhlink") != 0) {
134*433d6423SLionel Sambuc /* Failed. */
135*433d6423SLionel Sambuc e(22);
136*433d6423SLionel Sambuc printf(INTEGR_MSG);
137*433d6423SLionel Sambuc exit(errct);
138*433d6423SLionel Sambuc }
139*433d6423SLionel Sambuc }
140*433d6423SLionel Sambuc if (errno != ENOENT) e(23);
141*433d6423SLionel Sambuc
142*433d6423SLionel Sambuc /* Try to create a symlink */
143*433d6423SLionel Sambuc errno = 0;
144*433d6423SLionel Sambuc if (symlink(testroot, "testslink") == 0) {
145*433d6423SLionel Sambuc e(24);
146*433d6423SLionel Sambuc /* Try to remove the symlink to prevent fs corruption. */
147*433d6423SLionel Sambuc if (unlink("testslink") != 0) {
148*433d6423SLionel Sambuc /* Failed. */
149*433d6423SLionel Sambuc e(25);
150*433d6423SLionel Sambuc printf(INTEGR_MSG);
151*433d6423SLionel Sambuc exit(errct);
152*433d6423SLionel Sambuc }
153*433d6423SLionel Sambuc }
154*433d6423SLionel Sambuc if (errno != ENOENT) e(26);
155*433d6423SLionel Sambuc
156*433d6423SLionel Sambuc exit(errct);
157*433d6423SLionel Sambuc } else { /* Parent */
158*433d6423SLionel Sambuc int status;
159*433d6423SLionel Sambuc
160*433d6423SLionel Sambuc /* Wait for the child to enter the TEST_PATH dir */
161*433d6423SLionel Sambuc if (read(s[1], buf, sizeof(buf)) != sizeof(buf)) e(27);
162*433d6423SLionel Sambuc
163*433d6423SLionel Sambuc /* Delete TEST_PATH */
164*433d6423SLionel Sambuc if (rmdir(TEST_PATH) != 0) e(28);
165*433d6423SLionel Sambuc
166*433d6423SLionel Sambuc /* Tell child we removed its cwd */
167*433d6423SLionel Sambuc buf[0] = 'b';
168*433d6423SLionel Sambuc if (write(s[1], buf, sizeof(buf)) != sizeof(buf)) e(29);
169*433d6423SLionel Sambuc
170*433d6423SLionel Sambuc wait(&status);
171*433d6423SLionel Sambuc errct += WEXITSTATUS(status); /* Count errors */
172*433d6423SLionel Sambuc }
173*433d6423SLionel Sambuc }
174*433d6423SLionel Sambuc
main(int argc,char * argv[])175*433d6423SLionel Sambuc int main(int argc, char* argv[])
176*433d6423SLionel Sambuc {
177*433d6423SLionel Sambuc start(58);
178*433d6423SLionel Sambuc do_test();
179*433d6423SLionel Sambuc quit();
180*433d6423SLionel Sambuc return(-1); /* Unreachable */
181*433d6423SLionel Sambuc }
182*433d6423SLionel Sambuc
183*433d6423SLionel Sambuc
184