OSDN Git Service

remove all top-level FS-op code and the clearfat program
[android-x86/external-parted.git] / libparted / fs / ext2 / interface.c
1 /*
2     interface.c -- parted binding glue to libext2resize
3     Copyright (C) 1998-2000, 2007-2011 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 /* VERSION: libext2resize 1.1.6 (by Lennert)
20  * merged 1.1.11 changes (by Andrew)
21  */
22
23 #include <config.h>
24
25 #include <parted/parted.h>
26 #include "ext2.h"
27 #include "parted_io.h"
28
29 static PedFileSystemType _ext2_type;
30 static PedFileSystemType _ext3_type;
31
32 struct ext2_dev_handle* ext2_make_dev_handle_from_parted_geometry(PedGeometry* geom);
33
34 static PedGeometry*
35 _ext2_generic_probe (PedGeometry* geom, int expect_ext_ver)
36 {
37         void *sb_v;
38         if (!ped_geometry_read_alloc(geom, &sb_v, 2, 2))
39                 return NULL;
40         struct ext2_super_block *sb = sb_v;
41
42         if (EXT2_SUPER_MAGIC(*sb) == EXT2_SUPER_MAGIC_CONST) {
43                 PedSector block_size = 1 << (EXT2_SUPER_LOG_BLOCK_SIZE(*sb) + 1);
44                 PedSector block_count = EXT2_SUPER_BLOCKS_COUNT(*sb);
45                 PedSector group_blocks = EXT2_SUPER_BLOCKS_PER_GROUP(*sb);
46                 PedSector group_nr = EXT2_SUPER_BLOCK_GROUP_NR(*sb);
47                 PedSector first_data_block = EXT2_SUPER_FIRST_DATA_BLOCK(*sb);
48                 int version = EXT2_SUPER_REV_LEVEL(*sb);
49                 int is_ext3 = 0;
50                 int is_ext4 = 0;
51
52                 is_ext3 = (EXT2_SUPER_FEATURE_COMPAT (*sb)
53                            & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0;
54                 if (is_ext3) {
55                         is_ext4 = ((EXT2_SUPER_FEATURE_RO_COMPAT (*sb)
56                                     & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
57                                    || (EXT2_SUPER_FEATURE_RO_COMPAT (*sb)
58                                        & EXT4_FEATURE_RO_COMPAT_GDT_CSUM)
59                                    || (EXT2_SUPER_FEATURE_RO_COMPAT (*sb)
60                                        & EXT4_FEATURE_RO_COMPAT_DIR_NLINK)
61                                    || (EXT2_SUPER_FEATURE_INCOMPAT (*sb)
62                                        & EXT4_FEATURE_INCOMPAT_EXTENTS)
63                                    || (EXT2_SUPER_FEATURE_INCOMPAT (*sb)
64                                        & EXT4_FEATURE_INCOMPAT_64BIT)
65                                    || (EXT2_SUPER_FEATURE_INCOMPAT (*sb)
66                                        & EXT4_FEATURE_INCOMPAT_FLEX_BG));
67                         if (is_ext4)
68                                 is_ext3 = 0;
69                 }
70                 free (sb);
71
72                 if (expect_ext_ver == 2 && (is_ext3 || is_ext4))
73                         return NULL;
74                 if (expect_ext_ver == 3 && !is_ext3)
75                         return NULL;
76                 else if (expect_ext_ver == 4 && !is_ext4)
77                         return NULL;
78
79                 if (version > 0 && group_nr > 0) {
80                         PedSector start;
81                         PedGeometry probe_geom;
82
83                         start = geom->start
84                                         - group_blocks * group_nr
85                                         - first_data_block;
86
87                         if (start < 0)
88                                 return NULL;
89                         ped_geometry_init (&probe_geom, geom->dev,
90                                            start, block_count * block_size);
91                         return _ext2_generic_probe (&probe_geom,
92                                                     expect_ext_ver);
93                 } else {
94                         return ped_geometry_new (geom->dev, geom->start,
95                                                  block_count * block_size);
96                 }
97         }
98         else {
99                 free (sb);
100         }
101
102         return NULL;
103 }
104
105 static PedGeometry*
106 _ext2_probe (PedGeometry* geom)
107 {
108         return _ext2_generic_probe (geom, 2);
109 }
110
111 static PedGeometry*
112 _ext3_probe (PedGeometry* geom)
113 {
114         return _ext2_generic_probe (geom, 3);
115 }
116
117 static PedGeometry*
118 _ext4_probe (PedGeometry* geom)
119 {
120         return _ext2_generic_probe (geom, 4);
121 }
122
123 #ifndef DISCOVER_ONLY
124 static int
125 _ext2_clobber (PedGeometry* geom)
126 {
127         void *sb_v;
128         int ok = 0;
129
130         if (ped_geometry_read_alloc(geom, &sb_v, 2, 2)) {
131                 struct ext2_super_block *sb = sb_v;
132                 /* Clobber only if there's a matching magic number. */
133                 if (EXT2_SUPER_MAGIC(*sb) != EXT2_SUPER_MAGIC_CONST) {
134                         ok = 1;
135                 } else {
136                         sb->s_magic = 0;
137                         ok = ped_geometry_write(geom, sb, 2, 2);
138                 }
139                 free (sb);
140         }
141         return ok;
142 }
143
144 static PedFileSystem*
145 _ext2_open (PedGeometry* geom)
146 {
147         PedFileSystem*          fs;
148         struct ext2_fs*         fs_info;
149         struct ext2_dev_handle* handle;
150
151         fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem));
152         if (!fs) goto error;
153
154         fs->type = &_ext2_type;
155         fs->geom = ped_geometry_duplicate (geom);
156         fs->checked = 1;
157
158         handle = ext2_make_dev_handle_from_parted_geometry(fs->geom);
159         if (!handle) goto error_free_fs;
160
161         fs_info = (struct ext2_fs*) ext2_open(handle, 0);
162         if (!fs_info) goto error_free_handle;
163
164         fs->type_specific = (void*) fs_info;
165         fs_info->opt_verbose = 0;
166
167         return fs;
168
169 error_free_handle:
170         ext2_destroy_dev_handle(handle);
171 error_free_fs:
172         free(fs);
173 error:
174         return NULL;
175 }
176
177 static PedFileSystem*
178 _ext2_create (PedGeometry* geom, PedTimer* timer)
179 {
180         PedFileSystem*          fs;
181         struct ext2_fs*         fs_info;
182         struct ext2_dev_handle* handle;
183
184         fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem));
185         if (!fs) goto error;
186
187         fs->type = &_ext2_type;
188         fs->geom = ped_geometry_duplicate (geom);
189
190         handle = ext2_make_dev_handle_from_parted_geometry(fs->geom);
191         if (!handle) goto error_free_fs;
192
193         fs_info = ext2_mkfs (handle, 0, 0, 0, 0, -1, -1, timer);
194         if (!fs_info) goto error_free_handle;
195
196         fs->type_specific = (void*) fs_info;
197         fs_info->opt_verbose = 0;
198
199         return fs;
200
201 error_free_handle:
202         ext2_destroy_dev_handle(handle);
203 error_free_fs:
204         free(fs);
205 error:
206         return NULL;
207 }
208
209 static int
210 _ext2_close (PedFileSystem *fs)
211 {
212         struct ext2_dev_handle* handle;
213
214         handle = ((struct ext2_fs*)fs->type_specific)->devhandle;
215         ext2_close(fs->type_specific);
216         ext2_destroy_dev_handle(handle);
217
218         free(fs);
219         return 1;
220 }
221
222 static int
223 _ext2_check (PedFileSystem *fs, PedTimer* timer)
224 {
225         ped_exception_throw (PED_EXCEPTION_INFORMATION, PED_EXCEPTION_OK,
226                 _("The ext2 file system passed a basic check.  For a more "
227                   "comprehensive check, use the e2fsck program."));
228         return 1;
229 }
230
231 static int
232 _ext2_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer)
233 {
234         struct ext2_fs* f;
235         PedSector       old_length = fs->geom->length;
236
237         PED_ASSERT (fs->geom->dev == geom->dev);
238
239         if (fs->geom->start != geom->start)
240         {
241                 ped_exception_throw (PED_EXCEPTION_NO_FEATURE,
242                       PED_EXCEPTION_CANCEL,
243                       _("Sorry, can't move the start of ext2 partitions yet!"));
244                 return 0;
245         }
246
247         geom->dev->boot_dirty = 1;
248
249         f = (struct ext2_fs *) fs->type_specific;
250
251 /* ensure that the geometry contains the new and old geometry */
252         if (old_length > geom->length) {
253                 if (!ext2_resize_fs(f, geom->length >> (f->logsize - 9),
254                                     timer))
255                         goto error;
256
257                 fs->geom->length = geom->length;
258                 fs->geom->end = fs->geom->start + geom->length - 1;
259         } else {
260                 fs->geom->length = geom->length;
261                 fs->geom->end = fs->geom->start + geom->length - 1;
262
263                 if (!ext2_resize_fs(f, geom->length >> (f->logsize - 9),
264                                     timer))
265                         goto error;
266         }
267         return 1;
268
269 error:
270         return 0;
271 }
272
273 static PedConstraint*
274 _ext2_get_create_constraint (const PedDevice* dev)
275 {
276         PedGeometry     full_dev;
277
278         if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1))
279                 return NULL;
280
281         return ped_constraint_new (
282                         ped_alignment_any, ped_alignment_any,
283                         &full_dev, &full_dev,
284                         64, dev->length);
285 }
286
287 static PedConstraint*
288 _ext2_get_resize_constraint (const PedFileSystem* fs)
289 {
290         struct ext2_fs* f = (struct ext2_fs *) fs->type_specific;
291         PedDevice*      dev = fs->geom->dev;
292         PedAlignment    start_align;
293         PedGeometry     start_sector;
294         PedGeometry     full_dev;
295         PedSector       min_size;
296
297         if (!ped_alignment_init (&start_align, fs->geom->start, 0))
298                 return NULL;
299         if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1))
300                 return NULL;
301         if (!ped_geometry_init (&start_sector, dev, fs->geom->start, 1))
302                 return NULL;
303         min_size = (EXT2_SUPER_BLOCKS_COUNT(f->sb)
304                         - EXT2_SUPER_FREE_BLOCKS_COUNT(f->sb))
305                    * (f->blocksize / dev->sector_size);
306
307         return ped_constraint_new (&start_align, ped_alignment_any,
308                                    &start_sector, &full_dev, min_size,
309                                    dev->length);
310 }
311 #endif /* !DISCOVER_ONLY */
312
313 static PedFileSystemOps _ext2_ops = {
314         probe:          _ext2_probe,
315 };
316
317 static PedFileSystemOps _ext3_ops = {
318         probe:          _ext3_probe,
319 };
320
321 static PedFileSystemOps _ext4_ops = {
322         probe:          _ext4_probe,
323 };
324
325 #define EXT23_BLOCK_SIZES ((int[6]){512, 1024, 2048, 4096, 8192, 0})
326
327 static PedFileSystemType _ext2_type = {
328        next:             NULL,
329        ops:              &_ext2_ops,
330        name:             "ext2",
331        block_sizes:      EXT23_BLOCK_SIZES
332 };
333
334 static PedFileSystemType _ext3_type = {
335        next:             NULL,
336        ops:              &_ext3_ops,
337        name:             "ext3",
338        block_sizes:      EXT23_BLOCK_SIZES
339 };
340
341 static PedFileSystemType _ext4_type = {
342        next:             NULL,
343        ops:              &_ext4_ops,
344        name:             "ext4",
345        block_sizes:      EXT23_BLOCK_SIZES
346 };
347
348 void ped_file_system_ext2_init ()
349 {
350         ped_file_system_type_register (&_ext2_type);
351         ped_file_system_type_register (&_ext3_type);
352         ped_file_system_type_register (&_ext4_type);
353 }
354
355 void ped_file_system_ext2_done ()
356 {
357         ped_file_system_type_unregister (&_ext2_type);
358         ped_file_system_type_unregister (&_ext3_type);
359         ped_file_system_type_unregister (&_ext4_type);
360 }