File Coverage

blib/lib/Sys/GetRandom/PP.pm
Criterion Covered Total %
statement 45 47 95.7
branch 8 14 57.1
condition 3 9 33.3
subroutine 8 8 100.0
pod 2 2 100.0
total 66 80 82.5


line stmt bran cond sub pod time code
1             package Sys::GetRandom::PP;
2 1     1   157544 use strict;
  1         2  
  1         30  
3 1     1   4 use warnings;
  1         1  
  1         43  
4              
5 1     1   3 use Exporter qw(import);
  1         2  
  1         22  
6 1     1   3 use Carp qw(croak);
  1         1  
  1         60  
7 1     1   357 use Errno qw(EINVAL);
  1         1207  
  1         201  
8              
9 1         1 use constant do {
10 1         12 my %bits_getrandom = (
11             'dragonfly' => 550,
12             'freebsd' => 563,
13             'midnightbsd' => 563,
14             'netbsd' => 91,
15             'openbsd' => 7,
16             'solaris' => 126,
17              
18             'aarch64-linux' => 278,
19             'armv6l-linux' => 384,
20             'i686-linux' => 355,
21             'x86_64-linux' => 318,
22             );
23 1   33     8 my $getrandom = $bits_getrandom{$^O} || do {
24             require Config;
25             my ($arch) = $Config::Config{archname} =~ m{^([^\-]+-[^\-]+)};
26             $bits_getrandom{$arch} || die "Unsupported platform: $arch"
27             };
28             +{
29 1         473 _IS_OPENBSD => $^O eq 'openbsd',
30             _SYS_getrandom => $getrandom,
31             GRND_NONBLOCK => 1,
32             GRND_RANDOM => 2,
33             }
34 1     1   6 };
  1         1  
35              
36             our $VERSION = '0.08_001';
37             $VERSION =~ tr/_//d;
38              
39             our @EXPORT_OK = qw(
40             GRND_RANDOM
41             GRND_NONBLOCK
42             getrandom
43             random_bytes
44             );
45              
46             sub getrandom ($$;$$) {
47 21 50 33 21 1 148691 if (@_ < 2 || @_ > 4) {
48 0         0 croak 'Usage: ' . __PACKAGE__ . '::getrandom($buffer, $length, $flags = 0, $offset = 0)';
49             }
50 21         33 my $bufref = \$_[0];
51 21         38 my (undef, $length, $flags, $offset) = @_;
52 21         30 $length |= 0;
53 21         23 $flags |= 0;
54 21         21 $offset |= 0;
55 21         30 $$bufref .= '';
56              
57 21         34 my $realbuf = "\0" x $length;
58              
59 21         21 my $r;
60 21         21 if (_IS_OPENBSD) {
61             # validate, but ignore
62             if ($flags & ~(GRND_NONBLOCK | GRND_RANDOM)) {
63             $! = EINVAL;
64             return undef;
65             }
66             $r = syscall _SYS_getrandom, $realbuf, $length;
67             if ($r == -1) {
68             return undef;
69             }
70             $r = $length;
71             } else {
72 21         101 $r = syscall _SYS_getrandom, $realbuf, $length, $flags;
73 21 50       37 if ($r == -1) {
74 0         0 return undef;
75             }
76 21         50 substr($realbuf, $r) = '';
77             }
78              
79              
80 21         30 my $dlen = $offset - length $$bufref;
81 21 100       42 $$bufref .= "\0" x $dlen
82             if $dlen > 0;
83 21         28 substr($$bufref, $offset) = $realbuf;
84              
85 21         54 $r
86             }
87              
88             sub random_bytes {
89 1     1 1 549 my ($n) = @_;
90 1         2 $n |= 0;
91 1 50 33     7 $n >= 0 && $n <= 256
92             or croak "Argument to random_bytes() must be an integer between 0 and 256, not $n";
93 1 50       3 return '' if $n == 0;
94 1 50       2 defined(my $r = getrandom(my $buf, $n))
95             or die "Internal error: getrandom(\$buf, $n) failed: $!";
96 1 50       2 $r == $n
97             or die "Internal error: getrandom(\$buf, $n) returned $r";
98 1         4 $buf
99             }
100              
101             1
102             __END__