home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1998 February / PCOnline_02_1998.iso / filesbbs / win95 / ext2tool.exe / EXT2FS / INODE.C < prev    next >
C/C++ Source or Header  |  1995-05-10  |  6KB  |  251 lines

  1. /*
  2.  * inode.c --- utility routines to read and write inodes
  3.  * 
  4.  * Copyright (C) 1993 Theodore Ts'o.  This file may be redistributed
  5.  * under the terms of the GNU Public License.
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <unistd.h>
  11. #include <stdlib.h>
  12. #include <errno.h>
  13. #include <sys/stat.h>
  14. #include <sys/types.h>
  15.  
  16. #include <linux/ext2_fs.h>
  17.  
  18. #include "ext2fs.h"
  19.  
  20. errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
  21.                  ext2_inode_scan *ret_scan)
  22. {
  23.     ext2_inode_scan    scan;
  24.  
  25.     EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  26.  
  27.     scan = (ext2_inode_scan) malloc(sizeof(struct ext2_struct_inode_scan));
  28.     if (!scan)
  29.         return ENOMEM;
  30.     memset(scan, 0, sizeof(struct ext2_struct_inode_scan));
  31.  
  32.     scan->magic = EXT2_ET_MAGIC_INODE_SCAN;
  33.     scan->fs = fs;
  34.     scan->current_group = -1;
  35.     scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8;
  36.     scan->groups_left = fs->group_desc_count;
  37.     scan->inode_buffer = malloc(scan->inode_buffer_blocks * fs->blocksize);
  38.     if (!scan->inode_buffer) {
  39.         free(scan);
  40.         return ENOMEM;
  41.     }
  42.     *ret_scan = scan;
  43.     return 0;
  44. }
  45.  
  46. void ext2fs_close_inode_scan(ext2_inode_scan scan)
  47. {
  48.     if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
  49.         return;
  50.     
  51.     free(scan->inode_buffer);
  52.     scan->inode_buffer = NULL;
  53.     free(scan);
  54.     return;
  55. }
  56.  
  57. errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ino_t *ino,
  58.                 struct ext2_inode *inode)
  59. {
  60.     errcode_t    retval;
  61.     int        num_blocks;
  62.     
  63.     EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN);
  64.  
  65.     if (!scan->inode_buffer)
  66.         return EINVAL;
  67.     
  68.     if (scan->inodes_left <= 0) {
  69.         if (scan->blocks_left <= 0) {
  70.             do {
  71.                 if (scan->groups_left <= 0) {
  72.                     *ino = 0;
  73.                     return 0;
  74.                 }
  75.                 scan->current_group++;
  76.                 scan->groups_left--;
  77.             
  78.                 scan->current_block =
  79.         scan->fs->group_desc[scan->current_group].bg_inode_table;
  80.                 scan->blocks_left = (EXT2_INODES_PER_GROUP(scan->fs->super) /
  81.                              EXT2_INODES_PER_BLOCK(scan->fs->super));
  82.             } while (scan->current_block == 0);
  83.         } else {
  84.             scan->current_block += scan->inode_buffer_blocks;
  85.         }
  86.         scan->blocks_left -= scan->inode_buffer_blocks;
  87.         num_blocks = scan->inode_buffer_blocks;
  88.         if (scan->blocks_left < 0)
  89.             num_blocks += scan->blocks_left;
  90.         
  91.         scan->inodes_left = EXT2_INODES_PER_BLOCK(scan->fs->super) *
  92.             num_blocks;
  93.  
  94.         retval = io_channel_read_blk(scan->fs->io, scan->current_block,
  95.                          num_blocks, scan->inode_buffer);
  96.         if (retval)
  97.             return EXT2_ET_NEXT_INODE_READ;
  98.         scan->inode_scan_ptr = (struct ext2_inode *) scan->inode_buffer;
  99.     }
  100.     *inode = *scan->inode_scan_ptr++;
  101.     scan->inodes_left--;
  102.     scan->current_inode++;
  103.     *ino = scan->current_inode;
  104.     return 0;
  105. }
  106.  
  107. /*
  108.  * Functions to read and write a single inode.
  109.  */
  110. static char *inode_buffer = 0;
  111. static blk_t inode_buffer_block;
  112. static int inode_buffer_size = 0;
  113.  
  114. errcode_t ext2fs_read_inode (ext2_filsys fs, unsigned long ino,
  115.                  struct ext2_inode * inode)
  116. {
  117.     unsigned long group;
  118.     unsigned long block;
  119.     unsigned long block_nr;
  120.     errcode_t    retval;
  121.     int i;
  122.  
  123.     EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  124.  
  125.     if (ino > fs->super->s_inodes_count)
  126.         return EXT2_ET_BAD_INODE_NUM;
  127.     if (inode_buffer_size != fs->blocksize) {
  128.         if (inode_buffer)
  129.             free(inode_buffer);
  130.         inode_buffer_size = 0;
  131.         inode_buffer = malloc(fs->blocksize);
  132.         if (!inode_buffer)
  133.             return ENOMEM;
  134.         inode_buffer_size = fs->blocksize;
  135.         inode_buffer_block = 0;
  136.     }
  137.         
  138.     group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
  139.     block = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) /
  140.         EXT2_INODES_PER_BLOCK(fs->super);
  141.     i = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) %
  142.         EXT2_INODES_PER_BLOCK(fs->super);
  143.     block_nr = fs->group_desc[group].bg_inode_table + block;
  144.     if (block_nr != inode_buffer_block) {
  145.         retval = io_channel_read_blk(fs->io, block_nr, 1,
  146.                          inode_buffer);
  147.         if (retval)
  148.             return retval;
  149.         inode_buffer_block = block_nr;
  150.     }
  151.     memcpy (inode, (struct ext2_inode *) inode_buffer + i,
  152.         sizeof (struct ext2_inode));
  153.     return 0;
  154. }
  155.  
  156. errcode_t ext2fs_write_inode(ext2_filsys fs, unsigned long ino,
  157.              struct ext2_inode * inode)
  158. {
  159.     unsigned long group;
  160.     unsigned long block;
  161.     unsigned long block_nr;
  162.     errcode_t    retval;
  163.     int i;
  164.  
  165.     EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  166.  
  167.     if (!(fs->flags & EXT2_FLAG_RW))
  168.         return EXT2_ET_RO_FILSYS;
  169.  
  170.     if (ino > fs->super->s_inodes_count)
  171.         return EXT2_ET_BAD_INODE_NUM;
  172.  
  173.     if (inode_buffer_size != fs->blocksize) {
  174.         if (inode_buffer)
  175.             free(inode_buffer);
  176.         inode_buffer_size = 0;
  177.         inode_buffer = malloc(fs->blocksize);
  178.         if (!inode_buffer)
  179.             return ENOMEM;
  180.         inode_buffer_size = fs->blocksize;
  181.         inode_buffer_block = 0;
  182.     }
  183.         
  184.     group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
  185.     block = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) /
  186.         EXT2_INODES_PER_BLOCK(fs->super);
  187.     i = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) %
  188.         EXT2_INODES_PER_BLOCK(fs->super);
  189.     block_nr = fs->group_desc[group].bg_inode_table + block;
  190.     if (inode_buffer_block != block_nr) {
  191.         retval = io_channel_read_blk(fs->io, block_nr, 1,
  192.                          inode_buffer);
  193.         if (retval)
  194.             return retval;
  195.         inode_buffer_block = block_nr;
  196.     }
  197.     memcpy ((struct ext2_inode *) inode_buffer + i, inode,
  198.         sizeof (struct ext2_inode));
  199.     retval = io_channel_write_blk(fs->io, block_nr, 1, inode_buffer);
  200.     if (retval)
  201.         return retval;
  202.     fs->flags |= EXT2_FLAG_CHANGED;
  203.     return 0;
  204. }
  205.  
  206. errcode_t ext2fs_get_blocks(ext2_filsys fs, ino_t ino, blk_t *blocks)
  207. {
  208.     struct ext2_inode    inode;
  209.     int            i;
  210.     errcode_t        retval;
  211.     
  212.     EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  213.  
  214.     if (ino > fs->super->s_inodes_count)
  215.         return EXT2_ET_BAD_INODE_NUM;
  216.  
  217.     if (fs->get_blocks) {
  218.         if (!(*fs->get_blocks)(fs, ino, blocks))
  219.             return 0;
  220.     }
  221.     retval = ext2fs_read_inode(fs, ino, &inode);
  222.     if (retval)
  223.         return retval;
  224.     for (i=0; i < EXT2_N_BLOCKS; i++)
  225.         blocks[i] = inode.i_block[i];
  226.     return 0;
  227. }
  228.  
  229. errcode_t ext2fs_check_directory(ext2_filsys fs, ino_t ino)
  230. {
  231.     struct    ext2_inode    inode;
  232.     errcode_t        retval;
  233.     
  234.     EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  235.  
  236.     if (ino > fs->super->s_inodes_count)
  237.         return EXT2_ET_BAD_INODE_NUM;
  238.  
  239.     if (fs->check_directory)
  240.         return (fs->check_directory)(fs, ino);
  241.     retval = ext2fs_read_inode(fs, ino, &inode);
  242.     if (retval)
  243.         return retval;
  244.     if (!S_ISDIR(inode.i_mode))
  245.         return ENOTDIR;
  246.     return 0;
  247. }
  248.  
  249.     
  250.  
  251.