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  * %sccs.include.redist.c%
11  *
12  *	@(#)cd9660_vnops.c	8.19 (Berkeley) 05/27/95
13  */
14 
15 #include <sys/param.h>
16 #include <sys/systm.h>
17 #include <sys/namei.h>
18 #include <sys/resourcevar.h>
19 #include <sys/kernel.h>
20 #include <sys/file.h>
21 #include <sys/stat.h>
22 #include <sys/buf.h>
23 #include <sys/proc.h>
24 #include <sys/conf.h>
25 #include <sys/mount.h>
26 #include <sys/vnode.h>
27 #include <miscfs/specfs/specdev.h>
28 #include <miscfs/fifofs/fifo.h>
29 #include <sys/malloc.h>
30 #include <sys/dir.h>
31 
32 #include <isofs/cd9660/iso.h>
33 #include <isofs/cd9660/cd9660_node.h>
34 #include <isofs/cd9660/iso_rrip.h>
35 
36 #if 0
37 /*
38  * Mknod vnode call
39  *  Actually remap the device number
40  */
41 cd9660_mknod(ndp, vap, cred, p)
42 	struct nameidata *ndp;
43 	struct ucred *cred;
44 	struct vattr *vap;
45 	struct proc *p;
46 {
47 #ifndef	ISODEVMAP
48 	free(ndp->ni_pnbuf, M_NAMEI);
49 	vput(ndp->ni_dvp);
50 	vput(ndp->ni_vp);
51 	return (EINVAL);
52 #else
53 	register struct vnode *vp;
54 	struct iso_node *ip;
55 	struct iso_dnode *dp;
56 	int error;
57 
58 	vp = ndp->ni_vp;
59 	ip = VTOI(vp);
60 
61 	if (ip->i_mnt->iso_ftype != ISO_FTYPE_RRIP
62 	    || vap->va_type != vp->v_type
63 	    || (vap->va_type != VCHR && vap->va_type != VBLK)) {
64 		free(ndp->ni_pnbuf, M_NAMEI);
65 		vput(ndp->ni_dvp);
66 		vput(ndp->ni_vp);
67 		return (EINVAL);
68 	}
69 
70 	dp = iso_dmap(ip->i_dev,ip->i_number,1);
71 	if (ip->inode.iso_rdev == vap->va_rdev || vap->va_rdev == VNOVAL) {
72 		/* same as the unmapped one, delete the mapping */
73 		remque(dp);
74 		FREE(dp,M_CACHE);
75 	} else
76 		/* enter new mapping */
77 		dp->d_dev = vap->va_rdev;
78 
79 	/*
80 	 * Remove inode so that it will be reloaded by iget and
81 	 * checked to see if it is an alias of an existing entry
82 	 * in the inode cache.
83 	 */
84 	vput(vp);
85 	vp->v_type = VNON;
86 	vgone(vp);
87 	return (0);
88 #endif
89 }
90 #endif
91 
92 /*
93  * Setattr call. Only allowed for block and character special devices.
94  */
95 int
cd9660_setattr(ap)96 cd9660_setattr(ap)
97 	struct vop_setattr_args /* {
98 		struct vnodeop_desc *a_desc;
99 		struct vnode *a_vp;
100 		struct vattr *a_vap;
101 		struct ucred *a_cred;
102 		struct proc *a_p;
103 	} */ *ap;
104 {
105 	struct vnode *vp = ap->a_vp;
106 	struct vattr *vap = ap->a_vap;
107 
108   	if (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
109 	    vap->va_gid != (gid_t)VNOVAL || vap->va_atime.ts_sec != VNOVAL ||
110 	    vap->va_mtime.ts_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL)
111 		return (EROFS);
112 	if (vap->va_size != VNOVAL) {
113  		switch (vp->v_type) {
114  		case VDIR:
115  			return (EISDIR);
116 		case VLNK:
117 		case VREG:
118 			return (EROFS);
119  		case VCHR:
120  		case VBLK:
121  		case VSOCK:
122  		case VFIFO:
123 			return (0);
124 		}
125 	}
126 }
127 
128 /*
129  * Open called.
130  *
131  * Nothing to do.
132  */
133 /* ARGSUSED */
134 int
cd9660_open(ap)135 cd9660_open(ap)
136 	struct vop_open_args /* {
137 		struct vnode *a_vp;
138 		int  a_mode;
139 		struct ucred *a_cred;
140 		struct proc *a_p;
141 	} */ *ap;
142 {
143 	return (0);
144 }
145 
146 /*
147  * Close called
148  *
149  * Update the times on the inode on writeable file systems.
150  */
151 /* ARGSUSED */
152 int
cd9660_close(ap)153 cd9660_close(ap)
154 	struct vop_close_args /* {
155 		struct vnode *a_vp;
156 		int  a_fflag;
157 		struct ucred *a_cred;
158 		struct proc *a_p;
159 	} */ *ap;
160 {
161 	return (0);
162 }
163 
164 /*
165  * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
166  * The mode is shifted to select the owner/group/other fields. The
167  * super user is granted all permissions.
168  */
169 /* ARGSUSED */
170 cd9660_access(ap)
171 	struct vop_access_args /* {
172 		struct vnode *a_vp;
173 		int  a_mode;
174 		struct ucred *a_cred;
175 		struct proc *a_p;
176 	} */ *ap;
177 {
178 	struct vnode *vp = ap->a_vp;
179 	struct iso_node *ip = VTOI(vp);
180 	struct ucred *cred = ap->a_cred;
181 	mode_t mask, mode = ap->a_mode;
182 	gid_t *gp;
183 	int i;
184 
185 	/*
186 	 * Disallow write attempts unless the file is a socket,
187 	 * fifo, or a block or character device resident on the
188 	 * file system.
189 	 */
190 	if (mode & VWRITE) {
191 		switch (vp->v_type) {
192 		case VDIR:
193 		case VLNK:
194 		case VREG:
195 			return (EROFS);
196 		}
197 	}
198 
199 	/* User id 0 always gets access. */
200 	if (cred->cr_uid == 0)
201 		return (0);
202 
203 	mask = 0;
204 
205 	/* Otherwise, check the owner. */
206 	if (cred->cr_uid == ip->inode.iso_uid) {
207 		if (mode & VEXEC)
208 			mask |= S_IXUSR;
209 		if (mode & VREAD)
210 			mask |= S_IRUSR;
211 		if (mode & VWRITE)
212 			mask |= S_IWUSR;
213 		return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
214 	}
215 
216 	/* Otherwise, check the groups. */
217 	for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
218 		if (ip->inode.iso_gid == *gp) {
219 			if (mode & VEXEC)
220 				mask |= S_IXGRP;
221 			if (mode & VREAD)
222 				mask |= S_IRGRP;
223 			if (mode & VWRITE)
224 				mask |= S_IWGRP;
225 			return ((ip->inode.iso_mode & mask) == mask ?
226 			    0 : EACCES);
227 		}
228 
229 	/* Otherwise, check everyone else. */
230 	if (mode & VEXEC)
231 		mask |= S_IXOTH;
232 	if (mode & VREAD)
233 		mask |= S_IROTH;
234 	if (mode & VWRITE)
235 		mask |= S_IWOTH;
236 	return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
237 }
238 
239 cd9660_getattr(ap)
240 	struct vop_getattr_args /* {
241 		struct vnode *a_vp;
242 		struct vattr *a_vap;
243 		struct ucred *a_cred;
244 		struct proc *a_p;
245 	} */ *ap;
246 
247 {
248 	struct vnode *vp = ap->a_vp;
249 	register struct vattr *vap = ap->a_vap;
250 	register struct iso_node *ip = VTOI(vp);
251 	int i;
252 
253 	vap->va_fsid	= ip->i_dev;
254 	vap->va_fileid	= ip->i_number;
255 
256 	vap->va_mode	= ip->inode.iso_mode;
257 	vap->va_nlink	= ip->inode.iso_links;
258 	vap->va_uid	= ip->inode.iso_uid;
259 	vap->va_gid	= ip->inode.iso_gid;
260 	vap->va_atime	= ip->inode.iso_atime;
261 	vap->va_mtime	= ip->inode.iso_mtime;
262 	vap->va_ctime	= ip->inode.iso_ctime;
263 	vap->va_rdev	= ip->inode.iso_rdev;
264 
265 	vap->va_size	= (u_quad_t) ip->i_size;
266 	if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) {
267 		struct vop_readlink_args rdlnk;
268 		struct iovec aiov;
269 		struct uio auio;
270 		char *cp;
271 
272 		MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
273 		aiov.iov_base = cp;
274 		aiov.iov_len = MAXPATHLEN;
275 		auio.uio_iov = &aiov;
276 		auio.uio_iovcnt = 1;
277 		auio.uio_offset = 0;
278 		auio.uio_rw = UIO_READ;
279 		auio.uio_segflg = UIO_SYSSPACE;
280 		auio.uio_procp = ap->a_p;
281 		auio.uio_resid = MAXPATHLEN;
282 		rdlnk.a_uio = &auio;
283 		rdlnk.a_vp = ap->a_vp;
284 		rdlnk.a_cred = ap->a_cred;
285 		if (cd9660_readlink(&rdlnk) == 0)
286 			vap->va_size = MAXPATHLEN - auio.uio_resid;
287 		FREE(cp, M_TEMP);
288 	}
289 	vap->va_flags	= 0;
290 	vap->va_gen = 1;
291 	vap->va_blocksize = ip->i_mnt->logical_block_size;
292 	vap->va_bytes	= (u_quad_t) ip->i_size;
293 	vap->va_type	= vp->v_type;
294 	return (0);
295 }
296 
297 #if ISO_DEFAULT_BLOCK_SIZE >= NBPG
298 #ifdef DEBUG
299 extern int doclusterread;
300 #else
301 #define doclusterread 1
302 #endif
303 #else
304 /* XXX until cluster routines can handle block sizes less than one page */
305 #define doclusterread 0
306 #endif
307 
308 /*
309  * Vnode op for reading.
310  */
311 cd9660_read(ap)
312 	struct vop_read_args /* {
313 		struct vnode *a_vp;
314 		struct uio *a_uio;
315 		int a_ioflag;
316 		struct ucred *a_cred;
317 	} */ *ap;
318 {
319 	struct vnode *vp = ap->a_vp;
320 	register struct uio *uio = ap->a_uio;
321 	register struct iso_node *ip = VTOI(vp);
322 	register struct iso_mnt *imp;
323 	struct buf *bp;
324 	daddr_t lbn, bn, rablock;
325 	off_t diff;
326 	int rasize, error = 0;
327 	long size, n, on;
328 
329 	if (uio->uio_resid == 0)
330 		return (0);
331 	if (uio->uio_offset < 0)
332 		return (EINVAL);
333 	ip->i_flag |= IN_ACCESS;
334 	imp = ip->i_mnt;
335 	do {
336 		lbn = lblkno(imp, uio->uio_offset);
337 		on = blkoff(imp, uio->uio_offset);
338 		n = min((u_int)(imp->logical_block_size - on),
339 			uio->uio_resid);
340 		diff = (off_t)ip->i_size - uio->uio_offset;
341 		if (diff <= 0)
342 			return (0);
343 		if (diff < n)
344 			n = diff;
345 		size = blksize(imp, ip, lbn);
346 		rablock = lbn + 1;
347 		if (doclusterread) {
348 			if (lblktosize(imp, rablock) <= ip->i_size)
349 				error = cluster_read(vp, (off_t)ip->i_size,
350 						     lbn, size, NOCRED, &bp);
351 			else
352 				error = bread(vp, lbn, size, NOCRED, &bp);
353 		} else {
354 			if (vp->v_lastr + 1 == lbn &&
355 			    lblktosize(imp, rablock) < ip->i_size) {
356 				rasize = blksize(imp, ip, rablock);
357 				error = breadn(vp, lbn, size, &rablock,
358 					       &rasize, 1, NOCRED, &bp);
359 			} else
360 				error = bread(vp, lbn, size, NOCRED, &bp);
361 		}
362 		vp->v_lastr = lbn;
363 		n = min(n, size - bp->b_resid);
364 		if (error) {
365 			brelse(bp);
366 			return (error);
367 		}
368 
369 		error = uiomove(bp->b_data + on, (int)n, uio);
370 		if (n + on == imp->logical_block_size ||
371 		    uio->uio_offset == (off_t)ip->i_size)
372 			bp->b_flags |= B_AGE;
373 		brelse(bp);
374 	} while (error == 0 && uio->uio_resid > 0 && n != 0);
375 	return (error);
376 }
377 
378 /* ARGSUSED */
379 int
cd9660_ioctl(ap)380 cd9660_ioctl(ap)
381 	struct vop_ioctl_args /* {
382 		struct vnode *a_vp;
383 		u_long a_command;
384 		caddr_t  a_data;
385 		int  a_fflag;
386 		struct ucred *a_cred;
387 		struct proc *a_p;
388 	} */ *ap;
389 {
390 	printf("You did ioctl for isofs !!\n");
391 	return (ENOTTY);
392 }
393 
394 /* ARGSUSED */
395 int
cd9660_select(ap)396 cd9660_select(ap)
397 	struct vop_select_args /* {
398 		struct vnode *a_vp;
399 		int  a_which;
400 		int  a_fflags;
401 		struct ucred *a_cred;
402 		struct proc *a_p;
403 	} */ *ap;
404 {
405 
406 	/*
407 	 * We should really check to see if I/O is possible.
408 	 */
409 	return (1);
410 }
411 
412 /*
413  * Mmap a file
414  *
415  * NB Currently unsupported.
416  */
417 /* ARGSUSED */
418 int
cd9660_mmap(ap)419 cd9660_mmap(ap)
420 	struct vop_mmap_args /* {
421 		struct vnode *a_vp;
422 		int  a_fflags;
423 		struct ucred *a_cred;
424 		struct proc *a_p;
425 	} */ *ap;
426 {
427 
428 	return (EINVAL);
429 }
430 
431 /*
432  * Seek on a file
433  *
434  * Nothing to do, so just return.
435  */
436 /* ARGSUSED */
437 int
cd9660_seek(ap)438 cd9660_seek(ap)
439 	struct vop_seek_args /* {
440 		struct vnode *a_vp;
441 		off_t  a_oldoff;
442 		off_t  a_newoff;
443 		struct ucred *a_cred;
444 	} */ *ap;
445 {
446 
447 	return (0);
448 }
449 
450 /*
451  * Structure for reading directories
452  */
453 struct isoreaddir {
454 	struct dirent saveent;
455 	struct dirent assocent;
456 	struct dirent current;
457 	off_t saveoff;
458 	off_t assocoff;
459 	off_t curroff;
460 	struct uio *uio;
461 	off_t uio_off;
462 	int eofflag;
463 	u_long *cookies;
464 	int ncookies;
465 };
466 
467 int
iso_uiodir(idp,dp,off)468 iso_uiodir(idp,dp,off)
469 	struct isoreaddir *idp;
470 	struct dirent *dp;
471 	off_t off;
472 {
473 	int error;
474 
475 	dp->d_name[dp->d_namlen] = 0;
476 	dp->d_reclen = DIRSIZ(dp);
477 
478 	if (idp->uio->uio_resid < dp->d_reclen) {
479 		idp->eofflag = 0;
480 		return (-1);
481 	}
482 
483 	if (idp->cookies) {
484 		if (idp->ncookies <= 0) {
485 			idp->eofflag = 0;
486 			return (-1);
487 		}
488 
489 		*idp->cookies++ = off;
490 		--idp->ncookies;
491 	}
492 
493 	if (error = uiomove(dp,dp->d_reclen,idp->uio))
494 		return (error);
495 	idp->uio_off = off;
496 	return (0);
497 }
498 
499 int
iso_shipdir(idp)500 iso_shipdir(idp)
501 	struct isoreaddir *idp;
502 {
503 	struct dirent *dp;
504 	int cl, sl, assoc;
505 	int error;
506 	char *cname, *sname;
507 
508 	cl = idp->current.d_namlen;
509 	cname = idp->current.d_name;
510 	if (assoc = cl > 1 && *cname == ASSOCCHAR) {
511 		cl--;
512 		cname++;
513 	}
514 
515 	dp = &idp->saveent;
516 	sname = dp->d_name;
517 	if (!(sl = dp->d_namlen)) {
518 		dp = &idp->assocent;
519 		sname = dp->d_name + 1;
520 		sl = dp->d_namlen - 1;
521 	}
522 	if (sl > 0) {
523 		if (sl != cl
524 		    || bcmp(sname,cname,sl)) {
525 			if (idp->assocent.d_namlen) {
526 				if (error = iso_uiodir(idp,&idp->assocent,idp->assocoff))
527 					return (error);
528 				idp->assocent.d_namlen = 0;
529 			}
530 			if (idp->saveent.d_namlen) {
531 				if (error = iso_uiodir(idp,&idp->saveent,idp->saveoff))
532 					return (error);
533 				idp->saveent.d_namlen = 0;
534 			}
535 		}
536 	}
537 	idp->current.d_reclen = DIRSIZ(&idp->current);
538 	if (assoc) {
539 		idp->assocoff = idp->curroff;
540 		bcopy(&idp->current,&idp->assocent,idp->current.d_reclen);
541 	} else {
542 		idp->saveoff = idp->curroff;
543 		bcopy(&idp->current,&idp->saveent,idp->current.d_reclen);
544 	}
545 	return (0);
546 }
547 
548 /*
549  * Vnode op for readdir
550  */
551 int
cd9660_readdir(ap)552 cd9660_readdir(ap)
553 	struct vop_readdir_args /* {
554 		struct vnode *a_vp;
555 		struct uio *a_uio;
556 		struct ucred *a_cred;
557 		int *a_eofflag;
558 		int *a_ncookies;
559 		u_long *a_cookies;
560 	} */ *ap;
561 {
562 	register struct uio *uio = ap->a_uio;
563 	struct isoreaddir *idp;
564 	struct vnode *vdp = ap->a_vp;
565 	struct iso_node *dp;
566 	struct iso_mnt *imp;
567 	struct buf *bp = NULL;
568 	struct iso_directory_record *ep;
569 	int entryoffsetinblock;
570 	doff_t endsearch;
571 	u_long bmask;
572 	int error = 0;
573 	int reclen;
574 	u_short namelen;
575 	int ncookies = 0;
576 	u_long *cookies = NULL;
577 
578 	dp = VTOI(vdp);
579 	imp = dp->i_mnt;
580 	bmask = imp->im_bmask;
581 
582 	MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK);
583 	idp->saveent.d_namlen = idp->assocent.d_namlen = 0;
584 	/*
585 	 * XXX
586 	 * Is it worth trying to figure out the type?
587 	 */
588 	idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type =
589 	    DT_UNKNOWN;
590 	idp->uio = uio;
591 	if (ap->a_ncookies == NULL) {
592 		idp->cookies = NULL;
593 	} else {
594 		/*
595 		 * Guess the number of cookies needed.
596 		 */
597 		ncookies = uio->uio_resid / 16;
598 		MALLOC(cookies, u_int *, ncookies * sizeof(u_int), M_TEMP,
599 		    M_WAITOK);
600 		idp->cookies = cookies;
601 		idp->ncookies = ncookies;
602 	}
603 	idp->eofflag = 1;
604 	idp->curroff = uio->uio_offset;
605 
606 	if ((entryoffsetinblock = idp->curroff & bmask) &&
607 	    (error = VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp))) {
608 		FREE(idp, M_TEMP);
609 		return (error);
610 	}
611 	endsearch = dp->i_size;
612 
613 	while (idp->curroff < endsearch) {
614 		/*
615 		 * If offset is on a block boundary,
616 		 * read the next directory block.
617 		 * Release previous if it exists.
618 		 */
619 		if ((idp->curroff & bmask) == 0) {
620 			if (bp != NULL)
621 				brelse(bp);
622 			if (error =
623 			    VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp))
624 				break;
625 			entryoffsetinblock = 0;
626 		}
627 		/*
628 		 * Get pointer to next entry.
629 		 */
630 		ep = (struct iso_directory_record *)
631 			((char *)bp->b_data + entryoffsetinblock);
632 
633 		reclen = isonum_711(ep->length);
634 		if (reclen == 0) {
635 			/* skip to next block, if any */
636 			idp->curroff =
637 			    (idp->curroff & ~bmask) + imp->logical_block_size;
638 			continue;
639 		}
640 
641 		if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
642 			error = EINVAL;
643 			/* illegal entry, stop */
644 			break;
645 		}
646 
647 		if (entryoffsetinblock + reclen > imp->logical_block_size) {
648 			error = EINVAL;
649 			/* illegal directory, so stop looking */
650 			break;
651 		}
652 
653 		idp->current.d_namlen = isonum_711(ep->name_len);
654 
655 		if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
656 			error = EINVAL;
657 			/* illegal entry, stop */
658 			break;
659 		}
660 
661 		if (isonum_711(ep->flags)&2)
662 			idp->current.d_fileno = isodirino(ep, imp);
663 		else
664 			idp->current.d_fileno = dbtob(bp->b_blkno) +
665 				entryoffsetinblock;
666 
667 		idp->curroff += reclen;
668 
669 		switch (imp->iso_ftype) {
670 		case ISO_FTYPE_RRIP:
671 			cd9660_rrip_getname(ep,idp->current.d_name, &namelen,
672 					   &idp->current.d_fileno,imp);
673 			idp->current.d_namlen = (u_char)namelen;
674 			if (idp->current.d_namlen)
675 				error = iso_uiodir(idp,&idp->current,idp->curroff);
676 			break;
677 		default:	/* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */
678 			strcpy(idp->current.d_name,"..");
679 			switch (ep->name[0]) {
680 			case 0:
681 				idp->current.d_namlen = 1;
682 				error = iso_uiodir(idp,&idp->current,idp->curroff);
683 				break;
684 			case 1:
685 				idp->current.d_namlen = 2;
686 				error = iso_uiodir(idp,&idp->current,idp->curroff);
687 				break;
688 			default:
689 				isofntrans(ep->name,idp->current.d_namlen,
690 					   idp->current.d_name, &namelen,
691 					   imp->iso_ftype == ISO_FTYPE_9660,
692 					   isonum_711(ep->flags)&4);
693 				idp->current.d_namlen = (u_char)namelen;
694 				if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
695 					error = iso_shipdir(idp);
696 				else
697 					error = iso_uiodir(idp,&idp->current,idp->curroff);
698 				break;
699 			}
700 		}
701 		if (error)
702 			break;
703 
704 		entryoffsetinblock += reclen;
705 	}
706 
707 	if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
708 		idp->current.d_namlen = 0;
709 		error = iso_shipdir(idp);
710 	}
711 	if (error < 0)
712 		error = 0;
713 
714 	if (ap->a_ncookies != NULL) {
715 		if (error)
716 			free(cookies, M_TEMP);
717 		else {
718 			/*
719 			 * Work out the number of cookies actually used.
720 			 */
721 			*ap->a_ncookies = ncookies - idp->ncookies;
722 			*ap->a_cookies = cookies;
723 		}
724 	}
725 
726 	if (bp)
727 		brelse (bp);
728 
729 	uio->uio_offset = idp->uio_off;
730 	*ap->a_eofflag = idp->eofflag;
731 
732 	FREE(idp, M_TEMP);
733 
734 	return (error);
735 }
736 
737 /*
738  * Return target name of a symbolic link
739  * Shouldn't we get the parent vnode and read the data from there?
740  * This could eventually result in deadlocks in cd9660_lookup.
741  * But otherwise the block read here is in the block buffer two times.
742  */
743 typedef struct iso_directory_record ISODIR;
744 typedef struct iso_node             ISONODE;
745 typedef struct iso_mnt              ISOMNT;
746 int
cd9660_readlink(ap)747 cd9660_readlink(ap)
748 	struct vop_readlink_args /* {
749 		struct vnode *a_vp;
750 		struct uio *a_uio;
751 		struct ucred *a_cred;
752 	} */ *ap;
753 {
754 	ISONODE	*ip;
755 	ISODIR	*dirp;
756 	ISOMNT	*imp;
757 	struct	buf *bp;
758 	struct	uio *uio;
759 	u_short	symlen;
760 	int	error;
761 	char	*symname;
762 	ino_t	ino;
763 
764 	ip  = VTOI(ap->a_vp);
765 	imp = ip->i_mnt;
766 	uio = ap->a_uio;
767 
768 	if (imp->iso_ftype != ISO_FTYPE_RRIP)
769 		return (EINVAL);
770 
771 	/*
772 	 * Get parents directory record block that this inode included.
773 	 */
774 	error = bread(imp->im_devvp,
775 		      (ip->i_number >> imp->im_bshift) <<
776 		      (imp->im_bshift - DEV_BSHIFT),
777 		      imp->logical_block_size, NOCRED, &bp);
778 	if (error) {
779 		brelse(bp);
780 		return (EINVAL);
781 	}
782 
783 	/*
784 	 * Setup the directory pointer for this inode
785 	 */
786 	dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
787 
788 	/*
789 	 * Just make sure, we have a right one....
790 	 *   1: Check not cross boundary on block
791 	 */
792 	if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
793 	    > imp->logical_block_size) {
794 		brelse(bp);
795 		return (EINVAL);
796 	}
797 
798 	/*
799 	 * Now get a buffer
800 	 * Abuse a namei buffer for now.
801 	 */
802 	if (uio->uio_segflg == UIO_SYSSPACE)
803 		symname = uio->uio_iov->iov_base;
804 	else
805 		MALLOC(symname, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
806 
807 	/*
808 	 * Ok, we just gathering a symbolic name in SL record.
809 	 */
810 	if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
811 		if (uio->uio_segflg != UIO_SYSSPACE)
812 			FREE(symname, M_NAMEI);
813 		brelse(bp);
814 		return (EINVAL);
815 	}
816 	/*
817 	 * Don't forget before you leave from home ;-)
818 	 */
819 	brelse(bp);
820 
821 	/*
822 	 * return with the symbolic name to caller's.
823 	 */
824 	if (uio->uio_segflg != UIO_SYSSPACE) {
825 		error = uiomove(symname, symlen, uio);
826 		FREE(symname, M_NAMEI);
827 		return (error);
828 	}
829 	uio->uio_resid -= symlen;
830 	uio->uio_iov->iov_base += symlen;
831 	uio->uio_iov->iov_len -= symlen;
832 	return (0);
833 }
834 
835 /*
836  * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
837  * done. If a buffer has been saved in anticipation of a CREATE, delete it.
838  */
839 int
cd9660_abortop(ap)840 cd9660_abortop(ap)
841 	struct vop_abortop_args /* {
842 		struct vnode *a_dvp;
843 		struct componentname *a_cnp;
844 	} */ *ap;
845 {
846 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
847 		FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
848 	return (0);
849 }
850 
851 /*
852  * Lock an inode.
853  */
854 int
cd9660_lock(ap)855 cd9660_lock(ap)
856 	struct vop_lock_args /* {
857 		struct vnode *a_vp;
858 		int a_flags;
859 		struct proc *a_p;
860 	} */ *ap;
861 {
862 	struct vnode *vp = ap->a_vp;
863 
864 	return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, &vp->v_interlock,
865 		ap->a_p));
866 }
867 
868 /*
869  * Unlock an inode.
870  */
871 int
cd9660_unlock(ap)872 cd9660_unlock(ap)
873 	struct vop_unlock_args /* {
874 		struct vnode *a_vp;
875 		int a_flags;
876 		struct proc *a_p;
877 	} */ *ap;
878 {
879 	struct vnode *vp = ap->a_vp;
880 
881 	return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE,
882 		&vp->v_interlock, ap->a_p));
883 }
884 
885 /*
886  * Calculate the logical to physical mapping if not done already,
887  * then call the device strategy routine.
888  */
889 int
cd9660_strategy(ap)890 cd9660_strategy(ap)
891 	struct vop_strategy_args /* {
892 		struct buf *a_bp;
893 	} */ *ap;
894 {
895 	register struct buf *bp = ap->a_bp;
896 	register struct vnode *vp = bp->b_vp;
897 	register struct iso_node *ip;
898 	int error;
899 
900 	ip = VTOI(vp);
901 	if (vp->v_type == VBLK || vp->v_type == VCHR)
902 		panic("cd9660_strategy: spec");
903 	if (bp->b_blkno == bp->b_lblkno) {
904 		if (error =
905 		    VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL)) {
906 			bp->b_error = error;
907 			bp->b_flags |= B_ERROR;
908 			biodone(bp);
909 			return (error);
910 		}
911 		if ((long)bp->b_blkno == -1)
912 			clrbuf(bp);
913 	}
914 	if ((long)bp->b_blkno == -1) {
915 		biodone(bp);
916 		return (0);
917 	}
918 	vp = ip->i_devvp;
919 	bp->b_dev = vp->v_rdev;
920 	VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
921 	return (0);
922 }
923 
924 /*
925  * Print out the contents of an inode.
926  */
927 int
cd9660_print(ap)928 cd9660_print(ap)
929 	struct vop_print_args /* {
930 		struct vnode *a_vp;
931 	} */ *ap;
932 {
933 
934 	printf("tag VT_ISOFS, isofs vnode\n");
935 	return (0);
936 }
937 
938 /*
939  * Check for a locked inode.
940  */
941 int
cd9660_islocked(ap)942 cd9660_islocked(ap)
943 	struct vop_islocked_args /* {
944 		struct vnode *a_vp;
945 	} */ *ap;
946 {
947 
948 	return (lockstatus(&VTOI(ap->a_vp)->i_lock));
949 }
950 
951 /*
952  * Return POSIX pathconf information applicable to cd9660 filesystems.
953  */
954 int
cd9660_pathconf(ap)955 cd9660_pathconf(ap)
956 	struct vop_pathconf_args /* {
957 		struct vnode *a_vp;
958 		int a_name;
959 		register_t *a_retval;
960 	} */ *ap;
961 {
962 
963 	switch (ap->a_name) {
964 	case _PC_LINK_MAX:
965 		*ap->a_retval = 1;
966 		return (0);
967 	case _PC_NAME_MAX:
968 		if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP)
969 			*ap->a_retval = NAME_MAX;
970 		else
971 			*ap->a_retval = 37;
972 		return (0);
973 	case _PC_PATH_MAX:
974 		*ap->a_retval = PATH_MAX;
975 		return (0);
976 	case _PC_PIPE_BUF:
977 		*ap->a_retval = PIPE_BUF;
978 		return (0);
979 	case _PC_CHOWN_RESTRICTED:
980 		*ap->a_retval = 1;
981 		return (0);
982 	case _PC_NO_TRUNC:
983 		*ap->a_retval = 1;
984 		return (0);
985 	default:
986 		return (EINVAL);
987 	}
988 	/* NOTREACHED */
989 }
990 
991 /*
992  * Global vfs data structures for isofs
993  */
994 #define cd9660_create \
995 	((int (*) __P((struct  vop_create_args *)))eopnotsupp)
996 #define cd9660_mknod ((int (*) __P((struct  vop_mknod_args *)))eopnotsupp)
997 #define cd9660_write ((int (*) __P((struct  vop_write_args *)))eopnotsupp)
998 #ifdef NFS
999 int	 lease_check __P((struct vop_lease_args *));
1000 #define	 cd9660_lease_check lease_check
1001 #else
1002 #define	 cd9660_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
1003 #endif
1004 #define cd9660_fsync ((int (*) __P((struct  vop_fsync_args *)))nullop)
1005 #define cd9660_remove \
1006 	((int (*) __P((struct  vop_remove_args *)))eopnotsupp)
1007 #define cd9660_link ((int (*) __P((struct  vop_link_args *)))eopnotsupp)
1008 #define cd9660_rename \
1009 	((int (*) __P((struct  vop_rename_args *)))eopnotsupp)
1010 #define cd9660_mkdir ((int (*) __P((struct  vop_mkdir_args *)))eopnotsupp)
1011 #define cd9660_rmdir ((int (*) __P((struct  vop_rmdir_args *)))eopnotsupp)
1012 #define cd9660_symlink \
1013 	((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
1014 #define cd9660_advlock \
1015 	((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
1016 #define cd9660_valloc ((int(*) __P(( \
1017 		struct vnode *pvp, \
1018 		int mode, \
1019 		struct ucred *cred, \
1020 		struct vnode **vpp))) eopnotsupp)
1021 #define cd9660_vfree ((int (*) __P((struct  vop_vfree_args *)))eopnotsupp)
1022 #define cd9660_truncate \
1023 	((int (*) __P((struct  vop_truncate_args *)))eopnotsupp)
1024 #define cd9660_update \
1025 	((int (*) __P((struct  vop_update_args *)))eopnotsupp)
1026 #define cd9660_bwrite \
1027 	((int (*) __P((struct  vop_bwrite_args *)))eopnotsupp)
1028 
1029 /*
1030  * Global vfs data structures for cd9660
1031  */
1032 int (**cd9660_vnodeop_p)();
1033 struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
1034 	{ &vop_default_desc, vn_default_error },
1035 	{ &vop_lookup_desc, cd9660_lookup },	/* lookup */
1036 	{ &vop_create_desc, cd9660_create },	/* create */
1037 	{ &vop_mknod_desc, cd9660_mknod },	/* mknod */
1038 	{ &vop_open_desc, cd9660_open },	/* open */
1039 	{ &vop_close_desc, cd9660_close },	/* close */
1040 	{ &vop_access_desc, cd9660_access },	/* access */
1041 	{ &vop_getattr_desc, cd9660_getattr },	/* getattr */
1042 	{ &vop_setattr_desc, cd9660_setattr },	/* setattr */
1043 	{ &vop_read_desc, cd9660_read },	/* read */
1044 	{ &vop_write_desc, cd9660_write },	/* write */
1045 	{ &vop_lease_desc, cd9660_lease_check },/* lease */
1046 	{ &vop_ioctl_desc, cd9660_ioctl },	/* ioctl */
1047 	{ &vop_select_desc, cd9660_select },	/* select */
1048 	{ &vop_revoke_desc, cd9660_revoke },	/* revoke */
1049 	{ &vop_mmap_desc, cd9660_mmap },	/* mmap */
1050 	{ &vop_fsync_desc, cd9660_fsync },	/* fsync */
1051 	{ &vop_seek_desc, cd9660_seek },	/* seek */
1052 	{ &vop_remove_desc, cd9660_remove },	/* remove */
1053 	{ &vop_link_desc, cd9660_link },	/* link */
1054 	{ &vop_rename_desc, cd9660_rename },	/* rename */
1055 	{ &vop_mkdir_desc, cd9660_mkdir },	/* mkdir */
1056 	{ &vop_rmdir_desc, cd9660_rmdir },	/* rmdir */
1057 	{ &vop_symlink_desc, cd9660_symlink },	/* symlink */
1058 	{ &vop_readdir_desc, cd9660_readdir },	/* readdir */
1059 	{ &vop_readlink_desc, cd9660_readlink },/* readlink */
1060 	{ &vop_abortop_desc, cd9660_abortop },	/* abortop */
1061 	{ &vop_inactive_desc, cd9660_inactive },/* inactive */
1062 	{ &vop_reclaim_desc, cd9660_reclaim },	/* reclaim */
1063 	{ &vop_lock_desc, cd9660_lock },	/* lock */
1064 	{ &vop_unlock_desc, cd9660_unlock },	/* unlock */
1065 	{ &vop_bmap_desc, cd9660_bmap },	/* bmap */
1066 	{ &vop_strategy_desc, cd9660_strategy },/* strategy */
1067 	{ &vop_print_desc, cd9660_print },	/* print */
1068 	{ &vop_islocked_desc, cd9660_islocked },/* islocked */
1069 	{ &vop_pathconf_desc, cd9660_pathconf },/* pathconf */
1070 	{ &vop_advlock_desc, cd9660_advlock },	/* advlock */
1071 	{ &vop_blkatoff_desc, cd9660_blkatoff },/* blkatoff */
1072 	{ &vop_valloc_desc, cd9660_valloc },	/* valloc */
1073 	{ &vop_vfree_desc, cd9660_vfree },	/* vfree */
1074 	{ &vop_truncate_desc, cd9660_truncate },/* truncate */
1075 	{ &vop_update_desc, cd9660_update },	/* update */
1076 	{ &vop_bwrite_desc, vn_bwrite },
1077 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
1078 };
1079 struct vnodeopv_desc cd9660_vnodeop_opv_desc =
1080 	{ &cd9660_vnodeop_p, cd9660_vnodeop_entries };
1081 
1082 /*
1083  * Special device vnode ops
1084  */
1085 int (**cd9660_specop_p)();
1086 struct vnodeopv_entry_desc cd9660_specop_entries[] = {
1087 	{ &vop_default_desc, vn_default_error },
1088 	{ &vop_lookup_desc, spec_lookup },	/* lookup */
1089 	{ &vop_create_desc, spec_create },	/* create */
1090 	{ &vop_mknod_desc, spec_mknod },	/* mknod */
1091 	{ &vop_open_desc, spec_open },		/* open */
1092 	{ &vop_close_desc, spec_close },	/* close */
1093 	{ &vop_access_desc, cd9660_access },	/* access */
1094 	{ &vop_getattr_desc, cd9660_getattr },	/* getattr */
1095 	{ &vop_setattr_desc, cd9660_setattr },	/* setattr */
1096 	{ &vop_read_desc, spec_read },		/* read */
1097 	{ &vop_write_desc, spec_write },	/* write */
1098 	{ &vop_lease_desc, spec_lease_check },	/* lease */
1099 	{ &vop_ioctl_desc, spec_ioctl },	/* ioctl */
1100 	{ &vop_select_desc, spec_select },	/* select */
1101 	{ &vop_revoke_desc, spec_revoke },	/* revoke */
1102 	{ &vop_mmap_desc, spec_mmap },		/* mmap */
1103 	{ &vop_fsync_desc, spec_fsync },	/* fsync */
1104 	{ &vop_seek_desc, spec_seek },		/* seek */
1105 	{ &vop_remove_desc, spec_remove },	/* remove */
1106 	{ &vop_link_desc, spec_link },		/* link */
1107 	{ &vop_rename_desc, spec_rename },	/* rename */
1108 	{ &vop_mkdir_desc, spec_mkdir },	/* mkdir */
1109 	{ &vop_rmdir_desc, spec_rmdir },	/* rmdir */
1110 	{ &vop_symlink_desc, spec_symlink },	/* symlink */
1111 	{ &vop_readdir_desc, spec_readdir },	/* readdir */
1112 	{ &vop_readlink_desc, spec_readlink },	/* readlink */
1113 	{ &vop_abortop_desc, spec_abortop },	/* abortop */
1114 	{ &vop_inactive_desc, cd9660_inactive },/* inactive */
1115 	{ &vop_reclaim_desc, cd9660_reclaim },	/* reclaim */
1116 	{ &vop_lock_desc, cd9660_lock },	/* lock */
1117 	{ &vop_unlock_desc, cd9660_unlock },	/* unlock */
1118 	{ &vop_bmap_desc, spec_bmap },		/* bmap */
1119 	{ &vop_strategy_desc, spec_strategy },	/* strategy */
1120 	{ &vop_print_desc, cd9660_print },	/* print */
1121 	{ &vop_islocked_desc, cd9660_islocked },/* islocked */
1122 	{ &vop_pathconf_desc, spec_pathconf },	/* pathconf */
1123 	{ &vop_advlock_desc, spec_advlock },	/* advlock */
1124 	{ &vop_blkatoff_desc, spec_blkatoff },	/* blkatoff */
1125 	{ &vop_valloc_desc, spec_valloc },	/* valloc */
1126 	{ &vop_vfree_desc, spec_vfree },	/* vfree */
1127 	{ &vop_truncate_desc, spec_truncate },	/* truncate */
1128 	{ &vop_update_desc, cd9660_update },	/* update */
1129 	{ &vop_bwrite_desc, vn_bwrite },
1130 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
1131 };
1132 struct vnodeopv_desc cd9660_specop_opv_desc =
1133 	{ &cd9660_specop_p, cd9660_specop_entries };
1134 
1135 #ifdef FIFO
1136 int (**cd9660_fifoop_p)();
1137 struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
1138 	{ &vop_default_desc, vn_default_error },
1139 	{ &vop_lookup_desc, fifo_lookup },	/* lookup */
1140 	{ &vop_create_desc, fifo_create },	/* create */
1141 	{ &vop_mknod_desc, fifo_mknod },	/* mknod */
1142 	{ &vop_open_desc, fifo_open },		/* open */
1143 	{ &vop_close_desc, fifo_close },	/* close */
1144 	{ &vop_access_desc, cd9660_access },	/* access */
1145 	{ &vop_getattr_desc, cd9660_getattr },	/* getattr */
1146 	{ &vop_setattr_desc, cd9660_setattr },	/* setattr */
1147 	{ &vop_read_desc, fifo_read },		/* read */
1148 	{ &vop_write_desc, fifo_write },	/* write */
1149 	{ &vop_lease_desc, fifo_lease_check },	/* lease */
1150 	{ &vop_ioctl_desc, fifo_ioctl },	/* ioctl */
1151 	{ &vop_select_desc, fifo_select },	/* select */
1152 	{ &vop_revoke_desc, fifo_revoke },	/* revoke */
1153 	{ &vop_mmap_desc, fifo_mmap },		/* mmap */
1154 	{ &vop_fsync_desc, fifo_fsync },	/* fsync */
1155 	{ &vop_seek_desc, fifo_seek },		/* seek */
1156 	{ &vop_remove_desc, fifo_remove },	/* remove */
1157 	{ &vop_link_desc, fifo_link }	,	/* link */
1158 	{ &vop_rename_desc, fifo_rename },	/* rename */
1159 	{ &vop_mkdir_desc, fifo_mkdir },	/* mkdir */
1160 	{ &vop_rmdir_desc, fifo_rmdir },	/* rmdir */
1161 	{ &vop_symlink_desc, fifo_symlink },	/* symlink */
1162 	{ &vop_readdir_desc, fifo_readdir },	/* readdir */
1163 	{ &vop_readlink_desc, fifo_readlink },	/* readlink */
1164 	{ &vop_abortop_desc, fifo_abortop },	/* abortop */
1165 	{ &vop_inactive_desc, cd9660_inactive },/* inactive */
1166 	{ &vop_reclaim_desc, cd9660_reclaim },	/* reclaim */
1167 	{ &vop_lock_desc, cd9660_lock },	/* lock */
1168 	{ &vop_unlock_desc, cd9660_unlock },	/* unlock */
1169 	{ &vop_bmap_desc, fifo_bmap },		/* bmap */
1170 	{ &vop_strategy_desc, fifo_strategy },	/* strategy */
1171 	{ &vop_print_desc, cd9660_print },	/* print */
1172 	{ &vop_islocked_desc, cd9660_islocked },/* islocked */
1173 	{ &vop_pathconf_desc, fifo_pathconf },	/* pathconf */
1174 	{ &vop_advlock_desc, fifo_advlock },	/* advlock */
1175 	{ &vop_blkatoff_desc, fifo_blkatoff },	/* blkatoff */
1176 	{ &vop_valloc_desc, fifo_valloc },	/* valloc */
1177 	{ &vop_vfree_desc, fifo_vfree },	/* vfree */
1178 	{ &vop_truncate_desc, fifo_truncate },	/* truncate */
1179 	{ &vop_update_desc, cd9660_update },	/* update */
1180 	{ &vop_bwrite_desc, vn_bwrite },
1181 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
1182 };
1183 struct vnodeopv_desc cd9660_fifoop_opv_desc =
1184 	{ &cd9660_fifoop_p, cd9660_fifoop_entries };
1185 #endif /* FIFO */
1186