1*7439Sroot /* vfs_syscalls.c 4.28 82/07/15 */ 237Sbill 337Sbill #include "../h/param.h" 437Sbill #include "../h/systm.h" 537Sbill #include "../h/dir.h" 637Sbill #include "../h/user.h" 76254Sroot #include "../h/file.h" 86574Smckusic #include "../h/stat.h" 937Sbill #include "../h/inode.h" 106574Smckusic #include "../h/fs.h" 116254Sroot #include "../h/buf.h" 126254Sroot #include "../h/proc.h" 136254Sroot #include "../h/inline.h" 14*7439Sroot #ifdef EFS 15*7439Sroot #include "../net/in.h" 16*7439Sroot #include "../h/efs.h" 17*7439Sroot #endif 1837Sbill 196254Sroot chdir() 206254Sroot { 216254Sroot 226254Sroot chdirec(&u.u_cdir); 236254Sroot } 246254Sroot 256254Sroot chroot() 266254Sroot { 276254Sroot 286254Sroot if (suser()) 296254Sroot chdirec(&u.u_rdir); 306254Sroot } 316254Sroot 326254Sroot chdirec(ipp) 336254Sroot register struct inode **ipp; 346254Sroot { 356254Sroot register struct inode *ip; 366254Sroot struct a { 376254Sroot char *fname; 386254Sroot }; 396254Sroot 406254Sroot ip = namei(uchar, 0, 1); 416254Sroot if(ip == NULL) 426254Sroot return; 436254Sroot if((ip->i_mode&IFMT) != IFDIR) { 446254Sroot u.u_error = ENOTDIR; 456254Sroot goto bad; 466254Sroot } 476254Sroot if(access(ip, IEXEC)) 486254Sroot goto bad; 497122Smckusick iunlock(ip); 507142Smckusick if (*ipp) 517142Smckusick irele(*ipp); 526254Sroot *ipp = ip; 536254Sroot return; 546254Sroot 556254Sroot bad: 566254Sroot iput(ip); 576254Sroot } 586254Sroot 5937Sbill /* 606254Sroot * Open system call. 616254Sroot */ 626254Sroot open() 636254Sroot { 646254Sroot register struct inode *ip; 656254Sroot register struct a { 666254Sroot char *fname; 676254Sroot int rwmode; 686254Sroot } *uap; 696254Sroot 706254Sroot uap = (struct a *)u.u_ap; 716254Sroot ip = namei(uchar, 0, 1); 726254Sroot if (ip == NULL) 736254Sroot return; 746254Sroot open1(ip, ++uap->rwmode, 0); 756254Sroot } 766254Sroot 776254Sroot /* 786254Sroot * Creat system call. 796254Sroot */ 806254Sroot creat() 816254Sroot { 826254Sroot register struct inode *ip; 836254Sroot register struct a { 846254Sroot char *fname; 856254Sroot int fmode; 866254Sroot } *uap; 876254Sroot 886254Sroot uap = (struct a *)u.u_ap; 896254Sroot ip = namei(uchar, 1, 1); 906254Sroot if (ip == NULL) { 916254Sroot if (u.u_error) 926254Sroot return; 936254Sroot ip = maknode(uap->fmode&07777&(~ISVTX)); 946254Sroot if (ip==NULL) 956254Sroot return; 966254Sroot open1(ip, FWRITE, 2); 976254Sroot } else 986254Sroot open1(ip, FWRITE, 1); 996254Sroot } 1006254Sroot 1016254Sroot /* 1026254Sroot * Common code for open and creat. 1036254Sroot * Check permissions, allocate an open file structure, 1046254Sroot * and call the device open routine if any. 1056254Sroot */ 1066254Sroot open1(ip, mode, trf) 1076254Sroot register struct inode *ip; 1086254Sroot register mode; 1096254Sroot { 1106254Sroot register struct file *fp; 1116254Sroot int i; 1126254Sroot 1136254Sroot if (trf != 2) { 1146254Sroot if (mode&FREAD) 1156254Sroot (void) access(ip, IREAD); 1166254Sroot if (mode&FWRITE) { 1176254Sroot (void) access(ip, IWRITE); 1186254Sroot if ((ip->i_mode&IFMT) == IFDIR) 1196254Sroot u.u_error = EISDIR; 1206254Sroot } 1216254Sroot } 1227142Smckusick if (u.u_error) { 1237142Smckusick iput(ip); 1247142Smckusick return; 1257142Smckusick } 1266254Sroot if (trf == 1) 1276254Sroot itrunc(ip); 1287122Smckusick iunlock(ip); 1296254Sroot if ((fp = falloc()) == NULL) 1306254Sroot goto out; 1316254Sroot fp->f_flag = mode&(FREAD|FWRITE); 1326254Sroot i = u.u_r.r_val1; 1336254Sroot fp->f_inode = ip; 134*7439Sroot #ifdef EFS 135*7439Sroot openi(ip, mode&(FREAD|FWRITE), trf); 136*7439Sroot #else 1376254Sroot openi(ip, mode&(FREAD|FWRITE)); 138*7439Sroot #endif 1396254Sroot if (u.u_error == 0) 1406254Sroot return; 1416254Sroot u.u_ofile[i] = NULL; 1426254Sroot fp->f_count--; 1436254Sroot out: 1447142Smckusick irele(ip); 1456254Sroot } 1466254Sroot 1476254Sroot /* 1486254Sroot * Mknod system call 1496254Sroot */ 1506254Sroot mknod() 1516254Sroot { 1526254Sroot register struct inode *ip; 1536254Sroot register struct a { 1546254Sroot char *fname; 1556254Sroot int fmode; 1566254Sroot int dev; 1576254Sroot } *uap; 1586254Sroot 1596254Sroot uap = (struct a *)u.u_ap; 1606254Sroot if (suser()) { 1616254Sroot ip = namei(uchar, 1, 0); 1626254Sroot if (ip != NULL) { 1636254Sroot u.u_error = EEXIST; 1646254Sroot goto out; 1656254Sroot } 1666254Sroot } 1676254Sroot if (u.u_error) 1686254Sroot return; 1696254Sroot ip = maknode(uap->fmode); 1706254Sroot if (ip == NULL) 1716254Sroot return; 1726254Sroot if (uap->dev) { 1736254Sroot /* 1746254Sroot * Want to be able to use this to make badblock 1756254Sroot * inodes, so don't truncate the dev number. 1766254Sroot */ 1776574Smckusic ip->i_rdev = uap->dev; 1786254Sroot ip->i_flag |= IACC|IUPD|ICHG; 1796254Sroot } 1806254Sroot 1816254Sroot out: 1826254Sroot iput(ip); 1836254Sroot } 1846254Sroot 1856254Sroot /* 1866254Sroot * link system call 1876254Sroot */ 1886254Sroot link() 1896254Sroot { 1906254Sroot register struct inode *ip, *xp; 1916254Sroot register struct a { 1926254Sroot char *target; 1936254Sroot char *linkname; 1946254Sroot } *uap; 1956254Sroot 1966254Sroot uap = (struct a *)u.u_ap; 1976254Sroot ip = namei(uchar, 0, 1); /* well, this routine is doomed anyhow */ 1986254Sroot if (ip == NULL) 1996254Sroot return; 200*7439Sroot if ((ip->i_mode&IFMT)==IFDIR && !suser()) { 201*7439Sroot iput(ip); 202*7439Sroot return; 203*7439Sroot } 2046254Sroot ip->i_nlink++; 2056254Sroot ip->i_flag |= ICHG; 2066254Sroot iupdat(ip, &time, &time, 1); 2077122Smckusick iunlock(ip); 2086254Sroot u.u_dirp = (caddr_t)uap->linkname; 2096254Sroot xp = namei(uchar, 1, 0); 2106254Sroot if (xp != NULL) { 2116254Sroot u.u_error = EEXIST; 2126254Sroot iput(xp); 2136254Sroot goto out; 2146254Sroot } 2156254Sroot if (u.u_error) 2166254Sroot goto out; 2176254Sroot if (u.u_pdir->i_dev != ip->i_dev) { 2186254Sroot iput(u.u_pdir); 2196254Sroot u.u_error = EXDEV; 2206254Sroot goto out; 2216254Sroot } 2226254Sroot wdir(ip); 2236254Sroot out: 2246254Sroot if (u.u_error) { 2256254Sroot ip->i_nlink--; 2266254Sroot ip->i_flag |= ICHG; 2276254Sroot } 2286254Sroot out1: 2297142Smckusick irele(ip); 2306254Sroot } 2316254Sroot 2326254Sroot /* 2336254Sroot * symlink -- make a symbolic link 2346254Sroot */ 2356254Sroot symlink() 2366254Sroot { 2376254Sroot register struct a { 2386254Sroot char *target; 2396254Sroot char *linkname; 2406254Sroot } *uap; 2416254Sroot register struct inode *ip; 2426254Sroot register char *tp; 2436254Sroot register c, nc; 2446254Sroot 2456254Sroot uap = (struct a *)u.u_ap; 2466254Sroot tp = uap->target; 2476254Sroot nc = 0; 2486254Sroot while (c = fubyte(tp)) { 2496254Sroot if (c < 0) { 2506254Sroot u.u_error = EFAULT; 2516254Sroot return; 2526254Sroot } 2536254Sroot tp++; 2546254Sroot nc++; 2556254Sroot } 2566254Sroot u.u_dirp = uap->linkname; 2576254Sroot ip = namei(uchar, 1, 0); 2586254Sroot if (ip) { 2596254Sroot iput(ip); 2606254Sroot u.u_error = EEXIST; 2616254Sroot return; 2626254Sroot } 2636254Sroot if (u.u_error) 2646254Sroot return; 2656254Sroot ip = maknode(IFLNK | 0777); 2666254Sroot if (ip == NULL) 2676254Sroot return; 2686254Sroot u.u_base = uap->target; 2696254Sroot u.u_count = nc; 2706254Sroot u.u_offset = 0; 2716254Sroot u.u_segflg = 0; 2726254Sroot writei(ip); 2736254Sroot iput(ip); 2746254Sroot } 2756254Sroot 2766254Sroot /* 2776254Sroot * Unlink system call. 2786254Sroot * Hard to avoid races here, especially 2796254Sroot * in unlinking directories. 2806254Sroot */ 2816254Sroot unlink() 2826254Sroot { 2836254Sroot register struct inode *ip, *pp; 2846254Sroot struct a { 2856254Sroot char *fname; 2866254Sroot }; 2876574Smckusic struct fs *fs; 2886574Smckusic struct buf *bp; 2896574Smckusic int lbn, bn, base; 2907142Smckusick int unlinkingdot = 0; 2916254Sroot 2926254Sroot pp = namei(uchar, 2, 0); 2936254Sroot if(pp == NULL) 2946254Sroot return; 295*7439Sroot #ifdef EFS 296*7439Sroot /* divert to extended file system if off machine. */ 297*7439Sroot if (efsinode(pp)) { 298*7439Sroot dev_t ndev = pp->i_rdev; 299*7439Sroot 300*7439Sroot iput(pp); /* avoid recursive hang on inode */ 301*7439Sroot efsunlink(ndev); 302*7439Sroot if (u.u_error != EEXIST) 303*7439Sroot return; 304*7439Sroot 305*7439Sroot /* 306*7439Sroot * If a null pathname remainder, then do 307*7439Sroot * the unlink locally after restoring state. 308*7439Sroot */ 309*7439Sroot u.u_error = 0; 310*7439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 311*7439Sroot pp = namei(uchar, 2, 0); 312*7439Sroot } 313*7439Sroot #endif 314*7439Sroot 3156254Sroot /* 3166254Sroot * Check for unlink(".") 3176254Sroot * to avoid hanging on the iget 3186254Sroot */ 3196254Sroot if (pp->i_number == u.u_dent.d_ino) { 3206254Sroot ip = pp; 3216254Sroot ip->i_count++; 3227142Smckusick unlinkingdot++; 3236254Sroot } else 3246574Smckusic ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino); 3256254Sroot if(ip == NULL) 3266254Sroot goto out1; 3276254Sroot if((ip->i_mode&IFMT)==IFDIR && !suser()) 3286254Sroot goto out; 3296254Sroot /* 3306254Sroot * Don't unlink a mounted file. 3316254Sroot */ 3326254Sroot if (ip->i_dev != pp->i_dev) { 3336254Sroot u.u_error = EBUSY; 3346254Sroot goto out; 3356254Sroot } 3366254Sroot if (ip->i_flag&ITEXT) 3376254Sroot xrele(ip); /* try once to free text */ 3386254Sroot /* 3396254Sroot if ((ip->i_flag&ITEXT) && ip->i_nlink==1) { 3406254Sroot u.u_error = ETXTBSY; 3416254Sroot goto out; 3426254Sroot } 3436254Sroot */ 3446574Smckusic if (u.u_count == 0) { 3456574Smckusic /* 3466574Smckusic * first entry in block, so set d_ino to zero. 3476574Smckusic */ 3486574Smckusic u.u_base = (caddr_t)&u.u_dent; 3496574Smckusic u.u_count = DIRSIZ(&u.u_dent); 3506574Smckusic u.u_dent.d_ino = 0; 3516574Smckusic writei(pp); 3526574Smckusic } else { 3536574Smckusic /* 3546574Smckusic * updating preceeding entry to skip over current entry. 3556574Smckusic */ 3566574Smckusic fs = pp->i_fs; 3576574Smckusic lbn = lblkno(fs, u.u_offset); 3586574Smckusic base = blkoff(fs, u.u_offset); 3596574Smckusic bn = fsbtodb(fs, bmap(pp, lbn, B_WRITE, base + u.u_count)); 3606574Smckusic bp = bread(pp->i_dev, bn, blksize(fs, pp, lbn)); 3616574Smckusic if (bp->b_flags & B_ERROR) { 3626574Smckusic brelse(bp); 3636574Smckusic goto out; 3646574Smckusic } 3656574Smckusic ((struct direct *)(bp->b_un.b_addr + base))->d_reclen += 3666574Smckusic u.u_dent.d_reclen; 3676574Smckusic bwrite(bp); 3686574Smckusic pp->i_flag |= IUPD|ICHG; 3696574Smckusic } 3706254Sroot ip->i_nlink--; 3716254Sroot ip->i_flag |= ICHG; 3726254Sroot 3736254Sroot out: 3747142Smckusick if (unlinkingdot) 3757142Smckusick irele(ip); 3767142Smckusick else 3777142Smckusick iput(ip); 3786254Sroot out1: 3796254Sroot iput(pp); 3806254Sroot } 3816254Sroot 3826254Sroot /* 3836254Sroot * Seek system call 3846254Sroot */ 3856254Sroot seek() 3866254Sroot { 3876254Sroot register struct file *fp; 3886254Sroot register struct a { 3896254Sroot int fdes; 3906254Sroot off_t off; 3916254Sroot int sbase; 3926254Sroot } *uap; 3936254Sroot 3946254Sroot uap = (struct a *)u.u_ap; 3956254Sroot fp = getf(uap->fdes); 3966254Sroot if (fp == NULL) 3976254Sroot return; 3986254Sroot if (fp->f_flag&FSOCKET) { 3996254Sroot u.u_error = ESPIPE; 4006254Sroot return; 4016254Sroot } 4026254Sroot if (uap->sbase == 1) 4036254Sroot uap->off += fp->f_offset; 404*7439Sroot else if (uap->sbase == 2) { 405*7439Sroot #ifdef EFS 406*7439Sroot struct inode *ip = fp->f_inode; 407*7439Sroot uap->off += efsinode(ip) ? efsfilesize(fp) : ip->i_size; 408*7439Sroot #else 4096254Sroot uap->off += fp->f_inode->i_size; 410*7439Sroot #endif 411*7439Sroot } 4126254Sroot fp->f_offset = uap->off; 4136254Sroot u.u_r.r_off = uap->off; 4146254Sroot } 4156254Sroot 4166254Sroot /* 4176254Sroot * Access system call 4186254Sroot */ 4196254Sroot saccess() 4206254Sroot { 4216254Sroot register svuid, svgid; 4226254Sroot register struct inode *ip; 4236254Sroot register struct a { 4246254Sroot char *fname; 4256254Sroot int fmode; 4266254Sroot } *uap; 4276254Sroot 4286254Sroot uap = (struct a *)u.u_ap; 4296254Sroot svuid = u.u_uid; 4306254Sroot svgid = u.u_gid; 4316254Sroot u.u_uid = u.u_ruid; 4326254Sroot u.u_gid = u.u_rgid; 4336254Sroot ip = namei(uchar, 0, 1); 434*7439Sroot #ifdef EFS 435*7439Sroot if (efsinode(ip)) { 436*7439Sroot dev_t ndev = ip->i_rdev; 437*7439Sroot 438*7439Sroot iput(ip); 439*7439Sroot efssaccess(ndev); 440*7439Sroot if (u.u_error != EEXIST) 441*7439Sroot return; 442*7439Sroot u.u_error = 0; 443*7439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 444*7439Sroot ip = namei(uchar, 0, 1); 445*7439Sroot } 446*7439Sroot #endif 4476254Sroot if (ip != NULL) { 4486254Sroot if (uap->fmode&(IREAD>>6)) 4496254Sroot (void) access(ip, IREAD); 4506254Sroot if (uap->fmode&(IWRITE>>6)) 4516254Sroot (void) access(ip, IWRITE); 4526254Sroot if (uap->fmode&(IEXEC>>6)) 4536254Sroot (void) access(ip, IEXEC); 4546254Sroot iput(ip); 4556254Sroot } 4566254Sroot u.u_uid = svuid; 4576254Sroot u.u_gid = svgid; 4586254Sroot } 4596254Sroot 4606254Sroot /* 46137Sbill * the fstat system call. 46237Sbill */ 46337Sbill fstat() 46437Sbill { 46537Sbill register struct file *fp; 46637Sbill register struct a { 46737Sbill int fdes; 46837Sbill struct stat *sb; 46937Sbill } *uap; 47037Sbill 47137Sbill uap = (struct a *)u.u_ap; 47237Sbill fp = getf(uap->fdes); 4734828Swnj if (fp == NULL) 47437Sbill return; 475*7439Sroot #ifdef EFS 476*7439Sroot if (efsinode(fp->f_inode)) { 477*7439Sroot efsfstat(fp->f_inode->i_rdev, fp); 478*7439Sroot return; 479*7439Sroot } 480*7439Sroot #endif 4814828Swnj if (fp->f_flag & FSOCKET) 4824891Swnj u.u_error = sostat(fp->f_socket, uap->sb); 4834828Swnj else 4844828Swnj stat1(fp->f_inode, uap->sb); 48537Sbill } 48637Sbill 48737Sbill /* 4886574Smckusic * Stat system call. This version follows links. 48937Sbill */ 49037Sbill stat() 49137Sbill { 49237Sbill register struct inode *ip; 49337Sbill register struct a { 49437Sbill char *fname; 49537Sbill struct stat *sb; 49637Sbill } *uap; 49737Sbill 49837Sbill uap = (struct a *)u.u_ap; 4996423Sroot ip = namei(uchar, 0, 1); 5004828Swnj if (ip == NULL) 50137Sbill return; 502*7439Sroot #ifdef EFS 503*7439Sroot if (efsinode(ip)) { 504*7439Sroot dev_t ndev = ip->i_rdev; 505*7439Sroot 506*7439Sroot iput(ip); 507*7439Sroot efsstat(ndev); 508*7439Sroot if (u.u_error != EEXIST) 509*7439Sroot return; 510*7439Sroot u.u_error = 0; 511*7439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 512*7439Sroot ip = namei(uchar, 0, 1); 513*7439Sroot } 514*7439Sroot #endif 5153624Sroot stat1(ip, uap->sb); 51637Sbill iput(ip); 51737Sbill } 51837Sbill 51937Sbill /* 5206574Smckusic * Lstat system call. This version does not follow links. 5215992Swnj */ 5225992Swnj lstat() 5235992Swnj { 5245992Swnj register struct inode *ip; 5255992Swnj register struct a { 5265992Swnj char *fname; 5275992Swnj struct stat *sb; 5285992Swnj } *uap; 5295992Swnj 5305992Swnj uap = (struct a *)u.u_ap; 5316423Sroot ip = namei(uchar, 0, 0); 5325992Swnj if (ip == NULL) 5335992Swnj return; 534*7439Sroot #ifdef EFS 535*7439Sroot if (efsinode(ip)) { 536*7439Sroot dev_t ndev = ip->i_rdev; 537*7439Sroot 538*7439Sroot iput(ip); 539*7439Sroot efslstat(ndev); 540*7439Sroot if (u.u_error != EEXIST) 541*7439Sroot return; 542*7439Sroot u.u_error = 0; 543*7439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 544*7439Sroot ip = namei(uchar, 0, 0); 545*7439Sroot } 546*7439Sroot #endif 5476153Ssam stat1(ip, uap->sb); 5485992Swnj iput(ip); 5495992Swnj } 5505992Swnj 5515992Swnj /* 55237Sbill * The basic routine for fstat and stat: 55337Sbill * get the inode and pass appropriate parts back. 55437Sbill */ 5553624Sroot stat1(ip, ub) 5564828Swnj register struct inode *ip; 5574828Swnj struct stat *ub; 55837Sbill { 55937Sbill struct stat ds; 56037Sbill 5611204Sbill IUPDAT(ip, &time, &time, 0); 56237Sbill /* 5637023Smckusick * Copy from inode table 56437Sbill */ 56537Sbill ds.st_dev = ip->i_dev; 56637Sbill ds.st_ino = ip->i_number; 56737Sbill ds.st_mode = ip->i_mode; 56837Sbill ds.st_nlink = ip->i_nlink; 56937Sbill ds.st_uid = ip->i_uid; 57037Sbill ds.st_gid = ip->i_gid; 5716574Smckusic ds.st_rdev = (dev_t)ip->i_rdev; 5723624Sroot ds.st_size = ip->i_size; 5736574Smckusic ds.st_atime = ip->i_atime; 5746574Smckusic ds.st_mtime = ip->i_mtime; 5756574Smckusic ds.st_ctime = ip->i_ctime; 5767023Smckusick ds.st_blksize = ip->i_fs->fs_bsize; 57737Sbill if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 57837Sbill u.u_error = EFAULT; 57937Sbill } 58037Sbill 58137Sbill /* 5825992Swnj * Return target name of a symbolic link 58337Sbill */ 5845992Swnj readlink() 5855992Swnj { 5865992Swnj register struct inode *ip; 5875992Swnj register struct a { 5885992Swnj char *name; 5895992Swnj char *buf; 5905992Swnj int count; 5915992Swnj } *uap; 5925992Swnj 5935992Swnj ip = namei(uchar, 0, 0); 5945992Swnj if (ip == NULL) 5955992Swnj return; 596*7439Sroot #ifdef EFS 597*7439Sroot if (efsinode(ip)) { 598*7439Sroot dev_t ndev = ip->i_rdev; 599*7439Sroot 600*7439Sroot iput(ip); 601*7439Sroot efsreadlink(ndev); 602*7439Sroot if (u.u_error != EEXIST) 603*7439Sroot return; 604*7439Sroot u.u_error = 0; 605*7439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 606*7439Sroot ip = namei(uchar, 0, 0); 607*7439Sroot return (0); 608*7439Sroot } 609*7439Sroot #endif 6105992Swnj if ((ip->i_mode&IFMT) != IFLNK) { 6115992Swnj u.u_error = ENXIO; 6125992Swnj goto out; 6135992Swnj } 6145992Swnj uap = (struct a *)u.u_ap; 6155992Swnj u.u_offset = 0; 6165992Swnj u.u_base = uap->buf; 6175992Swnj u.u_count = uap->count; 6185992Swnj u.u_segflg = 0; 6195992Swnj readi(ip); 6205992Swnj out: 6215992Swnj iput(ip); 6225992Swnj u.u_r.r_val1 = uap->count - u.u_count; 6235992Swnj } 6245992Swnj 6256254Sroot chmod() 6265992Swnj { 6276254Sroot register struct inode *ip; 6285992Swnj register struct a { 6296254Sroot char *fname; 6306254Sroot int fmode; 6315992Swnj } *uap; 6325992Swnj 6335992Swnj uap = (struct a *)u.u_ap; 6346254Sroot if ((ip = owner(1)) == NULL) 6355992Swnj return; 636*7439Sroot #ifdef EFS 637*7439Sroot if (efsinode(ip)) { 638*7439Sroot dev_t ndev = ip->i_rdev; 639*7439Sroot 640*7439Sroot iput(ip); 641*7439Sroot efschmod(ndev); 642*7439Sroot if (u.u_error != EEXIST) 643*7439Sroot return; 644*7439Sroot u.u_error = 0; 645*7439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 646*7439Sroot ip = owner(1); 647*7439Sroot } 648*7439Sroot #endif 6496254Sroot ip->i_mode &= ~07777; 650*7439Sroot if (u.u_uid) { 6516254Sroot uap->fmode &= ~ISVTX; 652*7439Sroot if (ip->i_gid >= NGRPS || 653*7439Sroot (u.u_grps[ip->i_gid/(sizeof(int)*8)] & 654*7439Sroot (1 << ip->i_gid%(sizeof(int)*8))) == 0) 655*7439Sroot uap->fmode &= ~ISGID; 656*7439Sroot } 6576254Sroot ip->i_mode |= uap->fmode&07777; 6586254Sroot ip->i_flag |= ICHG; 6596254Sroot if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 6606254Sroot xrele(ip); 6615992Swnj iput(ip); 6625992Swnj } 6635992Swnj 6646254Sroot chown() 66537Sbill { 6666254Sroot register struct inode *ip; 66737Sbill register struct a { 6686254Sroot char *fname; 6696254Sroot int uid; 6706254Sroot int gid; 67137Sbill } *uap; 67237Sbill 67337Sbill uap = (struct a *)u.u_ap; 6746254Sroot if (!suser() || (ip = owner(0)) == NULL) 67537Sbill return; 676*7439Sroot #ifdef EFS 677*7439Sroot if (efsinode(ip)) { 678*7439Sroot dev_t ndev = ip->i_rdev; 679*7439Sroot 680*7439Sroot iput(ip); 681*7439Sroot efschown(ndev); 682*7439Sroot if (u.u_error != EEXIST) 683*7439Sroot return; 684*7439Sroot u.u_error = 0; 685*7439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 686*7439Sroot ip = owner(0); 687*7439Sroot } 688*7439Sroot #endif 689*7439Sroot /* 690*7439Sroot * keep uid/gid's in sane range - no err, so chown(file, uid, -1) 691*7439Sroot * will do something useful 692*7439Sroot */ 693*7439Sroot if (uap->uid >= 0 && uap->uid <= 32767) /* should have a const */ 694*7439Sroot ip->i_uid = uap->uid; 695*7439Sroot if (uap->gid >= 0 && uap->gid <= 32767) /* same here */ 696*7439Sroot ip->i_gid = uap->gid; 6976254Sroot ip->i_flag |= ICHG; 6986254Sroot if (u.u_ruid != 0) 6996254Sroot ip->i_mode &= ~(ISUID|ISGID); 7006254Sroot iput(ip); 70137Sbill } 70237Sbill 70337Sbill /* 7046254Sroot * Set IUPD and IACC times on file. 7056254Sroot * Can't set ICHG. 70637Sbill */ 7076254Sroot utime() 7084828Swnj { 70937Sbill register struct a { 7106254Sroot char *fname; 7116254Sroot time_t *tptr; 71237Sbill } *uap; 7136254Sroot register struct inode *ip; 7146254Sroot time_t tv[2]; 71537Sbill 71637Sbill uap = (struct a *)u.u_ap; 7176254Sroot if ((ip = owner(1)) == NULL) 71837Sbill return; 7196254Sroot if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { 7206254Sroot u.u_error = EFAULT; 7216254Sroot } else { 722*7439Sroot #ifdef EFS 723*7439Sroot if (efsinode(ip)) { 724*7439Sroot dev_t ndev = ip->i_rdev; 725*7439Sroot 726*7439Sroot iput(ip); 727*7439Sroot efsutime(ndev, uap->fname, tv); 728*7439Sroot if (u.u_error != EEXIST) 729*7439Sroot return; 730*7439Sroot u.u_error = 0; 731*7439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 732*7439Sroot ip = owner(1); 733*7439Sroot } 734*7439Sroot #endif 7356254Sroot ip->i_flag |= IACC|IUPD|ICHG; 7366254Sroot iupdat(ip, &tv[0], &tv[1], 0); 73737Sbill } 73837Sbill iput(ip); 73937Sbill } 74037Sbill 7416254Sroot sync() 74237Sbill { 74337Sbill 7445416Swnj update(0); 74537Sbill } 746