64-bit VFS_LSEEK_OFF
[minix3.git] / test / test18.c
blob6adb71407994ea34816d813006017f6a0d64dca9
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 max_error = 2;
68 #include "common.h"
71 /* "decl.c", created by Rene Montsma and Menno Wilcke */
73 /* Used in open_alot, close_alot */
74 char *file[MAXOPEN];
75 char *fnames[8] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"},
76 *dir[8] = {"d---", "d--x", "d-w-", "d-wx", "dr--", "dr-x", "drw-", "drwx"};
78 /* Needed for easy creating and deleting of directories */
80 /* "test.c", created by Rene Montsma and Menno Wilcke */
83 int main(int argc, char **argv);
84 void test(void);
85 void test01(void);
86 void test02(void);
87 void test03(void);
88 void write_standards(int filedes, char a []);
89 void test04(void);
90 void read_standards(int filedes, char a []);
91 void read_more(int filedes, char a []);
92 void test05(void);
93 void try_open(char *fname, int mode, int test);
94 void test06(void);
95 void test07(void);
96 void access_standards(void);
97 void test08(void);
98 static int iovec_is_equal(struct iovec *x, struct iovec *y, size_t
99 size);
100 static size_t iovec_setup(int pattern, struct iovec *iovec, char
101 *buffer, int count);
102 static int power(int base, int exponent);
103 void try_access(char *fname, int mode, int test);
104 void make_and_fill_dirs(void);
105 void put_file_in_dir(char *dirname, int mode);
106 void init_array(char *a);
107 void clear_array(char *b);
108 int comp_array(char *a, char *b, int range);
109 void try_close(int filedes, char *name);
110 void try_unlink(char *fname);
111 void Remove(int fdes, char *fname);
112 int get_mode(char *name);
113 void check(char *scall, int number);
114 void put(int nr);
115 int open_alot(void);
116 int close_alot(int number);
117 void clean_up_the_mess(void);
118 void chmod_8_dirs(int sw);
120 /*****************************************************************************
121 * TEST *
122 ****************************************************************************/
123 int main(int argc, char **argv)
125 int n, i;
126 pid_t child;
128 start(18);
130 /* Create filenames for MAXOPEN files, the *file[] array. */
131 for(i = 0; i < MAXOPEN; i++) {
132 if(asprintf(&file[i], "file%d", i) == -1) {
133 fprintf(stderr, "asprintf failed\n");
134 quit();
138 subtest = 0;
139 child = fork();
140 if (child == -1) {
141 e(1);
142 quit();
143 } else if (child == 0) {
144 test();
145 return(0);
146 } else {
147 wait(&n);
148 clean_up_the_mess();
149 quit();
152 return(-1);
155 void test()
157 umask(0); /* not honest, but i always forget */
159 test01();
160 make_and_fill_dirs();
161 test02();
162 test03();
163 test04();
164 test05();
165 test06();
166 test07();
167 test08();
168 umask(022);
169 } /* test */
171 /* "t1.c" created by Rene Montsma and Menno Wilcke */
173 /*****************************************************************************
174 * test UMASK *
175 ****************************************************************************/
176 void test01()
178 int oldvalue, newvalue, tempvalue;
179 int nr;
181 subtest = 1;
183 if ((oldvalue = umask(0777)) != 0) e(1);
185 /* Special test: only the lower 9 bits (protection bits) may part- *
186 * icipate. ~0777 means: 111 000 000 000. Giving this to umask must*
187 * not change any value. */
189 if ((newvalue = umask(~0777)) != 0777) e(2);
190 if (oldvalue == newvalue) e(3);
192 if ((tempvalue = umask(0)) != 0) e(4);
194 /* Now test all possible modes of umask on a file */
195 for (newvalue = MASK; newvalue >= 0; newvalue -= 0111) {
196 tempvalue = umask(newvalue);
197 if (tempvalue != oldvalue) {
198 e(5);
199 break; /* no use trying more */
200 } else if ((nr = creat("file01", 0777)) < 0)
201 e(6);
202 else {
203 try_close(nr, "'file01'");
204 if (get_mode("file01") != (MASK & ~newvalue)) e(7);
205 try_unlink("file01");
207 oldvalue = newvalue;
210 /* The loop has terminated with umask(0) */
211 if ((tempvalue = umask(0)) != 0) e(8);
212 } /* test01 */
214 /*****************************************************************************
215 * test CREAT *
216 ****************************************************************************/
217 void test02()
219 int n, n1, mode;
220 char a[ARSIZE], b[ARSIZE];
221 struct stat stbf1;
223 subtest = 2;
224 mode = 0;
225 /* Create MAXOPEN files, check filedes */
226 for (n = 0; n < MAXOPEN; n++) {
227 if (creat(file[n], mode) != FF + n)
228 e(1);
229 else {
230 if (get_mode(file[n]) != mode) e(2);
232 /* Change mode of file to standard mode, we want to *
233 * use a lot (20) of files to be opened later, see *
234 * open_alot(), close_alot(). */
235 if (chmod(file[n], 0700) != OK) e(3);
238 mode = (mode + 0100) % 01000;
241 /* Already twenty files opened; opening another has to fail */
242 if (creat("file02", 0777) != FAIL) e(4);
243 else
244 if (errno != EMFILE) e(5);;
247 /* Close all files: seems blunt, but it isn't because we've *
248 * checked all fd's already */
249 if ((n = close_alot(MAXOPEN)) < MAXOPEN) e(6);
251 /* Creat 1 file twice; check */
252 if ((n = creat("file02", 0777)) < 0) e(7);
253 else {
254 init_array(a);
255 if (write(n, a, ARSIZE) != ARSIZE) e(8);
257 if ((n1 = creat("file02", 0755)) < 0) e(9);
258 else {
259 /* Fd should be at the top after recreation */
260 if (lseek(n1, 0L, SEEK_END) != 0) e(10);
261 else {
262 /* Try to write on recreated file */
263 clear_array(b);
265 if (lseek(n1, 0L, SEEK_SET) != 0) e(11);
266 if (write(n1, a, ARSIZE) != ARSIZE) e(12);
268 /* In order to read we've to close and open again */
269 try_close(n1, "'file02' (2nd creation)");
270 if ((n1 = open("file02", RW)) < 0) e(13);
272 /* Continue */
273 if (lseek(n1, 0L, SEEK_SET) != 0) e(14);
274 if (read(n1, b, ARSIZE) != ARSIZE) e(15);
276 if (comp_array(a, b, ARSIZE) != OK) e(16);
278 if (get_mode("file02") != 0777) e(17);
279 try_close(n1, "recreated 'file02'");
282 Remove(n, "file02");
285 /* Give 'creat' wrong input: dir not searchable */
286 if (creat("drw-/file02", 0777) != FAIL) e(18);
287 else
288 if (errno != EACCES) e(19);
290 /* Dir not writable */
291 if (creat("dr-x/file02", 0777) != FAIL) e(20);
292 else
293 if (errno != EACCES) e(21);
295 /* File not writable */
296 if (creat("drwx/r-x", 0777) != FAIL) e(22);
297 else
298 if (errno != EACCES) e(23);
300 /* Try to creat a dir */
301 if ((n = creat("dir", 040777)) != FAIL) {
302 if (fstat(n, &stbf1) != OK) e(24);
303 else if (stbf1.st_mode != (mode_t) 0100777)
304 /* Cast because mode is negative :-(.
305 * HACK DEBUG FIXME: this appears to duplicate
306 * code in test17.c.
308 e(25);
309 Remove(n, "dir");
312 /* We don't consider it to be a bug when creat * does not accept
313 * tricky modes */
315 /* File is an existing dir */
316 if (creat("drwx", 0777) != FAIL) e(26);
317 else
318 if (errno != EISDIR) e(27);
319 } /* test02 */
321 /*****************************************************************************
322 * test WRITE *
323 ****************************************************************************/
324 void test03()
326 int n, n1;
327 int fd[2];
328 char a[ARSIZE];
330 subtest = 3;
331 init_array(a);
333 /* Test write after a CREAT */
334 if ((n = creat("file03", 0700)) != FF) e(1);
335 else {
336 write_standards(n, a); /* test simple writes, wrong input too */
337 try_close(n, "'file03'");
340 /* Test write after an OPEN */
341 if ((n = open("file03", W)) < 0) e(2);
342 else
343 write_standards(n, a); /* test simple writes, wrong input too */
345 /* Test write after a DUP */
346 if ((n1 = dup(n)) < 0) e(3);
347 else {
348 write_standards(n1, a);
349 try_close(n1, "duplicated fd 'file03'");
352 /* Remove testfile */
353 Remove(n, "file03");
355 /* Test write after a PIPE */
356 if (pipe(fd) < 0) e(4);
357 else {
358 write_standards(fd[1], a);
359 try_close(fd[0], "'fd[0]'");
360 try_close(fd[1], "'fd[1]'");
363 /* Last test: does write check protections ? */
364 if ((n = open("drwx/r--", R)) < 0) e(5);
365 else {
366 if (write(n, a, ARSIZE) != FAIL) e(6);
367 else
368 if (errno != EBADF) e(7);
369 try_close(n, "'drwx/r--'");
371 } /* test03 */
373 void write_standards(filedes, a)
374 int filedes;
375 char a[];
378 /* Write must return written account of numbers */
379 if (write(filedes, a, ARSIZE) != ARSIZE) e(80);
381 /* Try giving 'write' wrong input */
382 /* Wrong filedes */
383 if (write(-1, a, ARSIZE) != FAIL) e(81);
384 else
385 if (errno != EBADF) e(82);
387 /* Wrong length (illegal) */
388 #ifndef PDPNOHANG
389 if (write(filedes, a, -ARSIZE) != FAIL) e(83);
390 else
391 if (errno != EINVAL) e(84);
392 #endif
393 } /* write_standards */
396 /*****************************************************************************
397 * test READ *
398 ****************************************************************************/
399 void test04()
401 int n, n1, fd[2];
402 char a[ARSIZE];
404 subtest = 4;
406 /* Test read after creat */
407 if ((n = creat("file04", 0700)) != FF) e(1);
408 else {
409 /* Closing and opening needed before writing */
410 try_close(n, "'file04'");
411 if ((n = open("file04", RW)) < 0) e(2);
413 init_array(a);
415 if (write(n, a, ARSIZE) != ARSIZE) e(3);
416 else {
417 if (lseek(n, 0L, SEEK_SET) != 0) e(4);
418 read_standards(n, a);
419 read_more(n, a);
421 try_close(n, "'file04'");
424 /* Test read after OPEN */
425 if ((n = open("file04", R)) < 0) e(5);
426 else {
427 read_standards(n, a);
428 read_more(n, a);
429 try_close(n, "'file04'");
432 /* Test read after DUP */
433 if ((n = open("file04", R)) < 0) e(6);
434 if ((n1 = dup(n)) < 0) e(7);
435 else {
436 read_standards(n1, a);
437 read_more(n1, a);
438 try_close(n1, "duplicated fd 'file04'");
441 /* Remove testfile */
442 Remove(n, "file04");
444 /* Test read after pipe */
445 if (pipe(fd) < 0) e(8);
446 else {
447 if (write(fd[1], a, ARSIZE) != ARSIZE) {
448 e(9);
449 try_close(fd[1], "'fd[1]'");
450 } else {
451 try_close(fd[1], "'fd[1]'");
452 read_standards(fd[0], a);
454 try_close(fd[0], "'fd[0]'");
457 /* Last test: try to read a read-protected file */
458 if ((n = open("drwx/-wx", W)) < 0) e(10);
459 else {
460 if (read(n, a, ARSIZE) != FAIL) e(11);
461 else
462 if (errno != EBADF) e(12);
463 try_close(n, "'/drwx/-wx'");
465 } /* test04 */
467 void read_standards(filedes, a)
468 int filedes;
469 char a[];
471 char b[ARSIZE];
473 clear_array(b);
474 if (read(filedes, b, ARSIZE) != ARSIZE) e(85);
475 else if (comp_array(a, b, ARSIZE) != OK) e(86);
476 else if (read(filedes, b, ARSIZE) != READ_EOF) e(87);
478 /* Try giving read wrong input: wrong filedes */
479 if (read(FAIL, b, ARSIZE) != FAIL) e(88);
480 else
481 if (errno != EBADF) e(89);
483 /* Wrong length */
484 if (read(filedes, b, -ARSIZE) != FAIL) e(90);
485 else
486 if (errno != EINVAL) e(91);
487 } /* read_standards */
489 void read_more(filedes, a)
490 int filedes;
491 char a[];
492 /* Separated from read_standards() because the PIPE test * would fail. */
494 int i;
495 char b[ARSIZE];
497 if (lseek(filedes, (long) (ARSIZE / 2), SEEK_SET) != ARSIZE / 2) e(92);
499 clear_array(b);
500 if (read(filedes, b, ARSIZE) != ARSIZE / 2) e(93);
502 for (i = 0; i < ARSIZE / 2; i++)
503 if (b[i] != a[(ARSIZE / 2) + i]) e(94);
506 /*****************************************************************************
507 * test OPEN/CLOSE *
508 ****************************************************************************/
509 void test05()
511 int n, n1, mode, fd[2];
512 char b[ARSIZE];
514 subtest = 5;
515 /* Test open after CREAT */
516 if ((n = creat("file05", 0700)) != FF) e(1);
517 else {
518 if ((n1 = open("file05", RW)) != FF + 1) e(2);
519 try_close(n1, "'file05' (open after creation)");
521 try_close(n, "'file05'");
522 if ((n = open("file05", R)) != FF) e(3);
523 else
524 try_close(n, "'file05' (open after closing)");
526 /* Remove testfile */
527 try_unlink("file05");
530 /* Test all possible modes, try_open not only opens file (sometimes) *
531 * but closes files too (when opened) */
532 if ((n = creat("file05", 0700)) < 0) e(6);
533 else {
534 try_close(n, "file05");
535 for (mode = 0; mode <= 0700; mode += 0100) {
536 if (chmod("file05", mode) != OK) e(7);
538 if (mode <= 0100) {
539 try_open("file05", R, FAIL);
540 try_open("file05", W, FAIL);
541 try_open("file05", RW, FAIL);
542 } else if (mode >= 0200 && mode <= 0300) {
543 try_open("file05", R, FAIL);
544 try_open("file05", W, FF);
545 try_open("file05", RW, FAIL);
546 } else if (mode >= 0400 && mode <= 0500) {
547 try_open("file05", R, FF);
548 try_open("file05", W, FAIL);
549 try_open("file05", RW, FAIL);
550 } else {
551 try_open("file05", R, FF);
552 try_open("file05", W, FF);
553 try_open("file05", RW, FF);
558 /* Test opening existing file */
559 if ((n = open("drwx/rwx", R)) < 0) e(8);
560 else { /* test close after DUP */
561 if ((n1 = dup(n)) < 0) e(9);
562 else {
563 try_close(n1, "duplicated fd 'drwx/rwx'");
565 if (read(n1, b, ARSIZE) != FAIL) e(10);
566 else
567 if (errno != EBADF) e(11);
569 if (read(n, b, ARSIZE) == FAIL) e(12);/* should read an eof */
571 try_close(n, "'drwx/rwx'");
574 /* Test close after PIPE */
575 if (pipe(fd) < 0) e(13);
576 else {
577 try_close(fd[1], "duplicated fd 'fd[1]'");
579 /* Fd[1] really should be closed now; check */
580 clear_array(b);
581 if (read(fd[0], b, ARSIZE) != READ_EOF) e(14);
582 try_close(fd[0], "duplicated fd 'fd[0]'");
585 /* Try to open a non-existing file */
586 if (open("non-file", R) != FAIL) e(15);
587 else
588 if (errno != ENOENT) e(16);
590 /* Dir does not exist */
591 if (open("dzzz/file05", R) != FAIL) e(17);
592 else
593 if (errno != ENOENT) e(18);
595 /* Dir is not searchable */
596 if ((n = open("drw-/rwx", R)) != FAIL) e(19);
597 else
598 if (errno != EACCES) e(20);
600 /* Unlink testfile */
601 try_unlink("file05");
603 /* File is not readable */
604 if (open("drwx/-wx", R) != FAIL) e(21);
605 else
606 if (errno != EACCES) e(22);
608 /* File is not writable */
609 if (open("drwx/r-x", W) != FAIL) e(23);
610 else
611 if (errno != EACCES) e(24);
613 /* Try opening more than MAXOPEN ('extra' (19-8-85)) files */
614 if ((n = open_alot()) != MAXOPEN) e(25);
615 else
616 /* Maximum # of files opened now, another open should fail
617 * because * all filedescriptors have already been used. */
618 if (open("drwx/rwx", RW) != FAIL) e(26);
619 else
620 if (errno != EMFILE) e(27);
621 if (close_alot(n) != n) e(28);
623 /* Can close make mistakes ? */
624 if (close(-1) != FAIL) e(29);
625 else
626 if (errno != EBADF) e(30);
627 } /* test05 */
629 void try_open(fname, mode, test)
630 int mode, test;
631 char *fname;
633 int n;
635 if ((n = open(fname, mode)) != test) e(95);
636 if (n != FAIL) try_close(n, fname); /* cleanup */
637 } /* try_open */
639 /*****************************************************************************
640 * test LSEEK *
641 ****************************************************************************/
642 void test06()
644 char a[ARSIZE], b[ARSIZE];
645 int fd;
647 subtest = 6;
649 if ((fd = open("drwx/rwx", RW)) != FF) e(1);
650 else {
651 init_array(a);
652 if (write(fd, a, 10) != 10) e(2);
653 else {
654 /* Lseek back to begin file */
655 if (lseek(fd, 0L, SEEK_SET) != 0) e(3);
656 else if (read(fd, b, 10) != 10) e(4);
657 else if (comp_array(a, b, 10) != OK) e(5);
659 /* Lseek to endoffile */
660 if (lseek(fd, 0L, SEEK_END) != 10) e(6);
661 else if (read(fd, b, 1) != READ_EOF) e(7);
663 /* Lseek beyond file */
664 if (lseek(fd, 10L, SEEK_CUR) != 20) e(8);
665 else if (write(fd, a, 10) != 10) e(9);
666 else {
667 /* Lseek to begin second write */
668 if (lseek(fd, 20L, SEEK_SET) != 20) e(10);
669 if (read(fd, b, 10) != 10) e(11);
670 else if (comp_array(a, b, 10) != OK) e(12);
674 /* Lseek to position before begin of file */
675 if (lseek(fd, -1L, 0) != FAIL) e(13);
677 try_close(fd, "'drwx/rwx'");
680 /* Lseek on invalid filediscriptor */
681 if (lseek(-1, 0L, SEEK_SET) != FAIL) e(14);
682 else
683 if (errno != EBADF) e(15);
687 /*****************************************************************************
688 * test ACCESS *
689 ****************************************************************************/
690 void test07()
692 subtest = 7;
694 /* Check with proper parameters */
695 if (access("drwx/rwx", RWX) != OK) e(1);
697 if (access("./././drwx/././rwx", 0) != OK) e(2);
699 /* Check 8 files with 8 different modes on 8 accesses */
700 if (chdir("drwx") != OK) e(3);
702 access_standards();
704 if (chdir("..") != OK) e(4);
706 /* Check several wrong combinations */
707 /* File does not exist */
708 if (access("non-file", 0) != FAIL) e(5);
709 else
710 if (errno != ENOENT) e(6);
712 /* Non-searchable dir */
713 if (access("drw-/rwx", 0) != FAIL) e(7);
714 else
715 if (errno != EACCES) e(8);
717 /* Searchable dir, but wrong file-mode */
718 if (access("drwx/--x", RWX) != FAIL) e(9);
719 else
720 if (errno != EACCES) e(10);
722 } /* test07 */
724 void access_standards()
726 int i, mode = 0;
728 for (i = 0; i < 8; i++)
729 if (i == 0)
730 try_access(fnames[mode], i, OK);
731 else
732 try_access(fnames[mode], i, FAIL);
733 mode++;
735 for (i = 0; i < 8; i++)
736 if (i < 2)
737 try_access(fnames[mode], i, OK);
738 else
739 try_access(fnames[mode], i, FAIL);
740 mode++;
742 for (i = 0; i < 8; i++)
743 if (i == 0 || i == 2)
744 try_access(fnames[mode], i, OK);
745 else
746 try_access(fnames[mode], i, FAIL);
747 mode++;
749 for (i = 0; i < 8; i++)
750 if (i < 4)
751 try_access(fnames[mode], i, OK);
752 else
753 try_access(fnames[mode], i, FAIL);
754 mode++;
756 for (i = 0; i < 8; i++)
757 if (i == 0 || i == 4)
758 try_access(fnames[mode], i, OK);
759 else
760 try_access(fnames[mode], i, FAIL);
761 mode++;
763 for (i = 0; i < 8; i++)
764 if (i == 0 || i == 1 || i == 4 || i == 5)
765 try_access(fnames[mode], i, OK);
766 else
767 try_access(fnames[mode], i, FAIL);
768 mode++;
770 for (i = 0; i < 8; i++)
771 if (i % 2 == 0)
772 try_access(fnames[mode], i, OK);
773 else
774 try_access(fnames[mode], i, FAIL);
775 mode++;
777 for (i = 0; i < 8; i++) try_access(fnames[mode], i, OK);
778 } /* access_standards */
780 void try_access(fname, mode, test)
781 int mode, test;
782 char *fname;
784 if (access(fname, mode) != test) e(96);
785 } /* try_access */
788 /* Err, make_and_fill_dirs, init_array, clear_array, comp_array,
789 try_close, try_unlink, Remove, get_mode, check, open_alot,
790 close_alot, clean_up_the_mess.
793 /*****************************************************************************
794 * test READV/WRITEV *
795 ****************************************************************************/
796 #define TEST8_BUFSZCOUNT 3
797 #define TEST8_BUFSZMAX 65536
798 #define TEST8_IOVCOUNT 4
800 void test08()
802 char buffer_read[TEST8_IOVCOUNT * TEST8_BUFSZMAX];
803 char buffer_write[TEST8_IOVCOUNT * TEST8_BUFSZMAX];
804 struct iovec iovec_read[TEST8_IOVCOUNT];
805 struct iovec iovec_write[TEST8_IOVCOUNT];
806 int fd, i, j, k, l, m;
807 ssize_t sz_read, sz_write;
808 size_t sz_read_exp, sz_read_sum, sz_write_sum;
810 subtest = 8;
812 /* try various combinations of buffer sizes */
813 for (i = 0; i <= TEST8_IOVCOUNT; i++)
814 for (j = 0; j < power(TEST8_BUFSZCOUNT, i); j++)
815 for (k = 0; k <= TEST8_IOVCOUNT; k++)
816 for (l = 0; l < power(TEST8_BUFSZCOUNT, k); l++)
818 /* put data in the buffers */
819 for (m = 0; m < sizeof(buffer_write); m++)
821 buffer_write[m] = m ^ (m >> 8);
822 buffer_read[m] = ~buffer_write[m];
825 /* set up the vectors to point to the buffers */
826 sz_read_sum = iovec_setup(j, iovec_read, buffer_read, i);
827 sz_write_sum = iovec_setup(l, iovec_write, buffer_write, k);
828 sz_read_exp = (sz_read_sum < sz_write_sum) ?
829 sz_read_sum : sz_write_sum;
831 /* test reading and writing */
832 if ((fd = open("file08", O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0) e(1);
833 else {
834 sz_write = writev(fd, iovec_write, k);
835 if (sz_write != sz_write_sum) e(2);
836 if (lseek(fd, 0, SEEK_SET) != 0) e(3);
837 sz_read = readv(fd, iovec_read, i);
838 if (sz_read != sz_read_exp) e(4);
839 else {
840 if (!iovec_is_equal(iovec_read, iovec_write, sz_read))
841 e(5);
844 /* Remove testfile */
845 Remove(fd, "file08");
848 } /* test08 */
850 static int iovec_is_equal(struct iovec *x, struct iovec *y, size_t size)
852 int xpos = 0, xvec = 0, ypos = 0, yvec = 0;
854 /* compare byte by byte */
855 while (size-- > 0)
857 /* skip over zero-byte buffers and those that have been completed */
858 while (xpos >= x[xvec].iov_len)
860 xpos -= x[xvec++].iov_len;
861 assert(xvec < TEST8_IOVCOUNT);
863 while (ypos >= y[yvec].iov_len)
865 ypos -= y[yvec++].iov_len;
866 assert(yvec < TEST8_IOVCOUNT);
869 /* compare */
870 if (((char *) x[xvec].iov_base)[xpos++] !=
871 ((char *) y[yvec].iov_base)[ypos++])
872 return 0;
875 /* no difference found */
876 return 1;
879 static size_t iovec_setup(int pattern, struct iovec *iovec, char *buffer, int count)
881 static const size_t bufsizes[TEST8_BUFSZCOUNT] = { 0, 1, TEST8_BUFSZMAX };
882 int i;
883 size_t sum = 0;
885 /* the pattern specifies each buffer */
886 for (i = 0; i < TEST8_IOVCOUNT; i++)
888 iovec->iov_base = buffer;
889 sum += iovec->iov_len = bufsizes[pattern % TEST8_BUFSZCOUNT];
891 iovec++;
892 buffer += TEST8_BUFSZMAX;
893 pattern /= TEST8_BUFSZCOUNT;
896 return sum;
899 static int power(int base, int exponent)
901 int result = 1;
903 /* compute base^exponent */
904 while (exponent-- > 0)
905 result *= base;
907 return result;
911 /*****************************************************************************
913 * MAKE_AND_FILL_DIRS *
915 *****************************************************************************/
917 void make_and_fill_dirs()
918 /* Create 8 dir.'s: "d---", "d--x", "d-w-", "d-wx", "dr--", "dr-x", *
919 * "drw-", "drwx". * Then create 8 files
920 * in "drwx", and some needed files in other dirs. */
922 int mode, i;
924 for (i = 0; i < 8; i++) {
925 mkdir(dir[i], 0700);
926 chown(dir[i], USER_ID, GROUP_ID);
928 setuid(USER_ID);
929 setgid(GROUP_ID);
931 for (mode = 0; mode < 8; mode++) put_file_in_dir("drwx", mode);
933 put_file_in_dir("d-wx", RWX);
934 put_file_in_dir("dr-x", RWX);
935 put_file_in_dir("drw-", RWX);
937 chmod_8_dirs(8); /* 8 means; 8 different modes */
939 } /* make_and_fill_dirs */
941 void put_file_in_dir(dirname, mode)
942 char *dirname;
943 int mode;
944 /* Fill directory 'dirname' with file with mode 'mode'. */
946 int nr;
948 if (chdir(dirname) != OK) e(97);
949 else {
950 /* Creat the file */
951 if ((nr = creat(fnames[mode], mode * 0100)) < 0) e(98);
952 else
953 try_close(nr, fnames[mode]);
955 if (chdir("..") != OK) e(99);
957 } /* put_file_in_dir */
959 /*****************************************************************************
961 * MISCELLANEOUS *
963 *(all about arrays, 'try_close', 'try_unlink', 'Remove', 'get_mode') *
965 *****************************************************************************/
967 void init_array(a)
968 char *a;
970 int i;
972 i = 0;
973 while (i++ < ARSIZE) *a++ = 'a' + (i % 26);
974 } /* init_array */
976 void clear_array(b)
977 char *b;
979 int i;
981 i = 0;
982 while (i++ < ARSIZE) *b++ = '0';
984 } /* clear_array */
986 int comp_array(a, b, range)
987 char *a, *b;
988 int range;
990 assert(range >= 0 && range <= ARSIZE);
992 while (range-- && (*a++ == *b++));
993 if (*--a == *--b)
994 return(OK);
995 else
996 return(FAIL);
997 } /* comp_array */
999 void try_close(filedes, name)
1000 int filedes;
1001 char *name;
1003 if (close(filedes) != OK) e(100);
1004 } /* try_close */
1006 void try_unlink(fname)
1007 char *fname;
1009 if (unlink(fname) != 0) e(101);
1010 } /* try_unlink */
1012 void Remove(fdes, fname)
1013 int fdes;
1014 char *fname;
1016 try_close(fdes, fname);
1017 try_unlink(fname);
1018 } /* Remove */
1020 int get_mode(name)
1021 char *name;
1023 struct stat stbf1;
1025 if (stat(name, &stbf1) != OK) {
1026 e(102);
1027 return(stbf1.st_mode); /* return a mode which will cause *
1028 * error in the calling function *
1029 * (file/dir bit) */
1030 } else
1031 return(stbf1.st_mode & 07777); /* take last 4 bits */
1032 } /* get_mode */
1035 /*****************************************************************************
1037 * ALOT-functions *
1039 *****************************************************************************/
1041 int open_alot()
1043 int i;
1045 for (i = 0; i < MAXOPEN; i++)
1046 if (open(file[i], R) == FAIL) break;
1048 if (i == 0)
1049 e(103);
1050 return(i);
1051 } /* open_alot */
1053 int close_alot(number)
1054 int number;
1056 int i, count = 0;
1058 if (number > MAXOPEN) e(104);
1059 else
1060 for (i = FF; i < number + FF; i++)
1061 if (close(i) != OK) count++;
1063 return(number - count); /* return number of closed files */
1064 } /* close_alot */
1066 /*****************************************************************************
1068 * CLEAN UP THE MESS *
1070 *****************************************************************************/
1072 void clean_up_the_mess()
1074 int i;
1075 char dirname[6];
1077 /* First remove 'alot' files */
1078 for (i = 0; i < MAXOPEN; i++) try_unlink(file[i]);
1080 /* Unlink the files in dir 'drwx' */
1081 if (chdir("drwx") != OK) e(105);
1082 else {
1083 for (i = 0; i < 8; i++) try_unlink(fnames[i]);
1084 if (chdir("..") != OK) e(106);
1087 /* Before unlinking files in some dirs, make them writable */
1088 chmod_8_dirs(RWX);
1090 /* Unlink files in other dirs */
1091 try_unlink("d-wx/rwx");
1092 try_unlink("dr-x/rwx");
1093 try_unlink("drw-/rwx");
1095 /* Unlink dirs */
1096 for (i = 0; i < 8; i++) {
1097 strcpy(dirname, "d");
1098 strcat(dirname, fnames[i]);
1099 /* 'dirname' contains the directoryname */
1100 rmdir(dirname);
1103 /* FINISH */
1104 } /* clean_up_the_mess */
1106 void chmod_8_dirs(sw)
1107 int sw; /* if switch == 8, give all different
1108 * mode,else the same mode */
1110 int mode;
1111 int i;
1113 if (sw == 8)
1114 mode = 0;
1115 else
1116 mode = sw;
1118 for (i = 0; i < 8; i++) {
1119 chmod(dir[i], 040000 + mode * 0100);
1120 if (sw == 8) mode++;