+sub Getattr {
+ if (!defined($::client_id)) {
+ print "You must first ``connect''.\n";
+ return;
+ }
+
+ my $inode = shift;
+
+ if (!defined($inode) || scalar($inode) < 1) {
+ print "invalid arguments; type \"help getattr\" for a synopsis\n";
+ return;
+ }
+
+ # see Setattr
+ my $packed = pack("ILsx2lLLLI", $::client_id, $inode, 0, 0, 0, 0, 0, 0, 0,
+ 0);
+ my $rc = ioctl(DEV_OBD, &OBD_IOC_GETATTR, $packed);
+
+ if (!defined $rc) {
+ print STDERR "ioctl failed: $!\n";
+ } elsif ($rc eq "0 but true") {
+ my ($valid, $mode, $uid, $gid, $size, $atime, $mtime, $ctime, $flags);
+ ($valid, $mode, $uid, $gid, $size, $atime, $mtime, $ctime, $flags) =
+ unpack("ISssx2lLLLI", $packed);
+
+ printf("Inode: %d Mode: %o\n", $inode, $mode);
+ printf("User: %6d Group: %6d Size: %d\n", $uid, $gid, $size);
+ printf("ctime: %08lx -- %s\n", $ctime, scalar(gmtime($ctime)));
+ printf("atime: %08lx -- %s\n", $atime, scalar(gmtime($atime)));
+ printf("mtime: %08lx -- %s\n", $mtime, scalar(gmtime($mtime)));
+ printf("flags: %08x\n", $flags);
+ print "Finished (success)\n";
+ } else {
+ print "ioctl returned error code $rc.\n";
+ }
+}
+
+sub Setattr {
+ if (!defined($::client_id)) {
+ print "You must first ``connect''.\n";
+ return;
+ }
+
+ my $inode = shift;
+ my $valid = 0;
+ my $mode = oct(shift);
+ my $uid = shift;
+ my $gid = shift;
+ my $size = shift;
+ my $atime = shift;
+ my $mtime = shift;
+ my $ctime = shift;
+
+ if (defined($uid)) {
+ $valid |= &ATTR_UID;
+ }
+ if (defined($gid)) {
+ $valid |= &ATTR_GID;
+ }
+ if (defined($size)) {
+ $valid |= &ATTR_SIZE;
+ }
+ if (defined($atime)) {
+ $valid |= &ATTR_ATIME;
+ }
+ if (defined($mtime)) {
+ $valid |= &ATTR_MTIME;
+ }
+ if (defined($ctime)) {
+ $valid |= &ATTR_CTIME;
+ }
+ if (defined($mode)) {
+ $valid |= &ATTR_MODE;
+ }
+
+ if (!defined($inode) || scalar($inode) < 1) {
+ print "invalid arguments; type \"help setattr\" for a synopsis\n";
+ return;
+ }
+
+ #struct iattr {
+ # unsigned int ia_valid; (32)
+ # umode_t ia_mode; (16)
+ # uid_t ia_uid; (16)
+ # gid_t ia_gid; (16)
+ # -- 16 bit alignment here! --
+ # off_t ia_size; (32)
+ # time_t ia_atime; (32)
+ # time_t ia_mtime; (32)
+ # time_t ia_ctime; (32)
+ # unsigned int ia_attr_flags; (32)
+ #};
+
+ printf "valid is %x, mode is %o\n", $valid, $mode;
+ my $packed = pack("ILLSssx2ILLLL", $::client_id, $inode, $valid, $mode,
+ $uid, $gid, $size, $atime, $mtime, $ctime, 0);
+ my $rc = ioctl(DEV_OBD, &OBD_IOC_SETATTR, $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 Read {
+ if (!defined($::client_id)) {
+ print "You must first ``connect''.\n";
+ return;
+ }
+
+ my $inode = shift;
+ my $count = shift;
+ my $offset = shift;
+
+ if (!defined($inode) || scalar($inode) < 1 || !defined($count) ||
+ $count < 1 || (defined($offset) && $offset < 0)) {
+ print "invalid arguments; type \"help read\" for a synopsis\n";
+ return;
+ }
+
+ if (!defined($offset)) {
+ $offset = 0;
+ }
+
+ print("Reading $count bytes starting at byte $offset from object " .
+ "$inode...\n");
+
+ # "allocate" a large enough buffer
+ my $buf = sprintf("%${count}s", " ");
+ die "suck" if (length($buf) != $count);
+
+ # the perl we're using doesn't support pack type Q, and offset is 64 bits
+ my $packed = pack("ILpLLL", $::client_id, $inode, $buf, $count, $offset, 0);
+
+ my $rc = ioctl(DEV_OBD, &OBD_IOC_READ, $packed);
+
+ $retval = unpack("l", $packed);
+
+ if (!defined $rc) {
+ print STDERR "ioctl failed: $!\n";
+ } elsif ($rc eq "0 but true") {
+ if ($retval >= 0) {
+ print substr($buf, 0, $retval);
+ print "\nRead $retval of an attempted $count bytes.\n";
+ print "Finished (success)\n";
+ } else {
+ print "Finished (error $retval)\n";
+ }
+ } else {
+ print "ioctl returned error code $rc.\n";
+ }
+}
+
+sub Write {
+ if (!defined($::client_id)) {
+ print "You must first ``connect''.\n";
+ return;
+ }
+
+ my $inode = shift;
+ my $offset = shift;
+ my $text = join(' ', @_);
+ my $count = length($text);
+
+ if (!defined($inode) || scalar($inode) < 1 || !defined($offset) ||
+ scalar($offset) < 0) {
+ print "invalid arguments; type \"help write\" for a synopsis\n";
+ return;
+ }
+
+ if (!defined($text)) {
+ $text = "";
+ $count = 0;
+ }
+
+ print("Writing $count bytes starting at byte $offset to object " .
+ "$inode...\n");
+
+ # the perl we're using doesn't support pack type Q
+ my $packed = pack("ILpLLL", $::client_id, $inode, $text, $count, $offset, 0);
+ my $rc = ioctl(DEV_OBD, &OBD_IOC_WRITE, $packed);
+
+ $retval = unpack("l", $packed);
+
+ if (!defined $rc) {
+ print STDERR "ioctl failed: $!\n";
+ } elsif ($rc eq "0 but true") {
+ if ($retval >= 0) {
+ print "\nWrote $retval of an attempted $count bytes.\n";
+ print "Finished (success)\n";
+ } else {
+ print "Finished (error $retval)\n";
+ }
+ } else {
+ print "ioctl returned error code $rc.\n";
+ }
+}
+