FreeBSD/sys/fs/udf/udf_vnops.c
/*
 * Translate a file offset into a logical block and then into a physical
 * block.
 * max_size - maximum number of bytes that can be read starting from given
 * offset, rather than beginning of calculated sector number
 */
Translate a file offset into a logical block and then into a physical
block.
max_size - maximum number of bytes that can be read starting from given
offset, rather than beginning of calculated sector number
Translate a file offset into a logical block and then into a physical block . max_size - maximum number of bytes that can be read starting from given offset rather than beginning of calculated sector number
static int
udf_bmap_internal(struct udf_node *node, off_t offset, daddr_t *sector,
    uint32_t *max_size)
{
	struct udf_mnt *udfmp;
	struct file_entry *fentry;
	void *icb;
	struct icb_tag *tag;
	uint32_t icblen = 0;
	daddr_t lsector;
	int ad_offset, ad_num = 0;
	int i, p_offset;
	udfmp = node->udfmp;
	fentry = node->fentry;
	tag = &fentry->icbtag;
	switch (le16toh(tag->strat_type)) {
	case 4:
		break;
	case 4096:
		printf("Cannot deal with strategy4096 yet!\n");
		return (ENODEV);
	default:
		printf("Unknown strategy type %d\n", tag->strat_type);
		return (ENODEV);
	}
	switch (le16toh(tag->flags) & 0x7) {
	case 0:
		do {
			offset -= icblen;
			ad_offset = sizeof(struct short_ad) * ad_num;
			if (ad_offset > le32toh(fentry->l_ad)) {
				printf("File offset out of bounds\n");
				return (EINVAL);
			}
			icb = GETICB(short_ad, fentry,
			    le32toh(fentry->l_ea) + ad_offset);
			icblen = GETICBLEN(short_ad, icb);
			ad_num++;
		} while(offset >= icblen);
		lsector = (offset  >> udfmp->bshift) +
		    le32toh(((struct short_ad *)(icb))->pos);
		*max_size = icblen - offset;
		break;
	case 1:
		do {
			offset -= icblen;
			ad_offset = sizeof(struct long_ad) * ad_num;
			if (ad_offset > le32toh(fentry->l_ad)) {
				printf("File offset out of bounds\n");
				return (EINVAL);
			}
			icb = GETICB(long_ad, fentry,
			    le32toh(fentry->l_ea) + ad_offset);
			icblen = GETICBLEN(long_ad, icb);
			ad_num++;
		} while(offset >= icblen);
		lsector = (offset >> udfmp->bshift) +
		    le32toh(((struct long_ad *)(icb))->loc.lb_num);
		*max_size = icblen - offset;
		break;
	case 3:
		*max_size = 0;
		*sector = node->hash_id + udfmp->part_start;
		return (UDF_INVALID_BMAP);
	case 2:
	default:
		printf("Unsupported allocation descriptor %d\n",
		       tag->flags & 0x7);
		return (ENODEV);
	}
	*sector = lsector + udfmp->part_start;
	if (udfmp->s_table != NULL) {
		for (i = 0; i< udfmp->s_table_entries; i++) {
			p_offset =
			    lsector - le32toh(udfmp->s_table->entries[i].org);
			if ((p_offset < udfmp->p_sectors) && (p_offset >= 0)) {
				*sector =
				   le32toh(udfmp->s_table->entries[i].map) +
				    p_offset;
				break;
			}
		}
	}
	return (0);
}
static int udf_bmap_internal ( struct udf_node * node , off_t offset , daddr_t * sector , uint32_t * max_size ) { struct udf_mnt * udfmp ; struct file_entry * fentry ; void * icb ; struct icb_tag * tag ; uint32_t icblen = 0 ; daddr_t lsector ; int ad_offset , ad_num = 0 ; int i , p_offset ; udfmp = node -> udfmp ; fentry = node -> fentry ; tag = & fentry -> icbtag ; switch ( le16toh ( tag -> strat_type ) ) { case 4 : break ; case 4096 : printf ( " \n " ) ; return ( ENODEV ) ; default : printf ( " \n " , tag -> strat_type ) ; return ( ENODEV ) ; } switch ( le16toh ( tag -> flags ) & 0x7 ) { case 0 : do { offset -= icblen ; ad_offset = sizeof ( struct short_ad ) * ad_num ; if ( ad_offset > le32toh ( fentry -> l_ad ) ) { printf ( " \n " ) ; return ( EINVAL ) ; } icb = GETICB ( short_ad , fentry , le32toh ( fentry -> l_ea ) + ad_offset ) ; icblen = GETICBLEN ( short_ad , icb ) ; ad_num ++ ; } while ( offset >= icblen ) ; lsector = ( offset >> udfmp -> bshift ) + le32toh ( ( ( struct short_ad * ) ( icb ) ) -> pos ) ; * max_size = icblen - offset ; break ; case 1 : do { offset -= icblen ; ad_offset = sizeof ( struct long_ad ) * ad_num ; if ( ad_offset > le32toh ( fentry -> l_ad ) ) { printf ( " \n " ) ; return ( EINVAL ) ; } icb = GETICB ( long_ad , fentry , le32toh ( fentry -> l_ea ) + ad_offset ) ; icblen = GETICBLEN ( long_ad , icb ) ; ad_num ++ ; } while ( offset >= icblen ) ; lsector = ( offset >> udfmp -> bshift ) + le32toh ( ( ( struct long_ad * ) ( icb ) ) -> loc . lb_num ) ; * max_size = icblen - offset ; break ; case 3 : * max_size = 0 ; * sector = node -> hash_id + udfmp -> part_start ; return ( UDF_INVALID_BMAP ) ; case 2 : default : printf ( " \n " , tag -> flags & 0x7 ) ; return ( ENODEV ) ; } * sector = lsector + udfmp -> part_start ; if ( udfmp -> s_table != NULL ) { for ( i = 0 ; i < udfmp -> s_table_entries ; i ++ ) { p_offset = lsector - le32toh ( udfmp -> s_table -> entries [ i ] . org ) ; if ( ( p_offset < udfmp -> p_sectors ) && ( p_offset >= 0 ) ) { * sector = le32toh ( udfmp -> s_table -> entries [ i ] . map ) + p_offset ; break ; } } } return ( 0 ) ; }
Translate a file offset into a logical block and then into a physical
 block.
Translate a file offset into a logical block and then into a physical block .
/*
		 * The allocation descriptor field is filled with short_ad's.
		 * If the offset is beyond the current extent, look for the
		 * next extent.
		 */ /*
		 * The allocation descriptor field is filled with long_ad's
		 * If the offset is beyond the current extent, look for the
		 * next extent.
		 */ /*
		 * This type means that the file *data* is stored in the
		 * allocation descriptor field of the file entry.
		 */ /* DirectCD does not use extended_ad's */ /*
	 * Check the sparing table.  Each entry represents the beginning of
	 * a packet.
	 */