2012-09-26 16:44:03 +04:00
/*
2013-06-18 13:59:22 +04:00
* Copyright ( C ) 2011 - 2013 Red Hat , Inc .
2012-09-26 16:44:03 +04:00
*
* This file is part of LVM2 .
*
* This copyrighted material is made available to anyone wishing to use ,
* modify , copy , or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v .2 .1 .
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program ; if not , write to the Free Software Foundation ,
2016-01-21 13:49:46 +03:00
* Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
2012-09-26 16:44:03 +04:00
*/
2018-05-14 12:30:20 +03:00
# include "tools/tool.h"
2015-07-06 19:30:18 +03:00
2018-12-03 20:14:26 +03:00
# include "daemon-io.h"
2014-04-17 12:40:35 +04:00
2012-09-26 16:44:03 +04:00
# include <errno.h>
/*
* Read a single message from a ( socket ) filedescriptor . Messages are delimited
* by blank lines . This call will block until all of a message is received . The
* memory will be allocated from heap . Upon error , all memory is freed and the
* buffer pointer is set to NULL .
*
* See also write_buffer about blocking ( read_buffer has identical behaviour ) .
*/
2012-10-11 16:17:17 +04:00
int buffer_read ( int fd , struct buffer * buffer ) {
2013-06-18 13:59:22 +04:00
int result ;
2012-10-11 16:17:17 +04:00
if ( ! buffer_realloc ( buffer , 32 ) ) /* ensure we have some space */
2013-06-18 13:59:22 +04:00
return 0 ;
2012-09-26 16:44:03 +04:00
while ( 1 ) {
2013-06-18 13:59:22 +04:00
result = read ( fd , buffer - > mem + buffer - > used , buffer - > allocated - buffer - > used ) ;
2012-09-26 16:44:03 +04:00
if ( result > 0 ) {
2012-10-11 16:17:17 +04:00
buffer - > used + = result ;
2013-10-09 01:19:11 +04:00
if ( buffer - > used > = 4 & & ! strncmp ( ( buffer - > mem ) + buffer - > used - 4 , " \n ## \n " , 4 ) ) {
2012-10-11 16:17:17 +04:00
buffer - > used - = 4 ;
2013-06-18 13:59:22 +04:00
buffer - > mem [ buffer - > used ] = 0 ;
2012-09-26 16:44:03 +04:00
break ; /* success, we have the full message now */
}
2013-06-18 13:59:22 +04:00
if ( ( buffer - > allocated - buffer - > used < 32 ) & &
! buffer_realloc ( buffer , 1024 ) )
return 0 ;
} else if ( result = = 0 ) {
2012-09-26 16:44:03 +04:00
errno = ECONNRESET ;
2013-06-18 13:59:22 +04:00
return 0 ; /* we should never encounter EOF here */
2016-02-23 15:16:55 +03:00
} else if ( result < 0 & & ( errno = = EAGAIN | |
errno = = EINTR | | errno = = EIO ) ) {
2014-07-21 03:53:48 +04:00
fd_set in ;
FD_ZERO ( & in ) ;
FD_SET ( fd , & in ) ;
/* ignore the result, this is just a glorified sleep */
select ( FD_SETSIZE , & in , NULL , NULL , NULL ) ;
} else if ( result < 0 )
2013-06-18 13:59:22 +04:00
return 0 ;
2012-09-26 16:44:03 +04:00
}
2013-06-18 13:59:22 +04:00
2012-09-26 16:44:03 +04:00
return 1 ;
}
/*
* Write a buffer to a filedescriptor . Keep trying . Blocks ( even on
* SOCK_NONBLOCK ) until all of the write went through .
*/
2013-06-18 13:59:22 +04:00
int buffer_write ( int fd , const struct buffer * buffer ) {
static const struct buffer _terminate = { . mem = ( char * ) " \n ## \n " , . used = 4 } ;
const struct buffer * use ;
int done , written , result ;
for ( done = 0 ; done < 2 ; + + done ) {
use = ( done = = 0 ) ? buffer : & _terminate ;
for ( written = 0 ; written < use - > used ; ) {
result = write ( fd , use - > mem + written , use - > used - written ) ;
if ( result > 0 )
written + = result ;
2016-02-23 15:16:55 +03:00
else if ( result < 0 & & ( errno = = EAGAIN | |
errno = = EINTR | | errno = = EIO ) ) {
2014-07-21 03:53:48 +04:00
fd_set out ;
FD_ZERO ( & out ) ;
FD_SET ( fd , & out ) ;
/* ignore the result, this is just a glorified sleep */
select ( FD_SETSIZE , NULL , & out , NULL , NULL ) ;
} else if ( result < 0 )
2013-06-18 13:59:22 +04:00
return 0 ; /* too bad */
2012-09-26 16:44:03 +04:00
}
}
2013-06-18 13:59:22 +04:00
return 1 ;
2012-09-26 16:44:03 +04:00
}