xref: /minix3/minix/tests/test58.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
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