2012-09-26 16:44:03 +04:00
/*
* Copyright ( C ) 2011 - 2012 Red Hat , Inc .
*
* 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 ) {
if ( ! buffer_realloc ( buffer , 32 ) ) /* ensure we have some space */
goto fail ;
2012-09-26 16:44:03 +04:00
while ( 1 ) {
2012-10-11 16:17:17 +04:00
int 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 - > mem + buffer - > used - 4 ) = 0 ;
buffer - > used - = 4 ;
2012-09-26 16:44:03 +04:00
break ; /* success, we have the full message now */
}
2012-10-11 16:17:17 +04:00
if ( buffer - > used - buffer - > allocated < 32 )
if ( ! buffer_realloc ( buffer , 1024 ) )
2012-09-26 16:44:03 +04:00
goto fail ;
continue ;
}
if ( result = = 0 ) {
errno = ECONNRESET ;
goto fail ; /* we should never encounter EOF here */
}
if ( result < 0 & & errno ! = EAGAIN & & errno ! = EWOULDBLOCK & & errno ! = EINTR )
goto fail ;
/* TODO call select here if we encountered EAGAIN/EWOULDBLOCK/EINTR */
}
return 1 ;
fail :
return 0 ;
}
/*
* 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
*/
2012-10-11 16:17:17 +04:00
int buffer_write ( int fd , struct buffer * buffer ) {
struct buffer terminate = { . mem = ( char * ) " \n ## \n " , . used = 4 } ;
2012-09-26 16:44:03 +04:00
int done = 0 ;
int written = 0 ;
2012-10-11 16:17:17 +04:00
struct buffer * use = buffer ;
2012-09-26 16:44:03 +04:00
write :
while ( 1 ) {
2012-10-11 16:17:17 +04:00
int result = write ( fd , use - > mem + written , use - > used - written ) ;
2012-09-26 16:44:03 +04:00
if ( result > 0 )
written + = result ;
if ( result < 0 & & errno ! = EWOULDBLOCK & & errno ! = EAGAIN & & errno ! = EINTR )
return 0 ; /* too bad */
2012-10-11 16:17:17 +04:00
if ( written = = use - > used ) {
2012-09-26 16:44:03 +04:00
if ( done )
return 1 ;
else
break ; /* done */
}
}
2012-10-11 16:17:17 +04:00
use = & terminate ;
2012-09-26 16:44:03 +04:00
written = 0 ;
done = 1 ;
goto write ;
}