/*
 * bitmaps.c --- routines to read, write, and manipulate the inode and
 * block bitmaps.
 *
 * 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 <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif

#include "ext2_fs.h"
#include "ext2fs.h"

static errcode_t make_bitmap(__u32 start, __u32 end, __u32 real_end,
			     const char *descr, char *init_map,
			     ext2fs_generic_bitmap *ret)
{
	ext2fs_generic_bitmap	bitmap;
	errcode_t		retval;
	size_t			size;

	retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap), 
				&bitmap);
	if (retval)
		return retval;

	bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
	bitmap->fs = NULL;
	bitmap->start = start;
	bitmap->end = end;
	bitmap->real_end = real_end;
	bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
	if (descr) {
		retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description);
		if (retval) {
			ext2fs_free_mem(&bitmap);
			return retval;
		}
		strcpy(bitmap->description, descr);
	} else
		bitmap->description = 0;

	size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
	retval = ext2fs_get_mem(size, &bitmap->bitmap);
	if (retval) {
		ext2fs_free_mem(&bitmap->description);
		ext2fs_free_mem(&bitmap);
		return retval;
	}

	if (init_map)
		memcpy(bitmap->bitmap, init_map, size);
	else
		memset(bitmap->bitmap, 0, size);
	*ret = bitmap;
	return 0;
}

errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
					 __u32 end,
					 __u32 real_end,
					 const char *descr,
					 ext2fs_generic_bitmap *ret)
{
	return make_bitmap(start, end, real_end, descr, 0, ret);
}

errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
			     ext2fs_generic_bitmap *dest)
{
	errcode_t		retval;
	ext2fs_generic_bitmap	new_map;

	retval = make_bitmap(src->start, src->end, src->real_end,
			     src->description, src->bitmap, &new_map);
	if (retval)
		return retval;
	new_map->magic = src->magic;
	new_map->fs = src->fs;
	new_map->base_error_code = src->base_error_code;
	*dest = new_map;
	return 0;
}

void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map)
{
	__u32	i, j;

	for (i=map->end+1, j = i - map->start; i <= map->real_end; i++, j++)
		ext2fs_set_bit(j, map->bitmap);

	return;
}	

errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
				       const char *descr,
				       ext2fs_inode_bitmap *ret)
{
	ext2fs_inode_bitmap bitmap;
	errcode_t	retval;
	__u32		start, end, real_end;

	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

	fs->write_bitmaps = ext2fs_write_bitmaps;

	start = 1;
	end = fs->super->s_inodes_count;
	real_end = (EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count);

	retval = ext2fs_allocate_generic_bitmap(start, end, real_end,
						descr, &bitmap);
	if (retval)
		return retval;
	
	bitmap->magic = EXT2_ET_MAGIC_INODE_BITMAP;
	bitmap->fs = fs;
	bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK;
	
	*ret = bitmap;
	return 0;
}

errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
				       const char *descr,
				       ext2fs_block_bitmap *ret)
{
	ext2fs_block_bitmap bitmap;
	errcode_t	retval;
	__u32		start, end, real_end;

	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

	fs->write_bitmaps = ext2fs_write_bitmaps;

	start = fs->super->s_first_data_block;
	end = fs->super->s_blocks_count-1;
	real_end = (EXT2_BLOCKS_PER_GROUP(fs->super)  
		    * fs->group_desc_count)-1 + start;
	
	retval = ext2fs_allocate_generic_bitmap(start, end, real_end,
						descr, &bitmap);
	if (retval)
		return retval;

	bitmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP;
	bitmap->fs = fs;
	bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
	
	*ret = bitmap;
	return 0;
}

errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap,
					ext2_ino_t end, ext2_ino_t *oend)
{
	EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_INODE_BITMAP);
	
	if (end > bitmap->real_end)
		return EXT2_ET_FUDGE_INODE_BITMAP_END;
	if (oend)
		*oend = bitmap->end;
	bitmap->end = end;
	return 0;
}

errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap,
					blk_t end, blk_t *oend)
{
	EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_BLOCK_BITMAP);
	
	if (end > bitmap->real_end)
		return EXT2_ET_FUDGE_BLOCK_BITMAP_END;
	if (oend)
		*oend = bitmap->end;
	bitmap->end = end;
	return 0;
}

void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap)
{
	if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP))
		return;

	memset(bitmap->bitmap, 0,
	       (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
}

void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap)
{
	if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP))
		return;

	memset(bitmap->bitmap, 0,
	       (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
}
