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 )