Example #1
0
int hmfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
{
	struct inode *inode;
	struct hmfs_sb_info *sbi = HMFS_SB(dir->i_sb);
	void *data_blk;
	size_t symlen = strlen(symname) + 1;
	int ilock;

	if (symlen > HMFS_MAX_SYMLINK_NAME_LEN)
		return -ENAMETOOLONG;

	ilock = mutex_lock_op(sbi);
	inode = hmfs_make_dentry(dir, dentry, S_IFLNK | S_IRWXUGO);

	if (IS_ERR(inode))
		return PTR_ERR(inode);

	inode->i_op = &hmfs_symlink_inode_operations;
	inode->i_mapping->a_ops = &hmfs_dblock_aops;

	data_blk = alloc_new_data_block(inode, 0);
	if (IS_ERR(data_blk))
		return PTR_ERR(data_blk);
	hmfs_memcpy(data_blk, (void *)symname, symlen);

	mutex_unlock_op(sbi, ilock);

	d_instantiate(dentry, inode);
	unlock_new_inode(inode);

	return 0;
}
Example #2
0
static int __hmfs_setxattr(struct inode *inode, int index,
                           const char *name, const void *value, size_t size,
                           int flags)
{
    struct hmfs_xattr_entry *this, *last, *next;
    void *base_addr, *new_xattr_blk;
    int newsize, cpy_size;
    size_t name_len;
    int error = -ENOMEM;

    if (name == NULL)
        return -EINVAL;

    if (value == NULL)
        size = 0;

    name_len = strlen(name);

    if (name_len > HMFS_NAME_LEN)
        return -ERANGE;

    if (name_len + size > HMFS_XATTR_VALUE_LEN)
        return -E2BIG;

    base_addr = get_xattr_block(inode);
    if (!base_addr) {
        error = -ENODATA;
        goto out;
    }

    if (!base_addr) {
        if (flags & XATTR_CREATE)
            goto create;
        error = -ENODATA;
        goto out;
    }
    this = __find_xattr(base_addr, index, name_len, name);

    if (this->e_name_index == HMFS_XATTR_INDEX_END &&
            (flags & XATTR_REPLACE)) {
        error = -ENODATA;
        goto out;
    } else if ((flags & XATTR_CREATE) && this->e_name_index !=
               HMFS_XATTR_INDEX_END) {
        error = -EEXIST;
        goto out;
    }

    newsize = XATTR_RAW_SIZE + name_len + size;

    /* Check Space */
    if (value) {
        /* If value is NULL, it's a remove operation */
        /* Add another hmfs_xattr_entry for end entry */
        last = XATTR_ENTRY(JUMP(this, newsize + XATTR_RAW_SIZE));

        if (DISTANCE(base_addr, last) > HMFS_XATTR_BLOCK_SIZE) {
            error = -ENOSPC;
            goto out;
        }
    }

create:
    /* Allocate new xattr block */
    new_xattr_blk = alloc_new_x_block(inode, HMFS_X_BLOCK_TAG_XATTR, false);
    init_xattr_block(new_xattr_blk);

    /* Remove old entry in old xattr block */
    if (base_addr) {
        /* Copy first part */
        next = XATTR_FIRST_ENTRY(base_addr);
        cpy_size = DISTANCE(next, this);
        hmfs_memcpy(XATTR_FIRST_ENTRY(new_xattr_blk), next, cpy_size);

        /* Get last xattr in source xattr block */
        last = this;
        while (!IS_XATTR_LAST_ENTRY(last))
            last = XATTR_NEXT_ENTRY(last);

        /* Copy second part */
        next = XATTR_NEXT_ENTRY(this);
        cpy_size = DISTANCE(next, last);
        next = XATTR_ENTRY(JUMP(new_xattr_blk, DISTANCE(base_addr, this)));
        hmfs_memcpy(next, XATTR_NEXT_ENTRY(this), cpy_size);
        next = XATTR_ENTRY(JUMP(next, cpy_size));
    } else {
        next = XATTR_FIRST_ENTRY(new_xattr_blk);
    }

    /* Write new entry */
    if (value) {
        next->e_name_index = index;
        next->e_name_len = name_len;
        next->e_value_len = size;
        memcpy(next->e_name, name, name_len);
        memcpy(next->e_name + name_len, value, size);
        next = XATTR_ENTRY(next->e_name + name_len + size);
    }

    /* Write End entry */
    next->e_name_index = HMFS_XATTR_INDEX_END;
    hmfs_bug_on(HMFS_I_SB(inode), DISTANCE(new_xattr_blk,
                                           JUMP(next, XATTR_RAW_SIZE)) > HMFS_XATTR_BLOCK_SIZE);

    inode->i_ctime = CURRENT_TIME;
    mark_inode_dirty(inode);
out:
    return error;
}