xref: /minix/minix/tests/test21.c (revision 7f5f010b)
1 /* POSIX test program (21).			Author: Andy Tanenbaum */
2 
3 /* The following POSIX calls are tested:
4  *
5  *	rename(),  mkdir(),  rmdir()
6  */
7 
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <limits.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <stdio.h>
17 
18 #define ITERATIONS        1
19 int max_error = 3;
20 #include "common.h"
21 
22 
23 
24 int main(int argc, char *argv []);
25 void test21a(void);
26 void test21b(void);
27 void test21c(void);
28 void test21d(void);
29 void test21e(void);
30 void test21f(void);
31 void test21g(void);
32 void test21h(void);
33 void test21i(void);
34 void test21k(void);
35 void test21l(void);
36 void test21m(void);
37 void test21n(void);
38 void test21o(void);
39 int get_link(char *name);
40 
41 int main(argc, argv)
42 int argc;
43 char *argv[];
44 {
45 
46   int i, m = 0xFFFF;
47 
48   start(21);
49 
50   if (argc == 2) m = atoi(argv[1]);
51 
52   for (i = 0; i < ITERATIONS; i++) {
53 	if (m & 00001) test21a();
54 	if (m & 00002) test21b();
55 	if (m & 00004) test21c();
56 	if (m & 00010) test21d();
57 	if (m & 00020) test21e();
58 	if (m & 00040) test21f();
59 	if (m & 01000) test21g();
60 	if (m & 00200) test21h();
61 	if (m & 00400) test21i();
62 	if (m & 01000) test21k();
63 	if (m & 02000) test21l();
64 	if (m & 04000) test21m();
65 	if (m & 010000) test21n();
66 	if (m & 020000) test21o();
67   }
68   quit();
69 
70   return(-1);	/* Unreachable */
71 }
72 
73 void test21a()
74 {
75 /* Test rename(). */
76 
77   int fd, fd2;
78   char buf[PATH_MAX+1], buf1[PATH_MAX+1], buf2[PATH_MAX+1];
79   struct stat stat1, stat2;
80 
81   subtest = 1;
82 
83   unlink("A1");			/* get rid of it if it exists */
84   unlink("A2");			/* get rid of it if it exists */
85   unlink("A3");			/* get rid of it if it exists */
86   unlink("A4");			/* get rid of it if it exists */
87   unlink("A5");			/* get rid of it if it exists */
88   unlink("A6");			/* get rid of it if it exists */
89   unlink("A7");			/* get rid of it if it exists */
90 
91   /* Basic test.  Rename A1 to A2 and then A2 to A3. */
92   if ( (fd=creat("A1", 0666)) < 0) e(1);
93   if (write(fd, buf, 20) != 20) e(2);
94   if (close(fd) < 0) e(3);
95   if (rename("A1", "A2") < 0) e(4);
96   if ( (fd=open("A2", O_RDONLY)) < 0) e(5);
97   if (rename("A2", "A3") < 0) e(6);
98   if ( (fd2=open("A3", O_RDONLY)) < 0) e(7);
99   if (close(fd) != 0) e(8);
100   if (close(fd2) != 0) e(9);
101   if (unlink("A3") != 0) e(10);
102 
103   /* Now get the absolute path name of the current directory using getcwd()
104    * and use it to test RENAME using different combinations of relative and
105    * absolute path names.
106    */
107   if (getcwd(buf, PATH_MAX) == (char *) NULL) e(11);
108   if ( (fd = creat("A4", 0666)) < 0) e(12);
109   if (write(fd, buf, 30) != 30) e(13);
110   if (close(fd) != 0) e(14);
111   strcpy(buf1, buf);
112   strcat(buf1, "/A4");
113   if (rename(buf1, "A5") != 0) e(15);	/* rename(absolute, relative) */
114   if (access("A5", 6) != 0) e(16);	/* use access to see if file exists */
115   strcpy(buf2, buf);
116   strcat(buf2, "/A6");
117   if (rename("A5", buf2) != 0) e(17);	/* rename(relative, absolute) */
118   if (access("A6", 6) != 0) e(18);
119   if (access(buf2, 6) != 0) e(19);
120   strcpy(buf1, buf);
121   strcat(buf1, "/A6");
122   strcpy(buf2, buf);
123   strcat(buf2, "/A7");
124   if (rename(buf1, buf2) != 0) e(20);	/* rename(absolute, absolute) */
125   if (access("A7", 6) != 0) e(21);
126   if (access(buf2, 6) != 0) e(22);
127 
128   /* Try renaming using names like "./A8" */
129   if (rename("A7", "./A8") != 0) e(23);
130   if (access("A8", 6) != 0) e(24);
131   if (rename("./A8", "A9") != 0) e(25);
132   if (access("A9", 6) != 0) e(26);
133   if (rename("./A9", "./A10") != 0) e(27);
134   if (access("A10", 6) != 0) e(28);
135   if (access("./A10", 6) != 0) e(29);
136   if (unlink("A10") != 0) e(30);
137 
138   /* Now see if directories can be renamed. */
139   if (system("rm -rf ?uzzy scsi") != 0) e(31);
140   if (system("mkdir fuzzy") != 0) e(32);
141   if (rename("fuzzy", "wuzzy") != 0) e(33);
142   if ( (fd=creat("wuzzy/was_a_bear", 0666)) < 0) e(34);
143   if (access("wuzzy/was_a_bear", 6) != 0) e(35);
144   if (unlink("wuzzy/was_a_bear") != 0) e(36);
145   if (close(fd) != 0) e(37);
146   if (rename("wuzzy", "buzzy") != 0) e(38);
147   if (system("rmdir buzzy") != 0) e(39);
148 
149   /* Now start testing the case that 'new' exists. */
150   if ( (fd = creat("horse", 0666)) < 0) e(40);
151   if ( (fd2 = creat("sheep", 0666)) < 0) e(41);
152   if (write(fd, buf, PATH_MAX) != PATH_MAX) e(42);
153   if (write(fd2, buf, 23) != 23) e(43);
154   if (stat("horse", &stat1) != 0) e(44);
155   if (rename("horse", "sheep") != 0) e(45);
156   if (stat("sheep", &stat2) != 0) e(46);
157   if (stat1.st_dev != stat2.st_dev) e(47);
158   if (stat1.st_ino != stat2.st_ino) e(48);
159   if (stat2.st_size != PATH_MAX) e(49);
160   if (access("horse", 6) == 0) e(50);
161   if (close(fd) != 0) e(51);
162   if (close(fd2) != 0) e(52);
163   if (rename("sheep", "sheep") != 0) e(53);
164   if (unlink("sheep") != 0) e(54);
165 
166   /* Now try renaming something to a directory that already exists. */
167   if (system("mkdir fuzzy wuzzy") != 0) e(55);
168   if ( (fd = creat("fuzzy/was_a_bear", 0666)) < 0) e(56);
169   if (close(fd) != 0) e(57);
170   if (rename("fuzzy", "wuzzy") != 0) e(58);	/* 'new' is empty dir */
171   if (system("mkdir scsi") != 0) e(59);
172   if (rename("scsi", "wuzzy") == 0) e(60);	/* 'new' is full dir */
173   if (errno != EEXIST && errno != ENOTEMPTY) e(61);
174 
175   /* Test 14 character names--always tricky. */
176   if (rename("wuzzy/was_a_bear", "wuzzy/was_not_a_bear") != 0) e(62);
177   if (access("wuzzy/was_not_a_bear", 6) != 0) e(63);
178   if (rename("wuzzy/was_not_a_bear", "wuzzy/was_not_a_duck") != 0) e(64);
179   if (access("wuzzy/was_not_a_duck", 6) != 0) e(65);
180   if (rename("wuzzy/was_not_a_duck", "wuzzy/was_a_bird") != 0) e(65);
181   if (access("wuzzy/was_a_bird", 6) != 0) e(66);
182 
183   /* Test moves between directories. */
184   if (rename("wuzzy/was_a_bird", "beast") != 0) e(67);
185   if (access("beast", 6) != 0) e(68);
186   if (rename("beast", "wuzzy/was_a_cat") != 0) e(69);
187   if (access("wuzzy/was_a_cat", 6) != 0) e(70);
188 
189   /* Test error conditions. 'scsi' and 'wuzzy/was_a_cat' exist now. */
190   if (rename("wuzzy/was_a_cat", "wuzzy/was_a_dog") != 0) e(71);
191   if (access("wuzzy/was_a_dog", 6) != 0) e(72);
192   if (chmod("wuzzy", 0) != 0) e(73);
193 
194   errno = 0;
195   if (rename("wuzzy/was_a_dog", "wuzzy/was_a_pig") != -1) e(74);
196   if (errno != EACCES) e(75);
197 
198   errno = 0;
199   if (rename("wuzzy/was_a_dog", "doggie") != -1) e(76);
200   if (errno != EACCES) e(77);
201 
202   errno = 0;
203   if ( (fd = creat("beast", 0666)) < 0) e(78);
204   if (close(fd) != 0) e(79);
205   if (rename("beast", "wuzzy/was_a_twit") != -1) e(80);
206   if (errno != EACCES) e(81);
207 
208   errno = 0;
209   if (rename("beast", "wuzzy") != -1) e(82);
210   if (errno != EISDIR) e(83);
211 
212   errno = 0;
213   if (rename("beest", "baste") != -1) e(84);
214   if (errno != ENOENT) e(85);
215 
216   errno = 0;
217   if (rename("wuzzy", "beast") != -1) e(86);
218   if (errno != ENOTDIR) e(87);
219 
220   /* Test prefix rule. */
221   errno = 0;
222   if (chmod("wuzzy", 0777) != 0) e(88);
223   if (unlink("wuzzy/was_a_dog") != 0) e(89);
224   strcpy(buf1, buf);
225   strcat(buf1, "/wuzzy");
226   if (rename(buf, buf1) != -1) e(90);
227   if (errno != EINVAL) e(91);
228 
229   if (system("rm -rf wuzzy beast scsi") != 0) e(92);
230 }
231 
232 
233 
234 void test21b()
235 {
236 /* Test mkdir() and rmdir(). */
237 
238   int i;
239   char name[3];
240   struct stat statbuf;
241 
242   subtest = 2;
243 
244   /* Simple stuff. */
245   if (mkdir("D1", 0700) != 0) e(1);
246   if (stat("D1", &statbuf) != 0) e(2);
247   if (!S_ISDIR(statbuf.st_mode)) e(3);
248   if ( (statbuf.st_mode & 0777) != 0700) e(4);
249   if (rmdir("D1") != 0) e(5);
250 
251   /* Make and remove 40 directories.  By doing so, the directory has to
252    * grow to 2 blocks.  That presents plenty of opportunity for bugs.
253    */
254   name[0] = 'D';
255   name[2] = '\0';
256   for (i = 0; i < 40; i++) {
257 	name[1] = 'A' + i;
258 	if (mkdir(name, 0700 + i%7) != 0) e(10+i);	/* for simplicity */
259   }
260   for (i = 0; i < 40; i++) {
261 	name[1] = 'A' + i;
262 	if (rmdir(name) != 0) e(50+i);
263   }
264 }
265 
266 void test21c()
267 {
268 /* Test mkdir() and rmdir(). */
269 
270   subtest = 3;
271 
272   if (mkdir("D1", 0777) != 0) e(1);
273   if (mkdir("D1/D2", 0777) != 0) e(2);
274   if (mkdir("D1/D2/D3", 0777) != 0) e(3);
275   if (mkdir("D1/D2/D3/D4", 0777) != 0) e(4);
276   if (mkdir("D1/D2/D3/D4/D5", 0777) != 0) e(5);
277   if (mkdir("D1/D2/D3/D4/D5/D6", 0777) != 0) e(6);
278   if (mkdir("D1/D2/D3/D4/D5/D6/D7", 0777) != 0) e(7);
279   if (mkdir("D1/D2/D3/D4/D5/D6/D7/D8", 0777) != 0) e(8);
280   if (mkdir("D1/D2/D3/D4/D5/D6/D7/D8/D9", 0777) != 0) e(9);
281   if (access("D1/D2/D3/D4/D5/D6/D7/D8/D9", 7) != 0) e(10);
282   if (rmdir("D1/D2/D3/D4/D5/D6/D7/D8/D9") != 0) e(11);
283   if (rmdir("D1/D2/D3/D4/D5/D6/D7/D8") != 0) e(12);
284   if (rmdir("D1/D2/D3/D4/D5/D6/D7") != 0) e(13);
285   if (rmdir("D1/D2/D3/D4/D5/D6") != 0) e(11);
286   if (rmdir("D1/D2/D3/D4/D5") != 0) e(13);
287   if (rmdir("D1/D2/D3/D4") != 0) e(14);
288   if (rmdir("D1/D2/D3") != 0) e(15);
289   if (rmdir("D1/D2") != 0) e(16);
290   if (rmdir("D1") != 0) e(17);
291 }
292 
293 void test21d()
294 {
295 /* Test making directories with files and directories in them. */
296 
297   int fd1, fd2, fd3, fd4, fd5, fd6, fd7, fd8, fd9;
298 
299   subtest = 4;
300 
301   if (mkdir("D1", 0777) != 0) e(1);
302   if (mkdir("D1/D2", 0777) != 0) e(2);
303   if (mkdir("./D1/D3", 0777) != 0) e(3);
304   if (mkdir("././D1/D4", 0777) != 0) e(4);
305   if ( (fd1 = creat("D1/D2/x", 0700)) < 0) e(5);
306   if ( (fd2 = creat("D1/D2/y", 0700)) < 0) e(6);
307   if ( (fd3 = creat("D1/D2/z", 0700)) < 0) e(7);
308   if ( (fd4 = creat("D1/D3/x", 0700)) < 0) e(8);
309   if ( (fd5 = creat("D1/D3/y", 0700)) < 0) e(9);
310   if ( (fd6 = creat("D1/D3/z", 0700)) < 0) e(10);
311   if ( (fd7 = creat("D1/D4/x", 0700)) < 0) e(11);
312   if ( (fd8 = creat("D1/D4/y", 0700)) < 0) e(12);
313   if ( (fd9 = creat("D1/D4/z", 0700)) < 0) e(13);
314   if (unlink("D1/D2/z") != 0) e(14);
315   if (unlink("D1/D2/y") != 0) e(15);
316   if (unlink("D1/D2/x") != 0) e(16);
317   if (unlink("D1/D3/x") != 0) e(17);
318   if (unlink("D1/D3/z") != 0) e(18);
319   if (unlink("D1/D3/y") != 0) e(19);
320   if (unlink("D1/D4/y") != 0) e(20);
321   if (unlink("D1/D4/z") != 0) e(21);
322   if (unlink("D1/D4/x") != 0) e(22);
323   if (rmdir("D1/D2") != 0) e(23);
324   if (rmdir("D1/D3") != 0) e(24);
325   if (rmdir("D1/D4") != 0) e(25);
326   if (rmdir("D1") != 0) e(26);
327   if (close(fd1) != 0) e(27);
328   if (close(fd2) != 0) e(28);
329   if (close(fd3) != 0) e(29);
330   if (close(fd4) != 0) e(30);
331   if (close(fd5) != 0) e(31);
332   if (close(fd6) != 0) e(32);
333   if (close(fd7) != 0) e(33);
334   if (close(fd8) != 0) e(34);
335   if (close(fd9) != 0) e(35);
336 
337 }
338 
339 void test21e()
340 {
341 /* Test error conditions. */
342 
343   subtest = 5;
344 
345   if (mkdir("D1", 0677) != 0) e(1);
346   errno = 0;
347   if (mkdir("D1/D2", 0777) != -1) e(2);
348   if (errno != EACCES) e(3);
349   if (chmod ("D1", 0577) != 0) e(4);
350   errno = 0;
351   if (mkdir("D1/D2", 0777) != -1) e(5);
352   if (errno != EACCES) e(6);
353   if (chmod ("D1", 0777) != 0) e(7);
354   errno = 0;
355   if (mkdir("D1", 0777) != -1) e(8);
356   if (errno != EEXIST) e(9);
357   errno = 0;
358   if (mkdir("D1/D2/x", 0777) != -1) e(14);
359   if (errno != ENOENT) e(15);
360 
361   /* A particularly nasty test is when the parent has mode 0.  Although
362    * this is unlikely to work, it had better not muck up the file system
363    */
364   if (mkdir("D1/D2", 0777) != 0) e(16);
365   if (chmod("D1", 0) != 0) e(17);
366   errno = 0;
367   if (rmdir("D1/D2") != -1) e(18);
368   if (errno != EACCES) e(19);
369   if (chmod("D1", 0777) != 0) e(20);
370   if (rmdir("D1/D2") != 0) e(21);
371   if (rmdir("D1") != 0) e(22);
372 }
373 
374 void test21f()
375 {
376 /* The rename() function affects the link count of all the files and
377  * directories it goes near.  Test to make sure it gets everything ok.
378  * There are four cases:
379  *
380  *   1. rename("d1/file1", "d1/file2");	- rename file without moving it
381  *   2. rename("d1/file1", "d2/file2");	- move a file to another dir
382  *   3. rename("d1/dir1", "d2/dir2");	- rename a dir without moving it
383  *   4. rename("d1/dir1", "d2/dir2");	- move a dir to another dir
384  *
385  * Furthermore, a distinction has to be made when the target file exists
386  * and when it does not exist, giving 8 cases in all.
387  */
388 
389   int fd, D1_before, D1_after, x_link, y_link;
390 
391   /* Test case 1: renaming a file within the same directory. */
392   subtest = 6;
393   if (mkdir("D1", 0777) != 0) e(1);
394   if ( (fd = creat("D1/x", 0777)) < 0) e(2);
395   if (close(fd) != 0) e(3);
396   D1_before = get_link("D1");
397   x_link = get_link("D1/x");
398   if (rename("D1/x", "D1/y") != 0) e(4);
399   y_link = get_link("D1/y");
400   D1_after = get_link("D1");
401   if (D1_before != 2) e(5);
402   if (D1_after != 2) e(6);
403   if (x_link != 1) e(7);
404   if (y_link != 1) e(8);
405   if (access("D1/y", 7) != 0) e(9);
406   if (unlink("D1/y") != 0) e(10);
407   if (rmdir("D1") != 0) e(11);
408 }
409 
410 void test21g()
411 {
412   int fd, D1_before, D1_after, D2_before, D2_after, x_link, y_link;
413 
414   /* Test case 2: move a file to a new directory. */
415   subtest = 7;
416   if (mkdir("D1", 0777) != 0) e(1);
417   if (mkdir("D2", 0777) != 0) e(2);
418   if ( (fd = creat("D1/x", 0777)) < 0) e(3);
419   if (close(fd) != 0) e(4);
420   D1_before = get_link("D1");
421   D2_before = get_link("D2");
422   x_link = get_link("D1/x");
423   if (rename("D1/x", "D2/y") != 0) e(5);
424   y_link = get_link("D2/y");
425   D1_after = get_link("D1");
426   D2_after = get_link("D2");
427   if (D1_before != 2) e(6);
428   if (D2_before != 2) e(7);
429   if (D1_after != 2) e(8);
430   if (D2_after != 2) e(9);
431   if (x_link != 1) e(10);
432   if (y_link != 1) e(11);
433   if (access("D2/y", 7) != 0) e(12);
434   if (unlink("D2/y") != 0) e(13);
435   if (rmdir("D1") != 0) e(14);
436   if (rmdir("D2") != 0) e(15);
437 }
438 
439 void test21h()
440 {
441   int D1_before, D1_after, x_link, y_link;
442 
443   /* Test case 3: renaming a directory within the same directory. */
444   subtest = 8;
445   if (mkdir("D1", 0777) != 0) e(1);
446   if (mkdir("D1/X", 0777) != 0) e(2);
447   D1_before = get_link("D1");
448   x_link = get_link("D1/X");
449   if (rename("D1/X", "D1/Y") != 0) e(3);
450   y_link = get_link("D1/Y");
451   D1_after = get_link("D1");
452   if (D1_before != 3) e(4);
453   if (D1_after != 3) e(5);
454   if (x_link != 2) e(6);
455   if (y_link != 2) e(7);
456   if (access("D1/Y", 7) != 0) e(8);
457   if (rmdir("D1/Y") != 0) e(9);
458   if (get_link("D1") != 2) e(10);
459   if (rmdir("D1") != 0) e(11);
460 }
461 
462 void test21i()
463 {
464   int D1_before, D1_after, D2_before, D2_after, x_link, y_link;
465 
466   /* Test case 4: move a directory to a new directory. */
467   subtest = 9;
468   if (mkdir("D1", 0777) != 0) e(1);
469   if (mkdir("D2", 0777) != 0) e(2);
470   if (mkdir("D1/X", 0777) != 0) e(3);
471   D1_before = get_link("D1");
472   D2_before = get_link("D2");
473   x_link = get_link("D1/X");
474   if (rename("D1/X", "D2/Y") != 0) e(4);
475   y_link = get_link("D2/Y");
476   D1_after = get_link("D1");
477   D2_after = get_link("D2");
478   if (D1_before != 3) e(5);
479   if (D2_before != 2) e(6);
480   if (D1_after != 2) e(7);
481   if (D2_after != 3) e(8);
482   if (x_link != 2) e(9);
483   if (y_link != 2) e(10);
484   if (access("D2/Y", 7) != 0) e(11);
485   if (rename("D2/Y", "D1/Z") != 0) e(12);
486   if (get_link("D1") != 3) e(13);
487   if (get_link("D2") != 2) e(14);
488   if (rmdir("D1/Z") != 0) e(15);
489   if (get_link("D1") != 2) e(16);
490   if (rmdir("D1") != 0) e(17);
491   if (rmdir("D2") != 0) e(18);
492 }
493 
494 void test21k()
495 {
496 /* Now test the same 4 cases, except when the target exists. */
497 
498   int fd, D1_before, D1_after, x_link, y_link;
499 
500   /* Test case 5: renaming a file within the same directory. */
501   subtest = 10;
502   if (mkdir("D1", 0777) != 0) e(1);
503   if ( (fd = creat("D1/x", 0777)) < 0) e(2);
504   if (close(fd) != 0) e(3);
505   if ( (fd = creat("D1/y", 0777)) < 0) e(3);
506   if (close(fd) != 0) e(4);
507   D1_before = get_link("D1");
508   x_link = get_link("D1/x");
509   if (rename("D1/x", "D1/y") != 0) e(5);
510   y_link = get_link("D1/y");
511   D1_after = get_link("D1");
512   if (D1_before != 2) e(6);
513   if (D1_after != 2) e(7);
514   if (x_link != 1) e(8);
515   if (y_link != 1) e(9);
516   if (access("D1/y", 7) != 0) e(10);
517   if (unlink("D1/y") != 0) e(11);
518   if (rmdir("D1") != 0) e(12);
519 }
520 
521 void test21l()
522 {
523   int fd, D1_before, D1_after, D2_before, D2_after, x_link, y_link;
524 
525   /* Test case 6: move a file to a new directory. */
526   subtest = 11;
527   if (mkdir("D1", 0777) != 0) e(1);
528   if (mkdir("D2", 0777) != 0) e(2);
529   if ( (fd = creat("D1/x", 0777)) < 0) e(3);
530   if (close(fd) != 0) e(4);
531   if ( (fd = creat("D2/y", 0777)) < 0) e(5);
532   if (close(fd) != 0) e(6);
533   D1_before = get_link("D1");
534   D2_before = get_link("D2");
535   x_link = get_link("D1/x");
536   if (rename("D1/x", "D2/y") != 0) e(7);
537   y_link = get_link("D2/y");
538   D1_after = get_link("D1");
539   D2_after = get_link("D2");
540   if (D1_before != 2) e(8);
541   if (D2_before != 2) e(9);
542   if (D1_after != 2) e(10);
543   if (D2_after != 2) e(11);
544   if (x_link != 1) e(12);
545   if (y_link != 1) e(13);
546   if (access("D2/y", 7) != 0) e(14);
547   if (unlink("D2/y") != 0) e(15);
548   if (rmdir("D1") != 0) e(16);
549   if (rmdir("D2") != 0) e(17);
550 }
551 
552 void test21m()
553 {
554   int D1_before, D1_after, x_link, y_link;
555 
556   /* Test case 7: renaming a directory within the same directory. */
557   subtest = 12;
558   if (mkdir("D1", 0777) != 0) e(1);
559   if (mkdir("D1/X", 0777) != 0) e(2);
560   if (mkdir("D1/Y", 0777) != 0) e(3);
561   D1_before = get_link("D1");
562   x_link = get_link("D1/X");
563   if (rename("D1/X", "D1/Y") != 0) e(4);
564   y_link = get_link("D1/Y");
565   D1_after = get_link("D1");
566   if (D1_before != 4) e(5);
567   if (D1_after != 3) e(6);
568   if (x_link != 2) e(7);
569   if (y_link != 2) e(8);
570   if (access("D1/Y", 7) != 0) e(9);
571   if (rmdir("D1/Y") != 0) e(10);
572   if (get_link("D1") != 2) e(11);
573   if (rmdir("D1") != 0) e(12);
574 }
575 
576 void test21n()
577 {
578   int D1_before, D1_after, D2_before, D2_after, x_link, y_link;
579 
580   /* Test case 8: move a directory to a new directory. */
581   subtest = 13;
582   if (mkdir("D1", 0777) != 0) e(1);
583   if (mkdir("D2", 0777) != 0) e(2);
584   if (mkdir("D1/X", 0777) != 0) e(3);
585   if (mkdir("D2/Y", 0777) != 0) e(4);
586   D1_before = get_link("D1");
587   D2_before = get_link("D2");
588   x_link = get_link("D1/X");
589   if (rename("D1/X", "D2/Y") != 0) e(5);
590   y_link = get_link("D2/Y");
591   D1_after = get_link("D1");
592   D2_after = get_link("D2");
593   if (D1_before != 3) e(6);
594   if (D2_before != 3) e(7);
595   if (D1_after != 2) e(8);
596   if (D2_after != 3) e(9);
597   if (x_link != 2) e(10);
598   if (y_link != 2) e(11);
599   if (access("D2/Y", 7) != 0) e(12);
600   if (rename("D2/Y", "D1/Z") != 0) e(13);
601   if (get_link("D1") != 3) e(14);
602   if (get_link("D2") != 2) e(15);
603   if (rmdir("D1/Z") != 0) e(16);
604   if (get_link("D1") != 2) e(17);
605   if (rmdir("D1") != 0) e(18);
606   if (rmdir("D2") != 0) e(19);
607 }
608 
609 void test21o()
610 {
611   /* Test trying to remove . and .. */
612   subtest = 14;
613   if (mkdir("D1", 0777) != 0) e(1);
614   if (chdir("D1") != 0) e(2);
615   if (rmdir(".") == 0) e(3);
616   if (rmdir("..") == 0) e(4);
617   if (mkdir("D2", 0777) != 0) e(5);
618   if (mkdir("D3", 0777) != 0) e(6);
619   if (mkdir("D4", 0777) != 0) e(7);
620   if (rmdir("D2/../D3/../D4") != 0) e(8);	/* legal way to remove D4 */
621   if (rmdir("D2/../D3/../D2/..") == 0) e(9);	/* removing self is illegal */
622   if (rmdir("D2/../D3/../D2/../..") == 0) e(10);/* removing parent is illegal*/
623   if (rmdir("../D1/../D1/D3") != 0) e(11);	/* legal way to remove D3 */
624   if (rmdir("./D2/../D2") != 0) e(12);		/* legal way to remove D2 */
625   if (chdir("..") != 0) e(13);
626   if (rmdir("D1") != 0) e(14);
627 }
628 
629 int get_link(name)
630 char *name;
631 {
632   struct stat statbuf;
633 
634   if (stat(name, &statbuf) != 0) {
635 	printf("Unable to stat %s\n", name);
636 	errct++;
637 	return(-1);
638   }
639   return(statbuf.st_nlink);
640 }
641 
642