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