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 ,
* Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include <errno.h>
# include <stdio.h>
# include <string.h>
# include <unistd.h>
# include "daemon-io.h"
# include "libdevmapper.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 ;
if ( ! strncmp ( ( buffer - > mem ) + buffer - > used - 4 , " \n ## \n " , 4 ) ) {
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 */
} else if ( result < 0 & & errno ! = EAGAIN & & errno ! = EWOULDBLOCK & & errno ! = EINTR )
return 0 ;
2012-09-26 16:44:03 +04:00
/* TODO call select here if we encountered EAGAIN/EWOULDBLOCK/EINTR */
}
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 .
*
* TODO use select on EWOULDBLOCK / EAGAIN / EINTR to avoid useless spinning
*/
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 ;
else if ( result < 0 & & errno ! = EWOULDBLOCK & & errno ! = EAGAIN & & errno ! = EINTR )
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
}