minix/test/test18.c
Thomas Veerman a209c3ae12 Fix a ton of compiler warnings
This patch fixes most of current reasons to generate compiler warnings.
The changes consist of:
 - adding missing casts
 - hiding or unhiding function declarations
 - including headers where missing
 - add __UNCONST when assigning a const char * to a char *
 - adding missing return statements
 - changing some types from unsigned to signed, as the code seems to want
   signed ints
 - converting old-style function definitions to current style (i.e.,
   void func(param1, param2) short param1, param2; {...} to
   void func (short param1, short param2) {...})
 - making the compiler silent about signed vs unsigned comparisons. We
   have too many of those in the new libc to fix.

A number of bugs in the test set were fixed. These bugs were never
triggered with our old libc. Consequently, these tests are now forced to
link with the new libc or they will generate errors (in particular tests 43
and 55).

Most changes in NetBSD libc are limited to moving aroudn "#ifndef __minix"
or stuff related to Minix-specific things (code in sys-minix or gen/minix).
2011-11-14 10:07:49 +00:00

1414 lines
36 KiB
C

/* test 18 */
/* Comment on usage and program: ark!/mnt/rene/prac/os/unix/comment.changes */
/* "const.h", created by Rene Montsma and Menno Wilcke */
#include <sys/types.h> /* needed in struct stat */
#include <sys/stat.h> /* struct stat */
#include <sys/wait.h>
#include <errno.h> /* the error-numbers */
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <limits.h>
#include <assert.h>
#include <sys/uio.h>
#define NOCRASH 1 /* test11(), 2nd pipe */
#define PDPNOHANG 1 /* test03(), write_standards() */
#define MAXERR 5
#define USER_ID 12
#define GROUP_ID 1
#define FF 3 /* first free filedes. */
#define USER 1 /* uid */
#define GROUP 0 /* gid */
#define ARSIZE 256 /* array size */
#define PIPESIZE 3584 /* maxnumber of bytes to be written on pipe */
#define MAXOPEN (OPEN_MAX-3) /* maximum number of extra open files */
#define MAXLINK 0177 /* maximum number of links per file */
#define MASK 0777 /* selects lower nine bits */
#define READ_EOF 0 /* returned by read-call at eof */
#define OK 0
#define FAIL -1
#define R 0 /* read (open-call) */
#define W 1 /* write (open-call) */
#define RW 2 /* read & write (open-call) */
#define RWX 7 /* read & write & execute (mode) */
#define NIL ""
#define UMASK "umask"
#define CREAT "creat"
#define WRITE "write"
#define WRITEV "writev"
#define READ "read"
#define READV "readv"
#define OPEN "open"
#define CLOSE "close"
#define LSEEK "lseek"
#define ACCESS "access"
#define CHDIR "chdir"
#define CHMOD "chmod"
#define LINK "link"
#define UNLINK "unlink"
#define PIPE "pipe"
#define STAT "stat"
#define FSTAT "fstat"
#define DUP "dup"
#define UTIME "utime"
int errct;
/* "decl.c", created by Rene Montsma and Menno Wilcke */
/* Used in open_alot, close_alot */
char *file[MAXOPEN];
char *fnames[8] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"},
*dir[8] = {"d---", "d--x", "d-w-", "d-wx", "dr--", "dr-x", "drw-", "drwx"};
/* Needed for easy creating and deleting of directories */
/* "test.c", created by Rene Montsma and Menno Wilcke */
_PROTOTYPE(int main, (int argc, char **argv));
_PROTOTYPE(void test, (void));
_PROTOTYPE(void test01, (void));
_PROTOTYPE(void test02, (void));
_PROTOTYPE(void test03, (void));
_PROTOTYPE(void write_standards, (int filedes, char a []));
_PROTOTYPE(void test04, (void));
_PROTOTYPE(void read_standards, (int filedes, char a []));
_PROTOTYPE(void read_more, (int filedes, char a []));
_PROTOTYPE(void test05, (void));
_PROTOTYPE(void try_open, (char *fname, int mode, int test));
_PROTOTYPE(void test06, (void));
_PROTOTYPE(void test07, (void));
_PROTOTYPE(void access_standards, (void));
_PROTOTYPE(void test08, (void));
_PROTOTYPE(static int iovec_is_equal,
(struct iovec *x, struct iovec *y, size_t size));
_PROTOTYPE(static size_t iovec_setup,
(int pattern, struct iovec *iovec, char *buffer, int count));
_PROTOTYPE(static int power, (int base, int exponent));
_PROTOTYPE(void try_access, (char *fname, int mode, int test));
_PROTOTYPE(void e, (char *string));
_PROTOTYPE(void nlcr, (void));
_PROTOTYPE(void str, (char *s));
_PROTOTYPE(void err, (int number, char *scall, char *name));
_PROTOTYPE(void make_and_fill_dirs, (void));
_PROTOTYPE(void put_file_in_dir, (char *dirname, int mode));
_PROTOTYPE(void init_array, (char *a));
_PROTOTYPE(void clear_array, (char *b));
_PROTOTYPE(int comp_array, (char *a, char *b, int range));
_PROTOTYPE(void try_close, (int filedes, char *name));
_PROTOTYPE(void try_unlink, (char *fname));
_PROTOTYPE(void Remove, (int fdes, char *fname));
_PROTOTYPE(int get_mode, (char *name));
_PROTOTYPE(void check, (char *scall, int number));
_PROTOTYPE(void put, (int nr));
_PROTOTYPE(int open_alot, (void));
_PROTOTYPE(int close_alot, (int number));
_PROTOTYPE(void clean_up_the_mess, (void));
_PROTOTYPE(void chmod_8_dirs, (int sw));
_PROTOTYPE(void quit, (void));
/*****************************************************************************
* TEST *
****************************************************************************/
int main(int argc, char **argv)
{
int n, i;
/* Create filenames for MAXOPEN files, the *file[] array. */
for(i = 0; i < MAXOPEN; i++) {
if(asprintf(&file[i], "file%d", i) == -1) {
fprintf(stderr, "asprintf failed\n");
return 1;
}
}
#define DIR "DIR18"
system("rm -rf " DIR);
if(mkdir(DIR, 0755) != 0) {
perror("mkdir");
return 1;
}
if(chdir(DIR) != 0) {
perror("chdir");
return 1;
}
if (fork()) {
printf("Test 18 ");
fflush(stdout); /* have to flush for child's benefit */
wait(&n);
clean_up_the_mess();
quit();
} else {
test();
exit(0);
}
return(0);
}
void test()
{
umask(0); /* not honest, but i always forget */
test01();
make_and_fill_dirs();
test02();
test03();
test04();
test05();
test06();
test07();
test08();
umask(022);
} /* test */
/* "t1.c" created by Rene Montsma and Menno Wilcke */
/*****************************************************************************
* test UMASK *
****************************************************************************/
void test01()
{
int oldvalue, newvalue, tempvalue;
int nr;
if ((oldvalue = umask(0777)) != 0) err(0, UMASK, NIL);
/* Special test: only the lower 9 bits (protection bits) may part- *
* icipate. ~0777 means: 111 000 000 000. Giving this to umask must*
* not change any value. */
if ((newvalue = umask(~0777)) != 0777) err(1, UMASK, "illegal");
if (oldvalue == newvalue) err(11, UMASK, "not change mask");
if ((tempvalue = umask(0)) != 0) err(2, UMASK, "values");
/* Now test all possible modes of umask on a file */
for (newvalue = MASK; newvalue >= 0; newvalue -= 0111) {
tempvalue = umask(newvalue);
if (tempvalue != oldvalue) {
err(1, UMASK, "illegal");
break; /* no use trying more */
} else if ((nr = creat("file01", 0777)) < 0)
err(5, CREAT, "'file01'");
else {
try_close(nr, "'file01'");
if (get_mode("file01") != (MASK & ~newvalue))
err(7, UMASK, "mode computed");
try_unlink("file01");
}
oldvalue = newvalue;
}
/* The loop has terminated with umask(0) */
if ((tempvalue = umask(0)) != 0)
err(7, UMASK, "umask may influence rest of tests!");
} /* test01 */
/*****************************************************************************
* test CREAT *
****************************************************************************/
void test02()
{
int n, n1, mode;
char a[ARSIZE], b[ARSIZE];
struct stat stbf1;
mode = 0;
/* Create twenty files, check filedes */
for (n = 0; n < MAXOPEN; n++) {
if (creat(file[n], mode) != FF + n)
err(13, CREAT, file[n]);
else {
if (get_mode(file[n]) != mode)
err(7, CREAT, "mode set while creating many files");
/* Change mode of file to standard mode, we want to *
* use a lot (20) of files to be opened later, see *
* open_alot(), close_alot(). */
if (chmod(file[n], 0700) != OK) err(5, CHMOD, file[n]);
}
mode = (mode + 0100) % 01000;
}
/* Already twenty files opened; opening another has to fail */
if (creat("file02", 0777) != FAIL)
err(9, CREAT, "created");
else
check(CREAT, EMFILE);
/* Close all files: seems blunt, but it isn't because we've *
* checked all fd's already */
if ((n = close_alot(MAXOPEN)) < MAXOPEN) err(5, CLOSE, "MAXOPEN files");
/* Creat 1 file twice; check */
if ((n = creat("file02", 0777)) < 0)
err(5, CREAT, "'file02'");
else {
init_array(a);
if (write(n, a, ARSIZE) != ARSIZE) err(1, WRITE, "bad");
if ((n1 = creat("file02", 0755)) < 0) /* receate 'file02' */
err(5, CREAT, "'file02' (2nd time)");
else {
/* Fd should be at the top after recreation */
if (lseek(n1, 0L, SEEK_END) != 0)
err(11, CREAT, "not truncate file by recreation");
else {
/* Try to write on recreated file */
clear_array(b);
if (lseek(n1, 0L, SEEK_SET) != 0)
err(5, LSEEK, "to top of 2nd fd 'file02'");
if (write(n1, a, ARSIZE) != ARSIZE)
err(1, WRITE, "(2) bad");
/* In order to read we've to close and open again */
try_close(n1, "'file02' (2nd creation)");
if ((n1 = open("file02", RW)) < 0)
err(5, OPEN, "'file02' (2nd recreation)");
/* Continue */
if (lseek(n1, 0L, SEEK_SET) != 0)
err(5, LSEEK, "to top 'file02'(2nd fd) (2)");
if (read(n1, b, ARSIZE) != ARSIZE)
err(1, READ, "wrong");
if (comp_array(a, b, ARSIZE) != OK) err(11, CREAT,
"not really truncate file by recreation");
}
if (get_mode("file02") != 0777)
err(11, CREAT, "not maintain mode by recreation");
try_close(n1, "recreated 'file02'");
}
Remove(n, "file02");
}
/* Give 'creat' wrong input: dir not searchable */
if (creat("drw-/file02", 0777) != FAIL)
err(4, CREAT, "'drw-'");
else
check(CREAT, EACCES);
/* Dir not writable */
if (creat("dr-x/file02", 0777) != FAIL)
err(12, CREAT, "'dr-x/file02'");
else
check(CREAT, EACCES);
/* File not writable */
if (creat("drwx/r-x", 0777) != FAIL)
err(11, CREAT, "recreate non-writable file");
else
check(CREAT, EACCES);
/* Try to creat a dir */
if ((n = creat("dir", 040777)) != FAIL) {
if (fstat(n, &stbf1) != OK)
err(5, FSTAT, "'dir'");
else if (stbf1.st_mode != (mode_t) 0100777)
/* Cast because mode is negative :-(.
* HACK DEBUG FIXME: this appears to duplicate
* code in test17.c.
*/
err(11, CREAT, "'creat' a new directory");
Remove(n, "dir");
}
/* We don't consider it to be a bug when creat * does not accept
* tricky modes */
/* File is an existing dir */
if (creat("drwx", 0777) != FAIL)
err(11, CREAT, "create an existing dir!");
else
check(CREAT, EISDIR);
} /* test02 */
/*****************************************************************************
* test WRITE *
****************************************************************************/
void test03()
{
int n, n1;
int fd[2];
char a[ARSIZE];
init_array(a);
/* Test write after a CREAT */
if ((n = creat("file03", 0700)) != FF) /* 'file03' only open file */
err(13, CREAT, "'file03'");
else {
write_standards(n, a); /* test simple writes, wrong input too */
try_close(n, "'file03'");
}
/* Test write after an OPEN */
if ((n = open("file03", W)) < 0)
err(5, OPEN, "'file03'");
else
write_standards(n, a); /* test simple writes, wrong input too */
/* Test write after a DUP */
if ((n1 = dup(n)) < 0)
err(5, DUP, "'file03'");
else {
write_standards(n1, a);
try_close(n1, "duplicated fd 'file03'");
}
/* Remove testfile */
Remove(n, "file03");
/* Test write after a PIPE */
if (pipe(fd) < 0)
err(5, PIPE, NIL);
else {
write_standards(fd[1], a);
try_close(fd[0], "'fd[0]'");
try_close(fd[1], "'fd[1]'");
}
/* Last test: does write check protections ? */
if ((n = open("drwx/r--", R)) < 0)
err(5, OPEN, "'drwx/r--'");
else {
if (write(n, a, ARSIZE) != FAIL)
err(11, WRITE, "write on non-writ. file");
else
check(WRITE, EBADF);
try_close(n, "'drwx/r--'");
}
} /* test03 */
void write_standards(filedes, a)
int filedes;
char a[];
{
/* Write must return written account of numbers */
if (write(filedes, a, ARSIZE) != ARSIZE) err(1, WRITE, "bad");
/* Try giving 'write' wrong input */
/* Wrong filedes */
if (write(-1, a, ARSIZE) != FAIL)
err(2, WRITE, "filedes");
else
check(WRITE, EBADF);
/* Wrong length (illegal) */
#ifndef PDPNOHANG
if (write(filedes, a, -ARSIZE) != FAIL)
err(2, WRITE, "length");
else
check(WRITE, EINVAL); /* EFAULT on vu45 */
#endif
} /* write_standards */
/* "t2.c", created by Rene Montsma and Menno Wilcke */
/*****************************************************************************
* test READ *
****************************************************************************/
void test04()
{
int n, n1, fd[2];
char a[ARSIZE];
/* Test read after creat */
if ((n = creat("file04", 0700)) != FF) /* no other open files may be
* left */
err(13, CREAT, "'file04'");
else {
/* Closing and opening needed before writing */
try_close(n, "'file04'");
if ((n = open("file04", RW)) < 0) err(5, OPEN, "'file04'");
init_array(a);
if (write(n, a, ARSIZE) != ARSIZE)
err(1, WRITE, "bad");
else {
if (lseek(n, 0L, SEEK_SET) != 0) err(5, LSEEK, "'file04'");
read_standards(n, a);
read_more(n, a);
}
try_close(n, "'file04'");
}
/* Test read after OPEN */
if ((n = open("file04", R)) < 0)
err(5, OPEN, "'file04'");
else {
read_standards(n, a);
read_more(n, a);
try_close(n, "'file04'");
}
/* Test read after DUP */
if ((n = open("file04", R)) < 0) err(5, OPEN, "'file04'");
if ((n1 = dup(n)) < 0)
err(5, DUP, "'file04'");
else {
read_standards(n1, a);
read_more(n1, a);
try_close(n1, "duplicated fd 'file04'");
}
/* Remove testfile */
Remove(n, "file04");
/* Test read after pipe */
if (pipe(fd) < 0)
err(5, PIPE, NIL);
else {
if (write(fd[1], a, ARSIZE) != ARSIZE) {
err(5, WRITE, "'fd[1]'");
try_close(fd[1], "'fd[1]'");
} else {
try_close(fd[1], "'fd[1]'");
read_standards(fd[0], a);
}
try_close(fd[0], "'fd[0]'");
}
/* Last test: try to read a read-protected file */
if ((n = open("drwx/-wx", W)) < 0)
err(5, OPEN, "'drwx/-wx'");
else {
if (read(n, a, ARSIZE) != FAIL)
err(11, READ, "read a non-read. file");
else
check(READ, EBADF);
try_close(n, "'/drwx/-wx'");
}
} /* test04 */
void read_standards(filedes, a)
int filedes;
char a[];
{
char b[ARSIZE];
clear_array(b);
if (read(filedes, b, ARSIZE) != ARSIZE)
err(1, READ, "bad");
else if (comp_array(a, b, ARSIZE) != OK)
err(7, "read/write", "values");
else if (read(filedes, b, ARSIZE) != READ_EOF)
err(11, READ, "read beyond endoffile");
/* Try giving read wrong input: wrong filedes */
if (read(FAIL, b, ARSIZE) != FAIL)
err(2, READ, "filedes");
else
check(READ, EBADF);
/* Wrong length */
if (read(filedes, b, -ARSIZE) != FAIL)
err(2, READ, "length");
else
check(READ, EINVAL);
} /* read_standards */
void read_more(filedes, a)
int filedes;
char a[];
/* Separated from read_standards() because the PIPE test * would fail. */
{
int i;
char b[ARSIZE];
if (lseek(filedes, (long) (ARSIZE / 2), SEEK_SET) != ARSIZE / 2)
err(5, LSEEK, "to location ARSIZE/2");
clear_array(b);
if (read(filedes, b, ARSIZE) != ARSIZE / 2) err(1, READ, "bad");
for (i = 0; i < ARSIZE / 2; i++)
if (b[i] != a[(ARSIZE / 2) + i])
err(7, READ, "from location ARSIZE/2");
}
/*****************************************************************************
* test OPEN/CLOSE *
****************************************************************************/
void test05()
{
int n, n1, mode, fd[2];
char b[ARSIZE];
/* Test open after CREAT */
if ((n = creat("file05", 0700)) != FF) /* no other open files left */
err(13, CREAT, "'file05'");
else {
if ((n1 = open("file05", RW)) != FF + 1)
err(13, OPEN, "'file05' after creation");
try_close(n1, "'file05' (open after creation)");
try_close(n, "'file05'");
if ((n = open("file05", R)) != FF)
err(13, OPEN, "after closing");
else
try_close(n, "'file05' (open after closing)");
/* Remove testfile */
try_unlink("file05");
}
/* Test all possible modes, try_open not only opens file (sometimes) *
* but closes files too (when opened) */
if ((n = creat("file05", 0700)) < 0) /* no other files left */
err(5, CREAT, "'file05' (2nd time)");
else {
try_close(n, "file05");
for (mode = 0; mode <= 0700; mode += 0100) {
if (chmod("file05", mode) != OK) err(5, CHMOD, "'file05'");
if (mode <= 0100) {
try_open("file05", R, FAIL);
try_open("file05", W, FAIL);
try_open("file05", RW, FAIL);
} else if (mode >= 0200 && mode <= 0300) {
try_open("file05", R, FAIL);
try_open("file05", W, FF);
try_open("file05", RW, FAIL);
} else if (mode >= 0400 && mode <= 0500) {
try_open("file05", R, FF);
try_open("file05", W, FAIL);
try_open("file05", RW, FAIL);
} else {
try_open("file05", R, FF);
try_open("file05", W, FF);
try_open("file05", RW, FF);
}
}
}
/* Test opening existing file */
if ((n = open("drwx/rwx", R)) < 0)
err(13, OPEN, "existing file");
else { /* test close after DUP */
if ((n1 = dup(n)) < 0)
err(13, DUP, "'drwx/rwx'");
else {
try_close(n1, "duplicated fd 'drwx/rwx'");
if (read(n1, b, ARSIZE) != FAIL)
err(11, READ, "on closed dupped fd 'drwx/rwx'");
else
check(READ, EBADF);
if (read(n, b, ARSIZE) == FAIL) /* should read an eof */
err(13, READ, "on fd '/drwx/rwx'");
}
try_close(n, "'drwx/rwx'");
}
/* Test close after PIPE */
if (pipe(fd) < 0)
err(13, PIPE, NIL);
else {
try_close(fd[1], "duplicated fd 'fd[1]'");
/* Fd[1] really should be closed now; check */
clear_array(b);
if (read(fd[0], b, ARSIZE) != READ_EOF)
err(11, READ, "read on empty pipe (and fd[1] was closed)");
try_close(fd[0], "duplicated fd 'fd[0]'");
}
/* Try to open a non-existing file */
if (open("non-file", R) != FAIL)
err(11, OPEN, "open non-executable file");
else
check(OPEN, ENOENT);
/* Dir does not exist */
if (open("dzzz/file05", R) != FAIL)
err(11, OPEN, "open in an non-searchable dir");
else
check(OPEN, ENOENT);
/* Dir is not searchable */
if ((n = open("drw-/rwx", R)) != FAIL)
err(11, OPEN, "open in an non-searchabledir");
else
check(OPEN, EACCES);
/* Unlink testfile */
try_unlink("file05");
/* File is not readable */
if (open("drwx/-wx", R) != FAIL)
err(11, OPEN, "open unreadable file for reading");
else
check(OPEN, EACCES);
/* File is not writable */
if (open("drwx/r-x", W) != FAIL)
err(11, OPEN, "open unwritable file for writing");
else
check(OPEN, EACCES);
/* Try opening more than MAXOPEN ('extra' (19-8-85)) files */
if ((n = open_alot()) != MAXOPEN)
err(13, OPEN, "MAXOPEN files");
else
/* Maximum # of files opened now, another open should fail
* because * all filedescriptors have already been used. */
if (open("drwx/rwx", RW) != FAIL)
err(9, OPEN, "open");
else
check(OPEN, EMFILE);
if (close_alot(n) != n) err(5, CLOSE, "all opened files");
/* Can close make mistakes ? */
if (close(-1) != FAIL)
err(2, CLOSE, "filedes");
else
check(CLOSE, EBADF);
} /* test05 */
void try_open(fname, mode, test)
int mode, test;
char *fname;
{
int n;
if ((n = open(fname, mode)) != test)
err(11, OPEN, "break through filepermission with an incorrect mode");
if (n != FAIL) try_close(n, fname); /* cleanup */
} /* try_open */
/*****************************************************************************
* test LSEEK *
****************************************************************************/
void test06()
{
char a[ARSIZE], b[ARSIZE];
int fd;
if ((fd = open("drwx/rwx", RW)) != FF) /* there should be no */
err(13, OPEN, "'drwx/rwx'"); /* other open files */
else {
init_array(a);
if (write(fd, a, 10) != 10)
err(1, WRITE, "bad");
else {
/* Lseek back to begin file */
if (lseek(fd, 0L, SEEK_SET) != 0)
err(5, LSEEK, "to begin file");
else if (read(fd, b, 10) != 10)
err(1, READ, "bad");
else if (comp_array(a, b, 10) != OK)
err(7, LSEEK, "values r/w after lseek to begin");
/* Lseek to endoffile */
if (lseek(fd, 0L, SEEK_END) != 10)
err(5, LSEEK, "to end of file");
else if (read(fd, b, 1) != READ_EOF)
err(7, LSEEK, "read at end of file");
/* Lseek beyond file */
if (lseek(fd, 10L, SEEK_CUR) != 20)
err(5, LSEEK, "beyond end of file");
else if (write(fd, a, 10) != 10)
err(1, WRITE, "bad");
else {
/* Lseek to begin second write */
if (lseek(fd, 20L, SEEK_SET) != 20)
err(5, LSEEK, "'/drwx/rwx'");
if (read(fd, b, 10) != 10)
err(1, READ, "bad");
else if (comp_array(a, b, 10) != OK)
err(7, LSEEK,
"values read after lseek MAXOPEN");
}
}
/* Lseek to position before begin of file */
if (lseek(fd, -1L, 0) != FAIL)
err(11, LSEEK, "lseek before beginning of file");
try_close(fd, "'drwx/rwx'");
}
/* Lseek on invalid filediscriptor */
if (lseek(-1, 0L, SEEK_SET) != FAIL)
err(2, LSEEK, "filedes");
else
check(LSEEK, EBADF);
}
/* "t3.c", created by Rene Montsma and Menno Wilcke */
/*****************************************************************************
* test ACCESS *
****************************************************************************/
void test07()
{
/* Check with proper parameters */
if (access("drwx/rwx", RWX) != OK) err(5, ACCESS, "accessible file");
if (access("./././drwx/././rwx", 0) != OK)
err(5, ACCESS, "'/./.(etc)/drwx///rwx'");
/* Check 8 files with 8 different modes on 8 accesses */
if (chdir("drwx") != OK) err(5, CHDIR, "'drwx'");
access_standards();
if (chdir("..") != OK) err(5, CHDIR, "'..'");
/* Check several wrong combinations */
/* File does not exist */
if (access("non-file", 0) != FAIL)
err(11, ACCESS, "access non-existing file");
else
check(ACCESS, ENOENT);
/* Non-searchable dir */
if (access("drw-/rwx", 0) != FAIL)
err(4, ACCESS, "'drw-'");
else
check(ACCESS, EACCES);
/* Searchable dir, but wrong file-mode */
if (access("drwx/--x", RWX) != FAIL)
err(11, ACCESS, "a non accessible file");
else
check(ACCESS, EACCES);
} /* test07 */
void access_standards()
{
int i, mode = 0;
for (i = 0; i < 8; i++)
if (i == 0)
try_access(fnames[mode], i, OK);
else
try_access(fnames[mode], i, FAIL);
mode++;
for (i = 0; i < 8; i++)
if (i < 2)
try_access(fnames[mode], i, OK);
else
try_access(fnames[mode], i, FAIL);
mode++;
for (i = 0; i < 8; i++)
if (i == 0 || i == 2)
try_access(fnames[mode], i, OK);
else
try_access(fnames[mode], i, FAIL);
mode++;
for (i = 0; i < 8; i++)
if (i < 4)
try_access(fnames[mode], i, OK);
else
try_access(fnames[mode], i, FAIL);
mode++;
for (i = 0; i < 8; i++)
if (i == 0 || i == 4)
try_access(fnames[mode], i, OK);
else
try_access(fnames[mode], i, FAIL);
mode++;
for (i = 0; i < 8; i++)
if (i == 0 || i == 1 || i == 4 || i == 5)
try_access(fnames[mode], i, OK);
else
try_access(fnames[mode], i, FAIL);
mode++;
for (i = 0; i < 8; i++)
if (i % 2 == 0)
try_access(fnames[mode], i, OK);
else
try_access(fnames[mode], i, FAIL);
mode++;
for (i = 0; i < 8; i++) try_access(fnames[mode], i, OK);
} /* access_standards */
void try_access(fname, mode, test)
int mode, test;
char *fname;
{
if (access(fname, mode) != test)
err(100, ACCESS, "incorrect access on a file (try_access)");
} /* try_access */
/* "support.c", created by Rene Montsma and Menno Wilcke */
/* Err, make_and_fill_dirs, init_array, clear_array, comp_array,
try_close, try_unlink, Remove, get_mode, check, open_alot,
close_alot, clean_up_the_mess.
*/
/*****************************************************************************
* test READV/WRITEV *
****************************************************************************/
#define TEST8_BUFSZCOUNT 3
#define TEST8_BUFSZMAX 65536
#define TEST8_IOVCOUNT 4
void test08()
{
char buffer_read[TEST8_IOVCOUNT * TEST8_BUFSZMAX];
char buffer_write[TEST8_IOVCOUNT * TEST8_BUFSZMAX];
struct iovec iovec_read[TEST8_IOVCOUNT];
struct iovec iovec_write[TEST8_IOVCOUNT];
int fd, i, j, k, l, m;
ssize_t sz_read, sz_write;
size_t sz_read_exp, sz_read_sum, sz_write_sum;
/* try various combinations of buffer sizes */
for (i = 0; i <= TEST8_IOVCOUNT; i++)
for (j = 0; j < power(TEST8_BUFSZCOUNT, i); j++)
for (k = 0; k <= TEST8_IOVCOUNT; k++)
for (l = 0; l < power(TEST8_BUFSZCOUNT, k); l++)
{
/* put data in the buffers */
for (m = 0; m < sizeof(buffer_write); m++)
{
buffer_write[m] = m ^ (m >> 8);
buffer_read[m] = ~buffer_write[m];
}
/* set up the vectors to point to the buffers */
sz_read_sum = iovec_setup(j, iovec_read, buffer_read, i);
sz_write_sum = iovec_setup(l, iovec_write, buffer_write, k);
sz_read_exp = (sz_read_sum < sz_write_sum) ?
sz_read_sum : sz_write_sum;
/* test reading and writing */
if ((fd = open("file08", O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0)
err(13, OPEN, "'file08'");
else {
sz_write = writev(fd, iovec_write, k);
if (sz_write != sz_write_sum) err(5, WRITEV, "'file08'");
if (lseek(fd, 0, SEEK_SET) != 0) err(5, LSEEK, "'file08'");
sz_read = readv(fd, iovec_read, i);
if (sz_read != sz_read_exp)
err(5, READV, "'file08'");
else
{
if (!iovec_is_equal(iovec_read, iovec_write, sz_read))
err(8, READV, "'file08'");
}
/* Remove testfile */
Remove(fd, "file08");
}
}
} /* test08 */
static int iovec_is_equal(struct iovec *x, struct iovec *y, size_t size)
{
int xpos = 0, xvec = 0, ypos = 0, yvec = 0;
/* compare byte by byte */
while (size-- > 0)
{
/* skip over zero-byte buffers and those that have been completed */
while (xpos >= x[xvec].iov_len)
{
xpos -= x[xvec++].iov_len;
assert(xvec < TEST8_IOVCOUNT);
}
while (ypos >= y[yvec].iov_len)
{
ypos -= y[yvec++].iov_len;
assert(yvec < TEST8_IOVCOUNT);
}
/* compare */
if (((char *) x[xvec].iov_base)[xpos++] !=
((char *) y[yvec].iov_base)[ypos++])
return 0;
}
/* no difference found */
return 1;
}
static size_t iovec_setup(int pattern, struct iovec *iovec, char *buffer, int count)
{
static const size_t bufsizes[TEST8_BUFSZCOUNT] = { 0, 1, TEST8_BUFSZMAX };
int i;
size_t sum = 0;
/* the pattern specifies each buffer */
for (i = 0; i < TEST8_IOVCOUNT; i++)
{
iovec->iov_base = buffer;
sum += iovec->iov_len = bufsizes[pattern % TEST8_BUFSZCOUNT];
iovec++;
buffer += TEST8_BUFSZMAX;
pattern /= TEST8_BUFSZCOUNT;
}
return sum;
}
static int power(int base, int exponent)
{
int result = 1;
/* compute base^exponent */
while (exponent-- > 0)
result *= base;
return result;
}
/***********************************************************************
* EXTENDED FIONS *
**********************************************************************/
/* First extended functions (i.e. not oldfashioned monixcalls.
e(), nlcr(), octal.*/
void e(string)
char *string;
{
printf("Test program error: %s\n", string);
errct++;
}
void nlcr()
{
fputs("\n",stdout);
}
void str(char *s)
{
fputs(s,stdout);
}
/*****************************************************************************
* *
* ERR(or) messages *
* *
*****************************************************************************/
void err(number, scall, name)
/* Give nice error messages */
char *scall, *name;
int number;
{
errct++;
if (errct > MAXERR) {
printf("Too many errors; test aborted\n");
chdir("..");
system("rm -rf DIR*");
quit();
}
e("");
str("\t");
switch (number) {
case 0:
str(scall);
str(": illegal initial value.");
break;
case 1:
str(scall);
str(": ");
str(name);
str(" value returned.");
break;
case 2:
str(scall);
str(": accepting illegal ");
str(name);
str(".");
break;
case 3:
str(scall);
str(": accepting non-existing file.");
break;
case 4:
str(scall);
str(": could search non-searchable dir (");
str(name);
str(").");
break;
case 5:
str(scall);
str(": cannot ");
str(scall);
str(" ");
str(name);
str(".");
break;
case 7:
str(scall);
str(": incorrect ");
str(name);
str(".");
break;
case 8:
str(scall);
str(": wrong values.");
break;
case 9:
str(scall);
str(": accepting too many ");
str(name);
str(" files.");
break;
case 10:
str(scall);
str(": even a superuser can't do anything!");
break;
case 11:
str(scall);
str(": could ");
str(name);
str(".");
break;
case 12:
str(scall);
str(": could write in non-writable dir (");
str(name);
str(").");
break;
case 13:
str(scall);
str(": wrong filedes returned (");
str(name);
str(").");
break;
case 100:
str(scall); /* very common */
str(": ");
str(name);
str(".");
break;
default: str("errornumber does not exist!\n");
}
nlcr();
} /* err */
/*****************************************************************************
* *
* MAKE_AND_FILL_DIRS *
* *
*****************************************************************************/
void make_and_fill_dirs()
/* Create 8 dir.'s: "d---", "d--x", "d-w-", "d-wx", "dr--", "dr-x", *
* "drw-", "drwx". * Then create 8 files
* in "drwx", and some needed files in other dirs. */
{
int mode, i;
for (i = 0; i < 8; i++) {
mkdir(dir[i], 0700);
chown(dir[i], USER_ID, GROUP_ID);
}
setuid(USER_ID);
setgid(GROUP_ID);
for (mode = 0; mode < 8; mode++) put_file_in_dir("drwx", mode);
put_file_in_dir("d-wx", RWX);
put_file_in_dir("dr-x", RWX);
put_file_in_dir("drw-", RWX);
chmod_8_dirs(8); /* 8 means; 8 different modes */
} /* make_and_fill_dirs */
void put_file_in_dir(dirname, mode)
char *dirname;
int mode;
/* Fill directory 'dirname' with file with mode 'mode'. */
{
int nr;
if (chdir(dirname) != OK)
err(5, CHDIR, "to dirname (put_f_in_dir)");
else {
/* Creat the file */
if ((nr = creat(fnames[mode], mode * 0100)) < 0)
err(13, CREAT, fnames[mode]);
else
try_close(nr, fnames[mode]);
if (chdir("..") != OK)
err(5, CHDIR, "to previous dir (put_f_in_dir)");
}
} /* put_file_in_dir */
/*****************************************************************************
* *
* MISCELLANEOUS *
* *
*(all about arrays, 'try_close', 'try_unlink', 'Remove', 'get_mode') *
* *
*****************************************************************************/
void init_array(a)
char *a;
{
int i;
i = 0;
while (i++ < ARSIZE) *a++ = 'a' + (i % 26);
} /* init_array */
void clear_array(b)
char *b;
{
int i;
i = 0;
while (i++ < ARSIZE) *b++ = '0';
} /* clear_array */
int comp_array(a, b, range)
char *a, *b;
int range;
{
if ((range < 0) || (range > ARSIZE)) {
err(100, "comp_array", "illegal range");
return(FAIL);
} else {
while (range-- && (*a++ == *b++));
if (*--a == *--b)
return(OK);
else
return(FAIL);
}
} /* comp_array */
void try_close(filedes, name)
int filedes;
char *name;
{
if (close(filedes) != OK) err(5, CLOSE, name);
} /* try_close */
void try_unlink(fname)
char *fname;
{
if (unlink(fname) != 0) err(5, UNLINK, fname);
} /* try_unlink */
void Remove(fdes, fname)
int fdes;
char *fname;
{
try_close(fdes, fname);
try_unlink(fname);
} /* Remove */
int get_mode(name)
char *name;
{
struct stat stbf1;
if (stat(name, &stbf1) != OK) {
err(5, STAT, name);
return(stbf1.st_mode); /* return a mode which will cause *
* error in the calling function *
* (file/dir bit) */
} else
return(stbf1.st_mode & 07777); /* take last 4 bits */
} /* get_mode */
/*****************************************************************************
* *
* CHECK *
* *
*****************************************************************************/
void check(scall, number)
int number;
char *scall;
{
if (errno != number) {
e(NIL);
str("\t");
str(scall);
str(": bad errno-value: ");
put(errno);
str(" should have been: ");
put(number);
nlcr();
}
} /* check */
void put(nr)
int nr;
{
switch (nr) {
case 0: str("unused"); break;
case 1: str("EPERM"); break;
case 2: str("ENOENT"); break;
case 3: str("ESRCH"); break;
case 4: str("EINTR"); break;
case 5: str("EIO"); break;
case 6: str("ENXIO"); break;
case 7: str("E2BIG"); break;
case 8: str("ENOEXEC"); break;
case 9: str("EBADF"); break;
case 10: str("ECHILD"); break;
case 11: str("EAGAIN"); break;
case 12: str("ENOMEM"); break;
case 13: str("EACCES"); break;
case 14: str("EFAULT"); break;
case 15: str("ENOTBLK"); break;
case 16: str("EBUSY"); break;
case 17: str("EEXIST"); break;
case 18: str("EXDEV"); break;
case 19: str("ENODEV"); break;
case 20: str("ENOTDIR"); break;
case 21: str("EISDIR"); break;
case 22: str("EINVAL"); break;
case 23: str("ENFILE"); break;
case 24: str("EMFILE"); break;
case 25: str("ENOTTY"); break;
case 26: str("ETXTBSY"); break;
case 27: str("EFBIG"); break;
case 28: str("ENOSPC"); break;
case 29: str("ESPIPE"); break;
case 30: str("EROFS"); break;
case 31: str("EMLINK"); break;
case 32: str("EPIPE"); break;
case 33: str("EDOM"); break;
case 34: str("ERANGE"); break;
}
}
/*****************************************************************************
* *
* ALOT-functions *
* *
*****************************************************************************/
int open_alot()
{
int i;
for (i = 0; i < MAXOPEN; i++)
if (open(file[i], R) == FAIL) break;
if (i == 0) err(5, "open_alot", "at all");
return(i);
} /* open_alot */
int close_alot(number)
int number;
{
int i, count = 0;
if (number > MAXOPEN)
err(5, "close_alot", "accept this argument");
else
for (i = FF; i < number + FF; i++)
if (close(i) != OK) count++;
return(number - count); /* return number of closed files */
} /* close_alot */
/*****************************************************************************
* *
* CLEAN UP THE MESS *
* *
*****************************************************************************/
void clean_up_the_mess()
{
int i;
char dirname[6];
/* First remove 'alot' files */
for (i = 0; i < MAXOPEN; i++) try_unlink(file[i]);
/* Unlink the files in dir 'drwx' */
if (chdir("drwx") != OK)
err(5, CHDIR, "to 'drwx'");
else {
for (i = 0; i < 8; i++) try_unlink(fnames[i]);
if (chdir("..") != OK) err(5, CHDIR, "to '..'");
}
/* Before unlinking files in some dirs, make them writable */
chmod_8_dirs(RWX);
/* Unlink files in other dirs */
try_unlink("d-wx/rwx");
try_unlink("dr-x/rwx");
try_unlink("drw-/rwx");
/* Unlink dirs */
for (i = 0; i < 8; i++) {
strcpy(dirname, "d");
strcat(dirname, fnames[i]);
/* 'dirname' contains the directoryname */
rmdir(dirname);
}
/* FINISH */
} /* clean_up_the_mess */
void chmod_8_dirs(sw)
int sw; /* if switch == 8, give all different
* mode,else the same mode */
{
int mode;
int i;
if (sw == 8)
mode = 0;
else
mode = sw;
for (i = 0; i < 8; i++) {
chmod(dir[i], 040000 + mode * 0100);
if (sw == 8) mode++;
}
}
void quit()
{
chdir("..");
system("rm -rf DIR*");
if (errct == 0) {
printf("ok\n");
exit(0);
} else {
printf("%d errors\n", errct);
exit(1);
}
}