]> git.saurik.com Git - apple/xnu.git/blame - bsd/isofs/cd9660/cd9660_vnops.c
xnu-124.13.tar.gz
[apple/xnu.git] / bsd / isofs / cd9660 / cd9660_vnops.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_vnops.c,v 1.22 1994/12/27 19:05:12 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_vnops.c 8.15 (Berkeley) 12/5/94
62 *
63 * HISTORY
64 * 02-Feb-00 chw Add cd9660_copyfile to return error
65 * 29-Sep-98 djb Add cd9660_getattrlist VOP for VDI support.
66 * 15-sep-98 added cd9660_rmdir to do proper unlocking - chw
67 * 12-aug-98 added cd9660_remove which will do proper unlocking - chw
68 * 17-Feb-98 radar 1669467 - changed lock protocols to use the lock manager - chw
69 * 22-Jan-98 radar 1669467 - ISO 9660 CD support - jwc
70 */
71
72#include <sys/param.h>
73#include <sys/systm.h>
74#include <sys/vnode.h>
75#include <sys/mount.h>
76#include <sys/namei.h>
77#include <sys/resourcevar.h>
78#include <sys/kernel.h>
79#include <sys/file.h>
80#include <sys/stat.h>
81#include <sys/buf.h>
82#include <sys/proc.h>
83#include <sys/conf.h>
84#include <miscfs/specfs/specdev.h>
85#include <miscfs/fifofs/fifo.h>
86#include <sys/malloc.h>
87#include <sys/dir.h>
88#include <sys/attr.h>
89#include <vfs/vfs_support.h>
90#include <sys/ubc.h>
91
92#include <sys/lock.h>
93
94#include <isofs/cd9660/iso.h>
95#include <isofs/cd9660/cd9660_node.h>
96#include <isofs/cd9660/iso_rrip.h>
97
98/*
99 * Open called.
100 *
101 * Nothing to do.
102 */
103/* ARGSUSED */
104int
105cd9660_open(ap)
106 struct vop_open_args /* {
107 struct vnode *a_vp;
108 int a_mode;
109 struct ucred *a_cred;
110 struct proc *a_p;
111 } */ *ap;
112{
113 return (0);
114}
115
116/*
117 * Close called
118 *
119 * Update the times on the inode on writeable file systems.
120 */
121/* ARGSUSED */
122int
123cd9660_close(ap)
124 struct vop_close_args /* {
125 struct vnode *a_vp;
126 int a_fflag;
127 struct ucred *a_cred;
128 struct proc *a_p;
129 } */ *ap;
130{
131 return (0);
132}
133
134/*
135 * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
136 * The mode is shifted to select the owner/group/other fields. The
137 * super user is granted all permissions.
138 */
139/* ARGSUSED */
140int
141cd9660_access(ap)
142 struct vop_access_args /* {
143 struct vnode *a_vp;
144 int a_mode;
145 struct ucred *a_cred;
146 struct proc *a_p;
147 } */ *ap;
148{
149 struct vnode *vp = ap->a_vp;
150 struct iso_node *ip = VTOI(vp);
151 struct ucred *cred = ap->a_cred;
152 mode_t mask, mode = ap->a_mode;
153 register gid_t *gp;
154 int i, error;
155
156 /*
157 * Disallow write attempts on read-only file systems;
158 * unless the file is a socket, fifo, or a block or
159 * character device resident on the file system.
160 */
161 if (mode & VWRITE) {
162 switch (vp->v_type) {
163 case VDIR:
164 case VLNK:
165 case VREG:
166 return (EROFS);
167 /* NOT REACHED */
168 default:
169 break;
170 }
171 }
172
173 /* If immutable bit set, nobody gets to write it. */
174#if 0
175 if ((mode & VWRITE) && (ip->i_flag & IMMUTABLE))
176 return (EPERM);
177#endif
178 /* Otherwise, user id 0 always gets access. */
179 if (cred->cr_uid == 0)
180 return (0);
181
182 mask = 0;
183
184 /* Otherwise, check the owner. */
185 if (cred->cr_uid == ip->inode.iso_uid) {
186 if (mode & VEXEC)
187 mask |= S_IXUSR;
188 if (mode & VREAD)
189 mask |= S_IRUSR;
190 if (mode & VWRITE)
191 mask |= S_IWUSR;
192 return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
193 }
194
195 /* Otherwise, check the groups. */
196 for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
197 if (ip->inode.iso_gid == *gp) {
198 if (mode & VEXEC)
199 mask |= S_IXGRP;
200 if (mode & VREAD)
201 mask |= S_IRGRP;
202 if (mode & VWRITE)
203 mask |= S_IWGRP;
204 return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
205 }
206
207 /* Otherwise, check everyone else. */
208 if (mode & VEXEC)
209 mask |= S_IXOTH;
210 if (mode & VREAD)
211 mask |= S_IROTH;
212 if (mode & VWRITE)
213 mask |= S_IWOTH;
214 return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
215}
216
217int
218cd9660_getattr(ap)
219 struct vop_getattr_args /* {
220 struct vnode *a_vp;
221 struct vattr *a_vap;
222 struct ucred *a_cred;
223 struct proc *a_p;
224 } */ *ap;
225
226{
227 struct vnode *vp = ap->a_vp;
228 register struct vattr *vap = ap->a_vap;
229 register struct iso_node *ip = VTOI(vp);
230
231 vap->va_fsid = ip->i_dev;
232 vap->va_fileid = ip->i_number;
233
234 vap->va_mode = ip->inode.iso_mode;
235 vap->va_nlink = ip->inode.iso_links;
236 vap->va_uid = ip->inode.iso_uid;
237 vap->va_gid = ip->inode.iso_gid;
238 vap->va_atime = ip->inode.iso_atime;
239 vap->va_mtime = ip->inode.iso_mtime;
240 vap->va_ctime = ip->inode.iso_ctime;
241 vap->va_rdev = ip->inode.iso_rdev;
242
243 vap->va_size = (u_quad_t) ip->i_size;
244 if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) {
245 struct vop_readlink_args rdlnk;
246 struct iovec aiov;
247 struct uio auio;
248 char *cp;
249
250 MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
251 aiov.iov_base = cp;
252 aiov.iov_len = MAXPATHLEN;
253 auio.uio_iov = &aiov;
254 auio.uio_iovcnt = 1;
255 auio.uio_offset = 0;
256 auio.uio_rw = UIO_READ;
257 auio.uio_segflg = UIO_SYSSPACE;
258 auio.uio_procp = ap->a_p;
259 auio.uio_resid = MAXPATHLEN;
260 rdlnk.a_uio = &auio;
261 rdlnk.a_vp = ap->a_vp;
262 rdlnk.a_cred = ap->a_cred;
263 if (cd9660_readlink(&rdlnk) == 0)
264 vap->va_size = MAXPATHLEN - auio.uio_resid;
265 FREE(cp, M_TEMP);
266 }
267 vap->va_flags = 0;
268 vap->va_gen = 1;
269 vap->va_blocksize = ip->i_mnt->logical_block_size;
270 vap->va_bytes = (u_quad_t) (ip->i_size + ip->i_rsrcsize);
271 vap->va_type = vp->v_type;
272
273 return (0);
274}
275
276
277/*
278 * Vnode op for reading.
279 */
280int
281cd9660_read(ap)
282 struct vop_read_args /* {
283 struct vnode *a_vp;
284 struct uio *a_uio;
285 int a_ioflag;
286 struct ucred *a_cred;
287 } */ *ap;
288{
289 struct vnode *vp = ap->a_vp;
290 register struct uio *uio = ap->a_uio;
291 register struct iso_node *ip = VTOI(vp);
292 register struct iso_mnt *imp;
293 struct buf *bp;
294 daddr_t lbn, rablock;
295 off_t diff;
296 int rasize, error = 0;
297 long size, n, on;
298 int devBlockSize = 0;
299
300 if (uio->uio_resid == 0)
301 return (0);
302 if (uio->uio_offset < 0)
303 return (EINVAL);
304
305 imp = ip->i_mnt;
306 VOP_DEVBLOCKSIZE(ip->i_devvp, &devBlockSize);
307
308 if (UBCISVALID(vp))
309 error = cluster_read(vp, uio, (off_t)ip->i_size, devBlockSize, 0);
310 else {
311
312 do {
313 lbn = lblkno(imp, uio->uio_offset);
314 on = blkoff(imp, uio->uio_offset);
315 n = min((u_int)(imp->logical_block_size - on),
316 uio->uio_resid);
317 diff = (off_t)ip->i_size - uio->uio_offset;
318 if (diff <= 0)
319 return (0);
320 if (diff < n)
321 n = diff;
322 size = blksize(imp, ip, lbn);
323 rablock = lbn + 1;
324
325 if (vp->v_lastr + 1 == lbn &&
326 lblktosize(imp, rablock) < ip->i_size) {
327 rasize = blksize(imp, ip, rablock);
328 error = breadn(vp, lbn, size, &rablock,
329 &rasize, 1, NOCRED, &bp);
330 } else
331 error = bread(vp, lbn, size, NOCRED, &bp);
332
333 vp->v_lastr = lbn;
334 n = min(n, size - bp->b_resid);
335 if (error) {
336 brelse(bp);
337 return (error);
338 }
339
340 error = uiomove(bp->b_data + on, (int)n, uio);
341 if (n + on == imp->logical_block_size ||
342 uio->uio_offset == (off_t)ip->i_size)
343 bp->b_flags |= B_AGE;
344 brelse(bp);
345 } while (error == 0 && uio->uio_resid > 0 && n != 0);
346 }
347
348 return (error);
349}
350
351/* ARGSUSED */
352int
353cd9660_ioctl(ap)
354 struct vop_ioctl_args /* {
355 struct vnode *a_vp;
356 u_long a_command;
357 caddr_t a_data;
358 int a_fflag;
359 struct ucred *a_cred;
360 struct proc *a_p;
361 } */ *ap;
362{
363 printf("You did ioctl for isofs !!\n");
364 return (ENOTTY);
365}
366
367/* ARGSUSED */
368int
369cd9660_select(ap)
370 struct vop_select_args /* {
371 struct vnode *a_vp;
372 int a_which;
373 int a_fflags;
374 struct ucred *a_cred;
375 struct proc *a_p;
376 } */ *ap;
377{
378 /*
379 * We should really check to see if I/O is possible.
380 */
381 return (1);
382}
383
384/*
385 * Mmap a file
386 *
387 * NB Currently unsupported.
388 */
389/* ARGSUSED */
390int
391cd9660_mmap(ap)
392 struct vop_mmap_args /* {
393 struct vnode *a_vp;
394 int a_fflags;
395 struct ucred *a_cred;
396 struct proc *a_p;
397 } */ *ap;
398{
399
400 return (EINVAL);
401}
402
403/*
404 * Seek on a file
405 *
406 * Nothing to do, so just return.
407 */
408/* ARGSUSED */
409int
410cd9660_seek(ap)
411 struct vop_seek_args /* {
412 struct vnode *a_vp;
413 off_t a_oldoff;
414 off_t a_newoff;
415 struct ucred *a_cred;
416 } */ *ap;
417{
418
419 return (0);
420}
421
422/*
423 * Structure for reading directories
424 */
425struct isoreaddir {
426 struct dirent saveent;
427 struct dirent current;
428 off_t saveoff;
429 off_t curroff;
430 struct uio *uio;
431 off_t uio_off;
432 int eofflag;
433// u_long **cookies;
434// int *ncookies;
435};
436
437static int
438iso_uiodir(idp,dp,off)
439 struct isoreaddir *idp;
440 struct dirent *dp;
441 off_t off;
442{
443 int error;
444
445 dp->d_name[dp->d_namlen] = 0;
446 dp->d_reclen = DIRSIZ(dp);
447
448 if (idp->uio->uio_resid < dp->d_reclen) {
449 idp->eofflag = 0;
450 return (-1);
451 }
452
453#if 0
454 if (idp->cookies) {
455 if (*idp->ncookies <= 0) {
456 idp->eofflag = 0;
457 return (-1);
458 }
459
460 **idp->cookies++ = off;
461 --*idp->ncookies;
462 }
463#endif
464
465 if ( (error = uiomove( (caddr_t)dp, dp->d_reclen, idp->uio )) )
466 return (error);
467 idp->uio_off = off;
468 return (0);
469}
470
471static int
472iso_shipdir(idp)
473 struct isoreaddir *idp;
474{
475 struct dirent *dp;
476 int cl, sl;
477 int error;
478 char *cname, *sname;
479
480 cl = idp->current.d_namlen;
481 cname = idp->current.d_name;
482
483 dp = &idp->saveent;
484 sname = dp->d_name;
485 sl = dp->d_namlen;
486 if (sl > 0) {
487 if (sl != cl
488 || bcmp(sname,cname,sl)) {
489 if (idp->saveent.d_namlen) {
490 if ( (error = iso_uiodir(idp,&idp->saveent,idp->saveoff)) )
491 return (error);
492 idp->saveent.d_namlen = 0;
493 }
494 }
495 }
496 idp->current.d_reclen = DIRSIZ(&idp->current);
497 idp->saveoff = idp->curroff;
498 bcopy(&idp->current,&idp->saveent,idp->current.d_reclen);
499 return (0);
500}
501
502/*
503 * Vnode op for readdir
504 */
505int
506cd9660_readdir(ap)
507 struct vop_readdir_args /* {
508 struct vnodeop_desc *a_desc;
509 struct vnode *a_vp;
510 struct uio *a_uio;
511 struct ucred *a_cred;
512 int *a_eofflag;
513 int *a_ncookies;
514 u_long **a_cookies;
515 } */ *ap;
516{
517 register struct uio *uio = ap->a_uio;
518 off_t startingOffset = uio->uio_offset;
519 size_t lost = 0;
520 struct isoreaddir *idp;
521 struct vnode *vdp = ap->a_vp;
522 struct iso_node *dp;
523 struct iso_mnt *imp;
524 struct buf *bp = NULL;
525 struct iso_directory_record *ep;
526 int entryoffsetinblock;
527 doff_t endsearch;
528 u_long bmask;
529 int error = 0;
530 int reclen;
531 u_short namelen;
532
533 dp = VTOI(vdp);
534 imp = dp->i_mnt;
535 bmask = imp->im_bmask;
536
537 MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK);
538 idp->saveent.d_namlen = 0;
539 /*
540 * XXX
541 * Is it worth trying to figure out the type?
542 */
543 idp->saveent.d_type = idp->current.d_type = DT_UNKNOWN;
544 idp->uio = uio;
545 idp->eofflag = 1;
546 idp->curroff = uio->uio_offset;
547
548 if ((entryoffsetinblock = idp->curroff & bmask) &&
549 (error = VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp))) {
550 FREE(idp, M_TEMP);
551 return (error);
552 }
553 endsearch = dp->i_size;
554
555 while (idp->curroff < endsearch) {
556 /*
557 * If offset is on a block boundary,
558 * read the next directory block.
559 * Release previous if it exists.
560 */
561 if ((idp->curroff & bmask) == 0) {
562 if (bp != NULL)
563 brelse(bp);
564 if ( (error = VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp)) )
565 break;
566 entryoffsetinblock = 0;
567 }
568 /*
569 * Get pointer to next entry.
570 */
571 ep = (struct iso_directory_record *)
572 ((char *)bp->b_data + entryoffsetinblock);
573
574 reclen = isonum_711(ep->length);
575 if (reclen == 0) {
576 /* skip to next block, if any */
577 idp->curroff =
578 (idp->curroff & ~bmask) + imp->logical_block_size;
579 continue;
580 }
581
582 if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
583 error = EINVAL;
584 /* illegal entry, stop */
585 break;
586 }
587
588 if (entryoffsetinblock + reclen > imp->logical_block_size) {
589 error = EINVAL;
590 /* illegal directory, so stop looking */
591 break;
592 }
593
594 idp->current.d_namlen = isonum_711(ep->name_len);
595
596 if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
597 error = EINVAL;
598 /* illegal entry, stop */
599 break;
600 }
601
602 /* skip over associated files (Mac OS resource fork) */
603 if (isonum_711(ep->flags) & associatedBit) {
604 idp->curroff += reclen;
605 entryoffsetinblock += reclen;
606 continue;
607 }
608
609 if ( isonum_711(ep->flags) & directoryBit )
610 idp->current.d_fileno = isodirino(ep, imp);
611 else {
612 idp->current.d_fileno = (bp->b_blkno << imp->im_bshift) + entryoffsetinblock;
613 }
614
615 idp->curroff += reclen;
616
617 switch (imp->iso_ftype) {
618 case ISO_FTYPE_RRIP:
619 cd9660_rrip_getname(ep,idp->current.d_name, &namelen,
620 &idp->current.d_fileno,imp);
621 idp->current.d_namlen = (u_char)namelen;
622 if (idp->current.d_namlen)
623 error = iso_uiodir(idp,&idp->current,idp->curroff);
624 break;
625
626 case ISO_FTYPE_JOLIET:
627 ucsfntrans((u_int16_t *)ep->name, idp->current.d_namlen,
628 idp->current.d_name, &namelen,
629 isonum_711(ep->flags) & directoryBit);
630 idp->current.d_namlen = (u_char)namelen;
631 if (idp->current.d_namlen)
632 error = iso_uiodir(idp,&idp->current,idp->curroff);
633 break;
634
635 default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */
636 strcpy(idp->current.d_name,"..");
637 switch (ep->name[0]) {
638 case 0:
639 idp->current.d_namlen = 1;
640 error = iso_uiodir(idp,&idp->current,idp->curroff);
641 break;
642 case 1:
643 idp->current.d_namlen = 2;
644 error = iso_uiodir(idp,&idp->current,idp->curroff);
645 break;
646 default:
647 isofntrans(ep->name,idp->current.d_namlen,
648 idp->current.d_name, &namelen,
649 imp->iso_ftype == ISO_FTYPE_9660);
650 idp->current.d_namlen = (u_char)namelen;
651 if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
652 error = iso_shipdir(idp);
653 else
654 error = iso_uiodir(idp,&idp->current,idp->curroff);
655 break;
656 }
657 }
658 if (error)
659 break;
660
661 entryoffsetinblock += reclen;
662 }
663
664 if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
665 idp->current.d_namlen = 0;
666 error = iso_shipdir(idp);
667 }
668
669 if (!error && ap->a_ncookies) {
670 struct dirent *dp, *dpstart;
671 off_t bufferOffset;
672 u_long *cookies;
673 int ncookies;
674
675 /*
676 * Only the NFS server uses cookies, and it loads the
677 * directory block into system space, so we can just look at
678 * it directly.
679 *
680 * We assume the entire transfer is done to a single contiguous buffer.
681 */
682 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
683 panic("ufs_readdir: lost in space");
684
685 /*
686 * Make a first pass over the buffer just generated,
687 * counting the number of entries:
688 */
689 dpstart = (struct dirent *) (uio->uio_iov->iov_base - (uio->uio_offset - startingOffset));
690 for (dp = dpstart, bufferOffset = startingOffset, ncookies = 0;
691 bufferOffset < uio->uio_offset; ) {
692 if (dp->d_reclen == 0)
693 break;
694 bufferOffset += dp->d_reclen;
695 ncookies++;
696 dp = (struct dirent *)((caddr_t)dp + dp->d_reclen);
697 }
698 lost += uio->uio_offset - bufferOffset;
699 uio->uio_offset = bufferOffset;
700
701 /*
702 * Allocate a buffer to hold the cookies requested:
703 */
704 MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP, M_WAITOK);
705 *ap->a_ncookies = ncookies;
706 *ap->a_cookies = cookies;
707
708 /*
709 * Fill in the offsets for each entry in the buffer just allocated:
710 */
711 for (bufferOffset = startingOffset, dp = dpstart; bufferOffset < uio->uio_offset; ) {
712 *(cookies++) = bufferOffset;
713 bufferOffset += dp->d_reclen;
714 dp = (struct dirent *)((caddr_t)dp + dp->d_reclen);
715 }
716 }
717
718 if (error < 0)
719 error = 0;
720
721 if (bp)
722 brelse (bp);
723
724 uio->uio_offset = idp->uio_off;
725 *ap->a_eofflag = idp->eofflag;
726
727 FREE(idp, M_TEMP);
728
729 return (error);
730}
731
732/*
733 * Return target name of a symbolic link
734 * Shouldn't we get the parent vnode and read the data from there?
735 * This could eventually result in deadlocks in cd9660_lookup.
736 * But otherwise the block read here is in the block buffer two times.
737 */
738typedef struct iso_directory_record ISODIR;
739typedef struct iso_node ISONODE;
740typedef struct iso_mnt ISOMNT;
741int
742cd9660_readlink(ap)
743 struct vop_readlink_args /* {
744 struct vnode *a_vp;
745 struct uio *a_uio;
746 struct ucred *a_cred;
747 } */ *ap;
748{
749 ISONODE *ip;
750 ISODIR *dirp;
751 ISOMNT *imp;
752 struct buf *bp;
753 struct uio *uio;
754 u_short symlen;
755 int error;
756 char *symname;
757
758 ip = VTOI(ap->a_vp);
759 imp = ip->i_mnt;
760 uio = ap->a_uio;
761
762 if (imp->iso_ftype != ISO_FTYPE_RRIP)
763 return (EINVAL);
764
765 /*
766 * Get parents directory record block that this inode included.
767 */
768 error = bread(imp->im_devvp,
769 (ip->i_number >> imp->im_bshift),
770 imp->logical_block_size, NOCRED, &bp);
771 if (error) {
772 brelse(bp);
773 return (EINVAL);
774 }
775
776 /*
777 * Setup the directory pointer for this inode
778 */
779 dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
780
781 /*
782 * Just make sure, we have a right one....
783 * 1: Check not cross boundary on block
784 */
785 if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
786 > imp->logical_block_size) {
787 brelse(bp);
788 return (EINVAL);
789 }
790
791 /*
792 * Now get a buffer
793 * Abuse a namei buffer for now.
794 */
795 if (uio->uio_segflg == UIO_SYSSPACE)
796 symname = uio->uio_iov->iov_base;
797 else
798 MALLOC_ZONE(symname, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
799
800 /*
801 * Ok, we just gathering a symbolic name in SL record.
802 */
803 if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
804 if (uio->uio_segflg != UIO_SYSSPACE)
805 FREE_ZONE(symname, MAXPATHLEN, M_NAMEI);
806 brelse(bp);
807 return (EINVAL);
808 }
809 /*
810 * Don't forget before you leave from home ;-)
811 */
812 brelse(bp);
813
814 /*
815 * return with the symbolic name to caller's.
816 */
817 if (uio->uio_segflg != UIO_SYSSPACE) {
818 error = uiomove(symname, symlen, uio);
819 FREE_ZONE(symname, MAXPATHLEN, M_NAMEI);
820 return (error);
821 }
822 uio->uio_resid -= symlen;
823 uio->uio_iov->iov_base += symlen;
824 uio->uio_iov->iov_len -= symlen;
825 return (0);
826}
827
828/*
829 * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
830 * done. If a buffer has been saved in anticipation of a CREATE, delete it.
831 */
832int
833cd9660_abortop(ap)
834 struct vop_abortop_args /* {
835 struct vnode *a_dvp;
836 struct componentname *a_cnp;
837 } */ *ap;
838{
839 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
840 FREE_ZONE(ap->a_cnp->cn_pnbuf, ap->a_cnp->cn_pnlen, M_NAMEI);
841 return (0);
842}
843
844/*
845 * Lock an inode.
846 */
847
848int
849cd9660_lock(ap)
850 struct vop_lock_args /* {
851 struct vnode *a_vp;
852 int a_flags;
853 struct proc *a_p;
854 } */ *ap;
855{
856 struct vnode *vp = ap->a_vp;
857
858 if (VTOI(vp) == (struct iso_node *) NULL)
859 panic ("cd9660_lock: null inode");
860 return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, &vp->v_interlock,ap->a_p));
861}
862
863/*
864 * Unlock an inode.
865 */
866
867int
868cd9660_unlock(ap)
869 struct vop_unlock_args /* {
870 struct vnode *a_vp;
871 int a_flags;
872 struct proc *a_p;
873 } */ *ap;
874{
875 struct vnode *vp = ap->a_vp;
876
877 return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE, &vp->v_interlock,ap->a_p));
878
879}
880
881/*
882 * Calculate the logical to physical mapping if not done already,
883 * then call the device strategy routine.
884 */
885int
886cd9660_strategy(ap)
887 struct vop_strategy_args /* {
888 struct buf *a_bp;
889 } */ *ap;
890{
891 register struct buf *bp = ap->a_bp;
892 register struct vnode *vp = bp->b_vp;
893 register struct iso_node *ip;
894 int error;
895
896 ip = VTOI(vp);
897 if (vp->v_type == VBLK || vp->v_type == VCHR)
898 panic("cd9660_strategy: spec");
899 if (bp->b_blkno == bp->b_lblkno) {
900 if ( (error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL)) ) {
901 bp->b_error = error;
902 bp->b_flags |= B_ERROR;
903 biodone(bp);
904 return (error);
905 }
906 if ((long)bp->b_blkno == -1)
907 clrbuf(bp);
908 }
909 if ((long)bp->b_blkno == -1) {
910 biodone(bp);
911 return (0);
912 }
913 vp = ip->i_devvp;
914 bp->b_dev = vp->v_rdev;
915 VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
916 return (0);
917}
918
919/*
920 * Print out the contents of an inode.
921 */
922int
923cd9660_print(ap)
924 struct vop_print_args /* {
925 struct vnode *a_vp;
926 } */ *ap;
927{
928
929 printf("tag VT_ISOFS, isofs vnode\n");
930 return (0);
931}
932
933/*
934 * Check for a locked inode.
935 */
936int
937cd9660_islocked(ap)
938 struct vop_islocked_args /* {
939 struct vnode *a_vp;
940 } */ *ap;
941{
942
943 return (lockstatus(&VTOI(ap->a_vp)->i_lock));
944}
945
946/*
947 * Return POSIX pathconf information applicable to cd9660 filesystems.
948 */
949int
950cd9660_pathconf(ap)
951 struct vop_pathconf_args /* {
952 struct vnode *a_vp;
953 int a_name;
954 register_t *a_retval;
955 } */ *ap;
956{
957
958 switch (ap->a_name) {
959 case _PC_LINK_MAX:
960 *ap->a_retval = 1;
961 return (0);
962 case _PC_NAME_MAX:
963 switch (VTOI(ap->a_vp)->i_mnt->iso_ftype) {
964 case ISO_FTYPE_RRIP:
965 *ap->a_retval = ISO_RRIP_NAMEMAX;
966 break;
967 case ISO_FTYPE_JOLIET:
968 *ap->a_retval = ISO_JOLIET_NAMEMAX;
969 break;
970 default:
971 *ap->a_retval = ISO_NAMEMAX;
972 }
973 return (0);
974 case _PC_PATH_MAX:
975 *ap->a_retval = PATH_MAX;
976 return (0);
977 case _PC_PIPE_BUF:
978 *ap->a_retval = PIPE_BUF;
979 return (0);
980 case _PC_CHOWN_RESTRICTED:
981 *ap->a_retval = 1;
982 return (0);
983 case _PC_NO_TRUNC:
984 *ap->a_retval = 1;
985 return (0);
986 default:
987 return (EINVAL);
988 }
989 /* NOTREACHED */
990}
991
992/*
993 * Unsupported operation
994 */
995int
996cd9660_enotsupp()
997{
998
999 return (EOPNOTSUPP);
1000}
1001/* Pagein. similar to read */
1002int
1003cd9660_pagein(ap)
1004 struct vop_pagein_args /* {
1005 struct vnode *a_vp,
1006 upl_t a_pl,
1007 vm_offset_t a_pl_offset,
1008 off_t a_f_offset,
1009 size_t a_size,
1010 struct ucred *a_cred,
1011 int a_flags
1012 } */ *ap;
1013{
1014 struct vnode *vp = ap->a_vp;
1015 upl_t pl = ap->a_pl;
1016 size_t size= ap->a_size;
1017 off_t f_offset = ap->a_f_offset;
1018 vm_offset_t pl_offset = ap->a_pl_offset;
1019 int flags = ap->a_flags;
1020 register struct iso_node *ip = VTOI(vp);
1021 int devBlockSize=0, error;
1022
1023 /* check pageouts are for reg file only and ubc info is present*/
1024 if (UBCINVALID(vp))
1025 panic("cd9660_pagein: Not a VREG");
1026 UBCINFOCHECK("cd9660_pagein", vp);
1027
1028 VOP_DEVBLOCKSIZE(ip->i_devvp, &devBlockSize);
1029
1030 error = cluster_pagein(vp, pl, pl_offset, f_offset, size,
1031 (off_t)ip->i_size, devBlockSize, flags);
1032 return (error);
1033}
1034
1035/*
1036 * cd9660_remove - not possible to remove a file from iso cds
1037 *
1038 * Locking policy: a_dvp and vp locked on entry, unlocked on exit
1039 */
1040int
1041cd9660_remove(ap)
1042 struct vop_remove_args /* { struct vnode *a_dvp; struct vnode *a_vp;
1043 struct componentname *a_cnp; } */ *ap;
1044{
1045 if (ap->a_dvp == ap->a_vp)
1046 vrele(ap->a_vp);
1047 else
1048 vput(ap->a_vp);
1049 vput(ap->a_dvp);
1050
1051 return (EROFS);
1052}
1053
1054
1055/*
1056 * cd9660_rmdir - not possible to remove a directory from iso cds
1057 *
1058 * Locking policy: a_dvp and vp locked on entry, unlocked on exit
1059 */
1060int
1061cd9660_rmdir(ap)
1062 struct vop_rmdir_args /* { struct vnode *a_dvp; struct vnode *a_vp;
1063 struct componentname *a_cnp; } */ *ap;
1064{
1065 (void) nop_rmdir(ap);
1066 return (EROFS);
1067}
1068
1069/*
1070
1071#
1072#% getattrlist vp = = =
1073#
1074 vop_getattrlist {
1075 IN struct vnode *vp;
1076 IN struct attrlist *alist;
1077 INOUT struct uio *uio;
1078 IN struct ucred *cred;
1079 IN struct proc *p;
1080 };
1081
1082 */
1083int
1084cd9660_getattrlist(ap)
1085 struct vop_getattrlist_args /* {
1086 struct vnode *a_vp;
1087 struct attrlist *a_alist
1088 struct uio *a_uio;
1089 struct ucred *a_cred;
1090 struct proc *a_p;
1091 } */ *ap;
1092{
1093 struct attrlist *alist = ap->a_alist;
1094 int fixedblocksize;
1095 int attrblocksize;
1096 int attrbufsize;
1097 void *attrbufptr;
1098 void *attrptr;
1099 void *varptr;
1100 int error = 0;
1101
1102 if ((alist->bitmapcount != ATTR_BIT_MAP_COUNT) ||
1103 ((alist->commonattr & ~ATTR_CMN_VALIDMASK) != 0) ||
1104 ((alist->volattr & ~ATTR_VOL_VALIDMASK) != 0) ||
1105 ((alist->dirattr & ~ATTR_DIR_VALIDMASK) != 0) ||
1106 ((alist->fileattr & ~ATTR_FILE_VALIDMASK) != 0) ||
1107 ((alist->forkattr & ~ATTR_FORK_VALIDMASK) != 0)) {
1108 return EINVAL;
1109 };
1110
1111 /*
1112 * Requesting volume information requires setting the ATTR_VOL_INFO bit and
1113 * volume info requests are mutually exclusive with all other info requests:
1114 */
1115 if ((alist->volattr != 0) &&
1116 (((alist->volattr & ATTR_VOL_INFO) == 0) ||
1117 (alist->dirattr != 0) ||
1118 (alist->fileattr != 0) ||
1119 (alist->forkattr != 0) )) {
1120 return EINVAL;
1121 };
1122
1123 /*
1124 * Reject requests for unsupported options for now:
1125 */
1126 if (alist->volattr & ATTR_VOL_MOUNTPOINT) return EINVAL;
1127 if (alist->commonattr & (ATTR_CMN_NAMEDATTRCOUNT | ATTR_CMN_NAMEDATTRLIST)) return EINVAL;
1128 if (alist->fileattr &
1129 (ATTR_FILE_FILETYPE |
1130 ATTR_FILE_FORKCOUNT |
1131 ATTR_FILE_FORKLIST |
1132 ATTR_FILE_DATAEXTENTS |
1133 ATTR_FILE_RSRCEXTENTS)) {
1134 return EINVAL;
1135 };
1136
1137
1138 fixedblocksize = attrcalcsize(alist);
1139 attrblocksize = fixedblocksize + (sizeof(u_long)); /* u_long for length longword */
1140 if (alist->commonattr & ATTR_CMN_NAME) attrblocksize += NAME_MAX;
1141 if (alist->commonattr & ATTR_CMN_NAMEDATTRLIST) attrblocksize += 0; /* XXX PPD */
1142 if (alist->volattr & ATTR_VOL_MOUNTPOINT) attrblocksize += PATH_MAX;
1143 if (alist->volattr & ATTR_VOL_NAME) attrblocksize += NAME_MAX;
1144 if (alist->fileattr & ATTR_FILE_FORKLIST) attrblocksize += 0; /* XXX PPD */
1145
1146 attrbufsize = MIN(ap->a_uio->uio_resid, attrblocksize);
1147 MALLOC(attrbufptr, void *, attrblocksize, M_TEMP, M_WAITOK);
1148 attrptr = attrbufptr;
1149 *((u_long *)attrptr) = 0; /* Set buffer length in case of errors */
1150 ++((u_long *)attrptr); /* Reserve space for length field */
1151 varptr = ((char *)attrptr) + fixedblocksize; /* Point to variable-length storage */
1152
1153 packattrblk(alist, ap->a_vp, &attrptr, &varptr);
1154
1155 /* Store length of fixed + var block */
1156 *((u_long *)attrbufptr) = ((char*)varptr - (char*)attrbufptr);
1157 /* Don't copy out more data than was generated */
1158 attrbufsize = MIN(attrbufsize, (char*)varptr - (char*)attrbufptr);
1159
1160 error = uiomove((caddr_t)attrbufptr, attrbufsize, ap->a_uio);
1161
1162 FREE(attrbufptr, M_TEMP);
1163
1164 return error;
1165}
1166
1167/*
1168 * Global vfs data structures for isofs
1169 */
1170#define cd9660_create \
1171 ((int (*) __P((struct vop_create_args *)))err_create)
1172#define cd9660_mknod ((int (*) __P((struct vop_mknod_args *)))err_mknod)
1173#define cd9660_setattr \
1174 ((int (*) __P((struct vop_setattr_args *)))cd9660_enotsupp)
1175#define cd9660_write ((int (*) __P((struct vop_write_args *)))cd9660_enotsupp)
1176#if NFSSERVER
1177int lease_check __P((struct vop_lease_args *));
1178#define cd9660_lease_check lease_check
1179#else
1180#define cd9660_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
1181#endif
1182#define cd9660_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
1183#define cd9660_rename \
1184 ((int (*) __P((struct vop_rename_args *)))err_rename)
1185#define cd9660_copyfile \
1186 ((int (*) __P((struct vop_copyfile_args *)))err_copyfile)
1187#define cd9660_link ((int (*) __P((struct vop_link_args *)))err_link)
1188#define cd9660_mkdir ((int (*) __P((struct vop_mkdir_args *)))err_mkdir)
1189#define cd9660_symlink \
1190 ((int (*) __P((struct vop_symlink_args *)))err_symlink)
1191#define cd9660_advlock \
1192 ((int (*) __P((struct vop_advlock_args *)))cd9660_enotsupp)
1193#define cd9660_valloc ((int(*) __P(( \
1194 struct vnode *pvp, \
1195 int mode, \
1196 struct ucred *cred, \
1197 struct vnode **vpp))) cd9660_enotsupp)
1198#define cd9660_vfree ((int (*) __P((struct vop_vfree_args *)))cd9660_enotsupp)
1199#define cd9660_truncate \
1200 ((int (*) __P((struct vop_truncate_args *)))cd9660_enotsupp)
1201#define cd9660_update \
1202 ((int (*) __P((struct vop_update_args *)))cd9660_enotsupp)
1203#define cd9660_bwrite \
1204 ((int (*) __P((struct vop_bwrite_args *)))cd9660_enotsupp)
1205#define cd9660_pageout \
1206 ((int (*) __P((struct vop_pageout_args *)))cd9660_enotsupp)
1207int cd9660_blktooff(struct vop_blktooff_args *ap);
1208int cd9660_offtoblk(struct vop_offtoblk_args *ap);
1209int cd9660_cmap(struct vop_cmap_args *ap);
1210
1211#define VOPFUNC int (*)(void *)
1212/*
1213 * Global vfs data structures for cd9660
1214 */
1215int (**cd9660_vnodeop_p)(void *);
1216struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
1217 { &vop_default_desc, (VOPFUNC)vn_default_error },
1218 { &vop_lookup_desc, (VOPFUNC)cd9660_lookup }, /* lookup */
1219 { &vop_create_desc, (VOPFUNC)cd9660_create }, /* create */
1220 { &vop_mknod_desc, (VOPFUNC)cd9660_mknod }, /* mknod */
1221 { &vop_open_desc, (VOPFUNC)cd9660_open }, /* open */
1222 { &vop_close_desc, (VOPFUNC)cd9660_close }, /* close */
1223 { &vop_access_desc, (VOPFUNC)cd9660_access }, /* access */
1224 { &vop_getattr_desc, (VOPFUNC)cd9660_getattr }, /* getattr */
1225 { &vop_setattr_desc, (VOPFUNC)cd9660_setattr }, /* setattr */
1226 { &vop_read_desc, (VOPFUNC)cd9660_read }, /* read */
1227 { &vop_write_desc, (VOPFUNC)cd9660_write }, /* write */
1228 { &vop_lease_desc, (VOPFUNC)cd9660_lease_check },/* lease */
1229 { &vop_ioctl_desc, (VOPFUNC)cd9660_ioctl }, /* ioctl */
1230 { &vop_select_desc, (VOPFUNC)cd9660_select }, /* select */
1231 { &vop_mmap_desc, (VOPFUNC)cd9660_mmap }, /* mmap */
1232 { &vop_fsync_desc, (VOPFUNC)cd9660_fsync }, /* fsync */
1233 { &vop_seek_desc, (VOPFUNC)cd9660_seek }, /* seek */
1234 { &vop_remove_desc, (VOPFUNC)cd9660_remove }, /* remove */
1235 { &vop_link_desc, (VOPFUNC)cd9660_link }, /* link */
1236 { &vop_rename_desc, (VOPFUNC)cd9660_rename }, /* rename */
1237 { &vop_copyfile_desc, (VOPFUNC)cd9660_copyfile },/* copyfile */
1238 { &vop_mkdir_desc, (VOPFUNC)cd9660_mkdir }, /* mkdir */
1239 { &vop_rmdir_desc, (VOPFUNC)cd9660_rmdir }, /* rmdir */
1240 { &vop_symlink_desc, (VOPFUNC)cd9660_symlink }, /* symlink */
1241 { &vop_readdir_desc, (VOPFUNC)cd9660_readdir }, /* readdir */
1242 { &vop_readlink_desc, (VOPFUNC)cd9660_readlink },/* readlink */
1243 { &vop_abortop_desc, (VOPFUNC)cd9660_abortop }, /* abortop */
1244 { &vop_inactive_desc, (VOPFUNC)cd9660_inactive },/* inactive */
1245 { &vop_reclaim_desc, (VOPFUNC)cd9660_reclaim }, /* reclaim */
1246 { &vop_lock_desc, (VOPFUNC)cd9660_lock }, /* lock */
1247 { &vop_unlock_desc, (VOPFUNC)cd9660_unlock }, /* unlock */
1248 { &vop_bmap_desc, (VOPFUNC)cd9660_bmap }, /* bmap */
1249 { &vop_strategy_desc, (VOPFUNC)cd9660_strategy },/* strategy */
1250 { &vop_print_desc, (VOPFUNC)cd9660_print }, /* print */
1251 { &vop_islocked_desc, (VOPFUNC)cd9660_islocked },/* islocked */
1252 { &vop_pathconf_desc, (VOPFUNC)cd9660_pathconf },/* pathconf */
1253 { &vop_advlock_desc, (VOPFUNC)cd9660_advlock }, /* advlock */
1254 { &vop_blkatoff_desc, (VOPFUNC)cd9660_blkatoff },/* blkatoff */
1255 { &vop_valloc_desc, (VOPFUNC)cd9660_valloc }, /* valloc */
1256 { &vop_vfree_desc, (VOPFUNC)cd9660_vfree }, /* vfree */
1257 { &vop_truncate_desc, (VOPFUNC)cd9660_truncate },/* truncate */
1258 { &vop_update_desc, (VOPFUNC)cd9660_update }, /* update */
1259 { &vop_bwrite_desc, (VOPFUNC)vn_bwrite },
1260 { &vop_pagein_desc, (VOPFUNC)cd9660_pagein }, /* Pagein */
1261 { &vop_pageout_desc, (VOPFUNC)cd9660_pageout }, /* Pageout */
1262 { &vop_getattrlist_desc, (VOPFUNC)cd9660_getattrlist }, /* getattrlist */
1263 { &vop_blktooff_desc, (VOPFUNC)cd9660_blktooff }, /* blktooff */
1264 { &vop_offtoblk_desc, (VOPFUNC)cd9660_offtoblk }, /* offtoblk */
1265 { &vop_cmap_desc, (VOPFUNC)cd9660_cmap }, /* cmap */
1266 { (struct vnodeop_desc*)NULL, (VOPFUNC)NULL }
1267};
1268struct vnodeopv_desc cd9660_vnodeop_opv_desc =
1269 { &cd9660_vnodeop_p, cd9660_vnodeop_entries };
1270
1271/*
1272 * Special device vnode ops
1273 */
1274int (**cd9660_specop_p)(void *);
1275struct vnodeopv_entry_desc cd9660_specop_entries[] = {
1276 { &vop_default_desc, (VOPFUNC)vn_default_error },
1277 { &vop_lookup_desc, (VOPFUNC)spec_lookup }, /* lookup */
1278 { &vop_create_desc, (VOPFUNC)spec_create }, /* create */
1279 { &vop_mknod_desc, (VOPFUNC)spec_mknod }, /* mknod */
1280 { &vop_open_desc, (VOPFUNC)spec_open }, /* open */
1281 { &vop_close_desc, (VOPFUNC)spec_close }, /* close */
1282 { &vop_access_desc, (VOPFUNC)cd9660_access }, /* access */
1283 { &vop_getattr_desc, (VOPFUNC)cd9660_getattr }, /* getattr */
1284 { &vop_setattr_desc, (VOPFUNC)cd9660_setattr }, /* setattr */
1285 { &vop_read_desc, (VOPFUNC)spec_read }, /* read */
1286 { &vop_write_desc, (VOPFUNC)spec_write }, /* write */
1287 { &vop_lease_desc, (VOPFUNC)spec_lease_check }, /* lease */
1288 { &vop_ioctl_desc, (VOPFUNC)spec_ioctl }, /* ioctl */
1289 { &vop_select_desc, (VOPFUNC)spec_select }, /* select */
1290 { &vop_mmap_desc, (VOPFUNC)spec_mmap }, /* mmap */
1291 { &vop_fsync_desc, (VOPFUNC)spec_fsync }, /* fsync */
1292 { &vop_seek_desc, (VOPFUNC)spec_seek }, /* seek */
1293 { &vop_remove_desc, (VOPFUNC)spec_remove }, /* remove */
1294 { &vop_link_desc, (VOPFUNC)spec_link }, /* link */
1295 { &vop_rename_desc, (VOPFUNC)spec_rename }, /* rename */
1296 { &vop_mkdir_desc, (VOPFUNC)spec_mkdir }, /* mkdir */
1297 { &vop_rmdir_desc, (VOPFUNC)spec_rmdir }, /* rmdir */
1298 { &vop_symlink_desc, (VOPFUNC)spec_symlink }, /* symlink */
1299 { &vop_readdir_desc, (VOPFUNC)spec_readdir }, /* readdir */
1300 { &vop_readlink_desc, (VOPFUNC)spec_readlink }, /* readlink */
1301 { &vop_abortop_desc, (VOPFUNC)spec_abortop }, /* abortop */
1302 { &vop_inactive_desc, (VOPFUNC)cd9660_inactive },/* inactive */
1303 { &vop_reclaim_desc, (VOPFUNC)cd9660_reclaim }, /* reclaim */
1304 { &vop_lock_desc, (VOPFUNC)cd9660_lock }, /* lock */
1305 { &vop_unlock_desc, (VOPFUNC)cd9660_unlock }, /* unlock */
1306 { &vop_bmap_desc, (VOPFUNC)spec_bmap }, /* bmap */
1307 { &vop_strategy_desc, (VOPFUNC)spec_strategy }, /* strategy */
1308 { &vop_print_desc, (VOPFUNC)cd9660_print }, /* print */
1309 { &vop_islocked_desc, (VOPFUNC)cd9660_islocked },/* islocked */
1310 { &vop_pathconf_desc, (VOPFUNC)spec_pathconf }, /* pathconf */
1311 { &vop_advlock_desc, (VOPFUNC)spec_advlock }, /* advlock */
1312 { &vop_blkatoff_desc, (VOPFUNC)spec_blkatoff }, /* blkatoff */
1313 { &vop_valloc_desc, (VOPFUNC)spec_valloc }, /* valloc */
1314 { &vop_vfree_desc, (VOPFUNC)spec_vfree }, /* vfree */
1315 { &vop_truncate_desc, (VOPFUNC)spec_truncate }, /* truncate */
1316 { &vop_update_desc, (VOPFUNC)cd9660_update }, /* update */
1317 { &vop_bwrite_desc, (VOPFUNC)vn_bwrite },
1318 { &vop_devblocksize_desc, (VOPFUNC)spec_devblocksize }, /* devblocksize */
1319 { &vop_pagein_desc, (VOPFUNC)cd9660_pagein }, /* Pagein */
1320 { &vop_pageout_desc, (VOPFUNC)cd9660_pageout }, /* Pageout */
1321 { &vop_blktooff_desc, (VOPFUNC)cd9660_blktooff }, /* blktooff */
1322 { &vop_offtoblk_desc, (VOPFUNC)cd9660_offtoblk }, /* offtoblk */
1323 { &vop_cmap_desc, (VOPFUNC)cd9660_cmap }, /* cmap */
1324 { (struct vnodeop_desc*)NULL, (VOPFUNC)NULL }
1325};
1326struct vnodeopv_desc cd9660_specop_opv_desc =
1327 { &cd9660_specop_p, cd9660_specop_entries };
1328
1329#if FIFO
1330int (**cd9660_fifoop_p)(void *);
1331struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
1332 { &vop_default_desc, (VOPFUNC)vn_default_error },
1333 { &vop_lookup_desc, (VOPFUNC)fifo_lookup }, /* lookup */
1334 { &vop_create_desc, (VOPFUNC)fifo_create }, /* create */
1335 { &vop_mknod_desc, (VOPFUNC)fifo_mknod }, /* mknod */
1336 { &vop_open_desc, (VOPFUNC)fifo_open }, /* open */
1337 { &vop_close_desc, (VOPFUNC)fifo_close }, /* close */
1338 { &vop_access_desc, (VOPFUNC)cd9660_access }, /* access */
1339 { &vop_getattr_desc, (VOPFUNC)cd9660_getattr }, /* getattr */
1340 { &vop_setattr_desc, (VOPFUNC)cd9660_setattr }, /* setattr */
1341 { &vop_read_desc, (VOPFUNC)fifo_read }, /* read */
1342 { &vop_write_desc, (VOPFUNC)fifo_write }, /* write */
1343 { &vop_lease_desc, (VOPFUNC)fifo_lease_check }, /* lease */
1344 { &vop_ioctl_desc, (VOPFUNC)fifo_ioctl }, /* ioctl */
1345 { &vop_select_desc, (VOPFUNC)fifo_select }, /* select */
1346 { &vop_mmap_desc, (VOPFUNC)fifo_mmap }, /* mmap */
1347 { &vop_fsync_desc, (VOPFUNC)fifo_fsync }, /* fsync */
1348 { &vop_seek_desc, (VOPFUNC)fifo_seek }, /* seek */
1349 { &vop_remove_desc, (VOPFUNC)fifo_remove }, /* remove */
1350 { &vop_link_desc, (VOPFUNC)fifo_link } , /* link */
1351 { &vop_rename_desc, (VOPFUNC)fifo_rename }, /* rename */
1352 { &vop_mkdir_desc, (VOPFUNC)fifo_mkdir }, /* mkdir */
1353 { &vop_rmdir_desc, (VOPFUNC)fifo_rmdir }, /* rmdir */
1354 { &vop_symlink_desc, (VOPFUNC)fifo_symlink }, /* symlink */
1355 { &vop_readdir_desc, (VOPFUNC)fifo_readdir }, /* readdir */
1356 { &vop_readlink_desc, (VOPFUNC)fifo_readlink }, /* readlink */
1357 { &vop_abortop_desc, (VOPFUNC)fifo_abortop }, /* abortop */
1358 { &vop_inactive_desc, (VOPFUNC)cd9660_inactive },/* inactive */
1359 { &vop_reclaim_desc, (VOPFUNC)cd9660_reclaim }, /* reclaim */
1360 { &vop_lock_desc, (VOPFUNC)cd9660_lock }, /* lock */
1361 { &vop_unlock_desc, (VOPFUNC)cd9660_unlock }, /* unlock */
1362 { &vop_bmap_desc, (VOPFUNC)fifo_bmap }, /* bmap */
1363 { &vop_strategy_desc, (VOPFUNC)fifo_strategy }, /* strategy */
1364 { &vop_print_desc, (VOPFUNC)cd9660_print }, /* print */
1365 { &vop_islocked_desc, (VOPFUNC)cd9660_islocked },/* islocked */
1366 { &vop_pathconf_desc, (VOPFUNC)fifo_pathconf }, /* pathconf */
1367 { &vop_advlock_desc, (VOPFUNC)fifo_advlock }, /* advlock */
1368 { &vop_blkatoff_desc, (VOPFUNC)fifo_blkatoff }, /* blkatoff */
1369 { &vop_valloc_desc, (VOPFUNC)fifo_valloc }, /* valloc */
1370 { &vop_vfree_desc, (VOPFUNC)fifo_vfree }, /* vfree */
1371 { &vop_truncate_desc, (VOPFUNC)fifo_truncate }, /* truncate */
1372 { &vop_update_desc, (VOPFUNC)cd9660_update }, /* update */
1373 { &vop_bwrite_desc, (VOPFUNC)vn_bwrite },
1374 { &vop_pagein_desc, (VOPFUNC)cd9660_pagein }, /* Pagein */
1375 { &vop_pageout_desc, (VOPFUNC)cd9660_pageout }, /* Pageout */
1376 { &vop_blktooff_desc, (VOPFUNC)cd9660_blktooff }, /* blktooff */
1377 { &vop_offtoblk_desc, (VOPFUNC)cd9660_offtoblk }, /* offtoblk */
1378 { (struct vnodeop_desc*)NULL, (VOPFUNC)NULL }
1379};
1380struct vnodeopv_desc cd9660_fifoop_opv_desc =
1381 { &cd9660_fifoop_p, cd9660_fifoop_entries };
1382#endif /* FIFO */