2005-04-21 16:53:53 +02:00
|
|
|
/* 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>
|
2006-02-13 12:07:21 +01:00
|
|
|
#include <limits.h>
|
2010-01-08 14:40:34 +01:00
|
|
|
#include <assert.h>
|
|
|
|
#include <sys/uio.h>
|
2005-04-21 16:53:53 +02:00
|
|
|
|
|
|
|
#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 */
|
2006-02-13 12:07:21 +01:00
|
|
|
#define MAXOPEN (OPEN_MAX-3) /* maximum number of extra open files */
|
2005-04-21 16:53:53 +02:00
|
|
|
#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"
|
2010-01-08 14:40:34 +01:00
|
|
|
#define WRITEV "writev"
|
2005-04-21 16:53:53 +02:00
|
|
|
#define READ "read"
|
2010-01-08 14:40:34 +01:00
|
|
|
#define READV "readv"
|
2005-04-21 16:53:53 +02:00
|
|
|
#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 */
|
2010-07-13 14:38:58 +02:00
|
|
|
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"};
|
|
|
|
|
2005-04-21 16:53:53 +02:00
|
|
|
/* Needed for easy creating and deleting of directories */
|
|
|
|
|
|
|
|
/* "test.c", created by Rene Montsma and Menno Wilcke */
|
|
|
|
|
2009-12-04 18:51:06 +01:00
|
|
|
_PROTOTYPE(int main, (int argc, char **argv));
|
2005-04-21 16:53:53 +02:00
|
|
|
_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));
|
2010-01-08 14:40:34 +01:00
|
|
|
_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));
|
2005-04-21 16:53:53 +02:00
|
|
|
_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 *
|
|
|
|
****************************************************************************/
|
2009-12-04 18:51:06 +01:00
|
|
|
int main(int argc, char **argv)
|
2005-04-21 16:53:53 +02:00
|
|
|
{
|
2009-12-04 18:51:06 +01:00
|
|
|
char buffer[PATH_MAX + 1];
|
2010-07-13 14:38:58 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2005-04-21 16:53:53 +02:00
|
|
|
|
2010-07-13 14:38:58 +02:00
|
|
|
#define DIR "DIR18"
|
|
|
|
system("rm -rf " DIR);
|
|
|
|
if(mkdir(DIR, 0755) != 0) {
|
|
|
|
perror("mkdir");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if(chdir(DIR) != 0) {
|
|
|
|
perror("chdir");
|
|
|
|
return 1;
|
|
|
|
}
|
2005-04-21 16:53:53 +02:00
|
|
|
|
|
|
|
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();
|
2010-01-08 14:40:34 +01:00
|
|
|
test08();
|
2005-04-21 16:53:53 +02:00
|
|
|
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 */
|
2010-07-13 14:38:58 +02:00
|
|
|
if ((n = open("drw-/rwx", R)) != FAIL)
|
2005-04-21 16:53:53 +02:00
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
2010-01-08 14:40:34 +01:00
|
|
|
/*****************************************************************************
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
2005-04-21 16:53:53 +02:00
|
|
|
/***********************************************************************
|
|
|
|
* 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()
|
|
|
|
{
|
2010-07-06 13:29:23 +02:00
|
|
|
fputs("\n",stdout);
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
|
2010-07-06 13:29:23 +02:00
|
|
|
void str(char *s)
|
2005-04-21 16:53:53 +02:00
|
|
|
{
|
2010-07-06 13:29:23 +02:00
|
|
|
fputs(s,stdout);
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* *
|
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
}
|