1124 lines
27 KiB
C
1124 lines
27 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 max_error = 2;
|
|
#include "common.h"
|
|
|
|
|
|
/* "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 */
|
|
|
|
|
|
int main(int argc, char **argv);
|
|
void test(void);
|
|
void test01(void);
|
|
void test02(void);
|
|
void test03(void);
|
|
void write_standards(int filedes, char a []);
|
|
void test04(void);
|
|
void read_standards(int filedes, char a []);
|
|
void read_more(int filedes, char a []);
|
|
void test05(void);
|
|
void try_open(char *fname, int mode, int test);
|
|
void test06(void);
|
|
void test07(void);
|
|
void access_standards(void);
|
|
void test08(void);
|
|
static int iovec_is_equal(struct iovec *x, struct iovec *y, size_t
|
|
size);
|
|
static size_t iovec_setup(int pattern, struct iovec *iovec, char
|
|
*buffer, int count);
|
|
static int power(int base, int exponent);
|
|
void try_access(char *fname, int mode, int test);
|
|
void make_and_fill_dirs(void);
|
|
void put_file_in_dir(char *dirname, int mode);
|
|
void init_array(char *a);
|
|
void clear_array(char *b);
|
|
int comp_array(char *a, char *b, int range);
|
|
void try_close(int filedes, char *name);
|
|
void try_unlink(char *fname);
|
|
void Remove(int fdes, char *fname);
|
|
int get_mode(char *name);
|
|
void check(char *scall, int number);
|
|
void put(int nr);
|
|
int open_alot(void);
|
|
int close_alot(int number);
|
|
void clean_up_the_mess(void);
|
|
void chmod_8_dirs(int sw);
|
|
|
|
/*****************************************************************************
|
|
* TEST *
|
|
****************************************************************************/
|
|
int main(int argc, char **argv)
|
|
{
|
|
int n, i;
|
|
pid_t child;
|
|
|
|
start(18);
|
|
|
|
/* 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");
|
|
quit();
|
|
}
|
|
}
|
|
|
|
subtest = 0;
|
|
child = fork();
|
|
if (child == -1) {
|
|
e(1);
|
|
quit();
|
|
} else if (child == 0) {
|
|
test();
|
|
return(0);
|
|
} else {
|
|
wait(&n);
|
|
clean_up_the_mess();
|
|
quit();
|
|
}
|
|
|
|
return(-1);
|
|
}
|
|
|
|
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;
|
|
|
|
subtest = 1;
|
|
|
|
if ((oldvalue = umask(0777)) != 0) e(1);
|
|
|
|
/* 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) e(2);
|
|
if (oldvalue == newvalue) e(3);
|
|
|
|
if ((tempvalue = umask(0)) != 0) e(4);
|
|
|
|
/* Now test all possible modes of umask on a file */
|
|
for (newvalue = MASK; newvalue >= 0; newvalue -= 0111) {
|
|
tempvalue = umask(newvalue);
|
|
if (tempvalue != oldvalue) {
|
|
e(5);
|
|
break; /* no use trying more */
|
|
} else if ((nr = creat("file01", 0777)) < 0)
|
|
e(6);
|
|
else {
|
|
try_close(nr, "'file01'");
|
|
if (get_mode("file01") != (MASK & ~newvalue)) e(7);
|
|
try_unlink("file01");
|
|
}
|
|
oldvalue = newvalue;
|
|
}
|
|
|
|
/* The loop has terminated with umask(0) */
|
|
if ((tempvalue = umask(0)) != 0) e(8);
|
|
} /* test01 */
|
|
|
|
/*****************************************************************************
|
|
* test CREAT *
|
|
****************************************************************************/
|
|
void test02()
|
|
{
|
|
int n, n1, mode;
|
|
char a[ARSIZE], b[ARSIZE];
|
|
struct stat stbf1;
|
|
|
|
subtest = 2;
|
|
mode = 0;
|
|
/* Create MAXOPEN files, check filedes */
|
|
for (n = 0; n < MAXOPEN; n++) {
|
|
if (creat(file[n], mode) != FF + n)
|
|
e(1);
|
|
else {
|
|
if (get_mode(file[n]) != mode) e(2);
|
|
|
|
/* 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) e(3);
|
|
|
|
}
|
|
mode = (mode + 0100) % 01000;
|
|
}
|
|
|
|
/* Already twenty files opened; opening another has to fail */
|
|
if (creat("file02", 0777) != FAIL) e(4);
|
|
else
|
|
if (errno != EMFILE) e(5);;
|
|
|
|
|
|
/* Close all files: seems blunt, but it isn't because we've *
|
|
* checked all fd's already */
|
|
if ((n = close_alot(MAXOPEN)) < MAXOPEN) e(6);
|
|
|
|
/* Creat 1 file twice; check */
|
|
if ((n = creat("file02", 0777)) < 0) e(7);
|
|
else {
|
|
init_array(a);
|
|
if (write(n, a, ARSIZE) != ARSIZE) e(8);
|
|
|
|
if ((n1 = creat("file02", 0755)) < 0) e(9);
|
|
else {
|
|
/* Fd should be at the top after recreation */
|
|
if (lseek(n1, 0L, SEEK_END) != 0) e(10);
|
|
else {
|
|
/* Try to write on recreated file */
|
|
clear_array(b);
|
|
|
|
if (lseek(n1, 0L, SEEK_SET) != 0) e(11);
|
|
if (write(n1, a, ARSIZE) != ARSIZE) e(12);
|
|
|
|
/* In order to read we've to close and open again */
|
|
try_close(n1, "'file02' (2nd creation)");
|
|
if ((n1 = open("file02", RW)) < 0) e(13);
|
|
|
|
/* Continue */
|
|
if (lseek(n1, 0L, SEEK_SET) != 0) e(14);
|
|
if (read(n1, b, ARSIZE) != ARSIZE) e(15);
|
|
|
|
if (comp_array(a, b, ARSIZE) != OK) e(16);
|
|
}
|
|
if (get_mode("file02") != 0777) e(17);
|
|
try_close(n1, "recreated 'file02'");
|
|
|
|
}
|
|
Remove(n, "file02");
|
|
}
|
|
|
|
/* Give 'creat' wrong input: dir not searchable */
|
|
if (creat("drw-/file02", 0777) != FAIL) e(18);
|
|
else
|
|
if (errno != EACCES) e(19);
|
|
|
|
/* Dir not writable */
|
|
if (creat("dr-x/file02", 0777) != FAIL) e(20);
|
|
else
|
|
if (errno != EACCES) e(21);
|
|
|
|
/* File not writable */
|
|
if (creat("drwx/r-x", 0777) != FAIL) e(22);
|
|
else
|
|
if (errno != EACCES) e(23);
|
|
|
|
/* Try to creat a dir */
|
|
if ((n = creat("dir", 040777)) != FAIL) {
|
|
if (fstat(n, &stbf1) != OK) e(24);
|
|
else if (stbf1.st_mode != (mode_t) 0100777)
|
|
/* Cast because mode is negative :-(.
|
|
* HACK DEBUG FIXME: this appears to duplicate
|
|
* code in test17.c.
|
|
*/
|
|
e(25);
|
|
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) e(26);
|
|
else
|
|
if (errno != EISDIR) e(27);
|
|
} /* test02 */
|
|
|
|
/*****************************************************************************
|
|
* test WRITE *
|
|
****************************************************************************/
|
|
void test03()
|
|
{
|
|
int n, n1;
|
|
int fd[2];
|
|
char a[ARSIZE];
|
|
|
|
subtest = 3;
|
|
init_array(a);
|
|
|
|
/* Test write after a CREAT */
|
|
if ((n = creat("file03", 0700)) != FF) e(1);
|
|
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) e(2);
|
|
else
|
|
write_standards(n, a); /* test simple writes, wrong input too */
|
|
|
|
/* Test write after a DUP */
|
|
if ((n1 = dup(n)) < 0) e(3);
|
|
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) e(4);
|
|
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) e(5);
|
|
else {
|
|
if (write(n, a, ARSIZE) != FAIL) e(6);
|
|
else
|
|
if (errno != EBADF) e(7);
|
|
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) e(80);
|
|
|
|
/* Try giving 'write' wrong input */
|
|
/* Wrong filedes */
|
|
if (write(-1, a, ARSIZE) != FAIL) e(81);
|
|
else
|
|
if (errno != EBADF) e(82);
|
|
|
|
/* Wrong length (illegal) */
|
|
#ifndef PDPNOHANG
|
|
if (write(filedes, a, -ARSIZE) != FAIL) e(83);
|
|
else
|
|
if (errno != EINVAL) e(84);
|
|
#endif
|
|
} /* write_standards */
|
|
|
|
|
|
/*****************************************************************************
|
|
* test READ *
|
|
****************************************************************************/
|
|
void test04()
|
|
{
|
|
int n, n1, fd[2];
|
|
char a[ARSIZE];
|
|
|
|
subtest = 4;
|
|
|
|
/* Test read after creat */
|
|
if ((n = creat("file04", 0700)) != FF) e(1);
|
|
else {
|
|
/* Closing and opening needed before writing */
|
|
try_close(n, "'file04'");
|
|
if ((n = open("file04", RW)) < 0) e(2);
|
|
|
|
init_array(a);
|
|
|
|
if (write(n, a, ARSIZE) != ARSIZE) e(3);
|
|
else {
|
|
if (lseek(n, 0L, SEEK_SET) != 0) e(4);
|
|
read_standards(n, a);
|
|
read_more(n, a);
|
|
}
|
|
try_close(n, "'file04'");
|
|
}
|
|
|
|
/* Test read after OPEN */
|
|
if ((n = open("file04", R)) < 0) e(5);
|
|
else {
|
|
read_standards(n, a);
|
|
read_more(n, a);
|
|
try_close(n, "'file04'");
|
|
}
|
|
|
|
/* Test read after DUP */
|
|
if ((n = open("file04", R)) < 0) e(6);
|
|
if ((n1 = dup(n)) < 0) e(7);
|
|
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) e(8);
|
|
else {
|
|
if (write(fd[1], a, ARSIZE) != ARSIZE) {
|
|
e(9);
|
|
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) e(10);
|
|
else {
|
|
if (read(n, a, ARSIZE) != FAIL) e(11);
|
|
else
|
|
if (errno != EBADF) e(12);
|
|
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) e(85);
|
|
else if (comp_array(a, b, ARSIZE) != OK) e(86);
|
|
else if (read(filedes, b, ARSIZE) != READ_EOF) e(87);
|
|
|
|
/* Try giving read wrong input: wrong filedes */
|
|
if (read(FAIL, b, ARSIZE) != FAIL) e(88);
|
|
else
|
|
if (errno != EBADF) e(89);
|
|
|
|
/* Wrong length */
|
|
if (read(filedes, b, -ARSIZE) != FAIL) e(90);
|
|
else
|
|
if (errno != EINVAL) e(91);
|
|
} /* 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) e(92);
|
|
|
|
clear_array(b);
|
|
if (read(filedes, b, ARSIZE) != ARSIZE / 2) e(93);
|
|
|
|
for (i = 0; i < ARSIZE / 2; i++)
|
|
if (b[i] != a[(ARSIZE / 2) + i]) e(94);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* test OPEN/CLOSE *
|
|
****************************************************************************/
|
|
void test05()
|
|
{
|
|
int n, n1, mode, fd[2];
|
|
char b[ARSIZE];
|
|
|
|
subtest = 5;
|
|
/* Test open after CREAT */
|
|
if ((n = creat("file05", 0700)) != FF) e(1);
|
|
else {
|
|
if ((n1 = open("file05", RW)) != FF + 1) e(2);
|
|
try_close(n1, "'file05' (open after creation)");
|
|
|
|
try_close(n, "'file05'");
|
|
if ((n = open("file05", R)) != FF) e(3);
|
|
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) e(6);
|
|
else {
|
|
try_close(n, "file05");
|
|
for (mode = 0; mode <= 0700; mode += 0100) {
|
|
if (chmod("file05", mode) != OK) e(7);
|
|
|
|
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) e(8);
|
|
else { /* test close after DUP */
|
|
if ((n1 = dup(n)) < 0) e(9);
|
|
else {
|
|
try_close(n1, "duplicated fd 'drwx/rwx'");
|
|
|
|
if (read(n1, b, ARSIZE) != FAIL) e(10);
|
|
else
|
|
if (errno != EBADF) e(11);
|
|
|
|
if (read(n, b, ARSIZE) == FAIL) e(12);/* should read an eof */
|
|
}
|
|
try_close(n, "'drwx/rwx'");
|
|
}
|
|
|
|
/* Test close after PIPE */
|
|
if (pipe(fd) < 0) e(13);
|
|
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) e(14);
|
|
try_close(fd[0], "duplicated fd 'fd[0]'");
|
|
}
|
|
|
|
/* Try to open a non-existing file */
|
|
if (open("non-file", R) != FAIL) e(15);
|
|
else
|
|
if (errno != ENOENT) e(16);
|
|
|
|
/* Dir does not exist */
|
|
if (open("dzzz/file05", R) != FAIL) e(17);
|
|
else
|
|
if (errno != ENOENT) e(18);
|
|
|
|
/* Dir is not searchable */
|
|
if ((n = open("drw-/rwx", R)) != FAIL) e(19);
|
|
else
|
|
if (errno != EACCES) e(20);
|
|
|
|
/* Unlink testfile */
|
|
try_unlink("file05");
|
|
|
|
/* File is not readable */
|
|
if (open("drwx/-wx", R) != FAIL) e(21);
|
|
else
|
|
if (errno != EACCES) e(22);
|
|
|
|
/* File is not writable */
|
|
if (open("drwx/r-x", W) != FAIL) e(23);
|
|
else
|
|
if (errno != EACCES) e(24);
|
|
|
|
/* Try opening more than MAXOPEN ('extra' (19-8-85)) files */
|
|
if ((n = open_alot()) != MAXOPEN) e(25);
|
|
else
|
|
/* Maximum # of files opened now, another open should fail
|
|
* because * all filedescriptors have already been used. */
|
|
if (open("drwx/rwx", RW) != FAIL) e(26);
|
|
else
|
|
if (errno != EMFILE) e(27);
|
|
if (close_alot(n) != n) e(28);
|
|
|
|
/* Can close make mistakes ? */
|
|
if (close(-1) != FAIL) e(29);
|
|
else
|
|
if (errno != EBADF) e(30);
|
|
} /* test05 */
|
|
|
|
void try_open(fname, mode, test)
|
|
int mode, test;
|
|
char *fname;
|
|
{
|
|
int n;
|
|
|
|
if ((n = open(fname, mode)) != test) e(95);
|
|
if (n != FAIL) try_close(n, fname); /* cleanup */
|
|
} /* try_open */
|
|
|
|
/*****************************************************************************
|
|
* test LSEEK *
|
|
****************************************************************************/
|
|
void test06()
|
|
{
|
|
char a[ARSIZE], b[ARSIZE];
|
|
int fd;
|
|
|
|
subtest = 6;
|
|
|
|
if ((fd = open("drwx/rwx", RW)) != FF) e(1);
|
|
else {
|
|
init_array(a);
|
|
if (write(fd, a, 10) != 10) e(2);
|
|
else {
|
|
/* Lseek back to begin file */
|
|
if (lseek(fd, 0L, SEEK_SET) != 0) e(3);
|
|
else if (read(fd, b, 10) != 10) e(4);
|
|
else if (comp_array(a, b, 10) != OK) e(5);
|
|
|
|
/* Lseek to endoffile */
|
|
if (lseek(fd, 0L, SEEK_END) != 10) e(6);
|
|
else if (read(fd, b, 1) != READ_EOF) e(7);
|
|
|
|
/* Lseek beyond file */
|
|
if (lseek(fd, 10L, SEEK_CUR) != 20) e(8);
|
|
else if (write(fd, a, 10) != 10) e(9);
|
|
else {
|
|
/* Lseek to begin second write */
|
|
if (lseek(fd, 20L, SEEK_SET) != 20) e(10);
|
|
if (read(fd, b, 10) != 10) e(11);
|
|
else if (comp_array(a, b, 10) != OK) e(12);
|
|
}
|
|
}
|
|
|
|
/* Lseek to position before begin of file */
|
|
if (lseek(fd, -1L, 0) != FAIL) e(13);
|
|
|
|
try_close(fd, "'drwx/rwx'");
|
|
}
|
|
|
|
/* Lseek on invalid filediscriptor */
|
|
if (lseek(-1, 0L, SEEK_SET) != FAIL) e(14);
|
|
else
|
|
if (errno != EBADF) e(15);
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* test ACCESS *
|
|
****************************************************************************/
|
|
void test07()
|
|
{
|
|
subtest = 7;
|
|
|
|
/* Check with proper parameters */
|
|
if (access("drwx/rwx", RWX) != OK) e(1);
|
|
|
|
if (access("./././drwx/././rwx", 0) != OK) e(2);
|
|
|
|
/* Check 8 files with 8 different modes on 8 accesses */
|
|
if (chdir("drwx") != OK) e(3);
|
|
|
|
access_standards();
|
|
|
|
if (chdir("..") != OK) e(4);
|
|
|
|
/* Check several wrong combinations */
|
|
/* File does not exist */
|
|
if (access("non-file", 0) != FAIL) e(5);
|
|
else
|
|
if (errno != ENOENT) e(6);
|
|
|
|
/* Non-searchable dir */
|
|
if (access("drw-/rwx", 0) != FAIL) e(7);
|
|
else
|
|
if (errno != EACCES) e(8);
|
|
|
|
/* Searchable dir, but wrong file-mode */
|
|
if (access("drwx/--x", RWX) != FAIL) e(9);
|
|
else
|
|
if (errno != EACCES) e(10);
|
|
|
|
} /* 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) e(96);
|
|
} /* try_access */
|
|
|
|
|
|
/* 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;
|
|
|
|
subtest = 8;
|
|
|
|
/* 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) e(1);
|
|
else {
|
|
sz_write = writev(fd, iovec_write, k);
|
|
if (sz_write != sz_write_sum) e(2);
|
|
if (lseek(fd, 0, SEEK_SET) != 0) e(3);
|
|
sz_read = readv(fd, iovec_read, i);
|
|
if (sz_read != sz_read_exp) e(4);
|
|
else {
|
|
if (!iovec_is_equal(iovec_read, iovec_write, sz_read))
|
|
e(5);
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* 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) e(97);
|
|
else {
|
|
/* Creat the file */
|
|
if ((nr = creat(fnames[mode], mode * 0100)) < 0) e(98);
|
|
else
|
|
try_close(nr, fnames[mode]);
|
|
|
|
if (chdir("..") != OK) e(99);
|
|
}
|
|
} /* 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;
|
|
{
|
|
assert(range >= 0 && range <= ARSIZE);
|
|
|
|
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) e(100);
|
|
} /* try_close */
|
|
|
|
void try_unlink(fname)
|
|
char *fname;
|
|
{
|
|
if (unlink(fname) != 0) e(101);
|
|
} /* 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) {
|
|
e(102);
|
|
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 */
|
|
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* ALOT-functions *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
int open_alot()
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < MAXOPEN; i++)
|
|
if (open(file[i], R) == FAIL) break;
|
|
|
|
if (i == 0)
|
|
e(103);
|
|
return(i);
|
|
} /* open_alot */
|
|
|
|
int close_alot(number)
|
|
int number;
|
|
{
|
|
int i, count = 0;
|
|
|
|
if (number > MAXOPEN) e(104);
|
|
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) e(105);
|
|
else {
|
|
for (i = 0; i < 8; i++) try_unlink(fnames[i]);
|
|
if (chdir("..") != OK) e(106);
|
|
}
|
|
|
|
/* 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++;
|
|
}
|
|
}
|
|
|