4 BEGIN { require "asm/errno.ph" };
5 BEGIN { require "asm/ioctl.ph" };
7 # p2ph generated invalid macros for ioctl stuff, so I override some of it here
8 eval 'sub OBD_IOC_CREATE () { &_IOC(2, ord(\'f\'), 3, 4);}' unless
9 defined(&OBD_IOC_CREATE);
10 eval 'sub OBD_IOC_SETUP () { &_IOC(1, ord(\'f\'), 4, 4);}' unless
11 defined(&OBD_IOC_SETUP);
12 eval 'sub OBD_IOC_SYNC () { &_IOC(2, ord(\'f\'), 5, 4);}' unless
13 defined(&OBD_IOC_SYNC);
14 eval 'sub OBD_IOC_DESTROY () { &_IOC(1, ord(\'f\'), 6, 4);}' unless
15 defined(&OBD_IOC_DESTROY);
16 eval 'sub OBD_IOC_DEC_USE_COUNT () { &_IOC(0, ord(\'f\'), 8, 0);}' unless
17 defined(&OBD_IOC_DEC_USE_COUNT);
18 eval 'sub OBD_IOC_READ () { &_IOC(3, ord(\'f\'), 10, 4);}' unless
19 defined(&OBD_IOC_READ);
28 my ($device, $filesystem);
29 # startup options (I'll replace these when I have some to replace with)
30 GetOptions("device=s" => \$device, "fs=s" => $filesystem) || die "Getoptions";
32 $device = "/dev/obd" unless $device;
33 $filesystem = "/dev/loop0" unless $filesystem;
35 # get a console for the app
36 my $term = new Term::ReadLine 'obdcontrol ';
37 my $attribs = $term->Attribs;
38 $term->ornaments('md,me,,'); # bold face prompt
40 # make sure stdout is not buffered
48 ('create' => {func => "Create", doc => "create: creates a new inode"},
49 'setup' => {func => "Setup", doc => "setup: initializes the environment"},
50 'sync' => {func => "Sync", doc => "sync: flushes buffers to disk"},
51 'destroy' => {func => "Destroy", doc => "setup: destroys an inode"},
52 'dec_use_count' => {func => "Decusecount", doc => "decreases the module use count so that the module can be removed following an oops"},
53 'read' => {func => "Read", doc => "read <inode> <count> [offset]"},
54 'help' => {func => \&Help, doc => "help: this message"},
55 'quit' => {func => \&Quit, doc => "see \"exit\""},
56 'exit' => {func => \&Quit, doc => "see \"quit\""}
60 # setup completion function
62 my @jcm_cmd_list = keys %commands;
64 $attribs->{attempted_completion_function} = \&completeme;
65 #------------------------------------------------------------------------------
66 # Open the device, as we need an FD for the ioctl
67 sysopen(DEV_OBD, $device, 0);
69 if (!defined($::st = stat($filesystem))) {
70 die "Unable to stat $filesystem.\n";
73 # Get on with the show
76 #------------------------------------------------------------------------------
78 my ($text, $line, $start, $end) = @_;
79 if (substr($line, 0, $start) =~ /^\s*$/) {
80 $attribs->{completion_word} = \@jcm_cmd_list;
81 return $term->completion_matches($text,
82 $attribs->{'list_completion_function'});
89 my @completions = completeme($given, $given, 0, length($given));
90 if ($#completions == 0) {
91 $name = shift @completions;
97 # start making requests
100 $line = $term->readline("obdcontrol > ");
108 my @arg = split(' ', $line);
109 my $word = shift @arg;
111 my $cmd = find_command($word);
113 printf STDERR "$word: No such command, or not unique.\n";
117 if ($cmd eq "help" || $cmd eq "exit" || $cmd eq "quit") {
118 return (&{$commands{$cmd}->{func}}(@arg));
122 return (&{$commands{$cmd}->{func}}(@arg));
127 my $packed = pack("L", $::st->rdev());
128 my $rc = ioctl(DEV_OBD, &OBD_IOC_SETUP, $packed);
131 print STDERR "ioctl failed: $!\n";
132 } elsif ($rc eq "0 but true") {
133 print "Finished (success)\n";
135 print "ioctl returned error code $rc.\n";
145 if (defined($quiet) && !($quiet eq "quiet")) {
146 print "syntax: create [number of objects [quiet]]\n";
150 if (!defined($arg) || scalar($arg) < 2) {
151 print "Creating 1 object...\n";
152 $rc = ioctl(DEV_OBD, &OBD_IOC_CREATE, $err);
153 if (!defined($quiet)) {
154 my $ino = unpack("L", $err);
155 print "Created object #$ino.\n";
160 print "Creating " . scalar($arg) . " objects...\n";
161 for ($i = 0; $i < scalar($arg); $i++) {
162 $rc = ioctl(DEV_OBD, &OBD_IOC_CREATE, $err);
163 if (!($rc eq "0 but true") || $err < 0) {
165 } elsif (!defined($quiet)) {
166 my $ino = unpack("L", $err);
167 print "Created object #$ino.\n";
173 print STDERR "ioctl failed: $!\n";
174 } elsif ($rc eq "0 but true") {
175 print "Finished (success)\n";
177 print "ioctl returned error code $rc.\n";
183 my $rc = ioctl(DEV_OBD, &OBD_IOC_SYNC, $err);
186 print STDERR "ioctl failed: $!\n";
187 } elsif ($rc eq "0 but true") {
188 print "Finished (success)\n";
190 print "ioctl returned error code $rc.\n";
197 if (!defined($arg) || scalar($arg) < 1) {
198 print "destroy requires the object number to destroy.\n";
202 print "Destroying object $arg...\n";
203 my $packed = pack("L", $arg);
204 my $rc = ioctl(DEV_OBD, &OBD_IOC_DESTROY, $packed);
207 print STDERR "ioctl failed: $!\n";
208 } elsif ($rc eq "0 but true") {
209 print "Finished (success)\n";
211 print "ioctl returned error code $rc.\n";
220 if (!defined($inode) || scalar($inode) < 1 || !defined($count) ||
221 $count < 1 || (defined($offset) && $offset < 0)) {
222 print "invalid arguments; type \"help read\" for a synopsis\n";
226 if (!defined($offset)) {
230 print("Reading $count bytes starting at byte $offset from object " .
233 # "allocate" a large enough buffer
234 my $buf = sprintf("%${count}s", " ");
235 die "suck" if (length($buf) != $count);
237 my $packed = pack("LpLLL", $inode, $buf, $count, 0, $offset);
238 my $rc = ioctl(DEV_OBD, &OBD_IOC_READ, $packed);
240 $retval = unpack("x4x4L", $packed);
243 print STDERR "ioctl failed: $!\n";
244 } elsif ($rc eq "0 but true") {
246 print substr($buf, 0, $retval);
247 print "\nRead $retval of an attempted $count bytes.\n";
248 print "Finished (success)\n";
250 print "Finished (error $retval)\n";
253 print "ioctl returned error code $rc.\n";
261 if (!defined($arg) || scalar($arg) < 1 || scalar($arg) > 32) {
265 print "Preallocating $arg inodes...\n";
266 my $packed = pack("Lx128", $arg); # alloc, inodes[32]
267 my $rc = ioctl(DEV_OBD, &OBD_IOC_PREALLOCATE, $packed);
270 print STDERR "ioctl failed: $!\n";
271 } elsif ($rc eq "0 but true") {
272 my $alloc = unpack("L", $packed);
273 my @inodes = unpack("L32", $packed);
276 print "Got $alloc inodes: ";
277 for ($i = 1; $i <= $alloc; ++$i) {
278 print $inodes[$i] . " ";
280 print "\nFinished (success)\n";
282 print "ioctl returned error code $rc.\n";
287 my $rc = ioctl(DEV_OBD, &OBD_IOC_DEC_USE_COUNT, 0);
290 print STDERR "ioctl failed: $!\n";
291 } elsif ($rc eq "0 but true") {
292 print "Finished (success)\n";
294 print "ioctl returned error code $rc.\n";
301 if ( !$arg || !$commands{$arg} ) {
302 print "Comands: ", join( ' ', @jcm_cmd_list), "\n";
304 print "Usage: " . $commands{$arg}->{doc} . "\n";