| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Sys::Export; |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
our $VERSION = '0.005'; # VERSION |
|
4
|
|
|
|
|
|
|
# ABSTRACT: Export a subset of an OS file tree, for chroot/initrd |
|
5
|
|
|
|
|
|
|
|
|
6
|
18
|
|
|
18
|
|
1224306
|
use v5.26; |
|
|
18
|
|
|
|
|
56
|
|
|
7
|
18
|
|
|
18
|
|
67
|
use warnings; |
|
|
18
|
|
|
|
|
26
|
|
|
|
18
|
|
|
|
|
831
|
|
|
8
|
18
|
|
|
18
|
|
77
|
use experimental qw( signatures ); |
|
|
18
|
|
|
|
|
25
|
|
|
|
18
|
|
|
|
|
108
|
|
|
9
|
18
|
|
|
18
|
|
2231
|
use Carp; |
|
|
18
|
|
|
|
|
31
|
|
|
|
18
|
|
|
|
|
1224
|
|
|
10
|
18
|
|
|
18
|
|
93
|
use Scalar::Util qw( blessed looks_like_number ); |
|
|
18
|
|
|
|
|
28
|
|
|
|
18
|
|
|
|
|
862
|
|
|
11
|
18
|
|
|
18
|
|
7607
|
use Sys::Export::LogAny '$log'; |
|
|
18
|
|
|
|
|
54
|
|
|
|
18
|
|
|
|
|
190
|
|
|
12
|
18
|
|
|
18
|
|
3845
|
use Exporter (); |
|
|
18
|
|
|
|
|
30
|
|
|
|
18
|
|
|
|
|
2841
|
|
|
13
|
|
|
|
|
|
|
BEGIN { |
|
14
|
|
|
|
|
|
|
# Fcntl happily exports macros that don't exist, then fails at runtime. |
|
15
|
|
|
|
|
|
|
# Replace non-existent test macros with 'false', and nonexistent modes with 0. |
|
16
|
18
|
|
|
18
|
|
120
|
require Fcntl; |
|
17
|
306
|
100
|
|
|
|
6915
|
eval { Fcntl->can($_)->($_ =~ /_IS/? (0) : ()); 1 }? Fcntl->import($_) : eval "sub $_ { 0 }" |
|
|
270
|
|
|
|
|
62725
|
|
|
18
|
18
|
100
|
|
5
|
0
|
52
|
for qw( S_ISREG S_ISDIR S_ISLNK S_ISBLK S_ISCHR S_ISFIFO S_ISSOCK S_ISWHT |
|
|
5
|
|
|
0
|
0
|
104
|
|
|
|
0
|
|
|
|
|
0
|
|
|
19
|
|
|
|
|
|
|
S_IFREG S_IFDIR S_IFLNK S_IFBLK S_IFCHR S_IFIFO S_IFSOCK S_IFWHT S_IFMT ); |
|
20
|
|
|
|
|
|
|
} |
|
21
|
|
|
|
|
|
|
our @EXPORT_OK= qw( |
|
22
|
|
|
|
|
|
|
isa_exporter isa_export_dst isa_userdb isa_user isa_group exporter isa_hash isa_array isa_int |
|
23
|
|
|
|
|
|
|
isa_handle isa_pow2 isa_data_ref round_up_to_pow2 round_up_to_multiple map_or_load_file filedata |
|
24
|
|
|
|
|
|
|
add skip find which finish rewrite_path rewrite_user rewrite_group expand_stat_shorthand |
|
25
|
|
|
|
|
|
|
write_file_extent |
|
26
|
|
|
|
|
|
|
S_ISREG S_ISDIR S_ISLNK S_ISBLK S_ISCHR S_ISFIFO S_ISSOCK S_ISWHT |
|
27
|
|
|
|
|
|
|
S_IFREG S_IFDIR S_IFLNK S_IFBLK S_IFCHR S_IFIFO S_IFSOCK S_IFWHT S_IFMT |
|
28
|
|
|
|
|
|
|
); |
|
29
|
|
|
|
|
|
|
our %EXPORT_TAGS= ( |
|
30
|
|
|
|
|
|
|
basic_methods => [qw( exporter add skip find which finish rewrite_path rewrite_user rewrite_group filedata )], |
|
31
|
|
|
|
|
|
|
isa => [qw( isa_exporter isa_export_dst isa_userdb isa_user isa_group isa_hash isa_array isa_handle isa_int isa_pow2 isa_data_ref )], |
|
32
|
|
|
|
|
|
|
stat_modes => [qw( S_IFREG S_IFDIR S_IFLNK S_IFBLK S_IFCHR S_IFIFO S_IFSOCK S_IFWHT S_IFMT )], |
|
33
|
|
|
|
|
|
|
stat_tests => [qw( S_ISREG S_ISDIR S_ISLNK S_ISBLK S_ISCHR S_ISFIFO S_ISSOCK S_ISWHT )], |
|
34
|
|
|
|
|
|
|
); |
|
35
|
|
|
|
|
|
|
my ($is_module_name, $require_module); |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# optional dependency on Module::Runtime. This way if there's any bug in my cheap |
|
38
|
|
|
|
|
|
|
# substitute, the fix is to just install the official module. |
|
39
|
|
|
|
|
|
|
if (eval { require Module::Runtime; }) { |
|
40
|
|
|
|
|
|
|
$is_module_name= \&Module::Runtime::is_module_name; |
|
41
|
|
|
|
|
|
|
$require_module= \&Module::Runtime::require_module; |
|
42
|
|
|
|
|
|
|
} else { |
|
43
|
|
|
|
|
|
|
$is_module_name= sub { $_[0] =~ /^[A-Z_a-z][0-9A-Z_a-z]*(?:::[0-9A-Z_a-z]+)*\z/ }; |
|
44
|
|
|
|
|
|
|
$require_module= sub { require( ($_[0] =~ s{::}{/}gr).'.pm' ) }; |
|
45
|
|
|
|
|
|
|
} |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
sub import { |
|
49
|
41
|
|
|
41
|
|
124
|
my $class= $_[0]; |
|
50
|
41
|
|
|
|
|
85
|
my $caller= caller; |
|
51
|
41
|
|
|
|
|
65
|
my %ctor_opts; |
|
52
|
41
|
|
|
|
|
169
|
for (my $i= 1; $i < $#_; ++$i) { |
|
53
|
111
|
50
|
|
|
|
353
|
if (ref $_[$i] eq 'HASH') { |
|
|
|
100
|
|
|
|
|
|
|
54
|
0
|
|
|
|
|
0
|
%ctor_opts= ( %ctor_opts, %{ splice(@_, $i--, 1) } ); |
|
|
0
|
|
|
|
|
0
|
|
|
55
|
|
|
|
|
|
|
} |
|
56
|
|
|
|
|
|
|
elsif ($_[$i] =~ /^-(type|src|dst|tmp|src_userdb|dst_userdb|rewrite_path|rewrite_user|rewrite_group)\z/) { |
|
57
|
3
|
|
|
|
|
11
|
$ctor_opts{$1}= (splice @_, $i--, 2)[1]; |
|
58
|
|
|
|
|
|
|
} |
|
59
|
|
|
|
|
|
|
} |
|
60
|
41
|
100
|
|
|
|
89
|
if (keys %ctor_opts) { |
|
61
|
1
|
|
|
|
|
3
|
init_global_exporter(%ctor_opts); |
|
62
|
|
|
|
|
|
|
# caller requested the global exporter instance, so also include the standard methods |
|
63
|
|
|
|
|
|
|
# unless it looks like they were more selective about what to import. |
|
64
|
1
|
50
|
|
|
|
8
|
push @_, 'exporter', ':basic_methods' |
|
65
|
|
|
|
|
|
|
unless grep /^(add|:.*methods)\z/, @_; |
|
66
|
|
|
|
|
|
|
} |
|
67
|
41
|
|
|
|
|
190967
|
goto \&Exporter::import; |
|
68
|
|
|
|
|
|
|
} |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
our $exporter; |
|
71
|
0
|
|
|
0
|
1
|
0
|
sub exporter { $exporter } |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
our %osname_to_class= ( |
|
74
|
|
|
|
|
|
|
linux => 'Linux', |
|
75
|
|
|
|
|
|
|
); |
|
76
|
|
|
|
|
|
|
|
|
77
|
1
|
|
|
1
|
1
|
2
|
sub init_global_exporter(%config) { |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
1
|
|
|
78
|
1
|
|
33
|
|
|
3
|
my $type= delete $config{type} // $^O; |
|
79
|
|
|
|
|
|
|
# remap known OS names |
|
80
|
1
|
|
33
|
|
|
5
|
my $class= $osname_to_class{$type} // $type; |
|
81
|
|
|
|
|
|
|
# prefix bare names with namespace |
|
82
|
1
|
50
|
|
|
|
5
|
$class= "Sys::Export::$class" unless $class =~ /::/; |
|
83
|
1
|
50
|
|
|
|
3
|
$is_module_name->($class) or croak "Invalid module name '$class'"; |
|
84
|
|
|
|
|
|
|
# if it fails, die with 'croak' |
|
85
|
1
|
50
|
|
|
|
45
|
eval { $require_module->($class) } or croak "$@"; |
|
|
1
|
|
|
|
|
3
|
|
|
86
|
|
|
|
|
|
|
# now construct one |
|
87
|
1
|
|
|
|
|
8
|
$exporter= $class->new(%config); |
|
88
|
|
|
|
|
|
|
} |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
|
|
91
|
3
|
|
|
3
|
1
|
16
|
sub add { $exporter->add(@_) } |
|
92
|
1
|
|
|
1
|
1
|
11
|
sub skip { $exporter->skip(@_) } |
|
93
|
1
|
|
|
1
|
1
|
9
|
sub find { $exporter->src_find(@_) } |
|
94
|
0
|
|
|
0
|
1
|
0
|
sub which :prototype($) { $exporter->src_which(@_) } |
|
95
|
1
|
|
|
1
|
1
|
3
|
sub finish { $exporter->finish(@_) } |
|
96
|
0
|
|
|
0
|
1
|
0
|
sub rewrite_path { $exporter->rewrite_path(@_) } |
|
97
|
0
|
|
|
0
|
1
|
0
|
sub rewrite_user { $exporter->rewrite_user(@_) } |
|
98
|
0
|
|
|
0
|
1
|
0
|
sub rewrite_group { $exporter->rewrite_group(@_) } |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
101
|
10636
|
|
|
10636
|
1
|
25409
|
sub isa_hash :prototype($) { ref $_[0] eq 'HASH' } |
|
102
|
21099
|
|
|
21099
|
1
|
55733
|
sub isa_array :prototype($) { ref $_[0] eq 'ARRAY' } |
|
103
|
35
|
50
|
33
|
35
|
1
|
493
|
sub isa_handle :prototype($) { ref $_[0] eq 'GLOB' || (ref $_[0] && (ref $_[0])->isa('IO::Handle')) } |
|
104
|
31861
|
100
|
|
31861
|
1
|
106654
|
sub isa_int :prototype($) { looks_like_number($_[0]) && int($_[0]) == $_[0] } |
|
105
|
0
|
0
|
|
0
|
1
|
0
|
sub isa_exporter :prototype($) { blessed($_[0]) && $_[0]->isa('Sys::Export::Exporter') } |
|
106
|
9
|
100
|
66
|
9
|
1
|
163
|
sub isa_export_dst :prototype($) { blessed($_[0]) && $_[0]->can('add') && $_[0]->can('finish') } |
|
107
|
11
|
100
|
66
|
11
|
1
|
64
|
sub isa_userdb :prototype($) { blessed($_[0]) && $_[0]->can('user') && $_[0]->can('group') } |
|
108
|
18
|
100
|
|
18
|
1
|
89
|
sub isa_user :prototype($) { blessed($_[0]) && $_[0]->isa('Sys::Export::Unix::UserDB::User') } |
|
109
|
18
|
100
|
|
18
|
1
|
67
|
sub isa_group :prototype($) { blessed($_[0]) && $_[0]->isa('Sys::Export::Unix::UserDB::Group') } |
|
110
|
1330
|
|
|
1330
|
1
|
4221
|
sub isa_pow2 :prototype($) { !($_[0] & ($_[0]-1)) } |
|
111
|
24
|
50
|
0
|
24
|
1
|
64
|
sub isa_data_ref :prototype($) { ref $_[0] eq 'SCALAR' || blessed($_[0]) && $_[0]->can('as_scalarref') } |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
|
|
114
|
4
|
|
|
4
|
|
7
|
sub _parse_major_minor_data($attrs, $data) { |
|
|
4
|
|
|
|
|
5
|
|
|
|
4
|
|
|
|
|
4
|
|
|
|
4
|
|
|
|
|
4
|
|
|
115
|
4
|
100
|
|
|
|
5
|
@{$attrs}{'rdev_major','rdev_minor'}= isa_array $data? @$data : split(/[,:]/, $data); |
|
|
4
|
|
|
|
|
9
|
|
|
116
|
|
|
|
|
|
|
} |
|
117
|
|
|
|
|
|
|
our %_mode_alias= ( |
|
118
|
|
|
|
|
|
|
file => [ S_IFREG, sub { 0666 & ~umask } ], |
|
119
|
|
|
|
|
|
|
dir => [ S_IFDIR, sub { 0777 & ~umask } ], |
|
120
|
|
|
|
|
|
|
sym => [ S_IFLNK, sub { 0777 } ], |
|
121
|
|
|
|
|
|
|
blk => [ S_IFBLK, sub { 0666 & ~umask }, \&_parse_major_minor_data, ], |
|
122
|
|
|
|
|
|
|
chr => [ S_IFCHR, sub { 0666 & ~umask }, \&_parse_major_minor_data, ], |
|
123
|
|
|
|
|
|
|
fifo => [ S_IFIFO, sub { 0666 & ~umask } ], |
|
124
|
|
|
|
|
|
|
sock => [ S_IFSOCK, sub { 0666 & ~umask } ], |
|
125
|
|
|
|
|
|
|
); |
|
126
|
|
|
|
|
|
|
our @_mode_by_int; |
|
127
|
|
|
|
|
|
|
$_mode_by_int[$_->[0]]= $_ for values %_mode_alias; |
|
128
|
|
|
|
|
|
|
$_mode_by_int[0]= undef; # don't map 0 to any mode |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
sub expand_stat_shorthand { |
|
131
|
10543
|
100
|
66
|
10543
|
1
|
110210
|
@_= @{$_[0]} if @_ == 1 && isa_array $_[0]; |
|
|
10534
|
|
|
|
|
20546
|
|
|
132
|
10543
|
100
|
100
|
|
|
24129
|
my %attrs= @_ > 2 && isa_hash $_[-1]? %{ pop @_ } : (); |
|
|
46
|
|
|
|
|
125
|
|
|
133
|
10543
|
|
|
|
|
15294
|
my ($mode, $name, $data)= @_; |
|
134
|
10543
|
|
|
|
|
10959
|
my $mode_desc; |
|
135
|
10543
|
50
|
|
|
|
14778
|
if (isa_int $mode) { |
|
136
|
0
|
0
|
|
|
|
0
|
$mode_desc= $_mode_by_int[$mode & S_IFMT] |
|
137
|
|
|
|
|
|
|
or carp sprintf("Numeric mode %x doesn't match any known node types", $mode); |
|
138
|
|
|
|
|
|
|
} |
|
139
|
|
|
|
|
|
|
else { |
|
140
|
10543
|
50
|
|
|
|
34822
|
$mode =~ /^([a-z]+)([0-7]+)?\z/ |
|
141
|
|
|
|
|
|
|
or croak "Invalid mode '$mode': expected number, or prefix file/dir/sym/blk/chr/fifo/sock followed by octal permissions"; |
|
142
|
10543
|
50
|
|
|
|
26906
|
$mode_desc= $_mode_alias{$1} |
|
143
|
|
|
|
|
|
|
or croak "Unknown mode alias '$1'"; |
|
144
|
10543
|
100
|
|
|
|
22342
|
$mode= $mode_desc->[0] | (defined $2? oct($2) : $mode_desc->[1]->()); |
|
145
|
|
|
|
|
|
|
} |
|
146
|
10543
|
|
|
|
|
17551
|
$attrs{mode}= $mode; |
|
147
|
10543
|
50
|
|
|
|
15280
|
length $name or croak "Name must be nonzero length"; |
|
148
|
10543
|
|
|
|
|
13390
|
$attrs{name}= $name; |
|
149
|
10543
|
100
|
|
|
|
15117
|
if (defined $data) { |
|
150
|
10533
|
100
|
66
|
|
|
22259
|
if ($mode_desc && $mode_desc->[2]) { |
|
151
|
4
|
|
|
|
|
24
|
$mode_desc->[2]->(\%attrs, $data); |
|
152
|
|
|
|
|
|
|
} else { |
|
153
|
10529
|
|
|
|
|
12891
|
$attrs{data}= $data; |
|
154
|
|
|
|
|
|
|
} |
|
155
|
|
|
|
|
|
|
} |
|
156
|
10543
|
|
|
|
|
47240
|
return %attrs; |
|
157
|
|
|
|
|
|
|
} |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
|
|
160
|
0
|
|
|
0
|
1
|
0
|
sub round_up_to_pow2($n) { |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
161
|
0
|
0
|
|
|
|
0
|
croak "Not defined for negative numbers" unless $n > 0; |
|
162
|
0
|
0
|
|
|
|
0
|
return 1 if $n <= 1; |
|
163
|
0
|
|
|
|
|
0
|
--$n; |
|
164
|
0
|
|
|
|
|
0
|
$n |= $n >> 1; |
|
165
|
0
|
|
|
|
|
0
|
$n |= $n >> 2; |
|
166
|
0
|
|
|
|
|
0
|
$n |= $n >> 4; |
|
167
|
0
|
|
|
|
|
0
|
$n |= $n >> 8; |
|
168
|
0
|
|
|
|
|
0
|
$n |= $n >> 16; |
|
169
|
0
|
|
|
|
|
0
|
$n |= $n >> 32; |
|
170
|
0
|
|
|
|
|
0
|
return $n+1; |
|
171
|
|
|
|
|
|
|
} |
|
172
|
|
|
|
|
|
|
|
|
173
|
62
|
|
|
62
|
1
|
61
|
sub round_up_to_multiple($n, $pow2) { |
|
|
62
|
|
|
|
|
53
|
|
|
|
62
|
|
|
|
|
56
|
|
|
|
62
|
|
|
|
|
54
|
|
|
174
|
62
|
50
|
|
|
|
129
|
croak "Not defined for negative numbers" unless $n > 0; |
|
175
|
62
|
|
|
|
|
67
|
my $mask= $pow2-1; |
|
176
|
62
|
|
|
|
|
121
|
return ($n + $mask) & ~$mask; |
|
177
|
|
|
|
|
|
|
} |
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
if (eval { require File::Map; }) { |
|
181
|
|
|
|
|
|
|
eval q{ |
|
182
|
|
|
|
|
|
|
sub map_or_load_file($filename, $offset=0, $length=undef) { |
|
183
|
|
|
|
|
|
|
my $buf; |
|
184
|
|
|
|
|
|
|
defined $length? File::Map::map_file($buf, $filename, "<", $offset, $length) |
|
185
|
|
|
|
|
|
|
: File::Map::map_file($buf, $filename, "<", $offset, $length); |
|
186
|
|
|
|
|
|
|
return \$buf; |
|
187
|
|
|
|
|
|
|
} |
|
188
|
|
|
|
|
|
|
1; |
|
189
|
|
|
|
|
|
|
} or die "$@"; |
|
190
|
|
|
|
|
|
|
} else { |
|
191
|
|
|
|
|
|
|
*map_or_load_file= *_load_file; |
|
192
|
|
|
|
|
|
|
} |
|
193
|
|
|
|
|
|
|
|
|
194
|
7
|
|
|
7
|
|
11
|
sub _load_file($filename, $offset= 0, $length= undef) { |
|
|
7
|
|
|
|
|
11
|
|
|
|
7
|
|
|
|
|
10
|
|
|
|
7
|
|
|
|
|
7
|
|
|
|
7
|
|
|
|
|
40
|
|
|
195
|
7
|
50
|
|
|
|
268
|
open my $fh, "<:raw", $filename |
|
196
|
|
|
|
|
|
|
or die "open($filename): $!"; |
|
197
|
7
|
|
|
|
|
116
|
my $size= -s $fh; |
|
198
|
7
|
50
|
|
|
|
35
|
croak "Offset beyond end of file ($filename, $offset > $size)" if $offset > $size; |
|
199
|
7
|
|
33
|
|
|
21
|
$length //= $size - $offset; |
|
200
|
7
|
|
|
|
|
14
|
my $buf= ''; |
|
201
|
7
|
50
|
|
|
|
18
|
if ($length) { |
|
202
|
7
|
50
|
|
|
|
14
|
if ($offset > 0) { |
|
203
|
0
|
0
|
|
|
|
0
|
sysseek($fh, $offset, 0) == $offset |
|
204
|
|
|
|
|
|
|
or croak "sysseek($filename, $offset): $!"; |
|
205
|
|
|
|
|
|
|
} |
|
206
|
7
|
50
|
|
|
|
309
|
sysread($fh, $buf, $length) == $size |
|
207
|
|
|
|
|
|
|
or die "sysread($filename, $size): $!"; |
|
208
|
|
|
|
|
|
|
} |
|
209
|
7
|
|
|
|
|
200
|
\$buf; |
|
210
|
|
|
|
|
|
|
} |
|
211
|
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
sub filedata { |
|
214
|
7
|
|
|
7
|
1
|
77865
|
state $loaded= require Sys::Export::LazyFileData; |
|
215
|
7
|
|
|
|
|
33
|
Sys::Export::LazyFileData->new(@_); |
|
216
|
|
|
|
|
|
|
} |
|
217
|
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
|
|
219
|
10751
|
|
|
10751
|
1
|
9726
|
sub write_file_extent($fh, $addr, $size, $data_ref, $ofs=0, $descrip=undef) { |
|
|
10751
|
|
|
|
|
9709
|
|
|
|
10751
|
|
|
|
|
9684
|
|
|
|
10751
|
|
|
|
|
9763
|
|
|
|
10751
|
|
|
|
|
9651
|
|
|
|
10751
|
|
|
|
|
9556
|
|
|
|
10751
|
|
|
|
|
11103
|
|
|
|
10751
|
|
|
|
|
9645
|
|
|
220
|
10751
|
0
|
0
|
|
|
16805
|
$log->tracef("write %s at 0x%X-0x%X from buf size 0x%X%s", |
|
|
|
50
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
$descrip//'blocks', $addr, $addr+$size, length($$data_ref), $ofs? sprintf(" ofs 0x%X", $ofs) : '' |
|
222
|
|
|
|
|
|
|
) if $log->is_trace; |
|
223
|
10751
|
50
|
|
|
|
55854
|
return unless $size > 0; |
|
224
|
10751
|
50
|
|
|
|
13419
|
if (defined $addr) { |
|
225
|
10751
|
|
33
|
|
|
59854
|
my $reached= sysseek($fh, $addr, 0) // croak "sysseek($addr): $!"; |
|
226
|
10751
|
50
|
|
|
|
15239
|
$reached == $addr or croak "sysseek($addr) arrived at $reached instead of $addr"; |
|
227
|
|
|
|
|
|
|
} |
|
228
|
10751
|
|
50
|
|
|
13148
|
$ofs //= 0; |
|
229
|
10751
|
50
|
|
|
|
14543
|
my $avail= $data_ref? (length($$data_ref) - $ofs) : 0; |
|
230
|
10751
|
|
|
|
|
9188
|
my $second; |
|
231
|
|
|
|
|
|
|
# always write full size, padding with zeroes |
|
232
|
10751
|
100
|
|
|
|
13806
|
if ($avail < $size) { |
|
233
|
|
|
|
|
|
|
# If the scalar is particularly large, do two writes instead of reallocating the buffer. |
|
234
|
1747
|
50
|
|
|
|
2342
|
if ($avail > 0x100000) { |
|
235
|
0
|
|
|
|
|
0
|
my $first_write= $avail - ($avail & 0xFFF); |
|
236
|
0
|
|
|
|
|
0
|
$second= pack 'a'.($size-$first_write), substr($$data_ref, $first_write); |
|
237
|
0
|
|
|
|
|
0
|
$size= $first_write; |
|
238
|
|
|
|
|
|
|
} else { |
|
239
|
1747
|
50
|
|
|
|
5785
|
my $data= pack 'a'.$size, ($avail > 0? substr($$data_ref, $ofs) : ''); |
|
240
|
1747
|
|
|
|
|
1688
|
$data_ref= \$data; |
|
241
|
1747
|
|
|
|
|
1836
|
$ofs= 0; |
|
242
|
|
|
|
|
|
|
} |
|
243
|
|
|
|
|
|
|
} |
|
244
|
10751
|
|
|
|
|
184659
|
my $wrote= syswrite($fh, $$data_ref, $size, $ofs); |
|
245
|
10751
|
50
|
|
|
|
18830
|
croak "syswrite: $!" if !defined $wrote; |
|
246
|
10751
|
50
|
|
|
|
15490
|
croak "Unexpected short write ($wrote != $size)" if $wrote != $size; |
|
247
|
10751
|
50
|
|
|
|
13121
|
if (length $second) { |
|
248
|
0
|
|
|
|
|
0
|
$wrote= syswrite($fh, $second); |
|
249
|
0
|
0
|
|
|
|
0
|
croak "syswrite: $!" if !defined $wrote; |
|
250
|
0
|
0
|
|
|
|
0
|
croak "Unexpected short write ($wrote != $size)" if $wrote != length($second); |
|
251
|
|
|
|
|
|
|
} |
|
252
|
10751
|
|
|
|
|
18918
|
return 1; |
|
253
|
|
|
|
|
|
|
} |
|
254
|
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
1; |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
__END__ |