1 /* lfs_vnops.c 4.18 82/02/27 */ 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. This version does not follow links. 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, 0); 54 if (ip == NULL) 55 return; 56 stat1(ip, uap->sb); 57 iput(ip); 58 } 59 60 /* 61 * Lstat system call. This version does follow links. 62 */ 63 lstat() 64 { 65 register struct inode *ip; 66 register struct a { 67 char *fname; 68 struct stat *sb; 69 } *uap; 70 71 uap = (struct a *)u.u_ap; 72 ip = namei(uchar, 0, 1); 73 if (ip == NULL) 74 return; 75 stat1(ip, uap->sb, (off_t)0); 76 iput(ip); 77 } 78 79 /* 80 * The basic routine for fstat and stat: 81 * get the inode and pass appropriate parts back. 82 */ 83 stat1(ip, ub) 84 register struct inode *ip; 85 struct stat *ub; 86 { 87 register struct dinode *dp; 88 register struct buf *bp; 89 struct stat ds; 90 91 IUPDAT(ip, &time, &time, 0); 92 /* 93 * First copy from inode table 94 */ 95 ds.st_dev = ip->i_dev; 96 ds.st_ino = ip->i_number; 97 ds.st_mode = ip->i_mode; 98 ds.st_nlink = ip->i_nlink; 99 ds.st_uid = ip->i_uid; 100 ds.st_gid = ip->i_gid; 101 ds.st_rdev = (dev_t)ip->i_un.i_rdev; 102 ds.st_size = ip->i_size; 103 /* 104 * next the dates in the disk 105 */ 106 bp = bread(ip->i_dev, itod(ip->i_number)); 107 dp = bp->b_un.b_dino; 108 dp += itoo(ip->i_number); 109 ds.st_atime = dp->di_atime; 110 ds.st_mtime = dp->di_mtime; 111 ds.st_ctime = dp->di_ctime; 112 brelse(bp); 113 if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 114 u.u_error = EFAULT; 115 } 116 117 /* 118 * Return target name of a symbolic link 119 */ 120 readlink() 121 { 122 register struct inode *ip; 123 register struct a { 124 char *name; 125 char *buf; 126 int count; 127 } *uap; 128 129 ip = namei(uchar, 0, 0); 130 if (ip == NULL) 131 return; 132 if ((ip->i_mode&IFMT) != IFLNK) { 133 u.u_error = ENXIO; 134 goto out; 135 } 136 uap = (struct a *)u.u_ap; 137 u.u_offset = 0; 138 u.u_base = uap->buf; 139 u.u_count = uap->count; 140 u.u_segflg = 0; 141 readi(ip); 142 out: 143 iput(ip); 144 u.u_r.r_val1 = uap->count - u.u_count; 145 } 146 147 /* 148 * symlink -- make a symbolic link 149 */ 150 symlink() 151 { 152 register struct a { 153 char *target; 154 char *linkname; 155 } *uap; 156 register struct inode *ip; 157 register char *tp; 158 register c, nc; 159 160 uap = (struct a *)u.u_ap; 161 tp = uap->target; 162 nc = 0; 163 while (c = fubyte(tp)) { 164 if (c < 0) { 165 u.u_error = EFAULT; 166 return; 167 } 168 tp++; 169 nc++; 170 } 171 u.u_dirp = uap->linkname; 172 ip = namei(uchar, 1, 0); 173 if (ip) { 174 iput(ip); 175 u.u_error = EEXIST; 176 return; 177 } 178 ip = maknode(IFLNK | 0777); 179 if (ip == NULL) 180 return; 181 u.u_base = uap->target; 182 u.u_count = nc; 183 u.u_offset = 0; 184 u.u_segflg = 0; 185 writei(ip); 186 iput(ip); 187 } 188 189 /* 190 * the dup system call. 191 */ 192 dup() 193 { 194 register struct file *fp; 195 register struct a { 196 int fdes; 197 int fdes2; 198 } *uap; 199 register i, m; 200 201 uap = (struct a *)u.u_ap; 202 m = uap->fdes & ~077; 203 uap->fdes &= 077; 204 fp = getf(uap->fdes); 205 if (fp == NULL) 206 return; 207 if ((m&0100) == 0) { 208 if ((i = ufalloc()) < 0) 209 return; 210 } else { 211 i = uap->fdes2; 212 if (i<0 || i>=NOFILE) { 213 u.u_error = EBADF; 214 return; 215 } 216 u.u_r.r_val1 = i; 217 } 218 if (i != uap->fdes) { 219 if (u.u_ofile[i]!=NULL) 220 closef(u.u_ofile[i], 0); 221 if (u.u_error) 222 return; 223 u.u_ofile[i] = fp; 224 fp->f_count++; 225 } 226 } 227 228 /* 229 * Mount system call. 230 */ 231 smount() 232 { 233 dev_t dev; 234 register struct inode *ip; 235 register struct mount *mp; 236 struct mount *smp; 237 register struct filsys *fp; 238 struct buf *bp; 239 register struct a { 240 char *fspec; 241 char *freg; 242 int ronly; 243 } *uap; 244 register char *cp; 245 246 uap = (struct a *)u.u_ap; 247 dev = getmdev(); 248 if (u.u_error) 249 return; 250 u.u_dirp = (caddr_t)uap->freg; 251 ip = namei(uchar, 0, 1); 252 if (ip == NULL) 253 return; 254 if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR) 255 goto out; 256 smp = NULL; 257 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 258 if (mp->m_bufp != NULL) { 259 if (dev == mp->m_dev) 260 goto out; 261 } else 262 if (smp == NULL) 263 smp = mp; 264 } 265 mp = smp; 266 if (mp == NULL) 267 goto out; 268 (*bdevsw[major(dev)].d_open)(dev, !uap->ronly); 269 if (u.u_error) 270 goto out; 271 bp = bread(dev, SUPERB); 272 if (u.u_error) { 273 brelse(bp); 274 goto out1; 275 } 276 mp->m_inodp = ip; 277 mp->m_dev = dev; 278 bp->b_flags |= B_LOCKED; 279 mp->m_bufp = bp; 280 fp = bp->b_un.b_filsys; 281 fp->s_ilock = 0; 282 fp->s_flock = 0; 283 fp->s_ronly = uap->ronly & 1; 284 fp->s_nbehind = 0; 285 fp->s_lasti = 1; 286 u.u_dirp = uap->freg; 287 for (cp = fp->s_fsmnt; cp < &fp->s_fsmnt[sizeof (fp->s_fsmnt) - 1]; ) 288 if ((*cp++ = uchar()) == 0) 289 u.u_dirp--; /* get 0 again */ 290 *cp = 0; 291 brelse(bp); 292 ip->i_flag |= IMOUNT; 293 irele(ip); 294 return; 295 296 out: 297 u.u_error = EBUSY; 298 out1: 299 iput(ip); 300 } 301 302 /* 303 * the umount system call. 304 */ 305 sumount() 306 { 307 dev_t dev; 308 register struct inode *ip; 309 register struct mount *mp; 310 struct buf *bp; 311 int stillopen, flag; 312 register struct a { 313 char *fspec; 314 }; 315 316 dev = getmdev(); 317 if (u.u_error) 318 return; 319 xumount(dev); /* remove unused sticky files from text table */ 320 update(0); 321 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 322 if (mp->m_bufp != NULL && dev == mp->m_dev) 323 goto found; 324 u.u_error = EINVAL; 325 return; 326 327 found: 328 stillopen = 0; 329 for (ip = inode; ip < inodeNINODE; ip++) 330 if (ip->i_number != 0 && dev == ip->i_dev) { 331 u.u_error = EBUSY; 332 return; 333 } else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK && 334 ip->i_un.i_rdev == dev) 335 stillopen++; 336 ip = mp->m_inodp; 337 ip->i_flag &= ~IMOUNT; 338 ilock(ip); 339 iput(ip); 340 if ((bp = getblk(dev, SUPERB)) != mp->m_bufp) 341 panic("umount"); 342 bp->b_flags &= ~B_LOCKED; 343 flag = !bp->b_un.b_filsys->s_ronly; 344 mp->m_bufp = NULL; 345 brelse(bp); 346 mpurge(mp - &mount[0]); 347 if (!stillopen) { 348 (*bdevsw[major(dev)].d_close)(dev, flag); 349 binval(dev); 350 } 351 } 352 353 /* 354 * Common code for mount and umount. 355 * Check that the user's argument is a reasonable 356 * thing on which to mount, and return the device number if so. 357 */ 358 dev_t 359 getmdev() 360 { 361 dev_t dev; 362 register struct inode *ip; 363 364 if (!suser()) 365 return(NODEV); 366 ip = namei(uchar, 0, 1); 367 if (ip == NULL) 368 return(NODEV); 369 if ((ip->i_mode&IFMT) != IFBLK) 370 u.u_error = ENOTBLK; 371 dev = (dev_t)ip->i_un.i_rdev; 372 if (major(dev) >= nblkdev) 373 u.u_error = ENXIO; 374 iput(ip); 375 return(dev); 376 } 377