| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # REMOTE MODULE | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							| 
									
										
										
										
											2014-06-07 16:25:20 -04:00
										 |  |  | package BackRest::Remote; | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | use threads; | 
					
						
							|  |  |  | use strict; | 
					
						
							|  |  |  | use warnings; | 
					
						
							|  |  |  | use Carp; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-08 13:54:31 -04:00
										 |  |  | use Scalar::Util; | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  | use Net::OpenSSH; | 
					
						
							|  |  |  | use File::Basename; | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  | use POSIX ':sys_wait_h'; | 
					
						
							| 
									
										
										
										
											2014-10-08 13:54:31 -04:00
										 |  |  | use Scalar::Util 'blessed'; | 
					
						
							| 
									
										
										
										
											2015-02-26 19:12:22 -05:00
										 |  |  | use IO::Compress::Gzip qw($GzipError); | 
					
						
							|  |  |  | use IO::Uncompress::Gunzip qw($GunzipError); | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  | use Compress::Raw::Zlib; | 
					
						
							| 
									
										
										
										
											2014-06-15 16:53:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  | use lib dirname($0) . '/../lib'; | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  | use BackRest::Exception; | 
					
						
							| 
									
										
										
										
											2014-06-07 16:13:41 -04:00
										 |  |  | use BackRest::Utility; | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-23 18:52:38 -05:00
										 |  |  | use Exporter qw(import); | 
					
						
							|  |  |  | our @EXPORT = qw(DB BACKUP NONE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # DB/BACKUP Constants | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | use constant | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     DB              => 'db', | 
					
						
							|  |  |  |     BACKUP          => 'backup', | 
					
						
							|  |  |  |     NONE            => 'none' | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # Remote xfer default block size constant | 
					
						
							| 
									
										
										
										
											2015-02-27 23:31:39 -05:00
										 |  |  | #################################################################################################################################### | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  | use constant | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-02-28 15:54:49 -05:00
										 |  |  |     DEFAULT_BLOCK_SIZE  => 8192 | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # CONSTRUCTOR | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							| 
									
										
										
										
											2014-10-08 13:54:31 -04:00
										 |  |  | sub new | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-10-08 13:54:31 -04:00
										 |  |  |     my $class = shift;       # Class name | 
					
						
							|  |  |  |     my $strHost = shift;     # Host to connect to for remote (optional as this can also be used on the remote) | 
					
						
							|  |  |  |     my $strUser = shift;     # User to connect to for remote (must be set if strHost is set) | 
					
						
							|  |  |  |     my $strCommand = shift;  # Command to execute on remote | 
					
						
							|  |  |  |     my $iBlockSize = shift;  # Optionally, set the block size (defaults to DEFAULT_BLOCK_SIZE) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Create the class hash | 
					
						
							|  |  |  |     my $self = {}; | 
					
						
							|  |  |  |     bless $self, $class; | 
					
						
							| 
									
										
										
										
											2014-06-15 15:56:45 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-08 13:54:31 -04:00
										 |  |  |     # Create the greeting that will be used to check versions with the remote | 
					
						
							|  |  |  |     $self->{strGreeting} = 'PG_BACKREST_REMOTE ' . version_get(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Set default block size | 
					
						
							|  |  |  |     if (!defined($iBlockSize)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $self->{iBlockSize} = DEFAULT_BLOCK_SIZE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $self->{iBlockSize} = $iBlockSize; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-08 13:54:31 -04:00
										 |  |  |     # If host is defined then make a connnection | 
					
						
							|  |  |  |     if (defined($strHost)) | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  |     { | 
					
						
							|  |  |  |         # User must be defined | 
					
						
							| 
									
										
										
										
											2014-10-08 13:54:31 -04:00
										 |  |  |         if (!defined($strUser)) | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |             confess &log(ASSERT, 'strUser must be defined'); | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-08 13:54:31 -04:00
										 |  |  |         # Command must be defined | 
					
						
							|  |  |  |         if (!defined($strCommand)) | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |             confess &log(ASSERT, 'strCommand must be defined'); | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-08 13:54:31 -04:00
										 |  |  |         $self->{strHost} = $strHost; | 
					
						
							|  |  |  |         $self->{strUser} = $strUser; | 
					
						
							|  |  |  |         $self->{strCommand} = $strCommand; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  |         # Set SSH Options | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |         my $strOptionSSHRequestTTY = 'RequestTTY=yes'; | 
					
						
							|  |  |  |         my $strOptionSSHCompression = 'Compression=no'; | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |         &log(TRACE, 'connecting to remote ssh host ' . $self->{strHost}); | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Make SSH connection | 
					
						
							| 
									
										
										
										
											2014-10-08 13:54:31 -04:00
										 |  |  |         $self->{oSSH} = Net::OpenSSH->new($self->{strHost}, timeout => 600, user => $self->{strUser}, | 
					
						
							|  |  |  |                                           master_opts => [-o => $strOptionSSHCompression, -o => $strOptionSSHRequestTTY]); | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $self->{oSSH}->error and confess &log(ERROR, "unable to connect to $self->{strHost}: " . $self->{oSSH}->error); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Execute remote command | 
					
						
							|  |  |  |         ($self->{hIn}, $self->{hOut}, $self->{hErr}, $self->{pId}) = $self->{oSSH}->open3($self->{strCommand}); | 
					
						
							| 
									
										
										
										
											2014-06-07 15:30:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-07 15:01:29 -04:00
										 |  |  |         $self->greeting_read(); | 
					
						
							| 
									
										
										
										
											2014-06-29 17:23:34 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-08 13:54:31 -04:00
										 |  |  |     return $self; | 
					
						
							| 
									
										
										
										
											2014-06-29 17:23:34 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							| 
									
										
										
										
											2014-10-09 16:01:06 -04:00
										 |  |  | # THREAD_KILL | 
					
						
							| 
									
										
										
										
											2014-06-29 17:23:34 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							| 
									
										
										
										
											2015-01-30 18:58:49 -05:00
										 |  |  | sub thread_kill | 
					
						
							| 
									
										
										
										
											2014-06-29 17:23:34 -04:00
										 |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							| 
									
										
										
										
											2015-01-30 18:58:49 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # DESTRUCTOR | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub DEMOLISH | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							| 
									
										
										
										
											2014-06-29 17:23:34 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-30 18:58:49 -05:00
										 |  |  |     $self->thread_kill(); | 
					
						
							| 
									
										
										
										
											2014-06-29 17:23:34 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # CLONE | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub clone | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-21 20:08:49 -04:00
										 |  |  |     return BackRest::Remote->new | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  |     ( | 
					
						
							| 
									
										
										
										
											2014-10-08 13:54:31 -04:00
										 |  |  |         $self->{strHost}, | 
					
						
							|  |  |  |         $self->{strUser}, | 
					
						
							|  |  |  |         $self->{strCommand}, | 
					
						
							|  |  |  |         $self->{iBlockSize} | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  |     ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # GREETING_READ | 
					
						
							| 
									
										
										
										
											2014-06-15 16:53:20 -04:00
										 |  |  | # | 
					
						
							|  |  |  | # Read the greeting and make sure it is as expected. | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub greeting_read | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Make sure that the remote is running the right version | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |     if ($self->read_line($self->{hOut}) ne $self->{strGreeting}) | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |         confess &log(ERROR, 'remote version mismatch'); | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # GREETING_WRITE | 
					
						
							| 
									
										
										
										
											2014-06-15 16:53:20 -04:00
										 |  |  | # | 
					
						
							|  |  |  | # Send a greeting to the master process. | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub greeting_write | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!syswrite(*STDOUT, "$self->{strGreeting}\n")) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |         confess 'unable to write greeting'; | 
					
						
							| 
									
										
										
										
											2014-06-06 21:16:24 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # STRING_WRITE | 
					
						
							| 
									
										
										
										
											2014-06-15 16:53:20 -04:00
										 |  |  | # | 
					
						
							|  |  |  | # Write a string. | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub string_write | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     my $hOut = shift; | 
					
						
							|  |  |  |     my $strBuffer = shift; | 
					
						
							| 
									
										
										
										
											2014-06-07 15:30:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |     $strBuffer =~ s/\n/\n\./g; | 
					
						
							| 
									
										
										
										
											2014-06-07 15:30:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |     if (!syswrite($hOut, '.' . $strBuffer)) | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |         confess 'unable to write string'; | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # PIPE_TO_STRING Function | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Copies data from a file handle into a string. | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub pipe_to_string | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     my $hOut = shift; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     my $strBuffer; | 
					
						
							|  |  |  |     my $hString = IO::String->new($strBuffer); | 
					
						
							|  |  |  |     $self->binary_xfer($hOut, $hString); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return $strBuffer; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # ERROR_WRITE | 
					
						
							| 
									
										
										
										
											2014-06-15 16:53:20 -04:00
										 |  |  | # | 
					
						
							|  |  |  | # Write errors with error codes in protocol format, otherwise write to stderr and exit with error. | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub error_write | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     my $oMessage = shift; | 
					
						
							| 
									
										
										
										
											2014-06-07 15:30:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |     my $iCode; | 
					
						
							|  |  |  |     my $strMessage; | 
					
						
							| 
									
										
										
										
											2014-06-07 15:30:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |     if (blessed($oMessage)) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |         if ($oMessage->isa('BackRest::Exception')) | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |         { | 
					
						
							|  |  |  |             $iCode = $oMessage->code(); | 
					
						
							|  |  |  |             $strMessage = $oMessage->message(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |             syswrite(*STDERR, 'unknown error object: ' . $oMessage); | 
					
						
							|  |  |  |             exit 1; | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |         syswrite(*STDERR, $oMessage); | 
					
						
							|  |  |  |         exit 1; | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (defined($strMessage)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $self->string_write(*STDOUT, trim($strMessage)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |     if (!syswrite(*STDOUT, "\nERROR" . (defined($iCode) ? " $iCode" : '') . "\n")) | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |         confess 'unable to write error'; | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # READ_LINE | 
					
						
							| 
									
										
										
										
											2014-06-15 16:53:20 -04:00
										 |  |  | # | 
					
						
							|  |  |  | # Read a line. | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub read_line | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     my $hIn = shift; | 
					
						
							|  |  |  |     my $bError = shift; | 
					
						
							| 
									
										
										
										
											2014-06-15 15:56:45 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |     my $strLine; | 
					
						
							|  |  |  |     my $strChar; | 
					
						
							|  |  |  |     my $iByteIn; | 
					
						
							| 
									
										
										
										
											2014-06-15 09:32:11 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |     while (1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $iByteIn = sysread($hIn, $strChar, 1); | 
					
						
							| 
									
										
										
										
											2014-06-15 15:56:45 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |         if (!defined($iByteIn) || $iByteIn != 1) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2014-06-15 09:32:11 -04:00
										 |  |  |             $self->wait_pid(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |             if (defined($bError) and !$bError) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 return undef; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2014-06-15 15:56:45 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |             confess &log(ERROR, 'unable to read 1 byte' . (defined($!) ? ': ' . $! : '')); | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2014-06-15 15:56:45 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |         if ($strChar eq "\n") | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             last; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $strLine .= $strChar; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-06-15 15:56:45 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |     return $strLine; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-21 10:05:49 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # WRITE_LINE | 
					
						
							| 
									
										
										
										
											2014-06-21 20:08:49 -04:00
										 |  |  | # | 
					
						
							| 
									
										
										
										
											2014-06-21 10:05:49 -04:00
										 |  |  | # Write a line data | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub write_line | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     my $hOut = shift; | 
					
						
							|  |  |  |     my $strBuffer = shift; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     $strBuffer = $strBuffer . "\n"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     my $iLineOut = syswrite($hOut, $strBuffer, length($strBuffer)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!defined($iLineOut) || $iLineOut != length($strBuffer)) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |         confess 'unable to write ' . length($strBuffer) . ' byte(s)'; | 
					
						
							| 
									
										
										
										
											2014-06-21 10:05:49 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-15 09:32:11 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # WAIT_PID | 
					
						
							| 
									
										
										
										
											2014-06-21 20:08:49 -04:00
										 |  |  | # | 
					
						
							| 
									
										
										
										
											2014-06-15 16:53:20 -04:00
										 |  |  | # See if the remote process has terminated unexpectedly. | 
					
						
							| 
									
										
										
										
											2014-06-15 09:32:11 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub wait_pid | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (defined($self->{pId}) && waitpid($self->{pId}, WNOHANG) != 0) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |         my $strError = 'no error on stderr'; | 
					
						
							| 
									
										
										
										
											2014-06-15 15:56:45 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-15 09:32:11 -04:00
										 |  |  |         if (!defined($self->{hErr})) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |             $strError = 'no error captured because stderr is already closed'; | 
					
						
							| 
									
										
										
										
											2014-06-15 09:32:11 -04:00
										 |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             $strError = $self->pipe_to_string($self->{hErr}); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $self->{pId} = undef; | 
					
						
							|  |  |  |         $self->{hIn} = undef; | 
					
						
							|  |  |  |         $self->{hOut} = undef; | 
					
						
							|  |  |  |         $self->{hErr} = undef; | 
					
						
							| 
									
										
										
										
											2014-06-15 15:56:45 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-15 09:32:11 -04:00
										 |  |  |         confess &log(ERROR, "remote process terminated: ${strError}"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # BLOCK_READ | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Read a block from the protocol layer. | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub block_read | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     my $hIn = shift; | 
					
						
							|  |  |  |     my $strBlockRef = shift; | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |     my $bProtocol = shift; | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |     my $iBlockSize; | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |     if ($bProtocol) | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |         # Read the block header and make sure it's valid | 
					
						
							|  |  |  |         my $strBlockHeader = $self->read_line($hIn); | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |         if ($strBlockHeader !~ /^block -{0,1}[0-9]+$/) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             $self->wait_pid(); | 
					
						
							|  |  |  |             confess "unable to read block header ${strBlockHeader}"; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |         # Get block size from the header | 
					
						
							|  |  |  |         $iBlockSize = trim(substr($strBlockHeader, index($strBlockHeader, ' ') + 1)); | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |         # If block size is 0 or an error code then undef the buffer | 
					
						
							|  |  |  |         if ($iBlockSize <= 0) | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |             undef($$strBlockRef); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         # Else read the block | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             my $iBlockRead = 0; | 
					
						
							|  |  |  |             my $iBlockIn = 0; | 
					
						
							|  |  |  |             my $iOffset = defined($$strBlockRef) ? length($$strBlockRef) : 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # !!! Would be nice to modify this with a non-blocking read | 
					
						
							|  |  |  |             # http://docstore.mik.ua/orelly/perl/cookbook/ch07_15.htm | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |             # Read as many chunks as it takes to get the full block | 
					
						
							|  |  |  |             while ($iBlockRead != $iBlockSize) | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  |             { | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                 $iBlockIn = sysread($hIn, $$strBlockRef, $iBlockSize - $iBlockRead, $iBlockRead + $iOffset); | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                 if (!defined($iBlockIn)) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     my $strError = $!; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     $self->wait_pid(); | 
					
						
							|  |  |  |                     confess "only read ${iBlockRead}/${iBlockSize} block bytes from remote" . | 
					
						
							|  |  |  |                             (defined($strError) ? ": ${strError}" : ''); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                 $iBlockRead += $iBlockIn; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $iBlockSize = $self->stream_read($hIn, $strBlockRef, $self->{iBlockSize}, | 
					
						
							|  |  |  |                                          defined($$strBlockRef) ? length($$strBlockRef) : 0); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Return the block size | 
					
						
							|  |  |  |     return $iBlockSize; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # BLOCK_WRITE | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Write a block to the protocol layer. | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub block_write | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     my $hOut = shift; | 
					
						
							|  |  |  |     my $tBlockRef = shift; | 
					
						
							|  |  |  |     my $iBlockSize = shift; | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |     my $bProtocol = shift; | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # If block size is not defined, get it from buffer length | 
					
						
							|  |  |  |     $iBlockSize = defined($iBlockSize) ? $iBlockSize : length($$tBlockRef); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Write block header to the protocol stream | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |     if ($bProtocol) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $self->write_line($hOut, "block ${iBlockSize}"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Write block if size > 0 | 
					
						
							|  |  |  |     if ($iBlockSize > 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $self->stream_write($hOut, $tBlockRef, $iBlockSize); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # STREAM_READ | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Read data from a stream. | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub stream_read | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     my $hIn = shift; | 
					
						
							|  |  |  |     my $tBlockRef = shift; | 
					
						
							|  |  |  |     my $iBlockSize = shift; | 
					
						
							| 
									
										
										
										
											2015-02-27 23:31:39 -05:00
										 |  |  |     my $bOffset = shift; | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Read a block from the stream | 
					
						
							| 
									
										
										
										
											2015-02-27 23:31:39 -05:00
										 |  |  |     my $iBlockIn = sysread($hIn, $$tBlockRef, $iBlockSize, $bOffset ? length($$tBlockRef) : false); | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!defined($iBlockIn)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $self->wait_pid(); | 
					
						
							|  |  |  |         confess &log(ERROR, 'unable to read'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return $iBlockIn; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # STREAM_WRITE | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Write data to a stream. | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub stream_write | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     my $hOut = shift; | 
					
						
							|  |  |  |     my $tBlockRef = shift; | 
					
						
							|  |  |  |     my $iBlockSize = shift; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # If block size is not defined, get it from buffer length | 
					
						
							|  |  |  |     $iBlockSize = defined($iBlockSize) ? $iBlockSize : length($$tBlockRef); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Write the block | 
					
						
							|  |  |  |     my $iBlockOut = syswrite($hOut, $$tBlockRef, $iBlockSize); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Report any errors | 
					
						
							|  |  |  |     if (!defined($iBlockOut) || $iBlockOut != $iBlockSize) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         my $strError = $!; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $self->wait_pid(); | 
					
						
							|  |  |  |         confess "unable to write ${iBlockSize} bytes" . (defined($strError) ? ': ' . $strError : ''); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-12 21:56:20 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # BINARY_XFER | 
					
						
							|  |  |  | # | 
					
						
							| 
									
										
										
										
											2015-02-26 09:22:05 -05:00
										 |  |  | # Copies data from one file handle to another, optionally compressing or decompressing the data in stream.  If $strRemote != none | 
					
						
							|  |  |  | # then one side is a protocol stream. | 
					
						
							| 
									
										
										
										
											2014-06-12 21:56:20 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub binary_xfer | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     my $hIn = shift; | 
					
						
							|  |  |  |     my $hOut = shift; | 
					
						
							|  |  |  |     my $strRemote = shift; | 
					
						
							| 
									
										
										
										
											2014-06-21 08:42:30 -04:00
										 |  |  |     my $bSourceCompressed = shift; | 
					
						
							|  |  |  |     my $bDestinationCompress = shift; | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |     my $bProtocol = shift; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # The input stream must be defined (output is optional) | 
					
						
							|  |  |  |     if (!defined($hIn)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         confess &log(ASSERT, 'hIn is not defined'); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-06-12 21:56:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-30 18:35:05 -04:00
										 |  |  |     # If no remote is defined then set to none | 
					
						
							| 
									
										
										
										
											2014-06-21 08:42:30 -04:00
										 |  |  |     if (!defined($strRemote)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $strRemote = 'none'; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-06-30 18:35:05 -04:00
										 |  |  |     # Only set compression defaults when remote is defined | 
					
						
							| 
									
										
										
										
											2014-06-21 08:42:30 -04:00
										 |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $bSourceCompressed = defined($bSourceCompressed) ? $bSourceCompressed : false; | 
					
						
							|  |  |  |         $bDestinationCompress = defined($bDestinationCompress) ? $bDestinationCompress : false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |     # Default protocol to true | 
					
						
							|  |  |  |     $bProtocol = defined($bProtocol) ? $bProtocol : true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-30 18:35:05 -04:00
										 |  |  |     # Working variables | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |     my $iBlockSize = $self->{iBlockSize}; | 
					
						
							| 
									
										
										
										
											2014-06-12 21:56:20 -04:00
										 |  |  |     my $iBlockIn; | 
					
						
							| 
									
										
										
										
											2015-02-26 09:22:05 -05:00
										 |  |  |     my $iBlockBufferIn; | 
					
						
							| 
									
										
										
										
											2014-06-12 21:56:20 -04:00
										 |  |  |     my $strBlock; | 
					
						
							| 
									
										
										
										
											2015-02-26 09:22:05 -05:00
										 |  |  |     my $strBlockBuffer; | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |     my $iFileSize = undef; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-28 15:54:49 -05:00
										 |  |  |     my $oGzip = undef; | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |     my $oZLib = undef; | 
					
						
							|  |  |  |     my $iZLibStatus; | 
					
						
							| 
									
										
										
										
											2015-02-28 15:54:49 -05:00
										 |  |  |     my $oSHA = undef; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-26 19:12:22 -05:00
										 |  |  |     my $bFirst = true; | 
					
						
							| 
									
										
										
										
											2014-06-15 15:56:45 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |     while (1) | 
					
						
							| 
									
										
										
										
											2014-06-12 21:56:20 -04:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2015-02-26 09:22:05 -05:00
										 |  |  |         # Read from the protocol stream | 
					
						
							| 
									
										
										
										
											2014-06-12 21:56:20 -04:00
										 |  |  |         if ($strRemote eq 'in') | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2015-02-27 16:36:40 -05:00
										 |  |  |             # If the destination should not be compressed then decompress | 
					
						
							|  |  |  |             if (!$bDestinationCompress) | 
					
						
							| 
									
										
										
										
											2015-02-26 19:12:22 -05:00
										 |  |  |             { | 
					
						
							| 
									
										
										
										
											2015-02-27 16:36:40 -05:00
										 |  |  |                 # Read a block from the protocol stream | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                 $iBlockSize = $self->block_read($hIn, \$strBlockBuffer, $bProtocol); | 
					
						
							| 
									
										
										
										
											2015-02-26 19:12:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                 # If block size = -1 it means an error happened on the remote and we need to exit so it can be returned. | 
					
						
							| 
									
										
										
										
											2015-02-27 18:42:28 -05:00
										 |  |  |                 if ($iBlockSize == -1) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     last; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 16:36:40 -05:00
										 |  |  |                 # If this is the first block then initialize Gunzip | 
					
						
							|  |  |  |                 if ($bFirst) | 
					
						
							| 
									
										
										
										
											2015-02-26 19:12:22 -05:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2015-02-28 15:54:49 -05:00
										 |  |  |                     $oSHA = Digest::SHA->new('sha1'); | 
					
						
							|  |  |  |                     $iFileSize = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                     # if ($iBlockSize == 0) | 
					
						
							|  |  |  |                     # { | 
					
						
							|  |  |  |                     #     &log(ASSERT, 'first protocol block is zero'); | 
					
						
							|  |  |  |                     # } | 
					
						
							|  |  |  |                     # | 
					
						
							|  |  |  |                     # # Gunzip doesn't like to be initialized with just the header, so if the first block is 10 bytes then fetch | 
					
						
							|  |  |  |                     # # another another block to make sure so is at least some payload. | 
					
						
							|  |  |  |                     # if ($iBlockSize <= 10) | 
					
						
							|  |  |  |                     # { | 
					
						
							|  |  |  |                     #     $iBlockSize = $self->block_read($hIn, \$strBlockBuffer, $bProtocol); | 
					
						
							|  |  |  |                     # } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     # Initialize Gunzip | 
					
						
							|  |  |  |                     ($oZLib, $iZLibStatus) = new Compress::Raw::Zlib::Inflate(LimitOutput => 1, -WindowBits => WANT_GZIP, | 
					
						
							|  |  |  |                                                                               -Bufsize => $self->{iBlockSize}); | 
					
						
							| 
									
										
										
										
											2015-02-27 18:42:28 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                     if ($iZLibStatus != Z_OK) | 
					
						
							| 
									
										
										
										
											2015-02-27 16:36:40 -05:00
										 |  |  |                     { | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                         confess &log(ERROR, "unable create a inflation stream: ${iZLibStatus}"); | 
					
						
							| 
									
										
										
										
											2015-02-27 16:36:40 -05:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2015-02-26 19:12:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                     # $oGzip = new IO::Uncompress::Gunzip(\$strBlockBuffer, Append => 1, Transparent => 0, | 
					
						
							|  |  |  |                     #                                                       BlockSize => $self->{iBlockSize}) | 
					
						
							|  |  |  |                     #     or confess "IO::Uncompress::Gunzip failed (${iBlockSize}): $GunzipError"; | 
					
						
							| 
									
										
										
										
											2015-02-26 19:12:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 16:36:40 -05:00
										 |  |  |                     # Clear first block flag | 
					
						
							|  |  |  |                     $bFirst = false; | 
					
						
							| 
									
										
										
										
											2015-02-26 19:12:22 -05:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 16:36:40 -05:00
										 |  |  |                 # If the block contains data, decompress it | 
					
						
							|  |  |  |                 if ($iBlockSize > 0) | 
					
						
							| 
									
										
										
										
											2015-02-26 19:12:22 -05:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                     # my $iUncompressedTotal = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     # # Loop while there is more data to uncompress | 
					
						
							|  |  |  |                     # while (!$oGzip->eof()) | 
					
						
							|  |  |  |                     # { | 
					
						
							|  |  |  |                     #     # Decompress the block | 
					
						
							|  |  |  |                     #     $iBlockIn = $oGzip->read($strBlock); | 
					
						
							|  |  |  |                     # | 
					
						
							|  |  |  |                     #     if ($iBlockIn < 0) | 
					
						
							|  |  |  |                     #     { | 
					
						
							|  |  |  |                     #         confess &log(ERROR, "unable to decompress stream ($iBlockIn): ${GunzipError}"); | 
					
						
							|  |  |  |                     #     } | 
					
						
							|  |  |  |                     # | 
					
						
							|  |  |  |                     #     $iUncompressedTotal += $iBlockIn; | 
					
						
							|  |  |  |                     # } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     do | 
					
						
							| 
									
										
										
										
											2015-02-27 16:36:40 -05:00
										 |  |  |                     { | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                         $iZLibStatus = $oZLib->inflate($strBlockBuffer, $strBlock); | 
					
						
							| 
									
										
										
										
											2015-02-26 19:12:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                         if ($iZLibStatus == Z_OK || $iZLibStatus == Z_BUF_ERROR || $iZLibStatus == Z_STREAM_END) | 
					
						
							| 
									
										
										
										
											2015-02-27 16:36:40 -05:00
										 |  |  |                         { | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                             $iFileSize += length($strBlock); | 
					
						
							|  |  |  |                             $oSHA->add($strBlock); | 
					
						
							| 
									
										
										
										
											2015-02-26 19:12:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                             if (defined($hOut)) | 
					
						
							|  |  |  |                             { | 
					
						
							|  |  |  |                                 $self->stream_write($hOut, \$strBlock); | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         else | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             $iBlockSize = 0; | 
					
						
							|  |  |  |                             last; | 
					
						
							|  |  |  |                         } | 
					
						
							| 
									
										
										
										
											2015-02-27 16:36:40 -05:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                     while ($iZLibStatus == Z_OK && length($strBlock)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     # # Write out the uncompressed bytes if there are any | 
					
						
							|  |  |  |                     # if ($iUncompressedTotal > 0) | 
					
						
							|  |  |  |                     # { | 
					
						
							|  |  |  |                     #     $oSHA->add($strBlock); | 
					
						
							|  |  |  |                     #     $iFileSize += $iUncompressedTotal; | 
					
						
							|  |  |  |                     # | 
					
						
							|  |  |  |                     #     if (defined($hOut)) | 
					
						
							|  |  |  |                     #     { | 
					
						
							|  |  |  |                     #         $self->stream_write($hOut, \$strBlock, $iUncompressedTotal); | 
					
						
							|  |  |  |                     #     } | 
					
						
							|  |  |  |                     # | 
					
						
							|  |  |  |                     #     undef($strBlock); | 
					
						
							|  |  |  |                     # } | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                 # Make sure the decompression succeeded | 
					
						
							|  |  |  |                 if ($iBlockSize == 0) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     if ($iZLibStatus != Z_STREAM_END) | 
					
						
							| 
									
										
										
										
											2015-02-27 16:36:40 -05:00
										 |  |  |                     { | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                         confess &log(ERROR, "unable to inflate stream: gzip returned ${iZLibStatus}"); | 
					
						
							| 
									
										
										
										
											2015-02-27 16:36:40 -05:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 16:36:40 -05:00
										 |  |  |                     last; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-02-27 16:36:40 -05:00
										 |  |  |             # If the destination should be compressed then just write out the already compressed stream | 
					
						
							|  |  |  |             else | 
					
						
							| 
									
										
										
										
											2014-06-12 21:56:20 -04:00
										 |  |  |             { | 
					
						
							| 
									
										
										
										
											2015-02-27 16:36:40 -05:00
										 |  |  |                 # Read a block from the protocol stream | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                 $iBlockSize = $self->block_read($hIn, \$strBlock, $bProtocol); | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 16:36:40 -05:00
										 |  |  |                 # If the block contains data, write it | 
					
						
							|  |  |  |                 if ($iBlockSize > 0) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     $self->stream_write($hOut, \$strBlock, $iBlockSize); | 
					
						
							|  |  |  |                     undef($strBlock); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 # Else done | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     last; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2014-06-12 21:56:20 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-02-26 09:22:05 -05:00
										 |  |  |         # Read from file input stream | 
					
						
							| 
									
										
										
										
											2014-06-12 21:56:20 -04:00
										 |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2015-02-26 19:12:22 -05:00
										 |  |  |             # If source is not already compressed then compress it | 
					
						
							|  |  |  |             if ($strRemote eq 'out' && !$bSourceCompressed) | 
					
						
							| 
									
										
										
										
											2014-06-12 21:56:20 -04:00
										 |  |  |             { | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  |                 # Create the gzip object | 
					
						
							| 
									
										
										
										
											2015-02-26 19:12:22 -05:00
										 |  |  |                 if ($bFirst) | 
					
						
							|  |  |  |                 { | 
					
						
							| 
									
										
										
										
											2015-02-28 15:54:49 -05:00
										 |  |  |                     $oSHA = Digest::SHA->new('sha1'); | 
					
						
							|  |  |  |                     $iFileSize = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  |                     $oGzip = new IO::Compress::Gzip(\$strBlock, Append => 1) | 
					
						
							| 
									
										
										
										
											2015-02-26 19:12:22 -05:00
										 |  |  |                         or confess "IO::Compress::Gzip failed: $GzipError"; | 
					
						
							| 
									
										
										
										
											2015-02-27 16:36:40 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 23:31:39 -05:00
										 |  |  |                     # Clear first block flag | 
					
						
							| 
									
										
										
										
											2015-02-27 16:36:40 -05:00
										 |  |  |                     $bFirst = false; | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2015-02-26 09:22:05 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  |                 # Read a block from the stream | 
					
						
							|  |  |  |                 $iBlockBufferIn = $self->stream_read($hIn, \$strBlockBuffer, $iBlockSize); | 
					
						
							| 
									
										
										
										
											2015-02-28 15:54:49 -05:00
										 |  |  |                 $oSHA->add($strBlockBuffer); | 
					
						
							|  |  |  |                 $iFileSize += $iBlockBufferIn; | 
					
						
							| 
									
										
										
										
											2015-02-26 09:22:05 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  |                 # If block size > 0 then compress | 
					
						
							|  |  |  |                 if ($iBlockBufferIn > 0) | 
					
						
							| 
									
										
										
										
											2015-02-26 09:22:05 -05:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  |                     $iBlockIn = $oGzip->syswrite($strBlockBuffer, $iBlockBufferIn); | 
					
						
							| 
									
										
										
										
											2015-02-26 19:12:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  |                     if (!defined($iBlockIn) || $iBlockIn != $iBlockBufferIn) | 
					
						
							| 
									
										
										
										
											2015-02-26 19:12:22 -05:00
										 |  |  |                     { | 
					
						
							|  |  |  |                         $self->wait_pid(); | 
					
						
							| 
									
										
										
										
											2015-02-27 23:31:39 -05:00
										 |  |  |                         confess &log(ERROR, "IO::Compress::Gzip failed: $GzipError"); | 
					
						
							| 
									
										
										
										
											2015-02-26 19:12:22 -05:00
										 |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                     if (defined($hOut) && defined($strBlock) && length($strBlock) > $self->{iBlockSize}) | 
					
						
							| 
									
										
										
										
											2015-02-27 23:31:39 -05:00
										 |  |  |                     { | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                         $self->block_write($hOut, \$strBlock, undef, $bProtocol); | 
					
						
							| 
									
										
										
										
											2015-02-27 23:31:39 -05:00
										 |  |  |                         undef($strBlock); | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2015-02-27 14:11:59 -05:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  |                 # If there was nothing new to compress then close | 
					
						
							| 
									
										
										
										
											2015-02-27 14:11:59 -05:00
										 |  |  |                 else | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  |                 { | 
					
						
							|  |  |  |                     $oGzip->close(); | 
					
						
							| 
									
										
										
										
											2015-02-26 19:12:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                     if (defined($hOut)) | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         $self->block_write($hOut, \$strBlock, undef, $bProtocol); | 
					
						
							|  |  |  |                         $self->block_write($hOut, undef, 0, $bProtocol); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 14:11:59 -05:00
										 |  |  |                     last; | 
					
						
							| 
									
										
										
										
											2015-02-26 09:22:05 -05:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-02-26 19:12:22 -05:00
										 |  |  |             # If source is already compressed or transfer is not compressed then just read the stream | 
					
						
							| 
									
										
										
										
											2015-02-26 09:22:05 -05:00
										 |  |  |             else | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2015-02-27 13:48:29 -05:00
										 |  |  |                 $iBlockIn = $self->stream_read($hIn, \$strBlock, $iBlockSize); | 
					
						
							| 
									
										
										
										
											2014-06-12 21:56:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 14:11:59 -05:00
										 |  |  |                 if ($iBlockIn > 0) | 
					
						
							|  |  |  |                 { | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                     $self->block_write($hOut, \$strBlock, $iBlockIn, $bProtocol); | 
					
						
							| 
									
										
										
										
											2015-02-27 14:11:59 -05:00
										 |  |  |                 } | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                 { | 
					
						
							| 
									
										
										
										
											2015-03-01 13:41:35 -05:00
										 |  |  |                     $self->block_write($hOut, undef, 0, $bProtocol); | 
					
						
							| 
									
										
										
										
											2015-02-27 14:11:59 -05:00
										 |  |  |                     last; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2014-06-12 21:56:20 -04:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-02-28 15:54:49 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Return the checksum and size if they are available | 
					
						
							| 
									
										
										
										
											2015-02-28 19:07:29 -05:00
										 |  |  |     return (defined($oSHA) ? $oSHA->hexdigest() : undef), $iFileSize; | 
					
						
							| 
									
										
										
										
											2014-06-12 21:56:20 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # OUTPUT_READ | 
					
						
							| 
									
										
										
										
											2014-06-15 16:53:20 -04:00
										 |  |  | # | 
					
						
							|  |  |  | # Read output from the remote process. | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub output_read | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |     my $bOutputRequired = shift; | 
					
						
							|  |  |  |     my $strErrorPrefix = shift; | 
					
						
							| 
									
										
										
										
											2014-09-30 15:51:08 -04:00
										 |  |  |     my $bSuppressLog = shift; | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     my $strLine; | 
					
						
							|  |  |  |     my $strOutput; | 
					
						
							|  |  |  |     my $bError = false; | 
					
						
							|  |  |  |     my $iErrorCode; | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |     my $strError; | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-15 16:53:20 -04:00
										 |  |  |     # Read output lines | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |     while ($strLine = $self->read_line($self->{hOut}, false)) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |         if ($strLine =~ /^ERROR.*/) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             $bError = true; | 
					
						
							| 
									
										
										
										
											2014-06-07 15:30:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |             $iErrorCode = (split(' ', $strLine))[1]; | 
					
						
							| 
									
										
										
										
											2014-06-07 15:30:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |             last; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |         if ($strLine =~ /^OK$/) | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |         { | 
					
						
							|  |  |  |             last; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |         $strOutput .= (defined($strOutput) ? "\n" : '') . substr($strLine, 1); | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-15 16:53:20 -04:00
										 |  |  |     # Check if the process has exited abnormally | 
					
						
							|  |  |  |     $self->wait_pid(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Raise any errors | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |     if ($bError) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |         confess &log(ERROR, (defined($strErrorPrefix) ? "${strErrorPrefix}" : '') . | 
					
						
							| 
									
										
										
										
											2014-09-30 15:51:08 -04:00
										 |  |  |                             (defined($strOutput) ? ": ${strOutput}" : ''), $iErrorCode, $bSuppressLog); | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-06-15 15:56:45 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-15 16:53:20 -04:00
										 |  |  |     # If output is required and there is no output, raise exception | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |     if ($bOutputRequired && !defined($strOutput)) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |         confess &log(ERROR, (defined($strErrorPrefix) ? "${strErrorPrefix}: " : '') . 'output is not defined'); | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-15 16:53:20 -04:00
										 |  |  |     # Return output | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |     return $strOutput; | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # OUTPUT_WRITE | 
					
						
							| 
									
										
										
										
											2014-06-15 16:53:20 -04:00
										 |  |  | # | 
					
						
							|  |  |  | # Write output for the master process. | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub output_write | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     my $strOutput = shift; | 
					
						
							| 
									
										
										
										
											2014-06-07 15:30:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |     if (defined($strOutput)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $self->string_write(*STDOUT, "${strOutput}"); | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |         if (!syswrite(*STDOUT, "\n")) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |             confess 'unable to write output'; | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!syswrite(*STDOUT, "OK\n")) | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |         confess 'unable to write output'; | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							| 
									
										
										
										
											2014-06-07 15:01:29 -04:00
										 |  |  | # COMMAND_PARAM_STRING | 
					
						
							| 
									
										
										
										
											2014-06-15 16:53:20 -04:00
										 |  |  | # | 
					
						
							|  |  |  | # Output command parameters in the hash as a string (used for debugging). | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							| 
									
										
										
										
											2014-06-07 15:01:29 -04:00
										 |  |  | sub command_param_string | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							| 
									
										
										
										
											2014-06-07 15:01:29 -04:00
										 |  |  |     my $oParamHashRef = shift; | 
					
						
							| 
									
										
										
										
											2014-06-07 15:30:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-07 15:01:29 -04:00
										 |  |  |     my $strParamList; | 
					
						
							| 
									
										
										
										
											2014-06-07 15:30:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-06 13:08:56 -05:00
										 |  |  |     if (defined($oParamHashRef)) | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2015-01-06 13:08:56 -05:00
										 |  |  |         foreach my $strParam (sort(keys $oParamHashRef)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             $strParamList .= (defined($strParamList) ? ',' : '') . "${strParam}=" . | 
					
						
							|  |  |  |                              (defined(${$oParamHashRef}{"${strParam}"}) ? ${$oParamHashRef}{"${strParam}"} : '[undef]'); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-06-07 15:01:29 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return $strParamList; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # COMMAND_READ | 
					
						
							| 
									
										
										
										
											2014-06-15 16:53:20 -04:00
										 |  |  | # | 
					
						
							|  |  |  | # Read command sent by the master process. | 
					
						
							| 
									
										
										
										
											2014-06-07 15:01:29 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub command_read | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     my $oParamHashRef = shift; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     my $strLine; | 
					
						
							|  |  |  |     my $strCommand; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |     while ($strLine = $self->read_line(*STDIN)) | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-06-07 15:01:29 -04:00
										 |  |  |         if (!defined($strCommand)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if ($strLine =~ /:$/) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 $strCommand = substr($strLine, 0, length($strLine) - 1); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 $strCommand = $strLine; | 
					
						
							|  |  |  |                 last; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if ($strLine eq 'end') | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 last; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2014-06-07 15:30:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |             my $iPos = index($strLine, '='); | 
					
						
							| 
									
										
										
										
											2014-06-07 15:30:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-07 15:01:29 -04:00
										 |  |  |             if ($iPos == -1) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 confess "param \"${strLine}\" is missing = character"; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2014-06-07 15:30:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-07 15:01:29 -04:00
										 |  |  |             my $strParam = substr($strLine, 0, $iPos); | 
					
						
							|  |  |  |             my $strValue = substr($strLine, $iPos + 1); | 
					
						
							| 
									
										
										
										
											2014-06-07 15:30:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-07 15:01:29 -04:00
										 |  |  |             ${$oParamHashRef}{"${strParam}"} = ${strValue}; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-07 15:01:29 -04:00
										 |  |  |     return $strCommand; | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # COMMAND_WRITE | 
					
						
							| 
									
										
										
										
											2014-06-15 16:53:20 -04:00
										 |  |  | # | 
					
						
							|  |  |  | # Send command to remote process. | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub command_write | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     my $strCommand = shift; | 
					
						
							| 
									
										
										
										
											2014-06-07 15:01:29 -04:00
										 |  |  |     my $oParamRef = shift; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     my $strOutput = $strCommand; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (defined($oParamRef)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $strOutput = "${strCommand}:\n"; | 
					
						
							| 
									
										
										
										
											2014-06-07 15:30:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-07 15:01:29 -04:00
										 |  |  |         foreach my $strParam (sort(keys $oParamRef)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if ($strParam =~ /=/) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 confess &log(ASSERT, "param \"${strParam}\" cannot contain = character"); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             my $strValue = ${$oParamRef}{"${strParam}"}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if ($strParam =~ /\n\$/) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 confess &log(ASSERT, "param \"${strParam}\" value cannot end with LF"); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2014-06-07 15:30:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-07 15:01:29 -04:00
										 |  |  |             if (defined(${strValue})) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 $strOutput .= "${strParam}=${strValue}\n"; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |         $strOutput .= 'end'; | 
					
						
							| 
									
										
										
										
											2014-06-07 15:01:29 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |     &log(TRACE, "Remote->command_write:\n" . $strOutput); | 
					
						
							| 
									
										
										
										
											2014-06-07 13:15:55 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-07 15:01:29 -04:00
										 |  |  |     if (!syswrite($self->{hIn}, "${strOutput}\n")) | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-09-16 11:22:55 -04:00
										 |  |  |         confess 'unable to write command'; | 
					
						
							| 
									
										
										
										
											2014-06-07 11:51:27 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-07 13:15:55 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | # COMMAND_EXECUTE | 
					
						
							| 
									
										
										
										
											2014-06-15 16:53:20 -04:00
										 |  |  | # | 
					
						
							|  |  |  | # Send command to remote process and wait for output. | 
					
						
							| 
									
										
										
										
											2014-06-07 13:15:55 -04:00
										 |  |  | #################################################################################################################################### | 
					
						
							|  |  |  | sub command_execute | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     my $strCommand = shift; | 
					
						
							| 
									
										
										
										
											2014-06-12 21:56:20 -04:00
										 |  |  |     my $oParamRef = shift; | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |     my $bOutputRequired = shift; | 
					
						
							| 
									
										
										
										
											2014-06-07 13:15:55 -04:00
										 |  |  |     my $strErrorPrefix = shift; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-12 21:56:20 -04:00
										 |  |  |     $self->command_write($strCommand, $oParamRef); | 
					
						
							| 
									
										
										
										
											2014-06-07 15:30:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-14 19:50:54 -04:00
										 |  |  |     return $self->output_read($bOutputRequired, $strErrorPrefix); | 
					
						
							| 
									
										
										
										
											2014-06-07 13:15:55 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-10 15:13:28 -04:00
										 |  |  | 1; |