]> git.saurik.com Git - apple/xnu.git/blame - bsd/isofs/cd9660/cd9660_vfsops.c
xnu-124.13.tar.gz
[apple/xnu.git] / bsd / isofs / cd9660 / cd9660_vfsops.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
11 *
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
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/* $NetBSD: cd9660_vfsops.c,v 1.18 1995/03/09 12:05:36 mycroft Exp $ */
23
24/*-
25 * Copyright (c) 1994
26 * The Regents of the University of California. All rights reserved.
27 *
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).
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
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.
48 *
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
59 * SUCH DAMAGE.
60 *
61 * @(#)cd9660_vfsops.c 8.9 (Berkeley) 12/5/94
62 */
63
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>
69#include <sys/proc.h>
70#include <sys/kernel.h>
71#include <miscfs/specfs/specdev.h>
72#include <sys/buf.h>
73#include <sys/file.h>
74#include <sys/ioctl.h>
75#include <dev/disk.h>
76#include <sys/errno.h>
77#include <sys/malloc.h>
78#include <sys/stat.h>
79#include <sys/ubc.h>
80
81#include <isofs/cd9660/iso.h>
82#include <isofs/cd9660/iso_rrip.h>
83#include <isofs/cd9660/cd9660_node.h>
84#include <isofs/cd9660/cd9660_mount.h>
85
86u_char isonullname[] = "\0";
87
88extern int enodev ();
89
90struct vfsops cd9660_vfsops = {
91 cd9660_mount,
92 cd9660_start,
93 cd9660_unmount,
94 cd9660_root,
95 cd9660_quotactl,
96 cd9660_statfs,
97 cd9660_sync,
98 cd9660_vget,
99 cd9660_fhtovp,
100 cd9660_vptofh,
101 cd9660_init,
102 cd9660_sysctl
103};
104
105/*
106 * Called by vfs_mountroot when iso is going to be mounted as root.
107 *
108 * Name is updated by mount(8) after booting.
109 */
110#define ROOTNAME "root_device"
111
112static int iso_mountfs __P((struct vnode *devvp, struct mount *mp,
113 struct proc *p, struct iso_args *argp));
114
115static void DRGetTypeCreatorAndFlags(
116 struct iso_mnt * theMountPointPtr,
117 struct iso_directory_record * theDirRecPtr,
118 u_int32_t * theTypePtr,
119 u_int32_t * theCreatorPtr,
120 u_int16_t * theFlagsPtr);
121
122int cd9660_vget_internal(
123 struct mount *mp,
124 ino_t ino,
125 struct vnode **vpp,
126 int relocated,
127 struct iso_directory_record *isodir,
128 struct proc *p);
129
130int
131cd9660_mountroot()
132{
133 register struct mount *mp;
134 extern struct vnode *rootvp;
135 struct proc *p = current_proc(); /* XXX */
136 struct iso_mnt *imp;
137 size_t size;
138 int error;
139 struct iso_args args;
140
141 /*
142 * Get vnodes for swapdev and rootdev.
143 */
144 if ( bdevvp(rootdev, &rootvp))
145 panic("cd9660_mountroot: can't setup bdevvp's");
146
147 MALLOC_ZONE(mp, struct mount *,
148 sizeof(struct mount), M_MOUNT, M_WAITOK);
149 bzero((char *)mp, (u_long)sizeof(struct mount));
150 mp->mnt_op = &cd9660_vfsops;
151 mp->mnt_flag = MNT_RDONLY;
152 LIST_INIT(&mp->mnt_vnodelist);
153 args.flags = ISOFSMNT_ROOT;
154 args.ssector = 0;
155 if ((error = iso_mountfs(rootvp, mp, p, &args))) {
156 FREE_ZONE(mp, sizeof (struct mount), M_MOUNT);
157 return (error);
158 }
159 simple_lock(&mountlist_slock);
160 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
161 simple_unlock(&mountlist_slock);
162 mp->mnt_vnodecovered = NULLVP;
163 imp = VFSTOISOFS(mp);
164 (void) copystr("/", mp->mnt_stat.f_mntonname, MNAMELEN - 1,
165 &size);
166 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
167 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
168 &size);
169 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
170 (void)cd9660_statfs(mp, &mp->mnt_stat, p);
171 return (0);
172}
173
174/*
175 * VFS Operations.
176 *
177 * mount system call
178 */
179int
180cd9660_mount(mp, path, data, ndp, p)
181 register struct mount *mp;
182 char *path;
183 caddr_t data;
184 struct nameidata *ndp;
185 struct proc *p;
186{
187 struct vnode *devvp;
188 struct iso_args args;
189 size_t size;
190 int error;
191 struct iso_mnt *imp = NULL;
192
193 if ((error = copyin(data, (caddr_t)&args, sizeof (struct iso_args))))
194 return (error);
195
196 if ((mp->mnt_flag & MNT_RDONLY) == 0)
197 return (EROFS);
198
199 /*
200 * If updating, check whether changing from read-only to
201 * read/write; if there is no device name, that's all we do.
202 */
203 if (mp->mnt_flag & MNT_UPDATE) {
204 imp = VFSTOISOFS(mp);
205 if (args.fspec == 0)
206 return (vfs_export(mp, &imp->im_export, &args.export));
207 }
208 /*
209 * Not an update, or updating the name: look up the name
210 * and verify that it refers to a sensible block device.
211 */
212 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
213 if ((error = namei(ndp)))
214 return (error);
215 devvp = ndp->ni_vp;
216
217 if (devvp->v_type != VBLK) {
218 vrele(devvp);
219 return (ENOTBLK);
220 }
221 if (major(devvp->v_rdev) >= nblkdev) {
222 vrele(devvp);
223 return (ENXIO);
224 }
225 if ((mp->mnt_flag & MNT_UPDATE) == 0)
226 error = iso_mountfs(devvp, mp, p, &args);
227 else {
228 if (devvp != imp->im_devvp)
229 error = EINVAL; /* needs translation */
230 else
231 vrele(devvp);
232 }
233 if (error) {
234 vrele(devvp);
235 return (error);
236 }
237
238 /* Set the mount flag to indicate that we support volfs */
239 mp->mnt_flag |= MNT_DOVOLFS;
240
241 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
242 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
243 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
244 &size);
245 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
246 return (0);
247}
248
249/*
250 * Common code for mount and mountroot
251 */
252static int
253iso_mountfs(devvp, mp, p, argp)
254 register struct vnode *devvp;
255 struct mount *mp;
256 struct proc *p;
257 struct iso_args *argp;
258{
259 register struct iso_mnt *isomp = (struct iso_mnt *)0;
260 struct buf *bp = NULL;
261 struct buf *pribp = NULL, *supbp = NULL;
262 dev_t dev = devvp->v_rdev;
263 int error = EINVAL;
264 int breaderr = 0;
265 int needclose = 0;
266 extern struct vnode *rootvp;
267 u_long iso_bsize;
268 int iso_blknum;
269 int joliet_level;
270 struct iso_volume_descriptor *vdp = NULL;
271 struct iso_primary_descriptor *pri = NULL;
272 struct iso_primary_descriptor *sup = NULL;
273 struct iso_directory_record *rootp;
274 int logical_block_size;
275 u_int8_t vdtype;
276 int blkoff = argp->ssector;
277
278 if (!(mp->mnt_flag & MNT_RDONLY))
279 return (EROFS);
280
281 /*
282 * Disallow multiple mounts of the same device.
283 * Disallow mounting of a device that is currently in use
284 * (except for root, which might share swap device for miniroot).
285 * Flush out any old buffers remaining from a previous use.
286 */
287 if ((error = vfs_mountedon(devvp)))
288 return (error);
289 if (vcount(devvp) > 1 && devvp != rootvp)
290 return (EBUSY);
291 if ((error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)))
292 return (error);
293
294 if ((error = VOP_OPEN(devvp, FREAD, FSCRED, p)))
295 return (error);
296 needclose = 1;
297
298 /* This is the "logical sector size". The standard says this
299 * should be 2048 or the physical sector size on the device,
300 * whichever is greater. For now, we'll just use a constant.
301 */
302 iso_bsize = ISO_DEFAULT_BLOCK_SIZE;
303
304 /* tell IOKit that we're assuming 2K sectors */
305 if ((error = VOP_IOCTL(devvp, DKIOCSETBLOCKSIZE,
306 (caddr_t)&iso_bsize, FWRITE, p->p_ucred, p)))
307 return (error);
308 devvp->v_specsize = iso_bsize;
309 joliet_level = 0;
310 for (iso_blknum = 16 + blkoff; iso_blknum < (100 + blkoff); iso_blknum++) {
311 if ((error = bread(devvp, iso_blknum, iso_bsize, NOCRED, &bp))) {
312 if (bp) {
313 bp->b_flags |= B_AGE;
314 brelse(bp);
315 bp = NULL;
316 }
317 breaderr = error;
318 printf("iso_mountfs: bread error %d reading block %d\n", error, iso_blknum);
319 continue;
320 }
321
322 vdp = (struct iso_volume_descriptor *)bp->b_data;
323 if (bcmp (vdp->volume_desc_id, ISO_STANDARD_ID, sizeof(vdp->volume_desc_id)) != 0) {
324#ifdef DEBUG
325 printf("cd9660_vfsops.c: iso_mountfs: "
326 "Invalid ID in volume desciptor.\n");
327#endif
328 error = EINVAL;
329 goto out;
330 }
331
332 vdtype = isonum_711 (vdp->type);
333 if (vdtype == ISO_VD_END)
334 break;
335
336 if (vdtype == ISO_VD_PRIMARY) {
337 if (pribp == NULL) {
338 pribp = bp;
339 bp = NULL;
340 pri = (struct iso_primary_descriptor *)vdp;
341 }
342 } else if(vdtype == ISO_VD_SUPPLEMENTARY) {
343 if (supbp == NULL) {
344 supbp = bp;
345 bp = NULL;
346 sup = (struct iso_primary_descriptor *)vdp;
347
348 if ((argp->flags & ISOFSMNT_NOJOLIET) == 0) {
349 /*
350 * some Joliet CDs are "out-of-spec and don't correctly
351 * set the SVD flags. We ignore the flags and rely soely
352 * on the escape_seq
353 */
354 if (bcmp(sup->escape_seq, ISO_UCS2_Level_1, 3) == 0)
355 joliet_level = 1;
356 else if (bcmp(sup->escape_seq, ISO_UCS2_Level_2, 3) == 0)
357 joliet_level = 2;
358 else if (bcmp(sup->escape_seq, ISO_UCS2_Level_3, 3) == 0)
359 joliet_level = 3;
360 }
361 }
362 }
363
364 if (bp) {
365 bp->b_flags |= B_AGE;
366 brelse(bp);
367 bp = NULL;
368 }
369 }
370
371 if (bp) {
372 bp->b_flags |= B_AGE;
373 brelse(bp);
374 bp = NULL;
375 }
376
377 if (pri == NULL) {
378 if (breaderr)
379 error = breaderr;
380 else
381 error = EINVAL;
382 goto out;
383 }
384
385 logical_block_size = isonum_723 (pri->logical_block_size);
386
387 if (logical_block_size < DEV_BSIZE || logical_block_size > MAXBSIZE
388 || (logical_block_size & (logical_block_size - 1)) != 0) {
389 error = EINVAL;
390 goto out;
391 }
392
393 rootp = (struct iso_directory_record *)pri->root_directory_record;
394
395 MALLOC(isomp, struct iso_mnt *, sizeof *isomp, M_ISOFSMNT, M_WAITOK);
396 bzero((caddr_t)isomp, sizeof *isomp);
397 isomp->logical_block_size = logical_block_size;
398 isomp->volume_space_size = isonum_733 (pri->volume_space_size);
399 /*
400 * Since an ISO9660 multi-session CD can also access previous
401 * sessions, we have to include them into the space consider-
402 * ations. This doesn't yield a very accurate number since
403 * parts of the old sessions might be inaccessible now, but we
404 * can't do much better. This is also important for the NFS
405 * filehandle validation.
406 */
407 isomp->volume_space_size += blkoff;
408 bcopy (rootp, isomp->root, sizeof isomp->root);
409 isomp->root_extent = isonum_733 (rootp->extent);
410 isomp->root_size = isonum_733 (rootp->size);
411
412 /*
413 * getattrlist wants the volume name, create date and modify date
414 */
415
416 /* Remove any trailing white space */
417 if ( strlen(pri->volume_id) ) {
418 char *myPtr;
419
420 myPtr = pri->volume_id + strlen( pri->volume_id ) - 1;
421 while ( *myPtr == ' ' && myPtr >= pri->volume_id ) {
422 *myPtr = 0x00;
423 myPtr--;
424 }
425 }
426 /* YYY need to use secondary volume descriptor name for kanji disks */
427 bcopy(pri->volume_id, isomp->volume_id, sizeof(isomp->volume_id));
428 cd9660_tstamp_conv17(pri->creation_date, &isomp->creation_date);
429 cd9660_tstamp_conv17(pri->modification_date, &isomp->modification_date);
430
431 /* See if this is a CD-XA volume */
432 if (bcmp( pri->CDXASignature, ISO_XA_ID,
433 sizeof(pri->CDXASignature) ) == 0 )
434 isomp->im_flags2 |= IMF2_IS_CDXA;
435
436 isomp->im_bmask = logical_block_size - 1;
437 isomp->im_bshift = 0;
438 while ((1 << isomp->im_bshift) < isomp->logical_block_size)
439 isomp->im_bshift++;
440
441 pribp->b_flags |= B_AGE;
442 brelse(pribp);
443 pribp = NULL;
444
445 mp->mnt_data = (qaddr_t)isomp;
446 mp->mnt_stat.f_fsid.val[0] = (long)dev;
447 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
448 mp->mnt_maxsymlinklen = 0;
449 mp->mnt_flag |= MNT_LOCAL;
450
451 isomp->im_mountp = mp;
452 isomp->im_dev = dev;
453 isomp->im_devvp = devvp;
454
455 devvp->v_specflags |= SI_MOUNTEDON;
456
457 /* Check the Rock Ridge Extention support */
458 if (!(argp->flags & ISOFSMNT_NORRIP)) {
459 if ( (error = bread(isomp->im_devvp,
460 (isomp->root_extent + isonum_711(rootp->ext_attr_length)),
461 isomp->logical_block_size, NOCRED, &bp)) ) {
462
463 printf("iso_mountfs: bread error %d reading block %d\n",
464 error, isomp->root_extent + isonum_711(rootp->ext_attr_length));
465 argp->flags |= ISOFSMNT_NORRIP;
466 goto skipRRIP;
467 }
468 rootp = (struct iso_directory_record *)bp->b_data;
469
470 if ((isomp->rr_skip = cd9660_rrip_offset(rootp,isomp)) < 0) {
471 argp->flags |= ISOFSMNT_NORRIP;
472 } else {
473 argp->flags &= ~ISOFSMNT_GENS;
474 }
475
476 /*
477 * The contents are valid,
478 * but they will get reread as part of another vnode, so...
479 */
480 bp->b_flags |= B_AGE;
481 brelse(bp);
482 bp = NULL;
483 }
484skipRRIP:
485
486 isomp->im_flags = argp->flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS |
487 ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET);
488
489 switch (isomp->im_flags&(ISOFSMNT_NORRIP|ISOFSMNT_GENS)) {
490 default:
491 isomp->iso_ftype = ISO_FTYPE_DEFAULT;
492 break;
493 case ISOFSMNT_GENS|ISOFSMNT_NORRIP:
494 isomp->iso_ftype = ISO_FTYPE_9660;
495 break;
496 case 0:
497 isomp->iso_ftype = ISO_FTYPE_RRIP;
498 break;
499 }
500
501 /* Decide whether to use the Joliet descriptor */
502
503 if (isomp->iso_ftype != ISO_FTYPE_RRIP && joliet_level != 0) {
504 rootp = (struct iso_directory_record *)
505 sup->root_directory_record;
506 bcopy (rootp, isomp->root, sizeof isomp->root);
507 isomp->root_extent = isonum_733 (rootp->extent);
508 isomp->root_size = isonum_733 (rootp->size);
509 supbp->b_flags |= B_AGE;
510 isomp->iso_ftype = ISO_FTYPE_JOLIET;
511 }
512
513 if (supbp) {
514 brelse(supbp);
515 supbp = NULL;
516 }
517
518 return (0);
519out:
520 if (bp)
521 brelse(bp);
522 if (pribp)
523 brelse(pribp);
524 if (supbp)
525 brelse(supbp);
526 if (needclose)
527 (void)VOP_CLOSE(devvp, FREAD, NOCRED, p);
528 if (isomp) {
529 FREE((caddr_t)isomp, M_ISOFSMNT);
530 mp->mnt_data = (qaddr_t)0;
531 }
532
533 /* Clear the mounted on bit in the devvp If it */
534 /* not set, this is a nop and there is no way to */
535 /* get here with it set unless we did it. If you*/
536 /* are making code changes which makes the above */
537 /* assumption not true, change this code. */
538
539 devvp->v_specflags &= ~SI_MOUNTEDON;
540
541 return (error);
542}
543
544/*
545 * Make a filesystem operational.
546 * Nothing to do at the moment.
547 */
548/* ARGSUSED */
549int
550cd9660_start(mp, flags, p)
551 struct mount *mp;
552 int flags;
553 struct proc *p;
554{
555 return (0);
556}
557
558/*
559 * unmount system call
560 */
561int
562cd9660_unmount(mp, mntflags, p)
563 struct mount *mp;
564 int mntflags;
565 struct proc *p;
566{
567 register struct iso_mnt *isomp;
568 int error, flags = 0;
569
570 if ( (mntflags & MNT_FORCE) )
571 flags |= FORCECLOSE;
572
573 if ( (error = vflush(mp, NULLVP, flags)) )
574 return (error);
575
576 isomp = VFSTOISOFS(mp);
577
578#ifdef ISODEVMAP
579 if (isomp->iso_ftype == ISO_FTYPE_RRIP)
580 iso_dunmap(isomp->im_dev);
581#endif
582
583 isomp->im_devvp->v_specflags &= ~SI_MOUNTEDON;
584 error = VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, p);
585 vrele(isomp->im_devvp);
586 FREE((caddr_t)isomp, M_ISOFSMNT);
587 mp->mnt_data = (qaddr_t)0;
588 mp->mnt_flag &= ~MNT_LOCAL;
589
590 return (error);
591}
592
593/*
594 * Return root of a filesystem
595 */
596int
597cd9660_root(mp, vpp)
598 struct mount *mp;
599 struct vnode **vpp;
600{
601 struct iso_mnt *imp = VFSTOISOFS(mp);
602 struct iso_directory_record *dp =
603 (struct iso_directory_record *)imp->root;
604 ino_t ino = isodirino(dp, imp);
605
606 /*
607 * With RRIP we must use the `.' entry of the root directory.
608 * Simply tell vget, that it's a relocated directory.
609 */
610 return (cd9660_vget_internal(mp, ino, vpp,
611 imp->iso_ftype == ISO_FTYPE_RRIP, dp, current_proc()));
612}
613
614/*
615 * Do operations associated with quotas, not supported
616 */
617/* ARGSUSED */
618int
619cd9660_quotactl(mp, cmd, uid, arg, p)
620 struct mount *mp;
621 int cmd;
622 uid_t uid;
623 caddr_t arg;
624 struct proc *p;
625{
626
627 return (EOPNOTSUPP);
628}
629
630/*
631 * Get file system statistics.
632 */
633int
634cd9660_statfs(mp, sbp, p)
635 struct mount *mp;
636 register struct statfs *sbp;
637 struct proc *p;
638{
639 register struct iso_mnt *isomp;
640
641 isomp = VFSTOISOFS(mp);
642
643#ifdef COMPAT_09
644 sbp->f_type = 5;
645#else
646 sbp->f_type = 0;
647#endif
648 sbp->f_bsize = isomp->logical_block_size;
649 sbp->f_iosize = sbp->f_bsize; /* XXX */
650 sbp->f_blocks = isomp->volume_space_size;
651 sbp->f_bfree = 0; /* total free blocks */
652 sbp->f_bavail = 0; /* blocks free for non superuser */
653 sbp->f_files = 0; /* total files */
654 sbp->f_ffree = 0; /* free file nodes */
655 if (sbp != &mp->mnt_stat) {
656 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
657 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
658 }
659
660 strncpy( sbp->f_fstypename, mp->mnt_vfc->vfc_name, (MFSNAMELEN - 1) );
661 sbp->f_fstypename[(MFSNAMELEN - 1)] = '\0';
662
663 /* DO NOT use the first spare for flags; it's been reassigned for another use: */
664 /* sbp->f_spare[0] = isomp->im_flags; */
665
666 return (0);
667}
668
669/* ARGSUSED */
670int
671cd9660_sync(mp, waitfor, cred, p)
672 struct mount *mp;
673 int waitfor;
674 struct ucred *cred;
675 struct proc *p;
676{
677
678 return (0);
679}
680
681/*
682 * File handle to vnode
683 *
684 * Have to be really careful about stale file handles:
685 * - check that the inode number is in range
686 * - call iget() to get the locked inode
687 * - check for an unallocated inode (i_mode == 0)
688 * - check that the generation number matches
689 */
690
691struct ifid {
692 ushort ifid_len;
693 ushort ifid_pad;
694 int ifid_ino;
695 long ifid_start;
696};
697
698/* ARGSUSED */
699int
700cd9660_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
701 register struct mount *mp;
702 struct fid *fhp;
703 struct mbuf *nam;
704 struct vnode **vpp;
705 int *exflagsp;
706 struct ucred **credanonp;
707{
708 struct ifid *ifhp = (struct ifid *)fhp;
709 register struct iso_node *ip;
710 register struct netcred *np;
711 register struct iso_mnt *imp = VFSTOISOFS(mp);
712 struct vnode *nvp;
713 int error;
714
715#ifdef ISOFS_DBG
716 printf("fhtovp: ino %d, start %ld\n",
717 ifhp->ifid_ino, ifhp->ifid_start);
718#endif
719
720 /*
721 * Get the export permission structure for this <mp, client> tuple.
722 */
723 np = vfs_export_lookup(mp, &imp->im_export, nam);
724 if (np == NULL)
725 return (EACCES);
726
727 if ( (error = VFS_VGET(mp, &ifhp->ifid_ino, &nvp)) ) {
728 *vpp = NULLVP;
729 return (error);
730 }
731 ip = VTOI(nvp);
732 if (ip->inode.iso_mode == 0) {
733 vput(nvp);
734 *vpp = NULLVP;
735 return (ESTALE);
736 }
737 *vpp = nvp;
738 *exflagsp = np->netc_exflags;
739 *credanonp = &np->netc_anon;
740 return (0);
741}
742
743int
744cd9660_vget(mp, ino, vpp)
745 struct mount *mp;
746 void *ino;
747 struct vnode **vpp;
748{
749 /*
750 * XXXX
751 * It would be nice if we didn't always set the `relocated' flag
752 * and force the extra read, but I don't want to think about fixing
753 * that right now.
754 */
755
756 return ( cd9660_vget_internal( mp, *(ino_t*)ino, vpp, 0,
757 (struct iso_directory_record *) 0,
758 current_proc()) );
759}
760
761int
762cd9660_vget_internal(mp, ino, vpp, relocated, isodir, p)
763 struct mount *mp;
764 ino_t ino;
765 struct vnode **vpp;
766 int relocated;
767 struct iso_directory_record *isodir;
768 struct proc *p;
769{
770 register struct iso_mnt *imp;
771 struct iso_node *ip;
772 struct buf *bp;
773 struct vnode *vp, *nvp;
774 dev_t dev;
775 int error;
776
777 imp = VFSTOISOFS(mp);
778 dev = imp->im_dev;
779
780 /* Check for unmount in progress */
781 if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
782 *vpp = NULLVP;
783 return (EPERM);
784 }
785
786 if ((*vpp = cd9660_ihashget(dev, ino, p)) != NULLVP)
787 return (0);
788
789 MALLOC_ZONE(ip, struct iso_node *, sizeof(struct iso_node),
790 M_ISOFSNODE, M_WAITOK);
791 /* Allocate a new vnode/iso_node. */
792 if ( (error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, &vp)) ) {
793 FREE_ZONE(ip,sizeof(struct iso_node), M_ISOFSNODE);
794 *vpp = NULLVP;
795 return (error);
796 }
797 bzero((caddr_t)ip, sizeof(struct iso_node));
798 lockinit(&ip->i_lock, PINOD,"isonode",0,0);
799 vp->v_data = ip;
800 ip->i_vnode = vp;
801 ip->i_dev = dev;
802 ip->i_number = ino;
803 ip->i_namep = &isonullname[0];
804
805 /*
806 * Put it onto its hash chain and lock it so that other requests for
807 * this inode will block if they arrive while we are sleeping waiting
808 * for old data structures to be purged or for the contents of the
809 * disk portion of this inode to be read.
810 */
811 cd9660_ihashins(ip);
812
813 if (isodir == 0) {
814 int lbn, off;
815
816 lbn = lblkno(imp, ino);
817 if (lbn >= imp->volume_space_size) {
818 vput(vp);
819 printf("fhtovp: lbn exceed volume space %d\n", lbn);
820 return (ESTALE);
821 }
822
823 off = blkoff(imp, ino);
824 if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) {
825 vput(vp);
826 printf("fhtovp: crosses block boundary %d\n",
827 off + ISO_DIRECTORY_RECORD_SIZE);
828 return (ESTALE);
829 }
830
831 error = bread(imp->im_devvp, lbn,
832 imp->logical_block_size, NOCRED, &bp);
833 if (error) {
834 vput(vp);
835 brelse(bp);
836 printf("fhtovp: bread error %d\n",error);
837 return (error);
838 }
839 isodir = (struct iso_directory_record *)(bp->b_data + off);
840
841 if (off + isonum_711(isodir->length) >
842 imp->logical_block_size) {
843 vput(vp);
844 if (bp != 0)
845 brelse(bp);
846 printf("fhtovp: directory crosses block boundary "
847 "%d[off=%d/len=%d]\n",
848 off +isonum_711(isodir->length), off,
849 isonum_711(isodir->length));
850 return (ESTALE);
851 }
852
853 /*
854 * for directories we can get parentID from adjacent
855 * parent directory record
856 */
857 if ((isonum_711(isodir->flags) & directoryBit)
858 && (isodir->name[0] == 0)) {
859 struct iso_directory_record *pdp;
860
861 pdp = (struct iso_directory_record *)
862 ((char *)bp->b_data + isonum_711(isodir->length));
863 if ((isonum_711(pdp->flags) & directoryBit)
864 && (pdp->name[0] == 1))
865 ip->i_parent = isodirino(pdp, imp);
866 }
867 } else
868 bp = 0;
869
870 ip->i_mnt = imp;
871 ip->i_devvp = imp->im_devvp;
872 VREF(ip->i_devvp);
873
874 if (relocated) {
875 /*
876 * On relocated directories we must
877 * read the `.' entry out of a dir.
878 */
879 ip->iso_start = ino >> imp->im_bshift;
880 if (bp != 0)
881 brelse(bp);
882 if ( (error = VOP_BLKATOFF(vp, (off_t)0, NULL, &bp)) ) {
883 vput(vp);
884 return (error);
885 }
886 isodir = (struct iso_directory_record *)bp->b_data;
887 }
888
889 /*
890 * go get apple extensions to ISO directory record or use
891 * defaults when there are no apple extensions.
892 */
893 if ( (isonum_711( isodir->flags ) & directoryBit) == 0 ) {
894 /* This is an ISO directory record for a file */
895 DRGetTypeCreatorAndFlags( imp, isodir, &ip->i_FileType,
896 &ip->i_Creator, &ip->i_FinderFlags );
897 }
898
899 ip->iso_extent = isonum_733(isodir->extent);
900 ip->i_size = isonum_733(isodir->size);
901 ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
902
903 /*
904 * if we have a valid name, fill in i_namep with UTF-8 name
905 */
906 if (isonum_711(isodir->name_len) != 0) {
907 u_char *utf8namep;
908 u_short namelen;
909 ino_t inump = 0;
910
911 MALLOC(utf8namep, u_char *, ISO_RRIP_NAMEMAX + 1, M_TEMP, M_WAITOK);
912 namelen = isonum_711(isodir->name_len);
913
914 switch (imp->iso_ftype) {
915 case ISO_FTYPE_RRIP:
916 cd9660_rrip_getname(isodir, utf8namep, &namelen, &inump, imp);
917 break;
918
919 case ISO_FTYPE_JOLIET:
920 ucsfntrans((u_int16_t *)isodir->name, namelen,
921 utf8namep, &namelen,
922 isonum_711(isodir->flags) & directoryBit);
923 break;
924
925 default:
926 isofntrans (isodir->name, namelen,
927 utf8namep, &namelen,
928 imp->iso_ftype == ISO_FTYPE_9660);
929 }
930
931 utf8namep[namelen] = '\0';
932 MALLOC(ip->i_namep, u_char *, namelen + 1, M_TEMP, M_WAITOK);
933 bcopy(utf8namep, ip->i_namep, namelen + 1);
934 FREE(utf8namep, M_TEMP);
935 }
936
937 /*
938 * Setup time stamp, attribute
939 */
940 vp->v_type = VNON;
941 switch (imp->iso_ftype) {
942 default: /* ISO_FTYPE_9660 */
943 {
944 struct buf *bp2;
945 int off;
946 if ((imp->im_flags & ISOFSMNT_EXTATT)
947 && (off = isonum_711(isodir->ext_attr_length)))
948 VOP_BLKATOFF(vp, (off_t)-(off << imp->im_bshift), NULL, &bp2);
949 else
950 bp2 = NULL;
951 cd9660_defattr(isodir, ip, bp2);
952 cd9660_deftstamp(isodir, ip, bp2);
953 if (bp2)
954 brelse(bp2);
955 break;
956 }
957 case ISO_FTYPE_RRIP:
958 cd9660_rrip_analyze(isodir, ip, imp);
959 break;
960 }
961
962 if (bp != 0)
963 brelse(bp);
964
965 /*
966 * Initialize the associated vnode
967 */
968
969 if (ip->iso_extent == imp->root_extent) {
970 vp->v_flag |= VROOT;
971 ip->i_parent = 1; /* root's parent is always 1 by convention */
972 /* mode type must be S_IFDIR */
973 ip->inode.iso_mode = (ip->inode.iso_mode & ~S_IFMT) | S_IFDIR;
974 }
975
976 switch (vp->v_type = IFTOVT(ip->inode.iso_mode)) {
977 case VFIFO:
978#if FIFO
979 vp->v_op = cd9660_fifoop_p;
980 break;
981#else
982 vput(vp);
983 return (EOPNOTSUPP);
984#endif /* FIFO */
985 case VCHR:
986 case VBLK:
987 /*
988 * if device, look at device number table for translation
989 */
990#ifdef ISODEVMAP
991 if (dp = iso_dmap(dev, ino, 0))
992 ip->inode.iso_rdev = dp->d_dev;
993#endif
994 vp->v_op = cd9660_specop_p;
995 if ( (nvp = checkalias(vp, ip->inode.iso_rdev, mp)) ) {
996 /*
997 * Discard unneeded vnode, but save its iso_node.
998 */
999 cd9660_ihashrem(ip);
1000 VOP_UNLOCK(vp, 0, p);
1001 nvp->v_data = vp->v_data;
1002 vp->v_data = NULL;
1003 vp->v_op = spec_vnodeop_p;
1004 vrele(vp);
1005 vgone(vp);
1006 /*
1007 * Reinitialize aliased inode.
1008 */
1009 vp = nvp;
1010 ip->i_vnode = vp;
1011 cd9660_ihashins(ip);
1012 }
1013 break;
1014 case VREG:
1015 ubc_info_init(vp);
1016 break;
1017 default:
1018 break;
1019 }
1020
1021 /*
1022 * XXX need generation number?
1023 */
1024
1025 *vpp = vp;
1026
1027 return (0);
1028}
1029
1030
1031/************************************************************************
1032 *
1033 * Function: DRGetTypeCreatorAndFlags
1034 *
1035 * Purpose: Set up the fileType, fileCreator and fileFlags
1036 *
1037 * Returns: none
1038 *
1039 * Side Effects: sets *theTypePtr, *theCreatorPtr, and *theFlagsPtr
1040 *
1041 * Description:
1042 *
1043 * Revision History:
1044