1*6574Smckusic /* vfs_syscalls.c 4.23 82/04/19 */ 237Sbill 3*6574Smckusic /* merged into kernel: @(#)sys3.c 2.2 4/8/82 */ 4*6574Smckusic 5*6574Smckusic #ifdef SIMFS 6*6574Smckusic #include "../h/sysrenam.h" 7*6574Smckusic #endif 837Sbill #include "../h/param.h" 937Sbill #include "../h/systm.h" 1037Sbill #include "../h/dir.h" 1137Sbill #include "../h/user.h" 126254Sroot #include "../h/file.h" 13*6574Smckusic #include "../h/stat.h" 1437Sbill #include "../h/inode.h" 15*6574Smckusic #include "../h/fs.h" 166254Sroot #include "../h/buf.h" 176254Sroot #include "../h/proc.h" 186254Sroot #include "../h/inline.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) 346254Sroot 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; 506254Sroot irele(ip); 516254Sroot if (*ipp) { 526254Sroot ilock(*ipp); 536254Sroot iput(*ipp); 546254Sroot } 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; 706254Sroot int rwmode; 716254Sroot } *uap; 726254Sroot 736254Sroot uap = (struct a *)u.u_ap; 746254Sroot ip = namei(uchar, 0, 1); 756254Sroot if (ip == NULL) 766254Sroot return; 776254Sroot open1(ip, ++uap->rwmode, 0); 786254Sroot } 796254Sroot 806254Sroot /* 816254Sroot * Creat system call. 826254Sroot */ 836254Sroot creat() 846254Sroot { 856254Sroot register struct inode *ip; 866254Sroot register struct a { 876254Sroot char *fname; 886254Sroot int fmode; 896254Sroot } *uap; 906254Sroot 916254Sroot uap = (struct a *)u.u_ap; 926254Sroot ip = namei(uchar, 1, 1); 936254Sroot if (ip == NULL) { 946254Sroot if (u.u_error) 956254Sroot return; 966254Sroot ip = maknode(uap->fmode&07777&(~ISVTX)); 976254Sroot if (ip==NULL) 986254Sroot return; 996254Sroot open1(ip, FWRITE, 2); 1006254Sroot } else 1016254Sroot open1(ip, FWRITE, 1); 1026254Sroot } 1036254Sroot 1046254Sroot /* 1056254Sroot * Common code for open and creat. 1066254Sroot * Check permissions, allocate an open file structure, 1076254Sroot * and call the device open routine if any. 1086254Sroot */ 1096254Sroot open1(ip, mode, trf) 1106254Sroot register struct inode *ip; 1116254Sroot register mode; 1126254Sroot { 1136254Sroot register struct file *fp; 1146254Sroot int i; 1156254Sroot 1166254Sroot if (trf != 2) { 1176254Sroot if (mode&FREAD) 1186254Sroot (void) access(ip, IREAD); 1196254Sroot if (mode&FWRITE) { 1206254Sroot (void) access(ip, IWRITE); 1216254Sroot if ((ip->i_mode&IFMT) == IFDIR) 1226254Sroot u.u_error = EISDIR; 1236254Sroot } 1246254Sroot } 1256254Sroot if (u.u_error) 1266254Sroot goto out; 1276254Sroot if (trf == 1) 1286254Sroot itrunc(ip); 1296254Sroot irele(ip); 1306254Sroot if ((fp = falloc()) == NULL) 1316254Sroot goto out; 1326254Sroot fp->f_flag = mode&(FREAD|FWRITE); 1336254Sroot i = u.u_r.r_val1; 1346254Sroot fp->f_inode = ip; 1356254Sroot openi(ip, mode&(FREAD|FWRITE)); 1366254Sroot if (u.u_error == 0) 1376254Sroot return; 1386254Sroot u.u_ofile[i] = NULL; 1396254Sroot fp->f_count--; 1406254Sroot out: 1416254Sroot if (ip != NULL) 1426254Sroot iput(ip); 1436254Sroot } 1446254Sroot 1456254Sroot /* 1466254Sroot * Mknod system call 1476254Sroot */ 1486254Sroot mknod() 1496254Sroot { 1506254Sroot register struct inode *ip; 1516254Sroot register struct a { 1526254Sroot char *fname; 1536254Sroot int fmode; 1546254Sroot int dev; 1556254Sroot } *uap; 1566254Sroot 1576254Sroot uap = (struct a *)u.u_ap; 1586254Sroot if (suser()) { 1596254Sroot ip = namei(uchar, 1, 0); 1606254Sroot if (ip != NULL) { 1616254Sroot u.u_error = EEXIST; 1626254Sroot goto out; 1636254Sroot } 1646254Sroot } 1656254Sroot if (u.u_error) 1666254Sroot return; 1676254Sroot ip = maknode(uap->fmode); 1686254Sroot if (ip == NULL) 1696254Sroot return; 1706254Sroot if (uap->dev) { 1716254Sroot /* 1726254Sroot * Want to be able to use this to make badblock 1736254Sroot * inodes, so don't truncate the dev number. 1746254Sroot */ 175*6574Smckusic ip->i_rdev = uap->dev; 1766254Sroot ip->i_flag |= IACC|IUPD|ICHG; 1776254Sroot } 1786254Sroot 1796254Sroot out: 1806254Sroot iput(ip); 1816254Sroot } 1826254Sroot 1836254Sroot /* 1846254Sroot * link system call 1856254Sroot */ 1866254Sroot link() 1876254Sroot { 1886254Sroot register struct inode *ip, *xp; 1896254Sroot register struct a { 1906254Sroot char *target; 1916254Sroot char *linkname; 1926254Sroot } *uap; 1936254Sroot 1946254Sroot uap = (struct a *)u.u_ap; 1956254Sroot ip = namei(uchar, 0, 1); /* well, this routine is doomed anyhow */ 1966254Sroot if (ip == NULL) 1976254Sroot return; 1986254Sroot if ((ip->i_mode&IFMT)==IFDIR && !suser()) 1996254Sroot goto out1; 2006254Sroot ip->i_nlink++; 2016254Sroot ip->i_flag |= ICHG; 2026254Sroot iupdat(ip, &time, &time, 1); 2036254Sroot irele(ip); 2046254Sroot u.u_dirp = (caddr_t)uap->linkname; 2056254Sroot xp = namei(uchar, 1, 0); 2066254Sroot if (xp != NULL) { 2076254Sroot u.u_error = EEXIST; 2086254Sroot iput(xp); 2096254Sroot goto out; 2106254Sroot } 2116254Sroot if (u.u_error) 2126254Sroot goto out; 2136254Sroot if (u.u_pdir->i_dev != ip->i_dev) { 2146254Sroot iput(u.u_pdir); 2156254Sroot u.u_error = EXDEV; 2166254Sroot goto out; 2176254Sroot } 2186254Sroot wdir(ip); 2196254Sroot out: 2206254Sroot if (u.u_error) { 2216254Sroot ip->i_nlink--; 2226254Sroot ip->i_flag |= ICHG; 2236254Sroot } 2246254Sroot out1: 2256254Sroot iput(ip); 2266254Sroot } 2276254Sroot 2286254Sroot /* 2296254Sroot * symlink -- make a symbolic link 2306254Sroot */ 2316254Sroot symlink() 2326254Sroot { 2336254Sroot register struct a { 2346254Sroot char *target; 2356254Sroot char *linkname; 2366254Sroot } *uap; 2376254Sroot register struct inode *ip; 2386254Sroot register char *tp; 2396254Sroot register c, nc; 2406254Sroot 2416254Sroot uap = (struct a *)u.u_ap; 2426254Sroot tp = uap->target; 2436254Sroot nc = 0; 2446254Sroot while (c = fubyte(tp)) { 2456254Sroot if (c < 0) { 2466254Sroot u.u_error = EFAULT; 2476254Sroot return; 2486254Sroot } 2496254Sroot tp++; 2506254Sroot nc++; 2516254Sroot } 2526254Sroot u.u_dirp = uap->linkname; 2536254Sroot ip = namei(uchar, 1, 0); 2546254Sroot if (ip) { 2556254Sroot iput(ip); 2566254Sroot u.u_error = EEXIST; 2576254Sroot return; 2586254Sroot } 2596254Sroot if (u.u_error) 2606254Sroot return; 2616254Sroot ip = maknode(IFLNK | 0777); 2626254Sroot if (ip == NULL) 2636254Sroot return; 2646254Sroot u.u_base = uap->target; 2656254Sroot u.u_count = nc; 2666254Sroot u.u_offset = 0; 2676254Sroot u.u_segflg = 0; 2686254Sroot writei(ip); 2696254Sroot iput(ip); 2706254Sroot } 2716254Sroot 2726254Sroot /* 2736254Sroot * Unlink system call. 2746254Sroot * Hard to avoid races here, especially 2756254Sroot * in unlinking directories. 2766254Sroot */ 2776254Sroot unlink() 2786254Sroot { 2796254Sroot register struct inode *ip, *pp; 2806254Sroot struct a { 2816254Sroot char *fname; 2826254Sroot }; 283*6574Smckusic struct fs *fs; 284*6574Smckusic struct buf *bp; 285*6574Smckusic int lbn, bn, base; 2866254Sroot 2876254Sroot pp = namei(uchar, 2, 0); 2886254Sroot if(pp == NULL) 2896254Sroot return; 2906254Sroot /* 2916254Sroot * Check for unlink(".") 2926254Sroot * to avoid hanging on the iget 2936254Sroot */ 2946254Sroot if (pp->i_number == u.u_dent.d_ino) { 2956254Sroot ip = pp; 2966254Sroot ip->i_count++; 2976254Sroot } else 298*6574Smckusic ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino); 2996254Sroot if(ip == NULL) 3006254Sroot goto out1; 3016254Sroot if((ip->i_mode&IFMT)==IFDIR && !suser()) 3026254Sroot goto out; 3036254Sroot /* 3046254Sroot * Don't unlink a mounted file. 3056254Sroot */ 3066254Sroot if (ip->i_dev != pp->i_dev) { 3076254Sroot u.u_error = EBUSY; 3086254Sroot goto out; 3096254Sroot } 3106254Sroot if (ip->i_flag&ITEXT) 3116254Sroot xrele(ip); /* try once to free text */ 3126254Sroot /* 3136254Sroot if ((ip->i_flag&ITEXT) && ip->i_nlink==1) { 3146254Sroot u.u_error = ETXTBSY; 3156254Sroot goto out; 3166254Sroot } 3176254Sroot */ 318*6574Smckusic if (u.u_count == 0) { 319*6574Smckusic /* 320*6574Smckusic * first entry in block, so set d_ino to zero. 321*6574Smckusic */ 322*6574Smckusic u.u_base = (caddr_t)&u.u_dent; 323*6574Smckusic u.u_count = DIRSIZ(&u.u_dent); 324*6574Smckusic u.u_dent.d_ino = 0; 325*6574Smckusic writei(pp); 326*6574Smckusic } else { 327*6574Smckusic /* 328*6574Smckusic * updating preceeding entry to skip over current entry. 329*6574Smckusic */ 330*6574Smckusic fs = pp->i_fs; 331*6574Smckusic lbn = lblkno(fs, u.u_offset); 332*6574Smckusic base = blkoff(fs, u.u_offset); 333*6574Smckusic bn = fsbtodb(fs, bmap(pp, lbn, B_WRITE, base + u.u_count)); 334*6574Smckusic bp = bread(pp->i_dev, bn, blksize(fs, pp, lbn)); 335*6574Smckusic if (bp->b_flags & B_ERROR) { 336*6574Smckusic brelse(bp); 337*6574Smckusic goto out; 338*6574Smckusic } 339*6574Smckusic ((struct direct *)(bp->b_un.b_addr + base))->d_reclen += 340*6574Smckusic u.u_dent.d_reclen; 341*6574Smckusic bwrite(bp); 342*6574Smckusic pp->i_flag |= IUPD|ICHG; 343*6574Smckusic } 3446254Sroot ip->i_nlink--; 3456254Sroot ip->i_flag |= ICHG; 3466254Sroot 3476254Sroot out: 3486254Sroot iput(ip); 3496254Sroot out1: 3506254Sroot iput(pp); 3516254Sroot } 3526254Sroot 3536254Sroot /* 3546254Sroot * Seek system call 3556254Sroot */ 3566254Sroot seek() 3576254Sroot { 3586254Sroot register struct file *fp; 3596254Sroot register struct a { 3606254Sroot int fdes; 3616254Sroot off_t off; 3626254Sroot int sbase; 3636254Sroot } *uap; 3646254Sroot 3656254Sroot uap = (struct a *)u.u_ap; 3666254Sroot fp = getf(uap->fdes); 3676254Sroot if (fp == NULL) 3686254Sroot return; 3696254Sroot if (fp->f_flag&FSOCKET) { 3706254Sroot u.u_error = ESPIPE; 3716254Sroot return; 3726254Sroot } 3736254Sroot if (uap->sbase == 1) 3746254Sroot uap->off += fp->f_offset; 3756254Sroot else if (uap->sbase == 2) 3766254Sroot uap->off += fp->f_inode->i_size; 3776254Sroot fp->f_offset = uap->off; 3786254Sroot u.u_r.r_off = uap->off; 3796254Sroot } 3806254Sroot 3816254Sroot /* 3826254Sroot * Access system call 3836254Sroot */ 3846254Sroot saccess() 3856254Sroot { 3866254Sroot register svuid, svgid; 3876254Sroot register struct inode *ip; 3886254Sroot register struct a { 3896254Sroot char *fname; 3906254Sroot int fmode; 3916254Sroot } *uap; 3926254Sroot 3936254Sroot uap = (struct a *)u.u_ap; 3946254Sroot svuid = u.u_uid; 3956254Sroot svgid = u.u_gid; 3966254Sroot u.u_uid = u.u_ruid; 3976254Sroot u.u_gid = u.u_rgid; 3986254Sroot ip = namei(uchar, 0, 1); 3996254Sroot if (ip != NULL) { 4006254Sroot if (uap->fmode&(IREAD>>6)) 4016254Sroot (void) access(ip, IREAD); 4026254Sroot if (uap->fmode&(IWRITE>>6)) 4036254Sroot (void) access(ip, IWRITE); 4046254Sroot if (uap->fmode&(IEXEC>>6)) 4056254Sroot (void) access(ip, IEXEC); 4066254Sroot iput(ip); 4076254Sroot } 4086254Sroot u.u_uid = svuid; 4096254Sroot u.u_gid = svgid; 4106254Sroot } 4116254Sroot 4126254Sroot /* 41337Sbill * the fstat system call. 41437Sbill */ 41537Sbill fstat() 41637Sbill { 41737Sbill register struct file *fp; 41837Sbill register struct a { 41937Sbill int fdes; 42037Sbill struct stat *sb; 42137Sbill } *uap; 42237Sbill 42337Sbill uap = (struct a *)u.u_ap; 42437Sbill fp = getf(uap->fdes); 4254828Swnj if (fp == NULL) 42637Sbill return; 4274828Swnj if (fp->f_flag & FSOCKET) 4284891Swnj u.u_error = sostat(fp->f_socket, uap->sb); 4294828Swnj else 4304828Swnj stat1(fp->f_inode, uap->sb); 43137Sbill } 43237Sbill 43337Sbill /* 434*6574Smckusic * Stat system call. This version follows links. 43537Sbill */ 43637Sbill stat() 43737Sbill { 43837Sbill register struct inode *ip; 43937Sbill register struct a { 44037Sbill char *fname; 44137Sbill struct stat *sb; 44237Sbill } *uap; 44337Sbill 44437Sbill uap = (struct a *)u.u_ap; 4456423Sroot ip = namei(uchar, 0, 1); 4464828Swnj if (ip == NULL) 44737Sbill return; 4483624Sroot stat1(ip, uap->sb); 44937Sbill iput(ip); 45037Sbill } 45137Sbill 45237Sbill /* 453*6574Smckusic * Lstat system call. This version does not follow links. 4545992Swnj */ 4555992Swnj lstat() 4565992Swnj { 4575992Swnj register struct inode *ip; 4585992Swnj register struct a { 4595992Swnj char *fname; 4605992Swnj struct stat *sb; 4615992Swnj } *uap; 4625992Swnj 4635992Swnj uap = (struct a *)u.u_ap; 4646423Sroot ip = namei(uchar, 0, 0); 4655992Swnj if (ip == NULL) 4665992Swnj return; 4676153Ssam stat1(ip, uap->sb); 4685992Swnj iput(ip); 4695992Swnj } 4705992Swnj 4715992Swnj /* 47237Sbill * The basic routine for fstat and stat: 47337Sbill * get the inode and pass appropriate parts back. 47437Sbill */ 4753624Sroot stat1(ip, ub) 4764828Swnj register struct inode *ip; 4774828Swnj struct stat *ub; 47837Sbill { 47937Sbill struct stat ds; 48037Sbill 4811204Sbill IUPDAT(ip, &time, &time, 0); 48237Sbill /* 4834828Swnj * First copy from inode table 48437Sbill */ 48537Sbill ds.st_dev = ip->i_dev; 48637Sbill ds.st_ino = ip->i_number; 48737Sbill ds.st_mode = ip->i_mode; 48837Sbill ds.st_nlink = ip->i_nlink; 48937Sbill ds.st_uid = ip->i_uid; 49037Sbill ds.st_gid = ip->i_gid; 491*6574Smckusic ds.st_rdev = (dev_t)ip->i_rdev; 4923624Sroot ds.st_size = ip->i_size; 493*6574Smckusic ds.st_atime = ip->i_atime; 494*6574Smckusic ds.st_mtime = ip->i_mtime; 495*6574Smckusic ds.st_ctime = ip->i_ctime; 49637Sbill if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 49737Sbill u.u_error = EFAULT; 49837Sbill } 49937Sbill 50037Sbill /* 5015992Swnj * Return target name of a symbolic link 50237Sbill */ 5035992Swnj readlink() 5045992Swnj { 5055992Swnj register struct inode *ip; 5065992Swnj register struct a { 5075992Swnj char *name; 5085992Swnj char *buf; 5095992Swnj int count; 5105992Swnj } *uap; 5115992Swnj 5125992Swnj ip = namei(uchar, 0, 0); 5135992Swnj if (ip == NULL) 5145992Swnj return; 5155992Swnj if ((ip->i_mode&IFMT) != IFLNK) { 5165992Swnj u.u_error = ENXIO; 5175992Swnj goto out; 5185992Swnj } 5195992Swnj uap = (struct a *)u.u_ap; 5205992Swnj u.u_offset = 0; 5215992Swnj u.u_base = uap->buf; 5225992Swnj u.u_count = uap->count; 5235992Swnj u.u_segflg = 0; 5245992Swnj readi(ip); 5255992Swnj out: 5265992Swnj iput(ip); 5275992Swnj u.u_r.r_val1 = uap->count - u.u_count; 5285992Swnj } 5295992Swnj 5306254Sroot chmod() 5315992Swnj { 5326254Sroot register struct inode *ip; 5335992Swnj register struct a { 5346254Sroot char *fname; 5356254Sroot int fmode; 5365992Swnj } *uap; 5375992Swnj 5385992Swnj uap = (struct a *)u.u_ap; 5396254Sroot if ((ip = owner(1)) == NULL) 5405992Swnj return; 5416254Sroot ip->i_mode &= ~07777; 5426254Sroot if (u.u_uid) 5436254Sroot uap->fmode &= ~ISVTX; 5446254Sroot ip->i_mode |= uap->fmode&07777; 5456254Sroot ip->i_flag |= ICHG; 5466254Sroot if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 5476254Sroot xrele(ip); 5485992Swnj iput(ip); 5495992Swnj } 5505992Swnj 5516254Sroot chown() 55237Sbill { 5536254Sroot register struct inode *ip; 55437Sbill register struct a { 5556254Sroot char *fname; 5566254Sroot int uid; 5576254Sroot int gid; 55837Sbill } *uap; 55937Sbill 56037Sbill uap = (struct a *)u.u_ap; 5616254Sroot if (!suser() || (ip = owner(0)) == NULL) 56237Sbill return; 5636254Sroot ip->i_uid = uap->uid; 5646254Sroot ip->i_gid = uap->gid; 5656254Sroot ip->i_flag |= ICHG; 5666254Sroot if (u.u_ruid != 0) 5676254Sroot ip->i_mode &= ~(ISUID|ISGID); 5686254Sroot iput(ip); 56937Sbill } 57037Sbill 57137Sbill /* 5726254Sroot * Set IUPD and IACC times on file. 5736254Sroot * Can't set ICHG. 57437Sbill */ 5756254Sroot utime() 5764828Swnj { 57737Sbill register struct a { 5786254Sroot char *fname; 5796254Sroot time_t *tptr; 58037Sbill } *uap; 5816254Sroot register struct inode *ip; 5826254Sroot time_t tv[2]; 58337Sbill 58437Sbill uap = (struct a *)u.u_ap; 5856254Sroot if ((ip = owner(1)) == NULL) 58637Sbill return; 5876254Sroot if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { 5886254Sroot u.u_error = EFAULT; 5896254Sroot } else { 5906254Sroot ip->i_flag |= IACC|IUPD|ICHG; 5916254Sroot iupdat(ip, &tv[0], &tv[1], 0); 59237Sbill } 59337Sbill iput(ip); 59437Sbill } 59537Sbill 5966254Sroot sync() 59737Sbill { 59837Sbill 5995416Swnj update(0); 60037Sbill } 601