Importing Egor's testsuite.
This commit is contained in:
426
winsup/testsuite/winsup.api/ltp/fcntl07.c
Normal file
426
winsup/testsuite/winsup.api/ltp/fcntl07.c
Normal file
@@ -0,0 +1,426 @@
|
||||
/*
|
||||
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Further, this software is distributed without any warranty that it is
|
||||
* free of the rightful claim of any third person regarding infringement
|
||||
* or the like. Any license provided herein, whether implied or
|
||||
* otherwise, applies only to this software file. Patent licenses, if
|
||||
* any, provided herein do not apply to combinations of this program with
|
||||
* other software, or any other product whatsoever.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write the Free Software Foundation, Inc., 59
|
||||
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
*
|
||||
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
* Mountain View, CA 94043, or:
|
||||
*
|
||||
* http://www.sgi.com
|
||||
*
|
||||
* For further information regarding this notice, see:
|
||||
*
|
||||
* http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
*
|
||||
*/
|
||||
/* $Id$ */
|
||||
/**********************************************************
|
||||
*
|
||||
* OS Test - Silicon Graphics, Inc.
|
||||
*
|
||||
* TEST IDENTIFIER : fcntl07
|
||||
*
|
||||
* EXECUTED BY : anyone
|
||||
*
|
||||
* TEST TITLE : Close-On-Exec functional test
|
||||
*
|
||||
* PARENT DOCUMENT : none
|
||||
*
|
||||
* TEST CASE TOTAL : 2
|
||||
*
|
||||
* WALL CLOCK TIME : 5
|
||||
*
|
||||
* CPU TYPES : ALL
|
||||
*
|
||||
* AUTHOR : Glen Overby
|
||||
*
|
||||
* CO-PILOT : William Roske
|
||||
*
|
||||
* DATE STARTED : 08/11/93
|
||||
*
|
||||
* INITIAL RELEASE : UNICOS 7.0
|
||||
*
|
||||
* TEST CASES
|
||||
*
|
||||
* 1.) test close-on-exec with a regular file
|
||||
* 2.) test close-on-exec with a system pipe
|
||||
*
|
||||
* INPUT SPECIFICATIONS
|
||||
*
|
||||
* Standard arguments accepted by parse_opts(3).
|
||||
*
|
||||
* The -t (timing) and -e options apply to the fcntl(.., F_SETFD, ..)
|
||||
* system call.
|
||||
*
|
||||
* -T fd : If this option is given, the program runs as "test_open",
|
||||
* testing <fd> to see if it is open or not and exiting
|
||||
* accordingly:
|
||||
* 0 not open (EBADF from fcntl(..., F_GETFD, ...))
|
||||
* 3 no error from fcntl
|
||||
* errno fcntl returned an error other than EBADF
|
||||
*
|
||||
* -F name : File to open. Must be an absolute path
|
||||
* and the file must be writable;
|
||||
* -n program: path to the 'test_open' program
|
||||
*
|
||||
* OUTPUT SPECIFICATIONS
|
||||
* This test uses the cuts-style test_res format output consisting of:
|
||||
*
|
||||
* test-name PASS/FAIL/BROK message
|
||||
*
|
||||
* the message will tell what type of test and, if it failed, indicate
|
||||
* what the failure was.
|
||||
*
|
||||
* DURATION
|
||||
* Terminates
|
||||
*
|
||||
* SIGNALS
|
||||
* None
|
||||
*
|
||||
* RESOURCES
|
||||
* None
|
||||
*
|
||||
* ENVIRONMENTAL NEEDS
|
||||
* No run-time environmental needs.
|
||||
*
|
||||
* If this test is not called with a full pathname, it must be able
|
||||
* to find itself on $PATH
|
||||
*
|
||||
* INTERCASE DEPENDENCIES
|
||||
* none
|
||||
*
|
||||
* DETAILED DESCRIPTION
|
||||
*
|
||||
* Setup:
|
||||
* Setup signal handling.
|
||||
* Create and make current a temporary directory.
|
||||
* Open a regular file for writing
|
||||
* Create a system pipe
|
||||
* Create a named pipe and open it for writing
|
||||
*
|
||||
* Test:
|
||||
* Set the file descriptor for close-on-exec
|
||||
* Fork
|
||||
* Child execlp's the program "test_open".
|
||||
* If the exec fails, exit "2"
|
||||
* Parent waits
|
||||
* Report results.
|
||||
*
|
||||
* Cleanup:
|
||||
* Close file and pipes
|
||||
* Remove the temporary directory
|
||||
*
|
||||
* BUGS
|
||||
*
|
||||
*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "test.h"
|
||||
#include "usctest.h"
|
||||
#include "search_path.h"
|
||||
|
||||
void setup();
|
||||
void cleanup();
|
||||
void help();
|
||||
|
||||
char *TCID="fcntl07"; /* Test program identifier. */
|
||||
int TST_TOTAL=2; /* Total number of test cases. */
|
||||
extern int Tst_count; /* Test Case counter for tst_* routines */
|
||||
|
||||
|
||||
|
||||
/* for parse_opts */
|
||||
int fflag, Tflag; /* binary flags: opt or not */
|
||||
char *fopt, *Topt; /* option arguments */
|
||||
|
||||
option_t options[] = {
|
||||
{ "F:", &fflag, &fopt }, /* -F filename */
|
||||
{ "T:", &Tflag, &Topt }, /* -T <fd> exec'ed by test: test FD */
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
int stat_loc; /* for waitpid() */
|
||||
|
||||
int file_fd, pipe_fds[2];
|
||||
/* file descriptors for a file and a system pipe */
|
||||
#define DEFAULT_FILE "DefaultFileName"
|
||||
char *File1 = DEFAULT_FILE;
|
||||
|
||||
#define DEFAULT_SUBPROG "test_open"
|
||||
char *openck = DEFAULT_SUBPROG; /* support program name to check for open FD */
|
||||
char subprog_path[_POSIX_PATH_MAX]; /* path to exec "openck" with */
|
||||
#define STRSIZE 255
|
||||
|
||||
int *testfds[] = {
|
||||
&file_fd, &pipe_fds[1], 0
|
||||
};
|
||||
|
||||
char *testfdtypes[] = {
|
||||
"regular file",
|
||||
"write side of system pipe",
|
||||
};
|
||||
|
||||
int test_open(char *arg);
|
||||
int do_exec(char *prog, int fd, char *tcd);
|
||||
|
||||
int
|
||||
main(int ac, char **av)
|
||||
{
|
||||
int lc; /* loop counter */
|
||||
char *msg; /* message returned from parse_opts */
|
||||
|
||||
int exec_return; /* return from do_exec */
|
||||
int **tcp; /* testcase pointer (pointer to FD) */
|
||||
char **tcd; /* testcase description pointer */
|
||||
|
||||
/***************************************************************
|
||||
* parse standard options, and exit if there is an error
|
||||
***************************************************************/
|
||||
if ( (msg=parse_opts(ac, av, options, &help)) != (char *) NULL ) {
|
||||
tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
|
||||
tst_exit();
|
||||
}
|
||||
|
||||
if(fflag) /* -F option */
|
||||
File1 = fopt;
|
||||
|
||||
if(Tflag) { /* -T option */
|
||||
exit(test_open(Topt));
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* perform global setup for test
|
||||
***************************************************************/
|
||||
setup(av[0]);
|
||||
|
||||
/***************************************************************
|
||||
* check looping state if -c option given
|
||||
***************************************************************/
|
||||
for (lc=0; TEST_LOOPING(lc); lc++) {
|
||||
|
||||
/* reset Tst_count in case we are looping. */
|
||||
Tst_count=0;
|
||||
|
||||
for(tcp = testfds, tcd = testfdtypes; *tcp; tcp++, tcd++) {
|
||||
|
||||
TEST(fcntl(**tcp, F_SETFD, FD_CLOEXEC));
|
||||
|
||||
/* check return code */
|
||||
if ( TEST_RETURN == -1 ) {
|
||||
TEST_ERROR_LOG(TEST_ERRNO);
|
||||
tst_resm(TFAIL, "fcntl(%s[%d], F_SETFD, FD_CLOEXEC) Failed, errno=%d : %s",
|
||||
*tcd, **tcp, TEST_ERRNO, strerror(TEST_ERRNO));
|
||||
} else {
|
||||
|
||||
/*************************************************************
|
||||
* only perform functional verification if flag set
|
||||
* (-f not given)
|
||||
*************************************************************/
|
||||
if ( STD_FUNCTIONAL_TEST ) {
|
||||
|
||||
exec_return = do_exec(subprog_path, **tcp, *tcd);
|
||||
|
||||
switch(exec_return) {
|
||||
case -1:
|
||||
tst_resm(TBROK, "fork failed. Errno %s [%d]",
|
||||
strerror(errno), errno);
|
||||
break;
|
||||
case 1:
|
||||
tst_resm(TBROK, "waitpid return was 0%o", stat_loc);
|
||||
break;
|
||||
case 2:
|
||||
tst_resm(TBROK, "exec failed"); /* errno was in child */
|
||||
break;
|
||||
case 0:
|
||||
tst_resm(TPASS, "%s child exited 0, indicating that the file was closed",
|
||||
*tcd);
|
||||
break;
|
||||
default:
|
||||
tst_resm(TFAIL, "%s child exited non-zero, %d", *tcd,
|
||||
exec_return);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* End for TEST_LOOPING */
|
||||
|
||||
/***************************************************************
|
||||
* cleanup and exit
|
||||
***************************************************************/
|
||||
cleanup();
|
||||
|
||||
return 0;
|
||||
} /* End main */
|
||||
|
||||
/***************************************************************
|
||||
* setup() - performs all ONE TIME setup for this test.
|
||||
***************************************************************/
|
||||
void
|
||||
setup(char *path)
|
||||
{
|
||||
search_path(path, subprog_path, X_OK, 1);
|
||||
|
||||
/* capture signals */
|
||||
tst_sig(FORK, DEF_HANDLER, cleanup);
|
||||
|
||||
/* create a temporary directory and go to it */
|
||||
tst_tmpdir();
|
||||
|
||||
/* set up a regular file */
|
||||
if((file_fd=open(File1, O_CREAT|O_RDWR, 0666)) == -1) {
|
||||
tst_brkm(TBROK, cleanup, "Open of file %s failed errno %d (%s)\n", File1, errno, strerror(errno));
|
||||
}
|
||||
|
||||
/* set up a system pipe (write side gets CLOSE-ON-EXEC) */
|
||||
pipe(pipe_fds);
|
||||
|
||||
/* Pause if that option was specified */
|
||||
TEST_PAUSE;
|
||||
} /* End setup() */
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* 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;
|
||||
|
||||
/* close everything */
|
||||
close(file_fd);
|
||||
close(pipe_fds[0]);
|
||||
close(pipe_fds[1]);
|
||||
|
||||
/* remove temporary directory and all files in it. */
|
||||
tst_rmdir();
|
||||
|
||||
/* exit with return code appropriate for results */
|
||||
tst_exit();
|
||||
} /* End cleanup() */
|
||||
|
||||
/***************************************************************************
|
||||
* issue a help message
|
||||
***************************************************************************/
|
||||
void
|
||||
help()
|
||||
{
|
||||
printf("-T fd : If this option is given, the program runs as 'test_open'\n");
|
||||
printf(" testing <fd> to see if it is open or not and exiting accordingly\n");
|
||||
printf("-F name : File to open. Must be an absolute path,\n");
|
||||
printf(" and the file must be writable\n");
|
||||
printf("-n program: path to the 'test_open' program\n");
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Perform an exec, then wait for the child to terminate.
|
||||
* The child's termination status determines the success of the test
|
||||
*
|
||||
* Return codes:
|
||||
* -1 BROK fork failed
|
||||
* 1 BROK waitpid returned != exit status
|
||||
* <else> ???? exit code from child:
|
||||
* 2 BROK exec failed
|
||||
* 0 PASS fd was properly closed
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
do_exec(char *prog, int fd, char *tcd)
|
||||
{
|
||||
int pid;
|
||||
char pidname[STRSIZE];
|
||||
#ifdef DEBUG
|
||||
int rc, status; /* for the fcntl */
|
||||
#endif
|
||||
|
||||
/* set up arguments to exec'ed child */
|
||||
sprintf(pidname, "%d", fd);
|
||||
|
||||
#ifdef DEBUG
|
||||
rc = fcntl(fd, F_GETFD, &status);
|
||||
printf("%s: fd = %d rc = %d status= %d, errno= %d\n", tcd, fd, rc, status, errno);
|
||||
#endif
|
||||
|
||||
switch(pid=fork()) {
|
||||
case -1:
|
||||
return(-1);
|
||||
case 0: /* child */
|
||||
execlp(prog, openck, "-T", pidname, 0);
|
||||
|
||||
/* the ONLY reason to do this is to get the errno printed out */
|
||||
fprintf(stderr, "exec(%s, %s, -T, %s) failed. Errno %s [%d]\n",
|
||||
prog, openck, pidname, strerror(errno), errno);
|
||||
exit(2);
|
||||
default: /* parent */
|
||||
waitpid(pid, &stat_loc, 0);
|
||||
if(WIFEXITED(stat_loc)) {
|
||||
return(WEXITSTATUS(stat_loc));
|
||||
} else {
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* PROGRAM TITLE : Test if a named file descriptor is open
|
||||
* This function is called when fcntcs07 is called with the -T option.
|
||||
* It tests if a file descriptor is open and exits accordingly.
|
||||
*/
|
||||
int
|
||||
test_open(char *arg)
|
||||
{
|
||||
int fd, rc;
|
||||
int status;
|
||||
|
||||
fd = atoi(arg);
|
||||
|
||||
rc = fcntl(fd, F_GETFD, &status);
|
||||
|
||||
#ifdef DEBUG_T
|
||||
printf("%s: fd = %d rc = %d status= %d, errno= %d\n", openck, fd, rc,
|
||||
status, errno);
|
||||
#endif
|
||||
|
||||
if(rc == -1 && errno == EBADF) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if(rc != -1)
|
||||
exit(3);
|
||||
|
||||
exit(errno);
|
||||
return -1; /* to remove compiler warning on IRIX */
|
||||
}
|
Reference in New Issue
Block a user