1*7505Sroot /* vfs_syscalls.c 4.30 82/07/24 */ 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 187482Skre #include "../h/quota.h" 19*7505Sroot #include "../h/descrip.h" 2037Sbill 216254Sroot chdir() 226254Sroot { 236254Sroot 246254Sroot chdirec(&u.u_cdir); 256254Sroot } 266254Sroot 276254Sroot chroot() 286254Sroot { 296254Sroot 306254Sroot if (suser()) 316254Sroot chdirec(&u.u_rdir); 326254Sroot } 336254Sroot 346254Sroot chdirec(ipp) 356254Sroot register struct inode **ipp; 366254Sroot { 376254Sroot register struct inode *ip; 386254Sroot struct a { 396254Sroot char *fname; 406254Sroot }; 416254Sroot 426254Sroot ip = namei(uchar, 0, 1); 436254Sroot if(ip == NULL) 446254Sroot return; 456254Sroot if((ip->i_mode&IFMT) != IFDIR) { 466254Sroot u.u_error = ENOTDIR; 476254Sroot goto bad; 486254Sroot } 496254Sroot if(access(ip, IEXEC)) 506254Sroot goto bad; 517122Smckusick iunlock(ip); 527142Smckusick if (*ipp) 537142Smckusick irele(*ipp); 546254Sroot *ipp = ip; 556254Sroot return; 566254Sroot 576254Sroot bad: 586254Sroot iput(ip); 596254Sroot } 606254Sroot 6137Sbill /* 626254Sroot * Open system call. 636254Sroot */ 646254Sroot open() 656254Sroot { 666254Sroot register struct inode *ip; 676254Sroot register struct a { 686254Sroot char *fname; 696254Sroot int rwmode; 706254Sroot } *uap; 716254Sroot 726254Sroot uap = (struct a *)u.u_ap; 736254Sroot ip = namei(uchar, 0, 1); 746254Sroot if (ip == NULL) 756254Sroot return; 766254Sroot open1(ip, ++uap->rwmode, 0); 776254Sroot } 786254Sroot 796254Sroot /* 806254Sroot * Creat system call. 816254Sroot */ 82*7505Sroot ocreat() 836254Sroot { 846254Sroot register struct inode *ip; 856254Sroot register struct a { 866254Sroot char *fname; 876254Sroot int fmode; 886254Sroot } *uap; 896254Sroot 906254Sroot uap = (struct a *)u.u_ap; 916254Sroot ip = namei(uchar, 1, 1); 926254Sroot if (ip == NULL) { 936254Sroot if (u.u_error) 946254Sroot return; 956254Sroot ip = maknode(uap->fmode&07777&(~ISVTX)); 966254Sroot if (ip==NULL) 976254Sroot return; 986254Sroot open1(ip, FWRITE, 2); 996254Sroot } else 1006254Sroot open1(ip, FWRITE, 1); 1016254Sroot } 1026254Sroot 1036254Sroot /* 1046254Sroot * Common code for open and creat. 1056254Sroot * Check permissions, allocate an open file structure, 1066254Sroot * and call the device open routine if any. 1076254Sroot */ 1086254Sroot open1(ip, mode, trf) 1096254Sroot register struct inode *ip; 1106254Sroot register mode; 1116254Sroot { 1126254Sroot register struct file *fp; 1136254Sroot int i; 1146254Sroot 1156254Sroot if (trf != 2) { 1166254Sroot if (mode&FREAD) 1176254Sroot (void) access(ip, IREAD); 1186254Sroot if (mode&FWRITE) { 1196254Sroot (void) access(ip, IWRITE); 1206254Sroot if ((ip->i_mode&IFMT) == IFDIR) 1216254Sroot u.u_error = EISDIR; 1226254Sroot } 1236254Sroot } 1247142Smckusick if (u.u_error) { 1257142Smckusick iput(ip); 1267142Smckusick return; 1277142Smckusick } 1286254Sroot if (trf == 1) 1296254Sroot itrunc(ip); 1307122Smckusick iunlock(ip); 1316254Sroot if ((fp = falloc()) == NULL) 1326254Sroot goto out; 1336254Sroot fp->f_flag = mode&(FREAD|FWRITE); 134*7505Sroot fp->f_type = DTYPE_FILE; 1356254Sroot i = u.u_r.r_val1; 1366254Sroot fp->f_inode = ip; 1377439Sroot #ifdef EFS 1387439Sroot openi(ip, mode&(FREAD|FWRITE), trf); 1397439Sroot #else 1406254Sroot openi(ip, mode&(FREAD|FWRITE)); 1417439Sroot #endif 1426254Sroot if (u.u_error == 0) 1436254Sroot return; 1446254Sroot u.u_ofile[i] = NULL; 1456254Sroot fp->f_count--; 1466254Sroot out: 1477142Smckusick irele(ip); 1486254Sroot } 1496254Sroot 1506254Sroot /* 1516254Sroot * Mknod system call 1526254Sroot */ 1536254Sroot mknod() 1546254Sroot { 1556254Sroot register struct inode *ip; 1566254Sroot register struct a { 1576254Sroot char *fname; 1586254Sroot int fmode; 1596254Sroot int dev; 1606254Sroot } *uap; 1616254Sroot 1626254Sroot uap = (struct a *)u.u_ap; 1636254Sroot if (suser()) { 1646254Sroot ip = namei(uchar, 1, 0); 1656254Sroot if (ip != NULL) { 1666254Sroot u.u_error = EEXIST; 1676254Sroot goto out; 1686254Sroot } 1696254Sroot } 1706254Sroot if (u.u_error) 1716254Sroot return; 1726254Sroot ip = maknode(uap->fmode); 1736254Sroot if (ip == NULL) 1746254Sroot return; 1756254Sroot if (uap->dev) { 1766254Sroot /* 1776254Sroot * Want to be able to use this to make badblock 1786254Sroot * inodes, so don't truncate the dev number. 1796254Sroot */ 1806574Smckusic ip->i_rdev = uap->dev; 1816254Sroot ip->i_flag |= IACC|IUPD|ICHG; 1826254Sroot } 1836254Sroot 1846254Sroot out: 1856254Sroot iput(ip); 1866254Sroot } 1876254Sroot 1886254Sroot /* 1896254Sroot * link system call 1906254Sroot */ 1916254Sroot link() 1926254Sroot { 1936254Sroot register struct inode *ip, *xp; 1946254Sroot register struct a { 1956254Sroot char *target; 1966254Sroot char *linkname; 1976254Sroot } *uap; 1986254Sroot 1996254Sroot uap = (struct a *)u.u_ap; 2006254Sroot ip = namei(uchar, 0, 1); /* well, this routine is doomed anyhow */ 2016254Sroot if (ip == NULL) 2026254Sroot return; 2037439Sroot if ((ip->i_mode&IFMT)==IFDIR && !suser()) { 2047439Sroot iput(ip); 2057439Sroot return; 2067439Sroot } 2076254Sroot ip->i_nlink++; 2086254Sroot ip->i_flag |= ICHG; 2096254Sroot iupdat(ip, &time, &time, 1); 2107122Smckusick iunlock(ip); 2116254Sroot u.u_dirp = (caddr_t)uap->linkname; 2126254Sroot xp = namei(uchar, 1, 0); 2136254Sroot if (xp != NULL) { 2146254Sroot u.u_error = EEXIST; 2156254Sroot iput(xp); 2166254Sroot goto out; 2176254Sroot } 2186254Sroot if (u.u_error) 2196254Sroot goto out; 2206254Sroot if (u.u_pdir->i_dev != ip->i_dev) { 2216254Sroot iput(u.u_pdir); 2226254Sroot u.u_error = EXDEV; 2236254Sroot goto out; 2246254Sroot } 2256254Sroot wdir(ip); 2266254Sroot out: 2276254Sroot if (u.u_error) { 2286254Sroot ip->i_nlink--; 2296254Sroot ip->i_flag |= ICHG; 2306254Sroot } 2316254Sroot out1: 2327142Smckusick irele(ip); 2336254Sroot } 2346254Sroot 2356254Sroot /* 2366254Sroot * symlink -- make a symbolic link 2376254Sroot */ 2386254Sroot symlink() 2396254Sroot { 2406254Sroot register struct a { 2416254Sroot char *target; 2426254Sroot char *linkname; 2436254Sroot } *uap; 2446254Sroot register struct inode *ip; 2456254Sroot register char *tp; 2466254Sroot register c, nc; 2476254Sroot 2486254Sroot uap = (struct a *)u.u_ap; 2496254Sroot tp = uap->target; 2506254Sroot nc = 0; 2516254Sroot while (c = fubyte(tp)) { 2526254Sroot if (c < 0) { 2536254Sroot u.u_error = EFAULT; 2546254Sroot return; 2556254Sroot } 2566254Sroot tp++; 2576254Sroot nc++; 2586254Sroot } 2596254Sroot u.u_dirp = uap->linkname; 2606254Sroot ip = namei(uchar, 1, 0); 2616254Sroot if (ip) { 2626254Sroot iput(ip); 2636254Sroot u.u_error = EEXIST; 2646254Sroot return; 2656254Sroot } 2666254Sroot if (u.u_error) 2676254Sroot return; 2686254Sroot ip = maknode(IFLNK | 0777); 2696254Sroot if (ip == NULL) 2706254Sroot return; 2716254Sroot u.u_base = uap->target; 2726254Sroot u.u_count = nc; 2736254Sroot u.u_offset = 0; 2746254Sroot u.u_segflg = 0; 2756254Sroot writei(ip); 2766254Sroot iput(ip); 2776254Sroot } 2786254Sroot 2796254Sroot /* 2806254Sroot * Unlink system call. 2816254Sroot * Hard to avoid races here, especially 2826254Sroot * in unlinking directories. 2836254Sroot */ 2846254Sroot unlink() 2856254Sroot { 2866254Sroot register struct inode *ip, *pp; 2876254Sroot struct a { 2886254Sroot char *fname; 2896254Sroot }; 2906574Smckusic struct fs *fs; 2916574Smckusic struct buf *bp; 2926574Smckusic int lbn, bn, base; 2937142Smckusick int unlinkingdot = 0; 2946254Sroot 2956254Sroot pp = namei(uchar, 2, 0); 2966254Sroot if(pp == NULL) 2976254Sroot return; 2987439Sroot #ifdef EFS 2997439Sroot /* divert to extended file system if off machine. */ 3007439Sroot if (efsinode(pp)) { 3017439Sroot dev_t ndev = pp->i_rdev; 3027439Sroot 3037439Sroot iput(pp); /* avoid recursive hang on inode */ 3047439Sroot efsunlink(ndev); 3057439Sroot if (u.u_error != EEXIST) 3067439Sroot return; 3077439Sroot 3087439Sroot /* 3097439Sroot * If a null pathname remainder, then do 3107439Sroot * the unlink locally after restoring state. 3117439Sroot */ 3127439Sroot u.u_error = 0; 3137439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 3147439Sroot pp = namei(uchar, 2, 0); 3157439Sroot } 3167439Sroot #endif 3177439Sroot 3186254Sroot /* 3196254Sroot * Check for unlink(".") 3206254Sroot * to avoid hanging on the iget 3216254Sroot */ 3226254Sroot if (pp->i_number == u.u_dent.d_ino) { 3236254Sroot ip = pp; 3246254Sroot ip->i_count++; 3257142Smckusick unlinkingdot++; 3266254Sroot } else 3276574Smckusic ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino); 3286254Sroot if(ip == NULL) 3296254Sroot goto out1; 3306254Sroot if((ip->i_mode&IFMT)==IFDIR && !suser()) 3316254Sroot goto out; 3326254Sroot /* 3336254Sroot * Don't unlink a mounted file. 3346254Sroot */ 3356254Sroot if (ip->i_dev != pp->i_dev) { 3366254Sroot u.u_error = EBUSY; 3376254Sroot goto out; 3386254Sroot } 3396254Sroot if (ip->i_flag&ITEXT) 3406254Sroot xrele(ip); /* try once to free text */ 3416254Sroot /* 3426254Sroot if ((ip->i_flag&ITEXT) && ip->i_nlink==1) { 3436254Sroot u.u_error = ETXTBSY; 3446254Sroot goto out; 3456254Sroot } 3466254Sroot */ 3476574Smckusic if (u.u_count == 0) { 3486574Smckusic /* 3496574Smckusic * first entry in block, so set d_ino to zero. 3506574Smckusic */ 351*7505Sroot /*ZZ*/if(u.u_offset&0x1ff)printf("missed dir compact dir %s/%d off %d file %s\n" 352*7505Sroot /*ZZ*/,pp->i_fs->fs_fsmnt,pp->i_number,u.u_offset,u.u_dent.d_name); 3536574Smckusic u.u_base = (caddr_t)&u.u_dent; 3546574Smckusic u.u_count = DIRSIZ(&u.u_dent); 3556574Smckusic u.u_dent.d_ino = 0; 3566574Smckusic writei(pp); 3576574Smckusic } else { 3586574Smckusic /* 3596574Smckusic * updating preceeding entry to skip over current entry. 3606574Smckusic */ 3616574Smckusic fs = pp->i_fs; 3626574Smckusic lbn = lblkno(fs, u.u_offset); 3636574Smckusic base = blkoff(fs, u.u_offset); 3646574Smckusic bn = fsbtodb(fs, bmap(pp, lbn, B_WRITE, base + u.u_count)); 3656574Smckusic bp = bread(pp->i_dev, bn, blksize(fs, pp, lbn)); 3666574Smckusic if (bp->b_flags & B_ERROR) { 3676574Smckusic brelse(bp); 3686574Smckusic goto out; 3696574Smckusic } 3706574Smckusic ((struct direct *)(bp->b_un.b_addr + base))->d_reclen += 3716574Smckusic u.u_dent.d_reclen; 372*7505Sroot /*ZZ*/if(((int)(bp->b_un.b_addr + base)&0x1ff)+u.u_dent.d_reclen>512) 373*7505Sroot /*ZZ*/ panic("unlink: reclen"); 3746574Smckusic bwrite(bp); 3756574Smckusic pp->i_flag |= IUPD|ICHG; 3766574Smckusic } 3776254Sroot ip->i_nlink--; 3786254Sroot ip->i_flag |= ICHG; 3796254Sroot 3806254Sroot out: 3817142Smckusick if (unlinkingdot) 3827142Smckusick irele(ip); 3837142Smckusick else 3847142Smckusick iput(ip); 3856254Sroot out1: 3866254Sroot iput(pp); 3876254Sroot } 3886254Sroot 3896254Sroot /* 3906254Sroot * Seek system call 3916254Sroot */ 3926254Sroot seek() 3936254Sroot { 3946254Sroot register struct file *fp; 3956254Sroot register struct a { 3966254Sroot int fdes; 3976254Sroot off_t off; 3986254Sroot int sbase; 3996254Sroot } *uap; 4006254Sroot 4016254Sroot uap = (struct a *)u.u_ap; 4026254Sroot fp = getf(uap->fdes); 4036254Sroot if (fp == NULL) 4046254Sroot return; 405*7505Sroot if (fp->f_type == DTYPE_SOCKET) { 4066254Sroot u.u_error = ESPIPE; 4076254Sroot return; 4086254Sroot } 4096254Sroot if (uap->sbase == 1) 4106254Sroot uap->off += fp->f_offset; 4117439Sroot else if (uap->sbase == 2) { 4127439Sroot #ifdef EFS 4137439Sroot struct inode *ip = fp->f_inode; 4147439Sroot uap->off += efsinode(ip) ? efsfilesize(fp) : ip->i_size; 4157439Sroot #else 4166254Sroot uap->off += fp->f_inode->i_size; 4177439Sroot #endif 4187439Sroot } 4196254Sroot fp->f_offset = uap->off; 4206254Sroot u.u_r.r_off = uap->off; 4216254Sroot } 4226254Sroot 4236254Sroot /* 4246254Sroot * Access system call 4256254Sroot */ 4266254Sroot saccess() 4276254Sroot { 4286254Sroot register svuid, svgid; 4296254Sroot register struct inode *ip; 4306254Sroot register struct a { 4316254Sroot char *fname; 4326254Sroot int fmode; 4336254Sroot } *uap; 4346254Sroot 4356254Sroot uap = (struct a *)u.u_ap; 4366254Sroot svuid = u.u_uid; 4376254Sroot svgid = u.u_gid; 4386254Sroot u.u_uid = u.u_ruid; 4396254Sroot u.u_gid = u.u_rgid; 4406254Sroot ip = namei(uchar, 0, 1); 4417439Sroot #ifdef EFS 4427439Sroot if (efsinode(ip)) { 4437439Sroot dev_t ndev = ip->i_rdev; 4447439Sroot 4457439Sroot iput(ip); 4467439Sroot efssaccess(ndev); 4477439Sroot if (u.u_error != EEXIST) 4487439Sroot return; 4497439Sroot u.u_error = 0; 4507439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 4517439Sroot ip = namei(uchar, 0, 1); 4527439Sroot } 4537439Sroot #endif 4546254Sroot if (ip != NULL) { 4556254Sroot if (uap->fmode&(IREAD>>6)) 4566254Sroot (void) access(ip, IREAD); 4576254Sroot if (uap->fmode&(IWRITE>>6)) 4586254Sroot (void) access(ip, IWRITE); 4596254Sroot if (uap->fmode&(IEXEC>>6)) 4606254Sroot (void) access(ip, IEXEC); 4616254Sroot iput(ip); 4626254Sroot } 4636254Sroot u.u_uid = svuid; 4646254Sroot u.u_gid = svgid; 4656254Sroot } 4666254Sroot 4676254Sroot /* 46837Sbill * the fstat system call. 46937Sbill */ 47037Sbill fstat() 47137Sbill { 47237Sbill register struct file *fp; 47337Sbill register struct a { 47437Sbill int fdes; 47537Sbill struct stat *sb; 47637Sbill } *uap; 47737Sbill 47837Sbill uap = (struct a *)u.u_ap; 47937Sbill fp = getf(uap->fdes); 4804828Swnj if (fp == NULL) 48137Sbill return; 4827439Sroot #ifdef EFS 4837439Sroot if (efsinode(fp->f_inode)) { 4847439Sroot efsfstat(fp->f_inode->i_rdev, fp); 4857439Sroot return; 4867439Sroot } 4877439Sroot #endif 488*7505Sroot if (fp->f_type == DTYPE_SOCKET) 4894891Swnj u.u_error = sostat(fp->f_socket, uap->sb); 4904828Swnj else 4914828Swnj stat1(fp->f_inode, uap->sb); 49237Sbill } 49337Sbill 49437Sbill /* 4956574Smckusic * Stat system call. This version follows links. 49637Sbill */ 49737Sbill stat() 49837Sbill { 49937Sbill register struct inode *ip; 50037Sbill register struct a { 50137Sbill char *fname; 50237Sbill struct stat *sb; 50337Sbill } *uap; 50437Sbill 50537Sbill uap = (struct a *)u.u_ap; 5066423Sroot ip = namei(uchar, 0, 1); 5074828Swnj if (ip == NULL) 50837Sbill return; 5097439Sroot #ifdef EFS 5107439Sroot if (efsinode(ip)) { 5117439Sroot dev_t ndev = ip->i_rdev; 5127439Sroot 5137439Sroot iput(ip); 5147439Sroot efsstat(ndev); 5157439Sroot if (u.u_error != EEXIST) 5167439Sroot return; 5177439Sroot u.u_error = 0; 5187439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 5197439Sroot ip = namei(uchar, 0, 1); 5207439Sroot } 5217439Sroot #endif 5223624Sroot stat1(ip, uap->sb); 52337Sbill iput(ip); 52437Sbill } 52537Sbill 52637Sbill /* 5276574Smckusic * Lstat system call. This version does not follow links. 5285992Swnj */ 5295992Swnj lstat() 5305992Swnj { 5315992Swnj register struct inode *ip; 5325992Swnj register struct a { 5335992Swnj char *fname; 5345992Swnj struct stat *sb; 5355992Swnj } *uap; 5365992Swnj 5375992Swnj uap = (struct a *)u.u_ap; 5386423Sroot ip = namei(uchar, 0, 0); 5395992Swnj if (ip == NULL) 5405992Swnj return; 5417439Sroot #ifdef EFS 5427439Sroot if (efsinode(ip)) { 5437439Sroot dev_t ndev = ip->i_rdev; 5447439Sroot 5457439Sroot iput(ip); 5467439Sroot efslstat(ndev); 5477439Sroot if (u.u_error != EEXIST) 5487439Sroot return; 5497439Sroot u.u_error = 0; 5507439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 5517439Sroot ip = namei(uchar, 0, 0); 5527439Sroot } 5537439Sroot #endif 5546153Ssam stat1(ip, uap->sb); 5555992Swnj iput(ip); 5565992Swnj } 5575992Swnj 5585992Swnj /* 55937Sbill * The basic routine for fstat and stat: 56037Sbill * get the inode and pass appropriate parts back. 56137Sbill */ 5623624Sroot stat1(ip, ub) 5634828Swnj register struct inode *ip; 5644828Swnj struct stat *ub; 56537Sbill { 56637Sbill struct stat ds; 56737Sbill 5681204Sbill IUPDAT(ip, &time, &time, 0); 56937Sbill /* 5707023Smckusick * Copy from inode table 57137Sbill */ 57237Sbill ds.st_dev = ip->i_dev; 57337Sbill ds.st_ino = ip->i_number; 57437Sbill ds.st_mode = ip->i_mode; 57537Sbill ds.st_nlink = ip->i_nlink; 57637Sbill ds.st_uid = ip->i_uid; 57737Sbill ds.st_gid = ip->i_gid; 5786574Smckusic ds.st_rdev = (dev_t)ip->i_rdev; 5793624Sroot ds.st_size = ip->i_size; 5806574Smckusic ds.st_atime = ip->i_atime; 5816574Smckusic ds.st_mtime = ip->i_mtime; 5826574Smckusic ds.st_ctime = ip->i_ctime; 5837023Smckusick ds.st_blksize = ip->i_fs->fs_bsize; 58437Sbill if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 58537Sbill u.u_error = EFAULT; 58637Sbill } 58737Sbill 58837Sbill /* 5895992Swnj * Return target name of a symbolic link 59037Sbill */ 5915992Swnj readlink() 5925992Swnj { 5935992Swnj register struct inode *ip; 5945992Swnj register struct a { 5955992Swnj char *name; 5965992Swnj char *buf; 5975992Swnj int count; 5985992Swnj } *uap; 5995992Swnj 6005992Swnj ip = namei(uchar, 0, 0); 6015992Swnj if (ip == NULL) 6025992Swnj return; 6037439Sroot #ifdef EFS 6047439Sroot if (efsinode(ip)) { 6057439Sroot dev_t ndev = ip->i_rdev; 6067439Sroot 6077439Sroot iput(ip); 6087439Sroot efsreadlink(ndev); 6097439Sroot if (u.u_error != EEXIST) 6107439Sroot return; 6117439Sroot u.u_error = 0; 6127439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 6137439Sroot ip = namei(uchar, 0, 0); 6147439Sroot return (0); 6157439Sroot } 6167439Sroot #endif 6175992Swnj if ((ip->i_mode&IFMT) != IFLNK) { 6185992Swnj u.u_error = ENXIO; 6195992Swnj goto out; 6205992Swnj } 6215992Swnj uap = (struct a *)u.u_ap; 6225992Swnj u.u_offset = 0; 6235992Swnj u.u_base = uap->buf; 6245992Swnj u.u_count = uap->count; 6255992Swnj u.u_segflg = 0; 6265992Swnj readi(ip); 6275992Swnj out: 6285992Swnj iput(ip); 6295992Swnj u.u_r.r_val1 = uap->count - u.u_count; 6305992Swnj } 6315992Swnj 6326254Sroot chmod() 6335992Swnj { 6346254Sroot register struct inode *ip; 6355992Swnj register struct a { 6366254Sroot char *fname; 6376254Sroot int fmode; 6385992Swnj } *uap; 6395992Swnj 6405992Swnj uap = (struct a *)u.u_ap; 6416254Sroot if ((ip = owner(1)) == NULL) 6425992Swnj return; 6437439Sroot #ifdef EFS 6447439Sroot if (efsinode(ip)) { 6457439Sroot dev_t ndev = ip->i_rdev; 6467439Sroot 6477439Sroot iput(ip); 6487439Sroot efschmod(ndev); 6497439Sroot if (u.u_error != EEXIST) 6507439Sroot return; 6517439Sroot u.u_error = 0; 6527439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 6537439Sroot ip = owner(1); 6547439Sroot } 6557439Sroot #endif 6566254Sroot ip->i_mode &= ~07777; 6577439Sroot if (u.u_uid) { 6586254Sroot uap->fmode &= ~ISVTX; 6597439Sroot if (ip->i_gid >= NGRPS || 6607439Sroot (u.u_grps[ip->i_gid/(sizeof(int)*8)] & 6617439Sroot (1 << ip->i_gid%(sizeof(int)*8))) == 0) 6627439Sroot uap->fmode &= ~ISGID; 6637482Skre #if MUSH 6647482Skre if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 && 6657482Skre (ip->i_mode & IFMT) != IFCHR) 6667482Skre uap->fmode &= ~u.u_cmask; 6677482Skre #endif 6687439Sroot } 6696254Sroot ip->i_mode |= uap->fmode&07777; 6706254Sroot ip->i_flag |= ICHG; 6716254Sroot if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 6726254Sroot xrele(ip); 6737482Skre #ifdef MELB 6747482Skre if ((ip->i_mode & ISUID) && ip->i_uid == 0) 6757482Skre printf("%s: ino %d (%s) setuid root\n" 6767482Skre , getfs(ip->i_dev)->s_fsmnt 6777482Skre , ip->i_number 6787482Skre , u.u_dent.d_name 6797482Skre ); 6807482Skre #endif 6815992Swnj iput(ip); 6825992Swnj } 6835992Swnj 6846254Sroot chown() 68537Sbill { 6866254Sroot register struct inode *ip; 68737Sbill register struct a { 6886254Sroot char *fname; 6896254Sroot int uid; 6906254Sroot int gid; 69137Sbill } *uap; 6927482Skre #if QUOTA 6937482Skre register long change; 6947482Skre #endif 69537Sbill 69637Sbill uap = (struct a *)u.u_ap; 6976254Sroot if (!suser() || (ip = owner(0)) == NULL) 69837Sbill return; 6997439Sroot #ifdef EFS 7007439Sroot if (efsinode(ip)) { 7017439Sroot dev_t ndev = ip->i_rdev; 7027439Sroot 7037439Sroot iput(ip); 7047439Sroot efschown(ndev); 7057439Sroot if (u.u_error != EEXIST) 7067439Sroot return; 7077439Sroot u.u_error = 0; 7087439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 7097439Sroot ip = owner(0); 7107439Sroot } 7117439Sroot #endif 7127482Skre #if QUOTA 7137439Sroot /* 7147482Skre * This doesn't allow for holes in files (which hopefully don't 7157482Skre * happen often in files that we chown), and is not accurate anyway 7167482Skre * (eg: it totally ignores 3 level indir blk files - but hopefully 7177482Skre * noone who can make a file that big will have a quota) 7187482Skre */ 7197482Skre if (ip->i_uid == uap->uid) 7207482Skre change = 0; 7217482Skre else { 7227482Skre register struct fs *fs = ip->i_fs; 7237482Skre 7247482Skre if (ip->i_size > (change = NDADDR * fs->fs_bsize)) { 7257482Skre register off_t size; 7267482Skre 7277482Skre size = blkroundup(fs, ip->i_size) - change; 7287482Skre change += size; 7297482Skre change += fs->fs_bsize; 7307482Skre /* This assumes NIADDR <= 2 */ 7317482Skre if (size > NINDIR(fs) * fs->fs_bsize) 7327482Skre change += fs->fs_bsize; 7337482Skre } else 7347482Skre change = fragroundup(fs, ip->i_size); 7357482Skre change /= DEV_BSIZE; 7367482Skre } 7377482Skre chkdq(ip, -change, 1); 7387482Skre chkiq(ip->i_dev, ip, ip->i_uid, 1); 7397482Skre dqrele(ip->i_dquot); 7407482Skre #endif 7417482Skre /* 7427439Sroot * keep uid/gid's in sane range - no err, so chown(file, uid, -1) 7437439Sroot * will do something useful 7447439Sroot */ 7457439Sroot if (uap->uid >= 0 && uap->uid <= 32767) /* should have a const */ 7467439Sroot ip->i_uid = uap->uid; 7477439Sroot if (uap->gid >= 0 && uap->gid <= 32767) /* same here */ 7487439Sroot ip->i_gid = uap->gid; 7496254Sroot ip->i_flag |= ICHG; 7506254Sroot if (u.u_ruid != 0) 7516254Sroot ip->i_mode &= ~(ISUID|ISGID); 7527482Skre #if QUOTA 7537482Skre ip->i_dquot = inoquota(ip); 7547482Skre chkdq(ip, change, 1); 7557482Skre chkiq(ip->i_dev, NULL, uap->uid, 1); 7567482Skre #endif 7576254Sroot iput(ip); 75837Sbill } 75937Sbill 76037Sbill /* 7616254Sroot * Set IUPD and IACC times on file. 7626254Sroot * Can't set ICHG. 76337Sbill */ 7646254Sroot utime() 7654828Swnj { 76637Sbill register struct a { 7676254Sroot char *fname; 7686254Sroot time_t *tptr; 76937Sbill } *uap; 7706254Sroot register struct inode *ip; 7716254Sroot time_t tv[2]; 77237Sbill 77337Sbill uap = (struct a *)u.u_ap; 7746254Sroot if ((ip = owner(1)) == NULL) 77537Sbill return; 7766254Sroot if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { 7776254Sroot u.u_error = EFAULT; 7786254Sroot } else { 7797439Sroot #ifdef EFS 7807439Sroot if (efsinode(ip)) { 7817439Sroot dev_t ndev = ip->i_rdev; 7827439Sroot 7837439Sroot iput(ip); 7847439Sroot efsutime(ndev, uap->fname, tv); 7857439Sroot if (u.u_error != EEXIST) 7867439Sroot return; 7877439Sroot u.u_error = 0; 7887439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 7897439Sroot ip = owner(1); 7907439Sroot } 7917439Sroot #endif 7926254Sroot ip->i_flag |= IACC|IUPD|ICHG; 7936254Sroot iupdat(ip, &tv[0], &tv[1], 0); 79437Sbill } 79537Sbill iput(ip); 79637Sbill } 79737Sbill 7986254Sroot sync() 79937Sbill { 80037Sbill 8015416Swnj update(0); 80237Sbill } 803