3 Copyright (C) 1998-2001, 2007-2012 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <uuid/uuid.h>
27 fat_alloc (const PedGeometry* geom)
31 fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem));
35 fs->type_specific = (FatSpecific*) ped_malloc (sizeof (FatSpecific));
36 if (!fs->type_specific)
39 fs->geom = ped_geometry_duplicate (geom);
41 goto error_free_type_specific;
46 error_free_type_specific:
47 free (fs->type_specific);
54 /* Requires the boot sector to be analysed */
56 fat_alloc_buffers (PedFileSystem* fs)
58 FatSpecific* fs_info = FAT_SPECIFIC (fs);
60 fs_info->buffer_sectors = BUFFER_SIZE;
61 fs_info->buffer = ped_malloc (fs_info->buffer_sectors * 512);
65 fs_info->cluster_info = ped_malloc (fs_info->cluster_count + 2);
66 if (!fs_info->cluster_info)
67 goto error_free_buffer;
72 free (fs_info->buffer);
78 fat_free_buffers (PedFileSystem* fs)
80 FatSpecific* fs_info = FAT_SPECIFIC (fs);
82 free (fs_info->cluster_info);
83 free (fs_info->buffer);
87 fat_free (PedFileSystem* fs)
89 ped_geometry_destroy (fs->geom);
90 free (fs->type_specific);
95 fat_set_frag_sectors (PedFileSystem* fs, PedSector frag_sectors)
97 FatSpecific* fs_info = FAT_SPECIFIC (fs);
99 PED_ASSERT (fs_info->cluster_sectors % frag_sectors == 0
100 && frag_sectors <= fs_info->cluster_sectors);
102 fs_info->frag_size = frag_sectors * 512;
103 fs_info->frag_sectors = frag_sectors;
104 fs_info->buffer_frags = fs_info->buffer_sectors / frag_sectors;
105 fs_info->cluster_frags = fs_info->cluster_sectors / frag_sectors;
106 fs_info->frag_count = fs_info->cluster_count * fs_info->cluster_frags;
112 fat_probe (PedGeometry* geom, FatType* fat_type)
115 FatSpecific* fs_info;
118 fs = fat_alloc (geom);
121 fs_info = (FatSpecific*) fs->type_specific;
123 if (!fat_boot_sector_read (&fs_info->boot_sector, geom))
125 if (!fat_boot_sector_analyse (&fs_info->boot_sector, fs))
128 *fat_type = fs_info->fat_type;
129 result = ped_geometry_new (geom->dev, geom->start,
130 fs_info->sector_count);
142 fat_probe_fat16 (PedGeometry* geom)
145 PedGeometry* probed_geom = fat_probe (geom, &fat_type);
148 if (fat_type == FAT_TYPE_FAT16)
150 ped_geometry_destroy (probed_geom);
156 fat_probe_fat32 (PedGeometry* geom)
159 PedGeometry* probed_geom = fat_probe (geom, &fat_type);
162 if (fat_type == FAT_TYPE_FAT32)
164 ped_geometry_destroy (probed_geom);
169 #ifndef DISCOVER_ONLY
171 fat_clobber (PedGeometry* geom)
173 FatBootSector boot_sector;
175 if (!fat_boot_sector_read (&boot_sector, geom))
178 boot_sector.system_id[0] = 0;
179 boot_sector.boot_sign = 0;
180 if (boot_sector.u.fat16.fat_name[0] == 'F')
181 boot_sector.u.fat16.fat_name[0] = 0;
182 if (boot_sector.u.fat32.fat_name[0] == 'F')
183 boot_sector.u.fat32.fat_name[0] = 0;
185 return ped_geometry_write (geom, &boot_sector, 0, 1);
189 _init_fats (PedFileSystem* fs)
191 FatSpecific* fs_info = FAT_SPECIFIC (fs);
192 FatCluster table_size;
194 table_size = fs_info->fat_sectors * 512
195 / fat_table_entry_size (fs_info->fat_type);
196 fs_info->fat = fat_table_new (fs_info->fat_type, table_size);
200 if (!fat_table_read (fs_info->fat, fs, 0))
206 fat_table_destroy (fs_info->fat);
212 fat_open (PedGeometry* geom)
215 FatSpecific* fs_info;
217 fs = fat_alloc (geom);
220 fs_info = (FatSpecific*) fs->type_specific;
222 if (!fat_boot_sector_read (&fs_info->boot_sector, geom))
224 if (!fat_boot_sector_analyse (&fs_info->boot_sector, fs))
226 fs->type = (fs_info->fat_type == FAT_TYPE_FAT16)
229 if (fs_info->fat_type == FAT_TYPE_FAT32) {
230 if (!fat_info_sector_read (&fs_info->info_sector, fs))
234 if (!_init_fats (fs))
236 if (!fat_alloc_buffers (fs))
237 goto error_free_fat_table;
238 if (!fat_collect_cluster_info (fs))
239 goto error_free_buffers;
244 fat_free_buffers (fs);
245 error_free_fat_table:
246 fat_table_destroy (fs_info->fat);
254 fat_root_dir_clear (PedFileSystem* fs)
256 FatSpecific* fs_info = FAT_SPECIFIC (fs);
257 memset (fs_info->buffer, 0, 512 * fs_info->root_dir_sector_count);
258 return ped_geometry_write (fs->geom, fs_info->buffer,
259 fs_info->root_dir_offset,
260 fs_info->root_dir_sector_count);
263 /* hack: use the ext2 uuid library to generate a reasonably random (hopefully
264 * with /dev/random) number. Unfortunately, we can only use 4 bytes of it
267 _gen_new_serial_number (void)
274 uuid_generate (uu32.uuid);
279 fat_create (PedGeometry* geom, FatType fat_type, PedTimer* timer)
282 FatSpecific* fs_info;
283 FatCluster table_size;
285 fs = fat_alloc (geom);
288 fs_info = (FatSpecific*) fs->type_specific;
290 fs_info->logical_sector_size = 1;
291 fs_info->sectors_per_track = geom->dev->bios_geom.sectors;
292 fs_info->heads = geom->dev->bios_geom.heads;
293 fs_info->sector_count = fs->geom->length;
294 fs_info->fat_table_count = 2;
295 /* some initial values, to be changed later */
296 fs_info->root_dir_sector_count = FAT_ROOT_DIR_ENTRY_COUNT
297 / (512 / sizeof (FatDirEntry));
298 fs_info->root_dir_entry_count = FAT_ROOT_DIR_ENTRY_COUNT;
300 fs_info->fat_type = fat_type;
301 if (!fat_calc_sizes (fs->geom->length, 0,
303 fs_info->root_dir_sector_count,
304 &fs_info->cluster_sectors,
305 &fs_info->cluster_count,
306 &fs_info->fat_sectors)) {
307 ped_exception_throw (PED_EXCEPTION_ERROR,
308 PED_EXCEPTION_CANCEL,
309 _("Partition too big/small for a %s file system."),
310 (fat_type == FAT_TYPE_FAT16)
316 fs_info->cluster_size = fs_info->cluster_sectors * 512;
318 fs_info->fat_offset = fat_min_reserved_sector_count (fs_info->fat_type);
319 fs_info->dir_entries_per_cluster
320 = fs_info->cluster_size / sizeof (FatDirEntry);
322 if (fs_info->fat_type == FAT_TYPE_FAT16) {
324 fs->type = &fat16_type;
326 if (fs_info->cluster_count
327 > fat_max_cluster_count (fs_info->fat_type)) {
328 fs_info->cluster_count
329 = fat_max_cluster_count (fs_info->fat_type);
332 fs_info->root_dir_sector_count
333 = FAT_ROOT_DIR_ENTRY_COUNT
334 / (512 / sizeof (FatDirEntry));
335 fs_info->root_dir_entry_count = FAT_ROOT_DIR_ENTRY_COUNT;
336 fs_info->root_dir_offset
337 = fs_info->fat_offset
338 + fs_info->fat_sectors * fs_info->fat_table_count;
339 fs_info->cluster_offset
340 = fs_info->root_dir_offset
341 + fs_info->root_dir_sector_count;
344 fs->type = &fat32_type;
346 fs_info->info_sector_offset = 1;
347 fs_info->boot_sector_backup_offset = 6;
349 fs_info->root_dir_sector_count = 0;
350 fs_info->root_dir_entry_count = 0;
351 fs_info->root_dir_offset = 0;
353 fs_info->cluster_offset
354 = fs_info->fat_offset
355 + fs_info->fat_sectors * fs_info->fat_table_count;
358 table_size = fs_info->fat_sectors * 512
359 / fat_table_entry_size (fs_info->fat_type);
360 fs_info->fat = fat_table_new (fs_info->fat_type, table_size);
363 fat_table_set_cluster_count (fs_info->fat, fs_info->cluster_count);
364 if (!fat_alloc_buffers (fs))
365 goto error_free_fat_table;
367 if (fs_info->fat_type == FAT_TYPE_FAT32) {
368 fs_info->root_cluster
369 = fat_table_alloc_cluster (fs_info->fat);
370 fat_table_set_eof (fs_info->fat, fs_info->root_cluster);
371 memset (fs_info->buffer, 0, fs_info->cluster_size);
372 if (!fat_write_cluster (fs, fs_info->buffer,
373 fs_info->root_cluster))
377 fs_info->serial_number = _gen_new_serial_number ();
379 if (!fat_boot_sector_set_boot_code (&fs_info->boot_sector))
380 goto error_free_buffers;
381 if (!fat_boot_sector_generate (&fs_info->boot_sector, fs))
382 goto error_free_buffers;
383 if (!fat_boot_sector_write (&fs_info->boot_sector, fs))
384 goto error_free_buffers;
385 if (fs_info->fat_type == FAT_TYPE_FAT32) {
386 if (!fat_info_sector_generate (&fs_info->info_sector, fs))
387 goto error_free_buffers;
388 if (!fat_info_sector_write (&fs_info->info_sector, fs))
389 goto error_free_buffers;
392 if (!fat_table_write_all (fs_info->fat, fs))
393 goto error_free_buffers;
395 if (fs_info->fat_type == FAT_TYPE_FAT16) {
396 if (!fat_root_dir_clear (fs))
397 goto error_free_buffers;
403 fat_free_buffers (fs);
404 error_free_fat_table:
405 fat_table_destroy (fs_info->fat);
413 fat_create_fat16 (PedGeometry* geom, PedTimer* timer)
415 return fat_create (geom, FAT_TYPE_FAT16, timer);
419 fat_create_fat32 (PedGeometry* geom, PedTimer* timer)
421 return fat_create (geom, FAT_TYPE_FAT32, timer);
425 fat_close (PedFileSystem* fs)
427 FatSpecific* fs_info = FAT_SPECIFIC (fs);
429 fat_free_buffers (fs);
430 fat_table_destroy (fs_info->fat);
435 /* Hack: just resize the file system outside of its boundaries! */
437 fat_copy (const PedFileSystem* fs, PedGeometry* geom, PedTimer* timer)
439 PedFileSystem* new_fs;
441 new_fs = ped_file_system_open (fs->geom);
444 if (!ped_file_system_resize (new_fs, geom, timer))
445 goto error_close_new_fs;
449 ped_file_system_close (new_fs);
455 _compare_fats (PedFileSystem* fs)
457 FatSpecific* fs_info = FAT_SPECIFIC (fs);
458 FatTable* table_copy;
459 FatCluster table_size;
462 table_size = fs_info->fat_sectors * 512
463 / fat_table_entry_size (fs_info->fat_type);
465 table_copy = fat_table_new (fs_info->fat_type, table_size);
469 for (i = 1; i < fs_info->fat_table_count; i++) {
470 if (!fat_table_read (table_copy, fs, i))
471 goto error_free_table_copy;
472 if (!fat_table_compare (fs_info->fat, table_copy)) {
473 if (ped_exception_throw (PED_EXCEPTION_ERROR,
474 PED_EXCEPTION_IGNORE_CANCEL,
475 _("The FATs don't match. If you don't know "
476 "what this means, then select cancel, run "
477 "scandisk on the file system, and then come "
479 != PED_EXCEPTION_IGNORE)
480 goto error_free_table_copy;
484 fat_table_destroy (table_copy);
487 error_free_table_copy:
488 fat_table_destroy (table_copy);
494 fat_check (PedFileSystem* fs, PedTimer* timer)
496 FatSpecific* fs_info = FAT_SPECIFIC (fs);
497 PedSector cluster_sectors;
498 FatCluster cluster_count;
499 PedSector fat_sectors;
500 PedSector align_sectors;
501 FatCluster info_free_clusters;
503 align_sectors = fs_info->fat_offset
504 - fat_min_reserved_sector_count (fs_info->fat_type);
506 if (!fat_calc_sizes (fs->geom->length,
509 fs_info->root_dir_sector_count,
513 if (ped_exception_throw (PED_EXCEPTION_BUG,
514 PED_EXCEPTION_IGNORE_CANCEL,
515 _("There are no possible configurations for this FAT "
517 != PED_EXCEPTION_IGNORE)
521 if (fs_info->fat_type == FAT_TYPE_FAT16) {
522 if (cluster_sectors != fs_info->cluster_sectors
523 || cluster_count != fs_info->cluster_count
524 || fat_sectors != fs_info->fat_sectors) {
525 if (ped_exception_throw (PED_EXCEPTION_WARNING,
526 PED_EXCEPTION_IGNORE_CANCEL,
527 _("File system doesn't have expected sizes for "
528 "Windows to like it. "
529 "Cluster size is %dk (%dk expected); "
530 "number of clusters is %d (%d expected); "
531 "size of FATs is %d sectors (%d expected)."),
532 (int) fs_info->cluster_sectors / 2,
533 (int) cluster_sectors / 2,
534 (int) fs_info->cluster_count,
536 (int) fs_info->fat_sectors,
538 != PED_EXCEPTION_IGNORE)
543 if (fs_info->fat_type == FAT_TYPE_FAT32) {
545 = PED_LE32_TO_CPU (fs_info->info_sector.free_clusters);
546 if (info_free_clusters != (FatCluster) -1
547 && info_free_clusters != fs_info->fat->free_cluster_count) {
548 if (ped_exception_throw (PED_EXCEPTION_WARNING,
549 PED_EXCEPTION_IGNORE_CANCEL,
550 _("File system is reporting the free space as "
551 "%d clusters, not %d clusters."),
553 fs_info->fat->free_cluster_count)
554 != PED_EXCEPTION_IGNORE)
559 if (!_compare_fats (fs))
563 return 1; /* existence of fs implies consistency ;-) */
569 /* Calculates how much space there will be in clusters in:
570 * old_fs intersect the-new-fs
573 _calc_resize_data_size (
574 const PedFileSystem* old_fs,
575 PedSector new_cluster_sectors,
576 FatCluster new_cluster_count,
577 PedSector new_fat_size)
579 FatSpecific* old_fs_info = FAT_SPECIFIC (old_fs);
580 PedSector fat_size_delta;
582 fat_size_delta = old_fs_info->fat_sectors - new_fat_size;
583 return new_cluster_sectors * new_cluster_count - fat_size_delta * 2;
587 _test_resize_size (const PedFileSystem* fs,
588 PedSector length, PedSector min_data_size)
590 FatSpecific* fs_info = FAT_SPECIFIC (fs);
592 PedSector _cluster_sectors;
593 FatCluster _cluster_count;
596 ped_geometry_init (&geom, fs->geom->dev, fs->geom->start, length);
598 if (fat_calc_resize_sizes (
600 fs_info->cluster_sectors,
602 fs_info->root_dir_sector_count,
603 fs_info->cluster_sectors,
607 && _calc_resize_data_size (fs, _cluster_sectors, _cluster_count,
612 if (fat_calc_resize_sizes (
614 fs_info->cluster_sectors,
617 fs_info->cluster_sectors,
621 && _calc_resize_data_size (fs, _cluster_sectors, _cluster_count,
629 /* does a binary search (!) for the mininum size. Too hard to compute directly
630 * (see calc_sizes() for why!)
633 _get_min_resize_size (const PedFileSystem* fs, PedSector min_data_size)
635 PedSector min_length = 0;
636 PedSector max_length = fs->geom->length;
639 while (min_length < max_length - 1) {
640 length = (min_length + max_length) / 2;
641 if (_test_resize_size (fs, length, min_data_size))
647 /* adds a bit of leeway (64 sectors), for resolving extra issues, like root
648 * directory allocation, that aren't covered here.
650 return max_length + 64;
654 fat_get_copy_constraint (const PedFileSystem* fs, const PedDevice* dev)
656 FatSpecific* fs_info = FAT_SPECIFIC (fs);
657 PedGeometry full_dev;
658 PedSector min_cluster_count;
659 FatCluster used_clusters;
660 PedSector min_data_size;
662 if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1))
665 used_clusters = fs_info->fat->cluster_count
666 - fs_info->fat->free_cluster_count;
667 min_cluster_count = used_clusters + fs_info->total_dir_clusters;
668 min_data_size = min_cluster_count * fs_info->cluster_sectors;
670 return ped_constraint_new (ped_alignment_any, ped_alignment_any,
671 &full_dev, &full_dev,
672 _get_min_resize_size (fs, min_data_size),
677 fat_get_resize_constraint (const PedFileSystem* fs)
679 return fat_get_copy_constraint (fs, fs->geom->dev);
682 /* FIXME: fat_calc_sizes() needs to say "too big" or "too small", or
683 * something. This is a really difficult (maths) problem to do
685 * So, this algorithm works if dev->length / 2 is a valid fat_type
686 * size. (Which is how I got the magic numbers below)
689 /* returns: -1 too small, 0 ok, 1 too big */
691 _test_create_size (PedSector length, FatType fat_type,
692 PedSector cluster_sectors, PedSector cluster_count)
694 PedSector rootdir_sectors;
695 PedSector _cluster_sectors;
696 FatCluster _cluster_count;
699 rootdir_sectors = (fat_type == FAT_TYPE_FAT16) ? 16 : 0;
701 if (!fat_calc_sizes (length, 0, fat_type, rootdir_sectors,
702 &_cluster_sectors, &_cluster_count, &_fat_size))
703 return -1; // XXX: doesn't work... can't see a better way!
705 if (_cluster_sectors < cluster_sectors)
707 if (_cluster_sectors > cluster_sectors)
710 if (_cluster_count < cluster_count)
712 if (_cluster_count > cluster_count)
719 _get_create_size (PedSector upper_bound, FatType fat_type,
720 PedSector cluster_sectors, FatCluster cluster_count)
722 PedSector min_length = 0;
723 PedSector max_length = upper_bound;
727 length = (min_length + max_length) / 2;
728 switch (_test_create_size (length, fat_type, cluster_sectors,
730 case -1: min_length = length; break;
731 case 0: return length;
732 case 1: max_length = length; break;
734 /* hack... won't always be able to get max cluster count
735 * with max cluster size, etc. */
736 if (max_length - min_length == 1)
740 return 0; /* shut gcc up */
745 fat_get_create_constraint_fat16 (const PedDevice* dev)
747 PedGeometry full_dev;
751 if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1))
755 min_size = _get_create_size (dev->length, FAT_TYPE_FAT16,
756 fat_min_cluster_size (FAT_TYPE_FAT16),
757 fat_min_cluster_count (FAT_TYPE_FAT16));
758 max_size = _get_create_size (dev->length, FAT_TYPE_FAT16,
759 fat_max_cluster_size (FAT_TYPE_FAT16),
760 fat_max_cluster_count (FAT_TYPE_FAT16));
768 return ped_constraint_new (
769 ped_alignment_any, ped_alignment_any,
770 &full_dev, &full_dev,
775 fat_get_create_constraint_fat32 (const PedDevice* dev)
777 PedGeometry full_dev;
780 if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1))
784 min_size = _get_create_size (dev->length, FAT_TYPE_FAT32,
785 fat_min_cluster_size (FAT_TYPE_FAT32),
786 fat_min_cluster_count (FAT_TYPE_FAT32));
793 return ped_constraint_new (
794 ped_alignment_any, ped_alignment_any,
795 &full_dev, &full_dev,
796 min_size, dev->length);
798 #endif /* !DISCOVER_ONLY */
802 static PedFileSystemOps fat16_ops = {
803 probe: fat_probe_fat16,
804 #ifndef DISCOVER_ONLY
805 clobber: fat_clobber,
807 create: fat_create_fat16,
812 get_create_constraint: fat_get_create_constraint_fat16,
813 get_resize_constraint: fat_get_resize_constraint,
814 get_copy_constraint: fat_get_copy_constraint,
815 #else /* !DISCOVER_ONLY */
823 get_create_constraint: NULL,
824 get_resize_constraint: NULL,
825 get_copy_constraint: NULL,
826 #endif /* !DISCOVER_ONLY */
829 static PedFileSystemOps fat32_ops = {
830 probe: fat_probe_fat32,
831 #ifndef DISCOVER_ONLY
832 clobber: fat_clobber,
834 create: fat_create_fat32,
839 get_create_constraint: fat_get_create_constraint_fat32,
840 get_resize_constraint: fat_get_resize_constraint,
841 get_copy_constraint: fat_get_copy_constraint,
842 #else /* !DISCOVER_ONLY */
850 get_create_constraint: NULL,
851 get_resize_constraint: NULL,
852 get_copy_constraint: NULL,
853 #endif /* !DISCOVER_ONLY */
856 #define FAT_BLOCK_SIZES ((int[2]){512, 0})
858 PedFileSystemType fat16_type = {
862 block_sizes: FAT_BLOCK_SIZES
865 PedFileSystemType fat32_type = {
869 block_sizes: FAT_BLOCK_SIZES
873 ped_file_system_fat_init ()
875 if (sizeof (FatBootSector) != 512) {
876 ped_exception_throw (PED_EXCEPTION_BUG, PED_EXCEPTION_CANCEL,
877 _("GNU Parted was miscompiled: the FAT boot sector "
878 "should be 512 bytes. FAT support will be disabled."));
880 ped_file_system_type_register (&fat16_type);
881 ped_file_system_type_register (&fat32_type);
886 ped_file_system_fat_done ()
888 ped_file_system_type_unregister (&fat16_type);
889 ped_file_system_type_unregister (&fat32_type);