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
26 #warning "TODO : journal, tail packing (?)"
29 # define GRUB_REISERFS_KEYV2_BITFIELD 1
30 # define GRUB_REISERFS_DEBUG
31 # define GRUB_REISERFS_JOURNALING
36 #include <grub/file.h>
38 #include <grub/misc.h>
39 #include <grub/disk.h>
41 #include <grub/types.h>
42 #include <grub/fshelp.h>
45 ({ typeof (a) _a = (a); \
46 typeof (b) _b = (b); \
50 ({ typeof (a) _a = (a); \
51 typeof (b) _b = (b); \
54 #define REISERFS_SUPER_BLOCK_OFFSET 0x10000
55 #define REISERFS_MAGIC_LEN 12
56 #define REISERFS_MAGIC_STRING "ReIsEr2Fs\0\0\0"
57 /* If the 3rd bit of an item state is set, then it's visible. */
58 #define GRUB_REISERFS_VISIBLE_MASK ((grub_uint16_t) 0x04)
59 #define REISERFS_MAX_LABEL_LENGTH 16
60 #define REISERFS_LABEL_OFFSET 0x64
62 #define S_IFLNK 0xA000
65 static grub_dl_t my_mod
;
68 #define assert(boolean) real_assert (boolean, __FILE__, __LINE__)
70 real_assert (int boolean
, const char *file
, const int line
)
73 grub_printf ("Assertion failed at %s:%d\n", file
, line
);
76 enum grub_reiserfs_item_type
79 GRUB_REISERFS_DIRECTORY
,
81 GRUB_REISERFS_INDIRECT
,
82 /* Matches both _DIRECT and _INDIRECT when searching. */
87 struct grub_reiserfs_superblock
89 grub_uint32_t block_count
;
90 grub_uint32_t block_free_count
;
91 grub_uint32_t root_block
;
92 grub_uint32_t journal_block
;
93 grub_uint32_t journal_device
;
94 grub_uint32_t journal_original_size
;
95 grub_uint32_t journal_max_transaction_size
;
96 grub_uint32_t journal_block_count
;
97 grub_uint32_t journal_max_batch
;
98 grub_uint32_t journal_max_commit_age
;
99 grub_uint32_t journal_max_transaction_age
;
100 grub_uint16_t block_size
;
101 grub_uint16_t oid_max_size
;
102 grub_uint16_t oid_current_size
;
104 grub_uint8_t magic_string
[REISERFS_MAGIC_LEN
];
105 grub_uint32_t function_hash_code
;
106 grub_uint16_t tree_height
;
107 grub_uint16_t bitmap_number
;
108 grub_uint16_t version
;
109 grub_uint16_t reserved
;
110 grub_uint32_t inode_generation
;
111 } __attribute__ ((packed
));
113 #ifdef GRUB_REISERFS_JOURNALING
114 # error "Journaling not yet supported."
115 struct grub_reiserfs_journal_header
117 grub_uint32_t last_flush_uid
;
118 grub_uint32_t unflushed_offset
;
119 grub_uint32_t mount_id
;
120 } __attribute__ ((packed
));
122 struct grub_reiserfs_transaction_header
126 grub_uint32_t mount_id
;
129 } __attribute__ ((packed
));
132 struct grub_reiserfs_stat_item_v1
135 grub_uint16_t hardlink_count
;
143 grub_uint32_t first_direct_byte
;
144 } __attribute__ ((packed
));
146 struct grub_reiserfs_stat_item_v2
149 grub_uint16_t reserved
;
150 grub_uint32_t hardlink_count
;
157 grub_uint32_t blocks
;
158 grub_uint32_t first_direct_byte
;
159 } __attribute__ ((packed
));
161 struct grub_reiserfs_key
163 grub_uint32_t directory_id
;
164 grub_uint32_t object_id
;
169 grub_uint32_t offset
;
171 } v1
__attribute__ ((packed
));
174 #ifdef GRUB_REISERFS_KEYV2_BITFIELD
175 grub_uint64_t offset
:60;
176 grub_uint64_t type
:4;
178 grub_uint64_t offset_type
;
180 } v2
__attribute__ ((packed
));
182 } __attribute__ ((packed
));
184 struct grub_reiserfs_item_header
186 struct grub_reiserfs_key key
;
189 grub_uint16_t free_space
;
190 grub_uint16_t entry_count
;
191 } u
__attribute__ ((packed
));
192 grub_uint16_t item_size
;
193 grub_uint16_t item_location
;
194 grub_uint16_t version
;
195 } __attribute__ ((packed
));
197 struct grub_reiserfs_block_header
200 grub_uint16_t item_count
;
201 grub_uint16_t free_space
;
202 grub_uint16_t reserved
;
203 struct grub_reiserfs_key block_right_delimiting_key
;
204 } __attribute__ ((packed
));
206 struct grub_reiserfs_disk_child
208 grub_uint32_t block_number
;
210 grub_uint16_t reserved
;
211 } __attribute__ ((packed
));
213 struct grub_reiserfs_directory_header
215 grub_uint32_t offset
;
216 grub_uint32_t directory_id
;
217 grub_uint32_t object_id
;
218 grub_uint16_t location
;
220 } __attribute__ ((packed
));
222 struct grub_reiserfs_node_body
228 struct grub_reiserfs_key
*key_list
;
229 struct grub_reiserfs_disk_child
*child_list
;
233 struct grub_reiserfs_item_header
*item_header_list
;
238 struct grub_fshelp_node
240 struct grub_reiserfs_data
*data
;
241 grub_uint32_t block_number
; /* 0 if node is not found. */
242 grub_uint16_t block_position
;
243 enum grub_reiserfs_item_type type
; /* To know how to read the header. */
244 struct grub_reiserfs_item_header header
;
247 /* Returned when opening a file. */
248 struct grub_reiserfs_data
250 struct grub_reiserfs_superblock superblock
;
254 /* Internal-only functions. Not to be used outside of this file. */
256 /* Return the type of given v2 key. */
257 static enum grub_reiserfs_item_type
258 grub_reiserfs_get_key_v2_type (const struct grub_reiserfs_key
*key
)
260 #ifdef GRUB_REISERFS_KEYV2_BITFIELD
261 switch (key
->u
.v2
.type
)
263 switch (grub_le_to_cpu64 (key
->u
.v2
.offset_type
) >> 60)
267 return GRUB_REISERFS_STAT
;
269 return GRUB_REISERFS_ANY
;
271 return GRUB_REISERFS_DIRECTORY
;
273 return GRUB_REISERFS_DIRECT
;
275 return GRUB_REISERFS_INDIRECT
;
277 return GRUB_REISERFS_UNKNOWN
;
280 /* Return the type of given v1 key. */
281 static enum grub_reiserfs_item_type
282 grub_reiserfs_get_key_v1_type (const struct grub_reiserfs_key
*key
)
284 switch (grub_le_to_cpu32 (key
->u
.v1
.type
))
287 return GRUB_REISERFS_STAT
;
289 return GRUB_REISERFS_ANY
;
291 return GRUB_REISERFS_DIRECTORY
;
294 return GRUB_REISERFS_DIRECT
;
297 return GRUB_REISERFS_INDIRECT
;
299 return GRUB_REISERFS_UNKNOWN
;
302 /* Return 1 if the given key is version 1 key, 2 otherwise. */
304 grub_reiserfs_get_key_version (const struct grub_reiserfs_key
*key
)
306 return grub_reiserfs_get_key_v1_type (key
) == GRUB_REISERFS_UNKNOWN
? 2 : 1;
311 grub_hexdump (char *buffer
, grub_size_t len
)
314 for (a
= 0; a
< len
; a
++)
317 grub_printf ("\n%08x ", a
);
318 grub_printf ("%02x ",
319 ((unsigned int) ((unsigned char *) buffer
)[a
]) & 0xFF);
325 #ifdef GRUB_REISERFS_DEBUG
327 grub_reiserfs_get_key_offset (const struct grub_reiserfs_key
*key
);
329 static enum grub_reiserfs_item_type
330 grub_reiserfs_get_key_type (const struct grub_reiserfs_key
*key
);
333 grub_reiserfs_print_key (const struct grub_reiserfs_key
*key
)
336 char *reiserfs_type_strings
[] = {
345 for (a
= 0; a
< sizeof (struct grub_reiserfs_key
); a
++)
346 grub_printf ("%02x ", ((unsigned int) ((unsigned char *) key
)[a
]) & 0xFF);
347 grub_printf ("parent id = 0x%08x, self id = 0x%08x, type = %s, offset = ",
348 grub_le_to_cpu32 (key
->directory_id
),
349 grub_le_to_cpu32 (key
->object_id
),
350 reiserfs_type_strings
[grub_reiserfs_get_key_type (key
)]);
351 if (grub_reiserfs_get_key_version (key
) == 1)
352 grub_printf("%08x", (unsigned int) grub_reiserfs_get_key_offset (key
));
354 grub_printf("0x%07x%08x",
355 (unsigned) (grub_reiserfs_get_key_offset (key
) >> 32),
356 (unsigned) (grub_reiserfs_get_key_offset (key
) & 0xFFFFFFFF));
361 /* Return the offset of given key. */
363 grub_reiserfs_get_key_offset (const struct grub_reiserfs_key
*key
)
365 if (grub_reiserfs_get_key_version (key
) == 1)
366 return grub_le_to_cpu32 (key
->u
.v1
.offset
);
369 #ifdef GRUB_REISERFS_KEYV2_BITFIELD
370 return key
->u
.v2
.offset
;
372 return grub_le_to_cpu64 (key
->u
.v2
.offset_type
) & (~0ULL >> 4);
377 /* Set the offset of given key. */
379 grub_reiserfs_set_key_offset (struct grub_reiserfs_key
*key
,
382 if (grub_reiserfs_get_key_version (key
) == 1)
383 key
->u
.v1
.offset
= grub_cpu_to_le32 (value
);
385 #ifdef GRUB_REISERFS_KEYV2_BITFIELD
386 key
->u
.v2
.offset
= value
;
388 key
->u
.v2
.offset_type \
389 = ((key
->u
.v2
.offset_type
& grub_cpu_to_le64 (15ULL << 60))
390 | grub_cpu_to_le64 (value
& (~0ULL >> 4)));
394 /* Return the type of given key. */
395 static enum grub_reiserfs_item_type
396 grub_reiserfs_get_key_type (const struct grub_reiserfs_key
*key
)
398 if (grub_reiserfs_get_key_version (key
) == 1)
399 return grub_reiserfs_get_key_v1_type (key
);
401 return grub_reiserfs_get_key_v2_type (key
);
404 /* Set the type of given key, with given version number. */
406 grub_reiserfs_set_key_type (struct grub_reiserfs_key
*key
,
407 enum grub_reiserfs_item_type grub_type
,
414 case GRUB_REISERFS_STAT
:
417 case GRUB_REISERFS_ANY
:
418 type
= (version
== 1) ? 555 : 15;
420 case GRUB_REISERFS_DIRECTORY
:
421 type
= (version
== 1) ? 500 : 3;
423 case GRUB_REISERFS_DIRECT
:
424 type
= (version
== 1) ? 0xFFFFFFFF : 2;
426 case GRUB_REISERFS_INDIRECT
:
427 type
= (version
== 1) ? 0xFFFFFFFE : 1;
434 key
->u
.v1
.type
= grub_cpu_to_le32 (type
);
437 #ifdef GRUB_REISERFS_KEYV2_BITFIELD
438 key
->u
.v2
.type
= type
;
440 key
->u
.v2
.offset_type
441 = ((key
->u
.v2
.offset_type
& grub_cpu_to_le64 (~0ULL >> 4))
442 | grub_cpu_to_le64 ((grub_uint64_t
) type
<< 60));
445 assert (grub_reiserfs_get_key_type (key
) == grub_type
);
448 /* -1 if key 1 if lower than key 2.
449 0 if key 1 is equal to key 2.
450 1 if key 1 is higher than key 2. */
452 grub_reiserfs_compare_keys (const struct grub_reiserfs_key
*key1
,
453 const struct grub_reiserfs_key
*key2
)
455 grub_uint64_t offset1
, offset2
;
456 enum grub_reiserfs_item_type type1
, type2
;
457 grub_uint32_t id1
, id2
;
459 if (! key1
|| ! key2
)
462 id1
= grub_le_to_cpu32 (key1
->directory_id
);
463 id2
= grub_le_to_cpu32 (key2
->directory_id
);
469 id1
= grub_le_to_cpu32 (key1
->object_id
);
470 id2
= grub_le_to_cpu32 (key2
->object_id
);
476 offset1
= grub_reiserfs_get_key_offset (key1
);
477 offset2
= grub_reiserfs_get_key_offset (key2
);
478 if (offset1
< offset2
)
480 if (offset1
> offset2
)
483 type1
= grub_reiserfs_get_key_type (key1
);
484 type2
= grub_reiserfs_get_key_type (key2
);
485 if ((type1
== GRUB_REISERFS_ANY
486 && (type2
== GRUB_REISERFS_DIRECT
487 || type2
== GRUB_REISERFS_INDIRECT
))
488 || (type2
== GRUB_REISERFS_ANY
489 && (type1
== GRUB_REISERFS_DIRECT
490 || type1
== GRUB_REISERFS_INDIRECT
)))
500 /* Find the item identified by KEY in mounted filesystem DATA, and fill ITEM
501 accordingly to what was found. */
503 grub_reiserfs_get_item (struct grub_reiserfs_data
*data
,
504 const struct grub_reiserfs_key
*key
,
505 struct grub_fshelp_node
*item
)
507 grub_uint32_t block_number
;
508 struct grub_reiserfs_block_header
*block_header
= 0;
509 struct grub_reiserfs_key
*block_key
= 0;
510 grub_uint16_t block_size
, item_count
, current_level
;
512 grub_uint16_t previous_level
= ~0;
513 struct grub_reiserfs_item_header
*item_headers
= 0;
517 grub_error (GRUB_ERR_TEST_FAILURE
, "data is NULL");
523 grub_error (GRUB_ERR_TEST_FAILURE
, "key is NULL");
529 grub_error (GRUB_ERR_TEST_FAILURE
, "item is NULL");
533 block_size
= grub_le_to_cpu16 (data
->superblock
.block_size
);
534 block_number
= grub_le_to_cpu32 (data
->superblock
.root_block
);
535 #ifdef GRUB_REISERFS_DEBUG
536 grub_printf("Searching for ");
537 grub_reiserfs_print_key (key
);
539 block_header
= grub_malloc (block_size
);
545 grub_disk_read (data
->disk
,
546 (((grub_disk_addr_t
) block_number
* block_size
)
547 >> GRUB_DISK_SECTOR_BITS
),
548 (((grub_off_t
) block_number
* block_size
)
549 & (GRUB_DISK_SECTOR_SIZE
- 1)),
550 block_size
, (char *) block_header
);
553 current_level
= grub_le_to_cpu16 (block_header
->level
);
554 grub_dprintf ("reiserfs_tree", " at level %d\n", current_level
);
555 if (current_level
>= previous_level
)
557 grub_dprintf ("reiserfs_tree", "level loop detected, aborting\n");
558 grub_error (GRUB_ERR_FILE_READ_ERROR
, "level loop");
561 previous_level
= current_level
;
562 item_count
= grub_le_to_cpu16 (block_header
->item_count
);
563 grub_dprintf ("reiserfs_tree", " number of contained items : %d\n",
565 if (current_level
> 1)
567 /* Internal node. Navigate to the child that should contain
569 struct grub_reiserfs_key
*keys
570 = (struct grub_reiserfs_key
*) (block_header
+ 1);
571 struct grub_reiserfs_disk_child
*children
572 = ((struct grub_reiserfs_disk_child
*)
573 (keys
+ item_count
));
577 && grub_reiserfs_compare_keys (key
, &(keys
[i
])) >= 0;
580 #ifdef GRUB_REISERFS_DEBUG
581 grub_printf("i %03d/%03d ", i
+ 1, item_count
+ 1);
582 grub_reiserfs_print_key (&(keys
[i
]));
585 block_number
= grub_le_to_cpu32 (children
[i
].block_number
);
586 #ifdef GRUB_REISERFS_DEBUG
588 || grub_reiserfs_compare_keys (key
, &(keys
[i
])) == 0)
594 grub_printf (" %03d/%03d ", i
+ 1, item_count
+ 1);
595 grub_reiserfs_print_key (&(keys
[i
]));
596 if (i
+ 1 < item_count
)
598 grub_printf ("+ %03d/%03d ", i
+ 2, item_count
);
599 grub_reiserfs_print_key (&(keys
[i
+ 1]));
603 grub_printf ("Accessing rightmost child at block %d.\n",
609 /* Leaf node. Check that the key is actually present. */
611 = (struct grub_reiserfs_item_header
*) (block_header
+ 1);
614 && (grub_reiserfs_compare_keys (key
, &(item_headers
[i
].key
))
618 #ifdef GRUB_REISERFS_DEBUG
619 if (key
->directory_id
== item_headers
[i
].key
.directory_id
&& \
620 key
->object_id
== item_headers
[i
].key
.object_id
)
624 grub_printf(" %03d/%03d ", i
+ 1, item_count
);
625 grub_reiserfs_print_key (&(item_headers
[i
].key
));
629 block_key
= &(item_headers
[i
].key
);
632 while (current_level
> 1);
636 if (i
== item_count
|| grub_reiserfs_compare_keys (key
, block_key
))
638 item
->block_number
= 0;
639 item
->block_position
= 0;
640 item
->type
= GRUB_REISERFS_UNKNOWN
;
641 #ifdef GRUB_REISERFS_DEBUG
642 grub_printf("Not found.\n");
647 item
->block_number
= block_number
;
648 item
->block_position
= i
;
649 item
->type
= grub_reiserfs_get_key_type (block_key
);
650 grub_memcpy (&(item
->header
), &(item_headers
[i
]),
651 sizeof (struct grub_reiserfs_item_header
));
652 #ifdef GRUB_REISERFS_DEBUG
653 grub_printf ("F %03d/%03d ", i
+ 1, item_count
);
654 grub_reiserfs_print_key (block_key
);
658 assert (grub_errno
== GRUB_ERR_NONE
);
659 grub_free (block_header
);
660 return GRUB_ERR_NONE
;
663 assert (grub_errno
!= GRUB_ERR_NONE
);
664 grub_free (block_header
);
665 assert (grub_errno
!= GRUB_ERR_NONE
);
669 /* Return the path of the file which is pointed at by symlink NODE. */
671 grub_reiserfs_read_symlink (grub_fshelp_node_t node
)
673 char *symlink_buffer
= 0;
674 grub_uint16_t block_size
;
675 grub_disk_addr_t block
;
678 struct grub_fshelp_node found
;
679 struct grub_reiserfs_key key
;
681 grub_memcpy (&key
, &(node
->header
.key
), sizeof (key
));
682 grub_reiserfs_set_key_offset (&key
, 1);
683 grub_reiserfs_set_key_type (&key
, GRUB_REISERFS_DIRECT
,
684 grub_reiserfs_get_key_version (&key
));
686 if (grub_reiserfs_get_item (node
->data
, &key
, &found
) != GRUB_ERR_NONE
)
689 if (found
.block_number
== 0)
692 block_size
= grub_le_to_cpu16 (node
->data
->superblock
.block_size
);
693 len
= grub_le_to_cpu16 (found
.header
.item_size
);
694 block
= (((grub_disk_addr_t
) found
.block_number
* block_size
)
695 >> GRUB_DISK_SECTOR_BITS
);
696 offset
= grub_le_to_cpu16 (found
.header
.item_location
);
698 symlink_buffer
= grub_malloc (len
);
699 if (! symlink_buffer
)
702 grub_disk_read (node
->data
->disk
, block
, offset
, len
, symlink_buffer
);
706 return symlink_buffer
;
709 grub_free (symlink_buffer
);
713 /* Fill the mounted filesystem structure and return it. */
714 static struct grub_reiserfs_data
*
715 grub_reiserfs_mount (grub_disk_t disk
)
717 struct grub_reiserfs_data
*data
= 0;
718 data
= grub_malloc (sizeof (*data
));
721 grub_disk_read (disk
, REISERFS_SUPER_BLOCK_OFFSET
/ GRUB_DISK_SECTOR_SIZE
,
722 0, sizeof (data
->superblock
), (char *) &(data
->superblock
));
725 if (grub_memcmp (data
->superblock
.magic_string
,
726 REISERFS_MAGIC_STRING
, REISERFS_MAGIC_LEN
))
728 grub_error (GRUB_ERR_BAD_FS
, "not a reiserfs filesystem");
739 /* Call HOOK for each file in directory ITEM. */
741 grub_reiserfs_iterate_dir (grub_fshelp_node_t item
,
743 (*hook
) (const char *filename
,
744 enum grub_fshelp_filetype filetype
,
745 grub_fshelp_node_t node
))
747 struct grub_reiserfs_data
*data
= item
->data
;
748 struct grub_reiserfs_block_header
*block_header
= 0;
749 grub_uint16_t block_size
, block_position
;
750 grub_uint32_t block_number
;
753 if (item
->type
!= GRUB_REISERFS_DIRECTORY
)
755 grub_error (GRUB_ERR_BAD_FILE_TYPE
,
756 "grub_reiserfs_iterate_dir called on a non-directory item");
759 block_size
= grub_le_to_cpu16 (data
->superblock
.block_size
);
760 block_header
= grub_malloc (block_size
);
763 block_number
= item
->block_number
;
764 block_position
= item
->block_position
;
765 grub_dprintf ("reiserfs", "Iterating directory...\n");
768 struct grub_reiserfs_directory_header
*directory_headers
;
769 struct grub_fshelp_node directory_item
;
770 grub_uint16_t entry_count
, entry_number
;
771 struct grub_reiserfs_item_header
*item_headers
;
772 grub_uint64_t key_offset
;
774 grub_disk_read (data
->disk
,
775 (((grub_disk_addr_t
) block_number
* block_size
)
776 >> GRUB_DISK_SECTOR_BITS
),
777 (((grub_off_t
) block_number
* block_size
)
778 & (GRUB_DISK_SECTOR_SIZE
- 1)),
779 block_size
, (char *) block_header
);
784 if (grub_le_to_cpu16 (block_header
->level
) != 1)
786 grub_error (GRUB_ERR_TEST_FAILURE
,
787 "reiserfs: block %d is not a leaf block",
793 item_headers
= (struct grub_reiserfs_item_header
*) (block_header
+ 1);
795 = ((struct grub_reiserfs_directory_header
*)
796 ((char *) block_header
797 + grub_le_to_cpu16 (item_headers
[block_position
].item_location
)));
799 = grub_le_to_cpu16 (item_headers
[block_position
].u
.entry_count
);
800 for (entry_number
= 0; entry_number
< entry_count
; entry_number
++)
802 struct grub_reiserfs_directory_header
*directory_header
803 = &directory_headers
[entry_number
];
804 grub_uint16_t entry_state
805 = grub_le_to_cpu16 (directory_header
->state
);
807 if (entry_state
& GRUB_REISERFS_VISIBLE_MASK
)
809 grub_fshelp_node_t entry_item
;
810 struct grub_reiserfs_key entry_key
;
811 enum grub_reiserfs_item_type entry_type
;
814 entry_name
= (((char *) directory_headers
)
815 + grub_le_to_cpu16 (directory_header
->location
));
816 entry_key
.directory_id
= directory_header
->directory_id
;
817 entry_key
.object_id
= directory_header
->object_id
;
818 #ifdef GRUB_REISERFS_KEYV2_BITFIELD
819 entry_key
.u
.v2
.offset
= 0;
820 entry_key
.u
.v2
.type
= 0;
822 entry_key
.u
.v2
.offset_type
= 0;
824 grub_reiserfs_set_key_type (&entry_key
, GRUB_REISERFS_DIRECTORY
,
826 grub_reiserfs_set_key_offset (&entry_key
, 1);
828 entry_item
= grub_malloc (sizeof (*entry_item
));
832 if (grub_reiserfs_get_item (data
, &entry_key
, entry_item
)
835 grub_free (entry_item
);
839 if (entry_item
->type
== GRUB_REISERFS_DIRECTORY
)
840 entry_type
= GRUB_FSHELP_DIR
;
843 grub_uint32_t entry_block_number
;
844 /* Order is very important here.
845 First set the offset to 0 using current key version.
846 Then change the key type, which influes on key version
848 grub_reiserfs_set_key_offset (&entry_key
, 0);
849 grub_reiserfs_set_key_type (&entry_key
, GRUB_REISERFS_STAT
,
851 if (grub_reiserfs_get_item (data
, &entry_key
, entry_item
)
854 grub_free (entry_item
);
858 if (entry_item
->block_number
!= 0)
860 grub_uint16_t entry_version
;
862 = grub_le_to_cpu16 (entry_item
->header
.version
);
863 entry_block_number
= entry_item
->block_number
;
865 grub_dprintf ("reiserfs",
866 "version %04x block %08x (%08x) position %08x\n",
867 entry_version
, entry_block_number
,
868 ((grub_disk_addr_t
) entry_block_number
* block_size
) / GRUB_DISK_SECTOR_SIZE
,
869 grub_le_to_cpu16 (entry_item
->header
.item_location
));
871 if (entry_version
== 0) /* Version 1 stat item. */
873 struct grub_reiserfs_stat_item_v1 entry_v1_stat
;
874 grub_disk_read (data
->disk
,
875 ((grub_disk_addr_t
) entry_block_number
* block_size
) >> GRUB_DISK_SECTOR_BITS
,
876 grub_le_to_cpu16 (entry_item
->header
.item_location
),
877 sizeof (entry_v1_stat
),
878 (char *) &entry_v1_stat
);
882 grub_dprintf ("reiserfs",
883 "%04x %04x %04x %04x %08x %08x | %08x %08x %08x %08x\n",
884 grub_le_to_cpu16 (entry_v1_stat
.mode
),
885 grub_le_to_cpu16 (entry_v1_stat
.hardlink_count
),
886 grub_le_to_cpu16 (entry_v1_stat
.uid
),
887 grub_le_to_cpu16 (entry_v1_stat
.gid
),
888 grub_le_to_cpu32 (entry_v1_stat
.size
),
889 grub_le_to_cpu32 (entry_v1_stat
.atime
),
890 grub_le_to_cpu32 (entry_v1_stat
.mtime
),
891 grub_le_to_cpu32 (entry_v1_stat
.ctime
),
892 grub_le_to_cpu32 (entry_v1_stat
.rdev
),
893 grub_le_to_cpu32 (entry_v1_stat
.first_direct_byte
));
894 grub_dprintf ("reiserfs",
895 "%04x %04x %04x %04x %08x %08x | %08x %08x %08x %08x\n",
897 entry_v1_stat
.hardlink_count
,
905 entry_v1_stat
.first_direct_byte
);
907 if ((grub_le_to_cpu16 (entry_v1_stat
.mode
) & S_IFLNK
)
909 entry_type
= GRUB_FSHELP_SYMLINK
;
911 entry_type
= GRUB_FSHELP_REG
;
915 struct grub_reiserfs_stat_item_v2 entry_v2_stat
;
916 grub_disk_read (data
->disk
,
917 ((grub_disk_addr_t
) entry_block_number
* block_size
) >> GRUB_DISK_SECTOR_BITS
,
918 grub_le_to_cpu16 (entry_item
->header
.item_location
),
919 sizeof (entry_v2_stat
),
920 (char *) &entry_v2_stat
);
924 grub_dprintf ("reiserfs",
925 "%04x %04x %08x %08x%08x | %08x %08x %08x %08x | %08x %08x %08x\n",
926 grub_le_to_cpu16 (entry_v2_stat
.mode
),
927 grub_le_to_cpu16 (entry_v2_stat
.reserved
),
928 grub_le_to_cpu32 (entry_v2_stat
.hardlink_count
),
929 (unsigned int) (grub_le_to_cpu64 (entry_v2_stat
.size
) >> 32),
930 (unsigned int) (grub_le_to_cpu64 (entry_v2_stat
.size
) && 0xFFFFFFFF),
931 grub_le_to_cpu32 (entry_v2_stat
.uid
),
932 grub_le_to_cpu32 (entry_v2_stat
.gid
),
933 grub_le_to_cpu32 (entry_v2_stat
.atime
),
934 grub_le_to_cpu32 (entry_v2_stat
.mtime
),
935 grub_le_to_cpu32 (entry_v2_stat
.ctime
),
936 grub_le_to_cpu32 (entry_v2_stat
.blocks
),
937 grub_le_to_cpu32 (entry_v2_stat
.first_direct_byte
));
938 grub_dprintf ("reiserfs",
939 "%04x %04x %08x %08x%08x | %08x %08x %08x %08x | %08x %08x %08x\n",
941 entry_v2_stat
.reserved
,
942 entry_v2_stat
.hardlink_count
,
943 (unsigned int) (entry_v2_stat
.size
>> 32),
944 (unsigned int) (entry_v2_stat
.size
&& 0xFFFFFFFF),
950 entry_v2_stat
.blocks
,
951 entry_v2_stat
.first_direct_byte
);
953 if ((grub_le_to_cpu16 (entry_v2_stat
.mode
) & S_IFLNK
)
955 entry_type
= GRUB_FSHELP_SYMLINK
;
957 entry_type
= GRUB_FSHELP_REG
;
962 /* Pseudo file ".." never has stat block. */
963 if (grub_strcmp (entry_name
, ".."))
964 grub_dprintf ("reiserfs",
965 "Warning : %s has no stat block !\n",
967 grub_free (entry_item
);
971 if (hook (entry_name
, entry_type
, entry_item
))
973 grub_dprintf ("reiserfs", "Found : %s, type=%d\n",
974 entry_name
, entry_type
);
979 *entry_name
= 0; /* Make sure next entry name (which is just
980 before this one in disk order) stops before
986 = grub_reiserfs_get_key_offset (&(item_headers
[block_position
].key
));
987 grub_reiserfs_set_key_offset (&(item_headers
[block_position
].key
),
989 if (grub_reiserfs_get_item (data
, &(item_headers
[block_position
].key
),
990 &directory_item
) != GRUB_ERR_NONE
)
992 block_number
= directory_item
.block_number
;
993 block_position
= directory_item
.block_position
;
995 while (block_number
);
998 assert (grub_errno
== GRUB_ERR_NONE
);
999 grub_free (block_header
);
1002 assert (grub_errno
!= GRUB_ERR_NONE
);
1003 grub_free (block_header
);
1007 /****************************************************************************/
1008 /* grub api functions */
1009 /****************************************************************************/
1011 /* Open a file named NAME and initialize FILE. */
1013 grub_reiserfs_open (struct grub_file
*file
, const char *name
)
1015 struct grub_reiserfs_data
*data
= 0;
1016 struct grub_fshelp_node root
, *found
= 0, info
;
1017 struct grub_reiserfs_key key
;
1018 grub_uint32_t block_number
;
1019 grub_uint16_t entry_version
, block_size
, entry_location
;
1022 grub_dl_ref (my_mod
);
1024 data
= grub_reiserfs_mount (file
->device
->disk
);
1027 block_size
= grub_le_to_cpu16 (data
->superblock
.block_size
);
1028 key
.directory_id
= grub_cpu_to_le32 (1);
1029 key
.object_id
= grub_cpu_to_le32 (2);
1030 #ifdef GRUB_REISERFS_KEYV2_BITFIELD
1031 key
.u
.v2
.offset
= 0;
1034 key
.u
.v2
.offset_type
= 0;
1036 grub_reiserfs_set_key_type (&key
, GRUB_REISERFS_DIRECTORY
, 2);
1037 grub_reiserfs_set_key_offset (&key
, 1);
1038 if (grub_reiserfs_get_item (data
, &key
, &root
) != GRUB_ERR_NONE
)
1040 if (root
.block_number
== 0)
1042 grub_error (GRUB_ERR_BAD_FS
, "Unable to find root item");
1043 goto fail
; /* Should never happen since checked at mount. */
1045 grub_fshelp_find_file (name
, &root
, &found
,
1046 grub_reiserfs_iterate_dir
,
1047 grub_reiserfs_read_symlink
, GRUB_FSHELP_REG
);
1050 key
.directory_id
= found
->header
.key
.directory_id
;
1051 key
.object_id
= found
->header
.key
.object_id
;
1052 grub_reiserfs_set_key_type (&key
, GRUB_REISERFS_STAT
, 2);
1053 grub_reiserfs_set_key_offset (&key
, 0);
1054 if (grub_reiserfs_get_item (data
, &key
, &info
) != GRUB_ERR_NONE
)
1056 if (info
.block_number
== 0)
1058 grub_error (GRUB_ERR_BAD_FS
, "Unable to find searched item");
1061 entry_version
= grub_le_to_cpu16 (info
.header
.version
);
1062 entry_location
= grub_le_to_cpu16 (info
.header
.item_location
);
1063 block_number
= info
.block_number
;
1064 if (entry_version
== 0) /* Version 1 stat item. */
1066 struct grub_reiserfs_stat_item_v1 entry_v1_stat
;
1067 grub_disk_read (data
->disk
,
1068 (((grub_disk_addr_t
) block_number
* block_size
)
1069 >> GRUB_DISK_SECTOR_BITS
),
1071 + (((grub_off_t
) block_number
* block_size
)
1072 & (GRUB_DISK_SECTOR_SIZE
- 1)),
1073 sizeof (entry_v1_stat
), (char *) &entry_v1_stat
);
1076 file
->size
= (grub_off_t
) grub_le_to_cpu64 (entry_v1_stat
.size
);
1080 struct grub_reiserfs_stat_item_v2 entry_v2_stat
;
1081 grub_disk_read (data
->disk
,
1082 (((grub_disk_addr_t
) block_number
* block_size
)
1083 >> GRUB_DISK_SECTOR_BITS
),
1085 + (((grub_off_t
) block_number
* block_size
)
1086 & (GRUB_DISK_SECTOR_SIZE
- 1)),
1087 sizeof (entry_v2_stat
), (char *) &entry_v2_stat
);
1090 file
->size
= (grub_off_t
) grub_le_to_cpu64 (entry_v2_stat
.size
);
1092 grub_dprintf ("reiserfs", "file size : %d (%08x%08x)\n",
1093 (unsigned int) file
->size
,
1094 (unsigned int) (file
->size
>> 32), (unsigned int) file
->size
);
1097 return GRUB_ERR_NONE
;
1100 assert (grub_errno
!= GRUB_ERR_NONE
);
1104 grub_dl_unref (my_mod
);
1110 grub_reiserfs_read (grub_file_t file
, char *buf
, grub_size_t len
)
1112 unsigned int indirect_block
, indirect_block_count
;
1113 struct grub_reiserfs_key key
;
1114 struct grub_fshelp_node
*node
= file
->data
;
1115 struct grub_reiserfs_data
*data
= node
->data
;
1116 struct grub_fshelp_node found
;
1117 grub_uint16_t block_size
= grub_le_to_cpu16 (data
->superblock
.block_size
);
1118 grub_uint16_t item_size
;
1119 grub_uint32_t
*indirect_block_ptr
= 0;
1120 grub_uint64_t current_key_offset
= 1;
1121 grub_size_t initial_position
, current_position
, final_position
, length
;
1122 grub_disk_addr_t block
;
1125 if (file
->offset
>= file
->size
)
1128 key
.directory_id
= node
->header
.key
.directory_id
;
1129 key
.object_id
= node
->header
.key
.object_id
;
1130 #ifdef GRUB_REISERFS_KEYV2_BITFIELD
1131 key
.u
.v2
.offset
= 0;
1134 key
.u
.v2
.offset_type
= 0;
1136 grub_reiserfs_set_key_type (&key
, GRUB_REISERFS_ANY
, 2);
1137 initial_position
= file
->offset
;
1138 current_position
= 0;
1139 final_position
= MIN (len
+ initial_position
, file
->size
);
1140 grub_dprintf ("reiserfs",
1141 "Reading from %d to %d (%d instead of requested %d)\n",
1142 initial_position
, final_position
,
1143 final_position
- initial_position
, len
);
1144 while (current_position
< final_position
)
1146 grub_reiserfs_set_key_offset (&key
, current_key_offset
);
1148 if (grub_reiserfs_get_item (data
, &key
, &found
) != GRUB_ERR_NONE
)
1150 if (found
.block_number
== 0)
1152 item_size
= grub_le_to_cpu16 (found
.header
.item_size
);
1155 case GRUB_REISERFS_DIRECT
:
1156 block
= (((grub_disk_addr_t
) found
.block_number
* block_size
)
1157 >> GRUB_DISK_SECTOR_BITS
);
1158 grub_dprintf ("reiserfs_blocktype", "D: %u\n", (unsigned) block
);
1159 if (initial_position
< current_position
+ item_size
)
1161 offset
= MAX ((signed) (initial_position
- current_position
), 0);
1162 length
= (MIN (item_size
, final_position
- current_position
)
1164 grub_dprintf ("reiserfs",
1165 "Reading direct block %u from %u to %u...\n",
1166 (unsigned) block
, (unsigned) offset
,
1167 (unsigned) offset
+ length
);
1168 found
.data
->disk
->read_hook
= file
->read_hook
;
1169 grub_disk_read (found
.data
->disk
,
1172 + grub_le_to_cpu16 (found
.header
.item_location
),
1174 found
.data
->disk
->read_hook
= 0;
1178 current_position
+= offset
+ length
;
1181 current_position
+= item_size
;
1183 case GRUB_REISERFS_INDIRECT
:
1184 indirect_block_count
= item_size
/ sizeof (*indirect_block_ptr
);
1185 indirect_block_ptr
= grub_malloc (item_size
);
1186 if (! indirect_block_ptr
)
1188 grub_disk_read (found
.data
->disk
,
1189 (((grub_disk_addr_t
) found
.block_number
* block_size
)
1190 >> GRUB_DISK_SECTOR_BITS
),
1191 grub_le_to_cpu16 (found
.header
.item_location
),
1192 item_size
, (char *) indirect_block_ptr
);
1195 found
.data
->disk
->read_hook
= file
->read_hook
;
1196 for (indirect_block
= 0;
1197 indirect_block
< indirect_block_count
1198 && current_position
< final_position
;
1201 block
= ((grub_disk_addr_t
)
1202 grub_le_to_cpu32 (indirect_block_ptr
[indirect_block
])
1203 * block_size
) >> GRUB_DISK_SECTOR_BITS
;
1204 grub_dprintf ("reiserfs_blocktype", "I: %u\n", (unsigned) block
);
1205 if (current_position
+ block_size
>= initial_position
)
1207 offset
= MAX ((signed) (initial_position
- current_position
),
1209 length
= (MIN (block_size
, final_position
- current_position
)
1211 grub_dprintf ("reiserfs",
1212 "Reading indirect block %u from %u to %u...\n",
1213 (unsigned) block
, (unsigned) offset
,
1214 (unsigned) offset
+ length
);
1216 grub_dprintf ("reiserfs",
1217 "\nib=%04d/%04d, ip=%d, cp=%d, fp=%d, off=%d, l=%d, tl=%d\n",
1218 indirect_block
+ 1, indirect_block_count
,
1219 initial_position
, current_position
,
1220 final_position
, offset
, length
, len
);
1222 grub_disk_read (found
.data
->disk
, block
, offset
, length
, buf
);
1226 current_position
+= offset
+ length
;
1229 current_position
+= block_size
;
1231 found
.data
->disk
->read_hook
= 0;
1232 grub_free (indirect_block_ptr
);
1233 indirect_block_ptr
= 0;
1238 current_key_offset
= current_position
+ 1;
1241 grub_dprintf("reiserfs",
1242 "Have successfully read %d bytes (%d requested)\n",
1243 current_position
- initial_position
, len
);
1244 return current_position
- initial_position
;
1248 case GRUB_REISERFS_DIRECT:
1249 read_length = MIN (len, item_size - file->offset);
1250 grub_disk_read (found.data->disk,
1251 (found.block_number * block_size) / GRUB_DISK_SECTOR_SIZE,
1252 grub_le_to_cpu16 (found.header.item_location) + file->offset,
1257 case GRUB_REISERFS_INDIRECT:
1258 indirect_block_count = item_size / sizeof (*indirect_block_ptr);
1259 indirect_block_ptr = grub_malloc (item_size);
1260 if (!indirect_block_ptr)
1262 grub_disk_read (found.data->disk,
1263 (found.block_number * block_size) / GRUB_DISK_SECTOR_SIZE,
1264 grub_le_to_cpu16 (found.header.item_location),
1265 item_size, (char *) indirect_block_ptr);
1268 len = MIN (len, file->size - file->offset);
1269 for (indirect_block = file->offset / block_size;
1270 indirect_block < indirect_block_count && read_length < len;
1273 read = MIN (block_size, len - read_length);
1274 grub_disk_read (found.data->disk,
1275 (grub_le_to_cpu32 (indirect_block_ptr[indirect_block]) * block_size) / GRUB_DISK_SECTOR_SIZE,
1276 file->offset % block_size, read,
1277 ((void *) buf) + read_length);
1280 read_length += read;
1282 grub_free (indirect_block_ptr);
1288 return read_length;*/
1291 grub_free (indirect_block_ptr
);
1295 /* Close the file FILE. */
1297 grub_reiserfs_close (grub_file_t file
)
1299 struct grub_fshelp_node
*node
= file
->data
;
1300 struct grub_reiserfs_data
*data
= node
->data
;
1305 grub_dl_unref (my_mod
);
1307 return GRUB_ERR_NONE
;
1310 /* Call HOOK with each file under DIR. */
1312 grub_reiserfs_dir (grub_device_t device
, const char *path
,
1313 int (*hook
) (const char *filename
, int dir
))
1315 struct grub_reiserfs_data
*data
= 0;
1316 struct grub_fshelp_node root
, *found
;
1317 struct grub_reiserfs_key root_key
;
1319 auto int NESTED_FUNC_ATTR
iterate (const char *filename
,
1320 enum grub_fshelp_filetype filetype
,
1321 grub_fshelp_node_t node
);
1323 int NESTED_FUNC_ATTR
iterate (const char *filename
,
1324 enum grub_fshelp_filetype filetype
,
1325 grub_fshelp_node_t node
)
1329 if (filetype
== GRUB_FSHELP_DIR
)
1330 return hook (filename
, 1);
1332 return hook (filename
, 0);
1335 grub_dl_ref (my_mod
);
1337 data
= grub_reiserfs_mount (device
->disk
);
1340 root_key
.directory_id
= grub_cpu_to_le32 (1);
1341 root_key
.object_id
= grub_cpu_to_le32 (2);
1342 #ifdef GRUB_REISERFS_KEYV2_BITFIELD
1343 root_key
.u
.v2
.offset
= 0;
1344 root_key
.u
.v2
.type
= 0;
1346 root_key
.u
.v2
.offset_type
= 0;
1348 grub_reiserfs_set_key_type (&root_key
, GRUB_REISERFS_DIRECTORY
, 2);
1349 grub_reiserfs_set_key_offset (&root_key
, 1);
1350 if (grub_reiserfs_get_item (data
, &root_key
, &root
) != GRUB_ERR_NONE
)
1352 if (root
.block_number
== 0)
1354 grub_error(GRUB_ERR_BAD_FS
, "Root not found");
1357 grub_fshelp_find_file (path
, &root
, &found
, grub_reiserfs_iterate_dir
,
1358 grub_reiserfs_read_symlink
, GRUB_FSHELP_DIR
);
1361 grub_reiserfs_iterate_dir (found
, iterate
);
1364 grub_dl_unref (my_mod
);
1366 return GRUB_ERR_NONE
;
1371 grub_dl_unref (my_mod
);
1376 /* Return the label of the device DEVICE in LABEL. The label is
1377 returned in a grub_malloc'ed buffer and should be freed by the
1380 grub_reiserfs_label (grub_device_t device
, char **label
)
1382 *label
= grub_malloc (REISERFS_MAX_LABEL_LENGTH
);
1385 grub_disk_read (device
->disk
,
1386 REISERFS_SUPER_BLOCK_OFFSET
/ GRUB_DISK_SECTOR_SIZE
,
1387 REISERFS_LABEL_OFFSET
, REISERFS_MAX_LABEL_LENGTH
,
1393 static struct grub_fs grub_reiserfs_fs
=
1396 .dir
= grub_reiserfs_dir
,
1397 .open
= grub_reiserfs_open
,
1398 .read
= grub_reiserfs_read
,
1399 .close
= grub_reiserfs_close
,
1400 .label
= grub_reiserfs_label
,
1404 GRUB_MOD_INIT(reiserfs
)
1406 grub_fs_register (&grub_reiserfs_fs
);
1412 GRUB_MOD_FINI(reiserfs
)
1414 grub_fs_unregister (&grub_reiserfs_fs
);