2 interface.c -- parted binding glue to libext2resize
3 Copyright (C) 1998-2000, 2007, 2009 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/>.
19 /* VERSION: libext2resize 1.1.6 (by Lennert)
20 * merged 1.1.11 changes (by Andrew)
25 #include <parted/parted.h>
27 #include "parted_io.h"
29 static PedFileSystemType _ext2_type;
30 static PedFileSystemType _ext3_type;
32 struct ext2_dev_handle* ext2_make_dev_handle_from_parted_geometry(PedGeometry* geom);
35 _ext2_generic_probe (PedGeometry* geom, int expect_ext_ver)
37 struct ext2_super_block sb;
39 if (!ped_geometry_read(geom, &sb, 2, 2))
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);
52 is_ext3 = (EXT2_SUPER_FEATURE_COMPAT (sb)
53 & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0;
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_DIR_NLINK)
59 || (EXT2_SUPER_FEATURE_INCOMPAT (sb)
60 & EXT4_FEATURE_INCOMPAT_EXTENTS)
61 || (EXT2_SUPER_FEATURE_INCOMPAT (sb)
62 & EXT4_FEATURE_INCOMPAT_64BIT));
67 if (expect_ext_ver == 2 && (is_ext3 || is_ext4))
69 if (expect_ext_ver == 3 && !is_ext3)
71 else if (expect_ext_ver == 4 && !is_ext4)
74 if (version > 0 && group_nr > 0) {
76 PedGeometry probe_geom;
79 - group_blocks * group_nr
84 ped_geometry_init (&probe_geom, geom->dev,
85 start, block_count * block_size);
86 return _ext2_generic_probe (&probe_geom,
89 return ped_geometry_new (geom->dev, geom->start,
90 block_count * block_size);
97 _ext2_probe (PedGeometry* geom)
99 return _ext2_generic_probe (geom, 2);
103 _ext3_probe (PedGeometry* geom)
105 return _ext2_generic_probe (geom, 3);
109 _ext4_probe (PedGeometry* geom)
111 return _ext2_generic_probe (geom, 4);
114 #ifndef DISCOVER_ONLY
116 _ext2_clobber (PedGeometry* geom)
118 struct ext2_super_block sb;
120 if (!ped_geometry_read(geom, &sb, 2, 2))
122 if (EXT2_SUPER_MAGIC(sb) != EXT2_SUPER_MAGIC_CONST)
126 return ped_geometry_write(geom, &sb, 2, 2);
129 static PedFileSystem*
130 _ext2_open (PedGeometry* geom)
133 struct ext2_fs* fs_info;
134 struct ext2_dev_handle* handle;
136 fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem));
139 fs->type = &_ext2_type;
140 fs->geom = ped_geometry_duplicate (geom);
143 handle = ext2_make_dev_handle_from_parted_geometry(fs->geom);
144 if (!handle) goto error_free_fs;
146 fs_info = (struct ext2_fs*) ext2_open(handle, 0);
147 if (!fs_info) goto error_free_handle;
149 fs->type_specific = (void*) fs_info;
150 fs_info->opt_verbose = 0;
155 ext2_destroy_dev_handle(handle);
162 static PedFileSystem*
163 _ext2_create (PedGeometry* geom, PedTimer* timer)
166 struct ext2_fs* fs_info;
167 struct ext2_dev_handle* handle;
169 fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem));
172 fs->type = &_ext2_type;
173 fs->geom = ped_geometry_duplicate (geom);
175 handle = ext2_make_dev_handle_from_parted_geometry(fs->geom);
176 if (!handle) goto error_free_fs;
178 fs_info = ext2_mkfs (handle, 0, 0, 0, 0, -1, -1, timer);
179 if (!fs_info) goto error_free_handle;
181 fs->type_specific = (void*) fs_info;
182 fs_info->opt_verbose = 0;
187 ext2_destroy_dev_handle(handle);
195 _ext2_close (PedFileSystem *fs)
197 struct ext2_dev_handle* handle;
199 handle = ((struct ext2_fs*)fs->type_specific)->devhandle;
200 ext2_close(fs->type_specific);
201 ext2_destroy_dev_handle(handle);
208 _ext2_check (PedFileSystem *fs, PedTimer* timer)
210 ped_exception_throw (PED_EXCEPTION_INFORMATION, PED_EXCEPTION_OK,
211 _("The ext2 file system passed a basic check. For a more "
212 "comprehensive check, use the e2fsck program."));
217 _ext2_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer)
220 PedSector old_length = fs->geom->length;
222 PED_ASSERT (fs->geom->dev == geom->dev, return 0);
224 if (fs->geom->start != geom->start)
226 ped_exception_throw (PED_EXCEPTION_NO_FEATURE,
227 PED_EXCEPTION_CANCEL,
228 _("Sorry, can't move the start of ext2 partitions yet!"));
232 geom->dev->boot_dirty = 1;
234 f = (struct ext2_fs *) fs->type_specific;
236 /* ensure that the geometry contains the new and old geometry */
237 if (old_length > geom->length) {
238 if (!ext2_resize_fs(f, geom->length >> (f->logsize - 9),
242 fs->geom->length = geom->length;
243 fs->geom->end = fs->geom->start + geom->length - 1;
245 fs->geom->length = geom->length;
246 fs->geom->end = fs->geom->start + geom->length - 1;
248 if (!ext2_resize_fs(f, geom->length >> (f->logsize - 9),
258 static PedConstraint*
259 _ext2_get_create_constraint (const PedDevice* dev)
261 PedGeometry full_dev;
263 if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1))
266 return ped_constraint_new (
267 ped_alignment_any, ped_alignment_any,
268 &full_dev, &full_dev,
272 static PedConstraint*
273 _ext2_get_resize_constraint (const PedFileSystem* fs)
275 struct ext2_fs* f = (struct ext2_fs *) fs->type_specific;
276 PedDevice* dev = fs->geom->dev;
277 PedAlignment start_align;
278 PedGeometry start_sector;
279 PedGeometry full_dev;
282 if (!ped_alignment_init (&start_align, fs->geom->start, 0))
284 if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1))
286 if (!ped_geometry_init (&start_sector, dev, fs->geom->start, 1))
288 min_size = (EXT2_SUPER_BLOCKS_COUNT(f->sb)
289 - EXT2_SUPER_FREE_BLOCKS_COUNT(f->sb))
290 * (f->blocksize / dev->sector_size);
292 return ped_constraint_new (&start_align, ped_alignment_any,
293 &start_sector, &full_dev, min_size,
296 #endif /* !DISCOVER_ONLY */
298 static PedFileSystemOps _ext2_ops = {
300 #ifndef DISCOVER_ONLY
301 clobber: _ext2_clobber,
303 create: _ext2_create,
306 resize: _ext2_resize,
308 get_create_constraint: _ext2_get_create_constraint,
309 get_copy_constraint: NULL,
310 get_resize_constraint: _ext2_get_resize_constraint
311 #else /* !DISCOVER_ONLY */
319 get_create_constraint: NULL,
320 get_copy_constraint: NULL,
321 get_resize_constraint: NULL
322 #endif /* !DISCOVER_ONLY */
325 static PedFileSystemOps _ext3_ops = {
327 #ifndef DISCOVER_ONLY
328 clobber: _ext2_clobber,
333 resize: _ext2_resize,
335 get_create_constraint: _ext2_get_create_constraint,
336 get_copy_constraint: NULL,
337 get_resize_constraint: _ext2_get_resize_constraint
338 #else /* !DISCOVER_ONLY */
346 get_create_constraint: NULL,
347 get_copy_constraint: NULL,
348 get_resize_constraint: NULL
349 #endif /* !DISCOVER_ONLY */
352 static PedFileSystemOps _ext4_ops = {
361 get_create_constraint: NULL,
362 get_copy_constraint: NULL,
363 get_resize_constraint: NULL
366 #define EXT23_BLOCK_SIZES ((int[6]){512, 1024, 2048, 4096, 8192, 0})
368 static PedFileSystemType _ext2_type = {
372 block_sizes: EXT23_BLOCK_SIZES
375 static PedFileSystemType _ext3_type = {
379 block_sizes: EXT23_BLOCK_SIZES
382 static PedFileSystemType _ext4_type = {
386 block_sizes: EXT23_BLOCK_SIZES
389 void ped_file_system_ext2_init ()
391 ped_file_system_type_register (&_ext2_type);
392 ped_file_system_type_register (&_ext3_type);
393 ped_file_system_type_register (&_ext4_type);
396 void ped_file_system_ext2_done ()
398 ped_file_system_type_unregister (&_ext2_type);
399 ped_file_system_type_unregister (&_ext3_type);
400 ped_file_system_type_unregister (&_ext4_type);