1 /* 2 * $Id: $ 3 */ 4 #include "sys/param.h" 5 #include "systm.h" 6 #include "kernel.h" 7 #include "sys/file.h" 8 #include "sys/stat.h" 9 #include "sys/errno.h" 10 #include "buf.h" 11 #include "proc.h" 12 #include "resourcevar.h" 13 #include "sys/mount.h" 14 #include "uio.h" 15 #include "namei.h" 16 #include "vnode.h" 17 #include "specdev.h" 18 #include "fifo.h" 19 #include "malloc.h" 20 #include "sys/dir.h" 21 #include "prototypes.h" 22 23 #include "iso.h" 24 #include "isofs_node.h" 25 #include "iso_rrip.h" 26 27 /* 28 * Open called. 29 * 30 * Nothing to do. 31 */ 32 /* ARGSUSED */ 33 isofs_open(vp, mode, cred, p) 34 struct vnode *vp; 35 int mode; 36 struct ucred *cred; 37 struct proc *p; 38 { 39 return (0); 40 } 41 42 /* 43 * Close called 44 * 45 * Update the times on the inode on writeable file systems. 46 */ 47 /* ARGSUSED */ 48 isofs_close(vp, fflag, cred, p) 49 struct vnode *vp; 50 int fflag; 51 struct ucred *cred; 52 struct proc *p; 53 { 54 return (0); 55 } 56 57 /* 58 * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. 59 * The mode is shifted to select the owner/group/other fields. The 60 * super user is granted all permissions. 61 */ 62 isofs_access(vp, mode, cred, p) 63 struct vnode *vp; 64 register int mode; 65 struct ucred *cred; 66 struct proc *p; 67 { 68 return (0); 69 } 70 71 /* ARGSUSED */ 72 isofs_getattr(vp, vap, cred, p) 73 struct vnode *vp; 74 register struct vattr *vap; 75 struct ucred *cred; 76 struct proc *p; 77 { 78 register struct iso_node *ip = VTOI(vp); 79 int i; 80 81 vap->va_fsid = ip->i_dev; 82 vap->va_fileid = ip->i_number; 83 /*if (vp->v_type == VDIR) 84 vap->va_nlink = 2; 85 else 86 vap->va_nlink = 1; */ 87 88 vap->va_nlink = ip->inode.iso_links; 89 vap->va_mode = ip->inode.iso_mode; 90 /*printf("getattr mode %x ", vap->va_mode);*/ 91 vap->va_uid = ip->inode.iso_uid; 92 vap->va_gid = ip->inode.iso_gid; 93 vap->va_atime= ip->inode.iso_atime; 94 vap->va_mtime= ip->inode.iso_mtime; 95 vap->va_ctime= ip->inode.iso_ctime; 96 97 vap->va_rdev = ip->inode.iso_dev; 98 vap->va_size = ip->i_size; 99 vap->va_size_rsv = 0; 100 vap->va_flags = 0; 101 vap->va_gen = 1; 102 vap->va_blocksize = ip->i_mnt->logical_block_size; 103 vap->va_bytes = ip->i_size; 104 vap->va_bytes_rsv = 0; 105 vap->va_type = vp->v_type; 106 return (0); 107 } 108 109 /* 110 * Vnode op for reading. 111 */ 112 /* ARGSUSED */ 113 isofs_read(vp, uio, ioflag, cred) 114 struct vnode *vp; 115 register struct uio *uio; 116 int ioflag; 117 struct ucred *cred; 118 { 119 register struct iso_node *ip = VTOI(vp); 120 register struct iso_mnt *imp; 121 struct buf *bp; 122 daddr_t lbn, bn, rablock; 123 int size, diff, error = 0; 124 long n, on, type; 125 126 #ifdef DIAGNOSTICx 127 if (uio->uio_rw != UIO_READ) 128 panic("isofs_read mode"); 129 type = ip->i_mode & IFMT; 130 if (type != IFDIR && type != IFREG && type != IFLNK) 131 panic("isofs_read type"); 132 #endif 133 if (uio->uio_resid == 0) 134 return (0); 135 if (uio->uio_offset < 0) 136 return (EINVAL); 137 ip->i_flag |= IACC; 138 imp = ip->i_mnt; 139 do { 140 lbn = iso_lblkno(imp, uio->uio_offset); 141 on = iso_blkoff(imp, uio->uio_offset); 142 n = min((unsigned)(imp->im_bsize - on), uio->uio_resid); 143 diff = ip->i_size - uio->uio_offset; 144 if (diff <= 0) 145 return (0); 146 if (diff < n) 147 n = diff; 148 size = iso_blksize(imp, ip, lbn); 149 rablock = lbn + 1; 150 if (vp->v_lastr + 1 == lbn && 151 iso_lblktosize(imp, rablock) < ip->i_size) 152 error = breada(ITOV(ip), lbn, size, rablock, 153 iso_blksize(imp, ip, rablock), NOCRED, &bp); 154 else 155 error = bread(ITOV(ip), lbn, size, NOCRED, &bp); 156 vp->v_lastr = lbn; 157 n = min(n, size - bp->b_resid); 158 if (error) { 159 brelse(bp); 160 return (error); 161 } 162 163 error = uiomove(bp->b_un.b_addr + on, (int)n, uio); 164 if (n + on == imp->im_bsize || uio->uio_offset == ip->i_size) 165 bp->b_flags |= B_AGE; 166 brelse(bp); 167 } while (error == 0 && uio->uio_resid > 0 && n != 0); 168 return (error); 169 } 170 171 /* ARGSUSED */ 172 isofs_ioctl(vp, com, data, fflag, cred, p) 173 struct vnode *vp; 174 int com; 175 caddr_t data; 176 int fflag; 177 struct ucred *cred; 178 struct proc *p; 179 { 180 return (ENOTTY); 181 } 182 183 /* ARGSUSED */ 184 isofs_select(vp, which, fflags, cred, p) 185 struct vnode *vp; 186 int which, fflags; 187 struct ucred *cred; 188 struct proc *p; 189 { 190 191 /* 192 * We should really check to see if I/O is possible. 193 */ 194 return (1); 195 } 196 197 /* 198 * Mmap a file 199 * 200 * NB Currently unsupported. 201 */ 202 /* ARGSUSED */ 203 isofs_mmap(vp, fflags, cred, p) 204 struct vnode *vp; 205 int fflags; 206 struct ucred *cred; 207 struct proc *p; 208 { 209 210 return (EINVAL); 211 } 212 213 /* 214 * Seek on a file 215 * 216 * Nothing to do, so just return. 217 */ 218 /* ARGSUSED */ 219 isofs_seek(vp, oldoff, newoff, cred) 220 struct vnode *vp; 221 off_t oldoff, newoff; 222 struct ucred *cred; 223 { 224 225 return (0); 226 } 227 228 /* 229 * Vnode op for readdir 230 */ 231 isofs_readdir(vp, uio, cred, eofflagp) 232 struct vnode *vp; 233 register struct uio *uio; 234 struct ucred *cred; 235 int *eofflagp; 236 { 237 struct dirent dirent; 238 int iso_offset; 239 int entryoffsetinblock; 240 int error = 0; 241 int endsearch; 242 struct iso_directory_record *ep; 243 int reclen; 244 struct iso_mnt *imp; 245 struct iso_node *ip; 246 struct buf *bp = NULL; 247 int i; 248 int end_flag = 0; 249 ISO_RRIP_ANALYZE ana; 250 251 ip = VTOI (vp); 252 imp = ip->i_mnt; 253 254 iso_offset = uio->uio_offset; 255 256 entryoffsetinblock = iso_blkoff(imp, iso_offset); 257 if (entryoffsetinblock != 0) { 258 if (error = iso_blkatoff(ip, iso_offset, (char **)0, &bp)) 259 return (error); 260 } 261 262 endsearch = ip->i_size; 263 264 while (iso_offset < endsearch && uio->uio_resid > 0) { 265 /* 266 * If offset is on a block boundary, 267 * read the next directory block. 268 * Release previous if it exists. 269 */ 270 271 if (iso_blkoff(imp, iso_offset) == 0) { 272 if (bp != NULL) 273 brelse(bp); 274 if (error = iso_blkatoff(ip, iso_offset, 275 (char **)0, &bp)) 276 return (error); 277 entryoffsetinblock = 0; 278 } 279 /* 280 * Get pointer to next entry. 281 */ 282 283 ep = (struct iso_directory_record *) 284 (bp->b_un.b_addr + entryoffsetinblock); 285 286 reclen = isonum_711 (ep->length); 287 if (reclen == 0) { 288 /* skip to next block, if any */ 289 iso_offset = roundup (iso_offset, 290 imp->logical_block_size); 291 continue; 292 } 293 294 if (reclen < sizeof (struct iso_directory_record)) 295 /* illegal entry, stop */ 296 break; 297 298 /* 10 Aug 92*/ if (entryoffsetinblock + reclen -1 >= imp->logical_block_size) 299 /* illegal directory, so stop looking */ 300 break; 301 302 dirent.d_fileno = iso_lblktosize(imp, isonum_733 (ep->extent)) 303 + entryoffsetinblock; 304 dirent.d_namlen = isonum_711 (ep->name_len); 305 306 if (reclen < sizeof (struct iso_directory_record) 307 + dirent.d_namlen) 308 /* illegal entry, stop */ 309 break; 310 311 /* 312 * 313 */ 314 switch (ep->name[0]) { 315 case 0: 316 dirent.d_name[0] = '.'; 317 dirent.d_namlen = 1; 318 break; 319 case 1: 320 dirent.d_name[0] = '.'; 321 dirent.d_name[1] = '.'; 322 dirent.d_namlen = 2; 323 break; 324 default: 325 switch ( imp->iso_ftype ) { 326 case ISO_FTYPE_RRIP: 327 isofs_rrip_getname( ep, dirent.d_name, &dirent.d_namlen ); 328 break; 329 case ISO_FTYPE_9660: 330 isofntrans(ep->name, dirent.d_namlen, dirent.d_name, &dirent.d_namlen); 331 break; 332 default: 333 break; 334 } 335 break; 336 } 337 338 dirent.d_name[dirent.d_namlen] = 0; 339 dirent.d_reclen = DIRSIZ (&dirent); 340 341 if (uio->uio_resid < dirent.d_reclen) 342 break; 343 344 if (error = uiomove (&dirent, dirent.d_reclen, uio)) 345 break; 346 347 iso_offset += reclen; 348 entryoffsetinblock += reclen; 349 } 350 351 if (bp) 352 brelse (bp); 353 354 if (end_flag || (VTOI(vp)->i_size - iso_offset) <= 0) 355 *eofflagp = 1; 356 else 357 *eofflagp = 0; 358 359 uio->uio_offset = iso_offset; 360 361 return (error); 362 } 363 364 /* 365 * Return target name of a symbolic link 366 */ 367 typedef struct iso_directory_record ISODIR; 368 typedef struct iso_node ISONODE; 369 typedef struct iso_mnt ISOMNT; 370 int isofs_readlink(vp, uio, cred) 371 struct vnode *vp; 372 struct uio *uio; 373 struct ucred *cred; 374 { 375 ISONODE *ip; 376 ISODIR *dirp; 377 ISOMNT *imp; 378 struct buf *bp; 379 int symlen; 380 int error, rv; 381 char symname[NAME_MAX]; 382 383 ip = VTOI( vp ); 384 imp = ip->i_mnt; 385 /*printf("readlink mode %x ", ip->inode.iso_mode);*/ 386 /* 387 * Get parents directory record block that this inode included. 388 */ 389 error = bread( imp->im_devvp, 390 (daddr_t)(( ip->iso_parent_ext + (ip->iso_parent >> 11 ) ) 391 * imp->im_bsize / DEV_BSIZE ), 392 imp->im_bsize, 393 NOCRED, 394 &bp ); 395 if ( error ) { 396 return( EINVAL ); 397 } 398 399 /* 400 * Setup the directory pointer for this inode 401 */ 402 403 dirp = (ISODIR *)(bp->b_un.b_addr + ( ip->iso_parent & 0x7ff ) ); 404 #ifdef DEBUG 405 printf("lbn=%d[base=%d,off=%d,bsize=%d,DEV_BSIZE=%d], dirp= %08x, b_addr=%08x, offset=%08x(%08x)\n", 406 (daddr_t)(( ip->iso_parent_ext + (ip->iso_parent >> 12 ) ) * imp->im_bsize / DEV_BSIZE ), 407 ip->iso_parent_ext, 408 (ip->iso_parent >> 11 ), 409 imp->im_bsize, 410 DEV_BSIZE, 411 dirp, 412 bp->b_un.b_addr, 413 ip->iso_parent, 414 ip->iso_parent & 0x7ff ); 415 #endif 416 417 /* 418 * Just make sure, we have a right one.... 419 * 1: Check not cross boundary on block 420 * 2: Check number of inode 421 */ 422 if ( (ip->iso_parent & 0x7ff) + isonum_711( dirp->length ) >= 423 imp->im_bsize ) { 424 brelse ( bp ); 425 return( EINVAL ); 426 } 427 /*if ( isonum_733(dirp->extent) != ip->i_number ) { 428 brelse ( bp ); 429 return( EINVAL ); 430 }*/ 431 432 /* 433 * Ok, we just gathering a Symbolick name in SL record. 434 */ 435 rv = isofs_rrip_getsymname(vp, dirp, symname, &symlen); 436 brelse (bp); 437 438 if (rv == 0) 439 return( EINVAL ); 440 441 /* 442 * return with the Symbolic name to caller's. 443 */ 444 return ( uiomove( symname, symlen, uio ) ); 445 } 446 447 /* 448 * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually 449 * done. If a buffer has been saved in anticipation of a CREATE, delete it. 450 */ 451 /* ARGSUSED */ 452 isofs_abortop(ndp) 453 struct nameidata *ndp; 454 { 455 456 if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF) 457 FREE(ndp->ni_pnbuf, M_NAMEI); 458 return (0); 459 } 460 461 /* 462 * Lock an inode. 463 */ 464 isofs_lock(vp) 465 struct vnode *vp; 466 { 467 register struct iso_node *ip = VTOI(vp); 468 469 ISO_ILOCK(ip); 470 return (0); 471 } 472 473 /* 474 * Unlock an inode. 475 */ 476 isofs_unlock(vp) 477 struct vnode *vp; 478 { 479 register struct iso_node *ip = VTOI(vp); 480 481 if (!(ip->i_flag & ILOCKED)) 482 panic("isofs_unlock NOT LOCKED"); 483 ISO_IUNLOCK(ip); 484 return (0); 485 } 486 487 /* 488 * Check for a locked inode. 489 */ 490 isofs_islocked(vp) 491 struct vnode *vp; 492 { 493 494 if (VTOI(vp)->i_flag & ILOCKED) 495 return (1); 496 return (0); 497 } 498 499 /* 500 * Calculate the logical to physical mapping if not done already, 501 * then call the device strategy routine. 502 */ 503 504 isofs_strategy(bp) 505 register struct buf *bp; 506 { 507 register struct iso_node *ip = VTOI(bp->b_vp); 508 struct vnode *vp; 509 int error; 510 511 if (bp->b_vp->v_type == VBLK || bp->b_vp->v_type == VCHR) 512 panic("isofs_strategy: spec"); 513 if (bp->b_blkno == bp->b_lblkno) { 514 if (error = iso_bmap(ip, bp->b_lblkno, &bp->b_blkno)) 515 return (error); 516 if ((long)bp->b_blkno == -1) 517 clrbuf(bp); 518 } 519 if ((long)bp->b_blkno == -1) { 520 biodone(bp); 521 return (0); 522 } 523 vp = ip->i_devvp; 524 bp->b_dev = vp->v_rdev; 525 (*(vp->v_op->vop_strategy))(bp); 526 return (0); 527 } 528 529 /* 530 * Print out the contents of an inode. 531 */ 532 isofs_print(vp) 533 struct vnode *vp; 534 { 535 printf ("tag VT_ISOFS, isofs vnode\n"); 536 } 537 538 extern int _ENODEV_ (), nullop(); 539 540 /* 541 * Global vfs data structures for isofs 542 */ 543 struct vnodeops isofs_vnodeops = { 544 isofs_lookup, /* lookup */ 545 (void *)_ENODEV_, /* create */ 546 (void *)_ENODEV_, /* mknod */ 547 isofs_open, /* open */ 548 isofs_close, /* close */ 549 isofs_access, /* access */ 550 isofs_getattr, /* getattr */ 551 (void *)_ENODEV_, /* setattr */ 552 isofs_read, /* read */ 553 (void *)_ENODEV_, /* write */ 554 isofs_ioctl, /* ioctl */ 555 isofs_select, /* select */ 556 isofs_mmap, /* mmap */ 557 (void *)nullop, /* fsync */ 558 isofs_seek, /* seek */ 559 (void *)_ENODEV_, /* remove */ 560 (void *)_ENODEV_, /* link */ 561 (void *)_ENODEV_, /* rename */ 562 (void *)_ENODEV_, /* mkdir */ 563 (void *)_ENODEV_, /* rmdir */ 564 (void *)_ENODEV_, /* symlink */ 565 isofs_readdir, /* readdir */ 566 isofs_readlink, /* readlink */ 567 isofs_abortop, /* abortop */ 568 isofs_inactive, /* inactive */ 569 isofs_reclaim, /* reclaim */ 570 isofs_lock, /* lock */ 571 isofs_unlock, /* unlock */ 572 (void *)_ENODEV_, /* bmap */ 573 isofs_strategy, /* strategy */ 574 isofs_print, /* print */ 575 isofs_islocked, /* islocked */ 576 (void *)_ENODEV_, /* advlock */ 577 }; 578 579 struct vnodeops spec_isonodeops = { 580 spec_lookup, /* lookup */ 581 spec_create, /* create */ 582 spec_mknod, /* mknod */ 583 spec_open, /* open */ 584 spec_close, /* close */ 585 isofs_access, /* access */ 586 isofs_getattr, /* getattr */ 587 (void *)nullop, /* setattr -- XXX not enodev so writable*/ 588 spec_read, /* read */ 589 spec_write, /* write */ 590 spec_ioctl, /* ioctl */ 591 spec_select, /* select */ 592 spec_mmap, /* mmap */ 593 spec_fsync, /* fsync */ 594 spec_seek, /* seek */ 595 spec_remove, /* remove */ 596 spec_link, /* link */ 597 spec_rename, /* rename */ 598 spec_mkdir, /* mkdir */ 599 spec_rmdir, /* rmdir */ 600 spec_symlink, /* symlink */ 601 spec_readdir, /* readdir */ 602 spec_readlink, /* readlink */ 603 spec_abortop, /* abortop */ 604 isofs_inactive, /* inactive */ 605 isofs_reclaim, /* reclaim */ 606 isofs_lock, /* lock */ 607 isofs_unlock, /* unlock */ 608 spec_bmap, /* bmap */ 609 spec_strategy, /* strategy */ 610 isofs_print, /* print */ 611 isofs_islocked, /* islocked */ 612 spec_advlock, /* advlock */ 613 }; 614