Exemplo n.º 1
0
static uint8_t *
udf_filead_read(struct inode *dir, uint8_t *tmpad, uint8_t ad_size,
		kernel_lb_addr fe_loc, int *pos, int *offset,
		struct buffer_head **bh, int *error)
{
	int loffset = *offset;
	int block;
	uint8_t *ad;
	int remainder;

	*error = 0;

	ad = (uint8_t *)(*bh)->b_data + *offset;
	*offset += ad_size;

	if (!ad)
	{
		brelse(*bh);
		*error = 1;
		return NULL;
	}

	if (*offset == dir->i_sb->s_blocksize)
	{
		brelse(*bh);
		block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos);
		if (!block)
			return NULL;
		if (!(*bh = udf_tread(dir->i_sb, block)))
			return NULL;
	}
	else if (*offset > dir->i_sb->s_blocksize)
	{
		ad = tmpad;

		remainder = dir->i_sb->s_blocksize - loffset;
		memcpy((uint8_t *)ad, (*bh)->b_data + loffset, remainder);

		brelse(*bh);
		block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos);
		if (!block)
			return NULL;
		if (!((*bh) = udf_tread(dir->i_sb, block)))
			return NULL;

		memcpy((uint8_t *)ad + remainder, (*bh)->b_data, ad_size - remainder);
		*offset = ad_size - remainder;
	}
	return ad;
}
Exemplo n.º 2
0
/*
 * udf_read_tagged
 *
 * PURPOSE
 *	Read the first block of a tagged descriptor.
 *
 * HISTORY
 *	July 1, 1997 - Andrew E. Mileski
 *	Written, tested, and released.
 */
struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
				    uint32_t location, uint16_t *ident)
{
	struct tag *tag_p;
	struct buffer_head *bh = NULL;
	u8 checksum;

	
	if (block == 0xFFFFFFFF)
		return NULL;

	bh = udf_tread(sb, block);
	if (!bh) {
		udf_err(sb, "read failed, block=%u, location=%d\n",
			block, location);
		return NULL;
	}

	tag_p = (struct tag *)(bh->b_data);

	*ident = le16_to_cpu(tag_p->tagIdent);

	if (location != le32_to_cpu(tag_p->tagLocation)) {
		udf_debug("location mismatch block %u, tag %u != %u\n",
			  block, le32_to_cpu(tag_p->tagLocation), location);
		goto error_out;
	}

	
	checksum = udf_tag_checksum(tag_p);
	if (checksum != tag_p->tagChecksum) {
		udf_err(sb, "tag checksum failed, block %u: 0x%02x != 0x%02x\n",
			block, checksum, tag_p->tagChecksum);
		goto error_out;
	}

	
	if (tag_p->descVersion != cpu_to_le16(0x0002U) &&
	    tag_p->descVersion != cpu_to_le16(0x0003U)) {
		udf_err(sb, "tag version 0x%04x != 0x0002 || 0x0003, block %u\n",
			le16_to_cpu(tag_p->descVersion), block);
		goto error_out;
	}

	
	if (le16_to_cpu(tag_p->descCRCLength) + sizeof(struct tag) > sb->s_blocksize ||
	    le16_to_cpu(tag_p->descCRC) == crc_itu_t(0,
					bh->b_data + sizeof(struct tag),
					le16_to_cpu(tag_p->descCRCLength)))
		return bh;

	udf_debug("Crc failure block %d: crc = %d, crclen = %d\n", block,
		  le16_to_cpu(tag_p->descCRC),
		  le16_to_cpu(tag_p->descCRCLength));
error_out:
	brelse(bh);
	return NULL;
}
Exemplo n.º 3
0
/*
 * udf_read_tagged
 *
 * PURPOSE
 *	Read the first block of a tagged descriptor.
 *
 * HISTORY
 *	July 1, 1997 - Andrew E. Mileski
 *	Written, tested, and released.
 */
struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
				    uint32_t location, uint16_t *ident)
{
	tag *tag_p;
	struct buffer_head *bh = NULL;
	struct udf_sb_info *sbi = UDF_SB(sb);

	/* Read the block */
	if (block == 0xFFFFFFFF)
		return NULL;

	bh = udf_tread(sb, block + sbi->s_session);
	if (!bh) {
		udf_debug("block=%d, location=%d: read failed\n",
			  block + sbi->s_session, location);
		return NULL;
	}

	tag_p = (tag *)(bh->b_data);

	*ident = le16_to_cpu(tag_p->tagIdent);

	if (location != le32_to_cpu(tag_p->tagLocation)) {
		udf_debug("location mismatch block %u, tag %u != %u\n",
			  block + sbi->s_session,
			  le32_to_cpu(tag_p->tagLocation), location);
		goto error_out;
	}

	/* Verify the tag checksum */
	if (udf_tag_checksum(tag_p) != tag_p->tagChecksum) {
		printk(KERN_ERR "udf: tag checksum failed block %d\n", block);
		goto error_out;
	}

	/* Verify the tag version */
	if (tag_p->descVersion != cpu_to_le16(0x0002U) &&
	    tag_p->descVersion != cpu_to_le16(0x0003U)) {
		udf_debug("tag version 0x%04x != 0x0002 || 0x0003 block %d\n",
			  le16_to_cpu(tag_p->descVersion), block);
		goto error_out;
	}

	/* Verify the descriptor CRC */
	if (le16_to_cpu(tag_p->descCRCLength) + sizeof(tag) > sb->s_blocksize ||
	    le16_to_cpu(tag_p->descCRC) == udf_crc(bh->b_data + sizeof(tag),
					le16_to_cpu(tag_p->descCRCLength), 0))
		return bh;

	udf_debug("Crc failure block %d: crc = %d, crclen = %d\n",
		  block + sbi->s_session, le16_to_cpu(tag_p->descCRC),
		  le16_to_cpu(tag_p->descCRCLength));

error_out:
	brelse(bh);
	return NULL;
}
Exemplo n.º 4
0
static int read_block_bitmap(struct super_block *sb,
			     struct udf_bitmap *bitmap, unsigned int block,
			     unsigned long bitmap_nr)
{
	struct buffer_head *bh = NULL;
	int retval = 0;
	kernel_lb_addr loc;

	loc.logicalBlockNum = bitmap->s_extPosition;
	loc.partitionReferenceNum = UDF_SB(sb)->s_partition;

	bh = udf_tread(sb, udf_get_lb_pblock(sb, loc, block));
	if (!bh)
		retval = -EIO;

	bitmap->s_block_bitmap[bitmap_nr] = bh;
	return retval;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
/*
 * udf_read_tagged
 *
 * PURPOSE
 *	Read the first block of a tagged descriptor.
 *
 * HISTORY
 *	July 1, 1997 - Andrew E. Mileski
 *	Written, tested, and released.
 */
struct buffer_head *
udf_read_tagged(struct super_block *sb, uint32_t block, uint32_t location, uint16_t *ident)
{
	tag *tag_p;
	struct buffer_head *bh = NULL;
	register uint8_t checksum;
	register int i;

	/* Read the block */
	if (block == 0xFFFFFFFF)
		return NULL;

	bh = udf_tread(sb, block + UDF_SB_SESSION(sb));
	if (!bh)
	{
		udf_debug("block=%d, location=%d: read failed\n", block + UDF_SB_SESSION(sb), location);
		return NULL;
	}

	tag_p = (tag *)(bh->b_data);

	*ident = le16_to_cpu(tag_p->tagIdent);

	if ( location != le32_to_cpu(tag_p->tagLocation) )
	{
		udf_debug("location mismatch block %u, tag %u != %u\n",
			block + UDF_SB_SESSION(sb), le32_to_cpu(tag_p->tagLocation), location);
		goto error_out;
	}
	
	/* Verify the tag checksum */
	checksum = 0U;
	for (i = 0; i < 4; i++)
		checksum += (uint8_t)(bh->b_data[i]);
	for (i = 5; i < 16; i++)
		checksum += (uint8_t)(bh->b_data[i]);
	if (checksum != tag_p->tagChecksum) {
		printk(KERN_ERR "udf: tag checksum failed block %d\n", block);
		goto error_out;
	}

	/* Verify the tag version */
	if (le16_to_cpu(tag_p->descVersion) != 0x0002U &&
		le16_to_cpu(tag_p->descVersion) != 0x0003U)
	{
		udf_debug("tag version 0x%04x != 0x0002 || 0x0003 block %d\n",
			le16_to_cpu(tag_p->descVersion), block);
		goto error_out;
	}

	/* Verify the descriptor CRC */
	if (le16_to_cpu(tag_p->descCRCLength) + sizeof(tag) > sb->s_blocksize ||
		le16_to_cpu(tag_p->descCRC) == udf_crc(bh->b_data + sizeof(tag),
			le16_to_cpu(tag_p->descCRCLength), 0))
	{
		return bh;
	}
	udf_debug("Crc failure block %d: crc = %d, crclen = %d\n",
		block + UDF_SB_SESSION(sb), le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));

error_out:
	brelse(bh);
	return NULL;
}
Exemplo n.º 7
0
 void udf_fill_spartable(struct super_block *sb, struct udf_sparing_data *sdata, int partlen)
 {
 	Uint16 ident;
 	Uint32 spartable;
 	int i;
 	struct buffer_head *bh;
 	struct SparingTable *st;
 
 	for (i=0; i<4; i++)
 	{
 		if (!(spartable = sdata->s_spar_loc[i]))
 			continue;
 
 		bh = udf_read_tagged(sb, spartable, spartable, &ident);
 
 		if (!bh)
 		{
 			sdata->s_spar_loc[i] = 0;
 			continue;
 		}
 
 		if (ident == 0)
 		{
 			st = (struct SparingTable *)bh->b_data;
 			if (!strncmp(st->sparingIdent.ident, UDF_ID_SPARING, strlen(UDF_ID_SPARING)))
 			{
 				SparingEntry *se;
 				Uint16 rtl = le16_to_cpu(st->reallocationTableLen);
 				int index;
 
 				if (!sdata->s_spar_map)
 				{
 					int num = 1, mapsize;
 					sdata->s_spar_indexsize = 8;
 					while (rtl*sizeof(Uint32) >= (1 << sdata->s_spar_indexsize))
 					{
 						num ++;
 						sdata->s_spar_indexsize <<= 1;
 					}
 					mapsize = (rtl * sizeof(Uint32)) +
 						((partlen/(1 << sdata->s_spar_pshift)) * sizeof(Uint8) * num);
 					sdata->s_spar_map = kmalloc(mapsize, GFP_KERNEL);
 					sdata->s_spar_remap.s_spar_remap32 = &sdata->s_spar_map[rtl];
 					memset(sdata->s_spar_map, 0xFF, mapsize);
 				}
 
 				index = sizeof(struct SparingTable);
 				for (i=0; i<rtl; i++)
 				{
 					if (index > sb->s_blocksize)
 					{
 						udf_release_data(bh);
 						bh = udf_tread(sb, ++spartable, sb->s_blocksize);
 						if (!bh)
 						{
 							sdata->s_spar_loc[i] = 0;
 							continue;
 						}
 						index = 0;
 					}
 					se = (SparingEntry *)&(bh->b_data[index]);
 					index += sizeof(SparingEntry);
 
 					if (sdata->s_spar_map[i] == 0xFFFFFFFF)
 						sdata->s_spar_map[i] = le32_to_cpu(se->mappedLocation);
 					else if (sdata->s_spar_map[i] != le32_to_cpu(se->mappedLocation))
 					{
 						udf_debug("Found conflicting Sparing Data (%d vs %d for entry %d)\n",
 							sdata->s_spar_map[i], le32_to_cpu(se->mappedLocation), i);
 					}
 
 					if (le32_to_cpu(se->origLocation) < 0xFFFFFFF0)
 					{
 						int packet = le32_to_cpu(se->origLocation) >> sdata->s_spar_pshift;
 						if (sdata->s_spar_indexsize == 8)
 						{
 							if (sdata->s_spar_remap.s_spar_remap8[packet] == 0xFF)
 								sdata->s_spar_remap.s_spar_remap8[packet] = i;
 							else if (sdata->s_spar_remap.s_spar_remap8[packet] != i)
 							{
 								udf_debug("Found conflicting Sparing Data (%d vs %d)\n",
 									sdata->s_spar_remap.s_spar_remap8[packet], i);
 							}
 						}
 						else if (sdata->s_spar_indexsize == 16)
 						{
 							if (sdata->s_spar_remap.s_spar_remap16[packet] == 0xFFFF)
 								sdata->s_spar_remap.s_spar_remap16[packet] = i;
 							else if (sdata->s_spar_remap.s_spar_remap16[packet] != i)
 							{
 								udf_debug("Found conflicting Sparing Data (%d vs %d)\n",
 									sdata->s_spar_remap.s_spar_remap16[packet], i);
 							}
 						}
 						else if (sdata->s_spar_indexsize == 32)
 						{
 							if (sdata->s_spar_remap.s_spar_remap32[packet] == 0xFFFFFFFF)
 								sdata->s_spar_remap.s_spar_remap32[packet] = i;
 							else if (sdata->s_spar_remap.s_spar_remap32[packet] != i)
 							{
 								udf_debug("Found conflicting Sparing Data (%d vs %d)\n",
 									sdata->s_spar_remap.s_spar_remap32[packet], i);
 							}
 						}
 					}
 				}
 			}
Exemplo n.º 8
0
struct FileIdentDesc *
udf_fileident_read(struct inode *dir, loff_t *nf_pos,
	struct udf_fileident_bh *fibh,
	struct FileIdentDesc *cfi,
	lb_addr *bloc, Uint32 *extoffset, 
	lb_addr *eloc, Uint32 *elen,
	Uint32 *offset, struct buffer_head **bh)
{
	struct FileIdentDesc *fi;
	int block;

	fibh->soffset = fibh->eoffset;

	if (fibh->eoffset == dir->i_sb->s_blocksize)
	{
		int lextoffset = *extoffset;

		if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
			EXTENT_RECORDED_ALLOCATED)
		{
			return NULL;
		}

		block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);

		(*offset) ++;

		if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
			*offset = 0;
		else
			*extoffset = lextoffset;

		udf_release_data(fibh->sbh);
		if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
			return NULL;
		fibh->soffset = fibh->eoffset = 0;
	}
	else if (fibh->sbh != fibh->ebh)
	{
		udf_release_data(fibh->sbh);
		fibh->sbh = fibh->ebh;
	}

	fi = udf_get_fileident(fibh->sbh->b_data, dir->i_sb->s_blocksize,
		&(fibh->eoffset));

	if (!fi)
		return NULL;

	*nf_pos += ((fibh->eoffset - fibh->soffset) >> 2);

	if (fibh->eoffset <= dir->i_sb->s_blocksize)
	{
		memcpy((Uint8 *)cfi, (Uint8 *)fi, sizeof(struct FileIdentDesc));
	}
	else if (fibh->eoffset > dir->i_sb->s_blocksize)
	{
		int lextoffset = *extoffset;

		if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
			EXTENT_RECORDED_ALLOCATED)
		{
			return NULL;
		}

		block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);

		(*offset) ++;

		if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
			*offset = 0;
		else
			*extoffset = lextoffset;

		fibh->soffset -= dir->i_sb->s_blocksize;
		fibh->eoffset -= dir->i_sb->s_blocksize;

		if (!(fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
			return NULL;

		if (sizeof(struct FileIdentDesc) > - fibh->soffset)
		{
			int fi_len;

			memcpy((Uint8 *)cfi, (Uint8 *)fi, - fibh->soffset);
			memcpy((Uint8 *)cfi - fibh->soffset, fibh->ebh->b_data,
				sizeof(struct FileIdentDesc) + fibh->soffset);

			fi_len = (sizeof(struct FileIdentDesc) + cfi->lengthFileIdent +
				le16_to_cpu(cfi->lengthOfImpUse) + 3) & ~3;

			*nf_pos += ((fi_len - (fibh->eoffset - fibh->soffset)) >> 2);
			fibh->eoffset = fibh->soffset + fi_len;
		}