Exemplo n.º 1
0
/* Look up a sector in the VAT */
int
udf_vat_map(struct umount *ump, uint32_t *sector)
{
	/* If there's no VAT, then it's easy */
	if (!(ump->um_flags & UDF_MNT_USES_VAT)) {
		*sector += ump->um_start;
		return (0);
	}

	/* Sanity check the given sector */
	if (*sector >= ump->um_vat->u_vatlen)
		return (EINVAL);

	return (udf_vat_read(ump, sector));
}
Exemplo n.º 2
0
int
udf_translate_vtop(struct udf_mount *ump, struct long_ad *icb_loc,
		   uint32_t *lb_numres, uint32_t *extres)
{
	struct part_desc *pdesc;
	struct spare_map_entry *sme;
	struct long_ad s_icb_loc;
	uint64_t end_foffset, foffset;
	int eof, error, flags, part, rel, slot;
	uint32_t lb_num, lb_packet, lb_rel, lb_size, len;
	uint32_t ext_offset, udf_rw32_lbmap;
	uint16_t vpart;

	KASSERT(ump && icb_loc && lb_numres,("ump && icb_loc && lb_numres"));

	vpart = le16toh(icb_loc->loc.part_num);
	lb_num = le32toh(icb_loc->loc.lb_num);
	if (vpart > UDF_VTOP_RAWPART)
		return (EINVAL);

translate_again:
	part = ump->vtop[vpart];
	pdesc = ump->partitions[part];

	switch (ump->vtop_tp[vpart]) {
	case UDF_VTOP_TYPE_RAW:
		/* 1:1 to the end of the device */
		*lb_numres = lb_num;
		*extres = INT_MAX;
		return (0);
	case UDF_VTOP_TYPE_PHYS:
		/* transform into its disc logical block */
		if (lb_num > le32toh(pdesc->part_len))
			return (EINVAL);
		*lb_numres = lb_num + le32toh(pdesc->start_loc);

		/* extent from here to the end of the partition */
		*extres = le32toh(pdesc->part_len) - lb_num;
		return (0);
	case UDF_VTOP_TYPE_VIRT:
		/* only maps one logical block, lookup in VAT */
		if (lb_num >= ump->vat_entries)		/* XXX > or >= ? */
			return (EINVAL);

		/* lookup in virtual allocation table file */
		error = udf_vat_read(ump, (uint8_t *)&udf_rw32_lbmap, 4, 
		    ump->vat_offset + lb_num * 4);
		if (error != 0)
			return (error);

		lb_num = le32toh(udf_rw32_lbmap);

		/* transform into its disc logical block */
		if (lb_num > le32toh(pdesc->part_len))
			return (EINVAL);
		*lb_numres = lb_num + le32toh(pdesc->start_loc);

		/* just one logical block */
		*extres = 1;
		return (0);
	case UDF_VTOP_TYPE_SPARABLE:
		/* check if the packet containing the lb_num is remapped */
		lb_packet = lb_num / ump->sparable_packet_size;
		lb_rel = lb_num % ump->sparable_packet_size;

		for (rel = 0; rel < le16toh(ump->sparing_table->rt_l); rel++) {
			sme = &ump->sparing_table->entries[rel];
			if (lb_packet == le32toh(sme->org)) {
				/* NOTE maps to absolute disc logical block! */
				*lb_numres = le32toh(sme->map) + lb_rel;
				*extres = ump->sparable_packet_size - lb_rel;
				return (0);
			}
		}

		/* transform into its disc logical block */
		if (lb_num > le32toh(pdesc->part_len))
			return (EINVAL);
		*lb_numres = lb_num + le32toh(pdesc->start_loc);

		/* rest of block */
		*extres = ump->sparable_packet_size - lb_rel;
		return (0);
	case UDF_VTOP_TYPE_META:
		/* we have to look into the file's allocation descriptors */

		/* use metadatafile allocation mutex */
		lb_size = le32toh(ump->logical_vol->lb_size);

		UDF_LOCK_NODE(ump->metadata_node, 0);

		/* get first overlapping extent */
		foffset = 0;
		slot = 0;
		for (;;) {
			udf_get_adslot(ump->metadata_node, slot, &s_icb_loc,
			    &eof);
			if (eof) {
				UDF_UNLOCK_NODE(ump->metadata_node, 0);
				return (EINVAL);
			}
			len = le32toh(s_icb_loc.len);
			flags = UDF_EXT_FLAGS(len);
			len = UDF_EXT_LEN(len);

			if (flags == UDF_EXT_REDIRECT) {
				slot++;
				continue;
			}

			end_foffset = foffset + len;

			if (end_foffset > lb_num * lb_size)
				break;	/* found */
			foffset = end_foffset;
			slot++;
		}
		/* found overlapping slot */
		ext_offset = lb_num * lb_size - foffset;

		/* process extent offset */
		lb_num = le32toh(s_icb_loc.loc.lb_num);
		vpart = le16toh(s_icb_loc.loc.part_num);
		lb_num  += (ext_offset + lb_size -1) / lb_size;
		ext_offset = 0;

		UDF_UNLOCK_NODE(ump->metadata_node, 0);
		if (flags != UDF_EXT_ALLOCATED)
			return (EINVAL);

		/*
		 * vpart and lb_num are updated, translate again since we
		 * might be mapped on sparable media
		 */
		goto translate_again;
	default:
		printf("UDF vtop translation scheme %d unimplemented yet\n",
		    ump->vtop_tp[vpart]);
	}

	return (EINVAL);
}