vm: use arch_map2str to print pagefault info, to properly display code addrs
[minix.git] / test / test17.c
blobdf0afd915eb84ff8c9129b2723c1e894dc35480b
1 /* Comment on usage and program: ark!/mnt/rene/prac/os/unix/comment.changes */
3 /* "const.h", created by Rene Montsma and Menno Wilcke */
5 #include <sys/types.h> /* type defs */
6 #include <sys/stat.h> /* struct stat */
7 #include <sys/wait.h>
8 #include <errno.h> /* the error-numbers */
9 #include <fcntl.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <utime.h>
14 #include <stdio.h>
15 #include <limits.h>
17 #define NOCRASH 1 /* test11(), 2nd pipe */
18 #define PDPNOHANG 1 /* test03(), write_standards() */
19 #define MAXERR 2
21 #define USER_ID 12
22 #define GROUP_ID 1
23 #define FF 3 /* first free filedes. */
24 #define USER 1 /* uid */
25 #define GROUP 0 /* gid */
27 #define ARSIZE 256 /* array size */
28 #define PIPESIZE 3584 /* max number of bytes to be written on pipe */
29 #define MAXOPEN (OPEN_MAX-3) /* maximum number of extra open files */
30 #define MAXLINK 0177 /* maximum number of links per file */
31 #define LINKCOUNT 5
32 #define MASK 0777 /* selects lower nine bits */
33 #define END_FILE 0 /* returned by read-call at eof */
35 #define OK 0
36 #define FAIL -1
38 #define R 0 /* read (open-call) */
39 #define W 1 /* write (open-call) */
40 #define RW 2 /* read & write (open-call) */
42 #define RWX 7 /* read & write & execute (mode) */
44 #define NIL ""
45 #define UMASK "umask"
46 #define CREAT "creat"
47 #define WRITE "write"
48 #define READ "read"
49 #define OPEN "open"
50 #define CLOSE "close"
51 #define LSEEK "lseek"
52 #define ACCESS "access"
53 #define CHDIR "chdir"
54 #define CHMOD "chmod"
55 #define LINK "link"
56 #define UNLINK "unlink"
57 #define PIPE "pipe"
58 #define STAT "stat"
59 #define FSTAT "fstat"
60 #define DUP "dup"
61 #define UTIME "utime"
63 int errct;
65 char *file[];
66 char *fnames[];
67 char *dir[];
69 /* "decl.c", created by Rene Montsma and Menno Wilcke */
71 /* Used in open_alot, close_alot */
72 char *file[20] = {"f0", "f1", "f2", "f3", "f4", "f5", "f6",
73 "f7", "f8", "f9", "f10", "f11", "f12", "f13",
74 "f14", "f15", "f16", "f17", "f18", "f19"}, *fnames[8] = {"---", "--x", "-w-", "-wx", "r--",
75 "r-x", "rw-", "rwx"}, *dir[8] = {"d---", "d--x", "d-w-", "d-wx", "dr--", "dr-x",
76 "drw-", "drwx"};
77 /* Needed for easy creating and deleting of directories */
79 /* "test.c", created by Rene Montsma and Menno Wilcke */
81 _PROTOTYPE(int main, (int argc, char *argv []));
82 _PROTOTYPE(void test, (int mask));
83 _PROTOTYPE(void test01, (void));
84 _PROTOTYPE(void test02, (void));
85 _PROTOTYPE(void test08, (void));
86 _PROTOTYPE(void test09, (void));
87 _PROTOTYPE(void test10, (void));
88 _PROTOTYPE(int link_alot, (char *bigboss));
89 _PROTOTYPE(int unlink_alot, (int number));
90 _PROTOTYPE(void get_new, (char name []));
91 _PROTOTYPE(void test11, (void));
92 _PROTOTYPE(void comp_stats, (struct stat *stbf1, struct stat *stbf2));
93 _PROTOTYPE(void comp_inodes, (int m, int m1));
94 _PROTOTYPE(void e, (char *string));
95 _PROTOTYPE(void nlcr, (void));
96 _PROTOTYPE(void str, (char *s));
97 _PROTOTYPE(void err, (int number, char *scall, char *name));
98 _PROTOTYPE(void make_and_fill_dirs, (void));
99 _PROTOTYPE(void put_file_in_dir, (char *dirname, int mode));
100 _PROTOTYPE(void init_array, (char *a));
101 _PROTOTYPE(void clear_array, (char *b));
102 _PROTOTYPE(int comp_array, (char *a, char *b, int range));
103 _PROTOTYPE(void try_close, (int filedes, char *name));
104 _PROTOTYPE(void try_unlink, (char *fname));
105 _PROTOTYPE(void Remove, (int fdes, char *fname));
106 _PROTOTYPE(int get_mode, (char *name));
107 _PROTOTYPE(void check, (char *scall, int number));
108 _PROTOTYPE(void put, (int nr));
109 _PROTOTYPE(int open_alot, (void));
110 _PROTOTYPE(int close_alot, (int number));
111 _PROTOTYPE(void clean_up_the_mess, (void));
112 _PROTOTYPE(void chmod_8_dirs, (int sw));
113 _PROTOTYPE(void quit, (void));
115 /*****************************************************************************
116 * TEST *
117 ****************************************************************************/
118 int main(argc, argv)
119 int argc;
120 char *argv[];
122 char buffer[PATH_MAX + 1];
123 int n, mask;
125 sync();
126 if (geteuid() == 0 || getuid() == 0) {
127 realpath(argv[0], buffer);
128 execl("/usr/bin/su", "/usr/bin/su", "-", "ast", "-c", buffer, NULL);
129 printf("Test 17 cannot run as root; test aborted\n");
130 exit(1);
133 system("rm -rf DIR_17; mkdir DIR_17");
134 chdir("DIR_17");
136 mask = (argc == 2 ? atoi(argv[1]) : 0xFFFF);
138 if (fork()) {
139 printf("Test 17 ");
140 fflush(stdout);
142 wait(&n);
143 clean_up_the_mess();
144 quit();
145 } else {
146 test(mask);
147 exit(0);
149 return(-1); /* impossible */
152 void test(mask)
153 int mask;
155 umask(0); /* not honest, but i always forget */
157 if (mask & 00001) test01();
158 if (mask & 00002) make_and_fill_dirs();
159 if (mask & 00004) test02();
160 if (mask & 00010) test08();
161 if (mask & 00020) test09();
162 if (mask & 00040) test10();
163 if (mask & 00100) test11();
164 umask(022);
165 } /* test */
167 /* "t1.c" created by Rene Montsma and Menno Wilcke */
169 /*****************************************************************************
170 * test UMASK *
171 ****************************************************************************/
172 void test01()
174 int oldvalue, newvalue, tempvalue;
175 int nr;
177 if ((oldvalue = umask(0777)) != 0) err(0, UMASK, NIL);
179 /* Special test: only the lower 9 bits (protection bits) may part- *
180 * icipate. ~0777 means: 111 000 000 000. Giving this to umask must*
181 * not change any value. */
183 if ((newvalue = umask(~0777)) != 0777) err(1, UMASK, "illegal");
184 if (oldvalue == newvalue) err(11, UMASK, "not change mask");
186 if ((tempvalue = umask(0)) != 0) err(2, UMASK, "values");
188 /* Now test all possible modes of umask on a file */
189 for (newvalue = MASK; newvalue >= 0; newvalue -= 0111) {
190 tempvalue = umask(newvalue);
191 if (tempvalue != oldvalue) {
192 err(1, UMASK, "illegal");
193 break; /* no use trying more */
194 } else if ((nr = creat("file01", 0777)) < 0)
195 err(5, CREAT, "'file01'");
196 else {
197 try_close(nr, "'file01'");
198 if (get_mode("file01") != (MASK & ~newvalue))
199 err(7, UMASK, "mode computed");
200 try_unlink("file01");
202 oldvalue = newvalue;
205 /* The loop has terminated with umask(0) */
206 if ((tempvalue = umask(0)) != 0)
207 err(7, UMASK, "umask may influence rest of tests!");
208 } /* test01 */
210 /*****************************************************************************
211 * test CREAT *
212 ****************************************************************************/
213 void test02()
215 int n, n1, mode;
216 char a[ARSIZE], b[ARSIZE];
217 struct stat stbf1;
219 mode = 0;
220 /* Create twenty files, check filedes */
221 for (n = 0; n < MAXOPEN; n++) {
222 if (creat(file[n], mode) != FF + n)
223 err(13, CREAT, file[n]);
224 else {
225 if (get_mode(file[n]) != mode)
226 err(7, CREAT, "mode set while creating many files");
228 /* Change mode of file to standard mode, we want to *
229 * use a lot (20) of files to be opened later, see *
230 * open_alot(), close_alot(). */
231 if (chmod(file[n], 0700) != OK) err(5, CHMOD, file[n]);
234 mode = (mode + 0100) % 01000;
237 /* Already twenty files opened; opening another has to fail */
238 if (creat("file02", 0777) != FAIL)
239 err(9, CREAT, "created");
240 else
241 check(CREAT, EMFILE);
243 /* Close all files: seems blunt, but it isn't because we've *
244 * checked all fd's already */
245 if ((n = close_alot(MAXOPEN)) < MAXOPEN) err(5, CLOSE, "MAXOPEN files");
247 /* Creat 1 file twice; check */
248 if ((n = creat("file02", 0777)) < 0)
249 err(5, CREAT, "'file02'");
250 else {
251 init_array(a);
252 if (write(n, a, ARSIZE) != ARSIZE) err(1, WRITE, "bad");
254 if ((n1 = creat("file02", 0755)) < 0) /* receate 'file02' */
255 err(5, CREAT, "'file02' (2nd time)");
256 else {
257 /* Fd should be at the top after recreation */
258 if (lseek(n1, 0L, SEEK_END) != 0)
259 err(11, CREAT, "not truncate file by recreation");
260 else {
261 /* Try to write on recreated file */
262 clear_array(b);
264 if (lseek(n1, 0L, SEEK_SET) != 0)
265 err(5, LSEEK, "to top of 2nd fd 'file02'");
266 if (write(n1, a, ARSIZE) != ARSIZE)
267 err(1, WRITE, "(2) bad");
269 /* In order to read we've to close and open again */
270 try_close(n1, "'file02' (2nd creation)");
271 if ((n1 = open("file02", RW)) < 0)
272 err(5, OPEN, "'file02' (2nd recreation)");
274 /* Continue */
275 if (lseek(n1, 0L, SEEK_SET) != 0)
276 err(5, LSEEK, "to top 'file02'(2nd fd) (2)");
277 if (read(n1, b, ARSIZE) != ARSIZE)
278 err(1, READ, "wrong");
280 if (comp_array(a, b, ARSIZE) != OK) err(11, CREAT,
281 "not really truncate file by recreation");
283 if (get_mode("file02") != 0777)
284 err(11, CREAT, "not maintain mode by recreation");
285 try_close(n1, "recreated 'file02'");
288 Remove(n, "file02");
291 /* Give 'creat' wrong input: dir not searchable */
292 if (creat("drw-/file02", 0777) != FAIL)
293 err(4, CREAT, "'drw-'");
294 else
295 check(CREAT, EACCES);
297 /* Dir not writable */
298 if (creat("dr-x/file02", 0777) != FAIL)
299 err(12, CREAT, "'dr-x/file02'");
300 else
301 check(CREAT, EACCES);
303 /* File not writable */
304 if (creat("drwx/r-x", 0777) != FAIL)
305 err(11, CREAT, "recreate non-writable file");
306 else
307 check(CREAT, EACCES);
309 /* Try to creat a dir */
310 if ((n = creat("dir", 040777)) != FAIL) {
311 if (fstat(n, &stbf1) != OK)
312 err(5, FSTAT, "'dir'");
313 else if (stbf1.st_mode != (mode_t) 0100777)
314 /* cast because mode is negative :-( */
315 err(11, CREAT, "'creat' a new directory");
316 Remove(n, "dir");
319 /* We don't consider it to be a bug when creat * does not accept
320 * tricky modes */
322 /* File is an existing dir */
323 if (creat("drwx", 0777) != FAIL)
324 err(11, CREAT, "create an existing dir!");
325 else
326 check(CREAT, EISDIR);
327 } /* test02 */
329 void test08()
331 /* Test chdir to searchable dir */
332 if (chdir("drwx") != OK)
333 err(5, CHDIR, "to accessible dir");
334 else if (chdir("..") != OK)
335 err(11, CHDIR, "not return to '..'");
337 /* Check the chdir(".") and chdir("..") mechanism */
338 if (chdir("drwx") != OK)
339 err(5, CHDIR, "to 'drwx'");
340 else {
341 if (chdir(".") != OK) err(5, CHDIR, "to working dir (.)");
343 /* If we still are in 'drwx' , we should be able to access *
344 * file 'rwx'. */
345 if (access("rwx", 0) != OK) err(5, CHDIR, "rightly to '.'");
347 /* Try to return to previous dir ('/' !!) */
348 if (chdir("././../././d--x/../d--x/././..") != OK)
349 err(5, CHDIR, "to motherdir (..)");
351 /* Check whether we are back in '/' */
352 if (chdir("d--x") != OK) err(5, CHDIR, "rightly to a '..'");
355 /* Return to '..' */
356 if (chdir("..") != OK) err(5, CHDIR, "to '..'");
358 if (chdir("././././drwx") != OK)
359 err(11, CHDIR, "not follow a path");
360 else if (chdir("././././..") != OK)
361 err(11, CHDIR, "not return to path");
363 /* Try giving chdir wrong parameters */
364 if (chdir("drwx/rwx") != FAIL)
365 err(11, CHDIR, "chdir to a file");
366 else
367 check(CHDIR, ENOTDIR);
369 if (chdir("drw-") != FAIL)
370 err(4, CHDIR, "'/drw-'");
371 else
372 check(CHDIR, EACCES);
374 /* To be sure: return to root */
375 /* If (chdir("/") != OK) err(5, CHDIR, "to '/' (2nd time)"); */
376 } /* test08 */
378 /* New page */\f
379 /*****************************************************************************
380 * test CHMOD *
381 ****************************************************************************/
382 void test09()
384 int n;
386 /* Prepare file09 */
387 if ((n = creat("drwx/file09", 0644)) != FF) err(5, CREAT, "'drwx/file09'");
389 try_close(n, "'file09'");
391 /* Try to chmod a file, check and restore old values, check */
392 if (chmod("drwx/file09", 0700) != OK)
393 err(5, CHMOD, "'drwx/file09'"); /* set rwx */
394 else {
395 /* Check protection */
396 if (get_mode("drwx/file09") != 0700) err(7, CHMOD, "mode");
398 /* Test if chmod accepts just filenames too */
399 if (chdir("drwx") != OK)
400 err(5, CHDIR, "to '/drwx'");
401 else if (chmod("file09", 0177) != OK) /* restore oldies */
402 err(5, CHMOD, "'h1'");
403 else
404 /* Check if value has been restored */
405 if (get_mode("../drwx/file09") != 0177)
406 err(7, CHMOD, "restored mode");
409 /* Try setuid and setgid */
410 if ((chmod("file09", 04777) != OK) || (get_mode("file09") != 04777))
411 err(11, CHMOD, "not set uid-bit");
412 if ((chmod("file09", 02777) != OK) || (get_mode("file09") != 02777))
413 err(11, CHMOD, "not set gid-bit");
415 /* Remove testfile */
416 try_unlink("file09");
418 if (chdir("..") != OK) err(5, CHDIR, "to '..'");
420 /* Try to chmod directory */
421 if (chmod("d---", 0777) != OK)
422 err(5, CHMOD, "dir 'd---'");
423 else {
424 if (get_mode("d---") != 0777) err(7, CHMOD, "protection value");
425 if (chmod("d---", 0000) != OK) err(5, CHMOD, "dir 'a' 2nd time");
427 /* Check if old value has been restored */
428 if (get_mode("d---") != 0000)
429 err(7, CHMOD, "restored protection value");
432 /* Try to make chmod failures */
434 /* We still are in dir root */
435 /* Wrong filename */
436 if (chmod("non-file", 0777) != FAIL)
437 err(3, CHMOD, NIL);
438 else
439 check(CHMOD, ENOENT);
441 } /* test 09 */
443 /* New page */\f
445 /* "t4.c", created by Rene Montsma and Menno Wilcke */
447 /*****************************************************************************
448 * test LINK/UNLINK *
449 ****************************************************************************/
450 void test10()
452 int n, n1;
453 char a[ARSIZE], b[ARSIZE], *f, *lf;
455 f = "file10";
456 lf = "linkfile10";
458 if ((n = creat(f, 0702)) != FF) /* no other open files */
459 err(13, CREAT, f);
460 else {
461 /* Now link correctly */
462 if (link(f, lf) != OK)
463 err(5, LINK, lf);
464 else if ((n1 = open(lf, RW)) < 0)
465 err(5, OPEN, "'linkfile10'");
466 else {
467 init_array(a);
468 clear_array(b);
470 /* Write on 'file10' means being able to * read
471 * through linked filedescriptor */
472 if (write(n, a, ARSIZE) != ARSIZE) err(1, WRITE, "bad");
473 if (read(n1, b, ARSIZE) != ARSIZE) err(1, READ, "bad");
474 if (comp_array(a, b, ARSIZE) != OK) err(8, "r/w", NIL);
476 /* Clean up: unlink and close (twice): */
477 Remove(n, f);
478 try_close(n1, "'linkfile10'");
480 /* Check if "linkfile" exists and the info * on it
481 * is correct ('file' has been deleted) */
482 if ((n1 = open(lf, R)) < 0)
483 err(5, OPEN, "'linkfile10'");
484 else {
485 /* See if 'linkfile' still contains 0..511 ? */
487 clear_array(b);
488 if (read(n1, b, ARSIZE) != ARSIZE)
489 err(1, READ, "bad");
490 if (comp_array(a, b, ARSIZE) != OK)
491 err(8, "r/w", NIL);
493 try_close(n1, "'linkfile10' 2nd time");
494 try_unlink(lf);
499 /* Try if unlink fails with incorrect parameters */
500 /* File does not exist: */
501 if (unlink("non-file") != FAIL)
502 err(2, UNLINK, "name");
503 else
504 check(UNLINK, ENOENT);
506 /* Dir can't be written */
507 if (unlink("dr-x/rwx") != FAIL)
508 err(11, UNLINK, "could unlink in non-writable dir.");
509 else
510 check(UNLINK, EACCES);
512 /* Try to unlink a dir being user */
513 if (unlink("drwx") != FAIL)
514 err(11, UNLINK, "unlink dir's as user");
515 else
516 check(UNLINK, EPERM);
518 /* Try giving link wrong input */
520 /* First try if link fails with incorrect parameters * name1 does not
521 * exist. */
522 if (link("non-file", "linkfile") != FAIL)
523 err(2, LINK, "1st name");
524 else
525 check(LINK, ENOENT);
527 /* Name2 exists already */
528 if (link("drwx/rwx", "drwx/rw-") != FAIL)
529 err(2, LINK, "2nd name");
530 else
531 check(LINK, EEXIST);
533 /* Directory of name2 not writable: */
534 if (link("drwx/rwx", "dr-x/linkfile") != FAIL)
535 err(11, LINK, "link non-writable file");
536 else
537 check(LINK, EACCES);
539 /* Try to link a dir, being a user */
540 if (link("drwx", "linkfile") != FAIL)
541 err(11, LINK, "link a dir without superuser!");
542 else
543 check(LINK, EPERM);
545 /* File has too many links */
546 if ((n = link_alot("drwx/rwx")) != LINKCOUNT - 1) /* file already has one
547 * link */
548 err(5, LINK, "many files");
549 if (unlink_alot(n) != n) err(5, UNLINK, "all linked files");
551 } /* test10 */
553 int link_alot(bigboss)
554 char *bigboss;
556 int i;
557 static char employee[6] = "aaaaa";
559 /* Every file has already got 1 link, so link 0176 times */
560 for (i = 1; i < LINKCOUNT; i++) {
561 if (link(bigboss, employee) != OK)
562 break;
563 else
564 get_new(employee);
567 return(i - 1); /* number of linked files */
568 } /* link_alot */
570 int unlink_alot(number)
571 int number; /* number of files to be unlinked */
573 int j;
574 static char employee[6] = "aaaaa";
576 for (j = 0; j < number; j++) {
577 if (unlink(employee) != OK)
578 break;
579 else
580 get_new(employee);
583 return(j); /* return number of unlinked files */
584 } /* unlink_alot */
586 void get_new(name)
587 char name[];
588 /* Every call changes string 'name' to a string alphabetically *
589 * higher. Start with "aaaaa", next value: "aaaab" . *
590 * N.B. after "aaaaz" comes "aaabz" and not "aaaba" (not needed). *
591 * The last possibility will be "zzzzz". *
592 * Total # possibilities: 26+25*4 = 126 = MAXLINK -1 (exactly needed) */
594 int i;
596 for (i = 4; i >= 0; i--)
597 if (name[i] != 'z') {
598 name[i]++;
599 break;
601 } /* get_new */
603 /* New page */\f
605 /*****************************************************************************
606 * test PIPE *
607 ****************************************************************************/
608 void test11()
610 int n, fd[2];
611 char a[ARSIZE], b[ARSIZE];
613 if (pipe(fd) != OK)
614 err(13, PIPE, NIL);
615 else {
616 /* Try reading and writing on a pipe */
617 init_array(a);
618 clear_array(b);
620 if (write(fd[1], a, ARSIZE) != ARSIZE)
621 err(5, WRITE, "on pipe");
622 else if (read(fd[0], b, (ARSIZE / 2)) != (ARSIZE / 2))
623 err(5, READ, "on pipe (2nd time)");
624 else if (comp_array(a, b, (ARSIZE / 2)) != OK)
625 err(7, PIPE, "values read/written");
626 else if (read(fd[0], b, (ARSIZE / 2)) != (ARSIZE / 2))
627 err(5, READ, "on pipe 2");
628 else if (comp_array(&a[ARSIZE / 2], b, (ARSIZE / 2)) != OK)
629 err(7, PIPE, "pipe created");
631 /* Try to let the pipe make a mistake */
632 if (write(fd[0], a, ARSIZE) != FAIL)
633 err(11, WRITE, "write on fd[0]");
634 if (read(fd[1], b, ARSIZE) != FAIL) err(11, READ, "read on fd[1]");
636 try_close(fd[1], "'fd[1]'");
638 /* Now we shouldn't be able to read, because fd[1] has been closed */
639 if (read(fd[0], b, ARSIZE) != END_FILE) err(2, PIPE, "'fd[1]'");
641 try_close(fd[0], "'fd[0]'");
643 if (pipe(fd) < 0)
644 err(5, PIPE, "2nd time");
645 else {
646 /* Test lseek on a pipe: should fail */
647 if (write(fd[1], a, ARSIZE) != ARSIZE)
648 err(5, WRITE, "on pipe (2nd time)");
649 if (lseek(fd[1], 10L, SEEK_SET) != FAIL)
650 err(11, LSEEK, "lseek on a pipe");
651 else
652 check(PIPE, ESPIPE);
654 /* Eat half of the pipe: no writing should be possible */
655 try_close(fd[0], "'fd[0]' (2nd time)");
657 /* This makes UNIX crash: omit it if pdp or VAX */
658 #ifndef NOCRASH
659 if (write(fd[1], a, ARSIZE) != FAIL)
660 err(11, WRITE, "write on wrong pipe");
661 else
662 check(PIPE, EPIPE);
663 #endif
664 try_close(fd[1], "'fd[1]' (2nd time)");
667 /* BUG : *
668 * Here we planned to test if we could write 4K bytes on a pipe. *
669 * However, this was not possible to implement, because the whole *
670 * Monix system crashed when we tried to write more then 3584 bytes *
671 * (3.5K) on a pipe. That's why we try to write only 3.5K in the *
672 * folowing test. */
673 if (pipe(fd) < 0)
674 err(5, PIPE, "3rd time");
675 else {
676 for (n = 0; n < (PIPESIZE / ARSIZE); n++)
677 if (write(fd[1], a, ARSIZE) != ARSIZE)
678 err(5, WRITE, "on pipe (3rd time) 4K");
679 try_close(fd[1], "'fd[1]' (3rd time)");
681 for (n = 0; n < (PIPESIZE / ARSIZE); n++)
682 if (read(fd[0], b, ARSIZE) != ARSIZE)
683 err(5, READ, "from pipe (3rd time) 4K");
684 try_close(fd[0], "'fd[0]' (3rd time)");
687 /* Test opening a lot of files */
688 if ((n = open_alot()) != MAXOPEN) err(5, OPEN, "MAXOPEN files");
689 if (pipe(fd) != FAIL)
690 err(9, PIPE, "open");
691 else
692 check(PIPE, EMFILE);
693 if (close_alot(n) != n) err(5, CLOSE, "all opened files");
694 } /* test11 */
696 /* New page */\f
698 void comp_stats(stbf1, stbf2)
699 struct stat *stbf1, *stbf2;
701 if (stbf1->st_dev != stbf2->st_dev) err(7, "st/fst", "'dev'");
702 if (stbf1->st_ino != stbf2->st_ino) err(7, "st/fst", "'ino'");
703 if (stbf1->st_mode != stbf2->st_mode) err(7, "st/fst", "'mode'");
704 if (stbf1->st_nlink != stbf2->st_nlink) err(7, "st/fst", "'nlink'");
705 if (stbf1->st_uid != stbf2->st_uid) err(7, "st/fst", "'uid'");
706 if (stbf1->st_gid != stbf2->st_gid) err(7, "st/fst", "'gid'");
707 if (stbf1->st_rdev != stbf2->st_rdev) err(7, "st/fst", "'rdev'");
708 if (stbf1->st_size != stbf2->st_size) err(7, "st/fst", "'size'");
709 if (stbf1->st_atime != stbf2->st_atime) err(7, "st/fst", "'atime'");
710 if (stbf1->st_mtime != stbf2->st_mtime) err(7, "st/fst", "'mtime'");
711 } /* comp_stats */
713 /* New page */\f
715 /* "t5.c", created by Rene Montsma and Menno Wilcke */
717 void comp_inodes(m, m1)
718 int m, m1; /* twee filedes's */
720 struct stat stbf1, stbf2;
722 if (fstat(m, &stbf1) == OK)
723 if (fstat(m1, &stbf2) == OK) {
724 if (stbf1.st_ino != stbf2.st_ino)
725 err(7, DUP, "inode number");
726 } else
727 err(100, "comp_inodes", "cannot 'fstat' (m1)");
728 else
729 err(100, "comp_inodes", "cannot 'fstat' (m)");
730 } /* comp_inodes */
732 /* "support.c", created by Rene Montsma and Menno Wilcke */
734 /* Err, make_and_fill_dirs, init_array, clear_array, comp_array,
735 try_close, try_unlink, Remove, get_mode, check, open_alot,
736 close_alot, clean_up_the_mess.
739 /***********************************************************************
740 * EXTENDED FIONS *
741 **********************************************************************/
742 /* First extended functions (i.e. not oldfashioned monixcalls.
743 e(), nlcr(), octal.*/
745 void e(string)
746 char *string;
748 printf("Error: %s ", string);
751 void nlcr()
753 printf("\n");
756 void str(s)
757 char *s;
759 printf(s);
762 /*****************************************************************************
764 * ERR(or) messages *
766 *****************************************************************************/
767 void err(number, scall, name)
768 /* Give nice error messages */
770 char *scall, *name;
771 int number;
774 errct++;
775 if (errct > MAXERR) {
776 printf("Too many errors; test aborted\n");
777 quit();
779 e("");
780 str("\t");
781 switch (number) {
782 case 0:
783 str(scall);
784 str(": illegal initial value.");
785 break;
786 case 1:
787 str(scall);
788 str(": ");
789 str(name);
790 str(" value returned.");
791 break;
792 case 2:
793 str(scall);
794 str(": accepting illegal ");
795 str(name);
796 str(".");
797 break;
798 case 3:
799 str(scall);
800 str(": accepting non-existing file.");
801 break;
802 case 4:
803 str(scall);
804 str(": could search non-searchable dir (");
805 str(name);
806 str(").");
807 break;
808 case 5:
809 str(scall);
810 str(": cannot ");
811 str(scall);
812 str(" ");
813 str(name);
814 str(".");
815 break;
816 case 7:
817 str(scall);
818 str(": incorrect ");
819 str(name);
820 str(".");
821 break;
822 case 8:
823 str(scall);
824 str(": wrong values.");
825 break;
826 case 9:
827 str(scall);
828 str(": accepting too many ");
829 str(name);
830 str(" files.");
831 break;
832 case 10:
833 str(scall);
834 str(": even a superuser can't do anything!");
835 break;
836 case 11:
837 str(scall);
838 str(": could ");
839 str(name);
840 str(".");
841 break;
842 case 12:
843 str(scall);
844 str(": could write in non-writable dir (");
845 str(name);
846 str(").");
847 break;
848 case 13:
849 str(scall);
850 str(": wrong filedes returned (");
851 str(name);
852 str(").");
853 break;
854 case 100:
855 str(scall); /* very common */
856 str(": ");
857 str(name);
858 str(".");
859 break;
860 default: str("errornumber does not exist!\n");
862 nlcr();
863 } /* err */
865 /*****************************************************************************
867 * MAKE_AND_FILL_DIRS *
869 *****************************************************************************/
871 void make_and_fill_dirs()
872 /* Create 8 dir.'s: "d---", "d--x", "d-w-", "d-wx", "dr--", "dr-x", *
873 * "drw-", "drwx". * Then create 8 files
874 * in "drwx", and some needed files in other dirs. */
876 int mode, i;
878 for (i = 0; i < 8; i++) {
879 mkdir(dir[i], 0700);
880 chown(dir[i], USER_ID, GROUP_ID);
882 setuid(USER_ID);
883 setgid(GROUP_ID);
885 for (mode = 0; mode < 8; mode++) put_file_in_dir("drwx", mode);
887 put_file_in_dir("d-wx", RWX);
888 put_file_in_dir("dr-x", RWX);
889 put_file_in_dir("drw-", RWX);
891 chmod_8_dirs(8); /* 8 means; 8 different modes */
893 } /* make_and_fill_dirs */
895 void put_file_in_dir(dirname, mode)
896 char *dirname;
897 int mode;
898 /* Fill directory 'dirname' with file with mode 'mode'. */
900 int nr;
902 if (chdir(dirname) != OK)
903 err(5, CHDIR, "to dirname (put_f_in_dir)");
904 else {
905 /* Creat the file */
906 if ((nr = creat(fnames[mode], mode * 0100)) < 0)
907 err(13, CREAT, fnames[mode]);
908 else
909 try_close(nr, fnames[mode]);
911 if (chdir("..") != OK)
912 err(5, CHDIR, "to previous dir (put_f_in_dir)");
914 } /* put_file_in_dir */
916 /*****************************************************************************
918 * MISCELLANEOUS *
920 *(all about arrays, 'try_close', 'try_unlink', 'Remove', 'get_mode')*
922 *****************************************************************************/
924 void init_array(a)
925 char *a;
927 int i;
929 i = 0;
930 while (i++ < ARSIZE) *a++ = 'a' + (i % 26);
931 } /* init_array */
933 void clear_array(b)
934 char *b;
936 int i;
938 i = 0;
939 while (i++ < ARSIZE) *b++ = '0';
941 } /* clear_array */
943 int comp_array(a, b, range)
944 char *a, *b;
945 int range;
947 if ((range < 0) || (range > ARSIZE)) {
948 err(100, "comp_array", "illegal range");
949 return(FAIL);
950 } else {
951 while (range-- && (*a++ == *b++));
952 if (*--a == *--b)
953 return(OK);
954 else
955 return(FAIL);
957 } /* comp_array */
959 void try_close(filedes, name)
960 int filedes;
961 char *name;
963 if (close(filedes) != OK) err(5, CLOSE, name);
964 } /* try_close */
966 void try_unlink(fname)
967 char *fname;
969 if (unlink(fname) != 0) err(5, UNLINK, fname);
970 } /* try_unlink */
972 void Remove(fdes, fname)
973 int fdes;
974 char *fname;
976 try_close(fdes, fname);
977 try_unlink(fname);
978 } /* Remove */
980 int get_mode(name)
981 char *name;
983 struct stat stbf1;
985 if (stat(name, &stbf1) != OK) {
986 err(5, STAT, name);
987 return(stbf1.st_mode); /* return a mode which will cause *
988 * error in the calling function *
989 * (file/dir bit) */
990 } else
991 return(stbf1.st_mode & 07777); /* take last 4 bits */
992 } /* get_mode */
994 /*****************************************************************************
996 * CHECK *
998 *****************************************************************************/
1000 void check(scall, number)
1001 int number;
1002 char *scall;
1004 if (errno != number) {
1005 e(NIL);
1006 str("\t");
1007 str(scall);
1008 str(": bad errno-value: ");
1009 put(errno);
1010 str(" should have been: ");
1011 put(number);
1012 nlcr();
1014 } /* check */
1016 void put(nr)
1017 int nr;
1019 switch (nr) {
1020 case 0: str("unused"); break;
1021 case 1: str("EPERM"); break;
1022 case 2: str("ENOENT"); break;
1023 case 3: str("ESRCH"); break;
1024 case 4: str("EINTR"); break;
1025 case 5: str("EIO"); break;
1026 case 6: str("ENXIO"); break;
1027 case 7: str("E2BIG"); break;
1028 case 8: str("ENOEXEC"); break;
1029 case 9: str("EBADF"); break;
1030 case 10: str("ECHILD"); break;
1031 case 11: str("EAGAIN"); break;
1032 case 12: str("ENOMEM"); break;
1033 case 13: str("EACCES"); break;
1034 case 14: str("EFAULT"); break;
1035 case 15: str("ENOTBLK"); break;
1036 case 16: str("EBUSY"); break;
1037 case 17: str("EEXIST"); break;
1038 case 18: str("EXDEV"); break;
1039 case 19: str("ENODEV"); break;
1040 case 20: str("ENOTDIR"); break;
1041 case 21: str("EISDIR"); break;
1042 case 22: str("EINVAL"); break;
1043 case 23: str("ENFILE"); break;
1044 case 24: str("EMFILE"); break;
1045 case 25: str("ENOTTY"); break;
1046 case 26: str("ETXTBSY"); break;
1047 case 27: str("EFBIG"); break;
1048 case 28: str("ENOSPC"); break;
1049 case 29: str("ESPIPE"); break;
1050 case 30: str("EROFS"); break;
1051 case 31: str("EMLINK"); break;
1052 case 32: str("EPIPE"); break;
1053 case 33: str("EDOM"); break;
1054 case 34: str("ERANGE"); break;
1058 /*****************************************************************************
1060 * ALOT-functions *
1062 *****************************************************************************/
1064 int open_alot()
1066 int i;
1068 for (i = 0; i < MAXOPEN; i++)
1069 if (open(file[i], R) == FAIL) break;
1070 if (i == 0) err(5, "open_alot", "at all");
1071 return(i);
1072 } /* open_alot */
1074 int close_alot(number)
1075 int number;
1077 int i, count = 0;
1079 if (number > MAXOPEN)
1080 err(5, "close_alot", "accept this argument");
1081 else
1082 for (i = FF; i < number + FF; i++)
1083 if (close(i) != OK) count++;
1085 return(number - count); /* return number of closed files */
1086 } /* close_alot */
1088 /*****************************************************************************
1090 * CLEAN UP THE MESS *
1092 *****************************************************************************/
1094 void clean_up_the_mess()
1096 int i;
1097 char dirname[6];
1099 /* First remove 'a lot' files */
1100 for (i = 0; i < MAXOPEN; i++) try_unlink(file[i]);
1102 /* Unlink the files in dir 'drwx' */
1103 if (chdir("drwx") != OK)
1104 err(5, CHDIR, "to 'drwx'");
1105 else {
1106 for (i = 0; i < 8; i++) try_unlink(fnames[i]);
1107 if (chdir("..") != OK) err(5, CHDIR, "to '..'");
1110 /* Before unlinking files in some dirs, make them writable */
1111 chmod_8_dirs(RWX);
1113 /* Unlink files in other dirs */
1114 try_unlink("d-wx/rwx");
1115 try_unlink("dr-x/rwx");
1116 try_unlink("drw-/rwx");
1118 /* Unlink dirs */
1119 for (i = 0; i < 8; i++) {
1120 strcpy(dirname, "d");
1121 strcat(dirname, fnames[i]);
1123 /* 'dirname' contains the directoryname */
1124 rmdir(dirname);
1127 /* FINISH */
1128 } /* clean_up_the_mess */
1130 void chmod_8_dirs(sw)
1131 int sw; /* if switch == 8, give all different
1132 * mode,else the same mode */
1134 int mode;
1135 int i;
1137 if (sw == 8)
1138 mode = 0;
1139 else
1140 mode = sw;
1142 for (i = 0; i < 8; i++) {
1143 chmod(dir[i], 040000 + mode * 0100);
1144 if (sw == 8) mode++;
1148 void quit()
1151 chdir("..");
1152 system("rm -rf DIR*");
1154 if (errct == 0) {
1155 printf("ok\n");
1156 exit(0);
1157 } else {
1158 printf("%d errors\n", errct);
1159 exit(1);