366 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			366 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* vi: set sw=4 ts=4: */
 | |
| /*
 | |
|  * ext2fs.h --- ext2fs
 | |
|  *
 | |
|  * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
 | |
|  *
 | |
|  * %Begin-Header%
 | |
|  * This file may be redistributed under the terms of the GNU Public
 | |
|  * License.
 | |
|  * %End-Header%
 | |
|  */
 | |
| 
 | |
| #include "ext2fs.h"
 | |
| #include "bitops.h"
 | |
| #include <string.h>
 | |
| 
 | |
| /*
 | |
|  *  Allocate memory
 | |
|  */
 | |
| errcode_t ext2fs_get_mem(unsigned long size, void *ptr)
 | |
| {
 | |
| 	void **pp = (void **)ptr;
 | |
| 
 | |
| 	*pp = malloc(size);
 | |
| 	if (!*pp)
 | |
| 		return EXT2_ET_NO_MEMORY;
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Free memory
 | |
|  */
 | |
| errcode_t ext2fs_free_mem(void *ptr)
 | |
| {
 | |
| 	void **pp = (void **)ptr;
 | |
| 
 | |
| 	free(*pp);
 | |
| 	*pp = 0;
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *  Resize memory
 | |
|  */
 | |
| errcode_t ext2fs_resize_mem(unsigned long EXT2FS_ATTR((unused)) old_size,
 | |
| 				     unsigned long size, void *ptr)
 | |
| {
 | |
| 	void *p;
 | |
| 
 | |
| 	/* Use "memcpy" for pointer assignments here to avoid problems
 | |
| 	 * with C99 strict type aliasing rules. */
 | |
| 	memcpy(&p, ptr, sizeof (p));
 | |
| 	p = xrealloc(p, size);
 | |
| 	memcpy(ptr, &p, sizeof (p));
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Mark a filesystem superblock as dirty
 | |
|  */
 | |
| void ext2fs_mark_super_dirty(ext2_filsys fs)
 | |
| {
 | |
| 	fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_CHANGED;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Mark a filesystem as changed
 | |
|  */
 | |
| void ext2fs_mark_changed(ext2_filsys fs)
 | |
| {
 | |
| 	fs->flags |= EXT2_FLAG_CHANGED;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Check to see if a filesystem has changed
 | |
|  */
 | |
| int ext2fs_test_changed(ext2_filsys fs)
 | |
| {
 | |
| 	return (fs->flags & EXT2_FLAG_CHANGED);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Mark a filesystem as valid
 | |
|  */
 | |
| void ext2fs_mark_valid(ext2_filsys fs)
 | |
| {
 | |
| 	fs->flags |= EXT2_FLAG_VALID;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Mark a filesystem as NOT valid
 | |
|  */
 | |
| void ext2fs_unmark_valid(ext2_filsys fs)
 | |
| {
 | |
| 	fs->flags &= ~EXT2_FLAG_VALID;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Check to see if a filesystem is valid
 | |
|  */
 | |
| int ext2fs_test_valid(ext2_filsys fs)
 | |
| {
 | |
| 	return (fs->flags & EXT2_FLAG_VALID);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Mark the inode bitmap as dirty
 | |
|  */
 | |
| void ext2fs_mark_ib_dirty(ext2_filsys fs)
 | |
| {
 | |
| 	fs->flags |= EXT2_FLAG_IB_DIRTY | EXT2_FLAG_CHANGED;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Mark the block bitmap as dirty
 | |
|  */
 | |
| void ext2fs_mark_bb_dirty(ext2_filsys fs)
 | |
| {
 | |
| 	fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_CHANGED;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Check to see if a filesystem's inode bitmap is dirty
 | |
|  */
 | |
| int ext2fs_test_ib_dirty(ext2_filsys fs)
 | |
| {
 | |
| 	return (fs->flags & EXT2_FLAG_IB_DIRTY);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Check to see if a filesystem's block bitmap is dirty
 | |
|  */
 | |
| int ext2fs_test_bb_dirty(ext2_filsys fs)
 | |
| {
 | |
| 	return (fs->flags & EXT2_FLAG_BB_DIRTY);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Return the group # of a block
 | |
|  */
 | |
| int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk)
 | |
| {
 | |
| 	return (blk - fs->super->s_first_data_block) /
 | |
| 		fs->super->s_blocks_per_group;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Return the group # of an inode number
 | |
|  */
 | |
| int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino)
 | |
| {
 | |
| 	return (ino - 1) / fs->super->s_inodes_per_group;
 | |
| }
 | |
| 
 | |
| blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
 | |
| 					struct ext2_inode *inode)
 | |
| {
 | |
| 	return inode->i_blocks -
 | |
| 		(inode->i_file_acl ? fs->blocksize >> 9 : 0);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| __u16 ext2fs_swab16(__u16 val)
 | |
| {
 | |
| 	return (val >> 8) | (val << 8);
 | |
| }
 | |
| 
 | |
| __u32 ext2fs_swab32(__u32 val)
 | |
| {
 | |
| 	return ((val>>24) | ((val>>8)&0xFF00) |
 | |
| 		((val<<8)&0xFF0000) | (val<<24));
 | |
| }
 | |
| 
 | |
| int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
 | |
| 					blk_t bitno);
 | |
| 
 | |
| int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
 | |
| 					blk_t bitno)
 | |
| {
 | |
| 	if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
 | |
| 		ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno);
 | |
| 		return 0;
 | |
| 	}
 | |
| 	return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap);
 | |
| }
 | |
| 
 | |
| int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
 | |
| 				       blk_t block)
 | |
| {
 | |
| 	return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap)
 | |
| 				       bitmap,
 | |
| 					  block);
 | |
| }
 | |
| 
 | |
| int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
 | |
| 					 blk_t block)
 | |
| {
 | |
| 	return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
 | |
| 					    block);
 | |
| }
 | |
| 
 | |
| int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
 | |
| 				       blk_t block)
 | |
| {
 | |
| 	return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
 | |
| 					  block);
 | |
| }
 | |
| 
 | |
| int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
 | |
| 				       ext2_ino_t inode)
 | |
| {
 | |
| 	return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
 | |
| 					  inode);
 | |
| }
 | |
| 
 | |
| int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
 | |
| 					 ext2_ino_t inode)
 | |
| {
 | |
| 	return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
 | |
| 				     inode);
 | |
| }
 | |
| 
 | |
| int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
 | |
| 				       ext2_ino_t inode)
 | |
| {
 | |
| 	return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
 | |
| 					  inode);
 | |
| }
 | |
| 
 | |
| void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
 | |
| 					    blk_t block)
 | |
| {
 | |
| 	ext2fs_set_bit(block - bitmap->start, bitmap->bitmap);
 | |
| }
 | |
| 
 | |
| void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
 | |
| 					      blk_t block)
 | |
| {
 | |
| 	ext2fs_clear_bit(block - bitmap->start, bitmap->bitmap);
 | |
| }
 | |
| 
 | |
| int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
 | |
| 					    blk_t block)
 | |
| {
 | |
| 	return ext2fs_test_bit(block - bitmap->start, bitmap->bitmap);
 | |
| }
 | |
| 
 | |
| void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
 | |
| 					    ext2_ino_t inode)
 | |
| {
 | |
| 	ext2fs_set_bit(inode - bitmap->start, bitmap->bitmap);
 | |
| }
 | |
| 
 | |
| void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
 | |
| 					      ext2_ino_t inode)
 | |
| {
 | |
| 	ext2fs_clear_bit(inode - bitmap->start, bitmap->bitmap);
 | |
| }
 | |
| 
 | |
| int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
 | |
| 					   ext2_ino_t inode)
 | |
| {
 | |
| 	return ext2fs_test_bit(inode - bitmap->start, bitmap->bitmap);
 | |
| }
 | |
| 
 | |
| blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
 | |
| {
 | |
| 	return bitmap->start;
 | |
| }
 | |
| 
 | |
| ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
 | |
| {
 | |
| 	return bitmap->start;
 | |
| }
 | |
| 
 | |
| blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
 | |
| {
 | |
| 	return bitmap->end;
 | |
| }
 | |
| 
 | |
| ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
 | |
| {
 | |
| 	return bitmap->end;
 | |
| }
 | |
| 
 | |
| int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
 | |
| 					    blk_t block, int num)
 | |
| {
 | |
| 	int	i;
 | |
| 
 | |
| 	if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
 | |
| 		ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
 | |
| 				   block, bitmap->description);
 | |
| 		return 0;
 | |
| 	}
 | |
| 	for (i=0; i < num; i++) {
 | |
| 		if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
 | |
| 			return 0;
 | |
| 	}
 | |
| 	return 1;
 | |
| }
 | |
| 
 | |
| int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
 | |
| 						 blk_t block, int num)
 | |
| {
 | |
| 	int	i;
 | |
| 
 | |
| 	for (i=0; i < num; i++) {
 | |
| 		if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
 | |
| 			return 0;
 | |
| 	}
 | |
| 	return 1;
 | |
| }
 | |
| 
 | |
| void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
 | |
| 					     blk_t block, int num)
 | |
| {
 | |
| 	int	i;
 | |
| 
 | |
| 	if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
 | |
| 		ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
 | |
| 				   bitmap->description);
 | |
| 		return;
 | |
| 	}
 | |
| 	for (i=0; i < num; i++)
 | |
| 		ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
 | |
| }
 | |
| 
 | |
| void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
 | |
| 						  blk_t block, int num)
 | |
| {
 | |
| 	int	i;
 | |
| 
 | |
| 	for (i=0; i < num; i++)
 | |
| 		ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
 | |
| }
 | |
| 
 | |
| void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
 | |
| 					       blk_t block, int num)
 | |
| {
 | |
| 	int	i;
 | |
| 
 | |
| 	if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
 | |
| 		ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
 | |
| 				   bitmap->description);
 | |
| 		return;
 | |
| 	}
 | |
| 	for (i=0; i < num; i++)
 | |
| 		ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
 | |
| }
 | |
| 
 | |
| void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
 | |
| 						    blk_t block, int num)
 | |
| {
 | |
| 	int	i;
 | |
| 	for (i=0; i < num; i++)
 | |
| 		ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
 | |
| }
 |