On Perl 5.8, lchown() sometimes ends up with leaked errno; declare $! local.
[perl-fuse.git] / examples / rmount.pl
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);