1 /* ext2.c - Second Extended filesystem */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2003,2004,2005,2007,2008 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 /* Magic value used to identify an ext2 filesystem. */
21 #define EXT2_MAGIC 0xEF53
22 /* Amount of indirect blocks in an inode. */
23 #define INDIRECT_BLOCKS 12
24 /* Maximum length of a pathname. */
25 #define EXT2_PATH_MAX 4096
26 /* Maximum nesting of symlinks, used to prevent a loop. */
27 #define EXT2_MAX_SYMLINKCNT 8
29 /* The good old revision and the default inode size. */
30 #define EXT2_GOOD_OLD_REVISION 0
31 #define EXT2_GOOD_OLD_INODE_SIZE 128
33 /* Filetype used in directory entry. */
34 #define FILETYPE_UNKNOWN 0
35 #define FILETYPE_REG 1
36 #define FILETYPE_DIRECTORY 2
37 #define FILETYPE_SYMLINK 7
39 /* Filetype information as used in inodes. */
40 #define FILETYPE_INO_MASK 0170000
41 #define FILETYPE_INO_REG 0100000
42 #define FILETYPE_INO_DIRECTORY 0040000
43 #define FILETYPE_INO_SYMLINK 0120000
46 #include <grub/file.h>
48 #include <grub/misc.h>
49 #include <grub/disk.h>
51 #include <grub/types.h>
52 #include <grub/fshelp.h>
54 /* Log2 size of ext2 block in 512 blocks. */
55 #define LOG2_EXT2_BLOCK_SIZE(data) \
56 (grub_le_to_cpu32 (data->sblock.log2_block_size) + 1)
58 /* Log2 size of ext2 block in bytes. */
59 #define LOG2_BLOCK_SIZE(data) \
60 (grub_le_to_cpu32 (data->sblock.log2_block_size) + 10)
62 /* The size of an ext2 block in bytes. */
63 #define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE (data))
65 /* The revision level. */
66 #define EXT2_REVISION(data) grub_le_to_cpu32 (data->sblock.revision_level)
69 #define EXT2_INODE_SIZE(data) \
70 (EXT2_REVISION (data) == EXT2_GOOD_OLD_REVISION \
71 ? EXT2_GOOD_OLD_INODE_SIZE \
72 : grub_le_to_cpu16 (data->sblock.inode_size))
74 #define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
76 #define EXT3_JOURNAL_MAGIC_NUMBER 0xc03b3998U
78 #define EXT3_JOURNAL_DESCRIPTOR_BLOCK 1
79 #define EXT3_JOURNAL_COMMIT_BLOCK 2
80 #define EXT3_JOURNAL_SUPERBLOCK_V1 3
81 #define EXT3_JOURNAL_SUPERBLOCK_V2 4
82 #define EXT3_JOURNAL_REVOKE_BLOCK 5
84 #define EXT3_JOURNAL_FLAG_ESCAPE 1
85 #define EXT3_JOURNAL_FLAG_SAME_UUID 2
86 #define EXT3_JOURNAL_FLAG_DELETED 4
87 #define EXT3_JOURNAL_FLAG_LAST_TAG 8
89 /* The ext2 superblock. */
90 struct grub_ext2_sblock
92 grub_uint32_t total_inodes
;
93 grub_uint32_t total_blocks
;
94 grub_uint32_t reserved_blocks
;
95 grub_uint32_t free_blocks
;
96 grub_uint32_t free_inodes
;
97 grub_uint32_t first_data_block
;
98 grub_uint32_t log2_block_size
;
99 grub_uint32_t log2_fragment_size
;
100 grub_uint32_t blocks_per_group
;
101 grub_uint32_t fragments_per_group
;
102 grub_uint32_t inodes_per_group
;
105 grub_uint16_t mnt_count
;
106 grub_uint16_t max_mnt_count
;
108 grub_uint16_t fs_state
;
109 grub_uint16_t error_handling
;
110 grub_uint16_t minor_revision_level
;
111 grub_uint32_t lastcheck
;
112 grub_uint32_t checkinterval
;
113 grub_uint32_t creator_os
;
114 grub_uint32_t revision_level
;
115 grub_uint16_t uid_reserved
;
116 grub_uint16_t gid_reserved
;
117 grub_uint32_t first_inode
;
118 grub_uint16_t inode_size
;
119 grub_uint16_t block_group_number
;
120 grub_uint32_t feature_compatibility
;
121 grub_uint32_t feature_incompat
;
122 grub_uint32_t feature_ro_compat
;
123 grub_uint16_t uuid
[8];
124 char volume_name
[16];
125 char last_mounted_on
[64];
126 grub_uint32_t compression_info
;
127 grub_uint8_t prealloc_blocks
;
128 grub_uint8_t prealloc_dir_blocks
;
129 grub_uint16_t reserved_gdt_blocks
;
130 grub_uint8_t journal_uuid
[16];
131 grub_uint32_t journal_inum
;
132 grub_uint32_t journal_dev
;
133 grub_uint32_t last_orphan
;
134 grub_uint32_t hash_seed
[4];
135 grub_uint8_t def_hash_version
;
136 grub_uint8_t jnl_backup_type
;
137 grub_uint16_t reserved_word_pad
;
138 grub_uint32_t default_mount_opts
;
139 grub_uint32_t first_meta_bg
;
140 grub_uint32_t mkfs_time
;
141 grub_uint32_t jnl_blocks
[17];
144 /* The ext2 blockgroup. */
145 struct grub_ext2_block_group
147 grub_uint32_t block_id
;
148 grub_uint32_t inode_id
;
149 grub_uint32_t inode_table_id
;
150 grub_uint16_t free_blocks
;
151 grub_uint16_t free_inodes
;
152 grub_uint16_t used_dirs
;
154 grub_uint32_t reserved
[3];
157 /* The ext2 inode. */
158 struct grub_ext2_inode
168 grub_uint16_t nlinks
;
169 grub_uint32_t blockcnt
; /* Blocks of 512 bytes!! */
176 grub_uint32_t dir_blocks
[INDIRECT_BLOCKS
];
177 grub_uint32_t indir_block
;
178 grub_uint32_t double_indir_block
;
179 grub_uint32_t triple_indir_block
;
183 grub_uint32_t version
;
185 grub_uint32_t dir_acl
;
186 grub_uint32_t fragment_addr
;
187 grub_uint32_t osd2
[3];
190 /* The header of an ext2 directory entry. */
194 grub_uint16_t direntlen
;
195 grub_uint8_t namelen
;
196 grub_uint8_t filetype
;
199 struct grub_ext3_journal_header
202 grub_uint32_t block_type
;
203 grub_uint32_t sequence
;
206 struct grub_ext3_journal_revoke_header
208 struct grub_ext3_journal_header header
;
210 grub_uint32_t data
[0];
213 struct grub_ext3_journal_block_tag
219 struct grub_ext3_journal_sblock
221 struct grub_ext3_journal_header header
;
222 grub_uint32_t block_size
;
223 grub_uint32_t maxlen
;
225 grub_uint32_t sequence
;
229 struct grub_fshelp_node
231 struct grub_ext2_data
*data
;
232 struct grub_ext2_inode inode
;
237 /* Information about a "mounted" ext2 filesystem. */
238 struct grub_ext2_data
240 struct grub_ext2_sblock sblock
;
242 struct grub_ext2_inode
*inode
;
243 struct grub_fshelp_node diropen
;
244 struct grub_fshelp_node logfile
;
245 grub_fshelp_journal_t journal
;
249 static grub_dl_t my_mod
;
254 /* Read into BLKGRP the blockgroup descriptor of blockgroup GROUP of
255 the mounted filesystem DATA. */
256 inline static grub_err_t
257 grub_ext2_blockgroup (struct grub_ext2_data
*data
, int group
,
258 struct grub_ext2_block_group
*blkgrp
)
260 return grub_fshelp_read (data
->disk
, data
->journal
,
261 grub_le_to_cpu32 (data
->sblock
.first_data_block
) + 1,
262 group
* sizeof (struct grub_ext2_block_group
),
263 sizeof (struct grub_ext2_block_group
),
264 (char *) blkgrp
, LOG2_EXT2_BLOCK_SIZE (data
));
268 static grub_disk_addr_t
269 grub_ext2_read_block (grub_fshelp_node_t node
, grub_disk_addr_t fileblock
)
271 struct grub_ext2_data
*data
= node
->data
;
272 struct grub_ext2_inode
*inode
= &node
->inode
;
274 unsigned int blksz
= EXT2_BLOCK_SIZE (data
);
275 int log2_blksz
= LOG2_EXT2_BLOCK_SIZE (data
);
278 if (fileblock
< INDIRECT_BLOCKS
)
279 blknr
= grub_le_to_cpu32 (inode
->blocks
.dir_blocks
[fileblock
]);
281 else if (fileblock
< INDIRECT_BLOCKS
+ blksz
/ 4)
283 grub_uint32_t indir
[blksz
/ 4];
285 if (grub_fshelp_read (data
->disk
, data
->journal
,
286 grub_le_to_cpu32 (inode
->blocks
.indir_block
),
287 0, blksz
, (char *) indir
, log2_blksz
))
290 blknr
= grub_le_to_cpu32 (indir
[fileblock
- INDIRECT_BLOCKS
]);
292 /* Double indirect. */
293 else if (fileblock
< INDIRECT_BLOCKS
+ blksz
/ 4 * (blksz
/ 4 + 1))
295 unsigned int perblock
= blksz
/ 4;
296 unsigned int rblock
= fileblock
- (INDIRECT_BLOCKS
298 grub_uint32_t indir
[blksz
/ 4];
300 if (grub_fshelp_read (data
->disk
, data
->journal
,
301 grub_le_to_cpu32 (inode
->blocks
.double_indir_block
),
302 0, blksz
, (char *) indir
, log2_blksz
))
305 if (grub_fshelp_read (data
->disk
, data
->journal
,
306 grub_le_to_cpu32 (indir
[rblock
/ perblock
]),
307 0, blksz
, (char *) indir
, log2_blksz
))
311 blknr
= grub_le_to_cpu32 (indir
[rblock
% perblock
]);
313 /* triple indirect. */
316 grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET
,
317 "ext2fs doesn't support triple indirect blocks");
321 return grub_fshelp_map_block (data
->journal
, blknr
);
324 /* Read LEN bytes from the file described by DATA starting with byte
325 POS. Return the amount of read bytes in READ. */
327 grub_ext2_read_file (grub_fshelp_node_t node
,
328 void NESTED_FUNC_ATTR (*read_hook
) (grub_disk_addr_t sector
,
329 unsigned offset
, unsigned length
),
330 int pos
, grub_size_t len
, char *buf
)
332 return grub_fshelp_read_file (node
->data
->disk
, node
, read_hook
,
333 pos
, len
, buf
, grub_ext2_read_block
,
335 LOG2_EXT2_BLOCK_SIZE (node
->data
));
340 /* Read the inode INO for the file described by DATA into INODE. */
342 grub_ext2_read_inode (struct grub_ext2_data
*data
,
343 int ino
, struct grub_ext2_inode
*inode
)
345 struct grub_ext2_block_group blkgrp
;
346 struct grub_ext2_sblock
*sblock
= &data
->sblock
;
347 int inodes_per_block
;
352 /* It is easier to calculate if the first inode is 0. */
355 grub_ext2_blockgroup (data
,
356 ino
/ grub_le_to_cpu32 (sblock
->inodes_per_group
),
361 inodes_per_block
= EXT2_BLOCK_SIZE (data
) / EXT2_INODE_SIZE (data
);
362 blkno
= (ino
% grub_le_to_cpu32 (sblock
->inodes_per_group
))
364 blkoff
= (ino
% grub_le_to_cpu32 (sblock
->inodes_per_group
))
367 /* Read the inode. */
368 if (grub_fshelp_read (data
->disk
, data
->journal
,
369 grub_le_to_cpu32 (blkgrp
.inode_table_id
) + blkno
,
370 EXT2_INODE_SIZE (data
) * blkoff
,
371 sizeof (struct grub_ext2_inode
), (char *) inode
,
372 LOG2_EXT2_BLOCK_SIZE (data
)))
379 grub_ext3_get_journal (struct grub_ext2_data
*data
)
381 char buf
[1 << LOG2_BLOCK_SIZE (data
)];
382 struct grub_ext3_journal_sblock
*jsb
;
383 grub_fshelp_journal_t log
;
384 int last_num
, num
, block
, log2bs
;
387 auto void next_block (void);
388 void next_block (void)
391 if (block
>= log
->last_block
)
392 block
= log
->first_block
;
397 if (! (data
->sblock
.feature_compatibility
& EXT3_FEATURE_COMPAT_HAS_JOURNAL
))
400 if (! data
->sblock
.journal_inum
)
403 data
->logfile
.data
= data
;
404 data
->logfile
.ino
= data
->sblock
.journal_inum
;
405 data
->logfile
.inode_read
= 1;
407 if (grub_ext2_read_inode (data
, data
->logfile
.ino
, &data
->logfile
.inode
))
410 log2bs
= LOG2_EXT2_BLOCK_SIZE (data
);
411 if (grub_fshelp_read_file (data
->disk
, &data
->logfile
, 0,
412 0, sizeof (struct grub_ext3_journal_sblock
),
413 buf
, grub_ext2_read_block
,
414 sizeof (buf
), log2bs
) !=
415 sizeof (struct grub_ext3_journal_sblock
))
418 jsb
= (struct grub_ext3_journal_sblock
*) &buf
[0];
419 if (grub_be_to_cpu32 (jsb
->header
.magic
) != EXT3_JOURNAL_MAGIC_NUMBER
)
426 log
= grub_malloc (sizeof (struct grub_fshelp_journal
) +
427 grub_be_to_cpu32 (jsb
->maxlen
) * sizeof (grub_disk_addr_t
));
431 log
->type
= GRUB_FSHELP_JOURNAL_TYPE_FILE
;
432 log
->node
= &data
->logfile
;
433 log
->get_block
= grub_ext2_read_block
;
434 log
->first_block
= grub_be_to_cpu32 (jsb
->first
);
435 log
->last_block
= grub_be_to_cpu32 (jsb
->maxlen
);
436 log
->start_block
= grub_be_to_cpu32 (jsb
->start
);
439 block
= log
->start_block
;
440 seq
= grub_be_to_cpu32 (jsb
->sequence
);
444 struct grub_ext3_journal_header
*jh
;
446 if (grub_fshelp_read_file (data
->disk
, &data
->logfile
, 0,
447 block
<< (log2bs
+ 9), sizeof (buf
),
448 buf
, grub_ext2_read_block
,
449 log
->last_block
<< (log2bs
+ 9),
454 jh
= (struct grub_ext3_journal_header
*) &buf
[0];
455 if (grub_be_to_cpu32 (jh
->magic
) != EXT3_JOURNAL_MAGIC_NUMBER
)
458 if (grub_be_to_cpu32 (jh
->sequence
) != seq
)
461 log
->mapping
[num
++] = GRUB_FSHELP_JOURNAL_UNUSED_MAPPING
;
464 switch (grub_be_to_cpu32 (jh
->block_type
))
466 case EXT3_JOURNAL_DESCRIPTOR_BLOCK
:
468 struct grub_ext3_journal_block_tag
*tag
;
471 ofs
= sizeof (struct grub_ext3_journal_header
);
475 tag
= (struct grub_ext3_journal_block_tag
*) &buf
[ofs
];
476 ofs
+= sizeof (struct grub_ext3_journal_block_tag
);
478 if (ofs
> (int) sizeof (buf
))
481 flags
= grub_be_to_cpu32 (tag
->flags
);
482 if (! (flags
& EXT3_JOURNAL_FLAG_SAME_UUID
))
485 log
->mapping
[num
++] = grub_be_to_cpu32 (tag
->block
);
488 while (! (flags
& EXT3_JOURNAL_FLAG_LAST_TAG
));
493 case EXT3_JOURNAL_COMMIT_BLOCK
:
500 case EXT3_JOURNAL_REVOKE_BLOCK
:
502 struct grub_ext3_journal_revoke_header
*jrh
;
505 jrh
= (struct grub_ext3_journal_revoke_header
*) jh
;
507 for (i
= 0; i
< grub_be_to_cpu32 (jrh
->count
); i
++)
512 map
= grub_be_to_cpu32 (jrh
->data
[i
]);
513 for (j
= 0; j
< num
; j
++)
514 if (log
->mapping
[j
] == map
)
515 log
->mapping
[j
] = GRUB_FSHELP_JOURNAL_UNUSED_MAPPING
;
533 size
= sizeof (struct grub_fshelp_journal
) +
534 last_num
* sizeof (grub_disk_addr_t
);
536 log
->num_mappings
= last_num
;
537 data
->journal
= grub_realloc (log
, size
);
541 static struct grub_ext2_data
*
542 grub_ext2_mount (grub_disk_t disk
)
544 struct grub_ext2_data
*data
;
546 data
= grub_malloc (sizeof (struct grub_ext2_data
));
550 /* Read the superblock. */
551 grub_disk_read (disk
, 1 * 2, 0, sizeof (struct grub_ext2_sblock
),
552 (char *) &data
->sblock
);
556 /* Make sure this is an ext2 filesystem. */
557 if (grub_le_to_cpu16 (data
->sblock
.magic
) != EXT2_MAGIC
)
561 grub_ext3_get_journal (data
);
563 data
->diropen
.data
= data
;
564 data
->diropen
.ino
= 2;
565 data
->diropen
.inode_read
= 1;
567 data
->inode
= &data
->diropen
.inode
;
569 grub_ext2_read_inode (data
, 2, data
->inode
);
576 grub_error (GRUB_ERR_BAD_FS
, "not an ext2 filesystem");
582 grub_ext2_read_symlink (grub_fshelp_node_t node
)
585 struct grub_fshelp_node
*diro
= node
;
587 if (! diro
->inode_read
)
589 grub_ext2_read_inode (diro
->data
, diro
->ino
, &diro
->inode
);
594 symlink
= grub_malloc (grub_le_to_cpu32 (diro
->inode
.size
) + 1);
598 /* If the filesize of the symlink is bigger than
599 60 the symlink is stored in a separate block,
600 otherwise it is stored in the inode. */
601 if (grub_le_to_cpu32 (diro
->inode
.size
) <= 60)
602 grub_strncpy (symlink
,
604 grub_le_to_cpu32 (diro
->inode
.size
));
607 grub_ext2_read_file (diro
, 0, 0,
608 grub_le_to_cpu32 (diro
->inode
.size
),
617 symlink
[grub_le_to_cpu32 (diro
->inode
.size
)] = '\0';
622 grub_ext2_iterate_dir (grub_fshelp_node_t dir
,
624 (*hook
) (const char *filename
,
625 enum grub_fshelp_filetype filetype
,
626 grub_fshelp_node_t node
))
628 unsigned int fpos
= 0;
629 struct grub_fshelp_node
*diro
= (struct grub_fshelp_node
*) dir
;
631 if (! diro
->inode_read
)
633 grub_ext2_read_inode (diro
->data
, diro
->ino
, &diro
->inode
);
638 /* Search the file. */
639 while (fpos
< grub_le_to_cpu32 (diro
->inode
.size
))
641 struct ext2_dirent dirent
;
643 grub_ext2_read_file (diro
, 0, fpos
, sizeof (struct ext2_dirent
),
648 if (dirent
.namelen
!= 0)
650 char filename
[dirent
.namelen
+ 1];
651 struct grub_fshelp_node
*fdiro
;
652 enum grub_fshelp_filetype type
= GRUB_FSHELP_UNKNOWN
;
654 grub_ext2_read_file (diro
, 0, fpos
+ sizeof (struct ext2_dirent
),
655 dirent
.namelen
, filename
);
659 fdiro
= grub_malloc (sizeof (struct grub_fshelp_node
));
663 fdiro
->data
= diro
->data
;
664 fdiro
->ino
= grub_le_to_cpu32 (dirent
.inode
);
666 filename
[dirent
.namelen
] = '\0';
668 if (dirent
.filetype
!= FILETYPE_UNKNOWN
)
670 fdiro
->inode_read
= 0;
672 if (dirent
.filetype
== FILETYPE_DIRECTORY
)
673 type
= GRUB_FSHELP_DIR
;
674 else if (dirent
.filetype
== FILETYPE_SYMLINK
)
675 type
= GRUB_FSHELP_SYMLINK
;
676 else if (dirent
.filetype
== FILETYPE_REG
)
677 type
= GRUB_FSHELP_REG
;
681 /* The filetype can not be read from the dirent, read
682 the inode to get more information. */
683 grub_ext2_read_inode (diro
->data
,
684 grub_le_to_cpu32 (dirent
.inode
),
692 fdiro
->inode_read
= 1;
694 if ((grub_le_to_cpu16 (fdiro
->inode
.mode
)
695 & FILETYPE_INO_MASK
) == FILETYPE_INO_DIRECTORY
)
696 type
= GRUB_FSHELP_DIR
;
697 else if ((grub_le_to_cpu16 (fdiro
->inode
.mode
)
698 & FILETYPE_INO_MASK
) == FILETYPE_INO_SYMLINK
)
699 type
= GRUB_FSHELP_SYMLINK
;
700 else if ((grub_le_to_cpu16 (fdiro
->inode
.mode
)
701 & FILETYPE_INO_MASK
) == FILETYPE_INO_REG
)
702 type
= GRUB_FSHELP_REG
;
705 if (hook (filename
, type
, fdiro
))
709 fpos
+= grub_le_to_cpu16 (dirent
.direntlen
);
715 /* Open a file named NAME and initialize FILE. */
717 grub_ext2_open (struct grub_file
*file
, const char *name
)
719 struct grub_ext2_data
*data
;
720 struct grub_fshelp_node
*fdiro
= 0;
723 grub_dl_ref (my_mod
);
726 data
= grub_ext2_mount (file
->device
->disk
);
730 grub_fshelp_find_file (name
, &data
->diropen
, &fdiro
, grub_ext2_iterate_dir
,
731 grub_ext2_read_symlink
, GRUB_FSHELP_REG
);
735 if (! fdiro
->inode_read
)
737 grub_ext2_read_inode (data
, fdiro
->ino
, &fdiro
->inode
);
742 grub_memcpy (data
->inode
, &fdiro
->inode
, sizeof (struct grub_ext2_inode
));
745 file
->size
= grub_le_to_cpu32 (data
->inode
->size
);
752 if (fdiro
!= &data
->diropen
)
757 grub_dl_unref (my_mod
);
764 grub_ext2_close (grub_file_t file
)
768 grub_free (((struct grub_ext2_data
*) file
->data
)->journal
);
769 grub_free (file
->data
);
773 grub_dl_unref (my_mod
);
776 return GRUB_ERR_NONE
;
779 /* Read LEN bytes data from FILE into BUF. */
781 grub_ext2_read (grub_file_t file
, char *buf
, grub_size_t len
)
783 struct grub_ext2_data
*data
= (struct grub_ext2_data
*) file
->data
;
785 return grub_ext2_read_file (&data
->diropen
, file
->read_hook
,
786 file
->offset
, len
, buf
);
791 grub_ext2_dir (grub_device_t device
, const char *path
,
792 int (*hook
) (const char *filename
, int dir
))
794 struct grub_ext2_data
*data
= 0;;
795 struct grub_fshelp_node
*fdiro
= 0;
797 auto int NESTED_FUNC_ATTR
iterate (const char *filename
,
798 enum grub_fshelp_filetype filetype
,
799 grub_fshelp_node_t node
);
801 int NESTED_FUNC_ATTR
iterate (const char *filename
,
802 enum grub_fshelp_filetype filetype
,
803 grub_fshelp_node_t node
)
807 if (filetype
== GRUB_FSHELP_DIR
)
808 return hook (filename
, 1);
810 return hook (filename
, 0);
816 grub_dl_ref (my_mod
);
819 data
= grub_ext2_mount (device
->disk
);
823 grub_fshelp_find_file (path
, &data
->diropen
, &fdiro
, grub_ext2_iterate_dir
,
824 grub_ext2_read_symlink
, GRUB_FSHELP_DIR
);
828 grub_ext2_iterate_dir (fdiro
, iterate
);
831 if (fdiro
!= &data
->diropen
)
836 grub_dl_unref (my_mod
);
843 grub_ext2_label (grub_device_t device
, char **label
)
845 struct grub_ext2_data
*data
;
846 grub_disk_t disk
= device
->disk
;
849 grub_dl_ref (my_mod
);
852 data
= grub_ext2_mount (disk
);
854 *label
= grub_strndup (data
->sblock
.volume_name
, 14);
859 grub_dl_unref (my_mod
);
868 grub_ext2_uuid (grub_device_t device
, char **uuid
)
870 struct grub_ext2_data
*data
;
871 grub_disk_t disk
= device
->disk
;
874 grub_dl_ref (my_mod
);
877 data
= grub_ext2_mount (disk
);
880 *uuid
= grub_malloc (40 + sizeof ('\0'));
881 grub_sprintf (*uuid
, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
882 grub_be_to_cpu16 (data
->sblock
.uuid
[0]), grub_be_to_cpu16 (data
->sblock
.uuid
[1]),
883 grub_be_to_cpu16 (data
->sblock
.uuid
[2]), grub_be_to_cpu16 (data
->sblock
.uuid
[3]),
884 grub_be_to_cpu16 (data
->sblock
.uuid
[4]), grub_be_to_cpu16 (data
->sblock
.uuid
[5]),
885 grub_be_to_cpu16 (data
->sblock
.uuid
[6]), grub_be_to_cpu16 (data
->sblock
.uuid
[7]));
891 grub_dl_unref (my_mod
);
900 static struct grub_fs grub_ext2_fs
=
903 .dir
= grub_ext2_dir
,
904 .open
= grub_ext2_open
,
905 .read
= grub_ext2_read
,
906 .close
= grub_ext2_close
,
907 .label
= grub_ext2_label
,
908 .uuid
= grub_ext2_uuid
,
914 grub_fs_register (&grub_ext2_fs
);
922 grub_fs_unregister (&grub_ext2_fs
);