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 }