summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2009-08-14 22:23:46 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2009-08-14 22:23:46 +0000
commit4f8bb894710e6a2cc1f46b6a005873875815e6e7 (patch)
treedae566b4d01676a1702f3c3ef9af734343c15e17 /sys
parent9baabc7a1abe127297baad825172a45c4d172b78 (diff)
First cut at UDF 2.[56] support, allowing read-only access to HDDVD
and Blu-ray disks. Previously working DVDs should still work. Done at f2k9 with phessler@. Vnode bug squashing by beck@. Thanks to Bryan Brake for sending HDDVD/Blu-ray hardware and disks to f2k9 in Stockholm. ok beck@ dlg@ phessler@
Diffstat (limited to 'sys')
-rw-r--r--sys/isofs/udf/udf.h9
-rw-r--r--sys/isofs/udf/udf_vfsops.c137
-rw-r--r--sys/isofs/udf/udf_vnops.c123
3 files changed, 213 insertions, 56 deletions
diff --git a/sys/isofs/udf/udf.h b/sys/isofs/udf/udf.h
index 1d8ecb758c1..bd049a50d3e 100644
--- a/sys/isofs/udf/udf.h
+++ b/sys/isofs/udf/udf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: udf.h,v 1.12 2007/12/09 20:54:01 jmc Exp $ */
+/* $OpenBSD: udf.h,v 1.13 2009/08/14 22:23:45 krw Exp $ */
/*
* Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org>
@@ -46,7 +46,7 @@ struct unode {
long u_diroff;
long u_vatlen;
} un_u;
- struct file_entry *u_fentry;
+ struct extfile_entry *u_fentry;
};
#define u_diroff un_u.u_diroff
@@ -61,7 +61,11 @@ struct umount {
int um_bshift;
int um_bmask;
uint32_t um_start;
+ uint32_t um_realstart;
uint32_t um_len;
+ uint32_t um_reallen;
+ uint32_t um_meta_start;
+ uint32_t um_meta_len;
struct unode *um_vat;
struct long_ad um_root_icb;
LIST_HEAD(udf_hash_lh, unode) *um_hashtbl;
@@ -74,6 +78,7 @@ struct umount {
#define UDF_MNT_FIND_VAT 0x01 /* Indicates a VAT must be found */
#define UDF_MNT_USES_VAT 0x02 /* Indicates a VAT must be used */
+#define UDF_MNT_USES_META 0x04 /* Indicates we are using a Metadata partition*/
struct udf_dirstream {
struct unode *node;
diff --git a/sys/isofs/udf/udf_vfsops.c b/sys/isofs/udf/udf_vfsops.c
index 85bf2556eb2..4a1ac754931 100644
--- a/sys/isofs/udf/udf_vfsops.c
+++ b/sys/isofs/udf/udf_vfsops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udf_vfsops.c,v 1.29 2009/07/09 22:29:56 thib Exp $ */
+/* $OpenBSD: udf_vfsops.c,v 1.30 2009/08/14 22:23:45 krw Exp $ */
/*
* Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org>
@@ -79,6 +79,7 @@ struct pool udf_ds_pool;
int udf_find_partmaps(struct umount *, struct logvol_desc *);
int udf_get_vpartmap(struct umount *, struct part_map_virt *);
int udf_get_spartmap(struct umount *, struct part_map_spare *);
+int udf_get_mpartmap(struct umount *, struct part_map_meta *);
int udf_mountfs(struct vnode *, struct mount *, uint32_t, struct proc *);
const struct vfsops udf_vfsops = {
@@ -220,7 +221,8 @@ udf_mountfs(struct vnode *devvp, struct mount *mp, uint32_t lb, struct proc *p)
struct part_desc *pd;
struct logvol_desc *lvd;
struct fileset_desc *fsd;
- struct file_entry *root_fentry;
+ struct extfile_entry *xfentry;
+ struct file_entry *fentry;
uint32_t sector, size, mvds_start, mvds_end;
uint32_t fsd_offset = 0;
uint16_t part_num = 0, fsd_part = 0;
@@ -305,8 +307,8 @@ udf_mountfs(struct vnode *devvp, struct mount *mp, uint32_t lb, struct proc *p)
if (!udf_checktag(&pd->tag, TAGID_PARTITION)) {
part_found = 1;
part_num = letoh16(pd->part_num);
- ump->um_len = letoh32(pd->part_len);
- ump->um_start = letoh32(pd->start_loc);
+ ump->um_len = ump->um_reallen = letoh32(pd->part_len);
+ ump->um_start = ump->um_realstart = letoh32(pd->start_loc);
}
brelse(bp);
@@ -320,7 +322,34 @@ udf_mountfs(struct vnode *devvp, struct mount *mp, uint32_t lb, struct proc *p)
goto bail;
}
- if (fsd_part != part_num) {
+ if (ISSET(ump->um_flags, UDF_MNT_USES_META)) {
+ /* Read Metadata File 'File Entry' to find Metadata file. */
+ struct long_ad *la;
+ sector = ump->um_start + ump->um_meta_start; /* Set in udf_get_mpartmap() */
+ if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) {
+ printf("Cannot read sector %d for Metadata File Entry\n", sector);
+ error = EINVAL;
+ goto bail;
+ }
+ xfentry = (struct extfile_entry *)bp->b_data;
+ fentry = (struct file_entry *)bp->b_data;
+ if (udf_checktag(&xfentry->tag, TAGID_EXTFENTRY) == 0)
+ la = (struct long_ad *)&xfentry->data[letoh32(xfentry->l_ea)];
+ else if (udf_checktag(&fentry->tag, TAGID_FENTRY) == 0)
+ la = (struct long_ad *)&fentry->data[letoh32(fentry->l_ea)];
+ else {
+ printf("Invalid Metadata File FE @ sector %d! (tag.id %d)\n",
+ sector, fentry->tag.id);
+ error = EINVAL;
+ goto bail;
+ }
+ ump->um_meta_start = letoh32(la->loc.lb_num);
+ ump->um_meta_len = letoh32(la->len);
+ if (bp != NULL) {
+ brelse(bp);
+ bp = NULL;
+ }
+ } else if (fsd_part != part_num) {
printf("FSD does not lie within the partition!\n");
error = EINVAL;
goto bail;
@@ -342,7 +371,11 @@ udf_mountfs(struct vnode *devvp, struct mount *mp, uint32_t lb, struct proc *p)
* Thanks to Chuck McCrobie <mccrobie@cablespeed.com> for pointing
* me in the right direction here.
*/
- sector = fsd_offset;
+
+ if (ISSET(ump->um_flags, UDF_MNT_USES_META))
+ sector = ump->um_meta_start;
+ else
+ sector = fsd_offset;
udf_vat_map(ump, &sector);
if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) {
printf("Cannot read sector %d of FSD\n", sector);
@@ -353,6 +386,10 @@ udf_mountfs(struct vnode *devvp, struct mount *mp, uint32_t lb, struct proc *p)
fsd_found = 1;
bcopy(&fsd->rootdir_icb, &ump->um_root_icb,
sizeof(struct long_ad));
+ if (ISSET(ump->um_flags, UDF_MNT_USES_META)) {
+ ump->um_root_icb.loc.lb_num += ump->um_meta_start;
+ ump->um_root_icb.loc.part_num = part_num;
+ }
}
brelse(bp);
@@ -375,10 +412,15 @@ udf_mountfs(struct vnode *devvp, struct mount *mp, uint32_t lb, struct proc *p)
goto bail;
}
- root_fentry = (struct file_entry *)bp->b_data;
- if ((error = udf_checktag(&root_fentry->tag, TAGID_FENTRY))) {
- printf("Invalid root file entry!\n");
- goto bail;
+ xfentry = (struct extfile_entry *)bp->b_data;
+ fentry = (struct file_entry *)bp->b_data;
+ error = udf_checktag(&xfentry->tag, TAGID_EXTFENTRY);
+ if (error) {
+ error = udf_checktag(&fentry->tag, TAGID_FENTRY);
+ if (error) {
+ printf("Invalid root file entry!\n");
+ goto bail;
+ }
}
brelse(bp);
@@ -507,8 +549,9 @@ udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
struct vnode *devvp;
struct umount *ump;
struct proc *p;
- struct vnode *vp;
+ struct vnode *vp, *nvp;
struct unode *up;
+ struct extfile_entry *xfe;
struct file_entry *fe;
int error, sector, size;
@@ -543,24 +586,36 @@ udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
return (error);
}
+ xfe = (struct extfile_entry *)bp->b_data;
fe = (struct file_entry *)bp->b_data;
- if (udf_checktag(&fe->tag, TAGID_FENTRY)) {
- printf("Invalid file entry!\n");
- pool_put(&unode_pool, up);
- brelse(bp);
- return (ENOMEM);
+ error = udf_checktag(&xfe->tag, TAGID_EXTFENTRY);
+ if (error == 0) {
+ size = letoh32(xfe->l_ea) + letoh32(xfe->l_ad);
+ } else {
+ error = udf_checktag(&fe->tag, TAGID_FENTRY);
+ if (error) {
+ printf("Invalid file entry!\n");
+ pool_put(&unode_pool, up);
+ if (bp != NULL)
+ brelse(bp);
+ return (ENOMEM);
+ } else
+ size = letoh32(fe->l_ea) + letoh32(fe->l_ad);
}
- size = UDF_FENTRY_SIZE + letoh32(fe->l_ea) + letoh32(fe->l_ad);
-
- up->u_fentry = malloc(size, M_UDFFENTRY, M_NOWAIT);
+ /* Allocate max size of FE/XFE. */
+ up->u_fentry = malloc(size + UDF_EXTFENTRY_SIZE, M_UDFFENTRY, M_NOWAIT | M_ZERO);
if (up->u_fentry == NULL) {
pool_put(&unode_pool, up);
- brelse(bp);
+ if (bp != NULL)
+ brelse(bp);
return (ENOMEM); /* Cannot allocate file entry block */
}
- bcopy(bp->b_data, up->u_fentry, size);
+ if (udf_checktag(&xfe->tag, TAGID_EXTFENTRY) == 0)
+ bcopy(bp->b_data, up->u_fentry, size + UDF_EXTFENTRY_SIZE);
+ else
+ bcopy(bp->b_data, up->u_fentry, size + UDF_FENTRY_SIZE);
brelse(bp);
bp = NULL;
@@ -588,14 +643,12 @@ udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
switch (up->u_fentry->icbtag.file_type) {
default:
- vp->v_type = VBAD;
+ printf("Unrecognized file type (%d)\n", vp->v_type);
+ vp->v_type = VREG;
break;
case UDF_ICB_FILETYPE_DIRECTORY:
vp->v_type = VDIR;
break;
- case UDF_ICB_FILETYPE_RANDOMACCESS:
- vp->v_type = VREG;
- break;
case UDF_ICB_FILETYPE_BLOCKDEVICE:
vp->v_type = VBLK;
break;
@@ -611,11 +664,32 @@ udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
case UDF_ICB_FILETYPE_SYMLINK:
vp->v_type = VLNK;
break;
+ case UDF_ICB_FILETYPE_RANDOMACCESS:
+ case UDF_ICB_FILETYPE_REALTIME:
case UDF_ICB_FILETYPE_UNKNOWN:
vp->v_type = VREG;
break;
}
+ /* check if this is a vnode alias */
+ if ((nvp = checkalias(vp, up->u_dev, ump->um_mountp)) != NULL) {
+ printf("found a vnode alias\n");
+ /*
+ * Discard unneeded vnode, but save its udf_node.
+ * Note that the lock is carried over in the udf_node
+ */
+ nvp->v_data = vp->v_data;
+ vp->v_data = NULL;
+ vp->v_op = spec_vnodeop_p;
+ vrele(vp);
+ vgone(vp);
+ /*
+ * Reinitialize aliased inode.
+ */
+ vp = nvp;
+ ump->um_devvp = vp;
+ }
+
*vpp = vp;
return (0);
@@ -711,6 +785,7 @@ udf_get_spartmap(struct umount *ump, struct part_map_spare *pms)
bcopy(bp->b_data, ump->um_stbl, letoh32(pms->st_size));
brelse(bp);
+ bp = NULL;
if (udf_checktag(&ump->um_stbl->tag, 0)) {
free(ump->um_stbl, M_UDFMOUNT);
@@ -730,6 +805,14 @@ udf_get_spartmap(struct umount *ump, struct part_map_spare *pms)
return (0);
}
+/* Handle a metadata partition map */
+int
+udf_get_mpartmap(struct umount *ump, struct part_map_meta *pmm)
+{
+ ump->um_flags |= UDF_MNT_USES_META;
+ ump->um_meta_start = pmm->meta_file_lbn;
+ return (0);
+}
/* Scan the partition maps */
int
@@ -769,6 +852,10 @@ udf_find_partmaps(struct umount *ump, struct logvol_desc *lvd)
UDF_REGID_ID_SIZE))
error = udf_get_spartmap(ump,
(struct part_map_spare *) pmap);
+ else if (!bcmp(&regid_id[0], "*UDF Metadata Partition",
+ UDF_REGID_ID_SIZE))
+ error = udf_get_mpartmap(ump,
+ (struct part_map_meta *) pmap);
else
return (EINVAL); /* Unsupported partition map */
diff --git a/sys/isofs/udf/udf_vnops.c b/sys/isofs/udf/udf_vnops.c
index 623067f502d..d29e0bcae83 100644
--- a/sys/isofs/udf/udf_vnops.c
+++ b/sys/isofs/udf/udf_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udf_vnops.c,v 1.37 2009/08/13 15:00:14 jasper Exp $ */
+/* $OpenBSD: udf_vnops.c,v 1.38 2009/08/14 22:23:45 krw Exp $ */
/*
* Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org>
@@ -310,6 +310,7 @@ udf_getattr(void *v)
struct vnode *vp;
struct unode *up;
struct vattr *vap;
+ struct extfile_entry *xfentry;
struct file_entry *fentry;
struct timespec ts;
@@ -318,7 +319,9 @@ udf_getattr(void *v)
vp = ap->a_vp;
vap = ap->a_vap;
up = VTOU(vp);
- fentry = up->u_fentry;
+
+ xfentry = up->u_fentry;
+ fentry = (struct file_entry *)up->u_fentry;
vap->va_fsid = up->u_dev;
vap->va_fileid = up->u_ino;
@@ -330,9 +333,6 @@ udf_getattr(void *v)
*/
vap->va_uid = (letoh32(fentry->uid) == -1) ? 0 : letoh32(fentry->uid);
vap->va_gid = (letoh32(fentry->gid) == -1) ? 0 : letoh32(fentry->gid);
- udf_timetotimespec(&fentry->atime, &vap->va_atime);
- udf_timetotimespec(&fentry->mtime, &vap->va_mtime);
- vap->va_ctime = vap->va_mtime; /* Stored as an Extended Attribute */
vap->va_rdev = 0;
if (vp->v_type & VDIR) {
vap->va_nlink++; /* Count a reference to ourselves */
@@ -342,15 +342,23 @@ udf_getattr(void *v)
* that directories consume at least one logical block,
* make it appear so.
*/
- if (fentry->logblks_rec != 0) {
+ vap->va_size = up->u_ump->um_bsize;
+ } else
+ vap->va_size = letoh64(fentry->inf_len);
+ if (udf_checktag(&xfentry->tag, TAGID_EXTFENTRY) == 0) {
+ udf_timetotimespec(&xfentry->atime, &vap->va_atime);
+ udf_timetotimespec(&xfentry->mtime, &vap->va_mtime);
+ if ((vp->v_type & VDIR) && xfentry->logblks_rec != 0)
vap->va_size =
- letoh64(fentry->logblks_rec) * up->u_ump->um_bsize;
- } else {
- vap->va_size = up->u_ump->um_bsize;
- }
+ letoh64(xfentry->logblks_rec) * up->u_ump->um_bsize;
} else {
- vap->va_size = letoh64(fentry->inf_len);
+ udf_timetotimespec(&fentry->atime, &vap->va_atime);
+ udf_timetotimespec(&fentry->mtime, &vap->va_mtime);
+ if ((vp->v_type & VDIR) && fentry->logblks_rec != 0)
+ vap->va_size =
+ letoh64(fentry->logblks_rec) * up->u_ump->um_bsize;
}
+ vap->va_ctime = vap->va_mtime; /* Stored as an Extended Attribute */
vap->va_flags = 0;
vap->va_gen = 1;
vap->va_blocksize = up->u_ump->um_bsize;
@@ -437,8 +445,10 @@ udf_read(void *v)
error = udf_readatoffset(up, &size, offset, &bp, &data);
if (error == 0)
error = uiomove(data, size, uio);
- if (bp != NULL)
+ if (bp != NULL) {
brelse(bp);
+ bp = NULL;
+ }
if (error)
break;
};
@@ -579,8 +589,10 @@ udf_getfid(struct udf_dirstream *ds)
&ds->bp, &ds->data);
if (error) {
ds->error = error;
- if (ds->bp != NULL)
+ if (ds->bp != NULL) {
brelse(ds->bp);
+ ds->bp = NULL;
+ }
return (NULL);
}
}
@@ -622,8 +634,10 @@ udf_getfid(struct udf_dirstream *ds)
/* Reduce all of the casting magic */
fid = (struct fileid_desc*)ds->buf;
- if (ds->bp != NULL)
+ if (ds->bp != NULL) {
brelse(ds->bp);
+ ds->bp = NULL;
+ }
/* Fetch the next allocation */
ds->offset += ds->size;
@@ -632,6 +646,10 @@ udf_getfid(struct udf_dirstream *ds)
&ds->bp, &ds->data);
if (error) {
ds->error = error;
+ if (ds->bp != NULL) {
+ brelse(ds->bp);
+ ds->bp = NULL;
+ }
return (NULL);
}
@@ -680,8 +698,10 @@ static void
udf_closedir(struct udf_dirstream *ds)
{
- if (ds->bp != NULL)
+ if (ds->bp != NULL) {
brelse(ds->bp);
+ ds->bp = NULL;
+ }
if (ds->fid_fragment && ds->buf != NULL)
free(ds->buf, M_UDFFID);
@@ -733,6 +753,10 @@ udf_readdir(void *v)
* Iterate through the file id descriptors. Give the parent dir
* entry special attention.
*/
+ if (ISSET(up->u_ump->um_flags, UDF_MNT_USES_META)) {
+ up->u_ump->um_start += up->u_ump->um_meta_start;
+ up->u_ump->um_len = up->u_ump->um_meta_len;
+ }
ds = udf_opendir(up, uio->uio_offset,
letoh64(up->u_fentry->inf_len), up->u_ump);
@@ -740,7 +764,7 @@ udf_readdir(void *v)
/* Should we return an error on a bad fid? */
if (udf_checktag(&fid->tag, TAGID_FID)) {
- printf("Invalid FID tag\n");
+ printf("Invalid FID tag (%d)\n", fid->tag.id);
error = EIO;
break;
}
@@ -802,6 +826,10 @@ udf_readdir(void *v)
error = ds->error;
udf_closedir(ds);
+ if (ISSET(up->u_ump->um_flags, UDF_MNT_USES_META)) {
+ up->u_ump->um_start = up->u_ump->um_realstart;
+ up->u_ump->um_len = up->u_ump->um_reallen;
+ }
if (ap->a_ncookies != NULL) {
if (error)
@@ -1026,6 +1054,10 @@ udf_lookup(void *v)
nchstats.ncs_2passes++;
}
+ if (ISSET(up->u_ump->um_flags, UDF_MNT_USES_META)) {
+ up->u_ump->um_start += up->u_ump->um_meta_start;
+ up->u_ump->um_len = up->u_ump->um_meta_len;
+ }
lookloop:
ds = udf_opendir(up, offset, fsize, ump);
@@ -1041,6 +1073,7 @@ lookloop:
if (fid->file_char & UDF_FILE_CHAR_DEL)
continue;
+printf("name: '%s', file_char: %u\n", nameptr, fid->file_char);
if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) {
if (flags & ISDOTDOT) {
id = udf_getid(&fid->icb);
@@ -1060,6 +1093,10 @@ lookloop:
if (error) {
udf_closedir(ds);
+ if (ISSET(up->u_ump->um_flags, UDF_MNT_USES_META)) {
+ up->u_ump->um_start = up->u_ump->um_realstart;
+ up->u_ump->um_len = up->u_ump->um_reallen;
+ }
return (error);
}
@@ -1106,6 +1143,10 @@ lookloop:
cache_enter(dvp, *vpp, ap->a_cnp);
udf_closedir(ds);
+ if (ISSET(up->u_ump->um_flags, UDF_MNT_USES_META)) {
+ up->u_ump->um_start = up->u_ump->um_realstart;
+ up->u_ump->um_len = up->u_ump->um_reallen;
+ }
return (error);
}
@@ -1166,6 +1207,7 @@ udf_readatoffset(struct unode *up, int *size, off_t offset,
struct buf **bp, uint8_t **data)
{
struct umount *ump;
+ struct extfile_entry *xfentry = NULL;
struct file_entry *fentry = NULL;
struct buf *bp1;
uint32_t max_size;
@@ -1181,9 +1223,15 @@ udf_readatoffset(struct unode *up, int *size, off_t offset,
* This error means that the file *data* is stored in the
* allocation descriptor field of the file entry.
*/
- fentry = up->u_fentry;
- *data = &fentry->data[letoh32(fentry->l_ea)];
- *size = letoh32(fentry->l_ad);
+ if (udf_checktag(&up->u_fentry->tag, TAGID_EXTFENTRY) == 0) {
+ xfentry = up->u_fentry;
+ *data = &xfentry->data[letoh32(xfentry->l_ea)];
+ *size = letoh32(xfentry->l_ad);
+ } else {
+ fentry = (struct file_entry *)up->u_fentry;
+ *data = &fentry->data[letoh32(fentry->l_ea)];
+ *size = letoh32(fentry->l_ad);
+ }
return (0);
} else if (error != 0) {
return (error);
@@ -1214,17 +1262,26 @@ udf_bmap_internal(struct unode *up, off_t offset, daddr64_t *sector,
uint32_t *max_size)
{
struct umount *ump;
+ struct extfile_entry *xfentry;
struct file_entry *fentry;
void *icb;
struct icb_tag *tag;
uint32_t icblen = 0;
daddr64_t lsector;
int ad_offset, ad_num = 0;
- int i, p_offset;
+ int i, p_offset, l_ea, l_ad;
ump = up->u_ump;
- fentry = up->u_fentry;
+ xfentry = up->u_fentry;
+ fentry = (struct file_entry *)up->u_fentry;
tag = &fentry->icbtag;
+ if (udf_checktag(&xfentry->tag, TAGID_EXTFENTRY) == 0) {
+ l_ea = letoh32(xfentry->l_ea);
+ l_ad = letoh32(xfentry->l_ad);
+ } else {
+ l_ea = letoh32(fentry->l_ea);
+ l_ad = letoh32(fentry->l_ad);
+ }
switch (letoh16(tag->strat_type)) {
case 4:
@@ -1249,12 +1306,17 @@ udf_bmap_internal(struct unode *up, off_t offset, daddr64_t *sector,
do {
offset -= icblen;
ad_offset = sizeof(struct short_ad) * ad_num;
- if (ad_offset > letoh32(fentry->l_ad)) {
- printf("File offset out of bounds\n");
+ if (ad_offset > l_ad) {
+ printf("SFile offset out of bounds (%d > %d)\n",
+ ad_offset, l_ad);
return (EINVAL);
}
- icb = GETICB(short_ad, fentry,
- letoh32(fentry->l_ea) + ad_offset);
+
+ if (udf_checktag(&up->u_fentry->tag, TAGID_EXTFENTRY) == 0)
+ icb = GETICB(short_ad, xfentry, l_ea + ad_offset);
+ else
+ icb = GETICB(short_ad, fentry, l_ea + ad_offset);
+
icblen = GETICBLEN(short_ad, icb);
ad_num++;
} while(offset >= icblen);
@@ -1274,12 +1336,15 @@ udf_bmap_internal(struct unode *up, off_t offset, daddr64_t *sector,
do {
offset -= icblen;
ad_offset = sizeof(struct long_ad) * ad_num;
- if (ad_offset > letoh32(fentry->l_ad)) {
- printf("File offset out of bounds\n");
+ if (ad_offset > l_ad) {
+ printf("LFile offset out of bounds (%d > %d)\n",
+ ad_offset, l_ad);
return (EINVAL);
}
- icb = GETICB(long_ad, fentry,
- letoh32(fentry->l_ea) + ad_offset);
+ if (udf_checktag(&up->u_fentry->tag, TAGID_EXTFENTRY) == 0)
+ icb = GETICB(long_ad, xfentry, l_ea + ad_offset);
+ else
+ icb = GETICB(long_ad, fentry, l_ea + ad_offset);
icblen = GETICBLEN(long_ad, icb);
ad_num++;
} while(offset >= icblen);