1*7535Sroot /* vfs_syscalls.c 4.31 82/07/25 */ 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" 197505Sroot #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 */ 827505Sroot 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); 1347505Sroot 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 } 225*7535Sroot direnter(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); 296*7535Sroot 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 */ 341*7535Sroot if (dirremove()) { 342*7535Sroot ip->i_nlink--; 343*7535Sroot ip->i_flag |= ICHG; 3446254Sroot } 3456254Sroot out: 3467142Smckusick if (unlinkingdot) 3477142Smckusick irele(ip); 3487142Smckusick else 3497142Smckusick iput(ip); 3506254Sroot out1: 3516254Sroot iput(pp); 3526254Sroot } 3536254Sroot 3546254Sroot /* 3556254Sroot * Seek system call 3566254Sroot */ 3576254Sroot seek() 3586254Sroot { 3596254Sroot register struct file *fp; 3606254Sroot register struct a { 3616254Sroot int fdes; 3626254Sroot off_t off; 3636254Sroot int sbase; 3646254Sroot } *uap; 3656254Sroot 3666254Sroot uap = (struct a *)u.u_ap; 3676254Sroot fp = getf(uap->fdes); 3686254Sroot if (fp == NULL) 3696254Sroot return; 3707505Sroot if (fp->f_type == DTYPE_SOCKET) { 3716254Sroot u.u_error = ESPIPE; 3726254Sroot return; 3736254Sroot } 3746254Sroot if (uap->sbase == 1) 3756254Sroot uap->off += fp->f_offset; 3767439Sroot else if (uap->sbase == 2) { 3777439Sroot #ifdef EFS 3787439Sroot struct inode *ip = fp->f_inode; 3797439Sroot uap->off += efsinode(ip) ? efsfilesize(fp) : ip->i_size; 3807439Sroot #else 3816254Sroot uap->off += fp->f_inode->i_size; 3827439Sroot #endif 3837439Sroot } 3846254Sroot fp->f_offset = uap->off; 3856254Sroot u.u_r.r_off = uap->off; 3866254Sroot } 3876254Sroot 3886254Sroot /* 3896254Sroot * Access system call 3906254Sroot */ 3916254Sroot saccess() 3926254Sroot { 3936254Sroot register svuid, svgid; 3946254Sroot register struct inode *ip; 3956254Sroot register struct a { 3966254Sroot char *fname; 3976254Sroot int fmode; 3986254Sroot } *uap; 3996254Sroot 4006254Sroot uap = (struct a *)u.u_ap; 4016254Sroot svuid = u.u_uid; 4026254Sroot svgid = u.u_gid; 4036254Sroot u.u_uid = u.u_ruid; 4046254Sroot u.u_gid = u.u_rgid; 4056254Sroot ip = namei(uchar, 0, 1); 4067439Sroot #ifdef EFS 4077439Sroot if (efsinode(ip)) { 4087439Sroot dev_t ndev = ip->i_rdev; 4097439Sroot 4107439Sroot iput(ip); 4117439Sroot efssaccess(ndev); 4127439Sroot if (u.u_error != EEXIST) 4137439Sroot return; 4147439Sroot u.u_error = 0; 4157439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 4167439Sroot ip = namei(uchar, 0, 1); 4177439Sroot } 4187439Sroot #endif 4196254Sroot if (ip != NULL) { 4206254Sroot if (uap->fmode&(IREAD>>6)) 4216254Sroot (void) access(ip, IREAD); 4226254Sroot if (uap->fmode&(IWRITE>>6)) 4236254Sroot (void) access(ip, IWRITE); 4246254Sroot if (uap->fmode&(IEXEC>>6)) 4256254Sroot (void) access(ip, IEXEC); 4266254Sroot iput(ip); 4276254Sroot } 4286254Sroot u.u_uid = svuid; 4296254Sroot u.u_gid = svgid; 4306254Sroot } 4316254Sroot 4326254Sroot /* 43337Sbill * the fstat system call. 43437Sbill */ 43537Sbill fstat() 43637Sbill { 43737Sbill register struct file *fp; 43837Sbill register struct a { 43937Sbill int fdes; 44037Sbill struct stat *sb; 44137Sbill } *uap; 44237Sbill 44337Sbill uap = (struct a *)u.u_ap; 44437Sbill fp = getf(uap->fdes); 4454828Swnj if (fp == NULL) 44637Sbill return; 4477439Sroot #ifdef EFS 4487439Sroot if (efsinode(fp->f_inode)) { 4497439Sroot efsfstat(fp->f_inode->i_rdev, fp); 4507439Sroot return; 4517439Sroot } 4527439Sroot #endif 4537505Sroot if (fp->f_type == DTYPE_SOCKET) 4544891Swnj u.u_error = sostat(fp->f_socket, uap->sb); 4554828Swnj else 4564828Swnj stat1(fp->f_inode, uap->sb); 45737Sbill } 45837Sbill 45937Sbill /* 4606574Smckusic * Stat system call. This version follows links. 46137Sbill */ 46237Sbill stat() 46337Sbill { 46437Sbill register struct inode *ip; 46537Sbill register struct a { 46637Sbill char *fname; 46737Sbill struct stat *sb; 46837Sbill } *uap; 46937Sbill 47037Sbill uap = (struct a *)u.u_ap; 4716423Sroot ip = namei(uchar, 0, 1); 4724828Swnj if (ip == NULL) 47337Sbill return; 4747439Sroot #ifdef EFS 4757439Sroot if (efsinode(ip)) { 4767439Sroot dev_t ndev = ip->i_rdev; 4777439Sroot 4787439Sroot iput(ip); 4797439Sroot efsstat(ndev); 4807439Sroot if (u.u_error != EEXIST) 4817439Sroot return; 4827439Sroot u.u_error = 0; 4837439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 4847439Sroot ip = namei(uchar, 0, 1); 4857439Sroot } 4867439Sroot #endif 4873624Sroot stat1(ip, uap->sb); 48837Sbill iput(ip); 48937Sbill } 49037Sbill 49137Sbill /* 4926574Smckusic * Lstat system call. This version does not follow links. 4935992Swnj */ 4945992Swnj lstat() 4955992Swnj { 4965992Swnj register struct inode *ip; 4975992Swnj register struct a { 4985992Swnj char *fname; 4995992Swnj struct stat *sb; 5005992Swnj } *uap; 5015992Swnj 5025992Swnj uap = (struct a *)u.u_ap; 5036423Sroot ip = namei(uchar, 0, 0); 5045992Swnj if (ip == NULL) 5055992Swnj return; 5067439Sroot #ifdef EFS 5077439Sroot if (efsinode(ip)) { 5087439Sroot dev_t ndev = ip->i_rdev; 5097439Sroot 5107439Sroot iput(ip); 5117439Sroot efslstat(ndev); 5127439Sroot if (u.u_error != EEXIST) 5137439Sroot return; 5147439Sroot u.u_error = 0; 5157439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 5167439Sroot ip = namei(uchar, 0, 0); 5177439Sroot } 5187439Sroot #endif 5196153Ssam stat1(ip, uap->sb); 5205992Swnj iput(ip); 5215992Swnj } 5225992Swnj 5235992Swnj /* 52437Sbill * The basic routine for fstat and stat: 52537Sbill * get the inode and pass appropriate parts back. 52637Sbill */ 5273624Sroot stat1(ip, ub) 5284828Swnj register struct inode *ip; 5294828Swnj struct stat *ub; 53037Sbill { 53137Sbill struct stat ds; 53237Sbill 5331204Sbill IUPDAT(ip, &time, &time, 0); 53437Sbill /* 5357023Smckusick * Copy from inode table 53637Sbill */ 53737Sbill ds.st_dev = ip->i_dev; 53837Sbill ds.st_ino = ip->i_number; 53937Sbill ds.st_mode = ip->i_mode; 54037Sbill ds.st_nlink = ip->i_nlink; 54137Sbill ds.st_uid = ip->i_uid; 54237Sbill ds.st_gid = ip->i_gid; 5436574Smckusic ds.st_rdev = (dev_t)ip->i_rdev; 5443624Sroot ds.st_size = ip->i_size; 5456574Smckusic ds.st_atime = ip->i_atime; 5466574Smckusic ds.st_mtime = ip->i_mtime; 5476574Smckusic ds.st_ctime = ip->i_ctime; 5487023Smckusick ds.st_blksize = ip->i_fs->fs_bsize; 54937Sbill if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 55037Sbill u.u_error = EFAULT; 55137Sbill } 55237Sbill 55337Sbill /* 5545992Swnj * Return target name of a symbolic link 55537Sbill */ 5565992Swnj readlink() 5575992Swnj { 5585992Swnj register struct inode *ip; 5595992Swnj register struct a { 5605992Swnj char *name; 5615992Swnj char *buf; 5625992Swnj int count; 5635992Swnj } *uap; 5645992Swnj 5655992Swnj ip = namei(uchar, 0, 0); 5665992Swnj if (ip == NULL) 5675992Swnj return; 5687439Sroot #ifdef EFS 5697439Sroot if (efsinode(ip)) { 5707439Sroot dev_t ndev = ip->i_rdev; 5717439Sroot 5727439Sroot iput(ip); 5737439Sroot efsreadlink(ndev); 5747439Sroot if (u.u_error != EEXIST) 5757439Sroot return; 5767439Sroot u.u_error = 0; 5777439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 5787439Sroot ip = namei(uchar, 0, 0); 5797439Sroot return (0); 5807439Sroot } 5817439Sroot #endif 5825992Swnj if ((ip->i_mode&IFMT) != IFLNK) { 5835992Swnj u.u_error = ENXIO; 5845992Swnj goto out; 5855992Swnj } 5865992Swnj uap = (struct a *)u.u_ap; 5875992Swnj u.u_offset = 0; 5885992Swnj u.u_base = uap->buf; 5895992Swnj u.u_count = uap->count; 5905992Swnj u.u_segflg = 0; 5915992Swnj readi(ip); 5925992Swnj out: 5935992Swnj iput(ip); 5945992Swnj u.u_r.r_val1 = uap->count - u.u_count; 5955992Swnj } 5965992Swnj 5976254Sroot chmod() 5985992Swnj { 5996254Sroot register struct inode *ip; 6005992Swnj register struct a { 6016254Sroot char *fname; 6026254Sroot int fmode; 6035992Swnj } *uap; 6045992Swnj 6055992Swnj uap = (struct a *)u.u_ap; 6066254Sroot if ((ip = owner(1)) == NULL) 6075992Swnj return; 6087439Sroot #ifdef EFS 6097439Sroot if (efsinode(ip)) { 6107439Sroot dev_t ndev = ip->i_rdev; 6117439Sroot 6127439Sroot iput(ip); 6137439Sroot efschmod(ndev); 6147439Sroot if (u.u_error != EEXIST) 6157439Sroot return; 6167439Sroot u.u_error = 0; 6177439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 6187439Sroot ip = owner(1); 6197439Sroot } 6207439Sroot #endif 6216254Sroot ip->i_mode &= ~07777; 6227439Sroot if (u.u_uid) { 6236254Sroot uap->fmode &= ~ISVTX; 6247439Sroot if (ip->i_gid >= NGRPS || 6257439Sroot (u.u_grps[ip->i_gid/(sizeof(int)*8)] & 6267439Sroot (1 << ip->i_gid%(sizeof(int)*8))) == 0) 6277439Sroot uap->fmode &= ~ISGID; 6287482Skre #if MUSH 6297482Skre if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 && 6307482Skre (ip->i_mode & IFMT) != IFCHR) 6317482Skre uap->fmode &= ~u.u_cmask; 6327482Skre #endif 6337439Sroot } 6346254Sroot ip->i_mode |= uap->fmode&07777; 6356254Sroot ip->i_flag |= ICHG; 6366254Sroot if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 6376254Sroot xrele(ip); 6387482Skre #ifdef MELB 6397482Skre if ((ip->i_mode & ISUID) && ip->i_uid == 0) 6407482Skre printf("%s: ino %d (%s) setuid root\n" 6417482Skre , getfs(ip->i_dev)->s_fsmnt 6427482Skre , ip->i_number 6437482Skre , u.u_dent.d_name 6447482Skre ); 6457482Skre #endif 6465992Swnj iput(ip); 6475992Swnj } 6485992Swnj 6496254Sroot chown() 65037Sbill { 6516254Sroot register struct inode *ip; 65237Sbill register struct a { 6536254Sroot char *fname; 6546254Sroot int uid; 6556254Sroot int gid; 65637Sbill } *uap; 6577482Skre #if QUOTA 6587482Skre register long change; 6597482Skre #endif 66037Sbill 66137Sbill uap = (struct a *)u.u_ap; 6626254Sroot if (!suser() || (ip = owner(0)) == NULL) 66337Sbill return; 6647439Sroot #ifdef EFS 6657439Sroot if (efsinode(ip)) { 6667439Sroot dev_t ndev = ip->i_rdev; 6677439Sroot 6687439Sroot iput(ip); 6697439Sroot efschown(ndev); 6707439Sroot if (u.u_error != EEXIST) 6717439Sroot return; 6727439Sroot u.u_error = 0; 6737439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 6747439Sroot ip = owner(0); 6757439Sroot } 6767439Sroot #endif 6777482Skre #if QUOTA 6787439Sroot /* 6797482Skre * This doesn't allow for holes in files (which hopefully don't 6807482Skre * happen often in files that we chown), and is not accurate anyway 6817482Skre * (eg: it totally ignores 3 level indir blk files - but hopefully 6827482Skre * noone who can make a file that big will have a quota) 6837482Skre */ 6847482Skre if (ip->i_uid == uap->uid) 6857482Skre change = 0; 6867482Skre else { 6877482Skre register struct fs *fs = ip->i_fs; 6887482Skre 6897482Skre if (ip->i_size > (change = NDADDR * fs->fs_bsize)) { 6907482Skre register off_t size; 6917482Skre 6927482Skre size = blkroundup(fs, ip->i_size) - change; 6937482Skre change += size; 6947482Skre change += fs->fs_bsize; 6957482Skre /* This assumes NIADDR <= 2 */ 6967482Skre if (size > NINDIR(fs) * fs->fs_bsize) 6977482Skre change += fs->fs_bsize; 6987482Skre } else 6997482Skre change = fragroundup(fs, ip->i_size); 7007482Skre change /= DEV_BSIZE; 7017482Skre } 7027482Skre chkdq(ip, -change, 1); 7037482Skre chkiq(ip->i_dev, ip, ip->i_uid, 1); 7047482Skre dqrele(ip->i_dquot); 7057482Skre #endif 7067482Skre /* 7077439Sroot * keep uid/gid's in sane range - no err, so chown(file, uid, -1) 7087439Sroot * will do something useful 7097439Sroot */ 7107439Sroot if (uap->uid >= 0 && uap->uid <= 32767) /* should have a const */ 7117439Sroot ip->i_uid = uap->uid; 7127439Sroot if (uap->gid >= 0 && uap->gid <= 32767) /* same here */ 7137439Sroot ip->i_gid = uap->gid; 7146254Sroot ip->i_flag |= ICHG; 7156254Sroot if (u.u_ruid != 0) 7166254Sroot ip->i_mode &= ~(ISUID|ISGID); 7177482Skre #if QUOTA 7187482Skre ip->i_dquot = inoquota(ip); 7197482Skre chkdq(ip, change, 1); 7207482Skre chkiq(ip->i_dev, NULL, uap->uid, 1); 7217482Skre #endif 7226254Sroot iput(ip); 72337Sbill } 72437Sbill 72537Sbill /* 7266254Sroot * Set IUPD and IACC times on file. 7276254Sroot * Can't set ICHG. 72837Sbill */ 7296254Sroot utime() 7304828Swnj { 73137Sbill register struct a { 7326254Sroot char *fname; 7336254Sroot time_t *tptr; 73437Sbill } *uap; 7356254Sroot register struct inode *ip; 7366254Sroot time_t tv[2]; 73737Sbill 73837Sbill uap = (struct a *)u.u_ap; 7396254Sroot if ((ip = owner(1)) == NULL) 74037Sbill return; 7416254Sroot if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { 7426254Sroot u.u_error = EFAULT; 7436254Sroot } else { 7447439Sroot #ifdef EFS 7457439Sroot if (efsinode(ip)) { 7467439Sroot dev_t ndev = ip->i_rdev; 7477439Sroot 7487439Sroot iput(ip); 7497439Sroot efsutime(ndev, uap->fname, tv); 7507439Sroot if (u.u_error != EEXIST) 7517439Sroot return; 7527439Sroot u.u_error = 0; 7537439Sroot u.u_dirp = (caddr_t)u.u_arg[0]; 7547439Sroot ip = owner(1); 7557439Sroot } 7567439Sroot #endif 7576254Sroot ip->i_flag |= IACC|IUPD|ICHG; 7586254Sroot iupdat(ip, &tv[0], &tv[1], 0); 75937Sbill } 76037Sbill iput(ip); 76137Sbill } 76237Sbill 7636254Sroot sync() 76437Sbill { 76537Sbill 7665416Swnj update(0); 76737Sbill } 768*7535Sroot 769*7535Sroot /* 770*7535Sroot * Make a new file. 771*7535Sroot */ 772*7535Sroot struct inode * 773*7535Sroot maknode(mode) 774*7535Sroot int mode; 775*7535Sroot { 776*7535Sroot register struct inode *ip; 777*7535Sroot ino_t ipref; 778*7535Sroot 779*7535Sroot if ((mode & IFMT) == IFDIR) 780*7535Sroot ipref = dirpref(u.u_pdir->i_fs); 781*7535Sroot else 782*7535Sroot ipref = u.u_pdir->i_number; 783*7535Sroot ip = ialloc(u.u_pdir, ipref, mode); 784*7535Sroot if (ip == NULL) { 785*7535Sroot iput(u.u_pdir); 786*7535Sroot return(NULL); 787*7535Sroot } 788*7535Sroot #ifdef QUOTA 789*7535Sroot if (ip->i_dquot != NODQUOT) 790*7535Sroot panic("maknode: dquot"); 791*7535Sroot #endif 792*7535Sroot ip->i_flag |= IACC|IUPD|ICHG; 793*7535Sroot if ((mode & IFMT) == 0) 794*7535Sroot mode |= IFREG; 795*7535Sroot ip->i_mode = mode & ~u.u_cmask; 796*7535Sroot ip->i_nlink = 1; 797*7535Sroot ip->i_uid = u.u_uid; 798*7535Sroot ip->i_gid = u.u_pdir->i_gid; 799*7535Sroot #ifdef QUOTA 800*7535Sroot ip->i_dquot = inoquota(ip); 801*7535Sroot #endif 802*7535Sroot 803*7535Sroot /* 804*7535Sroot * Make sure inode goes to disk before directory entry. 805*7535Sroot */ 806*7535Sroot iupdat(ip, &time, &time, 1); 807*7535Sroot direnter(ip); 808*7535Sroot if (u.u_error) { 809*7535Sroot /* 810*7535Sroot * write error occurred trying to update directory 811*7535Sroot * so must deallocate the inode 812*7535Sroot */ 813*7535Sroot ip->i_nlink = 0; 814*7535Sroot ip->i_flag |= ICHG; 815*7535Sroot iput(ip); 816*7535Sroot return(NULL); 817*7535Sroot } 818*7535Sroot return(ip); 819*7535Sroot } 820