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