1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
package resize_fat::directory;
use diagnostics;
use strict;
use common qw(:system);
use resize_fat::dir_entry;
use resize_fat::io;
my $format = "a8 a3 C C C S7 I";
my @fields = (
'name',
'extension',
'attributes',
'is_upper_case_name',
'creation_time_low', #- milliseconds
'creation_time_high',
'creation_date',
'access_date',
'first_cluster_high', #- for FAT32
'time',
'date',
'first_cluster',
'length',
);
my $psizeof_format = psizeof($format);
1;
sub entry_size { $psizeof_format }
#- call `f' for each entry of the directory
#- if f return true, then modification in the entry are taken back
sub traverse($$) {
my ($directory, $f) = @_;
for (my $i = 0;; $i++) {
my $raw = \substr($directory, $i * $psizeof_format, $psizeof_format);
#- empty entry means end of directory
$$raw =~ /^\0*$/ and return $directory;
my $entry; @{$entry}{@fields} = unpack $format, $$raw;
&$f($entry)
and $$raw = pack $format, @{$entry}{@fields};
}
$directory;
}
sub traverse_all($$) {
my ($fs, $f) = @_;
my $traverse_all; $traverse_all = sub {
my ($entry) = @_;
&$f($entry);
resize_fat::dir_entry::is_directory($entry)
and traverse(resize_fat::io::read_file($fs, resize_fat::dir_entry::get_cluster($entry)), $traverse_all);
undef; #- no need to write back (cf traverse)
};
my $directory = $resize_fat::isFAT32 ?
resize_fat::io::read_file($fs, $fs->{fat32_root_dir_cluster}) :
resize_fat::io::read($fs, $fs->{root_dir_offset}, $fs->{root_dir_size});
traverse($directory, $traverse_all);
undef $traverse_all; #- circular reference is no good for perl's poor GC :(
}
#- function used by construct_dir_tree to translate the `cluster' fields in each
#- directory entry
sub remap($$) {
my ($fs, $directory) = @_;
traverse($directory, \&resize_fat::dir_entry::remap);
}
|