1 /* test 18 */ 2 3 /* Comment on usage and program: ark!/mnt/rene/prac/os/unix/comment.changes */ 4 5 /* "const.h", created by Rene Montsma and Menno Wilcke */ 6 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> 19 20 #define NOCRASH 1 /* test11(), 2nd pipe */ 21 #define PDPNOHANG 1 /* test03(), write_standards() */ 22 #define MAXERR 5 23 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 */ 29 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 */ 36 37 #define OK 0 38 #define FAIL -1 39 40 #define R 0 /* read (open-call) */ 41 #define W 1 /* write (open-call) */ 42 #define RW 2 /* read & write (open-call) */ 43 44 #define RWX 7 /* read & write & execute (mode) */ 45 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" 66 67 int max_error = 2; 68 #include "common.h" 69 70 71 /* "decl.c", created by Rene Montsma and Menno Wilcke */ 72 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"}; 77 78 /* Needed for easy creating and deleting of directories */ 79 80 /* "test.c", created by Rene Montsma and Menno Wilcke */ 81 82 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); 119 120 /***************************************************************************** 121 * TEST * 122 ****************************************************************************/ 123 int main(int argc, char **argv) 124 { 125 int n, i; 126 pid_t child; 127 128 start(18); 129 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(); 135 } 136 } 137 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(); 150 } 151 152 return(-1); 153 } 154 155 void test() 156 { 157 umask(0); /* not honest, but i always forget */ 158 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 */ 170 171 /* "t1.c" created by Rene Montsma and Menno Wilcke */ 172 173 /***************************************************************************** 174 * test UMASK * 175 ****************************************************************************/ 176 void test01() 177 { 178 int oldvalue, newvalue, tempvalue; 179 int nr; 180 181 subtest = 1; 182 183 if ((oldvalue = umask(0777)) != 0) e(1); 184 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. */ 188 189 if ((newvalue = umask(~0777)) != 0777) e(2); 190 if (oldvalue == newvalue) e(3); 191 192 if ((tempvalue = umask(0)) != 0) e(4); 193 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"); 206 } 207 oldvalue = newvalue; 208 } 209 210 /* The loop has terminated with umask(0) */ 211 if ((tempvalue = umask(0)) != 0) e(8); 212 } /* test01 */ 213 214 /***************************************************************************** 215 * test CREAT * 216 ****************************************************************************/ 217 void test02() 218 { 219 int n, n1, mode; 220 char a[ARSIZE], b[ARSIZE]; 221 struct stat stbf1; 222 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); 231 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); 236 237 } 238 mode = (mode + 0100) % 01000; 239 } 240 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);; 245 246 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); 250 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); 256 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); 264 265 if (lseek(n1, 0L, SEEK_SET) != 0) e(11); 266 if (write(n1, a, ARSIZE) != ARSIZE) e(12); 267 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); 271 272 /* Continue */ 273 if (lseek(n1, 0L, SEEK_SET) != 0) e(14); 274 if (read(n1, b, ARSIZE) != ARSIZE) e(15); 275 276 if (comp_array(a, b, ARSIZE) != OK) e(16); 277 } 278 if (get_mode("file02") != 0777) e(17); 279 try_close(n1, "recreated 'file02'"); 280 281 } 282 Remove(n, "file02"); 283 } 284 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); 289 290 /* Dir not writable */ 291 if (creat("dr-x/file02", 0777) != FAIL) e(20); 292 else 293 if (errno != EACCES) e(21); 294 295 /* File not writable */ 296 if (creat("drwx/r-x", 0777) != FAIL) e(22); 297 else 298 if (errno != EACCES) e(23); 299 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. 307 */ 308 e(25); 309 Remove(n, "dir"); 310 } 311 312 /* We don't consider it to be a bug when creat * does not accept 313 * tricky modes */ 314 315 /* File is an existing dir */ 316 if (creat("drwx", 0777) != FAIL) e(26); 317 else 318 if (errno != EISDIR) e(27); 319 } /* test02 */ 320 321 /***************************************************************************** 322 * test WRITE * 323 ****************************************************************************/ 324 void test03() 325 { 326 int n, n1; 327 int fd[2]; 328 char a[ARSIZE]; 329 330 subtest = 3; 331 init_array(a); 332 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'"); 338 } 339 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 */ 344 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'"); 350 } 351 352 /* Remove testfile */ 353 Remove(n, "file03"); 354 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]'"); 361 } 362 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--'"); 370 } 371 } /* test03 */ 372 373 void write_standards(filedes, a) 374 int filedes; 375 char a[]; 376 { 377 378 /* Write must return written account of numbers */ 379 if (write(filedes, a, ARSIZE) != ARSIZE) e(80); 380 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); 386 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 */ 394 395 396 /***************************************************************************** 397 * test READ * 398 ****************************************************************************/ 399 void test04() 400 { 401 int n, n1, fd[2]; 402 char a[ARSIZE]; 403 404 subtest = 4; 405 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); 412 413 init_array(a); 414 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); 420 } 421 try_close(n, "'file04'"); 422 } 423 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'"); 430 } 431 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'"); 439 } 440 441 /* Remove testfile */ 442 Remove(n, "file04"); 443 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); 453 } 454 try_close(fd[0], "'fd[0]'"); 455 } 456 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'"); 464 } 465 } /* test04 */ 466 467 void read_standards(filedes, a) 468 int filedes; 469 char a[]; 470 { 471 char b[ARSIZE]; 472 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); 477 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); 482 483 /* Wrong length */ 484 if (read(filedes, b, -ARSIZE) != FAIL) e(90); 485 else 486 if (errno != EINVAL) e(91); 487 } /* read_standards */ 488 489 void read_more(filedes, a) 490 int filedes; 491 char a[]; 492 /* Separated from read_standards() because the PIPE test * would fail. */ 493 { 494 int i; 495 char b[ARSIZE]; 496 497 if (lseek(filedes, (long) (ARSIZE / 2), SEEK_SET) != ARSIZE / 2) e(92); 498 499 clear_array(b); 500 if (read(filedes, b, ARSIZE) != ARSIZE / 2) e(93); 501 502 for (i = 0; i < ARSIZE / 2; i++) 503 if (b[i] != a[(ARSIZE / 2) + i]) e(94); 504 } 505 506 /***************************************************************************** 507 * test OPEN/CLOSE * 508 ****************************************************************************/ 509 void test05() 510 { 511 int n, n1, mode, fd[2]; 512 char b[ARSIZE]; 513 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)"); 520 521 try_close(n, "'file05'"); 522 if ((n = open("file05", R)) != FF) e(3); 523 else 524 try_close(n, "'file05' (open after closing)"); 525 526 /* Remove testfile */ 527 try_unlink("file05"); 528 } 529 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); 537 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); 554 } 555 } 556 } 557 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'"); 564 565 if (read(n1, b, ARSIZE) != FAIL) e(10); 566 else 567 if (errno != EBADF) e(11); 568 569 if (read(n, b, ARSIZE) == FAIL) e(12);/* should read an eof */ 570 } 571 try_close(n, "'drwx/rwx'"); 572 } 573 574 /* Test close after PIPE */ 575 if (pipe(fd) < 0) e(13); 576 else { 577 try_close(fd[1], "duplicated fd 'fd[1]'"); 578 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]'"); 583 } 584 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); 589 590 /* Dir does not exist */ 591 if (open("dzzz/file05", R) != FAIL) e(17); 592 else 593 if (errno != ENOENT) e(18); 594 595 /* Dir is not searchable */ 596 if ((n = open("drw-/rwx", R)) != FAIL) e(19); 597 else 598 if (errno != EACCES) e(20); 599 600 /* Unlink testfile */ 601 try_unlink("file05"); 602 603 /* File is not readable */ 604 if (open("drwx/-wx", R) != FAIL) e(21); 605 else 606 if (errno != EACCES) e(22); 607 608 /* File is not writable */ 609 if (open("drwx/r-x", W) != FAIL) e(23); 610 else 611 if (errno != EACCES) e(24); 612 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); 622 623 /* Can close make mistakes ? */ 624 if (close(-1) != FAIL) e(29); 625 else 626 if (errno != EBADF) e(30); 627 } /* test05 */ 628 629 void try_open(fname, mode, test) 630 int mode, test; 631 char *fname; 632 { 633 int n; 634 635 if ((n = open(fname, mode)) != test) e(95); 636 if (n != FAIL) try_close(n, fname); /* cleanup */ 637 } /* try_open */ 638 639 /***************************************************************************** 640 * test LSEEK * 641 ****************************************************************************/ 642 void test06() 643 { 644 char a[ARSIZE], b[ARSIZE]; 645 int fd; 646 647 subtest = 6; 648 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); 658 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); 662 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); 671 } 672 } 673 674 /* Lseek to position before begin of file */ 675 if (lseek(fd, -1L, 0) != FAIL) e(13); 676 677 try_close(fd, "'drwx/rwx'"); 678 } 679 680 /* Lseek on invalid filediscriptor */ 681 if (lseek(-1, 0L, SEEK_SET) != FAIL) e(14); 682 else 683 if (errno != EBADF) e(15); 684 685 } 686 687 /***************************************************************************** 688 * test ACCESS * 689 ****************************************************************************/ 690 void test07() 691 { 692 subtest = 7; 693 694 /* Check with proper parameters */ 695 if (access("drwx/rwx", RWX) != OK) e(1); 696 697 if (access("./././drwx/././rwx", 0) != OK) e(2); 698 699 /* Check 8 files with 8 different modes on 8 accesses */ 700 if (chdir("drwx") != OK) e(3); 701 702 access_standards(); 703 704 if (chdir("..") != OK) e(4); 705 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); 711 712 /* Non-searchable dir */ 713 if (access("drw-/rwx", 0) != FAIL) e(7); 714 else 715 if (errno != EACCES) e(8); 716 717 /* Searchable dir, but wrong file-mode */ 718 if (access("drwx/--x", RWX) != FAIL) e(9); 719 else 720 if (errno != EACCES) e(10); 721 722 } /* test07 */ 723 724 void access_standards() 725 { 726 int i, mode = 0; 727 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++; 734 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++; 741 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++; 748 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++; 755 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++; 762 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++; 769 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++; 776 777 for (i = 0; i < 8; i++) try_access(fnames[mode], i, OK); 778 } /* access_standards */ 779 780 void try_access(fname, mode, test) 781 int mode, test; 782 char *fname; 783 { 784 if (access(fname, mode) != test) e(96); 785 } /* try_access */ 786 787 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. 791 */ 792 793 /***************************************************************************** 794 * test READV/WRITEV * 795 ****************************************************************************/ 796 #define TEST8_BUFSZCOUNT 3 797 #define TEST8_BUFSZMAX 65536 798 #define TEST8_IOVCOUNT 4 799 800 void test08() 801 { 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; 809 810 subtest = 8; 811 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++) 817 { 818 /* put data in the buffers */ 819 for (m = 0; m < sizeof(buffer_write); m++) 820 { 821 buffer_write[m] = m ^ (m >> 8); 822 buffer_read[m] = ~buffer_write[m]; 823 } 824 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; 830 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); 842 } 843 844 /* Remove testfile */ 845 Remove(fd, "file08"); 846 } 847 } 848 } /* test08 */ 849 850 static int iovec_is_equal(struct iovec *x, struct iovec *y, size_t size) 851 { 852 int xpos = 0, xvec = 0, ypos = 0, yvec = 0; 853 854 /* compare byte by byte */ 855 while (size-- > 0) 856 { 857 /* skip over zero-byte buffers and those that have been completed */ 858 while (xpos >= x[xvec].iov_len) 859 { 860 xpos -= x[xvec++].iov_len; 861 assert(xvec < TEST8_IOVCOUNT); 862 } 863 while (ypos >= y[yvec].iov_len) 864 { 865 ypos -= y[yvec++].iov_len; 866 assert(yvec < TEST8_IOVCOUNT); 867 } 868 869 /* compare */ 870 if (((char *) x[xvec].iov_base)[xpos++] != 871 ((char *) y[yvec].iov_base)[ypos++]) 872 return 0; 873 } 874 875 /* no difference found */ 876 return 1; 877 } 878 879 static size_t iovec_setup(int pattern, struct iovec *iovec, char *buffer, int count) 880 { 881 static const size_t bufsizes[TEST8_BUFSZCOUNT] = { 0, 1, TEST8_BUFSZMAX }; 882 int i; 883 size_t sum = 0; 884 885 /* the pattern specifies each buffer */ 886 for (i = 0; i < TEST8_IOVCOUNT; i++) 887 { 888 iovec->iov_base = buffer; 889 sum += iovec->iov_len = bufsizes[pattern % TEST8_BUFSZCOUNT]; 890 891 iovec++; 892 buffer += TEST8_BUFSZMAX; 893 pattern /= TEST8_BUFSZCOUNT; 894 } 895 896 return sum; 897 } 898 899 static int power(int base, int exponent) 900 { 901 int result = 1; 902 903 /* compute base^exponent */ 904 while (exponent-- > 0) 905 result *= base; 906 907 return result; 908 } 909 910 911 /***************************************************************************** 912 * * 913 * MAKE_AND_FILL_DIRS * 914 * * 915 *****************************************************************************/ 916 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. */ 921 { 922 int mode, i; 923 924 for (i = 0; i < 8; i++) { 925 mkdir(dir[i], 0700); 926 chown(dir[i], USER_ID, GROUP_ID); 927 } 928 setuid(USER_ID); 929 setgid(GROUP_ID); 930 931 for (mode = 0; mode < 8; mode++) put_file_in_dir("drwx", mode); 932 933 put_file_in_dir("d-wx", RWX); 934 put_file_in_dir("dr-x", RWX); 935 put_file_in_dir("drw-", RWX); 936 937 chmod_8_dirs(8); /* 8 means; 8 different modes */ 938 939 } /* make_and_fill_dirs */ 940 941 void put_file_in_dir(dirname, mode) 942 char *dirname; 943 int mode; 944 /* Fill directory 'dirname' with file with mode 'mode'. */ 945 { 946 int nr; 947 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]); 954 955 if (chdir("..") != OK) e(99); 956 } 957 } /* put_file_in_dir */ 958 959 /***************************************************************************** 960 * * 961 * MISCELLANEOUS * 962 * * 963 *(all about arrays, 'try_close', 'try_unlink', 'Remove', 'get_mode') * 964 * * 965 *****************************************************************************/ 966 967 void init_array(a) 968 char *a; 969 { 970 int i; 971 972 i = 0; 973 while (i++ < ARSIZE) *a++ = 'a' + (i % 26); 974 } /* init_array */ 975 976 void clear_array(b) 977 char *b; 978 { 979 int i; 980 981 i = 0; 982 while (i++ < ARSIZE) *b++ = '0'; 983 984 } /* clear_array */ 985 986 int comp_array(a, b, range) 987 char *a, *b; 988 int range; 989 { 990 assert(range >= 0 && range <= ARSIZE); 991 992 while (range-- && (*a++ == *b++)); 993 if (*--a == *--b) 994 return(OK); 995 else 996 return(FAIL); 997 } /* comp_array */ 998 999 void try_close(filedes, name) 1000 int filedes; 1001 char *name; 1002 { 1003 if (close(filedes) != OK) e(100); 1004 } /* try_close */ 1005 1006 void try_unlink(fname) 1007 char *fname; 1008 { 1009 if (unlink(fname) != 0) e(101); 1010 } /* try_unlink */ 1011 1012 void Remove(fdes, fname) 1013 int fdes; 1014 char *fname; 1015 { 1016 try_close(fdes, fname); 1017 try_unlink(fname); 1018 } /* Remove */ 1019 1020 int get_mode(name) 1021 char *name; 1022 { 1023 struct stat stbf1; 1024 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 */ 1033 1034 1035 /***************************************************************************** 1036 * * 1037 * ALOT-functions * 1038 * * 1039 *****************************************************************************/ 1040 1041 int open_alot() 1042 { 1043 int i; 1044 1045 for (i = 0; i < MAXOPEN; i++) 1046 if (open(file[i], R) == FAIL) break; 1047 1048 if (i == 0) 1049 e(103); 1050 return(i); 1051 } /* open_alot */ 1052 1053 int close_alot(number) 1054 int number; 1055 { 1056 int i, count = 0; 1057 1058 if (number > MAXOPEN) e(104); 1059 else 1060 for (i = FF; i < number + FF; i++) 1061 if (close(i) != OK) count++; 1062 1063 return(number - count); /* return number of closed files */ 1064 } /* close_alot */ 1065 1066 /***************************************************************************** 1067 * * 1068 * CLEAN UP THE MESS * 1069 * * 1070 *****************************************************************************/ 1071 1072 void clean_up_the_mess() 1073 { 1074 int i; 1075 char dirname[6]; 1076 1077 /* First remove 'alot' files */ 1078 for (i = 0; i < MAXOPEN; i++) try_unlink(file[i]); 1079 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); 1085 } 1086 1087 /* Before unlinking files in some dirs, make them writable */ 1088 chmod_8_dirs(RWX); 1089 1090 /* Unlink files in other dirs */ 1091 try_unlink("d-wx/rwx"); 1092 try_unlink("dr-x/rwx"); 1093 try_unlink("drw-/rwx"); 1094 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); 1101 } 1102 1103 /* FINISH */ 1104 } /* clean_up_the_mess */ 1105 1106 void chmod_8_dirs(sw) 1107 int sw; /* if switch == 8, give all different 1108 * mode,else the same mode */ 1109 { 1110 int mode; 1111 int i; 1112 1113 if (sw == 8) 1114 mode = 0; 1115 else 1116 mode = sw; 1117 1118 for (i = 0; i < 8; i++) { 1119 chmod(dir[i], 040000 + mode * 0100); 1120 if (sw == 8) mode++; 1121 } 1122 } 1123 1124