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