Esempio n. 1
0
/*
 * Add a directory block to the directory block list
 */
errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
			       int blockcnt)
{
	struct ext2_db_entry 	*new_entry;
	errcode_t		retval;
	unsigned long		old_size;
	
	EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);

	if (dblist->count >= dblist->size) {
		old_size = dblist->size * sizeof(struct ext2_db_entry);
		dblist->size += 100;
		retval = ext2fs_resize_mem(old_size, (size_t) dblist->size *
					   sizeof(struct ext2_db_entry),
					   &dblist->list);
		if (retval) {
			dblist->size -= 100;
			return retval;
		}
	}
	new_entry = dblist->list + ( (int) dblist->count++);
	new_entry->blk = blk;
	new_entry->ino = ino;
	new_entry->blockcnt = blockcnt;

	dblist->sorted = 0;

	return 0;
}
Esempio n. 2
0
/*
 * This subroutine is called during pass1 to create a directory info
 * entry.  During pass1, the passed-in parent is 0; it will get filled
 * in during pass2.  
 */
void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
{
	struct dx_dir_info *dir;
	int		i, j;
	errcode_t	retval;
	unsigned long	old_size;

#if 0
	printf("add_dx_dir_info for inode %lu...\n", ino);
#endif
	if (!ctx->dx_dir_info) {
		ctx->dx_dir_info_count = 0;
		ctx->dx_dir_info_size = 100; /* Guess */
		ctx->dx_dir_info  = (struct dx_dir_info *)
			e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
					       * sizeof (struct dx_dir_info),
					       "directory map");
	}
	
	if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
		old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
		ctx->dx_dir_info_size += 10;
		retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
					   sizeof(struct dx_dir_info),
					   (void **) &ctx->dx_dir_info);
		if (retval) {
			ctx->dx_dir_info_size -= 10;
			return;
		}
	}

	/*
	 * Normally, add_dx_dir_info is called with each inode in
	 * sequential order; but once in a while (like when pass 3
	 * needs to recreate the root directory or lost+found
	 * directory) it is called out of order.  In those cases, we
	 * need to move the dx_dir_info entries down to make room, since
	 * the dx_dir_info array needs to be sorted by inode number for
	 * get_dx_dir_info()'s sake.
	 */
	if (ctx->dx_dir_info_count &&
	    ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
		for (i = ctx->dx_dir_info_count-1; i > 0; i--)
			if (ctx->dx_dir_info[i-1].ino < ino)
				break;
		dir = &ctx->dx_dir_info[i];
		if (dir->ino != ino) 
			for (j = ctx->dx_dir_info_count++; j > i; j--)
				ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
	} else
		dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
	
	dir->ino = ino;
	dir->numblocks = num_blocks;
	dir->hashversion = 0;
	dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
				       * sizeof (struct dx_dirblock_info),
				       "dx_block info array");

}
Esempio n. 3
0
/*
 * insert_refcount_el() --- Insert a new entry into the sorted list at a
 * 	specified position.
 */
static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
						 ea_key_t ea_key, int pos)
{
	struct ea_refcount_el 	*el;
	errcode_t		retval;
	size_t			new_size = 0;
	int			num;

	if (refcount->count >= refcount->size) {
		new_size = refcount->size + 100;
#ifdef DEBUG
		printf("Reallocating refcount %d entries...\n", new_size);
#endif
		retval = ext2fs_resize_mem((size_t) refcount->size *
					   sizeof(struct ea_refcount_el),
					   (size_t) new_size *
					   sizeof(struct ea_refcount_el),
					   &refcount->list);
		if (retval)
			return 0;
		refcount->size = new_size;
	}
	num = (int) refcount->count - pos;
	if (num < 0)
		return 0;	/* should never happen */
	if (num) {
		memmove(&refcount->list[pos+1], &refcount->list[pos],
			sizeof(struct ea_refcount_el) * num);
	}
	refcount->count++;
	el = &refcount->list[pos];
	el->ea_key = ea_key;
	el->ea_value = 0;
	return el;
}
Esempio n. 4
0
void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
{
	struct dx_dir_info *dir;
	int		i, j;
	errcode_t	retval;
	unsigned long	old_size;

#if 0
	printf("add_dx_dir_info for inode %lu...\n", ino);
#endif
	if (!ctx->dx_dir_info) {
		ctx->dx_dir_info_count = 0;
		ctx->dx_dir_info_size = 100; 
		ctx->dx_dir_info  = (struct dx_dir_info *)
			e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
					       * sizeof (struct dx_dir_info),
					       "directory map");
	}

	if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
		old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
		ctx->dx_dir_info_size += 10;
		retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
					   sizeof(struct dx_dir_info),
					   &ctx->dx_dir_info);
		if (retval) {
			ctx->dx_dir_info_size -= 10;
			return;
		}
	}

	if (ctx->dx_dir_info_count &&
	    ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
		for (i = ctx->dx_dir_info_count-1; i > 0; i--)
			if (ctx->dx_dir_info[i-1].ino < ino)
				break;
		dir = &ctx->dx_dir_info[i];
		if (dir->ino != ino)
			for (j = ctx->dx_dir_info_count++; j > i; j--)
				ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
	} else
		dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];

	dir->ino = ino;
	dir->numblocks = num_blocks;
	dir->hashversion = 0;
	dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
				       * sizeof (struct dx_dirblock_info),
				       "dx_block info array");

}
Esempio n. 5
0
static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
				e2_blkcnt_t blockcnt,
				blk_t ref_block EXT2FS_ATTR((unused)),
				int ref_offset EXT2FS_ATTR((unused)),
				void *priv_data)
{
	struct set_badblock_record *rec = (struct set_badblock_record *)
		priv_data;
	errcode_t	retval;
	unsigned long	old_size;

	if (!*block_nr)
		return 0;

	/*
	 * If the block number is outrageous, clear it and ignore it.
	 */
	if (*block_nr >= fs->super->s_blocks_count ||
	    *block_nr < fs->super->s_first_data_block) {
		*block_nr = 0;
		return BLOCK_CHANGED;
	}

	if (blockcnt < 0) {
		if (rec->ind_blocks_size >= rec->max_ind_blocks) {
			old_size = rec->max_ind_blocks * sizeof(blk_t);
			rec->max_ind_blocks += 10;
			retval = ext2fs_resize_mem(old_size,
				   rec->max_ind_blocks * sizeof(blk_t),
				   &rec->ind_blocks);
			if (retval) {
				rec->max_ind_blocks -= 10;
				rec->err = retval;
				return BLOCK_ABORT;
			}
		}
		rec->ind_blocks[rec->ind_blocks_size++] = *block_nr;
	}

	/*
	 * Mark the block as unused, and update accounting information
	 */
	ext2fs_block_alloc_stats(fs, *block_nr, -1);

	*block_nr = 0;
	return BLOCK_CHANGED;
}
Esempio n. 6
0
/*
 * insert_icount_el() --- Insert a new entry into the sorted list at a
 * 	specified position.
 */
static struct ext2_icount_el *insert_icount_el(ext2_icount_t icount,
					    ext2_ino_t ino, int pos)
{
	struct ext2_icount_el 	*el;
	errcode_t		retval;
	ext2_ino_t		new_size = 0;
	int			num;

	if (icount->last_lookup && icount->last_lookup->ino == ino)
		return icount->last_lookup;

	if (icount->count >= icount->size) {
		if (icount->count) {
			new_size = icount->list[(unsigned)icount->count-1].ino;
			new_size = (ext2_ino_t) (icount->count *
				((float) icount->num_inodes / new_size));
		}
		if (new_size < (icount->size + 100))
			new_size = icount->size + 100;
#if 0
		printf("Reallocating icount %u entries...\n", new_size);
#endif
		retval = ext2fs_resize_mem((size_t) icount->size *
					   sizeof(struct ext2_icount_el),
					   (size_t) new_size *
					   sizeof(struct ext2_icount_el),
					   &icount->list);
		if (retval)
			return 0;
		icount->size = new_size;
	}
	num = (int) icount->count - pos;
	if (num < 0)
		return 0;	/* should never happen */
	if (num) {
		memmove(&icount->list[pos+1], &icount->list[pos],
			sizeof(struct ext2_icount_el) * num);
	}
	icount->count++;
	el = &icount->list[pos];
	el->count = 0;
	el->ino = ino;
	icount->last_lookup = el;
	return el;
}
Esempio n. 7
0
/*
 * This procedure adds a block to a badblocks list.
 */
errcode_t ext2fs_u32_list_add(ext2_u32_list bb, u32 blk)
{
	errcode_t	retval;
	int		i, j;
	unsigned long	old_size;

	EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);

	if (bb->num >= bb->size) {
		old_size = bb->size * sizeof(u32);
		bb->size += 100;
		retval = ext2fs_resize_mem(old_size, bb->size * sizeof(u32),
					   &bb->list);
		if (retval) {
			bb->size -= 100;
			return retval;
		}
	}

	/*
	 * Add special case code for appending to the end of the list
	 */
	i = bb->num-1;
	if ((bb->num != 0) && (bb->list[i] == blk))
		return 0;
	if ((bb->num == 0) || (bb->list[i] < blk)) {
		bb->list[bb->num++] = blk;
		return 0;
	}

	j = bb->num;
	for (i=0; i < bb->num; i++) {
		if (bb->list[i] == blk)
			return 0;
		if (bb->list[i] > blk) {
			j = i;
			break;
		}
	}
	for (i=bb->num; i > j; i--)
		bb->list[i] = bb->list[i-1];
	bb->list[j] = blk;
	bb->num++;
	return 0;
}
Esempio n. 8
0
errcode_t ext2fs_resize_generic_bitmap(__u32 new_end, __u32 new_real_end,
				       ext2fs_generic_bitmap bmap)
{
	errcode_t	retval;
	size_t		size, new_size;
	__u32		bitno;

	if (!bmap)
		return EXT2_ET_INVALID_ARGUMENT;

	EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_GENERIC_BITMAP);

	/*
	 * If we're expanding the bitmap, make sure all of the new
	 * parts of the bitmap are zero.
	 */
	if (new_end > bmap->end) {
		bitno = bmap->real_end;
		if (bitno > new_end)
			bitno = new_end;
		for (; bitno > bmap->end; bitno--)
			ext2fs_clear_bit(bitno - bmap->start, bmap->bitmap);
	}
	if (new_real_end == bmap->real_end) {
		bmap->end = new_end;
		return 0;
	}

	size = ((bmap->real_end - bmap->start) / 8) + 1;
	new_size = ((new_real_end - bmap->start) / 8) + 1;

	if (size != new_size) {
		retval = ext2fs_resize_mem(size, new_size, &bmap->bitmap);
		if (retval)
			return retval;
	}
	if (new_size > size)
		memset(bmap->bitmap + size, 0, new_size - size);

	bmap->end = new_end;
	bmap->real_end = new_real_end;
	return 0;
}
/*
 * Add an entry to the extent table
 */
errcode_t ext2fs_add_extent_entry(ext2_extent extent, __u64 old_loc, __u64 new_loc)
{
	struct	ext2_extent_entry	*ent;
	errcode_t			retval;
	__u64				newsize;
	__u64				curr;

	if (extent->num >= extent->size) {
		newsize = extent->size + 100;
		retval = ext2fs_resize_mem(sizeof(struct ext2_extent_entry) *
					   extent->size,
					   sizeof(struct ext2_extent_entry) *
					   newsize, &extent->list);
		if (retval)
			return retval;
		extent->size = newsize;
	}
	curr = extent->num;
	ent = extent->list + curr;
	if (curr) {
		/*
		 * Check to see if this can be coalesced with the last
		 * extent
		 */
		ent--;
		if ((ent->old_loc + ent->size == old_loc) &&
		    (ent->new_loc + ent->size == new_loc)) {
			ent->size++;
			return 0;
		}
		/*
		 * Now see if we're going to ruin the sorting
		 */
		if (ent->old_loc + ent->size > old_loc)
			extent->sorted = 0;
		ent++;
	}
	ent->old_loc = old_loc;
	ent->new_loc = new_loc;
	ent->size = 1;
	extent->num++;
	return 0;
}
Esempio n. 10
0
errcode_t ext2fs_resize_generic_bitmap(errcode_t magic,
				       __u32 new_end, __u32 new_real_end,
				       ext2fs_generic_bitmap bmap)
{
	errcode_t	retval;
	size_t		size, new_size;
	__u32		bitno;

	if (!bmap || (bmap->magic != magic))
		return magic;

	/*
	 * If we're expanding the bitmap, make sure all of the new
	 * parts of the bitmap are zero.
	 */
	if (new_end > bmap->end) {
		bitno = bmap->real_end;
		if (bitno > new_end)
			bitno = new_end;
		for (; bitno > bmap->end; bitno--)
			ext2fs_clear_bit(bitno - bmap->start, bmap->bitmap);
	}
	if (new_real_end == bmap->real_end) {
		bmap->end = new_end;
		return 0;
	}

	size = ((bmap->real_end - bmap->start) / 8) + 1;
	new_size = ((new_real_end - bmap->start) / 8) + 1;

	if (size != new_size) {
		retval = ext2fs_resize_mem(size, new_size, &bmap->bitmap);
		if (retval)
			return retval;
	}
	if (new_size > size)
		memset(bmap->bitmap + size, 0, new_size - size);

	bmap->end = new_end;
	bmap->real_end = new_real_end;
	return 0;
}
Esempio n. 11
0
/*
 * Schedule a function to be called at (normal) program termination.
 * If you want this to be called during a signal exit, you must capture
 * the signal and call exit() yourself!
 */
errcode_t ext2fs_add_exit_fn(ext2_exit_fn func, void *data)
{
	struct exit_data *ed, *free_ed = NULL;
	size_t x;
	errcode_t ret;

	if (func == NULL)
		return EXT2_ET_INVALID_ARGUMENT;

	for (x = 0, ed = items; x < nr_items; x++, ed++) {
		if (ed->func == func && ed->data == data)
			return EXT2_ET_FILE_EXISTS;
		if (ed->func == NULL)
			free_ed = ed;
	}

	if (free_ed) {
		free_ed->func = func;
		free_ed->data = data;
		return 0;
	}

	if (nr_items == 0) {
		ret = atexit(handle_exit);
		if (ret)
			return ret;
	}

	ret = ext2fs_resize_mem(0, (nr_items + 1) * sizeof(struct exit_data),
				&items);
	if (ret)
		return ret;

	items[nr_items].func = func;
	items[nr_items].data = data;
	nr_items++;

	return 0;
}
Esempio n. 12
0
/*
 * This subroutine is called during pass1 to create a directory info
 * entry.  During pass1, the passed-in parent is 0; it will get filled
 * in during pass2.
 */
void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
{
    struct dir_info_db 	*db;
    struct dir_info		*dir, ent, *old_array;
    int			i, j;
    errcode_t		retval;
    unsigned long		old_size;

#ifdef DIRINFO_DEBUG
    printf("add_dir_info for inode (%lu, %lu)...\n", ino, parent);
#endif
    if (!ctx->dir_info)
        setup_db(ctx);
    db = ctx->dir_info;

    if (ctx->dir_info->count >= ctx->dir_info->size) {
        old_size = ctx->dir_info->size * sizeof(struct dir_info);
        ctx->dir_info->size += 10;
        old_array = ctx->dir_info->array;
        retval = ext2fs_resize_mem(old_size, ctx->dir_info->size *
                                   sizeof(struct dir_info),
                                   &ctx->dir_info->array);
        if (retval) {
            fprintf(stderr, "Couldn't reallocate dir_info "
                    "structure to %d entries\n",
                    ctx->dir_info->size);
            fatal_error(ctx, 0);
            ctx->dir_info->size -= 10;
            return;
        }
        if (old_array != ctx->dir_info->array)
            ctx->dir_info->last_lookup = NULL;
    }

    ent.ino = ino;
    ent.parent = parent;
    ent.dotdot = parent;

    if (db->tdb) {
        e2fsck_put_dir_info(ctx, &ent);
        return;
    }

    /*
     * Normally, add_dir_info is called with each inode in
     * sequential order; but once in a while (like when pass 3
     * needs to recreate the root directory or lost+found
     * directory) it is called out of order.  In those cases, we
     * need to move the dir_info entries down to make room, since
     * the dir_info array needs to be sorted by inode number for
     * get_dir_info()'s sake.
     */
    if (ctx->dir_info->count &&
            ctx->dir_info->array[ctx->dir_info->count-1].ino >= ino) {
        for (i = ctx->dir_info->count-1; i > 0; i--)
            if (ctx->dir_info->array[i-1].ino < ino)
                break;
        dir = &ctx->dir_info->array[i];
        if (dir->ino != ino)
            for (j = ctx->dir_info->count++; j > i; j--)
                ctx->dir_info->array[j] = ctx->dir_info->array[j-1];
    } else
        dir = &ctx->dir_info->array[ctx->dir_info->count++];

    dir->ino = ino;
    dir->dotdot = parent;
    dir->parent = parent;
}