Deleted Added
full compact
cd9660_vnops.c (30492) cd9660_vnops.c (30513)
1/*-
2 * Copyright (c) 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley
6 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
7 * Support code is derived from software contributed to Berkeley
8 * by Atsushi Murai (amurai@spec.co.jp).
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)cd9660_vnops.c 8.19 (Berkeley) 5/27/95
1/*-
2 * Copyright (c) 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley
6 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
7 * Support code is derived from software contributed to Berkeley
8 * by Atsushi Murai (amurai@spec.co.jp).
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)cd9660_vnops.c 8.19 (Berkeley) 5/27/95
39 * $Id: cd9660_vnops.c,v 1.44 1997/10/16 10:47:47 phk Exp $
39 * $Id: cd9660_vnops.c,v 1.45 1997/10/16 20:32:21 phk Exp $
40 */
41
42#include <sys/param.h>
43#include <sys/systm.h>
44#include <sys/namei.h>
45#include <sys/kernel.h>
46#include <sys/stat.h>
47#include <sys/sysctl.h>
48#include <sys/buf.h>
49#include <sys/mount.h>
50#include <sys/vnode.h>
51#include <miscfs/specfs/specdev.h>
52#include <miscfs/fifofs/fifo.h>
53#include <sys/malloc.h>
54#include <sys/dirent.h>
55#include <sys/unistd.h>
56
57#include <isofs/cd9660/iso.h>
58#include <isofs/cd9660/cd9660_node.h>
59#include <isofs/cd9660/iso_rrip.h>
60
61static int cd9660_setattr __P((struct vop_setattr_args *));
62static int cd9660_access __P((struct vop_access_args *));
63static int cd9660_getattr __P((struct vop_getattr_args *));
64static int cd9660_read __P((struct vop_read_args *));
65struct isoreaddir;
66static int iso_uiodir __P((struct isoreaddir *idp, struct dirent *dp,
67 off_t off));
68static int iso_shipdir __P((struct isoreaddir *idp));
69static int cd9660_readdir __P((struct vop_readdir_args *));
70static int cd9660_readlink __P((struct vop_readlink_args *ap));
71static int cd9660_abortop __P((struct vop_abortop_args *));
40 */
41
42#include <sys/param.h>
43#include <sys/systm.h>
44#include <sys/namei.h>
45#include <sys/kernel.h>
46#include <sys/stat.h>
47#include <sys/sysctl.h>
48#include <sys/buf.h>
49#include <sys/mount.h>
50#include <sys/vnode.h>
51#include <miscfs/specfs/specdev.h>
52#include <miscfs/fifofs/fifo.h>
53#include <sys/malloc.h>
54#include <sys/dirent.h>
55#include <sys/unistd.h>
56
57#include <isofs/cd9660/iso.h>
58#include <isofs/cd9660/cd9660_node.h>
59#include <isofs/cd9660/iso_rrip.h>
60
61static int cd9660_setattr __P((struct vop_setattr_args *));
62static int cd9660_access __P((struct vop_access_args *));
63static int cd9660_getattr __P((struct vop_getattr_args *));
64static int cd9660_read __P((struct vop_read_args *));
65struct isoreaddir;
66static int iso_uiodir __P((struct isoreaddir *idp, struct dirent *dp,
67 off_t off));
68static int iso_shipdir __P((struct isoreaddir *idp));
69static int cd9660_readdir __P((struct vop_readdir_args *));
70static int cd9660_readlink __P((struct vop_readlink_args *ap));
71static int cd9660_abortop __P((struct vop_abortop_args *));
72static int cd9660_lock __P((struct vop_lock_args *));
73static int cd9660_unlock __P((struct vop_unlock_args *));
74static int cd9660_strategy __P((struct vop_strategy_args *));
75static int cd9660_print __P((struct vop_print_args *));
72static int cd9660_strategy __P((struct vop_strategy_args *));
73static int cd9660_print __P((struct vop_print_args *));
76static int cd9660_islocked __P((struct vop_islocked_args *));
77
78/*
79 * Setattr call. Only allowed for block and character special devices.
80 */
81int
82cd9660_setattr(ap)
83 struct vop_setattr_args /* {
84 struct vnodeop_desc *a_desc;
85 struct vnode *a_vp;
86 struct vattr *a_vap;
87 struct ucred *a_cred;
88 struct proc *a_p;
89 } */ *ap;
90{
91 struct vnode *vp = ap->a_vp;
92 struct vattr *vap = ap->a_vap;
93
94 if (vap->va_flags != (u_long)VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
95 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
96 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL)
97 return (EROFS);
98 if (vap->va_size != (u_quad_t)VNOVAL) {
99 switch (vp->v_type) {
100 case VDIR:
101 return (EISDIR);
102 case VLNK:
103 case VREG:
104 return (EROFS);
105 case VCHR:
106 case VBLK:
107 case VSOCK:
108 case VFIFO:
109 return (0);
110 }
111 }
112 return (0);
113}
114
115/*
116 * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
117 * The mode is shifted to select the owner/group/other fields. The
118 * super user is granted all permissions.
119 */
120/* ARGSUSED */
121static int
122cd9660_access(ap)
123 struct vop_access_args /* {
124 struct vnode *a_vp;
125 int a_mode;
126 struct ucred *a_cred;
127 struct proc *a_p;
128 } */ *ap;
129{
130 struct vnode *vp = ap->a_vp;
131 struct iso_node *ip = VTOI(vp);
132 struct ucred *cred = ap->a_cred;
133 mode_t mask, mode = ap->a_mode;
134 gid_t *gp;
135 int i;
136
137 /*
138 * Disallow write attempts unless the file is a socket,
139 * fifo, or a block or character device resident on the
140 * file system.
141 */
142 if (mode & VWRITE) {
143 switch (vp->v_type) {
144 case VDIR:
145 case VLNK:
146 case VREG:
147 return (EROFS);
148 }
149 }
150
151 /* User id 0 always gets access. */
152 if (cred->cr_uid == 0)
153 return (0);
154
155 mask = 0;
156
157 /* Otherwise, check the owner. */
158 if (cred->cr_uid == ip->inode.iso_uid) {
159 if (mode & VEXEC)
160 mask |= S_IXUSR;
161 if (mode & VREAD)
162 mask |= S_IRUSR;
163 if (mode & VWRITE)
164 mask |= S_IWUSR;
165 return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
166 }
167
168 /* Otherwise, check the groups. */
169 for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
170 if (ip->inode.iso_gid == *gp) {
171 if (mode & VEXEC)
172 mask |= S_IXGRP;
173 if (mode & VREAD)
174 mask |= S_IRGRP;
175 if (mode & VWRITE)
176 mask |= S_IWGRP;
177 return ((ip->inode.iso_mode & mask) == mask ?
178 0 : EACCES);
179 }
180
181 /* Otherwise, check everyone else. */
182 if (mode & VEXEC)
183 mask |= S_IXOTH;
184 if (mode & VREAD)
185 mask |= S_IROTH;
186 if (mode & VWRITE)
187 mask |= S_IWOTH;
188 return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
189}
190
191static int
192cd9660_getattr(ap)
193 struct vop_getattr_args /* {
194 struct vnode *a_vp;
195 struct vattr *a_vap;
196 struct ucred *a_cred;
197 struct proc *a_p;
198 } */ *ap;
199
200{
201 struct vnode *vp = ap->a_vp;
202 register struct vattr *vap = ap->a_vap;
203 register struct iso_node *ip = VTOI(vp);
204
205 vap->va_fsid = ip->i_dev;
206 vap->va_fileid = ip->i_number;
207
208 vap->va_mode = ip->inode.iso_mode;
209 vap->va_nlink = ip->inode.iso_links;
210 vap->va_uid = ip->inode.iso_uid;
211 vap->va_gid = ip->inode.iso_gid;
212 vap->va_atime = ip->inode.iso_atime;
213 vap->va_mtime = ip->inode.iso_mtime;
214 vap->va_ctime = ip->inode.iso_ctime;
215 vap->va_rdev = ip->inode.iso_rdev;
216
217 vap->va_size = (u_quad_t) ip->i_size;
218 if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) {
219 struct vop_readlink_args rdlnk;
220 struct iovec aiov;
221 struct uio auio;
222 char *cp;
223
224 MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
225 aiov.iov_base = cp;
226 aiov.iov_len = MAXPATHLEN;
227 auio.uio_iov = &aiov;
228 auio.uio_iovcnt = 1;
229 auio.uio_offset = 0;
230 auio.uio_rw = UIO_READ;
231 auio.uio_segflg = UIO_SYSSPACE;
232 auio.uio_procp = ap->a_p;
233 auio.uio_resid = MAXPATHLEN;
234 rdlnk.a_uio = &auio;
235 rdlnk.a_vp = ap->a_vp;
236 rdlnk.a_cred = ap->a_cred;
237 if (cd9660_readlink(&rdlnk) == 0)
238 vap->va_size = MAXPATHLEN - auio.uio_resid;
239 FREE(cp, M_TEMP);
240 }
241 vap->va_flags = 0;
242 vap->va_gen = 1;
243 vap->va_blocksize = ip->i_mnt->logical_block_size;
244 vap->va_bytes = (u_quad_t) ip->i_size;
245 vap->va_type = vp->v_type;
246 vap->va_filerev = 0;
247 return (0);
248}
249
250/*
251 * Vnode op for reading.
252 */
253static int
254cd9660_read(ap)
255 struct vop_read_args /* {
256 struct vnode *a_vp;
257 struct uio *a_uio;
258 int a_ioflag;
259 struct ucred *a_cred;
260 } */ *ap;
261{
262 struct vnode *vp = ap->a_vp;
263 register struct uio *uio = ap->a_uio;
264 register struct iso_node *ip = VTOI(vp);
265 register struct iso_mnt *imp;
266 struct buf *bp;
267 daddr_t lbn, rablock;
268 off_t diff;
269 int rasize, error = 0;
270 long size, n, on;
271
272 if (uio->uio_resid == 0)
273 return (0);
274 if (uio->uio_offset < 0)
275 return (EINVAL);
276 ip->i_flag |= IN_ACCESS;
277 imp = ip->i_mnt;
278 do {
279 lbn = lblkno(imp, uio->uio_offset);
280 on = blkoff(imp, uio->uio_offset);
281 n = min((u_int)(imp->logical_block_size - on),
282 uio->uio_resid);
283 diff = (off_t)ip->i_size - uio->uio_offset;
284 if (diff <= 0)
285 return (0);
286 if (diff < n)
287 n = diff;
288 size = blksize(imp, ip, lbn);
289 rablock = lbn + 1;
290 if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) {
291 if (lblktosize(imp, rablock) <= ip->i_size)
292 error = cluster_read(vp, (off_t)ip->i_size,
293 lbn, size, NOCRED, uio->uio_resid,
294 (ap->a_ioflag >> 16), &bp);
295 else
296 error = bread(vp, lbn, size, NOCRED, &bp);
297 } else {
298 if (vp->v_lastr + 1 == lbn &&
299 lblktosize(imp, rablock) < ip->i_size) {
300 rasize = blksize(imp, ip, rablock);
301 error = breadn(vp, lbn, size, &rablock,
302 &rasize, 1, NOCRED, &bp);
303 } else
304 error = bread(vp, lbn, size, NOCRED, &bp);
305 }
306 vp->v_lastr = lbn;
307 n = min(n, size - bp->b_resid);
308 if (error) {
309 brelse(bp);
310 return (error);
311 }
312
313 error = uiomove(bp->b_data + on, (int)n, uio);
314 brelse(bp);
315 } while (error == 0 && uio->uio_resid > 0 && n != 0);
316 return (error);
317}
318
319/*
320 * Structure for reading directories
321 */
322struct isoreaddir {
323 struct dirent saveent;
324 struct dirent assocent;
325 struct dirent current;
326 off_t saveoff;
327 off_t assocoff;
328 off_t curroff;
329 struct uio *uio;
330 off_t uio_off;
331 int eofflag;
332 u_long *cookies;
333 int ncookies;
334};
335
336int
337iso_uiodir(idp,dp,off)
338 struct isoreaddir *idp;
339 struct dirent *dp;
340 off_t off;
341{
342 int error;
343
344 dp->d_name[dp->d_namlen] = 0;
345 dp->d_reclen = GENERIC_DIRSIZ(dp);
346
347 if (idp->uio->uio_resid < dp->d_reclen) {
348 idp->eofflag = 0;
349 return (-1);
350 }
351
352 if (idp->cookies) {
353 if (idp->ncookies <= 0) {
354 idp->eofflag = 0;
355 return (-1);
356 }
357
358 *idp->cookies++ = off;
359 --idp->ncookies;
360 }
361
362 if (error = uiomove((caddr_t) dp,dp->d_reclen,idp->uio))
363 return (error);
364 idp->uio_off = off;
365 return (0);
366}
367
368int
369iso_shipdir(idp)
370 struct isoreaddir *idp;
371{
372 struct dirent *dp;
373 int cl, sl, assoc;
374 int error;
375 char *cname, *sname;
376
377 cl = idp->current.d_namlen;
378 cname = idp->current.d_name;
379assoc = (cl > 1) && (*cname == ASSOCCHAR);
380 if (assoc) {
381 cl--;
382 cname++;
383 }
384
385 dp = &idp->saveent;
386 sname = dp->d_name;
387 if (!(sl = dp->d_namlen)) {
388 dp = &idp->assocent;
389 sname = dp->d_name + 1;
390 sl = dp->d_namlen - 1;
391 }
392 if (sl > 0) {
393 if (sl != cl
394 || bcmp(sname,cname,sl)) {
395 if (idp->assocent.d_namlen) {
396 if (error = iso_uiodir(idp,&idp->assocent,idp->assocoff))
397 return (error);
398 idp->assocent.d_namlen = 0;
399 }
400 if (idp->saveent.d_namlen) {
401 if (error = iso_uiodir(idp,&idp->saveent,idp->saveoff))
402 return (error);
403 idp->saveent.d_namlen = 0;
404 }
405 }
406 }
407 idp->current.d_reclen = GENERIC_DIRSIZ(&idp->current);
408 if (assoc) {
409 idp->assocoff = idp->curroff;
410 bcopy(&idp->current,&idp->assocent,idp->current.d_reclen);
411 } else {
412 idp->saveoff = idp->curroff;
413 bcopy(&idp->current,&idp->saveent,idp->current.d_reclen);
414 }
415 return (0);
416}
417
418/*
419 * Vnode op for readdir
420 */
421static int
422cd9660_readdir(ap)
423 struct vop_readdir_args /* {
424 struct vnode *a_vp;
425 struct uio *a_uio;
426 struct ucred *a_cred;
427 int *a_eofflag;
428 int *a_ncookies;
429 u_long *a_cookies;
430 } */ *ap;
431{
432 register struct uio *uio = ap->a_uio;
433 struct isoreaddir *idp;
434 struct vnode *vdp = ap->a_vp;
435 struct iso_node *dp;
436 struct iso_mnt *imp;
437 struct buf *bp = NULL;
438 struct iso_directory_record *ep;
439 int entryoffsetinblock;
440 doff_t endsearch;
441 u_long bmask;
442 int error = 0;
443 int reclen;
444 u_short namelen;
445 int ncookies = 0;
446 u_long *cookies = NULL;
447
448 dp = VTOI(vdp);
449 imp = dp->i_mnt;
450 bmask = imp->im_bmask;
451
452 MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK);
453 idp->saveent.d_namlen = idp->assocent.d_namlen = 0;
454 /*
455 * XXX
456 * Is it worth trying to figure out the type?
457 */
458 idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type =
459 DT_UNKNOWN;
460 idp->uio = uio;
461 if (ap->a_ncookies == NULL) {
462 idp->cookies = NULL;
463 } else {
464 /*
465 * Guess the number of cookies needed.
466 */
467 ncookies = uio->uio_resid / 16;
468 MALLOC(cookies, u_long *, ncookies * sizeof(u_int), M_TEMP,
469 M_WAITOK);
470 idp->cookies = cookies;
471 idp->ncookies = ncookies;
472 }
473 idp->eofflag = 1;
474 idp->curroff = uio->uio_offset;
475
476 if ((entryoffsetinblock = idp->curroff & bmask) &&
477 (error = cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp))) {
478 FREE(idp, M_TEMP);
479 return (error);
480 }
481 endsearch = dp->i_size;
482
483 while (idp->curroff < endsearch) {
484 /*
485 * If offset is on a block boundary,
486 * read the next directory block.
487 * Release previous if it exists.
488 */
489 if ((idp->curroff & bmask) == 0) {
490 if (bp != NULL)
491 brelse(bp);
492 if (error =
493 cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp))
494 break;
495 entryoffsetinblock = 0;
496 }
497 /*
498 * Get pointer to next entry.
499 */
500 ep = (struct iso_directory_record *)
501 ((char *)bp->b_data + entryoffsetinblock);
502
503 reclen = isonum_711(ep->length);
504 if (reclen == 0) {
505 /* skip to next block, if any */
506 idp->curroff =
507 (idp->curroff & ~bmask) + imp->logical_block_size;
508 continue;
509 }
510
511 if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
512 error = EINVAL;
513 /* illegal entry, stop */
514 break;
515 }
516
517 if (entryoffsetinblock + reclen > imp->logical_block_size) {
518 error = EINVAL;
519 /* illegal directory, so stop looking */
520 break;
521 }
522
523 idp->current.d_namlen = isonum_711(ep->name_len);
524
525 if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
526 error = EINVAL;
527 /* illegal entry, stop */
528 break;
529 }
530
531 if (isonum_711(ep->flags)&2)
532 idp->current.d_fileno = isodirino(ep, imp);
533 else
534 idp->current.d_fileno = dbtob(bp->b_blkno) +
535 entryoffsetinblock;
536
537 idp->curroff += reclen;
538
539 switch (imp->iso_ftype) {
540 case ISO_FTYPE_RRIP:
541 cd9660_rrip_getname(ep,idp->current.d_name, &namelen,
542 &idp->current.d_fileno,imp);
543 idp->current.d_namlen = (u_char)namelen;
544 if (idp->current.d_namlen)
545 error = iso_uiodir(idp,&idp->current,idp->curroff);
546 break;
547 default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA*/
548 strcpy(idp->current.d_name,"..");
549 switch (ep->name[0]) {
550 case 0:
551 idp->current.d_namlen = 1;
552 error = iso_uiodir(idp,&idp->current,idp->curroff);
553 break;
554 case 1:
555 idp->current.d_namlen = 2;
556 error = iso_uiodir(idp,&idp->current,idp->curroff);
557 break;
558 default:
559 isofntrans(ep->name,idp->current.d_namlen,
560 idp->current.d_name, &namelen,
561 imp->iso_ftype == ISO_FTYPE_9660,
562 isonum_711(ep->flags)&4);
563 idp->current.d_namlen = (u_char)namelen;
564 if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
565 error = iso_shipdir(idp);
566 else
567 error = iso_uiodir(idp,&idp->current,idp->curroff);
568 break;
569 }
570 }
571 if (error)
572 break;
573
574 entryoffsetinblock += reclen;
575 }
576
577 if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
578 idp->current.d_namlen = 0;
579 error = iso_shipdir(idp);
580 }
581 if (error < 0)
582 error = 0;
583
584 if (ap->a_ncookies != NULL) {
585 if (error)
586 free(cookies, M_TEMP);
587 else {
588 /*
589 * Work out the number of cookies actually used.
590 */
591 *ap->a_ncookies = ncookies - idp->ncookies;
592 *ap->a_cookies = cookies;
593 }
594 }
595
596 if (bp)
597 brelse (bp);
598
599 uio->uio_offset = idp->uio_off;
600 *ap->a_eofflag = idp->eofflag;
601
602 FREE(idp, M_TEMP);
603
604 return (error);
605}
606
607/*
608 * Return target name of a symbolic link
609 * Shouldn't we get the parent vnode and read the data from there?
610 * This could eventually result in deadlocks in cd9660_lookup.
611 * But otherwise the block read here is in the block buffer two times.
612 */
613typedef struct iso_directory_record ISODIR;
614typedef struct iso_node ISONODE;
615typedef struct iso_mnt ISOMNT;
616static int
617cd9660_readlink(ap)
618 struct vop_readlink_args /* {
619 struct vnode *a_vp;
620 struct uio *a_uio;
621 struct ucred *a_cred;
622 } */ *ap;
623{
624 ISONODE *ip;
625 ISODIR *dirp;
626 ISOMNT *imp;
627 struct buf *bp;
628 struct uio *uio;
629 u_short symlen;
630 int error;
631 char *symname;
632
633 ip = VTOI(ap->a_vp);
634 imp = ip->i_mnt;
635 uio = ap->a_uio;
636
637 if (imp->iso_ftype != ISO_FTYPE_RRIP)
638 return (EINVAL);
639
640 /*
641 * Get parents directory record block that this inode included.
642 */
643 error = bread(imp->im_devvp,
644 (ip->i_number >> imp->im_bshift) <<
645 (imp->im_bshift - DEV_BSHIFT),
646 imp->logical_block_size, NOCRED, &bp);
647 if (error) {
648 brelse(bp);
649 return (EINVAL);
650 }
651
652 /*
653 * Setup the directory pointer for this inode
654 */
655 dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
656
657 /*
658 * Just make sure, we have a right one....
659 * 1: Check not cross boundary on block
660 */
661 if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
662 > (unsigned)imp->logical_block_size) {
663 brelse(bp);
664 return (EINVAL);
665 }
666
667 /*
668 * Now get a buffer
669 * Abuse a namei buffer for now.
670 */
671 if (uio->uio_segflg == UIO_SYSSPACE)
672 symname = uio->uio_iov->iov_base;
673 else
674 symname = zalloc(namei_zone);
675
676 /*
677 * Ok, we just gathering a symbolic name in SL record.
678 */
679 if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
680 if (uio->uio_segflg != UIO_SYSSPACE)
681 zfree(namei_zone, symname);
682 brelse(bp);
683 return (EINVAL);
684 }
685 /*
686 * Don't forget before you leave from home ;-)
687 */
688 brelse(bp);
689
690 /*
691 * return with the symbolic name to caller's.
692 */
693 if (uio->uio_segflg != UIO_SYSSPACE) {
694 error = uiomove(symname, symlen, uio);
695 zfree(namei_zone, symname);
696 return (error);
697 }
698 uio->uio_resid -= symlen;
699 uio->uio_iov->iov_base += symlen;
700 uio->uio_iov->iov_len -= symlen;
701 return (0);
702}
703
704/*
705 * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
706 * done. If a buffer has been saved in anticipation of a CREATE, delete it.
707 */
708static int
709cd9660_abortop(ap)
710 struct vop_abortop_args /* {
711 struct vnode *a_dvp;
712 struct componentname *a_cnp;
713 } */ *ap;
714{
715 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
716 zfree(namei_zone, ap->a_cnp->cn_pnbuf);
717 return (0);
718}
719
720/*
74
75/*
76 * Setattr call. Only allowed for block and character special devices.
77 */
78int
79cd9660_setattr(ap)
80 struct vop_setattr_args /* {
81 struct vnodeop_desc *a_desc;
82 struct vnode *a_vp;
83 struct vattr *a_vap;
84 struct ucred *a_cred;
85 struct proc *a_p;
86 } */ *ap;
87{
88 struct vnode *vp = ap->a_vp;
89 struct vattr *vap = ap->a_vap;
90
91 if (vap->va_flags != (u_long)VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
92 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
93 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL)
94 return (EROFS);
95 if (vap->va_size != (u_quad_t)VNOVAL) {
96 switch (vp->v_type) {
97 case VDIR:
98 return (EISDIR);
99 case VLNK:
100 case VREG:
101 return (EROFS);
102 case VCHR:
103 case VBLK:
104 case VSOCK:
105 case VFIFO:
106 return (0);
107 }
108 }
109 return (0);
110}
111
112/*
113 * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
114 * The mode is shifted to select the owner/group/other fields. The
115 * super user is granted all permissions.
116 */
117/* ARGSUSED */
118static int
119cd9660_access(ap)
120 struct vop_access_args /* {
121 struct vnode *a_vp;
122 int a_mode;
123 struct ucred *a_cred;
124 struct proc *a_p;
125 } */ *ap;
126{
127 struct vnode *vp = ap->a_vp;
128 struct iso_node *ip = VTOI(vp);
129 struct ucred *cred = ap->a_cred;
130 mode_t mask, mode = ap->a_mode;
131 gid_t *gp;
132 int i;
133
134 /*
135 * Disallow write attempts unless the file is a socket,
136 * fifo, or a block or character device resident on the
137 * file system.
138 */
139 if (mode & VWRITE) {
140 switch (vp->v_type) {
141 case VDIR:
142 case VLNK:
143 case VREG:
144 return (EROFS);
145 }
146 }
147
148 /* User id 0 always gets access. */
149 if (cred->cr_uid == 0)
150 return (0);
151
152 mask = 0;
153
154 /* Otherwise, check the owner. */
155 if (cred->cr_uid == ip->inode.iso_uid) {
156 if (mode & VEXEC)
157 mask |= S_IXUSR;
158 if (mode & VREAD)
159 mask |= S_IRUSR;
160 if (mode & VWRITE)
161 mask |= S_IWUSR;
162 return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
163 }
164
165 /* Otherwise, check the groups. */
166 for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
167 if (ip->inode.iso_gid == *gp) {
168 if (mode & VEXEC)
169 mask |= S_IXGRP;
170 if (mode & VREAD)
171 mask |= S_IRGRP;
172 if (mode & VWRITE)
173 mask |= S_IWGRP;
174 return ((ip->inode.iso_mode & mask) == mask ?
175 0 : EACCES);
176 }
177
178 /* Otherwise, check everyone else. */
179 if (mode & VEXEC)
180 mask |= S_IXOTH;
181 if (mode & VREAD)
182 mask |= S_IROTH;
183 if (mode & VWRITE)
184 mask |= S_IWOTH;
185 return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
186}
187
188static int
189cd9660_getattr(ap)
190 struct vop_getattr_args /* {
191 struct vnode *a_vp;
192 struct vattr *a_vap;
193 struct ucred *a_cred;
194 struct proc *a_p;
195 } */ *ap;
196
197{
198 struct vnode *vp = ap->a_vp;
199 register struct vattr *vap = ap->a_vap;
200 register struct iso_node *ip = VTOI(vp);
201
202 vap->va_fsid = ip->i_dev;
203 vap->va_fileid = ip->i_number;
204
205 vap->va_mode = ip->inode.iso_mode;
206 vap->va_nlink = ip->inode.iso_links;
207 vap->va_uid = ip->inode.iso_uid;
208 vap->va_gid = ip->inode.iso_gid;
209 vap->va_atime = ip->inode.iso_atime;
210 vap->va_mtime = ip->inode.iso_mtime;
211 vap->va_ctime = ip->inode.iso_ctime;
212 vap->va_rdev = ip->inode.iso_rdev;
213
214 vap->va_size = (u_quad_t) ip->i_size;
215 if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) {
216 struct vop_readlink_args rdlnk;
217 struct iovec aiov;
218 struct uio auio;
219 char *cp;
220
221 MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
222 aiov.iov_base = cp;
223 aiov.iov_len = MAXPATHLEN;
224 auio.uio_iov = &aiov;
225 auio.uio_iovcnt = 1;
226 auio.uio_offset = 0;
227 auio.uio_rw = UIO_READ;
228 auio.uio_segflg = UIO_SYSSPACE;
229 auio.uio_procp = ap->a_p;
230 auio.uio_resid = MAXPATHLEN;
231 rdlnk.a_uio = &auio;
232 rdlnk.a_vp = ap->a_vp;
233 rdlnk.a_cred = ap->a_cred;
234 if (cd9660_readlink(&rdlnk) == 0)
235 vap->va_size = MAXPATHLEN - auio.uio_resid;
236 FREE(cp, M_TEMP);
237 }
238 vap->va_flags = 0;
239 vap->va_gen = 1;
240 vap->va_blocksize = ip->i_mnt->logical_block_size;
241 vap->va_bytes = (u_quad_t) ip->i_size;
242 vap->va_type = vp->v_type;
243 vap->va_filerev = 0;
244 return (0);
245}
246
247/*
248 * Vnode op for reading.
249 */
250static int
251cd9660_read(ap)
252 struct vop_read_args /* {
253 struct vnode *a_vp;
254 struct uio *a_uio;
255 int a_ioflag;
256 struct ucred *a_cred;
257 } */ *ap;
258{
259 struct vnode *vp = ap->a_vp;
260 register struct uio *uio = ap->a_uio;
261 register struct iso_node *ip = VTOI(vp);
262 register struct iso_mnt *imp;
263 struct buf *bp;
264 daddr_t lbn, rablock;
265 off_t diff;
266 int rasize, error = 0;
267 long size, n, on;
268
269 if (uio->uio_resid == 0)
270 return (0);
271 if (uio->uio_offset < 0)
272 return (EINVAL);
273 ip->i_flag |= IN_ACCESS;
274 imp = ip->i_mnt;
275 do {
276 lbn = lblkno(imp, uio->uio_offset);
277 on = blkoff(imp, uio->uio_offset);
278 n = min((u_int)(imp->logical_block_size - on),
279 uio->uio_resid);
280 diff = (off_t)ip->i_size - uio->uio_offset;
281 if (diff <= 0)
282 return (0);
283 if (diff < n)
284 n = diff;
285 size = blksize(imp, ip, lbn);
286 rablock = lbn + 1;
287 if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) {
288 if (lblktosize(imp, rablock) <= ip->i_size)
289 error = cluster_read(vp, (off_t)ip->i_size,
290 lbn, size, NOCRED, uio->uio_resid,
291 (ap->a_ioflag >> 16), &bp);
292 else
293 error = bread(vp, lbn, size, NOCRED, &bp);
294 } else {
295 if (vp->v_lastr + 1 == lbn &&
296 lblktosize(imp, rablock) < ip->i_size) {
297 rasize = blksize(imp, ip, rablock);
298 error = breadn(vp, lbn, size, &rablock,
299 &rasize, 1, NOCRED, &bp);
300 } else
301 error = bread(vp, lbn, size, NOCRED, &bp);
302 }
303 vp->v_lastr = lbn;
304 n = min(n, size - bp->b_resid);
305 if (error) {
306 brelse(bp);
307 return (error);
308 }
309
310 error = uiomove(bp->b_data + on, (int)n, uio);
311 brelse(bp);
312 } while (error == 0 && uio->uio_resid > 0 && n != 0);
313 return (error);
314}
315
316/*
317 * Structure for reading directories
318 */
319struct isoreaddir {
320 struct dirent saveent;
321 struct dirent assocent;
322 struct dirent current;
323 off_t saveoff;
324 off_t assocoff;
325 off_t curroff;
326 struct uio *uio;
327 off_t uio_off;
328 int eofflag;
329 u_long *cookies;
330 int ncookies;
331};
332
333int
334iso_uiodir(idp,dp,off)
335 struct isoreaddir *idp;
336 struct dirent *dp;
337 off_t off;
338{
339 int error;
340
341 dp->d_name[dp->d_namlen] = 0;
342 dp->d_reclen = GENERIC_DIRSIZ(dp);
343
344 if (idp->uio->uio_resid < dp->d_reclen) {
345 idp->eofflag = 0;
346 return (-1);
347 }
348
349 if (idp->cookies) {
350 if (idp->ncookies <= 0) {
351 idp->eofflag = 0;
352 return (-1);
353 }
354
355 *idp->cookies++ = off;
356 --idp->ncookies;
357 }
358
359 if (error = uiomove((caddr_t) dp,dp->d_reclen,idp->uio))
360 return (error);
361 idp->uio_off = off;
362 return (0);
363}
364
365int
366iso_shipdir(idp)
367 struct isoreaddir *idp;
368{
369 struct dirent *dp;
370 int cl, sl, assoc;
371 int error;
372 char *cname, *sname;
373
374 cl = idp->current.d_namlen;
375 cname = idp->current.d_name;
376assoc = (cl > 1) && (*cname == ASSOCCHAR);
377 if (assoc) {
378 cl--;
379 cname++;
380 }
381
382 dp = &idp->saveent;
383 sname = dp->d_name;
384 if (!(sl = dp->d_namlen)) {
385 dp = &idp->assocent;
386 sname = dp->d_name + 1;
387 sl = dp->d_namlen - 1;
388 }
389 if (sl > 0) {
390 if (sl != cl
391 || bcmp(sname,cname,sl)) {
392 if (idp->assocent.d_namlen) {
393 if (error = iso_uiodir(idp,&idp->assocent,idp->assocoff))
394 return (error);
395 idp->assocent.d_namlen = 0;
396 }
397 if (idp->saveent.d_namlen) {
398 if (error = iso_uiodir(idp,&idp->saveent,idp->saveoff))
399 return (error);
400 idp->saveent.d_namlen = 0;
401 }
402 }
403 }
404 idp->current.d_reclen = GENERIC_DIRSIZ(&idp->current);
405 if (assoc) {
406 idp->assocoff = idp->curroff;
407 bcopy(&idp->current,&idp->assocent,idp->current.d_reclen);
408 } else {
409 idp->saveoff = idp->curroff;
410 bcopy(&idp->current,&idp->saveent,idp->current.d_reclen);
411 }
412 return (0);
413}
414
415/*
416 * Vnode op for readdir
417 */
418static int
419cd9660_readdir(ap)
420 struct vop_readdir_args /* {
421 struct vnode *a_vp;
422 struct uio *a_uio;
423 struct ucred *a_cred;
424 int *a_eofflag;
425 int *a_ncookies;
426 u_long *a_cookies;
427 } */ *ap;
428{
429 register struct uio *uio = ap->a_uio;
430 struct isoreaddir *idp;
431 struct vnode *vdp = ap->a_vp;
432 struct iso_node *dp;
433 struct iso_mnt *imp;
434 struct buf *bp = NULL;
435 struct iso_directory_record *ep;
436 int entryoffsetinblock;
437 doff_t endsearch;
438 u_long bmask;
439 int error = 0;
440 int reclen;
441 u_short namelen;
442 int ncookies = 0;
443 u_long *cookies = NULL;
444
445 dp = VTOI(vdp);
446 imp = dp->i_mnt;
447 bmask = imp->im_bmask;
448
449 MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK);
450 idp->saveent.d_namlen = idp->assocent.d_namlen = 0;
451 /*
452 * XXX
453 * Is it worth trying to figure out the type?
454 */
455 idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type =
456 DT_UNKNOWN;
457 idp->uio = uio;
458 if (ap->a_ncookies == NULL) {
459 idp->cookies = NULL;
460 } else {
461 /*
462 * Guess the number of cookies needed.
463 */
464 ncookies = uio->uio_resid / 16;
465 MALLOC(cookies, u_long *, ncookies * sizeof(u_int), M_TEMP,
466 M_WAITOK);
467 idp->cookies = cookies;
468 idp->ncookies = ncookies;
469 }
470 idp->eofflag = 1;
471 idp->curroff = uio->uio_offset;
472
473 if ((entryoffsetinblock = idp->curroff & bmask) &&
474 (error = cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp))) {
475 FREE(idp, M_TEMP);
476 return (error);
477 }
478 endsearch = dp->i_size;
479
480 while (idp->curroff < endsearch) {
481 /*
482 * If offset is on a block boundary,
483 * read the next directory block.
484 * Release previous if it exists.
485 */
486 if ((idp->curroff & bmask) == 0) {
487 if (bp != NULL)
488 brelse(bp);
489 if (error =
490 cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp))
491 break;
492 entryoffsetinblock = 0;
493 }
494 /*
495 * Get pointer to next entry.
496 */
497 ep = (struct iso_directory_record *)
498 ((char *)bp->b_data + entryoffsetinblock);
499
500 reclen = isonum_711(ep->length);
501 if (reclen == 0) {
502 /* skip to next block, if any */
503 idp->curroff =
504 (idp->curroff & ~bmask) + imp->logical_block_size;
505 continue;
506 }
507
508 if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
509 error = EINVAL;
510 /* illegal entry, stop */
511 break;
512 }
513
514 if (entryoffsetinblock + reclen > imp->logical_block_size) {
515 error = EINVAL;
516 /* illegal directory, so stop looking */
517 break;
518 }
519
520 idp->current.d_namlen = isonum_711(ep->name_len);
521
522 if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
523 error = EINVAL;
524 /* illegal entry, stop */
525 break;
526 }
527
528 if (isonum_711(ep->flags)&2)
529 idp->current.d_fileno = isodirino(ep, imp);
530 else
531 idp->current.d_fileno = dbtob(bp->b_blkno) +
532 entryoffsetinblock;
533
534 idp->curroff += reclen;
535
536 switch (imp->iso_ftype) {
537 case ISO_FTYPE_RRIP:
538 cd9660_rrip_getname(ep,idp->current.d_name, &namelen,
539 &idp->current.d_fileno,imp);
540 idp->current.d_namlen = (u_char)namelen;
541 if (idp->current.d_namlen)
542 error = iso_uiodir(idp,&idp->current,idp->curroff);
543 break;
544 default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA*/
545 strcpy(idp->current.d_name,"..");
546 switch (ep->name[0]) {
547 case 0:
548 idp->current.d_namlen = 1;
549 error = iso_uiodir(idp,&idp->current,idp->curroff);
550 break;
551 case 1:
552 idp->current.d_namlen = 2;
553 error = iso_uiodir(idp,&idp->current,idp->curroff);
554 break;
555 default:
556 isofntrans(ep->name,idp->current.d_namlen,
557 idp->current.d_name, &namelen,
558 imp->iso_ftype == ISO_FTYPE_9660,
559 isonum_711(ep->flags)&4);
560 idp->current.d_namlen = (u_char)namelen;
561 if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
562 error = iso_shipdir(idp);
563 else
564 error = iso_uiodir(idp,&idp->current,idp->curroff);
565 break;
566 }
567 }
568 if (error)
569 break;
570
571 entryoffsetinblock += reclen;
572 }
573
574 if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
575 idp->current.d_namlen = 0;
576 error = iso_shipdir(idp);
577 }
578 if (error < 0)
579 error = 0;
580
581 if (ap->a_ncookies != NULL) {
582 if (error)
583 free(cookies, M_TEMP);
584 else {
585 /*
586 * Work out the number of cookies actually used.
587 */
588 *ap->a_ncookies = ncookies - idp->ncookies;
589 *ap->a_cookies = cookies;
590 }
591 }
592
593 if (bp)
594 brelse (bp);
595
596 uio->uio_offset = idp->uio_off;
597 *ap->a_eofflag = idp->eofflag;
598
599 FREE(idp, M_TEMP);
600
601 return (error);
602}
603
604/*
605 * Return target name of a symbolic link
606 * Shouldn't we get the parent vnode and read the data from there?
607 * This could eventually result in deadlocks in cd9660_lookup.
608 * But otherwise the block read here is in the block buffer two times.
609 */
610typedef struct iso_directory_record ISODIR;
611typedef struct iso_node ISONODE;
612typedef struct iso_mnt ISOMNT;
613static int
614cd9660_readlink(ap)
615 struct vop_readlink_args /* {
616 struct vnode *a_vp;
617 struct uio *a_uio;
618 struct ucred *a_cred;
619 } */ *ap;
620{
621 ISONODE *ip;
622 ISODIR *dirp;
623 ISOMNT *imp;
624 struct buf *bp;
625 struct uio *uio;
626 u_short symlen;
627 int error;
628 char *symname;
629
630 ip = VTOI(ap->a_vp);
631 imp = ip->i_mnt;
632 uio = ap->a_uio;
633
634 if (imp->iso_ftype != ISO_FTYPE_RRIP)
635 return (EINVAL);
636
637 /*
638 * Get parents directory record block that this inode included.
639 */
640 error = bread(imp->im_devvp,
641 (ip->i_number >> imp->im_bshift) <<
642 (imp->im_bshift - DEV_BSHIFT),
643 imp->logical_block_size, NOCRED, &bp);
644 if (error) {
645 brelse(bp);
646 return (EINVAL);
647 }
648
649 /*
650 * Setup the directory pointer for this inode
651 */
652 dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
653
654 /*
655 * Just make sure, we have a right one....
656 * 1: Check not cross boundary on block
657 */
658 if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
659 > (unsigned)imp->logical_block_size) {
660 brelse(bp);
661 return (EINVAL);
662 }
663
664 /*
665 * Now get a buffer
666 * Abuse a namei buffer for now.
667 */
668 if (uio->uio_segflg == UIO_SYSSPACE)
669 symname = uio->uio_iov->iov_base;
670 else
671 symname = zalloc(namei_zone);
672
673 /*
674 * Ok, we just gathering a symbolic name in SL record.
675 */
676 if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
677 if (uio->uio_segflg != UIO_SYSSPACE)
678 zfree(namei_zone, symname);
679 brelse(bp);
680 return (EINVAL);
681 }
682 /*
683 * Don't forget before you leave from home ;-)
684 */
685 brelse(bp);
686
687 /*
688 * return with the symbolic name to caller's.
689 */
690 if (uio->uio_segflg != UIO_SYSSPACE) {
691 error = uiomove(symname, symlen, uio);
692 zfree(namei_zone, symname);
693 return (error);
694 }
695 uio->uio_resid -= symlen;
696 uio->uio_iov->iov_base += symlen;
697 uio->uio_iov->iov_len -= symlen;
698 return (0);
699}
700
701/*
702 * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
703 * done. If a buffer has been saved in anticipation of a CREATE, delete it.
704 */
705static int
706cd9660_abortop(ap)
707 struct vop_abortop_args /* {
708 struct vnode *a_dvp;
709 struct componentname *a_cnp;
710 } */ *ap;
711{
712 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
713 zfree(namei_zone, ap->a_cnp->cn_pnbuf);
714 return (0);
715}
716
717/*
721 * Lock an inode.
722 */
723static int
724cd9660_lock(ap)
725 struct vop_lock_args /* {
726 struct vnode *a_vp;
727 int a_flags;
728 struct proc *a_p;
729 } */ *ap;
730{
731 struct vnode *vp = ap->a_vp;
732
733 return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, &vp->v_interlock,
734 ap->a_p));
735}
736
737/*
738 * Unlock an inode.
739 */
740static int
741cd9660_unlock(ap)
742 struct vop_unlock_args /* {
743 struct vnode *a_vp;
744 int a_flags;
745 struct proc *a_p;
746 } */ *ap;
747{
748 struct vnode *vp = ap->a_vp;
749
750 return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE,
751 &vp->v_interlock, ap->a_p));
752}
753
754/*
755 * Calculate the logical to physical mapping if not done already,
756 * then call the device strategy routine.
757 */
758static int
759cd9660_strategy(ap)
760 struct vop_strategy_args /* {
761 struct buf *a_bp;
762 } */ *ap;
763{
764 register struct buf *bp = ap->a_bp;
765 register struct vnode *vp = bp->b_vp;
766 register struct iso_node *ip;
767 int error;
768
769 ip = VTOI(vp);
770 if (vp->v_type == VBLK || vp->v_type == VCHR)
771 panic("cd9660_strategy: spec");
772 if (bp->b_blkno == bp->b_lblkno) {
773 if ((error =
774 VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL, NULL))) {
775 bp->b_error = error;
776 bp->b_flags |= B_ERROR;
777 biodone(bp);
778 return (error);
779 }
780 if ((long)bp->b_blkno == -1)
781 clrbuf(bp);
782 }
783 if ((long)bp->b_blkno == -1) {
784 biodone(bp);
785 return (0);
786 }
787 vp = ip->i_devvp;
788 bp->b_dev = vp->v_rdev;
789 VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
790 return (0);
791}
792
793/*
794 * Print out the contents of an inode.
795 */
796static int
797cd9660_print(ap)
798 struct vop_print_args /* {
799 struct vnode *a_vp;
800 } */ *ap;
801{
802
803 printf("tag VT_ISOFS, isofs vnode\n");
804 return (0);
805}
806
807/*
718 * Calculate the logical to physical mapping if not done already,
719 * then call the device strategy routine.
720 */
721static int
722cd9660_strategy(ap)
723 struct vop_strategy_args /* {
724 struct buf *a_bp;
725 } */ *ap;
726{
727 register struct buf *bp = ap->a_bp;
728 register struct vnode *vp = bp->b_vp;
729 register struct iso_node *ip;
730 int error;
731
732 ip = VTOI(vp);
733 if (vp->v_type == VBLK || vp->v_type == VCHR)
734 panic("cd9660_strategy: spec");
735 if (bp->b_blkno == bp->b_lblkno) {
736 if ((error =
737 VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL, NULL))) {
738 bp->b_error = error;
739 bp->b_flags |= B_ERROR;
740 biodone(bp);
741 return (error);
742 }
743 if ((long)bp->b_blkno == -1)
744 clrbuf(bp);
745 }
746 if ((long)bp->b_blkno == -1) {
747 biodone(bp);
748 return (0);
749 }
750 vp = ip->i_devvp;
751 bp->b_dev = vp->v_rdev;
752 VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
753 return (0);
754}
755
756/*
757 * Print out the contents of an inode.
758 */
759static int
760cd9660_print(ap)
761 struct vop_print_args /* {
762 struct vnode *a_vp;
763 } */ *ap;
764{
765
766 printf("tag VT_ISOFS, isofs vnode\n");
767 return (0);
768}
769
770/*
808 * Check for a locked inode.
809 */
810int
811cd9660_islocked(ap)
812 struct vop_islocked_args /* {
813 struct vnode *a_vp;
814 } */ *ap;
815{
816
817 return (lockstatus(&VTOI(ap->a_vp)->i_lock));
818}
819
820/*
821 * Return POSIX pathconf information applicable to cd9660 filesystems.
822 */
823int
824cd9660_pathconf(ap)
825 struct vop_pathconf_args /* {
826 struct vnode *a_vp;
827 int a_name;
828 register_t *a_retval;
829 } */ *ap;
830{
831
832 switch (ap->a_name) {
833 case _PC_LINK_MAX:
834 *ap->a_retval = 1;
835 return (0);
836 case _PC_NAME_MAX:
837 if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP)
838 *ap->a_retval = NAME_MAX;
839 else
840 *ap->a_retval = 37;
841 return (0);
842 case _PC_PATH_MAX:
843 *ap->a_retval = PATH_MAX;
844 return (0);
845 case _PC_PIPE_BUF:
846 *ap->a_retval = PIPE_BUF;
847 return (0);
848 case _PC_CHOWN_RESTRICTED:
849 *ap->a_retval = 1;
850 return (0);
851 case _PC_NO_TRUNC:
852 *ap->a_retval = 1;
853 return (0);
854 default:
855 return (EINVAL);
856 }
857 /* NOTREACHED */
858}
859
860/*
861 * Global vfs data structures for cd9660
862 */
863vop_t **cd9660_vnodeop_p;
864struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
865 { &vop_default_desc, (vop_t *) vn_default_error },
866 { &vop_abortop_desc, (vop_t *) cd9660_abortop },
867 { &vop_access_desc, (vop_t *) cd9660_access },
868 { &vop_bmap_desc, (vop_t *) cd9660_bmap },
869 { &vop_cachedlookup_desc, (vop_t *) cd9660_lookup },
870 { &vop_getattr_desc, (vop_t *) cd9660_getattr },
871 { &vop_inactive_desc, (vop_t *) cd9660_inactive },
771 * Return POSIX pathconf information applicable to cd9660 filesystems.
772 */
773int
774cd9660_pathconf(ap)
775 struct vop_pathconf_args /* {
776 struct vnode *a_vp;
777 int a_name;
778 register_t *a_retval;
779 } */ *ap;
780{
781
782 switch (ap->a_name) {
783 case _PC_LINK_MAX:
784 *ap->a_retval = 1;
785 return (0);
786 case _PC_NAME_MAX:
787 if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP)
788 *ap->a_retval = NAME_MAX;
789 else
790 *ap->a_retval = 37;
791 return (0);
792 case _PC_PATH_MAX:
793 *ap->a_retval = PATH_MAX;
794 return (0);
795 case _PC_PIPE_BUF:
796 *ap->a_retval = PIPE_BUF;
797 return (0);
798 case _PC_CHOWN_RESTRICTED:
799 *ap->a_retval = 1;
800 return (0);
801 case _PC_NO_TRUNC:
802 *ap->a_retval = 1;
803 return (0);
804 default:
805 return (EINVAL);
806 }
807 /* NOTREACHED */
808}
809
810/*
811 * Global vfs data structures for cd9660
812 */
813vop_t **cd9660_vnodeop_p;
814struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
815 { &vop_default_desc, (vop_t *) vn_default_error },
816 { &vop_abortop_desc, (vop_t *) cd9660_abortop },
817 { &vop_access_desc, (vop_t *) cd9660_access },
818 { &vop_bmap_desc, (vop_t *) cd9660_bmap },
819 { &vop_cachedlookup_desc, (vop_t *) cd9660_lookup },
820 { &vop_getattr_desc, (vop_t *) cd9660_getattr },
821 { &vop_inactive_desc, (vop_t *) cd9660_inactive },
872 { &vop_islocked_desc, (vop_t *) cd9660_islocked },
873 { &vop_lock_desc, (vop_t *) cd9660_lock },
822 { &vop_islocked_desc, (vop_t *) vop_stdislocked },
823 { &vop_lock_desc, (vop_t *) vop_stdlock },
874 { &vop_lookup_desc, (vop_t *) vfs_cache_lookup },
875 { &vop_pathconf_desc, (vop_t *) cd9660_pathconf },
876 { &vop_print_desc, (vop_t *) cd9660_print },
877 { &vop_read_desc, (vop_t *) cd9660_read },
878 { &vop_readdir_desc, (vop_t *) cd9660_readdir },
879 { &vop_readlink_desc, (vop_t *) cd9660_readlink },
880 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim },
881 { &vop_setattr_desc, (vop_t *) cd9660_setattr },
882 { &vop_strategy_desc, (vop_t *) cd9660_strategy },
824 { &vop_lookup_desc, (vop_t *) vfs_cache_lookup },
825 { &vop_pathconf_desc, (vop_t *) cd9660_pathconf },
826 { &vop_print_desc, (vop_t *) cd9660_print },
827 { &vop_read_desc, (vop_t *) cd9660_read },
828 { &vop_readdir_desc, (vop_t *) cd9660_readdir },
829 { &vop_readlink_desc, (vop_t *) cd9660_readlink },
830 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim },
831 { &vop_setattr_desc, (vop_t *) cd9660_setattr },
832 { &vop_strategy_desc, (vop_t *) cd9660_strategy },
883 { &vop_unlock_desc, (vop_t *) cd9660_unlock },
833 { &vop_unlock_desc, (vop_t *) vop_stdunlock },
884 { NULL, NULL }
885};
886static struct vnodeopv_desc cd9660_vnodeop_opv_desc =
887 { &cd9660_vnodeop_p, cd9660_vnodeop_entries };
888VNODEOP_SET(cd9660_vnodeop_opv_desc);
889
890/*
891 * Special device vnode ops
892 */
893vop_t **cd9660_specop_p;
894struct vnodeopv_entry_desc cd9660_specop_entries[] = {
895 { &vop_default_desc, (vop_t *) spec_vnoperate },
896 { &vop_access_desc, (vop_t *) cd9660_access },
897 { &vop_getattr_desc, (vop_t *) cd9660_getattr },
898 { &vop_inactive_desc, (vop_t *) cd9660_inactive },
834 { NULL, NULL }
835};
836static struct vnodeopv_desc cd9660_vnodeop_opv_desc =
837 { &cd9660_vnodeop_p, cd9660_vnodeop_entries };
838VNODEOP_SET(cd9660_vnodeop_opv_desc);
839
840/*
841 * Special device vnode ops
842 */
843vop_t **cd9660_specop_p;
844struct vnodeopv_entry_desc cd9660_specop_entries[] = {
845 { &vop_default_desc, (vop_t *) spec_vnoperate },
846 { &vop_access_desc, (vop_t *) cd9660_access },
847 { &vop_getattr_desc, (vop_t *) cd9660_getattr },
848 { &vop_inactive_desc, (vop_t *) cd9660_inactive },
899 { &vop_islocked_desc, (vop_t *) cd9660_islocked },
900 { &vop_lock_desc, (vop_t *) cd9660_lock },
849 { &vop_islocked_desc, (vop_t *) vop_stdislocked },
850 { &vop_lock_desc, (vop_t *) vop_stdlock },
901 { &vop_print_desc, (vop_t *) cd9660_print },
902 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim },
903 { &vop_setattr_desc, (vop_t *) cd9660_setattr },
851 { &vop_print_desc, (vop_t *) cd9660_print },
852 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim },
853 { &vop_setattr_desc, (vop_t *) cd9660_setattr },
904 { &vop_unlock_desc, (vop_t *) cd9660_unlock },
854 { &vop_unlock_desc, (vop_t *) vop_stdunlock },
905 { NULL, NULL }
906};
907static struct vnodeopv_desc cd9660_specop_opv_desc =
908 { &cd9660_specop_p, cd9660_specop_entries };
909VNODEOP_SET(cd9660_specop_opv_desc);
910
911vop_t **cd9660_fifoop_p;
912struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
913 { &vop_default_desc, (vop_t *) fifo_vnoperate },
914 { &vop_access_desc, (vop_t *) cd9660_access },
915 { &vop_getattr_desc, (vop_t *) cd9660_getattr },
916 { &vop_inactive_desc, (vop_t *) cd9660_inactive },
855 { NULL, NULL }
856};
857static struct vnodeopv_desc cd9660_specop_opv_desc =
858 { &cd9660_specop_p, cd9660_specop_entries };
859VNODEOP_SET(cd9660_specop_opv_desc);
860
861vop_t **cd9660_fifoop_p;
862struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
863 { &vop_default_desc, (vop_t *) fifo_vnoperate },
864 { &vop_access_desc, (vop_t *) cd9660_access },
865 { &vop_getattr_desc, (vop_t *) cd9660_getattr },
866 { &vop_inactive_desc, (vop_t *) cd9660_inactive },
917 { &vop_islocked_desc, (vop_t *) cd9660_islocked },
918 { &vop_lock_desc, (vop_t *) cd9660_lock },
867 { &vop_islocked_desc, (vop_t *) vop_stdislocked },
868 { &vop_lock_desc, (vop_t *) vop_stdlock },
919 { &vop_print_desc, (vop_t *) cd9660_print },
920 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim },
921 { &vop_setattr_desc, (vop_t *) cd9660_setattr },
869 { &vop_print_desc, (vop_t *) cd9660_print },
870 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim },
871 { &vop_setattr_desc, (vop_t *) cd9660_setattr },
922 { &vop_unlock_desc, (vop_t *) cd9660_unlock },
872 { &vop_unlock_desc, (vop_t *) vop_stdunlock },
923 { NULL, NULL }
924};
925static struct vnodeopv_desc cd9660_fifoop_opv_desc =
926 { &cd9660_fifoop_p, cd9660_fifoop_entries };
927
928VNODEOP_SET(cd9660_fifoop_opv_desc);
873 { NULL, NULL }
874};
875static struct vnodeopv_desc cd9660_fifoop_opv_desc =
876 { &cd9660_fifoop_p, cd9660_fifoop_entries };
877
878VNODEOP_SET(cd9660_fifoop_opv_desc);