~ubuntu-branches/ubuntu/utopic/parted/utopic-proposed

« back to all changes in this revision

Viewing changes to libparted/fs/r/fat/context.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2014-07-21 10:23:16 UTC
  • mfrom: (7.2.32 sid)
  • Revision ID: package-import@ubuntu.com-20140721102316-jsyv3yzmbo8vlde5
Tags: 3.1-3
Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    libparted
 
3
    Copyright (C) 1998-2000, 2007, 2009-2012 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
 
 
22
#include "fat.h"
 
23
 
 
24
#ifndef DISCOVER_ONLY
 
25
 
 
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
 
28
 * works ;-)
 
29
 */
 
30
static int
 
31
calc_deltas (FatOpContext* ctx)
 
32
{
 
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;
 
40
 
 
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;
 
43
 
 
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;
 
47
        } else {
 
48
                ctx->start_move_dir = FAT_DIR_BACKWARD;
 
49
                sector_delta = old_cluster_ofs - new_cluster_ofs;
 
50
        }
 
51
 
 
52
        if (sector_delta % new_fs_info->cluster_sectors) {
 
53
                ped_exception_throw (
 
54
                        PED_EXCEPTION_BUG, PED_EXCEPTION_CANCEL,
 
55
                        _("Cluster start delta = %d, which is not a multiple "
 
56
                          "of the cluster size %d."),
 
57
                        (int) sector_delta,
 
58
                        (int) new_fs_info->cluster_sectors);
 
59
                return 0;
 
60
        }
 
61
 
 
62
        ctx->start_move_delta = sector_delta / ctx->frag_sectors;
 
63
 
 
64
#ifdef PED_VERBOSE
 
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");
 
69
#endif
 
70
 
 
71
        return 1;
 
72
}
 
73
 
 
74
FatOpContext*
 
75
fat_op_context_new (PedFileSystem* new_fs, PedFileSystem* old_fs)
 
76
{
 
77
        FatSpecific*    old_fs_info = FAT_SPECIFIC (old_fs);
 
78
        FatSpecific*    new_fs_info = FAT_SPECIFIC (new_fs);
 
79
        FatOpContext*   ctx;
 
80
 
 
81
        ctx = (FatOpContext*) ped_malloc (sizeof (FatOpContext));
 
82
        if (!ctx)
 
83
                goto error;
 
84
 
 
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))
 
88
                goto error;
 
89
        if (!fat_set_frag_sectors (old_fs, ctx->frag_sectors))
 
90
                goto error;
 
91
 
 
92
        ctx->buffer_frags = old_fs_info->buffer_sectors / ctx->frag_sectors;
 
93
        ctx->buffer_map = (FatFragment*) ped_malloc (sizeof (FatFragment)
 
94
                                                     * ctx->buffer_frags);
 
95
        if (!ctx->buffer_map)
 
96
                goto error_free_ctx;
 
97
 
 
98
        ctx->remap = (FatFragment*) ped_malloc (sizeof (FatFragment)
 
99
                                                   * old_fs_info->frag_count);
 
100
        if (!ctx->remap)
 
101
                goto error_free_buffer_map;
 
102
 
 
103
        ctx->new_fs = new_fs;
 
104
        ctx->old_fs = old_fs;
 
105
        if (!calc_deltas (ctx))
 
106
                goto error_free_buffer_map;
 
107
 
 
108
        return ctx;
 
109
 
 
110
error_free_buffer_map:
 
111
        free (ctx->buffer_map);
 
112
error_free_ctx:
 
113
        free (ctx);
 
114
error:
 
115
        return NULL;
 
116
}
 
117
 
 
118
void
 
119
fat_op_context_destroy (FatOpContext* ctx)
 
120
{
 
121
        free (ctx->buffer_map);
 
122
        free (ctx->remap);
 
123
        free (ctx);
 
124
}
 
125
 
 
126
FatFragment
 
127
fat_op_context_map_static_fragment (const FatOpContext* ctx, FatFragment frag)
 
128
{
 
129
        FatSpecific*    new_fs_info = FAT_SPECIFIC (ctx->new_fs);
 
130
        FatFragment     result;
 
131
 
 
132
        if (ctx->new_fs->geom->dev != ctx->old_fs->geom->dev)
 
133
                return -1;
 
134
 
 
135
        if (ctx->start_move_dir == FAT_DIR_FORWARD) {
 
136
                if (frag < ctx->start_move_delta)
 
137
                        return -1;
 
138
                result = frag - ctx->start_move_delta;
 
139
        } else {
 
140
                result = frag + ctx->start_move_delta;
 
141
        }
 
142
 
 
143
        if (result >= new_fs_info->frag_count)
 
144
                return -1;
 
145
 
 
146
        return result;
 
147
}
 
148
 
 
149
FatCluster
 
150
fat_op_context_map_static_cluster (const FatOpContext* ctx, FatCluster clst)
 
151
{
 
152
        FatFragment     mapped_frag;
 
153
 
 
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);
 
158
        else
 
159
                return 0;
 
160
}
 
161
 
 
162
FatFragment
 
163
fat_op_context_map_fragment (const FatOpContext* ctx, FatFragment frag)
 
164
{
 
165
        return ctx->remap [frag];
 
166
}
 
167
 
 
168
FatCluster
 
169
fat_op_context_map_cluster (const FatOpContext* ctx, FatCluster clst)
 
170
{
 
171
        FatFragment     mapped_frag;
 
172
 
 
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);
 
177
        else
 
178
                return 0;
 
179
}
 
180
 
 
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
 
186
           file chain).
 
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.
 
191
 
 
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.
 
195
*/
 
196
int
 
197
fat_op_context_create_initial_fat (FatOpContext* ctx)
 
198
{
 
199
        FatSpecific*    old_fs_info = FAT_SPECIFIC (ctx->old_fs);
 
200
        FatSpecific*    new_fs_info = FAT_SPECIFIC (ctx->new_fs);
 
201
        FatCluster      clst;
 
202
        FatCluster      new_clst;
 
203
        PedSector       sect;
 
204
        PedSector       new_sect;
 
205
        FatFragment     frag;
 
206
        FatFragment     new_frag;
 
207
        FatClusterFlag  frag_flag;
 
208
 
 
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)
 
214
                return 0;
 
215
 
 
216
        if (!fat_table_set_cluster_count (new_fs_info->fat,
 
217
                                          new_fs_info->cluster_count))
 
218
                return 0;
 
219
 
 
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)
 
224
                        continue;
 
225
 
 
226
                new_frag = fat_op_context_map_static_fragment (ctx, frag);
 
227
                if (new_frag == -1)
 
228
                        continue;
 
229
 
 
230
                new_clst = fat_frag_to_cluster (ctx->new_fs, new_frag);
 
231
                PED_ASSERT (new_clst != 0);
 
232
 
 
233
                if (frag_flag == FAT_FLAG_BAD) {
 
234
                        if (!fat_table_set_bad (new_fs_info->fat, new_clst))
 
235
                                return 0;
 
236
                } else {
 
237
                        if (!fat_table_set_eof (new_fs_info->fat, new_clst))
 
238
                                return 0;
 
239
                }
 
240
        }
 
241
 
 
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);
 
246
                if (new_sect == -1
 
247
                    || !fat_is_sector_in_clusters (ctx->new_fs, new_sect))
 
248
                        continue;
 
249
 
 
250
                clst = fat_sector_to_cluster (ctx->new_fs, new_sect);
 
251
                PED_ASSERT (clst != 0);
 
252
 
 
253
                if (!fat_table_set_eof (new_fs_info->fat, clst))
 
254
                        return 0;
 
255
        }
 
256
 
 
257
        return 1;
 
258
}
 
259
 
 
260
#endif /* !DISCOVER_ONLY */