mirror of
https://github.com/microsoft/WSL.git
synced 2025-07-03 23:33:21 +00:00
657 lines
18 KiB
C
657 lines
18 KiB
C
![]() |
/*++
|
||
|
|
||
|
Copyright (c) Microsoft. All rights reserved.
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
splice.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This file contains tests for the splice syscall.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "lxtcommon.h"
|
||
|
#include "unittests.h"
|
||
|
#include <unistd.h>
|
||
|
#include <sys/syscall.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <sys/wait.h>
|
||
|
#include <fcntl.h>
|
||
|
|
||
|
#define LXT_NAME "Splice"
|
||
|
|
||
|
#define SPLICE_SYSCALL(_Fdin, _Offin, _Fdout, _Offout, _Size, _Flags) \
|
||
|
syscall(SYS_splice, _Fdin, _Offin, _Fdout, _Offout, _Size, _Flags)
|
||
|
|
||
|
#define TEE_SYSCALL(_Fdin, _Fdout, _Size, _Flags) syscall(SYS_tee, _Fdin, _Fdout, _Size, _Flags)
|
||
|
|
||
|
#ifndef SPLICE_F_NONBLOCK
|
||
|
#define SPLICE_F_NONBLOCK 0x02
|
||
|
#endif
|
||
|
|
||
|
#define SPLICE_READ_PIPE_INDEX 0
|
||
|
#define SPLICE_WRITE_PIPE_INDEX 1
|
||
|
|
||
|
//
|
||
|
// The following defines a standardized file path and content for a file that
|
||
|
// can be used for splicing.
|
||
|
//
|
||
|
|
||
|
#define SPLICE_STD_FILE "/data/test/splice_test_std_file_1.txt"
|
||
|
#define SPLICE_STD_FILE_CONTENT "123456789Test"
|
||
|
#define SPLICE_STD_FILE_SIZE (unsigned long)(strlen(SPLICE_STD_FILE_CONTENT))
|
||
|
|
||
|
int SpliceOpenStandardFile(void);
|
||
|
|
||
|
int SpliceVariationBasicTests(PLXT_ARGS Args);
|
||
|
|
||
|
int SpliceVariationBlocking(PLXT_ARGS Args);
|
||
|
|
||
|
int SpliceVariationInvalidParameters(PLXT_ARGS Args);
|
||
|
|
||
|
int TeeVariationBasicTests(PLXT_ARGS Args);
|
||
|
|
||
|
int TeeVariationInvalidParameters(PLXT_ARGS Args);
|
||
|
|
||
|
//
|
||
|
// Globals.
|
||
|
//
|
||
|
|
||
|
static const LXT_VARIATION g_LxtVariations[] = {
|
||
|
{"Splice - Invalid Parameter Test ", SpliceVariationInvalidParameters},
|
||
|
{"Splice - Blocking Tests", SpliceVariationBlocking},
|
||
|
{"Splice - Basic Usage Tests", SpliceVariationBasicTests},
|
||
|
{"Tee - Invalid Parameter Test ", TeeVariationInvalidParameters},
|
||
|
{"Tee - Basic Usage Test", TeeVariationBasicTests}};
|
||
|
|
||
|
int SpliceTestEntry(int Argc, char* Argv[])
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine is the main entry point for the procfs tests.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Argc - Supplies the number of command line arguments.
|
||
|
|
||
|
Argv - Supplies the command line arguments.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Returns 0 on success, -1 on failure.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
|
||
|
LXT_ARGS Args;
|
||
|
int Result;
|
||
|
|
||
|
LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
|
||
|
LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
|
||
|
|
||
|
ErrorExit:
|
||
|
LxtUninitialize();
|
||
|
return !LXT_SUCCESS(Result);
|
||
|
}
|
||
|
|
||
|
int SpliceOpenStandardFile(void)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine returns the file descriptor for the standard file which
|
||
|
include uniform data for splicing.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
On success, returns open file descriptor; otherwise, -1.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
|
||
|
int Fd;
|
||
|
off_t Offset;
|
||
|
int Result;
|
||
|
|
||
|
LxtCheckErrno(Fd = open(SPLICE_STD_FILE, (O_CREAT | O_RDWR), (S_IRUSR | S_IWUSR)));
|
||
|
|
||
|
LxtCheckErrno(write(Fd, SPLICE_STD_FILE_CONTENT, SPLICE_STD_FILE_SIZE));
|
||
|
|
||
|
//
|
||
|
// Set the offset back to zero.
|
||
|
//
|
||
|
|
||
|
LxtCheckErrno(Offset = lseek(Fd, 0, SEEK_SET));
|
||
|
|
||
|
//
|
||
|
// Set the result.
|
||
|
//
|
||
|
|
||
|
Result = Fd;
|
||
|
Fd = 0;
|
||
|
|
||
|
ErrorExit:
|
||
|
if (Fd > 0)
|
||
|
{
|
||
|
close(Fd);
|
||
|
unlink(SPLICE_STD_FILE);
|
||
|
}
|
||
|
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
int SpliceVariationBasicTests(PLXT_ARGS Args)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine runs basic usage tests for splice, including splicing between
|
||
|
two pipes and a pipe and a regular file, and tests the results for
|
||
|
accurate splice sizes, content, and file offsets.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Args - Supplies a pointer to variation arguments.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
On success, returns open file descriptor; otherwise, -1.
|
||
|
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
|
||
|
char Buffer[4];
|
||
|
LXT_PIPE DestinationPipe = {-1, -1};
|
||
|
loff_t InitialOffset;
|
||
|
loff_t Offset;
|
||
|
char* PipeData;
|
||
|
ssize_t PipeDataSize;
|
||
|
int RegularFd;
|
||
|
int Result;
|
||
|
ssize_t SpliceSize;
|
||
|
LXT_PIPE SourcePipe = {-1, -1};
|
||
|
|
||
|
RegularFd = -1;
|
||
|
PipeData = "1234";
|
||
|
PipeDataSize = strlen(PipeData);
|
||
|
LxtCheckResult(LxtCreatePipe(&DestinationPipe));
|
||
|
LxtCheckResult(LxtCreatePipe(&SourcePipe));
|
||
|
LxtCheckResult(RegularFd = SpliceOpenStandardFile());
|
||
|
|
||
|
//
|
||
|
// Set up read-end of pipes as non-blocking for empty tests.
|
||
|
//
|
||
|
|
||
|
LxtCheckErrno(fcntl(SourcePipe.Read, F_SETFL, O_NONBLOCK));
|
||
|
LxtCheckErrno(fcntl(DestinationPipe.Read, F_SETFL, O_NONBLOCK));
|
||
|
|
||
|
//
|
||
|
// Perform basic tests between pipes.
|
||
|
//
|
||
|
|
||
|
LxtLogInfo("Basic Usage - Splicing between two pipes");
|
||
|
LxtCheckErrno(write(SourcePipe.Write, PipeData, PipeDataSize));
|
||
|
LxtCheckErrno(SpliceSize = SPLICE_SYSCALL(SourcePipe.Read, NULL, DestinationPipe.Write, NULL, PipeDataSize, SPLICE_F_NONBLOCK));
|
||
|
|
||
|
LxtCheckEqual(SpliceSize, PipeDataSize, "%d");
|
||
|
|
||
|
//
|
||
|
// Check that the read pipe is now empty by attempting to read a single
|
||
|
// byte.
|
||
|
//
|
||
|
|
||
|
LxtCheckErrnoFailure(read(SourcePipe.Read, Buffer, 1), EAGAIN);
|
||
|
LxtCheckErrno(SpliceSize = read(DestinationPipe.Read, Buffer, PipeDataSize));
|
||
|
|
||
|
LxtCheckEqual(SpliceSize, PipeDataSize, "%d");
|
||
|
|
||
|
//
|
||
|
// LX_TODO: Enable the following additional basic tests once splicing is
|
||
|
// available for VolFs file types.
|
||
|
//
|
||
|
|
||
|
/*
|
||
|
//
|
||
|
// Perform test from a regular file to a pipe.
|
||
|
//
|
||
|
|
||
|
InitialOffset = 4;
|
||
|
Offset = InitialOffset;
|
||
|
LxtLogInfo("Basic Usage - Splicing from a regular file to a pipe");
|
||
|
LxtCheckErrno(SpliceSize = SPLICE_SYSCALL(RegularFd,
|
||
|
&Offset,
|
||
|
DestinationPipe.Write,
|
||
|
NULL,
|
||
|
4,
|
||
|
SPLICE_F_NONBLOCK));
|
||
|
|
||
|
LxtCheckEqual(SpliceSize, 4, "%d");
|
||
|
LxtCheckErrno(SpliceSize = read(DestinationPipe.Read, Buffer, 4));
|
||
|
LxtCheckEqual(SpliceSize, 4, "%d");
|
||
|
LxtCheckEqual(Offset - InitialOffset, 4, "%d");
|
||
|
LxtCheckEqual(Buffer[0],
|
||
|
SPLICE_STD_FILE_CONTENT[InitialOffset],
|
||
|
"%c");
|
||
|
|
||
|
//
|
||
|
// Ensure that offset remains unchanged on the file.
|
||
|
//
|
||
|
|
||
|
LxtCheckErrno(SpliceSize = read(RegularFd, Buffer, 4));
|
||
|
LxtCheckEqual(SpliceSize, 4, "%d");
|
||
|
LxtCheckEqual(Buffer[0],
|
||
|
SPLICE_STD_FILE_CONTENT[0],
|
||
|
"%c");
|
||
|
|
||
|
//
|
||
|
// Reset the file's offset for the next test.
|
||
|
//
|
||
|
|
||
|
LxtCheckErrno(lseek(RegularFd, 0, SEEK_SET));
|
||
|
|
||
|
//
|
||
|
// Perform test from a pipe to a regular file.
|
||
|
//
|
||
|
|
||
|
InitialOffset = 1;
|
||
|
Offset = InitialOffset;
|
||
|
LxtLogInfo("Basic Usage - Splicing from a pipe to a regular file");
|
||
|
LxtCheckErrno(write(SourcePipe.Write, PipeData, PipeDataSize));
|
||
|
LxtCheckErrno(SpliceSize = SPLICE_SYSCALL(SourcePipe.Read,
|
||
|
NULL,
|
||
|
RegularFd,
|
||
|
&Offset,
|
||
|
PipeDataSize,
|
||
|
SPLICE_F_NONBLOCK));
|
||
|
|
||
|
LxtCheckEqual(SpliceSize, PipeDataSize, "%d");
|
||
|
LxtCheckEqual(Offset - InitialOffset, PipeDataSize, "%d");
|
||
|
|
||
|
//
|
||
|
// Ensure that the regular file's internal offset is unchanged and that the
|
||
|
// the pipe data was properly splice into the file with the offset.
|
||
|
//
|
||
|
|
||
|
LxtCheckErrno(SpliceSize = read(RegularFd, Buffer, 2));
|
||
|
LxtCheckEqual(SpliceSize, 2, "%d");
|
||
|
LxtCheckEqual(Buffer[0],
|
||
|
SPLICE_STD_FILE_CONTENT[0],
|
||
|
"%c");
|
||
|
|
||
|
LxtCheckEqual(Buffer[1], PipeData[0], "%c");
|
||
|
*/
|
||
|
|
||
|
ErrorExit:
|
||
|
LxtClosePipe(&DestinationPipe);
|
||
|
LxtClosePipe(&SourcePipe);
|
||
|
if (RegularFd > 0)
|
||
|
{
|
||
|
close(RegularFd);
|
||
|
}
|
||
|
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
int SpliceVariationBlocking(PLXT_ARGS Args)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine tests the splice syscall with the splice-specific non-blocking
|
||
|
flag with pipes that have opposite internal blocking settings and checks for
|
||
|
proper behavior.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Args - Supplies a pointer to variation arguments.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
On success, returns open file descriptor; otherwise, -1.
|
||
|
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
|
||
|
pid_t ChildPid;
|
||
|
LXT_PIPE DestinationPipe = {-1, -1};
|
||
|
int Result;
|
||
|
LXT_PIPE SourcePipe = {-1, -1};
|
||
|
int WaitPidResult;
|
||
|
int WaitPidStatus;
|
||
|
|
||
|
LxtCheckResult(LxtCreatePipe(&DestinationPipe));
|
||
|
LxtCheckResult(LxtCreatePipe(&SourcePipe));
|
||
|
|
||
|
//
|
||
|
// Verify that a pipe which is automatically set to have blocking I/O
|
||
|
// semantics, does not block when the splice call is supplied with the
|
||
|
// splice-specific non-blocking flag.
|
||
|
//
|
||
|
|
||
|
LxtLogInfo("Blocking - Non-blocking splice with blocking pipes");
|
||
|
LxtCheckResult(ChildPid = fork());
|
||
|
if (ChildPid == 0)
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// By default, the created pipes are blocking. The splice non-blocking
|
||
|
// flag should override this behavior.
|
||
|
//
|
||
|
|
||
|
Result = SPLICE_SYSCALL(SourcePipe.Read, NULL, DestinationPipe.Write, NULL, 1, SPLICE_F_NONBLOCK);
|
||
|
|
||
|
if (Result >= 0)
|
||
|
{
|
||
|
LxtLogError("Non-blocking splice syscall succeeded");
|
||
|
_exit(1);
|
||
|
}
|
||
|
|
||
|
if (errno != EAGAIN)
|
||
|
{
|
||
|
LxtLogError("Non-blocking splice syscall returned with error %s", strerror(errno));
|
||
|
|
||
|
_exit(1);
|
||
|
}
|
||
|
|
||
|
_exit(0);
|
||
|
}
|
||
|
|
||
|
LxtCheckResult(WaitPidStatus = LxtWaitPidPollOptions(ChildPid, 0, 0, 2));
|
||
|
|
||
|
//
|
||
|
// Verify that a pipe that is set to non-blocking will block when the
|
||
|
// splice-specific non-blocking flag is not passed to splice.
|
||
|
//
|
||
|
|
||
|
LxtLogInfo("Blocking - Blocking splice with non-blocking pipe");
|
||
|
LxtCheckErrno(fcntl(SourcePipe.Read, F_SETFL, O_NONBLOCK));
|
||
|
LxtCheckResult(ChildPid = fork());
|
||
|
if (ChildPid == 0)
|
||
|
{
|
||
|
Result = SPLICE_SYSCALL(SourcePipe.Read, NULL, DestinationPipe.Write, NULL, 1, 0);
|
||
|
|
||
|
_exit(0);
|
||
|
}
|
||
|
|
||
|
sleep(2);
|
||
|
LxtCheckErrno(WaitPidResult = waitpid(ChildPid, &WaitPidStatus, WNOHANG));
|
||
|
|
||
|
//
|
||
|
// If the child is not alive, it did not block as expected.
|
||
|
//
|
||
|
|
||
|
LxtCheckEqual(WaitPidResult, 0, "%d");
|
||
|
kill(ChildPid, SIGKILL);
|
||
|
Result = 0;
|
||
|
ErrorExit:
|
||
|
LxtClosePipe(&DestinationPipe);
|
||
|
LxtClosePipe(&SourcePipe);
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
int SpliceVariationInvalidParameters(PLXT_ARGS Args)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine tests the splice syscall errors are properly set when invalid
|
||
|
parameters are passed to it.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Args - Supplies a pointer to variation arguments.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
On success, returns open file descriptor; otherwise, -1.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
|
||
|
LXT_PIPE DestinationPipe = {-1, -1};
|
||
|
loff_t ReadOffset;
|
||
|
int Result;
|
||
|
LXT_PIPE SourcePipe = {-1, -1};
|
||
|
int StandardFd;
|
||
|
|
||
|
StandardFd = 0;
|
||
|
LxtCheckErrno(LxtCreatePipe(&SourcePipe));
|
||
|
LxtCheckErrno(LxtCreatePipe(&DestinationPipe));
|
||
|
LxtCheckResult(StandardFd = SpliceOpenStandardFile());
|
||
|
|
||
|
//
|
||
|
// Put some random data into the source pipe and set the offset.
|
||
|
//
|
||
|
|
||
|
LxtCheckErrno(write(SourcePipe.Write, "1234", 4));
|
||
|
ReadOffset = 2;
|
||
|
|
||
|
//
|
||
|
// Check that a call with invalid parameters, but a splice size of zero will
|
||
|
// succeed.
|
||
|
//
|
||
|
|
||
|
LxtLogInfo("Invalid Params - Passing invalid parameters with splice size of zero");
|
||
|
|
||
|
LxtCheckErrno(SPLICE_SYSCALL(SourcePipe.Read, &ReadOffset, DestinationPipe.Write, NULL, 0, 0));
|
||
|
|
||
|
LxtCheckErrno(SPLICE_SYSCALL(StandardFd, NULL, StandardFd, NULL, 0, 0));
|
||
|
LxtCheckErrno(SPLICE_SYSCALL(-1, NULL, -1, NULL, 0, 0));
|
||
|
|
||
|
//
|
||
|
// Check that invalid flags do not cause any errors.
|
||
|
//
|
||
|
|
||
|
LxtCheckErrno(SPLICE_SYSCALL(SourcePipe.Read, NULL, DestinationPipe.Write, NULL, 4, 0xF0));
|
||
|
|
||
|
//
|
||
|
// Check the error result when a pipe is given a non-null offset.
|
||
|
//
|
||
|
|
||
|
LxtLogInfo("Invalid Params - Passing non-null offset with pipe fd");
|
||
|
LxtCheckErrnoFailure(SPLICE_SYSCALL(SourcePipe.Read, &ReadOffset, DestinationPipe.Write, NULL, 1, 0), ESPIPE);
|
||
|
|
||
|
LxtCheckErrnoFailure(SPLICE_SYSCALL(SourcePipe.Read, NULL, DestinationPipe.Write, &ReadOffset, 1, 0), ESPIPE);
|
||
|
|
||
|
//
|
||
|
// Ensure that the correct error is returned when splice takes two
|
||
|
// parameters that are not pipes.
|
||
|
//
|
||
|
|
||
|
LxtLogInfo("Invalid Params - Passing two non-pipe fd's to splice");
|
||
|
LxtCheckErrnoFailure(SPLICE_SYSCALL(StandardFd, NULL, StandardFd, NULL, 1, 0), EINVAL);
|
||
|
|
||
|
//
|
||
|
// Validate errors returned wrong read\write pipe
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// LX_TODO: Here and in the tee syscall variation, the atomic property of
|
||
|
// tee/splice must be implemented before these tests are enabled.
|
||
|
//
|
||
|
|
||
|
/*
|
||
|
LxtLogInfo("Invalid Params - Invalid splice read\write pipe 1");
|
||
|
LxtCheckErrnoFailure(SPLICE_SYSCALL(SourcePipe.Read,
|
||
|
NULL,
|
||
|
SourcePipe.Read,
|
||
|
NULL,
|
||
|
200,
|
||
|
0),
|
||
|
EBADF);
|
||
|
|
||
|
LxtLogInfo("Invalid Params - Invalid splice read\write pipe 2");
|
||
|
LxtCheckErrnoFailure(SPLICE_SYSCALL(SourcePipe.Write,
|
||
|
NULL,
|
||
|
SourcePipe.Read,
|
||
|
NULL,
|
||
|
200,
|
||
|
0),
|
||
|
EBADF);
|
||
|
|
||
|
LxtLogInfo("Invalid Params - Invalid splice read\write pipe 3");
|
||
|
LxtCheckErrnoFailure(SPLICE_SYSCALL(SourcePipe.Read,
|
||
|
NULL,
|
||
|
DestinationPipe.Read,
|
||
|
NULL,
|
||
|
200,
|
||
|
0),
|
||
|
EBADF);
|
||
|
*/
|
||
|
|
||
|
ErrorExit:
|
||
|
LxtClosePipe(&SourcePipe);
|
||
|
LxtClosePipe(&DestinationPipe);
|
||
|
if (StandardFd > 0)
|
||
|
{
|
||
|
close(StandardFd);
|
||
|
}
|
||
|
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
int TeeVariationBasicTests(PLXT_ARGS Args)
|
||
|
|
||
|
/*++
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
|
||
|
char Buffer[16];
|
||
|
LXT_PIPE DestinationPipe = {-1, -1};
|
||
|
char* PipeData;
|
||
|
ssize_t PipeDataSize;
|
||
|
ssize_t ReadSize;
|
||
|
int Result;
|
||
|
ssize_t SpliceSize;
|
||
|
LXT_PIPE SourcePipe = {-1, -1};
|
||
|
|
||
|
PipeData = "1234";
|
||
|
PipeDataSize = strlen(PipeData);
|
||
|
LxtCheckResult(LxtCreatePipe(&DestinationPipe));
|
||
|
LxtCheckResult(LxtCreatePipe(&SourcePipe));
|
||
|
|
||
|
//
|
||
|
// Set up read-end of pipes as non-blocking for empty tests.
|
||
|
//
|
||
|
|
||
|
LxtCheckErrno(fcntl(SourcePipe.Read, F_SETFL, O_NONBLOCK));
|
||
|
LxtCheckErrno(fcntl(DestinationPipe.Read, F_SETFL, O_NONBLOCK));
|
||
|
|
||
|
//
|
||
|
// Perform basic tests between pipes.
|
||
|
//
|
||
|
|
||
|
LxtLogInfo("Basic Usage - Tee");
|
||
|
LxtCheckErrno(write(SourcePipe.Write, PipeData, PipeDataSize));
|
||
|
LxtCheckErrno(SpliceSize = TEE_SYSCALL(SourcePipe.Read, DestinationPipe.Write, PipeDataSize, SPLICE_F_NONBLOCK));
|
||
|
|
||
|
LxtCheckEqual(SpliceSize, PipeDataSize, "%d");
|
||
|
|
||
|
//
|
||
|
// Check that the read pipe still has the same data as before.
|
||
|
//
|
||
|
|
||
|
LxtCheckErrno(ReadSize = read(SourcePipe.Read, Buffer, PipeDataSize));
|
||
|
LxtCheckEqual(ReadSize, PipeDataSize, "%d");
|
||
|
Buffer[ReadSize] = '\0';
|
||
|
LxtCheckStringEqual(Buffer, PipeData);
|
||
|
|
||
|
//
|
||
|
// Check that the destination pipe has the correct data after the tee.
|
||
|
//
|
||
|
|
||
|
LxtCheckErrno(ReadSize = read(DestinationPipe.Read, Buffer, PipeDataSize));
|
||
|
LxtCheckEqual(ReadSize, PipeDataSize, "%d");
|
||
|
Buffer[ReadSize] = '\0';
|
||
|
LxtCheckStringEqual(Buffer, PipeData);
|
||
|
|
||
|
ErrorExit:
|
||
|
LxtClosePipe(&SourcePipe);
|
||
|
LxtClosePipe(&DestinationPipe);
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
int TeeVariationInvalidParameters(PLXT_ARGS Args)
|
||
|
|
||
|
/*++
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
|
||
|
LXT_PIPE DestinationPipe = {-1, -1};
|
||
|
int Result;
|
||
|
LXT_PIPE SourcePipe = {-1, -1};
|
||
|
int StandardFd;
|
||
|
|
||
|
StandardFd = 0;
|
||
|
LxtCheckErrno(LxtCreatePipe(&SourcePipe));
|
||
|
LxtCheckErrno(LxtCreatePipe(&DestinationPipe));
|
||
|
LxtCheckResult(StandardFd = SpliceOpenStandardFile());
|
||
|
|
||
|
//
|
||
|
// Put some random data into the source pipe and set the offset.
|
||
|
//
|
||
|
|
||
|
LxtCheckErrno(write(SourcePipe.Write, "1234", 4));
|
||
|
|
||
|
//
|
||
|
// Check that a call with invalid parameters, but a size of zero will
|
||
|
// succeed.
|
||
|
//
|
||
|
|
||
|
LxtLogInfo("Invalid Params - Passing invalid parameters to tee with size of zero");
|
||
|
|
||
|
LxtCheckErrno(TEE_SYSCALL(StandardFd, DestinationPipe.Write, 0, 0));
|
||
|
LxtCheckErrno(TEE_SYSCALL(SourcePipe.Read, StandardFd, 0, 0));
|
||
|
LxtCheckErrno(TEE_SYSCALL(StandardFd, StandardFd, 0, 0));
|
||
|
|
||
|
//
|
||
|
// Check that invalid flags do not cause any errors.
|
||
|
//
|
||
|
|
||
|
LxtCheckErrno(TEE_SYSCALL(SourcePipe.Read, DestinationPipe.Write, 4, 0xF0));
|
||
|
//
|
||
|
// Validate the errors returned with invalid parameters and non-zero splice
|
||
|
// sizes.
|
||
|
//
|
||
|
|
||
|
LxtLogInfo("Invalid Params - Passing a non-pipe to a tee syscall");
|
||
|
LxtCheckErrnoFailure(TEE_SYSCALL(StandardFd, DestinationPipe.Write, 1, 0), EINVAL);
|
||
|
|
||
|
LxtCheckErrnoFailure(TEE_SYSCALL(SourcePipe.Read, StandardFd, 1, 0), EINVAL);
|
||
|
|
||
|
//
|
||
|
// Validate errors returned sending to the wrong read\write pipe
|
||
|
//
|
||
|
|
||
|
ErrorExit:
|
||
|
LxtClosePipe(&SourcePipe);
|
||
|
LxtClosePipe(&DestinationPipe);
|
||
|
if (StandardFd > 0)
|
||
|
{
|
||
|
close(StandardFd);
|
||
|
}
|
||
|
|
||
|
return Result;
|
||
|
}
|