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