xref: /dragonfly/sys/vfs/isofs/cd9660/cd9660_vnops.c (revision cfd1aba3)
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 	error = vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY | LK_FAILRECLAIM);
432 	if (error)
433 		return (error);
434 
435 	idp = kmalloc(sizeof(*idp), M_TEMP, M_WAITOK);
436 	idp->saveent.de.d_namlen = idp->assocent.de.d_namlen = 0;
437 	/*
438 	 * XXX
439 	 * Is it worth trying to figure out the type?
440 	 */
441 	idp->saveent.de.d_type = DT_UNKNOWN;
442 	idp->assocent.de.d_type = DT_UNKNOWN;
443 	idp->current.de.d_type = DT_UNKNOWN;
444 	idp->uio = uio;
445 	if (ap->a_ncookies == NULL) {
446 		idp->cookies = NULL;
447 	} else {
448 		/*
449 		 * Guess the number of cookies needed.  Guess at least
450 		 * 1 to avoid a degenerate case in malloc, and cap at
451 		 * a reasonable limit.
452 		 */
453 		ncookies = uio->uio_resid / 16 + 1;
454 		if (ncookies > 1024)
455 			ncookies = 1024;
456 		cookies = kmalloc(ncookies * sizeof(off_t), M_TEMP, M_WAITOK);
457 		idp->cookies = cookies;
458 		idp->ncookies = ncookies;
459 	}
460 	idp->eofflag = 1;
461 	idp->curroff = uio->uio_offset;
462 
463 	if ((entryoffsetinblock = idp->curroff & bmask) &&
464 	    (error = cd9660_devblkatoff(vdp, idp->curroff, NULL, &bp))) {
465 		kfree(idp, M_TEMP);
466 		goto done;
467 	}
468 	endsearch = dp->i_size;
469 
470 	while (idp->curroff < endsearch) {
471 		/*
472 		 * If offset is on a block boundary,
473 		 * read the next directory block.
474 		 * Release previous if it exists.
475 		 */
476 		if ((idp->curroff & bmask) == 0) {
477 			if (bp != NULL)
478 				brelse(bp);
479 			if ((error =
480 			    cd9660_devblkatoff(vdp, idp->curroff, NULL, &bp)) != 0)
481 				break;
482 			entryoffsetinblock = 0;
483 		}
484 		/*
485 		 * Get pointer to next entry.
486 		 */
487 		ep = (struct iso_directory_record *)
488 			((char *)bp->b_data + entryoffsetinblock);
489 
490 		reclen = isonum_711(ep->length);
491 		if (reclen == 0) {
492 			/* skip to next block, if any */
493 			idp->curroff =
494 			    (idp->curroff & ~bmask) + imp->logical_block_size;
495 			continue;
496 		}
497 
498 		if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
499 			error = EINVAL;
500 			/* illegal entry, stop */
501 			break;
502 		}
503 
504 		if (entryoffsetinblock + reclen > imp->logical_block_size) {
505 			error = EINVAL;
506 			/* illegal directory, so stop looking */
507 			break;
508 		}
509 
510 		idp->current.de.d_namlen = isonum_711(ep->name_len);
511 
512 		if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.de.d_namlen) {
513 			error = EINVAL;
514 			/* illegal entry, stop */
515 			break;
516 		}
517 
518 		if (isonum_711(ep->flags)&2)
519 			idp->current.de.d_ino = isodirino(ep, imp);
520 		else
521 			idp->current.de.d_ino = bp->b_bio1.bio_offset +
522 						entryoffsetinblock;
523 
524 		idp->curroff += reclen;
525 
526 		switch (imp->iso_ftype) {
527 		case ISO_FTYPE_RRIP:
528 		{
529 			ino_t cur_fileno = idp->current.de.d_ino;
530 			cd9660_rrip_getname(ep,idp->current.de.d_name, &namelen,
531 					   &cur_fileno,imp);
532 			idp->current.de.d_ino = cur_fileno;
533 			idp->current.de.d_namlen = namelen;
534 			if (idp->current.de.d_namlen)
535 				error = iso_uiodir(idp,&idp->current.de,idp->curroff);
536 			break;
537 		}
538 		default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA*/
539 			strcpy(idp->current.de.d_name,"..");
540 			if (idp->current.de.d_namlen == 1 && ep->name[0] == 0) {
541 				idp->current.de.d_namlen = 1;
542 				error = iso_uiodir(idp,&idp->current.de,idp->curroff);
543 			} else if (idp->current.de.d_namlen == 1 && ep->name[0] == 1) {
544 				idp->current.de.d_namlen = 2;
545 				error = iso_uiodir(idp,&idp->current.de,idp->curroff);
546 			} else {
547                                 isofntrans(ep->name,idp->current.de.d_namlen,
548                                            idp->current.de.d_name, &namelen,
549                                            imp->iso_ftype == ISO_FTYPE_9660,
550                                            isonum_711(ep->flags)&4,
551                                            imp->joliet_level,
552                                            imp->im_flags,
553                                            imp->im_d2l);
554 				idp->current.de.d_namlen = namelen;
555 				if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
556 					error = iso_shipdir(idp);
557 				else
558 					error = iso_uiodir(idp,&idp->current.de,idp->curroff);
559 			}
560 		}
561 		if (error)
562 			break;
563 
564 		entryoffsetinblock += reclen;
565 	}
566 
567 	if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
568 		idp->current.de.d_namlen = 0;
569 		error = iso_shipdir(idp);
570 	}
571 	if (error < 0)
572 		error = 0;
573 
574 	if (ap->a_ncookies != NULL) {
575 		if (error)
576 			kfree(cookies, M_TEMP);
577 		else {
578 			/*
579 			 * Work out the number of cookies actually used.
580 			 */
581 			*ap->a_ncookies = ncookies - idp->ncookies;
582 			*ap->a_cookies = cookies;
583 		}
584 	}
585 
586 	if (bp)
587 		brelse (bp);
588 
589 	uio->uio_offset = idp->uio_off;
590 	*ap->a_eofflag = idp->eofflag;
591 
592 	kfree(idp, M_TEMP);
593 
594 done:
595 	vn_unlock(vdp);
596 	return (error);
597 }
598 
599 /*
600  * Return target name of a symbolic link
601  * Shouldn't we get the parent vnode and read the data from there?
602  * This could eventually result in deadlocks in cd9660_lookup.
603  * But otherwise the block read here is in the block buffer two times.
604  */
605 typedef struct iso_directory_record ISODIR;
606 typedef struct iso_node		    ISONODE;
607 typedef struct iso_mnt		    ISOMNT;
608 /*
609  * cd9660_readlink(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred)
610  */
611 static int
612 cd9660_readlink(struct vop_readlink_args *ap)
613 {
614 	ISONODE	*ip;
615 	ISODIR	*dirp;
616 	ISOMNT	*imp;
617 	struct	buf *bp;
618 	struct	uio *uio;
619 	u_short	symlen;
620 	int	error;
621 	char	*symname;
622 
623 	ip  = VTOI(ap->a_vp);
624 	imp = ip->i_mnt;
625 	uio = ap->a_uio;
626 
627 	if (imp->iso_ftype != ISO_FTYPE_RRIP)
628 		return (EINVAL);
629 
630 	/*
631 	 * Get parents directory record block that this inode included.
632 	 */
633 	error = bread(imp->im_devvp,
634 			(off_t)ip->i_number & ~((1 << imp->im_bshift) - 1),
635 		      imp->logical_block_size, &bp);
636 	if (error) {
637 		brelse(bp);
638 		return (EINVAL);
639 	}
640 
641 	/*
642 	 * Setup the directory pointer for this inode
643 	 */
644 	dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
645 
646 	/*
647 	 * Just make sure, we have a right one....
648 	 *   1: Check not cross boundary on block
649 	 */
650 	if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
651 	    > (unsigned)imp->logical_block_size) {
652 		brelse(bp);
653 		return (EINVAL);
654 	}
655 
656 	/*
657 	 * Now get a buffer
658 	 * Abuse a namei buffer for now.
659 	 */
660 	if (uio->uio_segflg == UIO_SYSSPACE)
661 		symname = uio->uio_iov->iov_base;
662 	else
663 		symname = objcache_get(namei_oc, M_WAITOK);
664 
665 	/*
666 	 * Ok, we just gathering a symbolic name in SL record.
667 	 */
668 	if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
669 		if (uio->uio_segflg != UIO_SYSSPACE)
670 			objcache_put(namei_oc, symname);
671 		brelse(bp);
672 		return (EINVAL);
673 	}
674 	/*
675 	 * Don't forget before you leave from home ;-)
676 	 */
677 	brelse(bp);
678 
679 	/*
680 	 * return with the symbolic name to caller's.
681 	 */
682 	if (uio->uio_segflg != UIO_SYSSPACE) {
683 		error = uiomove(symname, symlen, uio);
684 		objcache_put(namei_oc, symname);
685 		return (error);
686 	}
687 	uio->uio_resid -= symlen;
688 	uio->uio_iov->iov_base = (char *)uio->uio_iov->iov_base + symlen;
689 	uio->uio_iov->iov_len -= symlen;
690 	return (0);
691 }
692 
693 /*
694  * Calculate the logical to physical mapping if not done already,
695  * then call the device strategy routine.
696  *
697  * cd9660_strategy(struct buf *a_vp, struct buf *a_bio)
698  */
699 static int
700 cd9660_strategy(struct vop_strategy_args *ap)
701 {
702 	struct bio *bio = ap->a_bio;
703 	struct bio *nbio;
704 	struct buf *bp = bio->bio_buf;
705 	struct vnode *vp = ap->a_vp;
706 	struct iso_node *ip;
707 	int error;
708 
709 	ip = VTOI(vp);
710 	if (vp->v_type == VBLK || vp->v_type == VCHR)
711 		panic("cd9660_strategy: spec");
712 	nbio = push_bio(bio);
713 	if (nbio->bio_offset == NOOFFSET) {
714 		error = VOP_BMAP(vp, bio->bio_offset,
715 				 &nbio->bio_offset, NULL, NULL, bp->b_cmd);
716 		if (error) {
717 			bp->b_error = error;
718 			bp->b_flags |= B_ERROR;
719 			/* I/O was never started on nbio, must biodone(bio) */
720 			biodone(bio);
721 			return (error);
722 		}
723 		if (nbio->bio_offset == NOOFFSET)
724 			clrbuf(bp);
725 	}
726 	if (nbio->bio_offset == NOOFFSET) {
727 		/* I/O was never started on nbio, must biodone(bio) */
728 		biodone(bio);
729 		return (0);
730 	}
731 	vp = ip->i_devvp;
732 	vn_strategy(vp, nbio);
733 	return (0);
734 }
735 
736 /*
737  * Print out the contents of an inode.
738  *
739  * cd9660_print(struct vnode *a_vp)
740  */
741 static int
742 cd9660_print(struct vop_print_args *ap)
743 {
744 	kprintf("tag VT_ISOFS, isofs vnode\n");
745 	return (0);
746 }
747 
748 /*
749  * Return POSIX pathconf information applicable to cd9660 filesystems.
750  *
751  * cd9660_pathconf(struct vnode *a_vp, int a_name, register_t *a_retval)
752  */
753 static int
754 cd9660_pathconf(struct vop_pathconf_args *ap)
755 {
756 	switch (ap->a_name) {
757 	case _PC_LINK_MAX:
758 		*ap->a_retval = 1;
759 		return (0);
760 	case _PC_NAME_MAX:
761 		if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP)
762 			*ap->a_retval = NAME_MAX;
763 		else
764 			*ap->a_retval = 37;
765 		return (0);
766 	case _PC_PATH_MAX:
767 		*ap->a_retval = PATH_MAX;
768 		return (0);
769 	case _PC_PIPE_BUF:
770 		*ap->a_retval = PIPE_BUF;
771 		return (0);
772 	case _PC_CHOWN_RESTRICTED:
773 		*ap->a_retval = 1;
774 		return (0);
775 	case _PC_NO_TRUNC:
776 		*ap->a_retval = 1;
777 		return (0);
778 	default:
779 		return (EINVAL);
780 	}
781 	/* NOTREACHED */
782 }
783 
784 /*
785  * Advisory lock support
786  */
787 static int
788 cd9660_advlock(struct vop_advlock_args *ap)
789 {
790 	struct iso_node *ip = VTOI(ap->a_vp);
791 	return (lf_advlock(ap, &(ip->i_lockf), ip->i_size));
792 }
793 
794 
795 /*
796  * Global vfs data structures for cd9660
797  */
798 struct vop_ops cd9660_vnode_vops = {
799 	.vop_default =		vop_defaultop,
800 	.vop_open =		cd9660_open,
801 	.vop_access =		cd9660_access,
802 	.vop_advlock =		cd9660_advlock,
803 	.vop_bmap =		cd9660_bmap,
804 	.vop_old_lookup =	cd9660_lookup,
805 	.vop_getattr =		cd9660_getattr,
806 	.vop_inactive =		cd9660_inactive,
807 	.vop_ioctl =		cd9660_ioctl,
808 	.vop_pathconf =		cd9660_pathconf,
809 	.vop_print =		cd9660_print,
810 	.vop_read =		cd9660_read,
811 	.vop_readdir =		cd9660_readdir,
812 	.vop_readlink =		cd9660_readlink,
813 	.vop_reclaim =		cd9660_reclaim,
814 	.vop_setattr =		cd9660_setattr,
815 	.vop_strategy =		cd9660_strategy,
816 	.vop_getpages =		vop_stdgetpages,
817 	.vop_putpages =		vop_stdputpages
818 };
819 
820 /*
821  * Special device vnode ops
822  */
823 struct vop_ops cd9660_spec_vops = {
824 	.vop_default =		vop_defaultop,
825 	.vop_read =		vop_stdnoread,
826 	.vop_access =		cd9660_access,
827 	.vop_getattr =		cd9660_getattr,
828 	.vop_inactive =		cd9660_inactive,
829 	.vop_print =		cd9660_print,
830 	.vop_reclaim =		cd9660_reclaim,
831 	.vop_setattr =		cd9660_setattr,
832 };
833 
834 struct vop_ops cd9660_fifo_vops = {
835 	.vop_default =		fifo_vnoperate,
836 	.vop_access =		cd9660_access,
837 	.vop_getattr =		cd9660_getattr,
838 	.vop_inactive =		cd9660_inactive,
839 	.vop_print =		cd9660_print,
840 	.vop_reclaim =		cd9660_reclaim,
841 	.vop_setattr =		cd9660_setattr,
842 };
843 
844