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);
|