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