421 lines
7.7 KiB
C
421 lines
7.7 KiB
C
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
|
||
|
#include <string.h>
|
||
|
#include <signal.h>
|
||
|
#include <errno.h>
|
||
|
#include <sys/wait.h>
|
||
|
#include <unistd.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <sys/stat.h>
|
||
|
|
||
|
#include "tsttmp.h" // defines DbgPrint as printf
|
||
|
|
||
|
extern int errno;
|
||
|
VOID npipe0(char *);
|
||
|
VOID npipe1(char *);
|
||
|
VOID npipe2(char *);
|
||
|
VOID npipe3(char *);
|
||
|
VOID npipe4(char *);
|
||
|
VOID npipe5(VOID);
|
||
|
|
||
|
//
|
||
|
// 'tstnpipe named.pip'.
|
||
|
//
|
||
|
// The directory /psx/test is used as the base directory. The zero-length
|
||
|
// file named 'named.pip must exist in that directory.
|
||
|
//
|
||
|
|
||
|
char
|
||
|
nulltouch(char *f)
|
||
|
{
|
||
|
return 'a';
|
||
|
}
|
||
|
|
||
|
|
||
|
int
|
||
|
main(int argc, char *argv[])
|
||
|
{
|
||
|
if (argc != 2) {
|
||
|
DbgPrint("Usage: 'tstnpipe named.pip'\n");
|
||
|
return 1;
|
||
|
}
|
||
|
ASSERT(strcmp(argv[1],"named.pip") == 0);
|
||
|
|
||
|
npipe0(argv[1]);
|
||
|
npipe1(argv[1]);
|
||
|
npipe2(argv[1]);
|
||
|
npipe3(argv[1]);
|
||
|
npipe4(argv[1]);
|
||
|
npipe5();
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
npipe0(char *f)
|
||
|
{
|
||
|
int rc,wfd,rfd;
|
||
|
char buf[512];
|
||
|
|
||
|
DbgPrint("npipe0:++ %s\n",f);
|
||
|
nulltouch(f);
|
||
|
|
||
|
//
|
||
|
// Open for read with NONBLOCK. Open should complete
|
||
|
// without delay.
|
||
|
//
|
||
|
|
||
|
rfd = open(f, O_RDONLY | O_NONBLOCK);
|
||
|
ASSERT(rfd != -1);
|
||
|
|
||
|
//
|
||
|
// Since there is no data in pipe, read should complete and
|
||
|
// return 0 as the byte count.
|
||
|
//
|
||
|
|
||
|
rc = read(rfd,buf,512);
|
||
|
ASSERT(rc == 0);
|
||
|
|
||
|
//
|
||
|
// Open for write with NONBLOCK. Should succeed
|
||
|
//
|
||
|
|
||
|
wfd = open(f,O_WRONLY | O_NONBLOCK);
|
||
|
ASSERT(wfd != -1);
|
||
|
|
||
|
rc = write(wfd,"Hello World\n",13);
|
||
|
ASSERT(rc == 13);
|
||
|
|
||
|
rc = read(rfd,buf,512);
|
||
|
ASSERT(rc == 13 && (strcmp(buf,"Hello World\n") == 0 ));
|
||
|
|
||
|
rc = close(rfd);
|
||
|
ASSERT(rc != -1);
|
||
|
|
||
|
rc = close(wfd);
|
||
|
ASSERT(rc != -1);
|
||
|
|
||
|
//
|
||
|
// Open for write with NONBLOCK. Should fail since read handle was
|
||
|
// closed.
|
||
|
//
|
||
|
|
||
|
wfd = open(f,O_WRONLY | O_NONBLOCK);
|
||
|
ASSERT(wfd == -1 && errno == ENXIO);
|
||
|
|
||
|
DbgPrint("npipe0:--\n");
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
npipe1(char *f)
|
||
|
{
|
||
|
int rc,wfd,rfd,stat_loc;
|
||
|
pid_t child;
|
||
|
char buf[512];
|
||
|
|
||
|
DbgPrint("npipe1:++ %s\n",f);
|
||
|
|
||
|
wfd = open("foobar.bad",O_WRONLY);
|
||
|
|
||
|
nulltouch(f);
|
||
|
child = fork();
|
||
|
nulltouch(f);
|
||
|
|
||
|
//
|
||
|
// Make sure that in the simple case,
|
||
|
// the named pipe open protocol works
|
||
|
//
|
||
|
|
||
|
if ( child == 0 ) {
|
||
|
|
||
|
rfd = open(f,O_RDONLY);
|
||
|
ASSERT(rfd != -1);
|
||
|
|
||
|
rc = read(rfd,buf,512);
|
||
|
ASSERT(rc == 13 && (strcmp(buf,"Hello World\n") == 0 ));
|
||
|
|
||
|
_exit(rc);
|
||
|
}
|
||
|
|
||
|
wfd = open(f,O_WRONLY);
|
||
|
ASSERT(wfd != -1);
|
||
|
|
||
|
rc = write(wfd,"Hello World\n",13);
|
||
|
ASSERT(rc == 13);
|
||
|
|
||
|
rc = waitpid(child,&stat_loc,0);
|
||
|
ASSERT(rc == child && WIFEXITED(stat_loc) && WEXITSTATUS(stat_loc) == 13);
|
||
|
|
||
|
rc = close(wfd);
|
||
|
ASSERT(rc != -1);
|
||
|
|
||
|
//
|
||
|
// Open for write with NONBLOCK. Should fail since read handle was
|
||
|
// closed by childs process exit.
|
||
|
//
|
||
|
|
||
|
wfd = open(f,O_WRONLY | O_NONBLOCK);
|
||
|
ASSERT(wfd == -1 && errno == ENXIO);
|
||
|
|
||
|
DbgPrint("npipe1:--\n");
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
npipe2(char *f)
|
||
|
{
|
||
|
int rc,wfd,rfd,rfd2,stat_loc;
|
||
|
pid_t child1,child2;
|
||
|
char buf[512];
|
||
|
|
||
|
DbgPrint("npipe2:++ %s\n",f);
|
||
|
|
||
|
nulltouch(f);
|
||
|
child1 = fork();
|
||
|
nulltouch(f);
|
||
|
|
||
|
//
|
||
|
// Make sure that if we have a case where two readers open the
|
||
|
// pipe, one writers open will catch them both
|
||
|
//
|
||
|
|
||
|
if ( child1 == 0 ) {
|
||
|
|
||
|
nulltouch(f);
|
||
|
child2 = fork();
|
||
|
nulltouch(f);
|
||
|
|
||
|
if ( child2 == 0 ) {
|
||
|
|
||
|
rfd2 = open(f,O_RDONLY);
|
||
|
ASSERT(rfd != -1);
|
||
|
|
||
|
rc = read(rfd2,buf,512);
|
||
|
ASSERT(rc == 13 && (strcmp(buf,"Hello World\n") == 0 ));
|
||
|
|
||
|
_exit(rc);
|
||
|
}
|
||
|
|
||
|
rfd = open(f,O_RDONLY);
|
||
|
ASSERT(rfd != -1);
|
||
|
|
||
|
rc = waitpid(child2,&stat_loc,0);
|
||
|
ASSERT(rc == child2 && WIFEXITED(stat_loc) && WEXITSTATUS(stat_loc) == 13);
|
||
|
|
||
|
_exit(WEXITSTATUS(stat_loc));
|
||
|
}
|
||
|
|
||
|
sleep(30);
|
||
|
|
||
|
wfd = open(f,O_WRONLY);
|
||
|
ASSERT(wfd != -1);
|
||
|
|
||
|
rc = write(wfd,"Hello World\n",13);
|
||
|
ASSERT(rc == 13);
|
||
|
|
||
|
rc = waitpid(child1,&stat_loc,0);
|
||
|
ASSERT(rc == child1 && WIFEXITED(stat_loc) && WEXITSTATUS(stat_loc) == 13);
|
||
|
|
||
|
rc = close(wfd);
|
||
|
ASSERT(rc != -1);
|
||
|
|
||
|
//
|
||
|
// Open for write with NONBLOCK. Should fail since read handle was
|
||
|
// closed by childs process exit.
|
||
|
//
|
||
|
|
||
|
wfd = open(f,O_WRONLY | O_NONBLOCK);
|
||
|
ASSERT(wfd == -1 && errno == ENXIO);
|
||
|
|
||
|
DbgPrint("npipe2:--\n");
|
||
|
}
|
||
|
|
||
|
void
|
||
|
npipe3_handler(
|
||
|
IN int sig
|
||
|
)
|
||
|
{
|
||
|
int wfd;
|
||
|
|
||
|
ASSERT(sig == SIGUSR1);
|
||
|
wfd = open("named.pip",O_WRONLY | O_NONBLOCK);
|
||
|
ASSERT(wfd == -1 && errno == ENXIO);
|
||
|
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
npipe3(char *f)
|
||
|
{
|
||
|
int rc,wfd,rfd,stat_loc;
|
||
|
pid_t child;
|
||
|
struct sigaction act;
|
||
|
|
||
|
DbgPrint("npipe3:++ %s\n",f);
|
||
|
|
||
|
nulltouch(f);
|
||
|
child = fork();
|
||
|
nulltouch(f);
|
||
|
|
||
|
//
|
||
|
// While child is blocked in open, terminate him with a signal
|
||
|
// and make sure everything is ok.
|
||
|
//
|
||
|
|
||
|
if ( child == 0 ) {
|
||
|
|
||
|
rfd = open(f,O_RDONLY);
|
||
|
ASSERT(FALSE);
|
||
|
}
|
||
|
|
||
|
sleep(20);
|
||
|
|
||
|
rc = kill(child,SIGKILL);
|
||
|
ASSERT(rc==0);
|
||
|
|
||
|
rc = waitpid(child,&stat_loc,0);
|
||
|
ASSERT(rc == child && WIFSIGNALED(stat_loc) && WTERMSIG(stat_loc) == SIGKILL);
|
||
|
|
||
|
wfd = open(f,O_WRONLY | O_NONBLOCK);
|
||
|
ASSERT(wfd == -1 && errno == ENXIO);
|
||
|
|
||
|
//
|
||
|
// Now Try again. This time send a signal that child catches. He should
|
||
|
// come back from his open with EINTR and the pipe should not be left
|
||
|
// open.
|
||
|
//
|
||
|
|
||
|
nulltouch(f);
|
||
|
child = fork();
|
||
|
nulltouch(f);
|
||
|
|
||
|
//
|
||
|
// While child is blocked in open, terminate him with a signal
|
||
|
// and make sure everything is ok.
|
||
|
//
|
||
|
|
||
|
act.sa_flags = 0;
|
||
|
sigfillset(&act.sa_mask);
|
||
|
act.sa_handler = npipe3_handler;
|
||
|
rc = sigaction(SIGUSR1, &act, NULL);
|
||
|
ASSERT( rc == 0 );
|
||
|
|
||
|
if ( child == 0 ) {
|
||
|
|
||
|
rfd = open(f,O_RDONLY);
|
||
|
ASSERT(rfd == -1 && errno == EINTR);
|
||
|
|
||
|
wfd = open(f,O_WRONLY | O_NONBLOCK);
|
||
|
ASSERT(wfd == -1 && errno == ENXIO);
|
||
|
|
||
|
rc = kill(getpid(),SIGKILL);
|
||
|
ASSERT(FALSE);
|
||
|
|
||
|
}
|
||
|
|
||
|
sleep(20);
|
||
|
|
||
|
rc = kill(child,SIGUSR1);
|
||
|
ASSERT(rc==0);
|
||
|
|
||
|
rc = waitpid(child,&stat_loc,0);
|
||
|
ASSERT(rc == child && WIFSIGNALED(stat_loc) && WTERMSIG(stat_loc) == SIGKILL);
|
||
|
|
||
|
wfd = open(f,O_WRONLY | O_NONBLOCK);
|
||
|
ASSERT(wfd == -1 && errno == ENXIO);
|
||
|
|
||
|
DbgPrint("npipe3:--\n");
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
npipe4(char *f)
|
||
|
{
|
||
|
int rc,rfd;
|
||
|
int fildes[2];
|
||
|
off_t off;
|
||
|
|
||
|
DbgPrint("npipe4:++ %s\n",f);
|
||
|
nulltouch(f);
|
||
|
|
||
|
//
|
||
|
// Open for read with NONBLOCK. Open should complete
|
||
|
// without delay.
|
||
|
//
|
||
|
|
||
|
rfd = open(f,O_RDONLY | O_NONBLOCK);
|
||
|
ASSERT(rfd != -1);
|
||
|
|
||
|
//
|
||
|
// lseek on named pipe should fail
|
||
|
//
|
||
|
|
||
|
off = (off_t) 1;
|
||
|
errno = 0;
|
||
|
|
||
|
off = lseek(rfd,off,SEEK_SET);
|
||
|
ASSERT(off == -1 && errno == ESPIPE);
|
||
|
|
||
|
rc = close(rfd);
|
||
|
ASSERT(rc != -1);
|
||
|
|
||
|
rc = pipe(fildes);
|
||
|
ASSERT(rc == 0);
|
||
|
|
||
|
//
|
||
|
// lseek on regular pipe should fail
|
||
|
//
|
||
|
|
||
|
off = (off_t)11;
|
||
|
errno = 0;
|
||
|
|
||
|
off = lseek(fildes[0],off,SEEK_SET);
|
||
|
ASSERT(off == -1 && errno == ESPIPE);
|
||
|
|
||
|
off = 10;
|
||
|
errno = 0;
|
||
|
|
||
|
off = lseek(fildes[1],off,SEEK_SET);
|
||
|
ASSERT(off == -1 && errno == ESPIPE);
|
||
|
|
||
|
DbgPrint("npipe4:--\n");
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
npipe5()
|
||
|
{
|
||
|
int rc,rfd;
|
||
|
off_t off;
|
||
|
|
||
|
DbgPrint("npipe5:++\n");
|
||
|
|
||
|
rc = mkfifo("xpipe.pip",0);
|
||
|
ASSERT(rc==0 || ( rc == -1 && errno == EEXIST ) );
|
||
|
|
||
|
if ( rc == -1 ) {
|
||
|
DbgPrint("npipe5: **** Warning Fifo Exists ****\n");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Open for read with NONBLOCK. Open should complete
|
||
|
// without delay.
|
||
|
//
|
||
|
|
||
|
rfd = open("xpipe.pip",O_RDONLY | O_NONBLOCK);
|
||
|
ASSERT(rfd != -1);
|
||
|
|
||
|
//
|
||
|
// lseek on named pipe should fail
|
||
|
//
|
||
|
|
||
|
off = 1;
|
||
|
errno = 0;
|
||
|
|
||
|
off = lseek(rfd,off,SEEK_SET);
|
||
|
ASSERT(off == -1 && errno == ESPIPE);
|
||
|
|
||
|
rc = close(rfd);
|
||
|
ASSERT(rc != -1);
|
||
|
|
||
|
DbgPrint("npipe5:--\n");
|
||
|
}
|