3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley
6 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
7 * Support code is derived from software contributed to Berkeley
8 * by Atsushi Murai (amurai@spec.co.jp).
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95
35 * $FreeBSD: src/sys/isofs/cd9660/cd9660_vfsops.c,v 1.74.2.7 2002/04/08 09:39:29 bde Exp $
38 #include <sys/param.h>
39 #include <sys/systm.h>
42 #include <sys/nlookup.h>
43 #include <sys/kernel.h>
44 #include <sys/vnode.h>
45 #include <sys/mount.h>
49 #include <sys/fcntl.h>
50 #include <sys/malloc.h>
52 #include <sys/syslog.h>
53 #include <sys/iconv.h>
55 #include <vm/vm_zone.h>
61 #include "cd9660_node.h"
62 #include "cd9660_mount.h"
64 extern struct vop_ops cd9660_vnode_vops
;
65 extern struct vop_ops cd9660_spec_vops
;
66 extern struct vop_ops cd9660_fifo_vops
;
68 MALLOC_DEFINE(M_ISOFSMNT
, "ISOFS mount", "ISOFS mount structure");
69 MALLOC_DEFINE(M_ISOFSNODE
, "ISOFS node", "ISOFS vnode private part");
71 struct iconv_functions
*cd9660_iconv
= NULL
;
73 static int cd9660_mount(struct mount
*, char *, caddr_t
, struct ucred
*);
74 static int cd9660_unmount(struct mount
*, int);
75 static int cd9660_root(struct mount
*, struct vnode
**);
76 static int cd9660_statfs(struct mount
*, struct statfs
*, struct ucred
*);
77 static int cd9660_vget(struct mount
*, struct vnode
*, ino_t
, struct vnode
**);
78 static int cd9660_fhtovp(struct mount
*, struct vnode
*rootvp
,
79 struct fid
*, struct vnode
**);
80 static int cd9660_checkexp(struct mount
*, struct sockaddr
*,
81 int *, struct ucred
**);
82 static int cd9660_vptofh (struct vnode
*, struct fid
*);
84 static struct vfsops cd9660_vfsops
= {
86 .vfs_mount
= cd9660_mount
,
87 .vfs_unmount
= cd9660_unmount
,
88 .vfs_root
= cd9660_root
,
89 .vfs_statfs
= cd9660_statfs
,
90 .vfs_vget
= cd9660_vget
,
91 .vfs_fhtovp
= cd9660_fhtovp
,
92 .vfs_checkexp
= cd9660_checkexp
,
93 .vfs_vptofh
= cd9660_vptofh
,
94 .vfs_init
= cd9660_init
,
95 .vfs_uninit
= cd9660_uninit
,
97 VFS_SET(cd9660_vfsops
, cd9660
, VFCF_READONLY
);
98 MODULE_VERSION(cd9660
, 1);
102 * Called by vfs_mountroot when iso is going to be mounted as root.
105 static int iso_get_ssector(cdev_t dev
);
106 static int iso_mountfs(struct vnode
*devvp
, struct mount
*mp
,
107 struct iso_args
*argp
);
110 * Try to find the start of the last data track on this CD-ROM. This
111 * is used to mount the last session of a multi-session CD. Bail out
112 * and return 0 if we fail, this is always a safe bet.
115 iso_get_ssector(cdev_t dev
)
117 struct ioc_toc_header h
;
118 struct ioc_read_toc_single_entry t
;
121 if (dev_dioctl(dev
, CDIOREADTOCHEADER
, (caddr_t
)&h
, FREAD
,
122 proc0
.p_ucred
, NULL
, NULL
) != 0)
125 for (i
= h
.ending_track
; i
>= 0; i
--) {
126 t
.address_format
= CD_LBA_FORMAT
;
128 if (dev_dioctl(dev
, CDIOREADTOCENTRY
, (caddr_t
)&t
, FREAD
,
129 proc0
.p_ucred
, NULL
, NULL
) != 0) {
132 if ((t
.entry
.control
& 4) != 0)
133 /* found a data track */
140 return ntohl(t
.entry
.addr
.lba
);
144 iso_mountroot(struct mount
*mp
)
146 struct iso_args args
;
147 struct vnode
*rootvp
;
150 if ((error
= bdevvp(rootdev
, &rootvp
))) {
151 kprintf("iso_mountroot: can't find rootvp\n");
154 args
.flags
= ISOFSMNT_ROOT
;
156 vn_lock(rootvp
, LK_EXCLUSIVE
| LK_RETRY
);
157 error
= VOP_OPEN(rootvp
, FREAD
, FSCRED
, NULL
);
162 args
.ssector
= iso_get_ssector(rootdev
);
164 vn_lock(rootvp
, LK_EXCLUSIVE
| LK_RETRY
);
165 VOP_CLOSE(rootvp
, FREAD
, NULL
);
169 kprintf("iso_mountroot(): using session at block %d\n",
171 if ((error
= iso_mountfs(rootvp
, mp
, &args
)) != 0)
174 cd9660_statfs(mp
, &mp
->mnt_stat
, proc0
.p_ucred
);
184 cd9660_mount(struct mount
*mp
, char *path
, caddr_t data
, struct ucred
*cred
)
187 struct iso_args args
;
191 struct iso_mnt
*imp
= NULL
;
192 struct nlookupdata nd
;
194 if ((mp
->mnt_flag
& (MNT_ROOTFS
|MNT_UPDATE
)) == MNT_ROOTFS
) {
195 return (iso_mountroot(mp
));
197 if ((error
= copyin(data
, (caddr_t
)&args
, sizeof (struct iso_args
))))
200 if ((mp
->mnt_flag
& MNT_RDONLY
) == 0)
204 * If updating, check whether changing from read-only to
205 * read/write; if there is no device name, that's all we do.
207 if (mp
->mnt_flag
& MNT_UPDATE
) {
208 imp
= VFSTOISOFS(mp
);
209 if (args
.fspec
== NULL
)
210 return (vfs_export(mp
, &imp
->im_export
, &args
.export
));
213 * Not an update, or updating the name: look up the name
214 * and verify that it refers to a sensible block device.
217 error
= nlookup_init(&nd
, args
.fspec
, UIO_USERSPACE
, NLC_FOLLOW
);
219 error
= nlookup(&nd
);
221 error
= cache_vref(&nd
.nl_nch
, nd
.nl_cred
, &devvp
);
226 if (!vn_isdisk(devvp
, &error
)) {
232 * Verify that user has necessary permissions on the device,
233 * or has superuser abilities
236 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
237 error
= VOP_EACCESS(devvp
, accessmode
, cred
);
239 error
= caps_priv_check(cred
, SYSCAP_RESTRICTEDROOT
);
246 if ((mp
->mnt_flag
& MNT_UPDATE
) == 0) {
247 error
= iso_mountfs(devvp
, mp
, &args
);
249 if (devvp
!= imp
->im_devvp
)
250 error
= EINVAL
; /* needs translation */
258 imp
= VFSTOISOFS(mp
);
259 copyinstr(args
.fspec
, mp
->mnt_stat
.f_mntfromname
, MNAMELEN
- 1,
261 bzero(mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
262 cd9660_statfs(mp
, &mp
->mnt_stat
, cred
);
267 * Common code for mount and mountroot
270 iso_mountfs(struct vnode
*devvp
, struct mount
*mp
, struct iso_args
*argp
)
272 struct iso_mnt
*isomp
= NULL
;
273 struct buf
*bp
= NULL
;
274 struct buf
*pribp
= NULL
, *supbp
= NULL
;
282 struct iso_volume_descriptor
*vdp
= NULL
;
283 struct iso_primary_descriptor
*pri
= NULL
;
284 struct iso_sierra_primary_descriptor
*pri_sierra
= NULL
;
285 struct iso_supplementary_descriptor
*sup
= NULL
;
286 struct iso_directory_record
*rootp
;
287 int logical_block_size
;
288 char cs_local
[ICONV_CSNMAXLEN
];
289 char cs_disk
[ICONV_CSNMAXLEN
];
291 if (!(mp
->mnt_flag
& MNT_RDONLY
))
295 * Disallow multiple mounts of the same device.
296 * Disallow mounting of a device that is currently in use
297 * Flush out any old buffers remaining from a previous use.
299 if ((error
= vfs_mountedon(devvp
)))
301 if (vcount(devvp
) > 0)
303 if ((error
= vinvalbuf(devvp
, V_SAVE
, 0, 0)))
306 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
307 error
= VOP_OPEN(devvp
, FREAD
, FSCRED
, NULL
);
312 if (dev
->si_iosize_max
!= 0)
313 mp
->mnt_iosize_max
= dev
->si_iosize_max
;
314 if (mp
->mnt_iosize_max
> MAXPHYS
)
315 mp
->mnt_iosize_max
= MAXPHYS
;
319 /* This is the "logical sector size". The standard says this
320 * should be 2048 or the physical sector size on the device,
321 * whichever is greater. For now, we'll just use a constant.
323 iso_bsize
= ISO_DEFAULT_BLOCK_SIZE
;
326 for (iso_blknum
= 16 + argp
->ssector
;
327 iso_blknum
< 100 + argp
->ssector
;
329 if ((error
= bread(devvp
, (off_t
)iso_blknum
* iso_bsize
,
330 iso_bsize
, &bp
)) != 0)
333 vdp
= (struct iso_volume_descriptor
*)bp
->b_data
;
334 if (bcmp (vdp
->id
, ISO_STANDARD_ID
, sizeof vdp
->id
) != 0) {
335 if (bcmp (vdp
->id_sierra
, ISO_SIERRA_ID
,
336 sizeof vdp
->id
) != 0) {
342 switch (isonum_711 (high_sierra
? vdp
->type_sierra
: vdp
->type
)){
347 pri
= (struct iso_primary_descriptor
*)vdp
;
349 (struct iso_sierra_primary_descriptor
*)vdp
;
353 case ISO_VD_SUPPLEMENTARY
:
357 sup
= (struct iso_supplementary_descriptor
*)vdp
;
359 if (!(argp
->flags
& ISOFSMNT_NOJOLIET
)) {
360 if (bcmp(sup
->escape
, "%/@", 3) == 0)
362 if (bcmp(sup
->escape
, "%/C", 3) == 0)
364 if (bcmp(sup
->escape
, "%/E", 3) == 0)
367 if ((isonum_711 (sup
->flags
) & 1) &&
368 (argp
->flags
& ISOFSMNT_BROKENJOLIET
) == 0)
397 isonum_723 (high_sierra
?
398 pri_sierra
->logical_block_size
:
399 pri
->logical_block_size
);
401 if (logical_block_size
< DEV_BSIZE
|| logical_block_size
> MAXBSIZE
402 || (logical_block_size
& (logical_block_size
- 1)) != 0) {
407 rootp
= (struct iso_directory_record
*)
409 pri_sierra
->root_directory_record
:
410 pri
->root_directory_record
);
412 isomp
= kmalloc(sizeof *isomp
, M_ISOFSMNT
, M_WAITOK
| M_ZERO
);
413 isomp
->logical_block_size
= logical_block_size
;
414 isomp
->volume_space_size
=
415 isonum_733 (high_sierra
?
416 pri_sierra
->volume_space_size
:
417 pri
->volume_space_size
);
418 isomp
->joliet_level
= 0;
420 * Since an ISO9660 multi-session CD can also access previous
421 * sessions, we have to include them into the space consider-
422 * ations. This doesn't yield a very accurate number since
423 * parts of the old sessions might be inaccessible now, but we
424 * can't do much better. This is also important for the NFS
425 * filehandle validation.
427 isomp
->volume_space_size
+= argp
->ssector
;
428 bcopy (rootp
, isomp
->root
, sizeof isomp
->root
);
429 isomp
->root_extent
= isonum_733 (rootp
->extent
);
430 isomp
->root_size
= isonum_733 (rootp
->size
);
432 isomp
->im_bmask
= logical_block_size
- 1;
433 isomp
->im_bshift
= ffs(logical_block_size
) - 1;
435 pribp
->b_flags
|= B_AGE
;
439 mp
->mnt_data
= (qaddr_t
)isomp
;
440 mp
->mnt_stat
.f_fsid
.val
[0] = devid_from_dev(dev
);
441 mp
->mnt_stat
.f_fsid
.val
[1] = mp
->mnt_vfc
->vfc_typenum
;
442 mp
->mnt_maxsymlinklen
= 0;
443 mp
->mnt_flag
|= MNT_LOCAL
;
444 isomp
->im_mountp
= mp
;
446 isomp
->im_devvp
= devvp
;
448 dev
->si_mountpoint
= mp
;
450 if (argp
->flags
& ISOFSMNT_UID
)
451 isomp
->im_uid
= argp
->uid
;
452 if (argp
->flags
& ISOFSMNT_GID
)
453 isomp
->im_gid
= argp
->gid
;
454 isomp
->im_fmask
= argp
->fmask
& ACCESSPERMS
;
455 isomp
->im_dmask
= argp
->dmask
& ACCESSPERMS
;
457 /* Check the Rock Ridge Extension support */
458 if (!(argp
->flags
& ISOFSMNT_NORRIP
)) {
459 if ((error
= bread(isomp
->im_devvp
,
460 lblktooff(isomp
, isomp
->root_extent
+ isonum_711(rootp
->ext_attr_length
)),
461 isomp
->logical_block_size
, &bp
)) != 0)
464 rootp
= (struct iso_directory_record
*)bp
->b_data
;
466 if ((isomp
->rr_skip
= cd9660_rrip_offset(rootp
,isomp
)) < 0) {
467 argp
->flags
|= ISOFSMNT_NORRIP
;
469 argp
->flags
&= ~ISOFSMNT_GENS
;
473 * The contents are valid,
474 * but they will get reread as part of another vnode, so...
476 bp
->b_flags
|= B_AGE
;
480 isomp
->im_flags
= argp
->flags
& (ISOFSMNT_NORRIP
| ISOFSMNT_GENS
|
481 ISOFSMNT_EXTATT
| ISOFSMNT_NOJOLIET
|
483 ISOFSMNT_UID
| ISOFSMNT_GID
);
485 if (isomp
->im_flags
& ISOFSMNT_KICONV
&& cd9660_iconv
) {
486 bcopy(argp
->cs_local
, cs_local
, sizeof(cs_local
));
487 bcopy(argp
->cs_disk
, cs_disk
, sizeof(cs_disk
));
488 cd9660_iconv
->open(cs_local
, cs_disk
, &isomp
->im_d2l
);
489 cd9660_iconv
->open(cs_disk
, cs_local
, &isomp
->im_l2d
);
491 isomp
->im_d2l
= NULL
;
492 isomp
->im_l2d
= NULL
;
496 /* this effectively ignores all the mount flags */
497 log(LOG_INFO
, "cd9660: High Sierra Format\n");
498 isomp
->iso_ftype
= ISO_FTYPE_HIGH_SIERRA
;
500 switch (isomp
->im_flags
&(ISOFSMNT_NORRIP
|ISOFSMNT_GENS
)) {
502 isomp
->iso_ftype
= ISO_FTYPE_DEFAULT
;
504 case ISOFSMNT_GENS
|ISOFSMNT_NORRIP
:
505 isomp
->iso_ftype
= ISO_FTYPE_9660
;
508 log(LOG_INFO
, "cd9660: RockRidge Extension\n");
509 isomp
->iso_ftype
= ISO_FTYPE_RRIP
;
514 /* Decide whether to use the Joliet descriptor */
516 if (isomp
->iso_ftype
!= ISO_FTYPE_RRIP
&& joliet_level
) {
517 log(LOG_INFO
, "cd9660: Joliet Extension (Level %d)\n", joliet_level
);
518 rootp
= (struct iso_directory_record
*)
519 sup
->root_directory_record
;
520 bcopy (rootp
, isomp
->root
, sizeof isomp
->root
);
521 isomp
->root_extent
= isonum_733 (rootp
->extent
);
522 isomp
->root_size
= isonum_733 (rootp
->size
);
523 isomp
->joliet_level
= joliet_level
;
524 supbp
->b_flags
|= B_AGE
;
532 vfs_add_vnodeops(mp
, &cd9660_vnode_vops
, &mp
->mnt_vn_norm_ops
);
533 vfs_add_vnodeops(mp
, &cd9660_spec_vops
, &mp
->mnt_vn_spec_ops
);
534 vfs_add_vnodeops(mp
, &cd9660_fifo_vops
, &mp
->mnt_vn_fifo_ops
);
538 dev
->si_mountpoint
= NULL
;
546 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
547 VOP_CLOSE(devvp
, FREAD
, NULL
);
551 kfree((caddr_t
)isomp
, M_ISOFSMNT
);
552 mp
->mnt_data
= (qaddr_t
)0;
558 * unmount system call
561 cd9660_unmount(struct mount
*mp
, int mntflags
)
563 struct iso_mnt
*isomp
;
564 int error
, flags
= 0;
566 if (mntflags
& MNT_FORCE
)
573 if ((error
= vflush(mp
, 0, flags
)))
576 isomp
= VFSTOISOFS(mp
);
578 if (isomp
->im_flags
& ISOFSMNT_KICONV
&& cd9660_iconv
) {
580 cd9660_iconv
->close(isomp
->im_d2l
);
582 cd9660_iconv
->close(isomp
->im_l2d
);
585 isomp
->im_devvp
->v_rdev
->si_mountpoint
= NULL
;
586 vn_lock(isomp
->im_devvp
, LK_EXCLUSIVE
| LK_RETRY
);
587 error
= VOP_CLOSE(isomp
->im_devvp
, FREAD
, NULL
);
588 vn_unlock(isomp
->im_devvp
);
589 vrele(isomp
->im_devvp
);
590 kfree((caddr_t
)isomp
, M_ISOFSMNT
);
591 mp
->mnt_data
= (qaddr_t
)0;
592 mp
->mnt_flag
&= ~MNT_LOCAL
;
597 * Return root of a filesystem
600 cd9660_root(struct mount
*mp
, struct vnode
**vpp
)
602 struct iso_mnt
*imp
= VFSTOISOFS(mp
);
603 struct iso_directory_record
*dp
=
604 (struct iso_directory_record
*)imp
->root
;
605 ino_t ino
= isodirino(dp
, imp
);
608 * With RRIP we must use the `.' entry of the root directory.
609 * Simply tell vget, that it's a relocated directory.
611 return (cd9660_vget_internal(mp
, ino
, vpp
,
612 imp
->iso_ftype
== ISO_FTYPE_RRIP
, dp
));
616 * Get filesystem statistics.
619 cd9660_statfs(struct mount
*mp
, struct statfs
*sbp
, struct ucred
*cred
)
621 struct iso_mnt
*isomp
;
623 isomp
= VFSTOISOFS(mp
);
625 sbp
->f_bsize
= isomp
->logical_block_size
;
626 sbp
->f_iosize
= sbp
->f_bsize
; /* XXX */
627 sbp
->f_blocks
= isomp
->volume_space_size
;
628 sbp
->f_bfree
= 0; /* total free blocks */
629 sbp
->f_bavail
= 0; /* blocks free for non superuser */
630 sbp
->f_files
= 0; /* total files */
631 sbp
->f_ffree
= 0; /* free file nodes */
632 if (sbp
!= &mp
->mnt_stat
) {
633 sbp
->f_type
= mp
->mnt_vfc
->vfc_typenum
;
634 bcopy(mp
->mnt_stat
.f_mntfromname
, sbp
->f_mntfromname
, MNAMELEN
);
640 * File handle to vnode
642 * Have to be really careful about stale file handles:
643 * - check that the inode number is in range
644 * - call iget() to get the locked inode
645 * - check for an unallocated inode (i_mode == 0)
646 * - check that the generation number matches
658 cd9660_fhtovp(struct mount
*mp
, struct vnode
*rootvp
,
659 struct fid
*fhp
, struct vnode
**vpp
)
661 struct ifid
*ifhp
= (struct ifid
*)fhp
;
667 kprintf("fhtovp: ino %d, start %ld\n",
668 ifhp
->ifid_ino
, ifhp
->ifid_start
);
671 if ((error
= VFS_VGET(mp
, NULL
, ifhp
->ifid_ino
, &nvp
)) != 0) {
676 if (ip
->inode
.iso_mode
== 0) {
686 cd9660_checkexp(struct mount
*mp
, struct sockaddr
*nam
, int *exflagsp
,
687 struct ucred
**credanonp
)
692 imp
= VFSTOISOFS(mp
);
695 * Get the export permission structure for this <mp, client> tuple.
697 np
= vfs_export_lookup(mp
, &imp
->im_export
, nam
);
701 *exflagsp
= np
->netc_exflags
;
702 *credanonp
= &np
->netc_anon
;
707 cd9660_vget(struct mount
*mp
, struct vnode
*dvp
, ino_t ino
, struct vnode
**vpp
)
712 * It would be nice if we didn't always set the `relocated' flag
713 * and force the extra read, but I don't want to think about fixing
716 return (cd9660_vget_internal(mp
, ino
, vpp
,
718 VFSTOISOFS(mp
)->iso_ftype
== ISO_FTYPE_RRIP
,
726 cd9660_vget_internal(struct mount
*mp
, ino_t ino
, struct vnode
**vpp
,
727 int relocated
, struct iso_directory_record
*isodir
)
736 imp
= VFSTOISOFS(mp
);
739 if ((*vpp
= cd9660_ihashget(dev
, ino
)) != NULLVP
)
742 /* Allocate a new vnode/iso_node. */
743 error
= getnewvnode(VT_ISOFS
, mp
, &vp
, 0, 0);
748 ip
= kmalloc(sizeof(struct iso_node
), M_ISOFSNODE
, M_WAITOK
| M_ZERO
);
754 * Insert it into the inode hash table and check for a collision.
755 * If a collision occurs, throw away the vnode and try again.
757 if (cd9660_ihashins(ip
) != 0) {
758 kprintf("debug: cd9660 ihashins collision, retrying\n");
760 kfree(ip
, M_ISOFSNODE
);
765 if (isodir
== NULL
) {
768 lbn
= lblkno(imp
, ino
);
769 if (lbn
>= imp
->volume_space_size
) {
771 kprintf("fhtovp: lbn exceed volume space %d\n", lbn
);
775 off
= blkoff(imp
, ino
);
776 if (off
+ ISO_DIRECTORY_RECORD_SIZE
> imp
->logical_block_size
) {
778 kprintf("fhtovp: crosses block boundary %d\n",
779 off
+ ISO_DIRECTORY_RECORD_SIZE
);
783 error
= bread(imp
->im_devvp
,
785 imp
->logical_block_size
, &bp
);
789 kprintf("fhtovp: bread error %d\n",error
);
792 isodir
= (struct iso_directory_record
*)(bp
->b_data
+ off
);
794 if (off
+ isonum_711(isodir
->length
) >
795 imp
->logical_block_size
) {
799 kprintf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
800 off
+isonum_711(isodir
->length
), off
,
801 isonum_711(isodir
->length
));
806 if (isonum_733(isodir
->extent
) +
807 isonum_711(isodir
->ext_attr_length
) != ifhp
->ifid_start
) {
810 kprintf("fhtovp: file start miss %d vs %d\n",
811 isonum_733(isodir
->extent
) + isonum_711(isodir
->ext_attr_length
),
820 ip
->i_devvp
= imp
->im_devvp
;
825 * On relocated directories we must
826 * read the `.' entry out of a dir.
828 ip
->iso_start
= ino
>> imp
->im_bshift
;
831 if ((error
= cd9660_devblkatoff(vp
, (off_t
)0, NULL
, &bp
)) != 0) {
835 isodir
= (struct iso_directory_record
*)bp
->b_data
;
838 ip
->iso_extent
= isonum_733(isodir
->extent
);
839 ip
->i_size
= isonum_733(isodir
->size
);
840 ip
->iso_start
= isonum_711(isodir
->ext_attr_length
) + ip
->iso_extent
;
843 * Setup time stamp, attribute
846 switch (imp
->iso_ftype
) {
847 default: /* ISO_FTYPE_9660 */
851 if ((imp
->im_flags
& ISOFSMNT_EXTATT
)
852 && (off
= isonum_711(isodir
->ext_attr_length
)))
853 cd9660_devblkatoff(vp
, (off_t
)-(off
<< imp
->im_bshift
), NULL
,
857 cd9660_defattr(isodir
, ip
, bp2
, ISO_FTYPE_9660
);
858 cd9660_deftstamp(isodir
, ip
, bp2
, ISO_FTYPE_9660
);
864 cd9660_rrip_analyze(isodir
, ip
, imp
);
872 * Initialize the associated vnode
874 vp
->v_type
= IFTOVT(ip
->inode
.iso_mode
);
876 switch (vp
->v_type
) {
878 vp
->v_ops
= &mp
->mnt_vn_fifo_ops
;
882 vp
->v_ops
= &mp
->mnt_vn_spec_ops
;
883 addaliasu(vp
, umajor(ip
->inode
.iso_rdev
),
884 uminor(ip
->inode
.iso_rdev
));
888 vinitvmio(vp
, ip
->i_size
, PAGE_SIZE
, -1);
894 if (ip
->iso_extent
== imp
->root_extent
)
895 vsetflags(vp
, VROOT
);
898 * Return the locked and refd vp
906 * Vnode pointer to File handle
910 cd9660_vptofh(struct vnode
*vp
, struct fid
*fhp
)
912 struct iso_node
*ip
= VTOI(vp
);
915 ifhp
= (struct ifid
*)fhp
;
916 ifhp
->ifid_len
= sizeof(struct ifid
);
918 ifhp
->ifid_ino
= ip
->i_number
;
919 ifhp
->ifid_start
= ip
->iso_start
;
922 kprintf("vptofh: ino %d, start %ld\n",
923 ifhp
->ifid_ino
,ifhp
->ifid_start
);