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