2015-08-19 04:25:39 +03:00
/*
2016-01-04 00:52:58 +03:00
* Copyright ( c ) 2015 - 2016 Dmitry V . Levin < ldv @ altlinux . org >
2015-08-19 04:25:39 +03:00
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
2016-01-02 16:28:43 +03:00
# include "tests.h"
2015-08-19 04:25:39 +03:00
# include <sys/syscall.h>
# ifdef __NR_sendfile
2016-01-04 00:52:58 +03:00
# include <assert.h>
# include <errno.h>
# include <fcntl.h>
# include <stdio.h>
# include <stdint.h>
# include <unistd.h>
# include <sys / socket.h>
# include <sys / stat.h>
2015-08-19 04:25:39 +03:00
int
main ( int ac , const char * * av )
{
assert ( ac = = 2 ) ;
( void ) close ( 0 ) ;
if ( open ( " /dev/zero " , O_RDONLY ) ! = 0 )
2016-01-04 00:52:58 +03:00
perror_msg_and_skip ( " open: %s " , " /dev/zero " ) ;
2015-08-19 04:25:39 +03:00
int sv [ 2 ] ;
if ( socketpair ( AF_UNIX , SOCK_STREAM , 0 , sv ) )
2016-01-04 00:52:58 +03:00
perror_msg_and_skip ( " socketpair " ) ;
2015-08-19 04:25:39 +03:00
int reg_in = open ( av [ 1 ] , O_RDONLY ) ;
if ( reg_in < 0 )
2016-01-04 00:52:58 +03:00
perror_msg_and_fail ( " open: %s " , av [ 1 ] ) ;
2015-08-19 04:25:39 +03:00
struct stat stb ;
2016-01-04 00:52:58 +03:00
assert ( fstat ( reg_in , & stb ) = = 0 ) ;
2015-08-19 04:25:39 +03:00
const size_t blen = stb . st_size / 3 ;
const size_t alen = stb . st_size - blen ;
assert ( S_ISREG ( stb . st_mode ) & & blen > 0 ) ;
2016-01-04 00:52:58 +03:00
const size_t page_len = get_page_size ( ) ;
assert ( syscall ( __NR_sendfile , 0 , 1 , NULL , page_len ) = = - 1 ) ;
if ( EBADF ! = errno )
perror_msg_and_skip ( " sendfile " ) ;
printf ( " sendfile(0, 1, NULL, %lu) = -1 EBADF (%m) \n " ,
2015-08-19 04:25:39 +03:00
( unsigned long ) page_len ) ;
2016-01-04 00:52:58 +03:00
uint32_t * p_off = tail_alloc ( sizeof ( uint32_t ) ) ;
void * p = p_off + 1 ;
* p_off = 0 ;
2015-08-19 04:25:39 +03:00
2016-01-04 00:52:58 +03:00
assert ( syscall ( __NR_sendfile , 0 , 1 , p , page_len ) = = - 1 ) ;
printf ( " sendfile(0, 1, %#lx, %lu) = -1 EFAULT (%m) \n " ,
( unsigned long ) p , ( unsigned long ) page_len ) ;
2015-08-19 04:25:39 +03:00
2016-01-04 00:52:58 +03:00
assert ( syscall ( __NR_sendfile , sv [ 1 ] , reg_in , NULL , alen )
= = ( long ) alen ) ;
2015-08-27 02:25:06 +03:00
printf ( " sendfile(%d, %d, NULL, %lu) = %lu \n " ,
2015-08-19 04:25:39 +03:00
sv [ 1 ] , reg_in , ( unsigned long ) alen ,
( unsigned long ) alen ) ;
2016-01-04 00:52:58 +03:00
p = p_off ;
2015-08-19 04:25:39 +03:00
if ( syscall ( __NR_sendfile , sv [ 1 ] , reg_in , p_off , alen ) ! = ( long ) alen ) {
2016-01-04 00:52:58 +03:00
printf ( " sendfile(%d, %d, %#lx, %lu) = -1 EFAULT (%m) \n " ,
2015-08-19 04:25:39 +03:00
sv [ 1 ] , reg_in , ( unsigned long ) p_off ,
( unsigned long ) alen ) ;
- - p_off ;
2016-01-04 00:52:58 +03:00
* p_off = 0 ;
assert ( syscall ( __NR_sendfile , sv [ 1 ] , reg_in , p_off , alen )
= = ( long ) alen ) ;
2015-08-19 04:25:39 +03:00
}
2015-08-27 02:25:06 +03:00
printf ( " sendfile(%d, %d, [0] => [%lu], %lu) = %lu \n " ,
2015-08-19 04:25:39 +03:00
sv [ 1 ] , reg_in , ( unsigned long ) alen ,
( unsigned long ) alen , ( unsigned long ) alen ) ;
2016-01-04 00:52:58 +03:00
assert ( syscall ( __NR_sendfile , sv [ 1 ] , reg_in , p_off , stb . st_size + 1 )
= = ( long ) blen ) ;
2015-08-27 02:25:06 +03:00
printf ( " sendfile(%d, %d, [%lu] => [%lu], %lu) = %lu \n " ,
2015-08-19 04:25:39 +03:00
sv [ 1 ] , reg_in , ( unsigned long ) alen ,
( unsigned long ) stb . st_size ,
( unsigned long ) stb . st_size + 1 ,
( unsigned long ) blen ) ;
2016-01-04 00:52:58 +03:00
if ( p_off ! = p ) {
2015-08-19 04:25:39 +03:00
uint64_t * p_off64 = ( uint64_t * ) p_off ;
* p_off64 = 0xcafef00dfacefeed ;
2016-01-04 00:52:58 +03:00
assert ( syscall ( __NR_sendfile , sv [ 1 ] , reg_in , p_off64 , 1 ) = = - 1 ) ;
printf ( " sendfile(%d, %d, [14627392582579060461], 1) "
" = -1 EINVAL (%m) \n " , sv [ 1 ] , reg_in ) ;
2015-08-19 04:25:39 +03:00
* p_off64 = 0xdefaced ;
} else {
* p_off = 0xdefaced ;
}
2016-01-04 00:52:58 +03:00
assert ( syscall ( __NR_sendfile , sv [ 1 ] , reg_in , p_off , 1 ) = = 0 ) ;
2015-08-27 02:25:06 +03:00
printf ( " sendfile(%d, %d, [233811181], 1) = 0 \n " ,
2015-08-19 04:25:39 +03:00
sv [ 1 ] , reg_in ) ;
2015-08-27 02:25:06 +03:00
puts ( " +++ exited with 0 +++ " ) ;
2015-08-19 04:25:39 +03:00
return 0 ;
}
# else
2016-01-04 00:52:58 +03:00
SKIP_MAIN_UNDEFINED ( " __NR_sendfile " )
2015-08-19 04:25:39 +03:00
# endif