File Coverage

blib/lib/Tsk/Fs/Iterator.pm
Criterion Covered Total %
statement 101 102 99.0
branch 16 22 72.7
condition 9 15 60.0
subroutine 17 17 100.0
pod 0 5 0.0
total 143 161 88.8


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;