struct buffer_head *udf_read_ptagged(struct super_block *sb,
				     struct kernel_lb_addr *loc,
				     uint32_t offset, uint16_t *ident)
{
	return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset),
			       loc->logicalBlockNum + offset, ident);
}
Exemple #2
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);
 							}
 						}
 					}
 				}
 			}
Exemple #3
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;
}