1*7423Sroot /* sys_generic.c 5.1 82/07/15 */ 2*7423Sroot 3*7423Sroot #include "../h/param.h" 4*7423Sroot #include "../h/systm.h" 5*7423Sroot #include "../h/dir.h" 6*7423Sroot #include "../h/user.h" 7*7423Sroot #include "../h/tty.h" 8*7423Sroot #include "../h/file.h" 9*7423Sroot #include "../h/inode.h" 10*7423Sroot #include "../h/buf.h" 11*7423Sroot #include "../h/proc.h" 12*7423Sroot #include "../h/inline.h" 13*7423Sroot #include "../h/conf.h" 14*7423Sroot #include "../h/socket.h" 15*7423Sroot #include "../h/socketvar.h" 16*7423Sroot #include "../h/cmap.h" 17*7423Sroot #include "../h/vlimit.h" 18*7423Sroot #include "../h/fs.h" 19*7423Sroot 20*7423Sroot /* 21*7423Sroot * Read system call. 22*7423Sroot */ 23*7423Sroot read() 24*7423Sroot { 25*7423Sroot register struct file *fp; 26*7423Sroot register struct inode *ip; 27*7423Sroot register struct a { 28*7423Sroot int fdes; 29*7423Sroot char *cbuf; 30*7423Sroot unsigned count; 31*7423Sroot } *uap; 32*7423Sroot 33*7423Sroot uap = (struct a *)u.u_ap; 34*7423Sroot if ((int)uap->count < 0) { 35*7423Sroot u.u_error = EINVAL; 36*7423Sroot return; 37*7423Sroot } 38*7423Sroot GETF(fp, uap->fdes); 39*7423Sroot if ((fp->f_flag&FREAD) == 0) { 40*7423Sroot u.u_error = EBADF; 41*7423Sroot return; 42*7423Sroot } 43*7423Sroot u.u_base = (caddr_t)uap->cbuf; 44*7423Sroot u.u_count = uap->count; 45*7423Sroot u.u_segflg = 0; 46*7423Sroot if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 47*7423Sroot if (u.u_count == uap->count) 48*7423Sroot u.u_eosys = RESTARTSYS; 49*7423Sroot } else if (fp->f_flag & FSOCKET) 50*7423Sroot u.u_error = soreceive(fp->f_socket, (struct sockaddr *)0); 51*7423Sroot else { 52*7423Sroot ip = fp->f_inode; 53*7423Sroot u.u_offset = fp->f_offset; 54*7423Sroot if ((ip->i_mode&IFMT) == IFREG) { 55*7423Sroot ilock(ip); 56*7423Sroot readi(ip); 57*7423Sroot iunlock(ip); 58*7423Sroot } else 59*7423Sroot readi(ip); 60*7423Sroot fp->f_offset += uap->count - u.u_count; 61*7423Sroot } 62*7423Sroot u.u_r.r_val1 = uap->count - u.u_count; 63*7423Sroot } 64*7423Sroot 65*7423Sroot /* 66*7423Sroot * Write system call 67*7423Sroot */ 68*7423Sroot write() 69*7423Sroot { 70*7423Sroot register struct file *fp; 71*7423Sroot register struct inode *ip; 72*7423Sroot register struct a { 73*7423Sroot int fdes; 74*7423Sroot char *cbuf; 75*7423Sroot unsigned count; 76*7423Sroot } *uap; 77*7423Sroot 78*7423Sroot uap = (struct a *)u.u_ap; 79*7423Sroot if ((int)uap->count < 0) { 80*7423Sroot u.u_error = EINVAL; 81*7423Sroot return; 82*7423Sroot } 83*7423Sroot GETF(fp, uap->fdes); 84*7423Sroot if ((fp->f_flag&FWRITE) == 0) { 85*7423Sroot u.u_error = EBADF; 86*7423Sroot return; 87*7423Sroot } 88*7423Sroot u.u_base = (caddr_t)uap->cbuf; 89*7423Sroot u.u_count = uap->count; 90*7423Sroot u.u_segflg = 0; 91*7423Sroot if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 92*7423Sroot if (u.u_count == uap->count) 93*7423Sroot u.u_eosys = RESTARTSYS; 94*7423Sroot } else if (fp->f_flag & FSOCKET) 95*7423Sroot u.u_error = sosend(fp->f_socket, (struct sockaddr *)0); 96*7423Sroot else { 97*7423Sroot ip = fp->f_inode; 98*7423Sroot u.u_offset = fp->f_offset; 99*7423Sroot if ((ip->i_mode&IFMT) == IFREG) { 100*7423Sroot ilock(ip); 101*7423Sroot writei(ip); 102*7423Sroot iunlock(ip); 103*7423Sroot } else 104*7423Sroot writei(ip); 105*7423Sroot fp->f_offset += uap->count - u.u_count; 106*7423Sroot } 107*7423Sroot u.u_r.r_val1 = uap->count - u.u_count; 108*7423Sroot } 109*7423Sroot 110*7423Sroot 111*7423Sroot /* 112*7423Sroot * Ioctl system call 113*7423Sroot * Check legality, execute common code, and switch out to individual 114*7423Sroot * device routine. 115*7423Sroot */ 116*7423Sroot ioctl() 117*7423Sroot { 118*7423Sroot register struct file *fp; 119*7423Sroot register struct inode *ip; 120*7423Sroot register struct a { 121*7423Sroot int fdes; 122*7423Sroot int cmd; 123*7423Sroot caddr_t cmarg; 124*7423Sroot } *uap; 125*7423Sroot register dev_t dev; 126*7423Sroot register fmt; 127*7423Sroot 128*7423Sroot uap = (struct a *)u.u_ap; 129*7423Sroot if ((fp = getf(uap->fdes)) == NULL) 130*7423Sroot return; 131*7423Sroot if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 132*7423Sroot u.u_error = EBADF; 133*7423Sroot return; 134*7423Sroot } 135*7423Sroot if (uap->cmd==FIOCLEX) { 136*7423Sroot u.u_pofile[uap->fdes] |= EXCLOSE; 137*7423Sroot return; 138*7423Sroot } 139*7423Sroot if (uap->cmd==FIONCLEX) { 140*7423Sroot u.u_pofile[uap->fdes] &= ~EXCLOSE; 141*7423Sroot return; 142*7423Sroot } 143*7423Sroot if (fp->f_flag & FSOCKET) { 144*7423Sroot soioctl(fp->f_socket, uap->cmd, uap->cmarg); 145*7423Sroot return; 146*7423Sroot } 147*7423Sroot ip = fp->f_inode; 148*7423Sroot fmt = ip->i_mode & IFMT; 149*7423Sroot if (fmt != IFCHR) { 150*7423Sroot if (uap->cmd==FIONREAD && (fmt == IFREG || fmt == IFDIR)) { 151*7423Sroot off_t nread = ip->i_size - fp->f_offset; 152*7423Sroot 153*7423Sroot if (copyout((caddr_t)&nread, uap->cmarg, sizeof(off_t))) 154*7423Sroot u.u_error = EFAULT; 155*7423Sroot } else if (uap->cmd == FIONBIO || uap->cmd == FIOASYNC) 156*7423Sroot return; 157*7423Sroot else 158*7423Sroot u.u_error = ENOTTY; 159*7423Sroot return; 160*7423Sroot } 161*7423Sroot dev = ip->i_rdev; 162*7423Sroot u.u_r.r_val1 = 0; 163*7423Sroot if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 164*7423Sroot u.u_eosys = RESTARTSYS; 165*7423Sroot return; 166*7423Sroot } 167*7423Sroot (*cdevsw[major(dev)].d_ioctl)(dev, uap->cmd, uap->cmarg, 0); 168*7423Sroot } 169*7423Sroot 170*7423Sroot /* 171*7423Sroot * Do nothing specific version of line 172*7423Sroot * discipline specific ioctl command. 173*7423Sroot */ 174*7423Sroot /*ARGSUSED*/ 175*7423Sroot nullioctl(tp, cmd, addr) 176*7423Sroot struct tty *tp; 177*7423Sroot caddr_t addr; 178*7423Sroot { 179*7423Sroot 180*7423Sroot return (cmd); 181*7423Sroot } 182*7423Sroot 183*7423Sroot /* 184*7423Sroot * Read the file corresponding to 185*7423Sroot * the inode pointed at by the argument. 186*7423Sroot * The actual read arguments are found 187*7423Sroot * in the variables: 188*7423Sroot * u_base core address for destination 189*7423Sroot * u_offset byte offset in file 190*7423Sroot * u_count number of bytes to read 191*7423Sroot * u_segflg read to kernel/user/user I 192*7423Sroot */ 193*7423Sroot readi(ip) 194*7423Sroot register struct inode *ip; 195*7423Sroot { 196*7423Sroot struct buf *bp; 197*7423Sroot struct fs *fs; 198*7423Sroot dev_t dev; 199*7423Sroot daddr_t lbn, bn; 200*7423Sroot off_t diff; 201*7423Sroot register int on, type; 202*7423Sroot register unsigned n; 203*7423Sroot int size; 204*7423Sroot long bsize; 205*7423Sroot extern int mem_no; 206*7423Sroot 207*7423Sroot if (u.u_count == 0) 208*7423Sroot return; 209*7423Sroot dev = (dev_t)ip->i_rdev; 210*7423Sroot if (u.u_offset < 0 && ((ip->i_mode&IFMT) != IFCHR || 211*7423Sroot mem_no != major(dev))) { 212*7423Sroot u.u_error = EINVAL; 213*7423Sroot return; 214*7423Sroot } 215*7423Sroot ip->i_flag |= IACC; 216*7423Sroot type = ip->i_mode&IFMT; 217*7423Sroot if (type == IFCHR) { 218*7423Sroot (*cdevsw[major(dev)].d_read)(dev); 219*7423Sroot return; 220*7423Sroot } 221*7423Sroot if (type != IFBLK) { 222*7423Sroot dev = ip->i_dev; 223*7423Sroot fs = ip->i_fs; 224*7423Sroot bsize = fs->fs_bsize; 225*7423Sroot } else 226*7423Sroot bsize = BLKDEV_IOSIZE; 227*7423Sroot do { 228*7423Sroot lbn = u.u_offset / bsize; 229*7423Sroot on = u.u_offset % bsize; 230*7423Sroot n = MIN((unsigned)(bsize - on), u.u_count); 231*7423Sroot if (type != IFBLK) { 232*7423Sroot diff = ip->i_size - u.u_offset; 233*7423Sroot if (diff <= 0) 234*7423Sroot return; 235*7423Sroot if (diff < n) 236*7423Sroot n = diff; 237*7423Sroot bn = fsbtodb(fs, bmap(ip, lbn, B_READ)); 238*7423Sroot if (u.u_error) 239*7423Sroot return; 240*7423Sroot size = blksize(fs, ip, lbn); 241*7423Sroot } else { 242*7423Sroot size = bsize; 243*7423Sroot bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE); 244*7423Sroot rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE); 245*7423Sroot rasize = bsize; 246*7423Sroot } 247*7423Sroot if ((long)bn<0) { 248*7423Sroot bp = geteblk(size); 249*7423Sroot clrbuf(bp); 250*7423Sroot } else if (ip->i_lastr + 1 == lbn) 251*7423Sroot bp = breada(dev, bn, size, rablock, rasize); 252*7423Sroot else 253*7423Sroot bp = bread(dev, bn, size); 254*7423Sroot ip->i_lastr = lbn; 255*7423Sroot n = MIN(n, size - bp->b_resid); 256*7423Sroot if (n != 0) { 257*7423Sroot #ifdef UNFAST 258*7423Sroot iomove(bp->b_un.b_addr + on, n, B_READ); 259*7423Sroot #else 260*7423Sroot if (u.u_segflg != 1) { 261*7423Sroot if (copyout(bp->b_un.b_addr+on, u.u_base, n)) { 262*7423Sroot u.u_error = EFAULT; 263*7423Sroot goto bad; 264*7423Sroot } 265*7423Sroot } else 266*7423Sroot bcopy(bp->b_un.b_addr + on, u.u_base, n); 267*7423Sroot u.u_base += n; 268*7423Sroot u.u_offset += n; 269*7423Sroot u.u_count -= n; 270*7423Sroot bad: 271*7423Sroot ; 272*7423Sroot #endif 273*7423Sroot } 274*7423Sroot if (n + on == bsize || u.u_offset == ip->i_size) 275*7423Sroot bp->b_flags |= B_AGE; 276*7423Sroot brelse(bp); 277*7423Sroot } while (u.u_error == 0 && u.u_count != 0 && n != 0); 278*7423Sroot } 279*7423Sroot 280*7423Sroot /* 281*7423Sroot * Write the file corresponding to 282*7423Sroot * the inode pointed at by the argument. 283*7423Sroot * The actual write arguments are found 284*7423Sroot * in the variables: 285*7423Sroot * u_base core address for source 286*7423Sroot * u_offset byte offset in file 287*7423Sroot * u_count number of bytes to write 288*7423Sroot * u_segflg write to kernel/user/user I 289*7423Sroot */ 290*7423Sroot writei(ip) 291*7423Sroot register struct inode *ip; 292*7423Sroot { 293*7423Sroot struct buf *bp; 294*7423Sroot register struct fs *fs; 295*7423Sroot dev_t dev; 296*7423Sroot daddr_t lbn, bn; 297*7423Sroot register int on, type; 298*7423Sroot register unsigned n; 299*7423Sroot long bsize; 300*7423Sroot int size, i, count; 301*7423Sroot extern int mem_no; 302*7423Sroot 303*7423Sroot dev = (dev_t)ip->i_rdev; 304*7423Sroot if (u.u_offset < 0 && ((ip->i_mode&IFMT) != IFCHR || 305*7423Sroot mem_no != major(dev)) ) { 306*7423Sroot u.u_error = EINVAL; 307*7423Sroot return; 308*7423Sroot } 309*7423Sroot type = ip->i_mode & IFMT; 310*7423Sroot if (type == IFCHR) { 311*7423Sroot ip->i_flag |= IUPD|ICHG; 312*7423Sroot (*cdevsw[major(dev)].d_write)(dev); 313*7423Sroot return; 314*7423Sroot } 315*7423Sroot if (u.u_count == 0) 316*7423Sroot return; 317*7423Sroot if ((ip->i_mode & IFMT) == IFREG && 318*7423Sroot u.u_offset + u.u_count > u.u_limit[LIM_FSIZE]) { 319*7423Sroot psignal(u.u_procp, SIGXFSZ); 320*7423Sroot u.u_error = EMFILE; 321*7423Sroot return; 322*7423Sroot } 323*7423Sroot if (type!=IFBLK) { 324*7423Sroot dev = ip->i_dev; 325*7423Sroot fs = ip->i_fs; 326*7423Sroot bsize = fs->fs_bsize; 327*7423Sroot } else { 328*7423Sroot bsize = BLKDEV_IOSIZE; 329*7423Sroot } 330*7423Sroot do { 331*7423Sroot lbn = u.u_offset / bsize; 332*7423Sroot on = u.u_offset % bsize; 333*7423Sroot n = MIN((unsigned)(bsize - on), u.u_count); 334*7423Sroot if (type != IFBLK) { 335*7423Sroot bn = fsbtodb(fs, bmap(ip, lbn, B_WRITE, (int)(on + n))); 336*7423Sroot if ((long)bn<0) 337*7423Sroot return; 338*7423Sroot if(u.u_offset + n > ip->i_size && 339*7423Sroot (type == IFDIR || type == IFREG || type == IFLNK)) 340*7423Sroot ip->i_size = u.u_offset + n; 341*7423Sroot size = blksize(fs, ip, lbn); 342*7423Sroot } else { 343*7423Sroot size = bsize; 344*7423Sroot bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE); 345*7423Sroot } 346*7423Sroot if (bn) { 347*7423Sroot count = howmany(size, DEV_BSIZE); 348*7423Sroot for (i = 0; i < count; i += CLSIZE) { 349*7423Sroot if (mfind(dev, bn + i)) 350*7423Sroot munhash(dev, bn + i); 351*7423Sroot } 352*7423Sroot } 353*7423Sroot if(n == bsize) 354*7423Sroot bp = getblk(dev, bn, size); 355*7423Sroot else 356*7423Sroot bp = bread(dev, bn, size); 357*7423Sroot #ifdef UNFAST 358*7423Sroot iomove(bp->b_un.b_addr + on, n, B_WRITE); 359*7423Sroot #else 360*7423Sroot if (u.u_segflg != 1) { 361*7423Sroot if (copyin(u.u_base, bp->b_un.b_addr + on, n)) { 362*7423Sroot u.u_error = EFAULT; 363*7423Sroot goto bad; 364*7423Sroot } 365*7423Sroot } else 366*7423Sroot bcopy(u.u_base, bp->b_un.b_addr + on, n); 367*7423Sroot u.u_base += n; 368*7423Sroot u.u_offset += n; 369*7423Sroot u.u_count -= n; 370*7423Sroot bad: 371*7423Sroot ; 372*7423Sroot #endif 373*7423Sroot if (u.u_error != 0) 374*7423Sroot brelse(bp); 375*7423Sroot else { 376*7423Sroot if ((ip->i_mode&IFMT) == IFDIR) 377*7423Sroot /* 378*7423Sroot * Writing to clear a directory entry. 379*7423Sroot * Must insure the write occurs before 380*7423Sroot * the inode is freed, or may end up 381*7423Sroot * pointing at a new (different) file 382*7423Sroot * if inode is quickly allocated again 383*7423Sroot * and system crashes. 384*7423Sroot */ 385*7423Sroot bwrite(bp); 386*7423Sroot else if (n + on == bsize) { 387*7423Sroot bp->b_flags |= B_AGE; 388*7423Sroot bawrite(bp); 389*7423Sroot } else 390*7423Sroot bdwrite(bp); 391*7423Sroot } 392*7423Sroot ip->i_flag |= IUPD|ICHG; 393*7423Sroot if (u.u_ruid != 0) 394*7423Sroot ip->i_mode &= ~(ISUID|ISGID); 395*7423Sroot } while (u.u_error == 0 && u.u_count != 0); 396*7423Sroot } 397*7423Sroot 398*7423Sroot /* 399*7423Sroot * Move n bytes at byte location 400*7423Sroot * &bp->b_un.b_addr[o] to/from (flag) the 401*7423Sroot * user/kernel (u.segflg) area starting at u.base. 402*7423Sroot * Update all the arguments by the number 403*7423Sroot * of bytes moved. 404*7423Sroot */ 405*7423Sroot iomove(cp, n, flag) 406*7423Sroot register caddr_t cp; 407*7423Sroot register unsigned n; 408*7423Sroot { 409*7423Sroot register int t; 410*7423Sroot 411*7423Sroot if (n==0) 412*7423Sroot return; 413*7423Sroot if (u.u_segflg != 1) { 414*7423Sroot if (flag==B_WRITE) 415*7423Sroot t = copyin(u.u_base, (caddr_t)cp, n); 416*7423Sroot else 417*7423Sroot t = copyout((caddr_t)cp, u.u_base, n); 418*7423Sroot if (t) { 419*7423Sroot u.u_error = EFAULT; 420*7423Sroot return; 421*7423Sroot } 422*7423Sroot } else 423*7423Sroot if (flag == B_WRITE) 424*7423Sroot bcopy(u.u_base, (caddr_t)cp, n); 425*7423Sroot else 426*7423Sroot bcopy((caddr_t)cp, u.u_base, n); 427*7423Sroot u.u_base += n; 428*7423Sroot u.u_offset += n; 429*7423Sroot u.u_count -= n; 430*7423Sroot } 431