int nextchar() { int c=dbuf[fwd]; if(c!=EOF) { fwd++; return c; } if(end_of_first_half(fwd)) //then load next buffer { read_disk_block(dbuf+SINGLE_BUF_SIZE); ++fwd; c=dbuf[fwd]; fwd++; return c; } else if(end_of_second_half(fwd)) //then load first buffer { read_disk_block(dbuf); fwd=0; c=dbuf[fwd]; fwd++; return c; } else return EOF; }
static int journal_read( __u32 block, __u32 len, char *buffer ) { return read_disk_block( INFO->file, (INFO->journal_block + block), 0, len, buffer ); }
init_dbuf(const char*filename) { dbuf[SINGLE_BUF_SIZE-1]=EOF; dbuf[2*SINGLE_BUF_SIZE-1]=EOF; fp=fopen(filename,"r"); if(!fp) { fprintf(stderr,"Cannot open %s",filename); perror(" "); return 1; } read_disk_block(dbuf); }
static int reiserfs_read_data( char *buf, __u32 len ) { __u32 blocksize; __u32 offset; __u32 to_read; char *prev_buf = buf; errnum = 0; DEBUG_F( "reiserfs_read_data: INFO->file->pos=%Lu len=%u, offset=%Lu\n", INFO->file->pos, len, (__u64) IH_KEY_OFFSET(INFO->current_ih) - 1 ); if ( INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid || IH_KEY_OFFSET( INFO->current_ih ) > INFO->file->pos + 1 ) { search_stat( INFO->fileinfo.k_dir_id, INFO->fileinfo.k_objectid ); goto get_next_key; } while ( errnum == 0 ) { if ( INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid ) break; offset = INFO->file->pos - IH_KEY_OFFSET( INFO->current_ih ) + 1; blocksize = ih_item_len(INFO->current_ih); DEBUG_F( " loop: INFO->file->pos=%Lu len=%u, offset=%u blocksize=%u\n", INFO->file->pos, len, offset, blocksize ); if ( IH_KEY_ISTYPE( INFO->current_ih, TYPE_DIRECT ) && offset < blocksize ) { to_read = blocksize - offset; if ( to_read > len ) to_read = len; memcpy( buf, INFO->current_item + offset, to_read ); goto update_buf_len; } else if ( IH_KEY_ISTYPE( INFO->current_ih, TYPE_INDIRECT ) ) { blocksize = ( blocksize >> 2 ) << INFO->blocksize_shift; while ( offset < blocksize ) { __u32 blocknr = le32_to_cpu(((__u32 *) INFO->current_item)[offset >> INFO->blocksize_shift]); int blk_offset = offset & (INFO->blocksize - 1); to_read = INFO->blocksize - blk_offset; if ( to_read > len ) to_read = len; /* Journal is only for meta data. Data blocks can be read directly without using block_read */ read_disk_block( INFO->file, blocknr, blk_offset, to_read, buf ); update_buf_len: len -= to_read; buf += to_read; offset += to_read; INFO->file->pos += to_read; if ( len == 0 ) goto done; } } get_next_key: next_key(); }
/* check filesystem types and read superblock into memory buffer */ static int reiserfs_read_super( void ) { struct reiserfs_super_block super; __u64 superblock = REISERFS_SUPERBLOCK_BLOCK; if (read_disk_block(INFO->file, superblock, 0, sizeof(super), &super) != sizeof(super)) { DEBUG_F("read_disk_block failed!\n"); return 0; } DEBUG_F( "Found super->magic: \"%s\"\n", super.s_magic ); if( strcmp( REISER2FS_SUPER_MAGIC_STRING, super.s_magic ) != 0 && strcmp( REISERFS_SUPER_MAGIC_STRING, super.s_magic ) != 0 ) { /* Try old super block position */ superblock = REISERFS_OLD_SUPERBLOCK_BLOCK; if (read_disk_block( INFO->file, superblock, 0, sizeof (super), &super ) != sizeof(super)) { DEBUG_F("read_disk_block failed!\n"); return 0; } if ( strcmp( REISER2FS_SUPER_MAGIC_STRING, super.s_magic ) != 0 && strcmp( REISERFS_SUPER_MAGIC_STRING, super.s_magic ) != 0 ) { /* pre journaling super block - untested */ if ( strcmp( REISERFS_SUPER_MAGIC_STRING, (char *) ((__u32) &super + 20 ) ) != 0 ) return 0; super.s_blocksize = cpu_to_le16(REISERFS_OLD_BLOCKSIZE); super.s_journal_block = 0; super.s_version = 0; } } DEBUG_F( "ReiserFS superblock data:\n" ); DEBUG_F( "Block count: %u\n", le32_to_cpu(super.s_block_count) ) DEBUG_F( "Free blocks: %u\n", le32_to_cpu(super.s_free_blocks) ); DEBUG_F( "Journal block: %u\n", le32_to_cpu(super.s_journal_block) ); DEBUG_F( "Journal size (in blocks): %u\n", le32_to_cpu(super.s_orig_journal_size) ); DEBUG_F( "Root block: %u\n\n", le32_to_cpu(super.s_root_block) ); INFO->version = le16_to_cpu(super.s_version); INFO->blocksize = le16_to_cpu(super.s_blocksize); INFO->blocksize_shift = log2( INFO->blocksize ); INFO->journal_block = le32_to_cpu(super.s_journal_block); INFO->journal_block_count = le32_to_cpu(super.s_orig_journal_size); INFO->cached_slots = (FSYSREISER_CACHE_SIZE >> INFO->blocksize_shift) - 1; /* At this point, we've found a valid superblock. If we run into problems * mounting the FS, the user should probably know. */ /* A few sanity checks ... */ if ( INFO->version > REISERFS_MAX_SUPPORTED_VERSION ) { prom_printf( "ReiserFS: Unsupported version field: %u\n", INFO->version ); return 0; } if ( INFO->blocksize < FSYSREISER_MIN_BLOCKSIZE || INFO->blocksize > FSYSREISER_MAX_BLOCKSIZE ) { prom_printf( "ReiserFS: Unsupported block size: %u\n", INFO->blocksize ); return 0; } /* Setup the journal.. */ if ( INFO->journal_block != 0 ) { if ( !is_power_of_two( INFO->journal_block_count ) ) { prom_printf( "ReiserFS: Unsupported journal size, " "not a power of 2: %u\n", INFO->journal_block_count ); return 0; } journal_init(); /* Read in super block again, maybe it is in the journal */ block_read( superblock, 0, sizeof (struct reiserfs_super_block), (char *) &super ); } /* Read in the root block */ if ( !block_read( le32_to_cpu(super.s_root_block), 0, INFO->blocksize, ROOT ) ) { prom_printf( "ReiserFS: Failed to read in root block\n" ); return 0; } /* The root node is always the "deepest", so we can determine the hieght of the tree using it. */ INFO->tree_depth = blkh_level(BLOCKHEAD(ROOT)); DEBUG_F( "root read_in: block=%u, depth=%u\n", le32_to_cpu(super.s_root_block), INFO->tree_depth ); if ( INFO->tree_depth >= REISERFS_MAX_TREE_HEIGHT ) { prom_printf( "ReiserFS: Unsupported tree depth (too deep): %u\n", INFO->tree_depth ); return 0; } if ( INFO->tree_depth == BLKH_LEVEL_LEAF ) { /* There is only one node in the whole filesystem, which is simultanously leaf and root */ memcpy( LEAF, ROOT, INFO->blocksize ); } return 1; }
/* Read a block from ReiserFS file system, taking the journal into * account. If the block nr is in the journal, the block from the * journal taken. */ static int block_read( __u32 blockNr, __u32 start, __u32 len, char *buffer ) { __u32 transactions = INFO->journal_transactions; __u32 desc_block = INFO->journal_first_desc; __u32 journal_mask = INFO->journal_block_count - 1; __u32 translatedNr = blockNr; __u32 *journal_table = JOURNAL_START; // DEBUG_F( "block_read( %u, %u, %u, ..)\n", blockNr, start, len ); while ( transactions-- > 0 ) { int i = 0; int j_len; if ( *journal_table != 0xffffffff ) { /* Search for the blockNr in cached journal */ j_len = le32_to_cpu(*journal_table++); while ( i++ < j_len ) { if ( le32_to_cpu(*journal_table++) == blockNr ) { journal_table += j_len - i; goto found; } } } else { /* This is the end of cached journal marker. The remaining * transactions are still on disk. */ struct reiserfs_journal_desc desc; struct reiserfs_journal_commit commit; if ( !journal_read( desc_block, sizeof(desc), (char *) &desc ) ) return 0; j_len = le32_to_cpu(desc.j_len); while ( i < j_len && i < JOURNAL_TRANS_HALF ) if ( le32_to_cpu(desc.j_realblock[i++]) == blockNr ) goto found; if ( j_len >= JOURNAL_TRANS_HALF ) { int commit_block = ( desc_block + 1 + j_len ) & journal_mask; if ( !journal_read( commit_block, sizeof(commit), (char *) &commit ) ) return 0; while ( i < j_len ) if ( le32_to_cpu(commit.j_realblock[i++ - JOURNAL_TRANS_HALF]) == blockNr ) goto found; } } goto not_found; found: translatedNr = INFO->journal_block + ( ( desc_block + i ) & journal_mask ); DEBUG_F( "block_read: block %u is mapped to journal block %u.\n", blockNr, translatedNr - INFO->journal_block ); /* We must continue the search, as this block may be overwritten in * later transactions. */ not_found: desc_block = (desc_block + 2 + j_len) & journal_mask; } return read_disk_block( INFO->file, translatedNr, start, len, buffer ); }