Update CMOS time at shutdown time.
[minix3.git] / test / test18.c
blob246b1580601a171c8c9b5e11460b23089981863f
1 /* test 18 */
3 /* Comment on usage and program: ark!/mnt/rene/prac/os/unix/comment.changes */
5 /* "const.h", created by Rene Montsma and Menno Wilcke */
7 #include <sys/types.h> /* needed in struct stat */
8 #include <sys/stat.h> /* struct stat */
9 #include <sys/wait.h>
10 #include <errno.h> /* the error-numbers */
11 #include <fcntl.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include <stdio.h>
16 #include <limits.h>
18 #define NOCRASH 1 /* test11(), 2nd pipe */
19 #define PDPNOHANG 1 /* test03(), write_standards() */
20 #define MAXERR 5
22 #define USER_ID 12
23 #define GROUP_ID 1
24 #define FF 3 /* first free filedes. */
25 #define USER 1 /* uid */
26 #define GROUP 0 /* gid */
28 #define ARSIZE 256 /* array size */
29 #define PIPESIZE 3584 /* maxnumber of bytes to be written on pipe */
30 #define MAXOPEN (OPEN_MAX-3) /* maximum number of extra open files */
31 #define MAXLINK 0177 /* maximum number of links per file */
32 #define MASK 0777 /* selects lower nine bits */
33 #define READ_EOF 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, (void));
82 _PROTOTYPE(void test, (void));
83 _PROTOTYPE(void test01, (void));
84 _PROTOTYPE(void test02, (void));
85 _PROTOTYPE(void test03, (void));
86 _PROTOTYPE(void write_standards, (int filedes, char a []));
87 _PROTOTYPE(void test04, (void));
88 _PROTOTYPE(void read_standards, (int filedes, char a []));
89 _PROTOTYPE(void read_more, (int filedes, char a []));
90 _PROTOTYPE(void test05, (void));
91 _PROTOTYPE(void try_open, (char *fname, int mode, int test));
92 _PROTOTYPE(void test06, (void));
93 _PROTOTYPE(void test07, (void));
94 _PROTOTYPE(void access_standards, (void));
95 _PROTOTYPE(void try_access, (char *fname, int mode, int test));
96 _PROTOTYPE(void e, (char *string));
97 _PROTOTYPE(void nlcr, (void));
98 _PROTOTYPE(void str, (char *s));
99 _PROTOTYPE(void err, (int number, char *scall, char *name));
100 _PROTOTYPE(void make_and_fill_dirs, (void));
101 _PROTOTYPE(void put_file_in_dir, (char *dirname, int mode));
102 _PROTOTYPE(void init_array, (char *a));
103 _PROTOTYPE(void clear_array, (char *b));
104 _PROTOTYPE(int comp_array, (char *a, char *b, int range));
105 _PROTOTYPE(void try_close, (int filedes, char *name));
106 _PROTOTYPE(void try_unlink, (char *fname));
107 _PROTOTYPE(void Remove, (int fdes, char *fname));
108 _PROTOTYPE(int get_mode, (char *name));
109 _PROTOTYPE(void check, (char *scall, int number));
110 _PROTOTYPE(void put, (int nr));
111 _PROTOTYPE(int open_alot, (void));
112 _PROTOTYPE(int close_alot, (int number));
113 _PROTOTYPE(void clean_up_the_mess, (void));
114 _PROTOTYPE(void chmod_8_dirs, (int sw));
115 _PROTOTYPE(void quit, (void));
117 /*****************************************************************************
118 * TEST *
119 ****************************************************************************/
120 int main()
122 int n;
124 if (geteuid() == 0 || getuid() == 0) {
125 printf("Test 18 cannot run as root; test aborted\n");
126 exit(1);
129 system("rm -rf DIR_18; mkdir DIR_18");
130 chdir("DIR_18");
132 if (fork()) {
133 printf("Test 18 ");
134 fflush(stdout); /* have to flush for child's benefit */
136 wait(&n);
137 clean_up_the_mess();
138 quit();
139 } else {
140 test();
141 exit(0);
144 return(0);
147 void test()
149 umask(0); /* not honest, but i always forget */
151 test01();
152 make_and_fill_dirs();
153 test02();
154 test03();
155 test04();
156 test05();
157 test06();
158 test07();
159 umask(022);
160 } /* test */
162 /* "t1.c" created by Rene Montsma and Menno Wilcke */
164 /*****************************************************************************
165 * test UMASK *
166 ****************************************************************************/
167 void test01()
169 int oldvalue, newvalue, tempvalue;
170 int nr;
172 if ((oldvalue = umask(0777)) != 0) err(0, UMASK, NIL);
174 /* Special test: only the lower 9 bits (protection bits) may part- *
175 * icipate. ~0777 means: 111 000 000 000. Giving this to umask must*
176 * not change any value. */
178 if ((newvalue = umask(~0777)) != 0777) err(1, UMASK, "illegal");
179 if (oldvalue == newvalue) err(11, UMASK, "not change mask");
181 if ((tempvalue = umask(0)) != 0) err(2, UMASK, "values");
183 /* Now test all possible modes of umask on a file */
184 for (newvalue = MASK; newvalue >= 0; newvalue -= 0111) {
185 tempvalue = umask(newvalue);
186 if (tempvalue != oldvalue) {
187 err(1, UMASK, "illegal");
188 break; /* no use trying more */
189 } else if ((nr = creat("file01", 0777)) < 0)
190 err(5, CREAT, "'file01'");
191 else {
192 try_close(nr, "'file01'");
193 if (get_mode("file01") != (MASK & ~newvalue))
194 err(7, UMASK, "mode computed");
195 try_unlink("file01");
197 oldvalue = newvalue;
200 /* The loop has terminated with umask(0) */
201 if ((tempvalue = umask(0)) != 0)
202 err(7, UMASK, "umask may influence rest of tests!");
203 } /* test01 */
205 /*****************************************************************************
206 * test CREAT *
207 ****************************************************************************/
208 void test02()
210 int n, n1, mode;
211 char a[ARSIZE], b[ARSIZE];
212 struct stat stbf1;
214 mode = 0;
215 /* Create twenty files, check filedes */
216 for (n = 0; n < MAXOPEN; n++) {
217 if (creat(file[n], mode) != FF + n)
218 err(13, CREAT, file[n]);
219 else {
220 if (get_mode(file[n]) != mode)
221 err(7, CREAT, "mode set while creating many files");
223 /* Change mode of file to standard mode, we want to *
224 * use a lot (20) of files to be opened later, see *
225 * open_alot(), close_alot(). */
226 if (chmod(file[n], 0700) != OK) err(5, CHMOD, file[n]);
229 mode = (mode + 0100) % 01000;
232 /* Already twenty files opened; opening another has to fail */
233 if (creat("file02", 0777) != FAIL)
234 err(9, CREAT, "created");
235 else
236 check(CREAT, EMFILE);
238 /* Close all files: seems blunt, but it isn't because we've *
239 * checked all fd's already */
240 if ((n = close_alot(MAXOPEN)) < MAXOPEN) err(5, CLOSE, "MAXOPEN files");
242 /* Creat 1 file twice; check */
243 if ((n = creat("file02", 0777)) < 0)
244 err(5, CREAT, "'file02'");
245 else {
246 init_array(a);
247 if (write(n, a, ARSIZE) != ARSIZE) err(1, WRITE, "bad");
249 if ((n1 = creat("file02", 0755)) < 0) /* receate 'file02' */
250 err(5, CREAT, "'file02' (2nd time)");
251 else {
252 /* Fd should be at the top after recreation */
253 if (lseek(n1, 0L, SEEK_END) != 0)
254 err(11, CREAT, "not truncate file by recreation");
255 else {
256 /* Try to write on recreated file */
257 clear_array(b);
259 if (lseek(n1, 0L, SEEK_SET) != 0)
260 err(5, LSEEK, "to top of 2nd fd 'file02'");
261 if (write(n1, a, ARSIZE) != ARSIZE)
262 err(1, WRITE, "(2) bad");
264 /* In order to read we've to close and open again */
265 try_close(n1, "'file02' (2nd creation)");
266 if ((n1 = open("file02", RW)) < 0)
267 err(5, OPEN, "'file02' (2nd recreation)");
269 /* Continue */
270 if (lseek(n1, 0L, SEEK_SET) != 0)
271 err(5, LSEEK, "to top 'file02'(2nd fd) (2)");
272 if (read(n1, b, ARSIZE) != ARSIZE)
273 err(1, READ, "wrong");
275 if (comp_array(a, b, ARSIZE) != OK) err(11, CREAT,
276 "not really truncate file by recreation");
278 if (get_mode("file02") != 0777)
279 err(11, CREAT, "not maintain mode by recreation");
280 try_close(n1, "recreated 'file02'");
283 Remove(n, "file02");
286 /* Give 'creat' wrong input: dir not searchable */
287 if (creat("drw-/file02", 0777) != FAIL)
288 err(4, CREAT, "'drw-'");
289 else
290 check(CREAT, EACCES);
292 /* Dir not writable */
293 if (creat("dr-x/file02", 0777) != FAIL)
294 err(12, CREAT, "'dr-x/file02'");
295 else
296 check(CREAT, EACCES);
298 /* File not writable */
299 if (creat("drwx/r-x", 0777) != FAIL)
300 err(11, CREAT, "recreate non-writable file");
301 else
302 check(CREAT, EACCES);
304 /* Try to creat a dir */
305 if ((n = creat("dir", 040777)) != FAIL) {
306 if (fstat(n, &stbf1) != OK)
307 err(5, FSTAT, "'dir'");
308 else if (stbf1.st_mode != (mode_t) 0100777)
309 /* Cast because mode is negative :-(.
310 * HACK DEBUG FIXME: this appears to duplicate
311 * code in test17.c.
313 err(11, CREAT, "'creat' a new directory");
314 Remove(n, "dir");
317 /* We don't consider it to be a bug when creat * does not accept
318 * tricky modes */
320 /* File is an existing dir */
321 if (creat("drwx", 0777) != FAIL)
322 err(11, CREAT, "create an existing dir!");
323 else
324 check(CREAT, EISDIR);
325 } /* test02 */
327 /*****************************************************************************
328 * test WRITE *
329 ****************************************************************************/
330 void test03()
332 int n, n1;
333 int fd[2];
334 char a[ARSIZE];
336 init_array(a);
338 /* Test write after a CREAT */
339 if ((n = creat("file03", 0700)) != FF) /* 'file03' only open file */
340 err(13, CREAT, "'file03'");
341 else {
342 write_standards(n, a); /* test simple writes, wrong input too */
343 try_close(n, "'file03'");
346 /* Test write after an OPEN */
347 if ((n = open("file03", W)) < 0)
348 err(5, OPEN, "'file03'");
349 else
350 write_standards(n, a); /* test simple writes, wrong input too */
352 /* Test write after a DUP */
353 if ((n1 = dup(n)) < 0)
354 err(5, DUP, "'file03'");
355 else {
356 write_standards(n1, a);
357 try_close(n1, "duplicated fd 'file03'");
360 /* Remove testfile */
361 Remove(n, "file03");
363 /* Test write after a PIPE */
364 if (pipe(fd) < 0)
365 err(5, PIPE, NIL);
366 else {
367 write_standards(fd[1], a);
368 try_close(fd[0], "'fd[0]'");
369 try_close(fd[1], "'fd[1]'");
372 /* Last test: does write check protections ? */
373 if ((n = open("drwx/r--", R)) < 0)
374 err(5, OPEN, "'drwx/r--'");
375 else {
376 if (write(n, a, ARSIZE) != FAIL)
377 err(11, WRITE, "write on non-writ. file");
378 else
379 check(WRITE, EBADF);
380 try_close(n, "'drwx/r--'");
382 } /* test03 */
384 void write_standards(filedes, a)
385 int filedes;
386 char a[];
389 /* Write must return written account of numbers */
390 if (write(filedes, a, ARSIZE) != ARSIZE) err(1, WRITE, "bad");
392 /* Try giving 'write' wrong input */
393 /* Wrong filedes */
394 if (write(-1, a, ARSIZE) != FAIL)
395 err(2, WRITE, "filedes");
396 else
397 check(WRITE, EBADF);
399 /* Wrong length (illegal) */
400 #ifndef PDPNOHANG
401 if (write(filedes, a, -ARSIZE) != FAIL)
402 err(2, WRITE, "length");
403 else
404 check(WRITE, EINVAL); /* EFAULT on vu45 */
405 #endif
406 } /* write_standards */
408 /* "t2.c", created by Rene Montsma and Menno Wilcke */
410 /*****************************************************************************
411 * test READ *
412 ****************************************************************************/
413 void test04()
415 int n, n1, fd[2];
416 char a[ARSIZE];
418 /* Test read after creat */
419 if ((n = creat("file04", 0700)) != FF) /* no other open files may be
420 * left */
421 err(13, CREAT, "'file04'");
422 else {
423 /* Closing and opening needed before writing */
424 try_close(n, "'file04'");
425 if ((n = open("file04", RW)) < 0) err(5, OPEN, "'file04'");
427 init_array(a);
429 if (write(n, a, ARSIZE) != ARSIZE)
430 err(1, WRITE, "bad");
431 else {
432 if (lseek(n, 0L, SEEK_SET) != 0) err(5, LSEEK, "'file04'");
433 read_standards(n, a);
434 read_more(n, a);
436 try_close(n, "'file04'");
439 /* Test read after OPEN */
440 if ((n = open("file04", R)) < 0)
441 err(5, OPEN, "'file04'");
442 else {
443 read_standards(n, a);
444 read_more(n, a);
445 try_close(n, "'file04'");
448 /* Test read after DUP */
449 if ((n = open("file04", R)) < 0) err(5, OPEN, "'file04'");
450 if ((n1 = dup(n)) < 0)
451 err(5, DUP, "'file04'");
452 else {
453 read_standards(n1, a);
454 read_more(n1, a);
455 try_close(n1, "duplicated fd 'file04'");
458 /* Remove testfile */
459 Remove(n, "file04");
461 /* Test read after pipe */
462 if (pipe(fd) < 0)
463 err(5, PIPE, NIL);
464 else {
465 if (write(fd[1], a, ARSIZE) != ARSIZE) {
466 err(5, WRITE, "'fd[1]'");
467 try_close(fd[1], "'fd[1]'");
468 } else {
469 try_close(fd[1], "'fd[1]'");
470 read_standards(fd[0], a);
472 try_close(fd[0], "'fd[0]'");
475 /* Last test: try to read a read-protected file */
476 if ((n = open("drwx/-wx", W)) < 0)
477 err(5, OPEN, "'drwx/-wx'");
478 else {
479 if (read(n, a, ARSIZE) != FAIL)
480 err(11, READ, "read a non-read. file");
481 else
482 check(READ, EBADF);
483 try_close(n, "'/drwx/-wx'");
485 } /* test04 */
487 void read_standards(filedes, a)
488 int filedes;
489 char a[];
491 char b[ARSIZE];
493 clear_array(b);
494 if (read(filedes, b, ARSIZE) != ARSIZE)
495 err(1, READ, "bad");
496 else if (comp_array(a, b, ARSIZE) != OK)
497 err(7, "read/write", "values");
498 else if (read(filedes, b, ARSIZE) != READ_EOF)
499 err(11, READ, "read beyond endoffile");
501 /* Try giving read wrong input: wrong filedes */
502 if (read(FAIL, b, ARSIZE) != FAIL)
503 err(2, READ, "filedes");
504 else
505 check(READ, EBADF);
507 /* Wrong length */
508 if (read(filedes, b, -ARSIZE) != FAIL)
509 err(2, READ, "length");
510 else
511 check(READ, EINVAL);
512 } /* read_standards */
514 void read_more(filedes, a)
515 int filedes;
516 char a[];
517 /* Separated from read_standards() because the PIPE test * would fail. */
519 int i;
520 char b[ARSIZE];
522 if (lseek(filedes, (long) (ARSIZE / 2), SEEK_SET) != ARSIZE / 2)
523 err(5, LSEEK, "to location ARSIZE/2");
525 clear_array(b);
526 if (read(filedes, b, ARSIZE) != ARSIZE / 2) err(1, READ, "bad");
528 for (i = 0; i < ARSIZE / 2; i++)
529 if (b[i] != a[(ARSIZE / 2) + i])
530 err(7, READ, "from location ARSIZE/2");
533 /*****************************************************************************
534 * test OPEN/CLOSE *
535 ****************************************************************************/
536 void test05()
538 int n, n1, mode, fd[2];
539 char b[ARSIZE];
541 /* Test open after CREAT */
542 if ((n = creat("file05", 0700)) != FF) /* no other open files left */
543 err(13, CREAT, "'file05'");
544 else {
545 if ((n1 = open("file05", RW)) != FF + 1)
546 err(13, OPEN, "'file05' after creation");
547 try_close(n1, "'file05' (open after creation)");
549 try_close(n, "'file05'");
550 if ((n = open("file05", R)) != FF)
551 err(13, OPEN, "after closing");
552 else
553 try_close(n, "'file05' (open after closing)");
555 /* Remove testfile */
556 try_unlink("file05");
559 /* Test all possible modes, try_open not only opens file (sometimes) *
560 * but closes files too (when opened) */
561 if ((n = creat("file05", 0700)) < 0) /* no other files left */
562 err(5, CREAT, "'file05' (2nd time)");
563 else {
564 try_close(n, "file05");
565 for (mode = 0; mode <= 0700; mode += 0100) {
566 if (chmod("file05", mode) != OK) err(5, CHMOD, "'file05'");
568 if (mode <= 0100) {
569 try_open("file05", R, FAIL);
570 try_open("file05", W, FAIL);
571 try_open("file05", RW, FAIL);
572 } else if (mode >= 0200 && mode <= 0300) {
573 try_open("file05", R, FAIL);
574 try_open("file05", W, FF);
575 try_open("file05", RW, FAIL);
576 } else if (mode >= 0400 && mode <= 0500) {
577 try_open("file05", R, FF);
578 try_open("file05", W, FAIL);
579 try_open("file05", RW, FAIL);
580 } else {
581 try_open("file05", R, FF);
582 try_open("file05", W, FF);
583 try_open("file05", RW, FF);
588 /* Test opening existing file */
589 if ((n = open("drwx/rwx", R)) < 0)
590 err(13, OPEN, "existing file");
591 else { /* test close after DUP */
592 if ((n1 = dup(n)) < 0)
593 err(13, DUP, "'drwx/rwx'");
594 else {
595 try_close(n1, "duplicated fd 'drwx/rwx'");
597 if (read(n1, b, ARSIZE) != FAIL)
598 err(11, READ, "on closed dupped fd 'drwx/rwx'");
599 else
600 check(READ, EBADF);
602 if (read(n, b, ARSIZE) == FAIL) /* should read an eof */
603 err(13, READ, "on fd '/drwx/rwx'");
605 try_close(n, "'drwx/rwx'");
608 /* Test close after PIPE */
609 if (pipe(fd) < 0)
610 err(13, PIPE, NIL);
611 else {
612 try_close(fd[1], "duplicated fd 'fd[1]'");
614 /* Fd[1] really should be closed now; check */
615 clear_array(b);
616 if (read(fd[0], b, ARSIZE) != READ_EOF)
617 err(11, READ, "read on empty pipe (and fd[1] was closed)");
618 try_close(fd[0], "duplicated fd 'fd[0]'");
621 /* Try to open a non-existing file */
622 if (open("non-file", R) != FAIL)
623 err(11, OPEN, "open non-executable file");
624 else
625 check(OPEN, ENOENT);
627 /* Dir does not exist */
628 if (open("dzzz/file05", R) != FAIL)
629 err(11, OPEN, "open in an non-searchable dir");
630 else
631 check(OPEN, ENOENT);
633 /* Dir is not searchable */
634 if (n = open("drw-/rwx", R) != FAIL)
635 err(11, OPEN, "open in an non-searchabledir");
636 else
637 check(OPEN, EACCES);
639 /* Unlink testfile */
640 try_unlink("file05");
642 /* File is not readable */
643 if (open("drwx/-wx", R) != FAIL)
644 err(11, OPEN, "open unreadable file for reading");
645 else
646 check(OPEN, EACCES);
648 /* File is not writable */
649 if (open("drwx/r-x", W) != FAIL)
650 err(11, OPEN, "open unwritable file for writing");
651 else
652 check(OPEN, EACCES);
654 /* Try opening more than MAXOPEN ('extra' (19-8-85)) files */
655 if ((n = open_alot()) != MAXOPEN)
656 err(13, OPEN, "MAXOPEN files");
657 else
658 /* Maximum # of files opened now, another open should fail
659 * because * all filedescriptors have already been used. */
660 if (open("drwx/rwx", RW) != FAIL)
661 err(9, OPEN, "open");
662 else
663 check(OPEN, EMFILE);
664 if (close_alot(n) != n) err(5, CLOSE, "all opened files");
666 /* Can close make mistakes ? */
667 if (close(-1) != FAIL)
668 err(2, CLOSE, "filedes");
669 else
670 check(CLOSE, EBADF);
671 } /* test05 */
673 void try_open(fname, mode, test)
674 int mode, test;
675 char *fname;
677 int n;
679 if ((n = open(fname, mode)) != test)
680 err(11, OPEN, "break through filepermission with an incorrect mode");
681 if (n != FAIL) try_close(n, fname); /* cleanup */
682 } /* try_open */
684 /*****************************************************************************
685 * test LSEEK *
686 ****************************************************************************/
687 void test06()
689 char a[ARSIZE], b[ARSIZE];
690 int fd;
692 if ((fd = open("drwx/rwx", RW)) != FF) /* there should be no */
693 err(13, OPEN, "'drwx/rwx'"); /* other open files */
694 else {
695 init_array(a);
696 if (write(fd, a, 10) != 10)
697 err(1, WRITE, "bad");
698 else {
699 /* Lseek back to begin file */
700 if (lseek(fd, 0L, SEEK_SET) != 0)
701 err(5, LSEEK, "to begin file");
702 else if (read(fd, b, 10) != 10)
703 err(1, READ, "bad");
704 else if (comp_array(a, b, 10) != OK)
705 err(7, LSEEK, "values r/w after lseek to begin");
706 /* Lseek to endoffile */
707 if (lseek(fd, 0L, SEEK_END) != 10)
708 err(5, LSEEK, "to end of file");
709 else if (read(fd, b, 1) != READ_EOF)
710 err(7, LSEEK, "read at end of file");
711 /* Lseek beyond file */
712 if (lseek(fd, 10L, SEEK_CUR) != 20)
713 err(5, LSEEK, "beyond end of file");
714 else if (write(fd, a, 10) != 10)
715 err(1, WRITE, "bad");
716 else {
717 /* Lseek to begin second write */
718 if (lseek(fd, 20L, SEEK_SET) != 20)
719 err(5, LSEEK, "'/drwx/rwx'");
720 if (read(fd, b, 10) != 10)
721 err(1, READ, "bad");
722 else if (comp_array(a, b, 10) != OK)
723 err(7, LSEEK,
724 "values read after lseek MAXOPEN");
728 /* Lseek to position before begin of file */
729 if (lseek(fd, -1L, 0) != FAIL)
730 err(11, LSEEK, "lseek before beginning of file");
732 try_close(fd, "'drwx/rwx'");
735 /* Lseek on invalid filediscriptor */
736 if (lseek(-1, 0L, SEEK_SET) != FAIL)
737 err(2, LSEEK, "filedes");
738 else
739 check(LSEEK, EBADF);
743 /* "t3.c", created by Rene Montsma and Menno Wilcke */
745 /*****************************************************************************
746 * test ACCESS *
747 ****************************************************************************/
748 void test07()
750 /* Check with proper parameters */
751 if (access("drwx/rwx", RWX) != OK) err(5, ACCESS, "accessible file");
753 if (access("./././drwx/././rwx", 0) != OK)
754 err(5, ACCESS, "'/./.(etc)/drwx///rwx'");
756 /* Check 8 files with 8 different modes on 8 accesses */
757 if (chdir("drwx") != OK) err(5, CHDIR, "'drwx'");
759 access_standards();
761 if (chdir("..") != OK) err(5, CHDIR, "'..'");
763 /* Check several wrong combinations */
764 /* File does not exist */
765 if (access("non-file", 0) != FAIL)
766 err(11, ACCESS, "access non-existing file");
767 else
768 check(ACCESS, ENOENT);
770 /* Non-searchable dir */
771 if (access("drw-/rwx", 0) != FAIL)
772 err(4, ACCESS, "'drw-'");
773 else
774 check(ACCESS, EACCES);
776 /* Searchable dir, but wrong file-mode */
777 if (access("drwx/--x", RWX) != FAIL)
778 err(11, ACCESS, "a non accessible file");
779 else
780 check(ACCESS, EACCES);
782 } /* test07 */
784 void access_standards()
786 int i, mode = 0;
788 for (i = 0; i < 8; i++)
789 if (i == 0)
790 try_access(fnames[mode], i, OK);
791 else
792 try_access(fnames[mode], i, FAIL);
793 mode++;
795 for (i = 0; i < 8; i++)
796 if (i < 2)
797 try_access(fnames[mode], i, OK);
798 else
799 try_access(fnames[mode], i, FAIL);
800 mode++;
802 for (i = 0; i < 8; i++)
803 if (i == 0 || i == 2)
804 try_access(fnames[mode], i, OK);
805 else
806 try_access(fnames[mode], i, FAIL);
807 mode++;
809 for (i = 0; i < 8; i++)
810 if (i < 4)
811 try_access(fnames[mode], i, OK);
812 else
813 try_access(fnames[mode], i, FAIL);
814 mode++;
816 for (i = 0; i < 8; i++)
817 if (i == 0 || i == 4)
818 try_access(fnames[mode], i, OK);
819 else
820 try_access(fnames[mode], i, FAIL);
821 mode++;
823 for (i = 0; i < 8; i++)
824 if (i == 0 || i == 1 || i == 4 || i == 5)
825 try_access(fnames[mode], i, OK);
826 else
827 try_access(fnames[mode], i, FAIL);
828 mode++;
830 for (i = 0; i < 8; i++)
831 if (i % 2 == 0)
832 try_access(fnames[mode], i, OK);
833 else
834 try_access(fnames[mode], i, FAIL);
835 mode++;
837 for (i = 0; i < 8; i++) try_access(fnames[mode], i, OK);
838 } /* access_standards */
840 void try_access(fname, mode, test)
841 int mode, test;
842 char *fname;
844 if (access(fname, mode) != test)
845 err(100, ACCESS, "incorrect access on a file (try_access)");
846 } /* try_access */
848 /* "support.c", created by Rene Montsma and Menno Wilcke */
850 /* Err, make_and_fill_dirs, init_array, clear_array, comp_array,
851 try_close, try_unlink, Remove, get_mode, check, open_alot,
852 close_alot, clean_up_the_mess.
855 /***********************************************************************
856 * EXTENDED FIONS *
857 **********************************************************************/
858 /* First extended functions (i.e. not oldfashioned monixcalls.
859 e(), nlcr(), octal.*/
861 void e(string)
862 char *string;
864 printf("Test program error: %s\n", string);
865 errct++;
868 void nlcr()
870 printf("\n");
873 void str(s)
874 char *s;
876 printf(s);
879 /*****************************************************************************
881 * ERR(or) messages *
883 *****************************************************************************/
884 void err(number, scall, name)
885 /* Give nice error messages */
887 char *scall, *name;
888 int number;
891 errct++;
892 if (errct > MAXERR) {
893 printf("Too many errors; test aborted\n");
894 chdir("..");
895 system("rm -rf DIR*");
896 quit();
898 e("");
899 str("\t");
900 switch (number) {
901 case 0:
902 str(scall);
903 str(": illegal initial value.");
904 break;
905 case 1:
906 str(scall);
907 str(": ");
908 str(name);
909 str(" value returned.");
910 break;
911 case 2:
912 str(scall);
913 str(": accepting illegal ");
914 str(name);
915 str(".");
916 break;
917 case 3:
918 str(scall);
919 str(": accepting non-existing file.");
920 break;
921 case 4:
922 str(scall);
923 str(": could search non-searchable dir (");
924 str(name);
925 str(").");
926 break;
927 case 5:
928 str(scall);
929 str(": cannot ");
930 str(scall);
931 str(" ");
932 str(name);
933 str(".");
934 break;
935 case 7:
936 str(scall);
937 str(": incorrect ");
938 str(name);
939 str(".");
940 break;
941 case 8:
942 str(scall);
943 str(": wrong values.");
944 break;
945 case 9:
946 str(scall);
947 str(": accepting too many ");
948 str(name);
949 str(" files.");
950 break;
951 case 10:
952 str(scall);
953 str(": even a superuser can't do anything!");
954 break;
955 case 11:
956 str(scall);
957 str(": could ");
958 str(name);
959 str(".");
960 break;
961 case 12:
962 str(scall);
963 str(": could write in non-writable dir (");
964 str(name);
965 str(").");
966 break;
967 case 13:
968 str(scall);
969 str(": wrong filedes returned (");
970 str(name);
971 str(").");
972 break;
973 case 100:
974 str(scall); /* very common */
975 str(": ");
976 str(name);
977 str(".");
978 break;
979 default: str("errornumber does not exist!\n");
981 nlcr();
982 } /* err */
984 /*****************************************************************************
986 * MAKE_AND_FILL_DIRS *
988 *****************************************************************************/
990 void make_and_fill_dirs()
991 /* Create 8 dir.'s: "d---", "d--x", "d-w-", "d-wx", "dr--", "dr-x", *
992 * "drw-", "drwx". * Then create 8 files
993 * in "drwx", and some needed files in other dirs. */
995 int mode, i;
997 for (i = 0; i < 8; i++) {
998 mkdir(dir[i], 0700);
999 chown(dir[i], USER_ID, GROUP_ID);
1001 setuid(USER_ID);
1002 setgid(GROUP_ID);
1004 for (mode = 0; mode < 8; mode++) put_file_in_dir("drwx", mode);
1006 put_file_in_dir("d-wx", RWX);
1007 put_file_in_dir("dr-x", RWX);
1008 put_file_in_dir("drw-", RWX);
1010 chmod_8_dirs(8); /* 8 means; 8 different modes */
1012 } /* make_and_fill_dirs */
1014 void put_file_in_dir(dirname, mode)
1015 char *dirname;
1016 int mode;
1017 /* Fill directory 'dirname' with file with mode 'mode'. */
1019 int nr;
1021 if (chdir(dirname) != OK)
1022 err(5, CHDIR, "to dirname (put_f_in_dir)");
1023 else {
1024 /* Creat the file */
1025 if ((nr = creat(fnames[mode], mode * 0100)) < 0)
1026 err(13, CREAT, fnames[mode]);
1027 else
1028 try_close(nr, fnames[mode]);
1030 if (chdir("..") != OK)
1031 err(5, CHDIR, "to previous dir (put_f_in_dir)");
1033 } /* put_file_in_dir */
1035 /*****************************************************************************
1037 * MISCELLANEOUS *
1039 *(all about arrays, 'try_close', 'try_unlink', 'Remove', 'get_mode') *
1041 *****************************************************************************/
1043 void init_array(a)
1044 char *a;
1046 int i;
1048 i = 0;
1049 while (i++ < ARSIZE) *a++ = 'a' + (i % 26);
1050 } /* init_array */
1052 void clear_array(b)
1053 char *b;
1055 int i;
1057 i = 0;
1058 while (i++ < ARSIZE) *b++ = '0';
1060 } /* clear_array */
1062 int comp_array(a, b, range)
1063 char *a, *b;
1064 int range;
1066 if ((range < 0) || (range > ARSIZE)) {
1067 err(100, "comp_array", "illegal range");
1068 return(FAIL);
1069 } else {
1070 while (range-- && (*a++ == *b++));
1071 if (*--a == *--b)
1072 return(OK);
1073 else
1074 return(FAIL);
1076 } /* comp_array */
1078 void try_close(filedes, name)
1079 int filedes;
1080 char *name;
1082 if (close(filedes) != OK) err(5, CLOSE, name);
1083 } /* try_close */
1085 void try_unlink(fname)
1086 char *fname;
1088 if (unlink(fname) != 0) err(5, UNLINK, fname);
1089 } /* try_unlink */
1091 void Remove(fdes, fname)
1092 int fdes;
1093 char *fname;
1095 try_close(fdes, fname);
1096 try_unlink(fname);
1097 } /* Remove */
1099 int get_mode(name)
1100 char *name;
1102 struct stat stbf1;
1104 if (stat(name, &stbf1) != OK) {
1105 err(5, STAT, name);
1106 return(stbf1.st_mode); /* return a mode which will cause *
1107 * error in the calling function *
1108 * (file/dir bit) */
1109 } else
1110 return(stbf1.st_mode & 07777); /* take last 4 bits */
1111 } /* get_mode */
1113 /*****************************************************************************
1115 * CHECK *
1117 *****************************************************************************/
1119 void check(scall, number)
1120 int number;
1121 char *scall;
1123 if (errno != number) {
1124 e(NIL);
1125 str("\t");
1126 str(scall);
1127 str(": bad errno-value: ");
1128 put(errno);
1129 str(" should have been: ");
1130 put(number);
1131 nlcr();
1133 } /* check */
1135 void put(nr)
1136 int nr;
1138 switch (nr) {
1139 case 0: str("unused"); break;
1140 case 1: str("EPERM"); break;
1141 case 2: str("ENOENT"); break;
1142 case 3: str("ESRCH"); break;
1143 case 4: str("EINTR"); break;
1144 case 5: str("EIO"); break;
1145 case 6: str("ENXIO"); break;
1146 case 7: str("E2BIG"); break;
1147 case 8: str("ENOEXEC"); break;
1148 case 9: str("EBADF"); break;
1149 case 10: str("ECHILD"); break;
1150 case 11: str("EAGAIN"); break;
1151 case 12: str("ENOMEM"); break;
1152 case 13: str("EACCES"); break;
1153 case 14: str("EFAULT"); break;
1154 case 15: str("ENOTBLK"); break;
1155 case 16: str("EBUSY"); break;
1156 case 17: str("EEXIST"); break;
1157 case 18: str("EXDEV"); break;
1158 case 19: str("ENODEV"); break;
1159 case 20: str("ENOTDIR"); break;
1160 case 21: str("EISDIR"); break;
1161 case 22: str("EINVAL"); break;
1162 case 23: str("ENFILE"); break;
1163 case 24: str("EMFILE"); break;
1164 case 25: str("ENOTTY"); break;
1165 case 26: str("ETXTBSY"); break;
1166 case 27: str("EFBIG"); break;
1167 case 28: str("ENOSPC"); break;
1168 case 29: str("ESPIPE"); break;
1169 case 30: str("EROFS"); break;
1170 case 31: str("EMLINK"); break;
1171 case 32: str("EPIPE"); break;
1172 case 33: str("EDOM"); break;
1173 case 34: str("ERANGE"); break;
1177 /*****************************************************************************
1179 * ALOT-functions *
1181 *****************************************************************************/
1183 int open_alot()
1185 int i;
1187 for (i = 0; i < MAXOPEN; i++)
1188 if (open(file[i], R) == FAIL) break;
1189 if (i == 0) err(5, "open_alot", "at all");
1190 return(i);
1191 } /* open_alot */
1193 int close_alot(number)
1194 int number;
1196 int i, count = 0;
1198 if (number > MAXOPEN)
1199 err(5, "close_alot", "accept this argument");
1200 else
1201 for (i = FF; i < number + FF; i++)
1202 if (close(i) != OK) count++;
1204 return(number - count); /* return number of closed files */
1205 } /* close_alot */
1207 /*****************************************************************************
1209 * CLEAN UP THE MESS *
1211 *****************************************************************************/
1213 void clean_up_the_mess()
1215 int i;
1216 char dirname[6];
1218 /* First remove 'alot' files */
1219 for (i = 0; i < MAXOPEN; i++) try_unlink(file[i]);
1221 /* Unlink the files in dir 'drwx' */
1222 if (chdir("drwx") != OK)
1223 err(5, CHDIR, "to 'drwx'");
1224 else {
1225 for (i = 0; i < 8; i++) try_unlink(fnames[i]);
1226 if (chdir("..") != OK) err(5, CHDIR, "to '..'");
1229 /* Before unlinking files in some dirs, make them writable */
1230 chmod_8_dirs(RWX);
1232 /* Unlink files in other dirs */
1233 try_unlink("d-wx/rwx");
1234 try_unlink("dr-x/rwx");
1235 try_unlink("drw-/rwx");
1237 /* Unlink dirs */
1238 for (i = 0; i < 8; i++) {
1239 strcpy(dirname, "d");
1240 strcat(dirname, fnames[i]);
1241 /* 'dirname' contains the directoryname */
1242 rmdir(dirname);
1245 /* FINISH */
1246 } /* clean_up_the_mess */
1248 void chmod_8_dirs(sw)
1249 int sw; /* if switch == 8, give all different
1250 * mode,else the same mode */
1252 int mode;
1253 int i;
1255 if (sw == 8)
1256 mode = 0;
1257 else
1258 mode = sw;
1260 for (i = 0; i < 8; i++) {
1261 chmod(dir[i], 040000 + mode * 0100);
1262 if (sw == 8) mode++;
1266 void quit()
1269 chdir("..");
1270 system("rm -rf DIR*");
1272 if (errct == 0) {
1273 printf("ok\n");
1274 exit(0);
1275 } else {
1276 printf("%d errors\n", errct);
1277 exit(1);