added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / arch / common / grub2 / fs / reiserfs.c
blobb5b32bedca5bd0ebec8b7811d800921367450c5e
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
26 #warning "TODO : journal, tail packing (?)"
28 #if 0
29 # define GRUB_REISERFS_KEYV2_BITFIELD 1
30 # define GRUB_REISERFS_DEBUG
31 # define GRUB_REISERFS_JOURNALING
32 # define GRUB_HEXDUMP
33 #endif
35 #include <grub/err.h>
36 #include <grub/file.h>
37 #include <grub/mm.h>
38 #include <grub/misc.h>
39 #include <grub/disk.h>
40 #include <grub/dl.h>
41 #include <grub/types.h>
42 #include <grub/fshelp.h>
44 #define MIN(a, b) \
45 ({ typeof (a) _a = (a); \
46 typeof (b) _b = (b); \
47 _a < _b ? _a : _b; })
49 #define MAX(a, b) \
50 ({ typeof (a) _a = (a); \
51 typeof (b) _b = (b); \
52 _a > _b ? _a : _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
64 #ifndef GRUB_UTIL
65 static grub_dl_t my_mod;
66 #endif
68 #define assert(boolean) real_assert (boolean, __FILE__, __LINE__)
69 static inline void
70 real_assert (int boolean, const char *file, const int line)
72 if (! boolean)
73 grub_printf ("Assertion failed at %s:%d\n", file, line);
76 enum grub_reiserfs_item_type
78 GRUB_REISERFS_STAT,
79 GRUB_REISERFS_DIRECTORY,
80 GRUB_REISERFS_DIRECT,
81 GRUB_REISERFS_INDIRECT,
82 /* Matches both _DIRECT and _INDIRECT when searching. */
83 GRUB_REISERFS_ANY,
84 GRUB_REISERFS_UNKNOWN
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;
103 grub_uint16_t state;
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
124 grub_uint32_t id;
125 grub_uint32_t len;
126 grub_uint32_t mount_id;
127 char *data;
128 char checksum[12];
129 } __attribute__ ((packed));
130 #endif
132 struct grub_reiserfs_stat_item_v1
134 grub_uint16_t mode;
135 grub_uint16_t hardlink_count;
136 grub_uint16_t uid;
137 grub_uint16_t gid;
138 grub_uint32_t size;
139 grub_uint32_t atime;
140 grub_uint32_t mtime;
141 grub_uint32_t ctime;
142 grub_uint32_t rdev;
143 grub_uint32_t first_direct_byte;
144 } __attribute__ ((packed));
146 struct grub_reiserfs_stat_item_v2
148 grub_uint16_t mode;
149 grub_uint16_t reserved;
150 grub_uint32_t hardlink_count;
151 grub_uint64_t size;
152 grub_uint32_t uid;
153 grub_uint32_t gid;
154 grub_uint32_t atime;
155 grub_uint32_t mtime;
156 grub_uint32_t ctime;
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;
165 union
167 struct
169 grub_uint32_t offset;
170 grub_uint32_t type;
171 } v1 __attribute__ ((packed));
172 struct
174 #ifdef GRUB_REISERFS_KEYV2_BITFIELD
175 grub_uint64_t offset:60;
176 grub_uint64_t type:4;
177 #else
178 grub_uint64_t offset_type;
179 #endif
180 } v2 __attribute__ ((packed));
181 } u;
182 } __attribute__ ((packed));
184 struct grub_reiserfs_item_header
186 struct grub_reiserfs_key key;
187 union
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
199 grub_uint16_t level;
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;
209 grub_uint16_t size;
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;
219 grub_uint16_t state;
220 } __attribute__ ((packed));
222 struct grub_reiserfs_node_body
224 union
226 struct
228 struct grub_reiserfs_key *key_list;
229 struct grub_reiserfs_disk_child *child_list;
230 } internal;
231 struct
233 struct grub_reiserfs_item_header *item_header_list;
234 } leaf;
235 } u;
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;
251 grub_disk_t disk;
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)
262 #else
263 switch (grub_le_to_cpu64 (key->u.v2.offset_type) >> 60)
264 #endif
266 case 0:
267 return GRUB_REISERFS_STAT;
268 case 15:
269 return GRUB_REISERFS_ANY;
270 case 3:
271 return GRUB_REISERFS_DIRECTORY;
272 case 2:
273 return GRUB_REISERFS_DIRECT;
274 case 1:
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))
286 case 0:
287 return GRUB_REISERFS_STAT;
288 case 555:
289 return GRUB_REISERFS_ANY;
290 case 500:
291 return GRUB_REISERFS_DIRECTORY;
292 case 0x20000000:
293 case 0xFFFFFFFF:
294 return GRUB_REISERFS_DIRECT;
295 case 0x10000000:
296 case 0xFFFFFFFE:
297 return GRUB_REISERFS_INDIRECT;
299 return GRUB_REISERFS_UNKNOWN;
302 /* Return 1 if the given key is version 1 key, 2 otherwise. */
303 static int
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;
309 #ifdef GRUB_HEXDUMP
310 static void
311 grub_hexdump (char *buffer, grub_size_t len)
313 grub_size_t a;
314 for (a = 0; a < len; a++)
316 if (! (a & 0x0F))
317 grub_printf ("\n%08x ", a);
318 grub_printf ("%02x ",
319 ((unsigned int) ((unsigned char *) buffer)[a]) & 0xFF);
321 grub_printf ("\n");
323 #endif
325 #ifdef GRUB_REISERFS_DEBUG
326 static grub_uint64_t
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);
332 static void
333 grub_reiserfs_print_key (const struct grub_reiserfs_key *key)
335 unsigned int a;
336 char *reiserfs_type_strings[] = {
337 "stat ",
338 "directory",
339 "direct ",
340 "indirect ",
341 "any ",
342 "unknown "
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));
353 else
354 grub_printf("0x%07x%08x",
355 (unsigned) (grub_reiserfs_get_key_offset (key) >> 32),
356 (unsigned) (grub_reiserfs_get_key_offset (key) & 0xFFFFFFFF));
357 grub_printf ("\n");
359 #endif
361 /* Return the offset of given key. */
362 static grub_uint64_t
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);
367 else
369 #ifdef GRUB_REISERFS_KEYV2_BITFIELD
370 return key->u.v2.offset;
371 #else
372 return grub_le_to_cpu64 (key->u.v2.offset_type) & (~0ULL >> 4);
373 #endif
377 /* Set the offset of given key. */
378 static void
379 grub_reiserfs_set_key_offset (struct grub_reiserfs_key *key,
380 grub_uint64_t value)
382 if (grub_reiserfs_get_key_version (key) == 1)
383 key->u.v1.offset = grub_cpu_to_le32 (value);
384 else
385 #ifdef GRUB_REISERFS_KEYV2_BITFIELD
386 key->u.v2.offset = value;
387 #else
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)));
391 #endif
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);
400 else
401 return grub_reiserfs_get_key_v2_type (key);
404 /* Set the type of given key, with given version number. */
405 static void
406 grub_reiserfs_set_key_type (struct grub_reiserfs_key *key,
407 enum grub_reiserfs_item_type grub_type,
408 int version)
410 grub_uint32_t type;
412 switch (grub_type)
414 case GRUB_REISERFS_STAT:
415 type = 0;
416 break;
417 case GRUB_REISERFS_ANY:
418 type = (version == 1) ? 555 : 15;
419 break;
420 case GRUB_REISERFS_DIRECTORY:
421 type = (version == 1) ? 500 : 3;
422 break;
423 case GRUB_REISERFS_DIRECT:
424 type = (version == 1) ? 0xFFFFFFFF : 2;
425 break;
426 case GRUB_REISERFS_INDIRECT:
427 type = (version == 1) ? 0xFFFFFFFE : 1;
428 break;
429 default:
430 return;
433 if (version == 1)
434 key->u.v1.type = grub_cpu_to_le32 (type);
435 else
437 #ifdef GRUB_REISERFS_KEYV2_BITFIELD
438 key->u.v2.type = type;
439 #else
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));
443 #endif
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. */
451 static int
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)
460 return -2;
462 id1 = grub_le_to_cpu32 (key1->directory_id);
463 id2 = grub_le_to_cpu32 (key2->directory_id);
464 if (id1 < id2)
465 return -1;
466 if (id1 > id2)
467 return 1;
469 id1 = grub_le_to_cpu32 (key1->object_id);
470 id2 = grub_le_to_cpu32 (key2->object_id);
471 if (id1 < id2)
472 return -1;
473 if (id1 > id2)
474 return 1;
476 offset1 = grub_reiserfs_get_key_offset (key1);
477 offset2 = grub_reiserfs_get_key_offset (key2);
478 if (offset1 < offset2)
479 return -1;
480 if (offset1 > offset2)
481 return 1;
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)))
491 return 0;
492 if (type1 < type2)
493 return -1;
494 if (type1 > type2)
495 return 1;
497 return 0;
500 /* Find the item identified by KEY in mounted filesystem DATA, and fill ITEM
501 accordingly to what was found. */
502 static grub_err_t
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;
511 grub_uint16_t i;
512 grub_uint16_t previous_level = ~0;
513 struct grub_reiserfs_item_header *item_headers = 0;
515 if (! data)
517 grub_error (GRUB_ERR_TEST_FAILURE, "data is NULL");
518 goto fail;
521 if (! key)
523 grub_error (GRUB_ERR_TEST_FAILURE, "key is NULL");
524 goto fail;
527 if (! item)
529 grub_error (GRUB_ERR_TEST_FAILURE, "item is NULL");
530 goto fail;
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);
538 #endif
539 block_header = grub_malloc (block_size);
540 if (! block_header)
541 goto fail;
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);
551 if (grub_errno)
552 goto fail;
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");
559 goto fail;
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",
564 item_count);
565 if (current_level > 1)
567 /* Internal node. Navigate to the child that should contain
568 the searched key. */
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));
575 for (i = 0;
576 i < item_count
577 && grub_reiserfs_compare_keys (key, &(keys[i])) >= 0;
578 i++)
580 #ifdef GRUB_REISERFS_DEBUG
581 grub_printf("i %03d/%03d ", i + 1, item_count + 1);
582 grub_reiserfs_print_key (&(keys[i]));
583 #endif
585 block_number = grub_le_to_cpu32 (children[i].block_number);
586 #ifdef GRUB_REISERFS_DEBUG
587 if (i == item_count
588 || grub_reiserfs_compare_keys (key, &(keys[i])) == 0)
589 grub_printf(">");
590 else
591 grub_printf("<");
592 if (i < item_count)
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]));
602 else
603 grub_printf ("Accessing rightmost child at block %d.\n",
604 block_number);
605 #endif
607 else
609 /* Leaf node. Check that the key is actually present. */
610 item_headers
611 = (struct grub_reiserfs_item_header *) (block_header + 1);
612 for (i = 0;
613 i < item_count
614 && (grub_reiserfs_compare_keys (key, &(item_headers[i].key))
615 != 0);
616 i++)
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)
621 grub_printf("C");
622 else
623 grub_printf(" ");
624 grub_printf(" %03d/%03d ", i + 1, item_count);
625 grub_reiserfs_print_key (&(item_headers[i].key));
626 #endif
628 if (i < item_count)
629 block_key = &(item_headers[i].key);
632 while (current_level > 1);
634 item->data = data;
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");
643 #endif
645 else
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);
655 #endif
658 assert (grub_errno == GRUB_ERR_NONE);
659 grub_free (block_header);
660 return GRUB_ERR_NONE;
662 fail:
663 assert (grub_errno != GRUB_ERR_NONE);
664 grub_free (block_header);
665 assert (grub_errno != GRUB_ERR_NONE);
666 return grub_errno;
669 /* Return the path of the file which is pointed at by symlink NODE. */
670 static char *
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;
676 grub_off_t offset;
677 grub_size_t len;
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)
687 goto fail;
689 if (found.block_number == 0)
690 goto fail;
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)
700 goto fail;
702 grub_disk_read (node->data->disk, block, offset, len, symlink_buffer);
703 if (grub_errno)
704 goto fail;
706 return symlink_buffer;
708 fail:
709 grub_free (symlink_buffer);
710 return 0;
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));
719 if (! data)
720 goto fail;
721 grub_disk_read (disk, REISERFS_SUPER_BLOCK_OFFSET / GRUB_DISK_SECTOR_SIZE,
722 0, sizeof (data->superblock), (char *) &(data->superblock));
723 if (grub_errno)
724 goto fail;
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");
729 goto fail;
731 data->disk = disk;
732 return data;
734 fail:
735 grub_free (data);
736 return 0;
739 /* Call HOOK for each file in directory ITEM. */
740 static int
741 grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
742 int NESTED_FUNC_ATTR
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;
751 int ret = 0;
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");
757 goto fail;
759 block_size = grub_le_to_cpu16 (data->superblock.block_size);
760 block_header = grub_malloc (block_size);
761 if (! block_header)
762 goto fail;
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);
780 if (grub_errno)
781 goto fail;
783 #if 0
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",
788 block_number);
789 goto fail;
791 #endif
793 item_headers = (struct grub_reiserfs_item_header *) (block_header + 1);
794 directory_headers
795 = ((struct grub_reiserfs_directory_header *)
796 ((char *) block_header
797 + grub_le_to_cpu16 (item_headers[block_position].item_location)));
798 entry_count
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;
812 char *entry_name;
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;
821 #else
822 entry_key.u.v2.offset_type = 0;
823 #endif
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));
829 if (! entry_item)
830 goto fail;
832 if (grub_reiserfs_get_item (data, &entry_key, entry_item)
833 != GRUB_ERR_NONE)
835 grub_free (entry_item);
836 goto fail;
839 if (entry_item->type == GRUB_REISERFS_DIRECTORY)
840 entry_type = GRUB_FSHELP_DIR;
841 else
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
847 detection. */
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)
852 != GRUB_ERR_NONE)
854 grub_free (entry_item);
855 goto fail;
858 if (entry_item->block_number != 0)
860 grub_uint16_t entry_version;
861 entry_version
862 = grub_le_to_cpu16 (entry_item->header.version);
863 entry_block_number = entry_item->block_number;
864 #if 0
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));
870 #endif
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);
879 if (grub_errno)
880 goto fail;
881 #if 0
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",
896 entry_v1_stat.mode,
897 entry_v1_stat.hardlink_count,
898 entry_v1_stat.uid,
899 entry_v1_stat.gid,
900 entry_v1_stat.size,
901 entry_v1_stat.atime,
902 entry_v1_stat.mtime,
903 entry_v1_stat.ctime,
904 entry_v1_stat.rdev,
905 entry_v1_stat.first_direct_byte);
906 #endif
907 if ((grub_le_to_cpu16 (entry_v1_stat.mode) & S_IFLNK)
908 == S_IFLNK)
909 entry_type = GRUB_FSHELP_SYMLINK;
910 else
911 entry_type = GRUB_FSHELP_REG;
913 else
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);
921 if (grub_errno)
922 goto fail;
923 #if 0
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",
940 entry_v2_stat.mode,
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),
945 entry_v2_stat.uid,
946 entry_v2_stat.gid,
947 entry_v2_stat.atime,
948 entry_v2_stat.mtime,
949 entry_v2_stat.ctime,
950 entry_v2_stat.blocks,
951 entry_v2_stat.first_direct_byte);
952 #endif
953 if ((grub_le_to_cpu16 (entry_v2_stat.mode) & S_IFLNK)
954 == S_IFLNK)
955 entry_type = GRUB_FSHELP_SYMLINK;
956 else
957 entry_type = GRUB_FSHELP_REG;
960 else
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",
966 entry_name);
967 grub_free (entry_item);
968 continue;
971 if (hook (entry_name, entry_type, entry_item))
973 grub_dprintf ("reiserfs", "Found : %s, type=%d\n",
974 entry_name, entry_type);
975 ret = 1;
976 goto found;
979 *entry_name = 0; /* Make sure next entry name (which is just
980 before this one in disk order) stops before
981 the current one. */
985 key_offset
986 = grub_reiserfs_get_key_offset (&(item_headers[block_position].key));
987 grub_reiserfs_set_key_offset (&(item_headers[block_position].key),
988 key_offset + 1);
989 if (grub_reiserfs_get_item (data, &(item_headers[block_position].key),
990 &directory_item) != GRUB_ERR_NONE)
991 goto fail;
992 block_number = directory_item.block_number;
993 block_position = directory_item.block_position;
995 while (block_number);
997 found:
998 assert (grub_errno == GRUB_ERR_NONE);
999 grub_free (block_header);
1000 return ret;
1001 fail:
1002 assert (grub_errno != GRUB_ERR_NONE);
1003 grub_free (block_header);
1004 return 0;
1007 /****************************************************************************/
1008 /* grub api functions */
1009 /****************************************************************************/
1011 /* Open a file named NAME and initialize FILE. */
1012 static grub_err_t
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;
1021 #ifndef GRUB_UTIL
1022 grub_dl_ref (my_mod);
1023 #endif
1024 data = grub_reiserfs_mount (file->device->disk);
1025 if (! data)
1026 goto fail;
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;
1032 key.u.v2.type = 0;
1033 #else
1034 key.u.v2.offset_type = 0;
1035 #endif
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)
1039 goto fail;
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);
1048 if (grub_errno)
1049 goto fail;
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)
1055 goto fail;
1056 if (info.block_number == 0)
1058 grub_error (GRUB_ERR_BAD_FS, "Unable to find searched item");
1059 goto fail;
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),
1070 entry_location
1071 + (((grub_off_t) block_number * block_size)
1072 & (GRUB_DISK_SECTOR_SIZE - 1)),
1073 sizeof (entry_v1_stat), (char *) &entry_v1_stat);
1074 if (grub_errno)
1075 goto fail;
1076 file->size = (grub_off_t) grub_le_to_cpu64 (entry_v1_stat.size);
1078 else
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),
1084 entry_location
1085 + (((grub_off_t) block_number * block_size)
1086 & (GRUB_DISK_SECTOR_SIZE - 1)),
1087 sizeof (entry_v2_stat), (char *) &entry_v2_stat);
1088 if (grub_errno)
1089 goto fail;
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);
1095 file->offset = 0;
1096 file->data = found;
1097 return GRUB_ERR_NONE;
1099 fail:
1100 assert (grub_errno != GRUB_ERR_NONE);
1101 grub_free (found);
1102 grub_free (data);
1103 #ifndef GRUB_UTIL
1104 grub_dl_unref (my_mod);
1105 #endif
1106 return grub_errno;
1109 static grub_ssize_t
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;
1123 grub_off_t offset;
1125 if (file->offset >= file->size)
1126 return 0;
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;
1132 key.u.v2.type = 0;
1133 #else
1134 key.u.v2.offset_type = 0;
1135 #endif
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)
1149 goto fail;
1150 if (found.block_number == 0)
1151 goto fail;
1152 item_size = grub_le_to_cpu16 (found.header.item_size);
1153 switch (found.type)
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)
1163 - offset);
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,
1170 block,
1171 offset
1172 + grub_le_to_cpu16 (found.header.item_location),
1173 length, buf);
1174 found.data->disk->read_hook = 0;
1175 if (grub_errno)
1176 goto fail;
1177 buf += length;
1178 current_position += offset + length;
1180 else
1181 current_position += item_size;
1182 break;
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)
1187 goto fail;
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);
1193 if (grub_errno)
1194 goto fail;
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;
1199 indirect_block++)
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)
1210 - offset);
1211 grub_dprintf ("reiserfs",
1212 "Reading indirect block %u from %u to %u...\n",
1213 (unsigned) block, (unsigned) offset,
1214 (unsigned) offset + length);
1215 #if 0
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);
1221 #endif
1222 grub_disk_read (found.data->disk, block, offset, length, buf);
1223 if (grub_errno)
1224 goto fail;
1225 buf += length;
1226 current_position += offset + length;
1228 else
1229 current_position += block_size;
1231 found.data->disk->read_hook = 0;
1232 grub_free (indirect_block_ptr);
1233 indirect_block_ptr = 0;
1234 break;
1235 default:
1236 goto fail;
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;
1246 switch (found.type)
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,
1253 read_length, buf);
1254 if (grub_errno)
1255 goto fail;
1256 break;
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)
1261 goto fail;
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);
1266 if (grub_errno)
1267 goto fail;
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;
1271 indirect_block++)
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);
1278 if (grub_errno)
1279 goto fail;
1280 read_length += read;
1282 grub_free (indirect_block_ptr);
1283 break;
1284 default:
1285 goto fail;
1288 return read_length;*/
1290 fail:
1291 grub_free (indirect_block_ptr);
1292 return 0;
1295 /* Close the file FILE. */
1296 static grub_err_t
1297 grub_reiserfs_close (grub_file_t file)
1299 struct grub_fshelp_node *node = file->data;
1300 struct grub_reiserfs_data *data = node->data;
1302 grub_free (data);
1303 grub_free (node);
1304 #ifndef GRUB_UTIL
1305 grub_dl_unref (my_mod);
1306 #endif
1307 return GRUB_ERR_NONE;
1310 /* Call HOOK with each file under DIR. */
1311 static grub_err_t
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)
1327 grub_free (node);
1329 if (filetype == GRUB_FSHELP_DIR)
1330 return hook (filename, 1);
1331 else
1332 return hook (filename, 0);
1334 #ifndef GRUB_UTIL
1335 grub_dl_ref (my_mod);
1336 #endif
1337 data = grub_reiserfs_mount (device->disk);
1338 if (! data)
1339 goto fail;
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;
1345 #else
1346 root_key.u.v2.offset_type = 0;
1347 #endif
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)
1351 goto fail;
1352 if (root.block_number == 0)
1354 grub_error(GRUB_ERR_BAD_FS, "Root not found");
1355 goto fail;
1357 grub_fshelp_find_file (path, &root, &found, grub_reiserfs_iterate_dir,
1358 grub_reiserfs_read_symlink, GRUB_FSHELP_DIR);
1359 if (grub_errno)
1360 goto fail;
1361 grub_reiserfs_iterate_dir (found, iterate);
1362 grub_free (data);
1363 #ifndef GRUB_UTIL
1364 grub_dl_unref (my_mod);
1365 #endif
1366 return GRUB_ERR_NONE;
1368 fail:
1369 grub_free (data);
1370 #ifndef GRUB_UTIL
1371 grub_dl_unref (my_mod);
1372 #endif
1373 return grub_errno;
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
1378 caller. */
1379 static grub_err_t
1380 grub_reiserfs_label (grub_device_t device, char **label)
1382 *label = grub_malloc (REISERFS_MAX_LABEL_LENGTH);
1383 if (*label)
1385 grub_disk_read (device->disk,
1386 REISERFS_SUPER_BLOCK_OFFSET / GRUB_DISK_SECTOR_SIZE,
1387 REISERFS_LABEL_OFFSET, REISERFS_MAX_LABEL_LENGTH,
1388 *label);
1390 return grub_errno;
1393 static struct grub_fs grub_reiserfs_fs =
1395 .name = "reiserfs",
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,
1401 .next = 0
1404 GRUB_MOD_INIT(reiserfs)
1406 grub_fs_register (&grub_reiserfs_fs);
1407 #ifndef GRUB_UTIL
1408 my_mod = mod;
1409 #endif
1412 GRUB_MOD_FINI(reiserfs)
1414 grub_fs_unregister (&grub_reiserfs_fs);