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