ghettofinger has asked for the wisdom of the Perl Monks concerning the following question:

Wise Monks,

I was asked to put together a script that will write hex to a block device until it is full using a variable for the block size. I think that I have accomplished this with the script below, with help from the chatterbox (thanks everyone).

#!/usr/bin/perl die "Usage: hexperlscript <blocksize> <destination file>\n" unless @AR +GV == 2; ($input, $output) = @ARGV; if ($input % 512 == 0) { $input = $input * .5; open ( DEST, '>>', $output ) or die "Cannot create ouput file. $! \n"; while (1 < 2) { for(0..0xff){$n=sprintf"%02x",$_;print DEST "$n" x $input;} print DEST "$n" x $input; } } else { print "Blocksize must be divisable by 512.\nExiting.\n"; END; }
My problem now is, how can I terminate the script? I was hoping that when the block device was full, it would just error out, and then I could work it from there, but it doesn't. When this is run against /dev/hdaX it works, but does not terminate. Is there a way in which I can write to the device until it is full and then end the script?

A little background: I have some forensics guys that I work with that want to use this in order to test where data is written between two or more drives on a SCSI device. This is really the first script that I have ever put together that does something useful so (as always) all comments are welcome.

Thank you,
ghettofinger

Replies are listed 'Best First'.
Re: Block device status and script termination
by kvale (Monsignor) on Feb 22, 2004 at 23:21 UTC
    It is not clear that the script will atuomatically die upon the block device filling. The print statement will probably fail, however. So I would try something like this (untested):
    #!/usr/bin/perl -w die "Usage: hexperlscript <blocksize> <destination file>\n" unless @AR +GV == 2; my ($input, $output) = @ARGV; die "Blocksize must be divisible by 512.\nExiting.\n" unless $input % +512== 0; $input /= 2; open ( DEST, '>>', $output ) or die "Cannot create ouput file. $! \n"; while (1) { for (0..0xff) { my $n = sprintf "%02x", $_; print DEST $n x $input or die "Could not print: $!\n"; } }

    -Mark

Re: Block device status and script termination
by matija (Priest) on Feb 23, 2004 at 07:52 UTC
    For things that need to work with low-level data like that you'd be much better off using syswrite instead of print.

    Not only will syswrite not bother scanning the string for variable substitutions and such, but syswrite returns the number of bytes actualy written.

    So instead of print DEST "$n" x $input; you should put in $written=syswrite(DEST,($n x $input)); and terminate when $written!=(length($n)*input)

      What? Using syswrite as opposed to print has nothing to do with variable interpolation.

      I think print is good enough in this case, it's just that print may report the error (ENOSPC or else) later than it actually occurs because of buffering, but I dont think this would be a problem in this case. You can probably still get the position of the error with sysseek after print reports the error I think.