1*7482Skre /* vfs_syscalls.c 4.29 82/07/22 */ 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" 147439Sroot #ifdef EFS 157439Sroot #include "../net/in.h" 167439Sroot #include "../h/efs.h" 177439Sroot #endif 18*7482Skre #include "../h/quota.h" 1937Sbill 206254Sroot chdir() 216254Sroot { 226254Sroot 236254Sroot chdirec(&u.u_cdir); 246254Sroot } 256254Sroot 266254Sroot chroot() 276254Sroot { 286254Sroot 296254Sroot if (suser()) 306254Sroot chdirec(&u.u_rdir); 316254Sroot } 326254Sroot 336254Sroot chdirec(ipp) 346254Sroot register struct inode **ipp; 356254Sroot { 366254Sroot register struct inode *ip; 376254Sroot struct a { 386254Sroot char *fname; 396254Sroot }; 406254Sroot 416254Sroot ip = namei(uchar, 0, 1); 426254Sroot if(ip == NULL) 436254Sroot return; 446254Sroot if((ip->i_mode&IFMT) != IFDIR) { 456254Sroot u.u_error = ENOTDIR; 466254Sroot goto bad; 476254Sroot } 486254Sroot if(access(ip, IEXEC)) 496254Sroot goto bad; 507122Smckusick iunlock(ip); 517142Smckusick if (*ipp) 527142Smckusick irele(*ipp); 536254Sroot *ipp = ip; 546254Sroot return; 556254Sroot 566254Sroot bad: 576254Sroot iput(ip); 586254Sroot } 596254Sroot 6037Sbill /* 616254Sroot * Open system call. 626254Sroot */ 636254Sroot open() 646254Sroot { 656254Sroot register struct inode *ip; 666254Sroot register struct a { 676254Sroot char *fname; 686254Sroot int rwmode; 696254Sroot } *uap; 706254Sroot 716254Sroot uap = (struct a *)u.u_ap; 726254Sroot ip = namei(uchar, 0, 1); 736254Sroot if (ip == NULL) 746254Sroot return; 756254Sroot open1(ip, ++uap->rwmode, 0); 766254Sroot } 776254Sroot 786254Sroot /* 796254Sroot * Creat system call. 806254Sroot */ 816254Sroot creat() 826254Sroot { 836254Sroot register struct inode *ip; 846254Sroot register struct a { 856254Sroot char *fname; 866254Sroot int fmode; 876254Sroot } *uap; 886254Sroot 896254Sroot uap = (struct a *)u.u_ap; 906254Sroot ip = namei(uchar, 1, 1); 916254Sroot if (ip == NULL) { 926254Sroot if (u.u_error) 936254Sroot return; 946254Sroot ip = maknode(uap->fmode&07777&(~ISVTX)); 956254Sroot if (ip==NULL) 966254Sroot return; 976254Sroot open1(ip, FWRITE, 2); 986254Sroot } else 996254Sroot open1(ip, FWRITE, 1); 1006254Sroot } 1016254Sroot 1026254Sroot /* 1036254Sroot * Common code for open and creat. 1046254Sroot * Check permissions, allocate an open file structure, 1056254Sroot * and call the device open routine if any. 1066254Sroot */ 1076254Sroot open1(ip, mode, trf) 1086254Sroot register struct inode *ip; 1096254Sroot register mode; 1106254Sroot { 1116254Sroot register struct file *fp; 1126254Sroot int i; 1136254Sroot 1146254Sroot if (trf != 2) { 1156254Sroot if (mode&FREAD) 1166254Sroot (void) access(ip, IREAD); 1176254Sroot if (mode&FWRITE) { 1186254Sroot (void) access(ip, IWRITE); 1196254Sroot if ((ip->i_mode&IFMT) == IFDIR) 1206254Sroot u.u_error = EISDIR; 1216254Sroot } 1226254Sroot } 1237142Smckusick if (u.u_error) { 1247142Smckusick iput(ip); 1257142Smckusick return; 1267142Smckusick } 1276254Sroot if (trf == 1) 1286254Sroot itrunc(ip); 1297122Smckusick iunlock(ip); 1306254Sroot if ((fp = falloc()) == NULL) 1316254Sroot goto out; 1326254Sroot fp->f_flag = mode&(FREAD|FWRITE); 1336254Sroot i = u.u_r.r_val1; 1346254Sroot fp->f_inode = ip; 1357439Sroot #ifdef EFS 1367439Sroot openi(ip, mode&(FREAD|FWRITE), trf); 1377439Sroot #else 1386254Sroot openi(ip, mode&(FREAD|FWRITE)); 1397439Sroot #endif 1406254Sroot if (u.u_error == 0) 1416254Sroot return; 1426254Sroot u.u_ofile[i] = NULL; 1436254Sroot fp->f_count--; 1446254Sroot out: 1457142Smckusick irele(ip); 1466254Sroot } 1476254Sroot 1486254Sroot /* 1496254Sroot * Mknod system call 1506254Sroot */ 1516254Sroot mknod() 1526254Sroot { 1536254Sroot register struct inode *ip; 1546254Sroot register struct a { 1556254Sroot char *fname; 1566254Sroot int fmode; 1576254Sroot int dev; 1586254Sroot } *uap; 1596254Sroot 1606254Sroot uap = (struct a *)u.u_ap; 1616254Sroot if (suser()) { 1626254Sroot ip = namei(uchar, 1, 0); 1636254Sroot if (ip != NULL) { 1646254Sroot u.u_error = EEXIST; 1656254Sroot goto out; 1666254Sroot } 1676254Sroot } 1686254Sroot if (u.u_error) 1696254Sroot return; 1706254Sroot ip = maknode(uap->fmode); 1716254Sroot if (ip == NULL) 1726254Sroot return; 1736254Sroot if (uap->dev) { 1746254Sroot /* 1756254Sroot * Want to be able to use this to make badblock 1766254Sroot * inodes, so don't truncate the dev number. 1776254Sroot */ 1786574Smckusic ip->i_rdev = uap->dev; 1796254Sroot ip->i_flag |= IACC|IUPD|ICHG; 1806254Sroot } 1816254Sroot 1826254Sroot out: 1836254Sroot iput(ip); 1846254Sroot } 1856254Sroot 1866254Sroot /* 1876254Sroot * link system call 1886254Sroot */ 1896254Sroot link() 1906254Sroot { 1916254Sroot register struct inode *ip, *xp; 1926254Sroot register struct a { 1936254Sroot char *target; 1946254Sroot char *linkname; 1956254Sroot } *uap; 1966254Sroot 1976254Sroot uap = (struct a *)u.u_ap; 1986254Sroot ip = namei(uchar, 0, 1); /* well, this routine is doomed anyhow */ 1996254Sroot if (ip == NULL) 2006254Sroot return; 2017439Sroot if ((ip->i_mode&IFMT)==IFDIR && !suser()) { 2027439Sroot iput(ip); 2037439Sroot return; 2047439Sroot } 2056254Sroot ip->i_nlink++; 2066254Sroot ip->i_flag |= ICHG; 2076254Sroot iupdat(ip, &time, &time, 1); 2087122Smckusick iunlock(ip); 2096254Sroot u.u_dirp = (caddr_t)uap->linkname; 2106254Sroot xp = namei(uchar, 1, 0); 2116254Sroot if (xp != NULL) { 2126254Sroot u.u_error = EEXIST; 2136254Sroot iput(xp); 2146254Sroot goto out; 2156254Sroot } 2166254Sroot if (u.u_error) 2176254Sroot goto out; 2186254Sroot if (u.u_pdir->i_dev != ip->i_dev) { 2196254Sroot iput(u.u_pdir); 2206254Sroot u.u_error = EXDEV; 2216254Sroot goto out; 2226254Sroot } 2236254Sroot wdir(ip); 2246254Sroot out: 2256254Sroot if (u.u_error) { 2266254Sroot ip->i_nlink--; 2276254Sroot ip->i_flag |= ICHG; 2286254Sroot } 2296254Sroot out1: 2307142Smckusick irele(ip); 2316254Sroot } 2326254Sroot 2336254Sroot /* 2346254Sroot * symlink -- make a symbolic link 2356254Sroot */ 2366254Sroot symlink() 2376254Sroot { 2386254Sroot register struct a { 2396254Sroot char *target; 2406254Sroot char *linkname; 2416254Sroot } *uap; 2426254Sroot register struct inode *ip; 2436254Sroot register char *tp; 2446254Sroot register c, nc; 2456254Sroot 2466254Sroot uap = (struct a *)u.u_ap; 2476254Sroot tp = uap->target; 2486254Sroot nc = 0; 2496254Sroot while (c = fubyte(tp)) { 2506254Sroot if (c < 0) { 2516254Sroot u.u_error = EFAULT; 2526254Sroot return; 2536254Sroot } 2546254Sroot tp++; 2556254Sroot nc++; 2566254Sroot } 2576254Sroot u.u_dirp = uap->linkname; 2586254Sroot ip = namei(uchar, 1, 0); 2596254Sroot if (ip) { 2606254Sroot iput(ip); 2616254Sroot u.u_error = EEXIST; 2626254Sroot return; 2636254Sroot } 2646254Sroot if (u.u_error) 2656254Sroot return; 2666254Sroot ip = maknode(IFLNK | 0777); 2676254Sroot if (ip == NULL) 2686254Sroot return; 2696254Sroot u.u_base = uap->target; 2706254Sroot u.u_count = nc; 2716254Sroot u.u_offset = 0; 2726254Sroot u.u_segflg = 0; 2736254Sroot writei(ip); 2746254Sroot iput(ip); 2756254Sroot } 2766254Sroot 2776254Sroot /* 2786254Sroot * Unlink system call. 2796254Sroot * Hard to avoid races here, especially 2806254Sroot * in unlinking directories. 2816254Sroot */ 2826254Sroot unlink() 2836254Sroot { 2846254Sroot register struct inode *ip, *pp; 2856254Sroot struct a { 2866254Sroot char *fname; 2876254Sroot }; 2886574Smckusic struct fs *fs; 2896574Smckusic struct buf *bp; 2906574Smckusic int lbn, bn, base; 2917142Smckusick int unlinkingdot = 0; 2926254Sroot 2936254Sroot pp = namei(uchar, 2, 0); 2946254Sroot if(pp == NULL) 2956254Sroot return; 2967439Sroot #ifdef EFS 2977439Sroot /* divert to extended file system if off machine. */ 2987439Sroot if (efsinode(pp)) { 2997439Sroot dev_t ndev = pp->i_rdev; 3007439Sroot 3017439Sroot iput(pp); /* avoid recursive hang on inode */ 3027439Sroot efsunlink(ndev); 3037439Sroot if (u.u_error != EEXIST) 3047439Sroot return; 3057439Sroot 3067439Sroot /* 3077439Sroot * If a null pathname remainder, then do 3087439Sroot * the unlink locally after restoring state. 3097439Sroot */ 3107439Sroot u.u_error = 0; 3117439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 3127439Sroot pp = namei(uchar, 2, 0); 3137439Sroot } 3147439Sroot #endif 3157439Sroot 3166254Sroot /* 3176254Sroot * Check for unlink(".") 3186254Sroot * to avoid hanging on the iget 3196254Sroot */ 3206254Sroot if (pp->i_number == u.u_dent.d_ino) { 3216254Sroot ip = pp; 3226254Sroot ip->i_count++; 3237142Smckusick unlinkingdot++; 3246254Sroot } else 3256574Smckusic ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino); 3266254Sroot if(ip == NULL) 3276254Sroot goto out1; 3286254Sroot if((ip->i_mode&IFMT)==IFDIR && !suser()) 3296254Sroot goto out; 3306254Sroot /* 3316254Sroot * Don't unlink a mounted file. 3326254Sroot */ 3336254Sroot if (ip->i_dev != pp->i_dev) { 3346254Sroot u.u_error = EBUSY; 3356254Sroot goto out; 3366254Sroot } 3376254Sroot if (ip->i_flag&ITEXT) 3386254Sroot xrele(ip); /* try once to free text */ 3396254Sroot /* 3406254Sroot if ((ip->i_flag&ITEXT) && ip->i_nlink==1) { 3416254Sroot u.u_error = ETXTBSY; 3426254Sroot goto out; 3436254Sroot } 3446254Sroot */ 3456574Smckusic if (u.u_count == 0) { 3466574Smckusic /* 3476574Smckusic * first entry in block, so set d_ino to zero. 3486574Smckusic */ 3496574Smckusic u.u_base = (caddr_t)&u.u_dent; 3506574Smckusic u.u_count = DIRSIZ(&u.u_dent); 3516574Smckusic u.u_dent.d_ino = 0; 3526574Smckusic writei(pp); 3536574Smckusic } else { 3546574Smckusic /* 3556574Smckusic * updating preceeding entry to skip over current entry. 3566574Smckusic */ 3576574Smckusic fs = pp->i_fs; 3586574Smckusic lbn = lblkno(fs, u.u_offset); 3596574Smckusic base = blkoff(fs, u.u_offset); 3606574Smckusic bn = fsbtodb(fs, bmap(pp, lbn, B_WRITE, base + u.u_count)); 3616574Smckusic bp = bread(pp->i_dev, bn, blksize(fs, pp, lbn)); 3626574Smckusic if (bp->b_flags & B_ERROR) { 3636574Smckusic brelse(bp); 3646574Smckusic goto out; 3656574Smckusic } 3666574Smckusic ((struct direct *)(bp->b_un.b_addr + base))->d_reclen += 3676574Smckusic u.u_dent.d_reclen; 3686574Smckusic bwrite(bp); 3696574Smckusic pp->i_flag |= IUPD|ICHG; 3706574Smckusic } 3716254Sroot ip->i_nlink--; 3726254Sroot ip->i_flag |= ICHG; 3736254Sroot 3746254Sroot out: 3757142Smckusick if (unlinkingdot) 3767142Smckusick irele(ip); 3777142Smckusick else 3787142Smckusick iput(ip); 3796254Sroot out1: 3806254Sroot iput(pp); 3816254Sroot } 3826254Sroot 3836254Sroot /* 3846254Sroot * Seek system call 3856254Sroot */ 3866254Sroot seek() 3876254Sroot { 3886254Sroot register struct file *fp; 3896254Sroot register struct a { 3906254Sroot int fdes; 3916254Sroot off_t off; 3926254Sroot int sbase; 3936254Sroot } *uap; 3946254Sroot 3956254Sroot uap = (struct a *)u.u_ap; 3966254Sroot fp = getf(uap->fdes); 3976254Sroot if (fp == NULL) 3986254Sroot return; 3996254Sroot if (fp->f_flag&FSOCKET) { 4006254Sroot u.u_error = ESPIPE; 4016254Sroot return; 4026254Sroot } 4036254Sroot if (uap->sbase == 1) 4046254Sroot uap->off += fp->f_offset; 4057439Sroot else if (uap->sbase == 2) { 4067439Sroot #ifdef EFS 4077439Sroot struct inode *ip = fp->f_inode; 4087439Sroot uap->off += efsinode(ip) ? efsfilesize(fp) : ip->i_size; 4097439Sroot #else 4106254Sroot uap->off += fp->f_inode->i_size; 4117439Sroot #endif 4127439Sroot } 4136254Sroot fp->f_offset = uap->off; 4146254Sroot u.u_r.r_off = uap->off; 4156254Sroot } 4166254Sroot 4176254Sroot /* 4186254Sroot * Access system call 4196254Sroot */ 4206254Sroot saccess() 4216254Sroot { 4226254Sroot register svuid, svgid; 4236254Sroot register struct inode *ip; 4246254Sroot register struct a { 4256254Sroot char *fname; 4266254Sroot int fmode; 4276254Sroot } *uap; 4286254Sroot 4296254Sroot uap = (struct a *)u.u_ap; 4306254Sroot svuid = u.u_uid; 4316254Sroot svgid = u.u_gid; 4326254Sroot u.u_uid = u.u_ruid; 4336254Sroot u.u_gid = u.u_rgid; 4346254Sroot ip = namei(uchar, 0, 1); 4357439Sroot #ifdef EFS 4367439Sroot if (efsinode(ip)) { 4377439Sroot dev_t ndev = ip->i_rdev; 4387439Sroot 4397439Sroot iput(ip); 4407439Sroot efssaccess(ndev); 4417439Sroot if (u.u_error != EEXIST) 4427439Sroot return; 4437439Sroot u.u_error = 0; 4447439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 4457439Sroot ip = namei(uchar, 0, 1); 4467439Sroot } 4477439Sroot #endif 4486254Sroot if (ip != NULL) { 4496254Sroot if (uap->fmode&(IREAD>>6)) 4506254Sroot (void) access(ip, IREAD); 4516254Sroot if (uap->fmode&(IWRITE>>6)) 4526254Sroot (void) access(ip, IWRITE); 4536254Sroot if (uap->fmode&(IEXEC>>6)) 4546254Sroot (void) access(ip, IEXEC); 4556254Sroot iput(ip); 4566254Sroot } 4576254Sroot u.u_uid = svuid; 4586254Sroot u.u_gid = svgid; 4596254Sroot } 4606254Sroot 4616254Sroot /* 46237Sbill * the fstat system call. 46337Sbill */ 46437Sbill fstat() 46537Sbill { 46637Sbill register struct file *fp; 46737Sbill register struct a { 46837Sbill int fdes; 46937Sbill struct stat *sb; 47037Sbill } *uap; 47137Sbill 47237Sbill uap = (struct a *)u.u_ap; 47337Sbill fp = getf(uap->fdes); 4744828Swnj if (fp == NULL) 47537Sbill return; 4767439Sroot #ifdef EFS 4777439Sroot if (efsinode(fp->f_inode)) { 4787439Sroot efsfstat(fp->f_inode->i_rdev, fp); 4797439Sroot return; 4807439Sroot } 4817439Sroot #endif 4824828Swnj if (fp->f_flag & FSOCKET) 4834891Swnj u.u_error = sostat(fp->f_socket, uap->sb); 4844828Swnj else 4854828Swnj stat1(fp->f_inode, uap->sb); 48637Sbill } 48737Sbill 48837Sbill /* 4896574Smckusic * Stat system call. This version follows links. 49037Sbill */ 49137Sbill stat() 49237Sbill { 49337Sbill register struct inode *ip; 49437Sbill register struct a { 49537Sbill char *fname; 49637Sbill struct stat *sb; 49737Sbill } *uap; 49837Sbill 49937Sbill uap = (struct a *)u.u_ap; 5006423Sroot ip = namei(uchar, 0, 1); 5014828Swnj if (ip == NULL) 50237Sbill return; 5037439Sroot #ifdef EFS 5047439Sroot if (efsinode(ip)) { 5057439Sroot dev_t ndev = ip->i_rdev; 5067439Sroot 5077439Sroot iput(ip); 5087439Sroot efsstat(ndev); 5097439Sroot if (u.u_error != EEXIST) 5107439Sroot return; 5117439Sroot u.u_error = 0; 5127439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 5137439Sroot ip = namei(uchar, 0, 1); 5147439Sroot } 5157439Sroot #endif 5163624Sroot stat1(ip, uap->sb); 51737Sbill iput(ip); 51837Sbill } 51937Sbill 52037Sbill /* 5216574Smckusic * Lstat system call. This version does not follow links. 5225992Swnj */ 5235992Swnj lstat() 5245992Swnj { 5255992Swnj register struct inode *ip; 5265992Swnj register struct a { 5275992Swnj char *fname; 5285992Swnj struct stat *sb; 5295992Swnj } *uap; 5305992Swnj 5315992Swnj uap = (struct a *)u.u_ap; 5326423Sroot ip = namei(uchar, 0, 0); 5335992Swnj if (ip == NULL) 5345992Swnj return; 5357439Sroot #ifdef EFS 5367439Sroot if (efsinode(ip)) { 5377439Sroot dev_t ndev = ip->i_rdev; 5387439Sroot 5397439Sroot iput(ip); 5407439Sroot efslstat(ndev); 5417439Sroot if (u.u_error != EEXIST) 5427439Sroot return; 5437439Sroot u.u_error = 0; 5447439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 5457439Sroot ip = namei(uchar, 0, 0); 5467439Sroot } 5477439Sroot #endif 5486153Ssam stat1(ip, uap->sb); 5495992Swnj iput(ip); 5505992Swnj } 5515992Swnj 5525992Swnj /* 55337Sbill * The basic routine for fstat and stat: 55437Sbill * get the inode and pass appropriate parts back. 55537Sbill */ 5563624Sroot stat1(ip, ub) 5574828Swnj register struct inode *ip; 5584828Swnj struct stat *ub; 55937Sbill { 56037Sbill struct stat ds; 56137Sbill 5621204Sbill IUPDAT(ip, &time, &time, 0); 56337Sbill /* 5647023Smckusick * Copy from inode table 56537Sbill */ 56637Sbill ds.st_dev = ip->i_dev; 56737Sbill ds.st_ino = ip->i_number; 56837Sbill ds.st_mode = ip->i_mode; 56937Sbill ds.st_nlink = ip->i_nlink; 57037Sbill ds.st_uid = ip->i_uid; 57137Sbill ds.st_gid = ip->i_gid; 5726574Smckusic ds.st_rdev = (dev_t)ip->i_rdev; 5733624Sroot ds.st_size = ip->i_size; 5746574Smckusic ds.st_atime = ip->i_atime; 5756574Smckusic ds.st_mtime = ip->i_mtime; 5766574Smckusic ds.st_ctime = ip->i_ctime; 5777023Smckusick ds.st_blksize = ip->i_fs->fs_bsize; 57837Sbill if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 57937Sbill u.u_error = EFAULT; 58037Sbill } 58137Sbill 58237Sbill /* 5835992Swnj * Return target name of a symbolic link 58437Sbill */ 5855992Swnj readlink() 5865992Swnj { 5875992Swnj register struct inode *ip; 5885992Swnj register struct a { 5895992Swnj char *name; 5905992Swnj char *buf; 5915992Swnj int count; 5925992Swnj } *uap; 5935992Swnj 5945992Swnj ip = namei(uchar, 0, 0); 5955992Swnj if (ip == NULL) 5965992Swnj return; 5977439Sroot #ifdef EFS 5987439Sroot if (efsinode(ip)) { 5997439Sroot dev_t ndev = ip->i_rdev; 6007439Sroot 6017439Sroot iput(ip); 6027439Sroot efsreadlink(ndev); 6037439Sroot if (u.u_error != EEXIST) 6047439Sroot return; 6057439Sroot u.u_error = 0; 6067439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 6077439Sroot ip = namei(uchar, 0, 0); 6087439Sroot return (0); 6097439Sroot } 6107439Sroot #endif 6115992Swnj if ((ip->i_mode&IFMT) != IFLNK) { 6125992Swnj u.u_error = ENXIO; 6135992Swnj goto out; 6145992Swnj } 6155992Swnj uap = (struct a *)u.u_ap; 6165992Swnj u.u_offset = 0; 6175992Swnj u.u_base = uap->buf; 6185992Swnj u.u_count = uap->count; 6195992Swnj u.u_segflg = 0; 6205992Swnj readi(ip); 6215992Swnj out: 6225992Swnj iput(ip); 6235992Swnj u.u_r.r_val1 = uap->count - u.u_count; 6245992Swnj } 6255992Swnj 6266254Sroot chmod() 6275992Swnj { 6286254Sroot register struct inode *ip; 6295992Swnj register struct a { 6306254Sroot char *fname; 6316254Sroot int fmode; 6325992Swnj } *uap; 6335992Swnj 6345992Swnj uap = (struct a *)u.u_ap; 6356254Sroot if ((ip = owner(1)) == NULL) 6365992Swnj return; 6377439Sroot #ifdef EFS 6387439Sroot if (efsinode(ip)) { 6397439Sroot dev_t ndev = ip->i_rdev; 6407439Sroot 6417439Sroot iput(ip); 6427439Sroot efschmod(ndev); 6437439Sroot if (u.u_error != EEXIST) 6447439Sroot return; 6457439Sroot u.u_error = 0; 6467439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 6477439Sroot ip = owner(1); 6487439Sroot } 6497439Sroot #endif 6506254Sroot ip->i_mode &= ~07777; 6517439Sroot if (u.u_uid) { 6526254Sroot uap->fmode &= ~ISVTX; 6537439Sroot if (ip->i_gid >= NGRPS || 6547439Sroot (u.u_grps[ip->i_gid/(sizeof(int)*8)] & 6557439Sroot (1 << ip->i_gid%(sizeof(int)*8))) == 0) 6567439Sroot uap->fmode &= ~ISGID; 657*7482Skre #if MUSH 658*7482Skre if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 && 659*7482Skre (ip->i_mode & IFMT) != IFCHR) 660*7482Skre uap->fmode &= ~u.u_cmask; 661*7482Skre #endif 6627439Sroot } 6636254Sroot ip->i_mode |= uap->fmode&07777; 6646254Sroot ip->i_flag |= ICHG; 6656254Sroot if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 6666254Sroot xrele(ip); 667*7482Skre #ifdef MELB 668*7482Skre if ((ip->i_mode & ISUID) && ip->i_uid == 0) 669*7482Skre printf("%s: ino %d (%s) setuid root\n" 670*7482Skre , getfs(ip->i_dev)->s_fsmnt 671*7482Skre , ip->i_number 672*7482Skre , u.u_dent.d_name 673*7482Skre ); 674*7482Skre #endif 6755992Swnj iput(ip); 6765992Swnj } 6775992Swnj 6786254Sroot chown() 67937Sbill { 6806254Sroot register struct inode *ip; 68137Sbill register struct a { 6826254Sroot char *fname; 6836254Sroot int uid; 6846254Sroot int gid; 68537Sbill } *uap; 686*7482Skre #if QUOTA 687*7482Skre register long change; 688*7482Skre #endif 68937Sbill 69037Sbill uap = (struct a *)u.u_ap; 6916254Sroot if (!suser() || (ip = owner(0)) == NULL) 69237Sbill return; 6937439Sroot #ifdef EFS 6947439Sroot if (efsinode(ip)) { 6957439Sroot dev_t ndev = ip->i_rdev; 6967439Sroot 6977439Sroot iput(ip); 6987439Sroot efschown(ndev); 6997439Sroot if (u.u_error != EEXIST) 7007439Sroot return; 7017439Sroot u.u_error = 0; 7027439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 7037439Sroot ip = owner(0); 7047439Sroot } 7057439Sroot #endif 706*7482Skre #if QUOTA 7077439Sroot /* 708*7482Skre * This doesn't allow for holes in files (which hopefully don't 709*7482Skre * happen often in files that we chown), and is not accurate anyway 710*7482Skre * (eg: it totally ignores 3 level indir blk files - but hopefully 711*7482Skre * noone who can make a file that big will have a quota) 712*7482Skre */ 713*7482Skre if (ip->i_uid == uap->uid) 714*7482Skre change = 0; 715*7482Skre else { 716*7482Skre register struct fs *fs = ip->i_fs; 717*7482Skre 718*7482Skre if (ip->i_size > (change = NDADDR * fs->fs_bsize)) { 719*7482Skre register off_t size; 720*7482Skre 721*7482Skre size = blkroundup(fs, ip->i_size) - change; 722*7482Skre change += size; 723*7482Skre change += fs->fs_bsize; 724*7482Skre /* This assumes NIADDR <= 2 */ 725*7482Skre if (size > NINDIR(fs) * fs->fs_bsize) 726*7482Skre change += fs->fs_bsize; 727*7482Skre } else 728*7482Skre change = fragroundup(fs, ip->i_size); 729*7482Skre change /= DEV_BSIZE; 730*7482Skre } 731*7482Skre chkdq(ip, -change, 1); 732*7482Skre chkiq(ip->i_dev, ip, ip->i_uid, 1); 733*7482Skre dqrele(ip->i_dquot); 734*7482Skre #endif 735*7482Skre /* 7367439Sroot * keep uid/gid's in sane range - no err, so chown(file, uid, -1) 7377439Sroot * will do something useful 7387439Sroot */ 7397439Sroot if (uap->uid >= 0 && uap->uid <= 32767) /* should have a const */ 7407439Sroot ip->i_uid = uap->uid; 7417439Sroot if (uap->gid >= 0 && uap->gid <= 32767) /* same here */ 7427439Sroot ip->i_gid = uap->gid; 7436254Sroot ip->i_flag |= ICHG; 7446254Sroot if (u.u_ruid != 0) 7456254Sroot ip->i_mode &= ~(ISUID|ISGID); 746*7482Skre #if QUOTA 747*7482Skre ip->i_dquot = inoquota(ip); 748*7482Skre chkdq(ip, change, 1); 749*7482Skre chkiq(ip->i_dev, NULL, uap->uid, 1); 750*7482Skre #endif 7516254Sroot iput(ip); 75237Sbill } 75337Sbill 75437Sbill /* 7556254Sroot * Set IUPD and IACC times on file. 7566254Sroot * Can't set ICHG. 75737Sbill */ 7586254Sroot utime() 7594828Swnj { 76037Sbill register struct a { 7616254Sroot char *fname; 7626254Sroot time_t *tptr; 76337Sbill } *uap; 7646254Sroot register struct inode *ip; 7656254Sroot time_t tv[2]; 76637Sbill 76737Sbill uap = (struct a *)u.u_ap; 7686254Sroot if ((ip = owner(1)) == NULL) 76937Sbill return; 7706254Sroot if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { 7716254Sroot u.u_error = EFAULT; 7726254Sroot } else { 7737439Sroot #ifdef EFS 7747439Sroot if (efsinode(ip)) { 7757439Sroot dev_t ndev = ip->i_rdev; 7767439Sroot 7777439Sroot iput(ip); 7787439Sroot efsutime(ndev, uap->fname, tv); 7797439Sroot if (u.u_error != EEXIST) 7807439Sroot return; 7817439Sroot u.u_error = 0; 7827439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 7837439Sroot ip = owner(1); 7847439Sroot } 7857439Sroot #endif 7866254Sroot ip->i_flag |= IACC|IUPD|ICHG; 7876254Sroot iupdat(ip, &tv[0], &tv[1], 0); 78837Sbill } 78937Sbill iput(ip); 79037Sbill } 79137Sbill 7926254Sroot sync() 79337Sbill { 79437Sbill 7955416Swnj update(0); 79637Sbill } 797