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