Handle the ioctl call returns better.
[perl-fuse.git] / examples / fioclient.pl
1 #!/usr/bin/env perl
2
3 use strict;
4 no strict qw(refs);
5
6 use Carp;
7 local $SIG{'__WARN__'} = \&Carp::cluck;
8
9 use Fcntl qw(:mode);
10 use Errno qw(:POSIX);
11 use POSIX;
12
13 use constant FIOC_NAME => 'fioc';
14 use constant FIOC_NONE  => 0;
15 use constant FIOC_ROOT  => 1;
16 use constant FIOC_FILE  => 2;
17
18 require 'asm/ioctl.ph';
19
20 our %sizeof = ('int' => 4);
21 sub FIOC_GET_SIZE { _IOR(ord 'E', 0, 'int'); }
22 sub FIOC_SET_SIZE { _IOW(ord 'E', 1, 'int'); }
23
24 sub usage {
25     print <<'_EOT_';
26 Usage: fioclient.pl FIOC_FILE COMMAND
27
28 COMMANDS
29   s [SIZE]     : get size if SIZE is omitted, set size otherwise
30   r SIZE [OFF] : read SIZE bytes @ OFF (default 0) and output to stdout
31   w SIZE [OFF] : write SIZE bytes @ OFF (default 0) from stdin
32
33 _EOT_
34     exit(1);
35 }
36
37
38 usage() if scalar(@ARGV) < 2;
39
40 open(my $file, '+<', $ARGV[0]) or usage();
41
42 if ($ARGV[1] eq 's') {
43     if (!defined $ARGV[2]) {
44         my $size;
45         my $rv = ioctl($file, FIOC_GET_SIZE, $size);
46         if (!defined($rv) || $rv != 0) {
47             croak($!);
48         }
49         printf("\%u\n", unpack('L', $size));
50     }
51     else {
52         my $rv = ioctl($file, FIOC_SET_SIZE, pack('L', $ARGV[2]));
53         if (!defined($rv) || $rv != 0) {
54             croak($!);
55         }
56     }
57 }
58 elsif ($ARGV[1] eq 'r' || $ARGV[1] eq 'w') {
59     usage() unless defined $ARGV[2];
60     my $size = $ARGV[2];
61     my $off = 0;
62     if (defined $ARGV[3]) {
63         $off = $ARGV[3];
64     }
65     seek($file, SEEK_SET, $off);
66     if ($ARGV[1] eq 'r') {
67         read($file, my $data, $size);
68         print $data;
69     }
70     else {
71         read(STDIN, my $data, $size);
72         print $file $data;
73     }
74 }
75 else {
76     usage();
77 }
78
79 close($file);