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