1*7868Sroot /* vfs_syscalls.c 4.35 82/08/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" 147701Ssam /* no reason to inline expand these guys here */ 157701Ssam #undef ilock 167701Ssam #undef iunlock 177482Skre #include "../h/quota.h" 187505Sroot #include "../h/descrip.h" 197826Sroot #include "../h/uio.h" 207826Sroot #include "../h/socket.h" 2137Sbill 226254Sroot chdir() 236254Sroot { 246254Sroot 256254Sroot chdirec(&u.u_cdir); 266254Sroot } 276254Sroot 286254Sroot chroot() 296254Sroot { 306254Sroot 316254Sroot if (suser()) 326254Sroot chdirec(&u.u_rdir); 336254Sroot } 346254Sroot 356254Sroot chdirec(ipp) 367701Ssam register struct inode **ipp; 376254Sroot { 386254Sroot register struct inode *ip; 396254Sroot struct a { 406254Sroot char *fname; 416254Sroot }; 426254Sroot 436254Sroot ip = namei(uchar, 0, 1); 446254Sroot if(ip == NULL) 456254Sroot return; 466254Sroot if((ip->i_mode&IFMT) != IFDIR) { 476254Sroot u.u_error = ENOTDIR; 486254Sroot goto bad; 496254Sroot } 506254Sroot if(access(ip, IEXEC)) 516254Sroot goto bad; 527122Smckusick iunlock(ip); 537142Smckusick if (*ipp) 547142Smckusick irele(*ipp); 556254Sroot *ipp = ip; 566254Sroot return; 576254Sroot 586254Sroot bad: 596254Sroot iput(ip); 606254Sroot } 616254Sroot 6237Sbill /* 636254Sroot * Open system call. 646254Sroot */ 656254Sroot open() 666254Sroot { 676254Sroot register struct inode *ip; 686254Sroot register struct a { 696254Sroot char *fname; 707701Ssam int flags; 717701Ssam int mode; 726254Sroot } *uap; 737701Ssam int checkpermissions = 1; 746254Sroot 756254Sroot uap = (struct a *)u.u_ap; 767701Ssam if (uap->flags&FCREATE) { 777701Ssam ip = namei(uchar, 1, 1); 787701Ssam if (ip == NULL) { 797701Ssam if (u.u_error) 807701Ssam return; 817701Ssam ip = maknode(uap->mode&07777&(~ISVTX)); 827701Ssam checkpermissions = 0; 837701Ssam uap->flags &= ~FTRUNCATE; 847701Ssam } 857701Ssam } else 867701Ssam ip = namei(uchar, 0, 1); 876254Sroot if (ip == NULL) 886254Sroot return; 897701Ssam open1(ip, ++uap->flags, checkpermissions); 906254Sroot } 916254Sroot 927701Ssam #ifndef NOCOMPAT 936254Sroot /* 946254Sroot * Creat system call. 956254Sroot */ 967505Sroot ocreat() 976254Sroot { 986254Sroot register struct inode *ip; 996254Sroot register struct a { 1006254Sroot char *fname; 1016254Sroot int fmode; 1026254Sroot } *uap; 1036254Sroot 1046254Sroot uap = (struct a *)u.u_ap; 1056254Sroot ip = namei(uchar, 1, 1); 1066254Sroot if (ip == NULL) { 1076254Sroot if (u.u_error) 1086254Sroot return; 1096254Sroot ip = maknode(uap->fmode&07777&(~ISVTX)); 1107701Ssam if (ip == NULL) 1116254Sroot return; 1127701Ssam open1(ip, FWRITE, 0); 1136254Sroot } else 1147701Ssam open1(ip, FWRITE|FTRUNCATE, 0); 1156254Sroot } 1167701Ssam #endif 1176254Sroot 1186254Sroot /* 1196254Sroot * Common code for open and creat. 1207701Ssam * Check permissions (if we haven't done so already), 1217701Ssam * allocate an open file structure, and call 1227701Ssam * the device open routine, if any. 1236254Sroot */ 1247701Ssam open1(ip, mode, checkpermissions) 1256254Sroot register struct inode *ip; 1266254Sroot register mode; 1276254Sroot { 1286254Sroot register struct file *fp; 1297701Ssam int i, flags; 1306254Sroot 1317701Ssam if (checkpermissions) { 1326254Sroot if (mode&FREAD) 1337701Ssam if (access(ip, IREAD)) 1347701Ssam goto bad; 1356254Sroot if (mode&FWRITE) { 1367701Ssam if (access(ip, IWRITE)) 1377701Ssam goto bad; 1387701Ssam if ((ip->i_mode&IFMT) == IFDIR) { 1396254Sroot u.u_error = EISDIR; 1407701Ssam goto bad; 1417701Ssam } 1426254Sroot } 1436254Sroot } 1447701Ssam 1457701Ssam /* 1467701Ssam * Check locking on inode. Release "inode lock" 1477701Ssam * while doing so in case we block inside flocki. 1487701Ssam */ 1497701Ssam flags = 0; 1507701Ssam if (mode&(FRDLOCK|FWRLOCK)) { 1517701Ssam iunlock(ip); 1527701Ssam flags = flocki(ip, 0, mode); 1537701Ssam ilock(ip); 1547701Ssam if (u.u_error) 1557701Ssam goto bad; 1567142Smckusick } 1577701Ssam if (mode&FTRUNCATE) 1587701Ssam itrunc(ip, 0); 1597122Smckusick iunlock(ip); 1606254Sroot if ((fp = falloc()) == NULL) 1616254Sroot goto out; 1627701Ssam fp->f_flag = mode & FMODES; 1637505Sroot fp->f_type = DTYPE_FILE; 1646254Sroot i = u.u_r.r_val1; 1656254Sroot fp->f_inode = ip; 1667701Ssam openi(ip, mode); 1677701Ssam if (u.u_error == 0) { 1687701Ssam u.u_pofile[i] = flags; 1696254Sroot return; 1707701Ssam } 1716254Sroot u.u_ofile[i] = NULL; 1726254Sroot fp->f_count--; 1736254Sroot out: 1747142Smckusick irele(ip); 1757701Ssam return; 1767701Ssam bad: 1777701Ssam iput(ip); 1786254Sroot } 1796254Sroot 1806254Sroot /* 1816254Sroot * Mknod system call 1826254Sroot */ 1836254Sroot mknod() 1846254Sroot { 1856254Sroot register struct inode *ip; 1866254Sroot register struct a { 1876254Sroot char *fname; 1886254Sroot int fmode; 1896254Sroot int dev; 1906254Sroot } *uap; 1916254Sroot 1926254Sroot uap = (struct a *)u.u_ap; 1936254Sroot if (suser()) { 1946254Sroot ip = namei(uchar, 1, 0); 1956254Sroot if (ip != NULL) { 1966254Sroot u.u_error = EEXIST; 1976254Sroot goto out; 1986254Sroot } 1996254Sroot } 2006254Sroot if (u.u_error) 2016254Sroot return; 2026254Sroot ip = maknode(uap->fmode); 2036254Sroot if (ip == NULL) 2046254Sroot return; 2056254Sroot if (uap->dev) { 2066254Sroot /* 2076254Sroot * Want to be able to use this to make badblock 2086254Sroot * inodes, so don't truncate the dev number. 2096254Sroot */ 2106574Smckusic ip->i_rdev = uap->dev; 2116254Sroot ip->i_flag |= IACC|IUPD|ICHG; 2126254Sroot } 2136254Sroot 2146254Sroot out: 2156254Sroot iput(ip); 2166254Sroot } 2176254Sroot 2186254Sroot /* 2196254Sroot * link system call 2206254Sroot */ 2216254Sroot link() 2226254Sroot { 2236254Sroot register struct inode *ip, *xp; 2246254Sroot register struct a { 2256254Sroot char *target; 2266254Sroot char *linkname; 2276254Sroot } *uap; 2286254Sroot 2296254Sroot uap = (struct a *)u.u_ap; 2306254Sroot ip = namei(uchar, 0, 1); /* well, this routine is doomed anyhow */ 2316254Sroot if (ip == NULL) 2326254Sroot return; 2337439Sroot if ((ip->i_mode&IFMT)==IFDIR && !suser()) { 2347439Sroot iput(ip); 2357439Sroot return; 2367439Sroot } 2376254Sroot ip->i_nlink++; 2386254Sroot ip->i_flag |= ICHG; 2396254Sroot iupdat(ip, &time, &time, 1); 2407122Smckusick iunlock(ip); 2416254Sroot u.u_dirp = (caddr_t)uap->linkname; 2426254Sroot xp = namei(uchar, 1, 0); 2436254Sroot if (xp != NULL) { 2446254Sroot u.u_error = EEXIST; 2456254Sroot iput(xp); 2466254Sroot goto out; 2476254Sroot } 2486254Sroot if (u.u_error) 2496254Sroot goto out; 2506254Sroot if (u.u_pdir->i_dev != ip->i_dev) { 2516254Sroot iput(u.u_pdir); 2526254Sroot u.u_error = EXDEV; 2536254Sroot goto out; 2546254Sroot } 2557535Sroot direnter(ip); 2566254Sroot out: 2576254Sroot if (u.u_error) { 2586254Sroot ip->i_nlink--; 2596254Sroot ip->i_flag |= ICHG; 2606254Sroot } 2617142Smckusick irele(ip); 2626254Sroot } 2636254Sroot 2646254Sroot /* 2656254Sroot * symlink -- make a symbolic link 2666254Sroot */ 2676254Sroot symlink() 2686254Sroot { 2696254Sroot register struct a { 2706254Sroot char *target; 2716254Sroot char *linkname; 2726254Sroot } *uap; 2736254Sroot register struct inode *ip; 2746254Sroot register char *tp; 2756254Sroot register c, nc; 2766254Sroot 2776254Sroot uap = (struct a *)u.u_ap; 2786254Sroot tp = uap->target; 2796254Sroot nc = 0; 2806254Sroot while (c = fubyte(tp)) { 2816254Sroot if (c < 0) { 2826254Sroot u.u_error = EFAULT; 2836254Sroot return; 2846254Sroot } 2856254Sroot tp++; 2866254Sroot nc++; 2876254Sroot } 2886254Sroot u.u_dirp = uap->linkname; 2896254Sroot ip = namei(uchar, 1, 0); 2906254Sroot if (ip) { 2916254Sroot iput(ip); 2926254Sroot u.u_error = EEXIST; 2936254Sroot return; 2946254Sroot } 2956254Sroot if (u.u_error) 2966254Sroot return; 2976254Sroot ip = maknode(IFLNK | 0777); 2986254Sroot if (ip == NULL) 2996254Sroot return; 3007826Sroot u.u_error = rdwri(UIO_WRITE, ip, uap->target, nc, 0, 0, (int *)0); 3016254Sroot iput(ip); 3026254Sroot } 3036254Sroot 3046254Sroot /* 3056254Sroot * Unlink system call. 3066254Sroot * Hard to avoid races here, especially 3076254Sroot * in unlinking directories. 3086254Sroot */ 3096254Sroot unlink() 3106254Sroot { 3116254Sroot register struct inode *ip, *pp; 3126254Sroot struct a { 3136254Sroot char *fname; 3146254Sroot }; 3157142Smckusick int unlinkingdot = 0; 3166254Sroot 3176254Sroot pp = namei(uchar, 2, 0); 3187535Sroot if (pp == NULL) 3196254Sroot return; 3207439Sroot 3216254Sroot /* 3226254Sroot * Check for unlink(".") 3236254Sroot * to avoid hanging on the iget 3246254Sroot */ 3256254Sroot if (pp->i_number == u.u_dent.d_ino) { 3266254Sroot ip = pp; 3276254Sroot ip->i_count++; 3287142Smckusick unlinkingdot++; 3296254Sroot } else 3306574Smckusic ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino); 3316254Sroot if(ip == NULL) 3326254Sroot goto out1; 3336254Sroot if((ip->i_mode&IFMT)==IFDIR && !suser()) 3346254Sroot goto out; 3356254Sroot /* 3366254Sroot * Don't unlink a mounted file. 3376254Sroot */ 3386254Sroot if (ip->i_dev != pp->i_dev) { 3396254Sroot u.u_error = EBUSY; 3406254Sroot goto out; 3416254Sroot } 3426254Sroot if (ip->i_flag&ITEXT) 3436254Sroot xrele(ip); /* try once to free text */ 3447535Sroot if (dirremove()) { 3457535Sroot ip->i_nlink--; 3467535Sroot ip->i_flag |= ICHG; 3476254Sroot } 3486254Sroot out: 3497142Smckusick if (unlinkingdot) 3507142Smckusick irele(ip); 3517142Smckusick else 3527142Smckusick iput(ip); 3536254Sroot out1: 3546254Sroot iput(pp); 3556254Sroot } 3566254Sroot 3576254Sroot /* 3586254Sroot * Seek system call 3596254Sroot */ 3606254Sroot seek() 3616254Sroot { 3626254Sroot register struct file *fp; 3636254Sroot register struct a { 3647701Ssam int fd; 3656254Sroot off_t off; 3666254Sroot int sbase; 3676254Sroot } *uap; 3686254Sroot 3696254Sroot uap = (struct a *)u.u_ap; 3707701Ssam fp = getf(uap->fd); 3716254Sroot if (fp == NULL) 3726254Sroot return; 3737505Sroot if (fp->f_type == DTYPE_SOCKET) { 3746254Sroot u.u_error = ESPIPE; 3756254Sroot return; 3766254Sroot } 3777701Ssam if (uap->sbase == FSEEK_RELATIVE) 3786254Sroot uap->off += fp->f_offset; 3797701Ssam else if (uap->sbase == FSEEK_EOF) 3806254Sroot uap->off += fp->f_inode->i_size; 3816254Sroot fp->f_offset = uap->off; 3826254Sroot u.u_r.r_off = uap->off; 3836254Sroot } 3846254Sroot 3856254Sroot /* 3866254Sroot * Access system call 3876254Sroot */ 3886254Sroot saccess() 3896254Sroot { 3906254Sroot register svuid, svgid; 3916254Sroot register struct inode *ip; 3926254Sroot register struct a { 3936254Sroot char *fname; 3946254Sroot int fmode; 3956254Sroot } *uap; 3966254Sroot 3976254Sroot uap = (struct a *)u.u_ap; 3986254Sroot svuid = u.u_uid; 3996254Sroot svgid = u.u_gid; 4006254Sroot u.u_uid = u.u_ruid; 4016254Sroot u.u_gid = u.u_rgid; 4026254Sroot ip = namei(uchar, 0, 1); 4036254Sroot if (ip != NULL) { 4047701Ssam if (uap->fmode&FACCESS_READ && access(ip, IREAD)) 4057701Ssam goto done; 4067701Ssam if (uap->fmode&FACCESS_WRITE && access(ip, IWRITE)) 4077701Ssam goto done; 4087701Ssam if (uap->fmode&FACCESS_EXECUTE && access(ip, IEXEC)) 4097701Ssam goto done; 4107701Ssam done: 4116254Sroot iput(ip); 4126254Sroot } 4136254Sroot u.u_uid = svuid; 4146254Sroot u.u_gid = svgid; 4156254Sroot } 4166254Sroot 4176254Sroot /* 41837Sbill * the fstat system call. 41937Sbill */ 42037Sbill fstat() 42137Sbill { 42237Sbill register struct file *fp; 42337Sbill register struct a { 4247701Ssam int fd; 42537Sbill struct stat *sb; 42637Sbill } *uap; 42737Sbill 42837Sbill uap = (struct a *)u.u_ap; 4297701Ssam fp = getf(uap->fd); 4304828Swnj if (fp == NULL) 43137Sbill return; 4327505Sroot if (fp->f_type == DTYPE_SOCKET) 4334891Swnj u.u_error = sostat(fp->f_socket, uap->sb); 4344828Swnj else 4354828Swnj stat1(fp->f_inode, uap->sb); 43637Sbill } 43737Sbill 43837Sbill /* 4396574Smckusic * Stat system call. This version follows links. 44037Sbill */ 44137Sbill stat() 44237Sbill { 44337Sbill register struct inode *ip; 44437Sbill register struct a { 44537Sbill char *fname; 44637Sbill struct stat *sb; 44737Sbill } *uap; 44837Sbill 44937Sbill uap = (struct a *)u.u_ap; 4506423Sroot ip = namei(uchar, 0, 1); 4514828Swnj if (ip == NULL) 45237Sbill return; 4533624Sroot stat1(ip, uap->sb); 45437Sbill iput(ip); 45537Sbill } 45637Sbill 45737Sbill /* 4586574Smckusic * Lstat system call. This version does not follow links. 4595992Swnj */ 4605992Swnj lstat() 4615992Swnj { 4625992Swnj register struct inode *ip; 4635992Swnj register struct a { 4645992Swnj char *fname; 4655992Swnj struct stat *sb; 4665992Swnj } *uap; 4675992Swnj 4685992Swnj uap = (struct a *)u.u_ap; 4696423Sroot ip = namei(uchar, 0, 0); 4705992Swnj if (ip == NULL) 4715992Swnj return; 4726153Ssam stat1(ip, uap->sb); 4735992Swnj iput(ip); 4745992Swnj } 4755992Swnj 4765992Swnj /* 47737Sbill * The basic routine for fstat and stat: 47837Sbill * get the inode and pass appropriate parts back. 47937Sbill */ 4803624Sroot stat1(ip, ub) 4814828Swnj register struct inode *ip; 4824828Swnj struct stat *ub; 48337Sbill { 48437Sbill struct stat ds; 48537Sbill 4861204Sbill IUPDAT(ip, &time, &time, 0); 48737Sbill /* 4887023Smckusick * Copy from inode table 48937Sbill */ 49037Sbill ds.st_dev = ip->i_dev; 49137Sbill ds.st_ino = ip->i_number; 49237Sbill ds.st_mode = ip->i_mode; 49337Sbill ds.st_nlink = ip->i_nlink; 49437Sbill ds.st_uid = ip->i_uid; 49537Sbill ds.st_gid = ip->i_gid; 4966574Smckusic ds.st_rdev = (dev_t)ip->i_rdev; 4973624Sroot ds.st_size = ip->i_size; 4986574Smckusic ds.st_atime = ip->i_atime; 4996574Smckusic ds.st_mtime = ip->i_mtime; 5006574Smckusic ds.st_ctime = ip->i_ctime; 5017701Ssam /* this doesn't belong here */ 5027701Ssam if ((ip->i_mode&IFMT) == IFBLK) 5037701Ssam ds.st_blksize = BLKDEV_IOSIZE; 5047701Ssam else if ((ip->i_mode&IFMT) == IFCHR) 5057701Ssam ds.st_blksize = MAXBSIZE; 5067701Ssam else 5077701Ssam ds.st_blksize = ip->i_fs->fs_bsize; 50837Sbill if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 50937Sbill u.u_error = EFAULT; 51037Sbill } 51137Sbill 51237Sbill /* 5135992Swnj * Return target name of a symbolic link 51437Sbill */ 5155992Swnj readlink() 5165992Swnj { 5175992Swnj register struct inode *ip; 5185992Swnj register struct a { 5195992Swnj char *name; 5205992Swnj char *buf; 5215992Swnj int count; 5227826Sroot } *uap = (struct a *)u.u_ap; 5237826Sroot int resid; 5245992Swnj 5255992Swnj ip = namei(uchar, 0, 0); 5265992Swnj if (ip == NULL) 5275992Swnj return; 5285992Swnj if ((ip->i_mode&IFMT) != IFLNK) { 5295992Swnj u.u_error = ENXIO; 5305992Swnj goto out; 5315992Swnj } 5327826Sroot u.u_error = rdwri(UIO_READ, ip, uap->buf, uap->count, 0, 0, &resid); 5335992Swnj out: 5345992Swnj iput(ip); 5357826Sroot u.u_r.r_val1 = uap->count - resid; 5365992Swnj } 5375992Swnj 5386254Sroot chmod() 5395992Swnj { 5407701Ssam struct inode *ip; 5417701Ssam struct a { 5426254Sroot char *fname; 5436254Sroot int fmode; 5445992Swnj } *uap; 5455992Swnj 5465992Swnj uap = (struct a *)u.u_ap; 5476254Sroot if ((ip = owner(1)) == NULL) 5485992Swnj return; 5497701Ssam chmod1(ip, uap->fmode); 5507701Ssam } 5517439Sroot 5527701Ssam fchmod() 5537701Ssam { 5547701Ssam struct a { 5557701Ssam int fd; 5567701Ssam int fmode; 5577701Ssam } *uap; 5587701Ssam register struct inode *ip; 5597701Ssam register struct file *fp; 5607701Ssam 5617701Ssam uap = (struct a *)u.u_ap; 5627701Ssam fp = getf(uap->fd); 5637701Ssam if (fp == NULL) 5647701Ssam return; 5657701Ssam if (fp->f_type == DTYPE_SOCKET) { 5667701Ssam u.u_error = EINVAL; 5677701Ssam return; 5687439Sroot } 5697701Ssam ip = fp->f_inode; 5707701Ssam ilock(ip); 5717701Ssam if (u.u_uid != ip->i_uid && !suser()) { 5727701Ssam iunlock(ip); 5737701Ssam return; 5747701Ssam } 5757701Ssam chmod1(ip, uap->fmode); 5767701Ssam } 5777701Ssam 5787701Ssam chmod1(ip, mode) 5797701Ssam register struct inode *ip; 5807701Ssam register int mode; 5817701Ssam { 582*7868Sroot register int *gp; 583*7868Sroot 5846254Sroot ip->i_mode &= ~07777; 5857439Sroot if (u.u_uid) { 5867701Ssam mode &= ~ISVTX; 587*7868Sroot for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++) 588*7868Sroot if (*gp == ip->i_gid) 589*7868Sroot goto ok; 590*7868Sroot mode &= ~ISGID; 591*7868Sroot ok: 592*7868Sroot ; 5937701Ssam #ifdef MUSH 5947482Skre if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 && 5957482Skre (ip->i_mode & IFMT) != IFCHR) 5967701Ssam mode &= ~u.u_cmask; 5977482Skre #endif 5987439Sroot } 5997701Ssam ip->i_mode |= mode&07777; 6006254Sroot ip->i_flag |= ICHG; 6016254Sroot if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 6026254Sroot xrele(ip); 6035992Swnj iput(ip); 6045992Swnj } 6055992Swnj 6066254Sroot chown() 60737Sbill { 6087701Ssam struct inode *ip; 6097701Ssam struct a { 6106254Sroot char *fname; 6116254Sroot int uid; 6126254Sroot int gid; 61337Sbill } *uap; 61437Sbill 61537Sbill uap = (struct a *)u.u_ap; 6166254Sroot if (!suser() || (ip = owner(0)) == NULL) 61737Sbill return; 6187701Ssam chown1(ip, uap->uid, uap->gid); 6197701Ssam } 6207439Sroot 6217701Ssam fchown() 6227701Ssam { 6237701Ssam struct a { 6247701Ssam int fd; 6257701Ssam int uid; 6267701Ssam int gid; 6277701Ssam } *uap; 6287701Ssam register struct inode *ip; 6297701Ssam register struct file *fp; 6307701Ssam 6317701Ssam uap = (struct a *)u.u_ap; 6327701Ssam fp = getf(uap->fd); 6337701Ssam if (fp == NULL) 6347701Ssam return; 6357701Ssam if (fp->f_type == DTYPE_SOCKET) { 6367701Ssam u.u_error = EINVAL; 6377701Ssam return; 6387439Sroot } 6397701Ssam ip = fp->f_inode; 6407701Ssam ilock(ip); 6417701Ssam if (!suser()) { 6427701Ssam iunlock(ip); 6437701Ssam return; 6447701Ssam } 6457701Ssam chown1(ip, uap->uid, uap->gid); 6467701Ssam } 6477701Ssam 6487701Ssam /* 6497701Ssam * Perform chown operation on inode ip; 6507701Ssam * inode must be locked prior to call. 6517701Ssam */ 6527701Ssam chown1(ip, uid, gid) 6537701Ssam register struct inode *ip; 6547701Ssam int uid, gid; 6557701Ssam { 6567701Ssam #ifdef QUOTA 6577701Ssam register long change; 6587701Ssam 6597439Sroot /* 6607482Skre * This doesn't allow for holes in files (which hopefully don't 6617482Skre * happen often in files that we chown), and is not accurate anyway 6627482Skre * (eg: it totally ignores 3 level indir blk files - but hopefully 6637482Skre * noone who can make a file that big will have a quota) 6647482Skre */ 6657701Ssam if (ip->i_uid == uid) 6667482Skre change = 0; 6677482Skre else { 6687482Skre register struct fs *fs = ip->i_fs; 6697482Skre 6707482Skre if (ip->i_size > (change = NDADDR * fs->fs_bsize)) { 6717482Skre register off_t size; 6727482Skre 6737482Skre size = blkroundup(fs, ip->i_size) - change; 6747482Skre change += size; 6757482Skre change += fs->fs_bsize; 6767701Ssam /* this assumes NIADDR <= 2 */ 6777482Skre if (size > NINDIR(fs) * fs->fs_bsize) 6787482Skre change += fs->fs_bsize; 6797482Skre } else 6807482Skre change = fragroundup(fs, ip->i_size); 6817482Skre change /= DEV_BSIZE; 6827482Skre } 6837482Skre chkdq(ip, -change, 1); 6847482Skre chkiq(ip->i_dev, ip, ip->i_uid, 1); 6857482Skre dqrele(ip->i_dquot); 6867482Skre #endif 6877482Skre /* 6887701Ssam * keep uid/gid's in sane range -- no err, 6897701Ssam * so chown(file, uid, -1) will do something useful 6907439Sroot */ 6917701Ssam if (uid >= 0 && uid <= 32767) /* should have a constant */ 6927701Ssam ip->i_uid = uid; 6937701Ssam if (gid >= 0 && gid <= 32767) /* same here */ 6947701Ssam ip->i_gid = gid; 6956254Sroot ip->i_flag |= ICHG; 6966254Sroot if (u.u_ruid != 0) 6976254Sroot ip->i_mode &= ~(ISUID|ISGID); 6987701Ssam #ifdef QUOTA 6997482Skre ip->i_dquot = inoquota(ip); 7007482Skre chkdq(ip, change, 1); 7017701Ssam chkiq(ip->i_dev, NULL, uid, 1); 7027482Skre #endif 7036254Sroot iput(ip); 70437Sbill } 70537Sbill 70637Sbill /* 7076254Sroot * Set IUPD and IACC times on file. 7086254Sroot * Can't set ICHG. 70937Sbill */ 7106254Sroot utime() 7114828Swnj { 71237Sbill register struct a { 7136254Sroot char *fname; 7146254Sroot time_t *tptr; 71537Sbill } *uap; 7166254Sroot register struct inode *ip; 7176254Sroot time_t tv[2]; 71837Sbill 71937Sbill uap = (struct a *)u.u_ap; 7206254Sroot if ((ip = owner(1)) == NULL) 72137Sbill return; 7226254Sroot if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { 7236254Sroot u.u_error = EFAULT; 7246254Sroot } else { 7256254Sroot ip->i_flag |= IACC|IUPD|ICHG; 7266254Sroot iupdat(ip, &tv[0], &tv[1], 0); 72737Sbill } 72837Sbill iput(ip); 72937Sbill } 73037Sbill 7316254Sroot sync() 73237Sbill { 73337Sbill 7345416Swnj update(0); 73537Sbill } 7367535Sroot 7377701Ssam flock() 7387701Ssam { 7397701Ssam struct a { 7407701Ssam int fd; 7417701Ssam int how; 7427701Ssam } *uap; 7437701Ssam register struct file *fp; 7447701Ssam register int cmd, flags; 7457701Ssam 7467701Ssam uap = (struct a *)u.u_ap; 7477701Ssam fp = getf(uap->fd); 7487701Ssam if (fp == NULL) 7497701Ssam return; 7507701Ssam if (fp->f_type == DTYPE_SOCKET) { /* XXX */ 7517701Ssam u.u_error = EINVAL; 7527701Ssam return; 7537701Ssam } 7547701Ssam cmd = uap->how; 7557701Ssam flags = u.u_pofile[uap->fd] & (RDLOCK|WRLOCK); 7567701Ssam if (cmd&FUNLOCK) { 7577701Ssam if (flags == 0) { 7587701Ssam u.u_error = EINVAL; 7597701Ssam return; 7607701Ssam } 7617701Ssam funlocki(fp->f_inode, flags); 7627701Ssam u.u_pofile[uap->fd] &= ~(RDLOCK|WRLOCK); 7637701Ssam return; 7647701Ssam } 7657701Ssam /* 7667701Ssam * No reason to write lock a file we've already 7677701Ssam * write locked, similarly with a read lock. 7687701Ssam */ 7697701Ssam if ((flags&WRLOCK) && (cmd&FWRLOCK) || 7707701Ssam (flags&RDLOCK) && (cmd&FRDLOCK)) 7717701Ssam return; 7727701Ssam u.u_pofile[uap->fd] = flocki(fp->f_inode, u.u_pofile[uap->fd], cmd); 7737701Ssam } 7747701Ssam 7757701Ssam truncate() 7767701Ssam { 7777701Ssam struct a { 7787701Ssam char *fname; 7797701Ssam int length; 7807826Sroot } *uap = (struct a *)u.u_ap; 7817701Ssam struct inode *ip; 7827701Ssam 7837701Ssam ip = namei(uchar, 0, 1); 7847701Ssam if (ip == NULL) 7857701Ssam return; 7867701Ssam if (access(ip, IWRITE)) 7877701Ssam goto bad; 7887701Ssam if ((ip->i_mode&IFMT) == IFDIR) { 7897701Ssam u.u_error = EISDIR; 7907701Ssam goto bad; 7917701Ssam } 7927701Ssam itrunc(ip, uap->length); 7937701Ssam return; 7947701Ssam bad: 7957701Ssam iput(ip); 7967701Ssam } 7977701Ssam 7987701Ssam ftruncate() 7997701Ssam { 8007701Ssam struct a { 8017701Ssam int fd; 8027701Ssam int length; 8037826Sroot } *uap = (struct a *)u.u_ap; 8047701Ssam struct inode *ip; 8057701Ssam struct file *fp; 8067701Ssam 8077701Ssam fp = getf(uap->fd); 8087701Ssam if (fp == NULL) 8097701Ssam return; 8107701Ssam if (fp->f_type == DTYPE_SOCKET) { 8117701Ssam u.u_error = EINVAL; 8127701Ssam return; 8137701Ssam } 8147701Ssam if ((fp->f_flag&FWRITE) == 0) { 8157701Ssam u.u_error = EINVAL; 8167701Ssam return; 8177701Ssam } 8187701Ssam ip = fp->f_inode; 8197701Ssam ilock(ip); 8207701Ssam itrunc(ip, uap->length); 8217701Ssam } 8227701Ssam 8237701Ssam rename() 8247701Ssam { 8257826Sroot #ifdef notdef 8267701Ssam struct a { 8277701Ssam char *from; 8287701Ssam char *to; 8297701Ssam } *uap; 8307826Sroot #endif 8317701Ssam 8327701Ssam } 8337701Ssam 8347535Sroot /* 8357535Sroot * Make a new file. 8367535Sroot */ 8377535Sroot struct inode * 8387535Sroot maknode(mode) 8397535Sroot int mode; 8407535Sroot { 8417535Sroot register struct inode *ip; 8427535Sroot ino_t ipref; 8437535Sroot 8447535Sroot if ((mode & IFMT) == IFDIR) 8457535Sroot ipref = dirpref(u.u_pdir->i_fs); 8467535Sroot else 8477535Sroot ipref = u.u_pdir->i_number; 8487535Sroot ip = ialloc(u.u_pdir, ipref, mode); 8497535Sroot if (ip == NULL) { 8507535Sroot iput(u.u_pdir); 8517701Ssam return (NULL); 8527535Sroot } 8537701Ssam #ifdef QUOTA 8547535Sroot if (ip->i_dquot != NODQUOT) 8557535Sroot panic("maknode: dquot"); 8567535Sroot #endif 8577535Sroot ip->i_flag |= IACC|IUPD|ICHG; 8587535Sroot if ((mode & IFMT) == 0) 8597535Sroot mode |= IFREG; 8607535Sroot ip->i_mode = mode & ~u.u_cmask; 8617535Sroot ip->i_nlink = 1; 8627535Sroot ip->i_uid = u.u_uid; 8637535Sroot ip->i_gid = u.u_pdir->i_gid; 8647701Ssam #ifdef QUOTA 8657535Sroot ip->i_dquot = inoquota(ip); 8667535Sroot #endif 8677535Sroot 8687535Sroot /* 8697535Sroot * Make sure inode goes to disk before directory entry. 8707535Sroot */ 8717535Sroot iupdat(ip, &time, &time, 1); 8727535Sroot direnter(ip); 8737535Sroot if (u.u_error) { 8747535Sroot /* 8757535Sroot * write error occurred trying to update directory 8767535Sroot * so must deallocate the inode 8777535Sroot */ 8787535Sroot ip->i_nlink = 0; 8797535Sroot ip->i_flag |= ICHG; 8807535Sroot iput(ip); 8817701Ssam return (NULL); 8827535Sroot } 8837701Ssam return (ip); 8847535Sroot } 885