+# set the object store in the ext2 formatted block device
+sub Filesystem {
+ my $filesystem = shift;
+ $filesystem = "/dev/loop0" unless $filesystem;
+
+ $::filesystem = $filesystem;
+ if (!defined($::st = stat($filesystem))) {
+ die "Unable to stat $filesystem.\n";
+ }
+}
+
+# select the OBD device we talk to
+sub Device {
+ my $device = shift;
+
+ if (! $device ) {
+ $device = "/dev/obd0";
+ }
+ $::device = $device;
+ # Open the device, as we need an FD for the ioctl
+ sysopen(DEV_OBD, $device, 0) || die "Cannot open $device";
+ print "Device now $device\n";
+}
+
+
+
+sub Attach {
+ my $err = 0;
+ my $type = shift;
+ my $data;
+ my $datalen = 0;
+
+ if ($type eq "obdscsi" ) {
+ my $adapter = shift;
+ my $bus = shift;
+ my $tid = shift;
+ my $lun = shift;
+ $data = pack("iiiii", $adapter, $bus, $tid, $lun, $size);
+ $datalen = 4 * 4;
+ }
+
+ my $packed = pack("Lipip", $::client_id, length($type), $type, $datalen, $data);
+
+ my $rc = ioctl(DEV_OBD, &OBD_IOC_ATTACH, $packed);
+
+ if (!defined $rc) {
+ print STDERR "ioctl failed: $!\n";
+ } elsif ($rc eq "0 but true") {
+ print "Finished (success)\n";
+ } else {
+ print "ioctl returned error code $rc.\n";
+ }
+}
+
+sub Detach {
+ my $err = 0;
+ my $data = "";
+ my $rc = ioctl(DEV_OBD, &OBD_IOC_DETACH, $data);
+
+ if (!defined $rc) {
+ print STDERR "ioctl failed: $!\n";
+ } elsif ($rc eq "0 but true") {
+ print "Finished (success)\n";
+ } else {
+ print "ioctl returned error code $rc.\n";
+ }
+}
+
+
+
+sub TestIterator {
+ my $err = 0;
+ my $type = "ext2_obd";
+
+ $data = pack("i", 4711);
+ $datalen = 4;
+
+ my $len = length($type);
+ my $cl = length($data);
+ my $add = pack("p", $data);
+ print "type $type (len $len), datalen $datalen ($cl)\n";
+ my $packed = pack("Lipip", $::client_id, length($type), $type, $datalen, $data);
+
+ my $rc = ioctl(DEV_OBD, &OBD_EXT2_RUNIT, $packed);
+
+ if (!defined $rc) {
+ print STDERR "ioctl failed: $!\n";
+ } elsif ($rc eq "0 but true") {
+ print "Finished (success)\n";
+ } else {
+ print "ioctl returned error code $rc.\n";
+ }
+}
+
+sub SnapPrint {
+ my $err = 0;
+ my $type = "snap_obd";
+ my $snaptableno = shift;
+
+ $data = pack("i", $snaptableno);
+ $datalen = 4;
+
+ my $len = length($type);
+ my $cl = length($data);
+ my $add = pack("p", $data);
+ print "type $type (len $len), datalen $datalen ($cl)\n";
+ my $packed = pack("Lipip", $::client_id, length($type), $type, $datalen, $data);
+
+ my $rc = ioctl(DEV_OBD, &OBD_SNAP_PRINTTABLE, $packed);
+
+ if (!defined $rc) {
+ print STDERR "ioctl failed: $!\n";
+ } elsif ($rc eq "0 but true") {
+ print "Finished (success)\n";
+ } else {
+ print "ioctl returned error code $rc.\n";
+ }
+}
+
+sub SnapSetTable {
+ my $err = 0;
+ my $type = "snap_obd";
+ my $snaptableno = shift;
+ my $file = shift;
+ my $snapcount;
+ my $table = {};
+ my $data;
+ my $datalen = 0;
+
+ if ( ! -f $file ) {
+ print "No such file $file\n";
+ }
+
+ $table = ReadSnapShotTable($file);
+
+ $snapcount = keys %{$table};
+ print "Snapcount $snapcount\n";
+
+ if ( ! defined $table->{0} ) {
+ print "No current snapshot in table! First make one\n";
+ return ;
+ }
+ $data = pack("ii", $snaptableno, $snapcount);
+ $datalen = 2 * 4;
+ foreach my $time (sort keys %{$table}) {
+ $data .= pack("Ii", $time, $table->{$time});
+ $datalen += 8;
+ }
+
+ my $len = length($type);
+ my $cl = length($data);
+ my $add = pack("p", $data);
+ print "type $type (len $len), datalen $datalen ($cl)\n";
+ my $packed = pack("Lipip", $::client_id, length($type), $type, $datalen, $data);
+
+ my $rc = ioctl(DEV_OBD, &OBD_SNAP_SETTABLE, $packed);
+
+ if (!defined $rc) {
+ print STDERR "ioctl failed: $!\n";
+ } elsif ($rc eq "0 but true") {
+ print "Finished (success)\n";
+ } else {
+ print "ioctl returned error code $rc.\n";
+ }
+}
+
+
+sub SnapAttach {
+ my $err = 0;
+ my $type = "snap_obd";
+ my $snapdev = shift;
+ my $snapno = shift;
+ my $tableno = shift;
+ my $snapcount;
+ my $data;
+ my $datalen = 0;
+
+# if ( ! -f $file ) {
+# print "No such file $file\n";
+# }
+
+# $table = ReadSnapShotTable($file);
+ $data = pack("iii", $snapdev, $snapno, $tableno);
+ $datalen = 3 * 4;
+
+ my $len = length($type);
+ my $cl = length($data);
+ my $add = pack("p", $data);
+ print "type $type (len $len), datalen $datalen ($cl)\n";
+ my $packed = pack("Lipip", $::client_id, length($type), $type, $datalen, $data);
+
+ my $rc = ioctl(DEV_OBD, &OBD_IOC_ATTACH, $packed);
+
+ if (!defined $rc) {
+ print STDERR "ioctl failed: $!\n";
+ } elsif ($rc eq "0 but true") {
+ print "Finished (success)\n";
+ } else {
+ print "ioctl returned error code $rc.\n";
+ }
+}
+
+
+sub SnapShotTable {
+
+ my $file = &readl("enter file name: ");
+ if ( ! -f $file ) {
+ `touch $file`;
+ }
+ my $table = ReadSnapShotTable($file);
+
+ again:
+ PrintSnapShotTable($table);
+ my $action = &readl("Add, Delete or Quit [adq]: ");
+ goto done if ($action =~ "^q.*" );
+ goto add if ($action =~ "^a.*");
+ goto del if ($action =~ "^d.*");
+ goto again;
+
+ add:
+ my $idx = &readl("enter index where you want this snapshot: ");
+ my $time = &readl("enter time or 'now' or 'current': ");
+ my $oldtime = SnapFindTimeFromIdx($idx, $table);
+ if (defined $oldtime) {
+ print "This already exists, first clean up\n";
+ goto again;
+ }
+
+ if ( $time eq 'now' ) {
+ $time = time;
+ } elsif ( $time eq 'current' ) {
+ $time = 0;
+ }
+ $table->{$time} = $idx;
+ goto again;
+
+ del:
+ $didx = &readl("Enter index to delete: ");
+ my $deltime = SnapFindTimeFromIdx($didx, $table);
+ delete $table->{$deltime} if defined $deltime;
+ goto again;
+
+ done:
+ my $ok = &readl("OK with new table? [Yn]: ");
+ unless ( $ok eq "no" ) {
+ WriteSnapShotTable($file, $table);
+ }
+}
+
+sub SnapFindTimeFromIdx {
+ my $idx = shift;
+ my $table = shift;
+
+ foreach my $time ( keys %{$table} ) {
+ if ( $table->{$time} == $idx ) {
+ return $time;
+ }
+ }
+ undef;
+}
+
+sub PrintSnapShotTable {
+ my $table = shift;
+ my $time;
+
+ foreach $time ( sort keys %{$table} ) {
+ my $stime = localtime($time);
+ if ( ! $time ) {
+ $stime = "current";
+ }
+ printf "Time: %s -- Index %d\n", $stime, $table->{$time};
+ }
+}
+
+sub ReadSnapShotTable {
+
+ my $file = shift;
+ my $table = {};
+
+ open FH, "<$file";
+ while ( <FH> ) {
+ my ($time, $index) = split ;
+ $table->{$time} = $index;
+ }
+ close FH;
+
+ PrintSnapShotTable($table);
+
+ return $table;
+}
+
+sub WriteSnapShotTable {
+ my $file = shift;
+ my $table = shift;
+
+ open FH, ">$file";
+ foreach my $time ( sort keys %{$table} ) {
+ print FH "$time $table->{$time}\n";
+ }
+ close FH;
+}
+
+sub Copy {
+ my $err = 0;
+ my $srcid = shift;
+ my $tgtid = shift;
+ my $data = pack("III", $::client_id, $srcid, $tgtid);
+ my $datalen = 12;
+
+ my $packed = pack("ip", $datalen, $data);
+ my $rc = ioctl(DEV_OBD, &OBD_IOC_COPY, $packed);
+
+ if (!defined $rc) {
+ print STDERR "ioctl failed: $!\n";
+ } elsif ($rc eq "0 but true") {
+ print "Finished (success)\n";
+ } else {
+ print "ioctl returned error code $rc.\n";
+ }
+}
+
+sub Migrate {
+ my $err = 0;
+ my $srcid = shift;
+ my $tgtid = shift;
+ my $data = pack("III", $::client_id, $srcid, $tgtid);
+ my $datalen = 12;
+
+ my $packed = pack("ip", $datalen, $data);
+ my $rc = ioctl(DEV_OBD, &OBD_IOC_MIGR, $packed);
+
+ if (!defined $rc) {
+ print STDERR "ioctl failed: $!\n";
+ } elsif ($rc eq "0 but true") {
+ print "Finished (success)\n";
+ } else {
+ print "ioctl returned error code $rc.\n";
+ }
+}
+
+
+sub Format {
+ my $err = 0;
+ my $size = shift;
+ my $data = pack("i", $size);
+ my $datalen = 4;
+
+ my $packed = pack("ip", $datalen, $data);
+ my $rc = ioctl(DEV_OBD, &OBD_IOC_FORMATOBD, $packed);
+
+ if (!defined $rc) {
+ print STDERR "ioctl failed: $!\n";
+ } elsif ($rc eq "0 but true") {
+ print "Finished (success)\n";
+ } else {
+ print "ioctl returned error code $rc.\n";
+ }
+}
+
+sub Partition {
+ my $err = 0;
+ my $partno = shift;
+ my $size = shift;
+ my $data = pack("ii", $partno, $size);
+ my $datalen = 2 * 4;
+
+ my $packed = pack("ip", $datalen, $data);
+ my $rc = ioctl(DEV_OBD, &OBD_IOC_PARTITION, $packed);
+
+ if (!defined $rc) {
+ print STDERR "ioctl failed: $!\n";
+ } elsif ($rc eq "0 but true") {
+ print "Finished (success)\n";
+ } else {
+ print "ioctl returned error code $rc.\n";
+ }
+}
+