1*7826Sroot /* vfs_syscalls.c 4.34 82/08/22 */ 237Sbill 337Sbill #include "../h/param.h" 437Sbill #include "../h/systm.h" 537Sbill #include "../h/dir.h" 637Sbill #include "../h/user.h" 76254Sroot #include "../h/file.h" 86574Smckusic #include "../h/stat.h" 937Sbill #include "../h/inode.h" 106574Smckusic #include "../h/fs.h" 116254Sroot #include "../h/buf.h" 126254Sroot #include "../h/proc.h" 136254Sroot #include "../h/inline.h" 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" 19*7826Sroot #include "../h/uio.h" 20*7826Sroot #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; 300*7826Sroot 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; 522*7826Sroot } *uap = (struct a *)u.u_ap; 523*7826Sroot 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 } 532*7826Sroot u.u_error = rdwri(UIO_READ, ip, uap->buf, uap->count, 0, 0, &resid); 5335992Swnj out: 5345992Swnj iput(ip); 535*7826Sroot 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 { 5826254Sroot ip->i_mode &= ~07777; 5837439Sroot if (u.u_uid) { 5847701Ssam mode &= ~ISVTX; 5857439Sroot if (ip->i_gid >= NGRPS || 5867439Sroot (u.u_grps[ip->i_gid/(sizeof(int)*8)] & 5877439Sroot (1 << ip->i_gid%(sizeof(int)*8))) == 0) 5887701Ssam mode &= ~ISGID; 5897701Ssam #ifdef MUSH 5907482Skre if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 && 5917482Skre (ip->i_mode & IFMT) != IFCHR) 5927701Ssam mode &= ~u.u_cmask; 5937482Skre #endif 5947439Sroot } 5957701Ssam ip->i_mode |= mode&07777; 5966254Sroot ip->i_flag |= ICHG; 5976254Sroot if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 5986254Sroot xrele(ip); 5995992Swnj iput(ip); 6005992Swnj } 6015992Swnj 6026254Sroot chown() 60337Sbill { 6047701Ssam struct inode *ip; 6057701Ssam struct a { 6066254Sroot char *fname; 6076254Sroot int uid; 6086254Sroot int gid; 60937Sbill } *uap; 61037Sbill 61137Sbill uap = (struct a *)u.u_ap; 6126254Sroot if (!suser() || (ip = owner(0)) == NULL) 61337Sbill return; 6147701Ssam chown1(ip, uap->uid, uap->gid); 6157701Ssam } 6167439Sroot 6177701Ssam fchown() 6187701Ssam { 6197701Ssam struct a { 6207701Ssam int fd; 6217701Ssam int uid; 6227701Ssam int gid; 6237701Ssam } *uap; 6247701Ssam register struct inode *ip; 6257701Ssam register struct file *fp; 6267701Ssam 6277701Ssam uap = (struct a *)u.u_ap; 6287701Ssam fp = getf(uap->fd); 6297701Ssam if (fp == NULL) 6307701Ssam return; 6317701Ssam if (fp->f_type == DTYPE_SOCKET) { 6327701Ssam u.u_error = EINVAL; 6337701Ssam return; 6347439Sroot } 6357701Ssam ip = fp->f_inode; 6367701Ssam ilock(ip); 6377701Ssam if (!suser()) { 6387701Ssam iunlock(ip); 6397701Ssam return; 6407701Ssam } 6417701Ssam chown1(ip, uap->uid, uap->gid); 6427701Ssam } 6437701Ssam 6447701Ssam /* 6457701Ssam * Perform chown operation on inode ip; 6467701Ssam * inode must be locked prior to call. 6477701Ssam */ 6487701Ssam chown1(ip, uid, gid) 6497701Ssam register struct inode *ip; 6507701Ssam int uid, gid; 6517701Ssam { 6527701Ssam #ifdef QUOTA 6537701Ssam register long change; 6547701Ssam 6557439Sroot /* 6567482Skre * This doesn't allow for holes in files (which hopefully don't 6577482Skre * happen often in files that we chown), and is not accurate anyway 6587482Skre * (eg: it totally ignores 3 level indir blk files - but hopefully 6597482Skre * noone who can make a file that big will have a quota) 6607482Skre */ 6617701Ssam if (ip->i_uid == uid) 6627482Skre change = 0; 6637482Skre else { 6647482Skre register struct fs *fs = ip->i_fs; 6657482Skre 6667482Skre if (ip->i_size > (change = NDADDR * fs->fs_bsize)) { 6677482Skre register off_t size; 6687482Skre 6697482Skre size = blkroundup(fs, ip->i_size) - change; 6707482Skre change += size; 6717482Skre change += fs->fs_bsize; 6727701Ssam /* this assumes NIADDR <= 2 */ 6737482Skre if (size > NINDIR(fs) * fs->fs_bsize) 6747482Skre change += fs->fs_bsize; 6757482Skre } else 6767482Skre change = fragroundup(fs, ip->i_size); 6777482Skre change /= DEV_BSIZE; 6787482Skre } 6797482Skre chkdq(ip, -change, 1); 6807482Skre chkiq(ip->i_dev, ip, ip->i_uid, 1); 6817482Skre dqrele(ip->i_dquot); 6827482Skre #endif 6837482Skre /* 6847701Ssam * keep uid/gid's in sane range -- no err, 6857701Ssam * so chown(file, uid, -1) will do something useful 6867439Sroot */ 6877701Ssam if (uid >= 0 && uid <= 32767) /* should have a constant */ 6887701Ssam ip->i_uid = uid; 6897701Ssam if (gid >= 0 && gid <= 32767) /* same here */ 6907701Ssam ip->i_gid = gid; 6916254Sroot ip->i_flag |= ICHG; 6926254Sroot if (u.u_ruid != 0) 6936254Sroot ip->i_mode &= ~(ISUID|ISGID); 6947701Ssam #ifdef QUOTA 6957482Skre ip->i_dquot = inoquota(ip); 6967482Skre chkdq(ip, change, 1); 6977701Ssam chkiq(ip->i_dev, NULL, uid, 1); 6987482Skre #endif 6996254Sroot iput(ip); 70037Sbill } 70137Sbill 70237Sbill /* 7036254Sroot * Set IUPD and IACC times on file. 7046254Sroot * Can't set ICHG. 70537Sbill */ 7066254Sroot utime() 7074828Swnj { 70837Sbill register struct a { 7096254Sroot char *fname; 7106254Sroot time_t *tptr; 71137Sbill } *uap; 7126254Sroot register struct inode *ip; 7136254Sroot time_t tv[2]; 71437Sbill 71537Sbill uap = (struct a *)u.u_ap; 7166254Sroot if ((ip = owner(1)) == NULL) 71737Sbill return; 7186254Sroot if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { 7196254Sroot u.u_error = EFAULT; 7206254Sroot } else { 7216254Sroot ip->i_flag |= IACC|IUPD|ICHG; 7226254Sroot iupdat(ip, &tv[0], &tv[1], 0); 72337Sbill } 72437Sbill iput(ip); 72537Sbill } 72637Sbill 7276254Sroot sync() 72837Sbill { 72937Sbill 7305416Swnj update(0); 73137Sbill } 7327535Sroot 7337701Ssam flock() 7347701Ssam { 7357701Ssam struct a { 7367701Ssam int fd; 7377701Ssam int how; 7387701Ssam } *uap; 7397701Ssam register struct file *fp; 7407701Ssam register int cmd, flags; 7417701Ssam 7427701Ssam uap = (struct a *)u.u_ap; 7437701Ssam fp = getf(uap->fd); 7447701Ssam if (fp == NULL) 7457701Ssam return; 7467701Ssam if (fp->f_type == DTYPE_SOCKET) { /* XXX */ 7477701Ssam u.u_error = EINVAL; 7487701Ssam return; 7497701Ssam } 7507701Ssam cmd = uap->how; 7517701Ssam flags = u.u_pofile[uap->fd] & (RDLOCK|WRLOCK); 7527701Ssam if (cmd&FUNLOCK) { 7537701Ssam if (flags == 0) { 7547701Ssam u.u_error = EINVAL; 7557701Ssam return; 7567701Ssam } 7577701Ssam funlocki(fp->f_inode, flags); 7587701Ssam u.u_pofile[uap->fd] &= ~(RDLOCK|WRLOCK); 7597701Ssam return; 7607701Ssam } 7617701Ssam /* 7627701Ssam * No reason to write lock a file we've already 7637701Ssam * write locked, similarly with a read lock. 7647701Ssam */ 7657701Ssam if ((flags&WRLOCK) && (cmd&FWRLOCK) || 7667701Ssam (flags&RDLOCK) && (cmd&FRDLOCK)) 7677701Ssam return; 7687701Ssam u.u_pofile[uap->fd] = flocki(fp->f_inode, u.u_pofile[uap->fd], cmd); 7697701Ssam } 7707701Ssam 7717701Ssam truncate() 7727701Ssam { 7737701Ssam struct a { 7747701Ssam char *fname; 7757701Ssam int length; 776*7826Sroot } *uap = (struct a *)u.u_ap; 7777701Ssam struct inode *ip; 7787701Ssam 7797701Ssam ip = namei(uchar, 0, 1); 7807701Ssam if (ip == NULL) 7817701Ssam return; 7827701Ssam if (access(ip, IWRITE)) 7837701Ssam goto bad; 7847701Ssam if ((ip->i_mode&IFMT) == IFDIR) { 7857701Ssam u.u_error = EISDIR; 7867701Ssam goto bad; 7877701Ssam } 7887701Ssam itrunc(ip, uap->length); 7897701Ssam return; 7907701Ssam bad: 7917701Ssam iput(ip); 7927701Ssam } 7937701Ssam 7947701Ssam ftruncate() 7957701Ssam { 7967701Ssam struct a { 7977701Ssam int fd; 7987701Ssam int length; 799*7826Sroot } *uap = (struct a *)u.u_ap; 8007701Ssam struct inode *ip; 8017701Ssam struct file *fp; 8027701Ssam 8037701Ssam fp = getf(uap->fd); 8047701Ssam if (fp == NULL) 8057701Ssam return; 8067701Ssam if (fp->f_type == DTYPE_SOCKET) { 8077701Ssam u.u_error = EINVAL; 8087701Ssam return; 8097701Ssam } 8107701Ssam if ((fp->f_flag&FWRITE) == 0) { 8117701Ssam u.u_error = EINVAL; 8127701Ssam return; 8137701Ssam } 8147701Ssam ip = fp->f_inode; 8157701Ssam ilock(ip); 8167701Ssam itrunc(ip, uap->length); 8177701Ssam } 8187701Ssam 8197701Ssam rename() 8207701Ssam { 821*7826Sroot #ifdef notdef 8227701Ssam struct a { 8237701Ssam char *from; 8247701Ssam char *to; 8257701Ssam } *uap; 826*7826Sroot #endif 8277701Ssam 8287701Ssam } 8297701Ssam 8307535Sroot /* 8317535Sroot * Make a new file. 8327535Sroot */ 8337535Sroot struct inode * 8347535Sroot maknode(mode) 8357535Sroot int mode; 8367535Sroot { 8377535Sroot register struct inode *ip; 8387535Sroot ino_t ipref; 8397535Sroot 8407535Sroot if ((mode & IFMT) == IFDIR) 8417535Sroot ipref = dirpref(u.u_pdir->i_fs); 8427535Sroot else 8437535Sroot ipref = u.u_pdir->i_number; 8447535Sroot ip = ialloc(u.u_pdir, ipref, mode); 8457535Sroot if (ip == NULL) { 8467535Sroot iput(u.u_pdir); 8477701Ssam return (NULL); 8487535Sroot } 8497701Ssam #ifdef QUOTA 8507535Sroot if (ip->i_dquot != NODQUOT) 8517535Sroot panic("maknode: dquot"); 8527535Sroot #endif 8537535Sroot ip->i_flag |= IACC|IUPD|ICHG; 8547535Sroot if ((mode & IFMT) == 0) 8557535Sroot mode |= IFREG; 8567535Sroot ip->i_mode = mode & ~u.u_cmask; 8577535Sroot ip->i_nlink = 1; 8587535Sroot ip->i_uid = u.u_uid; 8597535Sroot ip->i_gid = u.u_pdir->i_gid; 8607701Ssam #ifdef QUOTA 8617535Sroot ip->i_dquot = inoquota(ip); 8627535Sroot #endif 8637535Sroot 8647535Sroot /* 8657535Sroot * Make sure inode goes to disk before directory entry. 8667535Sroot */ 8677535Sroot iupdat(ip, &time, &time, 1); 8687535Sroot direnter(ip); 8697535Sroot if (u.u_error) { 8707535Sroot /* 8717535Sroot * write error occurred trying to update directory 8727535Sroot * so must deallocate the inode 8737535Sroot */ 8747535Sroot ip->i_nlink = 0; 8757535Sroot ip->i_flag |= ICHG; 8767535Sroot iput(ip); 8777701Ssam return (NULL); 8787535Sroot } 8797701Ssam return (ip); 8807535Sroot } 881