1 /* 2 libparted 3 Copyright (C) 1998, 1999, 2000, 2001, 2007 Free Software Foundation, Inc. 4 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. 9 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. 14 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/>. 17 */ 18 19 #include <config.h> 20 #include <string.h> 21 #include <uuid/uuid.h> 22 23 #include "fat.h" 24 #include "calc.h" 25 26 PedFileSystem* 27 fat_alloc (const PedGeometry* geom) 28 { 29 PedFileSystem* fs; 30 31 fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem)); 32 if (!fs) 33 goto error; 34 35 fs->type_specific = (FatSpecific*) ped_malloc (sizeof (FatSpecific)); 36 if (!fs->type_specific) 37 goto error_free_fs; 38 39 fs->geom = ped_geometry_duplicate (geom); 40 if (!fs->geom) 41 goto error_free_type_specific; 42 43 fs->checked = 0; 44 return fs; 45 46 error_free_type_specific: 47 ped_free (fs->type_specific); 48 error_free_fs: 49 ped_free (fs); 50 error: 51 return NULL; 52 } 53 54 /* Requires the boot sector to be analysed */ 55 int 56 fat_alloc_buffers (PedFileSystem* fs) 57 { 58 FatSpecific* fs_info = FAT_SPECIFIC (fs); 59 60 fs_info->buffer_sectors = BUFFER_SIZE; 61 fs_info->buffer = ped_malloc (fs_info->buffer_sectors * 512); 62 if (!fs_info->buffer) 63 goto error; 64 65 fs_info->cluster_info = ped_malloc (fs_info->cluster_count + 2); 66 if (!fs_info->cluster_info) 67 goto error_free_buffer; 68 69 return 1; 70 71 error_free_buffer: 72 ped_free (fs_info->buffer); 73 error: 74 return 0; 75 } 76 77 void 78 fat_free_buffers (PedFileSystem* fs) 79 { 80 FatSpecific* fs_info = FAT_SPECIFIC (fs); 81 82 ped_free (fs_info->cluster_info); 83 ped_free (fs_info->buffer); 84 } 85 86 void 87 fat_free (PedFileSystem* fs) 88 { 89 ped_geometry_destroy (fs->geom); 90 ped_free (fs->type_specific); 91 ped_free (fs); 92 } 93 94 int 95 fat_set_frag_sectors (PedFileSystem* fs, PedSector frag_sectors) 96 { 97 FatSpecific* fs_info = FAT_SPECIFIC (fs); 98 99 PED_ASSERT (fs_info->cluster_sectors % frag_sectors == 0 100 && frag_sectors <= fs_info->cluster_sectors, 101 return 0); 102 103 fs_info->frag_size = frag_sectors * 512; 104 fs_info->frag_sectors = frag_sectors; 105 fs_info->buffer_frags = fs_info->buffer_sectors / frag_sectors; 106 fs_info->cluster_frags = fs_info->cluster_sectors / frag_sectors; 107 fs_info->frag_count = fs_info->cluster_count * fs_info->cluster_frags; 108 109 return 1; 110 } 111 112 PedGeometry* 113 fat_probe (PedGeometry* geom, FatType* fat_type) 114 { 115 PedFileSystem* fs; 116 FatSpecific* fs_info; 117 PedGeometry* result; 118 119 fs = fat_alloc (geom); 120 if (!fs) 121 goto error; 122 fs_info = (FatSpecific*) fs->type_specific; 123 124 if (!fat_boot_sector_read (&fs_info->boot_sector, geom)) 125 goto error_free_fs; 126 if (!fat_boot_sector_analyse (&fs_info->boot_sector, fs)) 127 goto error_free_fs; 128 129 *fat_type = fs_info->fat_type; 130 result = ped_geometry_new (geom->dev, geom->start, 131 fs_info->sector_count); 132 133 fat_free (fs); 134 return result; 135 136 error_free_fs: 137 fat_free (fs); 138 error: 139 return NULL; 140 } 141 142 PedGeometry* 143 fat_probe_fat16 (PedGeometry* geom) 144 { 145 FatType fat_type; 146 PedGeometry* probed_geom = fat_probe (geom, &fat_type); 147 148 if (probed_geom) { 149 if (fat_type == FAT_TYPE_FAT16) 150 return probed_geom; 151 ped_geometry_destroy (probed_geom); 152 } 153 return NULL; 154 } 155 156 PedGeometry* 157 fat_probe_fat32 (PedGeometry* geom) 158 { 159 FatType fat_type; 160 PedGeometry* probed_geom = fat_probe (geom, &fat_type); 161 162 if (probed_geom) { 163 if (fat_type == FAT_TYPE_FAT32) 164 return probed_geom; 165 ped_geometry_destroy (probed_geom); 166 } 167 return NULL; 168 } 169 170 #ifndef DISCOVER_ONLY 171 int 172 fat_clobber (PedGeometry* geom) 173 { 174 FatBootSector boot_sector; 175 176 if (!fat_boot_sector_read (&boot_sector, geom)) 177 return 1; 178 179 boot_sector.system_id[0] = 0; 180 boot_sector.boot_sign = 0; 181 if (boot_sector.u.fat16.fat_name[0] == 'F') 182 boot_sector.u.fat16.fat_name[0] = 0; 183 if (boot_sector.u.fat32.fat_name[0] == 'F') 184 boot_sector.u.fat32.fat_name[0] = 0; 185 186 return ped_geometry_write (geom, &boot_sector, 0, 1); 187 } 188 189 static int 190 _init_fats (PedFileSystem* fs) 191 { 192 FatSpecific* fs_info = FAT_SPECIFIC (fs); 193 FatCluster table_size; 194 195 table_size = fs_info->fat_sectors * 512 196 / fat_table_entry_size (fs_info->fat_type); 197 fs_info->fat = fat_table_new (fs_info->fat_type, table_size); 198 if (!fs_info->fat) 199 goto error; 200 201 if (!fat_table_read (fs_info->fat, fs, 0)) 202 goto error_free_fat; 203 204 return 1; 205 206 error_free_fat: 207 fat_table_destroy (fs_info->fat); 208 error: 209 return 0; 210 } 211 212 PedFileSystem* 213 fat_open (PedGeometry* geom) 214 { 215 PedFileSystem* fs; 216 FatSpecific* fs_info; 217 218 fs = fat_alloc (geom); 219 if (!fs) 220 goto error; 221 fs_info = (FatSpecific*) fs->type_specific; 222 223 if (!fat_boot_sector_read (&fs_info->boot_sector, geom)) 224 goto error_free_fs; 225 if (!fat_boot_sector_analyse (&fs_info->boot_sector, fs)) 226 goto error_free_fs; 227 fs->type = (fs_info->fat_type == FAT_TYPE_FAT16) 228 ? &fat16_type 229 : &fat32_type; 230 if (fs_info->fat_type == FAT_TYPE_FAT32) { 231 if (!fat_info_sector_read (&fs_info->info_sector, fs)) 232 goto error_free_fs; 233 } 234 235 if (!_init_fats (fs)) 236 goto error_free_fs; 237 if (!fat_alloc_buffers (fs)) 238 goto error_free_fat_table; 239 if (!fat_collect_cluster_info (fs)) 240 goto error_free_buffers; 241 242 return fs; 243 244 error_free_buffers: 245 fat_free_buffers (fs); 246 error_free_fat_table: 247 fat_table_destroy (fs_info->fat); 248 error_free_fs: 249 fat_free (fs); 250 error: 251 return NULL; 252 } 253 254 static int 255 fat_root_dir_clear (PedFileSystem* fs) 256 { 257 FatSpecific* fs_info = FAT_SPECIFIC (fs); 258 memset (fs_info->buffer, 0, 512 * fs_info->root_dir_sector_count); 259 return ped_geometry_write (fs->geom, fs_info->buffer, 260 fs_info->root_dir_offset, 261 fs_info->root_dir_sector_count); 262 } 263 264 /* hack: use the ext2 uuid library to generate a reasonably random (hopefully 265 * with /dev/random) number. Unfortunately, we can only use 4 bytes of it 266 */ 267 static uint32_t 268 _gen_new_serial_number () 269 { 270 uuid_t uuid; 271 272 uuid_generate (uuid); 273 return * (uint32_t*) &uuid [0]; 274 } 275 276 PedFileSystem* 277 fat_create (PedGeometry* geom, FatType fat_type, PedTimer* timer) 278 { 279 PedFileSystem* fs; 280 FatSpecific* fs_info; 281 FatCluster table_size; 282 283 fs = fat_alloc (geom); 284 if (!fs) 285 goto error; 286 fs_info = (FatSpecific*) fs->type_specific; 287 288 fs_info->logical_sector_size = 1; 289 fs_info->sectors_per_track = geom->dev->bios_geom.sectors; 290 fs_info->heads = geom->dev->bios_geom.heads; 291 fs_info->sector_count = fs->geom->length; 292 fs_info->fat_table_count = 2; 293 /* some initial values, to be changed later */ 294 fs_info->root_dir_sector_count = FAT_ROOT_DIR_ENTRY_COUNT 295 / (512 / sizeof (FatDirEntry)); 296 fs_info->root_dir_entry_count = FAT_ROOT_DIR_ENTRY_COUNT; 297 298 fs_info->fat_type = fat_type; 299 if (!fat_calc_sizes (fs->geom->length, 0, 300 fs_info->fat_type, 301 fs_info->root_dir_sector_count, 302 &fs_info->cluster_sectors, 303 &fs_info->cluster_count, 304 &fs_info->fat_sectors)) { 305 ped_exception_throw (PED_EXCEPTION_ERROR, 306 PED_EXCEPTION_CANCEL, 307 _("Partition too big/small for a %s file system."), 308 (fat_type == FAT_TYPE_FAT16) 309 ? fat16_type.name 310 : fat32_type.name); 311 goto error_free_fs; 312 } 313 314 fs_info->cluster_size = fs_info->cluster_sectors * 512; 315 316 fs_info->fat_offset = fat_min_reserved_sector_count (fs_info->fat_type); 317 fs_info->dir_entries_per_cluster 318 = fs_info->cluster_size / sizeof (FatDirEntry); 319 320 if (fs_info->fat_type == FAT_TYPE_FAT16) { 321 /* FAT16 */ 322 fs->type = &fat16_type; 323 324 if (fs_info->cluster_count 325 > fat_max_cluster_count (fs_info->fat_type)) { 326 fs_info->cluster_count 327 = fat_max_cluster_count (fs_info->fat_type); 328 } 329 330 fs_info->root_dir_sector_count 331 = FAT_ROOT_DIR_ENTRY_COUNT 332 / (512 / sizeof (FatDirEntry)); 333 fs_info->root_dir_entry_count = FAT_ROOT_DIR_ENTRY_COUNT; 334 fs_info->root_dir_offset 335 = fs_info->fat_offset 336 + fs_info->fat_sectors * fs_info->fat_table_count; 337 fs_info->cluster_offset 338 = fs_info->root_dir_offset 339 + fs_info->root_dir_sector_count; 340 } else { 341 /* FAT32 */ 342 fs->type = &fat32_type; 343 344 fs_info->info_sector_offset = 1; 345 fs_info->boot_sector_backup_offset = 6; 346 347 fs_info->root_dir_sector_count = 0; 348 fs_info->root_dir_entry_count = 0; 349 fs_info->root_dir_offset = 0; 350 351 fs_info->cluster_offset 352 = fs_info->fat_offset 353 + fs_info->fat_sectors * fs_info->fat_table_count; 354 } 355 356 table_size = fs_info->fat_sectors * 512 357 / fat_table_entry_size (fs_info->fat_type); 358 fs_info->fat = fat_table_new (fs_info->fat_type, table_size); 359 if (!fs_info->fat) 360 goto error_free_fs; 361 fat_table_set_cluster_count (fs_info->fat, fs_info->cluster_count); 362 if (!fat_alloc_buffers (fs)) 363 goto error_free_fat_table; 364 365 if (fs_info->fat_type == FAT_TYPE_FAT32) { 366 fs_info->root_cluster 367 = fat_table_alloc_cluster (fs_info->fat); 368 fat_table_set_eof (fs_info->fat, fs_info->root_cluster); 369 memset (fs_info->buffer, 0, fs_info->cluster_size); 370 if (!fat_write_cluster (fs, fs_info->buffer, 371 fs_info->root_cluster)) 372 return 0; 373 } 374 375 fs_info->serial_number = _gen_new_serial_number (); 376 377 if (!fat_boot_sector_set_boot_code (&fs_info->boot_sector)) 378 goto error_free_buffers; 379 if (!fat_boot_sector_generate (&fs_info->boot_sector, fs)) 380 goto error_free_buffers; 381 if (!fat_boot_sector_write (&fs_info->boot_sector, fs)) 382 goto error_free_buffers; 383 if (fs_info->fat_type == FAT_TYPE_FAT32) { 384 if (!fat_info_sector_generate (&fs_info->info_sector, fs)) 385 goto error_free_buffers; 386 if (!fat_info_sector_write (&fs_info->info_sector, fs)) 387 goto error_free_buffers; 388 } 389 390 if (!fat_table_write_all (fs_info->fat, fs)) 391 goto error_free_buffers; 392 393 if (fs_info->fat_type == FAT_TYPE_FAT16) { 394 if (!fat_root_dir_clear (fs)) 395 goto error_free_buffers; 396 } 397 398 return fs; 399 400 error_free_buffers: 401 fat_free_buffers (fs); 402 error_free_fat_table: 403 fat_table_destroy (fs_info->fat); 404 error_free_fs: 405 fat_free (fs); 406 error: 407 return NULL; 408 } 409 410 PedFileSystem* 411 fat_create_fat16 (PedGeometry* geom, PedTimer* timer) 412 { 413 return fat_create (geom, FAT_TYPE_FAT16, timer); 414 } 415 416 PedFileSystem* 417 fat_create_fat32 (PedGeometry* geom, PedTimer* timer) 418 { 419 return fat_create (geom, FAT_TYPE_FAT32, timer); 420 } 421 422 int 423 fat_close (PedFileSystem* fs) 424 { 425 FatSpecific* fs_info = FAT_SPECIFIC (fs); 426 427 fat_free_buffers (fs); 428 fat_table_destroy (fs_info->fat); 429 fat_free (fs); 430 return 1; 431 } 432 433 /* Hack: just resize the file system outside of its boundaries! */ 434 PedFileSystem* 435 fat_copy (const PedFileSystem* fs, PedGeometry* geom, PedTimer* timer) 436 { 437 PedFileSystem* new_fs; 438 439 new_fs = ped_file_system_open (fs->geom); 440 if (!new_fs) 441 goto error; 442 if (!ped_file_system_resize (new_fs, geom, timer)) 443 goto error_close_new_fs; 444 return new_fs; 445 446 error_close_new_fs: 447 ped_file_system_close (new_fs); 448 error: 449 return 0; 450 } 451 452 static int 453 _compare_fats (PedFileSystem* fs) 454 { 455 FatSpecific* fs_info = FAT_SPECIFIC (fs); 456 FatTable* table_copy; 457 FatCluster table_size; 458 int i; 459 460 table_size = fs_info->fat_sectors * 512 461 / fat_table_entry_size (fs_info->fat_type); 462 463 table_copy = fat_table_new (fs_info->fat_type, table_size); 464 if (!table_copy) 465 goto error; 466 467 for (i = 1; i < fs_info->fat_table_count; i++) { 468 if (!fat_table_read (table_copy, fs, i)) 469 goto error_free_table_copy; 470 if (!fat_table_compare (fs_info->fat, table_copy)) { 471 if (ped_exception_throw (PED_EXCEPTION_ERROR, 472 PED_EXCEPTION_IGNORE_CANCEL, 473 _("The FATs don't match. If you don't know " 474 "what this means, then select cancel, run " 475 "scandisk on the file system, and then come " 476 "back.")) 477 != PED_EXCEPTION_IGNORE) 478 goto error_free_table_copy; 479 } 480 } 481 482 fat_table_destroy (table_copy); 483 return 1; 484 485 error_free_table_copy: 486 fat_table_destroy (table_copy); 487 error: 488 return 0; 489 } 490 491 int 492 fat_check (PedFileSystem* fs, PedTimer* timer) 493 { 494 FatSpecific* fs_info = FAT_SPECIFIC (fs); 495 PedSector cluster_sectors; 496 FatCluster cluster_count; 497 PedSector fat_sectors; 498 PedSector align_sectors; 499 FatCluster info_free_clusters; 500 501 align_sectors = fs_info->fat_offset 502 - fat_min_reserved_sector_count (fs_info->fat_type); 503 504 if (!fat_calc_sizes (fs->geom->length, 505 align_sectors, 506 fs_info->fat_type, 507 fs_info->root_dir_sector_count, 508 &cluster_sectors, 509 &cluster_count, 510 &fat_sectors)) { 511 if (ped_exception_throw (PED_EXCEPTION_BUG, 512 PED_EXCEPTION_IGNORE_CANCEL, 513 _("There are no possible configurations for this FAT " 514 "type.")) 515 != PED_EXCEPTION_IGNORE) 516 goto error; 517 } 518 519 if (fs_info->fat_type == FAT_TYPE_FAT16) { 520 if (cluster_sectors != fs_info->cluster_sectors 521 || cluster_count != fs_info->cluster_count 522 || fat_sectors != fs_info->fat_sectors) { 523 if (ped_exception_throw (PED_EXCEPTION_WARNING, 524 PED_EXCEPTION_IGNORE_CANCEL, 525 _("File system doesn't have expected sizes for " 526 "Windows to like it. " 527 "Cluster size is %dk (%dk expected); " 528 "number of clusters is %d (%d expected); " 529 "size of FATs is %d sectors (%d expected)."), 530 (int) fs_info->cluster_sectors / 2, 531 (int) cluster_sectors / 2, 532 (int) fs_info->cluster_count, 533 (int) cluster_count, 534 (int) fs_info->fat_sectors, 535 (int) fat_sectors) 536 != PED_EXCEPTION_IGNORE) 537 goto error; 538 } 539 } 540 541 if (fs_info->fat_type == FAT_TYPE_FAT32) { 542 info_free_clusters 543 = PED_LE32_TO_CPU (fs_info->info_sector.free_clusters); 544 if (info_free_clusters != (FatCluster) -1 545 && info_free_clusters != fs_info->fat->free_cluster_count) { 546 if (ped_exception_throw (PED_EXCEPTION_WARNING, 547 PED_EXCEPTION_IGNORE_CANCEL, 548 _("File system is reporting the free space as " 549 "%d clusters, not %d clusters."), 550 info_free_clusters, 551 fs_info->fat->free_cluster_count) 552 != PED_EXCEPTION_IGNORE) 553 goto error; 554 } 555 } 556 557 if (!_compare_fats (fs)) 558 goto error; 559 560 fs->checked = 1; 561 return 1; /* existence of fs implies consistency ;-) */ 562 563 error: 564 return 0; 565 } 566 567 /* Calculates how much space there will be in clusters in: 568 * old_fs intersect the-new-fs 569 */ 570 static PedSector 571 _calc_resize_data_size ( 572 const PedFileSystem* old_fs, 573 PedSector new_cluster_sectors, 574 FatCluster new_cluster_count, 575 PedSector new_fat_size) 576 { 577 FatSpecific* old_fs_info = FAT_SPECIFIC (old_fs); 578 PedSector fat_size_delta; 579 580 fat_size_delta = old_fs_info->fat_sectors - new_fat_size; 581 return new_cluster_sectors * new_cluster_count - fat_size_delta * 2; 582 } 583 584 static int 585 _test_resize_size (const PedFileSystem* fs, 586 PedSector length, PedSector min_data_size) 587 { 588 FatSpecific* fs_info = FAT_SPECIFIC (fs); 589 PedGeometry geom; 590 PedSector _cluster_sectors; 591 FatCluster _cluster_count; 592 PedSector _fat_size; 593 594 ped_geometry_init (&geom, fs->geom->dev, fs->geom->start, length); 595 596 if (fat_calc_resize_sizes ( 597 &geom, 598 fs_info->cluster_sectors, 599 FAT_TYPE_FAT16, 600 fs_info->root_dir_sector_count, 601 fs_info->cluster_sectors, 602 &_cluster_sectors, 603 &_cluster_count, 604 &_fat_size) 605 && _calc_resize_data_size (fs, _cluster_sectors, _cluster_count, 606 _fat_size) 607 >= min_data_size) 608 return 1; 609 610 if (fat_calc_resize_sizes ( 611 &geom, 612 fs_info->cluster_sectors, 613 FAT_TYPE_FAT32, 614 0, 615 fs_info->cluster_sectors, 616 &_cluster_sectors, 617 &_cluster_count, 618 &_fat_size) 619 && _calc_resize_data_size (fs, _cluster_sectors, _cluster_count, 620 _fat_size) 621 >= min_data_size) 622 return 1; 623 624 return 0; 625 } 626 627 /* does a binary search (!) for the mininum size. Too hard to compute directly 628 * (see calc_sizes() for why!) 629 */ 630 static PedSector 631 _get_min_resize_size (const PedFileSystem* fs, PedSector min_data_size) 632 { 633 PedSector min_length = 0; 634 PedSector max_length = fs->geom->length; 635 PedSector length; 636 637 while (min_length < max_length - 1) { 638 length = (min_length + max_length) / 2; 639 if (_test_resize_size (fs, length, min_data_size)) 640 max_length = length; 641 else 642 min_length = length; 643 } 644 645 /* adds a bit of leeway (64 sectors), for resolving extra issues, like root 646 * directory allocation, that aren't covered here. 647 */ 648 return max_length + 64; 649 } 650 651 PedConstraint* 652 fat_get_copy_constraint (const PedFileSystem* fs, const PedDevice* dev) 653 { 654 FatSpecific* fs_info = FAT_SPECIFIC (fs); 655 PedGeometry full_dev; 656 PedSector min_cluster_count; 657 FatCluster used_clusters; 658 PedSector min_data_size; 659 660 if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1)) 661 return NULL; 662 663 used_clusters = fs_info->fat->cluster_count 664 - fs_info->fat->free_cluster_count; 665 min_cluster_count = used_clusters + fs_info->total_dir_clusters; 666 min_data_size = min_cluster_count * fs_info->cluster_sectors; 667 668 return ped_constraint_new (ped_alignment_any, ped_alignment_any, 669 &full_dev, &full_dev, 670 _get_min_resize_size (fs, min_data_size), 671 dev->length); 672 } 673 674 PedConstraint* 675 fat_get_resize_constraint (const PedFileSystem* fs) 676 { 677 return fat_get_copy_constraint (fs, fs->geom->dev); 678 } 679 680 /* FIXME: fat_calc_sizes() needs to say "too big" or "too small", or 681 * something. This is a really difficult (maths) problem to do 682 * nicely... 683 * So, this algorithm works if dev->length / 2 is a valid fat_type 684 * size. (Which is how I got the magic numbers below) 685 */ 686 #if 0 687 /* returns: -1 too small, 0 ok, 1 too big */ 688 static int 689 _test_create_size (PedSector length, FatType fat_type, 690 PedSector cluster_sectors, PedSector cluster_count) 691 { 692 PedSector rootdir_sectors; 693 PedSector _cluster_sectors; 694 FatCluster _cluster_count; 695 PedSector _fat_size; 696 697 rootdir_sectors = (fat_type == FAT_TYPE_FAT16) ? 16 : 0; 698 699 if (!fat_calc_sizes (length, 0, fat_type, rootdir_sectors, 700 &_cluster_sectors, &_cluster_count, &_fat_size)) 701 return -1; // XXX: doesn't work... can't see a better way! 702 703 if (_cluster_sectors < cluster_sectors) 704 return -1; 705 if (_cluster_sectors > cluster_sectors) 706 return 1; 707 708 if (_cluster_count < cluster_count) 709 return -1; 710 if (_cluster_count > cluster_count) 711 return 1; 712 713 return 0; 714 } 715 716 static PedSector 717 _get_create_size (PedSector upper_bound, FatType fat_type, 718 PedSector cluster_sectors, FatCluster cluster_count) 719 { 720 PedSector min_length = 0; 721 PedSector max_length = upper_bound; 722 PedSector length; 723 724 while (1) { 725 length = (min_length + max_length) / 2; 726 switch (_test_create_size (length, fat_type, cluster_sectors, 727 cluster_count)) { 728 case -1: min_length = length; break; 729 case 0: return length; 730 case 1: max_length = length; break; 731 } 732 /* hack... won't always be able to get max cluster count 733 * with max cluster size, etc. */ 734 if (max_length - min_length == 1) 735 return min_length; 736 } 737 738 return 0; /* shut gcc up */ 739 } 740 #endif 741 742 PedConstraint* 743 fat_get_create_constraint_fat16 (const PedDevice* dev) 744 { 745 PedGeometry full_dev; 746 PedSector min_size; 747 PedSector max_size; 748 749 if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1)) 750 return NULL; 751 752 #if 0 753 min_size = _get_create_size (dev->length, FAT_TYPE_FAT16, 754 fat_min_cluster_size (FAT_TYPE_FAT16), 755 fat_min_cluster_count (FAT_TYPE_FAT16)); 756 max_size = _get_create_size (dev->length, FAT_TYPE_FAT16, 757 fat_max_cluster_size (FAT_TYPE_FAT16), 758 fat_max_cluster_count (FAT_TYPE_FAT16)); 759 if (!min_size) 760 return NULL; 761 #else 762 min_size = 65794; 763 max_size = 2097153; 764 #endif 765 766 return ped_constraint_new ( 767 ped_alignment_any, ped_alignment_any, 768 &full_dev, &full_dev, 769 min_size, max_size); 770 } 771 772 PedConstraint* 773 fat_get_create_constraint_fat32 (const PedDevice* dev) 774 { 775 PedGeometry full_dev; 776 PedSector min_size; 777 778 if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1)) 779 return NULL; 780 781 #if 0 782 min_size = _get_create_size (dev->length, FAT_TYPE_FAT32, 783 fat_min_cluster_size (FAT_TYPE_FAT32), 784 fat_min_cluster_count (FAT_TYPE_FAT32)); 785 if (!min_size) 786 return NULL; 787 #else 788 min_size = 525224; 789 #endif 790 791 return ped_constraint_new ( 792 ped_alignment_any, ped_alignment_any, 793 &full_dev, &full_dev, 794 min_size, dev->length); 795 } 796 #endif /* !DISCOVER_ONLY */ 797 798 static PedFileSystemOps fat16_ops = { 799 .probe = fat_probe_fat16, 800 #ifndef DISCOVER_ONLY 801 .clobber = fat_clobber, 802 .open = fat_open, 803 .create = fat_create_fat16, 804 .close = fat_close, 805 .check = fat_check, 806 .resize = fat_resize, 807 .copy = fat_copy, 808 .get_create_constraint = fat_get_create_constraint_fat16, 809 .get_resize_constraint = fat_get_resize_constraint, 810 .get_copy_constraint = fat_get_copy_constraint, 811 #else /* !DISCOVER_ONLY */ 812 .clobber = NULL, 813 .open = NULL, 814 .create = NULL, 815 .close = NULL, 816 .check = NULL, 817 .resize = NULL, 818 .copy = NULL, 819 .get_create_constraint = NULL, 820 .get_resize_constraint = NULL, 821 .get_copy_constraint = NULL, 822 #endif /* !DISCOVER_ONLY */ 823 }; 824 825 static PedFileSystemOps fat32_ops = { 826 .probe = fat_probe_fat32, 827 #ifndef DISCOVER_ONLY 828 .clobber = fat_clobber, 829 .open = fat_open, 830 .create = fat_create_fat32, 831 .close = fat_close, 832 .check = fat_check, 833 .resize = fat_resize, 834 .copy = fat_copy, 835 .get_create_constraint = fat_get_create_constraint_fat32, 836 .get_resize_constraint = fat_get_resize_constraint, 837 .get_copy_constraint = fat_get_copy_constraint, 838 #else /* !DISCOVER_ONLY */ 839 .clobber = NULL, 840 .open = NULL, 841 .create = NULL, 842 .close = NULL, 843 .check = NULL, 844 .resize = NULL, 845 .copy = NULL, 846 .get_create_constraint = NULL, 847 .get_resize_constraint = NULL, 848 .get_copy_constraint = NULL, 849 #endif /* !DISCOVER_ONLY */ 850 }; 851 852 #define FAT_BLOCK_SIZES ((int[2]){512, 0}) 853 854 PedFileSystemType fat16_type = { 855 .next = NULL, 856 .ops = &fat16_ops, 857 .name = "fat16", 858 .block_sizes = FAT_BLOCK_SIZES 859 }; 860 861 PedFileSystemType fat32_type = { 862 .next = NULL, 863 .ops = &fat32_ops, 864 .name = "fat32", 865 .block_sizes = FAT_BLOCK_SIZES 866 }; 867 868 void 869 ped_file_system_fat_init () 870 { 871 if (sizeof (FatBootSector) != 512) { 872 ped_exception_throw (PED_EXCEPTION_BUG, PED_EXCEPTION_CANCEL, 873 _("GNU Parted was miscompiled: the FAT boot sector " 874 "should be 512 bytes. FAT support will be disabled.")); 875 } else { 876 ped_file_system_type_register (&fat16_type); 877 ped_file_system_type_register (&fat32_type); 878 } 879 } 880 881 void 882 ped_file_system_fat_done () 883 { 884 ped_file_system_type_unregister (&fat16_type); 885 ped_file_system_type_unregister (&fat32_type); 886 } 887