1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)vfs_vnops.c 7.33 (Berkeley) 06/27/91 8 */ 9 10 #include "param.h" 11 #include "systm.h" 12 #include "kernel.h" 13 #include "file.h" 14 #include "stat.h" 15 #include "buf.h" 16 #include "proc.h" 17 #include "mount.h" 18 #include "namei.h" 19 #include "vnode.h" 20 #include "ioctl.h" 21 #include "tty.h" 22 23 struct fileops vnops = 24 { vn_read, vn_write, vn_ioctl, vn_select, vn_closefile }; 25 26 /* 27 * Common code for vnode open operations. 28 * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. 29 */ 30 vn_open(ndp, p, fmode, cmode) 31 register struct nameidata *ndp; 32 struct proc *p; 33 int fmode, cmode; 34 { 35 register struct vnode *vp; 36 register struct ucred *cred = p->p_ucred; 37 struct vattr vat; 38 struct vattr *vap = &vat; 39 int error; 40 41 if (fmode & O_CREAT) { 42 ndp->ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF; 43 if ((fmode & O_EXCL) == 0) 44 ndp->ni_nameiop |= FOLLOW; 45 if (error = namei(ndp, p)) 46 return (error); 47 if (ndp->ni_vp == NULL) { 48 VATTR_NULL(vap); 49 vap->va_type = VREG; 50 vap->va_mode = cmode; 51 if (error = VOP_CREATE(ndp, vap, p)) 52 return (error); 53 fmode &= ~O_TRUNC; 54 vp = ndp->ni_vp; 55 } else { 56 VOP_ABORTOP(ndp); 57 if (ndp->ni_dvp == ndp->ni_vp) 58 vrele(ndp->ni_dvp); 59 else 60 vput(ndp->ni_dvp); 61 ndp->ni_dvp = NULL; 62 vp = ndp->ni_vp; 63 if (fmode & O_EXCL) { 64 error = EEXIST; 65 goto bad; 66 } 67 fmode &= ~O_CREAT; 68 } 69 } else { 70 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 71 if (error = namei(ndp, p)) 72 return (error); 73 vp = ndp->ni_vp; 74 } 75 if (vp->v_type == VSOCK) { 76 error = EOPNOTSUPP; 77 goto bad; 78 } 79 if ((fmode & O_CREAT) == 0) { 80 if (fmode & FREAD) { 81 if (error = VOP_ACCESS(vp, VREAD, cred, p)) 82 goto bad; 83 } 84 if (fmode & (FWRITE | O_TRUNC)) { 85 if (vp->v_type == VDIR) { 86 error = EISDIR; 87 goto bad; 88 } 89 if ((error = vn_writechk(vp)) || 90 (error = VOP_ACCESS(vp, VWRITE, cred, p))) 91 goto bad; 92 } 93 } 94 if (fmode & O_TRUNC) { 95 VATTR_NULL(vap); 96 vap->va_size = 0; 97 if (error = VOP_SETATTR(vp, vap, cred, p)) 98 goto bad; 99 } 100 if (error = VOP_OPEN(vp, fmode, cred, p)) 101 goto bad; 102 if (fmode & FWRITE) 103 vp->v_writecount++; 104 return (0); 105 bad: 106 vput(vp); 107 return (error); 108 } 109 110 /* 111 * Check for write permissions on the specified vnode. 112 * The read-only status of the file system is checked. 113 * Also, prototype text segments cannot be written. 114 */ 115 vn_writechk(vp) 116 register struct vnode *vp; 117 { 118 119 /* 120 * Disallow write attempts on read-only file systems; 121 * unless the file is a socket or a block or character 122 * device resident on the file system. 123 */ 124 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 125 switch (vp->v_type) { 126 case VREG: case VDIR: case VLNK: 127 return (EROFS); 128 } 129 } 130 /* 131 * If there's shared text associated with 132 * the vnode, try to free it up once. If 133 * we fail, we can't allow writing. 134 */ 135 if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp)) 136 return (ETXTBSY); 137 return (0); 138 } 139 140 /* 141 * Vnode close call 142 */ 143 vn_close(vp, flags, cred, p) 144 register struct vnode *vp; 145 int flags; 146 struct ucred *cred; 147 struct proc *p; 148 { 149 int error; 150 151 if (flags & FWRITE) 152 vp->v_writecount--; 153 error = VOP_CLOSE(vp, flags, cred, p); 154 vrele(vp); 155 return (error); 156 } 157 158 /* 159 * Package up an I/O request on a vnode into a uio and do it. 160 */ 161 vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p) 162 enum uio_rw rw; 163 struct vnode *vp; 164 caddr_t base; 165 int len; 166 off_t offset; 167 enum uio_seg segflg; 168 int ioflg; 169 struct ucred *cred; 170 int *aresid; 171 struct proc *p; 172 { 173 struct uio auio; 174 struct iovec aiov; 175 int error; 176 177 if ((ioflg & IO_NODELOCKED) == 0) 178 VOP_LOCK(vp); 179 auio.uio_iov = &aiov; 180 auio.uio_iovcnt = 1; 181 aiov.iov_base = base; 182 aiov.iov_len = len; 183 auio.uio_resid = len; 184 auio.uio_offset = offset; 185 auio.uio_segflg = segflg; 186 auio.uio_rw = rw; 187 auio.uio_procp = p; 188 if (rw == UIO_READ) 189 error = VOP_READ(vp, &auio, ioflg, cred); 190 else 191 error = VOP_WRITE(vp, &auio, ioflg, cred); 192 if (aresid) 193 *aresid = auio.uio_resid; 194 else 195 if (auio.uio_resid && error == 0) 196 error = EIO; 197 if ((ioflg & IO_NODELOCKED) == 0) 198 VOP_UNLOCK(vp); 199 return (error); 200 } 201 202 /* 203 * File table vnode read routine. 204 */ 205 vn_read(fp, uio, cred) 206 struct file *fp; 207 struct uio *uio; 208 struct ucred *cred; 209 { 210 register struct vnode *vp = (struct vnode *)fp->f_data; 211 int count, error; 212 213 VOP_LOCK(vp); 214 uio->uio_offset = fp->f_offset; 215 count = uio->uio_resid; 216 error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0, 217 cred); 218 fp->f_offset += count - uio->uio_resid; 219 VOP_UNLOCK(vp); 220 return (error); 221 } 222 223 /* 224 * File table vnode write routine. 225 */ 226 vn_write(fp, uio, cred) 227 struct file *fp; 228 struct uio *uio; 229 struct ucred *cred; 230 { 231 register struct vnode *vp = (struct vnode *)fp->f_data; 232 int count, error, ioflag = 0; 233 234 if (vp->v_type == VREG && (fp->f_flag & O_APPEND)) 235 ioflag |= IO_APPEND; 236 if (fp->f_flag & FNONBLOCK) 237 ioflag |= IO_NDELAY; 238 VOP_LOCK(vp); 239 uio->uio_offset = fp->f_offset; 240 count = uio->uio_resid; 241 error = VOP_WRITE(vp, uio, ioflag, cred); 242 if (ioflag & IO_APPEND) 243 fp->f_offset = uio->uio_offset; 244 else 245 fp->f_offset += count - uio->uio_resid; 246 VOP_UNLOCK(vp); 247 return (error); 248 } 249 250 /* 251 * File table vnode stat routine. 252 */ 253 vn_stat(vp, sb, p) 254 struct vnode *vp; 255 register struct stat *sb; 256 struct proc *p; 257 { 258 struct vattr vattr; 259 register struct vattr *vap; 260 int error; 261 u_short mode; 262 263 vap = &vattr; 264 error = VOP_GETATTR(vp, vap, p->p_ucred, p); 265 if (error) 266 return (error); 267 /* 268 * Copy from vattr table 269 */ 270 sb->st_dev = vap->va_fsid; 271 sb->st_ino = vap->va_fileid; 272 mode = vap->va_mode; 273 switch (vp->v_type) { 274 case VREG: 275 mode |= S_IFREG; 276 break; 277 case VDIR: 278 mode |= S_IFDIR; 279 break; 280 case VBLK: 281 mode |= S_IFBLK; 282 break; 283 case VCHR: 284 mode |= S_IFCHR; 285 break; 286 case VLNK: 287 mode |= S_IFLNK; 288 break; 289 case VSOCK: 290 mode |= S_IFSOCK; 291 break; 292 case VFIFO: 293 mode |= S_IFIFO; 294 break; 295 default: 296 return (EBADF); 297 }; 298 sb->st_mode = mode; 299 sb->st_nlink = vap->va_nlink; 300 sb->st_uid = vap->va_uid; 301 sb->st_gid = vap->va_gid; 302 sb->st_rdev = vap->va_rdev; 303 sb->st_size = vap->va_size; 304 sb->st_atime = vap->va_atime.tv_sec; 305 sb->st_spare1 = 0; 306 sb->st_mtime = vap->va_mtime.tv_sec; 307 sb->st_spare2 = 0; 308 sb->st_ctime = vap->va_ctime.tv_sec; 309 sb->st_spare3 = 0; 310 sb->st_blksize = vap->va_blocksize; 311 sb->st_flags = vap->va_flags; 312 sb->st_gen = vap->va_gen; 313 sb->st_blocks = vap->va_bytes / S_BLKSIZE; 314 return (0); 315 } 316 317 /* 318 * File table vnode ioctl routine. 319 */ 320 vn_ioctl(fp, com, data, p) 321 struct file *fp; 322 int com; 323 caddr_t data; 324 struct proc *p; 325 { 326 register struct vnode *vp = ((struct vnode *)fp->f_data); 327 struct vattr vattr; 328 int error; 329 330 switch (vp->v_type) { 331 332 case VREG: 333 case VDIR: 334 if (com == FIONREAD) { 335 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 336 return (error); 337 *(off_t *)data = vattr.va_size - fp->f_offset; 338 return (0); 339 } 340 if (com == FIONBIO || com == FIOASYNC) /* XXX */ 341 return (0); /* XXX */ 342 /* fall into ... */ 343 344 default: 345 return (ENOTTY); 346 347 case VFIFO: 348 case VCHR: 349 case VBLK: 350 error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p); 351 if (error == 0 && com == TIOCSCTTY) { 352 p->p_session->s_ttyvp = vp; 353 VREF(vp); 354 } 355 return (error); 356 } 357 } 358 359 /* 360 * File table vnode select routine. 361 */ 362 vn_select(fp, which, p) 363 struct file *fp; 364 int which; 365 struct proc *p; 366 { 367 368 return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag, 369 fp->f_cred, p)); 370 } 371 372 /* 373 * File table vnode close routine. 374 */ 375 vn_closefile(fp, p) 376 struct file *fp; 377 struct proc *p; 378 { 379 380 return (vn_close(((struct vnode *)fp->f_data), fp->f_flag, 381 fp->f_cred, p)); 382 } 383 384 /* 385 * vn_fhtovp() - convert a fh to a vnode ptr (optionally locked) 386 * - look up fsid in mount list (if not found ret error) 387 * - get vp by calling VFS_FHTOVP() macro 388 * - if lockflag lock it with VOP_LOCK() 389 */ 390 vn_fhtovp(fhp, lockflag, vpp) 391 fhandle_t *fhp; 392 int lockflag; 393 struct vnode **vpp; 394 { 395 register struct mount *mp; 396 397 if ((mp = getvfs(&fhp->fh_fsid)) == NULL) 398 return (ESTALE); 399 if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp)) 400 return (ESTALE); 401 if (!lockflag) 402 VOP_UNLOCK(*vpp); 403 return (0); 404 } 405