mips: mtmips: make use of sysreset-resetctrl for mt7628 soc
[oweals/u-boot.git] / fs / reiserfs / reiserfs.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  *  Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
4  *
5  *  GRUB  --  GRand Unified Bootloader
6  *  Copyright (C) 2000, 2001  Free Software Foundation, Inc.
7  *
8  *  (C) Copyright 2003 - 2004
9  *  Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba@sysgo.com>
10  *
11  */
12
13 /* An implementation for the ReiserFS filesystem ported from GRUB.
14  * Some parts of this code (mainly the structures and defines) are
15  * from the original reiser fs code, as found in the linux kernel.
16  */
17
18 #include <common.h>
19 #include <malloc.h>
20 #include <linux/ctype.h>
21 #include <linux/time.h>
22 #include <asm/byteorder.h>
23 #include <reiserfs.h>
24
25 #include "reiserfs_private.h"
26
27 #undef REISERDEBUG
28
29 /* Some parts of this code (mainly the structures and defines) are
30  * from the original reiser fs code, as found in the linux kernel.
31  */
32
33 static char fsys_buf[FSYS_BUFLEN];
34 static reiserfs_error_t errnum = ERR_NONE;
35 static int print_possibilities;
36 static unsigned int filepos, filemax;
37
38 static int
39 substring (const char *s1, const char *s2)
40 {
41   while (*s1 == *s2)
42     {
43       /* The strings match exactly. */
44       if (! *(s1++))
45         return 0;
46       s2 ++;
47     }
48
49   /* S1 is a substring of S2. */
50   if (*s1 == 0)
51     return -1;
52
53   /* S1 isn't a substring. */
54   return 1;
55 }
56
57 static void sd_print_item (struct item_head * ih, char * item)
58 {
59     char filetime[30];
60     time_t ttime;
61
62     if (stat_data_v1 (ih)) {
63         struct stat_data_v1 * sd = (struct stat_data_v1 *)item;
64         ttime = sd_v1_mtime(sd);
65         ctime_r(&ttime, filetime);
66         printf ("%-10s %4hd %6d %6d %9d %24.24s",
67                  bb_mode_string(sd_v1_mode(sd)), sd_v1_nlink(sd),sd_v1_uid(sd), sd_v1_gid(sd),
68                  sd_v1_size(sd), filetime);
69     } else {
70         struct stat_data * sd = (struct stat_data *)item;
71         ttime = sd_v2_mtime(sd);
72         ctime_r(&ttime, filetime);
73         printf ("%-10s %4d %6d %6d %9d %24.24s",
74                  bb_mode_string(sd_v2_mode(sd)), sd_v2_nlink(sd),sd_v2_uid(sd),sd_v2_gid(sd),
75                  (__u32) sd_v2_size(sd), filetime);
76     }
77 }
78
79 static int
80 journal_read (int block, int len, char *buffer)
81 {
82   return reiserfs_devread ((INFO->journal_block + block) << INFO->blocksize_shift,
83                            0, len, buffer);
84 }
85
86 /* Read a block from ReiserFS file system, taking the journal into
87  * account.  If the block nr is in the journal, the block from the
88  * journal taken.
89  */
90 static int
91 block_read (unsigned int blockNr, int start, int len, char *buffer)
92 {
93   int transactions = INFO->journal_transactions;
94   int desc_block = INFO->journal_first_desc;
95   int journal_mask = INFO->journal_block_count - 1;
96   int translatedNr = blockNr;
97   __u32 *journal_table = JOURNAL_START;
98   while (transactions-- > 0)
99     {
100       int i = 0;
101       int j_len;
102       if (__le32_to_cpu(*journal_table) != 0xffffffff)
103         {
104           /* Search for the blockNr in cached journal */
105           j_len = __le32_to_cpu(*journal_table++);
106           while (i++ < j_len)
107             {
108               if (__le32_to_cpu(*journal_table++) == blockNr)
109                 {
110                   journal_table += j_len - i;
111                   goto found;
112                 }
113             }
114         }
115       else
116         {
117           /* This is the end of cached journal marker.  The remaining
118            * transactions are still on disk.
119            */
120           struct reiserfs_journal_desc   desc;
121           struct reiserfs_journal_commit commit;
122
123           if (! journal_read (desc_block, sizeof (desc), (char *) &desc))
124             return 0;
125
126           j_len = __le32_to_cpu(desc.j_len);
127           while (i < j_len && i < JOURNAL_TRANS_HALF)
128             if (__le32_to_cpu(desc.j_realblock[i++]) == blockNr)
129               goto found;
130
131           if (j_len >= JOURNAL_TRANS_HALF)
132             {
133               int commit_block = (desc_block + 1 + j_len) & journal_mask;
134               if (! journal_read (commit_block,
135                                   sizeof (commit), (char *) &commit))
136                 return 0;
137               while (i < j_len)
138                 if (__le32_to_cpu(commit.j_realblock[i++ - JOURNAL_TRANS_HALF]) == blockNr)
139                   goto found;
140             }
141         }
142       goto not_found;
143
144     found:
145       translatedNr = INFO->journal_block + ((desc_block + i) & journal_mask);
146 #ifdef REISERDEBUG
147       printf ("block_read: block %d is mapped to journal block %d.\n",
148               blockNr, translatedNr - INFO->journal_block);
149 #endif
150       /* We must continue the search, as this block may be overwritten
151        * in later transactions.
152        */
153     not_found:
154       desc_block = (desc_block + 2 + j_len) & journal_mask;
155     }
156   return reiserfs_devread (translatedNr << INFO->blocksize_shift, start, len, buffer);
157 }
158
159 /* Init the journal data structure.  We try to cache as much as
160  * possible in the JOURNAL_START-JOURNAL_END space, but if it is full
161  * we can still read the rest from the disk on demand.
162  *
163  * The first number of valid transactions and the descriptor block of the
164  * first valid transaction are held in INFO.  The transactions are all
165  * adjacent, but we must take care of the journal wrap around.
166  */
167 static int
168 journal_init (void)
169 {
170   unsigned int block_count = INFO->journal_block_count;
171   unsigned int desc_block;
172   unsigned int commit_block;
173   unsigned int next_trans_id;
174   struct reiserfs_journal_header header;
175   struct reiserfs_journal_desc   desc;
176   struct reiserfs_journal_commit commit;
177   __u32 *journal_table = JOURNAL_START;
178
179   journal_read (block_count, sizeof (header), (char *) &header);
180   desc_block = __le32_to_cpu(header.j_first_unflushed_offset);
181   if (desc_block >= block_count)
182     return 0;
183
184   INFO->journal_first_desc = desc_block;
185   next_trans_id = __le32_to_cpu(header.j_last_flush_trans_id) + 1;
186
187 #ifdef REISERDEBUG
188   printf ("journal_init: last flushed %d\n",
189           __le32_to_cpu(header.j_last_flush_trans_id));
190 #endif
191
192   while (1)
193     {
194       journal_read (desc_block, sizeof (desc), (char *) &desc);
195       if (substring (JOURNAL_DESC_MAGIC, desc.j_magic) > 0
196           || __le32_to_cpu(desc.j_trans_id) != next_trans_id
197           || __le32_to_cpu(desc.j_mount_id) != __le32_to_cpu(header.j_mount_id))
198         /* no more valid transactions */
199         break;
200
201       commit_block = (desc_block + __le32_to_cpu(desc.j_len) + 1) & (block_count - 1);
202       journal_read (commit_block, sizeof (commit), (char *) &commit);
203       if (__le32_to_cpu(desc.j_trans_id) != commit.j_trans_id
204           || __le32_to_cpu(desc.j_len) != __le32_to_cpu(commit.j_len))
205         /* no more valid transactions */
206         break;
207
208 #ifdef REISERDEBUG
209       printf ("Found valid transaction %d/%d at %d.\n",
210               __le32_to_cpu(desc.j_trans_id), __le32_to_cpu(desc.j_mount_id), desc_block);
211 #endif
212
213       next_trans_id++;
214       if (journal_table < JOURNAL_END)
215         {
216           if ((journal_table + 1 + __le32_to_cpu(desc.j_len)) >= JOURNAL_END)
217             {
218               /* The table is almost full; mark the end of the cached
219                * journal.*/
220               *journal_table = __cpu_to_le32(0xffffffff);
221               journal_table = JOURNAL_END;
222             }
223           else
224             {
225               unsigned int i;
226               /* Cache the length and the realblock numbers in the table.
227                * The block number of descriptor can easily be computed.
228                * and need not to be stored here.
229                */
230
231               /* both are in the little endian format */
232               *journal_table++ = desc.j_len;
233               for (i = 0; i < __le32_to_cpu(desc.j_len) && i < JOURNAL_TRANS_HALF; i++)
234                 {
235                   /* both are in the little endian format */
236                   *journal_table++ = desc.j_realblock[i];
237 #ifdef REISERDEBUG
238                   printf ("block %d is in journal %d.\n",
239                           __le32_to_cpu(desc.j_realblock[i]), desc_block);
240 #endif
241                 }
242               for (     ; i < __le32_to_cpu(desc.j_len); i++)
243                 {
244                   /* both are in the little endian format */
245                   *journal_table++ = commit.j_realblock[i-JOURNAL_TRANS_HALF];
246 #ifdef REISERDEBUG
247                   printf ("block %d is in journal %d.\n",
248                           __le32_to_cpu(commit.j_realblock[i-JOURNAL_TRANS_HALF]),
249                           desc_block);
250 #endif
251                 }
252             }
253         }
254       desc_block = (commit_block + 1) & (block_count - 1);
255     }
256 #ifdef REISERDEBUG
257   printf ("Transaction %d/%d at %d isn't valid.\n",
258           __le32_to_cpu(desc.j_trans_id), __le32_to_cpu(desc.j_mount_id), desc_block);
259 #endif
260
261   INFO->journal_transactions
262     = next_trans_id - __le32_to_cpu(header.j_last_flush_trans_id) - 1;
263   return errnum == 0;
264 }
265
266 /* check filesystem types and read superblock into memory buffer */
267 int
268 reiserfs_mount (unsigned part_length)
269 {
270   struct reiserfs_super_block super;
271   int superblock = REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS;
272   char *cache;
273
274   if (part_length < superblock + (sizeof (super) >> SECTOR_BITS)
275       || ! reiserfs_devread (superblock, 0, sizeof (struct reiserfs_super_block),
276                              (char *) &super)
277       || (substring (REISER3FS_SUPER_MAGIC_STRING, super.s_magic) > 0
278           && substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) > 0
279           && substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) > 0)
280       || (/* check that this is not a copy inside the journal log */
281           sb_journal_block(&super) * sb_blocksize(&super)
282           <= REISERFS_DISK_OFFSET_IN_BYTES))
283     {
284       /* Try old super block position */
285       superblock = REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS;
286       if (part_length < superblock + (sizeof (super) >> SECTOR_BITS)
287           || ! reiserfs_devread (superblock, 0, sizeof (struct reiserfs_super_block),
288                                  (char *) &super))
289         return 0;
290
291       if (substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) > 0
292           && substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) > 0)
293         {
294           /* pre journaling super block ? */
295           if (substring (REISERFS_SUPER_MAGIC_STRING,
296                          (char*) ((int) &super + 20)) > 0)
297             return 0;
298
299           set_sb_blocksize(&super, REISERFS_OLD_BLOCKSIZE);
300           set_sb_journal_block(&super, 0);
301           set_sb_version(&super, 0);
302         }
303     }
304
305   /* check the version number.  */
306   if (sb_version(&super) > REISERFS_MAX_SUPPORTED_VERSION)
307     return 0;
308
309   INFO->version = sb_version(&super);
310   INFO->blocksize = sb_blocksize(&super);
311   INFO->fullblocksize_shift = log2 (sb_blocksize(&super));
312   INFO->blocksize_shift = INFO->fullblocksize_shift - SECTOR_BITS;
313   INFO->cached_slots =
314     (FSYSREISER_CACHE_SIZE >> INFO->fullblocksize_shift) - 1;
315
316 #ifdef REISERDEBUG
317   printf ("reiserfs_mount: version=%d, blocksize=%d\n",
318           INFO->version, INFO->blocksize);
319 #endif /* REISERDEBUG */
320
321   /* Clear node cache. */
322   memset (INFO->blocks, 0, sizeof (INFO->blocks));
323
324   if (sb_blocksize(&super) < FSYSREISER_MIN_BLOCKSIZE
325       || sb_blocksize(&super) > FSYSREISER_MAX_BLOCKSIZE
326       || (SECTOR_SIZE << INFO->blocksize_shift) != sb_blocksize(&super))
327     return 0;
328
329   /* Initialize journal code.  If something fails we end with zero
330    * journal_transactions, so we don't access the journal at all.
331    */
332   INFO->journal_transactions = 0;
333   if (sb_journal_block(&super) != 0 && super.s_journal_dev == 0)
334     {
335       INFO->journal_block = sb_journal_block(&super);
336       INFO->journal_block_count = sb_journal_size(&super);
337       if (is_power_of_two (INFO->journal_block_count))
338         journal_init ();
339
340       /* Read in super block again, maybe it is in the journal */
341       block_read (superblock >> INFO->blocksize_shift,
342                   0, sizeof (struct reiserfs_super_block), (char *) &super);
343     }
344
345   if (! block_read (sb_root_block(&super), 0, INFO->blocksize, (char*) ROOT))
346     return 0;
347
348   cache = ROOT;
349   INFO->tree_depth = __le16_to_cpu(BLOCKHEAD (cache)->blk_level);
350
351 #ifdef REISERDEBUG
352   printf ("root read_in: block=%d, depth=%d\n",
353           sb_root_block(&super), INFO->tree_depth);
354 #endif /* REISERDEBUG */
355
356   if (INFO->tree_depth >= MAX_HEIGHT)
357     return 0;
358   if (INFO->tree_depth == DISK_LEAF_NODE_LEVEL)
359     {
360       /* There is only one node in the whole filesystem,
361        * which is simultanously leaf and root */
362       memcpy (LEAF, ROOT, INFO->blocksize);
363     }
364   return 1;
365 }
366
367 /***************** TREE ACCESSING METHODS *****************************/
368
369 /* I assume you are familiar with the ReiserFS tree, if not go to
370  * http://www.namesys.com/content_table.html
371  *
372  * My tree node cache is organized as following
373  *   0   ROOT node
374  *   1   LEAF node  (if the ROOT is also a LEAF it is copied here
375  *   2-n other nodes on current path from bottom to top.
376  *       if there is not enough space in the cache, the top most are
377  *       omitted.
378  *
379  * I have only two methods to find a key in the tree:
380  *   search_stat(dir_id, objectid) searches for the stat entry (always
381  *       the first entry) of an object.
382  *   next_key() gets the next key in tree order.
383  *
384  * This means, that I can only sequential reads of files are
385  * efficient, but this really doesn't hurt for grub.
386  */
387
388 /* Read in the node at the current path and depth into the node cache.
389  * You must set INFO->blocks[depth] before.
390  */
391 static char *
392 read_tree_node (unsigned int blockNr, int depth)
393 {
394   char* cache = CACHE(depth);
395   int num_cached = INFO->cached_slots;
396   if (depth < num_cached)
397     {
398       /* This is the cached part of the path.  Check if same block is
399        * needed.
400        */
401       if (blockNr == INFO->blocks[depth])
402         return cache;
403     }
404   else
405     cache = CACHE(num_cached);
406
407 #ifdef REISERDEBUG
408   printf ("  next read_in: block=%d (depth=%d)\n",
409           blockNr, depth);
410 #endif /* REISERDEBUG */
411   if (! block_read (blockNr, 0, INFO->blocksize, cache))
412     return 0;
413   /* Make sure it has the right node level */
414   if (__le16_to_cpu(BLOCKHEAD (cache)->blk_level) != depth)
415     {
416       errnum = ERR_FSYS_CORRUPT;
417       return 0;
418     }
419
420   INFO->blocks[depth] = blockNr;
421   return cache;
422 }
423
424 /* Get the next key, i.e. the key following the last retrieved key in
425  * tree order.  INFO->current_ih and
426  * INFO->current_info are adapted accordingly.  */
427 static int
428 next_key (void)
429 {
430   int depth;
431   struct item_head *ih = INFO->current_ih + 1;
432   char *cache;
433
434 #ifdef REISERDEBUG
435   printf ("next_key:\n  old ih: key %d:%d:%d:%d version:%d\n",
436           __le32_to_cpu(INFO->current_ih->ih_key.k_dir_id),
437           __le32_to_cpu(INFO->current_ih->ih_key.k_objectid),
438           __le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_offset),
439           __le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_uniqueness),
440           __le16_to_cpu(INFO->current_ih->ih_version));
441 #endif /* REISERDEBUG */
442
443   if (ih == &ITEMHEAD[__le16_to_cpu(BLOCKHEAD (LEAF)->blk_nr_item)])
444     {
445       depth = DISK_LEAF_NODE_LEVEL;
446       /* The last item, was the last in the leaf node.
447        * Read in the next block
448        */
449       do
450         {
451           if (depth == INFO->tree_depth)
452             {
453               /* There are no more keys at all.
454                * Return a dummy item with MAX_KEY */
455               ih = (struct item_head *) &BLOCKHEAD (LEAF)->blk_right_delim_key;
456               goto found;
457             }
458           depth++;
459 #ifdef REISERDEBUG
460           printf ("  depth=%d, i=%d\n", depth, INFO->next_key_nr[depth]);
461 #endif /* REISERDEBUG */
462         }
463       while (INFO->next_key_nr[depth] == 0);
464
465       if (depth == INFO->tree_depth)
466         cache = ROOT;
467       else if (depth <= INFO->cached_slots)
468         cache = CACHE (depth);
469       else
470         {
471           cache = read_tree_node (INFO->blocks[depth], depth);
472           if (! cache)
473             return 0;
474         }
475
476       do
477         {
478           int nr_item = __le16_to_cpu(BLOCKHEAD (cache)->blk_nr_item);
479           int key_nr = INFO->next_key_nr[depth]++;
480 #ifdef REISERDEBUG
481           printf ("  depth=%d, i=%d/%d\n", depth, key_nr, nr_item);
482 #endif /* REISERDEBUG */
483           if (key_nr == nr_item)
484             /* This is the last item in this block, set the next_key_nr to 0 */
485             INFO->next_key_nr[depth] = 0;
486
487           cache = read_tree_node (dc_block_number(&(DC (cache)[key_nr])), --depth);
488           if (! cache)
489             return 0;
490         }
491       while (depth > DISK_LEAF_NODE_LEVEL);
492
493       ih = ITEMHEAD;
494     }
495  found:
496   INFO->current_ih   = ih;
497   INFO->current_item = &LEAF[__le16_to_cpu(ih->ih_item_location)];
498 #ifdef REISERDEBUG
499   printf ("  new ih: key %d:%d:%d:%d version:%d\n",
500           __le32_to_cpu(INFO->current_ih->ih_key.k_dir_id),
501           __le32_to_cpu(INFO->current_ih->ih_key.k_objectid),
502           __le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_offset),
503           __le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_uniqueness),
504           __le16_to_cpu(INFO->current_ih->ih_version));
505 #endif /* REISERDEBUG */
506   return 1;
507 }
508
509 /* preconditions: reiserfs_mount already executed, therefore
510  *   INFO block is valid
511  * returns: 0 if error (errnum is set),
512  *   nonzero iff we were able to find the key successfully.
513  * postconditions: on a nonzero return, the current_ih and
514  *   current_item fields describe the key that equals the
515  *   searched key.  INFO->next_key contains the next key after
516  *   the searched key.
517  * side effects: messes around with the cache.
518  */
519 static int
520 search_stat (__u32 dir_id, __u32 objectid)
521 {
522   char *cache;
523   int depth;
524   int nr_item;
525   int i;
526   struct item_head *ih;
527 #ifdef REISERDEBUG
528   printf ("search_stat:\n  key %d:%d:0:0\n", dir_id, objectid);
529 #endif /* REISERDEBUG */
530
531   depth = INFO->tree_depth;
532   cache = ROOT;
533
534   while (depth > DISK_LEAF_NODE_LEVEL)
535     {
536       struct key *key;
537       nr_item = __le16_to_cpu(BLOCKHEAD (cache)->blk_nr_item);
538
539       key = KEY (cache);
540
541       for (i = 0; i < nr_item; i++)
542         {
543           if (__le32_to_cpu(key->k_dir_id) > dir_id
544               || (__le32_to_cpu(key->k_dir_id) == dir_id
545                   && (__le32_to_cpu(key->k_objectid) > objectid
546                       || (__le32_to_cpu(key->k_objectid) == objectid
547                           && (__le32_to_cpu(key->u.v1.k_offset)
548                               | __le32_to_cpu(key->u.v1.k_uniqueness)) > 0))))
549             break;
550           key++;
551         }
552
553 #ifdef REISERDEBUG
554       printf ("  depth=%d, i=%d/%d\n", depth, i, nr_item);
555 #endif /* REISERDEBUG */
556       INFO->next_key_nr[depth] = (i == nr_item) ? 0 : i+1;
557       cache = read_tree_node (dc_block_number(&(DC (cache)[i])), --depth);
558       if (! cache)
559         return 0;
560     }
561
562   /* cache == LEAF */
563   nr_item = __le16_to_cpu(BLOCKHEAD (LEAF)->blk_nr_item);
564   ih = ITEMHEAD;
565   for (i = 0; i < nr_item; i++)
566     {
567       if (__le32_to_cpu(ih->ih_key.k_dir_id) == dir_id
568           && __le32_to_cpu(ih->ih_key.k_objectid) == objectid
569           && __le32_to_cpu(ih->ih_key.u.v1.k_offset) == 0
570           && __le32_to_cpu(ih->ih_key.u.v1.k_uniqueness) == 0)
571         {
572 #ifdef REISERDEBUG
573           printf ("  depth=%d, i=%d/%d\n", depth, i, nr_item);
574 #endif /* REISERDEBUG */
575           INFO->current_ih   = ih;
576           INFO->current_item = &LEAF[__le16_to_cpu(ih->ih_item_location)];
577           return 1;
578         }
579       ih++;
580     }
581   errnum = ERR_FSYS_CORRUPT;
582   return 0;
583 }
584
585 int
586 reiserfs_read (char *buf, unsigned len)
587 {
588   unsigned int blocksize;
589   unsigned int offset;
590   unsigned int to_read;
591   char *prev_buf = buf;
592
593 #ifdef REISERDEBUG
594   printf ("reiserfs_read: filepos=%d len=%d, offset=%Lx\n",
595           filepos, len, (__u64) IH_KEY_OFFSET (INFO->current_ih) - 1);
596 #endif /* REISERDEBUG */
597
598   if (__le32_to_cpu(INFO->current_ih->ih_key.k_objectid) != INFO->fileinfo.k_objectid
599       || IH_KEY_OFFSET (INFO->current_ih) > filepos + 1)
600     {
601       search_stat (INFO->fileinfo.k_dir_id, INFO->fileinfo.k_objectid);
602       goto get_next_key;
603     }
604
605   while (! errnum)
606     {
607       if (__le32_to_cpu(INFO->current_ih->ih_key.k_objectid) != INFO->fileinfo.k_objectid) {
608         break;
609       }
610
611       offset = filepos - IH_KEY_OFFSET (INFO->current_ih) + 1;
612       blocksize = __le16_to_cpu(INFO->current_ih->ih_item_len);
613
614 #ifdef REISERDEBUG
615       printf ("  loop: filepos=%d len=%d, offset=%d blocksize=%d\n",
616               filepos, len, offset, blocksize);
617 #endif /* REISERDEBUG */
618
619       if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_DIRECT)
620           && offset < blocksize)
621         {
622 #ifdef REISERDEBUG
623           printf ("direct_read: offset=%d, blocksize=%d\n",
624                   offset, blocksize);
625 #endif /* REISERDEBUG */
626           to_read = blocksize - offset;
627           if (to_read > len)
628             to_read = len;
629
630           memcpy (buf, INFO->current_item + offset, to_read);
631           goto update_buf_len;
632         }
633       else if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_INDIRECT))
634         {
635           blocksize = (blocksize >> 2) << INFO->fullblocksize_shift;
636 #ifdef REISERDEBUG
637           printf ("indirect_read: offset=%d, blocksize=%d\n",
638                   offset, blocksize);
639 #endif /* REISERDEBUG */
640
641           while (offset < blocksize)
642             {
643               __u32 blocknr = __le32_to_cpu(((__u32 *) INFO->current_item)
644                 [offset >> INFO->fullblocksize_shift]);
645               int blk_offset = offset & (INFO->blocksize-1);
646               to_read = INFO->blocksize - blk_offset;
647               if (to_read > len)
648                 to_read = len;
649
650               /* Journal is only for meta data.  Data blocks can be read
651                * directly without using block_read
652                */
653               reiserfs_devread (blocknr << INFO->blocksize_shift,
654                                 blk_offset, to_read, buf);
655             update_buf_len:
656               len -= to_read;
657               buf += to_read;
658               offset += to_read;
659               filepos += to_read;
660               if (len == 0)
661                 goto done;
662             }
663         }
664     get_next_key:
665       next_key ();
666     }
667  done:
668   return errnum ? 0 : buf - prev_buf;
669 }
670
671
672 /* preconditions: reiserfs_mount already executed, therefore
673  *   INFO block is valid
674  * returns: 0 if error, nonzero iff we were able to find the file successfully
675  * postconditions: on a nonzero return, INFO->fileinfo contains the info
676  *   of the file we were trying to look up, filepos is 0 and filemax is
677  *   the size of the file.
678  */
679 static int
680 reiserfs_dir (char *dirname)
681 {
682   struct reiserfs_de_head *de_head;
683   char *rest, ch;
684   __u32 dir_id, objectid, parent_dir_id = 0, parent_objectid = 0;
685 #ifndef STAGE1_5
686   int do_possibilities = 0;
687 #endif /* ! STAGE1_5 */
688   char linkbuf[PATH_MAX];       /* buffer for following symbolic links */
689   int link_count = 0;
690   int mode;
691
692   dir_id = REISERFS_ROOT_PARENT_OBJECTID;
693   objectid = REISERFS_ROOT_OBJECTID;
694
695   while (1)
696     {
697 #ifdef REISERDEBUG
698       printf ("dirname=%s\n", dirname);
699 #endif /* REISERDEBUG */
700
701       /* Search for the stat info first. */
702       if (! search_stat (dir_id, objectid))
703         return 0;
704
705 #ifdef REISERDEBUG
706        printf ("sd_mode=%x sd_size=%d\n",
707                stat_data_v1(INFO->current_ih) ? sd_v1_mode((struct stat_data_v1 *) INFO->current_item) :
708                                                 sd_v2_mode((struct stat_data *) (INFO->current_item)),
709                stat_data_v1(INFO->current_ih) ? sd_v1_size((struct stat_data_v1 *) INFO->current_item) :
710                                                 sd_v2_size((struct stat_data *) INFO->current_item)
711               );
712
713 #endif /* REISERDEBUG */
714       mode = stat_data_v1(INFO->current_ih) ?
715                sd_v1_mode((struct stat_data_v1 *) INFO->current_item) :
716                sd_v2_mode((struct stat_data *) INFO->current_item);
717
718       /* If we've got a symbolic link, then chase it. */
719       if (S_ISLNK (mode))
720         {
721           unsigned int len;
722           if (++link_count > MAX_LINK_COUNT)
723             {
724               errnum = ERR_SYMLINK_LOOP;
725               return 0;
726             }
727
728           /* Get the symlink size. */
729           filemax = stat_data_v1(INFO->current_ih) ?
730                      sd_v1_size((struct stat_data_v1 *) INFO->current_item) :
731                      sd_v2_size((struct stat_data *) INFO->current_item);
732
733           /* Find out how long our remaining name is. */
734           len = 0;
735           while (dirname[len] && !isspace (dirname[len]))
736             len++;
737
738           if (filemax + len > sizeof (linkbuf) - 1)
739             {
740               errnum = ERR_FILELENGTH;
741               return 0;
742             }
743
744           /* Copy the remaining name to the end of the symlink data.
745              Note that DIRNAME and LINKBUF may overlap! */
746           memmove (linkbuf + filemax, dirname, len+1);
747
748           INFO->fileinfo.k_dir_id = dir_id;
749           INFO->fileinfo.k_objectid = objectid;
750           filepos = 0;
751           if (! next_key ()
752               || reiserfs_read (linkbuf, filemax) != filemax)
753             {
754               if (! errnum)
755                 errnum = ERR_FSYS_CORRUPT;
756               return 0;
757             }
758
759 #ifdef REISERDEBUG
760           printf ("symlink=%s\n", linkbuf);
761 #endif /* REISERDEBUG */
762
763           dirname = linkbuf;
764           if (*dirname == '/')
765             {
766               /* It's an absolute link, so look it up in root. */
767               dir_id = REISERFS_ROOT_PARENT_OBJECTID;
768               objectid = REISERFS_ROOT_OBJECTID;
769             }
770           else
771             {
772               /* Relative, so look it up in our parent directory. */
773               dir_id   = parent_dir_id;
774               objectid = parent_objectid;
775             }
776
777           /* Now lookup the new name. */
778           continue;
779         }
780
781       /* if we have a real file (and we're not just printing possibilities),
782          then this is where we want to exit */
783
784       if (! *dirname || isspace (*dirname))
785         {
786           if (! S_ISREG (mode))
787             {
788               errnum = ERR_BAD_FILETYPE;
789               return 0;
790             }
791
792           filepos = 0;
793           filemax = stat_data_v1(INFO->current_ih) ?
794                       sd_v1_size((struct stat_data_v1 *) INFO->current_item) :
795                       sd_v2_size((struct stat_data *) INFO->current_item);
796 #if 0
797           /* If this is a new stat data and size is > 4GB set filemax to
798            * maximum
799            */
800           if (__le16_to_cpu(INFO->current_ih->ih_version) == ITEM_VERSION_2
801               && sd_size_hi((struct stat_data *) INFO->current_item) > 0)
802             filemax = 0xffffffff;
803 #endif
804           INFO->fileinfo.k_dir_id = dir_id;
805           INFO->fileinfo.k_objectid = objectid;
806           return next_key ();
807         }
808
809       /* continue with the file/directory name interpretation */
810       while (*dirname == '/')
811         dirname++;
812       if (! S_ISDIR (mode))
813         {
814           errnum = ERR_BAD_FILETYPE;
815           return 0;
816         }
817       for (rest = dirname; (ch = *rest) && ! isspace (ch) && ch != '/'; rest++);
818       *rest = 0;
819
820 # ifndef STAGE1_5
821       if (print_possibilities && ch != '/')
822         do_possibilities = 1;
823 # endif /* ! STAGE1_5 */
824
825       while (1)
826         {
827           char *name_end;
828           int num_entries;
829
830           if (! next_key ())
831             return 0;
832 #ifdef REISERDEBUG
833           printf ("ih: key %d:%d:%d:%d version:%d\n",
834                   __le32_to_cpu(INFO->current_ih->ih_key.k_dir_id),
835                   __le32_to_cpu(INFO->current_ih->ih_key.k_objectid),
836                   __le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_offset),
837                   __le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_uniqueness),
838                   __le16_to_cpu(INFO->current_ih->ih_version));
839 #endif /* REISERDEBUG */
840
841           if (__le32_to_cpu(INFO->current_ih->ih_key.k_objectid) != objectid)
842             break;
843
844           name_end = INFO->current_item + __le16_to_cpu(INFO->current_ih->ih_item_len);
845           de_head = (struct reiserfs_de_head *) INFO->current_item;
846           num_entries = __le16_to_cpu(INFO->current_ih->u.ih_entry_count);
847           while (num_entries > 0)
848             {
849               char *filename = INFO->current_item + deh_location(de_head);
850               char  tmp = *name_end;
851               if ((deh_state(de_head) & DEH_Visible))
852                 {
853                   int cmp;
854                   /* Directory names in ReiserFS are not null
855                    * terminated.  We write a temporary 0 behind it.
856                    * NOTE: that this may overwrite the first block in
857                    * the tree cache.  That doesn't hurt as long as we
858                    * don't call next_key () in between.
859                    */
860                   *name_end = 0;
861                   cmp = substring (dirname, filename);
862                   *name_end = tmp;
863 # ifndef STAGE1_5
864                   if (do_possibilities)
865                     {
866                       if (cmp <= 0)
867                         {
868                           char fn[PATH_MAX];
869                           struct fsys_reiser_info info_save;
870
871                           if (print_possibilities > 0)
872                             print_possibilities = -print_possibilities;
873                           *name_end = 0;
874                           strcpy(fn, filename);
875                           *name_end = tmp;
876
877                           /* If NAME is "." or "..", do not count it.  */
878                           if (strcmp (fn, ".") != 0 && strcmp (fn, "..") != 0) {
879                             memcpy(&info_save, INFO, sizeof(struct fsys_reiser_info));
880                             search_stat (deh_dir_id(de_head), deh_objectid(de_head));
881                             sd_print_item(INFO->current_ih, INFO->current_item);
882                             printf(" %s\n", fn);
883                             search_stat (dir_id, objectid);
884                             memcpy(INFO, &info_save, sizeof(struct fsys_reiser_info));
885                           }
886                         }
887                     }
888                   else
889 # endif /* ! STAGE1_5 */
890                     if (cmp == 0)
891                       goto found;
892                 }
893               /* The beginning of this name marks the end of the next name.
894                */
895               name_end = filename;
896               de_head++;
897               num_entries--;
898             }
899         }
900
901 # ifndef STAGE1_5
902       if (print_possibilities < 0)
903         return 1;
904 # endif /* ! STAGE1_5 */
905
906       errnum = ERR_FILE_NOT_FOUND;
907       *rest = ch;
908       return 0;
909
910     found:
911       *rest = ch;
912       dirname = rest;
913
914       parent_dir_id = dir_id;
915       parent_objectid = objectid;
916       dir_id = deh_dir_id(de_head);
917       objectid = deh_objectid(de_head);
918     }
919 }
920
921 /*
922  * U-Boot interface functions
923  */
924
925 /*
926  * List given directory
927  *
928  * RETURN: 0 - OK, else grub_error_t errnum
929  */
930 int
931 reiserfs_ls (char *dirname)
932 {
933         char *dir_slash;
934         int res;
935
936         errnum = 0;
937         dir_slash = malloc(strlen(dirname) + 1);
938         if (dir_slash == NULL) {
939                 return ERR_NUMBER_OVERFLOW;
940         }
941         strcpy(dir_slash, dirname);
942         /* add "/" to the directory name */
943         strcat(dir_slash, "/");
944
945         print_possibilities = 1;
946         res = reiserfs_dir (dir_slash);
947         free(dir_slash);
948         if (!res || errnum) {
949                 return errnum;
950         }
951
952         return 0;
953 }
954
955 /*
956  * Open file for reading
957  *
958  * RETURN: >0 - OK, size of opened file
959  *         <0 - ERROR  -grub_error_t errnum
960  */
961 int
962 reiserfs_open (char *filename)
963 {
964         /* open the file */
965         errnum = 0;
966         print_possibilities = 0;
967         if (!reiserfs_dir (filename) || errnum) {
968                 return -errnum;
969         }
970         return filemax;
971 }