use strict; # buffer a file for block read # receive BLfilename # send ? or ! # iff ! send 16-bit block count sub blockload($) { my $req = shift; my ($head, $fname, $l, $m); my @names; if ($::blockmode != 0) { print "Buffering a new file without closing the old one!\n"; $::blockmode = 0; $::block = (); } if ($::cd =~ /\.d64$/i) { # handle d64 loading loadblockd64($req); goto BL_DONE; } $req = pettoa($req); # does it look like an URL? if ($req =~ /^[a-zA-Z]+:\/\//) { loadblockurl($req); goto BL_DONE; } ($head, $fname, $_) = splithead($req); @names = glob($fname); # take care of any wildcards $fname = $names[0]; if (! -e $fname) { print "$fname doesn't exist\n"; sendc("?"); # doesn't exist goto BL_DONE; } if (!-f $fname) { print "$req is not a file\n"; sendc("?"); # not a file goto BL_DONE; } if (-z $fname) { print "$req is empty\n"; sendc("?"); # empty goto BL_DONE; } print "buffering $fname for block I/O\n"; if (open(FILE, $fname)) { my $file = ""; my $i = 0; binmode(FILE); while (read(FILE, $::block[$i++], 256) > 0) { ; } close(FILE); if (!defined($::block[$#::block]) || length($::block[$#::block]) == 0) { pop(@::block); } print "buffered " . ($#::block+1) . " blocks\n"; # low and high byte of block count $l = chr(($#::block + 1) & 255); $m = chr(($#::block + 1) >> 8); sendc("!"); sendc($l . $m); $::blockmode = 1; } else { print "couldn't read from $fname\n"; sendc("?"); } BL_DONE: } # open file for block write # receive BSfilename # send ? or . sub blocksave($) { print "block save unimplemented\n"; sendc("?"); } # close file opened for block I/O sub blockclose() { if ($::blockmode == 0) { print "blockclose called without buffered data!\n"; sendc("?"); } elsif ($::blockmode == 1) { $::block = (); $::blockmode = 0; print "closed block buffer\n"; sendc("."); } elsif ($::blockmode == 2) { $::blockmode = 0; print "this is suppsed to be unimplemented. wtf?\n"; sendc("?"); } } # read a block from the buffer # receive BR[16-bit block number][8-bit block count] # send ? or ! # iff ! send 8-bit block length, data, and checksum for each block # (checksum is sum of block data mod 256) sub blockread($) { my $req = shift; my $block; my $count; my $b; # blockload before blockread if ($#::block < 0) { print "block read failure, no file buffered!\n"; sendc("?"); goto BR_DONE; } $block = unpack("S", substr($req,0,2)); $count = unpack("C", substr($req,2,1)); # block count should be at least 1 unless ($count > 0) { print "request for 0 blocks\n"; sendc("?"); goto BR_DONE; } # check if requested blocks are buffered foreach $b ($block .. ($block + $count - 1)) { unless (defined($::block[$b])) { print "request for empty block $b\n"; sendc("?"); goto BR_DONE; } } if ($count == 1) { print "sending block $block\n"; } else { print "sending blocks $block to " . ($block + $count - 1) . "\n"; } # send success sendc("!"); foreach $b ($block .. ($block + $count - 1)) { # send block length - 1 sendc(chr(length($::block[$b])-1)); # send block sendc($::block[$b]); # send checksum sendc(chr(checksum($::block[$b]))); } BR_DONE: } # write a block to the buffer # receive BW[16-bit block number], length, data, and checksum # (checksum is sum of all data mod 256) # send ? or . sub blockwrite($) { my $req = shift; my $block; if ($#::block < 0) { print "block write failure, no file buffered!\n"; sendc("?"); } $block = unpack("S", $req); print "block write unimplemented\n"; sendc("?"); } sub checksum($) { my $data = shift; my $cksum = 0; foreach (split(//, $data)) { $cksum += ord($_); } return($cksum & 255); } return(1);