2 * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* $NetBSD: cd9660_vfsops.c,v 1.18 1995/03/09 12:05:36 mycroft Exp $ */
26 * The Regents of the University of California. All rights reserved.
28 * This code is derived from software contributed to Berkeley
29 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
30 * Support code is derived from software contributed to Berkeley
31 * by Atsushi Murai (amurai@spec.co.jp).
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by the University of
44 * California, Berkeley and its contributors.
45 * 4. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * @(#)cd9660_vfsops.c 8.9 (Berkeley) 12/5/94
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/vnode.h>
67 #include <sys/mount.h>
68 #include <sys/namei.h>
70 #include <sys/kernel.h>
71 #include <miscfs/specfs/specdev.h>
74 #include <sys/ioctl.h>
76 #include <sys/errno.h>
77 #include <sys/malloc.h>
80 #include <sys/utfconv.h>
81 #include <architecture/byte_order.h>
83 #include <isofs/cd9660/iso.h>
84 #include <isofs/cd9660/iso_rrip.h>
85 #include <isofs/cd9660/cd9660_node.h>
86 #include <isofs/cd9660/cd9660_mount.h>
88 u_char isonullname
[] = "\0";
92 struct vfsops cd9660_vfsops
= {
108 * Called by vfs_mountroot when iso is going to be mounted as root.
110 * Name is updated by mount(8) after booting.
112 #define ROOTNAME "root_device"
114 static int iso_mountfs
__P((struct vnode
*devvp
, struct mount
*mp
,
115 struct proc
*p
, struct iso_args
*argp
));
117 static void DRGetTypeCreatorAndFlags(
118 struct iso_mnt
* theMountPointPtr
,
119 struct iso_directory_record
* theDirRecPtr
,
120 u_int32_t
* theTypePtr
,
121 u_int32_t
* theCreatorPtr
,
122 u_int16_t
* theFlagsPtr
);
124 int cd9660_vget_internal(
129 struct iso_directory_record
*isodir
,
135 register struct mount
*mp
;
136 extern struct vnode
*rootvp
;
137 struct proc
*p
= current_proc(); /* XXX */
141 struct iso_args args
;
144 * Get vnodes for swapdev and rootdev.
146 if ( bdevvp(rootdev
, &rootvp
))
147 panic("cd9660_mountroot: can't setup bdevvp's");
149 MALLOC_ZONE(mp
, struct mount
*,
150 sizeof(struct mount
), M_MOUNT
, M_WAITOK
);
151 bzero((char *)mp
, (u_long
)sizeof(struct mount
));
153 /* Initialize the default IO constraints */
154 mp
->mnt_maxreadcnt
= mp
->mnt_maxwritecnt
= MAXPHYS
;
155 mp
->mnt_segreadcnt
= mp
->mnt_segwritecnt
= 32;
157 mp
->mnt_op
= &cd9660_vfsops
;
158 mp
->mnt_flag
= MNT_RDONLY
;
159 LIST_INIT(&mp
->mnt_vnodelist
);
160 args
.flags
= ISOFSMNT_ROOT
;
162 if ((error
= iso_mountfs(rootvp
, mp
, p
, &args
))) {
163 vrele(rootvp
); /* release the reference from bdevvp() */
164 FREE_ZONE(mp
, sizeof (struct mount
), M_MOUNT
);
167 simple_lock(&mountlist_slock
);
168 CIRCLEQ_INSERT_TAIL(&mountlist
, mp
, mnt_list
);
169 simple_unlock(&mountlist_slock
);
170 mp
->mnt_vnodecovered
= NULLVP
;
171 imp
= VFSTOISOFS(mp
);
172 (void) copystr("/", mp
->mnt_stat
.f_mntonname
, MNAMELEN
- 1,
174 bzero(mp
->mnt_stat
.f_mntonname
+ size
, MNAMELEN
- size
);
175 (void) copystr(ROOTNAME
, mp
->mnt_stat
.f_mntfromname
, MNAMELEN
- 1,
177 bzero(mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
178 (void)cd9660_statfs(mp
, &mp
->mnt_stat
, p
);
188 cd9660_mount(mp
, path
, data
, ndp
, p
)
189 register struct mount
*mp
;
192 struct nameidata
*ndp
;
196 struct iso_args args
;
199 struct iso_mnt
*imp
= NULL
;
201 if ((error
= copyin(data
, (caddr_t
)&args
, sizeof (struct iso_args
))))
204 if ((mp
->mnt_flag
& MNT_RDONLY
) == 0)
208 * If updating, check whether changing from read-only to
209 * read/write; if there is no device name, that's all we do.
211 if (mp
->mnt_flag
& MNT_UPDATE
) {
212 imp
= VFSTOISOFS(mp
);
214 return (vfs_export(mp
, &imp
->im_export
, &args
.export
));
217 * Not an update, or updating the name: look up the name
218 * and verify that it refers to a sensible block device.
220 NDINIT(ndp
, LOOKUP
, FOLLOW
, UIO_USERSPACE
, args
.fspec
, p
);
221 if ((error
= namei(ndp
)))
225 if (devvp
->v_type
!= VBLK
) {
229 if (major(devvp
->v_rdev
) >= nblkdev
) {
233 if ((mp
->mnt_flag
& MNT_UPDATE
) == 0)
234 error
= iso_mountfs(devvp
, mp
, p
, &args
);
236 if (devvp
!= imp
->im_devvp
)
237 error
= EINVAL
; /* needs translation */
246 /* Set the mount flag to indicate that we support volfs */
247 mp
->mnt_flag
|= MNT_DOVOLFS
;
249 (void) copyinstr(path
, mp
->mnt_stat
.f_mntonname
, MNAMELEN
- 1, &size
);
250 bzero(mp
->mnt_stat
.f_mntonname
+ size
, MNAMELEN
- size
);
251 (void) copyinstr(args
.fspec
, mp
->mnt_stat
.f_mntfromname
, MNAMELEN
- 1,
253 bzero(mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
258 * Common code for mount and mountroot
261 iso_mountfs(devvp
, mp
, p
, argp
)
262 register struct vnode
*devvp
;
265 struct iso_args
*argp
;
267 register struct iso_mnt
*isomp
= (struct iso_mnt
*)0;
268 struct buf
*bp
= NULL
;
269 struct buf
*pribp
= NULL
, *supbp
= NULL
;
270 dev_t dev
= devvp
->v_rdev
;
274 extern struct vnode
*rootvp
;
278 struct iso_volume_descriptor
*vdp
= NULL
;
279 struct iso_primary_descriptor
*pri
= NULL
;
280 struct iso_primary_descriptor
*sup
= NULL
;
281 struct iso_directory_record
*rootp
;
282 int logical_block_size
;
284 int blkoff
= argp
->ssector
;
286 if (!(mp
->mnt_flag
& MNT_RDONLY
))
290 * Disallow multiple mounts of the same device.
291 * Disallow mounting of a device that is currently in use
292 * (except for root, which might share swap device for miniroot).
293 * Flush out any old buffers remaining from a previous use.
295 if ((error
= vfs_mountedon(devvp
)))
297 if (vcount(devvp
) > 1 && devvp
!= rootvp
)
299 if ((error
= vinvalbuf(devvp
, V_SAVE
, p
->p_ucred
, p
, 0, 0)))
302 if ((error
= VOP_OPEN(devvp
, FREAD
, FSCRED
, p
)))
306 /* This is the "logical sector size". The standard says this
307 * should be 2048 or the physical sector size on the device,
308 * whichever is greater. For now, we'll just use a constant.
310 iso_bsize
= ISO_DEFAULT_BLOCK_SIZE
;
312 /* tell IOKit that we're assuming 2K sectors */
313 if ((error
= VOP_IOCTL(devvp
, DKIOCSETBLOCKSIZE
,
314 (caddr_t
)&iso_bsize
, FWRITE
, p
->p_ucred
, p
)))
316 devvp
->v_specsize
= iso_bsize
;
318 for (iso_blknum
= 16 + blkoff
; iso_blknum
< (100 + blkoff
); iso_blknum
++) {
319 if ((error
= bread(devvp
, iso_blknum
, iso_bsize
, NOCRED
, &bp
))) {
321 bp
->b_flags
|= B_AGE
;
326 printf("iso_mountfs: bread error %d reading block %d\n", error
, iso_blknum
);
330 vdp
= (struct iso_volume_descriptor
*)bp
->b_data
;
331 if (bcmp (vdp
->volume_desc_id
, ISO_STANDARD_ID
, sizeof(vdp
->volume_desc_id
)) != 0) {
333 printf("cd9660_vfsops.c: iso_mountfs: "
334 "Invalid ID in volume desciptor.\n");
340 vdtype
= isonum_711 (vdp
->type
);
341 if (vdtype
== ISO_VD_END
)
344 if (vdtype
== ISO_VD_PRIMARY
) {
348 pri
= (struct iso_primary_descriptor
*)vdp
;
350 } else if(vdtype
== ISO_VD_SUPPLEMENTARY
) {
354 sup
= (struct iso_primary_descriptor
*)vdp
;
356 if ((argp
->flags
& ISOFSMNT_NOJOLIET
) == 0) {
358 * some Joliet CDs are "out-of-spec and don't correctly
359 * set the SVD flags. We ignore the flags and rely soely
362 if (bcmp(sup
->escape_seq
, ISO_UCS2_Level_1
, 3) == 0)
364 else if (bcmp(sup
->escape_seq
, ISO_UCS2_Level_2
, 3) == 0)
366 else if (bcmp(sup
->escape_seq
, ISO_UCS2_Level_3
, 3) == 0)
373 bp
->b_flags
|= B_AGE
;
380 bp
->b_flags
|= B_AGE
;
393 logical_block_size
= isonum_723 (pri
->logical_block_size
);
395 if (logical_block_size
< DEV_BSIZE
|| logical_block_size
> MAXBSIZE
396 || (logical_block_size
& (logical_block_size
- 1)) != 0) {
401 rootp
= (struct iso_directory_record
*)pri
->root_directory_record
;
403 MALLOC(isomp
, struct iso_mnt
*, sizeof *isomp
, M_ISOFSMNT
, M_WAITOK
);
404 bzero((caddr_t
)isomp
, sizeof *isomp
);
405 isomp
->logical_block_size
= logical_block_size
;
406 isomp
->volume_space_size
= isonum_733 (pri
->volume_space_size
);
408 * Since an ISO9660 multi-session CD can also access previous
409 * sessions, we have to include them into the space consider-
410 * ations. This doesn't yield a very accurate number since
411 * parts of the old sessions might be inaccessible now, but we
412 * can't do much better. This is also important for the NFS
413 * filehandle validation.
415 isomp
->volume_space_size
+= blkoff
;
416 bcopy (rootp
, isomp
->root
, sizeof isomp
->root
);
417 isomp
->root_extent
= isonum_733 (rootp
->extent
);
418 isomp
->root_size
= isonum_733 (rootp
->size
);
421 * getattrlist wants the volume name, create date and modify date
424 /* Remove any trailing white space */
425 if ( strlen(pri
->volume_id
) ) {
428 myPtr
= pri
->volume_id
+ strlen( pri
->volume_id
) - 1;
429 while ( *myPtr
== ' ' && myPtr
>= pri
->volume_id
) {
435 if (pri
->volume_id
[0] == 0)
436 strcpy(isomp
->volume_id
, ISO_DFLT_VOLUME_ID
);
438 bcopy(pri
->volume_id
, isomp
->volume_id
, sizeof(isomp
->volume_id
));
439 cd9660_tstamp_conv17(pri
->creation_date
, &isomp
->creation_date
);
440 cd9660_tstamp_conv17(pri
->modification_date
, &isomp
->modification_date
);
442 /* See if this is a CD-XA volume */
443 if (bcmp( pri
->CDXASignature
, ISO_XA_ID
,
444 sizeof(pri
->CDXASignature
) ) == 0 )
445 isomp
->im_flags2
|= IMF2_IS_CDXA
;
447 isomp
->im_bmask
= logical_block_size
- 1;
448 isomp
->im_bshift
= 0;
449 while ((1 << isomp
->im_bshift
) < isomp
->logical_block_size
)
452 pribp
->b_flags
|= B_AGE
;
456 mp
->mnt_data
= (qaddr_t
)isomp
;
457 mp
->mnt_stat
.f_fsid
.val
[0] = (long)dev
;
458 mp
->mnt_stat
.f_fsid
.val
[1] = mp
->mnt_vfc
->vfc_typenum
;
459 mp
->mnt_maxsymlinklen
= 0;
460 mp
->mnt_flag
|= MNT_LOCAL
;
462 isomp
->im_mountp
= mp
;
464 isomp
->im_devvp
= devvp
;
466 devvp
->v_specflags
|= SI_MOUNTEDON
;
468 /* Check the Rock Ridge Extention support */
469 if (!(argp
->flags
& ISOFSMNT_NORRIP
)) {
470 if ( (error
= bread(isomp
->im_devvp
,
471 (isomp
->root_extent
+ isonum_711(rootp
->ext_attr_length
)),
472 isomp
->logical_block_size
, NOCRED
, &bp
)) ) {
474 printf("iso_mountfs: bread error %d reading block %d\n",
475 error
, isomp
->root_extent
+ isonum_711(rootp
->ext_attr_length
));
476 argp
->flags
|= ISOFSMNT_NORRIP
;
479 rootp
= (struct iso_directory_record
*)bp
->b_data
;
481 if ((isomp
->rr_skip
= cd9660_rrip_offset(rootp
,isomp
)) < 0) {
482 argp
->flags
|= ISOFSMNT_NORRIP
;
484 argp
->flags
&= ~ISOFSMNT_GENS
;
488 * The contents are valid,
489 * but they will get reread as part of another vnode, so...
491 bp
->b_flags
|= B_AGE
;
497 isomp
->im_flags
= argp
->flags
& (ISOFSMNT_NORRIP
| ISOFSMNT_GENS
|
498 ISOFSMNT_EXTATT
| ISOFSMNT_NOJOLIET
);
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 isomp
->iso_ftype
= ISO_FTYPE_RRIP
;
512 /* Decide whether to use the Joliet descriptor */
514 if (isomp
->iso_ftype
!= ISO_FTYPE_RRIP
&& joliet_level
!= 0) {
521 * On Joliet CDs use the UCS-2 volume identifier.
523 * This name can have up to 15 UCS-2 chars and is
524 * terminated with 0x0000 or padded with 0x0020.
526 convflags
= UTF_DECOMPOSED
;
527 if (BYTE_ORDER
!= BIG_ENDIAN
)
528 convflags
|= UTF_REVERSE_ENDIAN
;
529 for (i
= 0, uchp
= (u_int16_t
*)sup
->volume_id
; i
< 15 && uchp
[i
]; ++i
);
530 if ((utf8_encodestr((u_int16_t
*)sup
->volume_id
, (i
* 2), vol_id
,
531 &convbytes
, sizeof(vol_id
), 0, convflags
) == 0)
532 && convbytes
&& (vol_id
[0] != ' ')) {
535 /* Remove trailing spaces */
536 strp
= vol_id
+ convbytes
- 1;
537 while (strp
> vol_id
&& *strp
== ' ')
539 bcopy(vol_id
, isomp
->volume_id
, convbytes
);
542 rootp
= (struct iso_directory_record
*)
543 sup
->root_directory_record
;
544 bcopy (rootp
, isomp
->root
, sizeof isomp
->root
);
545 isomp
->root_extent
= isonum_733 (rootp
->extent
);
546 isomp
->root_size
= isonum_733 (rootp
->size
);
547 supbp
->b_flags
|= B_AGE
;
548 isomp
->iso_ftype
= ISO_FTYPE_JOLIET
;
565 (void)VOP_CLOSE(devvp
, FREAD
, NOCRED
, p
);
567 FREE((caddr_t
)isomp
, M_ISOFSMNT
);
568 mp
->mnt_data
= (qaddr_t
)0;
571 /* Clear the mounted on bit in the devvp If it */
572 /* not set, this is a nop and there is no way to */
573 /* get here with it set unless we did it. If you*/
574 /* are making code changes which makes the above */
575 /* assumption not true, change this code. */
577 devvp
->v_specflags
&= ~SI_MOUNTEDON
;
583 * Make a filesystem operational.
584 * Nothing to do at the moment.
588 cd9660_start(mp
, flags
, p
)
597 * unmount system call
600 cd9660_unmount(mp
, mntflags
, p
)
605 register struct iso_mnt
*isomp
;
606 int error
, flags
= 0;
609 if ( (mntflags
& MNT_FORCE
) ) {
614 if ( (error
= vflush(mp
, NULLVP
, flags
)) && !force
)
617 isomp
= VFSTOISOFS(mp
);
620 if (isomp
->iso_ftype
== ISO_FTYPE_RRIP
)
621 iso_dunmap(isomp
->im_dev
);
624 isomp
->im_devvp
->v_specflags
&= ~SI_MOUNTEDON
;
625 error
= VOP_CLOSE(isomp
->im_devvp
, FREAD
, NOCRED
, p
);
626 if (error
&& !force
)
629 vrele(isomp
->im_devvp
);
630 FREE((caddr_t
)isomp
, M_ISOFSMNT
);
631 mp
->mnt_data
= (qaddr_t
)0;
632 mp
->mnt_flag
&= ~MNT_LOCAL
;
637 * Return root of a filesystem
644 struct iso_mnt
*imp
= VFSTOISOFS(mp
);
645 struct iso_directory_record
*dp
=
646 (struct iso_directory_record
*)imp
->root
;
647 ino_t ino
= isodirino(dp
, imp
);
650 * With RRIP we must use the `.' entry of the root directory.
651 * Simply tell vget, that it's a relocated directory.
653 return (cd9660_vget_internal(mp
, ino
, vpp
,
654 imp
->iso_ftype
== ISO_FTYPE_RRIP
, dp
, current_proc()));
658 * Do operations associated with quotas, not supported
662 cd9660_quotactl(mp
, cmd
, uid
, arg
, p
)
674 * Get file system statistics.
677 cd9660_statfs(mp
, sbp
, p
)
679 register struct statfs
*sbp
;
682 register struct iso_mnt
*isomp
;
684 isomp
= VFSTOISOFS(mp
);
691 sbp
->f_bsize
= isomp
->logical_block_size
;
692 sbp
->f_iosize
= sbp
->f_bsize
; /* XXX */
693 sbp
->f_blocks
= isomp
->volume_space_size
;
694 sbp
->f_bfree
= 0; /* total free blocks */
695 sbp
->f_bavail
= 0; /* blocks free for non superuser */
696 sbp
->f_files
= 0; /* total files */
697 sbp
->f_ffree
= 0; /* free file nodes */
698 if (sbp
!= &mp
->mnt_stat
) {
699 bcopy(mp
->mnt_stat
.f_mntonname
, sbp
->f_mntonname
, MNAMELEN
);
700 bcopy(mp
->mnt_stat
.f_mntfromname
, sbp
->f_mntfromname
, MNAMELEN
);
703 strncpy( sbp
->f_fstypename
, mp
->mnt_vfc
->vfc_name
, (MFSNAMELEN
- 1) );
704 sbp
->f_fstypename
[(MFSNAMELEN
- 1)] = '\0';
706 /* DO NOT use the first spare for flags; it's been reassigned for another use: */
707 /* sbp->f_spare[0] = isomp->im_flags; */
714 cd9660_sync(mp
, waitfor
, cred
, p
)
725 * File handle to vnode
727 * Have to be really careful about stale file handles:
728 * - check that the inode number is in range
729 * - call iget() to get the locked inode
730 * - check for an unallocated inode (i_mode == 0)
731 * - check that the generation number matches
743 cd9660_fhtovp(mp
, fhp
, nam
, vpp
, exflagsp
, credanonp
)
744 register struct mount
*mp
;
749 struct ucred
**credanonp
;
751 struct ifid
*ifhp
= (struct ifid
*)fhp
;
752 register struct iso_node
*ip
;
753 register struct netcred
*np
;
754 register struct iso_mnt
*imp
= VFSTOISOFS(mp
);
759 printf("fhtovp: ino %d, start %ld\n",
760 ifhp
->ifid_ino
, ifhp
->ifid_start
);
764 * Get the export permission structure for this <mp, client> tuple.
766 np
= vfs_export_lookup(mp
, &imp
->im_export
, nam
);
770 if ( (error
= VFS_VGET(mp
, &ifhp
->ifid_ino
, &nvp
)) ) {
775 if (ip
->inode
.iso_mode
== 0) {
781 *exflagsp
= np
->netc_exflags
;
782 *credanonp
= &np
->netc_anon
;
787 cd9660_vget(mp
, ino
, vpp
)
794 * It would be nice if we didn't always set the `relocated' flag
795 * and force the extra read, but I don't want to think about fixing
799 return ( cd9660_vget_internal( mp
, *(ino_t
*)ino
, vpp
, 0,
800 (struct iso_directory_record
*) 0,
805 cd9660_vget_internal(mp
, ino
, vpp
, relocated
, isodir
, p
)
810 struct iso_directory_record
*isodir
;
813 register struct iso_mnt
*imp
;
816 struct vnode
*vp
, *nvp
;
820 imp
= VFSTOISOFS(mp
);
823 /* Check for unmount in progress */
824 if (mp
->mnt_kern_flag
& MNTK_UNMOUNT
) {
829 if ((*vpp
= cd9660_ihashget(dev
, ino
, p
)) != NULLVP
)
832 MALLOC_ZONE(ip
, struct iso_node
*, sizeof(struct iso_node
),
833 M_ISOFSNODE
, M_WAITOK
);
834 /* Allocate a new vnode/iso_node. */
835 if ( (error
= getnewvnode(VT_ISOFS
, mp
, cd9660_vnodeop_p
, &vp
)) ) {
836 FREE_ZONE(ip
,sizeof(struct iso_node
), M_ISOFSNODE
);
840 bzero((caddr_t
)ip
, sizeof(struct iso_node
));
841 lockinit(&ip
->i_lock
, PINOD
,"isonode",0,0);
846 ip
->i_namep
= &isonullname
[0];
849 * Put it onto its hash chain and lock it so that other requests for
850 * this inode will block if they arrive while we are sleeping waiting
851 * for old data structures to be purged or for the contents of the
852 * disk portion of this inode to be read.
859 lbn
= lblkno(imp
, ino
);
860 if (lbn
>= imp
->volume_space_size
) {
862 printf("fhtovp: lbn exceed volume space %d\n", lbn
);
866 off
= blkoff(imp
, ino
);
867 if (off
+ ISO_DIRECTORY_RECORD_SIZE
> imp
->logical_block_size
) {
869 printf("fhtovp: crosses block boundary %d\n",
870 off
+ ISO_DIRECTORY_RECORD_SIZE
);
874 error
= bread(imp
->im_devvp
, lbn
,
875 imp
->logical_block_size
, NOCRED
, &bp
);
879 printf("fhtovp: bread error %d\n",error
);
882 isodir
= (struct iso_directory_record
*)(bp
->b_data
+ off
);
884 if (off
+ isonum_711(isodir
->length
) >
885 imp
->logical_block_size
) {
889 printf("fhtovp: directory crosses block boundary "
890 "%d[off=%d/len=%d]\n",
891 off
+isonum_711(isodir
->length
), off
,
892 isonum_711(isodir
->length
));
897 * for directories we can get parentID from adjacent
898 * parent directory record
900 if ((isonum_711(isodir
->flags
) & directoryBit
)
901 && (isodir
->name
[0] == 0)) {
902 struct iso_directory_record
*pdp
;
904 pdp
= (struct iso_directory_record
*)
905 ((char *)bp
->b_data
+ isonum_711(isodir
->length
));
906 if ((isonum_711(pdp
->flags
) & directoryBit
)
907 && (pdp
->name
[0] == 1))
908 ip
->i_parent
= isodirino(pdp
, imp
);
914 ip
->i_devvp
= imp
->im_devvp
;
919 * On relocated directories we must
920 * read the `.' entry out of a dir.
922 ip
->iso_start
= ino
>> imp
->im_bshift
;
925 if ( (error
= VOP_BLKATOFF(vp
, (off_t
)0, NULL
, &bp
)) ) {
929 isodir
= (struct iso_directory_record
*)bp
->b_data
;
933 * go get apple extensions to ISO directory record or use
934 * defaults when there are no apple extensions.
936 if ( (isonum_711( isodir
->flags
) & directoryBit
) == 0 ) {
937 /* This is an ISO directory record for a file */
938 DRGetTypeCreatorAndFlags( imp
, isodir
, &ip
->i_FileType
,
939 &ip
->i_Creator
, &ip
->i_FinderFlags
);
942 ip
->iso_extent
= isonum_733(isodir
->extent
);
943 ip
->i_size
= isonum_733(isodir
->size
);
944 ip
->iso_start
= isonum_711(isodir
->ext_attr_length
) + ip
->iso_extent
;
947 * if we have a valid name, fill in i_namep with UTF-8 name
949 if (isonum_711(isodir
->name_len
) != 0) {
954 MALLOC(utf8namep
, u_char
*, ISO_RRIP_NAMEMAX
+ 1, M_TEMP
, M_WAITOK
);
955 namelen
= isonum_711(isodir
->name_len
);
957 switch (imp
->iso_ftype
) {
959 cd9660_rrip_getname(isodir
, utf8namep
, &namelen
, &inump
, imp
);
962 case ISO_FTYPE_JOLIET
:
963 ucsfntrans((u_int16_t
*)isodir
->name
, namelen
,
965 isonum_711(isodir
->flags
) & directoryBit
);
969 isofntrans (isodir
->name
, namelen
,
971 imp
->iso_ftype
== ISO_FTYPE_9660
);
974 utf8namep
[namelen
] = '\0';
975 MALLOC(ip
->i_namep
, u_char
*, namelen
+ 1, M_TEMP
, M_WAITOK
);
976 bcopy(utf8namep
, ip
->i_namep
, namelen
+ 1);
977 FREE(utf8namep
, M_TEMP
);
981 * Setup time stamp, attribute
984 switch (imp
->iso_ftype
) {
985 default: /* ISO_FTYPE_9660 */
989 if ((imp
->im_flags
& ISOFSMNT_EXTATT
)
990 && (off
= isonum_711(isodir
->ext_attr_length
)))
991 VOP_BLKATOFF(vp
, (off_t
)-(off
<< imp
->im_bshift
), NULL
, &bp2
);
994 cd9660_defattr(isodir
, ip
, bp2
);
995 cd9660_deftstamp(isodir
, ip
, bp2
);
1000 case ISO_FTYPE_RRIP
:
1001 cd9660_rrip_analyze(isodir
, ip
, imp
);
1009 * Initialize the associated vnode
1012 if (ip
->iso_extent
== imp
->root_extent
) {
1013 vp
->v_flag
|= VROOT
;
1014 ip
->i_parent
= 1; /* root's parent is always 1 by convention */
1015 /* mode type must be S_IFDIR */
1016 ip
->inode
.iso_mode
= (ip
->inode
.iso_mode
& ~S_IFMT
) | S_IFDIR
;
1019 switch (vp
->v_type
= IFTOVT(ip
->inode
.iso_mode
)) {
1022 vp
->v_op
= cd9660_fifoop_p
;
1026 return (EOPNOTSUPP
);
1031 * if device, look at device number table for translation
1034 if (dp
= iso_dmap(dev
, ino
, 0))
1035 ip
->inode
.iso_rdev
= dp
->d_dev
;
1037 vp
->v_op
= cd9660_specop_p
;
1038 if ( (nvp
= checkalias(vp
, ip
->inode
.iso_rdev
, mp
)) ) {
1040 * Discard unneeded vnode, but save its iso_node.
1042 cd9660_ihashrem(ip
);
1043 VOP_UNLOCK(vp
, 0, p
);
1044 nvp
->v_data
= vp
->v_data
;
1046 vp
->v_op
= spec_vnodeop_p
;
1050 * Reinitialize aliased inode.
1054 cd9660_ihashins(ip
);
1065 * XXX need generation number?
1074 /************************************************************************
1076 * Function: DRGetTypeCreatorAndFlags
1078 * Purpose: Set up the fileType, fileCreator and fileFlags
1082 * Side Effects: sets *theTypePtr, *theCreatorPtr, and *theFlagsPtr
1087 * 28 Jul 88 BL¡B Added a new extension type of 6, which allows
1088 * the specification of four of the finder flags.
1089 * We let the creator of the disk just copy over
1090 * the finder flags, but we only look at always
1091 * switch launch, system, bundle, and locked bits.
1092 * 15 Aug 88 BL¡B The Apple extensions to ISO 9660 implemented the
1093 * padding field at the end of a directory record
1095 * 19 Jul 89 BG Rewrote routine to handle the "new" Apple
1096 * Extensions definition, as well as take into
1097 * account the possibility of "other" definitions.
1098 * 02 Nov 89 BG Corrected the 'AA' SystemUseID processing to
1099 * check for SystemUseID == 2 (HFS). Was incorrectly
1100 * checking for SystemUseID == 1 (ProDOS) before.
1101 * 18 Mar 92 CMP Fixed the check for whether len_fi was odd or even.
1102 * Before it would always assume even for an XA record.
1103 * 26 Dec 97 jwc Swiped from MacOS implementation of ISO 9660 CD-ROM
1104 * support and modified to work in MacOSX file system.
1106 *********************************************************************** */
1109 DRGetTypeCreatorAndFlags( struct iso_mnt
* theMountPointPtr
,
1110 struct iso_directory_record
* theDirRecPtr
,
1111 u_int32_t
* theTypePtr
,
1112 u_int32_t
* theCreatorPtr
,
1113 u_int16_t
* theFlagsPtr
)
1117 u_int32_t myCreator
;
1118 AppleExtension
*myAppleExtPtr
;
1119 NewAppleExtension
*myNewAppleExtPtr
;
1120 u_int16_t myFinderFlags
;
1124 myType
= 0x3f3f3f3f;
1125 myCreator
= 0x3f3f3f3f;
1127 *theFlagsPtr
= 0x0000;
1130 * handle the fact that our original apple extensions didn't take
1131 * into account the padding byte on a file name
1134 myPtr
= &theDirRecPtr
->name
[ (isonum_711(theDirRecPtr
->name_len
)) ];
1136 /* if string length is even, bump myPtr for padding byte */
1137 if ( ((isonum_711(theDirRecPtr
->name_len
)) & 0x01) == 0 )
1139 myAppleExtPtr
= (AppleExtension
*) myPtr
;
1142 * checking for whether or not the new 'AA' code is being
1143 * called (and if so, correctly)
1145 if ( (isonum_711(theDirRecPtr
->length
)) <=
1146 ISO_DIRECTORY_RECORD_SIZE
+ (isonum_711(theDirRecPtr
->name_len
)) ) {
1151 foundStuff
= 0; /* now we default to *false* until we find a good one */
1152 myPtr
= (char *) myAppleExtPtr
;
1154 if ( (theMountPointPtr
->im_flags2
& IMF2_IS_CDXA
) != 0 )
1155 myPtr
+= 14;/* add in CD-XA fixed record offset (tnx, Phillips) */
1156 myNewAppleExtPtr
= (NewAppleExtension
*) myPtr
;
1158 /* calculate the "real" end of the directory record information */
1159 myPtr
= ((char *) theDirRecPtr
) + (isonum_711(theDirRecPtr
->length
));
1160 while( (char *) myNewAppleExtPtr
< myPtr
) /* end of directory buffer */
1163 * If we get here, we can assume that ALL further entries in this
1164 * directory record are of the form:
1166 * struct OptionalSystemUse
1168 * byte Signature[2];
1171 * byte fileType[4]; # only if HFS
1172 * byte fileCreator[4]; # only if HFS
1173 * byte finderFlags[2]; # only if HFS
1176 * This means that we can examine the Signature bytes to see
1177 * if they are 'AA' (the NEW Apple extension signature).
1178 * If they are, deal with them. If they aren't,
1179 * the OSULength field will tell us how long this extension
1180 * info is (including the signature and length bytes) and that
1181 * will allow us to walk the OptionalSystemUse records until
1182 * we hit the end of them or run off the end of the
1185 u_char
*myFromPtr
, *myToPtr
;
1188 u_int32_t fourchars
;
1192 if ( (myNewAppleExtPtr
->signature
[0] == 'A') &&
1193 (myNewAppleExtPtr
->signature
[1] == 'A') ) {
1194 if ( isonum_711(myNewAppleExtPtr
->systemUseID
) == 2 ) {
1196 foundStuff
= 1; /* we got one! */
1198 myFromPtr
= &myNewAppleExtPtr
->fileType
[0];
1199 myToPtr
= &myChars
.chars
[0];
1200 *myToPtr
++ = *myFromPtr
++;
1201 *myToPtr
++ = *myFromPtr
++;
1202 *myToPtr
++ = *myFromPtr
++;
1203 *myToPtr
= *myFromPtr
;
1204 myType
= myChars
.fourchars
; /* copy file type to user var */
1206 myFromPtr
= &myNewAppleExtPtr
->fileCreator
[0];
1207 myToPtr
= &myChars
.chars
[0];
1208 *myToPtr
++ = *myFromPtr
++;
1209 *myToPtr
++ = *myFromPtr
++;
1210 *myToPtr
++ = *myFromPtr
++;
1211 *myToPtr
= *myFromPtr
;
1212 myCreator
= myChars
.fourchars
; /* copy creator to user var */
1214 myFromPtr
= &myNewAppleExtPtr
->finderFlags
[0];
1215 myToPtr
= &myChars
.chars
[2]; /* *flags* is a short */
1216 myChars
.fourchars
= 0;
1217 *myToPtr
++ = *myFromPtr
++;
1218 *myToPtr
= *myFromPtr
;
1219 myFinderFlags
= myChars
.fourchars
;
1221 ( fAlwaysBit
| fSystemBit
| fHasBundleBit
| fLockedBit
);
1222 /* return Finder flags to user var */
1223 *theFlagsPtr
= (myFinderFlags
| fInitedBit
);
1225 break; /* exit the loop */
1230 * Check to see if we have a reasonable OSULength value.
1231 * ZERO is not an acceptable value. Nor is any value less than 4.
1234 if ( (isonum_711(myNewAppleExtPtr
->OSULength
)) < 4 )
1235 break; /* not acceptable - get out! */
1237 /* otherwise, step past this SystemUse record */
1238 (char *)myNewAppleExtPtr
+= (isonum_711(myNewAppleExtPtr
->OSULength
));
1240 } /* end of while loop */
1243 if ( foundStuff
!= 0 ) {
1244 *theTypePtr
= myType
;
1245 *theCreatorPtr
= myCreator
;
1253 } /* DRGetTypeCreatorAndFlags */
1257 * Vnode pointer to File handle
1261 cd9660_vptofh(vp
, fhp
)
1265 register struct iso_node
*ip
= VTOI(vp
);
1266 register struct ifid
*ifhp
;
1268 ifhp
= (struct ifid
*)fhp
;
1269 ifhp
->ifid_len
= sizeof(struct ifid
);
1271 ifhp
->ifid_ino
= ip
->i_number
;
1272 ifhp
->ifid_start
= ip
->iso_start
;
1275 printf("vptofh: ino %d, start %ld\n",
1276 ifhp
->ifid_ino
,ifhp
->ifid_start
);
1282 * Fast-FileSystem only?
1285 cd9660_sysctl(name
, namelen
, oldp
, oldlenp
, newp
, newlen
, p
)
1294 return (EOPNOTSUPP
);