static int read_next_dir_buffer (FatTraverseInfo* trav_info) { FatSpecific* fs_info = FAT_SPECIFIC (trav_info->fs); PED_ASSERT (!trav_info->is_legacy_root_dir); trav_info->this_buffer = trav_info->next_buffer; if (trav_info->this_buffer < 2 || trav_info->this_buffer >= fs_info->cluster_count + 2) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, "Cluster %ld in directory %s is outside file system!", (long) trav_info->this_buffer, trav_info->dir_name); return 0; } trav_info->next_buffer = fat_table_get (fs_info->fat, trav_info->this_buffer); return fat_read_cluster (trav_info->fs, (void *) trav_info->dir_entries, trav_info->this_buffer); }
/* when converting FAT32 -> FAT16 * fat_duplicate clusters() duplicated the root directory unnecessarily. * Let's free it. * * This must be called AFTER fat_construct_new_fat(). (otherwise, our * changes just get overwritten) */ static int free_root_dir (FatOpContext* ctx) { FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs); FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs); FatCluster old_cluster; FatFragment i; PED_ASSERT (old_fs_info->fat_type == FAT_TYPE_FAT32); PED_ASSERT (new_fs_info->fat_type == FAT_TYPE_FAT16); for (old_cluster = old_fs_info->root_cluster; !fat_table_is_eof (old_fs_info->fat, old_cluster); old_cluster = fat_table_get (old_fs_info->fat, old_cluster)) { FatFragment old_frag; old_frag = fat_cluster_to_frag (ctx->old_fs, old_cluster); for (i = 0; i < new_fs_info->cluster_frags; i++) { FatFragment new_frag; FatCluster new_clst; new_frag = fat_op_context_map_fragment (ctx, old_frag + i); new_clst = fat_frag_to_cluster (ctx->old_fs, new_frag); if (!fat_table_set_avail (new_fs_info->fat, new_clst)) return 0; } } return 1; }
static FatFragment _get_next_old_frag (FatOpContext* ctx, FatFragment frag) { FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs); FatCluster cluster; FatCluster next_cluster; if ((frag + 1) % old_fs_info->cluster_frags != 0) { if (fat_is_fragment_active (ctx->old_fs, frag + 1)) return frag + 1; else return -1; } else { cluster = fat_frag_to_cluster (ctx->old_fs, frag); next_cluster = fat_table_get (old_fs_info->fat, cluster); if (fat_table_is_eof (old_fs_info->fat, next_cluster)) return -1; else return fat_cluster_to_frag (ctx->old_fs, next_cluster); } }
/* Constructs the new fat for the resized file system. */ static int fat_construct_new_fat (FatOpContext* ctx) { FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs); FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs); FatFragment old_frag; FatCluster new_cluster; FatFragment new_frag; FatFragment old_next_frag; FatFragment new_next_frag; FatCluster new_next_cluster; FatClusterFlag flag; int i; fat_table_clear (new_fs_info->fat); if (!fat_table_set_cluster_count (new_fs_info->fat, new_fs_info->cluster_count)) return 0; for (old_frag = 0; old_frag < old_fs_info->frag_count; old_frag++) { flag = fat_get_fragment_flag (ctx->old_fs, old_frag); if (flag == FAT_FLAG_FREE) continue; if (flag == FAT_FLAG_BAD) { new_frag = fat_op_context_map_static_fragment ( ctx, old_frag); if (new_frag == -1) continue; new_cluster = fat_frag_to_cluster (ctx->new_fs, new_frag); fat_table_set_bad (new_fs_info->fat, new_cluster); continue; } new_frag = fat_op_context_map_fragment (ctx, old_frag); new_cluster = fat_frag_to_cluster (ctx->new_fs, new_frag); old_next_frag = _get_next_old_frag (ctx, old_frag); if (old_next_frag == -1) { fat_table_set_eof (new_fs_info->fat, new_cluster); continue; } new_next_frag = fat_op_context_map_fragment (ctx, old_next_frag); PED_ASSERT (new_next_frag != -1); new_next_cluster = fat_frag_to_cluster (ctx->new_fs, new_next_frag); PED_ASSERT (new_next_cluster != new_cluster); fat_table_set (new_fs_info->fat, new_cluster, new_next_cluster); } #if 0 #ifdef PED_VERBOSE for (old_cluster=2; old_cluster < old_fs_info->cluster_count+2; old_cluster++) { if (fat_table_is_available (old_fs_info->fat, old_cluster)) continue; printf ("%d->%d\t(next: %d->%d)\n", old_cluster, ctx->remap [old_cluster], fat_table_get (old_fs_info->fat, old_cluster), fat_table_get (new_fs_info->fat, ctx->remap [old_cluster])); } #endif /* PED_VERBOSE */ #endif if (old_fs_info->fat_type == FAT_TYPE_FAT32 && new_fs_info->fat_type == FAT_TYPE_FAT32) { new_fs_info->root_cluster = fat_op_context_map_cluster (ctx, old_fs_info->root_cluster); } if (old_fs_info->fat_type == FAT_TYPE_FAT16 && new_fs_info->fat_type == FAT_TYPE_FAT32) { for (i=0; ctx->new_root_dir[i+1]; i++) { fat_table_set (new_fs_info->fat, ctx->new_root_dir[i], ctx->new_root_dir[i+1]); } fat_table_set_eof (new_fs_info->fat, ctx->new_root_dir[i]); } return 1; }