1*6153Ssam /* vfs_syscalls.c 4.19 82/03/12 */ 237Sbill 337Sbill #include "../h/param.h" 437Sbill #include "../h/systm.h" 537Sbill #include "../h/mount.h" 637Sbill #include "../h/ino.h" 737Sbill #include "../h/reg.h" 837Sbill #include "../h/buf.h" 937Sbill #include "../h/filsys.h" 1037Sbill #include "../h/dir.h" 1137Sbill #include "../h/user.h" 1237Sbill #include "../h/inode.h" 1337Sbill #include "../h/file.h" 1437Sbill #include "../h/conf.h" 1537Sbill #include "../h/stat.h" 1694Sbill #include "../h/inline.h" 174918Swnj #include "../h/socket.h" 184918Swnj #include "../h/socketvar.h" 1937Sbill 2037Sbill /* 2137Sbill * the fstat system call. 2237Sbill */ 2337Sbill fstat() 2437Sbill { 2537Sbill register struct file *fp; 2637Sbill register struct a { 2737Sbill int fdes; 2837Sbill struct stat *sb; 2937Sbill } *uap; 3037Sbill 3137Sbill uap = (struct a *)u.u_ap; 3237Sbill fp = getf(uap->fdes); 334828Swnj if (fp == NULL) 3437Sbill return; 354828Swnj if (fp->f_flag & FSOCKET) 364891Swnj u.u_error = sostat(fp->f_socket, uap->sb); 374828Swnj else 384828Swnj stat1(fp->f_inode, uap->sb); 3937Sbill } 4037Sbill 4137Sbill /* 425992Swnj * Stat system call. This version does not follow links. 4337Sbill */ 4437Sbill stat() 4537Sbill { 4637Sbill register struct inode *ip; 4737Sbill register struct a { 4837Sbill char *fname; 4937Sbill struct stat *sb; 5037Sbill } *uap; 5137Sbill 5237Sbill uap = (struct a *)u.u_ap; 535992Swnj ip = namei(uchar, 0, 0); 544828Swnj if (ip == NULL) 5537Sbill return; 563624Sroot stat1(ip, uap->sb); 5737Sbill iput(ip); 5837Sbill } 5937Sbill 6037Sbill /* 615992Swnj * Lstat system call. This version does follow links. 625992Swnj */ 635992Swnj lstat() 645992Swnj { 655992Swnj register struct inode *ip; 665992Swnj register struct a { 675992Swnj char *fname; 685992Swnj struct stat *sb; 695992Swnj } *uap; 705992Swnj 715992Swnj uap = (struct a *)u.u_ap; 725992Swnj ip = namei(uchar, 0, 1); 735992Swnj if (ip == NULL) 745992Swnj return; 75*6153Ssam stat1(ip, uap->sb); 765992Swnj iput(ip); 775992Swnj } 785992Swnj 795992Swnj /* 8037Sbill * The basic routine for fstat and stat: 8137Sbill * get the inode and pass appropriate parts back. 8237Sbill */ 833624Sroot stat1(ip, ub) 844828Swnj register struct inode *ip; 854828Swnj struct stat *ub; 8637Sbill { 8737Sbill register struct dinode *dp; 8837Sbill register struct buf *bp; 8937Sbill struct stat ds; 9037Sbill 911204Sbill IUPDAT(ip, &time, &time, 0); 9237Sbill /* 934828Swnj * First copy from inode table 9437Sbill */ 9537Sbill ds.st_dev = ip->i_dev; 9637Sbill ds.st_ino = ip->i_number; 9737Sbill ds.st_mode = ip->i_mode; 9837Sbill ds.st_nlink = ip->i_nlink; 9937Sbill ds.st_uid = ip->i_uid; 10037Sbill ds.st_gid = ip->i_gid; 10137Sbill ds.st_rdev = (dev_t)ip->i_un.i_rdev; 1023624Sroot ds.st_size = ip->i_size; 10337Sbill /* 1045992Swnj * next the dates in the disk 10537Sbill */ 10637Sbill bp = bread(ip->i_dev, itod(ip->i_number)); 10737Sbill dp = bp->b_un.b_dino; 10837Sbill dp += itoo(ip->i_number); 10937Sbill ds.st_atime = dp->di_atime; 11037Sbill ds.st_mtime = dp->di_mtime; 11137Sbill ds.st_ctime = dp->di_ctime; 11237Sbill brelse(bp); 11337Sbill if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 11437Sbill u.u_error = EFAULT; 11537Sbill } 11637Sbill 11737Sbill /* 1185992Swnj * Return target name of a symbolic link 11937Sbill */ 1205992Swnj readlink() 1215992Swnj { 1225992Swnj register struct inode *ip; 1235992Swnj register struct a { 1245992Swnj char *name; 1255992Swnj char *buf; 1265992Swnj int count; 1275992Swnj } *uap; 1285992Swnj 1295992Swnj ip = namei(uchar, 0, 0); 1305992Swnj if (ip == NULL) 1315992Swnj return; 1325992Swnj if ((ip->i_mode&IFMT) != IFLNK) { 1335992Swnj u.u_error = ENXIO; 1345992Swnj goto out; 1355992Swnj } 1365992Swnj uap = (struct a *)u.u_ap; 1375992Swnj u.u_offset = 0; 1385992Swnj u.u_base = uap->buf; 1395992Swnj u.u_count = uap->count; 1405992Swnj u.u_segflg = 0; 1415992Swnj readi(ip); 1425992Swnj out: 1435992Swnj iput(ip); 1445992Swnj u.u_r.r_val1 = uap->count - u.u_count; 1455992Swnj } 1465992Swnj 1475992Swnj /* 1485992Swnj * symlink -- make a symbolic link 1495992Swnj */ 1505992Swnj symlink() 1515992Swnj { 1525992Swnj register struct a { 1535992Swnj char *target; 1545992Swnj char *linkname; 1555992Swnj } *uap; 1565992Swnj register struct inode *ip; 1575992Swnj register char *tp; 1585992Swnj register c, nc; 1595992Swnj 1605992Swnj uap = (struct a *)u.u_ap; 1615992Swnj tp = uap->target; 1625992Swnj nc = 0; 1635992Swnj while (c = fubyte(tp)) { 1645992Swnj if (c < 0) { 1655992Swnj u.u_error = EFAULT; 1665992Swnj return; 1675992Swnj } 1685992Swnj tp++; 1695992Swnj nc++; 1705992Swnj } 1715992Swnj u.u_dirp = uap->linkname; 1725992Swnj ip = namei(uchar, 1, 0); 1735992Swnj if (ip) { 1745992Swnj iput(ip); 1755992Swnj u.u_error = EEXIST; 1765992Swnj return; 1775992Swnj } 1785992Swnj ip = maknode(IFLNK | 0777); 1795992Swnj if (ip == NULL) 1805992Swnj return; 1815992Swnj u.u_base = uap->target; 1825992Swnj u.u_count = nc; 1835992Swnj u.u_offset = 0; 1845992Swnj u.u_segflg = 0; 1855992Swnj writei(ip); 1865992Swnj iput(ip); 1875992Swnj } 1885992Swnj 1895992Swnj /* 1905992Swnj * the dup system call. 1915992Swnj */ 19237Sbill dup() 19337Sbill { 19437Sbill register struct file *fp; 19537Sbill register struct a { 19637Sbill int fdes; 19737Sbill int fdes2; 19837Sbill } *uap; 19937Sbill register i, m; 20037Sbill 20137Sbill uap = (struct a *)u.u_ap; 20237Sbill m = uap->fdes & ~077; 20337Sbill uap->fdes &= 077; 20437Sbill fp = getf(uap->fdes); 2054828Swnj if (fp == NULL) 20637Sbill return; 20737Sbill if ((m&0100) == 0) { 20837Sbill if ((i = ufalloc()) < 0) 20937Sbill return; 21037Sbill } else { 21137Sbill i = uap->fdes2; 21237Sbill if (i<0 || i>=NOFILE) { 21337Sbill u.u_error = EBADF; 21437Sbill return; 21537Sbill } 21637Sbill u.u_r.r_val1 = i; 21737Sbill } 2184828Swnj if (i != uap->fdes) { 21937Sbill if (u.u_ofile[i]!=NULL) 2205582Swnj closef(u.u_ofile[i], 0); 2215582Swnj if (u.u_error) 2225582Swnj return; 22337Sbill u.u_ofile[i] = fp; 22437Sbill fp->f_count++; 22537Sbill } 22637Sbill } 22737Sbill 22837Sbill /* 2294828Swnj * Mount system call. 23037Sbill */ 2314828Swnj smount() 2324828Swnj { 23337Sbill dev_t dev; 23437Sbill register struct inode *ip; 23537Sbill register struct mount *mp; 23637Sbill struct mount *smp; 23737Sbill register struct filsys *fp; 23837Sbill struct buf *bp; 23937Sbill register struct a { 24037Sbill char *fspec; 24137Sbill char *freg; 24237Sbill int ronly; 24337Sbill } *uap; 2442879Swnj register char *cp; 24537Sbill 24637Sbill uap = (struct a *)u.u_ap; 24737Sbill dev = getmdev(); 2484828Swnj if (u.u_error) 24937Sbill return; 25037Sbill u.u_dirp = (caddr_t)uap->freg; 2515992Swnj ip = namei(uchar, 0, 1); 2524828Swnj if (ip == NULL) 25337Sbill return; 2544828Swnj if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR) 25537Sbill goto out; 25637Sbill smp = NULL; 2574828Swnj for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 2584828Swnj if (mp->m_bufp != NULL) { 2594828Swnj if (dev == mp->m_dev) 26037Sbill goto out; 26137Sbill } else 2624828Swnj if (smp == NULL) 26337Sbill smp = mp; 26437Sbill } 26537Sbill mp = smp; 2664828Swnj if (mp == NULL) 26737Sbill goto out; 26837Sbill (*bdevsw[major(dev)].d_open)(dev, !uap->ronly); 2694828Swnj if (u.u_error) 27037Sbill goto out; 27137Sbill bp = bread(dev, SUPERB); 2724828Swnj if (u.u_error) { 27337Sbill brelse(bp); 27437Sbill goto out1; 27537Sbill } 27637Sbill mp->m_inodp = ip; 27737Sbill mp->m_dev = dev; 2782323Swnj bp->b_flags |= B_LOCKED; 2792323Swnj mp->m_bufp = bp; 2802323Swnj fp = bp->b_un.b_filsys; 28137Sbill fp->s_ilock = 0; 28237Sbill fp->s_flock = 0; 28337Sbill fp->s_ronly = uap->ronly & 1; 28437Sbill fp->s_nbehind = 0; 28537Sbill fp->s_lasti = 1; 2862879Swnj u.u_dirp = uap->freg; 2872879Swnj for (cp = fp->s_fsmnt; cp < &fp->s_fsmnt[sizeof (fp->s_fsmnt) - 1]; ) 2882879Swnj if ((*cp++ = uchar()) == 0) 2892879Swnj u.u_dirp--; /* get 0 again */ 2902879Swnj *cp = 0; 29137Sbill brelse(bp); 29237Sbill ip->i_flag |= IMOUNT; 2934828Swnj irele(ip); 29437Sbill return; 29537Sbill 29637Sbill out: 29737Sbill u.u_error = EBUSY; 29837Sbill out1: 29937Sbill iput(ip); 30037Sbill } 30137Sbill 30237Sbill /* 30337Sbill * the umount system call. 30437Sbill */ 30537Sbill sumount() 30637Sbill { 30737Sbill dev_t dev; 30837Sbill register struct inode *ip; 30937Sbill register struct mount *mp; 31037Sbill struct buf *bp; 3112323Swnj int stillopen, flag; 31237Sbill register struct a { 31337Sbill char *fspec; 31437Sbill }; 31537Sbill 31637Sbill dev = getmdev(); 3174828Swnj if (u.u_error) 31837Sbill return; 31937Sbill xumount(dev); /* remove unused sticky files from text table */ 3205416Swnj update(0); 3214828Swnj for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 3224828Swnj if (mp->m_bufp != NULL && dev == mp->m_dev) 32337Sbill goto found; 32437Sbill u.u_error = EINVAL; 32537Sbill return; 32637Sbill 32737Sbill found: 3282436Skre stillopen = 0; 3294828Swnj for (ip = inode; ip < inodeNINODE; ip++) 3302323Swnj if (ip->i_number != 0 && dev == ip->i_dev) { 33137Sbill u.u_error = EBUSY; 33237Sbill return; 3332323Swnj } else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK && 3342323Swnj ip->i_un.i_rdev == dev) 3352323Swnj stillopen++; 33637Sbill ip = mp->m_inodp; 33737Sbill ip->i_flag &= ~IMOUNT; 3384828Swnj ilock(ip); 33937Sbill iput(ip); 3402323Swnj if ((bp = getblk(dev, SUPERB)) != mp->m_bufp) 3412323Swnj panic("umount"); 3422323Swnj bp->b_flags &= ~B_LOCKED; 3432304Skre flag = !bp->b_un.b_filsys->s_ronly; 34437Sbill mp->m_bufp = NULL; 34537Sbill brelse(bp); 3462454Swnj mpurge(mp - &mount[0]); 3472304Skre if (!stillopen) { 3482304Skre (*bdevsw[major(dev)].d_close)(dev, flag); 3492304Skre binval(dev); 3502304Skre } 35137Sbill } 35237Sbill 35337Sbill /* 35437Sbill * Common code for mount and umount. 35537Sbill * Check that the user's argument is a reasonable 35637Sbill * thing on which to mount, and return the device number if so. 35737Sbill */ 35837Sbill dev_t 35937Sbill getmdev() 36037Sbill { 36137Sbill dev_t dev; 36237Sbill register struct inode *ip; 36337Sbill 36437Sbill if (!suser()) 36537Sbill return(NODEV); 3665992Swnj ip = namei(uchar, 0, 1); 3674828Swnj if (ip == NULL) 36837Sbill return(NODEV); 3694828Swnj if ((ip->i_mode&IFMT) != IFBLK) 37037Sbill u.u_error = ENOTBLK; 37137Sbill dev = (dev_t)ip->i_un.i_rdev; 3724828Swnj if (major(dev) >= nblkdev) 37337Sbill u.u_error = ENXIO; 37437Sbill iput(ip); 37537Sbill return(dev); 37637Sbill } 377