1 /* lfs_vnops.c 3.5 10/03/80 */ 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 { 140 dev_t dev; 141 register struct inode *ip; 142 register struct mount *mp; 143 struct mount *smp; 144 register struct filsys *fp; 145 struct buf *bp; 146 register struct a { 147 char *fspec; 148 char *freg; 149 int ronly; 150 } *uap; 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 mp->m_bufp = geteblk(); 185 bcopy((caddr_t)bp->b_un.b_addr, mp->m_bufp->b_un.b_addr, BSIZE); 186 fp = mp->m_bufp->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 brelse(bp); 193 ip->i_flag |= IMOUNT; 194 prele(ip); 195 return; 196 197 out: 198 u.u_error = EBUSY; 199 out1: 200 iput(ip); 201 } 202 203 /* 204 * the umount system call. 205 */ 206 sumount() 207 { 208 dev_t dev; 209 register struct inode *ip; 210 register struct mount *mp; 211 struct buf *bp; 212 register struct a { 213 char *fspec; 214 }; 215 216 dev = getmdev(); 217 if(u.u_error) 218 return; 219 xumount(dev); /* remove unused sticky files from text table */ 220 update(); 221 for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 222 if(mp->m_bufp != NULL && dev == mp->m_dev) 223 goto found; 224 u.u_error = EINVAL; 225 return; 226 227 found: 228 for(ip = &inode[0]; ip < &inode[NINODE]; ip++) 229 if(ip->i_number != 0 && dev == ip->i_dev) { 230 u.u_error = EBUSY; 231 return; 232 } 233 mpurge(mp - &mount[0]); 234 (*bdevsw[major(dev)].d_close)(dev, 0); 235 ip = mp->m_inodp; 236 ip->i_flag &= ~IMOUNT; 237 plock(ip); 238 iput(ip); 239 bp = mp->m_bufp; 240 mp->m_bufp = NULL; 241 brelse(bp); 242 } 243 244 /* 245 * Common code for mount and umount. 246 * Check that the user's argument is a reasonable 247 * thing on which to mount, and return the device number if so. 248 */ 249 dev_t 250 getmdev() 251 { 252 dev_t dev; 253 register struct inode *ip; 254 255 #ifdef UCB 256 if (!suser()) 257 return(NODEV); 258 #endif 259 ip = namei(uchar, 0); 260 if(ip == NULL) 261 return(NODEV); 262 if((ip->i_mode&IFMT) != IFBLK) 263 u.u_error = ENOTBLK; 264 dev = (dev_t)ip->i_un.i_rdev; 265 if(major(dev) >= nblkdev) 266 u.u_error = ENXIO; 267 iput(ip); 268 return(dev); 269 } 270