POE-Component-Fuse

 view release on metacpan or  search on metacpan

lib/POE/Component/Fuse/SubProcess.pm  view on Meta::CPAN

# Set the binmode stuff
binmode( STDIN );
binmode( STDOUT );

# This is the subroutine that will get executed upon the fork() call by our parent
sub main {
	# in order to mount the FUSE fs and start the eventloop, we have to get the INIT packet
	my $data = receive_master();
	if ( $data->{'ACTION'} eq 'INIT' ) {
		start_fuse( $data->{'MOUNT'}, $data->{'MOUNTOPTS'} );
	} else {
		die 'unable to receive INIT data';
	}

	# should never get here
	return;
}

# gets a packet from STDIN
sub receive_master {
	# Okay, now we listen for commands from our parent :)
	while ( sysread( STDIN, my $buffer = '', 1024 ) ) {
		# Feed the line into the filter
		my $data = $filter->get( [ $buffer ] );

		# should be an array with 1 element
		if ( defined $data ) {
			if ( scalar @$data == 1 ) {
				return $data->[0];
			} else {
				# get more data
			}
		}
	}

	# should never get here
	return;
}

# sends a packet via STDOUT
sub send_master {
	my $data = shift;

	# process it via Filter::Reference
	$data = $filter->put( [ $data ] );
	foreach my $l ( @$data ) {
		print STDOUT $l;
	}

	return;
}

# initializes FUSE and enters the eventloop
sub start_fuse {
	my $mount = shift;
	my $opts = shift;

	# setup our callbacks
	my %callbacks;
	foreach my $cb ( qw( getattr readlink getdir mknod mkdir unlink rmdir symlink rename link chmod
		chown truncate utime open read write statfs flush release fsync
		setxattr getxattr listxattr removexattr ) ) {

		$callbacks{ $cb } = "POE::Component::Fuse::SubProcess::callback_" . $cb;

		# create the sub!
		eval "sub callback_$cb { return fuse_callback( \$cb, \@_ ) }";	## no critic ( ProhibitStringyEval )
		if ( $@ ) {
			die $@;
		}
	}

	# setup FUSE
	POE::Component::Fuse::myFuse::main(
		# basic setup
		'debug'		=> 0,
		'threaded'	=> 0,
		'mountpoint'	=> $mount,
		( defined $opts ? ( 'mountopts' => $opts ) : () ),

		# the callbacks
		%callbacks,
	);

	# should never get here unless we encountered an error
	return;
}

# handles callbacks
sub fuse_callback {
	my $type = shift;

	# get the context
	my $cxt = fuse_get_context();

	# pass it on to our master!
	send_master( {
		'TYPE'		=> $type,
		'ARGS'		=> [ @_ ],
		'CONTEXT'	=> $cxt,
	} );

	# wait for the reply
	my $reply = receive_master();

	# make sure the type is the same
	if ( $reply->{'ACTION'} eq 'REPLY' ) {
		if ( $reply->{'TYPE'} eq $type ) {
			# Fix up the FH if needed
			if ( $type eq 'open' and exists $reply->{'FH'} and defined $reply->{'FH'} ) {
				# compare the data!
				if ( defined $cxt->{'fh'} ) {
					if ( $reply->{'FH'} != $cxt->{'fh'} ) {
						fuse_set_fh( $reply->{'FH'} );
					}
				} else {
					fuse_set_fh( $reply->{'FH'} );
				}
			}

			# one-arg check



( run in 0.871 second using v1.01-cache-2.11-cpan-5511b514fd6 )