This source file includes following definitions.
- udf_init
- udf_start
- udf_mount
- udf_checktag
- udf_mountfs
- udf_unmount
- udf_root
- udf_quotactl
- udf_statfs
- udf_sync
- udf_vget
- udf_fhtovp
- udf_vptofh
- udf_sysctl
- udf_checkexp
- udf_get_vpartmap
- udf_get_spartmap
- udf_find_partmaps
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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_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;
124 struct udf_args args;
125 size_t len;
126 int error;
127
128 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
129 mp->mnt_flag |= MNT_RDONLY;
130 printf("udf_mount: enforcing read-only mode\n");
131 }
132
133
134
135
136
137 if (mp->mnt_flag & MNT_ROOTFS)
138 return (EOPNOTSUPP);
139
140 error = copyin(data, &args, sizeof(struct udf_args));
141 if (error)
142 return (error);
143
144 if (args.fspec == NULL)
145 return (EINVAL);
146
147 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
148 if ((error = namei(ndp)))
149 return (error);
150
151 devvp = ndp->ni_vp;
152 if (devvp->v_type != VBLK) {
153 vrele(devvp);
154 return (ENOTBLK);
155 }
156
157 if (major(devvp->v_rdev) >= nblkdev) {
158 vrele(devvp);
159 return (ENXIO);
160 }
161
162
163 if (p->p_ucred->cr_uid) {
164 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
165 error = VOP_ACCESS(devvp, VREAD, p->p_ucred, p);
166 VOP_UNLOCK(devvp, 0, p);
167 if (error) {
168 vrele(devvp);
169 return (error);
170 }
171 }
172
173 if ((error = udf_mountfs(devvp, mp, args.lastblock, p))) {
174 vrele(devvp);
175 return (error);
176 }
177
178
179
180
181 copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &len);
182 bzero(mp->mnt_stat.f_mntonname + len, MNAMELEN - len);
183 copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &len);
184 bzero(mp->mnt_stat.f_mntfromname + len, MNAMELEN - len);
185
186 return (0);
187 };
188
189
190
191
192
193 int
194 udf_checktag(struct desc_tag *tag, uint16_t id)
195 {
196 uint8_t *itag;
197 uint8_t i, cksum = 0;
198
199 itag = (uint8_t *)tag;
200
201 if (letoh16(tag->id) != id)
202 return (EINVAL);
203
204 for (i = 0; i < 15; i++)
205 cksum = cksum + itag[i];
206 cksum = cksum - itag[4];
207
208 if (cksum == tag->cksum)
209 return (0);
210
211 return (EINVAL);
212 }
213
214 int
215 udf_mountfs(struct vnode *devvp, struct mount *mp, uint32_t lb, struct proc *p)
216 {
217 struct buf *bp = NULL;
218 struct anchor_vdp avdp;
219 struct umount *ump = NULL;
220 struct part_desc *pd;
221 struct logvol_desc *lvd;
222 struct fileset_desc *fsd;
223 struct file_entry *root_fentry;
224 uint32_t sector, size, mvds_start, mvds_end;
225 uint32_t fsd_offset = 0;
226 uint16_t part_num = 0, fsd_part = 0;
227 int error = EINVAL;
228 int logvol_found = 0, part_found = 0, fsd_found = 0;
229 int bsize;
230
231
232
233
234
235
236
237 if ((error = vfs_mountedon(devvp)))
238 return (error);
239 if (vcount(devvp) > 1 && devvp != rootvp)
240 return (EBUSY);
241 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
242 error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0);
243 VOP_UNLOCK(devvp, 0, p);
244 if (error)
245 return (error);
246
247 error = VOP_OPEN(devvp, FREAD, FSCRED, p);
248 if (error)
249 return (error);
250
251 MALLOC(ump, struct umount *, sizeof(struct umount), M_UDFMOUNT,
252 M_WAITOK);
253 bzero(ump, sizeof(struct umount));
254
255 mp->mnt_data = (qaddr_t) ump;
256 mp->mnt_stat.f_fsid.val[0] = devvp->v_rdev;
257 mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_UDF);
258 mp->mnt_flag |= MNT_LOCAL;
259
260 ump->um_mountp = mp;
261 ump->um_dev = devvp->v_rdev;
262 ump->um_devvp = devvp;
263
264 bsize = 2048;
265
266
267
268
269
270 sector = 256;
271 if ((error = bread(devvp, sector * btodb(bsize), bsize, NOCRED,
272 &bp)) != 0)
273 goto bail;
274 if ((error = udf_checktag((struct desc_tag *)bp->b_data, TAGID_ANCHOR)))
275 goto bail;
276
277 bcopy(bp->b_data, &avdp, sizeof(struct anchor_vdp));
278 brelse(bp);
279 bp = NULL;
280
281
282
283
284
285
286
287 mvds_start = letoh32(avdp.main_vds_ex.loc);
288 mvds_end = mvds_start + (letoh32(avdp.main_vds_ex.len) - 1) / bsize;
289 for (sector = mvds_start; sector < mvds_end; sector++) {
290 if ((error = bread(devvp, sector * btodb(bsize), bsize,
291 NOCRED, &bp)) != 0) {
292 printf("Can't read sector %d of VDS\n", sector);
293 goto bail;
294 }
295 lvd = (struct logvol_desc *)bp->b_data;
296 if (!udf_checktag(&lvd->tag, TAGID_LOGVOL)) {
297 ump->um_bsize = letoh32(lvd->lb_size);
298 ump->um_bmask = ump->um_bsize - 1;
299 ump->um_bshift = ffs(ump->um_bsize) - 1;
300 fsd_part = letoh16(lvd->_lvd_use.fsd_loc.loc.part_num);
301 fsd_offset = letoh32(lvd->_lvd_use.fsd_loc.loc.lb_num);
302 if (udf_find_partmaps(ump, lvd))
303 break;
304 logvol_found = 1;
305 }
306 pd = (struct part_desc *)bp->b_data;
307 if (!udf_checktag(&pd->tag, TAGID_PARTITION)) {
308 part_found = 1;
309 part_num = letoh16(pd->part_num);
310 ump->um_len = letoh32(pd->part_len);
311 ump->um_start = letoh32(pd->start_loc);
312 }
313
314 brelse(bp);
315 bp = NULL;
316 if ((part_found) && (logvol_found))
317 break;
318 }
319
320 if (!part_found || !logvol_found) {
321 error = EINVAL;
322 goto bail;
323 }
324
325 if (fsd_part != part_num) {
326 printf("FSD does not lie within the partition!\n");
327 error = EINVAL;
328 goto bail;
329 }
330
331 mtx_init(&ump->um_hashmtx, IPL_NONE);
332 ump->um_hashtbl = hashinit(UDF_HASHTBLSIZE, M_UDFMOUNT, M_WAITOK,
333 &ump->um_hashsz);
334
335
336 if (ump->um_flags & UDF_MNT_FIND_VAT) {
337 error = udf_vat_get(ump, lb);
338 if (error)
339 goto bail;
340 }
341
342
343
344
345
346
347 sector = fsd_offset;
348 udf_vat_map(ump, §or);
349 if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) {
350 printf("Cannot read sector %d of FSD\n", sector);
351 goto bail;
352 }
353 fsd = (struct fileset_desc *)bp->b_data;
354 if (!udf_checktag(&fsd->tag, TAGID_FSD)) {
355 fsd_found = 1;
356 bcopy(&fsd->rootdir_icb, &ump->um_root_icb,
357 sizeof(struct long_ad));
358 }
359
360 brelse(bp);
361 bp = NULL;
362
363 if (!fsd_found) {
364 printf("Couldn't find the fsd\n");
365 error = EINVAL;
366 goto bail;
367 }
368
369
370
371
372 sector = letoh32(ump->um_root_icb.loc.lb_num);
373 size = letoh32(ump->um_root_icb.len);
374 udf_vat_map(ump, §or);
375 if ((error = udf_readlblks(ump, sector, size, &bp)) != 0) {
376 printf("Cannot read sector %d\n", sector);
377 goto bail;
378 }
379
380 root_fentry = (struct file_entry *)bp->b_data;
381 if ((error = udf_checktag(&root_fentry->tag, TAGID_FENTRY))) {
382 printf("Invalid root file entry!\n");
383 goto bail;
384 }
385
386 brelse(bp);
387 bp = NULL;
388
389 devvp->v_specmountpoint = mp;
390
391 return (0);
392
393 bail:
394 if (ump->um_hashtbl != NULL)
395 free(ump->um_hashtbl, M_UDFMOUNT);
396
397 if (ump != NULL) {
398 FREE(ump, M_UDFMOUNT);
399 mp->mnt_data = NULL;
400 mp->mnt_flag &= ~MNT_LOCAL;
401 }
402 if (bp != NULL)
403 brelse(bp);
404 VOP_CLOSE(devvp, FREAD, FSCRED, p);
405
406 return (error);
407 }
408
409 int
410 udf_unmount(struct mount *mp, int mntflags, struct proc *p)
411 {
412 struct umount *ump;
413 struct vnode *devvp;
414 int error, flags = 0;
415
416 ump = VFSTOUDFFS(mp);
417 devvp = ump->um_devvp;
418
419 if (mntflags & MNT_FORCE)
420 flags |= FORCECLOSE;
421
422 if ((error = vflush(mp, NULL, flags)))
423 return (error);
424
425 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
426 vinvalbuf(devvp, V_SAVE, NOCRED, p, 0, 0);
427 error = VOP_CLOSE(devvp, FREAD, NOCRED, p);
428 VOP_UNLOCK(devvp, 0, p);
429 if (error)
430 return (error);
431
432 devvp->v_specmountpoint = NULL;
433 vrele(devvp);
434
435 if (ump->um_flags & UDF_MNT_USES_VAT)
436 free(ump->um_vat, M_UDFMOUNT);
437
438 if (ump->um_stbl != NULL)
439 free(ump->um_stbl, M_UDFMOUNT);
440
441 if (ump->um_hashtbl != NULL)
442 free(ump->um_hashtbl, M_UDFMOUNT);
443
444 FREE(ump, M_UDFMOUNT);
445
446 mp->mnt_data = (qaddr_t)0;
447 mp->mnt_flag &= ~MNT_LOCAL;
448
449 return (0);
450 }
451
452 int
453 udf_root(struct mount *mp, struct vnode **vpp)
454 {
455 struct umount *ump;
456 struct vnode *vp;
457 ino_t id;
458 int error;
459
460 ump = VFSTOUDFFS(mp);
461
462 id = udf_getid(&ump->um_root_icb);
463
464 error = udf_vget(mp, id, vpp);
465 if (error)
466 return (error);
467
468 vp = *vpp;
469 vp->v_flag |= VROOT;
470
471 return (0);
472 }
473
474 int
475 udf_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg,
476 struct proc *p)
477 {
478 return (EOPNOTSUPP);
479 }
480
481 int
482 udf_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
483 {
484 struct umount *ump;
485
486 ump = VFSTOUDFFS(mp);
487
488 sbp->f_bsize = ump->um_bsize;
489 sbp->f_iosize = ump->um_bsize;
490 sbp->f_blocks = ump->um_len;
491 sbp->f_bfree = 0;
492 sbp->f_bavail = 0;
493 sbp->f_files = 0;
494 sbp->f_ffree = 0;
495
496 return (0);
497 }
498
499 int
500 udf_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p)
501 {
502 return (0);
503 }
504
505 int
506 udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
507 {
508 struct buf *bp;
509 struct vnode *devvp;
510 struct umount *ump;
511 struct proc *p;
512 struct vnode *vp;
513 struct unode *up;
514 struct file_entry *fe;
515 int error, sector, size;
516
517 p = curproc;
518 bp = NULL;
519 *vpp = NULL;
520 ump = VFSTOUDFFS(mp);
521
522
523 if ((error = udf_hashlookup(ump, ino, LK_EXCLUSIVE, vpp)) != 0)
524 return (error);
525 if (*vpp != NULL)
526 return (0);
527
528
529
530
531
532 up = pool_get(&unode_pool, PR_WAITOK);
533 bzero(up, sizeof(struct unode));
534
535
536
537
538 sector = ino;
539 devvp = ump->um_devvp;
540 udf_vat_map(ump, §or);
541 if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) {
542 printf("Cannot read sector %d\n", sector);
543 pool_put(&unode_pool, up);
544 if (bp != NULL)
545 brelse(bp);
546 return (error);
547 }
548
549 fe = (struct file_entry *)bp->b_data;
550 if (udf_checktag(&fe->tag, TAGID_FENTRY)) {
551 printf("Invalid file entry!\n");
552 pool_put(&unode_pool, up);
553 brelse(bp);
554 return (ENOMEM);
555 }
556
557 size = UDF_FENTRY_SIZE + letoh32(fe->l_ea) + letoh32(fe->l_ad);
558
559 up->u_fentry = malloc(size, M_UDFFENTRY, M_NOWAIT);
560 if (up->u_fentry == NULL) {
561 pool_put(&unode_pool, up);
562 brelse(bp);
563 return (ENOMEM);
564 }
565
566 bcopy(bp->b_data, up->u_fentry, size);
567
568 brelse(bp);
569 bp = NULL;
570
571 if ((error = udf_allocv(mp, &vp, p))) {
572 free(up->u_fentry, M_UDFFENTRY);
573 pool_put(&unode_pool, up);
574 return (error);
575 }
576
577 up->u_vnode = vp;
578 up->u_ino = ino;
579 up->u_devvp = ump->um_devvp;
580 up->u_dev = ump->um_dev;
581 up->u_ump = ump;
582 vp->v_data = up;
583 VREF(ump->um_devvp);
584
585 lockinit(&up->u_lock, PINOD, "unode", 0, 0);
586
587
588
589
590 udf_hashins(up);
591
592 switch (up->u_fentry->icbtag.file_type) {
593 default:
594 vp->v_type = VBAD;
595 break;
596 case UDF_ICB_TYPE_DIR:
597 vp->v_type = VDIR;
598 break;
599 case UDF_ICB_TYPE_FILE:
600 vp->v_type = VREG;
601 break;
602 case UDF_ICB_TYPE_BLKDEV:
603 vp->v_type = VBLK;
604 break;
605 case UDF_ICB_TYPE_CHRDEV:
606 vp->v_type = VCHR;
607 break;
608 case UDF_ICB_TYPE_FIFO:
609 vp->v_type = VFIFO;
610 break;
611 case UDF_ICB_TYPE_SOCKET:
612 vp->v_type = VSOCK;
613 break;
614 case UDF_ICB_TYPE_SYMLINK:
615 vp->v_type = VLNK;
616 break;
617 case UDF_ICB_TYPE_VAT_150:
618 vp->v_type = VREG;
619 break;
620 }
621
622 *vpp = vp;
623
624 return (0);
625 }
626
627 struct ifid {
628 u_short ifid_len;
629 u_short ifid_pad;
630 int ifid_ino;
631 long ifid_start;
632 };
633
634 int
635 udf_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
636 {
637 struct ifid *ifhp;
638 struct vnode *nvp;
639 int error;
640
641 ifhp = (struct ifid *)fhp;
642
643 if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) {
644 *vpp = NULLVP;
645 return (error);
646 }
647
648 *vpp = nvp;
649
650 return (0);
651 }
652
653 int
654 udf_vptofh(struct vnode *vp, struct fid *fhp)
655 {
656 struct unode *up;
657 struct ifid *ifhp;
658
659 up = VTOU(vp);
660 ifhp = (struct ifid *)fhp;
661 ifhp->ifid_len = sizeof(struct ifid);
662 ifhp->ifid_ino = up->u_ino;
663
664 return (0);
665 }
666
667 int
668 udf_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
669 size_t newlen, struct proc *p)
670 {
671 return (EINVAL);
672 }
673
674 int
675 udf_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp,
676 struct ucred **credanonp)
677 {
678 return (EACCES);
679 }
680
681
682 int
683 udf_get_vpartmap(struct umount *ump, struct part_map_virt *pmv)
684 {
685 ump->um_flags |= UDF_MNT_FIND_VAT;
686 return (0);
687 }
688
689
690 int
691 udf_get_spartmap(struct umount *ump, struct part_map_spare *pms)
692 {
693 struct buf *bp;
694 int i, error;
695
696 ump->um_stbl = malloc(letoh32(pms->st_size), M_UDFMOUNT, M_NOWAIT);
697 if (ump->um_stbl == NULL)
698 return (ENOMEM);
699
700 bzero(ump->um_stbl, letoh32(pms->st_size));
701
702
703 ump->um_psecs = letoh16(pms->packet_len) / ump->um_bsize;
704
705 error = udf_readlblks(ump, letoh32(pms->st_loc[0]),
706 letoh32(pms->st_size), &bp);
707
708 if (error) {
709 if (bp != NULL)
710 brelse(bp);
711 free(ump->um_stbl, M_UDFMOUNT);
712 return (error);
713 }
714
715 bcopy(bp->b_data, ump->um_stbl, letoh32(pms->st_size));
716 brelse(bp);
717
718 if (udf_checktag(&ump->um_stbl->tag, 0)) {
719 free(ump->um_stbl, M_UDFMOUNT);
720 return (EINVAL);
721 }
722
723
724
725
726
727 for (i = 0; i < letoh16(ump->um_stbl->rt_l); i++) {
728 ump->um_stbl_len = i;
729 if (letoh32(ump->um_stbl->entries[i].org) >= 0xfffffff0)
730 break;
731 }
732
733 return (0);
734 }
735
736
737 int
738 udf_find_partmaps(struct umount *ump, struct logvol_desc *lvd)
739 {
740 struct regid *pmap_id;
741 unsigned char regid_id[UDF_REGID_ID_SIZE + 1];
742 int i, ptype, psize, error;
743 uint8_t *pmap = (uint8_t *) &lvd->maps[0];
744
745 for (i = 0; i < letoh32(lvd->n_pm); i++) {
746 ptype = pmap[0];
747 psize = pmap[1];
748
749 if (ptype != 1 && ptype != 2)
750 return (EINVAL);
751
752 if (psize != UDF_PMAP_TYPE1_SIZE &&
753 psize != UDF_PMAP_TYPE2_SIZE)
754 return (EINVAL);
755
756 if (ptype == 1) {
757 pmap += UDF_PMAP_TYPE1_SIZE;
758 continue;
759 }
760
761
762 pmap_id = (struct regid *) &pmap[4];
763 regid_id[UDF_REGID_ID_SIZE] = '\0';
764 bcopy(&pmap_id->id[0], ®id_id[0], UDF_REGID_ID_SIZE);
765
766 if (!bcmp(®id_id[0], "*UDF Virtual Partition",
767 UDF_REGID_ID_SIZE))
768 error = udf_get_vpartmap(ump,
769 (struct part_map_virt *) pmap);
770 else if (!bcmp(®id_id[0], "*UDF Sparable Partition",
771 UDF_REGID_ID_SIZE))
772 error = udf_get_spartmap(ump,
773 (struct part_map_spare *) pmap);
774 else
775 return (EINVAL);
776
777 if (error)
778 return (error);
779
780 pmap += UDF_PMAP_TYPE2_SIZE;
781 }
782
783 return (0);
784 }