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 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151package resize_fat::directory; # $Id$ use diagnostics; use strict; use common; 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, $curr_dir_name, $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($curr_dir_name, $entry) and $$raw = pack $format, @$entry{@fields}; } $directory; } sub traverse_all($$) { my ($fs, $f) = @_; my $traverse_all; $traverse_all = sub { my ($curr_dir_name, $entry) = @_; &$f($curr_dir_name, $entry); resize_fat::dir_entry::is_directory($entry) and traverse(resize_fat::io::read_file($fs, resize_fat::dir_entry::get_cluster($entry)), "$curr_dir_name/$entry->{name}", $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); } |