xref: /dragonfly/sys/vfs/isofs/cd9660/cd9660_vnops.c (revision 59a92d18)
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  * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_vnops.c,v 1.40 2008/06/19 23:27:39 dillon Exp $
41  */
42 
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/proc.h>
46 #include <sys/namei.h>
47 #include <sys/kernel.h>
48 #include <sys/stat.h>
49 #include <sys/buf.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>
59 
60 #include <vm/vm.h>
61 #include <vm/vnode_pager.h>
62 
63 #include "iso.h"
64 #include "cd9660_node.h"
65 #include "iso_rrip.h"
66 
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 *);
75 struct isoreaddir;
76 static int iso_uiodir (struct isoreaddir *idp, struct dirent *dp,
77 			   off_t off);
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 *);
83 
84 /*
85  * Setattr call. Only allowed for block and character special devices.
86  *
87  * cd9660_setattr(struct vnode *a_vp, struct vattr *a_vap,
88  *		  struct ucred *a_cred, struct proc *a_p)
89  */
90 int
91 cd9660_setattr(struct vop_setattr_args *ap)
92 {
93 	struct vnode *vp = ap->a_vp;
94 	struct vattr *vap = ap->a_vap;
95 
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)
99 		return (EROFS);
100 	if (vap->va_size != (u_quad_t)VNOVAL) {
101  		switch (vp->v_type) {
102  		case VDIR:
103  			return (EISDIR);
104 		case VLNK:
105 		case VREG:
106 		case VDATABASE:
107 			return (EROFS);
108  		case VCHR:
109  		case VBLK:
110  		case VSOCK:
111  		case VFIFO:
112 		default:
113 			return (0);
114 		}
115 	}
116 	return (0);
117 }
118 
119 /*
120  * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
121  * The mode is shifted to select the owner/group/other fields. The
122  * super user is granted all permissions.
123  *
124  * cd9660_access(struct vnode *a_vp, int a_mode, struct ucred *a_cred,
125  *		 struct proc *a_p)
126  */
127 /* ARGSUSED */
128 static int
129 cd9660_access(struct vop_access_args *ap)
130 {
131 	struct vnode *vp = ap->a_vp;
132 	struct iso_node *ip = VTOI(vp);
133 
134 	KKASSERT(vp->v_mount->mnt_flag & MNT_RDONLY);
135 	return (vop_helper_access(ap, ip->inode.iso_uid, ip->inode.iso_gid,
136 	    		ip->inode.iso_mode, 0));
137 }
138 
139 /*
140  * cd9660_getattr(struct vnode *a_vp, struct vattr *a_vap)
141  */
142 static int
143 cd9660_getattr(struct vop_getattr_args *ap)
144 {
145 	struct vnode *vp = ap->a_vp;
146 	struct vattr *vap = ap->a_vap;
147 	struct iso_node *ip = VTOI(vp);
148 
149 	vap->va_fsid	= dev2udev(ip->i_dev);
150 	vap->va_fileid	= ip->i_number;
151 
152 	vap->va_mode	= ip->inode.iso_mode;
153 	vap->va_nlink	= ip->inode.iso_links;
154 	vap->va_uid	= ip->inode.iso_uid;
155 	vap->va_gid	= ip->inode.iso_gid;
156 	vap->va_atime	= ip->inode.iso_atime;
157 	vap->va_mtime	= ip->inode.iso_mtime;
158 	vap->va_ctime	= ip->inode.iso_ctime;
159 	vap->va_rmajor	= umajor(ip->inode.iso_rdev);
160 	vap->va_rminor	= uminor(ip->inode.iso_rdev);
161 
162 	vap->va_size	= (u_quad_t)(unsigned long)ip->i_size;
163 	if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) {
164 		struct vop_readlink_args rdlnk;
165 		struct iovec aiov;
166 		struct uio auio;
167 		char *cp;
168 
169 		MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
170 		aiov.iov_base = cp;
171 		aiov.iov_len = MAXPATHLEN;
172 		auio.uio_iov = &aiov;
173 		auio.uio_iovcnt = 1;
174 		auio.uio_offset = 0;
175 		auio.uio_rw = UIO_READ;
176 		auio.uio_segflg = UIO_SYSSPACE;
177 		auio.uio_td = curthread;
178 		auio.uio_resid = MAXPATHLEN;
179 		rdlnk.a_uio = &auio;
180 		rdlnk.a_vp = ap->a_vp;
181 		rdlnk.a_cred = proc0.p_ucred; /* use root cred */
182 		if (cd9660_readlink(&rdlnk) == 0)
183 			vap->va_size = MAXPATHLEN - auio.uio_resid;
184 		FREE(cp, M_TEMP);
185 	}
186 	vap->va_flags	= 0;
187 	vap->va_gen = 1;
188 	vap->va_blocksize = ip->i_mnt->logical_block_size;
189 	vap->va_bytes	= (u_quad_t) ip->i_size;
190 	vap->va_type	= vp->v_type;
191 	vap->va_filerev	= 0;
192 	return (0);
193 }
194 
195 /*
196  * Vnode op for ioctl.
197  *
198  * cd9660_ioctl(struct vnode *a_vp, int a_command, caddr_t a_data,
199  *		int a_fflag, struct ucred *a_cred, struct proc *a_p)
200  */
201 static int
202 cd9660_ioctl(struct vop_ioctl_args *ap)
203 {
204 	struct vnode *vp = ap->a_vp;
205 	struct iso_node *ip = VTOI(vp);
206 
207         switch (ap->a_command) {
208 
209         case FIOGETLBA:
210 		*(int *)(ap->a_data) = ip->iso_start;
211 		return 0;
212         default:
213                 return (ENOTTY);
214         }
215 }
216 
217 /*
218  * open is called when the kernel intends to read or memory map a vnode.
219  */
220 static int
221 cd9660_open(struct vop_open_args *ap)
222 {
223 	return(vop_stdopen(ap));
224 }
225 
226 /*
227  * Vnode op for reading.
228  *
229  * cd9660_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
230  *		struct ucred *a_cred)
231  */
232 static int
233 cd9660_read(struct vop_read_args *ap)
234 {
235 	struct vnode *vp = ap->a_vp;
236 	struct uio *uio = ap->a_uio;
237 	struct iso_node *ip = VTOI(vp);
238 	struct iso_mnt *imp;
239 	struct buf *bp;
240 	daddr_t lbn, rablock;
241 	off_t raoffset;
242 	off_t loffset;
243 	off_t diff;
244 	int rasize, error = 0;
245 	int seqcount;
246 	long size, n, on;
247 
248 	seqcount = ap->a_ioflag >> 16;
249 
250 	if (uio->uio_resid == 0)
251 		return (0);
252 	if (uio->uio_offset < 0)
253 		return (EINVAL);
254 	ip->i_flag |= IN_ACCESS;
255 	imp = ip->i_mnt;
256 	do {
257 		lbn = lblkno(imp, uio->uio_offset);
258 		loffset = lblktooff(imp, lbn);
259 		on = blkoff(imp, uio->uio_offset);
260 		n = szmin((u_int)(imp->logical_block_size - on),
261 			  uio->uio_resid);
262 		diff = (off_t)ip->i_size - uio->uio_offset;
263 		if (diff <= 0)
264 			return (0);
265 		if (diff < n)
266 			n = diff;
267 		size = blksize(imp, ip, lbn);
268 		rablock = lbn + 1;
269 		raoffset = lblktooff(imp, rablock);
270 		if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) {
271 			if (raoffset < ip->i_size) {
272 				error = cluster_read(vp, (off_t)ip->i_size,
273 						     loffset, size,
274 						     uio->uio_resid,
275 						     (ap->a_ioflag >> 16) *
276 						      BKVASIZE,
277 						     &bp);
278 			} else {
279 				error = bread(vp, loffset, size, &bp);
280 			}
281 		} else {
282 			if (seqcount > 1 &&
283 			    lblktosize(imp, rablock) < ip->i_size) {
284 				rasize = blksize(imp, ip, rablock);
285 				error = breadn(vp, loffset, size, &raoffset,
286 					       &rasize, 1, &bp);
287 			} else
288 				error = bread(vp, loffset, size, &bp);
289 		}
290 		n = imin(n, size - bp->b_resid);
291 		if (error) {
292 			brelse(bp);
293 			return (error);
294 		}
295 
296 		error = uiomove(bp->b_data + on, (int)n, uio);
297 		brelse(bp);
298 	} while (error == 0 && uio->uio_resid > 0 && n != 0);
299 	return (error);
300 }
301 
302 /* struct dirent + enough space for the maximum supported size */
303 struct iso_dirent {
304 	struct dirent de;
305 	char de_name[_DIRENT_RECLEN(NAME_MAX) - sizeof(struct dirent)];
306 };
307 
308 /*
309  * Structure for reading directories
310  */
311 struct isoreaddir {
312 	struct iso_dirent saveent;
313 	struct iso_dirent assocent;
314 	struct iso_dirent current;
315 	off_t saveoff;
316 	off_t assocoff;
317 	off_t curroff;
318 	struct uio *uio;
319 	off_t uio_off;
320 	int eofflag;
321 	off_t *cookies;
322 	int ncookies;
323 };
324 
325 int
326 iso_uiodir(struct isoreaddir *idp, struct dirent *dp, off_t off)
327 {
328 	int error;
329 
330 	dp->d_name[dp->d_namlen] = 0;
331 
332 	if (idp->uio->uio_resid < _DIRENT_DIRSIZ(dp)) {
333 		idp->eofflag = 0;
334 		return (-1);
335 	}
336 
337 	if (idp->cookies) {
338 		if (idp->ncookies <= 0) {
339 			idp->eofflag = 0;
340 			return (-1);
341 		}
342 
343 		*idp->cookies++ = off;
344 		--idp->ncookies;
345 	}
346 
347 	if ((error = uiomove((caddr_t) dp,_DIRENT_DIRSIZ(dp),idp->uio)) != 0)
348 		return (error);
349 	idp->uio_off = off;
350 	return (0);
351 }
352 
353 int
354 iso_shipdir(struct isoreaddir *idp)
355 {
356 	struct dirent *dp;
357 	int cl, sl, assoc;
358 	int error;
359 	char *cname, *sname;
360 
361 	cl = idp->current.de.d_namlen;
362 	cname = idp->current.de.d_name;
363 assoc = (cl > 1) && (*cname == ASSOCCHAR);
364 	if (assoc) {
365 		cl--;
366 		cname++;
367 	}
368 
369 	dp = &idp->saveent.de;
370 	sname = dp->d_name;
371 	if (!(sl = dp->d_namlen)) {
372 		dp = &idp->assocent.de;
373 		sname = dp->d_name + 1;
374 		sl = dp->d_namlen - 1;
375 	}
376 	if (sl > 0) {
377 		if (sl != cl
378 		    || bcmp(sname,cname,sl)) {
379 			if (idp->assocent.de.d_namlen) {
380 				if ((error = iso_uiodir(idp,&idp->assocent.de,idp->assocoff)) != 0)
381 					return (error);
382 				idp->assocent.de.d_namlen = 0;
383 			}
384 			if (idp->saveent.de.d_namlen) {
385 				if ((error = iso_uiodir(idp,&idp->saveent.de,idp->saveoff)) != 0)
386 					return (error);
387 				idp->saveent.de.d_namlen = 0;
388 			}
389 		}
390 	}
391 	if (assoc) {
392 		idp->assocoff = idp->curroff;
393 		bcopy(&idp->current,&idp->assocent,_DIRENT_DIRSIZ(&idp->current.de));
394 	} else {
395 		idp->saveoff = idp->curroff;
396 		bcopy(&idp->current,&idp->saveent,_DIRENT_DIRSIZ(&idp->current.de));
397 	}
398 	return (0);
399 }
400 
401 /*
402  * Vnode op for readdir
403  *
404  * cd9660_readdir(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred,
405  *		  int *a_eofflag, int *a_ncookies, off_t *a_cookies)
406  */
407 static int
408 cd9660_readdir(struct vop_readdir_args *ap)
409 {
410 	struct uio *uio = ap->a_uio;
411 	struct isoreaddir *idp;
412 	struct vnode *vdp = ap->a_vp;
413 	struct iso_node *dp;
414 	struct iso_mnt *imp;
415 	struct buf *bp = NULL;
416 	struct iso_directory_record *ep;
417 	int entryoffsetinblock;
418 	doff_t endsearch;
419 	u_long bmask;
420 	int error = 0;
421 	int reclen;
422 	u_short namelen;
423 	int ncookies = 0;
424 	off_t *cookies = NULL;
425 
426 	dp = VTOI(vdp);
427 	imp = dp->i_mnt;
428 	bmask = imp->im_bmask;
429 
430 	if ((error = vn_lock(vdp, LK_EXCLUSIVE|LK_RETRY)) != 0)
431 		return (error);
432 
433 	MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK);
434 	idp->saveent.de.d_namlen = idp->assocent.de.d_namlen = 0;
435 	/*
436 	 * XXX
437 	 * Is it worth trying to figure out the type?
438 	 */
439 	idp->saveent.de.d_type = DT_UNKNOWN;
440 	idp->assocent.de.d_type = DT_UNKNOWN;
441 	idp->current.de.d_type = DT_UNKNOWN;
442 	idp->uio = uio;
443 	if (ap->a_ncookies == NULL) {
444 		idp->cookies = NULL;
445 	} else {
446 		/*
447 		 * Guess the number of cookies needed.  Guess at least
448 		 * 1 to avoid a degenerate case in malloc, and cap at
449 		 * a reasonable limit.
450 		 */
451 		ncookies = uio->uio_resid / 16 + 1;
452 		if (ncookies > 1024)
453 			ncookies = 1024;
454 		MALLOC(cookies, off_t *, ncookies * sizeof(off_t),
455 		       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, (off_t)idp->curroff, NULL, &bp))) {
464 		FREE(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, (off_t)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 	FREE(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