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