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