summaryrefslogtreecommitdiffstats
path: root/perl-install/resize_fat
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/resize_fat')
-rw-r--r--perl-install/resize_fat/Makefile16
-rw-r--r--perl-install/resize_fat/README4
-rw-r--r--perl-install/resize_fat/any.pm97
-rw-r--r--perl-install/resize_fat/boot_sector.pm76
-rw-r--r--perl-install/resize_fat/c_rewritten.pm2
-rw-r--r--perl-install/resize_fat/c_rewritten.xs195
-rw-r--r--perl-install/resize_fat/dir_entry.pm29
-rw-r--r--perl-install/resize_fat/directory.pm45
-rw-r--r--perl-install/resize_fat/fat.pm87
-rw-r--r--perl-install/resize_fat/info_sector.pm17
-rw-r--r--perl-install/resize_fat/io.pm29
-rw-r--r--perl-install/resize_fat/main.pm141
12 files changed, 480 insertions, 258 deletions
diff --git a/perl-install/resize_fat/Makefile b/perl-install/resize_fat/Makefile
index 34c257a4e..a82ca8441 100644
--- a/perl-install/resize_fat/Makefile
+++ b/perl-install/resize_fat/Makefile
@@ -1,12 +1,10 @@
-PRODUCT = libresize
-TARSOURCE = $(PRODUCT).tar.bz2
+.PHONY: clean
-.PHONY: clean tar
+c_rewritten: %: %.xs
+ test -e Makefile_c || perl Makefile.PL
+ $(MAKE) -f Makefile_c LD_RUN_PATH=
+ rm -f ../auto/resize_fat ; ln -s ../resize_fat/blib/arch/auto ../auto/resize_fat
clean:
- rm -f *~ TAGS $(TARSOURCE)
-
-tar: clean
- cp -f ../common.pm .
- cd .. ; tar cfy $(TARSOURCE) $(PRODUCT) ; mv $(TARSOURCE) $(PRODUCT)
- rm -f common.pm
+ test ! -e Makefile_c || $(MAKE) -f Makefile_c clean
+ rm -f *~ *.o
diff --git a/perl-install/resize_fat/README b/perl-install/resize_fat/README
index 2910c06c3..1c4798c82 100644
--- a/perl-install/resize_fat/README
+++ b/perl-install/resize_fat/README
@@ -1,5 +1,7 @@
-just do ./resize.pm and look at usage.
+TODO:
+resize_fat::fat::update($fs) should be called before doing undoable things
+(before the sync in construct_dir_tree)
BUGS:
no known bugs :)
diff --git a/perl-install/resize_fat/any.pm b/perl-install/resize_fat/any.pm
index d78a342be..3844e1c16 100644
--- a/perl-install/resize_fat/any.pm
+++ b/perl-install/resize_fat/any.pm
@@ -1,49 +1,79 @@
-package resize_fat::any;
+package resize_fat::any; # $Id$
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;
use resize_fat::directory;
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;
-# returns the number of clusters for a given filesystem type
+#- 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;
+ (1 << $ {{ FAT16 => 12, FAT32 => 12 }}{$fs->{fs_type}}) - 12;
}
sub max_cluster_count($) {
my ($fs) = @_;
- $resize_fat::bad_cluster_value - 2;
+ (1 << $ {{ FAT16 => 16, FAT32 => 28 }}{$fs->{fs_type}}) - 11;
}
-# calculates the minimum size of a partition, in physical sectors
+#- 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(-$_) }
+ die "any: empty FAT table of $fs->{nb_clusters} clusters";
+}
+#- 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(-$_) }
+
+ #- Oh at this point there are no unmoveable blocks!
+ 2;
+}
+
+#- calculates the minimum size of a partition, in physical sectors
sub min_size($) {
my ($fs) = @_;
- my $count = $fs->{clusters}->{count};
+ 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 :)
+ #- 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 = max($min_cluster_count, last_unmoveable($fs));
+
+ my $size = $min_cluster_count * divide($fs->{cluster_size}, $SECTORSIZE) +
+ divide($fs->{cluster_offset}, $SECTORSIZE) +
+ 64*1024*1024 / $SECTORSIZE; #- help with such more sectors (ie 64Mb).
+
+ #- help zindozs again with 512Mb+ at least else partition is ignored.
+ if ($resize_fat::isFAT32) {
+ $size = max($size, 524*1024*1024 / $SECTORSIZE);
+ }
+ $size;
- $min_cluster_count * divide($fs->{cluster_size}, $SECTORSIZE) +
- divide($fs->{cluster_offset}, $SECTORSIZE);
}
-# calculates the maximum size of a partition, in physical sectors
+#- calculates the maximum size of a partition, in physical sectors
sub max_size($) {
my ($fs) = @_;
@@ -52,31 +82,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(last_used($fs), min_cluster_count($fs));
+
+ $used_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.
+#- 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);
+ 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 }
- 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;
- }
+ my $nb = resize_fat::c_rewritten::checkFat($cluster, $type, "$curr_dir_name/$entry->{name}");
+ print "resize_fat:flag_clusters: check fat returned $nb of type $type for $curr_dir_name/$entry->{name}\n";
+ $nb_dirs += $nb if $type == $DIRECTORY;
+ 0;
};
- $fs->{fat_flag_map} = [ ($FREE) x ($fs->{nb_clusters} + 2) ];
- $fs->{clusters}->{count}->{dirs} = 0;
+
+ #- this must call allocate_fat_flag that zeroes the buffer allocated.
+ resize_fat::c_rewritten::allocate_fat_flag($fs->{nb_clusters} + 2);
+
resize_fat::directory::traverse_all($fs, $f);
+ $fs->{clusters}{count}{dirs} = $nb_dirs;
}
diff --git a/perl-install/resize_fat/boot_sector.pm b/perl-install/resize_fat/boot_sector.pm
index c236b1617..4ed4a73f7 100644
--- a/perl-install/resize_fat/boot_sector.pm
+++ b/perl-install/resize_fat/boot_sector.pm
@@ -1,69 +1,73 @@
-package resize_fat::boot_sector;
+package resize_fat::boot_sector; # $Id$
use diagnostics;
use strict;
-use common qw(:common :system :constant);
+use common qw(:common :system :constant :functional);
use resize_fat::io;
use resize_fat::any;
use resize_fat::directory;
+#- Oops, this will be unresizable on big-endian machine. trapped by signature.
my $format = "a3 a8 S C S C S S C S S S I I I S S I S S a458 S";
my @fields = (
- 'boot_jump', # boot strap short or near jump
- 'system_id', # Name - can be used to special case partition manager volumes
- 'sector_size', # bytes per logical sector
- 'cluster_size_in_sectors', # sectors/cluster
- 'nb_reserved', # reserved sectors
- 'nb_fats', # number of FATs
- 'nb_root_dir_entries', # number of root directory entries
- 'small_nb_sectors', # number of sectors: big_nb_sectors supersedes
- 'media', # media code
- 'fat16_fat_length', # sectors/FAT for FAT12/16
+ 'boot_jump', #- boot strap short or near jump
+ 'system_id', #- Name - can be used to special case partition manager volumes
+ 'sector_size', #- bytes per logical sector
+ 'cluster_size_in_sectors', #- sectors/cluster
+ 'nb_reserved', #- reserved sectors
+ 'nb_fats', #- number of FATs
+ 'nb_root_dir_entries', #- number of root directory entries
+ 'small_nb_sectors', #- number of sectors: big_nb_sectors supersedes
+ 'media', #- media code
+ 'fat16_fat_length', #- sectors/FAT for FAT12/16
'sectors_per_track',
'nb_heads',
- 'nb_hidden', # (unused)
- 'big_nb_sectors', # number of sectors (if small_nb_sectors == 0)
-
-# FAT32-only entries
- 'fat32_fat_length', # size of FAT in sectors
- 'fat32_flags', # bit8: fat mirroring,
- # low4: active fat
- 'fat32_version', # minor * 256 + major
+ 'nb_hidden', #- (unused)
+ 'big_nb_sectors', #- number of sectors (if small_nb_sectors == 0)
+
+#- FAT32-only entries
+ 'fat32_fat_length', #- size of FAT in sectors
+ 'fat32_flags', #- bit8: fat mirroring,
+ #- low4: active fat
+ 'fat32_version', #- minor * 256 + major
'fat32_root_dir_cluster',
'info_offset_in_sectors',
'fat32_backup_sector',
-# Common again...
- 'boot_code', # Boot code (or message)
- 'boot_sign', # 0xAA55
+#- Common again...
+ 'boot_code', #- Boot code (or message)
+ 'boot_sign', #- 0xAA55
);
1;
-# trimfs_init_boot_sector() - reads in the boot sector - gets important info out
-# of boot sector, and puts in main structure - performs sanity checks - returns 1
-# on success, 0 on failureparameters: filesystem an empty structure to fill.
+#- trimfs_init_boot_sector() - reads in the boot sector - gets important info out
+#- of boot sector, and puts in main structure - performs sanity checks - returns 1
+#- on success, 0 on failureparameters: filesystem an empty structure to fill.
sub read($) {
my ($fs) = @_;
-
+
my $boot = eval { resize_fat::io::read($fs, 0, $SECTORSIZE) }; $@ and die "reading boot sector failed on device $fs->{fs_name}";
@{$fs}{@fields} = unpack $format, $boot;
$fs->{nb_sectors} = $fs->{small_nb_sectors} || $fs->{big_nb_sectors};
- $fs->{cluster_size} = $fs->{cluster_size_in_sectors} * $fs->{sector_size};
+ $fs->{cluster_size} = $fs->{cluster_size_in_sectors} * $fs->{sector_size};
- $fs->{boot_sign} == 0xAA55 or die "Invalid signature for a MS-based filesystem.";
- $fs->{nb_fats} == 2 or die "Weird number of FATs: $fs->{nb_fats}, not 2.",
+ $fs->{boot_sign} == 0xAA55 or die "Invalid signature for a MS-based filesystem.\n";
$fs->{nb_sectors} < 32 and die "Too few sectors for viable file system\n";
+ $fs->{nb_fats} == 2 or cdie "Weird number of FATs: $fs->{nb_fats}, not 2.\n";
+ $fs->{sector_size} == 512 or cdie "Strange sector_size != 512\n";
if ($fs->{fat16_fat_length}) {
- # asserting FAT16, will be verified later on
+ #- asserting FAT16, will be verified later on
+ $resize_fat::isFAT32 = 0;
$fs->{fs_type} = 'FAT16';
$fs->{fs_type_size} = 16;
$fs->{fat_length} = $fs->{fat16_fat_length};
+ $resize_fat::bad_cluster_value = 0xfff7; #- 2**16 - 1
} else {
$resize_fat::isFAT32 = 1;
$fs->{fs_type} = 'FAT32';
@@ -72,9 +76,9 @@ sub read($) {
$fs->{nb_root_dir_entries} = 0;
$fs->{info_offset} = $fs->{info_offset_in_sectors} * $fs->{sector_size};
+ $resize_fat::bad_cluster_value = 0x0ffffff7;
}
- $resize_fat::bad_cluster_value = (1 << $fs->{fs_type_size}) - 9;
-
+
$fs->{fat_offset} = $fs->{nb_reserved} * $fs->{sector_size};
$fs->{fat_size} = $fs->{fat_length} * $fs->{sector_size};
$fs->{root_dir_offset} = $fs->{fat_offset} + $fs->{fat_size} * $fs->{nb_fats};
@@ -83,12 +87,12 @@ sub read($) {
$fs->{nb_fat_entries} = divide($fs->{fat_size}, $fs->{fs_type_size} / 8);
- # - 2 because clusters 0 & 1 doesn't exist
+ #- - 2 because clusters 0 & 1 doesn't exist
$fs->{nb_clusters} = divide($fs->{nb_sectors} * $fs->{sector_size} - $fs->{cluster_offset}, $fs->{cluster_size}) - 2;
$fs->{dir_entries_per_cluster} = divide($fs->{cluster_size}, psizeof($format));
- $fs->{nb_clusters} >= resize_fat::any::min_cluster_count($fs) or die "error: not enough sectors for a $fs->{fs_type}\n";
+#- $fs->{nb_clusters} >= resize_fat::any::min_cluster_count($fs) or die "error: not enough sectors for a $fs->{fs_type}\n";
$fs->{nb_clusters} < resize_fat::any::max_cluster_count($fs) or die "error: too many sectors for a $fs->{fs_type}\n";
}
@@ -99,7 +103,7 @@ sub write($) {
eval { resize_fat::io::write($fs, 0, $SECTORSIZE, $boot) }; $@ and die "writing the boot sector failed on device $fs->{fs_name}";
if ($resize_fat::isFAT32) {
- # write backup
+ #- write backup
eval { resize_fat::io::write($fs, $fs->{fat32_backup_sector} * $SECTORSIZE, $SECTORSIZE, $boot) };
$@ and die "writing the backup boot sector (#$fs->{fat32_backup_sector}) failed on device $fs->{fs_name}";
}
diff --git a/perl-install/resize_fat/c_rewritten.pm b/perl-install/resize_fat/c_rewritten.pm
index 1f5f505c7..d74ecb5d3 100644
--- a/perl-install/resize_fat/c_rewritten.pm
+++ b/perl-install/resize_fat/c_rewritten.pm
@@ -1,4 +1,4 @@
-package resize_fat::c_rewritten;
+package resize_fat::c_rewritten; # $Id$
use strict;
use vars qw($VERSION @ISA);
diff --git a/perl-install/resize_fat/c_rewritten.xs b/perl-install/resize_fat/c_rewritten.xs
index a42f3d133..92361097d 100644
--- a/perl-install/resize_fat/c_rewritten.xs
+++ b/perl-install/resize_fat/c_rewritten.xs
@@ -4,31 +4,105 @@
/* set by scan_fat, used by next */
short *fat = NULL;
+char *fat_flag_map = NULL;
+unsigned int *fat_remap = NULL;
+int fat_remap_size;
int type_size, nb_clusters, bad_cluster_value;
-char *fat_flag_map;
+
+void free_all() {
+#define FREE(p) if (p) free(p), p = NULL;
+ FREE(fat);
+ FREE(fat_flag_map);
+ FREE(fat_remap);
+#undef FREE
+}
unsigned int next(unsigned int cluster) {
short *p = fat + type_size * cluster;
- if (cluster > nb_clusters + 2) croak("fat::next: cluster %d outside filesystem", cluster);
+ if (!fat) {
+ free_all();
+ croak("fat::next: trying to use null pointer");
+ }
+ if (cluster >= nb_clusters + 2) {
+ free_all();
+ croak("fat::next: cluster %d outside filesystem", cluster);
+ }
return type_size == 1 ? *p : *((unsigned int *) p);
}
+void set_next(unsigned int cluster, unsigned int val) {
+ short *p = fat + type_size * cluster;
+ if (!fat) {
+ free_all();
+ croak("fat::set_next: trying to use null pointer");
+ }
+ if (cluster >= nb_clusters + 2) {
+ free_all();
+ croak("fat::set_next: cluster %d outside filesystem", cluster);
+ }
+ type_size == 1 ? *p : *((unsigned int *) p) = val;
+}
+
MODULE = resize_fat::c_rewritten PACKAGE = resize_fat::c_rewritten
+void
+read_fat(fd, offset, size, magic)
+ int fd
+ int offset
+ int size
+ unsigned char magic
+ PPCODE:
+{
+ fat = (short *) malloc(size);
+ if (!fat) {
+ free_all();
+ croak("read_fat: not enough memory");
+ }
+ if (lseek(fd, offset, SEEK_SET) != offset ||
+ read(fd, fat, size) != size) {
+ free_all();
+ croak("read_fat: reading FAT failed");
+ }
+ if (magic != *(unsigned char *) fat) {
+ free_all();
+ croak("read_fat: FAT has invalid signature");
+ }
+}
+
void
-scan_fat(fat_, nb_clusters_, type_size_)
- char *fat_
+write_fat(fd, size)
+ int fd
+ int size
+ PPCODE:
+{
+ if (write(fd, fat, size) != size) {
+ free_all();
+ croak("write_fat: write failed");
+ }
+}
+
+void
+free_all()
+ PPCODE:
+ free_all();
+
+void
+scan_fat(nb_clusters_, type_size_)
int nb_clusters_
int type_size_
PPCODE:
+{
unsigned int v;
int free = 0, bad = 0, used = 0;
short *p;
- fat = (short*) fat_; type_size = type_size_; nb_clusters = nb_clusters_;
- bad_cluster_value = type_size ? 0xffffff7 : 0xfff7;
+ type_size = type_size_; nb_clusters = nb_clusters_;
+ bad_cluster_value = type_size == 32 ? 0x0ffffff7 : 0xfff7;
- if (type_size % 16) fprintf(stderr, "unable to handle type_size"), exit(1);
+ if (type_size % 16) {
+ free_all();
+ croak("scan_fat: unable to handle FAT%d", type_size);
+ }
type_size /= 16;
for (p = fat + 2 * type_size; p < fat + type_size * (nb_clusters + 2); p += type_size) {
@@ -42,6 +116,7 @@ scan_fat(fat_, nb_clusters_, type_size_)
PUSHs(sv_2mortal(newSViv(free)));
PUSHs(sv_2mortal(newSViv(bad)));
PUSHs(sv_2mortal(newSViv(used)));
+}
unsigned int
next(unused, cluster)
@@ -52,20 +127,49 @@ next(unused, cluster)
OUTPUT:
RETVAL
+void
+set_next(unused, cluster, val)
+ void *unused
+ unsigned int cluster
+ unsigned int val
+ CODE:
+ set_next(cluster, val);
+
+void
+allocate_fat_flag(size)
+ int size
+ CODE:
+ fat_flag_map = calloc(size, 1);
+ if (!fat_flag_map) {
+ free_all();
+ croak("allocate_fat_flag: not enough memory");
+ }
+
int
-checkFat(fat_flag_map_, cluster, type, name)
- char *fat_flag_map_
+checkFat(cluster, type, name)
unsigned int cluster
int type
char *name
CODE:
int nb = 0;
- fat_flag_map = fat_flag_map_;
+ if (!fat_flag_map) {
+ free_all();
+ croak("Bad FAT: trying to use null pointer");
+ }
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 (cluster == 0) {
+ free_all();
+ croak("Bad FAT: unterminated chain for %s\n", name);
+ }
+ if (cluster >= nb_clusters + 2) {
+ free_all();
+ croak("Bad FAT: chain outside filesystem for %s\n", name);
+ }
+ if (fat_flag_map[cluster]) {
+ free_all();
+ croak("Bad FAT: cluster %d is cross-linked for %s\n", cluster, name);
+ }
fat_flag_map[cluster] = type;
nb++;
}
@@ -77,6 +181,14 @@ unsigned int
flag(cluster)
unsigned int cluster
CODE:
+ if (!fat_flag_map) {
+ free_all();
+ croak("Bad FAT: trying to use null pointer");
+ }
+ if (cluster >= nb_clusters + 2) {
+ free_all();
+ croak("Bad FAT: going outside filesystem");
+ }
RETVAL = fat_flag_map[cluster];
OUTPUT:
RETVAL
@@ -86,5 +198,62 @@ set_flag(cluster, flag)
unsigned int cluster
int flag
CODE:
+ if (!fat_flag_map) {
+ free_all();
+ croak("Bad FAT: trying to use null pointer");
+ }
+ if (cluster >= nb_clusters + 2) {
+ free_all();
+ croak("Bad FAT: going outside filesystem");
+ }
fat_flag_map[cluster] = flag;
+void
+allocate_fat_remap(size)
+ int size
+ CODE:
+ fat_remap_size = size;
+ fat_remap = (unsigned int *) calloc(size, sizeof(unsigned int *));
+ if (!fat_remap) {
+ free_all();
+ croak("allocate_fat_remap: not enough memory");
+ }
+
+unsigned int
+fat_remap(cluster)
+ unsigned int cluster
+ CODE:
+ if (!fat_remap) {
+ free_all();
+ croak("fat_remap: trying to use null pointer");
+ }
+ if (cluster >= bad_cluster_value) {
+ RETVAL = cluster; /* special cases */
+ } else {
+ if (cluster >= fat_remap_size) {
+ free_all();
+ croak("fat_remap: cluster %d >= %d in fat_remap", cluster, fat_remap_size);
+ }
+ RETVAL = fat_remap[cluster];
+ }
+ OUTPUT:
+ RETVAL
+
+void
+set_fat_remap(cluster, val)
+ unsigned int cluster
+ unsigned int val
+ CODE:
+ if (!fat_remap) {
+ free_all();
+ croak("set_fat_remap: trying to use null pointer");
+ }
+ if (cluster >= fat_remap_size) {
+ free_all();
+ croak("set_fat_remap: cluster %d >= %d in set_fat_remap", cluster, fat_remap_size);
+ }
+ if (val < bad_cluster_value && val >= fat_remap_size) {
+ free_all();
+ croak("set_fat_remap: remapping cluster %d to cluster %d >= %d in set_fat_remap", cluster, val, fat_remap_size);
+ }
+ fat_remap[cluster] = val;
diff --git a/perl-install/resize_fat/dir_entry.pm b/perl-install/resize_fat/dir_entry.pm
index fa5ebb344..b39c72094 100644
--- a/perl-install/resize_fat/dir_entry.pm
+++ b/perl-install/resize_fat/dir_entry.pm
@@ -1,10 +1,14 @@
-package resize_fat::dir_entry;
+package resize_fat::dir_entry; # $Id$
use diagnostics;
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;
@@ -13,7 +17,7 @@ my $DIRECTORY_ATTR = 0x10;
sub get_cluster($) {
my ($entry) = @_;
- $entry->{first_cluster} + ($resize_fat::isFAT32 ? $entry->{first_cluster_high} * 65536 : 0);
+ $entry->{first_cluster} + ($resize_fat::isFAT32 ? $entry->{first_cluster_high} * (1 << 16) : 0);
}
sub set_cluster($$) {
my ($entry, $val) = @_;
@@ -21,14 +25,14 @@ sub set_cluster($$) {
$entry->{first_cluster_high} = $val >> 16 if $resize_fat::isFAT32;
}
-sub is_directory_raw($) {
+sub is_unmoveable($) {
my ($entry) = @_;
- !is_special_entry($entry) && $entry->{attributes} & $DIRECTORY_ATTR;
+ $entry->{attributes} & $HIDDEN_ATTR || $entry->{attributes} & $SYSTEM_ATTR;
}
sub is_directory($) {
my ($entry) = @_;
- is_directory_raw($entry) && $entry->{name} !~ /^\.\.? /;
+ $entry->{attributes} & $DIRECTORY_ATTR && $entry->{name} !~ /^\.\.? / && !is_special_entry($entry);
}
sub is_volume($) {
@@ -46,7 +50,7 @@ sub is_special_entry($) {
my ($entry) = @_;
my ($c) = unpack "C", $entry->{name};
- # skip empty slots, deleted files, and 0xF6?? (taken from kernel)
+ #- skip empty slots, deleted files, and 0xF6?? (taken from kernel)
$c == 0 || $c == $DELETED_FLAG || $c == 0xF6 and return 1;
$entry->{attributes} == $VFAT_ATTR and return 1;
@@ -54,18 +58,19 @@ sub is_special_entry($) {
}
-# return true if entry has been modified
+#- return true if entry has been modified
+#- curr_dir_name is added to contains current directory name, "" for root.
sub remap {
- my ($fat_remap, $entry) = @_;
-
+ my ($curr_dir_name, $entry) = @_;
+
is_special_entry($entry) and return;
my $cluster = get_cluster($entry);
- my $new_cluster = $fat_remap->[$cluster];
+ my $new_cluster = resize_fat::c_rewritten::fat_remap($cluster);
- #print "remapping cluster ", get_first_cluster($fs, $entry), " to $new_cluster";
+ #-print "remapping cluster ", get_cluster($entry), " to $new_cluster";
- $new_cluster == $cluster and return; # no need to modify
+ $new_cluster == $cluster and return; #- no need to modify
set_cluster($entry, $new_cluster);
1;
diff --git a/perl-install/resize_fat/directory.pm b/perl-install/resize_fat/directory.pm
index ab8ec5328..beb780bcf 100644
--- a/perl-install/resize_fat/directory.pm
+++ b/perl-install/resize_fat/directory.pm
@@ -1,4 +1,4 @@
-package resize_fat::directory;
+package resize_fat::directory; # $Id$
use diagnostics;
use strict;
@@ -14,35 +14,36 @@ my @fields = (
'extension',
'attributes',
'is_upper_case_name',
- 'creation_time_low', # milliseconds
+ 'creation_time_low', #- milliseconds
'creation_time_high',
'creation_date',
'access_date',
- 'first_cluster_high', # for FAT32
+ 'first_cluster_high', #- for FAT32
'time',
'date',
'first_cluster',
'length',
);
+my $psizeof_format = psizeof($format);
1;
-sub entry_size { psizeof($format) }
+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
+#- call `f' for each entry of the directory
+#- if f return true, then modification in the entry are taken back
sub traverse($$$) {
- my ($fs, $directory, $f) = @_;
+ my ($directory, $curr_dir_name, $f) = @_;
- for (my $i = 0; 1; $i++) {
- my $raw = \substr($directory, $i * psizeof($format), psizeof($format));
+ for (my $i = 0;; $i++) {
+ my $raw = \substr($directory, $i * $psizeof_format, $psizeof_format);
- # empty entry means end of directory
+ #- empty entry means end of directory
$$raw =~ /^\0*$/ and return $directory;
my $entry; @{$entry}{@fields} = unpack $format, $$raw;
- &$f($entry)
+ &$f($curr_dir_name, $entry)
and $$raw = pack $format, @{$entry}{@fields};
}
$directory;
@@ -52,27 +53,27 @@ 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($fs, resize_fat::io::read_file($fs, resize_fat::dir_entry::get_cluster($entry)), $traverse_all);
+ 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)
+ 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($fs, $directory, $traverse_all);
+ 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 {
+#- function used by construct_dir_tree to translate the `cluster' fields in each
+#- directory entry
+sub remap($$) {
my ($fs, $directory) = @_;
-
- traverse($fs->{fat_remap}, $directory, sub { resize_fat::dir_entry::remap($fs->{fat_remap}, $_[0]) });
+ traverse($directory, "", \&resize_fat::dir_entry::remap);
}
diff --git a/perl-install/resize_fat/fat.pm b/perl-install/resize_fat/fat.pm
index 2b64bd6f7..31643f0a3 100644
--- a/perl-install/resize_fat/fat.pm
+++ b/perl-install/resize_fat/fat.pm
@@ -1,34 +1,21 @@
-package resize_fat::fat;
+package resize_fat::fat; # $Id$
use diagnostics;
use strict;
use resize_fat::any;
use resize_fat::io;
+use resize_fat::c_rewritten;
1;
sub read($) {
my ($fs) = @_;
- @{$fs->{fats}} = map {
- my $fat = eval { resize_fat::io::read($fs, $fs->{fat_offset} + $_ * $fs->{fat_size}, $fs->{fat_size}) };
- $@ and die "reading fat #$_ failed";
- vec($fat, 0, 8) == $fs->{media} or die "FAT $_ has invalid signature";
- $fat;
- } (0 .. $fs->{nb_fats} - 1);
+ resize_fat::c_rewritten::read_fat(fileno $fs->{fd}, $fs->{fat_offset}, $fs->{fat_size}, $fs->{media});
- $fs->{fat} = $fs->{fats}->[0];
-
- my ($free, $bad, $used) = (0, 0, 0);
-
- for (my $i = 2; $i < $fs->{nb_clusters} + 2; $i++) {
- my $cluster = &next($fs, $i);
- if ($cluster == 0) { $free++; }
- elsif ($cluster == $resize_fat::bad_cluster_value) { $bad++; }
- else { $used++; }
- }
- @{$fs->{clusters}->{count}}{qw(free bad used)} = ($free, $bad, $used);
+ @{$fs->{clusters}{count}}{qw(free bad used)} =
+ resize_fat::c_rewritten::scan_fat($fs->{nb_clusters}, $fs->{fs_type_size});
}
sub write($) {
@@ -36,32 +23,34 @@ sub write($) {
sysseek $fs->{fd}, $fs->{fat_offset}, 0 or die "write_fat: seek failed";
foreach (1..$fs->{nb_fats}) {
- syswrite $fs->{fd}, $fs->{fat}, $fs->{fat_size} or die "write_fat: write failed";
+ resize_fat::c_rewritten::write_fat(fileno $fs->{fd}, $fs->{fat_size});
}
}
-# allocates where all the clusters will be moved to. Clusters before cut_point
-# remain in the same position, however cluster that are part of a directory are
-# moved regardless (this is a mechanism to prevent data loss) (cut_point is the
-# first cluster that won't occur in the new fs)
+#- allocates where all the clusters will be moved to. Clusters before cut_point
+#- remain in the same position, however cluster that are part of a directory are
+#- moved regardless (this is a mechanism to prevent data loss) (cut_point is the
+#- first cluster that won't occur in the new fs)
sub allocate_remap {
my ($fs, $cut_point) = @_;
my ($cluster, $new_cluster);
- my $remap = sub { $fs->{fat_remap}->[$cluster] = $new_cluster; };
+ my $remap = sub { resize_fat::c_rewritten::set_fat_remap($cluster, $new_cluster) };
my $get_new = sub {
$new_cluster = get_free($fs);
0 < $new_cluster && $new_cluster < $cut_point or die "no free clusters";
- set_eof($fs, $new_cluster); # mark as used
- #log::ld("resize_fat: [$cluster,", &next($fs, $cluster), "...]->$new_cluster...");
+ set_eof($fs, $new_cluster); #- mark as used
+ #-log::ld("resize_fat: [$cluster,", &next($fs, $cluster), "...]->$new_cluster...");
};
- $fs->{fat_remap}->[0] = 0;
+ #- this must call allocate_fat_remap that zeroes the buffer allocated.
+ resize_fat::c_rewritten::allocate_fat_remap($fs->{nb_clusters} + 2);
+
$fs->{last_free_cluster} = 2;
for ($cluster = 2; $cluster < $fs->{nb_clusters} + 2; $cluster++) {
if ($cluster < $cut_point) {
- if ($fs->{fat_flag_map}->[$cluster] == $resize_fat::any::DIRECTORY) {
+ if (resize_fat::c_rewritten::flag($cluster) == $resize_fat::any::DIRECTORY) {
&$get_new();
} else {
$new_cluster = $cluster;
@@ -75,36 +64,26 @@ sub allocate_remap {
}
-# updates the fat for the resized filesystem
+#- updates the fat for the resized filesystem
sub update {
my ($fs) = @_;
for (my $cluster = 2; $cluster < $fs->{nb_clusters} + 2; $cluster++) {
- if ($fs->{fat_flag_map}->[$cluster]) {
+ if (resize_fat::c_rewritten::flag($cluster)) {
my $old_next = &next($fs, $cluster);
- my $new = $fs->{fat_remap}->[$cluster];
- my $new_next = $fs->{fat_remap}->[$old_next];
+ my $new = resize_fat::c_rewritten::fat_remap($cluster);
+ my $new_next = resize_fat::c_rewritten::fat_remap($old_next);
set_available($fs, $cluster);
is_eof($old_next) ?
set_eof($fs, $new) :
- set_next($fs, $new, $new_next);
+ set_next ($fs, $new, $new_next);
}
}
}
-# - compares the two FATs (one's a backup that should match) - skips first entry
-# - its just a signature (already checked above) NOTE: checks for cross-linking
-# are done in count.c
-sub check($) {
- my ($fs) = @_;
- foreach (@{$fs->{fats}}) {
- $_ eq $fs->{fats}->[0] or die "FAT tables do not match";
- }
-}
-
sub endianness16($) { (($_[0] & 0xff) << 8) + ($_[0] >> 8); }
sub endianness($$) {
my ($val, $nb_bits) = @_;
@@ -118,17 +97,9 @@ sub endianness($$) {
$r;
}
-sub next($$) {
- my ($fs, $cluster) = @_;
- $cluster > $fs->{nb_clusters} + 2 and die "fat::next: cluster $cluster outside filesystem";
- endianness(vec($fs->{fat}, $cluster, $fs->{fs_type_size}), $fs->{fs_type_size});
+*next = \&resize_fat::c_rewritten::next;
+*set_next = \&resize_fat::c_rewritten::set_next;
-}
-sub set_next($$$) {
- my ($fs, $cluster, $new_v) = @_;
- $cluster > $fs->{nb_clusters} + 2 and die "fat::set_next: cluster $cluster outside filesystem";
- vec($fs->{fat}, $cluster, $fs->{fs_type_size}) = endianness($new_v, $fs->{fs_type_size});
-}
sub get_free($) {
@@ -140,28 +111,28 @@ sub get_free($) {
die "no free clusters";
}
-# returns true if <cluster> represents an EOF marker
+#- returns true if <cluster> represents an EOF marker
sub is_eof($) {
my ($cluster) = @_;
$cluster >= $resize_fat::bad_cluster_value;
}
sub set_eof($$) {
my ($fs, $cluster) = @_;
- set_next($fs, $cluster, $resize_fat::bad_cluster_value + 1);
+ set_next ($fs, $cluster, $resize_fat::bad_cluster_value + 1);
}
-# returns true if <cluster> is empty. Note that this includes bad clusters.
+#- returns true if <cluster> is empty. Note that this includes bad clusters.
sub is_empty($) {
my ($cluster) = @_;
$cluster == 0 || $cluster == $resize_fat::bad_cluster_value;
}
-# returns true if <cluster> is available.
+#- returns true if <cluster> is available.
sub is_available($) {
my ($cluster) = @_;
$cluster == 0;
}
sub set_available($$) {
my ($fs, $cluster) = @_;
- set_next($fs, $cluster, 0);
+ set_next ($fs, $cluster, 0);
}
diff --git a/perl-install/resize_fat/info_sector.pm b/perl-install/resize_fat/info_sector.pm
index c46ae15fc..1d9c1690a 100644
--- a/perl-install/resize_fat/info_sector.pm
+++ b/perl-install/resize_fat/info_sector.pm
@@ -1,4 +1,4 @@
-package resize_fat::info_sector;
+package resize_fat::info_sector; # $Id$
use diagnostics;
use strict;
@@ -6,12 +6,13 @@ use strict;
use common qw(:system);
use resize_fat::io;
+#- Oops, this will be unresizable on big-endian machine. trapped by signature.
my $format = "a484 I I I a16";
my @fields = (
'unused',
- 'signature', # should be 0x61417272
- 'free_clusters', # -1 for unknown
- 'next_cluster', # most recently allocated cluster
+ 'signature', #- should be 0x61417272
+ 'free_clusters', #- -1 for unknown
+ 'next_cluster', #- most recently allocated cluster
'unused2',
);
@@ -20,15 +21,15 @@ my @fields = (
sub read($) {
my ($fs) = @_;
- my $info = resize_fat::io::read($fs, $fs->{offset}, psizeof($format));
+ my $info = resize_fat::io::read($fs, $fs->{info_offset}, psizeof($format));
@{$fs->{info_sector}}{@fields} = unpack $format, $info;
- $fs->{info_sector}->{signature} == 0x61417272 or die "Invalid information sector signature\n";
+ $fs->{info_sector}{signature} == 0x61417272 or die "Invalid information sector signature\n";
}
sub write($) {
my ($fs) = @_;
- $fs->{info_sector}->{free_clusters} = $fs->{clusters}->{count}->{free};
- $fs->{info_sector}->{next_cluster} = 2;
+ $fs->{info_sector}{free_clusters} = $fs->{clusters}->{count}->{free};
+ $fs->{info_sector}{next_cluster} = 2;
my $info = pack $format, @{$fs->{info_sector}}{@fields};
diff --git a/perl-install/resize_fat/io.pm b/perl-install/resize_fat/io.pm
index 8ffaa8355..7643a0953 100644
--- a/perl-install/resize_fat/io.pm
+++ b/perl-install/resize_fat/io.pm
@@ -1,16 +1,18 @@
-package resize_fat::io;
+package resize_fat::io; # $Id$
use diagnostics;
use strict;
use resize_fat::fat;
+use c;
1;
sub read($$$) {
my ($fs, $pos, $size) = @_;
- my $buf;
+ print "reading $size bytes at $pos\n";
+ my $buf = "\0" x $size;
sysseek $fs->{fd}, $pos, 0 or die "seeking to byte #$pos failed on device $fs->{fs_name}";
sysread $fs->{fd}, $buf, $size or die "reading at byte #$pos failed on device $fs->{fs_name}";
$buf;
@@ -18,36 +20,31 @@ sub read($$$) {
sub write($$$$) {
my ($fs, $pos, $size, $buf) = @_;
sysseek $fs->{fd}, $pos, 0 or die "seeking to byte #$pos failed on device $fs->{fs_name}";
- syswrite $fs->{fd}, $buf, $size or die "writing at byte #$pos failed on device $fs->{fs_name}";
+ syswrite $fs->{fd}, $buf or die "writing at byte #$pos failed on device $fs->{fs_name}";
}
sub read_cluster($$) {
my ($fs, $cluster) = @_;
my $buf;
+ my $pos = $fs->{cluster_offset} / 512 + $cluster * ($fs->{cluster_size} / 512);
- eval {
- $buf = &read($fs,
- $fs->{cluster_offset} + $cluster * $fs->{cluster_size},
- $fs->{cluster_size});
- }; @$ and die "reading cluster #$cluster failed on device $fs->{fs_name}";
+ c::lseek_sector(fileno $fs->{fd}, $pos, 0) or die "seeking to sector #$pos failed on device $fs->{fs_name}";
+ sysread $fs->{fd}, $buf, $fs->{cluster_size} or die "reading at sector #$pos failed on device $fs->{fs_name}";
$buf;
}
sub write_cluster($$$) {
my ($fs, $cluster, $buf) = @_;
+ my $pos = $fs->{cluster_offset} / 512 + $cluster * ($fs->{cluster_size} / 512);
- eval {
- &write($fs,
- $fs->{cluster_offset} + $cluster * $fs->{cluster_size},
- $fs->{cluster_size},
- $buf);
- }; @$ and die "writing cluster #$cluster failed on device $fs->{fs_name}";
+ c::lseek_sector(fileno $fs->{fd}, $pos, 0) or die "seeking to sector #$pos failed on device $fs->{fs_name}";
+ syswrite $fs->{fd}, $buf or die "writing at sector #$pos failed on device $fs->{fs_name}";
}
sub read_file($$) {
my ($fs, $cluster) = @_;
my $buf = '';
- for (; !resize_fat::fat::is_eof($cluster); $cluster = resize_fat::fat::next($fs, $cluster)) {
+ for (; !resize_fat::fat::is_eof($cluster); $cluster = resize_fat::fat::next ($fs, $cluster)) {
$cluster == 0 and die "Bad FAT: unterminated chain\n";
$buf .= read_cluster($fs, $cluster);
}
@@ -70,5 +67,5 @@ sub open($) {
check_mounted($fs->{device});
sysopen F, $fs->{fs_name}, 2 or sysopen F, $fs->{fs_name}, 0 or die "error opening device $fs->{fs_name} for writing\n";
- $fs->{fd} = \*F;
+ $fs->{fd} = *F;
}
diff --git a/perl-install/resize_fat/main.pm b/perl-install/resize_fat/main.pm
index 2d5f4f969..dc1a65e65 100644
--- a/perl-install/resize_fat/main.pm
+++ b/perl-install/resize_fat/main.pm
@@ -1,6 +1,25 @@
#!/usr/bin/perl
-package resize_fat::main;
+# DiskDrake
+# Copyright (C) 1999 MandrakeSoft (pixel@linux-mandrake.com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# This is mainly a perl rewrite of the work of Andrew Clausen (libresize)
+
+package resize_fat::main; # $Id$
use diagnostics;
use strict;
@@ -15,79 +34,86 @@ 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
+#- - 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);
-
+ eval {
+ 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::any::flag_clusters($fs);
+ };
+ if ($@) {
+ close $fs->{fd};
+ die;
+ }
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 DESTROY {
+ my ($fs) = @_;
+ close $fs->{fd};
+ resize_fat::c_rewritten::free_all();
+}
+
+#- 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 $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);
+ resize_fat::c_rewritten::flag($cluster) == $resize_fat::any::FILE or next;
+ push @buffer,
+ resize_fat::c_rewritten::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.
+#- 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;
+ 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
+ resize_fat::c_rewritten::set_flag($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::c_rewritten::flag($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)));
+ resize_fat::io::write_cluster($fs,
+ resize_fat::c_rewritten::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 :)
+ #- 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!
+ #- now we must be as fast as possible!
- # remapping non movable root directory
+ #- 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::io::write_cluster($fs,
+ resize_fat::c_rewritten::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},
@@ -97,44 +123,50 @@ 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
-# - checks boundaries before starting
-# - copies all data beyond new_cluster_count behind the frontier
+#- 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)");
+ log::l("resize_fat: Partition size will 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});
+ 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};
+ $fs->{clusters}{count}->{free} =
+ $fs->{nb_clusters} - $fs->{clusters}{count}->{used} - $fs->{clusters}->{count}->{bad} - 2;
$fs->{system_id} = 'was here!';
$fs->{small_nb_sectors} = 0;
@@ -144,9 +176,10 @@ sub resize {
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!
+ $resize_fat::isFAT32 and eval { resize_fat::info_sector::write($fs) }; #- doesn't matter if this fails - its pretty useless!
sync();
+ close $fs->{fd};
log::l("resize_fat: done");
}