1 /* 2 reiserfs.c -- libparted / libreiserfs glue 3 Copyright (C) 2001, 2002, 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 This is all rather complicated. There are a few combinations: 19 * shared libraries full support 20 * dynamic libraries present full support (via dlopen) 21 * dynamic libraries absent (full support disabled) (via dlopen) 22 * discover only 23 24 We'd love to hear comments... 25 26 So far, we've opted for maximum flexibility for the user. Is it 27 all worth it? 28 */ 29 30 #include <config.h> 31 32 #if (HAVE_LIBREISERFS || DYNAMIC_LOADING) && !DISCOVER_ONLY 33 # define REISER_FULL_SUPPORT 34 #endif 35 36 #include <uuid/uuid.h> 37 #include <fcntl.h> 38 #include <errno.h> 39 40 #ifdef DYNAMIC_LOADING 41 # include <dlfcn.h> 42 #endif 43 44 #include <parted/parted.h> 45 #include <parted/debug.h> 46 #include <parted/endian.h> 47 48 #if ENABLE_NLS 49 # include <libintl.h> 50 # define _(String) dgettext (PACKAGE, String) 51 #else 52 # define _(String) (String) 53 #endif 54 55 #include "reiserfs.h" 56 #include "geom_dal.h" 57 58 #define REISERFS_BLOCK_SIZES ((int[2]){512, 0}) 59 60 static PedSector reiserfs_super_offset[] = { 128, 16, -1 }; 61 static PedFileSystemType* reiserfs_type; 62 63 #ifdef DYNAMIC_LOADING 64 # define FPTR * 65 # define FCLASS static 66 #else 67 # define FPTR 68 # define FCLASS extern 69 #endif 70 71 #ifdef DYNAMIC_LOADING 72 73 static int libreiserfs_present; 74 75 static void *libdal_handle; 76 static void *libreiserfs_handle; 77 78 #endif /* DYNAMIC_LOADING */ 79 80 #ifdef REISER_FULL_SUPPORT 81 82 FCLASS blk_t (FPTR reiserfs_fs_probe) (dal_t *); 83 84 FCLASS int (FPTR libreiserfs_exception_type) (reiserfs_exception_t *); 85 FCLASS int (FPTR libreiserfs_exception_option) (reiserfs_exception_t *); 86 FCLASS char *(FPTR libreiserfs_exception_message) (reiserfs_exception_t *); 87 FCLASS void (FPTR libreiserfs_exception_set_handler) 88 (int(FPTR)(reiserfs_exception_t *)); 89 90 FCLASS void (FPTR dal_realize) (dal_t *); 91 FCLASS size_t (FPTR dal_block_size) (dal_t *); 92 FCLASS blk_t (FPTR dal_len) (dal_t *); 93 FCLASS int (FPTR dal_flags) (dal_t *); 94 95 FCLASS reiserfs_fs_t* (FPTR reiserfs_fs_open) (dal_t *, dal_t *); 96 FCLASS reiserfs_fs_t* (FPTR reiserfs_fs_create) (dal_t *, dal_t *, 97 blk_t, blk_t, blk_t, size_t, 98 int, int, const char *, 99 const char *, blk_t, 100 reiserfs_gauge_t *); 101 102 FCLASS int (FPTR reiserfs_fs_resize) (reiserfs_fs_t *, blk_t, reiserfs_gauge_t *); 103 #ifdef HAVE_REISERFS_FS_CHECK 104 FCLASS int (FPTR reiserfs_fs_check) (reiserfs_fs_t *, reiserfs_gauge_t *); 105 #endif 106 107 FCLASS reiserfs_fs_t *(FPTR reiserfs_fs_copy) (reiserfs_fs_t *, dal_t *, 108 reiserfs_gauge_t *); 109 110 FCLASS int (FPTR reiserfs_fs_clobber) (dal_t *); 111 FCLASS void (FPTR reiserfs_fs_close) (reiserfs_fs_t *); 112 113 FCLASS int (FPTR reiserfs_fs_is_resizeable) (reiserfs_fs_t *); 114 FCLASS int (FPTR reiserfs_fs_is_consistent) (reiserfs_fs_t *); 115 116 FCLASS blk_t (FPTR reiserfs_fs_min_size) (reiserfs_fs_t *); 117 FCLASS blk_t (FPTR reiserfs_fs_block_size) (reiserfs_fs_t *); 118 FCLASS dal_t* (FPTR reiserfs_fs_host_dal) (reiserfs_fs_t *); 119 120 FCLASS blk_t (FPTR reiserfs_fs_bitmap_used) (reiserfs_fs_t *); 121 FCLASS int (FPTR reiserfs_fs_bitmap_check) (reiserfs_fs_t *); 122 123 FCLASS reiserfs_gauge_t *(FPTR libreiserfs_gauge_create) ( 124 char *, reiserfs_gauge_handler_t, void *); 125 126 FCLASS void (FPTR libreiserfs_gauge_free) (reiserfs_gauge_t *); 127 128 static void gauge_handler(const char *name, unsigned int value, void *data, 129 int determined, int update_header, 130 int update_footer) 131 { 132 PedTimer *timer = (PedTimer *) data; 133 ped_timer_set_state_name(timer, name); 134 ped_timer_update(timer, 1.0 * value / 100); 135 } 136 137 static PedExceptionOption 138 exopt_libreiserfs_to_parted(reiserfs_exception_option_t option) 139 { 140 switch (option) { 141 case EXCEPTION_UNHANDLED: 142 return PED_EXCEPTION_UNHANDLED; 143 case EXCEPTION_FIX: 144 return PED_EXCEPTION_FIX; 145 case EXCEPTION_YES: 146 return PED_EXCEPTION_YES; 147 case EXCEPTION_NO: 148 return PED_EXCEPTION_NO; 149 case EXCEPTION_OK: 150 return PED_EXCEPTION_OK; 151 case EXCEPTION_RETRY: 152 return PED_EXCEPTION_RETRY; 153 case EXCEPTION_IGNORE: 154 return PED_EXCEPTION_IGNORE; 155 case EXCEPTION_CANCEL: 156 return PED_EXCEPTION_CANCEL; 157 158 default: 159 return PED_EXCEPTION_UNHANDLED; 160 } 161 } 162 163 static PedExceptionType 164 extype_libreiserfs_to_parted(reiserfs_exception_type_t type) 165 { 166 switch (type) { 167 case EXCEPTION_INFORMATION: 168 return PED_EXCEPTION_INFORMATION; 169 case EXCEPTION_WARNING: 170 return PED_EXCEPTION_WARNING; 171 case EXCEPTION_ERROR: 172 return PED_EXCEPTION_ERROR; 173 case EXCEPTION_FATAL: 174 return PED_EXCEPTION_FATAL; 175 case EXCEPTION_BUG: 176 return PED_EXCEPTION_BUG; 177 case EXCEPTION_NO_FEATURE: 178 return PED_EXCEPTION_NO_FEATURE; 179 180 default: 181 return PED_EXCEPTION_NO_FEATURE; 182 } 183 } 184 185 static int exception_handler(reiserfs_exception_t *exception) 186 { 187 int ex_type = libreiserfs_exception_type(exception); 188 int ex_option = libreiserfs_exception_option(exception); 189 char *ex_message = libreiserfs_exception_message(exception); 190 191 return ped_exception_throw (extype_libreiserfs_to_parted (ex_type), 192 exopt_libreiserfs_to_parted (ex_option), 193 ex_message); 194 } 195 #endif /* REISER_FULL_SUPPORT */ 196 197 static PedGeometry *reiserfs_probe(PedGeometry *geom) 198 { 199 int i; 200 reiserfs_super_block_t sb; 201 202 PED_ASSERT(geom != NULL, return NULL); 203 204 for (i = 0; reiserfs_super_offset[i] != -1; i++) { 205 if (reiserfs_super_offset[i] >= geom->length) 206 continue; 207 if (!ped_geometry_read (geom, &sb, reiserfs_super_offset[i], 1)) 208 continue; 209 210 if (strncmp(REISERFS_SIGNATURE, sb.s_magic, 211 strlen(REISERFS_SIGNATURE)) == 0 212 || strncmp(REISER2FS_SIGNATURE, sb.s_magic, 213 strlen(REISER2FS_SIGNATURE)) == 0 214 || strncmp(REISER3FS_SIGNATURE, sb.s_magic, 215 strlen(REISER3FS_SIGNATURE)) == 0) { 216 PedSector block_size; 217 PedSector block_count; 218 219 block_size = PED_LE16_TO_CPU(sb.s_blocksize) 220 / PED_SECTOR_SIZE_DEFAULT; 221 block_count = PED_LE32_TO_CPU(sb.s_block_count); 222 223 return ped_geometry_new(geom->dev, geom->start, 224 block_size * block_count); 225 } 226 } 227 return NULL; 228 } 229 230 #ifndef DISCOVER_ONLY 231 static int reiserfs_clobber(PedGeometry *geom) 232 { 233 int i; 234 char buf[512]; 235 236 PED_ASSERT(geom != NULL, return 0); 237 238 memset(buf, 0, 512); 239 for (i = 0; reiserfs_super_offset[i] != -1; i++) { 240 if (reiserfs_super_offset[i] >= geom->length) 241 continue; 242 if (!ped_geometry_write 243 (geom, buf, reiserfs_super_offset[i], 1)) 244 return 0; 245 } 246 return 1; 247 } 248 #endif /* !DISCOVER_ONLY */ 249 250 #ifdef REISER_FULL_SUPPORT 251 252 static PedFileSystem *reiserfs_open(PedGeometry *geom) 253 { 254 PedFileSystem *fs; 255 PedGeometry *fs_geom; 256 dal_t *dal; 257 reiserfs_fs_t *fs_info; 258 259 PED_ASSERT(geom != NULL, return NULL); 260 261 if (!(fs_geom = ped_geometry_duplicate(geom))) 262 goto error; 263 264 if (! (dal = geom_dal_create(fs_geom, DEFAULT_BLOCK_SIZE, O_RDONLY))) 265 goto error_fs_geom_free; 266 267 /* 268 We are passing NULL as DAL for journal. Therefore we let libreiserfs know, 269 that journal not available and parted will be working fine for reiserfs 270 with relocated journal too. 271 */ 272 if (!(fs = (PedFileSystem *) ped_malloc(sizeof(PedFileSystem)))) 273 goto error_free_dal; 274 275 if (!(fs_info = reiserfs_fs_open(dal, NULL))) 276 goto error_free_fs; 277 278 fs->type = reiserfs_type; 279 fs->geom = fs_geom; 280 fs->type_specific = (void *) fs_info; 281 282 return fs; 283 284 error_free_fs: 285 ped_free(fs); 286 error_free_dal: 287 geom_dal_free(dal); 288 error_fs_geom_free: 289 ped_geometry_destroy(fs_geom); 290 error: 291 return NULL; 292 } 293 294 static PedFileSystem *reiserfs_create(PedGeometry *geom, PedTimer *timer) 295 { 296 dal_t *dal; 297 uuid_t uuid; 298 PedFileSystem *fs; 299 PedGeometry *fs_geom; 300 reiserfs_fs_t *fs_info; 301 reiserfs_gauge_t *gauge = NULL; 302 303 PED_ASSERT(geom != NULL, return NULL); 304 305 fs_geom = ped_geometry_duplicate(geom); 306 307 if (!(dal = geom_dal_create(fs_geom, DEFAULT_BLOCK_SIZE, O_RDWR))) 308 goto error_fs_geom_free; 309 310 memset(uuid, 0, sizeof(uuid)); 311 uuid_generate(uuid); 312 313 ped_timer_reset(timer); 314 ped_timer_set_state_name(timer, _("creating")); 315 316 if (libreiserfs_gauge_create && libreiserfs_gauge_free) { 317 if (! (gauge = 318 libreiserfs_gauge_create(NULL, gauge_handler, timer))) 319 goto error_free_dal; 320 } 321 322 if (!(fs_info = reiserfs_fs_create(dal, dal, 0, JOURNAL_MAX_TRANS, 323 DEFAULT_JOURNAL_SIZE, 324 DEFAULT_BLOCK_SIZE, 325 FS_FORMAT_3_6, R5_HASH, NULL, 326 (char *) uuid, dal_len(dal), 327 gauge))) 328 goto error_free_gauge; 329 330 ped_timer_update(timer, 1.0); 331 332 if (gauge) 333 libreiserfs_gauge_free(gauge); 334 335 if (!(fs = (PedFileSystem *) ped_malloc(sizeof(PedFileSystem)))) 336 goto error_free_fs_info; 337 338 fs->type = reiserfs_type; 339 fs->geom = fs_geom; 340 fs->type_specific = (void *) fs_info; 341 342 return fs; 343 344 error_free_fs_info: 345 ped_free(fs_info); 346 error_free_gauge: 347 if (gauge) 348 libreiserfs_gauge_free(gauge); 349 error_free_dal: 350 geom_dal_free(dal); 351 error_fs_geom_free: 352 ped_geometry_destroy(fs_geom); 353 return NULL; 354 } 355 356 static int reiserfs_close(PedFileSystem *fs) 357 { 358 dal_t *dal; 359 360 PED_ASSERT(fs != NULL, return 0); 361 362 dal = reiserfs_fs_host_dal(fs->type_specific); 363 reiserfs_fs_close(fs->type_specific); 364 365 geom_dal_free(dal); 366 ped_geometry_sync(fs->geom); 367 368 ped_free(fs); 369 return 1; 370 } 371 372 static PedConstraint *reiserfs_get_create_constraint(const PedDevice *dev) 373 { 374 PedGeometry full_dev; 375 PedSector min_blks = (SUPER_OFFSET_IN_BYTES / DEFAULT_BLOCK_SIZE) 376 + 2 + DEFAULT_JOURNAL_SIZE + 1 + 100 + 1; 377 378 if (!ped_geometry_init(&full_dev, dev, 0, dev->length - 1)) 379 return NULL; 380 381 return ped_constraint_new(ped_alignment_any, ped_alignment_any, 382 &full_dev, &full_dev, 383 min_blks * (DEFAULT_BLOCK_SIZE / 512), 384 dev->length); 385 } 386 387 static int reiserfs_check(PedFileSystem *fs, PedTimer *timer) 388 { 389 reiserfs_fs_t *fs_info; 390 #ifdef HAVE_REISERFS_FS_CHECK 391 reiserfs_gauge_t *gauge = NULL; 392 #endif 393 394 PED_ASSERT(fs != NULL, return 0); 395 396 fs_info = fs->type_specific; 397 398 if (!reiserfs_fs_is_consistent(fs_info)) { 399 ped_exception_throw(PED_EXCEPTION_ERROR, 400 PED_EXCEPTION_CANCEL, 401 _("The file system is in an invalid " 402 "state. Perhaps it is mounted?")); 403 return 0; 404 } 405 406 if (!reiserfs_fs_is_resizeable(fs_info)) 407 ped_exception_throw(PED_EXCEPTION_WARNING, 408 PED_EXCEPTION_IGNORE, 409 _("The file system is in old " 410 "(unresizeable) format.")); 411 412 if (!reiserfs_fs_bitmap_check(fs_info)) { 413 ped_exception_throw(PED_EXCEPTION_ERROR, 414 PED_EXCEPTION_CANCEL, 415 _("Invalid free blocks count. Run " 416 "reiserfsck --check first.")); 417 return 0; 418 } 419 420 #ifdef HAVE_REISERFS_FS_CHECK 421 ped_timer_reset(timer); 422 423 if (libreiserfs_gauge_create && libreiserfs_gauge_free) { 424 if (! 425 (gauge = 426 libreiserfs_gauge_create(NULL, gauge_handler, timer))) 427 return 0; 428 } 429 430 ped_timer_set_state_name(timer, _("checking")); 431 ped_timer_update(timer, 0.0); 432 433 if (!reiserfs_fs_check(fs_info, gauge)) { 434 ped_exception_throw(PED_EXCEPTION_ERROR, 435 PED_EXCEPTION_CANCEL, 436 _("Reiserfs tree seems to be corrupted. " 437 "Run reiserfsck --check first.")); 438 return 0; 439 } 440 441 ped_timer_update(timer, 1.0); 442 443 if (gauge) 444 libreiserfs_gauge_free(gauge); 445 #endif 446 447 ped_exception_throw(PED_EXCEPTION_INFORMATION, PED_EXCEPTION_OK, 448 _("The reiserfs file system passed a basic check. " 449 "For a more comprehensive check, run " 450 "reiserfsck --check.")); 451 452 return 1; 453 } 454 455 static int reiserfs_resize(PedFileSystem *fs, PedGeometry *geom, 456 PedTimer *timer) 457 { 458 dal_t *dal; 459 blk_t fs_len; 460 PedSector old_length; 461 reiserfs_fs_t *fs_info; 462 reiserfs_gauge_t *gauge = NULL; 463 464 PED_ASSERT(fs != NULL, return 0); 465 466 old_length = fs->geom->length; 467 468 PED_ASSERT (fs->geom->dev == geom->dev, return 0); 469 470 if (fs->geom->start != geom->start) { 471 ped_exception_throw(PED_EXCEPTION_ERROR, 472 PED_EXCEPTION_CANCEL, 473 _("Sorry, can't move the start of " 474 "reiserfs partitions yet.")); 475 return 0; 476 } 477 478 fs_info = fs->type_specific; 479 480 fs_len = (blk_t) (geom->length / (reiserfs_fs_block_size(fs_info) / 481 PED_SECTOR_SIZE_DEFAULT)); 482 483 dal = reiserfs_fs_host_dal(fs_info); 484 485 if (dal_flags(dal) && O_RDONLY) { 486 if (!geom_dal_reopen(dal, O_RDWR)) { 487 ped_exception_throw(PED_EXCEPTION_ERROR, 488 PED_EXCEPTION_CANCEL, 489 _("Couldn't reopen device " 490 "abstraction layer for " 491 "read/write.")); 492 return 0; 493 } 494 } 495 496 ped_timer_reset(timer); 497 498 if (libreiserfs_gauge_create && libreiserfs_gauge_free) { 499 if (! 500 (gauge = 501 libreiserfs_gauge_create(NULL, gauge_handler, timer))) 502 return 0; 503 } 504 505 if (old_length > geom->length) { 506 507 ped_timer_set_state_name(timer, _("shrinking")); 508 ped_timer_update(timer, 0.0); 509 510 if (!reiserfs_fs_resize(fs_info, fs_len, gauge)) 511 goto error_free_gauge; 512 513 ped_geometry_set_end (fs->geom, geom->end); 514 dal_realize(dal); 515 } else { 516 ped_geometry_set_end (fs->geom, geom->end); 517 dal_realize(dal); 518 519 ped_timer_set_state_name(timer, _("expanding")); 520 ped_timer_update(timer, 0.0); 521 522 if (!reiserfs_fs_resize(fs_info, fs_len, gauge)) 523 goto error_free_gauge; 524 } 525 526 ped_timer_update(timer, 1.0); 527 528 if (gauge) 529 libreiserfs_gauge_free(gauge); 530 531 return 1; 532 533 error_free_gauge: 534 if (gauge) 535 libreiserfs_gauge_free(gauge); 536 ped_geometry_set_end (fs->geom, fs->geom->start + old_length - 1); 537 return 0; 538 } 539 540 static PedConstraint *reiserfs_get_resize_constraint(const PedFileSystem * 541 fs) 542 { 543 PedDevice *dev; 544 PedSector min_size; 545 PedGeometry full_disk; 546 reiserfs_fs_t *fs_info; 547 PedAlignment start_align; 548 PedGeometry start_sector; 549 550 PED_ASSERT(fs != NULL, return NULL); 551 552 fs_info = fs->type_specific; 553 dev = fs->geom->dev; 554 555 if (!ped_alignment_init(&start_align, fs->geom->start, 0)) 556 return NULL; 557 if (!ped_geometry_init(&full_disk, dev, 0, dev->length - 1)) 558 return NULL; 559 if (!ped_geometry_init(&start_sector, dev, fs->geom->start, 1)) 560 return NULL; 561 562 /* 563 Minsize for reiserfs is area occupied by data blocks and 564 metadata blocks minus free space blocks and minus bitmap 565 blocks which describes free space blocks. 566 */ 567 min_size = reiserfs_fs_min_size(fs_info) * 568 (reiserfs_fs_block_size(fs_info) / PED_SECTOR_SIZE_DEFAULT); 569 570 return ped_constraint_new(&start_align, ped_alignment_any, 571 &start_sector, &full_disk, min_size, 572 dev->length); 573 } 574 575 static PedFileSystem *reiserfs_copy(const PedFileSystem *fs, 576 PedGeometry *geom, PedTimer *timer) 577 { 578 dal_t *dal; 579 PedGeometry *fs_geom; 580 PedFileSystem *new_fs; 581 blk_t fs_len, min_needed_blk; 582 583 reiserfs_fs_t *dest_fs, *src_fs; 584 reiserfs_gauge_t *gauge = NULL; 585 586 fs_geom = ped_geometry_duplicate(geom); 587 588 if (!(dal = geom_dal_create(fs_geom, DEFAULT_BLOCK_SIZE, O_RDWR))) { 589 ped_exception_throw(PED_EXCEPTION_ERROR, 590 PED_EXCEPTION_CANCEL, 591 _("Couldn't create reiserfs device " 592 "abstraction handler.")); 593 goto error_free_fs_geom; 594 } 595 596 src_fs = fs->type_specific; 597 598 fs_len = 599 (geom->length / (reiserfs_fs_block_size(src_fs) / PED_SECTOR_SIZE_DEFAULT)); 600 min_needed_blk = reiserfs_fs_bitmap_used(src_fs); 601 602 if (fs_len <= min_needed_blk) { 603 ped_exception_throw(PED_EXCEPTION_ERROR, 604 PED_EXCEPTION_CANCEL, 605 _("Device is too small for %lu blocks."), 606 min_needed_blk); 607 goto error_free_dal; 608 } 609 610 if (! (new_fs = (PedFileSystem *) ped_malloc(sizeof(PedFileSystem)))) 611 goto error_free_dal; 612 613 ped_timer_reset(timer); 614 ped_timer_set_state_name(timer, _("copying")); 615 ped_timer_update(timer, 0.0); 616 617 if (libreiserfs_gauge_create && libreiserfs_gauge_free) { 618 if (! (gauge = 619 libreiserfs_gauge_create(NULL, gauge_handler, timer))) 620 goto error_free_new_fs; 621 } 622 623 if (!(dest_fs = reiserfs_fs_copy(src_fs, dal, gauge))) 624 goto error_free_gauge; 625 626 ped_timer_update(timer, 1.0); 627 628 if (gauge) 629 libreiserfs_gauge_free(gauge); 630 631 new_fs->type = reiserfs_type; 632 new_fs->geom = fs_geom; 633 new_fs->type_specific = (void *) dest_fs; 634 635 return new_fs; 636 637 error_free_gauge: 638 if (gauge) 639 libreiserfs_gauge_free(gauge); 640 error_free_new_fs: 641 ped_free(new_fs); 642 error_free_dal: 643 geom_dal_free(dal); 644 error_free_fs_geom: 645 ped_geometry_destroy(fs_geom); 646 return NULL; 647 } 648 649 static PedConstraint *reiserfs_get_copy_constraint(const PedFileSystem *fs, 650 const PedDevice *dev) 651 { 652 PedGeometry full_dev; 653 654 PED_ASSERT(fs != NULL, return NULL); 655 PED_ASSERT(dev != NULL, return NULL); 656 657 if (!ped_geometry_init(&full_dev, dev, 0, dev->length - 1)) 658 return NULL; 659 660 return ped_constraint_new(ped_alignment_any, ped_alignment_any, 661 &full_dev, &full_dev, 662 reiserfs_fs_bitmap_used(fs->type_specific), 663 dev->length); 664 } 665 666 #endif /* !REISER_FULL_SUPPORT */ 667 668 #ifdef DYNAMIC_LOADING 669 670 #define INIT_SYM(SYM) SYM = getsym (libreiserfs_handle, #SYM) 671 672 static void *getsym(void *handle, const char *symbol) 673 { 674 void *entry; 675 char *error; 676 677 entry = dlsym(handle, symbol); 678 if ((error = dlerror()) != NULL) { 679 ped_exception_throw(PED_EXCEPTION_WARNING, 680 PED_EXCEPTION_IGNORE, 681 _("Couldn't resolve symbol %s. " 682 "Error: %s."), 683 symbol, error); 684 return NULL; 685 } 686 687 return entry; 688 } 689 690 static int reiserfs_ops_interface_version_check(void) 691 { 692 int min_interface_version, max_interface_version; 693 int (*libreiserfs_get_max_interface_version) (void); 694 int (*libreiserfs_get_min_interface_version) (void); 695 696 INIT_SYM(libreiserfs_get_max_interface_version); 697 INIT_SYM(libreiserfs_get_min_interface_version); 698 699 if (!libreiserfs_get_min_interface_version || 700 !libreiserfs_get_max_interface_version) { 701 ped_exception_throw( 702 PED_EXCEPTION_WARNING, PED_EXCEPTION_CANCEL, 703 _("GNU Parted found an invalid libreiserfs library.")); 704 return 0; 705 } 706 707 min_interface_version = libreiserfs_get_min_interface_version(); 708 max_interface_version = libreiserfs_get_max_interface_version(); 709 710 if (REISERFS_API_VERSION < min_interface_version || 711 REISERFS_API_VERSION > max_interface_version) { 712 ped_exception_throw( 713 PED_EXCEPTION_WARNING, PED_EXCEPTION_CANCEL, 714 _("GNU Parted has detected libreiserfs interface " 715 "version mismatch. Found %d-%d, required %d. " 716 "ReiserFS support will be disabled."), 717 min_interface_version, 718 max_interface_version, 719 REISERFS_API_VERSION); 720 return 0; 721 } 722 723 return 1; 724 } 725 726 static int reiserfs_ops_init(void) 727 { 728 if (!(libreiserfs_handle = dlopen("libreiserfs.so", RTLD_NOW))) 729 goto error; 730 731 if (!reiserfs_ops_interface_version_check()) 732 goto error_free_libreiserfs_handle; 733 734 if (!(libdal_handle = dlopen("libdal.so", RTLD_NOW))) 735 goto error_free_libreiserfs_handle; 736 737 INIT_SYM(reiserfs_fs_probe); 738 INIT_SYM(libreiserfs_exception_type); 739 740 INIT_SYM(libreiserfs_exception_option); 741 INIT_SYM(libreiserfs_exception_message); 742 INIT_SYM(libreiserfs_exception_set_handler); 743 744 INIT_SYM(reiserfs_fs_clobber); 745 INIT_SYM(reiserfs_fs_open); 746 INIT_SYM(reiserfs_fs_create); 747 INIT_SYM(reiserfs_fs_resize); 748 INIT_SYM(reiserfs_fs_copy); 749 750 INIT_SYM(reiserfs_fs_is_resizeable); 751 INIT_SYM(reiserfs_fs_is_consistent); 752 753 INIT_SYM(reiserfs_fs_bitmap_check); 754 INIT_SYM(reiserfs_fs_bitmap_used); 755 756 INIT_SYM(reiserfs_fs_min_size); 757 INIT_SYM(reiserfs_fs_block_size); 758 759 INIT_SYM(reiserfs_fs_host_dal); 760 INIT_SYM(reiserfs_fs_close); 761 762 INIT_SYM(libreiserfs_gauge_create); 763 INIT_SYM(libreiserfs_gauge_free); 764 765 INIT_SYM(dal_realize); 766 INIT_SYM(dal_flags); 767 768 INIT_SYM(dal_block_size); 769 INIT_SYM(dal_len); 770 771 return 1; 772 773 error_free_libreiserfs_handle: 774 dlclose(libreiserfs_handle); 775 libreiserfs_handle = NULL; 776 error: 777 return 0; 778 } 779 780 static void reiserfs_ops_done() 781 { 782 if (libdal_handle) 783 dlclose(libdal_handle); 784 if (libreiserfs_handle) 785 dlclose(libreiserfs_handle); 786 } 787 #endif /* DYNAMIC_LOADING */ 788 789 #define REISER_BLOCK_SIZES ((int[]){512, 1024, 2048, 4096, 8192, 0}) 790 791 #ifdef REISER_FULL_SUPPORT 792 static PedFileSystemOps reiserfs_full_ops = { 793 .probe = reiserfs_probe, 794 .clobber = reiserfs_clobber, 795 .open = reiserfs_open, 796 .create = reiserfs_create, 797 .close = reiserfs_close, 798 .check = reiserfs_check, 799 .copy = reiserfs_copy, 800 .resize = reiserfs_resize, 801 .get_create_constraint = reiserfs_get_create_constraint, 802 .get_resize_constraint = reiserfs_get_resize_constraint, 803 .get_copy_constraint = reiserfs_get_copy_constraint 804 }; 805 806 static PedFileSystemType reiserfs_full_type = { 807 .next = NULL, 808 .ops = &reiserfs_full_ops, 809 .name = "reiserfs", 810 .block_sizes = REISER_BLOCK_SIZES 811 }; 812 #endif /* REISER_FULL_SUPPORT */ 813 814 static PedFileSystemOps reiserfs_simple_ops = { 815 .probe = reiserfs_probe, 816 #ifdef DISCOVER_ONLY 817 .clobber = NULL, 818 #else 819 .clobber = reiserfs_clobber, 820 #endif 821 .open = NULL, 822 .create = NULL, 823 .close = NULL, 824 .check = NULL, 825 .copy = NULL, 826 .resize = NULL, 827 .get_create_constraint = NULL, 828 .get_resize_constraint = NULL, 829 .get_copy_constraint = NULL 830 }; 831 832 static PedFileSystemType reiserfs_simple_type = { 833 .next = NULL, 834 .ops = &reiserfs_simple_ops, 835 .name = "reiserfs", 836 .block_sizes = REISER_BLOCK_SIZES 837 }; 838 839 void ped_file_system_reiserfs_init() 840 { 841 #ifdef DYNAMIC_LOADING 842 libreiserfs_present = reiserfs_ops_init(); 843 if (libreiserfs_present) { 844 reiserfs_type = &reiserfs_full_type; 845 libreiserfs_exception_set_handler(exception_handler); 846 } else { 847 reiserfs_type = &reiserfs_simple_type; 848 } 849 #else /* !DYNAMIC_LOADING */ 850 #ifdef REISER_FULL_SUPPORT 851 libreiserfs_exception_set_handler(exception_handler); 852 reiserfs_type = &reiserfs_full_type; 853 #else 854 reiserfs_type = &reiserfs_simple_type; 855 #endif 856 #endif /* !DYNAMIC_LOADING */ 857 ped_file_system_type_register(reiserfs_type); 858 } 859 860 void ped_file_system_reiserfs_done() 861 { 862 ped_file_system_type_unregister(reiserfs_type); 863 #ifdef DYNAMIC_LOADING 864 reiserfs_ops_done(); 865 #endif /* DYNAMIC_LOADING */ 866 }