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