1*8673Sroot /* vfs_syscalls.c 4.41 82/10/19 */ 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" 188632Sroot #include "../h/socketvar.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) 347701Ssam 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; 687701Ssam int flags; 697701Ssam int mode; 706254Sroot } *uap; 717701Ssam int checkpermissions = 1; 726254Sroot 736254Sroot uap = (struct a *)u.u_ap; 747701Ssam if (uap->flags&FCREATE) { 757701Ssam ip = namei(uchar, 1, 1); 767701Ssam if (ip == NULL) { 777701Ssam if (u.u_error) 787701Ssam return; 797701Ssam ip = maknode(uap->mode&07777&(~ISVTX)); 807701Ssam checkpermissions = 0; 817701Ssam uap->flags &= ~FTRUNCATE; 827701Ssam } 837701Ssam } else 847701Ssam ip = namei(uchar, 0, 1); 856254Sroot if (ip == NULL) 866254Sroot return; 877701Ssam open1(ip, ++uap->flags, checkpermissions); 886254Sroot } 896254Sroot 907701Ssam #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)); 1087701Ssam if (ip == NULL) 1096254Sroot return; 1107701Ssam open1(ip, FWRITE, 0); 1116254Sroot } else 1127701Ssam open1(ip, FWRITE|FTRUNCATE, 0); 1136254Sroot } 1147701Ssam #endif 1156254Sroot 1166254Sroot /* 1176254Sroot * Common code for open and creat. 1187701Ssam * Check permissions (if we haven't done so already), 1197701Ssam * allocate an open file structure, and call 1207701Ssam * the device open routine, if any. 1216254Sroot */ 1227701Ssam open1(ip, mode, checkpermissions) 1236254Sroot register struct inode *ip; 1246254Sroot register mode; 1256254Sroot { 1266254Sroot register struct file *fp; 1277701Ssam int i, flags; 1286254Sroot 1297701Ssam if (checkpermissions) { 1306254Sroot if (mode&FREAD) 1317701Ssam if (access(ip, IREAD)) 1327701Ssam goto bad; 1336254Sroot if (mode&FWRITE) { 1347701Ssam if (access(ip, IWRITE)) 1357701Ssam goto bad; 1367701Ssam if ((ip->i_mode&IFMT) == IFDIR) { 1376254Sroot u.u_error = EISDIR; 1387701Ssam goto bad; 1397701Ssam } 1406254Sroot } 1416254Sroot } 1427701Ssam 1437701Ssam /* 1447701Ssam * Check locking on inode. Release "inode lock" 1457701Ssam * while doing so in case we block inside flocki. 1467701Ssam */ 1477701Ssam flags = 0; 1487701Ssam if (mode&(FRDLOCK|FWRLOCK)) { 1497701Ssam iunlock(ip); 1507701Ssam flags = flocki(ip, 0, mode); 1517701Ssam ilock(ip); 1527701Ssam if (u.u_error) 1537701Ssam goto bad; 1547142Smckusick } 1557701Ssam if (mode&FTRUNCATE) 1567701Ssam itrunc(ip, 0); 1577122Smckusick iunlock(ip); 1586254Sroot if ((fp = falloc()) == NULL) 1596254Sroot goto out; 1607701Ssam fp->f_flag = mode & FMODES; 1617505Sroot fp->f_type = DTYPE_FILE; 1626254Sroot i = u.u_r.r_val1; 1636254Sroot fp->f_inode = ip; 1648559Sroot u.u_error = openi(ip, mode); 1657701Ssam if (u.u_error == 0) { 1667701Ssam u.u_pofile[i] = flags; 1676254Sroot return; 1687701Ssam } 1696254Sroot u.u_ofile[i] = NULL; 1706254Sroot fp->f_count--; 1716254Sroot out: 1727142Smckusick irele(ip); 1737701Ssam return; 1747701Ssam bad: 1757701Ssam 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; 237*8673Sroot 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 } 2597142Smckusick irele(ip); 2606254Sroot } 2616254Sroot 2626254Sroot /* 2636254Sroot * symlink -- make a symbolic link 2646254Sroot */ 2656254Sroot symlink() 2666254Sroot { 2676254Sroot register struct a { 2686254Sroot char *target; 2696254Sroot char *linkname; 2706254Sroot } *uap; 2716254Sroot register struct inode *ip; 2726254Sroot register char *tp; 2736254Sroot register c, nc; 2746254Sroot 2756254Sroot uap = (struct a *)u.u_ap; 2766254Sroot tp = uap->target; 2776254Sroot nc = 0; 2786254Sroot while (c = fubyte(tp)) { 2796254Sroot if (c < 0) { 2806254Sroot u.u_error = EFAULT; 2816254Sroot return; 2826254Sroot } 2836254Sroot tp++; 2846254Sroot nc++; 2856254Sroot } 2866254Sroot u.u_dirp = uap->linkname; 2876254Sroot ip = namei(uchar, 1, 0); 2886254Sroot if (ip) { 2896254Sroot iput(ip); 2906254Sroot u.u_error = EEXIST; 2916254Sroot return; 2926254Sroot } 2936254Sroot if (u.u_error) 2946254Sroot return; 2956254Sroot ip = maknode(IFLNK | 0777); 2966254Sroot if (ip == NULL) 2976254Sroot return; 2987826Sroot u.u_error = rdwri(UIO_WRITE, ip, uap->target, nc, 0, 0, (int *)0); 2996254Sroot iput(ip); 3006254Sroot } 3016254Sroot 3026254Sroot /* 3036254Sroot * Unlink system call. 3046254Sroot * Hard to avoid races here, especially 3056254Sroot * in unlinking directories. 3066254Sroot */ 3076254Sroot unlink() 3086254Sroot { 3096254Sroot register struct inode *ip, *pp; 3106254Sroot struct a { 3116254Sroot char *fname; 3126254Sroot }; 3137142Smckusick int unlinkingdot = 0; 3146254Sroot 3156254Sroot pp = namei(uchar, 2, 0); 3167535Sroot if (pp == NULL) 3176254Sroot return; 3187439Sroot 3196254Sroot /* 3206254Sroot * Check for unlink(".") 3216254Sroot * to avoid hanging on the iget 3226254Sroot */ 3236254Sroot if (pp->i_number == u.u_dent.d_ino) { 3246254Sroot ip = pp; 3256254Sroot ip->i_count++; 3267142Smckusick unlinkingdot++; 3276254Sroot } else 3286574Smckusic ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino); 3296254Sroot if(ip == NULL) 3306254Sroot goto out1; 3316254Sroot if((ip->i_mode&IFMT)==IFDIR && !suser()) 3326254Sroot goto out; 3336254Sroot /* 3346254Sroot * Don't unlink a mounted file. 3356254Sroot */ 3366254Sroot if (ip->i_dev != pp->i_dev) { 3376254Sroot u.u_error = EBUSY; 3386254Sroot goto out; 3396254Sroot } 3406254Sroot if (ip->i_flag&ITEXT) 3416254Sroot xrele(ip); /* try once to free text */ 3427535Sroot if (dirremove()) { 3437535Sroot ip->i_nlink--; 3447535Sroot ip->i_flag |= ICHG; 3456254Sroot } 3466254Sroot out: 3477142Smckusick if (unlinkingdot) 3487142Smckusick irele(ip); 3497142Smckusick else 3507142Smckusick iput(ip); 3516254Sroot out1: 3526254Sroot iput(pp); 3536254Sroot } 3546254Sroot 3556254Sroot /* 3566254Sroot * Seek system call 3576254Sroot */ 3588040Sroot lseek() 3596254Sroot { 3606254Sroot register struct file *fp; 3616254Sroot register struct a { 3627701Ssam int fd; 3636254Sroot off_t off; 3646254Sroot int sbase; 3656254Sroot } *uap; 3666254Sroot 3676254Sroot uap = (struct a *)u.u_ap; 3687701Ssam fp = getf(uap->fd); 3696254Sroot if (fp == NULL) 3706254Sroot return; 3717505Sroot if (fp->f_type == DTYPE_SOCKET) { 3726254Sroot u.u_error = ESPIPE; 3736254Sroot return; 3746254Sroot } 3757701Ssam if (uap->sbase == FSEEK_RELATIVE) 3766254Sroot uap->off += fp->f_offset; 3777701Ssam else if (uap->sbase == FSEEK_EOF) 3786254Sroot uap->off += fp->f_inode->i_size; 3796254Sroot fp->f_offset = uap->off; 3806254Sroot u.u_r.r_off = uap->off; 3816254Sroot } 3826254Sroot 3836254Sroot /* 3846254Sroot * Access system call 3856254Sroot */ 3866254Sroot saccess() 3876254Sroot { 3886254Sroot register svuid, svgid; 3896254Sroot register struct inode *ip; 3906254Sroot register struct a { 3916254Sroot char *fname; 3926254Sroot int fmode; 3936254Sroot } *uap; 3946254Sroot 3956254Sroot uap = (struct a *)u.u_ap; 3966254Sroot svuid = u.u_uid; 3976254Sroot svgid = u.u_gid; 3986254Sroot u.u_uid = u.u_ruid; 3996254Sroot u.u_gid = u.u_rgid; 4006254Sroot ip = namei(uchar, 0, 1); 4016254Sroot if (ip != NULL) { 4027701Ssam if (uap->fmode&FACCESS_READ && access(ip, IREAD)) 4037701Ssam goto done; 4047701Ssam if (uap->fmode&FACCESS_WRITE && access(ip, IWRITE)) 4057701Ssam goto done; 4067701Ssam if (uap->fmode&FACCESS_EXECUTE && access(ip, IEXEC)) 4077701Ssam goto done; 4087701Ssam done: 4096254Sroot iput(ip); 4106254Sroot } 4116254Sroot u.u_uid = svuid; 4126254Sroot u.u_gid = svgid; 4136254Sroot } 4146254Sroot 4156254Sroot /* 41637Sbill * the fstat system call. 41737Sbill */ 41837Sbill fstat() 41937Sbill { 42037Sbill register struct file *fp; 42137Sbill register struct a { 4227701Ssam int fd; 42337Sbill struct stat *sb; 42437Sbill } *uap; 42537Sbill 42637Sbill uap = (struct a *)u.u_ap; 4277701Ssam fp = getf(uap->fd); 4284828Swnj if (fp == NULL) 42937Sbill return; 4307505Sroot if (fp->f_type == DTYPE_SOCKET) 4314891Swnj u.u_error = sostat(fp->f_socket, uap->sb); 4324828Swnj else 4334828Swnj stat1(fp->f_inode, uap->sb); 43437Sbill } 43537Sbill 43637Sbill /* 4376574Smckusic * Stat system call. This version follows links. 43837Sbill */ 43937Sbill stat() 44037Sbill { 44137Sbill register struct inode *ip; 44237Sbill register struct a { 44337Sbill char *fname; 44437Sbill struct stat *sb; 44537Sbill } *uap; 44637Sbill 44737Sbill uap = (struct a *)u.u_ap; 4486423Sroot ip = namei(uchar, 0, 1); 4494828Swnj if (ip == NULL) 45037Sbill return; 4513624Sroot stat1(ip, uap->sb); 45237Sbill iput(ip); 45337Sbill } 45437Sbill 45537Sbill /* 4566574Smckusic * Lstat system call. This version does not follow links. 4575992Swnj */ 4585992Swnj lstat() 4595992Swnj { 4605992Swnj register struct inode *ip; 4615992Swnj register struct a { 4625992Swnj char *fname; 4635992Swnj struct stat *sb; 4645992Swnj } *uap; 4655992Swnj 4665992Swnj uap = (struct a *)u.u_ap; 4676423Sroot ip = namei(uchar, 0, 0); 4685992Swnj if (ip == NULL) 4695992Swnj return; 4706153Ssam stat1(ip, uap->sb); 4715992Swnj iput(ip); 4725992Swnj } 4735992Swnj 4745992Swnj /* 47537Sbill * The basic routine for fstat and stat: 47637Sbill * get the inode and pass appropriate parts back. 47737Sbill */ 4783624Sroot stat1(ip, ub) 4794828Swnj register struct inode *ip; 4804828Swnj struct stat *ub; 48137Sbill { 48237Sbill struct stat ds; 48337Sbill 484*8673Sroot IUPDAT(ip, &time, &time, 0); 48537Sbill /* 4867023Smckusick * Copy from inode table 48737Sbill */ 48837Sbill ds.st_dev = ip->i_dev; 48937Sbill ds.st_ino = ip->i_number; 49037Sbill ds.st_mode = ip->i_mode; 49137Sbill ds.st_nlink = ip->i_nlink; 49237Sbill ds.st_uid = ip->i_uid; 49337Sbill ds.st_gid = ip->i_gid; 4946574Smckusic ds.st_rdev = (dev_t)ip->i_rdev; 4953624Sroot ds.st_size = ip->i_size; 4966574Smckusic ds.st_atime = ip->i_atime; 4976574Smckusic ds.st_mtime = ip->i_mtime; 4986574Smckusic ds.st_ctime = ip->i_ctime; 4997701Ssam /* this doesn't belong here */ 5007701Ssam if ((ip->i_mode&IFMT) == IFBLK) 5017701Ssam ds.st_blksize = BLKDEV_IOSIZE; 5027701Ssam else if ((ip->i_mode&IFMT) == IFCHR) 5037701Ssam ds.st_blksize = MAXBSIZE; 5047701Ssam else 5057701Ssam ds.st_blksize = ip->i_fs->fs_bsize; 50637Sbill if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 50737Sbill u.u_error = EFAULT; 50837Sbill } 50937Sbill 51037Sbill /* 5115992Swnj * Return target name of a symbolic link 51237Sbill */ 5135992Swnj readlink() 5145992Swnj { 5155992Swnj register struct inode *ip; 5165992Swnj register struct a { 5175992Swnj char *name; 5185992Swnj char *buf; 5195992Swnj int count; 5207826Sroot } *uap = (struct a *)u.u_ap; 5217826Sroot int resid; 5225992Swnj 5235992Swnj ip = namei(uchar, 0, 0); 5245992Swnj if (ip == NULL) 5255992Swnj return; 5265992Swnj if ((ip->i_mode&IFMT) != IFLNK) { 5275992Swnj u.u_error = ENXIO; 5285992Swnj goto out; 5295992Swnj } 5307826Sroot u.u_error = rdwri(UIO_READ, ip, uap->buf, uap->count, 0, 0, &resid); 5315992Swnj out: 5325992Swnj iput(ip); 5337826Sroot u.u_r.r_val1 = uap->count - resid; 5345992Swnj } 5355992Swnj 5366254Sroot chmod() 5375992Swnj { 5387701Ssam struct inode *ip; 5397701Ssam struct a { 5406254Sroot char *fname; 5416254Sroot int fmode; 5425992Swnj } *uap; 5435992Swnj 5445992Swnj uap = (struct a *)u.u_ap; 5456254Sroot if ((ip = owner(1)) == NULL) 5465992Swnj return; 5477701Ssam chmod1(ip, uap->fmode); 5487701Ssam } 5497439Sroot 5507701Ssam fchmod() 5517701Ssam { 5527701Ssam struct a { 5537701Ssam int fd; 5547701Ssam int fmode; 5557701Ssam } *uap; 5567701Ssam register struct inode *ip; 5577701Ssam register struct file *fp; 5587701Ssam 5597701Ssam uap = (struct a *)u.u_ap; 5607701Ssam fp = getf(uap->fd); 5617701Ssam if (fp == NULL) 5627701Ssam return; 5637701Ssam if (fp->f_type == DTYPE_SOCKET) { 5647701Ssam u.u_error = EINVAL; 5657701Ssam return; 5667439Sroot } 5677701Ssam ip = fp->f_inode; 5687701Ssam ilock(ip); 5697701Ssam if (u.u_uid != ip->i_uid && !suser()) { 5707701Ssam iunlock(ip); 5717701Ssam return; 5727701Ssam } 5737701Ssam chmod1(ip, uap->fmode); 5747701Ssam } 5757701Ssam 5767701Ssam chmod1(ip, mode) 5777701Ssam register struct inode *ip; 5787701Ssam register int mode; 5797701Ssam { 5807868Sroot register int *gp; 5817868Sroot 5826254Sroot ip->i_mode &= ~07777; 5837439Sroot if (u.u_uid) { 5847701Ssam mode &= ~ISVTX; 5857868Sroot for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++) 5867868Sroot if (*gp == ip->i_gid) 5877868Sroot goto ok; 5887868Sroot mode &= ~ISGID; 5897868Sroot ok: 5907868Sroot ; 5917701Ssam #ifdef MUSH 5927482Skre if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 && 5937482Skre (ip->i_mode & IFMT) != IFCHR) 5947701Ssam mode &= ~u.u_cmask; 5957482Skre #endif 5967439Sroot } 5977701Ssam ip->i_mode |= mode&07777; 5986254Sroot ip->i_flag |= ICHG; 5996254Sroot if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 6006254Sroot xrele(ip); 6015992Swnj iput(ip); 6025992Swnj } 6035992Swnj 6046254Sroot chown() 60537Sbill { 6067701Ssam struct inode *ip; 6077701Ssam struct a { 6086254Sroot char *fname; 6096254Sroot int uid; 6106254Sroot int gid; 61137Sbill } *uap; 61237Sbill 61337Sbill uap = (struct a *)u.u_ap; 6146254Sroot if (!suser() || (ip = owner(0)) == NULL) 61537Sbill return; 6167701Ssam chown1(ip, uap->uid, uap->gid); 6177701Ssam } 6187439Sroot 6197701Ssam fchown() 6207701Ssam { 6217701Ssam struct a { 6227701Ssam int fd; 6237701Ssam int uid; 6247701Ssam int gid; 6257701Ssam } *uap; 6267701Ssam register struct inode *ip; 6277701Ssam register struct file *fp; 6287701Ssam 6297701Ssam uap = (struct a *)u.u_ap; 6307701Ssam fp = getf(uap->fd); 6317701Ssam if (fp == NULL) 6327701Ssam return; 6337701Ssam if (fp->f_type == DTYPE_SOCKET) { 6347701Ssam u.u_error = EINVAL; 6357701Ssam return; 6367439Sroot } 6377701Ssam ip = fp->f_inode; 6387701Ssam ilock(ip); 6397701Ssam if (!suser()) { 6407701Ssam iunlock(ip); 6417701Ssam return; 6427701Ssam } 6437701Ssam chown1(ip, uap->uid, uap->gid); 6447701Ssam } 6457701Ssam 6467701Ssam /* 6477701Ssam * Perform chown operation on inode ip; 6487701Ssam * inode must be locked prior to call. 6497701Ssam */ 6507701Ssam chown1(ip, uid, gid) 6517701Ssam register struct inode *ip; 6527701Ssam int uid, gid; 6537701Ssam { 6547701Ssam #ifdef QUOTA 6557701Ssam register long change; 6567701Ssam 6577439Sroot /* 6587482Skre * This doesn't allow for holes in files (which hopefully don't 6597482Skre * happen often in files that we chown), and is not accurate anyway 6607482Skre * (eg: it totally ignores 3 level indir blk files - but hopefully 6617482Skre * noone who can make a file that big will have a quota) 6627482Skre */ 6637701Ssam if (ip->i_uid == uid) 6647482Skre change = 0; 6657482Skre else { 6667482Skre register struct fs *fs = ip->i_fs; 6677482Skre 6687482Skre if (ip->i_size > (change = NDADDR * fs->fs_bsize)) { 6697482Skre register off_t size; 6707482Skre 6717482Skre size = blkroundup(fs, ip->i_size) - change; 6727482Skre change += size; 6737482Skre change += fs->fs_bsize; 6747701Ssam /* this assumes NIADDR <= 2 */ 6757482Skre if (size > NINDIR(fs) * fs->fs_bsize) 6767482Skre change += fs->fs_bsize; 6777482Skre } else 6787482Skre change = fragroundup(fs, ip->i_size); 6797482Skre change /= DEV_BSIZE; 6807482Skre } 6817482Skre chkdq(ip, -change, 1); 6827482Skre chkiq(ip->i_dev, ip, ip->i_uid, 1); 6837482Skre dqrele(ip->i_dquot); 6847482Skre #endif 6857482Skre /* 6867701Ssam * keep uid/gid's in sane range -- no err, 6877701Ssam * so chown(file, uid, -1) will do something useful 6887439Sroot */ 6897701Ssam if (uid >= 0 && uid <= 32767) /* should have a constant */ 6907701Ssam ip->i_uid = uid; 6917701Ssam if (gid >= 0 && gid <= 32767) /* same here */ 6927701Ssam ip->i_gid = gid; 6936254Sroot ip->i_flag |= ICHG; 6946254Sroot if (u.u_ruid != 0) 6956254Sroot ip->i_mode &= ~(ISUID|ISGID); 6967701Ssam #ifdef QUOTA 6977482Skre ip->i_dquot = inoquota(ip); 6987482Skre chkdq(ip, change, 1); 6997701Ssam chkiq(ip->i_dev, NULL, uid, 1); 7007482Skre #endif 7016254Sroot iput(ip); 70237Sbill } 70337Sbill 70437Sbill /* 7056254Sroot * Set IUPD and IACC times on file. 7066254Sroot * Can't set ICHG. 70737Sbill */ 7088107Sroot outime() 7094828Swnj { 71037Sbill register struct a { 7116254Sroot char *fname; 7126254Sroot time_t *tptr; 71337Sbill } *uap; 7146254Sroot register struct inode *ip; 7156254Sroot time_t tv[2]; 7168632Sroot struct timeval tv0, tv1; 71737Sbill 71837Sbill uap = (struct a *)u.u_ap; 7196254Sroot if ((ip = owner(1)) == NULL) 72037Sbill return; 7216254Sroot if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { 7226254Sroot u.u_error = EFAULT; 7236254Sroot } else { 7246254Sroot ip->i_flag |= IACC|IUPD|ICHG; 7258632Sroot tv0.tv_sec = tv[0]; tv0.tv_usec = 0; 7268632Sroot tv1.tv_sec = tv[1]; tv1.tv_usec = 0; 7278632Sroot iupdat(ip, &tv0, &tv1, 0); 72837Sbill } 72937Sbill iput(ip); 73037Sbill } 73137Sbill 7326254Sroot sync() 73337Sbill { 73437Sbill 735*8673Sroot update(); 73637Sbill } 7377535Sroot 7387701Ssam flock() 7397701Ssam { 7407701Ssam struct a { 7417701Ssam int fd; 7427701Ssam int how; 7437701Ssam } *uap; 7447701Ssam register struct file *fp; 7457701Ssam register int cmd, flags; 7467701Ssam 7477701Ssam uap = (struct a *)u.u_ap; 7487701Ssam fp = getf(uap->fd); 7497701Ssam if (fp == NULL) 7507701Ssam return; 7517701Ssam if (fp->f_type == DTYPE_SOCKET) { /* XXX */ 7527701Ssam u.u_error = EINVAL; 7537701Ssam return; 7547701Ssam } 7557701Ssam cmd = uap->how; 7567701Ssam flags = u.u_pofile[uap->fd] & (RDLOCK|WRLOCK); 7577701Ssam if (cmd&FUNLOCK) { 7587701Ssam if (flags == 0) { 7597701Ssam u.u_error = EINVAL; 7607701Ssam return; 7617701Ssam } 7627701Ssam funlocki(fp->f_inode, flags); 7637701Ssam u.u_pofile[uap->fd] &= ~(RDLOCK|WRLOCK); 7647701Ssam return; 7657701Ssam } 7667701Ssam /* 7677701Ssam * No reason to write lock a file we've already 7687701Ssam * write locked, similarly with a read lock. 7697701Ssam */ 7707701Ssam if ((flags&WRLOCK) && (cmd&FWRLOCK) || 7717701Ssam (flags&RDLOCK) && (cmd&FRDLOCK)) 7727701Ssam return; 7737701Ssam u.u_pofile[uap->fd] = flocki(fp->f_inode, u.u_pofile[uap->fd], cmd); 7747701Ssam } 7757701Ssam 7767701Ssam truncate() 7777701Ssam { 7787701Ssam struct a { 7797701Ssam char *fname; 7807701Ssam int length; 7817826Sroot } *uap = (struct a *)u.u_ap; 7827701Ssam struct inode *ip; 7837701Ssam 7847701Ssam ip = namei(uchar, 0, 1); 7857701Ssam if (ip == NULL) 7867701Ssam return; 7877701Ssam if (access(ip, IWRITE)) 7887701Ssam goto bad; 7897701Ssam if ((ip->i_mode&IFMT) == IFDIR) { 7907701Ssam u.u_error = EISDIR; 7917701Ssam goto bad; 7927701Ssam } 7937701Ssam itrunc(ip, uap->length); 7947701Ssam return; 7957701Ssam bad: 7967701Ssam iput(ip); 7977701Ssam } 7987701Ssam 7997701Ssam ftruncate() 8007701Ssam { 8017701Ssam struct a { 8027701Ssam int fd; 8037701Ssam int length; 8047826Sroot } *uap = (struct a *)u.u_ap; 8057701Ssam struct inode *ip; 8067701Ssam struct file *fp; 8077701Ssam 8087701Ssam fp = getf(uap->fd); 8097701Ssam if (fp == NULL) 8107701Ssam return; 8117701Ssam if (fp->f_type == DTYPE_SOCKET) { 8127701Ssam u.u_error = EINVAL; 8137701Ssam return; 8147701Ssam } 8157701Ssam if ((fp->f_flag&FWRITE) == 0) { 8167701Ssam u.u_error = EINVAL; 8177701Ssam return; 8187701Ssam } 8197701Ssam ip = fp->f_inode; 8207701Ssam ilock(ip); 8217701Ssam itrunc(ip, uap->length); 8227701Ssam } 8237701Ssam 8247701Ssam rename() 8257701Ssam { 8267826Sroot #ifdef notdef 8277701Ssam struct a { 8287701Ssam char *from; 8297701Ssam char *to; 8307701Ssam } *uap; 8317826Sroot #endif 8327701Ssam 8337701Ssam } 8347701Ssam 8357535Sroot /* 8367535Sroot * Make a new file. 8377535Sroot */ 8387535Sroot struct inode * 8397535Sroot maknode(mode) 8407535Sroot int mode; 8417535Sroot { 8427535Sroot register struct inode *ip; 8437535Sroot ino_t ipref; 8447535Sroot 8457535Sroot if ((mode & IFMT) == IFDIR) 8467535Sroot ipref = dirpref(u.u_pdir->i_fs); 8477535Sroot else 8487535Sroot ipref = u.u_pdir->i_number; 8497535Sroot ip = ialloc(u.u_pdir, ipref, mode); 8507535Sroot if (ip == NULL) { 8517535Sroot iput(u.u_pdir); 8527701Ssam return (NULL); 8537535Sroot } 8547701Ssam #ifdef QUOTA 8557535Sroot if (ip->i_dquot != NODQUOT) 8567535Sroot panic("maknode: dquot"); 8577535Sroot #endif 8587535Sroot ip->i_flag |= IACC|IUPD|ICHG; 8597535Sroot if ((mode & IFMT) == 0) 8607535Sroot mode |= IFREG; 8617535Sroot ip->i_mode = mode & ~u.u_cmask; 8627535Sroot ip->i_nlink = 1; 8637535Sroot ip->i_uid = u.u_uid; 8647535Sroot ip->i_gid = u.u_pdir->i_gid; 8657701Ssam #ifdef QUOTA 8667535Sroot ip->i_dquot = inoquota(ip); 8677535Sroot #endif 8687535Sroot 8697535Sroot /* 8707535Sroot * Make sure inode goes to disk before directory entry. 8717535Sroot */ 872*8673Sroot iupdat(ip, &time, &time, 1); 8737535Sroot direnter(ip); 8747535Sroot if (u.u_error) { 8757535Sroot /* 8767535Sroot * write error occurred trying to update directory 8777535Sroot * so must deallocate the inode 8787535Sroot */ 8797535Sroot ip->i_nlink = 0; 8807535Sroot ip->i_flag |= ICHG; 8817535Sroot iput(ip); 8827701Ssam return (NULL); 8837535Sroot } 8847701Ssam return (ip); 8857535Sroot } 886