xref: /dragonfly/sys/vfs/isofs/cd9660/cd9660_vnops.c (revision 7485684f)
1 /*-
2  * Copyright (c) 1994
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley
6  * by Pace Willisson (pace@blitz.com).  The Rock Ridge Extension
7  * Support code is derived from software contributed to Berkeley
8  * by Atsushi Murai (amurai@spec.co.jp).
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
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. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *	@(#)cd9660_vnops.c	8.19 (Berkeley) 5/27/95
35  * $FreeBSD: src/sys/isofs/cd9660/cd9660_vnops.c,v 1.62 1999/12/15 23:01:51 eivind Exp $
36  */
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/uio.h>
41 #include <sys/proc.h>
42 #include <sys/kernel.h>
43 #include <sys/stat.h>
44 #include <sys/buf.h>
45 #include <sys/mount.h>
46 #include <sys/vnode.h>
47 #include <vfs/fifofs/fifo.h>
48 #include <sys/malloc.h>
49 #include <sys/dirent.h>
50 #include <sys/unistd.h>
51 #include <sys/filio.h>
52 #include <sys/lockf.h>
53 #include <sys/objcache.h>
54 
55 #include <vm/vm.h>
56 #include <vm/vnode_pager.h>
57 
58 #include <sys/buf2.h>
59 
60 #include "iso.h"
61 #include "cd9660_mount.h"
62 #include "cd9660_node.h"
63 #include "iso_rrip.h"
64 
65 static int cd9660_access(struct vop_access_args *);
66 static int cd9660_advlock(struct vop_advlock_args *);
67 static int cd9660_getattr(struct vop_getattr_args *);
68 static int cd9660_ioctl(struct vop_ioctl_args *);
69 static int cd9660_pathconf(struct vop_pathconf_args *);
70 static int cd9660_open(struct vop_open_args *);
71 static int cd9660_read(struct vop_read_args *);
72 static int cd9660_setattr(struct vop_setattr_args *);
73 struct isoreaddir;
74 static int iso_uiodir(struct isoreaddir *idp, struct dirent *dp, off_t off);
75 static int iso_shipdir(struct isoreaddir *idp);
76 static int cd9660_readdir(struct vop_readdir_args *);
77 static int cd9660_readlink(struct vop_readlink_args *ap);
78 static int cd9660_strategy(struct vop_strategy_args *);
79 static int cd9660_print(struct vop_print_args *);
80 
81 /*
82  * Setattr call. Only allowed for block and character special devices.
83  *
84  * cd9660_setattr(struct vnode *a_vp, struct vattr *a_vap,
85  *		  struct ucred *a_cred, struct proc *a_p)
86  */
87 int
88 cd9660_setattr(struct vop_setattr_args *ap)
89 {
90 	struct vnode *vp = ap->a_vp;
91 	struct vattr *vap = ap->a_vap;
92 
93 	if (vap->va_flags != (u_long)VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
94 	    vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
95 	    vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL)
96 		return (EROFS);
97 	if (vap->va_size != (u_quad_t)VNOVAL) {
98 		switch (vp->v_type) {
99 		case VDIR:
100 			return (EISDIR);
101 		case VLNK:
102 		case VREG:
103 		case VDATABASE:
104 			return (EROFS);
105 		case VCHR:
106 		case VBLK:
107 		case VSOCK:
108 		case VFIFO:
109 		default:
110 			return (0);
111 		}
112 	}
113 	return (0);
114 }
115 
116 /*
117  * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
118  * The mode is shifted to select the owner/group/other fields. The
119  * super user is granted all permissions.
120  *
121  * cd9660_access(struct vnode *a_vp, int a_mode, struct ucred *a_cred,
122  *		 struct proc *a_p)
123  */
124 /* ARGSUSED */
125 static int
126 cd9660_access(struct vop_access_args *ap)
127 {
128 	struct vnode *vp = ap->a_vp;
129 	struct iso_node *ip = VTOI(vp);
130 	mode_t file_mode;
131 	uid_t uid;
132 	gid_t gid;
133 
134 	KKASSERT(vp->v_mount->mnt_flag & MNT_RDONLY);
135 
136 	file_mode = ip->inode.iso_mode;
137 	file_mode &= (vp->v_type == VDIR ?
138 		      ip->i_mnt->im_dmask : ip->i_mnt->im_fmask);
139 	uid = (ip->i_mnt->im_flags & ISOFSMNT_UID) ?
140 	       ip->i_mnt->im_uid : ip->inode.iso_uid;
141 	gid = (ip->i_mnt->im_flags & ISOFSMNT_GID) ?
142 	       ip->i_mnt->im_gid : ip->inode.iso_gid;
143 
144 	return (vop_helper_access(ap, uid, gid, file_mode, 0));
145 }
146 
147 /*
148  * cd9660_getattr(struct vnode *a_vp, struct vattr *a_vap)
149  */
150 static int
151 cd9660_getattr(struct vop_getattr_args *ap)
152 {
153 	struct vnode *vp = ap->a_vp;
154 	struct vattr *vap = ap->a_vap;
155 	struct iso_node *ip = VTOI(vp);
156 
157 	vap->va_fsid	= devid_from_dev(ip->i_dev);
158 	vap->va_fileid	= ip->i_number;
159 
160 	vap->va_mode	= ip->inode.iso_mode;
161 	vap->va_mode	&= (vp->v_type == VDIR ?
162 			    ip->i_mnt->im_dmask : ip->i_mnt->im_fmask);
163 
164 	vap->va_nlink	= ip->inode.iso_links;
165 	vap->va_uid	= (ip->i_mnt->im_flags & ISOFSMNT_UID) ?
166 			   ip->i_mnt->im_uid : ip->inode.iso_uid;
167 	vap->va_gid	= (ip->i_mnt->im_flags & ISOFSMNT_GID) ?
168 			   ip->i_mnt->im_gid : ip->inode.iso_gid;
169 	vap->va_atime	= ip->inode.iso_atime;
170 	vap->va_mtime	= ip->inode.iso_mtime;
171 	vap->va_ctime	= ip->inode.iso_ctime;
172 	vap->va_rmajor	= umajor(ip->inode.iso_rdev);
173 	vap->va_rminor	= uminor(ip->inode.iso_rdev);
174 
175 	vap->va_size	= (u_quad_t)(unsigned long)ip->i_size;
176 	if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) {
177 		struct vop_readlink_args rdlnk;
178 		struct iovec aiov;
179 		struct uio auio;
180 		char *cp;
181 
182 		cp = kmalloc(MAXPATHLEN, M_TEMP, M_WAITOK);
183 		aiov.iov_base = cp;
184 		aiov.iov_len = MAXPATHLEN;
185 		auio.uio_iov = &aiov;
186 		auio.uio_iovcnt = 1;
187 		auio.uio_offset = 0;
188 		auio.uio_rw = UIO_READ;
189 		auio.uio_segflg = UIO_SYSSPACE;
190 		auio.uio_td = curthread;
191 		auio.uio_resid = MAXPATHLEN;
192 		rdlnk.a_uio = &auio;
193 		rdlnk.a_vp = ap->a_vp;
194 		rdlnk.a_cred = proc0.p_ucred; /* use root cred */
195 		if (cd9660_readlink(&rdlnk) == 0)
196 			vap->va_size = MAXPATHLEN - auio.uio_resid;
197 		kfree(cp, M_TEMP);
198 	}
199 	vap->va_flags	= 0;
200 	vap->va_gen = 1;
201 	vap->va_blocksize = ip->i_mnt->logical_block_size;
202 	vap->va_bytes	= (u_quad_t) ip->i_size;
203 	vap->va_type	= vp->v_type;
204 	vap->va_filerev	= 0;
205 	return (0);
206 }
207 
208 /*
209  * Vnode op for ioctl.
210  *
211  * cd9660_ioctl(struct vnode *a_vp, int a_command, caddr_t a_data,
212  *		int a_fflag, struct ucred *a_cred, struct proc *a_p)
213  */
214 static int
215 cd9660_ioctl(struct vop_ioctl_args *ap)
216 {
217 	struct vnode *vp = ap->a_vp;
218 	struct iso_node *ip = VTOI(vp);
219 
220 	switch (ap->a_command) {
221 
222 	case FIOGETLBA:
223 		*(int *)(ap->a_data) = ip->iso_start;
224 		return 0;
225 	default:
226 		return (ENOTTY);
227 	}
228 }
229 
230 /*
231  * open is called when the kernel intends to read or memory map a vnode.
232  */
233 static int
234 cd9660_open(struct vop_open_args *ap)
235 {
236 	return(vop_stdopen(ap));
237 }
238 
239 /*
240  * Vnode op for reading.
241  *
242  * cd9660_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
243  *		struct ucred *a_cred)
244  */
245 static int
246 cd9660_read(struct vop_read_args *ap)
247 {
248 	struct vnode *vp = ap->a_vp;
249 	struct uio *uio = ap->a_uio;
250 	struct iso_node *ip = VTOI(vp);
251 	struct iso_mnt *imp;
252 	struct buf *bp;
253 	daddr_t lbn, rablock;
254 	off_t raoffset;
255 	off_t loffset;
256 	off_t diff;
257 	int rasize, error = 0;
258 	int seqcount;
259 	long size, n, on;
260 
261 	seqcount = ap->a_ioflag >> IO_SEQSHIFT;
262 
263 	if (uio->uio_resid == 0)
264 		return (0);
265 	if (uio->uio_offset < 0)
266 		return (EINVAL);
267 	ip->i_flag |= IN_ACCESS;
268 	imp = ip->i_mnt;
269 	do {
270 		lbn = lblkno(imp, uio->uio_offset);
271 		loffset = lblktooff(imp, lbn);
272 		on = blkoff(imp, uio->uio_offset);
273 		n = szmin((u_int)(imp->logical_block_size - on),
274 			  uio->uio_resid);
275 		diff = (off_t)ip->i_size - uio->uio_offset;
276 		if (diff <= 0)
277 			return (0);
278 		if (diff < n)
279 			n = diff;
280 		size = blksize(imp, ip, lbn);
281 		rablock = lbn + 1;
282 		raoffset = lblktooff(imp, rablock);
283 		if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) {
284 			if (raoffset < ip->i_size) {
285 				error = cluster_read(vp, (off_t)ip->i_size,
286 						     loffset, size,
287 						     uio->uio_resid,
288 						     (ap->a_ioflag >> IO_SEQSHIFT) *
289 						      MAXBSIZE,
290 						     &bp);
291 			} else {
292 				error = bread(vp, loffset, size, &bp);
293 			}
294 		} else {
295 			if (seqcount > 1 &&
296 			    lblktosize(imp, rablock) < ip->i_size) {
297 				rasize = blksize(imp, ip, rablock);
298 				error = breadn(vp, loffset, size, &raoffset,
299 					       &rasize, 1, &bp);
300 			} else
301 				error = bread(vp, loffset, size, &bp);
302 		}
303 		n = imin(n, size - bp->b_resid);
304 		if (error) {
305 			brelse(bp);
306 			return (error);
307 		}
308 
309 		error = uiomove(bp->b_data + on, (int)n, uio);
310 		brelse(bp);
311 	} while (error == 0 && uio->uio_resid > 0 && n != 0);
312 	return (error);
313 }
314 
315 /* struct dirent + enough space for the maximum supported size */
316 struct iso_dirent {
317 	struct dirent de;
318 	char de_name[_DIRENT_RECLEN(NAME_MAX) - sizeof(struct dirent)];
319 };
320 
321 /*
322  * Structure for reading directories
323  */
324 struct isoreaddir {
325 	struct iso_dirent saveent;
326 	struct iso_dirent assocent;
327 	struct iso_dirent current;
328 	off_t saveoff;
329 	off_t assocoff;
330 	off_t curroff;
331 	struct uio *uio;
332 	off_t uio_off;
333 	int eofflag;
334 	off_t *cookies;
335 	int ncookies;
336 };
337 
338 int
339 iso_uiodir(struct isoreaddir *idp, struct dirent *dp, off_t off)
340 {
341 	int error;
342 
343 	dp->d_name[dp->d_namlen] = 0;
344 
345 	if (idp->uio->uio_resid < _DIRENT_DIRSIZ(dp)) {
346 		idp->eofflag = 0;
347 		return (-1);
348 	}
349 
350 	if (idp->cookies) {
351 		if (idp->ncookies <= 0) {
352 			idp->eofflag = 0;
353 			return (-1);
354 		}
355 
356 		*idp->cookies++ = off;
357 		--idp->ncookies;
358 	}
359 
360 	if ((error = uiomove((caddr_t) dp,_DIRENT_DIRSIZ(dp),idp->uio)) != 0)
361 		return (error);
362 	idp->uio_off = off;
363 	return (0);
364 }
365 
366 int
367 iso_shipdir(struct isoreaddir *idp)
368 {
369 	struct dirent *dp;
370 	int cl, sl, assoc;
371 	int error;
372 	char *cname, *sname;
373 
374 	cl = idp->current.de.d_namlen;
375 	cname = idp->current.de.d_name;
376 assoc = (cl > 1) && (*cname == ASSOCCHAR);
377 	if (assoc) {
378 		cl--;
379 		cname++;
380 	}
381 
382 	dp = &idp->saveent.de;
383 	sname = dp->d_name;
384 	if (!(sl = dp->d_namlen)) {
385 		dp = &idp->assocent.de;
386 		sname = dp->d_name + 1;
387 		sl = dp->d_namlen - 1;
388 	}
389 	if (sl > 0) {
390 		if (sl != cl
391 		    || bcmp(sname,cname,sl)) {
392 			if (idp->assocent.de.d_namlen) {
393 				if ((error = iso_uiodir(idp,&idp->assocent.de,idp->assocoff)) != 0)
394 					return (error);
395 				idp->assocent.de.d_namlen = 0;
396 			}
397 			if (idp->saveent.de.d_namlen) {
398 				if ((error = iso_uiodir(idp,&idp->saveent.de,idp->saveoff)) != 0)
399 					return (error);
400 				idp->saveent.de.d_namlen = 0;
401 			}
402 		}
403 	}
404 	if (assoc) {
405 		idp->assocoff = idp->curroff;
406 		bcopy(&idp->current,&idp->assocent,_DIRENT_DIRSIZ(&idp->current.de));
407 	} else {
408 		idp->saveoff = idp->curroff;
409 		bcopy(&idp->current,&idp->saveent,_DIRENT_DIRSIZ(&idp->current.de));
410 	}
411 	return (0);
412 }
413 
414 /*
415  * Vnode op for readdir
416  *
417  * cd9660_readdir(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred,
418  *		  int *a_eofflag, int *a_ncookies, off_t *a_cookies)
419  */
420 static int
421 cd9660_readdir(struct vop_readdir_args *ap)
422 {
423 	struct uio *uio = ap->a_uio;
424 	struct isoreaddir *idp;
425 	struct vnode *vdp = ap->a_vp;
426 	struct iso_node *dp;
427 	struct iso_mnt *imp;
428 	struct buf *bp = NULL;
429 	struct iso_directory_record *ep;
430 	int entryoffsetinblock;
431 	doff_t endsearch;
432 	u_long bmask;
433 	int error = 0;
434 	int reclen;
435 	u_short namelen;
436 	int ncookies = 0;
437 	off_t *cookies = NULL;
438 
439 	dp = VTOI(vdp);
440 	imp = dp->i_mnt;
441 	bmask = imp->im_bmask;
442 
443 	error = vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY | LK_FAILRECLAIM);
444 	if (error)
445 		return (error);
446 
447 	idp = kmalloc(sizeof(*idp), M_TEMP, M_WAITOK);
448 	idp->saveent.de.d_namlen = idp->assocent.de.d_namlen = 0;
449 	/*
450 	 * XXX
451 	 * Is it worth trying to figure out the type?
452 	 */
453 	idp->saveent.de.d_type = DT_UNKNOWN;
454 	idp->assocent.de.d_type = DT_UNKNOWN;
455 	idp->current.de.d_type = DT_UNKNOWN;
456 	idp->uio = uio;
457 	if (ap->a_ncookies == NULL) {
458 		idp->cookies = NULL;
459 	} else {
460 		/*
461 		 * Guess the number of cookies needed.  Guess at least
462 		 * 1 to avoid a degenerate case in malloc, and cap at
463 		 * a reasonable limit.
464 		 */
465 		ncookies = uio->uio_resid / 16 + 1;
466 		if (ncookies > 1024)
467 			ncookies = 1024;
468 		cookies = kmalloc(ncookies * sizeof(off_t), M_TEMP, M_WAITOK);
469 		idp->cookies = cookies;
470 		idp->ncookies = ncookies;
471 	}
472 	idp->eofflag = 1;
473 	idp->curroff = uio->uio_offset;
474 
475 	if ((entryoffsetinblock = idp->curroff & bmask) &&
476 	    (error = cd9660_devblkatoff(vdp, idp->curroff, NULL, &bp))) {
477 		kfree(idp, M_TEMP);
478 		goto done;
479 	}
480 	endsearch = dp->i_size;
481 
482 	while (idp->curroff < endsearch) {
483 		/*
484 		 * If offset is on a block boundary,
485 		 * read the next directory block.
486 		 * Release previous if it exists.
487 		 */
488 		if ((idp->curroff & bmask) == 0) {
489 			if (bp != NULL)
490 				brelse(bp);
491 			if ((error =
492 			    cd9660_devblkatoff(vdp, idp->curroff, NULL, &bp)) != 0)
493 				break;
494 			entryoffsetinblock = 0;
495 		}
496 		/*
497 		 * Get pointer to next entry.
498 		 */
499 		ep = (struct iso_directory_record *)
500 			((char *)bp->b_data + entryoffsetinblock);
501 
502 		reclen = isonum_711(ep->length);
503 		if (reclen == 0) {
504 			/* skip to next block, if any */
505 			idp->curroff =
506 			    (idp->curroff & ~bmask) + imp->logical_block_size;
507 			continue;
508 		}
509 
510 		if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
511 			error = EINVAL;
512 			/* illegal entry, stop */
513 			break;
514 		}
515 
516 		if (entryoffsetinblock + reclen > imp->logical_block_size) {
517 			error = EINVAL;
518 			/* illegal directory, so stop looking */
519 			break;
520 		}
521 
522 		idp->current.de.d_namlen = isonum_711(ep->name_len);
523 
524 		if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.de.d_namlen) {
525 			error = EINVAL;
526 			/* illegal entry, stop */
527 			break;
528 		}
529 
530 		if (isonum_711(ep->flags)&2)
531 			idp->current.de.d_ino = isodirino(ep, imp);
532 		else
533 			idp->current.de.d_ino = bp->b_bio1.bio_offset +
534 						entryoffsetinblock;
535 
536 		idp->curroff += reclen;
537 
538 		switch (imp->iso_ftype) {
539 		case ISO_FTYPE_RRIP:
540 		{
541 			ino_t cur_fileno = idp->current.de.d_ino;
542 			cd9660_rrip_getname(ep,idp->current.de.d_name, &namelen,
543 					   &cur_fileno,imp);
544 			idp->current.de.d_ino = cur_fileno;
545 			idp->current.de.d_namlen = namelen;
546 			if (idp->current.de.d_namlen)
547 				error = iso_uiodir(idp,&idp->current.de,idp->curroff);
548 			break;
549 		}
550 		default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA*/
551 			strcpy(idp->current.de.d_name,"..");
552 			if (idp->current.de.d_namlen == 1 && ep->name[0] == 0) {
553 				idp->current.de.d_namlen = 1;
554 				error = iso_uiodir(idp,&idp->current.de,idp->curroff);
555 			} else if (idp->current.de.d_namlen == 1 && ep->name[0] == 1) {
556 				idp->current.de.d_namlen = 2;
557 				error = iso_uiodir(idp,&idp->current.de,idp->curroff);
558 			} else {
559 				isofntrans(ep->name,idp->current.de.d_namlen,
560 					   idp->current.de.d_name, &namelen,
561 					   imp->iso_ftype == ISO_FTYPE_9660,
562 					   isonum_711(ep->flags)&4,
563 					   imp->joliet_level,
564 					   imp->im_flags,
565 					   imp->im_d2l);
566 				idp->current.de.d_namlen = namelen;
567 				if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
568 					error = iso_shipdir(idp);
569 				else
570 					error = iso_uiodir(idp,&idp->current.de,idp->curroff);
571 			}
572 		}
573 		if (error)
574 			break;
575 
576 		entryoffsetinblock += reclen;
577 	}
578 
579 	if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
580 		idp->current.de.d_namlen = 0;
581 		error = iso_shipdir(idp);
582 	}
583 	if (error < 0)
584 		error = 0;
585 
586 	if (ap->a_ncookies != NULL) {
587 		if (error)
588 			kfree(cookies, M_TEMP);
589 		else {
590 			/*
591 			 * Work out the number of cookies actually used.
592 			 */
593 			*ap->a_ncookies = ncookies - idp->ncookies;
594 			*ap->a_cookies = cookies;
595 		}
596 	}
597 
598 	if (bp)
599 		brelse (bp);
600 
601 	uio->uio_offset = idp->uio_off;
602 	*ap->a_eofflag = idp->eofflag;
603 
604 	kfree(idp, M_TEMP);
605 
606 done:
607 	vn_unlock(vdp);
608 	return (error);
609 }
610 
611 /*
612  * Return target name of a symbolic link
613  * Shouldn't we get the parent vnode and read the data from there?
614  * This could eventually result in deadlocks in cd9660_lookup.
615  * But otherwise the block read here is in the block buffer two times.
616  */
617 typedef struct iso_directory_record ISODIR;
618 typedef struct iso_node		    ISONODE;
619 typedef struct iso_mnt		    ISOMNT;
620 /*
621  * cd9660_readlink(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred)
622  */
623 static int
624 cd9660_readlink(struct vop_readlink_args *ap)
625 {
626 	ISONODE	*ip;
627 	ISODIR	*dirp;
628 	ISOMNT	*imp;
629 	struct	buf *bp;
630 	struct	uio *uio;
631 	u_short	symlen;
632 	int	error;
633 	char	*symname;
634 
635 	ip  = VTOI(ap->a_vp);
636 	imp = ip->i_mnt;
637 	uio = ap->a_uio;
638 
639 	if (imp->iso_ftype != ISO_FTYPE_RRIP)
640 		return (EINVAL);
641 
642 	/*
643 	 * Get parents directory record block that this inode included.
644 	 */
645 	error = bread(imp->im_devvp,
646 		      rounddown2((off_t)ip->i_number, 1 << imp->im_bshift),
647 		      imp->logical_block_size, &bp);
648 	if (error) {
649 		brelse(bp);
650 		return (EINVAL);
651 	}
652 
653 	/*
654 	 * Setup the directory pointer for this inode
655 	 */
656 	dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
657 
658 	/*
659 	 * Just make sure, we have a right one....
660 	 *   1: Check not cross boundary on block
661 	 */
662 	if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
663 	    > (unsigned)imp->logical_block_size) {
664 		brelse(bp);
665 		return (EINVAL);
666 	}
667 
668 	/*
669 	 * Now get a buffer
670 	 * Abuse a namei buffer for now.
671 	 */
672 	if (uio->uio_segflg == UIO_SYSSPACE)
673 		symname = uio->uio_iov->iov_base;
674 	else
675 		symname = objcache_get(namei_oc, M_WAITOK);
676 
677 	/*
678 	 * Ok, we just gathering a symbolic name in SL record.
679 	 */
680 	if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
681 		if (uio->uio_segflg != UIO_SYSSPACE)
682 			objcache_put(namei_oc, symname);
683 		brelse(bp);
684 		return (EINVAL);
685 	}
686 	/*
687 	 * Don't forget before you leave from home ;-)
688 	 */
689 	brelse(bp);
690 
691 	/*
692 	 * return with the symbolic name to caller's.
693 	 */
694 	if (uio->uio_segflg != UIO_SYSSPACE) {
695 		error = uiomove(symname, symlen, uio);
696 		objcache_put(namei_oc, symname);
697 		return (error);
698 	}
699 	uio->uio_resid -= symlen;
700 	uio->uio_iov->iov_base = (char *)uio->uio_iov->iov_base + symlen;
701 	uio->uio_iov->iov_len -= symlen;
702 	return (0);
703 }
704 
705 /*
706  * Calculate the logical to physical mapping if not done already,
707  * then call the device strategy routine.
708  *
709  * cd9660_strategy(struct buf *a_vp, struct buf *a_bio)
710  */
711 static int
712 cd9660_strategy(struct vop_strategy_args *ap)
713 {
714 	struct bio *bio = ap->a_bio;
715 	struct bio *nbio;
716 	struct buf *bp = bio->bio_buf;
717 	struct vnode *vp = ap->a_vp;
718 	struct iso_node *ip;
719 	int error;
720 
721 	ip = VTOI(vp);
722 	if (vp->v_type == VBLK || vp->v_type == VCHR)
723 		panic("cd9660_strategy: spec");
724 	nbio = push_bio(bio);
725 	if (nbio->bio_offset == NOOFFSET) {
726 		error = VOP_BMAP(vp, bio->bio_offset,
727 				 &nbio->bio_offset, NULL, NULL, bp->b_cmd);
728 		if (error) {
729 			bp->b_error = error;
730 			bp->b_flags |= B_ERROR;
731 			/* I/O was never started on nbio, must biodone(bio) */
732 			biodone(bio);
733 			return (error);
734 		}
735 		if (nbio->bio_offset == NOOFFSET)
736 			clrbuf(bp);
737 	}
738 	if (nbio->bio_offset == NOOFFSET) {
739 		/* I/O was never started on nbio, must biodone(bio) */
740 		biodone(bio);
741 		return (0);
742 	}
743 	vp = ip->i_devvp;
744 	vn_strategy(vp, nbio);
745 	return (0);
746 }
747 
748 /*
749  * Print out the contents of an inode.
750  *
751  * cd9660_print(struct vnode *a_vp)
752  */
753 static int
754 cd9660_print(struct vop_print_args *ap)
755 {
756 	kprintf("tag VT_ISOFS, isofs vnode\n");
757 	return (0);
758 }
759 
760 /*
761  * Return POSIX pathconf information applicable to cd9660 filesystems.
762  *
763  * cd9660_pathconf(struct vnode *a_vp, int a_name, register_t *a_retval)
764  */
765 static int
766 cd9660_pathconf(struct vop_pathconf_args *ap)
767 {
768 	switch (ap->a_name) {
769 	case _PC_LINK_MAX:
770 		*ap->a_retval = 1;
771 		return (0);
772 	case _PC_NAME_MAX:
773 		if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP)
774 			*ap->a_retval = NAME_MAX;
775 		else
776 			*ap->a_retval = 37;
777 		return (0);
778 	case _PC_PATH_MAX:
779 		*ap->a_retval = PATH_MAX;
780 		return (0);
781 	case _PC_PIPE_BUF:
782 		*ap->a_retval = PIPE_BUF;
783 		return (0);
784 	case _PC_CHOWN_RESTRICTED:
785 		*ap->a_retval = 1;
786 		return (0);
787 	case _PC_NO_TRUNC:
788 		*ap->a_retval = 1;
789 		return (0);
790 	default:
791 		return (EINVAL);
792 	}
793 	/* NOTREACHED */
794 }
795 
796 /*
797  * Advisory lock support
798  */
799 static int
800 cd9660_advlock(struct vop_advlock_args *ap)
801 {
802 	struct iso_node *ip = VTOI(ap->a_vp);
803 	return (lf_advlock(ap, &(ip->i_lockf), ip->i_size));
804 }
805 
806 /*
807  * Global vfs data structures for cd9660
808  */
809 struct vop_ops cd9660_vnode_vops = {
810 	.vop_default =		vop_defaultop,
811 	.vop_open =		cd9660_open,
812 	.vop_access =		cd9660_access,
813 	.vop_advlock =		cd9660_advlock,
814 	.vop_bmap =		cd9660_bmap,
815 	.vop_old_lookup =	cd9660_lookup,
816 	.vop_getattr =		cd9660_getattr,
817 	.vop_inactive =		cd9660_inactive,
818 	.vop_ioctl =		cd9660_ioctl,
819 	.vop_pathconf =		cd9660_pathconf,
820 	.vop_print =		cd9660_print,
821 	.vop_read =		cd9660_read,
822 	.vop_readdir =		cd9660_readdir,
823 	.vop_readlink =		cd9660_readlink,
824 	.vop_reclaim =		cd9660_reclaim,
825 	.vop_setattr =		cd9660_setattr,
826 	.vop_strategy =		cd9660_strategy,
827 	.vop_getpages =		vop_stdgetpages,
828 	.vop_putpages =		vop_stdputpages
829 };
830 
831 /*
832  * Special device vnode ops
833  */
834 struct vop_ops cd9660_spec_vops = {
835 	.vop_default =		vop_defaultop,
836 	.vop_read =		vop_stdnoread,
837 	.vop_access =		cd9660_access,
838 	.vop_getattr =		cd9660_getattr,
839 	.vop_inactive =		cd9660_inactive,
840 	.vop_print =		cd9660_print,
841 	.vop_reclaim =		cd9660_reclaim,
842 	.vop_setattr =		cd9660_setattr,
843 };
844 
845 struct vop_ops cd9660_fifo_vops = {
846 	.vop_default =		fifo_vnoperate,
847 	.vop_access =		cd9660_access,
848 	.vop_getattr =		cd9660_getattr,
849 	.vop_inactive =		cd9660_inactive,
850 	.vop_print =		cd9660_print,
851 	.vop_reclaim =		cd9660_reclaim,
852 	.vop_setattr =		cd9660_setattr,
853 };
854