1*37Sbill /* vfs_syscalls.c 3.1 10/14/12 */ 2*37Sbill 3*37Sbill #include "../h/param.h" 4*37Sbill #include "../h/systm.h" 5*37Sbill #include "../h/mount.h" 6*37Sbill #include "../h/ino.h" 7*37Sbill #include "../h/reg.h" 8*37Sbill #include "../h/buf.h" 9*37Sbill #include "../h/filsys.h" 10*37Sbill #include "../h/dir.h" 11*37Sbill #include "../h/user.h" 12*37Sbill #include "../h/inode.h" 13*37Sbill #include "../h/file.h" 14*37Sbill #include "../h/conf.h" 15*37Sbill #include "../h/stat.h" 16*37Sbill 17*37Sbill /* 18*37Sbill * the fstat system call. 19*37Sbill */ 20*37Sbill fstat() 21*37Sbill { 22*37Sbill register struct file *fp; 23*37Sbill register struct a { 24*37Sbill int fdes; 25*37Sbill struct stat *sb; 26*37Sbill } *uap; 27*37Sbill 28*37Sbill uap = (struct a *)u.u_ap; 29*37Sbill fp = getf(uap->fdes); 30*37Sbill if(fp == NULL) 31*37Sbill return; 32*37Sbill stat1(fp->f_inode, uap->sb, fp->f_flag&FPIPE? fp->f_un.f_offset: 0); 33*37Sbill } 34*37Sbill 35*37Sbill /* 36*37Sbill * the stat system call. 37*37Sbill */ 38*37Sbill stat() 39*37Sbill { 40*37Sbill register struct inode *ip; 41*37Sbill register struct a { 42*37Sbill char *fname; 43*37Sbill struct stat *sb; 44*37Sbill } *uap; 45*37Sbill 46*37Sbill uap = (struct a *)u.u_ap; 47*37Sbill ip = namei(uchar, 0); 48*37Sbill if(ip == NULL) 49*37Sbill return; 50*37Sbill stat1(ip, uap->sb, (off_t)0); 51*37Sbill iput(ip); 52*37Sbill } 53*37Sbill 54*37Sbill /* 55*37Sbill * The basic routine for fstat and stat: 56*37Sbill * get the inode and pass appropriate parts back. 57*37Sbill */ 58*37Sbill stat1(ip, ub, pipeadj) 59*37Sbill register struct inode *ip; 60*37Sbill struct stat *ub; 61*37Sbill off_t pipeadj; 62*37Sbill { 63*37Sbill register struct dinode *dp; 64*37Sbill register struct buf *bp; 65*37Sbill struct stat ds; 66*37Sbill 67*37Sbill iupdat(ip, &time, &time); 68*37Sbill /* 69*37Sbill * first copy from inode table 70*37Sbill */ 71*37Sbill ds.st_dev = ip->i_dev; 72*37Sbill ds.st_ino = ip->i_number; 73*37Sbill ds.st_mode = ip->i_mode; 74*37Sbill ds.st_nlink = ip->i_nlink; 75*37Sbill ds.st_uid = ip->i_uid; 76*37Sbill ds.st_gid = ip->i_gid; 77*37Sbill ds.st_rdev = (dev_t)ip->i_un.i_rdev; 78*37Sbill ds.st_size = ip->i_size - pipeadj; 79*37Sbill /* 80*37Sbill * next the dates in the disk 81*37Sbill */ 82*37Sbill bp = bread(ip->i_dev, itod(ip->i_number)); 83*37Sbill dp = bp->b_un.b_dino; 84*37Sbill dp += itoo(ip->i_number); 85*37Sbill ds.st_atime = dp->di_atime; 86*37Sbill ds.st_mtime = dp->di_mtime; 87*37Sbill ds.st_ctime = dp->di_ctime; 88*37Sbill brelse(bp); 89*37Sbill if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 90*37Sbill u.u_error = EFAULT; 91*37Sbill } 92*37Sbill 93*37Sbill /* 94*37Sbill * the dup system call. 95*37Sbill */ 96*37Sbill dup() 97*37Sbill { 98*37Sbill register struct file *fp; 99*37Sbill register struct a { 100*37Sbill int fdes; 101*37Sbill int fdes2; 102*37Sbill } *uap; 103*37Sbill register i, m; 104*37Sbill 105*37Sbill uap = (struct a *)u.u_ap; 106*37Sbill m = uap->fdes & ~077; 107*37Sbill uap->fdes &= 077; 108*37Sbill fp = getf(uap->fdes); 109*37Sbill if(fp == NULL) 110*37Sbill return; 111*37Sbill if ((m&0100) == 0) { 112*37Sbill if ((i = ufalloc()) < 0) 113*37Sbill return; 114*37Sbill } else { 115*37Sbill i = uap->fdes2; 116*37Sbill if (i<0 || i>=NOFILE) { 117*37Sbill u.u_error = EBADF; 118*37Sbill return; 119*37Sbill } 120*37Sbill if (u.u_vrpages[i]) { 121*37Sbill u.u_error = ETXTBSY; 122*37Sbill return; 123*37Sbill } 124*37Sbill u.u_r.r_val1 = i; 125*37Sbill } 126*37Sbill if (i!=uap->fdes) { 127*37Sbill if (u.u_ofile[i]!=NULL) 128*37Sbill closef(u.u_ofile[i]); 129*37Sbill u.u_ofile[i] = fp; 130*37Sbill fp->f_count++; 131*37Sbill } 132*37Sbill } 133*37Sbill 134*37Sbill /* 135*37Sbill * the mount system call. 136*37Sbill */ 137*37Sbill smount() 138*37Sbill { 139*37Sbill dev_t dev; 140*37Sbill register struct inode *ip; 141*37Sbill register struct mount *mp; 142*37Sbill struct mount *smp; 143*37Sbill register struct filsys *fp; 144*37Sbill struct buf *bp; 145*37Sbill register struct a { 146*37Sbill char *fspec; 147*37Sbill char *freg; 148*37Sbill int ronly; 149*37Sbill } *uap; 150*37Sbill 151*37Sbill uap = (struct a *)u.u_ap; 152*37Sbill dev = getmdev(); 153*37Sbill if(u.u_error) 154*37Sbill return; 155*37Sbill u.u_dirp = (caddr_t)uap->freg; 156*37Sbill ip = namei(uchar, 0); 157*37Sbill if(ip == NULL) 158*37Sbill return; 159*37Sbill if(ip->i_count!=1 || (ip->i_mode&(IFBLK&IFCHR))!=0) 160*37Sbill goto out; 161*37Sbill smp = NULL; 162*37Sbill for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 163*37Sbill if(mp->m_bufp != NULL) { 164*37Sbill if(dev == mp->m_dev) 165*37Sbill goto out; 166*37Sbill } else 167*37Sbill if(smp == NULL) 168*37Sbill smp = mp; 169*37Sbill } 170*37Sbill mp = smp; 171*37Sbill if(mp == NULL) 172*37Sbill goto out; 173*37Sbill (*bdevsw[major(dev)].d_open)(dev, !uap->ronly); 174*37Sbill if(u.u_error) 175*37Sbill goto out; 176*37Sbill bp = bread(dev, SUPERB); 177*37Sbill if(u.u_error) { 178*37Sbill brelse(bp); 179*37Sbill goto out1; 180*37Sbill } 181*37Sbill mp->m_inodp = ip; 182*37Sbill mp->m_dev = dev; 183*37Sbill mp->m_bufp = geteblk(); 184*37Sbill bcopy((caddr_t)bp->b_un.b_addr, mp->m_bufp->b_un.b_addr, BSIZE); 185*37Sbill fp = mp->m_bufp->b_un.b_filsys; 186*37Sbill fp->s_ilock = 0; 187*37Sbill fp->s_flock = 0; 188*37Sbill fp->s_ronly = uap->ronly & 1; 189*37Sbill fp->s_nbehind = 0; 190*37Sbill fp->s_lasti = 1; 191*37Sbill brelse(bp); 192*37Sbill ip->i_flag |= IMOUNT; 193*37Sbill prele(ip); 194*37Sbill return; 195*37Sbill 196*37Sbill out: 197*37Sbill u.u_error = EBUSY; 198*37Sbill out1: 199*37Sbill iput(ip); 200*37Sbill } 201*37Sbill 202*37Sbill /* 203*37Sbill * the umount system call. 204*37Sbill */ 205*37Sbill sumount() 206*37Sbill { 207*37Sbill dev_t dev; 208*37Sbill register struct inode *ip; 209*37Sbill register struct mount *mp; 210*37Sbill struct buf *bp; 211*37Sbill register struct a { 212*37Sbill char *fspec; 213*37Sbill }; 214*37Sbill 215*37Sbill dev = getmdev(); 216*37Sbill if(u.u_error) 217*37Sbill return; 218*37Sbill xumount(dev); /* remove unused sticky files from text table */ 219*37Sbill update(); 220*37Sbill for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 221*37Sbill if(mp->m_bufp != NULL && dev == mp->m_dev) 222*37Sbill goto found; 223*37Sbill u.u_error = EINVAL; 224*37Sbill return; 225*37Sbill 226*37Sbill found: 227*37Sbill for(ip = &inode[0]; ip < &inode[NINODE]; ip++) 228*37Sbill if(ip->i_number != 0 && dev == ip->i_dev) { 229*37Sbill u.u_error = EBUSY; 230*37Sbill return; 231*37Sbill } 232*37Sbill (*bdevsw[major(dev)].d_close)(dev, 0); 233*37Sbill ip = mp->m_inodp; 234*37Sbill ip->i_flag &= ~IMOUNT; 235*37Sbill plock(ip); 236*37Sbill iput(ip); 237*37Sbill bp = mp->m_bufp; 238*37Sbill mp->m_bufp = NULL; 239*37Sbill brelse(bp); 240*37Sbill } 241*37Sbill 242*37Sbill /* 243*37Sbill * Common code for mount and umount. 244*37Sbill * Check that the user's argument is a reasonable 245*37Sbill * thing on which to mount, and return the device number if so. 246*37Sbill */ 247*37Sbill dev_t 248*37Sbill getmdev() 249*37Sbill { 250*37Sbill dev_t dev; 251*37Sbill register struct inode *ip; 252*37Sbill 253*37Sbill #ifdef UCB 254*37Sbill if (!suser()) 255*37Sbill return(NODEV); 256*37Sbill #endif 257*37Sbill ip = namei(uchar, 0); 258*37Sbill if(ip == NULL) 259*37Sbill return(NODEV); 260*37Sbill if((ip->i_mode&IFMT) != IFBLK) 261*37Sbill u.u_error = ENOTBLK; 262*37Sbill dev = (dev_t)ip->i_un.i_rdev; 263*37Sbill if(major(dev) >= nblkdev) 264*37Sbill u.u_error = ENXIO; 265*37Sbill iput(ip); 266*37Sbill return(dev); 267*37Sbill } 268