1 /* $NetBSD: cd9660_vfsops.c,v 1.68 2009/10/19 17:53:36 tsutsui Exp $ */
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley
8 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
9 * Support code is derived from software contributed to Berkeley
10 * by Atsushi Murai (amurai@spec.co.jp).
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: cd9660_vfsops.c,v 1.68 2009/10/19 17:53:36 tsutsui Exp $");
42 #if defined(_KERNEL_OPT)
43 #include "opt_compat_netbsd.h"
46 #include <sys/param.h>
47 #include <sys/sysctl.h>
48 #include <sys/systm.h>
49 #include <sys/namei.h>
51 #include <sys/kernel.h>
52 #include <sys/vnode.h>
53 #include <miscfs/genfs/genfs.h>
54 #include <miscfs/specfs/specdev.h>
55 #include <sys/mount.h>
58 #include <sys/disklabel.h>
59 #include <sys/device.h>
60 #include <sys/ioctl.h>
62 #include <sys/errno.h>
63 #include <sys/malloc.h>
67 #include <sys/dirent.h>
68 #include <sys/kauth.h>
69 #include <sys/module.h>
71 #include <fs/cd9660/iso.h>
72 #include <fs/cd9660/cd9660_extern.h>
73 #include <fs/cd9660/iso_rrip.h>
74 #include <fs/cd9660/cd9660_node.h>
75 #include <fs/cd9660/cd9660_mount.h>
77 MODULE(MODULE_CLASS_VFS
, cd9660
, NULL
);
79 MALLOC_JUSTDEFINE(M_ISOFSMNT
, "ISOFS mount", "ISOFS mount structure");
81 static struct sysctllog
*cd9660_sysctl_log
;
83 extern const struct vnodeopv_desc cd9660_vnodeop_opv_desc
;
84 extern const struct vnodeopv_desc cd9660_specop_opv_desc
;
85 extern const struct vnodeopv_desc cd9660_fifoop_opv_desc
;
87 const struct vnodeopv_desc
* const cd9660_vnodeopv_descs
[] = {
88 &cd9660_vnodeop_opv_desc
,
89 &cd9660_specop_opv_desc
,
90 &cd9660_fifoop_opv_desc
,
94 struct vfsops cd9660_vfsops
= {
96 sizeof (struct iso_args
),
111 (int (*)(struct mount
*, struct vnode
*, struct timespec
*)) eopnotsupp
,
113 (void *)eopnotsupp
, /* vfs_suspendctl */
114 genfs_renamelock_enter
,
115 genfs_renamelock_exit
,
117 cd9660_vnodeopv_descs
,
119 { NULL
, NULL
} /* list */
122 static const struct genfs_ops cd9660_genfsops
= {
123 .gop_size
= genfs_size
,
127 * Called by vfs_mountroot when iso is going to be mounted as root.
129 * Name is updated by mount(8) after booting.
131 #define ROOTNAME "root_device"
133 static int iso_makemp(struct iso_mnt
*isomp
, struct buf
*bp
, int *ea_len
);
134 static int iso_mountfs(struct vnode
*devvp
, struct mount
*mp
,
135 struct lwp
*l
, struct iso_args
*argp
);
138 cd9660_modcmd(modcmd_t cmd
, void *arg
)
143 case MODULE_CMD_INIT
:
144 error
= vfs_attach(&cd9660_vfsops
);
147 sysctl_createv(&cd9660_sysctl_log
, 0, NULL
, NULL
,
148 CTLFLAG_PERMANENT
, CTLTYPE_NODE
, "vfs", NULL
,
151 sysctl_createv(&cd9660_sysctl_log
, 0, NULL
, NULL
,
152 CTLFLAG_PERMANENT
, CTLTYPE_NODE
, "cd9660",
153 SYSCTL_DESCR("ISO-9660 file system"),
155 CTL_VFS
, 14, CTL_EOL
);
156 sysctl_createv(&cd9660_sysctl_log
, 0, NULL
, NULL
,
157 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
158 CTLTYPE_INT
, "utf8_joliet",
159 SYSCTL_DESCR("Encode Joliet filenames to UTF-8"),
160 NULL
, 0, &cd9660_utf8_joliet
, 0,
161 CTL_VFS
, 14, CD9660_UTF8_JOLIET
, CTL_EOL
);
163 * XXX the "14" above could be dynamic, thereby eliminating
164 * one more instance of the "number to vfs" mapping problem,
165 * but "14" is the order as taken from sys/mount.h
168 case MODULE_CMD_FINI
:
169 error
= vfs_detach(&cd9660_vfsops
);
172 sysctl_teardown(&cd9660_sysctl_log
);
183 cd9660_mountroot(void)
186 struct lwp
*l
= curlwp
;
188 struct iso_args args
;
190 if (device_class(root_device
) != DV_DISK
)
193 if ((error
= vfs_rootmountalloc(MOUNT_CD9660
, "root_device", &mp
))
199 args
.flags
= ISOFSMNT_ROOT
;
200 if ((error
= iso_mountfs(rootvp
, mp
, l
, &args
)) != 0) {
201 vfs_unbusy(mp
, false, NULL
);
205 mutex_enter(&mountlist_lock
);
206 CIRCLEQ_INSERT_TAIL(&mountlist
, mp
, mnt_list
);
207 mutex_exit(&mountlist_lock
);
208 (void)cd9660_statvfs(mp
, &mp
->mnt_stat
);
209 vfs_unbusy(mp
, false, NULL
);
219 cd9660_mount(struct mount
*mp
, const char *path
, void *data
, size_t *data_len
)
221 struct lwp
*l
= curlwp
;
223 struct iso_args
*args
= data
;
225 struct iso_mnt
*imp
= VFSTOISOFS(mp
);
227 if (*data_len
< sizeof *args
)
230 if (mp
->mnt_flag
& MNT_GETARGS
) {
234 args
->flags
= imp
->im_flags
;
235 *data_len
= sizeof (*args
);
239 if ((mp
->mnt_flag
& MNT_RDONLY
) == 0)
242 if ((mp
->mnt_flag
& MNT_UPDATE
) && args
->fspec
== NULL
)
246 * Not an update, or updating the name: look up the name
247 * and verify that it refers to a sensible block device.
249 error
= namei_simple_user(args
->fspec
,
250 NSM_FOLLOW_NOEMULROOT
, &devvp
);
254 if (devvp
->v_type
!= VBLK
) {
258 if (bdevsw_lookup(devvp
->v_rdev
) == NULL
) {
263 * If mount by non-root, then verify that user has necessary
264 * permissions on the device.
266 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
267 error
= genfs_can_mount(devvp
, VREAD
, l
->l_cred
);
268 VOP_UNLOCK(devvp
, 0);
273 if ((mp
->mnt_flag
& MNT_UPDATE
) == 0) {
274 error
= VOP_OPEN(devvp
, FREAD
, FSCRED
);
277 error
= iso_mountfs(devvp
, mp
, l
, args
);
279 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
280 (void)VOP_CLOSE(devvp
, FREAD
, NOCRED
);
281 VOP_UNLOCK(devvp
, 0);
286 if (devvp
!= imp
->im_devvp
&&
287 devvp
->v_rdev
!= imp
->im_devvp
->v_rdev
)
288 return (EINVAL
); /* needs translation */
290 return set_statvfs_info(path
, UIO_USERSPACE
, args
->fspec
, UIO_USERSPACE
,
291 mp
->mnt_op
->vfs_name
, mp
, l
);
299 * Make a mount point from a volume descriptor
302 iso_makemp(struct iso_mnt
*isomp
, struct buf
*bp
, int *ea_len
)
304 struct iso_primary_descriptor
*pri
;
305 int logical_block_size
;
306 struct iso_directory_record
*rootp
;
308 pri
= (struct iso_primary_descriptor
*)bp
->b_data
;
310 logical_block_size
= isonum_723 (pri
->logical_block_size
);
312 if (logical_block_size
< DEV_BSIZE
|| logical_block_size
> MAXBSIZE
313 || (logical_block_size
& (logical_block_size
- 1)) != 0)
316 rootp
= (struct iso_directory_record
*)pri
->root_directory_record
;
318 isomp
->logical_block_size
= logical_block_size
;
319 isomp
->volume_space_size
= isonum_733 (pri
->volume_space_size
);
320 memcpy(isomp
->root
, rootp
, sizeof(isomp
->root
));
321 isomp
->root_extent
= isonum_733 (rootp
->extent
);
322 isomp
->root_size
= isonum_733 (rootp
->size
);
323 isomp
->im_joliet_level
= 0;
325 isomp
->im_bmask
= logical_block_size
- 1;
326 isomp
->im_bshift
= 0;
327 while ((1 << isomp
->im_bshift
) < isomp
->logical_block_size
)
331 *ea_len
= isonum_711(rootp
->ext_attr_length
);
337 * Common code for mount and mountroot
340 iso_mountfs(struct vnode
*devvp
, struct mount
*mp
, struct lwp
*l
,
341 struct iso_args
*argp
)
343 struct iso_mnt
*isomp
= (struct iso_mnt
*)0;
344 struct buf
*bp
= NULL
, *pribp
= NULL
, *supbp
= NULL
;
345 dev_t dev
= devvp
->v_rdev
;
347 int ronly
= (mp
->mnt_flag
& MNT_RDONLY
) != 0;
351 struct iso_volume_descriptor
*vdp
;
352 struct iso_supplementary_descriptor
*sup
;
355 struct disklabel label
;
360 /* Flush out any old buffers remaining from a previous use. */
361 if ((error
= vinvalbuf(devvp
, V_SAVE
, l
->l_cred
, l
, 0, 0)) != 0)
364 /* This is the "logical sector size". The standard says this
365 * should be 2048 or the physical sector size on the device,
366 * whichever is greater. For now, we'll just use a constant.
368 iso_bsize
= ISO_DEFAULT_BLOCK_SIZE
;
370 error
= VOP_IOCTL(devvp
, DIOCGDINFO
, &label
, FREAD
, FSCRED
);
372 label
.d_partitions
[DISKPART(dev
)].p_fstype
== FS_ISO9660
) {
373 /* XXX more sanity checks? */
374 sess
= label
.d_partitions
[DISKPART(dev
)].p_cdsession
;
376 /* fallback to old method */
377 error
= VOP_IOCTL(devvp
, CDIOREADMSADDR
, &sess
, 0, FSCRED
);
379 sess
= 0; /* never mind */
382 printf("isofs: session offset (part %"PRId32
") %d\n", DISKPART(dev
), sess
);
385 for (iso_blknum
= 16; iso_blknum
< 100; iso_blknum
++) {
386 if ((error
= bread(devvp
, (iso_blknum
+sess
) * btodb(iso_bsize
),
387 iso_bsize
, NOCRED
, 0, &bp
)) != 0)
390 vdp
= (struct iso_volume_descriptor
*)bp
->b_data
;
391 if (memcmp(vdp
->id
, ISO_STANDARD_ID
, sizeof(vdp
->id
)) != 0) {
396 switch (isonum_711(vdp
->type
)) {
404 case ISO_VD_SUPPLEMENTARY
:
415 if (isonum_711 (vdp
->type
) == ISO_VD_END
) {
432 isomp
= malloc(sizeof *isomp
, M_ISOFSMNT
, M_WAITOK
);
433 memset(isomp
, 0, sizeof *isomp
);
434 if (iso_makemp(isomp
, pribp
, &ext_attr_length
) == -1) {
439 isomp
->volume_space_size
+= sess
;
441 brelse(pribp
, BC_AGE
);
444 mp
->mnt_data
= isomp
;
445 mp
->mnt_stat
.f_fsidx
.__fsid_val
[0] = (long)dev
;
446 mp
->mnt_stat
.f_fsidx
.__fsid_val
[1] = makefstype(MOUNT_CD9660
);
447 mp
->mnt_stat
.f_fsid
= mp
->mnt_stat
.f_fsidx
.__fsid_val
[0];
448 mp
->mnt_stat
.f_namemax
= MAXNAMLEN
;
449 mp
->mnt_flag
|= MNT_LOCAL
;
450 mp
->mnt_iflag
|= IMNT_MPSAFE
;
451 mp
->mnt_dev_bshift
= iso_bsize
;
452 mp
->mnt_fs_bshift
= isomp
->im_bshift
;
453 isomp
->im_mountp
= mp
;
455 isomp
->im_devvp
= devvp
;
457 /* Check the Rock Ridge Extension support */
458 if (!(argp
->flags
& ISOFSMNT_NORRIP
)) {
459 struct iso_directory_record
*rootp
;
461 if ((error
= bread(isomp
->im_devvp
,
462 (isomp
->root_extent
+ ext_attr_length
) <<
463 (isomp
->im_bshift
- DEV_BSHIFT
),
464 isomp
->logical_block_size
, NOCRED
,
468 rootp
= (struct iso_directory_record
*)bp
->b_data
;
470 if ((isomp
->rr_skip
= cd9660_rrip_offset(rootp
,isomp
)) < 0) {
471 argp
->flags
|= ISOFSMNT_NORRIP
;
473 argp
->flags
&= ~ISOFSMNT_GENS
;
477 * The contents are valid,
478 * but they will get reread as part of another vnode, so...
483 isomp
->im_flags
= argp
->flags
& (ISOFSMNT_NORRIP
| ISOFSMNT_GENS
|
484 ISOFSMNT_EXTATT
| ISOFSMNT_NOJOLIET
| ISOFSMNT_RRCASEINS
);
486 if (isomp
->im_flags
& ISOFSMNT_GENS
)
487 isomp
->iso_ftype
= ISO_FTYPE_9660
;
488 else if (isomp
->im_flags
& ISOFSMNT_NORRIP
) {
489 isomp
->iso_ftype
= ISO_FTYPE_DEFAULT
;
490 if (argp
->flags
& ISOFSMNT_NOCASETRANS
)
491 isomp
->im_flags
|= ISOFSMNT_NOCASETRANS
;
493 isomp
->iso_ftype
= ISO_FTYPE_RRIP
;
495 /* Check the Joliet Extension support */
496 if ((argp
->flags
& ISOFSMNT_NORRIP
) != 0 &&
497 (argp
->flags
& ISOFSMNT_NOJOLIET
) == 0 &&
500 sup
= (struct iso_supplementary_descriptor
*)supbp
->b_data
;
502 if ((isonum_711(sup
->flags
) & 1) == 0) {
503 if (memcmp(sup
->escape
, "%/@", 3) == 0)
505 if (memcmp(sup
->escape
, "%/C", 3) == 0)
507 if (memcmp(sup
->escape
, "%/E", 3) == 0)
510 if (joliet_level
!= 0) {
511 if (iso_makemp(isomp
, supbp
, NULL
) == -1) {
515 isomp
->im_joliet_level
= joliet_level
;
524 devvp
->v_specmountpoint
= mp
;
535 free(isomp
, M_ISOFSMNT
);
542 * Make a filesystem operational.
543 * Nothing to do at the moment.
547 cd9660_start(struct mount
*mp
, int flags
)
553 * unmount system call
556 cd9660_unmount(struct mount
*mp
, int mntflags
)
558 struct iso_mnt
*isomp
;
559 int error
, flags
= 0;
561 if (mntflags
& MNT_FORCE
)
563 if ((error
= vflush(mp
, NULLVP
, flags
)) != 0)
566 isomp
= VFSTOISOFS(mp
);
568 if (isomp
->im_devvp
->v_type
!= VBAD
)
569 isomp
->im_devvp
->v_specmountpoint
= NULL
;
571 vn_lock(isomp
->im_devvp
, LK_EXCLUSIVE
| LK_RETRY
);
572 error
= VOP_CLOSE(isomp
->im_devvp
, FREAD
, NOCRED
);
573 vput(isomp
->im_devvp
);
574 free(isomp
, M_ISOFSMNT
);
576 mp
->mnt_flag
&= ~MNT_LOCAL
;
581 * Return root of a filesystem
584 cd9660_root(struct mount
*mp
, struct vnode
**vpp
)
586 struct iso_mnt
*imp
= VFSTOISOFS(mp
);
587 struct iso_directory_record
*dp
=
588 (struct iso_directory_record
*)imp
->root
;
589 ino_t ino
= isodirino(dp
, imp
);
592 * With RRIP we must use the `.' entry of the root directory.
593 * Simply tell vget, that it's a relocated directory.
595 return (cd9660_vget_internal(mp
, ino
, vpp
,
596 imp
->iso_ftype
== ISO_FTYPE_RRIP
, dp
));
600 * Get file system statistics.
603 cd9660_statvfs(struct mount
*mp
, struct statvfs
*sbp
)
605 struct iso_mnt
*isomp
;
607 isomp
= VFSTOISOFS(mp
);
609 sbp
->f_bsize
= isomp
->logical_block_size
;
610 sbp
->f_frsize
= sbp
->f_bsize
;
611 sbp
->f_iosize
= sbp
->f_bsize
; /* XXX */
612 sbp
->f_blocks
= isomp
->volume_space_size
;
613 sbp
->f_bfree
= 0; /* total free blocks */
614 sbp
->f_bavail
= 0; /* blocks free for non superuser */
615 sbp
->f_bresvd
= 0; /* total reserved blocks */
616 sbp
->f_files
= 0; /* total files */
617 sbp
->f_ffree
= 0; /* free file nodes */
618 sbp
->f_favail
= 0; /* free file nodes for non superuser */
619 sbp
->f_fresvd
= 0; /* reserved file nodes */
620 copy_statvfs_info(sbp
, mp
);
621 /* Use the first spare for flags: */
622 sbp
->f_spare
[0] = isomp
->im_flags
;
628 cd9660_sync(struct mount
*mp
, int waitfor
, kauth_cred_t cred
)
634 * File handle to vnode
636 * Have to be really careful about stale file handles:
637 * - check that the inode number is in range
638 * - call iget() to get the locked inode
639 * - check for an unallocated inode (i_mode == 0)
640 * - check that the generation number matches
652 cd9660_fhtovp(struct mount
*mp
, struct fid
*fhp
, struct vnode
**vpp
)
659 if (fhp
->fid_len
!= sizeof(ifh
))
662 memcpy(&ifh
, fhp
, sizeof(ifh
));
664 printf("fhtovp: ino %d, start %ld\n",
665 ifh
.ifid_ino
, ifh
.ifid_start
);
668 if ((error
= VFS_VGET(mp
, ifh
.ifid_ino
, &nvp
)) != 0) {
673 if (ip
->inode
.iso_mode
== 0) {
683 cd9660_vget(struct mount
*mp
, ino_t ino
, struct vnode
**vpp
)
688 * It would be nice if we didn't always set the `relocated' flag
689 * and force the extra read, but I don't want to think about fixing
692 return (cd9660_vget_internal(mp
, ino
, vpp
,
694 VFSTOISOFS(mp
)->iso_ftype
== ISO_FTYPE_RRIP
,
702 cd9660_vget_internal(struct mount
*mp
, ino_t ino
, struct vnode
**vpp
,
703 int relocated
, struct iso_directory_record
*isodir
)
712 imp
= VFSTOISOFS(mp
);
716 if ((*vpp
= cd9660_ihashget(dev
, ino
, LK_EXCLUSIVE
)) != NULLVP
)
719 /* Allocate a new vnode/iso_node. */
720 if ((error
= getnewvnode(VT_ISOFS
, mp
, cd9660_vnodeop_p
, &vp
)) != 0) {
724 ip
= pool_get(&cd9660_node_pool
, PR_WAITOK
);
727 * If someone beat us to it, put back the freshly allocated
728 * vnode/inode pair and retry.
730 mutex_enter(&cd9660_hashlock
);
731 if (cd9660_ihashget(dev
, ino
, 0) != NULL
) {
732 mutex_exit(&cd9660_hashlock
);
734 pool_put(&cd9660_node_pool
, ip
);
738 memset(ip
, 0, sizeof(struct iso_node
));
744 ip
->i_devvp
= imp
->im_devvp
;
745 genfs_node_init(vp
, &cd9660_genfsops
);
748 * Put it onto its hash chain and lock it so that other requests for
749 * this inode will block if they arrive while we are sleeping waiting
750 * for old data structures to be purged or for the contents of the
751 * disk portion of this inode to be read.
754 mutex_exit(&cd9660_hashlock
);
759 lbn
= lblkno(imp
, ino
);
760 if (lbn
>= imp
->volume_space_size
) {
762 printf("fhtovp: lbn exceed volume space %d\n", lbn
);
766 off
= blkoff(imp
, ino
);
767 if (off
+ ISO_DIRECTORY_RECORD_SIZE
> imp
->logical_block_size
) {
769 printf("fhtovp: crosses block boundary %d\n",
770 off
+ ISO_DIRECTORY_RECORD_SIZE
);
774 error
= bread(imp
->im_devvp
,
775 lbn
<< (imp
->im_bshift
- DEV_BSHIFT
),
776 imp
->logical_block_size
, NOCRED
, 0, &bp
);
780 printf("fhtovp: bread error %d\n",error
);
783 isodir
= (struct iso_directory_record
*)((char *)bp
->b_data
+ off
);
785 if (off
+ isonum_711(isodir
->length
) >
786 imp
->logical_block_size
) {
790 printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
791 off
+isonum_711(isodir
->length
), off
,
792 isonum_711(isodir
->length
));
797 if (isonum_733(isodir
->extent
) +
798 isonum_711(isodir
->ext_attr_length
) != ifhp
->ifid_start
) {
801 printf("fhtovp: file start miss %d vs %d\n",
802 isonum_733(isodir
->extent
) + isonum_711(isodir
->ext_attr_length
),
814 * On relocated directories we must
815 * read the `.' entry out of a dir.
817 ip
->iso_start
= ino
>> imp
->im_bshift
;
820 if ((error
= cd9660_blkatoff(vp
, (off_t
)0, NULL
, &bp
)) != 0) {
824 isodir
= (struct iso_directory_record
*)bp
->b_data
;
827 ip
->iso_extent
= isonum_733(isodir
->extent
);
828 ip
->i_size
= isonum_733(isodir
->size
);
829 ip
->iso_start
= isonum_711(isodir
->ext_attr_length
) + ip
->iso_extent
;
832 * Setup time stamp, attribute
835 switch (imp
->iso_ftype
) {
836 default: /* ISO_FTYPE_9660 */
840 if ((imp
->im_flags
& ISOFSMNT_EXTATT
)
841 && (off
= isonum_711(isodir
->ext_attr_length
)))
842 cd9660_blkatoff(vp
, (off_t
)-(off
<< imp
->im_bshift
),
846 cd9660_defattr(isodir
, ip
, bp2
);
847 cd9660_deftstamp(isodir
, ip
, bp2
);
853 cd9660_rrip_analyze(isodir
, ip
, imp
);
861 * Initialize the associated vnode
863 switch (vp
->v_type
= IFTOVT(ip
->inode
.iso_mode
)) {
865 vp
->v_op
= cd9660_fifoop_p
;
870 * if device, look at device number table for translation
872 vp
->v_op
= cd9660_specop_p
;
873 spec_node_init(vp
, ip
->inode
.iso_rdev
);
882 uvm_vnp_setsize(vp
, ip
->i_size
);
886 if (vp
->v_type
!= VREG
)
887 uvm_vnp_setsize(vp
, 0);
889 if (ip
->iso_extent
== imp
->root_extent
)
890 vp
->v_vflag
|= VV_ROOT
;
893 * XXX need generation number?
901 * Vnode pointer to File handle
905 cd9660_vptofh(struct vnode
*vp
, struct fid
*fhp
, size_t *fh_size
)
907 struct iso_node
*ip
= VTOI(vp
);
910 if (*fh_size
< sizeof(struct ifid
)) {
911 *fh_size
= sizeof(struct ifid
);
914 *fh_size
= sizeof(struct ifid
);
916 memset(&ifh
, 0, sizeof(ifh
));
917 ifh
.ifid_len
= sizeof(struct ifid
);
918 ifh
.ifid_ino
= ip
->i_number
;
919 ifh
.ifid_start
= ip
->iso_start
;
920 memcpy(fhp
, &ifh
, sizeof(ifh
));
923 printf("vptofh: ino %d, start %ld\n",
924 ifh
.ifid_ino
,ifh
.ifid_start
);