コード例 #1
0
/*
 * Initialize new quotafile
 */
static int v2_new_io(struct quota_handle *h)
{
	int file_magics[] = INITQMAGICS;
	struct v2_disk_dqheader ddqheader;
	struct v2_disk_dqinfo ddqinfo;

	if (h->qh_fmt != QFMT_VFS_V1)
		return -1;

	/* Write basic quota header */
	ddqheader.dqh_magic = ext2fs_cpu_to_le32(file_magics[h->qh_type]);
	ddqheader.dqh_version = ext2fs_cpu_to_le32(V2_VERSION);
	if (h->e2fs_write(&h->qh_qf, 0, &ddqheader, sizeof(ddqheader)) !=
			sizeof(ddqheader))
		return -1;

	/* Write information about quotafile */
	h->qh_info.dqi_bgrace = MAX_DQ_TIME;
	h->qh_info.dqi_igrace = MAX_IQ_TIME;
	h->qh_info.u.v2_mdqi.dqi_flags = 0;
	h->qh_info.u.v2_mdqi.dqi_qtree.dqi_blocks = QT_TREEOFF + 1;
	h->qh_info.u.v2_mdqi.dqi_qtree.dqi_free_blk = 0;
	h->qh_info.u.v2_mdqi.dqi_qtree.dqi_free_entry = 0;
	h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size =
				sizeof(struct v2r1_disk_dqblk);
	h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r1_fmt_ops;
	v2_mem2diskdqinfo(&ddqinfo, &h->qh_info);
	if (h->e2fs_write(&h->qh_qf, V2_DQINFOOFF, &ddqinfo,
			  sizeof(ddqinfo)) !=
	    sizeof(ddqinfo))
		return -1;

	return 0;
}
コード例 #2
0
ファイル: acl.c プロジェクト: ngkaho1234/fuse-lwext4
int fuse_to_ext4_acl(const acl_ea_header *facl, size_t facl_sz,
			    ext4_acl_header **eacl, size_t *eacl_sz)
{
	int i, facl_count;
	ext4_acl_header *h;
	size_t h_sz;
	ext4_acl_entry *e;
	acl_ea_entry *a;
	unsigned char *hptr;
	int err = 0;

	facl_count = acl_ea_count(facl_sz);
	h_sz = ext4_acl_size(facl_count);
	if (facl_count < 0 || facl->a_version != ACL_EA_VERSION)
		return -EINVAL;

	h = malloc(h_sz);
	if (!h)
		return -ENOMEM;

	h->a_version = ext2fs_cpu_to_le32(EXT4_ACL_VERSION);
	hptr = (unsigned char *) (h + 1);
	for (i = 0, a = facl->a_entries; i < facl_count; i++, a++) {
		e = (ext4_acl_entry *) hptr;
		e->e_tag = ext2fs_cpu_to_le16(a->e_tag);
		e->e_perm = ext2fs_cpu_to_le16(a->e_perm);

		switch (a->e_tag) {
		case ACL_USER:
		case ACL_GROUP:
			e->e_id = ext2fs_cpu_to_le32(a->e_id);
			hptr += sizeof(ext4_acl_entry);
			break;
		case ACL_USER_OBJ:
		case ACL_GROUP_OBJ:
		case ACL_MASK:
		case ACL_OTHER:
			hptr += sizeof(ext4_acl_entry_short);
			break;
		default:
			err = -EINVAL;
			goto out;
		}
	}

	*eacl = h;
	*eacl_sz = h_sz;
	return err;
out:
	free(h);
	return err;
}
コード例 #3
0
ファイル: newdir.c プロジェクト: DebdutBiswas/WinFLASHTool
/*
 * Create new directory on inline data
 */
errcode_t ext2fs_new_dir_inline_data(ext2_filsys fs, ext2_ino_t dir_ino,
				     ext2_ino_t parent_ino, __u32 *iblock)
{
	struct ext2_dir_entry 	*dir = NULL;
	errcode_t		retval;
	int			rec_len;

	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

	iblock[0] = ext2fs_cpu_to_le32(parent_ino);

	dir = (struct ext2_dir_entry *)((char *)iblock +
					EXT4_INLINE_DATA_DOTDOT_SIZE);
	dir->inode = 0;
	rec_len = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DATA_DOTDOT_SIZE;
	retval = ext2fs_set_rec_len(fs, rec_len, dir);
	if (retval)
		goto errout;

#ifdef WORDS_BIGENDIAN
	retval = ext2fs_dirent_swab_out2(fs, (char *)dir, rec_len, 0);
	if (retval)
		goto errout;
#endif

errout:
	return retval;
}
コード例 #4
0
ファイル: extent.c プロジェクト: haie1011/nofs
errcode_t ext2fs_extent_replace(ext2_extent_handle_t handle,
				int flags EXT2FS_ATTR((unused)),
				struct ext2fs_extent *extent)
{
	struct extent_path		*path;
	struct ext3_extent_idx		*ix;
	struct ext3_extent		*ex;

	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);

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

	if (!handle->path)
		return EXT2_ET_NO_CURRENT_NODE;

	path = handle->path + handle->level;
	if (!path->curr)
		return EXT2_ET_NO_CURRENT_NODE;

#ifdef DEBUG
	printf("extent replace: %u ", handle->ino);
	dbg_print_extent(0, extent);
#endif

	if (handle->level == handle->max_depth) {
		ex = path->curr;

		ex->ee_block = ext2fs_cpu_to_le32(extent->e_lblk);
		ex->ee_start = ext2fs_cpu_to_le32(extent->e_pblk & 0xFFFFFFFF);
		ex->ee_start_hi = ext2fs_cpu_to_le16(extent->e_pblk >> 32);
		if (extent->e_flags & EXT2_EXTENT_FLAGS_UNINIT) {
			if (extent->e_len > EXT_UNINIT_MAX_LEN)
				return EXT2_ET_EXTENT_INVALID_LENGTH;
			ex->ee_len = ext2fs_cpu_to_le16(extent->e_len +
							EXT_INIT_MAX_LEN);
		} else {
			if (extent->e_len > EXT_INIT_MAX_LEN)
				return EXT2_ET_EXTENT_INVALID_LENGTH;
			ex->ee_len = ext2fs_cpu_to_le16(extent->e_len);
		}
	} else {
コード例 #5
0
ファイル: acl.c プロジェクト: ngkaho1234/fuse-lwext4
int ext4_to_fuse_acl(acl_ea_header **facl, size_t *facl_sz,
		     const ext4_acl_header *eacl, size_t eacl_sz)
{
	int i, eacl_count;
	acl_ea_header *f;
	ext4_acl_entry *e;
	acl_ea_entry *a;
	size_t f_sz;
	unsigned char *hptr;
	int err = 0;

	eacl_count = ext4_acl_count(eacl_sz);
	f_sz = acl_ea_size(eacl_count);
	if (eacl_count < 0 ||
	    eacl->a_version != ext2fs_cpu_to_le32(EXT4_ACL_VERSION))
		return -EINVAL;

	f = malloc(f_sz);
	if (!f)
		return -ENOMEM;

	f->a_version = ACL_EA_VERSION;
	hptr = (unsigned char *) (eacl + 1);
	for (i = 0, a = f->a_entries; i < eacl_count; i++, a++) {
		e = (ext4_acl_entry *) hptr;
		a->e_tag = ext2fs_le16_to_cpu(e->e_tag);
		a->e_perm = ext2fs_le16_to_cpu(e->e_perm);

		switch (a->e_tag) {
		case ACL_USER:
		case ACL_GROUP:
			a->e_id = ext2fs_le32_to_cpu(e->e_id);
			hptr += sizeof(ext4_acl_entry);
			break;
		case ACL_USER_OBJ:
		case ACL_GROUP_OBJ:
		case ACL_MASK:
		case ACL_OTHER:
			hptr += sizeof(ext4_acl_entry_short);
			break;
		default:
			err = -EINVAL;
			goto out;
		}
	}

	*facl = f;
	*facl_sz = f_sz;
	return err;
out:
	free(f);
	return err;
}
コード例 #6
0
ファイル: undo_io.c プロジェクト: matt-wu/e2fsprogs
static errcode_t undo_setup_tdb(struct undo_private_data *data)
{
	int i;
	errcode_t retval;

	if (data->tdb_written == 1)
		return 0;

	data->tdb_written = 1;

	/* Make a bitmap to track what we've written */
	memset(&data->fake_fs, 0, sizeof(data->fake_fs));
	data->fake_fs.blocksize = data->tdb_data_size;
	retval = ext2fs_alloc_generic_bmap(&data->fake_fs,
				EXT2_ET_MAGIC_BLOCK_BITMAP64,
				EXT2FS_BMAP64_RBTREE,
				0, ~1ULL, ~1ULL,
				"undo block map", &data->written_block_map);
	if (retval)
		return retval;

	/* Allocate key block */
	retval = ext2fs_get_mem(data->tdb_data_size, &data->keyb);
	if (retval)
		return retval;
	data->key_blk_num = data->first_key_blk;

	/* Record block size */
	dbg_printf("Undo block size %llu\n", data->tdb_data_size);
	dbg_printf("Keys per block %llu\n", KEYS_PER_BLOCK(data));
	data->hdr.block_size = ext2fs_cpu_to_le32(data->tdb_data_size);
	io_channel_set_blksize(data->undo_file, data->tdb_data_size);

	/* Ensure that we have space for header blocks */
	for (i = 0; i <= 2; i++) {
		retval = io_channel_read_blk64(data->undo_file, i, 1,
					       data->keyb);
		if (retval)
			memset(data->keyb, 0, data->tdb_data_size);
		retval = io_channel_write_blk64(data->undo_file, i, 1,
						data->keyb);
		if (retval)
			return retval;
		retval = io_channel_flush(data->undo_file);
		if (retval)
			return retval;
	}
	memset(data->keyb, 0, data->tdb_data_size);
	return 0;
}
コード例 #7
0
/*
 * Copy dquot from memory to disk
 */
static void v2r1_mem2diskdqblk(void *dp, struct dquot *dquot)
{
	struct util_dqblk *m = &dquot->dq_dqb;
	struct v2r1_disk_dqblk *d = dp;

	d->dqb_ihardlimit = ext2fs_cpu_to_le64(m->dqb_ihardlimit);
	d->dqb_isoftlimit = ext2fs_cpu_to_le64(m->dqb_isoftlimit);
	d->dqb_bhardlimit = ext2fs_cpu_to_le64(m->dqb_bhardlimit);
	d->dqb_bsoftlimit = ext2fs_cpu_to_le64(m->dqb_bsoftlimit);
	d->dqb_curinodes = ext2fs_cpu_to_le64(m->dqb_curinodes);
	d->dqb_curspace = ext2fs_cpu_to_le64(m->dqb_curspace);
	d->dqb_itime = ext2fs_cpu_to_le64(m->dqb_itime);
	d->dqb_btime = ext2fs_cpu_to_le64(m->dqb_btime);
	d->dqb_id = ext2fs_cpu_to_le32(dquot->dq_id);
	if (qtree_entry_unused(&dquot->dq_h->qh_info.u.v2_mdqi.dqi_qtree, dp))
		d->dqb_itime = ext2fs_cpu_to_le64(1);
}
コード例 #8
0
/*
 * Copy dqinfo from memory to disk
 */
static inline void v2_mem2diskdqinfo(struct v2_disk_dqinfo *d,
				     struct util_dqinfo *m)
{
	d->dqi_bgrace = ext2fs_cpu_to_le32(m->dqi_bgrace);
	d->dqi_igrace = ext2fs_cpu_to_le32(m->dqi_igrace);
	d->dqi_flags = ext2fs_cpu_to_le32(m->u.v2_mdqi.dqi_flags & V2_DQF_MASK);
	d->dqi_blocks = ext2fs_cpu_to_le32(m->u.v2_mdqi.dqi_qtree.dqi_blocks);
	d->dqi_free_blk =
		ext2fs_cpu_to_le32(m->u.v2_mdqi.dqi_qtree.dqi_free_blk);
	d->dqi_free_entry =
		ext2fs_cpu_to_le32(m->u.v2_mdqi.dqi_qtree.dqi_free_entry);
}
コード例 #9
0
ファイル: rehash.c プロジェクト: DebdutBiswas/WinFLASHTool
/*
 * This function takes the leaf nodes which have been written in
 * outdir, and populates the root node and any necessary interior nodes.
 */
static errcode_t calculate_tree(ext2_filsys fs,
				struct out_dir *outdir,
				ext2_ino_t ino,
				ext2_ino_t parent)
{
	struct ext2_dx_root_info  	*root_info;
	struct ext2_dx_entry 		*root, *dx_ent = 0;
	struct ext2_dx_countlimit	*root_limit, *limit;
	errcode_t			retval;
	char				* block_start;
	int				i, c1, c2, nblks;
	int				limit_offset, root_offset;

	root_info = set_root_node(fs, outdir->buf, ino, parent);
	root_offset = limit_offset = ((char *) root_info - outdir->buf) +
		root_info->info_length;
	root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
	c1 = root_limit->limit;
	nblks = outdir->num;

	/* Write out the pointer blocks */
	if (nblks-1 <= c1) {
		/* Just write out the root block, and we're done */
		root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
		for (i=1; i < nblks; i++) {
			root->block = ext2fs_cpu_to_le32(i);
			if (i != 1)
				root->hash =
					ext2fs_cpu_to_le32(outdir->hashes[i]);
			root++;
			c1--;
		}
	} else {
		c2 = 0;
		limit = 0;
		root_info->indirect_levels = 1;
		for (i=1; i < nblks; i++) {
			if (c1 == 0)
				return ENOSPC;
			if (c2 == 0) {
				if (limit)
					limit->limit = limit->count =
		ext2fs_cpu_to_le16(limit->limit);
				root = (struct ext2_dx_entry *)
					(outdir->buf + root_offset);
				root->block = ext2fs_cpu_to_le32(outdir->num);
				if (i != 1)
					root->hash =
			ext2fs_cpu_to_le32(outdir->hashes[i]);
				if ((retval =  get_next_block(fs, outdir,
							      &block_start)))
					return retval;
				dx_ent = set_int_node(fs, block_start);
				limit = (struct ext2_dx_countlimit *) dx_ent;
				c2 = limit->limit;
				root_offset += sizeof(struct ext2_dx_entry);
				c1--;
			}
			dx_ent->block = ext2fs_cpu_to_le32(i);
			if (c2 != limit->limit)
				dx_ent->hash =
					ext2fs_cpu_to_le32(outdir->hashes[i]);
			dx_ent++;
			c2--;
		}
		limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
		limit->limit = ext2fs_cpu_to_le16(limit->limit);
	}
	root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
	root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
	root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);

	return 0;
}
コード例 #10
0
ファイル: inline_data.c プロジェクト: kikimo/w4118-hmwk6
int ext2fs_inline_data_dir_iterate(ext2_filsys fs, ext2_ino_t ino,
                                   void *priv_data)
{
    struct dir_context *ctx;
    struct ext2_inode inode;
    struct ext2_dir_entry dirent;
    struct ext2_inline_data data;
    int ret = BLOCK_ABORT;
    e2_blkcnt_t blockcnt = 0;
    char *old_buf;
    unsigned int old_buflen;
    int old_flags;

    ctx = (struct dir_context *)priv_data;
    old_buf = ctx->buf;
    old_buflen = ctx->buflen;
    old_flags = ctx->flags;
    ctx->flags |= DIRENT_FLAG_INCLUDE_INLINE_DATA;

    ctx->errcode = ext2fs_read_inode(fs, ino, &inode);
    if (ctx->errcode)
        goto out;

    if (!(inode.i_flags & EXT4_INLINE_DATA_FL)) {
        ctx->errcode = EXT2_ET_NO_INLINE_DATA;
        goto out;
    }

    if (!LINUX_S_ISDIR(inode.i_mode)) {
        ctx->errcode = EXT2_ET_NO_DIRECTORY;
        goto out;
    }
    ret = 0;

    /* we first check '.' and '..' dir */
    dirent.inode = ino;
    dirent.name_len = 1;
    ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(2), &dirent);
    dirent.name[0] = '.';
    dirent.name[1] = '\0';
    ctx->buf = (char *)&dirent;
    ext2fs_get_rec_len(fs, &dirent, &ctx->buflen);
    ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
    if (ret & BLOCK_ABORT)
        goto out;

    dirent.inode = ext2fs_le32_to_cpu(inode.i_block[0]);
    dirent.name_len = 2;
    ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(3), &dirent);
    dirent.name[0] = '.';
    dirent.name[1] = '.';
    dirent.name[2] = '\0';
    ctx->buf = (char *)&dirent;
    ext2fs_get_rec_len(fs, &dirent, &ctx->buflen);
    ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
    if (ret & BLOCK_INLINE_DATA_CHANGED) {
        errcode_t err;

        inode.i_block[0] = ext2fs_cpu_to_le32(dirent.inode);
        err = ext2fs_write_inode(fs, ino, &inode);
        if (err)
            goto out;
        ret &= ~BLOCK_INLINE_DATA_CHANGED;
    }
    if (ret & BLOCK_ABORT)
        goto out;

    ctx->buf = (char *)inode.i_block + EXT4_INLINE_DATA_DOTDOT_SIZE;
    ctx->buflen = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DATA_DOTDOT_SIZE;
#ifdef WORDS_BIGENDIAN
    ctx->errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0);
    if (ctx->errcode) {
        ret |= BLOCK_ABORT;
        goto out;
    }
#endif
    ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
    if (ret & BLOCK_INLINE_DATA_CHANGED) {
#ifdef WORDS_BIGENDIAN
        ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf,
                                               ctx->buflen, 0);
        if (ctx->errcode) {
            ret |= BLOCK_ABORT;
            goto out;
        }
#endif
        ctx->errcode = ext2fs_write_inode(fs, ino, &inode);
        if (ctx->errcode)
            ret |= BLOCK_ABORT;
        ret &= ~BLOCK_INLINE_DATA_CHANGED;
    }
    if (ret & BLOCK_ABORT)
        goto out;

    data.fs = fs;
    data.ino = ino;
    ctx->errcode = ext2fs_inline_data_ea_get(&data);
    if (ctx->errcode) {
        ret |= BLOCK_ABORT;
        goto out;
    }
    if (data.ea_size <= 0)
        goto out1;

    ctx->buf = data.ea_data;
    ctx->buflen = data.ea_size;
#ifdef WORDS_BIGENDIAN
    ctx->errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0);
    if (ctx->errcode) {
        ret |= BLOCK_ABORT;
        goto out1;
    }
#endif

    ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
    if (ret & BLOCK_INLINE_DATA_CHANGED) {
#ifdef WORDS_BIGENDIAN
        ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf,
                                               ctx->buflen, 0);
        if (ctx->errcode) {
            ret |= BLOCK_ABORT;
            goto out1;
        }
#endif
        ctx->errcode = ext2fs_inline_data_ea_set(&data);
        if (ctx->errcode)
            ret |= BLOCK_ABORT;
    }

out1:
    ext2fs_free_mem(&data.ea_data);
out:
    ctx->buf = old_buf;
    ctx->buflen = old_buflen;
    ctx->flags = old_flags;
    ret &= ~(BLOCK_ABORT | BLOCK_INLINE_DATA_CHANGED);
    return ret;
}
コード例 #11
0
ファイル: undo_io.c プロジェクト: matt-wu/e2fsprogs
static errcode_t undo_write_tdb(io_channel channel,
				unsigned long long block, int count)

{
	int size, sz;
	unsigned long long block_num, backing_blk_num;
	errcode_t retval = 0;
	ext2_loff_t offset;
	struct undo_private_data *data;
	unsigned char *read_ptr;
	unsigned long long end_block;
	unsigned long long data_size;
	void *data_ptr;
	struct undo_key *key;
	__u32 blk_crc;

	data = (struct undo_private_data *) channel->private_data;

	if (data->undo_file == NULL) {
		/*
		 * Transaction database not initialized
		 */
		return 0;
	}

	if (count == 1)
		size = channel->block_size;
	else {
		if (count < 0)
			size = -count;
		else
			size = count * channel->block_size;
	}

	retval = undo_setup_tdb(data);
	if (retval)
		return retval;
	/*
	 * Data is stored in tdb database as blocks of tdb_data_size size
	 * This helps in efficient lookup further.
	 *
	 * We divide the disk to blocks of tdb_data_size.
	 */
	offset = (block * channel->block_size) + data->offset ;
	block_num = offset / data->tdb_data_size;
	end_block = (offset + size - 1) / data->tdb_data_size;

	while (block_num <= end_block) {
		__u32 keysz;

		/*
		 * Check if we have the record already
		 */
		if (ext2fs_test_block_bitmap2(data->written_block_map,
						   block_num)) {
			/* Try the next block */
			block_num++;
			continue;
		}
		ext2fs_mark_block_bitmap2(data->written_block_map, block_num);

		/*
		 * Read one block using the backing I/O manager
		 * The backing I/O manager block size may be
		 * different from the tdb_data_size.
		 * Also we need to recalcuate the block number with respect
		 * to the backing I/O manager.
		 */
		offset = block_num * data->tdb_data_size;
		backing_blk_num = (offset - data->offset) / channel->block_size;

		count = data->tdb_data_size +
				((offset - data->offset) % channel->block_size);
		retval = ext2fs_get_mem(count, &read_ptr);
		if (retval) {
			return retval;
		}

		memset(read_ptr, 0, count);
		actual_size = 0;
		if ((count % channel->block_size) == 0)
			sz = count / channel->block_size;
		else
			sz = -count;
		retval = io_channel_read_blk64(data->real, backing_blk_num,
					     sz, read_ptr);
		if (retval) {
			if (retval != EXT2_ET_SHORT_READ) {
				free(read_ptr);
				return retval;
			}
			/*
			 * short read so update the record size
			 * accordingly
			 */
			data_size = actual_size;
		} else {
			data_size = data->tdb_data_size;
		}
		if (data_size == 0) {
			free(read_ptr);
			block_num++;
			continue;
		}
		dbg_printf("Read %llu bytes from FS block %llu (blk=%llu cnt=%u)\n",
		       data_size, backing_blk_num, block, count);
		if ((data_size % data->undo_file->block_size) == 0)
			sz = data_size / data->undo_file->block_size;
		else
			sz = -actual_size;
		data_ptr = read_ptr + ((offset - data->offset) %
				       data->undo_file->block_size);
		/* extend this key? */
		if (data->keys_in_block) {
			key = data->keyb->keys + data->keys_in_block - 1;
			keysz = ext2fs_le32_to_cpu(key->size);
		} else {
			key = NULL;
			keysz = 0;
		}
		if (key != NULL &&
		    ext2fs_le64_to_cpu(key->fsblk) +
		    ((keysz + data->tdb_data_size - 1) /
		     data->tdb_data_size) == backing_blk_num &&
		    E2UNDO_MAX_EXTENT_BLOCKS * data->tdb_data_size >
		    keysz + sz) {
			blk_crc = ext2fs_le32_to_cpu(key->blk_crc);
			blk_crc = ext2fs_crc32c_le(blk_crc,
						   (unsigned char *)data_ptr,
						   data_size);
			key->blk_crc = ext2fs_cpu_to_le32(blk_crc);
			key->size = ext2fs_cpu_to_le32(keysz + data_size);
		} else {
			data->num_keys++;
			key = data->keyb->keys + data->keys_in_block;
			data->keys_in_block++;
			key->fsblk = ext2fs_cpu_to_le64(backing_blk_num);
			blk_crc = ext2fs_crc32c_le(~0,
						   (unsigned char *)data_ptr,
						   data_size);
			key->blk_crc = ext2fs_cpu_to_le32(blk_crc);
			key->size = ext2fs_cpu_to_le32(data_size);
		}
		dbg_printf("Writing block %llu to offset %llu size %d key %zu\n",
		       block_num,
		       data->undo_blk_num,
		       sz, data->num_keys - 1);
		retval = io_channel_write_blk64(data->undo_file,
					data->undo_blk_num, sz, data_ptr);
		if (retval) {
			free(read_ptr);
			return retval;
		}
		data->undo_blk_num++;
		free(read_ptr);

		/* Write out the key block */
		retval = write_undo_indexes(data, 0);
		if (retval)
			return retval;

		/* Next block */
		block_num++;
	}

	return retval;
}
コード例 #12
0
ファイル: undo_io.c プロジェクト: matt-wu/e2fsprogs
static errcode_t write_undo_indexes(struct undo_private_data *data, int flush)
{
	errcode_t retval;
	struct ext2_super_block super;
	io_channel channel;
	int block_size;
	__u32 sb_crc, hdr_crc;

	/* Spit out a key block, if there's any data */
	if (data->keys_in_block) {
		data->keyb->magic = ext2fs_cpu_to_le32(KEYBLOCK_MAGIC);
		data->keyb->crc = 0;
		data->keyb->crc = ext2fs_cpu_to_le32(
					 ext2fs_crc32c_le(~0,
					 (unsigned char *)data->keyb,
					 data->tdb_data_size));
		dbg_printf("Writing keyblock to blk %llu\n", data->key_blk_num);
		retval = io_channel_write_blk64(data->undo_file,
						data->key_blk_num,
						1, data->keyb);
		if (retval)
			return retval;
		/* Move on to the next key block if it's full. */
		if (data->keys_in_block == KEYS_PER_BLOCK(data)) {
			memset(data->keyb, 0, data->tdb_data_size);
			data->keys_in_block = 0;
			data->key_blk_num = data->undo_blk_num;
			data->undo_blk_num++;
		}
	}

	/* Prepare superblock for write */
	channel = data->real;
	block_size = channel->block_size;

	io_channel_set_blksize(channel, SUPERBLOCK_OFFSET);
	retval = io_channel_read_blk64(channel, 1, -SUPERBLOCK_SIZE, &super);
	if (retval)
		goto err_out;
	sb_crc = ext2fs_crc32c_le(~0, (unsigned char *)&super, SUPERBLOCK_SIZE);
	super.s_magic = ~super.s_magic;

	/* Write the undo header to disk. */
	memcpy(data->hdr.magic, E2UNDO_MAGIC, sizeof(data->hdr.magic));
	data->hdr.num_keys = ext2fs_cpu_to_le64(data->num_keys);
	data->hdr.super_offset = ext2fs_cpu_to_le64(data->super_blk_num);
	data->hdr.key_offset = ext2fs_cpu_to_le64(data->first_key_blk);
	data->hdr.fs_block_size = ext2fs_cpu_to_le32(block_size);
	data->hdr.sb_crc = ext2fs_cpu_to_le32(sb_crc);
	hdr_crc = ext2fs_crc32c_le(~0, (unsigned char *)&data->hdr,
				   sizeof(data->hdr) -
				   sizeof(data->hdr.header_crc));
	data->hdr.header_crc = ext2fs_cpu_to_le32(hdr_crc);
	retval = io_channel_write_blk64(data->undo_file, 0,
					-(int)sizeof(data->hdr),
					&data->hdr);
	if (retval)
		goto err_out;

	/*
	 * Record the entire superblock (in FS byte order) so that we can't
	 * apply e2undo files to the wrong FS or out of order.
	 */
	dbg_printf("Writing superblock to block %llu\n", data->super_blk_num);
	retval = io_channel_write_blk64(data->undo_file, data->super_blk_num,
					-SUPERBLOCK_SIZE, &super);
	if (retval)
		goto err_out;

	if (flush)
		retval = io_channel_flush(data->undo_file);
err_out:
	io_channel_set_blksize(channel, block_size);
	return retval;
}
コード例 #13
0
int do_create (ext2_filsys e2fs, const char *path, mode_t mode, dev_t dev, const char *fastsymlink)
{
	int rt;
	time_t tm;
	errcode_t rc;

	char *p_path;
	char *r_path;

	ext2_ino_t ino;
	struct ext2_inode inode;
	ext2_ino_t n_ino;

	struct fuse_context *ctx;

	debugf("enter");
	debugf("path = %s, mode: 0%o", path, mode);

	rt=do_check_split(path, &p_path, &r_path);

	debugf("parent: %s, child: %s", p_path, r_path);

	rt = do_readinode(e2fs, p_path, &ino, &inode);
	if (rt) {
		debugf("do_readinode(%s, &ino, &inode); failed", p_path);
		free_split(p_path, r_path);
		return rt;
	}

	rc = ext2fs_new_inode(e2fs, ino, mode, 0, &n_ino);
	if (rc) {
		debugf("ext2fs_new_inode(ep.fs, ino, mode, 0, &n_ino); failed");
		return -ENOMEM;
	}

	do {
		debugf("calling ext2fs_link(e2fs, %d, %s, %d, %d);", ino, r_path, n_ino, do_modetoext2lag(mode));
		rc = ext2fs_link(e2fs, ino, r_path, n_ino, do_modetoext2lag(mode));
		if (rc == EXT2_ET_DIR_NO_SPACE) {
			debugf("calling ext2fs_expand_dir(e2fs, &d)", ino);
			if (ext2fs_expand_dir(e2fs, ino)) {
				debugf("error while expanding directory %s (%d)", p_path, ino);
				free_split(p_path, r_path);
				return -ENOSPC;
			}
		}
	} while (rc == EXT2_ET_DIR_NO_SPACE);
	if (rc) {
		debugf("ext2fs_link(e2fs, %d, %s, %d, %d); failed", ino, r_path, n_ino, do_modetoext2lag(mode));
		free_split(p_path, r_path);
		return -EIO;
	}

	if (ext2fs_test_inode_bitmap(e2fs->inode_map, n_ino)) {
		debugf("inode already set");
	}

	ext2fs_inode_alloc_stats2(e2fs, n_ino, +1, 0);
	memset(&inode, 0, sizeof(inode));
	tm = e2fs->now ? e2fs->now : time(NULL);
	inode.i_mode = mode;
	inode.i_atime = inode.i_ctime = inode.i_mtime = tm;
	inode.i_links_count = 1;
	inode.i_size = 0;
	ctx = fuse_get_context();
	if (ctx) {
		inode.i_uid = ctx->uid;
		inode.i_gid = ctx->gid;
	}

	if (S_ISCHR(mode) || S_ISBLK(mode)) {
		if (old_valid_dev(dev))
			inode.i_block[0]= ext2fs_cpu_to_le32(old_encode_dev(dev));
		else
			inode.i_block[1]= ext2fs_cpu_to_le32(new_encode_dev(dev));
	}

	if (S_ISLNK(mode) && fastsymlink != NULL) {
		inode.i_size = strlen(fastsymlink);
		strncpy((char *)&(inode.i_block[0]),fastsymlink,
				(EXT2_N_BLOCKS * sizeof(inode.i_block[0])));
	}

	rc = ext2fs_write_new_inode(e2fs, n_ino, &inode);
	if (rc) {
		debugf("ext2fs_write_new_inode(e2fs, n_ino, &inode);");
		free_split(p_path, r_path);
		return -EIO;
	}

	/* update parent dir */
	rt = do_readinode(e2fs, p_path, &ino, &inode);
	if (rt) {
		debugf("do_readinode(%s, &ino, &inode); dailed", p_path);
		free_split(p_path, r_path);
		return -EIO;
	}
	inode.i_ctime = inode.i_mtime = tm;
	rc = ext2fs_write_inode(e2fs, ino, &inode);
	if (rc) {
		debugf("ext2fs_write_inode(e2fs, ino, &inode); failed");
		free_split(p_path, r_path);
		return -EIO;
	}

	free_split(p_path, r_path);

	debugf("leave");
	return 0;
}