home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1998 February / PCOnline_02_1998.iso / filesbbs / dos / lread10.exe / INODE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-08  |  9.7 KB  |  353 lines

  1. /* inode.c
  2.  * David Lutz
  3.  * Error messages added by Jason Hunter
  4.  *
  5.  * This file contains functions to mess with inodes
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include <time.h>
  10. #include <stdlib.h>
  11. #define _INODE_C_
  12. #include "ext2.h"
  13. #include "proto.h"
  14.  
  15. /* load_inode
  16.  *
  17.  * Will read the specified inode off the disk and return it.
  18.  *
  19.  * Return NULL for failure
  20.  *        address for success
  21.  */
  22. inode *load_inode( unsigned long inode_no )
  23. {
  24.   static inode res;
  25.   unsigned long loc;
  26.  
  27.   if( inode_no < 1 || inode_no > sb.s_inodes_count )
  28.   {
  29.     fprintf( stderr, "Inode value %ld was out of range in load_inode.\n",
  30.                                inode_no );
  31.     fprintf( stderr, "This is common with large directories  (Shitty DOS)\n" );
  32.     return( NULL );        /* Inode out of range */
  33.   }
  34.  
  35.   inode_no--;            /* adjust inode number */
  36.  
  37.   loc = gt[inode_no / sb.s_inodes_per_group].bg_inode_table * BLOCK_SIZE +
  38.     (inode_no % sb.s_inodes_per_group) * 128; /* sizeof(inode)+2 :-) */
  39.  
  40.   if( readdisk( (byte *)&res, loc, 128 ) != 128 ) /* sizeof(inode)==128 */
  41.   {
  42.     fprintf( stderr, "Disk problem in load_inode.\n");
  43.     return( NULL );        /* Disk problems */
  44.   }
  45.  
  46.   return( &res );        /* Everything OK! */
  47. }
  48.  
  49. /* print_inode
  50.  *
  51.  * print out an inode (good for debugging)
  52.  */
  53. void print_inode( inode *i )
  54. {
  55.   if( i == NULL ) return;    /* Early Bailout */
  56.  
  57.   printf( "File Mode: %o\n", i->i_mode );
  58.   printf( "Owner UID: %u\n", i->i_uid );
  59.   printf( "Size (bytes): %lu\n", i->i_size );
  60.   printf( "Access Time: %s", ctime( &(i->i_atime) ) );
  61.   printf( "Creation Time: %s", ctime( &(i->i_ctime) ) );
  62.   printf( "Modification Time: %s", ctime( &(i->i_mtime ) ) );
  63.   printf( "Deletion Time: %s", ctime( &(i->i_dtime ) ) );
  64.   printf( "Owner GID: %u\n", i->i_gid );
  65.   printf( "Links Count: %u\n", i->i_links_count );
  66.   printf( "(512 byte)Blocks Count: %lu\n", i->i_blocks );
  67.   printf( "File Flags: 0x%lX\n", i->i_flags );
  68.   printf( "File Version: %lu\n", i->i_version );
  69.   printf( "File ACL: %lu\n", i->i_file_acl );
  70.   printf( "Directory ACL: %lu\n", i->i_dir_acl );
  71.   printf( "Fragment Address: %lu\n", i->i_faddr );
  72.   printf( "Fragment Number: %u\n", i->i_frag );
  73.   printf( "Fragment Size: %u\n", i->i_fsize );
  74. }
  75.  
  76. /* block_list
  77.  *
  78.  * This function returns the sequence of blocks used by the inode.
  79.  * The first time it should be called with i equal the inode, all
  80.  * subsequent time with i equal NULL.  If pflg is TRUE then the
  81.  * block number will be printed to stdout.
  82.  * On error returns 0.
  83.  */
  84. unsigned long block_list( inode *i, int pflg )
  85. {
  86.   int j;
  87.   unsigned long block_num;
  88.   static int blocks_per_block;
  89.   static unsigned long blocks_used;
  90.   static unsigned long *sind = NULL;
  91.   static unsigned long *dind = NULL;
  92.   static unsigned long *tind = NULL;
  93.   static unsigned long inode_blocks[15];
  94.   static int blocks_so_far, s_idx, d_idx, t_idx;
  95.  
  96.   if( i != NULL )        /* New inode, do initialization */
  97.     {
  98.       blocks_per_block = BLOCK_SIZE / 4;
  99.       blocks_used = 512 * i->i_blocks / BLOCK_SIZE;
  100.  
  101.       if( sind != NULL )    /* Free sind */
  102.     {
  103.       free( sind );
  104.       sind = NULL;
  105.     }
  106.       if( dind != NULL )    /* Free dind */
  107.     {
  108.       free( dind );
  109.       dind = NULL;
  110.     }
  111.       if( tind != NULL )    /* Free tind */
  112.     {
  113.       free( tind );
  114.       tind = NULL;
  115.     }
  116.  
  117.       /* Save vital inode info */
  118.       for( j=0; j<15; j++ ) inode_blocks[j] = i->i_block[j];
  119.  
  120.       blocks_so_far = 0;    /* Reset block counter */
  121.       s_idx = d_idx = t_idx = 0; /* Reset index counters */
  122.     }
  123.  
  124.   if( blocks_so_far == blocks_used ) /* No more blocks to return */
  125.     return( 0 );        /* Give 'em a zero */
  126.   /* is this an error, Dave? */
  127.  
  128.   if( blocks_so_far < 12 )    /* Block numbers in inode */
  129.     {
  130.       if( pflg )
  131.     printf( "%lu  ", inode_blocks[blocks_so_far] );
  132.       return( inode_blocks[blocks_so_far++] );
  133.     }
  134.  
  135. /*
  136.   if( must load single block )
  137.     1 get from inode or
  138.     2 get from double indirect
  139.       if( must load double block )
  140.     1 get from inode or
  141.     2 get from triple indirect
  142.       if( must load triple indirect )
  143.         1 get from inode
  144. */
  145.  
  146.   /* Load Single Indirect Block? */
  147.   if( s_idx % blocks_per_block == 0 )
  148.     {
  149.       /* Get block number from inode */
  150.       if( s_idx < blocks_per_block )
  151.     block_num = inode_blocks[12];
  152.  
  153.       /* Or get block number from Double Indirect Block */
  154.       else
  155.     {
  156.       /* Load Double Indirect Block? */
  157.       if( d_idx % blocks_per_block == 0 )
  158.         {
  159.           /* Get block number from inode */
  160.           if( d_idx < blocks_per_block )
  161.         block_num = inode_blocks[13];
  162.  
  163.           /* Or get block number from Triple Indirect Block */
  164.           else
  165.         {
  166.           /* Load Triple Indirect Block? */
  167.           if( t_idx % blocks_per_block == 0 )
  168.             {
  169.               if( t_idx == blocks_per_block )
  170.                       {
  171.                         fprintf( stderr, "You want too many blocks in block_list.\n" );
  172.             return( -1 ); /* You want too many blocks */
  173.                       }
  174.  
  175.  
  176.               blocks_so_far++; /* inc for tind block */
  177.               if( pflg )
  178.             printf( "(tind)%lu  ", inode_blocks[14] );
  179.  
  180.               /* Allocate tind block */
  181.               if( (tind = (unsigned long *)malloc( BLOCK_SIZE )) == NULL )
  182.                       {
  183.                         fprintf( stderr, "Memory problem in block_list.\n" );
  184.             return( -1 );    /* Memory problem */
  185.                       }
  186.  
  187.               /* Get block from disk */
  188.               if( readdisk( (byte *)tind, inode_blocks[14]*BLOCK_SIZE,
  189.                    BLOCK_SIZE ) != BLOCK_SIZE )
  190.                       {
  191.                         fprintf( stderr, "Disk problem in block_list.\n" );
  192.             return( -1 );    /* Disk problem */
  193.                       }
  194.  
  195.               t_idx = 0;    /* Reset triple block index */
  196.             }
  197.  
  198.           block_num = tind[t_idx++]; /* exit if w/block_num */
  199.         }
  200.  
  201.           blocks_so_far++;    /* inc for dind block */
  202.           if( pflg )
  203.         printf( "(dind)%lu  ", block_num );
  204.  
  205.           /* See if dind block allocated yet */
  206.           if( dind == NULL )
  207.         {
  208.           if( (dind = (unsigned long *)malloc( BLOCK_SIZE )) == NULL )
  209.                   {
  210.                     fprintf( stderr, "Memory problem in block_list.\n" );
  211.                     return( -1 );    /* Memory problem */
  212.                   }
  213.         }
  214.  
  215.           /* Get block from disk */
  216.           if( readdisk( (byte *)dind, block_num * BLOCK_SIZE,
  217.                BLOCK_SIZE ) != BLOCK_SIZE )
  218.               {
  219.                 fprintf( stderr, "Disk problem in block_list.\n" );
  220.             return( -1 );    /* Disk problem */
  221.               }
  222.  
  223.           d_idx = 0;    /* Reset single block index */
  224.         }
  225.  
  226.       block_num = dind[d_idx++]; /* exit if with block_num */
  227.     }
  228.  
  229.       blocks_so_far++;        /* inc for sind block */
  230.       if( pflg )
  231.     printf( "(sind)%lu  ", block_num );
  232.  
  233.       /* See if sind block allocated yet */
  234.       if( sind == NULL )
  235.     {
  236.       if( (sind = (unsigned long *)malloc( BLOCK_SIZE )) == NULL )
  237.           {
  238.             fprintf( stderr, "Memory problem in block_list.\n" );
  239.             return( -1 );    /* Memory problem */
  240.           }
  241.     }
  242.  
  243.       /* Get block from disk */
  244.       if( readdisk( (byte *)sind, block_num * BLOCK_SIZE, BLOCK_SIZE ) !=
  245.      BLOCK_SIZE )
  246.       {
  247.         fprintf( stderr, "Disk problem in block_list.\n" );
  248.         return( -1 );    /* Disk problem */
  249.       }
  250.  
  251.       s_idx = 0;        /* Reset single block index */
  252.     }
  253.  
  254.   if( pflg )
  255.     printf( "%lu  ", sind[s_idx] );
  256.   return( sind[s_idx++] );    /* return the block number */
  257. }
  258.  
  259. /* read_inode
  260.  *
  261.  * Read size byte from the inode i, if i equal NULL continue reading
  262.  * from last inode.  Returns the number of bytes read, -1 on error.
  263.  */
  264.  
  265. int read_inode( inode *i, byte *buffer, size_t size )
  266. {
  267.   static byte *buf = NULL;
  268.   static unsigned long total_bytes, bytes_so_far, index;
  269.   unsigned long j, block_num;
  270.  
  271.   if( i != NULL )        /* Initialize stuff */
  272.     {
  273.       /* Allocate the buffer */
  274.       if( buf == NULL )
  275.     if( (buf = (byte *)malloc( BLOCK_SIZE )) == NULL )
  276.     {
  277.       fprintf( stderr, "Memory problem in read_inode.\n" );
  278.       return( -1 );        /* Memory Problems */
  279.         }
  280.  
  281.       total_bytes = i->i_size;
  282.       bytes_so_far = 0;
  283.       index = 0;
  284.       block_num = block_list( i, 0 );
  285.       if( block_num == -1 ) exit( -1 );  /* ERROR */
  286.       if( readdisk( buf, block_num * BLOCK_SIZE, BLOCK_SIZE ) !=
  287.      BLOCK_SIZE )
  288.       {
  289.         fprintf( stderr, "Disk problem in read_inode.\n" );
  290.         return( -1 ); /* Disk Problem */
  291.       }
  292.     }
  293.  
  294.   for( j=0; (j<size) && (bytes_so_far<total_bytes); j++ )
  295.     {
  296.       /* Load new block? */
  297.       if( index == BLOCK_SIZE )
  298.     {
  299.       block_num = block_list( NULL, 0 );
  300.       if( readdisk( buf, block_num * BLOCK_SIZE, BLOCK_SIZE ) !=
  301.          BLOCK_SIZE )
  302.       {
  303.         fprintf( stderr, "Disk problem in read_inode.\n" );
  304.         return( -1 ); /* Disk Problem */
  305.       }
  306.       index = 0;
  307.     }
  308.  
  309.       /* Copy bytes */
  310.       buffer[j] = buf[index++];
  311.       bytes_so_far++;
  312.     }
  313.  
  314.   return( j );
  315. }
  316.  
  317. /* print_blocks
  318.  *
  319.  * prints out which blocks are used by the file (useful for debugging)
  320.  */
  321. void print_blocks( inode *i )
  322. {
  323.   unsigned long blocks_used;
  324.   long j, fudge, blocks_per_block;
  325.  
  326.   if( i == NULL ) return;    /* Early Bailout */
  327.  
  328.   blocks_per_block = BLOCK_SIZE / 4;
  329.   blocks_used = 512 * i->i_blocks / BLOCK_SIZE;
  330.  
  331.   fudge = 0;
  332.   if( blocks_used > 12 )    /* single indirect */
  333.     fudge = ((blocks_used-12)/blocks_per_block)+1;
  334.   
  335.   if( blocks_used > 12 + blocks_per_block ) /* double indirect */
  336.     fudge += ((blocks_used-12)/(blocks_per_block*blocks_per_block))+1;
  337.  
  338.   if( blocks_used > 12+(blocks_per_block*blocks_per_block) )  /* triple */
  339.     fudge += ((blocks_used-12)/(blocks_per_block*blocks_per_block*
  340.                 blocks_per_block))+1;
  341.  
  342.   blocks_used -= fudge;
  343.  
  344.   block_list( i, 1 );        /* Get first block */
  345.   for( j=0; j < blocks_used - 1; j++ )
  346.     {
  347.       block_list( NULL, 1 );
  348.       if( !(j%6) ) printf( "\n" );
  349.     }
  350.  
  351.   printf( "\n" );
  352. }
  353.