]> git.saurik.com Git - apple/xnu.git/blame_incremental - bsd/isofs/cd9660/cd9660_vfsops.c
xnu-517.tar.gz
[apple/xnu.git] / bsd / isofs / cd9660 / cd9660_vfsops.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/* $NetBSD: cd9660_vfsops.c,v 1.18 1995/03/09 12:05:36 mycroft Exp $ */
26
27/*-
28 * Copyright (c) 1994
29 * The Regents of the University of California. All rights reserved.
30 *
31 * This code is derived from software contributed to Berkeley
32 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
33 * Support code is derived from software contributed to Berkeley
34 * by Atsushi Murai (amurai@spec.co.jp).
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by the University of
47 * California, Berkeley and its contributors.
48 * 4. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
64 * @(#)cd9660_vfsops.c 8.9 (Berkeley) 12/5/94
65 */
66
67#include <sys/param.h>
68#include <sys/systm.h>
69#include <sys/vnode.h>
70#include <sys/mount.h>
71#include <sys/namei.h>
72#include <sys/proc.h>
73#include <sys/kernel.h>
74#include <miscfs/specfs/specdev.h>
75#include <sys/buf.h>
76#include <sys/file.h>
77#include <sys/ioctl.h>
78#include <sys/disk.h>
79#include <sys/errno.h>
80#include <sys/malloc.h>
81#include <sys/stat.h>
82#include <sys/ubc.h>
83#include <sys/utfconv.h>
84#include <architecture/byte_order.h>
85
86#include <isofs/cd9660/iso.h>
87#include <isofs/cd9660/iso_rrip.h>
88#include <isofs/cd9660/cd9660_node.h>
89#include <isofs/cd9660/cd9660_mount.h>
90
91/*
92 * Minutes, Seconds, Frames (M:S:F)
93 */
94struct CDMSF {
95 u_char minute;
96 u_char second;
97 u_char frame;
98};
99
100/*
101 * Table Of Contents
102 */
103struct CDTOC_Desc {
104 u_char session;
105 u_char ctrl_adr; /* typed to be machine and compiler independent */
106 u_char tno;
107 u_char point;
108 struct CDMSF address;
109 u_char zero;
110 struct CDMSF p;
111};
112
113struct CDTOC {
114 u_short length; /* in native cpu endian */
115 u_char first_session;
116 u_char last_session;
117 struct CDTOC_Desc trackdesc[1];
118};
119
120#define MSF_TO_LBA(msf) \
121 (((((msf).minute * 60UL) + (msf).second) * 75UL) + (msf).frame - 150)
122
123u_char isonullname[] = "\0";
124
125extern int enodev ();
126
127struct vfsops cd9660_vfsops = {
128 cd9660_mount,
129 cd9660_start,
130 cd9660_unmount,
131 cd9660_root,
132 cd9660_quotactl,
133 cd9660_statfs,
134 cd9660_sync,
135 cd9660_vget,
136 cd9660_fhtovp,
137 cd9660_vptofh,
138 cd9660_init,
139 cd9660_sysctl
140};
141
142/*
143 * Called by vfs_mountroot when iso is going to be mounted as root.
144 *
145 * Name is updated by mount(8) after booting.
146 */
147#define ROOTNAME "root_device"
148
149static int iso_mountfs __P((struct vnode *devvp, struct mount *mp,
150 struct proc *p, struct iso_args *argp));
151
152static void DRGetTypeCreatorAndFlags(
153 struct iso_mnt * theMountPointPtr,
154 struct iso_directory_record * theDirRecPtr,
155 u_int32_t * theTypePtr,
156 u_int32_t * theCreatorPtr,
157 u_int16_t * theFlagsPtr);
158
159int cd9660_vget_internal(
160 struct mount *mp,
161 ino_t ino,
162 struct vnode **vpp,
163 int relocated,
164 struct iso_directory_record *isodir,
165 struct proc *p);
166
167int
168cd9660_mountroot()
169{
170 register struct mount *mp;
171 extern struct vnode *rootvp;
172 struct proc *p = current_proc(); /* XXX */
173 struct iso_mnt *imp;
174 size_t size;
175 int error;
176 struct iso_args args;
177
178 /*
179 * Get vnodes for swapdev and rootdev.
180 */
181 if ( bdevvp(rootdev, &rootvp))
182 panic("cd9660_mountroot: can't setup bdevvp's");
183
184 MALLOC_ZONE(mp, struct mount *,
185 sizeof(struct mount), M_MOUNT, M_WAITOK);
186 bzero((char *)mp, (u_long)sizeof(struct mount));
187
188 /* Initialize the default IO constraints */
189 mp->mnt_maxreadcnt = mp->mnt_maxwritecnt = MAXPHYS;
190 mp->mnt_segreadcnt = mp->mnt_segwritecnt = 32;
191
192 mp->mnt_op = &cd9660_vfsops;
193 mp->mnt_flag = MNT_RDONLY;
194 LIST_INIT(&mp->mnt_vnodelist);
195 args.flags = ISOFSMNT_ROOT;
196 args.ssector = 0;
197 args.fspec = 0;
198 args.toc_length = 0;
199 args.toc = 0;
200 if ((error = iso_mountfs(rootvp, mp, p, &args))) {
201 vrele(rootvp); /* release the reference from bdevvp() */
202
203 if (mp->mnt_kern_flag & MNTK_IO_XINFO)
204 FREE(mp->mnt_xinfo_ptr, M_TEMP);
205 FREE_ZONE(mp, sizeof (struct mount), M_MOUNT);
206 return (error);
207 }
208 simple_lock(&mountlist_slock);
209 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
210 simple_unlock(&mountlist_slock);
211 mp->mnt_vnodecovered = NULLVP;
212 imp = VFSTOISOFS(mp);
213 (void) copystr("/", mp->mnt_stat.f_mntonname, MNAMELEN - 1,
214 &size);
215 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
216 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
217 &size);
218 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
219 (void)cd9660_statfs(mp, &mp->mnt_stat, p);
220 return (0);
221}
222
223/*
224 * VFS Operations.
225 *
226 * mount system call
227 */
228int
229cd9660_mount(mp, path, data, ndp, p)
230 register struct mount *mp;
231 char *path;
232 caddr_t data;
233 struct nameidata *ndp;
234 struct proc *p;
235{
236 struct vnode *devvp;
237 struct iso_args args;
238 size_t size;
239 int error;
240 struct iso_mnt *imp = NULL;
241
242 if ((error = copyin(data, (caddr_t)&args, sizeof (struct iso_args))))
243 return (error);
244
245 if ((mp->mnt_flag & MNT_RDONLY) == 0)
246 return (EROFS);
247
248 /*
249 * If updating, check whether changing from read-only to
250 * read/write; if there is no device name, that's all we do.
251 */
252 if (mp->mnt_flag & MNT_UPDATE) {
253 imp = VFSTOISOFS(mp);
254 if (args.fspec == 0)
255 return (vfs_export(mp, &imp->im_export, &args.export));
256 }
257 /*
258 * Not an update, or updating the name: look up the name
259 * and verify that it refers to a sensible block device.
260 */
261 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
262 if ((error = namei(ndp)))
263 return (error);
264 devvp = ndp->ni_vp;
265
266 if (devvp->v_type != VBLK) {
267 vrele(devvp);
268 return (ENOTBLK);
269 }
270 if (major(devvp->v_rdev) >= nblkdev) {
271 vrele(devvp);
272 return (ENXIO);
273 }
274 if ((mp->mnt_flag & MNT_UPDATE) == 0)
275 error = iso_mountfs(devvp, mp, p, &args);
276 else {
277 if (devvp != imp->im_devvp)
278 error = EINVAL; /* needs translation */
279 else
280 vrele(devvp);
281 }
282 if (error) {
283 vrele(devvp);
284 return (error);
285 }
286
287 /* Indicate that we don't support volfs */
288 mp->mnt_flag &= ~MNT_DOVOLFS;
289
290 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
291 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
292 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
293 &size);
294 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
295 return (0);
296}
297
298/*
299 * Find the BSD device for the physical disk corresponding to the
300 * mount point's device. We use this physical device to read whole
301 * (2352 byte) sectors from the CD to get the content for the video
302 * files (tracks).
303 *
304 * The "path" argument is the path to the block device that the volume
305 * is being mounted on (args.fspec). It should be of the form:
306 * /dev/disk1s0
307 * where the last "s0" part is stripped off to determine the physical
308 * device's path. It is assumed to be in user memory.
309 */
310static struct vnode *
311cd9660_phys_device(char *path, struct proc *p)
312{
313 int err;
314 char *whole_path = NULL; // path to "whole" device
315 char *s, *saved;
316 struct nameidata nd;
317 struct vnode *result;
318 size_t actual_size;
319
320 if (path == NULL)
321 return NULL;
322
323 result = NULL;
324
325 /* Make a copy of the mount from name, then remove trailing "s...". */
326 MALLOC(whole_path, char *, MNAMELEN, M_ISOFSMNT, M_WAITOK);
327 copyinstr(path, whole_path, MNAMELEN-1, &actual_size);
328
329 /*
330 * I would use strrchr or rindex here, but those are declared __private_extern__,
331 * and can't be used across component boundaries at this time.
332 */
333 for (s=whole_path, saved=NULL; *s; ++s)
334 if (*s == 's')
335 saved = s;
336 *saved = '\0';
337
338 /* Lookup the "whole" device. */
339 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, whole_path, p);
340 err = namei(&nd);
341 if (err) {
342 printf("isofs: Cannot find physical device: %s\n", whole_path);
343 goto done;
344 }
345
346 /* Open the "whole" device. */
347 err = VOP_OPEN(nd.ni_vp, FREAD, FSCRED, p);
348 if (err) {
349 vrele(nd.ni_vp);
350 printf("isofs: Cannot open physical device: %s\n", whole_path);
351 goto done;
352 }
353
354 result = nd.ni_vp;
355
356done:
357 FREE(whole_path, M_ISOFSMNT);
358 return result;
359}
360
361
362/*
363 * See if the given CD-ROM XA disc appears to be a Video CD
364 * (version < 2.0; so, not SVCD). If so, fill in the extent
365 * information for the MPEGAV directory, set the VCD flag,
366 * and return true.
367 */
368static int
369cd9660_find_video_dir(struct iso_mnt *isomp)
370{
371 int result, err;
372 struct vnode *rootvp = NULL;
373 struct vnode *videovp = NULL;
374 struct componentname cn;
375 char dirname[] = "MPEGAV";
376
377 result = 0; /* Assume not a video CD */
378
379 err = cd9660_root(isomp->im_mountp, &rootvp);
380 if (err) {
381 printf("cd9660_find_video_dir: cd9660_root failed (%d)\n", err);
382 return 0; /* couldn't find video dir */
383 }
384
385 cn.cn_nameiop = LOOKUP;
386 cn.cn_flags = LOCKPARENT|ISLASTCN;
387 cn.cn_proc = current_proc();
388 cn.cn_cred = cn.cn_proc->p_ucred;
389 cn.cn_pnbuf = dirname;
390 cn.cn_pnlen = sizeof(dirname)-1;
391 cn.cn_nameptr = cn.cn_pnbuf;
392 cn.cn_namelen = cn.cn_pnlen;
393
394 err = VOP_LOOKUP(rootvp, &videovp, &cn);
395 if (err == 0) {
396 struct iso_node *ip = VTOI(videovp);
397 result = 1; /* Looks like video CD */
398 isomp->video_dir_start = ip->iso_start;
399 isomp->video_dir_end = ip->iso_start + (ip->i_size >> isomp->im_bshift);
400 isomp->im_flags2 |= IMF2_IS_VCD;
401 }
402
403 if (videovp != NULL)
404 vput(videovp);
405 if (rootvp != NULL)
406 vput(rootvp);
407
408 return result;
409}
410
411/*
412 * Common code for mount and mountroot
413 */
414static int
415iso_mountfs(devvp, mp, p, argp)
416 register struct vnode *devvp;
417 struct mount *mp;
418 struct proc *p;
419 struct iso_args *argp;
420{
421 register struct iso_mnt *isomp = (struct iso_mnt *)0;
422 struct buf *bp = NULL;
423 struct buf *pribp = NULL, *supbp = NULL;
424 dev_t dev = devvp->v_rdev;
425 int error = EINVAL;
426 int breaderr = 0;
427 int needclose = 0;
428 extern struct vnode *rootvp;
429 u_long iso_bsize;
430 int iso_blknum;
431 int joliet_level;
432 struct iso_volume_descriptor *vdp = NULL;
433 struct iso_primary_descriptor *pri = NULL;
434 struct iso_primary_descriptor *sup = NULL;
435 struct iso_directory_record *rootp;
436 int logical_block_size;
437 u_int8_t vdtype;
438 int blkoff = argp->ssector;
439
440 if (!(mp->mnt_flag & MNT_RDONLY))
441 return (EROFS);
442
443 /*
444 * Disallow multiple mounts of the same device.
445 * Disallow mounting of a device that is currently in use
446 * (except for root, which might share swap device for miniroot).
447 * Flush out any old buffers remaining from a previous use.
448 */
449 if ((error = vfs_mountedon(devvp)))
450 return (error);
451 if (vcount(devvp) > 1 && devvp != rootvp)
452 return (EBUSY);
453 if ((error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)))
454 return (error);
455
456 if ((error = VOP_OPEN(devvp, FREAD, FSCRED, p)))
457 return (error);
458 needclose = 1;
459
460 /* This is the "logical sector size". The standard says this
461 * should be 2048 or the physical sector size on the device,
462 * whichever is greater. For now, we'll just use a constant.
463 */
464 iso_bsize = ISO_DEFAULT_BLOCK_SIZE;
465
466 /* tell IOKit that we're assuming 2K sectors */
467 if ((error = VOP_IOCTL(devvp, DKIOCSETBLOCKSIZE,
468 (caddr_t)&iso_bsize, FWRITE, p->p_ucred, p)))
469 return (error);
470 devvp->v_specsize = iso_bsize;
471 joliet_level = 0;
472 for (iso_blknum = 16 + blkoff; iso_blknum < (100 + blkoff); iso_blknum++) {
473 if ((error = bread(devvp, iso_blknum, iso_bsize, NOCRED, &bp))) {
474 if (bp) {
475 bp->b_flags |= B_AGE;
476 brelse(bp);
477 bp = NULL;
478 }
479 breaderr = error;
480 printf("iso_mountfs: bread error %d reading block %d\n", error, iso_blknum);
481 continue;
482 }
483
484 vdp = (struct iso_volume_descriptor *)bp->b_data;
485 if (bcmp (vdp->volume_desc_id, ISO_STANDARD_ID, sizeof(vdp->volume_desc_id)) != 0) {
486#ifdef DEBUG
487 printf("cd9660_vfsops.c: iso_mountfs: "
488 "Invalid ID in volume desciptor.\n");
489#endif
490 /* There should be a primary volume descriptor followed by any
491 * secondary volume descriptors, then an end volume descriptor.
492 * Some discs are mastered without an end volume descriptor or
493 * they have the type field set and the volume descriptor ID is
494 * not set. If we at least found a primary volume descriptor,
495 * mount the disc.
496 */
497 if (pri != NULL)
498 break;
499
500 error = EINVAL;
501 goto out;
502 }
503
504 vdtype = isonum_711 (vdp->type);
505 if (vdtype == ISO_VD_END)
506 break;
507
508 if (vdtype == ISO_VD_PRIMARY) {
509 if (pribp == NULL) {
510 pribp = bp;
511 bp = NULL;
512 pri = (struct iso_primary_descriptor *)vdp;
513 }
514 } else if(vdtype == ISO_VD_SUPPLEMENTARY) {
515 if (supbp == NULL) {
516 supbp = bp;
517 bp = NULL;
518 sup = (struct iso_primary_descriptor *)vdp;
519
520 if ((argp->flags & ISOFSMNT_NOJOLIET) == 0) {
521 /*
522 * some Joliet CDs are "out-of-spec and don't correctly
523 * set the SVD flags. We ignore the flags and rely soely
524 * on the escape_seq
525 */
526 if (bcmp(sup->escape_seq, ISO_UCS2_Level_1, 3) == 0)
527 joliet_level = 1;
528 else if (bcmp(sup->escape_seq, ISO_UCS2_Level_2, 3) == 0)
529 joliet_level = 2;
530 else if (bcmp(sup->escape_seq, ISO_UCS2_Level_3, 3) == 0)
531 joliet_level = 3;
532 }
533 }
534 }
535
536 if (bp) {
537 bp->b_flags |= B_AGE;
538 brelse(bp);
539 bp = NULL;
540 }
541 }
542
543 if (bp) {
544 bp->b_flags |= B_AGE;
545 brelse(bp);
546 bp = NULL;
547 }
548
549 if (pri == NULL) {
550 if (breaderr)
551 error = breaderr;
552 else
553 error = EINVAL;
554 goto out;
555 }
556
557 logical_block_size = isonum_723 (pri->logical_block_size);
558
559 if (logical_block_size < DEV_BSIZE || logical_block_size > MAXBSIZE
560 || (logical_block_size & (logical_block_size - 1)) != 0) {
561 error = EINVAL;
562 goto out;
563 }
564
565 rootp = (struct iso_directory_record *)pri->root_directory_record;
566
567 MALLOC(isomp, struct iso_mnt *, sizeof *isomp, M_ISOFSMNT, M_WAITOK);
568 bzero((caddr_t)isomp, sizeof *isomp);
569 isomp->im_sector_size = ISO_DEFAULT_BLOCK_SIZE;
570 isomp->logical_block_size = logical_block_size;
571 isomp->volume_space_size = isonum_733 (pri->volume_space_size);
572 /*
573 * Since an ISO9660 multi-session CD can also access previous
574 * sessions, we have to include them into the space consider-
575 * ations. This doesn't yield a very accurate number since
576 * parts of the old sessions might be inaccessible now, but we
577 * can't do much better. This is also important for the NFS
578 * filehandle validation.
579 */
580 isomp->volume_space_size += blkoff;
581 bcopy (rootp, isomp->root, sizeof isomp->root);
582 isomp->root_extent = isonum_733 (rootp->extent);
583 isomp->root_size = isonum_733 (rootp->size);
584
585 /*
586 * getattrlist wants the volume name, create date and modify date
587 */
588
589 /* Remove any trailing white space */
590 if ( strlen(pri->volume_id) ) {
591 char *myPtr;
592
593 myPtr = pri->volume_id + strlen( pri->volume_id ) - 1;
594 while ( *myPtr == ' ' && myPtr >= pri->volume_id ) {
595 *myPtr = 0x00;
596 myPtr--;
597 }
598 }
599
600 if (pri->volume_id[0] == 0)
601 strcpy(isomp->volume_id, ISO_DFLT_VOLUME_ID);
602 else
603 bcopy(pri->volume_id, isomp->volume_id, sizeof(isomp->volume_id));
604 cd9660_tstamp_conv17(pri->creation_date, &isomp->creation_date);
605 cd9660_tstamp_conv17(pri->modification_date, &isomp->modification_date);
606
607 /* See if this is a CD-XA volume */
608 if (bcmp( pri->CDXASignature, ISO_XA_ID,
609 sizeof(pri->CDXASignature) ) == 0 ) {
610 isomp->im_flags2 |= IMF2_IS_CDXA;
611 }
612
613 isomp->im_bmask = logical_block_size - 1;
614 isomp->im_bshift = 0;
615 while ((1 << isomp->im_bshift) < isomp->logical_block_size)
616 isomp->im_bshift++;
617
618 pribp->b_flags |= B_AGE;
619 brelse(pribp);
620 pribp = NULL;
621
622 mp->mnt_data = (qaddr_t)isomp;
623 mp->mnt_stat.f_fsid.val[0] = (long)dev;
624 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
625 mp->mnt_maxsymlinklen = 0;
626 mp->mnt_flag |= MNT_LOCAL;
627
628 isomp->im_mountp = mp;
629 isomp->im_dev = dev;
630 isomp->im_devvp = devvp;
631
632 devvp->v_specflags |= SI_MOUNTEDON;
633
634 /*
635 * If the logical block size is not 2K then we must
636 * set the block device's physical block size to this
637 * disc's logical block size.
638 *
639 */
640 if (logical_block_size != iso_bsize) {
641 iso_bsize = logical_block_size;
642 if ((error = VOP_IOCTL(devvp, DKIOCSETBLOCKSIZE,
643 (caddr_t)&iso_bsize, FWRITE, p->p_ucred, p)))
644 goto out;
645 devvp->v_specsize = iso_bsize;
646 }
647
648 /* Check the Rock Ridge Extention support */
649 if (!(argp->flags & ISOFSMNT_NORRIP)) {
650 if ( (error = bread(isomp->im_devvp,
651 (isomp->root_extent + isonum_711(rootp->ext_attr_length)),
652 isomp->logical_block_size, NOCRED, &bp)) ) {
653
654 printf("iso_mountfs: bread error %d reading block %d\n",
655 error, isomp->root_extent + isonum_711(rootp->ext_attr_length));
656 argp->flags |= ISOFSMNT_NORRIP;
657 goto skipRRIP;
658 }
659 rootp = (struct iso_directory_record *)bp->b_data;
660
661 if ((isomp->rr_skip = cd9660_rrip_offset(rootp,isomp)) < 0) {
662 argp->flags |= ISOFSMNT_NORRIP;
663 } else {
664 argp->flags &= ~ISOFSMNT_GENS;
665 }
666
667 /*
668 * The contents are valid,
669 * but they will get reread as part of another vnode, so...
670 */
671 bp->b_flags |= B_AGE;
672 brelse(bp);
673 bp = NULL;
674 }
675skipRRIP:
676
677 isomp->im_flags = argp->flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS |
678 ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET);
679
680 switch (isomp->im_flags&(ISOFSMNT_NORRIP|ISOFSMNT_GENS)) {
681 default:
682 isomp->iso_ftype = ISO_FTYPE_DEFAULT;
683 break;
684 case ISOFSMNT_GENS|ISOFSMNT_NORRIP:
685 isomp->iso_ftype = ISO_FTYPE_9660;
686 break;
687 case 0:
688 isomp->iso_ftype = ISO_FTYPE_RRIP;
689 break;
690 }
691
692 /* Decide whether to use the Joliet descriptor */
693
694 if (isomp->iso_ftype != ISO_FTYPE_RRIP && joliet_level != 0) {
695 char vol_id[32];
696 int i, convflags;
697 size_t convbytes;
698 u_int16_t *uchp;
699
700 /*
701 * On Joliet CDs use the UCS-2 volume identifier.
702 *
703 * This name can have up to 16 UCS-2 chars.
704 */
705 convflags = UTF_DECOMPOSED;
706 if (BYTE_ORDER != BIG_ENDIAN)
707 convflags |= UTF_REVERSE_ENDIAN;
708 uchp = (u_int16_t *)sup->volume_id;
709 for (i = 0; i < 16 && uchp[i]; ++i);
710 if ((utf8_encodestr((u_int16_t *)sup->volume_id, (i * 2), vol_id,
711 &convbytes, sizeof(vol_id), 0, convflags) == 0)
712 && convbytes && (vol_id[0] != ' ')) {
713 char * strp;
714
715 /* Remove trailing spaces */
716 strp = vol_id + convbytes - 1;
717 while (strp > vol_id && *strp == ' ')
718 *strp-- = '\0';
719 bcopy(vol_id, isomp->volume_id, convbytes + 1);
720 }
721
722 rootp = (struct iso_directory_record *)
723 sup->root_directory_record;
724 bcopy (rootp, isomp->root, sizeof isomp->root);
725 isomp->root_extent = isonum_733 (rootp->extent);
726 isomp->root_size = isonum_733 (rootp->size);
727 supbp->b_flags |= B_AGE;
728 isomp->iso_ftype = ISO_FTYPE_JOLIET;
729 }
730
731 if (supbp) {
732 brelse(supbp);
733 supbp = NULL;
734 }
735
736 /* If there was a TOC in the arguments, copy it in. */
737 if (argp->flags & ISOFSMNT_TOC) {
738 MALLOC(isomp->toc, struct CDTOC *, argp->toc_length, M_ISOFSMNT, M_WAITOK);
739 if ((error = copyin(argp->toc, isomp->toc, argp->toc_length)))
740 goto out;
741 }
742
743 /* See if this could be a Video CD */
744 if ((isomp->im_flags2 & IMF2_IS_CDXA) && cd9660_find_video_dir(isomp)) {
745 /* Get the 2352-bytes-per-block device. */
746 isomp->phys_devvp = cd9660_phys_device(argp->fspec, p);
747 }
748
749 return (0);
750out:
751 if (bp)
752 brelse(bp);
753 if (pribp)
754 brelse(pribp);
755 if (supbp)
756 brelse(supbp);
757 if (needclose)
758 (void)VOP_CLOSE(devvp, FREAD, NOCRED, p);
759 if (isomp) {
760 if (isomp->toc)
761 FREE((caddr_t)isomp->toc, M_ISOFSMNT);
762 FREE((caddr_t)isomp, M_ISOFSMNT);
763 mp->mnt_data = (qaddr_t)0;
764 }
765
766 /* Clear the mounted on bit in the devvp If it */
767 /* not set, this is a nop and there is no way to */
768 /* get here with it set unless we did it. If you*/
769 /* are making code changes which makes the above */
770 /* assumption not true, change this code. */
771
772 devvp->v_specflags &= ~SI_MOUNTEDON;
773
774 return (error);
775}
776
777/*
778 * Make a filesystem operational.
779 * Nothing to do at the moment.
780 */
781/* ARGSUSED */
782int
783cd9660_start(mp, flags, p)
784 struct mount *mp;
785 int flags;
786 struct proc *p;
787{
788 return (0);
789}
790
791/*
792 * unmount system call
793 */
794int
795cd9660_unmount(mp, mntflags, p)
796 struct mount *mp;
797 int mntflags;
798 struct proc *p;
799{
800 register struct iso_mnt *isomp;
801 int error, flags = 0;
802 int force = 0;
803
804 if ( (mntflags & MNT_FORCE) ) {
805 flags |= FORCECLOSE;
806 force = 1;
807 }
808
809 if ( (error = vflush(mp, NULLVP, flags)) && !force )
810 return (error);
811
812 isomp = VFSTOISOFS(mp);
813
814#ifdef ISODEVMAP
815 if (isomp->iso_ftype == ISO_FTYPE_RRIP)
816 iso_dunmap(isomp->im_dev);
817#endif
818
819 isomp->im_devvp->v_specflags &= ~SI_MOUNTEDON;
820 error = VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, p);
821 if (error && !force )
822 return(error);
823
824 vrele(isomp->im_devvp);
825
826 if (isomp->phys_devvp) {
827 error = VOP_CLOSE(isomp->phys_devvp, FREAD, FSCRED, p);
828 if (error && !force)
829 return error;
830 vrele(isomp->phys_devvp);
831 }
832
833 if (isomp->toc)
834 FREE((caddr_t)isomp->toc, M_ISOFSMNT);
835
836 FREE((caddr_t)isomp, M_ISOFSMNT);
837 mp->mnt_data = (qaddr_t)0;
838 mp->mnt_flag &= ~MNT_LOCAL;
839 return (0);
840}
841
842/*
843 * Return root of a filesystem
844 */
845int
846cd9660_root(mp, vpp)
847 struct mount *mp;
848 struct vnode **vpp;
849{
850 struct iso_mnt *imp = VFSTOISOFS(mp);
851 struct iso_directory_record *dp =
852 (struct iso_directory_record *)imp->root;
853 ino_t ino = isodirino(dp, imp);
854
855 /*
856 * With RRIP we must use the `.' entry of the root directory.
857 * Simply tell vget, that it's a relocated directory.
858 */
859 return (cd9660_vget_internal(mp, ino, vpp,
860 imp->iso_ftype == ISO_FTYPE_RRIP, dp, current_proc()));
861}
862
863/*
864 * Do operations associated with quotas, not supported
865 */
866/* ARGSUSED */
867int
868cd9660_quotactl(mp, cmd, uid, arg, p)
869 struct mount *mp;
870 int cmd;
871 uid_t uid;
872 caddr_t arg;
873 struct proc *p;
874{
875
876 return (EOPNOTSUPP);
877}
878
879/*
880 * Get file system statistics.
881 */
882int
883cd9660_statfs(mp, sbp, p)
884 struct mount *mp;
885 register struct statfs *sbp;
886 struct proc *p;
887{
888 register struct iso_mnt *isomp;
889
890 isomp = VFSTOISOFS(mp);
891
892#ifdef COMPAT_09
893 sbp->f_type = 5;
894#else
895 sbp->f_type = 0;
896#endif
897 sbp->f_bsize = isomp->logical_block_size;
898 sbp->f_iosize = sbp->f_bsize; /* XXX */
899 sbp->f_blocks = isomp->volume_space_size;
900 sbp->f_bfree = 0; /* total free blocks */
901 sbp->f_bavail = 0; /* blocks free for non superuser */
902 sbp->f_files = 0; /* total files */
903 sbp->f_ffree = 0; /* free file nodes */
904 if (sbp != &mp->mnt_stat) {
905 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
906 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
907 }
908
909 strncpy( sbp->f_fstypename, mp->mnt_vfc->vfc_name, (MFSNAMELEN - 1) );
910 sbp->f_fstypename[(MFSNAMELEN - 1)] = '\0';
911
912 /* DO NOT use the first spare for flags; it's been reassigned for another use: */
913 /* sbp->f_spare[0] = isomp->im_flags; */
914
915 return (0);
916}
917
918/* ARGSUSED */
919int
920cd9660_sync(mp, waitfor, cred, p)
921 struct mount *mp;
922 int waitfor;
923 struct ucred *cred;
924 struct proc *p;
925{
926
927 return (0);
928}
929
930/*
931 * File handle to vnode
932 *
933 * Have to be really careful about stale file handles:
934 * - check that the inode number is in range
935 * - call iget() to get the locked inode
936 * - check for an unallocated inode (i_mode == 0)
937 * - check that the generation number matches
938 */
939
940struct ifid {
941 ushort ifid_len;
942 ushort ifid_pad;
943 int ifid_ino;
944 long ifid_start;
945};
946
947/* ARGSUSED */
948int
949cd9660_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
950 register struct mount *mp;
951 struct fid *fhp;
952 struct mbuf *nam;
953 struct vnode **vpp;
954 int *exflagsp;
955 struct ucred **credanonp;
956{
957 struct ifid *ifhp = (struct ifid *)fhp;
958 register struct iso_node *ip;
959 register struct netcred *np;
960 register struct iso_mnt *imp = VFSTOISOFS(mp);
961 struct vnode *nvp;
962 int error;
963
964#ifdef ISOFS_DBG
965 printf("fhtovp: ino %d, start %ld\n",
966 ifhp->ifid_ino, ifhp->ifid_start);
967#endif
968
969 /*
970 * Get the export permission structure for this <mp, client> tuple.
971 */
972 np = vfs_export_lookup(mp, &imp->im_export, nam);
973 if (nam && (np == NULL))
974 return (EACCES);
975
976 if ( (error = VFS_VGET(mp, &ifhp->ifid_ino, &nvp)) ) {
977 *vpp = NULLVP;
978 return (error);
979 }
980 ip = VTOI(nvp);
981 if (ip->inode.iso_mode == 0) {
982 vput(nvp);
983 *vpp = NULLVP;
984 return (ESTALE);
985 }
986 *vpp = nvp;
987 if (np) {
988 *exflagsp = np->netc_exflags;
989 *credanonp = &np->netc_anon;
990 }
991 return (0);
992}
993
994/*
995 * Scan the TOC for the track which contains the given sector.
996 *
997 * If there is no matching track, or no TOC, then return -1.
998 */
999static int
1000cd9660_track_for_sector(struct CDTOC *toc, u_int sector)
1001{
1002 int i, tracks, result;
1003
1004 if (toc == NULL)
1005 return -1;
1006
1007 tracks = toc->length / sizeof(struct CDTOC_Desc);
1008
1009 result = -1; /* Sentinel in case we don't find the right track. */
1010 for (i=0; i<tracks; ++i) {
1011 if (toc->trackdesc[i].point < 100 && MSF_TO_LBA(toc->trackdesc[i].p) <= sector) {
1012 result = toc->trackdesc[i].point;
1013 }
1014 }
1015
1016 return result;
1017}
1018
1019/*
1020 * Determine whether the given node is really a video CD video
1021 * file. Return non-zero if it appears to be a video file.
1022 */
1023static int
1024cd9660_is_video_file(struct iso_node *ip, struct iso_mnt *imp)
1025{
1026 int lbn;
1027 int track;
1028
1029 /* Check whether this could really be a Video CD at all */
1030 if (((imp->im_flags2 & IMF2_IS_VCD) == 0) ||
1031 imp->phys_devvp == NULL ||
1032 imp->toc == NULL)
1033 {
1034 return 0; /* Doesn't even look like VCD... */
1035 }
1036
1037 /* Make sure it is a file */
1038 if ((ip->inode.iso_mode & S_IFMT) != S_IFREG)
1039 return 0; /* Not even a file... */
1040
1041 /*
1042 * And in the right directory. This assumes the same inode
1043 * number convention that cd9660_vget_internal uses (that
1044 * part of the inode number is the block containing the
1045 * file's directory entry).
1046 */
1047 lbn = lblkno(imp, ip->i_number);
1048 if (lbn < imp->video_dir_start || lbn >= imp->video_dir_end)
1049 return 0; /* Not in the correct directory */
1050
1051 /*
1052 * If we get here, the file should be a video file, but
1053 * do a couple of extra sanity checks just to be sure.
1054 * First, verify the form of the name
1055 */
1056 if (strlen(ip->i_namep) != 11 || /* Wrong length? */
1057 bcmp(ip->i_namep+7, ".DAT", 4) || /* Wrong extension? */
1058 (bcmp(ip->i_namep, "AVSEQ", 5) && /* Wrong beginning? */
1059 bcmp(ip->i_namep, "MUSIC", 5)))
1060 {
1061 return 0; /* Invalid name format */
1062 }
1063
1064 /*
1065 * Verify that AVSEQnn.DAT is in track #(nn+1). This would
1066 * not be appropriate for Super Video CD, which allows
1067 * multiple sessions, so the track numbers might not
1068 * match up like this.
1069 */
1070 track = (ip->i_namep[5] - '0') * 10 + ip->i_namep[6] - '0';
1071 if (track != (cd9660_track_for_sector(imp->toc, ip->iso_start) - 1))
1072 {
1073 return 0; /* Wrong number in name */
1074 }
1075
1076 /* It must be a video file if we got here. */
1077 return 1;
1078}
1079
1080int
1081cd9660_vget(mp, ino, vpp)
1082 struct mount *mp;
1083 void *ino;
1084 struct vnode **vpp;
1085{
1086 /*
1087 * XXXX
1088 * It would be nice if we didn't always set the `relocated' flag
1089 * and force the extra read, but I don't want to think about fixing
1090 * that right now.
1091 */
1092
1093 return ( cd9660_vget_internal( mp, *(ino_t*)ino, vpp, 0,
1094 (struct iso_directory_record *) 0,
1095 current_proc()) );
1096}
1097
1098int
1099cd9660_vget_internal(mp, ino, vpp, relocated, isodir, p)
1100 struct mount *mp;
1101 ino_t ino;
1102 struct vnode **vpp;
1103 int relocated;
1104 struct iso_directory_record *isodir;
1105 struct proc *p;
1106{
1107 register struct iso_mnt *imp;
1108 struct iso_node *ip;
1109 struct buf *bp;
1110 struct vnode *vp, *nvp;
1111 dev_t dev;
1112 int error;
1113
1114 imp = VFSTOISOFS(mp);
1115 dev = imp->im_dev;
1116
1117 /* Check for unmount in progress */
1118 if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
1119 *vpp = NULLVP;
1120 return (EPERM);
1121 }
1122
1123 if ((*vpp = cd9660_ihashget(dev, ino, p)) != NULLVP)
1124 return (0);
1125
1126 MALLOC_ZONE(ip, struct iso_node *, sizeof(struct iso_node),
1127 M_ISOFSNODE, M_WAITOK);
1128 /* Allocate a new vnode/iso_node. */
1129 if ( (error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, &vp)) ) {
1130 FREE_ZONE(ip,sizeof(struct iso_node), M_ISOFSNODE);
1131 *vpp = NULLVP;
1132 return (error);
1133 }
1134 bzero((caddr_t)ip, sizeof(struct iso_node));
1135 lockinit(&ip->i_lock, PINOD,"isonode",0,0);
1136 vp->v_data = ip;
1137 ip->i_vnode = vp;
1138 ip->i_dev = dev;
1139 ip->i_number = ino;
1140 ip->i_namep = &isonullname[0];
1141
1142 /*
1143 * Put it onto its hash chain and lock it so that other requests for
1144 * this inode will block if they arrive while we are sleeping waiting
1145 * for old data structures to be purged or for the contents of the
1146 * disk portion of this inode to be read.
1147 */
1148 cd9660_ihashins(ip);
1149
1150 if (isodir == 0) {
1151 int lbn, off;
1152
1153 lbn = lblkno(imp, ino);
1154 if (lbn >= imp->volume_space_size) {
1155 vput(vp);
1156 printf("fhtovp: lbn exceed volume space %d\n", lbn);
1157 return (ESTALE);
1158 }
1159
1160 off = blkoff(imp, ino);
1161 if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) {
1162 vput(vp);
1163 printf("fhtovp: crosses block boundary %d\n",
1164 off + ISO_DIRECTORY_RECORD_SIZE);
1165 return (ESTALE);
1166 }
1167
1168 error = bread(imp->im_devvp, lbn,
1169 imp->logical_block_size, NOCRED, &bp);
1170 if (error) {
1171 vput(vp);
1172 brelse(bp);
1173 printf("fhtovp: bread error %d\n",error);
1174 return (error);
1175 }
1176 isodir = (struct iso_directory_record *)(bp->b_data + off);
1177
1178 if (off + isonum_711(isodir->length) >
1179 imp->logical_block_size) {
1180 vput(vp);
1181 if (bp != 0)
1182 brelse(bp);
1183 printf("fhtovp: directory crosses block boundary "
1184 "%d[off=%d/len=%d]\n",
1185 off +isonum_711(isodir->length), off,
1186 isonum_711(isodir->length));
1187 return (ESTALE);
1188 }
1189
1190 /*
1191 * for directories we can get parentID from adjacent
1192 * parent directory record
1193 */
1194 if ((isonum_711(isodir->flags) & directoryBit)
1195 && (isodir->name[0] == 0)) {
1196 struct iso_directory_record *pdp;
1197
1198 pdp = (struct iso_directory_record *)
1199 ((char *)bp->b_data + isonum_711(isodir->length));
1200 if ((isonum_711(pdp->flags) & directoryBit)
1201 && (pdp->name[0] == 1))
1202 ip->i_parent = isodirino(pdp, imp);
1203 }
1204 } else
1205 bp = 0;
1206
1207 ip->i_mnt = imp;
1208 ip->i_devvp = imp->im_devvp;
1209 VREF(ip->i_devvp);
1210
1211 if (relocated) {
1212 /*
1213 * On relocated directories we must
1214 * read the `.' entry out of a dir.
1215 */
1216 ip->iso_start = ino >> imp->im_bshift;
1217 if (bp != 0)
1218 brelse(bp);
1219 if ( (error = VOP_BLKATOFF(vp, (off_t)0, NULL, &bp)) ) {
1220 vput(vp);
1221 return (error);
1222 }
1223 isodir = (struct iso_directory_record *)bp->b_data;
1224 }
1225
1226 /*
1227 * go get apple extensions to ISO directory record or use
1228 * defaults when there are no apple extensions.
1229 */
1230 if ( ((isonum_711( isodir->flags ) & directoryBit) == 0) &&
1231 (imp->iso_ftype != ISO_FTYPE_RRIP) ) {
1232 /* This is an ISO directory record for a file */
1233 DRGetTypeCreatorAndFlags(imp, isodir, &ip->i_FileType,
1234 &ip->i_Creator, &ip->i_FinderFlags);
1235
1236 if (isonum_711(isodir->flags) & associatedBit)
1237 ip->i_flag |= ISO_ASSOCIATED;
1238 }
1239
1240 /*
1241 * Shadow the ISO 9660 invisible state to the FinderInfo
1242 */
1243 if (isonum_711(isodir->flags) & existenceBit) {
1244 ip->i_FinderFlags |= fInvisibleBit;
1245 }
1246
1247 ip->iso_extent = isonum_733(isodir->extent);
1248 ip->i_size = isonum_733(isodir->size);
1249 ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
1250 /*
1251 * account for AppleDouble header
1252 */
1253 if (ip->i_flag & ISO_ASSOCIATED)
1254 ip->i_size += ADH_SIZE;
1255
1256 /*
1257 * if we have a valid name, fill in i_namep with UTF-8 name
1258 */
1259 if (isonum_711(isodir->name_len) != 0) {
1260 u_char *utf8namep;
1261 u_short namelen;
1262 ino_t inump = 0;
1263
1264 MALLOC(utf8namep, u_char *, ISO_RRIP_NAMEMAX + 1, M_TEMP, M_WAITOK);
1265 namelen = isonum_711(isodir->name_len);
1266
1267 switch (imp->iso_ftype) {
1268 case ISO_FTYPE_RRIP:
1269 cd9660_rrip_getname(isodir, utf8namep, &namelen, &inump, imp);
1270 break;
1271
1272 case ISO_FTYPE_JOLIET:
1273 ucsfntrans((u_int16_t *)isodir->name, namelen,
1274 utf8namep, &namelen,
1275 isonum_711(isodir->flags) & directoryBit, ip->i_flag & ISO_ASSOCIATED);
1276 break;
1277
1278 default:
1279 isofntrans (isodir->name, namelen,
1280 utf8namep, &namelen,
1281 imp->iso_ftype == ISO_FTYPE_9660, ip->i_flag & ISO_ASSOCIATED);
1282 }
1283
1284 utf8namep[namelen] = '\0';
1285 MALLOC(ip->i_namep, u_char *, namelen + 1, M_TEMP, M_WAITOK);
1286 bcopy(utf8namep, ip->i_namep, namelen + 1);
1287 FREE(utf8namep, M_TEMP);
1288 }
1289
1290 /*
1291 * Setup time stamp, attribute
1292 */
1293 vp->v_type = VNON;
1294 switch (imp->iso_ftype) {
1295 default: /* ISO_FTYPE_9660 */
1296 {
1297 struct buf *bp2;
1298 int off;
1299 if ((imp->im_flags & ISOFSMNT_EXTATT)
1300 && (off = isonum_711(isodir->ext_attr_length)))
1301 VOP_BLKATOFF(vp, (off_t)-(off << imp->im_bshift), NULL, &bp2);
1302 else
1303 bp2 = NULL;
1304 cd9660_defattr(isodir, ip, bp2);
1305 cd9660_deftstamp(isodir, ip, bp2);
1306 if (bp2)
1307 brelse(bp2);
1308 break;
1309 }
1310 case ISO_FTYPE_RRIP:
1311 cd9660_rrip_analyze(isodir, ip, imp);
1312 break;
1313 }
1314
1315 /*
1316 * See if this is a Video CD file. If so, we must adjust the
1317 * length to account for larger sectors plus the RIFF header.
1318 * We also must substitute the VOP_READ and VOP_PAGEIN functions.
1319 *
1320 * The cd9660_is_video_file routine assumes that the inode has
1321 * been completely set up; it refers to several fields.
1322 *
1323 * This must be done before we release bp, because isodir
1324 * points into bp's data.
1325 */
1326 if (cd9660_is_video_file(ip, imp))
1327 {
1328 cd9660_xa_init(vp, isodir);
1329 }
1330
1331 if (bp != 0)
1332 brelse(bp);
1333
1334 /*
1335 * Initialize the associated vnode
1336 */
1337
1338 if (ip->iso_extent == imp->root_extent) {
1339 vp->v_flag |= VROOT;
1340 ip->i_parent = 1; /* root's parent is always 1 by convention */
1341 /* mode type must be S_IFDIR */
1342 ip->inode.iso_mode = (ip->inode.iso_mode & ~S_IFMT) | S_IFDIR;
1343 }
1344
1345 switch (vp->v_type = IFTOVT(ip->inode.iso_mode)) {
1346 case VFIFO:
1347#if FIFO
1348 vp->v_op = cd9660_fifoop_p;
1349 break;
1350#else
1351 vput(vp);
1352 return (EOPNOTSUPP);
1353#endif /* FIFO */
1354 case VCHR:
1355 case VBLK:
1356 /*
1357 * if device, look at device number table for translation
1358 */
1359#ifdef ISODEVMAP
1360 if (dp = iso_dmap(dev, ino, 0))
1361 ip->inode.iso_rdev = dp->d_dev;
1362#endif
1363 vp->v_op = cd9660_specop_p;
1364 if ( (nvp = checkalias(vp, ip->inode.iso_rdev, mp)) ) {
1365 /*
1366 * Discard unneeded vnode, but save its iso_node.
1367 */
1368 cd9660_ihashrem(ip);
1369 VOP_UNLOCK(vp, 0, p);
1370 nvp->v_data = vp->v_data;
1371 vp->v_data = NULL;
1372 vp->v_op = spec_vnodeop_p;
1373 vrele(vp);
1374 vgone(vp);
1375 /*
1376 * Reinitialize aliased inode.
1377 */
1378 vp = nvp;
1379 ip->i_vnode = vp;
1380 cd9660_ihashins(ip);
1381 }
1382 break;
1383 case VREG:
1384 ubc_info_init(vp);
1385 break;
1386 default:
1387 break;
1388 }
1389
1390 /*
1391 * XXX need generation number?
1392 */
1393
1394 *vpp = vp;
1395
1396 return (0);
1397}
1398
1399
1400/************************************************************************
1401 *
1402 * Function: DRGetTypeCreatorAndFlags
1403 *
1404 * Purpose: Set up the fileType, fileCreator and fileFlags
1405 *
1406 * Returns: none
1407 *
1408 * Side Effects: sets *theTypePtr, *theCreatorPtr, and *theFlagsPtr
1409 *
1410 * Description:
1411 *
1412 * Revision History:
1413