Esempio n. 1
0
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;
}
Esempio n. 2
0
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 {
Esempio n. 3
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. 4
0
/*
 * 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;
}
extern errcode_t ext2fs_extent_open(ext2_filsys fs, ext2_ino_t ino,
				    ext2_extent_handle_t *ret_handle)
{
	struct ext2_extent_handle	*handle;
	errcode_t			retval;
	int				isize = EXT2_INODE_SIZE(fs->super);
	int				i;
	struct ext3_extent_header	*eh;

	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

	if ((ino == 0) || (ino > fs->super->s_inodes_count))
		return EXT2_ET_BAD_INODE_NUM;

	retval = ext2fs_get_mem(sizeof(struct ext2_extent_handle), &handle);
	if (retval)
		return retval;
	memset(handle, 0, sizeof(struct ext2_extent_handle));

	retval = ext2fs_get_mem(isize, &handle->inode);
	if (retval)
		goto errout;

	handle->ino = ino;
	handle->fs = fs;

	retval = ext2fs_read_inode_full(fs, ino, handle->inode, isize);
	if (retval)
		goto errout;

	eh = (struct ext3_extent_header *) &handle->inode->i_block[0];

	for (i=0; i < EXT2_N_BLOCKS; i++)
		if (handle->inode->i_block[i])
			break;
	if (i >= EXT2_N_BLOCKS) {
		eh->eh_magic = ext2fs_cpu_to_le16(EXT3_EXT_MAGIC);
		eh->eh_depth = 0;
		eh->eh_entries = 0;
		i = (sizeof(handle->inode->i_block) - sizeof(*eh)) /
			sizeof(struct ext3_extent);
		eh->eh_max = ext2fs_cpu_to_le16(i);
		handle->inode->i_flags |= EXT4_EXTENTS_FL;
	}

	if (!(handle->inode->i_flags & EXT4_EXTENTS_FL)) {
		retval = EXT2_ET_INODE_NOT_EXTENT;
		goto errout;
	}

	retval = ext2fs_extent_header_verify(eh, sizeof(handle->inode->i_block));
	if (retval)
		goto errout;

	handle->max_depth = ext2fs_le16_to_cpu(eh->eh_depth);
	handle->type = ext2fs_le16_to_cpu(eh->eh_magic);

	retval = ext2fs_get_mem(((handle->max_depth+1) *
				 sizeof(struct extent_path)),
				&handle->path);
	memset(handle->path, 0,
	       (handle->max_depth+1) * sizeof(struct extent_path));
	handle->path[0].buf = (char *) handle->inode->i_block;

	handle->path[0].left = handle->path[0].entries =
		ext2fs_le16_to_cpu(eh->eh_entries);
	handle->path[0].max_entries = ext2fs_le16_to_cpu(eh->eh_max);
	handle->path[0].curr = 0;
	handle->path[0].end_blk =
		((((__u64) handle->inode->i_size_high << 32) +
		  handle->inode->i_size + (fs->blocksize - 1))
		 >> EXT2_BLOCK_SIZE_BITS(fs->super));
	handle->path[0].visit_num = 1;
	handle->level = 0;
	handle->magic = EXT2_ET_MAGIC_EXTENT_HANDLE;

	*ret_handle = handle;
	return 0;

errout:
	ext2fs_extent_free(handle);
	return retval;
}
Esempio n. 6
0
/* Copy the native file to the fs */
errcode_t do_write_internal(ext2_filsys fs, ext2_ino_t cwd, const char *src,
			    const char *dest, ext2_ino_t root)
{
	int		fd;
	struct stat	statbuf;
	ext2_ino_t	newfile;
	errcode_t	retval;
	struct ext2_inode inode;
	int		bufsize = IO_BUFSIZE;
	int		make_holes = 0;

	fd = ext2fs_open_file(src, O_RDONLY, 0);
	if (fd < 0) {
		com_err(src, errno, 0);
		return errno;
	}
	if (fstat(fd, &statbuf) < 0) {
		com_err(src, errno, 0);
		close(fd);
		return errno;
	}

	retval = ext2fs_namei(fs, root, cwd, dest, &newfile);
	if (retval == 0) {
		close(fd);
		return EXT2_ET_FILE_EXISTS;
	}

	retval = ext2fs_new_inode(fs, cwd, 010755, 0, &newfile);
	if (retval) {
		com_err(__func__, retval, 0);
		close(fd);
		return retval;
	}
#ifdef DEBUGFS
	printf("Allocated inode: %u\n", newfile);
#endif
	retval = ext2fs_link(fs, cwd, dest, newfile,
				EXT2_FT_REG_FILE);
	if (retval == EXT2_ET_DIR_NO_SPACE) {
		retval = ext2fs_expand_dir(fs, cwd);
		if (retval) {
			com_err(__func__, retval, "while expanding directory");
			close(fd);
			return retval;
		}
		retval = ext2fs_link(fs, cwd, dest, newfile,
					EXT2_FT_REG_FILE);
	}
	if (retval) {
		com_err(dest, retval, 0);
		close(fd);
		return errno;
	}
	if (ext2fs_test_inode_bitmap2(fs->inode_map, newfile))
		com_err(__func__, 0, "Warning: inode already set");
	ext2fs_inode_alloc_stats2(fs, newfile, +1, 0);
	memset(&inode, 0, sizeof(inode));
	inode.i_mode = (statbuf.st_mode & ~LINUX_S_IFMT) | LINUX_S_IFREG;
	inode.i_atime = inode.i_ctime = inode.i_mtime =
		fs->now ? fs->now : time(0);
	inode.i_links_count = 1;
	retval = ext2fs_inode_size_set(fs, &inode, statbuf.st_size);
	if (retval) {
		com_err(dest, retval, 0);
		close(fd);
		return retval;
	}
	if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
				      EXT4_FEATURE_INCOMPAT_INLINE_DATA)) {
		inode.i_flags |= EXT4_INLINE_DATA_FL;
	} else if (fs->super->s_feature_incompat &
		   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;
	}

	retval = ext2fs_write_new_inode(fs, newfile, &inode);
	if (retval) {
		com_err(__func__, retval, "while creating inode %u", newfile);
		close(fd);
		return retval;
	}
	if (inode.i_flags & EXT4_INLINE_DATA_FL) {
		retval = ext2fs_inline_data_init(fs, newfile);
		if (retval) {
			com_err("copy_file", retval, 0);
			close(fd);
			return retval;
		}
	}
	if (LINUX_S_ISREG(inode.i_mode)) {
		if (statbuf.st_blocks < statbuf.st_size / S_BLKSIZE) {
			make_holes = 1;
			/*
			 * Use I/O blocksize as buffer size when
			 * copying sparse files.
			 */
			bufsize = statbuf.st_blksize;
		}
		retval = copy_file(fs, fd, newfile, bufsize, make_holes);
		if (retval)
			com_err("copy_file", retval, 0);
	}
	close(fd);

	return retval;
}