1 /* lfs_vnops.c 4.17 82/01/19 */ 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 #include "../h/socket.h" 18 #include "../h/socketvar.h" 19 20 /* 21 * the fstat system call. 22 */ 23 fstat() 24 { 25 register struct file *fp; 26 register struct a { 27 int fdes; 28 struct stat *sb; 29 } *uap; 30 31 uap = (struct a *)u.u_ap; 32 fp = getf(uap->fdes); 33 if (fp == NULL) 34 return; 35 if (fp->f_flag & FSOCKET) 36 u.u_error = sostat(fp->f_socket, uap->sb); 37 else 38 stat1(fp->f_inode, uap->sb); 39 } 40 41 /* 42 * Stat system call. 43 */ 44 stat() 45 { 46 register struct inode *ip; 47 register struct a { 48 char *fname; 49 struct stat *sb; 50 } *uap; 51 52 uap = (struct a *)u.u_ap; 53 ip = namei(uchar, 0); 54 if (ip == NULL) 55 return; 56 stat1(ip, uap->sb); 57 iput(ip); 58 } 59 60 /* 61 * The basic routine for fstat and stat: 62 * get the inode and pass appropriate parts back. 63 */ 64 stat1(ip, ub) 65 register struct inode *ip; 66 struct stat *ub; 67 { 68 register struct dinode *dp; 69 register struct buf *bp; 70 struct stat ds; 71 72 IUPDAT(ip, &time, &time, 0); 73 /* 74 * First copy from inode table 75 */ 76 ds.st_dev = ip->i_dev; 77 ds.st_ino = ip->i_number; 78 ds.st_mode = ip->i_mode; 79 ds.st_nlink = ip->i_nlink; 80 ds.st_uid = ip->i_uid; 81 ds.st_gid = ip->i_gid; 82 ds.st_rdev = (dev_t)ip->i_un.i_rdev; 83 ds.st_size = ip->i_size; 84 /* 85 * Next the dates in the disk 86 */ 87 bp = bread(ip->i_dev, itod(ip->i_number)); 88 dp = bp->b_un.b_dino; 89 dp += itoo(ip->i_number); 90 ds.st_atime = dp->di_atime; 91 ds.st_mtime = dp->di_mtime; 92 ds.st_ctime = dp->di_ctime; 93 brelse(bp); 94 if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 95 u.u_error = EFAULT; 96 } 97 98 /* 99 * Dup system call. 100 */ 101 dup() 102 { 103 register struct file *fp; 104 register struct a { 105 int fdes; 106 int fdes2; 107 } *uap; 108 register i, m; 109 110 uap = (struct a *)u.u_ap; 111 m = uap->fdes & ~077; 112 uap->fdes &= 077; 113 fp = getf(uap->fdes); 114 if (fp == NULL) 115 return; 116 if ((m&0100) == 0) { 117 if ((i = ufalloc()) < 0) 118 return; 119 } else { 120 i = uap->fdes2; 121 if (i<0 || i>=NOFILE) { 122 u.u_error = EBADF; 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], 0); 130 if (u.u_error) 131 return; 132 u.u_ofile[i] = fp; 133 fp->f_count++; 134 } 135 } 136 137 /* 138 * Mount system call. 139 */ 140 smount() 141 { 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&IFMT) != IFDIR) 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 irele(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(0); 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 ilock(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