Joren's proposed fix for a too-conservative split point selection.
[minix3.git] / test / test17.c
blobbf0310aee74874fc9a2daf58abc62cc54d0cc845
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 int n, mask;
124 sync();
125 if (geteuid() == 0 || getuid() == 0) {
126 printf("Test 17 cannot run as root; test aborted\n");
127 exit(1);
130 system("rm -rf DIR_18; mkdir DIR_18");
131 chdir("DIR_18");
133 mask = (argc == 2 ? atoi(argv[1]) : 0xFFFF);
135 if (fork()) {
136 printf("Test 17 ");
137 fflush(stdout);
139 wait(&n);
140 clean_up_the_mess();
141 quit();
142 } else {
143 test(mask);
144 exit(0);
146 return(-1); /* impossible */
149 void test(mask)
150 int mask;
152 umask(0); /* not honest, but i always forget */
154 if (mask & 00001) test01();
155 if (mask & 00002) make_and_fill_dirs();
156 if (mask & 00004) test02();
157 if (mask & 00010) test08();
158 if (mask & 00020) test09();
159 if (mask & 00040) test10();
160 if (mask & 00100) test11();
161 umask(022);
162 } /* test */
164 /* "t1.c" created by Rene Montsma and Menno Wilcke */
166 /*****************************************************************************
167 * test UMASK *
168 ****************************************************************************/
169 void test01()
171 int oldvalue, newvalue, tempvalue;
172 int nr;
174 if ((oldvalue = umask(0777)) != 0) err(0, UMASK, NIL);
176 /* Special test: only the lower 9 bits (protection bits) may part- *
177 * icipate. ~0777 means: 111 000 000 000. Giving this to umask must*
178 * not change any value. */
180 if ((newvalue = umask(~0777)) != 0777) err(1, UMASK, "illegal");
181 if (oldvalue == newvalue) err(11, UMASK, "not change mask");
183 if ((tempvalue = umask(0)) != 0) err(2, UMASK, "values");
185 /* Now test all possible modes of umask on a file */
186 for (newvalue = MASK; newvalue >= 0; newvalue -= 0111) {
187 tempvalue = umask(newvalue);
188 if (tempvalue != oldvalue) {
189 err(1, UMASK, "illegal");
190 break; /* no use trying more */
191 } else if ((nr = creat("file01", 0777)) < 0)
192 err(5, CREAT, "'file01'");
193 else {
194 try_close(nr, "'file01'");
195 if (get_mode("file01") != (MASK & ~newvalue))
196 err(7, UMASK, "mode computed");
197 try_unlink("file01");
199 oldvalue = newvalue;
202 /* The loop has terminated with umask(0) */
203 if ((tempvalue = umask(0)) != 0)
204 err(7, UMASK, "umask may influence rest of tests!");
205 } /* test01 */
207 /*****************************************************************************
208 * test CREAT *
209 ****************************************************************************/
210 void test02()
212 int n, n1, mode;
213 char a[ARSIZE], b[ARSIZE];
214 struct stat stbf1;
216 mode = 0;
217 /* Create twenty files, check filedes */
218 for (n = 0; n < MAXOPEN; n++) {
219 if (creat(file[n], mode) != FF + n)
220 err(13, CREAT, file[n]);
221 else {
222 if (get_mode(file[n]) != mode)
223 err(7, CREAT, "mode set while creating many files");
225 /* Change mode of file to standard mode, we want to *
226 * use a lot (20) of files to be opened later, see *
227 * open_alot(), close_alot(). */
228 if (chmod(file[n], 0700) != OK) err(5, CHMOD, file[n]);
231 mode = (mode + 0100) % 01000;
234 /* Already twenty files opened; opening another has to fail */
235 if (creat("file02", 0777) != FAIL)
236 err(9, CREAT, "created");
237 else
238 check(CREAT, EMFILE);
240 /* Close all files: seems blunt, but it isn't because we've *
241 * checked all fd's already */
242 if ((n = close_alot(MAXOPEN)) < MAXOPEN) err(5, CLOSE, "MAXOPEN files");
244 /* Creat 1 file twice; check */
245 if ((n = creat("file02", 0777)) < 0)
246 err(5, CREAT, "'file02'");
247 else {
248 init_array(a);
249 if (write(n, a, ARSIZE) != ARSIZE) err(1, WRITE, "bad");
251 if ((n1 = creat("file02", 0755)) < 0) /* receate 'file02' */
252 err(5, CREAT, "'file02' (2nd time)");
253 else {
254 /* Fd should be at the top after recreation */
255 if (lseek(n1, 0L, SEEK_END) != 0)
256 err(11, CREAT, "not truncate file by recreation");
257 else {
258 /* Try to write on recreated file */
259 clear_array(b);
261 if (lseek(n1, 0L, SEEK_SET) != 0)
262 err(5, LSEEK, "to top of 2nd fd 'file02'");
263 if (write(n1, a, ARSIZE) != ARSIZE)
264 err(1, WRITE, "(2) bad");
266 /* In order to read we've to close and open again */
267 try_close(n1, "'file02' (2nd creation)");
268 if ((n1 = open("file02", RW)) < 0)
269 err(5, OPEN, "'file02' (2nd recreation)");
271 /* Continue */
272 if (lseek(n1, 0L, SEEK_SET) != 0)
273 err(5, LSEEK, "to top 'file02'(2nd fd) (2)");
274 if (read(n1, b, ARSIZE) != ARSIZE)
275 err(1, READ, "wrong");
277 if (comp_array(a, b, ARSIZE) != OK) err(11, CREAT,
278 "not really truncate file by recreation");
280 if (get_mode("file02") != 0777)
281 err(11, CREAT, "not maintain mode by recreation");
282 try_close(n1, "recreated 'file02'");
285 Remove(n, "file02");
288 /* Give 'creat' wrong input: dir not searchable */
289 if (creat("drw-/file02", 0777) != FAIL)
290 err(4, CREAT, "'drw-'");
291 else
292 check(CREAT, EACCES);
294 /* Dir not writable */
295 if (creat("dr-x/file02", 0777) != FAIL)
296 err(12, CREAT, "'dr-x/file02'");
297 else
298 check(CREAT, EACCES);
300 /* File not writable */
301 if (creat("drwx/r-x", 0777) != FAIL)
302 err(11, CREAT, "recreate non-writable file");
303 else
304 check(CREAT, EACCES);
306 /* Try to creat a dir */
307 if ((n = creat("dir", 040777)) != FAIL) {
308 if (fstat(n, &stbf1) != OK)
309 err(5, FSTAT, "'dir'");
310 else if (stbf1.st_mode != (mode_t) 0100777)
311 /* cast because mode is negative :-( */
312 err(11, CREAT, "'creat' a new directory");
313 Remove(n, "dir");
316 /* We don't consider it to be a bug when creat * does not accept
317 * tricky modes */
319 /* File is an existing dir */
320 if (creat("drwx", 0777) != FAIL)
321 err(11, CREAT, "create an existing dir!");
322 else
323 check(CREAT, EISDIR);
324 } /* test02 */
326 void test08()
328 /* Test chdir to searchable dir */
329 if (chdir("drwx") != OK)
330 err(5, CHDIR, "to accessible dir");
331 else if (chdir("..") != OK)
332 err(11, CHDIR, "not return to '..'");
334 /* Check the chdir(".") and chdir("..") mechanism */
335 if (chdir("drwx") != OK)
336 err(5, CHDIR, "to 'drwx'");
337 else {
338 if (chdir(".") != OK) err(5, CHDIR, "to working dir (.)");
340 /* If we still are in 'drwx' , we should be able to access *
341 * file 'rwx'. */
342 if (access("rwx", 0) != OK) err(5, CHDIR, "rightly to '.'");
344 /* Try to return to previous dir ('/' !!) */
345 if (chdir("././../././d--x/../d--x/././..") != OK)
346 err(5, CHDIR, "to motherdir (..)");
348 /* Check whether we are back in '/' */
349 if (chdir("d--x") != OK) err(5, CHDIR, "rightly to a '..'");
352 /* Return to '..' */
353 if (chdir("..") != OK) err(5, CHDIR, "to '..'");
355 if (chdir("././././drwx") != OK)
356 err(11, CHDIR, "not follow a path");
357 else if (chdir("././././..") != OK)
358 err(11, CHDIR, "not return to path");
360 /* Try giving chdir wrong parameters */
361 if (chdir("drwx/rwx") != FAIL)
362 err(11, CHDIR, "chdir to a file");
363 else
364 check(CHDIR, ENOTDIR);
366 if (chdir("drw-") != FAIL)
367 err(4, CHDIR, "'/drw-'");
368 else
369 check(CHDIR, EACCES);
371 /* To be sure: return to root */
372 /* If (chdir("/") != OK) err(5, CHDIR, "to '/' (2nd time)"); */
373 } /* test08 */
375 /* New page */\f
376 /*****************************************************************************
377 * test CHMOD *
378 ****************************************************************************/
379 void test09()
381 int n;
383 /* Prepare file09 */
384 if ((n = creat("drwx/file09", 0644)) != FF) err(5, CREAT, "'drwx/file09'");
386 try_close(n, "'file09'");
388 /* Try to chmod a file, check and restore old values, check */
389 if (chmod("drwx/file09", 0700) != OK)
390 err(5, CHMOD, "'drwx/file09'"); /* set rwx */
391 else {
392 /* Check protection */
393 if (get_mode("drwx/file09") != 0700) err(7, CHMOD, "mode");
395 /* Test if chmod accepts just filenames too */
396 if (chdir("drwx") != OK)
397 err(5, CHDIR, "to '/drwx'");
398 else if (chmod("file09", 0177) != OK) /* restore oldies */
399 err(5, CHMOD, "'h1'");
400 else
401 /* Check if value has been restored */
402 if (get_mode("../drwx/file09") != 0177)
403 err(7, CHMOD, "restored mode");
406 /* Try setuid and setgid */
407 if ((chmod("file09", 04777) != OK) || (get_mode("file09") != 04777))
408 err(11, CHMOD, "not set uid-bit");
409 if ((chmod("file09", 02777) != OK) || (get_mode("file09") != 02777))
410 err(11, CHMOD, "not set gid-bit");
412 /* Remove testfile */
413 try_unlink("file09");
415 if (chdir("..") != OK) err(5, CHDIR, "to '..'");
417 /* Try to chmod directory */
418 if (chmod("d---", 0777) != OK)
419 err(5, CHMOD, "dir 'd---'");
420 else {
421 if (get_mode("d---") != 0777) err(7, CHMOD, "protection value");
422 if (chmod("d---", 0000) != OK) err(5, CHMOD, "dir 'a' 2nd time");
424 /* Check if old value has been restored */
425 if (get_mode("d---") != 0000)
426 err(7, CHMOD, "restored protection value");
429 /* Try to make chmod failures */
431 /* We still are in dir root */
432 /* Wrong filename */
433 if (chmod("non-file", 0777) != FAIL)
434 err(3, CHMOD, NIL);
435 else
436 check(CHMOD, ENOENT);
438 } /* test 09 */
440 /* New page */\f
442 /* "t4.c", created by Rene Montsma and Menno Wilcke */
444 /*****************************************************************************
445 * test LINK/UNLINK *
446 ****************************************************************************/
447 void test10()
449 int n, n1;
450 char a[ARSIZE], b[ARSIZE], *f, *lf;
452 f = "file10";
453 lf = "linkfile10";
455 if ((n = creat(f, 0702)) != FF) /* no other open files */
456 err(13, CREAT, f);
457 else {
458 /* Now link correctly */
459 if (link(f, lf) != OK)
460 err(5, LINK, lf);
461 else if ((n1 = open(lf, RW)) < 0)
462 err(5, OPEN, "'linkfile10'");
463 else {
464 init_array(a);
465 clear_array(b);
467 /* Write on 'file10' means being able to * read
468 * through linked filedescriptor */
469 if (write(n, a, ARSIZE) != ARSIZE) err(1, WRITE, "bad");
470 if (read(n1, b, ARSIZE) != ARSIZE) err(1, READ, "bad");
471 if (comp_array(a, b, ARSIZE) != OK) err(8, "r/w", NIL);
473 /* Clean up: unlink and close (twice): */
474 Remove(n, f);
475 try_close(n1, "'linkfile10'");
477 /* Check if "linkfile" exists and the info * on it
478 * is correct ('file' has been deleted) */
479 if ((n1 = open(lf, R)) < 0)
480 err(5, OPEN, "'linkfile10'");
481 else {
482 /* See if 'linkfile' still contains 0..511 ? */
484 clear_array(b);
485 if (read(n1, b, ARSIZE) != ARSIZE)
486 err(1, READ, "bad");
487 if (comp_array(a, b, ARSIZE) != OK)
488 err(8, "r/w", NIL);
490 try_close(n1, "'linkfile10' 2nd time");
491 try_unlink(lf);
496 /* Try if unlink fails with incorrect parameters */
497 /* File does not exist: */
498 if (unlink("non-file") != FAIL)
499 err(2, UNLINK, "name");
500 else
501 check(UNLINK, ENOENT);
503 /* Dir can't be written */
504 if (unlink("dr-x/rwx") != FAIL)
505 err(11, UNLINK, "could unlink in non-writable dir.");
506 else
507 check(UNLINK, EACCES);
509 /* Try to unlink a dir being user */
510 if (unlink("drwx") != FAIL)
511 err(11, UNLINK, "unlink dir's as user");
512 else
513 check(UNLINK, EPERM);
515 /* Try giving link wrong input */
517 /* First try if link fails with incorrect parameters * name1 does not
518 * exist. */
519 if (link("non-file", "linkfile") != FAIL)
520 err(2, LINK, "1st name");
521 else
522 check(LINK, ENOENT);
524 /* Name2 exists already */
525 if (link("drwx/rwx", "drwx/rw-") != FAIL)
526 err(2, LINK, "2nd name");
527 else
528 check(LINK, EEXIST);
530 /* Directory of name2 not writable: */
531 if (link("drwx/rwx", "dr-x/linkfile") != FAIL)
532 err(11, LINK, "link non-writable file");
533 else
534 check(LINK, EACCES);
536 /* Try to link a dir, being a user */
537 if (link("drwx", "linkfile") != FAIL)
538 err(11, LINK, "link a dir without superuser!");
539 else
540 check(LINK, EPERM);
542 /* File has too many links */
543 if ((n = link_alot("drwx/rwx")) != LINKCOUNT - 1) /* file already has one
544 * link */
545 err(5, LINK, "many files");
546 if (unlink_alot(n) != n) err(5, UNLINK, "all linked files");
548 } /* test10 */
550 int link_alot(bigboss)
551 char *bigboss;
553 int i;
554 static char employee[6] = "aaaaa";
556 /* Every file has already got 1 link, so link 0176 times */
557 for (i = 1; i < LINKCOUNT; i++) {
558 if (link(bigboss, employee) != OK)
559 break;
560 else
561 get_new(employee);
564 return(i - 1); /* number of linked files */
565 } /* link_alot */
567 int unlink_alot(number)
568 int number; /* number of files to be unlinked */
570 int j;
571 static char employee[6] = "aaaaa";
573 for (j = 0; j < number; j++) {
574 if (unlink(employee) != OK)
575 break;
576 else
577 get_new(employee);
580 return(j); /* return number of unlinked files */
581 } /* unlink_alot */
583 void get_new(name)
584 char name[];
585 /* Every call changes string 'name' to a string alphabetically *
586 * higher. Start with "aaaaa", next value: "aaaab" . *
587 * N.B. after "aaaaz" comes "aaabz" and not "aaaba" (not needed). *
588 * The last possibility will be "zzzzz". *
589 * Total # possibilities: 26+25*4 = 126 = MAXLINK -1 (exactly needed) */
591 int i;
593 for (i = 4; i >= 0; i--)
594 if (name[i] != 'z') {
595 name[i]++;
596 break;
598 } /* get_new */
600 /* New page */\f
602 /*****************************************************************************
603 * test PIPE *
604 ****************************************************************************/
605 void test11()
607 int n, fd[2];
608 char a[ARSIZE], b[ARSIZE];
610 if (pipe(fd) != OK)
611 err(13, PIPE, NIL);
612 else {
613 /* Try reading and writing on a pipe */
614 init_array(a);
615 clear_array(b);
617 if (write(fd[1], a, ARSIZE) != ARSIZE)
618 err(5, WRITE, "on pipe");
619 else if (read(fd[0], b, (ARSIZE / 2)) != (ARSIZE / 2))
620 err(5, READ, "on pipe (2nd time)");
621 else if (comp_array(a, b, (ARSIZE / 2)) != OK)
622 err(7, PIPE, "values read/written");
623 else if (read(fd[0], b, (ARSIZE / 2)) != (ARSIZE / 2))
624 err(5, READ, "on pipe 2");
625 else if (comp_array(&a[ARSIZE / 2], b, (ARSIZE / 2)) != OK)
626 err(7, PIPE, "pipe created");
628 /* Try to let the pipe make a mistake */
629 if (write(fd[0], a, ARSIZE) != FAIL)
630 err(11, WRITE, "write on fd[0]");
631 if (read(fd[1], b, ARSIZE) != FAIL) err(11, READ, "read on fd[1]");
633 try_close(fd[1], "'fd[1]'");
635 /* Now we shouldn't be able to read, because fd[1] has been closed */
636 if (read(fd[0], b, ARSIZE) != END_FILE) err(2, PIPE, "'fd[1]'");
638 try_close(fd[0], "'fd[0]'");
640 if (pipe(fd) < 0)
641 err(5, PIPE, "2nd time");
642 else {
643 /* Test lseek on a pipe: should fail */
644 if (write(fd[1], a, ARSIZE) != ARSIZE)
645 err(5, WRITE, "on pipe (2nd time)");
646 if (lseek(fd[1], 10L, SEEK_SET) != FAIL)
647 err(11, LSEEK, "lseek on a pipe");
648 else
649 check(PIPE, ESPIPE);
651 /* Eat half of the pipe: no writing should be possible */
652 try_close(fd[0], "'fd[0]' (2nd time)");
654 /* This makes UNIX crash: omit it if pdp or VAX */
655 #ifndef NOCRASH
656 if (write(fd[1], a, ARSIZE) != FAIL)
657 err(11, WRITE, "write on wrong pipe");
658 else
659 check(PIPE, EPIPE);
660 #endif
661 try_close(fd[1], "'fd[1]' (2nd time)");
664 /* BUG : *
665 * Here we planned to test if we could write 4K bytes on a pipe. *
666 * However, this was not possible to implement, because the whole *
667 * Monix system crashed when we tried to write more then 3584 bytes *
668 * (3.5K) on a pipe. That's why we try to write only 3.5K in the *
669 * folowing test. */
670 if (pipe(fd) < 0)
671 err(5, PIPE, "3rd time");
672 else {
673 for (n = 0; n < (PIPESIZE / ARSIZE); n++)
674 if (write(fd[1], a, ARSIZE) != ARSIZE)
675 err(5, WRITE, "on pipe (3rd time) 4K");
676 try_close(fd[1], "'fd[1]' (3rd time)");
678 for (n = 0; n < (PIPESIZE / ARSIZE); n++)
679 if (read(fd[0], b, ARSIZE) != ARSIZE)
680 err(5, READ, "from pipe (3rd time) 4K");
681 try_close(fd[0], "'fd[0]' (3rd time)");
684 /* Test opening a lot of files */
685 if ((n = open_alot()) != MAXOPEN) err(5, OPEN, "MAXOPEN files");
686 if (pipe(fd) != FAIL)
687 err(9, PIPE, "open");
688 else
689 check(PIPE, EMFILE);
690 if (close_alot(n) != n) err(5, CLOSE, "all opened files");
691 } /* test11 */
693 /* New page */\f
695 void comp_stats(stbf1, stbf2)
696 struct stat *stbf1, *stbf2;
698 if (stbf1->st_dev != stbf2->st_dev) err(7, "st/fst", "'dev'");
699 if (stbf1->st_ino != stbf2->st_ino) err(7, "st/fst", "'ino'");
700 if (stbf1->st_mode != stbf2->st_mode) err(7, "st/fst", "'mode'");
701 if (stbf1->st_nlink != stbf2->st_nlink) err(7, "st/fst", "'nlink'");
702 if (stbf1->st_uid != stbf2->st_uid) err(7, "st/fst", "'uid'");
703 if (stbf1->st_gid != stbf2->st_gid) err(7, "st/fst", "'gid'");
704 if (stbf1->st_rdev != stbf2->st_rdev) err(7, "st/fst", "'rdev'");
705 if (stbf1->st_size != stbf2->st_size) err(7, "st/fst", "'size'");
706 if (stbf1->st_atime != stbf2->st_atime) err(7, "st/fst", "'atime'");
707 if (stbf1->st_mtime != stbf2->st_mtime) err(7, "st/fst", "'mtime'");
708 } /* comp_stats */
710 /* New page */\f
712 /* "t5.c", created by Rene Montsma and Menno Wilcke */
714 void comp_inodes(m, m1)
715 int m, m1; /* twee filedes's */
717 struct stat stbf1, stbf2;
719 if (fstat(m, &stbf1) == OK)
720 if (fstat(m1, &stbf2) == OK) {
721 if (stbf1.st_ino != stbf2.st_ino)
722 err(7, DUP, "inode number");
723 } else
724 err(100, "comp_inodes", "cannot 'fstat' (m1)");
725 else
726 err(100, "comp_inodes", "cannot 'fstat' (m)");
727 } /* comp_inodes */
729 /* "support.c", created by Rene Montsma and Menno Wilcke */
731 /* Err, make_and_fill_dirs, init_array, clear_array, comp_array,
732 try_close, try_unlink, Remove, get_mode, check, open_alot,
733 close_alot, clean_up_the_mess.
736 /***********************************************************************
737 * EXTENDED FIONS *
738 **********************************************************************/
739 /* First extended functions (i.e. not oldfashioned monixcalls.
740 e(), nlcr(), octal.*/
742 void e(string)
743 char *string;
745 printf("Error: %s ", string);
748 void nlcr()
750 printf("\n");
753 void str(s)
754 char *s;
756 printf(s);
759 /*****************************************************************************
761 * ERR(or) messages *
763 *****************************************************************************/
764 void err(number, scall, name)
765 /* Give nice error messages */
767 char *scall, *name;
768 int number;
771 errct++;
772 if (errct > MAXERR) {
773 printf("Too many errors; test aborted\n");
774 quit();
776 e("");
777 str("\t");
778 switch (number) {
779 case 0:
780 str(scall);
781 str(": illegal initial value.");
782 break;
783 case 1:
784 str(scall);
785 str(": ");
786 str(name);
787 str(" value returned.");
788 break;
789 case 2:
790 str(scall);
791 str(": accepting illegal ");
792 str(name);
793 str(".");
794 break;
795 case 3:
796 str(scall);
797 str(": accepting non-existing file.");
798 break;
799 case 4:
800 str(scall);
801 str(": could search non-searchable dir (");
802 str(name);
803 str(").");
804 break;
805 case 5:
806 str(scall);
807 str(": cannot ");
808 str(scall);
809 str(" ");
810 str(name);
811 str(".");
812 break;
813 case 7:
814 str(scall);
815 str(": incorrect ");
816 str(name);
817 str(".");
818 break;
819 case 8:
820 str(scall);
821 str(": wrong values.");
822 break;
823 case 9:
824 str(scall);
825 str(": accepting too many ");
826 str(name);
827 str(" files.");
828 break;
829 case 10:
830 str(scall);
831 str(": even a superuser can't do anything!");
832 break;
833 case 11:
834 str(scall);
835 str(": could ");
836 str(name);
837 str(".");
838 break;
839 case 12:
840 str(scall);
841 str(": could write in non-writable dir (");
842 str(name);
843 str(").");
844 break;
845 case 13:
846 str(scall);
847 str(": wrong filedes returned (");
848 str(name);
849 str(").");
850 break;
851 case 100:
852 str(scall); /* very common */
853 str(": ");
854 str(name);
855 str(".");
856 break;
857 default: str("errornumber does not exist!\n");
859 nlcr();
860 } /* err */
862 /*****************************************************************************
864 * MAKE_AND_FILL_DIRS *
866 *****************************************************************************/
868 void make_and_fill_dirs()
869 /* Create 8 dir.'s: "d---", "d--x", "d-w-", "d-wx", "dr--", "dr-x", *
870 * "drw-", "drwx". * Then create 8 files
871 * in "drwx", and some needed files in other dirs. */
873 int mode, i;
875 for (i = 0; i < 8; i++) {
876 mkdir(dir[i], 0700);
877 chown(dir[i], USER_ID, GROUP_ID);
879 setuid(USER_ID);
880 setgid(GROUP_ID);
882 for (mode = 0; mode < 8; mode++) put_file_in_dir("drwx", mode);
884 put_file_in_dir("d-wx", RWX);
885 put_file_in_dir("dr-x", RWX);
886 put_file_in_dir("drw-", RWX);
888 chmod_8_dirs(8); /* 8 means; 8 different modes */
890 } /* make_and_fill_dirs */
892 void put_file_in_dir(dirname, mode)
893 char *dirname;
894 int mode;
895 /* Fill directory 'dirname' with file with mode 'mode'. */
897 int nr;
899 if (chdir(dirname) != OK)
900 err(5, CHDIR, "to dirname (put_f_in_dir)");
901 else {
902 /* Creat the file */
903 if ((nr = creat(fnames[mode], mode * 0100)) < 0)
904 err(13, CREAT, fnames[mode]);
905 else
906 try_close(nr, fnames[mode]);
908 if (chdir("..") != OK)
909 err(5, CHDIR, "to previous dir (put_f_in_dir)");
911 } /* put_file_in_dir */
913 /*****************************************************************************
915 * MISCELLANEOUS *
917 *(all about arrays, 'try_close', 'try_unlink', 'Remove', 'get_mode')*
919 *****************************************************************************/
921 void init_array(a)
922 char *a;
924 int i;
926 i = 0;
927 while (i++ < ARSIZE) *a++ = 'a' + (i % 26);
928 } /* init_array */
930 void clear_array(b)
931 char *b;
933 int i;
935 i = 0;
936 while (i++ < ARSIZE) *b++ = '0';
938 } /* clear_array */
940 int comp_array(a, b, range)
941 char *a, *b;
942 int range;
944 if ((range < 0) || (range > ARSIZE)) {
945 err(100, "comp_array", "illegal range");
946 return(FAIL);
947 } else {
948 while (range-- && (*a++ == *b++));
949 if (*--a == *--b)
950 return(OK);
951 else
952 return(FAIL);
954 } /* comp_array */
956 void try_close(filedes, name)
957 int filedes;
958 char *name;
960 if (close(filedes) != OK) err(5, CLOSE, name);
961 } /* try_close */
963 void try_unlink(fname)
964 char *fname;
966 if (unlink(fname) != 0) err(5, UNLINK, fname);
967 } /* try_unlink */
969 void Remove(fdes, fname)
970 int fdes;
971 char *fname;
973 try_close(fdes, fname);
974 try_unlink(fname);
975 } /* Remove */
977 int get_mode(name)
978 char *name;
980 struct stat stbf1;
982 if (stat(name, &stbf1) != OK) {
983 err(5, STAT, name);
984 return(stbf1.st_mode); /* return a mode which will cause *
985 * error in the calling function *
986 * (file/dir bit) */
987 } else
988 return(stbf1.st_mode & 07777); /* take last 4 bits */
989 } /* get_mode */
991 /*****************************************************************************
993 * CHECK *
995 *****************************************************************************/
997 void check(scall, number)
998 int number;
999 char *scall;
1001 if (errno != number) {
1002 e(NIL);
1003 str("\t");
1004 str(scall);
1005 str(": bad errno-value: ");
1006 put(errno);
1007 str(" should have been: ");
1008 put(number);
1009 nlcr();
1011 } /* check */
1013 void put(nr)
1014 int nr;
1016 switch (nr) {
1017 case 0: str("unused"); break;
1018 case 1: str("EPERM"); break;
1019 case 2: str("ENOENT"); break;
1020 case 3: str("ESRCH"); break;
1021 case 4: str("EINTR"); break;
1022 case 5: str("EIO"); break;
1023 case 6: str("ENXIO"); break;
1024 case 7: str("E2BIG"); break;
1025 case 8: str("ENOEXEC"); break;
1026 case 9: str("EBADF"); break;
1027 case 10: str("ECHILD"); break;
1028 case 11: str("EAGAIN"); break;
1029 case 12: str("ENOMEM"); break;
1030 case 13: str("EACCES"); break;
1031 case 14: str("EFAULT"); break;
1032 case 15: str("ENOTBLK"); break;
1033 case 16: str("EBUSY"); break;
1034 case 17: str("EEXIST"); break;
1035 case 18: str("EXDEV"); break;
1036 case 19: str("ENODEV"); break;
1037 case 20: str("ENOTDIR"); break;
1038 case 21: str("EISDIR"); break;
1039 case 22: str("EINVAL"); break;
1040 case 23: str("ENFILE"); break;
1041 case 24: str("EMFILE"); break;
1042 case 25: str("ENOTTY"); break;
1043 case 26: str("ETXTBSY"); break;
1044 case 27: str("EFBIG"); break;
1045 case 28: str("ENOSPC"); break;
1046 case 29: str("ESPIPE"); break;
1047 case 30: str("EROFS"); break;
1048 case 31: str("EMLINK"); break;
1049 case 32: str("EPIPE"); break;
1050 case 33: str("EDOM"); break;
1051 case 34: str("ERANGE"); break;
1055 /*****************************************************************************
1057 * ALOT-functions *
1059 *****************************************************************************/
1061 int open_alot()
1063 int i;
1065 for (i = 0; i < MAXOPEN; i++)
1066 if (open(file[i], R) == FAIL) break;
1067 if (i == 0) err(5, "open_alot", "at all");
1068 return(i);
1069 } /* open_alot */
1071 int close_alot(number)
1072 int number;
1074 int i, count = 0;
1076 if (number > MAXOPEN)
1077 err(5, "close_alot", "accept this argument");
1078 else
1079 for (i = FF; i < number + FF; i++)
1080 if (close(i) != OK) count++;
1082 return(number - count); /* return number of closed files */
1083 } /* close_alot */
1085 /*****************************************************************************
1087 * CLEAN UP THE MESS *
1089 *****************************************************************************/
1091 void clean_up_the_mess()
1093 int i;
1094 char dirname[6];
1096 /* First remove 'a lot' files */
1097 for (i = 0; i < MAXOPEN; i++) try_unlink(file[i]);
1099 /* Unlink the files in dir 'drwx' */
1100 if (chdir("drwx") != OK)
1101 err(5, CHDIR, "to 'drwx'");
1102 else {
1103 for (i = 0; i < 8; i++) try_unlink(fnames[i]);
1104 if (chdir("..") != OK) err(5, CHDIR, "to '..'");
1107 /* Before unlinking files in some dirs, make them writable */
1108 chmod_8_dirs(RWX);
1110 /* Unlink files in other dirs */
1111 try_unlink("d-wx/rwx");
1112 try_unlink("dr-x/rwx");
1113 try_unlink("drw-/rwx");
1115 /* Unlink dirs */
1116 for (i = 0; i < 8; i++) {
1117 strcpy(dirname, "d");
1118 strcat(dirname, fnames[i]);
1120 /* 'dirname' contains the directoryname */
1121 rmdir(dirname);
1124 /* FINISH */
1125 } /* clean_up_the_mess */
1127 void chmod_8_dirs(sw)
1128 int sw; /* if switch == 8, give all different
1129 * mode,else the same mode */
1131 int mode;
1132 int i;
1134 if (sw == 8)
1135 mode = 0;
1136 else
1137 mode = sw;
1139 for (i = 0; i < 8; i++) {
1140 chmod(dir[i], 040000 + mode * 0100);
1141 if (sw == 8) mode++;
1145 void quit()
1148 chdir("..");
1149 system("rm -rf DIR*");
1151 if (errct == 0) {
1152 printf("ok\n");
1153 exit(0);
1154 } else {
1155 printf("%d errors\n", errct);
1156 exit(1);