1 /*	$OpenBSD: cd9660_vnops.c,v 1.32 2004/11/29 17:05:05 grange Exp $	*/
2 /*	$NetBSD: cd9660_vnops.c,v 1.42 1997/10/16 23:56:57 christos Exp $	*/
3 
4 /*-
5  * Copyright (c) 1994
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley
9  * by Pace Willisson (pace@blitz.com).  The Rock Ridge Extension
10  * Support code is derived from software contributed to Berkeley
11  * by Atsushi Murai (amurai@spec.co.jp).
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *	@(#)cd9660_vnops.c	8.15 (Berkeley) 12/5/94
38  */
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/namei.h>
43 #include <sys/resourcevar.h>
44 #include <sys/kernel.h>
45 #include <sys/file.h>
46 #include <sys/stat.h>
47 #include <sys/buf.h>
48 #include <sys/proc.h>
49 #include <sys/conf.h>
50 #include <sys/mount.h>
51 #include <sys/vnode.h>
52 #include <sys/malloc.h>
53 #include <sys/pool.h>
54 #include <sys/dirent.h>
55 #include <sys/ioctl.h>
56 #include <sys/ioccom.h>
57 #include <sys/cdio.h>
58 #include <sys/poll.h>
59 
60 #include <miscfs/fifofs/fifo.h>
61 #include <miscfs/specfs/specdev.h>
62 
63 #include <isofs/cd9660/iso.h>
64 #include <isofs/cd9660/cd9660_extern.h>
65 #include <isofs/cd9660/cd9660_node.h>
66 #include <isofs/cd9660/iso_rrip.h>
67 
68 /*
69  * Structure for reading directories
70  */
71 struct isoreaddir {
72 	struct dirent saveent;
73 	struct dirent assocent;
74 	struct dirent current;
75 	off_t saveoff;
76 	off_t assocoff;
77 	off_t curroff;
78 	struct uio *uio;
79 	off_t uio_off;
80 	int eofflag;
81 	u_long *cookies;
82 	int ncookies;
83 };
84 
85 int	iso_uiodir(struct isoreaddir *, struct dirent *, off_t);
86 int	iso_shipdir(struct isoreaddir *);
87 
88 #if 0
89 /*
90  * Mknod vnode call
91  *  Actually remap the device number
92  */
93 int
94 cd9660_mknod(ndp, vap, cred, p)
95 	struct nameidata *ndp;
96 	struct ucred *cred;
97 	struct vattr *vap;
98 	struct proc *p;
99 {
100 #ifndef	ISODEVMAP
101 	pool_put(&namei_pool, ndp->ni_pnbuf);
102 	vput(ndp->ni_dvp);
103 	vput(ndp->ni_vp);
104 	return (EINVAL);
105 #else
106 	register struct vnode *vp;
107 	struct iso_node *ip;
108 	struct iso_dnode *dp;
109 	int error;
110 
111 	vp = ndp->ni_vp;
112 	ip = VTOI(vp);
113 
114 	if (ip->i_mnt->iso_ftype != ISO_FTYPE_RRIP
115 	    || vap->va_type != vp->v_type
116 	    || (vap->va_type != VCHR && vap->va_type != VBLK)) {
117 		pool_put(&namei_pool, ndp->ni_pnbuf);
118 		vput(ndp->ni_dvp);
119 		vput(ndp->ni_vp);
120 		return (EINVAL);
121 	}
122 
123 	dp = iso_dmap(ip->i_dev,ip->i_number,1);
124 	if (ip->inode.iso_rdev == vap->va_rdev || vap->va_rdev == VNOVAL) {
125 		/* same as the unmapped one, delete the mapping */
126 		remque(dp);
127 		FREE(dp, M_CACHE);
128 	} else
129 		/* enter new mapping */
130 		dp->d_dev = vap->va_rdev;
131 
132 	/*
133 	 * Remove inode so that it will be reloaded by iget and
134 	 * checked to see if it is an alias of an existing entry
135 	 * in the inode cache.
136 	 */
137 	vput(vp);
138 	vp->v_type = VNON;
139 	vgone(vp);
140 	return (0);
141 #endif
142 }
143 #endif
144 
145 /*
146  * Setattr call. Only allowed for block and character special devices.
147  */
148 int
cd9660_setattr(v)149 cd9660_setattr(v)
150 	void *v;
151 {
152 	struct vop_setattr_args /* {
153 		struct vnodeop_desc *a_desc;
154 		struct vnode *a_vp;
155 		struct vattr *a_vap;
156 		struct ucred *a_cred;
157 		struct proc *a_p;
158 	} */ *ap = v;
159 	struct vnode *vp = ap->a_vp;
160 	struct vattr *vap = ap->a_vap;
161 
162 	if (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
163 	    vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
164 	    vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL)
165 		return (EROFS);
166 	if (vap->va_size != VNOVAL) {
167 		switch (vp->v_type) {
168 		case VDIR:
169 			return (EISDIR);
170 		case VLNK:
171 		case VREG:
172 			return (EROFS);
173 		case VCHR:
174 		case VBLK:
175 		case VSOCK:
176 		case VFIFO:
177 			return (0);
178 		default:
179 			return (EINVAL);
180 		}
181 	}
182 
183 	return (EINVAL);
184 }
185 
186 /*
187  * Open called.
188  *
189  * Nothing to do.
190  */
191 /* ARGSUSED */
192 int
cd9660_open(v)193 cd9660_open(v)
194 	void *v;
195 {
196 	return (0);
197 }
198 
199 /*
200  * Close called
201  *
202  * Update the times on the inode on writeable file systems.
203  */
204 /* ARGSUSED */
205 int
cd9660_close(v)206 cd9660_close(v)
207 	void *v;
208 {
209 	return (0);
210 }
211 
212 /*
213  * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
214  * The mode is shifted to select the owner/group/other fields. The
215  * super user is granted all permissions.
216  */
217 int
cd9660_access(v)218 cd9660_access(v)
219 	void *v;
220 {
221 	struct vop_access_args /* {
222 		struct vnode *a_vp;
223 		int  a_mode;
224 		struct ucred *a_cred;
225 		struct proc *a_p;
226 	} */ *ap = v;
227 	struct iso_node *ip = VTOI(ap->a_vp);
228 
229 	return (vaccess(ip->inode.iso_mode & ALLPERMS, ip->inode.iso_uid,
230 	    ip->inode.iso_gid, ap->a_mode, ap->a_cred));
231 }
232 
233 int
cd9660_getattr(v)234 cd9660_getattr(v)
235 	void *v;
236 {
237 	struct vop_getattr_args /* {
238 		struct vnode *a_vp;
239 		struct vattr *a_vap;
240 		struct ucred *a_cred;
241 		struct proc *a_p;
242 	} */ *ap = v;
243 	struct vnode *vp = ap->a_vp;
244 	register struct vattr *vap = ap->a_vap;
245 	register struct iso_node *ip = VTOI(vp);
246 
247 	vap->va_fsid	= ip->i_dev;
248 	vap->va_fileid	= ip->i_number;
249 
250 	vap->va_mode	= ip->inode.iso_mode & ALLPERMS;
251 	vap->va_nlink	= ip->inode.iso_links;
252 	vap->va_uid	= ip->inode.iso_uid;
253 	vap->va_gid	= ip->inode.iso_gid;
254 	vap->va_atime	= ip->inode.iso_atime;
255 	vap->va_mtime	= ip->inode.iso_mtime;
256 	vap->va_ctime	= ip->inode.iso_ctime;
257 	vap->va_rdev	= ip->inode.iso_rdev;
258 
259 	vap->va_size	= (u_quad_t) ip->i_size;
260 	if (ip->i_size == 0 && vp->v_type  == VLNK) {
261 		struct vop_readlink_args rdlnk;
262 		struct iovec aiov;
263 		struct uio auio;
264 		char *cp;
265 
266 		MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
267 		aiov.iov_base = cp;
268 		aiov.iov_len = MAXPATHLEN;
269 		auio.uio_iov = &aiov;
270 		auio.uio_iovcnt = 1;
271 		auio.uio_offset = 0;
272 		auio.uio_rw = UIO_READ;
273 		auio.uio_segflg = UIO_SYSSPACE;
274 		auio.uio_procp = ap->a_p;
275 		auio.uio_resid = MAXPATHLEN;
276 		rdlnk.a_uio = &auio;
277 		rdlnk.a_vp = ap->a_vp;
278 		rdlnk.a_cred = ap->a_cred;
279 		if (cd9660_readlink(&rdlnk) == 0)
280 			vap->va_size = MAXPATHLEN - auio.uio_resid;
281 		FREE(cp, M_TEMP);
282 	}
283 	vap->va_flags	= 0;
284 	vap->va_gen = 1;
285 	vap->va_blocksize = ip->i_mnt->logical_block_size;
286 	vap->va_bytes	= (u_quad_t) ip->i_size;
287 	vap->va_type	= vp->v_type;
288 	return (0);
289 }
290 
291 #ifdef DEBUG
292 extern int doclusterread;
293 #else
294 #define doclusterread 1
295 #endif
296 
297 /* XXX until cluster routines can handle block sizes less than one page */
298 #define cd9660_doclusterread \
299 	(doclusterread && (ISO_DEFAULT_BLOCK_SIZE >= NBPG))
300 
301 /*
302  * Vnode op for reading.
303  */
304 int
cd9660_read(v)305 cd9660_read(v)
306 	void *v;
307 {
308 	struct vop_read_args /* {
309 		struct vnode *a_vp;
310 		struct uio *a_uio;
311 		int a_ioflag;
312 		struct ucred *a_cred;
313 	} */ *ap = v;
314 	struct vnode *vp = ap->a_vp;
315 	register struct uio *uio = ap->a_uio;
316 	register struct iso_node *ip = VTOI(vp);
317 	register struct iso_mnt *imp;
318 	struct buf *bp;
319 	daddr_t lbn, rablock;
320 	off_t diff;
321 	int error = 0;
322 	long size, n, on;
323 
324 	if (uio->uio_resid == 0)
325 		return (0);
326 	if (uio->uio_offset < 0)
327 		return (EINVAL);
328 	ip->i_flag |= IN_ACCESS;
329 	imp = ip->i_mnt;
330 	do {
331 		struct cluster_info *ci = &ip->i_ci;
332 
333 		lbn = lblkno(imp, uio->uio_offset);
334 		on = blkoff(imp, uio->uio_offset);
335 		n = min((u_int)(imp->logical_block_size - on),
336 			uio->uio_resid);
337 		diff = (off_t)ip->i_size - uio->uio_offset;
338 		if (diff <= 0)
339 			return (0);
340 		if (diff < n)
341 			n = diff;
342 		size = blksize(imp, ip, lbn);
343 		rablock = lbn + 1;
344 		if (cd9660_doclusterread) {
345 			if (lblktosize(imp, rablock) <= ip->i_size)
346 				error = cluster_read(vp, &ip->i_ci,
347 				    (off_t)ip->i_size, lbn, size, NOCRED, &bp);
348 			else
349 				error = bread(vp, lbn, size, NOCRED, &bp);
350 		} else {
351 #define MAX_RA 32
352 			if (ci->ci_lastr + 1 == lbn) {
353 				daddr_t rablks[MAX_RA];
354 				int rasizes[MAX_RA];
355 				int i;
356 
357 				for (i = 0; i < MAX_RA &&
358 				    lblktosize(imp, (rablock + i)) < ip->i_size;
359 				    i++) {
360 					rablks[i] = rablock + i;
361 					rasizes[i] = blksize(imp, ip, rablock + i);
362 				}
363 				error = breadn(vp, lbn, size, rablks,
364 				    rasizes, i, NOCRED, &bp);
365 			} else
366 				error = bread(vp, lbn, size, NOCRED, &bp);
367 		}
368 		ci->ci_lastr = lbn;
369 		n = min(n, size - bp->b_resid);
370 		if (error) {
371 			brelse(bp);
372 			return (error);
373 		}
374 
375 		error = uiomove(bp->b_data + on, (int)n, uio);
376 
377                 if (n + on == imp->logical_block_size ||
378 		    uio->uio_offset == (off_t)ip->i_size)
379 			bp->b_flags |= B_AGE;
380 		brelse(bp);
381 	} while (error == 0 && uio->uio_resid > 0 && n != 0);
382 	return (error);
383 }
384 
385 /* ARGSUSED */
386 int
cd9660_ioctl(v)387 cd9660_ioctl(v)
388 	void *v;
389 {
390 	struct vop_ioctl_args /* {
391 		struct vnode *a_vp;
392 		u_long a_command;
393 		caddr_t  a_data;
394 		int  a_fflag;
395 		struct ucred *a_cred;
396 		struct proc *a_p;
397 	} */ *ap = v;
398 	daddr_t *block;
399 
400 	switch (ap->a_command) {
401 	case FIBMAP:
402 		block = (daddr_t *)ap->a_data;
403 
404 		return (VOP_BMAP(ap->a_vp, *block, NULL, block, 0));
405 	default:
406 		return (ENOTTY);
407 	}
408 }
409 
410 /* ARGSUSED */
411 int
cd9660_poll(v)412 cd9660_poll(v)
413 	void *v;
414 {
415 	struct vop_poll_args /* {
416 		struct vnode *a_vp;
417 		int a_events;
418 		struct proc *a_p;
419 	} */ *ap = v;
420 
421 	/*
422 	 * We should really check to see if I/O is possible.
423 	 */
424 	return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
425 }
426 
427 /*
428  * Mmap a file
429  *
430  * NB Currently unsupported.
431  */
432 /* ARGSUSED */
433 int
cd9660_mmap(v)434 cd9660_mmap(v)
435 	void *v;
436 {
437 
438 	return (EINVAL);
439 }
440 
441 /*
442  * Seek on a file
443  *
444  * Nothing to do, so just return.
445  */
446 /* ARGSUSED */
447 int
cd9660_seek(v)448 cd9660_seek(v)
449 	void *v;
450 {
451 	return (0);
452 }
453 
454 int
iso_uiodir(idp,dp,off)455 iso_uiodir(idp,dp,off)
456 	struct isoreaddir *idp;
457 	struct dirent *dp;
458 	off_t off;
459 {
460 	int error;
461 
462 	dp->d_name[dp->d_namlen] = 0;
463 	dp->d_reclen = DIRENT_SIZE(dp);
464 
465 	if (idp->uio->uio_resid < dp->d_reclen) {
466 		idp->eofflag = 0;
467 		return (-1);
468 	}
469 
470 	if (idp->cookies) {
471 		if (idp->ncookies <= 0) {
472 			idp->eofflag = 0;
473 			return (-1);
474 		}
475 
476 		*idp->cookies++ = off;
477 		--idp->ncookies;
478 	}
479 
480 	if ((error = uiomove((caddr_t)dp, dp->d_reclen, idp->uio)) != 0)
481 		return (error);
482 	idp->uio_off = off;
483 	return (0);
484 }
485 
486 int
iso_shipdir(idp)487 iso_shipdir(idp)
488 	struct isoreaddir *idp;
489 {
490 	struct dirent *dp;
491 	int cl, sl, assoc;
492 	int error;
493 	char *cname, *sname;
494 
495 	cl = idp->current.d_namlen;
496 	cname = idp->current.d_name;
497 
498 	if ((assoc = cl > 1 && *cname == ASSOCCHAR)) {
499 		cl--;
500 		cname++;
501 	}
502 
503 	dp = &idp->saveent;
504 	sname = dp->d_name;
505 	if (!(sl = dp->d_namlen)) {
506 		dp = &idp->assocent;
507 		sname = dp->d_name + 1;
508 		sl = dp->d_namlen - 1;
509 	}
510 	if (sl > 0) {
511 		if (sl != cl
512 		    || bcmp(sname,cname,sl)) {
513 			if (idp->assocent.d_namlen) {
514 				error = iso_uiodir(idp, &idp->assocent,
515 						   idp->assocoff);
516 				if (error)
517 					return (error);
518 				idp->assocent.d_namlen = 0;
519 			}
520 			if (idp->saveent.d_namlen) {
521 				error = iso_uiodir(idp, &idp->saveent,
522 						   idp->saveoff);
523 				if (error)
524 					return (error);
525 				idp->saveent.d_namlen = 0;
526 			}
527 		}
528 	}
529 	idp->current.d_reclen = DIRENT_SIZE(&idp->current);
530 	if (assoc) {
531 		idp->assocoff = idp->curroff;
532 		bcopy(&idp->current,&idp->assocent,idp->current.d_reclen);
533 	} else {
534 		idp->saveoff = idp->curroff;
535 		bcopy(&idp->current,&idp->saveent,idp->current.d_reclen);
536 	}
537 	return (0);
538 }
539 
540 /*
541  * Vnode op for readdir
542  */
543 int
cd9660_readdir(v)544 cd9660_readdir(v)
545 	void *v;
546 {
547 	struct vop_readdir_args /* {
548 		struct vnode *a_vp;
549 		struct uio *a_uio;
550 		struct ucred *a_cred;
551 		int *a_eofflag;
552 		u_long *a_cookies;
553 		int a_ncookies;
554 	} */ *ap = v;
555 	register struct uio *uio = ap->a_uio;
556 	struct isoreaddir *idp;
557 	struct vnode *vdp = ap->a_vp;
558 	struct iso_node *dp;
559 	struct iso_mnt *imp;
560 	struct buf *bp = NULL;
561 	struct iso_directory_record *ep;
562 	int entryoffsetinblock;
563 	doff_t endsearch;
564 	u_long bmask;
565 	int error = 0;
566 	int reclen;
567 	u_short namelen;
568 	int  ncookies = 0;
569 	u_long *cookies = NULL;
570 
571 	dp = VTOI(vdp);
572 	imp = dp->i_mnt;
573 	bmask = imp->im_bmask;
574 
575 	MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK);
576 	idp->saveent.d_namlen = idp->assocent.d_namlen = 0;
577 	/*
578 	 * XXX
579 	 * Is it worth trying to figure out the type?
580 	 */
581 	idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type =
582 	    DT_UNKNOWN;
583 	idp->uio = uio;
584 	if (ap->a_ncookies == NULL) {
585 		idp->cookies = NULL;
586 	} else {
587                /*
588                 * Guess the number of cookies needed.
589                 */
590                ncookies = uio->uio_resid / 16;
591                MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP,
592                    M_WAITOK);
593                idp->cookies = cookies;
594                idp->ncookies = ncookies;
595 	}
596 	idp->eofflag = 1;
597 	idp->curroff = uio->uio_offset;
598 	idp->uio_off = uio->uio_offset;
599 
600 	if ((entryoffsetinblock = idp->curroff & bmask) &&
601 	    (error = cd9660_bufatoff(dp, (off_t)idp->curroff, NULL, &bp))) {
602 		FREE(idp, M_TEMP);
603 		return (error);
604 	}
605 	endsearch = dp->i_size;
606 
607 	while (idp->curroff < endsearch) {
608 		/*
609 		 * If offset is on a block boundary,
610 		 * read the next directory block.
611 		 * Release previous if it exists.
612 		 */
613 		if ((idp->curroff & bmask) == 0) {
614 			if (bp != NULL)
615 				brelse(bp);
616 			error = cd9660_bufatoff(dp, (off_t)idp->curroff,
617 					     NULL, &bp);
618 			if (error)
619 				break;
620 			entryoffsetinblock = 0;
621 		}
622 		/*
623 		 * Get pointer to next entry.
624 		 */
625 		ep = (struct iso_directory_record *)
626 			((char *)bp->b_data + entryoffsetinblock);
627 
628 		reclen = isonum_711(ep->length);
629 		if (reclen == 0) {
630 			/* skip to next block, if any */
631 			idp->curroff =
632 			    (idp->curroff & ~bmask) + imp->logical_block_size;
633 			continue;
634 		}
635 
636 		if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
637 			error = EINVAL;
638 			/* illegal entry, stop */
639 			break;
640 		}
641 
642 		if (entryoffsetinblock + reclen > imp->logical_block_size) {
643 			error = EINVAL;
644 			/* illegal directory, so stop looking */
645 			break;
646 		}
647 
648 		idp->current.d_namlen = isonum_711(ep->name_len);
649 
650 		if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
651 			error = EINVAL;
652 			/* illegal entry, stop */
653 			break;
654 		}
655 
656 		if (isonum_711(ep->flags)&2)
657 			idp->current.d_fileno = isodirino(ep, imp);
658 		else
659 			idp->current.d_fileno = dbtob(bp->b_blkno) +
660 				entryoffsetinblock;
661 
662 		idp->curroff += reclen;
663 
664 		switch (imp->iso_ftype) {
665 		case ISO_FTYPE_RRIP:
666 			cd9660_rrip_getname(ep,idp->current.d_name, &namelen,
667 					   &idp->current.d_fileno,imp);
668 			idp->current.d_namlen = (u_char)namelen;
669 			if (idp->current.d_namlen)
670 				error = iso_uiodir(idp,&idp->current,idp->curroff);
671 			break;
672 		default:	/* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */
673 			strlcpy(idp->current.d_name,"..",
674 			    sizeof idp->current.d_name);
675 			if (idp->current.d_namlen == 1 && ep->name[0] == 0) {
676 				idp->current.d_namlen = 1;
677 				error = iso_uiodir(idp,&idp->current,idp->curroff);
678 			} else if (idp->current.d_namlen == 1 &&
679 			    ep->name[0] == 1) {
680 				idp->current.d_namlen = 2;
681 				error = iso_uiodir(idp,&idp->current,idp->curroff);
682 			} else {
683 				isofntrans(ep->name,idp->current.d_namlen,
684 					   idp->current.d_name, &namelen,
685 					   imp->iso_ftype == ISO_FTYPE_9660,
686 					   isonum_711(ep->flags) & 4,
687 					   imp->joliet_level);
688 				idp->current.d_namlen = (u_char)namelen;
689 				if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
690 					error = iso_shipdir(idp);
691 				else
692 					error = iso_uiodir(idp,&idp->current,idp->curroff);
693 			}
694 		}
695 		if (error)
696 			break;
697 
698 		entryoffsetinblock += reclen;
699 	}
700 
701 	if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
702 		idp->current.d_namlen = 0;
703 		error = iso_shipdir(idp);
704 	}
705 	if (error < 0)
706 		error = 0;
707 
708 	if (ap->a_ncookies != NULL) {
709 		if (error)
710 			free(cookies, M_TEMP);
711 		else {
712 			/*
713 			 * Work out the number of cookies actually used.
714 			 */
715 			*ap->a_ncookies = ncookies - idp->ncookies;
716 			*ap->a_cookies = cookies;
717 		}
718 	}
719 
720 	if (bp)
721 		brelse (bp);
722 
723 	uio->uio_offset = idp->uio_off;
724 	*ap->a_eofflag = idp->eofflag;
725 
726 	FREE(idp, M_TEMP);
727 
728 	return (error);
729 }
730 
731 /*
732  * Return target name of a symbolic link
733  * Shouldn't we get the parent vnode and read the data from there?
734  * This could eventually result in deadlocks in cd9660_lookup.
735  * But otherwise the block read here is in the block buffer two times.
736  */
737 typedef struct iso_directory_record ISODIR;
738 typedef struct iso_node             ISONODE;
739 typedef struct iso_mnt              ISOMNT;
740 int
cd9660_readlink(v)741 cd9660_readlink(v)
742 	void *v;
743 {
744 	struct vop_readlink_args /* {
745 		struct vnode *a_vp;
746 		struct uio *a_uio;
747 		struct ucred *a_cred;
748 	} */ *ap = v;
749 	ISONODE	*ip;
750 	ISODIR	*dirp;
751 	ISOMNT	*imp;
752 	struct	buf *bp;
753 	struct	uio *uio;
754 	u_short	symlen;
755 	int	error;
756 	char	*symname;
757 
758 	ip  = VTOI(ap->a_vp);
759 	imp = ip->i_mnt;
760 	uio = ap->a_uio;
761 
762 	if (imp->iso_ftype != ISO_FTYPE_RRIP)
763 		return (EINVAL);
764 
765 	/*
766 	 * Get parents directory record block that this inode included.
767 	 */
768 	error = bread(imp->im_devvp,
769 		      (ip->i_number >> imp->im_bshift) <<
770 		      (imp->im_bshift - DEV_BSHIFT),
771 		      imp->logical_block_size, NOCRED, &bp);
772 	if (error) {
773 		brelse(bp);
774 		return (EINVAL);
775 	}
776 
777 	/*
778 	 * Setup the directory pointer for this inode
779 	 */
780 	dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
781 
782 	/*
783 	 * Just make sure, we have a right one....
784 	 *   1: Check not cross boundary on block
785 	 */
786 	if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
787 	    > imp->logical_block_size) {
788 		brelse(bp);
789 		return (EINVAL);
790 	}
791 
792 	/*
793 	 * Now get a buffer
794 	 * Abuse a namei buffer for now.
795 	 */
796 	if (uio->uio_segflg == UIO_SYSSPACE &&
797 	    uio->uio_iov->iov_len >= MAXPATHLEN)
798 		symname = uio->uio_iov->iov_base;
799 	else
800 		symname = pool_get(&namei_pool, PR_WAITOK);
801 
802 	/*
803 	 * Ok, we just gathering a symbolic name in SL record.
804 	 */
805 	if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
806 		if (uio->uio_segflg != UIO_SYSSPACE ||
807 		    uio->uio_iov->iov_len < MAXPATHLEN)
808 			pool_put(&namei_pool, symname);
809 		brelse(bp);
810 		return (EINVAL);
811 	}
812 	/*
813 	 * Don't forget before you leave from home ;-)
814 	 */
815 	brelse(bp);
816 
817 	/*
818 	 * return with the symbolic name to caller's.
819 	 */
820 	if (uio->uio_segflg != UIO_SYSSPACE ||
821 	    uio->uio_iov->iov_len < MAXPATHLEN) {
822 		error = uiomove(symname, symlen, uio);
823 		pool_put(&namei_pool, symname);
824 		return (error);
825 	}
826 	uio->uio_resid -= symlen;
827 	uio->uio_iov->iov_base += symlen;
828 	uio->uio_iov->iov_len -= symlen;
829 	return (0);
830 }
831 
832 int
cd9660_link(v)833 cd9660_link(v)
834 	void *v;
835 {
836 	struct vop_link_args /* {
837 		struct vnode *a_dvp;
838 		struct vnode *a_vp;
839 		struct componentname *a_cnp;
840 	} */ *ap = v;
841 
842 	VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
843 	vput(ap->a_dvp);
844 	return (EROFS);
845 }
846 
847 int
cd9660_symlink(v)848 cd9660_symlink(v)
849 	void *v;
850 {
851 	struct vop_symlink_args /* {
852 		struct vnode *a_dvp;
853 		struct vnode **a_vpp;
854 		struct componentname *a_cnp;
855 		struct vattr *a_vap;
856 		char *a_target;
857 	} */ *ap = v;
858 
859 	VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
860 	vput(ap->a_dvp);
861 	return (EROFS);
862 }
863 
864 /*
865  * Lock an inode.
866  */
867 int
cd9660_lock(v)868 cd9660_lock(v)
869 	void *v;
870 {
871 	struct vop_lock_args /* {
872 		struct vnode *a_vp;
873 	} */ *ap = v;
874 	struct vnode *vp = ap->a_vp;
875 
876 	return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, &vp->v_interlock,
877 			ap->a_p));
878 }
879 
880 /*
881  * Unlock an inode.
882  */
883 int
cd9660_unlock(v)884 cd9660_unlock(v)
885 	void *v;
886 {
887 	struct vop_unlock_args /* {
888 		struct vnode *a_vp;
889 	} */ *ap = v;
890 	struct vnode *vp = ap->a_vp;
891 
892 	return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE,
893 			&vp->v_interlock, ap->a_p));
894 }
895 
896 /*
897  * Calculate the logical to physical mapping if not done already,
898  * then call the device strategy routine.
899  */
900 int
cd9660_strategy(v)901 cd9660_strategy(v)
902 	void *v;
903 {
904 	struct vop_strategy_args /* {
905 		struct buf *a_bp;
906 	} */ *ap = v;
907 	struct buf *bp = ap->a_bp;
908 	struct vnode *vp = bp->b_vp;
909 	struct iso_node *ip;
910 	int error;
911 	int s;
912 
913 	ip = VTOI(vp);
914 	if (vp->v_type == VBLK || vp->v_type == VCHR)
915 		panic("cd9660_strategy: spec");
916 	if (bp->b_blkno == bp->b_lblkno) {
917 		error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL);
918 		if (error) {
919 			bp->b_error = error;
920 			bp->b_flags |= B_ERROR;
921 			s = splbio();
922 			biodone(bp);
923 			splx(s);
924 			return (error);
925 		}
926 		if ((long)bp->b_blkno == -1)
927 			clrbuf(bp);
928 	}
929 	if ((long)bp->b_blkno == -1) {
930 		s = splbio();
931 		biodone(bp);
932 		splx(s);
933 		return (0);
934 	}
935 	vp = ip->i_devvp;
936 	bp->b_dev = vp->v_rdev;
937 	VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
938 	return (0);
939 }
940 
941 /*
942  * Print out the contents of an inode.
943  */
944 /*ARGSUSED*/
945 int
cd9660_print(v)946 cd9660_print(v)
947 	void *v;
948 {
949 	printf("tag VT_ISOFS, isofs vnode\n");
950 	return (0);
951 }
952 
953 /*
954  * Check for a locked inode.
955  */
956 int
cd9660_islocked(v)957 cd9660_islocked(v)
958 	void *v;
959 {
960 	struct vop_islocked_args /* {
961 		struct vnode *a_vp;
962 	} */ *ap = v;
963 
964 	return (lockstatus(&VTOI(ap->a_vp)->i_lock));
965 }
966 
967 /*
968  * Return POSIX pathconf information applicable to cd9660 filesystems.
969  */
970 int
cd9660_pathconf(v)971 cd9660_pathconf(v)
972 	void *v;
973 {
974 	struct vop_pathconf_args /* {
975 		struct vnode *a_vp;
976 		int a_name;
977 		register_t *a_retval;
978 	} */ *ap = v;
979 	switch (ap->a_name) {
980 	case _PC_LINK_MAX:
981 		*ap->a_retval = 1;
982 		return (0);
983 	case _PC_NAME_MAX:
984 		if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP)
985 			*ap->a_retval = NAME_MAX;
986 		else
987 			*ap->a_retval = 37;
988 		return (0);
989 	case _PC_PATH_MAX:
990 		*ap->a_retval = PATH_MAX;
991 		return (0);
992 	case _PC_PIPE_BUF:
993 		*ap->a_retval = PIPE_BUF;
994 		return (0);
995 	case _PC_CHOWN_RESTRICTED:
996 		*ap->a_retval = 1;
997 		return (0);
998 	case _PC_NO_TRUNC:
999 		*ap->a_retval = 1;
1000 		return (0);
1001 	default:
1002 		return (EINVAL);
1003 	}
1004 	/* NOTREACHED */
1005 }
1006 
1007 /*
1008  * Global vfs data structures for isofs
1009  */
1010 #define	cd9660_create	eopnotsupp
1011 #define	cd9660_mknod	eopnotsupp
1012 #define	cd9660_write	eopnotsupp
1013 #ifdef	NFSSERVER
1014 int	lease_check(void *);
1015 #define	cd9660_lease_check	lease_check
1016 #else
1017 #define	cd9660_lease_check	nullop
1018 #endif
1019 #define	cd9660_fsync	nullop
1020 #define	cd9660_remove	eopnotsupp
1021 #define	cd9660_rename	eopnotsupp
1022 #define	cd9660_mkdir	eopnotsupp
1023 #define	cd9660_rmdir	eopnotsupp
1024 #define	cd9660_advlock	eopnotsupp
1025 #define	cd9660_valloc	eopnotsupp
1026 #define	cd9660_vfree	eopnotsupp
1027 #define	cd9660_truncate	eopnotsupp
1028 #define	cd9660_update	eopnotsupp
1029 #define	cd9660_bwrite	eopnotsupp
1030 #define cd9660_revoke   vop_generic_revoke
1031 
1032 /*
1033  * Global vfs data structures for cd9660
1034  */
1035 int (**cd9660_vnodeop_p)(void *);
1036 struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
1037 	{ &vop_default_desc, vn_default_error },
1038 	{ &vop_lookup_desc, cd9660_lookup },	/* lookup */
1039 	{ &vop_create_desc, cd9660_create },	/* create */
1040 	{ &vop_mknod_desc, cd9660_mknod },	/* mknod */
1041 	{ &vop_open_desc, cd9660_open },	/* open */
1042 	{ &vop_close_desc, cd9660_close },	/* close */
1043 	{ &vop_access_desc, cd9660_access },	/* access */
1044 	{ &vop_getattr_desc, cd9660_getattr },	/* getattr */
1045 	{ &vop_setattr_desc, cd9660_setattr },	/* setattr */
1046 	{ &vop_read_desc, cd9660_read },	/* read */
1047 	{ &vop_write_desc, cd9660_write },	/* write */
1048 	{ &vop_lease_desc, cd9660_lease_check },/* lease */
1049 	{ &vop_ioctl_desc, cd9660_ioctl },	/* ioctl */
1050 	{ &vop_poll_desc, cd9660_poll },	/* poll */
1051 	{ &vop_revoke_desc, cd9660_revoke },    /* revoke */
1052 	{ &vop_fsync_desc, cd9660_fsync },	/* fsync */
1053 	{ &vop_remove_desc, cd9660_remove },	/* remove */
1054 	{ &vop_link_desc, cd9660_link },	/* link */
1055 	{ &vop_rename_desc, cd9660_rename },	/* rename */
1056 	{ &vop_mkdir_desc, cd9660_mkdir },	/* mkdir */
1057 	{ &vop_rmdir_desc, cd9660_rmdir },	/* rmdir */
1058 	{ &vop_symlink_desc, cd9660_symlink },	/* symlink */
1059 	{ &vop_readdir_desc, cd9660_readdir },	/* readdir */
1060 	{ &vop_readlink_desc, cd9660_readlink },/* readlink */
1061 	{ &vop_abortop_desc, vop_generic_abortop },	/* abortop */
1062 	{ &vop_inactive_desc, cd9660_inactive },/* inactive */
1063 	{ &vop_reclaim_desc, cd9660_reclaim },	/* reclaim */
1064 	{ &vop_lock_desc, cd9660_lock },	/* lock */
1065 	{ &vop_unlock_desc, cd9660_unlock },	/* unlock */
1066 	{ &vop_bmap_desc, cd9660_bmap },	/* bmap */
1067 	{ &vop_strategy_desc, cd9660_strategy },/* strategy */
1068 	{ &vop_print_desc, cd9660_print },	/* print */
1069 	{ &vop_islocked_desc, cd9660_islocked },/* islocked */
1070 	{ &vop_pathconf_desc, cd9660_pathconf },/* pathconf */
1071 	{ &vop_advlock_desc, cd9660_advlock },	/* advlock */
1072 	{ &vop_bwrite_desc, vop_generic_bwrite },
1073 	{ NULL, NULL }
1074 };
1075 struct vnodeopv_desc cd9660_vnodeop_opv_desc =
1076 	{ &cd9660_vnodeop_p, cd9660_vnodeop_entries };
1077 
1078 /*
1079  * Special device vnode ops
1080  */
1081 int (**cd9660_specop_p)(void *);
1082 struct vnodeopv_entry_desc cd9660_specop_entries[] = {
1083 	{ &vop_default_desc, spec_vnoperate },
1084 	{ &vop_access_desc, cd9660_access },	/* access */
1085 	{ &vop_getattr_desc, cd9660_getattr },	/* getattr */
1086 	{ &vop_setattr_desc, cd9660_setattr },	/* setattr */
1087 	{ &vop_inactive_desc, cd9660_inactive },/* inactive */
1088 	{ &vop_reclaim_desc, cd9660_reclaim },	/* reclaim */
1089 	{ &vop_lock_desc, cd9660_lock },	/* lock */
1090 	{ &vop_unlock_desc, cd9660_unlock },	/* unlock */
1091 	{ &vop_print_desc, cd9660_print },	/* print */
1092 	{ &vop_islocked_desc, cd9660_islocked },/* islocked */
1093 	{ NULL, NULL }
1094 };
1095 struct vnodeopv_desc cd9660_specop_opv_desc =
1096 	{ &cd9660_specop_p, cd9660_specop_entries };
1097 
1098 #ifdef FIFO
1099 int (**cd9660_fifoop_p)(void *);
1100 struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
1101 	{ &vop_default_desc, fifo_vnoperate },
1102 	{ &vop_access_desc, cd9660_access },	/* access */
1103 	{ &vop_getattr_desc, cd9660_getattr },	/* getattr */
1104 	{ &vop_setattr_desc, cd9660_setattr },	/* setattr */
1105 	{ &vop_inactive_desc, cd9660_inactive },/* inactive */
1106 	{ &vop_reclaim_desc, cd9660_reclaim },	/* reclaim */
1107 	{ &vop_lock_desc, cd9660_lock },	/* lock */
1108 	{ &vop_unlock_desc, cd9660_unlock },	/* unlock */
1109 	{ &vop_print_desc, cd9660_print },	/* print */
1110 	{ &vop_islocked_desc, cd9660_islocked },/* islocked */
1111 	{ &vop_bwrite_desc, vop_generic_bwrite },
1112 	{ NULL, NULL }
1113 };
1114 struct vnodeopv_desc cd9660_fifoop_opv_desc =
1115 	{ &cd9660_fifoop_p, cd9660_fifoop_entries };
1116 #endif /* FIFO */
1117