3 Copyright (C) 1998-2000, 2002, 2004, 2007, 2009 Free Software Foundation,
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include <sys/types.h>
32 fat_boot_sector_is_sane (const FatBootSector* bs)
34 PED_ASSERT (bs != NULL, return 0);
36 if (PED_LE16_TO_CPU (bs->boot_sign) != 0xAA55) {
37 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
38 _("File system has an invalid signature for a FAT "
43 if (!bs->system_id[0]) {
44 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
45 _("File system has an invalid signature for a FAT "
51 || PED_LE16_TO_CPU (bs->sector_size) % PED_SECTOR_SIZE_DEFAULT) {
52 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
53 _("File system has an invalid sector size for a FAT "
58 if (!bs->cluster_size) {
59 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
60 _("File system has an invalid cluster size for a FAT "
66 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
67 _("File system has an invalid number of reserved "
68 "sectors for a FAT file system."));
72 if (bs->fats < 1 || bs->fats > 4) {
73 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
74 _("File system has an invalid number of FATs."));
81 /* Reads in the boot sector (superblock), and does a minimum of sanity
82 * checking. The goals are:
83 * - to detect fat file systems, even if they are damaged [i.e. not
84 * return an error / throw an exception]
85 * - to fail detection if there's not enough information for
86 * fat_boot_sector_probe_type() to work (or possibly crash on a divide-by-zero)
89 fat_boot_sector_read (FatBootSector* bs, const PedGeometry *geom)
91 PED_ASSERT (bs != NULL, return 0);
92 PED_ASSERT (geom != NULL, return 0);
94 if (!ped_geometry_read (geom, bs, 0, 1))
97 return fat_boot_sector_is_sane (bs);
101 Don't trust the FAT12, FAT16 or FAT32 label string.
104 fat_boot_sector_probe_type (const FatBootSector* bs, const PedGeometry* geom)
106 PedSector logical_sector_size;
107 PedSector first_cluster_sector;
108 FatCluster cluster_count;
110 if (!PED_LE16_TO_CPU (bs->dir_entries))
111 return FAT_TYPE_FAT32;
113 logical_sector_size = PED_LE16_TO_CPU (bs->sector_size) / 512;
116 = PED_LE16_TO_CPU (bs->reserved) * logical_sector_size
117 + 2 * PED_LE16_TO_CPU (bs->fat_length) * logical_sector_size
118 + PED_LE16_TO_CPU (bs->dir_entries)
119 / (512 / sizeof (FatDirEntry));
120 cluster_count = (geom->length - first_cluster_sector)
121 / bs->cluster_size / logical_sector_size;
122 if (cluster_count > MAX_FAT12_CLUSTERS)
123 return FAT_TYPE_FAT16;
125 return FAT_TYPE_FAT12;
128 /* Analyses the boot sector, and sticks appropriate numbers in
131 Note: you need to subtract (2 * cluster_sectors) off cluster offset,
132 because the first cluster is number 2. (0 and 1 are not real clusters,
133 and referencing them is a bug)
136 fat_boot_sector_analyse (FatBootSector* bs, PedFileSystem* fs)
138 FatSpecific* fs_info = FAT_SPECIFIC (fs);
141 PED_ASSERT (bs != NULL, return 0);
143 if (PED_LE16_TO_CPU (bs->sector_size) != 512) {
144 if (ped_exception_throw (
146 PED_EXCEPTION_IGNORE_CANCEL,
147 _("This file system has a logical sector size of %d. "
148 "GNU Parted is known not to work properly with sector "
149 "sizes other than 512 bytes."),
150 (int) PED_LE16_TO_CPU (bs->sector_size))
151 != PED_EXCEPTION_IGNORE)
155 fs_info->logical_sector_size = PED_LE16_TO_CPU (bs->sector_size) / 512;
157 fs_info->sectors_per_track = PED_LE16_TO_CPU (bs->secs_track);
158 fs_info->heads = PED_LE16_TO_CPU (bs->heads);
159 if (fs_info->sectors_per_track < 1 || fs_info->sectors_per_track > 63
160 || fs_info->heads < 1 || fs_info->heads > 255) {
161 PedCHSGeometry* bios_geom = &fs->geom->dev->bios_geom;
164 if (fs_info->heads > 0 && fs_info->sectors_per_track > 0)
165 cyl_count = fs->geom->dev->length / fs_info->heads
166 / fs_info->sectors_per_track;
168 switch (ped_exception_throw (
170 PED_EXCEPTION_FIX + PED_EXCEPTION_IGNORE
171 + PED_EXCEPTION_CANCEL,
172 _("The file system's CHS geometry is (%d, %d, %d), "
173 "which is invalid. The partition table's CHS "
174 "geometry is (%d, %d, %d). If you select Ignore, "
175 "the file system's CHS geometry will be left "
176 "unchanged. If you select Fix, the file system's "
177 "CHS geometry will be set to match the partition "
178 "table's CHS geometry."),
179 cyl_count, fs_info->heads, fs_info->sectors_per_track,
180 bios_geom->cylinders, bios_geom->heads,
181 bios_geom->sectors)) {
183 case PED_EXCEPTION_FIX:
184 fs_info->sectors_per_track = bios_geom->sectors;
185 fs_info->heads = bios_geom->heads;
187 = PED_CPU_TO_LE16 (fs_info->sectors_per_track);
188 bs->heads = PED_CPU_TO_LE16 (fs_info->heads);
189 if (!fat_boot_sector_write (bs, fs))
193 case PED_EXCEPTION_CANCEL:
196 case PED_EXCEPTION_IGNORE:
205 fs_info->sector_count = PED_LE16_TO_CPU (bs->sectors)
206 * fs_info->logical_sector_size;
208 fs_info->sector_count = PED_LE32_TO_CPU (bs->sector_count)
209 * fs_info->logical_sector_size;
211 fs_info->fat_table_count = bs->fats;
212 fs_info->root_dir_entry_count = PED_LE16_TO_CPU (bs->dir_entries);
213 fs_info->fat_offset = PED_LE16_TO_CPU (bs->reserved)
214 * fs_info->logical_sector_size;
215 fs_info->cluster_sectors = bs->cluster_size
216 * fs_info->logical_sector_size;
217 fs_info->cluster_size = fs_info->cluster_sectors * 512;
219 if (fs_info->logical_sector_size == 0) {
220 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
221 _("FAT boot sector says logical sector size is 0. "
225 if (fs_info->fat_table_count == 0) {
226 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
227 _("FAT boot sector says there are no FAT tables. This "
231 if (fs_info->cluster_sectors == 0) {
232 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
233 _("FAT boot sector says clusters are 0 sectors. This "
238 fs_info->fat_type = fat_boot_sector_probe_type (bs, fs->geom);
239 if (fs_info->fat_type == FAT_TYPE_FAT12) {
240 ped_exception_throw (
241 PED_EXCEPTION_NO_FEATURE,
242 PED_EXCEPTION_CANCEL,
243 _("File system is FAT12, which is unsupported."));
246 if (fs_info->fat_type == FAT_TYPE_FAT16) {
247 fs_info->fat_sectors = PED_LE16_TO_CPU (bs->fat_length)
248 * fs_info->logical_sector_size;
249 fs_info->serial_number
250 = PED_LE32_TO_CPU (bs->u.fat16.serial_number);
251 fs_info->root_cluster = 0;
252 fs_info->root_dir_offset
253 = fs_info->fat_offset
254 + fs_info->fat_sectors * fs_info->fat_table_count;
255 fs_info->root_dir_sector_count
256 = fs_info->root_dir_entry_count * sizeof (FatDirEntry)
257 / (512 * fs_info->logical_sector_size);
258 fs_info->cluster_offset
259 = fs_info->root_dir_offset
260 + fs_info->root_dir_sector_count;
262 if (fs_info->fat_type == FAT_TYPE_FAT32) {
263 fs_info->fat_sectors = PED_LE32_TO_CPU (bs->u.fat32.fat_length)
264 * fs_info->logical_sector_size;
265 fs_info->serial_number
266 = PED_LE32_TO_CPU (bs->u.fat32.serial_number);
267 fs_info->info_sector_offset
268 = PED_LE16_TO_CPU (fs_info->boot_sector.u.fat32.info_sector)
269 * fs_info->logical_sector_size;
270 fs_info->boot_sector_backup_offset
271 = PED_LE16_TO_CPU (fs_info->boot_sector.u.fat32.backup_sector)
272 * fs_info->logical_sector_size;
273 fs_info->root_cluster
274 = PED_LE32_TO_CPU (bs->u.fat32.root_dir_cluster);
275 fs_info->root_dir_offset = 0;
276 fs_info->root_dir_sector_count = 0;
277 fs_info->cluster_offset
278 = fs_info->fat_offset
279 + fs_info->fat_sectors * fs_info->fat_table_count;
282 fs_info->cluster_count
283 = (fs_info->sector_count - fs_info->cluster_offset)
284 / fs_info->cluster_sectors;
286 fat_entry_size = fat_table_entry_size (fs_info->fat_type);
287 if (fs_info->cluster_count + 2
288 > fs_info->fat_sectors * 512 / fat_entry_size)
289 fs_info->cluster_count
290 = fs_info->fat_sectors * 512 / fat_entry_size - 2;
292 fs_info->dir_entries_per_cluster
293 = fs_info->cluster_size / sizeof (FatDirEntry);
297 #ifndef DISCOVER_ONLY
299 fat_boot_sector_set_boot_code (FatBootSector* bs)
301 PED_ASSERT (bs != NULL, return 0);
304 memcpy (bs->boot_jump, FAT_BOOT_JUMP, 3);
305 memcpy (bs->u.fat32.boot_code, FAT_BOOT_CODE, FAT_BOOT_CODE_LENGTH);
310 fat_boot_sector_generate (FatBootSector* bs, const PedFileSystem* fs)
312 FatSpecific* fs_info = FAT_SPECIFIC (fs);
314 PED_ASSERT (bs != NULL, return 0);
316 memcpy (bs->system_id, "MSWIN4.1", 8);
317 bs->sector_size = PED_CPU_TO_LE16 (fs_info->logical_sector_size * 512);
318 bs->cluster_size = fs_info->cluster_sectors
319 / fs_info->logical_sector_size;
320 bs->reserved = PED_CPU_TO_LE16 (fs_info->fat_offset
321 / fs_info->logical_sector_size);
322 bs->fats = fs_info->fat_table_count;
324 bs->dir_entries = (fs_info->fat_type == FAT_TYPE_FAT16)
325 ? PED_CPU_TO_LE16 (fs_info->root_dir_entry_count)
328 if (fs_info->sector_count / fs_info->logical_sector_size > 0xffff
329 || fs_info->fat_type == FAT_TYPE_FAT32) {
331 bs->sector_count = PED_CPU_TO_LE32 (fs_info->sector_count
332 / fs_info->logical_sector_size);
334 bs->sectors = PED_CPU_TO_LE16 (fs_info->sector_count
335 / fs_info->logical_sector_size);
336 bs->sector_count = 0;
341 bs->secs_track = PED_CPU_TO_LE16 (fs_info->sectors_per_track);
342 bs->heads = PED_CPU_TO_LE16 (fs_info->heads);
343 bs->hidden = PED_CPU_TO_LE32 (fs->geom->start);
345 if (fs_info->fat_type == FAT_TYPE_FAT32) {
347 bs->u.fat32.fat_length = PED_CPU_TO_LE32 (fs_info->fat_sectors
348 / fs_info->logical_sector_size);
349 bs->u.fat32.flags = 0; /* FIXME: what the hell are these? */
350 bs->u.fat32.version = 0; /* must be 0, for Win98 bootstrap */
351 bs->u.fat32.root_dir_cluster
352 = PED_CPU_TO_LE32 (fs_info->root_cluster);
353 bs->u.fat32.info_sector
354 = PED_CPU_TO_LE16 (fs_info->info_sector_offset
355 / fs_info->logical_sector_size);
356 bs->u.fat32.backup_sector
357 = PED_CPU_TO_LE16 (fs_info->boot_sector_backup_offset
358 / fs_info->logical_sector_size);
360 bs->u.fat32.drive_num = 0x80; /* _ALWAYS_ 0x80. silly DOS */
362 memset (bs->u.fat32.empty_1, 0, 12);
364 bs->u.fat32.ext_signature = 0x29;
365 bs->u.fat32.serial_number
366 = PED_CPU_TO_LE32 (fs_info->serial_number);
367 memcpy (bs->u.fat32.volume_name, "NO NAME ", 11);
368 memcpy (bs->u.fat32.fat_name, "FAT32 ", 8);
371 = PED_CPU_TO_LE16 (fs_info->fat_sectors
372 / fs_info->logical_sector_size);
374 bs->u.fat16.drive_num = 0x80; /* _ALWAYS_ 0x80. silly DOS */
376 bs->u.fat16.ext_signature = 0x29;
377 bs->u.fat16.serial_number
378 = PED_CPU_TO_LE32 (fs_info->serial_number);
379 memcpy (bs->u.fat16.volume_name, "NO NAME ", 11);
380 memcpy (bs->u.fat16.fat_name, "FAT16 ", 8);
383 bs->boot_sign = PED_CPU_TO_LE16 (0xaa55);
389 fat_boot_sector_write (const FatBootSector* bs, PedFileSystem* fs)
391 FatSpecific* fs_info = FAT_SPECIFIC (fs);
393 PED_ASSERT (bs != NULL, return 0);
395 /* Allocate a sector-sized buffer and copy bs into it
396 at the beginning. Fill any remainder with zeros. */
397 size_t buf_len = fs->geom->dev->sector_size;
398 char *buf = ped_malloc (buf_len);
399 memcpy (buf, bs, sizeof *bs);
400 memset (buf + sizeof *bs, 0, buf_len - sizeof *bs);
403 = (ped_geometry_write (fs->geom, buf, 0, 1)
404 && (fs_info->fat_type != FAT_TYPE_FAT32
405 || ped_geometry_write (fs->geom, buf,
406 fs_info->boot_sector_backup_offset, 1)));
409 ped_geometry_sync (fs->geom);
414 fat_info_sector_read (FatInfoSector* is, const PedFileSystem* fs)
416 FatSpecific* fs_info = FAT_SPECIFIC (fs);
419 PED_ASSERT (is != NULL, return 0);
421 if (!ped_geometry_read (fs->geom, is, fs_info->info_sector_offset, 1))
424 if (PED_LE32_TO_CPU (is->signature_2) != FAT32_INFO_MAGIC2) {
425 status = ped_exception_throw (PED_EXCEPTION_WARNING,
426 PED_EXCEPTION_IGNORE_CANCEL,
427 _("The information sector has the wrong "
428 "signature (%x). Select cancel for now, "
429 "and send in a bug report. If you're "
430 "desperate, it's probably safe to ignore."),
431 PED_LE32_TO_CPU (is->signature_2));
432 if (status == PED_EXCEPTION_CANCEL) return 0;
438 fat_info_sector_generate (FatInfoSector* is, const PedFileSystem* fs)
440 FatSpecific* fs_info = FAT_SPECIFIC (fs);
442 PED_ASSERT (is != NULL, return 0);
444 fat_table_count_stats (fs_info->fat);
448 is->signature_1 = PED_CPU_TO_LE32 (FAT32_INFO_MAGIC1);
449 is->signature_2 = PED_CPU_TO_LE32 (FAT32_INFO_MAGIC2);
450 is->free_clusters = PED_CPU_TO_LE32 (fs_info->fat->free_cluster_count);
451 is->next_cluster = PED_CPU_TO_LE32 (fs_info->fat->last_alloc);
452 is->signature_3 = PED_CPU_TO_LE16 (FAT32_INFO_MAGIC3);
458 fat_info_sector_write (const FatInfoSector* is, PedFileSystem *fs)
460 FatSpecific* fs_info = FAT_SPECIFIC (fs);
462 PED_ASSERT (is != NULL, return 0);
464 if (!ped_geometry_write (fs->geom, is, fs_info->info_sector_offset, 1))
466 return ped_geometry_sync (fs->geom);
468 #endif /* !DISCOVER_ONLY */