Esempio n. 1
0
errcode_t ext2fs_inline_data_set(ext2_filsys fs, ext2_ino_t ino,
                                 struct ext2_inode *inode,
                                 void *buf, size_t size)
{
    struct ext2_inode inode_buf;
    struct ext2_inline_data data;
    errcode_t retval;
    size_t free_ea_size, existing_size, free_inode_size;

    if (!inode) {
        retval = ext2fs_read_inode(fs, ino, &inode_buf);
        if (retval)
            return retval;
        inode = &inode_buf;
    }

    if (size <= EXT4_MIN_INLINE_DATA_SIZE) {
        retval = ext2fs_inline_data_ea_remove(fs, ino);
        if (retval)
            return retval;
        memcpy((void *)inode->i_block, buf, size);
        return ext2fs_write_inode(fs, ino, inode);
    }

    retval = ext2fs_xattr_inode_max_size(fs, ino, &free_ea_size);
    if (retval)
        return retval;

    retval = ext2fs_inline_data_size(fs, ino, &existing_size);
    if (retval)
        return retval;

    if (existing_size < EXT4_MIN_INLINE_DATA_SIZE)
        free_inode_size = EXT4_MIN_INLINE_DATA_SIZE - existing_size;
    else
        free_inode_size = 0;

    if (size != existing_size &&
            size > existing_size + free_ea_size + free_inode_size)
        return EXT2_ET_INLINE_DATA_NO_SPACE;

    memcpy((void *)inode->i_block, buf, EXT4_MIN_INLINE_DATA_SIZE);
    retval = ext2fs_write_inode(fs, ino, inode);
    if (retval)
        return retval;
    data.fs = fs;
    data.ino = ino;
    data.ea_size = size - EXT4_MIN_INLINE_DATA_SIZE;
    data.ea_data = buf + EXT4_MIN_INLINE_DATA_SIZE;
    return ext2fs_inline_data_ea_set(&data);
}
Esempio n. 2
0
static void move_quota_inode(ext2_filsys fs, ext2_ino_t from_ino,
			     ext2_ino_t to_ino, int qtype)
{
	struct ext2_inode	inode;
	char			qf_name[QUOTA_NAME_LEN];

	/* We need the inode bitmap to be loaded */
	if (ext2fs_read_bitmaps(fs))
		return;

	if (ext2fs_read_inode(fs, from_ino, &inode))
		return;

	inode.i_links_count = 1;
	inode.i_mode = LINUX_S_IFREG | 0600;
	inode.i_flags = EXT2_IMMUTABLE_FL;
	if (fs->super->s_feature_incompat &
			EXT3_FEATURE_INCOMPAT_EXTENTS)
		inode.i_flags |= EXT4_EXTENTS_FL;

	ext2fs_write_new_inode(fs, to_ino, &inode);
	/* unlink the old inode */
	quota_get_qf_name(qtype, QFMT_VFS_V1, qf_name);
	ext2fs_unlink(fs, EXT2_ROOT_INO, qf_name, from_ino, 0);
	ext2fs_inode_alloc_stats(fs, from_ino, -1);
	/* Clear out the original inode in the inode-table block. */
	memset(&inode, 0, sizeof(struct ext2_inode));
	ext2fs_write_inode(fs, from_ino, &inode);
}
Esempio n. 3
0
static int fix_directory(ext2_filsys fs,
			 struct ext2_db_entry2 *db,
			 void *priv_data)
{
	errcode_t	retval;

	empty_dir_info edi = (empty_dir_info) priv_data;

	edi->logblk = 0;
	edi->freed_blocks = 0;
	edi->ino = db->ino;

	retval = ext2fs_read_inode(fs, db->ino, &edi->inode);
	if (retval)
		return 0;

	retval = ext2fs_block_iterate3(fs, db->ino, 0, edi->block_buf,
				       empty_pass1, edi);
	if (retval)
		return 0;

	if (edi->freed_blocks) {
		edi->inode.i_size -= edi->freed_blocks * fs->blocksize;
		ext2fs_iblk_add_blocks(fs, &edi->inode, edi->freed_blocks);
		retval = ext2fs_write_inode(fs, db->ino, &edi->inode);
		if (retval)
			return 0;
	}
	return 0;
}
Esempio n. 4
0
static errcode_t update_path(ext2_extent_handle_t handle)
{
	blk64_t				blk;
	errcode_t			retval;
	struct ext3_extent_idx		*ix;
	struct ext3_extent_header	*eh;

	if (handle->level == 0) {
		retval = ext2fs_write_inode(handle->fs, handle->ino,
					    handle->inode);
	} else {
		ix = handle->path[handle->level - 1].curr;
		blk = ext2fs_le32_to_cpu(ix->ei_leaf) +
			((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32);

		/* then update the checksum */
		eh = (struct ext3_extent_header *)
				handle->path[handle->level].buf;
		retval = ext2fs_extent_block_csum_set(handle->fs, handle->ino,
						      eh);
		if (retval)
			return retval;

		retval = io_channel_write_blk64(handle->fs->io,
				      blk, 1, handle->path[handle->level].buf);
	}
	return retval;
}
Esempio n. 5
0
int modinode(e2i_ctx_t *e2c, const char *fname, ext2_ino_t e2ino)
{
	struct ext2_inode inode;
	int uid, gid, ret;
	
	/* read the inode, alter uid, gid  and write it back */
	ret = ext2fs_read_inode(e2c->fs, e2ino, &inode);
	E2_ERR(ret, "Ext2 read Inode Error", "");

	/* do the root squash */
	if (! e2c->preserve_uidgid) {
		inode.i_uid = e2c->default_uid;
		inode.i_gid = e2c->default_gid;
	}

	/* if the filename is mentioned in .UIDGID we must change the owner */
	if (uiddb_search(e2c->uid_db, fname, &uid, &gid)){
		if (e2c->verbose)
			printf("Changing UID and GID for %s (%d:%d)\n", fname, uid, gid);
		inode.i_uid = uid;
		inode.i_gid = gid;
	}		
		
	ret = ext2fs_write_inode(e2c->fs, e2ino, &inode);
	E2_ERR(ret, "Ext2 write Inode Error", "");
	
	return 0;
}
Esempio n. 6
0
/* Link an inode number to a directory */
static errcode_t add_link(ext2_filsys fs, ext2_ino_t parent_ino,
			  ext2_ino_t ino, const char *name)
{
	struct ext2_inode	inode;
	errcode_t		retval;

	retval = ext2fs_read_inode(fs, ino, &inode);
        if (retval) {
		com_err(__func__, retval, "while reading inode %u", ino);
		return retval;
	}

	retval = ext2fs_link(fs, parent_ino, name, ino, inode.i_flags);
	if (retval == EXT2_ET_DIR_NO_SPACE) {
		retval = ext2fs_expand_dir(fs, parent_ino);
		if (retval) {
			com_err(__func__, retval, "while expanding directory");
			return retval;
		}
		retval = ext2fs_link(fs, parent_ino, name, ino, inode.i_flags);
	}
	if (retval) {
		com_err(__func__, retval, "while linking %s", name);
		return retval;
	}

	inode.i_links_count++;

	retval = ext2fs_write_inode(fs, ino, &inode);
	if (retval)
		com_err(__func__, retval, "while writing inode %u", ino);

	return retval;
}
Esempio n. 7
0
static errcode_t mk_hugefile(ext2_filsys fs, blk64_t num,
                             ext2_ino_t dir, unsigned long idx, ext2_ino_t *ino)

{
    errcode_t		retval;
    struct ext2_inode	inode;

    retval = ext2fs_new_inode(fs, 0, LINUX_S_IFREG, NULL, ino);
    if (retval)
        return retval;

    memset(&inode, 0, sizeof(struct ext2_inode));
    inode.i_mode = LINUX_S_IFREG | (0666 & ~fs->umask);
    inode.i_links_count = 1;
    inode.i_uid = uid & 0xFFFF;
    ext2fs_set_i_uid_high(inode, (uid >> 16) & 0xffff);
    inode.i_gid = gid & 0xFFFF;
    ext2fs_set_i_gid_high(inode, (gid >> 16) & 0xffff);

    retval = ext2fs_write_new_inode(fs, *ino, &inode);
    if (retval)
        return retval;

    ext2fs_inode_alloc_stats2(fs, *ino, +1, 0);

    if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
                                  EXT3_FEATURE_INCOMPAT_EXTENTS))
        inode.i_flags |= EXT4_EXTENTS_FL;
    retval = ext2fs_fallocate(fs,
                              EXT2_FALLOCATE_FORCE_INIT |
                              EXT2_FALLOCATE_ZERO_BLOCKS,
                              *ino, &inode, goal, 0, num);
    if (retval)
        return retval;
    retval = ext2fs_inode_size_set(fs, &inode, num * fs->blocksize);
    if (retval)
        return retval;

    retval = ext2fs_write_inode(fs, *ino, &inode);
    if (retval)
        goto errout;

    if (idx_digits)
        sprintf(fn_numbuf, "%0*lu", idx_digits, idx);
    else if (num_files > 1)
        sprintf(fn_numbuf, "%lu", idx);

retry:
    retval = ext2fs_link(fs, dir, fn_buf, *ino, EXT2_FT_REG_FILE);
    if (retval == EXT2_ET_DIR_NO_SPACE) {
        retval = ext2fs_expand_dir(fs, dir);
        if (retval)
            goto errout;
        goto retry;
    }

errout:
    return retval;
}
Esempio n. 8
0
static errcode_t ext3u_write_inode(ext2_filsys fs, ext2_ino_t undel_ino, int flags)
{

	char				*buf;
	errcode_t			retval;
	struct ext2_inode	inode;
	struct mk_ext3u_struct	es;
	__u32 num_blocks = ext3u_fifo_reserved + ext3u_skip_reserved + ext3u_index_reserved + 1;

	if ((retval = ext3u_create_superblock(fs, flags, &buf)))
		return retval;

	if ((retval = ext2fs_read_bitmaps(fs)))
		return retval;

	if ((retval = ext2fs_read_inode(fs, undel_ino, &inode)))
		return retval;

	if (inode.i_blocks > 0)
		return EEXIST;

	es.goal = 0;
	es.num_blocks = num_blocks;
	es.newblocks = 0;
	es.buf = buf;
	es.err = 0;
	es.zero_count = 0;

	retval = ext2fs_block_iterate2(fs, undel_ino, BLOCK_FLAG_APPEND, 0, mk_ext3u_proc, &es);
	if (es.err) {
		retval = es.err;
		goto errout;
	}
	if (es.zero_count) {
		retval = ext2fs_zero_blocks(fs, es.blk_to_zero, es.zero_count, 0, 0);
		if (retval)
			goto errout;
	}

	 if ((retval = ext2fs_read_inode(fs, undel_ino, &inode)))
		goto errout;

 	inode.i_size += fs->blocksize * num_blocks;
	ext2fs_iblk_add_blocks(fs, &inode, es.newblocks);
	inode.i_mtime = inode.i_ctime = fs->now ? fs->now : time(0);
	inode.i_links_count = 1;
	inode.i_mode = LINUX_S_IFREG | 0600;

	if ((retval = ext2fs_write_inode(fs, undel_ino, &inode)))
		goto errout;
	retval = 0;


errout:
	ext2fs_free_mem(&buf);
	return retval;
}
Esempio n. 9
0
File: util.c Progetto: er13/e2tools
long
write_inode(ext2_filsys fs, ext2_ino_t file, struct ext2_inode *inode)
{
  long retval;

  if ((retval = ext2fs_write_inode(fs, file, inode)))
    fprintf(stderr, "%s\n", error_message(retval));
  return retval;

}
Esempio n. 10
0
/*
 * This function creates a journal using direct I/O routines.
 */
static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
				     blk_t size, int flags)
{
	char			*buf;
	errcode_t		retval;
	struct ext2_inode	inode;
	struct mkjournal_struct	es;

	if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf)))
		return retval;

	if ((retval = ext2fs_read_bitmaps(fs)))
		return retval;

	if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
		return retval;

	if (inode.i_blocks > 0)
		return EEXIST;

	es.num_blocks = size;
	es.newblocks = 0;
	es.buf = buf;
	es.err = 0;

	retval = ext2fs_block_iterate2(fs, journal_ino, BLOCK_FLAG_APPEND,
				       0, mkjournal_proc, &es);
	if (es.err) {
		retval = es.err;
		goto errout;
	}

	if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
		goto errout;

	inode.i_size += fs->blocksize * size;
	inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
	inode.i_mtime = inode.i_ctime = time(0);
	inode.i_links_count = 1;
	inode.i_mode = LINUX_S_IFREG | 0600;

	if ((retval = ext2fs_write_inode(fs, journal_ino, &inode)))
		goto errout;
	retval = 0;

	memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4);
	fs->super->s_jnl_blocks[16] = inode.i_size;
	fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
	ext2fs_mark_super_dirty(fs);

errout:
	ext2fs_free_mem(&buf);
	return retval;
}
Esempio n. 11
0
void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
			struct ext2_inode * inode, const char *proc)
{
	errcode_t retval;

	retval = ext2fs_write_inode(ctx->fs, ino, inode);
	if (retval) {
		com_err("ext2fs_write_inode", retval,
			_("while writing inode %lu in %s"), ino, proc);
		fatal_error(ctx, 0);
	}
}
Esempio n. 12
0
int debugfs_write_inode(ext2_ino_t ino, struct ext2_inode * inode,
			const char *cmd)
{
	int retval;

	retval = ext2fs_write_inode(current_fs, ino, inode);
	if (retval) {
		com_err(cmd, retval, "while writing inode %u", ino);
		return 1;
	}
	return 0;
}
Esempio n. 13
0
static errcode_t create_directory(ext2_filsys fs, char *dir,
                                  ext2_ino_t *ret_ino)

{
    struct ext2_inode	inode;
    ext2_ino_t		ino = EXT2_ROOT_INO;
    ext2_ino_t		newdir;
    errcode_t		retval = 0;
    char			*fn, *cp, *next;

    fn = malloc(strlen(dir) + 1);
    if (fn == NULL)
        return ENOMEM;

    strcpy(fn, dir);
    cp = fn;
    while(1) {
        next = strchr(cp, '/');
        if (next)
            *next++ = 0;
        if (*cp) {
            retval = ext2fs_new_inode(fs, ino, LINUX_S_IFDIR,
                                      NULL, &newdir);
            if (retval)
                goto errout;

            retval = ext2fs_mkdir(fs, ino, newdir, cp);
            if (retval)
                goto errout;

            ino = newdir;
            retval = ext2fs_read_inode(fs, ino, &inode);
            if (retval)
                goto errout;

            inode.i_uid = uid & 0xFFFF;
            ext2fs_set_i_uid_high(inode, (uid >> 16) & 0xffff);
            inode.i_gid = gid & 0xFFFF;
            ext2fs_set_i_gid_high(inode, (gid >> 16) & 0xffff);
            retval = ext2fs_write_inode(fs, ino, &inode);
            if (retval)
                goto errout;
        }
        if (next == NULL || *next == '\0')
            break;
        cp = next;
    }
errout:
    free(fn);
    if (retval == 0)
        *ret_ino = ino;
    return retval;
}
Esempio n. 14
0
static errcode_t
ext2fs_inline_data_dir_expand(ext2_filsys fs, ext2_ino_t ino,
                              struct ext2_inode *inode, char *buf, size_t size)
{
    errcode_t retval;
    blk64_t blk;
    char *blk_buf;

    retval = ext2fs_get_memzero(fs->blocksize, &blk_buf);
    if (retval)
        return retval;

#ifdef WORDS_BIGENDIAN
    retval = ext2fs_dirent_swab_in2(fs, buf + EXT4_INLINE_DATA_DOTDOT_SIZE,
                                    size, 0);
    if (retval)
        goto errout;
#endif

    /* Adjust the rec_len */
    retval = ext2fs_inline_data_convert_dir(fs, ino, blk_buf, buf, size);
    if (retval)
        goto errout;
    /* Allocate a new block */
    retval = ext2fs_new_block2(fs, 0, 0, &blk);
    if (retval)
        goto errout;
    retval = ext2fs_write_dir_block4(fs, blk, blk_buf, 0, ino);
    if (retval)
        goto errout;

    /* Update inode */
    if (EXT2_HAS_INCOMPAT_FEATURE(fs->super, EXT3_FEATURE_INCOMPAT_EXTENTS))
        inode->i_flags |= EXT4_EXTENTS_FL;
    inode->i_flags &= ~EXT4_INLINE_DATA_FL;
    retval = ext2fs_iblk_add_blocks(fs, inode, 1);
    if (retval)
        goto errout;
    inode->i_size = fs->blocksize;
    retval = ext2fs_bmap2(fs, ino, inode, 0, BMAP_SET, 0, 0, &blk);
    if (retval)
        goto errout;
    retval = ext2fs_write_inode(fs, ino, inode);
    if (retval)
        goto errout;
    ext2fs_block_alloc_stats(fs, blk, +1);

errout:
    ext2fs_free_mem(&blk_buf);
    return retval;
}
Esempio n. 15
0
errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir)
{
	errcode_t	retval;
	struct expand_dir_struct es;
	struct ext2_inode	inode;

	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

	if (!(fs->flags & EXT2_FLAG_RW))
		return EXT2_ET_RO_FILSYS;

	if (!fs->block_map)
		return EXT2_ET_NO_BLOCK_BITMAP;

	retval = ext2fs_check_directory(fs, dir);
	if (retval)
		return retval;

	es.done = 0;
	es.err = 0;
	es.goal = 0;
	es.newblocks = 0;
	es.dir = dir;

	retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_APPEND,
				       0, expand_dir_proc, &es);

	if (es.err)
		return es.err;
	if (!es.done)
		return EXT2_ET_EXPAND_DIR_ERR;

	/*
	 * Update the size and block count fields in the inode.
	 */
	retval = ext2fs_read_inode(fs, dir, &inode);
	if (retval)
		return retval;

	inode.i_size += fs->blocksize;
	ext2fs_iblk_add_blocks(fs, &inode, es.newblocks);

	retval = ext2fs_write_inode(fs, dir, &inode);
	if (retval)
		return retval;

	return 0;
}
Esempio n. 16
0
errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
		      ext2_ino_t ino, int flags)
{
	errcode_t		retval;
	struct link_struct	ls;
	struct ext2_inode	inode;

	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

	if (!(fs->flags & EXT2_FLAG_RW))
		return EXT2_ET_RO_FILSYS;

	ls.fs = fs;
	ls.name = name;
	ls.namelen = name ? strlen(name) : 0;
	ls.inode = ino;
	ls.flags = flags;
	ls.done = 0;
	ls.sb = fs->super;
	ls.blocksize = fs->blocksize;
	ls.err = 0;

	retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
				    0, link_proc, &ls);
	if (retval)
		return retval;
	if (ls.err)
		return ls.err;

	if (!ls.done)
		return EXT2_ET_DIR_NO_SPACE;

	if ((retval = ext2fs_read_inode(fs, dir, &inode)) != 0)
		return retval;

	/*
	 * If this function changes to preserve the htree, remove the
	 * two hunks in link_proc that shove checksum tails into the
	 * former dx_root/dx_node blocks.
	 */
	if (inode.i_flags & EXT2_INDEX_FL) {
		inode.i_flags &= ~EXT2_INDEX_FL;
		if ((retval = ext2fs_write_inode(fs, dir, &inode)) != 0)
			return retval;
	}

	return 0;
}
Esempio n. 17
0
int do_writeinode (ext2_filsys e2fs, ext2_ino_t ino, struct ext2_inode *inode)
{
	int rt;
	errcode_t rc;
	if (inode->i_links_count < 1) {
		rt = do_killfilebyinode(e2fs, ino, inode);
		if (rt) {
			debugf("do_killfilebyinode(e2fs, ino, inode); failed");
			return rt;
		}
	} else {
		rc = ext2fs_write_inode(e2fs, ino, inode);
		if (rc) {
			debugf("ext2fs_read_inode(e2fs, *ino, inode); failed");
			return -EIO;
		}
	}
	return 0;
}
Esempio n. 18
0
/* Set the uid, gid, mode and time for the inode */
static errcode_t set_inode_extra(ext2_filsys fs, ext2_ino_t cwd,
				 ext2_ino_t ino, struct stat *st)
{
	errcode_t		retval;
	struct ext2_inode	inode;

	retval = ext2fs_read_inode(fs, ino, &inode);
        if (retval) {
		com_err(__func__, retval, "while reading inode %u", ino);
		return retval;
	}

	fill_inode(&inode, st);

	retval = ext2fs_write_inode(fs, ino, &inode);
	if (retval)
		com_err(__func__, retval, "while writing inode %u", ino);
	return retval;
}
Esempio n. 19
0
static errcode_t update_path(ext2_extent_handle_t handle)
{
	blk64_t				blk;
	errcode_t			retval;
	struct ext3_extent_idx		*ix;

	if (handle->level == 0) {
		retval = ext2fs_write_inode(handle->fs, handle->ino,
					    handle->inode);
	} else {
		ix = handle->path[handle->level - 1].curr;
		blk = ext2fs_le32_to_cpu(ix->ei_leaf) +
			((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32);

		retval = io_channel_write_blk(handle->fs->io,
				      blk, 1, handle->path[handle->level].buf);
	}
	return retval;
}
Esempio n. 20
0
errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
		      ext2_ino_t ino, int flags)
{
	errcode_t		retval;
	struct link_struct	ls;
	struct ext2_inode	inode;

	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

	if (!(fs->flags & EXT2_FLAG_RW))
		return EXT2_ET_RO_FILSYS;

	ls.fs = fs;
	ls.name = name;
	ls.namelen = name ? strlen(name) : 0;
	ls.inode = ino;
	ls.flags = flags;
	ls.done = 0;
	ls.sb = fs->super;
	ls.blocksize = fs->blocksize;
	ls.err = 0;

	retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
				    0, link_proc, &ls);
	if (retval)
		return retval;
	if (ls.err)
		return ls.err;

	if (!ls.done)
		return EXT2_ET_DIR_NO_SPACE;

	if ((retval = ext2fs_read_inode(fs, dir, &inode)) != 0)
		return retval;

	if (inode.i_flags & EXT2_INDEX_FL) {
		inode.i_flags &= ~EXT2_INDEX_FL;
		if ((retval = ext2fs_write_inode(fs, dir, &inode)) != 0)
			return retval;
	}

	return 0;
}
Esempio n. 21
0
errcode_t quota_remove_inode(ext2_filsys fs, enum quota_type qtype)
{
	ext2_ino_t qf_ino;
	errcode_t	retval;

	retval = ext2fs_read_bitmaps(fs);
	if (retval) {
		log_debug("Couldn't read bitmaps: %s", error_message(retval));
		return retval;
	}

	qf_ino = *quota_sb_inump(fs->super, qtype);
	if (qf_ino == 0)
		return 0;
	retval = quota_inode_truncate(fs, qf_ino);
	if (retval)
		return retval;
	if (qf_ino >= EXT2_FIRST_INODE(fs->super)) {
		struct ext2_inode inode;

		retval = ext2fs_read_inode(fs, qf_ino, &inode);
		if (!retval) {
			memset(&inode, 0, sizeof(struct ext2_inode));
			ext2fs_write_inode(fs, qf_ino, &inode);
		}
		ext2fs_inode_alloc_stats2(fs, qf_ino, -1, 0);
		ext2fs_mark_ib_dirty(fs);

	}
	quota_set_sb_inum(fs, 0, qtype);

	ext2fs_mark_super_dirty(fs);
	fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
	retval = ext2fs_write_bitmaps(fs);
	if (retval) {
		log_debug("Couldn't write bitmaps: %s", error_message(retval));
		return retval;
	}
	return 0;
}
Esempio n. 22
0
static void move_quota_inode(ext2_filsys fs, ext2_ino_t from_ino,
			     ext2_ino_t to_ino, enum quota_type qtype)
{
	struct ext2_inode	inode;
	errcode_t		retval;
	char			qf_name[QUOTA_NAME_LEN];

	/* We need the inode bitmap to be loaded */
	if (ext2fs_read_bitmaps(fs))
		return;

	retval = ext2fs_read_inode(fs, from_ino, &inode);
	if (retval) {
		com_err("ext2fs_read_inode", retval, "%s",
			_("in move_quota_inode"));
		return;
	}

	inode.i_links_count = 1;
	inode.i_mode = LINUX_S_IFREG | 0600;
	inode.i_flags = EXT2_IMMUTABLE_FL;
	if (ext2fs_has_feature_extents(fs->super))
		inode.i_flags |= EXT4_EXTENTS_FL;

	retval = ext2fs_write_new_inode(fs, to_ino, &inode);
	if (retval) {
		com_err("ext2fs_write_new_inode", retval, "%s",
			_("in move_quota_inode"));
		return;
	}

	/* unlink the old inode */
	quota_get_qf_name(qtype, QFMT_VFS_V1, qf_name);
	ext2fs_unlink(fs, EXT2_ROOT_INO, qf_name, from_ino, 0);
	ext2fs_inode_alloc_stats(fs, from_ino, -1);
	/* Clear out the original inode in the inode-table block. */
	memset(&inode, 0, sizeof(struct ext2_inode));
	ext2fs_write_inode(fs, from_ino, &inode);
}
Esempio n. 23
0
/*
 * Utility routine to adjust the inode counts on an inode.
 */
errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
{
	ext2_filsys fs = ctx->fs;
	errcode_t		retval;
	struct ext2_inode 	inode;

	if (!ino)
		return 0;

	retval = ext2fs_read_inode(fs, ino, &inode);
	if (retval)
		return retval;

#if 0
	printf("Adjusting link count for inode %lu by %d (from %d)\n", ino, adj,
	       inode.i_links_count);
#endif

	if (adj == 1) {
		ext2fs_icount_increment(ctx->inode_count, ino, 0);
		if (inode.i_links_count == (__u16) ~0)
			return 0;
		ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
		inode.i_links_count++;
	} else if (adj == -1) {
		ext2fs_icount_decrement(ctx->inode_count, ino, 0);
		if (inode.i_links_count == 0)
			return 0;
		ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
		inode.i_links_count--;
	}

	retval = ext2fs_write_inode(fs, ino, &inode);
	if (retval)
		return retval;

	return 0;
}
Esempio n. 24
0
/* Set the uid, gid, mode and time for the inode */
static errcode_t set_inode_extra(ext2_filsys fs, ext2_ino_t ino,
				 struct stat *st)
{
	errcode_t		retval;
	struct ext2_inode	inode;

	retval = ext2fs_read_inode(fs, ino, &inode);
        if (retval) {
		com_err(__func__, retval, _("while reading inode %u"), ino);
		return retval;
	}

	inode.i_uid = st->st_uid;
	inode.i_gid = st->st_gid;
	inode.i_mode |= st->st_mode;
	inode.i_atime = st->st_atime;
	inode.i_mtime = st->st_mtime;
	inode.i_ctime = st->st_ctime;

	retval = ext2fs_write_inode(fs, ino, &inode);
	if (retval)
		com_err(__func__, retval, _("while writing inode %u"), ino);
	return retval;
}
Esempio n. 25
0
void ext2CloseEntry(ext2_vd *vd, ext2_inode_t * ni)
{
    // Sanity check
    if (!vd || !ni) {
        errno = ENODEV;
        return;
    }

    // Lock
    ext2Lock(vd);

    // Sync the entry (if it is dirty)
    if(ni && ni->dirty)
        ext2fs_write_inode(vd->fs, ni->ino, &ni->ni);

    // Close the entry
	if(ni)
		mem_free(ni);

    // Unlock
    ext2Unlock(vd);

    return;
}
Esempio n. 26
0
static errcode_t
ext2fs_inline_data_file_expand(ext2_filsys fs, ext2_ino_t ino,
                               struct ext2_inode *inode, char *buf, size_t size)
{
    ext2_file_t e2_file;
    errcode_t retval;

    /* Update inode */
    if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
                                  EXT3_FEATURE_INCOMPAT_EXTENTS)) {
        int i;
        struct ext3_extent_header *eh;

        eh = (struct ext3_extent_header *) &inode->i_block[0];
        eh->eh_depth = 0;
        eh->eh_entries = 0;
        eh->eh_magic = ext2fs_cpu_to_le16(EXT3_EXT_MAGIC);
        i = (sizeof(inode->i_block) - sizeof(*eh)) /
            sizeof(struct ext3_extent);
        eh->eh_max = ext2fs_cpu_to_le16(i);
        inode->i_flags |= EXT4_EXTENTS_FL;
    }
    inode->i_flags &= ~EXT4_INLINE_DATA_FL;
    inode->i_size = 0;
    retval = ext2fs_write_inode(fs, ino, inode);
    if (retval)
        return retval;

    /* Write out the block buffer */
    retval = ext2fs_file_open(fs, ino, EXT2_FILE_WRITE, &e2_file);
    if (retval)
        return retval;
    retval = ext2fs_file_write(e2_file, buf, size, 0);
    ext2fs_file_close(e2_file);
    return retval;
}
Esempio n. 27
0
void e2fsck_move_ext3_journal(e2fsck_t ctx)
{
	struct ext2_super_block *sb = ctx->fs->super;
	struct problem_context	pctx;
	struct ext2_inode 	inode;
	ext2_filsys		fs = ctx->fs;
	ext2_ino_t		ino;
	errcode_t		retval;
	const char * const *	cpp;
	int			group, mount_flags;
	
	clear_problem_context(&pctx);

	/*
	 * If the filesystem is opened read-only, or there is no
	 * journal, then do nothing.
	 */
	if ((ctx->options & E2F_OPT_READONLY) ||
	    (sb->s_journal_inum == 0) ||
	    !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
		return;

	/*
	 * Read in the journal inode
	 */
	if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
		return;

	/*
	 * If it's necessary to backup the journal inode, do so.
	 */
	if ((sb->s_jnl_backup_type == 0) ||
	    ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
	     memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
		if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
			memcpy(sb->s_jnl_blocks, inode.i_block,
			       EXT2_N_BLOCKS*4);
			sb->s_jnl_blocks[16] = inode.i_size;
			sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
			ext2fs_mark_super_dirty(fs);
			fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
		}
	}

	/*
	 * If the journal is already the hidden inode, then do nothing
	 */
	if (sb->s_journal_inum == EXT2_JOURNAL_INO)
		return;
	
	/*
	 * The journal inode had better have only one link and not be readable.
	 */
	if (inode.i_links_count != 1)
		return;

	/*
	 * If the filesystem is mounted, or we can't tell whether
	 * or not it's mounted, do nothing.
	 */
	retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
	if (retval || (mount_flags & EXT2_MF_MOUNTED))
		return;

	/*
	 * If we can't find the name of the journal inode, then do
	 * nothing.
	 */
	for (cpp = journal_names; *cpp; cpp++) {
		retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
				       strlen(*cpp), 0, &ino);
		if ((retval == 0) && (ino == sb->s_journal_inum))
			break;
	}
	if (*cpp == 0)
		return;

	/* We need the inode bitmap to be loaded */
	retval = ext2fs_read_bitmaps(fs);
	if (retval)
		return;

	pctx.str = *cpp;
	if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
		return;
		
	/*
	 * OK, we've done all the checks, let's actually move the
	 * journal inode.  Errors at this point mean we need to force
	 * an ext2 filesystem check.
	 */
	if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
		goto err_out;
	if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
		goto err_out;
	sb->s_journal_inum = EXT2_JOURNAL_INO;
	ext2fs_mark_super_dirty(fs);
	fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
	inode.i_links_count = 0;
	inode.i_dtime = ctx->now;
	if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
		goto err_out;

	group = ext2fs_group_of_ino(fs, ino);
	ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
	ext2fs_mark_ib_dirty(fs);
	fs->group_desc[group].bg_free_inodes_count++;
	fs->super->s_free_inodes_count++;
	return;

err_out:
	pctx.errcode = retval;
	fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
	fs->super->s_state &= ~EXT2_VALID_FS;
	ext2fs_mark_super_dirty(fs);
	return;
}
Esempio n. 28
0
/*
 * Given a bad blocks bitmap, update the bad blocks inode to reflect
 * the map.
 */
errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list)
{
	errcode_t			retval;
	struct set_badblock_record	rec;
	struct ext2_inode		inode;

	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

	if (!fs->block_map)
		return EXT2_ET_NO_BLOCK_BITMAP;

	rec.bad_block_count = 0;
	rec.ind_blocks_size = rec.ind_blocks_ptr = 0;
	rec.max_ind_blocks = 10;
	retval = ext2fs_get_mem(rec.max_ind_blocks * sizeof(blk_t),
				&rec.ind_blocks);
	if (retval)
		return retval;
	memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t));
	retval = ext2fs_get_mem(fs->blocksize, &rec.block_buf);
	if (retval)
		goto cleanup;
	memset(rec.block_buf, 0, fs->blocksize);
	rec.err = 0;

	/*
	 * First clear the old bad blocks (while saving the indirect blocks)
	 */
	retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
				       BLOCK_FLAG_DEPTH_TRAVERSE, 0,
				       clear_bad_block_proc, &rec);
	if (retval)
		goto cleanup;
	if (rec.err) {
		retval = rec.err;
		goto cleanup;
	}

	/*
	 * Now set the bad blocks!
	 *
	 * First, mark the bad blocks as used.  This prevents a bad
	 * block from being used as an indirecto block for the bad
	 * block inode (!).
	 */
	if (bb_list) {
		retval = ext2fs_badblocks_list_iterate_begin(bb_list,
							     &rec.bb_iter);
		if (retval)
			goto cleanup;
		retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
					       BLOCK_FLAG_APPEND, 0,
					       set_bad_block_proc, &rec);
		ext2fs_badblocks_list_iterate_end(rec.bb_iter);
		if (retval)
			goto cleanup;
		if (rec.err) {
			retval = rec.err;
			goto cleanup;
		}
	}

	/*
	 * Update the bad block inode's mod time and block count
	 * field.
	 */
	retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
	if (retval)
		goto cleanup;

	inode.i_atime = inode.i_mtime = time(NULL);
	if (!inode.i_ctime)
		inode.i_ctime = time(NULL);
	inode.i_blocks = rec.bad_block_count * (fs->blocksize / 512);
	inode.i_size = rec.bad_block_count * fs->blocksize;

	retval = ext2fs_write_inode(fs, EXT2_BAD_INO, &inode);
	if (retval)
		goto cleanup;

cleanup:
	ext2fs_free_mem(&rec.ind_blocks);
	ext2fs_free_mem(&rec.block_buf);
	return retval;
}
Esempio n. 29
0
/*
 * This code assumes that the reserved blocks have already been marked in-use
 * during ext2fs_initialize(), so that they are not allocated for other
 * uses before we can add them to the resize inode (which has to come
 * after the creation of the inode table).
 */
errcode_t ext2fs_create_resize_inode(ext2_filsys fs)
{
    errcode_t		retval, retval2;
    struct ext2_super_block	*sb;
    struct ext2_inode	inode;
    __u32			*dindir_buf, *gdt_buf;
    int			rsv_add;
    unsigned long long	apb, inode_size;
    blk_t			dindir_blk, rsv_off, gdt_off, gdt_blk;
    int			dindir_dirty = 0, inode_dirty = 0;

    EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

    sb = fs->super;

    retval = ext2fs_get_mem(2 * fs->blocksize, (void **)&dindir_buf);
    if (retval)
        goto out_free;
    gdt_buf = (__u32 *)((char *)dindir_buf + fs->blocksize);

    retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
    if (retval)
        goto out_free;

    /* Maximum possible file size (we donly use the dindirect blocks) */
    apb = EXT2_ADDR_PER_BLOCK(sb);
    rsv_add = fs->blocksize / 512;
    if ((dindir_blk = inode.i_block[EXT2_DIND_BLOCK])) {
#ifdef RES_GDT_DEBUG
        printf("reading GDT dindir %u\n", dindir_blk);
#endif
        retval = ext2fs_read_ind_block(fs, dindir_blk, dindir_buf);
        if (retval)
            goto out_inode;
    } else {
        blk_t goal = 3 + sb->s_reserved_gdt_blocks +
                     fs->desc_blocks + fs->inode_blocks_per_group;

        retval = ext2fs_alloc_block(fs, goal, 0, &dindir_blk);
        if (retval)
            goto out_free;
        inode.i_mode = LINUX_S_IFREG | 0600;
        inode.i_links_count = 1;
        inode.i_block[EXT2_DIND_BLOCK] = dindir_blk;
        inode.i_blocks = rsv_add;
        memset(dindir_buf, 0, fs->blocksize);
#ifdef RES_GDT_DEBUG
        printf("allocated GDT dindir %u\n", dindir_blk);
#endif
        dindir_dirty = inode_dirty = 1;
        inode_size = apb*apb + apb + EXT2_NDIR_BLOCKS;
        inode_size *= fs->blocksize;
        inode.i_size = inode_size & 0xFFFFFFFF;
        inode.i_size_high = (inode_size >> 32) & 0xFFFFFFFF;
        if(inode.i_size_high) {
            sb->s_feature_ro_compat |=
                EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
        }
        inode.i_ctime = time(0);
    }

    for (rsv_off = 0, gdt_off = fs->desc_blocks,
            gdt_blk = sb->s_first_data_block + 1 + fs->desc_blocks;
            rsv_off < sb->s_reserved_gdt_blocks;
            rsv_off++, gdt_off++, gdt_blk++) {
        unsigned int three = 1, five = 5, seven = 7;
        unsigned int grp, last = 0;
        int gdt_dirty = 0;

        gdt_off %= apb;
        if (!dindir_buf[gdt_off]) {
            /* FIXME XXX XXX
            blk_t new_blk;

            retval = ext2fs_new_block(fs, gdt_blk, 0, &new_blk);
            if (retval)
            	goto out_free;
            if (new_blk != gdt_blk) {
            	// XXX free block
            	retval = -1; // XXX
            }
            */
            gdt_dirty = dindir_dirty = inode_dirty = 1;
            memset(gdt_buf, 0, fs->blocksize);
            dindir_buf[gdt_off] = gdt_blk;
            inode.i_blocks += rsv_add;
#ifdef RES_GDT_DEBUG
            printf("added primary GDT block %u at %u[%u]\n",
                   gdt_blk, dindir_blk, gdt_off);
#endif
        } else if (dindir_buf[gdt_off] == gdt_blk) {
#ifdef RES_GDT_DEBUG
            printf("reading primary GDT block %u\n", gdt_blk);
#endif
            retval = ext2fs_read_ind_block(fs, gdt_blk, gdt_buf);
            if (retval)
                goto out_dindir;
        } else {
#ifdef RES_GDT_DEBUG
            printf("bad primary GDT %u != %u at %u[%u]\n",
                   dindir_buf[gdt_off], gdt_blk,dindir_blk,gdt_off);
#endif
            retval = EXT2_ET_RESIZE_INODE_CORRUPT;
            goto out_dindir;
        }

        while ((grp = list_backups(fs, &three, &five, &seven)) <
                fs->group_desc_count) {
            blk_t expect = gdt_blk + grp * sb->s_blocks_per_group;

            if (!gdt_buf[last]) {
#ifdef RES_GDT_DEBUG
                printf("added backup GDT %u grp %u@%u[%u]\n",
                       expect, grp, gdt_blk, last);
#endif
                gdt_buf[last] = expect;
                inode.i_blocks += rsv_add;
                gdt_dirty = inode_dirty = 1;
            } else if (gdt_buf[last] != expect) {
#ifdef RES_GDT_DEBUG
                printf("bad backup GDT %u != %u at %u[%u]\n",
                       gdt_buf[last], expect, gdt_blk, last);
#endif
                retval = EXT2_ET_RESIZE_INODE_CORRUPT;
                goto out_dindir;
            }
            last++;
        }
        if (gdt_dirty) {
#ifdef RES_GDT_DEBUG
            printf("writing primary GDT block %u\n", gdt_blk);
#endif
            retval = ext2fs_write_ind_block(fs, gdt_blk, gdt_buf);
            if (retval)
                goto out_dindir;
        }
    }

out_dindir:
    if (dindir_dirty) {
        retval2 = ext2fs_write_ind_block(fs, dindir_blk, dindir_buf);
        if (!retval)
            retval = retval2;
    }
out_inode:
#ifdef RES_GDT_DEBUG
    printf("inode.i_blocks = %u, i_size = %u\n", inode.i_blocks,
           inode.i_size);
#endif
    if (inode_dirty) {
        inode.i_atime = inode.i_mtime = time(0);
        retval2 = ext2fs_write_inode(fs, EXT2_RESIZE_INO, &inode);
        if (!retval)
            retval = retval2;
    }
out_free:
    ext2fs_free_mem((void **)&dindir_buf);
    return retval;
}
Esempio n. 30
0
/*
 * This function creates a journal using direct I/O routines.
 */
static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
				     blk_t num_blocks, int flags)
{
	char			*buf;
	dgrp_t			group, start, end, i, log_flex;
	errcode_t		retval;
	struct ext2_inode	inode;
	unsigned long long	inode_size;
	struct mkjournal_struct	es;

	if ((retval = ext2fs_create_journal_superblock(fs, num_blocks, flags,
						       &buf)))
		return retval;

	if ((retval = ext2fs_read_bitmaps(fs)))
		goto out2;

	if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
		goto out2;

	if (inode.i_blocks > 0) {
		retval = EEXIST;
		goto out2;
	}

	es.num_blocks = num_blocks;
	es.newblocks = 0;
	es.buf = buf;
	es.err = 0;
	es.flags = flags;
	es.zero_count = 0;

	if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) {
		inode.i_flags |= EXT4_EXTENTS_FL;
		if ((retval = ext2fs_write_inode(fs, journal_ino, &inode)))
			goto out2;
	}

	/*
	 * Set the initial goal block to be roughly at the middle of
	 * the filesystem.  Pick a group that has the largest number
	 * of free blocks.
	 */
	group = ext2fs_group_of_blk2(fs, (ext2fs_blocks_count(fs->super) -
					 fs->super->s_first_data_block) / 2);
	log_flex = 1 << fs->super->s_log_groups_per_flex;
	if (fs->super->s_log_groups_per_flex && (group > log_flex)) {
		group = group & ~(log_flex - 1);
		while ((group < fs->group_desc_count) &&
		       ext2fs_bg_free_blocks_count(fs, group) == 0)
			group++;
		if (group == fs->group_desc_count)
			group = 0;
		start = group;
	} else
		start = (group > 0) ? group-1 : group;
	end = ((group+1) < fs->group_desc_count) ? group+1 : group;
	group = start;
	for (i=start+1; i <= end; i++)
		if (ext2fs_bg_free_blocks_count(fs, i) >
		    ext2fs_bg_free_blocks_count(fs, group))
			group = i;

	es.goal = ext2fs_group_first_block2(fs, group);
	retval = ext2fs_block_iterate3(fs, journal_ino, BLOCK_FLAG_APPEND,
				       0, mkjournal_proc, &es);
	if (es.err) {
		retval = es.err;
		goto errout;
	}
	if (es.zero_count) {
		retval = ext2fs_zero_blocks2(fs, es.blk_to_zero,
					    es.zero_count, 0, 0);
		if (retval)
			goto errout;
	}

	if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
		goto errout;

	inode_size = (unsigned long long)fs->blocksize * num_blocks;
	inode.i_size = inode_size & 0xFFFFFFFF;
	inode.i_size_high = (inode_size >> 32) & 0xFFFFFFFF;
	if (ext2fs_needs_large_file_feature(inode_size))
		fs->super->s_feature_ro_compat |=
			EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
	ext2fs_iblk_add_blocks(fs, &inode, es.newblocks);
	inode.i_mtime = inode.i_ctime = fs->now ? fs->now : time(0);
	inode.i_links_count = 1;
	inode.i_mode = LINUX_S_IFREG | 0600;

	if ((retval = ext2fs_write_new_inode(fs, journal_ino, &inode)))
		goto errout;
	retval = 0;

	memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4);
	fs->super->s_jnl_blocks[15] = inode.i_size_high;
	fs->super->s_jnl_blocks[16] = inode.i_size;
	fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
	ext2fs_mark_super_dirty(fs);

errout:
	ext2fs_zero_blocks2(0, 0, 0, 0, 0);
out2:
	ext2fs_free_mem(&buf);
	return retval;
}