476 lines
9.6 KiB
C
476 lines
9.6 KiB
C
/*
|
|
* 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 = realloc(p, size);
|
|
if (!p)
|
|
return EXT2_ET_NO_MEMORY;
|
|
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_find_first_bit_set(void * addr, unsigned size)
|
|
{
|
|
unsigned char *cp = (unsigned char *) addr;
|
|
int res = 0, d0;
|
|
|
|
if (!size)
|
|
return 0;
|
|
|
|
while ((size > res) && (*cp == 0)) {
|
|
cp++;
|
|
res += 8;
|
|
}
|
|
d0 = ffs(*cp);
|
|
if (d0 == 0)
|
|
return size;
|
|
|
|
return res + d0 - 1;
|
|
}
|
|
|
|
int ext2fs_find_next_bit_set (void * addr, int size, int offset)
|
|
{
|
|
unsigned char * p;
|
|
int set = 0, bit = offset & 7, res = 0, d0;
|
|
|
|
res = offset >> 3;
|
|
p = ((unsigned char *) addr) + res;
|
|
|
|
if (bit) {
|
|
set = ffs(*p & ~((1 << bit) - 1));
|
|
if (set)
|
|
return (offset & ~7) + set - 1;
|
|
p++;
|
|
res += 8;
|
|
}
|
|
while ((size > res) && (*p == 0)) {
|
|
p++;
|
|
res += 8;
|
|
}
|
|
d0 = ffs(*p);
|
|
if (d0 == 0)
|
|
return size;
|
|
|
|
return (res + d0 - 1);
|
|
}
|
|
|
|
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)
|
|
{
|
|
#ifdef EXT2FS_DEBUG_FAST_OPS
|
|
if ((block < bitmap->start) || (block > bitmap->end)) {
|
|
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
|
|
bitmap->description);
|
|
return;
|
|
}
|
|
#endif
|
|
ext2fs_set_bit(block - bitmap->start, bitmap->bitmap);
|
|
}
|
|
|
|
void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
|
|
blk_t block)
|
|
{
|
|
#ifdef EXT2FS_DEBUG_FAST_OPS
|
|
if ((block < bitmap->start) || (block > bitmap->end)) {
|
|
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK,
|
|
block, bitmap->description);
|
|
return;
|
|
}
|
|
#endif
|
|
ext2fs_clear_bit(block - bitmap->start, bitmap->bitmap);
|
|
}
|
|
|
|
int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
|
|
blk_t block)
|
|
{
|
|
#ifdef EXT2FS_DEBUG_FAST_OPS
|
|
if ((block < bitmap->start) || (block > bitmap->end)) {
|
|
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
|
|
block, bitmap->description);
|
|
return 0;
|
|
}
|
|
#endif
|
|
return ext2fs_test_bit(block - bitmap->start, bitmap->bitmap);
|
|
}
|
|
|
|
void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
|
|
ext2_ino_t inode)
|
|
{
|
|
#ifdef EXT2FS_DEBUG_FAST_OPS
|
|
if ((inode < bitmap->start) || (inode > bitmap->end)) {
|
|
ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_MARK,
|
|
inode, bitmap->description);
|
|
return;
|
|
}
|
|
#endif
|
|
ext2fs_set_bit(inode - bitmap->start, bitmap->bitmap);
|
|
}
|
|
|
|
void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
|
|
ext2_ino_t inode)
|
|
{
|
|
#ifdef EXT2FS_DEBUG_FAST_OPS
|
|
if ((inode < bitmap->start) || (inode > bitmap->end)) {
|
|
ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_UNMARK,
|
|
inode, bitmap->description);
|
|
return;
|
|
}
|
|
#endif
|
|
ext2fs_clear_bit(inode - bitmap->start, bitmap->bitmap);
|
|
}
|
|
|
|
int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
|
|
ext2_ino_t inode)
|
|
{
|
|
#ifdef EXT2FS_DEBUG_FAST_OPS
|
|
if ((inode < bitmap->start) || (inode > bitmap->end)) {
|
|
ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_TEST,
|
|
inode, bitmap->description);
|
|
return 0;
|
|
}
|
|
#endif
|
|
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;
|
|
|
|
#ifdef EXT2FS_DEBUG_FAST_OPS
|
|
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
|
|
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
|
|
block, bitmap->description);
|
|
return 0;
|
|
}
|
|
#endif
|
|
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;
|
|
|
|
#ifdef EXT2FS_DEBUG_FAST_OPS
|
|
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
|
|
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
|
|
bitmap->description);
|
|
return;
|
|
}
|
|
#endif
|
|
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;
|
|
|
|
#ifdef EXT2FS_DEBUG_FAST_OPS
|
|
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
|
|
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
|
|
bitmap->description);
|
|
return;
|
|
}
|
|
#endif
|
|
for (i=0; i < num; i++)
|
|
ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
|
|
}
|