• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
substring(const char * s1,const char * s2)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 
sd_print_item(struct item_head * ih,char * item)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
journal_read(int block,int len,char * buffer)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
block_read(unsigned int blockNr,int start,int len,char * buffer)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
journal_init(void)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
reiserfs_mount(unsigned part_length)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 *
read_tree_node(unsigned int blockNr,int depth)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
next_key(void)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
search_stat(__u32 dir_id,__u32 objectid)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
reiserfs_read(char * buf,unsigned len)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
reiserfs_dir(char * dirname)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
reiserfs_ls(char * dirname)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
reiserfs_open(char * filename)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 }
972