1*7487Skre /* sys_generic.c 5.2 82/07/22 */ 27423Sroot 37423Sroot #include "../h/param.h" 47423Sroot #include "../h/systm.h" 57423Sroot #include "../h/dir.h" 67423Sroot #include "../h/user.h" 77423Sroot #include "../h/tty.h" 87423Sroot #include "../h/file.h" 97423Sroot #include "../h/inode.h" 107423Sroot #include "../h/buf.h" 117423Sroot #include "../h/proc.h" 127423Sroot #include "../h/inline.h" 137423Sroot #include "../h/conf.h" 147423Sroot #include "../h/socket.h" 157423Sroot #include "../h/socketvar.h" 167423Sroot #include "../h/cmap.h" 177423Sroot #include "../h/vlimit.h" 187423Sroot #include "../h/fs.h" 19*7487Skre #ifdef MUSH 20*7487Skre #include "../h/quota.h" 21*7487Skre #include "../h/share.h" 22*7487Skre #else 23*7487Skre #define CHARGE(nothing) 24*7487Skre #endif 257423Sroot 267423Sroot /* 277423Sroot * Read system call. 287423Sroot */ 297423Sroot read() 307423Sroot { 317423Sroot register struct file *fp; 327423Sroot register struct inode *ip; 337423Sroot register struct a { 347423Sroot int fdes; 357423Sroot char *cbuf; 367423Sroot unsigned count; 377423Sroot } *uap; 387423Sroot 397423Sroot uap = (struct a *)u.u_ap; 407423Sroot if ((int)uap->count < 0) { 417423Sroot u.u_error = EINVAL; 427423Sroot return; 437423Sroot } 447423Sroot GETF(fp, uap->fdes); 457423Sroot if ((fp->f_flag&FREAD) == 0) { 467423Sroot u.u_error = EBADF; 477423Sroot return; 487423Sroot } 497423Sroot u.u_base = (caddr_t)uap->cbuf; 507423Sroot u.u_count = uap->count; 517423Sroot u.u_segflg = 0; 527423Sroot if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 537423Sroot if (u.u_count == uap->count) 547423Sroot u.u_eosys = RESTARTSYS; 557423Sroot } else if (fp->f_flag & FSOCKET) 567423Sroot u.u_error = soreceive(fp->f_socket, (struct sockaddr *)0); 577423Sroot else { 587423Sroot ip = fp->f_inode; 597423Sroot u.u_offset = fp->f_offset; 607423Sroot if ((ip->i_mode&IFMT) == IFREG) { 617423Sroot ilock(ip); 627423Sroot readi(ip); 637423Sroot iunlock(ip); 647423Sroot } else 657423Sroot readi(ip); 667423Sroot fp->f_offset += uap->count - u.u_count; 677423Sroot } 687423Sroot u.u_r.r_val1 = uap->count - u.u_count; 697423Sroot } 707423Sroot 717423Sroot /* 727423Sroot * Write system call 737423Sroot */ 747423Sroot write() 757423Sroot { 767423Sroot register struct file *fp; 777423Sroot register struct inode *ip; 787423Sroot register struct a { 797423Sroot int fdes; 807423Sroot char *cbuf; 817423Sroot unsigned count; 827423Sroot } *uap; 837423Sroot 847423Sroot uap = (struct a *)u.u_ap; 857423Sroot if ((int)uap->count < 0) { 867423Sroot u.u_error = EINVAL; 877423Sroot return; 887423Sroot } 897423Sroot GETF(fp, uap->fdes); 907423Sroot if ((fp->f_flag&FWRITE) == 0) { 917423Sroot u.u_error = EBADF; 927423Sroot return; 937423Sroot } 947423Sroot u.u_base = (caddr_t)uap->cbuf; 957423Sroot u.u_count = uap->count; 967423Sroot u.u_segflg = 0; 977423Sroot if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 987423Sroot if (u.u_count == uap->count) 997423Sroot u.u_eosys = RESTARTSYS; 1007423Sroot } else if (fp->f_flag & FSOCKET) 1017423Sroot u.u_error = sosend(fp->f_socket, (struct sockaddr *)0); 1027423Sroot else { 1037423Sroot ip = fp->f_inode; 1047423Sroot u.u_offset = fp->f_offset; 1057423Sroot if ((ip->i_mode&IFMT) == IFREG) { 1067423Sroot ilock(ip); 1077423Sroot writei(ip); 1087423Sroot iunlock(ip); 1097423Sroot } else 1107423Sroot writei(ip); 1117423Sroot fp->f_offset += uap->count - u.u_count; 1127423Sroot } 1137423Sroot u.u_r.r_val1 = uap->count - u.u_count; 1147423Sroot } 1157423Sroot 1167423Sroot 1177423Sroot /* 1187423Sroot * Ioctl system call 1197423Sroot * Check legality, execute common code, and switch out to individual 1207423Sroot * device routine. 1217423Sroot */ 1227423Sroot ioctl() 1237423Sroot { 1247423Sroot register struct file *fp; 1257423Sroot register struct inode *ip; 1267423Sroot register struct a { 1277423Sroot int fdes; 1287423Sroot int cmd; 1297423Sroot caddr_t cmarg; 1307423Sroot } *uap; 1317423Sroot register dev_t dev; 1327423Sroot register fmt; 1337423Sroot 1347423Sroot uap = (struct a *)u.u_ap; 1357423Sroot if ((fp = getf(uap->fdes)) == NULL) 1367423Sroot return; 1377423Sroot if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 1387423Sroot u.u_error = EBADF; 1397423Sroot return; 1407423Sroot } 1417423Sroot if (uap->cmd==FIOCLEX) { 1427423Sroot u.u_pofile[uap->fdes] |= EXCLOSE; 1437423Sroot return; 1447423Sroot } 1457423Sroot if (uap->cmd==FIONCLEX) { 1467423Sroot u.u_pofile[uap->fdes] &= ~EXCLOSE; 1477423Sroot return; 1487423Sroot } 1497423Sroot if (fp->f_flag & FSOCKET) { 1507423Sroot soioctl(fp->f_socket, uap->cmd, uap->cmarg); 1517423Sroot return; 1527423Sroot } 1537423Sroot ip = fp->f_inode; 1547423Sroot fmt = ip->i_mode & IFMT; 1557423Sroot if (fmt != IFCHR) { 1567423Sroot if (uap->cmd==FIONREAD && (fmt == IFREG || fmt == IFDIR)) { 1577423Sroot off_t nread = ip->i_size - fp->f_offset; 1587423Sroot 1597423Sroot if (copyout((caddr_t)&nread, uap->cmarg, sizeof(off_t))) 1607423Sroot u.u_error = EFAULT; 1617423Sroot } else if (uap->cmd == FIONBIO || uap->cmd == FIOASYNC) 1627423Sroot return; 1637423Sroot else 1647423Sroot u.u_error = ENOTTY; 1657423Sroot return; 1667423Sroot } 1677423Sroot dev = ip->i_rdev; 1687423Sroot u.u_r.r_val1 = 0; 1697423Sroot if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 1707423Sroot u.u_eosys = RESTARTSYS; 1717423Sroot return; 1727423Sroot } 1737423Sroot (*cdevsw[major(dev)].d_ioctl)(dev, uap->cmd, uap->cmarg, 0); 1747423Sroot } 1757423Sroot 1767423Sroot /* 1777423Sroot * Do nothing specific version of line 1787423Sroot * discipline specific ioctl command. 1797423Sroot */ 1807423Sroot /*ARGSUSED*/ 1817423Sroot nullioctl(tp, cmd, addr) 1827423Sroot struct tty *tp; 1837423Sroot caddr_t addr; 1847423Sroot { 1857423Sroot 1867423Sroot return (cmd); 1877423Sroot } 1887423Sroot 1897423Sroot /* 1907423Sroot * Read the file corresponding to 1917423Sroot * the inode pointed at by the argument. 1927423Sroot * The actual read arguments are found 1937423Sroot * in the variables: 1947423Sroot * u_base core address for destination 1957423Sroot * u_offset byte offset in file 1967423Sroot * u_count number of bytes to read 1977423Sroot * u_segflg read to kernel/user/user I 1987423Sroot */ 1997423Sroot readi(ip) 2007423Sroot register struct inode *ip; 2017423Sroot { 2027423Sroot struct buf *bp; 2037423Sroot struct fs *fs; 2047423Sroot dev_t dev; 2057423Sroot daddr_t lbn, bn; 2067423Sroot off_t diff; 2077423Sroot register int on, type; 2087423Sroot register unsigned n; 2097423Sroot int size; 2107423Sroot long bsize; 2117423Sroot extern int mem_no; 2127423Sroot 2137423Sroot if (u.u_count == 0) 2147423Sroot return; 2157423Sroot dev = (dev_t)ip->i_rdev; 2167423Sroot if (u.u_offset < 0 && ((ip->i_mode&IFMT) != IFCHR || 2177423Sroot mem_no != major(dev))) { 2187423Sroot u.u_error = EINVAL; 2197423Sroot return; 2207423Sroot } 2217423Sroot ip->i_flag |= IACC; 2227423Sroot type = ip->i_mode&IFMT; 2237423Sroot if (type == IFCHR) { 224*7487Skre register c = u.u_count; 2257423Sroot (*cdevsw[major(dev)].d_read)(dev); 226*7487Skre CHARGE(sc_tio * (c - u.u_count)); 2277423Sroot return; 2287423Sroot } 2297423Sroot if (type != IFBLK) { 2307423Sroot dev = ip->i_dev; 2317423Sroot fs = ip->i_fs; 2327423Sroot bsize = fs->fs_bsize; 2337423Sroot } else 2347423Sroot bsize = BLKDEV_IOSIZE; 2357423Sroot do { 2367423Sroot lbn = u.u_offset / bsize; 2377423Sroot on = u.u_offset % bsize; 2387423Sroot n = MIN((unsigned)(bsize - on), u.u_count); 2397423Sroot if (type != IFBLK) { 2407423Sroot diff = ip->i_size - u.u_offset; 2417423Sroot if (diff <= 0) 2427423Sroot return; 2437423Sroot if (diff < n) 2447423Sroot n = diff; 2457423Sroot bn = fsbtodb(fs, bmap(ip, lbn, B_READ)); 2467423Sroot if (u.u_error) 2477423Sroot return; 2487423Sroot size = blksize(fs, ip, lbn); 2497423Sroot } else { 2507423Sroot size = bsize; 2517423Sroot bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE); 2527423Sroot rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE); 2537423Sroot rasize = bsize; 2547423Sroot } 2557423Sroot if ((long)bn<0) { 2567423Sroot bp = geteblk(size); 2577423Sroot clrbuf(bp); 2587423Sroot } else if (ip->i_lastr + 1 == lbn) 2597423Sroot bp = breada(dev, bn, size, rablock, rasize); 2607423Sroot else 2617423Sroot bp = bread(dev, bn, size); 2627423Sroot ip->i_lastr = lbn; 2637423Sroot n = MIN(n, size - bp->b_resid); 2647423Sroot if (n != 0) { 2657423Sroot #ifdef UNFAST 2667423Sroot iomove(bp->b_un.b_addr + on, n, B_READ); 2677423Sroot #else 2687423Sroot if (u.u_segflg != 1) { 2697423Sroot if (copyout(bp->b_un.b_addr+on, u.u_base, n)) { 2707423Sroot u.u_error = EFAULT; 2717423Sroot goto bad; 2727423Sroot } 2737423Sroot } else 2747423Sroot bcopy(bp->b_un.b_addr + on, u.u_base, n); 2757423Sroot u.u_base += n; 2767423Sroot u.u_offset += n; 2777423Sroot u.u_count -= n; 2787423Sroot bad: 2797423Sroot ; 2807423Sroot #endif 2817423Sroot } 2827423Sroot if (n + on == bsize || u.u_offset == ip->i_size) 2837423Sroot bp->b_flags |= B_AGE; 2847423Sroot brelse(bp); 2857423Sroot } while (u.u_error == 0 && u.u_count != 0 && n != 0); 2867423Sroot } 2877423Sroot 2887423Sroot /* 2897423Sroot * Write the file corresponding to 2907423Sroot * the inode pointed at by the argument. 2917423Sroot * The actual write arguments are found 2927423Sroot * in the variables: 2937423Sroot * u_base core address for source 2947423Sroot * u_offset byte offset in file 2957423Sroot * u_count number of bytes to write 2967423Sroot * u_segflg write to kernel/user/user I 2977423Sroot */ 2987423Sroot writei(ip) 2997423Sroot register struct inode *ip; 3007423Sroot { 3017423Sroot struct buf *bp; 3027423Sroot register struct fs *fs; 3037423Sroot dev_t dev; 3047423Sroot daddr_t lbn, bn; 3057423Sroot register int on, type; 3067423Sroot register unsigned n; 3077423Sroot long bsize; 3087423Sroot int size, i, count; 3097423Sroot extern int mem_no; 3107423Sroot 3117423Sroot dev = (dev_t)ip->i_rdev; 3127423Sroot if (u.u_offset < 0 && ((ip->i_mode&IFMT) != IFCHR || 3137423Sroot mem_no != major(dev)) ) { 3147423Sroot u.u_error = EINVAL; 3157423Sroot return; 3167423Sroot } 3177423Sroot type = ip->i_mode & IFMT; 3187423Sroot if (type == IFCHR) { 3197423Sroot ip->i_flag |= IUPD|ICHG; 320*7487Skre CHARGE(sc_tio * u.u_count); 3217423Sroot (*cdevsw[major(dev)].d_write)(dev); 3227423Sroot return; 3237423Sroot } 3247423Sroot if (u.u_count == 0) 3257423Sroot return; 3267423Sroot if ((ip->i_mode & IFMT) == IFREG && 3277423Sroot u.u_offset + u.u_count > u.u_limit[LIM_FSIZE]) { 3287423Sroot psignal(u.u_procp, SIGXFSZ); 3297423Sroot u.u_error = EMFILE; 3307423Sroot return; 3317423Sroot } 3327423Sroot if (type!=IFBLK) { 3337423Sroot dev = ip->i_dev; 3347423Sroot fs = ip->i_fs; 3357423Sroot bsize = fs->fs_bsize; 3367423Sroot } else { 3377423Sroot bsize = BLKDEV_IOSIZE; 3387423Sroot } 3397423Sroot do { 3407423Sroot lbn = u.u_offset / bsize; 3417423Sroot on = u.u_offset % bsize; 3427423Sroot n = MIN((unsigned)(bsize - on), u.u_count); 3437423Sroot if (type != IFBLK) { 3447423Sroot bn = fsbtodb(fs, bmap(ip, lbn, B_WRITE, (int)(on + n))); 3457423Sroot if ((long)bn<0) 3467423Sroot return; 3477423Sroot if(u.u_offset + n > ip->i_size && 3487423Sroot (type == IFDIR || type == IFREG || type == IFLNK)) 3497423Sroot ip->i_size = u.u_offset + n; 3507423Sroot size = blksize(fs, ip, lbn); 3517423Sroot } else { 3527423Sroot size = bsize; 3537423Sroot bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE); 3547423Sroot } 3557423Sroot if (bn) { 3567423Sroot count = howmany(size, DEV_BSIZE); 3577423Sroot for (i = 0; i < count; i += CLSIZE) { 3587423Sroot if (mfind(dev, bn + i)) 3597423Sroot munhash(dev, bn + i); 3607423Sroot } 3617423Sroot } 3627423Sroot if(n == bsize) 3637423Sroot bp = getblk(dev, bn, size); 3647423Sroot else 3657423Sroot bp = bread(dev, bn, size); 3667423Sroot #ifdef UNFAST 3677423Sroot iomove(bp->b_un.b_addr + on, n, B_WRITE); 3687423Sroot #else 3697423Sroot if (u.u_segflg != 1) { 3707423Sroot if (copyin(u.u_base, bp->b_un.b_addr + on, n)) { 3717423Sroot u.u_error = EFAULT; 3727423Sroot goto bad; 3737423Sroot } 3747423Sroot } else 3757423Sroot bcopy(u.u_base, bp->b_un.b_addr + on, n); 3767423Sroot u.u_base += n; 3777423Sroot u.u_offset += n; 3787423Sroot u.u_count -= n; 3797423Sroot bad: 3807423Sroot ; 3817423Sroot #endif 3827423Sroot if (u.u_error != 0) 3837423Sroot brelse(bp); 3847423Sroot else { 3857423Sroot if ((ip->i_mode&IFMT) == IFDIR) 3867423Sroot /* 3877423Sroot * Writing to clear a directory entry. 3887423Sroot * Must insure the write occurs before 3897423Sroot * the inode is freed, or may end up 3907423Sroot * pointing at a new (different) file 3917423Sroot * if inode is quickly allocated again 3927423Sroot * and system crashes. 3937423Sroot */ 3947423Sroot bwrite(bp); 3957423Sroot else if (n + on == bsize) { 3967423Sroot bp->b_flags |= B_AGE; 3977423Sroot bawrite(bp); 3987423Sroot } else 3997423Sroot bdwrite(bp); 4007423Sroot } 4017423Sroot ip->i_flag |= IUPD|ICHG; 4027423Sroot if (u.u_ruid != 0) 4037423Sroot ip->i_mode &= ~(ISUID|ISGID); 4047423Sroot } while (u.u_error == 0 && u.u_count != 0); 4057423Sroot } 4067423Sroot 4077423Sroot /* 4087423Sroot * Move n bytes at byte location 4097423Sroot * &bp->b_un.b_addr[o] to/from (flag) the 4107423Sroot * user/kernel (u.segflg) area starting at u.base. 4117423Sroot * Update all the arguments by the number 4127423Sroot * of bytes moved. 4137423Sroot */ 4147423Sroot iomove(cp, n, flag) 4157423Sroot register caddr_t cp; 4167423Sroot register unsigned n; 4177423Sroot { 4187423Sroot register int t; 4197423Sroot 4207423Sroot if (n==0) 4217423Sroot return; 4227423Sroot if (u.u_segflg != 1) { 4237423Sroot if (flag==B_WRITE) 4247423Sroot t = copyin(u.u_base, (caddr_t)cp, n); 4257423Sroot else 4267423Sroot t = copyout((caddr_t)cp, u.u_base, n); 4277423Sroot if (t) { 4287423Sroot u.u_error = EFAULT; 4297423Sroot return; 4307423Sroot } 4317423Sroot } else 4327423Sroot if (flag == B_WRITE) 4337423Sroot bcopy(u.u_base, (caddr_t)cp, n); 4347423Sroot else 4357423Sroot bcopy((caddr_t)cp, u.u_base, n); 4367423Sroot u.u_base += n; 4377423Sroot u.u_offset += n; 4387423Sroot u.u_count -= n; 4397423Sroot } 440