3
Copyright (C) 1998-2000, 2007, 2009-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/>.
26
/* Note: this deals with file system start and end sectors, even if the physical
27
* devices are different (eg for fat_copy()) Perhaps this is a hack, but it
31
calc_deltas (FatOpContext* ctx)
33
PedFileSystem* old_fs = ctx->old_fs;
34
PedFileSystem* new_fs = ctx->new_fs;
35
FatSpecific* old_fs_info = FAT_SPECIFIC (old_fs);
36
FatSpecific* new_fs_info = FAT_SPECIFIC (new_fs);
37
PedSector old_cluster_ofs;
38
PedSector new_cluster_ofs;
39
PedSector sector_delta;
41
old_cluster_ofs = old_fs->geom->start + old_fs_info->cluster_offset;
42
new_cluster_ofs = new_fs->geom->start + new_fs_info->cluster_offset;
44
if (new_cluster_ofs > old_cluster_ofs) {
45
ctx->start_move_dir = FAT_DIR_FORWARD;
46
sector_delta = new_cluster_ofs - old_cluster_ofs;
48
ctx->start_move_dir = FAT_DIR_BACKWARD;
49
sector_delta = old_cluster_ofs - new_cluster_ofs;
52
if (sector_delta % new_fs_info->cluster_sectors) {
54
PED_EXCEPTION_BUG, PED_EXCEPTION_CANCEL,
55
_("Cluster start delta = %d, which is not a multiple "
56
"of the cluster size %d."),
58
(int) new_fs_info->cluster_sectors);
62
ctx->start_move_delta = sector_delta / ctx->frag_sectors;
65
printf ("Start move delta is: %d %s.\n",
66
(int) ctx->start_move_delta,
67
(ctx->start_move_dir == FAT_DIR_FORWARD)?
68
"forwards" : "backwards");
75
fat_op_context_new (PedFileSystem* new_fs, PedFileSystem* old_fs)
77
FatSpecific* old_fs_info = FAT_SPECIFIC (old_fs);
78
FatSpecific* new_fs_info = FAT_SPECIFIC (new_fs);
81
ctx = (FatOpContext*) ped_malloc (sizeof (FatOpContext));
85
ctx->frag_sectors = PED_MIN (old_fs_info->cluster_sectors,
86
new_fs_info->cluster_sectors);
87
if (!fat_set_frag_sectors (new_fs, ctx->frag_sectors))
89
if (!fat_set_frag_sectors (old_fs, ctx->frag_sectors))
92
ctx->buffer_frags = old_fs_info->buffer_sectors / ctx->frag_sectors;
93
ctx->buffer_map = (FatFragment*) ped_malloc (sizeof (FatFragment)
98
ctx->remap = (FatFragment*) ped_malloc (sizeof (FatFragment)
99
* old_fs_info->frag_count);
101
goto error_free_buffer_map;
103
ctx->new_fs = new_fs;
104
ctx->old_fs = old_fs;
105
if (!calc_deltas (ctx))
106
goto error_free_buffer_map;
110
error_free_buffer_map:
111
free (ctx->buffer_map);
119
fat_op_context_destroy (FatOpContext* ctx)
121
free (ctx->buffer_map);
127
fat_op_context_map_static_fragment (const FatOpContext* ctx, FatFragment frag)
129
FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs);
132
if (ctx->new_fs->geom->dev != ctx->old_fs->geom->dev)
135
if (ctx->start_move_dir == FAT_DIR_FORWARD) {
136
if (frag < ctx->start_move_delta)
138
result = frag - ctx->start_move_delta;
140
result = frag + ctx->start_move_delta;
143
if (result >= new_fs_info->frag_count)
150
fat_op_context_map_static_cluster (const FatOpContext* ctx, FatCluster clst)
152
FatFragment mapped_frag;
154
mapped_frag = fat_op_context_map_static_fragment (ctx,
155
fat_cluster_to_frag (ctx->old_fs, clst));
156
if (mapped_frag != -1)
157
return fat_frag_to_cluster (ctx->new_fs, mapped_frag);
163
fat_op_context_map_fragment (const FatOpContext* ctx, FatFragment frag)
165
return ctx->remap [frag];
169
fat_op_context_map_cluster (const FatOpContext* ctx, FatCluster clst)
171
FatFragment mapped_frag;
173
mapped_frag = fat_op_context_map_fragment (ctx,
174
fat_cluster_to_frag (ctx->old_fs, clst));
175
if (mapped_frag != -1)
176
return fat_frag_to_cluster (ctx->new_fs, mapped_frag);
181
/* This function sets the initial fat for the new resized file system.
182
This is in *NO WAY* a proper FAT table - all it does is:
183
a) mark bad clusters as bad.
184
b) mark used clusters (that is, clusters from the original FS that are
185
reachable from the resized one). Marks as EOF (i.e. used, end of
187
c) mark original file system metadata as EOF (i.e. used), to prevent
188
it from being clobbered. This will leave the original file system
189
intact, until the partition table is modified, if the start of
190
the partition is moved.
192
The FATs are rebuilt *properly* after cluster relocation. This here is
193
only to mark clusters as used, so when cluster relocation occurs, clusters
194
aren't relocated on top of ones marked in a, b or c.
197
fat_op_context_create_initial_fat (FatOpContext* ctx)
199
FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs);
200
FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs);
206
FatFragment new_frag;
207
FatClusterFlag frag_flag;
209
new_fs_info->fat = fat_table_new (
210
new_fs_info->fat_type,
211
new_fs_info->fat_sectors * 512
212
/ fat_table_entry_size (new_fs_info->fat_type));
213
if (!new_fs_info->fat)
216
if (!fat_table_set_cluster_count (new_fs_info->fat,
217
new_fs_info->cluster_count))
220
/* mark bad and used clusters */
221
for (frag = 0; frag < old_fs_info->frag_count; frag++) {
222
frag_flag = fat_get_fragment_flag (ctx->old_fs, frag);
223
if (frag_flag == FAT_FLAG_FREE)
226
new_frag = fat_op_context_map_static_fragment (ctx, frag);
230
new_clst = fat_frag_to_cluster (ctx->new_fs, new_frag);
231
PED_ASSERT (new_clst != 0);
233
if (frag_flag == FAT_FLAG_BAD) {
234
if (!fat_table_set_bad (new_fs_info->fat, new_clst))
237
if (!fat_table_set_eof (new_fs_info->fat, new_clst))
242
/* mark metadata regions that map to clusters on the new FS */
243
for (sect = 0; sect < old_fs_info->cluster_offset; sect++) {
244
new_sect = ped_geometry_map (ctx->new_fs->geom,
245
ctx->old_fs->geom, sect);
247
|| !fat_is_sector_in_clusters (ctx->new_fs, new_sect))
250
clst = fat_sector_to_cluster (ctx->new_fs, new_sect);
251
PED_ASSERT (clst != 0);
253
if (!fat_table_set_eof (new_fs_info->fat, clst))
260
#endif /* !DISCOVER_ONLY */