3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley
6 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
7 * Support code is derived from software contributed to Berkeley
8 * by Atsushi Murai (amurai@spec.co.jp).
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * @(#)cd9660_vnops.c 8.19 (Berkeley) 5/27/95
39 * $FreeBSD: src/sys/isofs/cd9660/cd9660_vnops.c,v 1.62 1999/12/15 23:01:51 eivind Exp $
40 * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_vnops.c,v 1.40 2008/06/19 23:27:39 dillon Exp $
43 #include <sys/param.h>
44 #include <sys/systm.h>
46 #include <sys/namei.h>
47 #include <sys/kernel.h>
50 #include <sys/mount.h>
51 #include <sys/vnode.h>
52 #include <vfs/fifofs/fifo.h>
53 #include <sys/malloc.h>
54 #include <sys/dirent.h>
55 #include <sys/unistd.h>
56 #include <sys/filio.h>
57 #include <sys/lockf.h>
58 #include <sys/objcache.h>
61 #include <vm/vnode_pager.h>
64 #include "cd9660_node.h"
67 static int cd9660_access (struct vop_access_args
*);
68 static int cd9660_advlock (struct vop_advlock_args
*);
69 static int cd9660_getattr (struct vop_getattr_args
*);
70 static int cd9660_ioctl (struct vop_ioctl_args
*);
71 static int cd9660_pathconf (struct vop_pathconf_args
*);
72 static int cd9660_open (struct vop_open_args
*);
73 static int cd9660_read (struct vop_read_args
*);
74 static int cd9660_setattr (struct vop_setattr_args
*);
76 static int iso_uiodir (struct isoreaddir
*idp
, struct dirent
*dp
,
78 static int iso_shipdir (struct isoreaddir
*idp
);
79 static int cd9660_readdir (struct vop_readdir_args
*);
80 static int cd9660_readlink (struct vop_readlink_args
*ap
);
81 static int cd9660_strategy (struct vop_strategy_args
*);
82 static int cd9660_print (struct vop_print_args
*);
85 * Setattr call. Only allowed for block and character special devices.
87 * cd9660_setattr(struct vnode *a_vp, struct vattr *a_vap,
88 * struct ucred *a_cred, struct proc *a_p)
91 cd9660_setattr(struct vop_setattr_args
*ap
)
93 struct vnode
*vp
= ap
->a_vp
;
94 struct vattr
*vap
= ap
->a_vap
;
96 if (vap
->va_flags
!= (u_long
)VNOVAL
|| vap
->va_uid
!= (uid_t
)VNOVAL
||
97 vap
->va_gid
!= (gid_t
)VNOVAL
|| vap
->va_atime
.tv_sec
!= VNOVAL
||
98 vap
->va_mtime
.tv_sec
!= VNOVAL
|| vap
->va_mode
!= (mode_t
)VNOVAL
)
100 if (vap
->va_size
!= (u_quad_t
)VNOVAL
) {
101 switch (vp
->v_type
) {
121 * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
122 * The mode is shifted to select the owner/group/other fields. The
123 * super user is granted all permissions.
125 * cd9660_access(struct vnode *a_vp, int a_mode, struct ucred *a_cred,
130 cd9660_access(struct vop_access_args
*ap
)
132 struct vnode
*vp
= ap
->a_vp
;
133 struct iso_node
*ip
= VTOI(vp
);
134 struct ucred
*cred
= ap
->a_cred
;
135 mode_t mask
, mode
= ap
->a_mode
;
140 * Disallow write attempts unless the file is a socket,
141 * fifo, or a block or character device resident on the
145 switch (vp
->v_type
) {
156 /* User id 0 always gets access. */
157 if (cred
->cr_uid
== 0)
162 /* Otherwise, check the owner. */
163 if (cred
->cr_uid
== ip
->inode
.iso_uid
) {
170 return ((ip
->inode
.iso_mode
& mask
) == mask
? 0 : EACCES
);
173 /* Otherwise, check the groups. */
174 for (i
= 0, gp
= cred
->cr_groups
; i
< cred
->cr_ngroups
; i
++, gp
++)
175 if (ip
->inode
.iso_gid
== *gp
) {
182 return ((ip
->inode
.iso_mode
& mask
) == mask
?
186 /* Otherwise, check everyone else. */
193 return ((ip
->inode
.iso_mode
& mask
) == mask
? 0 : EACCES
);
197 * cd9660_getattr(struct vnode *a_vp, struct vattr *a_vap)
200 cd9660_getattr(struct vop_getattr_args
*ap
)
202 struct vnode
*vp
= ap
->a_vp
;
203 struct vattr
*vap
= ap
->a_vap
;
204 struct iso_node
*ip
= VTOI(vp
);
206 vap
->va_fsid
= dev2udev(ip
->i_dev
);
207 vap
->va_fileid
= ip
->i_number
;
209 vap
->va_mode
= ip
->inode
.iso_mode
;
210 vap
->va_nlink
= ip
->inode
.iso_links
;
211 vap
->va_uid
= ip
->inode
.iso_uid
;
212 vap
->va_gid
= ip
->inode
.iso_gid
;
213 vap
->va_atime
= ip
->inode
.iso_atime
;
214 vap
->va_mtime
= ip
->inode
.iso_mtime
;
215 vap
->va_ctime
= ip
->inode
.iso_ctime
;
216 vap
->va_rmajor
= umajor(ip
->inode
.iso_rdev
);
217 vap
->va_rminor
= uminor(ip
->inode
.iso_rdev
);
219 vap
->va_size
= (u_quad_t
)(unsigned long)ip
->i_size
;
220 if (ip
->i_size
== 0 && (vap
->va_mode
& S_IFMT
) == S_IFLNK
) {
221 struct vop_readlink_args rdlnk
;
226 MALLOC(cp
, char *, MAXPATHLEN
, M_TEMP
, M_WAITOK
);
228 aiov
.iov_len
= MAXPATHLEN
;
229 auio
.uio_iov
= &aiov
;
232 auio
.uio_rw
= UIO_READ
;
233 auio
.uio_segflg
= UIO_SYSSPACE
;
234 auio
.uio_td
= curthread
;
235 auio
.uio_resid
= MAXPATHLEN
;
237 rdlnk
.a_vp
= ap
->a_vp
;
238 rdlnk
.a_cred
= proc0
.p_ucred
; /* use root cred */
239 if (cd9660_readlink(&rdlnk
) == 0)
240 vap
->va_size
= MAXPATHLEN
- auio
.uio_resid
;
245 vap
->va_blocksize
= ip
->i_mnt
->logical_block_size
;
246 vap
->va_bytes
= (u_quad_t
) ip
->i_size
;
247 vap
->va_type
= vp
->v_type
;
253 * Vnode op for ioctl.
255 * cd9660_ioctl(struct vnode *a_vp, int a_command, caddr_t a_data,
256 * int a_fflag, struct ucred *a_cred, struct proc *a_p)
259 cd9660_ioctl(struct vop_ioctl_args
*ap
)
261 struct vnode
*vp
= ap
->a_vp
;
262 struct iso_node
*ip
= VTOI(vp
);
264 switch (ap
->a_command
) {
267 *(int *)(ap
->a_data
) = ip
->iso_start
;
275 * open is called when the kernel intends to read or memory map a vnode.
278 cd9660_open(struct vop_open_args
*ap
)
280 return(vop_stdopen(ap
));
284 * Vnode op for reading.
286 * cd9660_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
287 * struct ucred *a_cred)
290 cd9660_read(struct vop_read_args
*ap
)
292 struct vnode
*vp
= ap
->a_vp
;
293 struct uio
*uio
= ap
->a_uio
;
294 struct iso_node
*ip
= VTOI(vp
);
297 daddr_t lbn
, rablock
;
301 int rasize
, error
= 0;
305 seqcount
= ap
->a_ioflag
>> 16;
307 if (uio
->uio_resid
== 0)
309 if (uio
->uio_offset
< 0)
311 ip
->i_flag
|= IN_ACCESS
;
314 lbn
= lblkno(imp
, uio
->uio_offset
);
315 loffset
= lblktooff(imp
, lbn
);
316 on
= blkoff(imp
, uio
->uio_offset
);
317 n
= min((u_int
)(imp
->logical_block_size
- on
),
319 diff
= (off_t
)ip
->i_size
- uio
->uio_offset
;
324 size
= blksize(imp
, ip
, lbn
);
326 raoffset
= lblktooff(imp
, rablock
);
327 if ((vp
->v_mount
->mnt_flag
& MNT_NOCLUSTERR
) == 0) {
328 if (raoffset
< ip
->i_size
)
329 error
= cluster_read(vp
, (off_t
)ip
->i_size
,
332 (ap
->a_ioflag
>> 16), &bp
);
334 error
= bread(vp
, loffset
, size
, &bp
);
337 lblktosize(imp
, rablock
) < ip
->i_size
) {
338 rasize
= blksize(imp
, ip
, rablock
);
339 error
= breadn(vp
, loffset
, size
, &raoffset
,
342 error
= bread(vp
, loffset
, size
, &bp
);
344 n
= min(n
, size
- bp
->b_resid
);
350 error
= uiomove(bp
->b_data
+ on
, (int)n
, uio
);
352 } while (error
== 0 && uio
->uio_resid
> 0 && n
!= 0);
356 /* struct dirent + enough space for the maximum supported size */
359 char de_name
[_DIRENT_RECLEN(NAME_MAX
) - sizeof(struct dirent
)];
363 * Structure for reading directories
366 struct iso_dirent saveent
;
367 struct iso_dirent assocent
;
368 struct iso_dirent current
;
380 iso_uiodir(struct isoreaddir
*idp
, struct dirent
*dp
, off_t off
)
384 dp
->d_name
[dp
->d_namlen
] = 0;
386 if (idp
->uio
->uio_resid
< _DIRENT_DIRSIZ(dp
)) {
392 if (idp
->ncookies
<= 0) {
397 *idp
->cookies
++ = off
;
401 if ((error
= uiomove((caddr_t
) dp
,_DIRENT_DIRSIZ(dp
),idp
->uio
)) != 0)
408 iso_shipdir(struct isoreaddir
*idp
)
415 cl
= idp
->current
.de
.d_namlen
;
416 cname
= idp
->current
.de
.d_name
;
417 assoc
= (cl
> 1) && (*cname
== ASSOCCHAR
);
423 dp
= &idp
->saveent
.de
;
425 if (!(sl
= dp
->d_namlen
)) {
426 dp
= &idp
->assocent
.de
;
427 sname
= dp
->d_name
+ 1;
428 sl
= dp
->d_namlen
- 1;
432 || bcmp(sname
,cname
,sl
)) {
433 if (idp
->assocent
.de
.d_namlen
) {
434 if ((error
= iso_uiodir(idp
,&idp
->assocent
.de
,idp
->assocoff
)) != 0)
436 idp
->assocent
.de
.d_namlen
= 0;
438 if (idp
->saveent
.de
.d_namlen
) {
439 if ((error
= iso_uiodir(idp
,&idp
->saveent
.de
,idp
->saveoff
)) != 0)
441 idp
->saveent
.de
.d_namlen
= 0;
446 idp
->assocoff
= idp
->curroff
;
447 bcopy(&idp
->current
,&idp
->assocent
,_DIRENT_DIRSIZ(&idp
->current
.de
));
449 idp
->saveoff
= idp
->curroff
;
450 bcopy(&idp
->current
,&idp
->saveent
,_DIRENT_DIRSIZ(&idp
->current
.de
));
456 * Vnode op for readdir
458 * cd9660_readdir(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred,
459 * int *a_eofflag, int *a_ncookies, off_t *a_cookies)
462 cd9660_readdir(struct vop_readdir_args
*ap
)
464 struct uio
*uio
= ap
->a_uio
;
465 struct isoreaddir
*idp
;
466 struct vnode
*vdp
= ap
->a_vp
;
469 struct buf
*bp
= NULL
;
470 struct iso_directory_record
*ep
;
471 int entryoffsetinblock
;
478 off_t
*cookies
= NULL
;
482 bmask
= imp
->im_bmask
;
484 if ((error
= vn_lock(vdp
, LK_EXCLUSIVE
|LK_RETRY
)) != 0)
487 MALLOC(idp
, struct isoreaddir
*, sizeof(*idp
), M_TEMP
, M_WAITOK
);
488 idp
->saveent
.de
.d_namlen
= idp
->assocent
.de
.d_namlen
= 0;
491 * Is it worth trying to figure out the type?
493 idp
->saveent
.de
.d_type
= DT_UNKNOWN
;
494 idp
->assocent
.de
.d_type
= DT_UNKNOWN
;
495 idp
->current
.de
.d_type
= DT_UNKNOWN
;
497 if (ap
->a_ncookies
== NULL
) {
501 * Guess the number of cookies needed. Guess at least
502 * 1 to avoid a degenerate case in malloc, and cap at
503 * a reasonable limit.
505 ncookies
= uio
->uio_resid
/ 16 + 1;
508 MALLOC(cookies
, off_t
*, ncookies
* sizeof(off_t
),
510 idp
->cookies
= cookies
;
511 idp
->ncookies
= ncookies
;
514 idp
->curroff
= uio
->uio_offset
;
516 if ((entryoffsetinblock
= idp
->curroff
& bmask
) &&
517 (error
= cd9660_devblkatoff(vdp
, (off_t
)idp
->curroff
, NULL
, &bp
))) {
521 endsearch
= dp
->i_size
;
523 while (idp
->curroff
< endsearch
) {
525 * If offset is on a block boundary,
526 * read the next directory block.
527 * Release previous if it exists.
529 if ((idp
->curroff
& bmask
) == 0) {
533 cd9660_devblkatoff(vdp
, (off_t
)idp
->curroff
, NULL
, &bp
)) != 0)
535 entryoffsetinblock
= 0;
538 * Get pointer to next entry.
540 ep
= (struct iso_directory_record
*)
541 ((char *)bp
->b_data
+ entryoffsetinblock
);
543 reclen
= isonum_711(ep
->length
);
545 /* skip to next block, if any */
547 (idp
->curroff
& ~bmask
) + imp
->logical_block_size
;
551 if (reclen
< ISO_DIRECTORY_RECORD_SIZE
) {
553 /* illegal entry, stop */
557 if (entryoffsetinblock
+ reclen
> imp
->logical_block_size
) {
559 /* illegal directory, so stop looking */
563 idp
->current
.de
.d_namlen
= isonum_711(ep
->name_len
);
565 if (reclen
< ISO_DIRECTORY_RECORD_SIZE
+ idp
->current
.de
.d_namlen
) {
567 /* illegal entry, stop */
571 if (isonum_711(ep
->flags
)&2)
572 idp
->current
.de
.d_ino
= isodirino(ep
, imp
);
574 idp
->current
.de
.d_ino
= bp
->b_bio1
.bio_offset
+
577 idp
->curroff
+= reclen
;
579 switch (imp
->iso_ftype
) {
582 ino_t cur_fileno
= idp
->current
.de
.d_ino
;
583 cd9660_rrip_getname(ep
,idp
->current
.de
.d_name
, &namelen
,
585 idp
->current
.de
.d_ino
= cur_fileno
;
586 idp
->current
.de
.d_namlen
= namelen
;
587 if (idp
->current
.de
.d_namlen
)
588 error
= iso_uiodir(idp
,&idp
->current
.de
,idp
->curroff
);
591 default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA*/
592 strcpy(idp
->current
.de
.d_name
,"..");
593 if (idp
->current
.de
.d_namlen
== 1 && ep
->name
[0] == 0) {
594 idp
->current
.de
.d_namlen
= 1;
595 error
= iso_uiodir(idp
,&idp
->current
.de
,idp
->curroff
);
596 } else if (idp
->current
.de
.d_namlen
== 1 && ep
->name
[0] == 1) {
597 idp
->current
.de
.d_namlen
= 2;
598 error
= iso_uiodir(idp
,&idp
->current
.de
,idp
->curroff
);
600 isofntrans(ep
->name
,idp
->current
.de
.d_namlen
,
601 idp
->current
.de
.d_name
, &namelen
,
602 imp
->iso_ftype
== ISO_FTYPE_9660
,
603 isonum_711(ep
->flags
)&4,
605 idp
->current
.de
.d_namlen
= namelen
;
606 if (imp
->iso_ftype
== ISO_FTYPE_DEFAULT
)
607 error
= iso_shipdir(idp
);
609 error
= iso_uiodir(idp
,&idp
->current
.de
,idp
->curroff
);
615 entryoffsetinblock
+= reclen
;
618 if (!error
&& imp
->iso_ftype
== ISO_FTYPE_DEFAULT
) {
619 idp
->current
.de
.d_namlen
= 0;
620 error
= iso_shipdir(idp
);
625 if (ap
->a_ncookies
!= NULL
) {
627 kfree(cookies
, M_TEMP
);
630 * Work out the number of cookies actually used.
632 *ap
->a_ncookies
= ncookies
- idp
->ncookies
;
633 *ap
->a_cookies
= cookies
;
640 uio
->uio_offset
= idp
->uio_off
;
641 *ap
->a_eofflag
= idp
->eofflag
;
651 * Return target name of a symbolic link
652 * Shouldn't we get the parent vnode and read the data from there?
653 * This could eventually result in deadlocks in cd9660_lookup.
654 * But otherwise the block read here is in the block buffer two times.
656 typedef struct iso_directory_record ISODIR
;
657 typedef struct iso_node ISONODE
;
658 typedef struct iso_mnt ISOMNT
;
660 * cd9660_readlink(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred)
663 cd9660_readlink(struct vop_readlink_args
*ap
)
678 if (imp
->iso_ftype
!= ISO_FTYPE_RRIP
)
682 * Get parents directory record block that this inode included.
684 error
= bread(imp
->im_devvp
,
685 (off_t
)ip
->i_number
& ~((1 << imp
->im_bshift
) - 1),
686 imp
->logical_block_size
, &bp
);
693 * Setup the directory pointer for this inode
695 dirp
= (ISODIR
*)(bp
->b_data
+ (ip
->i_number
& imp
->im_bmask
));
698 * Just make sure, we have a right one....
699 * 1: Check not cross boundary on block
701 if ((ip
->i_number
& imp
->im_bmask
) + isonum_711(dirp
->length
)
702 > (unsigned)imp
->logical_block_size
) {
709 * Abuse a namei buffer for now.
711 if (uio
->uio_segflg
== UIO_SYSSPACE
)
712 symname
= uio
->uio_iov
->iov_base
;
714 symname
= objcache_get(namei_oc
, M_WAITOK
);
717 * Ok, we just gathering a symbolic name in SL record.
719 if (cd9660_rrip_getsymname(dirp
, symname
, &symlen
, imp
) == 0) {
720 if (uio
->uio_segflg
!= UIO_SYSSPACE
)
721 objcache_put(namei_oc
, symname
);
726 * Don't forget before you leave from home ;-)
731 * return with the symbolic name to caller's.
733 if (uio
->uio_segflg
!= UIO_SYSSPACE
) {
734 error
= uiomove(symname
, symlen
, uio
);
735 objcache_put(namei_oc
, symname
);
738 uio
->uio_resid
-= symlen
;
739 uio
->uio_iov
->iov_base
= (char *)uio
->uio_iov
->iov_base
+ symlen
;
740 uio
->uio_iov
->iov_len
-= symlen
;
745 * Calculate the logical to physical mapping if not done already,
746 * then call the device strategy routine.
748 * cd9660_strategy(struct buf *a_vp, struct buf *a_bio)
751 cd9660_strategy(struct vop_strategy_args
*ap
)
753 struct bio
*bio
= ap
->a_bio
;
755 struct buf
*bp
= bio
->bio_buf
;
756 struct vnode
*vp
= ap
->a_vp
;
761 if (vp
->v_type
== VBLK
|| vp
->v_type
== VCHR
)
762 panic("cd9660_strategy: spec");
763 nbio
= push_bio(bio
);
764 if (nbio
->bio_offset
== NOOFFSET
) {
765 error
= VOP_BMAP(vp
, bio
->bio_offset
,
766 &nbio
->bio_offset
, NULL
, NULL
, bp
->b_cmd
);
769 bp
->b_flags
|= B_ERROR
;
770 /* I/O was never started on nbio, must biodone(bio) */
774 if (nbio
->bio_offset
== NOOFFSET
)
777 if (nbio
->bio_offset
== NOOFFSET
) {
778 /* I/O was never started on nbio, must biodone(bio) */
783 vn_strategy(vp
, nbio
);
788 * Print out the contents of an inode.
790 * cd9660_print(struct vnode *a_vp)
793 cd9660_print(struct vop_print_args
*ap
)
795 kprintf("tag VT_ISOFS, isofs vnode\n");
800 * Return POSIX pathconf information applicable to cd9660 filesystems.
802 * cd9660_pathconf(struct vnode *a_vp, int a_name, register_t *a_retval)
805 cd9660_pathconf(struct vop_pathconf_args
*ap
)
807 switch (ap
->a_name
) {
812 if (VTOI(ap
->a_vp
)->i_mnt
->iso_ftype
== ISO_FTYPE_RRIP
)
813 *ap
->a_retval
= NAME_MAX
;
818 *ap
->a_retval
= PATH_MAX
;
821 *ap
->a_retval
= PIPE_BUF
;
823 case _PC_CHOWN_RESTRICTED
:
836 * Advisory lock support
839 cd9660_advlock(struct vop_advlock_args
*ap
)
841 struct iso_node
*ip
= VTOI(ap
->a_vp
);
842 return (lf_advlock(ap
, &(ip
->i_lockf
), ip
->i_size
));
847 * Global vfs data structures for cd9660
849 struct vop_ops cd9660_vnode_vops
= {
850 .vop_default
= vop_defaultop
,
851 .vop_open
= cd9660_open
,
852 .vop_access
= cd9660_access
,
853 .vop_advlock
= cd9660_advlock
,
854 .vop_bmap
= cd9660_bmap
,
855 .vop_old_lookup
= cd9660_lookup
,
856 .vop_getattr
= cd9660_getattr
,
857 .vop_inactive
= cd9660_inactive
,
858 .vop_ioctl
= cd9660_ioctl
,
859 .vop_pathconf
= cd9660_pathconf
,
860 .vop_print
= cd9660_print
,
861 .vop_read
= cd9660_read
,
862 .vop_readdir
= cd9660_readdir
,
863 .vop_readlink
= cd9660_readlink
,
864 .vop_reclaim
= cd9660_reclaim
,
865 .vop_setattr
= cd9660_setattr
,
866 .vop_strategy
= cd9660_strategy
,
867 .vop_getpages
= vop_stdgetpages
,
868 .vop_putpages
= vop_stdputpages
872 * Special device vnode ops
874 struct vop_ops cd9660_spec_vops
= {
875 .vop_default
= spec_vnoperate
,
876 .vop_access
= cd9660_access
,
877 .vop_getattr
= cd9660_getattr
,
878 .vop_inactive
= cd9660_inactive
,
879 .vop_print
= cd9660_print
,
880 .vop_reclaim
= cd9660_reclaim
,
881 .vop_setattr
= cd9660_setattr
,
884 struct vop_ops cd9660_fifo_vops
= {
885 .vop_default
= fifo_vnoperate
,
886 .vop_access
= cd9660_access
,
887 .vop_getattr
= cd9660_getattr
,
888 .vop_inactive
= cd9660_inactive
,
889 .vop_print
= cd9660_print
,
890 .vop_reclaim
= cd9660_reclaim
,
891 .vop_setattr
= cd9660_setattr
,