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