diff options
author | Chmouel Boudjnah <chmouel@mandriva.org> | 1999-07-01 12:29:54 +0000 |
---|---|---|
committer | Chmouel Boudjnah <chmouel@mandriva.org> | 1999-07-01 12:29:54 +0000 |
commit | e1729dfdb9c341fe0b9fed7d7b0a80691a547d82 (patch) | |
tree | b72fd8f59af166fe944ebcf114d648ed5644f752 /perl-install/resize_fat/main.pm | |
parent | b50e655e352e2524fb3fb84b2bb4bc96e6a04cf0 (diff) | |
download | drakx-backup-do-not-use-e1729dfdb9c341fe0b9fed7d7b0a80691a547d82.tar drakx-backup-do-not-use-e1729dfdb9c341fe0b9fed7d7b0a80691a547d82.tar.gz drakx-backup-do-not-use-e1729dfdb9c341fe0b9fed7d7b0a80691a547d82.tar.bz2 drakx-backup-do-not-use-e1729dfdb9c341fe0b9fed7d7b0a80691a547d82.tar.xz drakx-backup-do-not-use-e1729dfdb9c341fe0b9fed7d7b0a80691a547d82.zip |
"See_The_Changelog"
Diffstat (limited to 'perl-install/resize_fat/main.pm')
-rw-r--r-- | perl-install/resize_fat/main.pm | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/perl-install/resize_fat/main.pm b/perl-install/resize_fat/main.pm new file mode 100644 index 000000000..2d5f4f969 --- /dev/null +++ b/perl-install/resize_fat/main.pm @@ -0,0 +1,152 @@ +#!/usr/bin/perl + +package resize_fat::main; + +use diagnostics; +use strict; + +use log; +use common qw(:common :system :constant); +use resize_fat::boot_sector; +use resize_fat::info_sector; +use resize_fat::directory; +use resize_fat::io; +use resize_fat::fat; +use resize_fat::any; + + +#@ARGV == 2 or die "usage: fatresize <device> <size>\n <size> = 100 means `resize to 100Mb'\n <size> = +10 means `keep 10Mb of free space'\n"; +# +#my $fs = init($ARGV[0]); +#resize($fs, $ARGV[1]); + +1; + +# - reads in the boot sector/partition info., and tries to make some sense of it +sub new($$$) { + my ($type, $device, $fs_name) = @_; + my $fs = { device => $device, fs_name => $fs_name } ; + + resize_fat::io::open($fs); + resize_fat::boot_sector::read($fs); + $resize_fat::isFAT32 and eval { resize_fat::info_sector::read($fs) }; + resize_fat::fat::read($fs); + resize_fat::fat::check($fs); + resize_fat::any::flag_clusters($fs); + + bless $fs, $type; +} + +# copy all clusters >= <start_cluster> to a new place on the partition, less +# than <start_cluster>. Only copies files, not directories. +# (use of buffer needed because the seeks slow like hell the hard drive) +sub copy_clusters { + my ($fs, $cluster) = @_; + my @buffer; + my $flush = sub { + while (@buffer) { + my $cluster = shift @buffer; + resize_fat::io::write_cluster($fs, $cluster, shift @buffer); + } + }; + for (; $cluster < $fs->{nb_clusters} + 2; $cluster++) { + $fs->{fat_flag_map}->[$cluster] == $resize_fat::any::FILE or next; + push @buffer, $fs->{fat_remap}->[$cluster], resize_fat::io::read_cluster($fs, $cluster); + @buffer > 50 and &$flush(); + } + &$flush(); +} + +# Constructs the new directory tree to match the new file locations. +sub construct_dir_tree { + my ($fs) = @_; + + if ($resize_fat::isFAT32) { + # fat32's root must remain in the first 64k clusters + # so don't set it as DIRECTORY, it will be specially handled + $fs->{fat_flag_map}->[$fs->{fat32_root_dir_cluster}] = $resize_fat::any::FREE; + } + + for (my $cluster = 2; $cluster < $fs->{nb_clusters} + 2; $cluster++) { + $fs->{fat_flag_map}->[$cluster] == $resize_fat::any::DIRECTORY or next; + + resize_fat::io::write_cluster($fs, + $fs->{fat_remap}->[$cluster], + resize_fat::directory::remap($fs, resize_fat::io::read_cluster($fs, $cluster))); + } + + sync(); + + # until now, only free clusters have been written. it's a null operation if we stop here. + # it means no corruption :) + # + # now we must be as fast as possible! + + # remapping non movable root directory + if ($resize_fat::isFAT32) { + my $cluster = $fs->{fat32_root_dir_cluster}; + + resize_fat::io::write_cluster($fs, + $fs->{fat_remap}->[$cluster], + resize_fat::directory::remap($fs, resize_fat::io::read_cluster($fs, $cluster))); + } else { + resize_fat::io::write($fs, $fs->{root_dir_offset}, $fs->{root_dir_size}, + resize_fat::directory::remap($fs, resize_fat::io::read($fs, $fs->{root_dir_offset}, $fs->{root_dir_size}))); + } +} + +sub min_size($) { &resize_fat::any::min_size } +sub max_size($) { &resize_fat::any::max_size } + +# resize +# - size is in sectors +# - checks boundaries before starting +# - copies all data beyond new_cluster_count behind the frontier +sub resize { + my ($fs, $size) = @_; + + my ($min, $max) = (min_size($fs), max_size($fs)); + + + $size += $min if $size =~ /^\+/; + + $size >= $min or die "Minimum filesystem size is $min sectors"; + $size <= $max or die "Maximum filesystem size is $max sectors"; + + log::l("resize_fat: Partition size fill be ", $size * $SECTORSIZE >> 20, "Mb (well exactly ${size} sectors)"); + + my $new_data_size = $size * $SECTORSIZE - $fs->{cluster_offset}; + my $new_nb_clusters = divide($new_data_size, $fs->{cluster_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 directories"); + construct_dir_tree($fs); + + log::l("Writing new FAT..."); + resize_fat::fat::update($fs); + resize_fat::fat::write($fs); + + $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}; + + $fs->{system_id} = 'was here!'; + $fs->{small_nb_sectors} = 0; + $fs->{big_nb_sectors} = $size; + + log::l("resize_fat: Writing new boot sector..."); + + resize_fat::boot_sector::write($fs); + + $resize_fat::isFAT32 and eval { resize_fat::info_sector::write($fs) }; # doesn't matter if this fails - its pretty useless! + + sync(); + log::l("resize_fat: done"); +} + |