]> git.saurik.com Git - apple/xnu.git/blob - bsd/isofs/cd9660/cd9660_vnops.c
xnu-201.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 * 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 */
104 int
105 cd9660_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 */
122 int
123 cd9660_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 */
140 int
141 cd9660_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
217 int
218 cd9660_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 */
280 int
281 cd9660_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 */
352 int
353 cd9660_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 */
368 int
369 cd9660_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 void *a_wql;
376 struct proc *a_p;
377 } */ *ap;
378 {
379 /*
380 * We should really check to see if I/O is possible.
381 */
382 return (1);
383 }
384
385 /*
386 * Mmap a file
387 *
388 * NB Currently unsupported.
389 */
390 /* ARGSUSED */
391 int
392 cd9660_mmap(ap)
393 struct vop_mmap_args /* {
394 struct vnode *a_vp;
395 int a_fflags;
396 struct ucred *a_cred;
397 struct proc *a_p;
398 } */ *ap;
399 {
400
401 return (EINVAL);
402 }
403
404 /*
405 * Seek on a file
406 *
407 * Nothing to do, so just return.
408 */
409 /* ARGSUSED */
410 int
411 cd9660_seek(ap)
412 struct vop_seek_args /* {
413 struct vnode *a_vp;
414 off_t a_oldoff;
415 off_t a_newoff;
416 struct ucred *a_cred;
417 } */ *ap;
418 {
419
420 return (0);
421 }
422
423 /*
424 * Structure for reading directories
425 */
426 struct isoreaddir {
427 struct dirent saveent;
428 struct dirent current;
429 off_t saveoff;
430 off_t curroff;
431 struct uio *uio;
432 off_t uio_off;
433 int eofflag;
434 // u_long **cookies;
435 // int *ncookies;
436 };
437
438 static int
439 iso_uiodir(idp,dp,off)
440 struct isoreaddir *idp;
441 struct dirent *dp;
442 off_t off;
443 {
444 int error;
445
446 dp->d_name[dp->d_namlen] = 0;
447 dp->d_reclen = DIRSIZ(dp);
448
449 if (idp->uio->uio_resid < dp->d_reclen) {
450 idp->eofflag = 0;
451 return (-1);
452 }
453
454 #if 0
455 if (idp->cookies) {
456 if (*idp->ncookies <= 0) {
457 idp->eofflag = 0;
458 return (-1);
459 }
460
461 **idp->cookies++ = off;
462 --*idp->ncookies;
463 }
464 #endif
465
466 if ( (error = uiomove( (caddr_t)dp, dp->d_reclen, idp->uio )) )
467 return (error);
468 idp->uio_off = off;
469 return (0);
470 }
471
472 static int
473 iso_shipdir(idp)
474 struct isoreaddir *idp;
475 {
476 struct dirent *dp;
477 int cl, sl;
478 int error;
479 char *cname, *sname;
480
481 cl = idp->current.d_namlen;
482 cname = idp->current.d_name;
483
484 dp = &idp->saveent;
485 sname = dp->d_name;
486 sl = dp->d_namlen;
487 if (sl > 0) {
488 if (sl != cl
489 || bcmp(sname,cname,sl)) {
490 if (idp->saveent.d_namlen) {
491 if ( (error = iso_uiodir(idp,&idp->saveent,idp->saveoff)) )
492 return (error);
493 idp->saveent.d_namlen = 0;
494 }
495 }
496 }
497 idp->current.d_reclen = DIRSIZ(&idp->current);
498 idp->saveoff = idp->curroff;
499 bcopy(&idp->current,&idp->saveent,idp->current.d_reclen);
500 return (0);
501 }
502
503 /*
504 * Vnode op for readdir
505 */
506 int
507 cd9660_readdir(ap)
508 struct vop_readdir_args /* {
509 struct vnodeop_desc *a_desc;
510 struct vnode *a_vp;
511 struct uio *a_uio;
512 struct ucred *a_cred;
513 int *a_eofflag;
514 int *a_ncookies;
515 u_long **a_cookies;
516 } */ *ap;
517 {
518 register struct uio *uio = ap->a_uio;
519 off_t startingOffset = uio->uio_offset;
520 size_t lost = 0;
521 struct isoreaddir *idp;
522 struct vnode *vdp = ap->a_vp;
523 struct iso_node *dp;
524 struct iso_mnt *imp;
525 struct buf *bp = NULL;
526 struct iso_directory_record *ep;
527 int entryoffsetinblock;
528 doff_t endsearch;
529 u_long bmask;
530 int error = 0;
531 int reclen;
532 u_short namelen;
533
534 dp = VTOI(vdp);
535 imp = dp->i_mnt;
536 bmask = imp->im_bmask;
537
538 MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK);
539 idp->saveent.d_namlen = 0;
540 /*
541 * XXX
542 * Is it worth trying to figure out the type?
543 */
544 idp->saveent.d_type = idp->current.d_type = DT_UNKNOWN;
545 idp->uio = uio;
546 idp->eofflag = 1;
547 idp->curroff = uio->uio_offset;
548
549 if ((entryoffsetinblock = idp->curroff & bmask) &&
550 (error = VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp))) {
551 FREE(idp, M_TEMP);
552 return (error);
553 }
554 endsearch = dp->i_size;
555
556 while (idp->curroff < endsearch) {
557 /*
558 * If offset is on a block boundary,
559 * read the next directory block.
560 * Release previous if it exists.
561 */
562 if ((idp->curroff & bmask) == 0) {
563 if (bp != NULL)
564 brelse(bp);
565 if ( (error = VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp)) )
566 break;
567 entryoffsetinblock = 0;
568 }
569 /*
570 * Get pointer to next entry.
571 */
572 ep = (struct iso_directory_record *)
573 ((char *)bp->b_data + entryoffsetinblock);
574
575 reclen = isonum_711(ep->length);
576 if (reclen == 0) {
577 /* skip to next block, if any */
578 idp->curroff =
579 (idp->curroff & ~bmask) + imp->logical_block_size;
580 continue;
581 }
582
583 if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
584 error = EINVAL;
585 /* illegal entry, stop */
586 break;
587 }
588
589 if (entryoffsetinblock + reclen > imp->logical_block_size) {
590 error = EINVAL;
591 /* illegal directory, so stop looking */
592 break;
593 }
594
595 idp->current.d_namlen = isonum_711(ep->name_len);
596
597 if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
598 error = EINVAL;
599 /* illegal entry, stop */
600 break;
601 }
602
603 /* skip over associated files (Mac OS resource fork) */
604 if (isonum_711(ep->flags) & associatedBit) {
605 idp->curroff += reclen;
606 entryoffsetinblock += reclen;
607 continue;
608 }
609
610 if ( isonum_711(ep->flags) & directoryBit )
611 idp->current.d_fileno = isodirino(ep, imp);
612 else {
613 idp->current.d_fileno = (bp->b_blkno << imp->im_bshift) + entryoffsetinblock;
614 }
615
616 idp->curroff += reclen;
617
618 switch (imp->iso_ftype) {
619 case ISO_FTYPE_RRIP:
620 cd9660_rrip_getname(ep,idp->current.d_name, &namelen,
621 &idp->current.d_fileno,imp);
622 idp->current.d_namlen = (u_char)namelen;
623 if (idp->current.d_namlen)
624 error = iso_uiodir(idp,&idp->current,idp->curroff);
625 break;
626
627 case ISO_FTYPE_JOLIET:
628 ucsfntrans((u_int16_t *)ep->name, idp->current.d_namlen,
629 idp->current.d_name, &namelen,
630 isonum_711(ep->flags) & directoryBit);
631 idp->current.d_namlen = (u_char)namelen;
632 if (idp->current.d_namlen)
633 error = iso_uiodir(idp,&idp->current,idp->curroff);
634 break;
635
636 default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */
637 strcpy(idp->current.d_name,"..");
638 switch (ep->name[0]) {
639 case 0:
640 idp->current.d_namlen = 1;
641 error = iso_uiodir(idp,&idp->current,idp->curroff);
642 break;
643 case 1:
644 idp->current.d_namlen = 2;
645 error = iso_uiodir(idp,&idp->current,idp->curroff);
646 break;
647 default:
648 isofntrans(ep->name,idp->current.d_namlen,
649 idp->current.d_name, &namelen,
650 imp->iso_ftype == ISO_FTYPE_9660);
651 idp->current.d_namlen = (u_char)namelen;
652 if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
653 error = iso_shipdir(idp);
654 else
655 error = iso_uiodir(idp,&idp->current,idp->curroff);
656 break;
657 }
658 }
659 if (error)
660 break;
661
662 entryoffsetinblock += reclen;
663 }
664
665 if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
666 idp->current.d_namlen = 0;
667 error = iso_shipdir(idp);
668 }
669
670 if (!error && ap->a_ncookies) {
671 struct dirent *dp, *dpstart;
672 off_t bufferOffset;
673 u_long *cookies;
674 int ncookies;
675
676 /*
677 * Only the NFS server uses cookies, and it loads the
678 * directory block into system space, so we can just look at
679 * it directly.
680 *
681 * We assume the entire transfer is done to a single contiguous buffer.
682 */
683 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
684 panic("ufs_readdir: lost in space");
685
686 /*
687 * Make a first pass over the buffer just generated,
688 * counting the number of entries:
689 */
690 dpstart = (struct dirent *) (uio->uio_iov->iov_base - (uio->uio_offset - startingOffset));
691 for (dp = dpstart, bufferOffset = startingOffset, ncookies = 0;
692 bufferOffset < uio->uio_offset; ) {
693 if (dp->d_reclen == 0)
694 break;
695 bufferOffset += dp->d_reclen;
696 ncookies++;
697 dp = (struct dirent *)((caddr_t)dp + dp->d_reclen);
698 }
699 lost += uio->uio_offset - bufferOffset;
700 uio->uio_offset = bufferOffset;
701
702 /*
703 * Allocate a buffer to hold the cookies requested:
704 */
705 MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP, M_WAITOK);
706 *ap->a_ncookies = ncookies;
707 *ap->a_cookies = cookies;
708
709 /*
710 * Fill in the offsets for each entry in the buffer just allocated:
711 */
712 for (bufferOffset = startingOffset, dp = dpstart; bufferOffset < uio->uio_offset; ) {
713 *(cookies++) = bufferOffset;
714 bufferOffset += dp->d_reclen;
715 dp = (struct dirent *)((caddr_t)dp + dp->d_reclen);
716 }
717 }
718
719 if (error < 0)
720 error = 0;
721
722 if (bp)
723 brelse (bp);
724
725 uio->uio_offset = idp->uio_off;
726 *ap->a_eofflag = idp->eofflag;
727
728 FREE(idp, M_TEMP);
729
730 return (error);
731 }
732
733 /*
734 * Return target name of a symbolic link
735 * Shouldn't we get the parent vnode and read the data from there?
736 * This could eventually result in deadlocks in cd9660_lookup.
737 * But otherwise the block read here is in the block buffer two times.
738 */
739 typedef struct iso_directory_record ISODIR;
740 typedef struct iso_node ISONODE;
741 typedef struct iso_mnt ISOMNT;
742 int
743 cd9660_readlink(ap)
744 struct vop_readlink_args /* {
745 struct vnode *a_vp;
746 struct uio *a_uio;
747 struct ucred *a_cred;
748 } */ *ap;
749 {
750 ISONODE *ip;
751 ISODIR *dirp;
752 ISOMNT *imp;
753 struct buf *bp;
754 struct uio *uio;
755 u_short symlen;
756 int error;
757 char *symname;
758
759 ip = VTOI(ap->a_vp);
760 imp = ip->i_mnt;
761 uio = ap->a_uio;
762
763 if (imp->iso_ftype != ISO_FTYPE_RRIP)
764 return (EINVAL);
765
766 /*
767 * Get parents directory record block that this inode included.
768 */
769 error = bread(imp->im_devvp,
770 (ip->i_number >> imp->im_bshift),
771 imp->logical_block_size, NOCRED, &bp);
772 if (error) {
773 brelse(bp);
774 return (EINVAL);
775 }
776
777 /*
778 * Setup the directory pointer for this inode
779 */
780 dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
781
782 /*
783 * Just make sure, we have a right one....
784 * 1: Check not cross boundary on block
785 */
786 if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
787 > imp->logical_block_size) {
788 brelse(bp);
789 return (EINVAL);
790 }
791
792 /*
793 * Now get a buffer
794 * Abuse a namei buffer for now.
795 */
796 if (uio->uio_segflg == UIO_SYSSPACE)
797 symname = uio->uio_iov->iov_base;
798 else
799 MALLOC_ZONE(symname, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
800
801 /*
802 * Ok, we just gathering a symbolic name in SL record.
803 */
804 if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
805 if (uio->uio_segflg != UIO_SYSSPACE)
806 FREE_ZONE(symname, MAXPATHLEN, M_NAMEI);
807 brelse(bp);
808 return (EINVAL);
809 }
810 /*
811 * Don't forget before you leave from home ;-)
812 */
813 brelse(bp);
814
815 /*
816 * return with the symbolic name to caller's.
817 */
818 if (uio->uio_segflg != UIO_SYSSPACE) {
819 error = uiomove(symname, symlen, uio);
820 FREE_ZONE(symname, MAXPATHLEN, M_NAMEI);
821 return (error);
822 }
823 uio->uio_resid -= symlen;
824 uio->uio_iov->iov_base += symlen;
825 uio->uio_iov->iov_len -= symlen;
826 return (0);
827 }
828
829 /*
830 * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
831 * done. If a buffer has been saved in anticipation of a CREATE, delete it.
832 */
833 int
834 cd9660_abortop(ap)
835 struct vop_abortop_args /* {
836 struct vnode *a_dvp;
837 struct componentname *a_cnp;
838 } */ *ap;
839 {
840 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
841 FREE_ZONE(ap->a_cnp->cn_pnbuf, ap->a_cnp->cn_pnlen, M_NAMEI);
842 return (0);
843 }
844
845 /*
846 * Lock an inode.
847 */
848
849 int
850 cd9660_lock(ap)
851 struct vop_lock_args /* {
852 struct vnode *a_vp;
853 int a_flags;
854 struct proc *a_p;
855 } */ *ap;
856 {
857 struct vnode *vp = ap->a_vp;
858
859 if (VTOI(vp) == (struct iso_node *) NULL)
860 panic ("cd9660_lock: null inode");
861 return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, &vp->v_interlock,ap->a_p));
862 }
863
864 /*
865 * Unlock an inode.
866 */
867
868 int
869 cd9660_unlock(ap)
870 struct vop_unlock_args /* {
871 struct vnode *a_vp;
872 int a_flags;
873 struct proc *a_p;
874 } */ *ap;
875 {
876 struct vnode *vp = ap->a_vp;
877
878 return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE, &vp->v_interlock,ap->a_p));
879
880 }
881
882 /*
883 * Calculate the logical to physical mapping if not done already,
884 * then call the device strategy routine.
885 */
886 int
887 cd9660_strategy(ap)
888 struct vop_strategy_args /* {
889 struct buf *a_bp;
890 } */ *ap;
891 {
892 register struct buf *bp = ap->a_bp;
893 register struct vnode *vp = bp->b_vp;
894 register struct iso_node *ip;
895 int error;
896
897 ip = VTOI(vp);
898 if (vp->v_type == VBLK || vp->v_type == VCHR)
899 panic("cd9660_strategy: spec");
900 if (bp->b_blkno == bp->b_lblkno) {
901 if ( (error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL)) ) {
902 bp->b_error = error;
903 bp->b_flags |= B_ERROR;
904 biodone(bp);
905 return (error);
906 }
907 if ((long)bp->b_blkno == -1)
908 clrbuf(bp);
909 }
910 if ((long)bp->b_blkno == -1) {
911 biodone(bp);
912 return (0);
913 }
914 vp = ip->i_devvp;
915 bp->b_dev = vp->v_rdev;
916 VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
917 return (0);
918 }
919
920 /*
921 * Print out the contents of an inode.
922 */
923 int
924 cd9660_print(ap)
925 struct vop_print_args /* {
926 struct vnode *a_vp;
927 } */ *ap;
928 {
929
930 printf("tag VT_ISOFS, isofs vnode\n");
931 return (0);
932 }
933
934 /*
935 * Check for a locked inode.
936 */
937 int
938 cd9660_islocked(ap)
939 struct vop_islocked_args /* {
940 struct vnode *a_vp;
941 } */ *ap;
942 {
943
944 return (lockstatus(&VTOI(ap->a_vp)->i_lock));
945 }
946
947 /*
948 * Return POSIX pathconf information applicable to cd9660 filesystems.
949 */
950 int
951 cd9660_pathconf(ap)
952 struct vop_pathconf_args /* {
953 struct vnode *a_vp;
954 int a_name;
955 register_t *a_retval;
956 } */ *ap;
957 {
958
959 switch (ap->a_name) {
960 case _PC_LINK_MAX:
961 *ap->a_retval = 1;
962 return (0);
963 case _PC_NAME_MAX:
964 switch (VTOI(ap->a_vp)->i_mnt->iso_ftype) {
965 case ISO_FTYPE_RRIP:
966 *ap->a_retval = ISO_RRIP_NAMEMAX;
967 break;
968 case ISO_FTYPE_JOLIET:
969 *ap->a_retval = ISO_JOLIET_NAMEMAX;
970 break;
971 default:
972 *ap->a_retval = ISO_NAMEMAX;
973 }
974 return (0);
975 case _PC_PATH_MAX:
976 *ap->a_retval = PATH_MAX;
977 return (0);
978 case _PC_PIPE_BUF:
979 *ap->a_retval = PIPE_BUF;
980 return (0);
981 case _PC_CHOWN_RESTRICTED:
982 *ap->a_retval = 1;
983 return (0);
984 case _PC_NO_TRUNC:
985 *ap->a_retval = 1;
986 return (0);
987 default:
988 return (EINVAL);
989 }
990 /* NOTREACHED */
991 }
992
993 /*
994 * Unsupported operation
995 */
996 int
997 cd9660_enotsupp()
998 {
999
1000 return (EOPNOTSUPP);
1001 }
1002 /* Pagein. similar to read */
1003 int
1004 cd9660_pagein(ap)
1005 struct vop_pagein_args /* {
1006 struct vnode *a_vp,
1007 upl_t a_pl,
1008 vm_offset_t a_pl_offset,
1009 off_t a_f_offset,
1010 size_t a_size,
1011 struct ucred *a_cred,
1012 int a_flags
1013 } */ *ap;
1014 {
1015 struct vnode *vp = ap->a_vp;
1016 upl_t pl = ap->a_pl;
1017 size_t size= ap->a_size;
1018 off_t f_offset = ap->a_f_offset;
1019 vm_offset_t pl_offset = ap->a_pl_offset;
1020 int flags = ap->a_flags;
1021 register struct iso_node *ip = VTOI(vp);
1022 int devBlockSize=0, error;
1023
1024 /* check pageouts are for reg file only and ubc info is present*/
1025 if (UBCINVALID(vp))
1026 panic("cd9660_pagein: Not a VREG");
1027 UBCINFOCHECK("cd9660_pagein", vp);
1028
1029 VOP_DEVBLOCKSIZE(ip->i_devvp, &devBlockSize);
1030
1031 error = cluster_pagein(vp, pl, pl_offset, f_offset, size,
1032 (off_t)ip->i_size, devBlockSize, flags);
1033 return (error);
1034 }
1035
1036 /*
1037 * cd9660_remove - not possible to remove a file from iso cds
1038 *
1039 * Locking policy: a_dvp and vp locked on entry, unlocked on exit
1040 */
1041 int
1042 cd9660_remove(ap)
1043 struct vop_remove_args /* { struct vnode *a_dvp; struct vnode *a_vp;
1044 struct componentname *a_cnp; } */ *ap;
1045 {
1046 if (ap->a_dvp == ap->a_vp)
1047 vrele(ap->a_vp);
1048 else
1049 vput(ap->a_vp);
1050 vput(ap->a_dvp);
1051
1052 return (EROFS);
1053 }
1054
1055
1056 /*
1057 * cd9660_rmdir - not possible to remove a directory from iso cds
1058 *
1059 * Locking policy: a_dvp and vp locked on entry, unlocked on exit
1060 */
1061 int
1062 cd9660_rmdir(ap)
1063 struct vop_rmdir_args /* { struct vnode *a_dvp; struct vnode *a_vp;
1064 struct componentname *a_cnp; } */ *ap;
1065 {
1066 (void) nop_rmdir(ap);
1067 return (EROFS);
1068 }
1069
1070 /*
1071
1072 #
1073 #% getattrlist vp = = =
1074 #
1075 vop_getattrlist {
1076 IN struct vnode *vp;
1077 IN struct attrlist *alist;
1078 INOUT struct uio *uio;
1079 IN struct ucred *cred;
1080 IN struct proc *p;
1081 };
1082
1083 */
1084 int
1085 cd9660_getattrlist(ap)
1086 struct vop_getattrlist_args /* {
1087 struct vnode *a_vp;
1088 struct attrlist *a_alist
1089 struct uio *a_uio;
1090 struct ucred *a_cred;
1091 struct proc *a_p;
1092 } */ *ap;
1093 {
1094 struct attrlist *alist = ap->a_alist;
1095 int fixedblocksize;
1096 int attrblocksize;
1097 int attrbufsize;
1098 void *attrbufptr;
1099 void *attrptr;
1100 void *varptr;
1101 int error = 0;
1102
1103 if ((alist->bitmapcount != ATTR_BIT_MAP_COUNT) ||
1104 ((alist->commonattr & ~ATTR_CMN_VALIDMASK) != 0) ||
1105 ((alist->volattr & ~ATTR_VOL_VALIDMASK) != 0) ||
1106 ((alist->dirattr & ~ATTR_DIR_VALIDMASK) != 0) ||
1107 ((alist->fileattr & ~ATTR_FILE_VALIDMASK) != 0) ||
1108 ((alist->forkattr & ~ATTR_FORK_VALIDMASK) != 0)) {
1109 return EINVAL;
1110 };
1111
1112 /*
1113 * Requesting volume information requires setting the ATTR_VOL_INFO bit and
1114 * volume info requests are mutually exclusive with all other info requests:
1115 */
1116 if ((alist->volattr != 0) &&
1117 (((alist->volattr & ATTR_VOL_INFO) == 0) ||
1118 (alist->dirattr != 0) ||
1119 (alist->fileattr != 0) ||
1120 (alist->forkattr != 0) )) {
1121 return EINVAL;
1122 };
1123
1124 /*
1125 * Reject requests for unsupported options for now:
1126 */
1127 if (alist->volattr & ATTR_VOL_MOUNTPOINT) return EINVAL;
1128 if (alist->commonattr & (ATTR_CMN_NAMEDATTRCOUNT | ATTR_CMN_NAMEDATTRLIST)) return EINVAL;
1129 if (alist->fileattr &
1130 (ATTR_FILE_FILETYPE |
1131 ATTR_FILE_FORKCOUNT |
1132 ATTR_FILE_FORKLIST |
1133 ATTR_FILE_DATAEXTENTS |
1134 ATTR_FILE_RSRCEXTENTS)) {
1135 return EINVAL;
1136 };
1137
1138
1139 fixedblocksize = attrcalcsize(alist);
1140 attrblocksize = fixedblocksize + (sizeof(u_long)); /* u_long for length longword */
1141 if (alist->commonattr & ATTR_CMN_NAME) attrblocksize += NAME_MAX;
1142 if (alist->commonattr & ATTR_CMN_NAMEDATTRLIST) attrblocksize += 0; /* XXX PPD */
1143 if (alist->volattr & ATTR_VOL_MOUNTPOINT) attrblocksize += PATH_MAX;
1144 if (alist->volattr & ATTR_VOL_NAME) attrblocksize += NAME_MAX;
1145 if (alist->fileattr & ATTR_FILE_FORKLIST) attrblocksize += 0; /* XXX PPD */
1146
1147 attrbufsize = MIN(ap->a_uio->uio_resid, attrblocksize);
1148 MALLOC(attrbufptr, void *, attrblocksize, M_TEMP, M_WAITOK);
1149 attrptr = attrbufptr;
1150 *((u_long *)attrptr) = 0; /* Set buffer length in case of errors */
1151 ++((u_long *)attrptr); /* Reserve space for length field */
1152 varptr = ((char *)attrptr) + fixedblocksize; /* Point to variable-length storage */
1153
1154 packattrblk(alist, ap->a_vp, &attrptr, &varptr);
1155
1156 /* Store length of fixed + var block */
1157 *((u_long *)attrbufptr) = ((char*)varptr - (char*)attrbufptr);
1158 /* Don't copy out more data than was generated */
1159 attrbufsize = MIN(attrbufsize, (char*)varptr - (char*)attrbufptr);
1160
1161 error = uiomove((caddr_t)attrbufptr, attrbufsize, ap->a_uio);
1162
1163 FREE(attrbufptr, M_TEMP);
1164
1165 return error;
1166 }
1167
1168 /*
1169 * Global vfs data structures for isofs
1170 */
1171 #define cd9660_create \
1172 ((int (*) __P((struct vop_create_args *)))err_create)
1173 #define cd9660_mknod ((int (*) __P((struct vop_mknod_args *)))err_mknod)
1174 #define cd9660_setattr \
1175 ((int (*) __P((struct vop_setattr_args *)))cd9660_enotsupp)
1176 #define cd9660_write ((int (*) __P((struct vop_write_args *)))cd9660_enotsupp)
1177 #if NFSSERVER
1178 int lease_check __P((struct vop_lease_args *));
1179 #define cd9660_lease_check lease_check
1180 #else
1181 #define cd9660_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
1182 #endif
1183 #define cd9660_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
1184 #define cd9660_rename \
1185 ((int (*) __P((struct vop_rename_args *)))err_rename)
1186 #define cd9660_copyfile \
1187 ((int (*) __P((struct vop_copyfile_args *)))err_copyfile)
1188 #define cd9660_link ((int (*) __P((struct vop_link_args *)))err_link)
1189 #define cd9660_mkdir ((int (*) __P((struct vop_mkdir_args *)))err_mkdir)
1190 #define cd9660_symlink \
1191 ((int (*) __P((struct vop_symlink_args *)))err_symlink)
1192 #define cd9660_advlock \
1193 ((int (*) __P((struct vop_advlock_args *)))cd9660_enotsupp)
1194 #define cd9660_valloc ((int(*) __P(( \
1195 struct vnode *pvp, \
1196 int mode, \
1197 struct ucred *cred, \
1198 struct vnode **vpp))) cd9660_enotsupp)
1199 #define cd9660_vfree ((int (*) __P((struct vop_vfree_args *)))cd9660_enotsupp)
1200 #define cd9660_truncate \
1201 ((int (*) __P((struct vop_truncate_args *)))cd9660_enotsupp)
1202 #define cd9660_update \
1203 ((int (*) __P((struct vop_update_args *)))cd9660_enotsupp)
1204 #define cd9660_bwrite \
1205 ((int (*) __P((struct vop_bwrite_args *)))cd9660_enotsupp)
1206 #define cd9660_pageout \
1207 ((int (*) __P((struct vop_pageout_args *)))cd9660_enotsupp)
1208 int cd9660_blktooff(struct vop_blktooff_args *ap);
1209 int cd9660_offtoblk(struct vop_offtoblk_args *ap);
1210 int cd9660_cmap(struct vop_cmap_args *ap);
1211
1212 #define VOPFUNC int (*)(void *)
1213 /*
1214 * Global vfs data structures for cd9660
1215 */
1216 int (**cd9660_vnodeop_p)(void *);
1217 struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
1218 { &vop_default_desc, (VOPFUNC)vn_default_error },
1219 { &vop_lookup_desc, (VOPFUNC)cd9660_lookup }, /* lookup */
1220 { &vop_create_desc, (VOPFUNC)cd9660_create }, /* create */
1221 { &vop_mknod_desc, (VOPFUNC)cd9660_mknod }, /* mknod */
1222 { &vop_open_desc, (VOPFUNC)cd9660_open }, /* open */
1223 { &vop_close_desc, (VOPFUNC)cd9660_close }, /* close */
1224 { &vop_access_desc, (VOPFUNC)cd9660_access }, /* access */
1225 { &vop_getattr_desc, (VOPFUNC)cd9660_getattr }, /* getattr */
1226 { &vop_setattr_desc, (VOPFUNC)cd9660_setattr }, /* setattr */
1227 { &vop_read_desc, (VOPFUNC)cd9660_read }, /* read */
1228 { &vop_write_desc, (VOPFUNC)cd9660_write }, /* write */
1229 { &vop_lease_desc, (VOPFUNC)cd9660_lease_check },/* lease */
1230 { &vop_ioctl_desc, (VOPFUNC)cd9660_ioctl }, /* ioctl */
1231 { &vop_select_desc, (VOPFUNC)cd9660_select }, /* select */
1232 { &vop_mmap_desc, (VOPFUNC)cd9660_mmap }, /* mmap */
1233 { &vop_fsync_desc, (VOPFUNC)cd9660_fsync }, /* fsync */
1234 { &vop_seek_desc, (VOPFUNC)cd9660_seek }, /* seek */
1235 { &vop_remove_desc, (VOPFUNC)cd9660_remove }, /* remove */
1236 { &vop_link_desc, (VOPFUNC)cd9660_link }, /* link */
1237 { &vop_rename_desc, (VOPFUNC)cd9660_rename }, /* rename */
1238 { &vop_copyfile_desc, (VOPFUNC)cd9660_copyfile },/* copyfile */
1239 { &vop_mkdir_desc, (VOPFUNC)cd9660_mkdir }, /* mkdir */
1240 { &vop_rmdir_desc, (VOPFUNC)cd9660_rmdir }, /* rmdir */
1241 { &vop_symlink_desc, (VOPFUNC)cd9660_symlink }, /* symlink */
1242 { &vop_readdir_desc, (VOPFUNC)cd9660_readdir }, /* readdir */
1243 { &vop_readlink_desc, (VOPFUNC)cd9660_readlink },/* readlink */
1244 { &vop_abortop_desc, (VOPFUNC)cd9660_abortop }, /* abortop */
1245 { &vop_inactive_desc, (VOPFUNC)cd9660_inactive },/* inactive */
1246 { &vop_reclaim_desc, (VOPFUNC)cd9660_reclaim }, /* reclaim */
1247 { &vop_lock_desc, (VOPFUNC)cd9660_lock }, /* lock */
1248 { &vop_unlock_desc, (VOPFUNC)cd9660_unlock }, /* unlock */
1249 { &vop_bmap_desc, (VOPFUNC)cd9660_bmap }, /* bmap */
1250 { &vop_strategy_desc, (VOPFUNC)cd9660_strategy },/* strategy */
1251 { &vop_print_desc, (VOPFUNC)cd9660_print }, /* print */
1252 { &vop_islocked_desc, (VOPFUNC)cd9660_islocked },/* islocked */
1253 { &vop_pathconf_desc, (VOPFUNC)cd9660_pathconf },/* pathconf */
1254 { &vop_advlock_desc, (VOPFUNC)cd9660_advlock }, /* advlock */
1255 { &vop_blkatoff_desc, (VOPFUNC)cd9660_blkatoff },/* blkatoff */
1256 { &vop_valloc_desc, (VOPFUNC)cd9660_valloc }, /* valloc */
1257 { &vop_vfree_desc, (VOPFUNC)cd9660_vfree }, /* vfree */
1258 { &vop_truncate_desc, (VOPFUNC)cd9660_truncate },/* truncate */
1259 { &vop_update_desc, (VOPFUNC)cd9660_update }, /* update */
1260 { &vop_bwrite_desc, (VOPFUNC)vn_bwrite },
1261 { &vop_pagein_desc, (VOPFUNC)cd9660_pagein }, /* Pagein */
1262 { &vop_pageout_desc, (VOPFUNC)cd9660_pageout }, /* Pageout */
1263 { &vop_getattrlist_desc, (VOPFUNC)cd9660_getattrlist }, /* getattrlist */
1264 { &vop_blktooff_desc, (VOPFUNC)cd9660_blktooff }, /* blktooff */
1265 { &vop_offtoblk_desc, (VOPFUNC)cd9660_offtoblk }, /* offtoblk */
1266 { &vop_cmap_desc, (VOPFUNC)cd9660_cmap }, /* cmap */
1267 { (struct vnodeop_desc*)NULL, (VOPFUNC)NULL }
1268 };
1269 struct vnodeopv_desc cd9660_vnodeop_opv_desc =
1270 { &cd9660_vnodeop_p, cd9660_vnodeop_entries };
1271
1272 /*
1273 * Special device vnode ops
1274 */
1275 int (**cd9660_specop_p)(void *);
1276 struct vnodeopv_entry_desc cd9660_specop_entries[] = {
1277 { &vop_default_desc, (VOPFUNC)vn_default_error },
1278 { &vop_lookup_desc, (VOPFUNC)spec_lookup }, /* lookup */
1279 { &vop_create_desc, (VOPFUNC)spec_create }, /* create */
1280 { &vop_mknod_desc, (VOPFUNC)spec_mknod }, /* mknod */
1281 { &vop_open_desc, (VOPFUNC)spec_open }, /* open */
1282 { &vop_close_desc, (VOPFUNC)spec_close }, /* close */
1283 { &vop_access_desc, (VOPFUNC)cd9660_access }, /* access */
1284 { &vop_getattr_desc, (VOPFUNC)cd9660_getattr }, /* getattr */
1285 { &vop_setattr_desc, (VOPFUNC)cd9660_setattr }, /* setattr */
1286 { &vop_read_desc, (VOPFUNC)spec_read }, /* read */
1287 { &vop_write_desc, (VOPFUNC)spec_write }, /* write */
1288 { &vop_lease_desc, (VOPFUNC)spec_lease_check }, /* lease */
1289 { &vop_ioctl_desc, (VOPFUNC)spec_ioctl }, /* ioctl */
1290 { &vop_select_desc, (VOPFUNC)spec_select }, /* select */
1291 { &vop_mmap_desc, (VOPFUNC)spec_mmap }, /* mmap */
1292 { &vop_fsync_desc, (VOPFUNC)spec_fsync }, /* fsync */
1293 { &vop_seek_desc, (VOPFUNC)spec_seek }, /* seek */
1294 { &vop_remove_desc, (VOPFUNC)spec_remove }, /* remove */
1295 { &vop_link_desc, (VOPFUNC)spec_link }, /* link */
1296 { &vop_rename_desc, (VOPFUNC)spec_rename }, /* rename */
1297 { &vop_mkdir_desc, (VOPFUNC)spec_mkdir }, /* mkdir */
1298 { &vop_rmdir_desc, (VOPFUNC)spec_rmdir }, /* rmdir */
1299 { &vop_symlink_desc, (VOPFUNC)spec_symlink }, /* symlink */
1300 { &vop_readdir_desc, (VOPFUNC)spec_readdir }, /* readdir */
1301 { &vop_readlink_desc, (VOPFUNC)spec_readlink }, /* readlink */
1302 { &vop_abortop_desc, (VOPFUNC)spec_abortop }, /* abortop */
1303 { &vop_inactive_desc, (VOPFUNC)cd9660_inactive },/* inactive */
1304 { &vop_reclaim_desc, (VOPFUNC)cd9660_reclaim }, /* reclaim */
1305 { &vop_lock_desc, (VOPFUNC)cd9660_lock }, /* lock */
1306 { &vop_unlock_desc, (VOPFUNC)cd9660_unlock }, /* unlock */
1307 { &vop_bmap_desc, (VOPFUNC)spec_bmap }, /* bmap */
1308 { &vop_strategy_desc, (VOPFUNC)spec_strategy }, /* strategy */
1309 { &vop_print_desc, (VOPFUNC)cd9660_print }, /* print */
1310 { &vop_islocked_desc, (VOPFUNC)cd9660_islocked },/* islocked */
1311 { &vop_pathconf_desc, (VOPFUNC)spec_pathconf }, /* pathconf */
1312 { &vop_advlock_desc, (VOPFUNC)spec_advlock }, /* advlock */
1313 { &vop_blkatoff_desc, (VOPFUNC)spec_blkatoff }, /* blkatoff */
1314 { &vop_valloc_desc, (VOPFUNC)spec_valloc }, /* valloc */
1315 { &vop_vfree_desc, (VOPFUNC)spec_vfree }, /* vfree */
1316 { &vop_truncate_desc, (VOPFUNC)spec_truncate }, /* truncate */
1317 { &vop_update_desc, (VOPFUNC)cd9660_update }, /* update */
1318 { &vop_bwrite_desc, (VOPFUNC)vn_bwrite },
1319 { &vop_devblocksize_desc, (VOPFUNC)spec_devblocksize }, /* devblocksize */
1320 { &vop_pagein_desc, (VOPFUNC)cd9660_pagein }, /* Pagein */
1321 { &vop_pageout_desc, (VOPFUNC)cd9660_pageout }, /* Pageout */
1322 { &vop_blktooff_desc, (VOPFUNC)cd9660_blktooff }, /* blktooff */
1323 { &vop_offtoblk_desc, (VOPFUNC)cd9660_offtoblk }, /* offtoblk */
1324 { &vop_cmap_desc, (VOPFUNC)cd9660_cmap }, /* cmap */
1325 { (struct vnodeop_desc*)NULL, (VOPFUNC)NULL }
1326 };
1327 struct vnodeopv_desc cd9660_specop_opv_desc =
1328 { &cd9660_specop_p, cd9660_specop_entries };
1329
1330 #if FIFO
1331 int (**cd9660_fifoop_p)(void *);
1332 struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
1333 { &vop_default_desc, (VOPFUNC)vn_default_error },
1334 { &vop_lookup_desc, (VOPFUNC)fifo_lookup }, /* lookup */
1335 { &vop_create_desc, (VOPFUNC)fifo_create }, /* create */
1336 { &vop_mknod_desc, (VOPFUNC)fifo_mknod }, /* mknod */
1337 { &vop_open_desc, (VOPFUNC)fifo_open }, /* open */
1338 { &vop_close_desc, (VOPFUNC)fifo_close }, /* close */
1339 { &vop_access_desc, (VOPFUNC)cd9660_access }, /* access */
1340 { &vop_getattr_desc, (VOPFUNC)cd9660_getattr }, /* getattr */
1341 { &vop_setattr_desc, (VOPFUNC)cd9660_setattr }, /* setattr */
1342 { &vop_read_desc, (VOPFUNC)fifo_read }, /* read */
1343 { &vop_write_desc, (VOPFUNC)fifo_write }, /* write */
1344 { &vop_lease_desc, (VOPFUNC)fifo_lease_check }, /* lease */
1345 { &vop_ioctl_desc, (VOPFUNC)fifo_ioctl }, /* ioctl */
1346 { &vop_select_desc, (VOPFUNC)fifo_select }, /* select */
1347 { &vop_mmap_desc, (VOPFUNC)fifo_mmap }, /* mmap */
1348 { &vop_fsync_desc, (VOPFUNC)fifo_fsync }, /* fsync */
1349 { &vop_seek_desc, (VOPFUNC)fifo_seek }, /* seek */
1350 { &vop_remove_desc, (VOPFUNC)fifo_remove }, /* remove */
1351 { &vop_link_desc, (VOPFUNC)fifo_link } , /* link */
1352 { &vop_rename_desc, (VOPFUNC)fifo_rename }, /* rename */
1353 { &vop_mkdir_desc, (VOPFUNC)fifo_mkdir }, /* mkdir */
1354 { &vop_rmdir_desc, (VOPFUNC)fifo_rmdir }, /* rmdir */
1355 { &vop_symlink_desc, (VOPFUNC)fifo_symlink }, /* symlink */
1356 { &vop_readdir_desc, (VOPFUNC)fifo_readdir }, /* readdir */
1357 { &vop_readlink_desc, (VOPFUNC)fifo_readlink }, /* readlink */
1358 { &vop_abortop_desc, (VOPFUNC)fifo_abortop }, /* abortop */
1359 { &vop_inactive_desc, (VOPFUNC)cd9660_inactive },/* inactive */
1360 { &vop_reclaim_desc, (VOPFUNC)cd9660_reclaim }, /* reclaim */
1361 { &vop_lock_desc, (VOPFUNC)cd9660_lock }, /* lock */
1362 { &vop_unlock_desc, (VOPFUNC)cd9660_unlock }, /* unlock */
1363 { &vop_bmap_desc, (VOPFUNC)fifo_bmap }, /* bmap */
1364 { &vop_strategy_desc, (VOPFUNC)fifo_strategy }, /* strategy */
1365 { &vop_print_desc, (VOPFUNC)cd9660_print }, /* print */
1366 { &vop_islocked_desc, (VOPFUNC)cd9660_islocked },/* islocked */
1367 { &vop_pathconf_desc, (VOPFUNC)fifo_pathconf }, /* pathconf */
1368 { &vop_advlock_desc, (VOPFUNC)fifo_advlock }, /* advlock */
1369 { &vop_blkatoff_desc, (VOPFUNC)fifo_blkatoff }, /* blkatoff */
1370 { &vop_valloc_desc, (VOPFUNC)fifo_valloc }, /* valloc */
1371 { &vop_vfree_desc, (VOPFUNC)fifo_vfree }, /* vfree */
1372 { &vop_truncate_desc, (VOPFUNC)fifo_truncate }, /* truncate */
1373 { &vop_update_desc, (VOPFUNC)cd9660_update }, /* update */
1374 { &vop_bwrite_desc, (VOPFUNC)vn_bwrite },
1375 { &vop_pagein_desc, (VOPFUNC)cd9660_pagein }, /* Pagein */
1376 { &vop_pageout_desc, (VOPFUNC)cd9660_pageout }, /* Pageout */
1377 { &vop_blktooff_desc, (VOPFUNC)cd9660_blktooff }, /* blktooff */
1378 { &vop_offtoblk_desc, (VOPFUNC)cd9660_offtoblk }, /* offtoblk */
1379 { (struct vnodeop_desc*)NULL, (VOPFUNC)NULL }
1380 };
1381 struct vnodeopv_desc cd9660_fifoop_opv_desc =
1382 { &cd9660_fifoop_p, cd9660_fifoop_entries };
1383 #endif /* FIFO */