Beispiel #1
0
Uint8 * udf_filead_read(struct inode *dir, Uint8 *tmpad, Uint8 ad_size,
	lb_addr fe_loc, int *pos, int *offset, struct buffer_head **bh, int *error)
{
	int loffset = *offset;
	int block;
	Uint8 *ad;
	int remainder;

	*error = 0;

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

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

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

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

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

		memcpy((Uint8 *)ad + remainder, (*bh)->b_data, ad_size - remainder);
		*offset = ad_size - remainder;
	}
	return ad;
}
Beispiel #2
0
uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block, uint16_t partition, uint32_t offset)
{
	struct buffer_head *bh = NULL;
	uint32_t newblock;
	uint32_t index;
	uint32_t loc;

	index = (sb->s_blocksize - UDF_SB_TYPEVIRT(sb,partition).s_start_offset) / sizeof(uint32_t);

	if (block > UDF_SB_TYPEVIRT(sb,partition).s_num_entries)
	{
		udf_debug("Trying to access block beyond end of VAT (%d max %d)\n",
			block, UDF_SB_TYPEVIRT(sb,partition).s_num_entries);
		return 0xFFFFFFFF;
	}

	if (block >= index)
	{
		block -= index;
		newblock = 1 + (block / (sb->s_blocksize / sizeof(uint32_t)));
		index = block % (sb->s_blocksize / sizeof(uint32_t));
	}
	else
	{
		newblock = 0;
		index = UDF_SB_TYPEVIRT(sb,partition).s_start_offset / sizeof(uint32_t) + block;
	}

	loc = udf_block_map(UDF_SB_VAT(sb), newblock, NULL);

	if (!(bh = sb_bread(sb, loc)))
	{
		udf_debug("get_pblock(UDF_VIRTUAL_MAP:%p,%d,%d) VAT: %d[%d]\n",
			sb, block, partition, loc, index);
		return 0xFFFFFFFF;
	}

	loc = le32_to_cpu(((__le32 *)bh->b_data)[index]);

	udf_release_data(bh);

	if (UDF_I_LOCATION(UDF_SB_VAT(sb)).partitionReferenceNum == partition)
	{
		udf_debug("recursive call to udf_get_pblock!\n");
		return 0xFFFFFFFF;
	}

	return udf_get_pblock(sb, loc, UDF_I_LOCATION(UDF_SB_VAT(sb)).partitionReferenceNum, offset);
}
Beispiel #3
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;
}
Beispiel #4
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);
 							}
 						}
 					}
 				}
 			}
Beispiel #5
0
static int 
udf_find_fileset(struct super_block *sb, lb_addr *fileset, lb_addr *root)
{
	struct buffer_head *bh = NULL;
	long lastblock;
	Uint16 ident;

	if (fileset->logicalBlockNum != 0xFFFFFFFF ||
		fileset->partitionReferenceNum != 0xFFFF)
	{
		bh = udf_read_ptagged(sb, *fileset, 0, &ident);

		if (!bh)
			return 1;
		else if (ident != TID_FILE_SET_DESC)
		{
			udf_release_data(bh);
			return 1;
		}
			
	}

	if (!bh) /* Search backwards through the partitions */
	{
		lb_addr newfileset;

		return 1;
		
		for (newfileset.partitionReferenceNum=UDF_SB_NUMPARTS(sb)-1;
			(newfileset.partitionReferenceNum != 0xFFFF &&
				fileset->logicalBlockNum == 0xFFFFFFFF &&
				fileset->partitionReferenceNum == 0xFFFF);
			newfileset.partitionReferenceNum--)
		{
			lastblock = UDF_SB_PARTLEN(sb, newfileset.partitionReferenceNum);
			newfileset.logicalBlockNum = 0;

			do
			{
				bh = udf_read_ptagged(sb, newfileset, 0, &ident);
				if (!bh)
				{
					newfileset.logicalBlockNum ++;
					continue;
				}

				switch (ident)
				{
					case TID_SPACE_BITMAP_DESC:
					{
						struct SpaceBitmapDesc *sp;
						sp = (struct SpaceBitmapDesc *)bh->b_data;
						newfileset.logicalBlockNum += 1 +
							((le32_to_cpu(sp->numOfBytes) + sizeof(struct SpaceBitmapDesc) - 1)
								>> sb->s_blocksize_bits);
						udf_release_data(bh);
						break;
					}
					case TID_FILE_SET_DESC:
					{
						*fileset = newfileset;
						break;
					}
					default:
					{
						newfileset.logicalBlockNum ++;
						udf_release_data(bh);
						bh = NULL;
						break;
					}
				}
			}
			while (newfileset.logicalBlockNum < lastblock &&
				fileset->logicalBlockNum == 0xFFFFFFFF &&
				fileset->partitionReferenceNum == 0xFFFF);
		}
	}
Beispiel #6
0
/*
 * udf_find_anchor
 *
 * PURPOSE
 *	Find an anchor volume descriptor.
 *
 * PRE-CONDITIONS
 *	sb			Pointer to _locked_ superblock.
 *	lastblock		Last block on media.
 *
 * POST-CONDITIONS
 *	<return>		1 if not found, 0 if ok
 *
 * HISTORY
 *	July 1, 1997 - Andrew E. Mileski
 *	Written, tested, and released.
 */
static void
udf_find_anchor(struct super_block *sb)
{
	int lastblock = UDF_SB_LASTBLOCK(sb);
	struct buffer_head *bh = NULL;
	Uint16 ident;
	Uint32 location;
	int i;

	if (lastblock)
	{
		int varlastblock = udf_variable_to_fixed(lastblock);
		int last[] =  { lastblock, lastblock - 2,
				lastblock - 150, lastblock - 152,
				varlastblock, varlastblock - 2,
				varlastblock - 150, varlastblock - 152 };

		lastblock = 0;

		/* Search for an anchor volume descriptor pointer */

		/*  according to spec, anchor is in either:
		 *     block 256
		 *     lastblock-256
		 *     lastblock
		 *  however, if the disc isn't closed, it could be 512 */

		for (i=0; (!lastblock && i<sizeof(last)/sizeof(int)); i++)
		{
			if (last[i] < 0 || !(bh = sb_bread(sb, last[i])))
			{
				ident = location = 0;
			}
			else
			{
				ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent);
				location = le32_to_cpu(((tag *)bh->b_data)->tagLocation);
				udf_release_data(bh);
			}
	
			if (ident == TID_ANCHOR_VOL_DESC_PTR)
			{
				if (location == last[i] - UDF_SB_SESSION(sb))
				{
					lastblock = UDF_SB_ANCHOR(sb)[0] = last[i];
					UDF_SB_ANCHOR(sb)[1] = last[i] - 256;
				}
				else if (location == udf_variable_to_fixed(last[i]) - UDF_SB_SESSION(sb))
				{
					UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
					lastblock = UDF_SB_ANCHOR(sb)[0] = udf_variable_to_fixed(last[i]);
					UDF_SB_ANCHOR(sb)[1] = lastblock - 256;
				}
				else
					udf_debug("Anchor found at block %d, location mismatch %d.\n",
						last[i], location);
			}
			else if (ident == TID_FILE_ENTRY || ident == TID_EXTENDED_FILE_ENTRY)
			{
				lastblock = last[i];
				UDF_SB_ANCHOR(sb)[3] = 512 + UDF_SB_SESSION(sb);
			}
			else
			{
				if (last[i] < 256 || !(bh = sb_bread(sb, last[i] - 256)))
				{
					ident = location = 0;
				}
				else
				{
					ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent);
					location = le32_to_cpu(((tag *)bh->b_data)->tagLocation);
					udf_release_data(bh);
				}
	
				if (ident == TID_ANCHOR_VOL_DESC_PTR &&
					location == last[i] - 256 - UDF_SB_SESSION(sb))
				{
					lastblock = last[i];
					UDF_SB_ANCHOR(sb)[1] = last[i] - 256;
				}
				else
				{
					if (last[i] < 312 + UDF_SB_SESSION(sb) || !(bh = sb_bread(sb, last[i] - 312 - UDF_SB_SESSION(sb))))
					{
						ident = location = 0;
					}
					else
					{
						ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent);
						location = le32_to_cpu(((tag *)bh->b_data)->tagLocation);
						udf_release_data(bh);
					}
	
					if (ident == TID_ANCHOR_VOL_DESC_PTR &&
						location == udf_variable_to_fixed(last[i]) - 256)
					{
						UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
						lastblock = udf_variable_to_fixed(last[i]);
						UDF_SB_ANCHOR(sb)[1] = lastblock - 256;
					}
				}
			}
		}
	}

	if (!lastblock)
	{
		/* We havn't found the lastblock. check 312 */
		if ((bh = sb_bread(sb, 312 + UDF_SB_SESSION(sb))))
		{
			ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent);
			location = le32_to_cpu(((tag *)bh->b_data)->tagLocation);
			udf_release_data(bh);

			if (ident == TID_ANCHOR_VOL_DESC_PTR && location == 256)
				UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
		}
	}

	for (i=0; i<sizeof(UDF_SB_ANCHOR(sb))/sizeof(int); i++)
	{
		if (UDF_SB_ANCHOR(sb)[i])
		{
			if (!(bh = udf_read_tagged(sb,
				UDF_SB_ANCHOR(sb)[i], UDF_SB_ANCHOR(sb)[i], &ident)))
			{
				UDF_SB_ANCHOR(sb)[i] = 0;
			}
			else
			{
				udf_release_data(bh);
				if ((ident != TID_ANCHOR_VOL_DESC_PTR) && (i ||
					(ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY)))
				{
					UDF_SB_ANCHOR(sb)[i] = 0;
				}
			}
		}
	}

	UDF_SB_LASTBLOCK(sb) = lastblock;
}
Beispiel #7
0
static int
udf_vrs(struct super_block *sb, int silent)
{
	struct VolStructDesc *vsd = NULL;
	int sector = 32768;
	int sectorsize;
	struct buffer_head *bh = NULL;
	int iso9660=0;
	int nsr02=0;
	int nsr03=0;

	/* Block size must be a multiple of 512 */
	if (sb->s_blocksize & 511)
		return 0;

	if (sb->s_blocksize < sizeof(struct VolStructDesc))
		sectorsize = sizeof(struct VolStructDesc);
	else
		sectorsize = sb->s_blocksize;

	sector += (UDF_SB_SESSION(sb) << sb->s_blocksize_bits);

	udf_debug("Starting at sector %u (%ld byte sectors)\n",
		(sector >> sb->s_blocksize_bits), sb->s_blocksize);
	/* Process the sequence (if applicable) */
	for (;!nsr02 && !nsr03; sector += sectorsize)
	{
		/* Read a block */
		bh = udf_tread(sb, sector >> sb->s_blocksize_bits);
		if (!bh)
			break;

		/* Look for ISO  descriptors */
		vsd = (struct VolStructDesc *)(bh->b_data +
			(sector & (sb->s_blocksize - 1)));

		if (vsd->stdIdent[0] == 0)
		{
			udf_release_data(bh);
			break;
		}
		else if (!strncmp(vsd->stdIdent, STD_ID_CD001, STD_ID_LEN))
		{
			iso9660 = sector;
			switch (vsd->structType)
			{
				case 0: 
					udf_debug("ISO9660 Boot Record found\n");
					break;
				case 1: 
					udf_debug("ISO9660 Primary Volume Descriptor found\n");
					break;
				case 2: 
					udf_debug("ISO9660 Supplementary Volume Descriptor found\n");
					break;
				case 3: 
					udf_debug("ISO9660 Volume Partition Descriptor found\n");
					break;
				case 255: 
					udf_debug("ISO9660 Volume Descriptor Set Terminator found\n");
					break;
				default: 
					udf_debug("ISO9660 VRS (%u) found\n", vsd->structType);
					break;
			}
		}
		else if (!strncmp(vsd->stdIdent, STD_ID_BEA01, STD_ID_LEN))
		{
		}
		else if (!strncmp(vsd->stdIdent, STD_ID_TEA01, STD_ID_LEN))
		{
			udf_release_data(bh);
			break;
		}
		else if (!strncmp(vsd->stdIdent, STD_ID_NSR02, STD_ID_LEN))
		{
			nsr02 = sector;
		}
		else if (!strncmp(vsd->stdIdent, STD_ID_NSR03, STD_ID_LEN))
		{
			nsr03 = sector;
		}
		udf_release_data(bh);
	}

	if (nsr03)
		return nsr03;
	else if (nsr02)
		return nsr02;
	else if (sector - (UDF_SB_SESSION(sb) << sb->s_blocksize_bits) == 32768)
		return -1;
	else
		return 0;
}
Beispiel #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;
		}