3 Copyright (C) 1998-2000, 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/>.
28 #include <sys/types.h>
38 /* Recursively builds (i.e. makes consistent) the duplicated directory tree
39 * (leaving the original directory tree in tact)
42 fat_construct_directory (FatOpContext* ctx, FatTraverseInfo* trav_info)
44 FatTraverseInfo* sub_dir_info;
45 FatDirEntry* dir_entry;
46 FatCluster old_first_cluster;
48 while ( (dir_entry = fat_traverse_next_dir_entry (trav_info)) ) {
49 if (fat_dir_entry_is_null_term (dir_entry))
51 if (!fat_dir_entry_has_first_cluster (dir_entry, ctx->old_fs))
54 fat_traverse_mark_dirty (trav_info);
56 old_first_cluster = fat_dir_entry_get_first_cluster (dir_entry,
58 fat_dir_entry_set_first_cluster (dir_entry, ctx->new_fs,
59 fat_op_context_map_cluster (ctx, old_first_cluster));
61 if (fat_dir_entry_is_directory (dir_entry)
62 && dir_entry->name [0] != '.') {
64 = fat_traverse_directory (trav_info, dir_entry);
67 if (!fat_construct_directory (ctx, sub_dir_info))
71 /* remove "stale" entries at the end */
72 while ((dir_entry = fat_traverse_next_dir_entry (trav_info))) {
73 memset (dir_entry, 0, sizeof (FatDirEntry));
74 fat_traverse_mark_dirty (trav_info);
76 fat_traverse_complete (trav_info);
81 duplicate_legacy_root_dir (FatOpContext* ctx)
83 FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs);
84 FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs);
86 PED_ASSERT (old_fs_info->root_dir_sector_count
87 == new_fs_info->root_dir_sector_count);
89 if (!ped_geometry_read (ctx->old_fs->geom, old_fs_info->buffer,
90 old_fs_info->root_dir_offset,
91 old_fs_info->root_dir_sector_count))
94 if (!ped_geometry_write (ctx->new_fs->geom, old_fs_info->buffer,
95 new_fs_info->root_dir_offset,
96 new_fs_info->root_dir_sector_count))
103 Constructs the new directory tree for legacy (FAT16) file systems.
106 fat_construct_legacy_root (FatOpContext* ctx)
108 FatTraverseInfo* trav_info;
110 if (!duplicate_legacy_root_dir (ctx))
112 trav_info = fat_traverse_begin (ctx->new_fs, FAT_ROOT, "\\");
113 return fat_construct_directory (ctx, trav_info);
117 Constructs the new directory tree for new (FAT32) file systems.
120 fat_construct_root (FatOpContext* ctx)
122 FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs);
123 FatTraverseInfo* trav_info;
125 trav_info = fat_traverse_begin (ctx->new_fs, new_fs_info->root_cluster,
127 fat_construct_directory (ctx, trav_info);
131 /* Converts the root directory between FAT16 and FAT32. NOTE: this code
132 * can also do no conversion. I'm leaving fat_construct_directory(), because
133 * it's really pretty :-) It also leaves a higher chance of deleted file
134 * recovery, because it doesn't remove redundant entries. (We do this here,
135 * because brain-damaged FAT16 has an arbitary limit on root directory entries,
139 fat_convert_directory (FatOpContext* ctx, FatTraverseInfo* old_trav,
140 FatTraverseInfo* new_trav)
142 FatTraverseInfo* sub_old_dir_trav;
143 FatTraverseInfo* sub_new_dir_trav;
144 FatDirEntry* new_dir_entry;
145 FatDirEntry* old_dir_entry;
146 FatCluster old_first_cluster;
148 while ( (old_dir_entry = fat_traverse_next_dir_entry (old_trav)) ) {
149 if (fat_dir_entry_is_null_term (old_dir_entry))
151 if (!fat_dir_entry_is_active (old_dir_entry))
154 new_dir_entry = fat_traverse_next_dir_entry (new_trav);
155 if (!new_dir_entry) {
156 return ped_exception_throw (PED_EXCEPTION_ERROR,
157 PED_EXCEPTION_IGNORE_CANCEL,
158 _("There's not enough room in the root "
159 "directory for all of the files. Either "
160 "cancel, or ignore to lose the files."))
161 == PED_EXCEPTION_IGNORE;
164 *new_dir_entry = *old_dir_entry;
165 fat_traverse_mark_dirty (new_trav);
167 if (!fat_dir_entry_has_first_cluster (old_dir_entry,
171 old_first_cluster = fat_dir_entry_get_first_cluster (
172 old_dir_entry, ctx->old_fs);
173 fat_dir_entry_set_first_cluster (new_dir_entry, ctx->new_fs,
174 fat_op_context_map_cluster (ctx, old_first_cluster));
176 if (fat_dir_entry_is_directory (old_dir_entry)
177 && old_dir_entry->name [0] != '.') {
179 = fat_traverse_directory (old_trav, old_dir_entry);
181 = fat_traverse_directory (new_trav, new_dir_entry);
182 if (!sub_old_dir_trav || !sub_new_dir_trav)
185 if (!fat_convert_directory (ctx, sub_old_dir_trav,
191 /* remove "stale" entries at the end, just in case there is some
194 while ((new_dir_entry = fat_traverse_next_dir_entry (new_trav))) {
195 memset (new_dir_entry, 0, sizeof (FatDirEntry));
196 fat_traverse_mark_dirty (new_trav);
199 fat_traverse_complete (old_trav);
200 fat_traverse_complete (new_trav);
205 clear_cluster (PedFileSystem* fs, FatCluster cluster)
207 FatSpecific* fs_info = FAT_SPECIFIC (fs);
209 memset (fs_info->buffer, 0, fs_info->cluster_size);
210 fat_write_cluster (fs, fs_info->buffer, cluster);
213 /* This MUST be called BEFORE the fat_construct_new_fat(), because cluster
214 * allocation depend on the old FAT. The reason is, old clusters may
215 * still be needed during the resize, (particularly clusters in the directory
216 * tree) even if they will be discarded later.
219 alloc_root_dir (FatOpContext* ctx)
221 FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs);
222 FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs);
225 FatCluster cluster_count;
227 PED_ASSERT (new_fs_info->fat_type == FAT_TYPE_FAT32);
229 cluster_count = ped_div_round_up (
230 PED_MAX (16, old_fs_info->root_dir_sector_count),
231 new_fs_info->cluster_sectors);
233 for (i = 0; i < cluster_count; i++) {
234 cluster = fat_table_alloc_check_cluster (new_fs_info->fat,
238 ctx->new_root_dir [i] = cluster;
239 clear_cluster (ctx->new_fs, cluster);
241 ctx->new_root_dir [i] = 0;
242 new_fs_info->root_cluster = ctx->new_root_dir [0];
246 /* when converting FAT32 -> FAT16
247 * fat_duplicate clusters() duplicated the root directory unnecessarily.
250 * This must be called AFTER fat_construct_new_fat(). (otherwise, our
251 * changes just get overwritten)
254 free_root_dir (FatOpContext* ctx)
256 FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs);
257 FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs);
258 FatCluster old_cluster;
261 PED_ASSERT (old_fs_info->fat_type == FAT_TYPE_FAT32);
262 PED_ASSERT (new_fs_info->fat_type == FAT_TYPE_FAT16);
264 for (old_cluster = old_fs_info->root_cluster;
265 !fat_table_is_eof (old_fs_info->fat, old_cluster);
266 old_cluster = fat_table_get (old_fs_info->fat, old_cluster)) {
267 FatFragment old_frag;
268 old_frag = fat_cluster_to_frag (ctx->old_fs, old_cluster);
269 for (i = 0; i < new_fs_info->cluster_frags; i++) {
270 FatFragment new_frag;
272 new_frag = fat_op_context_map_fragment (ctx,
274 new_clst = fat_frag_to_cluster (ctx->old_fs, new_frag);
275 if (!fat_table_set_avail (new_fs_info->fat, new_clst))
284 fat_clear_root_dir (PedFileSystem* fs)
286 FatSpecific* fs_info = FAT_SPECIFIC (fs);
289 PED_ASSERT (fs_info->fat_type == FAT_TYPE_FAT16);
290 PED_ASSERT (fs_info->root_dir_sector_count);
292 memset (fs_info->buffer, 0, 512);
294 for (i = 0; i < fs_info->root_dir_sector_count; i++) {
295 if (!ped_geometry_write (fs->geom, fs_info->buffer,
296 fs_info->root_dir_offset + i, 1)) {
297 if (ped_exception_throw (PED_EXCEPTION_ERROR,
298 PED_EXCEPTION_IGNORE_CANCEL,
299 _("Error writing to the root directory."))
300 == PED_EXCEPTION_CANCEL)
308 fat_construct_converted_tree (FatOpContext* ctx)
310 FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs);
311 FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs);
312 FatTraverseInfo* old_trav_info;
313 FatTraverseInfo* new_trav_info;
315 if (new_fs_info->fat_type == FAT_TYPE_FAT32) {
316 new_trav_info = fat_traverse_begin (ctx->new_fs,
317 new_fs_info->root_cluster, "\\");
318 old_trav_info = fat_traverse_begin (ctx->old_fs, FAT_ROOT,
321 fat_clear_root_dir (ctx->new_fs);
322 new_trav_info = fat_traverse_begin (ctx->new_fs, FAT_ROOT,
324 old_trav_info = fat_traverse_begin (ctx->old_fs,
325 old_fs_info->root_cluster, "\\");
327 if (!new_trav_info || !old_trav_info)
329 if (!fat_convert_directory (ctx, old_trav_info, new_trav_info))
335 Constructs the new directory tree to match the new file locations.
338 fat_construct_dir_tree (FatOpContext* ctx)
340 FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs);
341 FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs);
343 if (new_fs_info->fat_type == old_fs_info->fat_type) {
344 switch (old_fs_info->fat_type) {
350 return fat_construct_legacy_root (ctx);
353 return fat_construct_root (ctx);
356 return fat_construct_converted_tree (ctx);
363 _get_next_old_frag (FatOpContext* ctx, FatFragment frag)
365 FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs);
367 FatCluster next_cluster;
369 if ((frag + 1) % old_fs_info->cluster_frags != 0) {
370 if (fat_is_fragment_active (ctx->old_fs, frag + 1))
375 cluster = fat_frag_to_cluster (ctx->old_fs, frag);
376 next_cluster = fat_table_get (old_fs_info->fat, cluster);
378 if (fat_table_is_eof (old_fs_info->fat, next_cluster))
381 return fat_cluster_to_frag (ctx->old_fs, next_cluster);
386 Constructs the new fat for the resized file system.
389 fat_construct_new_fat (FatOpContext* ctx)
391 FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs);
392 FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs);
393 FatFragment old_frag;
394 FatCluster new_cluster;
395 FatFragment new_frag;
396 FatFragment old_next_frag;
397 FatFragment new_next_frag;
398 FatCluster new_next_cluster;
402 fat_table_clear (new_fs_info->fat);
403 if (!fat_table_set_cluster_count (new_fs_info->fat,
404 new_fs_info->cluster_count))
407 for (old_frag = 0; old_frag < old_fs_info->frag_count; old_frag++) {
408 flag = fat_get_fragment_flag (ctx->old_fs, old_frag);
409 if (flag == FAT_FLAG_FREE)
411 if (flag == FAT_FLAG_BAD) {
412 new_frag = fat_op_context_map_static_fragment (
416 new_cluster = fat_frag_to_cluster (ctx->new_fs,
418 fat_table_set_bad (new_fs_info->fat, new_cluster);
422 new_frag = fat_op_context_map_fragment (ctx, old_frag);
423 new_cluster = fat_frag_to_cluster (ctx->new_fs, new_frag);
425 old_next_frag = _get_next_old_frag (ctx, old_frag);
426 if (old_next_frag == -1) {
427 fat_table_set_eof (new_fs_info->fat, new_cluster);
431 new_next_frag = fat_op_context_map_fragment (ctx,
433 PED_ASSERT (new_next_frag != -1);
435 new_next_cluster = fat_frag_to_cluster (ctx->new_fs,
437 PED_ASSERT (new_next_cluster != new_cluster);
439 fat_table_set (new_fs_info->fat, new_cluster, new_next_cluster);
444 for (old_cluster=2; old_cluster < old_fs_info->cluster_count+2;
446 if (fat_table_is_available (old_fs_info->fat, old_cluster))
449 printf ("%d->%d\t(next: %d->%d)\n",
451 ctx->remap [old_cluster],
452 fat_table_get (old_fs_info->fat, old_cluster),
453 fat_table_get (new_fs_info->fat,
454 ctx->remap [old_cluster]));
456 #endif /* PED_VERBOSE */
459 if (old_fs_info->fat_type == FAT_TYPE_FAT32
460 && new_fs_info->fat_type == FAT_TYPE_FAT32) {
461 new_fs_info->root_cluster
462 = fat_op_context_map_cluster (ctx,
463 old_fs_info->root_cluster);
466 if (old_fs_info->fat_type == FAT_TYPE_FAT16
467 && new_fs_info->fat_type == FAT_TYPE_FAT32) {
468 for (i=0; ctx->new_root_dir[i+1]; i++) {
469 fat_table_set (new_fs_info->fat,
470 ctx->new_root_dir[i],
471 ctx->new_root_dir[i+1]);
473 fat_table_set_eof (new_fs_info->fat, ctx->new_root_dir[i]);
480 ask_type (PedFileSystem* fs, int fat16_ok, int fat32_ok, FatType* out_fat_type)
482 FatSpecific* fs_info = FAT_SPECIFIC (fs);
483 PedExceptionOption status;
484 const char* fat16_msg;
485 const char* fat32_msg;
487 if (fs_info->fat_type == FAT_TYPE_FAT16)
488 fat16_msg = _("If you leave your file system as FAT16, "
489 "then you will have no problems.");
491 fat16_msg = _("If you convert to FAT16, and MS Windows "
492 "is installed on this partition, then "
493 "you must re-install the MS Windows boot "
494 "loader. If you want to do this, you "
495 "should consult the Parted manual (or "
496 "your distribution's manual).");
498 if (fs_info->fat_type == FAT_TYPE_FAT32)
499 fat32_msg = _("If you leave your file system as FAT32, "
500 "then you will not introduce any new "
503 fat32_msg = _("If you convert to FAT32, and MS Windows "
504 "is installed on this partition, then "
505 "you must re-install the MS Windows boot "
506 "loader. If you want to do this, you "
507 "should consult the Parted manual (or "
508 "your distribution's manual). Also, "
509 "converting to FAT32 will make the file "
510 "system unreadable by MS DOS, MS Windows "
511 "95a, and MS Windows NT.");
513 if (fat16_ok && fat32_ok) {
514 status = ped_exception_throw (
515 PED_EXCEPTION_INFORMATION,
516 PED_EXCEPTION_YES_NO_CANCEL,
518 _("Would you like to use FAT32?"),
523 case PED_EXCEPTION_YES:
524 *out_fat_type = FAT_TYPE_FAT32;
527 case PED_EXCEPTION_NO:
528 *out_fat_type = FAT_TYPE_FAT16;
531 case PED_EXCEPTION_UNHANDLED:
532 *out_fat_type = fs_info->fat_type;
535 case PED_EXCEPTION_CANCEL:
545 if (fs_info->fat_type != FAT_TYPE_FAT16) {
546 status = ped_exception_throw (
547 PED_EXCEPTION_WARNING,
548 PED_EXCEPTION_OK_CANCEL,
550 _("The file system can only be resized to this "
551 "size by converting to FAT16."),
553 if (status == PED_EXCEPTION_CANCEL)
556 *out_fat_type = FAT_TYPE_FAT16;
561 if (fs_info->fat_type != FAT_TYPE_FAT32) {
562 status = ped_exception_throw (
563 PED_EXCEPTION_WARNING,
564 PED_EXCEPTION_OK_CANCEL,
566 _("The file system can only be resized to this "
567 "size by converting to FAT32."),
569 if (status == PED_EXCEPTION_CANCEL)
572 *out_fat_type = FAT_TYPE_FAT32;
576 ped_exception_throw (
577 PED_EXCEPTION_NO_FEATURE,
578 PED_EXCEPTION_CANCEL,
579 _("GNU Parted cannot resize this partition to this size. "
580 "We're working on it!"));
585 /* For resize operations: determine if the file system must be FAT16 or FAT32,
586 * or either. If the new file system must be FAT32, then query for
587 * confirmation. If either file system can be used, query for which one.
590 get_fat_type (PedFileSystem* fs, const PedGeometry* new_geom,
591 FatType* out_fat_type)
593 FatSpecific* fs_info = FAT_SPECIFIC (fs);
594 PedSector fat16_cluster_sectors;
595 PedSector fat32_cluster_sectors;
596 FatCluster dummy_cluster_count;
597 PedSector dummy_fat_sectors;
601 fat16_ok = fat_calc_resize_sizes (
603 fs_info->cluster_sectors,
605 fs_info->root_dir_sector_count,
606 fs_info->cluster_sectors,
607 &fat16_cluster_sectors,
608 &dummy_cluster_count,
611 fat32_ok = fat_calc_resize_sizes (
613 fs_info->cluster_sectors,
615 fs_info->root_dir_sector_count,
616 fs_info->cluster_sectors,
617 &fat32_cluster_sectors,
618 &dummy_cluster_count,
621 return ask_type (fs, fat16_ok, fat32_ok, out_fat_type);
624 /* Creates the PedFileSystem struct for the new resized file system, and
625 sticks it in a FatOpContext. At the end of the process, the original
626 (ctx->old_fs) is destroyed, and replaced with the new one (ctx->new_fs).
629 create_resize_context (PedFileSystem* fs, const PedGeometry* new_geom)
631 FatSpecific* fs_info = FAT_SPECIFIC (fs);
632 FatSpecific* new_fs_info;
633 PedFileSystem* new_fs;
634 PedSector new_cluster_sectors;
635 FatCluster new_cluster_count;
636 PedSector new_fat_sectors;
637 FatType new_fat_type;
638 PedSector root_dir_sector_count;
639 FatOpContext* context;
641 /* hypothetical number of root dir sectors, if we end up using
644 if (fs_info->root_dir_sector_count)
645 root_dir_sector_count = fs_info->root_dir_sector_count;
647 root_dir_sector_count = FAT_ROOT_DIR_ENTRY_COUNT
648 * sizeof (FatDirEntry) / 512;
650 if (!get_fat_type (fs, new_geom, &new_fat_type))
653 fat_calc_resize_sizes (new_geom, fs_info->cluster_sectors, new_fat_type,
654 root_dir_sector_count, fs_info->cluster_sectors,
655 &new_cluster_sectors, &new_cluster_count, &new_fat_sectors);
657 if (!fat_check_resize_geometry (fs, new_geom, new_cluster_sectors,
661 new_fs = fat_alloc (new_geom);
665 new_fs_info = FAT_SPECIFIC (new_fs);
667 goto error_free_new_fs;
669 /* preserve boot code, etc. */
670 memcpy (&new_fs_info->boot_sector, &fs_info->boot_sector,
671 sizeof (FatBootSector));
672 memcpy (&new_fs_info->info_sector, &fs_info->info_sector,
673 sizeof (FatInfoSector));
675 new_fs_info->logical_sector_size = fs_info->logical_sector_size;
676 new_fs_info->sector_count = new_geom->length;
678 new_fs_info->sectors_per_track = fs_info->sectors_per_track;
679 new_fs_info->heads = fs_info->heads;
681 new_fs_info->cluster_size = new_cluster_sectors * 512;
682 new_fs_info->cluster_sectors = new_cluster_sectors;
683 new_fs_info->cluster_count = new_cluster_count;
684 new_fs_info->dir_entries_per_cluster = fs_info->dir_entries_per_cluster;
686 new_fs_info->fat_type = new_fat_type;
687 new_fs_info->fat_table_count = 2;
688 new_fs_info->fat_sectors = new_fat_sectors;
690 /* what about copying? */
691 new_fs_info->serial_number = fs_info->serial_number;
693 if (new_fs_info->fat_type == FAT_TYPE_FAT32) {
694 new_fs_info->info_sector_offset = 1;
695 new_fs_info->boot_sector_backup_offset = 6;
697 new_fs_info->root_dir_offset = 0;
698 new_fs_info->root_dir_entry_count = 0;
699 new_fs_info->root_dir_sector_count = 0;
701 /* we add calc_align_sectors to push the cluster_offset
702 forward, to keep the clusters aligned between the new
705 new_fs_info->fat_offset
706 = fat_min_reserved_sector_count (FAT_TYPE_FAT32)
707 + fat_calc_align_sectors (new_fs, fs);
709 new_fs_info->cluster_offset
710 = new_fs_info->fat_offset
711 + 2 * new_fs_info->fat_sectors;
713 new_fs_info->root_dir_sector_count = root_dir_sector_count;
714 new_fs_info->root_dir_entry_count
715 = root_dir_sector_count * 512 / sizeof (FatDirEntry);
717 new_fs_info->fat_offset
718 = fat_min_reserved_sector_count (FAT_TYPE_FAT16)
719 + fat_calc_align_sectors (new_fs, fs);
721 new_fs_info->root_dir_offset = new_fs_info->fat_offset
722 + 2 * new_fs_info->fat_sectors;
724 new_fs_info->cluster_offset = new_fs_info->root_dir_offset
725 + new_fs_info->root_dir_sector_count;
728 new_fs_info->total_dir_clusters = fs_info->total_dir_clusters;
730 context = fat_op_context_new (new_fs, fs);
732 goto error_free_new_fs_info;
734 if (!fat_op_context_create_initial_fat (context))
735 goto error_free_context;
737 if (!fat_alloc_buffers (new_fs))
743 fat_table_destroy (new_fs_info->fat);
746 error_free_new_fs_info:
755 resize_context_assimilate (FatOpContext* ctx)
757 FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs);
758 FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs);
760 fat_free_buffers (ctx->old_fs);
761 fat_table_destroy (old_fs_info->fat);
763 ped_geometry_destroy (ctx->old_fs->geom);
765 ctx->old_fs->type_specific = ctx->new_fs->type_specific;
766 ctx->old_fs->geom = ctx->new_fs->geom;
767 ctx->old_fs->type = (new_fs_info->fat_type == FAT_TYPE_FAT16)
773 fat_op_context_destroy (ctx);
779 resize_context_abort (FatOpContext* ctx)
781 FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs);
783 fat_free_buffers (ctx->new_fs);
784 fat_table_destroy (new_fs_info->fat);
786 ped_geometry_destroy (ctx->new_fs->geom);
789 fat_op_context_destroy (ctx);
794 /* copies the "hidden" sectors, between the boot sector and the FAT. Required,
795 * for the Windows 98 FAT32 boot loader
798 _copy_hidden_sectors (FatOpContext* ctx)
800 FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs);
801 FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs);
806 /* nothing to copy for FAT16 */
807 if (old_fs_info->fat_type == FAT_TYPE_FAT16
808 || new_fs_info->fat_type == FAT_TYPE_FAT16)
811 last = PED_MIN (old_fs_info->fat_offset, new_fs_info->fat_offset) - 1;
812 count = last - first + 1;
814 PED_ASSERT (count < BUFFER_SIZE);
816 if (!ped_geometry_read (ctx->old_fs->geom, old_fs_info->buffer,
819 if (!ped_geometry_write (ctx->new_fs->geom, old_fs_info->buffer,
826 fat_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer)
828 FatSpecific* fs_info = FAT_SPECIFIC (fs);
829 FatSpecific* new_fs_info;
831 PedFileSystem* new_fs;
833 ctx = create_resize_context (fs, geom);
836 new_fs = ctx->new_fs;
837 new_fs_info = FAT_SPECIFIC (new_fs);
839 if (!fat_duplicate_clusters (ctx, timer))
840 goto error_abort_ctx;
841 if (fs_info->fat_type == FAT_TYPE_FAT16
842 && new_fs_info->fat_type == FAT_TYPE_FAT32) {
843 if (!alloc_root_dir (ctx))
844 goto error_abort_ctx;
846 if (!fat_construct_new_fat (ctx))
847 goto error_abort_ctx;
848 if (fs_info->fat_type == FAT_TYPE_FAT32
849 && new_fs_info->fat_type == FAT_TYPE_FAT16) {
850 if (!free_root_dir (ctx))
851 goto error_abort_ctx;
853 if (!fat_construct_dir_tree (ctx))
854 goto error_abort_ctx;
855 if (!fat_table_write_all (new_fs_info->fat, new_fs))
856 goto error_abort_ctx;
858 _copy_hidden_sectors (ctx);
859 fat_boot_sector_generate (&new_fs_info->boot_sector, new_fs);
860 fat_boot_sector_write (&new_fs_info->boot_sector, new_fs);
861 if (new_fs_info->fat_type == FAT_TYPE_FAT32) {
862 fat_info_sector_generate (&new_fs_info->info_sector, new_fs);
863 fat_info_sector_write (&new_fs_info->info_sector, new_fs);
866 if (!resize_context_assimilate (ctx))
872 resize_context_abort (ctx);
877 #endif /* !DISCOVER_ONLY */