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
|
package resize_fat::boot_sector;
use diagnostics;
use strict;
use common qw(:common :system :constant);
use resize_fat::io;
use resize_fat::any;
use resize_fat::directory;
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
'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
'fat32_root_dir_cluster',
'info_offset_in_sectors',
'fat32_backup_sector',
# 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.
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->{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->{nb_sectors} < 32 and die "Too few sectors for viable file system\n";
if ($fs->{fat16_fat_length}) {
# asserting FAT16, will be verified later on
$fs->{fs_type} = 'FAT16';
$fs->{fs_type_size} = 16;
$fs->{fat_length} = $fs->{fat16_fat_length};
} else {
$resize_fat::isFAT32 = 1;
$fs->{fs_type} = 'FAT32';
$fs->{fs_type_size} = 32;
$fs->{fat_length} = $fs->{fat32_fat_length};
$fs->{nb_root_dir_entries} = 0;
$fs->{info_offset} = $fs->{info_offset_in_sectors} * $fs->{sector_size};
}
$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};
$fs->{root_dir_size} = $fs->{nb_root_dir_entries} * resize_fat::directory::entry_size();
$fs->{cluster_offset} = $fs->{root_dir_offset} + $fs->{root_dir_size} - 2 * $fs->{cluster_size};
$fs->{nb_fat_entries} = divide($fs->{fat_size}, $fs->{fs_type_size} / 8);
# - 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::max_cluster_count($fs) or die "error: too many sectors for a $fs->{fs_type}\n";
}
sub write($) {
my ($fs) = @_;
my $boot = pack($format, @{$fs}{@fields});
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
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}";
}
}
|