Ejemplo n.º 1
0
Archivo: file.c Proyecto: infidel/linux
static ssize_t udf_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
{
    ssize_t retval;
    struct file *file = iocb->ki_filp;
    struct inode *inode = file_inode(file);
    struct udf_inode_info *iinfo = UDF_I(inode);
    int err;

    mutex_lock(&inode->i_mutex);

    retval = generic_write_checks(iocb, from);
    if (retval <= 0)
        goto out;

    down_write(&iinfo->i_data_sem);
    if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
        loff_t end = iocb->ki_pos + iov_iter_count(from);

        if (inode->i_sb->s_blocksize <
                (udf_file_entry_alloc_offset(inode) + end)) {
            err = udf_expand_file_adinicb(inode);
            if (err) {
                mutex_unlock(&inode->i_mutex);
                udf_debug("udf_expand_adinicb: err=%d\n", err);
                return err;
            }
        } else {
            iinfo->i_lenAlloc = max(end, inode->i_size);
            up_write(&iinfo->i_data_sem);
        }
    } else
        up_write(&iinfo->i_data_sem);

    retval = __generic_file_write_iter(iocb, from);
out:
    mutex_unlock(&inode->i_mutex);

    if (retval > 0) {
        mark_inode_dirty(inode);
        err = generic_write_sync(file, iocb->ki_pos - retval, retval);
        if (err < 0)
            retval = err;
    }

    return retval;
}
Ejemplo n.º 2
0
static int udf_symlink_filler(struct file *file, struct page *page)
{
	struct inode *inode = page->mapping->host;
	struct buffer_head *bh = NULL;
	char *symlink;
	int err = -EIO;
	char *p = kmap(page);
	
	lock_kernel();
	if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
	{
		bh = udf_tread(inode->i_sb, inode->i_ino);

		if (!bh)
			goto out;

		symlink = bh->b_data + udf_file_entry_alloc_offset(inode);
	}
	else
	{
		bh = sb_bread(inode->i_sb, udf_block_map(inode, 0));

		if (!bh)
			goto out;

		symlink = bh->b_data;
	}

	udf_pc_to_char(symlink, inode->i_size, p);
	udf_release_data(bh);

	unlock_kernel();
	SetPageUptodate(page);
	kunmap(page);
	UnlockPage(page);
	return 0;
out:
	unlock_kernel();
	SetPageError(page);
	kunmap(page);
	UnlockPage(page);
	return err;
}
Ejemplo n.º 3
0
static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
				  unsigned long nr_segs, loff_t ppos)
{
	ssize_t retval;
	struct file *file = iocb->ki_filp;
	struct inode *inode = file->f_path.dentry->d_inode;
	int err, pos;
	size_t count = iocb->ki_left;
	struct udf_inode_info *iinfo = UDF_I(inode);

	down_write(&iinfo->i_data_sem);
	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
		if (file->f_flags & O_APPEND)
			pos = inode->i_size;
		else
			pos = ppos;

		if (inode->i_sb->s_blocksize <
				(udf_file_entry_alloc_offset(inode) +
						pos + count)) {
			err = udf_expand_file_adinicb(inode);
			if (err) {
				udf_debug("udf_expand_adinicb: err=%d\n", err);
				return err;
			}
		} else {
			if (pos + count > inode->i_size)
				iinfo->i_lenAlloc = pos + count;
			else
				iinfo->i_lenAlloc = inode->i_size;
			up_write(&iinfo->i_data_sem);
		}
	} else
		up_write(&iinfo->i_data_sem);

	retval = generic_file_aio_write(iocb, iov, nr_segs, ppos);
	if (retval > 0)
		mark_inode_dirty(inode);

	return retval;
}
Ejemplo n.º 4
0
Archivo: file.c Proyecto: cilynx/dd-wrt
static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
				  unsigned long nr_segs, loff_t ppos)
{
	ssize_t retval;
	struct file *file = iocb->ki_filp;
	struct inode *inode = file->f_path.dentry->d_inode;
	int err, pos;
	size_t count = iocb->ki_left;

	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB) {
		if (file->f_flags & O_APPEND)
			pos = inode->i_size;
		else
			pos = ppos;

		if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) +
						pos + count)) {
			udf_expand_file_adinicb(inode, pos + count, &err);
			if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB) {
				udf_debug("udf_expand_adinicb: err=%d\n", err);
				return err;
			}
		} else {
			if (pos + count > inode->i_size)
				UDF_I_LENALLOC(inode) = pos + count;
			else
				UDF_I_LENALLOC(inode) = inode->i_size;
		}
	}

	retval = generic_file_aio_write(iocb, iov, nr_segs, ppos);
	if (retval > 0)
		mark_inode_dirty(inode);

	return retval;
}
Ejemplo n.º 5
0
struct genericFormat *
udf_add_extendedattr(struct inode * inode, uint32_t size, uint32_t type,
	uint8_t loc)
{
	uint8_t *ea = NULL, *ad = NULL;
	int offset;
	uint16_t crclen;
	int i;

	ea = UDF_I_DATA(inode);
	if (UDF_I_LENEATTR(inode))
		ad = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
	else
	{
		ad = ea;
		size += sizeof(struct extendedAttrHeaderDesc);
	}

	offset = inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode) -
		UDF_I_LENALLOC(inode);

	/* TODO - Check for FreeEASpace */

	if (loc & 0x01 && offset >= size)
	{
		struct extendedAttrHeaderDesc *eahd;
		eahd = (struct extendedAttrHeaderDesc *)ea;

		if (UDF_I_LENALLOC(inode))
		{
			memmove(&ad[size], ad, UDF_I_LENALLOC(inode));
		}

		if (UDF_I_LENEATTR(inode))
		{
			/* check checksum/crc */
			if (le16_to_cpu(eahd->descTag.tagIdent) != TAG_IDENT_EAHD ||
				le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum)
			{
				return NULL;
			}
		}
		else
		{
			size -= sizeof(struct extendedAttrHeaderDesc);
			UDF_I_LENEATTR(inode) += sizeof(struct extendedAttrHeaderDesc);
			eahd->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EAHD);
			if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200)
				eahd->descTag.descVersion = cpu_to_le16(3);
			else
				eahd->descTag.descVersion = cpu_to_le16(2);
			eahd->descTag.tagSerialNum = cpu_to_le16(UDF_SB_SERIALNUM(inode->i_sb));
			eahd->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
			eahd->impAttrLocation = cpu_to_le32(0xFFFFFFFF);
			eahd->appAttrLocation = cpu_to_le32(0xFFFFFFFF);
		}

		offset = UDF_I_LENEATTR(inode);
		if (type < 2048)
		{
			if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode))
			{
				uint32_t aal = le32_to_cpu(eahd->appAttrLocation);
				memmove(&ea[offset - aal + size],
					&ea[aal], offset - aal);
				offset -= aal;
				eahd->appAttrLocation = cpu_to_le32(aal + size);
			}
			if (le32_to_cpu(eahd->impAttrLocation) < UDF_I_LENEATTR(inode))
			{
				uint32_t ial = le32_to_cpu(eahd->impAttrLocation);
				memmove(&ea[offset - ial + size],
					&ea[ial], offset - ial);
				offset -= ial;
				eahd->impAttrLocation = cpu_to_le32(ial + size);
			}
		}
		else if (type < 65536)
		{
			if (le32_to_cpu(eahd->appAttrLocation) < UDF_I_LENEATTR(inode))
			{
				uint32_t aal = le32_to_cpu(eahd->appAttrLocation);
				memmove(&ea[offset - aal + size],
					&ea[aal], offset - aal);
				offset -= aal;
				eahd->appAttrLocation = cpu_to_le32(aal + size);
			}
		}
		/* rewrite CRC + checksum of eahd */
		crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(tag);
		eahd->descTag.descCRCLength = cpu_to_le16(crclen);
		eahd->descTag.descCRC = cpu_to_le16(udf_crc((char *)eahd + sizeof(tag), crclen, 0));
		eahd->descTag.tagChecksum = 0;
		for (i=0; i<16; i++)
			if (i != 4)
				eahd->descTag.tagChecksum += ((uint8_t *)&(eahd->descTag))[i];
		UDF_I_LENEATTR(inode) += size;
		return (struct genericFormat *)&ea[offset];
	}
	if (loc & 0x02)
	{
	}
	return NULL;
}
Ejemplo n.º 6
0
struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size,
					   uint32_t type, uint8_t loc)
{
	uint8_t *ea = NULL, *ad = NULL;
	int offset;
	uint16_t crclen;
	struct udf_inode_info *iinfo = UDF_I(inode);

	ea = iinfo->i_ext.i_data;
	if (iinfo->i_lenEAttr) {
		ad = iinfo->i_ext.i_data + iinfo->i_lenEAttr;
	} else {
		ad = ea;
		size += sizeof(struct extendedAttrHeaderDesc);
	}

	offset = inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode) -
		iinfo->i_lenAlloc;

	

	if (loc & 0x01 && offset >= size) {
		struct extendedAttrHeaderDesc *eahd;
		eahd = (struct extendedAttrHeaderDesc *)ea;

		if (iinfo->i_lenAlloc)
			memmove(&ad[size], ad, iinfo->i_lenAlloc);

		if (iinfo->i_lenEAttr) {
			
			if (eahd->descTag.tagIdent !=
					cpu_to_le16(TAG_IDENT_EAHD) ||
			    le32_to_cpu(eahd->descTag.tagLocation) !=
					iinfo->i_location.logicalBlockNum)
				return NULL;
		} else {
			struct udf_sb_info *sbi = UDF_SB(inode->i_sb);

			size -= sizeof(struct extendedAttrHeaderDesc);
			iinfo->i_lenEAttr +=
				sizeof(struct extendedAttrHeaderDesc);
			eahd->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EAHD);
			if (sbi->s_udfrev >= 0x0200)
				eahd->descTag.descVersion = cpu_to_le16(3);
			else
				eahd->descTag.descVersion = cpu_to_le16(2);
			eahd->descTag.tagSerialNum =
					cpu_to_le16(sbi->s_serial_number);
			eahd->descTag.tagLocation = cpu_to_le32(
					iinfo->i_location.logicalBlockNum);
			eahd->impAttrLocation = cpu_to_le32(0xFFFFFFFF);
			eahd->appAttrLocation = cpu_to_le32(0xFFFFFFFF);
		}

		offset = iinfo->i_lenEAttr;
		if (type < 2048) {
			if (le32_to_cpu(eahd->appAttrLocation) <
					iinfo->i_lenEAttr) {
				uint32_t aal =
					le32_to_cpu(eahd->appAttrLocation);
				memmove(&ea[offset - aal + size],
					&ea[aal], offset - aal);
				offset -= aal;
				eahd->appAttrLocation =
						cpu_to_le32(aal + size);
			}
			if (le32_to_cpu(eahd->impAttrLocation) <
					iinfo->i_lenEAttr) {
				uint32_t ial =
					le32_to_cpu(eahd->impAttrLocation);
				memmove(&ea[offset - ial + size],
					&ea[ial], offset - ial);
				offset -= ial;
				eahd->impAttrLocation =
						cpu_to_le32(ial + size);
			}
		} else if (type < 65536) {
			if (le32_to_cpu(eahd->appAttrLocation) <
					iinfo->i_lenEAttr) {
				uint32_t aal =
					le32_to_cpu(eahd->appAttrLocation);
				memmove(&ea[offset - aal + size],
					&ea[aal], offset - aal);
				offset -= aal;
				eahd->appAttrLocation =
						cpu_to_le32(aal + size);
			}
		}
		
		crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(struct tag);
		eahd->descTag.descCRCLength = cpu_to_le16(crclen);
		eahd->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)eahd +
						sizeof(struct tag), crclen));
		eahd->descTag.tagChecksum = udf_tag_checksum(&eahd->descTag);
		iinfo->i_lenEAttr += size;
		return (struct genericFormat *)&ea[offset];
	}
	if (loc & 0x02)
		;

	return NULL;
}