xref: /openbsd/sys/isofs/udf/udf_vfsops.c (revision 998de4a5)
1 /*	$OpenBSD: udf_vfsops.c,v 1.54 2016/08/25 00:06:44 dlg Exp $	*/
2 
3 /*
4  * Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD: src/sys/fs/udf/udf_vfsops.c,v 1.25 2005/01/25 15:52:03 phk Exp $
29  */
30 
31 /*
32  * Ported to OpenBSD by Pedro Martelletto in February 2005.
33  */
34 
35 /*
36  * Ok, here's how it goes.  The UDF specs are pretty clear on how each data
37  * structure is made up, but not very clear on how they relate to each other.
38  * Here is the skinny... This demostrates a filesystem with one file in the
39  * root directory.  Subdirectories are treated just as normal files, but they
40  * have File Id Descriptors of their children as their file data.  As for the
41  * Anchor Volume Descriptor Pointer, it can exist in two of the following three
42  * places: sector 256, sector n (the max sector of the disk), or sector
43  * n - 256.  It's a pretty good bet that one will exist at sector 256 though.
44  * One caveat is unclosed CD media.  For that, sector 256 cannot be written,
45  * so the Anchor Volume Descriptor Pointer can exist at sector 512 until the
46  * media is closed.
47  */
48 
49 #include <sys/types.h>
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/uio.h>
53 #include <sys/buf.h>
54 #include <sys/dirent.h>
55 #include <sys/fcntl.h>
56 #include <sys/kernel.h>
57 #include <sys/malloc.h>
58 #include <sys/mutex.h>
59 #include <sys/mount.h>
60 #include <sys/namei.h>
61 #include <sys/pool.h>
62 #include <sys/proc.h>
63 #include <sys/lock.h>
64 #include <sys/queue.h>
65 #include <sys/vnode.h>
66 #include <sys/lock.h>
67 #include <sys/endian.h>
68 #include <sys/specdev.h>
69 
70 #include <crypto/siphash.h>
71 
72 #include <isofs/udf/ecma167-udf.h>
73 #include <isofs/udf/udf.h>
74 #include <isofs/udf/udf_extern.h>
75 
76 struct pool udf_trans_pool;
77 struct pool unode_pool;
78 struct pool udf_ds_pool;
79 
80 int udf_find_partmaps(struct umount *, struct logvol_desc *);
81 int udf_get_vpartmap(struct umount *, struct part_map_virt *);
82 int udf_get_spartmap(struct umount *, struct part_map_spare *);
83 int udf_get_mpartmap(struct umount *, struct part_map_meta *);
84 int udf_mountfs(struct vnode *, struct mount *, uint32_t, struct proc *);
85 
86 const struct vfsops udf_vfsops = {
87 	.vfs_fhtovp =		udf_fhtovp,
88 	.vfs_init =		udf_init,
89 	.vfs_mount =		udf_mount,
90 	.vfs_start =		udf_start,
91 	.vfs_root =		udf_root,
92 	.vfs_quotactl =		udf_quotactl,
93 	.vfs_statfs =		udf_statfs,
94 	.vfs_sync =		udf_sync,
95 	.vfs_unmount =		udf_unmount,
96 	.vfs_vget =		udf_vget,
97 	.vfs_vptofh =		udf_vptofh,
98 	.vfs_sysctl =		udf_sysctl,
99 	.vfs_checkexp =		udf_checkexp,
100 };
101 
102 int
103 udf_init(struct vfsconf *foo)
104 {
105 	pool_init(&udf_trans_pool, MAXNAMLEN * sizeof(unicode_t), 0, 0,
106 	    PR_WAITOK, "udftrpl", NULL);
107 	pool_setipl(&udf_trans_pool, IPL_NONE);
108 	pool_init(&unode_pool, sizeof(struct unode), 0, 0,
109 	    PR_WAITOK, "udfndpl", NULL);
110 	pool_setipl(&unode_pool, IPL_NONE);
111 	pool_init(&udf_ds_pool, sizeof(struct udf_dirstream), 0, 0,
112 	    PR_WAITOK, "udfdspl", NULL);
113 	pool_setipl(&udf_ds_pool, IPL_NONE);
114 
115 	return (0);
116 }
117 
118 int
119 udf_start(struct mount *mp, int flags, struct proc *p)
120 {
121 	return (0);
122 }
123 
124 int
125 udf_mount(struct mount *mp, const char *path, void *data,
126     struct nameidata *ndp,  struct proc *p)
127 {
128 	struct vnode *devvp;	/* vnode of the mount device */
129 	struct udf_args args;
130 	char fspec[MNAMELEN];
131 	int error;
132 
133 	if ((mp->mnt_flag & MNT_RDONLY) == 0) {
134 		mp->mnt_flag |= MNT_RDONLY;
135 #ifdef UDF_DEBUG
136 		printf("udf_mount: enforcing read-only mode\n");
137 #endif
138 	}
139 
140 	/*
141 	 * No root filesystem support.  Probably not a big deal, since the
142 	 * bootloader doesn't understand UDF.
143 	 */
144 	if (mp->mnt_flag & MNT_ROOTFS)
145 		return (EOPNOTSUPP);
146 
147 	error = copyin(data, &args, sizeof(struct udf_args));
148 	if (error)
149 		return (error);
150 
151 	if (args.fspec == NULL)
152 		return (EINVAL);
153 
154 	error = copyinstr(args.fspec, fspec, sizeof(fspec), NULL);
155 	if (error)
156 		return (error);
157 
158 	NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fspec, p);
159 	if ((error = namei(ndp)))
160 		return (error);
161 
162 	devvp = ndp->ni_vp;
163 	if (devvp->v_type != VBLK) {
164 		vrele(devvp);
165 		return (ENOTBLK);
166 	}
167 
168 	if (major(devvp->v_rdev) >= nblkdev) {
169 		vrele(devvp);
170 		return (ENXIO);
171 	}
172 
173 	/* Check the access rights on the mount device */
174 	if (p->p_ucred->cr_uid) {
175 		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
176 		error = VOP_ACCESS(devvp, VREAD, p->p_ucred, p);
177 		VOP_UNLOCK(devvp, p);
178 		if (error) {
179 			vrele(devvp);
180 			return (error);
181 		}
182 	}
183 
184 	if ((error = udf_mountfs(devvp, mp, args.lastblock, p))) {
185 		vrele(devvp);
186 		return (error);
187 	}
188 
189 	/*
190 	 * Keep a copy of the mount information.
191 	 */
192 	bzero(mp->mnt_stat.f_mntonname, MNAMELEN);
193 	strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN);
194 	bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
195 	strlcpy(mp->mnt_stat.f_mntfromname, fspec, MNAMELEN);
196 	bzero(mp->mnt_stat.f_mntfromspec, MNAMELEN);
197 	strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN);
198 
199 	return (0);
200 };
201 
202 /*
203  * Check the descriptor tag for both the correct id and correct checksum.
204  * Return zero if all is good, EINVAL if not.
205  */
206 int
207 udf_checktag(struct desc_tag *tag, uint16_t id)
208 {
209 	uint8_t *itag;
210 	uint8_t i, cksum = 0;
211 
212 	itag = (uint8_t *)tag;
213 
214 	if (letoh16(tag->id) != id)
215 		return (EINVAL);
216 
217 	for (i = 0; i < 15; i++)
218 		cksum = cksum + itag[i];
219 	cksum = cksum - itag[4];
220 
221 	if (cksum == tag->cksum)
222 		return (0);
223 
224 	return (EINVAL);
225 }
226 
227 int
228 udf_mountfs(struct vnode *devvp, struct mount *mp, uint32_t lb, struct proc *p)
229 {
230 	struct buf *bp = NULL;
231 	struct anchor_vdp avdp;
232 	struct umount *ump = NULL;
233 	struct part_desc *pd;
234 	struct logvol_desc *lvd;
235 	struct fileset_desc *fsd;
236 	struct extfile_entry *xfentry;
237 	struct file_entry *fentry;
238 	uint32_t sector, size, mvds_start, mvds_end;
239 	uint32_t fsd_offset = 0;
240 	uint16_t part_num = 0, fsd_part = 0;
241 	int error = EINVAL;
242 	int logvol_found = 0, part_found = 0, fsd_found = 0;
243 	int bsize;
244 
245 	/*
246 	 * Disallow multiple mounts of the same device.
247 	 * Disallow mounting of a device that is currently in use
248 	 * (except for root, which might share swap device for miniroot).
249 	 * Flush out any old buffers remaining from a previous use.
250 	 */
251 	if ((error = vfs_mountedon(devvp)))
252 		return (error);
253 	if (vcount(devvp) > 1 && devvp != rootvp)
254 		return (EBUSY);
255 	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
256 	error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0);
257 	VOP_UNLOCK(devvp, p);
258 	if (error)
259 		return (error);
260 
261 	error = VOP_OPEN(devvp, FREAD, FSCRED, p);
262 	if (error)
263 		return (error);
264 
265 	ump = malloc(sizeof(*ump), M_UDFMOUNT, M_WAITOK | M_ZERO);
266 
267 	mp->mnt_data = ump;
268 	mp->mnt_stat.f_fsid.val[0] = devvp->v_rdev;
269 	mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
270 	mp->mnt_stat.f_namemax = NAME_MAX;
271 	mp->mnt_flag |= MNT_LOCAL;
272 
273 	ump->um_mountp = mp;
274 	ump->um_dev = devvp->v_rdev;
275 	ump->um_devvp = devvp;
276 
277 	bsize = 2048;	/* Should probe the media for its size. */
278 
279 	/*
280 	 * Get the Anchor Volume Descriptor Pointer from sector 256.
281 	 * Should also check sector n - 256, n, and 512.
282 	 */
283 	sector = 256;
284 	if ((error = bread(devvp, sector * btodb(bsize), bsize, &bp)) != 0)
285 		goto bail;
286 	if ((error = udf_checktag((struct desc_tag *)bp->b_data, TAGID_ANCHOR)))
287 		goto bail;
288 
289 	bcopy(bp->b_data, &avdp, sizeof(struct anchor_vdp));
290 	brelse(bp);
291 	bp = NULL;
292 
293 	/*
294 	 * Extract the Partition Descriptor and Logical Volume Descriptor
295 	 * from the Volume Descriptor Sequence.
296 	 * Should we care about the partition type right now?
297 	 * What about multiple partitions?
298 	 */
299 	mvds_start = letoh32(avdp.main_vds_ex.loc);
300 	mvds_end = mvds_start + (letoh32(avdp.main_vds_ex.len) - 1) / bsize;
301 	for (sector = mvds_start; sector < mvds_end; sector++) {
302 		if ((error = bread(devvp, sector * btodb(bsize), bsize,
303 				   &bp)) != 0) {
304 			printf("Can't read sector %d of VDS\n", sector);
305 			goto bail;
306 		}
307 		lvd = (struct logvol_desc *)bp->b_data;
308 		if (!udf_checktag(&lvd->tag, TAGID_LOGVOL)) {
309 			ump->um_bsize = letoh32(lvd->lb_size);
310 			ump->um_bmask = ump->um_bsize - 1;
311 			ump->um_bshift = ffs(ump->um_bsize) - 1;
312 			fsd_part = letoh16(lvd->_lvd_use.fsd_loc.loc.part_num);
313 			fsd_offset = letoh32(lvd->_lvd_use.fsd_loc.loc.lb_num);
314 			if (udf_find_partmaps(ump, lvd))
315 				break;
316 			logvol_found = 1;
317 		}
318 		pd = (struct part_desc *)bp->b_data;
319 		if (!udf_checktag(&pd->tag, TAGID_PARTITION)) {
320 			part_found = 1;
321 			part_num = letoh16(pd->part_num);
322 			ump->um_len = ump->um_reallen = letoh32(pd->part_len);
323 			ump->um_start = ump->um_realstart = letoh32(pd->start_loc);
324 		}
325 
326 		brelse(bp);
327 		bp = NULL;
328 		if ((part_found) && (logvol_found))
329 			break;
330 	}
331 
332 	if (!part_found || !logvol_found) {
333 		error = EINVAL;
334 		goto bail;
335 	}
336 
337 	if (ISSET(ump->um_flags, UDF_MNT_USES_META)) {
338 		/* Read Metadata File 'File Entry' to find Metadata file. */
339 		struct long_ad *la;
340 		sector = ump->um_start + ump->um_meta_start; /* Set in udf_get_mpartmap() */
341 		if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) {
342 			printf("Cannot read sector %d for Metadata File Entry\n", sector);
343 			error = EINVAL;
344 			goto bail;
345 		}
346 		xfentry = (struct extfile_entry *)bp->b_data;
347 		fentry = (struct file_entry *)bp->b_data;
348 		if (udf_checktag(&xfentry->tag, TAGID_EXTFENTRY) == 0)
349 			la = (struct long_ad *)&xfentry->data[letoh32(xfentry->l_ea)];
350 		else if (udf_checktag(&fentry->tag, TAGID_FENTRY) == 0)
351 			la = (struct long_ad *)&fentry->data[letoh32(fentry->l_ea)];
352 		else {
353 			printf("Invalid Metadata File FE @ sector %d! (tag.id %d)\n",
354 			    sector, fentry->tag.id);
355 			error = EINVAL;
356 			goto bail;
357 		}
358 		ump->um_meta_start = letoh32(la->loc.lb_num);
359 		ump->um_meta_len = letoh32(la->len);
360 		if (bp != NULL) {
361 			brelse(bp);
362 			bp = NULL;
363 		}
364 	} else if (fsd_part != part_num) {
365 		printf("FSD does not lie within the partition!\n");
366 		error = EINVAL;
367 		goto bail;
368 	}
369 
370 	mtx_init(&ump->um_hashmtx, IPL_NONE);
371 	ump->um_hashtbl = hashinit(UDF_HASHTBLSIZE, M_UDFMOUNT, M_WAITOK,
372 	    &ump->um_hashsz);
373 	arc4random_buf(&ump->um_hashkey, sizeof(ump->um_hashkey));
374 
375 	/* Get the VAT, if needed */
376 	if (ump->um_flags & UDF_MNT_FIND_VAT) {
377 		error = udf_vat_get(ump, lb);
378 		if (error)
379 			goto bail;
380 	}
381 
382 	/*
383 	 * Grab the Fileset Descriptor
384 	 * Thanks to Chuck McCrobie <mccrobie@cablespeed.com> for pointing
385 	 * me in the right direction here.
386 	 */
387 
388 	if (ISSET(ump->um_flags, UDF_MNT_USES_META))
389 		sector = ump->um_meta_start;
390 	else
391 		sector = fsd_offset;
392 	udf_vat_map(ump, &sector);
393 	if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) {
394 		printf("Cannot read sector %d of FSD\n", sector);
395 		goto bail;
396 	}
397 	fsd = (struct fileset_desc *)bp->b_data;
398 	if (!udf_checktag(&fsd->tag, TAGID_FSD)) {
399 		fsd_found = 1;
400 		bcopy(&fsd->rootdir_icb, &ump->um_root_icb,
401 		    sizeof(struct long_ad));
402 		if (ISSET(ump->um_flags, UDF_MNT_USES_META)) {
403 			ump->um_root_icb.loc.lb_num += ump->um_meta_start;
404 			ump->um_root_icb.loc.part_num = part_num;
405 		}
406 	}
407 
408 	brelse(bp);
409 	bp = NULL;
410 
411 	if (!fsd_found) {
412 		printf("Couldn't find the fsd\n");
413 		error = EINVAL;
414 		goto bail;
415 	}
416 
417 	/*
418 	 * Find the file entry for the root directory.
419 	 */
420 	sector = letoh32(ump->um_root_icb.loc.lb_num);
421 	size = letoh32(ump->um_root_icb.len);
422 	udf_vat_map(ump, &sector);
423 	if ((error = udf_readlblks(ump, sector, size, &bp)) != 0) {
424 		printf("Cannot read sector %d\n", sector);
425 		goto bail;
426 	}
427 
428 	xfentry = (struct extfile_entry *)bp->b_data;
429 	fentry = (struct file_entry *)bp->b_data;
430 	error = udf_checktag(&xfentry->tag, TAGID_EXTFENTRY);
431 	if (error) {
432 	    	error = udf_checktag(&fentry->tag, TAGID_FENTRY);
433 		if (error) {
434 			printf("Invalid root file entry!\n");
435 			goto bail;
436 		}
437 	}
438 
439 	brelse(bp);
440 	bp = NULL;
441 
442 	devvp->v_specmountpoint = mp;
443 
444 	return (0);
445 
446 bail:
447 	if (ump->um_hashtbl != NULL)
448 		free(ump->um_hashtbl, M_UDFMOUNT, 0);
449 
450 	if (ump != NULL) {
451 		free(ump, M_UDFMOUNT, 0);
452 		mp->mnt_data = NULL;
453 		mp->mnt_flag &= ~MNT_LOCAL;
454 	}
455 	if (devvp->v_specinfo)
456 		devvp->v_specmountpoint = NULL;
457 	if (bp != NULL)
458 		brelse(bp);
459 
460 	vn_lock(devvp, LK_EXCLUSIVE|LK_RETRY, p);
461 	VOP_CLOSE(devvp, FREAD, FSCRED, p);
462 	VOP_UNLOCK(devvp, p);
463 
464 	return (error);
465 }
466 
467 int
468 udf_unmount(struct mount *mp, int mntflags, struct proc *p)
469 {
470 	struct umount *ump;
471 	struct vnode *devvp;
472 	int error, flags = 0;
473 
474 	ump = VFSTOUDFFS(mp);
475 	devvp = ump->um_devvp;
476 
477 	if (mntflags & MNT_FORCE)
478 		flags |= FORCECLOSE;
479 
480 	if ((error = vflush(mp, NULL, flags)))
481 		return (error);
482 
483 	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
484 	vinvalbuf(devvp, V_SAVE, NOCRED, p, 0, 0);
485 	(void)VOP_CLOSE(devvp, FREAD, NOCRED, p);
486 	VOP_UNLOCK(devvp, p);
487 
488 	devvp->v_specmountpoint = NULL;
489 	vrele(devvp);
490 
491 	if (ump->um_flags & UDF_MNT_USES_VAT)
492 		free(ump->um_vat, M_UDFMOUNT, 0);
493 
494 	if (ump->um_stbl != NULL)
495 		free(ump->um_stbl, M_UDFMOUNT, 0);
496 
497 	if (ump->um_hashtbl != NULL)
498 		free(ump->um_hashtbl, M_UDFMOUNT, 0);
499 
500 	free(ump, M_UDFMOUNT, 0);
501 
502 	mp->mnt_data = NULL;
503 	mp->mnt_flag &= ~MNT_LOCAL;
504 
505 	return (0);
506 }
507 
508 int
509 udf_root(struct mount *mp, struct vnode **vpp)
510 {
511 	struct umount *ump;
512 	struct vnode *vp;
513 	udfino_t id;
514 	int error;
515 
516 	ump = VFSTOUDFFS(mp);
517 
518 	id = udf_getid(&ump->um_root_icb);
519 
520 	error = udf_vget(mp, id, vpp);
521 	if (error)
522 		return (error);
523 
524 	vp = *vpp;
525 	vp->v_flag |= VROOT;
526 
527 	return (0);
528 }
529 
530 int
531 udf_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg,
532     struct proc *p)
533 {
534 	return (EOPNOTSUPP);
535 }
536 
537 int
538 udf_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
539 {
540 	struct umount *ump;
541 
542 	ump = VFSTOUDFFS(mp);
543 
544 	sbp->f_bsize = ump->um_bsize;
545 	sbp->f_iosize = ump->um_bsize;
546 	sbp->f_blocks = ump->um_len;
547 	sbp->f_bfree = 0;
548 	sbp->f_bavail = 0;
549 	sbp->f_files = 0;
550 	sbp->f_ffree = 0;
551 	sbp->f_favail = 0;
552 	copy_statfs_info(sbp, mp);
553 
554 	return (0);
555 }
556 
557 int
558 udf_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p)
559 {
560 	return (0);
561 }
562 
563 int
564 udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
565 {
566 	struct buf *bp;
567 	struct vnode *devvp;
568 	struct umount *ump;
569 	struct proc *p;
570 	struct vnode *vp, *nvp;
571 	struct unode *up;
572 	struct extfile_entry *xfe;
573 	struct file_entry *fe;
574 	uint32_t sector;
575 	int error, size;
576 
577 	if (ino > (udfino_t)-1)
578 		panic("udf_vget: alien ino_t %llu", (unsigned long long)ino);
579 
580 	p = curproc;
581 	bp = NULL;
582 	*vpp = NULL;
583 	ump = VFSTOUDFFS(mp);
584 
585 	/* See if we already have this in the cache */
586 	if ((error = udf_hashlookup(ump, ino, LK_EXCLUSIVE, vpp)) != 0)
587 		return (error);
588 	if (*vpp != NULL)
589 		return (0);
590 
591 	/*
592 	 * Allocate memory and check the tag id's before grabbing a new
593 	 * vnode, since it's hard to roll back if there is a problem.
594 	 */
595 	up = pool_get(&unode_pool, PR_WAITOK | PR_ZERO);
596 
597 	/*
598 	 * Copy in the file entry.  Per the spec, the size can only be 1 block.
599 	 */
600 	sector = ino;
601 	devvp = ump->um_devvp;
602 	udf_vat_map(ump, &sector);
603 	if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) {
604 		printf("Cannot read sector %d\n", sector);
605 		pool_put(&unode_pool, up);
606 		if (bp != NULL)
607 			brelse(bp);
608 		return (error);
609 	}
610 
611 	xfe = (struct extfile_entry *)bp->b_data;
612 	fe = (struct file_entry *)bp->b_data;
613 	error = udf_checktag(&xfe->tag, TAGID_EXTFENTRY);
614 	if (error == 0) {
615 		size = letoh32(xfe->l_ea) + letoh32(xfe->l_ad);
616 	} else {
617 		error = udf_checktag(&fe->tag, TAGID_FENTRY);
618 		if (error) {
619 			printf("Invalid file entry!\n");
620 			pool_put(&unode_pool, up);
621 			if (bp != NULL)
622 				brelse(bp);
623 			return (ENOMEM);
624 		} else
625 			size = letoh32(fe->l_ea) + letoh32(fe->l_ad);
626 	}
627 
628 	/* Allocate max size of FE/XFE. */
629 	up->u_fentry = malloc(size + UDF_EXTFENTRY_SIZE, M_UDFFENTRY, M_NOWAIT | M_ZERO);
630 	if (up->u_fentry == NULL) {
631 		pool_put(&unode_pool, up);
632 		if (bp != NULL)
633 			brelse(bp);
634 		return (ENOMEM); /* Cannot allocate file entry block */
635 	}
636 
637 	if (udf_checktag(&xfe->tag, TAGID_EXTFENTRY) == 0)
638 		bcopy(bp->b_data, up->u_fentry, size + UDF_EXTFENTRY_SIZE);
639 	else
640 		bcopy(bp->b_data, up->u_fentry, size + UDF_FENTRY_SIZE);
641 
642 	brelse(bp);
643 	bp = NULL;
644 
645 	if ((error = udf_allocv(mp, &vp, p))) {
646 		free(up->u_fentry, M_UDFFENTRY, 0);
647 		pool_put(&unode_pool, up);
648 		return (error); /* Error from udf_allocv() */
649 	}
650 
651 	up->u_vnode = vp;
652 	up->u_ino = ino;
653 	up->u_devvp = ump->um_devvp;
654 	up->u_dev = ump->um_dev;
655 	up->u_ump = ump;
656 	vp->v_data = up;
657 	vref(ump->um_devvp);
658 
659 	rrw_init(&up->u_lock, "unode");
660 
661 	/*
662 	 * udf_hashins() will lock the vnode for us.
663 	 */
664 	udf_hashins(up);
665 
666 	switch (up->u_fentry->icbtag.file_type) {
667 	default:
668 		printf("Unrecognized file type (%d)\n", vp->v_type);
669 		vp->v_type = VREG;
670 		break;
671 	case UDF_ICB_FILETYPE_DIRECTORY:
672 		vp->v_type = VDIR;
673 		break;
674 	case UDF_ICB_FILETYPE_BLOCKDEVICE:
675 		vp->v_type = VBLK;
676 		break;
677 	case UDF_ICB_FILETYPE_CHARDEVICE:
678 		vp->v_type = VCHR;
679 		break;
680 	case UDF_ICB_FILETYPE_FIFO:
681 		vp->v_type = VFIFO;
682 		break;
683 	case UDF_ICB_FILETYPE_SOCKET:
684 		vp->v_type = VSOCK;
685 		break;
686 	case UDF_ICB_FILETYPE_SYMLINK:
687 		vp->v_type = VLNK;
688 		break;
689 	case UDF_ICB_FILETYPE_RANDOMACCESS:
690 	case UDF_ICB_FILETYPE_REALTIME:
691 	case UDF_ICB_FILETYPE_UNKNOWN:
692 		vp->v_type = VREG;
693 		break;
694 	}
695 
696 	/* check if this is a vnode alias */
697 	if ((nvp = checkalias(vp, up->u_dev, ump->um_mountp)) != NULL) {
698 		printf("found a vnode alias\n");
699 		/*
700 		 * Discard unneeded vnode, but save its udf_node.
701 		 * Note that the lock is carried over in the udf_node
702 		 */
703 		nvp->v_data = vp->v_data;
704 		vp->v_data = NULL;
705 		vp->v_op = &spec_vops;
706 		vrele(vp);
707 		vgone(vp);
708 		/*
709 		 * Reinitialize aliased inode.
710 		 */
711 		vp = nvp;
712 		ump->um_devvp = vp;
713 	}
714 
715 	*vpp = vp;
716 
717 	return (0);
718 }
719 
720 struct ifid {
721 	u_short	ifid_len;
722 	u_short	ifid_pad;
723 	int	ifid_ino;
724 	long	ifid_start;
725 };
726 
727 int
728 udf_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
729 {
730 	struct ifid *ifhp;
731 	struct vnode *nvp;
732 	int error;
733 
734 	ifhp = (struct ifid *)fhp;
735 
736 	if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) {
737 		*vpp = NULLVP;
738 		return (error);
739 	}
740 
741 	*vpp = nvp;
742 
743 	return (0);
744 }
745 
746 int
747 udf_vptofh(struct vnode *vp, struct fid *fhp)
748 {
749 	struct unode *up;
750 	struct ifid *ifhp;
751 
752 	up = VTOU(vp);
753 	ifhp = (struct ifid *)fhp;
754 	ifhp->ifid_len = sizeof(struct ifid);
755 	ifhp->ifid_ino = up->u_ino;
756 
757 	return (0);
758 }
759 
760 int
761 udf_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
762     size_t newlen, struct proc *p)
763 {
764 	return (EINVAL);
765 }
766 
767 int
768 udf_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp,
769     struct ucred **credanonp)
770 {
771 	return (EACCES); /* For the time being */
772 }
773 
774 /* Handle a virtual partition map */
775 int
776 udf_get_vpartmap(struct umount *ump, struct part_map_virt *pmv)
777 {
778 	ump->um_flags |= UDF_MNT_FIND_VAT; /* Should do more than this */
779 	return (0);
780 }
781 
782 /* Handle a sparable partition map */
783 int
784 udf_get_spartmap(struct umount *ump, struct part_map_spare *pms)
785 {
786 	struct buf *bp;
787 	int i, error;
788 
789 	ump->um_stbl = malloc(letoh32(pms->st_size), M_UDFMOUNT, M_NOWAIT);
790 	if (ump->um_stbl == NULL)
791 		return (ENOMEM);
792 
793 	bzero(ump->um_stbl, letoh32(pms->st_size));
794 
795 	/* Calculate the number of sectors per packet */
796 	ump->um_psecs = letoh16(pms->packet_len) / ump->um_bsize;
797 
798 	error = udf_readlblks(ump, letoh32(pms->st_loc[0]),
799 	    letoh32(pms->st_size), &bp);
800 
801 	if (error) {
802 		if (bp != NULL)
803 			brelse(bp);
804 		free(ump->um_stbl, M_UDFMOUNT, 0);
805 		return (error); /* Failed to read sparing table */
806 	}
807 
808 	bcopy(bp->b_data, ump->um_stbl, letoh32(pms->st_size));
809 	brelse(bp);
810 	bp = NULL;
811 
812 	if (udf_checktag(&ump->um_stbl->tag, 0)) {
813 		free(ump->um_stbl, M_UDFMOUNT, 0);
814 		return (EINVAL); /* Invalid sparing table found */
815 	}
816 
817 	/*
818 	 * See how many valid entries there are here. The list is
819 	 * supposed to be sorted, 0xfffffff0 and higher are not valid.
820 	 */
821 	for (i = 0; i < letoh16(ump->um_stbl->rt_l); i++) {
822 		ump->um_stbl_len = i;
823 		if (letoh32(ump->um_stbl->entries[i].org) >= 0xfffffff0)
824 			break;
825 	}
826 
827 	return (0);
828 }
829 
830 /* Handle a metadata partition map */
831 int
832 udf_get_mpartmap(struct umount *ump, struct part_map_meta *pmm)
833 {
834 	ump->um_flags |= UDF_MNT_USES_META;
835 	ump->um_meta_start = pmm->meta_file_lbn;
836 	return (0);
837 }
838 
839 /* Scan the partition maps */
840 int
841 udf_find_partmaps(struct umount *ump, struct logvol_desc *lvd)
842 {
843 	struct regid *pmap_id;
844 	unsigned char regid_id[UDF_REGID_ID_SIZE + 1];
845 	int i, ptype, psize, error;
846 	uint8_t *pmap = (uint8_t *) &lvd->maps[0];
847 
848 	for (i = 0; i < letoh32(lvd->n_pm); i++) {
849 		ptype = pmap[0];
850 		psize = pmap[1];
851 
852 		if (ptype != 1 && ptype != 2)
853 			return (EINVAL); /* Invalid partition map type */
854 
855 		if (psize != sizeof(struct part_map_1)  &&
856 		    psize != sizeof(struct part_map_2))
857 			return (EINVAL); /* Invalid partition map size */
858 
859 		if (ptype == 1) {
860 			pmap += sizeof(struct part_map_1);
861 			continue;
862 		}
863 
864 		/* Type 2 map. Find out the details */
865 		pmap_id = (struct regid *) &pmap[4];
866 		regid_id[UDF_REGID_ID_SIZE] = '\0';
867 		bcopy(&pmap_id->id[0], &regid_id[0], UDF_REGID_ID_SIZE);
868 
869 		if (!bcmp(&regid_id[0], "*UDF Virtual Partition",
870 		    UDF_REGID_ID_SIZE))
871 			error = udf_get_vpartmap(ump,
872 			    (struct part_map_virt *) pmap);
873 		else if (!bcmp(&regid_id[0], "*UDF Sparable Partition",
874 		    UDF_REGID_ID_SIZE))
875 			error = udf_get_spartmap(ump,
876 			    (struct part_map_spare *) pmap);
877 		else if (!bcmp(&regid_id[0], "*UDF Metadata Partition",
878 		    UDF_REGID_ID_SIZE))
879 			error = udf_get_mpartmap(ump,
880 			    (struct part_map_meta *) pmap);
881 		else
882 			return (EINVAL); /* Unsupported partition map */
883 
884 		if (error)
885 			return (error); /* Error getting partition */
886 
887 		pmap += sizeof(struct part_map_2);
888 	}
889 
890 	return (0);
891 }
892