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