コード例 #1
0
ファイル: xattr.c プロジェクト: timemath/hmfs
ssize_t hmfs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
{
    struct inode *inode =dentry->d_inode;
    struct hmfs_xattr_entry *entry;
    void *xattr_block;
    int error = 0;
    size_t size, rest = buffer_size;

    xattr_block  = get_xattr_block(inode);
    if (!xattr_block)
        return -ENODATA;

    list_for_each_xattr(entry, xattr_block) {
        const struct xattr_handler *handler =
            hmfs_xattr_handler(entry->e_name_index);

        if (!handler)
            continue;

        size = handler->list(dentry, buffer, rest,entry->e_name,
                             entry->e_name_len, handler->flags);
        if (buffer && size > rest) {
            error = -ERANGE;
            goto out;
        }

        if (buffer)
            buffer += size;
        rest -= size;
    }
    error = buffer_size - rest;
out:
    return error;
}
コード例 #2
0
ファイル: xattr.c プロジェクト: timemath/hmfs
static int __hmfs_getxattr(struct inode *inode, int index, const char *name,
                           void *buffer, size_t buffer_size)
{
    struct hmfs_xattr_entry *entry;
    void *xattr_block;
    int error = 0;
    size_t value_len, name_len;

    if (name == NULL)
        return -EINVAL;

    name_len = strlen(name);
    if (name_len > HMFS_NAME_LEN)
        return -ERANGE;

    xattr_block = get_xattr_block(inode);
    if (!xattr_block) {
        return -ENODATA;
    }

    entry = __find_xattr(xattr_block, index, name_len, name);
    if (IS_XATTR_LAST_ENTRY(entry)) {
        error = -ENODATA;
        goto out;
    }

    value_len = entry->e_value_len;

    if (buffer && value_len > buffer_size) {
        error = -ERANGE;
        goto out;
    }

    if (buffer) {
        memcpy(buffer, entry->e_name + name_len, value_len);
    }

    error = value_len;
out:
    return error;
}
コード例 #3
0
ファイル: read_xattrs.c プロジェクト: OliverGesch/epk2extract
/*
 * Construct and return the list of xattr name:value pairs for the passed xattr
 * id
 *
 * There are two users for get_xattr(), Mksquashfs uses it to read the
 * xattrs from the filesystem on appending, and Unsquashfs uses it
 * to retrieve the xattrs for writing to disk.
 *
 * Unfortunately, the two users disagree on what to do with unknown
 * xattr prefixes, Mksquashfs wants to treat this as fatal otherwise
 * this will cause xattrs to be be lost on appending.  Unsquashfs
 * on the otherhand wants to retrieve the xattrs which are known and
 * to ignore the rest, this allows Unsquashfs to cope more gracefully
 * with future versions which may have unknown xattrs, as long as the
 * general xattr structure is adhered to, Unsquashfs should be able
 * to safely ignore unknown xattrs, and to write the ones it knows about,
 * this is better than completely refusing to retrieve all the xattrs.
 *
 * If ignore is TRUE then don't treat unknown xattr prefixes as
 * a failure to read the xattr.  
 */
struct xattr_list *get_xattr(int i, unsigned int *count, int ignore) {
	long long start;
	struct xattr_list *xattr_list = NULL;
	unsigned int offset;
	void *xptr;
	int j = 0, res = 1;

	TRACE("get_xattr\n");

	*count = xattr_ids[i].count;
	start = SQUASHFS_XATTR_BLK(xattr_ids[i].xattr) + xattr_table_start;
	offset = SQUASHFS_XATTR_OFFSET(xattr_ids[i].xattr);
	xptr = xattrs + get_xattr_block(start) + offset;

	TRACE("get_xattr: xattr_id %d, count %d, start %lld, offset %d\n", i, *count, start, offset);

	while (j < *count) {
		struct squashfs_xattr_entry entry;
		struct squashfs_xattr_val val;

		if (res != 0) {
			xattr_list = realloc(xattr_list, (j + 1) * sizeof(struct xattr_list));
			if (xattr_list == NULL)
				MEM_ERROR();
		}

		SQUASHFS_SWAP_XATTR_ENTRY(xptr, &entry);
		xptr += sizeof(entry);

		res = read_xattr_entry(&xattr_list[j], &entry, xptr);
		if (ignore && res == 0) {
			/* unknown prefix, but ignore flag is set */
			(*count)--;
			continue;
		}

		if (res != 1)
			goto failed;

		xptr += entry.size;

		TRACE("get_xattr: xattr %d, type %d, size %d, name %s\n", j, entry.type, entry.size, xattr_list[j].full_name);

		if (entry.type & SQUASHFS_XATTR_VALUE_OOL) {
			long long xattr;
			void *ool_xptr;

			xptr += sizeof(val);
			SQUASHFS_SWAP_LONG_LONGS(xptr, &xattr, 1);
			xptr += sizeof(xattr);
			start = SQUASHFS_XATTR_BLK(xattr) + xattr_table_start;
			offset = SQUASHFS_XATTR_OFFSET(xattr);
			ool_xptr = xattrs + get_xattr_block(start) + offset;
			SQUASHFS_SWAP_XATTR_VAL(ool_xptr, &val);
			xattr_list[j].value = ool_xptr + sizeof(val);
		} else {
			SQUASHFS_SWAP_XATTR_VAL(xptr, &val);
			xattr_list[j].value = xptr + sizeof(val);
			xptr += sizeof(val) + val.vsize;
		}

		TRACE("get_xattr: xattr %d, vsize %d\n", j, val.vsize);

		xattr_list[j++].vsize = val.vsize;
	}

	if (*count == 0)
		goto failed;

	return xattr_list;

 failed:
	free_xattr(xattr_list, j);

	return NULL;
}
コード例 #4
0
ファイル: xattr.c プロジェクト: timemath/hmfs
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;
}
コード例 #5
0
ファイル: read_xattrs.c プロジェクト: 13572293130/radare2
/*
 * Construct and return the list of xattr name:value pairs for the passed xattr
 * id
 */
struct xattr_list *get_xattr(int i, unsigned int *count)
{
	long long start;
	struct xattr_list *xattr_list = NULL;
	unsigned int offset;
	void *xptr;
	int j;

	TRACE("get_xattr\n");

	*count = xattr_ids[i].count;
	start = SQUASHFS_XATTR_BLK(xattr_ids[i].xattr) + xattr_table_start;
	offset = SQUASHFS_XATTR_OFFSET(xattr_ids[i].xattr);
	xptr = xattrs + get_xattr_block(start) + offset;

	TRACE("get_xattr: xattr_id %d, count %d, start %lld, offset %d\n", i,
			*count, start, offset);

	for(j = 0; j < *count; j++) {
		struct squashfs_xattr_entry entry;
		struct squashfs_xattr_val val;
		int res;

		xattr_list = realloc(xattr_list, (j + 1) *
						sizeof(struct xattr_list));
		if(xattr_list == NULL) {
			ERROR("Out of memory in get_xattrs\n");
			goto failed;
		}
			
		SQUASHFS_SWAP_XATTR_ENTRY(&entry, xptr);
		xptr += sizeof(entry);
		res = read_xattr_entry(&xattr_list[j], &entry, xptr);
		if(res != 1)
			goto failed;
		xptr += entry.size;
			
		TRACE("get_xattr: xattr %d, type %d, size %d, name %s\n", j,
			entry.type, entry.size, xattr_list[j].full_name); 

		if(entry.type & SQUASHFS_XATTR_VALUE_OOL) {
			long long xattr;
			void *ool_xptr;

			xptr += sizeof(val);
			SQUASHFS_SWAP_LONG_LONGS(&xattr, xptr, 1);
			xptr += sizeof(xattr);	
			start = SQUASHFS_XATTR_BLK(xattr) + xattr_table_start;
			offset = SQUASHFS_XATTR_OFFSET(xattr);
			ool_xptr = xattrs + get_xattr_block(start) + offset;
			SQUASHFS_SWAP_XATTR_VAL(&val, ool_xptr);
			xattr_list[j].value = ool_xptr + sizeof(val);
		} else {
			SQUASHFS_SWAP_XATTR_VAL(&val, xptr);
			xattr_list[j].value = xptr + sizeof(val);
			xptr += sizeof(val) + val.vsize;
		}

		TRACE("get_xattr: xattr %d, vsize %d\n", j, val.vsize);

		xattr_list[j].vsize = val.vsize;
	}

	return xattr_list;

failed:
	free(xattr_list);

	return NULL;
}