home *** CD-ROM | disk | FTP | other *** search
- /* inode.c
- * David Lutz
- * Error messages added by Jason Hunter
- *
- * This file contains functions to mess with inodes
- */
-
- #include <stdio.h>
- #include <time.h>
- #include <stdlib.h>
- #define _INODE_C_
- #include "ext2.h"
- #include "proto.h"
-
- /* load_inode
- *
- * Will read the specified inode off the disk and return it.
- *
- * Return NULL for failure
- * address for success
- */
- inode *load_inode( unsigned long inode_no )
- {
- static inode res;
- unsigned long loc;
-
- if( inode_no < 1 || inode_no > sb.s_inodes_count )
- {
- fprintf( stderr, "Inode value %ld was out of range in load_inode.\n",
- inode_no );
- fprintf( stderr, "This is common with large directories (Shitty DOS)\n" );
- return( NULL ); /* Inode out of range */
- }
-
- inode_no--; /* adjust inode number */
-
- loc = gt[inode_no / sb.s_inodes_per_group].bg_inode_table * BLOCK_SIZE +
- (inode_no % sb.s_inodes_per_group) * 128; /* sizeof(inode)+2 :-) */
-
- if( readdisk( (byte *)&res, loc, 128 ) != 128 ) /* sizeof(inode)==128 */
- {
- fprintf( stderr, "Disk problem in load_inode.\n");
- return( NULL ); /* Disk problems */
- }
-
- return( &res ); /* Everything OK! */
- }
-
- /* print_inode
- *
- * print out an inode (good for debugging)
- */
- void print_inode( inode *i )
- {
- if( i == NULL ) return; /* Early Bailout */
-
- printf( "File Mode: %o\n", i->i_mode );
- printf( "Owner UID: %u\n", i->i_uid );
- printf( "Size (bytes): %lu\n", i->i_size );
- printf( "Access Time: %s", ctime( &(i->i_atime) ) );
- printf( "Creation Time: %s", ctime( &(i->i_ctime) ) );
- printf( "Modification Time: %s", ctime( &(i->i_mtime ) ) );
- printf( "Deletion Time: %s", ctime( &(i->i_dtime ) ) );
- printf( "Owner GID: %u\n", i->i_gid );
- printf( "Links Count: %u\n", i->i_links_count );
- printf( "(512 byte)Blocks Count: %lu\n", i->i_blocks );
- printf( "File Flags: 0x%lX\n", i->i_flags );
- printf( "File Version: %lu\n", i->i_version );
- printf( "File ACL: %lu\n", i->i_file_acl );
- printf( "Directory ACL: %lu\n", i->i_dir_acl );
- printf( "Fragment Address: %lu\n", i->i_faddr );
- printf( "Fragment Number: %u\n", i->i_frag );
- printf( "Fragment Size: %u\n", i->i_fsize );
- }
-
- /* block_list
- *
- * This function returns the sequence of blocks used by the inode.
- * The first time it should be called with i equal the inode, all
- * subsequent time with i equal NULL. If pflg is TRUE then the
- * block number will be printed to stdout.
- * On error returns 0.
- */
- unsigned long block_list( inode *i, int pflg )
- {
- int j;
- unsigned long block_num;
- static int blocks_per_block;
- static unsigned long blocks_used;
- static unsigned long *sind = NULL;
- static unsigned long *dind = NULL;
- static unsigned long *tind = NULL;
- static unsigned long inode_blocks[15];
- static int blocks_so_far, s_idx, d_idx, t_idx;
-
- if( i != NULL ) /* New inode, do initialization */
- {
- blocks_per_block = BLOCK_SIZE / 4;
- blocks_used = 512 * i->i_blocks / BLOCK_SIZE;
-
- if( sind != NULL ) /* Free sind */
- {
- free( sind );
- sind = NULL;
- }
- if( dind != NULL ) /* Free dind */
- {
- free( dind );
- dind = NULL;
- }
- if( tind != NULL ) /* Free tind */
- {
- free( tind );
- tind = NULL;
- }
-
- /* Save vital inode info */
- for( j=0; j<15; j++ ) inode_blocks[j] = i->i_block[j];
-
- blocks_so_far = 0; /* Reset block counter */
- s_idx = d_idx = t_idx = 0; /* Reset index counters */
- }
-
- if( blocks_so_far == blocks_used ) /* No more blocks to return */
- return( 0 ); /* Give 'em a zero */
- /* is this an error, Dave? */
-
- if( blocks_so_far < 12 ) /* Block numbers in inode */
- {
- if( pflg )
- printf( "%lu ", inode_blocks[blocks_so_far] );
- return( inode_blocks[blocks_so_far++] );
- }
-
- /*
- if( must load single block )
- 1 get from inode or
- 2 get from double indirect
- if( must load double block )
- 1 get from inode or
- 2 get from triple indirect
- if( must load triple indirect )
- 1 get from inode
- */
-
- /* Load Single Indirect Block? */
- if( s_idx % blocks_per_block == 0 )
- {
- /* Get block number from inode */
- if( s_idx < blocks_per_block )
- block_num = inode_blocks[12];
-
- /* Or get block number from Double Indirect Block */
- else
- {
- /* Load Double Indirect Block? */
- if( d_idx % blocks_per_block == 0 )
- {
- /* Get block number from inode */
- if( d_idx < blocks_per_block )
- block_num = inode_blocks[13];
-
- /* Or get block number from Triple Indirect Block */
- else
- {
- /* Load Triple Indirect Block? */
- if( t_idx % blocks_per_block == 0 )
- {
- if( t_idx == blocks_per_block )
- {
- fprintf( stderr, "You want too many blocks in block_list.\n" );
- return( -1 ); /* You want too many blocks */
- }
-
-
- blocks_so_far++; /* inc for tind block */
- if( pflg )
- printf( "(tind)%lu ", inode_blocks[14] );
-
- /* Allocate tind block */
- if( (tind = (unsigned long *)malloc( BLOCK_SIZE )) == NULL )
- {
- fprintf( stderr, "Memory problem in block_list.\n" );
- return( -1 ); /* Memory problem */
- }
-
- /* Get block from disk */
- if( readdisk( (byte *)tind, inode_blocks[14]*BLOCK_SIZE,
- BLOCK_SIZE ) != BLOCK_SIZE )
- {
- fprintf( stderr, "Disk problem in block_list.\n" );
- return( -1 ); /* Disk problem */
- }
-
- t_idx = 0; /* Reset triple block index */
- }
-
- block_num = tind[t_idx++]; /* exit if w/block_num */
- }
-
- blocks_so_far++; /* inc for dind block */
- if( pflg )
- printf( "(dind)%lu ", block_num );
-
- /* See if dind block allocated yet */
- if( dind == NULL )
- {
- if( (dind = (unsigned long *)malloc( BLOCK_SIZE )) == NULL )
- {
- fprintf( stderr, "Memory problem in block_list.\n" );
- return( -1 ); /* Memory problem */
- }
- }
-
- /* Get block from disk */
- if( readdisk( (byte *)dind, block_num * BLOCK_SIZE,
- BLOCK_SIZE ) != BLOCK_SIZE )
- {
- fprintf( stderr, "Disk problem in block_list.\n" );
- return( -1 ); /* Disk problem */
- }
-
- d_idx = 0; /* Reset single block index */
- }
-
- block_num = dind[d_idx++]; /* exit if with block_num */
- }
-
- blocks_so_far++; /* inc for sind block */
- if( pflg )
- printf( "(sind)%lu ", block_num );
-
- /* See if sind block allocated yet */
- if( sind == NULL )
- {
- if( (sind = (unsigned long *)malloc( BLOCK_SIZE )) == NULL )
- {
- fprintf( stderr, "Memory problem in block_list.\n" );
- return( -1 ); /* Memory problem */
- }
- }
-
- /* Get block from disk */
- if( readdisk( (byte *)sind, block_num * BLOCK_SIZE, BLOCK_SIZE ) !=
- BLOCK_SIZE )
- {
- fprintf( stderr, "Disk problem in block_list.\n" );
- return( -1 ); /* Disk problem */
- }
-
- s_idx = 0; /* Reset single block index */
- }
-
- if( pflg )
- printf( "%lu ", sind[s_idx] );
- return( sind[s_idx++] ); /* return the block number */
- }
-
- /* read_inode
- *
- * Read size byte from the inode i, if i equal NULL continue reading
- * from last inode. Returns the number of bytes read, -1 on error.
- */
-
- int read_inode( inode *i, byte *buffer, size_t size )
- {
- static byte *buf = NULL;
- static unsigned long total_bytes, bytes_so_far, index;
- unsigned long j, block_num;
-
- if( i != NULL ) /* Initialize stuff */
- {
- /* Allocate the buffer */
- if( buf == NULL )
- if( (buf = (byte *)malloc( BLOCK_SIZE )) == NULL )
- {
- fprintf( stderr, "Memory problem in read_inode.\n" );
- return( -1 ); /* Memory Problems */
- }
-
- total_bytes = i->i_size;
- bytes_so_far = 0;
- index = 0;
- block_num = block_list( i, 0 );
- if( block_num == -1 ) exit( -1 ); /* ERROR */
- if( readdisk( buf, block_num * BLOCK_SIZE, BLOCK_SIZE ) !=
- BLOCK_SIZE )
- {
- fprintf( stderr, "Disk problem in read_inode.\n" );
- return( -1 ); /* Disk Problem */
- }
- }
-
- for( j=0; (j<size) && (bytes_so_far<total_bytes); j++ )
- {
- /* Load new block? */
- if( index == BLOCK_SIZE )
- {
- block_num = block_list( NULL, 0 );
- if( readdisk( buf, block_num * BLOCK_SIZE, BLOCK_SIZE ) !=
- BLOCK_SIZE )
- {
- fprintf( stderr, "Disk problem in read_inode.\n" );
- return( -1 ); /* Disk Problem */
- }
- index = 0;
- }
-
- /* Copy bytes */
- buffer[j] = buf[index++];
- bytes_so_far++;
- }
-
- return( j );
- }
-
- /* print_blocks
- *
- * prints out which blocks are used by the file (useful for debugging)
- */
- void print_blocks( inode *i )
- {
- unsigned long blocks_used;
- long j, fudge, blocks_per_block;
-
- if( i == NULL ) return; /* Early Bailout */
-
- blocks_per_block = BLOCK_SIZE / 4;
- blocks_used = 512 * i->i_blocks / BLOCK_SIZE;
-
- fudge = 0;
- if( blocks_used > 12 ) /* single indirect */
- fudge = ((blocks_used-12)/blocks_per_block)+1;
-
- if( blocks_used > 12 + blocks_per_block ) /* double indirect */
- fudge += ((blocks_used-12)/(blocks_per_block*blocks_per_block))+1;
-
- if( blocks_used > 12+(blocks_per_block*blocks_per_block) ) /* triple */
- fudge += ((blocks_used-12)/(blocks_per_block*blocks_per_block*
- blocks_per_block))+1;
-
- blocks_used -= fudge;
-
- block_list( i, 1 ); /* Get first block */
- for( j=0; j < blocks_used - 1; j++ )
- {
- block_list( NULL, 1 );
- if( !(j%6) ) printf( "\n" );
- }
-
- printf( "\n" );
- }
-