Crypt-IDA

 view release on metacpan or  search on metacpan

lib/Crypt/IDA/ShareFile.pm  view on Meta::CPAN

	 $bytes_to_write=$override_bytes;
       } else {
	 $bytes_to_write=$default_bytes_per_write;
       }

       # Writing is a little easier than reading, but we have to take
       # care if the number passed is too large to fit in the
       # requested number of bytes.  If it's too large a warning will
       # be emitted and we discard any extra *high* bits.

       my $buf="";

       if ($num >= 256 ** $bytes_to_write) {
	 carp "ostream: Number too large. Discarded high bits.";
	 $num %= (256 ** ($bytes_to_write) - 1);
       }

       my $hex_format="H" . ($bytes_to_write * 2);
       $buf=pack $hex_format, sprintf "%0*x", $bytes_to_write*2, $num;
       syswrite $fh,$buf,$bytes_to_write;

     },
     EOF      => sub { 0; },
     FILENAME => sub { return $filename; },
     FLUSH    => sub { 0; },
     SEEK     => sub { seek $fh, shift, 0; },
     TELL     => sub { tell $fh; },
     CLOSE    => sub { close $fh; }
    };
  return $methods;		# be explicit
}

# Routines to read/write share file header
#
# header version 1
#
# bytes  name           value
# 2      magic          marker for "Share File" format; "SF" = {5346}
# 1      version        file format version = 1
# 1      options        options bits (see below)
# 1-2    k,quorum       quorum k-value (set both names on read)
# 1-2    s,security     security level s-value (width in bytes)
# var    chunk_start    absolute offset of chunk in file
# var    chunk_next     absolute offset of next chunk in file
# var    transform      transform matrix row
#
# The options bits are as follows:
#
# Bit    name           Settings
# 0      opt_large_k    Large (2-byte) k value?
# 1 	 opt_large_w    Large (2-byte) s value?
# 2 	 opt_final      Final chunk in file? (1=full file/final chunk)
# 3 	 opt_transform  Is transform data included?
#
# Note that the chunk_next field is 1 greater than the actual offset
# of the chunk end. In other words, the chunk ranges from the byte
# starting at chunk_start up to, but not including the byte at
# chunk_next. That's why it's called chunk_next rather than chunk_end.
#
# More on this: it might seem that it's ok to refuse to split a
# zero-length file, but if we're using this for backups, it's not a
# good idea to fail just because we don't like zero-length
# files. Also, splitting a zero-length file might be useful in some
# cases, since we might be interested in just creating and storing a
# transform matrix for later use, or maybe generating test cases or
# debugging a matrix inverse routine.

sub sf_read_ida_header {
  my $istream=shift;		  # assume istream is at start of file
  my $header_info={};   	  # values will be returned in this hash

  #warn "Reading header from istream " . ($istream->{FILENAME}->()) . "\n";

  # When calling this routine the caller can specify any
  # previously-read values for k, s, and so on and have us check the
  # values in the current header against these values for consistency.
  # This implies that all the shares we're being presented for
  # processing will combine to form a single chunk (or full file). If
  # this is the first share header being read, the following may be
  # undefined. We store any read values in the returned hash, so it's
  # up to the caller to take them out and pass them back to us when
  # reading the next header in the batch.
  my ($k,$w,$start,$next,$hdr)=@_;

  my $header_size=0;		  # we also send this back in hash

  # error reporting
  $header_info->{header_error}=0;   # 0=no error, 1=failure
  $header_info->{error_message}=""; # text of error

  # use a local subroutine to save the tedium of checking for eof and
  # doing conversion of input. Updates variables from our local scope
  # directly, so we don't need to pass them in or out. (Actually,
  # technically speaking, this creates an anonymous closure and
  # locally assigns a name to it for the current scope, but it's
  # pretty much the same thing as a local subroutine)
  local *read_some = sub {
    my ($bytes,$field,$conversion)=@_;
    my ($vec,$hex);
    if ($vec=$istream->{READ}->($bytes), defined($vec)) {
      if (defined ($conversion)) {
	if ($conversion eq "hex") {
	  $vec=sprintf "%*x", $bytes, $vec;
	} elsif ($conversion eq "dec") {
	  $vec=$vec;		# istream already returns integers
	} else {
	  die "Unknown format conversion (use undef, hex or dec)\n";
	}
      }
      $header_info->{$field}=$vec;
      $header_size+=$bytes;
      return 1;			# read some? got some.
    } else {
      $header_info->{error}++;
      $header_info->{error_message}="Premature end of stream\n";
      return 0;                 # read some? got none!
    }
  };

  # same idea for saving and reporting errors
  local *header_error = sub {



( run in 2.209 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )