line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Tsk::Fs::Iterator; |
2
|
1
|
|
|
1
|
|
53691
|
use 5.012005; |
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
47
|
|
3
|
1
|
|
|
1
|
|
6
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
233
|
|
4
|
1
|
|
|
1
|
|
8
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
32
|
|
5
|
1
|
|
|
1
|
|
1001
|
use Tsk; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
620
|
|
6
|
1
|
|
|
1
|
|
973
|
use Tsk::Stack; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
383
|
|
7
|
1
|
|
|
1
|
|
823
|
use Tsk::Fs::File; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
786
|
|
8
|
1
|
|
|
1
|
|
976
|
use Tsk::Fs::Dir ; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
35
|
|
9
|
1
|
|
|
1
|
|
1919
|
use Tsk::Fs::Info ; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
456
|
|
10
|
1
|
|
|
1
|
|
732
|
use Tsk::Img::Info ; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
297
|
|
11
|
|
|
|
|
|
|
|
12
|
1
|
|
|
1
|
|
707
|
use Tsk::Vs::Info; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
1167
|
|
13
|
|
|
|
|
|
|
#use Tsk::Vs::PartInfo; |
14
|
1
|
|
|
1
|
|
9
|
use Carp; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
3038
|
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head1 NAME |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
Tsk::Fs::Iterator - File iterator over files in a disk image |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
=head1 DESCRIPTION |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
This module allows for easy traversal of the a filesystem. |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=head1 SYNOPSIS |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
use Tsk::Fs::Iterator; |
27
|
|
|
|
|
|
|
my $iter = Tsk::Fs::Iterator->new("./testdata/testimage001.001", 65536); |
28
|
|
|
|
|
|
|
while(my $f = $iter->next() ) { |
29
|
|
|
|
|
|
|
print $f->{name}."\n"; |
30
|
|
|
|
|
|
|
}; |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
=head1 new(path, offset) |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
The constructor receives two parameters. The path to the image on disk and an offset indicating |
35
|
|
|
|
|
|
|
where the volume to be read starts. |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=cut |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
sub new { |
40
|
1
|
|
|
1
|
0
|
16
|
my ($class, $image, $offset) = @_; |
41
|
1
|
50
|
33
|
|
|
39
|
croak "[ERR] image path invalid" if !defined($image) || !-f $image; |
42
|
1
|
50
|
33
|
|
|
13
|
croak "[ERR] offset not provided" if !defined($offset) || ! $offset =~ /^\d+$/; |
43
|
1
|
|
|
|
|
11
|
my $h = { |
44
|
|
|
|
|
|
|
fstack => [], |
45
|
|
|
|
|
|
|
dstack => [], |
46
|
|
|
|
|
|
|
inumstack => undef, |
47
|
|
|
|
|
|
|
fs_info => undef, |
48
|
|
|
|
|
|
|
img_info => undef, |
49
|
|
|
|
|
|
|
image_path => $image, |
50
|
|
|
|
|
|
|
}; |
51
|
1
|
|
|
|
|
3
|
my $self = bless $h,$class; |
52
|
|
|
|
|
|
|
|
53
|
1
|
|
|
|
|
2
|
my ($img_info,$fs_info); |
54
|
1
|
|
|
|
|
28
|
my $inumstack = Tsk::Stack->new(); |
55
|
1
|
|
|
|
|
11
|
$img_info = Tsk::Img::Info->new(); |
56
|
1
|
|
|
|
|
898
|
$img_info->open($image,$TSK_IMG_TYPE_DETECT,0); |
57
|
1
|
|
|
|
|
13
|
$fs_info = Tsk::Fs::Info->new(); |
58
|
|
|
|
|
|
|
#$fs_info->open($img_info, 65536, $TSK_FS_TYPE_DETECT); |
59
|
|
|
|
|
|
|
|
60
|
1
|
|
|
|
|
3323
|
$fs_info->open($img_info, $offset, $TSK_FS_TYPE_DETECT); |
61
|
1
|
|
|
|
|
20
|
$self->{fs_info} = $fs_info; |
62
|
1
|
|
|
|
|
3
|
$self->{img_info} = $img_info; |
63
|
1
|
|
|
|
|
2
|
$self->{inumstack} = $inumstack; |
64
|
1
|
|
|
|
|
10
|
$self->init_stacks; |
65
|
1
|
|
|
|
|
7
|
return $self; |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=head1 INumToDir($fs_info) |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
Takes an inode number as a parameter and returns a Tsk::Fs::Dir structure. |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=cut |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub INumToDir { |
76
|
4
|
|
|
4
|
0
|
6
|
my ($self,$dir_inum) = @_; |
77
|
4
|
|
|
|
|
30
|
my $fs_dir = Tsk::Fs::Dir->new(); |
78
|
4
|
|
|
|
|
1303
|
$fs_dir->open($self->{fs_info},$dir_inum); |
79
|
4
|
|
|
|
|
12
|
return $fs_dir; |
80
|
|
|
|
|
|
|
}; |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=head2 get_separated(Tsk::Fs::File) |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
Gets a TskFsFile as a parameter. It expects the file to point to a directory node on the disk. |
85
|
|
|
|
|
|
|
Returns two separated arrayrefs, one with files contained in $tsk_fs_file, and one with directories contained in $tsk_fs_file . |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
=cut |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
sub get_separated { |
90
|
3
|
|
|
3
|
0
|
6
|
my ($self,$x) = @_; |
91
|
3
|
|
|
|
|
4
|
my @dirs ; |
92
|
|
|
|
|
|
|
my @files ; |
93
|
|
|
|
|
|
|
|
94
|
0
|
|
|
|
|
0
|
my ($fs_dir,$fs_dir_sz,$prevpath); |
95
|
|
|
|
|
|
|
#print "addr=$x->{addr}\n"; |
96
|
3
|
|
|
|
|
10
|
$fs_dir = $self->INumToDir($x->{addr}); |
97
|
3
|
|
|
|
|
12
|
$fs_dir_sz = $fs_dir->getSize(); |
98
|
3
|
|
|
|
|
8
|
$prevpath = $x->{path}; |
99
|
|
|
|
|
|
|
|
100
|
3
|
|
|
|
|
8
|
for(my $i=0;$i<$fs_dir_sz;$i++) { |
101
|
55
|
|
|
|
|
1210
|
my $fs_file = $fs_dir->getFile($i); |
102
|
55
|
|
|
|
|
165
|
my $fs_meta = $fs_file->getMeta(); |
103
|
55
|
|
|
|
|
158
|
my $fs_name = $fs_file->getName(); |
104
|
55
|
|
|
|
|
51
|
my $name; |
105
|
55
|
50
|
|
|
|
123
|
if($fs_meta) { |
106
|
55
|
|
|
|
|
109
|
my $type = $fs_meta->getType(); |
107
|
55
|
50
|
|
|
|
100
|
if($fs_name) { |
108
|
55
|
|
|
|
|
119
|
$name = $fs_name->getName(); |
109
|
|
|
|
|
|
|
}; |
110
|
55
|
100
|
100
|
|
|
460
|
if($name =~ /^\$/ || $name eq "." || $name eq "..") { |
|
|
|
100
|
|
|
|
|
111
|
17
|
|
|
|
|
33
|
$fs_file->close; |
112
|
17
|
|
|
|
|
88
|
next; |
113
|
|
|
|
|
|
|
}; |
114
|
38
|
|
|
|
|
57
|
my $path = "$prevpath/$name"; |
115
|
38
|
100
|
|
|
|
58
|
if($type == $TSK_FS_META_TYPE_DIR) { |
116
|
2
|
|
|
|
|
6
|
my $addr = $fs_meta->getAddr(); |
117
|
2
|
|
|
|
|
13
|
push @dirs, { |
118
|
|
|
|
|
|
|
name => $name, |
119
|
|
|
|
|
|
|
fs_meta => $fs_meta, |
120
|
|
|
|
|
|
|
fs_file => $fs_file, |
121
|
|
|
|
|
|
|
addr => $addr, |
122
|
|
|
|
|
|
|
path => $path, |
123
|
|
|
|
|
|
|
}; |
124
|
|
|
|
|
|
|
} else { |
125
|
36
|
|
|
|
|
198
|
push @files, { |
126
|
|
|
|
|
|
|
name => $name, |
127
|
|
|
|
|
|
|
fs_meta => $fs_meta, |
128
|
|
|
|
|
|
|
fs_file => $fs_file, |
129
|
|
|
|
|
|
|
path => $prevpath, |
130
|
|
|
|
|
|
|
}; |
131
|
|
|
|
|
|
|
}; |
132
|
|
|
|
|
|
|
}; |
133
|
|
|
|
|
|
|
}; |
134
|
3
|
|
|
|
|
29
|
return (\@dirs,\@files); |
135
|
|
|
|
|
|
|
}; |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=head1 init_stacks() |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
Initializes stacks. Puts the root directory on the directory stack. |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=cut |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
sub init_stacks { |
144
|
1
|
|
|
1
|
0
|
2
|
my ($self) = @_; |
145
|
1
|
|
|
|
|
4
|
my $dstack = $self->{dstack}; |
146
|
1
|
|
|
|
|
7
|
my $rootINum = $self->{fs_info}->getRootINum(); |
147
|
1
|
|
|
|
|
8
|
my $root_dir = $self->INumToDir($rootINum); |
148
|
1
|
|
|
|
|
24
|
push @$dstack, { |
149
|
|
|
|
|
|
|
fs_dir => undef, |
150
|
|
|
|
|
|
|
fs_file => undef, |
151
|
|
|
|
|
|
|
fs_meta => undef, |
152
|
|
|
|
|
|
|
name => "", |
153
|
|
|
|
|
|
|
path => "", |
154
|
|
|
|
|
|
|
addr => $rootINum, |
155
|
|
|
|
|
|
|
}; |
156
|
|
|
|
|
|
|
}; |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=head1 next() |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
Returns next Tsk::Fs::File object. |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=cut |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
sub next { |
165
|
40
|
|
|
40
|
0
|
390
|
my ($self) = @_; |
166
|
40
|
|
|
|
|
61
|
my $fstack = $self->{fstack}; |
167
|
40
|
|
|
|
|
47
|
my $dstack = $self->{dstack}; |
168
|
40
|
50
|
33
|
|
|
140
|
croak "[ERR] not initialized" if !defined($self->{fs_info}) || !defined($self->{inumstack}); |
169
|
|
|
|
|
|
|
|
170
|
40
|
|
|
|
|
45
|
my $inumstack = $self->{inumstack}; |
171
|
|
|
|
|
|
|
|
172
|
40
|
100
|
|
|
|
75
|
if(@$fstack > 0) { |
173
|
36
|
|
|
|
|
47
|
my $newFile = pop(@$fstack); |
174
|
36
|
|
|
|
|
87
|
return $newFile; |
175
|
|
|
|
|
|
|
}; |
176
|
|
|
|
|
|
|
|
177
|
4
|
100
|
|
|
|
11
|
if(@$dstack > 0) { |
178
|
3
|
|
|
|
|
5
|
my $newDir = pop(@$dstack); |
179
|
3
|
|
|
|
|
14
|
$inumstack->push($newDir->{addr}); |
180
|
3
|
|
|
|
|
7
|
my ($dirs, $newFiles) = $self->get_separated($newDir); |
181
|
3
|
|
|
|
|
9
|
my @newDirs = grep { $inumstack->find($_->{addr}) == 0 } @$dirs; |
|
2
|
|
|
|
|
13
|
|
182
|
3
|
100
|
|
|
|
10
|
push @$dstack,@newDirs if @newDirs > 0; |
183
|
3
|
50
|
|
|
|
15
|
push @$fstack,@$newFiles if @$newFiles > 0; |
184
|
3
|
|
|
|
|
16
|
return $newDir; |
185
|
|
|
|
|
|
|
}; |
186
|
1
|
|
|
|
|
4
|
return undef; |
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
sub DESTROY { |
190
|
1
|
|
|
1
|
|
1883
|
my ($self) = @_; |
191
|
1
|
|
|
|
|
283
|
$self->{fs_info}->close; |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=head1 BUGS |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
L |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
L |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
=head1 AUTHOR |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
Stefan Petrea, C<< >> |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
=cut |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
1; |