Indentation fix, cleanup.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / fs / reiserfs.c
blobb78166554b98d6bfd1110593fac40b33989cd939
1 /* reiserfs.c - ReiserFS versions up to 3.6 */
2 /*
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/>.
21 TODO:
22 implement journal handling (ram replay)
23 test tail packing & direct files
24 validate partition label position
27 #if 0
28 # define GRUB_REISERFS_DEBUG
29 # define GRUB_REISERFS_JOURNALING
30 # define GRUB_HEXDUMP
31 #endif
33 #include <grub/err.h>
34 #include <grub/file.h>
35 #include <grub/mm.h>
36 #include <grub/misc.h>
37 #include <grub/disk.h>
38 #include <grub/dl.h>
39 #include <grub/types.h>
40 #include <grub/fshelp.h>
41 #include <grub/i18n.h>
43 GRUB_MOD_LICENSE ("GPLv3+");
45 #define MIN(a, b) \
46 ({ typeof (a) _a = (a); \
47 typeof (b) _b = (b); \
48 _a < _b ? _a : _b; })
50 #define MAX(a, b) \
51 ({ typeof (a) _a = (a); \
52 typeof (b) _b = (b); \
53 _a > _b ? _a : _b; })
55 #define REISERFS_SUPER_BLOCK_OFFSET 0x10000
56 #define REISERFS_MAGIC_LEN 12
57 #define REISERFS_MAGIC_STRING "ReIsEr"
58 #define REISERFS_MAGIC_DESC_BLOCK "ReIsErLB"
59 /* If the 3rd bit of an item state is set, then it's visible. */
60 #define GRUB_REISERFS_VISIBLE_MASK ((grub_uint16_t) 0x04)
62 #define S_IFLNK 0xA000
64 static grub_dl_t my_mod;
66 #define assert(boolean) real_assert (boolean, GRUB_FILE, __LINE__)
67 static inline void
68 real_assert (int boolean, const char *file, const int line)
70 if (! boolean)
71 grub_printf ("Assertion failed at %s:%d\n", file, line);
74 enum grub_reiserfs_item_type
76 GRUB_REISERFS_STAT,
77 GRUB_REISERFS_DIRECTORY,
78 GRUB_REISERFS_DIRECT,
79 GRUB_REISERFS_INDIRECT,
80 /* Matches both _DIRECT and _INDIRECT when searching. */
81 GRUB_REISERFS_ANY,
82 GRUB_REISERFS_UNKNOWN
85 struct grub_reiserfs_superblock
87 grub_uint32_t block_count;
88 grub_uint32_t block_free_count;
89 grub_uint32_t root_block;
90 grub_uint32_t journal_block;
91 grub_uint32_t journal_device;
92 grub_uint32_t journal_original_size;
93 grub_uint32_t journal_max_transaction_size;
94 grub_uint32_t journal_block_count;
95 grub_uint32_t journal_max_batch;
96 grub_uint32_t journal_max_commit_age;
97 grub_uint32_t journal_max_transaction_age;
98 grub_uint16_t block_size;
99 grub_uint16_t oid_max_size;
100 grub_uint16_t oid_current_size;
101 grub_uint16_t state;
102 grub_uint8_t magic_string[REISERFS_MAGIC_LEN];
103 grub_uint32_t function_hash_code;
104 grub_uint16_t tree_height;
105 grub_uint16_t bitmap_number;
106 grub_uint16_t version;
107 grub_uint16_t reserved;
108 grub_uint32_t inode_generation;
109 grub_uint8_t unused[4];
110 grub_uint16_t uuid[8];
111 char label[16];
112 } GRUB_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 } GRUB_PACKED;
121 struct grub_reiserfs_description_block
123 grub_uint32_t id;
124 grub_uint32_t len;
125 grub_uint32_t mount_id;
126 grub_uint32_t real_blocks[0];
127 } GRUB_PACKED;
129 struct grub_reiserfs_commit_block
131 grub_uint32_t id;
132 grub_uint32_t len;
133 grub_uint32_t real_blocks[0];
134 } GRUB_PACKED;
136 struct grub_reiserfs_stat_item_v1
138 grub_uint16_t mode;
139 grub_uint16_t hardlink_count;
140 grub_uint16_t uid;
141 grub_uint16_t gid;
142 grub_uint32_t size;
143 grub_uint32_t atime;
144 grub_uint32_t mtime;
145 grub_uint32_t ctime;
146 grub_uint32_t rdev;
147 grub_uint32_t first_direct_byte;
148 } GRUB_PACKED;
150 struct grub_reiserfs_stat_item_v2
152 grub_uint16_t mode;
153 grub_uint16_t reserved;
154 grub_uint32_t hardlink_count;
155 grub_uint64_t size;
156 grub_uint32_t uid;
157 grub_uint32_t gid;
158 grub_uint32_t atime;
159 grub_uint32_t mtime;
160 grub_uint32_t ctime;
161 grub_uint32_t blocks;
162 grub_uint32_t first_direct_byte;
163 } GRUB_PACKED;
165 struct grub_reiserfs_key
167 grub_uint32_t directory_id;
168 grub_uint32_t object_id;
169 union
171 struct
173 grub_uint32_t offset;
174 grub_uint32_t type;
175 } GRUB_PACKED v1;
176 struct
178 grub_uint64_t offset_type;
179 } GRUB_PACKED v2;
180 } u;
181 } GRUB_PACKED;
183 struct grub_reiserfs_item_header
185 struct grub_reiserfs_key key;
186 union
188 grub_uint16_t free_space;
189 grub_uint16_t entry_count;
190 } GRUB_PACKED u;
191 grub_uint16_t item_size;
192 grub_uint16_t item_location;
193 grub_uint16_t version;
194 } GRUB_PACKED;
196 struct grub_reiserfs_block_header
198 grub_uint16_t level;
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 } GRUB_PACKED;
205 struct grub_reiserfs_disk_child
207 grub_uint32_t block_number;
208 grub_uint16_t size;
209 grub_uint16_t reserved;
210 } GRUB_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;
218 grub_uint16_t state;
219 } GRUB_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 grub_int32_t mtime;
228 grub_off_t size;
229 enum grub_reiserfs_item_type type; /* To know how to read the header. */
230 struct grub_reiserfs_item_header header;
233 /* Returned when opening a file. */
234 struct grub_reiserfs_data
236 struct grub_reiserfs_superblock superblock;
237 grub_disk_t disk;
240 static grub_ssize_t
241 grub_reiserfs_read_real (struct grub_fshelp_node *node,
242 grub_off_t off, char *buf, grub_size_t len,
243 grub_disk_read_hook_t read_hook,
244 void *read_hook_data);
246 /* Internal-only functions. Not to be used outside of this file. */
248 /* Return the type of given v2 key. */
249 static enum grub_reiserfs_item_type
250 grub_reiserfs_get_key_v2_type (const struct grub_reiserfs_key *key)
252 switch (grub_le_to_cpu64 (key->u.v2.offset_type) >> 60)
254 case 0:
255 return GRUB_REISERFS_STAT;
256 case 15:
257 return GRUB_REISERFS_ANY;
258 case 3:
259 return GRUB_REISERFS_DIRECTORY;
260 case 2:
261 return GRUB_REISERFS_DIRECT;
262 case 1:
263 return GRUB_REISERFS_INDIRECT;
265 return GRUB_REISERFS_UNKNOWN;
268 /* Return the type of given v1 key. */
269 static enum grub_reiserfs_item_type
270 grub_reiserfs_get_key_v1_type (const struct grub_reiserfs_key *key)
272 switch (grub_le_to_cpu32 (key->u.v1.type))
274 case 0:
275 return GRUB_REISERFS_STAT;
276 case 555:
277 return GRUB_REISERFS_ANY;
278 case 500:
279 return GRUB_REISERFS_DIRECTORY;
280 case 0x20000000:
281 case 0xFFFFFFFF:
282 return GRUB_REISERFS_DIRECT;
283 case 0x10000000:
284 case 0xFFFFFFFE:
285 return GRUB_REISERFS_INDIRECT;
287 return GRUB_REISERFS_UNKNOWN;
290 /* Return 1 if the given key is version 1 key, 2 otherwise. */
291 static int
292 grub_reiserfs_get_key_version (const struct grub_reiserfs_key *key)
294 return grub_reiserfs_get_key_v1_type (key) == GRUB_REISERFS_UNKNOWN ? 2 : 1;
297 #ifdef GRUB_HEXDUMP
298 static void
299 grub_hexdump (char *buffer, grub_size_t len)
301 grub_size_t a;
302 for (a = 0; a < len; a++)
304 if (! (a & 0x0F))
305 grub_printf ("\n%08x ", a);
306 grub_printf ("%02x ",
307 ((unsigned int) ((unsigned char *) buffer)[a]) & 0xFF);
309 grub_printf ("\n");
311 #endif
313 #ifdef GRUB_REISERFS_DEBUG
314 static grub_uint64_t
315 grub_reiserfs_get_key_offset (const struct grub_reiserfs_key *key);
317 static enum grub_reiserfs_item_type
318 grub_reiserfs_get_key_type (const struct grub_reiserfs_key *key);
320 static void
321 grub_reiserfs_print_key (const struct grub_reiserfs_key *key)
323 unsigned int a;
324 char *reiserfs_type_strings[] = {
325 "stat ",
326 "directory",
327 "direct ",
328 "indirect ",
329 "any ",
330 "unknown "
333 for (a = 0; a < sizeof (struct grub_reiserfs_key); a++)
334 grub_printf ("%02x ", ((unsigned int) ((unsigned char *) key)[a]) & 0xFF);
335 grub_printf ("parent id = 0x%08x, self id = 0x%08x, type = %s, offset = ",
336 grub_le_to_cpu32 (key->directory_id),
337 grub_le_to_cpu32 (key->object_id),
338 reiserfs_type_strings [grub_reiserfs_get_key_type (key)]);
339 if (grub_reiserfs_get_key_version (key) == 1)
340 grub_printf("%08x", (unsigned int) grub_reiserfs_get_key_offset (key));
341 else
342 grub_printf("0x%07x%08x",
343 (unsigned) (grub_reiserfs_get_key_offset (key) >> 32),
344 (unsigned) (grub_reiserfs_get_key_offset (key) & 0xFFFFFFFF));
345 grub_printf ("\n");
347 #endif
349 /* Return the offset of given key. */
350 static grub_uint64_t
351 grub_reiserfs_get_key_offset (const struct grub_reiserfs_key *key)
353 if (grub_reiserfs_get_key_version (key) == 1)
354 return grub_le_to_cpu32 (key->u.v1.offset);
355 else
356 return grub_le_to_cpu64 (key->u.v2.offset_type) & (~0ULL >> 4);
359 /* Set the offset of given key. */
360 static void
361 grub_reiserfs_set_key_offset (struct grub_reiserfs_key *key,
362 grub_uint64_t value)
364 if (grub_reiserfs_get_key_version (key) == 1)
365 key->u.v1.offset = grub_cpu_to_le32 (value);
366 else
367 key->u.v2.offset_type \
368 = ((key->u.v2.offset_type & grub_cpu_to_le64_compile_time (15ULL << 60))
369 | grub_cpu_to_le64 (value & (~0ULL >> 4)));
372 /* Return the type of given key. */
373 static enum grub_reiserfs_item_type
374 grub_reiserfs_get_key_type (const struct grub_reiserfs_key *key)
376 if (grub_reiserfs_get_key_version (key) == 1)
377 return grub_reiserfs_get_key_v1_type (key);
378 else
379 return grub_reiserfs_get_key_v2_type (key);
382 /* Set the type of given key, with given version number. */
383 static void
384 grub_reiserfs_set_key_type (struct grub_reiserfs_key *key,
385 enum grub_reiserfs_item_type grub_type,
386 int version)
388 grub_uint32_t type;
390 switch (grub_type)
392 case GRUB_REISERFS_STAT:
393 type = 0;
394 break;
395 case GRUB_REISERFS_ANY:
396 type = (version == 1) ? 555 : 15;
397 break;
398 case GRUB_REISERFS_DIRECTORY:
399 type = (version == 1) ? 500 : 3;
400 break;
401 case GRUB_REISERFS_DIRECT:
402 type = (version == 1) ? 0xFFFFFFFF : 2;
403 break;
404 case GRUB_REISERFS_INDIRECT:
405 type = (version == 1) ? 0xFFFFFFFE : 1;
406 break;
407 default:
408 return;
411 if (version == 1)
412 key->u.v1.type = grub_cpu_to_le32 (type);
413 else
414 key->u.v2.offset_type
415 = ((key->u.v2.offset_type & grub_cpu_to_le64_compile_time (~0ULL >> 4))
416 | grub_cpu_to_le64 ((grub_uint64_t) type << 60));
418 assert (grub_reiserfs_get_key_type (key) == grub_type);
421 /* -1 if key 1 if lower than key 2.
422 0 if key 1 is equal to key 2.
423 1 if key 1 is higher than key 2. */
424 static int
425 grub_reiserfs_compare_keys (const struct grub_reiserfs_key *key1,
426 const struct grub_reiserfs_key *key2)
428 grub_uint64_t offset1, offset2;
429 enum grub_reiserfs_item_type type1, type2;
430 grub_uint32_t id1, id2;
432 if (! key1 || ! key2)
433 return -2;
435 id1 = grub_le_to_cpu32 (key1->directory_id);
436 id2 = grub_le_to_cpu32 (key2->directory_id);
437 if (id1 < id2)
438 return -1;
439 if (id1 > id2)
440 return 1;
442 id1 = grub_le_to_cpu32 (key1->object_id);
443 id2 = grub_le_to_cpu32 (key2->object_id);
444 if (id1 < id2)
445 return -1;
446 if (id1 > id2)
447 return 1;
449 offset1 = grub_reiserfs_get_key_offset (key1);
450 offset2 = grub_reiserfs_get_key_offset (key2);
451 if (offset1 < offset2)
452 return -1;
453 if (offset1 > offset2)
454 return 1;
456 type1 = grub_reiserfs_get_key_type (key1);
457 type2 = grub_reiserfs_get_key_type (key2);
458 if ((type1 == GRUB_REISERFS_ANY
459 && (type2 == GRUB_REISERFS_DIRECT
460 || type2 == GRUB_REISERFS_INDIRECT))
461 || (type2 == GRUB_REISERFS_ANY
462 && (type1 == GRUB_REISERFS_DIRECT
463 || type1 == GRUB_REISERFS_INDIRECT)))
464 return 0;
465 if (type1 < type2)
466 return -1;
467 if (type1 > type2)
468 return 1;
470 return 0;
473 /* Find the item identified by KEY in mounted filesystem DATA, and fill ITEM
474 accordingly to what was found. */
475 static grub_err_t
476 grub_reiserfs_get_item (struct grub_reiserfs_data *data,
477 const struct grub_reiserfs_key *key,
478 struct grub_fshelp_node *item, int exact)
480 grub_uint32_t block_number;
481 struct grub_reiserfs_block_header *block_header = 0;
482 struct grub_reiserfs_key *block_key = 0;
483 grub_uint16_t block_size, item_count, current_level;
484 grub_uint16_t i;
485 grub_uint16_t previous_level = ~0;
486 struct grub_reiserfs_item_header *item_headers = 0;
488 #if 0
489 if (! data)
491 grub_error (GRUB_ERR_BAD_FS, "data is NULL");
492 goto fail;
495 if (! key)
497 grub_error (GRUB_ERR_BAD_FS, "key is NULL");
498 goto fail;
501 if (! item)
503 grub_error (GRUB_ERR_BAD_FS, "item is NULL");
504 goto fail;
506 #endif
508 block_size = grub_le_to_cpu16 (data->superblock.block_size);
509 block_number = grub_le_to_cpu32 (data->superblock.root_block);
510 #ifdef GRUB_REISERFS_DEBUG
511 grub_printf("Searching for ");
512 grub_reiserfs_print_key (key);
513 #endif
514 block_header = grub_malloc (block_size);
515 if (! block_header)
516 goto fail;
518 item->next_offset = 0;
521 grub_disk_read (data->disk,
522 block_number * (block_size >> GRUB_DISK_SECTOR_BITS),
523 (((grub_off_t) block_number * block_size)
524 & (GRUB_DISK_SECTOR_SIZE - 1)),
525 block_size, block_header);
526 if (grub_errno)
527 goto fail;
528 current_level = grub_le_to_cpu16 (block_header->level);
529 grub_dprintf ("reiserfs_tree", " at level %d\n", current_level);
530 if (current_level >= previous_level)
532 grub_dprintf ("reiserfs_tree", "level loop detected, aborting\n");
533 grub_error (GRUB_ERR_BAD_FS, "level loop");
534 goto fail;
536 previous_level = current_level;
537 item_count = grub_le_to_cpu16 (block_header->item_count);
538 grub_dprintf ("reiserfs_tree", " number of contained items : %d\n",
539 item_count);
540 if (current_level > 1)
542 /* Internal node. Navigate to the child that should contain
543 the searched key. */
544 struct grub_reiserfs_key *keys
545 = (struct grub_reiserfs_key *) (block_header + 1);
546 struct grub_reiserfs_disk_child *children
547 = ((struct grub_reiserfs_disk_child *)
548 (keys + item_count));
550 for (i = 0;
551 i < item_count
552 && grub_reiserfs_compare_keys (key, &(keys[i])) >= 0;
553 i++)
555 #ifdef GRUB_REISERFS_DEBUG
556 grub_printf("i %03d/%03d ", i + 1, item_count + 1);
557 grub_reiserfs_print_key (&(keys[i]));
558 #endif
560 block_number = grub_le_to_cpu32 (children[i].block_number);
561 if ((i < item_count) && (key->directory_id == keys[i].directory_id)
562 && (key->object_id == keys[i].object_id))
563 item->next_offset = grub_reiserfs_get_key_offset(&(keys[i]));
564 #ifdef GRUB_REISERFS_DEBUG
565 if (i == item_count
566 || grub_reiserfs_compare_keys (key, &(keys[i])) == 0)
567 grub_printf(">");
568 else
569 grub_printf("<");
570 if (i < item_count)
572 grub_printf (" %03d/%03d ", i + 1, item_count + 1);
573 grub_reiserfs_print_key (&(keys[i]));
574 if (i + 1 < item_count)
576 grub_printf ("+ %03d/%03d ", i + 2, item_count);
577 grub_reiserfs_print_key (&(keys[i + 1]));
580 else
581 grub_printf ("Accessing rightmost child at block %d.\n",
582 block_number);
583 #endif
585 else
587 /* Leaf node. Check that the key is actually present. */
588 item_headers
589 = (struct grub_reiserfs_item_header *) (block_header + 1);
590 for (i = 0;
591 i < item_count;
592 i++)
594 int val;
595 val = grub_reiserfs_compare_keys (key, &(item_headers[i].key));
596 if (val == 0)
598 block_key = &(item_headers[i].key);
599 break;
601 if (val < 0 && exact)
602 break;
603 if (val < 0)
605 if (i == 0)
607 grub_error (GRUB_ERR_READ_ERROR, "unexpected btree node");
608 goto fail;
610 i--;
611 block_key = &(item_headers[i].key);
612 break;
615 if (!exact && i == item_count)
617 if (i == 0)
619 grub_error (GRUB_ERR_READ_ERROR, "unexpected btree node");
620 goto fail;
622 i--;
623 block_key = &(item_headers[i].key);
627 while (current_level > 1);
629 item->data = data;
631 if (!block_key)
633 item->block_number = 0;
634 item->block_position = 0;
635 item->type = GRUB_REISERFS_UNKNOWN;
636 #ifdef GRUB_REISERFS_DEBUG
637 grub_printf("Not found.\n");
638 #endif
640 else
642 item->block_number = block_number;
643 item->block_position = i;
644 item->type = grub_reiserfs_get_key_type (block_key);
645 grub_memcpy (&(item->header), &(item_headers[i]),
646 sizeof (struct grub_reiserfs_item_header));
647 #ifdef GRUB_REISERFS_DEBUG
648 grub_printf ("F %03d/%03d ", i + 1, item_count);
649 grub_reiserfs_print_key (block_key);
650 #endif
653 assert (grub_errno == GRUB_ERR_NONE);
654 grub_free (block_header);
655 return GRUB_ERR_NONE;
657 fail:
658 assert (grub_errno != GRUB_ERR_NONE);
659 grub_free (block_header);
660 assert (grub_errno != GRUB_ERR_NONE);
661 return grub_errno;
664 /* Return the path of the file which is pointed at by symlink NODE. */
665 static char *
666 grub_reiserfs_read_symlink (grub_fshelp_node_t node)
668 char *symlink_buffer = 0;
669 grub_size_t len = node->size;
670 grub_ssize_t ret;
672 symlink_buffer = grub_malloc (len + 1);
673 if (! symlink_buffer)
674 return 0;
676 ret = grub_reiserfs_read_real (node, 0, symlink_buffer, len, 0, 0);
677 if (ret < 0)
679 grub_free (symlink_buffer);
680 return 0;
683 symlink_buffer[ret] = 0;
684 return symlink_buffer;
687 /* Fill the mounted filesystem structure and return it. */
688 static struct grub_reiserfs_data *
689 grub_reiserfs_mount (grub_disk_t disk)
691 struct grub_reiserfs_data *data = 0;
692 data = grub_malloc (sizeof (*data));
693 if (! data)
694 goto fail;
695 grub_disk_read (disk, REISERFS_SUPER_BLOCK_OFFSET / GRUB_DISK_SECTOR_SIZE,
696 0, sizeof (data->superblock), &(data->superblock));
697 if (grub_errno)
698 goto fail;
699 if (grub_memcmp (data->superblock.magic_string,
700 REISERFS_MAGIC_STRING, sizeof (REISERFS_MAGIC_STRING) - 1))
702 grub_error (GRUB_ERR_BAD_FS, "not a ReiserFS filesystem");
703 goto fail;
705 data->disk = disk;
706 return data;
708 fail:
709 /* Disk is too small to contain a ReiserFS. */
710 if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
711 grub_error (GRUB_ERR_BAD_FS, "not a ReiserFS filesystem");
713 grub_free (data);
714 return 0;
717 /* Call HOOK for each file in directory ITEM. */
718 static int
719 grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
720 grub_fshelp_iterate_dir_hook_t hook,
721 void *hook_data)
723 struct grub_reiserfs_data *data = item->data;
724 struct grub_reiserfs_block_header *block_header = 0;
725 grub_uint16_t block_size, block_position;
726 grub_uint32_t block_number;
727 grub_uint64_t next_offset = item->next_offset;
728 int ret = 0;
730 if (item->type != GRUB_REISERFS_DIRECTORY)
732 grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
733 goto fail;
735 block_size = grub_le_to_cpu16 (data->superblock.block_size);
736 block_header = grub_malloc (block_size + 1);
737 if (! block_header)
738 goto fail;
739 block_number = item->block_number;
740 block_position = item->block_position;
741 grub_dprintf ("reiserfs", "Iterating directory...\n");
744 struct grub_reiserfs_directory_header *directory_headers;
745 struct grub_fshelp_node directory_item;
746 grub_uint16_t entry_count, entry_number;
747 struct grub_reiserfs_item_header *item_headers;
749 grub_disk_read (data->disk,
750 block_number * (block_size >> GRUB_DISK_SECTOR_BITS),
751 (((grub_off_t) block_number * block_size)
752 & (GRUB_DISK_SECTOR_SIZE - 1)),
753 block_size, (char *) block_header);
754 if (grub_errno)
755 goto fail;
757 ((char *) block_header)[block_size] = 0;
759 #if 0
760 if (grub_le_to_cpu16 (block_header->level) != 1)
762 grub_error (GRUB_ERR_BAD_FS,
763 "reiserfs: block %d is not a leaf block",
764 block_number);
765 goto fail;
767 #endif
769 item_headers = (struct grub_reiserfs_item_header *) (block_header + 1);
770 directory_headers
771 = ((struct grub_reiserfs_directory_header *)
772 ((char *) block_header
773 + grub_le_to_cpu16 (item_headers[block_position].item_location)));
774 entry_count
775 = grub_le_to_cpu16 (item_headers[block_position].u.entry_count);
776 for (entry_number = 0; entry_number < entry_count; entry_number++)
778 struct grub_reiserfs_directory_header *directory_header
779 = &directory_headers[entry_number];
780 grub_uint16_t entry_state
781 = grub_le_to_cpu16 (directory_header->state);
782 grub_fshelp_node_t entry_item;
783 struct grub_reiserfs_key entry_key;
784 enum grub_fshelp_filetype entry_type;
785 char *entry_name;
787 if (!(entry_state & GRUB_REISERFS_VISIBLE_MASK))
788 continue;
790 entry_name = (((char *) directory_headers)
791 + grub_le_to_cpu16 (directory_header->location));
792 entry_key.directory_id = directory_header->directory_id;
793 entry_key.object_id = directory_header->object_id;
794 entry_key.u.v2.offset_type = 0;
795 grub_reiserfs_set_key_type (&entry_key, GRUB_REISERFS_DIRECTORY,
797 grub_reiserfs_set_key_offset (&entry_key, 1);
799 entry_item = grub_malloc (sizeof (*entry_item));
800 if (! entry_item)
801 goto fail;
803 if (grub_reiserfs_get_item (data, &entry_key, entry_item, 1)
804 != GRUB_ERR_NONE)
806 grub_free (entry_item);
807 goto fail;
810 if (entry_item->type == GRUB_REISERFS_DIRECTORY)
811 entry_type = GRUB_FSHELP_DIR;
812 else
814 grub_uint32_t entry_block_number;
815 /* Order is very important here.
816 First set the offset to 0 using current key version.
817 Then change the key type, which affects key version
818 detection. */
819 grub_reiserfs_set_key_offset (&entry_key, 0);
820 grub_reiserfs_set_key_type (&entry_key, GRUB_REISERFS_STAT,
822 if (grub_reiserfs_get_item (data, &entry_key, entry_item, 1)
823 != GRUB_ERR_NONE)
825 grub_free (entry_item);
826 goto fail;
829 if (entry_item->block_number != 0)
831 grub_uint16_t entry_version;
832 entry_version
833 = grub_le_to_cpu16 (entry_item->header.version);
834 entry_block_number = entry_item->block_number;
835 #if 0
836 grub_dprintf ("reiserfs",
837 "version %04x block %08x (%08x) position %08x\n",
838 entry_version, entry_block_number,
839 ((grub_disk_addr_t) entry_block_number * block_size) / GRUB_DISK_SECTOR_SIZE,
840 grub_le_to_cpu16 (entry_item->header.item_location));
841 #endif
842 if (entry_version == 0) /* Version 1 stat item. */
844 struct grub_reiserfs_stat_item_v1 entry_v1_stat;
845 grub_disk_read (data->disk,
846 entry_block_number * (block_size >> GRUB_DISK_SECTOR_BITS),
847 grub_le_to_cpu16 (entry_item->header.item_location),
848 sizeof (entry_v1_stat),
849 (char *) &entry_v1_stat);
850 if (grub_errno)
851 goto fail;
852 #if 0
853 grub_dprintf ("reiserfs",
854 "%04x %04x %04x %04x %08x %08x | %08x %08x %08x %08x\n",
855 grub_le_to_cpu16 (entry_v1_stat.mode),
856 grub_le_to_cpu16 (entry_v1_stat.hardlink_count),
857 grub_le_to_cpu16 (entry_v1_stat.uid),
858 grub_le_to_cpu16 (entry_v1_stat.gid),
859 grub_le_to_cpu32 (entry_v1_stat.size),
860 grub_le_to_cpu32 (entry_v1_stat.atime),
861 grub_le_to_cpu32 (entry_v1_stat.mtime),
862 grub_le_to_cpu32 (entry_v1_stat.ctime),
863 grub_le_to_cpu32 (entry_v1_stat.rdev),
864 grub_le_to_cpu32 (entry_v1_stat.first_direct_byte));
865 grub_dprintf ("reiserfs",
866 "%04x %04x %04x %04x %08x %08x | %08x %08x %08x %08x\n",
867 entry_v1_stat.mode,
868 entry_v1_stat.hardlink_count,
869 entry_v1_stat.uid,
870 entry_v1_stat.gid,
871 entry_v1_stat.size,
872 entry_v1_stat.atime,
873 entry_v1_stat.mtime,
874 entry_v1_stat.ctime,
875 entry_v1_stat.rdev,
876 entry_v1_stat.first_direct_byte);
877 #endif
878 entry_item->mtime = grub_le_to_cpu32 (entry_v1_stat.mtime);
879 if ((grub_le_to_cpu16 (entry_v1_stat.mode) & S_IFLNK)
880 == S_IFLNK)
881 entry_type = GRUB_FSHELP_SYMLINK;
882 else
883 entry_type = GRUB_FSHELP_REG;
884 entry_item->size = (grub_off_t) grub_le_to_cpu32 (entry_v1_stat.size);
886 else
888 struct grub_reiserfs_stat_item_v2 entry_v2_stat;
889 grub_disk_read (data->disk,
890 entry_block_number * (block_size >> GRUB_DISK_SECTOR_BITS),
891 grub_le_to_cpu16 (entry_item->header.item_location),
892 sizeof (entry_v2_stat),
893 (char *) &entry_v2_stat);
894 if (grub_errno)
895 goto fail;
896 #if 0
897 grub_dprintf ("reiserfs",
898 "%04x %04x %08x %08x%08x | %08x %08x %08x %08x | %08x %08x %08x\n",
899 grub_le_to_cpu16 (entry_v2_stat.mode),
900 grub_le_to_cpu16 (entry_v2_stat.reserved),
901 grub_le_to_cpu32 (entry_v2_stat.hardlink_count),
902 (unsigned int) (grub_le_to_cpu64 (entry_v2_stat.size) >> 32),
903 (unsigned int) (grub_le_to_cpu64 (entry_v2_stat.size) && 0xFFFFFFFF),
904 grub_le_to_cpu32 (entry_v2_stat.uid),
905 grub_le_to_cpu32 (entry_v2_stat.gid),
906 grub_le_to_cpu32 (entry_v2_stat.atime),
907 grub_le_to_cpu32 (entry_v2_stat.mtime),
908 grub_le_to_cpu32 (entry_v2_stat.ctime),
909 grub_le_to_cpu32 (entry_v2_stat.blocks),
910 grub_le_to_cpu32 (entry_v2_stat.first_direct_byte));
911 grub_dprintf ("reiserfs",
912 "%04x %04x %08x %08x%08x | %08x %08x %08x %08x | %08x %08x %08x\n",
913 entry_v2_stat.mode,
914 entry_v2_stat.reserved,
915 entry_v2_stat.hardlink_count,
916 (unsigned int) (entry_v2_stat.size >> 32),
917 (unsigned int) (entry_v2_stat.size && 0xFFFFFFFF),
918 entry_v2_stat.uid,
919 entry_v2_stat.gid,
920 entry_v2_stat.atime,
921 entry_v2_stat.mtime,
922 entry_v2_stat.ctime,
923 entry_v2_stat.blocks,
924 entry_v2_stat.first_direct_byte);
925 #endif
926 entry_item->mtime = grub_le_to_cpu32 (entry_v2_stat.mtime);
927 entry_item->size = (grub_off_t) grub_le_to_cpu64 (entry_v2_stat.size);
928 if ((grub_le_to_cpu16 (entry_v2_stat.mode) & S_IFLNK)
929 == S_IFLNK)
930 entry_type = GRUB_FSHELP_SYMLINK;
931 else
932 entry_type = GRUB_FSHELP_REG;
935 else
937 /* Pseudo file ".." never has stat block. */
938 if (grub_strcmp (entry_name, ".."))
939 grub_dprintf ("reiserfs",
940 "Warning : %s has no stat block !\n",
941 entry_name);
942 grub_free (entry_item);
943 goto next;
946 if (hook (entry_name, entry_type, entry_item, hook_data))
948 grub_dprintf ("reiserfs", "Found : %s, type=%d\n",
949 entry_name, entry_type);
950 ret = 1;
951 goto found;
954 next:
955 *entry_name = 0; /* Make sure next entry name (which is just
956 before this one in disk order) stops before
957 the current one. */
960 if (next_offset == 0)
961 break;
963 grub_reiserfs_set_key_offset (&(item_headers[block_position].key),
964 next_offset);
965 if (grub_reiserfs_get_item (data, &(item_headers[block_position].key),
966 &directory_item, 1) != GRUB_ERR_NONE)
967 goto fail;
968 block_number = directory_item.block_number;
969 block_position = directory_item.block_position;
970 next_offset = directory_item.next_offset;
972 while (block_number);
974 found:
975 assert (grub_errno == GRUB_ERR_NONE);
976 grub_free (block_header);
977 return ret;
978 fail:
979 assert (grub_errno != GRUB_ERR_NONE);
980 grub_free (block_header);
981 return 0;
984 /****************************************************************************/
985 /* grub api functions */
986 /****************************************************************************/
988 /* Open a file named NAME and initialize FILE. */
989 static grub_err_t
990 grub_reiserfs_open (struct grub_file *file, const char *name)
992 struct grub_reiserfs_data *data = 0;
993 struct grub_fshelp_node root, *found = 0;
994 struct grub_reiserfs_key key;
996 grub_dl_ref (my_mod);
997 data = grub_reiserfs_mount (file->device->disk);
998 if (! data)
999 goto fail;
1000 key.directory_id = grub_cpu_to_le32_compile_time (1);
1001 key.object_id = grub_cpu_to_le32_compile_time (2);
1002 key.u.v2.offset_type = 0;
1003 grub_reiserfs_set_key_type (&key, GRUB_REISERFS_DIRECTORY, 2);
1004 grub_reiserfs_set_key_offset (&key, 1);
1005 if (grub_reiserfs_get_item (data, &key, &root, 1) != GRUB_ERR_NONE)
1006 goto fail;
1007 if (root.block_number == 0)
1009 grub_error (GRUB_ERR_BAD_FS, "unable to find root item");
1010 goto fail; /* Should never happen since checked at mount. */
1012 grub_fshelp_find_file (name, &root, &found,
1013 grub_reiserfs_iterate_dir,
1014 grub_reiserfs_read_symlink, GRUB_FSHELP_REG);
1015 if (grub_errno)
1016 goto fail;
1017 file->size = found->size;
1019 grub_dprintf ("reiserfs", "file size : %d (%08x%08x)\n",
1020 (unsigned int) file->size,
1021 (unsigned int) (file->size >> 32), (unsigned int) file->size);
1022 file->offset = 0;
1023 file->data = found;
1024 return GRUB_ERR_NONE;
1026 fail:
1027 assert (grub_errno != GRUB_ERR_NONE);
1028 if (found != &root)
1029 grub_free (found);
1030 grub_free (data);
1031 grub_dl_unref (my_mod);
1032 return grub_errno;
1035 static grub_ssize_t
1036 grub_reiserfs_read_real (struct grub_fshelp_node *node,
1037 grub_off_t off, char *buf, grub_size_t len,
1038 grub_disk_read_hook_t read_hook, void *read_hook_data)
1040 unsigned int indirect_block, indirect_block_count;
1041 struct grub_reiserfs_key key;
1042 struct grub_reiserfs_data *data = node->data;
1043 struct grub_fshelp_node found;
1044 grub_uint16_t block_size = grub_le_to_cpu16 (data->superblock.block_size);
1045 grub_uint16_t item_size;
1046 grub_uint32_t *indirect_block_ptr = 0;
1047 grub_uint64_t current_key_offset = 1;
1048 grub_off_t initial_position, current_position, final_position, length;
1049 grub_disk_addr_t block;
1050 grub_off_t offset;
1052 key.directory_id = node->header.key.directory_id;
1053 key.object_id = node->header.key.object_id;
1054 key.u.v2.offset_type = 0;
1055 grub_reiserfs_set_key_type (&key, GRUB_REISERFS_ANY, 2);
1056 initial_position = off;
1057 current_position = 0;
1058 final_position = MIN (len + initial_position, node->size);
1059 grub_dprintf ("reiserfs",
1060 "Reading from %lld to %lld (%lld instead of requested %ld)\n",
1061 (unsigned long long) initial_position,
1062 (unsigned long long) final_position,
1063 (unsigned long long) (final_position - initial_position),
1064 (unsigned long) len);
1066 grub_reiserfs_set_key_offset (&key, initial_position + 1);
1068 if (grub_reiserfs_get_item (data, &key, &found, 0) != GRUB_ERR_NONE)
1069 goto fail;
1071 if (found.block_number == 0)
1073 grub_error (GRUB_ERR_READ_ERROR, "offset %lld not found",
1074 (unsigned long long) initial_position);
1075 goto fail;
1078 current_key_offset = grub_reiserfs_get_key_offset (&found.header.key);
1079 current_position = current_key_offset - 1;
1081 while (current_position < final_position)
1083 grub_reiserfs_set_key_offset (&key, current_key_offset);
1085 if (grub_reiserfs_get_item (data, &key, &found, 1) != GRUB_ERR_NONE)
1086 goto fail;
1087 if (found.block_number == 0)
1088 goto fail;
1089 item_size = grub_le_to_cpu16 (found.header.item_size);
1090 switch (found.type)
1092 case GRUB_REISERFS_DIRECT:
1093 block = ((grub_disk_addr_t) found.block_number) * (block_size >> GRUB_DISK_SECTOR_BITS);
1094 grub_dprintf ("reiserfs_blocktype", "D: %u\n", (unsigned) block);
1095 if (initial_position < current_position + item_size)
1097 offset = MAX ((signed) (initial_position - current_position), 0);
1098 length = (MIN (item_size, final_position - current_position)
1099 - offset);
1100 grub_dprintf ("reiserfs",
1101 "Reading direct block %u from %u to %u...\n",
1102 (unsigned) block, (unsigned) offset,
1103 (unsigned) (offset + length));
1104 found.data->disk->read_hook = read_hook;
1105 found.data->disk->read_hook_data = read_hook_data;
1106 grub_disk_read (found.data->disk,
1107 block,
1108 offset
1109 + grub_le_to_cpu16 (found.header.item_location),
1110 length, buf);
1111 found.data->disk->read_hook = 0;
1112 if (grub_errno)
1113 goto fail;
1114 buf += length;
1115 current_position += offset + length;
1117 else
1118 current_position += item_size;
1119 break;
1120 case GRUB_REISERFS_INDIRECT:
1121 indirect_block_count = item_size / sizeof (*indirect_block_ptr);
1122 indirect_block_ptr = grub_malloc (item_size);
1123 if (! indirect_block_ptr)
1124 goto fail;
1125 grub_disk_read (found.data->disk,
1126 found.block_number * (block_size >> GRUB_DISK_SECTOR_BITS),
1127 grub_le_to_cpu16 (found.header.item_location),
1128 item_size, indirect_block_ptr);
1129 if (grub_errno)
1130 goto fail;
1131 found.data->disk->read_hook = read_hook;
1132 found.data->disk->read_hook_data = read_hook_data;
1133 for (indirect_block = 0;
1134 indirect_block < indirect_block_count
1135 && current_position < final_position;
1136 indirect_block++)
1138 block = grub_le_to_cpu32 (indirect_block_ptr[indirect_block]) *
1139 (block_size >> GRUB_DISK_SECTOR_BITS);
1140 grub_dprintf ("reiserfs_blocktype", "I: %u\n", (unsigned) block);
1141 if (current_position + block_size >= initial_position)
1143 offset = MAX ((signed) (initial_position - current_position),
1145 length = (MIN (block_size, final_position - current_position)
1146 - offset);
1147 grub_dprintf ("reiserfs",
1148 "Reading indirect block %u from %u to %u...\n",
1149 (unsigned) block, (unsigned) offset,
1150 (unsigned) (offset + length));
1151 #if 0
1152 grub_dprintf ("reiserfs",
1153 "\nib=%04d/%04d, ip=%d, cp=%d, fp=%d, off=%d, l=%d, tl=%d\n",
1154 indirect_block + 1, indirect_block_count,
1155 initial_position, current_position,
1156 final_position, offset, length, len);
1157 #endif
1158 grub_disk_read (found.data->disk, block, offset, length, buf);
1159 if (grub_errno)
1160 goto fail;
1161 buf += length;
1162 current_position += offset + length;
1164 else
1165 current_position += block_size;
1167 found.data->disk->read_hook = 0;
1168 grub_free (indirect_block_ptr);
1169 indirect_block_ptr = 0;
1170 break;
1171 default:
1172 goto fail;
1174 current_key_offset = current_position + 1;
1177 grub_dprintf ("reiserfs",
1178 "Have successfully read %lld bytes (%ld requested)\n",
1179 (unsigned long long) (current_position - initial_position),
1180 (unsigned long) len);
1181 return current_position - initial_position;
1183 #if 0
1184 switch (found.type)
1186 case GRUB_REISERFS_DIRECT:
1187 read_length = MIN (len, item_size - file->offset);
1188 grub_disk_read (found.data->disk,
1189 (found.block_number * block_size) / GRUB_DISK_SECTOR_SIZE,
1190 grub_le_to_cpu16 (found.header.item_location) + file->offset,
1191 read_length, buf);
1192 if (grub_errno)
1193 goto fail;
1194 break;
1195 case GRUB_REISERFS_INDIRECT:
1196 indirect_block_count = item_size / sizeof (*indirect_block_ptr);
1197 indirect_block_ptr = grub_malloc (item_size);
1198 if (!indirect_block_ptr)
1199 goto fail;
1200 grub_disk_read (found.data->disk,
1201 (found.block_number * block_size) / GRUB_DISK_SECTOR_SIZE,
1202 grub_le_to_cpu16 (found.header.item_location),
1203 item_size, (char *) indirect_block_ptr);
1204 if (grub_errno)
1205 goto fail;
1206 len = MIN (len, file->size - file->offset);
1207 for (indirect_block = file->offset / block_size;
1208 indirect_block < indirect_block_count && read_length < len;
1209 indirect_block++)
1211 read = MIN (block_size, len - read_length);
1212 grub_disk_read (found.data->disk,
1213 (grub_le_to_cpu32 (indirect_block_ptr[indirect_block]) * block_size) / GRUB_DISK_SECTOR_SIZE,
1214 file->offset % block_size, read,
1215 ((void *) buf) + read_length);
1216 if (grub_errno)
1217 goto fail;
1218 read_length += read;
1220 grub_free (indirect_block_ptr);
1221 break;
1222 default:
1223 goto fail;
1226 return read_length;
1227 #endif
1229 fail:
1230 grub_free (indirect_block_ptr);
1231 return -1;
1234 static grub_ssize_t
1235 grub_reiserfs_read (grub_file_t file, char *buf, grub_size_t len)
1237 return grub_reiserfs_read_real (file->data, file->offset, buf, len,
1238 file->read_hook, file->read_hook_data);
1241 /* Close the file FILE. */
1242 static grub_err_t
1243 grub_reiserfs_close (grub_file_t file)
1245 struct grub_fshelp_node *node = file->data;
1246 struct grub_reiserfs_data *data = node->data;
1248 grub_free (data);
1249 grub_free (node);
1250 grub_dl_unref (my_mod);
1251 return GRUB_ERR_NONE;
1254 /* Context for grub_reiserfs_dir. */
1255 struct grub_reiserfs_dir_ctx
1257 grub_fs_dir_hook_t hook;
1258 void *hook_data;
1261 /* Helper for grub_reiserfs_dir. */
1262 static int
1263 grub_reiserfs_dir_iter (const char *filename,
1264 enum grub_fshelp_filetype filetype,
1265 grub_fshelp_node_t node, void *data)
1267 struct grub_reiserfs_dir_ctx *ctx = data;
1268 struct grub_dirhook_info info;
1270 grub_memset (&info, 0, sizeof (info));
1271 info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
1272 info.mtimeset = 1;
1273 info.mtime = node->mtime;
1274 grub_free (node);
1275 return ctx->hook (filename, &info, ctx->hook_data);
1278 /* Call HOOK with each file under DIR. */
1279 static grub_err_t
1280 grub_reiserfs_dir (grub_device_t device, const char *path,
1281 grub_fs_dir_hook_t hook, void *hook_data)
1283 struct grub_reiserfs_dir_ctx ctx = { hook, hook_data };
1284 struct grub_reiserfs_data *data = 0;
1285 struct grub_fshelp_node root, *found;
1286 struct grub_reiserfs_key root_key;
1288 grub_dl_ref (my_mod);
1289 data = grub_reiserfs_mount (device->disk);
1290 if (! data)
1291 goto fail;
1292 root_key.directory_id = grub_cpu_to_le32_compile_time (1);
1293 root_key.object_id = grub_cpu_to_le32_compile_time (2);
1294 root_key.u.v2.offset_type = 0;
1295 grub_reiserfs_set_key_type (&root_key, GRUB_REISERFS_DIRECTORY, 2);
1296 grub_reiserfs_set_key_offset (&root_key, 1);
1297 if (grub_reiserfs_get_item (data, &root_key, &root, 1) != GRUB_ERR_NONE)
1298 goto fail;
1299 if (root.block_number == 0)
1301 grub_error(GRUB_ERR_BAD_FS, "root not found");
1302 goto fail;
1304 grub_fshelp_find_file (path, &root, &found, grub_reiserfs_iterate_dir,
1305 grub_reiserfs_read_symlink, GRUB_FSHELP_DIR);
1306 if (grub_errno)
1307 goto fail;
1308 grub_reiserfs_iterate_dir (found, grub_reiserfs_dir_iter, &ctx);
1309 grub_free (data);
1310 grub_dl_unref (my_mod);
1311 return GRUB_ERR_NONE;
1313 fail:
1314 grub_free (data);
1315 grub_dl_unref (my_mod);
1316 return grub_errno;
1319 /* Return the label of the device DEVICE in LABEL. The label is
1320 returned in a grub_malloc'ed buffer and should be freed by the
1321 caller. */
1322 static grub_err_t
1323 grub_reiserfs_label (grub_device_t device, char **label)
1325 struct grub_reiserfs_data *data;
1326 grub_disk_t disk = device->disk;
1328 grub_dl_ref (my_mod);
1330 data = grub_reiserfs_mount (disk);
1331 if (data)
1333 *label = grub_strndup (data->superblock.label,
1334 sizeof (data->superblock.label));
1336 else
1337 *label = NULL;
1339 grub_dl_unref (my_mod);
1341 grub_free (data);
1343 return grub_errno;
1346 static grub_err_t
1347 grub_reiserfs_uuid (grub_device_t device, char **uuid)
1349 struct grub_reiserfs_data *data;
1350 grub_disk_t disk = device->disk;
1352 grub_dl_ref (my_mod);
1354 *uuid = NULL;
1355 data = grub_reiserfs_mount (disk);
1356 if (data)
1358 unsigned i;
1359 for (i = 0; i < ARRAY_SIZE (data->superblock.uuid); i++)
1360 if (data->superblock.uuid[i])
1361 break;
1362 if (i < ARRAY_SIZE (data->superblock.uuid))
1363 *uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
1364 grub_be_to_cpu16 (data->superblock.uuid[0]),
1365 grub_be_to_cpu16 (data->superblock.uuid[1]),
1366 grub_be_to_cpu16 (data->superblock.uuid[2]),
1367 grub_be_to_cpu16 (data->superblock.uuid[3]),
1368 grub_be_to_cpu16 (data->superblock.uuid[4]),
1369 grub_be_to_cpu16 (data->superblock.uuid[5]),
1370 grub_be_to_cpu16 (data->superblock.uuid[6]),
1371 grub_be_to_cpu16 (data->superblock.uuid[7]));
1374 grub_dl_unref (my_mod);
1376 grub_free (data);
1378 return grub_errno;
1381 static struct grub_fs grub_reiserfs_fs =
1383 .name = "reiserfs",
1384 .dir = grub_reiserfs_dir,
1385 .open = grub_reiserfs_open,
1386 .read = grub_reiserfs_read,
1387 .close = grub_reiserfs_close,
1388 .label = grub_reiserfs_label,
1389 .uuid = grub_reiserfs_uuid,
1390 #ifdef GRUB_UTIL
1391 .reserved_first_sector = 1,
1392 .blocklist_install = 1,
1393 #endif
1394 .next = 0
1397 GRUB_MOD_INIT(reiserfs)
1399 grub_fs_register (&grub_reiserfs_fs);
1400 my_mod = mod;
1403 GRUB_MOD_FINI(reiserfs)
1405 grub_fs_unregister (&grub_reiserfs_fs);