summaryrefslogtreecommitdiffstats
path: root/perl-install/resize_fat/any.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/resize_fat/any.pm')
-rw-r--r--perl-install/resize_fat/any.pm82
1 files changed, 82 insertions, 0 deletions
diff --git a/perl-install/resize_fat/any.pm b/perl-install/resize_fat/any.pm
new file mode 100644
index 000000000..d78a342be
--- /dev/null
+++ b/perl-install/resize_fat/any.pm
@@ -0,0 +1,82 @@
+package resize_fat::any;
+
+use diagnostics;
+use strict;
+use vars qw($FREE $FILE $DIRECTORY);
+
+use common qw(:common :constant);
+use resize_fat::fat;
+use resize_fat::directory;
+use resize_fat::dir_entry;
+
+
+$FREE = 0;
+$FILE = 1;
+$DIRECTORY = 2;
+
+
+1;
+
+
+# returns the number of clusters for a given filesystem type
+sub min_cluster_count($) {
+ my ($fs) = @_;
+ (1 << $ {{ FAT16 => 12, FAT32 => 16 }}{$fs->{fs_type}}) - 12;
+}
+sub max_cluster_count($) {
+ my ($fs) = @_;
+ $resize_fat::bad_cluster_value - 2;
+}
+
+
+
+# calculates the minimum size of a partition, in physical sectors
+sub min_size($) {
+ my ($fs) = @_;
+ my $count = $fs->{clusters}->{count};
+
+ # directories are both in `used' and `dirs', so are counted twice
+ # It's done on purpose since we're moving all directories. So at the worse
+ # moment, 2 directories are there, but that way nothing wrong can happen :)
+ my $min_cluster_count = max(2 + $count->{used} + $count->{bad} + $count->{dirs}, min_cluster_count($fs));
+
+ $min_cluster_count * divide($fs->{cluster_size}, $SECTORSIZE) +
+ divide($fs->{cluster_offset}, $SECTORSIZE);
+}
+# calculates the maximum size of a partition, in physical sectors
+sub max_size($) {
+ my ($fs) = @_;
+
+ my $max_cluster_count = min($fs->{nb_fat_entries} - 2, max_cluster_count($fs));
+
+ $max_cluster_count * divide($fs->{cluster_size}, $SECTORSIZE) +
+ divide($fs->{cluster_offset}, $SECTORSIZE);
+}
+
+# fills in $fs->{fat_flag_map}.
+# Each FAT entry is flagged as either FREE, FILE or DIRECTORY.
+sub flag_clusters {
+ my ($fs) = @_;
+ my ($cluster, $entry, $type);
+
+ my $f = sub {
+ ($entry) = @_;
+ $cluster = resize_fat::dir_entry::get_cluster($entry);
+
+ if (resize_fat::dir_entry::is_file($entry)) {
+ $type = $FILE;
+ } elsif (resize_fat::dir_entry::is_directory($entry)) {
+ $type = $DIRECTORY;
+ } else { return }
+
+ for (; !resize_fat::fat::is_eof($cluster); $cluster = resize_fat::fat::next($fs, $cluster)) {
+ $cluster == 0 and die "Bad FAT: unterminated chain for $entry->{name}\n";
+ $fs->{fat_flag_map}->[$cluster] and die "Bad FAT: cluster $cluster is cross-linked for $entry->{name}\n";
+ $fs->{fat_flag_map}->[$cluster] = $type;
+ $fs->{clusters}->{count}->{dirs}++ if $type == $DIRECTORY;
+ }
+ };
+ $fs->{fat_flag_map} = [ ($FREE) x ($fs->{nb_clusters} + 2) ];
+ $fs->{clusters}->{count}->{dirs} = 0;
+ resize_fat::directory::traverse_all($fs, $f);
+}