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);
26 my ($device, $filesystem);
27 # startup options (I'll replace these when I have some to replace with)
28 GetOptions("device=s" => \$device, "fs=s" => $filesystem) || die "Getoptions";
30 $device = "/dev/obd" unless $device;
31 $filesystem = "/dev/loop0" unless $filesystem;
33 # get a console for the app
34 my $term = new Term::ReadLine 'obdcontrol ';
35 my $attribs = $term->Attribs;
36 $term->ornaments('md,me,,'); # bold face prompt
38 # make sure stdout is not buffered
46 ('create' => {func => "Create", doc => "create: creates a new inode"},
47 'setup' => {func => "Setup", doc => "setup: initializes the environment"},
48 'sync' => {func => "Sync", doc => "sync: flushes buffers to disk"},
49 'destroy' => {func => "Destroy", doc => "setup: destroys an inode"},
50 'dec_use_count' => {func => "Decusecount", doc => "decreases the module use count so that it can be unmounted following an oops"},
51 'help' => {func => \&Help, doc => "help: this message"},
52 'quit' => {func => \&Quit, doc => "see \"exit\""},
53 'exit' => {func => \&Quit, doc => "see \"quit\""}
57 # setup completion function
59 my @jcm_cmd_list = keys %commands;
61 $attribs->{attempted_completion_function} = \&completeme;
62 #------------------------------------------------------------------------------
63 # Open the device, as we need an FD for the ioctl
64 sysopen(DEV_OBD, $device, 0);
66 if (!defined($::st = stat($filesystem))) {
67 die "Unable to stat $filesystem.\n";
70 # Get on with the show
73 #------------------------------------------------------------------------------
75 my ($text, $line, $start, $end) = @_;
76 if (substr($line, 0, $start) =~ /^\s*$/) {
77 $attribs->{completion_word} = \@jcm_cmd_list;
78 return $term->completion_matches($text,
79 $attribs->{'list_completion_function'});
86 my @completions = completeme($given, $given, 0, length($given));
87 if ($#completions == 0) {
88 $name = shift @completions;
94 # start making requests
97 $line = $term->readline("obdcontrol > ");
105 my @arg = split(' ', $line);
106 my $word = shift @arg;
108 my $cmd = find_command($word);
110 printf STDERR "$word: No such command, or not unique.\n";
114 if ($cmd eq "help" || $cmd eq "exit" || $cmd eq "quit") {
115 return (&{$commands{$cmd}->{func}}(@arg));
119 return (&{$commands{$cmd}->{func}}(@arg));
124 my $packed = pack("L", $::st->rdev());
125 my $rc = ioctl(DEV_OBD, &OBD_IOC_SETUP, $packed);
128 print STDERR "ioctl failed: $!\n";
129 } elsif ($rc eq "0 but true") {
130 print "Finished (success)\n";
132 print "ioctl returned error code $rc.\n";
142 if (defined($quiet) && !($quiet eq "quiet")) {
143 print "syntax: create [number of objects [quiet]]\n";
147 if (!defined($arg) || scalar($arg) < 2) {
148 print "Creating 1 object...\n";
149 $rc = ioctl(DEV_OBD, &OBD_IOC_CREATE, $err);
150 if (!defined($quiet)) {
151 my $ino = unpack("L", $err);
152 print "Created object #$ino.\n";
157 print "Creating " . scalar($arg) . " objects...\n";
158 for ($i = 0; $i < scalar($arg); $i++) {
159 $rc = ioctl(DEV_OBD, &OBD_IOC_CREATE, $err);
160 if (!($rc eq "0 but true") || $err < 0) {
162 } elsif (!defined($quiet)) {
163 my $ino = unpack("L", $err);
164 print "Created object #$ino.\n";
170 print STDERR "ioctl failed: $!\n";
171 } elsif ($rc eq "0 but true") {
172 print "Finished (success)\n";
174 print "ioctl returned error code $rc.\n";
180 my $rc = ioctl(DEV_OBD, &OBD_IOC_SYNC, $err);
183 print STDERR "ioctl failed: $!\n";
184 } elsif ($rc eq "0 but true") {
185 print "Finished (success)\n";
187 print "ioctl returned error code $rc.\n";
194 if (!defined($arg) || scalar($arg) < 1) {
195 print "destroy requires the object number to destroy.\n";
199 print "Destroying object $arg...\n";
200 my $packed = pack("L", $arg);
201 my $rc = ioctl(DEV_OBD, &OBD_IOC_DESTROY, $packed);
204 print STDERR "ioctl failed: $!\n";
205 } elsif ($rc eq "0 but true") {
206 print "Finished (success)\n";
208 print "ioctl returned error code $rc.\n";
215 if (!defined($arg) || scalar($arg) < 1 || scalar($arg) > 32) {
219 print "Preallocating $arg inodes...\n";
220 my $packed = pack("Lx128", $arg); # alloc, inodes[32]
221 my $rc = ioctl(DEV_OBD, &OBD_IOC_PREALLOCATE, $packed);
224 print STDERR "ioctl failed: $!\n";
225 } elsif ($rc eq "0 but true") {
226 my $alloc = unpack("L", $packed);
227 my @inodes = unpack("L32", $packed);
230 print "Got $alloc inodes: ";
231 for ($i = 1; $i <= $alloc; ++$i) {
232 print $inodes[$i] . " ";
234 print "\nFinished (success)\n";
236 print "ioctl returned error code $rc.\n";
241 my $rc = ioctl(DEV_OBD, &OBD_IOC_DEC_USE_COUNT, NULL);
244 print STDERR "ioctl failed: $!\n";
245 } elsif ($rc eq "0 but true") {
246 print "Finished (success)\n";
248 print "ioctl returned error code $rc.\n";
255 if ( !$arg || !$commands{$arg} ) {
256 print "Comands: ", join( ' ', @jcm_cmd_list), "\n";
258 print "Usage: " . $commands{$arg}->{doc} . "\n";