cleanups (from mycroft)
[unix-history] / usr / src / sys / isofs / cd9660 / cd9660_vfsops.c
CommitLineData
5fc285c5
KM
1/*-
2 * Copyright (c) 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley
6 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
7 * Support code is derived from software contributed to Berkeley
8 * by Atsushi Murai (amurai@spec.co.jp).
9 *
10 * %sccs.include.redist.c%
11 *
706651ee 12 * @(#)cd9660_vfsops.c 8.13 (Berkeley) %G%
5fc285c5
KM
13 */
14
15#include <sys/param.h>
16#include <sys/systm.h>
17#include <sys/namei.h>
18#include <sys/proc.h>
19#include <sys/kernel.h>
20#include <sys/vnode.h>
21#include <miscfs/specfs/specdev.h>
22#include <sys/mount.h>
23#include <sys/buf.h>
24#include <sys/file.h>
25#include <sys/dkbad.h>
26#include <sys/disklabel.h>
27#include <sys/ioctl.h>
28#include <sys/errno.h>
29#include <sys/malloc.h>
b3e9029f 30#include <sys/stat.h>
5fc285c5
KM
31
32#include <isofs/cd9660/iso.h>
13275923 33#include <isofs/cd9660/cd9660_node.h>
eceb865c 34#include <isofs/cd9660/cd9660_mount.h>
5fc285c5
KM
35
36extern int enodev ();
37
13275923
KM
38struct vfsops cd9660_vfsops = {
39 cd9660_mount,
40 cd9660_start,
41 cd9660_unmount,
42 cd9660_root,
43 cd9660_quotactl,
44 cd9660_statfs,
45 cd9660_sync,
46 cd9660_vget,
47 cd9660_fhtovp,
48 cd9660_vptofh,
49 cd9660_init,
eceb865c 50 cd9660_sysctl
5fc285c5
KM
51};
52
53/*
54 * Called by vfs_mountroot when iso is going to be mounted as root.
55 *
56 * Name is updated by mount(8) after booting.
57 */
58#define ROOTNAME "root_device"
59
60static iso_mountfs();
61
13275923 62cd9660_mountroot()
5fc285c5
KM
63{
64 register struct mount *mp;
65 extern struct vnode *rootvp;
66 struct proc *p = curproc; /* XXX */
67 struct iso_mnt *imp;
68 register struct fs *fs;
69 u_int size;
70 int error;
71 struct iso_args args;
72
73 /*
74 * Get vnodes for swapdev and rootdev.
75 */
76 if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp))
13275923 77 panic("cd9660_mountroot: can't setup bdevvp's");
5fc285c5
KM
78
79 mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
80 bzero((char *)mp, (u_long)sizeof(struct mount));
13275923 81 mp->mnt_op = &cd9660_vfsops;
5fc285c5 82 mp->mnt_flag = MNT_RDONLY;
05e5da84 83 LIST_INIT(&mp->mnt_vnodelist);
5fc285c5
KM
84 args.flags = ISOFSMNT_ROOT;
85 if (error = iso_mountfs(rootvp, mp, p, &args)) {
86 free(mp, M_MOUNT);
87 return (error);
88 }
89 if (error = vfs_lock(mp)) {
13275923 90 (void)cd9660_unmount(mp, 0, p);
5fc285c5
KM
91 free(mp, M_MOUNT);
92 return (error);
93 }
3df1ed0c 94 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
5fc285c5
KM
95 mp->mnt_vnodecovered = NULLVP;
96 imp = VFSTOISOFS(mp);
706651ee
KM
97 (void) copystr("/", mp->mnt_stat.f_mntonname, MNAMELEN - 1,
98 &size);
99 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
5fc285c5
KM
100 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
101 &size);
102 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
706651ee 103 (void)cd9660_statfs(mp, &mp->mnt_stat, p);
5fc285c5
KM
104 vfs_unlock(mp);
105 return (0);
106}
107
5fc285c5
KM
108/*
109 * VFS Operations.
110 *
111 * mount system call
112 */
13275923 113cd9660_mount(mp, path, data, ndp, p)
5fc285c5
KM
114 register struct mount *mp;
115 char *path;
116 caddr_t data;
117 struct nameidata *ndp;
118 struct proc *p;
119{
120 struct vnode *devvp;
121 struct iso_args args;
122 u_int size;
123 int error;
124 struct iso_mnt *imp;
125
126 if (error = copyin(data, (caddr_t)&args, sizeof (struct iso_args)))
127 return (error);
128
129 if ((mp->mnt_flag & MNT_RDONLY) == 0)
130 return (EROFS);
131
132 /*
133 * If updating, check whether changing from read-only to
134 * read/write; if there is no device name, that's all we do.
135 */
136 if (mp->mnt_flag & MNT_UPDATE) {
137 imp = VFSTOISOFS(mp);
138 if (args.fspec == 0)
139 return (vfs_export(mp, &imp->im_export, &args.export));
140 }
141 /*
142 * Not an update, or updating the name: look up the name
143 * and verify that it refers to a sensible block device.
144 */
145 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
146 if (error = namei(ndp))
147 return (error);
148 devvp = ndp->ni_vp;
149
150 if (devvp->v_type != VBLK) {
151 vrele(devvp);
152 return ENOTBLK;
153 }
154 if (major(devvp->v_rdev) >= nblkdev) {
155 vrele(devvp);
156 return ENXIO;
157 }
158 if ((mp->mnt_flag & MNT_UPDATE) == 0)
159 error = iso_mountfs(devvp, mp, p, &args);
160 else {
161 if (devvp != imp->im_devvp)
162 error = EINVAL; /* needs translation */
163 else
164 vrele(devvp);
165 }
166 if (error) {
167 vrele(devvp);
168 return error;
169 }
170 imp = VFSTOISOFS(mp);
706651ee
KM
171 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
172 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
5fc285c5
KM
173 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
174 &size);
175 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
13275923 176 (void) cd9660_statfs(mp, &mp->mnt_stat, p);
5fc285c5
KM
177 return 0;
178}
179
180/*
181 * Common code for mount and mountroot
182 */
183static iso_mountfs(devvp, mp, p, argp)
184 register struct vnode *devvp;
185 struct mount *mp;
186 struct proc *p;
187 struct iso_args *argp;
188{
189 register struct iso_mnt *isomp = (struct iso_mnt *)0;
190 struct buf *bp = NULL;
191 dev_t dev = devvp->v_rdev;
192 caddr_t base, space;
193 int havepart = 0, blks;
194 int error = EINVAL, i, size;
195 int needclose = 0;
196 int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
197 extern struct vnode *rootvp;
198 int j;
199 int iso_bsize;
200 int iso_blknum;
201 struct iso_volume_descriptor *vdp;
202 struct iso_primary_descriptor *pri;
203 struct iso_directory_record *rootp;
204 int logical_block_size;
205
206 if (!ronly)
207 return EROFS;
208
209 /*
210 * Disallow multiple mounts of the same device.
211 * Disallow mounting of a device that is currently in use
212 * (except for root, which might share swap device for miniroot).
213 * Flush out any old buffers remaining from a previous use.
214 */
215 if (error = vfs_mountedon(devvp))
216 return error;
217 if (vcount(devvp) > 1 && devvp != rootvp)
218 return EBUSY;
219 if (error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0))
220 return (error);
221
222 if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p))
223 return error;
224 needclose = 1;
225
226 /* This is the "logical sector size". The standard says this
227 * should be 2048 or the physical sector size on the device,
228 * whichever is greater. For now, we'll just use a constant.
229 */
230 iso_bsize = ISO_DEFAULT_BLOCK_SIZE;
231
232 for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
349b9aaf
KM
233 if (error = bread(devvp, iso_blknum * btodb(iso_bsize),
234 iso_bsize, NOCRED, &bp))
5fc285c5
KM
235 goto out;
236
349b9aaf 237 vdp = (struct iso_volume_descriptor *)bp->b_data;
5fc285c5
KM
238 if (bcmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) != 0) {
239 error = EINVAL;
240 goto out;
241 }
242
243 if (isonum_711 (vdp->type) == ISO_VD_END) {
244 error = EINVAL;
245 goto out;
246 }
247
248 if (isonum_711 (vdp->type) == ISO_VD_PRIMARY)
249 break;
250 brelse(bp);
251 }
252
253 if (isonum_711 (vdp->type) != ISO_VD_PRIMARY) {
254 error = EINVAL;
255 goto out;
256 }
257
258 pri = (struct iso_primary_descriptor *)vdp;
259
260 logical_block_size = isonum_723 (pri->logical_block_size);
261
262 if (logical_block_size < DEV_BSIZE || logical_block_size > MAXBSIZE
263 || (logical_block_size & (logical_block_size - 1)) != 0) {
264 error = EINVAL;
265 goto out;
266 }
267
268 rootp = (struct iso_directory_record *)pri->root_directory_record;
269
2d80cfd2
MH
270 isomp = malloc(sizeof *isomp, M_ISOFSMNT, M_WAITOK);
271 bzero((caddr_t)isomp, sizeof *isomp);
5fc285c5
KM
272 isomp->logical_block_size = logical_block_size;
273 isomp->volume_space_size = isonum_733 (pri->volume_space_size);
274 bcopy (rootp, isomp->root, sizeof isomp->root);
275 isomp->root_extent = isonum_733 (rootp->extent);
276 isomp->root_size = isonum_733 (rootp->size);
277
278 isomp->im_bmask = logical_block_size - 1;
279 isomp->im_bshift = 0;
280 while ((1 << isomp->im_bshift) < isomp->logical_block_size)
281 isomp->im_bshift++;
282
283 bp->b_flags |= B_AGE;
284 brelse(bp);
285 bp = NULL;
286
287 mp->mnt_data = (qaddr_t)isomp;
288 mp->mnt_stat.f_fsid.val[0] = (long)dev;
eceb865c 289 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
5fc285c5
KM
290 mp->mnt_maxsymlinklen = 0;
291 mp->mnt_flag |= MNT_LOCAL;
292 isomp->im_mountp = mp;
293 isomp->im_dev = dev;
294 isomp->im_devvp = devvp;
295
296 devvp->v_specflags |= SI_MOUNTEDON;
297
298 /* Check the Rock Ridge Extention support */
299 if (!(argp->flags & ISOFSMNT_NORRIP)) {
349b9aaf
KM
300 if (error = bread(isomp->im_devvp,
301 (isomp->root_extent + isonum_711(rootp->ext_attr_length)) <<
302 (isomp->im_bshift - DEV_BSHIFT),
303 isomp->logical_block_size, NOCRED, &bp))
5fc285c5
KM
304 goto out;
305
349b9aaf 306 rootp = (struct iso_directory_record *)bp->b_data;
5fc285c5 307
13275923 308 if ((isomp->rr_skip = cd9660_rrip_offset(rootp,isomp)) < 0) {
5fc285c5
KM
309 argp->flags |= ISOFSMNT_NORRIP;
310 } else {
311 argp->flags &= ~ISOFSMNT_GENS;
312 }
313
314 /*
315 * The contents are valid,
316 * but they will get reread as part of another vnode, so...
317 */
318 bp->b_flags |= B_AGE;
319 brelse(bp);
320 bp = NULL;
321 }
322 isomp->im_flags = argp->flags&(ISOFSMNT_NORRIP|ISOFSMNT_GENS|ISOFSMNT_EXTATT);
323 switch (isomp->im_flags&(ISOFSMNT_NORRIP|ISOFSMNT_GENS)) {
324 default:
325 isomp->iso_ftype = ISO_FTYPE_DEFAULT;
326 break;
327 case ISOFSMNT_GENS|ISOFSMNT_NORRIP:
328 isomp->iso_ftype = ISO_FTYPE_9660;
329 break;
330 case 0:
331 isomp->iso_ftype = ISO_FTYPE_RRIP;
332 break;
333 }
334
335 return 0;
336out:
337 if (bp)
338 brelse(bp);
339 if (needclose)
340 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
341 if (isomp) {
342 free((caddr_t)isomp, M_ISOFSMNT);
343 mp->mnt_data = (qaddr_t)0;
344 }
345 return error;
346}
347
348/*
349 * Make a filesystem operational.
350 * Nothing to do at the moment.
351 */
352/* ARGSUSED */
13275923 353cd9660_start(mp, flags, p)
5fc285c5
KM
354 struct mount *mp;
355 int flags;
356 struct proc *p;
357{
358 return 0;
359}
360
361/*
362 * unmount system call
363 */
364int
13275923 365cd9660_unmount(mp, mntflags, p)
5fc285c5
KM
366 struct mount *mp;
367 int mntflags;
368 struct proc *p;
369{
370 register struct iso_mnt *isomp;
371 int i, error, ronly, flags = 0;
372
fe5239dc 373 if (mntflags & MNT_FORCE)
5fc285c5 374 flags |= FORCECLOSE;
5fc285c5
KM
375#if 0
376 mntflushbuf(mp, 0);
377 if (mntinvalbuf(mp))
378 return EBUSY;
379#endif
380 if (error = vflush(mp, NULLVP, flags))
381 return (error);
382
383 isomp = VFSTOISOFS(mp);
384
385#ifdef ISODEVMAP
386 if (isomp->iso_ftype == ISO_FTYPE_RRIP)
387 iso_dunmap(isomp->im_dev);
388#endif
389
390 isomp->im_devvp->v_specflags &= ~SI_MOUNTEDON;
391 error = VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, p);
392 vrele(isomp->im_devvp);
393 free((caddr_t)isomp, M_ISOFSMNT);
394 mp->mnt_data = (qaddr_t)0;
395 mp->mnt_flag &= ~MNT_LOCAL;
396 return (error);
397}
398
399/*
400 * Return root of a filesystem
401 */
13275923 402cd9660_root(mp, vpp)
5fc285c5
KM
403 struct mount *mp;
404 struct vnode **vpp;
405{
b3e9029f 406 struct iso_mnt *imp = VFSTOISOFS(mp);
085443c5
KM
407 struct iso_directory_record *dp =
408 (struct iso_directory_record *)imp->root;
349b9aaf 409 ino_t ino = isodirino(dp, imp);
5fc285c5
KM
410
411 /*
412 * With RRIP we must use the `.' entry of the root directory.
085443c5 413 * Simply tell vget, that it's a relocated directory.
5fc285c5 414 */
085443c5
KM
415 return (cd9660_vget_internal(mp, ino, vpp,
416 imp->iso_ftype == ISO_FTYPE_RRIP, dp));
5fc285c5
KM
417}
418
419/*
420 * Do operations associated with quotas, not supported
421 */
422/* ARGSUSED */
423int
13275923 424cd9660_quotactl(mp, cmd, uid, arg, p)
5fc285c5
KM
425 struct mount *mp;
426 int cmd;
427 uid_t uid;
428 caddr_t arg;
429 struct proc *p;
430{
431
432 return (EOPNOTSUPP);
433}
434
435/*
436 * Get file system statistics.
437 */
13275923 438cd9660_statfs(mp, sbp, p)
5fc285c5
KM
439 struct mount *mp;
440 register struct statfs *sbp;
441 struct proc *p;
442{
443 register struct iso_mnt *isomp;
444 register struct fs *fs;
445
446 isomp = VFSTOISOFS(mp);
05e5da84 447
349b9aaf
KM
448#ifdef COMPAT_09
449 sbp->f_type = 5;
450#else
451 sbp->f_type = 0;
452#endif
5fc285c5
KM
453 sbp->f_bsize = isomp->logical_block_size;
454 sbp->f_iosize = sbp->f_bsize; /* XXX */
455 sbp->f_blocks = isomp->volume_space_size;
456 sbp->f_bfree = 0; /* total free blocks */
457 sbp->f_bavail = 0; /* blocks free for non superuser */
458 sbp->f_files = 0; /* total files */
459 sbp->f_ffree = 0; /* free file nodes */
460 if (sbp != &mp->mnt_stat) {
706651ee
KM
461 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
462 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
5fc285c5
KM
463 }
464 /* Use the first spare for flags: */
465 sbp->f_spare[0] = isomp->im_flags;
466 return 0;
467}
468
469/* ARGSUSED */
470int
13275923 471cd9660_sync(mp, waitfor, cred, p)
5fc285c5
KM
472 struct mount *mp;
473 int waitfor;
474 struct ucred *cred;
475 struct proc *p;
476{
477 return (0);
478}
479
5fc285c5
KM
480/*
481 * File handle to vnode
482 *
483 * Have to be really careful about stale file handles:
484 * - check that the inode number is in range
485 * - call iget() to get the locked inode
486 * - check for an unallocated inode (i_mode == 0)
487 * - check that the generation number matches
488 */
489
490struct ifid {
491 ushort ifid_len;
492 ushort ifid_pad;
493 int ifid_ino;
494 long ifid_start;
495};
496
497/* ARGSUSED */
498int
13275923 499cd9660_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
5fc285c5
KM
500 register struct mount *mp;
501 struct fid *fhp;
502 struct mbuf *nam;
503 struct vnode **vpp;
504 int *exflagsp;
505 struct ucred **credanonp;
506{
b3e9029f
KM
507 struct ifid *ifhp = (struct ifid *)fhp;
508 register struct iso_node *ip;
509 register struct netcred *np;
510 register struct iso_mnt *imp = VFSTOISOFS(mp);
511 struct vnode *nvp;
512 int error;
5fc285c5
KM
513
514#ifdef ISOFS_DBG
515 printf("fhtovp: ino %d, start %ld\n",
516 ifhp->ifid_ino, ifhp->ifid_start);
517#endif
518
b3e9029f
KM
519 /*
520 * Get the export permission structure for this <mp, client> tuple.
521 */
5fc285c5
KM
522 np = vfs_export_lookup(mp, &imp->im_export, nam);
523 if (np == NULL)
524 return (EACCES);
525
b3e9029f
KM
526 if (error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) {
527 *vpp = NULLVP;
528 return (error);
529 }
530 ip = VTOI(nvp);
531 if (ip->inode.iso_mode == 0) {
532 vput(nvp);
533 *vpp = NULLVP;
534 return (ESTALE);
535 }
536 *vpp = nvp;
537 *exflagsp = np->netc_exflags;
538 *credanonp = &np->netc_anon;
539 return (0);
540}
541
542int
543cd9660_vget(mp, ino, vpp)
544 struct mount *mp;
545 ino_t ino;
546 struct vnode **vpp;
547{
548
549 /*
550 * XXXX
551 * It would be nice if we didn't always set the `relocated' flag
552 * and force the extra read, but I don't want to think about fixing
553 * that right now.
554 */
555 return (cd9660_vget_internal(mp, ino, vpp,
085443c5 556#if 0
b3e9029f 557 VFSTOISOFS(mp)->iso_ftype == ISO_FTYPE_RRIP,
085443c5
KM
558#else
559 0,
560#endif
b3e9029f
KM
561 (struct iso_directory_entry *)0));
562}
563
564int
565cd9660_vget_internal(mp, ino, vpp, relocated, isodir)
566 struct mount *mp;
567 ino_t ino;
568 struct vnode **vpp;
569 int relocated;
570 struct iso_directory_record *isodir;
571{
572 register struct iso_mnt *imp;
573 struct iso_node *ip;
574 struct buf *bp;
575 struct vnode *vp, *nvp;
b3e9029f
KM
576 dev_t dev;
577 int error;
578
579 imp = VFSTOISOFS(mp);
580 dev = imp->im_dev;
581 if ((*vpp = cd9660_ihashget(dev, ino)) != NULLVP)
582 return (0);
583
584 /* Allocate a new vnode/iso_node. */
585 if (error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, &vp)) {
586 *vpp = NULLVP;
587 return (error);
588 }
589 MALLOC(ip, struct iso_node *, sizeof(struct iso_node), M_ISOFSNODE,
590 M_WAITOK);
591 bzero((caddr_t)ip, sizeof(struct iso_node));
592 vp->v_data = ip;
593 ip->i_vnode = vp;
594 ip->i_dev = dev;
595 ip->i_number = ino;
596
597 /*
598 * Put it onto its hash chain and lock it so that other requests for
599 * this inode will block if they arrive while we are sleeping waiting
600 * for old data structures to be purged or for the contents of the
601 * disk portion of this inode to be read.
602 */
603 cd9660_ihashins(ip);
604
085443c5
KM
605 if (isodir == 0) {
606 int lbn, off;
607
349b9aaf 608 lbn = lblkno(imp, ino);
085443c5
KM
609 if (lbn >= imp->volume_space_size) {
610 vput(vp);
611 printf("fhtovp: lbn exceed volume space %d\n", lbn);
612 return (ESTALE);
613 }
5fc285c5 614
349b9aaf 615 off = blkoff(imp, ino);
085443c5
KM
616 if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) {
617 vput(vp);
618 printf("fhtovp: crosses block boundary %d\n",
619 off + ISO_DIRECTORY_RECORD_SIZE);
620 return (ESTALE);
621 }
5fc285c5 622
085443c5 623 error = bread(imp->im_devvp,
349b9aaf 624 lbn << (imp->im_bshift - DEV_BSHIFT),
b3e9029f
KM
625 imp->logical_block_size, NOCRED, &bp);
626 if (error) {
627 vput(vp);
628 brelse(bp);
629 printf("fhtovp: bread error %d\n",error);
630 return (error);
631 }
632 isodir = (struct iso_directory_record *)(bp->b_data + off);
b3e9029f 633
085443c5
KM
634 if (off + isonum_711(isodir->length) >
635 imp->logical_block_size) {
636 vput(vp);
637 if (bp != 0)
638 brelse(bp);
639 printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
640 off +isonum_711(isodir->length), off,
641 isonum_711(isodir->length));
642 return (ESTALE);
643 }
5fc285c5 644
b3e9029f 645#if 0
085443c5
KM
646 if (isonum_733(isodir->extent) +
647 isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) {
648 if (bp != 0)
649 brelse(bp);
650 printf("fhtovp: file start miss %d vs %d\n",
651 isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length),
652 ifhp->ifid_start);
653 return (ESTALE);
654 }
b3e9029f 655#endif
085443c5
KM
656 } else
657 bp = 0;
b3e9029f
KM
658
659 ip->i_mnt = imp;
660 ip->i_devvp = imp->im_devvp;
661 VREF(ip->i_devvp);
662
663 if (relocated) {
664 /*
665 * On relocated directories we must
666 * read the `.' entry out of a dir.
667 */
668 ip->iso_start = ino >> imp->im_bshift;
669 if (bp != 0)
670 brelse(bp);
349b9aaf 671 if (error = VOP_BLKATOFF(vp, (off_t)0, NULL, &bp)) {
b3e9029f
KM
672 vput(vp);
673 return (error);
674 }
675 isodir = (struct iso_directory_record *)bp->b_data;
676 }
677
678 ip->iso_extent = isonum_733(isodir->extent);
679 ip->i_size = isonum_733(isodir->size);
680 ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
5fc285c5 681
b3e9029f
KM
682 /*
683 * Setup time stamp, attribute
684 */
685 vp->v_type = VNON;
686 switch (imp->iso_ftype) {
687 default: /* ISO_FTYPE_9660 */
688 {
689 struct buf *bp2;
349b9aaf 690 int off;
b3e9029f 691 if ((imp->im_flags & ISOFSMNT_EXTATT)
349b9aaf
KM
692 && (off = isonum_711(isodir->ext_attr_length)))
693 VOP_BLKATOFF(vp, (off_t)-(off << imp->im_bshift), NULL,
b3e9029f 694 &bp2);
672f03cc
KM
695 else
696 bp2 = NULL;
b3e9029f
KM
697 cd9660_defattr(isodir, ip, bp2);
698 cd9660_deftstamp(isodir, ip, bp2);
672f03cc
KM
699 if (bp2)
700 brelse(bp2);
b3e9029f
KM
701 break;
702 }
703 case ISO_FTYPE_RRIP:
704 cd9660_rrip_analyze(isodir, ip, imp);
705 break;
5fc285c5 706 }
b3e9029f
KM
707
708 if (bp != 0)
709 brelse(bp);
710
5fc285c5 711 /*
b3e9029f 712 * Initialize the associated vnode
5fc285c5 713 */
b3e9029f
KM
714 switch (vp->v_type = IFTOVT(ip->inode.iso_mode)) {
715 case VFIFO:
716#ifdef FIFO
717 vp->v_op = cd9660_fifoop_p;
718 break;
719#else
720 vput(vp);
721 return (EOPNOTSUPP);
722#endif /* FIFO */
723 case VCHR:
724 case VBLK:
725 /*
726 * if device, look at device number table for translation
727 */
728#ifdef ISODEVMAP
729 if (dp = iso_dmap(dev, ino, 0))
730 ip->inode.iso_rdev = dp->d_dev;
731#endif
732 vp->v_op = cd9660_specop_p;
733 if (nvp = checkalias(vp, ip->inode.iso_rdev, mp)) {
734 /*
735 * Discard unneeded vnode, but save its iso_node.
736 */
737 cd9660_ihashrem(ip);
738 VOP_UNLOCK(vp);
739 nvp->v_data = vp->v_data;
740 vp->v_data = NULL;
741 vp->v_op = spec_vnodeop_p;
742 vrele(vp);
743 vgone(vp);
744 /*
745 * Reinitialize aliased inode.
746 */
747 vp = nvp;
748 ip->i_vnode = vp;
749 cd9660_ihashins(ip);
750 }
751 break;
5fc285c5 752 }
b3e9029f
KM
753
754 if (ip->iso_extent == imp->root_extent)
755 vp->v_flag |= VROOT;
756
757 /*
758 * XXX need generation number?
759 */
760
761 *vpp = vp;
762 return (0);
5fc285c5
KM
763}
764
765/*
766 * Vnode pointer to File handle
767 */
768/* ARGSUSED */
13275923 769cd9660_vptofh(vp, fhp)
5fc285c5
KM
770 struct vnode *vp;
771 struct fid *fhp;
772{
773 register struct iso_node *ip = VTOI(vp);
774 register struct ifid *ifhp;
775 register struct iso_mnt *mp = ip->i_mnt;
776
777 ifhp = (struct ifid *)fhp;
778 ifhp->ifid_len = sizeof(struct ifid);
779
780 ifhp->ifid_ino = ip->i_number;
781 ifhp->ifid_start = ip->iso_start;
782
783#ifdef ISOFS_DBG
784 printf("vptofh: ino %d, start %ld\n",
785 ifhp->ifid_ino,ifhp->ifid_start);
786#endif
787 return 0;
788}