From 77d16a3330cab8b9c86667220114542958e7a348 Mon Sep 17 00:00:00 2001 From: Francois Pons Date: Wed, 9 Feb 2000 11:40:32 +0000 Subject: *** empty log message *** --- perl-install/resize_fat/any.pm | 47 +++++++++++++++++++++++++++++----- perl-install/resize_fat/c_rewritten.xs | 2 +- perl-install/resize_fat/dir_entry.pm | 12 ++++++++- perl-install/resize_fat/directory.pm | 16 ++++++------ perl-install/resize_fat/fat.pm | 4 +++ perl-install/resize_fat/main.pm | 28 ++++++++++++-------- 6 files changed, 81 insertions(+), 28 deletions(-) (limited to 'perl-install/resize_fat') diff --git a/perl-install/resize_fat/any.pm b/perl-install/resize_fat/any.pm index 252caed4b..47f15558b 100644 --- a/perl-install/resize_fat/any.pm +++ b/perl-install/resize_fat/any.pm @@ -2,7 +2,7 @@ package resize_fat::any; use diagnostics; use strict; -use vars qw($FREE $FILE $DIRECTORY); +use vars qw($FREE $FILE $DIRECTORY $UNMOVEABLE); use common qw(:common :constant); use resize_fat::fat; @@ -11,9 +11,10 @@ use resize_fat::dir_entry; use resize_fat::c_rewritten; -$FREE = 0; -$FILE = 1; -$DIRECTORY = 2; +$FREE = 0; +$FILE = 1; +$DIRECTORY = 2; +$UNMOVEABLE = 8; 1; @@ -31,6 +32,23 @@ sub max_cluster_count($) { +#- patch to get the function last_used that return the last used cluster of a fs. +sub last_used($) { + my ($fs) = @_; + + #- count in negative so absolute value count back to 2. + foreach (-($fs->{nb_clusters}+1)..-2) { return -$_ if resize_fat::c_rewritten::flag(-$_) } + return 2; +} +#- patch to get the function last_unmoveable that return the last unmoveable cluster of a fs. +sub last_unmoveable($) { + my ($fs) = @_; + + #- count in negative so absolute value count back to 2. + foreach (-($fs->{nb_clusters}+1)..-2) { return -$_ if 0x8 & resize_fat::c_rewritten::flag(-$_) } + return 2; +} + #- calculates the minimum size of a partition, in physical sectors sub min_size($) { my ($fs) = @_; @@ -40,6 +58,7 @@ sub min_size($) { #- 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 = max($min_cluster_count, 2 + last_unmoveable($fs)); $min_cluster_count * divide($fs->{cluster_size}, $SECTORSIZE) + divide($fs->{cluster_offset}, $SECTORSIZE); @@ -53,28 +72,42 @@ sub max_size($) { $max_cluster_count * divide($fs->{cluster_size}, $SECTORSIZE) + divide($fs->{cluster_offset}, $SECTORSIZE); } +#- calculates used size in order to avoid modifying anything. +sub used_size($) { + my ($fs) = @_; + + my $used_cluster_count = max(2 + last_used($fs), min_cluster_count($fs)); + + $used_cluster_count * divide($fs->{cluster_size}, $SECTORSIZE) + + divide($fs->{cluster_offset}, $SECTORSIZE); +} #- fills in fat_flag_map in c_rewritten. #- Each FAT entry is flagged as either FREE, FILE or DIRECTORY. sub flag_clusters { my ($fs) = @_; - my ($cluster, $entry, $type, $nb_dirs); + my ($cluster, $curr_dir_name, $entry, $type, $nb_dirs); my $f = sub { - ($entry) = @_; + ($curr_dir_name, $entry) = @_; $cluster = resize_fat::dir_entry::get_cluster($entry); if (resize_fat::dir_entry::is_file($entry)) { $type = $FILE; + $type |= $UNMOVEABLE if resize_fat::dir_entry::is_unmoveable($entry); } elsif (resize_fat::dir_entry::is_directory($entry)) { $type = $DIRECTORY; } else { return } - my $nb = resize_fat::c_rewritten::checkFat($cluster, $type, $entry->{name}); + my $nb = resize_fat::c_rewritten::checkFat($cluster, $type, "$curr_dir_name/$entry->{name}"); $nb_dirs += $nb if $type == $DIRECTORY; 0; }; resize_fat::c_rewritten::allocate_fat_flag($fs->{nb_clusters} + 2); + + #- patch to reset contents of memory allocated by allocate_fat_flag + foreach (0..$fs->{nb_clusters} + 1) { resize_fat::c_rewritten::set_flag($_, 0) } + resize_fat::directory::traverse_all($fs, $f); $fs->{clusters}{count}{dirs} = $nb_dirs; } diff --git a/perl-install/resize_fat/c_rewritten.xs b/perl-install/resize_fat/c_rewritten.xs index 388f8b9ea..5aebb1ffb 100644 --- a/perl-install/resize_fat/c_rewritten.xs +++ b/perl-install/resize_fat/c_rewritten.xs @@ -124,7 +124,7 @@ checkFat(cluster, type, name) for (; cluster < bad_cluster_value; cluster = next(cluster)) { if (cluster == 0) croak("Bad FAT: unterminated chain for %s\n", name); - if (fat_flag_map[cluster]) croak("Bad FAT: cluster $cluster is cross-linked for %s\n", name); + if (fat_flag_map[cluster]) croak("Bad FAT: cluster %d is cross-linked for %s\n", cluster, name); fat_flag_map[cluster] = type; nb++; } diff --git a/perl-install/resize_fat/dir_entry.pm b/perl-install/resize_fat/dir_entry.pm index be3bd436a..390659b0e 100644 --- a/perl-install/resize_fat/dir_entry.pm +++ b/perl-install/resize_fat/dir_entry.pm @@ -5,6 +5,10 @@ use strict; my $DELETED_FLAG = 0xe5; + +my $READ_ONLY_ATTR = 0x01; +my $HIDDEN_ATTR = 0x02; +my $SYSTEM_ATTR = 0x04; my $VOLUME_LABEL_ATTR = 0x08; my $VFAT_ATTR = 0x0f; my $DIRECTORY_ATTR = 0x10; @@ -21,6 +25,11 @@ sub set_cluster($$) { $entry->{first_cluster_high} = $val >> 16 if $resize_fat::isFAT32; } +sub is_unmoveable($) { + my ($entry) = @_; + $entry->{attributes} & $HIDDEN_ATTR || $entry->{attributes} & $SYSTEM_ATTR; +} + sub is_directory($) { my ($entry) = @_; $entry->{attributes} & $DIRECTORY_ATTR && $entry->{name} !~ /^\.\.? / && !is_special_entry($entry); @@ -50,8 +59,9 @@ sub is_special_entry($) { #- return true if entry has been modified +#- curr_dir_name is added to contains current directory name, "" for root. sub remap { - my ($entry) = @_; + my ($curr_dir_name, $entry) = @_; is_special_entry($entry) and return; diff --git a/perl-install/resize_fat/directory.pm b/perl-install/resize_fat/directory.pm index cdce4be88..1bc1014c6 100644 --- a/perl-install/resize_fat/directory.pm +++ b/perl-install/resize_fat/directory.pm @@ -32,8 +32,8 @@ 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) = @_; +sub traverse($$$) { + my ($directory, $curr_dir_name, $f) = @_; for (my $i = 0;; $i++) { my $raw = \substr($directory, $i * $psizeof_format, $psizeof_format); @@ -43,7 +43,7 @@ sub traverse($$) { my $entry; @{$entry}{@fields} = unpack $format, $$raw; - &$f($entry) + &$f($curr_dir_name, $entry) and $$raw = pack $format, @{$entry}{@fields}; } $directory; @@ -53,12 +53,12 @@ sub traverse_all($$) { my ($fs, $f) = @_; my $traverse_all; $traverse_all = sub { - my ($entry) = @_; + my ($curr_dir_name, $entry) = @_; - &$f($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)), $traverse_all); + 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) }; @@ -66,7 +66,7 @@ sub traverse_all($$) { 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); + traverse($directory, "", $traverse_all); undef $traverse_all; #- circular reference is no good for perl's poor GC :( } @@ -75,5 +75,5 @@ sub traverse_all($$) { #- directory entry sub remap($$) { my ($fs, $directory) = @_; - traverse($directory, \&resize_fat::dir_entry::remap); + traverse($directory, "", \&resize_fat::dir_entry::remap); } diff --git a/perl-install/resize_fat/fat.pm b/perl-install/resize_fat/fat.pm index 83426471a..33572624a 100644 --- a/perl-install/resize_fat/fat.pm +++ b/perl-install/resize_fat/fat.pm @@ -46,6 +46,10 @@ sub allocate_remap { resize_fat::c_rewritten::allocate_fat_remap($fs->{fat_size}); + #- patch to reset contents of memory allocated by allocate_fat_remap + #- divide by 4 because fat_size is in bytes. + foreach (0..$fs->{fat_size}/4 - 1) { resize_fat::c_rewritten::set_fat_remap($_, 0) } + $fs->{last_free_cluster} = 2; for ($cluster = 2; $cluster < $fs->{nb_clusters} + 2; $cluster++) { if ($cluster < $cut_point) { diff --git a/perl-install/resize_fat/main.pm b/perl-install/resize_fat/main.pm index ac2fffaa2..bac7f8ad1 100644 --- a/perl-install/resize_fat/main.pm +++ b/perl-install/resize_fat/main.pm @@ -114,6 +114,7 @@ sub construct_dir_tree { sub min_size($) { &resize_fat::any::min_size } sub max_size($) { &resize_fat::any::max_size } +sub used_size($) { &resize_fat::any::used_size } #- resize #- - size is in sectors @@ -124,7 +125,6 @@ sub resize { my ($min, $max) = (min_size($fs), max_size($fs)); - $size += $min if $size =~ /^\+/; $size >= $min or die "Minimum filesystem size is $min sectors"; @@ -134,24 +134,30 @@ sub resize { my $new_data_size = $size * $SECTORSIZE - $fs->{cluster_offset}; my $new_nb_clusters = divide($new_data_size, $fs->{cluster_size}); + my $used_size = used_size($fs); - log::l("resize_fat: Allocating new clusters"); - resize_fat::fat::allocate_remap($fs, $new_nb_clusters); + log::l("resize_fat: Break point for moving files is ". ($used_size * $SECTORSIZE >> 20) ." Mb ($used_size sectors)"); + if ($size < $used_size) { + log::l("resize_fat: Allocating new clusters"); + resize_fat::fat::allocate_remap($fs, $new_nb_clusters); - log::l("resize_fat: Copying files"); - copy_clusters($fs, $new_nb_clusters); + log::l("resize_fat: Copying files"); + copy_clusters($fs, $new_nb_clusters); - log::l("resize_fat: Copying directories"); - construct_dir_tree($fs); + log::l("resize_fat: Copying directories"); + construct_dir_tree($fs); - log::l("Writing new FAT..."); - resize_fat::fat::update($fs); - resize_fat::fat::write($fs); + log::l("Writing new FAT..."); + resize_fat::fat::update($fs); + resize_fat::fat::write($fs); + } else { + log::l("resize_fat: Nothing need to be moved"); + } $fs->{nb_sectors} = $size; $fs->{nb_clusters} = $new_nb_clusters; $fs->{clusters}{count}->{free} = - $fs->{nb_clusters} - $fs->{clusters}{count}->{used} - $fs->{clusters}->{count}->{bad} - 2; + $fs->{nb_clusters} - $fs->{clusters}{count}->{used} - $fs->{clusters}->{count}->{bad} - 2; $fs->{system_id} = 'was here!'; $fs->{small_nb_sectors} = 0; -- cgit v1.2.1