vm: don't force physical addresses to be nonzero.
[minix.git] / test / test18.c
blob17fbf4aa05b78d551ac61aeda5df37589dd65447
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>
17 #include <assert.h>
18 #include <sys/uio.h>
20 #define NOCRASH 1 /* test11(), 2nd pipe */
21 #define PDPNOHANG 1 /* test03(), write_standards() */
22 #define MAXERR 5
24 #define USER_ID 12
25 #define GROUP_ID 1
26 #define FF 3 /* first free filedes. */
27 #define USER 1 /* uid */
28 #define GROUP 0 /* gid */
30 #define ARSIZE 256 /* array size */
31 #define PIPESIZE 3584 /* maxnumber of bytes to be written on pipe */
32 #define MAXOPEN (OPEN_MAX-3) /* maximum number of extra open files */
33 #define MAXLINK 0177 /* maximum number of links per file */
34 #define MASK 0777 /* selects lower nine bits */
35 #define READ_EOF 0 /* returned by read-call at eof */
37 #define OK 0
38 #define FAIL -1
40 #define R 0 /* read (open-call) */
41 #define W 1 /* write (open-call) */
42 #define RW 2 /* read & write (open-call) */
44 #define RWX 7 /* read & write & execute (mode) */
46 #define NIL ""
47 #define UMASK "umask"
48 #define CREAT "creat"
49 #define WRITE "write"
50 #define WRITEV "writev"
51 #define READ "read"
52 #define READV "readv"
53 #define OPEN "open"
54 #define CLOSE "close"
55 #define LSEEK "lseek"
56 #define ACCESS "access"
57 #define CHDIR "chdir"
58 #define CHMOD "chmod"
59 #define LINK "link"
60 #define UNLINK "unlink"
61 #define PIPE "pipe"
62 #define STAT "stat"
63 #define FSTAT "fstat"
64 #define DUP "dup"
65 #define UTIME "utime"
67 int errct;
69 char *file[];
70 char *fnames[];
71 char *dir[];
73 /* "decl.c", created by Rene Montsma and Menno Wilcke */
75 /* Used in open_alot, close_alot */
76 char *file[20] = {"f0", "f1", "f2", "f3", "f4", "f5", "f6",
77 "f7", "f8", "f9", "f10", "f11", "f12", "f13",
78 "f14", "f15", "f16", "f17", "f18", "f19"}, *fnames[8] = {"---", "--x", "-w-", "-wx", "r--",
79 "r-x", "rw-", "rwx"}, *dir[8] = {"d---", "d--x", "d-w-", "d-wx", "dr--", "dr-x",
80 "drw-", "drwx"};
81 /* Needed for easy creating and deleting of directories */
83 /* "test.c", created by Rene Montsma and Menno Wilcke */
85 _PROTOTYPE(int main, (int argc, char **argv));
86 _PROTOTYPE(void test, (void));
87 _PROTOTYPE(void test01, (void));
88 _PROTOTYPE(void test02, (void));
89 _PROTOTYPE(void test03, (void));
90 _PROTOTYPE(void write_standards, (int filedes, char a []));
91 _PROTOTYPE(void test04, (void));
92 _PROTOTYPE(void read_standards, (int filedes, char a []));
93 _PROTOTYPE(void read_more, (int filedes, char a []));
94 _PROTOTYPE(void test05, (void));
95 _PROTOTYPE(void try_open, (char *fname, int mode, int test));
96 _PROTOTYPE(void test06, (void));
97 _PROTOTYPE(void test07, (void));
98 _PROTOTYPE(void access_standards, (void));
99 _PROTOTYPE(void test08, (void));
100 _PROTOTYPE(static int iovec_is_equal,
101 (struct iovec *x, struct iovec *y, size_t size));
102 _PROTOTYPE(static size_t iovec_setup,
103 (int pattern, struct iovec *iovec, char *buffer, int count));
104 _PROTOTYPE(static int power, (int base, int exponent));
105 _PROTOTYPE(void try_access, (char *fname, int mode, int test));
106 _PROTOTYPE(void e, (char *string));
107 _PROTOTYPE(void nlcr, (void));
108 _PROTOTYPE(void str, (char *s));
109 _PROTOTYPE(void err, (int number, char *scall, char *name));
110 _PROTOTYPE(void make_and_fill_dirs, (void));
111 _PROTOTYPE(void put_file_in_dir, (char *dirname, int mode));
112 _PROTOTYPE(void init_array, (char *a));
113 _PROTOTYPE(void clear_array, (char *b));
114 _PROTOTYPE(int comp_array, (char *a, char *b, int range));
115 _PROTOTYPE(void try_close, (int filedes, char *name));
116 _PROTOTYPE(void try_unlink, (char *fname));
117 _PROTOTYPE(void Remove, (int fdes, char *fname));
118 _PROTOTYPE(int get_mode, (char *name));
119 _PROTOTYPE(void check, (char *scall, int number));
120 _PROTOTYPE(void put, (int nr));
121 _PROTOTYPE(int open_alot, (void));
122 _PROTOTYPE(int close_alot, (int number));
123 _PROTOTYPE(void clean_up_the_mess, (void));
124 _PROTOTYPE(void chmod_8_dirs, (int sw));
125 _PROTOTYPE(void quit, (void));
127 /*****************************************************************************
128 * TEST *
129 ****************************************************************************/
130 int main(int argc, char **argv)
132 char buffer[PATH_MAX + 1];
133 int n;
135 if (geteuid() == 0 || getuid() == 0) {
136 realpath(argv[0], buffer);
137 execl("/usr/bin/su", "/usr/bin/su", "-", "ast", "-c", buffer, NULL);
138 printf("Test 18 cannot run as root; test aborted\n");
139 exit(1);
142 system("rm -rf DIR_18; mkdir DIR_18");
143 chdir("DIR_18");
145 if (fork()) {
146 printf("Test 18 ");
147 fflush(stdout); /* have to flush for child's benefit */
149 wait(&n);
150 clean_up_the_mess();
151 quit();
152 } else {
153 test();
154 exit(0);
157 return(0);
160 void test()
162 umask(0); /* not honest, but i always forget */
164 test01();
165 make_and_fill_dirs();
166 test02();
167 test03();
168 test04();
169 test05();
170 test06();
171 test07();
172 test08();
173 umask(022);
174 } /* test */
176 /* "t1.c" created by Rene Montsma and Menno Wilcke */
178 /*****************************************************************************
179 * test UMASK *
180 ****************************************************************************/
181 void test01()
183 int oldvalue, newvalue, tempvalue;
184 int nr;
186 if ((oldvalue = umask(0777)) != 0) err(0, UMASK, NIL);
188 /* Special test: only the lower 9 bits (protection bits) may part- *
189 * icipate. ~0777 means: 111 000 000 000. Giving this to umask must*
190 * not change any value. */
192 if ((newvalue = umask(~0777)) != 0777) err(1, UMASK, "illegal");
193 if (oldvalue == newvalue) err(11, UMASK, "not change mask");
195 if ((tempvalue = umask(0)) != 0) err(2, UMASK, "values");
197 /* Now test all possible modes of umask on a file */
198 for (newvalue = MASK; newvalue >= 0; newvalue -= 0111) {
199 tempvalue = umask(newvalue);
200 if (tempvalue != oldvalue) {
201 err(1, UMASK, "illegal");
202 break; /* no use trying more */
203 } else if ((nr = creat("file01", 0777)) < 0)
204 err(5, CREAT, "'file01'");
205 else {
206 try_close(nr, "'file01'");
207 if (get_mode("file01") != (MASK & ~newvalue))
208 err(7, UMASK, "mode computed");
209 try_unlink("file01");
211 oldvalue = newvalue;
214 /* The loop has terminated with umask(0) */
215 if ((tempvalue = umask(0)) != 0)
216 err(7, UMASK, "umask may influence rest of tests!");
217 } /* test01 */
219 /*****************************************************************************
220 * test CREAT *
221 ****************************************************************************/
222 void test02()
224 int n, n1, mode;
225 char a[ARSIZE], b[ARSIZE];
226 struct stat stbf1;
228 mode = 0;
229 /* Create twenty files, check filedes */
230 for (n = 0; n < MAXOPEN; n++) {
231 if (creat(file[n], mode) != FF + n)
232 err(13, CREAT, file[n]);
233 else {
234 if (get_mode(file[n]) != mode)
235 err(7, CREAT, "mode set while creating many files");
237 /* Change mode of file to standard mode, we want to *
238 * use a lot (20) of files to be opened later, see *
239 * open_alot(), close_alot(). */
240 if (chmod(file[n], 0700) != OK) err(5, CHMOD, file[n]);
243 mode = (mode + 0100) % 01000;
246 /* Already twenty files opened; opening another has to fail */
247 if (creat("file02", 0777) != FAIL)
248 err(9, CREAT, "created");
249 else
250 check(CREAT, EMFILE);
252 /* Close all files: seems blunt, but it isn't because we've *
253 * checked all fd's already */
254 if ((n = close_alot(MAXOPEN)) < MAXOPEN) err(5, CLOSE, "MAXOPEN files");
256 /* Creat 1 file twice; check */
257 if ((n = creat("file02", 0777)) < 0)
258 err(5, CREAT, "'file02'");
259 else {
260 init_array(a);
261 if (write(n, a, ARSIZE) != ARSIZE) err(1, WRITE, "bad");
263 if ((n1 = creat("file02", 0755)) < 0) /* receate 'file02' */
264 err(5, CREAT, "'file02' (2nd time)");
265 else {
266 /* Fd should be at the top after recreation */
267 if (lseek(n1, 0L, SEEK_END) != 0)
268 err(11, CREAT, "not truncate file by recreation");
269 else {
270 /* Try to write on recreated file */
271 clear_array(b);
273 if (lseek(n1, 0L, SEEK_SET) != 0)
274 err(5, LSEEK, "to top of 2nd fd 'file02'");
275 if (write(n1, a, ARSIZE) != ARSIZE)
276 err(1, WRITE, "(2) bad");
278 /* In order to read we've to close and open again */
279 try_close(n1, "'file02' (2nd creation)");
280 if ((n1 = open("file02", RW)) < 0)
281 err(5, OPEN, "'file02' (2nd recreation)");
283 /* Continue */
284 if (lseek(n1, 0L, SEEK_SET) != 0)
285 err(5, LSEEK, "to top 'file02'(2nd fd) (2)");
286 if (read(n1, b, ARSIZE) != ARSIZE)
287 err(1, READ, "wrong");
289 if (comp_array(a, b, ARSIZE) != OK) err(11, CREAT,
290 "not really truncate file by recreation");
292 if (get_mode("file02") != 0777)
293 err(11, CREAT, "not maintain mode by recreation");
294 try_close(n1, "recreated 'file02'");
297 Remove(n, "file02");
300 /* Give 'creat' wrong input: dir not searchable */
301 if (creat("drw-/file02", 0777) != FAIL)
302 err(4, CREAT, "'drw-'");
303 else
304 check(CREAT, EACCES);
306 /* Dir not writable */
307 if (creat("dr-x/file02", 0777) != FAIL)
308 err(12, CREAT, "'dr-x/file02'");
309 else
310 check(CREAT, EACCES);
312 /* File not writable */
313 if (creat("drwx/r-x", 0777) != FAIL)
314 err(11, CREAT, "recreate non-writable file");
315 else
316 check(CREAT, EACCES);
318 /* Try to creat a dir */
319 if ((n = creat("dir", 040777)) != FAIL) {
320 if (fstat(n, &stbf1) != OK)
321 err(5, FSTAT, "'dir'");
322 else if (stbf1.st_mode != (mode_t) 0100777)
323 /* Cast because mode is negative :-(.
324 * HACK DEBUG FIXME: this appears to duplicate
325 * code in test17.c.
327 err(11, CREAT, "'creat' a new directory");
328 Remove(n, "dir");
331 /* We don't consider it to be a bug when creat * does not accept
332 * tricky modes */
334 /* File is an existing dir */
335 if (creat("drwx", 0777) != FAIL)
336 err(11, CREAT, "create an existing dir!");
337 else
338 check(CREAT, EISDIR);
339 } /* test02 */
341 /*****************************************************************************
342 * test WRITE *
343 ****************************************************************************/
344 void test03()
346 int n, n1;
347 int fd[2];
348 char a[ARSIZE];
350 init_array(a);
352 /* Test write after a CREAT */
353 if ((n = creat("file03", 0700)) != FF) /* 'file03' only open file */
354 err(13, CREAT, "'file03'");
355 else {
356 write_standards(n, a); /* test simple writes, wrong input too */
357 try_close(n, "'file03'");
360 /* Test write after an OPEN */
361 if ((n = open("file03", W)) < 0)
362 err(5, OPEN, "'file03'");
363 else
364 write_standards(n, a); /* test simple writes, wrong input too */
366 /* Test write after a DUP */
367 if ((n1 = dup(n)) < 0)
368 err(5, DUP, "'file03'");
369 else {
370 write_standards(n1, a);
371 try_close(n1, "duplicated fd 'file03'");
374 /* Remove testfile */
375 Remove(n, "file03");
377 /* Test write after a PIPE */
378 if (pipe(fd) < 0)
379 err(5, PIPE, NIL);
380 else {
381 write_standards(fd[1], a);
382 try_close(fd[0], "'fd[0]'");
383 try_close(fd[1], "'fd[1]'");
386 /* Last test: does write check protections ? */
387 if ((n = open("drwx/r--", R)) < 0)
388 err(5, OPEN, "'drwx/r--'");
389 else {
390 if (write(n, a, ARSIZE) != FAIL)
391 err(11, WRITE, "write on non-writ. file");
392 else
393 check(WRITE, EBADF);
394 try_close(n, "'drwx/r--'");
396 } /* test03 */
398 void write_standards(filedes, a)
399 int filedes;
400 char a[];
403 /* Write must return written account of numbers */
404 if (write(filedes, a, ARSIZE) != ARSIZE) err(1, WRITE, "bad");
406 /* Try giving 'write' wrong input */
407 /* Wrong filedes */
408 if (write(-1, a, ARSIZE) != FAIL)
409 err(2, WRITE, "filedes");
410 else
411 check(WRITE, EBADF);
413 /* Wrong length (illegal) */
414 #ifndef PDPNOHANG
415 if (write(filedes, a, -ARSIZE) != FAIL)
416 err(2, WRITE, "length");
417 else
418 check(WRITE, EINVAL); /* EFAULT on vu45 */
419 #endif
420 } /* write_standards */
422 /* "t2.c", created by Rene Montsma and Menno Wilcke */
424 /*****************************************************************************
425 * test READ *
426 ****************************************************************************/
427 void test04()
429 int n, n1, fd[2];
430 char a[ARSIZE];
432 /* Test read after creat */
433 if ((n = creat("file04", 0700)) != FF) /* no other open files may be
434 * left */
435 err(13, CREAT, "'file04'");
436 else {
437 /* Closing and opening needed before writing */
438 try_close(n, "'file04'");
439 if ((n = open("file04", RW)) < 0) err(5, OPEN, "'file04'");
441 init_array(a);
443 if (write(n, a, ARSIZE) != ARSIZE)
444 err(1, WRITE, "bad");
445 else {
446 if (lseek(n, 0L, SEEK_SET) != 0) err(5, LSEEK, "'file04'");
447 read_standards(n, a);
448 read_more(n, a);
450 try_close(n, "'file04'");
453 /* Test read after OPEN */
454 if ((n = open("file04", R)) < 0)
455 err(5, OPEN, "'file04'");
456 else {
457 read_standards(n, a);
458 read_more(n, a);
459 try_close(n, "'file04'");
462 /* Test read after DUP */
463 if ((n = open("file04", R)) < 0) err(5, OPEN, "'file04'");
464 if ((n1 = dup(n)) < 0)
465 err(5, DUP, "'file04'");
466 else {
467 read_standards(n1, a);
468 read_more(n1, a);
469 try_close(n1, "duplicated fd 'file04'");
472 /* Remove testfile */
473 Remove(n, "file04");
475 /* Test read after pipe */
476 if (pipe(fd) < 0)
477 err(5, PIPE, NIL);
478 else {
479 if (write(fd[1], a, ARSIZE) != ARSIZE) {
480 err(5, WRITE, "'fd[1]'");
481 try_close(fd[1], "'fd[1]'");
482 } else {
483 try_close(fd[1], "'fd[1]'");
484 read_standards(fd[0], a);
486 try_close(fd[0], "'fd[0]'");
489 /* Last test: try to read a read-protected file */
490 if ((n = open("drwx/-wx", W)) < 0)
491 err(5, OPEN, "'drwx/-wx'");
492 else {
493 if (read(n, a, ARSIZE) != FAIL)
494 err(11, READ, "read a non-read. file");
495 else
496 check(READ, EBADF);
497 try_close(n, "'/drwx/-wx'");
499 } /* test04 */
501 void read_standards(filedes, a)
502 int filedes;
503 char a[];
505 char b[ARSIZE];
507 clear_array(b);
508 if (read(filedes, b, ARSIZE) != ARSIZE)
509 err(1, READ, "bad");
510 else if (comp_array(a, b, ARSIZE) != OK)
511 err(7, "read/write", "values");
512 else if (read(filedes, b, ARSIZE) != READ_EOF)
513 err(11, READ, "read beyond endoffile");
515 /* Try giving read wrong input: wrong filedes */
516 if (read(FAIL, b, ARSIZE) != FAIL)
517 err(2, READ, "filedes");
518 else
519 check(READ, EBADF);
521 /* Wrong length */
522 if (read(filedes, b, -ARSIZE) != FAIL)
523 err(2, READ, "length");
524 else
525 check(READ, EINVAL);
526 } /* read_standards */
528 void read_more(filedes, a)
529 int filedes;
530 char a[];
531 /* Separated from read_standards() because the PIPE test * would fail. */
533 int i;
534 char b[ARSIZE];
536 if (lseek(filedes, (long) (ARSIZE / 2), SEEK_SET) != ARSIZE / 2)
537 err(5, LSEEK, "to location ARSIZE/2");
539 clear_array(b);
540 if (read(filedes, b, ARSIZE) != ARSIZE / 2) err(1, READ, "bad");
542 for (i = 0; i < ARSIZE / 2; i++)
543 if (b[i] != a[(ARSIZE / 2) + i])
544 err(7, READ, "from location ARSIZE/2");
547 /*****************************************************************************
548 * test OPEN/CLOSE *
549 ****************************************************************************/
550 void test05()
552 int n, n1, mode, fd[2];
553 char b[ARSIZE];
555 /* Test open after CREAT */
556 if ((n = creat("file05", 0700)) != FF) /* no other open files left */
557 err(13, CREAT, "'file05'");
558 else {
559 if ((n1 = open("file05", RW)) != FF + 1)
560 err(13, OPEN, "'file05' after creation");
561 try_close(n1, "'file05' (open after creation)");
563 try_close(n, "'file05'");
564 if ((n = open("file05", R)) != FF)
565 err(13, OPEN, "after closing");
566 else
567 try_close(n, "'file05' (open after closing)");
569 /* Remove testfile */
570 try_unlink("file05");
573 /* Test all possible modes, try_open not only opens file (sometimes) *
574 * but closes files too (when opened) */
575 if ((n = creat("file05", 0700)) < 0) /* no other files left */
576 err(5, CREAT, "'file05' (2nd time)");
577 else {
578 try_close(n, "file05");
579 for (mode = 0; mode <= 0700; mode += 0100) {
580 if (chmod("file05", mode) != OK) err(5, CHMOD, "'file05'");
582 if (mode <= 0100) {
583 try_open("file05", R, FAIL);
584 try_open("file05", W, FAIL);
585 try_open("file05", RW, FAIL);
586 } else if (mode >= 0200 && mode <= 0300) {
587 try_open("file05", R, FAIL);
588 try_open("file05", W, FF);
589 try_open("file05", RW, FAIL);
590 } else if (mode >= 0400 && mode <= 0500) {
591 try_open("file05", R, FF);
592 try_open("file05", W, FAIL);
593 try_open("file05", RW, FAIL);
594 } else {
595 try_open("file05", R, FF);
596 try_open("file05", W, FF);
597 try_open("file05", RW, FF);
602 /* Test opening existing file */
603 if ((n = open("drwx/rwx", R)) < 0)
604 err(13, OPEN, "existing file");
605 else { /* test close after DUP */
606 if ((n1 = dup(n)) < 0)
607 err(13, DUP, "'drwx/rwx'");
608 else {
609 try_close(n1, "duplicated fd 'drwx/rwx'");
611 if (read(n1, b, ARSIZE) != FAIL)
612 err(11, READ, "on closed dupped fd 'drwx/rwx'");
613 else
614 check(READ, EBADF);
616 if (read(n, b, ARSIZE) == FAIL) /* should read an eof */
617 err(13, READ, "on fd '/drwx/rwx'");
619 try_close(n, "'drwx/rwx'");
622 /* Test close after PIPE */
623 if (pipe(fd) < 0)
624 err(13, PIPE, NIL);
625 else {
626 try_close(fd[1], "duplicated fd 'fd[1]'");
628 /* Fd[1] really should be closed now; check */
629 clear_array(b);
630 if (read(fd[0], b, ARSIZE) != READ_EOF)
631 err(11, READ, "read on empty pipe (and fd[1] was closed)");
632 try_close(fd[0], "duplicated fd 'fd[0]'");
635 /* Try to open a non-existing file */
636 if (open("non-file", R) != FAIL)
637 err(11, OPEN, "open non-executable file");
638 else
639 check(OPEN, ENOENT);
641 /* Dir does not exist */
642 if (open("dzzz/file05", R) != FAIL)
643 err(11, OPEN, "open in an non-searchable dir");
644 else
645 check(OPEN, ENOENT);
647 /* Dir is not searchable */
648 if (n = open("drw-/rwx", R) != FAIL)
649 err(11, OPEN, "open in an non-searchabledir");
650 else
651 check(OPEN, EACCES);
653 /* Unlink testfile */
654 try_unlink("file05");
656 /* File is not readable */
657 if (open("drwx/-wx", R) != FAIL)
658 err(11, OPEN, "open unreadable file for reading");
659 else
660 check(OPEN, EACCES);
662 /* File is not writable */
663 if (open("drwx/r-x", W) != FAIL)
664 err(11, OPEN, "open unwritable file for writing");
665 else
666 check(OPEN, EACCES);
668 /* Try opening more than MAXOPEN ('extra' (19-8-85)) files */
669 if ((n = open_alot()) != MAXOPEN)
670 err(13, OPEN, "MAXOPEN files");
671 else
672 /* Maximum # of files opened now, another open should fail
673 * because * all filedescriptors have already been used. */
674 if (open("drwx/rwx", RW) != FAIL)
675 err(9, OPEN, "open");
676 else
677 check(OPEN, EMFILE);
678 if (close_alot(n) != n) err(5, CLOSE, "all opened files");
680 /* Can close make mistakes ? */
681 if (close(-1) != FAIL)
682 err(2, CLOSE, "filedes");
683 else
684 check(CLOSE, EBADF);
685 } /* test05 */
687 void try_open(fname, mode, test)
688 int mode, test;
689 char *fname;
691 int n;
693 if ((n = open(fname, mode)) != test)
694 err(11, OPEN, "break through filepermission with an incorrect mode");
695 if (n != FAIL) try_close(n, fname); /* cleanup */
696 } /* try_open */
698 /*****************************************************************************
699 * test LSEEK *
700 ****************************************************************************/
701 void test06()
703 char a[ARSIZE], b[ARSIZE];
704 int fd;
706 if ((fd = open("drwx/rwx", RW)) != FF) /* there should be no */
707 err(13, OPEN, "'drwx/rwx'"); /* other open files */
708 else {
709 init_array(a);
710 if (write(fd, a, 10) != 10)
711 err(1, WRITE, "bad");
712 else {
713 /* Lseek back to begin file */
714 if (lseek(fd, 0L, SEEK_SET) != 0)
715 err(5, LSEEK, "to begin file");
716 else if (read(fd, b, 10) != 10)
717 err(1, READ, "bad");
718 else if (comp_array(a, b, 10) != OK)
719 err(7, LSEEK, "values r/w after lseek to begin");
720 /* Lseek to endoffile */
721 if (lseek(fd, 0L, SEEK_END) != 10)
722 err(5, LSEEK, "to end of file");
723 else if (read(fd, b, 1) != READ_EOF)
724 err(7, LSEEK, "read at end of file");
725 /* Lseek beyond file */
726 if (lseek(fd, 10L, SEEK_CUR) != 20)
727 err(5, LSEEK, "beyond end of file");
728 else if (write(fd, a, 10) != 10)
729 err(1, WRITE, "bad");
730 else {
731 /* Lseek to begin second write */
732 if (lseek(fd, 20L, SEEK_SET) != 20)
733 err(5, LSEEK, "'/drwx/rwx'");
734 if (read(fd, b, 10) != 10)
735 err(1, READ, "bad");
736 else if (comp_array(a, b, 10) != OK)
737 err(7, LSEEK,
738 "values read after lseek MAXOPEN");
742 /* Lseek to position before begin of file */
743 if (lseek(fd, -1L, 0) != FAIL)
744 err(11, LSEEK, "lseek before beginning of file");
746 try_close(fd, "'drwx/rwx'");
749 /* Lseek on invalid filediscriptor */
750 if (lseek(-1, 0L, SEEK_SET) != FAIL)
751 err(2, LSEEK, "filedes");
752 else
753 check(LSEEK, EBADF);
757 /* "t3.c", created by Rene Montsma and Menno Wilcke */
759 /*****************************************************************************
760 * test ACCESS *
761 ****************************************************************************/
762 void test07()
764 /* Check with proper parameters */
765 if (access("drwx/rwx", RWX) != OK) err(5, ACCESS, "accessible file");
767 if (access("./././drwx/././rwx", 0) != OK)
768 err(5, ACCESS, "'/./.(etc)/drwx///rwx'");
770 /* Check 8 files with 8 different modes on 8 accesses */
771 if (chdir("drwx") != OK) err(5, CHDIR, "'drwx'");
773 access_standards();
775 if (chdir("..") != OK) err(5, CHDIR, "'..'");
777 /* Check several wrong combinations */
778 /* File does not exist */
779 if (access("non-file", 0) != FAIL)
780 err(11, ACCESS, "access non-existing file");
781 else
782 check(ACCESS, ENOENT);
784 /* Non-searchable dir */
785 if (access("drw-/rwx", 0) != FAIL)
786 err(4, ACCESS, "'drw-'");
787 else
788 check(ACCESS, EACCES);
790 /* Searchable dir, but wrong file-mode */
791 if (access("drwx/--x", RWX) != FAIL)
792 err(11, ACCESS, "a non accessible file");
793 else
794 check(ACCESS, EACCES);
796 } /* test07 */
798 void access_standards()
800 int i, mode = 0;
802 for (i = 0; i < 8; i++)
803 if (i == 0)
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 < 2)
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 == 2)
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 < 4)
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 == 0 || i == 4)
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++)
838 if (i == 0 || i == 1 || i == 4 || i == 5)
839 try_access(fnames[mode], i, OK);
840 else
841 try_access(fnames[mode], i, FAIL);
842 mode++;
844 for (i = 0; i < 8; i++)
845 if (i % 2 == 0)
846 try_access(fnames[mode], i, OK);
847 else
848 try_access(fnames[mode], i, FAIL);
849 mode++;
851 for (i = 0; i < 8; i++) try_access(fnames[mode], i, OK);
852 } /* access_standards */
854 void try_access(fname, mode, test)
855 int mode, test;
856 char *fname;
858 if (access(fname, mode) != test)
859 err(100, ACCESS, "incorrect access on a file (try_access)");
860 } /* try_access */
862 /* "support.c", created by Rene Montsma and Menno Wilcke */
864 /* Err, make_and_fill_dirs, init_array, clear_array, comp_array,
865 try_close, try_unlink, Remove, get_mode, check, open_alot,
866 close_alot, clean_up_the_mess.
869 /*****************************************************************************
870 * test READV/WRITEV *
871 ****************************************************************************/
872 #define TEST8_BUFSZCOUNT 3
873 #define TEST8_BUFSZMAX 65536
874 #define TEST8_IOVCOUNT 4
876 void test08()
878 char buffer_read[TEST8_IOVCOUNT * TEST8_BUFSZMAX];
879 char buffer_write[TEST8_IOVCOUNT * TEST8_BUFSZMAX];
880 struct iovec iovec_read[TEST8_IOVCOUNT];
881 struct iovec iovec_write[TEST8_IOVCOUNT];
882 int fd, i, j, k, l, m;
883 ssize_t sz_read, sz_write;
884 size_t sz_read_exp, sz_read_sum, sz_write_sum;
886 /* try various combinations of buffer sizes */
887 for (i = 0; i <= TEST8_IOVCOUNT; i++)
888 for (j = 0; j < power(TEST8_BUFSZCOUNT, i); j++)
889 for (k = 0; k <= TEST8_IOVCOUNT; k++)
890 for (l = 0; l < power(TEST8_BUFSZCOUNT, k); l++)
892 /* put data in the buffers */
893 for (m = 0; m < sizeof(buffer_write); m++)
895 buffer_write[m] = m ^ (m >> 8);
896 buffer_read[m] = ~buffer_write[m];
899 /* set up the vectors to point to the buffers */
900 sz_read_sum = iovec_setup(j, iovec_read, buffer_read, i);
901 sz_write_sum = iovec_setup(l, iovec_write, buffer_write, k);
902 sz_read_exp = (sz_read_sum < sz_write_sum) ?
903 sz_read_sum : sz_write_sum;
905 /* test reading and writing */
906 if ((fd = open("file08", O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0)
907 err(13, OPEN, "'file08'");
908 else {
909 sz_write = writev(fd, iovec_write, k);
910 if (sz_write != sz_write_sum) err(5, WRITEV, "'file08'");
911 if (lseek(fd, 0, SEEK_SET) != 0) err(5, LSEEK, "'file08'");
912 sz_read = readv(fd, iovec_read, i);
913 if (sz_read != sz_read_exp)
914 err(5, READV, "'file08'");
915 else
917 if (!iovec_is_equal(iovec_read, iovec_write, sz_read))
918 err(8, READV, "'file08'");
921 /* Remove testfile */
922 Remove(fd, "file08");
925 } /* test08 */
927 static int iovec_is_equal(struct iovec *x, struct iovec *y, size_t size)
929 int xpos = 0, xvec = 0, ypos = 0, yvec = 0;
931 /* compare byte by byte */
932 while (size-- > 0)
934 /* skip over zero-byte buffers and those that have been completed */
935 while (xpos >= x[xvec].iov_len)
937 xpos -= x[xvec++].iov_len;
938 assert(xvec < TEST8_IOVCOUNT);
940 while (ypos >= y[yvec].iov_len)
942 ypos -= y[yvec++].iov_len;
943 assert(yvec < TEST8_IOVCOUNT);
946 /* compare */
947 if (((char *) x[xvec].iov_base)[xpos++] !=
948 ((char *) y[yvec].iov_base)[ypos++])
949 return 0;
952 /* no difference found */
953 return 1;
956 static size_t iovec_setup(int pattern, struct iovec *iovec, char *buffer, int count)
958 static const size_t bufsizes[TEST8_BUFSZCOUNT] = { 0, 1, TEST8_BUFSZMAX };
959 int i;
960 size_t sum = 0;
962 /* the pattern specifies each buffer */
963 for (i = 0; i < TEST8_IOVCOUNT; i++)
965 iovec->iov_base = buffer;
966 sum += iovec->iov_len = bufsizes[pattern % TEST8_BUFSZCOUNT];
968 iovec++;
969 buffer += TEST8_BUFSZMAX;
970 pattern /= TEST8_BUFSZCOUNT;
973 return sum;
976 static int power(int base, int exponent)
978 int result = 1;
980 /* compute base^exponent */
981 while (exponent-- > 0)
982 result *= base;
984 return result;
987 /***********************************************************************
988 * EXTENDED FIONS *
989 **********************************************************************/
990 /* First extended functions (i.e. not oldfashioned monixcalls.
991 e(), nlcr(), octal.*/
993 void e(string)
994 char *string;
996 printf("Test program error: %s\n", string);
997 errct++;
1000 void nlcr()
1002 printf("\n");
1005 void str(s)
1006 char *s;
1008 printf(s);
1011 /*****************************************************************************
1013 * ERR(or) messages *
1015 *****************************************************************************/
1016 void err(number, scall, name)
1017 /* Give nice error messages */
1019 char *scall, *name;
1020 int number;
1023 errct++;
1024 if (errct > MAXERR) {
1025 printf("Too many errors; test aborted\n");
1026 chdir("..");
1027 system("rm -rf DIR*");
1028 quit();
1030 e("");
1031 str("\t");
1032 switch (number) {
1033 case 0:
1034 str(scall);
1035 str(": illegal initial value.");
1036 break;
1037 case 1:
1038 str(scall);
1039 str(": ");
1040 str(name);
1041 str(" value returned.");
1042 break;
1043 case 2:
1044 str(scall);
1045 str(": accepting illegal ");
1046 str(name);
1047 str(".");
1048 break;
1049 case 3:
1050 str(scall);
1051 str(": accepting non-existing file.");
1052 break;
1053 case 4:
1054 str(scall);
1055 str(": could search non-searchable dir (");
1056 str(name);
1057 str(").");
1058 break;
1059 case 5:
1060 str(scall);
1061 str(": cannot ");
1062 str(scall);
1063 str(" ");
1064 str(name);
1065 str(".");
1066 break;
1067 case 7:
1068 str(scall);
1069 str(": incorrect ");
1070 str(name);
1071 str(".");
1072 break;
1073 case 8:
1074 str(scall);
1075 str(": wrong values.");
1076 break;
1077 case 9:
1078 str(scall);
1079 str(": accepting too many ");
1080 str(name);
1081 str(" files.");
1082 break;
1083 case 10:
1084 str(scall);
1085 str(": even a superuser can't do anything!");
1086 break;
1087 case 11:
1088 str(scall);
1089 str(": could ");
1090 str(name);
1091 str(".");
1092 break;
1093 case 12:
1094 str(scall);
1095 str(": could write in non-writable dir (");
1096 str(name);
1097 str(").");
1098 break;
1099 case 13:
1100 str(scall);
1101 str(": wrong filedes returned (");
1102 str(name);
1103 str(").");
1104 break;
1105 case 100:
1106 str(scall); /* very common */
1107 str(": ");
1108 str(name);
1109 str(".");
1110 break;
1111 default: str("errornumber does not exist!\n");
1113 nlcr();
1114 } /* err */
1116 /*****************************************************************************
1118 * MAKE_AND_FILL_DIRS *
1120 *****************************************************************************/
1122 void make_and_fill_dirs()
1123 /* Create 8 dir.'s: "d---", "d--x", "d-w-", "d-wx", "dr--", "dr-x", *
1124 * "drw-", "drwx". * Then create 8 files
1125 * in "drwx", and some needed files in other dirs. */
1127 int mode, i;
1129 for (i = 0; i < 8; i++) {
1130 mkdir(dir[i], 0700);
1131 chown(dir[i], USER_ID, GROUP_ID);
1133 setuid(USER_ID);
1134 setgid(GROUP_ID);
1136 for (mode = 0; mode < 8; mode++) put_file_in_dir("drwx", mode);
1138 put_file_in_dir("d-wx", RWX);
1139 put_file_in_dir("dr-x", RWX);
1140 put_file_in_dir("drw-", RWX);
1142 chmod_8_dirs(8); /* 8 means; 8 different modes */
1144 } /* make_and_fill_dirs */
1146 void put_file_in_dir(dirname, mode)
1147 char *dirname;
1148 int mode;
1149 /* Fill directory 'dirname' with file with mode 'mode'. */
1151 int nr;
1153 if (chdir(dirname) != OK)
1154 err(5, CHDIR, "to dirname (put_f_in_dir)");
1155 else {
1156 /* Creat the file */
1157 if ((nr = creat(fnames[mode], mode * 0100)) < 0)
1158 err(13, CREAT, fnames[mode]);
1159 else
1160 try_close(nr, fnames[mode]);
1162 if (chdir("..") != OK)
1163 err(5, CHDIR, "to previous dir (put_f_in_dir)");
1165 } /* put_file_in_dir */
1167 /*****************************************************************************
1169 * MISCELLANEOUS *
1171 *(all about arrays, 'try_close', 'try_unlink', 'Remove', 'get_mode') *
1173 *****************************************************************************/
1175 void init_array(a)
1176 char *a;
1178 int i;
1180 i = 0;
1181 while (i++ < ARSIZE) *a++ = 'a' + (i % 26);
1182 } /* init_array */
1184 void clear_array(b)
1185 char *b;
1187 int i;
1189 i = 0;
1190 while (i++ < ARSIZE) *b++ = '0';
1192 } /* clear_array */
1194 int comp_array(a, b, range)
1195 char *a, *b;
1196 int range;
1198 if ((range < 0) || (range > ARSIZE)) {
1199 err(100, "comp_array", "illegal range");
1200 return(FAIL);
1201 } else {
1202 while (range-- && (*a++ == *b++));
1203 if (*--a == *--b)
1204 return(OK);
1205 else
1206 return(FAIL);
1208 } /* comp_array */
1210 void try_close(filedes, name)
1211 int filedes;
1212 char *name;
1214 if (close(filedes) != OK) err(5, CLOSE, name);
1215 } /* try_close */
1217 void try_unlink(fname)
1218 char *fname;
1220 if (unlink(fname) != 0) err(5, UNLINK, fname);
1221 } /* try_unlink */
1223 void Remove(fdes, fname)
1224 int fdes;
1225 char *fname;
1227 try_close(fdes, fname);
1228 try_unlink(fname);
1229 } /* Remove */
1231 int get_mode(name)
1232 char *name;
1234 struct stat stbf1;
1236 if (stat(name, &stbf1) != OK) {
1237 err(5, STAT, name);
1238 return(stbf1.st_mode); /* return a mode which will cause *
1239 * error in the calling function *
1240 * (file/dir bit) */
1241 } else
1242 return(stbf1.st_mode & 07777); /* take last 4 bits */
1243 } /* get_mode */
1245 /*****************************************************************************
1247 * CHECK *
1249 *****************************************************************************/
1251 void check(scall, number)
1252 int number;
1253 char *scall;
1255 if (errno != number) {
1256 e(NIL);
1257 str("\t");
1258 str(scall);
1259 str(": bad errno-value: ");
1260 put(errno);
1261 str(" should have been: ");
1262 put(number);
1263 nlcr();
1265 } /* check */
1267 void put(nr)
1268 int nr;
1270 switch (nr) {
1271 case 0: str("unused"); break;
1272 case 1: str("EPERM"); break;
1273 case 2: str("ENOENT"); break;
1274 case 3: str("ESRCH"); break;
1275 case 4: str("EINTR"); break;
1276 case 5: str("EIO"); break;
1277 case 6: str("ENXIO"); break;
1278 case 7: str("E2BIG"); break;
1279 case 8: str("ENOEXEC"); break;
1280 case 9: str("EBADF"); break;
1281 case 10: str("ECHILD"); break;
1282 case 11: str("EAGAIN"); break;
1283 case 12: str("ENOMEM"); break;
1284 case 13: str("EACCES"); break;
1285 case 14: str("EFAULT"); break;
1286 case 15: str("ENOTBLK"); break;
1287 case 16: str("EBUSY"); break;
1288 case 17: str("EEXIST"); break;
1289 case 18: str("EXDEV"); break;
1290 case 19: str("ENODEV"); break;
1291 case 20: str("ENOTDIR"); break;
1292 case 21: str("EISDIR"); break;
1293 case 22: str("EINVAL"); break;
1294 case 23: str("ENFILE"); break;
1295 case 24: str("EMFILE"); break;
1296 case 25: str("ENOTTY"); break;
1297 case 26: str("ETXTBSY"); break;
1298 case 27: str("EFBIG"); break;
1299 case 28: str("ENOSPC"); break;
1300 case 29: str("ESPIPE"); break;
1301 case 30: str("EROFS"); break;
1302 case 31: str("EMLINK"); break;
1303 case 32: str("EPIPE"); break;
1304 case 33: str("EDOM"); break;
1305 case 34: str("ERANGE"); break;
1309 /*****************************************************************************
1311 * ALOT-functions *
1313 *****************************************************************************/
1315 int open_alot()
1317 int i;
1319 for (i = 0; i < MAXOPEN; i++)
1320 if (open(file[i], R) == FAIL) break;
1321 if (i == 0) err(5, "open_alot", "at all");
1322 return(i);
1323 } /* open_alot */
1325 int close_alot(number)
1326 int number;
1328 int i, count = 0;
1330 if (number > MAXOPEN)
1331 err(5, "close_alot", "accept this argument");
1332 else
1333 for (i = FF; i < number + FF; i++)
1334 if (close(i) != OK) count++;
1336 return(number - count); /* return number of closed files */
1337 } /* close_alot */
1339 /*****************************************************************************
1341 * CLEAN UP THE MESS *
1343 *****************************************************************************/
1345 void clean_up_the_mess()
1347 int i;
1348 char dirname[6];
1350 /* First remove 'alot' files */
1351 for (i = 0; i < MAXOPEN; i++) try_unlink(file[i]);
1353 /* Unlink the files in dir 'drwx' */
1354 if (chdir("drwx") != OK)
1355 err(5, CHDIR, "to 'drwx'");
1356 else {
1357 for (i = 0; i < 8; i++) try_unlink(fnames[i]);
1358 if (chdir("..") != OK) err(5, CHDIR, "to '..'");
1361 /* Before unlinking files in some dirs, make them writable */
1362 chmod_8_dirs(RWX);
1364 /* Unlink files in other dirs */
1365 try_unlink("d-wx/rwx");
1366 try_unlink("dr-x/rwx");
1367 try_unlink("drw-/rwx");
1369 /* Unlink dirs */
1370 for (i = 0; i < 8; i++) {
1371 strcpy(dirname, "d");
1372 strcat(dirname, fnames[i]);
1373 /* 'dirname' contains the directoryname */
1374 rmdir(dirname);
1377 /* FINISH */
1378 } /* clean_up_the_mess */
1380 void chmod_8_dirs(sw)
1381 int sw; /* if switch == 8, give all different
1382 * mode,else the same mode */
1384 int mode;
1385 int i;
1387 if (sw == 8)
1388 mode = 0;
1389 else
1390 mode = sw;
1392 for (i = 0; i < 8; i++) {
1393 chmod(dir[i], 040000 + mode * 0100);
1394 if (sw == 8) mode++;
1398 void quit()
1401 chdir("..");
1402 system("rm -rf DIR*");
1404 if (errct == 0) {
1405 printf("ok\n");
1406 exit(0);
1407 } else {
1408 printf("%d errors\n", errct);
1409 exit(1);