1 |
#!/usr/bin/perl -w |
2 |
|
3 |
# This example needs some work before it can support threads. |
4 |
use strict; |
5 |
use Net::SSH 'sshopen2'; |
6 |
use IPC::Open2; |
7 |
use Fuse; |
8 |
use Data::Dumper; |
9 |
|
10 |
my ($host, $dir, $mount) = @ARGV; |
11 |
if(!defined($mount)) { |
12 |
$mount = $dir; |
13 |
if($host =~ /^(.*):(.*)$/) { |
14 |
($host,$dir) = ($1,$2); |
15 |
} else { |
16 |
die "usage: $0 user\@host remotedir mountpoint\n". |
17 |
"or : $0 user\@host:remotedir mountpoint\n"; |
18 |
} |
19 |
} |
20 |
|
21 |
`umount $mount` unless -d $mount; |
22 |
die "mountpoint $mount isn't a directory!\n" unless -d $mount; |
23 |
|
24 |
my (%args) = (mountpoint => $mount); |
25 |
|
26 |
map { my ($str) = $_; $args{$str} = sub { netlink($str,@_) } } |
27 |
qw(getattr getdir open read write readlink unlink rmdir |
28 |
symlink rename link chown chmod truncate utime mkdir |
29 |
rmdir mknod statfs); |
30 |
|
31 |
sub connect_remote { |
32 |
sshopen2($host, *READER, *WRITER, "./rmount_remote.pl $dir") |
33 |
or die "ssh: $!\n"; |
34 |
select WRITER; |
35 |
$| = 1; |
36 |
select STDOUT; |
37 |
} |
38 |
|
39 |
$SIG{CHLD} = sub { |
40 |
use POSIX ":sys_wait_h"; |
41 |
my $kid; |
42 |
do { |
43 |
$kid = waitpid(-1,WNOHANG); |
44 |
} until $kid < 1; |
45 |
}; |
46 |
|
47 |
connect_remote; |
48 |
|
49 |
sub netlink { |
50 |
my ($str) = Dumper(\@_)."\n"; |
51 |
$str = sprintf("%08i\n%s",length($str),$str); |
52 |
while(1) { # retry as necessary |
53 |
my ($VAR1); |
54 |
$VAR1 = undef; |
55 |
eval { |
56 |
local $SIG{ALRM} = sub { die "timeout\n" }; |
57 |
alarm 10; |
58 |
print WRITER $str; |
59 |
my ($len, $data); |
60 |
$data = ''; |
61 |
if(sysread(READER,$len,9) == 9) { |
62 |
sysread(READER,$data,$len-length($data),length($data)) |
63 |
while(length($data) < $len); |
64 |
eval $data; |
65 |
} |
66 |
alarm 0; |
67 |
}; |
68 |
if(defined $VAR1) { |
69 |
return wantarray ? @{$VAR1} : $$VAR1[0]; |
70 |
} |
71 |
print STDERR "failed to send command; reconnecting ssh\n"; |
72 |
close(READER); |
73 |
close(WRITER); |
74 |
connect_remote(); |
75 |
} |
76 |
} |
77 |
|
78 |
Fuse::main(%args); |
79 |
|
80 |
netlink("bye"); |
81 |
close(READER); |
82 |
close(WRITER); |