1 /* $NetBSD: spec_vnops.c,v 1.22 1994/12/14 18:49:38 mycroft Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)spec_vnops.c 8.8 (Berkeley) 11/21/94 36 */ 37 38 #include <sys/param.h> 39 #include <sys/proc.h> 40 #include <sys/systm.h> 41 #include <sys/kernel.h> 42 #include <sys/conf.h> 43 #include <sys/buf.h> 44 #include <sys/mount.h> 45 #include <sys/namei.h> 46 #include <sys/vnode.h> 47 #include <sys/stat.h> 48 #include <sys/errno.h> 49 #include <sys/ioctl.h> 50 #include <sys/file.h> 51 #include <sys/disklabel.h> 52 #include <miscfs/specfs/specdev.h> 53 54 /* symbolic sleep message strings for devices */ 55 char devopn[] = "devopn"; 56 char devio[] = "devio"; 57 char devwait[] = "devwait"; 58 char devin[] = "devin"; 59 char devout[] = "devout"; 60 char devioc[] = "devioc"; 61 char devcls[] = "devcls"; 62 63 int (**spec_vnodeop_p)(); 64 struct vnodeopv_entry_desc spec_vnodeop_entries[] = { 65 { &vop_default_desc, vn_default_error }, 66 { &vop_lookup_desc, spec_lookup }, /* lookup */ 67 { &vop_create_desc, spec_create }, /* create */ 68 { &vop_mknod_desc, spec_mknod }, /* mknod */ 69 { &vop_open_desc, spec_open }, /* open */ 70 { &vop_close_desc, spec_close }, /* close */ 71 { &vop_access_desc, spec_access }, /* access */ 72 { &vop_getattr_desc, spec_getattr }, /* getattr */ 73 { &vop_setattr_desc, spec_setattr }, /* setattr */ 74 { &vop_read_desc, spec_read }, /* read */ 75 { &vop_write_desc, spec_write }, /* write */ 76 { &vop_lease_desc, spec_lease_check }, /* lease */ 77 { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ 78 { &vop_select_desc, spec_select }, /* select */ 79 { &vop_mmap_desc, spec_mmap }, /* mmap */ 80 { &vop_fsync_desc, spec_fsync }, /* fsync */ 81 { &vop_seek_desc, spec_seek }, /* seek */ 82 { &vop_remove_desc, spec_remove }, /* remove */ 83 { &vop_link_desc, spec_link }, /* link */ 84 { &vop_rename_desc, spec_rename }, /* rename */ 85 { &vop_mkdir_desc, spec_mkdir }, /* mkdir */ 86 { &vop_rmdir_desc, spec_rmdir }, /* rmdir */ 87 { &vop_symlink_desc, spec_symlink }, /* symlink */ 88 { &vop_readdir_desc, spec_readdir }, /* readdir */ 89 { &vop_readlink_desc, spec_readlink }, /* readlink */ 90 { &vop_abortop_desc, spec_abortop }, /* abortop */ 91 { &vop_inactive_desc, spec_inactive }, /* inactive */ 92 { &vop_reclaim_desc, spec_reclaim }, /* reclaim */ 93 { &vop_lock_desc, spec_lock }, /* lock */ 94 { &vop_unlock_desc, spec_unlock }, /* unlock */ 95 { &vop_bmap_desc, spec_bmap }, /* bmap */ 96 { &vop_strategy_desc, spec_strategy }, /* strategy */ 97 { &vop_print_desc, spec_print }, /* print */ 98 { &vop_islocked_desc, spec_islocked }, /* islocked */ 99 { &vop_pathconf_desc, spec_pathconf }, /* pathconf */ 100 { &vop_advlock_desc, spec_advlock }, /* advlock */ 101 { &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */ 102 { &vop_valloc_desc, spec_valloc }, /* valloc */ 103 { &vop_vfree_desc, spec_vfree }, /* vfree */ 104 { &vop_truncate_desc, spec_truncate }, /* truncate */ 105 { &vop_update_desc, spec_update }, /* update */ 106 { &vop_bwrite_desc, spec_bwrite }, /* bwrite */ 107 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 108 }; 109 struct vnodeopv_desc spec_vnodeop_opv_desc = 110 { &spec_vnodeop_p, spec_vnodeop_entries }; 111 112 /* 113 * Trivial lookup routine that always fails. 114 */ 115 int 116 spec_lookup(ap) 117 struct vop_lookup_args /* { 118 struct vnode *a_dvp; 119 struct vnode **a_vpp; 120 struct componentname *a_cnp; 121 } */ *ap; 122 { 123 124 *ap->a_vpp = NULL; 125 return (ENOTDIR); 126 } 127 128 /* 129 * Open a special file. 130 */ 131 /* ARGSUSED */ 132 spec_open(ap) 133 struct vop_open_args /* { 134 struct vnode *a_vp; 135 int a_mode; 136 struct ucred *a_cred; 137 struct proc *a_p; 138 } */ *ap; 139 { 140 struct vnode *bvp, *vp = ap->a_vp; 141 dev_t bdev, dev = (dev_t)vp->v_rdev; 142 register int maj = major(dev); 143 int error; 144 145 /* 146 * Don't allow open if fs is mounted -nodev. 147 */ 148 if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV)) 149 return (ENXIO); 150 151 switch (vp->v_type) { 152 153 case VCHR: 154 if ((u_int)maj >= nchrdev) 155 return (ENXIO); 156 if (ap->a_cred != FSCRED && (ap->a_mode & FWRITE)) { 157 /* 158 * When running in very secure mode, do not allow 159 * opens for writing of any disk character devices. 160 */ 161 if (securelevel >= 2 && isdisk(dev, VCHR)) 162 return (EPERM); 163 /* 164 * When running in secure mode, do not allow opens 165 * for writing of /dev/mem, /dev/kmem, or character 166 * devices whose corresponding block devices are 167 * currently mounted. 168 */ 169 if (securelevel >= 1) { 170 if ((bdev = chrtoblk(dev)) != NODEV && 171 vfinddev(bdev, VBLK, &bvp) && 172 bvp->v_usecount > 0 && 173 (error = vfs_mountedon(bvp))) 174 return (error); 175 if (iskmemdev(dev)) 176 return (EPERM); 177 } 178 } 179 VOP_UNLOCK(vp); 180 error = (*cdevsw[maj].d_open)(dev, ap->a_mode, S_IFCHR, ap->a_p); 181 VOP_LOCK(vp); 182 return (error); 183 184 case VBLK: 185 if ((u_int)maj >= nblkdev) 186 return (ENXIO); 187 /* 188 * When running in very secure mode, do not allow 189 * opens for writing of any disk block devices. 190 */ 191 if (securelevel >= 2 && ap->a_cred != FSCRED && 192 (ap->a_mode & FWRITE) && isdisk(dev, VBLK)) 193 return (EPERM); 194 /* 195 * Do not allow opens of block devices that are 196 * currently mounted. 197 */ 198 if (error = vfs_mountedon(vp)) 199 return (error); 200 return ((*bdevsw[maj].d_open)(dev, ap->a_mode, S_IFBLK, ap->a_p)); 201 } 202 return (0); 203 } 204 205 /* 206 * Vnode op for read 207 */ 208 /* ARGSUSED */ 209 spec_read(ap) 210 struct vop_read_args /* { 211 struct vnode *a_vp; 212 struct uio *a_uio; 213 int a_ioflag; 214 struct ucred *a_cred; 215 } */ *ap; 216 { 217 register struct vnode *vp = ap->a_vp; 218 register struct uio *uio = ap->a_uio; 219 struct proc *p = uio->uio_procp; 220 struct buf *bp; 221 daddr_t bn, nextbn; 222 long bsize, bscale, ssize; 223 struct partinfo dpart; 224 int n, on, majordev, (*ioctl)(); 225 int error = 0; 226 dev_t dev; 227 228 #ifdef DIAGNOSTIC 229 if (uio->uio_rw != UIO_READ) 230 panic("spec_read mode"); 231 if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) 232 panic("spec_read proc"); 233 #endif 234 if (uio->uio_resid == 0) 235 return (0); 236 237 switch (vp->v_type) { 238 239 case VCHR: 240 VOP_UNLOCK(vp); 241 error = (*cdevsw[major(vp->v_rdev)].d_read) 242 (vp->v_rdev, uio, ap->a_ioflag); 243 VOP_LOCK(vp); 244 return (error); 245 246 case VBLK: 247 if (uio->uio_offset < 0) 248 return (EINVAL); 249 bsize = BLKDEV_IOSIZE; 250 ssize = DEV_BSIZE; 251 dev = vp->v_rdev; 252 if ((majordev = major(dev)) < nblkdev && 253 (ioctl = bdevsw[majordev].d_ioctl) != NULL && 254 (*ioctl)(dev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0) { 255 if (dpart.part->p_fstype == FS_BSDFFS && 256 dpart.part->p_frag != 0 && dpart.part->p_fsize != 0) 257 bsize = dpart.part->p_frag * 258 dpart.part->p_fsize; 259 if (dpart.disklab->d_secsize != 0) 260 ssize = dpart.disklab->d_secsize; 261 } 262 bscale = bsize / ssize; 263 do { 264 bn = (uio->uio_offset / ssize) &~ (bscale - 1); 265 on = uio->uio_offset % bsize; 266 n = min((unsigned)(bsize - on), uio->uio_resid); 267 if (vp->v_lastr + bscale == bn) { 268 nextbn = bn + bscale; 269 error = breadn(vp, bn, (int)bsize, &nextbn, 270 (int *)&bsize, 1, NOCRED, &bp); 271 } else 272 error = bread(vp, bn, (int)bsize, NOCRED, &bp); 273 vp->v_lastr = bn; 274 n = min(n, bsize - bp->b_resid); 275 if (error) { 276 brelse(bp); 277 return (error); 278 } 279 error = uiomove((char *)bp->b_data + on, n, uio); 280 if (n + on == bsize) 281 bp->b_flags |= B_AGE; 282 brelse(bp); 283 } while (error == 0 && uio->uio_resid > 0 && n != 0); 284 return (error); 285 286 default: 287 panic("spec_read type"); 288 } 289 /* NOTREACHED */ 290 } 291 292 /* 293 * Vnode op for write 294 */ 295 /* ARGSUSED */ 296 spec_write(ap) 297 struct vop_write_args /* { 298 struct vnode *a_vp; 299 struct uio *a_uio; 300 int a_ioflag; 301 struct ucred *a_cred; 302 } */ *ap; 303 { 304 register struct vnode *vp = ap->a_vp; 305 register struct uio *uio = ap->a_uio; 306 struct proc *p = uio->uio_procp; 307 struct buf *bp; 308 daddr_t bn; 309 int bsize, blkmask, ssize; 310 struct partinfo dpart; 311 register int n, on; 312 int error = 0; 313 314 #ifdef DIAGNOSTIC 315 if (uio->uio_rw != UIO_WRITE) 316 panic("spec_write mode"); 317 if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) 318 panic("spec_write proc"); 319 #endif 320 321 switch (vp->v_type) { 322 323 case VCHR: 324 VOP_UNLOCK(vp); 325 error = (*cdevsw[major(vp->v_rdev)].d_write) 326 (vp->v_rdev, uio, ap->a_ioflag); 327 VOP_LOCK(vp); 328 return (error); 329 330 case VBLK: 331 if (uio->uio_resid == 0) 332 return (0); 333 if (uio->uio_offset < 0) 334 return (EINVAL); 335 bsize = BLKDEV_IOSIZE; 336 ssize = DEV_BSIZE; 337 if ((*bdevsw[major(vp->v_rdev)].d_ioctl)(vp->v_rdev, DIOCGPART, 338 (caddr_t)&dpart, FREAD, p) == 0) { 339 if (dpart.part->p_fstype == FS_BSDFFS && 340 dpart.part->p_frag != 0 && dpart.part->p_fsize != 0) 341 bsize = dpart.part->p_frag * 342 dpart.part->p_fsize; 343 if (dpart.disklab->d_secsize != 0) 344 ssize = dpart.disklab->d_secsize; 345 } 346 blkmask = (bsize / ssize) - 1; 347 do { 348 bn = (uio->uio_offset / ssize) &~ blkmask; 349 on = uio->uio_offset % bsize; 350 n = min((unsigned)(bsize - on), uio->uio_resid); 351 if (n == bsize) 352 bp = getblk(vp, bn, bsize, 0, 0); 353 else 354 error = bread(vp, bn, bsize, NOCRED, &bp); 355 n = min(n, bsize - bp->b_resid); 356 if (error) { 357 brelse(bp); 358 return (error); 359 } 360 error = uiomove((char *)bp->b_data + on, n, uio); 361 if (n + on == bsize) { 362 bp->b_flags |= B_AGE; 363 bawrite(bp); 364 } else 365 bdwrite(bp); 366 } while (error == 0 && uio->uio_resid > 0 && n != 0); 367 return (error); 368 369 default: 370 panic("spec_write type"); 371 } 372 /* NOTREACHED */ 373 } 374 375 /* 376 * Device ioctl operation. 377 */ 378 /* ARGSUSED */ 379 spec_ioctl(ap) 380 struct vop_ioctl_args /* { 381 struct vnode *a_vp; 382 u_long a_command; 383 caddr_t a_data; 384 int a_fflag; 385 struct ucred *a_cred; 386 struct proc *a_p; 387 } */ *ap; 388 { 389 dev_t dev = ap->a_vp->v_rdev; 390 391 switch (ap->a_vp->v_type) { 392 393 case VCHR: 394 return ((*cdevsw[major(dev)].d_ioctl)(dev, ap->a_command, ap->a_data, 395 ap->a_fflag, ap->a_p)); 396 397 case VBLK: 398 if (ap->a_command == 0 && (long)ap->a_data == B_TAPE) 399 if (bdevsw[major(dev)].d_flags & B_TAPE) 400 return (0); 401 else 402 return (1); 403 return ((*bdevsw[major(dev)].d_ioctl)(dev, ap->a_command, ap->a_data, 404 ap->a_fflag, ap->a_p)); 405 406 default: 407 panic("spec_ioctl"); 408 /* NOTREACHED */ 409 } 410 } 411 412 /* ARGSUSED */ 413 spec_select(ap) 414 struct vop_select_args /* { 415 struct vnode *a_vp; 416 int a_which; 417 int a_fflags; 418 struct ucred *a_cred; 419 struct proc *a_p; 420 } */ *ap; 421 { 422 register dev_t dev; 423 424 switch (ap->a_vp->v_type) { 425 426 default: 427 return (1); /* XXX */ 428 429 case VCHR: 430 dev = ap->a_vp->v_rdev; 431 return (*cdevsw[major(dev)].d_select)(dev, ap->a_which, ap->a_p); 432 } 433 } 434 /* 435 * Synch buffers associated with a block device 436 */ 437 /* ARGSUSED */ 438 int 439 spec_fsync(ap) 440 struct vop_fsync_args /* { 441 struct vnode *a_vp; 442 struct ucred *a_cred; 443 int a_waitfor; 444 struct proc *a_p; 445 } */ *ap; 446 { 447 register struct vnode *vp = ap->a_vp; 448 register struct buf *bp; 449 struct buf *nbp; 450 int s; 451 452 if (vp->v_type == VCHR) 453 return (0); 454 /* 455 * Flush all dirty buffers associated with a block device. 456 */ 457 loop: 458 s = splbio(); 459 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 460 nbp = bp->b_vnbufs.le_next; 461 if ((bp->b_flags & B_BUSY)) 462 continue; 463 if ((bp->b_flags & B_DELWRI) == 0) 464 panic("spec_fsync: not dirty"); 465 bremfree(bp); 466 bp->b_flags |= B_BUSY; 467 splx(s); 468 bawrite(bp); 469 goto loop; 470 } 471 if (ap->a_waitfor == MNT_WAIT) { 472 while (vp->v_numoutput) { 473 vp->v_flag |= VBWAIT; 474 sleep((caddr_t)&vp->v_numoutput, PRIBIO + 1); 475 } 476 #ifdef DIAGNOSTIC 477 if (vp->v_dirtyblkhd.lh_first) { 478 vprint("spec_fsync: dirty", vp); 479 goto loop; 480 } 481 #endif 482 } 483 splx(s); 484 return (0); 485 } 486 487 /* 488 * Just call the device strategy routine 489 */ 490 spec_strategy(ap) 491 struct vop_strategy_args /* { 492 struct buf *a_bp; 493 } */ *ap; 494 { 495 496 (*bdevsw[major(ap->a_bp->b_dev)].d_strategy)(ap->a_bp); 497 return (0); 498 } 499 500 /* 501 * This is a noop, simply returning what one has been given. 502 */ 503 spec_bmap(ap) 504 struct vop_bmap_args /* { 505 struct vnode *a_vp; 506 daddr_t a_bn; 507 struct vnode **a_vpp; 508 daddr_t *a_bnp; 509 } */ *ap; 510 { 511 512 if (ap->a_vpp != NULL) 513 *ap->a_vpp = ap->a_vp; 514 if (ap->a_bnp != NULL) 515 *ap->a_bnp = ap->a_bn; 516 return (0); 517 } 518 519 /* 520 * At the moment we do not do any locking. 521 */ 522 /* ARGSUSED */ 523 spec_lock(ap) 524 struct vop_lock_args /* { 525 struct vnode *a_vp; 526 } */ *ap; 527 { 528 529 return (0); 530 } 531 532 /* ARGSUSED */ 533 spec_unlock(ap) 534 struct vop_unlock_args /* { 535 struct vnode *a_vp; 536 } */ *ap; 537 { 538 539 return (0); 540 } 541 542 /* 543 * Device close routine 544 */ 545 /* ARGSUSED */ 546 spec_close(ap) 547 struct vop_close_args /* { 548 struct vnode *a_vp; 549 int a_fflag; 550 struct ucred *a_cred; 551 struct proc *a_p; 552 } */ *ap; 553 { 554 register struct vnode *vp = ap->a_vp; 555 dev_t dev = vp->v_rdev; 556 int (*devclose) __P((dev_t, int, int, struct proc *)); 557 int mode, error; 558 559 switch (vp->v_type) { 560 561 case VCHR: 562 /* 563 * Hack: a tty device that is a controlling terminal 564 * has a reference from the session structure. 565 * We cannot easily tell that a character device is 566 * a controlling terminal, unless it is the closing 567 * process' controlling terminal. In that case, 568 * if the reference count is 2 (this last descriptor 569 * plus the session), release the reference from the session. 570 */ 571 if (vcount(vp) == 2 && ap->a_p && 572 vp == ap->a_p->p_session->s_ttyvp) { 573 vrele(vp); 574 ap->a_p->p_session->s_ttyvp = NULL; 575 } 576 /* 577 * If the vnode is locked, then we are in the midst 578 * of forcably closing the device, otherwise we only 579 * close on last reference. 580 */ 581 if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0) 582 return (0); 583 devclose = cdevsw[major(dev)].d_close; 584 mode = S_IFCHR; 585 break; 586 587 case VBLK: 588 /* 589 * On last close of a block device (that isn't mounted) 590 * we must invalidate any in core blocks, so that 591 * we can, for instance, change floppy disks. 592 */ 593 if (error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, 0)) 594 return (error); 595 /* 596 * We do not want to really close the device if it 597 * is still in use unless we are trying to close it 598 * forcibly. Since every use (buffer, vnode, swap, cmap) 599 * holds a reference to the vnode, and because we mark 600 * any other vnodes that alias this device, when the 601 * sum of the reference counts on all the aliased 602 * vnodes descends to one, we are on last close. 603 */ 604 if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0) 605 return (0); 606 devclose = bdevsw[major(dev)].d_close; 607 mode = S_IFBLK; 608 break; 609 610 default: 611 panic("spec_close: not special"); 612 } 613 614 return ((*devclose)(dev, ap->a_fflag, mode, ap->a_p)); 615 } 616 617 /* 618 * Print out the contents of a special device vnode. 619 */ 620 spec_print(ap) 621 struct vop_print_args /* { 622 struct vnode *a_vp; 623 } */ *ap; 624 { 625 626 printf("tag VT_NON, dev %d, %d\n", major(ap->a_vp->v_rdev), 627 minor(ap->a_vp->v_rdev)); 628 } 629 630 /* 631 * Return POSIX pathconf information applicable to special devices. 632 */ 633 spec_pathconf(ap) 634 struct vop_pathconf_args /* { 635 struct vnode *a_vp; 636 int a_name; 637 register_t *a_retval; 638 } */ *ap; 639 { 640 641 switch (ap->a_name) { 642 case _PC_LINK_MAX: 643 *ap->a_retval = LINK_MAX; 644 return (0); 645 case _PC_MAX_CANON: 646 *ap->a_retval = MAX_CANON; 647 return (0); 648 case _PC_MAX_INPUT: 649 *ap->a_retval = MAX_INPUT; 650 return (0); 651 case _PC_PIPE_BUF: 652 *ap->a_retval = PIPE_BUF; 653 return (0); 654 case _PC_CHOWN_RESTRICTED: 655 *ap->a_retval = 1; 656 return (0); 657 case _PC_VDISABLE: 658 *ap->a_retval = _POSIX_VDISABLE; 659 return (0); 660 default: 661 return (EINVAL); 662 } 663 /* NOTREACHED */ 664 } 665 666 /* 667 * Special device advisory byte-level locks. 668 */ 669 /* ARGSUSED */ 670 spec_advlock(ap) 671 struct vop_advlock_args /* { 672 struct vnode *a_vp; 673 caddr_t a_id; 674 int a_op; 675 struct flock *a_fl; 676 int a_flags; 677 } */ *ap; 678 { 679 680 return (EOPNOTSUPP); 681 } 682 683 /* 684 * Special device failed operation 685 */ 686 spec_ebadf() 687 { 688 689 return (EBADF); 690 } 691 692 /* 693 * Special device bad operation 694 */ 695 spec_badop() 696 { 697 698 panic("spec_badop called"); 699 /* NOTREACHED */ 700 } 701