From 615643cb123d295dbb8d0fe7b48689f8c6611f4a Mon Sep 17 00:00:00 2001 From: Egor Duda Date: Sat, 15 Sep 2001 19:54:04 +0000 Subject: [PATCH] * winsup.api/ltp/sbrk01.c (main): Force output at startup to make sure that stdio file buffer get allocated. * winsup.api/ltp/stat06.c (high_address_setup): On cygwin, area after sbrk(0) may be available, use 0xffff0000 as "high address". * winsup.api/ltp/symlink01.c: Perform all tests. Mark those tests that don't work on cygwin with '-1'. Close open files so that temporary directory can be deleted on exit. * winsup.api/ltp/vfork01.c: New test. --- winsup/testsuite/ChangeLog | 11 + winsup/testsuite/winsup.api/ltp/sbrk01.c | 9 +- winsup/testsuite/winsup.api/ltp/stat06.c | 4 + winsup/testsuite/winsup.api/ltp/symlink01.c | 28 +- winsup/testsuite/winsup.api/ltp/vfork01.c | 402 ++++++++++++++++++++ 5 files changed, 442 insertions(+), 12 deletions(-) create mode 100644 winsup/testsuite/winsup.api/ltp/vfork01.c diff --git a/winsup/testsuite/ChangeLog b/winsup/testsuite/ChangeLog index b8e2cc6c4..c95966b8e 100644 --- a/winsup/testsuite/ChangeLog +++ b/winsup/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2001-09-15 Egor Duda + + * winsup.api/ltp/sbrk01.c (main): Force output at startup to + make sure that stdio file buffer get allocated. + * winsup.api/ltp/stat06.c (high_address_setup): On cygwin, area + after sbrk(0) may be available, use 0xffff0000 as "high address". + * winsup.api/ltp/symlink01.c: Perform all tests. Mark those tests that + don't work on cygwin with '-1'. Close open files so that temporary + directory can be deleted on exit. + * winsup.api/ltp/vfork01.c: New test. + 2001-09-13 Egor Duda * winsup.api/winsup.exp: Run only selected test if environment diff --git a/winsup/testsuite/winsup.api/ltp/sbrk01.c b/winsup/testsuite/winsup.api/ltp/sbrk01.c index a302d5d0d..08fb0a184 100644 --- a/winsup/testsuite/winsup.api/ltp/sbrk01.c +++ b/winsup/testsuite/winsup.api/ltp/sbrk01.c @@ -149,6 +149,13 @@ main(int ac, char **av) ***************************************************************/ setup(); +#ifdef __CYGWIN__ + /* we need to initialize output buffer before first sbrk. + otherwise, when memory is freed bu second sbrk, fwrite will + fail */ + tst_resm(TINFO, "Entering test"); +#endif + /*************************************************************** * check looping state if -c option given ***************************************************************/ @@ -243,8 +250,6 @@ setup() /* make a temp dir and cd to it */ tst_tmpdir(); - - /* Pause if that option was specified */ TEST_PAUSE; } /* End setup() */ diff --git a/winsup/testsuite/winsup.api/ltp/stat06.c b/winsup/testsuite/winsup.api/ltp/stat06.c index f9fd0a90f..6da1507da 100644 --- a/winsup/testsuite/winsup.api/ltp/stat06.c +++ b/winsup/testsuite/winsup.api/ltp/stat06.c @@ -327,7 +327,11 @@ high_address_setup() for (ind=0; Test_cases[ind].desc != NULL; ind++ ) { if ( Test_cases[ind].pathname == High_address ) { /*if ( strcmp(Test_cases[ind].pathname, HIGH_ADDRESS) == 0 ) { ***/ +#ifndef __CYGWIN__ Test_cases[ind].pathname = (char *)(sbrk(0)+5); +#else + Test_cases[ind].pathname = (char *)0xffff0000; +#endif break; } } diff --git a/winsup/testsuite/winsup.api/ltp/symlink01.c b/winsup/testsuite/winsup.api/ltp/symlink01.c index cd0b56089..dcd6a749b 100644 --- a/winsup/testsuite/winsup.api/ltp/symlink01.c +++ b/winsup/testsuite/winsup.api/ltp/symlink01.c @@ -317,6 +317,7 @@ void do_open(); #define BIG_STRING "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz" #define DEFAULT_TCID "symlink01" +#define ALL 1 #define SYMLINK "symlink01" #define READLINK "readlink01" @@ -420,7 +421,7 @@ struct all_test_cases {LINK, 0, 0, 15, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}}, /* The following link test case is invalid - leaving it defined so */ /* I don't have to change all the entries in the all_tcses array after link */ - {LINK, 1, -1, -1, creat_symlink, ck_symlink, {NULL, NULL, NULL}}, + {LINK, -1, -1, -1, creat_symlink, ck_symlink, {NULL, NULL, NULL}}, {UNLINK, 0, 0, 16, creat_both, ck_both, {O_FILE, S_FILE, O_FILE}}, {CHMOD, 0, 0, 17, creat_both, ck_both, {O_FILE, S_FILE, O_FILE}}, {CHMOD, 1, ENOENT, 18, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}}, @@ -430,10 +431,10 @@ struct all_test_cases {UTIME, 1, ELOOP, 28, creat_symlink, ck_symlink, {S_FILE, S_FILE, NULL}}, {RENAME, 0, 0, 21, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}}, {RENAME, 0, 0, 22, creat_both, ck_both, {O_FILE, S_FILE, O_FILE}}, - {RENAME, 1, EXDEV, 23, creat_both, ck_both, {O_FILE, S_FILE, O_FILE}}, + {RENAME, -1, EXDEV, 23, creat_both, ck_both, {O_FILE, S_FILE, O_FILE}}, {OPEN, 0, 0, 24, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}}, {OPEN, 0, 0, 25, creat_both, ck_both, {O_FILE, S_FILE, O_FILE}}, - {OPEN, 1, EEXIST, 26, creat_symlink, ck_symlink, {O_FILE, S_FILE, O_FILE}}, + {OPEN, -1, EEXIST, 26, creat_symlink, ck_symlink, {O_FILE, S_FILE, O_FILE}}, {OPEN, 1, ENOENT, 27, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}}, {OPEN, 1, ELOOP, 28, creat_symlink, ck_symlink, {S_FILE, S_FILE, NULL}} }; @@ -485,7 +486,7 @@ struct tcses int TST_TOTAL; int TEST_RESULT; time_t a_time_value = 100; -char *TCID; +char *TCID = NULL; char *Selectedtests = NULL; /* Name (tcid) of selected test cases */ char test_msg[BUFMAX]; char full_path[PATH_MAX+1]; @@ -534,12 +535,14 @@ main(int argc, char *argv[]) Selectedtests=Tcid; } -#ifndef ALL else { TCID = DEFAULT_TCID; +#ifndef ALL Selectedtests = DEFAULT_TCID; - } +#else + Selectedtests = NULL; #endif + } /* * Get test case specification information and assign TST_TOTAL @@ -932,13 +935,15 @@ struct tcses *tcs; */ for (ctr=0, tc_ptr=tcs->tc_ptr; ctr < TST_TOTAL; ctr++, tc_ptr++) { + if (tc_ptr->test_fail < 0) continue; + Buffer[0]='\0'; /* * If running all test cases for all tcid, set the TCID if needed. */ if ( Selectedtests == NULL ) { - if ( strcmp(tcs->tcid, tc_ptr->tcid) != 0 ) { + if ( !TCID || strcmp(TCID, tc_ptr->tcid) != 0 ) { TCID = tc_ptr->tcid; Tst_count=0; } @@ -946,9 +951,9 @@ struct tcses *tcs; /* * Insure that we are executing the correct tcs test case */ - if (strcmp(tcs->tcid, tc_ptr->tcid) != 0) { + if (strcmp(TCID, tc_ptr->tcid) != 0) { tst_resm(TBROK, "%s TCID attempted to execute %s %d %d test case", - tcs->tcid, tc_ptr->tcid, tc_ptr->test_fail, tc_ptr->errno_val); + TCID, tc_ptr->tcid, tc_ptr->test_fail, tc_ptr->errno_val); continue; } TEST_RESULT=TPASS; @@ -1091,6 +1096,7 @@ struct all_test_cases *tc_ptr; "Expected EEXIST error for exclusively opening an object file", "through a symbolic link file was not received:", errno, strerror(errno)); + close (TEST_RETURN); } else tst_resm(TBROK, "Unknown test case processing actions declared"); @@ -1185,6 +1191,7 @@ struct all_test_cases *tc_ptr; "Expected ENOENT error for opening a non-existent object", " file through a symbolic link file was not received,", errno, strerror(errno)); + close (TEST_RETURN); } else tst_resm(TBROK, "Unknown test case processing actions declared"); @@ -1294,6 +1301,7 @@ struct all_test_cases *tc_ptr; tst_resm(TFAIL, "%s errno:%d %s", "Expected ELOOP error condition when open(2) a nested symbolic link:", errno, strerror(errno)); + close (fd); } else tst_resm(TBROK, "Unknown test case processing actions declared"); @@ -1583,7 +1591,7 @@ struct all_test_cases *tc_ptr; Buffer, "symbolic link which which pointed at object"); else { - char buf [PATH_MAX]; + char buf [PATH_MAX]; char *cwd; char expected_location[PATH_MAX]; /* diff --git a/winsup/testsuite/winsup.api/ltp/vfork01.c b/winsup/testsuite/winsup.api/ltp/vfork01.c new file mode 100644 index 000000000..41e48c461 --- /dev/null +++ b/winsup/testsuite/winsup.api/ltp/vfork01.c @@ -0,0 +1,402 @@ +/* + * + * Copyright (c) International Business Machines Corp., 2001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Name: vfork01 + * + * Test Description: + * Fork a process using vfork() and verify that, the attribute values like + * euid, ruid, suid, egid, rgid, sgid, umask, inode and device number of + * root and current working directories are same as that of the parent + * process. + * + * Expected Result: + * The attribute values like euid, ruid, suid, egid, rgid, sgid, umask, inode + * and device number of root and current working directory of the parent and + * child processes should be equal. + * + * Algorithm: + * Setup: + * Setup signal handling. + * Pause for SIGUSR1 if option specified. + * + * Test: + * Loop if the proper options are given. + * Execute system call + * Check return code, if system call failed (return=-1) + * Log the errno and Issue a FAIL message. + * Otherwise, + * Verify the Functionality of system call + * if successful, + * Issue Functionality-Pass message. + * Otherwise, + * Issue Functionality-Fail message. + * Cleanup: + * Print errno log and/or timing stats if options given + * + * Usage: + * vfork01 [-c n] [-e] [-f] [-i n] [-I x] [-p x] [-t] + * where, -c n : Run n copies concurrently. + * -e : Turn on errno logging. + * -f : Turn off functionality Testing. + * -i n : Execute test n times. + * -I x : Execute test for x seconds. + * -P x : Pause for x seconds between iterations. + * -t : Turn on syscall timing. + * + * History + * 07/2001 John George + * -Ported + * + * Restrictions: + * None. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test.h" +#include "usctest.h" + +char *TCID="vfork01"; /* Test program identifier. */ +int TST_TOTAL=1; /* Total number of test cases. */ +extern int Tst_count; /* Test Case counter for tst_* routines */ +int exp_enos[]={0}; + +/* Variables to hold parent/child eff/real/saved uid/gid values */ +uid_t Peuid, Ceuid, Csuid, Psuid, Pruid, Cruid; +gid_t Pegid, Cegid, Psgid, Csgid, Prgid, Crgid; +mode_t Pumask,Cumask; + +char Pcwd_buf [PATH_MAX], Ccwd_buf [PATH_MAX]; +char *Pcwd, *Ccwd; /* + * pathname of working directory of + * child/parent process. + */ +/* stat structure to hold directory/inode information for parent/child */ +struct stat StatPbuf; +struct stat StatCbuf; +struct stat Stat_cwd_Pbuf; +struct stat Stat_cwd_Cbuf; + +void setup(); /* Main setup function of test */ +void cleanup(); /* cleanup function for the test */ + +int +main(int ac, char **av) +{ + int lc; /* loop counter */ + const char *msg; /* message returned from parse_opts */ + pid_t cpid; /* process id of the child process */ + int exit_status; /* exit status of child process */ + + /* Parse standard options given to run the test. */ + msg = parse_opts(ac, av, (option_t *) NULL, NULL); + if (msg != (char *) NULL) { + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); + tst_exit(); + } + + /* Perform global setup for test */ + setup(); + + /* set the expected errnos... */ + TEST_EXP_ENOS(exp_enos); + + /* Check looping state if -i option given */ + for (lc = 0; TEST_LOOPING(lc); lc++) { + /* Reset Tst_count in case we are looping. */ + Tst_count=0; + + /* + * Call vfork(2) to create a child process without + * fully copying the address space of parent. + */ + TEST(vfork()); + + /* check return code of vfork() */ + if ((cpid = TEST_RETURN) == -1) { + TEST_ERROR_LOG(TEST_ERRNO); + tst_resm(TFAIL, "vfork() Failed, errno=%d : %s", + TEST_ERRNO, strerror(TEST_ERRNO)); + } else if (cpid == 0) { /* Child process */ + /* + * Perform functional verification if test + * executed without (-f) option. + */ + if (STD_FUNCTIONAL_TEST) { + /* + * Get the euid, ruid, egid, rgid, umask value + * and the current working directory of the + * child process + */ +#if (linux) + if (getresuid(&Cruid, &Ceuid, &Csuid) < 0) { + tst_resm(TFAIL, "getresuid() fails to " + "get real/eff./saved uid of " + "child process"); + _exit(1); + } + + if (getresgid(&Crgid, &Cegid, &Csgid) < 0) { + tst_resm(TFAIL, "getresgid() fails to " + "get real/eff./saved gid of " + "child process"); + _exit(1); + } +#else + Cruid = getuid (); + Ceuid = geteuid (); + Csuid = 0; + Crgid = getgid (); + Cegid = getegid (); + Csgid = 0; +#endif + /* + * Get the file mode creation mask value of + * child process by setting value zero and + * restore the previous mask value. + */ + Cumask = umask(0); + + /* + * Restore the process mask of child to + * previous value. + */ + umask(Cumask); + + /* + * Get the pathname of current working + * directory for the child process. + */ + if ((Ccwd = (char *)getcwd(Ccwd_buf, \ + BUFSIZ)) == NULL) { + tst_resm(TFAIL, "getcwd failed for the " + "child process"); + _exit(1); + } + + /* + * Get the device number and the inode + * number of "/" directory for the child + * process. + */ + if (stat("/", &StatCbuf) < 0) { + tst_resm(TFAIL, "stat(2) failed to get " + "info. of'/' in the child " + "process"); + _exit(1); + } + + /* + * Get the device/inode number of "." + * (working directory) for the child process. + */ + if (stat(Ccwd, &Stat_cwd_Cbuf) < 0) { + tst_resm(TFAIL, "stat(2) failed to get " + "info. of working irectory in " + "the child"); + _exit(1); + } + + /* Now, do the actual comparision */ + if (Peuid != Ceuid || Pegid != Cegid || \ + Psuid != Csuid || Psgid != Csgid || \ + Pruid != Cruid || Prgid != Crgid || \ + Pumask != Cumask) { + tst_resm(TFAIL, "Arribute values of " + "parent and child don't match"); + _exit(1); + } else { + tst_resm(TINFO, "Arribute values of " + "parent and child match"); + } + + /* Check for the same working directories */ + if (strcmp(Pcwd, Ccwd) != 0) { + tst_resm(TFAIL, "Working directories " + "of parent and child don't " + "match"); + _exit(1); + } else { + tst_resm(TINFO, "Working directories " + "of parent and child match"); + } + + /* + * Check for the same device/inode number of + * '/' directory. + */ + if ((StatPbuf.st_ino != StatCbuf.st_ino) || \ + (StatPbuf.st_dev != StatCbuf.st_dev)) { + tst_resm(TFAIL, "Device/inode number " + "of parent and childs '/' " + " don't match"); + _exit(1); + } else { + tst_resm(TINFO, "Device/inode number " + "of parent and childs '/' " + "match"); + } + + /* + * Check for the same device and inode number + * of "." (current working directory. + */ + if ((Stat_cwd_Pbuf.st_ino != \ + Stat_cwd_Cbuf.st_ino) || \ + (Stat_cwd_Pbuf.st_dev != \ + Stat_cwd_Cbuf.st_dev)) { + tst_resm(TFAIL, "Device/inode number " + "of parent and childs '.' " + "don't match"); + _exit(1); + } else { + tst_resm(TINFO, "Device/inode number " + "of parent and childs '.' " + "match"); + } + + /* + * Exit with normal exit code if everything + * fine + */ + _exit(0); + } + } else { /* parent process */ + /* + * Let the parent process wait till child completes + * its execution. + */ + wait(&exit_status); + + /* Check for the exit status of child process */ + if (WEXITSTATUS(exit_status) == 0) { + tst_resm(TPASS, \ + "Call of vfork() successful"); + } else if (WEXITSTATUS(exit_status) == 1) { + tst_resm(TFAIL, \ + "Child process exited abnormally"); + } + } + Tst_count++; /* incr. TEST_LOOP counter */ + } /* End for TEST_LOOPING */ + + /* Call cleanup() to undo setup done for the test. */ + cleanup(); + /*NOTREACHED*/ + +} /* End main */ + +/* + * void + * setup() - performs all ONE TIME setup for this test. + * This function gets real/effective/saved uid/gid, umask, the device/inode + * number of '/' and current working directory for the parent process. + */ +void +setup() +{ + /* capture signals */ + tst_sig(FORK, DEF_HANDLER, cleanup); + + /* Pause if that option was specified */ + TEST_PAUSE; + + /* + * Get the euid, ruid, egid, rgid, umask value + * and the current working directory of the parent process. + */ +#if (linux) + if (getresuid(&Pruid, &Peuid, &Psuid) < 0) { + tst_brkm(TFAIL, cleanup, "getresuid() fails to get " + "real/eff./saved uid of parent"); + } + + if (getresgid(&Prgid, &Pegid, &Psgid) < 0) { + tst_brkm(TFAIL, cleanup, "getresgid() fails to get " + "real/eff./saved gid of parent"); + } +#else + Pruid = getuid (); + Peuid = geteuid (); + Psuid = 0; + Prgid = getgid (); + Pegid = getegid (); + Psgid = 0; +#endif + /* Get the process file mode creation mask by setting value 0 */ + Pumask = umask(0); + umask(Pumask); /* + * Restore the mask value of the + * process. + */ + /* + * Get the pathname of current working directory of the parent + * process. + */ + if ((Pcwd = (char *) getcwd(Pcwd_buf, BUFSIZ)) == NULL) { + tst_brkm(TFAIL, cleanup, + "getcwd failed for the parent process"); + } + + /* + * Get the device and inode number of root directory for the + * parent process. + */ + if (stat("/", &StatPbuf) == -1) { + tst_brkm(TFAIL, cleanup, "stat(2) failed to get info. of '/' " + "in parent process"); + } + + /* + * Get the device number and the inode number of "." (current- + * working directory) for the parent process. + */ + if (stat(Pcwd, &Stat_cwd_Pbuf) < 0) { + tst_brkm(TFAIL, cleanup, "stat(2) failed to get info. of " + "working directory in parent process"); + } +} /* End setup() */ + +/* + * void + * cleanup() - performs all ONE TIME cleanup for this test at + * completion or premature exit. + */ +void +cleanup() +{ + /* + * print timing stats if that option was specified. + * print errno log if that option was specified. + */ + TEST_CLEANUP; + + /* exit with return code appropriate for results */ + tst_exit(); +} /* End cleanup() */