1*8040Sroot /* vfs_syscalls.c 4.36 82/09/04 */ 237Sbill 337Sbill #include "../h/param.h" 437Sbill #include "../h/systm.h" 537Sbill #include "../h/dir.h" 637Sbill #include "../h/user.h" 7*8040Sroot #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" 146254Sroot #include "../h/inline.h" 157701Ssam /* no reason to inline expand these guys here */ 167701Ssam #undef ilock 177701Ssam #undef iunlock 187482Skre #include "../h/quota.h" 197505Sroot #include "../h/descrip.h" 207826Sroot #include "../h/uio.h" 217826Sroot #include "../h/socket.h" 2237Sbill 236254Sroot chdir() 246254Sroot { 256254Sroot 266254Sroot chdirec(&u.u_cdir); 276254Sroot } 286254Sroot 296254Sroot chroot() 306254Sroot { 316254Sroot 326254Sroot if (suser()) 336254Sroot chdirec(&u.u_rdir); 346254Sroot } 356254Sroot 366254Sroot chdirec(ipp) 377701Ssam register struct inode **ipp; 386254Sroot { 396254Sroot register struct inode *ip; 406254Sroot struct a { 416254Sroot char *fname; 426254Sroot }; 436254Sroot 446254Sroot ip = namei(uchar, 0, 1); 456254Sroot if(ip == NULL) 466254Sroot return; 476254Sroot if((ip->i_mode&IFMT) != IFDIR) { 486254Sroot u.u_error = ENOTDIR; 496254Sroot goto bad; 506254Sroot } 516254Sroot if(access(ip, IEXEC)) 526254Sroot goto bad; 537122Smckusick iunlock(ip); 547142Smckusick if (*ipp) 557142Smckusick irele(*ipp); 566254Sroot *ipp = ip; 576254Sroot return; 586254Sroot 596254Sroot bad: 606254Sroot iput(ip); 616254Sroot } 626254Sroot 6337Sbill /* 646254Sroot * Open system call. 656254Sroot */ 666254Sroot open() 676254Sroot { 686254Sroot register struct inode *ip; 696254Sroot register struct a { 706254Sroot char *fname; 717701Ssam int flags; 727701Ssam int mode; 736254Sroot } *uap; 747701Ssam int checkpermissions = 1; 756254Sroot 766254Sroot uap = (struct a *)u.u_ap; 777701Ssam if (uap->flags&FCREATE) { 787701Ssam ip = namei(uchar, 1, 1); 797701Ssam if (ip == NULL) { 807701Ssam if (u.u_error) 817701Ssam return; 827701Ssam ip = maknode(uap->mode&07777&(~ISVTX)); 837701Ssam checkpermissions = 0; 847701Ssam uap->flags &= ~FTRUNCATE; 857701Ssam } 867701Ssam } else 877701Ssam ip = namei(uchar, 0, 1); 886254Sroot if (ip == NULL) 896254Sroot return; 907701Ssam open1(ip, ++uap->flags, checkpermissions); 916254Sroot } 926254Sroot 937701Ssam #ifndef NOCOMPAT 946254Sroot /* 956254Sroot * Creat system call. 966254Sroot */ 977505Sroot ocreat() 986254Sroot { 996254Sroot register struct inode *ip; 1006254Sroot register struct a { 1016254Sroot char *fname; 1026254Sroot int fmode; 1036254Sroot } *uap; 1046254Sroot 1056254Sroot uap = (struct a *)u.u_ap; 1066254Sroot ip = namei(uchar, 1, 1); 1076254Sroot if (ip == NULL) { 1086254Sroot if (u.u_error) 1096254Sroot return; 1106254Sroot ip = maknode(uap->fmode&07777&(~ISVTX)); 1117701Ssam if (ip == NULL) 1126254Sroot return; 1137701Ssam open1(ip, FWRITE, 0); 1146254Sroot } else 1157701Ssam open1(ip, FWRITE|FTRUNCATE, 0); 1166254Sroot } 1177701Ssam #endif 1186254Sroot 1196254Sroot /* 1206254Sroot * Common code for open and creat. 1217701Ssam * Check permissions (if we haven't done so already), 1227701Ssam * allocate an open file structure, and call 1237701Ssam * the device open routine, if any. 1246254Sroot */ 1257701Ssam open1(ip, mode, checkpermissions) 1266254Sroot register struct inode *ip; 1276254Sroot register mode; 1286254Sroot { 1296254Sroot register struct file *fp; 1307701Ssam int i, flags; 1316254Sroot 1327701Ssam if (checkpermissions) { 1336254Sroot if (mode&FREAD) 1347701Ssam if (access(ip, IREAD)) 1357701Ssam goto bad; 1366254Sroot if (mode&FWRITE) { 1377701Ssam if (access(ip, IWRITE)) 1387701Ssam goto bad; 1397701Ssam if ((ip->i_mode&IFMT) == IFDIR) { 1406254Sroot u.u_error = EISDIR; 1417701Ssam goto bad; 1427701Ssam } 1436254Sroot } 1446254Sroot } 1457701Ssam 1467701Ssam /* 1477701Ssam * Check locking on inode. Release "inode lock" 1487701Ssam * while doing so in case we block inside flocki. 1497701Ssam */ 1507701Ssam flags = 0; 1517701Ssam if (mode&(FRDLOCK|FWRLOCK)) { 1527701Ssam iunlock(ip); 1537701Ssam flags = flocki(ip, 0, mode); 1547701Ssam ilock(ip); 1557701Ssam if (u.u_error) 1567701Ssam goto bad; 1577142Smckusick } 1587701Ssam if (mode&FTRUNCATE) 1597701Ssam itrunc(ip, 0); 1607122Smckusick iunlock(ip); 1616254Sroot if ((fp = falloc()) == NULL) 1626254Sroot goto out; 1637701Ssam fp->f_flag = mode & FMODES; 1647505Sroot fp->f_type = DTYPE_FILE; 1656254Sroot i = u.u_r.r_val1; 1666254Sroot fp->f_inode = ip; 1677701Ssam openi(ip, mode); 1687701Ssam if (u.u_error == 0) { 1697701Ssam u.u_pofile[i] = flags; 1706254Sroot return; 1717701Ssam } 1726254Sroot u.u_ofile[i] = NULL; 1736254Sroot fp->f_count--; 1746254Sroot out: 1757142Smckusick irele(ip); 1767701Ssam return; 1777701Ssam bad: 1787701Ssam iput(ip); 1796254Sroot } 1806254Sroot 1816254Sroot /* 1826254Sroot * Mknod system call 1836254Sroot */ 1846254Sroot mknod() 1856254Sroot { 1866254Sroot register struct inode *ip; 1876254Sroot register struct a { 1886254Sroot char *fname; 1896254Sroot int fmode; 1906254Sroot int dev; 1916254Sroot } *uap; 1926254Sroot 1936254Sroot uap = (struct a *)u.u_ap; 1946254Sroot if (suser()) { 1956254Sroot ip = namei(uchar, 1, 0); 1966254Sroot if (ip != NULL) { 1976254Sroot u.u_error = EEXIST; 1986254Sroot goto out; 1996254Sroot } 2006254Sroot } 2016254Sroot if (u.u_error) 2026254Sroot return; 2036254Sroot ip = maknode(uap->fmode); 2046254Sroot if (ip == NULL) 2056254Sroot return; 2066254Sroot if (uap->dev) { 2076254Sroot /* 2086254Sroot * Want to be able to use this to make badblock 2096254Sroot * inodes, so don't truncate the dev number. 2106254Sroot */ 2116574Smckusic ip->i_rdev = uap->dev; 2126254Sroot ip->i_flag |= IACC|IUPD|ICHG; 2136254Sroot } 2146254Sroot 2156254Sroot out: 2166254Sroot iput(ip); 2176254Sroot } 2186254Sroot 2196254Sroot /* 2206254Sroot * link system call 2216254Sroot */ 2226254Sroot link() 2236254Sroot { 2246254Sroot register struct inode *ip, *xp; 2256254Sroot register struct a { 2266254Sroot char *target; 2276254Sroot char *linkname; 2286254Sroot } *uap; 2296254Sroot 2306254Sroot uap = (struct a *)u.u_ap; 2316254Sroot ip = namei(uchar, 0, 1); /* well, this routine is doomed anyhow */ 2326254Sroot if (ip == NULL) 2336254Sroot return; 2347439Sroot if ((ip->i_mode&IFMT)==IFDIR && !suser()) { 2357439Sroot iput(ip); 2367439Sroot return; 2377439Sroot } 2386254Sroot ip->i_nlink++; 2396254Sroot ip->i_flag |= ICHG; 240*8040Sroot iupdat(ip, &time.tv_sec, &time.tv_sec, 1); 2417122Smckusick iunlock(ip); 2426254Sroot u.u_dirp = (caddr_t)uap->linkname; 2436254Sroot xp = namei(uchar, 1, 0); 2446254Sroot if (xp != NULL) { 2456254Sroot u.u_error = EEXIST; 2466254Sroot iput(xp); 2476254Sroot goto out; 2486254Sroot } 2496254Sroot if (u.u_error) 2506254Sroot goto out; 2516254Sroot if (u.u_pdir->i_dev != ip->i_dev) { 2526254Sroot iput(u.u_pdir); 2536254Sroot u.u_error = EXDEV; 2546254Sroot goto out; 2556254Sroot } 2567535Sroot direnter(ip); 2576254Sroot out: 2586254Sroot if (u.u_error) { 2596254Sroot ip->i_nlink--; 2606254Sroot ip->i_flag |= ICHG; 2616254Sroot } 2627142Smckusick irele(ip); 2636254Sroot } 2646254Sroot 2656254Sroot /* 2666254Sroot * symlink -- make a symbolic link 2676254Sroot */ 2686254Sroot symlink() 2696254Sroot { 2706254Sroot register struct a { 2716254Sroot char *target; 2726254Sroot char *linkname; 2736254Sroot } *uap; 2746254Sroot register struct inode *ip; 2756254Sroot register char *tp; 2766254Sroot register c, nc; 2776254Sroot 2786254Sroot uap = (struct a *)u.u_ap; 2796254Sroot tp = uap->target; 2806254Sroot nc = 0; 2816254Sroot while (c = fubyte(tp)) { 2826254Sroot if (c < 0) { 2836254Sroot u.u_error = EFAULT; 2846254Sroot return; 2856254Sroot } 2866254Sroot tp++; 2876254Sroot nc++; 2886254Sroot } 2896254Sroot u.u_dirp = uap->linkname; 2906254Sroot ip = namei(uchar, 1, 0); 2916254Sroot if (ip) { 2926254Sroot iput(ip); 2936254Sroot u.u_error = EEXIST; 2946254Sroot return; 2956254Sroot } 2966254Sroot if (u.u_error) 2976254Sroot return; 2986254Sroot ip = maknode(IFLNK | 0777); 2996254Sroot if (ip == NULL) 3006254Sroot return; 3017826Sroot u.u_error = rdwri(UIO_WRITE, ip, uap->target, nc, 0, 0, (int *)0); 3026254Sroot iput(ip); 3036254Sroot } 3046254Sroot 3056254Sroot /* 3066254Sroot * Unlink system call. 3076254Sroot * Hard to avoid races here, especially 3086254Sroot * in unlinking directories. 3096254Sroot */ 3106254Sroot unlink() 3116254Sroot { 3126254Sroot register struct inode *ip, *pp; 3136254Sroot struct a { 3146254Sroot char *fname; 3156254Sroot }; 3167142Smckusick int unlinkingdot = 0; 3176254Sroot 3186254Sroot pp = namei(uchar, 2, 0); 3197535Sroot if (pp == NULL) 3206254Sroot return; 3217439Sroot 3226254Sroot /* 3236254Sroot * Check for unlink(".") 3246254Sroot * to avoid hanging on the iget 3256254Sroot */ 3266254Sroot if (pp->i_number == u.u_dent.d_ino) { 3276254Sroot ip = pp; 3286254Sroot ip->i_count++; 3297142Smckusick unlinkingdot++; 3306254Sroot } else 3316574Smckusic ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino); 3326254Sroot if(ip == NULL) 3336254Sroot goto out1; 3346254Sroot if((ip->i_mode&IFMT)==IFDIR && !suser()) 3356254Sroot goto out; 3366254Sroot /* 3376254Sroot * Don't unlink a mounted file. 3386254Sroot */ 3396254Sroot if (ip->i_dev != pp->i_dev) { 3406254Sroot u.u_error = EBUSY; 3416254Sroot goto out; 3426254Sroot } 3436254Sroot if (ip->i_flag&ITEXT) 3446254Sroot xrele(ip); /* try once to free text */ 3457535Sroot if (dirremove()) { 3467535Sroot ip->i_nlink--; 3477535Sroot ip->i_flag |= ICHG; 3486254Sroot } 3496254Sroot out: 3507142Smckusick if (unlinkingdot) 3517142Smckusick irele(ip); 3527142Smckusick else 3537142Smckusick iput(ip); 3546254Sroot out1: 3556254Sroot iput(pp); 3566254Sroot } 3576254Sroot 3586254Sroot /* 3596254Sroot * Seek system call 3606254Sroot */ 361*8040Sroot lseek() 3626254Sroot { 3636254Sroot register struct file *fp; 3646254Sroot register struct a { 3657701Ssam int fd; 3666254Sroot off_t off; 3676254Sroot int sbase; 3686254Sroot } *uap; 3696254Sroot 3706254Sroot uap = (struct a *)u.u_ap; 3717701Ssam fp = getf(uap->fd); 3726254Sroot if (fp == NULL) 3736254Sroot return; 3747505Sroot if (fp->f_type == DTYPE_SOCKET) { 3756254Sroot u.u_error = ESPIPE; 3766254Sroot return; 3776254Sroot } 3787701Ssam if (uap->sbase == FSEEK_RELATIVE) 3796254Sroot uap->off += fp->f_offset; 3807701Ssam else if (uap->sbase == FSEEK_EOF) 3816254Sroot uap->off += fp->f_inode->i_size; 3826254Sroot fp->f_offset = uap->off; 3836254Sroot u.u_r.r_off = uap->off; 3846254Sroot } 3856254Sroot 3866254Sroot /* 3876254Sroot * Access system call 3886254Sroot */ 3896254Sroot saccess() 3906254Sroot { 3916254Sroot register svuid, svgid; 3926254Sroot register struct inode *ip; 3936254Sroot register struct a { 3946254Sroot char *fname; 3956254Sroot int fmode; 3966254Sroot } *uap; 3976254Sroot 3986254Sroot uap = (struct a *)u.u_ap; 3996254Sroot svuid = u.u_uid; 4006254Sroot svgid = u.u_gid; 4016254Sroot u.u_uid = u.u_ruid; 4026254Sroot u.u_gid = u.u_rgid; 4036254Sroot ip = namei(uchar, 0, 1); 4046254Sroot if (ip != NULL) { 4057701Ssam if (uap->fmode&FACCESS_READ && access(ip, IREAD)) 4067701Ssam goto done; 4077701Ssam if (uap->fmode&FACCESS_WRITE && access(ip, IWRITE)) 4087701Ssam goto done; 4097701Ssam if (uap->fmode&FACCESS_EXECUTE && access(ip, IEXEC)) 4107701Ssam goto done; 4117701Ssam done: 4126254Sroot iput(ip); 4136254Sroot } 4146254Sroot u.u_uid = svuid; 4156254Sroot u.u_gid = svgid; 4166254Sroot } 4176254Sroot 4186254Sroot /* 41937Sbill * the fstat system call. 42037Sbill */ 42137Sbill fstat() 42237Sbill { 42337Sbill register struct file *fp; 42437Sbill register struct a { 4257701Ssam int fd; 42637Sbill struct stat *sb; 42737Sbill } *uap; 42837Sbill 42937Sbill uap = (struct a *)u.u_ap; 4307701Ssam fp = getf(uap->fd); 4314828Swnj if (fp == NULL) 43237Sbill return; 4337505Sroot if (fp->f_type == DTYPE_SOCKET) 4344891Swnj u.u_error = sostat(fp->f_socket, uap->sb); 4354828Swnj else 4364828Swnj stat1(fp->f_inode, uap->sb); 43737Sbill } 43837Sbill 43937Sbill /* 4406574Smckusic * Stat system call. This version follows links. 44137Sbill */ 44237Sbill stat() 44337Sbill { 44437Sbill register struct inode *ip; 44537Sbill register struct a { 44637Sbill char *fname; 44737Sbill struct stat *sb; 44837Sbill } *uap; 44937Sbill 45037Sbill uap = (struct a *)u.u_ap; 4516423Sroot ip = namei(uchar, 0, 1); 4524828Swnj if (ip == NULL) 45337Sbill return; 4543624Sroot stat1(ip, uap->sb); 45537Sbill iput(ip); 45637Sbill } 45737Sbill 45837Sbill /* 4596574Smckusic * Lstat system call. This version does not follow links. 4605992Swnj */ 4615992Swnj lstat() 4625992Swnj { 4635992Swnj register struct inode *ip; 4645992Swnj register struct a { 4655992Swnj char *fname; 4665992Swnj struct stat *sb; 4675992Swnj } *uap; 4685992Swnj 4695992Swnj uap = (struct a *)u.u_ap; 4706423Sroot ip = namei(uchar, 0, 0); 4715992Swnj if (ip == NULL) 4725992Swnj return; 4736153Ssam stat1(ip, uap->sb); 4745992Swnj iput(ip); 4755992Swnj } 4765992Swnj 4775992Swnj /* 47837Sbill * The basic routine for fstat and stat: 47937Sbill * get the inode and pass appropriate parts back. 48037Sbill */ 4813624Sroot stat1(ip, ub) 4824828Swnj register struct inode *ip; 4834828Swnj struct stat *ub; 48437Sbill { 48537Sbill struct stat ds; 48637Sbill 487*8040Sroot IUPDAT(ip, &time.tv_sec, &time.tv_sec, 0); 48837Sbill /* 4897023Smckusick * Copy from inode table 49037Sbill */ 49137Sbill ds.st_dev = ip->i_dev; 49237Sbill ds.st_ino = ip->i_number; 49337Sbill ds.st_mode = ip->i_mode; 49437Sbill ds.st_nlink = ip->i_nlink; 49537Sbill ds.st_uid = ip->i_uid; 49637Sbill ds.st_gid = ip->i_gid; 4976574Smckusic ds.st_rdev = (dev_t)ip->i_rdev; 4983624Sroot ds.st_size = ip->i_size; 4996574Smckusic ds.st_atime = ip->i_atime; 5006574Smckusic ds.st_mtime = ip->i_mtime; 5016574Smckusic ds.st_ctime = ip->i_ctime; 5027701Ssam /* this doesn't belong here */ 5037701Ssam if ((ip->i_mode&IFMT) == IFBLK) 5047701Ssam ds.st_blksize = BLKDEV_IOSIZE; 5057701Ssam else if ((ip->i_mode&IFMT) == IFCHR) 5067701Ssam ds.st_blksize = MAXBSIZE; 5077701Ssam else 5087701Ssam ds.st_blksize = ip->i_fs->fs_bsize; 50937Sbill if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 51037Sbill u.u_error = EFAULT; 51137Sbill } 51237Sbill 51337Sbill /* 5145992Swnj * Return target name of a symbolic link 51537Sbill */ 5165992Swnj readlink() 5175992Swnj { 5185992Swnj register struct inode *ip; 5195992Swnj register struct a { 5205992Swnj char *name; 5215992Swnj char *buf; 5225992Swnj int count; 5237826Sroot } *uap = (struct a *)u.u_ap; 5247826Sroot int resid; 5255992Swnj 5265992Swnj ip = namei(uchar, 0, 0); 5275992Swnj if (ip == NULL) 5285992Swnj return; 5295992Swnj if ((ip->i_mode&IFMT) != IFLNK) { 5305992Swnj u.u_error = ENXIO; 5315992Swnj goto out; 5325992Swnj } 5337826Sroot u.u_error = rdwri(UIO_READ, ip, uap->buf, uap->count, 0, 0, &resid); 5345992Swnj out: 5355992Swnj iput(ip); 5367826Sroot u.u_r.r_val1 = uap->count - resid; 5375992Swnj } 5385992Swnj 5396254Sroot chmod() 5405992Swnj { 5417701Ssam struct inode *ip; 5427701Ssam struct a { 5436254Sroot char *fname; 5446254Sroot int fmode; 5455992Swnj } *uap; 5465992Swnj 5475992Swnj uap = (struct a *)u.u_ap; 5486254Sroot if ((ip = owner(1)) == NULL) 5495992Swnj return; 5507701Ssam chmod1(ip, uap->fmode); 5517701Ssam } 5527439Sroot 5537701Ssam fchmod() 5547701Ssam { 5557701Ssam struct a { 5567701Ssam int fd; 5577701Ssam int fmode; 5587701Ssam } *uap; 5597701Ssam register struct inode *ip; 5607701Ssam register struct file *fp; 5617701Ssam 5627701Ssam uap = (struct a *)u.u_ap; 5637701Ssam fp = getf(uap->fd); 5647701Ssam if (fp == NULL) 5657701Ssam return; 5667701Ssam if (fp->f_type == DTYPE_SOCKET) { 5677701Ssam u.u_error = EINVAL; 5687701Ssam return; 5697439Sroot } 5707701Ssam ip = fp->f_inode; 5717701Ssam ilock(ip); 5727701Ssam if (u.u_uid != ip->i_uid && !suser()) { 5737701Ssam iunlock(ip); 5747701Ssam return; 5757701Ssam } 5767701Ssam chmod1(ip, uap->fmode); 5777701Ssam } 5787701Ssam 5797701Ssam chmod1(ip, mode) 5807701Ssam register struct inode *ip; 5817701Ssam register int mode; 5827701Ssam { 5837868Sroot register int *gp; 5847868Sroot 5856254Sroot ip->i_mode &= ~07777; 5867439Sroot if (u.u_uid) { 5877701Ssam mode &= ~ISVTX; 5887868Sroot for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++) 5897868Sroot if (*gp == ip->i_gid) 5907868Sroot goto ok; 5917868Sroot mode &= ~ISGID; 5927868Sroot ok: 5937868Sroot ; 5947701Ssam #ifdef MUSH 5957482Skre if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 && 5967482Skre (ip->i_mode & IFMT) != IFCHR) 5977701Ssam mode &= ~u.u_cmask; 5987482Skre #endif 5997439Sroot } 6007701Ssam ip->i_mode |= mode&07777; 6016254Sroot ip->i_flag |= ICHG; 6026254Sroot if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 6036254Sroot xrele(ip); 6045992Swnj iput(ip); 6055992Swnj } 6065992Swnj 6076254Sroot chown() 60837Sbill { 6097701Ssam struct inode *ip; 6107701Ssam struct a { 6116254Sroot char *fname; 6126254Sroot int uid; 6136254Sroot int gid; 61437Sbill } *uap; 61537Sbill 61637Sbill uap = (struct a *)u.u_ap; 6176254Sroot if (!suser() || (ip = owner(0)) == NULL) 61837Sbill return; 6197701Ssam chown1(ip, uap->uid, uap->gid); 6207701Ssam } 6217439Sroot 6227701Ssam fchown() 6237701Ssam { 6247701Ssam struct a { 6257701Ssam int fd; 6267701Ssam int uid; 6277701Ssam int gid; 6287701Ssam } *uap; 6297701Ssam register struct inode *ip; 6307701Ssam register struct file *fp; 6317701Ssam 6327701Ssam uap = (struct a *)u.u_ap; 6337701Ssam fp = getf(uap->fd); 6347701Ssam if (fp == NULL) 6357701Ssam return; 6367701Ssam if (fp->f_type == DTYPE_SOCKET) { 6377701Ssam u.u_error = EINVAL; 6387701Ssam return; 6397439Sroot } 6407701Ssam ip = fp->f_inode; 6417701Ssam ilock(ip); 6427701Ssam if (!suser()) { 6437701Ssam iunlock(ip); 6447701Ssam return; 6457701Ssam } 6467701Ssam chown1(ip, uap->uid, uap->gid); 6477701Ssam } 6487701Ssam 6497701Ssam /* 6507701Ssam * Perform chown operation on inode ip; 6517701Ssam * inode must be locked prior to call. 6527701Ssam */ 6537701Ssam chown1(ip, uid, gid) 6547701Ssam register struct inode *ip; 6557701Ssam int uid, gid; 6567701Ssam { 6577701Ssam #ifdef QUOTA 6587701Ssam register long change; 6597701Ssam 6607439Sroot /* 6617482Skre * This doesn't allow for holes in files (which hopefully don't 6627482Skre * happen often in files that we chown), and is not accurate anyway 6637482Skre * (eg: it totally ignores 3 level indir blk files - but hopefully 6647482Skre * noone who can make a file that big will have a quota) 6657482Skre */ 6667701Ssam if (ip->i_uid == uid) 6677482Skre change = 0; 6687482Skre else { 6697482Skre register struct fs *fs = ip->i_fs; 6707482Skre 6717482Skre if (ip->i_size > (change = NDADDR * fs->fs_bsize)) { 6727482Skre register off_t size; 6737482Skre 6747482Skre size = blkroundup(fs, ip->i_size) - change; 6757482Skre change += size; 6767482Skre change += fs->fs_bsize; 6777701Ssam /* this assumes NIADDR <= 2 */ 6787482Skre if (size > NINDIR(fs) * fs->fs_bsize) 6797482Skre change += fs->fs_bsize; 6807482Skre } else 6817482Skre change = fragroundup(fs, ip->i_size); 6827482Skre change /= DEV_BSIZE; 6837482Skre } 6847482Skre chkdq(ip, -change, 1); 6857482Skre chkiq(ip->i_dev, ip, ip->i_uid, 1); 6867482Skre dqrele(ip->i_dquot); 6877482Skre #endif 6887482Skre /* 6897701Ssam * keep uid/gid's in sane range -- no err, 6907701Ssam * so chown(file, uid, -1) will do something useful 6917439Sroot */ 6927701Ssam if (uid >= 0 && uid <= 32767) /* should have a constant */ 6937701Ssam ip->i_uid = uid; 6947701Ssam if (gid >= 0 && gid <= 32767) /* same here */ 6957701Ssam ip->i_gid = gid; 6966254Sroot ip->i_flag |= ICHG; 6976254Sroot if (u.u_ruid != 0) 6986254Sroot ip->i_mode &= ~(ISUID|ISGID); 6997701Ssam #ifdef QUOTA 7007482Skre ip->i_dquot = inoquota(ip); 7017482Skre chkdq(ip, change, 1); 7027701Ssam chkiq(ip->i_dev, NULL, uid, 1); 7037482Skre #endif 7046254Sroot iput(ip); 70537Sbill } 70637Sbill 70737Sbill /* 7086254Sroot * Set IUPD and IACC times on file. 7096254Sroot * Can't set ICHG. 71037Sbill */ 7116254Sroot utime() 7124828Swnj { 71337Sbill register struct a { 7146254Sroot char *fname; 7156254Sroot time_t *tptr; 71637Sbill } *uap; 7176254Sroot register struct inode *ip; 7186254Sroot time_t tv[2]; 71937Sbill 72037Sbill uap = (struct a *)u.u_ap; 7216254Sroot if ((ip = owner(1)) == NULL) 72237Sbill return; 7236254Sroot if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { 7246254Sroot u.u_error = EFAULT; 7256254Sroot } else { 7266254Sroot ip->i_flag |= IACC|IUPD|ICHG; 7276254Sroot iupdat(ip, &tv[0], &tv[1], 0); 72837Sbill } 72937Sbill iput(ip); 73037Sbill } 73137Sbill 7326254Sroot sync() 73337Sbill { 73437Sbill 7355416Swnj update(0); 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*8040Sroot iupdat(ip, &time.tv_sec, &time.tv_sec, 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