| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Sys::Export::CPIO; |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# ABSTRACT: Write CPIO archives needed for Linux initrd |
|
4
|
|
|
|
|
|
|
our $VERSION = '0.003'; # VERSION |
|
5
|
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
304734
|
use v5.26; |
|
|
1
|
|
|
|
|
5
|
|
|
7
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
61
|
|
|
8
|
1
|
|
|
1
|
|
7
|
use experimental qw( signatures ); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
6
|
|
|
9
|
1
|
|
|
1
|
|
205
|
use Fcntl qw( S_IFDIR S_IFMT ); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
77
|
|
|
10
|
1
|
|
|
1
|
|
6
|
use Scalar::Util 'blessed'; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
89
|
|
|
11
|
1
|
|
|
1
|
|
6
|
use Carp; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
1646
|
|
|
12
|
|
|
|
|
|
|
our @CARP_NOT= qw( Sys::Export Sys::Export::Unix ); |
|
13
|
|
|
|
|
|
|
require Sys::Export::Unix; # for _dev_major_minor |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
|
|
16
|
1
|
|
|
1
|
1
|
285243
|
sub new($class, $f, @attrs) { |
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
2
|
|
|
17
|
1
|
50
|
|
|
|
6
|
croak "Expected even-length key/value list after filename" if @attrs & 1; |
|
18
|
1
|
|
|
|
|
2
|
my $filename; |
|
19
|
|
|
|
|
|
|
my $fh= blessed $f && $f->can('print')? $f |
|
20
|
1
|
50
|
33
|
|
|
6
|
: do { $filename= $f; open my $x, '>:raw', $f or die "open($f): $!"; $x }; |
|
|
1
|
50
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
27
|
|
|
|
1
|
|
|
|
|
4
|
|
|
21
|
1
|
|
|
|
|
10
|
my $self= bless { |
|
22
|
|
|
|
|
|
|
fh => $fh, |
|
23
|
|
|
|
|
|
|
seen_inode => {}, |
|
24
|
|
|
|
|
|
|
ino => 0, |
|
25
|
|
|
|
|
|
|
virtual_inodes => 1, |
|
26
|
|
|
|
|
|
|
filename => $filename, |
|
27
|
|
|
|
|
|
|
autoclose => defined $filename, |
|
28
|
|
|
|
|
|
|
}, $class; |
|
29
|
|
|
|
|
|
|
|
|
30
|
1
|
|
|
|
|
4
|
while (@attrs) { |
|
31
|
0
|
|
|
|
|
0
|
my ($attr, $val)= splice(@attrs, 0, 2); |
|
32
|
0
|
|
|
|
|
0
|
$self->$attr($val); |
|
33
|
|
|
|
|
|
|
} |
|
34
|
|
|
|
|
|
|
|
|
35
|
1
|
|
|
|
|
4
|
$self; |
|
36
|
|
|
|
|
|
|
} |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
sub autoclose { |
|
40
|
0
|
0
|
|
0
|
1
|
0
|
$_[0]{autoclose}= !!$_[1] if @_ > 1; # cast to boolean |
|
41
|
|
|
|
|
|
|
$_[0]{autoclose} |
|
42
|
0
|
|
|
|
|
0
|
} |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
sub filename { |
|
45
|
0
|
0
|
|
0
|
1
|
0
|
$_[0]{filename}= $_[1] if @_ > 1; |
|
46
|
|
|
|
|
|
|
$_[0]{filename} |
|
47
|
0
|
|
|
|
|
0
|
} |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
sub virtual_inodes { |
|
50
|
3
|
50
|
|
3
|
1
|
10
|
$_[0]{virtual_inodes}= !!$_[1] if @_ > 1; # cast to boolean |
|
51
|
|
|
|
|
|
|
$_[0]{virtual_inodes} |
|
52
|
3
|
|
|
|
|
16
|
} |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
|
|
55
|
3
|
|
|
3
|
1
|
9974
|
sub add($self, $fileinfo) { |
|
|
3
|
|
|
|
|
6
|
|
|
|
3
|
|
|
|
|
8
|
|
|
|
3
|
|
|
|
|
6
|
|
|
56
|
|
|
|
|
|
|
my ($dev, $dev_major, $dev_minor, $ino, $mode, $nlink, $uid, $gid, $rdev, $rdev_major, $rdev_minor, $mtime, $name) |
|
57
|
3
|
|
|
|
|
7
|
= @{$fileinfo}{qw( dev dev_major dev_minor ino mode nlink uid gid rdev rdev_major rdev_minor mtime name )}; |
|
|
3
|
|
|
|
|
19
|
|
|
58
|
|
|
|
|
|
|
# best-effort to extract major/minor from dev and rdev, unless user specified them |
|
59
|
3
|
50
|
0
|
|
|
13
|
($dev_major, $dev_minor)= Sys::Export::Unix::_dev_major_minor($dev) |
|
|
|
|
33
|
|
|
|
|
|
60
|
|
|
|
|
|
|
if defined $dev and !defined $dev_major || !defined $dev_minor; |
|
61
|
3
|
100
|
33
|
|
|
24
|
($rdev_major, $rdev_minor)= Sys::Export::Unix::_dev_major_minor($rdev) |
|
|
|
|
66
|
|
|
|
|
|
62
|
|
|
|
|
|
|
if defined $rdev and !defined $rdev_major || !defined $rdev_minor; |
|
63
|
3
|
50
|
|
|
|
10
|
defined $mode or croak "require 'mode'"; |
|
64
|
3
|
50
|
|
|
|
9
|
defined $name or croak "require 'name'"; |
|
65
|
|
|
|
|
|
|
|
|
66
|
3
|
|
50
|
|
|
18
|
my $size= length($fileinfo->{data}) // 0; |
|
67
|
|
|
|
|
|
|
# Handle hard links |
|
68
|
3
|
50
|
66
|
|
|
37
|
if ($nlink && $nlink > 1 && ($mode & S_IFMT) != S_IFDIR) { |
|
|
|
50
|
66
|
|
|
|
|
|
69
|
0
|
|
|
|
|
0
|
my $hardlink_key= "$dev_major:$dev_minor:$ino"; |
|
70
|
0
|
0
|
|
|
|
0
|
if ($self->virtual_inodes) { |
|
71
|
|
|
|
|
|
|
# the previous virtual inode is stored in the seen_inode hash |
|
72
|
0
|
0
|
|
|
|
0
|
if ($ino= $self->{seen_inode}{$hardlink_key}) { |
|
73
|
0
|
|
|
|
|
0
|
$size= 0; |
|
74
|
|
|
|
|
|
|
} else { |
|
75
|
0
|
|
|
|
|
0
|
$ino= $self->{seen_inode}{$hardlink_key}= ++$self->{ino}; |
|
76
|
|
|
|
|
|
|
} |
|
77
|
0
|
|
|
|
|
0
|
($dev_major, $dev_minor)= (0,0); |
|
78
|
|
|
|
|
|
|
} |
|
79
|
|
|
|
|
|
|
else { |
|
80
|
0
|
0
|
|
|
|
0
|
$size= 0 if $self->{seen_inode}{$hardlink_key}++; |
|
81
|
|
|
|
|
|
|
} |
|
82
|
|
|
|
|
|
|
} |
|
83
|
|
|
|
|
|
|
elsif ($self->virtual_inodes) { |
|
84
|
3
|
|
|
|
|
9
|
($dev_major, $dev_minor, $ino)= (0,0); |
|
85
|
|
|
|
|
|
|
} |
|
86
|
3
|
|
33
|
|
|
18
|
$ino //= ++$self->{ino}; |
|
87
|
|
|
|
|
|
|
|
|
88
|
3
|
|
50
|
|
|
72
|
my $header= sprintf "070701%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%s\0%s", |
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
89
|
|
|
|
|
|
|
$ino, $mode, $uid//0, $gid//0, $nlink//1, $mtime//0, $size, |
|
90
|
|
|
|
|
|
|
$dev_major//0, $dev_minor//0, $rdev_major//0, $rdev_minor//0, |
|
91
|
|
|
|
|
|
|
1+length $name, 0, $name, |
|
92
|
|
|
|
|
|
|
"\0"x((4 - ((13*8+6+length($name)+1) & 3)) & 3); # pad to multiple of 4 |
|
93
|
3
|
50
|
|
|
|
10
|
die "BUG" if length $header & 3; |
|
94
|
|
|
|
|
|
|
|
|
95
|
3
|
50
|
|
|
|
27
|
$self->{fh}->print($header) || die "write: $!"; |
|
96
|
|
|
|
|
|
|
# This is written in multiple parts like this because $fileinfo->{data} might be a File::Map, |
|
97
|
|
|
|
|
|
|
# and optimal to pass that directly back to fprint without a perl-side concatenation. |
|
98
|
3
|
50
|
0
|
|
|
66
|
$self->{fh}->print($fileinfo->{data}) || die "write: $!" |
|
99
|
|
|
|
|
|
|
if $size; |
|
100
|
3
|
50
|
0
|
|
|
10
|
$self->{fh}->print("\0"x(4-($size & 3))) || die "write: $!" |
|
101
|
|
|
|
|
|
|
if $size & 3; # pad to multiple of 4 |
|
102
|
3
|
|
|
|
|
12
|
$self; |
|
103
|
|
|
|
|
|
|
} |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
|
|
106
|
0
|
|
|
0
|
1
|
|
sub finish($self) { |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
107
|
0
|
|
|
|
|
|
$self->add({ mode => 0, ino => 0, name => 'TRAILER!!!' }); |
|
108
|
0
|
|
|
|
|
|
$self->{fh}->flush; |
|
109
|
0
|
0
|
|
|
|
|
$self->{fh}->close if $self->autoclose; |
|
110
|
0
|
|
|
|
|
|
$self; |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
# Avoiding dependency on namespace::clean |
|
114
|
1
|
|
|
1
|
|
9
|
{ no strict 'refs'; |
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
121
|
|
|
115
|
|
|
|
|
|
|
delete @{"Sys::Export::CPIO::"}{qw( |
|
116
|
|
|
|
|
|
|
S_IFDIR S_IFMT blessed carp croak |
|
117
|
|
|
|
|
|
|
)} |
|
118
|
|
|
|
|
|
|
} |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
1; |
|
121
|
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
__END__ |