0dc7bfc4415dd3567d70fe50e1a5e6f8780924c7
[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 sub _IOC_NRBITS  { 8 }
19 sub _IOC_NRMASK  { ( 1 << &_IOC_NRBITS ) - 1 }
20 sub _IOC_NRSHIFT { 0 }
21
22 sub _IOC_TYPEBITS  { 8 }
23 sub _IOC_TYPEMASK  { ( 1 << &_IOC_TYPEBITS ) - 1 }
24 sub _IOC_TYPESHIFT { &_IOC_NRSHIFT + &_IOC_NRBITS }
25
26 sub _IOC_SIZEBITS { ( POSIX::uname() )[4] =~ /^i[3-6]86|x86_64$/ ? 14 : 13 }
27 sub _IOC_SIZEMASK  { ( 1 << &_IOC_SIZEBITS ) - 1 }
28 sub _IOC_SIZESHIFT { &_IOC_TYPESHIFT + &_IOC_TYPEBITS }
29
30 sub _IOC_DIRBITS  { 32 - &_IOC_NRBITS - &_IOC_TYPEBITS - &_IOC_SIZEBITS }
31 sub _IOC_DIRMASK  { ( 1 << &_IOC_DIRBITS ) - 1 }
32 sub _IOC_DIRSHIFT { &_IOC_SIZESHIFT + &_IOC_SIZEBITS }
33
34 sub _IOC_NONE  { ( POSIX::uname() )[4] =~ /^i[3-6]86|x86_64$/ ? 0 : 1 }
35 sub _IOC_WRITE { ( POSIX::uname() )[4] =~ /^i[3-6]86|x86_64$/ ? 1 : 4 }
36 sub _IOC_READ  { ( POSIX::uname() )[4] =~ /^i[3-6]86|x86_64$/ ? 2 : 2 }
37
38 sub _IOC ($$$$) {
39   ( $_[0] << &_IOC_DIRSHIFT ) |  ( ord( $_[1] ) << &_IOC_TYPESHIFT ) |
40     ( $_[2] << &_IOC_NRSHIFT ) | ( $_[3] << &_IOC_SIZESHIFT );
41 }
42
43 sub _IO ($$)    { &_IOC( &_IOC_NONE,               $_[0], $_[1], 0 ) }
44 sub _IOR ($$$)  { &_IOC( &_IOC_READ,               $_[0], $_[1], $_[2] ) }
45 sub _IOW ($$$)  { &_IOC( &_IOC_WRITE,              $_[0], $_[1], $_[2] ) }
46 sub _IOWR ($$$) { &_IOC( &_IOC_READ | &_IOC_WRITE, $_[0], $_[1], $_[2] ) }
47
48 sub FIOC_GET_SIZE { _IOR('E', 0, 4); }
49 sub FIOC_SET_SIZE { _IOW('E', 1, 4); }
50
51 sub usage {
52     print <<'_EOT_';
53 Usage: fioclient.pl FIOC_FILE COMMAND
54
55 COMMANDS
56   s [SIZE]     : get size if SIZE is omitted, set size otherwise
57   r SIZE [OFF] : read SIZE bytes @ OFF (default 0) and output to stdout
58   w SIZE [OFF] : write SIZE bytes @ OFF (default 0) from stdin
59
60 _EOT_
61     exit(1);
62 }
63
64
65 usage() if scalar(@ARGV) < 2;
66
67 open(my $file, '+<', $ARGV[0]) or usage();
68
69 if ($ARGV[1] eq 's') {
70     if (!defined $ARGV[2]) {
71         my $size;
72         my $rv = ioctl($file, FIOC_GET_SIZE, $size);
73         if (ioctl($file, FIOC_GET_SIZE, $size) != 0) {
74             croak($!);
75         }
76         printf("\%u\n", unpack('L', $size));
77     }
78     else {
79         if (ioctl($file, FIOC_SET_SIZE, pack('L', $ARGV[2])) != 0) {
80             croak($!);
81         }
82     }
83 }
84 elsif ($ARGV[1] eq 'r' || $ARGV[1] eq 'w') {
85     usage() unless defined $ARGV[2];
86     my $size = $ARGV[2];
87     my $off = 0;
88     if (defined $ARGV[3]) {
89         $off = $ARGV[3];
90     }
91     seek($file, SEEK_SET, $off);
92     if ($ARGV[1] eq 'r') {
93         read($file, my $data, $size);
94         print $data;
95     }
96     else {
97         read(STDIN, my $data, $size);
98         print $file $data;
99     }
100 }
101 else {
102     usage();
103 }
104
105 close($file);