1*6254Sroot /* vfs_syscalls.c 4.21 82/03/18 */ 237Sbill 337Sbill #include "../h/param.h" 437Sbill #include "../h/systm.h" 537Sbill #include "../h/dir.h" 637Sbill #include "../h/user.h" 7*6254Sroot #include "../h/reg.h" 8*6254Sroot #include "../h/file.h" 937Sbill #include "../h/inode.h" 10*6254Sroot #include "../h/ino.h" 11*6254Sroot #include "../h/pte.h" 12*6254Sroot #include "../h/vm.h" 13*6254Sroot #include "../h/buf.h" 14*6254Sroot #include "../h/mtpr.h" 15*6254Sroot #include "../h/proc.h" 16*6254Sroot #include "../h/inline.h" 1737Sbill #include "../h/conf.h" 184918Swnj #include "../h/socket.h" 194918Swnj #include "../h/socketvar.h" 20*6254Sroot #include "../h/stat.h" 2137Sbill 22*6254Sroot chdir() 23*6254Sroot { 24*6254Sroot 25*6254Sroot chdirec(&u.u_cdir); 26*6254Sroot } 27*6254Sroot 28*6254Sroot chroot() 29*6254Sroot { 30*6254Sroot 31*6254Sroot if (suser()) 32*6254Sroot chdirec(&u.u_rdir); 33*6254Sroot } 34*6254Sroot 35*6254Sroot chdirec(ipp) 36*6254Sroot register struct inode **ipp; 37*6254Sroot { 38*6254Sroot register struct inode *ip; 39*6254Sroot struct a { 40*6254Sroot char *fname; 41*6254Sroot }; 42*6254Sroot 43*6254Sroot ip = namei(uchar, 0, 1); 44*6254Sroot if(ip == NULL) 45*6254Sroot return; 46*6254Sroot if((ip->i_mode&IFMT) != IFDIR) { 47*6254Sroot u.u_error = ENOTDIR; 48*6254Sroot goto bad; 49*6254Sroot } 50*6254Sroot if(access(ip, IEXEC)) 51*6254Sroot goto bad; 52*6254Sroot irele(ip); 53*6254Sroot if (*ipp) { 54*6254Sroot ilock(*ipp); 55*6254Sroot iput(*ipp); 56*6254Sroot } 57*6254Sroot *ipp = ip; 58*6254Sroot return; 59*6254Sroot 60*6254Sroot bad: 61*6254Sroot iput(ip); 62*6254Sroot } 63*6254Sroot 6437Sbill /* 65*6254Sroot * Open system call. 66*6254Sroot */ 67*6254Sroot open() 68*6254Sroot { 69*6254Sroot register struct inode *ip; 70*6254Sroot register struct a { 71*6254Sroot char *fname; 72*6254Sroot int rwmode; 73*6254Sroot } *uap; 74*6254Sroot 75*6254Sroot uap = (struct a *)u.u_ap; 76*6254Sroot ip = namei(uchar, 0, 1); 77*6254Sroot if (ip == NULL) 78*6254Sroot return; 79*6254Sroot open1(ip, ++uap->rwmode, 0); 80*6254Sroot } 81*6254Sroot 82*6254Sroot /* 83*6254Sroot * Creat system call. 84*6254Sroot */ 85*6254Sroot creat() 86*6254Sroot { 87*6254Sroot register struct inode *ip; 88*6254Sroot register struct a { 89*6254Sroot char *fname; 90*6254Sroot int fmode; 91*6254Sroot } *uap; 92*6254Sroot 93*6254Sroot uap = (struct a *)u.u_ap; 94*6254Sroot ip = namei(uchar, 1, 1); 95*6254Sroot if (ip == NULL) { 96*6254Sroot if (u.u_error) 97*6254Sroot return; 98*6254Sroot ip = maknode(uap->fmode&07777&(~ISVTX)); 99*6254Sroot if (ip==NULL) 100*6254Sroot return; 101*6254Sroot open1(ip, FWRITE, 2); 102*6254Sroot } else 103*6254Sroot open1(ip, FWRITE, 1); 104*6254Sroot } 105*6254Sroot 106*6254Sroot /* 107*6254Sroot * Common code for open and creat. 108*6254Sroot * Check permissions, allocate an open file structure, 109*6254Sroot * and call the device open routine if any. 110*6254Sroot */ 111*6254Sroot open1(ip, mode, trf) 112*6254Sroot register struct inode *ip; 113*6254Sroot register mode; 114*6254Sroot { 115*6254Sroot register struct file *fp; 116*6254Sroot int i; 117*6254Sroot 118*6254Sroot if (trf != 2) { 119*6254Sroot if (mode&FREAD) 120*6254Sroot (void) access(ip, IREAD); 121*6254Sroot if (mode&FWRITE) { 122*6254Sroot (void) access(ip, IWRITE); 123*6254Sroot if ((ip->i_mode&IFMT) == IFDIR) 124*6254Sroot u.u_error = EISDIR; 125*6254Sroot } 126*6254Sroot } 127*6254Sroot if (u.u_error) 128*6254Sroot goto out; 129*6254Sroot if (trf == 1) 130*6254Sroot itrunc(ip); 131*6254Sroot irele(ip); 132*6254Sroot if ((fp = falloc()) == NULL) 133*6254Sroot goto out; 134*6254Sroot fp->f_flag = mode&(FREAD|FWRITE); 135*6254Sroot i = u.u_r.r_val1; 136*6254Sroot fp->f_inode = ip; 137*6254Sroot openi(ip, mode&(FREAD|FWRITE)); 138*6254Sroot if (u.u_error == 0) 139*6254Sroot return; 140*6254Sroot u.u_ofile[i] = NULL; 141*6254Sroot fp->f_count--; 142*6254Sroot out: 143*6254Sroot if (ip != NULL) 144*6254Sroot iput(ip); 145*6254Sroot } 146*6254Sroot 147*6254Sroot /* 148*6254Sroot * Mknod system call 149*6254Sroot */ 150*6254Sroot mknod() 151*6254Sroot { 152*6254Sroot register struct inode *ip; 153*6254Sroot register struct a { 154*6254Sroot char *fname; 155*6254Sroot int fmode; 156*6254Sroot int dev; 157*6254Sroot } *uap; 158*6254Sroot 159*6254Sroot uap = (struct a *)u.u_ap; 160*6254Sroot if (suser()) { 161*6254Sroot ip = namei(uchar, 1, 0); 162*6254Sroot if (ip != NULL) { 163*6254Sroot u.u_error = EEXIST; 164*6254Sroot goto out; 165*6254Sroot } 166*6254Sroot } 167*6254Sroot if (u.u_error) 168*6254Sroot return; 169*6254Sroot ip = maknode(uap->fmode); 170*6254Sroot if (ip == NULL) 171*6254Sroot return; 172*6254Sroot if (uap->dev) { 173*6254Sroot /* 174*6254Sroot * Want to be able to use this to make badblock 175*6254Sroot * inodes, so don't truncate the dev number. 176*6254Sroot */ 177*6254Sroot ip->i_un.i_rdev = uap->dev; 178*6254Sroot ip->i_flag |= IACC|IUPD|ICHG; 179*6254Sroot } 180*6254Sroot 181*6254Sroot out: 182*6254Sroot iput(ip); 183*6254Sroot } 184*6254Sroot 185*6254Sroot /* 186*6254Sroot * link system call 187*6254Sroot */ 188*6254Sroot link() 189*6254Sroot { 190*6254Sroot register struct inode *ip, *xp; 191*6254Sroot register struct a { 192*6254Sroot char *target; 193*6254Sroot char *linkname; 194*6254Sroot } *uap; 195*6254Sroot 196*6254Sroot uap = (struct a *)u.u_ap; 197*6254Sroot ip = namei(uchar, 0, 1); /* well, this routine is doomed anyhow */ 198*6254Sroot if (ip == NULL) 199*6254Sroot return; 200*6254Sroot if ((ip->i_mode&IFMT)==IFDIR && !suser()) 201*6254Sroot goto out1; 202*6254Sroot ip->i_nlink++; 203*6254Sroot ip->i_flag |= ICHG; 204*6254Sroot iupdat(ip, &time, &time, 1); 205*6254Sroot irele(ip); 206*6254Sroot u.u_dirp = (caddr_t)uap->linkname; 207*6254Sroot xp = namei(uchar, 1, 0); 208*6254Sroot if (xp != NULL) { 209*6254Sroot u.u_error = EEXIST; 210*6254Sroot iput(xp); 211*6254Sroot goto out; 212*6254Sroot } 213*6254Sroot if (u.u_error) 214*6254Sroot goto out; 215*6254Sroot if (u.u_pdir->i_dev != ip->i_dev) { 216*6254Sroot iput(u.u_pdir); 217*6254Sroot u.u_error = EXDEV; 218*6254Sroot goto out; 219*6254Sroot } 220*6254Sroot wdir(ip); 221*6254Sroot out: 222*6254Sroot if (u.u_error) { 223*6254Sroot ip->i_nlink--; 224*6254Sroot ip->i_flag |= ICHG; 225*6254Sroot } 226*6254Sroot out1: 227*6254Sroot iput(ip); 228*6254Sroot } 229*6254Sroot 230*6254Sroot /* 231*6254Sroot * symlink -- make a symbolic link 232*6254Sroot */ 233*6254Sroot symlink() 234*6254Sroot { 235*6254Sroot register struct a { 236*6254Sroot char *target; 237*6254Sroot char *linkname; 238*6254Sroot } *uap; 239*6254Sroot register struct inode *ip; 240*6254Sroot register char *tp; 241*6254Sroot register c, nc; 242*6254Sroot 243*6254Sroot uap = (struct a *)u.u_ap; 244*6254Sroot tp = uap->target; 245*6254Sroot nc = 0; 246*6254Sroot while (c = fubyte(tp)) { 247*6254Sroot if (c < 0) { 248*6254Sroot u.u_error = EFAULT; 249*6254Sroot return; 250*6254Sroot } 251*6254Sroot tp++; 252*6254Sroot nc++; 253*6254Sroot } 254*6254Sroot u.u_dirp = uap->linkname; 255*6254Sroot ip = namei(uchar, 1, 0); 256*6254Sroot if (ip) { 257*6254Sroot iput(ip); 258*6254Sroot u.u_error = EEXIST; 259*6254Sroot return; 260*6254Sroot } 261*6254Sroot if (u.u_error) 262*6254Sroot return; 263*6254Sroot ip = maknode(IFLNK | 0777); 264*6254Sroot if (ip == NULL) 265*6254Sroot return; 266*6254Sroot u.u_base = uap->target; 267*6254Sroot u.u_count = nc; 268*6254Sroot u.u_offset = 0; 269*6254Sroot u.u_segflg = 0; 270*6254Sroot writei(ip); 271*6254Sroot iput(ip); 272*6254Sroot } 273*6254Sroot 274*6254Sroot /* 275*6254Sroot * Unlink system call. 276*6254Sroot * Hard to avoid races here, especially 277*6254Sroot * in unlinking directories. 278*6254Sroot */ 279*6254Sroot unlink() 280*6254Sroot { 281*6254Sroot register struct inode *ip, *pp; 282*6254Sroot struct a { 283*6254Sroot char *fname; 284*6254Sroot }; 285*6254Sroot 286*6254Sroot pp = namei(uchar, 2, 0); 287*6254Sroot if(pp == NULL) 288*6254Sroot return; 289*6254Sroot /* 290*6254Sroot * Check for unlink(".") 291*6254Sroot * to avoid hanging on the iget 292*6254Sroot */ 293*6254Sroot if (pp->i_number == u.u_dent.d_ino) { 294*6254Sroot ip = pp; 295*6254Sroot ip->i_count++; 296*6254Sroot } else 297*6254Sroot ip = iget(pp->i_dev, u.u_dent.d_ino); 298*6254Sroot if(ip == NULL) 299*6254Sroot goto out1; 300*6254Sroot if((ip->i_mode&IFMT)==IFDIR && !suser()) 301*6254Sroot goto out; 302*6254Sroot /* 303*6254Sroot * Don't unlink a mounted file. 304*6254Sroot */ 305*6254Sroot if (ip->i_dev != pp->i_dev) { 306*6254Sroot u.u_error = EBUSY; 307*6254Sroot goto out; 308*6254Sroot } 309*6254Sroot if (ip->i_flag&ITEXT) 310*6254Sroot xrele(ip); /* try once to free text */ 311*6254Sroot /* 312*6254Sroot if ((ip->i_flag&ITEXT) && ip->i_nlink==1) { 313*6254Sroot u.u_error = ETXTBSY; 314*6254Sroot goto out; 315*6254Sroot } 316*6254Sroot */ 317*6254Sroot u.u_offset -= sizeof(struct direct); 318*6254Sroot u.u_base = (caddr_t)&u.u_dent; 319*6254Sroot u.u_count = sizeof(struct direct); 320*6254Sroot u.u_dent.d_ino = 0; 321*6254Sroot writei(pp); 322*6254Sroot ip->i_nlink--; 323*6254Sroot ip->i_flag |= ICHG; 324*6254Sroot 325*6254Sroot out: 326*6254Sroot iput(ip); 327*6254Sroot out1: 328*6254Sroot iput(pp); 329*6254Sroot } 330*6254Sroot 331*6254Sroot /* 332*6254Sroot * Seek system call 333*6254Sroot */ 334*6254Sroot seek() 335*6254Sroot { 336*6254Sroot register struct file *fp; 337*6254Sroot register struct a { 338*6254Sroot int fdes; 339*6254Sroot off_t off; 340*6254Sroot int sbase; 341*6254Sroot } *uap; 342*6254Sroot 343*6254Sroot uap = (struct a *)u.u_ap; 344*6254Sroot fp = getf(uap->fdes); 345*6254Sroot if (fp == NULL) 346*6254Sroot return; 347*6254Sroot if (fp->f_flag&FSOCKET) { 348*6254Sroot u.u_error = ESPIPE; 349*6254Sroot return; 350*6254Sroot } 351*6254Sroot if (uap->sbase == 1) 352*6254Sroot uap->off += fp->f_offset; 353*6254Sroot else if (uap->sbase == 2) 354*6254Sroot uap->off += fp->f_inode->i_size; 355*6254Sroot fp->f_offset = uap->off; 356*6254Sroot u.u_r.r_off = uap->off; 357*6254Sroot } 358*6254Sroot 359*6254Sroot /* 360*6254Sroot * Access system call 361*6254Sroot */ 362*6254Sroot saccess() 363*6254Sroot { 364*6254Sroot register svuid, svgid; 365*6254Sroot register struct inode *ip; 366*6254Sroot register struct a { 367*6254Sroot char *fname; 368*6254Sroot int fmode; 369*6254Sroot } *uap; 370*6254Sroot 371*6254Sroot uap = (struct a *)u.u_ap; 372*6254Sroot svuid = u.u_uid; 373*6254Sroot svgid = u.u_gid; 374*6254Sroot u.u_uid = u.u_ruid; 375*6254Sroot u.u_gid = u.u_rgid; 376*6254Sroot ip = namei(uchar, 0, 1); 377*6254Sroot if (ip != NULL) { 378*6254Sroot if (uap->fmode&(IREAD>>6)) 379*6254Sroot (void) access(ip, IREAD); 380*6254Sroot if (uap->fmode&(IWRITE>>6)) 381*6254Sroot (void) access(ip, IWRITE); 382*6254Sroot if (uap->fmode&(IEXEC>>6)) 383*6254Sroot (void) access(ip, IEXEC); 384*6254Sroot iput(ip); 385*6254Sroot } 386*6254Sroot u.u_uid = svuid; 387*6254Sroot u.u_gid = svgid; 388*6254Sroot } 389*6254Sroot 390*6254Sroot /* 39137Sbill * the fstat system call. 39237Sbill */ 39337Sbill fstat() 39437Sbill { 39537Sbill register struct file *fp; 39637Sbill register struct a { 39737Sbill int fdes; 39837Sbill struct stat *sb; 39937Sbill } *uap; 40037Sbill 40137Sbill uap = (struct a *)u.u_ap; 40237Sbill fp = getf(uap->fdes); 4034828Swnj if (fp == NULL) 40437Sbill return; 4054828Swnj if (fp->f_flag & FSOCKET) 4064891Swnj u.u_error = sostat(fp->f_socket, uap->sb); 4074828Swnj else 4084828Swnj stat1(fp->f_inode, uap->sb); 40937Sbill } 41037Sbill 41137Sbill /* 4125992Swnj * Stat system call. This version does not follow links. 41337Sbill */ 41437Sbill stat() 41537Sbill { 41637Sbill register struct inode *ip; 41737Sbill register struct a { 41837Sbill char *fname; 41937Sbill struct stat *sb; 42037Sbill } *uap; 42137Sbill 42237Sbill uap = (struct a *)u.u_ap; 4235992Swnj ip = namei(uchar, 0, 0); 4244828Swnj if (ip == NULL) 42537Sbill return; 4263624Sroot stat1(ip, uap->sb); 42737Sbill iput(ip); 42837Sbill } 42937Sbill 43037Sbill /* 4315992Swnj * Lstat system call. This version does follow links. 4325992Swnj */ 4335992Swnj lstat() 4345992Swnj { 4355992Swnj register struct inode *ip; 4365992Swnj register struct a { 4375992Swnj char *fname; 4385992Swnj struct stat *sb; 4395992Swnj } *uap; 4405992Swnj 4415992Swnj uap = (struct a *)u.u_ap; 4425992Swnj ip = namei(uchar, 0, 1); 4435992Swnj if (ip == NULL) 4445992Swnj return; 4456153Ssam stat1(ip, uap->sb); 4465992Swnj iput(ip); 4475992Swnj } 4485992Swnj 4495992Swnj /* 45037Sbill * The basic routine for fstat and stat: 45137Sbill * get the inode and pass appropriate parts back. 45237Sbill */ 4533624Sroot stat1(ip, ub) 4544828Swnj register struct inode *ip; 4554828Swnj struct stat *ub; 45637Sbill { 45737Sbill register struct dinode *dp; 45837Sbill register struct buf *bp; 45937Sbill struct stat ds; 46037Sbill 4611204Sbill IUPDAT(ip, &time, &time, 0); 46237Sbill /* 4634828Swnj * First copy from inode table 46437Sbill */ 46537Sbill ds.st_dev = ip->i_dev; 46637Sbill ds.st_ino = ip->i_number; 46737Sbill ds.st_mode = ip->i_mode; 46837Sbill ds.st_nlink = ip->i_nlink; 46937Sbill ds.st_uid = ip->i_uid; 47037Sbill ds.st_gid = ip->i_gid; 47137Sbill ds.st_rdev = (dev_t)ip->i_un.i_rdev; 4723624Sroot ds.st_size = ip->i_size; 47337Sbill /* 4745992Swnj * next the dates in the disk 47537Sbill */ 47637Sbill bp = bread(ip->i_dev, itod(ip->i_number)); 47737Sbill dp = bp->b_un.b_dino; 47837Sbill dp += itoo(ip->i_number); 47937Sbill ds.st_atime = dp->di_atime; 48037Sbill ds.st_mtime = dp->di_mtime; 48137Sbill ds.st_ctime = dp->di_ctime; 48237Sbill brelse(bp); 48337Sbill if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 48437Sbill u.u_error = EFAULT; 48537Sbill } 48637Sbill 48737Sbill /* 4885992Swnj * Return target name of a symbolic link 48937Sbill */ 4905992Swnj readlink() 4915992Swnj { 4925992Swnj register struct inode *ip; 4935992Swnj register struct a { 4945992Swnj char *name; 4955992Swnj char *buf; 4965992Swnj int count; 4975992Swnj } *uap; 4985992Swnj 4995992Swnj ip = namei(uchar, 0, 0); 5005992Swnj if (ip == NULL) 5015992Swnj return; 5025992Swnj if ((ip->i_mode&IFMT) != IFLNK) { 5035992Swnj u.u_error = ENXIO; 5045992Swnj goto out; 5055992Swnj } 5065992Swnj uap = (struct a *)u.u_ap; 5075992Swnj u.u_offset = 0; 5085992Swnj u.u_base = uap->buf; 5095992Swnj u.u_count = uap->count; 5105992Swnj u.u_segflg = 0; 5115992Swnj readi(ip); 5125992Swnj out: 5135992Swnj iput(ip); 5145992Swnj u.u_r.r_val1 = uap->count - u.u_count; 5155992Swnj } 5165992Swnj 517*6254Sroot chmod() 5185992Swnj { 519*6254Sroot register struct inode *ip; 5205992Swnj register struct a { 521*6254Sroot char *fname; 522*6254Sroot int fmode; 5235992Swnj } *uap; 5245992Swnj 5255992Swnj uap = (struct a *)u.u_ap; 526*6254Sroot if ((ip = owner(1)) == NULL) 5275992Swnj return; 528*6254Sroot ip->i_mode &= ~07777; 529*6254Sroot if (u.u_uid) 530*6254Sroot uap->fmode &= ~ISVTX; 531*6254Sroot ip->i_mode |= uap->fmode&07777; 532*6254Sroot ip->i_flag |= ICHG; 533*6254Sroot if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 534*6254Sroot xrele(ip); 5355992Swnj iput(ip); 5365992Swnj } 5375992Swnj 538*6254Sroot chown() 53937Sbill { 540*6254Sroot register struct inode *ip; 54137Sbill register struct a { 542*6254Sroot char *fname; 543*6254Sroot int uid; 544*6254Sroot int gid; 54537Sbill } *uap; 54637Sbill 54737Sbill uap = (struct a *)u.u_ap; 548*6254Sroot if (!suser() || (ip = owner(0)) == NULL) 54937Sbill return; 550*6254Sroot ip->i_uid = uap->uid; 551*6254Sroot ip->i_gid = uap->gid; 552*6254Sroot ip->i_flag |= ICHG; 553*6254Sroot if (u.u_ruid != 0) 554*6254Sroot ip->i_mode &= ~(ISUID|ISGID); 555*6254Sroot iput(ip); 55637Sbill } 55737Sbill 55837Sbill /* 559*6254Sroot * Set IUPD and IACC times on file. 560*6254Sroot * Can't set ICHG. 56137Sbill */ 562*6254Sroot utime() 5634828Swnj { 56437Sbill register struct a { 565*6254Sroot char *fname; 566*6254Sroot time_t *tptr; 56737Sbill } *uap; 568*6254Sroot register struct inode *ip; 569*6254Sroot time_t tv[2]; 57037Sbill 57137Sbill uap = (struct a *)u.u_ap; 572*6254Sroot if ((ip = owner(1)) == NULL) 57337Sbill return; 574*6254Sroot if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { 575*6254Sroot u.u_error = EFAULT; 576*6254Sroot } else { 577*6254Sroot ip->i_flag |= IACC|IUPD|ICHG; 578*6254Sroot iupdat(ip, &tv[0], &tv[1], 0); 57937Sbill } 58037Sbill iput(ip); 58137Sbill } 58237Sbill 583*6254Sroot sync() 58437Sbill { 58537Sbill 5865416Swnj update(0); 58737Sbill } 588