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