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