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