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, §or);
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, §or);
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, §or);
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], ®id_id[0], UDF_REGID_ID_SIZE);
849
850 if (!bcmp(®id_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(®id_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(®id_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