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. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95
39 * $FreeBSD: src/sys/isofs/cd9660/cd9660_vfsops.c,v 1.74.2.7 2002/04/08 09:39:29 bde Exp $
40 * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_vfsops.c,v 1.46 2008/09/17 21:44:23 dillon Exp $
43 #include <sys/param.h>
44 #include <sys/systm.h>
47 #include <sys/nlookup.h>
48 #include <sys/kernel.h>
49 #include <sys/vnode.h>
50 #include <sys/mount.h>
54 #include <sys/fcntl.h>
55 #include <sys/malloc.h>
57 #include <sys/syslog.h>
58 #include <sys/iconv.h>
60 #include <vm/vm_zone.h>
64 #include "cd9660_node.h"
65 #include "cd9660_mount.h"
67 extern struct vop_ops cd9660_vnode_vops
;
68 extern struct vop_ops cd9660_spec_vops
;
69 extern struct vop_ops cd9660_fifo_vops
;
71 MALLOC_DEFINE(M_ISOFSMNT
, "ISOFS mount", "ISOFS mount structure");
72 MALLOC_DEFINE(M_ISOFSNODE
, "ISOFS node", "ISOFS vnode private part");
74 struct iconv_functions
*cd9660_iconv
= NULL
;
76 static int cd9660_mount (struct mount
*, char *, caddr_t
, struct ucred
*);
77 static int cd9660_unmount (struct mount
*, int);
78 static int cd9660_root (struct mount
*, struct vnode
**);
79 static int cd9660_statfs (struct mount
*, struct statfs
*, struct ucred
*);
80 static int cd9660_vget (struct mount
*, struct vnode
*, ino_t
, struct vnode
**);
81 static int cd9660_fhtovp (struct mount
*, struct vnode
*rootvp
,
82 struct fid
*, struct vnode
**);
83 static int cd9660_checkexp (struct mount
*, struct sockaddr
*,
84 int *, struct ucred
**);
85 static int cd9660_vptofh (struct vnode
*, struct fid
*);
87 static struct vfsops cd9660_vfsops
= {
88 .vfs_mount
= cd9660_mount
,
89 .vfs_unmount
= cd9660_unmount
,
90 .vfs_root
= cd9660_root
,
91 .vfs_statfs
= cd9660_statfs
,
92 .vfs_sync
= vfs_stdsync
,
93 .vfs_vget
= cd9660_vget
,
94 .vfs_fhtovp
= cd9660_fhtovp
,
95 .vfs_checkexp
= cd9660_checkexp
,
96 .vfs_vptofh
= cd9660_vptofh
,
97 .vfs_init
= cd9660_init
,
98 .vfs_uninit
= cd9660_uninit
,
100 VFS_SET(cd9660_vfsops
, cd9660
, VFCF_READONLY
);
101 MODULE_VERSION(cd9660
, 1);
105 * Called by vfs_mountroot when iso is going to be mounted as root.
108 static int iso_get_ssector (cdev_t dev
);
109 static int iso_mountfs (struct vnode
*devvp
, struct mount
*mp
,
110 struct iso_args
*argp
);
113 * Try to find the start of the last data track on this CD-ROM. This
114 * is used to mount the last session of a multi-session CD. Bail out
115 * and return 0 if we fail, this is always a safe bet.
118 iso_get_ssector(cdev_t dev
)
120 struct ioc_toc_header h
;
121 struct ioc_read_toc_single_entry t
;
124 if (dev_dioctl(dev
, CDIOREADTOCHEADER
, (caddr_t
)&h
, FREAD
,
125 proc0
.p_ucred
, NULL
) != 0)
128 for (i
= h
.ending_track
; i
>= 0; i
--) {
129 t
.address_format
= CD_LBA_FORMAT
;
131 if (dev_dioctl(dev
, CDIOREADTOCENTRY
, (caddr_t
)&t
, FREAD
,
132 proc0
.p_ucred
, NULL
) != 0) {
135 if ((t
.entry
.control
& 4) != 0)
136 /* found a data track */
143 return ntohl(t
.entry
.addr
.lba
);
147 iso_mountroot(struct mount
*mp
)
149 struct iso_args args
;
150 struct vnode
*rootvp
;
153 if ((error
= bdevvp(rootdev
, &rootvp
))) {
154 kprintf("iso_mountroot: can't find rootvp\n");
157 args
.flags
= ISOFSMNT_ROOT
;
159 vn_lock(rootvp
, LK_EXCLUSIVE
| LK_RETRY
);
160 error
= VOP_OPEN(rootvp
, FREAD
, FSCRED
, NULL
);
165 args
.ssector
= iso_get_ssector(rootdev
);
167 VOP_CLOSE(rootvp
, FREAD
);
170 kprintf("iso_mountroot(): using session at block %d\n",
172 if ((error
= iso_mountfs(rootvp
, mp
, &args
)) != 0)
175 cd9660_statfs(mp
, &mp
->mnt_stat
, proc0
.p_ucred
);
185 cd9660_mount(struct mount
*mp
, char *path
, caddr_t data
, struct ucred
*cred
)
188 struct iso_args args
;
192 struct iso_mnt
*imp
= 0;
193 struct nlookupdata nd
;
195 if ((mp
->mnt_flag
& (MNT_ROOTFS
|MNT_UPDATE
)) == MNT_ROOTFS
) {
196 return (iso_mountroot(mp
));
198 if ((error
= copyin(data
, (caddr_t
)&args
, sizeof (struct iso_args
))))
201 if ((mp
->mnt_flag
& MNT_RDONLY
) == 0)
205 * If updating, check whether changing from read-only to
206 * read/write; if there is no device name, that's all we do.
208 if (mp
->mnt_flag
& MNT_UPDATE
) {
209 imp
= VFSTOISOFS(mp
);
211 return (vfs_export(mp
, &imp
->im_export
, &args
.export
));
214 * Not an update, or updating the name: look up the name
215 * and verify that it refers to a sensible block device.
218 error
= nlookup_init(&nd
, args
.fspec
, UIO_USERSPACE
, NLC_FOLLOW
);
220 error
= nlookup(&nd
);
222 error
= cache_vref(&nd
.nl_nch
, nd
.nl_cred
, &devvp
);
227 if (!vn_isdisk(devvp
, &error
)) {
233 * Verify that user has necessary permissions on the device,
234 * or has superuser abilities
237 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
238 error
= VOP_EACCESS(devvp
, accessmode
, cred
);
240 error
= priv_check_cred(cred
, PRIV_ROOT
, 0);
247 if ((mp
->mnt_flag
& MNT_UPDATE
) == 0) {
248 error
= iso_mountfs(devvp
, mp
, &args
);
250 if (devvp
!= imp
->im_devvp
)
251 error
= EINVAL
; /* needs translation */
259 imp
= VFSTOISOFS(mp
);
260 copyinstr(args
.fspec
, mp
->mnt_stat
.f_mntfromname
, MNAMELEN
- 1,
262 bzero(mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
263 cd9660_statfs(mp
, &mp
->mnt_stat
, cred
);
268 * Common code for mount and mountroot
271 iso_mountfs(struct vnode
*devvp
, struct mount
*mp
, struct iso_args
*argp
)
273 struct iso_mnt
*isomp
= NULL
;
274 struct buf
*bp
= NULL
;
275 struct buf
*pribp
= NULL
, *supbp
= NULL
;
283 struct iso_volume_descriptor
*vdp
= 0;
284 struct iso_primary_descriptor
*pri
= NULL
;
285 struct iso_sierra_primary_descriptor
*pri_sierra
= NULL
;
286 struct iso_supplementary_descriptor
*sup
= NULL
;
287 struct iso_directory_record
*rootp
;
288 int logical_block_size
;
289 char cs_local
[ICONV_CSNMAXLEN
];
290 char cs_disk
[ICONV_CSNMAXLEN
];
292 if (!(mp
->mnt_flag
& MNT_RDONLY
))
296 * Disallow multiple mounts of the same device.
297 * Disallow mounting of a device that is currently in use
298 * Flush out any old buffers remaining from a previous use.
300 if ((error
= vfs_mountedon(devvp
)))
302 if (vcount(devvp
) > 0)
304 if ((error
= vinvalbuf(devvp
, V_SAVE
, 0, 0)))
307 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
308 error
= VOP_OPEN(devvp
, FREAD
, FSCRED
, NULL
);
313 if (dev
->si_iosize_max
!= 0)
314 mp
->mnt_iosize_max
= dev
->si_iosize_max
;
315 if (mp
->mnt_iosize_max
> MAXPHYS
)
316 mp
->mnt_iosize_max
= MAXPHYS
;
320 /* This is the "logical sector size". The standard says this
321 * should be 2048 or the physical sector size on the device,
322 * whichever is greater. For now, we'll just use a constant.
324 iso_bsize
= ISO_DEFAULT_BLOCK_SIZE
;
327 for (iso_blknum
= 16 + argp
->ssector
;
328 iso_blknum
< 100 + argp
->ssector
;
330 if ((error
= bread(devvp
, (off_t
)iso_blknum
* iso_bsize
,
331 iso_bsize
, &bp
)) != 0)
334 vdp
= (struct iso_volume_descriptor
*)bp
->b_data
;
335 if (bcmp (vdp
->id
, ISO_STANDARD_ID
, sizeof vdp
->id
) != 0) {
336 if (bcmp (vdp
->id_sierra
, ISO_SIERRA_ID
,
337 sizeof vdp
->id
) != 0) {
343 switch (isonum_711 (high_sierra
? vdp
->type_sierra
: vdp
->type
)){
348 pri
= (struct iso_primary_descriptor
*)vdp
;
350 (struct iso_sierra_primary_descriptor
*)vdp
;
354 case ISO_VD_SUPPLEMENTARY
:
358 sup
= (struct iso_supplementary_descriptor
*)vdp
;
360 if (!(argp
->flags
& ISOFSMNT_NOJOLIET
)) {
361 if (bcmp(sup
->escape
, "%/@", 3) == 0)
363 if (bcmp(sup
->escape
, "%/C", 3) == 0)
365 if (bcmp(sup
->escape
, "%/E", 3) == 0)
368 if ((isonum_711 (sup
->flags
) & 1) &&
369 (argp
->flags
& ISOFSMNT_BROKENJOLIET
) == 0)
398 isonum_723 (high_sierra
?
399 pri_sierra
->logical_block_size
:
400 pri
->logical_block_size
);
402 if (logical_block_size
< DEV_BSIZE
|| logical_block_size
> MAXBSIZE
403 || (logical_block_size
& (logical_block_size
- 1)) != 0) {
408 rootp
= (struct iso_directory_record
*)
410 pri_sierra
->root_directory_record
:
411 pri
->root_directory_record
);
413 isomp
= kmalloc(sizeof *isomp
, M_ISOFSMNT
, M_WAITOK
| M_ZERO
);
414 isomp
->logical_block_size
= logical_block_size
;
415 isomp
->volume_space_size
=
416 isonum_733 (high_sierra
?
417 pri_sierra
->volume_space_size
:
418 pri
->volume_space_size
);
419 isomp
->joliet_level
= 0;
421 * Since an ISO9660 multi-session CD can also access previous
422 * sessions, we have to include them into the space consider-
423 * ations. This doesn't yield a very accurate number since
424 * parts of the old sessions might be inaccessible now, but we
425 * can't do much better. This is also important for the NFS
426 * filehandle validation.
428 isomp
->volume_space_size
+= argp
->ssector
;
429 bcopy (rootp
, isomp
->root
, sizeof isomp
->root
);
430 isomp
->root_extent
= isonum_733 (rootp
->extent
);
431 isomp
->root_size
= isonum_733 (rootp
->size
);
433 isomp
->im_bmask
= logical_block_size
- 1;
434 isomp
->im_bshift
= ffs(logical_block_size
) - 1;
436 pribp
->b_flags
|= B_AGE
;
440 mp
->mnt_data
= (qaddr_t
)isomp
;
441 mp
->mnt_stat
.f_fsid
.val
[0] = dev2udev(dev
);
442 mp
->mnt_stat
.f_fsid
.val
[1] = mp
->mnt_vfc
->vfc_typenum
;
443 mp
->mnt_maxsymlinklen
= 0;
444 mp
->mnt_flag
|= MNT_LOCAL
;
445 isomp
->im_mountp
= mp
;
447 isomp
->im_devvp
= devvp
;
449 dev
->si_mountpoint
= mp
;
451 /* Check the Rock Ridge Extention support */
452 if (!(argp
->flags
& ISOFSMNT_NORRIP
)) {
453 if ((error
= bread(isomp
->im_devvp
,
454 lblktooff(isomp
, isomp
->root_extent
+ isonum_711(rootp
->ext_attr_length
)),
455 isomp
->logical_block_size
, &bp
)) != 0)
458 rootp
= (struct iso_directory_record
*)bp
->b_data
;
460 if ((isomp
->rr_skip
= cd9660_rrip_offset(rootp
,isomp
)) < 0) {
461 argp
->flags
|= ISOFSMNT_NORRIP
;
463 argp
->flags
&= ~ISOFSMNT_GENS
;
467 * The contents are valid,
468 * but they will get reread as part of another vnode, so...
470 bp
->b_flags
|= B_AGE
;
474 isomp
->im_flags
= argp
->flags
& (ISOFSMNT_NORRIP
| ISOFSMNT_GENS
|
475 ISOFSMNT_EXTATT
| ISOFSMNT_NOJOLIET
|
477 if (isomp
->im_flags
& ISOFSMNT_KICONV
&& cd9660_iconv
) {
478 bcopy(argp
->cs_local
, cs_local
, sizeof(cs_local
));
479 bcopy(argp
->cs_disk
, cs_disk
, sizeof(cs_disk
));
480 cd9660_iconv
->open(cs_local
, cs_disk
, &isomp
->im_d2l
);
481 cd9660_iconv
->open(cs_disk
, cs_local
, &isomp
->im_l2d
);
483 isomp
->im_d2l
= NULL
;
484 isomp
->im_l2d
= NULL
;
488 /* this effectively ignores all the mount flags */
489 log(LOG_INFO
, "cd9660: High Sierra Format\n");
490 isomp
->iso_ftype
= ISO_FTYPE_HIGH_SIERRA
;
492 switch (isomp
->im_flags
&(ISOFSMNT_NORRIP
|ISOFSMNT_GENS
)) {
494 isomp
->iso_ftype
= ISO_FTYPE_DEFAULT
;
496 case ISOFSMNT_GENS
|ISOFSMNT_NORRIP
:
497 isomp
->iso_ftype
= ISO_FTYPE_9660
;
500 log(LOG_INFO
, "cd9660: RockRidge Extension\n");
501 isomp
->iso_ftype
= ISO_FTYPE_RRIP
;
506 /* Decide whether to use the Joliet descriptor */
508 if (isomp
->iso_ftype
!= ISO_FTYPE_RRIP
&& joliet_level
) {
509 log(LOG_INFO
, "cd9660: Joliet Extension (Level %d)\n", joliet_level
);
510 rootp
= (struct iso_directory_record
*)
511 sup
->root_directory_record
;
512 bcopy (rootp
, isomp
->root
, sizeof isomp
->root
);
513 isomp
->root_extent
= isonum_733 (rootp
->extent
);
514 isomp
->root_size
= isonum_733 (rootp
->size
);
515 isomp
->joliet_level
= joliet_level
;
516 supbp
->b_flags
|= B_AGE
;
524 vfs_add_vnodeops(mp
, &cd9660_vnode_vops
, &mp
->mnt_vn_norm_ops
);
525 vfs_add_vnodeops(mp
, &cd9660_spec_vops
, &mp
->mnt_vn_spec_ops
);
526 vfs_add_vnodeops(mp
, &cd9660_fifo_vops
, &mp
->mnt_vn_fifo_ops
);
530 dev
->si_mountpoint
= NULL
;
538 VOP_CLOSE(devvp
, FREAD
);
540 kfree((caddr_t
)isomp
, M_ISOFSMNT
);
541 mp
->mnt_data
= (qaddr_t
)0;
547 * unmount system call
550 cd9660_unmount(struct mount
*mp
, int mntflags
)
552 struct iso_mnt
*isomp
;
553 int error
, flags
= 0;
555 if (mntflags
& MNT_FORCE
)
562 if ((error
= vflush(mp
, 0, flags
)))
565 isomp
= VFSTOISOFS(mp
);
567 if (isomp
->im_flags
& ISOFSMNT_KICONV
&& cd9660_iconv
) {
569 cd9660_iconv
->close(isomp
->im_d2l
);
571 cd9660_iconv
->close(isomp
->im_l2d
);
574 isomp
->im_devvp
->v_rdev
->si_mountpoint
= NULL
;
575 error
= VOP_CLOSE(isomp
->im_devvp
, FREAD
);
576 vrele(isomp
->im_devvp
);
577 kfree((caddr_t
)isomp
, M_ISOFSMNT
);
578 mp
->mnt_data
= (qaddr_t
)0;
579 mp
->mnt_flag
&= ~MNT_LOCAL
;
584 * Return root of a filesystem
587 cd9660_root(struct mount
*mp
, struct vnode
**vpp
)
589 struct iso_mnt
*imp
= VFSTOISOFS(mp
);
590 struct iso_directory_record
*dp
=
591 (struct iso_directory_record
*)imp
->root
;
592 ino_t ino
= isodirino(dp
, imp
);
595 * With RRIP we must use the `.' entry of the root directory.
596 * Simply tell vget, that it's a relocated directory.
598 return (cd9660_vget_internal(mp
, ino
, vpp
,
599 imp
->iso_ftype
== ISO_FTYPE_RRIP
, dp
));
603 * Get file system statistics.
606 cd9660_statfs(struct mount
*mp
, struct statfs
*sbp
, struct ucred
*cred
)
608 struct iso_mnt
*isomp
;
610 isomp
= VFSTOISOFS(mp
);
612 sbp
->f_bsize
= isomp
->logical_block_size
;
613 sbp
->f_iosize
= sbp
->f_bsize
; /* XXX */
614 sbp
->f_blocks
= isomp
->volume_space_size
;
615 sbp
->f_bfree
= 0; /* total free blocks */
616 sbp
->f_bavail
= 0; /* blocks free for non superuser */
617 sbp
->f_files
= 0; /* total files */
618 sbp
->f_ffree
= 0; /* free file nodes */
619 if (sbp
!= &mp
->mnt_stat
) {
620 sbp
->f_type
= mp
->mnt_vfc
->vfc_typenum
;
621 bcopy(mp
->mnt_stat
.f_mntfromname
, sbp
->f_mntfromname
, MNAMELEN
);
627 * File handle to vnode
629 * Have to be really careful about stale file handles:
630 * - check that the inode number is in range
631 * - call iget() to get the locked inode
632 * - check for an unallocated inode (i_mode == 0)
633 * - check that the generation number matches
645 cd9660_fhtovp(struct mount
*mp
, struct vnode
*rootvp
,
646 struct fid
*fhp
, struct vnode
**vpp
)
648 struct ifid
*ifhp
= (struct ifid
*)fhp
;
654 kprintf("fhtovp: ino %d, start %ld\n",
655 ifhp
->ifid_ino
, ifhp
->ifid_start
);
658 if ((error
= VFS_VGET(mp
, NULL
, ifhp
->ifid_ino
, &nvp
)) != 0) {
663 if (ip
->inode
.iso_mode
== 0) {
673 cd9660_checkexp(struct mount
*mp
, struct sockaddr
*nam
, int *exflagsp
,
674 struct ucred
**credanonp
)
679 imp
= VFSTOISOFS(mp
);
682 * Get the export permission structure for this <mp, client> tuple.
684 np
= vfs_export_lookup(mp
, &imp
->im_export
, nam
);
688 *exflagsp
= np
->netc_exflags
;
689 *credanonp
= &np
->netc_anon
;
694 cd9660_vget(struct mount
*mp
, struct vnode
*dvp
, ino_t ino
, struct vnode
**vpp
)
699 * It would be nice if we didn't always set the `relocated' flag
700 * and force the extra read, but I don't want to think about fixing
703 return (cd9660_vget_internal(mp
, ino
, vpp
,
705 VFSTOISOFS(mp
)->iso_ftype
== ISO_FTYPE_RRIP
,
713 cd9660_vget_internal(struct mount
*mp
, ino_t ino
, struct vnode
**vpp
,
714 int relocated
, struct iso_directory_record
*isodir
)
723 imp
= VFSTOISOFS(mp
);
726 if ((*vpp
= cd9660_ihashget(dev
, ino
)) != NULLVP
)
729 /* Allocate a new vnode/iso_node. */
730 error
= getnewvnode(VT_ISOFS
, mp
, &vp
, 0, 0);
735 MALLOC(ip
, struct iso_node
*, sizeof(struct iso_node
), M_ISOFSNODE
,
742 * Insert it into the inode hash table and check for a collision.
743 * If a collision occurs, throw away the vnode and try again.
745 if (cd9660_ihashins(ip
) != 0) {
746 kprintf("debug: cd9660 ihashins collision, retrying\n");
748 kfree(ip
, M_ISOFSNODE
);
753 if (isodir
== NULL
) {
756 lbn
= lblkno(imp
, ino
);
757 if (lbn
>= imp
->volume_space_size
) {
759 kprintf("fhtovp: lbn exceed volume space %d\n", lbn
);
763 off
= blkoff(imp
, ino
);
764 if (off
+ ISO_DIRECTORY_RECORD_SIZE
> imp
->logical_block_size
) {
766 kprintf("fhtovp: crosses block boundary %d\n",
767 off
+ ISO_DIRECTORY_RECORD_SIZE
);
771 error
= bread(imp
->im_devvp
,
773 imp
->logical_block_size
, &bp
);
777 kprintf("fhtovp: bread error %d\n",error
);
780 isodir
= (struct iso_directory_record
*)(bp
->b_data
+ off
);
782 if (off
+ isonum_711(isodir
->length
) >
783 imp
->logical_block_size
) {
787 kprintf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
788 off
+isonum_711(isodir
->length
), off
,
789 isonum_711(isodir
->length
));
794 if (isonum_733(isodir
->extent
) +
795 isonum_711(isodir
->ext_attr_length
) != ifhp
->ifid_start
) {
798 kprintf("fhtovp: file start miss %d vs %d\n",
799 isonum_733(isodir
->extent
) + isonum_711(isodir
->ext_attr_length
),
808 ip
->i_devvp
= imp
->im_devvp
;
813 * On relocated directories we must
814 * read the `.' entry out of a dir.
816 ip
->iso_start
= ino
>> imp
->im_bshift
;
819 if ((error
= cd9660_devblkatoff(vp
, (off_t
)0, NULL
, &bp
)) != 0) {
823 isodir
= (struct iso_directory_record
*)bp
->b_data
;
826 ip
->iso_extent
= isonum_733(isodir
->extent
);
827 ip
->i_size
= isonum_733(isodir
->size
);
828 ip
->iso_start
= isonum_711(isodir
->ext_attr_length
) + ip
->iso_extent
;
831 * Setup time stamp, attribute
834 switch (imp
->iso_ftype
) {
835 default: /* ISO_FTYPE_9660 */
839 if ((imp
->im_flags
& ISOFSMNT_EXTATT
)
840 && (off
= isonum_711(isodir
->ext_attr_length
)))
841 cd9660_devblkatoff(vp
, (off_t
)-(off
<< imp
->im_bshift
), NULL
,
845 cd9660_defattr(isodir
, ip
, bp2
, ISO_FTYPE_9660
);
846 cd9660_deftstamp(isodir
, ip
, bp2
, ISO_FTYPE_9660
);
852 cd9660_rrip_analyze(isodir
, ip
, imp
);
860 * Initialize the associated vnode
862 vp
->v_type
= IFTOVT(ip
->inode
.iso_mode
);
864 switch (vp
->v_type
) {
866 vp
->v_ops
= &mp
->mnt_vn_fifo_ops
;
870 vp
->v_ops
= &mp
->mnt_vn_spec_ops
;
871 addaliasu(vp
, umajor(ip
->inode
.iso_rdev
),
872 uminor(ip
->inode
.iso_rdev
));
876 vinitvmio(vp
, ip
->i_size
, PAGE_SIZE
, -1);
882 if (ip
->iso_extent
== imp
->root_extent
)
883 vsetflags(vp
, VROOT
);
886 * Return the locked and refd vp
893 * Vnode pointer to File handle
897 cd9660_vptofh(struct vnode
*vp
, struct fid
*fhp
)
899 struct iso_node
*ip
= VTOI(vp
);
902 ifhp
= (struct ifid
*)fhp
;
903 ifhp
->ifid_len
= sizeof(struct ifid
);
905 ifhp
->ifid_ino
= ip
->i_number
;
906 ifhp
->ifid_start
= ip
->iso_start
;
909 kprintf("vptofh: ino %d, start %ld\n",
910 ifhp
->ifid_ino
,ifhp
->ifid_start
);