1 /* reiserfs.c - ReiserFS versions up to 3.6 */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2003,2004,2005,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/>.
22 implement journal handling (ram replay)
23 test tail packing & direct files
24 validate partition label position
28 # define GRUB_REISERFS_DEBUG
29 # define GRUB_REISERFS_JOURNALING
34 #include <grub/file.h>
36 #include <grub/misc.h>
37 #include <grub/disk.h>
39 #include <grub/types.h>
40 #include <grub/fshelp.h>
43 ({ typeof (a) _a = (a); \
44 typeof (b) _b = (b); \
48 ({ typeof (a) _a = (a); \
49 typeof (b) _b = (b); \
52 #define REISERFS_SUPER_BLOCK_OFFSET 0x10000
53 #define REISERFS_MAGIC_LEN 12
54 #define REISERFS_MAGIC_STRING "ReIsEr"
55 #define REISERFS_MAGIC_DESC_BLOCK "ReIsErLB"
56 /* If the 3rd bit of an item state is set, then it's visible. */
57 #define GRUB_REISERFS_VISIBLE_MASK ((grub_uint16_t) 0x04)
58 #define REISERFS_MAX_LABEL_LENGTH 16
59 #define REISERFS_LABEL_OFFSET 0x64
61 #define S_IFLNK 0xA000
64 static grub_dl_t my_mod
;
67 #define assert(boolean) real_assert (boolean, __FILE__, __LINE__)
69 real_assert (int boolean
, const char *file
, const int line
)
72 grub_printf ("Assertion failed at %s:%d\n", file
, line
);
75 enum grub_reiserfs_item_type
78 GRUB_REISERFS_DIRECTORY
,
80 GRUB_REISERFS_INDIRECT
,
81 /* Matches both _DIRECT and _INDIRECT when searching. */
86 struct grub_reiserfs_superblock
88 grub_uint32_t block_count
;
89 grub_uint32_t block_free_count
;
90 grub_uint32_t root_block
;
91 grub_uint32_t journal_block
;
92 grub_uint32_t journal_device
;
93 grub_uint32_t journal_original_size
;
94 grub_uint32_t journal_max_transaction_size
;
95 grub_uint32_t journal_block_count
;
96 grub_uint32_t journal_max_batch
;
97 grub_uint32_t journal_max_commit_age
;
98 grub_uint32_t journal_max_transaction_age
;
99 grub_uint16_t block_size
;
100 grub_uint16_t oid_max_size
;
101 grub_uint16_t oid_current_size
;
103 grub_uint8_t magic_string
[REISERFS_MAGIC_LEN
];
104 grub_uint32_t function_hash_code
;
105 grub_uint16_t tree_height
;
106 grub_uint16_t bitmap_number
;
107 grub_uint16_t version
;
108 grub_uint16_t reserved
;
109 grub_uint32_t inode_generation
;
110 grub_uint8_t unused
[4];
111 grub_uint16_t uuid
[8];
112 } __attribute__ ((packed
));
114 struct grub_reiserfs_journal_header
116 grub_uint32_t last_flush_uid
;
117 grub_uint32_t unflushed_offset
;
118 grub_uint32_t mount_id
;
119 } __attribute__ ((packed
));
121 struct grub_reiserfs_description_block
125 grub_uint32_t mount_id
;
126 grub_uint32_t real_blocks
[0];
127 } __attribute__ ((packed
));
129 struct grub_reiserfs_commit_block
133 grub_uint32_t real_blocks
[0];
134 } __attribute__ ((packed
));
136 struct grub_reiserfs_stat_item_v1
139 grub_uint16_t hardlink_count
;
147 grub_uint32_t first_direct_byte
;
148 } __attribute__ ((packed
));
150 struct grub_reiserfs_stat_item_v2
153 grub_uint16_t reserved
;
154 grub_uint32_t hardlink_count
;
161 grub_uint32_t blocks
;
162 grub_uint32_t first_direct_byte
;
163 } __attribute__ ((packed
));
165 struct grub_reiserfs_key
167 grub_uint32_t directory_id
;
168 grub_uint32_t object_id
;
173 grub_uint32_t offset
;
175 } v1
__attribute__ ((packed
));
178 grub_uint64_t offset_type
;
179 } v2
__attribute__ ((packed
));
181 } __attribute__ ((packed
));
183 struct grub_reiserfs_item_header
185 struct grub_reiserfs_key key
;
188 grub_uint16_t free_space
;
189 grub_uint16_t entry_count
;
190 } u
__attribute__ ((packed
));
191 grub_uint16_t item_size
;
192 grub_uint16_t item_location
;
193 grub_uint16_t version
;
194 } __attribute__ ((packed
));
196 struct grub_reiserfs_block_header
199 grub_uint16_t item_count
;
200 grub_uint16_t free_space
;
201 grub_uint16_t reserved
;
202 struct grub_reiserfs_key block_right_delimiting_key
;
203 } __attribute__ ((packed
));
205 struct grub_reiserfs_disk_child
207 grub_uint32_t block_number
;
209 grub_uint16_t reserved
;
210 } __attribute__ ((packed
));
212 struct grub_reiserfs_directory_header
214 grub_uint32_t offset
;
215 grub_uint32_t directory_id
;
216 grub_uint32_t object_id
;
217 grub_uint16_t location
;
219 } __attribute__ ((packed
));
221 struct grub_fshelp_node
223 struct grub_reiserfs_data
*data
;
224 grub_uint32_t block_number
; /* 0 if node is not found. */
225 grub_uint16_t block_position
;
226 grub_uint64_t next_offset
;
227 enum grub_reiserfs_item_type type
; /* To know how to read the header. */
228 struct grub_reiserfs_item_header header
;
231 /* Returned when opening a file. */
232 struct grub_reiserfs_data
234 struct grub_reiserfs_superblock superblock
;
238 /* Internal-only functions. Not to be used outside of this file. */
240 /* Return the type of given v2 key. */
241 static enum grub_reiserfs_item_type
242 grub_reiserfs_get_key_v2_type (const struct grub_reiserfs_key
*key
)
244 switch (grub_le_to_cpu64 (key
->u
.v2
.offset_type
) >> 60)
247 return GRUB_REISERFS_STAT
;
249 return GRUB_REISERFS_ANY
;
251 return GRUB_REISERFS_DIRECTORY
;
253 return GRUB_REISERFS_DIRECT
;
255 return GRUB_REISERFS_INDIRECT
;
257 return GRUB_REISERFS_UNKNOWN
;
260 /* Return the type of given v1 key. */
261 static enum grub_reiserfs_item_type
262 grub_reiserfs_get_key_v1_type (const struct grub_reiserfs_key
*key
)
264 switch (grub_le_to_cpu32 (key
->u
.v1
.type
))
267 return GRUB_REISERFS_STAT
;
269 return GRUB_REISERFS_ANY
;
271 return GRUB_REISERFS_DIRECTORY
;
274 return GRUB_REISERFS_DIRECT
;
277 return GRUB_REISERFS_INDIRECT
;
279 return GRUB_REISERFS_UNKNOWN
;
282 /* Return 1 if the given key is version 1 key, 2 otherwise. */
284 grub_reiserfs_get_key_version (const struct grub_reiserfs_key
*key
)
286 return grub_reiserfs_get_key_v1_type (key
) == GRUB_REISERFS_UNKNOWN
? 2 : 1;
291 grub_hexdump (char *buffer
, grub_size_t len
)
294 for (a
= 0; a
< len
; a
++)
297 grub_printf ("\n%08x ", a
);
298 grub_printf ("%02x ",
299 ((unsigned int) ((unsigned char *) buffer
)[a
]) & 0xFF);
305 #ifdef GRUB_REISERFS_DEBUG
307 grub_reiserfs_get_key_offset (const struct grub_reiserfs_key
*key
);
309 static enum grub_reiserfs_item_type
310 grub_reiserfs_get_key_type (const struct grub_reiserfs_key
*key
);
313 grub_reiserfs_print_key (const struct grub_reiserfs_key
*key
)
316 char *reiserfs_type_strings
[] = {
325 for (a
= 0; a
< sizeof (struct grub_reiserfs_key
); a
++)
326 grub_printf ("%02x ", ((unsigned int) ((unsigned char *) key
)[a
]) & 0xFF);
327 grub_printf ("parent id = 0x%08x, self id = 0x%08x, type = %s, offset = ",
328 grub_le_to_cpu32 (key
->directory_id
),
329 grub_le_to_cpu32 (key
->object_id
),
330 reiserfs_type_strings
[grub_reiserfs_get_key_type (key
)]);
331 if (grub_reiserfs_get_key_version (key
) == 1)
332 grub_printf("%08x", (unsigned int) grub_reiserfs_get_key_offset (key
));
334 grub_printf("0x%07x%08x",
335 (unsigned) (grub_reiserfs_get_key_offset (key
) >> 32),
336 (unsigned) (grub_reiserfs_get_key_offset (key
) & 0xFFFFFFFF));
341 /* Return the offset of given key. */
343 grub_reiserfs_get_key_offset (const struct grub_reiserfs_key
*key
)
345 if (grub_reiserfs_get_key_version (key
) == 1)
346 return grub_le_to_cpu32 (key
->u
.v1
.offset
);
348 return grub_le_to_cpu64 (key
->u
.v2
.offset_type
) & (~0ULL >> 4);
351 /* Set the offset of given key. */
353 grub_reiserfs_set_key_offset (struct grub_reiserfs_key
*key
,
356 if (grub_reiserfs_get_key_version (key
) == 1)
357 key
->u
.v1
.offset
= grub_cpu_to_le32 (value
);
359 key
->u
.v2
.offset_type \
360 = ((key
->u
.v2
.offset_type
& grub_cpu_to_le64 (15ULL << 60))
361 | grub_cpu_to_le64 (value
& (~0ULL >> 4)));
364 /* Return the type of given key. */
365 static enum grub_reiserfs_item_type
366 grub_reiserfs_get_key_type (const struct grub_reiserfs_key
*key
)
368 if (grub_reiserfs_get_key_version (key
) == 1)
369 return grub_reiserfs_get_key_v1_type (key
);
371 return grub_reiserfs_get_key_v2_type (key
);
374 /* Set the type of given key, with given version number. */
376 grub_reiserfs_set_key_type (struct grub_reiserfs_key
*key
,
377 enum grub_reiserfs_item_type grub_type
,
384 case GRUB_REISERFS_STAT
:
387 case GRUB_REISERFS_ANY
:
388 type
= (version
== 1) ? 555 : 15;
390 case GRUB_REISERFS_DIRECTORY
:
391 type
= (version
== 1) ? 500 : 3;
393 case GRUB_REISERFS_DIRECT
:
394 type
= (version
== 1) ? 0xFFFFFFFF : 2;
396 case GRUB_REISERFS_INDIRECT
:
397 type
= (version
== 1) ? 0xFFFFFFFE : 1;
404 key
->u
.v1
.type
= grub_cpu_to_le32 (type
);
406 key
->u
.v2
.offset_type
407 = ((key
->u
.v2
.offset_type
& grub_cpu_to_le64 (~0ULL >> 4))
408 | grub_cpu_to_le64 ((grub_uint64_t
) type
<< 60));
410 assert (grub_reiserfs_get_key_type (key
) == grub_type
);
413 /* -1 if key 1 if lower than key 2.
414 0 if key 1 is equal to key 2.
415 1 if key 1 is higher than key 2. */
417 grub_reiserfs_compare_keys (const struct grub_reiserfs_key
*key1
,
418 const struct grub_reiserfs_key
*key2
)
420 grub_uint64_t offset1
, offset2
;
421 enum grub_reiserfs_item_type type1
, type2
;
422 grub_uint32_t id1
, id2
;
424 if (! key1
|| ! key2
)
427 id1
= grub_le_to_cpu32 (key1
->directory_id
);
428 id2
= grub_le_to_cpu32 (key2
->directory_id
);
434 id1
= grub_le_to_cpu32 (key1
->object_id
);
435 id2
= grub_le_to_cpu32 (key2
->object_id
);
441 offset1
= grub_reiserfs_get_key_offset (key1
);
442 offset2
= grub_reiserfs_get_key_offset (key2
);
443 if (offset1
< offset2
)
445 if (offset1
> offset2
)
448 type1
= grub_reiserfs_get_key_type (key1
);
449 type2
= grub_reiserfs_get_key_type (key2
);
450 if ((type1
== GRUB_REISERFS_ANY
451 && (type2
== GRUB_REISERFS_DIRECT
452 || type2
== GRUB_REISERFS_INDIRECT
))
453 || (type2
== GRUB_REISERFS_ANY
454 && (type1
== GRUB_REISERFS_DIRECT
455 || type1
== GRUB_REISERFS_INDIRECT
)))
465 /* Find the item identified by KEY in mounted filesystem DATA, and fill ITEM
466 accordingly to what was found. */
468 grub_reiserfs_get_item (struct grub_reiserfs_data
*data
,
469 const struct grub_reiserfs_key
*key
,
470 struct grub_fshelp_node
*item
)
472 grub_uint32_t block_number
;
473 struct grub_reiserfs_block_header
*block_header
= 0;
474 struct grub_reiserfs_key
*block_key
= 0;
475 grub_uint16_t block_size
, item_count
, current_level
;
477 grub_uint16_t previous_level
= ~0;
478 struct grub_reiserfs_item_header
*item_headers
= 0;
482 grub_error (GRUB_ERR_TEST_FAILURE
, "data is NULL");
488 grub_error (GRUB_ERR_TEST_FAILURE
, "key is NULL");
494 grub_error (GRUB_ERR_TEST_FAILURE
, "item is NULL");
498 block_size
= grub_le_to_cpu16 (data
->superblock
.block_size
);
499 block_number
= grub_le_to_cpu32 (data
->superblock
.root_block
);
500 #ifdef GRUB_REISERFS_DEBUG
501 grub_printf("Searching for ");
502 grub_reiserfs_print_key (key
);
504 block_header
= grub_malloc (block_size
);
508 item
->next_offset
= 0;
511 grub_disk_read (data
->disk
,
512 block_number
* (block_size
>> GRUB_DISK_SECTOR_BITS
),
513 (((grub_off_t
) block_number
* block_size
)
514 & (GRUB_DISK_SECTOR_SIZE
- 1)),
515 block_size
, (char *) block_header
);
518 current_level
= grub_le_to_cpu16 (block_header
->level
);
519 grub_dprintf ("reiserfs_tree", " at level %d\n", current_level
);
520 if (current_level
>= previous_level
)
522 grub_dprintf ("reiserfs_tree", "level loop detected, aborting\n");
523 grub_error (GRUB_ERR_FILE_READ_ERROR
, "level loop");
526 previous_level
= current_level
;
527 item_count
= grub_le_to_cpu16 (block_header
->item_count
);
528 grub_dprintf ("reiserfs_tree", " number of contained items : %d\n",
530 if (current_level
> 1)
532 /* Internal node. Navigate to the child that should contain
534 struct grub_reiserfs_key
*keys
535 = (struct grub_reiserfs_key
*) (block_header
+ 1);
536 struct grub_reiserfs_disk_child
*children
537 = ((struct grub_reiserfs_disk_child
*)
538 (keys
+ item_count
));
542 && grub_reiserfs_compare_keys (key
, &(keys
[i
])) >= 0;
545 #ifdef GRUB_REISERFS_DEBUG
546 grub_printf("i %03d/%03d ", i
+ 1, item_count
+ 1);
547 grub_reiserfs_print_key (&(keys
[i
]));
550 block_number
= grub_le_to_cpu32 (children
[i
].block_number
);
551 if ((i
< item_count
) && (key
->directory_id
== keys
[i
].directory_id
)
552 && (key
->object_id
== keys
[i
].object_id
))
553 item
->next_offset
= grub_reiserfs_get_key_offset(&(keys
[i
]));
554 #ifdef GRUB_REISERFS_DEBUG
556 || grub_reiserfs_compare_keys (key
, &(keys
[i
])) == 0)
562 grub_printf (" %03d/%03d ", i
+ 1, item_count
+ 1);
563 grub_reiserfs_print_key (&(keys
[i
]));
564 if (i
+ 1 < item_count
)
566 grub_printf ("+ %03d/%03d ", i
+ 2, item_count
);
567 grub_reiserfs_print_key (&(keys
[i
+ 1]));
571 grub_printf ("Accessing rightmost child at block %d.\n",
577 /* Leaf node. Check that the key is actually present. */
579 = (struct grub_reiserfs_item_header
*) (block_header
+ 1);
582 && (grub_reiserfs_compare_keys (key
, &(item_headers
[i
].key
))
586 #ifdef GRUB_REISERFS_DEBUG
587 if (key
->directory_id
== item_headers
[i
].key
.directory_id
&& \
588 key
->object_id
== item_headers
[i
].key
.object_id
)
592 grub_printf(" %03d/%03d ", i
+ 1, item_count
);
593 grub_reiserfs_print_key (&(item_headers
[i
].key
));
597 block_key
= &(item_headers
[i
].key
);
600 while (current_level
> 1);
604 if (i
== item_count
|| grub_reiserfs_compare_keys (key
, block_key
))
606 item
->block_number
= 0;
607 item
->block_position
= 0;
608 item
->type
= GRUB_REISERFS_UNKNOWN
;
609 #ifdef GRUB_REISERFS_DEBUG
610 grub_printf("Not found.\n");
615 item
->block_number
= block_number
;
616 item
->block_position
= i
;
617 item
->type
= grub_reiserfs_get_key_type (block_key
);
618 grub_memcpy (&(item
->header
), &(item_headers
[i
]),
619 sizeof (struct grub_reiserfs_item_header
));
620 #ifdef GRUB_REISERFS_DEBUG
621 grub_printf ("F %03d/%03d ", i
+ 1, item_count
);
622 grub_reiserfs_print_key (block_key
);
626 assert (grub_errno
== GRUB_ERR_NONE
);
627 grub_free (block_header
);
628 return GRUB_ERR_NONE
;
631 assert (grub_errno
!= GRUB_ERR_NONE
);
632 grub_free (block_header
);
633 assert (grub_errno
!= GRUB_ERR_NONE
);
637 /* Return the path of the file which is pointed at by symlink NODE. */
639 grub_reiserfs_read_symlink (grub_fshelp_node_t node
)
641 char *symlink_buffer
= 0;
642 grub_uint16_t block_size
;
643 grub_disk_addr_t block
;
646 struct grub_fshelp_node found
;
647 struct grub_reiserfs_key key
;
649 grub_memcpy (&key
, &(node
->header
.key
), sizeof (key
));
650 grub_reiserfs_set_key_offset (&key
, 1);
651 grub_reiserfs_set_key_type (&key
, GRUB_REISERFS_DIRECT
,
652 grub_reiserfs_get_key_version (&key
));
654 if (grub_reiserfs_get_item (node
->data
, &key
, &found
) != GRUB_ERR_NONE
)
657 if (found
.block_number
== 0)
660 block_size
= grub_le_to_cpu16 (node
->data
->superblock
.block_size
);
661 len
= grub_le_to_cpu16 (found
.header
.item_size
);
662 block
= found
.block_number
* (block_size
>> GRUB_DISK_SECTOR_BITS
);
663 offset
= grub_le_to_cpu16 (found
.header
.item_location
);
665 symlink_buffer
= grub_malloc (len
+ 1);
666 if (! symlink_buffer
)
669 grub_disk_read (node
->data
->disk
, block
, offset
, len
, symlink_buffer
);
673 symlink_buffer
[len
] = 0;
674 return symlink_buffer
;
677 grub_free (symlink_buffer
);
681 /* Fill the mounted filesystem structure and return it. */
682 static struct grub_reiserfs_data
*
683 grub_reiserfs_mount (grub_disk_t disk
)
685 struct grub_reiserfs_data
*data
= 0;
686 data
= grub_malloc (sizeof (*data
));
689 grub_disk_read (disk
, REISERFS_SUPER_BLOCK_OFFSET
/ GRUB_DISK_SECTOR_SIZE
,
690 0, sizeof (data
->superblock
), (char *) &(data
->superblock
));
693 if (grub_memcmp (data
->superblock
.magic_string
,
694 REISERFS_MAGIC_STRING
, sizeof (REISERFS_MAGIC_STRING
) - 1))
696 grub_error (GRUB_ERR_BAD_FS
, "not a reiserfs filesystem");
703 /* Disk is too small to contain a ReiserFS. */
704 if (grub_errno
== GRUB_ERR_OUT_OF_RANGE
)
705 grub_error (GRUB_ERR_BAD_FS
, "not a reiserfs filesystem");
711 /* Call HOOK for each file in directory ITEM. */
713 grub_reiserfs_iterate_dir (grub_fshelp_node_t item
,
715 (*hook
) (const char *filename
,
716 enum grub_fshelp_filetype filetype
,
717 grub_fshelp_node_t node
))
719 struct grub_reiserfs_data
*data
= item
->data
;
720 struct grub_reiserfs_block_header
*block_header
= 0;
721 grub_uint16_t block_size
, block_position
;
722 grub_uint32_t block_number
;
723 grub_uint64_t next_offset
= item
->next_offset
;
726 if (item
->type
!= GRUB_REISERFS_DIRECTORY
)
728 grub_error (GRUB_ERR_BAD_FILE_TYPE
,
729 "grub_reiserfs_iterate_dir called on a non-directory item");
732 block_size
= grub_le_to_cpu16 (data
->superblock
.block_size
);
733 block_header
= grub_malloc (block_size
);
736 block_number
= item
->block_number
;
737 block_position
= item
->block_position
;
738 grub_dprintf ("reiserfs", "Iterating directory...\n");
741 struct grub_reiserfs_directory_header
*directory_headers
;
742 struct grub_fshelp_node directory_item
;
743 grub_uint16_t entry_count
, entry_number
;
744 struct grub_reiserfs_item_header
*item_headers
;
746 grub_disk_read (data
->disk
,
747 block_number
* (block_size
>> GRUB_DISK_SECTOR_BITS
),
748 (((grub_off_t
) block_number
* block_size
)
749 & (GRUB_DISK_SECTOR_SIZE
- 1)),
750 block_size
, (char *) block_header
);
755 if (grub_le_to_cpu16 (block_header
->level
) != 1)
757 grub_error (GRUB_ERR_TEST_FAILURE
,
758 "reiserfs: block %d is not a leaf block",
764 item_headers
= (struct grub_reiserfs_item_header
*) (block_header
+ 1);
766 = ((struct grub_reiserfs_directory_header
*)
767 ((char *) block_header
768 + grub_le_to_cpu16 (item_headers
[block_position
].item_location
)));
770 = grub_le_to_cpu16 (item_headers
[block_position
].u
.entry_count
);
771 for (entry_number
= 0; entry_number
< entry_count
; entry_number
++)
773 struct grub_reiserfs_directory_header
*directory_header
774 = &directory_headers
[entry_number
];
775 grub_uint16_t entry_state
776 = grub_le_to_cpu16 (directory_header
->state
);
778 if (entry_state
& GRUB_REISERFS_VISIBLE_MASK
)
780 grub_fshelp_node_t entry_item
;
781 struct grub_reiserfs_key entry_key
;
782 enum grub_reiserfs_item_type entry_type
;
785 entry_name
= (((char *) directory_headers
)
786 + grub_le_to_cpu16 (directory_header
->location
));
787 entry_key
.directory_id
= directory_header
->directory_id
;
788 entry_key
.object_id
= directory_header
->object_id
;
789 entry_key
.u
.v2
.offset_type
= 0;
790 grub_reiserfs_set_key_type (&entry_key
, GRUB_REISERFS_DIRECTORY
,
792 grub_reiserfs_set_key_offset (&entry_key
, 1);
794 entry_item
= grub_malloc (sizeof (*entry_item
));
798 if (grub_reiserfs_get_item (data
, &entry_key
, entry_item
)
801 grub_free (entry_item
);
805 if (entry_item
->type
== GRUB_REISERFS_DIRECTORY
)
806 entry_type
= GRUB_FSHELP_DIR
;
809 grub_uint32_t entry_block_number
;
810 /* Order is very important here.
811 First set the offset to 0 using current key version.
812 Then change the key type, which influes on key version
814 grub_reiserfs_set_key_offset (&entry_key
, 0);
815 grub_reiserfs_set_key_type (&entry_key
, GRUB_REISERFS_STAT
,
817 if (grub_reiserfs_get_item (data
, &entry_key
, entry_item
)
820 grub_free (entry_item
);
824 if (entry_item
->block_number
!= 0)
826 grub_uint16_t entry_version
;
828 = grub_le_to_cpu16 (entry_item
->header
.version
);
829 entry_block_number
= entry_item
->block_number
;
831 grub_dprintf ("reiserfs",
832 "version %04x block %08x (%08x) position %08x\n",
833 entry_version
, entry_block_number
,
834 ((grub_disk_addr_t
) entry_block_number
* block_size
) / GRUB_DISK_SECTOR_SIZE
,
835 grub_le_to_cpu16 (entry_item
->header
.item_location
));
837 if (entry_version
== 0) /* Version 1 stat item. */
839 struct grub_reiserfs_stat_item_v1 entry_v1_stat
;
840 grub_disk_read (data
->disk
,
841 entry_block_number
* (block_size
>> GRUB_DISK_SECTOR_BITS
),
842 grub_le_to_cpu16 (entry_item
->header
.item_location
),
843 sizeof (entry_v1_stat
),
844 (char *) &entry_v1_stat
);
848 grub_dprintf ("reiserfs",
849 "%04x %04x %04x %04x %08x %08x | %08x %08x %08x %08x\n",
850 grub_le_to_cpu16 (entry_v1_stat
.mode
),
851 grub_le_to_cpu16 (entry_v1_stat
.hardlink_count
),
852 grub_le_to_cpu16 (entry_v1_stat
.uid
),
853 grub_le_to_cpu16 (entry_v1_stat
.gid
),
854 grub_le_to_cpu32 (entry_v1_stat
.size
),
855 grub_le_to_cpu32 (entry_v1_stat
.atime
),
856 grub_le_to_cpu32 (entry_v1_stat
.mtime
),
857 grub_le_to_cpu32 (entry_v1_stat
.ctime
),
858 grub_le_to_cpu32 (entry_v1_stat
.rdev
),
859 grub_le_to_cpu32 (entry_v1_stat
.first_direct_byte
));
860 grub_dprintf ("reiserfs",
861 "%04x %04x %04x %04x %08x %08x | %08x %08x %08x %08x\n",
863 entry_v1_stat
.hardlink_count
,
871 entry_v1_stat
.first_direct_byte
);
873 if ((grub_le_to_cpu16 (entry_v1_stat
.mode
) & S_IFLNK
)
875 entry_type
= GRUB_FSHELP_SYMLINK
;
877 entry_type
= GRUB_FSHELP_REG
;
881 struct grub_reiserfs_stat_item_v2 entry_v2_stat
;
882 grub_disk_read (data
->disk
,
883 entry_block_number
* (block_size
>> GRUB_DISK_SECTOR_BITS
),
884 grub_le_to_cpu16 (entry_item
->header
.item_location
),
885 sizeof (entry_v2_stat
),
886 (char *) &entry_v2_stat
);
890 grub_dprintf ("reiserfs",
891 "%04x %04x %08x %08x%08x | %08x %08x %08x %08x | %08x %08x %08x\n",
892 grub_le_to_cpu16 (entry_v2_stat
.mode
),
893 grub_le_to_cpu16 (entry_v2_stat
.reserved
),
894 grub_le_to_cpu32 (entry_v2_stat
.hardlink_count
),
895 (unsigned int) (grub_le_to_cpu64 (entry_v2_stat
.size
) >> 32),
896 (unsigned int) (grub_le_to_cpu64 (entry_v2_stat
.size
) && 0xFFFFFFFF),
897 grub_le_to_cpu32 (entry_v2_stat
.uid
),
898 grub_le_to_cpu32 (entry_v2_stat
.gid
),
899 grub_le_to_cpu32 (entry_v2_stat
.atime
),
900 grub_le_to_cpu32 (entry_v2_stat
.mtime
),
901 grub_le_to_cpu32 (entry_v2_stat
.ctime
),
902 grub_le_to_cpu32 (entry_v2_stat
.blocks
),
903 grub_le_to_cpu32 (entry_v2_stat
.first_direct_byte
));
904 grub_dprintf ("reiserfs",
905 "%04x %04x %08x %08x%08x | %08x %08x %08x %08x | %08x %08x %08x\n",
907 entry_v2_stat
.reserved
,
908 entry_v2_stat
.hardlink_count
,
909 (unsigned int) (entry_v2_stat
.size
>> 32),
910 (unsigned int) (entry_v2_stat
.size
&& 0xFFFFFFFF),
916 entry_v2_stat
.blocks
,
917 entry_v2_stat
.first_direct_byte
);
919 if ((grub_le_to_cpu16 (entry_v2_stat
.mode
) & S_IFLNK
)
921 entry_type
= GRUB_FSHELP_SYMLINK
;
923 entry_type
= GRUB_FSHELP_REG
;
928 /* Pseudo file ".." never has stat block. */
929 if (grub_strcmp (entry_name
, ".."))
930 grub_dprintf ("reiserfs",
931 "Warning : %s has no stat block !\n",
933 grub_free (entry_item
);
937 if (hook (entry_name
, entry_type
, entry_item
))
939 grub_dprintf ("reiserfs", "Found : %s, type=%d\n",
940 entry_name
, entry_type
);
945 *entry_name
= 0; /* Make sure next entry name (which is just
946 before this one in disk order) stops before
951 if (next_offset
== 0)
954 grub_reiserfs_set_key_offset (&(item_headers
[block_position
].key
),
956 if (grub_reiserfs_get_item (data
, &(item_headers
[block_position
].key
),
957 &directory_item
) != GRUB_ERR_NONE
)
959 block_number
= directory_item
.block_number
;
960 block_position
= directory_item
.block_position
;
961 next_offset
= directory_item
.next_offset
;
963 while (block_number
);
966 assert (grub_errno
== GRUB_ERR_NONE
);
967 grub_free (block_header
);
970 assert (grub_errno
!= GRUB_ERR_NONE
);
971 grub_free (block_header
);
975 /****************************************************************************/
976 /* grub api functions */
977 /****************************************************************************/
979 /* Open a file named NAME and initialize FILE. */
981 grub_reiserfs_open (struct grub_file
*file
, const char *name
)
983 struct grub_reiserfs_data
*data
= 0;
984 struct grub_fshelp_node root
, *found
= 0, info
;
985 struct grub_reiserfs_key key
;
986 grub_uint32_t block_number
;
987 grub_uint16_t entry_version
, block_size
, entry_location
;
990 grub_dl_ref (my_mod
);
992 data
= grub_reiserfs_mount (file
->device
->disk
);
995 block_size
= grub_le_to_cpu16 (data
->superblock
.block_size
);
996 key
.directory_id
= grub_cpu_to_le32 (1);
997 key
.object_id
= grub_cpu_to_le32 (2);
998 key
.u
.v2
.offset_type
= 0;
999 grub_reiserfs_set_key_type (&key
, GRUB_REISERFS_DIRECTORY
, 2);
1000 grub_reiserfs_set_key_offset (&key
, 1);
1001 if (grub_reiserfs_get_item (data
, &key
, &root
) != GRUB_ERR_NONE
)
1003 if (root
.block_number
== 0)
1005 grub_error (GRUB_ERR_BAD_FS
, "Unable to find root item");
1006 goto fail
; /* Should never happen since checked at mount. */
1008 grub_fshelp_find_file (name
, &root
, &found
,
1009 grub_reiserfs_iterate_dir
,
1010 grub_reiserfs_read_symlink
, GRUB_FSHELP_REG
);
1013 key
.directory_id
= found
->header
.key
.directory_id
;
1014 key
.object_id
= found
->header
.key
.object_id
;
1015 grub_reiserfs_set_key_type (&key
, GRUB_REISERFS_STAT
, 2);
1016 grub_reiserfs_set_key_offset (&key
, 0);
1017 if (grub_reiserfs_get_item (data
, &key
, &info
) != GRUB_ERR_NONE
)
1019 if (info
.block_number
== 0)
1021 grub_error (GRUB_ERR_BAD_FS
, "Unable to find searched item");
1024 entry_version
= grub_le_to_cpu16 (info
.header
.version
);
1025 entry_location
= grub_le_to_cpu16 (info
.header
.item_location
);
1026 block_number
= info
.block_number
;
1027 if (entry_version
== 0) /* Version 1 stat item. */
1029 struct grub_reiserfs_stat_item_v1 entry_v1_stat
;
1030 grub_disk_read (data
->disk
,
1031 block_number
* (block_size
>> GRUB_DISK_SECTOR_BITS
),
1033 + (((grub_off_t
) block_number
* block_size
)
1034 & (GRUB_DISK_SECTOR_SIZE
- 1)),
1035 sizeof (entry_v1_stat
), (char *) &entry_v1_stat
);
1038 file
->size
= (grub_off_t
) grub_le_to_cpu64 (entry_v1_stat
.size
);
1042 struct grub_reiserfs_stat_item_v2 entry_v2_stat
;
1043 grub_disk_read (data
->disk
,
1044 block_number
* (block_size
>> GRUB_DISK_SECTOR_BITS
),
1046 + (((grub_off_t
) block_number
* block_size
)
1047 & (GRUB_DISK_SECTOR_SIZE
- 1)),
1048 sizeof (entry_v2_stat
), (char *) &entry_v2_stat
);
1051 file
->size
= (grub_off_t
) grub_le_to_cpu64 (entry_v2_stat
.size
);
1053 grub_dprintf ("reiserfs", "file size : %d (%08x%08x)\n",
1054 (unsigned int) file
->size
,
1055 (unsigned int) (file
->size
>> 32), (unsigned int) file
->size
);
1058 return GRUB_ERR_NONE
;
1061 assert (grub_errno
!= GRUB_ERR_NONE
);
1065 grub_dl_unref (my_mod
);
1071 grub_reiserfs_read (grub_file_t file
, char *buf
, grub_size_t len
)
1073 unsigned int indirect_block
, indirect_block_count
;
1074 struct grub_reiserfs_key key
;
1075 struct grub_fshelp_node
*node
= file
->data
;
1076 struct grub_reiserfs_data
*data
= node
->data
;
1077 struct grub_fshelp_node found
;
1078 grub_uint16_t block_size
= grub_le_to_cpu16 (data
->superblock
.block_size
);
1079 grub_uint16_t item_size
;
1080 grub_uint32_t
*indirect_block_ptr
= 0;
1081 grub_uint64_t current_key_offset
= 1;
1082 grub_off_t initial_position
, current_position
, final_position
, length
;
1083 grub_disk_addr_t block
;
1086 if (file
->offset
>= file
->size
)
1089 key
.directory_id
= node
->header
.key
.directory_id
;
1090 key
.object_id
= node
->header
.key
.object_id
;
1091 key
.u
.v2
.offset_type
= 0;
1092 grub_reiserfs_set_key_type (&key
, GRUB_REISERFS_ANY
, 2);
1093 initial_position
= file
->offset
;
1094 current_position
= 0;
1095 final_position
= MIN (len
+ initial_position
, file
->size
);
1096 grub_dprintf ("reiserfs",
1097 "Reading from %lld to %lld (%lld instead of requested %ld)\n",
1098 (unsigned long long) initial_position
,
1099 (unsigned long long) final_position
,
1100 (unsigned long long) (final_position
- initial_position
),
1101 (unsigned long) len
);
1102 while (current_position
< final_position
)
1104 grub_reiserfs_set_key_offset (&key
, current_key_offset
);
1106 if (grub_reiserfs_get_item (data
, &key
, &found
) != GRUB_ERR_NONE
)
1108 if (found
.block_number
== 0)
1110 item_size
= grub_le_to_cpu16 (found
.header
.item_size
);
1113 case GRUB_REISERFS_DIRECT
:
1114 block
= found
.block_number
* (block_size
>> GRUB_DISK_SECTOR_BITS
);
1115 grub_dprintf ("reiserfs_blocktype", "D: %u\n", (unsigned) block
);
1116 if (initial_position
< current_position
+ item_size
)
1118 offset
= MAX ((signed) (initial_position
- current_position
), 0);
1119 length
= (MIN (item_size
, final_position
- current_position
)
1121 grub_dprintf ("reiserfs",
1122 "Reading direct block %u from %u to %u...\n",
1123 (unsigned) block
, (unsigned) offset
,
1124 (unsigned) (offset
+ length
));
1125 found
.data
->disk
->read_hook
= file
->read_hook
;
1126 grub_disk_read (found
.data
->disk
,
1129 + grub_le_to_cpu16 (found
.header
.item_location
),
1131 found
.data
->disk
->read_hook
= 0;
1135 current_position
+= offset
+ length
;
1138 current_position
+= item_size
;
1140 case GRUB_REISERFS_INDIRECT
:
1141 indirect_block_count
= item_size
/ sizeof (*indirect_block_ptr
);
1142 indirect_block_ptr
= grub_malloc (item_size
);
1143 if (! indirect_block_ptr
)
1145 grub_disk_read (found
.data
->disk
,
1146 found
.block_number
* (block_size
>> GRUB_DISK_SECTOR_BITS
),
1147 grub_le_to_cpu16 (found
.header
.item_location
),
1148 item_size
, (char *) indirect_block_ptr
);
1151 found
.data
->disk
->read_hook
= file
->read_hook
;
1152 for (indirect_block
= 0;
1153 indirect_block
< indirect_block_count
1154 && current_position
< final_position
;
1157 block
= grub_le_to_cpu32 (indirect_block_ptr
[indirect_block
]) *
1158 (block_size
>> GRUB_DISK_SECTOR_BITS
);
1159 grub_dprintf ("reiserfs_blocktype", "I: %u\n", (unsigned) block
);
1160 if (current_position
+ block_size
>= initial_position
)
1162 offset
= MAX ((signed) (initial_position
- current_position
),
1164 length
= (MIN (block_size
, final_position
- current_position
)
1166 grub_dprintf ("reiserfs",
1167 "Reading indirect block %u from %u to %u...\n",
1168 (unsigned) block
, (unsigned) offset
,
1169 (unsigned) (offset
+ length
));
1171 grub_dprintf ("reiserfs",
1172 "\nib=%04d/%04d, ip=%d, cp=%d, fp=%d, off=%d, l=%d, tl=%d\n",
1173 indirect_block
+ 1, indirect_block_count
,
1174 initial_position
, current_position
,
1175 final_position
, offset
, length
, len
);
1177 grub_disk_read (found
.data
->disk
, block
, offset
, length
, buf
);
1181 current_position
+= offset
+ length
;
1184 current_position
+= block_size
;
1186 found
.data
->disk
->read_hook
= 0;
1187 grub_free (indirect_block_ptr
);
1188 indirect_block_ptr
= 0;
1193 current_key_offset
= current_position
+ 1;
1196 grub_dprintf ("reiserfs",
1197 "Have successfully read %lld bytes (%ld requested)\n",
1198 (unsigned long long) (current_position
- initial_position
),
1199 (unsigned long) len
);
1200 return current_position
- initial_position
;
1204 case GRUB_REISERFS_DIRECT:
1205 read_length = MIN (len, item_size - file->offset);
1206 grub_disk_read (found.data->disk,
1207 (found.block_number * block_size) / GRUB_DISK_SECTOR_SIZE,
1208 grub_le_to_cpu16 (found.header.item_location) + file->offset,
1213 case GRUB_REISERFS_INDIRECT:
1214 indirect_block_count = item_size / sizeof (*indirect_block_ptr);
1215 indirect_block_ptr = grub_malloc (item_size);
1216 if (!indirect_block_ptr)
1218 grub_disk_read (found.data->disk,
1219 (found.block_number * block_size) / GRUB_DISK_SECTOR_SIZE,
1220 grub_le_to_cpu16 (found.header.item_location),
1221 item_size, (char *) indirect_block_ptr);
1224 len = MIN (len, file->size - file->offset);
1225 for (indirect_block = file->offset / block_size;
1226 indirect_block < indirect_block_count && read_length < len;
1229 read = MIN (block_size, len - read_length);
1230 grub_disk_read (found.data->disk,
1231 (grub_le_to_cpu32 (indirect_block_ptr[indirect_block]) * block_size) / GRUB_DISK_SECTOR_SIZE,
1232 file->offset % block_size, read,
1233 ((void *) buf) + read_length);
1236 read_length += read;
1238 grub_free (indirect_block_ptr);
1244 return read_length;*/
1247 grub_free (indirect_block_ptr
);
1251 /* Close the file FILE. */
1253 grub_reiserfs_close (grub_file_t file
)
1255 struct grub_fshelp_node
*node
= file
->data
;
1256 struct grub_reiserfs_data
*data
= node
->data
;
1261 grub_dl_unref (my_mod
);
1263 return GRUB_ERR_NONE
;
1266 /* Call HOOK with each file under DIR. */
1268 grub_reiserfs_dir (grub_device_t device
, const char *path
,
1269 int (*hook
) (const char *filename
, int dir
))
1271 struct grub_reiserfs_data
*data
= 0;
1272 struct grub_fshelp_node root
, *found
;
1273 struct grub_reiserfs_key root_key
;
1275 auto int NESTED_FUNC_ATTR
iterate (const char *filename
,
1276 enum grub_fshelp_filetype filetype
,
1277 grub_fshelp_node_t node
);
1279 int NESTED_FUNC_ATTR
iterate (const char *filename
,
1280 enum grub_fshelp_filetype filetype
,
1281 grub_fshelp_node_t node
)
1285 if (filetype
== GRUB_FSHELP_DIR
)
1286 return hook (filename
, 1);
1288 return hook (filename
, 0);
1291 grub_dl_ref (my_mod
);
1293 data
= grub_reiserfs_mount (device
->disk
);
1296 root_key
.directory_id
= grub_cpu_to_le32 (1);
1297 root_key
.object_id
= grub_cpu_to_le32 (2);
1298 root_key
.u
.v2
.offset_type
= 0;
1299 grub_reiserfs_set_key_type (&root_key
, GRUB_REISERFS_DIRECTORY
, 2);
1300 grub_reiserfs_set_key_offset (&root_key
, 1);
1301 if (grub_reiserfs_get_item (data
, &root_key
, &root
) != GRUB_ERR_NONE
)
1303 if (root
.block_number
== 0)
1305 grub_error(GRUB_ERR_BAD_FS
, "Root not found");
1308 grub_fshelp_find_file (path
, &root
, &found
, grub_reiserfs_iterate_dir
,
1309 grub_reiserfs_read_symlink
, GRUB_FSHELP_DIR
);
1312 grub_reiserfs_iterate_dir (found
, iterate
);
1315 grub_dl_unref (my_mod
);
1317 return GRUB_ERR_NONE
;
1322 grub_dl_unref (my_mod
);
1327 /* Return the label of the device DEVICE in LABEL. The label is
1328 returned in a grub_malloc'ed buffer and should be freed by the
1331 grub_reiserfs_label (grub_device_t device
, char **label
)
1333 *label
= grub_malloc (REISERFS_MAX_LABEL_LENGTH
);
1336 grub_disk_read (device
->disk
,
1337 REISERFS_SUPER_BLOCK_OFFSET
/ GRUB_DISK_SECTOR_SIZE
,
1338 REISERFS_LABEL_OFFSET
, REISERFS_MAX_LABEL_LENGTH
,
1345 grub_reiserfs_uuid (grub_device_t device
, char **uuid
)
1347 struct grub_reiserfs_data
*data
;
1348 grub_disk_t disk
= device
->disk
;
1351 grub_dl_ref (my_mod
);
1354 data
= grub_reiserfs_mount (disk
);
1357 *uuid
= grub_malloc (sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"));
1358 grub_sprintf (*uuid
, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
1359 grub_be_to_cpu16 (data
->superblock
.uuid
[0]), grub_be_to_cpu16 (data
->superblock
.uuid
[1]),
1360 grub_be_to_cpu16 (data
->superblock
.uuid
[2]), grub_be_to_cpu16 (data
->superblock
.uuid
[3]),
1361 grub_be_to_cpu16 (data
->superblock
.uuid
[4]), grub_be_to_cpu16 (data
->superblock
.uuid
[5]),
1362 grub_be_to_cpu16 (data
->superblock
.uuid
[6]), grub_be_to_cpu16 (data
->superblock
.uuid
[7]));
1368 grub_dl_unref (my_mod
);
1376 static struct grub_fs grub_reiserfs_fs
=
1379 .dir
= grub_reiserfs_dir
,
1380 .open
= grub_reiserfs_open
,
1381 .read
= grub_reiserfs_read
,
1382 .close
= grub_reiserfs_close
,
1383 .label
= grub_reiserfs_label
,
1384 .uuid
= grub_reiserfs_uuid
,
1388 GRUB_MOD_INIT(reiserfs
)
1390 grub_fs_register (&grub_reiserfs_fs
);
1396 GRUB_MOD_FINI(reiserfs
)
1398 grub_fs_unregister (&grub_reiserfs_fs
);