1*8559Sroot /* vfs_syscalls.c 4.39 82/10/17 */ 237Sbill 337Sbill #include "../h/param.h" 437Sbill #include "../h/systm.h" 537Sbill #include "../h/dir.h" 637Sbill #include "../h/user.h" 78040Sroot #include "../h/kernel.h" 86254Sroot #include "../h/file.h" 96574Smckusic #include "../h/stat.h" 1037Sbill #include "../h/inode.h" 116574Smckusic #include "../h/fs.h" 126254Sroot #include "../h/buf.h" 136254Sroot #include "../h/proc.h" 147482Skre #include "../h/quota.h" 157505Sroot #include "../h/descrip.h" 167826Sroot #include "../h/uio.h" 177826Sroot #include "../h/socket.h" 1837Sbill 196254Sroot chdir() 206254Sroot { 216254Sroot 226254Sroot chdirec(&u.u_cdir); 236254Sroot } 246254Sroot 256254Sroot chroot() 266254Sroot { 276254Sroot 286254Sroot if (suser()) 296254Sroot chdirec(&u.u_rdir); 306254Sroot } 316254Sroot 326254Sroot chdirec(ipp) 337701Ssam register struct inode **ipp; 346254Sroot { 356254Sroot register struct inode *ip; 366254Sroot struct a { 376254Sroot char *fname; 386254Sroot }; 396254Sroot 406254Sroot ip = namei(uchar, 0, 1); 416254Sroot if(ip == NULL) 426254Sroot return; 436254Sroot if((ip->i_mode&IFMT) != IFDIR) { 446254Sroot u.u_error = ENOTDIR; 456254Sroot goto bad; 466254Sroot } 476254Sroot if(access(ip, IEXEC)) 486254Sroot goto bad; 497122Smckusick iunlock(ip); 507142Smckusick if (*ipp) 517142Smckusick irele(*ipp); 526254Sroot *ipp = ip; 536254Sroot return; 546254Sroot 556254Sroot bad: 566254Sroot iput(ip); 576254Sroot } 586254Sroot 5937Sbill /* 606254Sroot * Open system call. 616254Sroot */ 626254Sroot open() 636254Sroot { 646254Sroot register struct inode *ip; 656254Sroot register struct a { 666254Sroot char *fname; 677701Ssam int flags; 687701Ssam int mode; 696254Sroot } *uap; 707701Ssam int checkpermissions = 1; 716254Sroot 726254Sroot uap = (struct a *)u.u_ap; 737701Ssam if (uap->flags&FCREATE) { 747701Ssam ip = namei(uchar, 1, 1); 757701Ssam if (ip == NULL) { 767701Ssam if (u.u_error) 777701Ssam return; 787701Ssam ip = maknode(uap->mode&07777&(~ISVTX)); 797701Ssam checkpermissions = 0; 807701Ssam uap->flags &= ~FTRUNCATE; 817701Ssam } 827701Ssam } else 837701Ssam ip = namei(uchar, 0, 1); 846254Sroot if (ip == NULL) 856254Sroot return; 867701Ssam open1(ip, ++uap->flags, checkpermissions); 876254Sroot } 886254Sroot 897701Ssam #ifndef NOCOMPAT 906254Sroot /* 916254Sroot * Creat system call. 926254Sroot */ 937505Sroot ocreat() 946254Sroot { 956254Sroot register struct inode *ip; 966254Sroot register struct a { 976254Sroot char *fname; 986254Sroot int fmode; 996254Sroot } *uap; 1006254Sroot 1016254Sroot uap = (struct a *)u.u_ap; 1026254Sroot ip = namei(uchar, 1, 1); 1036254Sroot if (ip == NULL) { 1046254Sroot if (u.u_error) 1056254Sroot return; 1066254Sroot ip = maknode(uap->fmode&07777&(~ISVTX)); 1077701Ssam if (ip == NULL) 1086254Sroot return; 1097701Ssam open1(ip, FWRITE, 0); 1106254Sroot } else 1117701Ssam open1(ip, FWRITE|FTRUNCATE, 0); 1126254Sroot } 1137701Ssam #endif 1146254Sroot 1156254Sroot /* 1166254Sroot * Common code for open and creat. 1177701Ssam * Check permissions (if we haven't done so already), 1187701Ssam * allocate an open file structure, and call 1197701Ssam * the device open routine, if any. 1206254Sroot */ 1217701Ssam open1(ip, mode, checkpermissions) 1226254Sroot register struct inode *ip; 1236254Sroot register mode; 1246254Sroot { 1256254Sroot register struct file *fp; 1267701Ssam int i, flags; 1276254Sroot 1287701Ssam if (checkpermissions) { 1296254Sroot if (mode&FREAD) 1307701Ssam if (access(ip, IREAD)) 1317701Ssam goto bad; 1326254Sroot if (mode&FWRITE) { 1337701Ssam if (access(ip, IWRITE)) 1347701Ssam goto bad; 1357701Ssam if ((ip->i_mode&IFMT) == IFDIR) { 1366254Sroot u.u_error = EISDIR; 1377701Ssam goto bad; 1387701Ssam } 1396254Sroot } 1406254Sroot } 1417701Ssam 1427701Ssam /* 1437701Ssam * Check locking on inode. Release "inode lock" 1447701Ssam * while doing so in case we block inside flocki. 1457701Ssam */ 1467701Ssam flags = 0; 1477701Ssam if (mode&(FRDLOCK|FWRLOCK)) { 1487701Ssam iunlock(ip); 1497701Ssam flags = flocki(ip, 0, mode); 1507701Ssam ilock(ip); 1517701Ssam if (u.u_error) 1527701Ssam goto bad; 1537142Smckusick } 1547701Ssam if (mode&FTRUNCATE) 1557701Ssam itrunc(ip, 0); 1567122Smckusick iunlock(ip); 1576254Sroot if ((fp = falloc()) == NULL) 1586254Sroot goto out; 1597701Ssam fp->f_flag = mode & FMODES; 1607505Sroot fp->f_type = DTYPE_FILE; 1616254Sroot i = u.u_r.r_val1; 1626254Sroot fp->f_inode = ip; 163*8559Sroot u.u_error = openi(ip, mode); 1647701Ssam if (u.u_error == 0) { 1657701Ssam u.u_pofile[i] = flags; 1666254Sroot return; 1677701Ssam } 1686254Sroot u.u_ofile[i] = NULL; 1696254Sroot fp->f_count--; 1706254Sroot out: 1717142Smckusick irele(ip); 1727701Ssam return; 1737701Ssam bad: 1747701Ssam iput(ip); 1756254Sroot } 1766254Sroot 1776254Sroot /* 1786254Sroot * Mknod system call 1796254Sroot */ 1806254Sroot mknod() 1816254Sroot { 1826254Sroot register struct inode *ip; 1836254Sroot register struct a { 1846254Sroot char *fname; 1856254Sroot int fmode; 1866254Sroot int dev; 1876254Sroot } *uap; 1886254Sroot 1896254Sroot uap = (struct a *)u.u_ap; 1906254Sroot if (suser()) { 1916254Sroot ip = namei(uchar, 1, 0); 1926254Sroot if (ip != NULL) { 1936254Sroot u.u_error = EEXIST; 1946254Sroot goto out; 1956254Sroot } 1966254Sroot } 1976254Sroot if (u.u_error) 1986254Sroot return; 1996254Sroot ip = maknode(uap->fmode); 2006254Sroot if (ip == NULL) 2016254Sroot return; 2026254Sroot if (uap->dev) { 2036254Sroot /* 2046254Sroot * Want to be able to use this to make badblock 2056254Sroot * inodes, so don't truncate the dev number. 2066254Sroot */ 2076574Smckusic ip->i_rdev = uap->dev; 2086254Sroot ip->i_flag |= IACC|IUPD|ICHG; 2096254Sroot } 2106254Sroot 2116254Sroot out: 2126254Sroot iput(ip); 2136254Sroot } 2146254Sroot 2156254Sroot /* 2166254Sroot * link system call 2176254Sroot */ 2186254Sroot link() 2196254Sroot { 2206254Sroot register struct inode *ip, *xp; 2216254Sroot register struct a { 2226254Sroot char *target; 2236254Sroot char *linkname; 2246254Sroot } *uap; 2256254Sroot 2266254Sroot uap = (struct a *)u.u_ap; 2276254Sroot ip = namei(uchar, 0, 1); /* well, this routine is doomed anyhow */ 2286254Sroot if (ip == NULL) 2296254Sroot return; 2307439Sroot if ((ip->i_mode&IFMT)==IFDIR && !suser()) { 2317439Sroot iput(ip); 2327439Sroot return; 2337439Sroot } 2346254Sroot ip->i_nlink++; 2356254Sroot ip->i_flag |= ICHG; 2368040Sroot iupdat(ip, &time.tv_sec, &time.tv_sec, 1); 2377122Smckusick iunlock(ip); 2386254Sroot u.u_dirp = (caddr_t)uap->linkname; 2396254Sroot xp = namei(uchar, 1, 0); 2406254Sroot if (xp != NULL) { 2416254Sroot u.u_error = EEXIST; 2426254Sroot iput(xp); 2436254Sroot goto out; 2446254Sroot } 2456254Sroot if (u.u_error) 2466254Sroot goto out; 2476254Sroot if (u.u_pdir->i_dev != ip->i_dev) { 2486254Sroot iput(u.u_pdir); 2496254Sroot u.u_error = EXDEV; 2506254Sroot goto out; 2516254Sroot } 2527535Sroot direnter(ip); 2536254Sroot out: 2546254Sroot if (u.u_error) { 2556254Sroot ip->i_nlink--; 2566254Sroot ip->i_flag |= ICHG; 2576254Sroot } 2587142Smckusick irele(ip); 2596254Sroot } 2606254Sroot 2616254Sroot /* 2626254Sroot * symlink -- make a symbolic link 2636254Sroot */ 2646254Sroot symlink() 2656254Sroot { 2666254Sroot register struct a { 2676254Sroot char *target; 2686254Sroot char *linkname; 2696254Sroot } *uap; 2706254Sroot register struct inode *ip; 2716254Sroot register char *tp; 2726254Sroot register c, nc; 2736254Sroot 2746254Sroot uap = (struct a *)u.u_ap; 2756254Sroot tp = uap->target; 2766254Sroot nc = 0; 2776254Sroot while (c = fubyte(tp)) { 2786254Sroot if (c < 0) { 2796254Sroot u.u_error = EFAULT; 2806254Sroot return; 2816254Sroot } 2826254Sroot tp++; 2836254Sroot nc++; 2846254Sroot } 2856254Sroot u.u_dirp = uap->linkname; 2866254Sroot ip = namei(uchar, 1, 0); 2876254Sroot if (ip) { 2886254Sroot iput(ip); 2896254Sroot u.u_error = EEXIST; 2906254Sroot return; 2916254Sroot } 2926254Sroot if (u.u_error) 2936254Sroot return; 2946254Sroot ip = maknode(IFLNK | 0777); 2956254Sroot if (ip == NULL) 2966254Sroot return; 2977826Sroot u.u_error = rdwri(UIO_WRITE, ip, uap->target, nc, 0, 0, (int *)0); 2986254Sroot iput(ip); 2996254Sroot } 3006254Sroot 3016254Sroot /* 3026254Sroot * Unlink system call. 3036254Sroot * Hard to avoid races here, especially 3046254Sroot * in unlinking directories. 3056254Sroot */ 3066254Sroot unlink() 3076254Sroot { 3086254Sroot register struct inode *ip, *pp; 3096254Sroot struct a { 3106254Sroot char *fname; 3116254Sroot }; 3127142Smckusick int unlinkingdot = 0; 3136254Sroot 3146254Sroot pp = namei(uchar, 2, 0); 3157535Sroot if (pp == NULL) 3166254Sroot return; 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 */ 3417535Sroot if (dirremove()) { 3427535Sroot ip->i_nlink--; 3437535Sroot 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 */ 3578040Sroot lseek() 3586254Sroot { 3596254Sroot register struct file *fp; 3606254Sroot register struct a { 3617701Ssam int fd; 3626254Sroot off_t off; 3636254Sroot int sbase; 3646254Sroot } *uap; 3656254Sroot 3666254Sroot uap = (struct a *)u.u_ap; 3677701Ssam fp = getf(uap->fd); 3686254Sroot if (fp == NULL) 3696254Sroot return; 3707505Sroot if (fp->f_type == DTYPE_SOCKET) { 3716254Sroot u.u_error = ESPIPE; 3726254Sroot return; 3736254Sroot } 3747701Ssam if (uap->sbase == FSEEK_RELATIVE) 3756254Sroot uap->off += fp->f_offset; 3767701Ssam else if (uap->sbase == FSEEK_EOF) 3776254Sroot uap->off += fp->f_inode->i_size; 3786254Sroot fp->f_offset = uap->off; 3796254Sroot u.u_r.r_off = uap->off; 3806254Sroot } 3816254Sroot 3826254Sroot /* 3836254Sroot * Access system call 3846254Sroot */ 3856254Sroot saccess() 3866254Sroot { 3876254Sroot register svuid, svgid; 3886254Sroot register struct inode *ip; 3896254Sroot register struct a { 3906254Sroot char *fname; 3916254Sroot int fmode; 3926254Sroot } *uap; 3936254Sroot 3946254Sroot uap = (struct a *)u.u_ap; 3956254Sroot svuid = u.u_uid; 3966254Sroot svgid = u.u_gid; 3976254Sroot u.u_uid = u.u_ruid; 3986254Sroot u.u_gid = u.u_rgid; 3996254Sroot ip = namei(uchar, 0, 1); 4006254Sroot if (ip != NULL) { 4017701Ssam if (uap->fmode&FACCESS_READ && access(ip, IREAD)) 4027701Ssam goto done; 4037701Ssam if (uap->fmode&FACCESS_WRITE && access(ip, IWRITE)) 4047701Ssam goto done; 4057701Ssam if (uap->fmode&FACCESS_EXECUTE && access(ip, IEXEC)) 4067701Ssam goto done; 4077701Ssam done: 4086254Sroot iput(ip); 4096254Sroot } 4106254Sroot u.u_uid = svuid; 4116254Sroot u.u_gid = svgid; 4126254Sroot } 4136254Sroot 4146254Sroot /* 41537Sbill * the fstat system call. 41637Sbill */ 41737Sbill fstat() 41837Sbill { 41937Sbill register struct file *fp; 42037Sbill register struct a { 4217701Ssam int fd; 42237Sbill struct stat *sb; 42337Sbill } *uap; 42437Sbill 42537Sbill uap = (struct a *)u.u_ap; 4267701Ssam fp = getf(uap->fd); 4274828Swnj if (fp == NULL) 42837Sbill return; 4297505Sroot if (fp->f_type == DTYPE_SOCKET) 4304891Swnj u.u_error = sostat(fp->f_socket, uap->sb); 4314828Swnj else 4324828Swnj stat1(fp->f_inode, uap->sb); 43337Sbill } 43437Sbill 43537Sbill /* 4366574Smckusic * Stat system call. This version follows links. 43737Sbill */ 43837Sbill stat() 43937Sbill { 44037Sbill register struct inode *ip; 44137Sbill register struct a { 44237Sbill char *fname; 44337Sbill struct stat *sb; 44437Sbill } *uap; 44537Sbill 44637Sbill uap = (struct a *)u.u_ap; 4476423Sroot ip = namei(uchar, 0, 1); 4484828Swnj if (ip == NULL) 44937Sbill return; 4503624Sroot stat1(ip, uap->sb); 45137Sbill iput(ip); 45237Sbill } 45337Sbill 45437Sbill /* 4556574Smckusic * Lstat system call. This version does not follow links. 4565992Swnj */ 4575992Swnj lstat() 4585992Swnj { 4595992Swnj register struct inode *ip; 4605992Swnj register struct a { 4615992Swnj char *fname; 4625992Swnj struct stat *sb; 4635992Swnj } *uap; 4645992Swnj 4655992Swnj uap = (struct a *)u.u_ap; 4666423Sroot ip = namei(uchar, 0, 0); 4675992Swnj if (ip == NULL) 4685992Swnj return; 4696153Ssam stat1(ip, uap->sb); 4705992Swnj iput(ip); 4715992Swnj } 4725992Swnj 4735992Swnj /* 47437Sbill * The basic routine for fstat and stat: 47537Sbill * get the inode and pass appropriate parts back. 47637Sbill */ 4773624Sroot stat1(ip, ub) 4784828Swnj register struct inode *ip; 4794828Swnj struct stat *ub; 48037Sbill { 48137Sbill struct stat ds; 48237Sbill 4838040Sroot IUPDAT(ip, &time.tv_sec, &time.tv_sec, 0); 48437Sbill /* 4857023Smckusick * Copy from inode table 48637Sbill */ 48737Sbill ds.st_dev = ip->i_dev; 48837Sbill ds.st_ino = ip->i_number; 48937Sbill ds.st_mode = ip->i_mode; 49037Sbill ds.st_nlink = ip->i_nlink; 49137Sbill ds.st_uid = ip->i_uid; 49237Sbill ds.st_gid = ip->i_gid; 4936574Smckusic ds.st_rdev = (dev_t)ip->i_rdev; 4943624Sroot ds.st_size = ip->i_size; 4956574Smckusic ds.st_atime = ip->i_atime; 4966574Smckusic ds.st_mtime = ip->i_mtime; 4976574Smckusic ds.st_ctime = ip->i_ctime; 4987701Ssam /* this doesn't belong here */ 4997701Ssam if ((ip->i_mode&IFMT) == IFBLK) 5007701Ssam ds.st_blksize = BLKDEV_IOSIZE; 5017701Ssam else if ((ip->i_mode&IFMT) == IFCHR) 5027701Ssam ds.st_blksize = MAXBSIZE; 5037701Ssam else 5047701Ssam ds.st_blksize = ip->i_fs->fs_bsize; 50537Sbill if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 50637Sbill u.u_error = EFAULT; 50737Sbill } 50837Sbill 50937Sbill /* 5105992Swnj * Return target name of a symbolic link 51137Sbill */ 5125992Swnj readlink() 5135992Swnj { 5145992Swnj register struct inode *ip; 5155992Swnj register struct a { 5165992Swnj char *name; 5175992Swnj char *buf; 5185992Swnj int count; 5197826Sroot } *uap = (struct a *)u.u_ap; 5207826Sroot int resid; 5215992Swnj 5225992Swnj ip = namei(uchar, 0, 0); 5235992Swnj if (ip == NULL) 5245992Swnj return; 5255992Swnj if ((ip->i_mode&IFMT) != IFLNK) { 5265992Swnj u.u_error = ENXIO; 5275992Swnj goto out; 5285992Swnj } 5297826Sroot u.u_error = rdwri(UIO_READ, ip, uap->buf, uap->count, 0, 0, &resid); 5305992Swnj out: 5315992Swnj iput(ip); 5327826Sroot u.u_r.r_val1 = uap->count - resid; 5335992Swnj } 5345992Swnj 5356254Sroot chmod() 5365992Swnj { 5377701Ssam struct inode *ip; 5387701Ssam struct a { 5396254Sroot char *fname; 5406254Sroot int fmode; 5415992Swnj } *uap; 5425992Swnj 5435992Swnj uap = (struct a *)u.u_ap; 5446254Sroot if ((ip = owner(1)) == NULL) 5455992Swnj return; 5467701Ssam chmod1(ip, uap->fmode); 5477701Ssam } 5487439Sroot 5497701Ssam fchmod() 5507701Ssam { 5517701Ssam struct a { 5527701Ssam int fd; 5537701Ssam int fmode; 5547701Ssam } *uap; 5557701Ssam register struct inode *ip; 5567701Ssam register struct file *fp; 5577701Ssam 5587701Ssam uap = (struct a *)u.u_ap; 5597701Ssam fp = getf(uap->fd); 5607701Ssam if (fp == NULL) 5617701Ssam return; 5627701Ssam if (fp->f_type == DTYPE_SOCKET) { 5637701Ssam u.u_error = EINVAL; 5647701Ssam return; 5657439Sroot } 5667701Ssam ip = fp->f_inode; 5677701Ssam ilock(ip); 5687701Ssam if (u.u_uid != ip->i_uid && !suser()) { 5697701Ssam iunlock(ip); 5707701Ssam return; 5717701Ssam } 5727701Ssam chmod1(ip, uap->fmode); 5737701Ssam } 5747701Ssam 5757701Ssam chmod1(ip, mode) 5767701Ssam register struct inode *ip; 5777701Ssam register int mode; 5787701Ssam { 5797868Sroot register int *gp; 5807868Sroot 5816254Sroot ip->i_mode &= ~07777; 5827439Sroot if (u.u_uid) { 5837701Ssam mode &= ~ISVTX; 5847868Sroot for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++) 5857868Sroot if (*gp == ip->i_gid) 5867868Sroot goto ok; 5877868Sroot mode &= ~ISGID; 5887868Sroot ok: 5897868Sroot ; 5907701Ssam #ifdef MUSH 5917482Skre if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 && 5927482Skre (ip->i_mode & IFMT) != IFCHR) 5937701Ssam mode &= ~u.u_cmask; 5947482Skre #endif 5957439Sroot } 5967701Ssam ip->i_mode |= mode&07777; 5976254Sroot ip->i_flag |= ICHG; 5986254Sroot if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 5996254Sroot xrele(ip); 6005992Swnj iput(ip); 6015992Swnj } 6025992Swnj 6036254Sroot chown() 60437Sbill { 6057701Ssam struct inode *ip; 6067701Ssam struct a { 6076254Sroot char *fname; 6086254Sroot int uid; 6096254Sroot int gid; 61037Sbill } *uap; 61137Sbill 61237Sbill uap = (struct a *)u.u_ap; 6136254Sroot if (!suser() || (ip = owner(0)) == NULL) 61437Sbill return; 6157701Ssam chown1(ip, uap->uid, uap->gid); 6167701Ssam } 6177439Sroot 6187701Ssam fchown() 6197701Ssam { 6207701Ssam struct a { 6217701Ssam int fd; 6227701Ssam int uid; 6237701Ssam int gid; 6247701Ssam } *uap; 6257701Ssam register struct inode *ip; 6267701Ssam register struct file *fp; 6277701Ssam 6287701Ssam uap = (struct a *)u.u_ap; 6297701Ssam fp = getf(uap->fd); 6307701Ssam if (fp == NULL) 6317701Ssam return; 6327701Ssam if (fp->f_type == DTYPE_SOCKET) { 6337701Ssam u.u_error = EINVAL; 6347701Ssam return; 6357439Sroot } 6367701Ssam ip = fp->f_inode; 6377701Ssam ilock(ip); 6387701Ssam if (!suser()) { 6397701Ssam iunlock(ip); 6407701Ssam return; 6417701Ssam } 6427701Ssam chown1(ip, uap->uid, uap->gid); 6437701Ssam } 6447701Ssam 6457701Ssam /* 6467701Ssam * Perform chown operation on inode ip; 6477701Ssam * inode must be locked prior to call. 6487701Ssam */ 6497701Ssam chown1(ip, uid, gid) 6507701Ssam register struct inode *ip; 6517701Ssam int uid, gid; 6527701Ssam { 6537701Ssam #ifdef QUOTA 6547701Ssam register long change; 6557701Ssam 6567439Sroot /* 6577482Skre * This doesn't allow for holes in files (which hopefully don't 6587482Skre * happen often in files that we chown), and is not accurate anyway 6597482Skre * (eg: it totally ignores 3 level indir blk files - but hopefully 6607482Skre * noone who can make a file that big will have a quota) 6617482Skre */ 6627701Ssam if (ip->i_uid == uid) 6637482Skre change = 0; 6647482Skre else { 6657482Skre register struct fs *fs = ip->i_fs; 6667482Skre 6677482Skre if (ip->i_size > (change = NDADDR * fs->fs_bsize)) { 6687482Skre register off_t size; 6697482Skre 6707482Skre size = blkroundup(fs, ip->i_size) - change; 6717482Skre change += size; 6727482Skre change += fs->fs_bsize; 6737701Ssam /* this assumes NIADDR <= 2 */ 6747482Skre if (size > NINDIR(fs) * fs->fs_bsize) 6757482Skre change += fs->fs_bsize; 6767482Skre } else 6777482Skre change = fragroundup(fs, ip->i_size); 6787482Skre change /= DEV_BSIZE; 6797482Skre } 6807482Skre chkdq(ip, -change, 1); 6817482Skre chkiq(ip->i_dev, ip, ip->i_uid, 1); 6827482Skre dqrele(ip->i_dquot); 6837482Skre #endif 6847482Skre /* 6857701Ssam * keep uid/gid's in sane range -- no err, 6867701Ssam * so chown(file, uid, -1) will do something useful 6877439Sroot */ 6887701Ssam if (uid >= 0 && uid <= 32767) /* should have a constant */ 6897701Ssam ip->i_uid = uid; 6907701Ssam if (gid >= 0 && gid <= 32767) /* same here */ 6917701Ssam ip->i_gid = gid; 6926254Sroot ip->i_flag |= ICHG; 6936254Sroot if (u.u_ruid != 0) 6946254Sroot ip->i_mode &= ~(ISUID|ISGID); 6957701Ssam #ifdef QUOTA 6967482Skre ip->i_dquot = inoquota(ip); 6977482Skre chkdq(ip, change, 1); 6987701Ssam chkiq(ip->i_dev, NULL, uid, 1); 6997482Skre #endif 7006254Sroot iput(ip); 70137Sbill } 70237Sbill 70337Sbill /* 7046254Sroot * Set IUPD and IACC times on file. 7056254Sroot * Can't set ICHG. 70637Sbill */ 7078107Sroot outime() 7084828Swnj { 70937Sbill register struct a { 7106254Sroot char *fname; 7116254Sroot time_t *tptr; 71237Sbill } *uap; 7136254Sroot register struct inode *ip; 7146254Sroot time_t tv[2]; 71537Sbill 71637Sbill uap = (struct a *)u.u_ap; 7176254Sroot if ((ip = owner(1)) == NULL) 71837Sbill return; 7196254Sroot if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { 7206254Sroot u.u_error = EFAULT; 7216254Sroot } else { 7226254Sroot ip->i_flag |= IACC|IUPD|ICHG; 7236254Sroot iupdat(ip, &tv[0], &tv[1], 0); 72437Sbill } 72537Sbill iput(ip); 72637Sbill } 72737Sbill 7286254Sroot sync() 72937Sbill { 73037Sbill 7315416Swnj update(0); 73237Sbill } 7337535Sroot 7347701Ssam flock() 7357701Ssam { 7367701Ssam struct a { 7377701Ssam int fd; 7387701Ssam int how; 7397701Ssam } *uap; 7407701Ssam register struct file *fp; 7417701Ssam register int cmd, flags; 7427701Ssam 7437701Ssam uap = (struct a *)u.u_ap; 7447701Ssam fp = getf(uap->fd); 7457701Ssam if (fp == NULL) 7467701Ssam return; 7477701Ssam if (fp->f_type == DTYPE_SOCKET) { /* XXX */ 7487701Ssam u.u_error = EINVAL; 7497701Ssam return; 7507701Ssam } 7517701Ssam cmd = uap->how; 7527701Ssam flags = u.u_pofile[uap->fd] & (RDLOCK|WRLOCK); 7537701Ssam if (cmd&FUNLOCK) { 7547701Ssam if (flags == 0) { 7557701Ssam u.u_error = EINVAL; 7567701Ssam return; 7577701Ssam } 7587701Ssam funlocki(fp->f_inode, flags); 7597701Ssam u.u_pofile[uap->fd] &= ~(RDLOCK|WRLOCK); 7607701Ssam return; 7617701Ssam } 7627701Ssam /* 7637701Ssam * No reason to write lock a file we've already 7647701Ssam * write locked, similarly with a read lock. 7657701Ssam */ 7667701Ssam if ((flags&WRLOCK) && (cmd&FWRLOCK) || 7677701Ssam (flags&RDLOCK) && (cmd&FRDLOCK)) 7687701Ssam return; 7697701Ssam u.u_pofile[uap->fd] = flocki(fp->f_inode, u.u_pofile[uap->fd], cmd); 7707701Ssam } 7717701Ssam 7727701Ssam truncate() 7737701Ssam { 7747701Ssam struct a { 7757701Ssam char *fname; 7767701Ssam int length; 7777826Sroot } *uap = (struct a *)u.u_ap; 7787701Ssam struct inode *ip; 7797701Ssam 7807701Ssam ip = namei(uchar, 0, 1); 7817701Ssam if (ip == NULL) 7827701Ssam return; 7837701Ssam if (access(ip, IWRITE)) 7847701Ssam goto bad; 7857701Ssam if ((ip->i_mode&IFMT) == IFDIR) { 7867701Ssam u.u_error = EISDIR; 7877701Ssam goto bad; 7887701Ssam } 7897701Ssam itrunc(ip, uap->length); 7907701Ssam return; 7917701Ssam bad: 7927701Ssam iput(ip); 7937701Ssam } 7947701Ssam 7957701Ssam ftruncate() 7967701Ssam { 7977701Ssam struct a { 7987701Ssam int fd; 7997701Ssam int length; 8007826Sroot } *uap = (struct a *)u.u_ap; 8017701Ssam struct inode *ip; 8027701Ssam struct file *fp; 8037701Ssam 8047701Ssam fp = getf(uap->fd); 8057701Ssam if (fp == NULL) 8067701Ssam return; 8077701Ssam if (fp->f_type == DTYPE_SOCKET) { 8087701Ssam u.u_error = EINVAL; 8097701Ssam return; 8107701Ssam } 8117701Ssam if ((fp->f_flag&FWRITE) == 0) { 8127701Ssam u.u_error = EINVAL; 8137701Ssam return; 8147701Ssam } 8157701Ssam ip = fp->f_inode; 8167701Ssam ilock(ip); 8177701Ssam itrunc(ip, uap->length); 8187701Ssam } 8197701Ssam 8207701Ssam rename() 8217701Ssam { 8227826Sroot #ifdef notdef 8237701Ssam struct a { 8247701Ssam char *from; 8257701Ssam char *to; 8267701Ssam } *uap; 8277826Sroot #endif 8287701Ssam 8297701Ssam } 8307701Ssam 8317535Sroot /* 8327535Sroot * Make a new file. 8337535Sroot */ 8347535Sroot struct inode * 8357535Sroot maknode(mode) 8367535Sroot int mode; 8377535Sroot { 8387535Sroot register struct inode *ip; 8397535Sroot ino_t ipref; 8407535Sroot 8417535Sroot if ((mode & IFMT) == IFDIR) 8427535Sroot ipref = dirpref(u.u_pdir->i_fs); 8437535Sroot else 8447535Sroot ipref = u.u_pdir->i_number; 8457535Sroot ip = ialloc(u.u_pdir, ipref, mode); 8467535Sroot if (ip == NULL) { 8477535Sroot iput(u.u_pdir); 8487701Ssam return (NULL); 8497535Sroot } 8507701Ssam #ifdef QUOTA 8517535Sroot if (ip->i_dquot != NODQUOT) 8527535Sroot panic("maknode: dquot"); 8537535Sroot #endif 8547535Sroot ip->i_flag |= IACC|IUPD|ICHG; 8557535Sroot if ((mode & IFMT) == 0) 8567535Sroot mode |= IFREG; 8577535Sroot ip->i_mode = mode & ~u.u_cmask; 8587535Sroot ip->i_nlink = 1; 8597535Sroot ip->i_uid = u.u_uid; 8607535Sroot ip->i_gid = u.u_pdir->i_gid; 8617701Ssam #ifdef QUOTA 8627535Sroot ip->i_dquot = inoquota(ip); 8637535Sroot #endif 8647535Sroot 8657535Sroot /* 8667535Sroot * Make sure inode goes to disk before directory entry. 8677535Sroot */ 8688040Sroot iupdat(ip, &time.tv_sec, &time.tv_sec, 1); 8697535Sroot direnter(ip); 8707535Sroot if (u.u_error) { 8717535Sroot /* 8727535Sroot * write error occurred trying to update directory 8737535Sroot * so must deallocate the inode 8747535Sroot */ 8757535Sroot ip->i_nlink = 0; 8767535Sroot ip->i_flag |= ICHG; 8777535Sroot iput(ip); 8787701Ssam return (NULL); 8797535Sroot } 8807701Ssam return (ip); 8817535Sroot } 882