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