1 /* Comment on usage and program: ark!/mnt/rene/prac/os/unix/comment.changes */
3 /* "const.h", created by Rene Montsma and Menno Wilcke */
5 #include <sys/types.h> /* type defs */
6 #include <sys/stat.h> /* struct stat */
8 #include <errno.h> /* the error-numbers */
18 #define NOCRASH 1 /* test11(), 2nd pipe */
19 #define PDPNOHANG 1 /* test03(), write_standards() */
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 /* max number 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 */
35 #define MASK 0777 /* selects lower nine bits */
36 #define END_FILE 0 /* returned by read-call at eof */
41 #define R 0 /* read (open-call) */
42 #define W 1 /* write (open-call) */
43 #define RW 2 /* read & write (open-call) */
45 #define RWX 7 /* read & write & execute (mode) */
55 #define ACCESS "access"
59 #define UNLINK "unlink"
67 /* "decl.c", created by Rene Montsma and Menno Wilcke */
69 /* Used in open_alot, close_alot */
70 char *filenames
[MAXOPEN
];
73 char *mode_fnames
[MODES
] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"},
74 *mode_dir
[MODES
] = {"d---", "d--x", "d-w-", "d-wx", "dr--", "dr-x", "drw-", "drwx"};
76 /* Needed for easy creating and deleting of directories */
78 /* "test.c", created by Rene Montsma and Menno Wilcke */
81 int main(int argc
, char *argv
[]);
88 int link_alot(char *bigboss
);
89 int unlink_alot(int number
);
90 void get_new(char name
[]);
95 void put_file_in_dir(char *dirname
, int mode
);
96 void init_array(char *a
);
97 void clear_array(char *b
);
98 int comp_array(char *a
, char *b
, int range
);
99 void try_close(int filedes
, char *name
);
100 void try_unlink(char *fname
);
101 void Remove(int fdes
, char *fname
);
102 int get_mode(char *name
);
103 void check(char *scall
, int number
);
106 int close_alot(int number
);
107 void clean_up_the_mess(void);
108 void chmod_8_dirs(int sw
);
111 /*****************************************************************************
113 ****************************************************************************/
123 /* Create filenames for MAXOPEN files, the *filenames[] array. */
124 for(i
= 0; i
< MAXOPEN
; i
++) {
125 if(asprintf(&filenames
[i
], "file%d", i
) == -1) {
126 fprintf(stderr
, "asprintf failed\n");
132 mask
= (argc
== 2 ? atoi(argv
[1]) : 0xFFFF);
138 } else if (child
== 0) {
146 return(-1); /* impossible */
152 umask(0); /* not honest, but i always forget */
154 if (mask
& 00001) test01();
155 if (mask
& 00002) test03();
156 if (mask
& 00004) test02();
157 if (mask
& 00010) test08();
158 if (mask
& 00020) test09();
159 if (mask
& 00040) test10();
160 if (mask
& 00100) test11();
164 /* "t1.c" created by Rene Montsma and Menno Wilcke */
166 /*****************************************************************************
168 ****************************************************************************/
171 int oldvalue
, newvalue
, tempvalue
;
175 if ((oldvalue
= umask(0777)) != 0) e(1);
177 /* Special test: only the lower 9 bits (protection bits) may part- *
178 * icipate. ~0777 means: 111 000 000 000. Giving this to umask must*
179 * not change any value. */
181 if ((newvalue
= umask(~0777)) != 0777) e(2);
182 if (oldvalue
== newvalue
) e(3);
184 if ((tempvalue
= umask(0)) != 0) e(4);
186 /* Now test all possible modes of umask on a file */
187 for (newvalue
= MASK
; newvalue
>= 0; newvalue
-= 0111) {
188 tempvalue
= umask(newvalue
);
189 if (tempvalue
!= oldvalue
) {
191 break; /* no use trying more */
192 } else if ((nr
= creat("file01", 0777)) < 0)
195 try_close(nr
, "'file01'");
196 if (get_mode("file01") != (MASK
& ~newvalue
))
198 try_unlink("file01");
203 /* The loop has terminated with umask(0) */
204 if ((tempvalue
= umask(0)) != 0)
208 /*****************************************************************************
210 ****************************************************************************/
214 char a
[ARSIZE
], b
[ARSIZE
];
220 for (n
= 0; n
< MAXOPEN
; n
++) {
221 if (creat(filenames
[n
], mode
) != FF
+ n
)
224 if (get_mode(filenames
[n
]) != mode
)
227 /* Change mode of file to standard mode, we want to *
228 * use a lot (20) of files to be opened later, see *
229 * open_alot(), close_alot(). */
230 if (chmod(filenames
[n
], 0700) != OK
) e(3);
232 mode
= (mode
+ 0100) % 01000;
235 /* Already twenty files opened; opening another has to fail */
236 if (creat("file02", 0777) != FAIL
)
239 if (errno
!= EMFILE
) e(5);
241 /* Close all files: seems blunt, but it isn't because we've *
242 * checked all fd's already */
243 if ((n
= close_alot(MAXOPEN
)) < MAXOPEN
) e(6);
245 /* Creat 1 file twice; check */
246 if ((n
= creat("file02", 0777)) < 0)
250 if (write(n
, a
, ARSIZE
) != ARSIZE
) e(8);
252 if ((n1
= creat("file02", 0755)) < 0) /* receate 'file02' */
255 /* Fd should be at the top after recreation */
256 if (lseek(n1
, 0L, SEEK_END
) != 0)
259 /* Try to write on recreated file */
262 if (lseek(n1
, 0L, SEEK_SET
) != 0) e(11);
263 if (write(n1
, a
, ARSIZE
) != ARSIZE
) e(12);
265 /* In order to read we've to close and open again */
266 try_close(n1
, "'file02' (2nd creation)");
267 if ((n1
= open("file02", RW
)) < 0)
271 if (lseek(n1
, 0L, SEEK_SET
) != 0) e(14);
272 if (read(n1
, b
, ARSIZE
) != ARSIZE
) e(15);
274 if (comp_array(a
, b
, ARSIZE
) != OK
) e(16);
276 if (get_mode("file02") != 0777) e(17);
277 try_close(n1
, "recreated 'file02'");
283 /* Give 'creat' wrong input: dir not searchable */
284 if (creat("drw-/file02", 0777) != FAIL
) e(18);
286 if (errno
!= EACCES
) e(19);
288 /* Dir not writable */
289 if (creat("dr-x/file02", 0777) != FAIL
) e(20);
291 if (errno
!= EACCES
) e(21);
293 /* File not writable */
294 if (creat("drwx/r-x", 0777) != FAIL
) e(22);
296 if (errno
!= EACCES
) e(23);
298 /* Try to creat a dir */
299 if ((n
= creat("dir", 040777)) != FAIL
) {
300 if (fstat(n
, &stbf1
) != OK
) e(24);
301 else if (stbf1
.st_mode
!= (mode_t
) 0100777)
302 /* cast because mode is negative :-( */
307 /* We don't consider it to be a bug when creat * does not accept
310 /* File is an existing dir */
311 if (creat("drwx", 0777) != FAIL
) e(26);
313 if (errno
!= EISDIR
) e(27);
320 /* Test chdir to searchable dir */
321 if (chdir("drwx") != OK
) e(1);
322 else if (chdir("..") != OK
) e(2);
324 /* Check the chdir(".") and chdir("..") mechanism */
325 if (chdir("drwx") != OK
) e(3);
327 if (chdir(".") != OK
) e(4);
329 /* If we still are in 'drwx' , we should be able to access *
331 if (access("rwx", 0) != OK
) e(5);
333 /* Try to return to previous dir ('/' !!) */
334 if (chdir("././../././d--x/../d--x/././..") != OK
) e(6);
336 /* Check whether we are back in '/' */
337 if (chdir("d--x") != OK
) e(7);
338 } /* Return to '..' */
339 if (chdir("..") != OK
) e(8);
341 if (chdir("././././drwx") != OK
) e(9);
342 else if (chdir("././././..") != OK
) e(10);
344 /* Try giving chdir wrong parameters */
345 if (chdir("drwx/rwx") != FAIL
) e(11);
347 if (errno
!= ENOTDIR
) e(12);
349 if (chdir("drw-") != FAIL
) e(13);
351 if (errno
!= EACCES
) e(14);
355 /*****************************************************************************
357 ****************************************************************************/
365 if ((n
= creat("drwx/file09", 0644)) != FF
) e(1);
367 try_close(n
, "'file09'");
369 /* Try to chmod a file, check and restore old values, check */
370 if (chmod("drwx/file09", 0700) != OK
) e(2);
372 /* Check protection */
373 if (get_mode("drwx/file09") != 0700) e(3);
375 /* Test if chmod accepts just filenames too */
376 if (chdir("drwx") != OK
) e(4);
377 else if (chmod("file09", 0177) != OK
) e(5);
379 /* Check if value has been restored */
380 if (get_mode("../drwx/file09") != 0177) e(6);
383 /* Try setuid and setgid */
384 if ((chmod("file09", 04777) != OK
) || (get_mode("file09") != 04777))
386 if ((chmod("file09", 02777) != OK
) || (get_mode("file09") != 02777))
389 /* Remove testfile */
390 try_unlink("file09");
392 if (chdir("..") != OK
) e(9);
394 /* Try to chmod directory */
395 if (chmod("d---", 0777) != OK
) e(10);
397 if (get_mode("d---") != 0777) e(11);
398 if (chmod("d---", 0000) != OK
) e(12);
400 /* Check if old value has been restored */
401 if (get_mode("d---") != 0000) e(13);
404 /* Try to make chmod failures */
406 /* We still are in dir root */
408 if (chmod("non-file", 0777) != FAIL
) e(14);
410 if (errno
!= ENOENT
) e(15);
415 /* "t4.c", created by Rene Montsma and Menno Wilcke */
417 /*****************************************************************************
419 ****************************************************************************/
423 char a
[ARSIZE
], b
[ARSIZE
], *f
, *lf
;
430 if ((n
= creat(f
, 0702)) != FF
) e(1); /* no other open files */
432 /* Now link correctly */
433 if (link(f
, lf
) != OK
) e(2);
434 else if ((n1
= open(lf
, RW
)) < 0) e(3);
439 /* Write on 'file10' means being able to * read
440 * through linked filedescriptor */
441 if (write(n
, a
, ARSIZE
) != ARSIZE
) e(4);
442 if (read(n1
, b
, ARSIZE
) != ARSIZE
) e(5);
443 if (comp_array(a
, b
, ARSIZE
) != OK
) e(6);
445 /* Clean up: unlink and close (twice): */
447 try_close(n1
, "'linkfile10'");
449 /* Check if "linkfile" exists and the info * on it
450 * is correct ('file' has been deleted) */
451 if ((n1
= open(lf
, R
)) < 0) e(7);
453 /* See if 'linkfile' still contains 0..511 ? */
456 if (read(n1
, b
, ARSIZE
) != ARSIZE
) e(8);
457 if (comp_array(a
, b
, ARSIZE
) != OK
) e(9);
459 try_close(n1
, "'linkfile10' 2nd time");
465 /* Try if unlink fails with incorrect parameters */
466 /* File does not exist: */
467 if (unlink("non-file") != FAIL
) e(10);
469 if (errno
!= ENOENT
) e(11);
471 /* Dir can't be written */
472 if (unlink("dr-x/rwx") != FAIL
) e(12);
474 if (errno
!= EACCES
) e(13);
476 /* Try to unlink a dir being user */
477 if (unlink("drwx") != FAIL
) e(14);
479 if (errno
!= EPERM
) e(15);
481 /* Try giving link wrong input */
483 /* First try if link fails with incorrect parameters * name1 does not
485 if (link("non-file", "linkfile") != FAIL
) e(16);
487 if (errno
!= ENOENT
) e(17);
489 /* Name2 exists already */
490 if (link("drwx/rwx", "drwx/rw-") != FAIL
) e(18);
492 if (errno
!= EEXIST
) e(19);
494 /* Directory of name2 not writable: */
495 if (link("drwx/rwx", "dr-x/linkfile") != FAIL
) e(20);
497 if (errno
!= EACCES
) e(21);
499 /* Try to link a dir, being a user */
500 if (link("drwx", "linkfile") != FAIL
) e(22);
502 if (errno
!= EPERM
) e(23);
504 /* File has too many links */
505 if ((n
= link_alot("drwx/rwx")) != LINKCOUNT
- 1) /* file already has one
508 if (unlink_alot(n
) != n
) e(25);
512 int link_alot(bigboss
)
516 static char employee
[6] = "aaaaa";
518 /* Every file has already got 1 link, so link 0176 times */
519 for (i
= 1; i
< LINKCOUNT
; i
++) {
520 if (link(bigboss
, employee
) != OK
)
526 return(i
- 1); /* number of linked files */
529 int unlink_alot(number
)
530 int number
; /* number of files to be unlinked */
533 static char employee
[6] = "aaaaa";
535 for (j
= 0; j
< number
; j
++) {
536 if (unlink(employee
) != OK
)
542 return(j
); /* return number of unlinked files */
547 /* Every call changes string 'name' to a string alphabetically *
548 * higher. Start with "aaaaa", next value: "aaaab" . *
549 * N.B. after "aaaaz" comes "aaabz" and not "aaaba" (not needed). *
550 * The last possibility will be "zzzzz". *
551 * Total # possibilities: 26+25*4 = 126 = MAXLINK -1 (exactly needed) */
555 for (i
= 4; i
>= 0; i
--)
556 if (name
[i
] != 'z') {
563 /*****************************************************************************
565 ****************************************************************************/
569 char a
[ARSIZE
], b
[ARSIZE
];
573 if (pipe(fd
) != OK
) e(1);
575 /* Try reading and writing on a pipe */
579 if (write(fd
[1], a
, ARSIZE
) != ARSIZE
) e(2);
580 else if (read(fd
[0], b
, (ARSIZE
/ 2)) != (ARSIZE
/ 2)) e(3);
581 else if (comp_array(a
, b
, (ARSIZE
/ 2)) != OK
) e(4);
582 else if (read(fd
[0], b
, (ARSIZE
/ 2)) != (ARSIZE
/ 2)) e(5);
583 else if (comp_array(&a
[ARSIZE
/ 2], b
, (ARSIZE
/ 2)) != OK
) e(6);
585 /* Try to let the pipe make a mistake */
586 if (write(fd
[0], a
, ARSIZE
) != FAIL
) e(7);
587 if (read(fd
[1], b
, ARSIZE
) != FAIL
) e(8);
589 try_close(fd
[1], "'fd[1]'");
591 /* Now we shouldn't be able to read, because fd[1] has been closed */
592 if (read(fd
[0], b
, ARSIZE
) != END_FILE
) e(9);
594 try_close(fd
[0], "'fd[0]'");
596 if (pipe(fd
) < 0) e(10);
598 /* Test lseek on a pipe: should fail */
599 if (write(fd
[1], a
, ARSIZE
) != ARSIZE
) e(11);
600 if (lseek(fd
[1], 10L, SEEK_SET
) != FAIL
) e(12);
602 if (errno
!= ESPIPE
) e(13);
604 /* Eat half of the pipe: no writing should be possible */
605 try_close(fd
[0], "'fd[0]' (2nd time)");
607 /* This makes UNIX crash: omit it if pdp or VAX */
609 if (write(fd
[1], a
, ARSIZE
) != FAIL
) e(14);
611 if (errno
!= EPIPE
) e(15);
613 try_close(fd
[1], "'fd[1]' (2nd time)");
617 * Here we planned to test if we could write 4K bytes on a pipe. *
618 * However, this was not possible to implement, because the whole *
619 * Monix system crashed when we tried to write more then 3584 bytes *
620 * (3.5K) on a pipe. That's why we try to write only 3.5K in the *
622 if (pipe(fd
) < 0) e(16);
624 for (n
= 0; n
< (PIPESIZE
/ ARSIZE
); n
++)
625 if (write(fd
[1], a
, ARSIZE
) != ARSIZE
) e(17);
626 try_close(fd
[1], "'fd[1]' (3rd time)");
628 for (n
= 0; n
< (PIPESIZE
/ ARSIZE
); n
++)
629 if (read(fd
[0], b
, ARSIZE
) != ARSIZE
) e(18);
630 try_close(fd
[0], "'fd[0]' (3rd time)");
633 /* Test opening a lot of files */
634 if ((n
= open_alot()) != MAXOPEN
) e(19);
635 if (pipe(fd
) != FAIL
) e(20);
637 if (errno
!= EMFILE
) e(21);
638 if (close_alot(n
) != n
) e(22);
642 /* Err, test03, init_array, clear_array, comp_array,
643 try_close, try_unlink, Remove, get_mode, check, open_alot,
644 close_alot, clean_up_the_mess.
648 /*****************************************************************************
650 * MAKE_AND_FILL_DIRS *
652 *****************************************************************************/
655 /* Create 8 dir.'s: "d---", "d--x", "d-w-", "d-wx", "dr--", "dr-x", *
656 * "drw-", "drwx". * Then create 8 files
657 * in "drwx", and some needed files in other dirs. */
661 for (i
= 0; i
< MODES
; i
++) {
662 mkdir(mode_dir
[i
], 0700);
663 chown(mode_dir
[i
], USER_ID
, GROUP_ID
);
668 for (mode
= 0; mode
< 8; mode
++) put_file_in_dir("drwx", mode
);
670 put_file_in_dir("d-wx", RWX
);
671 put_file_in_dir("dr-x", RWX
);
672 put_file_in_dir("drw-", RWX
);
674 chmod_8_dirs(8); /* 8 means; 8 different modes */
678 void put_file_in_dir(dirname
, mode
)
681 /* Fill directory 'dirname' with file with mode 'mode'. */
685 if (chdir(dirname
) != OK
) e(1);
688 assert(mode
>= 0 && mode
< MODES
);
689 if ((nr
= creat(mode_fnames
[mode
], mode
* 0100)) < 0) e(2);
691 try_close(nr
, mode_fnames
[mode
]);
694 if (chdir("..") != OK
) e(3);
696 } /* put_file_in_dir */
698 /*****************************************************************************
702 *(all about arrays, 'try_close', 'try_unlink', 'Remove', 'get_mode')*
704 *****************************************************************************/
712 while (i
++ < ARSIZE
) *a
++ = 'a' + (i
% 26);
721 while (i
++ < ARSIZE
) *b
++ = '0';
725 int comp_array(a
, b
, range
)
729 assert(range
>= 0 && range
<= ARSIZE
);
730 while (range
-- && (*a
++ == *b
++));
737 void try_close(filedes
, name
)
741 if (close(filedes
) != OK
) e(90);
744 void try_unlink(fname
)
747 if (unlink(fname
) != 0) e(91);
750 void Remove(fdes
, fname
)
754 try_close(fdes
, fname
);
763 if (stat(name
, &stbf1
) != OK
) {
765 return(stbf1
.st_mode
); /* return a mode which will cause *
766 * error in the calling function *
769 return(stbf1
.st_mode
& 07777); /* take last 4 bits */
773 /*****************************************************************************
777 *****************************************************************************/
783 for (i
= 0; i
< MAXOPEN
; i
++)
784 if (open(filenames
[i
], R
) == FAIL
) break;
789 int close_alot(number
)
794 if (number
> MAXOPEN
)
797 for (i
= FF
; i
< number
+ FF
; i
++)
798 if (close(i
) != OK
) count
++;
800 return(number
- count
); /* return number of closed files */
803 /*****************************************************************************
805 * CLEAN UP THE MESS *
807 *****************************************************************************/
809 void clean_up_the_mess()
814 /* First remove 'a lot' files */
815 for (i
= 0; i
< MAXOPEN
; i
++) {
816 try_unlink(filenames
[i
]);
819 /* Unlink the files in dir 'drwx' */
820 if (chdir("drwx") != OK
)
823 for (i
= 0; i
< MODES
; i
++) {
824 try_unlink(mode_fnames
[i
]);
826 if (chdir("..") != OK
) e(96);
829 /* Before unlinking files in some dirs, make them writable */
832 /* Unlink files in other dirs */
833 try_unlink("d-wx/rwx");
834 try_unlink("dr-x/rwx");
835 try_unlink("drw-/rwx");
838 for (i
= 0; i
< MODES
; i
++) {
839 strcpy(dirname
, "d");
840 strcat(dirname
, mode_fnames
[i
]);
842 /* 'dirname' contains the directoryname */
847 } /* clean_up_the_mess */
849 void chmod_8_dirs(sw
)
850 int sw
; /* if switch == 8, give all different
851 * mode,else the same mode */
861 for (i
= 0; i
< MODES
; i
++) {
862 chmod(mode_dir
[i
], 040000 + mode
* 0100);