1*7701Ssam /* vfs_syscalls.c 4.32 82/08/10 */ 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*7701Ssam /* no reason to inline expand these guys here */ 15*7701Ssam #undef ilock 16*7701Ssam #undef iunlock 177482Skre #include "../h/quota.h" 187505Sroot #include "../h/descrip.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) 34*7701Ssam 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; 68*7701Ssam int flags; 69*7701Ssam int mode; 706254Sroot } *uap; 71*7701Ssam int checkpermissions = 1; 726254Sroot 736254Sroot uap = (struct a *)u.u_ap; 74*7701Ssam if (uap->flags&FCREATE) { 75*7701Ssam ip = namei(uchar, 1, 1); 76*7701Ssam if (ip == NULL) { 77*7701Ssam if (u.u_error) 78*7701Ssam return; 79*7701Ssam ip = maknode(uap->mode&07777&(~ISVTX)); 80*7701Ssam checkpermissions = 0; 81*7701Ssam uap->flags &= ~FTRUNCATE; 82*7701Ssam } 83*7701Ssam } else 84*7701Ssam ip = namei(uchar, 0, 1); 856254Sroot if (ip == NULL) 866254Sroot return; 87*7701Ssam open1(ip, ++uap->flags, checkpermissions); 886254Sroot } 896254Sroot 90*7701Ssam #ifndef NOCOMPAT 916254Sroot /* 926254Sroot * Creat system call. 936254Sroot */ 947505Sroot ocreat() 956254Sroot { 966254Sroot register struct inode *ip; 976254Sroot register struct a { 986254Sroot char *fname; 996254Sroot int fmode; 1006254Sroot } *uap; 1016254Sroot 1026254Sroot uap = (struct a *)u.u_ap; 1036254Sroot ip = namei(uchar, 1, 1); 1046254Sroot if (ip == NULL) { 1056254Sroot if (u.u_error) 1066254Sroot return; 1076254Sroot ip = maknode(uap->fmode&07777&(~ISVTX)); 108*7701Ssam if (ip == NULL) 1096254Sroot return; 110*7701Ssam open1(ip, FWRITE, 0); 1116254Sroot } else 112*7701Ssam open1(ip, FWRITE|FTRUNCATE, 0); 1136254Sroot } 114*7701Ssam #endif 1156254Sroot 1166254Sroot /* 1176254Sroot * Common code for open and creat. 118*7701Ssam * Check permissions (if we haven't done so already), 119*7701Ssam * allocate an open file structure, and call 120*7701Ssam * the device open routine, if any. 1216254Sroot */ 122*7701Ssam open1(ip, mode, checkpermissions) 1236254Sroot register struct inode *ip; 1246254Sroot register mode; 1256254Sroot { 1266254Sroot register struct file *fp; 127*7701Ssam int i, flags; 1286254Sroot 129*7701Ssam if (checkpermissions) { 1306254Sroot if (mode&FREAD) 131*7701Ssam if (access(ip, IREAD)) 132*7701Ssam goto bad; 1336254Sroot if (mode&FWRITE) { 134*7701Ssam if (access(ip, IWRITE)) 135*7701Ssam goto bad; 136*7701Ssam if ((ip->i_mode&IFMT) == IFDIR) { 1376254Sroot u.u_error = EISDIR; 138*7701Ssam goto bad; 139*7701Ssam } 1406254Sroot } 1416254Sroot } 142*7701Ssam 143*7701Ssam /* 144*7701Ssam * Check locking on inode. Release "inode lock" 145*7701Ssam * while doing so in case we block inside flocki. 146*7701Ssam */ 147*7701Ssam flags = 0; 148*7701Ssam if (mode&(FRDLOCK|FWRLOCK)) { 149*7701Ssam iunlock(ip); 150*7701Ssam flags = flocki(ip, 0, mode); 151*7701Ssam ilock(ip); 152*7701Ssam if (u.u_error) 153*7701Ssam goto bad; 1547142Smckusick } 155*7701Ssam if (mode&FTRUNCATE) 156*7701Ssam itrunc(ip, 0); 1577122Smckusick iunlock(ip); 1586254Sroot if ((fp = falloc()) == NULL) 1596254Sroot goto out; 160*7701Ssam fp->f_flag = mode & FMODES; 1617505Sroot fp->f_type = DTYPE_FILE; 1626254Sroot i = u.u_r.r_val1; 1636254Sroot fp->f_inode = ip; 164*7701Ssam openi(ip, mode); 165*7701Ssam if (u.u_error == 0) { 166*7701Ssam u.u_pofile[i] = flags; 1676254Sroot return; 168*7701Ssam } 1696254Sroot u.u_ofile[i] = NULL; 1706254Sroot fp->f_count--; 1716254Sroot out: 1727142Smckusick irele(ip); 173*7701Ssam return; 174*7701Ssam bad: 175*7701Ssam iput(ip); 1766254Sroot } 1776254Sroot 1786254Sroot /* 1796254Sroot * Mknod system call 1806254Sroot */ 1816254Sroot mknod() 1826254Sroot { 1836254Sroot register struct inode *ip; 1846254Sroot register struct a { 1856254Sroot char *fname; 1866254Sroot int fmode; 1876254Sroot int dev; 1886254Sroot } *uap; 1896254Sroot 1906254Sroot uap = (struct a *)u.u_ap; 1916254Sroot if (suser()) { 1926254Sroot ip = namei(uchar, 1, 0); 1936254Sroot if (ip != NULL) { 1946254Sroot u.u_error = EEXIST; 1956254Sroot goto out; 1966254Sroot } 1976254Sroot } 1986254Sroot if (u.u_error) 1996254Sroot return; 2006254Sroot ip = maknode(uap->fmode); 2016254Sroot if (ip == NULL) 2026254Sroot return; 2036254Sroot if (uap->dev) { 2046254Sroot /* 2056254Sroot * Want to be able to use this to make badblock 2066254Sroot * inodes, so don't truncate the dev number. 2076254Sroot */ 2086574Smckusic ip->i_rdev = uap->dev; 2096254Sroot ip->i_flag |= IACC|IUPD|ICHG; 2106254Sroot } 2116254Sroot 2126254Sroot out: 2136254Sroot iput(ip); 2146254Sroot } 2156254Sroot 2166254Sroot /* 2176254Sroot * link system call 2186254Sroot */ 2196254Sroot link() 2206254Sroot { 2216254Sroot register struct inode *ip, *xp; 2226254Sroot register struct a { 2236254Sroot char *target; 2246254Sroot char *linkname; 2256254Sroot } *uap; 2266254Sroot 2276254Sroot uap = (struct a *)u.u_ap; 2286254Sroot ip = namei(uchar, 0, 1); /* well, this routine is doomed anyhow */ 2296254Sroot if (ip == NULL) 2306254Sroot return; 2317439Sroot if ((ip->i_mode&IFMT)==IFDIR && !suser()) { 2327439Sroot iput(ip); 2337439Sroot return; 2347439Sroot } 2356254Sroot ip->i_nlink++; 2366254Sroot ip->i_flag |= ICHG; 2376254Sroot iupdat(ip, &time, &time, 1); 2387122Smckusick iunlock(ip); 2396254Sroot u.u_dirp = (caddr_t)uap->linkname; 2406254Sroot xp = namei(uchar, 1, 0); 2416254Sroot if (xp != NULL) { 2426254Sroot u.u_error = EEXIST; 2436254Sroot iput(xp); 2446254Sroot goto out; 2456254Sroot } 2466254Sroot if (u.u_error) 2476254Sroot goto out; 2486254Sroot if (u.u_pdir->i_dev != ip->i_dev) { 2496254Sroot iput(u.u_pdir); 2506254Sroot u.u_error = EXDEV; 2516254Sroot goto out; 2526254Sroot } 2537535Sroot direnter(ip); 2546254Sroot out: 2556254Sroot if (u.u_error) { 2566254Sroot ip->i_nlink--; 2576254Sroot ip->i_flag |= ICHG; 2586254Sroot } 2596254Sroot out1: 2607142Smckusick irele(ip); 2616254Sroot } 2626254Sroot 2636254Sroot /* 2646254Sroot * symlink -- make a symbolic link 2656254Sroot */ 2666254Sroot symlink() 2676254Sroot { 2686254Sroot register struct a { 2696254Sroot char *target; 2706254Sroot char *linkname; 2716254Sroot } *uap; 2726254Sroot register struct inode *ip; 2736254Sroot register char *tp; 2746254Sroot register c, nc; 2756254Sroot 2766254Sroot uap = (struct a *)u.u_ap; 2776254Sroot tp = uap->target; 2786254Sroot nc = 0; 2796254Sroot while (c = fubyte(tp)) { 2806254Sroot if (c < 0) { 2816254Sroot u.u_error = EFAULT; 2826254Sroot return; 2836254Sroot } 2846254Sroot tp++; 2856254Sroot nc++; 2866254Sroot } 2876254Sroot u.u_dirp = uap->linkname; 2886254Sroot ip = namei(uchar, 1, 0); 2896254Sroot if (ip) { 2906254Sroot iput(ip); 2916254Sroot u.u_error = EEXIST; 2926254Sroot return; 2936254Sroot } 2946254Sroot if (u.u_error) 2956254Sroot return; 2966254Sroot ip = maknode(IFLNK | 0777); 2976254Sroot if (ip == NULL) 2986254Sroot return; 2996254Sroot u.u_base = uap->target; 3006254Sroot u.u_count = nc; 3016254Sroot u.u_offset = 0; 3026254Sroot u.u_segflg = 0; 3036254Sroot writei(ip); 3046254Sroot iput(ip); 3056254Sroot } 3066254Sroot 3076254Sroot /* 3086254Sroot * Unlink system call. 3096254Sroot * Hard to avoid races here, especially 3106254Sroot * in unlinking directories. 3116254Sroot */ 3126254Sroot unlink() 3136254Sroot { 3146254Sroot register struct inode *ip, *pp; 3156254Sroot struct a { 3166254Sroot char *fname; 3176254Sroot }; 3186574Smckusic struct fs *fs; 3196574Smckusic struct buf *bp; 3206574Smckusic int lbn, bn, base; 3217142Smckusick int unlinkingdot = 0; 3226254Sroot 3236254Sroot pp = namei(uchar, 2, 0); 3247535Sroot if (pp == NULL) 3256254Sroot return; 3267439Sroot 3276254Sroot /* 3286254Sroot * Check for unlink(".") 3296254Sroot * to avoid hanging on the iget 3306254Sroot */ 3316254Sroot if (pp->i_number == u.u_dent.d_ino) { 3326254Sroot ip = pp; 3336254Sroot ip->i_count++; 3347142Smckusick unlinkingdot++; 3356254Sroot } else 3366574Smckusic ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino); 3376254Sroot if(ip == NULL) 3386254Sroot goto out1; 3396254Sroot if((ip->i_mode&IFMT)==IFDIR && !suser()) 3406254Sroot goto out; 3416254Sroot /* 3426254Sroot * Don't unlink a mounted file. 3436254Sroot */ 3446254Sroot if (ip->i_dev != pp->i_dev) { 3456254Sroot u.u_error = EBUSY; 3466254Sroot goto out; 3476254Sroot } 3486254Sroot if (ip->i_flag&ITEXT) 3496254Sroot xrele(ip); /* try once to free text */ 3507535Sroot if (dirremove()) { 3517535Sroot ip->i_nlink--; 3527535Sroot ip->i_flag |= ICHG; 3536254Sroot } 3546254Sroot out: 3557142Smckusick if (unlinkingdot) 3567142Smckusick irele(ip); 3577142Smckusick else 3587142Smckusick iput(ip); 3596254Sroot out1: 3606254Sroot iput(pp); 3616254Sroot } 3626254Sroot 3636254Sroot /* 3646254Sroot * Seek system call 3656254Sroot */ 3666254Sroot seek() 3676254Sroot { 3686254Sroot register struct file *fp; 3696254Sroot register struct a { 370*7701Ssam int fd; 3716254Sroot off_t off; 3726254Sroot int sbase; 3736254Sroot } *uap; 3746254Sroot 3756254Sroot uap = (struct a *)u.u_ap; 376*7701Ssam fp = getf(uap->fd); 3776254Sroot if (fp == NULL) 3786254Sroot return; 3797505Sroot if (fp->f_type == DTYPE_SOCKET) { 3806254Sroot u.u_error = ESPIPE; 3816254Sroot return; 3826254Sroot } 383*7701Ssam if (uap->sbase == FSEEK_RELATIVE) 3846254Sroot uap->off += fp->f_offset; 385*7701Ssam else if (uap->sbase == FSEEK_EOF) 3866254Sroot uap->off += fp->f_inode->i_size; 3876254Sroot fp->f_offset = uap->off; 3886254Sroot u.u_r.r_off = uap->off; 3896254Sroot } 3906254Sroot 3916254Sroot /* 3926254Sroot * Access system call 3936254Sroot */ 3946254Sroot saccess() 3956254Sroot { 3966254Sroot register svuid, svgid; 3976254Sroot register struct inode *ip; 3986254Sroot register struct a { 3996254Sroot char *fname; 4006254Sroot int fmode; 4016254Sroot } *uap; 4026254Sroot 4036254Sroot uap = (struct a *)u.u_ap; 4046254Sroot svuid = u.u_uid; 4056254Sroot svgid = u.u_gid; 4066254Sroot u.u_uid = u.u_ruid; 4076254Sroot u.u_gid = u.u_rgid; 4086254Sroot ip = namei(uchar, 0, 1); 4096254Sroot if (ip != NULL) { 410*7701Ssam if (uap->fmode&FACCESS_READ && access(ip, IREAD)) 411*7701Ssam goto done; 412*7701Ssam if (uap->fmode&FACCESS_WRITE && access(ip, IWRITE)) 413*7701Ssam goto done; 414*7701Ssam if (uap->fmode&FACCESS_EXECUTE && access(ip, IEXEC)) 415*7701Ssam goto done; 416*7701Ssam done: 4176254Sroot iput(ip); 4186254Sroot } 4196254Sroot u.u_uid = svuid; 4206254Sroot u.u_gid = svgid; 4216254Sroot } 4226254Sroot 4236254Sroot /* 42437Sbill * the fstat system call. 42537Sbill */ 42637Sbill fstat() 42737Sbill { 42837Sbill register struct file *fp; 42937Sbill register struct a { 430*7701Ssam int fd; 43137Sbill struct stat *sb; 43237Sbill } *uap; 43337Sbill 43437Sbill uap = (struct a *)u.u_ap; 435*7701Ssam fp = getf(uap->fd); 4364828Swnj if (fp == NULL) 43737Sbill return; 4387505Sroot if (fp->f_type == DTYPE_SOCKET) 4394891Swnj u.u_error = sostat(fp->f_socket, uap->sb); 4404828Swnj else 4414828Swnj stat1(fp->f_inode, uap->sb); 44237Sbill } 44337Sbill 44437Sbill /* 4456574Smckusic * Stat system call. This version follows links. 44637Sbill */ 44737Sbill stat() 44837Sbill { 44937Sbill register struct inode *ip; 45037Sbill register struct a { 45137Sbill char *fname; 45237Sbill struct stat *sb; 45337Sbill } *uap; 45437Sbill 45537Sbill uap = (struct a *)u.u_ap; 4566423Sroot ip = namei(uchar, 0, 1); 4574828Swnj if (ip == NULL) 45837Sbill return; 4593624Sroot stat1(ip, uap->sb); 46037Sbill iput(ip); 46137Sbill } 46237Sbill 46337Sbill /* 4646574Smckusic * Lstat system call. This version does not follow links. 4655992Swnj */ 4665992Swnj lstat() 4675992Swnj { 4685992Swnj register struct inode *ip; 4695992Swnj register struct a { 4705992Swnj char *fname; 4715992Swnj struct stat *sb; 4725992Swnj } *uap; 4735992Swnj 4745992Swnj uap = (struct a *)u.u_ap; 4756423Sroot ip = namei(uchar, 0, 0); 4765992Swnj if (ip == NULL) 4775992Swnj return; 4786153Ssam stat1(ip, uap->sb); 4795992Swnj iput(ip); 4805992Swnj } 4815992Swnj 4825992Swnj /* 48337Sbill * The basic routine for fstat and stat: 48437Sbill * get the inode and pass appropriate parts back. 48537Sbill */ 4863624Sroot stat1(ip, ub) 4874828Swnj register struct inode *ip; 4884828Swnj struct stat *ub; 48937Sbill { 49037Sbill struct stat ds; 49137Sbill 4921204Sbill IUPDAT(ip, &time, &time, 0); 49337Sbill /* 4947023Smckusick * Copy from inode table 49537Sbill */ 49637Sbill ds.st_dev = ip->i_dev; 49737Sbill ds.st_ino = ip->i_number; 49837Sbill ds.st_mode = ip->i_mode; 49937Sbill ds.st_nlink = ip->i_nlink; 50037Sbill ds.st_uid = ip->i_uid; 50137Sbill ds.st_gid = ip->i_gid; 5026574Smckusic ds.st_rdev = (dev_t)ip->i_rdev; 5033624Sroot ds.st_size = ip->i_size; 5046574Smckusic ds.st_atime = ip->i_atime; 5056574Smckusic ds.st_mtime = ip->i_mtime; 5066574Smckusic ds.st_ctime = ip->i_ctime; 507*7701Ssam /* this doesn't belong here */ 508*7701Ssam if ((ip->i_mode&IFMT) == IFBLK) 509*7701Ssam ds.st_blksize = BLKDEV_IOSIZE; 510*7701Ssam else if ((ip->i_mode&IFMT) == IFCHR) 511*7701Ssam ds.st_blksize = MAXBSIZE; 512*7701Ssam else 513*7701Ssam ds.st_blksize = ip->i_fs->fs_bsize; 51437Sbill if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 51537Sbill u.u_error = EFAULT; 51637Sbill } 51737Sbill 51837Sbill /* 5195992Swnj * Return target name of a symbolic link 52037Sbill */ 5215992Swnj readlink() 5225992Swnj { 5235992Swnj register struct inode *ip; 5245992Swnj register struct a { 5255992Swnj char *name; 5265992Swnj char *buf; 5275992Swnj int count; 5285992Swnj } *uap; 5295992Swnj 5305992Swnj ip = namei(uchar, 0, 0); 5315992Swnj if (ip == NULL) 5325992Swnj return; 5335992Swnj if ((ip->i_mode&IFMT) != IFLNK) { 5345992Swnj u.u_error = ENXIO; 5355992Swnj goto out; 5365992Swnj } 5375992Swnj uap = (struct a *)u.u_ap; 5385992Swnj u.u_offset = 0; 5395992Swnj u.u_base = uap->buf; 5405992Swnj u.u_count = uap->count; 5415992Swnj u.u_segflg = 0; 5425992Swnj readi(ip); 5435992Swnj out: 5445992Swnj iput(ip); 5455992Swnj u.u_r.r_val1 = uap->count - u.u_count; 5465992Swnj } 5475992Swnj 5486254Sroot chmod() 5495992Swnj { 550*7701Ssam struct inode *ip; 551*7701Ssam struct a { 5526254Sroot char *fname; 5536254Sroot int fmode; 5545992Swnj } *uap; 5555992Swnj 5565992Swnj uap = (struct a *)u.u_ap; 5576254Sroot if ((ip = owner(1)) == NULL) 5585992Swnj return; 559*7701Ssam chmod1(ip, uap->fmode); 560*7701Ssam } 5617439Sroot 562*7701Ssam fchmod() 563*7701Ssam { 564*7701Ssam struct a { 565*7701Ssam int fd; 566*7701Ssam int fmode; 567*7701Ssam } *uap; 568*7701Ssam register struct inode *ip; 569*7701Ssam register struct file *fp; 570*7701Ssam 571*7701Ssam uap = (struct a *)u.u_ap; 572*7701Ssam fp = getf(uap->fd); 573*7701Ssam if (fp == NULL) 574*7701Ssam return; 575*7701Ssam if (fp->f_type == DTYPE_SOCKET) { 576*7701Ssam u.u_error = EINVAL; 577*7701Ssam return; 5787439Sroot } 579*7701Ssam ip = fp->f_inode; 580*7701Ssam ilock(ip); 581*7701Ssam if (u.u_uid != ip->i_uid && !suser()) { 582*7701Ssam iunlock(ip); 583*7701Ssam return; 584*7701Ssam } 585*7701Ssam chmod1(ip, uap->fmode); 586*7701Ssam } 587*7701Ssam 588*7701Ssam chmod1(ip, mode) 589*7701Ssam register struct inode *ip; 590*7701Ssam register int mode; 591*7701Ssam { 5926254Sroot ip->i_mode &= ~07777; 5937439Sroot if (u.u_uid) { 594*7701Ssam mode &= ~ISVTX; 5957439Sroot if (ip->i_gid >= NGRPS || 5967439Sroot (u.u_grps[ip->i_gid/(sizeof(int)*8)] & 5977439Sroot (1 << ip->i_gid%(sizeof(int)*8))) == 0) 598*7701Ssam mode &= ~ISGID; 599*7701Ssam #ifdef MUSH 6007482Skre if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 && 6017482Skre (ip->i_mode & IFMT) != IFCHR) 602*7701Ssam mode &= ~u.u_cmask; 6037482Skre #endif 6047439Sroot } 605*7701Ssam ip->i_mode |= mode&07777; 6066254Sroot ip->i_flag |= ICHG; 6076254Sroot if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 6086254Sroot xrele(ip); 6095992Swnj iput(ip); 6105992Swnj } 6115992Swnj 6126254Sroot chown() 61337Sbill { 614*7701Ssam struct inode *ip; 615*7701Ssam struct a { 6166254Sroot char *fname; 6176254Sroot int uid; 6186254Sroot int gid; 61937Sbill } *uap; 62037Sbill 62137Sbill uap = (struct a *)u.u_ap; 6226254Sroot if (!suser() || (ip = owner(0)) == NULL) 62337Sbill return; 624*7701Ssam chown1(ip, uap->uid, uap->gid); 625*7701Ssam } 6267439Sroot 627*7701Ssam fchown() 628*7701Ssam { 629*7701Ssam struct a { 630*7701Ssam int fd; 631*7701Ssam int uid; 632*7701Ssam int gid; 633*7701Ssam } *uap; 634*7701Ssam register struct inode *ip; 635*7701Ssam register struct file *fp; 636*7701Ssam 637*7701Ssam uap = (struct a *)u.u_ap; 638*7701Ssam fp = getf(uap->fd); 639*7701Ssam if (fp == NULL) 640*7701Ssam return; 641*7701Ssam if (fp->f_type == DTYPE_SOCKET) { 642*7701Ssam u.u_error = EINVAL; 643*7701Ssam return; 6447439Sroot } 645*7701Ssam ip = fp->f_inode; 646*7701Ssam ilock(ip); 647*7701Ssam if (!suser()) { 648*7701Ssam iunlock(ip); 649*7701Ssam return; 650*7701Ssam } 651*7701Ssam chown1(ip, uap->uid, uap->gid); 652*7701Ssam } 653*7701Ssam 654*7701Ssam /* 655*7701Ssam * Perform chown operation on inode ip; 656*7701Ssam * inode must be locked prior to call. 657*7701Ssam */ 658*7701Ssam chown1(ip, uid, gid) 659*7701Ssam register struct inode *ip; 660*7701Ssam int uid, gid; 661*7701Ssam { 662*7701Ssam #ifdef QUOTA 663*7701Ssam register long change; 664*7701Ssam 6657439Sroot /* 6667482Skre * This doesn't allow for holes in files (which hopefully don't 6677482Skre * happen often in files that we chown), and is not accurate anyway 6687482Skre * (eg: it totally ignores 3 level indir blk files - but hopefully 6697482Skre * noone who can make a file that big will have a quota) 6707482Skre */ 671*7701Ssam if (ip->i_uid == uid) 6727482Skre change = 0; 6737482Skre else { 6747482Skre register struct fs *fs = ip->i_fs; 6757482Skre 6767482Skre if (ip->i_size > (change = NDADDR * fs->fs_bsize)) { 6777482Skre register off_t size; 6787482Skre 6797482Skre size = blkroundup(fs, ip->i_size) - change; 6807482Skre change += size; 6817482Skre change += fs->fs_bsize; 682*7701Ssam /* this assumes NIADDR <= 2 */ 6837482Skre if (size > NINDIR(fs) * fs->fs_bsize) 6847482Skre change += fs->fs_bsize; 6857482Skre } else 6867482Skre change = fragroundup(fs, ip->i_size); 6877482Skre change /= DEV_BSIZE; 6887482Skre } 6897482Skre chkdq(ip, -change, 1); 6907482Skre chkiq(ip->i_dev, ip, ip->i_uid, 1); 6917482Skre dqrele(ip->i_dquot); 6927482Skre #endif 6937482Skre /* 694*7701Ssam * keep uid/gid's in sane range -- no err, 695*7701Ssam * so chown(file, uid, -1) will do something useful 6967439Sroot */ 697*7701Ssam if (uid >= 0 && uid <= 32767) /* should have a constant */ 698*7701Ssam ip->i_uid = uid; 699*7701Ssam if (gid >= 0 && gid <= 32767) /* same here */ 700*7701Ssam ip->i_gid = gid; 7016254Sroot ip->i_flag |= ICHG; 7026254Sroot if (u.u_ruid != 0) 7036254Sroot ip->i_mode &= ~(ISUID|ISGID); 704*7701Ssam #ifdef QUOTA 7057482Skre ip->i_dquot = inoquota(ip); 7067482Skre chkdq(ip, change, 1); 707*7701Ssam chkiq(ip->i_dev, NULL, uid, 1); 7087482Skre #endif 7096254Sroot iput(ip); 71037Sbill } 71137Sbill 71237Sbill /* 7136254Sroot * Set IUPD and IACC times on file. 7146254Sroot * Can't set ICHG. 71537Sbill */ 7166254Sroot utime() 7174828Swnj { 71837Sbill register struct a { 7196254Sroot char *fname; 7206254Sroot time_t *tptr; 72137Sbill } *uap; 7226254Sroot register struct inode *ip; 7236254Sroot time_t tv[2]; 72437Sbill 72537Sbill uap = (struct a *)u.u_ap; 7266254Sroot if ((ip = owner(1)) == NULL) 72737Sbill return; 7286254Sroot if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { 7296254Sroot u.u_error = EFAULT; 7306254Sroot } else { 7316254Sroot ip->i_flag |= IACC|IUPD|ICHG; 7326254Sroot iupdat(ip, &tv[0], &tv[1], 0); 73337Sbill } 73437Sbill iput(ip); 73537Sbill } 73637Sbill 7376254Sroot sync() 73837Sbill { 73937Sbill 7405416Swnj update(0); 74137Sbill } 7427535Sroot 743*7701Ssam flock() 744*7701Ssam { 745*7701Ssam struct a { 746*7701Ssam int fd; 747*7701Ssam int how; 748*7701Ssam } *uap; 749*7701Ssam register struct file *fp; 750*7701Ssam register int cmd, flags; 751*7701Ssam 752*7701Ssam uap = (struct a *)u.u_ap; 753*7701Ssam fp = getf(uap->fd); 754*7701Ssam if (fp == NULL) 755*7701Ssam return; 756*7701Ssam if (fp->f_type == DTYPE_SOCKET) { /* XXX */ 757*7701Ssam u.u_error = EINVAL; 758*7701Ssam return; 759*7701Ssam } 760*7701Ssam cmd = uap->how; 761*7701Ssam flags = u.u_pofile[uap->fd] & (RDLOCK|WRLOCK); 762*7701Ssam if (cmd&FUNLOCK) { 763*7701Ssam if (flags == 0) { 764*7701Ssam u.u_error = EINVAL; 765*7701Ssam return; 766*7701Ssam } 767*7701Ssam funlocki(fp->f_inode, flags); 768*7701Ssam u.u_pofile[uap->fd] &= ~(RDLOCK|WRLOCK); 769*7701Ssam return; 770*7701Ssam } 771*7701Ssam /* 772*7701Ssam * No reason to write lock a file we've already 773*7701Ssam * write locked, similarly with a read lock. 774*7701Ssam */ 775*7701Ssam if ((flags&WRLOCK) && (cmd&FWRLOCK) || 776*7701Ssam (flags&RDLOCK) && (cmd&FRDLOCK)) 777*7701Ssam return; 778*7701Ssam u.u_pofile[uap->fd] = flocki(fp->f_inode, u.u_pofile[uap->fd], cmd); 779*7701Ssam } 780*7701Ssam 781*7701Ssam truncate() 782*7701Ssam { 783*7701Ssam struct a { 784*7701Ssam char *fname; 785*7701Ssam int length; 786*7701Ssam } *uap; 787*7701Ssam struct inode *ip; 788*7701Ssam 789*7701Ssam ip = namei(uchar, 0, 1); 790*7701Ssam if (ip == NULL) 791*7701Ssam return; 792*7701Ssam if (access(ip, IWRITE)) 793*7701Ssam goto bad; 794*7701Ssam if ((ip->i_mode&IFMT) == IFDIR) { 795*7701Ssam u.u_error = EISDIR; 796*7701Ssam goto bad; 797*7701Ssam } 798*7701Ssam itrunc(ip, uap->length); 799*7701Ssam return; 800*7701Ssam bad: 801*7701Ssam iput(ip); 802*7701Ssam } 803*7701Ssam 804*7701Ssam ftruncate() 805*7701Ssam { 806*7701Ssam struct a { 807*7701Ssam int fd; 808*7701Ssam int length; 809*7701Ssam } *uap; 810*7701Ssam struct inode *ip; 811*7701Ssam struct file *fp; 812*7701Ssam 813*7701Ssam fp = getf(uap->fd); 814*7701Ssam if (fp == NULL) 815*7701Ssam return; 816*7701Ssam if (fp->f_type == DTYPE_SOCKET) { 817*7701Ssam u.u_error = EINVAL; 818*7701Ssam return; 819*7701Ssam } 820*7701Ssam if ((fp->f_flag&FWRITE) == 0) { 821*7701Ssam u.u_error = EINVAL; 822*7701Ssam return; 823*7701Ssam } 824*7701Ssam ip = fp->f_inode; 825*7701Ssam ilock(ip); 826*7701Ssam itrunc(ip, uap->length); 827*7701Ssam } 828*7701Ssam 829*7701Ssam rename() 830*7701Ssam { 831*7701Ssam struct a { 832*7701Ssam char *from; 833*7701Ssam char *to; 834*7701Ssam } *uap; 835*7701Ssam 836*7701Ssam } 837*7701Ssam 8387535Sroot /* 8397535Sroot * Make a new file. 8407535Sroot */ 8417535Sroot struct inode * 8427535Sroot maknode(mode) 8437535Sroot int mode; 8447535Sroot { 8457535Sroot register struct inode *ip; 8467535Sroot ino_t ipref; 8477535Sroot 8487535Sroot if ((mode & IFMT) == IFDIR) 8497535Sroot ipref = dirpref(u.u_pdir->i_fs); 8507535Sroot else 8517535Sroot ipref = u.u_pdir->i_number; 8527535Sroot ip = ialloc(u.u_pdir, ipref, mode); 8537535Sroot if (ip == NULL) { 8547535Sroot iput(u.u_pdir); 855*7701Ssam return (NULL); 8567535Sroot } 857*7701Ssam #ifdef QUOTA 8587535Sroot if (ip->i_dquot != NODQUOT) 8597535Sroot panic("maknode: dquot"); 8607535Sroot #endif 8617535Sroot ip->i_flag |= IACC|IUPD|ICHG; 8627535Sroot if ((mode & IFMT) == 0) 8637535Sroot mode |= IFREG; 8647535Sroot ip->i_mode = mode & ~u.u_cmask; 8657535Sroot ip->i_nlink = 1; 8667535Sroot ip->i_uid = u.u_uid; 8677535Sroot ip->i_gid = u.u_pdir->i_gid; 868*7701Ssam #ifdef QUOTA 8697535Sroot ip->i_dquot = inoquota(ip); 8707535Sroot #endif 8717535Sroot 8727535Sroot /* 8737535Sroot * Make sure inode goes to disk before directory entry. 8747535Sroot */ 8757535Sroot iupdat(ip, &time, &time, 1); 8767535Sroot direnter(ip); 8777535Sroot if (u.u_error) { 8787535Sroot /* 8797535Sroot * write error occurred trying to update directory 8807535Sroot * so must deallocate the inode 8817535Sroot */ 8827535Sroot ip->i_nlink = 0; 8837535Sroot ip->i_flag |= ICHG; 8847535Sroot iput(ip); 885*7701Ssam return (NULL); 8867535Sroot } 887*7701Ssam return (ip); 8887535Sroot } 889