1 /*
2 ext2.c -- generic ext2 stuff
3 Copyright (C) 1998, 1999, 2000, 2001, 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 #include <config.h>
20
21 #ifndef DISCOVER_ONLY
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <time.h>
27 #include <uuid/uuid.h>
28 #include "ext2.h"
29
30 /* ext2 stuff ****************************************************************/
31
32 unsigned char _bitmap[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
33
34 int ext2_copy_block(struct ext2_fs *fs, blk_t from, blk_t to)
35 {
36 unsigned char* buf = ped_malloc (fs->blocksize);
37
38 if (!ext2_bcache_flush(fs, from)) return 0;
39 if (!ext2_bcache_flush(fs, to)) return 0;
40
41 if (!ext2_read_blocks(fs, buf, from, 1)) return 0;
42 if (!ext2_write_blocks(fs, buf, to, 1)) return 0;
43
44 return 1;
45 }
46
47 int ext2_get_block_state(struct ext2_fs *fs, blk_t block)
48 {
49 struct ext2_buffer_head *bh;
50 int group;
51 int offset;
52 int state;
53
54 block -= EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb);
55 group = block / EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
56 offset = block % EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
57
58 bh = ext2_bread(fs, EXT2_GROUP_BLOCK_BITMAP(fs->gd[group]));
59 state = bh->data[offset>>3] & _bitmap[offset&7];
60 ext2_brelse(bh, 0);
61
62 return state;
63 }
64
65 blk_t ext2_find_free_block(struct ext2_fs *fs)
66 {
67 int i;
68
69 for (i=0;i<fs->numgroups;i++)
70 if (EXT2_GROUP_FREE_BLOCKS_COUNT(fs->gd[i]))
71 {
72 blk_t j;
73 blk_t offset;
74
75 offset = i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)
76 + EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb);
77 for (j=fs->adminblocks;
78 j<EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
79 j++)
80 if (ext2_is_data_block(fs, offset + j) &&
81 !ext2_get_block_state(fs, offset + j))
82 return offset + j;
83
84 ped_exception_throw (PED_EXCEPTION_ERROR,
85 PED_EXCEPTION_CANCEL,
86 _("Inconsistent group descriptors!"));
87 }
88
89 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
90 _("File system full!"));
91 return 0;
92 }
93
94 ino_t ext2_find_free_inode(struct ext2_fs *fs)
95 {
96 int i;
97
98 for (i=0;i<fs->numgroups;i++)
99 if (EXT2_GROUP_FREE_INODES_COUNT(fs->gd[i]))
100 {
101 ino_t j;
102 ino_t offset;
103
104 offset = i * EXT2_SUPER_INODES_PER_GROUP(fs->sb) + 1;
105 for (j=0;j<EXT2_SUPER_INODES_PER_GROUP(fs->sb);j++)
106 if (!ext2_get_inode_state(fs, offset + j))
107 return offset + j;
108
109 ped_exception_throw (PED_EXCEPTION_ERROR,
110 PED_EXCEPTION_CANCEL,
111 _("Inconsistent group descriptors!"));
112 }
113
114 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
115 _("File system full!"));
116 return 0;
117 }
118
119 int ext2_move_blocks(struct ext2_fs *fs, blk_t src, blk_t num, blk_t dest)
120 {
121 unsigned char *buf;
122 blk_t i;
123
124 ped_exception_fetch_all();
125 if ((buf = ped_malloc(num << fs->logsize)) != NULL)
126 {
127 ped_exception_leave_all();
128
129 if (!ext2_bcache_flush_range(fs, src, num)) return 0;
130 if (!ext2_bcache_flush_range(fs, dest, num)) return 0;
131
132 if (!ext2_read_blocks(fs, buf, src, num)) return 0;
133 if (!ext2_write_blocks(fs, buf, dest, num)) return 0;
134
135 ped_free(buf);
136 return 1;
137 }
138 ped_exception_catch();
139 ped_exception_leave_all();
140
141 if (src > dest)
142 {
143 for (i=0;i<num;i++)
144 if (!ext2_copy_block(fs, src+i, dest+i))
145 return 0;
146 }
147 else
148 {
149 for (i=num;i>0;i--)
150 if (!ext2_copy_block(fs, src+i, dest+i))
151 return 0;
152 }
153 return 1;
154 }
155
156 int ext2_read_blocks(struct ext2_fs *fs, void *ptr, blk_t block, blk_t num)
157 {
158 return fs->devhandle->ops->read(fs->devhandle->cookie, ptr, block, num);
159 }
160
161 int ext2_set_block_state(struct ext2_fs *fs, blk_t block, int state, int updatemetadata)
162 {
163 struct ext2_buffer_head *bh;
164 int group;
165 int offset;
166
167 block -= EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb);
168 group = block / EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
169 offset = block % EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
170
171 bh = ext2_bread(fs, EXT2_GROUP_BLOCK_BITMAP(fs->gd[group]));
172 bh->dirty = 1;
173 if (state)
174 bh->data[offset>>3] |= _bitmap[offset&7];
175 else
176 bh->data[offset>>3] &= ~_bitmap[offset&7];
177 ext2_brelse(bh, 0);
178
179 if (updatemetadata)
180 {
181 int diff;
182
183 diff = state ? -1 : 1;
184
185 fs->gd[group].bg_free_blocks_count = PED_CPU_TO_LE16
186 (EXT2_GROUP_FREE_BLOCKS_COUNT(fs->gd[group]) + diff);
187 fs->sb.s_free_blocks_count = PED_CPU_TO_LE32
188 (EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) + diff);
189 fs->metadirty |= EXT2_META_SB | EXT2_META_GD;
190 }
191 return 1;
192 }
193
194 int ext2_write_blocks(struct ext2_fs *fs, void *ptr, blk_t block, blk_t num)
195 {
196 return fs->devhandle->ops->write(fs->devhandle->cookie, ptr, block, num);
197 }
198
199 int ext2_zero_blocks(struct ext2_fs *fs, blk_t block, blk_t num)
200 {
201 unsigned char *buf;
202 blk_t i;
203
204 ped_exception_fetch_all();
205 buf = ped_malloc (num << fs->logsize);
206 if (buf)
207 {
208 ped_exception_leave_all();
209
210 memset(buf, 0, num << fs->logsize);
211 if (!ext2_bcache_flush_range(fs, block, num))
212 goto error_free_buf;
213 if (!ext2_write_blocks(fs, buf, block, num))
214 goto error_free_buf;
215 ped_free(buf);
216 return 1;
217 }
218 ped_exception_catch();
219
220 buf = ped_malloc (fs->blocksize);
221 if (buf)
222 {
223 ped_exception_leave_all();
224
225 memset(buf, 0, fs->blocksize);
226
227 for (i=0;i<num;i++)
228 {
229 if (!ext2_bcache_flush(fs, block+i))
230 goto error_free_buf;
231 if (!ext2_write_blocks(fs, buf, block+i, 1))
232 goto error_free_buf;
233 }
234
235 ped_free(buf);
236 return 1;
237 }
238 ped_exception_catch();
239 ped_exception_leave_all();
240
241 for (i=0;i<num;i++)
242 {
243 struct ext2_buffer_head *bh;
244
245 bh = ext2_bcreate(fs, block+i);
246 if (!bh)
247 goto error;
248 bh->dirty = 1;
249 if (!ext2_brelse(bh, 1))
250 goto error;
251 }
252 return 1;
253
254 error_free_buf:
255 ped_free(buf);
256 error:
257 return 0;
258 }
259
260 off_t ext2_get_inode_offset(struct ext2_fs *fs, ino_t inode, blk_t *block)
261 {
262 int group;
263 int offset;
264
265 inode--;
266
267 group = inode / EXT2_SUPER_INODES_PER_GROUP(fs->sb);
268 offset = (inode % EXT2_SUPER_INODES_PER_GROUP(fs->sb))
269 * sizeof(struct ext2_inode);
270
271 *block = EXT2_GROUP_INODE_TABLE(fs->gd[group])
272 + (offset >> fs->logsize);
273
274 return offset & (fs->blocksize - 1);
275 }
276
277 int ext2_get_inode_state(struct ext2_fs *fs, ino_t inode)
278 {
279 struct ext2_buffer_head *bh;
280 int group;
281 int offset;
282 int ret;
283
284 inode--;
285 group = inode / EXT2_SUPER_INODES_PER_GROUP(fs->sb);
286 offset = inode % EXT2_SUPER_INODES_PER_GROUP(fs->sb);
287
288 bh = ext2_bread(fs, EXT2_GROUP_INODE_BITMAP(fs->gd[group]));
289 ret = bh->data[offset>>3] & _bitmap[offset&7];
290 ext2_brelse(bh, 0);
291
292 return ret;
293 }
294
295 int ext2_read_inode(struct ext2_fs *fs, ino_t inode, struct ext2_inode *data)
296 {
297 struct ext2_buffer_head *bh;
298 blk_t blk;
299 off_t off;
300
301 off = ext2_get_inode_offset(fs, inode, &blk);
302
303 bh = ext2_bread(fs, blk);
304 if (!bh)
305 return 0;
306
307 memcpy(data, bh->data + off, sizeof(struct ext2_inode));
308 ext2_brelse(bh, 0);
309 return 1;
310 }
311
312 int ext2_set_inode_state(struct ext2_fs *fs, ino_t inode, int state, int updatemetadata)
313 {
314 struct ext2_buffer_head *bh;
315 int group;
316 int offset;
317
318 inode--;
319 group = inode / EXT2_SUPER_INODES_PER_GROUP(fs->sb);
320 offset = inode % EXT2_SUPER_INODES_PER_GROUP(fs->sb);
321
322 bh = ext2_bread(fs, EXT2_GROUP_INODE_BITMAP(fs->gd[group]));
323 if (!bh)
324 return 0;
325 bh->dirty = 1;
326 if (state)
327 bh->data[offset>>3] |= _bitmap[offset&7];
328 else
329 bh->data[offset>>3] &= ~_bitmap[offset&7];
330 ext2_brelse(bh, 0);
331
332 if (updatemetadata)
333 {
334 int diff;
335
336 diff = state ? -1 : 1;
337
338 fs->gd[group].bg_free_inodes_count = PED_CPU_TO_LE16
339 (EXT2_GROUP_FREE_INODES_COUNT(fs->gd[group]) + diff);
340 fs->sb.s_free_inodes_count = PED_CPU_TO_LE32
341 (EXT2_SUPER_FREE_INODES_COUNT(fs->sb) + diff);
342 fs->metadirty = EXT2_META_SB | EXT2_META_GD;
343 }
344 return 1;
345 }
346
347 static void
348 _inode_update_size(struct ext2_fs *fs, struct ext2_inode *inode, int delta)
349 {
350 int i512perblock = 1 << (fs->logsize - 9);
351 uint64_t size;
352
353 /* i_blocks is in 512 byte blocks */
354 inode->i_blocks = PED_CPU_TO_LE32(EXT2_INODE_BLOCKS(*inode)
355 + delta * i512perblock);
356 size = EXT2_INODE_SIZE(*inode) + delta * fs->blocksize;
357 inode->i_size = PED_CPU_TO_LE32(size % (1LL << 32));
358 inode->i_size_high = PED_CPU_TO_LE32(size / (1LL << 32));
359 inode->i_mtime = PED_CPU_TO_LE32(time(NULL));
360 }
361
362 int ext2_do_inode(struct ext2_fs *fs, struct ext2_inode *inode, blk_t block,
363 int action)
364 {
365 struct ext2_buffer_head *bh;
366 uint32_t *udata;
367 blk_t count = 0;
368 int i;
369 int u32perblock = fs->blocksize >> 2;
370 int i512perblock = 1 << (fs->logsize - 9);
371
372 if (block == 0 || EXT2_INODE_MODE(*inode) == 0)
373 return -1;
374
375 if (fs->opt_debug)
376 switch (action)
377 {
378 case EXT2_ACTION_ADD:
379 fprintf(stderr,"adding 0x%04x to inode\n",
380 block);
381 break;
382 case EXT2_ACTION_DELETE:
383 fprintf(stderr,"deleting 0x%04x from inode\n",
384 block);
385 break;
386 case EXT2_ACTION_FIND:
387 fprintf(stderr,"finding 0x%04x in inode\n",
388 block);
389 break;
390 }
391
392 /* Direct blocks for first 12 blocks */
393 for (i = 0; i < EXT2_NDIR_BLOCKS; i++)
394 {
395 if (action == EXT2_ACTION_ADD && !EXT2_INODE_BLOCK(*inode, i))
396 {
397 inode->i_block[i] = PED_CPU_TO_LE32(block);
398 _inode_update_size (fs, inode, 1);
399 ext2_set_block_state(fs, block, 1, 1);
400 return i;
401 }
402 if (EXT2_INODE_BLOCK(*inode, i) == block)
403 {
404 if (action == EXT2_ACTION_DELETE)
405 {
406 inode->i_block[i] = 0;
407 _inode_update_size (fs, inode, -1);
408 ext2_set_block_state(fs, block, 0, 1);
409 }
410 return i;
411 }
412 if (EXT2_INODE_BLOCK(*inode, i))
413 count += i512perblock;
414 }
415
416 count += EXT2_INODE_BLOCK(*inode, EXT2_IND_BLOCK) ? i512perblock : 0;
417 count += EXT2_INODE_BLOCK(*inode, EXT2_DIND_BLOCK) ? i512perblock : 0;
418 count += EXT2_INODE_BLOCK(*inode, EXT2_TIND_BLOCK) ? i512perblock : 0;
419
420 if (!EXT2_INODE_BLOCK(*inode, EXT2_IND_BLOCK) ||
421 (count >= EXT2_INODE_BLOCKS(*inode) && action != EXT2_ACTION_ADD))
422 return -1;
423
424 bh = ext2_bread(fs, EXT2_INODE_BLOCK(*inode, EXT2_IND_BLOCK));
425 udata = (uint32_t *)bh->data;
426
427 /* Indirect blocks for next 256/512/1024 blocks (for 1k/2k/4k blocks) */
428 for (i = 0; i < u32perblock; i++) {
429 if (action == EXT2_ACTION_ADD && !udata[i]) {
430 bh->dirty = 1;
431 udata[i] = PED_CPU_TO_LE32(block);
432 _inode_update_size (fs, inode, 1);
433 ext2_set_block_state(fs, block, 1, 1);
434 ext2_brelse(bh, 0);
435 return EXT2_NDIR_BLOCKS + i;
436 }
437 if (PED_LE32_TO_CPU(udata[i]) == block) {
438 if (action == EXT2_ACTION_DELETE) {
439 bh->dirty = 1;
440 udata[i] = 0;
441 _inode_update_size (fs, inode, -1);
442 ext2_set_block_state(fs, block, 0, 1);
443 }
444 ext2_brelse(bh, 0);
445 return EXT2_NDIR_BLOCKS + i;
446 }
447 if (udata[i])
448 {
449 count += i512perblock;
450 if (count >= EXT2_INODE_BLOCKS(*inode) &&
451 action != EXT2_ACTION_ADD)
452 return -1;
453 }
454 }
455
456 ext2_brelse(bh, 0);
457
458 if (!EXT2_INODE_BLOCK(*inode, EXT2_DIND_BLOCK) ||
459 (count >= EXT2_INODE_BLOCKS(*inode) && action != EXT2_ACTION_ADD))
460 return -1;
461 bh = ext2_bread(fs, EXT2_INODE_BLOCK(*inode, EXT2_DIND_BLOCK));
462 udata = (uint32_t *)bh->data;
463
464 /* Double indirect blocks for next 2^16/2^18/2^20 1k/2k/4k blocks */
465 for (i = 0; i < u32perblock; i++) {
466 struct ext2_buffer_head *bh2;
467 uint32_t *udata2;
468 int j;
469
470 if (!udata[i]) {
471 ext2_brelse(bh, 0);
472 return -1;
473 }
474 bh2 = ext2_bread(fs, PED_LE32_TO_CPU(udata[i]));
475 udata2 = (uint32_t *)bh2->data;
476 count += i512perblock;
477
478 for (j = 0; j < u32perblock; j++) {
479 if (action == EXT2_ACTION_ADD && !udata2[j]) {
480 bh2->dirty = 1;
481 udata2[j] = PED_CPU_TO_LE32(block);
482 _inode_update_size (fs, inode, 1);
483 ext2_set_block_state(fs, block, 1, 1);
484 ext2_brelse(bh, 0);
485 ext2_brelse(bh2, 0);
486 return EXT2_NDIR_BLOCKS + i * u32perblock + j;
487 }
488 if (PED_LE32_TO_CPU(udata2[j]) == block) {
489 if (action == EXT2_ACTION_DELETE) {
490 bh2->dirty = 1;
491 udata2[j] = 0;
492 _inode_update_size (fs, inode, -1);
493 ext2_set_block_state(fs, block, 0, 1);
494 }
495 ext2_brelse(bh, 0);
496 ext2_brelse(bh2, 0);
497 return EXT2_NDIR_BLOCKS + i * u32perblock + j;
498 }
499 if (udata2[j])
500 {
501 count += i512perblock;
502 if (count >= EXT2_INODE_BLOCKS(*inode) &&
503 action != EXT2_ACTION_ADD)
504 return -1;
505 }
506 }
507 ext2_brelse(bh2, 0);
508 }
509 ext2_brelse(bh, 0);
510
511 /* FIXME: we should check for triple-indirect blocks here, but it
512 * would be nice to have a better routine to traverse blocks, and
513 * file systems that need triple-indirect blocks for the resize
514 * inode are too big to worry about yet.
515 */
516
517 return -1;
518 }
519
520 int ext2_write_inode(struct ext2_fs *fs, ino_t inode, const struct ext2_inode *data)
521 {
522 struct ext2_buffer_head *bh;
523 blk_t blk;
524 off_t off;
525
526 off = ext2_get_inode_offset(fs, inode, &blk);
527
528 bh = ext2_bread(fs, blk);
529 if (!bh)
530 return 0;
531 bh->dirty = 1;
532 memcpy(bh->data + off, data, sizeof(struct ext2_inode));
533 ext2_brelse(bh, 0);
534
535 return 1;
536 }
537
538 int ext2_zero_inode(struct ext2_fs *fs, ino_t inode)
539 {
540 struct ext2_inode buf;
541
542 memset(&buf, 0, sizeof(struct ext2_inode));
543 return ext2_write_inode(fs, inode, &buf);
544 }
545
546
547
548
549
550 /* check whether y is root of x
551 * (formula grabbed from linux ext2 kernel source) */
552 static int is_root(int x, int y)
553 {
554 if (!x)
555 return 1;
556
557 while (1)
558 {
559 if (x == 1)
560 return 1;
561
562 if (x % y)
563 return 0;
564
565 x /= y;
566 }
567 }
568
569 /* check whether group contains a superblock copy on file systems
570 * where not all groups have one (sparse superblock feature) */
571 int ext2_is_group_sparse(struct ext2_fs *fs, int group)
572 {
573 if (!fs->sparse)
574 return 1;
575
576 if (is_root(group, 3) || is_root(group, 5) || is_root(group, 7))
577 return 1;
578
579 return 0;
580 }
581
582 void ext2_close(struct ext2_fs *fs)
583 {
584 ext2_commit_metadata(fs, EXT2_META_PRIMARY | EXT2_META_BACKUP);
585 ext2_sync(fs);
586
587 ext2_bcache_deinit(fs);
588
589 fs->devhandle->ops->close(fs->devhandle->cookie);
590
591 ped_free(fs->gd);
592 ped_free(fs);
593 }
594
595 int ext2_commit_metadata(struct ext2_fs *fs, int copies)
596 {
597 int i;
598 int num;
599 int wmeta = fs->metadirty & copies;
600 unsigned char* sb = ped_malloc(fs->blocksize);
601 struct ext2_super_block *sb_for_io;
602 int sb_block;
603
604 /* See if there is even anything to write... */
605 if (wmeta == EXT2_META_CLEAN)
606 return 1;
607
608 fs->sb.s_r_blocks_count = PED_CPU_TO_LE32 (
609 fs->r_frac * (loff_t)EXT2_SUPER_BLOCKS_COUNT(fs->sb)
610 / 100);
611
612 if (!ext2_read_blocks (fs, sb, 0, 1))
613 return 0;
614
615 if (EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb)) {
616 memcpy(sb, &fs->sb, 1024);
617 sb_for_io = (struct ext2_super_block *) sb;
618 } else {
619 memcpy(sb+1024, &fs->sb, 1024);
620 sb_for_io = (struct ext2_super_block *) (sb + 1024);
621 }
622
623 num = copies & EXT2_META_BACKUP ? fs->numgroups : 1;
624
625 for (i = 0, sb_block = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); i < num;
626 i++, sb_block += EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb))
627 {
628
629 if (!ext2_is_group_sparse(fs, i))
630 continue;
631
632 if (fs->dynamic_version)
633 sb_for_io->s_block_group_nr = PED_CPU_TO_LE16 (i);
634
635 if ((i == 0 && wmeta & EXT2_META_PRIMARY_SB) ||
636 (i != 0 && wmeta & EXT2_META_SB))
637 {
638 if (!ext2_bcache_flush_range(fs, sb_block, 1))
639 return 0;
640 if (!ext2_write_blocks(fs, sb, sb_block, 1))
641 return 0;
642 }
643 if ((i == 0 && wmeta & EXT2_META_PRIMARY_GD) ||
644 (i != 0 && wmeta & EXT2_META_GD))
645 {
646 if (!ext2_bcache_flush_range(fs, sb_block + 1,
647 fs->gdblocks))
648 return 0;
649 if (!ext2_write_blocks(fs, fs->gd, sb_block + 1,
650 fs->gdblocks))
651 return 0;
652 }
653 }
654
655 sb_for_io->s_block_group_nr = 0;
656
657 /* Clear the flags of the components we just finished writing. */
658 fs->metadirty &= ~copies;
659
660 return 1;
661 }
662
663 int ext2_sync(struct ext2_fs *fs)
664 {
665 if (!ext2_commit_metadata(fs, EXT2_META_PRIMARY)) return 0;
666 if (!ext2_bcache_sync(fs)) return 0;
667 if (!fs->devhandle->ops->sync(fs->devhandle->cookie)) return 0;
668 return 1;
669 }
670
671 struct ext2_fs *ext2_open(struct ext2_dev_handle *handle, int state)
672 {
673 struct ext2_fs *fs;
674
675 if ((fs = (struct ext2_fs *) ped_malloc(sizeof(struct ext2_fs)))
676 == NULL)
677 goto error;
678
679 handle->ops->set_blocksize(handle->cookie, 10);
680
681 if (!handle->ops->read(handle->cookie, &fs->sb, 1, 1)
682 || EXT2_SUPER_MAGIC(fs->sb) != EXT2_SUPER_MAGIC_CONST)
683 {
684 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
685 _("Invalid superblock. Are you sure this is an ext2 "
686 "file system?"));
687 goto error_free_fs;
688 }
689
690
691 fs->opt_debug = 1;
692 fs->opt_safe = 1;
693 fs->opt_verbose = 0;
694
695 if (EXT2_SUPER_STATE(fs->sb) & EXT2_ERROR_FS & ~(state & EXT2_ERROR_FS))
696 {
697 if (ped_exception_throw (
698 PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE_CANCEL,
699 _("File system has errors! You should run e2fsck."))
700 == PED_EXCEPTION_CANCEL)
701 goto error_free_fs;
702 }
703
704 if (!((EXT2_SUPER_STATE(fs->sb) | state) & EXT2_VALID_FS)
705 || (EXT2_SUPER_FEATURE_INCOMPAT(fs->sb)
706 & EXT3_FEATURE_INCOMPAT_RECOVER))
707 {
708 if (ped_exception_throw (
709 PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
710 _("File system was not cleanly unmounted! "
711 "You should run e2fsck. Modifying an unclean "
712 "file system could cause severe corruption."))
713 != PED_EXCEPTION_IGNORE)
714 goto error_free_fs;
715 }
716
717 fs->dynamic_version = EXT2_SUPER_REV_LEVEL (fs->sb) > 0;
718
719 if ((EXT2_SUPER_FEATURE_COMPAT(fs->sb)
720 & ~(EXT3_FEATURE_COMPAT_HAS_JOURNAL |
721 EXT2_FEATURE_COMPAT_HAS_DIR_INDEX)) ||
722 (EXT2_SUPER_FEATURE_INCOMPAT(fs->sb)
723 & ~(EXT2_FEATURE_INCOMPAT_FILETYPE |
724 EXT3_FEATURE_INCOMPAT_RECOVER)) ||
725 (EXT2_SUPER_FEATURE_RO_COMPAT(fs->sb)
726 & ~(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER |
727 EXT2_FEATURE_RO_COMPAT_LARGE_FILE)))
728 {
729 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
730 _("File system has an incompatible feature enabled."));
731 goto error_free_fs;
732 }
733
734 fs->devhandle = handle;
735 fs->logsize = EXT2_SUPER_LOG_BLOCK_SIZE(fs->sb) + 10;
736 handle->ops->set_blocksize(handle->cookie, fs->logsize);
737
738 if (!ext2_bcache_init(fs))
739 {
740 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
741 _("Error allocating buffer cache."));
742 goto error_free_fs;
743 }
744
745 fs->blocksize = 1 << fs->logsize;
746
747 fs->numgroups = ped_div_round_up (EXT2_SUPER_BLOCKS_COUNT(fs->sb)
748 - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb),
749 EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb));
750 fs->gdblocks = ped_div_round_up (fs->numgroups
751 * sizeof(struct ext2_group_desc),
752 fs->blocksize);
753 fs->inodeblocks = ped_div_round_up (EXT2_SUPER_INODES_PER_GROUP(fs->sb)
754 * sizeof(struct ext2_inode),
755 fs->blocksize);
756 fs->r_frac = ped_div_round_up (100 * (loff_t)EXT2_SUPER_R_BLOCKS_COUNT(fs->sb),
757 EXT2_SUPER_BLOCKS_COUNT(fs->sb));
758 fs->adminblocks = 3 + fs->gdblocks + fs->inodeblocks;
759
760 fs->sparse = 0;
761 if (EXT2_SUPER_FEATURE_RO_COMPAT(fs->sb)
762 & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)
763 fs->sparse = 1;
764
765 fs->has_journal = 0 < (EXT2_SUPER_FEATURE_COMPAT(fs->sb)
766 & EXT3_FEATURE_COMPAT_HAS_JOURNAL);
767 fs->has_internal_journal
768 = fs->has_journal
769 && uuid_is_null(EXT2_SUPER_JOURNAL_UUID(fs->sb))
770 && EXT2_SUPER_JOURNAL_INUM(fs->sb);
771
772 fs->gd = ped_malloc (fs->numgroups * sizeof (struct ext2_group_desc)
773 + fs->blocksize);
774 if (!fs->gd)
775 goto error_deinit_bcache;
776
777 ext2_read_blocks(fs, fs->gd, EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) + 1,
778 fs->gdblocks);
779
780 fs->metadirty = 0;
781 return fs;
782
783 ped_free(fs->gd);
784 error_deinit_bcache:
785 ext2_bcache_deinit(fs);
786 error_free_fs:
787 ped_free(fs);
788 error:
789 return NULL;
790 }
791
792 #endif /* !DISCOVER_ONLY */