2009-04-13 Felix Zielcke <fzielcke@z-51.de>
[grub2/phcoder.git] / fs / reiserfs.c
blob433e89b019927ed1ada489515837bb09862e8637
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>
42 #define MIN(a, b) \
43 ({ typeof (a) _a = (a); \
44 typeof (b) _b = (b); \
45 _a < _b ? _a : _b; })
47 #define MAX(a, b) \
48 ({ typeof (a) _a = (a); \
49 typeof (b) _b = (b); \
50 _a > _b ? _a : _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
63 #ifndef GRUB_UTIL
64 static grub_dl_t my_mod;
65 #endif
67 #define assert(boolean) real_assert (boolean, __FILE__, __LINE__)
68 static inline void
69 real_assert (int boolean, const char *file, const int line)
71 if (! boolean)
72 grub_printf ("Assertion failed at %s:%d\n", file, line);
75 enum grub_reiserfs_item_type
77 GRUB_REISERFS_STAT,
78 GRUB_REISERFS_DIRECTORY,
79 GRUB_REISERFS_DIRECT,
80 GRUB_REISERFS_INDIRECT,
81 /* Matches both _DIRECT and _INDIRECT when searching. */
82 GRUB_REISERFS_ANY,
83 GRUB_REISERFS_UNKNOWN
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;
102 grub_uint16_t state;
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
123 grub_uint32_t id;
124 grub_uint32_t len;
125 grub_uint32_t mount_id;
126 grub_uint32_t real_blocks[0];
127 } __attribute__ ((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 } __attribute__ ((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 } __attribute__ ((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 } __attribute__ ((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 } v1 __attribute__ ((packed));
176 struct
178 grub_uint64_t offset_type;
179 } v2 __attribute__ ((packed));
180 } u;
181 } __attribute__ ((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 } 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
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 } __attribute__ ((packed));
205 struct grub_reiserfs_disk_child
207 grub_uint32_t block_number;
208 grub_uint16_t size;
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;
218 grub_uint16_t state;
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;
235 grub_disk_t disk;
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)
246 case 0:
247 return GRUB_REISERFS_STAT;
248 case 15:
249 return GRUB_REISERFS_ANY;
250 case 3:
251 return GRUB_REISERFS_DIRECTORY;
252 case 2:
253 return GRUB_REISERFS_DIRECT;
254 case 1:
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))
266 case 0:
267 return GRUB_REISERFS_STAT;
268 case 555:
269 return GRUB_REISERFS_ANY;
270 case 500:
271 return GRUB_REISERFS_DIRECTORY;
272 case 0x20000000:
273 case 0xFFFFFFFF:
274 return GRUB_REISERFS_DIRECT;
275 case 0x10000000:
276 case 0xFFFFFFFE:
277 return GRUB_REISERFS_INDIRECT;
279 return GRUB_REISERFS_UNKNOWN;
282 /* Return 1 if the given key is version 1 key, 2 otherwise. */
283 static int
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;
289 #ifdef GRUB_HEXDUMP
290 static void
291 grub_hexdump (char *buffer, grub_size_t len)
293 grub_size_t a;
294 for (a = 0; a < len; a++)
296 if (! (a & 0x0F))
297 grub_printf ("\n%08x ", a);
298 grub_printf ("%02x ",
299 ((unsigned int) ((unsigned char *) buffer)[a]) & 0xFF);
301 grub_printf ("\n");
303 #endif
305 #ifdef GRUB_REISERFS_DEBUG
306 static grub_uint64_t
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);
312 static void
313 grub_reiserfs_print_key (const struct grub_reiserfs_key *key)
315 unsigned int a;
316 char *reiserfs_type_strings[] = {
317 "stat ",
318 "directory",
319 "direct ",
320 "indirect ",
321 "any ",
322 "unknown "
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));
333 else
334 grub_printf("0x%07x%08x",
335 (unsigned) (grub_reiserfs_get_key_offset (key) >> 32),
336 (unsigned) (grub_reiserfs_get_key_offset (key) & 0xFFFFFFFF));
337 grub_printf ("\n");
339 #endif
341 /* Return the offset of given key. */
342 static grub_uint64_t
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);
347 else
348 return grub_le_to_cpu64 (key->u.v2.offset_type) & (~0ULL >> 4);
351 /* Set the offset of given key. */
352 static void
353 grub_reiserfs_set_key_offset (struct grub_reiserfs_key *key,
354 grub_uint64_t value)
356 if (grub_reiserfs_get_key_version (key) == 1)
357 key->u.v1.offset = grub_cpu_to_le32 (value);
358 else
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);
370 else
371 return grub_reiserfs_get_key_v2_type (key);
374 /* Set the type of given key, with given version number. */
375 static void
376 grub_reiserfs_set_key_type (struct grub_reiserfs_key *key,
377 enum grub_reiserfs_item_type grub_type,
378 int version)
380 grub_uint32_t type;
382 switch (grub_type)
384 case GRUB_REISERFS_STAT:
385 type = 0;
386 break;
387 case GRUB_REISERFS_ANY:
388 type = (version == 1) ? 555 : 15;
389 break;
390 case GRUB_REISERFS_DIRECTORY:
391 type = (version == 1) ? 500 : 3;
392 break;
393 case GRUB_REISERFS_DIRECT:
394 type = (version == 1) ? 0xFFFFFFFF : 2;
395 break;
396 case GRUB_REISERFS_INDIRECT:
397 type = (version == 1) ? 0xFFFFFFFE : 1;
398 break;
399 default:
400 return;
403 if (version == 1)
404 key->u.v1.type = grub_cpu_to_le32 (type);
405 else
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. */
416 static int
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)
425 return -2;
427 id1 = grub_le_to_cpu32 (key1->directory_id);
428 id2 = grub_le_to_cpu32 (key2->directory_id);
429 if (id1 < id2)
430 return -1;
431 if (id1 > id2)
432 return 1;
434 id1 = grub_le_to_cpu32 (key1->object_id);
435 id2 = grub_le_to_cpu32 (key2->object_id);
436 if (id1 < id2)
437 return -1;
438 if (id1 > id2)
439 return 1;
441 offset1 = grub_reiserfs_get_key_offset (key1);
442 offset2 = grub_reiserfs_get_key_offset (key2);
443 if (offset1 < offset2)
444 return -1;
445 if (offset1 > offset2)
446 return 1;
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)))
456 return 0;
457 if (type1 < type2)
458 return -1;
459 if (type1 > type2)
460 return 1;
462 return 0;
465 /* Find the item identified by KEY in mounted filesystem DATA, and fill ITEM
466 accordingly to what was found. */
467 static grub_err_t
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;
476 grub_uint16_t i;
477 grub_uint16_t previous_level = ~0;
478 struct grub_reiserfs_item_header *item_headers = 0;
480 if (! data)
482 grub_error (GRUB_ERR_TEST_FAILURE, "data is NULL");
483 goto fail;
486 if (! key)
488 grub_error (GRUB_ERR_TEST_FAILURE, "key is NULL");
489 goto fail;
492 if (! item)
494 grub_error (GRUB_ERR_TEST_FAILURE, "item is NULL");
495 goto fail;
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);
503 #endif
504 block_header = grub_malloc (block_size);
505 if (! block_header)
506 goto fail;
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);
516 if (grub_errno)
517 goto fail;
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");
524 goto fail;
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",
529 item_count);
530 if (current_level > 1)
532 /* Internal node. Navigate to the child that should contain
533 the searched key. */
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));
540 for (i = 0;
541 i < item_count
542 && grub_reiserfs_compare_keys (key, &(keys[i])) >= 0;
543 i++)
545 #ifdef GRUB_REISERFS_DEBUG
546 grub_printf("i %03d/%03d ", i + 1, item_count + 1);
547 grub_reiserfs_print_key (&(keys[i]));
548 #endif
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
555 if (i == item_count
556 || grub_reiserfs_compare_keys (key, &(keys[i])) == 0)
557 grub_printf(">");
558 else
559 grub_printf("<");
560 if (i < item_count)
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]));
570 else
571 grub_printf ("Accessing rightmost child at block %d.\n",
572 block_number);
573 #endif
575 else
577 /* Leaf node. Check that the key is actually present. */
578 item_headers
579 = (struct grub_reiserfs_item_header *) (block_header + 1);
580 for (i = 0;
581 i < item_count
582 && (grub_reiserfs_compare_keys (key, &(item_headers[i].key))
583 != 0);
584 i++)
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)
589 grub_printf("C");
590 else
591 grub_printf(" ");
592 grub_printf(" %03d/%03d ", i + 1, item_count);
593 grub_reiserfs_print_key (&(item_headers[i].key));
594 #endif
596 if (i < item_count)
597 block_key = &(item_headers[i].key);
600 while (current_level > 1);
602 item->data = data;
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");
611 #endif
613 else
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);
623 #endif
626 assert (grub_errno == GRUB_ERR_NONE);
627 grub_free (block_header);
628 return GRUB_ERR_NONE;
630 fail:
631 assert (grub_errno != GRUB_ERR_NONE);
632 grub_free (block_header);
633 assert (grub_errno != GRUB_ERR_NONE);
634 return grub_errno;
637 /* Return the path of the file which is pointed at by symlink NODE. */
638 static char *
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;
644 grub_off_t offset;
645 grub_size_t len;
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)
655 goto fail;
657 if (found.block_number == 0)
658 goto fail;
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)
667 goto fail;
669 grub_disk_read (node->data->disk, block, offset, len, symlink_buffer);
670 if (grub_errno)
671 goto fail;
673 symlink_buffer[len] = 0;
674 return symlink_buffer;
676 fail:
677 grub_free (symlink_buffer);
678 return 0;
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));
687 if (! data)
688 goto fail;
689 grub_disk_read (disk, REISERFS_SUPER_BLOCK_OFFSET / GRUB_DISK_SECTOR_SIZE,
690 0, sizeof (data->superblock), (char *) &(data->superblock));
691 if (grub_errno)
692 goto fail;
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");
697 goto fail;
699 data->disk = disk;
700 return data;
702 fail:
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");
707 grub_free (data);
708 return 0;
711 /* Call HOOK for each file in directory ITEM. */
712 static int
713 grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
714 int NESTED_FUNC_ATTR
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;
724 int ret = 0;
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");
730 goto fail;
732 block_size = grub_le_to_cpu16 (data->superblock.block_size);
733 block_header = grub_malloc (block_size);
734 if (! block_header)
735 goto fail;
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);
751 if (grub_errno)
752 goto fail;
754 #if 0
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",
759 block_number);
760 goto fail;
762 #endif
764 item_headers = (struct grub_reiserfs_item_header *) (block_header + 1);
765 directory_headers
766 = ((struct grub_reiserfs_directory_header *)
767 ((char *) block_header
768 + grub_le_to_cpu16 (item_headers[block_position].item_location)));
769 entry_count
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;
783 char *entry_name;
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));
795 if (! entry_item)
796 goto fail;
798 if (grub_reiserfs_get_item (data, &entry_key, entry_item)
799 != GRUB_ERR_NONE)
801 grub_free (entry_item);
802 goto fail;
805 if (entry_item->type == GRUB_REISERFS_DIRECTORY)
806 entry_type = GRUB_FSHELP_DIR;
807 else
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
813 detection. */
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)
818 != GRUB_ERR_NONE)
820 grub_free (entry_item);
821 goto fail;
824 if (entry_item->block_number != 0)
826 grub_uint16_t entry_version;
827 entry_version
828 = grub_le_to_cpu16 (entry_item->header.version);
829 entry_block_number = entry_item->block_number;
830 #if 0
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));
836 #endif
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);
845 if (grub_errno)
846 goto fail;
847 #if 0
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",
862 entry_v1_stat.mode,
863 entry_v1_stat.hardlink_count,
864 entry_v1_stat.uid,
865 entry_v1_stat.gid,
866 entry_v1_stat.size,
867 entry_v1_stat.atime,
868 entry_v1_stat.mtime,
869 entry_v1_stat.ctime,
870 entry_v1_stat.rdev,
871 entry_v1_stat.first_direct_byte);
872 #endif
873 if ((grub_le_to_cpu16 (entry_v1_stat.mode) & S_IFLNK)
874 == S_IFLNK)
875 entry_type = GRUB_FSHELP_SYMLINK;
876 else
877 entry_type = GRUB_FSHELP_REG;
879 else
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);
887 if (grub_errno)
888 goto fail;
889 #if 0
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",
906 entry_v2_stat.mode,
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),
911 entry_v2_stat.uid,
912 entry_v2_stat.gid,
913 entry_v2_stat.atime,
914 entry_v2_stat.mtime,
915 entry_v2_stat.ctime,
916 entry_v2_stat.blocks,
917 entry_v2_stat.first_direct_byte);
918 #endif
919 if ((grub_le_to_cpu16 (entry_v2_stat.mode) & S_IFLNK)
920 == S_IFLNK)
921 entry_type = GRUB_FSHELP_SYMLINK;
922 else
923 entry_type = GRUB_FSHELP_REG;
926 else
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",
932 entry_name);
933 grub_free (entry_item);
934 continue;
937 if (hook (entry_name, entry_type, entry_item))
939 grub_dprintf ("reiserfs", "Found : %s, type=%d\n",
940 entry_name, entry_type);
941 ret = 1;
942 goto found;
945 *entry_name = 0; /* Make sure next entry name (which is just
946 before this one in disk order) stops before
947 the current one. */
951 if (next_offset == 0)
952 break;
954 grub_reiserfs_set_key_offset (&(item_headers[block_position].key),
955 next_offset);
956 if (grub_reiserfs_get_item (data, &(item_headers[block_position].key),
957 &directory_item) != GRUB_ERR_NONE)
958 goto fail;
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);
965 found:
966 assert (grub_errno == GRUB_ERR_NONE);
967 grub_free (block_header);
968 return ret;
969 fail:
970 assert (grub_errno != GRUB_ERR_NONE);
971 grub_free (block_header);
972 return 0;
975 /****************************************************************************/
976 /* grub api functions */
977 /****************************************************************************/
979 /* Open a file named NAME and initialize FILE. */
980 static grub_err_t
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;
989 #ifndef GRUB_UTIL
990 grub_dl_ref (my_mod);
991 #endif
992 data = grub_reiserfs_mount (file->device->disk);
993 if (! data)
994 goto fail;
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)
1002 goto fail;
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);
1011 if (grub_errno)
1012 goto fail;
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)
1018 goto fail;
1019 if (info.block_number == 0)
1021 grub_error (GRUB_ERR_BAD_FS, "Unable to find searched item");
1022 goto fail;
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),
1032 entry_location
1033 + (((grub_off_t) block_number * block_size)
1034 & (GRUB_DISK_SECTOR_SIZE - 1)),
1035 sizeof (entry_v1_stat), (char *) &entry_v1_stat);
1036 if (grub_errno)
1037 goto fail;
1038 file->size = (grub_off_t) grub_le_to_cpu64 (entry_v1_stat.size);
1040 else
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),
1045 entry_location
1046 + (((grub_off_t) block_number * block_size)
1047 & (GRUB_DISK_SECTOR_SIZE - 1)),
1048 sizeof (entry_v2_stat), (char *) &entry_v2_stat);
1049 if (grub_errno)
1050 goto fail;
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);
1056 file->offset = 0;
1057 file->data = found;
1058 return GRUB_ERR_NONE;
1060 fail:
1061 assert (grub_errno != GRUB_ERR_NONE);
1062 grub_free (found);
1063 grub_free (data);
1064 #ifndef GRUB_UTIL
1065 grub_dl_unref (my_mod);
1066 #endif
1067 return grub_errno;
1070 static grub_ssize_t
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;
1084 grub_off_t offset;
1086 if (file->offset >= file->size)
1087 return 0;
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)
1107 goto fail;
1108 if (found.block_number == 0)
1109 goto fail;
1110 item_size = grub_le_to_cpu16 (found.header.item_size);
1111 switch (found.type)
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)
1120 - offset);
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,
1127 block,
1128 offset
1129 + grub_le_to_cpu16 (found.header.item_location),
1130 length, buf);
1131 found.data->disk->read_hook = 0;
1132 if (grub_errno)
1133 goto fail;
1134 buf += length;
1135 current_position += offset + length;
1137 else
1138 current_position += item_size;
1139 break;
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)
1144 goto fail;
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);
1149 if (grub_errno)
1150 goto fail;
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;
1155 indirect_block++)
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)
1165 - offset);
1166 grub_dprintf ("reiserfs",
1167 "Reading indirect block %u from %u to %u...\n",
1168 (unsigned) block, (unsigned) offset,
1169 (unsigned) (offset + length));
1170 #if 0
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);
1176 #endif
1177 grub_disk_read (found.data->disk, block, offset, length, buf);
1178 if (grub_errno)
1179 goto fail;
1180 buf += length;
1181 current_position += offset + length;
1183 else
1184 current_position += block_size;
1186 found.data->disk->read_hook = 0;
1187 grub_free (indirect_block_ptr);
1188 indirect_block_ptr = 0;
1189 break;
1190 default:
1191 goto fail;
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;
1202 switch (found.type)
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,
1209 read_length, buf);
1210 if (grub_errno)
1211 goto fail;
1212 break;
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)
1217 goto fail;
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);
1222 if (grub_errno)
1223 goto fail;
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;
1227 indirect_block++)
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);
1234 if (grub_errno)
1235 goto fail;
1236 read_length += read;
1238 grub_free (indirect_block_ptr);
1239 break;
1240 default:
1241 goto fail;
1244 return read_length;*/
1246 fail:
1247 grub_free (indirect_block_ptr);
1248 return 0;
1251 /* Close the file FILE. */
1252 static grub_err_t
1253 grub_reiserfs_close (grub_file_t file)
1255 struct grub_fshelp_node *node = file->data;
1256 struct grub_reiserfs_data *data = node->data;
1258 grub_free (data);
1259 grub_free (node);
1260 #ifndef GRUB_UTIL
1261 grub_dl_unref (my_mod);
1262 #endif
1263 return GRUB_ERR_NONE;
1266 /* Call HOOK with each file under DIR. */
1267 static grub_err_t
1268 grub_reiserfs_dir (grub_device_t device, const char *path,
1269 int (*hook) (const char *filename,
1270 const struct grub_dirhook_info *info))
1272 struct grub_reiserfs_data *data = 0;
1273 struct grub_fshelp_node root, *found;
1274 struct grub_reiserfs_key root_key;
1276 auto int NESTED_FUNC_ATTR iterate (const char *filename,
1277 enum grub_fshelp_filetype filetype,
1278 grub_fshelp_node_t node);
1280 int NESTED_FUNC_ATTR iterate (const char *filename,
1281 enum grub_fshelp_filetype filetype,
1282 grub_fshelp_node_t node)
1284 struct grub_dirhook_info info;
1285 grub_memset (&info, 0, sizeof (info));
1286 info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
1287 grub_free (node);
1288 return hook (filename, &info);
1290 #ifndef GRUB_UTIL
1291 grub_dl_ref (my_mod);
1292 #endif
1293 data = grub_reiserfs_mount (device->disk);
1294 if (! data)
1295 goto fail;
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)
1302 goto fail;
1303 if (root.block_number == 0)
1305 grub_error(GRUB_ERR_BAD_FS, "Root not found");
1306 goto fail;
1308 grub_fshelp_find_file (path, &root, &found, grub_reiserfs_iterate_dir,
1309 grub_reiserfs_read_symlink, GRUB_FSHELP_DIR);
1310 if (grub_errno)
1311 goto fail;
1312 grub_reiserfs_iterate_dir (found, iterate);
1313 grub_free (data);
1314 #ifndef GRUB_UTIL
1315 grub_dl_unref (my_mod);
1316 #endif
1317 return GRUB_ERR_NONE;
1319 fail:
1320 grub_free (data);
1321 #ifndef GRUB_UTIL
1322 grub_dl_unref (my_mod);
1323 #endif
1324 return grub_errno;
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
1329 caller. */
1330 static grub_err_t
1331 grub_reiserfs_label (grub_device_t device, char **label)
1333 *label = grub_malloc (REISERFS_MAX_LABEL_LENGTH);
1334 if (*label)
1336 grub_disk_read (device->disk,
1337 REISERFS_SUPER_BLOCK_OFFSET / GRUB_DISK_SECTOR_SIZE,
1338 REISERFS_LABEL_OFFSET, REISERFS_MAX_LABEL_LENGTH,
1339 *label);
1341 return grub_errno;
1344 static grub_err_t
1345 grub_reiserfs_uuid (grub_device_t device, char **uuid)
1347 struct grub_reiserfs_data *data;
1348 grub_disk_t disk = device->disk;
1350 #ifndef GRUB_UTIL
1351 grub_dl_ref (my_mod);
1352 #endif
1354 data = grub_reiserfs_mount (disk);
1355 if (data)
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]));
1364 else
1365 *uuid = NULL;
1367 #ifndef GRUB_UTIL
1368 grub_dl_unref (my_mod);
1369 #endif
1371 grub_free (data);
1373 return grub_errno;
1376 static struct grub_fs grub_reiserfs_fs =
1378 .name = "reiserfs",
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,
1385 .next = 0
1388 GRUB_MOD_INIT(reiserfs)
1390 grub_fs_register (&grub_reiserfs_fs);
1391 #ifndef GRUB_UTIL
1392 my_mod = mod;
1393 #endif
1396 GRUB_MOD_FINI(reiserfs)
1398 grub_fs_unregister (&grub_reiserfs_fs);